From b3bd470962860af0cf4840dfbf1f1fd39efcdc89 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Jan 2020 14:02:17 +0100 Subject: [PATCH 001/562] lnwallet: restore missing field in local log update When restoring an htlc fulfill update from disk, the payment hash wasn't restored previously. --- lnwallet/channel.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 837f05cb55..367e04070b 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -1564,6 +1564,7 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate, pd = &PaymentDescriptor{ Amount: ogHTLC.Amount, + RHash: ogHTLC.RHash, RPreimage: wireMsg.PaymentPreimage, LogIndex: logUpdate.LogIndex, ParentIndex: ogHTLC.HtlcIndex, From 41c207e247048f8db1b4cc2f5284f92e87fd14f3 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Jan 2020 15:29:45 +0100 Subject: [PATCH 002/562] lnwallet/test: describe existing bug after restart with dangling remote updates --- lnwallet/channel_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 665917cf45..bddb3cdafa 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -6178,7 +6178,12 @@ func TestChannelRestoreUpdateLogsFailedHTLC(t *testing.T) { // At this point Alice has advanced her local commitment chain to a // commitment with no HTLCs left. The current state on her remote // commitment chain, however, still has the HTLC active, as she hasn't - // sent a new signature yet. + // sent a new signature yet. If we'd now restart and restore, the htlc + // failure update should still be waiting for inclusion in Alice's next + // signature. Otherwise the produced signature would be invalid. + // + // THIS IS NOT HAPPENING. The update log entry is dropped after a + // restart! assertInLogs(t, aliceChannel, 1, 0, 0, 1) restoreAndAssert(t, aliceChannel, 1, 0, 0, 0) From 280611ab6e206e6a1031418664ca2d42a5b70724 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 9 Jan 2020 13:53:25 +0100 Subject: [PATCH 003/562] sweep+walletrpc+lncli: report requested fee preference for pending sweeps Previously only the fee rate used for the last sweep (the sweep bucket average) was reported. This commit adds the request fee preference to the report, which is used to select a bucket and the sweep tx fee rate. --- cmd/lncli/walletrpc_types.go | 4 + lnrpc/walletrpc/walletkit.pb.go | 144 ++++++++++++++++------------ lnrpc/walletrpc/walletkit.proto | 6 ++ lnrpc/walletrpc/walletkit_server.go | 5 + sweep/sweeper.go | 4 + 5 files changed, 101 insertions(+), 62 deletions(-) diff --git a/cmd/lncli/walletrpc_types.go b/cmd/lncli/walletrpc_types.go index f336e02e20..11842c6f23 100644 --- a/cmd/lncli/walletrpc_types.go +++ b/cmd/lncli/walletrpc_types.go @@ -11,6 +11,8 @@ type PendingSweep struct { SatPerByte uint32 `json:"sat_per_byte"` BroadcastAttempts uint32 `json:"broadcast_attempts"` NextBroadcastHeight uint32 `json:"next_broadcast_height"` + RequestedSatPerByte uint32 `json:"requested_sat_per_byte"` + RequestedConfTarget uint32 `json:"requested_conf_target"` } // NewPendingSweepFromProto converts the walletrpc.PendingSweep proto type into @@ -23,5 +25,7 @@ func NewPendingSweepFromProto(pendingSweep *walletrpc.PendingSweep) *PendingSwee SatPerByte: pendingSweep.SatPerByte, BroadcastAttempts: pendingSweep.BroadcastAttempts, NextBroadcastHeight: pendingSweep.NextBroadcastHeight, + RequestedSatPerByte: pendingSweep.RequestedSatPerByte, + RequestedConfTarget: pendingSweep.RequestedConfTarget, } } diff --git a/lnrpc/walletrpc/walletkit.pb.go b/lnrpc/walletrpc/walletkit.pb.go index 9737602c58..6feab45ba9 100644 --- a/lnrpc/walletrpc/walletkit.pb.go +++ b/lnrpc/walletrpc/walletkit.pb.go @@ -531,7 +531,11 @@ type PendingSweep struct { // //The next height of the chain at which we'll attempt to broadcast the //sweep transaction of the output. - NextBroadcastHeight uint32 `protobuf:"varint,6,opt,name=next_broadcast_height,proto3" json:"next_broadcast_height,omitempty"` + NextBroadcastHeight uint32 `protobuf:"varint,6,opt,name=next_broadcast_height,proto3" json:"next_broadcast_height,omitempty"` + // The requested confirmation target for this output. + RequestedConfTarget uint32 `protobuf:"varint,8,opt,name=requested_conf_target,proto3" json:"requested_conf_target,omitempty"` + // The requested fee rate, expressed in sat/byte, for this output. + RequestedSatPerByte uint32 `protobuf:"varint,9,opt,name=requested_sat_per_byte,proto3" json:"requested_sat_per_byte,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -604,6 +608,20 @@ func (m *PendingSweep) GetNextBroadcastHeight() uint32 { return 0 } +func (m *PendingSweep) GetRequestedConfTarget() uint32 { + if m != nil { + return m.RequestedConfTarget + } + return 0 +} + +func (m *PendingSweep) GetRequestedSatPerByte() uint32 { + if m != nil { + return m.RequestedSatPerByte + } + return 0 +} + type PendingSweepsRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -788,68 +806,70 @@ func init() { func init() { proto.RegisterFile("walletrpc/walletkit.proto", fileDescriptor_6cc6942ac78249e5) } var fileDescriptor_6cc6942ac78249e5 = []byte{ - // 976 bytes of a gzipped FileDescriptorProto + // 1003 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xed, 0x6e, 0xe2, 0x46, - 0x14, 0x2d, 0x21, 0x61, 0xc3, 0x05, 0x12, 0x67, 0x08, 0x89, 0x97, 0xcd, 0x6e, 0xa8, 0xfb, 0x21, - 0xd4, 0x56, 0xa0, 0x66, 0xdb, 0xaa, 0x6a, 0x7f, 0xb4, 0x59, 0x70, 0x44, 0xc4, 0x87, 0xa9, 0xed, - 0x6c, 0xba, 0x55, 0xa5, 0x91, 0x81, 0x59, 0xb0, 0x00, 0xdb, 0x3b, 0x1e, 0x0a, 0xfc, 0x6d, 0x9f, - 0xa4, 0xaf, 0xd1, 0xa7, 0xab, 0x3c, 0xb6, 0xc9, 0x18, 0x92, 0x4a, 0xfd, 0x15, 0xe7, 0x9c, 0x73, - 0xcf, 0xdc, 0xb9, 0x33, 0x73, 0x04, 0x3c, 0x5f, 0x5a, 0xb3, 0x19, 0x61, 0xd4, 0x1b, 0xd6, 0xc3, - 0xaf, 0xa9, 0xcd, 0x6a, 0x1e, 0x75, 0x99, 0x8b, 0xb2, 0x1b, 0xaa, 0x9c, 0xa5, 0xde, 0x30, 0x44, - 0xcb, 0xa7, 0xbe, 0x3d, 0x76, 0x02, 0x79, 0xf0, 0x97, 0xd0, 0x10, 0x55, 0x7e, 0x81, 0x4c, 0x9b, - 0xac, 0x75, 0xf2, 0x01, 0x55, 0x41, 0x9a, 0x92, 0x35, 0x7e, 0x6f, 0x3b, 0x63, 0x42, 0xb1, 0x47, - 0x6d, 0x87, 0xc9, 0xa9, 0x4a, 0xaa, 0x7a, 0xa0, 0x1f, 0x4d, 0xc9, 0xfa, 0x86, 0xc3, 0xfd, 0x00, - 0x45, 0x2f, 0x01, 0xb8, 0xd2, 0x9a, 0xdb, 0xb3, 0xb5, 0xbc, 0xc7, 0x35, 0xd9, 0x40, 0xc3, 0x01, - 0xa5, 0x00, 0xb9, 0xeb, 0xd1, 0x88, 0xea, 0xe4, 0xc3, 0x82, 0xf8, 0x4c, 0x51, 0x20, 0x1f, 0xfe, - 0xeb, 0x7b, 0xae, 0xe3, 0x13, 0x84, 0x60, 0xdf, 0x1a, 0x8d, 0x28, 0xf7, 0xce, 0xea, 0xfc, 0x5b, - 0xf9, 0x14, 0x72, 0x26, 0xb5, 0x1c, 0xdf, 0x1a, 0x32, 0xdb, 0x75, 0x50, 0x09, 0x32, 0x6c, 0x85, - 0x27, 0x64, 0xc5, 0x45, 0x79, 0xfd, 0x80, 0xad, 0x5a, 0x64, 0xa5, 0x7c, 0x07, 0xc7, 0xfd, 0xc5, - 0x60, 0x66, 0xfb, 0x93, 0x8d, 0xd9, 0x27, 0x50, 0xf0, 0x42, 0x08, 0x13, 0x4a, 0xdd, 0xd8, 0x35, - 0x1f, 0x81, 0x6a, 0x80, 0x29, 0xbf, 0x03, 0x32, 0x88, 0x33, 0xd2, 0x16, 0xcc, 0x5b, 0x30, 0x3f, - 0xea, 0x0b, 0x5d, 0x00, 0xf8, 0x16, 0xc3, 0x1e, 0xa1, 0x78, 0xba, 0xe4, 0x75, 0x69, 0xfd, 0xd0, - 0xb7, 0x58, 0x9f, 0xd0, 0xf6, 0x12, 0x55, 0xe1, 0x99, 0x1b, 0xea, 0xe5, 0xbd, 0x4a, 0xba, 0x9a, - 0xbb, 0x3a, 0xaa, 0x45, 0xf3, 0xab, 0x99, 0x2b, 0x6d, 0xc1, 0xf4, 0x98, 0x56, 0xbe, 0x82, 0x62, - 0xc2, 0x3d, 0xea, 0xac, 0x04, 0x19, 0x6a, 0x2d, 0x31, 0xdb, 0xec, 0x81, 0x5a, 0x4b, 0x73, 0xa5, - 0x7c, 0x0b, 0x48, 0xf5, 0x99, 0x3d, 0xb7, 0x18, 0xb9, 0x21, 0x24, 0xee, 0xe5, 0x12, 0x72, 0x43, - 0xd7, 0x79, 0x8f, 0x99, 0x45, 0xc7, 0x24, 0x1e, 0x3b, 0x04, 0x90, 0xc9, 0x11, 0xe5, 0x35, 0x14, - 0x13, 0x65, 0xd1, 0x22, 0xff, 0xb9, 0x07, 0xe5, 0xef, 0x3d, 0xc8, 0xf7, 0x89, 0x33, 0xb2, 0x9d, - 0xb1, 0xb1, 0x24, 0xc4, 0x43, 0x5f, 0xc2, 0x61, 0xd0, 0xb5, 0x1b, 0x1f, 0x6d, 0xee, 0xea, 0xb8, - 0x36, 0xe3, 0x7b, 0xd2, 0x16, 0xac, 0x1f, 0xc0, 0xfa, 0x46, 0x80, 0x7e, 0x80, 0xfc, 0xd2, 0x66, - 0x0e, 0xf1, 0x7d, 0xcc, 0xd6, 0x1e, 0xe1, 0xe7, 0x7c, 0x74, 0x75, 0x56, 0xdb, 0x5c, 0xae, 0xda, - 0x7d, 0x48, 0x9b, 0x6b, 0x8f, 0xe8, 0x09, 0x2d, 0x7a, 0x05, 0x60, 0xcd, 0xdd, 0x85, 0xc3, 0xb0, - 0x6f, 0x31, 0x39, 0x5d, 0x49, 0x55, 0x0b, 0xba, 0x80, 0x20, 0x05, 0xf2, 0x71, 0xdf, 0x83, 0x35, - 0x23, 0xf2, 0x3e, 0x57, 0x24, 0x30, 0x54, 0x03, 0x34, 0xa0, 0xae, 0x35, 0x1a, 0x5a, 0x3e, 0xc3, - 0x16, 0x63, 0x64, 0xee, 0x31, 0x5f, 0x3e, 0xe0, 0xca, 0x47, 0x18, 0xf4, 0x0d, 0x94, 0x1c, 0xb2, - 0x62, 0xf8, 0x81, 0x9a, 0x10, 0x7b, 0x3c, 0x61, 0x72, 0x86, 0x97, 0x3c, 0x4e, 0x2a, 0x67, 0x70, - 0x2a, 0x8e, 0x28, 0xbe, 0x1d, 0xca, 0xaf, 0x50, 0xda, 0xc2, 0xa3, 0x91, 0xff, 0x04, 0x47, 0x5e, - 0x48, 0x60, 0x9f, 0x33, 0x72, 0x8a, 0xdf, 0x8f, 0x73, 0x61, 0x30, 0x62, 0xa5, 0xbe, 0x25, 0x57, - 0xfe, 0x4a, 0xc1, 0xd1, 0x9b, 0xc5, 0xdc, 0x13, 0x8e, 0xff, 0x7f, 0x9d, 0x4b, 0x05, 0x72, 0xe1, - 0x35, 0xc1, 0xc1, 0xfd, 0xe0, 0xc7, 0x52, 0xd0, 0x45, 0x68, 0x67, 0xba, 0xe9, 0xdd, 0xe9, 0x2a, - 0x27, 0x70, 0xbc, 0x69, 0x22, 0xdc, 0xd9, 0x17, 0x7f, 0xa6, 0x21, 0x27, 0x1c, 0x29, 0x2a, 0xc2, - 0xf1, 0x5d, 0xaf, 0xdd, 0xd3, 0xee, 0x7b, 0xf8, 0xfe, 0xd6, 0xec, 0xa9, 0x86, 0x21, 0x7d, 0x84, - 0x64, 0x38, 0x6d, 0x68, 0xdd, 0xee, 0xad, 0xd9, 0x55, 0x7b, 0x26, 0x36, 0x6f, 0xbb, 0x2a, 0xee, - 0x68, 0x8d, 0xb6, 0x94, 0x42, 0xe7, 0x50, 0x14, 0x98, 0x9e, 0x86, 0x9b, 0x6a, 0xe7, 0xfa, 0x9d, - 0xb4, 0x87, 0x4a, 0x70, 0x22, 0x10, 0xba, 0xfa, 0x56, 0x6b, 0xab, 0x52, 0x3a, 0xd0, 0xb7, 0xcc, - 0x4e, 0x03, 0x6b, 0x37, 0x37, 0xaa, 0xae, 0x36, 0x63, 0x62, 0x3f, 0x58, 0x82, 0x13, 0xd7, 0x8d, - 0x86, 0xda, 0x37, 0x1f, 0x98, 0x03, 0xf4, 0x19, 0x7c, 0x9c, 0x28, 0x09, 0x96, 0xd7, 0xee, 0x4c, - 0x6c, 0xa8, 0x0d, 0xad, 0xd7, 0xc4, 0x1d, 0xf5, 0xad, 0xda, 0x91, 0x32, 0xe8, 0x73, 0x50, 0x92, - 0x06, 0xc6, 0x5d, 0xa3, 0xa1, 0x1a, 0x46, 0x52, 0xf7, 0x0c, 0x5d, 0xc2, 0x8b, 0xad, 0x0e, 0xba, - 0x9a, 0xa9, 0xc6, 0xae, 0xd2, 0x21, 0xaa, 0xc0, 0xc5, 0x76, 0x27, 0x5c, 0x11, 0xf9, 0x49, 0x59, - 0x74, 0x01, 0x32, 0x57, 0x88, 0xce, 0x71, 0xbf, 0x80, 0x4e, 0x41, 0x8a, 0x26, 0x87, 0xdb, 0xea, - 0x3b, 0xdc, 0xba, 0x36, 0x5a, 0x52, 0x0e, 0xbd, 0x80, 0xf3, 0x9e, 0x6a, 0x04, 0x76, 0x3b, 0x64, - 0xfe, 0xea, 0x9f, 0x7d, 0xc8, 0xde, 0xf3, 0x8b, 0xd4, 0xb6, 0x83, 0x37, 0x58, 0x68, 0x12, 0x6a, - 0xff, 0x41, 0x7a, 0x64, 0xc5, 0xda, 0x64, 0x8d, 0x4e, 0x84, 0x5b, 0x16, 0xe6, 0x76, 0xf9, 0x6c, - 0x13, 0x4c, 0x6d, 0xb2, 0x6e, 0x12, 0x7f, 0x48, 0x6d, 0x8f, 0xb9, 0x14, 0x7d, 0x0f, 0xd9, 0xb0, - 0x36, 0xa8, 0x2b, 0x8a, 0xa2, 0x8e, 0x3b, 0xb4, 0x98, 0x4b, 0x9f, 0xac, 0xfc, 0x11, 0x0e, 0x83, - 0xf5, 0x82, 0xd4, 0x46, 0xe2, 0x7b, 0x17, 0x52, 0xbd, 0x7c, 0xbe, 0x83, 0x47, 0xef, 0xa3, 0x05, - 0x28, 0x0a, 0x69, 0x31, 0xd1, 0x45, 0x1b, 0x01, 0x2f, 0x97, 0xc5, 0x57, 0xb3, 0x95, 0xed, 0x1d, - 0xc8, 0x09, 0xc1, 0x8a, 0x5e, 0x0a, 0xd2, 0xdd, 0x38, 0x2f, 0xbf, 0x7a, 0x8a, 0x7e, 0x70, 0x13, - 0x12, 0x34, 0xe1, 0xb6, 0x1b, 0xc8, 0x09, 0xb7, 0xc7, 0x82, 0x57, 0x87, 0x42, 0x22, 0x1e, 0xd0, - 0xe5, 0x13, 0xcf, 0x7f, 0xd3, 0x5f, 0xe5, 0x69, 0x41, 0xe4, 0xf9, 0x33, 0x3c, 0x8b, 0x9e, 0x24, - 0x7a, 0x2e, 0x88, 0x93, 0x59, 0x91, 0x98, 0xd8, 0xd6, 0x0b, 0x7e, 0xf3, 0xf5, 0x6f, 0xf5, 0xb1, - 0xcd, 0x26, 0x8b, 0x41, 0x6d, 0xe8, 0xce, 0xeb, 0xb3, 0x20, 0xe0, 0x1c, 0xdb, 0x19, 0x3b, 0x84, - 0x2d, 0x5d, 0x3a, 0xad, 0xcf, 0x9c, 0x51, 0x9d, 0xc7, 0x4a, 0x7d, 0x63, 0x31, 0xc8, 0xf0, 0x9f, - 0x01, 0xaf, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xd3, 0xc7, 0x77, 0x11, 0x4f, 0x08, 0x00, 0x00, + 0x14, 0x2d, 0x21, 0x21, 0xe1, 0x02, 0x89, 0x33, 0xf9, 0xf2, 0xb2, 0xd9, 0x0d, 0x75, 0x3f, 0x84, + 0xda, 0x0a, 0xd4, 0x6c, 0xbb, 0xaa, 0xda, 0x1f, 0x6d, 0x16, 0x1c, 0x11, 0xf1, 0x61, 0x6a, 0x3b, + 0x9b, 0x6e, 0x55, 0x69, 0x64, 0x60, 0x16, 0x2c, 0xc0, 0xf6, 0x8e, 0x87, 0x02, 0x7f, 0xdb, 0x07, + 0xe8, 0xfb, 0xf4, 0xe9, 0x2a, 0x8f, 0x6d, 0x32, 0x86, 0x50, 0x69, 0x7f, 0xc5, 0x39, 0xe7, 0xdc, + 0x33, 0x77, 0xe6, 0xde, 0xb9, 0x03, 0x3c, 0x9b, 0x5b, 0x93, 0x09, 0x61, 0xd4, 0xeb, 0x57, 0xc3, + 0xaf, 0xb1, 0xcd, 0x2a, 0x1e, 0x75, 0x99, 0x8b, 0xb2, 0x2b, 0xaa, 0x98, 0xa5, 0x5e, 0x3f, 0x44, + 0x8b, 0xa7, 0xbe, 0x3d, 0x74, 0x02, 0x79, 0xf0, 0x97, 0xd0, 0x10, 0x55, 0x7e, 0x85, 0x4c, 0x93, + 0x2c, 0x75, 0xf2, 0x01, 0x95, 0x41, 0x1a, 0x93, 0x25, 0x7e, 0x6f, 0x3b, 0x43, 0x42, 0xb1, 0x47, + 0x6d, 0x87, 0xc9, 0xa9, 0x52, 0xaa, 0xbc, 0xa7, 0x1f, 0x8e, 0xc9, 0xf2, 0x96, 0xc3, 0xdd, 0x00, + 0x45, 0x2f, 0x00, 0xb8, 0xd2, 0x9a, 0xda, 0x93, 0xa5, 0xbc, 0xc3, 0x35, 0xd9, 0x40, 0xc3, 0x01, + 0xa5, 0x00, 0xb9, 0x9b, 0xc1, 0x80, 0xea, 0xe4, 0xc3, 0x8c, 0xf8, 0x4c, 0x51, 0x20, 0x1f, 0xfe, + 0xeb, 0x7b, 0xae, 0xe3, 0x13, 0x84, 0x60, 0xd7, 0x1a, 0x0c, 0x28, 0xf7, 0xce, 0xea, 0xfc, 0x5b, + 0xf9, 0x1c, 0x72, 0x26, 0xb5, 0x1c, 0xdf, 0xea, 0x33, 0xdb, 0x75, 0xd0, 0x19, 0x64, 0xd8, 0x02, + 0x8f, 0xc8, 0x82, 0x8b, 0xf2, 0xfa, 0x1e, 0x5b, 0x34, 0xc8, 0x42, 0x79, 0x0d, 0x47, 0xdd, 0x59, + 0x6f, 0x62, 0xfb, 0xa3, 0x95, 0xd9, 0x67, 0x50, 0xf0, 0x42, 0x08, 0x13, 0x4a, 0xdd, 0xd8, 0x35, + 0x1f, 0x81, 0x6a, 0x80, 0x29, 0x7f, 0x00, 0x32, 0x88, 0x33, 0xd0, 0x66, 0xcc, 0x9b, 0x31, 0x3f, + 0xca, 0x0b, 0x5d, 0x02, 0xf8, 0x16, 0xc3, 0x1e, 0xa1, 0x78, 0x3c, 0xe7, 0x71, 0x69, 0xfd, 0xc0, + 0xb7, 0x58, 0x97, 0xd0, 0xe6, 0x1c, 0x95, 0x61, 0xdf, 0x0d, 0xf5, 0xf2, 0x4e, 0x29, 0x5d, 0xce, + 0x5d, 0x1f, 0x56, 0xa2, 0xf3, 0xab, 0x98, 0x0b, 0x6d, 0xc6, 0xf4, 0x98, 0x56, 0xbe, 0x81, 0x93, + 0x84, 0x7b, 0x94, 0xd9, 0x19, 0x64, 0xa8, 0x35, 0xc7, 0x6c, 0xb5, 0x07, 0x6a, 0xcd, 0xcd, 0x85, + 0xf2, 0x3d, 0x20, 0xd5, 0x67, 0xf6, 0xd4, 0x62, 0xe4, 0x96, 0x90, 0x38, 0x97, 0x2b, 0xc8, 0xf5, + 0x5d, 0xe7, 0x3d, 0x66, 0x16, 0x1d, 0x92, 0xf8, 0xd8, 0x21, 0x80, 0x4c, 0x8e, 0x28, 0xaf, 0xe0, + 0x24, 0x11, 0x16, 0x2d, 0xf2, 0xbf, 0x7b, 0x50, 0xfe, 0x49, 0x43, 0xbe, 0x4b, 0x9c, 0x81, 0xed, + 0x0c, 0x8d, 0x39, 0x21, 0x1e, 0xfa, 0x1a, 0x0e, 0x82, 0xac, 0xdd, 0xb8, 0xb4, 0xb9, 0xeb, 0xa3, + 0xca, 0x84, 0xef, 0x49, 0x9b, 0xb1, 0x6e, 0x00, 0xeb, 0x2b, 0x01, 0xfa, 0x11, 0xf2, 0x73, 0x9b, + 0x39, 0xc4, 0xf7, 0x31, 0x5b, 0x7a, 0x84, 0xd7, 0xf9, 0xf0, 0xfa, 0xbc, 0xb2, 0x6a, 0xae, 0xca, + 0x43, 0x48, 0x9b, 0x4b, 0x8f, 0xe8, 0x09, 0x2d, 0x7a, 0x09, 0x60, 0x4d, 0xdd, 0x99, 0xc3, 0xb0, + 0x6f, 0x31, 0x39, 0x5d, 0x4a, 0x95, 0x0b, 0xba, 0x80, 0x20, 0x05, 0xf2, 0x71, 0xde, 0xbd, 0x25, + 0x23, 0xf2, 0x2e, 0x57, 0x24, 0x30, 0x54, 0x01, 0xd4, 0xa3, 0xae, 0x35, 0xe8, 0x5b, 0x3e, 0xc3, + 0x16, 0x63, 0x64, 0xea, 0x31, 0x5f, 0xde, 0xe3, 0xca, 0x27, 0x18, 0xf4, 0x1d, 0x9c, 0x39, 0x64, + 0xc1, 0xf0, 0x23, 0x35, 0x22, 0xf6, 0x70, 0xc4, 0xe4, 0x0c, 0x0f, 0x79, 0x9a, 0x0c, 0xa2, 0x68, + 0x58, 0x04, 0x32, 0xc0, 0x62, 0x0d, 0x0e, 0xc2, 0xa8, 0x27, 0x49, 0xf4, 0x1a, 0xce, 0x1f, 0x89, + 0xc4, 0x4e, 0xb2, 0x3c, 0x6c, 0x0b, 0xab, 0x9c, 0xc3, 0xa9, 0x58, 0x90, 0xb8, 0x17, 0x95, 0xdf, + 0xe0, 0x6c, 0x0d, 0x8f, 0x0a, 0xfc, 0x33, 0x1c, 0x7a, 0x21, 0x81, 0x7d, 0xce, 0xc8, 0x29, 0xde, + 0x8d, 0x17, 0x42, 0x19, 0xc4, 0x48, 0x7d, 0x4d, 0xae, 0xfc, 0x9d, 0x82, 0xc3, 0x37, 0xb3, 0xa9, + 0x27, 0x34, 0xdb, 0x47, 0x75, 0x41, 0x09, 0x72, 0xe1, 0x9e, 0xf9, 0xfe, 0x79, 0x13, 0x14, 0x74, + 0x11, 0xda, 0xa8, 0x65, 0x7a, 0xb3, 0x96, 0xca, 0x31, 0x1c, 0xad, 0x92, 0x08, 0x77, 0xf6, 0xd5, + 0x5f, 0x69, 0xc8, 0x09, 0x0d, 0x84, 0x4e, 0xe0, 0xe8, 0xbe, 0xd3, 0xec, 0x68, 0x0f, 0x1d, 0xfc, + 0x70, 0x67, 0x76, 0x54, 0xc3, 0x90, 0x3e, 0x41, 0x32, 0x9c, 0xd6, 0xb4, 0x76, 0xfb, 0xce, 0x6c, + 0xab, 0x1d, 0x13, 0x9b, 0x77, 0x6d, 0x15, 0xb7, 0xb4, 0x5a, 0x53, 0x4a, 0xa1, 0x0b, 0x38, 0x11, + 0x98, 0x8e, 0x86, 0xeb, 0x6a, 0xeb, 0xe6, 0x9d, 0xb4, 0x83, 0xce, 0xe0, 0x58, 0x20, 0x74, 0xf5, + 0xad, 0xd6, 0x54, 0xa5, 0x74, 0xa0, 0x6f, 0x98, 0xad, 0x1a, 0xd6, 0x6e, 0x6f, 0x55, 0x5d, 0xad, + 0xc7, 0xc4, 0x6e, 0xb0, 0x04, 0x27, 0x6e, 0x6a, 0x35, 0xb5, 0x6b, 0x3e, 0x32, 0x7b, 0xe8, 0x0b, + 0xf8, 0x34, 0x11, 0x12, 0x2c, 0xaf, 0xdd, 0x9b, 0xd8, 0x50, 0x6b, 0x5a, 0xa7, 0x8e, 0x5b, 0xea, + 0x5b, 0xb5, 0x25, 0x65, 0xd0, 0x97, 0xa0, 0x24, 0x0d, 0x8c, 0xfb, 0x5a, 0x4d, 0x35, 0x8c, 0xa4, + 0x6e, 0x1f, 0x5d, 0xc1, 0xf3, 0xb5, 0x0c, 0xda, 0x9a, 0xa9, 0xc6, 0xae, 0xd2, 0x01, 0x2a, 0xc1, + 0xe5, 0x7a, 0x26, 0x5c, 0x11, 0xf9, 0x49, 0x59, 0x74, 0x09, 0x32, 0x57, 0x88, 0xce, 0x71, 0xbe, + 0x80, 0x4e, 0x41, 0x8a, 0x4e, 0x0e, 0x37, 0xd5, 0x77, 0xb8, 0x71, 0x63, 0x34, 0xa4, 0x1c, 0x7a, + 0x0e, 0x17, 0x1d, 0xd5, 0x08, 0xec, 0x36, 0xc8, 0xfc, 0xf5, 0xbf, 0xbb, 0x90, 0x7d, 0xe0, 0x8d, + 0xd4, 0xb4, 0x83, 0x1b, 0x5f, 0xa8, 0x13, 0x6a, 0xff, 0x49, 0x3a, 0x64, 0xc1, 0x9a, 0x64, 0x89, + 0x8e, 0x85, 0x2e, 0x0b, 0x5f, 0x89, 0xe2, 0xf9, 0x6a, 0x0c, 0x36, 0xc9, 0xb2, 0x4e, 0xfc, 0x3e, + 0xb5, 0x3d, 0xe6, 0x52, 0xf4, 0x03, 0x64, 0xc3, 0xd8, 0x20, 0xee, 0x44, 0x14, 0xb5, 0xdc, 0xbe, + 0xc5, 0x5c, 0xba, 0x35, 0xf2, 0x27, 0x38, 0x08, 0xd6, 0x0b, 0xde, 0x08, 0x24, 0x4e, 0x17, 0xe1, + 0x0d, 0x29, 0x5e, 0x6c, 0xe0, 0xd1, 0xfd, 0x68, 0x00, 0x8a, 0x9e, 0x04, 0xf1, 0xfd, 0x10, 0x6d, + 0x04, 0xbc, 0x58, 0x14, 0x6f, 0xcd, 0xda, 0x4b, 0xd2, 0x82, 0x9c, 0x30, 0xc6, 0xd1, 0x0b, 0x41, + 0xba, 0xf9, 0x78, 0x14, 0x5f, 0x6e, 0xa3, 0x1f, 0xdd, 0x84, 0x79, 0x9d, 0x70, 0xdb, 0x1c, 0xff, + 0x09, 0xb7, 0xa7, 0xc6, 0xbc, 0x0e, 0x85, 0xc4, 0x78, 0x40, 0x57, 0x5b, 0xae, 0xff, 0x2a, 0xbf, + 0xd2, 0x76, 0x41, 0xe4, 0xf9, 0x0b, 0xec, 0x47, 0x57, 0x12, 0x3d, 0x13, 0xc4, 0xc9, 0x59, 0x91, + 0x38, 0xb1, 0xb5, 0x1b, 0xfc, 0xe6, 0xdb, 0xdf, 0xab, 0x43, 0x9b, 0x8d, 0x66, 0xbd, 0x4a, 0xdf, + 0x9d, 0x56, 0x27, 0xc1, 0x38, 0x75, 0x6c, 0x67, 0xe8, 0x10, 0x36, 0x77, 0xe9, 0xb8, 0x3a, 0x71, + 0x06, 0x55, 0x3e, 0x56, 0xaa, 0x2b, 0x8b, 0x5e, 0x86, 0xff, 0xe8, 0x78, 0xf5, 0x5f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x2c, 0x7c, 0x20, 0x44, 0xbd, 0x08, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/walletrpc/walletkit.proto b/lnrpc/walletrpc/walletkit.proto index 96441025b2..5b5ae694f6 100644 --- a/lnrpc/walletrpc/walletkit.proto +++ b/lnrpc/walletrpc/walletkit.proto @@ -191,6 +191,12 @@ message PendingSweep { sweep transaction of the output. */ uint32 next_broadcast_height = 6 [json_name = "next_broadcast_height"]; + + // The requested confirmation target for this output. + uint32 requested_conf_target = 8 [json_name = "requested_conf_target"]; + + // The requested fee rate, expressed in sat/byte, for this output. + uint32 requested_sat_per_byte = 9 [json_name = "requested_sat_per_byte"]; } message PendingSweepsRequest { diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 53a25e7bca..b98767f0b9 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -404,6 +404,9 @@ func (w *WalletKit) PendingSweeps(ctx context.Context, broadcastAttempts := uint32(pendingInput.BroadcastAttempts) nextBroadcastHeight := uint32(pendingInput.NextBroadcastHeight) + requestedFee := pendingInput.Params.Fee + requestedFeeRate := uint32(requestedFee.FeeRate.FeePerKVByte() / 1000) + rpcPendingSweeps = append(rpcPendingSweeps, &PendingSweep{ Outpoint: op, WitnessType: witnessType, @@ -411,6 +414,8 @@ func (w *WalletKit) PendingSweeps(ctx context.Context, SatPerByte: satPerByte, BroadcastAttempts: broadcastAttempts, NextBroadcastHeight: nextBroadcastHeight, + RequestedSatPerByte: requestedFeeRate, + RequestedConfTarget: requestedFee.ConfTarget, }) } diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 9114cf8a45..89ba0fb0c7 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -146,6 +146,9 @@ type PendingInput struct { // NextBroadcastHeight is the next height of the chain at which we'll // attempt to broadcast a transaction sweeping the input. NextBroadcastHeight uint32 + + // Params contains the sweep parameters for this pending request. + Params Params } // bumpFeeReq is an internal message we'll use to represent an external caller's @@ -1034,6 +1037,7 @@ func (s *UtxoSweeper) handlePendingSweepsReq( LastFeeRate: pendingInput.lastFeeRate, BroadcastAttempts: pendingInput.publishAttempts, NextBroadcastHeight: uint32(pendingInput.minPublishHeight), + Params: pendingInput.params, } } From dae5dddfd273341e7b665a133d021fbadf3db931 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 13 Jan 2020 13:25:14 +0100 Subject: [PATCH 004/562] mobile: trim arg spaces before comparison Since spaces where trimmed only after checking for empty strings, an empty flag '-- ' would be passed along to lnd. Intead we trim first to properly ingore such flags. --- mobile/bindings.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mobile/bindings.go b/mobile/bindings.go index 0945a17b44..d18bf3b019 100644 --- a/mobile/bindings.go +++ b/mobile/bindings.go @@ -25,12 +25,15 @@ func Start(extraArgs string, unlockerReady, rpcReady Callback) { // arguments. var splitArgs []string for _, a := range strings.Split(extraArgs, "--") { + // Trim any whitespace space, and ignore empty params. + a := strings.TrimSpace(a) if a == "" { continue } - // Finally we prefix any non-empty string with --, and trim - // whitespace to mimic the regular command line arguments. - splitArgs = append(splitArgs, strings.TrimSpace("--"+a)) + + // Finally we prefix any non-empty string with -- to mimic the + // regular command line arguments. + splitArgs = append(splitArgs, "--"+a) } // Add the extra arguments to os.Args, as that will be parsed during From 6a866890a8a6474a6e68a94a25bcc0eefeb1411a Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 23 Dec 2019 12:45:41 +0100 Subject: [PATCH 005/562] lnwallet/test: test remote update after restart This test asserts that remote updates that are locked-in on the local commitment, but haven't been signed for on the remote commitment, are properly restored after a restart. --- lnwallet/channel_test.go | 108 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index bddb3cdafa..94b9d63c7a 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -19,6 +19,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" ) @@ -3050,6 +3051,113 @@ func TestChanSyncOweCommitment(t *testing.T) { } } +// TestChanSyncOweCommitmentPendingRemote asserts that local updates are applied +// to the remote commit across restarts. +func TestChanSyncOweCommitmentPendingRemote(t *testing.T) { + t.Parallel() + + // Create a test channel which will be used for the duration of this + // unittest. + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + if err != nil { + t.Fatalf("unable to create test channels: %v", err) + } + defer cleanUp() + + var fakeOnionBlob [lnwire.OnionPacketSize]byte + copy(fakeOnionBlob[:], bytes.Repeat([]byte{0x05}, lnwire.OnionPacketSize)) + + // We'll start off the scenario where Bob send two htlcs to Alice in a + // single state update. + var preimages []lntypes.Preimage + const numHtlcs = 2 + for id := byte(0); id < numHtlcs; id++ { + htlcAmt := lnwire.NewMSatFromSatoshis(20000) + var bobPreimage [32]byte + copy(bobPreimage[:], bytes.Repeat([]byte{id}, 32)) + rHash := sha256.Sum256(bobPreimage[:]) + h := &lnwire.UpdateAddHTLC{ + PaymentHash: rHash, + Amount: htlcAmt, + Expiry: uint32(10), + OnionBlob: fakeOnionBlob, + } + + htlcIndex, err := bobChannel.AddHTLC(h, nil) + if err != nil { + t.Fatalf("unable to add bob's htlc: %v", err) + } + + h.ID = htlcIndex + if _, err := aliceChannel.ReceiveHTLC(h); err != nil { + t.Fatalf("unable to recv bob's htlc: %v", err) + } + + preimages = append(preimages, bobPreimage) + } + + // With the HTLCs applied to both update logs, we'll initiate a state + // transition from Bob. + if err := ForceStateTransition(bobChannel, aliceChannel); err != nil { + t.Fatalf("unable to complete bob's state transition: %v", err) + } + + // Next, Alice settles the HTLCs from Bob in distinct state updates. + for i := 0; i < numHtlcs; i++ { + err = aliceChannel.SettleHTLC(preimages[i], uint64(i), nil, nil, nil) + if err != nil { + t.Fatalf("unable to settle htlc: %v", err) + } + err = bobChannel.ReceiveHTLCSettle(preimages[i], uint64(i)) + if err != nil { + t.Fatalf("unable to settle htlc: %v", err) + } + + aliceSig, aliceHtlcSigs, _, err := aliceChannel.SignNextCommitment() + if err != nil { + t.Fatalf("unable to sign commitment: %v", err) + } + + err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs) + if err != nil { + t.Fatalf("unable to receive commitment: %v", err) + } + + // Bob revokes his current commitment. After this call + // completes, the htlc is settled on the local commitment + // transaction. Bob still owes Alice a signature to also settle + // the htlc on her local commitment transaction. + bobRevoke, _, err := bobChannel.RevokeCurrentCommitment() + if err != nil { + t.Fatalf("unable to revoke commitment: %v", err) + } + + _, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevoke) + if err != nil { + t.Fatalf("unable to revoke commitment: %v", err) + } + } + + // We restart Bob. This should have no impact on further message that + // are generated. + bobChannel, err = restartChannel(bobChannel) + if err != nil { + t.Fatalf("unable to restart bob: %v", err) + } + + // Bob signs the commitment he owes. + _, bobHtlcSigs, _, err := bobChannel.SignNextCommitment() + if err != nil { + t.Fatalf("unable to sign commitment: %v", err) + } + + // This commitment is expected to contain no htlcs anymore, but because + // of a bug it is still present. THIS IS NOT CORRECT! + if len(bobHtlcSigs) != 2 { + t.Fatal("expected htlc to still be pending") + } +} + // TestChanSyncOweRevocation tests that if Bob restarts (and then Alice) before // he receiver's Alice's RevokeAndAck message, then Alice concludes that she // needs to re-send the RevokeAndAck. After the revocation has been sent, both From ea892fce179c51ed7eb0a7c267655dc0cf312234 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 2 Jan 2020 17:32:46 +0100 Subject: [PATCH 006/562] channeldb: update UpdateCommitment description This method is only used to update the local commitment transaction. Updated comment accordingly. --- channeldb/channel.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 84e96c8ea2..ac21b8178c 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -1239,11 +1239,11 @@ func syncNewChannel(tx *bbolt.Tx, c *OpenChannel, addrs []net.Addr) error { return putLinkNode(nodeInfoBucket, linkNode) } -// UpdateCommitment updates the commitment state for the specified party -// (remote or local). The commitment stat completely describes the balance -// state at this point in the commitment chain. This method its to be called on -// two occasions: when we revoke our prior commitment state, and when the -// remote party revokes their prior commitment state. +// UpdateCommitment updates the local commitment state. It locks in the pending +// local updates that were received by us from the remote party. The commitment +// state completely describes the balance state at this point in the commitment +// chain. This method its to be called when we revoke our prior commitment +// state. func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment) error { c.Lock() defer c.Unlock() From 2d37d341a15878d3b4d7cc5e3bf6bf17530ee4ef Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 2 Jan 2020 17:35:03 +0100 Subject: [PATCH 007/562] channeldb: extract log update serialization Extract functionality to methods as a preparation for serializing remote log updates. --- channeldb/channel.go | 60 ++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index ac21b8178c..de4bd6d9db 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -1564,6 +1564,42 @@ type CommitDiff struct { SettleFailAcks []SettleFailRef } +// serializeLogUpdates serializes provided list of updates to a stream. +func serializeLogUpdates(w io.Writer, logUpdates []LogUpdate) error { + numUpdates := uint16(len(logUpdates)) + if err := binary.Write(w, byteOrder, numUpdates); err != nil { + return err + } + + for _, diff := range logUpdates { + err := WriteElements(w, diff.LogIndex, diff.UpdateMsg) + if err != nil { + return err + } + } + + return nil +} + +// deserializeLogUpdates deserializes a list of updates from a stream. +func deserializeLogUpdates(r io.Reader) ([]LogUpdate, error) { + var numUpdates uint16 + if err := binary.Read(r, byteOrder, &numUpdates); err != nil { + return nil, err + } + + logUpdates := make([]LogUpdate, numUpdates) + for i := 0; i < int(numUpdates); i++ { + err := ReadElements(r, + &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg, + ) + if err != nil { + return nil, err + } + } + return logUpdates, nil +} + func serializeCommitDiff(w io.Writer, diff *CommitDiff) error { if err := serializeChanCommit(w, &diff.Commitment); err != nil { return err @@ -1573,18 +1609,10 @@ func serializeCommitDiff(w io.Writer, diff *CommitDiff) error { return err } - numUpdates := uint16(len(diff.LogUpdates)) - if err := binary.Write(w, byteOrder, numUpdates); err != nil { + if err := serializeLogUpdates(w, diff.LogUpdates); err != nil { return err } - for _, diff := range diff.LogUpdates { - err := WriteElements(w, diff.LogIndex, diff.UpdateMsg) - if err != nil { - return err - } - } - numOpenRefs := uint16(len(diff.OpenedCircuitKeys)) if err := binary.Write(w, byteOrder, numOpenRefs); err != nil { return err @@ -1628,21 +1656,11 @@ func deserializeCommitDiff(r io.Reader) (*CommitDiff, error) { return nil, err } - var numUpdates uint16 - if err := binary.Read(r, byteOrder, &numUpdates); err != nil { + d.LogUpdates, err = deserializeLogUpdates(r) + if err != nil { return nil, err } - d.LogUpdates = make([]LogUpdate, numUpdates) - for i := 0; i < int(numUpdates); i++ { - err := ReadElements(r, - &d.LogUpdates[i].LogIndex, &d.LogUpdates[i].UpdateMsg, - ) - if err != nil { - return nil, err - } - } - var numOpenRefs uint16 if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil { return nil, err From ed8fa35ed44a8e2569c0f875284444cf8dd587db Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Jan 2020 13:14:25 +0100 Subject: [PATCH 008/562] lnwallet: extract pending local updates restore method Extract method in preparation for restoring dangling remote updates. We need to get rid of the early return. --- lnwallet/channel.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 367e04070b..08d685066e 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -1814,12 +1814,26 @@ func (lc *LightningChannel) restoreStateLogs( lc.localUpdateLog.restoreHtlc(&htlc) } - // If we didn't have a dangling (un-acked) commit for the remote party, - // then we can exit here. - if pendingRemoteCommit == nil { - return nil + // If we have a dangling (un-acked) commit for the remote party, then we + // restore the updates leading up to this commit. + if pendingRemoteCommit != nil { + err := lc.restorePendingLocalUpdates( + pendingRemoteCommitDiff, pendingRemoteKeys, + ) + if err != nil { + return err + } } + return nil +} + +// restorePendingLocalUpdates restores the local log updates leading up to the +// given pending remote commitment. +func (lc *LightningChannel) restorePendingLocalUpdates( + pendingRemoteCommitDiff *channeldb.CommitDiff, + pendingRemoteKeys *CommitmentKeyRing) error { + pendingCommit := pendingRemoteCommitDiff.Commitment pendingHeight := pendingCommit.CommitHeight From 0b9940a398cc01f3b182f91af8186b90118b1100 Mon Sep 17 00:00:00 2001 From: chokoboko <44872722+chokoboko@users.noreply.github.com> Date: Wed, 15 Jan 2020 14:03:44 +0200 Subject: [PATCH 009/562] Remove duplicated address permission entity --- rpcserver.go | 1 - 1 file changed, 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index 11227fe64e..1e731975fb 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -200,7 +200,6 @@ var ( validEntities = []string{ "onchain", "offchain", "address", "message", "peers", "info", "invoices", "signer", "macaroon", - "address", } ) From 82579400b32db8e831e195d3bde623e205ece01c Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 3 Jan 2020 15:53:51 +0100 Subject: [PATCH 010/562] lnwallet: restore unsigned acked remote updates This commit updates the channel state machine to persistently store remote updates that we have received a signature for, but that we haven't yet included in a commit signature of our own. Previously those updates were only stored in memory and dropped across restarts. This lead to the production of an invalid signature and channel force closure. The remote party expects us to include those updates. --- channeldb/channel.go | 68 ++++++++- channeldb/channel_test.go | 26 +++- channeldb/db_test.go | 2 +- lnwallet/channel.go | 292 +++++++++++++++++++++++++++++++++++++- lnwallet/channel_test.go | 12 +- 5 files changed, 384 insertions(+), 16 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index de4bd6d9db..ec81a6005e 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -66,6 +66,11 @@ var ( // party. chanCommitmentKey = []byte("chan-commitment-key") + // unsignedAckedUpdatesKey is an entry in the channel bucket that + // contains the remote updates that we have acked, but not yet signed + // for in one of our remote commits. + unsignedAckedUpdatesKey = []byte("unsigned-acked-updates-key") + // revocationStateKey stores their current revocation hash, our // preimage producer and their preimage store. revocationStateKey = []byte("revocation-state-key") @@ -1242,9 +1247,14 @@ func syncNewChannel(tx *bbolt.Tx, c *OpenChannel, addrs []net.Addr) error { // UpdateCommitment updates the local commitment state. It locks in the pending // local updates that were received by us from the remote party. The commitment // state completely describes the balance state at this point in the commitment -// chain. This method its to be called when we revoke our prior commitment +// chain. In addition to that, it persists all the remote log updates that we +// have acked, but not signed a remote commitment for yet. These need to be +// persisted to be able to produce a valid commit signature if a restart would +// occur. This method its to be called when we revoke our prior commitment // state. -func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment) error { +func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment, + unsignedAckedUpdates []LogUpdate) error { + c.Lock() defer c.Unlock() @@ -1287,6 +1297,20 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment) error { "revocations: %v", err) } + // Persist unsigned but acked remote updates that need to be + // restored after a restart. + var b bytes.Buffer + err = serializeLogUpdates(&b, unsignedAckedUpdates) + if err != nil { + return err + } + + err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes()) + if err != nil { + return fmt.Errorf("unable to store dangline remote "+ + "updates: %v", err) + } + return nil }) if err != nil { @@ -1751,6 +1775,14 @@ func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error { return err } + // Clear unsigned acked remote updates. We are signing now for + // all that we've got. + err = chanBucket.Delete(unsignedAckedUpdatesKey) + if err != nil { + return fmt.Errorf("unable to clear dangling remote "+ + "updates: %v", err) + } + // TODO(roasbeef): use seqno to derive key for later LCP // With the bucket retrieved, we'll now serialize the commit @@ -1804,6 +1836,38 @@ func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) { return cd, err } +// UnsignedAckedUpdates retrieves the persisted unsigned acked remote log +// updates that still need to be signed for. +func (c *OpenChannel) UnsignedAckedUpdates() ([]LogUpdate, error) { + var updates []LogUpdate + err := c.Db.View(func(tx *bbolt.Tx) error { + chanBucket, err := fetchChanBucket( + tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, + ) + switch err { + case nil: + case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound: + return nil + default: + return err + } + + updateBytes := chanBucket.Get(unsignedAckedUpdatesKey) + if updateBytes == nil { + return nil + } + + r := bytes.NewReader(updateBytes) + updates, err = deserializeLogUpdates(r) + return err + }) + if err != nil { + return nil, err + } + + return updates, nil +} + // InsertNextRevocation inserts the _next_ commitment point (revocation) into // the database, and also modifies the internal RemoteNextRevocation attribute // to point to the passed key. This method is to be using during final channel diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index 525b248907..2580f552d0 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -524,10 +524,34 @@ func TestChannelStateTransition(t *testing.T) { // First update the local node's broadcastable state and also add a // CommitDiff remote node's as well in order to simulate a proper state // transition. - if err := channel.UpdateCommitment(&commitment); err != nil { + unsignedAckedUpdates := []LogUpdate{ + { + LogIndex: 2, + UpdateMsg: &lnwire.UpdateAddHTLC{ + ChanID: lnwire.ChannelID{1, 2, 3}, + }, + }, + } + + err = channel.UpdateCommitment(&commitment, unsignedAckedUpdates) + if err != nil { t.Fatalf("unable to update commitment: %v", err) } + // Assert that update is correctly written to the database. + dbUnsignedAckedUpdates, err := channel.UnsignedAckedUpdates() + if err != nil { + t.Fatalf("unable to fetch dangling remote updates: %v", err) + } + if len(dbUnsignedAckedUpdates) != 1 { + t.Fatalf("unexpected number of dangling remote updates") + } + if !reflect.DeepEqual( + dbUnsignedAckedUpdates[0], unsignedAckedUpdates[0], + ) { + t.Fatalf("unexpected update") + } + // The balances, new update, the HTLCs and the changes to the fake // commitment transaction along with the modified signature should all // have been updated. diff --git a/channeldb/db_test.go b/channeldb/db_test.go index 4deffe986e..b9b1189be8 100644 --- a/channeldb/db_test.go +++ b/channeldb/db_test.go @@ -403,7 +403,7 @@ func TestRestoreChannelShells(t *testing.T) { // Ensure that it isn't possible to modify the commitment state machine // of this restored channel. channel := nodeChans[0] - err = channel.UpdateCommitment(nil) + err = channel.UpdateCommitment(nil, nil) if err != ErrNoRestoredChannelMutation { t.Fatalf("able to mutate restored channel") } diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 08d685066e..be4302d94f 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -4,6 +4,7 @@ import ( "bytes" "container/list" "crypto/sha256" + "errors" "fmt" "math" "sort" @@ -1177,6 +1178,13 @@ func (u *updateLog) appendUpdate(pd *PaymentDescriptor) { u.logIndex++ } +// restoreUpdate appends a new update to the tip of the updateLog. The entry is +// also added to index accordingly. This function differs from appendUpdate in +// that it won't increment the log index counter. +func (u *updateLog) restoreUpdate(pd *PaymentDescriptor) { + u.updateIndex[u.logIndex] = u.PushBack(pd) +} + // appendHtlc appends a new HTLC offer to the tip of the update log. The entry // is also added to the offer index accordingly. func (u *updateLog) appendHtlc(pd *PaymentDescriptor) { @@ -1627,6 +1635,110 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate, return pd, nil } +// remoteLogUpdateToPayDesc converts a LogUpdate into a matching +// PaymentDescriptor entry that can be re-inserted into the update log. This +// method is used when we revoked a local commitment, but the connection was +// obstructed before we could sign a remote commitment that contains these +// updates. In this case, we need to re-insert the original entries back into +// the update log so we can resume as if nothing happened. The height of the +// latest local commitment is also expected to be provided. We are restoring all +// log update entries with this height, even though the real commitment height +// may be lower. In the way these fields are used elsewhere, this doesn't change +// anything. +func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpdate, + localUpdateLog *updateLog, commitHeight uint64) (*PaymentDescriptor, + error) { + + switch wireMsg := logUpdate.UpdateMsg.(type) { + + case *lnwire.UpdateAddHTLC: + pd := &PaymentDescriptor{ + RHash: wireMsg.PaymentHash, + Timeout: wireMsg.Expiry, + Amount: wireMsg.Amount, + EntryType: Add, + HtlcIndex: wireMsg.ID, + LogIndex: logUpdate.LogIndex, + addCommitHeightLocal: commitHeight, + } + pd.OnionBlob = make([]byte, len(wireMsg.OnionBlob)) + copy(pd.OnionBlob, wireMsg.OnionBlob[:]) + + // We don't need to generate an htlc script yet. This will be + // done once we sign our remote commitment. + + return pd, nil + + // For HTLCs that the remote party settled, we'll fetch the original + // offered HTLC from the local update log so we can retrieve the same + // PaymentDescriptor that ReceiveHTLCSettle would produce. + case *lnwire.UpdateFulfillHTLC: + ogHTLC := localUpdateLog.lookupHtlc(wireMsg.ID) + + return &PaymentDescriptor{ + Amount: ogHTLC.Amount, + RHash: ogHTLC.RHash, + RPreimage: wireMsg.PaymentPreimage, + LogIndex: logUpdate.LogIndex, + ParentIndex: ogHTLC.HtlcIndex, + EntryType: Settle, + removeCommitHeightLocal: commitHeight, + }, nil + + // If we received a failure for a prior outgoing HTLC, then we'll + // consult the local update log so we can retrieve the information of + // the original HTLC we're failing. + case *lnwire.UpdateFailHTLC: + ogHTLC := localUpdateLog.lookupHtlc(wireMsg.ID) + + return &PaymentDescriptor{ + Amount: ogHTLC.Amount, + RHash: ogHTLC.RHash, + ParentIndex: ogHTLC.HtlcIndex, + LogIndex: logUpdate.LogIndex, + EntryType: Fail, + FailReason: wireMsg.Reason[:], + removeCommitHeightLocal: commitHeight, + }, nil + + // HTLC fails due to malformed onion blobs are treated the exact same + // way as regular HTLC fails. + case *lnwire.UpdateFailMalformedHTLC: + ogHTLC := localUpdateLog.lookupHtlc(wireMsg.ID) + + return &PaymentDescriptor{ + Amount: ogHTLC.Amount, + RHash: ogHTLC.RHash, + ParentIndex: ogHTLC.HtlcIndex, + LogIndex: logUpdate.LogIndex, + EntryType: MalformedFail, + FailCode: wireMsg.FailureCode, + ShaOnionBlob: wireMsg.ShaOnionBlob, + removeCommitHeightLocal: commitHeight, + }, nil + + // For fee updates we'll create a FeeUpdate type to add to the log. We + // reuse the amount field to hold the fee rate. Since the amount field + // is denominated in msat we won't lose precision when storing the + // sat/kw denominated feerate. Note that we set both the add and remove + // height to the same value, as we consider the fee update locked in by + // adding and removing it at the same height. + case *lnwire.UpdateFee: + return &PaymentDescriptor{ + LogIndex: logUpdate.LogIndex, + Amount: lnwire.NewMSatFromSatoshis( + btcutil.Amount(wireMsg.FeePerKw), + ), + EntryType: FeeUpdate, + addCommitHeightLocal: commitHeight, + removeCommitHeightLocal: commitHeight, + }, nil + + default: + return nil, errors.New("unknown message type") + } +} + // restoreCommitState will restore the local commitment chain and updateLog // state to a consistent in-memory representation of the passed disk commitment. // This method is to be used upon reconnection to our channel counter party. @@ -1727,12 +1839,19 @@ func (lc *LightningChannel) restoreCommitState( ) } + // Fetch remote updates that we have acked but not yet signed for. + unsignedAckedUpdates, err := lc.channelState.UnsignedAckedUpdates() + if err != nil { + return err + } + // Finally, with the commitment states restored, we'll now restore the // state logs based on the current local+remote commit, and any pending // remote commit that exists. err = lc.restoreStateLogs( localCommit, remoteCommit, pendingRemoteCommit, pendingRemoteCommitDiff, pendingRemoteKeyChain, + unsignedAckedUpdates, ) if err != nil { return err @@ -1748,7 +1867,8 @@ func (lc *LightningChannel) restoreCommitState( func (lc *LightningChannel) restoreStateLogs( localCommitment, remoteCommitment, pendingRemoteCommit *commitment, pendingRemoteCommitDiff *channeldb.CommitDiff, - pendingRemoteKeys *CommitmentKeyRing) error { + pendingRemoteKeys *CommitmentKeyRing, + unsignedAckedUpdates []channeldb.LogUpdate) error { // We make a map of incoming HTLCs to the height of the remote // commitment they were first added, and outgoing HTLCs to the height @@ -1825,6 +1945,71 @@ func (lc *LightningChannel) restoreStateLogs( } } + // Restore unsigned acked remote log updates so that we can include them + // in our next signature. + err := lc.restorePendingRemoteUpdates( + unsignedAckedUpdates, localCommitment.height, + ) + if err != nil { + return err + } + + return nil +} + +// restorePendingRemoteUpdates restores the acked remote log updates that we +// haven't yet signed for. +func (lc *LightningChannel) restorePendingRemoteUpdates( + unsignedAckedUpdates []channeldb.LogUpdate, + localCommitmentHeight uint64) error { + + lc.log.Debugf("Restoring %v dangling remote updates", + len(unsignedAckedUpdates)) + + for _, logUpdate := range unsignedAckedUpdates { + logUpdate := logUpdate + + payDesc, err := lc.remoteLogUpdateToPayDesc( + &logUpdate, lc.localUpdateLog, localCommitmentHeight, + ) + if err != nil { + return err + } + + // Sanity check that we are not restoring a remote log update + // that we haven't received a sig for. + if payDesc.LogIndex >= lc.remoteUpdateLog.logIndex { + return fmt.Errorf("attempted to restore an "+ + "unsigned remote update: log_index=%v", + payDesc.LogIndex) + } + + // Insert the update into the log. The log update index doesn't + // need to be incremented (hence the restore calls), because its + // final value was properly persisted with the last local + // commitment update. + switch payDesc.EntryType { + case Add: + lc.remoteUpdateLog.restoreHtlc(payDesc) + + // Sanity check to be sure that we are not restoring an + // add update that the remote hasn't signed for yet. + if payDesc.HtlcIndex >= lc.remoteUpdateLog.htlcCounter { + return fmt.Errorf("attempted to restore an "+ + "unsigned remote htlc: htlc_index=%v", + payDesc.HtlcIndex) + } + + case FeeUpdate: + lc.remoteUpdateLog.restoreUpdate(payDesc) + + default: + lc.remoteUpdateLog.restoreUpdate(payDesc) + + lc.localUpdateLog.markHtlcModified(payDesc.ParentIndex) + } + } + return nil } @@ -3092,6 +3277,96 @@ func (lc *LightningChannel) createCommitDiff( }, nil } +// getUnsignedAckedUpdates returns all remote log updates that we haven't +// signed for yet ourselves. +func (lc *LightningChannel) getUnsignedAckedUpdates() []channeldb.LogUpdate { + // First, we need to convert the funding outpoint into the ID that's + // used on the wire to identify this channel. + chanID := lnwire.NewChanIDFromOutPoint(&lc.channelState.FundingOutpoint) + + // Fetch the last remote update that we have signed for. + lastRemoteCommitted := lc.remoteCommitChain.tip().theirMessageIndex + + // Fetch the last remote update that we have acked. + lastLocalCommitted := lc.localCommitChain.tail().theirMessageIndex + + // We'll now run through the remote update log to locate the items that + // we haven't signed for yet. This will be the set of items we need to + // restore if we reconnect in order to produce the signature that the + // remote party expects. + var logUpdates []channeldb.LogUpdate + for e := lc.remoteUpdateLog.Front(); e != nil; e = e.Next() { + pd := e.Value.(*PaymentDescriptor) + + // Skip all remote updates that we have already included in our + // commit chain. + if pd.LogIndex < lastRemoteCommitted { + continue + } + + // Skip all remote updates that we haven't acked yet. At the + // moment this function is called, there shouldn't be any, but + // we check it anyway to make this function more generally + // usable. + if pd.LogIndex >= lastLocalCommitted { + continue + } + + logUpdate := channeldb.LogUpdate{ + LogIndex: pd.LogIndex, + } + + // We'll map the type of the PaymentDescriptor to one of the + // four messages that it corresponds to. + switch pd.EntryType { + case Add: + htlc := &lnwire.UpdateAddHTLC{ + ChanID: chanID, + ID: pd.HtlcIndex, + Amount: pd.Amount, + Expiry: pd.Timeout, + PaymentHash: pd.RHash, + } + copy(htlc.OnionBlob[:], pd.OnionBlob) + logUpdate.UpdateMsg = htlc + + case Settle: + logUpdate.UpdateMsg = &lnwire.UpdateFulfillHTLC{ + ChanID: chanID, + ID: pd.ParentIndex, + PaymentPreimage: pd.RPreimage, + } + + case Fail: + logUpdate.UpdateMsg = &lnwire.UpdateFailHTLC{ + ChanID: chanID, + ID: pd.ParentIndex, + Reason: pd.FailReason, + } + + case MalformedFail: + logUpdate.UpdateMsg = &lnwire.UpdateFailMalformedHTLC{ + ChanID: chanID, + ID: pd.ParentIndex, + ShaOnionBlob: pd.ShaOnionBlob, + FailureCode: pd.FailCode, + } + + case FeeUpdate: + // The Amount field holds the feerate denominated in + // msat. Since feerates are only denominated in sat/kw, + // we can convert it without loss of precision. + logUpdate.UpdateMsg = &lnwire.UpdateFee{ + ChanID: chanID, + FeePerKw: uint32(pd.Amount.ToSatoshis()), + } + } + + logUpdates = append(logUpdates, logUpdate) + } + return logUpdates +} + // validateCommitmentSanity is used to validate the current state of the // commitment transaction in terms of the ChannelConstraints that we and our // remote peer agreed upon during the funding workflow. The predictAdded @@ -4280,15 +4555,24 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, []c // persistent storage. chainTail := lc.localCommitChain.tail() newCommitment := chainTail.toDiskCommit(true) - err = lc.channelState.UpdateCommitment(newCommitment) + + // Get the unsigned acked remotes updates that are currently in memory. + // We need them after a restart to sync our remote commitment with what + // is committed locally. + unsignedAckedUpdates := lc.getUnsignedAckedUpdates() + + err = lc.channelState.UpdateCommitment( + newCommitment, unsignedAckedUpdates, + ) if err != nil { return nil, nil, err } lc.log.Tracef("state transition accepted: "+ - "our_balance=%v, their_balance=%v", + "our_balance=%v, their_balance=%v, unsigned_acked_updates=%v", chainTail.ourBalance, - chainTail.theirBalance) + chainTail.theirBalance, + len(unsignedAckedUpdates)) revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint( &lc.channelState.FundingOutpoint, diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 94b9d63c7a..9e5ecec5ab 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -3151,10 +3151,9 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) { t.Fatalf("unable to sign commitment: %v", err) } - // This commitment is expected to contain no htlcs anymore, but because - // of a bug it is still present. THIS IS NOT CORRECT! - if len(bobHtlcSigs) != 2 { - t.Fatal("expected htlc to still be pending") + // This commitment is expected to contain no htlcs anymore. + if len(bobHtlcSigs) != 0 { + t.Fatalf("no htlcs expected, but got %v", len(bobHtlcSigs)) } } @@ -6289,11 +6288,8 @@ func TestChannelRestoreUpdateLogsFailedHTLC(t *testing.T) { // sent a new signature yet. If we'd now restart and restore, the htlc // failure update should still be waiting for inclusion in Alice's next // signature. Otherwise the produced signature would be invalid. - // - // THIS IS NOT HAPPENING. The update log entry is dropped after a - // restart! assertInLogs(t, aliceChannel, 1, 0, 0, 1) - restoreAndAssert(t, aliceChannel, 1, 0, 0, 0) + restoreAndAssert(t, aliceChannel, 1, 0, 0, 1) // Now send a signature from Alice. This will give Bob a new commitment // where the HTLC is removed. From 16832cefa3e41e6f945c20d45751961270bf49cb Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 9 Jan 2020 14:41:28 +0100 Subject: [PATCH 011/562] sweep: allow updating all sweep parameters This is a preparation for adding additional parameters besides the fee preference. --- lnrpc/walletrpc/walletkit_server.go | 6 ++- sweep/sweeper.go | 75 +++++++++++++++-------------- sweep/sweeper_test.go | 10 ++-- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index b98767f0b9..7be25ade39 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -485,7 +485,11 @@ func (w *WalletKit) BumpFee(ctx context.Context, // bump its fee, which will result in a replacement transaction (RBF) // being broadcast. If it is not aware of the input however, // lnwallet.ErrNotMine is returned. - _, err = w.cfg.Sweeper.BumpFee(*op, feePreference) + params := sweep.Params{ + Fee: feePreference, + } + + _, err = w.cfg.Sweeper.UpdateParams(*op, params) switch err { case nil: return &BumpFeeResponse{}, nil diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 89ba0fb0c7..b044ec097c 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -69,6 +69,11 @@ type Params struct { Fee FeePreference } +// String returns a human readable interpretation of the sweep parameters. +func (p Params) String() string { + return fmt.Sprintf("fee=%v", p.Fee) +} + // pendingInput is created when an input reaches the main loop for the first // time. It wraps the input and tracks all relevant state that is needed for // sweeping. @@ -151,17 +156,17 @@ type PendingInput struct { Params Params } -// bumpFeeReq is an internal message we'll use to represent an external caller's -// intent to bump the fee rate of a given input. -type bumpFeeReq struct { - input wire.OutPoint - feePreference FeePreference - responseChan chan *bumpFeeResp +// updateReq is an internal message we'll use to represent an external caller's +// intent to update the sweep parameters of a given input. +type updateReq struct { + input wire.OutPoint + params Params + responseChan chan *updateResp } -// bumpFeeResp is an internal message we'll use to hand off the response of a -// bumpFeeReq from the UtxoSweeper's main event loop back to the caller. -type bumpFeeResp struct { +// updateResp is an internal message we'll use to hand off the response of a +// updateReq from the UtxoSweeper's main event loop back to the caller. +type updateResp struct { resultChan chan Result err error } @@ -181,9 +186,9 @@ type UtxoSweeper struct { // UtxoSweeper is attempting to sweep. pendingSweepsReqs chan *pendingSweepsReq - // bumpFeeReqs is a channel that will be sent requests by external + // updateReqs is a channel that will be sent requests by external // callers who wish to bump the fee rate of a given input. - bumpFeeReqs chan *bumpFeeReq + updateReqs chan *updateReq // pendingInputs is the total set of inputs the UtxoSweeper has been // requested to sweep. @@ -290,7 +295,7 @@ func New(cfg *UtxoSweeperConfig) *UtxoSweeper { cfg: cfg, newInputs: make(chan *sweepInputMessage), spendChan: make(chan *chainntnfs.SpendDetail), - bumpFeeReqs: make(chan *bumpFeeReq), + updateReqs: make(chan *updateReq), pendingSweepsReqs: make(chan *pendingSweepsReq), quit: make(chan struct{}), pendingInputs: make(pendingInputs), @@ -575,9 +580,9 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch) { // A new external request has been received to bump the fee rate // of a given input. - case req := <-s.bumpFeeReqs: - resultChan, err := s.handleBumpFeeReq(req, bestHeight) - req.responseChan <- &bumpFeeResp{ + case req := <-s.updateReqs: + resultChan, err := s.handleUpdateReq(req, bestHeight) + req.responseChan <- &updateResp{ resultChan: resultChan, err: err, } @@ -1044,28 +1049,28 @@ func (s *UtxoSweeper) handlePendingSweepsReq( return pendingInputs } -// BumpFee allows bumping the fee of an input being swept by the UtxoSweeper -// according to the provided fee preference. The new fee preference will be used -// for a new sweep transaction of the input that will act as a replacement -// transaction (RBF) of the original sweeping transaction, if any. +// UpdateParams allows updating the sweep parameters of a pending input in the +// UtxoSweeper. This function can be used to provide an updated fee preference +// that will be used for a new sweep transaction of the input that will act as a +// replacement transaction (RBF) of the original sweeping transaction, if any. // // NOTE: This currently doesn't do any fee rate validation to ensure that a bump // is actually successful. The responsibility of doing so should be handled by // the caller. -func (s *UtxoSweeper) BumpFee(input wire.OutPoint, - feePreference FeePreference) (chan Result, error) { +func (s *UtxoSweeper) UpdateParams(input wire.OutPoint, + params Params) (chan Result, error) { // Ensure the client provided a sane fee preference. - if _, err := s.feeRateForPreference(feePreference); err != nil { + if _, err := s.feeRateForPreference(params.Fee); err != nil { return nil, err } - responseChan := make(chan *bumpFeeResp, 1) + responseChan := make(chan *updateResp, 1) select { - case s.bumpFeeReqs <- &bumpFeeReq{ - input: input, - feePreference: feePreference, - responseChan: responseChan, + case s.updateReqs <- &updateReq{ + input: input, + params: params, + responseChan: responseChan, }: case <-s.quit: return nil, ErrSweeperShuttingDown @@ -1079,9 +1084,9 @@ func (s *UtxoSweeper) BumpFee(input wire.OutPoint, } } -// handleBumpFeeReq handles a bump fee request by simply updating the inputs fee -// preference. Currently, no validation is done on the new fee preference to -// ensure it will properly create a replacement transaction. +// handleUpdateReq handles an update request by simply updating the sweep +// parameters of the pending input. Currently, no validation is done on the new +// fee preference to ensure it will properly create a replacement transaction. // // TODO(wilmer): // * Validate fee preference to ensure we'll create a valid replacement @@ -1090,8 +1095,8 @@ func (s *UtxoSweeper) BumpFee(input wire.OutPoint, // * Ensure we don't combine this input with any other unconfirmed inputs that // did not exist in the original sweep transaction, resulting in an invalid // replacement transaction. -func (s *UtxoSweeper) handleBumpFeeReq(req *bumpFeeReq, - bestHeight int32) (chan Result, error) { +func (s *UtxoSweeper) handleUpdateReq(req *updateReq, bestHeight int32) ( + chan Result, error) { // If the UtxoSweeper is already trying to sweep this input, then we can // simply just increase its fee rate. This will allow the input to be @@ -1103,10 +1108,10 @@ func (s *UtxoSweeper) handleBumpFeeReq(req *bumpFeeReq, return nil, lnwallet.ErrNotMine } - log.Debugf("Updating fee preference for %v from %v to %v", req.input, - pendingInput.params.Fee, req.feePreference) + log.Debugf("Updating sweep parameters for %v from %v to %v", req.input, + pendingInput.params, req.params) - pendingInput.params.Fee = req.feePreference + pendingInput.params = req.params // We'll reset the input's publish height to the current so that a new // transaction can be created that replaces the transaction currently diff --git a/sweep/sweeper_test.go b/sweep/sweeper_test.go index b63129c9a7..a663c3ab51 100644 --- a/sweep/sweeper_test.go +++ b/sweep/sweeper_test.go @@ -1178,7 +1178,9 @@ func TestBumpFeeRBF(t *testing.T) { // We'll first try to bump the fee of an output currently unknown to the // UtxoSweeper. Doing so should result in a lnwallet.ErrNotMine error. - bumpResult, err := ctx.sweeper.BumpFee(wire.OutPoint{}, lowFeePref) + _, err := ctx.sweeper.UpdateParams( + wire.OutPoint{}, Params{Fee: lowFeePref}, + ) if err != lnwallet.ErrNotMine { t.Fatalf("expected error lnwallet.ErrNotMine, got \"%v\"", err) } @@ -1206,12 +1208,14 @@ func TestBumpFeeRBF(t *testing.T) { ctx.estimator.blocksToFee[highFeePref.ConfTarget] = highFeeRate // We should expect to see an error if a fee preference isn't provided. - _, err = ctx.sweeper.BumpFee(*input.OutPoint(), FeePreference{}) + _, err = ctx.sweeper.UpdateParams(*input.OutPoint(), Params{}) if err != ErrNoFeePreference { t.Fatalf("expected ErrNoFeePreference, got %v", err) } - bumpResult, err = ctx.sweeper.BumpFee(*input.OutPoint(), highFeePref) + bumpResult, err := ctx.sweeper.UpdateParams( + *input.OutPoint(), Params{Fee: highFeePref}, + ) if err != nil { t.Fatalf("unable to bump input's fee: %v", err) } From 14237f5fd4e3c6dd9f6708134c196340c350849a Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 13 Dec 2019 15:04:32 +0100 Subject: [PATCH 012/562] sweep: create add constraints This refactor prepares for the addition of specific constraints for force sweep inputs. --- sweep/tx_input_set.go | 62 +++++++++++++++++++++++++++----------- sweep/tx_input_set_test.go | 8 ++--- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/sweep/tx_input_set.go b/sweep/tx_input_set.go index a00ac6ca58..88d749a90a 100644 --- a/sweep/tx_input_set.go +++ b/sweep/tx_input_set.go @@ -13,6 +13,19 @@ import ( "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) +// addConstraints defines the constraints to apply when adding an input. +type addConstraints uint8 + +const ( + // constraintsRegular is for regular input sweeps that should have a positive + // yield. + constraintsRegular addConstraints = iota + + // constraintsWallet is for wallet inputs that are only added to bring up the tx + // output value. + constraintsWallet +) + // txInputSet is an object that accumulates tx inputs and keeps running counters // on various properties of the tx. type txInputSet struct { @@ -78,10 +91,12 @@ func (t *txInputSet) dustLimitReached() bool { // add adds a new input to the set. It returns a bool indicating whether the // input was added to the set. An input is rejected if it decreases the tx // output value after paying fees. -func (t *txInputSet) add(input input.Input, fromWallet bool) bool { +func (t *txInputSet) add(input input.Input, constraints addConstraints) bool { // Stop if max inputs is reached. Do not count additional wallet inputs, // because we don't know in advance how many we may need. - if !fromWallet && len(t.inputs) >= t.maxInputs { + if constraints != constraintsWallet && + len(t.inputs) >= t.maxInputs { + return false } @@ -108,19 +123,33 @@ func (t *txInputSet) add(input input.Input, fromWallet bool) bool { // added to the set. newOutputValue := newInputTotal - fee - // If adding this input makes the total output value of the set - // decrease, this is a negative yield input. We don't add the input to - // the set and return the outcome. - if newOutputValue <= t.outputValue { - return false - } + // Initialize new wallet total with the current wallet total. This is + // updated below if this input is a wallet input. + newWalletTotal := t.walletInputTotal + + // Calculate the yield of this input from the change in tx output value. + inputYield := newOutputValue - t.outputValue + + switch constraints { + + // Don't sweep inputs that cost us more to sweep than they give us. + case constraintsRegular: + if inputYield <= 0 { + return false + } + + // We are attaching a wallet input to raise the tx output value above + // the dust limit. + case constraintsWallet: + // Skip this wallet input if adding it would lower the output + // value. + if inputYield <= 0 { + return false + } - // If this input comes from the wallet, verify that we still gain - // something with this transaction. - if fromWallet { // Calculate the total value that we spend in this tx from the // wallet if we'd add this wallet input. - newWalletTotal := t.walletInputTotal + value + newWalletTotal += value // In any case, we don't want to lose money by sweeping. If we // don't get more out of the tx then we put in ourselves, do not @@ -142,10 +171,6 @@ func (t *txInputSet) add(input input.Input, fromWallet bool) bool { return false } - - // We've decided to add the wallet input. Increment the total - // wallet funds that go into this tx. - t.walletInputTotal = newWalletTotal } // Update running values. @@ -153,6 +178,7 @@ func (t *txInputSet) add(input input.Input, fromWallet bool) bool { t.outputValue = newOutputValue t.inputs = append(t.inputs, input) t.weightEstimate = newWeightEstimate + t.walletInputTotal = newWalletTotal return true } @@ -171,7 +197,7 @@ func (t *txInputSet) addPositiveYieldInputs(sweepableInputs []txInput) { // succeed because it wouldn't increase the output value, // return. Assuming inputs are sorted by yield, any further // inputs wouldn't increase the output value either. - if !t.add(input, false) { + if !t.add(input, constraintsRegular) { return } } @@ -202,7 +228,7 @@ func (t *txInputSet) tryAddWalletInputsIfNeeded() error { // If the wallet input isn't positively-yielding at this fee // rate, skip it. - if !t.add(input, true) { + if !t.add(input, constraintsWallet) { continue } diff --git a/sweep/tx_input_set_test.go b/sweep/tx_input_set_test.go index 2fa5018836..c3b8b0af7a 100644 --- a/sweep/tx_input_set_test.go +++ b/sweep/tx_input_set_test.go @@ -24,13 +24,13 @@ func TestTxInputSet(t *testing.T) { // Create a 300 sat input. The fee to sweep this input to a P2WKH output // is 439 sats. That means that this input yields -139 sats and we // expect it not to be added. - if set.add(createP2WKHInput(300), false) { + if set.add(createP2WKHInput(300), constraintsRegular) { t.Fatal("expected add of negatively yielding input to fail") } // A 700 sat input should be accepted into the set, because it yields // positively. - if !set.add(createP2WKHInput(700), false) { + if !set.add(createP2WKHInput(700), constraintsRegular) { t.Fatal("expected add of positively yielding input to succeed") } @@ -45,7 +45,7 @@ func TestTxInputSet(t *testing.T) { // Add a 1000 sat input. This increases the tx fee to 712 sats. The tx // output should now be 1000+700 - 712 = 988 sats. - if !set.add(createP2WKHInput(1000), false) { + if !set.add(createP2WKHInput(1000), constraintsRegular) { t.Fatal("expected add of positively yielding input to succeed") } if set.outputValue != 988 { @@ -70,7 +70,7 @@ func TestTxInputSetFromWallet(t *testing.T) { // Add a 700 sat input to the set. It yields positively, but doesn't // reach the output dust limit. - if !set.add(createP2WKHInput(700), false) { + if !set.add(createP2WKHInput(700), constraintsRegular) { t.Fatal("expected add of positively yielding input to succeed") } if set.dustLimitReached() { From b0aae13d70447f56a273b21c6b8a4d2b150978bf Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 9 Dec 2019 15:40:05 +0100 Subject: [PATCH 013/562] sweep: allow force sweeps --- cmd/lncli/walletrpc_active.go | 31 +++--- cmd/lncli/walletrpc_types.go | 2 + lnrpc/walletrpc/walletkit.pb.go | 156 ++++++++++++++++------------ lnrpc/walletrpc/walletkit.proto | 12 +++ lnrpc/walletrpc/walletkit_server.go | 4 +- sweep/sweeper.go | 12 ++- sweep/tx_input_set.go | 27 ++++- sweep/tx_input_set_test.go | 10 ++ sweep/txgenerator.go | 8 ++ 9 files changed, 172 insertions(+), 90 deletions(-) diff --git a/cmd/lncli/walletrpc_active.go b/cmd/lncli/walletrpc_active.go index 35dc562d67..31b14b764f 100644 --- a/cmd/lncli/walletrpc_active.go +++ b/cmd/lncli/walletrpc_active.go @@ -4,7 +4,6 @@ package main import ( "context" - "fmt" "sort" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" @@ -113,7 +112,13 @@ var bumpFeeCommand = cli.Command{ Note that this command currently doesn't perform any validation checks on the fee preference being provided. For now, the responsibility of ensuring that the new fee preference is sufficient is delegated to the - user.`, + user. + + The force flag enables sweeping of inputs that are negatively yielding. + Normally it does not make sense to lose money on sweeping, unless a + parent transaction needs to get confirmed and there is only a small + output available to attach the child transaction to. + `, Flags: []cli.Flag{ cli.Uint64Flag{ Name: "conf_target", @@ -125,6 +130,10 @@ var bumpFeeCommand = cli.Command{ Usage: "a manual fee expressed in sat/byte that " + "should be used when sweeping the output", }, + cli.BoolFlag{ + Name: "force", + Usage: "sweep even if the yield is negative", + }, }, Action: actionDecorator(bumpFee), } @@ -132,7 +141,7 @@ var bumpFeeCommand = cli.Command{ func bumpFee(ctx *cli.Context) error { // Display the command's help message if we do not have the expected // number of arguments/flags. - if ctx.NArg() != 1 || ctx.NumFlags() != 1 { + if ctx.NArg() != 1 { return cli.ShowCommandHelp(ctx, "bumpfee") } @@ -142,24 +151,14 @@ func bumpFee(ctx *cli.Context) error { return err } - var confTarget, satPerByte uint32 - switch { - case ctx.IsSet("conf_target") && ctx.IsSet("sat_per_byte"): - return fmt.Errorf("either conf_target or sat_per_byte should " + - "be set, but not both") - case ctx.IsSet("conf_target"): - confTarget = uint32(ctx.Uint64("conf_target")) - case ctx.IsSet("sat_per_byte"): - satPerByte = uint32(ctx.Uint64("sat_per_byte")) - } - client, cleanUp := getWalletClient(ctx) defer cleanUp() resp, err := client.BumpFee(context.Background(), &walletrpc.BumpFeeRequest{ Outpoint: protoOutPoint, - TargetConf: confTarget, - SatPerByte: satPerByte, + TargetConf: uint32(ctx.Uint64("conf_target")), + SatPerByte: uint32(ctx.Uint64("sat_per_byte")), + Force: ctx.Bool("force"), }) if err != nil { return err diff --git a/cmd/lncli/walletrpc_types.go b/cmd/lncli/walletrpc_types.go index 11842c6f23..c2b5698191 100644 --- a/cmd/lncli/walletrpc_types.go +++ b/cmd/lncli/walletrpc_types.go @@ -13,6 +13,7 @@ type PendingSweep struct { NextBroadcastHeight uint32 `json:"next_broadcast_height"` RequestedSatPerByte uint32 `json:"requested_sat_per_byte"` RequestedConfTarget uint32 `json:"requested_conf_target"` + Force bool `json:"force"` } // NewPendingSweepFromProto converts the walletrpc.PendingSweep proto type into @@ -27,5 +28,6 @@ func NewPendingSweepFromProto(pendingSweep *walletrpc.PendingSweep) *PendingSwee NextBroadcastHeight: pendingSweep.NextBroadcastHeight, RequestedSatPerByte: pendingSweep.RequestedSatPerByte, RequestedConfTarget: pendingSweep.RequestedConfTarget, + Force: pendingSweep.Force, } } diff --git a/lnrpc/walletrpc/walletkit.pb.go b/lnrpc/walletrpc/walletkit.pb.go index 6feab45ba9..e2ded0cc0c 100644 --- a/lnrpc/walletrpc/walletkit.pb.go +++ b/lnrpc/walletrpc/walletkit.pb.go @@ -535,7 +535,11 @@ type PendingSweep struct { // The requested confirmation target for this output. RequestedConfTarget uint32 `protobuf:"varint,8,opt,name=requested_conf_target,proto3" json:"requested_conf_target,omitempty"` // The requested fee rate, expressed in sat/byte, for this output. - RequestedSatPerByte uint32 `protobuf:"varint,9,opt,name=requested_sat_per_byte,proto3" json:"requested_sat_per_byte,omitempty"` + RequestedSatPerByte uint32 `protobuf:"varint,9,opt,name=requested_sat_per_byte,proto3" json:"requested_sat_per_byte,omitempty"` + //* + //Whether this input must be force-swept. This means that it is swept even + //if it has a negative yield. + Force bool `protobuf:"varint,7,opt,name=force,proto3" json:"force,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -622,6 +626,13 @@ func (m *PendingSweep) GetRequestedSatPerByte() uint32 { return 0 } +func (m *PendingSweep) GetForce() bool { + if m != nil { + return m.Force + } + return false +} + type PendingSweepsRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -702,7 +713,11 @@ type BumpFeeRequest struct { // //The fee rate, expressed in sat/byte, that should be used to spend the input //with. - SatPerByte uint32 `protobuf:"varint,3,opt,name=sat_per_byte,proto3" json:"sat_per_byte,omitempty"` + SatPerByte uint32 `protobuf:"varint,3,opt,name=sat_per_byte,proto3" json:"sat_per_byte,omitempty"` + //* + //Whether this input must be force-swept. This means that it is swept even + //if it has a negative yield. + Force bool `protobuf:"varint,4,opt,name=force,proto3" json:"force,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -754,6 +769,13 @@ func (m *BumpFeeRequest) GetSatPerByte() uint32 { return 0 } +func (m *BumpFeeRequest) GetForce() bool { + if m != nil { + return m.Force + } + return false +} + type BumpFeeResponse struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -806,70 +828,72 @@ func init() { func init() { proto.RegisterFile("walletrpc/walletkit.proto", fileDescriptor_6cc6942ac78249e5) } var fileDescriptor_6cc6942ac78249e5 = []byte{ - // 1003 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xed, 0x6e, 0xe2, 0x46, - 0x14, 0x2d, 0x21, 0x21, 0xe1, 0x02, 0x89, 0x33, 0xf9, 0xf2, 0xb2, 0xd9, 0x0d, 0x75, 0x3f, 0x84, - 0xda, 0x0a, 0xd4, 0x6c, 0xbb, 0xaa, 0xda, 0x1f, 0x6d, 0x16, 0x1c, 0x11, 0xf1, 0x61, 0x6a, 0x3b, - 0x9b, 0x6e, 0x55, 0x69, 0x64, 0x60, 0x16, 0x2c, 0xc0, 0xf6, 0x8e, 0x87, 0x02, 0x7f, 0xdb, 0x07, - 0xe8, 0xfb, 0xf4, 0xe9, 0x2a, 0x8f, 0x6d, 0x32, 0x86, 0x50, 0x69, 0x7f, 0xc5, 0x39, 0xe7, 0xdc, - 0x33, 0x77, 0xe6, 0xde, 0xb9, 0x03, 0x3c, 0x9b, 0x5b, 0x93, 0x09, 0x61, 0xd4, 0xeb, 0x57, 0xc3, - 0xaf, 0xb1, 0xcd, 0x2a, 0x1e, 0x75, 0x99, 0x8b, 0xb2, 0x2b, 0xaa, 0x98, 0xa5, 0x5e, 0x3f, 0x44, - 0x8b, 0xa7, 0xbe, 0x3d, 0x74, 0x02, 0x79, 0xf0, 0x97, 0xd0, 0x10, 0x55, 0x7e, 0x85, 0x4c, 0x93, - 0x2c, 0x75, 0xf2, 0x01, 0x95, 0x41, 0x1a, 0x93, 0x25, 0x7e, 0x6f, 0x3b, 0x43, 0x42, 0xb1, 0x47, - 0x6d, 0x87, 0xc9, 0xa9, 0x52, 0xaa, 0xbc, 0xa7, 0x1f, 0x8e, 0xc9, 0xf2, 0x96, 0xc3, 0xdd, 0x00, - 0x45, 0x2f, 0x00, 0xb8, 0xd2, 0x9a, 0xda, 0x93, 0xa5, 0xbc, 0xc3, 0x35, 0xd9, 0x40, 0xc3, 0x01, - 0xa5, 0x00, 0xb9, 0x9b, 0xc1, 0x80, 0xea, 0xe4, 0xc3, 0x8c, 0xf8, 0x4c, 0x51, 0x20, 0x1f, 0xfe, - 0xeb, 0x7b, 0xae, 0xe3, 0x13, 0x84, 0x60, 0xd7, 0x1a, 0x0c, 0x28, 0xf7, 0xce, 0xea, 0xfc, 0x5b, - 0xf9, 0x1c, 0x72, 0x26, 0xb5, 0x1c, 0xdf, 0xea, 0x33, 0xdb, 0x75, 0xd0, 0x19, 0x64, 0xd8, 0x02, - 0x8f, 0xc8, 0x82, 0x8b, 0xf2, 0xfa, 0x1e, 0x5b, 0x34, 0xc8, 0x42, 0x79, 0x0d, 0x47, 0xdd, 0x59, - 0x6f, 0x62, 0xfb, 0xa3, 0x95, 0xd9, 0x67, 0x50, 0xf0, 0x42, 0x08, 0x13, 0x4a, 0xdd, 0xd8, 0x35, - 0x1f, 0x81, 0x6a, 0x80, 0x29, 0x7f, 0x00, 0x32, 0x88, 0x33, 0xd0, 0x66, 0xcc, 0x9b, 0x31, 0x3f, - 0xca, 0x0b, 0x5d, 0x02, 0xf8, 0x16, 0xc3, 0x1e, 0xa1, 0x78, 0x3c, 0xe7, 0x71, 0x69, 0xfd, 0xc0, - 0xb7, 0x58, 0x97, 0xd0, 0xe6, 0x1c, 0x95, 0x61, 0xdf, 0x0d, 0xf5, 0xf2, 0x4e, 0x29, 0x5d, 0xce, - 0x5d, 0x1f, 0x56, 0xa2, 0xf3, 0xab, 0x98, 0x0b, 0x6d, 0xc6, 0xf4, 0x98, 0x56, 0xbe, 0x81, 0x93, - 0x84, 0x7b, 0x94, 0xd9, 0x19, 0x64, 0xa8, 0x35, 0xc7, 0x6c, 0xb5, 0x07, 0x6a, 0xcd, 0xcd, 0x85, - 0xf2, 0x3d, 0x20, 0xd5, 0x67, 0xf6, 0xd4, 0x62, 0xe4, 0x96, 0x90, 0x38, 0x97, 0x2b, 0xc8, 0xf5, - 0x5d, 0xe7, 0x3d, 0x66, 0x16, 0x1d, 0x92, 0xf8, 0xd8, 0x21, 0x80, 0x4c, 0x8e, 0x28, 0xaf, 0xe0, - 0x24, 0x11, 0x16, 0x2d, 0xf2, 0xbf, 0x7b, 0x50, 0xfe, 0x49, 0x43, 0xbe, 0x4b, 0x9c, 0x81, 0xed, - 0x0c, 0x8d, 0x39, 0x21, 0x1e, 0xfa, 0x1a, 0x0e, 0x82, 0xac, 0xdd, 0xb8, 0xb4, 0xb9, 0xeb, 0xa3, - 0xca, 0x84, 0xef, 0x49, 0x9b, 0xb1, 0x6e, 0x00, 0xeb, 0x2b, 0x01, 0xfa, 0x11, 0xf2, 0x73, 0x9b, - 0x39, 0xc4, 0xf7, 0x31, 0x5b, 0x7a, 0x84, 0xd7, 0xf9, 0xf0, 0xfa, 0xbc, 0xb2, 0x6a, 0xae, 0xca, - 0x43, 0x48, 0x9b, 0x4b, 0x8f, 0xe8, 0x09, 0x2d, 0x7a, 0x09, 0x60, 0x4d, 0xdd, 0x99, 0xc3, 0xb0, - 0x6f, 0x31, 0x39, 0x5d, 0x4a, 0x95, 0x0b, 0xba, 0x80, 0x20, 0x05, 0xf2, 0x71, 0xde, 0xbd, 0x25, - 0x23, 0xf2, 0x2e, 0x57, 0x24, 0x30, 0x54, 0x01, 0xd4, 0xa3, 0xae, 0x35, 0xe8, 0x5b, 0x3e, 0xc3, - 0x16, 0x63, 0x64, 0xea, 0x31, 0x5f, 0xde, 0xe3, 0xca, 0x27, 0x18, 0xf4, 0x1d, 0x9c, 0x39, 0x64, - 0xc1, 0xf0, 0x23, 0x35, 0x22, 0xf6, 0x70, 0xc4, 0xe4, 0x0c, 0x0f, 0x79, 0x9a, 0x0c, 0xa2, 0x68, - 0x58, 0x04, 0x32, 0xc0, 0x62, 0x0d, 0x0e, 0xc2, 0xa8, 0x27, 0x49, 0xf4, 0x1a, 0xce, 0x1f, 0x89, - 0xc4, 0x4e, 0xb2, 0x3c, 0x6c, 0x0b, 0xab, 0x9c, 0xc3, 0xa9, 0x58, 0x90, 0xb8, 0x17, 0x95, 0xdf, - 0xe0, 0x6c, 0x0d, 0x8f, 0x0a, 0xfc, 0x33, 0x1c, 0x7a, 0x21, 0x81, 0x7d, 0xce, 0xc8, 0x29, 0xde, - 0x8d, 0x17, 0x42, 0x19, 0xc4, 0x48, 0x7d, 0x4d, 0xae, 0xfc, 0x9d, 0x82, 0xc3, 0x37, 0xb3, 0xa9, - 0x27, 0x34, 0xdb, 0x47, 0x75, 0x41, 0x09, 0x72, 0xe1, 0x9e, 0xf9, 0xfe, 0x79, 0x13, 0x14, 0x74, - 0x11, 0xda, 0xa8, 0x65, 0x7a, 0xb3, 0x96, 0xca, 0x31, 0x1c, 0xad, 0x92, 0x08, 0x77, 0xf6, 0xd5, - 0x5f, 0x69, 0xc8, 0x09, 0x0d, 0x84, 0x4e, 0xe0, 0xe8, 0xbe, 0xd3, 0xec, 0x68, 0x0f, 0x1d, 0xfc, - 0x70, 0x67, 0x76, 0x54, 0xc3, 0x90, 0x3e, 0x41, 0x32, 0x9c, 0xd6, 0xb4, 0x76, 0xfb, 0xce, 0x6c, - 0xab, 0x1d, 0x13, 0x9b, 0x77, 0x6d, 0x15, 0xb7, 0xb4, 0x5a, 0x53, 0x4a, 0xa1, 0x0b, 0x38, 0x11, - 0x98, 0x8e, 0x86, 0xeb, 0x6a, 0xeb, 0xe6, 0x9d, 0xb4, 0x83, 0xce, 0xe0, 0x58, 0x20, 0x74, 0xf5, - 0xad, 0xd6, 0x54, 0xa5, 0x74, 0xa0, 0x6f, 0x98, 0xad, 0x1a, 0xd6, 0x6e, 0x6f, 0x55, 0x5d, 0xad, - 0xc7, 0xc4, 0x6e, 0xb0, 0x04, 0x27, 0x6e, 0x6a, 0x35, 0xb5, 0x6b, 0x3e, 0x32, 0x7b, 0xe8, 0x0b, - 0xf8, 0x34, 0x11, 0x12, 0x2c, 0xaf, 0xdd, 0x9b, 0xd8, 0x50, 0x6b, 0x5a, 0xa7, 0x8e, 0x5b, 0xea, - 0x5b, 0xb5, 0x25, 0x65, 0xd0, 0x97, 0xa0, 0x24, 0x0d, 0x8c, 0xfb, 0x5a, 0x4d, 0x35, 0x8c, 0xa4, - 0x6e, 0x1f, 0x5d, 0xc1, 0xf3, 0xb5, 0x0c, 0xda, 0x9a, 0xa9, 0xc6, 0xae, 0xd2, 0x01, 0x2a, 0xc1, - 0xe5, 0x7a, 0x26, 0x5c, 0x11, 0xf9, 0x49, 0x59, 0x74, 0x09, 0x32, 0x57, 0x88, 0xce, 0x71, 0xbe, - 0x80, 0x4e, 0x41, 0x8a, 0x4e, 0x0e, 0x37, 0xd5, 0x77, 0xb8, 0x71, 0x63, 0x34, 0xa4, 0x1c, 0x7a, - 0x0e, 0x17, 0x1d, 0xd5, 0x08, 0xec, 0x36, 0xc8, 0xfc, 0xf5, 0xbf, 0xbb, 0x90, 0x7d, 0xe0, 0x8d, - 0xd4, 0xb4, 0x83, 0x1b, 0x5f, 0xa8, 0x13, 0x6a, 0xff, 0x49, 0x3a, 0x64, 0xc1, 0x9a, 0x64, 0x89, - 0x8e, 0x85, 0x2e, 0x0b, 0x5f, 0x89, 0xe2, 0xf9, 0x6a, 0x0c, 0x36, 0xc9, 0xb2, 0x4e, 0xfc, 0x3e, - 0xb5, 0x3d, 0xe6, 0x52, 0xf4, 0x03, 0x64, 0xc3, 0xd8, 0x20, 0xee, 0x44, 0x14, 0xb5, 0xdc, 0xbe, - 0xc5, 0x5c, 0xba, 0x35, 0xf2, 0x27, 0x38, 0x08, 0xd6, 0x0b, 0xde, 0x08, 0x24, 0x4e, 0x17, 0xe1, - 0x0d, 0x29, 0x5e, 0x6c, 0xe0, 0xd1, 0xfd, 0x68, 0x00, 0x8a, 0x9e, 0x04, 0xf1, 0xfd, 0x10, 0x6d, - 0x04, 0xbc, 0x58, 0x14, 0x6f, 0xcd, 0xda, 0x4b, 0xd2, 0x82, 0x9c, 0x30, 0xc6, 0xd1, 0x0b, 0x41, - 0xba, 0xf9, 0x78, 0x14, 0x5f, 0x6e, 0xa3, 0x1f, 0xdd, 0x84, 0x79, 0x9d, 0x70, 0xdb, 0x1c, 0xff, - 0x09, 0xb7, 0xa7, 0xc6, 0xbc, 0x0e, 0x85, 0xc4, 0x78, 0x40, 0x57, 0x5b, 0xae, 0xff, 0x2a, 0xbf, - 0xd2, 0x76, 0x41, 0xe4, 0xf9, 0x0b, 0xec, 0x47, 0x57, 0x12, 0x3d, 0x13, 0xc4, 0xc9, 0x59, 0x91, - 0x38, 0xb1, 0xb5, 0x1b, 0xfc, 0xe6, 0xdb, 0xdf, 0xab, 0x43, 0x9b, 0x8d, 0x66, 0xbd, 0x4a, 0xdf, - 0x9d, 0x56, 0x27, 0xc1, 0x38, 0x75, 0x6c, 0x67, 0xe8, 0x10, 0x36, 0x77, 0xe9, 0xb8, 0x3a, 0x71, - 0x06, 0x55, 0x3e, 0x56, 0xaa, 0x2b, 0x8b, 0x5e, 0x86, 0xff, 0xe8, 0x78, 0xf5, 0x5f, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x2c, 0x7c, 0x20, 0x44, 0xbd, 0x08, 0x00, 0x00, + // 1026 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x6d, 0x6f, 0xe2, 0xc6, + 0x13, 0xff, 0x13, 0x12, 0x02, 0x03, 0x24, 0xce, 0xe6, 0xc9, 0xc7, 0xe5, 0x2e, 0xfc, 0xdd, 0x07, + 0xa1, 0xb6, 0x02, 0x35, 0xd7, 0x9e, 0xaa, 0xf6, 0x45, 0x9b, 0x23, 0x8e, 0x12, 0x41, 0x30, 0xb5, + 0x9d, 0x4b, 0xaf, 0xaa, 0xb4, 0x72, 0x60, 0x03, 0x16, 0x60, 0xfb, 0xd6, 0x4b, 0x81, 0xb7, 0xfd, + 0x16, 0xfd, 0x00, 0xfd, 0x12, 0xfd, 0x74, 0x95, 0xd7, 0x0f, 0x59, 0xf3, 0x50, 0xa9, 0xaf, 0x82, + 0x7f, 0xbf, 0xdf, 0xcc, 0xce, 0xce, 0xcc, 0xce, 0x04, 0x5e, 0xcc, 0xac, 0xf1, 0x98, 0x30, 0xea, + 0xf5, 0x1a, 0xe1, 0xaf, 0x91, 0xcd, 0xea, 0x1e, 0x75, 0x99, 0x8b, 0x0a, 0x09, 0x55, 0x29, 0x50, + 0xaf, 0x17, 0xa2, 0x95, 0x23, 0xdf, 0x1e, 0x38, 0x81, 0x3c, 0xf8, 0x4b, 0x68, 0x88, 0x2a, 0x3f, + 0x43, 0xae, 0x45, 0x16, 0x3a, 0xf9, 0x88, 0x6a, 0x20, 0x8d, 0xc8, 0x02, 0x3f, 0xd9, 0xce, 0x80, + 0x50, 0xec, 0x51, 0xdb, 0x61, 0x72, 0xa6, 0x9a, 0xa9, 0xed, 0xe8, 0x7b, 0x23, 0xb2, 0xb8, 0xe6, + 0x70, 0x37, 0x40, 0xd1, 0x2b, 0x00, 0xae, 0xb4, 0x26, 0xf6, 0x78, 0x21, 0x6f, 0x71, 0x4d, 0x21, + 0xd0, 0x70, 0x40, 0x29, 0x43, 0xf1, 0xb2, 0xdf, 0xa7, 0x3a, 0xf9, 0x38, 0x25, 0x3e, 0x53, 0x14, + 0x28, 0x85, 0x9f, 0xbe, 0xe7, 0x3a, 0x3e, 0x41, 0x08, 0xb6, 0xad, 0x7e, 0x9f, 0x72, 0xdf, 0x05, + 0x9d, 0xff, 0x56, 0x3e, 0x85, 0xa2, 0x49, 0x2d, 0xc7, 0xb7, 0x7a, 0xcc, 0x76, 0x1d, 0x74, 0x0c, + 0x39, 0x36, 0xc7, 0x43, 0x32, 0xe7, 0xa2, 0x92, 0xbe, 0xc3, 0xe6, 0x37, 0x64, 0xae, 0xbc, 0x85, + 0xfd, 0xee, 0xf4, 0x71, 0x6c, 0xfb, 0xc3, 0xc4, 0xd9, 0x27, 0x50, 0xf6, 0x42, 0x08, 0x13, 0x4a, + 0xdd, 0xd8, 0x6b, 0x29, 0x02, 0xd5, 0x00, 0x53, 0x7e, 0x03, 0x64, 0x10, 0xa7, 0xaf, 0x4d, 0x99, + 0x37, 0x65, 0x7e, 0x14, 0x17, 0x3a, 0x03, 0xf0, 0x2d, 0x86, 0x3d, 0x42, 0xf1, 0x68, 0xc6, 0xed, + 0xb2, 0x7a, 0xde, 0xb7, 0x58, 0x97, 0xd0, 0xd6, 0x0c, 0xd5, 0x60, 0xd7, 0x0d, 0xf5, 0xf2, 0x56, + 0x35, 0x5b, 0x2b, 0x5e, 0xec, 0xd5, 0xa3, 0xfc, 0xd5, 0xcd, 0xb9, 0x36, 0x65, 0x7a, 0x4c, 0x2b, + 0x5f, 0xc1, 0x61, 0xca, 0x7b, 0x14, 0xd9, 0x31, 0xe4, 0xa8, 0x35, 0xc3, 0x2c, 0xb9, 0x03, 0xb5, + 0x66, 0xe6, 0x5c, 0xf9, 0x16, 0x90, 0xea, 0x33, 0x7b, 0x62, 0x31, 0x72, 0x4d, 0x48, 0x1c, 0xcb, + 0x39, 0x14, 0x7b, 0xae, 0xf3, 0x84, 0x99, 0x45, 0x07, 0x24, 0x4e, 0x3b, 0x04, 0x90, 0xc9, 0x11, + 0xe5, 0x0d, 0x1c, 0xa6, 0xcc, 0xa2, 0x43, 0xfe, 0xf5, 0x0e, 0xca, 0x5f, 0x59, 0x28, 0x75, 0x89, + 0xd3, 0xb7, 0x9d, 0x81, 0x31, 0x23, 0xc4, 0x43, 0x5f, 0x42, 0x3e, 0x88, 0xda, 0x8d, 0x4b, 0x5b, + 0xbc, 0xd8, 0xaf, 0x8f, 0xf9, 0x9d, 0xb4, 0x29, 0xeb, 0x06, 0xb0, 0x9e, 0x08, 0xd0, 0xf7, 0x50, + 0x9a, 0xd9, 0xcc, 0x21, 0xbe, 0x8f, 0xd9, 0xc2, 0x23, 0xbc, 0xce, 0x7b, 0x17, 0x27, 0xf5, 0xa4, + 0xb9, 0xea, 0x0f, 0x21, 0x6d, 0x2e, 0x3c, 0xa2, 0xa7, 0xb4, 0xe8, 0x35, 0x80, 0x35, 0x71, 0xa7, + 0x0e, 0xc3, 0xbe, 0xc5, 0xe4, 0x6c, 0x35, 0x53, 0x2b, 0xeb, 0x02, 0x82, 0x14, 0x28, 0xc5, 0x71, + 0x3f, 0x2e, 0x18, 0x91, 0xb7, 0xb9, 0x22, 0x85, 0xa1, 0x3a, 0xa0, 0x47, 0xea, 0x5a, 0xfd, 0x9e, + 0xe5, 0x33, 0x6c, 0x31, 0x46, 0x26, 0x1e, 0xf3, 0xe5, 0x1d, 0xae, 0x5c, 0xc3, 0xa0, 0x6f, 0xe0, + 0xd8, 0x21, 0x73, 0x86, 0x9f, 0xa9, 0x21, 0xb1, 0x07, 0x43, 0x26, 0xe7, 0xb8, 0xc9, 0x7a, 0x32, + 0xb0, 0xa2, 0x61, 0x11, 0x48, 0x1f, 0x8b, 0x35, 0xc8, 0x87, 0x56, 0x6b, 0x49, 0xf4, 0x16, 0x4e, + 0x9e, 0x89, 0xd4, 0x4d, 0x0a, 0xdc, 0x6c, 0x03, 0x8b, 0x8e, 0x60, 0xe7, 0xc9, 0xa5, 0x3d, 0x22, + 0xef, 0x56, 0x33, 0xb5, 0xbc, 0x1e, 0x7e, 0x28, 0x27, 0x70, 0x24, 0x96, 0x29, 0xee, 0x50, 0xe5, + 0x17, 0x38, 0x5e, 0xc2, 0xa3, 0xb2, 0xff, 0x08, 0x7b, 0x5e, 0x48, 0x60, 0x9f, 0x33, 0x72, 0x86, + 0xf7, 0xe8, 0xa9, 0x50, 0x1c, 0xd1, 0x52, 0x5f, 0x92, 0x2b, 0x7f, 0x66, 0x60, 0xef, 0xdd, 0x74, + 0xe2, 0x09, 0x2d, 0xf8, 0x9f, 0x7a, 0xa3, 0x0a, 0xc5, 0x30, 0x13, 0x3c, 0x2b, 0xbc, 0x35, 0xca, + 0xba, 0x08, 0xad, 0x54, 0x38, 0xbb, 0xa6, 0xc2, 0x49, 0x36, 0xb6, 0xc5, 0x6c, 0x1c, 0xc0, 0x7e, + 0x12, 0x5a, 0x78, 0xdf, 0x2f, 0xfe, 0xc8, 0x42, 0x51, 0x68, 0x36, 0x74, 0x08, 0xfb, 0xf7, 0x9d, + 0x56, 0x47, 0x7b, 0xe8, 0xe0, 0x87, 0x5b, 0xb3, 0xa3, 0x1a, 0x86, 0xf4, 0x3f, 0x24, 0xc3, 0x51, + 0x53, 0xbb, 0xbb, 0xbb, 0x35, 0xef, 0xd4, 0x8e, 0x89, 0xcd, 0xdb, 0x3b, 0x15, 0xb7, 0xb5, 0x66, + 0x4b, 0xca, 0xa0, 0x53, 0x38, 0x14, 0x98, 0x8e, 0x86, 0xaf, 0xd4, 0xf6, 0xe5, 0x07, 0x69, 0x0b, + 0x1d, 0xc3, 0x81, 0x40, 0xe8, 0xea, 0x7b, 0xad, 0xa5, 0x4a, 0xd9, 0x40, 0x7f, 0x63, 0xb6, 0x9b, + 0x58, 0xbb, 0xbe, 0x56, 0x75, 0xf5, 0x2a, 0x26, 0xb6, 0x83, 0x23, 0x38, 0x71, 0xd9, 0x6c, 0xaa, + 0x5d, 0xf3, 0x99, 0xd9, 0x41, 0x9f, 0xc1, 0xff, 0x53, 0x26, 0xc1, 0xf1, 0xda, 0xbd, 0x89, 0x0d, + 0xb5, 0xa9, 0x75, 0xae, 0x70, 0x5b, 0x7d, 0xaf, 0xb6, 0xa5, 0x1c, 0xfa, 0x1c, 0x94, 0xb4, 0x03, + 0xe3, 0xbe, 0xd9, 0x54, 0x0d, 0x23, 0xad, 0xdb, 0x45, 0xe7, 0xf0, 0x72, 0x29, 0x82, 0x3b, 0xcd, + 0x54, 0x63, 0xaf, 0x52, 0x1e, 0x55, 0xe1, 0x6c, 0x39, 0x12, 0xae, 0x88, 0xfc, 0x49, 0x05, 0x74, + 0x06, 0x32, 0x57, 0x88, 0x9e, 0xe3, 0x78, 0x01, 0x1d, 0x81, 0x14, 0x65, 0x0e, 0xb7, 0xd4, 0x0f, + 0xf8, 0xe6, 0xd2, 0xb8, 0x91, 0x8a, 0xe8, 0x25, 0x9c, 0x76, 0x54, 0x23, 0x70, 0xb7, 0x42, 0x96, + 0x2e, 0xfe, 0xde, 0x86, 0xc2, 0x03, 0x6f, 0xaf, 0x96, 0x1d, 0x4c, 0x87, 0xf2, 0x15, 0xa1, 0xf6, + 0xef, 0xa4, 0x43, 0xe6, 0xac, 0x45, 0x16, 0xe8, 0x40, 0xe8, 0xbd, 0x70, 0xa3, 0x54, 0x4e, 0x92, + 0x91, 0xd9, 0x22, 0x8b, 0x2b, 0xe2, 0xf7, 0xa8, 0xed, 0x31, 0x97, 0xa2, 0xef, 0xa0, 0x10, 0xda, + 0x06, 0x76, 0x87, 0xa2, 0xa8, 0xed, 0xf6, 0x2c, 0xe6, 0xd2, 0x8d, 0x96, 0x3f, 0x40, 0x3e, 0x38, + 0x2f, 0xd8, 0x27, 0x48, 0x9c, 0x44, 0xc2, 0xbe, 0xa9, 0x9c, 0xae, 0xe0, 0xd1, 0xab, 0xb9, 0x01, + 0x14, 0xad, 0x0f, 0x71, 0xd7, 0x88, 0x6e, 0x04, 0xbc, 0x52, 0x11, 0xdf, 0xd2, 0xd2, 0xd6, 0x69, + 0x43, 0x51, 0x18, 0xf9, 0xe8, 0x95, 0x20, 0x5d, 0x5d, 0x34, 0x95, 0xd7, 0x9b, 0xe8, 0x67, 0x6f, + 0xc2, 0x6c, 0x4f, 0x79, 0x5b, 0x5d, 0x15, 0x29, 0x6f, 0xeb, 0x56, 0x82, 0x0e, 0xe5, 0xd4, 0xd0, + 0x40, 0xe7, 0x1b, 0x86, 0x42, 0x12, 0x5f, 0x75, 0xb3, 0x20, 0xf2, 0xf9, 0x13, 0xec, 0x46, 0x4f, + 0x12, 0xbd, 0x10, 0xc4, 0xe9, 0x09, 0x92, 0xca, 0xd8, 0xd2, 0x0b, 0x7e, 0xf7, 0xf5, 0xaf, 0x8d, + 0x81, 0xcd, 0x86, 0xd3, 0xc7, 0x7a, 0xcf, 0x9d, 0x34, 0xc6, 0xc1, 0xe8, 0x75, 0x6c, 0x67, 0xe0, + 0x10, 0x36, 0x73, 0xe9, 0xa8, 0x31, 0x76, 0xfa, 0x0d, 0x3e, 0x6c, 0x1a, 0x89, 0x8b, 0xc7, 0x1c, + 0xff, 0x07, 0xe5, 0xcd, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5a, 0x4e, 0xaf, 0xaf, 0xe9, 0x08, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/walletrpc/walletkit.proto b/lnrpc/walletrpc/walletkit.proto index 5b5ae694f6..446e79fe32 100644 --- a/lnrpc/walletrpc/walletkit.proto +++ b/lnrpc/walletrpc/walletkit.proto @@ -197,6 +197,12 @@ message PendingSweep { // The requested fee rate, expressed in sat/byte, for this output. uint32 requested_sat_per_byte = 9 [json_name = "requested_sat_per_byte"]; + + /** + Whether this input must be force-swept. This means that it is swept even + if it has a negative yield. + */ + bool force = 7 [json_name = "force"]; } message PendingSweepsRequest { @@ -221,6 +227,12 @@ message BumpFeeRequest { with. */ uint32 sat_per_byte = 3 [json_name = "sat_per_byte"]; + + /** + Whether this input must be force-swept. This means that it is swept even + if it has a negative yield. + */ + bool force = 4 [json_name = "force"]; } message BumpFeeResponse { diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 7be25ade39..42534c653e 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -416,6 +416,7 @@ func (w *WalletKit) PendingSweeps(ctx context.Context, NextBroadcastHeight: nextBroadcastHeight, RequestedSatPerByte: requestedFeeRate, RequestedConfTarget: requestedFee.ConfTarget, + Force: pendingInput.Params.Force, }) } @@ -486,7 +487,8 @@ func (w *WalletKit) BumpFee(ctx context.Context, // being broadcast. If it is not aware of the input however, // lnwallet.ErrNotMine is returned. params := sweep.Params{ - Fee: feePreference, + Fee: feePreference, + Force: in.Force, } _, err = w.cfg.Sweeper.UpdateParams(*op, params) diff --git a/sweep/sweeper.go b/sweep/sweeper.go index b044ec097c..fc65879f66 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -67,11 +67,15 @@ type Params struct { // swept. If a confirmation target is specified, then we'll map it into // a fee rate whenever we attempt to cluster inputs for a sweep. Fee FeePreference + + // Force indicates whether the input should be swept regardless of + // whether it is economical to do so. + Force bool } // String returns a human readable interpretation of the sweep parameters. func (p Params) String() string { - return fmt.Sprintf("fee=%v", p.Fee) + return fmt.Sprintf("fee=%v, force=%v", p.Fee, p.Force) } // pendingInput is created when an input reaches the main loop for the first @@ -398,10 +402,10 @@ func (s *UtxoSweeper) SweepInput(input input.Input, } log.Infof("Sweep request received: out_point=%v, witness_type=%v, "+ - "time_lock=%v, amount=%v, fee_preference=%v", input.OutPoint(), - input.WitnessType(), input.BlocksToMaturity(), + "time_lock=%v, amount=%v, fee_preference=%v, force=%v", + input.OutPoint(), input.WitnessType(), input.BlocksToMaturity(), btcutil.Amount(input.SignDesc().Output.Value), - params.Fee) + params.Fee, params.Force) sweeperInput := &sweepInputMessage{ input: input, diff --git a/sweep/tx_input_set.go b/sweep/tx_input_set.go index 88d749a90a..1f21f9602c 100644 --- a/sweep/tx_input_set.go +++ b/sweep/tx_input_set.go @@ -24,6 +24,10 @@ const ( // constraintsWallet is for wallet inputs that are only added to bring up the tx // output value. constraintsWallet + + // constraintsForce is for inputs that should be swept even with a negative + // yield at the set fee rate. + constraintsForce ) // txInputSet is an object that accumulates tx inputs and keeps running counters @@ -58,6 +62,10 @@ type txInputSet struct { // wallet contains wallet functionality required by the input set to // retrieve utxos. wallet Wallet + + // force indicates that this set must be swept even if the total yield + // is negative. + force bool } // newTxInputSet constructs a new, empty input set. @@ -138,6 +146,10 @@ func (t *txInputSet) add(input input.Input, constraints addConstraints) bool { return false } + // For force adds, no further constraints apply. + case constraintsForce: + t.force = true + // We are attaching a wallet input to raise the tx output value above // the dust limit. case constraintsWallet: @@ -153,7 +165,8 @@ func (t *txInputSet) add(input input.Input, constraints addConstraints) bool { // In any case, we don't want to lose money by sweeping. If we // don't get more out of the tx then we put in ourselves, do not - // add this wallet input. + // add this wallet input. If there is at least one force sweep + // in the set, this does no longer apply. // // We should only add wallet inputs to get the tx output value // above the dust limit, otherwise we'd only burn into fees. @@ -163,7 +176,7 @@ func (t *txInputSet) add(input input.Input, constraints addConstraints) bool { // value of the wallet input and what we get out of this // transaction. To prevent attaching and locking a big utxo for // very little benefit. - if newWalletTotal >= newOutputValue { + if !t.force && newWalletTotal >= newOutputValue { log.Debugf("Rejecting wallet input of %v, because it "+ "would make a negative yielding transaction "+ "(%v)", @@ -174,6 +187,8 @@ func (t *txInputSet) add(input input.Input, constraints addConstraints) bool { } // Update running values. + // + // TODO: Return new instance? t.inputTotal = newInputTotal t.outputValue = newOutputValue t.inputs = append(t.inputs, input) @@ -193,11 +208,17 @@ func (t *txInputSet) add(input input.Input, constraints addConstraints) bool { // whole. func (t *txInputSet) addPositiveYieldInputs(sweepableInputs []txInput) { for _, input := range sweepableInputs { + // Apply relaxed constraints for force sweeps. + constraints := constraintsRegular + if input.parameters().Force { + constraints = constraintsForce + } + // Try to add the input to the transaction. If that doesn't // succeed because it wouldn't increase the output value, // return. Assuming inputs are sorted by yield, any further // inputs wouldn't increase the output value either. - if !t.add(input, constraintsRegular) { + if !t.add(input, constraints) { return } } diff --git a/sweep/tx_input_set_test.go b/sweep/tx_input_set_test.go index c3b8b0af7a..d9e98f7330 100644 --- a/sweep/tx_input_set_test.go +++ b/sweep/tx_input_set_test.go @@ -77,6 +77,16 @@ func TestTxInputSetFromWallet(t *testing.T) { t.Fatal("expected dust limit not yet to be reached") } + // Expect that adding a negative yield input fails. + if set.add(createP2WKHInput(50), constraintsRegular) { + t.Fatal("expected negative yield input add to fail") + } + + // Force add the negative yield input. It should succeed. + if !set.add(createP2WKHInput(50), constraintsForce) { + t.Fatal("expected forced add to succeed") + } + err := set.tryAddWalletInputsIfNeeded() if err != nil { t.Fatal(err) diff --git a/sweep/txgenerator.go b/sweep/txgenerator.go index 47c8d3c652..229ecf3eb4 100644 --- a/sweep/txgenerator.go +++ b/sweep/txgenerator.go @@ -67,6 +67,14 @@ func generateInputPartitionings(sweepableInputs []txInput, } sort.Slice(sweepableInputs, func(i, j int) bool { + // Because of the specific ordering and termination condition + // that is described above, we place force sweeps at the start + // of the list. Otherwise we can't be sure that they will be + // included in an input set. + if sweepableInputs[i].parameters().Force { + return true + } + return yields[*sweepableInputs[i].OutPoint()] > yields[*sweepableInputs[j].OutPoint()] }) From 57b69e3b1ab18017a4f42ce5c42635ce162f811f Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 17 Jan 2020 11:51:09 -0800 Subject: [PATCH 014/562] discovery: check ChainHash in QueryChannelRange messages If the provided ChainHash in a QueryChannelRange message does not match that of our current chain, then we should send a blank response, rather than reply with channels for the wrong chain. --- discovery/syncer.go | 17 +++++++++++++ discovery/syncer_test.go | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/discovery/syncer.go b/discovery/syncer.go index 8348abc562..a154f99008 100644 --- a/discovery/syncer.go +++ b/discovery/syncer.go @@ -894,6 +894,23 @@ func (g *GossipSyncer) replyPeerQueries(msg lnwire.Message) error { // ensure that our final fragment carries the "complete" bit to indicate the // end of our streaming response. func (g *GossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) error { + // Before responding, we'll check to ensure that the remote peer is + // querying for the same chain that we're on. If not, we'll send back a + // response with a complete value of zero to indicate we're on a + // different chain. + if g.cfg.chainHash != query.ChainHash { + log.Warnf("Remote peer requested QueryChannelRange for "+ + "chain=%v, we're on chain=%v", query.ChainHash, + g.cfg.chainHash) + + return g.cfg.sendToPeerSync(&lnwire.ReplyChannelRange{ + QueryChannelRange: *query, + Complete: 0, + EncodingType: g.cfg.encodingType, + ShortChanIDs: nil, + }) + } + log.Infof("GossipSyncer(%x): filtering chan range: start_height=%v, "+ "num_blocks=%v", g.cfg.peerPub[:], query.FirstBlockHeight, query.NumBlocks) diff --git a/discovery/syncer_test.go b/discovery/syncer_test.go index 1b1f88909a..606fc0629c 100644 --- a/discovery/syncer_test.go +++ b/discovery/syncer_test.go @@ -533,6 +533,61 @@ func TestGossipSyncerApplyGossipFilter(t *testing.T) { } } +// TestGossipSyncerQueryChannelRangeWrongChainHash tests that if we receive a +// channel range query for the wrong chain, then we send back a response with no +// channels and complete=0. +func TestGossipSyncerQueryChannelRangeWrongChainHash(t *testing.T) { + t.Parallel() + + // First, we'll create a GossipSyncer instance with a canned sendToPeer + // message to allow us to intercept their potential sends. + msgChan, syncer, _ := newTestSyncer( + lnwire.NewShortChanIDFromInt(10), defaultEncoding, + defaultChunkSize, + ) + + // We'll now ask the syncer to reply to a channel range query, but for a + // chain that it isn't aware of. + query := &lnwire.QueryChannelRange{ + ChainHash: *chaincfg.SimNetParams.GenesisHash, + FirstBlockHeight: 0, + NumBlocks: math.MaxUint32, + } + err := syncer.replyChanRangeQuery(query) + if err != nil { + t.Fatalf("unable to process short chan ID's: %v", err) + } + + select { + case <-time.After(time.Second * 15): + t.Fatalf("no msgs received") + + case msgs := <-msgChan: + // We should get back exactly one message, that's a + // ReplyChannelRange with a matching query, and a complete value + // of zero. + if len(msgs) != 1 { + t.Fatalf("wrong messages: expected %v, got %v", + 1, len(msgs)) + } + + msg, ok := msgs[0].(*lnwire.ReplyChannelRange) + if !ok { + t.Fatalf("expected lnwire.ReplyChannelRange, got %T", msg) + } + + if msg.QueryChannelRange != *query { + t.Fatalf("wrong query channel range in reply: "+ + "expected: %v\ngot: %v", spew.Sdump(*query), + spew.Sdump(msg.QueryChannelRange)) + } + if msg.Complete != 0 { + t.Fatalf("expected complete set to 0, got %v", + msg.Complete) + } + } +} + // TestGossipSyncerReplyShortChanIDsWrongChainHash tests that if we get a chan // ID query for the wrong chain, then we send back only a short ID end with // complete=0. From a908a74acb427b85b3065556d0671ed39addb1be Mon Sep 17 00:00:00 2001 From: Carsten Otto Date: Fri, 17 Jan 2020 21:12:02 +0000 Subject: [PATCH 015/562] Fix typos --- feature/deps.go | 2 +- lnrpc/routerrpc/router.pb.go | 2 +- lnrpc/routerrpc/router.proto | 2 +- lnrpc/routerrpc/router_backend.go | 2 +- lnrpc/rpc.pb.go | 4 ++-- lnrpc/rpc.proto | 4 ++-- lnrpc/rpc.swagger.json | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/feature/deps.go b/feature/deps.go index 6382ff33cd..343f3f6043 100644 --- a/feature/deps.go +++ b/feature/deps.go @@ -82,7 +82,7 @@ func validateDeps(features featureSet, supported supportedFeatures) error { return NewErrMissingFeatureDep(bit) } - // Alternatively, if we know that this depdendency is valid, we + // Alternatively, if we know that this dependency is valid, we // can short circuit and continue verifying other bits. if checked { continue diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 1be1423edb..25aa0b0911 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -260,7 +260,7 @@ type SendPaymentRequest struct { AllowSelfPayment bool `protobuf:"varint,15,opt,name=allow_self_payment,json=allowSelfPayment,proto3" json:"allow_self_payment,omitempty"` //* //Features assumed to be supported by the final node. All transitive feature - //depdencies must also be set properly. For a given feature bit pair, either + //dependencies must also be set properly. For a given feature bit pair, either //optional or remote may be set, but not both. If this field is nil or empty, //the router will try to load destination features from the graph as a //fallback. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 034ee2c53f..bc5ad74d62 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -108,7 +108,7 @@ message SendPaymentRequest { /** Features assumed to be supported by the final node. All transitive feature - depdencies must also be set properly. For a given feature bit pair, either + dependencies must also be set properly. For a given feature bit pair, either optional or remote may be set, but not both. If this field is nil or empty, the router will try to load destination features from the graph as a fallback. diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 23cd32e0bc..4802902e36 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -749,7 +749,7 @@ func unmarshallHopHint(rpcHint *lnrpc.HopHint) (zpay32.HopHint, error) { // UnmarshalFeatures converts a list of uint32's into a valid feature vector. // This method checks that feature bit pairs aren't assigned toegether, and -// validates transitive depdencies. +// validates transitive dependencies. func UnmarshalFeatures( rpcFeatures []lnrpc.FeatureBit) (*lnwire.FeatureVector, error) { diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 696d09693e..c1a95dc77d 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -1228,7 +1228,7 @@ type SendRequest struct { AllowSelfPayment bool `protobuf:"varint,14,opt,name=allow_self_payment,json=allowSelfPayment,proto3" json:"allow_self_payment,omitempty"` //* //Features assumed to be supported by the final node. All transitive feature - //depdencies must also be set properly. For a given feature bit pair, either + //dependencies must also be set properly. For a given feature bit pair, either //optional or remote may be set, but not both. If this field is nil or empty, //the router will try to load destination features from the graph as a //fallback. @@ -5915,7 +5915,7 @@ type QueryRoutesRequest struct { RouteHints []*RouteHint `protobuf:"bytes,16,rep,name=route_hints,json=routeHints,proto3" json:"route_hints,omitempty"` //* //Features assumed to be supported by the final node. All transitive feature - //depdencies must also be set properly. For a given feature bit pair, either + //dependencies must also be set properly. For a given feature bit pair, either //optional or remote may be set, but not both. If this field is nil or empty, //the router will try to load destination features from the graph as a //fallback. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index bc63c4148f..27e552ffc4 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -985,7 +985,7 @@ message SendRequest { /** Features assumed to be supported by the final node. All transitive feature - depdencies must also be set properly. For a given feature bit pair, either + dependencies must also be set properly. For a given feature bit pair, either optional or remote may be set, but not both. If this field is nil or empty, the router will try to load destination features from the graph as a fallback. @@ -2065,7 +2065,7 @@ message QueryRoutesRequest { /** Features assumed to be supported by the final node. All transitive feature - depdencies must also be set properly. For a given feature bit pair, either + dependencies must also be set properly. For a given feature bit pair, either optional or remote may be set, but not both. If this field is nil or empty, the router will try to load destination features from the graph as a fallback. diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 9ed22f8d7e..73c3778aad 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -831,7 +831,7 @@ }, { "name": "dest_features", - "description": "*\nFeatures assumed to be supported by the final node. All transitive feature\ndepdencies must also be set properly. For a given feature bit pair, either\noptional or remote may be set, but not both. If this field is nil or empty,\nthe router will try to load destination features from the graph as a\nfallback.", + "description": "*\nFeatures assumed to be supported by the final node. All transitive feature\ndependencies must also be set properly. For a given feature bit pair, either\noptional or remote may be set, but not both. If this field is nil or empty,\nthe router will try to load destination features from the graph as a\nfallback.", "in": "query", "required": false, "type": "array", @@ -4012,7 +4012,7 @@ "items": { "$ref": "#/definitions/lnrpcFeatureBit" }, - "description": "*\nFeatures assumed to be supported by the final node. All transitive feature\ndepdencies must also be set properly. For a given feature bit pair, either\noptional or remote may be set, but not both. If this field is nil or empty,\nthe router will try to load destination features from the graph as a\nfallback." + "description": "*\nFeatures assumed to be supported by the final node. All transitive feature\ndependencies must also be set properly. For a given feature bit pair, either\noptional or remote may be set, but not both. If this field is nil or empty,\nthe router will try to load destination features from the graph as a\nfallback." } } }, From b600ecda86047288f4a93ca4be61e36abe4d74a5 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 20 Jan 2020 10:57:34 +0100 Subject: [PATCH 016/562] channeldb: inject clock into database Use our standard clock mock for database time queries. --- channeldb/channel_test.go | 5 ++++- channeldb/db.go | 6 +++--- channeldb/invoice_test.go | 3 --- channeldb/invoices.go | 2 +- channeldb/options.go | 13 +++++++++++++ invoices/invoiceregistry_test.go | 6 +++--- invoices/test_utils_test.go | 9 +++++---- 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index 525b248907..7f82e9d3ca 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -16,6 +16,7 @@ import ( "github.com/btcsuite/btcutil" _ "github.com/btcsuite/btcwallet/walletdb/bdb" "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" @@ -68,6 +69,8 @@ var ( privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), key[:]) wireSig, _ = lnwire.NewSigFromSignature(testSig) + + testClock = clock.NewTestClock(testNow) ) // makeTestDB creates a new instance of the ChannelDB for testing purposes. A @@ -82,7 +85,7 @@ func makeTestDB() (*DB, func(), error) { } // Next, create channeldb for the first time. - cdb, err := Open(tempDirName) + cdb, err := Open(tempDirName, OptionClock(testClock)) if err != nil { return nil, nil, err } diff --git a/channeldb/db.go b/channeldb/db.go index c3f6323486..c9410bfbb5 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -15,6 +15,7 @@ import ( "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb/migration12" "github.com/lightningnetwork/lnd/channeldb/migration_01_to_11" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lnwire" ) @@ -137,8 +138,7 @@ type DB struct { *bbolt.DB dbPath string graph *ChannelGraph - - Now func() time.Time + clock clock.Clock } // Open opens an existing channeldb. Any necessary schemas migrations due to @@ -172,7 +172,7 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) { chanDB := &DB{ DB: bdb, dbPath: dbPath, - Now: time.Now, + clock: opts.clock, } chanDB.graph = newChannelGraph( chanDB, opts.RejectCacheSize, opts.ChannelCacheSize, diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index 922239e5b2..2680789445 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -304,7 +304,6 @@ func TestInvoiceAddTimeSeries(t *testing.T) { if err != nil { t.Fatalf("unable to make test db: %v", err) } - db.Now = func() time.Time { return testNow } // We'll start off by creating 20 random invoices, and inserting them // into the database. @@ -556,7 +555,6 @@ func TestDuplicateSettleInvoice(t *testing.T) { if err != nil { t.Fatalf("unable to make test db: %v", err) } - db.Now = func() time.Time { return testNow } // We'll start out by creating an invoice and writing it to the DB. amt := lnwire.NewMSatFromSatoshis(1000) @@ -631,7 +629,6 @@ func TestQueryInvoices(t *testing.T) { if err != nil { t.Fatalf("unable to make test db: %v", err) } - db.Now = func() time.Time { return testNow } // To begin the test, we'll add 50 invoices to the database. We'll // assume that the index of the invoice within the database is the same diff --git a/channeldb/invoices.go b/channeldb/invoices.go index c2969a4aa7..66363fe127 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -1348,7 +1348,7 @@ func (d *DB) updateInvoice(hash lntypes.Hash, invoices, settleIndex *bbolt.Bucke return &invoice, nil } - now := d.Now() + now := d.clock.Now() // Update invoice state if the update descriptor indicates an invoice // state change. diff --git a/channeldb/options.go b/channeldb/options.go index 38ac05efdd..90185f2cd0 100644 --- a/channeldb/options.go +++ b/channeldb/options.go @@ -1,5 +1,7 @@ package channeldb +import "github.com/lightningnetwork/lnd/clock" + const ( // DefaultRejectCacheSize is the default number of rejectCacheEntries to // cache for use in the rejection cache of incoming gossip traffic. This @@ -26,6 +28,9 @@ type Options struct { // freelist to disk, resulting in improved performance at the expense of // increased startup time. NoFreelistSync bool + + // clock is the time source used by the database. + clock clock.Clock } // DefaultOptions returns an Options populated with default values. @@ -34,6 +39,7 @@ func DefaultOptions() Options { RejectCacheSize: DefaultRejectCacheSize, ChannelCacheSize: DefaultChannelCacheSize, NoFreelistSync: true, + clock: clock.NewDefaultClock(), } } @@ -60,3 +66,10 @@ func OptionSetSyncFreelist(b bool) OptionModifier { o.NoFreelistSync = !b } } + +// OptionClock sets a non-default clock dependency. +func OptionClock(clock clock.Clock) OptionModifier { + return func(o *Options) { + o.clock = clock + } +} diff --git a/invoices/invoiceregistry_test.go b/invoices/invoiceregistry_test.go index b9fbe4b64d..9f360e267f 100644 --- a/invoices/invoiceregistry_test.go +++ b/invoices/invoiceregistry_test.go @@ -317,7 +317,7 @@ func TestCancelInvoice(t *testing.T) { func TestSettleHoldInvoice(t *testing.T) { defer timeout()() - cdb, cleanup, err := newTestChannelDB() + cdb, cleanup, err := newTestChannelDB(clock.NewTestClock(time.Time{})) if err != nil { t.Fatal(err) } @@ -497,7 +497,7 @@ func TestSettleHoldInvoice(t *testing.T) { func TestCancelHoldInvoice(t *testing.T) { defer timeout()() - cdb, cleanup, err := newTestChannelDB() + cdb, cleanup, err := newTestChannelDB(clock.NewTestClock(time.Time{})) if err != nil { t.Fatal(err) } @@ -798,7 +798,7 @@ func TestMppPayment(t *testing.T) { func TestInvoiceExpiryWithRegistry(t *testing.T) { t.Parallel() - cdb, cleanup, err := newTestChannelDB() + cdb, cleanup, err := newTestChannelDB(clock.NewTestClock(time.Time{})) defer cleanup() if err != nil { diff --git a/invoices/test_utils_test.go b/invoices/test_utils_test.go index a1f84e2640..cf0f14ea1b 100644 --- a/invoices/test_utils_test.go +++ b/invoices/test_utils_test.go @@ -110,7 +110,7 @@ var ( } ) -func newTestChannelDB() (*channeldb.DB, func(), error) { +func newTestChannelDB(clock clock.Clock) (*channeldb.DB, func(), error) { // First, create a temporary directory to be used for the duration of // this test. tempDirName, err := ioutil.TempDir("", "channeldb") @@ -119,7 +119,9 @@ func newTestChannelDB() (*channeldb.DB, func(), error) { } // Next, create channeldb for the first time. - cdb, err := channeldb.Open(tempDirName) + cdb, err := channeldb.Open( + tempDirName, channeldb.OptionClock(clock), + ) if err != nil { os.RemoveAll(tempDirName) return nil, nil, err @@ -145,11 +147,10 @@ type testContext struct { func newTestContext(t *testing.T) *testContext { clock := clock.NewTestClock(testTime) - cdb, cleanup, err := newTestChannelDB() + cdb, cleanup, err := newTestChannelDB(clock) if err != nil { t.Fatal(err) } - cdb.Now = clock.Now expiryWatcher := NewInvoiceExpiryWatcher(clock) From bb619352be5bee0a8e8682238ff49c4f913e6fec Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 12 Jun 2019 10:25:53 +0200 Subject: [PATCH 017/562] lntest: check payment status settled after claim test --- ...d_multi-hop_htlc_local_chain_claim_test.go | 64 +++++++++++++++++++ ...ulti-hop_htlc_receiver_chain_claim_test.go | 10 +++ ..._multi-hop_htlc_remote_chain_claim_test.go | 10 +++ 3 files changed, 84 insertions(+) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 0b155c9776..7d79eacb51 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -393,6 +393,16 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) if err != nil { t.Fatalf(predErr.Error()) } + + // Finally, check that the Alice's payment is correctly marked + // succeeded. + ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) + err = checkPaymentStatus( + ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ) + if err != nil { + t.Fatalf(err.Error()) + } } // waitForInvoiceAccepted waits until the specified invoice moved to the @@ -421,3 +431,57 @@ func waitForInvoiceAccepted(t *harnessTest, node *lntest.HarnessNode, } } } + +// checkPaymentStatus asserts that the given node list a payment with the given +// preimage has the expected status. +func checkPaymentStatus(ctxt context.Context, node *lntest.HarnessNode, + preimage lntypes.Preimage, status lnrpc.Payment_PaymentStatus) error { + + req := &lnrpc.ListPaymentsRequest{ + IncludeIncomplete: true, + } + paymentsResp, err := node.ListPayments(ctxt, req) + if err != nil { + return fmt.Errorf("error when obtaining Alice payments: %v", + err) + } + + payHash := preimage.Hash() + var found bool + for _, p := range paymentsResp.Payments { + if p.PaymentHash != payHash.String() { + continue + } + + found = true + if p.Status != status { + return fmt.Errorf("expected payment status "+ + "%v, got %v", status, p.Status) + } + + switch status { + + // If this expected status is SUCCEEDED, we expect the final preimage. + case lnrpc.Payment_SUCCEEDED: + if p.PaymentPreimage != preimage.String() { + return fmt.Errorf("preimage doesn't match: %v vs %v", + p.PaymentPreimage, preimage.String()) + } + + // Otherwise we expect an all-zero preimage. + default: + if p.PaymentPreimage != (lntypes.Preimage{}).String() { + return fmt.Errorf("expected zero preimage, got %v", + p.PaymentPreimage) + } + } + + } + + if !found { + return fmt.Errorf("payment with payment hash %v not found "+ + "in response", payHash) + } + + return nil +} diff --git a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go index fc497aec1a..8a01763393 100644 --- a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go @@ -298,6 +298,16 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) "%d sat", invoiceAmt, invoice.AmtPaidSat) } + // Finally, check that the Alice's payment is correctly marked + // succeeded. + ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) + err = checkPaymentStatus( + ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ) + if err != nil { + t.Fatalf(err.Error()) + } + // We'll close out the channel between Alice and Bob, then shutdown // carol to conclude the test. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) diff --git a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go index 14894e99cc..b96bc17f8e 100644 --- a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go @@ -332,4 +332,14 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest t.Fatalf("expected invoice to be settled with %d sat, got "+ "%d sat", invoiceAmt, invoice.AmtPaidSat) } + + // Finally, check that the Alice's payment is correctly marked + // succeeded. + ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) + err = checkPaymentStatus( + ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ) + if err != nil { + t.Fatalf(err.Error()) + } } From 80ad0fdd5ca906d540db56f05486dc79496d9e8c Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 12 Jun 2019 10:44:22 +0200 Subject: [PATCH 018/562] lntest: restart Alice after on-chain settle To ensure lnd is able to pick up an on-chain preimage properly after a restart, we suspend Alice and check that the payment is listed correctly as succeeded after a restart. --- .../lnd_multi-hop_htlc_local_chain_claim_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 7d79eacb51..123359dc49 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -195,6 +195,13 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) } } + // At this point we suspend Alice to make sure she'll handle the + // on-chain settle after a restart. + restartAlice, err := net.SuspendNode(net.Alice) + if err != nil { + t.Fatalf("unable to suspend alice: %v", err) + } + // Mine a block to confirm the two transactions (+ the coinbase). block = mineBlocks(t, net, 1, 2)[0] if len(block.Transactions) != 3 { @@ -285,6 +292,12 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) bobSecondLevelCSV := uint32(defaultCSV) carolSecondLevelCSV-- + // Now that the preimage from Bob has hit the chain, restart Alice to + // ensure she'll pick it up. + if err := restartAlice(); err != nil { + t.Fatalf("unable to restart alice: %v", err) + } + // If we then mine 3 additional blocks, Carol's second level tx should // mature, and she can pull the funds from it with a sweep tx. if _, err := net.Miner.Node.Generate(carolSecondLevelCSV); err != nil { From ef28d2aaedf3f324036a17a1ef05a91cb791c174 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 21 Jan 2020 09:02:25 +0100 Subject: [PATCH 019/562] routing: penalize node-level failures harder Previously we only penalized the outgoing connections of a failing node. This turned out not to be sufficient, because the next route sometimes went into the same failing node again to try a different outgoing connection that wasn't yet known to mission control and therefore not penalized before. --- routing/missioncontrol.go | 20 ++++++++++---------- routing/missioncontrol_test.go | 4 ++-- routing/result_interpretation.go | 9 ++++++--- routing/result_interpretation_test.go | 8 ++++++++ 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/routing/missioncontrol.go b/routing/missioncontrol.go index c360953afb..f52c6fce9a 100644 --- a/routing/missioncontrol.go +++ b/routing/missioncontrol.go @@ -333,18 +333,18 @@ func (m *MissionControl) setLastPairResult(fromNode, toNode route.Vertex, nodePairs[toNode] = current } -// setAllFail stores a fail result for all known connection of the given node. -func (m *MissionControl) setAllFail(fromNode route.Vertex, +// setAllFail stores a fail result for all known connections to and from the +// given node. +func (m *MissionControl) setAllFail(node route.Vertex, timestamp time.Time) { - nodePairs, ok := m.lastPairResult[fromNode] - if !ok { - return - } - - for connection := range nodePairs { - nodePairs[connection] = TimedPairResult{ - FailTime: timestamp, + for fromNode, nodePairs := range m.lastPairResult { + for toNode := range nodePairs { + if fromNode == node || toNode == node { + nodePairs[toNode] = TimedPairResult{ + FailTime: timestamp, + } + } } } } diff --git a/routing/missioncontrol_test.go b/routing/missioncontrol_test.go index f921b71de3..98cf95302f 100644 --- a/routing/missioncontrol_test.go +++ b/routing/missioncontrol_test.go @@ -186,8 +186,8 @@ func TestMissionControl(t *testing.T) { // Check whether history snapshot looks sane. history := ctx.mc.GetHistorySnapshot() - if len(history.Pairs) != 3 { - t.Fatalf("expected 3 pairs, but got %v", len(history.Pairs)) + if len(history.Pairs) != 4 { + t.Fatalf("expected 4 pairs, but got %v", len(history.Pairs)) } // Test reporting a success. diff --git a/routing/result_interpretation.go b/routing/result_interpretation.go index 30d65cc0b2..660ce69cc8 100644 --- a/routing/result_interpretation.go +++ b/routing/result_interpretation.go @@ -424,11 +424,13 @@ func (i *interpretedResult) failNode(rt *route.Route, idx int) { // Mark the incoming connection as failed for the node. We intent to // penalize as much as we can for a node level failure, including future // outgoing traffic for this connection. The pair as it is returned by - // getPair is directed towards the failed node. Therefore we first - // reverse the pair. We don't want to affect the score of the node - // sending towards the failing node. + // getPair is penalized in the original and the reversed direction. Note + // that this will also affect the score of the failing node's peers. + // This is necessary to prevent future routes from keep going into the + // same node again. incomingChannelIdx := idx - 1 inPair, _ := getPair(rt, incomingChannelIdx) + i.pairResults[inPair] = failPairResult(0) i.pairResults[inPair.Reverse()] = failPairResult(0) // If not the ultimate node, mark the outgoing connection as failed for @@ -437,6 +439,7 @@ func (i *interpretedResult) failNode(rt *route.Route, idx int) { outgoingChannelIdx := idx outPair, _ := getPair(rt, outgoingChannelIdx) i.pairResults[outPair] = failPairResult(0) + i.pairResults[outPair.Reverse()] = failPairResult(0) } } diff --git a/routing/result_interpretation_test.go b/routing/result_interpretation_test.go index 2204139e32..537869f0b6 100644 --- a/routing/result_interpretation_test.go +++ b/routing/result_interpretation_test.go @@ -165,6 +165,8 @@ var resultTestCases = []resultTestCase{ pairResults: map[DirectedNodePair]pairResult{ getTestPair(1, 0): failPairResult(0), getTestPair(1, 2): failPairResult(0), + getTestPair(0, 1): failPairResult(0), + getTestPair(2, 1): failPairResult(0), }, }, }, @@ -182,6 +184,7 @@ var resultTestCases = []resultTestCase{ nodeFailure: &hops[1], pairResults: map[DirectedNodePair]pairResult{ getTestPair(1, 0): failPairResult(0), + getTestPair(0, 1): failPairResult(0), }, }, }, @@ -233,6 +236,7 @@ var resultTestCases = []resultTestCase{ amt: 97, }, getTestPair(4, 3): {}, + getTestPair(3, 4): {}, }, finalFailureReason: &reasonError, nodeFailure: &hops[4], @@ -257,6 +261,7 @@ var resultTestCases = []resultTestCase{ amt: 99, }, getTestPair(3, 2): {}, + getTestPair(2, 3): {}, }, finalFailureReason: &reasonError, nodeFailure: &hops[3], @@ -284,6 +289,8 @@ var resultTestCases = []resultTestCase{ }, getTestPair(3, 2): {}, getTestPair(3, 4): {}, + getTestPair(2, 3): {}, + getTestPair(4, 3): {}, }, nodeFailure: &hops[3], }, @@ -301,6 +308,7 @@ var resultTestCases = []resultTestCase{ expectedResult: &interpretedResult{ pairResults: map[DirectedNodePair]pairResult{ getTestPair(1, 0): {}, + getTestPair(0, 1): {}, }, finalFailureReason: &reasonError, nodeFailure: &hops[1], From f20f29696aa82aac0a91ba5bde9956b43a3a0928 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 2 Nov 2018 11:33:01 +0100 Subject: [PATCH 020/562] rpcserver: let sendPayment sendLoop listen for shutdown Intead of checking for shutdown in the receive loop, we let the sendLoop handle it, as it can return the error directly. This works since the returning sendLoop will trigger a close of the `reqQuit` channel, which will ensure the receive loop exits. --- rpcserver.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 11227fe64e..ff02ea0d39 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3696,9 +3696,7 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { select { case <-reqQuit: return - case <-r.quit: - errChan <- nil - return + default: // Receive the next pending payment within the // stream sent by the client. If we read the @@ -3756,6 +3754,9 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { case err := <-errChan: return err + case <-r.quit: + return errors.New("rpc server shutting down") + case payIntent := <-payChan: // We launch a new goroutine to execute the current // payment so we can continue to serve requests while From c49ba0c5cb53bc55d48e374e33f2268c72b54231 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 2 Nov 2018 11:33:01 +0100 Subject: [PATCH 021/562] rpcServer: ensure we don't get blocked on bidirectional payment errors This commit fixes a potential issue in the bidirectional sendPayment case, where multiple goroutines could be sending on an errChan with buffer 1. Instead we select on default as well, as it is enough to handle the first error that was received. --- rpcserver.go | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index ff02ea0d39..43f7f76277 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3707,10 +3707,12 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { errChan <- nil return } else if err != nil { + rpcsLog.Errorf("Failed receiving from "+ + "stream: %v", err) + select { case errChan <- err: - case <-reqQuit: - return + default: } return } @@ -3728,18 +3730,22 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { PaymentError: err.Error(), PaymentHash: payIntent.rHash[:], }); err != nil { + rpcsLog.Errorf("Failed "+ + "sending on "+ + "stream: %v", err) + select { case errChan <- err: - case <-reqQuit: - return + default: } + return } continue } // If the payment was well formed, then we'll // send to the dispatch goroutine, or exit, - // which ever comes first + // which ever comes first. select { case payChan <- &payIntent: case <-reqQuit: @@ -3751,6 +3757,9 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { for { select { + + // If we encounter and error either during sending or + // receiving, we return directly, closing the stream. case err := <-errChan: return err @@ -3779,7 +3788,13 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { // payment, then we'll return the error to the // user, and terminate. case saveErr != nil: - errChan <- saveErr + rpcsLog.Errorf("Failed dispatching "+ + "payment intent: %v", saveErr) + + select { + case errChan <- saveErr: + default: + } return // If we receive payment error than, instead of @@ -3791,7 +3806,14 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { PaymentHash: payIntent.rHash[:], }) if err != nil { - errChan <- err + rpcsLog.Errorf("Failed "+ + "sending error "+ + "response: %v", err) + + select { + case errChan <- err: + default: + } } return } @@ -3811,7 +3833,13 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { PaymentRoute: marshalledRouted, }) if err != nil { - errChan <- err + rpcsLog.Errorf("Failed sending "+ + "response: %v", err) + + select { + case errChan <- err: + default: + } return } }() From 5b85721c04028f69999a29834cc137437473fe75 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 2 Nov 2018 11:33:01 +0100 Subject: [PATCH 022/562] rpcServer: ensure all payIntents are handled before exiting This commit fixes a problem that could arise when handling a continuous stream of payIntents. We would risk the client sending a set of payment intents and closing the stream, but we wouldn't be sure the sendLoop had read all messages on the `payChan` before exiting with the nil error from the `errChan`. Instead, we close the `payChan` to indicate that no more payments are going to be received. --- rpcserver.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 43f7f76277..7dd1ef5e70 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3704,7 +3704,7 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { // stream, and we can exit normally. nextPayment, err := stream.recv() if err == io.EOF { - errChan <- nil + close(payChan) return } else if err != nil { rpcsLog.Errorf("Failed receiving from "+ @@ -3755,6 +3755,7 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { } }() +sendLoop: for { select { @@ -3766,7 +3767,14 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { case <-r.quit: return errors.New("rpc server shutting down") - case payIntent := <-payChan: + case payIntent, ok := <-payChan: + // If the receive loop is done, we break the send loop + // and wait for the ongoing payments to finish before + // exiting. + if !ok { + break sendLoop + } + // We launch a new goroutine to execute the current // payment so we can continue to serve requests while // this payment is being dispatched. From dc238101183fae60ef5ea1799727ea529160349d Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 2 Nov 2018 11:33:01 +0100 Subject: [PATCH 023/562] rpcServer: wait for all goroutines to finish before exiting Returning from the sendPayments method closes the underlying stream, so we would risk payments still being in flight when returning. We add the running goroutines to a waitgroup, such that we can wait for them all to exit before exiting and closing the stream. In case an error is encountered in the process, we will return directly, which will close the `reqQuit` channel and prompt the gorpoutines to shut down. --- rpcserver.go | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 7dd1ef5e70..35eec95215 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3680,18 +3680,23 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error { htlcSema <- struct{}{} } + // We keep track of the running goroutines and set up a quit signal we + // can use to request them to exit if the method returns because of an + // encountered error. + var wg sync.WaitGroup + reqQuit := make(chan struct{}) + defer close(reqQuit) + // Launch a new goroutine to handle reading new payment requests from // the client. This way we can handle errors independently of blocking // and waiting for the next payment request to come through. - reqQuit := make(chan struct{}) - defer func() { - close(reqQuit) - }() - // TODO(joostjager): Callers expect result to come in in the same order // as the request were sent, but this is far from guarantueed in the // code below. + wg.Add(1) go func() { + defer wg.Done() + for { select { case <-reqQuit: @@ -3778,11 +3783,18 @@ sendLoop: // We launch a new goroutine to execute the current // payment so we can continue to serve requests while // this payment is being dispatched. + wg.Add(1) go func() { + defer wg.Done() + // Attempt to grab a free semaphore slot, using // a defer to eventually release the slot // regardless of payment success. - <-htlcSema + select { + case <-htlcSema: + case <-reqQuit: + return + } defer func() { htlcSema <- struct{}{} }() @@ -3853,6 +3865,10 @@ sendLoop: }() } } + + // Wait for all goroutines to finish before closing the stream. + wg.Wait() + return nil } // SendPaymentSync is the synchronous non-streaming version of SendPayment. From c7208ffb2c150c3b02425f5550b683420b7a9880 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 21 Jan 2020 13:55:14 +0100 Subject: [PATCH 024/562] invoices: add missing String() cases --- invoices/update.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/invoices/update.go b/invoices/update.go index 15bcf08aeb..57a41de9f7 100644 --- a/invoices/update.go +++ b/invoices/update.go @@ -128,6 +128,9 @@ func (u ResolutionResult) String() string { case ResultSettled: return "settled" + case ResultCanceled: + return "canceled" + case ResultInvoiceNotOpen: return "invoice no longer open" @@ -137,6 +140,9 @@ func (u ResolutionResult) String() string { case ResultMppInProgress: return "mpp reception in progress" + case ResultMppTimeout: + return "mpp timeout" + case ResultAddressMismatch: return "payment address mismatch" @@ -152,6 +158,9 @@ func (u ResolutionResult) String() string { case ResultKeySendError: return "invalid keysend parameters" + case ResultInvoiceNotFound: + return "invoice not found" + default: return "unknown" } From 227e66c469cf59e43620585996f4bc73ea4c52f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hampus=20Sj=C3=B6berg?= Date: Sun, 29 Sep 2019 12:13:01 +0200 Subject: [PATCH 025/562] rpc: Add PendingOpenChannel to SubscribeChannelEvents This commit adds PendingOpenChannel to SubscribeChannelEvents stream in the gRPC API. This is useful for keeping track of channel openings that Autopilot does. It can also be used for the non-initator side of a channel opening to keep track of channel openings. --- channelnotifier/channelnotifier.go | 17 + fundingmanager.go | 11 + fundingmanager_test.go | 11 +- lnrpc/rpc.pb.go | 1265 ++++++++++++++-------------- lnrpc/rpc.proto | 2 + lnrpc/rpc.swagger.json | 6 +- lntest/itest/lnd_test.go | 23 +- rpcserver.go | 14 +- server.go | 15 +- 9 files changed, 720 insertions(+), 644 deletions(-) diff --git a/channelnotifier/channelnotifier.go b/channelnotifier/channelnotifier.go index b2e5c6740c..e484b9a6c8 100644 --- a/channelnotifier/channelnotifier.go +++ b/channelnotifier/channelnotifier.go @@ -20,6 +20,13 @@ type ChannelNotifier struct { chanDB *channeldb.DB } +// PendingOpenChannelEvent represents a new event where a new channel has +// entered a pending open state. +type PendingOpenChannelEvent struct { + // ChannelPoint is the channelpoint for the new channel. + ChannelPoint *wire.OutPoint +} + // OpenChannelEvent represents a new event where a channel goes from pending // open to open. type OpenChannelEvent struct { @@ -82,6 +89,16 @@ func (c *ChannelNotifier) SubscribeChannelEvents() (*subscribe.Client, error) { return c.ntfnServer.Subscribe() } +// NotifyPendingOpenChannelEvent notifies the channelEventNotifier goroutine that a +// new channel is pending. +func (c *ChannelNotifier) NotifyPendingOpenChannelEvent(chanPoint wire.OutPoint) { + event := PendingOpenChannelEvent{ChannelPoint: &chanPoint} + + if err := c.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send pending open channel update: %v", err) + } +} + // NotifyOpenChannelEvent notifies the channelEventNotifier goroutine that a // channel has gone from pending open to open. func (c *ChannelNotifier) NotifyOpenChannelEvent(chanPoint wire.OutPoint) { diff --git a/fundingmanager.go b/fundingmanager.go index 09d5807b8f..8484b94554 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -363,6 +363,10 @@ type fundingConfig struct { // and on the requesting node's public key that returns a bool which tells // the funding manager whether or not to accept the channel. OpenChannelPredicate chanacceptor.ChannelAcceptor + + // NotifyPendingOpenChannelEvent informs the ChannelNotifier when channels + // enter a pending state. + NotifyPendingOpenChannelEvent func(wire.OutPoint) } // fundingManager acts as an orchestrator/bridge between the wallet's @@ -1691,6 +1695,10 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { f.localDiscoverySignals[channelID] = make(chan struct{}) f.localDiscoveryMtx.Unlock() + // Inform the ChannelNotifier that the channel has entered + // pending open state. + f.cfg.NotifyPendingOpenChannelEvent(fundingOut) + // At this point we have sent our last funding message to the // initiating peer before the funding transaction will be broadcast. // With this last message, our job as the responder is now complete. @@ -1835,6 +1843,9 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) { select { case resCtx.updates <- upd: + // Inform the ChannelNotifier that the channel has entered + // pending open state. + f.cfg.NotifyPendingOpenChannelEvent(*fundingPoint) case <-f.quit: return } diff --git a/fundingmanager_test.go b/fundingmanager_test.go index 3221f20d52..c9f9a42129 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -376,11 +376,12 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, publTxChan <- txn return nil }, - ZombieSweeperInterval: 1 * time.Hour, - ReservationTimeout: 1 * time.Nanosecond, - MaxPendingChannels: DefaultMaxPendingChannels, - NotifyOpenChannelEvent: func(wire.OutPoint) {}, - OpenChannelPredicate: chainedAcceptor, + ZombieSweeperInterval: 1 * time.Hour, + ReservationTimeout: 1 * time.Nanosecond, + MaxPendingChannels: DefaultMaxPendingChannels, + NotifyOpenChannelEvent: func(wire.OutPoint) {}, + OpenChannelPredicate: chainedAcceptor, + NotifyPendingOpenChannelEvent: func(wire.OutPoint) {}, } for _, op := range options { diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 696d09693e..147efba282 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -256,10 +256,11 @@ func (PeerEvent_EventType) EnumDescriptor() ([]byte, []int) { type ChannelEventUpdate_UpdateType int32 const ( - ChannelEventUpdate_OPEN_CHANNEL ChannelEventUpdate_UpdateType = 0 - ChannelEventUpdate_CLOSED_CHANNEL ChannelEventUpdate_UpdateType = 1 - ChannelEventUpdate_ACTIVE_CHANNEL ChannelEventUpdate_UpdateType = 2 - ChannelEventUpdate_INACTIVE_CHANNEL ChannelEventUpdate_UpdateType = 3 + ChannelEventUpdate_OPEN_CHANNEL ChannelEventUpdate_UpdateType = 0 + ChannelEventUpdate_CLOSED_CHANNEL ChannelEventUpdate_UpdateType = 1 + ChannelEventUpdate_ACTIVE_CHANNEL ChannelEventUpdate_UpdateType = 2 + ChannelEventUpdate_INACTIVE_CHANNEL ChannelEventUpdate_UpdateType = 3 + ChannelEventUpdate_PENDING_OPEN_CHANNEL ChannelEventUpdate_UpdateType = 4 ) var ChannelEventUpdate_UpdateType_name = map[int32]string{ @@ -267,13 +268,15 @@ var ChannelEventUpdate_UpdateType_name = map[int32]string{ 1: "CLOSED_CHANNEL", 2: "ACTIVE_CHANNEL", 3: "INACTIVE_CHANNEL", + 4: "PENDING_OPEN_CHANNEL", } var ChannelEventUpdate_UpdateType_value = map[string]int32{ - "OPEN_CHANNEL": 0, - "CLOSED_CHANNEL": 1, - "ACTIVE_CHANNEL": 2, - "INACTIVE_CHANNEL": 3, + "OPEN_CHANNEL": 0, + "CLOSED_CHANNEL": 1, + "ACTIVE_CHANNEL": 2, + "INACTIVE_CHANNEL": 3, + "PENDING_OPEN_CHANNEL": 4, } func (x ChannelEventUpdate_UpdateType) String() string { @@ -5565,6 +5568,7 @@ type ChannelEventUpdate struct { // *ChannelEventUpdate_ClosedChannel // *ChannelEventUpdate_ActiveChannel // *ChannelEventUpdate_InactiveChannel + // *ChannelEventUpdate_PendingOpenChannel Channel isChannelEventUpdate_Channel `protobuf_oneof:"channel"` Type ChannelEventUpdate_UpdateType `protobuf:"varint,5,opt,name=type,proto3,enum=lnrpc.ChannelEventUpdate_UpdateType" json:"type,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -5617,6 +5621,10 @@ type ChannelEventUpdate_InactiveChannel struct { InactiveChannel *ChannelPoint `protobuf:"bytes,4,opt,name=inactive_channel,proto3,oneof"` } +type ChannelEventUpdate_PendingOpenChannel struct { + PendingOpenChannel *PendingUpdate `protobuf:"bytes,6,opt,name=pending_open_channel,proto3,oneof"` +} + func (*ChannelEventUpdate_OpenChannel) isChannelEventUpdate_Channel() {} func (*ChannelEventUpdate_ClosedChannel) isChannelEventUpdate_Channel() {} @@ -5625,6 +5633,8 @@ func (*ChannelEventUpdate_ActiveChannel) isChannelEventUpdate_Channel() {} func (*ChannelEventUpdate_InactiveChannel) isChannelEventUpdate_Channel() {} +func (*ChannelEventUpdate_PendingOpenChannel) isChannelEventUpdate_Channel() {} + func (m *ChannelEventUpdate) GetChannel() isChannelEventUpdate_Channel { if m != nil { return m.Channel @@ -5660,6 +5670,13 @@ func (m *ChannelEventUpdate) GetInactiveChannel() *ChannelPoint { return nil } +func (m *ChannelEventUpdate) GetPendingOpenChannel() *PendingUpdate { + if x, ok := m.GetChannel().(*ChannelEventUpdate_PendingOpenChannel); ok { + return x.PendingOpenChannel + } + return nil +} + func (m *ChannelEventUpdate) GetType() ChannelEventUpdate_UpdateType { if m != nil { return m.Type @@ -5674,6 +5691,7 @@ func (*ChannelEventUpdate) XXX_OneofWrappers() []interface{} { (*ChannelEventUpdate_ClosedChannel)(nil), (*ChannelEventUpdate_ActiveChannel)(nil), (*ChannelEventUpdate_InactiveChannel)(nil), + (*ChannelEventUpdate_PendingOpenChannel)(nil), } } @@ -10552,623 +10570,624 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 9841 bytes of a gzipped FileDescriptorProto + // 9864 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x6c, 0x1c, 0xd9, 0x95, 0x98, 0xaa, 0x1f, 0x64, 0xf7, 0xe9, 0x07, 0x9b, 0x97, 0x14, 0xd9, 0x6a, 0x3d, 0x46, 0x53, - 0x96, 0x67, 0x64, 0x79, 0x4c, 0x69, 0x68, 0x7b, 0x56, 0x3b, 0xca, 0x7a, 0xcd, 0x97, 0x44, 0x7a, - 0x28, 0x92, 0x2e, 0x52, 0xd6, 0xda, 0xde, 0x45, 0xb9, 0xd8, 0x7d, 0x49, 0x96, 0xd5, 0x5d, 0xd5, - 0x53, 0x55, 0x4d, 0x8a, 0x76, 0x26, 0x1f, 0x41, 0x12, 0x04, 0xf9, 0x09, 0x8c, 0x45, 0x80, 0x6c, - 0x90, 0x60, 0x01, 0x6f, 0x82, 0x20, 0x08, 0x90, 0xe4, 0x27, 0xc1, 0x26, 0x70, 0xbe, 0xf2, 0xb1, - 0xf9, 0x09, 0xf2, 0x91, 0x00, 0x01, 0x12, 0x20, 0xc0, 0x62, 0xf3, 0x91, 0x45, 0x80, 0x7c, 0x25, - 0xf9, 0x0e, 0xee, 0xb9, 0x8f, 0xba, 0xb7, 0xaa, 0x9a, 0xd2, 0xd8, 0xde, 0xf9, 0x91, 0x78, 0xcf, - 0xb9, 0x75, 0x9f, 0xe7, 0x9c, 0x7b, 0x5e, 0xf7, 0x36, 0xd4, 0xa3, 0x71, 0x7f, 0x65, 0x1c, 0x85, - 0x49, 0x48, 0xaa, 0xc3, 0x20, 0x1a, 0xf7, 0x7b, 0xb7, 0x4e, 0xc3, 0xf0, 0x74, 0x48, 0x1f, 0x7a, - 0x63, 0xff, 0xa1, 0x17, 0x04, 0x61, 0xe2, 0x25, 0x7e, 0x18, 0xc4, 0xbc, 0x92, 0xfd, 0x23, 0x68, - 0x3f, 0xa3, 0xc1, 0x21, 0xa5, 0x03, 0x87, 0x7e, 0x3a, 0xa1, 0x71, 0x42, 0xbe, 0x0a, 0xf3, 0x1e, - 0xfd, 0x09, 0xa5, 0x03, 0x77, 0xec, 0xc5, 0xf1, 0xf8, 0x2c, 0xf2, 0x62, 0xda, 0xb5, 0xee, 0x5a, - 0xf7, 0x9b, 0x4e, 0x87, 0x23, 0x0e, 0x14, 0x9c, 0xbc, 0x0b, 0xcd, 0x98, 0x55, 0xa5, 0x41, 0x12, - 0x85, 0xe3, 0xcb, 0x6e, 0x09, 0xeb, 0x35, 0x18, 0x6c, 0x8b, 0x83, 0xec, 0x21, 0xcc, 0xa9, 0x1e, - 0xe2, 0x71, 0x18, 0xc4, 0x94, 0x3c, 0x82, 0xc5, 0xbe, 0x3f, 0x3e, 0xa3, 0x91, 0x8b, 0x1f, 0x8f, - 0x02, 0x3a, 0x0a, 0x03, 0xbf, 0xdf, 0xb5, 0xee, 0x96, 0xef, 0xd7, 0x1d, 0xc2, 0x71, 0xec, 0x8b, - 0xe7, 0x02, 0x43, 0xde, 0x87, 0x39, 0x1a, 0x70, 0x38, 0x1d, 0xe0, 0x57, 0xa2, 0xab, 0x76, 0x0a, - 0x66, 0x1f, 0xd8, 0x7f, 0xb3, 0x04, 0xf3, 0x3b, 0x81, 0x9f, 0xbc, 0xf4, 0x86, 0x43, 0x9a, 0xc8, - 0x39, 0xbd, 0x0f, 0x73, 0x17, 0x08, 0xc0, 0x39, 0x5d, 0x84, 0xd1, 0x40, 0xcc, 0xa8, 0xcd, 0xc1, - 0x07, 0x02, 0x3a, 0x75, 0x64, 0xa5, 0xa9, 0x23, 0x2b, 0x5c, 0xae, 0xf2, 0x94, 0xe5, 0x7a, 0x1f, - 0xe6, 0x22, 0xda, 0x0f, 0xcf, 0x69, 0x74, 0xe9, 0x5e, 0xf8, 0xc1, 0x20, 0xbc, 0xe8, 0x56, 0xee, - 0x5a, 0xf7, 0xab, 0x4e, 0x5b, 0x82, 0x5f, 0x22, 0x94, 0xac, 0xc3, 0x5c, 0xff, 0xcc, 0x0b, 0x02, - 0x3a, 0x74, 0x8f, 0xbd, 0xfe, 0xab, 0xc9, 0x38, 0xee, 0x56, 0xef, 0x5a, 0xf7, 0x1b, 0xab, 0x37, - 0x56, 0x70, 0x57, 0x57, 0x36, 0xce, 0xbc, 0x60, 0x1d, 0x31, 0x87, 0x81, 0x37, 0x8e, 0xcf, 0xc2, - 0xc4, 0x69, 0x8b, 0x2f, 0x38, 0x38, 0xb6, 0x17, 0x81, 0xe8, 0x2b, 0xc1, 0xd7, 0xde, 0xfe, 0xa7, - 0x16, 0x2c, 0xbc, 0x08, 0x86, 0x61, 0xff, 0xd5, 0x2f, 0xb9, 0x44, 0x05, 0x73, 0x28, 0xbd, 0xed, - 0x1c, 0xca, 0x9f, 0x77, 0x0e, 0x4b, 0xb0, 0x68, 0x0e, 0x56, 0xcc, 0x82, 0xc2, 0x75, 0xf6, 0xf5, - 0x29, 0x95, 0xc3, 0x92, 0xd3, 0xf8, 0x0a, 0x74, 0xfa, 0x93, 0x28, 0xa2, 0x41, 0x6e, 0x1e, 0x73, - 0x02, 0xae, 0x26, 0xf2, 0x2e, 0x34, 0x03, 0x7a, 0x91, 0x56, 0x13, 0xb4, 0x1b, 0xd0, 0x0b, 0x59, - 0xc5, 0xee, 0xc2, 0x52, 0xb6, 0x1b, 0x31, 0x80, 0x3f, 0xb5, 0xa0, 0xf2, 0x22, 0x79, 0x1d, 0x92, - 0x15, 0xa8, 0x24, 0x97, 0x63, 0xce, 0x21, 0xed, 0x55, 0x22, 0xa6, 0xb6, 0x36, 0x18, 0x44, 0x34, - 0x8e, 0x8f, 0x2e, 0xc7, 0xd4, 0x69, 0x7a, 0xbc, 0xe0, 0xb2, 0x7a, 0xa4, 0x0b, 0xb3, 0xa2, 0x8c, - 0x1d, 0xd6, 0x1d, 0x59, 0x24, 0x77, 0x00, 0xbc, 0x51, 0x38, 0x09, 0x12, 0x37, 0xf6, 0x12, 0x5c, - 0xaa, 0xb2, 0xa3, 0x41, 0xc8, 0x2d, 0xa8, 0x8f, 0x5f, 0xb9, 0x71, 0x3f, 0xf2, 0xc7, 0x09, 0x92, - 0x4d, 0xdd, 0x49, 0x01, 0xe4, 0xab, 0x50, 0x0b, 0x27, 0xc9, 0x38, 0xf4, 0x83, 0x44, 0x90, 0xca, - 0x9c, 0x18, 0xcb, 0xfe, 0x24, 0x39, 0x60, 0x60, 0x47, 0x55, 0x20, 0xf7, 0xa0, 0xd5, 0x0f, 0x83, - 0x13, 0x3f, 0x1a, 0x71, 0x61, 0xd0, 0x9d, 0xc1, 0xde, 0x4c, 0xa0, 0xfd, 0xaf, 0x4b, 0xd0, 0x38, - 0x8a, 0xbc, 0x20, 0xf6, 0xfa, 0x0c, 0xc0, 0x86, 0x9e, 0xbc, 0x76, 0xcf, 0xbc, 0xf8, 0x0c, 0x67, - 0x5b, 0x77, 0x64, 0x91, 0x2c, 0xc1, 0x0c, 0x1f, 0x28, 0xce, 0xa9, 0xec, 0x88, 0x12, 0xf9, 0x00, - 0xe6, 0x83, 0xc9, 0xc8, 0x35, 0xfb, 0x2a, 0x23, 0xb5, 0xe4, 0x11, 0x6c, 0x01, 0x8e, 0xd9, 0x5e, - 0xf3, 0x2e, 0xf8, 0x0c, 0x35, 0x08, 0xb1, 0xa1, 0x29, 0x4a, 0xd4, 0x3f, 0x3d, 0xe3, 0xd3, 0xac, - 0x3a, 0x06, 0x8c, 0xb5, 0x91, 0xf8, 0x23, 0xea, 0xc6, 0x89, 0x37, 0x1a, 0x8b, 0x69, 0x69, 0x10, - 0xc4, 0x87, 0x89, 0x37, 0x74, 0x4f, 0x28, 0x8d, 0xbb, 0xb3, 0x02, 0xaf, 0x20, 0xe4, 0x3d, 0x68, - 0x0f, 0x68, 0x9c, 0xb8, 0x62, 0x53, 0x68, 0xdc, 0xad, 0x21, 0xeb, 0x67, 0xa0, 0xac, 0x9d, 0xc8, - 0xbb, 0x70, 0xd9, 0x02, 0xd0, 0xd7, 0xdd, 0x3a, 0x1f, 0x6b, 0x0a, 0x61, 0x94, 0xf3, 0x8c, 0x26, - 0xda, 0xea, 0xc5, 0x82, 0x42, 0xed, 0x5d, 0x20, 0x1a, 0x78, 0x93, 0x26, 0x9e, 0x3f, 0x8c, 0xc9, - 0x47, 0xd0, 0x4c, 0xb4, 0xca, 0x28, 0x0a, 0x1b, 0x8a, 0x9c, 0xb4, 0x0f, 0x1c, 0xa3, 0x9e, 0x7d, - 0x06, 0xb5, 0xa7, 0x94, 0xee, 0xfa, 0x23, 0x3f, 0x21, 0x4b, 0x50, 0x3d, 0xf1, 0x5f, 0x53, 0x4e, - 0xf0, 0xe5, 0xed, 0x6b, 0x0e, 0x2f, 0x92, 0x77, 0x00, 0xf0, 0x0f, 0x77, 0xa4, 0x08, 0x6b, 0xfb, - 0x9a, 0x53, 0x47, 0xd8, 0x73, 0x46, 0x59, 0x3d, 0x98, 0x1d, 0xd3, 0xa8, 0x4f, 0xe5, 0xfe, 0x6d, - 0x5f, 0x73, 0x24, 0x60, 0x7d, 0x16, 0xaa, 0x43, 0xd6, 0xba, 0xfd, 0x27, 0x55, 0x68, 0x1c, 0xd2, - 0x40, 0x71, 0x1a, 0x81, 0x0a, 0x5b, 0x13, 0xc1, 0x5d, 0xf8, 0x37, 0xf9, 0x12, 0x34, 0x70, 0x9d, - 0xe2, 0x24, 0xf2, 0x83, 0x53, 0x4e, 0xe0, 0xeb, 0xa5, 0xae, 0xe5, 0x00, 0x03, 0x1f, 0x22, 0x94, - 0x74, 0xa0, 0xec, 0x8d, 0x24, 0x81, 0xb3, 0x3f, 0xc9, 0x0d, 0xa8, 0x79, 0xa3, 0x84, 0x0f, 0xaf, - 0x89, 0xe0, 0x59, 0x6f, 0x94, 0xe0, 0xd0, 0xde, 0x85, 0xe6, 0xd8, 0xbb, 0x1c, 0x31, 0x7e, 0x56, - 0x54, 0xd1, 0x74, 0x1a, 0x02, 0xb6, 0xcd, 0xc8, 0x62, 0x15, 0x16, 0xf4, 0x2a, 0xb2, 0xf3, 0xaa, - 0xea, 0x7c, 0x5e, 0xab, 0x2d, 0xc6, 0xf0, 0x3e, 0xcc, 0xc9, 0x6f, 0x22, 0x3e, 0x1f, 0xa4, 0x95, - 0xba, 0xd3, 0x16, 0x60, 0x39, 0xcb, 0xfb, 0xd0, 0x39, 0xf1, 0x03, 0x6f, 0xe8, 0xf6, 0x87, 0xc9, - 0xb9, 0x3b, 0xa0, 0xc3, 0xc4, 0x43, 0xaa, 0xa9, 0x3a, 0x6d, 0x84, 0x6f, 0x0c, 0x93, 0xf3, 0x4d, - 0x06, 0x25, 0x1f, 0x40, 0xfd, 0x84, 0x52, 0x17, 0x17, 0xab, 0x5b, 0x33, 0x38, 0x50, 0xee, 0x90, - 0x53, 0x3b, 0x91, 0x7b, 0xf5, 0x01, 0x74, 0xc2, 0x49, 0x72, 0x1a, 0xfa, 0xc1, 0xa9, 0xcb, 0x64, - 0x9e, 0xeb, 0x0f, 0x90, 0x8a, 0x2a, 0xeb, 0xa5, 0x47, 0x96, 0xd3, 0x96, 0x38, 0x26, 0x7d, 0x76, - 0x06, 0xe4, 0x3d, 0x98, 0x1b, 0x7a, 0x71, 0xe2, 0x9e, 0x85, 0x63, 0x77, 0x3c, 0x39, 0x7e, 0x45, - 0x2f, 0xbb, 0x2d, 0x5c, 0x88, 0x16, 0x03, 0x6f, 0x87, 0xe3, 0x03, 0x04, 0x92, 0xdb, 0x00, 0x38, - 0x4e, 0x3e, 0x08, 0xb8, 0x6b, 0xdd, 0x6f, 0x39, 0x75, 0x06, 0xe1, 0x9d, 0x7e, 0x1f, 0x16, 0x70, - 0x7b, 0xfa, 0x93, 0x38, 0x09, 0x47, 0x2e, 0x93, 0xd7, 0xd1, 0x20, 0xee, 0x36, 0x90, 0xd6, 0xbe, - 0x22, 0x06, 0xab, 0xed, 0xf1, 0xca, 0x26, 0x8d, 0x93, 0x0d, 0xac, 0xec, 0xf0, 0xba, 0xec, 0x50, - 0xbf, 0x74, 0xe6, 0x07, 0x59, 0x38, 0xf9, 0x00, 0x88, 0x37, 0x1c, 0x86, 0x17, 0x6e, 0x4c, 0x87, - 0x27, 0xae, 0x58, 0xc4, 0x6e, 0xfb, 0xae, 0x75, 0xbf, 0xe6, 0x74, 0x10, 0x73, 0x48, 0x87, 0x27, - 0x07, 0x1c, 0x4e, 0x3e, 0x82, 0x16, 0x0e, 0xe4, 0x84, 0x7a, 0xc9, 0x24, 0xa2, 0x71, 0x77, 0xee, - 0x6e, 0xf9, 0x7e, 0x7b, 0x75, 0x5e, 0xad, 0x17, 0x82, 0xd7, 0xfd, 0xc4, 0x69, 0xb2, 0x7a, 0xa2, - 0x1c, 0xf7, 0x36, 0x61, 0xa9, 0x78, 0x48, 0x8c, 0xa8, 0xd8, 0xaa, 0x30, 0x62, 0xac, 0x38, 0xec, - 0x4f, 0xb2, 0x08, 0xd5, 0x73, 0x6f, 0x38, 0xa1, 0x42, 0xae, 0xf3, 0xc2, 0xc7, 0xa5, 0xc7, 0x96, - 0xfd, 0xc7, 0x16, 0x34, 0xf9, 0x2c, 0x85, 0x3e, 0x72, 0x0f, 0x5a, 0x92, 0x1a, 0x68, 0x14, 0x85, - 0x91, 0x10, 0x6f, 0x26, 0x90, 0x3c, 0x80, 0x8e, 0x04, 0x8c, 0x23, 0xea, 0x8f, 0xbc, 0x53, 0xd9, - 0x76, 0x0e, 0x4e, 0x56, 0xd3, 0x16, 0xa3, 0x70, 0x92, 0x50, 0x71, 0xf2, 0x35, 0xc5, 0x04, 0x1d, - 0x06, 0x73, 0xcc, 0x2a, 0x4c, 0xbc, 0x15, 0x90, 0xba, 0x01, 0xb3, 0xff, 0x8e, 0x05, 0x84, 0x0d, - 0xfd, 0x28, 0xe4, 0x4d, 0x08, 0x2a, 0xcd, 0x72, 0x89, 0xf5, 0xd6, 0x5c, 0x52, 0xba, 0x8a, 0x4b, - 0x6c, 0xa8, 0xf2, 0xd1, 0x57, 0x0a, 0x46, 0xcf, 0x51, 0xdf, 0xa9, 0xd4, 0xca, 0x9d, 0x8a, 0xfd, - 0x5f, 0xcb, 0xb0, 0xb8, 0xc1, 0x8f, 0xee, 0xb5, 0x7e, 0x9f, 0x8e, 0x15, 0xff, 0xbc, 0x03, 0x8d, - 0x20, 0x1c, 0x50, 0x49, 0xb5, 0x7c, 0x60, 0xc0, 0x40, 0x1a, 0xc9, 0x9e, 0x79, 0x7e, 0xc0, 0x07, - 0xce, 0xd7, 0xb3, 0x8e, 0x10, 0x1c, 0xf6, 0x7b, 0x30, 0x37, 0xa6, 0xc1, 0x40, 0x67, 0x13, 0xae, - 0x5c, 0xb5, 0x04, 0x58, 0x70, 0xc8, 0x3b, 0xd0, 0x38, 0x99, 0xf0, 0x7a, 0x4c, 0xb8, 0x54, 0x90, - 0x0e, 0x40, 0x80, 0xd6, 0xb8, 0x8c, 0x19, 0x4f, 0xe2, 0x33, 0xc4, 0x56, 0x11, 0x3b, 0xcb, 0xca, - 0x0c, 0x75, 0x1b, 0x60, 0x30, 0x89, 0x13, 0xc1, 0x35, 0x33, 0x88, 0xac, 0x33, 0x08, 0xe7, 0x9a, - 0xaf, 0xc1, 0xc2, 0xc8, 0x7b, 0xed, 0x22, 0xfd, 0xb8, 0x7e, 0xe0, 0x9e, 0x0c, 0xf1, 0xf4, 0x99, - 0xc5, 0x7a, 0x9d, 0x91, 0xf7, 0xfa, 0x7b, 0x0c, 0xb3, 0x13, 0x3c, 0x45, 0x38, 0x13, 0x2d, 0x52, - 0xed, 0x89, 0x68, 0x4c, 0xa3, 0x73, 0x8a, 0xd2, 0xa0, 0xa2, 0x74, 0x1b, 0x87, 0x43, 0xd9, 0x88, - 0x46, 0x6c, 0xde, 0xc9, 0xb0, 0xcf, 0x59, 0xdf, 0x99, 0x1d, 0xf9, 0xc1, 0x76, 0x32, 0xec, 0x93, - 0x5b, 0x00, 0x4c, 0x96, 0x8c, 0x69, 0xe4, 0xbe, 0xba, 0x40, 0x3e, 0xae, 0xa0, 0xec, 0x38, 0xa0, - 0xd1, 0x27, 0x17, 0xe4, 0x26, 0xd4, 0xfb, 0x31, 0x0a, 0x23, 0xef, 0xb2, 0xdb, 0x40, 0x26, 0xaf, - 0xf5, 0x63, 0x26, 0x86, 0xbc, 0x4b, 0xc6, 0x88, 0x6c, 0xb4, 0x1e, 0xee, 0x02, 0x1d, 0x60, 0xf3, - 0x31, 0x4a, 0xd5, 0x16, 0x0e, 0x76, 0x4d, 0x20, 0x58, 0x3f, 0x31, 0xf9, 0x12, 0xb4, 0xe4, 0x60, - 0x4f, 0x86, 0xde, 0x69, 0x8c, 0x62, 0xa5, 0xe5, 0x34, 0x05, 0xf0, 0x29, 0x83, 0xd9, 0x2f, 0xb9, - 0xb2, 0xa5, 0xed, 0xad, 0xe0, 0x1b, 0x76, 0xec, 0x23, 0x04, 0xf7, 0xb5, 0xe6, 0x88, 0x52, 0xd1, - 0xa6, 0x95, 0x0a, 0x36, 0xcd, 0xfe, 0xb9, 0x05, 0x4d, 0xd1, 0x32, 0x6a, 0x28, 0xe4, 0x11, 0x10, - 0xb9, 0x8b, 0xc9, 0x6b, 0x7f, 0xe0, 0x1e, 0x5f, 0x26, 0x34, 0xe6, 0x44, 0xb3, 0x7d, 0xcd, 0x29, - 0xc0, 0x31, 0x39, 0x6a, 0x40, 0xe3, 0x24, 0xe2, 0x34, 0xbd, 0x7d, 0xcd, 0xc9, 0x61, 0x18, 0x8b, - 0x31, 0x1d, 0x68, 0x92, 0xb8, 0x7e, 0x30, 0xa0, 0xaf, 0x91, 0x94, 0x5a, 0x8e, 0x01, 0x5b, 0x6f, - 0x43, 0x53, 0xff, 0xce, 0xfe, 0x31, 0xd4, 0xa4, 0x06, 0x85, 0xda, 0x43, 0x66, 0x5c, 0x8e, 0x06, - 0x21, 0x3d, 0xa8, 0x99, 0xa3, 0x70, 0x6a, 0x9f, 0xa7, 0x6f, 0xfb, 0x5b, 0xd0, 0xd9, 0x65, 0x44, - 0x14, 0x30, 0xa2, 0x15, 0x6a, 0xe1, 0x12, 0xcc, 0x68, 0xcc, 0x53, 0x77, 0x44, 0x89, 0x9d, 0xbf, - 0x67, 0x61, 0x9c, 0x88, 0x7e, 0xf0, 0x6f, 0xfb, 0x4f, 0x2c, 0x20, 0x5b, 0x71, 0xe2, 0x8f, 0xbc, - 0x84, 0x3e, 0xa5, 0x4a, 0x3c, 0xec, 0x43, 0x93, 0xb5, 0x76, 0x14, 0xae, 0x71, 0x25, 0x8d, 0x2b, - 0x17, 0x5f, 0x15, 0xec, 0x9c, 0xff, 0x60, 0x45, 0xaf, 0xcd, 0x45, 0xbe, 0xd1, 0x00, 0xe3, 0xb6, - 0xc4, 0x8b, 0x4e, 0x69, 0x82, 0x1a, 0x9c, 0xd0, 0xff, 0x81, 0x83, 0x36, 0xc2, 0xe0, 0xa4, 0xf7, - 0xdb, 0x30, 0x9f, 0x6b, 0x43, 0x97, 0xd1, 0xf5, 0x02, 0x19, 0x5d, 0xd6, 0x65, 0x74, 0x1f, 0x16, - 0x8c, 0x71, 0x09, 0x8a, 0xeb, 0xc2, 0x2c, 0x63, 0x0c, 0xa6, 0x28, 0x58, 0x5c, 0x51, 0x10, 0x45, - 0xb2, 0x0a, 0x8b, 0x27, 0x94, 0x46, 0x5e, 0x82, 0x45, 0x64, 0x1d, 0xb6, 0x27, 0xa2, 0xe5, 0x42, - 0x9c, 0xfd, 0x67, 0x16, 0xcc, 0x31, 0x69, 0xfa, 0xdc, 0x0b, 0x2e, 0xe5, 0x5a, 0xed, 0x16, 0xae, - 0xd5, 0x7d, 0xed, 0x70, 0xd4, 0x6a, 0x7f, 0xde, 0x85, 0x2a, 0x67, 0x17, 0x8a, 0xdc, 0x85, 0xa6, - 0x31, 0xdc, 0x2a, 0xd7, 0x48, 0x63, 0x2f, 0x39, 0xa0, 0xd1, 0xfa, 0x65, 0x42, 0x7f, 0xf5, 0xa5, - 0x7c, 0x0f, 0x3a, 0xe9, 0xb0, 0xc5, 0x3a, 0x12, 0xa8, 0x30, 0xc2, 0x14, 0x0d, 0xe0, 0xdf, 0xf6, - 0xdf, 0xb7, 0x78, 0xc5, 0x8d, 0xd0, 0x57, 0xda, 0x2a, 0xab, 0xc8, 0x94, 0x5e, 0x59, 0x91, 0xfd, - 0x3d, 0x55, 0xdb, 0xff, 0xd5, 0x27, 0xcb, 0x64, 0x62, 0x4c, 0x83, 0x81, 0xeb, 0x0d, 0x87, 0x28, - 0x88, 0x6b, 0xce, 0x2c, 0x2b, 0xaf, 0x0d, 0x87, 0xf6, 0xfb, 0x30, 0xaf, 0x8d, 0xee, 0x8a, 0x79, - 0xec, 0x01, 0xd9, 0xf5, 0xe3, 0xe4, 0x45, 0x10, 0x8f, 0x35, 0x45, 0xee, 0x26, 0xd4, 0x99, 0xb4, - 0x65, 0x23, 0xe3, 0x9c, 0x5b, 0x75, 0x98, 0xf8, 0x65, 0xe3, 0x8a, 0x11, 0xe9, 0xbd, 0x16, 0xc8, - 0x92, 0x40, 0x7a, 0xaf, 0x11, 0x69, 0x3f, 0x86, 0x05, 0xa3, 0x3d, 0xd1, 0xf5, 0xbb, 0x50, 0x9d, - 0x24, 0xaf, 0x43, 0xa9, 0xaa, 0x37, 0x04, 0x85, 0x30, 0xa3, 0xd0, 0xe1, 0x18, 0xfb, 0x09, 0xcc, - 0xef, 0xd1, 0x0b, 0xc1, 0xc8, 0x72, 0x20, 0xef, 0xbd, 0xd1, 0x60, 0x44, 0xbc, 0xbd, 0x02, 0x44, - 0xff, 0x38, 0x65, 0x00, 0x69, 0x3e, 0x5a, 0x86, 0xf9, 0x68, 0xbf, 0x07, 0xe4, 0xd0, 0x3f, 0x0d, - 0x9e, 0xd3, 0x38, 0xf6, 0x4e, 0x15, 0xeb, 0x77, 0xa0, 0x3c, 0x8a, 0x4f, 0x85, 0xa8, 0x62, 0x7f, - 0xda, 0x5f, 0x87, 0x05, 0xa3, 0x9e, 0x68, 0xf8, 0x16, 0xd4, 0x63, 0xff, 0x34, 0x40, 0x45, 0x4b, - 0x34, 0x9d, 0x02, 0xec, 0xa7, 0xb0, 0xf8, 0x3d, 0x1a, 0xf9, 0x27, 0x97, 0x6f, 0x6a, 0xde, 0x6c, - 0xa7, 0x94, 0x6d, 0x67, 0x0b, 0xae, 0x67, 0xda, 0x11, 0xdd, 0x73, 0xf2, 0x15, 0x3b, 0x59, 0x73, - 0x78, 0x41, 0x93, 0x7d, 0x25, 0x5d, 0xf6, 0xd9, 0x2f, 0x80, 0x6c, 0x84, 0x41, 0x40, 0xfb, 0xc9, - 0x01, 0xa5, 0x51, 0xea, 0xb9, 0x4a, 0x69, 0xb5, 0xb1, 0xba, 0x2c, 0x56, 0x36, 0x2b, 0x50, 0x05, - 0x11, 0x13, 0xa8, 0x8c, 0x69, 0x34, 0xc2, 0x86, 0x6b, 0x0e, 0xfe, 0x6d, 0x5f, 0x87, 0x05, 0xa3, - 0x59, 0x61, 0xeb, 0x7f, 0x08, 0xd7, 0x37, 0xfd, 0xb8, 0x9f, 0xef, 0xb0, 0x0b, 0xb3, 0xe3, 0xc9, - 0xb1, 0x9b, 0x72, 0xa2, 0x2c, 0x32, 0xf3, 0x2f, 0xfb, 0x89, 0x68, 0xec, 0x6f, 0x58, 0x50, 0xd9, - 0x3e, 0xda, 0xdd, 0x60, 0x67, 0x85, 0x1f, 0xf4, 0xc3, 0x11, 0xd3, 0xc2, 0xf8, 0xa4, 0x55, 0x79, - 0x2a, 0x87, 0xdd, 0x82, 0x3a, 0x2a, 0x6f, 0xcc, 0xe2, 0x15, 0x7a, 0x50, 0x0a, 0x60, 0xd6, 0x36, - 0x7d, 0x3d, 0xf6, 0x23, 0x34, 0xa7, 0xa5, 0x91, 0x5c, 0xc1, 0x63, 0x26, 0x8f, 0xb0, 0xff, 0xfd, - 0x2c, 0xcc, 0x8a, 0xc3, 0x97, 0x1f, 0xe4, 0x89, 0x7f, 0x4e, 0xd3, 0x83, 0x9c, 0x95, 0x98, 0x62, - 0x1c, 0xd1, 0x51, 0x98, 0x28, 0xfd, 0x8d, 0x6f, 0x83, 0x09, 0x44, 0x6f, 0x82, 0x50, 0x22, 0xb8, - 0xff, 0xa1, 0xcc, 0x6b, 0x19, 0x40, 0x72, 0x0b, 0x66, 0xa5, 0x32, 0x50, 0x51, 0x86, 0x8e, 0x04, - 0xb1, 0xd5, 0xe8, 0x7b, 0x63, 0xaf, 0xef, 0x27, 0x97, 0x42, 0x2c, 0xa8, 0x32, 0x6b, 0x7f, 0x18, - 0xf6, 0xbd, 0xa1, 0x7b, 0xec, 0x0d, 0xbd, 0xa0, 0x4f, 0xa5, 0xb7, 0xc2, 0x00, 0x32, 0xcb, 0x5d, - 0x0c, 0x4b, 0x56, 0xe3, 0xd6, 0x7d, 0x06, 0xca, 0xce, 0xf0, 0x7e, 0x38, 0x1a, 0xf9, 0xcc, 0xfa, - 0xe0, 0xaa, 0x59, 0xd9, 0xd1, 0x20, 0xdc, 0x37, 0x82, 0xa5, 0x0b, 0xbe, 0x82, 0x75, 0xe9, 0x1b, - 0xd1, 0x80, 0xac, 0x95, 0x8c, 0x86, 0x56, 0x76, 0x34, 0x08, 0xdb, 0x8b, 0x49, 0x10, 0xd3, 0x24, - 0x19, 0xd2, 0x81, 0x1a, 0x50, 0x03, 0xab, 0xe5, 0x11, 0xe4, 0x11, 0x2c, 0x70, 0x1f, 0x44, 0xec, - 0x25, 0x61, 0x7c, 0xe6, 0xc7, 0x6e, 0xcc, 0xcc, 0x27, 0x6e, 0x0b, 0x17, 0xa1, 0xc8, 0x63, 0x58, - 0xce, 0x80, 0x23, 0xda, 0xa7, 0xfe, 0x39, 0x1d, 0xa0, 0x0a, 0x57, 0x76, 0xa6, 0xa1, 0xc9, 0x5d, - 0x68, 0x04, 0x93, 0x91, 0x3b, 0x19, 0x0f, 0x3c, 0xa6, 0xc4, 0xb4, 0x51, 0xb9, 0xd4, 0x41, 0xe4, - 0x43, 0x90, 0x7a, 0x9a, 0xd0, 0x1e, 0xe7, 0x0c, 0x09, 0xc7, 0xa8, 0xd7, 0x31, 0x6b, 0x30, 0xc2, - 0x4c, 0x55, 0xd2, 0x8e, 0xb0, 0x3b, 0x25, 0x00, 0xf9, 0x24, 0xf2, 0xcf, 0xbd, 0x84, 0x76, 0xe7, - 0xb9, 0x50, 0x17, 0x45, 0xf6, 0x9d, 0x1f, 0xf8, 0x89, 0xef, 0x25, 0x61, 0xd4, 0x25, 0x88, 0x4b, - 0x01, 0x6c, 0x11, 0x91, 0x3e, 0xe2, 0xc4, 0x4b, 0x26, 0xb1, 0xd0, 0x50, 0x17, 0x90, 0xb8, 0xf2, - 0x08, 0xf2, 0x11, 0x2c, 0x71, 0x8a, 0x40, 0x94, 0xd0, 0xbd, 0x51, 0x55, 0x58, 0xc4, 0x15, 0x99, - 0x82, 0x65, 0x4b, 0x29, 0x48, 0x24, 0xf7, 0xe1, 0x75, 0xbe, 0x94, 0x53, 0xd0, 0x6c, 0x7c, 0x6c, - 0x04, 0x7e, 0xdf, 0x15, 0x35, 0x18, 0x8b, 0x2c, 0xe1, 0x2c, 0xf2, 0x08, 0x46, 0xe2, 0x43, 0xff, - 0x84, 0x26, 0xfe, 0x88, 0x76, 0x97, 0x39, 0x89, 0xcb, 0x32, 0x63, 0xc0, 0xc9, 0x18, 0x31, 0x5d, - 0xce, 0xf0, 0xbc, 0x84, 0xc4, 0x38, 0x0c, 0x63, 0x2a, 0x3d, 0x4f, 0xdd, 0x1b, 0x82, 0xb5, 0x74, - 0xa0, 0xfd, 0x87, 0x16, 0x3f, 0xa2, 0x04, 0x3b, 0xc7, 0x9a, 0xf1, 0xc5, 0x19, 0xd9, 0x0d, 0x83, - 0xe1, 0xa5, 0xe0, 0x6d, 0xe0, 0xa0, 0xfd, 0x60, 0x78, 0xc9, 0xd4, 0x7f, 0x3f, 0xd0, 0xab, 0x70, - 0x69, 0xd8, 0x94, 0x40, 0xac, 0xf4, 0x0e, 0x34, 0xc6, 0x93, 0xe3, 0xa1, 0xdf, 0xe7, 0x55, 0xca, - 0xbc, 0x15, 0x0e, 0xc2, 0x0a, 0xcc, 0xfa, 0xe4, 0xfb, 0xc9, 0x6b, 0x54, 0xb0, 0x46, 0x43, 0xc0, - 0x58, 0x15, 0x7b, 0x1d, 0x16, 0xcd, 0x01, 0x0a, 0xb1, 0xff, 0x00, 0x6a, 0x42, 0x4a, 0x48, 0x37, - 0x44, 0x5b, 0x73, 0x0e, 0x33, 0x63, 0x49, 0xe1, 0xed, 0x7f, 0x53, 0x81, 0x05, 0x01, 0xdd, 0x60, - 0xd3, 0x3f, 0x9c, 0x8c, 0x46, 0x5e, 0x54, 0x20, 0x7e, 0xac, 0x37, 0x88, 0x9f, 0x52, 0x5e, 0xfc, - 0xdc, 0x31, 0xac, 0x50, 0x2e, 0xbf, 0x34, 0x08, 0xb9, 0x0f, 0x73, 0x6c, 0xc9, 0xb9, 0x51, 0xa0, - 0xfb, 0x27, 0xb3, 0xe0, 0xbc, 0xc8, 0xac, 0x16, 0x89, 0x4c, 0x5d, 0xdc, 0xcd, 0x64, 0xc4, 0x9d, - 0x0d, 0x4d, 0xbe, 0xbd, 0x42, 0x82, 0xcf, 0x0a, 0x93, 0x4c, 0x83, 0xb1, 0xf1, 0x64, 0x85, 0x0b, - 0x97, 0x64, 0x73, 0x45, 0xa2, 0xc5, 0x1f, 0x51, 0x3c, 0x21, 0xb4, 0xda, 0x75, 0x21, 0x5a, 0xf2, - 0x28, 0xf2, 0x14, 0x80, 0xf7, 0x85, 0x6a, 0x0a, 0xa0, 0x9a, 0xf2, 0x9e, 0xb9, 0x2b, 0xfa, 0xfa, - 0xaf, 0xb0, 0xc2, 0x24, 0xa2, 0xa8, 0xba, 0x68, 0x5f, 0xda, 0x7f, 0xcb, 0x82, 0x86, 0x86, 0x23, - 0xd7, 0x61, 0x7e, 0x63, 0x7f, 0xff, 0x60, 0xcb, 0x59, 0x3b, 0xda, 0xf9, 0xde, 0x96, 0xbb, 0xb1, - 0xbb, 0x7f, 0xb8, 0xd5, 0xb9, 0xc6, 0xc0, 0xbb, 0xfb, 0x1b, 0x6b, 0xbb, 0xee, 0xd3, 0x7d, 0x67, - 0x43, 0x82, 0x2d, 0xb2, 0x04, 0xc4, 0xd9, 0x7a, 0xbe, 0x7f, 0xb4, 0x65, 0xc0, 0x4b, 0xa4, 0x03, - 0xcd, 0x75, 0x67, 0x6b, 0x6d, 0x63, 0x5b, 0x40, 0xca, 0x64, 0x11, 0x3a, 0x4f, 0x5f, 0xec, 0x6d, - 0xee, 0xec, 0x3d, 0x73, 0x37, 0xd6, 0xf6, 0x36, 0xb6, 0x76, 0xb7, 0x36, 0x3b, 0x15, 0xd2, 0x82, - 0xfa, 0xda, 0xfa, 0xda, 0xde, 0xe6, 0xfe, 0xde, 0xd6, 0x66, 0xa7, 0x6a, 0xff, 0x77, 0x0b, 0xae, - 0xe3, 0xa8, 0x07, 0x59, 0x26, 0xb9, 0x0b, 0x8d, 0x7e, 0x18, 0x8e, 0x99, 0x79, 0x90, 0x1e, 0x80, - 0x3a, 0x88, 0x31, 0x00, 0x17, 0x1d, 0x27, 0x61, 0xd4, 0xa7, 0x82, 0x47, 0x00, 0x41, 0x4f, 0x19, - 0x84, 0x31, 0x80, 0xd8, 0x5e, 0x5e, 0x83, 0xb3, 0x48, 0x83, 0xc3, 0x78, 0x95, 0x25, 0x98, 0x39, - 0x8e, 0xa8, 0xd7, 0x3f, 0x13, 0xdc, 0x21, 0x4a, 0xe4, 0x2b, 0xa9, 0xfd, 0xda, 0x67, 0xab, 0x3f, - 0xa4, 0x03, 0xa4, 0x98, 0x9a, 0x33, 0x27, 0xe0, 0x1b, 0x02, 0xcc, 0x64, 0xa5, 0x77, 0xec, 0x05, - 0x83, 0x30, 0xa0, 0x03, 0xa1, 0x1c, 0xa7, 0x00, 0xfb, 0x00, 0x96, 0xb2, 0xf3, 0x13, 0x3c, 0xf6, - 0x91, 0xc6, 0x63, 0x5c, 0x57, 0xed, 0x4d, 0xdf, 0x4d, 0x8d, 0xdf, 0xfe, 0xac, 0x0c, 0x15, 0xa6, - 0xba, 0x4c, 0x57, 0x73, 0x74, 0x6d, 0xb4, 0x9c, 0x0b, 0x66, 0xa0, 0x49, 0xcc, 0x0f, 0x32, 0xe1, - 0x8e, 0x49, 0x21, 0x29, 0x3e, 0xa2, 0xfd, 0x73, 0xe1, 0x90, 0xd1, 0x20, 0x8c, 0x41, 0x98, 0xa9, - 0x80, 0x5f, 0x0b, 0x06, 0x91, 0x65, 0x89, 0xc3, 0x2f, 0x67, 0x53, 0x1c, 0x7e, 0xd7, 0x85, 0x59, - 0x3f, 0x38, 0x0e, 0x27, 0xc1, 0x00, 0x19, 0xa2, 0xe6, 0xc8, 0x22, 0x86, 0x4f, 0x90, 0x51, 0x99, - 0x94, 0xe5, 0xe4, 0x9f, 0x02, 0xc8, 0x2a, 0xd4, 0xe3, 0xcb, 0xa0, 0xaf, 0xd3, 0xfc, 0xa2, 0x58, - 0x25, 0xb6, 0x06, 0x2b, 0x87, 0x97, 0x41, 0x1f, 0x29, 0x3c, 0xad, 0x46, 0xbe, 0x09, 0x35, 0xe5, - 0xc0, 0xe4, 0xc2, 0xeb, 0x86, 0xfe, 0x89, 0xf4, 0x5a, 0x72, 0xbb, 0x50, 0x55, 0xed, 0x7d, 0x02, - 0x2d, 0x03, 0xa5, 0x1b, 0x73, 0x2d, 0x6e, 0xcc, 0xdd, 0xd3, 0x8d, 0xb9, 0x54, 0x26, 0x8a, 0xcf, - 0x74, 0xe3, 0xee, 0xb7, 0xa1, 0x26, 0x87, 0xc6, 0x58, 0xe3, 0xc5, 0xde, 0x27, 0x7b, 0xfb, 0x2f, - 0xf7, 0xdc, 0xc3, 0xef, 0xef, 0x6d, 0x74, 0xae, 0x91, 0x39, 0x68, 0xac, 0x6d, 0x20, 0xb7, 0x21, - 0xc0, 0x62, 0x55, 0x0e, 0xd6, 0x0e, 0x0f, 0x15, 0xa4, 0x64, 0x13, 0xe8, 0x30, 0xc9, 0xcc, 0x46, - 0xac, 0x42, 0x14, 0x1f, 0xc1, 0xbc, 0x06, 0x4b, 0xed, 0x9d, 0x31, 0x03, 0x64, 0xec, 0x1d, 0x54, - 0x6e, 0x39, 0xc6, 0x5e, 0x86, 0xeb, 0xac, 0xb8, 0x75, 0x4e, 0x83, 0xe4, 0x70, 0x72, 0xcc, 0x23, - 0x53, 0x7e, 0x18, 0xd8, 0x7f, 0xdd, 0x82, 0xba, 0xc2, 0x5c, 0x41, 0x4f, 0x32, 0x98, 0x56, 0xc2, - 0x0d, 0xe8, 0x69, 0x5d, 0xe0, 0x97, 0x2b, 0xf8, 0xaf, 0x61, 0x23, 0xd5, 0x15, 0x88, 0x4d, 0xf6, - 0x60, 0x6b, 0xcb, 0x71, 0xf7, 0xf7, 0x76, 0x77, 0xf6, 0x98, 0x64, 0x61, 0x93, 0x45, 0xc0, 0xd3, - 0xa7, 0x08, 0xb1, 0xec, 0x0e, 0xb4, 0x9f, 0xd1, 0x64, 0x27, 0x38, 0x09, 0xe5, 0x54, 0xff, 0x5f, - 0x15, 0xe6, 0x14, 0x28, 0xb5, 0xb1, 0xce, 0x69, 0x14, 0xfb, 0x61, 0x80, 0xda, 0x51, 0xdd, 0x91, - 0x45, 0x26, 0x76, 0xfd, 0x01, 0x0d, 0x12, 0x3f, 0xb9, 0x74, 0x0d, 0xa7, 0x4c, 0x16, 0xcc, 0xec, - 0x19, 0x6f, 0xe8, 0x7b, 0x32, 0xc8, 0xc7, 0x0b, 0x0c, 0xda, 0x0f, 0x87, 0x61, 0x84, 0x6a, 0x50, - 0xdd, 0xe1, 0x05, 0xb2, 0x0a, 0x8b, 0x4c, 0xfd, 0xd2, 0x5d, 0x66, 0xc8, 0xac, 0xdc, 0x43, 0x54, - 0x88, 0x63, 0x62, 0x9d, 0xc1, 0xc5, 0xd9, 0xad, 0x3e, 0xe1, 0xda, 0x7e, 0x11, 0x8a, 0x7c, 0x03, - 0xae, 0x33, 0xb0, 0x3a, 0xef, 0xd5, 0x37, 0x73, 0xf8, 0x4d, 0x31, 0x92, 0x71, 0x0d, 0xef, 0x9f, - 0xed, 0x7c, 0x95, 0x2b, 0x76, 0x0a, 0x90, 0x8b, 0xc8, 0xcd, 0xf0, 0xa3, 0x2a, 0x1b, 0x91, 0xd3, - 0xa2, 0x7a, 0xb5, 0x5c, 0x54, 0xef, 0x1b, 0x70, 0xfd, 0x98, 0xc6, 0x89, 0x7b, 0x46, 0xbd, 0x01, - 0x8d, 0x90, 0x1b, 0x79, 0xf0, 0x8e, 0xeb, 0xb1, 0xc5, 0x48, 0x3c, 0x00, 0x2f, 0x83, 0x3e, 0x1d, - 0xb8, 0x49, 0xe8, 0xe2, 0x41, 0x8d, 0x3c, 0x5d, 0x73, 0xb2, 0x60, 0xb3, 0xe6, 0x69, 0xe4, 0x8d, - 0xcf, 0x84, 0xa2, 0x99, 0x05, 0x33, 0x15, 0x21, 0xa1, 0x71, 0x12, 0x50, 0x1e, 0x3a, 0xa9, 0xa1, - 0x5b, 0x5c, 0x82, 0xc8, 0x3d, 0x98, 0xc1, 0x06, 0xe3, 0x6e, 0x07, 0x19, 0xa0, 0x99, 0x0a, 0x51, - 0x3f, 0x70, 0x04, 0x8e, 0x99, 0x95, 0x93, 0xc8, 0x8f, 0xbb, 0x4d, 0x8c, 0x1a, 0xe2, 0xdf, 0xe4, - 0xdb, 0x9a, 0x9c, 0x58, 0xc0, 0x6f, 0xef, 0x89, 0x6f, 0x33, 0x94, 0xf7, 0x85, 0x88, 0x8c, 0xef, - 0x54, 0x6a, 0x8d, 0x4e, 0xd3, 0xfe, 0x0d, 0xa8, 0xe2, 0xc8, 0x91, 0x26, 0x71, 0xfd, 0x2c, 0x41, - 0x93, 0x08, 0xed, 0xc2, 0x6c, 0x40, 0x93, 0x8b, 0x30, 0x7a, 0x25, 0xc3, 0xd4, 0xa2, 0x68, 0xff, - 0x04, 0x6d, 0x6f, 0x15, 0xb6, 0x7d, 0x81, 0x46, 0x03, 0xb9, 0x09, 0x75, 0xbe, 0xa7, 0xf1, 0x99, - 0x27, 0xdc, 0x01, 0x35, 0x04, 0x1c, 0x9e, 0x79, 0xec, 0x7c, 0x34, 0xc8, 0x84, 0x7b, 0x58, 0x1a, - 0x08, 0xdb, 0xe6, 0x54, 0x72, 0x0f, 0xda, 0x32, 0x20, 0x1c, 0xbb, 0x43, 0x7a, 0x92, 0x48, 0xff, - 0x68, 0x30, 0x19, 0xa1, 0x1b, 0x66, 0x97, 0x9e, 0x24, 0xf6, 0x1e, 0xcc, 0x8b, 0x33, 0x6b, 0x7f, - 0x4c, 0x65, 0xd7, 0xbf, 0x59, 0xa4, 0xff, 0x35, 0x56, 0x17, 0xcc, 0x43, 0x8e, 0x87, 0xc0, 0xcd, - 0x9a, 0xb6, 0x03, 0x44, 0x3f, 0x03, 0x45, 0x83, 0x42, 0x01, 0x93, 0x1e, 0x60, 0x31, 0x1d, 0x03, - 0xc6, 0xd6, 0x27, 0x9e, 0xf4, 0xfb, 0x32, 0x8c, 0x5f, 0x73, 0x64, 0xd1, 0xfe, 0xcf, 0x16, 0x2c, - 0x60, 0x6b, 0x52, 0x83, 0x15, 0x7a, 0xc6, 0xe3, 0xcf, 0x31, 0x4c, 0xe9, 0x7f, 0xe7, 0x5e, 0xe7, - 0x45, 0xa8, 0xea, 0x9a, 0x07, 0x2f, 0x7c, 0x7e, 0x6f, 0x5b, 0x25, 0xe7, 0x6d, 0x7b, 0x00, 0x9d, - 0x01, 0x1d, 0xfa, 0x98, 0xca, 0x21, 0xcf, 0x71, 0xae, 0xae, 0xe6, 0xe0, 0xf6, 0xdf, 0xb5, 0x60, - 0x9e, 0x2b, 0x0a, 0x68, 0x73, 0x89, 0xa5, 0xfa, 0x4b, 0xd2, 0x3e, 0x11, 0x02, 0x4a, 0x4c, 0x2a, - 0x3d, 0x3a, 0x11, 0xca, 0x2b, 0x6f, 0x5f, 0x73, 0xcc, 0xca, 0xe4, 0x09, 0x6a, 0xdd, 0x81, 0x8b, - 0xd0, 0x82, 0xe4, 0x10, 0x73, 0x5f, 0xb6, 0xaf, 0x39, 0x5a, 0xf5, 0xf5, 0x1a, 0x33, 0x99, 0x18, - 0xdc, 0x7e, 0x06, 0x2d, 0xa3, 0x23, 0xc3, 0x2b, 0xd8, 0xe4, 0x5e, 0xc1, 0x9c, 0xfb, 0xbd, 0x54, - 0xe0, 0x7e, 0xff, 0xfd, 0x0a, 0x10, 0x46, 0x58, 0x99, 0x9d, 0xbb, 0x6b, 0xc6, 0xb0, 0x64, 0x9e, - 0x48, 0x0a, 0x22, 0xab, 0x40, 0xb4, 0xa2, 0x8c, 0xad, 0x95, 0x55, 0x6c, 0xad, 0x00, 0xcb, 0xa4, - 0xbe, 0xd0, 0x2a, 0x55, 0xdc, 0x0a, 0x3d, 0x3e, 0x7c, 0x9b, 0x0a, 0x71, 0x4c, 0xf3, 0xc1, 0x20, - 0x16, 0xb3, 0x4d, 0x85, 0x97, 0x44, 0x96, 0xb3, 0xf4, 0x30, 0xf3, 0x46, 0x7a, 0x98, 0xcd, 0xd1, - 0x83, 0x66, 0xa7, 0xd7, 0x4c, 0x3b, 0xfd, 0x1e, 0xb4, 0x64, 0xac, 0x8a, 0x87, 0xe9, 0x85, 0x53, - 0xc4, 0x00, 0x32, 0x7a, 0x92, 0xa6, 0xb2, 0x72, 0x06, 0xf0, 0x20, 0x74, 0x0e, 0xce, 0x0e, 0x96, - 0xd4, 0x1f, 0xdb, 0xc0, 0xc1, 0xa6, 0x00, 0xb4, 0xac, 0x19, 0x95, 0xb8, 0x93, 0x40, 0xe4, 0x88, - 0xd0, 0x01, 0xba, 0x43, 0x98, 0x65, 0x9d, 0x45, 0xe4, 0xad, 0xe4, 0x56, 0x81, 0x95, 0x4c, 0x3e, - 0x4a, 0x03, 0x3b, 0xf1, 0x99, 0x3f, 0xc2, 0xb3, 0x3d, 0x4d, 0xb1, 0x78, 0xca, 0x51, 0x87, 0x67, - 0xfe, 0xc8, 0x31, 0xea, 0xd9, 0xbf, 0xb0, 0xa0, 0xc3, 0xa8, 0xc2, 0x20, 0xfc, 0x8f, 0x01, 0x79, - 0xf4, 0x2d, 0xe9, 0xde, 0xa8, 0x4b, 0x1e, 0x43, 0x1d, 0xcb, 0xe1, 0x98, 0x06, 0x82, 0xea, 0xbb, - 0x26, 0xd5, 0xa7, 0xd2, 0x6d, 0xfb, 0x9a, 0x93, 0x56, 0x66, 0x67, 0x59, 0x36, 0xb0, 0xc6, 0xa3, - 0xc4, 0x59, 0xb0, 0xc6, 0x1d, 0xdb, 0x00, 0x9f, 0xd0, 0xcb, 0xdd, 0xb0, 0x8f, 0x2e, 0x95, 0xdb, - 0x00, 0x8c, 0x06, 0x4f, 0xbc, 0x91, 0x2f, 0x3c, 0x02, 0x55, 0xa7, 0xfe, 0x8a, 0x5e, 0x3e, 0x45, - 0x00, 0x13, 0xe3, 0x0c, 0x9d, 0xb2, 0x48, 0xd5, 0xa9, 0xbd, 0xa2, 0x97, 0x3b, 0xc8, 0x1e, 0x2e, - 0xb4, 0x3e, 0xa1, 0x97, 0x9b, 0x94, 0xeb, 0x75, 0x61, 0x44, 0x6c, 0x68, 0x45, 0xde, 0x05, 0xd3, - 0xdc, 0x8c, 0x88, 0x58, 0x23, 0xf2, 0x2e, 0x3e, 0xa1, 0x97, 0xeb, 0x18, 0x12, 0x7b, 0x00, 0xb3, - 0x0c, 0x3f, 0x0c, 0xfb, 0xe2, 0x64, 0x92, 0x41, 0xfe, 0x74, 0x50, 0xce, 0xcc, 0x2b, 0xfc, 0xdb, - 0xfe, 0x8f, 0x16, 0xb4, 0xd8, 0x0a, 0xa0, 0xd8, 0x63, 0x3b, 0x21, 0x73, 0x45, 0xac, 0x34, 0x57, - 0x64, 0x55, 0xc8, 0x0c, 0x2e, 0x43, 0x4b, 0xd3, 0x65, 0x28, 0x2e, 0x1b, 0x17, 0xa0, 0x1f, 0x42, - 0x9d, 0xb3, 0x13, 0x63, 0xdf, 0xb2, 0xb1, 0x53, 0xc6, 0x84, 0x9c, 0x1a, 0x56, 0xfb, 0x84, 0x87, - 0xa5, 0x35, 0x9f, 0x0e, 0x5f, 0xe4, 0x3a, 0x87, 0x30, 0x74, 0x41, 0x84, 0xb3, 0x5a, 0x14, 0xe1, - 0x7c, 0x01, 0x0d, 0x8d, 0xb0, 0xc8, 0xb7, 0x78, 0x6c, 0x98, 0x0f, 0x9e, 0x53, 0xa1, 0x49, 0x38, - 0xc6, 0xec, 0x51, 0x60, 0xea, 0x80, 0xf5, 0x19, 0xa8, 0x20, 0x49, 0x3e, 0x81, 0x79, 0xad, 0x59, - 0x6e, 0x21, 0x16, 0x8d, 0xc9, 0x2a, 0x1a, 0xd3, 0x1f, 0x58, 0xb0, 0x28, 0xbe, 0xc6, 0xbc, 0x22, - 0x9f, 0x1d, 0xe3, 0xcf, 0xe3, 0x53, 0x76, 0x90, 0xb2, 0xd6, 0xdd, 0x88, 0x9e, 0xfa, 0x71, 0x42, - 0xa5, 0x23, 0xbd, 0x80, 0x43, 0x18, 0x49, 0xb3, 0xaa, 0x8e, 0xa8, 0x49, 0x9e, 0x40, 0x03, 0x3f, - 0xe5, 0x36, 0xac, 0xd8, 0x96, 0x6e, 0xfe, 0x43, 0x3e, 0x54, 0x26, 0xc9, 0x63, 0x55, 0x5a, 0xaf, - 0xc3, 0x6c, 0x12, 0xf9, 0xa7, 0xa7, 0x34, 0xb2, 0x97, 0xd4, 0xd0, 0x18, 0xb7, 0xd1, 0xc3, 0x84, - 0x8e, 0x99, 0x72, 0xc4, 0x28, 0xa3, 0x21, 0x98, 0xea, 0x97, 0x76, 0x9e, 0xf7, 0xb4, 0x0c, 0x39, - 0x6e, 0xad, 0xa6, 0x09, 0x71, 0xf7, 0x61, 0x6e, 0xc4, 0x14, 0x25, 0xa6, 0xc1, 0x1b, 0x8e, 0xf3, - 0x2c, 0x98, 0x29, 0xde, 0xa8, 0xb7, 0xc4, 0x6e, 0xe2, 0x0f, 0x5d, 0x89, 0x15, 0xb9, 0x68, 0x45, - 0x28, 0x76, 0x7c, 0xc7, 0x89, 0x77, 0x4a, 0x85, 0x76, 0xcc, 0x0b, 0x76, 0x17, 0x96, 0x0e, 0xd2, - 0x6d, 0xd1, 0x1c, 0x12, 0xf6, 0x3f, 0x6f, 0xc1, 0x72, 0x0e, 0xa5, 0x32, 0x67, 0x85, 0x37, 0x78, - 0xe8, 0x8f, 0x8e, 0x43, 0xe5, 0xcd, 0xb1, 0x74, 0x47, 0xb1, 0x81, 0x22, 0xa7, 0x70, 0x5d, 0x52, - 0x05, 0x13, 0x21, 0xa9, 0xda, 0x5f, 0x42, 0x4d, 0xf4, 0x43, 0x53, 0x62, 0x65, 0x3b, 0x94, 0x70, - 0xfd, 0x54, 0x2c, 0x6e, 0x8f, 0x9c, 0x41, 0x57, 0x91, 0x9f, 0xd0, 0x94, 0x34, 0x4b, 0x86, 0xf5, - 0xf5, 0xc1, 0x1b, 0xfa, 0x32, 0xfc, 0x17, 0xce, 0xd4, 0xd6, 0xc8, 0x25, 0xdc, 0x91, 0x38, 0x54, - 0x85, 0xf2, 0xfd, 0x55, 0xde, 0x6a, 0x6e, 0xe8, 0x99, 0x31, 0x3b, 0x7d, 0x43, 0xc3, 0xe4, 0xc7, - 0xb0, 0x74, 0xe1, 0xf9, 0x89, 0x1c, 0x96, 0x66, 0x45, 0x55, 0xb1, 0xcb, 0xd5, 0x37, 0x74, 0xf9, - 0x92, 0x7f, 0x6c, 0xe8, 0x87, 0x53, 0x5a, 0xec, 0xfd, 0xa2, 0x04, 0x6d, 0xb3, 0x1d, 0x46, 0xa6, - 0x42, 0x2a, 0x49, 0x85, 0x42, 0xda, 0x9f, 0x19, 0x70, 0xde, 0x29, 0x5a, 0x2a, 0x72, 0x8a, 0xea, - 0x6e, 0xc8, 0xf2, 0x9b, 0xa2, 0x2e, 0x95, 0xb7, 0x8b, 0xba, 0x54, 0x0b, 0xa3, 0x2e, 0xd3, 0x9d, - 0xf3, 0x33, 0xbf, 0xac, 0x73, 0x7e, 0xf6, 0x4a, 0xe7, 0x7c, 0xef, 0xff, 0x5a, 0x40, 0xf2, 0xd4, - 0x4b, 0x9e, 0x71, 0x3f, 0x70, 0x40, 0x87, 0x42, 0xbc, 0x7d, 0xed, 0xed, 0x38, 0x40, 0xee, 0x96, - 0xfc, 0x9a, 0xb1, 0xa2, 0x9e, 0xbe, 0xaa, 0xdb, 0x36, 0x2d, 0xa7, 0x08, 0x95, 0x89, 0x3c, 0x55, - 0xde, 0x1c, 0x79, 0xaa, 0xbe, 0x39, 0xf2, 0x34, 0x93, 0x8d, 0x3c, 0xf5, 0xfe, 0x9a, 0x05, 0x0b, - 0x05, 0x64, 0xf6, 0xeb, 0x9b, 0x38, 0x23, 0x0c, 0x43, 0xfa, 0x94, 0x04, 0x61, 0xe8, 0xc0, 0xde, - 0x5f, 0x86, 0x96, 0xc1, 0x5a, 0xbf, 0xbe, 0xfe, 0xb3, 0xe6, 0x19, 0xa7, 0x6c, 0x03, 0xd6, 0xfb, - 0x5f, 0x25, 0x20, 0x79, 0xf6, 0xfe, 0x42, 0xc7, 0x90, 0x5f, 0xa7, 0x72, 0xc1, 0x3a, 0xfd, 0x85, - 0x9e, 0x3c, 0x1f, 0xc0, 0xbc, 0xc8, 0xc9, 0xd7, 0x3c, 0xff, 0x9c, 0x62, 0xf2, 0x08, 0x66, 0xa0, - 0x9a, 0x61, 0xbf, 0x9a, 0x91, 0x83, 0xac, 0x1d, 0xbf, 0x99, 0xe8, 0x9f, 0xdd, 0x83, 0xae, 0x58, - 0xa1, 0xbc, 0xeb, 0xef, 0x5f, 0x96, 0x95, 0x8d, 0x8d, 0x48, 0xa1, 0x3f, 0x7f, 0x03, 0x9a, 0xfa, - 0xf1, 0x21, 0xb6, 0x23, 0x13, 0xfc, 0x61, 0x6a, 0x86, 0x5e, 0x8b, 0x6c, 0x42, 0x1b, 0x85, 0xe4, - 0x40, 0x7d, 0xc7, 0x35, 0x8d, 0x2b, 0x1c, 0xda, 0xdb, 0xd7, 0x9c, 0xcc, 0x37, 0xe4, 0xb7, 0xa0, - 0x6d, 0xba, 0xb9, 0x84, 0x4e, 0x58, 0xa4, 0x46, 0xb2, 0xcf, 0xcd, 0xca, 0x64, 0x0d, 0x3a, 0x59, - 0x3f, 0x99, 0x48, 0x90, 0x9c, 0xd2, 0x40, 0xae, 0x3a, 0x79, 0x2c, 0xfc, 0x9c, 0x55, 0xf4, 0x73, - 0xde, 0x33, 0x3f, 0xd3, 0x96, 0x69, 0x85, 0xff, 0xa7, 0x79, 0x3c, 0x7f, 0x17, 0x20, 0x85, 0x91, - 0x0e, 0x34, 0xf7, 0x0f, 0xb6, 0xf6, 0xdc, 0x8d, 0xed, 0xb5, 0xbd, 0xbd, 0xad, 0xdd, 0xce, 0x35, - 0x42, 0xa0, 0x8d, 0x71, 0x91, 0x4d, 0x05, 0xb3, 0x18, 0x4c, 0x78, 0x81, 0x25, 0xac, 0x44, 0x16, - 0xa1, 0xb3, 0xb3, 0x97, 0x81, 0x96, 0x99, 0x26, 0x26, 0x86, 0xc8, 0x34, 0x31, 0x7e, 0xe7, 0x62, - 0x9d, 0x93, 0x87, 0xd4, 0x4e, 0xfe, 0x81, 0x05, 0xd7, 0x33, 0x88, 0x34, 0x8b, 0x96, 0x2b, 0x20, - 0xa6, 0x56, 0x62, 0x02, 0x31, 0xa6, 0x2b, 0x0d, 0xb7, 0x8c, 0x04, 0xc9, 0x23, 0x18, 0xcd, 0x6b, - 0x86, 0x5e, 0x86, 0x93, 0x8a, 0x50, 0xf6, 0xb2, 0x4a, 0x56, 0xcc, 0x0c, 0xfc, 0x84, 0xdf, 0xe5, - 0xd0, 0x11, 0xa9, 0xbf, 0xd7, 0x1c, 0xb2, 0x2c, 0x32, 0x1b, 0xdd, 0x50, 0x76, 0xcc, 0xf1, 0x16, - 0xe2, 0xec, 0x7f, 0x36, 0x03, 0xe4, 0xbb, 0x13, 0x1a, 0x5d, 0x62, 0x9a, 0xac, 0x0a, 0x33, 0x2d, - 0x67, 0x9d, 0xde, 0x33, 0xe3, 0xc9, 0x31, 0x33, 0x25, 0x84, 0x89, 0x53, 0x7a, 0xab, 0x74, 0xf8, - 0xa2, 0x74, 0xf4, 0xca, 0x9b, 0xd3, 0xd1, 0xab, 0x6f, 0x4a, 0x47, 0xff, 0x12, 0xb4, 0xfc, 0xd3, - 0x20, 0x64, 0xe2, 0x80, 0xa9, 0x10, 0x71, 0x77, 0xe6, 0x6e, 0xf9, 0x7e, 0xd3, 0x69, 0x0a, 0xe0, - 0x1e, 0x83, 0x91, 0x27, 0x69, 0x25, 0x3a, 0x38, 0xc5, 0xeb, 0x13, 0xba, 0x80, 0xd8, 0x1a, 0x9c, - 0x52, 0x61, 0xd1, 0xa1, 0xd3, 0x43, 0x7e, 0xcc, 0xe0, 0x31, 0xb9, 0x07, 0xed, 0x38, 0x9c, 0x30, - 0xa5, 0x4a, 0x2e, 0x03, 0x77, 0x05, 0x37, 0x39, 0xf4, 0x80, 0x2f, 0xc6, 0x0a, 0x2c, 0x4c, 0x62, - 0xea, 0x8e, 0xfc, 0x38, 0x66, 0x07, 0x67, 0x3f, 0x0c, 0x92, 0x28, 0x1c, 0x0a, 0xd7, 0xee, 0xfc, - 0x24, 0xa6, 0xcf, 0x39, 0x66, 0x83, 0x23, 0xc8, 0x37, 0xd2, 0x21, 0x8d, 0x3d, 0x3f, 0x8a, 0xbb, - 0x80, 0x43, 0x92, 0x33, 0x65, 0xe3, 0x3e, 0xf0, 0xfc, 0x48, 0x8d, 0x85, 0x15, 0xe2, 0x4c, 0x9a, - 0x7c, 0x23, 0x9b, 0x26, 0xff, 0xa3, 0xe2, 0x34, 0xf9, 0x16, 0x36, 0xfd, 0x48, 0x34, 0x9d, 0xdf, - 0xe2, 0xcf, 0x95, 0x2d, 0x9f, 0xcf, 0xfe, 0x6f, 0x7f, 0x9e, 0xec, 0xff, 0xb9, 0xa2, 0xec, 0xff, - 0x0f, 0xa1, 0x81, 0x39, 0xd9, 0xee, 0x99, 0x1f, 0x24, 0xd2, 0x4d, 0xdd, 0xd1, 0x93, 0xb6, 0xb7, - 0x99, 0x61, 0x0c, 0x91, 0xfc, 0x33, 0xce, 0x27, 0xe2, 0xcf, 0x7f, 0x81, 0x89, 0xf8, 0x22, 0x77, - 0x7c, 0x05, 0x6a, 0x72, 0x9f, 0x08, 0x81, 0xca, 0x49, 0x14, 0x8e, 0xa4, 0xe7, 0x8e, 0xfd, 0x4d, - 0xda, 0x50, 0x4a, 0x42, 0xf1, 0x71, 0x29, 0x09, 0xed, 0xdf, 0x83, 0x86, 0x46, 0x6a, 0xe4, 0x5d, - 0xee, 0x10, 0x60, 0x4a, 0xad, 0xb0, 0x78, 0xf9, 0x2a, 0xd6, 0x05, 0x74, 0x67, 0x40, 0xbe, 0x0a, - 0xf3, 0x03, 0x3f, 0xa2, 0x78, 0x65, 0xc6, 0x8d, 0xe8, 0x39, 0x8d, 0x62, 0xe9, 0x4c, 0xed, 0x28, - 0x84, 0xc3, 0xe1, 0xb6, 0x0b, 0x0b, 0xc6, 0xde, 0x2a, 0xe9, 0x36, 0x83, 0xeb, 0x26, 0xe3, 0x5f, - 0x66, 0x32, 0xbc, 0xc0, 0x31, 0xbd, 0x40, 0xf8, 0x81, 0xdd, 0x71, 0x14, 0x1e, 0x63, 0x27, 0x96, - 0x63, 0xc0, 0xec, 0xff, 0x59, 0x86, 0xf2, 0x76, 0x38, 0xd6, 0x33, 0x12, 0xac, 0x7c, 0x46, 0x82, - 0x50, 0xe0, 0x5d, 0xa5, 0x9f, 0x0b, 0x2d, 0xcb, 0x00, 0x92, 0x07, 0xd0, 0x66, 0xa2, 0x22, 0x09, - 0x99, 0xc1, 0x72, 0xe1, 0x45, 0x3c, 0x3b, 0xbe, 0x8c, 0xfc, 0x97, 0xc1, 0x90, 0x45, 0x28, 0x2b, - 0xbd, 0x13, 0x2b, 0xb0, 0x22, 0xb3, 0x96, 0x31, 0x37, 0xec, 0x52, 0x44, 0x77, 0x44, 0x89, 0x49, - 0x5e, 0xf3, 0x7b, 0x2e, 0x8f, 0xb8, 0xf6, 0x50, 0x84, 0x62, 0xc6, 0x04, 0x93, 0x38, 0xa3, 0x54, - 0x37, 0x57, 0x65, 0x3d, 0xe4, 0x57, 0x33, 0x43, 0x7e, 0x77, 0xa1, 0x91, 0x0c, 0xcf, 0xdd, 0xb1, - 0x77, 0x39, 0x0c, 0xbd, 0x81, 0xe0, 0x74, 0x1d, 0x44, 0x1e, 0x01, 0x8c, 0xc6, 0x63, 0xc1, 0x86, - 0xe8, 0x4f, 0x4c, 0xa9, 0xfa, 0xf9, 0xc1, 0x01, 0xa7, 0x3e, 0x47, 0xab, 0x43, 0xb6, 0xa0, 0x5d, - 0x78, 0xc5, 0xe5, 0xb6, 0xcc, 0x60, 0x0a, 0xc7, 0x2b, 0x05, 0x8c, 0x9a, 0xf9, 0xa8, 0xf7, 0x6d, - 0x20, 0xbf, 0xe2, 0x4d, 0x93, 0x97, 0x50, 0x57, 0x23, 0xd4, 0xef, 0x77, 0x60, 0x9a, 0x62, 0xc3, - 0xbc, 0xdf, 0x81, 0x59, 0x89, 0xef, 0x41, 0x9b, 0x1f, 0x97, 0xea, 0x00, 0xe0, 0xa9, 0x65, 0x19, - 0xa8, 0xfd, 0xe7, 0x16, 0x54, 0x91, 0xf2, 0x98, 0xfe, 0xc8, 0x71, 0x2a, 0x95, 0x43, 0x44, 0x85, - 0xb2, 0x60, 0x62, 0x1b, 0x57, 0xdf, 0x4a, 0x8a, 0x0c, 0xf4, 0xeb, 0x6f, 0x77, 0xa1, 0xae, 0x7a, - 0xd2, 0x48, 0x29, 0x05, 0x92, 0x3b, 0x50, 0x39, 0x0b, 0xc7, 0xd2, 0xc4, 0x86, 0x74, 0x45, 0x1d, - 0x84, 0xa7, 0xe3, 0x61, 0xed, 0xf1, 0x29, 0x70, 0x33, 0x26, 0x0b, 0x2e, 0x98, 0xeb, 0x4c, 0xe1, - 0x5c, 0x5f, 0xc0, 0x1c, 0x93, 0x0f, 0x5a, 0xd4, 0x76, 0xfa, 0x61, 0xfa, 0x15, 0xa6, 0x9b, 0xf5, - 0x87, 0x93, 0x01, 0xd5, 0x1d, 0x1d, 0x18, 0xed, 0x13, 0x70, 0xa9, 0xe2, 0xdb, 0xff, 0xc2, 0xe2, - 0x72, 0x87, 0xb5, 0x4b, 0xee, 0x43, 0x85, 0x9d, 0x7b, 0x19, 0x6f, 0x9c, 0x4a, 0x1d, 0x65, 0xf5, - 0x1c, 0xac, 0xc1, 0x76, 0x11, 0x03, 0x55, 0x7a, 0xeb, 0x3c, 0x4c, 0x95, 0x7a, 0x09, 0xd4, 0xcc, - 0x32, 0xc6, 0x75, 0x06, 0x4a, 0x56, 0xb4, 0xcc, 0x8c, 0x8a, 0x71, 0x96, 0x4a, 0x55, 0x70, 0x70, - 0x4a, 0xb5, 0x8c, 0x8c, 0x7f, 0x55, 0x82, 0x96, 0x31, 0x26, 0xc6, 0x3d, 0x78, 0x34, 0x70, 0x5f, - 0xaf, 0xd8, 0x79, 0x1d, 0xa4, 0x73, 0x5e, 0xc9, 0xe4, 0x3c, 0x15, 0xa2, 0x2e, 0xeb, 0x21, 0xea, - 0x47, 0x50, 0x4f, 0xef, 0x3e, 0x9a, 0x83, 0x62, 0x3d, 0xca, 0x24, 0xda, 0xb4, 0x52, 0x1a, 0xd4, - 0xae, 0xea, 0x41, 0xed, 0x6f, 0x69, 0x41, 0xcf, 0x19, 0x6c, 0xc6, 0x2e, 0x5a, 0xd5, 0x2f, 0x26, - 0x4b, 0xe2, 0x09, 0x34, 0xb4, 0xc1, 0xeb, 0xc1, 0x4d, 0xcb, 0x08, 0x6e, 0xaa, 0x74, 0xf7, 0x52, - 0x9a, 0xee, 0x6e, 0xff, 0xac, 0x04, 0x2d, 0xc6, 0x6b, 0x7e, 0x70, 0x7a, 0x10, 0x0e, 0xfd, 0xfe, - 0x25, 0xd2, 0xb8, 0x64, 0x2b, 0xa1, 0x84, 0x49, 0x9e, 0x33, 0xc1, 0x4c, 0x26, 0xaa, 0x3b, 0x3e, - 0x5c, 0x80, 0xab, 0x32, 0x93, 0xf0, 0x4c, 0x3e, 0x1e, 0x7b, 0x31, 0xd5, 0x6e, 0x66, 0x3a, 0x26, - 0x90, 0xc9, 0x61, 0x06, 0xc0, 0xcb, 0x0b, 0x23, 0x7f, 0x38, 0xf4, 0x79, 0x5d, 0xee, 0x3d, 0x28, - 0x42, 0xb1, 0x3e, 0x07, 0x7e, 0xec, 0x1d, 0xa7, 0xa9, 0x44, 0xaa, 0x8c, 0x71, 0x1c, 0xef, 0xb5, - 0x16, 0xc7, 0xe1, 0xb7, 0x9d, 0x4c, 0x60, 0x96, 0xaa, 0x66, 0x73, 0x54, 0x65, 0xff, 0xbb, 0x12, - 0x34, 0x34, 0x1a, 0x65, 0xb2, 0xa5, 0xf0, 0x10, 0xd6, 0xa0, 0x22, 0xc7, 0x2e, 0x30, 0xfc, 0x51, - 0x1a, 0x84, 0xdc, 0x33, 0x7b, 0xc5, 0xf8, 0x2f, 0x4a, 0x1f, 0x83, 0x9e, 0x6f, 0x41, 0x9d, 0xf1, - 0xe1, 0x87, 0xe8, 0xfc, 0x12, 0xb7, 0xa0, 0x15, 0x40, 0x62, 0x57, 0x11, 0x5b, 0x4d, 0xb1, 0x08, - 0xb8, 0x32, 0xeb, 0xee, 0x31, 0x34, 0x45, 0x33, 0xb8, 0xc7, 0x38, 0xe9, 0x54, 0x12, 0x18, 0xfb, - 0xef, 0x18, 0x35, 0xe5, 0x97, 0xab, 0xf2, 0xcb, 0xda, 0x9b, 0xbe, 0x94, 0x35, 0xed, 0x67, 0x2a, - 0xa1, 0xf1, 0x59, 0xe4, 0x8d, 0xcf, 0xa4, 0x74, 0x7b, 0x04, 0x0b, 0x52, 0x88, 0x4d, 0x02, 0x2f, - 0x08, 0xc2, 0x49, 0xd0, 0xa7, 0x32, 0x33, 0xbe, 0x08, 0x65, 0x0f, 0xd4, 0x3d, 0x2a, 0x6c, 0x88, - 0x3c, 0x80, 0x2a, 0x57, 0xe3, 0xb9, 0xae, 0x52, 0x2c, 0xcf, 0x78, 0x15, 0x72, 0x1f, 0xaa, 0x5c, - 0x9b, 0x2f, 0x4d, 0x95, 0x40, 0xbc, 0x82, 0xbd, 0x02, 0x73, 0xa8, 0x91, 0x6a, 0x82, 0xf8, 0x66, - 0x91, 0x0e, 0x33, 0xd3, 0xe7, 0x81, 0x86, 0x45, 0x20, 0x7b, 0x9c, 0xaf, 0xf4, 0x8c, 0x9b, 0x3f, - 0x2f, 0x43, 0x43, 0x03, 0x33, 0x61, 0x89, 0xe9, 0x17, 0xee, 0xc0, 0xf7, 0x46, 0x54, 0x86, 0x1d, - 0x5a, 0x4e, 0x06, 0xca, 0xea, 0x79, 0xe7, 0xa7, 0x6e, 0x38, 0x49, 0xdc, 0x01, 0x3d, 0x8d, 0x28, - 0x15, 0xca, 0x55, 0x06, 0xca, 0xea, 0x31, 0x6a, 0xd6, 0xea, 0xf1, 0x4c, 0x82, 0x0c, 0x54, 0x66, - 0xb6, 0xf0, 0x75, 0xaa, 0xa4, 0x99, 0x2d, 0x7c, 0x55, 0xb2, 0x62, 0xbe, 0x5a, 0x20, 0xe6, 0x3f, - 0x82, 0x25, 0x2e, 0xd0, 0x85, 0xf4, 0x70, 0x33, 0xc4, 0x35, 0x05, 0x4b, 0x1e, 0x40, 0x87, 0x8d, - 0x59, 0xb2, 0x46, 0xec, 0xff, 0x84, 0xf3, 0x98, 0xe5, 0xe4, 0xe0, 0xac, 0x2e, 0x46, 0x45, 0xf5, - 0xba, 0x3c, 0xd3, 0x33, 0x07, 0xc7, 0xba, 0xde, 0x6b, 0xb3, 0x6e, 0x5d, 0xd4, 0xcd, 0xc0, 0xc9, - 0x63, 0x58, 0x1e, 0xd1, 0x81, 0xef, 0x99, 0x4d, 0xb8, 0xa9, 0xc6, 0x31, 0x0d, 0xcd, 0x7a, 0x61, - 0xab, 0xf0, 0x93, 0x70, 0x74, 0xec, 0xf3, 0x53, 0x96, 0xc7, 0x6f, 0x2b, 0x4e, 0x0e, 0x6e, 0xb7, - 0xa0, 0x71, 0x98, 0x84, 0x63, 0xb9, 0xf5, 0x6d, 0x68, 0xf2, 0xa2, 0xb8, 0x0b, 0x71, 0x13, 0x6e, - 0x20, 0xbd, 0x1e, 0x85, 0xe3, 0x70, 0x18, 0x9e, 0x5e, 0x1a, 0x8e, 0xa3, 0xff, 0x60, 0xc1, 0x82, - 0x81, 0x4d, 0x3d, 0x47, 0xe8, 0xe5, 0x96, 0x09, 0xec, 0x9c, 0xc4, 0xe7, 0xb5, 0x33, 0x8a, 0x57, - 0xe4, 0x11, 0xfa, 0x17, 0x22, 0xa7, 0x7d, 0x2d, 0xbd, 0x95, 0x29, 0x3f, 0xe4, 0xf4, 0xde, 0xcd, - 0xd3, 0xbb, 0xf8, 0x5e, 0xde, 0xd7, 0x94, 0x4d, 0xfc, 0x96, 0xc8, 0xcb, 0x1d, 0x88, 0x49, 0x97, - 0xcd, 0x5c, 0x4a, 0xdd, 0xd1, 0x28, 0x47, 0xd0, 0x57, 0xc0, 0xd8, 0xfe, 0xb9, 0x05, 0x90, 0x8e, - 0x0e, 0xb3, 0x39, 0xd5, 0x39, 0xcb, 0x1f, 0x3e, 0xd1, 0xce, 0xd4, 0x77, 0xa1, 0xa9, 0x32, 0xca, - 0xd2, 0xa3, 0xbb, 0x21, 0x61, 0x4c, 0xd5, 0x79, 0x1f, 0xe6, 0x4e, 0x87, 0xe1, 0x31, 0xaa, 0x54, - 0xe2, 0x9c, 0xe5, 0x37, 0x42, 0xda, 0x1c, 0x2c, 0x4f, 0xcf, 0xf4, 0x9c, 0xaf, 0x14, 0xa6, 0xa2, - 0xe9, 0xa7, 0x36, 0x3b, 0xeb, 0xe6, 0x73, 0x2b, 0x71, 0x25, 0x97, 0xff, 0x52, 0x01, 0xd9, 0xab, - 0xe2, 0x0e, 0x4f, 0xa0, 0x1d, 0x71, 0x99, 0x29, 0x05, 0x6a, 0xe5, 0x0a, 0x81, 0xda, 0x8a, 0x8c, - 0x93, 0xf9, 0x2b, 0xd0, 0xf1, 0x06, 0xe7, 0x34, 0x4a, 0x7c, 0xf4, 0xc3, 0xa2, 0x4e, 0xc7, 0x27, - 0x38, 0xa7, 0xc1, 0x51, 0x75, 0x7a, 0x1f, 0xe6, 0xc4, 0xfd, 0x1c, 0x55, 0x53, 0x3c, 0x01, 0x90, - 0x82, 0x59, 0x45, 0xfb, 0x1f, 0xcb, 0x84, 0x1e, 0x73, 0x77, 0xaf, 0x5e, 0x15, 0x7d, 0x86, 0xa5, - 0xcc, 0x0c, 0xbf, 0x24, 0xd2, 0x15, 0x06, 0xd2, 0xe1, 0x5b, 0xd6, 0x32, 0xbc, 0x07, 0x22, 0x21, - 0xca, 0x5c, 0xd6, 0xca, 0xdb, 0x2c, 0xab, 0xfd, 0x5f, 0x2c, 0x98, 0xdd, 0x0e, 0xc7, 0xcc, 0xb4, - 0x47, 0x1d, 0x87, 0xb1, 0x89, 0xba, 0x1c, 0x27, 0x8b, 0x6f, 0xc8, 0x84, 0x2f, 0xd4, 0x4a, 0x5a, - 0x59, 0xad, 0xe4, 0xdb, 0x70, 0x13, 0x43, 0x0e, 0x51, 0x38, 0x0e, 0x23, 0xc6, 0xae, 0xde, 0x90, - 0xab, 0x20, 0x61, 0x90, 0x9c, 0x49, 0x71, 0x7a, 0x55, 0x15, 0xf4, 0x03, 0x0e, 0x93, 0x73, 0x97, - 0x9b, 0x9b, 0x42, 0x8b, 0xe2, 0x52, 0x36, 0x8f, 0xb0, 0x7f, 0x13, 0xea, 0xca, 0x81, 0x41, 0x3e, - 0x80, 0xfa, 0x59, 0x38, 0x16, 0x5e, 0x0e, 0xcb, 0xb8, 0x35, 0x20, 0x66, 0xef, 0xa4, 0x15, 0xec, - 0xff, 0x3d, 0x0b, 0xb3, 0x3b, 0xc1, 0x79, 0xe8, 0xf7, 0x31, 0x31, 0x68, 0x44, 0x47, 0xa1, 0xbc, - 0x2e, 0xc8, 0xfe, 0xc6, 0x97, 0x3c, 0xd2, 0x0b, 0xfd, 0x9c, 0x85, 0x34, 0x08, 0x33, 0x90, 0x23, - 0xfd, 0x42, 0xbe, 0x28, 0xa5, 0x56, 0x5f, 0x55, 0xbb, 0x70, 0xc9, 0x5a, 0xe3, 0x17, 0xc5, 0x71, - 0xed, 0xf8, 0x35, 0x0f, 0x0d, 0xc2, 0x16, 0x5f, 0x64, 0xe8, 0xf3, 0x14, 0x6e, 0x9e, 0x63, 0x28, - 0x40, 0x68, 0xf4, 0x47, 0x94, 0x07, 0x8d, 0x94, 0xea, 0xc5, 0x8c, 0x7e, 0x1d, 0xc8, 0xd4, 0x33, - 0xfe, 0x01, 0xaf, 0xc3, 0x8f, 0x03, 0x1d, 0x84, 0x79, 0x22, 0x99, 0xe7, 0x2d, 0xf8, 0x13, 0x25, - 0x59, 0x30, 0x4f, 0x01, 0x53, 0x42, 0x97, 0xcf, 0x13, 0xf8, 0xa3, 0x06, 0x59, 0xb8, 0xe6, 0x2a, - 0xe0, 0x17, 0x99, 0xa4, 0xab, 0x80, 0x91, 0x8c, 0x37, 0x1c, 0x1e, 0x7b, 0xfd, 0x57, 0xdc, 0xb2, - 0x6d, 0xf2, 0x58, 0xa3, 0x01, 0xc4, 0x3c, 0xfb, 0x74, 0x5f, 0x31, 0x45, 0xa7, 0xe2, 0xe8, 0x20, - 0xb2, 0x6a, 0xfa, 0xaf, 0xda, 0x53, 0xfc, 0x57, 0x7a, 0x25, 0x3d, 0x65, 0x69, 0x2e, 0x77, 0xb5, - 0xc8, 0x1b, 0x0c, 0x44, 0x2a, 0x4b, 0x87, 0x5f, 0xea, 0x57, 0x00, 0x74, 0xd4, 0xf0, 0x05, 0xe3, - 0x15, 0xe6, 0xb1, 0x82, 0x01, 0x23, 0x77, 0xb8, 0x1f, 0x76, 0xec, 0xf9, 0x03, 0x4c, 0x19, 0xe5, - 0xb6, 0xb0, 0x82, 0xb1, 0x36, 0xe4, 0xdf, 0x78, 0x70, 0x2e, 0xe0, 0xaa, 0x18, 0x30, 0xb6, 0x36, - 0xaa, 0x3c, 0x4a, 0xef, 0x22, 0x99, 0x40, 0xf2, 0x21, 0xa6, 0x08, 0x24, 0x14, 0x2f, 0x1c, 0xb5, - 0x57, 0x6f, 0x8a, 0x39, 0x0b, 0xb2, 0x95, 0xff, 0x63, 0x4a, 0x84, 0xc3, 0x6b, 0x32, 0xb5, 0x8d, - 0x47, 0x69, 0x96, 0x0c, 0xb5, 0x4d, 0x54, 0xc5, 0x28, 0x0d, 0xaf, 0x40, 0x1e, 0x6b, 0x96, 0x58, - 0x17, 0x2b, 0xdf, 0xca, 0xb4, 0x3f, 0xc5, 0x06, 0x63, 0xc4, 0xec, 0xc7, 0xec, 0xfc, 0x89, 0x69, - 0x30, 0xc0, 0xab, 0x47, 0x35, 0x47, 0x83, 0xfc, 0x7a, 0x6d, 0xb4, 0x35, 0x68, 0xea, 0xf3, 0x24, - 0x35, 0xa8, 0xec, 0x1f, 0x6c, 0xed, 0x75, 0xae, 0x91, 0x06, 0xcc, 0x1e, 0x6e, 0x1d, 0x1d, 0xed, - 0x6e, 0x6d, 0x76, 0x2c, 0xd2, 0x84, 0x9a, 0xba, 0xe5, 0x51, 0x62, 0xa5, 0xb5, 0x8d, 0x8d, 0xad, - 0x83, 0xa3, 0xad, 0xcd, 0x4e, 0xf9, 0x3b, 0x95, 0x5a, 0xa9, 0x53, 0x46, 0x05, 0x53, 0x5b, 0x86, - 0x37, 0xf8, 0xd9, 0xee, 0x00, 0xa0, 0xe1, 0x93, 0xa6, 0x3c, 0x55, 0x1c, 0x0d, 0xc2, 0x04, 0xb9, - 0xf2, 0x4f, 0x94, 0xf9, 0x43, 0x0c, 0xb2, 0x8c, 0x9b, 0x8b, 0x2f, 0x1e, 0xe8, 0x91, 0xbb, 0xaa, - 0x63, 0x02, 0x19, 0xe1, 0x0b, 0x00, 0x5e, 0x3d, 0xe0, 0xe2, 0x42, 0x07, 0x31, 0x42, 0x8a, 0x68, - 0x1c, 0x0e, 0xcf, 0x29, 0xaf, 0xc2, 0xd5, 0x47, 0x03, 0xc6, 0xfa, 0x12, 0x12, 0x51, 0xbb, 0x16, - 0x54, 0x75, 0x4c, 0x20, 0xf9, 0x9a, 0x24, 0xa4, 0x1a, 0x12, 0xd2, 0x72, 0x9e, 0x2a, 0x0c, 0x22, - 0x7a, 0x9e, 0x73, 0x94, 0xd5, 0x91, 0x40, 0xbe, 0x9c, 0xff, 0xee, 0x2d, 0x1c, 0x66, 0x64, 0x05, - 0xc8, 0x68, 0x3c, 0x76, 0x0b, 0x3c, 0x58, 0x15, 0xa7, 0x00, 0xf3, 0x6b, 0x70, 0xb0, 0x25, 0x40, - 0xd6, 0x06, 0x03, 0x31, 0x4c, 0xfd, 0x5d, 0x8a, 0x48, 0x7f, 0x08, 0x45, 0x8a, 0xec, 0x02, 0xb1, - 0x58, 0x2a, 0x16, 0x8b, 0x57, 0x0a, 0x0f, 0x7b, 0x07, 0x1a, 0x07, 0xda, 0xd3, 0x2a, 0x36, 0x3b, - 0x41, 0xe4, 0xa3, 0x2a, 0xfc, 0x6c, 0xe1, 0x8e, 0xb5, 0x14, 0xaa, 0x0d, 0xa9, 0xa4, 0x0f, 0xc9, - 0xfe, 0x87, 0x16, 0xbf, 0xad, 0xae, 0xa6, 0xc0, 0xfb, 0xb7, 0xa1, 0xa9, 0x82, 0x4b, 0xe9, 0xd5, - 0x3d, 0x03, 0xc6, 0xea, 0xe0, 0x70, 0xdc, 0xf0, 0xe4, 0x24, 0xa6, 0xf2, 0x92, 0x8d, 0x01, 0x93, - 0xca, 0x3a, 0x53, 0xff, 0x7d, 0xde, 0x43, 0x2c, 0x2e, 0xdb, 0xe4, 0xe0, 0x8c, 0xd2, 0x85, 0x6f, - 0x5c, 0x5e, 0x2f, 0x52, 0x65, 0x75, 0xc3, 0x30, 0xbb, 0xd2, 0x0f, 0xa0, 0xa6, 0xda, 0x35, 0x4f, - 0x62, 0x59, 0x53, 0xe1, 0xd9, 0x89, 0x8f, 0x86, 0xbc, 0x31, 0x68, 0xce, 0x70, 0x79, 0x04, 0xa3, - 0xa5, 0x13, 0x3f, 0xca, 0x56, 0xe7, 0x1c, 0x58, 0x80, 0xb1, 0x5f, 0xc2, 0x82, 0x14, 0x1f, 0x9a, - 0x15, 0x61, 0x6e, 0xa4, 0xf5, 0xa6, 0x53, 0xa0, 0x94, 0x3f, 0x05, 0xec, 0x7f, 0x5b, 0x81, 0x59, - 0xf9, 0x6e, 0x91, 0x5d, 0xf0, 0xce, 0x4e, 0xdd, 0x7c, 0xa2, 0x87, 0x74, 0x8d, 0x87, 0x18, 0x90, - 0x10, 0x84, 0x6e, 0x70, 0x3f, 0x7b, 0xba, 0xa7, 0x0e, 0xd6, 0xcc, 0x09, 0xbf, 0x04, 0x95, 0xb1, - 0x97, 0x9c, 0xa1, 0xff, 0x8d, 0xd3, 0x12, 0x96, 0xa5, 0x0b, 0xbf, 0x6a, 0xba, 0xf0, 0x8b, 0x1e, - 0x26, 0xe2, 0xaa, 0x6c, 0xfe, 0x61, 0xa2, 0x5b, 0x50, 0xe7, 0xda, 0x48, 0xea, 0xa5, 0x4f, 0x01, - 0x19, 0xed, 0xa5, 0x96, 0xd3, 0x5e, 0xde, 0x5e, 0xaf, 0xf8, 0x06, 0xcc, 0xf0, 0xcb, 0xb9, 0xe2, - 0x32, 0x95, 0x3c, 0x72, 0xc4, 0x4a, 0xca, 0xff, 0x79, 0x4e, 0xad, 0x23, 0xea, 0xea, 0xcf, 0x7b, - 0x34, 0xcc, 0xe7, 0x3d, 0xf4, 0xe0, 0x42, 0x33, 0x13, 0x5c, 0x78, 0x00, 0x1d, 0xb5, 0x7c, 0xe8, - 0x80, 0x0b, 0x62, 0x71, 0x79, 0x24, 0x07, 0x4f, 0x8f, 0xcd, 0xb6, 0x71, 0x6c, 0x32, 0x09, 0xb7, - 0x96, 0x24, 0x74, 0x34, 0x4e, 0xc4, 0xb1, 0x69, 0x3f, 0x85, 0x96, 0x31, 0x48, 0x76, 0x0c, 0x89, - 0xeb, 0x55, 0x9d, 0x6b, 0xa4, 0x05, 0xf5, 0x9d, 0x3d, 0xf7, 0xe9, 0xee, 0xce, 0xb3, 0xed, 0xa3, - 0x8e, 0xc5, 0x8a, 0x87, 0x2f, 0x36, 0x36, 0xb6, 0xb6, 0x36, 0xf1, 0x58, 0x02, 0x98, 0x79, 0xba, - 0xb6, 0xc3, 0x8e, 0xa8, 0xb2, 0xfd, 0x7f, 0x2c, 0x68, 0x68, 0xcd, 0x93, 0x6f, 0xaa, 0x95, 0xe1, - 0x2f, 0x40, 0xdc, 0xce, 0x0f, 0x61, 0x45, 0x0a, 0x6a, 0x6d, 0x69, 0xd4, 0x5b, 0x4c, 0xa5, 0xa9, - 0x6f, 0x31, 0xb1, 0xed, 0xf1, 0x78, 0x0b, 0x6a, 0x1d, 0xb8, 0x75, 0x95, 0x05, 0xf3, 0x44, 0xb2, - 0xf4, 0x74, 0x61, 0x35, 0xb9, 0x47, 0x31, 0x0b, 0xb6, 0x3f, 0x02, 0x48, 0x47, 0x63, 0x4e, 0xfb, - 0x9a, 0x39, 0x6d, 0x4b, 0x9b, 0x76, 0xc9, 0xde, 0xe4, 0x02, 0x43, 0x2c, 0xa1, 0x0a, 0x83, 0x7f, - 0x0d, 0x88, 0x74, 0x60, 0x61, 0xc2, 0xe6, 0x78, 0x48, 0x13, 0x79, 0xe9, 0x72, 0x5e, 0x60, 0x76, - 0x14, 0x42, 0xde, 0x1b, 0x4e, 0x5b, 0x49, 0xe5, 0x8e, 0xa0, 0xb8, 0xac, 0xdc, 0x11, 0x55, 0x1d, - 0x85, 0xb7, 0x7b, 0xd0, 0xdd, 0xa4, 0xac, 0xb5, 0xb5, 0xe1, 0x30, 0x33, 0x1c, 0xfb, 0x26, 0xdc, - 0x28, 0xc0, 0x09, 0xf7, 0xc4, 0x77, 0xe1, 0xfa, 0x1a, 0xbf, 0x5f, 0xf9, 0xeb, 0xba, 0xca, 0x61, - 0x77, 0x61, 0x29, 0xdb, 0xa4, 0xe8, 0xec, 0x29, 0xcc, 0x6f, 0xd2, 0xe3, 0xc9, 0xe9, 0x2e, 0x3d, - 0x4f, 0x3b, 0x22, 0x50, 0x89, 0xcf, 0xc2, 0x0b, 0xb1, 0x3e, 0xf8, 0x37, 0xb9, 0x0d, 0x30, 0x64, - 0x75, 0xdc, 0x78, 0x4c, 0xfb, 0xf2, 0x85, 0x0d, 0x84, 0x1c, 0x8e, 0x69, 0xdf, 0xfe, 0x08, 0x88, - 0xde, 0x8e, 0x58, 0x2f, 0x66, 0x32, 0x4c, 0x8e, 0xdd, 0xf8, 0x32, 0x4e, 0xe8, 0x48, 0x3e, 0x1d, - 0xa2, 0x83, 0xec, 0xf7, 0xa1, 0x79, 0xe0, 0x5d, 0x3a, 0xf4, 0x53, 0xf1, 0xf6, 0xd7, 0x32, 0xcc, - 0x8e, 0xbd, 0x4b, 0xc6, 0xcf, 0x2a, 0xc4, 0x82, 0x68, 0xfb, 0x8f, 0x2b, 0x30, 0xc3, 0x6b, 0xb2, - 0x56, 0x07, 0x34, 0x4e, 0xfc, 0x00, 0x79, 0x4c, 0xb6, 0xaa, 0x81, 0x72, 0x02, 0xb3, 0x54, 0x20, - 0x30, 0x85, 0xab, 0x4d, 0xbe, 0x54, 0x20, 0x48, 0xd6, 0x80, 0x31, 0xb1, 0x95, 0x5e, 0x0c, 0xe3, - 0x94, 0x9a, 0x02, 0x32, 0x31, 0xcc, 0xd4, 0x30, 0xe1, 0xe3, 0x93, 0x67, 0x81, 0x90, 0x89, 0x3a, - 0xa8, 0xd0, 0xfc, 0x99, 0x95, 0x37, 0x60, 0x32, 0xe6, 0x4f, 0xce, 0xcc, 0xa9, 0xbd, 0x85, 0x99, - 0xc3, 0xfd, 0x6f, 0x57, 0x99, 0x39, 0xf0, 0x36, 0x66, 0xce, 0xdb, 0xc4, 0x0e, 0x7b, 0x50, 0xc3, - 0x33, 0x5d, 0x13, 0x91, 0xb2, 0x4c, 0x7e, 0x43, 0xb3, 0x01, 0x78, 0x1e, 0xc3, 0xcd, 0x94, 0x5f, - 0x1c, 0xfa, 0xe9, 0x17, 0x13, 0x86, 0xf9, 0x21, 0xcc, 0x0a, 0x28, 0xa3, 0xec, 0xc0, 0x1b, 0xc9, - 0x17, 0x62, 0xf0, 0x6f, 0xb6, 0x74, 0xf8, 0x50, 0xc5, 0xa7, 0x13, 0x3f, 0xa2, 0x03, 0x79, 0x8b, - 0x5a, 0x03, 0x61, 0xda, 0x77, 0xec, 0xbe, 0x0a, 0xc2, 0x8b, 0x40, 0xdc, 0xa3, 0x56, 0x65, 0x9b, - 0x40, 0x07, 0x5f, 0x8a, 0x1a, 0x87, 0x91, 0x7c, 0xf4, 0xc7, 0xfe, 0x03, 0x0b, 0x3a, 0x82, 0xd1, - 0x14, 0x4e, 0x26, 0x0c, 0x5c, 0xf5, 0x58, 0xc0, 0x3d, 0x68, 0xa1, 0xaf, 0x43, 0x1d, 0x39, 0x22, - 0xf8, 0x6e, 0x00, 0xd9, 0x78, 0x65, 0xde, 0xe5, 0xc8, 0x1f, 0x0a, 0xba, 0xd5, 0x41, 0xf2, 0xd4, - 0x8a, 0x3c, 0x71, 0xfd, 0xca, 0x72, 0x54, 0xd9, 0xfe, 0x85, 0x05, 0xf3, 0xda, 0x80, 0x05, 0xa3, - 0x3e, 0x81, 0xa6, 0x7a, 0x90, 0x8d, 0x2a, 0xa5, 0x6a, 0xd9, 0x94, 0x2c, 0xe9, 0x67, 0x46, 0x65, - 0xa4, 0x77, 0xef, 0x12, 0x07, 0x18, 0x4f, 0x46, 0x42, 0x9b, 0xd1, 0x41, 0x8c, 0x8e, 0x2e, 0x28, - 0x7d, 0xa5, 0xaa, 0x70, 0x7d, 0xca, 0x80, 0x61, 0x8c, 0x28, 0x0c, 0x92, 0x33, 0x55, 0xa9, 0x22, - 0x62, 0x44, 0x3a, 0xd0, 0xfe, 0x6f, 0x25, 0x58, 0xe0, 0x4e, 0x37, 0xe1, 0xec, 0x54, 0x6f, 0xe2, - 0xcc, 0x70, 0xff, 0x23, 0x17, 0x5a, 0xdb, 0xd7, 0x1c, 0x51, 0x26, 0xdf, 0x7c, 0x4b, 0x47, 0xa1, - 0xba, 0xe7, 0x35, 0x65, 0x2f, 0xca, 0x45, 0x7b, 0x71, 0xc5, 0x4a, 0x17, 0x85, 0xeb, 0xaa, 0xc5, - 0xe1, 0xba, 0xb7, 0x0b, 0x8f, 0xe5, 0x2e, 0x43, 0xcd, 0x8a, 0x5a, 0xc6, 0x65, 0xa8, 0x55, 0x58, - 0x36, 0x00, 0x28, 0xaf, 0xfd, 0x13, 0x9f, 0xca, 0x9b, 0xe9, 0xf3, 0x31, 0x4d, 0x5c, 0xa3, 0xca, - 0xfa, 0x2c, 0x54, 0xe3, 0x7e, 0x38, 0xa6, 0xf6, 0x12, 0x2c, 0x9a, 0x8b, 0x2b, 0x4e, 0x89, 0x9f, - 0x5b, 0xd0, 0x7d, 0xca, 0x93, 0x2e, 0xfc, 0xe0, 0x74, 0xdb, 0x8f, 0x93, 0x30, 0x52, 0x4f, 0x97, - 0xdd, 0x01, 0x88, 0x13, 0x2f, 0x12, 0x76, 0x26, 0x57, 0x76, 0x35, 0x08, 0x5b, 0x23, 0x1a, 0x0c, - 0x38, 0x96, 0xd3, 0x86, 0x2a, 0xe7, 0x8c, 0x09, 0xe1, 0x92, 0x34, 0x54, 0xf2, 0xf7, 0xf8, 0x1d, - 0x4d, 0xb6, 0x18, 0xf4, 0x1c, 0x8f, 0x5e, 0xee, 0xe7, 0xcb, 0x40, 0xed, 0x3f, 0x2c, 0xc1, 0x5c, - 0x3a, 0x48, 0x7e, 0xe7, 0xdb, 0x10, 0xe0, 0x42, 0x0f, 0x4f, 0x05, 0xb8, 0x08, 0x1f, 0xba, 0x3e, - 0x53, 0xcc, 0x35, 0xaf, 0xa4, 0x06, 0x25, 0xf7, 0xa0, 0x21, 0x4b, 0xe1, 0x24, 0xd1, 0xde, 0x10, - 0xd2, 0xc1, 0xfc, 0xf2, 0x07, 0x33, 0x0d, 0x84, 0x99, 0x23, 0x4a, 0xf8, 0x52, 0xc1, 0x28, 0xc1, - 0x2f, 0xf9, 0x9e, 0xca, 0x22, 0x13, 0x68, 0x4c, 0xa7, 0xe6, 0x7b, 0x88, 0xfa, 0xb4, 0xae, 0x6b, - 0xd6, 0xd4, 0xdb, 0x8b, 0x8a, 0xe7, 0x79, 0x8b, 0xe9, 0x35, 0xb8, 0x8a, 0xa3, 0x83, 0xa4, 0x57, - 0x28, 0x9c, 0x18, 0xe6, 0xaf, 0x01, 0xb3, 0xff, 0xb6, 0x05, 0x37, 0x0a, 0xb6, 0x51, 0xc8, 0x80, - 0x4d, 0x98, 0x3f, 0x51, 0x48, 0xb9, 0xd4, 0x5c, 0x10, 0x2c, 0x49, 0xe1, 0x6a, 0x2e, 0xaf, 0x93, - 0xff, 0x40, 0x99, 0x5b, 0x7c, 0xf3, 0x8c, 0x5b, 0x8f, 0x79, 0x84, 0x7d, 0x00, 0xbd, 0xad, 0xd7, - 0x4c, 0xa4, 0x6c, 0xe8, 0x0f, 0x70, 0x4b, 0xca, 0x5a, 0xcd, 0x89, 0xcc, 0x37, 0x3b, 0xa3, 0x4f, - 0xf8, 0x5d, 0x2e, 0xd5, 0x16, 0xf9, 0xfa, 0xdb, 0x36, 0xa2, 0x73, 0xff, 0x5d, 0xb1, 0xeb, 0xfc, - 0x05, 0x71, 0x79, 0xf7, 0x52, 0x03, 0xd9, 0xe7, 0x30, 0xf7, 0x7c, 0x32, 0x4c, 0xfc, 0xf4, 0x35, - 0x71, 0xf2, 0x4d, 0xf1, 0x11, 0x36, 0x21, 0x97, 0xae, 0xb0, 0x2b, 0xbd, 0x1e, 0x5b, 0xb1, 0x11, - 0x6b, 0xc9, 0xcd, 0xf7, 0x98, 0x47, 0xd8, 0x37, 0x60, 0x39, 0xed, 0x92, 0xaf, 0x9d, 0x3c, 0x76, - 0xfe, 0xc8, 0xe2, 0x39, 0xcf, 0xe6, 0xe3, 0xe6, 0xe4, 0x19, 0x2c, 0xc4, 0x7e, 0x70, 0x3a, 0xa4, - 0x7a, 0x3b, 0xb1, 0x58, 0x89, 0xeb, 0xe6, 0xf0, 0xc4, 0x03, 0xe8, 0x4e, 0xd1, 0x17, 0x8c, 0x40, - 0x8a, 0x07, 0x9a, 0x12, 0x48, 0x66, 0x49, 0x8a, 0x26, 0xf0, 0x1d, 0x68, 0x9b, 0x9d, 0x91, 0xc7, - 0xe2, 0x52, 0x63, 0x3a, 0xb2, 0x72, 0xe6, 0x6e, 0x5a, 0x4a, 0x19, 0x46, 0x4d, 0xfb, 0x67, 0x16, - 0x74, 0x1d, 0xca, 0xc8, 0x98, 0x6a, 0x9d, 0x0a, 0xea, 0x79, 0x92, 0x6b, 0x76, 0xfa, 0x84, 0xd5, - 0x65, 0x49, 0x39, 0xd7, 0x95, 0xa9, 0x9b, 0xb2, 0x7d, 0xad, 0x60, 0x56, 0xeb, 0x35, 0x98, 0x11, - 0xf3, 0x5b, 0x86, 0xeb, 0x62, 0x48, 0x72, 0x38, 0x69, 0xd8, 0xd1, 0xe8, 0xd4, 0x08, 0x3b, 0xf6, - 0xa0, 0xcb, 0x5f, 0xa8, 0xd3, 0xe7, 0x21, 0x3e, 0xdc, 0x04, 0xf2, 0xdc, 0xeb, 0x7b, 0x51, 0x18, - 0x06, 0x07, 0x34, 0x12, 0x49, 0xaa, 0xa8, 0x7d, 0x62, 0x54, 0x4e, 0x2a, 0xca, 0xbc, 0x24, 0x1f, - 0x55, 0x0b, 0x03, 0xf9, 0x78, 0x1d, 0x2f, 0xd9, 0x0e, 0x2c, 0xac, 0x7b, 0xaf, 0xa8, 0x6c, 0x29, - 0x5d, 0xa5, 0xc6, 0x58, 0x35, 0x2a, 0xd7, 0x5e, 0xde, 0x86, 0xce, 0x77, 0xeb, 0xe8, 0xb5, 0xed, - 0x55, 0x58, 0x34, 0xdb, 0x14, 0xa2, 0xa4, 0x07, 0xb5, 0x91, 0x80, 0x89, 0xd1, 0xa9, 0xf2, 0x83, - 0xcf, 0xa0, 0xa1, 0xbd, 0x3a, 0x48, 0x96, 0x61, 0xe1, 0xe5, 0xce, 0xd1, 0xde, 0xd6, 0xe1, 0xa1, - 0x7b, 0xf0, 0x62, 0xfd, 0x93, 0xad, 0xef, 0xbb, 0xdb, 0x6b, 0x87, 0xdb, 0x9d, 0x6b, 0x64, 0x09, - 0xc8, 0xde, 0xd6, 0xe1, 0xd1, 0xd6, 0xa6, 0x01, 0xb7, 0xc8, 0x1d, 0xe8, 0xbd, 0xd8, 0x7b, 0x71, - 0xb8, 0xb5, 0xe9, 0x16, 0x7d, 0x57, 0x22, 0xb7, 0xe1, 0x86, 0xc0, 0x17, 0x7c, 0x5e, 0x7e, 0xf0, - 0x04, 0x3a, 0x59, 0xb7, 0xa4, 0xe1, 0xce, 0xbd, 0xca, 0xef, 0xfb, 0xe0, 0x1f, 0x95, 0x01, 0xd2, - 0xe4, 0x54, 0xd2, 0x85, 0xc5, 0xcd, 0xb5, 0xa3, 0xb5, 0xdd, 0x7d, 0x36, 0x08, 0x67, 0xff, 0x68, - 0x6b, 0xe3, 0xc8, 0x75, 0xb6, 0xbe, 0xdb, 0xb9, 0x56, 0x88, 0xd9, 0x3f, 0x60, 0x26, 0xfb, 0x32, - 0x2c, 0xec, 0xec, 0xed, 0x1c, 0xed, 0xac, 0xed, 0xba, 0xce, 0xfe, 0x8b, 0x9d, 0xbd, 0x67, 0xfc, - 0x45, 0x94, 0x32, 0x79, 0x07, 0x6e, 0xbe, 0x38, 0x78, 0xea, 0xec, 0xef, 0x1d, 0xb9, 0x87, 0xdb, - 0x2f, 0x8e, 0x36, 0xf1, 0x3d, 0x95, 0x0d, 0x67, 0xe7, 0x80, 0xb7, 0x59, 0xb9, 0xaa, 0x02, 0x6b, - 0xba, 0xca, 0x56, 0xec, 0xd9, 0xfe, 0xe1, 0xe1, 0xce, 0x81, 0xfb, 0xdd, 0x17, 0x5b, 0xce, 0xce, - 0xd6, 0x21, 0x7e, 0x38, 0x53, 0x00, 0x67, 0xf5, 0x67, 0xc9, 0x3c, 0xb4, 0x8e, 0x76, 0xbf, 0xe7, - 0xee, 0xef, 0xed, 0xec, 0xef, 0x61, 0xd5, 0x9a, 0x09, 0x62, 0xb5, 0xea, 0xa4, 0x07, 0x4b, 0x5b, - 0xbf, 0x73, 0xe4, 0x16, 0xb4, 0x0c, 0x53, 0x70, 0xec, 0xbb, 0x06, 0xb9, 0x01, 0xd7, 0x0f, 0x8f, - 0xd6, 0x8e, 0x76, 0x36, 0x5c, 0xf1, 0xa0, 0x12, 0xdb, 0x04, 0xf6, 0x59, 0xb3, 0x18, 0xc5, 0xbe, - 0x6a, 0x91, 0x45, 0xe8, 0x1c, 0xac, 0x7d, 0xff, 0xf9, 0xd6, 0xde, 0x91, 0xbb, 0xb6, 0xb9, 0xe9, - 0xe0, 0x07, 0xed, 0x1c, 0x94, 0xd5, 0x9d, 0x63, 0x1b, 0xf5, 0xfc, 0xe0, 0x00, 0xab, 0x74, 0x64, - 0x81, 0x61, 0xe6, 0x57, 0x7f, 0x56, 0x86, 0x36, 0xbf, 0x2d, 0xc0, 0x7f, 0xc6, 0x81, 0x46, 0xe4, - 0x39, 0xcc, 0x8a, 0xdf, 0x03, 0x21, 0xd7, 0xd5, 0x33, 0x18, 0xfa, 0x2f, 0x90, 0xf4, 0x96, 0xb2, - 0x60, 0xc1, 0x7e, 0x0b, 0x7f, 0xf5, 0x3f, 0xfd, 0x8f, 0xdf, 0x2f, 0xb5, 0x48, 0xe3, 0xe1, 0xf9, - 0x87, 0x0f, 0x4f, 0x69, 0x10, 0xb3, 0x36, 0x7e, 0x17, 0x20, 0xfd, 0x95, 0x0b, 0xd2, 0x55, 0xde, - 0xc7, 0xcc, 0x4f, 0x80, 0xf4, 0x6e, 0x14, 0x60, 0x44, 0xbb, 0x37, 0xb0, 0xdd, 0x05, 0xbb, 0xcd, - 0xda, 0xf5, 0x03, 0x3f, 0xe1, 0xbf, 0x78, 0xf1, 0xb1, 0xf5, 0x80, 0x0c, 0xa0, 0xa9, 0xff, 0xfe, - 0x04, 0x91, 0xd1, 0xfe, 0x82, 0x5f, 0xd0, 0xe8, 0xdd, 0x2c, 0xc4, 0x49, 0x99, 0x83, 0x7d, 0x5c, - 0xb7, 0x3b, 0xac, 0x8f, 0x09, 0xd6, 0x48, 0x7b, 0x19, 0x72, 0x49, 0x9c, 0xfe, 0xcc, 0x04, 0xb9, - 0xa5, 0x09, 0xc7, 0xdc, 0x8f, 0x5c, 0xf4, 0x6e, 0x4f, 0xc1, 0x8a, 0xbe, 0x6e, 0x63, 0x5f, 0xcb, - 0x36, 0x61, 0x7d, 0xf5, 0xb1, 0x8e, 0xfc, 0x91, 0x8b, 0x8f, 0xad, 0x07, 0xab, 0x7f, 0x7a, 0x1f, - 0xea, 0x2a, 0x13, 0x88, 0xfc, 0x18, 0x5a, 0xc6, 0x75, 0x0e, 0x22, 0xa7, 0x51, 0x74, 0xfb, 0xa3, - 0x77, 0xab, 0x18, 0x29, 0x3a, 0xbe, 0x83, 0x1d, 0x77, 0xc9, 0x12, 0xeb, 0x58, 0xdc, 0x87, 0x78, - 0x88, 0x17, 0x93, 0xf8, 0xa3, 0x22, 0xaf, 0xb4, 0x13, 0x87, 0x77, 0x76, 0x2b, 0x7b, 0x08, 0x18, - 0xbd, 0xdd, 0x9e, 0x82, 0x15, 0xdd, 0xdd, 0xc2, 0xee, 0x96, 0xc8, 0xa2, 0xde, 0x9d, 0xca, 0xce, - 0xa1, 0xf8, 0xb0, 0x8f, 0xfe, 0x0b, 0x0c, 0xe4, 0x76, 0xfa, 0xec, 0x4a, 0xc1, 0x2f, 0x33, 0x28, - 0x12, 0xc9, 0xff, 0x3c, 0x83, 0xdd, 0xc5, 0xae, 0x08, 0xc1, 0xed, 0xd3, 0x7f, 0x80, 0x81, 0x1c, - 0x43, 0x43, 0x7b, 0xa8, 0x98, 0xdc, 0x98, 0xfa, 0xa8, 0x72, 0xaf, 0x57, 0x84, 0x2a, 0x9a, 0x8a, - 0xde, 0xfe, 0x43, 0xa6, 0x90, 0xfe, 0x10, 0xea, 0xea, 0xe9, 0x5b, 0xb2, 0xac, 0x3d, 0x45, 0xac, - 0x3f, 0xd5, 0xdb, 0xeb, 0xe6, 0x11, 0x45, 0xc4, 0xa7, 0xb7, 0xce, 0x88, 0xef, 0x25, 0x34, 0xb4, - 0xe7, 0x6d, 0xd5, 0x04, 0xf2, 0x4f, 0xe8, 0xaa, 0x09, 0x14, 0xbc, 0x86, 0x6b, 0xcf, 0x63, 0x17, - 0x0d, 0x52, 0x47, 0xfa, 0x4e, 0x5e, 0x87, 0x31, 0xd9, 0x85, 0xeb, 0xe2, 0x64, 0x3d, 0xa6, 0x9f, - 0x67, 0x1b, 0x0a, 0x7e, 0xf4, 0xe2, 0x91, 0x45, 0x9e, 0x40, 0x4d, 0xbe, 0x62, 0x4c, 0x96, 0x8a, - 0x5f, 0x63, 0xee, 0x2d, 0xe7, 0xe0, 0xe2, 0x18, 0xfc, 0x3e, 0x40, 0xfa, 0x96, 0xae, 0x12, 0x12, - 0xb9, 0xb7, 0x79, 0x15, 0x05, 0xe4, 0x1f, 0xde, 0xb5, 0x97, 0x70, 0x82, 0x1d, 0x82, 0x42, 0x22, - 0xa0, 0x17, 0xf2, 0x55, 0x89, 0x1f, 0x41, 0x43, 0x7b, 0x4e, 0x57, 0x2d, 0x5f, 0xfe, 0x29, 0x5e, - 0xb5, 0x7c, 0x05, 0xaf, 0xef, 0xda, 0x3d, 0x6c, 0x7d, 0xd1, 0x9e, 0x63, 0xad, 0xc7, 0xfe, 0x69, - 0x30, 0xe2, 0x15, 0xd8, 0x06, 0x9d, 0x41, 0xcb, 0x78, 0x33, 0x57, 0x71, 0x68, 0xd1, 0x8b, 0xbc, - 0x8a, 0x43, 0x0b, 0x9f, 0xd9, 0x95, 0x74, 0x66, 0xcf, 0xb3, 0x7e, 0xce, 0xb1, 0x8a, 0xd6, 0xd3, - 0x0f, 0xa0, 0xa1, 0xbd, 0x7f, 0xab, 0xe6, 0x92, 0x7f, 0x6a, 0x57, 0xcd, 0xa5, 0xe8, 0xb9, 0xdc, - 0x45, 0xec, 0xa3, 0x6d, 0x23, 0x29, 0xe0, 0x3b, 0x51, 0xac, 0xed, 0x1f, 0x43, 0xdb, 0x7c, 0x11, - 0x57, 0xf1, 0x7e, 0xe1, 0xdb, 0xba, 0x8a, 0xf7, 0xa7, 0x3c, 0xa3, 0x2b, 0x48, 0xfa, 0xc1, 0x82, - 0xea, 0xe4, 0xe1, 0x4f, 0x45, 0x62, 0xf3, 0x67, 0xe4, 0xbb, 0x4c, 0xc0, 0x89, 0xf7, 0xcb, 0xc8, - 0xb2, 0x46, 0xb5, 0xfa, 0x2b, 0x67, 0x8a, 0x5f, 0x72, 0x4f, 0x9d, 0x99, 0xc4, 0xcc, 0x5f, 0xba, - 0x7a, 0x06, 0x0b, 0x8a, 0x98, 0xd5, 0x7b, 0x64, 0xb1, 0x9a, 0x43, 0xe1, 0xb3, 0x67, 0xbd, 0x4e, - 0x16, 0xfb, 0xc8, 0xe2, 0xc7, 0x1f, 0xbe, 0xfa, 0xa4, 0x1d, 0x7f, 0xfa, 0x93, 0x64, 0xda, 0xf1, - 0x67, 0x3c, 0x0e, 0x95, 0x3d, 0xfe, 0x12, 0x9f, 0xb5, 0x11, 0xc0, 0x5c, 0xe6, 0xee, 0xaa, 0x62, - 0xaf, 0xe2, 0xe7, 0x05, 0x7a, 0x77, 0xae, 0xbe, 0xf2, 0x6a, 0x8a, 0x22, 0x29, 0x4d, 0x1f, 0xca, - 0xb7, 0x4b, 0x7e, 0x0f, 0x9a, 0xfa, 0x43, 0x9e, 0x44, 0x97, 0x09, 0xd9, 0x9e, 0x6e, 0x16, 0xe2, - 0x4c, 0x2a, 0x21, 0x4d, 0xbd, 0x1b, 0xf2, 0x3d, 0x58, 0x52, 0xcb, 0xac, 0x5f, 0x87, 0x8c, 0xc9, - 0x3b, 0x05, 0x97, 0x24, 0x8d, 0xc5, 0xbe, 0x31, 0xf5, 0x16, 0xe5, 0x23, 0x8b, 0x51, 0x9f, 0xf9, - 0x3a, 0x62, 0x7a, 0xf2, 0x14, 0x3d, 0x0a, 0x99, 0x9e, 0x3c, 0x85, 0x4f, 0x2a, 0x4a, 0xea, 0x23, - 0x0b, 0xc6, 0x1a, 0xf1, 0xfc, 0x2d, 0xf2, 0x03, 0x98, 0xd3, 0x2e, 0x9c, 0x1f, 0x5e, 0x06, 0x7d, - 0xc5, 0x49, 0xf9, 0xc7, 0x85, 0x7a, 0x45, 0x66, 0xa9, 0xbd, 0x8c, 0xed, 0xcf, 0xdb, 0xc6, 0xe2, - 0x30, 0x2e, 0xda, 0x80, 0x86, 0x7e, 0x99, 0xfd, 0x8a, 0x76, 0x97, 0x35, 0x94, 0xfe, 0x72, 0xcd, - 0x23, 0x8b, 0xec, 0x42, 0x27, 0xfb, 0xc8, 0x86, 0x92, 0x29, 0x45, 0x0f, 0x83, 0xf4, 0x32, 0x48, - 0xe3, 0x69, 0x0e, 0x72, 0xc0, 0xb3, 0x82, 0xd5, 0xaf, 0x43, 0x84, 0x51, 0xf6, 0x54, 0x37, 0x7f, - 0x35, 0x42, 0xb5, 0x56, 0xf4, 0x7b, 0x21, 0xf7, 0xad, 0x47, 0x16, 0xf9, 0x7b, 0x16, 0x34, 0x8d, - 0xab, 0xeb, 0x46, 0x8e, 0x65, 0x66, 0x9e, 0x5d, 0x1d, 0xa7, 0x4f, 0xd4, 0x76, 0x70, 0x11, 0x77, - 0x1f, 0x7c, 0xc7, 0xd8, 0xa4, 0x9f, 0x1a, 0x9e, 0xde, 0x95, 0xec, 0x4f, 0x44, 0x7c, 0x96, 0xad, - 0xa0, 0x3f, 0x10, 0xf5, 0xd9, 0x23, 0x8b, 0xfc, 0x13, 0x0b, 0xda, 0x66, 0x08, 0x47, 0x4d, 0xb7, - 0x30, 0x58, 0xa4, 0x48, 0x69, 0x4a, 0xdc, 0xe7, 0x07, 0x38, 0xca, 0xa3, 0x07, 0x8e, 0x31, 0x4a, - 0xf1, 0xae, 0xe7, 0xaf, 0x36, 0x5a, 0xf2, 0x31, 0xff, 0xc5, 0x26, 0x19, 0xbd, 0x26, 0xf9, 0x5f, - 0xf8, 0x51, 0xe4, 0xa7, 0xff, 0x1e, 0x0e, 0x6e, 0xc2, 0x8f, 0xf8, 0x4f, 0x23, 0xc8, 0x10, 0x28, - 0xa3, 0xe2, 0xb7, 0xfd, 0xde, 0xbe, 0x87, 0x73, 0xba, 0x63, 0xdf, 0x30, 0xe6, 0x94, 0x55, 0x3c, - 0xd6, 0xf8, 0xe8, 0xc4, 0x4f, 0xd9, 0xa4, 0x27, 0x67, 0xee, 0xe7, 0x6d, 0xa6, 0x0f, 0x72, 0xc4, - 0x07, 0x29, 0xaa, 0x1b, 0xac, 0xf6, 0x96, 0xcd, 0xd8, 0x0f, 0x70, 0xac, 0xf7, 0xec, 0x77, 0xa6, - 0x8e, 0xf5, 0x21, 0x06, 0x62, 0xd8, 0x88, 0x0f, 0x00, 0xd2, 0x6c, 0x13, 0x92, 0xc9, 0x74, 0x50, - 0x02, 0x28, 0x9f, 0x90, 0x62, 0xf2, 0xb3, 0x4c, 0x88, 0x60, 0x2d, 0xfe, 0x90, 0x8b, 0xd3, 0x1d, - 0x99, 0x23, 0xa1, 0x6b, 0x5f, 0x66, 0x4a, 0x88, 0xa1, 0x7d, 0x65, 0xdb, 0x37, 0x84, 0xa9, 0x4a, - 0xb8, 0x78, 0x01, 0xad, 0xdd, 0x30, 0x7c, 0x35, 0x19, 0xab, 0xf4, 0x47, 0x33, 0x46, 0xba, 0xed, - 0xc5, 0x67, 0xbd, 0xcc, 0x2c, 0xec, 0xbb, 0xd8, 0x54, 0x8f, 0x74, 0xb5, 0xa6, 0x1e, 0xfe, 0x34, - 0xcd, 0x64, 0xf9, 0x8c, 0x78, 0x30, 0xaf, 0x64, 0xb4, 0x1a, 0x78, 0xcf, 0x6c, 0xc6, 0x90, 0xcc, - 0xd9, 0x2e, 0x0c, 0x33, 0x41, 0x8e, 0xf6, 0x61, 0x2c, 0xdb, 0x7c, 0x64, 0x91, 0x03, 0x68, 0x6e, - 0xd2, 0x3e, 0x5e, 0x0a, 0xc5, 0x40, 0xe3, 0x82, 0x11, 0xac, 0xe2, 0x11, 0xca, 0x5e, 0xcb, 0x00, - 0x9a, 0xe7, 0xd6, 0xd8, 0xbb, 0x8c, 0xe8, 0xa7, 0x0f, 0x7f, 0x2a, 0x42, 0x98, 0x9f, 0xc9, 0x73, - 0x4b, 0xc6, 0x78, 0x8d, 0x73, 0x2b, 0x13, 0x14, 0x36, 0xce, 0xad, 0x5c, 0x50, 0xd8, 0x58, 0x6a, - 0x19, 0x63, 0x26, 0x43, 0x98, 0xcf, 0xc5, 0x91, 0xd5, 0x91, 0x35, 0x2d, 0xfa, 0xdc, 0xbb, 0x3b, - 0xbd, 0x82, 0xd9, 0xdb, 0x03, 0xb3, 0xb7, 0x43, 0x68, 0xf1, 0x47, 0xab, 0x8e, 0x29, 0xbf, 0xef, - 0x91, 0x79, 0xff, 0x40, 0xbf, 0x4d, 0x92, 0x3d, 0x60, 0x10, 0x67, 0x6a, 0x38, 0xfc, 0xf5, 0xcb, - 0x1f, 0x42, 0xe3, 0x19, 0x4d, 0xe4, 0x05, 0x0f, 0xa5, 0x63, 0x67, 0x6e, 0x7c, 0xf4, 0x0a, 0xee, - 0x87, 0x98, 0x34, 0x83, 0xad, 0x3d, 0xa4, 0x83, 0x53, 0xca, 0x85, 0x93, 0xeb, 0x0f, 0x3e, 0x23, - 0xbf, 0x83, 0x8d, 0xab, 0xeb, 0x76, 0x4b, 0x5a, 0xb6, 0xbe, 0xde, 0xf8, 0x5c, 0x06, 0x5e, 0xd4, - 0x72, 0x10, 0x0e, 0xa8, 0xa6, 0xeb, 0x05, 0xd0, 0xd0, 0xae, 0xeb, 0x2a, 0x06, 0xca, 0x5f, 0xcf, - 0x56, 0x0c, 0x54, 0x70, 0xbb, 0xd7, 0xbe, 0x8f, 0xfd, 0xd8, 0xe4, 0x6e, 0xda, 0x0f, 0xbf, 0xd1, - 0x9b, 0xf6, 0xf4, 0xf0, 0xa7, 0xde, 0x28, 0xf9, 0x8c, 0xbc, 0xc4, 0x27, 0x64, 0xf5, 0x0b, 0x2c, - 0xa9, 0xd1, 0x90, 0xbd, 0xeb, 0xa2, 0x16, 0x4b, 0x43, 0x99, 0x86, 0x04, 0xef, 0x0a, 0x35, 0xb9, - 0x6f, 0x02, 0x1c, 0x26, 0xe1, 0x78, 0xd3, 0xa3, 0xa3, 0x30, 0x48, 0x65, 0x6d, 0x7a, 0x7d, 0x22, - 0x95, 0x5f, 0xda, 0x1d, 0x0a, 0xf2, 0x52, 0xb3, 0xb2, 0x8c, 0x3b, 0x40, 0x92, 0xb8, 0xa6, 0xde, - 0xb0, 0x50, 0x0b, 0x52, 0x70, 0xcb, 0xe2, 0x91, 0x45, 0xd6, 0x00, 0xd2, 0x44, 0x02, 0x65, 0x33, - 0xe5, 0x72, 0x14, 0x94, 0xd8, 0x2b, 0xc8, 0x3a, 0x38, 0x80, 0x7a, 0x1a, 0x76, 0x5d, 0x4e, 0x5f, - 0x1f, 0x30, 0x82, 0xb4, 0xea, 0x04, 0xcf, 0x05, 0x43, 0xed, 0x0e, 0x2e, 0x15, 0x90, 0x1a, 0x5b, - 0x2a, 0x8c, 0x70, 0xfa, 0xb0, 0xc0, 0x07, 0xa8, 0xd4, 0x25, 0x4c, 0xfb, 0x57, 0x2f, 0x05, 0xe7, - 0x03, 0x92, 0x8a, 0x9b, 0x0b, 0xe3, 0x69, 0x86, 0xeb, 0x87, 0x51, 0x2b, 0xbf, 0x72, 0xc0, 0x44, - 0xf3, 0x08, 0xe6, 0x73, 0x21, 0x1a, 0xc5, 0xd2, 0xd3, 0x62, 0x70, 0x8a, 0xa5, 0xa7, 0x46, 0x77, - 0xec, 0xeb, 0xd8, 0xe5, 0x9c, 0x0d, 0x68, 0xea, 0x5d, 0xf8, 0x49, 0xff, 0x8c, 0x75, 0xf7, 0x47, - 0x16, 0x2c, 0x14, 0x44, 0x60, 0xc8, 0xbb, 0xd2, 0x6b, 0x30, 0x35, 0x3a, 0xd3, 0x2b, 0x74, 0xd0, - 0xdb, 0x87, 0xd8, 0xcf, 0x73, 0xf2, 0x89, 0x71, 0xb0, 0x71, 0xdf, 0xb8, 0xe0, 0xcc, 0x2b, 0x95, - 0x8a, 0x42, 0x8d, 0xe2, 0x53, 0x58, 0xe6, 0x03, 0x59, 0x1b, 0x0e, 0x33, 0xc1, 0x83, 0x3b, 0xb9, - 0x5f, 0x75, 0x35, 0x82, 0x22, 0xbd, 0xe9, 0xbf, 0xfa, 0x3a, 0x45, 0x9d, 0xe6, 0x43, 0x25, 0x13, - 0xe8, 0x64, 0x1d, 0xf2, 0x64, 0x7a, 0x5b, 0xbd, 0x77, 0x0c, 0xfb, 0xb7, 0xc0, 0x89, 0xff, 0x65, - 0xec, 0xec, 0x1d, 0xbb, 0x57, 0xb4, 0x2e, 0xdc, 0x24, 0x66, 0xfb, 0xf1, 0x57, 0x54, 0xf4, 0x20, - 0x33, 0x4f, 0xd9, 0xc1, 0xb4, 0x70, 0x87, 0xb2, 0xc0, 0x8b, 0x83, 0x0f, 0xef, 0x61, 0xf7, 0x77, - 0xed, 0x9b, 0x45, 0xdd, 0x47, 0xfc, 0x13, 0x6e, 0x8b, 0x2f, 0x67, 0xf9, 0x5a, 0x8e, 0xe0, 0x6e, - 0xd1, 0x7e, 0x4f, 0xb5, 0x85, 0x32, 0x6b, 0x7d, 0x0d, 0x75, 0xbb, 0xa6, 0x1e, 0x2d, 0x50, 0xec, - 0x53, 0x10, 0x96, 0x50, 0xec, 0x53, 0x14, 0x5e, 0x30, 0xf5, 0x1a, 0x19, 0x58, 0xf8, 0xd8, 0x7a, - 0xb0, 0xfe, 0xfe, 0x0f, 0xbe, 0x7c, 0xea, 0x27, 0x67, 0x93, 0xe3, 0x95, 0x7e, 0x38, 0x7a, 0x38, - 0x94, 0xde, 0x46, 0x71, 0x15, 0xee, 0xe1, 0x30, 0x18, 0x3c, 0xc4, 0x66, 0x8f, 0x67, 0xf0, 0x67, - 0xa8, 0xbf, 0xfe, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x3e, 0xee, 0x20, 0xb8, 0x7a, 0x00, - 0x00, + 0xd6, 0xce, 0xc8, 0xf2, 0x98, 0xd2, 0xd0, 0xf6, 0xac, 0x76, 0x94, 0xf5, 0x9a, 0x2f, 0x89, 0x9c, + 0xa1, 0x48, 0xba, 0x48, 0x59, 0x6b, 0x3b, 0x8b, 0x72, 0xb1, 0xfb, 0x92, 0x2c, 0xab, 0xbb, 0xaa, + 0xa7, 0xaa, 0x9a, 0x14, 0xed, 0x4c, 0x3e, 0x82, 0x24, 0x08, 0xf2, 0x13, 0x18, 0x8b, 0x00, 0xd9, + 0x3c, 0xb0, 0x80, 0x37, 0x41, 0x10, 0x04, 0x48, 0xf2, 0x15, 0x6c, 0x02, 0xe7, 0x2b, 0x1f, 0x9b, + 0x9f, 0x20, 0x1f, 0x09, 0x10, 0x20, 0x01, 0x02, 0x2c, 0x36, 0x1f, 0x59, 0x04, 0xc8, 0x57, 0x92, + 0xef, 0xe0, 0x9e, 0xfb, 0xa8, 0x7b, 0xab, 0xaa, 0x29, 0x8d, 0xed, 0xcc, 0x8f, 0xc4, 0x7b, 0xce, + 0xad, 0xfb, 0x3c, 0xe7, 0xdc, 0xf3, 0xba, 0xb7, 0xa1, 0x1e, 0x8d, 0xfb, 0x2b, 0xe3, 0x28, 0x4c, + 0x42, 0x52, 0x1d, 0x06, 0xd1, 0xb8, 0xdf, 0xbb, 0x75, 0x1a, 0x86, 0xa7, 0x43, 0xfa, 0xd0, 0x1b, + 0xfb, 0x0f, 0xbd, 0x20, 0x08, 0x13, 0x2f, 0xf1, 0xc3, 0x20, 0xe6, 0x95, 0xec, 0x1f, 0x41, 0xfb, + 0x19, 0x0d, 0x0e, 0x29, 0x1d, 0x38, 0xf4, 0xb3, 0x09, 0x8d, 0x13, 0xf2, 0x35, 0x98, 0xf7, 0xe8, + 0x4f, 0x28, 0x1d, 0xb8, 0x63, 0x2f, 0x8e, 0xc7, 0x67, 0x91, 0x17, 0xd3, 0xae, 0x75, 0xd7, 0xba, + 0xdf, 0x74, 0x3a, 0x1c, 0x71, 0xa0, 0xe0, 0xe4, 0x5d, 0x68, 0xc6, 0xac, 0x2a, 0x0d, 0x92, 0x28, + 0x1c, 0x5f, 0x76, 0x4b, 0x58, 0xaf, 0xc1, 0x60, 0x5b, 0x1c, 0x64, 0x0f, 0x61, 0x4e, 0xf5, 0x10, + 0x8f, 0xc3, 0x20, 0xa6, 0xe4, 0x11, 0x2c, 0xf6, 0xfd, 0xf1, 0x19, 0x8d, 0x5c, 0xfc, 0x78, 0x14, + 0xd0, 0x51, 0x18, 0xf8, 0xfd, 0xae, 0x75, 0xb7, 0x7c, 0xbf, 0xee, 0x10, 0x8e, 0x63, 0x5f, 0x3c, + 0x17, 0x18, 0xf2, 0x3e, 0xcc, 0xd1, 0x80, 0xc3, 0xe9, 0x00, 0xbf, 0x12, 0x5d, 0xb5, 0x53, 0x30, + 0xfb, 0xc0, 0xfe, 0x1b, 0x25, 0x98, 0xdf, 0x09, 0xfc, 0xe4, 0xa5, 0x37, 0x1c, 0xd2, 0x44, 0xce, + 0xe9, 0x7d, 0x98, 0xbb, 0x40, 0x00, 0xce, 0xe9, 0x22, 0x8c, 0x06, 0x62, 0x46, 0x6d, 0x0e, 0x3e, + 0x10, 0xd0, 0xa9, 0x23, 0x2b, 0x4d, 0x1d, 0x59, 0xe1, 0x72, 0x95, 0xa7, 0x2c, 0xd7, 0xfb, 0x30, + 0x17, 0xd1, 0x7e, 0x78, 0x4e, 0xa3, 0x4b, 0xf7, 0xc2, 0x0f, 0x06, 0xe1, 0x45, 0xb7, 0x72, 0xd7, + 0xba, 0x5f, 0x75, 0xda, 0x12, 0xfc, 0x12, 0xa1, 0x64, 0x1d, 0xe6, 0xfa, 0x67, 0x5e, 0x10, 0xd0, + 0xa1, 0x7b, 0xec, 0xf5, 0x5f, 0x4d, 0xc6, 0x71, 0xb7, 0x7a, 0xd7, 0xba, 0xdf, 0x58, 0xbd, 0xb1, + 0x82, 0xbb, 0xba, 0xb2, 0x71, 0xe6, 0x05, 0xeb, 0x88, 0x39, 0x0c, 0xbc, 0x71, 0x7c, 0x16, 0x26, + 0x4e, 0x5b, 0x7c, 0xc1, 0xc1, 0xb1, 0xbd, 0x08, 0x44, 0x5f, 0x09, 0xbe, 0xf6, 0xf6, 0x3f, 0xb5, + 0x60, 0xe1, 0x45, 0x30, 0x0c, 0xfb, 0xaf, 0x7e, 0xc9, 0x25, 0x2a, 0x98, 0x43, 0xe9, 0x6d, 0xe7, + 0x50, 0xfe, 0xa2, 0x73, 0x58, 0x82, 0x45, 0x73, 0xb0, 0x62, 0x16, 0x14, 0xae, 0xb3, 0xaf, 0x4f, + 0xa9, 0x1c, 0x96, 0x9c, 0xc6, 0x57, 0xa1, 0xd3, 0x9f, 0x44, 0x11, 0x0d, 0x72, 0xf3, 0x98, 0x13, + 0x70, 0x35, 0x91, 0x77, 0xa1, 0x19, 0xd0, 0x8b, 0xb4, 0x9a, 0xa0, 0xdd, 0x80, 0x5e, 0xc8, 0x2a, + 0x76, 0x17, 0x96, 0xb2, 0xdd, 0x88, 0x01, 0xfc, 0xa9, 0x05, 0x95, 0x17, 0xc9, 0xeb, 0x90, 0xac, + 0x40, 0x25, 0xb9, 0x1c, 0x73, 0x0e, 0x69, 0xaf, 0x12, 0x31, 0xb5, 0xb5, 0xc1, 0x20, 0xa2, 0x71, + 0x7c, 0x74, 0x39, 0xa6, 0x4e, 0xd3, 0xe3, 0x05, 0x97, 0xd5, 0x23, 0x5d, 0x98, 0x15, 0x65, 0xec, + 0xb0, 0xee, 0xc8, 0x22, 0xb9, 0x03, 0xe0, 0x8d, 0xc2, 0x49, 0x90, 0xb8, 0xb1, 0x97, 0xe0, 0x52, + 0x95, 0x1d, 0x0d, 0x42, 0x6e, 0x41, 0x7d, 0xfc, 0xca, 0x8d, 0xfb, 0x91, 0x3f, 0x4e, 0x90, 0x6c, + 0xea, 0x4e, 0x0a, 0x20, 0x5f, 0x83, 0x5a, 0x38, 0x49, 0xc6, 0xa1, 0x1f, 0x24, 0x82, 0x54, 0xe6, + 0xc4, 0x58, 0xf6, 0x27, 0xc9, 0x01, 0x03, 0x3b, 0xaa, 0x02, 0xb9, 0x07, 0xad, 0x7e, 0x18, 0x9c, + 0xf8, 0xd1, 0x88, 0x0b, 0x83, 0xee, 0x0c, 0xf6, 0x66, 0x02, 0xed, 0x7f, 0x55, 0x82, 0xc6, 0x51, + 0xe4, 0x05, 0xb1, 0xd7, 0x67, 0x00, 0x36, 0xf4, 0xe4, 0xb5, 0x7b, 0xe6, 0xc5, 0x67, 0x38, 0xdb, + 0xba, 0x23, 0x8b, 0x64, 0x09, 0x66, 0xf8, 0x40, 0x71, 0x4e, 0x65, 0x47, 0x94, 0xc8, 0x07, 0x30, + 0x1f, 0x4c, 0x46, 0xae, 0xd9, 0x57, 0x19, 0xa9, 0x25, 0x8f, 0x60, 0x0b, 0x70, 0xcc, 0xf6, 0x9a, + 0x77, 0xc1, 0x67, 0xa8, 0x41, 0x88, 0x0d, 0x4d, 0x51, 0xa2, 0xfe, 0xe9, 0x19, 0x9f, 0x66, 0xd5, + 0x31, 0x60, 0xac, 0x8d, 0xc4, 0x1f, 0x51, 0x37, 0x4e, 0xbc, 0xd1, 0x58, 0x4c, 0x4b, 0x83, 0x20, + 0x3e, 0x4c, 0xbc, 0xa1, 0x7b, 0x42, 0x69, 0xdc, 0x9d, 0x15, 0x78, 0x05, 0x21, 0xef, 0x41, 0x7b, + 0x40, 0xe3, 0xc4, 0x15, 0x9b, 0x42, 0xe3, 0x6e, 0x0d, 0x59, 0x3f, 0x03, 0x65, 0xed, 0x44, 0xde, + 0x85, 0xcb, 0x16, 0x80, 0xbe, 0xee, 0xd6, 0xf9, 0x58, 0x53, 0x08, 0xa3, 0x9c, 0x67, 0x34, 0xd1, + 0x56, 0x2f, 0x16, 0x14, 0x6a, 0xef, 0x02, 0xd1, 0xc0, 0x9b, 0x34, 0xf1, 0xfc, 0x61, 0x4c, 0x3e, + 0x82, 0x66, 0xa2, 0x55, 0x46, 0x51, 0xd8, 0x50, 0xe4, 0xa4, 0x7d, 0xe0, 0x18, 0xf5, 0xec, 0x33, + 0xa8, 0x3d, 0xa5, 0x74, 0xd7, 0x1f, 0xf9, 0x09, 0x59, 0x82, 0xea, 0x89, 0xff, 0x9a, 0x72, 0x82, + 0x2f, 0x6f, 0x5f, 0x73, 0x78, 0x91, 0xbc, 0x03, 0x80, 0x7f, 0xb8, 0x23, 0x45, 0x58, 0xdb, 0xd7, + 0x9c, 0x3a, 0xc2, 0x9e, 0x33, 0xca, 0xea, 0xc1, 0xec, 0x98, 0x46, 0x7d, 0x2a, 0xf7, 0x6f, 0xfb, + 0x9a, 0x23, 0x01, 0xeb, 0xb3, 0x50, 0x1d, 0xb2, 0xd6, 0xed, 0x3f, 0xa9, 0x42, 0xe3, 0x90, 0x06, + 0x8a, 0xd3, 0x08, 0x54, 0xd8, 0x9a, 0x08, 0xee, 0xc2, 0xbf, 0xc9, 0x57, 0xa0, 0x81, 0xeb, 0x14, + 0x27, 0x91, 0x1f, 0x9c, 0x72, 0x02, 0x5f, 0x2f, 0x75, 0x2d, 0x07, 0x18, 0xf8, 0x10, 0xa1, 0xa4, + 0x03, 0x65, 0x6f, 0x24, 0x09, 0x9c, 0xfd, 0x49, 0x6e, 0x40, 0xcd, 0x1b, 0x25, 0x7c, 0x78, 0x4d, + 0x04, 0xcf, 0x7a, 0xa3, 0x04, 0x87, 0xf6, 0x2e, 0x34, 0xc7, 0xde, 0xe5, 0x88, 0xf1, 0xb3, 0xa2, + 0x8a, 0xa6, 0xd3, 0x10, 0xb0, 0x6d, 0x46, 0x16, 0xab, 0xb0, 0xa0, 0x57, 0x91, 0x9d, 0x57, 0x55, + 0xe7, 0xf3, 0x5a, 0x6d, 0x31, 0x86, 0xf7, 0x61, 0x4e, 0x7e, 0x13, 0xf1, 0xf9, 0x20, 0xad, 0xd4, + 0x9d, 0xb6, 0x00, 0xcb, 0x59, 0xde, 0x87, 0xce, 0x89, 0x1f, 0x78, 0x43, 0xb7, 0x3f, 0x4c, 0xce, + 0xdd, 0x01, 0x1d, 0x26, 0x1e, 0x52, 0x4d, 0xd5, 0x69, 0x23, 0x7c, 0x63, 0x98, 0x9c, 0x6f, 0x32, + 0x28, 0xf9, 0x00, 0xea, 0x27, 0x94, 0xba, 0xb8, 0x58, 0xdd, 0x9a, 0xc1, 0x81, 0x72, 0x87, 0x9c, + 0xda, 0x89, 0xdc, 0xab, 0x0f, 0xa0, 0x13, 0x4e, 0x92, 0xd3, 0xd0, 0x0f, 0x4e, 0x5d, 0x26, 0xf3, + 0x5c, 0x7f, 0x80, 0x54, 0x54, 0x59, 0x2f, 0x3d, 0xb2, 0x9c, 0xb6, 0xc4, 0x31, 0xe9, 0xb3, 0x33, + 0x20, 0xef, 0xc1, 0xdc, 0xd0, 0x8b, 0x13, 0xf7, 0x2c, 0x1c, 0xbb, 0xe3, 0xc9, 0xf1, 0x2b, 0x7a, + 0xd9, 0x6d, 0xe1, 0x42, 0xb4, 0x18, 0x78, 0x3b, 0x1c, 0x1f, 0x20, 0x90, 0xdc, 0x06, 0xc0, 0x71, + 0xf2, 0x41, 0xc0, 0x5d, 0xeb, 0x7e, 0xcb, 0xa9, 0x33, 0x08, 0xef, 0xf4, 0xfb, 0xb0, 0x80, 0xdb, + 0xd3, 0x9f, 0xc4, 0x49, 0x38, 0x72, 0x99, 0xbc, 0x8e, 0x06, 0x71, 0xb7, 0x81, 0xb4, 0xf6, 0x55, + 0x31, 0x58, 0x6d, 0x8f, 0x57, 0x36, 0x69, 0x9c, 0x6c, 0x60, 0x65, 0x87, 0xd7, 0x65, 0x87, 0xfa, + 0xa5, 0x33, 0x3f, 0xc8, 0xc2, 0xc9, 0x07, 0x40, 0xbc, 0xe1, 0x30, 0xbc, 0x70, 0x63, 0x3a, 0x3c, + 0x71, 0xc5, 0x22, 0x76, 0xdb, 0x77, 0xad, 0xfb, 0x35, 0xa7, 0x83, 0x98, 0x43, 0x3a, 0x3c, 0x39, + 0xe0, 0x70, 0xf2, 0x11, 0xb4, 0x70, 0x20, 0x27, 0xd4, 0x4b, 0x26, 0x11, 0x8d, 0xbb, 0x73, 0x77, + 0xcb, 0xf7, 0xdb, 0xab, 0xf3, 0x6a, 0xbd, 0x10, 0xbc, 0xee, 0x27, 0x4e, 0x93, 0xd5, 0x13, 0xe5, + 0xb8, 0xb7, 0x09, 0x4b, 0xc5, 0x43, 0x62, 0x44, 0xc5, 0x56, 0x85, 0x11, 0x63, 0xc5, 0x61, 0x7f, + 0x92, 0x45, 0xa8, 0x9e, 0x7b, 0xc3, 0x09, 0x15, 0x72, 0x9d, 0x17, 0x3e, 0x2e, 0x3d, 0xb6, 0xec, + 0x3f, 0xb6, 0xa0, 0xc9, 0x67, 0x29, 0xf4, 0x91, 0x7b, 0xd0, 0x92, 0xd4, 0x40, 0xa3, 0x28, 0x8c, + 0x84, 0x78, 0x33, 0x81, 0xe4, 0x01, 0x74, 0x24, 0x60, 0x1c, 0x51, 0x7f, 0xe4, 0x9d, 0xca, 0xb6, + 0x73, 0x70, 0xb2, 0x9a, 0xb6, 0x18, 0x85, 0x93, 0x84, 0x8a, 0x93, 0xaf, 0x29, 0x26, 0xe8, 0x30, + 0x98, 0x63, 0x56, 0x61, 0xe2, 0xad, 0x80, 0xd4, 0x0d, 0x98, 0xfd, 0xb7, 0x2d, 0x20, 0x6c, 0xe8, + 0x47, 0x21, 0x6f, 0x42, 0x50, 0x69, 0x96, 0x4b, 0xac, 0xb7, 0xe6, 0x92, 0xd2, 0x55, 0x5c, 0x62, + 0x43, 0x95, 0x8f, 0xbe, 0x52, 0x30, 0x7a, 0x8e, 0xfa, 0xa4, 0x52, 0x2b, 0x77, 0x2a, 0xf6, 0x7f, + 0x29, 0xc3, 0xe2, 0x06, 0x3f, 0xba, 0xd7, 0xfa, 0x7d, 0x3a, 0x56, 0xfc, 0xf3, 0x0e, 0x34, 0x82, + 0x70, 0x40, 0x25, 0xd5, 0xf2, 0x81, 0x01, 0x03, 0x69, 0x24, 0x7b, 0xe6, 0xf9, 0x01, 0x1f, 0x38, + 0x5f, 0xcf, 0x3a, 0x42, 0x70, 0xd8, 0xef, 0xc1, 0xdc, 0x98, 0x06, 0x03, 0x9d, 0x4d, 0xb8, 0x72, + 0xd5, 0x12, 0x60, 0xc1, 0x21, 0xef, 0x40, 0xe3, 0x64, 0xc2, 0xeb, 0x31, 0xe1, 0x52, 0x41, 0x3a, + 0x00, 0x01, 0x5a, 0xe3, 0x32, 0x66, 0x3c, 0x89, 0xcf, 0x10, 0x5b, 0x45, 0xec, 0x2c, 0x2b, 0x33, + 0xd4, 0x6d, 0x80, 0xc1, 0x24, 0x4e, 0x04, 0xd7, 0xcc, 0x20, 0xb2, 0xce, 0x20, 0x9c, 0x6b, 0xbe, + 0x0e, 0x0b, 0x23, 0xef, 0xb5, 0x8b, 0xf4, 0xe3, 0xfa, 0x81, 0x7b, 0x32, 0xc4, 0xd3, 0x67, 0x16, + 0xeb, 0x75, 0x46, 0xde, 0xeb, 0xef, 0x31, 0xcc, 0x4e, 0xf0, 0x14, 0xe1, 0x4c, 0xb4, 0x48, 0xb5, + 0x27, 0xa2, 0x31, 0x8d, 0xce, 0x29, 0x4a, 0x83, 0x8a, 0xd2, 0x6d, 0x1c, 0x0e, 0x65, 0x23, 0x1a, + 0xb1, 0x79, 0x27, 0xc3, 0x3e, 0x67, 0x7d, 0x67, 0x76, 0xe4, 0x07, 0xdb, 0xc9, 0xb0, 0x4f, 0x6e, + 0x01, 0x30, 0x59, 0x32, 0xa6, 0x91, 0xfb, 0xea, 0x02, 0xf9, 0xb8, 0x82, 0xb2, 0xe3, 0x80, 0x46, + 0x9f, 0x5e, 0x90, 0x9b, 0x50, 0xef, 0xc7, 0x28, 0x8c, 0xbc, 0xcb, 0x6e, 0x03, 0x99, 0xbc, 0xd6, + 0x8f, 0x99, 0x18, 0xf2, 0x2e, 0x19, 0x23, 0xb2, 0xd1, 0x7a, 0xb8, 0x0b, 0x74, 0x80, 0xcd, 0xc7, + 0x28, 0x55, 0x5b, 0x38, 0xd8, 0x35, 0x81, 0x60, 0xfd, 0xc4, 0xe4, 0x2b, 0xd0, 0x92, 0x83, 0x3d, + 0x19, 0x7a, 0xa7, 0x31, 0x8a, 0x95, 0x96, 0xd3, 0x14, 0xc0, 0xa7, 0x0c, 0x66, 0xbf, 0xe4, 0xca, + 0x96, 0xb6, 0xb7, 0x82, 0x6f, 0xd8, 0xb1, 0x8f, 0x10, 0xdc, 0xd7, 0x9a, 0x23, 0x4a, 0x45, 0x9b, + 0x56, 0x2a, 0xd8, 0x34, 0xfb, 0xe7, 0x16, 0x34, 0x45, 0xcb, 0xa8, 0xa1, 0x90, 0x47, 0x40, 0xe4, + 0x2e, 0x26, 0xaf, 0xfd, 0x81, 0x7b, 0x7c, 0x99, 0xd0, 0x98, 0x13, 0xcd, 0xf6, 0x35, 0xa7, 0x00, + 0xc7, 0xe4, 0xa8, 0x01, 0x8d, 0x93, 0x88, 0xd3, 0xf4, 0xf6, 0x35, 0x27, 0x87, 0x61, 0x2c, 0xc6, + 0x74, 0xa0, 0x49, 0xe2, 0xfa, 0xc1, 0x80, 0xbe, 0x46, 0x52, 0x6a, 0x39, 0x06, 0x6c, 0xbd, 0x0d, + 0x4d, 0xfd, 0x3b, 0xfb, 0xc7, 0x50, 0x93, 0x1a, 0x14, 0x6a, 0x0f, 0x99, 0x71, 0x39, 0x1a, 0x84, + 0xf4, 0xa0, 0x66, 0x8e, 0xc2, 0xa9, 0x7d, 0x91, 0xbe, 0xed, 0x6f, 0x43, 0x67, 0x97, 0x11, 0x51, + 0xc0, 0x88, 0x56, 0xa8, 0x85, 0x4b, 0x30, 0xa3, 0x31, 0x4f, 0xdd, 0x11, 0x25, 0x76, 0xfe, 0x9e, + 0x85, 0x71, 0x22, 0xfa, 0xc1, 0xbf, 0xed, 0x3f, 0xb1, 0x80, 0x6c, 0xc5, 0x89, 0x3f, 0xf2, 0x12, + 0xfa, 0x94, 0x2a, 0xf1, 0xb0, 0x0f, 0x4d, 0xd6, 0xda, 0x51, 0xb8, 0xc6, 0x95, 0x34, 0xae, 0x5c, + 0x7c, 0x4d, 0xb0, 0x73, 0xfe, 0x83, 0x15, 0xbd, 0x36, 0x17, 0xf9, 0x46, 0x03, 0x8c, 0xdb, 0x12, + 0x2f, 0x3a, 0xa5, 0x09, 0x6a, 0x70, 0x42, 0xff, 0x07, 0x0e, 0xda, 0x08, 0x83, 0x93, 0xde, 0xef, + 0xc0, 0x7c, 0xae, 0x0d, 0x5d, 0x46, 0xd7, 0x0b, 0x64, 0x74, 0x59, 0x97, 0xd1, 0x7d, 0x58, 0x30, + 0xc6, 0x25, 0x28, 0xae, 0x0b, 0xb3, 0x8c, 0x31, 0x98, 0xa2, 0x60, 0x71, 0x45, 0x41, 0x14, 0xc9, + 0x2a, 0x2c, 0x9e, 0x50, 0x1a, 0x79, 0x09, 0x16, 0x91, 0x75, 0xd8, 0x9e, 0x88, 0x96, 0x0b, 0x71, + 0xf6, 0x9f, 0x59, 0x30, 0xc7, 0xa4, 0xe9, 0x73, 0x2f, 0xb8, 0x94, 0x6b, 0xb5, 0x5b, 0xb8, 0x56, + 0xf7, 0xb5, 0xc3, 0x51, 0xab, 0xfd, 0x45, 0x17, 0xaa, 0x9c, 0x5d, 0x28, 0x72, 0x17, 0x9a, 0xc6, + 0x70, 0xab, 0x5c, 0x23, 0x8d, 0xbd, 0xe4, 0x80, 0x46, 0xeb, 0x97, 0x09, 0xfd, 0xd5, 0x97, 0xf2, + 0x3d, 0xe8, 0xa4, 0xc3, 0x16, 0xeb, 0x48, 0xa0, 0xc2, 0x08, 0x53, 0x34, 0x80, 0x7f, 0xdb, 0x7f, + 0xdf, 0xe2, 0x15, 0x37, 0x42, 0x5f, 0x69, 0xab, 0xac, 0x22, 0x53, 0x7a, 0x65, 0x45, 0xf6, 0xf7, + 0x54, 0x6d, 0xff, 0x57, 0x9f, 0x2c, 0x93, 0x89, 0x31, 0x0d, 0x06, 0xae, 0x37, 0x1c, 0xa2, 0x20, + 0xae, 0x39, 0xb3, 0xac, 0xbc, 0x36, 0x1c, 0xda, 0xef, 0xc3, 0xbc, 0x36, 0xba, 0x2b, 0xe6, 0xb1, + 0x07, 0x64, 0xd7, 0x8f, 0x93, 0x17, 0x41, 0x3c, 0xd6, 0x14, 0xb9, 0x9b, 0x50, 0x67, 0xd2, 0x96, + 0x8d, 0x8c, 0x73, 0x6e, 0xd5, 0x61, 0xe2, 0x97, 0x8d, 0x2b, 0x46, 0xa4, 0xf7, 0x5a, 0x20, 0x4b, + 0x02, 0xe9, 0xbd, 0x46, 0xa4, 0xfd, 0x18, 0x16, 0x8c, 0xf6, 0x44, 0xd7, 0xef, 0x42, 0x75, 0x92, + 0xbc, 0x0e, 0xa5, 0xaa, 0xde, 0x10, 0x14, 0xc2, 0x8c, 0x42, 0x87, 0x63, 0xec, 0x27, 0x30, 0xbf, + 0x47, 0x2f, 0x04, 0x23, 0xcb, 0x81, 0xbc, 0xf7, 0x46, 0x83, 0x11, 0xf1, 0xf6, 0x0a, 0x10, 0xfd, + 0xe3, 0x94, 0x01, 0xa4, 0xf9, 0x68, 0x19, 0xe6, 0xa3, 0xfd, 0x1e, 0x90, 0x43, 0xff, 0x34, 0x78, + 0x4e, 0xe3, 0xd8, 0x3b, 0x55, 0xac, 0xdf, 0x81, 0xf2, 0x28, 0x3e, 0x15, 0xa2, 0x8a, 0xfd, 0x69, + 0x7f, 0x03, 0x16, 0x8c, 0x7a, 0xa2, 0xe1, 0x5b, 0x50, 0x8f, 0xfd, 0xd3, 0x00, 0x15, 0x2d, 0xd1, + 0x74, 0x0a, 0xb0, 0x9f, 0xc2, 0xe2, 0xf7, 0x68, 0xe4, 0x9f, 0x5c, 0xbe, 0xa9, 0x79, 0xb3, 0x9d, + 0x52, 0xb6, 0x9d, 0x2d, 0xb8, 0x9e, 0x69, 0x47, 0x74, 0xcf, 0xc9, 0x57, 0xec, 0x64, 0xcd, 0xe1, + 0x05, 0x4d, 0xf6, 0x95, 0x74, 0xd9, 0x67, 0xbf, 0x00, 0xb2, 0x11, 0x06, 0x01, 0xed, 0x27, 0x07, + 0x94, 0x46, 0xa9, 0xe7, 0x2a, 0xa5, 0xd5, 0xc6, 0xea, 0xb2, 0x58, 0xd9, 0xac, 0x40, 0x15, 0x44, + 0x4c, 0xa0, 0x32, 0xa6, 0xd1, 0x08, 0x1b, 0xae, 0x39, 0xf8, 0xb7, 0x7d, 0x1d, 0x16, 0x8c, 0x66, + 0x85, 0xad, 0xff, 0x21, 0x5c, 0xdf, 0xf4, 0xe3, 0x7e, 0xbe, 0xc3, 0x2e, 0xcc, 0x8e, 0x27, 0xc7, + 0x6e, 0xca, 0x89, 0xb2, 0xc8, 0xcc, 0xbf, 0xec, 0x27, 0xa2, 0xb1, 0xbf, 0x6e, 0x41, 0x65, 0xfb, + 0x68, 0x77, 0x83, 0x9d, 0x15, 0x7e, 0xd0, 0x0f, 0x47, 0x4c, 0x0b, 0xe3, 0x93, 0x56, 0xe5, 0xa9, + 0x1c, 0x76, 0x0b, 0xea, 0xa8, 0xbc, 0x31, 0x8b, 0x57, 0xe8, 0x41, 0x29, 0x80, 0x59, 0xdb, 0xf4, + 0xf5, 0xd8, 0x8f, 0xd0, 0x9c, 0x96, 0x46, 0x72, 0x05, 0x8f, 0x99, 0x3c, 0xc2, 0xfe, 0x77, 0xb3, + 0x30, 0x2b, 0x0e, 0x5f, 0x7e, 0x90, 0x27, 0xfe, 0x39, 0x4d, 0x0f, 0x72, 0x56, 0x62, 0x8a, 0x71, + 0x44, 0x47, 0x61, 0xa2, 0xf4, 0x37, 0xbe, 0x0d, 0x26, 0x10, 0xbd, 0x09, 0x42, 0x89, 0xe0, 0xfe, + 0x87, 0x32, 0xaf, 0x65, 0x00, 0xc9, 0x2d, 0x98, 0x95, 0xca, 0x40, 0x45, 0x19, 0x3a, 0x12, 0xc4, + 0x56, 0xa3, 0xef, 0x8d, 0xbd, 0xbe, 0x9f, 0x5c, 0x0a, 0xb1, 0xa0, 0xca, 0xac, 0xfd, 0x61, 0xd8, + 0xf7, 0x86, 0xee, 0xb1, 0x37, 0xf4, 0x82, 0x3e, 0x95, 0xde, 0x0a, 0x03, 0xc8, 0x2c, 0x77, 0x31, + 0x2c, 0x59, 0x8d, 0x5b, 0xf7, 0x19, 0x28, 0x3b, 0xc3, 0xfb, 0xe1, 0x68, 0xe4, 0x33, 0xeb, 0x83, + 0xab, 0x66, 0x65, 0x47, 0x83, 0x70, 0xdf, 0x08, 0x96, 0x2e, 0xf8, 0x0a, 0xd6, 0xa5, 0x6f, 0x44, + 0x03, 0xb2, 0x56, 0x32, 0x1a, 0x5a, 0xd9, 0xd1, 0x20, 0x6c, 0x2f, 0x26, 0x41, 0x4c, 0x93, 0x64, + 0x48, 0x07, 0x6a, 0x40, 0x0d, 0xac, 0x96, 0x47, 0x90, 0x47, 0xb0, 0xc0, 0x7d, 0x10, 0xb1, 0x97, + 0x84, 0xf1, 0x99, 0x1f, 0xbb, 0x31, 0x33, 0x9f, 0xb8, 0x2d, 0x5c, 0x84, 0x22, 0x8f, 0x61, 0x39, + 0x03, 0x8e, 0x68, 0x9f, 0xfa, 0xe7, 0x74, 0x80, 0x2a, 0x5c, 0xd9, 0x99, 0x86, 0x26, 0x77, 0xa1, + 0x11, 0x4c, 0x46, 0xee, 0x64, 0x3c, 0xf0, 0x98, 0x12, 0xd3, 0x46, 0xe5, 0x52, 0x07, 0x91, 0x0f, + 0x41, 0xea, 0x69, 0x42, 0x7b, 0x9c, 0x33, 0x24, 0x1c, 0xa3, 0x5e, 0xc7, 0xac, 0xc1, 0x08, 0x33, + 0x55, 0x49, 0x3b, 0xc2, 0xee, 0x94, 0x00, 0xe4, 0x93, 0xc8, 0x3f, 0xf7, 0x12, 0xda, 0x9d, 0xe7, + 0x42, 0x5d, 0x14, 0xd9, 0x77, 0x7e, 0xe0, 0x27, 0xbe, 0x97, 0x84, 0x51, 0x97, 0x20, 0x2e, 0x05, + 0xb0, 0x45, 0x44, 0xfa, 0x88, 0x13, 0x2f, 0x99, 0xc4, 0x42, 0x43, 0x5d, 0x40, 0xe2, 0xca, 0x23, + 0xc8, 0x47, 0xb0, 0xc4, 0x29, 0x02, 0x51, 0x42, 0xf7, 0x46, 0x55, 0x61, 0x11, 0x57, 0x64, 0x0a, + 0x96, 0x2d, 0xa5, 0x20, 0x91, 0xdc, 0x87, 0xd7, 0xf9, 0x52, 0x4e, 0x41, 0xb3, 0xf1, 0xb1, 0x11, + 0xf8, 0x7d, 0x57, 0xd4, 0x60, 0x2c, 0xb2, 0x84, 0xb3, 0xc8, 0x23, 0x18, 0x89, 0x0f, 0xfd, 0x13, + 0x9a, 0xf8, 0x23, 0xda, 0x5d, 0xe6, 0x24, 0x2e, 0xcb, 0x8c, 0x01, 0x27, 0x63, 0xc4, 0x74, 0x39, + 0xc3, 0xf3, 0x12, 0x12, 0xe3, 0x30, 0x8c, 0xa9, 0xf4, 0x3c, 0x75, 0x6f, 0x08, 0xd6, 0xd2, 0x81, + 0xf6, 0x1f, 0x5a, 0xfc, 0x88, 0x12, 0xec, 0x1c, 0x6b, 0xc6, 0x17, 0x67, 0x64, 0x37, 0x0c, 0x86, + 0x97, 0x82, 0xb7, 0x81, 0x83, 0xf6, 0x83, 0xe1, 0x25, 0x53, 0xff, 0xfd, 0x40, 0xaf, 0xc2, 0xa5, + 0x61, 0x53, 0x02, 0xb1, 0xd2, 0x3b, 0xd0, 0x18, 0x4f, 0x8e, 0x87, 0x7e, 0x9f, 0x57, 0x29, 0xf3, + 0x56, 0x38, 0x08, 0x2b, 0x30, 0xeb, 0x93, 0xef, 0x27, 0xaf, 0x51, 0xc1, 0x1a, 0x0d, 0x01, 0x63, + 0x55, 0xec, 0x75, 0x58, 0x34, 0x07, 0x28, 0xc4, 0xfe, 0x03, 0xa8, 0x09, 0x29, 0x21, 0xdd, 0x10, + 0x6d, 0xcd, 0x39, 0xcc, 0x8c, 0x25, 0x85, 0xb7, 0xff, 0x75, 0x05, 0x16, 0x04, 0x74, 0x83, 0x4d, + 0xff, 0x70, 0x32, 0x1a, 0x79, 0x51, 0x81, 0xf8, 0xb1, 0xde, 0x20, 0x7e, 0x4a, 0x79, 0xf1, 0x73, + 0xc7, 0xb0, 0x42, 0xb9, 0xfc, 0xd2, 0x20, 0xe4, 0x3e, 0xcc, 0xb1, 0x25, 0xe7, 0x46, 0x81, 0xee, + 0x9f, 0xcc, 0x82, 0xf3, 0x22, 0xb3, 0x5a, 0x24, 0x32, 0x75, 0x71, 0x37, 0x93, 0x11, 0x77, 0x36, + 0x34, 0xf9, 0xf6, 0x0a, 0x09, 0x3e, 0x2b, 0x4c, 0x32, 0x0d, 0xc6, 0xc6, 0x93, 0x15, 0x2e, 0x5c, + 0x92, 0xcd, 0x15, 0x89, 0x16, 0x7f, 0x44, 0xf1, 0x84, 0xd0, 0x6a, 0xd7, 0x85, 0x68, 0xc9, 0xa3, + 0xc8, 0x53, 0x00, 0xde, 0x17, 0xaa, 0x29, 0x80, 0x6a, 0xca, 0x7b, 0xe6, 0xae, 0xe8, 0xeb, 0xbf, + 0xc2, 0x0a, 0x93, 0x88, 0xa2, 0xea, 0xa2, 0x7d, 0x69, 0xff, 0x4d, 0x0b, 0x1a, 0x1a, 0x8e, 0x5c, + 0x87, 0xf9, 0x8d, 0xfd, 0xfd, 0x83, 0x2d, 0x67, 0xed, 0x68, 0xe7, 0x7b, 0x5b, 0xee, 0xc6, 0xee, + 0xfe, 0xe1, 0x56, 0xe7, 0x1a, 0x03, 0xef, 0xee, 0x6f, 0xac, 0xed, 0xba, 0x4f, 0xf7, 0x9d, 0x0d, + 0x09, 0xb6, 0xc8, 0x12, 0x10, 0x67, 0xeb, 0xf9, 0xfe, 0xd1, 0x96, 0x01, 0x2f, 0x91, 0x0e, 0x34, + 0xd7, 0x9d, 0xad, 0xb5, 0x8d, 0x6d, 0x01, 0x29, 0x93, 0x45, 0xe8, 0x3c, 0x7d, 0xb1, 0xb7, 0xb9, + 0xb3, 0xf7, 0xcc, 0xdd, 0x58, 0xdb, 0xdb, 0xd8, 0xda, 0xdd, 0xda, 0xec, 0x54, 0x48, 0x0b, 0xea, + 0x6b, 0xeb, 0x6b, 0x7b, 0x9b, 0xfb, 0x7b, 0x5b, 0x9b, 0x9d, 0xaa, 0xfd, 0xdf, 0x2c, 0xb8, 0x8e, + 0xa3, 0x1e, 0x64, 0x99, 0xe4, 0x2e, 0x34, 0xfa, 0x61, 0x38, 0x66, 0xe6, 0x41, 0x7a, 0x00, 0xea, + 0x20, 0xc6, 0x00, 0x5c, 0x74, 0x9c, 0x84, 0x51, 0x9f, 0x0a, 0x1e, 0x01, 0x04, 0x3d, 0x65, 0x10, + 0xc6, 0x00, 0x62, 0x7b, 0x79, 0x0d, 0xce, 0x22, 0x0d, 0x0e, 0xe3, 0x55, 0x96, 0x60, 0xe6, 0x38, + 0xa2, 0x5e, 0xff, 0x4c, 0x70, 0x87, 0x28, 0x91, 0xaf, 0xa6, 0xf6, 0x6b, 0x9f, 0xad, 0xfe, 0x90, + 0x0e, 0x90, 0x62, 0x6a, 0xce, 0x9c, 0x80, 0x6f, 0x08, 0x30, 0x93, 0x95, 0xde, 0xb1, 0x17, 0x0c, + 0xc2, 0x80, 0x0e, 0x84, 0x72, 0x9c, 0x02, 0xec, 0x03, 0x58, 0xca, 0xce, 0x4f, 0xf0, 0xd8, 0x47, + 0x1a, 0x8f, 0x71, 0x5d, 0xb5, 0x37, 0x7d, 0x37, 0x35, 0x7e, 0xfb, 0xb3, 0x32, 0x54, 0x98, 0xea, + 0x32, 0x5d, 0xcd, 0xd1, 0xb5, 0xd1, 0x72, 0x2e, 0x98, 0x81, 0x26, 0x31, 0x3f, 0xc8, 0x84, 0x3b, + 0x26, 0x85, 0xa4, 0xf8, 0x88, 0xf6, 0xcf, 0x85, 0x43, 0x46, 0x83, 0x30, 0x06, 0x61, 0xa6, 0x02, + 0x7e, 0x2d, 0x18, 0x44, 0x96, 0x25, 0x0e, 0xbf, 0x9c, 0x4d, 0x71, 0xf8, 0x5d, 0x17, 0x66, 0xfd, + 0xe0, 0x38, 0x9c, 0x04, 0x03, 0x64, 0x88, 0x9a, 0x23, 0x8b, 0x18, 0x3e, 0x41, 0x46, 0x65, 0x52, + 0x96, 0x93, 0x7f, 0x0a, 0x20, 0xab, 0x50, 0x8f, 0x2f, 0x83, 0xbe, 0x4e, 0xf3, 0x8b, 0x62, 0x95, + 0xd8, 0x1a, 0xac, 0x1c, 0x5e, 0x06, 0x7d, 0xa4, 0xf0, 0xb4, 0x1a, 0xf9, 0x16, 0xd4, 0x94, 0x03, + 0x93, 0x0b, 0xaf, 0x1b, 0xfa, 0x27, 0xd2, 0x6b, 0xc9, 0xed, 0x42, 0x55, 0xb5, 0xf7, 0x29, 0xb4, + 0x0c, 0x94, 0x6e, 0xcc, 0xb5, 0xb8, 0x31, 0x77, 0x4f, 0x37, 0xe6, 0x52, 0x99, 0x28, 0x3e, 0xd3, + 0x8d, 0xbb, 0xdf, 0x81, 0x9a, 0x1c, 0x1a, 0x63, 0x8d, 0x17, 0x7b, 0x9f, 0xee, 0xed, 0xbf, 0xdc, + 0x73, 0x0f, 0xbf, 0xbf, 0xb7, 0xd1, 0xb9, 0x46, 0xe6, 0xa0, 0xb1, 0xb6, 0x81, 0xdc, 0x86, 0x00, + 0x8b, 0x55, 0x39, 0x58, 0x3b, 0x3c, 0x54, 0x90, 0x92, 0x4d, 0xa0, 0xc3, 0x24, 0x33, 0x1b, 0xb1, + 0x0a, 0x51, 0x7c, 0x04, 0xf3, 0x1a, 0x2c, 0xb5, 0x77, 0xc6, 0x0c, 0x90, 0xb1, 0x77, 0x50, 0xb9, + 0xe5, 0x18, 0x7b, 0x19, 0xae, 0xb3, 0xe2, 0xd6, 0x39, 0x0d, 0x92, 0xc3, 0xc9, 0x31, 0x8f, 0x4c, + 0xf9, 0x61, 0x60, 0xff, 0x35, 0x0b, 0xea, 0x0a, 0x73, 0x05, 0x3d, 0xc9, 0x60, 0x5a, 0x09, 0x37, + 0xa0, 0xa7, 0x75, 0x81, 0x5f, 0xae, 0xe0, 0xbf, 0x86, 0x8d, 0x54, 0x57, 0x20, 0x36, 0xd9, 0x83, + 0xad, 0x2d, 0xc7, 0xdd, 0xdf, 0xdb, 0xdd, 0xd9, 0x63, 0x92, 0x85, 0x4d, 0x16, 0x01, 0x4f, 0x9f, + 0x22, 0xc4, 0xb2, 0x3b, 0xd0, 0x7e, 0x46, 0x93, 0x9d, 0xe0, 0x24, 0x94, 0x53, 0xfd, 0xbf, 0x55, + 0x98, 0x53, 0xa0, 0xd4, 0xc6, 0x3a, 0xa7, 0x51, 0xec, 0x87, 0x01, 0x6a, 0x47, 0x75, 0x47, 0x16, + 0x99, 0xd8, 0xf5, 0x07, 0x34, 0x48, 0xfc, 0xe4, 0xd2, 0x35, 0x9c, 0x32, 0x59, 0x30, 0xb3, 0x67, + 0xbc, 0xa1, 0xef, 0xc9, 0x20, 0x1f, 0x2f, 0x30, 0x68, 0x3f, 0x1c, 0x86, 0x11, 0xaa, 0x41, 0x75, + 0x87, 0x17, 0xc8, 0x2a, 0x2c, 0x32, 0xf5, 0x4b, 0x77, 0x99, 0x21, 0xb3, 0x72, 0x0f, 0x51, 0x21, + 0x8e, 0x89, 0x75, 0x06, 0x17, 0x67, 0xb7, 0xfa, 0x84, 0x6b, 0xfb, 0x45, 0x28, 0xf2, 0x4d, 0xb8, + 0xce, 0xc0, 0xea, 0xbc, 0x57, 0xdf, 0xcc, 0xe1, 0x37, 0xc5, 0x48, 0xc6, 0x35, 0xbc, 0x7f, 0xb6, + 0xf3, 0x55, 0xae, 0xd8, 0x29, 0x40, 0x2e, 0x22, 0x37, 0xc3, 0x8f, 0xaa, 0x6c, 0x44, 0x4e, 0x8b, + 0xea, 0xd5, 0x72, 0x51, 0xbd, 0x6f, 0xc2, 0xf5, 0x63, 0x1a, 0x27, 0xee, 0x19, 0xf5, 0x06, 0x34, + 0x42, 0x6e, 0xe4, 0xc1, 0x3b, 0xae, 0xc7, 0x16, 0x23, 0xf1, 0x00, 0xbc, 0x0c, 0xfa, 0x74, 0xe0, + 0x26, 0xa1, 0x8b, 0x07, 0x35, 0xf2, 0x74, 0xcd, 0xc9, 0x82, 0xcd, 0x9a, 0xa7, 0x91, 0x37, 0x3e, + 0x13, 0x8a, 0x66, 0x16, 0xcc, 0x54, 0x84, 0x84, 0xc6, 0x49, 0x40, 0x79, 0xe8, 0xa4, 0x86, 0x6e, + 0x71, 0x09, 0x22, 0xf7, 0x60, 0x06, 0x1b, 0x8c, 0xbb, 0x1d, 0x64, 0x80, 0x66, 0x2a, 0x44, 0xfd, + 0xc0, 0x11, 0x38, 0x66, 0x56, 0x4e, 0x22, 0x3f, 0xee, 0x36, 0x31, 0x6a, 0x88, 0x7f, 0x93, 0xef, + 0x68, 0x72, 0x62, 0x01, 0xbf, 0xbd, 0x27, 0xbe, 0xcd, 0x50, 0xde, 0x97, 0x22, 0x32, 0x3e, 0xa9, + 0xd4, 0x1a, 0x9d, 0xa6, 0xfd, 0x9b, 0x50, 0xc5, 0x91, 0x23, 0x4d, 0xe2, 0xfa, 0x59, 0x82, 0x26, + 0x11, 0xda, 0x85, 0xd9, 0x80, 0x26, 0x17, 0x61, 0xf4, 0x4a, 0x86, 0xa9, 0x45, 0xd1, 0xfe, 0x09, + 0xda, 0xde, 0x2a, 0x6c, 0xfb, 0x02, 0x8d, 0x06, 0x72, 0x13, 0xea, 0x7c, 0x4f, 0xe3, 0x33, 0x4f, + 0xb8, 0x03, 0x6a, 0x08, 0x38, 0x3c, 0xf3, 0xd8, 0xf9, 0x68, 0x90, 0x09, 0xf7, 0xb0, 0x34, 0x10, + 0xb6, 0xcd, 0xa9, 0xe4, 0x1e, 0xb4, 0x65, 0x40, 0x38, 0x76, 0x87, 0xf4, 0x24, 0x91, 0xfe, 0xd1, + 0x60, 0x32, 0x42, 0x37, 0xcc, 0x2e, 0x3d, 0x49, 0xec, 0x3d, 0x98, 0x17, 0x67, 0xd6, 0xfe, 0x98, + 0xca, 0xae, 0x7f, 0xab, 0x48, 0xff, 0x6b, 0xac, 0x2e, 0x98, 0x87, 0x1c, 0x0f, 0x81, 0x9b, 0x35, + 0x6d, 0x07, 0x88, 0x7e, 0x06, 0x8a, 0x06, 0x85, 0x02, 0x26, 0x3d, 0xc0, 0x62, 0x3a, 0x06, 0x8c, + 0xad, 0x4f, 0x3c, 0xe9, 0xf7, 0x65, 0x18, 0xbf, 0xe6, 0xc8, 0xa2, 0xfd, 0x9f, 0x2c, 0x58, 0xc0, + 0xd6, 0xa4, 0x06, 0x2b, 0xf4, 0x8c, 0xc7, 0x5f, 0x60, 0x98, 0xd2, 0xff, 0xce, 0xbd, 0xce, 0x8b, + 0x50, 0xd5, 0x35, 0x0f, 0x5e, 0xf8, 0xe2, 0xde, 0xb6, 0x4a, 0xce, 0xdb, 0xf6, 0x00, 0x3a, 0x03, + 0x3a, 0xf4, 0x31, 0x95, 0x43, 0x9e, 0xe3, 0x5c, 0x5d, 0xcd, 0xc1, 0xed, 0xbf, 0x63, 0xc1, 0x3c, + 0x57, 0x14, 0xd0, 0xe6, 0x12, 0x4b, 0xf5, 0x17, 0xa4, 0x7d, 0x22, 0x04, 0x94, 0x98, 0x54, 0x7a, + 0x74, 0x22, 0x94, 0x57, 0xde, 0xbe, 0xe6, 0x98, 0x95, 0xc9, 0x13, 0xd4, 0xba, 0x03, 0x17, 0xa1, + 0x05, 0xc9, 0x21, 0xe6, 0xbe, 0x6c, 0x5f, 0x73, 0xb4, 0xea, 0xeb, 0x35, 0x66, 0x32, 0x31, 0xb8, + 0xfd, 0x0c, 0x5a, 0x46, 0x47, 0x86, 0x57, 0xb0, 0xc9, 0xbd, 0x82, 0x39, 0xf7, 0x7b, 0xa9, 0xc0, + 0xfd, 0xfe, 0xfb, 0x15, 0x20, 0x8c, 0xb0, 0x32, 0x3b, 0x77, 0xd7, 0x8c, 0x61, 0xc9, 0x3c, 0x91, + 0x14, 0x44, 0x56, 0x81, 0x68, 0x45, 0x19, 0x5b, 0x2b, 0xab, 0xd8, 0x5a, 0x01, 0x96, 0x49, 0x7d, + 0xa1, 0x55, 0xaa, 0xb8, 0x15, 0x7a, 0x7c, 0xf8, 0x36, 0x15, 0xe2, 0x98, 0xe6, 0x83, 0x41, 0x2c, + 0x66, 0x9b, 0x0a, 0x2f, 0x89, 0x2c, 0x67, 0xe9, 0x61, 0xe6, 0x8d, 0xf4, 0x30, 0x9b, 0xa3, 0x07, + 0xcd, 0x4e, 0xaf, 0x99, 0x76, 0xfa, 0x3d, 0x68, 0xc9, 0x58, 0x15, 0x0f, 0xd3, 0x0b, 0xa7, 0x88, + 0x01, 0x64, 0xf4, 0x24, 0x4d, 0x65, 0xe5, 0x0c, 0xe0, 0x41, 0xe8, 0x1c, 0x9c, 0x1d, 0x2c, 0xa9, + 0x3f, 0xb6, 0x81, 0x83, 0x4d, 0x01, 0x68, 0x59, 0x33, 0x2a, 0x71, 0x27, 0x81, 0xc8, 0x11, 0xa1, + 0x03, 0x74, 0x87, 0x30, 0xcb, 0x3a, 0x8b, 0xc8, 0x5b, 0xc9, 0xad, 0x02, 0x2b, 0x99, 0x7c, 0x94, + 0x06, 0x76, 0xe2, 0x33, 0x7f, 0x84, 0x67, 0x7b, 0x9a, 0x62, 0xf1, 0x94, 0xa3, 0x0e, 0xcf, 0xfc, + 0x91, 0x63, 0xd4, 0xb3, 0x7f, 0x61, 0x41, 0x87, 0x51, 0x85, 0x41, 0xf8, 0x1f, 0x03, 0xf2, 0xe8, + 0x5b, 0xd2, 0xbd, 0x51, 0x97, 0x3c, 0x86, 0x3a, 0x96, 0xc3, 0x31, 0x0d, 0x04, 0xd5, 0x77, 0x4d, + 0xaa, 0x4f, 0xa5, 0xdb, 0xf6, 0x35, 0x27, 0xad, 0xcc, 0xce, 0xb2, 0x6c, 0x60, 0x8d, 0x47, 0x89, + 0xb3, 0x60, 0x8d, 0x3b, 0xb6, 0x01, 0x3e, 0xa5, 0x97, 0xbb, 0x61, 0x1f, 0x5d, 0x2a, 0xb7, 0x01, + 0x18, 0x0d, 0x9e, 0x78, 0x23, 0x5f, 0x78, 0x04, 0xaa, 0x4e, 0xfd, 0x15, 0xbd, 0x7c, 0x8a, 0x00, + 0x26, 0xc6, 0x19, 0x3a, 0x65, 0x91, 0xaa, 0x53, 0x7b, 0x45, 0x2f, 0x77, 0x90, 0x3d, 0x5c, 0x68, + 0x7d, 0x4a, 0x2f, 0x37, 0x29, 0xd7, 0xeb, 0xc2, 0x88, 0xd8, 0xd0, 0x8a, 0xbc, 0x0b, 0xa6, 0xb9, + 0x19, 0x11, 0xb1, 0x46, 0xe4, 0x5d, 0x7c, 0x4a, 0x2f, 0xd7, 0x31, 0x24, 0xf6, 0x00, 0x66, 0x19, + 0x7e, 0x18, 0xf6, 0xc5, 0xc9, 0x24, 0x83, 0xfc, 0xe9, 0xa0, 0x9c, 0x99, 0x57, 0xf8, 0xb7, 0xfd, + 0x1f, 0x2c, 0x68, 0xb1, 0x15, 0x40, 0xb1, 0xc7, 0x76, 0x42, 0xe6, 0x8a, 0x58, 0x69, 0xae, 0xc8, + 0xaa, 0x90, 0x19, 0x5c, 0x86, 0x96, 0xa6, 0xcb, 0x50, 0x5c, 0x36, 0x2e, 0x40, 0x3f, 0x84, 0x3a, + 0x67, 0x27, 0xc6, 0xbe, 0x65, 0x63, 0xa7, 0x8c, 0x09, 0x39, 0x35, 0xac, 0xf6, 0x29, 0x0f, 0x4b, + 0x6b, 0x3e, 0x1d, 0xbe, 0xc8, 0x75, 0x0e, 0x61, 0xe8, 0x82, 0x08, 0x67, 0xb5, 0x28, 0xc2, 0xf9, + 0x02, 0x1a, 0x1a, 0x61, 0x91, 0x6f, 0xf3, 0xd8, 0x30, 0x1f, 0x3c, 0xa7, 0x42, 0x93, 0x70, 0x8c, + 0xd9, 0xa3, 0xc0, 0xd4, 0x01, 0xeb, 0x33, 0x50, 0x41, 0x92, 0x7c, 0x02, 0xf3, 0x5a, 0xb3, 0xdc, + 0x42, 0x2c, 0x1a, 0x93, 0x55, 0x34, 0xa6, 0x3f, 0xb0, 0x60, 0x51, 0x7c, 0x8d, 0x79, 0x45, 0x3e, + 0x3b, 0xc6, 0x9f, 0xc7, 0xa7, 0xec, 0x20, 0x65, 0xad, 0xbb, 0x11, 0x3d, 0xf5, 0xe3, 0x84, 0x4a, + 0x47, 0x7a, 0x01, 0x87, 0x30, 0x92, 0x66, 0x55, 0x1d, 0x51, 0x93, 0x3c, 0x81, 0x06, 0x7e, 0xca, + 0x6d, 0x58, 0xb1, 0x2d, 0xdd, 0xfc, 0x87, 0x7c, 0xa8, 0x4c, 0x92, 0xc7, 0xaa, 0xb4, 0x5e, 0x87, + 0xd9, 0x24, 0xf2, 0x4f, 0x4f, 0x69, 0x64, 0x2f, 0xa9, 0xa1, 0x31, 0x6e, 0xa3, 0x87, 0x09, 0x1d, + 0x33, 0xe5, 0x88, 0x51, 0x46, 0x43, 0x30, 0xd5, 0x2f, 0xed, 0x3c, 0xef, 0x69, 0x19, 0x72, 0xdc, + 0x5a, 0x4d, 0x13, 0xe2, 0xee, 0xc3, 0xdc, 0x88, 0x29, 0x4a, 0x4c, 0x83, 0x37, 0x1c, 0xe7, 0x59, + 0x30, 0x53, 0xbc, 0x51, 0x6f, 0x89, 0xdd, 0xc4, 0x1f, 0xba, 0x12, 0x2b, 0x72, 0xd1, 0x8a, 0x50, + 0xec, 0xf8, 0x8e, 0x13, 0xef, 0x94, 0x0a, 0xed, 0x98, 0x17, 0xec, 0x2e, 0x2c, 0x1d, 0xa4, 0xdb, + 0xa2, 0x39, 0x24, 0xec, 0x7f, 0xde, 0x82, 0xe5, 0x1c, 0x4a, 0x65, 0xce, 0x0a, 0x6f, 0xf0, 0xd0, + 0x1f, 0x1d, 0x87, 0xca, 0x9b, 0x63, 0xe9, 0x8e, 0x62, 0x03, 0x45, 0x4e, 0xe1, 0xba, 0xa4, 0x0a, + 0x26, 0x42, 0x52, 0xb5, 0xbf, 0x84, 0x9a, 0xe8, 0x87, 0xa6, 0xc4, 0xca, 0x76, 0x28, 0xe1, 0xfa, + 0xa9, 0x58, 0xdc, 0x1e, 0x39, 0x83, 0xae, 0x22, 0x3f, 0xa1, 0x29, 0x69, 0x96, 0x0c, 0xeb, 0xeb, + 0x83, 0x37, 0xf4, 0x65, 0xf8, 0x2f, 0x9c, 0xa9, 0xad, 0x91, 0x4b, 0xb8, 0x23, 0x71, 0xa8, 0x0a, + 0xe5, 0xfb, 0xab, 0xbc, 0xd5, 0xdc, 0xd0, 0x33, 0x63, 0x76, 0xfa, 0x86, 0x86, 0xc9, 0x8f, 0x61, + 0xe9, 0xc2, 0xf3, 0x13, 0x39, 0x2c, 0xcd, 0x8a, 0xaa, 0x62, 0x97, 0xab, 0x6f, 0xe8, 0xf2, 0x25, + 0xff, 0xd8, 0xd0, 0x0f, 0xa7, 0xb4, 0xd8, 0xfb, 0x45, 0x09, 0xda, 0x66, 0x3b, 0x8c, 0x4c, 0x85, + 0x54, 0x92, 0x0a, 0x85, 0xb4, 0x3f, 0x33, 0xe0, 0xbc, 0x53, 0xb4, 0x54, 0xe4, 0x14, 0xd5, 0xdd, + 0x90, 0xe5, 0x37, 0x45, 0x5d, 0x2a, 0x6f, 0x17, 0x75, 0xa9, 0x16, 0x46, 0x5d, 0xa6, 0x3b, 0xe7, + 0x67, 0x7e, 0x59, 0xe7, 0xfc, 0xec, 0x95, 0xce, 0xf9, 0xde, 0xff, 0xb1, 0x80, 0xe4, 0xa9, 0x97, + 0x3c, 0xe3, 0x7e, 0xe0, 0x80, 0x0e, 0x85, 0x78, 0xfb, 0xfa, 0xdb, 0x71, 0x80, 0xdc, 0x2d, 0xf9, + 0x35, 0x63, 0x45, 0x3d, 0x7d, 0x55, 0xb7, 0x6d, 0x5a, 0x4e, 0x11, 0x2a, 0x13, 0x79, 0xaa, 0xbc, + 0x39, 0xf2, 0x54, 0x7d, 0x73, 0xe4, 0x69, 0x26, 0x1b, 0x79, 0xea, 0xfd, 0x55, 0x0b, 0x16, 0x0a, + 0xc8, 0xec, 0xd7, 0x37, 0x71, 0x46, 0x18, 0x86, 0xf4, 0x29, 0x09, 0xc2, 0xd0, 0x81, 0xbd, 0xbf, + 0x04, 0x2d, 0x83, 0xb5, 0x7e, 0x7d, 0xfd, 0x67, 0xcd, 0x33, 0x4e, 0xd9, 0x06, 0xac, 0xf7, 0x3f, + 0x4b, 0x40, 0xf2, 0xec, 0xfd, 0xa5, 0x8e, 0x21, 0xbf, 0x4e, 0xe5, 0x82, 0x75, 0xfa, 0xff, 0x7a, + 0xf2, 0x7c, 0x00, 0xf3, 0x22, 0x27, 0x5f, 0xf3, 0xfc, 0x73, 0x8a, 0xc9, 0x23, 0x98, 0x81, 0x6a, + 0x86, 0xfd, 0x6a, 0x46, 0x0e, 0xb2, 0x76, 0xfc, 0x66, 0xa2, 0x7f, 0x76, 0x0f, 0xba, 0x62, 0x85, + 0xf2, 0xae, 0xbf, 0xbf, 0x57, 0x51, 0x36, 0x36, 0x22, 0x85, 0xfe, 0xfc, 0x4d, 0x68, 0xea, 0xc7, + 0x87, 0xd8, 0x8e, 0x4c, 0xf0, 0x87, 0xa9, 0x19, 0x7a, 0x2d, 0xb2, 0x09, 0x6d, 0x14, 0x92, 0x03, + 0xf5, 0x1d, 0xd7, 0x34, 0xae, 0x70, 0x68, 0x6f, 0x5f, 0x73, 0x32, 0xdf, 0x90, 0xdf, 0x86, 0xb6, + 0xe9, 0xe6, 0x12, 0x3a, 0x61, 0x91, 0x1a, 0xc9, 0x3e, 0x37, 0x2b, 0x93, 0x35, 0xe8, 0x64, 0xfd, + 0x64, 0x22, 0x41, 0x72, 0x4a, 0x03, 0xb9, 0xea, 0xe4, 0x13, 0x58, 0x2c, 0x3a, 0x44, 0x71, 0x6f, + 0xa6, 0x5b, 0x11, 0x85, 0xdf, 0x90, 0xc7, 0xc2, 0x67, 0x5a, 0x45, 0x9f, 0xe9, 0x3d, 0x73, 0x08, + 0xda, 0x92, 0xaf, 0xf0, 0xff, 0x34, 0xef, 0xe9, 0x39, 0x40, 0x0a, 0x23, 0x1d, 0x68, 0xee, 0x1f, + 0x6c, 0xed, 0xb9, 0x1b, 0xdb, 0x6b, 0x7b, 0x7b, 0x5b, 0xbb, 0x9d, 0x6b, 0x84, 0x40, 0x1b, 0x63, + 0x2c, 0x9b, 0x0a, 0x66, 0x31, 0x98, 0xf0, 0x28, 0x4b, 0x58, 0x89, 0x2c, 0x42, 0x67, 0x67, 0x2f, + 0x03, 0x2d, 0x93, 0x2e, 0x2c, 0x1e, 0x6c, 0xf1, 0xb0, 0x8c, 0xd1, 0x6e, 0x85, 0xe9, 0x7b, 0x62, + 0xf0, 0x4c, 0xdf, 0xe3, 0x37, 0x3b, 0xd6, 0x39, 0x11, 0x4a, 0x1d, 0xe8, 0x1f, 0x58, 0x70, 0x3d, + 0x83, 0x48, 0x73, 0x75, 0xb9, 0x9a, 0x63, 0xea, 0x3e, 0x26, 0x10, 0x23, 0xc7, 0xd2, 0x3c, 0xcc, + 0xc8, 0xa9, 0x3c, 0x82, 0x71, 0x96, 0x66, 0x4e, 0x66, 0xf8, 0xb5, 0x08, 0x65, 0x2f, 0xab, 0x94, + 0xc8, 0xcc, 0xc0, 0x4f, 0xf8, 0x8d, 0x11, 0x1d, 0x91, 0x7a, 0x95, 0xcd, 0x21, 0xcb, 0x22, 0x59, + 0xcd, 0x50, 0x83, 0x39, 0xde, 0x42, 0x9c, 0xfd, 0xcf, 0x66, 0x80, 0x7c, 0x77, 0x42, 0xa3, 0x4b, + 0x4c, 0xc6, 0x55, 0xc1, 0xac, 0xe5, 0xac, 0x6b, 0x7d, 0x66, 0x3c, 0x39, 0x66, 0x06, 0x8b, 0x30, + 0xa4, 0x4a, 0x6f, 0x95, 0x74, 0x5f, 0x94, 0xf4, 0x5e, 0x79, 0x73, 0xd2, 0x7b, 0xf5, 0x4d, 0x49, + 0xef, 0x5f, 0x81, 0x96, 0x7f, 0x1a, 0x84, 0x4c, 0xe8, 0x30, 0x45, 0x25, 0xee, 0xce, 0xdc, 0x2d, + 0xdf, 0x6f, 0x3a, 0x4d, 0x01, 0xdc, 0x63, 0x30, 0xf2, 0x24, 0xad, 0x44, 0x07, 0xa7, 0x78, 0x49, + 0x43, 0x17, 0x43, 0x5b, 0x83, 0x53, 0x2a, 0xec, 0x46, 0x74, 0xad, 0xc8, 0x8f, 0x19, 0x3c, 0x26, + 0xf7, 0xa0, 0x1d, 0x87, 0x13, 0xa6, 0xba, 0xc9, 0x65, 0xe0, 0x0e, 0xe7, 0x26, 0x87, 0x1e, 0xf0, + 0xc5, 0x58, 0x81, 0x85, 0x49, 0x4c, 0xdd, 0x91, 0x1f, 0xc7, 0xec, 0x78, 0xee, 0x87, 0x41, 0x12, + 0x85, 0x43, 0xe1, 0x40, 0x9e, 0x9f, 0xc4, 0xf4, 0x39, 0xc7, 0x6c, 0x70, 0x04, 0xf9, 0x66, 0x3a, + 0xa4, 0xb1, 0xe7, 0x47, 0x71, 0x17, 0x70, 0x48, 0x72, 0xa6, 0x6c, 0xdc, 0x07, 0x9e, 0x1f, 0xa9, + 0xb1, 0xb0, 0x42, 0x9c, 0x49, 0xc6, 0x6f, 0x64, 0x93, 0xf1, 0x7f, 0x54, 0x9c, 0x8c, 0xdf, 0xc2, + 0xa6, 0x1f, 0x89, 0xa6, 0xf3, 0x5b, 0xfc, 0x85, 0x72, 0xf2, 0xf3, 0x77, 0x0c, 0xda, 0x5f, 0xe4, + 0x8e, 0xc1, 0x5c, 0xd1, 0x1d, 0x83, 0x0f, 0xa1, 0x81, 0x99, 0xdf, 0xee, 0x99, 0x1f, 0x24, 0xd2, + 0x19, 0xde, 0xd1, 0x53, 0xc3, 0xb7, 0x99, 0xf9, 0x0d, 0x91, 0xfc, 0x33, 0xce, 0xa7, 0xfb, 0xcf, + 0x7f, 0x89, 0xe9, 0xfe, 0x22, 0x43, 0x7d, 0x05, 0x6a, 0x72, 0x9f, 0x08, 0x81, 0xca, 0x49, 0x14, + 0x8e, 0xa4, 0x7f, 0x90, 0xfd, 0x4d, 0xda, 0x50, 0x4a, 0x42, 0xf1, 0x71, 0x29, 0x09, 0xed, 0xdf, + 0x83, 0x86, 0x46, 0x6a, 0xe4, 0x5d, 0xee, 0x76, 0x60, 0xaa, 0xb3, 0xb0, 0xab, 0xf9, 0x2a, 0xd6, + 0x05, 0x74, 0x67, 0x40, 0xbe, 0x06, 0xf3, 0x03, 0x3f, 0xa2, 0x78, 0x31, 0xc7, 0x8d, 0xe8, 0x39, + 0x8d, 0x62, 0xe9, 0xb2, 0xed, 0x28, 0x84, 0xc3, 0xe1, 0xb6, 0x0b, 0x0b, 0xc6, 0xde, 0x2a, 0xe9, + 0x36, 0x83, 0xeb, 0x26, 0xa3, 0x6c, 0x66, 0xca, 0xbd, 0xc0, 0x31, 0xed, 0x43, 0x78, 0x9b, 0xdd, + 0x71, 0x14, 0x1e, 0x63, 0x27, 0x96, 0x63, 0xc0, 0xec, 0xff, 0x51, 0x86, 0xf2, 0x76, 0x38, 0xd6, + 0xf3, 0x1e, 0xac, 0x7c, 0xde, 0x83, 0x30, 0x13, 0x5c, 0x65, 0x05, 0x08, 0x5d, 0xce, 0x00, 0x92, + 0x07, 0xd0, 0x66, 0xa2, 0x22, 0x09, 0x99, 0x59, 0x74, 0xe1, 0x45, 0x3c, 0x07, 0xbf, 0x8c, 0xfc, + 0x97, 0xc1, 0x90, 0x45, 0x28, 0x2b, 0xed, 0x16, 0x2b, 0xb0, 0x22, 0xb3, 0xc9, 0x31, 0x03, 0xed, + 0x52, 0xc4, 0x90, 0x44, 0x89, 0x49, 0x5e, 0xf3, 0x7b, 0x2e, 0x8f, 0xb8, 0x8e, 0x52, 0x84, 0x62, + 0x26, 0x0b, 0x93, 0x38, 0xa3, 0xd4, 0x02, 0x50, 0x65, 0x3d, 0xb0, 0x58, 0x33, 0x03, 0x8b, 0x77, + 0xa1, 0x91, 0x0c, 0xcf, 0xdd, 0xb1, 0x77, 0x39, 0x0c, 0xbd, 0x81, 0xe0, 0x74, 0x1d, 0x44, 0x1e, + 0x01, 0x8c, 0xc6, 0x63, 0xc1, 0x86, 0xe8, 0xb5, 0x4c, 0xa9, 0xfa, 0xf9, 0xc1, 0x01, 0xa7, 0x3e, + 0x47, 0xab, 0x43, 0xb6, 0xa0, 0x5d, 0x78, 0x91, 0xe6, 0xb6, 0xcc, 0x93, 0x0a, 0xc7, 0x2b, 0x05, + 0x8c, 0x9a, 0xf9, 0xa8, 0xf7, 0x1d, 0x20, 0xbf, 0xe2, 0x7d, 0x96, 0x97, 0x50, 0x57, 0x23, 0xd4, + 0x6f, 0x91, 0x60, 0x32, 0x64, 0xc3, 0xbc, 0x45, 0x82, 0xb9, 0x8f, 0xef, 0x41, 0x9b, 0x1f, 0x97, + 0xea, 0x00, 0xe0, 0x09, 0x6c, 0x19, 0xa8, 0xfd, 0xe7, 0x16, 0x54, 0x91, 0xf2, 0x98, 0x96, 0xca, + 0x71, 0x2a, 0x61, 0x44, 0xc4, 0x9e, 0xb2, 0x60, 0x62, 0x1b, 0x17, 0xec, 0x4a, 0x8a, 0x0c, 0xf4, + 0x4b, 0x76, 0x77, 0xa1, 0xae, 0x7a, 0xd2, 0x48, 0x29, 0x05, 0x92, 0x3b, 0x50, 0x39, 0x0b, 0xc7, + 0xd2, 0x90, 0x87, 0x74, 0x45, 0x1d, 0x84, 0xa7, 0xe3, 0x61, 0xed, 0xf1, 0x29, 0x70, 0x63, 0x29, + 0x0b, 0x2e, 0x98, 0xeb, 0x4c, 0xe1, 0x5c, 0x5f, 0xc0, 0x1c, 0x93, 0x0f, 0x5a, 0x6c, 0x78, 0xfa, + 0x61, 0xfa, 0x55, 0xa6, 0x01, 0xf6, 0x87, 0x93, 0x01, 0xd5, 0xdd, 0x29, 0x18, 0x53, 0x14, 0x70, + 0x69, 0x48, 0xd8, 0xff, 0xc2, 0xe2, 0x72, 0x87, 0xb5, 0x4b, 0xee, 0x43, 0x85, 0x9d, 0x7b, 0x19, + 0x9f, 0x9f, 0x4a, 0x50, 0x65, 0xf5, 0x1c, 0xac, 0xc1, 0x76, 0x11, 0xc3, 0x61, 0x7a, 0xeb, 0x3c, + 0x18, 0x96, 0xfa, 0x22, 0xd4, 0xcc, 0x32, 0x26, 0x7c, 0x06, 0x4a, 0x56, 0xb4, 0xfc, 0x8f, 0x8a, + 0x71, 0x96, 0x4a, 0x25, 0x71, 0x70, 0x4a, 0xb5, 0xbc, 0x8f, 0x7f, 0x59, 0x82, 0x96, 0x31, 0x26, + 0xc6, 0x3d, 0x78, 0x34, 0x70, 0x8f, 0xb2, 0xd8, 0x79, 0x1d, 0xa4, 0x73, 0x5e, 0xc9, 0xe4, 0x3c, + 0x15, 0x08, 0x2f, 0xeb, 0x81, 0xf0, 0x47, 0x50, 0x4f, 0x6f, 0x58, 0x9a, 0x83, 0x62, 0x3d, 0xca, + 0x54, 0xdd, 0xb4, 0x52, 0x1a, 0x3a, 0xaf, 0xea, 0xa1, 0xf3, 0x6f, 0x6b, 0xa1, 0xd5, 0x19, 0x6c, + 0xc6, 0x2e, 0x5a, 0xd5, 0x2f, 0x27, 0x17, 0xe3, 0x09, 0x34, 0xb4, 0xc1, 0xeb, 0x21, 0x54, 0xcb, + 0x08, 0xa1, 0xaa, 0xa4, 0xfa, 0x52, 0x9a, 0x54, 0x6f, 0xff, 0xac, 0x04, 0x2d, 0xc6, 0x6b, 0x7e, + 0x70, 0x7a, 0x10, 0x0e, 0xfd, 0xfe, 0x25, 0xd2, 0xb8, 0x64, 0x2b, 0xa1, 0x84, 0x49, 0x9e, 0x33, + 0xc1, 0x4c, 0x26, 0xaa, 0x9b, 0x44, 0x5c, 0x80, 0xab, 0x32, 0x93, 0xf0, 0x4c, 0x3e, 0x1e, 0x7b, + 0x31, 0xd5, 0xee, 0x7f, 0x3a, 0x26, 0x90, 0xc9, 0x61, 0x06, 0xc0, 0x2b, 0x12, 0x23, 0x7f, 0x38, + 0xf4, 0x79, 0x5d, 0xee, 0xa3, 0x28, 0x42, 0xb1, 0x3e, 0x07, 0x7e, 0xec, 0x1d, 0xa7, 0x09, 0x4b, + 0xaa, 0x8c, 0xd1, 0x22, 0xef, 0xb5, 0x16, 0x2d, 0xe2, 0x77, 0xaa, 0x4c, 0x60, 0x96, 0xaa, 0x66, + 0x73, 0x54, 0x65, 0xff, 0xdb, 0x12, 0x34, 0x34, 0x1a, 0x65, 0xb2, 0xa5, 0xf0, 0x10, 0xd6, 0xa0, + 0x22, 0x93, 0x2f, 0x30, 0xbc, 0x5e, 0x1a, 0x84, 0xdc, 0x33, 0x7b, 0xc5, 0x28, 0x33, 0x4a, 0x1f, + 0x83, 0x9e, 0x6f, 0x41, 0x9d, 0xf1, 0xe1, 0x87, 0xe8, 0x62, 0x13, 0x77, 0xad, 0x15, 0x40, 0x62, + 0x57, 0x11, 0x5b, 0x4d, 0xb1, 0x08, 0xb8, 0x32, 0xb7, 0xef, 0x31, 0x34, 0x45, 0x33, 0xb8, 0xc7, + 0x38, 0xe9, 0x54, 0x12, 0x18, 0xfb, 0xef, 0x18, 0x35, 0xe5, 0x97, 0xab, 0xf2, 0xcb, 0xda, 0x9b, + 0xbe, 0x94, 0x35, 0xed, 0x67, 0x2a, 0x6d, 0xf2, 0x59, 0xe4, 0x8d, 0xcf, 0xa4, 0x74, 0x7b, 0x04, + 0x0b, 0x52, 0x88, 0x4d, 0x02, 0x2f, 0x08, 0xc2, 0x49, 0xd0, 0xa7, 0x32, 0xff, 0xbe, 0x08, 0x65, + 0x0f, 0xd4, 0x6d, 0x2d, 0x6c, 0x88, 0x3c, 0x80, 0x2a, 0x57, 0xe3, 0xb9, 0xae, 0x52, 0x2c, 0xcf, + 0x78, 0x15, 0x72, 0x1f, 0xaa, 0x5c, 0x9b, 0x2f, 0x4d, 0x95, 0x40, 0xbc, 0x82, 0xbd, 0x02, 0x73, + 0xa8, 0x91, 0x6a, 0x82, 0xf8, 0x66, 0x91, 0x0e, 0x33, 0xd3, 0xe7, 0xe1, 0x8c, 0x45, 0x20, 0x7b, + 0x9c, 0xaf, 0xf4, 0xbc, 0x9e, 0x3f, 0x2f, 0x43, 0x43, 0x03, 0x33, 0x61, 0x89, 0x49, 0x1e, 0xee, + 0xc0, 0xf7, 0x46, 0x54, 0x06, 0x37, 0x5a, 0x4e, 0x06, 0xca, 0xea, 0x79, 0xe7, 0xa7, 0x6e, 0x38, + 0x49, 0xdc, 0x01, 0x3d, 0x8d, 0x28, 0x15, 0xca, 0x55, 0x06, 0xca, 0xea, 0x31, 0x6a, 0xd6, 0xea, + 0xf1, 0x7c, 0x85, 0x0c, 0x54, 0xe6, 0xcf, 0xf0, 0x75, 0xaa, 0xa4, 0xf9, 0x33, 0x7c, 0x55, 0xb2, + 0x62, 0xbe, 0x5a, 0x20, 0xe6, 0x3f, 0x82, 0x25, 0x2e, 0xd0, 0x85, 0xf4, 0x70, 0x33, 0xc4, 0x35, + 0x05, 0x4b, 0x1e, 0x40, 0x87, 0x8d, 0x59, 0xb2, 0x46, 0xec, 0xff, 0x84, 0xf3, 0x98, 0xe5, 0xe4, + 0xe0, 0xac, 0x2e, 0xc6, 0x5e, 0xf5, 0xba, 0x3c, 0x9f, 0x34, 0x07, 0xc7, 0xba, 0xde, 0x6b, 0xb3, + 0x6e, 0x5d, 0xd4, 0xcd, 0xc0, 0xc9, 0x63, 0x58, 0x1e, 0xd1, 0x81, 0xef, 0x99, 0x4d, 0xb8, 0xa9, + 0xc6, 0x31, 0x0d, 0xcd, 0x7a, 0x61, 0xab, 0xf0, 0x93, 0x70, 0x74, 0xec, 0xf3, 0x53, 0x96, 0x47, + 0x89, 0x2b, 0x4e, 0x0e, 0x6e, 0xb7, 0xa0, 0x71, 0x98, 0x84, 0x63, 0xb9, 0xf5, 0x6d, 0x68, 0xf2, + 0xa2, 0xb8, 0x71, 0x71, 0x13, 0x6e, 0x20, 0xbd, 0x1e, 0x85, 0xe3, 0x70, 0x18, 0x9e, 0x5e, 0x1a, + 0xee, 0xa9, 0x7f, 0x6f, 0xc1, 0x82, 0x81, 0x4d, 0xfd, 0x53, 0xe8, 0x4b, 0x97, 0x69, 0xf2, 0x9c, + 0xc4, 0xe7, 0xb5, 0x33, 0x8a, 0x57, 0xe4, 0x79, 0x00, 0x2f, 0x44, 0xe6, 0xfc, 0x5a, 0x7a, 0xf7, + 0x53, 0x7e, 0xc8, 0xe9, 0xbd, 0x9b, 0xa7, 0x77, 0xf1, 0xbd, 0xbc, 0x15, 0x2a, 0x9b, 0xf8, 0x6d, + 0x91, 0xfd, 0x3b, 0x10, 0x93, 0x2e, 0x9b, 0x19, 0x9b, 0xba, 0x3b, 0x53, 0x8e, 0xa0, 0xaf, 0x80, + 0xb1, 0xfd, 0x73, 0x0b, 0x20, 0x1d, 0x1d, 0xe6, 0x8c, 0xaa, 0x73, 0x96, 0x3f, 0xaf, 0xa2, 0x9d, + 0xa9, 0xef, 0x42, 0x53, 0xe5, 0xad, 0xa5, 0x47, 0x77, 0x43, 0xc2, 0x98, 0xaa, 0xf3, 0x3e, 0xcc, + 0x9d, 0x0e, 0xc3, 0x63, 0x54, 0xa9, 0xc4, 0x39, 0xcb, 0xef, 0x9d, 0xb4, 0x39, 0x58, 0x9e, 0x9e, + 0xe9, 0x39, 0x5f, 0x29, 0x4c, 0x78, 0xd3, 0x4f, 0x6d, 0x76, 0xd6, 0xcd, 0xe7, 0x56, 0xe2, 0x4a, + 0x2e, 0xff, 0xa5, 0xc2, 0xbe, 0x57, 0x45, 0x37, 0x9e, 0x40, 0x3b, 0xe2, 0x32, 0x53, 0x0a, 0xd4, + 0xca, 0x15, 0x02, 0xb5, 0x15, 0x19, 0x27, 0xf3, 0x57, 0xa1, 0xe3, 0x0d, 0xce, 0x69, 0x94, 0xf8, + 0xe8, 0xed, 0x45, 0x9d, 0x8e, 0x4f, 0x70, 0x4e, 0x83, 0xa3, 0xea, 0xf4, 0x3e, 0xcc, 0x89, 0x5b, + 0x40, 0xaa, 0xa6, 0x78, 0x68, 0x20, 0x05, 0xb3, 0x8a, 0xf6, 0x3f, 0x96, 0x69, 0x43, 0xe6, 0xee, + 0x5e, 0xbd, 0x2a, 0xfa, 0x0c, 0x4b, 0x99, 0x19, 0x7e, 0x45, 0x24, 0x45, 0x0c, 0xa4, 0x5b, 0xb9, + 0xac, 0xe5, 0x91, 0x0f, 0x44, 0xda, 0x95, 0xb9, 0xac, 0x95, 0xb7, 0x59, 0x56, 0xfb, 0x3f, 0x5b, + 0x30, 0xbb, 0x1d, 0x8e, 0x99, 0x69, 0x8f, 0x3a, 0x0e, 0x63, 0x13, 0x75, 0x05, 0x4f, 0x16, 0xdf, + 0x90, 0x6f, 0x5f, 0xa8, 0x95, 0xb4, 0xb2, 0x5a, 0xc9, 0x77, 0xe0, 0x26, 0x06, 0x36, 0xa2, 0x70, + 0x1c, 0x46, 0x8c, 0x5d, 0xbd, 0x21, 0x57, 0x41, 0xc2, 0x20, 0x39, 0x93, 0xe2, 0xf4, 0xaa, 0x2a, + 0xe8, 0x07, 0x1c, 0x26, 0xe7, 0x2e, 0x37, 0x37, 0x85, 0x16, 0xc5, 0xa5, 0x6c, 0x1e, 0x61, 0xff, + 0x16, 0xd4, 0x95, 0x03, 0x83, 0x7c, 0x00, 0xf5, 0xb3, 0x70, 0x2c, 0xbc, 0x1c, 0x96, 0x71, 0x37, + 0x41, 0xcc, 0xde, 0x49, 0x2b, 0xd8, 0xff, 0x6b, 0x16, 0x66, 0x77, 0x82, 0xf3, 0xd0, 0xef, 0x63, + 0xfa, 0xd1, 0x88, 0x8e, 0x42, 0x79, 0x29, 0x91, 0xfd, 0x8d, 0xef, 0x85, 0xa4, 0xcf, 0x06, 0x70, + 0x16, 0xd2, 0x20, 0xcc, 0x40, 0x8e, 0xf4, 0x6b, 0xff, 0xa2, 0x94, 0x5a, 0x7d, 0x55, 0xed, 0x5a, + 0x27, 0x6b, 0x8d, 0x5f, 0x47, 0xc7, 0xb5, 0xe3, 0x97, 0x49, 0x34, 0x08, 0x5b, 0x7c, 0x71, 0x0f, + 0x80, 0x27, 0x8a, 0xf3, 0x4c, 0x46, 0x01, 0x42, 0xa3, 0x3f, 0xa2, 0x3c, 0x34, 0xa5, 0x54, 0x2f, + 0x66, 0xf4, 0xeb, 0x40, 0xa6, 0x9e, 0xf1, 0x0f, 0x78, 0x1d, 0x7e, 0x1c, 0xe8, 0x20, 0xcc, 0x46, + 0xc9, 0x3c, 0xa2, 0xc1, 0x1f, 0x42, 0xc9, 0x82, 0x79, 0xa2, 0x99, 0x12, 0xba, 0x7c, 0x9e, 0xc0, + 0x9f, 0x4e, 0xc8, 0xc2, 0x35, 0x57, 0x01, 0xbf, 0x2e, 0x25, 0x5d, 0x05, 0x8c, 0x64, 0xbc, 0xe1, + 0xf0, 0xd8, 0xeb, 0xbf, 0xe2, 0x96, 0x6d, 0x93, 0x47, 0x34, 0x0d, 0x20, 0x66, 0xf3, 0xa7, 0xfb, + 0x8a, 0x89, 0x40, 0x15, 0x47, 0x07, 0x91, 0x55, 0xd3, 0x7f, 0xd5, 0x9e, 0xe2, 0xbf, 0xd2, 0x2b, + 0xe9, 0x89, 0x51, 0x73, 0xb9, 0x0b, 0x4c, 0xde, 0x60, 0x20, 0x12, 0x66, 0x3a, 0xfc, 0xe9, 0x00, + 0x05, 0x40, 0x47, 0x0d, 0x5f, 0x30, 0x5e, 0x61, 0x1e, 0x2b, 0x18, 0x30, 0x72, 0x87, 0xfb, 0x61, + 0xc7, 0x9e, 0x3f, 0xc0, 0xc4, 0x54, 0x6e, 0x0b, 0x2b, 0x18, 0x6b, 0x43, 0xfe, 0x8d, 0x07, 0xe7, + 0x02, 0xae, 0x8a, 0x01, 0x63, 0x6b, 0xa3, 0xca, 0xa3, 0xf4, 0xc6, 0x93, 0x09, 0x24, 0x1f, 0x62, + 0x22, 0x42, 0x42, 0xf1, 0x5a, 0x53, 0x7b, 0xf5, 0xa6, 0x98, 0xb3, 0x20, 0x5b, 0xf9, 0x3f, 0x26, + 0x5e, 0x38, 0xbc, 0x26, 0x53, 0xdb, 0x78, 0x2c, 0x68, 0xc9, 0x50, 0xdb, 0x44, 0x55, 0x8c, 0x05, + 0xf1, 0x0a, 0xe4, 0xb1, 0x66, 0x89, 0x75, 0xb1, 0xf2, 0xad, 0x4c, 0xfb, 0x53, 0x6c, 0x30, 0x46, + 0xcc, 0x7e, 0xcc, 0xce, 0x9f, 0x98, 0x06, 0x03, 0xbc, 0xe0, 0x54, 0x73, 0x34, 0xc8, 0xaf, 0xd7, + 0x46, 0x5b, 0x83, 0xa6, 0x3e, 0x4f, 0x52, 0x83, 0xca, 0xfe, 0xc1, 0xd6, 0x5e, 0xe7, 0x1a, 0x69, + 0xc0, 0xec, 0xe1, 0xd6, 0xd1, 0xd1, 0xee, 0xd6, 0x66, 0xc7, 0x22, 0x4d, 0xa8, 0xa9, 0xbb, 0x24, + 0x25, 0x56, 0x5a, 0xdb, 0xd8, 0xd8, 0x3a, 0x38, 0xda, 0xda, 0xec, 0x94, 0x3f, 0xa9, 0xd4, 0x4a, + 0x9d, 0x32, 0x2a, 0x98, 0xda, 0x32, 0xbc, 0xc1, 0xcf, 0x76, 0x07, 0x00, 0x0d, 0x9f, 0x34, 0xb1, + 0xaa, 0xe2, 0x68, 0x10, 0x26, 0xc8, 0x95, 0x7f, 0xa2, 0xcc, 0x9f, 0x7b, 0x90, 0x65, 0xdc, 0x5c, + 0x7c, 0x57, 0x41, 0x8f, 0x0f, 0x56, 0x1d, 0x13, 0xc8, 0x08, 0x5f, 0x00, 0xf0, 0x82, 0x03, 0x17, + 0x17, 0x3a, 0x88, 0x11, 0x52, 0x44, 0xe3, 0x70, 0x78, 0x4e, 0x79, 0x15, 0xae, 0x3e, 0x1a, 0x30, + 0xd6, 0x97, 0x90, 0x88, 0xda, 0xe5, 0xa3, 0xaa, 0x63, 0x02, 0xc9, 0xd7, 0x25, 0x21, 0xd5, 0x90, + 0x90, 0x96, 0xf3, 0x54, 0x61, 0x10, 0xd1, 0xf3, 0x9c, 0xa3, 0xac, 0x8e, 0x04, 0xf2, 0x1b, 0xf9, + 0xef, 0xde, 0xc2, 0x61, 0x46, 0x56, 0x80, 0x8c, 0xc6, 0x63, 0xb7, 0xc0, 0x83, 0x55, 0x71, 0x0a, + 0x30, 0xbf, 0x06, 0x07, 0x5b, 0x02, 0x64, 0x6d, 0x30, 0x10, 0xc3, 0xd4, 0x5f, 0xbf, 0x88, 0xf4, + 0xe7, 0x56, 0xa4, 0xc8, 0x2e, 0x10, 0x8b, 0xa5, 0x62, 0xb1, 0x78, 0xa5, 0xf0, 0xb0, 0x77, 0xa0, + 0x71, 0xa0, 0x3d, 0xe0, 0x62, 0xb3, 0x13, 0x44, 0x3e, 0xdd, 0xc2, 0xcf, 0x16, 0xee, 0x58, 0x4b, + 0xa1, 0xda, 0x90, 0x4a, 0xfa, 0x90, 0xec, 0x7f, 0x68, 0xf1, 0x3b, 0xf1, 0x6a, 0x0a, 0xbc, 0x7f, + 0x1b, 0x9a, 0x2a, 0xb8, 0x94, 0x5e, 0x10, 0x34, 0x60, 0xac, 0x0e, 0x0e, 0xc7, 0x0d, 0x4f, 0x4e, + 0x62, 0x2a, 0xaf, 0xf2, 0x18, 0x30, 0xa9, 0xac, 0x33, 0xf5, 0xdf, 0xe7, 0x3d, 0xc4, 0xe2, 0x4a, + 0x4f, 0x0e, 0xce, 0x28, 0x5d, 0xf8, 0xc6, 0xe5, 0x25, 0x26, 0x55, 0x56, 0xf7, 0x18, 0xb3, 0x2b, + 0xfd, 0x00, 0x6a, 0xaa, 0x5d, 0xf3, 0x24, 0x96, 0x35, 0x15, 0x9e, 0x9d, 0xf8, 0x68, 0xc8, 0x1b, + 0x83, 0xe6, 0x0c, 0x97, 0x47, 0x30, 0x5a, 0x3a, 0xf1, 0xa3, 0x6c, 0x75, 0xce, 0x81, 0x05, 0x18, + 0xfb, 0x25, 0x2c, 0x48, 0xf1, 0xa1, 0x59, 0x11, 0xe6, 0x46, 0x5a, 0x6f, 0x3a, 0x05, 0x4a, 0xf9, + 0x53, 0xc0, 0xfe, 0x37, 0x15, 0x98, 0x95, 0xaf, 0x23, 0xd9, 0x05, 0xaf, 0xf9, 0xd4, 0xcd, 0x87, + 0x80, 0x48, 0xd7, 0x78, 0xee, 0x01, 0x09, 0x41, 0xe8, 0x06, 0xf7, 0xb3, 0xa7, 0x7b, 0xea, 0x60, + 0xcd, 0x9c, 0xf0, 0x4b, 0x50, 0x19, 0x7b, 0xc9, 0x19, 0xfa, 0xdf, 0x38, 0x2d, 0x61, 0x59, 0xba, + 0xf0, 0xab, 0xa6, 0x0b, 0xbf, 0xe8, 0xf9, 0x23, 0xae, 0xca, 0xe6, 0x9f, 0x3f, 0xba, 0x05, 0x75, + 0xae, 0x8d, 0xa4, 0x5e, 0xfa, 0x14, 0x90, 0xd1, 0x5e, 0x6a, 0x39, 0xed, 0xe5, 0xed, 0xf5, 0x8a, + 0x6f, 0xc2, 0x0c, 0xbf, 0x02, 0x2c, 0xae, 0x6c, 0xc9, 0x23, 0x47, 0xac, 0xa4, 0xfc, 0x9f, 0x67, + 0xee, 0x3a, 0xa2, 0xae, 0xfe, 0x88, 0x48, 0xc3, 0x7c, 0x44, 0x44, 0x0f, 0x2e, 0x34, 0x33, 0xc1, + 0x85, 0x07, 0xd0, 0x51, 0xcb, 0x87, 0x0e, 0xb8, 0x20, 0x16, 0x57, 0x54, 0x72, 0xf0, 0xf4, 0xd8, + 0x6c, 0x1b, 0xc7, 0x26, 0x93, 0x70, 0x6b, 0x49, 0x42, 0x47, 0xe3, 0x44, 0x1c, 0x9b, 0xf6, 0x53, + 0x68, 0x19, 0x83, 0x64, 0xc7, 0x90, 0xb8, 0xc4, 0xd5, 0xb9, 0x46, 0x5a, 0x50, 0xdf, 0xd9, 0x73, + 0x9f, 0xee, 0xee, 0x3c, 0xdb, 0x3e, 0xea, 0x58, 0xac, 0x78, 0xf8, 0x62, 0x63, 0x63, 0x6b, 0x6b, + 0x13, 0x8f, 0x25, 0x80, 0x99, 0xa7, 0x6b, 0x3b, 0xec, 0x88, 0x2a, 0xdb, 0xff, 0xdb, 0x82, 0x86, + 0xd6, 0x3c, 0xf9, 0x96, 0x5a, 0x19, 0xfe, 0xce, 0xc4, 0xed, 0xfc, 0x10, 0x56, 0xa4, 0xa0, 0xd6, + 0x96, 0x46, 0xbd, 0xf8, 0x54, 0x9a, 0xfa, 0xe2, 0x13, 0xdb, 0x1e, 0x8f, 0xb7, 0xa0, 0xd6, 0x81, + 0x5b, 0x57, 0x59, 0x30, 0x4f, 0x57, 0x4b, 0x4f, 0x17, 0x56, 0x93, 0x7b, 0x14, 0xb3, 0x60, 0xfb, + 0x23, 0x80, 0x74, 0x34, 0xe6, 0xb4, 0xaf, 0x99, 0xd3, 0xb6, 0xb4, 0x69, 0x97, 0xec, 0x4d, 0x2e, + 0x30, 0xc4, 0x12, 0xaa, 0x30, 0xf8, 0xd7, 0x81, 0x48, 0x07, 0x16, 0xa6, 0x85, 0x8e, 0x87, 0x34, + 0x91, 0x57, 0x3b, 0xe7, 0x05, 0x66, 0x47, 0x21, 0xe4, 0xed, 0xe4, 0xb4, 0x95, 0x54, 0xee, 0x08, + 0x8a, 0xcb, 0xca, 0x1d, 0x51, 0xd5, 0x51, 0x78, 0xbb, 0x07, 0xdd, 0x4d, 0xca, 0x5a, 0x5b, 0x1b, + 0x0e, 0x33, 0xc3, 0xb1, 0x6f, 0xc2, 0x8d, 0x02, 0x9c, 0x70, 0x4f, 0x7c, 0x17, 0xae, 0xaf, 0xf1, + 0x5b, 0x9c, 0xbf, 0xae, 0x0b, 0x23, 0x76, 0x17, 0x96, 0xb2, 0x4d, 0x8a, 0xce, 0x9e, 0xc2, 0xfc, + 0x26, 0x3d, 0x9e, 0x9c, 0xee, 0xd2, 0xf3, 0xb4, 0x23, 0x02, 0x95, 0xf8, 0x2c, 0xbc, 0x10, 0xeb, + 0x83, 0x7f, 0x93, 0xdb, 0x00, 0x43, 0x56, 0xc7, 0x8d, 0xc7, 0xb4, 0x2f, 0xdf, 0xf1, 0x40, 0xc8, + 0xe1, 0x98, 0xf6, 0xed, 0x8f, 0x80, 0xe8, 0xed, 0x88, 0xf5, 0x62, 0x26, 0xc3, 0xe4, 0xd8, 0x8d, + 0x2f, 0xe3, 0x84, 0x8e, 0xe4, 0x03, 0x25, 0x3a, 0xc8, 0x7e, 0x1f, 0x9a, 0x07, 0xde, 0xa5, 0x43, + 0x3f, 0x13, 0x2f, 0x8c, 0x2d, 0xc3, 0xec, 0xd8, 0xbb, 0x64, 0xfc, 0xac, 0x42, 0x2c, 0x88, 0xb6, + 0xff, 0xb8, 0x02, 0x33, 0xbc, 0x26, 0x6b, 0x75, 0x40, 0xe3, 0xc4, 0x0f, 0x90, 0xc7, 0x64, 0xab, + 0x1a, 0x28, 0x27, 0x30, 0x4b, 0x05, 0x02, 0x53, 0xb8, 0xda, 0xe4, 0x7b, 0x08, 0x82, 0x64, 0x0d, + 0x18, 0x13, 0x5b, 0xe9, 0xf5, 0x33, 0x4e, 0xa9, 0x29, 0x20, 0x13, 0xc3, 0x4c, 0x0d, 0x13, 0x3e, + 0x3e, 0x79, 0x16, 0x08, 0x99, 0xa8, 0x83, 0x0a, 0xcd, 0x9f, 0x59, 0x79, 0xcf, 0x26, 0x63, 0xfe, + 0xe4, 0xcc, 0x9c, 0xda, 0x5b, 0x98, 0x39, 0xdc, 0xff, 0x76, 0x95, 0x99, 0x03, 0x6f, 0x63, 0xe6, + 0xbc, 0x4d, 0xec, 0xb0, 0x07, 0x35, 0x3c, 0xd3, 0x35, 0x11, 0x29, 0xcb, 0xe4, 0x37, 0x35, 0x1b, + 0x80, 0xe7, 0x31, 0xdc, 0x4c, 0xf9, 0xc5, 0xa1, 0x9f, 0x7d, 0x39, 0x61, 0x98, 0x1f, 0xc2, 0xac, + 0x80, 0x32, 0xca, 0x0e, 0xbc, 0x91, 0x7c, 0x87, 0x06, 0xff, 0x66, 0x4b, 0x87, 0xcf, 0x61, 0x7c, + 0x36, 0xf1, 0x23, 0x3a, 0x90, 0x77, 0xb5, 0x35, 0x10, 0x26, 0x97, 0xc7, 0xee, 0xab, 0x20, 0xbc, + 0x08, 0xc4, 0x6d, 0x6d, 0x55, 0xb6, 0x09, 0x74, 0xf0, 0x3d, 0xaa, 0x71, 0x18, 0xc9, 0xa7, 0x85, + 0xec, 0x3f, 0xb0, 0xa0, 0x23, 0x18, 0x4d, 0xe1, 0x64, 0xc2, 0xc0, 0x55, 0x4f, 0x12, 0xdc, 0x83, + 0x16, 0xfa, 0x3a, 0xd4, 0x91, 0x23, 0x82, 0xef, 0x06, 0x90, 0x8d, 0x57, 0x66, 0x77, 0x8e, 0xfc, + 0xa1, 0xa0, 0x5b, 0x1d, 0x24, 0x4f, 0xad, 0xc8, 0x13, 0x97, 0xbc, 0x2c, 0x47, 0x95, 0xed, 0x5f, + 0x58, 0x30, 0xaf, 0x0d, 0x58, 0x30, 0xea, 0x13, 0x68, 0xaa, 0x67, 0xdf, 0xa8, 0x52, 0xaa, 0x96, + 0x4d, 0xc9, 0x92, 0x7e, 0x66, 0x54, 0x46, 0x7a, 0xf7, 0x2e, 0x71, 0x80, 0xf1, 0x64, 0x24, 0xb4, + 0x19, 0x1d, 0xc4, 0xe8, 0xe8, 0x82, 0xd2, 0x57, 0xaa, 0x0a, 0xd7, 0xa7, 0x0c, 0x18, 0xc6, 0x88, + 0xc2, 0x20, 0x39, 0x53, 0x95, 0x2a, 0x22, 0x46, 0xa4, 0x03, 0xed, 0xff, 0x5a, 0x82, 0x05, 0xee, + 0x74, 0x13, 0xce, 0x4e, 0xf5, 0xf2, 0xce, 0x0c, 0xf7, 0x3f, 0x72, 0xa1, 0xb5, 0x7d, 0xcd, 0x11, + 0x65, 0xf2, 0xad, 0xb7, 0x74, 0x14, 0xaa, 0xdb, 0x64, 0x53, 0xf6, 0xa2, 0x5c, 0xb4, 0x17, 0x57, + 0xac, 0x74, 0x51, 0xb8, 0xae, 0x5a, 0x1c, 0xae, 0x7b, 0xbb, 0xf0, 0x58, 0xee, 0xca, 0xd5, 0xac, + 0xa8, 0x65, 0x5c, 0xb9, 0x5a, 0x85, 0x65, 0x03, 0x80, 0xf2, 0xda, 0x3f, 0xf1, 0xa9, 0xbc, 0xff, + 0x3e, 0x1f, 0xd3, 0xc4, 0x35, 0xaa, 0xac, 0xcf, 0x42, 0x35, 0xee, 0x87, 0x63, 0x6a, 0x2f, 0xc1, + 0xa2, 0xb9, 0xb8, 0xe2, 0x94, 0xf8, 0xb9, 0x05, 0xdd, 0xa7, 0x3c, 0xe9, 0xc2, 0x0f, 0x4e, 0xb7, + 0xfd, 0x38, 0x09, 0x23, 0xf5, 0x40, 0xda, 0x1d, 0x80, 0x38, 0xf1, 0x22, 0x61, 0x67, 0x72, 0x65, + 0x57, 0x83, 0xb0, 0x35, 0xa2, 0xc1, 0x80, 0x63, 0x39, 0x6d, 0xa8, 0x72, 0xce, 0x98, 0x10, 0x2e, + 0x49, 0x43, 0x25, 0x7f, 0x8f, 0xdf, 0x04, 0x65, 0x8b, 0x41, 0xcf, 0xf1, 0xe8, 0xe5, 0x7e, 0xbe, + 0x0c, 0xd4, 0xfe, 0xc3, 0x12, 0xcc, 0xa5, 0x83, 0xe4, 0x37, 0xcb, 0x0d, 0x01, 0x2e, 0xf4, 0xf0, + 0x54, 0x80, 0x8b, 0xf0, 0xa1, 0xeb, 0x33, 0xc5, 0x5c, 0xf3, 0x4a, 0x6a, 0x50, 0x72, 0x0f, 0x1a, + 0xb2, 0x14, 0x4e, 0x12, 0xed, 0xa5, 0x22, 0x1d, 0xcc, 0xaf, 0x98, 0x30, 0xd3, 0x40, 0x98, 0x39, + 0xa2, 0x84, 0xef, 0x21, 0x8c, 0x12, 0xfc, 0x92, 0xef, 0xa9, 0x2c, 0x32, 0x81, 0xc6, 0x74, 0x6a, + 0xbe, 0x87, 0xa8, 0x4f, 0xeb, 0xba, 0x66, 0x4d, 0xbd, 0xf0, 0xa8, 0x78, 0x9e, 0xb7, 0x98, 0x5e, + 0xb6, 0xab, 0x38, 0x3a, 0x48, 0x7a, 0x85, 0xc2, 0x89, 0x61, 0xfe, 0x1a, 0x30, 0xfb, 0x6f, 0x59, + 0x70, 0xa3, 0x60, 0x1b, 0x85, 0x0c, 0xd8, 0x84, 0xf9, 0x13, 0x85, 0x94, 0x4b, 0xcd, 0x05, 0xc1, + 0x92, 0x14, 0xae, 0xe6, 0xf2, 0x3a, 0xf9, 0x0f, 0x94, 0xb9, 0xc5, 0x37, 0xcf, 0xb8, 0x5b, 0x99, + 0x47, 0xd8, 0x07, 0xd0, 0xdb, 0x7a, 0xcd, 0x44, 0xca, 0x86, 0xfe, 0xcc, 0xb7, 0xa4, 0xac, 0xd5, + 0x9c, 0xc8, 0x7c, 0xb3, 0x33, 0xfa, 0x84, 0xdf, 0x18, 0x53, 0x6d, 0x91, 0x6f, 0xbc, 0x6d, 0x23, + 0x3a, 0xf7, 0xdf, 0x15, 0xbb, 0xce, 0xdf, 0x29, 0x97, 0x37, 0x3c, 0x35, 0x90, 0x7d, 0x0e, 0x73, + 0xcf, 0x27, 0xc3, 0xc4, 0x4f, 0xdf, 0x2c, 0x27, 0xdf, 0x12, 0x1f, 0x61, 0x13, 0x72, 0xe9, 0x0a, + 0xbb, 0xd2, 0xeb, 0xb1, 0x15, 0x1b, 0xb1, 0x96, 0xdc, 0x7c, 0x8f, 0x79, 0x84, 0x7d, 0x03, 0x96, + 0xd3, 0x2e, 0xf9, 0xda, 0xc9, 0x63, 0xe7, 0x8f, 0x2c, 0x9e, 0x59, 0x6d, 0x3e, 0xa1, 0x4e, 0x9e, + 0xc1, 0x42, 0xec, 0x07, 0xa7, 0x43, 0xaa, 0xb7, 0x13, 0x8b, 0x95, 0xb8, 0x6e, 0x0e, 0x4f, 0x3c, + 0xb3, 0xee, 0x14, 0x7d, 0xc1, 0x08, 0xa4, 0x78, 0xa0, 0x29, 0x81, 0x64, 0x96, 0xa4, 0x68, 0x02, + 0x9f, 0x40, 0xdb, 0xec, 0x8c, 0x3c, 0x16, 0x57, 0x27, 0xd3, 0x91, 0x95, 0x33, 0x37, 0xe0, 0x52, + 0xca, 0x30, 0x6a, 0xda, 0x3f, 0xb3, 0xa0, 0xeb, 0x50, 0x46, 0xc6, 0x54, 0xeb, 0x54, 0x50, 0xcf, + 0x93, 0x5c, 0xb3, 0xd3, 0x27, 0xac, 0xae, 0x64, 0xca, 0xb9, 0xae, 0x4c, 0xdd, 0x94, 0xed, 0x6b, + 0x05, 0xb3, 0x5a, 0xaf, 0xc1, 0x8c, 0x98, 0xdf, 0x32, 0x5c, 0x17, 0x43, 0x92, 0xc3, 0x49, 0xc3, + 0x8e, 0x46, 0xa7, 0x46, 0xd8, 0xb1, 0x07, 0x5d, 0xfe, 0x0e, 0x9e, 0x3e, 0x0f, 0xf1, 0xe1, 0x26, + 0x90, 0xe7, 0x5e, 0xdf, 0x8b, 0xc2, 0x30, 0x38, 0xa0, 0x91, 0x48, 0x52, 0x45, 0xed, 0x13, 0xa3, + 0x72, 0x52, 0x51, 0xe6, 0x25, 0xf9, 0x74, 0x5b, 0x18, 0xc8, 0x27, 0xf2, 0x78, 0xc9, 0x76, 0x60, + 0x61, 0xdd, 0x7b, 0x45, 0x65, 0x4b, 0xe9, 0x2a, 0x35, 0xc6, 0xaa, 0x51, 0xb9, 0xf6, 0xf2, 0xce, + 0x75, 0xbe, 0x5b, 0x47, 0xaf, 0x6d, 0xaf, 0xc2, 0xa2, 0xd9, 0xa6, 0x10, 0x25, 0x3d, 0xa8, 0x8d, + 0x04, 0x4c, 0x8c, 0x4e, 0x95, 0x1f, 0x7c, 0x0e, 0x0d, 0xed, 0x6d, 0x43, 0xb2, 0x0c, 0x0b, 0x2f, + 0x77, 0x8e, 0xf6, 0xb6, 0x0e, 0x0f, 0xdd, 0x83, 0x17, 0xeb, 0x9f, 0x6e, 0x7d, 0xdf, 0xdd, 0x5e, + 0x3b, 0xdc, 0xee, 0x5c, 0x23, 0x4b, 0x40, 0xf6, 0xb6, 0x0e, 0x8f, 0xb6, 0x36, 0x0d, 0xb8, 0x45, + 0xee, 0x40, 0xef, 0xc5, 0xde, 0x8b, 0xc3, 0xad, 0x4d, 0xb7, 0xe8, 0xbb, 0x12, 0xb9, 0x0d, 0x37, + 0x04, 0xbe, 0xe0, 0xf3, 0xf2, 0x83, 0x27, 0xd0, 0xc9, 0xba, 0x25, 0x0d, 0x77, 0xee, 0x55, 0x7e, + 0xdf, 0x07, 0xff, 0xa8, 0x0c, 0x90, 0x26, 0xa7, 0x92, 0x2e, 0x2c, 0x6e, 0xae, 0x1d, 0xad, 0xed, + 0xee, 0xb3, 0x41, 0x38, 0xfb, 0x47, 0x5b, 0x1b, 0x47, 0xae, 0xb3, 0xf5, 0xdd, 0xce, 0xb5, 0x42, + 0xcc, 0xfe, 0x01, 0x33, 0xd9, 0x97, 0x61, 0x61, 0x67, 0x6f, 0xe7, 0x68, 0x67, 0x6d, 0xd7, 0x75, + 0xf6, 0x5f, 0xec, 0xec, 0x3d, 0xe3, 0xef, 0xae, 0x94, 0xc9, 0x3b, 0x70, 0xf3, 0xc5, 0xc1, 0x53, + 0x67, 0x7f, 0xef, 0xc8, 0x3d, 0xdc, 0x7e, 0x71, 0xb4, 0x89, 0xaf, 0xb6, 0x6c, 0x38, 0x3b, 0x07, + 0xbc, 0xcd, 0xca, 0x55, 0x15, 0x58, 0xd3, 0x55, 0xb6, 0x62, 0xcf, 0xf6, 0x0f, 0x0f, 0x77, 0x0e, + 0xdc, 0xef, 0xbe, 0xd8, 0x72, 0x76, 0xb6, 0x0e, 0xf1, 0xc3, 0x99, 0x02, 0x38, 0xab, 0x3f, 0x4b, + 0xe6, 0xa1, 0x75, 0xb4, 0xfb, 0x3d, 0x77, 0x7f, 0x6f, 0x67, 0x7f, 0x0f, 0xab, 0xd6, 0x4c, 0x10, + 0xab, 0x55, 0x27, 0x3d, 0x58, 0xda, 0xfa, 0xdd, 0x23, 0xb7, 0xa0, 0x65, 0x98, 0x82, 0x63, 0xdf, + 0x35, 0xc8, 0x0d, 0xb8, 0x7e, 0x78, 0xb4, 0x76, 0xb4, 0xb3, 0xe1, 0x8a, 0x67, 0x9b, 0xd8, 0x26, + 0xb0, 0xcf, 0x9a, 0xc5, 0x28, 0xf6, 0x55, 0x8b, 0x2c, 0x42, 0xe7, 0x60, 0xed, 0xfb, 0xcf, 0xb7, + 0xf6, 0x8e, 0xdc, 0xb5, 0xcd, 0x4d, 0x07, 0x3f, 0x68, 0xe7, 0xa0, 0xac, 0xee, 0x1c, 0xdb, 0xa8, + 0xe7, 0x07, 0x07, 0x58, 0xa5, 0x23, 0x0b, 0x0c, 0x33, 0xbf, 0xfa, 0xb3, 0x32, 0xb4, 0xf9, 0x6d, + 0x01, 0xfe, 0x63, 0x11, 0x34, 0x22, 0xcf, 0x61, 0x56, 0xfc, 0xea, 0x08, 0xb9, 0xae, 0x1e, 0xdb, + 0xd0, 0x7f, 0xe7, 0xa4, 0xb7, 0x94, 0x05, 0x0b, 0xf6, 0x5b, 0xf8, 0x2b, 0xff, 0xf1, 0xbf, 0xff, + 0x7e, 0xa9, 0x45, 0x1a, 0x0f, 0xcf, 0x3f, 0x7c, 0x78, 0x4a, 0x83, 0x98, 0xb5, 0xf1, 0x17, 0x01, + 0xd2, 0xdf, 0xd2, 0x20, 0x5d, 0xe5, 0x7d, 0xcc, 0xfc, 0xd0, 0x48, 0xef, 0x46, 0x01, 0x46, 0xb4, + 0x7b, 0x03, 0xdb, 0x5d, 0xb0, 0xdb, 0xac, 0x5d, 0x3f, 0xf0, 0x13, 0xfe, 0xbb, 0x1a, 0x1f, 0x5b, + 0x0f, 0xc8, 0x00, 0x9a, 0xfa, 0xaf, 0x5c, 0x10, 0x19, 0xed, 0x2f, 0xf8, 0x9d, 0x8e, 0xde, 0xcd, + 0x42, 0x9c, 0x94, 0x39, 0xd8, 0xc7, 0x75, 0xbb, 0xc3, 0xfa, 0x98, 0x60, 0x8d, 0xb4, 0x97, 0x21, + 0x97, 0xc4, 0xe9, 0x8f, 0x59, 0x90, 0x5b, 0x9a, 0x70, 0xcc, 0xfd, 0x94, 0x46, 0xef, 0xf6, 0x14, + 0xac, 0xe8, 0xeb, 0x36, 0xf6, 0xb5, 0x6c, 0x13, 0xd6, 0x57, 0x1f, 0xeb, 0xc8, 0x9f, 0xd2, 0xf8, + 0xd8, 0x7a, 0xb0, 0xfa, 0xa7, 0xf7, 0xa1, 0xae, 0x32, 0x81, 0xc8, 0x8f, 0xa1, 0x65, 0x5c, 0xe7, + 0x20, 0x72, 0x1a, 0x45, 0xb7, 0x3f, 0x7a, 0xb7, 0x8a, 0x91, 0xa2, 0xe3, 0x3b, 0xd8, 0x71, 0x97, + 0x2c, 0xb1, 0x8e, 0xc5, 0x7d, 0x88, 0x87, 0x78, 0xfd, 0x89, 0x3f, 0x5d, 0xf2, 0x4a, 0x3b, 0x71, + 0x78, 0x67, 0xb7, 0xb2, 0x87, 0x80, 0xd1, 0xdb, 0xed, 0x29, 0x58, 0xd1, 0xdd, 0x2d, 0xec, 0x6e, + 0x89, 0x2c, 0xea, 0xdd, 0xa9, 0xec, 0x1c, 0x8a, 0xcf, 0x07, 0xe9, 0xbf, 0xf3, 0x40, 0x6e, 0xa7, + 0x8f, 0xbb, 0x14, 0xfc, 0xfe, 0x83, 0x22, 0x91, 0xfc, 0x8f, 0x40, 0xd8, 0x5d, 0xec, 0x8a, 0x10, + 0xdc, 0x3e, 0xfd, 0x67, 0x1e, 0xc8, 0x31, 0x34, 0xb4, 0xe7, 0x90, 0xc9, 0x8d, 0xa9, 0x4f, 0x37, + 0xf7, 0x7a, 0x45, 0xa8, 0xa2, 0xa9, 0xe8, 0xed, 0x3f, 0x64, 0x0a, 0xe9, 0x0f, 0xa1, 0xae, 0x1e, + 0xd8, 0x25, 0xcb, 0xda, 0x83, 0xc7, 0xfa, 0x83, 0xc0, 0xbd, 0x6e, 0x1e, 0x51, 0x44, 0x7c, 0x7a, + 0xeb, 0x8c, 0xf8, 0x5e, 0x42, 0x43, 0x7b, 0x44, 0x57, 0x4d, 0x20, 0xff, 0x50, 0xaf, 0x9a, 0x40, + 0xc1, 0x9b, 0xbb, 0xf6, 0x3c, 0x76, 0xd1, 0x20, 0x75, 0xa4, 0xef, 0xe4, 0x75, 0x18, 0x93, 0x5d, + 0xb8, 0x2e, 0x4e, 0xd6, 0x63, 0xfa, 0x45, 0xb6, 0xa1, 0xe0, 0xa7, 0x35, 0x1e, 0x59, 0xe4, 0x09, + 0xd4, 0xe4, 0x5b, 0xc9, 0x64, 0xa9, 0xf8, 0xcd, 0xe7, 0xde, 0x72, 0x0e, 0x2e, 0x8e, 0xc1, 0xef, + 0x03, 0xa4, 0x2f, 0xf6, 0x2a, 0x21, 0x91, 0x7b, 0x01, 0x58, 0x51, 0x40, 0xfe, 0x79, 0x5f, 0x7b, + 0x09, 0x27, 0xd8, 0x21, 0x28, 0x24, 0x02, 0x7a, 0x21, 0xdf, 0xae, 0xf8, 0x11, 0x34, 0xb4, 0x47, + 0x7b, 0xd5, 0xf2, 0xe5, 0x1f, 0xfc, 0x55, 0xcb, 0x57, 0xf0, 0xc6, 0xaf, 0xdd, 0xc3, 0xd6, 0x17, + 0xed, 0x39, 0xd6, 0x7a, 0xec, 0x9f, 0x06, 0x23, 0x5e, 0x81, 0x6d, 0xd0, 0x19, 0xb4, 0x8c, 0x97, + 0x79, 0x15, 0x87, 0x16, 0xbd, 0xfb, 0xab, 0x38, 0xb4, 0xf0, 0x31, 0x5f, 0x49, 0x67, 0xf6, 0x3c, + 0xeb, 0xe7, 0x1c, 0xab, 0x68, 0x3d, 0xfd, 0x00, 0x1a, 0xda, 0x2b, 0xbb, 0x6a, 0x2e, 0xf9, 0x07, + 0x7d, 0xd5, 0x5c, 0x8a, 0x1e, 0xe5, 0x5d, 0xc4, 0x3e, 0xda, 0x36, 0x92, 0x02, 0xbe, 0x46, 0xc5, + 0xda, 0xfe, 0x31, 0xb4, 0xcd, 0x77, 0x77, 0x15, 0xef, 0x17, 0xbe, 0xe0, 0xab, 0x78, 0x7f, 0xca, + 0x63, 0xbd, 0x82, 0xa4, 0x1f, 0x2c, 0xa8, 0x4e, 0x1e, 0xfe, 0x54, 0x24, 0x36, 0x7f, 0x4e, 0xbe, + 0xcb, 0x04, 0x9c, 0x78, 0x25, 0x8d, 0x2c, 0x6b, 0x54, 0xab, 0xbf, 0xa5, 0xa6, 0xf8, 0x25, 0xf7, + 0xa0, 0x9a, 0x49, 0xcc, 0xfc, 0x3d, 0xad, 0x67, 0xb0, 0xa0, 0x88, 0x59, 0xbd, 0x7a, 0x16, 0xab, + 0x39, 0x14, 0x3e, 0xae, 0xd6, 0xeb, 0x64, 0xb1, 0x8f, 0x2c, 0x7e, 0xfc, 0xe1, 0xdb, 0x52, 0xda, + 0xf1, 0xa7, 0x3f, 0x7c, 0xa6, 0x1d, 0x7f, 0xc6, 0x13, 0x54, 0xd9, 0xe3, 0x2f, 0xf1, 0x59, 0x1b, + 0x01, 0xcc, 0x65, 0x6e, 0xc8, 0x2a, 0xf6, 0x2a, 0x7e, 0xc4, 0xa0, 0x77, 0xe7, 0xea, 0x8b, 0xb5, + 0xa6, 0x28, 0x92, 0xd2, 0xf4, 0xa1, 0x7c, 0x21, 0xe5, 0xf7, 0xa0, 0xa9, 0x3f, 0x17, 0x4a, 0x74, + 0x99, 0x90, 0xed, 0xe9, 0x66, 0x21, 0xce, 0xa4, 0x12, 0xd2, 0xd4, 0xbb, 0x21, 0xdf, 0x83, 0x25, + 0xb5, 0xcc, 0xfa, 0x45, 0xc9, 0x98, 0xbc, 0x53, 0x70, 0x7d, 0xd2, 0x58, 0xec, 0x1b, 0x53, 0xef, + 0x57, 0x3e, 0xb2, 0x18, 0xf5, 0x99, 0x6f, 0x30, 0xa6, 0x27, 0x4f, 0xd1, 0xd3, 0x93, 0xe9, 0xc9, + 0x53, 0xf8, 0x70, 0xa3, 0xa4, 0x3e, 0xb2, 0x60, 0xac, 0x11, 0xcf, 0xdf, 0x22, 0x3f, 0x80, 0x39, + 0xed, 0x5a, 0xfb, 0xe1, 0x65, 0xd0, 0x57, 0x9c, 0x94, 0x7f, 0xc2, 0xa8, 0x57, 0x64, 0x96, 0xda, + 0xcb, 0xd8, 0xfe, 0xbc, 0x6d, 0x2c, 0x0e, 0xe3, 0xa2, 0x0d, 0x68, 0xe8, 0x57, 0xe6, 0xaf, 0x68, + 0x77, 0x59, 0x43, 0xe9, 0xef, 0xe3, 0x3c, 0xb2, 0xc8, 0x2e, 0x74, 0xb2, 0x4f, 0x79, 0x28, 0x99, + 0x52, 0xf4, 0xfc, 0x48, 0x2f, 0x83, 0x34, 0x1e, 0x00, 0x21, 0x07, 0x3c, 0x2b, 0x58, 0xfd, 0x06, + 0x45, 0x18, 0x65, 0x4f, 0x75, 0xf3, 0xb7, 0x29, 0x54, 0x6b, 0x45, 0xbf, 0x4a, 0x72, 0xdf, 0x7a, + 0x64, 0x91, 0xbf, 0x6b, 0x41, 0xd3, 0xb8, 0x20, 0x6f, 0xe4, 0x58, 0x66, 0xe6, 0xd9, 0xd5, 0x71, + 0xfa, 0x44, 0x6d, 0x07, 0x17, 0x71, 0xf7, 0xc1, 0x27, 0xc6, 0x26, 0xfd, 0xd4, 0xf0, 0xf4, 0xae, + 0x64, 0x7f, 0x88, 0xe2, 0xf3, 0x6c, 0x05, 0xfd, 0x19, 0xaa, 0xcf, 0x1f, 0x59, 0xe4, 0x9f, 0x58, + 0xd0, 0x36, 0x43, 0x38, 0x6a, 0xba, 0x85, 0xc1, 0x22, 0x45, 0x4a, 0x53, 0xe2, 0x3e, 0x3f, 0xc0, + 0x51, 0x1e, 0x3d, 0x70, 0x8c, 0x51, 0x8a, 0xd7, 0x43, 0x7f, 0xb5, 0xd1, 0x92, 0x8f, 0xf9, 0xef, + 0x42, 0xc9, 0xe8, 0x35, 0xc9, 0xff, 0x8e, 0x90, 0x22, 0x3f, 0xfd, 0x57, 0x77, 0x70, 0x13, 0x7e, + 0xc4, 0x7f, 0x80, 0x41, 0x86, 0x40, 0x19, 0x15, 0xbf, 0xed, 0xf7, 0xf6, 0x3d, 0x9c, 0xd3, 0x1d, + 0xfb, 0x86, 0x31, 0xa7, 0xac, 0xe2, 0xb1, 0xc6, 0x47, 0x27, 0x7e, 0x30, 0x27, 0x3d, 0x39, 0x73, + 0x3f, 0xa2, 0x33, 0x7d, 0x90, 0x23, 0x3e, 0x48, 0x51, 0xdd, 0x60, 0xb5, 0xb7, 0x6c, 0xc6, 0x7e, + 0x80, 0x63, 0xbd, 0x67, 0xbf, 0x33, 0x75, 0xac, 0x0f, 0x31, 0x10, 0xc3, 0x46, 0x7c, 0x00, 0x90, + 0x66, 0x9b, 0x90, 0x4c, 0xa6, 0x83, 0x12, 0x40, 0xf9, 0x84, 0x14, 0x93, 0x9f, 0x65, 0x42, 0x04, + 0x6b, 0xf1, 0x87, 0x5c, 0x9c, 0xee, 0xc8, 0x1c, 0x09, 0x5d, 0xfb, 0x32, 0x53, 0x42, 0x0c, 0xed, + 0x2b, 0xdb, 0xbe, 0x21, 0x4c, 0x55, 0xc2, 0xc5, 0x0b, 0x68, 0xed, 0x86, 0xe1, 0xab, 0xc9, 0x58, + 0xa5, 0x3f, 0x9a, 0x31, 0xd2, 0x6d, 0x2f, 0x3e, 0xeb, 0x65, 0x66, 0x61, 0xdf, 0xc5, 0xa6, 0x7a, + 0xa4, 0xab, 0x35, 0xf5, 0xf0, 0xa7, 0x69, 0x26, 0xcb, 0xe7, 0xc4, 0x83, 0x79, 0x25, 0xa3, 0xd5, + 0xc0, 0x7b, 0x66, 0x33, 0x86, 0x64, 0xce, 0x76, 0x61, 0x98, 0x09, 0x72, 0xb4, 0x0f, 0x63, 0xd9, + 0xe6, 0x23, 0x8b, 0x1c, 0x40, 0x73, 0x93, 0xf6, 0xf1, 0x52, 0x28, 0x06, 0x1a, 0x17, 0x8c, 0x60, + 0x15, 0x8f, 0x50, 0xf6, 0x5a, 0x06, 0xd0, 0x3c, 0xb7, 0xc6, 0xde, 0x65, 0x44, 0x3f, 0x7b, 0xf8, + 0x53, 0x11, 0xc2, 0xfc, 0x5c, 0x9e, 0x5b, 0x32, 0xc6, 0x6b, 0x9c, 0x5b, 0x99, 0xa0, 0xb0, 0x71, + 0x6e, 0xe5, 0x82, 0xc2, 0xc6, 0x52, 0xcb, 0x18, 0x33, 0x19, 0xc2, 0x7c, 0x2e, 0x8e, 0xac, 0x8e, + 0xac, 0x69, 0xd1, 0xe7, 0xde, 0xdd, 0xe9, 0x15, 0xcc, 0xde, 0x1e, 0x98, 0xbd, 0x1d, 0x42, 0x8b, + 0x3f, 0x8d, 0x75, 0x4c, 0xf9, 0x7d, 0x8f, 0xcc, 0x2b, 0x0b, 0xfa, 0x6d, 0x92, 0xec, 0x01, 0x83, + 0x38, 0x53, 0xc3, 0xe1, 0x6f, 0x6c, 0xfe, 0x10, 0x1a, 0xcf, 0x68, 0x22, 0x2f, 0x78, 0x28, 0x1d, + 0x3b, 0x73, 0xe3, 0xa3, 0x57, 0x70, 0x3f, 0xc4, 0xa4, 0x19, 0x6c, 0xed, 0x21, 0x1d, 0x9c, 0x52, + 0x2e, 0x9c, 0x5c, 0x7f, 0xf0, 0x39, 0xf9, 0x5d, 0x6c, 0x5c, 0x5d, 0xb7, 0x5b, 0xd2, 0xb2, 0xf5, + 0xf5, 0xc6, 0xe7, 0x32, 0xf0, 0xa2, 0x96, 0x83, 0x70, 0x40, 0x35, 0x5d, 0x2f, 0x80, 0x86, 0x76, + 0x5d, 0x57, 0x31, 0x50, 0xfe, 0x7a, 0xb6, 0x62, 0xa0, 0x82, 0xdb, 0xbd, 0xf6, 0x7d, 0xec, 0xc7, + 0x26, 0x77, 0xd3, 0x7e, 0xf8, 0x8d, 0xde, 0xb4, 0xa7, 0x87, 0x3f, 0xf5, 0x46, 0xc9, 0xe7, 0xe4, + 0x25, 0x3e, 0x54, 0xab, 0x5f, 0x60, 0x49, 0x8d, 0x86, 0xec, 0x5d, 0x17, 0xb5, 0x58, 0x1a, 0xca, + 0x34, 0x24, 0x78, 0x57, 0xa8, 0xc9, 0x7d, 0x0b, 0xe0, 0x30, 0x09, 0xc7, 0x9b, 0x1e, 0x1d, 0x85, + 0x41, 0x2a, 0x6b, 0xd3, 0xeb, 0x13, 0xa9, 0xfc, 0xd2, 0xee, 0x50, 0x90, 0x97, 0x9a, 0x95, 0x65, + 0xdc, 0x01, 0x92, 0xc4, 0x35, 0xf5, 0x86, 0x85, 0x5a, 0x90, 0x82, 0x5b, 0x16, 0x8f, 0x2c, 0xb2, + 0x06, 0x90, 0x26, 0x12, 0x28, 0x9b, 0x29, 0x97, 0xa3, 0xa0, 0xc4, 0x5e, 0x41, 0xd6, 0xc1, 0x01, + 0xd4, 0xd3, 0xb0, 0xeb, 0x72, 0xfa, 0xfa, 0x80, 0x11, 0xa4, 0x55, 0x27, 0x78, 0x2e, 0x18, 0x6a, + 0x77, 0x70, 0xa9, 0x80, 0xd4, 0xd8, 0x52, 0x61, 0x84, 0xd3, 0x87, 0x05, 0x3e, 0x40, 0xa5, 0x2e, + 0x61, 0xda, 0xbf, 0x7a, 0x8f, 0x38, 0x1f, 0x90, 0x54, 0xdc, 0x5c, 0x18, 0x4f, 0x33, 0x5c, 0x3f, + 0x8c, 0x5a, 0xf9, 0x95, 0x03, 0x26, 0x9a, 0x47, 0x30, 0x9f, 0x0b, 0xd1, 0x28, 0x96, 0x9e, 0x16, + 0x83, 0x53, 0x2c, 0x3d, 0x35, 0xba, 0x63, 0x5f, 0xc7, 0x2e, 0xe7, 0x6c, 0x40, 0x53, 0xef, 0xc2, + 0x4f, 0xfa, 0x67, 0xac, 0xbb, 0x3f, 0xb2, 0x60, 0xa1, 0x20, 0x02, 0x43, 0xde, 0x95, 0x5e, 0x83, + 0xa9, 0xd1, 0x99, 0x5e, 0xa1, 0x83, 0xde, 0x3e, 0xc4, 0x7e, 0x9e, 0x93, 0x4f, 0x8d, 0x83, 0x8d, + 0xfb, 0xc6, 0x05, 0x67, 0x5e, 0xa9, 0x54, 0x14, 0x6a, 0x14, 0x9f, 0xc1, 0x32, 0x1f, 0xc8, 0xda, + 0x70, 0x98, 0x09, 0x1e, 0xdc, 0xc9, 0xfd, 0x76, 0xac, 0x11, 0x14, 0xe9, 0x4d, 0xff, 0x6d, 0xd9, + 0x29, 0xea, 0x34, 0x1f, 0x2a, 0x99, 0x40, 0x27, 0xeb, 0x90, 0x27, 0xd3, 0xdb, 0xea, 0xbd, 0x63, + 0xd8, 0xbf, 0x05, 0x4e, 0xfc, 0xdf, 0xc0, 0xce, 0xde, 0xb1, 0x7b, 0x45, 0xeb, 0xc2, 0x4d, 0x62, + 0xb6, 0x1f, 0x7f, 0x59, 0x45, 0x0f, 0x32, 0xf3, 0x94, 0x1d, 0x4c, 0x0b, 0x77, 0x28, 0x0b, 0xbc, + 0x38, 0xf8, 0xf0, 0x1e, 0x76, 0x7f, 0xd7, 0xbe, 0x59, 0xd4, 0x7d, 0xc4, 0x3f, 0xe1, 0xb6, 0xf8, + 0x72, 0x96, 0xaf, 0xe5, 0x08, 0xee, 0x16, 0xed, 0xf7, 0x54, 0x5b, 0x28, 0xb3, 0xd6, 0xd7, 0x50, + 0xb7, 0x6b, 0xea, 0xd1, 0x02, 0xc5, 0x3e, 0x05, 0x61, 0x09, 0xc5, 0x3e, 0x45, 0xe1, 0x05, 0x53, + 0xaf, 0x91, 0x81, 0x85, 0x8f, 0xad, 0x07, 0xeb, 0xef, 0xff, 0xe0, 0x37, 0x4e, 0xfd, 0xe4, 0x6c, + 0x72, 0xbc, 0xd2, 0x0f, 0x47, 0x0f, 0x87, 0xd2, 0xdb, 0x28, 0xae, 0xc2, 0x3d, 0x1c, 0x06, 0x83, + 0x87, 0xd8, 0xec, 0xf1, 0x0c, 0xfe, 0xd8, 0xf5, 0x37, 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x18, 0xa4, 0xd2, 0x33, 0x1e, 0x7b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index bc63c4148f..cea78fee10 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1930,6 +1930,7 @@ message ChannelEventUpdate { ChannelCloseSummary closed_channel = 2 [ json_name = "closed_channel" ]; ChannelPoint active_channel = 3 [ json_name = "active_channel" ]; ChannelPoint inactive_channel = 4 [ json_name = "inactive_channel" ]; + PendingUpdate pending_open_channel = 6 [json_name = "pending_open_channel"]; } enum UpdateType { @@ -1937,6 +1938,7 @@ message ChannelEventUpdate { CLOSED_CHANNEL = 1; ACTIVE_CHANNEL = 2; INACTIVE_CHANNEL = 3; + PENDING_OPEN_CHANNEL = 4; } UpdateType type = 5 [ json_name = "type" ]; diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 9ed22f8d7e..63bd594b94 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1467,7 +1467,8 @@ "OPEN_CHANNEL", "CLOSED_CHANNEL", "ACTIVE_CHANNEL", - "INACTIVE_CHANNEL" + "INACTIVE_CHANNEL", + "PENDING_OPEN_CHANNEL" ], "default": "OPEN_CHANNEL" }, @@ -2149,6 +2150,9 @@ "inactive_channel": { "$ref": "#/definitions/lnrpcChannelPoint" }, + "pending_open_channel": { + "$ref": "#/definitions/lnrpcPendingUpdate" + }, "type": { "$ref": "#/definitions/ChannelEventUpdateUpdateType" } diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 5ddf28ab67..c18b60d9a8 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -6460,25 +6460,34 @@ func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTe // Since each of the channels just became open, Bob and Alice should // each receive an open and an active notification for each channel. var numChannelUpds int - const totalNtfns = 2 * numChannels + const totalNtfns = 3 * numChannels verifyOpenUpdatesReceived := func(sub channelSubscription) error { numChannelUpds = 0 for numChannelUpds < totalNtfns { select { case update := <-sub.updateChan: switch update.Type { - case lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL: - if numChannelUpds%2 != 1 { - return fmt.Errorf("expected open" + - "channel ntfn, got active " + + case lnrpc.ChannelEventUpdate_PENDING_OPEN_CHANNEL: + if numChannelUpds%3 != 0 { + return fmt.Errorf("expected " + + "open or active" + + "channel ntfn, got pending open " + "channel ntfn instead") } case lnrpc.ChannelEventUpdate_OPEN_CHANNEL: - if numChannelUpds%2 != 0 { - return fmt.Errorf("expected active" + + if numChannelUpds%3 != 1 { + return fmt.Errorf("expected " + + "pending open or active" + "channel ntfn, got open" + "channel ntfn instead") } + case lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL: + if numChannelUpds%3 != 2 { + return fmt.Errorf("expected " + + "pending open or open" + + "channel ntfn, got active " + + "channel ntfn instead") + } default: return fmt.Errorf("update type mismatch: "+ "expected open or active channel "+ diff --git a/rpcserver.go b/rpcserver.go index 35eec95215..16e0677d2f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3187,6 +3187,16 @@ func (r *rpcServer) SubscribeChannelEvents(req *lnrpc.ChannelEventSubscription, case e := <-channelEventSub.Updates(): var update *lnrpc.ChannelEventUpdate switch event := e.(type) { + case channelnotifier.PendingOpenChannelEvent: + update = &lnrpc.ChannelEventUpdate{ + Type: lnrpc.ChannelEventUpdate_PENDING_OPEN_CHANNEL, + Channel: &lnrpc.ChannelEventUpdate_PendingOpenChannel{ + PendingOpenChannel: &lnrpc.PendingUpdate{ + Txid: event.ChannelPoint.Hash[:], + OutputIndex: event.ChannelPoint.Index, + }, + }, + } case channelnotifier.OpenChannelEvent: channel, err := createRPCOpenChannel(r, graph, event.Channel, true) @@ -5601,7 +5611,9 @@ func (r *rpcServer) SubscribeChannelBackups(req *lnrpc.ChannelBackupSubscription switch e.(type) { // We only care about new/closed channels, so we'll - // skip any events for active/inactive channels. + // skip any events for pending/active/inactive channels. + case channelnotifier.PendingOpenChannelEvent: + continue case channelnotifier.ActiveChannelEvent: continue case channelnotifier.InactiveChannelEvent: diff --git a/server.go b/server.go index a5538483d8..72c6661476 100644 --- a/server.go +++ b/server.go @@ -1113,13 +1113,14 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, // channel bandwidth. return uint16(input.MaxHTLCNumber / 2) }, - ZombieSweeperInterval: 1 * time.Minute, - ReservationTimeout: 10 * time.Minute, - MinChanSize: btcutil.Amount(cfg.MinChanSize), - MaxPendingChannels: cfg.MaxPendingChannels, - RejectPush: cfg.RejectPush, - NotifyOpenChannelEvent: s.channelNotifier.NotifyOpenChannelEvent, - OpenChannelPredicate: chanPredicate, + ZombieSweeperInterval: 1 * time.Minute, + ReservationTimeout: 10 * time.Minute, + MinChanSize: btcutil.Amount(cfg.MinChanSize), + MaxPendingChannels: cfg.MaxPendingChannels, + RejectPush: cfg.RejectPush, + NotifyOpenChannelEvent: s.channelNotifier.NotifyOpenChannelEvent, + OpenChannelPredicate: chanPredicate, + NotifyPendingOpenChannelEvent: s.channelNotifier.NotifyPendingOpenChannelEvent, }) if err != nil { return nil, err From 1cb52491a303d13f1108a68c2cf2addf8781903d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 24 Jan 2020 11:06:06 +0100 Subject: [PATCH 026/562] mod: update btcwallet dependency --- go.mod | 4 ++-- go.sum | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index bdcff838b6..d1a887a2b5 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,10 @@ require ( github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d - github.com/btcsuite/btcwallet v0.11.0 + github.com/btcsuite/btcwallet v0.11.1-0.20200124023827-704cd189ac23 github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 - github.com/btcsuite/btcwallet/walletdb v1.1.0 + github.com/btcsuite/btcwallet/walletdb v1.2.0 github.com/btcsuite/btcwallet/wtxmgr v1.0.0 github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 github.com/coreos/bbolt v1.3.3 diff --git a/go.sum b/go.sum index 4c6503ff1b..b22de20a5d 100644 --- a/go.sum +++ b/go.sum @@ -28,6 +28,8 @@ github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6 github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcwallet v0.11.0 h1:XhwqdhEchy5a0q6R+y3F82roD2hYycPCHovgNyJS08w= github.com/btcsuite/btcwallet v0.11.0/go.mod h1:qtPAohN1ioo0pvJt/j7bZM8ANBWlYWVCVFL0kkijs7s= +github.com/btcsuite/btcwallet v0.11.1-0.20200124023827-704cd189ac23 h1:WDhq9qH16fXAQVg0MO0AAHXtzgSAyVd5Z56vq8WwYHY= +github.com/btcsuite/btcwallet v0.11.1-0.20200124023827-704cd189ac23/go.mod h1:1O1uRHMPXHdwA4/od8nqYqrgclVKp+wtfXUAqHmeRvE= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= @@ -38,6 +40,8 @@ github.com/btcsuite/btcwallet/walletdb v1.0.0 h1:mheT7vCWK5EP6rZzhxsQ7ms9+yX4VE8 github.com/btcsuite/btcwallet/walletdb v1.0.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= github.com/btcsuite/btcwallet/walletdb v1.1.0 h1:JHAL7wZ8pX4SULabeAv/wPO9sseRWMGzE80lfVmRw6Y= github.com/btcsuite/btcwallet/walletdb v1.1.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= +github.com/btcsuite/btcwallet/walletdb v1.2.0 h1:E0+M4jHOToAvGWZ27ew5AaDAHDi6fUiXkjUJUnoEOD0= +github.com/btcsuite/btcwallet/walletdb v1.2.0/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= github.com/btcsuite/btcwallet/wtxmgr v1.0.0 h1:aIHgViEmZmZfe0tQQqF1xyd2qBqFWxX5vZXkkbjtbeA= github.com/btcsuite/btcwallet/wtxmgr v1.0.0/go.mod h1:vc4gBprll6BP0UJ+AIGDaySoc7MdAmZf8kelfNb8CFY= github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 h1:kij1x2aL7VE6gtx8KMIt8PGPgI5GV9LgtHFG5KaEMPY= @@ -200,6 +204,7 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 29ece5fe2451bf94a4c6ff751c304ac0986c09a6 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 24 Jan 2020 11:08:28 +0100 Subject: [PATCH 027/562] keychain: use fast scrypt options for unit tests --- keychain/interface_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/keychain/interface_test.go b/keychain/interface_test.go index a857185588..345754db50 100644 --- a/keychain/interface_test.go +++ b/keychain/interface_test.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcwallet/snacl" "github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/wallet" "github.com/btcsuite/btcwallet/walletdb" @@ -41,6 +42,19 @@ var ( ) func createTestBtcWallet(coinType uint32) (func(), *wallet.Wallet, error) { + // Instruct waddrmgr to use the cranked down scrypt parameters when + // creating new wallet encryption keys. + fastScrypt := waddrmgr.FastScryptOptions + keyGen := func(passphrase *[]byte, config *waddrmgr.ScryptOptions) ( + *snacl.SecretKey, error) { + + return snacl.NewSecretKey( + passphrase, fastScrypt.N, fastScrypt.R, fastScrypt.P, + ) + } + waddrmgr.SetSecretKeyGen(keyGen) + + // Create a new test wallet that uses fast scrypt as KDF. tempDir, err := ioutil.TempDir("", "keyring-lnwallet") if err != nil { return nil, nil, err From 3f45fb3781836c8dc75a2adcf465eb3b7dd576c9 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 17 Jan 2020 23:58:29 +0100 Subject: [PATCH 028/562] walletunlocker: use fast scrypt options for unit tests --- walletunlocker/service_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/walletunlocker/service_test.go b/walletunlocker/service_test.go index 9b497ede1a..fc331f42c5 100644 --- a/walletunlocker/service_test.go +++ b/walletunlocker/service_test.go @@ -10,6 +10,8 @@ import ( "time" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcwallet/snacl" + "github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/wallet" "github.com/lightningnetwork/lnd/aezeed" "github.com/lightningnetwork/lnd/keychain" @@ -35,6 +37,19 @@ var ( ) func createTestWallet(t *testing.T, dir string, netParams *chaincfg.Params) { + // Instruct waddrmgr to use the cranked down scrypt parameters when + // creating new wallet encryption keys. + fastScrypt := waddrmgr.FastScryptOptions + keyGen := func(passphrase *[]byte, config *waddrmgr.ScryptOptions) ( + *snacl.SecretKey, error) { + + return snacl.NewSecretKey( + passphrase, fastScrypt.N, fastScrypt.R, fastScrypt.P, + ) + } + waddrmgr.SetSecretKeyGen(keyGen) + + // Create a new test wallet that uses fast scrypt as KDF. netDir := btcwallet.NetworkDir(dir, netParams) loader := wallet.NewLoader(netParams, netDir, true, 0) _, err := loader.CreateNewWallet( From fabcdf754a07c41de5b86545c0cdc6c8f565d5f0 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Thu, 23 Jan 2020 00:21:12 +0100 Subject: [PATCH 029/562] invoices: fix slow startup with many expired invoices This commit intends to fix slow first startup time when there are many invoices that need to be canceled. The slowdown is caused by a combination of adding invoices to the expiry watcher one-by-one and slow cancellation. Due to slow cancellation and the unbuffered channel which we use to pass invoices to the expiry watcher blocks the registry. With this fix we'll instead batch add invoices to the expiry watcher and thereby won't block the registry startup. --- invoices/invoice_expiry_watcher.go | 105 +++++++++++++++++------- invoices/invoice_expiry_watcher_test.go | 29 +++++++ invoices/invoiceregistry.go | 8 +- 3 files changed, 108 insertions(+), 34 deletions(-) diff --git a/invoices/invoice_expiry_watcher.go b/invoices/invoice_expiry_watcher.go index db9d9cd57f..07c2178080 100644 --- a/invoices/invoice_expiry_watcher.go +++ b/invoices/invoice_expiry_watcher.go @@ -49,7 +49,7 @@ type InvoiceExpiryWatcher struct { // newInvoices channel is used to wake up the main loop when a new invoices // is added. - newInvoices chan *invoiceExpiry + newInvoices chan []*invoiceExpiry wg sync.WaitGroup @@ -61,7 +61,7 @@ type InvoiceExpiryWatcher struct { func NewInvoiceExpiryWatcher(clock clock.Clock) *InvoiceExpiryWatcher { return &InvoiceExpiryWatcher{ clock: clock, - newInvoices: make(chan *invoiceExpiry), + newInvoices: make(chan []*invoiceExpiry), quit: make(chan struct{}), } } @@ -102,15 +102,14 @@ func (ew *InvoiceExpiryWatcher) Stop() { } } -// AddInvoice adds a new invoice to the InvoiceExpiryWatcher. This won't check -// if the invoice is already added and will only add invoices with ContractOpen -// state. -func (ew *InvoiceExpiryWatcher) AddInvoice( - paymentHash lntypes.Hash, invoice *channeldb.Invoice) { +// prepareInvoice checks if the passed invoice may be canceled and calculates +// the expiry time. +func (ew *InvoiceExpiryWatcher) prepareInvoice( + paymentHash lntypes.Hash, invoice *channeldb.Invoice) *invoiceExpiry { if invoice.State != channeldb.ContractOpen { log.Debugf("Invoice not added to expiry watcher: %v", invoice) - return + return nil } realExpiry := invoice.Terms.Expiry @@ -119,20 +118,55 @@ func (ew *InvoiceExpiryWatcher) AddInvoice( } expiry := invoice.CreationDate.Add(realExpiry) - - log.Debugf("Adding invoice '%v' to expiry watcher, expiration: %v", - paymentHash, expiry) - - newInvoiceExpiry := &invoiceExpiry{ + return &invoiceExpiry{ PaymentHash: paymentHash, Expiry: expiry, } +} + +// AddInvoices adds multiple invoices to the InvoiceExpiryWatcher. +func (ew *InvoiceExpiryWatcher) AddInvoices( + invoices []channeldb.InvoiceWithPaymentHash) { + + invoicesWithExpiry := make([]*invoiceExpiry, 0, len(invoices)) + for _, invoiceWithPaymentHash := range invoices { + newInvoiceExpiry := ew.prepareInvoice( + invoiceWithPaymentHash.PaymentHash, &invoiceWithPaymentHash.Invoice, + ) + if newInvoiceExpiry != nil { + invoicesWithExpiry = append(invoicesWithExpiry, newInvoiceExpiry) + } + } + + if len(invoicesWithExpiry) > 0 { + log.Debugf("Added %v invoices to the expiry watcher: %v", + len(invoicesWithExpiry)) + select { + case ew.newInvoices <- invoicesWithExpiry: + // Select on quit too so that callers won't get blocked in case + // of concurrent shutdown. + case <-ew.quit: + } + } +} - select { - case ew.newInvoices <- newInvoiceExpiry: - case <-ew.quit: +// AddInvoice adds a new invoice to the InvoiceExpiryWatcher. This won't check +// if the invoice is already added and will only add invoices with ContractOpen +// state. +func (ew *InvoiceExpiryWatcher) AddInvoice( + paymentHash lntypes.Hash, invoice *channeldb.Invoice) { + + newInvoiceExpiry := ew.prepareInvoice(paymentHash, invoice) + if newInvoiceExpiry != nil { + log.Debugf("Adding invoice '%v' to expiry watcher, expiration: %v", + paymentHash, newInvoiceExpiry.Expiry) + + select { + case ew.newInvoices <- []*invoiceExpiry{newInvoiceExpiry}: // Select on quit too so that callers won't get blocked in case // of concurrent shutdown. + case <-ew.quit: + } } } @@ -147,13 +181,13 @@ func (ew *InvoiceExpiryWatcher) nextExpiry() <-chan time.Time { return nil } -// cancelExpiredInvoices will cancel all expired invoices and removes them from -// the expiry queue. -func (ew *InvoiceExpiryWatcher) cancelExpiredInvoices() { - for !ew.expiryQueue.Empty() { +// cancelNextExpiredInvoice will cancel the next expired invoice and removes +// it from the expiry queue. +func (ew *InvoiceExpiryWatcher) cancelNextExpiredInvoice() { + if !ew.expiryQueue.Empty() { top := ew.expiryQueue.Top().(*invoiceExpiry) if !top.Expiry.Before(ew.clock.Now()) { - break + return } err := ew.cancelInvoice(top.PaymentHash) @@ -174,18 +208,33 @@ func (ew *InvoiceExpiryWatcher) mainLoop() { for { // Cancel any invoices that may have expired. - ew.cancelExpiredInvoices() + ew.cancelNextExpiredInvoice() select { - case <-ew.nextExpiry(): - // Wait until the next invoice expires, then cancel expired invoices. + + case invoicesWithExpiry := <-ew.newInvoices: + // Take newly forwarded invoices with higher priority + // in order to not block the newInvoices channel. + for _, invoiceWithExpiry := range invoicesWithExpiry { + ew.expiryQueue.Push(invoiceWithExpiry) + } continue - case newInvoiceExpiry := <-ew.newInvoices: - ew.expiryQueue.Push(newInvoiceExpiry) + default: + select { - case <-ew.quit: - return + case <-ew.nextExpiry(): + // Wait until the next invoice expires. + continue + + case invoicesWithExpiry := <-ew.newInvoices: + for _, invoiceWithExpiry := range invoicesWithExpiry { + ew.expiryQueue.Push(invoiceWithExpiry) + } + + case <-ew.quit: + return + } } } } diff --git a/invoices/invoice_expiry_watcher_test.go b/invoices/invoice_expiry_watcher_test.go index 8bfdfd6933..8940063bc9 100644 --- a/invoices/invoice_expiry_watcher_test.go +++ b/invoices/invoice_expiry_watcher_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lntypes" ) @@ -123,3 +124,31 @@ func TestInvoiceExpiryWithPendingAndExpiredInvoices(t *testing.T) { test.watcher.Stop() test.checkExpectations() } + +// Tests adding multiple invoices at once. +func TestInvoiceExpiryWhenAddingMultipleInvoices(t *testing.T) { + t.Parallel() + test := newInvoiceExpiryWatcherTest(t, testTime, 5, 5) + var invoices []channeldb.InvoiceWithPaymentHash + for hash, invoice := range test.testData.expiredInvoices { + invoices = append(invoices, + channeldb.InvoiceWithPaymentHash{ + Invoice: *invoice, + PaymentHash: hash, + }, + ) + } + for hash, invoice := range test.testData.pendingInvoices { + invoices = append(invoices, + channeldb.InvoiceWithPaymentHash{ + Invoice: *invoice, + PaymentHash: hash, + }, + ) + } + + test.watcher.AddInvoices(invoices) + time.Sleep(testTimeout) + test.watcher.Stop() + test.checkExpectations() +} diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index ea10750b85..4b3a1b2d8e 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -198,12 +198,8 @@ func (i *InvoiceRegistry) populateExpiryWatcher() error { return err } - for idx := range pendingInvoices { - i.expiryWatcher.AddInvoice( - pendingInvoices[idx].PaymentHash, &pendingInvoices[idx].Invoice, - ) - } - + log.Debugf("Adding %v pending invoices to the expiry watcher") + i.expiryWatcher.AddInvoices(pendingInvoices) return nil } From 548f42f6e73b18f795afbddc3850662d299e9ce2 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 8 Jan 2020 17:21:17 +0100 Subject: [PATCH 030/562] doc: add Operational Safety Guidelines document --- README.md | 7 + docs/safety.md | 438 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 445 insertions(+) create mode 100644 docs/safety.md diff --git a/README.md b/README.md index c62b2e2d17..8990132c11 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,13 @@ discuss various aspects of `lnd` and also Lightning in general. * channel #lnd * [webchat](https://webchat.freenode.net/?channels=lnd) +## Safety + +When operating a mainnet `lnd` node, please refer to our [operational safety +guildelines](docs/safety.md). It is important to note that `lnd` is still +**beta** software and that ignoring these operational guidelines can lead to +loss of funds. + ## Security The developers of `lnd` take security _very_ seriously. The disclosure of diff --git a/docs/safety.md b/docs/safety.md new file mode 100644 index 0000000000..6f3d74cc83 --- /dev/null +++ b/docs/safety.md @@ -0,0 +1,438 @@ +# lnd Operational Safety Guidelines + +## Table of Contents + +* [Overview](#overview) + - [aezeed](#aezeed) + - [Wallet password](#wallet-password) + - [TLS](#tls) + - [Macaroons](#macaroons) + - [Static Channel Backups (SCBs)](#static-channel-backups-scbs) + - [Static remote keys](#static-remote-keys) +* [Best practices](#best-practices) + - [aezeed storage](#aezeed-storage) + - [File based backups](#file-based-backups) + - [Keeping Static Channel Backups (SCBs) safe](#keeping-static-channel-backups-scb-safe) + - [Keep `lnd` updated](#keep-lnd-updated) + - [Zombie channels](#zombie-channels) + - [Migrating a node to a new device](#migrating-a-node-to-a-new-device) + - [Migrating a node from clearnet to Tor](#migrating-a-node-from-clearnet-to-tor) + - [Prevent data corruption](#prevent-data-corruption) + - [Don't interrupt `lncli` commands](#dont-interrupt-lncli-commands) + - [Regular accounting/monitoring](#regular-accountingmonitoring) + - [Pruned bitcoind node](#pruned-bitcoind-node) + - [The `--noseedbackup` flag](#the---noseedbackup-flag) + +## Overview + +This chapter describes the security/safety mechanisms that are implemented in +`lnd`. We encourage every person that is planning on putting mainnet funds into +a Lightning Network channel using `lnd` to read this guide carefully. +As of this writing, `lnd` is still in beta and it is considered `#reckless` to +put any life altering amounts of BTC into the network. +That said, we constantly put in a lot of effort to make `lnd` safer to use and +more secure. We will update this documentation with each safety mechanism that +we implement. + +The first part of this document describes the security elements that are used in +`lnd` and how they work on a high level. +The second part is a list of best practices that has crystallized from bug +reports, developer recommendations and experiences from a lot of individuals +running mainnet `lnd` nodes during the last 18 months and counting. + +### aezeed + +This is what all the on-chain private keys are derived from. `aezeed` is similar +to BIP39 as it uses the same word list to encode the seed as a mnemonic phrase. +But this is where the similarities end, because `aezeed` is _not_ compatible +with BIP39. The 24 words of `aezeed` encode a 128 bit entropy (the seed itself), +a wallet birthday (days since BTC genesis block) and a version. +This data is _encrypted_ with a password using the AEZ cipher suite (hence the +name). Encrypting the content instead of using the password to derive the HD +extended root key has the advantage that the password can actually be checked +for correctness and can also be changed without affecting any of the derived +keys. +A BIP for the `aezeed` scheme is being written and should be published soon. + +Important to know: +* As with any bitcoin seed phrase, never reveal this to any person and store + the 24 words (and the password) in a safe place. +* You should never run two different `lnd` nodes with the same seed! Even if + they aren't running at the same time. This will lead to strange/unpredictable + behavior or even loss of funds. To migrate an `lnd` node to a new device, + please see the [node migration section](#migrating-a-node-to-a-new-device). +* For more technical information [see the aezeed README](../aezeed/README.md). + +### Wallet password + +The wallet password is one of the first things that has to be entered if a new +wallet is created using `lnd`. It is completely independent from the `aezeed` +cipher seed passphrase (which is optional). The wallet password is used to +encrypt the sensitive parts of `lnd`'s databases, currently some parts of +`wallet.db` and `macaroons.db`. Loss of this password does not necessarily +mean loss of funds, as long as the `aezeed` passphrase is still available. +But the node will need to be restored using the +[SCB restore procedure](recovery.md). + +### TLS + +By default the two API connections `lnd` offers (gRPC on port 10009 and REST on +port 8080) use TLS with a self-signed certificate for transport level security. +Specifying the certificate on the client side (for example `lncli`) is only a +protection against man-in-the-middle attacks and does not provide any +authentication. In fact, `lnd` will never even see the certificate that is +supplied to `lncli` with the `--tlscertpath` argument. `lncli` only uses that +certificate to verify it is talking to the correct gRPC server. +If the key/certificate pair (`tls.cert` and `tls.key` in the main `lnd` data +directory) is missing on startup, a new self-signed key/certificate pair is +generated. Clients connecting to `lnd` then have to use the new certificate +to verify they are talking to the correct server. + +### Macaroons + +Macaroons are used as the main authentication method in `lnd`. A macaroon is a +cryptographically verifiable token, comparable to a [JWT](https://jwt.io/) +or other form of API access token. In `lnd` this token consists of a _list of +permissions_ (what operations does the user of the token have access to) and a +set of _restrictions_ (e.g. token expiration timestamp, IP address restriction). +`lnd` does not keep track of the individual macaroons issued, only the key that +was used to create (and later verify) them. That means, individual tokens cannot +currently be invalidated, only all of them at once. +See the [high-level macaroons documentation](macaroons.md) or the [technical +README](../macaroons/README.md) for more information. + +Important to know: +* Deleting the `*.macaroon` files in the `/data/chain/bitcoin/mainnet/` + folder will trigger `lnd` to recreate the default macaroons. But this does + **NOT** invalidate clients that use an old macaroon. To make sure all + previously generated macaroons are invalidated, the `macaroons.db` has to be + deleted as well as all `*.macaroon`. + +### Static Channel Backups (SCBs) + +A Static Channel Backup is a piece of data that contains all _static_ +information about a channel, like funding transaction, capacity, key derivation +paths, remote node public key, remote node last known network addresses and +some static settings like CSV timeout and min HTLC setting. +Such a backup can either be obtained as a file containing entries for multiple +channels or by calling RPC methods to get individual (or all) channel data. +See the section on [keeping SCBs safe](#keeping-static-channel-backups-scb-safe) +for more information. + +What the SCB does **not** contain is the current channel balance (or the +associated commitment transaction). So how can a channel be restored using +SCBs? +That's the important part: _A channel cannot be restored using SCBs_, but the +funds that are in the channel can be claimed. The restore procedure relies on +the Data Loss Prevention (DLP) protocol which works by connecting to the remote +node and asking them to **force close** the channel and hand over the needed +information to sweep the on-chain funds that belong to the local node. +Because of this, [restoring a node from SCB](recovery.md) should be seen as an +emergency measure as all channels will be closed and on-chain fees incur to the +party that opened the channel initially. +To migrate an existing, working node to a new device, SCBs are _not_ the way to +do it. See the section about +[migrating a node](#migrating-a-node-to-a-new-device) on how to do it correctly. + +Important to know: +* [Restoring a node from SCB](recovery.md) will force-close all channels + contained in that file. +* Restoring a node from SCB relies on the remote node of each channel to be + online and respond to the DLP protocol. That's why it's important to + [get rid of zombie channels](#zombie-channels) because they cannot be + recovered using SCBs. +* The SCB data is encrypted with a key from the seed the node was created with. + A node can therefore only be restored from SCB if the seed is also known. + +### Static remote keys + +Since version `v0.8.0-beta`, `lnd` supports the `option_static_remote_key` (also +known as "safu commitments"). All new channels will be opened with this option +enabled by default, if the other node also supports it. +In essence, this change makes it possible for a node to sweep their channel +funds if the remote node force-closes, without any further communication between +the nodes. Previous to this change, your node needed to get a random channel +secret (called the `per_commit_point`) from the remote node even if they +force-closed the channel, which could make recovery very difficult. + +## Best practices + +### aezeed storage + +When creating a new wallet, `lnd` will print out 24 words to write down, which +is the wallet's seed (in the [aezeed](#aezeed) format). That seed is optionally +encrypted with a passphrase, also called the _cipher seed passphrase_. +It is absolutely important to write both the seed and, if set, the password down +and store it in a safe place as **there is no way of exporting the seed from an +lnd wallet**. When creating the wallet, after printing the seed to the command +line, it is hashed and only the hash (or to be more exact, the BIP32 extended +root key) is stored in the `wallet.db` file. +There is +[a tool being worked on](https://github.com/lightningnetwork/lnd/pull/2373) +that can extract the BIP32 extended root key but currently you cannot restore +lnd with only this root key. + +Important to know: +* Setting a password/passphrase for the aezeed is meant to protect it from + an attacker that finds the paper/storage device. Writing down the password + alongside the 24 seed words does not enhance the security in any way. + Therefore the password should be stored in a separate place. + +### File based backups + +There is a lot of confusion and also some myths about how to best backup the +off-chain funds of an `lnd` node. Making a mistake here is also still the single +biggest risk of losing off-chain funds, even though we do everything to mitigate +those risks. + +**What files can/should I regularly backup?** +The single most important file that needs to be backed up whenever it changes +is the `/data/chain/bitcoin/mainnet/channel.backup` file which holds +the Static Channel Backups (SCBs). This file is only updated every time `lnd` +starts, a channel is opened or a channel is closed. + +Most consumer Lightning wallet apps upload the file to the cloud automatically. + +See the [SCB chapter](#static-channel-backups-scbs) for more +information on how to use the file to restore channels. + +**What files should never be backed up to avoid problems?** +This is a bit of a trick question, as making the backup is not the problem. +Restoring/using an old version of a specific file called +`/data/graph/mainnet/channel.db` is what is very risky and should +_never_ be done! +This requires some explanation: +The way LN channels are currently set up (until `eltoo` is implemented) is that +both parties agree on a current balance. To make sure none of the two peers in +a channel ever try to publish an old state of that balance, they both hand over +their keys to the other peer that gives them the means to take _all_ funds (not +just their agreed upon part) from a channel, if an _old_ state is ever +published. Therefore, having an old state of a channel basically means +forfeiting the balance to the other party. + +As payments in `lnd` can be made multiple times a second, it's very hard to +make a backup of the channel database every time it is updated. And even if it +can be technically done, the confidence that a particular state is certainly the +most up-to-date can never be very high. That's why the focus should be on +[making sure the channel database is not corrupted](#prevent-data-corruption), +[closing out the zombie channels](#zombie-channels) and keeping your SCBs safe. + +### Keeping Static Channel Backups (SCB) safe + +As mentioned in the previous chapter, there is a file where `lnd` stores and +updates a backup of all channels whenever the node is restarted, a new channel +is opened or a channel is closed: +`/data/chain/bitcoin/mainnet/channel.backup` + +One straight-forward way of backing that file up is to create a file watcher and +react whenever the file is changed. Here is an example script that +[automatically makes a copy of the file whenever it changes](https://gist.github.com/alexbosworth/2c5e185aedbdac45a03655b709e255a3). + +Other ways of obtaining SCBs for a node's channels are +[described in the recovery documentation](recovery.md#obtaining-scbs). + +Because the backup file is encrypted with a key from the seed the node was +created with, it can safely be stored on a cloud storage or any other storage +medium. Many consumer focused wallet smartphone apps automatically store a +backup file to the cloud, if the phone is set up to allow it. + +### Keep `lnd` updated + +With every larger update of `lnd`, new security features are added. Users are +always encouraged to update their nodes as soon as possible. This also helps the +network in general as new safety features that require compatibility among nodes +can be used sooner. + +### Zombie channels + +Zombie channels are channels that are most likely dead but are still around. +This can happen if one of the channel peers has gone offline for good (possibly +due to a failure of some sort) and didn't close its channels. The other, still +online node doesn't necessarily know that its partner will never come back +online. + +Funds that are in such channels are at great risk, as is described quite +dramatically in +[this article](https://medium.com/@gcomxx/get-rid-of-those-zombie-channels-1267d5a2a708?) +. + +The TL;DR of the article is that if you have funds in a zombie channel and you +need to recover your node after a failure, SCBs won't be able to recover those +funds. Because SCB restore +[relies on the remote node cooperating](#static-channel-backups-scbs). + +That's why it's important to **close channels with peers that have been +offline** for a length of time as a precautionary measure. + +Of course this might not be good advice for a routing node operator that wants +to support mobile users and route for them. Nodes running on a mobile device +tend to be offline for long periods of time. It would be bad for those users if +they needed to open a new channel every time they want to use the wallet. +Most mobile wallets only open private channels as they do not intend to route +payments through them. A routing node operator should therefore take into +account if a channel is public or private when thinking about closing it. + +### Migrating a node to a new device + +As mentioned in the chapters [aezeed](#aezeed) and +[SCB](#static-channel-backups-scbs) you should never use the same seed on two +different nodes and restoring from SCB is not a migration but an emergency +procedure. +What is the correct way to migrate an existing node to a new device? There is +an easy way that should work for most people and there's the harder/costlier +fallback way to do it. + +**Option 1: Move the whole data directory to the new device** +This option works very well if the new device runs the same operating system on +the same architecture. If that is the case, the whole `/home//.lnd` +directory in Linux (or `$HOME/Library/Application Support/lnd` in MacOS, +`%LOCALAPPDATA%\lnd` in Windows) can be moved to the new device and `lnd` +started there. It is important to shut down `lnd` on the old device before +moving the directory! +**Not supported/untested** is moving the data directory between different +operating systems (for example `MacOS` -> `Linux`) or different system +architectures (for example `32bit` -> `64bit` or `ARM` -> `amd64`). Data +corruption or unexpected behavior can be the result. Users switching between +operating systems or architectures should always use Option 2! + +**Option 2: Start from scratch** +If option 1 does not work or is too risky, the safest course of action is to +initialize the existing node again from scratch. Unfortunately this incurs some +on-chain fee costs as all channels will need to be closed. Using the same seed +means restoring the same network node identity as before. If a new identity +should be created, a new seed needs to be created. +Follow these steps to create the **same node (with the same seed)** from +scratch: +1. On the old device, close all channels (`lncli closeallchannels`). The + command can take up to several minutes depending on the number of channels. + **Do not interrupt the command!** +1. Wait for all channels to be fully closed. If some nodes don't respond to the + close request it can be that `lnd` will go ahead and force close those + channels. This means that the local balance will be time locked for up to + two weeks (depending on the channel size). Check `lncli pendingchannels` to + see if any channels are still in the process of being force closed. +1. After all channels are fully closed (and `lncli pendingchannels` lists zero + channels), `lnd` can be shut down on the old device. +1. Start `lnd` on the new device and create a new wallet with the existing seed + that was used on the old device (answer "yes" when asked if an existing seed + should be used). +1. Wait for the wallet to rescan the blockchain. This can take up to several + hours depending on the age of the seed and the speed of the chain backend. +1. After the chain is fully synced (`lncli getinfo` shows + `"synced_to_chain": true`) the on-chain funds from the previous device should + now be visible on the new device as well and new channels can be opened. + +**What to do after the move** +If things don't work as expected on the moved or re-created node, consider this +list things that possibly need to be changed to work on a new device: +* In case the new device has a different hostname and TLS connection problems + occur, delete the `tls.key` and `tls.cert` files in the data directory and + restart `lnd` to recreate them. +* If an external IP is set (either with `--externalip` or `--tlsextraip`) these + might need to be changed if the new machine has a different address. Changing + the `--tlsextraip` setting also means regenerating the certificate pair. See + point 1. +* If port `9735` (or `10009` for gRPC) was forwarded on the router, these + forwarded ports need to point to the new device. The same applies to firewall + rules. +* It might take more than 24 hours for a new IP address to be visible on + network explorers. +* If channels show as offline after several hours, try to manually connect to + the remote peer. They might still try to reach `lnd` on the old address. + +### Migrating a node from clearnet to Tor + +If an `lnd` node has already been connected to the internet with an IPv4 or IPv6 +(clearnet) address and has any non-private channels, this connection between +channels and IP address is known to the network and cannot be deleted. +Starting the same node with the same identity and channels using Tor is trivial +to link back to any previously used clearnet IP address and does therefore not +provide any privacy benefits. +The following steps are recommended to cut all links between the old clearnet +node and the new Tor node: +1. Close all channels on the old node and wait for them to fully close. +1. Send all on-chain funds of the old node through a Coin Join service (like + Wasabi or Samurai/Whirlpool) until a sufficiently high anonymity set is + reached. +1. Create a new `lnd` node with a **new seed** that is only connected to Tor + and generate an on-chain address on the new node. +1. Send the mixed/coinjoined coins to the address of the new node. +1. Start opening channels. +1. Check an online network explorer that no IPv4 or IPv6 address is associated + with the new node's identity. + +### Prevent data corruption + +Many problems while running an `lnd` node can be prevented by avoiding data +corruption in the channel database (`/data/graph/mainnet/channel.db`). + +The following (non-exhaustive) list of things can lead to data corruption: +* A spinning hard drive gets a physical shock. +* `lnd`'s main data directory being written on an SD card or USB thumb drive + (SD cards and USB thumb drives _must_ be considered unsafe for critical files + that are written to very often, as the channel DB is). +* `lnd`'s main data directory being written to a network drive without + `fsync` support. +* Unclean shutdown of `lnd`. +* Aborting channel operation commands (see next chapter). +* Not enough disk space for a growing channel DB file. +* Moving `lnd`'s main data directory between different operating systems/ + architectures. + +To avoid most of these factors, it is recommended to store `lnd`'s main data +directory on an Solid State Drive (SSD) of a reliable manufacturer. +An alternative or extension to that is to use a replicated disk setup. Making +sure a power failure does not interrupt the node by running a UPS ( +uninterruptible power supply) might also make sense depending on the reliability +of the local power grid and the amount of funds at stake. + +### Don't interrupt `lncli` commands + +Things can start to take a while to execute if a node has more than 50 to 100 +channels. It is extremely important to **never interrupt an `lncli` command** +if it is manipulating the channel database, which is true for the following +commands: + - `openchannel` + - `closechannel` and `closeallchannels` + - `abandonchannel` + - `updatechanpolicy` + - `restorechanbackup` + +Interrupting any of those commands can lead to an inconsistent state of the +channel database and unpredictable behavior. If it is uncertain if a command +is really stuck or if the node is still working on it, a look at the log file +can help to get an idea. + +### Regular accounting/monitoring + +Regular monitoring of a node and keeping track of the movement of funds can help +prevent problems. Tools like [`lndmon`](https://github.com/lightninglabs/lndmon) +can assist with these tasks. + +### Pruned bitcoind node + +Running `lnd` connected to a `bitcoind` node that is running in prune mode is +not supported! `lnd` needs to verify the funding transaction of every channel +in the network and be able to retrieve that information from `bitcoind` which +it cannot deliver when that information is pruned away. + +In theory pruning away all blocks _before_ the SegWit activation would work +as LN channels rely on SegWit. But this has neither been tested nor would it +be recommended/supported. + +In addition to not running a pruned node, it is recommended to run `bitcoind` +with the `-txindex` flag for performance reasons, though this is not strictly +required. + +Multiple `lnd` nodes can run off of a single `bitcoind` instance. There will be +connection/thread/performance limits at some number of `lnd` nodes but in +practice running 2 or 3 `lnd` instances per `bitcoind` node didn't show any +problems. + +### The `--noseedbackup` flag + +This is a flag that is only used for integration tests and should **never** be +used on mainnet! Turning this flag on means that the 24 word seed will not be +shown when creating a wallet. The seed is required to restore a node in case +of data corruption and without it all funds (on-chain and off-chain) are +being put at risk. From c8b7108eeb8c681baaff5d62097f7a1d07da857c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 27 Jan 2020 15:06:01 +0100 Subject: [PATCH 031/562] rpcserver: instruct REST marshaler to emit default values This change instructs the REST proxy server to overwrite its default JSON marshaler settings. That allows us to set EmitDefaults to true which will result in all JSON fields returned in REST responses to be fully populated, even if their values are falsey. --- rpcserver.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index 16e0677d2f..f4e13cd65f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -750,6 +750,17 @@ func (r *rpcServer) Start() error { } } + // The default JSON marshaler of the REST proxy only sets OrigName to + // true, which instructs it to use the same field names as specified in + // the proto file and not switch to camel case. What we also want is + // that the marshaler prints all values, even if they are falsey. + customMarshalerOption := proxy.WithMarshalerOption( + proxy.MIMEWildcard, &proxy.JSONPb{ + OrigName: true, + EmitDefaults: true, + }, + ) + // Finally, start the REST proxy for our gRPC server above. We'll ensure // we direct LND to connect to its loopback address rather than a // wildcard to prevent certificate issues when accessing the proxy @@ -757,7 +768,7 @@ func (r *rpcServer) Start() error { // // TODO(roasbeef): eventually also allow the sub-servers to themselves // have a REST proxy. - mux := proxy.NewServeMux() + mux := proxy.NewServeMux(customMarshalerOption) err := lnrpc.RegisterLightningHandlerFromEndpoint( context.Background(), mux, r.restProxyDest, From de88a4b17427eb489c57d316d3073e6cbc11597f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 28 Jan 2020 06:43:07 -0800 Subject: [PATCH 032/562] record: add AMP record and encode/decode methods --- record/amp.go | 107 ++++++++++++++++++++++++++++++++++++++++++ record/record_test.go | 30 +++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 record/amp.go diff --git a/record/amp.go b/record/amp.go new file mode 100644 index 0000000000..72b4cbf427 --- /dev/null +++ b/record/amp.go @@ -0,0 +1,107 @@ +package record + +import ( + "fmt" + "io" + + "github.com/lightningnetwork/lnd/tlv" +) + +// 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 + +// AMP is a record that encodes the fields necessary for atomic multi-path +// payments. +type AMP struct { + rootShare [32]byte + setID [32]byte + childIndex uint16 +} + +// 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 { + return &{ + rootShare: rootShare, + setID: setID, + childIndex: childIndex, + } +} + +// RootShare returns the root share contained in the AMP record. +func (a *AMP) RootShare() [32]byte { + return a.rootShare +} + +// SetID returns the set id contained in the AMP record. +func (a *AMP) SetID() [32]byte { + return a.setID +} + +// ChildIndex returns the child index contained in the AMP record. +func (a *AMP) ChildIndex() uint16 { + return a.childIndex +} + +// AMPEncoder writes the AMP record to the provided io.Writer. +func AMPEncoder(w io.Writer, val interface{}, buf *[8]byte) error { + if v, ok := val.(*AMP); ok { + if err := tlv.EBytes32(w, &v.rootShare, buf); err != nil { + return err + } + + if err := tlv.EBytes32(w, &v.setID, buf); err != nil { + return err + } + + return tlv.ETUint16T(w, v.childIndex, buf) + } + return tlv.NewTypeForEncodingErr(val, "AMP") +} + +const ( + // minAMPLength is the minimum length of a serialized AMP TLV record, + // which occurs when the truncated encoding of child_index takes 0 + // bytes, leaving only the root_share and set_id. + minAMPLength = 64 + + // 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 +) + +// AMPDecoder reads the AMP record from the provided io.Reader. +func AMPDecoder(r io.Reader, val interface{}, buf *[8]byte, l uint64) error { + if v, ok := val.(*AMP); ok && minAMPLength <= l && l <= maxAMPLength { + if err := tlv.DBytes32(r, &v.rootShare, buf, 32); err != nil { + return err + } + + if err := tlv.DBytes32(r, &v.setID, buf, 32); err != nil { + return err + } + + return tlv.DTUint16(r, &v.childIndex, buf, l-64) + } + return tlv.NewTypeForDecodingErr(val, "AMP", l, maxAMPLength) +} + +// Record returns a tlv.Record that can be used to encode or decode this record. +func (a *AMP) Record() tlv.Record { + return tlv.MakeDynamicRecord( + AMPOnionType, a, a.PayloadSize, AMPEncoder, AMPDecoder, + ) +} + +// PayloadSize returns the size this record takes up in encoded form. +func (a *AMP) PayloadSize() uint64 { + return 32 + 32 + tlv.SizeTUint16(a.childIndex) +} + +// String returns a human-readble description of the amp payload fields. +func (a *AMP) String() string { + return fmt.Sprintf("root_share=%x set_id=%x child_index=%d", + a.rootShare, a.setID, a.childIndex) +} diff --git a/record/record_test.go b/record/record_test.go index 052e2f1f0d..8c39790ed8 100644 --- a/record/record_test.go +++ b/record/record_test.go @@ -17,8 +17,11 @@ type recordEncDecTest struct { } var ( - testTotal = lnwire.MilliSatoshi(45) - testAddr = [32]byte{0x01, 0x02} + testTotal = lnwire.MilliSatoshi(45) + testAddr = [32]byte{0x01, 0x02} + testShare = [32]byte{0x03, 0x04} + testSetID = [32]byte{0x05, 0x06} + testChildIndex = uint16(17) ) var recordEncDecTests = []recordEncDecTest{ @@ -40,6 +43,29 @@ var recordEncDecTests = []recordEncDecTest{ } }, }, + { + name: "amp", + encRecord: func() tlv.RecordProducer { + return record.NewAMP( + testShare, testSetID, testChildIndex, + ) + }, + decRecord: func() tlv.RecordProducer { + return new(record.AMP) + }, + assert: func(t *testing.T, r interface{}) { + amp := r.(*record.AMP) + if amp.RootShare() != testShare { + t.Fatal("incorrect root share") + } + if amp.SetID() != testSetID { + t.Fatal("incorrect set id") + } + if amp.ChildIndex() != testChildIndex { + t.Fatal("incorrect child index") + } + }, + }, } // TestRecordEncodeDecode is a generic test framework for custom TLV records. It From 0cb27151e50d2d6ea7a6144d962db3223a110fa7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 28 Jan 2020 06:43:34 -0800 Subject: [PATCH 033/562] routing/route: add AMP record to payload size calcs --- routing/route/route.go | 25 +++++++++++++++++++++++++ routing/route/route_test.go | 5 +++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/routing/route/route.go b/routing/route/route.go index 90a407e388..f4de728fc7 100644 --- a/routing/route/route.go +++ b/routing/route/route.go @@ -34,6 +34,10 @@ var ( // record to an intermediate hop, only final hops can receive MPP // records. ErrIntermediateMPPHop = errors.New("cannot send MPP to intermediate") + + // ErrAMPMissingMPP is returned when the caller tries to attach an AMP + // record but no MPP record is presented for the final hop. + ErrAMPMissingMPP = errors.New("cannot send AMP without MPP record") ) // Vertex is a simple alias for the serialization of a compressed Bitcoin @@ -111,6 +115,10 @@ type Hop struct { // only be set for the final hop. MPP *record.MPP + // AMP encapsulates the data required for option_amp. This field should + // only be set for the final hop. + AMP *record.AMP + // CustomRecords if non-nil are a set of additional TLV records that // should be included in the forwarding instructions for this node. CustomRecords record.CustomSet @@ -168,6 +176,18 @@ func (h *Hop) PackHopPayload(w io.Writer, nextChanID uint64) error { } } + // If an AMP record is destined for this hop, ensure that we only ever + // attach it if we also have an MPP record. We can infer that this is + // already a final hop if MPP is non-nil otherwise we would have exited + // above. + if h.AMP != nil { + if h.MPP != nil { + records = append(records, h.AMP.Record()) + } else { + return ErrAMPMissingMPP + } + } + // Append any custom types destined for this hop. tlvRecords := tlv.MapToRecords(h.CustomRecords) records = append(records, tlvRecords...) @@ -217,6 +237,11 @@ func (h *Hop) PayloadSize(nextChanID uint64) uint64 { addRecord(record.MPPOnionType, h.MPP.PayloadSize()) } + // Add amp if present. + if h.AMP != nil { + addRecord(record.AMPOnionType, h.AMP.PayloadSize()) + } + // Add custom records. for k, v := range h.CustomRecords { addRecord(tlv.Type(k), uint64(len(v))) diff --git a/routing/route/route_test.go b/routing/route/route_test.go index 6c32d8be3f..df1b9fc3c4 100644 --- a/routing/route/route_test.go +++ b/routing/route/route_test.go @@ -71,8 +71,8 @@ var ( testAddr = [32]byte{0x01, 0x02} ) -// TestMPPHop asserts that a Hop will encode a non-nil to final nodes, and fail -// when trying to send to intermediaries. +// TestMPPHop asserts that a Hop will encode a non-nil MPP to final nodes, and +// fail when trying to send to intermediaries. func TestMPPHop(t *testing.T) { t.Parallel() @@ -123,6 +123,7 @@ func TestPayloadSize(t *testing.T) { AmtToForward: 1200, OutgoingTimeLock: 700000, MPP: record.NewMPP(500, [32]byte{}), + AMP: record.NewAMP([32]byte{}, [32]byte{}, 8), CustomRecords: map[uint64][]byte{ 100000: {1, 2, 3}, 1000000: {4, 5}, From 9fc197d8b191de51cb4afc42bf8ffbb2217469b5 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 28 Jan 2020 06:43:44 -0800 Subject: [PATCH 034/562] routing/route: fix TestMPPHop comment --- routing/route/route_test.go | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/routing/route/route_test.go b/routing/route/route_test.go index df1b9fc3c4..2095430b8c 100644 --- a/routing/route/route_test.go +++ b/routing/route/route_test.go @@ -101,6 +101,47 @@ func TestMPPHop(t *testing.T) { } } +// TestAMPHop asserts that a Hop will encode a non-nil AMP to final nodes of an +// MPP record is also present, and fail otherwise. +func TestAMPHop(t *testing.T) { + t.Parallel() + + hop := Hop{ + ChannelID: 1, + OutgoingTimeLock: 44, + AmtToForward: testAmt, + LegacyPayload: false, + AMP: record.NewAMP([32]byte{}, [32]byte{}, 3), + } + + // Encoding an AMP record to an intermediate hop w/o an MPP record + // should result in a failure. + var b bytes.Buffer + err := hop.PackHopPayload(&b, 2) + if err != ErrAMPMissingMPP { + t.Fatalf("expected err: %v, got: %v", + ErrAMPMissingMPP, err) + } + + // Encoding an AMP record to a final hop w/o an MPP record should result + // in a failure. + b.Reset() + err = hop.PackHopPayload(&b, 0) + if err != ErrAMPMissingMPP { + t.Fatalf("expected err: %v, got: %v", + ErrAMPMissingMPP, err) + } + + // Encoding an AMP record to a final hop w/ an MPP record should be + // successful. + hop.MPP = record.NewMPP(testAmt, testAddr) + b.Reset() + err = hop.PackHopPayload(&b, 0) + if err != nil { + t.Fatalf("expected err: %v, got: %v", nil, err) + } +} + // TestPayloadSize tests the payload size calculation that is provided by Hop // structs. func TestPayloadSize(t *testing.T) { From bdb20d00532f19177467547cb07d27d9dffa1d28 Mon Sep 17 00:00:00 2001 From: nsa Date: Tue, 28 Jan 2020 20:20:35 -0500 Subject: [PATCH 035/562] fuzz/wtwire: adding wtwire fuzzers --- fuzz/wtwire/create_session.go | 20 ++++++++ fuzz/wtwire/create_session_reply.go | 20 ++++++++ fuzz/wtwire/delete_session.go | 20 ++++++++ fuzz/wtwire/delete_session_reply.go | 20 ++++++++ fuzz/wtwire/error.go | 20 ++++++++ fuzz/wtwire/fuzz_utils.go | 75 +++++++++++++++++++++++++++++ fuzz/wtwire/init.go | 20 ++++++++ fuzz/wtwire/state_update.go | 20 ++++++++ fuzz/wtwire/state_update_reply.go | 20 ++++++++ 9 files changed, 235 insertions(+) create mode 100644 fuzz/wtwire/create_session.go create mode 100644 fuzz/wtwire/create_session_reply.go create mode 100644 fuzz/wtwire/delete_session.go create mode 100644 fuzz/wtwire/delete_session_reply.go create mode 100644 fuzz/wtwire/error.go create mode 100644 fuzz/wtwire/fuzz_utils.go create mode 100644 fuzz/wtwire/init.go create mode 100644 fuzz/wtwire/state_update.go create mode 100644 fuzz/wtwire/state_update_reply.go diff --git a/fuzz/wtwire/create_session.go b/fuzz/wtwire/create_session.go new file mode 100644 index 0000000000..df521bf407 --- /dev/null +++ b/fuzz/wtwire/create_session.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// Fuzz_create_session is used by go-fuzz. +func Fuzz_create_session(data []byte) int { + // Prefix with MsgCreateSession. + data = prefixWithMsgType(data, wtwire.MsgCreateSession) + + // Create an empty message so that the FuzzHarness func can check if the + // max payload constraint is violated. + emptyMsg := wtwire.CreateSession{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/wtwire/create_session_reply.go b/fuzz/wtwire/create_session_reply.go new file mode 100644 index 0000000000..a0e07f85f0 --- /dev/null +++ b/fuzz/wtwire/create_session_reply.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// Fuzz_create_session_reply is used by go-fuzz. +func Fuzz_create_session_reply(data []byte) int { + // Prefix with MsgCreateSessionReply. + data = prefixWithMsgType(data, wtwire.MsgCreateSessionReply) + + // Create an empty message so that the FuzzHarness func can check if the + // max payload constraint is violated. + emptyMsg := wtwire.CreateSessionReply{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/wtwire/delete_session.go b/fuzz/wtwire/delete_session.go new file mode 100644 index 0000000000..2cb56225cf --- /dev/null +++ b/fuzz/wtwire/delete_session.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// Fuzz_delete_session is used by go-fuzz. +func Fuzz_delete_session(data []byte) int { + // Prefix with MsgDeleteSession. + data = prefixWithMsgType(data, wtwire.MsgDeleteSession) + + // Create an empty message so that the FuzzHarness func can check if the + // max payload constraint is violated. + emptyMsg := wtwire.DeleteSession{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/wtwire/delete_session_reply.go b/fuzz/wtwire/delete_session_reply.go new file mode 100644 index 0000000000..0f0360f1a4 --- /dev/null +++ b/fuzz/wtwire/delete_session_reply.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// Fuzz_delete_session_reply is used by go-fuzz. +func Fuzz_delete_session_reply(data []byte) int { + // Prefix with MsgDeleteSessionReply. + data = prefixWithMsgType(data, wtwire.MsgDeleteSessionReply) + + // Create an empty message so that the FuzzHarness func can check if the + // max payload constraint is violated. + emptyMsg := wtwire.DeleteSessionReply{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/wtwire/error.go b/fuzz/wtwire/error.go new file mode 100644 index 0000000000..f0f5fae231 --- /dev/null +++ b/fuzz/wtwire/error.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// Fuzz_error is used by go-fuzz. +func Fuzz_error(data []byte) int { + // Prefix with MsgError. + data = prefixWithMsgType(data, wtwire.MsgError) + + // Create an empty message so that the FuzzHarness func can check if the + // max payload constraint is violated. + emptyMsg := wtwire.Error{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/wtwire/fuzz_utils.go b/fuzz/wtwire/fuzz_utils.go new file mode 100644 index 0000000000..8c8ee89b82 --- /dev/null +++ b/fuzz/wtwire/fuzz_utils.go @@ -0,0 +1,75 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "bytes" + "encoding/binary" + "fmt" + "reflect" + + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// prefixWithMsgType takes []byte and adds a wire protocol prefix +// to make the []byte into an actual message to be used in fuzzing. +func prefixWithMsgType(data []byte, prefix wtwire.MessageType) []byte { + var prefixBytes [2]byte + binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix)) + data = append(prefixBytes[:], data...) + return data +} + +// harness performs the actual fuzz testing of the appropriate wire message. +// This function will check that the passed-in message passes wire length checks, +// is a valid message once deserialized, and passes a sequence of serialization +// and deserialization checks. Returns an int that determines whether the input +// is unique or not. +func harness(data []byte, emptyMsg wtwire.Message) int { + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Make sure byte array length (excluding 2 bytes for message type) is + // less than max payload size for the wire message. We check this because + // otherwise `go-fuzz` will keep creating inputs that crash on ReadMessage + // due to a large message size. + payloadLen := uint32(len(data)) - 2 + if payloadLen > emptyMsg.MaxPayloadLength(0) { + // Ignore this input - max payload constraint violated. + return -1 + } + + msg, err := wtwire.ReadMessage(r, 0) + if err != nil { + // go-fuzz generated []byte that cannot be represented as a + // wire message but we will return 0 so go-fuzz can modify the + // input. + return 0 + } + + // We will serialize the message into a new bytes buffer. + var b bytes.Buffer + if _, err := wtwire.WriteMessage(&b, msg, 0); err != nil { + // Could not serialize message into bytes buffer, panic. + panic(err) + } + + // Deserialize the message from the serialized bytes buffer, and then + // assert that the original message is equal to the newly deserialized + // message. + newMsg, err := wtwire.ReadMessage(&b, 0) + if err != nil { + // Could not deserialize message from bytes buffer, panic. + panic(err) + } + + if !reflect.DeepEqual(msg, newMsg) { + // Deserialized message and original message are not + // deeply equal. + panic(fmt.Errorf("deserialized message and original message " + + "are not deeply equal.")) + } + + // Add this input to the corpus. + return 1 +} diff --git a/fuzz/wtwire/init.go b/fuzz/wtwire/init.go new file mode 100644 index 0000000000..31112b8f25 --- /dev/null +++ b/fuzz/wtwire/init.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// Fuzz_init is used by go-fuzz. +func Fuzz_init(data []byte) int { + // Prefix with MsgInit. + data = prefixWithMsgType(data, wtwire.MsgInit) + + // Create an empty message so that the FuzzHarness func can check if the + // max payload constraint is violated. + emptyMsg := wtwire.Init{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/wtwire/state_update.go b/fuzz/wtwire/state_update.go new file mode 100644 index 0000000000..5d13568ef5 --- /dev/null +++ b/fuzz/wtwire/state_update.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// Fuzz_state_update is used by go-fuzz. +func Fuzz_state_update(data []byte) int { + // Prefix with MsgStateUpdate. + data = prefixWithMsgType(data, wtwire.MsgStateUpdate) + + // Create an empty message so that the FuzzHarness func can check if the + // max payload constraint is violated. + emptyMsg := wtwire.StateUpdate{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/wtwire/state_update_reply.go b/fuzz/wtwire/state_update_reply.go new file mode 100644 index 0000000000..fb7a3bbb85 --- /dev/null +++ b/fuzz/wtwire/state_update_reply.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package wtwirefuzz + +import ( + "github.com/lightningnetwork/lnd/watchtower/wtwire" +) + +// Fuzz_state_update_reply is used by go-fuzz. +func Fuzz_state_update_reply(data []byte) int { + // Prefix with MsgStateUpdateReply. + data = prefixWithMsgType(data, wtwire.MsgStateUpdateReply) + + // Create an empty message so that the FuzzHarness func can check if the + // max payload constraint is violated. + emptyMsg := wtwire.StateUpdateReply{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} From c08377d303d7f95b45dc51933ea9c0579eb01b27 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 30 Jan 2020 10:01:10 +0200 Subject: [PATCH 036/562] htlcswitch/test: replace mock server delta with constant --- htlcswitch/link_test.go | 1 + htlcswitch/switch_test.go | 96 +++++++++++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 16d64d70e5..427322ee9e 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -39,6 +39,7 @@ import ( const ( testStartingHeight = 100 + testDefaultDelta = 6 ) // concurrentTester is a thread-safe wrapper around the Fatalf method of a diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index 69425dc212..1497f00987 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -32,7 +32,9 @@ func genPreimage() ([32]byte, error) { func TestSwitchAddDuplicateLink(t *testing.T) { t.Parallel() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } @@ -90,7 +92,9 @@ func TestSwitchAddDuplicateLink(t *testing.T) { func TestSwitchHasActiveLink(t *testing.T) { t.Parallel() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } @@ -158,7 +162,9 @@ func TestSwitchHasActiveLink(t *testing.T) { func TestSwitchSendPending(t *testing.T) { t.Parallel() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } @@ -253,11 +259,15 @@ func TestSwitchSendPending(t *testing.T) { func TestSwitchForward(t *testing.T) { t.Parallel() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -358,11 +368,15 @@ func TestSwitchForwardFailAfterFullAdd(t *testing.T) { chanID1, chanID2, aliceChanID, bobChanID := genIDs() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -549,11 +563,15 @@ func TestSwitchForwardSettleAfterFullAdd(t *testing.T) { chanID1, chanID2, aliceChanID, bobChanID := genIDs() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -743,11 +761,15 @@ func TestSwitchForwardDropAfterFullAdd(t *testing.T) { chanID1, chanID2, aliceChanID, bobChanID := genIDs() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -906,11 +928,15 @@ func TestSwitchForwardFailAfterHalfAdd(t *testing.T) { chanID1, chanID2, aliceChanID, bobChanID := genIDs() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -1064,11 +1090,15 @@ func TestSwitchForwardCircuitPersistence(t *testing.T) { chanID1, chanID2, aliceChanID, bobChanID := genIDs() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -1359,11 +1389,15 @@ func testSkipIneligibleLinksMultiHopForward(t *testing.T, var packet *htlcPacket - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -1470,7 +1504,9 @@ func testSkipLinkLocalForward(t *testing.T, eligible bool, // We'll create a single link for this test, marking it as being unable // to forward form the get go. - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } @@ -1524,11 +1560,15 @@ func testSkipLinkLocalForward(t *testing.T, eligible bool, func TestSwitchCancel(t *testing.T) { t.Parallel() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -1637,11 +1677,15 @@ func TestSwitchAddSamePayment(t *testing.T) { chanID1, chanID2, aliceChanID, bobChanID := genIDs() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } - bobPeer, err := newMockServer(t, "bob", testStartingHeight, nil, 6) + bobPeer, err := newMockServer( + t, "bob", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create bob server: %v", err) } @@ -1796,7 +1840,9 @@ func TestSwitchAddSamePayment(t *testing.T) { func TestSwitchSendPayment(t *testing.T) { t.Parallel() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } @@ -2334,7 +2380,9 @@ func TestSwitchGetPaymentResult(t *testing.T) { func TestInvalidFailure(t *testing.T) { t.Parallel() - alicePeer, err := newMockServer(t, "alice", testStartingHeight, nil, 6) + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, testDefaultDelta, + ) if err != nil { t.Fatalf("unable to create alice server: %v", err) } From a3478f1d998c6d19efda3d7e0fba2f765a3d2888 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 30 Jan 2020 10:01:17 +0200 Subject: [PATCH 037/562] htlcswitch: add CheckCircularForward to handlePacketForward Add a CheckCircularForward function which detects packets which are forwards over the same incoming and outgoing link, and errors if the node is configured to disallow forwards of this nature. This check is added to increase the cost of a liquidity lockup attack, because it increases the length of the route required to lock up an individual node's bandwidth. Since nodes are currently limited to 20 hops, increasing the length of the route needed to lock up capital increases the number of malicious payments an attacker will have to route, which increases the capital requirement of the attack overall. --- htlcswitch/failure_detail.go | 8 ++ htlcswitch/switch.go | 51 +++++++++++ htlcswitch/switch_test.go | 166 +++++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+) diff --git a/htlcswitch/failure_detail.go b/htlcswitch/failure_detail.go index 92b25510ea..976015b8c4 100644 --- a/htlcswitch/failure_detail.go +++ b/htlcswitch/failure_detail.go @@ -29,6 +29,11 @@ const ( // FailureDetailInsufficientBalance is returned when we cannot route a // htlc due to insufficient outgoing capacity. FailureDetailInsufficientBalance + + // FailureDetailCircularRoute is returned when an attempt is made + // to forward a htlc through our node which arrives and leaves on the + // same channel. + FailureDetailCircularRoute ) // String returns the string representation of a failure detail. @@ -52,6 +57,9 @@ func (fd FailureDetail) String() string { case FailureDetailInsufficientBalance: return "insufficient bandwidth to route htlc" + case FailureDetailCircularRoute: + return "same incoming and outgoing channel" + default: return "unknown failure detail" } diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index c08bdc0cfb..760aadf007 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -167,6 +167,10 @@ type Config struct { // fails in forwarding packages. AckEventTicker ticker.Ticker + // AllowCircularRoute is true if the user has configured their node to + // allow forwards that arrive and depart our node over the same channel. + AllowCircularRoute bool + // RejectHTLC is a flag that instructs the htlcswitch to reject any // HTLCs that are not from the source hop. RejectHTLC bool @@ -986,6 +990,22 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { return s.handleLocalDispatch(packet) } + // Before we attempt to find a non-strict forwarding path for + // this htlc, check whether the htlc is being routed over the + // same incoming and outgoing channel. If our node does not + // allow forwards of this nature, we fail the htlc early. This + // check is in place to disallow inefficiently routed htlcs from + // locking up our balance. + linkErr := checkCircularForward( + packet.incomingChanID, packet.outgoingChanID, + s.cfg.AllowCircularRoute, htlc.PaymentHash, + ) + if linkErr != nil { + return s.failAddPacket( + packet, linkErr.WireMessage(), linkErr, + ) + } + s.indexMtx.RLock() targetLink, err := s.getLinkByShortID(packet.outgoingChanID) if err != nil { @@ -1170,6 +1190,37 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { } } +// checkCircularForward checks whether a forward is circular (arrives and +// departs on the same link) and returns a link error if the switch is +// configured to disallow this behaviour. +func checkCircularForward(incoming, outgoing lnwire.ShortChannelID, + allowCircular bool, paymentHash lntypes.Hash) *LinkError { + + // If the route is not circular we do not need to perform any further + // checks. + if incoming != outgoing { + return nil + } + + // If the incoming and outgoing link are equal, the htlc is part of a + // circular route which may be used to lock up our liquidity. If the + // switch is configured to allow circular routes, log that we are + // allowing the route then return nil. + if allowCircular { + log.Debugf("allowing circular route over link: %v "+ + "(payment hash: %x)", incoming, paymentHash) + return nil + } + + // If our node disallows circular routes, return a temporary channel + // failure. There is nothing wrong with the policy used by the remote + // node, so we do not include a channel update. + return NewDetailedLinkError( + lnwire.NewTemporaryChannelFailure(nil), + FailureDetailCircularRoute, + ) +} + // failAddPacket encrypts a fail packet back to an add packet's source. // The ciphertext will be derived from the failure message proivded by context. // This method returns the failErr if all other steps complete successfully. diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index 1497f00987..828ef232cd 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "io/ioutil" + "reflect" "testing" "time" @@ -1324,6 +1325,171 @@ type multiHopFwdTest struct { expectedReply lnwire.FailCode } +// TestCircularForwards tests the allowing/disallowing of circular payments +// through the same channel in the case where the switch is configured to allow +// and disallow same channel circular forwards. +func TestCircularForwards(t *testing.T) { + chanID1, aliceChanID := genID() + preimage := [sha256.Size]byte{1} + hash := fastsha256.Sum256(preimage[:]) + + tests := []struct { + name string + allowCircularPayment bool + expectedErr error + }{ + { + name: "circular payment allowed", + allowCircularPayment: true, + expectedErr: nil, + }, + { + name: "circular payment disallowed", + allowCircularPayment: false, + expectedErr: NewDetailedLinkError( + lnwire.NewTemporaryChannelFailure(nil), + FailureDetailCircularRoute, + ), + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + alicePeer, err := newMockServer( + t, "alice", testStartingHeight, nil, + testDefaultDelta, + ) + if err != nil { + t.Fatalf("unable to create alice server: %v", + err) + } + + s, err := initSwitchWithDB(testStartingHeight, nil) + if err != nil { + t.Fatalf("unable to init switch: %v", err) + } + if err := s.Start(); err != nil { + t.Fatalf("unable to start switch: %v", err) + } + defer func() { _ = s.Stop() }() + + // Set the switch to allow or disallow circular routes + // according to the test's requirements. + s.cfg.AllowCircularRoute = test.allowCircularPayment + + aliceChannelLink := newMockChannelLink( + s, chanID1, aliceChanID, alicePeer, true, + ) + + if err := s.AddLink(aliceChannelLink); err != nil { + t.Fatalf("unable to add alice link: %v", err) + } + + // Create a new packet that loops through alice's link + // in a circle. + obfuscator := NewMockObfuscator() + packet := &htlcPacket{ + incomingChanID: aliceChannelLink.ShortChanID(), + outgoingChanID: aliceChannelLink.ShortChanID(), + htlc: &lnwire.UpdateAddHTLC{ + PaymentHash: hash, + Amount: 1, + }, + obfuscator: obfuscator, + } + + // Attempt to forward the packet and check for the expected + // error. + err = s.forward(packet) + if !reflect.DeepEqual(err, test.expectedErr) { + t.Fatalf("expected: %v, got: %v", + test.expectedErr, err) + } + + // Ensure that no circuits were opened. + if s.circuits.NumOpen() > 0 { + t.Fatal("do not expect any open circuits") + } + }) + } +} + +// TestCheckCircularForward tests the error returned by checkCircularForward +// in cases where we allow and disallow same channel circular forwards. +func TestCheckCircularForward(t *testing.T) { + tests := []struct { + name string + + // allowCircular determines whether we should allow circular + // forwards. + allowCircular bool + + // incomingLink is the link that the htlc arrived on. + incomingLink lnwire.ShortChannelID + + // outgoingLink is the link that the htlc forward + // is destined to leave on. + outgoingLink lnwire.ShortChannelID + + // expectedErr is the error we expect to be returned. + expectedErr *LinkError + }{ + { + name: "not circular, allowed in config", + allowCircular: true, + incomingLink: lnwire.NewShortChanIDFromInt(123), + outgoingLink: lnwire.NewShortChanIDFromInt(321), + expectedErr: nil, + }, + { + name: "not circular, not allowed in config", + allowCircular: false, + incomingLink: lnwire.NewShortChanIDFromInt(123), + outgoingLink: lnwire.NewShortChanIDFromInt(321), + expectedErr: nil, + }, + { + name: "circular, allowed in config", + allowCircular: true, + incomingLink: lnwire.NewShortChanIDFromInt(123), + outgoingLink: lnwire.NewShortChanIDFromInt(123), + expectedErr: nil, + }, + { + name: "circular, not allowed in config", + allowCircular: false, + incomingLink: lnwire.NewShortChanIDFromInt(123), + outgoingLink: lnwire.NewShortChanIDFromInt(123), + expectedErr: NewDetailedLinkError( + lnwire.NewTemporaryChannelFailure(nil), + FailureDetailCircularRoute, + ), + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + // Check for a circular forward, the hash passed can + // be nil because it is only used for logging. + err := checkCircularForward( + test.incomingLink, test.outgoingLink, + test.allowCircular, lntypes.Hash{}, + ) + if !reflect.DeepEqual(err, test.expectedErr) { + t.Fatalf("expected: %v, got: %v", + test.expectedErr, err) + } + }) + } +} + // TestSkipIneligibleLinksMultiHopForward tests that if a multi-hop HTLC comes // along, then we won't attempt to froward it down al ink that isn't yet able // to forward any HTLC's. From afc7cc7f84f546d917409234d18ac322ebfdd741 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 30 Jan 2020 10:01:18 +0200 Subject: [PATCH 038/562] htlcswitch+config: make circular forwarding defence configurable Add a bool to the switch's config which can be used to disable same channel circular route checks. --- config.go | 2 ++ server.go | 1 + 2 files changed, 3 insertions(+) diff --git a/config.go b/config.go index 10f79ba549..89b934a8b9 100644 --- a/config.go +++ b/config.go @@ -341,6 +341,8 @@ type config struct { Watchtower *lncfg.Watchtower `group:"watchtower" namespace:"watchtower"` LegacyProtocol *lncfg.LegacyProtocol `group:"legacyprotocol" namespace:"legacyprotocol"` + + AllowCircularRoute bool `long:"allow-circular-route" description:"If true, our node will allow htlc forwards that arrive and depart on the same channel."` } // loadConfig initializes and parses the config using a config file and command diff --git a/server.go b/server.go index 72c6661476..09a4dbc041 100644 --- a/server.go +++ b/server.go @@ -470,6 +470,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, FwdEventTicker: ticker.New(htlcswitch.DefaultFwdEventInterval), LogEventTicker: ticker.New(htlcswitch.DefaultLogInterval), AckEventTicker: ticker.New(htlcswitch.DefaultAckInterval), + AllowCircularRoute: cfg.AllowCircularRoute, RejectHTLC: cfg.RejectHTLC, }, uint32(currentHeight)) if err != nil { From 7c316b9194317d950a55d56e0534eed6f986ff65 Mon Sep 17 00:00:00 2001 From: nsa Date: Thu, 30 Jan 2020 13:34:49 -0500 Subject: [PATCH 039/562] brontide: add SetCurveToNil function --- brontide/noise.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/brontide/noise.go b/brontide/noise.go index 7d5f42d4ed..16263e5fa0 100644 --- a/brontide/noise.go +++ b/brontide/noise.go @@ -871,3 +871,23 @@ func (b *Machine) ReadBody(r io.Reader, buf []byte) ([]byte, error) { // TODO(roasbeef): modify to let pass in slice return b.recvCipher.Decrypt(nil, nil, buf) } + +// SetCurveToNil sets the 'Curve' parameter to nil on the handshakeState keys. +// This allows us to log the Machine object without spammy log messages. +func (b *Machine) SetCurveToNil() { + if b.localStatic != nil { + b.localStatic.Curve = nil + } + + if b.localEphemeral != nil { + b.localEphemeral.Curve = nil + } + + if b.remoteStatic != nil { + b.remoteStatic.Curve = nil + } + + if b.remoteEphemeral != nil { + b.remoteEphemeral.Curve = nil + } +} From 511fdb2520d865841546f624e1ff7a1d370375ac Mon Sep 17 00:00:00 2001 From: nsa Date: Thu, 30 Jan 2020 13:35:27 -0500 Subject: [PATCH 040/562] fuzz/brontide: add fuzzing helper utilities --- fuzz/brontide/fuzz_utils.go | 137 ++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 fuzz/brontide/fuzz_utils.go diff --git a/fuzz/brontide/fuzz_utils.go b/fuzz/brontide/fuzz_utils.go new file mode 100644 index 0000000000..48388dc0d8 --- /dev/null +++ b/fuzz/brontide/fuzz_utils.go @@ -0,0 +1,137 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "encoding/hex" + "fmt" + + "github.com/btcsuite/btcd/btcec" + "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/brontide" +) + +var ( + initBytes = []byte{ + 0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda, + 0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17, + 0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d, + 0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9, + } + + respBytes = []byte{ + 0xaa, 0xb6, 0x37, 0xd9, 0xfc, 0xd2, 0xc6, 0xda, + 0x63, 0x59, 0xe6, 0x99, 0x31, 0x13, 0xa1, 0x17, + 0xd, 0xe7, 0x95, 0xe9, 0xb7, 0x25, 0xb8, 0x4d, + 0x1e, 0xb, 0x4c, 0xf9, 0x9e, 0xc5, 0x8c, 0xe9, + } + + // Returns the initiator's ephemeral private key. + initEphemeral = brontide.EphemeralGenerator(func() (*btcec.PrivateKey, error) { + e := "121212121212121212121212121212121212121212121212121212" + + "1212121212" + eBytes, err := hex.DecodeString(e) + if err != nil { + return nil, err + } + + priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), eBytes) + return priv, nil + }) + + // Returns the responder's ephemeral private key. + respEphemeral = brontide.EphemeralGenerator(func() (*btcec.PrivateKey, error) { + e := "222222222222222222222222222222222222222222222222222" + + "2222222222222" + eBytes, err := hex.DecodeString(e) + if err != nil { + return nil, err + } + + priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), eBytes) + return priv, nil + }) +) + +// completeHandshake takes two brontide machines (initiator, responder) +// and completes the brontide handshake between them. If any part of the +// handshake fails, this function will panic. +func completeHandshake(initiator, responder *brontide.Machine) { + if err := handshake(initiator, responder); err != nil { + nilAndPanic(initiator, responder, err) + } +} + +// handshake actually completes the brontide handshake and bubbles up +// an error to the calling function. +func handshake(initiator, responder *brontide.Machine) error { + // Generate ActOne and send to the responder. + actOne, err := initiator.GenActOne() + if err != nil { + return err + } + + if err := responder.RecvActOne(actOne); err != nil { + return err + } + + // Generate ActTwo and send to initiator. + actTwo, err := responder.GenActTwo() + if err != nil { + return err + } + + if err := initiator.RecvActTwo(actTwo); err != nil { + return err + } + + // Generate ActThree and send to responder. + actThree, err := initiator.GenActThree() + if err != nil { + return err + } + + return responder.RecvActThree(actThree) +} + +// nilAndPanic first nils the initiator and responder's Curve fields and then +// panics. +func nilAndPanic(initiator, responder *brontide.Machine, err error) { + if initiator != nil { + initiator.SetCurveToNil() + } + if responder != nil { + responder.SetCurveToNil() + } + panic(fmt.Errorf("error: %v, initiator: %v, responder: %v", err, + spew.Sdump(initiator), spew.Sdump(responder))) +} + +// getBrontideMachines returns two brontide machines that use random keys +// everywhere. +func getBrontideMachines() (*brontide.Machine, *brontide.Machine) { + initPriv, _ := btcec.NewPrivateKey(btcec.S256()) + respPriv, _ := btcec.NewPrivateKey(btcec.S256()) + respPub := (*btcec.PublicKey)(&respPriv.PublicKey) + + initiator := brontide.NewBrontideMachine(true, initPriv, respPub) + responder := brontide.NewBrontideMachine(false, respPriv, nil) + + return initiator, responder +} + +// getStaticBrontideMachines returns two brontide machines that use static keys +// everywhere. +func getStaticBrontideMachines() (*brontide.Machine, *brontide.Machine) { + initPriv, _ := btcec.PrivKeyFromBytes(btcec.S256(), initBytes) + respPriv, respPub := btcec.PrivKeyFromBytes(btcec.S256(), respBytes) + + initiator := brontide.NewBrontideMachine( + true, initPriv, respPub, initEphemeral, + ) + responder := brontide.NewBrontideMachine( + false, respPriv, nil, respEphemeral, + ) + + return initiator, responder +} From 116c5469bc2a51919dcac2d639f14b228641ac73 Mon Sep 17 00:00:00 2001 From: nsa Date: Thu, 30 Jan 2020 13:40:01 -0500 Subject: [PATCH 041/562] fuzz/brontide: random+static harnesses for acts 1-3 --- fuzz/brontide/random_actone.go | 30 +++++++++++++++++++ fuzz/brontide/random_actthree.go | 50 ++++++++++++++++++++++++++++++++ fuzz/brontide/random_acttwo.go | 39 +++++++++++++++++++++++++ fuzz/brontide/static_actone.go | 30 +++++++++++++++++++ fuzz/brontide/static_actthree.go | 50 ++++++++++++++++++++++++++++++++ fuzz/brontide/static_acttwo.go | 39 +++++++++++++++++++++++++ 6 files changed, 238 insertions(+) create mode 100644 fuzz/brontide/random_actone.go create mode 100644 fuzz/brontide/random_actthree.go create mode 100644 fuzz/brontide/random_acttwo.go create mode 100644 fuzz/brontide/static_actone.go create mode 100644 fuzz/brontide/static_actthree.go create mode 100644 fuzz/brontide/static_acttwo.go diff --git a/fuzz/brontide/random_actone.go b/fuzz/brontide/random_actone.go new file mode 100644 index 0000000000..259d7d6ad1 --- /dev/null +++ b/fuzz/brontide/random_actone.go @@ -0,0 +1,30 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "github.com/lightningnetwork/lnd/brontide" +) + +// Fuzz_random_actone is a go-fuzz harness for ActOne in the brontide +// handshake. +func Fuzz_random_actone(data []byte) int { + // Check if data is large enough. + if len(data) < brontide.ActOneSize { + return -1 + } + + // This will return brontide machines with random keys. + _, responder := getBrontideMachines() + + // Copy data into [ActOneSize]byte. + var actOne [brontide.ActOneSize]byte + copy(actOne[:], data) + + // Responder receives ActOne, should fail on the MAC check. + if err := responder.RecvActOne(actOne); err == nil { + nilAndPanic(nil, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/random_actthree.go b/fuzz/brontide/random_actthree.go new file mode 100644 index 0000000000..38a3847ffb --- /dev/null +++ b/fuzz/brontide/random_actthree.go @@ -0,0 +1,50 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "github.com/lightningnetwork/lnd/brontide" +) + +// Fuzz_random_actthree is a go-fuzz harness for ActThree in the brontide +// handshake. +func Fuzz_random_actthree(data []byte) int { + // Check if data is large enough. + if len(data) < brontide.ActThreeSize { + return -1 + } + + // This will return brontide machines with random keys. + initiator, responder := getBrontideMachines() + + // Generate ActOne and send to the responder. + actOne, err := initiator.GenActOne() + if err != nil { + nilAndPanic(initiator, responder, err) + } + + // Receiving ActOne should succeed, so we panic on error. + if err := responder.RecvActOne(actOne); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Generate ActTwo - this is not sent to the initiator because nothing is + // done with the initiator after this point and it would slow down fuzzing. + // GenActTwo needs to be called to set the appropriate state in the + // responder machine. + _, err = responder.GenActTwo() + if err != nil { + nilAndPanic(initiator, responder, err) + } + + // Copy data into [ActThreeSize]byte. + var actThree [brontide.ActThreeSize]byte + copy(actThree[:], data) + + // Responder receives ActThree, should fail on the MAC check. + if err := responder.RecvActThree(actThree); err == nil { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/random_acttwo.go b/fuzz/brontide/random_acttwo.go new file mode 100644 index 0000000000..1cda2f9326 --- /dev/null +++ b/fuzz/brontide/random_acttwo.go @@ -0,0 +1,39 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "github.com/lightningnetwork/lnd/brontide" +) + +// Fuzz_random_acttwo is a go-fuzz harness for ActTwo in the brontide +// handshake. +func Fuzz_random_acttwo(data []byte) int { + // Check if data is large enough. + if len(data) < brontide.ActTwoSize { + return -1 + } + + // This will return brontide machines with random keys. + initiator, _ := getBrontideMachines() + + // Generate ActOne - this isn't sent to the responder because nothing is + // done with the responder machine and this would slow down fuzzing. + // GenActOne needs to be called to set the appropriate state in the + // initiator machine. + _, err := initiator.GenActOne() + if err != nil { + nilAndPanic(initiator, nil, err) + } + + // Copy data into [ActTwoSize]byte. + var actTwo [brontide.ActTwoSize]byte + copy(actTwo[:], data) + + // Initiator receives ActTwo, should fail. + if err := initiator.RecvActTwo(actTwo); err == nil { + nilAndPanic(initiator, nil, nil) + } + + return 1 +} diff --git a/fuzz/brontide/static_actone.go b/fuzz/brontide/static_actone.go new file mode 100644 index 0000000000..7c351680f1 --- /dev/null +++ b/fuzz/brontide/static_actone.go @@ -0,0 +1,30 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "github.com/lightningnetwork/lnd/brontide" +) + +// Fuzz_static_actone is a go-fuzz harness for ActOne in the brontide +// handshake. +func Fuzz_static_actone(data []byte) int { + // Check if data is large enough. + if len(data) < brontide.ActOneSize { + return -1 + } + + // This will return brontide machines with static keys. + _, responder := getStaticBrontideMachines() + + // Copy data into [ActOneSize]byte. + var actOne [brontide.ActOneSize]byte + copy(actOne[:], data) + + // Responder receives ActOne, should fail. + if err := responder.RecvActOne(actOne); err == nil { + nilAndPanic(nil, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/static_actthree.go b/fuzz/brontide/static_actthree.go new file mode 100644 index 0000000000..3f4878bfac --- /dev/null +++ b/fuzz/brontide/static_actthree.go @@ -0,0 +1,50 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "github.com/lightningnetwork/lnd/brontide" +) + +// Fuzz_static_actthree is a go-fuzz harness for ActThree in the brontide +// handshake. +func Fuzz_static_actthree(data []byte) int { + // Check if data is large enough. + if len(data) < brontide.ActThreeSize { + return -1 + } + + // This will return brontide machines with static keys. + initiator, responder := getStaticBrontideMachines() + + // Generate ActOne and send to the responder. + actOne, err := initiator.GenActOne() + if err != nil { + nilAndPanic(initiator, responder, err) + } + + // Receiving ActOne should succeed, so we panic on error. + if err := responder.RecvActOne(actOne); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Generate ActTwo - this is not sent to the initiator because nothing is + // done with the initiator after this point and it would slow down fuzzing. + // GenActTwo needs to be called to set the appropriate state in the responder + // machine. + _, err = responder.GenActTwo() + if err != nil { + nilAndPanic(initiator, responder, err) + } + + // Copy data into [ActThreeSize]byte. + var actThree [brontide.ActThreeSize]byte + copy(actThree[:], data) + + // Responder receives ActThree, should fail. + if err := responder.RecvActThree(actThree); err == nil { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/static_acttwo.go b/fuzz/brontide/static_acttwo.go new file mode 100644 index 0000000000..4a2b094f7d --- /dev/null +++ b/fuzz/brontide/static_acttwo.go @@ -0,0 +1,39 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "github.com/lightningnetwork/lnd/brontide" +) + +// Fuzz_static_acttwo is a go-fuzz harness for ActTwo in the brontide +// handshake. +func Fuzz_static_acttwo(data []byte) int { + // Check if data is large enough. + if len(data) < brontide.ActTwoSize { + return -1 + } + + // This will return brontide machines with static keys. + initiator, _ := getStaticBrontideMachines() + + // Generate ActOne - this isn't sent to the responder because nothing is + // done with the responder machine and this would slow down fuzzing. + // GenActOne needs to be called to set the appropriate state in the initiator + // machine. + _, err := initiator.GenActOne() + if err != nil { + nilAndPanic(initiator, nil, err) + } + + // Copy data into [ActTwoSize]byte. + var actTwo [brontide.ActTwoSize]byte + copy(actTwo[:], data) + + // Initiator receives ActTwo, should fail. + if err := initiator.RecvActTwo(actTwo); err == nil { + nilAndPanic(initiator, nil, nil) + } + + return 1 +} From 468e5c03e9290705167b4c3207f54ff1840e08fd Mon Sep 17 00:00:00 2001 From: nsa Date: Thu, 30 Jan 2020 13:41:46 -0500 Subject: [PATCH 042/562] fuzz/brontide: random+static decrypt harnesses --- fuzz/brontide/random_init_decrypt.go | 27 +++++++++++++++++++++++++++ fuzz/brontide/random_resp_decrypt.go | 27 +++++++++++++++++++++++++++ fuzz/brontide/static_init_decrypt.go | 27 +++++++++++++++++++++++++++ fuzz/brontide/static_resp_decrypt.go | 27 +++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 fuzz/brontide/random_init_decrypt.go create mode 100644 fuzz/brontide/random_resp_decrypt.go create mode 100644 fuzz/brontide/static_init_decrypt.go create mode 100644 fuzz/brontide/static_resp_decrypt.go diff --git a/fuzz/brontide/random_init_decrypt.go b/fuzz/brontide/random_init_decrypt.go new file mode 100644 index 0000000000..3328a2b6be --- /dev/null +++ b/fuzz/brontide/random_init_decrypt.go @@ -0,0 +1,27 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" +) + +// Fuzz_random_init_decrypt is a go-fuzz harness that decrypts arbitrary data +// with the initiator. +func Fuzz_random_init_decrypt(data []byte) int { + // This will return brontide machines with random keys. + initiator, responder := getBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Decrypt the encrypted message using ReadMessage w/ initiator machine. + if _, err := initiator.ReadMessage(r); err == nil { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/random_resp_decrypt.go b/fuzz/brontide/random_resp_decrypt.go new file mode 100644 index 0000000000..1ae40bd27f --- /dev/null +++ b/fuzz/brontide/random_resp_decrypt.go @@ -0,0 +1,27 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" +) + +// Fuzz_random_resp_decrypt is a go-fuzz harness that decrypts arbitrary data +// with the responder. +func Fuzz_random_resp_decrypt(data []byte) int { + // This will return brontide machines with random keys. + initiator, responder := getBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Decrypt the encrypted message using ReadMessage w/ responder machine. + if _, err := responder.ReadMessage(r); err == nil { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/static_init_decrypt.go b/fuzz/brontide/static_init_decrypt.go new file mode 100644 index 0000000000..35525d203a --- /dev/null +++ b/fuzz/brontide/static_init_decrypt.go @@ -0,0 +1,27 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" +) + +// Fuzz_static_init_decrypt is a go-fuzz harness that decrypts arbitrary data +// with the initiator. +func Fuzz_static_init_decrypt(data []byte) int { + // This will return brontide machines with static keys. + initiator, responder := getStaticBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Decrypt the encrypted message using ReadMessage w/ initiator machine. + if _, err := initiator.ReadMessage(r); err == nil { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/static_resp_decrypt.go b/fuzz/brontide/static_resp_decrypt.go new file mode 100644 index 0000000000..fee4500b50 --- /dev/null +++ b/fuzz/brontide/static_resp_decrypt.go @@ -0,0 +1,27 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" +) + +// Fuzz_static_resp_decrypt is a go-fuzz harness that decrypts arbitrary data +// with the responder. +func Fuzz_static_resp_decrypt(data []byte) int { + // This will return brontide machines with static keys. + initiator, responder := getStaticBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Decrypt the encrypted message using ReadMessage w/ responder machine. + if _, err := responder.ReadMessage(r); err == nil { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} From 0be5660a2a6509a38db0d1c203f341e0737f1ec3 Mon Sep 17 00:00:00 2001 From: nsa Date: Thu, 30 Jan 2020 13:43:54 -0500 Subject: [PATCH 043/562] fuzz/brontide: random+static encrypt harnesses --- fuzz/brontide/random_init_encrypt.go | 37 ++++++++++++++++++++++++++++ fuzz/brontide/random_resp_encrypt.go | 37 ++++++++++++++++++++++++++++ fuzz/brontide/static_init_encrypt.go | 37 ++++++++++++++++++++++++++++ fuzz/brontide/static_resp_encrypt.go | 37 ++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 fuzz/brontide/random_init_encrypt.go create mode 100644 fuzz/brontide/random_resp_encrypt.go create mode 100644 fuzz/brontide/static_init_encrypt.go create mode 100644 fuzz/brontide/static_resp_encrypt.go diff --git a/fuzz/brontide/random_init_encrypt.go b/fuzz/brontide/random_init_encrypt.go new file mode 100644 index 0000000000..c041429e89 --- /dev/null +++ b/fuzz/brontide/random_init_encrypt.go @@ -0,0 +1,37 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" + "math" +) + +// Fuzz_random_init_encrypt is a go-fuzz harness that encrypts arbitrary data +// with the initiator. +func Fuzz_random_init_encrypt(data []byte) int { + // Ensure that length of message is not greater than max allowed size. + if len(data) > math.MaxUint16 { + return 0 + } + + // This will return brontide machines with random keys. + initiator, responder := getBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + var b bytes.Buffer + + // Encrypt the message using WriteMessage w/ initiator machine. + if err := initiator.WriteMessage(data); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Flush the encrypted message w/ initiator machine. + if _, err := initiator.Flush(&b); err != nil { + nilAndPanic(initiator, responder, err) + } + + return 1 +} diff --git a/fuzz/brontide/random_resp_encrypt.go b/fuzz/brontide/random_resp_encrypt.go new file mode 100644 index 0000000000..691bcff50a --- /dev/null +++ b/fuzz/brontide/random_resp_encrypt.go @@ -0,0 +1,37 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" + "math" +) + +// Fuzz_random_resp_encrypt is a go-fuzz harness that encrypts arbitrary data +// with the responder. +func Fuzz_random_resp_encrypt(data []byte) int { + // Ensure that length of message is not greater than max allowed size. + if len(data) > math.MaxUint16 { + return 0 + } + + // This will return brontide machines with random keys. + initiator, responder := getBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + var b bytes.Buffer + + // Encrypt the message using WriteMessage w/ responder machine. + if err := responder.WriteMessage(data); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Flush the encrypted message w/ responder machine. + if _, err := responder.Flush(&b); err != nil { + nilAndPanic(initiator, responder, err) + } + + return 1 +} diff --git a/fuzz/brontide/static_init_encrypt.go b/fuzz/brontide/static_init_encrypt.go new file mode 100644 index 0000000000..96040e7457 --- /dev/null +++ b/fuzz/brontide/static_init_encrypt.go @@ -0,0 +1,37 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" + "math" +) + +// Fuzz_static_init_encrypt is a go-fuzz harness that encrypts arbitrary data +// with the initiator. +func Fuzz_static_init_encrypt(data []byte) int { + // Ensure that length of message is not greater than max allowed size. + if len(data) > math.MaxUint16 { + return 0 + } + + // This will return brontide machines with static keys. + initiator, responder := getStaticBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + var b bytes.Buffer + + // Encrypt the message using WriteMessage w/ initiator machine. + if err := initiator.WriteMessage(data); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Flush the encrypted message w/ initiator machine. + if _, err := initiator.Flush(&b); err != nil { + nilAndPanic(initiator, responder, err) + } + + return 1 +} diff --git a/fuzz/brontide/static_resp_encrypt.go b/fuzz/brontide/static_resp_encrypt.go new file mode 100644 index 0000000000..b97a0390b5 --- /dev/null +++ b/fuzz/brontide/static_resp_encrypt.go @@ -0,0 +1,37 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" + "math" +) + +// Fuzz_static_resp_encrypt is a go-fuzz harness that encrypts arbitrary data +// with the responder. +func Fuzz_static_resp_encrypt(data []byte) int { + // Ensure that length of message is not greater than max allowed size. + if len(data) > math.MaxUint16 { + return 0 + } + + // This will return brontide machines with static keys. + initiator, responder := getStaticBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + var b bytes.Buffer + + // Encrypt the message using WriteMessage w/ responder machine. + if err := responder.WriteMessage(data); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Flush the encrypted message w/ responder machine. + if _, err := responder.Flush(&b); err != nil { + nilAndPanic(initiator, responder, err) + } + + return 1 +} From 0d42da0cb3d4b16ba65b24972a9ebc48d08cf314 Mon Sep 17 00:00:00 2001 From: nsa Date: Thu, 30 Jan 2020 13:44:55 -0500 Subject: [PATCH 044/562] fuzz/brontide: random+static round-trip encrypt+decrypt harnesses --- fuzz/brontide/random_init_enc_dec.go | 48 +++++++++++++++++++++++++++ fuzz/brontide/random_resp_enc_dec.go | 48 +++++++++++++++++++++++++++ fuzz/brontide/static_init_enc_dec.go | 49 ++++++++++++++++++++++++++++ fuzz/brontide/static_resp_enc_dec.go | 48 +++++++++++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 fuzz/brontide/random_init_enc_dec.go create mode 100644 fuzz/brontide/random_resp_enc_dec.go create mode 100644 fuzz/brontide/static_init_enc_dec.go create mode 100644 fuzz/brontide/static_resp_enc_dec.go diff --git a/fuzz/brontide/random_init_enc_dec.go b/fuzz/brontide/random_init_enc_dec.go new file mode 100644 index 0000000000..17f5583f6d --- /dev/null +++ b/fuzz/brontide/random_init_enc_dec.go @@ -0,0 +1,48 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" + "math" +) + +// Fuzz_random_init_enc_dec is a go-fuzz harness that tests round-trip +// encryption and decryption between the initiator and the responder. +func Fuzz_random_init_enc_dec(data []byte) int { + // Ensure that length of message is not greater than max allowed size. + if len(data) > math.MaxUint16 { + return 0 + } + + // This will return brontide machines with random keys. + initiator, responder := getBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + var b bytes.Buffer + + // Encrypt the message using WriteMessage w/ initiator machine. + if err := initiator.WriteMessage(data); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Flush the encrypted message w/ initiator machine. + if _, err := initiator.Flush(&b); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Decrypt the ciphertext using ReadMessage w/ responder machine. + plaintext, err := responder.ReadMessage(&b) + if err != nil { + nilAndPanic(initiator, responder, err) + } + + // Check that the decrypted message and the original message are equal. + if !bytes.Equal(data, plaintext) { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/random_resp_enc_dec.go b/fuzz/brontide/random_resp_enc_dec.go new file mode 100644 index 0000000000..e2fad9a58b --- /dev/null +++ b/fuzz/brontide/random_resp_enc_dec.go @@ -0,0 +1,48 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" + "math" +) + +// Fuzz_random_resp_enc_dec is a go-fuzz harness that tests round-trip +// encryption and decryption between the responder and the initiator. +func Fuzz_random_resp_enc_dec(data []byte) int { + // Ensure that length of message is not greater than max allowed size. + if len(data) > math.MaxUint16 { + return 0 + } + + // This will return brontide machines with random keys. + initiator, responder := getBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + var b bytes.Buffer + + // Encrypt the message using WriteMessage w/ responder machine. + if err := responder.WriteMessage(data); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Flush the encrypted message w/ responder machine. + if _, err := responder.Flush(&b); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Decrypt the ciphertext using ReadMessage w/ initiator machine. + plaintext, err := initiator.ReadMessage(&b) + if err != nil { + nilAndPanic(initiator, responder, err) + } + + // Check that the decrypted message and the original message are equal. + if !bytes.Equal(data, plaintext) { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/static_init_enc_dec.go b/fuzz/brontide/static_init_enc_dec.go new file mode 100644 index 0000000000..a333c3f4fc --- /dev/null +++ b/fuzz/brontide/static_init_enc_dec.go @@ -0,0 +1,49 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" + "math" +) + +// Fuzz_static_init_enc_dec is a go-fuzz harness that tests round-trip +// encryption and decryption +// between the initiator and the responder. +func Fuzz_static_init_enc_dec(data []byte) int { + // Ensure that length of message is not greater than max allowed size. + if len(data) > math.MaxUint16 { + return 0 + } + + // This will return brontide machines with static keys. + initiator, responder := getStaticBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + var b bytes.Buffer + + // Encrypt the message using WriteMessage w/ initiator machine. + if err := initiator.WriteMessage(data); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Flush the encrypted message w/ initiator machine. + if _, err := initiator.Flush(&b); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Decrypt the ciphertext using ReadMessage w/ responder machine. + plaintext, err := responder.ReadMessage(&b) + if err != nil { + nilAndPanic(initiator, responder, err) + } + + // Check that the decrypted message and the original message are equal. + if !bytes.Equal(data, plaintext) { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} diff --git a/fuzz/brontide/static_resp_enc_dec.go b/fuzz/brontide/static_resp_enc_dec.go new file mode 100644 index 0000000000..b9a3ad3946 --- /dev/null +++ b/fuzz/brontide/static_resp_enc_dec.go @@ -0,0 +1,48 @@ +// +build gofuzz + +package brontidefuzz + +import ( + "bytes" + "math" +) + +// Fuzz_static_resp_enc_dec is a go-fuzz harness that tests round-trip +// encryption and decryption between the responder and the initiator. +func Fuzz_static_resp_enc_dec(data []byte) int { + // Ensure that length of message is not greater than max allowed size. + if len(data) > math.MaxUint16 { + return 0 + } + + // This will return brontide machines with static keys. + initiator, responder := getStaticBrontideMachines() + + // Complete the brontide handshake. + completeHandshake(initiator, responder) + + var b bytes.Buffer + + // Encrypt the message using WriteMessage w/ responder machine. + if err := responder.WriteMessage(data); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Flush the encrypted message w/ responder machine. + if _, err := responder.Flush(&b); err != nil { + nilAndPanic(initiator, responder, err) + } + + // Decrypt the ciphertext using ReadMessage w/ initiator machine. + plaintext, err := initiator.ReadMessage(&b) + if err != nil { + nilAndPanic(initiator, responder, err) + } + + // Check that the decrypted message and the original message are equal. + if !bytes.Equal(data, plaintext) { + nilAndPanic(initiator, responder, nil) + } + + return 1 +} From f8da26ee30c00041f63e02ee1ce9e6426d161995 Mon Sep 17 00:00:00 2001 From: Roei Erez Date: Mon, 3 Feb 2020 12:46:21 +0200 Subject: [PATCH 045/562] contractcourt: change shouldGoOnChain signature. This commit changes the shouldGoOnChain signature to get the htlc as parameter. I will allow the function to take decisions based on whether the htlc is Incoming or Outgoing. --- contractcourt/channel_arbitrator.go | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index bb0821709b..8b6896e15a 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -1113,17 +1113,17 @@ func (c ChainActionMap) Merge(actions ChainActionMap) { // we should go on chain to claim. We do this rather than waiting up until the // last minute as we want to ensure that when we *need* (HTLC is timed out) to // sweep, the commitment is already confirmed. -func (c *ChannelArbitrator) shouldGoOnChain(htlcExpiry, broadcastDelta, - currentHeight uint32) bool { +func (c *ChannelArbitrator) shouldGoOnChain(htlc channeldb.HTLC, + broadcastDelta, currentHeight uint32) bool { // We'll calculate the broadcast cut off for this HTLC. This is the // height that (based on our current fee estimation) we should // broadcast in order to ensure the commitment transaction is confirmed // before the HTLC fully expires. - broadcastCutOff := htlcExpiry - broadcastDelta + broadcastCutOff := htlc.RefundTimeout - broadcastDelta log.Tracef("ChannelArbitrator(%v): examining outgoing contract: "+ - "expiry=%v, cutoff=%v, height=%v", c.cfg.ChanPoint, htlcExpiry, + "expiry=%v, cutoff=%v, height=%v", c.cfg.ChanPoint, htlc.RefundTimeout, broadcastCutOff, currentHeight) // TODO(roasbeef): take into account default HTLC delta, don't need to @@ -1162,8 +1162,7 @@ func (c *ChannelArbitrator) checkCommitChainActions(height uint32, for _, htlc := range htlcs.outgoingHTLCs { // We'll need to go on-chain for an outgoing HTLC if it was // never resolved downstream, and it's "close" to timing out. - toChain := c.shouldGoOnChain( - htlc.RefundTimeout, c.cfg.OutgoingBroadcastDelta, + toChain := c.shouldGoOnChain(htlc, c.cfg.OutgoingBroadcastDelta, height, ) @@ -1194,8 +1193,7 @@ func (c *ChannelArbitrator) checkCommitChainActions(height uint32, continue } - toChain := c.shouldGoOnChain( - htlc.RefundTimeout, c.cfg.IncomingBroadcastDelta, + toChain := c.shouldGoOnChain(htlc, c.cfg.IncomingBroadcastDelta, height, ) @@ -1245,8 +1243,7 @@ func (c *ChannelArbitrator) checkCommitChainActions(height uint32, // mark it still "live". After we broadcast, we'll monitor it // until the HTLC times out to see if we can also redeem it // on-chain. - case !c.shouldGoOnChain( - htlc.RefundTimeout, c.cfg.OutgoingBroadcastDelta, + case !c.shouldGoOnChain(htlc, c.cfg.OutgoingBroadcastDelta, height, ): // TODO(roasbeef): also need to be able to query @@ -1415,8 +1412,7 @@ func (c *ChannelArbitrator) checkRemoteDanglingActions( for _, htlc := range pendingRemoteHTLCs { // We'll now check if we need to go to chain in order to cancel // the incoming HTLC. - goToChain := c.shouldGoOnChain( - htlc.RefundTimeout, c.cfg.OutgoingBroadcastDelta, + goToChain := c.shouldGoOnChain(htlc, c.cfg.OutgoingBroadcastDelta, height, ) From e6561ca86dc89b44bf89444ec02d727ef174e33a Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Mon, 3 Feb 2020 14:24:22 +0100 Subject: [PATCH 046/562] invoices: fix log messages This commit fixes incorrect log messages. --- invoices/invoice_expiry_watcher.go | 4 ++-- invoices/invoiceregistry.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/invoices/invoice_expiry_watcher.go b/invoices/invoice_expiry_watcher.go index 07c2178080..08c57f3964 100644 --- a/invoices/invoice_expiry_watcher.go +++ b/invoices/invoice_expiry_watcher.go @@ -108,7 +108,7 @@ func (ew *InvoiceExpiryWatcher) prepareInvoice( paymentHash lntypes.Hash, invoice *channeldb.Invoice) *invoiceExpiry { if invoice.State != channeldb.ContractOpen { - log.Debugf("Invoice not added to expiry watcher: %v", invoice) + log.Debugf("Invoice not added to expiry watcher: %v", paymentHash) return nil } @@ -139,7 +139,7 @@ func (ew *InvoiceExpiryWatcher) AddInvoices( } if len(invoicesWithExpiry) > 0 { - log.Debugf("Added %v invoices to the expiry watcher: %v", + log.Debugf("Added %d invoices to the expiry watcher", len(invoicesWithExpiry)) select { case ew.newInvoices <- invoicesWithExpiry: diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 4b3a1b2d8e..75cd170dad 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -198,7 +198,8 @@ func (i *InvoiceRegistry) populateExpiryWatcher() error { return err } - log.Debugf("Adding %v pending invoices to the expiry watcher") + log.Debugf("Adding %d pending invoices to the expiry watcher", + len(pendingInvoices)) i.expiryWatcher.AddInvoices(pendingInvoices) return nil } From 19bdbe7f8d4c13d5eb9d21fd0d6fe8467f443da7 Mon Sep 17 00:00:00 2001 From: MrManPew <35897350+MrManPew@users.noreply.github.com> Date: Fri, 27 Dec 2019 23:58:34 +0200 Subject: [PATCH 047/562] Update channeldb opening log It might take a few minutes and it should therefore state it... --- lnd.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lnd.go b/lnd.go index 1d0e9ce727..f72b57a316 100644 --- a/lnd.go +++ b/lnd.go @@ -224,6 +224,7 @@ func Main(lisCfg ListenerCfg) error { // Open the channeldb, which is dedicated to storing channel, and // network related metadata. + ltndLog.Infof("Opening the channeldb, might take a few minutes") chanDB, err := channeldb.Open( graphDir, channeldb.OptionSetRejectCacheSize(cfg.Caches.RejectCacheSize), From 698f1175f8930d2b2af3f0107e4c6d3b95f95d48 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 3 Feb 2020 16:18:06 -0800 Subject: [PATCH 048/562] lnd: add timing information to db open log --- lnd.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lnd.go b/lnd.go index f72b57a316..16a47a4384 100644 --- a/lnd.go +++ b/lnd.go @@ -222,9 +222,12 @@ func Main(lisCfg ListenerCfg) error { defaultGraphSubDirname, normalizeNetwork(activeNetParams.Name)) + ltndLog.Infof("Opening the main database, this might take a few " + + "minutes...") + // Open the channeldb, which is dedicated to storing channel, and // network related metadata. - ltndLog.Infof("Opening the channeldb, might take a few minutes") + startOpenTime := time.Now() chanDB, err := channeldb.Open( graphDir, channeldb.OptionSetRejectCacheSize(cfg.Caches.RejectCacheSize), @@ -238,6 +241,9 @@ func Main(lisCfg ListenerCfg) error { } defer chanDB.Close() + openTime := time.Now().Sub(startOpenTime) + ltndLog.Infof("Database now open (time_to_open=%v)!", openTime) + // Only process macaroons if --no-macaroons isn't set. ctx := context.Background() ctx, cancel := context.WithCancel(ctx) From bbf3877d6577e923483e1511e67f21325cffc399 Mon Sep 17 00:00:00 2001 From: carla Date: Tue, 4 Feb 2020 10:06:34 +0200 Subject: [PATCH 049/562] lnd: fix gosimple linter failure GoSimple linter check fails for time.Now().Sub. Change the logged database open time to use time.Since instead. --- lnd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnd.go b/lnd.go index 16a47a4384..1c10c54648 100644 --- a/lnd.go +++ b/lnd.go @@ -241,7 +241,7 @@ func Main(lisCfg ListenerCfg) error { } defer chanDB.Close() - openTime := time.Now().Sub(startOpenTime) + openTime := time.Since(startOpenTime) ltndLog.Infof("Database now open (time_to_open=%v)!", openTime) // Only process macaroons if --no-macaroons isn't set. From a339065fdcec38be273bf75431757f7de1c1872c Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 4 Feb 2020 15:15:48 +0100 Subject: [PATCH 050/562] invoices: add hash to update context --- invoices/invoiceregistry.go | 10 +++++----- invoices/update.go | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 4b3a1b2d8e..9ab1a65bb6 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -693,8 +693,7 @@ func (i *InvoiceRegistry) cancelSingleHtlc(hash lntypes.Hash, // processKeySend just-in-time inserts an invoice if this htlc is a keysend // htlc. -func (i *InvoiceRegistry) processKeySend(ctx invoiceUpdateCtx, - hash lntypes.Hash) error { +func (i *InvoiceRegistry) processKeySend(ctx invoiceUpdateCtx) error { // Retrieve keysend record if present. preimageSlice, ok := ctx.customRecords[record.KeySendType] @@ -704,7 +703,7 @@ func (i *InvoiceRegistry) processKeySend(ctx invoiceUpdateCtx, // Cancel htlc is preimage is invalid. preimage, err := lntypes.MakePreimage(preimageSlice) - if err != nil || preimage.Hash() != hash { + if err != nil || preimage.Hash() != ctx.hash { return errors.New("invalid keysend preimage") } @@ -751,7 +750,7 @@ func (i *InvoiceRegistry) processKeySend(ctx invoiceUpdateCtx, // Insert invoice into database. Ignore duplicates, because this // may be a replay. - _, err = i.AddInvoice(invoice, hash) + _, err = i.AddInvoice(invoice, ctx.hash) if err != nil && err != channeldb.ErrDuplicateInvoice { return err } @@ -789,6 +788,7 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, // Create the update context containing the relevant details of the // incoming htlc. updateCtx := invoiceUpdateCtx{ + hash: rHash, circuitKey: circuitKey, amtPaid: amtPaid, expiry: expiry, @@ -802,7 +802,7 @@ 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(updateCtx, rHash) + err := i.processKeySend(updateCtx) if err != nil { debugLog(fmt.Sprintf("keysend error: %v", err)) diff --git a/invoices/update.go b/invoices/update.go index 57a41de9f7..2e05b3984a 100644 --- a/invoices/update.go +++ b/invoices/update.go @@ -4,6 +4,7 @@ import ( "errors" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" ) @@ -169,6 +170,7 @@ func (u ResolutionResult) String() string { // invoiceUpdateCtx is an object that describes the context for the invoice // update to be carried out. type invoiceUpdateCtx struct { + hash lntypes.Hash circuitKey channeldb.CircuitKey amtPaid lnwire.MilliSatoshi expiry uint32 From 51324ac7ae49c84df2ab751bc12c33d7a5a769ff Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 4 Feb 2020 15:17:54 +0100 Subject: [PATCH 051/562] invoices: move log into update context --- invoices/invoiceregistry.go | 11 +++-------- invoices/update.go | 6 ++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 9ab1a65bb6..e83a21b614 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -780,11 +780,6 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, mpp := payload.MultiPath() - debugLog := func(s string) { - log.Debugf("Invoice(%x): %v, amt=%v, expiry=%v, circuit=%v, "+ - "mpp=%v", rHash[:], s, amtPaid, expiry, circuitKey, mpp) - } - // Create the update context containing the relevant details of the // incoming htlc. updateCtx := invoiceUpdateCtx{ @@ -804,7 +799,7 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, if i.cfg.AcceptKeySend { err := i.processKeySend(updateCtx) if err != nil { - debugLog(fmt.Sprintf("keysend error: %v", err)) + updateCtx.log(fmt.Sprintf("keysend error: %v", err)) return NewFailureResolution( circuitKey, currentHeight, ResultKeySendError, @@ -852,11 +847,11 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, case nil: default: - debugLog(err.Error()) + updateCtx.log(err.Error()) return nil, err } - debugLog(result.String()) + updateCtx.log(result.String()) if updateSubscribers { i.notifyClients(rHash, invoice, invoice.State) diff --git a/invoices/update.go b/invoices/update.go index 2e05b3984a..e6feaba062 100644 --- a/invoices/update.go +++ b/invoices/update.go @@ -180,6 +180,12 @@ type invoiceUpdateCtx struct { mpp *record.MPP } +// log logs a message specific to this update context. +func (i *invoiceUpdateCtx) log(s string) { + log.Debugf("Invoice(%x): %v, amt=%v, expiry=%v, circuit=%v, mpp=%v", + i.hash[:], s, i.amtPaid, i.expiry, i.circuitKey, i.mpp) +} + // updateInvoice is a callback for DB.UpdateInvoice that contains the invoice // settlement logic. func updateInvoice(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( From 0042a1ffeb8812417f467dbb32b14c61117ba062 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 4 Feb 2020 10:07:56 +0100 Subject: [PATCH 052/562] invoices: fix htlc timer deadlock --- invoices/invoiceregistry.go | 86 ++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index e83a21b614..d7ac13f7e5 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -807,8 +807,53 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, } } + // Execute locked notify exit hop logic. i.Lock() - defer i.Unlock() + resolution, err := i.notifyExitHopHtlcLocked(&updateCtx, hodlChan) + i.Unlock() + if err != nil { + return nil, err + } + + switch r := resolution.(type) { + + // A direct resolution was received for this htlc. + case *HtlcResolution: + return r, nil + + // The htlc is held. Start a timer outside the lock if the htlc should + // be auto-released, because otherwise a deadlock may happen with the + // main event loop. + case *acceptResolution: + if r.autoRelease { + err := i.startHtlcTimer(rHash, circuitKey, r.acceptTime) + if err != nil { + return nil, err + } + } + + return nil, nil + + default: + return nil, errors.New("invalid resolution type") + } +} + +// acceptResolution is returned when the htlc should be held. +type acceptResolution struct { + // autoRelease signals that the htlc should be automatically released + // after a timeout. + autoRelease bool + + // acceptTime is the time at which this htlc was accepted. + acceptTime time.Time +} + +// notifyExitHopHtlcLocked is the internal implementation of NotifyExitHopHtlc +// that should be executed inside the registry lock. +func (i *InvoiceRegistry) notifyExitHopHtlcLocked( + ctx *invoiceUpdateCtx, hodlChan chan<- interface{}) ( + interface{}, error) { // We'll attempt to settle an invoice matching this rHash on disk (if // one exists). The callback will update the invoice state and/or htlcs. @@ -817,11 +862,11 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, updateSubscribers bool ) invoice, err := i.cdb.UpdateInvoice( - rHash, + ctx.hash, func(inv *channeldb.Invoice) ( *channeldb.InvoiceUpdateDesc, error) { - updateDesc, res, err := updateInvoice(&updateCtx, inv) + updateDesc, res, err := updateInvoice(ctx, inv) if err != nil { return nil, err } @@ -841,29 +886,30 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, // If the invoice was not found, return a failure resolution // with an invoice not found result. return NewFailureResolution( - circuitKey, currentHeight, ResultInvoiceNotFound, + ctx.circuitKey, ctx.currentHeight, + ResultInvoiceNotFound, ), nil case nil: default: - updateCtx.log(err.Error()) + ctx.log(err.Error()) return nil, err } - updateCtx.log(result.String()) + ctx.log(result.String()) if updateSubscribers { - i.notifyClients(rHash, invoice, invoice.State) + i.notifyClients(ctx.hash, invoice, invoice.State) } // Inspect latest htlc state on the invoice. - invoiceHtlc, ok := invoice.Htlcs[circuitKey] + invoiceHtlc, ok := invoice.Htlcs[ctx.circuitKey] // If it isn't recorded, cancel htlc. if !ok { return NewFailureResolution( - circuitKey, currentHeight, result, + ctx.circuitKey, ctx.currentHeight, result, ), nil } @@ -876,7 +922,7 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, switch invoiceHtlc.State { case channeldb.HtlcStateCanceled: return NewFailureResolution( - circuitKey, acceptHeight, result, + ctx.circuitKey, acceptHeight, result, ), nil case channeldb.HtlcStateSettled: @@ -902,27 +948,25 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, } resolution := NewSettleResolution( - invoice.Terms.PaymentPreimage, circuitKey, + invoice.Terms.PaymentPreimage, ctx.circuitKey, acceptHeight, result, ) return resolution, nil case channeldb.HtlcStateAccepted: - // (Re)start the htlc timer if the invoice is still open. It can + var resolution acceptResolution + + // Auto-release the htlc if the invoice is still open. It can // only happen for mpp payments that there are htlcs in state // Accepted while the invoice is Open. if invoice.State == channeldb.ContractOpen { - err := i.startHtlcTimer( - rHash, circuitKey, - invoiceHtlc.AcceptTime, - ) - if err != nil { - return nil, err - } + resolution.acceptTime = invoiceHtlc.AcceptTime + resolution.autoRelease = true + } - i.hodlSubscribe(hodlChan, circuitKey) - return nil, nil + i.hodlSubscribe(hodlChan, ctx.circuitKey) + return &resolution, nil default: panic("unknown action") From 2569b4d08a0d11912c3f9cb88ececc6327360a32 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 6 Feb 2020 19:35:10 +0200 Subject: [PATCH 053/562] multi: replace htlcResolution with an interface This commit repalces the htlcResolution struct with an interface. This interface is implemeted by failure, settle and accept resolution structs. Only settles and fails are exported because the existing code that handles htlc resolutions uses a nil resolution to indicate that a htlc was accepted. The accept resolution is used internally to report on the resolution result of the accepted htlc, but a nil resolution is surfaced. Further refactoring of all the functions that call NotifyExitHopHtlc to handle a htlc accept case (rather than having a nil check) is required. --- .../htlc_incoming_contest_resolver.go | 59 ++++-- contractcourt/htlc_incoming_resolver_test.go | 14 +- contractcourt/interfaces.go | 2 +- contractcourt/mock_registry_test.go | 4 +- htlcswitch/interfaces.go | 2 +- htlcswitch/link.go | 63 +++--- htlcswitch/mock.go | 2 +- invoices/invoiceregistry.go | 184 ++++++++---------- invoices/invoiceregistry_test.go | 181 ++++++++++------- invoices/resolution.go | 124 ++++++++++++ invoices/update.go | 95 ++++++--- 11 files changed, 475 insertions(+), 255 deletions(-) create mode 100644 invoices/resolution.go diff --git a/contractcourt/htlc_incoming_contest_resolver.go b/contractcourt/htlc_incoming_contest_resolver.go index 98e52500a9..cc4c0f2b20 100644 --- a/contractcourt/htlc_incoming_contest_resolver.go +++ b/contractcourt/htlc_incoming_contest_resolver.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "errors" + "fmt" "io" "github.com/btcsuite/btcutil" @@ -172,7 +173,23 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) { processHtlcResolution := func(e invoices.HtlcResolution) ( ContractResolver, error) { - if e.Preimage == nil { + // Take action based on the type of resolution we have + // received. + switch resolution := e.(type) { + + // If the htlc resolution was a settle, apply the + // preimage and return a success resolver. + case *invoices.HtlcSettleResolution: + err := applyPreimage(resolution.Preimage) + if err != nil { + return nil, err + } + + return &h.htlcSuccessResolver, nil + + // If the htlc was failed, mark the htlc as + // resolved. + case *invoices.HtlcFailResolution: log.Infof("%T(%v): Exit hop HTLC canceled "+ "(expiry=%v, height=%v), abandoning", h, h.htlcResolution.ClaimOutpoint, @@ -180,13 +197,13 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) { h.resolved = true return nil, h.Checkpoint(h) - } - if err := applyPreimage(*e.Preimage); err != nil { - return nil, err + // Error if the resolution type is unknown, we are only + // expecting settles and fails. + default: + return nil, fmt.Errorf("unknown resolution"+ + " type: %v", e) } - - return &h.htlcSuccessResolver, nil } // Create a buffered hodl chan to prevent deadlock. @@ -211,14 +228,29 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) { defer h.Registry.HodlUnsubscribeAll(hodlChan) - // If the resolution is non-nil (indicating that a settle or cancel has - // occurred), and the invoice is known to the registry (indicating that - // the htlc is paying one of our invoices and is not a forward), try to - // resolve it directly. - if resolution != nil && - resolution.Outcome != invoices.ResultInvoiceNotFound { + // Take action based on the resolution we received. If the htlc was + // settled, or a htlc for a known invoice failed we can resolve it + // directly. If the resolution is nil, the htlc was neither accepted + // nor failed, so we cannot take action yet. + switch res := resolution.(type) { + case *invoices.HtlcFailResolution: + // In the case where the htlc failed, but the invoice was known + // to the registry, we can directly resolve the htlc. + if res.Outcome != invoices.ResultInvoiceNotFound { + return processHtlcResolution(resolution) + } - return processHtlcResolution(*resolution) + // If we settled the htlc, we can resolve it. + case *invoices.HtlcSettleResolution: + return processHtlcResolution(resolution) + + // If the resolution is nil, the htlc was neither settled nor failed so + // we cannot take action at present. + case nil: + + default: + return nil, fmt.Errorf("unknown htlc resolution type: %T", + resolution) } // With the epochs and preimage subscriptions initialized, we'll query @@ -256,7 +288,6 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) { case hodlItem := <-hodlChan: htlcResolution := hodlItem.(invoices.HtlcResolution) - return processHtlcResolution(htlcResolution) case newBlock, ok := <-blockEpochs.Epochs: diff --git a/contractcourt/htlc_incoming_resolver_test.go b/contractcourt/htlc_incoming_resolver_test.go index 773b22c003..400662d739 100644 --- a/contractcourt/htlc_incoming_resolver_test.go +++ b/contractcourt/htlc_incoming_resolver_test.go @@ -35,7 +35,7 @@ func TestHtlcIncomingResolverFwdPreimageKnown(t *testing.T) { defer timeout(t)() ctx := newIncomingResolverTestContext(t) - ctx.registry.notifyResolution = invoices.NewFailureResolution( + ctx.registry.notifyResolution = invoices.NewFailResolution( testResCircuitKey, testHtlcExpiry, invoices.ResultInvoiceNotFound, ) @@ -52,7 +52,7 @@ func TestHtlcIncomingResolverFwdContestedSuccess(t *testing.T) { defer timeout(t)() ctx := newIncomingResolverTestContext(t) - ctx.registry.notifyResolution = invoices.NewFailureResolution( + ctx.registry.notifyResolution = invoices.NewFailResolution( testResCircuitKey, testHtlcExpiry, invoices.ResultInvoiceNotFound, ) @@ -72,7 +72,7 @@ func TestHtlcIncomingResolverFwdContestedTimeout(t *testing.T) { defer timeout(t)() ctx := newIncomingResolverTestContext(t) - ctx.registry.notifyResolution = invoices.NewFailureResolution( + ctx.registry.notifyResolution = invoices.NewFailResolution( testResCircuitKey, testHtlcExpiry, invoices.ResultInvoiceNotFound, ) @@ -91,7 +91,7 @@ func TestHtlcIncomingResolverFwdTimeout(t *testing.T) { defer timeout(t)() ctx := newIncomingResolverTestContext(t) - ctx.registry.notifyResolution = invoices.NewFailureResolution( + ctx.registry.notifyResolution = invoices.NewFailResolution( testResCircuitKey, testHtlcExpiry, invoices.ResultInvoiceNotFound, ) @@ -139,7 +139,7 @@ func TestHtlcIncomingResolverExitCancel(t *testing.T) { defer timeout(t)() ctx := newIncomingResolverTestContext(t) - ctx.registry.notifyResolution = invoices.NewFailureResolution( + ctx.registry.notifyResolution = invoices.NewFailResolution( testResCircuitKey, testAcceptHeight, invoices.ResultInvoiceAlreadyCanceled, ) @@ -158,7 +158,7 @@ func TestHtlcIncomingResolverExitSettleHodl(t *testing.T) { ctx.resolve() notifyData := <-ctx.registry.notifyChan - notifyData.hodlChan <- *invoices.NewSettleResolution( + notifyData.hodlChan <- invoices.NewSettleResolution( testResPreimage, testResCircuitKey, testAcceptHeight, invoices.ResultSettled, ) @@ -187,7 +187,7 @@ func TestHtlcIncomingResolverExitCancelHodl(t *testing.T) { ctx := newIncomingResolverTestContext(t) ctx.resolve() notifyData := <-ctx.registry.notifyChan - notifyData.hodlChan <- *invoices.NewFailureResolution( + notifyData.hodlChan <- invoices.NewFailResolution( testResCircuitKey, testAcceptHeight, invoices.ResultCanceled, ) diff --git a/contractcourt/interfaces.go b/contractcourt/interfaces.go index 086a2aee56..18dfbc0e86 100644 --- a/contractcourt/interfaces.go +++ b/contractcourt/interfaces.go @@ -27,7 +27,7 @@ type Registry interface { NotifyExitHopHtlc(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi, expiry uint32, currentHeight int32, circuitKey channeldb.CircuitKey, hodlChan chan<- interface{}, - payload invoices.Payload) (*invoices.HtlcResolution, error) + payload invoices.Payload) (invoices.HtlcResolution, error) // HodlUnsubscribeAll unsubscribes from all htlc resolutions. HodlUnsubscribeAll(subscriber chan<- interface{}) diff --git a/contractcourt/mock_registry_test.go b/contractcourt/mock_registry_test.go index dca27d6299..a7f430f23e 100644 --- a/contractcourt/mock_registry_test.go +++ b/contractcourt/mock_registry_test.go @@ -18,13 +18,13 @@ type notifyExitHopData struct { type mockRegistry struct { notifyChan chan notifyExitHopData notifyErr error - notifyResolution *invoices.HtlcResolution + notifyResolution invoices.HtlcResolution } func (r *mockRegistry) NotifyExitHopHtlc(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi, expiry uint32, currentHeight int32, circuitKey channeldb.CircuitKey, hodlChan chan<- interface{}, - payload invoices.Payload) (*invoices.HtlcResolution, error) { + payload invoices.Payload) (invoices.HtlcResolution, error) { r.notifyChan <- notifyExitHopData{ hodlChan: hodlChan, diff --git a/htlcswitch/interfaces.go b/htlcswitch/interfaces.go index 1281e9515e..f0eae99ddc 100644 --- a/htlcswitch/interfaces.go +++ b/htlcswitch/interfaces.go @@ -27,7 +27,7 @@ type InvoiceDatabase interface { NotifyExitHopHtlc(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi, expiry uint32, currentHeight int32, circuitKey channeldb.CircuitKey, hodlChan chan<- interface{}, - payload invoices.Payload) (*invoices.HtlcResolution, error) + payload invoices.Payload) (invoices.HtlcResolution, error) // CancelInvoice attempts to cancel the invoice corresponding to the // passed payment hash. diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 92ecba65cb..dee3c588da 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1158,7 +1158,7 @@ loop: for { // Lookup all hodl htlcs that can be failed or settled with this event. // The hodl htlc must be present in the map. - circuitKey := htlcResolution.CircuitKey + circuitKey := htlcResolution.CircuitKey() hodlHtlc, ok := l.hodlMap[circuitKey] if !ok { return fmt.Errorf("hodl htlc not found: %v", circuitKey) @@ -1193,46 +1193,61 @@ loop: func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution, htlc hodlHtlc) error { - circuitKey := resolution.CircuitKey + circuitKey := resolution.CircuitKey() - // Determine required action for the resolution. If the event's preimage is - // non-nil, the htlc must be settled. Otherwise, it should be canceled. - if resolution.Preimage != nil { - l.log.Debugf("received settle resolution for %v", circuitKey) + // Determine required action for the resolution based on the type of + // resolution we have received. + switch res := resolution.(type) { + // Settle htlcs that returned a settle resolution using the preimage + // in the resolution. + case *invoices.HtlcSettleResolution: + l.log.Debugf("received settle resolution for %v"+ + "with outcome: %v", circuitKey, res.Outcome) return l.settleHTLC( - *resolution.Preimage, htlc.pd.HtlcIndex, + res.Preimage, htlc.pd.HtlcIndex, htlc.pd.SourceRef, ) - } - l.log.Debugf("received cancel resolution for %v with outcome: %v", - circuitKey, resolution.Outcome) + // For htlc failures, we get the relevant failure message based + // on the failure resolution and then fail the htlc. + case *invoices.HtlcFailResolution: + l.log.Debugf("received cancel resolution for "+ + "%v with outcome: %v", circuitKey, res.Outcome) - // Get the lnwire failure message based on the resolution result. - failure := getResolutionFailure(resolution, htlc.pd.Amount) + // Get the lnwire failure message based on the resolution + // result. + failure := getResolutionFailure(res, htlc.pd.Amount) - l.sendHTLCError( - htlc.pd.HtlcIndex, failure, htlc.obfuscator, - htlc.pd.SourceRef, - ) - return nil + l.sendHTLCError( + htlc.pd.HtlcIndex, failure, htlc.obfuscator, + htlc.pd.SourceRef, + ) + return nil + + // Fail if we do not get a settle of fail resolution, since we + // are only expecting to handle settles and fails. + default: + return fmt.Errorf("unknown htlc resolution type: %T", + resolution) + } } // getResolutionFailure returns the wire message that a htlc resolution should // be failed with. -func getResolutionFailure(resolution invoices.HtlcResolution, +func getResolutionFailure(resolution *invoices.HtlcFailResolution, amount lnwire.MilliSatoshi) lnwire.FailureMessage { - // If the resolution has been resolved as part of a MPP timeout, we need - // to fail the htlc with lnwire.FailMppTimeout. + // If the resolution has been resolved as part of a MPP timeout, + // we need to fail the htlc with lnwire.FailMppTimeout. if resolution.Outcome == invoices.ResultMppTimeout { return &lnwire.FailMPPTimeout{} } - // If the htlc is not a MPP timeout, we fail it with FailIncorrectDetails - // This covers hodl cancels (which return it to avoid leaking information - // and other invoice failures such as underpayment or expiry too soon. + // If the htlc is not a MPP timeout, we fail it with + // FailIncorrectDetails. This error is sent for invoice payment + // failures such as underpayment/ expiry too soon and hodl invoices + // (which return FailIncorrectDetails to avoid leaking information). return lnwire.NewFailIncorrectDetails( amount, uint32(resolution.AcceptHeight), ) @@ -2863,7 +2878,7 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor, } // Process the received resolution. - return l.processHtlcResolution(*event, htlc) + return l.processHtlcResolution(event, htlc) } // settleHTLC settles the HTLC on the channel. diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index 02737a715a..7cc9fb04ab 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -816,7 +816,7 @@ func (i *mockInvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error func (i *mockInvoiceRegistry) NotifyExitHopHtlc(rhash lntypes.Hash, amt lnwire.MilliSatoshi, expiry uint32, currentHeight int32, circuitKey channeldb.CircuitKey, hodlChan chan<- interface{}, - payload invoices.Payload) (*invoices.HtlcResolution, error) { + payload invoices.Payload) (invoices.HtlcResolution, error) { event, err := i.registry.NotifyExitHopHtlc( rhash, amt, expiry, currentHeight, circuitKey, hodlChan, diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 115b38af79..7f62ae45e7 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -36,48 +36,6 @@ const ( DefaultHtlcHoldDuration = 120 * time.Second ) -// HtlcResolution describes how an htlc should be resolved. If the preimage -// field is set, the event indicates a settle event. If Preimage is nil, it is -// a cancel event. -type HtlcResolution struct { - // Preimage is the htlc preimage. Its value is nil in case of a cancel. - Preimage *lntypes.Preimage - - // CircuitKey is the key of the htlc for which we have a resolution - // decision. - CircuitKey channeldb.CircuitKey - - // AcceptHeight is the original height at which the htlc was accepted. - AcceptHeight int32 - - // Outcome indicates the outcome of the invoice registry update. - Outcome ResolutionResult -} - -// NewFailureResolution returns a htlc failure resolution. -func NewFailureResolution(key channeldb.CircuitKey, - acceptHeight int32, outcome ResolutionResult) *HtlcResolution { - - return &HtlcResolution{ - CircuitKey: key, - AcceptHeight: acceptHeight, - Outcome: outcome, - } -} - -// NewSettleResolution returns a htlc resolution which is associated with a -// settle. -func NewSettleResolution(preimage lntypes.Preimage, key channeldb.CircuitKey, - acceptHeight int32, outcome ResolutionResult) *HtlcResolution { - - return &HtlcResolution{ - Preimage: &preimage, - CircuitKey: key, - AcceptHeight: acceptHeight, - Outcome: outcome, - } -} - // RegistryConfig contains the configuration parameters for invoice registry. type RegistryConfig struct { // FinalCltvRejectDelta defines the number of blocks before the expiry @@ -683,7 +641,7 @@ func (i *InvoiceRegistry) cancelSingleHtlc(hash lntypes.Hash, return fmt.Errorf("htlc %v not found", key) } if htlc.State == channeldb.HtlcStateCanceled { - resolution := *NewFailureResolution( + resolution := NewFailResolution( key, int32(htlc.AcceptHeight), result, ) @@ -777,7 +735,7 @@ func (i *InvoiceRegistry) processKeySend(ctx invoiceUpdateCtx) error { func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, amtPaid lnwire.MilliSatoshi, expiry uint32, currentHeight int32, circuitKey channeldb.CircuitKey, hodlChan chan<- interface{}, - payload Payload) (*HtlcResolution, error) { + payload Payload) (HtlcResolution, error) { mpp := payload.MultiPath() @@ -802,7 +760,7 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, if err != nil { updateCtx.log(fmt.Sprintf("keysend error: %v", err)) - return NewFailureResolution( + return NewFailResolution( circuitKey, currentHeight, ResultKeySendError, ), nil } @@ -817,15 +775,10 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, } switch r := resolution.(type) { - - // A direct resolution was received for this htlc. - case *HtlcResolution: - return r, nil - // The htlc is held. Start a timer outside the lock if the htlc should // be auto-released, because otherwise a deadlock may happen with the // main event loop. - case *acceptResolution: + case *htlcAcceptResolution: if r.autoRelease { err := i.startHtlcTimer(rHash, circuitKey, r.acceptTime) if err != nil { @@ -833,33 +786,31 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, } } + // We return a nil resolution because htlc acceptances are + // represented as nil resolutions externally. + // TODO(carla) update calling code to handle accept resolutions. return nil, nil + // A direct resolution was received for this htlc. + case HtlcResolution: + return r, nil + + // Fail if an unknown resolution type was received. default: return nil, errors.New("invalid resolution type") } } -// acceptResolution is returned when the htlc should be held. -type acceptResolution struct { - // autoRelease signals that the htlc should be automatically released - // after a timeout. - autoRelease bool - - // acceptTime is the time at which this htlc was accepted. - acceptTime time.Time -} - // notifyExitHopHtlcLocked is the internal implementation of NotifyExitHopHtlc // that should be executed inside the registry lock. func (i *InvoiceRegistry) notifyExitHopHtlcLocked( ctx *invoiceUpdateCtx, hodlChan chan<- interface{}) ( - interface{}, error) { + HtlcResolution, error) { // We'll attempt to settle an invoice matching this rHash on disk (if // one exists). The callback will update the invoice state and/or htlcs. var ( - result ResolutionResult + resolution HtlcResolution updateSubscribers bool ) invoice, err := i.cdb.UpdateInvoice( @@ -876,8 +827,8 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( updateSubscribers = updateDesc != nil && updateDesc.State != nil - // Assign result to outer scope variable. - result = res + // Assign resolution to outer scope variable. + resolution = res return updateDesc, nil }, @@ -886,7 +837,7 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( case channeldb.ErrInvoiceNotFound: // If the invoice was not found, return a failure resolution // with an invoice not found result. - return NewFailureResolution( + return NewFailResolution( ctx.circuitKey, ctx.currentHeight, ResultInvoiceNotFound, ), nil @@ -898,38 +849,40 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( return nil, err } - ctx.log(result.String()) - if updateSubscribers { i.notifyClients(ctx.hash, invoice, invoice.State) } - // Inspect latest htlc state on the invoice. - invoiceHtlc, ok := invoice.Htlcs[ctx.circuitKey] + switch res := resolution.(type) { + case *HtlcFailResolution: + // Inspect latest htlc state on the invoice. If it is found, + // we will update the accept height as it was recorded in the + // invoice database (which occurs in the case where the htlc + // reached the database in a previous call). If the htlc was + // not found on the invoice, it was immediately failed so we + // send the failure resolution as is, which has the current + // height set as the accept height. + invoiceHtlc, ok := invoice.Htlcs[ctx.circuitKey] + if ok { + res.AcceptHeight = int32(invoiceHtlc.AcceptHeight) + } - // If it isn't recorded, cancel htlc. - if !ok { - return NewFailureResolution( - ctx.circuitKey, ctx.currentHeight, result, - ), nil - } + ctx.log(fmt.Sprintf("failure resolution result "+ + "outcome: %v, at accept height: %v", + res.Outcome, res.AcceptHeight)) - // Determine accepted height of this htlc. If the htlc reached the - // invoice database (possibly in a previous call to the invoice - // registry), we'll take the original accepted height as it was recorded - // in the database. - acceptHeight := int32(invoiceHtlc.AcceptHeight) + return res, nil - switch invoiceHtlc.State { - case channeldb.HtlcStateCanceled: - return NewFailureResolution( - ctx.circuitKey, acceptHeight, result, - ), nil + // If the htlc was settled, we will settle any previously accepted + // htlcs and notify our peer to settle them. + case *HtlcSettleResolution: + ctx.log(fmt.Sprintf("settle resolution result "+ + "outcome: %v, at accept height: %v", + res.Outcome, res.AcceptHeight)) - case channeldb.HtlcStateSettled: - // Also settle any previously accepted htlcs. The invoice state - // is leading. If an htlc is marked as settled, we should follow - // now and settle the htlc with our peer. + // Also settle any previously accepted htlcs. If a htlc is + // marked as settled, we should follow now and settle the htlc + // with our peer. for key, htlc := range invoice.Htlcs { if htlc.State != channeldb.HtlcStateSettled { continue @@ -940,34 +893,49 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( // resolution is set based on the outcome of the single // htlc that we just settled, so may not be accurate // for all htlcs. - resolution := *NewSettleResolution( - invoice.Terms.PaymentPreimage, key, - acceptHeight, result, + htlcSettleResolution := NewSettleResolution( + res.Preimage, key, + int32(htlc.AcceptHeight), res.Outcome, ) - i.notifyHodlSubscribers(resolution) + // Notify subscribers that the htlc should be settled + // with our peer. + i.notifyHodlSubscribers(htlcSettleResolution) } - resolution := NewSettleResolution( - invoice.Terms.PaymentPreimage, ctx.circuitKey, - acceptHeight, result, - ) return resolution, nil - case channeldb.HtlcStateAccepted: - var resolution acceptResolution + // If we accepted the htlc, subscribe to the hodl invoice and return + // an accept resolution with the htlc's accept time on it. + case *htlcAcceptResolution: + invoiceHtlc, ok := invoice.Htlcs[ctx.circuitKey] + if !ok { + return nil, fmt.Errorf("accepted htlc: %v not"+ + " present on invoice: %x", ctx.circuitKey, + ctx.hash[:]) + } + + // Determine accepted height of this htlc. If the htlc reached + // the invoice database (possibly in a previous call to the + // invoice registry), we'll take the original accepted height + // as it was recorded in the database. + acceptHeight := int32(invoiceHtlc.AcceptHeight) + + ctx.log(fmt.Sprintf("accept resolution result "+ + "outcome: %v, at accept height: %v", + res.outcome, acceptHeight)) // Auto-release the htlc if the invoice is still open. It can // only happen for mpp payments that there are htlcs in state // Accepted while the invoice is Open. if invoice.State == channeldb.ContractOpen { - resolution.acceptTime = invoiceHtlc.AcceptTime - resolution.autoRelease = true + res.acceptTime = invoiceHtlc.AcceptTime + res.autoRelease = true } i.hodlSubscribe(hodlChan, ctx.circuitKey) - return &resolution, nil + return res, nil default: panic("unknown action") @@ -1022,7 +990,7 @@ func (i *InvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error { continue } - resolution := *NewSettleResolution( + resolution := NewSettleResolution( preimage, key, int32(htlc.AcceptHeight), ResultSettled, ) @@ -1102,7 +1070,7 @@ func (i *InvoiceRegistry) cancelInvoiceImpl(payHash lntypes.Hash, } i.notifyHodlSubscribers( - *NewFailureResolution( + NewFailResolution( key, int32(htlc.AcceptHeight), ResultCanceled, ), ) @@ -1374,7 +1342,7 @@ func (i *InvoiceRegistry) SubscribeSingleInvoice( // notifyHodlSubscribers sends out the htlc resolution to all current // subscribers. func (i *InvoiceRegistry) notifyHodlSubscribers(htlcResolution HtlcResolution) { - subscribers, ok := i.hodlSubscriptions[htlcResolution.CircuitKey] + subscribers, ok := i.hodlSubscriptions[htlcResolution.CircuitKey()] if !ok { return } @@ -1391,11 +1359,11 @@ func (i *InvoiceRegistry) notifyHodlSubscribers(htlcResolution HtlcResolution) { delete( i.hodlReverseSubscriptions[subscriber], - htlcResolution.CircuitKey, + htlcResolution.CircuitKey(), ) } - delete(i.hodlSubscriptions, htlcResolution.CircuitKey) + delete(i.hodlSubscriptions, htlcResolution.CircuitKey()) } // hodlSubscribe adds a new invoice subscription. diff --git a/invoices/invoiceregistry_test.go b/invoices/invoiceregistry_test.go index 9f360e267f..319c30cf05 100644 --- a/invoices/invoiceregistry_test.go +++ b/invoices/invoiceregistry_test.go @@ -74,29 +74,38 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatal(err) } - if resolution.Preimage != nil { - t.Fatal("expected cancel resolution") + failResolution, ok := resolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + resolution) } - if resolution.AcceptHeight != testCurrentHeight { + if failResolution.AcceptHeight != testCurrentHeight { t.Fatalf("expected acceptHeight %v, but got %v", - testCurrentHeight, resolution.AcceptHeight) + testCurrentHeight, failResolution.AcceptHeight) } - if resolution.Outcome != ResultExpiryTooSoon { + if failResolution.Outcome != ResultExpiryTooSoon { t.Fatalf("expected expiry too soon, got: %v", - resolution.Outcome) + failResolution.Outcome) } // Settle invoice with a slightly higher amount. amtPaid := lnwire.MilliSatoshi(100500) resolution, err = ctx.registry.NotifyExitHopHtlc( - testInvoicePaymentHash, amtPaid, testHtlcExpiry, testCurrentHeight, - getCircuitKey(0), hodlChan, testPayload, + testInvoicePaymentHash, amtPaid, testHtlcExpiry, + testCurrentHeight, getCircuitKey(0), hodlChan, + testPayload, ) if err != nil { t.Fatal(err) } - if resolution.Outcome != ResultSettled { - t.Fatalf("expected settled, got: %v", resolution.Outcome) + 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) } // We expect the settled state to be sent to the single invoice @@ -134,12 +143,14 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err) } - if resolution.Preimage == nil { - t.Fatal("expected settle resolution") + settleResolution, ok = resolution.(*HtlcSettleResolution) + if !ok { + t.Fatalf("expected settle resolution, got: %T", + resolution) } - if resolution.Outcome != ResultReplayToSettled { + if settleResolution.Outcome != ResultReplayToSettled { t.Fatalf("expected replay settled, got: %v", - resolution.Outcome) + settleResolution.Outcome) } // Try to settle again with a new higher-valued htlc. This payment @@ -152,12 +163,14 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err) } - if resolution.Preimage == nil { - t.Fatal("expected settle resolution") + settleResolution, ok = resolution.(*HtlcSettleResolution) + if !ok { + t.Fatalf("expected settle resolution, got: %T", + resolution) } - if resolution.Outcome != ResultDuplicateToSettled { + if settleResolution.Outcome != ResultDuplicateToSettled { t.Fatalf("expected duplicate settled, got: %v", - resolution.Outcome) + settleResolution.Outcome) } // Try to settle again with a lower amount. This should fail just as it @@ -169,12 +182,14 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err) } - if resolution.Preimage != nil { - t.Fatal("expected cancel resolution") + failResolution, ok = resolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + resolution) } - if resolution.Outcome != ResultAmountTooLow { + if failResolution.Outcome != ResultAmountTooLow { t.Fatalf("expected amount too low, got: %v", - resolution.Outcome) + failResolution.Outcome) } // Check that settled amount is equal to the sum of values of the htlcs @@ -298,17 +313,18 @@ func TestCancelInvoice(t *testing.T) { if err != nil { t.Fatal("expected settlement of a canceled invoice to succeed") } - - if resolution.Preimage != nil { - t.Fatal("expected cancel htlc resolution") + failResolution, ok := resolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + resolution) } - if resolution.AcceptHeight != testCurrentHeight { + if failResolution.AcceptHeight != testCurrentHeight { t.Fatalf("expected acceptHeight %v, but got %v", - testCurrentHeight, resolution.AcceptHeight) + testCurrentHeight, failResolution.AcceptHeight) } - if resolution.Outcome != ResultInvoiceAlreadyCanceled { - t.Fatalf("expected invoice already canceled, got: %v", - resolution.Outcome) + if failResolution.Outcome != ResultInvoiceAlreadyCanceled { + t.Fatalf("expected expiry too soon, got: %v", + failResolution.Outcome) } } @@ -422,12 +438,14 @@ func TestSettleHoldInvoice(t *testing.T) { if err != nil { t.Fatalf("expected settle to succeed but got %v", err) } - if resolution == nil || resolution.Preimage != nil { - t.Fatalf("expected htlc to be canceled") + failResolution, ok := resolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + resolution) } - if resolution.Outcome != ResultExpiryTooSoon { + if failResolution.Outcome != ResultExpiryTooSoon { t.Fatalf("expected expiry too soon, got: %v", - resolution.Outcome) + failResolution.Outcome) } // We expect the accepted state to be sent to the single invoice @@ -449,16 +467,21 @@ func TestSettleHoldInvoice(t *testing.T) { } htlcResolution := (<-hodlChan).(HtlcResolution) - if *htlcResolution.Preimage != testInvoicePreimage { + 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 htlcResolution.AcceptHeight != testCurrentHeight { + if settleResolution.AcceptHeight != testCurrentHeight { t.Fatalf("expected acceptHeight %v, but got %v", - testCurrentHeight, resolution.AcceptHeight) + testCurrentHeight, settleResolution.AcceptHeight) } - if htlcResolution.Outcome != ResultSettled { + if settleResolution.Outcome != ResultSettled { t.Fatalf("expected result settled, got: %v", - htlcResolution.Outcome) + settleResolution.Outcome) } // We expect a settled notification to be sent out for both all and @@ -545,8 +568,10 @@ func TestCancelHoldInvoice(t *testing.T) { } htlcResolution := (<-hodlChan).(HtlcResolution) - if htlcResolution.Preimage != nil { - t.Fatal("expected cancel htlc resolution") + _, ok := htlcResolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + htlcResolution) } // Offering the same htlc again at a higher height should still result @@ -559,16 +584,18 @@ func TestCancelHoldInvoice(t *testing.T) { if err != nil { t.Fatalf("expected settle to succeed but got %v", err) } - if resolution.Preimage != nil { - t.Fatalf("expected htlc to be canceled") + failResolution, ok := resolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + resolution) } - if resolution.AcceptHeight != testCurrentHeight { + if failResolution.AcceptHeight != testCurrentHeight { t.Fatalf("expected acceptHeight %v, but got %v", - testCurrentHeight, resolution.AcceptHeight) + testCurrentHeight, failResolution.AcceptHeight) } - if resolution.Outcome != ResultReplayToCanceled { + if failResolution.Outcome != ResultReplayToCanceled { t.Fatalf("expected replay to canceled, got %v", - resolution.Outcome) + failResolution.Outcome) } } @@ -585,16 +612,21 @@ func TestUnknownInvoice(t *testing.T) { // succeed. hodlChan := make(chan interface{}) amt := lnwire.MilliSatoshi(100000) - result, err := ctx.registry.NotifyExitHopHtlc( + resolution, err := ctx.registry.NotifyExitHopHtlc( testInvoicePaymentHash, amt, testHtlcExpiry, testCurrentHeight, getCircuitKey(0), hodlChan, testPayload, ) if err != nil { t.Fatal("unexpected error") } - if result.Outcome != ResultInvoiceNotFound { + failResolution, ok := resolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + resolution) + } + if failResolution.Outcome != ResultInvoiceNotFound { t.Fatalf("expected ResultInvoiceNotFound, got: %v", - result.Outcome) + failResolution.Outcome) } } @@ -646,16 +678,17 @@ func testKeySend(t *testing.T, keySendEnabled bool) { if err != nil { t.Fatal(err) } - - // Expect a cancel resolution with the correct outcome. - if resolution.Preimage != nil { - t.Fatal("expected cancel resolution") + failResolution, ok := resolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + resolution) } + switch { - case !keySendEnabled && resolution.Outcome != ResultInvoiceNotFound: + case !keySendEnabled && failResolution.Outcome != ResultInvoiceNotFound: t.Fatal("expected invoice not found outcome") - case keySendEnabled && resolution.Outcome != ResultKeySendError: + case keySendEnabled && failResolution.Outcome != ResultKeySendError: t.Fatal("expected keysend error") } @@ -676,15 +709,25 @@ func testKeySend(t *testing.T, keySendEnabled bool) { // Expect a cancel resolution if keysend is disabled. if !keySendEnabled { - if resolution.Outcome != ResultInvoiceNotFound { + 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") } return } // Otherwise we expect no error and a settle resolution for the htlc. - if resolution.Preimage == nil || *resolution.Preimage != preimage { - t.Fatal("expected valid settle event") + settleResolution, ok := resolution.(*HtlcSettleResolution) + if !ok { + t.Fatalf("expected settle resolution, got: %T", + resolution) + } + if settleResolution.Preimage != preimage { + t.Fatalf("expected settle with matching preimage") } // We expect a new invoice notification to be sent out. @@ -739,12 +782,14 @@ func TestMppPayment(t *testing.T) { ctx.clock.SetTime(testTime.Add(30 * time.Second)) htlcResolution := (<-hodlChan1).(HtlcResolution) - if htlcResolution.Preimage != nil { - t.Fatal("expected cancel resolution") + failResolution, ok := htlcResolution.(*HtlcFailResolution) + if !ok { + t.Fatalf("expected fail resolution, got: %T", + resolution) } - if htlcResolution.Outcome != ResultMppTimeout { + if failResolution.Outcome != ResultMppTimeout { t.Fatalf("expected mpp timeout, got: %v", - htlcResolution.Outcome) + failResolution.Outcome) } // Send htlc 2. @@ -771,12 +816,14 @@ func TestMppPayment(t *testing.T) { if err != nil { t.Fatal(err) } - if resolution == nil { - t.Fatal("expected a settle resolution") + settleResolution, ok := resolution.(*HtlcSettleResolution) + if !ok { + t.Fatalf("expected settle resolution, got: %T", + htlcResolution) } - if resolution.Outcome != ResultSettled { + if settleResolution.Outcome != ResultSettled { t.Fatalf("expected result settled, got: %v", - resolution.Outcome) + settleResolution.Outcome) } // Check that settled amount is equal to the sum of values of the htlcs diff --git a/invoices/resolution.go b/invoices/resolution.go new file mode 100644 index 0000000000..483a577752 --- /dev/null +++ b/invoices/resolution.go @@ -0,0 +1,124 @@ +package invoices + +import ( + "time" + + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lntypes" +) + +// HtlcResolution describes how an htlc should be resolved. +type HtlcResolution interface { + // CircuitKey returns the circuit key for the htlc that we have a + // resolution for. + CircuitKey() channeldb.CircuitKey +} + +// HtlcFailResolution is an implementation of the HtlcResolution interface +// which is returned when a htlc is failed. +type HtlcFailResolution struct { + // circuitKey is the key of the htlc for which we have a resolution. + circuitKey channeldb.CircuitKey + + // AcceptHeight is the original height at which the htlc was accepted. + AcceptHeight int32 + + // outcome indicates the outcome of the invoice registry update. + Outcome ResolutionResult +} + +// NewFailResolution returns a htlc failure resolution. +func NewFailResolution(key channeldb.CircuitKey, + acceptHeight int32, outcome ResolutionResult) *HtlcFailResolution { + + return &HtlcFailResolution{ + circuitKey: key, + AcceptHeight: acceptHeight, + Outcome: outcome, + } +} + +// CircuitKey returns the circuit key for the htlc that we have a +// resolution for. +// +// Note: it is part of the HtlcResolution interface. +func (f *HtlcFailResolution) CircuitKey() channeldb.CircuitKey { + return f.circuitKey +} + +// HtlcSettleResolution is an implementation of the HtlcResolution interface +// which is returned when a htlc is settled. +type HtlcSettleResolution struct { + // Preimage is the htlc preimage. Its value is nil in case of a cancel. + Preimage lntypes.Preimage + + // circuitKey is the key of the htlc for which we have a resolution. + circuitKey channeldb.CircuitKey + + // acceptHeight is the original height at which the htlc was accepted. + AcceptHeight int32 + + // Outcome indicates the outcome of the invoice registry update. + Outcome ResolutionResult +} + +// NewSettleResolution returns a htlc resolution which is associated with a +// settle. +func NewSettleResolution(preimage lntypes.Preimage, key channeldb.CircuitKey, + acceptHeight int32, outcome ResolutionResult) *HtlcSettleResolution { + + return &HtlcSettleResolution{ + Preimage: preimage, + circuitKey: key, + AcceptHeight: acceptHeight, + Outcome: outcome, + } +} + +// CircuitKey returns the circuit key for the htlc that we have a +// resolution for. +// +// Note: it is part of the HtlcResolution interface. +func (s *HtlcSettleResolution) CircuitKey() channeldb.CircuitKey { + return s.circuitKey +} + +// htlcAcceptResolution is an implementation of the HtlcResolution interface +// which is returned when a htlc is accepted. This struct is not exported +// because the codebase uses a nil resolution to indicate that a htlc was +// accepted. This struct is used internally in the invoice registry to +// surface accept resolution results. When an invoice update returns an +// acceptResolution, a nil resolution should be surfaced. +type htlcAcceptResolution struct { + // circuitKey is the key of the htlc for which we have a resolution. + circuitKey channeldb.CircuitKey + + // autoRelease signals that the htlc should be automatically released + // after a timeout. + autoRelease bool + + // acceptTime is the time at which this htlc was accepted. + acceptTime time.Time + + // outcome indicates the outcome of the invoice registry update. + outcome ResolutionResult +} + +// newAcceptResolution returns a htlc resolution which is associated with a +// htlc accept. +func newAcceptResolution(key channeldb.CircuitKey, + outcome ResolutionResult) *htlcAcceptResolution { + + return &htlcAcceptResolution{ + circuitKey: key, + outcome: outcome, + } +} + +// CircuitKey returns the circuit key for the htlc that we have a +// resolution for. +// +// Note: it is part of the HtlcResolution interface. +func (a *htlcAcceptResolution) CircuitKey() channeldb.CircuitKey { + return a.circuitKey +} diff --git a/invoices/update.go b/invoices/update.go index e6feaba062..c747521e84 100644 --- a/invoices/update.go +++ b/invoices/update.go @@ -186,26 +186,53 @@ func (i *invoiceUpdateCtx) log(s string) { i.hash[:], s, i.amtPaid, i.expiry, i.circuitKey, i.mpp) } +// failRes is a helper function which creates a failure resolution with +// the information contained in the invoiceUpdateCtx and the outcome provided. +func (i invoiceUpdateCtx) failRes(outcome ResolutionResult) *HtlcFailResolution { + return NewFailResolution(i.circuitKey, i.currentHeight, outcome) +} + +// settleRes is a helper function which creates a settle resolution with +// the information contained in the invoiceUpdateCtx and the preimage and +// outcome provided. +func (i invoiceUpdateCtx) settleRes(preimage lntypes.Preimage, + outcome ResolutionResult) *HtlcSettleResolution { + + return NewSettleResolution( + preimage, i.circuitKey, i.currentHeight, outcome, + ) +} + +// acceptRes is a helper function which creates an accept resolution with +// the information contained in the invoiceUpdateCtx and the outcome provided. +func (i invoiceUpdateCtx) acceptRes(outcome ResolutionResult) *htlcAcceptResolution { + return newAcceptResolution(i.circuitKey, outcome) +} + // updateInvoice is a callback for DB.UpdateInvoice that contains the invoice -// settlement logic. +// settlement logic. It returns a hltc resolution that indicates what the +// outcome of the update was. func updateInvoice(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( - *channeldb.InvoiceUpdateDesc, ResolutionResult, error) { + *channeldb.InvoiceUpdateDesc, HtlcResolution, error) { // Don't update the invoice when this is a replayed htlc. htlc, ok := inv.Htlcs[ctx.circuitKey] if ok { switch htlc.State { case channeldb.HtlcStateCanceled: - return nil, ResultReplayToCanceled, nil + return nil, ctx.failRes(ResultReplayToCanceled), nil case channeldb.HtlcStateAccepted: - return nil, ResultReplayToAccepted, nil + return nil, ctx.acceptRes(ResultReplayToAccepted), nil case channeldb.HtlcStateSettled: - return nil, ResultReplayToSettled, nil + return nil, ctx.settleRes( + inv.Terms.PaymentPreimage, + ResultReplayToSettled, + ), nil default: - return nil, 0, errors.New("unknown htlc state") + return nil, nil, errors.New("unknown htlc state") } } @@ -218,8 +245,9 @@ func updateInvoice(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( // updateMpp is a callback for DB.UpdateInvoice that contains the invoice // settlement logic for mpp payments. -func updateMpp(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( - *channeldb.InvoiceUpdateDesc, ResolutionResult, error) { +func updateMpp(ctx *invoiceUpdateCtx, + inv *channeldb.Invoice) (*channeldb.InvoiceUpdateDesc, + HtlcResolution, error) { // Start building the accept descriptor. acceptDesc := &channeldb.HtlcAcceptDesc{ @@ -235,23 +263,23 @@ func updateMpp(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( // Because non-mpp payments don't have a payment address, this is needed // to thwart probing. if inv.State != channeldb.ContractOpen { - return nil, ResultInvoiceNotOpen, nil + return nil, ctx.failRes(ResultInvoiceNotOpen), nil } // Check the payment address that authorizes the payment. if ctx.mpp.PaymentAddr() != inv.Terms.PaymentAddr { - return nil, ResultAddressMismatch, nil + return nil, ctx.failRes(ResultAddressMismatch), nil } // Don't accept zero-valued sets. if ctx.mpp.TotalMsat() == 0 { - return nil, ResultHtlcSetTotalTooLow, nil + return nil, ctx.failRes(ResultHtlcSetTotalTooLow), nil } // Check that the total amt of the htlc set is high enough. In case this // is a zero-valued invoice, it will always be enough. if ctx.mpp.TotalMsat() < inv.Terms.Value { - return nil, ResultHtlcSetTotalTooLow, nil + return nil, ctx.failRes(ResultHtlcSetTotalTooLow), nil } // Check whether total amt matches other htlcs in the set. @@ -265,7 +293,7 @@ func updateMpp(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( } if ctx.mpp.TotalMsat() != htlc.MppTotalAmt { - return nil, ResultHtlcSetTotalMismatch, nil + return nil, ctx.failRes(ResultHtlcSetTotalMismatch), nil } newSetTotal += htlc.Amt @@ -276,16 +304,16 @@ func updateMpp(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( // Make sure the communicated set total isn't overpaid. if newSetTotal > ctx.mpp.TotalMsat() { - return nil, ResultHtlcSetOverpayment, nil + return nil, ctx.failRes(ResultHtlcSetOverpayment), nil } // The invoice is still open. Check the expiry. if ctx.expiry < uint32(ctx.currentHeight+ctx.finalCltvRejectDelta) { - return nil, ResultExpiryTooSoon, nil + return nil, ctx.failRes(ResultExpiryTooSoon), nil } if ctx.expiry < uint32(ctx.currentHeight+inv.Terms.FinalCltvDelta) { - return nil, ResultExpiryTooSoon, nil + return nil, ctx.failRes(ResultExpiryTooSoon), nil } // Record HTLC in the invoice database. @@ -300,7 +328,7 @@ func updateMpp(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( // If the invoice cannot be settled yet, only record the htlc. setComplete := newSetTotal == ctx.mpp.TotalMsat() if !setComplete { - return &update, ResultPartialAccepted, nil + return &update, ctx.acceptRes(ResultPartialAccepted), nil } // Check to see if we can settle or this is an hold invoice and @@ -310,7 +338,7 @@ func updateMpp(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( update.State = &channeldb.InvoiceStateUpdateDesc{ NewState: channeldb.ContractAccepted, } - return &update, ResultAccepted, nil + return &update, ctx.acceptRes(ResultAccepted), nil } update.State = &channeldb.InvoiceStateUpdateDesc{ @@ -318,18 +346,20 @@ func updateMpp(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( Preimage: inv.Terms.PaymentPreimage, } - return &update, ResultSettled, nil + return &update, ctx.settleRes( + inv.Terms.PaymentPreimage, ResultSettled, + ), nil } // updateLegacy is a callback for DB.UpdateInvoice that contains the invoice // settlement logic for legacy payments. -func updateLegacy(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( - *channeldb.InvoiceUpdateDesc, ResolutionResult, error) { +func updateLegacy(ctx *invoiceUpdateCtx, + inv *channeldb.Invoice) (*channeldb.InvoiceUpdateDesc, HtlcResolution, error) { // If the invoice is already canceled, there is no further // checking to do. if inv.State == channeldb.ContractCanceled { - return nil, ResultInvoiceAlreadyCanceled, nil + return nil, ctx.failRes(ResultInvoiceAlreadyCanceled), nil } // If an invoice amount is specified, check that enough is paid. Also @@ -337,7 +367,7 @@ func updateLegacy(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( // or accepted. In case this is a zero-valued invoice, it will always be // enough. if ctx.amtPaid < inv.Terms.Value { - return nil, ResultAmountTooLow, nil + return nil, ctx.failRes(ResultAmountTooLow), nil } // TODO(joostjager): Check invoice mpp required feature @@ -350,17 +380,17 @@ func updateLegacy(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( if htlc.State == channeldb.HtlcStateAccepted && htlc.MppTotalAmt > 0 { - return nil, ResultMppInProgress, nil + return nil, ctx.failRes(ResultMppInProgress), nil } } // The invoice is still open. Check the expiry. if ctx.expiry < uint32(ctx.currentHeight+ctx.finalCltvRejectDelta) { - return nil, ResultExpiryTooSoon, nil + return nil, ctx.failRes(ResultExpiryTooSoon), nil } if ctx.expiry < uint32(ctx.currentHeight+inv.Terms.FinalCltvDelta) { - return nil, ResultExpiryTooSoon, nil + return nil, ctx.failRes(ResultExpiryTooSoon), nil } // Record HTLC in the invoice database. @@ -381,10 +411,12 @@ func updateLegacy(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( // We do accept or settle the HTLC. switch inv.State { case channeldb.ContractAccepted: - return &update, ResultDuplicateToAccepted, nil + return &update, ctx.acceptRes(ResultDuplicateToAccepted), nil case channeldb.ContractSettled: - return &update, ResultDuplicateToSettled, nil + return &update, ctx.settleRes( + inv.Terms.PaymentPreimage, ResultDuplicateToSettled, + ), nil } // Check to see if we can settle or this is an hold invoice and we need @@ -394,7 +426,8 @@ func updateLegacy(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( update.State = &channeldb.InvoiceStateUpdateDesc{ NewState: channeldb.ContractAccepted, } - return &update, ResultAccepted, nil + + return &update, ctx.acceptRes(ResultAccepted), nil } update.State = &channeldb.InvoiceStateUpdateDesc{ @@ -402,5 +435,7 @@ func updateLegacy(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( Preimage: inv.Terms.PaymentPreimage, } - return &update, ResultSettled, nil + return &update, ctx.settleRes( + inv.Terms.PaymentPreimage, ResultSettled, + ), nil } From 8cbed23f26ee208200865874ed18e03db6e6f046 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 6 Feb 2020 19:35:16 +0200 Subject: [PATCH 054/562] invoices: split resolution result into settle, fail and accept enums This commit splits the resolution result enum into results divided by outcome (settled, failed or accepted). This allows us to more strictly control which resolution results can be used with which HtlcResolution structs, to prevent the combination of a settle resolution result with a failure resolution result, for example. --- invoices/invoiceregistry.go | 2 +- invoices/resolution.go | 17 +-- invoices/resolution_result.go | 200 ++++++++++++++++++++++++++++++++++ invoices/update.go | 182 +++---------------------------- 4 files changed, 223 insertions(+), 178 deletions(-) create mode 100644 invoices/resolution_result.go diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 7f62ae45e7..00885edb9d 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -565,7 +565,7 @@ func (i *InvoiceRegistry) startHtlcTimer(hash lntypes.Hash, // a resolution result which will be used to notify subscribed links and // resolvers of the details of the htlc cancellation. func (i *InvoiceRegistry) cancelSingleHtlc(hash lntypes.Hash, - key channeldb.CircuitKey, result ResolutionResult) error { + key channeldb.CircuitKey, result FailResolutionResult) error { i.Lock() defer i.Unlock() diff --git a/invoices/resolution.go b/invoices/resolution.go index 483a577752..e6f3133036 100644 --- a/invoices/resolution.go +++ b/invoices/resolution.go @@ -23,13 +23,13 @@ type HtlcFailResolution struct { // AcceptHeight is the original height at which the htlc was accepted. AcceptHeight int32 - // outcome indicates the outcome of the invoice registry update. - Outcome ResolutionResult + // Outcome indicates the outcome of the invoice registry update. + Outcome FailResolutionResult } // NewFailResolution returns a htlc failure resolution. func NewFailResolution(key channeldb.CircuitKey, - acceptHeight int32, outcome ResolutionResult) *HtlcFailResolution { + acceptHeight int32, outcome FailResolutionResult) *HtlcFailResolution { return &HtlcFailResolution{ circuitKey: key, @@ -59,13 +59,14 @@ type HtlcSettleResolution struct { AcceptHeight int32 // Outcome indicates the outcome of the invoice registry update. - Outcome ResolutionResult + Outcome SettleResolutionResult } // NewSettleResolution returns a htlc resolution which is associated with a // settle. -func NewSettleResolution(preimage lntypes.Preimage, key channeldb.CircuitKey, - acceptHeight int32, outcome ResolutionResult) *HtlcSettleResolution { +func NewSettleResolution(preimage lntypes.Preimage, + key channeldb.CircuitKey, acceptHeight int32, + outcome SettleResolutionResult) *HtlcSettleResolution { return &HtlcSettleResolution{ Preimage: preimage, @@ -101,13 +102,13 @@ type htlcAcceptResolution struct { acceptTime time.Time // outcome indicates the outcome of the invoice registry update. - outcome ResolutionResult + outcome acceptResolutionResult } // newAcceptResolution returns a htlc resolution which is associated with a // htlc accept. func newAcceptResolution(key channeldb.CircuitKey, - outcome ResolutionResult) *htlcAcceptResolution { + outcome acceptResolutionResult) *htlcAcceptResolution { return &htlcAcceptResolution{ circuitKey: key, diff --git a/invoices/resolution_result.go b/invoices/resolution_result.go new file mode 100644 index 0000000000..3952d11a57 --- /dev/null +++ b/invoices/resolution_result.go @@ -0,0 +1,200 @@ +package invoices + +// acceptResolutionResult provides metadata which about a htlc that was +// accepted by the registry. +type acceptResolutionResult uint8 + +const ( + resultInvalidAccept acceptResolutionResult = iota + + // resultReplayToAccepted is returned when we replay an accepted + // invoice. + resultReplayToAccepted + + // resultDuplicateToAccepted is returned when we accept a duplicate + // htlc. + resultDuplicateToAccepted + + // resultAccepted is returned when we accept a hodl invoice. + resultAccepted + + // resultPartialAccepted is returned when we have partially received + // payment. + resultPartialAccepted +) + +// String returns a string representation of the result. +func (a acceptResolutionResult) String() string { + switch a { + case resultInvalidAccept: + return "invalid accept result" + + case resultReplayToAccepted: + return "replayed htlc to accepted invoice" + + case resultDuplicateToAccepted: + return "accepting duplicate payment to accepted invoice" + + case resultAccepted: + return "accepted" + + case resultPartialAccepted: + return "partial payment accepted" + + default: + return "unknown accept resolution result" + } +} + +// FailResolutionResult provides metadata about a htlc that was failed by +// the registry. It can be used to take custom actions on resolution of the +// htlc. +type FailResolutionResult uint8 + +const ( + resultInvalidFailure FailResolutionResult = iota + + // ResultReplayToCanceled is returned when we replay a canceled invoice. + ResultReplayToCanceled + + // ResultInvoiceAlreadyCanceled is returned when trying to pay an + // invoice that is already canceled. + ResultInvoiceAlreadyCanceled + + // ResultAmountTooLow is returned when an invoice is underpaid. + ResultAmountTooLow + + // ResultExpiryTooSoon is returned when we do not accept an invoice + // payment because it expires too soon. + ResultExpiryTooSoon + + // ResultCanceled is returned when we cancel an invoice and its + // associated htlcs. + ResultCanceled + + // ResultInvoiceNotOpen is returned when a mpp invoice is not open. + ResultInvoiceNotOpen + + // ResultMppTimeout is returned when an invoice paid with multiple + // partial payments times out before it is fully paid. + ResultMppTimeout + + // ResultAddressMismatch is returned when the payment address for a mpp + // invoice does not match. + ResultAddressMismatch + + // ResultHtlcSetTotalMismatch is returned when the amount paid by a + // htlc does not match its set total. + ResultHtlcSetTotalMismatch + + // ResultHtlcSetTotalTooLow is returned when a mpp set total is too low + // for an invoice. + ResultHtlcSetTotalTooLow + + // ResultHtlcSetOverpayment is returned when a mpp set is overpaid. + ResultHtlcSetOverpayment + + // ResultInvoiceNotFound is returned when an attempt is made to pay an + // invoice that is unknown to us. + ResultInvoiceNotFound + + // ResultKeySendError is returned when we receive invalid keysend + // parameters. + ResultKeySendError + + // ResultMppInProgress is returned when we are busy receiving a mpp + // payment. + ResultMppInProgress +) + +// String returns a string representation of the result. +func (f FailResolutionResult) String() string { + switch f { + case resultInvalidFailure: + return "invalid failure result" + + case ResultReplayToCanceled: + return "replayed htlc to canceled invoice" + + case ResultInvoiceAlreadyCanceled: + return "invoice already canceled" + + case ResultAmountTooLow: + return "amount too low" + + case ResultExpiryTooSoon: + return "expiry too soon" + + case ResultCanceled: + return "canceled" + + case ResultInvoiceNotOpen: + return "invoice no longer open" + + case ResultMppTimeout: + return "mpp timeout" + + case ResultAddressMismatch: + return "payment address mismatch" + + case ResultHtlcSetTotalMismatch: + return "htlc total amt doesn't match set total" + + case ResultHtlcSetTotalTooLow: + return "set total too low for invoice" + + case ResultHtlcSetOverpayment: + return "mpp is overpaying set total" + + case ResultInvoiceNotFound: + return "invoice not found" + + case ResultKeySendError: + return "invalid keysend parameters" + + case ResultMppInProgress: + return "mpp reception in progress" + + default: + return "unknown failure resolution result" + } +} + +// 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. +type SettleResolutionResult uint8 + +const ( + resultInvalidSettle SettleResolutionResult = iota + + // ResultSettled is returned when we settle an invoice. + ResultSettled + + // ResultReplayToSettled is returned when we replay a settled invoice. + ResultReplayToSettled + + // ResultDuplicateToSettled is returned when we settle an invoice which + // has already been settled at least once. + ResultDuplicateToSettled +) + +// String returns a string representation of the result. +func (s SettleResolutionResult) String() string { + switch s { + case resultInvalidSettle: + return "invalid settle result" + + case ResultSettled: + return "settled" + + case ResultReplayToSettled: + return "replayed htlc to settled invoice" + + case ResultDuplicateToSettled: + return "accepting duplicate payment to settled invoice" + + default: + return "unknown settle resolution result" + } +} diff --git a/invoices/update.go b/invoices/update.go index c747521e84..3226779ce1 100644 --- a/invoices/update.go +++ b/invoices/update.go @@ -9,164 +9,6 @@ import ( "github.com/lightningnetwork/lnd/record" ) -// ResolutionResult provides metadata which about an invoice update which can -// be used to take custom actions on resolution of the htlc. Only results which -// are actionable by the link are exported. -type ResolutionResult uint8 - -const ( - resultInvalid ResolutionResult = iota - - // ResultReplayToCanceled is returned when we replay a canceled invoice. - ResultReplayToCanceled - - // ResultReplayToAccepted is returned when we replay an accepted invoice. - ResultReplayToAccepted - - // ResultReplayToSettled is returned when we replay a settled invoice. - ResultReplayToSettled - - // ResultInvoiceAlreadyCanceled is returned when trying to pay an invoice - // that is already canceled. - ResultInvoiceAlreadyCanceled - - // ResultAmountTooLow is returned when an invoice is underpaid. - ResultAmountTooLow - - // ResultExpiryTooSoon is returned when we do not accept an invoice payment - // because it expires too soon. - ResultExpiryTooSoon - - // ResultDuplicateToAccepted is returned when we accept a duplicate htlc. - ResultDuplicateToAccepted - - // ResultDuplicateToSettled is returned when we settle an invoice which has - // already been settled at least once. - ResultDuplicateToSettled - - // ResultAccepted is returned when we accept a hodl invoice. - ResultAccepted - - // ResultSettled is returned when we settle an invoice. - ResultSettled - - // ResultCanceled is returned when we cancel an invoice and its associated - // htlcs. - ResultCanceled - - // ResultInvoiceNotOpen is returned when a mpp invoice is not open. - ResultInvoiceNotOpen - - // ResultPartialAccepted is returned when we have partially received - // payment. - ResultPartialAccepted - - // ResultMppInProgress is returned when we are busy receiving a mpp payment. - ResultMppInProgress - - // ResultMppTimeout is returned when an invoice paid with multiple partial - // payments times out before it is fully paid. - ResultMppTimeout - - // ResultAddressMismatch is returned when the payment address for a mpp - // invoice does not match. - ResultAddressMismatch - - // ResultHtlcSetTotalMismatch is returned when the amount paid by a htlc - // does not match its set total. - ResultHtlcSetTotalMismatch - - // ResultHtlcSetTotalTooLow is returned when a mpp set total is too low for - // an invoice. - ResultHtlcSetTotalTooLow - - // ResultHtlcSetOverpayment is returned when a mpp set is overpaid. - ResultHtlcSetOverpayment - - // ResultInvoiceNotFound is returned when an attempt is made to pay an - // invoice that is unknown to us. - ResultInvoiceNotFound - - // ResultKeySendError is returned when we receive invalid keysend - // parameters. - ResultKeySendError -) - -// String returns a human-readable representation of the invoice update result. -func (u ResolutionResult) String() string { - switch u { - - case resultInvalid: - return "invalid" - - case ResultReplayToCanceled: - return "replayed htlc to canceled invoice" - - case ResultReplayToAccepted: - return "replayed htlc to accepted invoice" - - case ResultReplayToSettled: - return "replayed htlc to settled invoice" - - case ResultInvoiceAlreadyCanceled: - return "invoice already canceled" - - case ResultAmountTooLow: - return "amount too low" - - case ResultExpiryTooSoon: - return "expiry too soon" - - case ResultDuplicateToAccepted: - return "accepting duplicate payment to accepted invoice" - - case ResultDuplicateToSettled: - return "accepting duplicate payment to settled invoice" - - case ResultAccepted: - return "accepted" - - case ResultSettled: - return "settled" - - case ResultCanceled: - return "canceled" - - case ResultInvoiceNotOpen: - return "invoice no longer open" - - case ResultPartialAccepted: - return "partial payment accepted" - - case ResultMppInProgress: - return "mpp reception in progress" - - case ResultMppTimeout: - return "mpp timeout" - - case ResultAddressMismatch: - return "payment address mismatch" - - case ResultHtlcSetTotalMismatch: - return "htlc total amt doesn't match set total" - - case ResultHtlcSetTotalTooLow: - return "set total too low for invoice" - - case ResultHtlcSetOverpayment: - return "mpp is overpaying set total" - - case ResultKeySendError: - return "invalid keysend parameters" - - case ResultInvoiceNotFound: - return "invoice not found" - - default: - return "unknown" - } -} - // invoiceUpdateCtx is an object that describes the context for the invoice // update to be carried out. type invoiceUpdateCtx struct { @@ -187,16 +29,17 @@ func (i *invoiceUpdateCtx) log(s string) { } // failRes is a helper function which creates a failure resolution with -// the information contained in the invoiceUpdateCtx and the outcome provided. -func (i invoiceUpdateCtx) failRes(outcome ResolutionResult) *HtlcFailResolution { +// the information contained in the invoiceUpdateCtx and the fail resolution +// result provided. +func (i invoiceUpdateCtx) failRes(outcome FailResolutionResult) *HtlcFailResolution { return NewFailResolution(i.circuitKey, i.currentHeight, outcome) } // settleRes is a helper function which creates a settle resolution with // the information contained in the invoiceUpdateCtx and the preimage and -// outcome provided. +// the settle resolution result provided. func (i invoiceUpdateCtx) settleRes(preimage lntypes.Preimage, - outcome ResolutionResult) *HtlcSettleResolution { + outcome SettleResolutionResult) *HtlcSettleResolution { return NewSettleResolution( preimage, i.circuitKey, i.currentHeight, outcome, @@ -204,8 +47,9 @@ func (i invoiceUpdateCtx) settleRes(preimage lntypes.Preimage, } // acceptRes is a helper function which creates an accept resolution with -// the information contained in the invoiceUpdateCtx and the outcome provided. -func (i invoiceUpdateCtx) acceptRes(outcome ResolutionResult) *htlcAcceptResolution { +// the information contained in the invoiceUpdateCtx and the accept resolution +// result provided. +func (i invoiceUpdateCtx) acceptRes(outcome acceptResolutionResult) *htlcAcceptResolution { return newAcceptResolution(i.circuitKey, outcome) } @@ -223,7 +67,7 @@ func updateInvoice(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( return nil, ctx.failRes(ResultReplayToCanceled), nil case channeldb.HtlcStateAccepted: - return nil, ctx.acceptRes(ResultReplayToAccepted), nil + return nil, ctx.acceptRes(resultReplayToAccepted), nil case channeldb.HtlcStateSettled: return nil, ctx.settleRes( @@ -328,7 +172,7 @@ func updateMpp(ctx *invoiceUpdateCtx, // If the invoice cannot be settled yet, only record the htlc. setComplete := newSetTotal == ctx.mpp.TotalMsat() if !setComplete { - return &update, ctx.acceptRes(ResultPartialAccepted), nil + return &update, ctx.acceptRes(resultPartialAccepted), nil } // Check to see if we can settle or this is an hold invoice and @@ -338,7 +182,7 @@ func updateMpp(ctx *invoiceUpdateCtx, update.State = &channeldb.InvoiceStateUpdateDesc{ NewState: channeldb.ContractAccepted, } - return &update, ctx.acceptRes(ResultAccepted), nil + return &update, ctx.acceptRes(resultAccepted), nil } update.State = &channeldb.InvoiceStateUpdateDesc{ @@ -411,7 +255,7 @@ func updateLegacy(ctx *invoiceUpdateCtx, // We do accept or settle the HTLC. switch inv.State { case channeldb.ContractAccepted: - return &update, ctx.acceptRes(ResultDuplicateToAccepted), nil + return &update, ctx.acceptRes(resultDuplicateToAccepted), nil case channeldb.ContractSettled: return &update, ctx.settleRes( @@ -427,7 +271,7 @@ func updateLegacy(ctx *invoiceUpdateCtx, NewState: channeldb.ContractAccepted, } - return &update, ctx.acceptRes(ResultAccepted), nil + return &update, ctx.acceptRes(resultAccepted), nil } update.State = &channeldb.InvoiceStateUpdateDesc{ From bdd9411bbdc90b8b30cd47fd7f226a753c5e27fd Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 6 Feb 2020 19:35:16 +0200 Subject: [PATCH 055/562] htlcswitch: rename FailureDetail to OutgoingFailure Rename FailureDetail in a separate commit so that a FailureDetail interface can be introduced in the following commit. OutgoingFailureOnionDecode is renamed to OutgoingFailureDecodeError to specifically indicate that we could not decode the wire failure that our payment experienced. --- htlcswitch/failure.go | 14 ++++----- htlcswitch/failure_detail.go | 58 ++++++++++++++++++------------------ htlcswitch/link.go | 4 +-- htlcswitch/switch.go | 14 ++++----- htlcswitch/switch_test.go | 6 ++-- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/htlcswitch/failure.go b/htlcswitch/failure.go index 35d78590b9..c4ef73c5c6 100644 --- a/htlcswitch/failure.go +++ b/htlcswitch/failure.go @@ -34,8 +34,8 @@ type LinkError struct { // node. msg lnwire.FailureMessage - // FailureDetail enriches the wire error with additional information. - FailureDetail + // OutgoingFailure enriches the wire error with additional information. + OutgoingFailure } // NewLinkError returns a LinkError with the failure message provided. @@ -48,11 +48,11 @@ func NewLinkError(msg lnwire.FailureMessage) *LinkError { // NewDetailedLinkError returns a link error that enriches a wire message with // a failure detail. func NewDetailedLinkError(msg lnwire.FailureMessage, - detail FailureDetail) *LinkError { + detail OutgoingFailure) *LinkError { return &LinkError{ - msg: msg, - FailureDetail: detail, + msg: msg, + OutgoingFailure: detail, } } @@ -72,11 +72,11 @@ func (l *LinkError) WireMessage() lnwire.FailureMessage { func (l *LinkError) Error() string { // If the link error has no failure detail, return the wire message's // error. - if l.FailureDetail == FailureDetailNone { + if l.OutgoingFailure == OutgoingFailureNone { return l.msg.Error() } - return fmt.Sprintf("%v: %v", l.msg.Error(), l.FailureDetail) + return fmt.Sprintf("%v: %v", l.msg.Error(), l.OutgoingFailure) } // ForwardingError wraps an lnwire.FailureMessage in a struct that also diff --git a/htlcswitch/failure_detail.go b/htlcswitch/failure_detail.go index 976015b8c4..95f43f1182 100644 --- a/htlcswitch/failure_detail.go +++ b/htlcswitch/failure_detail.go @@ -1,63 +1,63 @@ package htlcswitch -// FailureDetail is an enum which is used to enrich failures with -// additional information. -type FailureDetail int +// OutgoingFailure is an enum which is used to enrich failures which occur in +// the switch or on our outgoing link with additional metadata. +type OutgoingFailure int const ( - // FailureDetailNone is returned when the wire message contains + // OutgoingFailureNone is returned when the wire message contains // sufficient information. - FailureDetailNone = iota + OutgoingFailureNone OutgoingFailure = iota - // FailureDetailOnionDecode indicates that we could not decode an - // onion error. - FailureDetailOnionDecode + // OutgoingFailureDecodeError indicates that we could not decode the + // failure reason provided for a failed payment. + OutgoingFailureDecodeError - // FailureDetailLinkNotEligible indicates that a routing attempt was + // OutgoingFailureLinkNotEligible indicates that a routing attempt was // made over a link that is not eligible for routing. - FailureDetailLinkNotEligible + OutgoingFailureLinkNotEligible - // FailureDetailOnChainTimeout indicates that a payment had to be timed - // out on chain before it got past the first hop by us or the remote - // party. - FailureDetailOnChainTimeout + // OutgoingFailureOnChainTimeout indicates that a payment had to be + // timed out on chain before it got past the first hop by us or the + // remote party. + OutgoingFailureOnChainTimeout - // FailureDetailHTLCExceedsMax is returned when a htlc exceeds our + // OutgoingFailureHTLCExceedsMax is returned when a htlc exceeds our // policy's maximum htlc amount. - FailureDetailHTLCExceedsMax + OutgoingFailureHTLCExceedsMax - // FailureDetailInsufficientBalance is returned when we cannot route a + // OutgoingFailureInsufficientBalance is returned when we cannot route a // htlc due to insufficient outgoing capacity. - FailureDetailInsufficientBalance + OutgoingFailureInsufficientBalance - // FailureDetailCircularRoute is returned when an attempt is made + // OutgoingFailureCircularRoute is returned when an attempt is made // to forward a htlc through our node which arrives and leaves on the // same channel. - FailureDetailCircularRoute + OutgoingFailureCircularRoute ) // String returns the string representation of a failure detail. -func (fd FailureDetail) String() string { +func (fd OutgoingFailure) String() string { switch fd { - case FailureDetailNone: + case OutgoingFailureNone: return "no failure detail" - case FailureDetailOnionDecode: - return "could not decode onion" + case OutgoingFailureDecodeError: + return "could not decode wire failure" - case FailureDetailLinkNotEligible: + case OutgoingFailureLinkNotEligible: return "link not eligible" - case FailureDetailOnChainTimeout: + case OutgoingFailureOnChainTimeout: return "payment was resolved on-chain, then canceled back" - case FailureDetailHTLCExceedsMax: + case OutgoingFailureHTLCExceedsMax: return "htlc exceeds maximum policy amount" - case FailureDetailInsufficientBalance: + case OutgoingFailureInsufficientBalance: return "insufficient bandwidth to route htlc" - case FailureDetailCircularRoute: + case OutgoingFailureCircularRoute: return "same incoming and outgoing channel" default: diff --git a/htlcswitch/link.go b/htlcswitch/link.go index dee3c588da..94773f2cf3 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -2284,7 +2284,7 @@ func (l *channelLink) canSendHtlc(policy ForwardingPolicy, return lnwire.NewTemporaryChannelFailure(upd) }, ) - return NewDetailedLinkError(failure, FailureDetailHTLCExceedsMax) + return NewDetailedLinkError(failure, OutgoingFailureHTLCExceedsMax) } // We want to avoid offering an HTLC which will expire in the near @@ -2319,7 +2319,7 @@ func (l *channelLink) canSendHtlc(policy ForwardingPolicy, }, ) return NewDetailedLinkError( - failure, FailureDetailInsufficientBalance, + failure, OutgoingFailureInsufficientBalance, ) } diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 760aadf007..5db9dac550 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -771,7 +771,7 @@ func (s *Switch) handleLocalDispatch(pkt *htlcPacket) error { // will be returned back to the router. return NewDetailedLinkError( lnwire.NewTemporaryChannelFailure(nil), - FailureDetailLinkNotEligible, + OutgoingFailureLinkNotEligible, ) } @@ -919,11 +919,11 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter, // need to apply an update here since it goes // directly to the router. lnwire.NewTemporaryChannelFailure(nil), - FailureDetailOnionDecode, + OutgoingFailureDecodeError, ) log.Errorf("%v: (hash=%v, pid=%d): %v", - linkError.FailureDetail, paymentHash, paymentID, + linkError.OutgoingFailure, paymentHash, paymentID, err) return linkError @@ -939,10 +939,10 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter, case isResolution && htlc.Reason == nil: linkError := NewDetailedLinkError( &lnwire.FailPermanentChannelFailure{}, - FailureDetailOnChainTimeout, + OutgoingFailureOnChainTimeout, ) - log.Info("%v: hash=%v, pid=%d", linkError.FailureDetail, + log.Info("%v: hash=%v, pid=%d", linkError.OutgoingFailure, paymentHash, paymentID) return linkError @@ -1041,7 +1041,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { if !link.EligibleToForward() { failure = NewDetailedLinkError( &lnwire.FailUnknownNextPeer{}, - FailureDetailLinkNotEligible, + OutgoingFailureLinkNotEligible, ) } else { // We'll ensure that the HTLC satisfies the @@ -1217,7 +1217,7 @@ func checkCircularForward(incoming, outgoing lnwire.ShortChannelID, // node, so we do not include a channel update. return NewDetailedLinkError( lnwire.NewTemporaryChannelFailure(nil), - FailureDetailCircularRoute, + OutgoingFailureCircularRoute, ) } diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index 828ef232cd..a098967b6c 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -1348,7 +1348,7 @@ func TestCircularForwards(t *testing.T) { allowCircularPayment: false, expectedErr: NewDetailedLinkError( lnwire.NewTemporaryChannelFailure(nil), - FailureDetailCircularRoute, + OutgoingFailureCircularRoute, ), }, } @@ -1465,7 +1465,7 @@ func TestCheckCircularForward(t *testing.T) { outgoingLink: lnwire.NewShortChanIDFromInt(123), expectedErr: NewDetailedLinkError( lnwire.NewTemporaryChannelFailure(nil), - FailureDetailCircularRoute, + OutgoingFailureCircularRoute, ), }, } @@ -1527,7 +1527,7 @@ func TestSkipIneligibleLinksMultiHopForward(t *testing.T) { eligible1: true, failure1: NewDetailedLinkError( lnwire.NewTemporaryChannelFailure(nil), - FailureDetailInsufficientBalance, + OutgoingFailureInsufficientBalance, ), eligible2: true, failure2: NewLinkError( From 9390d3bbfd2db5706b8a383a06bacf51526f6ed2 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 6 Feb 2020 19:35:16 +0200 Subject: [PATCH 056/562] htlcswitch: replace outgoing failure with interface Add a FailureDetail interface which allows us have different kinds of failures for link errors. This interface will be used to cover failures that occur when on invoice payment, because the errors have already been enumerated in the invoices package. --- htlcswitch/failure.go | 14 +++++++------- htlcswitch/failure_detail.go | 14 ++++++++++++-- htlcswitch/switch.go | 7 ++++--- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/htlcswitch/failure.go b/htlcswitch/failure.go index c4ef73c5c6..9734a2e029 100644 --- a/htlcswitch/failure.go +++ b/htlcswitch/failure.go @@ -34,8 +34,8 @@ type LinkError struct { // node. msg lnwire.FailureMessage - // OutgoingFailure enriches the wire error with additional information. - OutgoingFailure + // FailureDetail enriches the wire error with additional information. + FailureDetail } // NewLinkError returns a LinkError with the failure message provided. @@ -48,11 +48,11 @@ func NewLinkError(msg lnwire.FailureMessage) *LinkError { // NewDetailedLinkError returns a link error that enriches a wire message with // a failure detail. func NewDetailedLinkError(msg lnwire.FailureMessage, - detail OutgoingFailure) *LinkError { + detail FailureDetail) *LinkError { return &LinkError{ - msg: msg, - OutgoingFailure: detail, + msg: msg, + FailureDetail: detail, } } @@ -72,11 +72,11 @@ func (l *LinkError) WireMessage() lnwire.FailureMessage { func (l *LinkError) Error() string { // If the link error has no failure detail, return the wire message's // error. - if l.OutgoingFailure == OutgoingFailureNone { + if l.FailureDetail == nil { return l.msg.Error() } - return fmt.Sprintf("%v: %v", l.msg.Error(), l.OutgoingFailure) + return fmt.Sprintf("%v: %v", l.msg.Error(), l.FailureDetail) } // ForwardingError wraps an lnwire.FailureMessage in a struct that also diff --git a/htlcswitch/failure_detail.go b/htlcswitch/failure_detail.go index 95f43f1182..9c068cebfb 100644 --- a/htlcswitch/failure_detail.go +++ b/htlcswitch/failure_detail.go @@ -1,5 +1,13 @@ package htlcswitch +// FailureDetail is an interface implemented by failures that occur on +// our incoming or outgoing link, or within the switch itself. +type FailureDetail interface { + // FailureString returns the string representation of a failure + // detail. + FailureString() string +} + // OutgoingFailure is an enum which is used to enrich failures which occur in // the switch or on our outgoing link with additional metadata. type OutgoingFailure int @@ -36,8 +44,10 @@ const ( OutgoingFailureCircularRoute ) -// String returns the string representation of a failure detail. -func (fd OutgoingFailure) String() string { +// FailureString returns the string representation of a failure detail. +// +// Note: it is part of the FailureDetail interface. +func (fd OutgoingFailure) FailureString() string { switch fd { case OutgoingFailureNone: return "no failure detail" diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 5db9dac550..7ca56223a0 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -923,8 +923,8 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter, ) log.Errorf("%v: (hash=%v, pid=%d): %v", - linkError.OutgoingFailure, paymentHash, paymentID, - err) + linkError.FailureDetail.FailureString(), + paymentHash, paymentID, err) return linkError } @@ -942,7 +942,8 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter, OutgoingFailureOnChainTimeout, ) - log.Info("%v: hash=%v, pid=%d", linkError.OutgoingFailure, + log.Info("%v: hash=%v, pid=%d", + linkError.FailureDetail.FailureString(), paymentHash, paymentID) return linkError From 74e0d545fe83c3acea95d1eaea4c232d4c5b0951 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 6 Feb 2020 19:35:17 +0200 Subject: [PATCH 057/562] htlcswitch: add linkError field to htlcpacket This commit adds a linkError field to track the value of failures which occur at our node. This field is set when local payments or multi hop htlcs fail in the switch or on our outgoing link. This addition is required for the addition of a htlc notifier which will notify these failures in handleDownstreamPacket. The passing of link error to failAddPacket removes the need for an additional error field, because the link error's failure detail will contain any additional metadata. In the places where the failure detail does not cover all the metadata that was previously supplied by addr err, the error is logged before calling failAddPacket so that this change does not reduce the amount of information we log. --- htlcswitch/failure.go | 2 +- htlcswitch/failure_detail.go | 21 ++++++++++++ htlcswitch/link.go | 32 +++++++++++++++--- htlcswitch/packet.go | 5 +++ htlcswitch/switch.go | 65 +++++++++++++++++++----------------- htlcswitch/switch_test.go | 21 ++++++++---- 6 files changed, 102 insertions(+), 44 deletions(-) diff --git a/htlcswitch/failure.go b/htlcswitch/failure.go index 9734a2e029..373263381f 100644 --- a/htlcswitch/failure.go +++ b/htlcswitch/failure.go @@ -76,7 +76,7 @@ func (l *LinkError) Error() string { return l.msg.Error() } - return fmt.Sprintf("%v: %v", l.msg.Error(), l.FailureDetail) + return l.FailureDetail.FailureString() } // ForwardingError wraps an lnwire.FailureMessage in a struct that also diff --git a/htlcswitch/failure_detail.go b/htlcswitch/failure_detail.go index 9c068cebfb..341688d124 100644 --- a/htlcswitch/failure_detail.go +++ b/htlcswitch/failure_detail.go @@ -42,6 +42,18 @@ const ( // to forward a htlc through our node which arrives and leaves on the // same channel. OutgoingFailureCircularRoute + + // OutgoingFailureIncompleteForward is returned when we cancel an incomplete + // forward. + OutgoingFailureIncompleteForward + + // OutgoingFailureDownstreamHtlcAdd is returned when we fail to add a + // downstream htlc to our outgoing link. + OutgoingFailureDownstreamHtlcAdd + + // OutgoingFailureForwardsDisabled is returned when the switch is + // configured to disallow forwards. + OutgoingFailureForwardsDisabled ) // FailureString returns the string representation of a failure detail. @@ -70,6 +82,15 @@ func (fd OutgoingFailure) FailureString() string { case OutgoingFailureCircularRoute: return "same incoming and outgoing channel" + case OutgoingFailureIncompleteForward: + return "failed after detecting incomplete forward" + + case OutgoingFailureDownstreamHtlcAdd: + return "could not add downstream htlc" + + case OutgoingFailureForwardsDisabled: + return "node configured to disallow forwards" + default: return "unknown failure detail" } diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 94773f2cf3..484d0e07e4 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1314,6 +1314,10 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) { reason lnwire.OpaqueReason ) + // Create a temporary channel failure which we + // will send back to our peer if this is a + // forward, or report to the user if the failed + // payment was locally initiated. failure := l.createFailureWithUpdate( func(upd *lnwire.ChannelUpdate) lnwire.FailureMessage { return lnwire.NewTemporaryChannelFailure( @@ -1322,28 +1326,43 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) { }, ) - // Encrypt the error back to the source unless - // the payment was generated locally. + // If the payment was locally initiated (which + // is indicated by a nil obfuscator), we do + // not need to encrypt it back to the sender. if pkt.obfuscator == nil { var b bytes.Buffer err := lnwire.EncodeFailure(&b, failure, 0) if err != nil { - l.log.Errorf("unable to encode failure: %v", err) + l.log.Errorf("unable to "+ + "encode failure: %v", err) l.mailBox.AckPacket(pkt.inKey()) return } reason = lnwire.OpaqueReason(b.Bytes()) localFailure = true } else { + // If the packet is part of a forward, + // (identified by a non-nil obfuscator) + // we need to encrypt the error back to + // the source. var err error reason, err = pkt.obfuscator.EncryptFirstHop(failure) if err != nil { - l.log.Errorf("unable to obfuscate error: %v", err) + l.log.Errorf("unable to "+ + "obfuscate error: %v", err) l.mailBox.AckPacket(pkt.inKey()) return } } + // Create a link error containing the temporary + // channel failure and a detail which indicates + // the we failed to add the htlc. + linkError := NewDetailedLinkError( + failure, + OutgoingFailureDownstreamHtlcAdd, + ) + failPkt := &htlcPacket{ incomingChanID: pkt.incomingChanID, incomingHTLCID: pkt.incomingHTLCID, @@ -1351,6 +1370,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) { sourceRef: pkt.sourceRef, hasSource: true, localFailure: localFailure, + linkFailure: linkError, htlc: &lnwire.UpdateFailHTLC{ Reason: reason, }, @@ -2461,7 +2481,9 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg, } // Fetch the reason the HTLC was canceled so we can - // continue to propagate it. + // continue to propagate it. This failure originated + // from another node, so the linkFailure field is not + // set on the packet. failPacket := &htlcPacket{ outgoingChanID: l.ShortChanID(), outgoingHTLCID: pd.ParentIndex, diff --git a/htlcswitch/packet.go b/htlcswitch/packet.go index 3e0816e6e1..e0aa752751 100644 --- a/htlcswitch/packet.go +++ b/htlcswitch/packet.go @@ -54,6 +54,11 @@ type htlcPacket struct { // encrypted with any shared secret. localFailure bool + // linkFailure is non-nil for htlcs that fail at our node. This may + // occur for our own payments which fail on the outgoing link, + // or for forwards which fail in the switch or on the outgoing link. + linkFailure *LinkError + // convertedError is set to true if this is an HTLC fail that was // created using an UpdateFailMalformedHTLC from the remote party. If // this is true, then when forwarding this failure packet, we'll need diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 7ca56223a0..f4370635d9 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -45,11 +45,6 @@ var ( // through the switch and is locked into another commitment txn. ErrDuplicateAdd = errors.New("duplicate add HTLC detected") - // ErrIncompleteForward is used when an htlc was already forwarded - // through the switch, but did not get locked into another commitment - // txn. - ErrIncompleteForward = errors.New("incomplete forward detected") - // ErrUnknownErrorDecryptor signals that we were unable to locate the // error decryptor for this payment. This is likely due to restarting // the daemon. @@ -496,9 +491,12 @@ func (s *Switch) forward(packet *htlcPacket) error { } else { failure = lnwire.NewTemporaryChannelFailure(update) } - addErr := ErrIncompleteForward - return s.failAddPacket(packet, failure, addErr) + linkError := NewDetailedLinkError( + failure, OutgoingFailureIncompleteForward, + ) + + return s.failAddPacket(packet, linkError) } packet.circuit = circuit @@ -647,14 +645,14 @@ func (s *Switch) ForwardPackets(linkQuit chan struct{}, } else { failure = lnwire.NewTemporaryChannelFailure(update) } + linkError := NewDetailedLinkError( + failure, OutgoingFailureIncompleteForward, + ) for _, packet := range failedPackets { - addErr := errors.New("failing packet after " + - "detecting incomplete forward") - // We don't handle the error here since this method // always returns an error. - s.failAddPacket(packet, failure, addErr) + _ = s.failAddPacket(packet, linkError) } } @@ -979,10 +977,12 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { // Check if the node is set to reject all onward HTLCs and also make // sure that HTLC is not from the source node. if s.cfg.RejectHTLC && packet.incomingChanID != hop.Source { - failure := &lnwire.FailChannelDisabled{} - addErr := fmt.Errorf("unable to forward any htlcs") + failure := NewDetailedLinkError( + &lnwire.FailChannelDisabled{}, + OutgoingFailureForwardsDisabled, + ) - return s.failAddPacket(packet, failure, addErr) + return s.failAddPacket(packet, failure) } if packet.incomingChanID == hop.Source { @@ -1002,9 +1002,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { s.cfg.AllowCircularRoute, htlc.PaymentHash, ) if linkErr != nil { - return s.failAddPacket( - packet, linkErr.WireMessage(), linkErr, - ) + return s.failAddPacket(packet, linkErr) } s.indexMtx.RLock() @@ -1012,14 +1010,17 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { if err != nil { s.indexMtx.RUnlock() + log.Debugf("unable to find link with "+ + "destination %v", packet.outgoingChanID) + // If packet was forwarded from another channel link // than we should notify this link that some error // occurred. - failure := &lnwire.FailUnknownNextPeer{} - addErr := fmt.Errorf("unable to find link with "+ - "destination %v", packet.outgoingChanID) + linkError := NewLinkError( + &lnwire.FailUnknownNextPeer{}, + ) - return s.failAddPacket(packet, failure, addErr) + return s.failAddPacket(packet, linkError) } targetPeerKey := targetLink.Peer().PubKey() interfaceLinks, _ := s.getLinks(targetPeerKey) @@ -1088,12 +1089,12 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { })) } - addErr := fmt.Errorf("incoming HTLC(%x) violated "+ + log.Tracef("incoming HTLC(%x) violated "+ "target outgoing link (id=%v) policy: %v", htlc.PaymentHash[:], packet.outgoingChanID, linkErr) - return s.failAddPacket(packet, linkErr.WireMessage(), addErr) + return s.failAddPacket(packet, linkErr) } // Send the packet to the destination channel link which @@ -1225,13 +1226,11 @@ func checkCircularForward(incoming, outgoing lnwire.ShortChannelID, // failAddPacket encrypts a fail packet back to an add packet's source. // The ciphertext will be derived from the failure message proivded by context. // This method returns the failErr if all other steps complete successfully. -func (s *Switch) failAddPacket(packet *htlcPacket, - failure lnwire.FailureMessage, failErr error) error { - +func (s *Switch) failAddPacket(packet *htlcPacket, failure *LinkError) error { // Encrypt the failure so that the sender will be able to read the error // message. Since we failed this packet, we use EncryptFirstHop to // obfuscate the failure for their eyes only. - reason, err := packet.obfuscator.EncryptFirstHop(failure) + reason, err := packet.obfuscator.EncryptFirstHop(failure.WireMessage()) if err != nil { err := fmt.Errorf("unable to obfuscate "+ "error: %v", err) @@ -1239,13 +1238,14 @@ func (s *Switch) failAddPacket(packet *htlcPacket, return err } - log.Error(failErr) + log.Error(failure.Error()) failPkt := &htlcPacket{ sourceRef: packet.sourceRef, incomingChanID: packet.incomingChanID, incomingHTLCID: packet.incomingHTLCID, circuit: packet.circuit, + linkFailure: failure, htlc: &lnwire.UpdateFailHTLC{ Reason: reason, }, @@ -1261,7 +1261,7 @@ func (s *Switch) failAddPacket(packet *htlcPacket, return err } - return failErr + return failure } // closeCircuit accepts a settle or fail htlc and the associated htlc packet and @@ -1869,8 +1869,11 @@ func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) { // commitment state, so we'll forward this to the switch so the // backwards undo can continue. case lnwallet.Fail: - // Fetch the reason the HTLC was canceled so we can - // continue to propagate it. + // Fetch the reason the HTLC was canceled so + // we can continue to propagate it. This + // failure originated from another node, so + // the linkFailure field is not set on this + // packet. failPacket := &htlcPacket{ outgoingChanID: fwdPkg.Source, outgoingHTLCID: pd.ParentIndex, diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index a098967b6c..adc196499f 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -211,10 +211,13 @@ func TestSwitchSendPending(t *testing.T) { // Send the ADD packet, this should not be forwarded out to the link // since there are no eligible links. err = s.forward(packet) - expErr := fmt.Sprintf("unable to find link with destination %v", - aliceChanID) - if err != nil && err.Error() != expErr { - t.Fatalf("expected forward failure: %v", err) + linkErr, ok := err.(*LinkError) + if !ok { + t.Fatalf("expected link error, got: %T", err) + } + if linkErr.WireMessage().Code() != lnwire.CodeUnknownNextPeer { + t.Fatalf("expected fail unknown next peer, got: %T", + linkErr.WireMessage().Code()) } // No message should be sent, since the packet was failed. @@ -1070,9 +1073,13 @@ func TestSwitchForwardFailAfterHalfAdd(t *testing.T) { // Resend the failed htlc, it should be returned to alice since the // switch will detect that it has been half added previously. err = s2.forward(ogPacket) - if err != ErrIncompleteForward { - t.Fatal("unexpected error when reforwarding a "+ - "failed packet", err) + linkErr, ok := err.(*LinkError) + if !ok { + t.Fatalf("expected link error, got: %T", err) + } + if linkErr.FailureDetail != OutgoingFailureIncompleteForward { + t.Fatalf("expected incomplete forward, got: %v", + linkErr.FailureDetail) } // After detecting an incomplete forward, the fail packet should have From 1ad395ec3ff8293f516279490433d60d541988ee Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 6 Feb 2020 19:35:17 +0200 Subject: [PATCH 058/562] htlcswitch: add failure details to incoming failures This commit adds LinkErrors with failure details to htlcs which fail on our incoming link. This change is made with the intention of notifying detailed htlc failure reasons in sendHTLCError. The FailureDetail interface is implemented on FailureResolutionResults so that they can directly be used to enrich LinkErrors. sendHtlcError is updated to take a LinkError in preparation for the addition of a htlcnotifier which will notify the detail of the error. --- htlcswitch/link.go | 34 +++++++++++++++++++++++----------- invoices/resolution_result.go | 6 ++++-- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 484d0e07e4..80b90f4832 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1220,8 +1220,8 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution, failure := getResolutionFailure(res, htlc.pd.Amount) l.sendHTLCError( - htlc.pd.HtlcIndex, failure, htlc.obfuscator, - htlc.pd.SourceRef, + htlc.pd.HtlcIndex, failure, + htlc.obfuscator, htlc.pd.SourceRef, ) return nil @@ -1236,21 +1236,25 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution, // getResolutionFailure returns the wire message that a htlc resolution should // be failed with. func getResolutionFailure(resolution *invoices.HtlcFailResolution, - amount lnwire.MilliSatoshi) lnwire.FailureMessage { + amount lnwire.MilliSatoshi) *LinkError { // If the resolution has been resolved as part of a MPP timeout, // we need to fail the htlc with lnwire.FailMppTimeout. if resolution.Outcome == invoices.ResultMppTimeout { - return &lnwire.FailMPPTimeout{} + return NewDetailedLinkError( + &lnwire.FailMPPTimeout{}, resolution.Outcome, + ) } // If the htlc is not a MPP timeout, we fail it with // FailIncorrectDetails. This error is sent for invoice payment // failures such as underpayment/ expiry too soon and hodl invoices // (which return FailIncorrectDetails to avoid leaking information). - return lnwire.NewFailIncorrectDetails( + incorrectDetails := lnwire.NewFailIncorrectDetails( amount, uint32(resolution.AcceptHeight), ) + + return NewDetailedLinkError(incorrectDetails, resolution.Outcome) } // randomFeeUpdateTimeout returns a random timeout between the bounds defined @@ -2650,9 +2654,10 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, // for TLV payloads that also supports injecting invalid // payloads. Deferring this non-trival effort till a // later date + failure := lnwire.NewInvalidOnionPayload(failedType, 0) l.sendHTLCError( pd.HtlcIndex, - lnwire.NewInvalidOnionPayload(failedType, 0), + NewLinkError(failure), obfuscator, pd.SourceRef, ) @@ -2766,7 +2771,10 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, ) l.sendHTLCError( - pd.HtlcIndex, failure, obfuscator, pd.SourceRef, + pd.HtlcIndex, + NewLinkError(failure), + obfuscator, + pd.SourceRef, ) continue } @@ -2849,7 +2857,9 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor, "value: expected %v, got %v", pd.RHash, pd.Amount, fwdInfo.AmountToForward) - failure := lnwire.NewFinalIncorrectHtlcAmount(pd.Amount) + failure := NewLinkError( + lnwire.NewFinalIncorrectHtlcAmount(pd.Amount), + ) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef) return nil @@ -2862,7 +2872,9 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor, "time-lock: expected %v, got %v", pd.RHash[:], pd.Timeout, fwdInfo.OutgoingCTLV) - failure := lnwire.NewFinalIncorrectCltvExpiry(pd.Timeout) + failure := NewLinkError( + lnwire.NewFinalIncorrectCltvExpiry(pd.Timeout), + ) l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef) return nil @@ -2979,10 +2991,10 @@ func (l *channelLink) handleBatchFwdErrs(errChan chan error) { // sendHTLCError functions cancels HTLC and send cancel message back to the // peer from which HTLC was received. -func (l *channelLink) sendHTLCError(htlcIndex uint64, failure lnwire.FailureMessage, +func (l *channelLink) sendHTLCError(htlcIndex uint64, failure *LinkError, e hop.ErrorEncrypter, sourceRef *channeldb.AddRef) { - reason, err := e.EncryptFirstHop(failure) + reason, err := e.EncryptFirstHop(failure.WireMessage()) if err != nil { l.log.Errorf("unable to obfuscate error: %v", err) return diff --git a/invoices/resolution_result.go b/invoices/resolution_result.go index 3952d11a57..41da902a61 100644 --- a/invoices/resolution_result.go +++ b/invoices/resolution_result.go @@ -107,8 +107,10 @@ const ( ResultMppInProgress ) -// String returns a string representation of the result. -func (f FailResolutionResult) String() string { +// FailureString returns a string representation of the result. +// +// Note: it is part of the FailureDetail interface. +func (f FailResolutionResult) FailureString() string { switch f { case resultInvalidFailure: return "invalid failure result" From c5c2fc27f90f9a9de853fc090fc4ce13aa48bfec Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 5 Feb 2020 15:39:31 +0200 Subject: [PATCH 059/562] channeldb/test: replace test channel boilerplate createTestChannel This change replaces test channel creation boilerplate with a createTestChannel function which can be customized using functional options. --- channeldb/channel_test.go | 346 ++++++++++++++++++++++---------------- channeldb/db_test.go | 59 ++----- 2 files changed, 210 insertions(+), 195 deletions(-) diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index 891f0d824c..927c380c38 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -71,6 +71,17 @@ var ( wireSig, _ = lnwire.NewSigFromSignature(testSig) testClock = clock.NewTestClock(testNow) + + // defaultPendingHeight is the default height at which we set + // channels to pending. + defaultPendingHeight = 100 + + // defaultAddr is the default address that we mark test channels pending + // with. + defaultAddr = &net.TCPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: 18555, + } ) // makeTestDB creates a new instance of the ChannelDB for testing purposes. A @@ -98,21 +109,141 @@ func makeTestDB() (*DB, func(), error) { return cdb, cleanUp, nil } -func createTestChannelState(cdb *DB) (*OpenChannel, error) { +// testChannelParams is a struct which details the specifics of how a channel +// should be created. +type testChannelParams struct { + // channel is the channel that will be written to disk. + channel *OpenChannel + + // addr is the address that the channel will be synced pending with. + addr *net.TCPAddr + + // pendingHeight is the height that the channel should be recorded as + // pending. + pendingHeight uint32 + + // openChannel is set to true if the channel should be fully marked as + // open if this is false, the channel will be left in pending state. + openChannel bool +} + +// testChannelOption is a functional option which can be used to alter the +// default channel that is creates for testing. +type testChannelOption func(params *testChannelParams) + +// pendingHeightOption is an option which can be used to set the height the +// channel is marked as pending at. +func pendingHeightOption(height uint32) testChannelOption { + return func(params *testChannelParams) { + params.pendingHeight = height + } +} + +// openChannelOption is an option which can be used to create a test channel +// that is open. +func openChannelOption() testChannelOption { + return func(params *testChannelParams) { + params.openChannel = true + } +} + +// localHtlcsOption is an option which allows setting of htlcs on the local +// commitment. +func localHtlcsOption(htlcs []HTLC) testChannelOption { + return func(params *testChannelParams) { + params.channel.LocalCommitment.Htlcs = htlcs + } +} + +// remoteHtlcsOption is an option which allows setting of htlcs on the remote +// commitment. +func remoteHtlcsOption(htlcs []HTLC) testChannelOption { + return func(params *testChannelParams) { + params.channel.RemoteCommitment.Htlcs = htlcs + } +} + +// localShutdownOption is an option which sets the local upfront shutdown +// script for the channel. +func localShutdownOption(addr lnwire.DeliveryAddress) testChannelOption { + return func(params *testChannelParams) { + params.channel.LocalShutdownScript = addr + } +} + +// remoteShutdownOption is an option which sets the remote upfront shutdown +// script for the channel. +func remoteShutdownOption(addr lnwire.DeliveryAddress) testChannelOption { + return func(params *testChannelParams) { + params.channel.RemoteShutdownScript = addr + } +} + +// fundingPointOption is an option which sets the funding outpoint of the +// channel. +func fundingPointOption(chanPoint wire.OutPoint) testChannelOption { + return func(params *testChannelParams) { + params.channel.FundingOutpoint = chanPoint + } +} + +// createTestChannel writes a test channel to the database. It takes a set of +// functional options which can be used to overwrite the default of creating +// a pending channel that was broadcast at height 100. +func createTestChannel(t *testing.T, cdb *DB, + opts ...testChannelOption) *OpenChannel { + + // Create a default set of parameters. + params := &testChannelParams{ + channel: createTestChannelState(t, cdb), + addr: defaultAddr, + openChannel: false, + pendingHeight: uint32(defaultPendingHeight), + } + + // Apply all functional options to the test channel params. + for _, o := range opts { + o(params) + } + + // Mark the channel as pending. + err := params.channel.SyncPending(params.addr, params.pendingHeight) + if err != nil { + t.Fatalf("unable to save and serialize channel "+ + "state: %v", err) + } + + // If the parameters do not specify that we should open the channel + // fully, we return the pending channel. + if !params.openChannel { + return params.channel + } + + // Mark the channel as open with the short channel id provided. + err = params.channel.MarkAsOpen(params.channel.ShortChannelID) + if err != nil { + t.Fatalf("unable to mark channel open: %v", err) + } + + return params.channel +} + +func createTestChannelState(t *testing.T, cdb *DB) *OpenChannel { // Simulate 1000 channel updates. producer, err := shachain.NewRevocationProducerFromBytes(key[:]) if err != nil { - return nil, err + t.Fatalf("could not get producer: %v", err) } store := shachain.NewRevocationStore() for i := 0; i < 1; i++ { preImage, err := producer.AtIndex(uint64(i)) if err != nil { - return nil, err + t.Fatalf("could not get "+ + "preimage: %v", err) } if err := store.AddNextEntry(preImage); err != nil { - return nil, err + t.Fatalf("could not add entry: %v", err) } } @@ -228,7 +359,7 @@ func createTestChannelState(cdb *DB) (*OpenChannel, error) { Db: cdb, Packager: NewChannelPackager(chanID), FundingTxn: testTx, - }, nil + } } func TestOpenChannelPutGetDelete(t *testing.T) { @@ -240,15 +371,10 @@ func TestOpenChannelPutGetDelete(t *testing.T) { } defer cleanUp() - // Create the test channel state, then add an additional fake HTLC - // before syncing to disk. - state, err := createTestChannelState(cdb) - if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } - state.LocalCommitment.Htlcs = []HTLC{ - { - Signature: testSig.Serialize(), + // Create the test channel state, with additional htlcs on the local + // and remote commitment. + localHtlcs := []HTLC{ + {Signature: testSig.Serialize(), Incoming: true, Amt: 10, RHash: key, @@ -256,7 +382,8 @@ func TestOpenChannelPutGetDelete(t *testing.T) { OnionBlob: []byte("onionblob"), }, } - state.RemoteCommitment.Htlcs = []HTLC{ + + remoteHtlcs := []HTLC{ { Signature: testSig.Serialize(), Incoming: false, @@ -267,13 +394,11 @@ func TestOpenChannelPutGetDelete(t *testing.T) { }, } - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18556, - } - if err := state.SyncPending(addr, 101); err != nil { - t.Fatalf("unable to save and serialize channel state: %v", err) - } + state := createTestChannel( + t, cdb, + remoteHtlcsOption(remoteHtlcs), + localHtlcsOption(localHtlcs), + ) openChannels, err := cdb.FetchOpenChannels(state.IdentityPub) if err != nil { @@ -360,36 +485,28 @@ func TestOptionalShutdown(t *testing.T) { tests := []struct { name string - modifyChannel func(channel *OpenChannel) - expectedLocal lnwire.DeliveryAddress - expectedRemote lnwire.DeliveryAddress + localShutdown lnwire.DeliveryAddress + remoteShutdown lnwire.DeliveryAddress }{ { - name: "no shutdown scripts", - modifyChannel: func(channel *OpenChannel) {}, + name: "no shutdown scripts", + localShutdown: nil, + remoteShutdown: nil, }, { - name: "local shutdown script", - modifyChannel: func(channel *OpenChannel) { - channel.LocalShutdownScript = local - }, - expectedLocal: local, + name: "local shutdown script", + localShutdown: local, + remoteShutdown: nil, }, { - name: "remote shutdown script", - modifyChannel: func(channel *OpenChannel) { - channel.RemoteShutdownScript = remote - }, - expectedRemote: remote, + name: "remote shutdown script", + localShutdown: nil, + remoteShutdown: remote, }, { - name: "both scripts set", - modifyChannel: func(channel *OpenChannel) { - channel.LocalShutdownScript = local - channel.RemoteShutdownScript = remote - }, - expectedLocal: local, - expectedRemote: remote, + name: "both scripts set", + localShutdown: local, + remoteShutdown: remote, }, } @@ -403,40 +520,40 @@ func TestOptionalShutdown(t *testing.T) { } defer cleanUp() - // Create the test channel state, then add an additional fake HTLC - // before syncing to disk. - state, err := createTestChannelState(cdb) + // Create a channel with upfront scripts set as + // specified in the test. + state := createTestChannel( + t, cdb, + localShutdownOption(test.localShutdown), + remoteShutdownOption(test.remoteShutdown), + ) + + openChannels, err := cdb.FetchOpenChannels( + state.IdentityPub, + ) if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } - - test.modifyChannel(state) - - // Write channels to Db. - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18556, - } - if err := state.SyncPending(addr, 101); err != nil { - t.Fatalf("unable to save and serialize channel state: %v", err) - } - - openChannels, err := cdb.FetchOpenChannels(state.IdentityPub) - if err != nil { - t.Fatalf("unable to fetch open channel: %v", err) + t.Fatalf("unable to fetch open"+ + " channel: %v", err) } if len(openChannels) != 1 { - t.Fatalf("Expected one channel open, got: %v", len(openChannels)) + t.Fatalf("Expected one channel open,"+ + " got: %v", len(openChannels)) } - if !bytes.Equal(openChannels[0].LocalShutdownScript, test.expectedLocal) { - t.Fatalf("Expected local: %x, got: %x", test.expectedLocal, + if !bytes.Equal(openChannels[0].LocalShutdownScript, + test.localShutdown) { + + t.Fatalf("Expected local: %x, got: %x", + test.localShutdown, openChannels[0].LocalShutdownScript) } - if !bytes.Equal(openChannels[0].RemoteShutdownScript, test.expectedRemote) { - t.Fatalf("Expected remote: %x, got: %x", test.expectedRemote, + if !bytes.Equal(openChannels[0].RemoteShutdownScript, + test.remoteShutdown) { + + t.Fatalf("Expected remote: %x, got: %x", + test.remoteShutdown, openChannels[0].RemoteShutdownScript) } }) @@ -462,18 +579,7 @@ func TestChannelStateTransition(t *testing.T) { // First create a minimal channel, then perform a full sync in order to // persist the data. - channel, err := createTestChannelState(cdb) - if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } - - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18556, - } - if err := channel.SyncPending(addr, 101); err != nil { - t.Fatalf("unable to save and serialize channel state: %v", err) - } + channel := createTestChannel(t, cdb) // Add some HTLCs which were added during this new state transition. // Half of the HTLCs are incoming, while the other half are outgoing. @@ -776,21 +882,9 @@ func TestFetchPendingChannels(t *testing.T) { } defer cleanUp() - // Create first test channel state - state, err := createTestChannelState(cdb) - if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } - - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18555, - } - + // Create a pending channel that was broadcast at height 99. const broadcastHeight = 99 - if err := state.SyncPending(addr, broadcastHeight); err != nil { - t.Fatalf("unable to save and serialize channel state: %v", err) - } + createTestChannel(t, cdb, pendingHeightOption(broadcastHeight)) pendingChannels, err := cdb.FetchPendingChannels() if err != nil { @@ -867,35 +961,8 @@ func TestFetchClosedChannels(t *testing.T) { } defer cleanUp() - // First create a test channel, that we'll be closing within this pull - // request. - state, err := createTestChannelState(cdb) - if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } - - // Next sync the channel to disk, marking it as being in a pending open - // state. - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18555, - } - const broadcastHeight = 99 - if err := state.SyncPending(addr, broadcastHeight); err != nil { - t.Fatalf("unable to save and serialize channel state: %v", err) - } - - // Next, simulate the confirmation of the channel by marking it as - // pending within the database. - chanOpenLoc := lnwire.ShortChannelID{ - BlockHeight: 5, - TxIndex: 10, - TxPosition: 15, - } - err = state.MarkAsOpen(chanOpenLoc) - if err != nil { - t.Fatalf("unable to mark channel as open: %v", err) - } + // Create an open channel in the database. + state := createTestChannel(t, cdb, openChannelOption()) // Next, close the channel by including a close channel summary in the // database. @@ -975,7 +1042,6 @@ func TestFetchWaitingCloseChannels(t *testing.T) { const numChannels = 2 const broadcastHeight = 99 - addr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 18555} // We'll start by creating two channels within our test database. One of // them will have their funding transaction confirmed on-chain, while @@ -988,15 +1054,11 @@ func TestFetchWaitingCloseChannels(t *testing.T) { channels := make([]*OpenChannel, numChannels) for i := 0; i < numChannels; i++ { - channel, err := createTestChannelState(db) - if err != nil { - t.Fatalf("unable to create channel: %v", err) - } - err = channel.SyncPending(addr, broadcastHeight) - if err != nil { - t.Fatalf("unable to sync channel: %v", err) - } - channels[i] = channel + // Create a pending channel in the database at the broadcast + // height. + channels[i] = createTestChannel( + t, db, pendingHeightOption(broadcastHeight), + ) } // We'll only confirm the first one. @@ -1106,21 +1168,7 @@ func TestRefreshShortChanID(t *testing.T) { defer cleanUp() // First create a test channel. - state, err := createTestChannelState(cdb) - if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } - - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18555, - } - - // Mark the channel as pending within the channeldb. - const broadcastHeight = 99 - if err := state.SyncPending(addr, broadcastHeight); err != nil { - t.Fatalf("unable to save and serialize channel state: %v", err) - } + state := createTestChannel(t, cdb) // Next, locate the pending channel with the database. pendingChannels, err := cdb.FetchPendingChannels() diff --git a/channeldb/db_test.go b/channeldb/db_test.go index b9b1189be8..c1f5250770 100644 --- a/channeldb/db_test.go +++ b/channeldb/db_test.go @@ -100,10 +100,7 @@ func TestFetchClosedChannelForID(t *testing.T) { // Create the test channel state, that we will mutate the index of the // funding point. - state, err := createTestChannelState(cdb) - if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } + state := createTestChannelState(t, cdb) // Now run through the number of channels, and modify the outpoint index // to create new channel IDs. @@ -111,14 +108,12 @@ func TestFetchClosedChannelForID(t *testing.T) { // Save the open channel to disk. state.FundingOutpoint.Index = i - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18556, - } - if err := state.SyncPending(addr, 101); err != nil { - t.Fatalf("unable to save and serialize channel "+ - "state: %v", err) - } + // Write the channel to disk in a pending state. + createTestChannel( + t, cdb, + fundingPointOption(state.FundingOutpoint), + openChannelOption(), + ) // Close the channel. To make sure we retrieve the correct // summary later, we make them differ in the SettledBalance. @@ -235,26 +230,8 @@ func TestFetchChannel(t *testing.T) { } defer cleanUp() - // Create the test channel state that we'll sync to the database - // shortly. - channelState, err := createTestChannelState(cdb) - if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } - - // Mark the channel as pending, then immediately mark it as open to it - // can be fully visible. - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18555, - } - if err := channelState.SyncPending(addr, 9); err != nil { - t.Fatalf("unable to save and serialize channel state: %v", err) - } - err = channelState.MarkAsOpen(lnwire.NewShortChanIDFromInt(99)) - if err != nil { - t.Fatalf("unable to mark channel open: %v", err) - } + // Create an open channel. + channelState := createTestChannel(t, cdb, openChannelOption()) // Next, attempt to fetch the channel by its chan point. dbChannel, err := cdb.FetchChannel(channelState.FundingOutpoint) @@ -271,7 +248,7 @@ func TestFetchChannel(t *testing.T) { // If we attempt to query for a non-exist ante channel, then we should // get an error. - channelState2, err := createTestChannelState(cdb) + channelState2 := createTestChannelState(t, cdb) if err != nil { t.Fatalf("unable to create channel state: %v", err) } @@ -491,19 +468,9 @@ func TestAbandonChannel(t *testing.T) { t.Fatalf("removing non-existent channel should have failed") } - // We'll now create a new channel to abandon shortly. - chanState, err := createTestChannelState(cdb) - if err != nil { - t.Fatalf("unable to create channel state: %v", err) - } - addr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18555, - } - err = chanState.SyncPending(addr, 10) - if err != nil { - t.Fatalf("unable to sync pending channel: %v", err) - } + // We'll now create a new channel in a pending state to abandon + // shortly. + chanState := createTestChannel(t, cdb) // We should now be able to abandon the channel without any errors. closeHeight := uint32(11) From ed81c882395af051e3d4e781c811ab2b0e085a18 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 6 Feb 2020 10:21:12 +0200 Subject: [PATCH 060/562] channeldb: replace fetch channels booleans with optional filters This changes replaces the pending an waiting booleans in fetchChannels with optional filters which can be more flexibly used. This change allows filtering of channels without having to reason about the matrix of possible boolean combinations. A test is added to ensure that the combinations of these filters act as expected. --- channeldb/channel_test.go | 7 ++ channeldb/db.go | 119 ++++++++++++----------- channeldb/db_test.go | 193 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+), 53 deletions(-) diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index 927c380c38..cb29b52131 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -187,6 +187,13 @@ func fundingPointOption(chanPoint wire.OutPoint) testChannelOption { } } +// channelIDOption is an option which sets the short channel ID of the channel. +var channelIDOption = func(chanID lnwire.ShortChannelID) testChannelOption { + return func(params *testChannelParams) { + params.channel.ShortChannelID = chanID + } +} + // createTestChannel writes a test channel to the database. It takes a set of // functional options which can be used to overwrite the default of creating // a pending channel that was broadcast at height 100. diff --git a/channeldb/db.go b/channeldb/db.go index c9410bfbb5..696f3f0086 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -556,42 +556,28 @@ func (d *DB) FetchChannel(chanPoint wire.OutPoint) (*OpenChannel, error) { // within the database, including pending open, fully open and channels waiting // for a closing transaction to confirm. func (d *DB) FetchAllChannels() ([]*OpenChannel, error) { - var channels []*OpenChannel - - // TODO(halseth): fetch all in one db tx. - openChannels, err := d.FetchAllOpenChannels() - if err != nil { - return nil, err - } - channels = append(channels, openChannels...) - - pendingChannels, err := d.FetchPendingChannels() - if err != nil { - return nil, err - } - channels = append(channels, pendingChannels...) - - waitingClose, err := d.FetchWaitingCloseChannels() - if err != nil { - return nil, err - } - channels = append(channels, waitingClose...) - - return channels, nil + return fetchChannels(d) } // FetchAllOpenChannels will return all channels that have the funding // transaction confirmed, and is not waiting for a closing transaction to be // confirmed. func (d *DB) FetchAllOpenChannels() ([]*OpenChannel, error) { - return fetchChannels(d, false, false) + return fetchChannels( + d, + pendingChannelFilter(false), + waitingCloseFilter(false), + ) } // FetchPendingChannels will return channels that have completed the process of // generating and broadcasting funding transactions, but whose funding // transactions have yet to be confirmed on the blockchain. func (d *DB) FetchPendingChannels() ([]*OpenChannel, error) { - return fetchChannels(d, true, false) + return fetchChannels(d, + pendingChannelFilter(true), + waitingCloseFilter(false), + ) } // FetchWaitingCloseChannels will return all channels that have been opened, @@ -599,25 +585,49 @@ func (d *DB) FetchPendingChannels() ([]*OpenChannel, error) { // // NOTE: This includes channels that are also pending to be opened. func (d *DB) FetchWaitingCloseChannels() ([]*OpenChannel, error) { - waitingClose, err := fetchChannels(d, false, true) - if err != nil { - return nil, err - } - pendingWaitingClose, err := fetchChannels(d, true, true) - if err != nil { - return nil, err + return fetchChannels( + d, waitingCloseFilter(true), + ) +} + +// fetchChannelsFilter applies a filter to channels retrieved in fetchchannels. +// A set of filters can be combined to filter across multiple dimensions. +type fetchChannelsFilter func(channel *OpenChannel) bool + +// pendingChannelFilter returns a filter based on whether channels are pending +// (ie, their funding transaction still needs to confirm). If pending is false, +// channels with confirmed funding transactions are returned. +func pendingChannelFilter(pending bool) fetchChannelsFilter { + return func(channel *OpenChannel) bool { + return channel.IsPending == pending } +} - return append(waitingClose, pendingWaitingClose...), nil +// waitingCloseFilter returns a filter which filters channels based on whether +// they are awaiting the confirmation of their closing transaction. If waiting +// close is true, channels that have had their closing tx broadcast are +// included. If it is false, channels that are not awaiting confirmation of +// their close transaction are returned. +func waitingCloseFilter(waitingClose bool) fetchChannelsFilter { + return func(channel *OpenChannel) bool { + // If the channel is in any other state than Default, + // then it means it is waiting to be closed. + channelWaitingClose := + channel.ChanStatus() != ChanStatusDefault + + // Include the channel if it matches the value for + // waiting close that we are filtering on. + return channelWaitingClose == waitingClose + } } // fetchChannels attempts to retrieve channels currently stored in the -// database. The pending parameter determines whether only pending channels -// will be returned, or only open channels will be returned. The waitingClose -// parameter determines whether only channels waiting for a closing transaction -// to be confirmed should be returned. If no active channels exist within the -// network, then ErrNoActiveChannels is returned. -func fetchChannels(d *DB, pending, waitingClose bool) ([]*OpenChannel, error) { +// database. It takes a set of filters which are applied to each channel to +// obtain a set of channels with the desired set of properties. Only channels +// which have a true value returned for *all* of the filters will be returned. +// If no filters are provided, every channel in the open channels bucket will +// be returned. +func fetchChannels(d *DB, filters ...fetchChannelsFilter) ([]*OpenChannel, error) { var channels []*OpenChannel err := d.View(func(tx *bbolt.Tx) error { @@ -667,24 +677,27 @@ func fetchChannels(d *DB, pending, waitingClose bool) ([]*OpenChannel, error) { "node_key=%x: %v", chainHash[:], k, err) } for _, channel := range nodeChans { - if channel.IsPending != pending { - continue + // includeChannel indicates whether the channel + // meets the criteria specified by our filters. + includeChannel := true + + // Run through each filter and check whether the + // channel should be included. + for _, f := range filters { + // If the channel fails the filter, set + // includeChannel to false and don't bother + // checking the remaining filters. + if !f(channel) { + includeChannel = false + break + } } - // If the channel is in any other state - // than Default, then it means it is - // waiting to be closed. - channelWaitingClose := - channel.ChanStatus() != ChanStatusDefault - - // Only include it if we requested - // channels with the same waitingClose - // status. - if channelWaitingClose != waitingClose { - continue + // If the channel passed every filter, include it in + // our set of channels. + if includeChannel { + channels = append(channels, channel) } - - channels = append(channels, channel) } return nil }) diff --git a/channeldb/db_test.go b/channeldb/db_test.go index c1f5250770..935a287ced 100644 --- a/channeldb/db_test.go +++ b/channeldb/db_test.go @@ -500,3 +500,196 @@ func TestAbandonChannel(t *testing.T) { t.Fatalf("unable to abandon channel: %v", err) } } + +// TestFetchChannels tests the filtering of open channels in fetchChannels. +// It tests the case where no filters are provided (which is equivalent to +// FetchAllOpenChannels) and every combination of pending and waiting close. +func TestFetchChannels(t *testing.T) { + // Create static channel IDs for each kind of channel retrieved by + // fetchChannels so that the expected channel IDs can be set in tests. + var ( + // Pending is a channel that is pending open, and has not had + // a close initiated. + pendingChan = lnwire.NewShortChanIDFromInt(1) + + // pendingWaitingClose is a channel that is pending open and + // has has its closing transaction broadcast. + pendingWaitingChan = lnwire.NewShortChanIDFromInt(2) + + // openChan is a channel that has confirmed on chain. + openChan = lnwire.NewShortChanIDFromInt(3) + + // openWaitingChan is a channel that has confirmed on chain, + // and it waiting for its close transaction to confirm. + openWaitingChan = lnwire.NewShortChanIDFromInt(4) + ) + + tests := []struct { + name string + filters []fetchChannelsFilter + expectedChannels map[lnwire.ShortChannelID]bool + }{ + { + name: "get all channels", + filters: []fetchChannelsFilter{}, + expectedChannels: map[lnwire.ShortChannelID]bool{ + pendingChan: true, + pendingWaitingChan: true, + openChan: true, + openWaitingChan: true, + }, + }, + { + name: "pending channels", + filters: []fetchChannelsFilter{ + pendingChannelFilter(true), + }, + expectedChannels: map[lnwire.ShortChannelID]bool{ + pendingChan: true, + pendingWaitingChan: true, + }, + }, + { + name: "open channels", + filters: []fetchChannelsFilter{ + pendingChannelFilter(false), + }, + expectedChannels: map[lnwire.ShortChannelID]bool{ + openChan: true, + openWaitingChan: true, + }, + }, + { + name: "waiting close channels", + filters: []fetchChannelsFilter{ + waitingCloseFilter(true), + }, + expectedChannels: map[lnwire.ShortChannelID]bool{ + pendingWaitingChan: true, + openWaitingChan: true, + }, + }, + { + name: "not waiting close channels", + filters: []fetchChannelsFilter{ + waitingCloseFilter(false), + }, + expectedChannels: map[lnwire.ShortChannelID]bool{ + pendingChan: true, + openChan: true, + }, + }, + { + name: "pending waiting", + filters: []fetchChannelsFilter{ + pendingChannelFilter(true), + waitingCloseFilter(true), + }, + expectedChannels: map[lnwire.ShortChannelID]bool{ + pendingWaitingChan: true, + }, + }, + { + name: "pending, not waiting", + filters: []fetchChannelsFilter{ + pendingChannelFilter(true), + waitingCloseFilter(false), + }, + expectedChannels: map[lnwire.ShortChannelID]bool{ + pendingChan: true, + }, + }, + { + name: "open waiting", + filters: []fetchChannelsFilter{ + pendingChannelFilter(false), + waitingCloseFilter(true), + }, + expectedChannels: map[lnwire.ShortChannelID]bool{ + openWaitingChan: true, + }, + }, + { + name: "open, not waiting", + filters: []fetchChannelsFilter{ + pendingChannelFilter(false), + waitingCloseFilter(false), + }, + expectedChannels: map[lnwire.ShortChannelID]bool{ + openChan: true, + }, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + cdb, cleanUp, err := makeTestDB() + if err != nil { + t.Fatalf("unable to make test "+ + "database: %v", err) + } + defer cleanUp() + + // Create a pending channel that is not awaiting close. + createTestChannel( + t, cdb, channelIDOption(pendingChan), + ) + + // Create a pending channel which has has been marked as + // broadcast, indicating that its closing transaction is + // waiting to confirm. + pendingClosing := createTestChannel( + t, cdb, + channelIDOption(pendingWaitingChan), + ) + + err = pendingClosing.MarkCoopBroadcasted(nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + // Create a open channel that is not awaiting close. + createTestChannel( + t, cdb, + channelIDOption(openChan), + openChannelOption(), + ) + + // Create a open channel which has has been marked as + // broadcast, indicating that its closing transaction is + // waiting to confirm. + openClosing := createTestChannel( + t, cdb, + channelIDOption(openWaitingChan), + openChannelOption(), + ) + err = openClosing.MarkCoopBroadcasted(nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + channels, err := fetchChannels(cdb, test.filters...) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if len(channels) != len(test.expectedChannels) { + t.Fatalf("expected: %v channels, "+ + "got: %v", len(test.expectedChannels), + len(channels)) + } + + for _, ch := range channels { + _, ok := test.expectedChannels[ch.ShortChannelID] + if !ok { + t.Fatalf("fetch channels unexpected "+ + "channel: %v", ch.ShortChannelID) + } + } + }) + } +} From 1528ef8b8588c84026c07fdb2dcf0d2735c4c605 Mon Sep 17 00:00:00 2001 From: yancy Date: Fri, 7 Feb 2020 08:26:32 -0600 Subject: [PATCH 061/562] docker: add terminal symbol to docker readme example commands --- docker/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/README.md b/docker/README.md index ebce1990b1..78e0319a58 100644 --- a/docker/README.md +++ b/docker/README.md @@ -64,8 +64,8 @@ bitcoin into. $ export NETWORK="simnet" # Create persistent volumes for alice and bob. -docker volume create simnet_lnd_alice -docker volume create simnet_lnd_bob +$ docker volume create simnet_lnd_alice +$ docker volume create simnet_lnd_bob # Run the "Alice" container and log into it: $ docker-compose run -d --name alice --volume simnet_lnd_alice:/root/.lnd lnd From 90008386d8630fba0cac1d881bf7dc0f41470526 Mon Sep 17 00:00:00 2001 From: Yaacov Akiba Slama Date: Sun, 9 Feb 2020 10:55:50 +0200 Subject: [PATCH 062/562] Copy InputIndex into the underlying SignDescriptor struct When the InputIndex is not 0, the index is not currently copied into the underlying SignDescriptor structure and the siganture generated is not valid. --- lnrpc/signrpc/signer_server.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lnrpc/signrpc/signer_server.go b/lnrpc/signrpc/signer_server.go index b3da2f9386..e51fe5d00e 100644 --- a/lnrpc/signrpc/signer_server.go +++ b/lnrpc/signrpc/signer_server.go @@ -373,8 +373,9 @@ func (s *Server) ComputeInputScript(ctx context.Context, Value: signDesc.Output.Value, PkScript: signDesc.Output.PkScript, }, - HashType: txscript.SigHashType(signDesc.Sighash), - SigHashes: sigHashCache, + HashType: txscript.SigHashType(signDesc.Sighash), + SigHashes: sigHashCache, + InputIndex: int(signDesc.InputIndex), }) } From 88eae6eafe8ad54945a9501537244cf4cb6b3de1 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 10 Feb 2020 13:52:19 +0100 Subject: [PATCH 063/562] lnwallet: fix invalid value use in restoreUpdate Updates were always restored with the same log index. This could cause a crash when the logs were compacted and possibly other problems elsewhere. Extended unit test to cover the crash scenario. --- lnwallet/channel.go | 2 +- lnwallet/channel_test.go | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index bc472598ab..131d863279 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -1064,7 +1064,7 @@ func (u *updateLog) appendUpdate(pd *PaymentDescriptor) { // also added to index accordingly. This function differs from appendUpdate in // that it won't increment the log index counter. func (u *updateLog) restoreUpdate(pd *PaymentDescriptor) { - u.updateIndex[u.logIndex] = u.PushBack(pd) + u.updateIndex[pd.LogIndex] = u.PushBack(pd) } // appendHtlc appends a new HTLC offer to the tip of the update log. The entry diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 03ac925fcb..1e871ab68c 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -3146,7 +3146,7 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) { } // Bob signs the commitment he owes. - _, bobHtlcSigs, _, err := bobChannel.SignNextCommitment() + bobCommit, bobHtlcSigs, _, err := bobChannel.SignNextCommitment() if err != nil { t.Fatalf("unable to sign commitment: %v", err) } @@ -3155,6 +3155,20 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) { if len(bobHtlcSigs) != 0 { t.Fatalf("no htlcs expected, but got %v", len(bobHtlcSigs)) } + + // Get Alice to revoke and trigger Bob to compact his logs. + err = aliceChannel.ReceiveNewCommitment(bobCommit, bobHtlcSigs) + if err != nil { + t.Fatal(err) + } + aliceRevoke, _, err := aliceChannel.RevokeCurrentCommitment() + if err != nil { + t.Fatal(err) + } + _, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevoke) + if err != nil { + t.Fatal(err) + } } // TestChanSyncOweRevocation tests that if Bob restarts (and then Alice) before From a8ed1b342aac6f2393277e93af1634b5bd79d2d9 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 27 Jan 2020 13:19:08 +0100 Subject: [PATCH 064/562] routing: remove pathfinding db tx Pathfinding is never used with an externally supplied bbolt transaction. --- routing/pathfind.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/routing/pathfind.go b/routing/pathfind.go index 23bc1f9e9f..77686337f5 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -271,10 +271,6 @@ func edgeWeight(lockedAmt lnwire.MilliSatoshi, fee lnwire.MilliSatoshi, // graphParams wraps the set of graph parameters passed to findPath. type graphParams struct { - // tx can be set to an existing db transaction. If not set, a new - // transaction will be started. - tx *bbolt.Tx - // graph is the ChannelGraph to be used during path finding. graph *channeldb.ChannelGraph @@ -425,14 +421,12 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, } self := selfNode.PubKeyBytes - tx := g.tx - if tx == nil { - tx, err = g.graph.Database().Begin(false) - if err != nil { - return nil, err - } - defer tx.Rollback() + // Get a db transaction to execute the graph queries in. + tx, err := g.graph.Database().Begin(false) + if err != nil { + return nil, err } + defer tx.Rollback() // If no destination features are provided, we will load what features // we have for the target node from our graph. From 99ebe50f4cec41d5fce05c4dbcf95a25584ed222 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 11 Feb 2020 13:23:34 +0100 Subject: [PATCH 065/562] contractcourt/chainwatcher: add missing chanpoint log --- contractcourt/chain_watcher.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contractcourt/chain_watcher.go b/contractcourt/chain_watcher.go index e9eb8e396e..c08916d010 100644 --- a/contractcourt/chain_watcher.go +++ b/contractcourt/chain_watcher.go @@ -607,8 +607,9 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) { c.cfg.chanState.FundingOutpoint) } else { - log.Infof("ChannelPoint(%v) is tweakless, " + - "moving to sweep directly on chain") + log.Infof("ChannelPoint(%v) is tweakless, "+ + "moving to sweep directly on chain", + c.cfg.chanState.FundingOutpoint) } // Since we don't have the commitment stored for this From 06bdeb56e23b6c838efcf7a3eb862d16586f554f Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 27 Jan 2020 12:33:53 +0100 Subject: [PATCH 066/562] routing: add graph interface --- routing/graph.go | 104 ++++++++++++++++++++++- routing/pathfind.go | 163 +++++++++++++++++------------------- routing/router.go | 26 ++++-- routing/unified_policies.go | 9 +- 4 files changed, 204 insertions(+), 98 deletions(-) diff --git a/routing/graph.go b/routing/graph.go index f3dfa121da..14eca17861 100644 --- a/routing/graph.go +++ b/routing/graph.go @@ -1,4 +1,104 @@ package routing -// TODO(roasbeef): abstract out graph to interface -// * add in-memory version of graph for tests +import ( + "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" +) + +// routingGraph is an abstract interface that provides information about nodes +// and edges to pathfinding. +type routingGraph interface { + // forEachNodeChannel calls the callback for every channel of the given node. + forEachNodeChannel(nodePub route.Vertex, + cb func(*channeldb.ChannelEdgeInfo, *channeldb.ChannelEdgePolicy, + *channeldb.ChannelEdgePolicy) error) error + + // sourceNode returns the source node of the graph. + sourceNode() route.Vertex + + // fetchNodeFeatures returns the features of the given node. + fetchNodeFeatures(nodePub route.Vertex) (*lnwire.FeatureVector, error) +} + +// dbRoutingTx is a routingGraph implementation that retrieves from the +// database. +type dbRoutingTx struct { + graph *channeldb.ChannelGraph + tx *bbolt.Tx + source route.Vertex +} + +// newDbRoutingTx instantiates a new db-connected routing graph. It implictly +// instantiates a new read transaction. +func newDbRoutingTx(graph *channeldb.ChannelGraph) (*dbRoutingTx, error) { + sourceNode, err := graph.SourceNode() + if err != nil { + return nil, err + } + + tx, err := graph.Database().Begin(false) + if err != nil { + return nil, err + } + + return &dbRoutingTx{ + graph: graph, + tx: tx, + source: sourceNode.PubKeyBytes, + }, nil +} + +// close closes the underlying db transaction. +func (g *dbRoutingTx) close() error { + return g.tx.Rollback() +} + +// forEachNodeChannel calls the callback for every channel of the given node. +// +// NOTE: Part of the routingGraph interface. +func (g *dbRoutingTx) forEachNodeChannel(nodePub route.Vertex, + cb func(*channeldb.ChannelEdgeInfo, *channeldb.ChannelEdgePolicy, + *channeldb.ChannelEdgePolicy) error) error { + + txCb := func(_ *bbolt.Tx, info *channeldb.ChannelEdgeInfo, + p1, p2 *channeldb.ChannelEdgePolicy) error { + + return cb(info, p1, p2) + } + + return g.graph.ForEachNodeChannel(g.tx, nodePub[:], txCb) +} + +// sourceNode returns the source node of the graph. +// +// NOTE: Part of the routingGraph interface. +func (g *dbRoutingTx) sourceNode() route.Vertex { + return g.source +} + +// fetchNodeFeatures returns the features of the given node. If the node is +// unknown, assume no additional features are supported. +// +// NOTE: Part of the routingGraph interface. +func (g *dbRoutingTx) fetchNodeFeatures(nodePub route.Vertex) ( + *lnwire.FeatureVector, error) { + + targetNode, err := g.graph.FetchLightningNode(g.tx, nodePub) + switch err { + + // If the node exists and has features, return them directly. + case nil: + return targetNode.Features, nil + + // If we couldn't find a node announcement, populate a blank feature + // vector. + case channeldb.ErrGraphNodeNotFound: + return lnwire.EmptyFeatureVector(), nil + + // Otherwise bubble the error up. + default: + return nil, err + } +} diff --git a/routing/pathfind.go b/routing/pathfind.go index 77686337f5..f2ea782d9b 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -7,7 +7,6 @@ import ( "math" "time" - "github.com/coreos/bbolt" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/feature" @@ -346,10 +345,11 @@ type PathFindingConfig struct { // getMaxOutgoingAmt returns the maximum available balance in any of the // channels of the given node. func getMaxOutgoingAmt(node route.Vertex, outgoingChan *uint64, - g *graphParams, tx *bbolt.Tx) (lnwire.MilliSatoshi, error) { + bandwidthHints map[uint64]lnwire.MilliSatoshi, + g routingGraph) (lnwire.MilliSatoshi, error) { var max lnwire.MilliSatoshi - cb := func(_ *bbolt.Tx, edgeInfo *channeldb.ChannelEdgeInfo, outEdge, + cb := func(edgeInfo *channeldb.ChannelEdgeInfo, outEdge, _ *channeldb.ChannelEdgePolicy) error { if outEdge == nil { @@ -363,7 +363,7 @@ func getMaxOutgoingAmt(node route.Vertex, outgoingChan *uint64, return nil } - bandwidth, ok := g.bandwidthHints[chanID] + bandwidth, ok := bandwidthHints[chanID] // If the bandwidth is not available for whatever reason, don't // fail the pathfinding early. @@ -380,28 +380,54 @@ func getMaxOutgoingAmt(node route.Vertex, outgoingChan *uint64, } // Iterate over all channels of the to node. - err := g.graph.ForEachNodeChannel(tx, node[:], cb) + err := g.forEachNodeChannel(node, cb) if err != nil { return 0, err } return max, err } -// findPath attempts to find a path from the source node within the -// ChannelGraph to the target node that's capable of supporting a payment of -// `amt` value. The current approach implemented is modified version of -// Dijkstra's algorithm to find a single shortest path between the source node -// and the destination. The distance metric used for edges is related to the -// time-lock+fee costs along a particular edge. If a path is found, this -// function returns a slice of ChannelHop structs which encoded the chosen path -// from the target to the source. The search is performed backwards from -// destination node back to source. This is to properly accumulate fees -// that need to be paid along the path and accurately check the amount -// to forward at every node against the available bandwidth. +// findPath attempts to find a path from the source node within the ChannelGraph +// to the target node that's capable of supporting a payment of `amt` value. The +// current approach implemented is modified version of Dijkstra's algorithm to +// find a single shortest path between the source node and the destination. The +// distance metric used for edges is related to the time-lock+fee costs along a +// particular edge. If a path is found, this function returns a slice of +// ChannelHop structs which encoded the chosen path from the target to the +// source. The search is performed backwards from destination node back to +// source. This is to properly accumulate fees that need to be paid along the +// path and accurately check the amount to forward at every node against the +// available bandwidth. func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, source, target route.Vertex, amt lnwire.MilliSatoshi, finalHtlcExpiry int32) ( []*channeldb.ChannelEdgePolicy, error) { + routingTx, err := newDbRoutingTx(g.graph) + if err != nil { + return nil, err + } + defer func() { + err := routingTx.close() + if err != nil { + log.Errorf("Error closing db tx: %v", err) + } + }() + + return findPathInternal( + g.additionalEdges, g.bandwidthHints, routingTx, r, cfg, source, + target, amt, finalHtlcExpiry, + ) +} + +// findPathInternal is the internal implementation of findPath. +func findPathInternal( + additionalEdges map[route.Vertex][]*channeldb.ChannelEdgePolicy, + bandwidthHints map[uint64]lnwire.MilliSatoshi, + graph routingGraph, + r *RestrictParams, cfg *PathFindingConfig, + source, target route.Vertex, amt lnwire.MilliSatoshi, finalHtlcExpiry int32) ( + []*channeldb.ChannelEdgePolicy, error) { + // Pathfinding can be a significant portion of the total payment // latency, especially on low-powered devices. Log several metrics to // aid in the analysis performance problems in this area. @@ -414,45 +440,20 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, "time=%v", nodesVisited, edgesExpanded, timeElapsed) }() - // Get source node outside of the pathfinding tx, to prevent a deadlock. - selfNode, err := g.graph.SourceNode() - if err != nil { - return nil, err - } - self := selfNode.PubKeyBytes - - // Get a db transaction to execute the graph queries in. - tx, err := g.graph.Database().Begin(false) - if err != nil { - return nil, err - } - defer tx.Rollback() - // If no destination features are provided, we will load what features // we have for the target node from our graph. features := r.DestFeatures if features == nil { - targetNode, err := g.graph.FetchLightningNode(tx, target) - switch { - - // If the node exists and has features, use them directly. - case err == nil: - features = targetNode.Features - - // If an error other than the node not existing is hit, abort. - case err != channeldb.ErrGraphNodeNotFound: + var err error + features, err = graph.fetchNodeFeatures(target) + if err != nil { return nil, err - - // Otherwise, we couldn't find a node announcement, populate a - // blank feature vector. - default: - features = lnwire.EmptyFeatureVector() } } // Ensure that the destination's features don't include unknown // required features. - err = feature.ValidateRequired(features) + err := feature.ValidateRequired(features) if err != nil { return nil, err } @@ -485,8 +486,12 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, // If we are routing from ourselves, check that we have enough local // balance available. + self := graph.sourceNode() + if source == self { - max, err := getMaxOutgoingAmt(self, r.OutgoingChannelID, g, tx) + max, err := getMaxOutgoingAmt( + self, r.OutgoingChannelID, bandwidthHints, graph, + ) if err != nil { return nil, err } @@ -504,7 +509,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, distance := make(map[route.Vertex]*nodeWithDist, estimatedNodeCount) additionalEdgesWithSrc := make(map[route.Vertex][]*edgePolicyWithSource) - for vertex, outgoingEdgePolicies := range g.additionalEdges { + for vertex, outgoingEdgePolicies := range additionalEdges { // Build reverse lookup to find incoming edges. Needed because // search is taken place from target to source. for _, outgoingEdgePolicy := range outgoingEdgePolicies { @@ -746,45 +751,35 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, // Check cache for features of the fromNode. fromFeatures, ok := featureCache[node] - if !ok { - targetNode, err := g.graph.FetchLightningNode(tx, node) - switch { - - // If the node exists and has valid features, use them. - case err == nil: - nodeFeatures := targetNode.Features - - // Don't route through nodes that contain - // unknown required features. - err = feature.ValidateRequired(nodeFeatures) - if err != nil { - break - } - - // Don't route through nodes that don't properly - // set all transitive feature dependencies. - err = feature.ValidateDeps(nodeFeatures) - if err != nil { - break - } - - fromFeatures = nodeFeatures - - // If an error other than the node not existing is hit, - // abort. - case err != channeldb.ErrGraphNodeNotFound: - return nil, err + if ok { + return fromFeatures, nil + } - // Otherwise, we couldn't find a node announcement, - // populate a blank feature vector. - default: - fromFeatures = lnwire.EmptyFeatureVector() - } + // Fetch node features fresh from the graph. + fromFeatures, err := graph.fetchNodeFeatures(node) + if err != nil { + return nil, err + } - // Update cache. - featureCache[node] = fromFeatures + // Don't route through nodes that contain unknown required + // features and mark as nil in the cache. + err = feature.ValidateRequired(fromFeatures) + if err != nil { + featureCache[node] = nil + return nil, nil } + // Don't route through nodes that don't properly set all + // transitive feature dependencies and mark as nil in the cache. + err = feature.ValidateDeps(fromFeatures) + if err != nil { + featureCache[node] = nil + return nil, nil + } + + // Update cache. + featureCache[node] = fromFeatures + return fromFeatures, nil } @@ -797,7 +792,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, // Create unified policies for all incoming connections. u := newUnifiedPolicies(self, pivot, r.OutgoingChannelID) - err := u.addGraphPolicies(g.graph, tx) + err := u.addGraphPolicies(graph) if err != nil { return nil, err } @@ -828,7 +823,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, } policy := unifiedPolicy.getPolicy( - amtToSend, g.bandwidthHints, + amtToSend, bandwidthHints, ) if policy == nil { diff --git a/routing/router.go b/routing/router.go index a7c24ba4e2..e42ce7a0e8 100644 --- a/routing/router.go +++ b/routing/router.go @@ -2311,6 +2311,13 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi, return nil, err } + // Fetch the current block height outside the routing transaction, to + // prevent the rpc call blocking the database. + _, height, err := r.cfg.Chain.GetBestBlock() + if err != nil { + return nil, err + } + // Allocate a list that will contain the unified policies for this // route. edges := make([]*unifiedPolicy, len(hops)) @@ -2328,6 +2335,18 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi, runningAmt = *amt } + // Open a transaction to execute the graph queries in. + routingTx, err := newDbRoutingTx(r.cfg.Graph) + if err != nil { + return nil, err + } + defer func() { + err := routingTx.close() + if err != nil { + log.Errorf("Error closing db tx: %v", err) + } + }() + // Traverse hops backwards to accumulate fees in the running amounts. source := r.selfNode.PubKeyBytes for i := len(hops) - 1; i >= 0; i-- { @@ -2346,7 +2365,7 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi, // known in the graph. u := newUnifiedPolicies(source, toNode, outgoingChan) - err := u.addGraphPolicies(r.cfg.Graph, nil) + err := u.addGraphPolicies(routingTx) if err != nil { return nil, err } @@ -2414,11 +2433,6 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi, } // Build and return the final route. - _, height, err := r.cfg.Chain.GetBestBlock() - if err != nil { - return nil, err - } - return newRoute( source, pathEdges, uint32(height), finalHopParams{ diff --git a/routing/unified_policies.go b/routing/unified_policies.go index 81e646c297..3759175a6e 100644 --- a/routing/unified_policies.go +++ b/routing/unified_policies.go @@ -2,7 +2,6 @@ package routing import ( "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -69,10 +68,8 @@ func (u *unifiedPolicies) addPolicy(fromNode route.Vertex, // addGraphPolicies adds all policies that are known for the toNode in the // graph. -func (u *unifiedPolicies) addGraphPolicies(g *channeldb.ChannelGraph, - tx *bbolt.Tx) error { - - cb := func(_ *bbolt.Tx, edgeInfo *channeldb.ChannelEdgeInfo, _, +func (u *unifiedPolicies) addGraphPolicies(g routingGraph) error { + cb := func(edgeInfo *channeldb.ChannelEdgeInfo, _, inEdge *channeldb.ChannelEdgePolicy) error { // If there is no edge policy for this candidate node, skip. @@ -95,7 +92,7 @@ func (u *unifiedPolicies) addGraphPolicies(g *channeldb.ChannelGraph, } // Iterate over all channels of the to node. - return g.ForEachNodeChannel(tx, u.toNode[:], cb) + return g.forEachNodeChannel(u.toNode, cb) } // unifiedPolicyEdge is the individual channel data that is kept inside an From 29476ec6a3bdf3512c6c6f0c50eda37ac2825de8 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 27 Jan 2020 15:40:33 +0100 Subject: [PATCH 067/562] routing/test: test probability extrapolation Adds an integrated routing test of probability extrapolation for untried channels. The larger part of this commit is mock code to simulate the Lightning Network. The difference between this test and the existing pathfinding tests, is that this test focuses on the feedback loop from result interpretation via mission control updates and probability estimation back to pathfinding. Improvements like probability extrapolation were previously only validated by reasoning, while this setup makes it possible to assert the improvement in a test and guard it for the future. --- routing/integrated_routing_context_test.go | 194 +++++++++++++++ routing/integrated_routing_test.go | 57 +++++ routing/mock_graph_test.go | 265 +++++++++++++++++++++ 3 files changed, 516 insertions(+) create mode 100644 routing/integrated_routing_context_test.go create mode 100644 routing/integrated_routing_test.go create mode 100644 routing/mock_graph_test.go diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go new file mode 100644 index 0000000000..eb59473e6a --- /dev/null +++ b/routing/integrated_routing_context_test.go @@ -0,0 +1,194 @@ +package routing + +import ( + "io/ioutil" + "os" + "testing" + "time" + + "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" +) + +// integratedRoutingContext defines the context in which integrated routing +// tests run. +type integratedRoutingContext struct { + graph *mockGraph + t *testing.T + + source *mockNode + target *mockNode + + amt lnwire.MilliSatoshi + finalExpiry int32 + + mcCfg MissionControlConfig + pathFindingCfg PathFindingConfig +} + +// newIntegratedRoutingContext instantiates a new integrated routing test +// context with a source and a target node. +func newIntegratedRoutingContext(t *testing.T) *integratedRoutingContext { + // Instantiate a mock graph. + source := newMockNode() + target := newMockNode() + + graph := newMockGraph(t) + graph.addNode(source) + graph.addNode(target) + graph.source = source + + // Initiate the test context with a set of default configuration values. + // We don't use the lnd defaults here, because otherwise changing the + // defaults would break the unit tests. The actual values picked aren't + // critical to excite certain behavior, but do need to be aligned with + // the test case assertions. + ctx := integratedRoutingContext{ + t: t, + graph: graph, + amt: 100000, + finalExpiry: 40, + + mcCfg: MissionControlConfig{ + PenaltyHalfLife: 30 * time.Minute, + AprioriHopProbability: 0.6, + AprioriWeight: 0.5, + SelfNode: source.pubkey, + }, + + pathFindingCfg: PathFindingConfig{ + PaymentAttemptPenalty: 1000, + }, + + source: source, + target: target, + } + + return &ctx +} + +// testPayment launches a test payment and asserts that it is completed after +// the expected number of attempts. +func (c *integratedRoutingContext) testPayment(expectedNofAttempts int) { + var nextPid uint64 + + // Create temporary database for mission control. + file, err := ioutil.TempFile("", "*.db") + if err != nil { + c.t.Fatal(err) + } + + dbPath := file.Name() + defer os.Remove(dbPath) + + db, err := bbolt.Open(dbPath, 0600, nil) + if err != nil { + c.t.Fatal(err) + } + defer db.Close() + + // Instantiate a new mission control with the current configuration + // values. + mc, err := NewMissionControl(db, &c.mcCfg) + if err != nil { + c.t.Fatal(err) + } + + // Instruct pathfinding to use mission control as a probabiltiy source. + restrictParams := RestrictParams{ + ProbabilitySource: mc.GetProbability, + FeeLimit: lnwire.MaxMilliSatoshi, + } + + // Now the payment control loop starts. It will keep trying routes until + // the payment succeeds. + for { + // Create bandwidth hints based on local channel balances. + bandwidthHints := map[uint64]lnwire.MilliSatoshi{} + for _, ch := range c.graph.nodes[c.source.pubkey].channels { + bandwidthHints[ch.id] = ch.balance + } + + // Find a route. + path, err := findPathInternal( + nil, bandwidthHints, c.graph, + &restrictParams, + &c.pathFindingCfg, + c.source.pubkey, c.target.pubkey, + c.amt, c.finalExpiry, + ) + if err != nil { + c.t.Fatal(err) + } + + finalHop := finalHopParams{ + amt: c.amt, + cltvDelta: uint16(c.finalExpiry), + } + + route, err := newRoute(c.source.pubkey, path, 0, finalHop) + if err != nil { + c.t.Fatal(err) + } + + // Send out the htlc on the mock graph. + pid := nextPid + nextPid++ + htlcResult, err := c.graph.sendHtlc(route) + if err != nil { + c.t.Fatal(err) + } + + // Process the result. + if htlcResult.failure == nil { + err := mc.ReportPaymentSuccess(pid, route) + if err != nil { + c.t.Fatal(err) + } + + // If the payment is successful, the control loop can be + // broken out of. + break + } + + // Failure, update mission control and retry. + c.t.Logf("fail: %v @ %v\n", htlcResult.failure, htlcResult.failureSource) + + finalResult, err := mc.ReportPaymentFail( + pid, route, + getNodeIndex(route, htlcResult.failureSource), + htlcResult.failure, + ) + if err != nil { + c.t.Fatal(err) + } + + if finalResult != nil { + c.t.Logf("final result: %v\n", finalResult) + break + } + } + + c.t.Logf("Payment attempts: %v\n", nextPid) + if expectedNofAttempts != int(nextPid) { + c.t.Fatalf("expected %v attempts, but needed %v", + expectedNofAttempts, nextPid) + } +} + +// getNodeIndex returns the zero-based index of the given node in the route. +func getNodeIndex(route *route.Route, failureSource route.Vertex) *int { + if failureSource == route.SourcePubKey { + idx := 0 + return &idx + } + + for i, h := range route.Hops { + if h.PubKeyBytes == failureSource { + idx := i + 1 + return &idx + } + } + return nil +} diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go new file mode 100644 index 0000000000..19df17a35e --- /dev/null +++ b/routing/integrated_routing_test.go @@ -0,0 +1,57 @@ +package routing + +import ( + "testing" +) + +// TestProbabilityExtrapolation tests that probabilities for tried channels are +// extrapolated to untried channels. This is a way to improve pathfinding +// success by steering away from bad nodes. +func TestProbabilityExtrapolation(t *testing.T) { + ctx := newIntegratedRoutingContext(t) + + // Create the following network of nodes: + // source -> expensiveNode (charges routing fee) -> target + // source -> intermediate1 (free routing) -> intermediate(1-10) (free routing) -> target + g := ctx.graph + + expensiveNode := newMockNode() + expensiveNode.baseFee = 10000 + g.addNode(expensiveNode) + + g.addChannel(ctx.source, expensiveNode, 100000) + g.addChannel(ctx.target, expensiveNode, 100000) + + intermediate1 := newMockNode() + g.addNode(intermediate1) + g.addChannel(ctx.source, intermediate1, 100000) + + for i := 0; i < 10; i++ { + imNode := newMockNode() + g.addNode(imNode) + g.addChannel(imNode, ctx.target, 100000) + g.addChannel(imNode, intermediate1, 100000) + + // The channels from intermediate1 all have insufficient balance. + g.nodes[intermediate1.pubkey].channels[imNode.pubkey].balance = 0 + } + + // It is expected that pathfinding will try to explore the routes via + // intermediate1 first, because those are free. But as failures happen, + // the node probability of intermediate1 will go down in favor of the + // paid route via expensiveNode. + // + // The exact number of attempts required is dependent on mission control + // config. For this test, it would have been enough to only assert that + // we are not trying all routes via intermediate1. However, we do assert + // a specific number of attempts to safe-guard against accidental + // modifications anywhere in the chain of components that is involved in + // this test. + ctx.testPayment(5) + + // If we use a static value for the node probability (no extrapolation + // of data from other channels), all ten bad channels will be tried + // first before switching to the paid channel. + ctx.mcCfg.AprioriWeight = 1 + ctx.testPayment(11) +} diff --git a/routing/mock_graph_test.go b/routing/mock_graph_test.go new file mode 100644 index 0000000000..075a416a1a --- /dev/null +++ b/routing/mock_graph_test.go @@ -0,0 +1,265 @@ +package routing + +import ( + "bytes" + "fmt" + "testing" + + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" +) + +// nextTestPubkey is global variable that is used to deterministically generate +// test keys. +var nextTestPubkey byte + +// createPubkey return a new test pubkey. +func createPubkey() route.Vertex { + pubkey := route.Vertex{nextTestPubkey} + nextTestPubkey++ + return pubkey +} + +// mockChannel holds the channel state of a channel in the mock graph. +type mockChannel struct { + id uint64 + capacity btcutil.Amount + balance lnwire.MilliSatoshi +} + +// mockNode holds a set of mock channels and routing policies for a node in the +// mock graph. +type mockNode struct { + channels map[route.Vertex]*mockChannel + baseFee lnwire.MilliSatoshi + pubkey route.Vertex +} + +// newMockNode instantiates a new mock node with a newly generated pubkey. +func newMockNode() *mockNode { + pubkey := createPubkey() + return &mockNode{ + channels: make(map[route.Vertex]*mockChannel), + pubkey: pubkey, + } +} + +// fwd simulates an htlc forward through this node. If the from parameter is +// nil, this node is considered to be the sender of the payment. The route +// parameter describes the remaining route from this node onwards. If route.next +// is nil, this node is the final hop. +func (m *mockNode) fwd(from *mockNode, route *hop) (htlcResult, error) { + next := route.next + + // Get the incoming channel, if any. + var inChan *mockChannel + if from != nil { + inChan = m.channels[from.pubkey] + } + + // If there is no next node, this is the final node and we can settle the htlc. + if next == nil { + // Update the incoming balance. + inChan.balance += route.amtToFwd + + return htlcResult{}, nil + } + + // Check if the outgoing channel has enough balance. + outChan, ok := m.channels[next.node.pubkey] + if !ok { + return htlcResult{}, + fmt.Errorf("%v: unknown next %v", + m.pubkey, next.node.pubkey) + } + if outChan.balance < route.amtToFwd { + return htlcResult{ + failureSource: m.pubkey, + failure: lnwire.NewTemporaryChannelFailure(nil), + }, nil + } + + // Htlc can be forwarded, update channel balances. + outChan.balance -= route.amtToFwd + if inChan != nil { + inChan.balance += route.amtToFwd + } + + // Recursively forward down the given route. + result, err := next.node.fwd(m, route.next) + if err != nil { + return htlcResult{}, err + } + + // Revert balances when a failure occurs. + if result.failure != nil { + outChan.balance += route.amtToFwd + if inChan != nil { + inChan.balance -= route.amtToFwd + } + } + + return result, nil +} + +// mockGraph contains a set of nodes that together for a mocked graph. +type mockGraph struct { + t *testing.T + nodes map[route.Vertex]*mockNode + nextChanID uint64 + source *mockNode +} + +// newMockGraph instantiates a new mock graph. +func newMockGraph(t *testing.T) *mockGraph { + return &mockGraph{ + nodes: make(map[route.Vertex]*mockNode), + t: t, + } +} + +// addNode adds the given mock node to the network. +func (m *mockGraph) addNode(node *mockNode) { + m.nodes[node.pubkey] = node +} + +// addChannel adds a new channel between two existing nodes on the network. It +// sets the channel balance to 50/50%. +// +// Ignore linter error because addChannel isn't yet called with different +// capacities. +// nolint:unparam +func (m *mockGraph) addChannel(node1, node2 *mockNode, capacity btcutil.Amount) { + id := m.nextChanID + m.nextChanID++ + + m.nodes[node1.pubkey].channels[node2.pubkey] = &mockChannel{ + capacity: capacity, + id: id, + balance: lnwire.NewMSatFromSatoshis(capacity / 2), + } + m.nodes[node2.pubkey].channels[node1.pubkey] = &mockChannel{ + capacity: capacity, + id: id, + balance: lnwire.NewMSatFromSatoshis(capacity / 2), + } +} + +// forEachNodeChannel calls the callback for every channel of the given node. +// +// NOTE: Part of the routingGraph interface. +func (m *mockGraph) forEachNodeChannel(nodePub route.Vertex, + cb func(*channeldb.ChannelEdgeInfo, *channeldb.ChannelEdgePolicy, + *channeldb.ChannelEdgePolicy) error) error { + + // Look up the mock node. + node, ok := m.nodes[nodePub] + if !ok { + return channeldb.ErrGraphNodeNotFound + } + + // Iterate over all of its channels. + for peer, channel := range node.channels { + // Lexicographically sort the pubkeys. + var node1, node2 route.Vertex + if bytes.Compare(nodePub[:], peer[:]) == -1 { + node1, node2 = peer, nodePub + } else { + node1, node2 = nodePub, peer + } + + peerNode := m.nodes[peer] + + // Call the per channel callback. + err := cb( + &channeldb.ChannelEdgeInfo{ + NodeKey1Bytes: node1, + NodeKey2Bytes: node2, + }, + &channeldb.ChannelEdgePolicy{ + ChannelID: channel.id, + Node: &channeldb.LightningNode{ + PubKeyBytes: peer, + Features: lnwire.EmptyFeatureVector(), + }, + FeeBaseMSat: node.baseFee, + }, + &channeldb.ChannelEdgePolicy{ + ChannelID: channel.id, + Node: &channeldb.LightningNode{ + PubKeyBytes: nodePub, + Features: lnwire.EmptyFeatureVector(), + }, + FeeBaseMSat: peerNode.baseFee, + }, + ) + if err != nil { + return err + } + } + return nil +} + +// sourceNode returns the source node of the graph. +// +// NOTE: Part of the routingGraph interface. +func (m *mockGraph) sourceNode() route.Vertex { + return m.source.pubkey +} + +// fetchNodeFeatures returns the features of the given node. +// +// NOTE: Part of the routingGraph interface. +func (m *mockGraph) fetchNodeFeatures(nodePub route.Vertex) ( + *lnwire.FeatureVector, error) { + + return lnwire.EmptyFeatureVector(), nil +} + +// htlcResult describes the resolution of an htlc. If failure is nil, the htlc +// was settled. +type htlcResult struct { + failureSource route.Vertex + failure lnwire.FailureMessage +} + +// hop describes one hop of a route. +type hop struct { + node *mockNode + amtToFwd lnwire.MilliSatoshi + next *hop +} + +// sendHtlc sends out an htlc on the mock network and synchronously returns the +// final resolution of the htlc. +func (m *mockGraph) sendHtlc(route *route.Route) (htlcResult, error) { + var next *hop + + // Convert the route into a structure that is suitable for recursive + // processing. + for i := len(route.Hops) - 1; i >= 0; i-- { + routeHop := route.Hops[i] + node := m.nodes[routeHop.PubKeyBytes] + next = &hop{ + node: node, + next: next, + amtToFwd: routeHop.AmtToForward, + } + } + + // Create the starting hop instance. + source := m.nodes[route.SourcePubKey] + next = &hop{ + node: source, + next: next, + amtToFwd: route.TotalAmount, + } + + // Recursively walk the path and obtain the htlc resolution. + return source.fwd(nil, next) +} + +// Compile-time check for the routingGraph interface. +var _ routingGraph = &mockGraph{} From 69a6107d066508eda6bfe48550817d9c95168c8d Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 4 Feb 2020 14:55:16 +0100 Subject: [PATCH 068/562] sweep: log full parameter struct --- sweep/sweeper.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sweep/sweeper.go b/sweep/sweeper.go index fc65879f66..8a9a38da5f 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -402,10 +402,9 @@ func (s *UtxoSweeper) SweepInput(input input.Input, } log.Infof("Sweep request received: out_point=%v, witness_type=%v, "+ - "time_lock=%v, amount=%v, fee_preference=%v, force=%v", + "time_lock=%v, amount=%v, params=(%v)", input.OutPoint(), input.WitnessType(), input.BlocksToMaturity(), - btcutil.Amount(input.SignDesc().Output.Value), - params.Fee, params.Force) + btcutil.Amount(input.SignDesc().Output.Value), params) sweeperInput := &sweepInputMessage{ input: input, From d3161077498a58940fe2bd084218bcf62fddb38d Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 5 Feb 2020 13:51:48 +0100 Subject: [PATCH 069/562] cert: extract IP and DNS parsing into methods --- cert/selfsigned.go | 72 +++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/cert/selfsigned.go b/cert/selfsigned.go index e428e5eb57..574a37f330 100644 --- a/cert/selfsigned.go +++ b/cert/selfsigned.go @@ -31,31 +31,9 @@ var ( serialNumberLimit = new(big.Int).Lsh(big.NewInt(1), 128) ) -// GenCertPair generates a key/cert pair to the paths provided. The -// auto-generated certificates should *not* be used in production for public -// access as they're self-signed and don't necessarily contain all of the -// desired hostnames for the service. For production/public use, consider a -// real PKI. -// -// This function is adapted from https://github.com/btcsuite/btcd and -// https://github.com/btcsuite/btcutil -func GenCertPair(org, certFile, keyFile string, tlsExtraIPs, - tlsExtraDomains []string, certValidity time.Duration) error { - - now := time.Now() - validUntil := now.Add(certValidity) - - // Check that the certificate validity isn't past the ASN.1 end of time. - if validUntil.After(endOfTime) { - validUntil = endOfTime - } - - // Generate a serial number that's below the serialNumberLimit. - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - return fmt.Errorf("failed to generate serial number: %s", err) - } - +// ipAddresses returns the parserd IP addresses to use when creating the TLS +// certificate. +func ipAddresses(tlsExtraIPs []string) ([]net.IP, error) { // Collect the host's IP addresses, including loopback, in a slice. ipAddresses := []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")} @@ -72,7 +50,7 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs, // Add all the interface IPs that aren't already in the slice. addrs, err := net.InterfaceAddrs() if err != nil { - return err + return nil, err } for _, a := range addrs { ipAddr, _, err := net.ParseCIDR(a.String()) @@ -89,6 +67,12 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs, } } + return ipAddresses, nil +} + +// dnsNames returns the host and DNS names to use when creating the TLS +// ceftificate. +func dnsNames(tlsExtraDomains []string) (string, []string) { // Collect the host's names into a slice. host, err := os.Hostname() if err != nil { @@ -113,6 +97,42 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs, // in-memory connections used on mobile. dnsNames = append(dnsNames, "bufconn") + return host, dnsNames +} + +// GenCertPair generates a key/cert pair to the paths provided. The +// auto-generated certificates should *not* be used in production for public +// access as they're self-signed and don't necessarily contain all of the +// desired hostnames for the service. For production/public use, consider a +// real PKI. +// +// This function is adapted from https://github.com/btcsuite/btcd and +// https://github.com/btcsuite/btcutil +func GenCertPair(org, certFile, keyFile string, tlsExtraIPs, + tlsExtraDomains []string, certValidity time.Duration) error { + + now := time.Now() + validUntil := now.Add(certValidity) + + // Check that the certificate validity isn't past the ASN.1 end of time. + if validUntil.After(endOfTime) { + validUntil = endOfTime + } + + // Generate a serial number that's below the serialNumberLimit. + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return fmt.Errorf("failed to generate serial number: %s", err) + } + + // Get all DNS names and IP addresses to use when creating the + // certificate. + host, dnsNames := dnsNames(tlsExtraDomains) + ipAddresses, err := ipAddresses(tlsExtraIPs) + if err != nil { + return err + } + // Generate a private key for the certificate. priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { From 83dcf95f929dfb3b604a9dc6978e34c14b0651a1 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 5 Feb 2020 13:51:48 +0100 Subject: [PATCH 070/562] cert+test: IsOutdated check for TLS files if IPs or DNS changed This commit creates a new utility method IsOutdated that can be used to check whether a TLS certificate mathces the extra IPs and domains given in the lnd config. --- cert/selfsigned.go | 77 +++++++++++++++++++++++ cert/selfsigned_test.go | 135 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 cert/selfsigned_test.go diff --git a/cert/selfsigned.go b/cert/selfsigned.go index 574a37f330..f67e8cd8ae 100644 --- a/cert/selfsigned.go +++ b/cert/selfsigned.go @@ -100,6 +100,83 @@ func dnsNames(tlsExtraDomains []string) (string, []string) { return host, dnsNames } +// IsOutdated returns whether the given certificate is outdated w.r.t. the IPs +// and domains given. The certificate is considered up to date if it was +// created with _exactly_ the IPs and domains given. +func IsOutdated(cert *x509.Certificate, tlsExtraIPs, + tlsExtraDomains []string) (bool, error) { + + // Parse the slice of IP strings. + ips, err := ipAddresses(tlsExtraIPs) + if err != nil { + return false, err + } + + // To not consider the certificate outdated if it has duplicate IPs or + // if only the order has changed, we create two maps from the slice of + // IPs to compare. + ips1 := make(map[string]net.IP) + for _, ip := range ips { + ips1[ip.String()] = ip + } + + ips2 := make(map[string]net.IP) + for _, ip := range cert.IPAddresses { + ips2[ip.String()] = ip + } + + // If the certificate has a different number of IP addresses, it is + // definitely out of date. + if len(ips1) != len(ips2) { + return true, nil + } + + // Go through each IP address, and check that they are equal. We expect + // both the string representation and the exact IP to match. + for s, ip1 := range ips1 { + // Assert the IP string is found in both sets. + ip2, ok := ips2[s] + if !ok { + return true, nil + } + + // And that the IPs are considered equal. + if !ip1.Equal(ip2) { + return true, nil + } + } + + // Get the full list of DNS names to use. + _, dnsNames := dnsNames(tlsExtraDomains) + + // We do the same kind of deduplication for the DNS names. + dns1 := make(map[string]struct{}) + for _, n := range cert.DNSNames { + dns1[n] = struct{}{} + } + + dns2 := make(map[string]struct{}) + for _, n := range dnsNames { + dns2[n] = struct{}{} + } + + // If the number of domains are different, it is out of date. + if len(dns1) != len(dns2) { + return true, nil + } + + // Similarly, check that each DNS name matches what is found in the + // certificate. + for k := range dns1 { + if _, ok := dns2[k]; !ok { + return true, nil + } + } + + // Certificate was up-to-date. + return false, nil +} + // GenCertPair generates a key/cert pair to the paths provided. The // auto-generated certificates should *not* be used in production for public // access as they're self-signed and don't necessarily contain all of the diff --git a/cert/selfsigned_test.go b/cert/selfsigned_test.go new file mode 100644 index 0000000000..0a5888a96e --- /dev/null +++ b/cert/selfsigned_test.go @@ -0,0 +1,135 @@ +package cert_test + +import ( + "io/ioutil" + "testing" + + "github.com/lightningnetwork/lnd/cert" +) + +var ( + extraIPs = []string{"1.1.1.1", "123.123.123.1", "199.189.12.12"} + extraDomains = []string{"home", "and", "away"} +) + +// TestIsOutdatedCert checks that we'll consider the TLS certificate outdated +// if the ip addresses or dns names don't match. +func TestIsOutdatedCert(t *testing.T) { + tempDir, err := ioutil.TempDir("", "certtest") + if err != nil { + t.Fatal(err) + } + + certPath := tempDir + "/tls.cert" + keyPath := tempDir + "/tls.key" + + // Generate TLS files with two extra IPs and domains. + err = cert.GenCertPair( + "lnd autogenerated cert", certPath, keyPath, extraIPs[:2], + extraDomains[:2], cert.DefaultAutogenValidity, + ) + if err != nil { + t.Fatal(err) + } + + // We'll attempt to check up-to-date status for all variants of 1-3 + // number of IPs and domains. + for numIPs := 1; numIPs <= len(extraIPs); numIPs++ { + for numDomains := 1; numDomains <= len(extraDomains); numDomains++ { + _, parsedCert, err := cert.LoadCert( + certPath, keyPath, + ) + if err != nil { + t.Fatal(err) + } + + // Using the test case's number of IPs and domains, get + // the outdated status of the certificate we created + // above. + outdated, err := cert.IsOutdated( + parsedCert, extraIPs[:numIPs], + extraDomains[:numDomains], + ) + if err != nil { + t.Fatal(err) + } + + // We expect it to be considered outdated if the IPs or + // domains don't match exactly what we created. + expected := numIPs != 2 || numDomains != 2 + if outdated != expected { + t.Fatalf("expected certificate to be "+ + "outdated=%v, got=%v", expected, + outdated) + } + } + } +} + +// TestIsOutdatedPermutation tests that the order of listed IPs or DNS names, +// nor dulicates in the lists, matter for whether we consider the certificate +// outdated. +func TestIsOutdatedPermutation(t *testing.T) { + tempDir, err := ioutil.TempDir("", "certtest") + if err != nil { + t.Fatal(err) + } + + certPath := tempDir + "/tls.cert" + keyPath := tempDir + "/tls.key" + + // Generate TLS files from the IPs and domains. + err = cert.GenCertPair( + "lnd autogenerated cert", certPath, keyPath, extraIPs[:], + extraDomains[:], cert.DefaultAutogenValidity, + ) + if err != nil { + t.Fatal(err) + } + _, parsedCert, err := cert.LoadCert(certPath, keyPath) + if err != nil { + t.Fatal(err) + } + + // If we have duplicate IPs or DNS names listed, that shouldn't matter. + dupIPs := make([]string, len(extraIPs)*2) + for i := range dupIPs { + dupIPs[i] = extraIPs[i/2] + } + + dupDNS := make([]string, len(extraDomains)*2) + for i := range dupDNS { + dupDNS[i] = extraDomains[i/2] + } + + outdated, err := cert.IsOutdated(parsedCert, dupIPs, dupDNS) + if err != nil { + t.Fatal(err) + } + + if outdated { + t.Fatalf("did not expect duplicate IPs or DNS names be " + + "considered outdated") + } + + // Similarly, the order of the lists shouldn't matter. + revIPs := make([]string, len(extraIPs)) + for i := range revIPs { + revIPs[i] = extraIPs[len(extraIPs)-1-i] + } + + revDNS := make([]string, len(extraDomains)) + for i := range revDNS { + revDNS[i] = extraDomains[len(extraDomains)-1-i] + } + + outdated, err = cert.IsOutdated(parsedCert, revIPs, revDNS) + if err != nil { + t.Fatal(err) + } + + if outdated { + t.Fatalf("did not expect reversed IPs or DNS names be " + + "considered outdated") + } +} From f7a85e07b0c130375d57611f2a50581c349e7127 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 5 Feb 2020 13:51:48 +0100 Subject: [PATCH 071/562] lnd+cert: recreate TLS files if IPs or DNS changed This commit makes lnd recreate its TLS certificate if the config's tlsextradomains or tlsextraips changed. This is useful, since earlier user would have to manually delete the files to trigger lnd to recreate them. To ensure users don't accidentally have their TLS certificate recreated, we gate it behind a flag --tlsautorefresh that defaults to false. --- config.go | 25 ++++++++++++++----------- lnd.go | 23 +++++++++++++++++++---- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/config.go b/config.go index 89b934a8b9..2308cd6b55 100644 --- a/config.go +++ b/config.go @@ -232,21 +232,24 @@ type torConfig struct { type config struct { ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` - LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."` - ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` - DataDir string `short:"b" long:"datadir" description:"The directory to store lnd's data within"` - SyncFreelist bool `long:"sync-freelist" description:"Whether the databases used within lnd should sync their freelist to disk. This is disabled by default resulting in improved memory performance during operation, but with an increase in startup time."` + LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."` + ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` + DataDir string `short:"b" long:"datadir" description:"The directory to store lnd's data within"` + SyncFreelist bool `long:"sync-freelist" description:"Whether the databases used within lnd should sync their freelist to disk. This is disabled by default resulting in improved memory performance during operation, but with an increase in startup time."` + TLSCertPath string `long:"tlscertpath" description:"Path to write the TLS certificate for lnd's RPC and REST services"` TLSKeyPath string `long:"tlskeypath" description:"Path to write the TLS private key for lnd's RPC and REST services"` TLSExtraIPs []string `long:"tlsextraip" description:"Adds an extra ip to the generated certificate"` TLSExtraDomains []string `long:"tlsextradomain" description:"Adds an extra domain to the generated certificate"` - NoMacaroons bool `long:"no-macaroons" description:"Disable macaroon authentication"` - AdminMacPath string `long:"adminmacaroonpath" description:"Path to write the admin macaroon for lnd's RPC and REST services if it doesn't exist"` - ReadMacPath string `long:"readonlymacaroonpath" description:"Path to write the read-only macaroon for lnd's RPC and REST services if it doesn't exist"` - InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to the invoice-only macaroon for lnd's RPC and REST services if it doesn't exist"` - LogDir string `long:"logdir" description:"Directory to log output."` - MaxLogFiles int `long:"maxlogfiles" description:"Maximum logfiles to keep (0 for no rotation)"` - MaxLogFileSize int `long:"maxlogfilesize" description:"Maximum logfile size in MB"` + TLSAutoRefresh bool `long:"tlsautorefresh" description:"Re-generate TLS certificate and key if the IPs or domains are changed"` + + NoMacaroons bool `long:"no-macaroons" description:"Disable macaroon authentication"` + AdminMacPath string `long:"adminmacaroonpath" description:"Path to write the admin macaroon for lnd's RPC and REST services if it doesn't exist"` + ReadMacPath string `long:"readonlymacaroonpath" description:"Path to write the read-only macaroon for lnd's RPC and REST services if it doesn't exist"` + InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to the invoice-only macaroon for lnd's RPC and REST services if it doesn't exist"` + LogDir string `long:"logdir" description:"Directory to log output."` + MaxLogFiles int `long:"maxlogfiles" description:"Maximum logfiles to keep (0 for no rotation)"` + MaxLogFileSize int `long:"maxlogfilesize" description:"Maximum logfile size in MB"` // We'll parse these 'raw' string arguments into real net.Addrs in the // loadConfig function. We need to expose the 'raw' strings so the diff --git a/lnd.go b/lnd.go index 1c10c54648..1a28cebcf3 100644 --- a/lnd.go +++ b/lnd.go @@ -717,10 +717,25 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs, return nil, nil, "", err } - // If the certificate expired, delete it and the TLS key and generate a - // new pair. - if time.Now().After(parsedCert.NotAfter) { - ltndLog.Info("TLS certificate is expired, generating a new one") + // We check whether the certifcate we have on disk match the IPs and + // domains specified by the config. If the extra IPs or domains have + // changed from when the certificate was created, we will refresh the + // certificate if auto refresh is active. + refresh := false + if cfg.TLSAutoRefresh { + refresh, err = cert.IsOutdated( + parsedCert, tlsExtraIPs, tlsExtraDomains, + ) + if err != nil { + return nil, nil, "", err + } + } + + // If the certificate expired or it was outdated, delete it and the TLS + // key and generate a new pair. + if time.Now().After(parsedCert.NotAfter) || refresh { + ltndLog.Info("TLS certificate is expired or outdated, " + + "generating a new one") err := os.Remove(tlsCertPath) if err != nil { From ba38bda5f06843e0c3add40130efb615b58bf21e Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 5 Feb 2020 13:51:48 +0100 Subject: [PATCH 072/562] lnd: reload cert data after renewal After renewing the certificate, the new certificate wasn't actually loaded and used, causing the old one to be used until lnd was restarted. This fixes that by reloading it after it has been written. --- lnd.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lnd.go b/lnd.go index 1a28cebcf3..a080f5a7b2 100644 --- a/lnd.go +++ b/lnd.go @@ -757,6 +757,12 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs, return nil, nil, "", err } rpcsLog.Infof("Done renewing TLS certificates") + + // Reload the certificate data. + certData, _, err = cert.LoadCert(tlsCertPath, tlsKeyPath) + if err != nil { + return nil, nil, "", err + } } tlsCfg := cert.TLSConfFromCert(certData) From e114f58b5e0881d3a5705b9849e16ceef48ebcf3 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 12 Feb 2020 11:10:18 +0100 Subject: [PATCH 073/562] lnwallet: unify remote and local update log fetch --- lnwallet/channel.go | 74 +++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 131d863279..94d036a8ab 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2460,6 +2460,46 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, skipUs := make(map[uint64]struct{}) skipThem := make(map[uint64]struct{}) + // fetchParentEntry is a helper method that will fetch the parent of + // entry from the corresponding update log. + fetchParentEntry := func(entry *PaymentDescriptor, + remoteLog bool) *PaymentDescriptor { + + var ( + updateLog *updateLog + logName string + ) + + if remoteLog { + updateLog = lc.remoteUpdateLog + logName = "remote" + } else { + updateLog = lc.localUpdateLog + logName = "local" + } + + addEntry := updateLog.lookupHtlc(entry.ParentIndex) + + switch { + // We check if the parent entry is not found at this point. We + // have seen this happening a few times and panic with some + // addtitional info to figure out why. + // TODO(halseth): remove when bug is fixed. + case addEntry == nil: + panic(fmt.Sprintf("unable to find parent entry %d "+ + "in %v update log: %v\nUpdatelog: %v", + entry.ParentIndex, logName, + newLogClosure(func() string { + return spew.Sdump(entry) + }), newLogClosure(func() string { + return spew.Sdump(updateLog) + }), + )) + } + + return addEntry + } + // First we run through non-add entries in both logs, populating the // skip sets and mutating the current chain state (crediting balances, // etc) to reflect the settle/timeout entry encountered. @@ -2486,22 +2526,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, lc.channelState.TotalMSatReceived += entry.Amount } - addEntry := lc.remoteUpdateLog.lookupHtlc(entry.ParentIndex) - - // We check if the parent entry is not found at this point. We - // have seen this happening a few times and panic with some - // addtitional info to figure out why. - // TODO(halseth): remove when bug is fixed. - if addEntry == nil { - panic(fmt.Sprintf("unable to find parent entry %d "+ - "in remote update log: %v\nUpdatelog: %v", - entry.ParentIndex, newLogClosure(func() string { - return spew.Sdump(entry) - }), newLogClosure(func() string { - return spew.Sdump(lc.remoteUpdateLog) - }), - )) - } + addEntry := fetchParentEntry(entry, true) skipThem[addEntry.HtlcIndex] = struct{}{} processRemoveEntry(entry, ourBalance, theirBalance, @@ -2531,22 +2556,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, lc.channelState.TotalMSatSent += entry.Amount } - addEntry := lc.localUpdateLog.lookupHtlc(entry.ParentIndex) - - // We check if the parent entry is not found at this point. We - // have seen this happening a few times and panic with some - // addtitional info to figure out why. - // TODO(halseth): remove when bug is fixed. - if addEntry == nil { - panic(fmt.Sprintf("unable to find parent entry %d "+ - "in local update log: %v\nUpdatelog: %v", - entry.ParentIndex, newLogClosure(func() string { - return spew.Sdump(entry) - }), newLogClosure(func() string { - return spew.Sdump(lc.localUpdateLog) - }), - )) - } + addEntry := fetchParentEntry(entry, false) skipUs[addEntry.HtlcIndex] = struct{}{} processRemoveEntry(entry, ourBalance, theirBalance, From 5943e5d8b1708ac08e6436a954bdcfac3b994863 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 12 Feb 2020 11:10:19 +0100 Subject: [PATCH 074/562] lnwallet: state transition from correct node during test, remove panic The unit test TestNewBreachRetributionSkipsDustHtlcs triggered a state transition from Bob, even though it was Alice that had added the HTLCs. This is wrong since it will lead to Bob still owing Alice a commitment, which is not accounted for in the unit tests. We add a sanity check that the add heights has been set for all entries found in the logs, and return an error otherwise. This won't happen during normal operation, but it does reveal the mistake in the unit test, which is fixed by making Alice trigger the transition. In addition we resolve a long standing TODO by removing a (purposeful) panic in the channel state machine. Old version of lnd had a bug that could lead to the parent entries being lost during channel restore. A panic was added to get to the bottom of if. This is now fixed, so new nodes shouldn't encounter it. However, to be on the safe side, instead of panicking we return an error back to gracefully exit the channel state machine. --- lnwallet/channel.go | 70 ++++++++++++++++++++++++++++------------ lnwallet/channel_test.go | 4 +-- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 94d036a8ab..a83e4dbbd9 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2374,9 +2374,12 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool, // these balances will be *before* taking a commitment fee from the // initiator. htlcView := lc.fetchHTLCView(theirLogIndex, ourLogIndex) - ourBalance, theirBalance, _, filteredHTLCView := lc.computeView( + ourBalance, theirBalance, _, filteredHTLCView, err := lc.computeView( htlcView, remoteChain, true, ) + if err != nil { + return nil, err + } feePerKw := filteredHTLCView.feePerKw // Actually generate unsigned commitment transaction for this view. @@ -2444,7 +2447,7 @@ func fundingTxIn(chanState *channeldb.OpenChannel) wire.TxIn { // method. func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, theirBalance *lnwire.MilliSatoshi, nextHeight uint64, - remoteChain, mutateState bool) *htlcView { + remoteChain, mutateState bool) (*htlcView, error) { // We initialize the view's fee rate to the fee rate of the unfiltered // view. If any fee updates are found when evaluating the view, it will @@ -2463,7 +2466,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, // fetchParentEntry is a helper method that will fetch the parent of // entry from the corresponding update log. fetchParentEntry := func(entry *PaymentDescriptor, - remoteLog bool) *PaymentDescriptor { + remoteLog bool) (*PaymentDescriptor, error) { var ( updateLog *updateLog @@ -2481,23 +2484,34 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, addEntry := updateLog.lookupHtlc(entry.ParentIndex) switch { - // We check if the parent entry is not found at this point. We - // have seen this happening a few times and panic with some - // addtitional info to figure out why. - // TODO(halseth): remove when bug is fixed. + // We check if the parent entry is not found at this point. + // This could happen for old versions of lnd, and we return an + // error to gracefully shut down the state machine if such an + // entry is still in the logs. case addEntry == nil: - panic(fmt.Sprintf("unable to find parent entry %d "+ - "in %v update log: %v\nUpdatelog: %v", + return nil, fmt.Errorf("unable to find parent entry "+ + "%d in %v update log: %v\nUpdatelog: %v", entry.ParentIndex, logName, newLogClosure(func() string { return spew.Sdump(entry) }), newLogClosure(func() string { return spew.Sdump(updateLog) }), - )) + ) + + // The parent add height should never be zero at this point. If + // that's the case we probably forgot to send a new commitment. + case remoteChain && addEntry.addCommitHeightRemote == 0: + return nil, fmt.Errorf("parent entry %d for update %d "+ + "had zero remote add height", entry.ParentIndex, + entry.LogIndex) + case !remoteChain && addEntry.addCommitHeightLocal == 0: + return nil, fmt.Errorf("parent entry %d for update %d "+ + "had zero local add height", entry.ParentIndex, + entry.LogIndex) } - return addEntry + return addEntry, nil } // First we run through non-add entries in both logs, populating the @@ -2526,7 +2540,10 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, lc.channelState.TotalMSatReceived += entry.Amount } - addEntry := fetchParentEntry(entry, true) + addEntry, err := fetchParentEntry(entry, true) + if err != nil { + return nil, err + } skipThem[addEntry.HtlcIndex] = struct{}{} processRemoveEntry(entry, ourBalance, theirBalance, @@ -2556,7 +2573,10 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, lc.channelState.TotalMSatSent += entry.Amount } - addEntry := fetchParentEntry(entry, false) + addEntry, err := fetchParentEntry(entry, false) + if err != nil { + return nil, err + } skipUs[addEntry.HtlcIndex] = struct{}{} processRemoveEntry(entry, ourBalance, theirBalance, @@ -2587,7 +2607,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance, newView.theirUpdates = append(newView.theirUpdates, entry) } - return newView + return newView, nil } // processAddEntry evaluates the effect of an add entry within the HTLC log. @@ -3109,9 +3129,12 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter, ourInitialBalance := commitChain.tip().ourBalance theirInitialBalance := commitChain.tip().theirBalance - ourBalance, theirBalance, commitWeight, filteredView := lc.computeView( + ourBalance, theirBalance, commitWeight, filteredView, err := lc.computeView( view, remoteChain, false, ) + if err != nil { + return err + } feePerKw := filteredView.feePerKw // Calculate the commitment fee, and subtract it from the initiator's @@ -3202,7 +3225,7 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter, // First check that the remote updates won't violate it's channel // constraints. - err := validateUpdates( + err = validateUpdates( filteredView.theirUpdates, &lc.channelState.RemoteChanCfg, ) if err != nil { @@ -3698,7 +3721,7 @@ func (lc *LightningChannel) ProcessChanSyncMsg( // HTLCs will be set to the next commitment height. func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, updateState bool) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, int64, - *htlcView) { + *htlcView, error) { commitChain := lc.localCommitChain dustLimit := lc.channelState.LocalChanCfg.DustLimit @@ -3737,8 +3760,11 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, // channel constraints to the final commitment state. If any fee // updates are found in the logs, the commitment fee rate should be // changed, so we'll also set the feePerKw to this new value. - filteredHTLCView := lc.evaluateHTLCView(view, &ourBalance, + filteredHTLCView, err := lc.evaluateHTLCView(view, &ourBalance, &theirBalance, nextHeight, remoteChain, updateState) + if err != nil { + return 0, 0, 0, nil, err + } feePerKw := filteredHTLCView.feePerKw // Now go through all HTLCs at this stage, to calculate the total @@ -3762,7 +3788,7 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, } totalCommitWeight := input.CommitWeight + totalHtlcWeight - return ourBalance, theirBalance, totalCommitWeight, filteredHTLCView + return ourBalance, theirBalance, totalCommitWeight, filteredHTLCView, nil } // genHtlcSigValidationJobs generates a series of signatures verification jobs @@ -5967,8 +5993,12 @@ func (lc *LightningChannel) availableBalance() (lnwire.MilliSatoshi, int64) { lc.localUpdateLog.logIndex) // Then compute our current balance for that view. - ourBalance, _, commitWeight, filteredView := + ourBalance, _, commitWeight, filteredView, err := lc.computeView(htlcView, false, false) + if err != nil { + lc.log.Errorf("Unable to fetch available balance: %v", err) + return 0, 0 + } // If we are the channel initiator, we must remember to subtract the // commitment fee from our available balance. diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 1e871ab68c..d34862ed74 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -5922,8 +5922,8 @@ func TestNewBreachRetributionSkipsDustHtlcs(t *testing.T) { // With the HTLC's applied to both update logs, we'll initiate a state // transition from Alice. - if err := ForceStateTransition(bobChannel, aliceChannel); err != nil { - t.Fatalf("unable to complete bob's state transition: %v", err) + if err := ForceStateTransition(aliceChannel, bobChannel); err != nil { + t.Fatalf("unable to complete alice's state transition: %v", err) } // At this point, we'll capture the current state number, as well as From 9dc349488be2d6007268c8b28628372f4a8580e6 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 9 Dec 2019 11:51:13 +0100 Subject: [PATCH 075/562] sweep: add exclusive groups Allows certain sweep inputs to be kept in separate transactions at all times. This is a preparation for anchor outputs. Before the commitment tx confirms, there are three potential anchors that can be cpfp'ed. We want to cpfp them all, but if done in the same transaction, the transaction would guaranteed to be invalid. Exponential backoff would eventually get the txes published, but having exclusive groups makes the process faster. --- sweep/bucket_list.go | 45 ++++++++++++++++++++++++ sweep/sweeper.go | 82 ++++++++++++++++++++++++++++++++++--------- sweep/sweeper_test.go | 60 +++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 16 deletions(-) create mode 100644 sweep/bucket_list.go diff --git a/sweep/bucket_list.go b/sweep/bucket_list.go new file mode 100644 index 0000000000..4b3c67cd4d --- /dev/null +++ b/sweep/bucket_list.go @@ -0,0 +1,45 @@ +package sweep + +// bucket contains a set of inputs that are not mutually exclusive. +type bucket pendingInputs + +// tryAdd tries to add a new input to this bucket. +func (b bucket) tryAdd(input *pendingInput) bool { + exclusiveGroup := input.params.ExclusiveGroup + if exclusiveGroup != nil { + for _, input := range b { + existingGroup := input.params.ExclusiveGroup + if existingGroup != nil && + *existingGroup == *exclusiveGroup { + + return false + } + } + } + + b[*input.OutPoint()] = input + + return true +} + +// bucketList is a list of buckets that contain non-mutually exclusive inputs. +type bucketList struct { + buckets []bucket +} + +// add adds a new input. If the input is not accepted by any of the existing +// buckets, a new bucket will be created. +func (b *bucketList) add(input *pendingInput) { + for _, existingBucket := range b.buckets { + if existingBucket.tryAdd(input) { + return + } + } + + // Create a new bucket and add the input. It is not necessary to check + // the return value of tryAdd because it will always succeed on an empty + // bucket. + newBucket := make(bucket) + newBucket.tryAdd(input) + b.buckets = append(b.buckets, newBucket) +} diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 8a9a38da5f..5997149348 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -50,6 +50,11 @@ var ( // request from a client whom did not specify a fee preference. ErrNoFeePreference = errors.New("no fee preference specified") + // ErrExclusiveGroupSpend is returned in case a different input of the + // same exclusive group was spent. + ErrExclusiveGroupSpend = errors.New("other member of exclusive group " + + "was spent") + // ErrSweeperShuttingDown is an error returned when a client attempts to // make a request to the UtxoSweeper, but it is unable to handle it as // it is/has already been stoppepd. @@ -71,11 +76,16 @@ type Params struct { // Force indicates whether the input should be swept regardless of // whether it is economical to do so. Force bool + + // ExclusiveGroup is an identifier that, if set, prevents other inputs + // with the same identifier from being batched together. + ExclusiveGroup *uint64 } // String returns a human readable interpretation of the sweep parameters. func (p Params) String() string { - return fmt.Sprintf("fee=%v, force=%v", p.Fee, p.Force) + return fmt.Sprintf("fee=%v, force=%v, exclusive_group=%v", + p.Fee, p.Force, p.ExclusiveGroup) } // pendingInput is created when an input reaches the main loop for the first @@ -552,7 +562,7 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch) { // registration, deleted from pendingInputs but // the ntfn was in-flight already. Or this could // be not one of our inputs. - _, ok := s.pendingInputs[outpoint] + input, ok := s.pendingInputs[outpoint] if !ok { continue } @@ -568,6 +578,14 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch) { Tx: spend.SpendingTx, Err: err, }) + + // Remove all other inputs in this exclusive + // group. + if input.params.ExclusiveGroup != nil { + s.removeExclusiveGroup( + *input.params.ExclusiveGroup, + ) + } } // Now that an input of ours is spent, we can try to @@ -639,6 +657,31 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch) { } } +// removeExclusiveGroup removes all inputs in the given exclusive group. This +// function is called when one of the exclusive group inputs has been spent. The +// other inputs won't ever be spendable and can be removed. This also prevents +// them from being part of future sweep transactions that would fail. +func (s *UtxoSweeper) removeExclusiveGroup(group uint64) { + for outpoint, input := range s.pendingInputs { + outpoint := outpoint + + // Skip inputs that aren't exclusive. + if input.params.ExclusiveGroup == nil { + continue + } + + // Skip inputs from other exclusive groups. + if *input.params.ExclusiveGroup != group { + continue + } + + // Signal result channels. + s.signalAndRemove(&outpoint, Result{ + Err: ErrExclusiveGroupSpend, + }) + } +} + // sweepCluster tries to sweep the given input cluster. func (s *UtxoSweeper) sweepCluster(cluster inputCluster, currentHeight int32) error { @@ -679,7 +722,7 @@ func (s *UtxoSweeper) bucketForFeeRate( // sweep fee rate, which is determined by calculating the average fee rate of // all inputs within that cluster. func (s *UtxoSweeper) clusterBySweepFeeRate() []inputCluster { - bucketInputs := make(map[int]pendingInputs) + bucketInputs := make(map[int]*bucketList) inputFeeRates := make(map[wire.OutPoint]chainfee.SatPerKWeight) // First, we'll group together all inputs with similar fee rates. This @@ -692,30 +735,37 @@ func (s *UtxoSweeper) clusterBySweepFeeRate() []inputCluster { } feeGroup := s.bucketForFeeRate(feeRate) - inputs, ok := bucketInputs[feeGroup] + // Create a bucket list for this fee rate if there isn't one + // yet. + buckets, ok := bucketInputs[feeGroup] if !ok { - inputs = make(pendingInputs) - bucketInputs[feeGroup] = inputs + buckets = &bucketList{} + bucketInputs[feeGroup] = buckets } + // Request the bucket list to add this input. The bucket list + // will take into account exclusive group constraints. + buckets.add(input) + input.lastFeeRate = feeRate - inputs[op] = input inputFeeRates[op] = feeRate } // We'll then determine the sweep fee rate for each set of inputs by // calculating the average fee rate of the inputs within each set. inputClusters := make([]inputCluster, 0, len(bucketInputs)) - for _, inputs := range bucketInputs { - var sweepFeeRate chainfee.SatPerKWeight - for op := range inputs { - sweepFeeRate += inputFeeRates[op] + for _, buckets := range bucketInputs { + for _, inputs := range buckets.buckets { + var sweepFeeRate chainfee.SatPerKWeight + for op := range inputs { + sweepFeeRate += inputFeeRates[op] + } + sweepFeeRate /= chainfee.SatPerKWeight(len(inputs)) + inputClusters = append(inputClusters, inputCluster{ + sweepFeeRate: sweepFeeRate, + inputs: inputs, + }) } - sweepFeeRate /= chainfee.SatPerKWeight(len(inputs)) - inputClusters = append(inputClusters, inputCluster{ - sweepFeeRate: sweepFeeRate, - inputs: inputs, - }) } return inputClusters diff --git a/sweep/sweeper_test.go b/sweep/sweeper_test.go index a663c3ab51..85908f7e81 100644 --- a/sweep/sweeper_test.go +++ b/sweep/sweeper_test.go @@ -1232,3 +1232,63 @@ func TestBumpFeeRBF(t *testing.T) { ctx.finish(1) } + +// TestExclusiveGroup tests the sweeper exclusive group functionality. +func TestExclusiveGroup(t *testing.T) { + ctx := createSweeperTestContext(t) + + // Sweep three inputs in the same exclusive group. + var results []chan Result + for i := 0; i < 3; i++ { + exclusiveGroup := uint64(1) + result, err := ctx.sweeper.SweepInput( + spendableInputs[i], Params{ + Fee: FeePreference{ConfTarget: 6}, + ExclusiveGroup: &exclusiveGroup, + }, + ) + if err != nil { + t.Fatal(err) + } + results = append(results, result) + } + + // We expect all inputs to be published in separate transactions, even + // though they share the same fee preference. + ctx.tick() + for i := 0; i < 3; i++ { + sweepTx := ctx.receiveTx() + if len(sweepTx.TxOut) != 1 { + t.Fatal("expected a single tx out in the sweep tx") + } + + // Remove all txes except for the one that sweeps the first + // input. This simulates the sweeps being conflicting. + if sweepTx.TxIn[0].PreviousOutPoint != + *spendableInputs[0].OutPoint() { + + ctx.backend.deleteUnconfirmed(sweepTx.TxHash()) + } + } + + // Mine the first sweep tx. + ctx.backend.mine() + + // Expect the first input to be swept by the confirmed sweep tx. + result0 := <-results[0] + if result0.Err != nil { + t.Fatal("expected first input to be swept") + } + + // Expect the other two inputs to return an error. They have no chance + // of confirming. + result1 := <-results[1] + if result1.Err != ErrExclusiveGroupSpend { + t.Fatal("expected second input to be canceled") + } + + result2 := <-results[2] + if result2.Err != ErrExclusiveGroupSpend { + t.Fatal("expected third input to be canceled") + } +} From 182835d504d1202048e55bf32d54cc4914c12ca2 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 10 Feb 2020 11:02:14 +0100 Subject: [PATCH 076/562] fundingmgr+channelnotifier: add channel config to pending chan ntfn To be able to write a new channel backup file for pending channels, we need to include the channel configuration in the pending channel notification event. --- channelnotifier/channelnotifier.go | 24 ++++++++--- fundingmanager.go | 6 +-- fundingmanager_test.go | 66 ++++++++++++++++++++++++++++-- 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/channelnotifier/channelnotifier.go b/channelnotifier/channelnotifier.go index e484b9a6c8..e6a1fada7d 100644 --- a/channelnotifier/channelnotifier.go +++ b/channelnotifier/channelnotifier.go @@ -23,8 +23,14 @@ type ChannelNotifier struct { // PendingOpenChannelEvent represents a new event where a new channel has // entered a pending open state. type PendingOpenChannelEvent struct { - // ChannelPoint is the channelpoint for the new channel. + // ChannelPoint is the channel outpoint for the new channel. ChannelPoint *wire.OutPoint + + // PendingChannel is the channel configuration for the newly created + // channel. This might not have been persisted to the channel DB yet + // because we are still waiting for the final message from the remote + // peer. + PendingChannel *channeldb.OpenChannel } // OpenChannelEvent represents a new event where a channel goes from pending @@ -89,10 +95,18 @@ func (c *ChannelNotifier) SubscribeChannelEvents() (*subscribe.Client, error) { return c.ntfnServer.Subscribe() } -// NotifyPendingOpenChannelEvent notifies the channelEventNotifier goroutine that a -// new channel is pending. -func (c *ChannelNotifier) NotifyPendingOpenChannelEvent(chanPoint wire.OutPoint) { - event := PendingOpenChannelEvent{ChannelPoint: &chanPoint} +// NotifyPendingOpenChannelEvent notifies the channelEventNotifier goroutine +// that a new channel is pending. The pending channel is passed as a parameter +// instead of read from the database because it might not yet have been +// persisted to the DB because we still wait for the final message from the +// remote peer. +func (c *ChannelNotifier) NotifyPendingOpenChannelEvent(chanPoint wire.OutPoint, + pendingChan *channeldb.OpenChannel) { + + event := PendingOpenChannelEvent{ + ChannelPoint: &chanPoint, + PendingChannel: pendingChan, + } if err := c.ntfnServer.SendUpdate(event); err != nil { log.Warnf("Unable to send pending open channel update: %v", err) diff --git a/fundingmanager.go b/fundingmanager.go index 8484b94554..2937a19c2f 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -366,7 +366,7 @@ type fundingConfig struct { // NotifyPendingOpenChannelEvent informs the ChannelNotifier when channels // enter a pending state. - NotifyPendingOpenChannelEvent func(wire.OutPoint) + NotifyPendingOpenChannelEvent func(wire.OutPoint, *channeldb.OpenChannel) } // fundingManager acts as an orchestrator/bridge between the wallet's @@ -1697,7 +1697,7 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { // Inform the ChannelNotifier that the channel has entered // pending open state. - f.cfg.NotifyPendingOpenChannelEvent(fundingOut) + f.cfg.NotifyPendingOpenChannelEvent(fundingOut, completeChan) // At this point we have sent our last funding message to the // initiating peer before the funding transaction will be broadcast. @@ -1845,7 +1845,7 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) { case resCtx.updates <- upd: // Inform the ChannelNotifier that the channel has entered // pending open state. - f.cfg.NotifyPendingOpenChannelEvent(*fundingPoint) + f.cfg.NotifyPendingOpenChannelEvent(*fundingPoint, completeChan) case <-f.quit: return } diff --git a/fundingmanager_test.go b/fundingmanager_test.go index c9f9a42129..f1ff528d6c 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -25,6 +25,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chanacceptor" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/discovery" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" @@ -48,6 +49,10 @@ const ( // testPollSleepMs is the number of milliseconds to sleep between // each attempt to access the database to check its state. testPollSleepMs = 500 + + // maxPending is the maximum number of channels we allow opening to the + // same peer in the max pending channels test. + maxPending = 4 ) var ( @@ -138,6 +143,24 @@ func (m *mockNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, _ []byte, }, nil } +type mockChanEvent struct { + openEvent chan wire.OutPoint + pendingOpenEvent chan channelnotifier.PendingOpenChannelEvent +} + +func (m *mockChanEvent) NotifyOpenChannelEvent(outpoint wire.OutPoint) { + m.openEvent <- outpoint +} + +func (m *mockChanEvent) NotifyPendingOpenChannelEvent(outpoint wire.OutPoint, + pendingChannel *channeldb.OpenChannel) { + + m.pendingOpenEvent <- channelnotifier.PendingOpenChannelEvent{ + ChannelPoint: &outpoint, + PendingChannel: pendingChannel, + } +} + type testNode struct { privKey *btcec.PrivateKey addr *lnwire.NetAddress @@ -147,6 +170,7 @@ type testNode struct { fundingMgr *fundingManager newChannels chan *newChannelMsg mockNotifier *mockNotifier + mockChanEvent *mockChanEvent testDir string shutdownChannel chan struct{} remoteFeatures []lnwire.FeatureBit @@ -274,6 +298,17 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, bestHeight: fundingBroadcastHeight, } + // The mock channel event notifier will receive events for each pending + // open and open channel. Because some tests will create multiple + // channels in a row before advancing to the next step, these channels + // need to be buffered. + evt := &mockChanEvent{ + openEvent: make(chan wire.OutPoint, maxPending), + pendingOpenEvent: make( + chan channelnotifier.PendingOpenChannelEvent, maxPending, + ), + } + dbDir := filepath.Join(tempTestDir, "cdb") cdb, err := channeldb.Open(dbDir) if err != nil { @@ -379,9 +414,9 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, ZombieSweeperInterval: 1 * time.Hour, ReservationTimeout: 1 * time.Nanosecond, MaxPendingChannels: DefaultMaxPendingChannels, - NotifyOpenChannelEvent: func(wire.OutPoint) {}, + NotifyOpenChannelEvent: evt.NotifyOpenChannelEvent, OpenChannelPredicate: chainedAcceptor, - NotifyPendingOpenChannelEvent: func(wire.OutPoint) {}, + NotifyPendingOpenChannelEvent: evt.NotifyPendingOpenChannelEvent, } for _, op := range options { @@ -404,6 +439,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, publTxChan: publTxChan, fundingMgr: f, mockNotifier: chainNotifier, + mockChanEvent: evt, testDir: tempTestDir, shutdownChannel: shutdownChan, addr: addr, @@ -685,6 +721,18 @@ func fundChannel(t *testing.T, alice, bob *testNode, localFundingAmt, t.Fatalf("alice did not publish funding tx") } + // Make sure the notification about the pending channel was sent out. + select { + case <-alice.mockChanEvent.pendingOpenEvent: + case <-time.After(time.Second * 5): + t.Fatalf("alice did not send pending channel event") + } + select { + case <-bob.mockChanEvent.pendingOpenEvent: + case <-time.After(time.Second * 5): + t.Fatalf("bob did not send pending channel event") + } + // Finally, make sure neither have active reservation for the channel // now pending open in the database. assertNumPendingReservations(t, alice, bobPubKey, 0) @@ -867,6 +915,18 @@ func assertMarkedOpen(t *testing.T, alice, bob *testNode, fundingOutPoint *wire.OutPoint) { t.Helper() + // Make sure the notification about the pending channel was sent out. + select { + case <-alice.mockChanEvent.openEvent: + case <-time.After(time.Second * 5): + t.Fatalf("alice did not send open channel event") + } + select { + case <-bob.mockChanEvent.openEvent: + case <-time.After(time.Second * 5): + t.Fatalf("bob did not send open channel event") + } + assertDatabaseState(t, alice, fundingOutPoint, markedOpen) assertDatabaseState(t, bob, fundingOutPoint, markedOpen) } @@ -2558,8 +2618,6 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { func TestFundingManagerMaxPendingChannels(t *testing.T) { t.Parallel() - const maxPending = 4 - alice, bob := setupFundingManagers( t, func(cfg *fundingConfig) { cfg.MaxPendingChannels = maxPending From 56c07a52d84f60123078ca6e68755dbd680a1588 Mon Sep 17 00:00:00 2001 From: nsa Date: Sat, 15 Feb 2020 09:45:25 -0500 Subject: [PATCH 077/562] lnwallet: call valdiateCommitmentSanity in ReceiveHTLC This commit checks the commitment sanity when receiving an HTLC so that if a commitment transaction will overflow from an ADD, it is caught earlier rather than in ReceiveNewCommitment. --- lnwallet/channel.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 131d863279..92bf538c36 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -3084,12 +3084,16 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter, view := lc.fetchHTLCView(theirLogCounter, ourLogCounter) // If we are checking if we can add a new HTLC, we add this to the - // update log, in order to validate the sanity of the commitment - // resulting from _actually adding_ this HTLC to the state. + // appropriate update log, in order to validate the sanity of the + // commitment resulting from _actually adding_ this HTLC to the state. if predictAdded != nil { - // If we are adding an HTLC, this will be an Add to the local - // update log. - view.ourUpdates = append(view.ourUpdates, predictAdded) + // If the remoteChain bool is true, add to ourUpdates. + if remoteChain { + view.ourUpdates = append(view.ourUpdates, predictAdded) + } else { + // Else add to theirUpdates. + view.theirUpdates = append(view.theirUpdates, predictAdded) + } } commitChain := lc.localCommitChain @@ -4640,6 +4644,17 @@ func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64, err OnionBlob: htlc.OnionBlob[:], } + localACKedIndex := lc.remoteCommitChain.tail().ourMessageIndex + + // Clamp down on the number of HTLC's we can receive by checking the + // commitment sanity. + err := lc.validateCommitmentSanity( + lc.remoteUpdateLog.logIndex, localACKedIndex, false, pd, + ) + if err != nil { + return 0, err + } + lc.remoteUpdateLog.appendHtlc(pd) return pd.HtlcIndex, nil From 4af00c6b256a539cd757e862347612cd19f8f761 Mon Sep 17 00:00:00 2001 From: nsa Date: Sat, 15 Feb 2020 09:51:07 -0500 Subject: [PATCH 078/562] lnwallet: fixing unit tests to properly handle new receive validation This commit fixes the TestMaxAcceptedHTLCs, TestMaxPendingAmount, TestMinHTLC, & TestChanReserve unit tests to pass with the new ReceiveHTLC logic. Instead of asserting specific failures upon receiving a new commitment signature, the various assertions were moved to assert on the error returned from ReceiveHTLC. --- lnwallet/channel_test.go | 108 ++++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 36 deletions(-) diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 1e871ab68c..94d6d48784 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -5462,23 +5462,26 @@ func TestMaxAcceptedHTLCs(t *testing.T) { defer cleanUp() // One over the maximum number of HTLCs that either can accept. - const numHTLCs = 20 - const numHTLCsReceived = 12 + const numHTLCs = 12 - // Set the remote's required MaxAcceptedHtlcs. This means that alice + // Set the remote's required MaxAcceptedHtlcs. This means that Alice // can only offer the remote up to numHTLCs HTLCs. aliceChannel.channelState.LocalChanCfg.MaxAcceptedHtlcs = numHTLCs bobChannel.channelState.RemoteChanCfg.MaxAcceptedHtlcs = numHTLCs // Similarly, set the remote config's MaxAcceptedHtlcs. This means - // that the remote will be aware that Alice will only accept up to - // numHTLCsRecevied at a time. - aliceChannel.channelState.RemoteChanCfg.MaxAcceptedHtlcs = numHTLCsReceived - bobChannel.channelState.LocalChanCfg.MaxAcceptedHtlcs = numHTLCsReceived + // that the remote will be aware that Bob will only accept up to + // numHTLCs at a time. + aliceChannel.channelState.RemoteChanCfg.MaxAcceptedHtlcs = numHTLCs + bobChannel.channelState.LocalChanCfg.MaxAcceptedHtlcs = numHTLCs // Each HTLC amount is 0.1 BTC. htlcAmt := lnwire.NewMSatFromSatoshis(0.1 * btcutil.SatoshiPerBitcoin) + // htlcID is used to keep track of the HTLC that Bob will fail back to + // Alice. + var htlcID uint64 + // Send the maximum allowed number of HTLCs. for i := 0; i < numHTLCs; i++ { htlc, _ := createHTLC(i, htlcAmt) @@ -5488,6 +5491,13 @@ func TestMaxAcceptedHTLCs(t *testing.T) { if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { t.Fatalf("unable to recv htlc: %v", err) } + + // Just assign htlcID to the last received HTLC. + htlcID = htlc.ID + } + + if err := ForceStateTransition(aliceChannel, bobChannel); err != nil { + t.Fatalf("unable to transition state: %v", err) } // The next HTLC should fail with ErrMaxHTLCNumber. @@ -5497,13 +5507,57 @@ func TestMaxAcceptedHTLCs(t *testing.T) { t.Fatalf("expected ErrMaxHTLCNumber, instead received: %v", err) } - // After receiving the next HTLC, next state transition should fail - // with ErrMaxHTLCNumber. + // Receiving the next HTLC should fail. + if _, err := bobChannel.ReceiveHTLC(htlc); err != ErrMaxHTLCNumber { + t.Fatalf("expected ErrMaxHTLCNumber, instead received: %v", err) + } + + // Bob will fail the htlc specified by htlcID and then force a state + // transition. + err = bobChannel.FailHTLC(htlcID, []byte{}, nil, nil, nil) + if err != nil { + t.Fatalf("unable to fail htlc: %v", err) + } + + if err := aliceChannel.ReceiveFailHTLC(htlcID, []byte{}); err != nil { + t.Fatalf("unable to receive fail htlc: %v", err) + } + + if err := ForceStateTransition(bobChannel, aliceChannel); err != nil { + t.Fatalf("unable to transition state: %v", err) + } + + // Bob should succeed in adding a new HTLC since a previous HTLC was just + // failed. We use numHTLCs here since the previous AddHTLC with this index + // failed. + htlc, _ = createHTLC(numHTLCs, htlcAmt) + if _, err := aliceChannel.AddHTLC(htlc, nil); err != nil { + t.Fatalf("unable to add htlc: %v", err) + } if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { t.Fatalf("unable to recv htlc: %v", err) } - err = ForceStateTransition(aliceChannel, bobChannel) - if err != ErrMaxHTLCNumber { + + // Add a commitment to Bob's commitment chain. + aliceSig, aliceHtlcSigs, _, err := aliceChannel.SignNextCommitment() + if err != nil { + t.Fatalf("unable to sign next commitment: %v", err) + } + err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs) + if err != nil { + t.Fatalf("unable to recv new commitment: %v", err) + } + + // The next HTLC should fail with ErrMaxHTLCNumber. The index is incremented + // by one. + htlc, _ = createHTLC(numHTLCs+1, htlcAmt) + if _, err = aliceChannel.AddHTLC(htlc, nil); err != ErrMaxHTLCNumber { + t.Fatalf("expected ErrMaxHTLCNumber, instead received: %v", err) + } + + // Likewise, Bob should not be able to receive this HTLC if Alice can't + // add it. + if _, err := bobChannel.ReceiveHTLC(htlc); err != ErrMaxHTLCNumber { t.Fatalf("expected ErrMaxHTLCNumber, instead received: %v", err) } } @@ -5556,13 +5610,8 @@ func TestMaxPendingAmount(t *testing.T) { t.Fatalf("expected ErrMaxPendingAmount, instead received: %v", err) } - // And also Bob shouldn't be accepting this HTLC in the next state - // transition. - if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { - t.Fatalf("unable to recv htlc: %v", err) - } - err = ForceStateTransition(aliceChannel, bobChannel) - if err != ErrMaxPendingAmount { + // And also Bob shouldn't be accepting this HTLC upon calling ReceiveHTLC. + if _, err := bobChannel.ReceiveHTLC(htlc); err != ErrMaxPendingAmount { t.Fatalf("expected ErrMaxPendingAmount, instead received: %v", err) } } @@ -5684,12 +5733,8 @@ func TestChanReserve(t *testing.T) { t.Fatalf("expected ErrBelowChanReserve, instead received: %v", err) } - // Alice will reject this htlc when a state transition is attempted. - if _, err := aliceChannel.ReceiveHTLC(htlc); err != nil { - t.Fatalf("unable to recv htlc: %v", err) - } - err = ForceStateTransition(aliceChannel, bobChannel) - if err != ErrBelowChanReserve { + // Alice will reject this htlc upon receiving the htlc. + if _, err := aliceChannel.ReceiveHTLC(htlc); err != ErrBelowChanReserve { t.Fatalf("expected ErrBelowChanReserve, instead received: %v", err) } @@ -5731,13 +5776,8 @@ func TestChanReserve(t *testing.T) { t.Fatalf("expected ErrBelowChanReserve, instead received: %v", err) } - // Likewise, Bob will reject a state transition after this htlc is - // received, of the same reason. - if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { - t.Fatalf("unable to recv htlc: %v", err) - } - err = ForceStateTransition(aliceChannel, bobChannel) - if err != ErrBelowChanReserve { + // Likewise, Bob will reject receiving the htlc because of the same reason. + if _, err := bobChannel.ReceiveHTLC(htlc); err != ErrBelowChanReserve { t.Fatalf("expected ErrBelowChanReserve, instead received: %v", err) } @@ -5857,13 +5897,9 @@ func TestMinHTLC(t *testing.T) { t.Fatalf("expected ErrBelowMinHTLC, instead received: %v", err) } - // Bob will receive this HTLC, but reject the next state update, since + // Bob will receive this HTLC, but reject the next received htlc, since // the htlc is too small. _, err = bobChannel.ReceiveHTLC(htlc) - if err != nil { - t.Fatalf("error receiving htlc: %v", err) - } - err = ForceStateTransition(aliceChannel, bobChannel) if err != ErrBelowMinHTLC { t.Fatalf("expected ErrBelowMinHTLC, instead received: %v", err) } From 5a5e09568484fecf35c0e1972fc7e23b0f56e6d0 Mon Sep 17 00:00:00 2001 From: nsa Date: Sat, 15 Feb 2020 09:52:47 -0500 Subject: [PATCH 079/562] lnwallet: adding TestMaxAsynchronousHtlcs unit test Adds a new test which asserts that the new ReceiveHTLC logic can handle proper commitment overflow calculation in the face of asynchronous updates. --- lnwallet/channel_test.go | 152 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 94d6d48784..48a6b5afdb 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -5562,6 +5562,158 @@ func TestMaxAcceptedHTLCs(t *testing.T) { } } +// TestMaxAsynchronousHtlcs tests that Bob correctly receives (and does not +// fail) an HTLC from Alice when exchanging asynchronous payments. We want to +// mimic the following case where Bob's commitment transaction is full before +// starting: +// Alice Bob +// 1. <---settle/fail--- +// 2. <-------sig------- +// 3. --------sig------> (covers an add sent before step 1) +// 4. <-------rev------- +// 5. --------rev------> +// 6. --------add------> +// 7. - - - - sig - - -> +// This represents an asynchronous commitment dance in which both sides are +// sending signatures at the same time. In step 3, the signature does not +// cover the recent settle/fail that Bob sent in step 1. However, the add that +// Alice sends to Bob in step 6 does not overflow Bob's commitment transaction. +// This is because validateCommitmentSanity counts the HTLC's by ignoring +// HTLC's which will be removed in the next signature that Alice sends. Thus, +// the add won't overflow. This is because the signature received in step 7 +// covers the settle/fail in step 1 and makes space for the add in step 6. +func TestMaxAsynchronousHtlcs(t *testing.T) { + t.Parallel() + + // We'll kick off the test by creating our channels which both are + // loaded with 5 BTC each. + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + if err != nil { + t.Fatalf("unable to create test channels: %v", err) + } + defer cleanUp() + + // One over the maximum number of HTLCs that either can accept. + const numHTLCs = 12 + + // Set the remote's required MaxAcceptedHtlcs. This means that Alice + // can only offer the remote up to numHTLCs HTLCs. + aliceChannel.channelState.LocalChanCfg.MaxAcceptedHtlcs = numHTLCs + bobChannel.channelState.RemoteChanCfg.MaxAcceptedHtlcs = numHTLCs + + // Similarly, set the remote config's MaxAcceptedHtlcs. This means + // that the remote will be aware that Bob will only accept up to + // numHTLCs at a time. + aliceChannel.channelState.RemoteChanCfg.MaxAcceptedHtlcs = numHTLCs + bobChannel.channelState.LocalChanCfg.MaxAcceptedHtlcs = numHTLCs + + // Each HTLC amount is 0.1 BTC. + htlcAmt := lnwire.NewMSatFromSatoshis(0.1 * btcutil.SatoshiPerBitcoin) + + var htlcID uint64 + + // Send the maximum allowed number of HTLCs minus one. + for i := 0; i < numHTLCs-1; i++ { + htlc, _ := createHTLC(i, htlcAmt) + if _, err := aliceChannel.AddHTLC(htlc, nil); err != nil { + t.Fatalf("unable to add htlc: %v", err) + } + if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { + t.Fatalf("unable to recv htlc: %v", err) + } + + // Just assign htlcID to the last received HTLC. + htlcID = htlc.ID + } + + if err := ForceStateTransition(aliceChannel, bobChannel); err != nil { + t.Fatalf("unable to transition state: %v", err) + } + + // Send an HTLC to Bob so that Bob's commitment transaction is full. + htlc, _ := createHTLC(numHTLCs-1, htlcAmt) + if _, err := aliceChannel.AddHTLC(htlc, nil); err != nil { + t.Fatalf("unable to add htlc: %v", err) + } + if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { + t.Fatalf("unable to recv htlc: %v", err) + } + + // Fail back an HTLC and sign a commitment as in steps 1 & 2. + err = bobChannel.FailHTLC(htlcID, []byte{}, nil, nil, nil) + if err != nil { + t.Fatalf("unable to fail htlc: %v", err) + } + + if err := aliceChannel.ReceiveFailHTLC(htlcID, []byte{}); err != nil { + t.Fatalf("unable to receive fail htlc: %v", err) + } + + bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment() + if err != nil { + t.Fatalf("unable to sign next commitment: %v", err) + } + + err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs) + if err != nil { + t.Fatalf("unable to receive new commitment: %v", err) + } + + // Cover the HTLC referenced with id equal to numHTLCs-1 with a new + // signature (step 3). + aliceSig, aliceHtlcSigs, _, err := aliceChannel.SignNextCommitment() + if err != nil { + t.Fatalf("unable to sign next commitment: %v", err) + } + + err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs) + if err != nil { + t.Fatalf("unable to receive new commitment: %v", err) + } + + // Both sides exchange revocations as in step 4 & 5. + bobRevocation, _, err := bobChannel.RevokeCurrentCommitment() + if err != nil { + t.Fatalf("unable to revoke revocation: %v", err) + } + + _, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) + if err != nil { + t.Fatalf("unable to receive revocation: %v", err) + } + + aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment() + if err != nil { + t.Fatalf("unable to revoke revocation: %v", err) + } + + _, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation) + if err != nil { + t.Fatalf("unable to receive revocation: %v", err) + } + + // Send the final Add which should succeed as in step 6. + htlc, _ = createHTLC(numHTLCs, htlcAmt) + if _, err := aliceChannel.AddHTLC(htlc, nil); err != nil { + t.Fatalf("unable to add htlc: %v", err) + } + if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { + t.Fatalf("unable to recv htlc: %v", err) + } + + // Receiving the commitment should succeed as in step 7 since space was + // made. + aliceSig, aliceHtlcSigs, _, err = aliceChannel.SignNextCommitment() + if err != nil { + t.Fatalf("unable to sign next commitment: %v", err) + } + + err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs) + if err != nil { + t.Fatalf("unable to receive new commitment: %v", err) + } +} + // TestMaxPendingAmount tests that the maximum overall pending HTLC value is met // given several HTLCs that, combined, exceed this value. An ErrMaxPendingAmount // error should be returned. From 0407b37fceb8370d79cd6e56745588d58d0d27ca Mon Sep 17 00:00:00 2001 From: Roei Erez Date: Mon, 3 Feb 2020 12:52:22 +0200 Subject: [PATCH 080/562] contractcourt+switch: keep channels with timed-out initiated htlcs. This commit enables the user to specify he is not interested in automatically close channels with pending payments that their corresponding htlcs have timed-out. By requiring a configurable grace period uptime of our node before closing such channels, we give a chance to the other node to properly cancel the htlc and avoid unnecessary on-chain transaction. In mobile it is very important for the user experience as otherwise channels will be force closed more frequently. --- config.go | 47 ++++++------ contractcourt/chain_arbitrator.go | 15 ++++ contractcourt/chain_arbitrator_test.go | 3 + contractcourt/channel_arbitrator.go | 29 +++++++- contractcourt/channel_arbitrator_test.go | 91 ++++++++++++++++++++++++ htlcswitch/switch.go | 12 ++++ htlcswitch/switch_test.go | 7 ++ server.go | 13 ++-- test_utils.go | 7 ++ 9 files changed, 196 insertions(+), 28 deletions(-) diff --git a/config.go b/config.go index 66d096a258..7923b7a0b7 100644 --- a/config.go +++ b/config.go @@ -58,15 +58,16 @@ const ( // pending channels permitted per peer. DefaultMaxPendingChannels = 1 - defaultNoSeedBackup = false - defaultTrickleDelay = 90 * 1000 - defaultChanStatusSampleInterval = time.Minute - defaultChanEnableTimeout = 19 * time.Minute - defaultChanDisableTimeout = 20 * time.Minute - defaultMaxLogFiles = 3 - defaultMaxLogFileSize = 10 - defaultMinBackoff = time.Second - defaultMaxBackoff = time.Hour + defaultNoSeedBackup = false + defaultPaymentsExpirationGracePeriod = time.Duration(0) + defaultTrickleDelay = 90 * 1000 + defaultChanStatusSampleInterval = time.Minute + defaultChanEnableTimeout = 19 * time.Minute + defaultChanDisableTimeout = 20 * time.Minute + defaultMaxLogFiles = 3 + defaultMaxLogFileSize = 10 + defaultMinBackoff = time.Second + defaultMaxBackoff = time.Hour defaultTorSOCKSPort = 9050 defaultTorDNSHost = "soa.nodes.lightning.directory" @@ -298,10 +299,11 @@ type config struct { NoSeedBackup bool `long:"noseedbackup" description:"If true, NO SEED WILL BE EXPOSED AND THE WALLET WILL BE ENCRYPTED USING THE DEFAULT PASSPHRASE -- EVER. THIS FLAG IS ONLY FOR TESTING AND IS BEING DEPRECATED."` - TrickleDelay int `long:"trickledelay" description:"Time in milliseconds between each release of announcements to the network"` - ChanEnableTimeout time.Duration `long:"chan-enable-timeout" description:"The duration that a peer connection must be stable before attempting to send a channel update to reenable or cancel a pending disables of the peer's channels on the network (default: 19m)."` - ChanDisableTimeout time.Duration `long:"chan-disable-timeout" description:"The duration that must elapse after first detecting that an already active channel is actually inactive and sending channel update disabling it to the network. The pending disable can be canceled if the peer reconnects and becomes stable for chan-enable-timeout before the disable update is sent. (default: 20m)"` - ChanStatusSampleInterval time.Duration `long:"chan-status-sample-interval" description:"The polling interval between attempts to detect if an active channel has become inactive due to its peer going offline. (default: 1m)"` + PaymentsExpirationGracePeriod time.Duration `long:"payments-expiration-grace-period" description:"A period to wait before force closing channels with outgoing htlcs that have timed-out and are a result of this node initiated payments."` + TrickleDelay int `long:"trickledelay" description:"Time in milliseconds between each release of announcements to the network"` + ChanEnableTimeout time.Duration `long:"chan-enable-timeout" description:"The duration that a peer connection must be stable before attempting to send a channel update to reenable or cancel a pending disables of the peer's channels on the network (default: 19m)."` + ChanDisableTimeout time.Duration `long:"chan-disable-timeout" description:"The duration that must elapse after first detecting that an already active channel is actually inactive and sending channel update disabling it to the network. The pending disable can be canceled if the peer reconnects and becomes stable for chan-enable-timeout before the disable update is sent. (default: 20m)"` + ChanStatusSampleInterval time.Duration `long:"chan-status-sample-interval" description:"The polling interval between attempts to detect if an active channel has become inactive due to its peer going offline. (default: 1m)"` Alias string `long:"alias" description:"The node alias. Used as a moniker by peers and intelligence services"` Color string `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"` @@ -416,15 +418,16 @@ func loadConfig() (*config, error) { "preferential": 1.0, }, }, - TrickleDelay: defaultTrickleDelay, - ChanStatusSampleInterval: defaultChanStatusSampleInterval, - ChanEnableTimeout: defaultChanEnableTimeout, - ChanDisableTimeout: defaultChanDisableTimeout, - Alias: defaultAlias, - Color: defaultColor, - MinChanSize: int64(minChanFundingSize), - NumGraphSyncPeers: defaultMinPeers, - HistoricalSyncInterval: discovery.DefaultHistoricalSyncInterval, + PaymentsExpirationGracePeriod: defaultPaymentsExpirationGracePeriod, + TrickleDelay: defaultTrickleDelay, + ChanStatusSampleInterval: defaultChanStatusSampleInterval, + ChanEnableTimeout: defaultChanEnableTimeout, + ChanDisableTimeout: defaultChanDisableTimeout, + Alias: defaultAlias, + Color: defaultColor, + MinChanSize: int64(minChanFundingSize), + NumGraphSyncPeers: defaultMinPeers, + HistoricalSyncInterval: discovery.DefaultHistoricalSyncInterval, Tor: &torConfig{ SOCKS: defaultTorSOCKS, DNS: defaultTorDNS, diff --git a/contractcourt/chain_arbitrator.go b/contractcourt/chain_arbitrator.go index add69c0f7e..552549f463 100644 --- a/contractcourt/chain_arbitrator.go +++ b/contractcourt/chain_arbitrator.go @@ -5,12 +5,14 @@ import ( "fmt" "sync" "sync/atomic" + "time" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -153,6 +155,19 @@ type ChainArbitratorConfig struct { // OnionProcessor is used to decode onion payloads for on-chain // resolution. OnionProcessor OnionProcessor + + // PaymentsExpirationGracePeriod indicates is a time window we let the + // other node to cancel an outgoing htlc that our node has initiated and + // has timed out. + PaymentsExpirationGracePeriod time.Duration + + // IsForwardedHTLC checks for a given htlc, identified by channel id and + // htlcIndex, if it is a forwarded one. + IsForwardedHTLC func(chanID lnwire.ShortChannelID, htlcIndex uint64) bool + + // Clock is the clock implementation that ChannelArbitrator uses. + // It is useful for testing. + Clock clock.Clock } // ChainArbitrator is a sub-system that oversees the on-chain resolution of all diff --git a/contractcourt/chain_arbitrator_test.go b/contractcourt/chain_arbitrator_test.go index 07c31b28d2..5710b14ae3 100644 --- a/contractcourt/chain_arbitrator_test.go +++ b/contractcourt/chain_arbitrator_test.go @@ -9,6 +9,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lnwallet" ) @@ -83,6 +84,7 @@ func TestChainArbitratorRepublishCloses(t *testing.T) { published[tx.TxHash()]++ return nil }, + Clock: clock.NewDefaultClock(), } chainArb := NewChainArbitrator( chainArbCfg, db, @@ -171,6 +173,7 @@ func TestResolveContract(t *testing.T) { PublishTx: func(tx *wire.MsgTx) error { return nil }, + Clock: clock.NewDefaultClock(), } chainArb := NewChainArbitrator( chainArbCfg, db, diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 8b6896e15a..b11c81aab9 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -6,6 +6,7 @@ import ( "fmt" "sync" "sync/atomic" + "time" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" @@ -260,6 +261,9 @@ type ChannelArbitrator struct { started int32 // To be used atomically. stopped int32 // To be used atomically. + // startTimestamp is the time when this ChannelArbitrator was started. + startTimestamp time.Time + // log is a persistent log that the attendant will use to checkpoint // its next action, and the state of any unresolved contracts. log ArbitratorLog @@ -328,6 +332,7 @@ func (c *ChannelArbitrator) Start() error { if !atomic.CompareAndSwapInt32(&c.started, 0, 1) { return nil } + c.startTimestamp = c.cfg.Clock.Now() var ( err error @@ -1132,7 +1137,29 @@ func (c *ChannelArbitrator) shouldGoOnChain(htlc channeldb.HTLC, // We should on-chain for this HTLC, iff we're within out broadcast // cutoff window. - return currentHeight >= broadcastCutOff + if currentHeight < broadcastCutOff { + return false + } + + // In case of incoming htlc we should go to chain. + if htlc.Incoming { + return true + } + + // For htlcs that are result of our initiated payments we give some grace + // period before force closing the channel. During this time we expect + // both nodes to connect and give a chance to the other node to send its + // updates and cancel the htlc. + // This shouldn't add any security risk as there is no incoming htlc to + // fulfill at this case and the expectation is that when the channel is + // active the other node will send update_fail_htlc to remove the htlc + // without closing the channel. It is up to the user to force close the + // channel if the peer misbehaves and doesn't send the update_fail_htlc. + // It is useful when this node is most of the time not online and is + // likely to miss the time slot where the htlc may be cancelled. + isForwarded := c.cfg.IsForwardedHTLC(c.cfg.ShortChanID, htlc.HtlcIndex) + upTime := c.cfg.Clock.Now().Sub(c.startTimestamp) + return isForwarded || upTime > c.cfg.PaymentsExpirationGracePeriod } // checkCommitChainActions is called for each new block connected to the end of diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index af4681a30d..9375d895bb 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -15,6 +15,7 @@ import ( "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" @@ -309,6 +310,12 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog) (*chanArbTestC return nil }, OnionProcessor: &mockOnionProcessor{}, + IsForwardedHTLC: func(chanID lnwire.ShortChannelID, + htlcIndex uint64) bool { + + return true + }, + Clock: clock.NewDefaultClock(), } // We'll use the resolvedChan to synchronize on call to @@ -1811,3 +1818,87 @@ func TestChannelArbitratorDanglingCommitForceClose(t *testing.T) { }) } } + +// TestChannelArbitratorPendingExpiredHTLC tests that if we have pending htlc +// that is expired we will only go to chain if we are running at least the +// time defined in PaymentsExpirationGracePeriod. +// During this time the remote party is expected to send his updates and cancel +// The htlc. +func TestChannelArbitratorPendingExpiredHTLC(t *testing.T) { + t.Parallel() + + // We'll create the arbitrator and its backing log in a default state. + log := &mockArbitratorLog{ + state: StateDefault, + newStates: make(chan ArbitratorState, 5), + resolvers: make(map[ContractResolver]struct{}), + } + chanArbCtx, err := createTestChannelArbitrator(t, log) + if err != nil { + t.Fatalf("unable to create ChannelArbitrator: %v", err) + } + chanArb := chanArbCtx.chanArb + + // We'll inject a test clock implementation so we can control the uptime. + startTime := time.Date(2020, time.February, 3, 13, 0, 0, 0, time.UTC) + testClock := clock.NewTestClock(startTime) + chanArb.cfg.Clock = testClock + + // We also configure the grace period and the IsForwardedHTLC to identify + // the htlc as our initiated payment. + chanArb.cfg.PaymentsExpirationGracePeriod = time.Second * 15 + chanArb.cfg.IsForwardedHTLC = func(chanID lnwire.ShortChannelID, + htlcIndex uint64) bool { + + return false + } + + if err := chanArb.Start(); err != nil { + t.Fatalf("unable to start ChannelArbitrator: %v", err) + } + defer func() { + if err := chanArb.Stop(); err != nil { + t.Fatalf("unable to stop chan arb: %v", err) + } + }() + + // Now that our channel arb has started, we'll set up + // its contract signals channel so we can send it + // various HTLC updates for this test. + htlcUpdates := make(chan *ContractUpdate) + signals := &ContractSignals{ + HtlcUpdates: htlcUpdates, + ShortChanID: lnwire.ShortChannelID{}, + } + chanArb.UpdateContractSignals(signals) + + // Next, we'll send it a new HTLC that is set to expire + // in 10 blocks. + htlcIndex := uint64(99) + htlcExpiry := uint32(10) + pendingHTLC := channeldb.HTLC{ + Incoming: false, + Amt: 10000, + HtlcIndex: htlcIndex, + RefundTimeout: htlcExpiry, + } + htlcUpdates <- &ContractUpdate{ + HtlcKey: RemoteHtlcSet, + Htlcs: []channeldb.HTLC{pendingHTLC}, + } + + // We will advance the uptime to 10 seconds which should be still within + // the grace period and should not trigger going to chain. + testClock.SetTime(startTime.Add(time.Second * 10)) + chanArbCtx.blockEpochs <- &chainntnfs.BlockEpoch{Height: 5} + chanArbCtx.AssertState(StateDefault) + + // We will advance the uptime to 16 seconds which should trigger going + // to chain. + testClock.SetTime(startTime.Add(time.Second * 16)) + chanArbCtx.blockEpochs <- &chainntnfs.BlockEpoch{Height: 6} + chanArbCtx.AssertStateTransitions( + StateBroadcastCommit, + StateCommitmentBroadcasted, + ) +} diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index b78f43b132..bdd4d446e6 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -460,6 +460,18 @@ func (s *Switch) UpdateForwardingPolicies( s.indexMtx.RUnlock() } +// IsForwardedHTLC checks for a given channel and htlc index if it is related +// to an opened circuit that represents a forwarded payment. +func (s *Switch) IsForwardedHTLC(chanID lnwire.ShortChannelID, + htlcIndex uint64) bool { + + circuit := s.circuits.LookupOpenCircuit(channeldb.CircuitKey{ + ChanID: chanID, + HtlcID: htlcIndex, + }) + return circuit != nil && circuit.Incoming.ChanID != hop.Source +} + // forward is used in order to find next channel link and apply htlc update. // Also this function is used by channel links itself in order to forward the // update after it has been included in the channel. diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index 28493c831b..5a8ace217a 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -322,6 +322,10 @@ func TestSwitchForward(t *testing.T) { t.Fatal("wrong amount of circuits") } + if !s.IsForwardedHTLC(bobChannelLink.ShortChanID(), 0) { + t.Fatal("htlc should be identified as forwarded") + } + // Create settle request pretending that bob link handled the add htlc // request and sent the htlc settle request back. This request should // be forwarder back to Alice link. @@ -1892,6 +1896,9 @@ func TestSwitchSendPayment(t *testing.T) { t.Fatalf("unable obfuscate failure: %v", err) } + if s.IsForwardedHTLC(aliceChannelLink.ShortChanID(), update.ID) { + t.Fatal("htlc should be identified as not forwarded") + } packet := &htlcPacket{ outgoingChanID: aliceChannelLink.ShortChanID(), outgoingHTLCID: 0, diff --git a/server.go b/server.go index a5538483d8..9ce272f248 100644 --- a/server.go +++ b/server.go @@ -915,11 +915,14 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, return ErrServerShuttingDown } }, - DisableChannel: s.chanStatusMgr.RequestDisable, - Sweeper: s.sweeper, - Registry: s.invoices, - NotifyClosedChannel: s.channelNotifier.NotifyClosedChannelEvent, - OnionProcessor: s.sphinx, + DisableChannel: s.chanStatusMgr.RequestDisable, + Sweeper: s.sweeper, + Registry: s.invoices, + NotifyClosedChannel: s.channelNotifier.NotifyClosedChannelEvent, + OnionProcessor: s.sphinx, + PaymentsExpirationGracePeriod: cfg.PaymentsExpirationGracePeriod, + IsForwardedHTLC: s.htlcSwitch.IsForwardedHTLC, + Clock: clock.NewDefaultClock(), }, chanDB) s.breachArbiter = newBreachArbiter(&BreachConfig{ diff --git a/test_utils.go b/test_utils.go index afb16cd54b..11c025e2c9 100644 --- a/test_utils.go +++ b/test_utils.go @@ -17,6 +17,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" @@ -360,6 +361,12 @@ func createTestPeer(notifier chainntnfs.ChainNotifier, publTx chan *wire.MsgTx, contractcourt.ChainArbitratorConfig{ Notifier: notifier, ChainIO: chainIO, + IsForwardedHTLC: func(chanID lnwire.ShortChannelID, + htlcIndex uint64) bool { + + return true + }, + Clock: clock.NewDefaultClock(), }, dbAlice, ) chainArb.WatchNewChannel(aliceChannelState) From 746fdd3d30274a5a2e3cf6f3e2e59e6c7fd3e21c Mon Sep 17 00:00:00 2001 From: carla Date: Sun, 16 Feb 2020 14:49:35 +0200 Subject: [PATCH 081/562] gosum: tidy up old btcwallet dependencies Run go mod tidy to clean up dependencies that were upgraded in #3927. --- go.sum | 4 ---- 1 file changed, 4 deletions(-) diff --git a/go.sum b/go.sum index b22de20a5d..e2abfb2006 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,6 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.11.0 h1:XhwqdhEchy5a0q6R+y3F82roD2hYycPCHovgNyJS08w= -github.com/btcsuite/btcwallet v0.11.0/go.mod h1:qtPAohN1ioo0pvJt/j7bZM8ANBWlYWVCVFL0kkijs7s= github.com/btcsuite/btcwallet v0.11.1-0.20200124023827-704cd189ac23 h1:WDhq9qH16fXAQVg0MO0AAHXtzgSAyVd5Z56vq8WwYHY= github.com/btcsuite/btcwallet v0.11.1-0.20200124023827-704cd189ac23/go.mod h1:1O1uRHMPXHdwA4/od8nqYqrgclVKp+wtfXUAqHmeRvE= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= @@ -38,8 +36,6 @@ github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0 h1:6DxkcoMnCPY4E9cUDPB5tbuuf github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= github.com/btcsuite/btcwallet/walletdb v1.0.0 h1:mheT7vCWK5EP6rZzhxsQ7ms9+yX4VE8bwiJctECBeNw= github.com/btcsuite/btcwallet/walletdb v1.0.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= -github.com/btcsuite/btcwallet/walletdb v1.1.0 h1:JHAL7wZ8pX4SULabeAv/wPO9sseRWMGzE80lfVmRw6Y= -github.com/btcsuite/btcwallet/walletdb v1.1.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= github.com/btcsuite/btcwallet/walletdb v1.2.0 h1:E0+M4jHOToAvGWZ27ew5AaDAHDi6fUiXkjUJUnoEOD0= github.com/btcsuite/btcwallet/walletdb v1.2.0/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= github.com/btcsuite/btcwallet/wtxmgr v1.0.0 h1:aIHgViEmZmZfe0tQQqF1xyd2qBqFWxX5vZXkkbjtbeA= From cdf3a49c5455c54bc913b7ebb5209de8a18a829b Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 18 Feb 2020 13:01:57 +0100 Subject: [PATCH 082/562] channeldb: remove unused payments status serialization --- channeldb/payments.go | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/channeldb/payments.go b/channeldb/payments.go index c3c093269c..a03c9e0c75 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -3,7 +3,6 @@ package channeldb import ( "bytes" "encoding/binary" - "errors" "fmt" "io" "sort" @@ -154,27 +153,6 @@ const ( StatusFailed PaymentStatus = 3 ) -// Bytes returns status as slice of bytes. -func (ps PaymentStatus) Bytes() []byte { - return []byte{byte(ps)} -} - -// FromBytes sets status from slice of bytes. -func (ps *PaymentStatus) FromBytes(status []byte) error { - if len(status) != 1 { - return errors.New("payment status is empty") - } - - switch PaymentStatus(status[0]) { - case StatusUnknown, StatusInFlight, StatusSucceeded, StatusFailed: - *ps = PaymentStatus(status[0]) - default: - return errors.New("unknown payment status") - } - - return nil -} - // String returns readable representation of payment status. func (ps PaymentStatus) String() string { switch ps { From 3b5d12fd6c81a27dc3e30b560d1eb8fb8399f15e Mon Sep 17 00:00:00 2001 From: fguisso Date: Mon, 17 Feb 2020 18:21:01 -0300 Subject: [PATCH 083/562] make: remove remaining wtclientrpc flags --- .golangci.yml | 1 - make/testing_flags.mk | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 2051938b29..b3289f16b5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -21,7 +21,6 @@ run: - signrpc - walletrpc - watchtowerrpc - - wtclientrpc linters-settings: govet: diff --git a/make/testing_flags.mk b/make/testing_flags.mk index 22b5926eb6..e4f5661c0d 100644 --- a/make/testing_flags.mk +++ b/make/testing_flags.mk @@ -61,6 +61,6 @@ backend = btcd endif # Construct the integration test command with the added build flags. -ITEST_TAGS := $(DEV_TAGS) rpctest chainrpc walletrpc signrpc invoicesrpc autopilotrpc routerrpc watchtowerrpc wtclientrpc $(backend) +ITEST_TAGS := $(DEV_TAGS) rpctest chainrpc walletrpc signrpc invoicesrpc autopilotrpc routerrpc watchtowerrpc $(backend) ITEST := rm lntest/itest/*.log; date; $(GOTEST) -v ./lntest/itest -tags="$(ITEST_TAGS)" $(TEST_FLAGS) -logoutput -goroutinedump From d091f24316c2ee68ca1275bb8ab4efe7a07dcb89 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 18 Feb 2020 16:56:19 -0800 Subject: [PATCH 084/562] build: update to latest btcwallet version with rescan addr fix In this commit, we update to the latest `btcwallet` version that includes a fix for how we perform rescans. Before this commit, the wallet would load ALL the created keys into the wallet to perform a rescan. This is unnecessary, as many of the keys we create are actually used in contracts, so the wallet can't spend them directly anyway. For neutrino nodes, this would've caused them to attempt o match more items in the filter than necessary, possibly resulting in an increased number of false positive block fetches. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d1a887a2b5..63b5e7dbc0 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d - github.com/btcsuite/btcwallet v0.11.1-0.20200124023827-704cd189ac23 + github.com/btcsuite/btcwallet v0.11.1-0.20200219004649-ae9416ad7623 github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 github.com/btcsuite/btcwallet/walletdb v1.2.0 diff --git a/go.sum b/go.sum index e2abfb2006..b8991183ef 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.11.1-0.20200124023827-704cd189ac23 h1:WDhq9qH16fXAQVg0MO0AAHXtzgSAyVd5Z56vq8WwYHY= -github.com/btcsuite/btcwallet v0.11.1-0.20200124023827-704cd189ac23/go.mod h1:1O1uRHMPXHdwA4/od8nqYqrgclVKp+wtfXUAqHmeRvE= +github.com/btcsuite/btcwallet v0.11.1-0.20200219004649-ae9416ad7623 h1:ZuJRjucNsTmlrbZncsqzD0z3EaXrOobCx2I4lc12R4g= +github.com/btcsuite/btcwallet v0.11.1-0.20200219004649-ae9416ad7623/go.mod h1:1O1uRHMPXHdwA4/od8nqYqrgclVKp+wtfXUAqHmeRvE= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= From 05fb272deb3bddffab38708a792d5a18171f6289 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:41 +0100 Subject: [PATCH 085/562] lnwallet/channel: make validateCommitmentSanity take our/their predict add To ba able to validate the commitment sanity both for remote and local commitments, and at the same time predict both our and their add, we let validateCommitmentSanity take an extra payment descriptor to make this possible. --- lnwallet/channel.go | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index fb774c1a5a..9519e7fe15 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -3103,12 +3103,13 @@ func (lc *LightningChannel) getUnsignedAckedUpdates() []channeldb.LogUpdate { // validateCommitmentSanity is used to validate the current state of the // commitment transaction in terms of the ChannelConstraints that we and our -// remote peer agreed upon during the funding workflow. The predictAdded -// parameter should be set to a valid PaymentDescriptor if we are validating -// in the state when adding a new HTLC, or nil otherwise. +// remote peer agreed upon during the funding workflow. The +// predict[Our|Their]Add should parameters should be set to a valid +// PaymentDescriptor if we are validating in the state when adding a new HTLC, +// or nil otherwise. func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter, ourLogCounter uint64, remoteChain bool, - predictAdded *PaymentDescriptor) error { + predictOurAdd, predictTheirAdd *PaymentDescriptor) error { // Fetch all updates not committed. view := lc.fetchHTLCView(theirLogCounter, ourLogCounter) @@ -3116,14 +3117,11 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter, // If we are checking if we can add a new HTLC, we add this to the // appropriate update log, in order to validate the sanity of the // commitment resulting from _actually adding_ this HTLC to the state. - if predictAdded != nil { - // If the remoteChain bool is true, add to ourUpdates. - if remoteChain { - view.ourUpdates = append(view.ourUpdates, predictAdded) - } else { - // Else add to theirUpdates. - view.theirUpdates = append(view.theirUpdates, predictAdded) - } + if predictOurAdd != nil { + view.ourUpdates = append(view.ourUpdates, predictOurAdd) + } + if predictTheirAdd != nil { + view.theirUpdates = append(view.theirUpdates, predictTheirAdd) } commitChain := lc.localCommitChain @@ -3296,7 +3294,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig, []ch // party set up when we initially set up the channel. If we are, then // we'll abort this state transition. err := lc.validateCommitmentSanity( - remoteACKedIndex, lc.localUpdateLog.logIndex, true, nil, + remoteACKedIndex, lc.localUpdateLog.logIndex, true, nil, nil, ) if err != nil { return sig, htlcSigs, nil, err @@ -4050,7 +4048,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig, // the constraints we specified during initial channel setup. If not, // then we'll abort the channel as they've violated our constraints. err := lc.validateCommitmentSanity( - lc.remoteUpdateLog.logIndex, localACKedIndex, false, nil, + lc.remoteUpdateLog.logIndex, localACKedIndex, false, nil, nil, ) if err != nil { return err @@ -4647,7 +4645,7 @@ func (lc *LightningChannel) AddHTLC(htlc *lnwire.UpdateAddHTLC, // must keep on our commitment transaction. remoteACKedIndex := lc.localCommitChain.tail().theirMessageIndex err := lc.validateCommitmentSanity( - remoteACKedIndex, lc.localUpdateLog.logIndex, true, pd, + remoteACKedIndex, lc.localUpdateLog.logIndex, true, pd, nil, ) if err != nil { return 0, err @@ -4685,7 +4683,7 @@ func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64, err // Clamp down on the number of HTLC's we can receive by checking the // commitment sanity. err := lc.validateCommitmentSanity( - lc.remoteUpdateLog.logIndex, localACKedIndex, false, pd, + lc.remoteUpdateLog.logIndex, localACKedIndex, false, nil, pd, ) if err != nil { return 0, err From 4ea822efeb18fda284304bf20ceb015296c719c8 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:41 +0100 Subject: [PATCH 086/562] lnwallet tests: add test for dipping remote below chan reserve This commit adds a test that was previously not performed, namely that adding a HTLC would dip the remote initiator below its channel reserve. --- lnwallet/channel_test.go | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 7cd5aa9f12..3f97f9f9d7 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -6007,6 +6007,60 @@ func TestChanReserve(t *testing.T) { ) } +// TestChanReserveRemoteInitiator tests that the channel reserve of the +// initiator is accounted for when adding HTLCs, whether the initiator is the +// local or remote node. +func TestChanReserveRemoteInitiator(t *testing.T) { + t.Parallel() + + // We start out with a channel where both parties have 5 BTC. + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + true, + ) + if err != nil { + t.Fatal(err) + } + defer cleanUp() + + // Set Alice's channel reserve to be 5 BTC-commitfee. This means she + // has just enough balance to cover the comitment fee, but not enough + // to add any more HTLCs to the commitment. Although a reserve this + // high is unrealistic, a channel can easiliy get into a situation + // where the initiator cannot pay for the fee of any more HTLCs. + commitFee := aliceChannel.channelState.LocalCommitment.CommitFee + aliceMinReserve := 5*btcutil.SatoshiPerBitcoin - commitFee + + aliceChannel.channelState.LocalChanCfg.ChanReserve = aliceMinReserve + bobChannel.channelState.RemoteChanCfg.ChanReserve = aliceMinReserve + + // Now let Bob attempt to add an HTLC of 0.1 BTC. He has plenty of + // money available to spend, but Alice, which is the initiator, cannot + // afford any more HTLCs on the commitment transaction because that + // would take here below her channel reserve.. + htlcAmt := lnwire.NewMSatFromSatoshis(0.1 * btcutil.SatoshiPerBitcoin) + htlc, _ := createHTLC(0, htlcAmt) + + // Bob should refuse to add this HTLC, since he realizes it will create + // an invalid commitment. + _, err = bobChannel.AddHTLC(htlc, nil) + if err != ErrBelowChanReserve { + t.Fatalf("expected ErrBelowChanReserve, instead received: %v", + err) + } + + // Of course Alice will also not have enough balance to add it herself. + _, err = aliceChannel.AddHTLC(htlc, nil) + if err != ErrBelowChanReserve { + t.Fatalf("expected ErrBelowChanReserve, instead received: %v", + err) + } + + // Same for Alice, she should refuse to accept this second HTLC. + if _, err := aliceChannel.ReceiveHTLC(htlc); err != ErrBelowChanReserve { + t.Fatalf("expected ErrBelowChanReserve, instead received: %v", err) + } +} + // TestMinHTLC tests that the ErrBelowMinHTLC error is thrown if an HTLC is added // that is below the minimm allowed value for HTLCs. func TestMinHTLC(t *testing.T) { From 0d9a1b865621c918820a885007b21da8e4ddcd1b Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:41 +0100 Subject: [PATCH 087/562] lnwallet: check local commitment sanity when adding HTLC This commit adds an extra validation step when adding HTLCs. Previously we would only validate the remote commitment resulting from adding an HTLC, which in most cases is enough. However, there are situations where the dustlimits are different, which could lead to the resulting remote commitment from adding the HTLC being valid, but not the local commitment. Now we also validate the local commitment. A test to trigger the case is added. --- lnwallet/channel.go | 18 +++++++++++++++- lnwallet/channel_test.go | 45 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 9519e7fe15..8b25936564 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -4642,8 +4642,11 @@ func (lc *LightningChannel) AddHTLC(htlc *lnwire.UpdateAddHTLC, } // Make sure adding this HTLC won't violate any of the constraints we - // must keep on our commitment transaction. + // must keep on the commitment transactions. remoteACKedIndex := lc.localCommitChain.tail().theirMessageIndex + + // First we'll check whether this HTLC can be added to the remote + // commitment transaction without violation any of the constraints. err := lc.validateCommitmentSanity( remoteACKedIndex, lc.localUpdateLog.logIndex, true, pd, nil, ) @@ -4651,6 +4654,19 @@ func (lc *LightningChannel) AddHTLC(htlc *lnwire.UpdateAddHTLC, return 0, err } + // We must also check whether it can be added to our own commitment + // transaction, or the remote node will refuse to sign. This is not + // totally bullet proof, as the remote might be adding updates + // concurrently, but if we fail this check there is for sure not + // possible for us to add the HTLC. + err = lc.validateCommitmentSanity( + lc.remoteUpdateLog.logIndex, lc.localUpdateLog.logIndex, + false, pd, nil, + ) + if err != nil { + return 0, err + } + lc.localUpdateLog.appendHtlc(pd) return pd.HtlcIndex, nil diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 3f97f9f9d7..e9455b7543 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -6061,6 +6061,51 @@ func TestChanReserveRemoteInitiator(t *testing.T) { } } +// TestChanReserveLocalInitiatorDustHtlc tests that fee the initiator must pay +// when adding HTLCs is accounted for, even though the HTLC is considered dust +// by the remote bode. +func TestChanReserveLocalInitiatorDustHtlc(t *testing.T) { + t.Parallel() + + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + true, + ) + if err != nil { + t.Fatal(err) + } + defer cleanUp() + + // The amount of the HTLC should not be considered dust according to + // Alice's dust limit (200 sat), but be dust according to Bob's dust + // limit (1300 sat). It is considered dust if the amount remaining + // after paying the HTLC fee is below the dustlimit, so we choose a + // size of 500+htlcFee. + htlcSat := btcutil.Amount(500) + htlcTimeoutFee( + chainfee.SatPerKWeight( + aliceChannel.channelState.LocalCommitment.FeePerKw, + ), + ) + + // Set Alice's channel reserve to be low enough to carry the value of + // the HTLC, but not low enough to allow the extra fee from adding the + // HTLC to the commitment. + commitFee := aliceChannel.channelState.LocalCommitment.CommitFee + aliceMinReserve := 5*btcutil.SatoshiPerBitcoin - commitFee - htlcSat + + aliceChannel.channelState.LocalChanCfg.ChanReserve = aliceMinReserve + bobChannel.channelState.RemoteChanCfg.ChanReserve = aliceMinReserve + + htlcDustAmt := lnwire.NewMSatFromSatoshis(htlcSat) + htlc, _ := createHTLC(0, htlcDustAmt) + + // Alice should realize that the fee she must pay to add this HTLC to + // the local commitment would take her below the channel reserve. + _, err = aliceChannel.AddHTLC(htlc, nil) + if err != ErrBelowChanReserve { + t.Fatalf("expected ErrBelowChanReserve, instead received: %v", err) + } +} + // TestMinHTLC tests that the ErrBelowMinHTLC error is thrown if an HTLC is added // that is below the minimm allowed value for HTLCs. func TestMinHTLC(t *testing.T) { From 58dec106800a90def81f9dbd52c08808a58c83f9 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:41 +0100 Subject: [PATCH 088/562] lnwallet/channel: break up availableBalance --- lnwallet/channel.go | 58 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 8b25936564..074c8bf2c5 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -5997,11 +5997,14 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte, return closeTx, ourBalance, nil } -// AvailableBalance returns the current available balance within the channel. -// By available balance, we mean that if at this very instance s new commitment -// were to be created which evals all the log entries, what would our available -// balance me. This method is useful when deciding if a given channel can -// accept an HTLC in the multi-hop forwarding scenario. +// AvailableBalance returns the current balance available for sending within +// the channel. By available balance, we mean that if at this very instance a +// new commitment were to be created which evals all the log entries, what +// would our available balance for adding an additional HTLC be. It takes into +// account the fee that must be paid for adding this HTLC (if we're the +// initiator), and that we cannot spend from the channel reserve. This method +// is useful when deciding if a given channel can accept an HTLC in the +// multi-hop forwarding scenario. func (lc *LightningChannel) AvailableBalance() lnwire.MilliSatoshi { lc.RLock() defer lc.RUnlock() @@ -6021,19 +6024,50 @@ func (lc *LightningChannel) availableBalance() (lnwire.MilliSatoshi, int64) { htlcView := lc.fetchHTLCView(remoteACKedIndex, lc.localUpdateLog.logIndex) - // Then compute our current balance for that view. - ourBalance, _, commitWeight, filteredView, err := - lc.computeView(htlcView, false, false) + // Calculate our available balance from our local commitment. + // + // NOTE: This is not always accurate, since the remote node can always + // add updates concurrently, causing our balance to go down if we're + // the initiator, but this is a problem on the protocol level. + ourLocalCommitBalance, commitWeight := lc.availableCommitmentBalance( + htlcView, + ) + + return ourLocalCommitBalance, commitWeight +} + +// availableCommitmentBalance attempts to calculate the balance we have +// available for HTLCs on the local/remote commitment given the htlcView. To +// account for sending HTLCs of different sizes, it will report the balance +// available for sending non-dust HTLCs, which will be manifested on the +// commitment, increasing the commitment fee we must pay as an initiator, +// eating into our balance. It will make sure we won't violate the channel +// reserve constraints for this amount. +func (lc *LightningChannel) availableCommitmentBalance(view *htlcView) ( + lnwire.MilliSatoshi, int64) { + + // Compute the current balances for this commitment. This will take + // into account HTLCs to determine the commit weight, which the + // initiator must pay the fee for. + ourBalance, _, commitWeight, filteredView, err := lc.computeView( + view, false, false, + ) if err != nil { lc.log.Errorf("Unable to fetch available balance: %v", err) return 0, 0 } - // If we are the channel initiator, we must remember to subtract the - // commitment fee from our available balance. - commitFee := filteredView.feePerKw.FeeForWeight(commitWeight) + // Given the commitment weight, find the commitment fee in case of no + // added HTLC output. + feePerKw := filteredView.feePerKw + baseCommitFee := lnwire.NewMSatFromSatoshis( + feePerKw.FeeForWeight(commitWeight), + ) + + // If we are the channel initiator, we must to subtract the commitment + // fee from our available balance. if lc.channelState.IsInitiator { - ourBalance -= lnwire.NewMSatFromSatoshis(commitFee) + ourBalance -= baseCommitFee } return ourBalance, commitWeight From 5e89d5b6c2f402664e36e03dabe3822f56785bf7 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:42 +0100 Subject: [PATCH 089/562] link+lnwallet: move bandwidth channel reserve validation into channel Since we want to handle the edge case where paying the HTLC fee would take the initiator below the reserve, we move the subtraction of the reserve into availableBalance where this calculation will be performed. --- htlcswitch/link.go | 17 ++++++----------- lnwallet/channel.go | 19 +++++++++++++++++-- lnwallet/channel_test.go | 13 ++++++++++--- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 80b90f4832..e127cfa13a 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -2127,26 +2127,21 @@ func (l *channelLink) ChanID() lnwire.ChannelID { // // NOTE: Part of the ChannelLink interface. func (l *channelLink) Bandwidth() lnwire.MilliSatoshi { + // Get the balance available on the channel for new HTLCs. This takes + // the channel reserve into account so HTLCs up to this value won't + // violate it. channelBandwidth := l.channel.AvailableBalance() - overflowBandwidth := l.overflowQueue.TotalHtlcAmount() // To compute the total bandwidth, we'll take the current available // bandwidth, then subtract the overflow bandwidth as we'll eventually // also need to evaluate those HTLC's once space on the commitment // transaction is free. - linkBandwidth := channelBandwidth - overflowBandwidth - - // If the channel reserve is greater than the total available balance - // of the link, just return 0. - reserve := lnwire.NewMSatFromSatoshis(l.channel.LocalChanReserve()) - if linkBandwidth < reserve { + overflowBandwidth := l.overflowQueue.TotalHtlcAmount() + if channelBandwidth < overflowBandwidth { return 0 } - // Else the amount that is available to flow through the link at this - // point is the available balance minus the reserve amount we are - // required to keep as collateral. - return linkBandwidth - reserve + return channelBandwidth - overflowBandwidth } // AttachMailBox updates the current mailbox used by this link, and hooks up diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 074c8bf2c5..f8512d72a6 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -6057,6 +6057,17 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView) ( return 0, 0 } + // We can never spend from the channel reserve, so we'll subtract it + // from our available balance. + ourReserve := lnwire.NewMSatFromSatoshis( + lc.channelState.LocalChanCfg.ChanReserve, + ) + if ourReserve <= ourBalance { + ourBalance -= ourReserve + } else { + ourBalance = 0 + } + // Given the commitment weight, find the commitment fee in case of no // added HTLC output. feePerKw := filteredView.feePerKw @@ -6067,6 +6078,9 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView) ( // If we are the channel initiator, we must to subtract the commitment // fee from our available balance. if lc.channelState.IsInitiator { + if ourBalance < baseCommitFee { + return 0, commitWeight + } ourBalance -= baseCommitFee } @@ -6278,13 +6292,14 @@ func (lc *LightningChannel) MaxFeeRate(maxAllocation float64) chainfee.SatPerKWe // The maximum fee depends of the available balance that can be // committed towards fees. - balance, weight := lc.availableBalance() + commit := lc.channelState.LocalCommitment feeBalance := float64( - balance.ToSatoshis() + lc.channelState.LocalCommitment.CommitFee, + commit.LocalBalance.ToSatoshis() + commit.CommitFee, ) maxFee := feeBalance * maxAllocation // Ensure the fee rate doesn't dip below the fee floor. + _, weight := lc.availableBalance() maxFeeRate := maxFee / (float64(weight) / 1000) return chainfee.SatPerKWeight( math.Max(maxFeeRate, float64(chainfee.FeePerKwFloor)), diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index e9455b7543..77af8d3faf 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -4599,6 +4599,10 @@ func TestChanAvailableBandwidth(t *testing.T) { } defer cleanUp() + aliceReserve := lnwire.NewMSatFromSatoshis( + aliceChannel.channelState.LocalChanCfg.ChanReserve, + ) + assertBandwidthEstimateCorrect := func(aliceInitiate bool) { // With the HTLC's added, we'll now query the AvailableBalance // method for the current available channel bandwidth from @@ -4625,11 +4629,14 @@ func TestChanAvailableBandwidth(t *testing.T) { // Now, we'll obtain the current available bandwidth in Alice's // latest commitment and compare that to the prior estimate. aliceBalance := aliceChannel.channelState.LocalCommitment.LocalBalance - if aliceBalance != aliceAvailableBalance { + + // The balance we have available for new HTLCs should be the + // current local commitment balance, minus the channel reserve. + expBalance := aliceBalance - aliceReserve + if expBalance != aliceAvailableBalance { _, _, line, _ := runtime.Caller(1) t.Fatalf("line: %v, incorrect balance: expected %v, "+ - "got %v", line, aliceBalance, - aliceAvailableBalance) + "got %v", line, expBalance, aliceAvailableBalance) } } From 9ff79ae59517c34444d66c4a13e802b0cdac52d5 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:42 +0100 Subject: [PATCH 090/562] lnwallet/channel: account for HTLC fee when reporting available balance --- htlcswitch/link_test.go | 23 ++++--- lnwallet/channel.go | 26 +++++--- lnwallet/channel_test.go | 135 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 166 insertions(+), 18 deletions(-) diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 427322ee9e..ca31d68d75 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -1982,8 +1982,11 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { ) // The starting bandwidth of the channel should be exactly the amount - // that we created the channel between her and Bob. - expectedBandwidth := lnwire.NewMSatFromSatoshis(chanAmt - defaultCommitFee) + // that we created the channel between her and Bob, minus the + // commitment fee and fee for adding an additional HTLC. + expectedBandwidth := lnwire.NewMSatFromSatoshis( + chanAmt-defaultCommitFee, + ) - htlcFee assertLinkBandwidth(t, aliceLink, expectedBandwidth) // Next, we'll create an HTLC worth 1 BTC, and send it into the link as @@ -2656,8 +2659,10 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // The starting bandwidth of the channel should be exactly the amount // that we created the channel between her and Bob, minus the commitment - // fee. - expectedBandwidth := lnwire.NewMSatFromSatoshis(chanAmt - defaultCommitFee) + // fee and fee of adding an HTLC. + expectedBandwidth := lnwire.NewMSatFromSatoshis( + chanAmt-defaultCommitFee, + ) - htlcFee assertLinkBandwidth(t, alice.link, expectedBandwidth) // Capture Alice's starting bandwidth to perform later, relative @@ -2935,8 +2940,10 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { // The starting bandwidth of the channel should be exactly the amount // that we created the channel between her and Bob, minus the commitment - // fee. - expectedBandwidth := lnwire.NewMSatFromSatoshis(chanAmt - defaultCommitFee) + // fee and fee for adding an additional HTLC. + expectedBandwidth := lnwire.NewMSatFromSatoshis( + chanAmt-defaultCommitFee, + ) - htlcFee assertLinkBandwidth(t, alice.link, expectedBandwidth) // Capture Alice's starting bandwidth to perform later, relative @@ -3191,9 +3198,9 @@ func TestChannelLinkBandwidthChanReserve(t *testing.T) { // The starting bandwidth of the channel should be exactly the amount // that we created the channel between her and Bob, minus the channel - // reserve. + // reserve, commitment fee and fee for adding an additional HTLC. expectedBandwidth := lnwire.NewMSatFromSatoshis( - chanAmt - defaultCommitFee - chanReserve) + chanAmt-defaultCommitFee-chanReserve) - htlcFee assertLinkBandwidth(t, aliceLink, expectedBandwidth) // Next, we'll create an HTLC worth 3 BTC, and send it into the link as diff --git a/lnwallet/channel.go b/lnwallet/channel.go index f8512d72a6..f3368218ea 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -6068,20 +6068,30 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView) ( ourBalance = 0 } - // Given the commitment weight, find the commitment fee in case of no - // added HTLC output. + // Calculate the commitment fee in the case where we would add another + // HTLC to the commitment, as only the balance remaining after this fee + // has been paid is actually available for sending. feePerKw := filteredView.feePerKw - baseCommitFee := lnwire.NewMSatFromSatoshis( - feePerKw.FeeForWeight(commitWeight), + htlcCommitFee := lnwire.NewMSatFromSatoshis( + feePerKw.FeeForWeight(commitWeight + input.HTLCWeight), ) - // If we are the channel initiator, we must to subtract the commitment - // fee from our available balance. + // If we are the channel initiator, we must to subtract this commitment + // fee from our available balance in order to ensure we can afford both + // the value of the HTLC and the additional commitment fee from adding + // the HTLC. if lc.channelState.IsInitiator { - if ourBalance < baseCommitFee { + // There is an edge case where our non-zero balance is lower + // than the htlcCommitFee, where we could still be sending dust + // HTLCs, but we return 0 in this case. This is to avoid + // lowering our balance even further, as this takes us into a + // bad state wehere neither we nor our channel counterparty can + // add HTLCs. + if ourBalance < htlcCommitFee { return 0, commitWeight } - ourBalance -= baseCommitFee + + ourBalance -= htlcCommitFee } return ourBalance, commitWeight diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 77af8d3faf..0969762958 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -4602,6 +4602,12 @@ func TestChanAvailableBandwidth(t *testing.T) { aliceReserve := lnwire.NewMSatFromSatoshis( aliceChannel.channelState.LocalChanCfg.ChanReserve, ) + feeRate := chainfee.SatPerKWeight( + aliceChannel.channelState.LocalCommitment.FeePerKw, + ) + htlcFee := lnwire.NewMSatFromSatoshis( + feeRate.FeeForWeight(input.HTLCWeight), + ) assertBandwidthEstimateCorrect := func(aliceInitiate bool) { // With the HTLC's added, we'll now query the AvailableBalance @@ -4631,8 +4637,9 @@ func TestChanAvailableBandwidth(t *testing.T) { aliceBalance := aliceChannel.channelState.LocalCommitment.LocalBalance // The balance we have available for new HTLCs should be the - // current local commitment balance, minus the channel reserve. - expBalance := aliceBalance - aliceReserve + // current local commitment balance, minus the channel reserve + // and the fee for adding an HTLC. + expBalance := aliceBalance - aliceReserve - htlcFee if expBalance != aliceAvailableBalance { _, _, line, _ := runtime.Caller(1) t.Fatalf("line: %v, incorrect balance: expected %v, "+ @@ -4714,6 +4721,130 @@ func TestChanAvailableBandwidth(t *testing.T) { // TODO(roasbeef): additional tests from diff starting conditions } +// TestChanAvailableBalanceNearHtlcFee checks that we get the expected reported +// balance when it is close to the htlc fee. +func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { + t.Parallel() + + // Create a test channel which will be used for the duration of this + // unittest. The channel will be funded evenly with Alice having 5 BTC, + // and Bob having 5 BTC. + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + if err != nil { + t.Fatalf("unable to create test channels: %v", err) + } + defer cleanUp() + + // Alice starts with half the channel capacity. + aliceBalance := lnwire.NewMSatFromSatoshis(5 * btcutil.SatoshiPerBitcoin) + + aliceReserve := lnwire.NewMSatFromSatoshis( + aliceChannel.channelState.LocalChanCfg.ChanReserve, + ) + + aliceDustlimit := lnwire.NewMSatFromSatoshis( + aliceChannel.channelState.LocalChanCfg.DustLimit, + ) + feeRate := chainfee.SatPerKWeight( + aliceChannel.channelState.LocalCommitment.FeePerKw, + ) + htlcFee := lnwire.NewMSatFromSatoshis( + feeRate.FeeForWeight(input.HTLCWeight), + ) + commitFee := lnwire.NewMSatFromSatoshis( + aliceChannel.channelState.LocalCommitment.CommitFee, + ) + htlcTimeoutFee := lnwire.NewMSatFromSatoshis( + htlcTimeoutFee(feeRate), + ) + + // Helper method to check the current reported balance. + checkBalance := func(t *testing.T, expBalanceAlice lnwire.MilliSatoshi) { + t.Helper() + balance := aliceChannel.AvailableBalance() + if balance != expBalanceAlice { + t.Fatalf("Expected balance %v, got %v", expBalanceAlice, + balance) + } + } + + // Helper method to send an HTLC from Alice to Bob, decreasing Alice's + // balance. + htlcIndex := uint64(0) + sendHtlc := func(htlcAmt lnwire.MilliSatoshi) { + t.Helper() + + htlc, preImage := createHTLC(int(htlcIndex), htlcAmt) + if _, err := aliceChannel.AddHTLC(htlc, nil); err != nil { + t.Fatalf("unable to add htlc: %v", err) + } + if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { + t.Fatalf("unable to recv htlc: %v", err) + } + + if err := ForceStateTransition(aliceChannel, bobChannel); err != nil { + t.Fatalf("unable to complete alice's state "+ + "transition: %v", err) + } + + err = bobChannel.SettleHTLC(preImage, htlcIndex, nil, nil, nil) + if err != nil { + t.Fatalf("unable to settle htlc: %v", err) + } + err = aliceChannel.ReceiveHTLCSettle(preImage, htlcIndex) + if err != nil { + t.Fatalf("unable to settle htlc: %v", err) + } + + if err := ForceStateTransition(aliceChannel, bobChannel); err != nil { + t.Fatalf("unable to complete alice's state "+ + "transition: %v", err) + } + + htlcIndex++ + aliceBalance -= htlcAmt + } + + // Balance should start out equal to half the channel capacity minus + // the commitment fee Alice must pay and the channel reserve. In + // addition the HTLC fee will be subtracted fromt the balance to + // reflect that this value must be reserved for any payment above the + // dust limit. + expAliceBalance := aliceBalance - commitFee - aliceReserve - htlcFee + checkBalance(t, expAliceBalance) + + // Find the minumim size of a non-dust HTLC. + aliceNonDustHtlc := aliceDustlimit + htlcTimeoutFee + + // Send a HTLC leaving the remaining balance just enough to have + // nonDustHtlc left after paying the commit fee and htlc fee. + htlcAmt := aliceBalance - (commitFee + aliceReserve + htlcFee + aliceNonDustHtlc) + sendHtlc(htlcAmt) + + // Now the real balance left will be + // nonDustHtlc+commitfee+aliceReserve+htlcfee. The available balance + // reported will just be nonDustHtlc, since the rest of the balance is + // reserved. + expAliceBalance = aliceNonDustHtlc + checkBalance(t, expAliceBalance) + + // Send an HTLC using all but one msat of the reported balance. + htlcAmt = aliceNonDustHtlc - 1 + sendHtlc(htlcAmt) + + // 1 msat should be left. + expAliceBalance = 1 + checkBalance(t, expAliceBalance) + + // Sendng the last msat. + htlcAmt = 1 + sendHtlc(htlcAmt) + + // No balance left. + expAliceBalance = 0 + checkBalance(t, expAliceBalance) +} + // TestSignCommitmentFailNotLockedIn tests that a channel will not attempt to // create a new state if it doesn't yet know of the next revocation point for // the remote party. From f94464d987468757763a90f66a7a3f23ecfc6a2b Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:42 +0100 Subject: [PATCH 091/562] lnwallet: take remote initiator's balance into account When we send non-dust HTLCs as the non-initiator, the remote party will have to pay the extra commitment fee. To account for this we figure out if they can afford paying this fee, if not we report that we only have balance available for dust HTLCs, since these HTLCs won't increase the commitment fee. --- lnwallet/channel.go | 39 ++++++++++++++++++++-- lnwallet/channel_test.go | 72 ++++++++++++++++++++++++++++++++++------ 2 files changed, 98 insertions(+), 13 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index f3368218ea..0cc512d5e2 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -6049,7 +6049,7 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView) ( // Compute the current balances for this commitment. This will take // into account HTLCs to determine the commit weight, which the // initiator must pay the fee for. - ourBalance, _, commitWeight, filteredView, err := lc.computeView( + ourBalance, theirBalance, commitWeight, filteredView, err := lc.computeView( view, false, false, ) if err != nil { @@ -6091,7 +6091,42 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView) ( return 0, commitWeight } - ourBalance -= htlcCommitFee + return ourBalance - htlcCommitFee, commitWeight + } + + // If we're not the initiator, we must check whether the remote has + // enough balance to pay for the fee of our HTLC. We'll start by also + // subtracting our counterparty's reserve from their balance. + theirReserve := lnwire.NewMSatFromSatoshis( + lc.channelState.RemoteChanCfg.ChanReserve, + ) + if theirReserve <= theirBalance { + theirBalance -= theirReserve + } else { + theirBalance = 0 + } + + // We'll use the dustlimit and htlcFee to find the largest HTLC value + // that will be considered dust on the commitment. + dustlimit := lnwire.NewMSatFromSatoshis( + lc.channelState.LocalChanCfg.DustLimit, + ) + + // For an extra HTLC fee to be paid on our commitment, the HTLC must be + // large enough to make a non-dust HTLC timeout transaction. + htlcFee := lnwire.NewMSatFromSatoshis( + htlcTimeoutFee(feePerKw), + ) + + // The HTLC output will be manifested on the commitment if it + // is non-dust after paying the HTLC fee. + nonDustHtlcAmt := dustlimit + htlcFee + + // If they cannot pay the fee if we add another non-dust HTLC, we'll + // report our available balance just below the non-dust amount, to + // avoid attempting HTLCs larger than this size. + if theirBalance < htlcCommitFee && ourBalance >= nonDustHtlcAmt { + ourBalance = nonDustHtlcAmt - 1 } return ourBalance, commitWeight diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 0969762958..be7395201d 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -4735,16 +4735,23 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { } defer cleanUp() - // Alice starts with half the channel capacity. + // Alice and Bob start with half the channel capacity. aliceBalance := lnwire.NewMSatFromSatoshis(5 * btcutil.SatoshiPerBitcoin) + bobBalance := lnwire.NewMSatFromSatoshis(5 * btcutil.SatoshiPerBitcoin) aliceReserve := lnwire.NewMSatFromSatoshis( aliceChannel.channelState.LocalChanCfg.ChanReserve, ) + bobReserve := lnwire.NewMSatFromSatoshis( + bobChannel.channelState.LocalChanCfg.ChanReserve, + ) aliceDustlimit := lnwire.NewMSatFromSatoshis( aliceChannel.channelState.LocalChanCfg.DustLimit, ) + bobDustlimit := lnwire.NewMSatFromSatoshis( + bobChannel.channelState.LocalChanCfg.DustLimit, + ) feeRate := chainfee.SatPerKWeight( aliceChannel.channelState.LocalCommitment.FeePerKw, ) @@ -4759,12 +4766,20 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { ) // Helper method to check the current reported balance. - checkBalance := func(t *testing.T, expBalanceAlice lnwire.MilliSatoshi) { + checkBalance := func(t *testing.T, expBalanceAlice, + expBalanceBob lnwire.MilliSatoshi) { + t.Helper() - balance := aliceChannel.AvailableBalance() - if balance != expBalanceAlice { - t.Fatalf("Expected balance %v, got %v", expBalanceAlice, - balance) + aliceBalance := aliceChannel.AvailableBalance() + if aliceBalance != expBalanceAlice { + t.Fatalf("Expected alice balance %v, got %v", + expBalanceAlice, aliceBalance) + } + + bobBalance := bobChannel.AvailableBalance() + if bobBalance != expBalanceBob { + t.Fatalf("Expected bob balance %v, got %v", + expBalanceBob, bobBalance) } } @@ -4803,6 +4818,7 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { htlcIndex++ aliceBalance -= htlcAmt + bobBalance += htlcAmt } // Balance should start out equal to half the channel capacity minus @@ -4811,12 +4827,17 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { // reflect that this value must be reserved for any payment above the // dust limit. expAliceBalance := aliceBalance - commitFee - aliceReserve - htlcFee - checkBalance(t, expAliceBalance) + + // Bob is not the initiator, so he will have all his balance available, + // since Alice pays for fees. Bob only need to keep his balance above + // the reserve. + expBobBalance := bobBalance - bobReserve + checkBalance(t, expAliceBalance, expBobBalance) // Find the minumim size of a non-dust HTLC. aliceNonDustHtlc := aliceDustlimit + htlcTimeoutFee - // Send a HTLC leaving the remaining balance just enough to have + // Send a HTLC leaving Alice's remaining balance just enough to have // nonDustHtlc left after paying the commit fee and htlc fee. htlcAmt := aliceBalance - (commitFee + aliceReserve + htlcFee + aliceNonDustHtlc) sendHtlc(htlcAmt) @@ -4826,7 +4847,8 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { // reported will just be nonDustHtlc, since the rest of the balance is // reserved. expAliceBalance = aliceNonDustHtlc - checkBalance(t, expAliceBalance) + expBobBalance = bobBalance - bobReserve + checkBalance(t, expAliceBalance, expBobBalance) // Send an HTLC using all but one msat of the reported balance. htlcAmt = aliceNonDustHtlc - 1 @@ -4834,7 +4856,12 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { // 1 msat should be left. expAliceBalance = 1 - checkBalance(t, expAliceBalance) + + // Bob should still have all his balance available, since even though + // Alice cannot afford to add a non-dust HTLC, she can afford to add a + // non-dust HTLC from Bob. + expBobBalance = bobBalance - bobReserve + checkBalance(t, expAliceBalance, expBobBalance) // Sendng the last msat. htlcAmt = 1 @@ -4842,7 +4869,30 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { // No balance left. expAliceBalance = 0 - checkBalance(t, expAliceBalance) + + // We try to always reserve enough for the non-iniitator to be able to + // add an HTLC, hence Bob should still have all his non-reserved + // balance available. + expBobBalance = bobBalance - bobReserve + checkBalance(t, expAliceBalance, expBobBalance) + + // Even though Alice has a reported balance of 0, this is because we + // try to avoid getting into the position where she cannot pay the fee + // for Bob adding another HTLC. This means she actually _has_ some + // balance left, and we now force the channel into this situation by + // sending yet another HTLC. In practice this can also happen if a fee + // update eats into Alice's balance. + htlcAmt = 1 + sendHtlc(htlcAmt) + + // Now Alice balance is so low that she cannot even afford to add a new + // HTLC from Bob to the commitment transaction. Bob's balance should + // reflect this, by only reporting dust amount being available. Alice + // should still report a zero balance. + bobNonDustHtlc := bobDustlimit + htlcTimeoutFee + expBobBalance = bobNonDustHtlc - 1 + expAliceBalance = 0 + checkBalance(t, expAliceBalance, expBobBalance) } // TestSignCommitmentFailNotLockedIn tests that a channel will not attempt to From e398544b8bc385f16d5688021d7ca5101ec4f7a1 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:42 +0100 Subject: [PATCH 092/562] lnwallet/channel: take remote commitment view into availableBalance calculation Since our HTLC must also be added to the remote commitment, we do the balance caluclation also from the remote chain perspective and report our minimum balance from the two commit views as our available balance. --- lnwallet/channel.go | 29 +++++++++++++++++++++++++---- lnwallet/channel_test.go | 13 +++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 0cc512d5e2..01be611763 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -6030,9 +6030,19 @@ func (lc *LightningChannel) availableBalance() (lnwire.MilliSatoshi, int64) { // add updates concurrently, causing our balance to go down if we're // the initiator, but this is a problem on the protocol level. ourLocalCommitBalance, commitWeight := lc.availableCommitmentBalance( - htlcView, + htlcView, false, ) + // Do the same calculation from the remote commitment point of view. + ourRemoteCommitBalance, _ := lc.availableCommitmentBalance( + htlcView, true, + ) + + // Return which ever balance is lowest. + if ourRemoteCommitBalance < ourLocalCommitBalance { + return ourRemoteCommitBalance, commitWeight + } + return ourLocalCommitBalance, commitWeight } @@ -6043,14 +6053,14 @@ func (lc *LightningChannel) availableBalance() (lnwire.MilliSatoshi, int64) { // commitment, increasing the commitment fee we must pay as an initiator, // eating into our balance. It will make sure we won't violate the channel // reserve constraints for this amount. -func (lc *LightningChannel) availableCommitmentBalance(view *htlcView) ( - lnwire.MilliSatoshi, int64) { +func (lc *LightningChannel) availableCommitmentBalance(view *htlcView, + remoteChain bool) (lnwire.MilliSatoshi, int64) { // Compute the current balances for this commitment. This will take // into account HTLCs to determine the commit weight, which the // initiator must pay the fee for. ourBalance, theirBalance, commitWeight, filteredView, err := lc.computeView( - view, false, false, + view, remoteChain, false, ) if err != nil { lc.log.Errorf("Unable to fetch available balance: %v", err) @@ -6118,6 +6128,17 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView) ( htlcTimeoutFee(feePerKw), ) + // If we are looking at the remote commitment, we must use the remote + // dust limit and the fee for adding an HTLC success transaction. + if remoteChain { + dustlimit = lnwire.NewMSatFromSatoshis( + lc.channelState.RemoteChanCfg.DustLimit, + ) + htlcFee = lnwire.NewMSatFromSatoshis( + htlcSuccessFee(feePerKw), + ) + } + // The HTLC output will be manifested on the commitment if it // is non-dust after paying the HTLC fee. nonDustHtlcAmt := dustlimit + htlcFee diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index be7395201d..c4c886709d 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -4749,9 +4749,6 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { aliceDustlimit := lnwire.NewMSatFromSatoshis( aliceChannel.channelState.LocalChanCfg.DustLimit, ) - bobDustlimit := lnwire.NewMSatFromSatoshis( - bobChannel.channelState.LocalChanCfg.DustLimit, - ) feeRate := chainfee.SatPerKWeight( aliceChannel.channelState.LocalCommitment.FeePerKw, ) @@ -4764,6 +4761,9 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { htlcTimeoutFee := lnwire.NewMSatFromSatoshis( htlcTimeoutFee(feeRate), ) + htlcSuccessFee := lnwire.NewMSatFromSatoshis( + htlcSuccessFee(feeRate), + ) // Helper method to check the current reported balance. checkBalance := func(t *testing.T, expBalanceAlice, @@ -4889,7 +4889,12 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { // HTLC from Bob to the commitment transaction. Bob's balance should // reflect this, by only reporting dust amount being available. Alice // should still report a zero balance. - bobNonDustHtlc := bobDustlimit + htlcTimeoutFee + + // Since the dustlimit is different for the two commitments, the + // largest HTLC Bob can send that Alice can afford on both commitments + // (remember she cannot afford to pay the HTLC fee) is the largest dust + // HTLC on Alice's commitemnt, since her dust limit is lower. + bobNonDustHtlc := aliceDustlimit + htlcSuccessFee expBobBalance = bobNonDustHtlc - 1 expAliceBalance = 0 checkBalance(t, expAliceBalance, expBobBalance) From 3e5f2e437da7e7b37d4bdc98e543900b78ecc581 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Feb 2020 12:27:42 +0100 Subject: [PATCH 093/562] lnwallet/channel: add TODO --- lnwallet/channel.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 01be611763..08ec5ebcaf 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -4623,6 +4623,12 @@ func (lc *LightningChannel) InitNextRevocation(revKey *btcec.PublicKey) error { // The additional openKey argument corresponds to the incoming CircuitKey of the // committed circuit for this HTLC. This value should never be nil. // +// Note that AddHTLC doesn't reserve the HTLC fee for future payment (like +// AvailableBalance does), so one could get into the "stuck channel" state by +// sending dust HTLCs. +// TODO(halseth): fix this either by using additional reserve, or better commit +// format. See https://github.com/lightningnetwork/lightning-rfc/issues/728 +// // NOTE: It is okay for sourceRef to be nil when unit testing the wallet. func (lc *LightningChannel) AddHTLC(htlc *lnwire.UpdateAddHTLC, openKey *channeldb.CircuitKey) (uint64, error) { @@ -6025,6 +6031,8 @@ func (lc *LightningChannel) availableBalance() (lnwire.MilliSatoshi, int64) { lc.localUpdateLog.logIndex) // Calculate our available balance from our local commitment. + // TODO(halseth): could reuse parts validateCommitmentSanity to do this + // balance calculation, as most of the logic is the same. // // NOTE: This is not always accurate, since the remote node can always // add updates concurrently, causing our balance to go down if we're From 2074820d85c7d658cba5e9aa6712b6d32bae301e Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:33:53 +0200 Subject: [PATCH 094/562] htlcswitch: add htlcnotifier This commit adds a HTLCNotifier to htlcswitch which HTLC events will be piped through to provide clients with subscriptions to HTLC level events. The event types added are forward events (which occur for sends from and forwards through our node), forward failues (when a send or forward fails down the line), settles for forwards or receives to our node and link failures which occur when a htlc is failed at our node (which may occur for a send, receive or foreward). --- htlcswitch/htlcnotifier.go | 365 +++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 htlcswitch/htlcnotifier.go diff --git a/htlcswitch/htlcnotifier.go b/htlcswitch/htlcnotifier.go new file mode 100644 index 0000000000..1fb523b855 --- /dev/null +++ b/htlcswitch/htlcnotifier.go @@ -0,0 +1,365 @@ +package htlcswitch + +import ( + "fmt" + "strings" + "sync" + "time" + + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/htlcswitch/hop" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/subscribe" +) + +// HtlcNotifier notifies clients of htlc forwards, failures and settles for +// htlcs that the switch handles. It takes subscriptions for its events and +// notifies them when htlc events occur. These are served on a best-effort +// basis; events are not persisted, delivery is not guaranteed (in the event +// of a crash in the switch, forward events may be lost) and some events may +// be replayed upon restart. Events consumed from this package should be +// de-duplicated by the htlc's unique combination of incoming+outgoing circuit +// and not relied upon for critical operations. +// +// The htlc notifier sends the following kinds of events: +// Forwarding Event: +// - Represents a htlc which is forwarded onward from our node. +// - Present for htlc forwards through our node and local sends. +// +// Link Failure Event: +// - Indicates that a htlc has failed on our incoming or outgoing link, +// with an incoming boolean which indicates where the failure occurred. +// - Incoming link failures are present for failed attempts to pay one of +// our invoices (insufficient amount or mpp timeout, for example) and for +// forwards that we cannot decode to forward onwards. +// - Outgoing link failures are present for forwards or local payments that +// do not meet our outgoing link's policy (insufficient fees, for example) +// and when we fail to forward the payment on (insufficient outgoing +// capacity, or an unknown outgoing link). +// +// Forwarding Failure Event: +// - Forwarding failures indicate that a htlc we forwarded has failed at +// another node down the route. +// - Present for local sends and htlc forwards which fail after they left +// our node. +// +// Settle event: +// - Settle events are present when a htlc which we added is settled through +// the release of a preimage. +// - Present for local receives, and successful local sends or forwards. +// +// Each htlc is identified by its incoming and outgoing circuit key. Htlcs, +// and their subsequent settles or fails, can be identified by the combination +// of incoming and outgoing circuits. Note that receives to our node will +// have a zero outgoing circuit key because the htlc terminates at our +// node, and sends from our node will have a zero incoming circuit key because +// the send originates at our node. +type HtlcNotifier struct { + started sync.Once + stopped sync.Once + + // now returns the current time, it is set in the htlcnotifier to allow + // for timestamp mocking in tests. + now func() time.Time + + ntfnServer *subscribe.Server +} + +// NewHtlcNotifier creates a new HtlcNotifier which gets htlc forwarded, +// failed and settled events from links our node has established with peers +// and sends notifications to subscribing clients. +func NewHtlcNotifier(now func() time.Time) *HtlcNotifier { + return &HtlcNotifier{ + now: now, + ntfnServer: subscribe.NewServer(), + } +} + +// Start starts the HtlcNotifier and all goroutines it needs to consume +// events and provide subscriptions to clients. +func (h *HtlcNotifier) Start() error { + var err error + h.started.Do(func() { + log.Trace("HtlcNotifier starting") + err = h.ntfnServer.Start() + }) + return err +} + +// Stop signals the notifier for a graceful shutdown. +func (h *HtlcNotifier) Stop() { + h.stopped.Do(func() { + if err := h.ntfnServer.Stop(); err != nil { + log.Warnf("error stopping htlc notifier: %v", err) + } + }) +} + +// SubscribeHtlcEvents returns a subscribe.Client that will receive updates +// any time the server is made aware of a new event. +func (h *HtlcNotifier) SubscribeHtlcEvents() (*subscribe.Client, error) { + return h.ntfnServer.Subscribe() +} + +// HtlcKey uniquely identifies the htlc. +type HtlcKey struct { + // IncomingCircuit is the channel an htlc id of the incoming htlc. + IncomingCircuit channeldb.CircuitKey + + // OutgoingCircuit is the channel and htlc id of the outgoing htlc. + OutgoingCircuit channeldb.CircuitKey +} + +// String returns a string representation of a htlc key. +func (k HtlcKey) String() string { + switch { + case k.IncomingCircuit.ChanID == hop.Source: + return k.OutgoingCircuit.String() + + case k.OutgoingCircuit.ChanID == hop.Exit: + return k.IncomingCircuit.String() + + default: + return fmt.Sprintf("%v -> %v", k.IncomingCircuit, + k.OutgoingCircuit) + } +} + +// HtlcInfo provides the details of a htlc that our node has processed. For +// forwards, incoming and outgoing values are set, whereas sends and receives +// will only have outgoing or incoming details set. +type HtlcInfo struct { + // IncomingTimelock is the time lock of the htlc on our incoming + // channel. + IncomingTimeLock uint32 + + // OutgoingTimelock is the time lock the htlc on our outgoing channel. + OutgoingTimeLock uint32 + + // IncomingAmt is the amount of the htlc on our incoming channel. + IncomingAmt lnwire.MilliSatoshi + + // OutgoingAmt is the amount of the htlc on our outgoing channel. + OutgoingAmt lnwire.MilliSatoshi +} + +// String returns a string representation of a htlc. +func (h HtlcInfo) String() string { + var details []string + + // If the incoming information is not zero, as is the case for a send, + // we include the incoming amount and timelock. + if h.IncomingAmt != 0 || h.IncomingTimeLock != 0 { + str := fmt.Sprintf("incoming amount: %v, "+ + "incoming timelock: %v", h.IncomingAmt, + h.IncomingTimeLock) + + details = append(details, str) + } + + // If the outgoing information is not zero, as is the case for a + // receive, we include the outgoing amount and timelock. + if h.OutgoingAmt != 0 || h.OutgoingTimeLock != 0 { + str := fmt.Sprintf("outgoing amount: %v, "+ + "outgoing timelock: %v", h.OutgoingAmt, + h.OutgoingTimeLock) + + details = append(details, str) + } + + return strings.Join(details, ", ") +} + +// HtlcEventType represents the type of event that a htlc was part of. +type HtlcEventType int + +const ( + // HtlcEventTypeSend represents a htlc that was part of a send from + // our node. + HtlcEventTypeSend HtlcEventType = iota + + // HtlcEventTypeReceive represents a htlc that was part of a receive + // to our node. + HtlcEventTypeReceive + + // HtlcEventTypeForward represents a htlc that was forwarded through + // our node. + HtlcEventTypeForward +) + +// String returns a string representation of a htlc event type. +func (h HtlcEventType) String() string { + switch h { + case HtlcEventTypeSend: + return "send" + + case HtlcEventTypeReceive: + return "receive" + + case HtlcEventTypeForward: + return "forward" + + default: + return "unknown" + } +} + +// ForwardingEvent represents a htlc that was forwarded onwards from our node. +// Sends which originate from our node will report forward events with zero +// incoming circuits in their htlc key. +type ForwardingEvent struct { + // HtlcKey uniquely identifies the htlc, and can be used to match the + // forwarding event with subsequent settle/fail events. + HtlcKey + + // HtlcInfo contains details about the htlc. + HtlcInfo + + // HtlcEventType classifies the event as part of a local send or + // receive, or as part of a forward. + HtlcEventType + + // Timestamp is the time when this htlc was forwarded. + Timestamp time.Time +} + +// LinkFailEvent describes a htlc that failed on our incoming or outgoing +// link. The incoming bool is true for failures on incoming links, and false +// for failures on outgoing links. The failure reason is provided by a lnwire +// failure message which is enriched with a failure detail in the cases where +// the wire failure message does not contain full information about the +// failure. +type LinkFailEvent struct { + // HtlcKey uniquely identifies the htlc. + HtlcKey + + // HtlcInfo contains details about the htlc. + HtlcInfo + + // HtlcEventType classifies the event as part of a local send or + // receive, or as part of a forward. + HtlcEventType + + // LinkError is the reason that we failed the htlc. + LinkError *LinkError + + // Incoming is true if the htlc was failed on an incoming link. + // If it failed on the outgoing link, it is false. + Incoming bool + + // Timestamp is the time when the link failure occurred. + Timestamp time.Time +} + +// ForwardingFailEvent represents a htlc failure which occurred down the line +// after we forwarded a htlc onwards. An error is not included in this event +// because errors returned down the route are encrypted. HtlcInfo is not +// reliably available for forwarding failures, so it is omitted. These events +// should be matched with their corresponding forward event to obtain this +// information. +type ForwardingFailEvent struct { + // HtlcKey uniquely identifies the htlc, and can be used to match the + // htlc with its corresponding forwarding event. + HtlcKey + + // HtlcEventType classifies the event as part of a local send or + // receive, or as part of a forward. + HtlcEventType + + // Timestamp is the time when the forwarding failure was received. + Timestamp time.Time +} + +// SettleEvent represents a htlc that was settled. HtlcInfo is not reliably +// available for forwarding failures, so it is omitted. These events should +// be matched with corresponding forward events or invoices (for receives) +// to obtain additional information about the htlc. +type SettleEvent struct { + // HtlcKey uniquely identifies the htlc, and can be used to match + // forwards with their corresponding forwarding event. + HtlcKey + + // HtlcEventType classifies the event as part of a local send or + // receive, or as part of a forward. + HtlcEventType + + // Timestamp is the time when this htlc was settled. + Timestamp time.Time +} + +// NotifyForwardingEvent notifies the HtlcNotifier than a htlc has been +// forwarded. +func (h *HtlcNotifier) NotifyForwardingEvent(key HtlcKey, info HtlcInfo, + eventType HtlcEventType) { + + event := &ForwardingEvent{ + HtlcKey: key, + HtlcInfo: info, + HtlcEventType: eventType, + Timestamp: h.now(), + } + + log.Tracef("Notifying forward event: %v over %v, %v", eventType, key, + info) + + if err := h.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send forwarding event: %v", err) + } +} + +// NotifyLinkFailEvent notifies that a htlc has failed on our incoming +// or outgoing link. +func (h *HtlcNotifier) NotifyLinkFailEvent(key HtlcKey, info HtlcInfo, + eventType HtlcEventType, linkErr *LinkError, incoming bool) { + + event := &LinkFailEvent{ + HtlcKey: key, + HtlcInfo: info, + HtlcEventType: eventType, + LinkError: linkErr, + Incoming: incoming, + Timestamp: h.now(), + } + + log.Tracef("Notifying link failure event: %v over %v, %v", eventType, + key, info) + + if err := h.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send link fail event: %v", err) + } +} + +// NotifyForwardingFailEvent notifies the HtlcNotifier that a htlc we +// forwarded has failed down the line. +func (h *HtlcNotifier) NotifyForwardingFailEvent(key HtlcKey, + eventType HtlcEventType) { + + event := &ForwardingFailEvent{ + HtlcKey: key, + HtlcEventType: eventType, + Timestamp: h.now(), + } + + log.Tracef("Notifying forwarding failure event: %v over %v", eventType, + key) + + if err := h.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send forwarding fail event: %v", err) + } +} + +// NotifySettleEvent notifies the HtlcNotifier that a htlc that we committed +// to as part of a forward or a receive to our node has been settled. +func (h *HtlcNotifier) NotifySettleEvent(key HtlcKey, eventType HtlcEventType) { + event := &SettleEvent{ + HtlcKey: key, + HtlcEventType: eventType, + Timestamp: h.now(), + } + + log.Tracef("Notifying settle event: %v over %v", eventType, key) + + if err := h.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send settle event: %v", err) + } +} From abf780bf03c8893c0d4bdcc01704306caa4a5c82 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:34:47 +0200 Subject: [PATCH 095/562] multi: add htlcNotifier interface to switch and link In this commit, a htlcNotifier interface is added to allow for easy unit testing. Instances of the HtlcNotifier are added to the server, switch and link. --- htlcswitch/htlcnotifier.go | 8 ++++++++ htlcswitch/interfaces.go | 26 ++++++++++++++++++++++++++ htlcswitch/link.go | 4 ++++ htlcswitch/link_test.go | 3 +++ htlcswitch/mock.go | 20 ++++++++++++++++++++ htlcswitch/switch.go | 4 ++++ htlcswitch/test_utils.go | 1 + peer.go | 1 + server.go | 10 ++++++++++ 9 files changed, 77 insertions(+) diff --git a/htlcswitch/htlcnotifier.go b/htlcswitch/htlcnotifier.go index 1fb523b855..dd71f3da5c 100644 --- a/htlcswitch/htlcnotifier.go +++ b/htlcswitch/htlcnotifier.go @@ -289,6 +289,8 @@ type SettleEvent struct { // NotifyForwardingEvent notifies the HtlcNotifier than a htlc has been // forwarded. +// +// Note this is part of the htlcNotifier interface. func (h *HtlcNotifier) NotifyForwardingEvent(key HtlcKey, info HtlcInfo, eventType HtlcEventType) { @@ -309,6 +311,8 @@ func (h *HtlcNotifier) NotifyForwardingEvent(key HtlcKey, info HtlcInfo, // NotifyLinkFailEvent notifies that a htlc has failed on our incoming // or outgoing link. +// +// Note this is part of the htlcNotifier interface. func (h *HtlcNotifier) NotifyLinkFailEvent(key HtlcKey, info HtlcInfo, eventType HtlcEventType, linkErr *LinkError, incoming bool) { @@ -331,6 +335,8 @@ func (h *HtlcNotifier) NotifyLinkFailEvent(key HtlcKey, info HtlcInfo, // NotifyForwardingFailEvent notifies the HtlcNotifier that a htlc we // forwarded has failed down the line. +// +// Note this is part of the htlcNotifier interface. func (h *HtlcNotifier) NotifyForwardingFailEvent(key HtlcKey, eventType HtlcEventType) { @@ -350,6 +356,8 @@ func (h *HtlcNotifier) NotifyForwardingFailEvent(key HtlcKey, // NotifySettleEvent notifies the HtlcNotifier that a htlc that we committed // to as part of a forward or a receive to our node has been settled. +// +// Note this is part of the htlcNotifier interface. func (h *HtlcNotifier) NotifySettleEvent(key HtlcKey, eventType HtlcEventType) { event := &SettleEvent{ HtlcKey: key, diff --git a/htlcswitch/interfaces.go b/htlcswitch/interfaces.go index f0eae99ddc..b28d137f5a 100644 --- a/htlcswitch/interfaces.go +++ b/htlcswitch/interfaces.go @@ -180,3 +180,29 @@ type TowerClient interface { // isTweakless should be true. BackupState(*lnwire.ChannelID, *lnwallet.BreachRetribution, bool) error } + +// htlcNotifier is an interface which represents the input side of the +// HtlcNotifier which htlc events are piped through. This interface is intended +// to allow for mocking of the htlcNotifier in tests, so is unexported because +// it is not needed outside of the htlcSwitch package. +type htlcNotifier interface { + // NotifyForwardingEvent notifies the HtlcNotifier than a htlc has been + // forwarded. + NotifyForwardingEvent(key HtlcKey, info HtlcInfo, + eventType HtlcEventType) + + // NotifyIncomingLinkFailEvent notifies that a htlc has failed on our + // incoming link. It takes an isReceive bool to differentiate between + // our node's receives and forwards. + NotifyLinkFailEvent(key HtlcKey, info HtlcInfo, + eventType HtlcEventType, linkErr *LinkError, incoming bool) + + // NotifyForwardingFailEvent notifies the HtlcNotifier that a htlc we + // forwarded has failed down the line. + NotifyForwardingFailEvent(key HtlcKey, eventType HtlcEventType) + + // NotifySettleEvent notifies the HtlcNotifier that a htlc that we + // committed to as part of a forward or a receive to our node has been + // settled. + NotifySettleEvent(key HtlcKey, eventType HtlcEventType) +} diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 80b90f4832..d8da0f13a3 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -272,6 +272,10 @@ type ChannelLinkConfig struct { // NotifyInactiveChannel allows the switch to tell the ChannelNotifier // when channels become inactive. NotifyInactiveChannel func(wire.OutPoint) + + // HtlcNotifier is an instance of a htlcNotifier which we will pipe htlc + // events through. + HtlcNotifier htlcNotifier } // channelLink is the service which drives a channel's commitment update diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 427322ee9e..3b48c157a4 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -1750,6 +1750,7 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) ( MaxFeeAllocation: DefaultMaxLinkFeeAllocation, NotifyActiveChannel: func(wire.OutPoint) {}, NotifyInactiveChannel: func(wire.OutPoint) {}, + HtlcNotifier: aliceSwitch.cfg.HtlcNotifier, } aliceLink := NewChannelLink(aliceCfg, aliceLc.channel) @@ -4313,6 +4314,7 @@ func (h *persistentLinkHarness) restartLink( MaxFeeAllocation: DefaultMaxLinkFeeAllocation, NotifyActiveChannel: func(wire.OutPoint) {}, NotifyInactiveChannel: func(wire.OutPoint) {}, + HtlcNotifier: aliceSwitch.cfg.HtlcNotifier, } aliceLink := NewChannelLink(aliceCfg, aliceChannel) @@ -5523,6 +5525,7 @@ func TestCheckHtlcForward(t *testing.T) { }, FetchLastChannelUpdate: fetchLastChannelUpdate, MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, + HtlcNotifier: &mockHTLCNotifier{}, }, log: log, channel: testChannel.channel, diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index 7cc9fb04ab..0c7f1ed85a 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -176,6 +176,7 @@ func initSwitchWithDB(startingHeight uint32, db *channeldb.DB) (*Switch, error) FwdEventTicker: ticker.NewForce(DefaultFwdEventInterval), LogEventTicker: ticker.NewForce(DefaultLogInterval), AckEventTicker: ticker.NewForce(DefaultAckInterval), + HtlcNotifier: &mockHTLCNotifier{}, } return New(cfg, startingHeight) @@ -1009,3 +1010,22 @@ func (m *mockOnionErrorDecryptor) DecryptError(encryptedData []byte) ( Message: m.message, }, m.err } + +var _ htlcNotifier = (*mockHTLCNotifier)(nil) + +type mockHTLCNotifier struct{} + +func (h *mockHTLCNotifier) NotifyForwardingEvent(key HtlcKey, info HtlcInfo, + eventType HtlcEventType) { +} + +func (h *mockHTLCNotifier) NotifyLinkFailEvent(key HtlcKey, info HtlcInfo, + eventType HtlcEventType, linkErr *LinkError, incoming bool) { +} + +func (h *mockHTLCNotifier) NotifyForwardingFailEvent(key HtlcKey, + eventType HtlcEventType) { +} + +func (h *mockHTLCNotifier) NotifySettleEvent(key HtlcKey, eventType HtlcEventType) { +} diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index b70e36628d..f3ca020891 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -150,6 +150,10 @@ type Config struct { // the switch when a new block has arrived. Notifier chainntnfs.ChainNotifier + // HtlcNotifier is an instance of a htlcNotifier which we will pipe htlc + // events through. + HtlcNotifier htlcNotifier + // FwdEventTicker is a signal that instructs the htlcswitch to flush any // pending forwarding events. FwdEventTicker ticker.Ticker diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index da6b07edd3..5102015080 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1139,6 +1139,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer, MaxFeeAllocation: DefaultMaxLinkFeeAllocation, NotifyActiveChannel: func(wire.OutPoint) {}, NotifyInactiveChannel: func(wire.OutPoint) {}, + HtlcNotifier: server.htlcSwitch.cfg.HtlcNotifier, }, channel, ) diff --git a/peer.go b/peer.go index a956890433..ea482d1f51 100644 --- a/peer.go +++ b/peer.go @@ -636,6 +636,7 @@ func (p *peer) addLink(chanPoint *wire.OutPoint, MaxFeeAllocation: cfg.MaxChannelFeeAllocation, NotifyActiveChannel: p.server.channelNotifier.NotifyActiveChannelEvent, NotifyInactiveChannel: p.server.channelNotifier.NotifyInactiveChannelEvent, + HtlcNotifier: p.server.htlcNotifier, } link := htlcswitch.NewChannelLink(linkCfg, lnChan) diff --git a/server.go b/server.go index 7d2d7470e8..bde65671ad 100644 --- a/server.go +++ b/server.go @@ -203,6 +203,8 @@ type server struct { peerNotifier *peernotifier.PeerNotifier + htlcNotifier *htlcswitch.HtlcNotifier + witnessBeacon contractcourt.WitnessBeacon breachArbiter *breachArbiter @@ -438,6 +440,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, return nil, err } + s.htlcNotifier = htlcswitch.NewHtlcNotifier(time.Now) + s.htlcSwitch, err = htlcswitch.New(htlcswitch.Config{ DB: chanDB, LocalChannelClose: func(pubKey []byte, @@ -467,6 +471,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, ExtractErrorEncrypter: s.sphinx.ExtractErrorEncrypter, FetchLastChannelUpdate: s.fetchLastChanUpdate(), Notifier: s.cc.chainNotifier, + HtlcNotifier: s.htlcNotifier, FwdEventTicker: ticker.New(htlcswitch.DefaultFwdEventInterval), LogEventTicker: ticker.New(htlcswitch.DefaultLogInterval), AckEventTicker: ticker.New(htlcswitch.DefaultAckInterval), @@ -1265,6 +1270,10 @@ func (s *server) Start() error { startErr = err return } + if err := s.htlcNotifier.Start(); err != nil { + startErr = err + return + } if err := s.sphinx.Start(); err != nil { startErr = err return @@ -1429,6 +1438,7 @@ func (s *server) Stop() error { s.sweeper.Stop() s.channelNotifier.Stop() s.peerNotifier.Stop() + s.htlcNotifier.Stop() s.cc.wallet.Shutdown() s.cc.chainView.Stop() s.connMgr.Stop() From b70080a267c49b340d4b4cb64704f62402ccba9d Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:51:53 +0200 Subject: [PATCH 096/562] htlcswitch: failAddPacket with full packet information This commit sets more fields on the htlcPacket created to fail adding a htlc packet to the switch for notification purposes. This new data is copied by value from the original packet. The packet is then failed back to the peer that forwarded us the packet, which is handled by handledownstream packet. The values added to the packet are not used in the handling of a failed packet. --- htlcswitch/switch.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index f3ca020891..52c47f3bc1 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -1256,12 +1256,21 @@ func (s *Switch) failAddPacket(packet *htlcPacket, failure *LinkError) error { log.Error(failure.Error()) + // Create a failure packet for this htlc. The the full set of + // information about the htlc failure is included so that they can + // be included in link failure notifications. failPkt := &htlcPacket{ - sourceRef: packet.sourceRef, - incomingChanID: packet.incomingChanID, - incomingHTLCID: packet.incomingHTLCID, - circuit: packet.circuit, - linkFailure: failure, + sourceRef: packet.sourceRef, + incomingChanID: packet.incomingChanID, + incomingHTLCID: packet.incomingHTLCID, + outgoingChanID: packet.outgoingChanID, + outgoingHTLCID: packet.outgoingHTLCID, + incomingAmount: packet.incomingAmount, + amount: packet.amount, + incomingTimeout: packet.incomingTimeout, + outgoingTimeout: packet.outgoingTimeout, + circuit: packet.circuit, + linkFailure: failure, htlc: &lnwire.UpdateFailHTLC{ Reason: reason, }, From fc0ee06a9906e2908ee4c04fc8afdbafbe473a42 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 18:03:22 +0200 Subject: [PATCH 097/562] htlcswitch: add notifications for forwards This commit adds notifications for htlcs which are forwarded through our node. Forwards are notified when the htlc is added on our ougoing link, settles when we send a settle message to the downstream peer. If a failure occurs, we check whether it occurred at our node, then notify a link or forwarding failure accordingly. Note that this change also adds forward event notifications for sends which are initiated by our node because the handling code for adding a htlc which originates from our node is the same as that for handling forwards. Htlcs for our locally initiated sends have our internal pid set in the incoming htlcs id field, so we extract this value and notify with a zero htlc id to be consistent with receives (which have zero outgoing circuits). Subsequent settles or failures are not noitfied for local sends in this commit, and will be handled in a follow up. --- htlcswitch/htlcnotifier.go | 56 ++++++++++++++++++++++++++++++++++++++ htlcswitch/link.go | 40 +++++++++++++++++++++++++-- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/htlcswitch/htlcnotifier.go b/htlcswitch/htlcnotifier.go index dd71f3da5c..25953e6566 100644 --- a/htlcswitch/htlcnotifier.go +++ b/htlcswitch/htlcnotifier.go @@ -371,3 +371,59 @@ func (h *HtlcNotifier) NotifySettleEvent(key HtlcKey, eventType HtlcEventType) { log.Warnf("Unable to send settle event: %v", err) } } + +// newHtlc key returns a htlc key for the packet provided. If the packet +// has a zero incoming channel ID, the packet is for one of our own sends, +// which has the payment id stashed in the incoming htlc id. If this is the +// case, we replace the incoming htlc id with zero so that the notifier +// consistently reports zero circuit keys for events that terminate or +// originate at our node. +func newHtlcKey(pkt *htlcPacket) HtlcKey { + htlcKey := HtlcKey{ + IncomingCircuit: channeldb.CircuitKey{ + ChanID: pkt.incomingChanID, + HtlcID: pkt.incomingHTLCID, + }, + OutgoingCircuit: CircuitKey{ + ChanID: pkt.outgoingChanID, + HtlcID: pkt.outgoingHTLCID, + }, + } + + // If the packet has a zero incoming channel ID, it is a send that was + // initiated at our node. If this is the case, our internal pid is in + // the incoming htlc ID, so we overwrite it with 0 for notification + // purposes. + if pkt.incomingChanID == hop.Source { + htlcKey.IncomingCircuit.HtlcID = 0 + } + + return htlcKey +} + +// newHtlcInfo returns HtlcInfo for the packet provided. +func newHtlcInfo(pkt *htlcPacket) HtlcInfo { + return HtlcInfo{ + IncomingTimeLock: pkt.incomingTimeout, + OutgoingTimeLock: pkt.outgoingTimeout, + IncomingAmt: pkt.incomingAmount, + OutgoingAmt: pkt.amount, + } +} + +// getEventType returns the htlc type based on the fields set in the htlc +// packet. Sends that originate at our node have the source (zero) incoming +// channel ID. Receives to our node have the exit (zero) outgoing channel ID +// and forwards have both fields set. +func getEventType(pkt *htlcPacket) HtlcEventType { + switch { + case pkt.incomingChanID == hop.Source: + return HtlcEventTypeSend + + case pkt.outgoingChanID == hop.Exit: + return HtlcEventTypeReceive + + default: + return HtlcEventTypeForward + } +} diff --git a/htlcswitch/link.go b/htlcswitch/link.go index d8da0f13a3..c386ad3453 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1418,6 +1418,18 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) { l.cfg.Peer.SendMessage(false, htlc) + // Send a forward event notification to htlcNotifier. + l.cfg.HtlcNotifier.NotifyForwardingEvent( + newHtlcKey(pkt), + HtlcInfo{ + IncomingTimeLock: pkt.incomingTimeout, + IncomingAmt: pkt.incomingAmount, + OutgoingTimeLock: htlc.Expiry, + OutgoingAmt: htlc.Amount, + }, + getEventType(pkt), + ) + case *lnwire.UpdateFulfillHTLC: // If hodl.SettleOutgoing mode is active, we exit early to // simulate arbitrary delays between the switch adding the @@ -1476,6 +1488,12 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) { l.cfg.Peer.SendMessage(false, htlc) isSettle = true + // Send a settle event notification to htlcNotifier. + l.cfg.HtlcNotifier.NotifySettleEvent( + newHtlcKey(pkt), + getEventType(pkt), + ) + case *lnwire.UpdateFailHTLC: // If hodl.FailOutgoing mode is active, we exit early to // simulate arbitrary delays between the switch adding a FAIL to @@ -1529,10 +1547,28 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) { htlc.ChanID = l.ChanID() htlc.ID = pkt.incomingHTLCID - // Finally, we send the HTLC message to the peer which - // initially created the HTLC. + // We send the HTLC message to the peer which initially created + // the HTLC. l.cfg.Peer.SendMessage(false, htlc) isSettle = true + + // If the packet does not have a link failure set, it failed + // further down the route so we notify a forwarding failure. + // Otherwise, we notify a link failure because it failed at our + // node. + if pkt.linkFailure != nil { + l.cfg.HtlcNotifier.NotifyLinkFailEvent( + newHtlcKey(pkt), + newHtlcInfo(pkt), + getEventType(pkt), + pkt.linkFailure, + false, + ) + } else { + l.cfg.HtlcNotifier.NotifyForwardingFailEvent( + newHtlcKey(pkt), getEventType(pkt), + ) + } } // If this newly added update exceeds the min batch size for adds, or From 937062b6d313831f428e6ed4fb500d467e5fc674 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:34:47 +0200 Subject: [PATCH 098/562] htlcswitch: refactor handleLocalDispatch Split handleLocalDispatch into an extra handleLocalAddHTLC function so we can easily notify an error should one occur adding the htlc. --- htlcswitch/switch.go | 74 +++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 52c47f3bc1..84e5aa1586 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -768,38 +768,9 @@ func (s *Switch) handleLocalDispatch(pkt *htlcPacket) error { // User have created the htlc update therefore we should find the // appropriate channel link and send the payment over this link. if htlc, ok := pkt.htlc.(*lnwire.UpdateAddHTLC); ok { - // Try to find links by node destination. - s.indexMtx.RLock() - link, err := s.getLinkByShortID(pkt.outgoingChanID) - s.indexMtx.RUnlock() + link, err := s.handleLocalAddHTLC(pkt, htlc) if err != nil { - log.Errorf("Link %v not found", pkt.outgoingChanID) - return NewLinkError(&lnwire.FailUnknownNextPeer{}) - } - - if !link.EligibleToForward() { - log.Errorf("Link %v is not available to forward", - pkt.outgoingChanID) - - // The update does not need to be populated as the error - // will be returned back to the router. - return NewDetailedLinkError( - lnwire.NewTemporaryChannelFailure(nil), - OutgoingFailureLinkNotEligible, - ) - } - - // Ensure that the htlc satisfies the outgoing channel policy. - currentHeight := atomic.LoadUint32(&s.bestHeight) - htlcErr := link.CheckHtlcTransit( - htlc.PaymentHash, - htlc.Amount, - htlc.Expiry, currentHeight, - ) - if htlcErr != nil { - log.Errorf("Link %v policy for local forward not "+ - "satisfied", pkt.outgoingChanID) - return htlcErr + return err } return link.HandleSwitchPacket(pkt) @@ -811,6 +782,47 @@ func (s *Switch) handleLocalDispatch(pkt *htlcPacket) error { return nil } +// handleLocalAddHTLC handles the addition of a htlc for a send that +// originates from our node. It returns the link that the htlc should +// be forwarded outwards on, and a link error if the htlc cannot be +// forwarded. +func (s *Switch) handleLocalAddHTLC(pkt *htlcPacket, + htlc *lnwire.UpdateAddHTLC) (ChannelLink, *LinkError) { + + // Try to find links by node destination. + s.indexMtx.RLock() + link, err := s.getLinkByShortID(pkt.outgoingChanID) + s.indexMtx.RUnlock() + if err != nil { + log.Errorf("Link %v not found", pkt.outgoingChanID) + return nil, NewLinkError(&lnwire.FailUnknownNextPeer{}) + } + + if !link.EligibleToForward() { + log.Errorf("Link %v is not available to forward", + pkt.outgoingChanID) + + // The update does not need to be populated as the error + // will be returned back to the router. + return nil, NewDetailedLinkError( + lnwire.NewTemporaryChannelFailure(nil), + OutgoingFailureLinkNotEligible, + ) + } + + // Ensure that the htlc satisfies the outgoing channel policy. + currentHeight := atomic.LoadUint32(&s.bestHeight) + htlcErr := link.CheckHtlcTransit( + htlc.PaymentHash, htlc.Amount, htlc.Expiry, currentHeight, + ) + if htlcErr != nil { + log.Errorf("Link %v policy for local forward not "+ + "satisfied", pkt.outgoingChanID) + return nil, htlcErr + } + return link, nil +} + // handleLocalResponse processes a Settle or Fail responding to a // locally-initiated payment. This is handled asynchronously to avoid blocking // the main event loop within the switch, as these operations can require From 79a890fa487a891577fd4154073c464b88634036 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:34:47 +0200 Subject: [PATCH 099/562] htlcswitch: notify outgoing link failures for local sends Notify link failures for our own payments. Separate handling code is required for local payment link failures because we do not pass these failures back through the switch (like we do for link failures for forwards), but rather send them straight back to the router. Our own sends have the payment ID saved in the incoming htlc ID of the packet's incoming circuit. This change replaces that value with for the sake of consistent notifying of sends and receives from our node. --- htlcswitch/switch.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 84e5aa1586..a30eb58466 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -770,6 +770,20 @@ func (s *Switch) handleLocalDispatch(pkt *htlcPacket) error { if htlc, ok := pkt.htlc.(*lnwire.UpdateAddHTLC); ok { link, err := s.handleLocalAddHTLC(pkt, htlc) if err != nil { + // Notify the htlc notifier of a link failure on our + // outgoing link. Incoming timelock/amount values are + // not set because they are not present for local sends. + s.cfg.HtlcNotifier.NotifyLinkFailEvent( + newHtlcKey(pkt), + HtlcInfo{ + OutgoingTimeLock: htlc.Expiry, + OutgoingAmt: htlc.Amount, + }, + HtlcEventTypeSend, + err, + false, + ) + return err } From 22d370aa5155b5dba43eeaf1a9818c40724147dd Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:34:47 +0200 Subject: [PATCH 100/562] htlcswitch: notify send forward failures and settles Add notifications for local initiated sends settles and forwarding failures. As with link failures, local send settles and forwarding failures are reported directly to the router so must have their own notification handling. --- htlcswitch/switch.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index a30eb58466..602dc55b0e 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -898,6 +898,18 @@ func (s *Switch) handleLocalResponse(pkt *htlcPacket) { pkt.inKey(), err) return } + + // Finally, notify on the htlc failure or success that has been handled. + key := newHtlcKey(pkt) + eventType := getEventType(pkt) + + switch pkt.htlc.(type) { + case *lnwire.UpdateFulfillHTLC: + s.cfg.HtlcNotifier.NotifySettleEvent(key, eventType) + + case *lnwire.UpdateFailHTLC: + s.cfg.HtlcNotifier.NotifyForwardingFailEvent(key, eventType) + } } // extractResult uses the given deobfuscator to extract the payment result from From 6bd0de257a70997065d51eee96c590610a7179ce Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:34:47 +0200 Subject: [PATCH 101/562] htlcswitch: notify incoming link failures This commit adds link failure notifications for failures which occur on our incoming link. These failures may be receives which we failed or forwards which we could not parse. --- htlcswitch/link.go | 50 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index c386ad3453..5d5a304032 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1224,8 +1224,7 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution, failure := getResolutionFailure(res, htlc.pd.Amount) l.sendHTLCError( - htlc.pd.HtlcIndex, failure, - htlc.obfuscator, htlc.pd.SourceRef, + htlc.pd, failure, htlc.obfuscator, true, ) return nil @@ -2696,9 +2695,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, // later date failure := lnwire.NewInvalidOnionPayload(failedType, 0) l.sendHTLCError( - pd.HtlcIndex, - NewLinkError(failure), - obfuscator, pd.SourceRef, + pd, NewLinkError(failure), obfuscator, false, ) l.log.Errorf("unable to decode forwarding "+ @@ -2811,10 +2808,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, ) l.sendHTLCError( - pd.HtlcIndex, - NewLinkError(failure), - obfuscator, - pd.SourceRef, + pd, NewLinkError(failure), obfuscator, false, ) continue } @@ -2900,7 +2894,7 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor, failure := NewLinkError( lnwire.NewFinalIncorrectHtlcAmount(pd.Amount), ) - l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef) + l.sendHTLCError(pd, failure, obfuscator, true) return nil } @@ -2915,7 +2909,7 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor, failure := NewLinkError( lnwire.NewFinalIncorrectCltvExpiry(pd.Timeout), ) - l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef) + l.sendHTLCError(pd, failure, obfuscator, true) return nil } @@ -3031,8 +3025,8 @@ func (l *channelLink) handleBatchFwdErrs(errChan chan error) { // sendHTLCError functions cancels HTLC and send cancel message back to the // peer from which HTLC was received. -func (l *channelLink) sendHTLCError(htlcIndex uint64, failure *LinkError, - e hop.ErrorEncrypter, sourceRef *channeldb.AddRef) { +func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor, + failure *LinkError, e hop.ErrorEncrypter, isReceive bool) { reason, err := e.EncryptFirstHop(failure.WireMessage()) if err != nil { @@ -3040,7 +3034,7 @@ func (l *channelLink) sendHTLCError(htlcIndex uint64, failure *LinkError, return } - err = l.channel.FailHTLC(htlcIndex, reason, sourceRef, nil, nil) + err = l.channel.FailHTLC(pd.HtlcIndex, reason, pd.SourceRef, nil, nil) if err != nil { l.log.Errorf("unable cancel htlc: %v", err) return @@ -3048,9 +3042,35 @@ func (l *channelLink) sendHTLCError(htlcIndex uint64, failure *LinkError, l.cfg.Peer.SendMessage(false, &lnwire.UpdateFailHTLC{ ChanID: l.ChanID(), - ID: htlcIndex, + ID: pd.HtlcIndex, Reason: reason, }) + + // Notify a link failure on our incoming link. Outgoing htlc information + // is not available at this point, because we have not decrypted the + // onion, so it is excluded. + var eventType HtlcEventType + if isReceive { + eventType = HtlcEventTypeReceive + } else { + eventType = HtlcEventTypeForward + } + + l.cfg.HtlcNotifier.NotifyLinkFailEvent( + HtlcKey{ + IncomingCircuit: channeldb.CircuitKey{ + ChanID: l.ShortChanID(), + HtlcID: pd.HtlcIndex, + }, + }, + HtlcInfo{ + IncomingTimeLock: pd.Timeout, + IncomingAmt: pd.Amount, + }, + eventType, + failure, + true, + ) } // sendMalformedHTLCError helper function which sends the malformed HTLC update From 71fdd755b44f709a43a32ef0ddb0b1a0b7a33cc0 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:34:48 +0200 Subject: [PATCH 102/562] htlcswitch: notify local receive settles --- htlcswitch/link.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 5d5a304032..797c3c724f 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1208,10 +1208,7 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution, l.log.Debugf("received settle resolution for %v"+ "with outcome: %v", circuitKey, res.Outcome) - return l.settleHTLC( - res.Preimage, htlc.pd.HtlcIndex, - htlc.pd.SourceRef, - ) + return l.settleHTLC(res.Preimage, htlc.pd) // For htlc failures, we get the relevant failure message based // on the failure resolution and then fail the htlc. @@ -2950,15 +2947,15 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor, } // settleHTLC settles the HTLC on the channel. -func (l *channelLink) settleHTLC(preimage lntypes.Preimage, htlcIndex uint64, - sourceRef *channeldb.AddRef) error { +func (l *channelLink) settleHTLC(preimage lntypes.Preimage, + pd *lnwallet.PaymentDescriptor) error { hash := preimage.Hash() l.log.Infof("settling htlc %v as exit hop", hash) err := l.channel.SettleHTLC( - preimage, htlcIndex, sourceRef, nil, nil, + preimage, pd.HtlcIndex, pd.SourceRef, nil, nil, ) if err != nil { return fmt.Errorf("unable to settle htlc: %v", err) @@ -2976,10 +2973,21 @@ func (l *channelLink) settleHTLC(preimage lntypes.Preimage, htlcIndex uint64, // remote peer. l.cfg.Peer.SendMessage(false, &lnwire.UpdateFulfillHTLC{ ChanID: l.ChanID(), - ID: htlcIndex, + ID: pd.HtlcIndex, PaymentPreimage: preimage, }) + // Once we have successfully settled the htlc, notify a settle event. + l.cfg.HtlcNotifier.NotifySettleEvent( + HtlcKey{ + IncomingCircuit: channeldb.CircuitKey{ + ChanID: l.ShortChanID(), + HtlcID: pd.HtlcIndex, + }, + }, + HtlcEventTypeReceive, + ) + return nil } From c0a4923dc1f24b7b83f075bb420c25e226de2aa1 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 19 Feb 2020 17:34:48 +0200 Subject: [PATCH 103/562] htlcswitch: add htlc notifier test --- htlcswitch/switch_test.go | 361 ++++++++++++++++++++++++++++++++++++++ htlcswitch/test_utils.go | 38 +++- 2 files changed, 398 insertions(+), 1 deletion(-) diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index 14032ed2e6..9cfed11774 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -14,11 +14,14 @@ import ( "github.com/btcsuite/fastsha256" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/ticker" ) +var zeroCircuit = channeldb.CircuitKey{} + func genPreimage() ([32]byte, error) { var preimage [32]byte if _, err := io.ReadFull(rand.Reader, preimage[:]); err != nil { @@ -2697,3 +2700,361 @@ func TestInvalidFailure(t *testing.T) { t.Fatal("err wasn't received") } } + +// htlcNotifierEvents is a function that generates a set of expected htlc +// notifier evetns for each node in a three hop network with the dynamic +// values provided. These functions take dynamic values so that changes to +// external systems (such as our default timelock delta) do not break +// these tests. +type htlcNotifierEvents func(channels *clusterChannels, htlcID uint64, + ts time.Time, htlc *lnwire.UpdateAddHTLC, + hops []*hop.Payload) ([]interface{}, []interface{}, []interface{}) + +// TestHtlcNotifier tests the notifying of htlc events that are routed over a +// three hop network. It sets up an Alice -> Bob -> Carol network and routes +// payments from Alice -> Carol to test events from the perspective of a +// sending (Alice), forwarding (Bob) and receiving (Carol) node. Test cases +// are present for saduccessful and failed payments. +func TestHtlcNotifier(t *testing.T) { + tests := []struct { + name string + + // Options is a set of options to apply to the three hop + // network's servers. + options []serverOption + + // expectedEvents is a function which returns an expected set + // of events for the test. + expectedEvents htlcNotifierEvents + + // iterations is the number of times we will send a payment, + // this is used to send more than one payment to force non- + // zero htlc indexes to make sure we aren't just checking + // default values. + iterations int + }{ + { + name: "successful three hop payment", + options: nil, + expectedEvents: func(channels *clusterChannels, + htlcID uint64, ts time.Time, + htlc *lnwire.UpdateAddHTLC, + hops []*hop.Payload) ([]interface{}, + []interface{}, []interface{}) { + + return getThreeHopEvents( + channels, htlcID, ts, htlc, hops, nil, + ) + }, + iterations: 2, + }, + { + name: "failed at forwarding link", + // Set a functional option which disables bob as a + // forwarding node to force a payment error. + options: []serverOption{ + serverOptionRejectHtlc(false, true, false), + }, + expectedEvents: func(channels *clusterChannels, + htlcID uint64, ts time.Time, + htlc *lnwire.UpdateAddHTLC, + hops []*hop.Payload) ([]interface{}, + []interface{}, []interface{}) { + + return getThreeHopEvents( + channels, htlcID, ts, htlc, hops, + &LinkError{ + msg: &lnwire.FailChannelDisabled{}, + FailureDetail: OutgoingFailureForwardsDisabled, + }, + ) + }, + iterations: 1, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + testHtcNotifier( + t, test.options, test.iterations, + test.expectedEvents, + ) + }) + } +} + +// testHtcNotifier runs a htlc notifier test. +func testHtcNotifier(t *testing.T, testOpts []serverOption, iterations int, + getEvents htlcNotifierEvents) { + + t.Parallel() + + // First, we'll create our traditional three hop + // network. + channels, cleanUp, _, err := createClusterChannels( + btcutil.SatoshiPerBitcoin*3, + btcutil.SatoshiPerBitcoin*5) + if err != nil { + t.Fatalf("unable to create channel: %v", err) + } + defer cleanUp() + + // Mock time so that all events are reported with a static timestamp. + now := time.Now() + mockTime := func() time.Time { + return now + } + + // Create htlc notifiers for each server in the three hop network and + // start them. + aliceNotifier := NewHtlcNotifier(mockTime) + if err := aliceNotifier.Start(); err != nil { + t.Fatalf("could not start alice notifier") + } + defer aliceNotifier.Stop() + + bobNotifier := NewHtlcNotifier(mockTime) + if err := bobNotifier.Start(); err != nil { + t.Fatalf("could not start bob notifier") + } + defer bobNotifier.Stop() + + carolNotifier := NewHtlcNotifier(mockTime) + if err := carolNotifier.Start(); err != nil { + t.Fatalf("could not start carol notifier") + } + defer carolNotifier.Stop() + + // Create a notifier server option which will set our htlc notifiers + // for the three hop network. + notifierOption := serverOptionWithHtlcNotifier( + aliceNotifier, bobNotifier, carolNotifier, + ) + + // Add the htlcNotifier option to any other options + // set in the test. + options := append(testOpts, notifierOption) + + n := newThreeHopNetwork( + t, channels.aliceToBob, + channels.bobToAlice, channels.bobToCarol, + channels.carolToBob, testStartingHeight, + options..., + ) + if err := n.start(); err != nil { + t.Fatalf("unable to start three hop "+ + "network: %v", err) + } + defer n.stop() + + // Before we forward anything, subscribe to htlc events + // from each notifier. + aliceEvents, err := aliceNotifier.SubscribeHtlcEvents() + if err != nil { + t.Fatalf("could not subscribe to alice's"+ + " events: %v", err) + } + defer aliceEvents.Cancel() + + bobEvents, err := bobNotifier.SubscribeHtlcEvents() + if err != nil { + t.Fatalf("could not subscribe to bob's"+ + " events: %v", err) + } + defer bobEvents.Cancel() + + carolEvents, err := carolNotifier.SubscribeHtlcEvents() + if err != nil { + t.Fatalf("could not subscribe to carol's"+ + " events: %v", err) + } + defer carolEvents.Cancel() + + // Send multiple payments, as specified by the test to test incrementing + // of htlc ids. + for i := 0; i < iterations; i++ { + // We'll start off by making a payment from + // Alice -> Bob -> Carol. + htlc, hops := n.sendThreeHopPayment(t) + + alice, bob, carol := getEvents( + channels, uint64(i), now, htlc, hops, + ) + + checkHtlcEvents(t, aliceEvents.Updates(), alice) + checkHtlcEvents(t, bobEvents.Updates(), bob) + checkHtlcEvents(t, carolEvents.Updates(), carol) + + } +} + +// checkHtlcEvents checks that a subscription has the set of htlc events +// we expect it to have. +func checkHtlcEvents(t *testing.T, events <-chan interface{}, + expectedEvents []interface{}) { + + for _, expected := range expectedEvents { + select { + case event := <-events: + if !reflect.DeepEqual(event, expected) { + t.Fatalf("expected %v, got: %v", expected, + event) + } + + case <-time.After(time.Second): + t.Fatalf("expected event: %v", expected) + } + } +} + +// sendThreeHopPayment is a helper function which sends a payment over +// Alice -> Bob -> Carol in a three hop network and returns Alice's first htlc +// and the remainder of the hops. +func (n *threeHopNetwork) sendThreeHopPayment(t *testing.T) (*lnwire.UpdateAddHTLC, + []*hop.Payload) { + + amount := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin) + + htlcAmt, totalTimelock, hops := generateHops(amount, testStartingHeight, + n.firstBobChannelLink, n.carolChannelLink) + blob, err := generateRoute(hops...) + if err != nil { + t.Fatal(err) + } + invoice, htlc, pid, err := generatePayment( + amount, htlcAmt, totalTimelock, blob, + ) + if err != nil { + t.Fatal(err) + } + + err = n.carolServer.registry.AddInvoice(*invoice, htlc.PaymentHash) + if err != nil { + t.Fatalf("unable to add invoice in carol registry: %v", err) + } + + if err := n.aliceServer.htlcSwitch.SendHTLC( + n.firstBobChannelLink.ShortChanID(), pid, htlc, + ); err != nil { + t.Fatalf("could not send htlc") + } + + return htlc, hops +} + +// getThreeHopEvents gets the set of htlc events that we expect for a payment +// from Alice -> Bob -> Carol. If a non-nil link error is provided, the set +// of events will fail on Bob's outgoing link. +func getThreeHopEvents(channels *clusterChannels, htlcID uint64, + ts time.Time, htlc *lnwire.UpdateAddHTLC, hops []*hop.Payload, + linkError *LinkError) ([]interface{}, []interface{}, []interface{}) { + + aliceKey := HtlcKey{ + IncomingCircuit: zeroCircuit, + OutgoingCircuit: channeldb.CircuitKey{ + ChanID: channels.aliceToBob.ShortChanID(), + HtlcID: htlcID, + }, + } + + // Alice always needs a forwarding event because she initiates the + // send. + aliceEvents := []interface{}{ + &ForwardingEvent{ + HtlcKey: aliceKey, + HtlcInfo: HtlcInfo{ + OutgoingTimeLock: htlc.Expiry, + OutgoingAmt: htlc.Amount, + }, + HtlcEventType: HtlcEventTypeSend, + Timestamp: ts, + }, + } + + bobKey := HtlcKey{ + IncomingCircuit: channeldb.CircuitKey{ + ChanID: channels.bobToAlice.ShortChanID(), + HtlcID: htlcID, + }, + OutgoingCircuit: channeldb.CircuitKey{ + ChanID: channels.bobToCarol.ShortChanID(), + HtlcID: htlcID, + }, + } + + bobInfo := HtlcInfo{ + IncomingTimeLock: htlc.Expiry, + IncomingAmt: htlc.Amount, + OutgoingTimeLock: hops[1].FwdInfo.OutgoingCTLV, + OutgoingAmt: hops[1].FwdInfo.AmountToForward, + } + + // If we expect the payment to fail, we add failures for alice and + // bob, and no events for carol because the payment never reaches her. + if linkError != nil { + aliceEvents = append(aliceEvents, + &ForwardingFailEvent{ + HtlcKey: aliceKey, + HtlcEventType: HtlcEventTypeSend, + Timestamp: ts, + }, + ) + + bobEvents := []interface{}{ + &LinkFailEvent{ + HtlcKey: bobKey, + HtlcInfo: bobInfo, + HtlcEventType: HtlcEventTypeForward, + LinkError: linkError, + Incoming: false, + Timestamp: ts, + }, + } + + return aliceEvents, bobEvents, nil + } + + // If we want to get events for a successful payment, we add a settle + // for alice, a forward and settle for bob and a receive settle for + // carol. + aliceEvents = append( + aliceEvents, + &SettleEvent{ + HtlcKey: aliceKey, + HtlcEventType: HtlcEventTypeSend, + Timestamp: ts, + }, + ) + + bobEvents := []interface{}{ + &ForwardingEvent{ + HtlcKey: bobKey, + HtlcInfo: bobInfo, + HtlcEventType: HtlcEventTypeForward, + Timestamp: ts, + }, + &SettleEvent{ + HtlcKey: bobKey, + HtlcEventType: HtlcEventTypeForward, + Timestamp: ts, + }, + } + + carolEvents := []interface{}{ + &SettleEvent{ + HtlcKey: HtlcKey{ + IncomingCircuit: channeldb.CircuitKey{ + ChanID: channels.carolToBob.ShortChanID(), + HtlcID: htlcID, + }, + OutgoingCircuit: zeroCircuit, + }, + HtlcEventType: HtlcEventTypeReceive, + Timestamp: ts, + }, + } + + return aliceEvents, bobEvents, carolEvents +} diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index 5102015080..26b8dad576 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -966,9 +966,11 @@ func createClusterChannels(aliceToBob, bobToCarol btcutil.Amount) ( // alice first bob second bob carol // channel link channel link channel link channel link // +// This function takes server options which can be used to apply custom +// settings to alice, bob and carol. func newThreeHopNetwork(t testing.TB, aliceChannel, firstBobChannel, secondBobChannel, carolChannel *lnwallet.LightningChannel, - startingHeight uint32) *threeHopNetwork { + startingHeight uint32, opts ...serverOption) *threeHopNetwork { aliceDb := aliceChannel.State().Db bobDb := firstBobChannel.State().Db @@ -996,6 +998,12 @@ func newThreeHopNetwork(t testing.TB, aliceChannel, firstBobChannel, t.Fatalf("unable to create carol server: %v", err) } + // Apply all additional functional options to the servers before + // creating any links. + for _, option := range opts { + option(aliceServer, bobServer, carolServer) + } + // Create mock decoder instead of sphinx one in order to mock the route // which htlc should follow. aliceDecoder := newMockIteratorDecoder() @@ -1045,6 +1053,34 @@ func newThreeHopNetwork(t testing.TB, aliceChannel, firstBobChannel, } } +// serverOption is a function which alters the three servers created for +// a three hop network to allow custom settings on each server. +type serverOption func(aliceServer, bobServer, carolServer *mockServer) + +// serverOptionWithHtlcNotifier is a functional option for the creation of +// three hop network servers which allows setting of htlc notifiers. +// Note that these notifiers should be started and stopped by the calling +// function. +func serverOptionWithHtlcNotifier(alice, bob, + carol *HtlcNotifier) serverOption { + + return func(aliceServer, bobServer, carolServer *mockServer) { + aliceServer.htlcSwitch.cfg.HtlcNotifier = alice + bobServer.htlcSwitch.cfg.HtlcNotifier = bob + carolServer.htlcSwitch.cfg.HtlcNotifier = carol + } +} + +// serverOptionRejectHtlc is the functional option for setting the reject +// htlc config option in each server's switch. +func serverOptionRejectHtlc(alice, bob, carol bool) serverOption { + return func(aliceServer, bobServer, carolServer *mockServer) { + aliceServer.htlcSwitch.cfg.RejectHTLC = alice + bobServer.htlcSwitch.cfg.RejectHTLC = bob + carolServer.htlcSwitch.cfg.RejectHTLC = carol + } +} + // createTwoClusterChannels creates lightning channels which are needed for // a 2 hop network cluster to be initialized. func createTwoClusterChannels(aliceToBob, bobToCarol btcutil.Amount) ( From ac28b2c69221e5382c0e33db0d3f872ed2725cbf Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 20 Feb 2020 20:18:43 +0100 Subject: [PATCH 104/562] travis: remove git clone depth limitation to fix linter By default, Travis-CI does `git clone --depth=50` which limits the repo to the last 50 commits. Because we do linting against an old commit, it cannot be found any more. We remove the limit completely to not run into this problem again. --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 35e39df23a..c996ca51e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,11 @@ cache: - $GOPATH/src/github.com/golang - $GOPATH/src/gopkg.in/alecthomas +# Remove Travis' default flag --depth=50 from the git clone command to make sure +# we have the whole git history, including the commit we lint against. +git: + depth: false + go: - "1.13.x" From 8d632b80220fe7676360fb52fdf4e12826cc12ba Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 21 Feb 2020 13:23:30 +0200 Subject: [PATCH 105/562] channeldb: add historical channel bucket lookup --- channeldb/db.go | 47 ++++++++++++++++++++++++++++++++++++++ channeldb/db_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++ channeldb/error.go | 5 ++++ 3 files changed, 106 insertions(+) diff --git a/channeldb/db.go b/channeldb/db.go index 696f3f0086..6377df63a3 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -1249,3 +1249,50 @@ func getMigrationsToApply(versions []version, version uint32) ([]migration, []ui return migrations, migrationVersions } + +// fetchHistoricalChanBucket returns a the channel bucket for a given outpoint +// from the historical channel bucket. If the bucket does not exist, +// ErrNoHistoricalBucket is returned. +func fetchHistoricalChanBucket(tx *bbolt.Tx, + outPoint *wire.OutPoint) (*bbolt.Bucket, error) { + + // First fetch the top level bucket which stores all data related to + // historically stored channels. + historicalChanBucket := tx.Bucket(historicalChannelBucket) + if historicalChanBucket == nil { + return nil, ErrNoHistoricalBucket + } + + // With the bucket for the node and chain fetched, we can now go down + // another level, for the channel itself. + var chanPointBuf bytes.Buffer + if err := writeOutpoint(&chanPointBuf, outPoint); err != nil { + return nil, err + } + chanBucket := historicalChanBucket.Bucket(chanPointBuf.Bytes()) + if chanBucket == nil { + return nil, ErrChannelNotFound + } + + return chanBucket, nil +} + +// FetchHistoricalChannel fetches open channel data from the historical channel +// bucket. +func (d *DB) FetchHistoricalChannel(outPoint *wire.OutPoint) (*OpenChannel, error) { + var channel *OpenChannel + err := d.View(func(tx *bbolt.Tx) error { + chanBucket, err := fetchHistoricalChanBucket(tx, outPoint) + if err != nil { + return err + } + + channel, err = fetchOpenChannel(chanBucket, outPoint) + return err + }) + if err != nil { + return nil, err + } + + return channel, nil +} diff --git a/channeldb/db_test.go b/channeldb/db_test.go index 935a287ced..4d678303aa 100644 --- a/channeldb/db_test.go +++ b/channeldb/db_test.go @@ -693,3 +693,57 @@ func TestFetchChannels(t *testing.T) { }) } } + +// TestFetchHistoricalChannel tests lookup of historical channels. +func TestFetchHistoricalChannel(t *testing.T) { + cdb, cleanUp, err := makeTestDB() + if err != nil { + t.Fatalf("unable to make test database: %v", err) + } + defer cleanUp() + + // Create a an open channel in the database. + channel := createTestChannel(t, cdb, openChannelOption()) + + // First, try to lookup a channel when the bucket does not + // exist. + _, err = cdb.FetchHistoricalChannel(&channel.FundingOutpoint) + if err != ErrNoHistoricalBucket { + t.Fatalf("expected no bucket, got: %v", err) + } + + // Close the channel so that it will be written to the historical + // bucket. The values provided in the channel close summary are the + // minimum required for this call to run without panicking. + if err := channel.CloseChannel(&ChannelCloseSummary{ + ChanPoint: channel.FundingOutpoint, + RemotePub: channel.IdentityPub, + SettledBalance: btcutil.Amount(500), + }); err != nil { + t.Fatalf("unexpected error closing channel: %v", err) + } + + histChannel, err := cdb.FetchHistoricalChannel(&channel.FundingOutpoint) + if err != nil { + t.Fatalf("unexepected error getting channel: %v", err) + } + + // Set the db on our channel to nil so that we can check that all other + // fields on the channel equal those on the historical channel. + channel.Db = nil + + if !reflect.DeepEqual(histChannel, channel) { + t.Fatalf("expected: %v, got: %v", channel, histChannel) + } + + // Create an outpoint that will not be in the db and look it up. + badOutpoint := &wire.OutPoint{ + Hash: channel.FundingOutpoint.Hash, + Index: channel.FundingOutpoint.Index + 1, + } + _, err = cdb.FetchHistoricalChannel(badOutpoint) + if err != ErrChannelNotFound { + t.Fatalf("expected chan not found, got: %v", err) + } + +} diff --git a/channeldb/error.go b/channeldb/error.go index e0e7545220..b1364fb4ba 100644 --- a/channeldb/error.go +++ b/channeldb/error.go @@ -10,6 +10,11 @@ var ( // created. ErrNoChanDBExists = fmt.Errorf("channel db has not yet been created") + // ErrNoHistoricalBucket is returned when the historical channel bucket + // not been created yet. + ErrNoHistoricalBucket = fmt.Errorf("historical channel bucket has " + + "not yet been created") + // ErrDBReversion is returned when detecting an attempt to revert to a // prior database version. ErrDBReversion = fmt.Errorf("channel db cannot revert to prior version") From d3cb6ad869749d5a72de55a543c912a237e7d6f0 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 21 Feb 2020 13:24:23 +0200 Subject: [PATCH 106/562] channeldb: store close initiator status This commit adds two new channel statuses which indicate the party that initatited closing the channel. These statuses are set in conjunction with the existing commit broadcast status so that we do not need to migrate existing logic to handle multiple types of closes. This status is set for locally initiated force closes in this commit because they follow a similar pattern to cooparative closes, marking the commitment broadcast then proceeding with tx broadcast. Remote force closes are added in the following commit, as they are handled differently. --- chancloser.go | 12 ++- channeldb/channel.go | 63 +++++++++---- channeldb/channel_test.go | 108 ++++++++++++++++++++++- channeldb/db_test.go | 4 +- contractcourt/chain_arbitrator_test.go | 4 +- contractcourt/channel_arbitrator.go | 8 +- contractcourt/channel_arbitrator_test.go | 2 +- lnwallet/channel.go | 18 ++-- peer.go | 2 + 9 files changed, 186 insertions(+), 35 deletions(-) diff --git a/chancloser.go b/chancloser.go index 3536f1ce88..00dff1bf74 100644 --- a/chancloser.go +++ b/chancloser.go @@ -155,6 +155,9 @@ type channelCloser struct { // remoteDeliveryScript is the script that we'll send the remote // party's settled channel funds to. remoteDeliveryScript []byte + + // locallyInitiated is true if we initiated the channel close. + locallyInitiated bool } // newChannelCloser creates a new instance of the channel closure given the @@ -162,7 +165,7 @@ type channelCloser struct { // only be populated iff, we're the initiator of this closing request. func newChannelCloser(cfg chanCloseCfg, deliveryScript []byte, idealFeePerKw chainfee.SatPerKWeight, negotiationHeight uint32, - closeReq *htlcswitch.ChanClose) *channelCloser { + closeReq *htlcswitch.ChanClose, locallyInitiated bool) *channelCloser { // Given the target fee-per-kw, we'll compute what our ideal _total_ // fee will be starting at for this fee negotiation. @@ -198,6 +201,7 @@ func newChannelCloser(cfg chanCloseCfg, deliveryScript []byte, idealFeeSat: idealFeeSat, localDeliveryScript: deliveryScript, priorFeeOffers: make(map[btcutil.Amount]*lnwire.ClosingSigned), + locallyInitiated: locallyInitiated, } } @@ -224,7 +228,7 @@ func (c *channelCloser) initChanShutdown() (*lnwire.Shutdown, error) { // guarantees that our listchannels rpc will be externally consistent, // and reflect that the channel is being shutdown by the time the // closing request returns. - err := c.cfg.channel.MarkCoopBroadcasted(nil) + err := c.cfg.channel.MarkCoopBroadcasted(nil, c.locallyInitiated) if err != nil { return nil, err } @@ -511,7 +515,9 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b // Before publishing the closing tx, we persist it to the // database, such that it can be republished if something goes // wrong. - err = c.cfg.channel.MarkCoopBroadcasted(closeTx) + err = c.cfg.channel.MarkCoopBroadcasted( + closeTx, c.locallyInitiated, + ) if err != nil { return nil, false, err } diff --git a/channeldb/channel.go b/channeldb/channel.go index 3e3403905d..bc20548866 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -401,20 +401,35 @@ var ( // will have. ChanStatusRestored ChannelStatus = 1 << 3 - // ChanStatusCoopBroadcasted indicates that a cooperative close for this - // channel has been broadcasted. + // ChanStatusCoopBroadcasted indicates that a cooperative close for + // this channel has been broadcasted. Older cooperatively closed + // channels will only have this status set. Newer ones will also have + // close initiator information stored using the local/remote initiator + // status. This status is set in conjunction with the initiator status + // so that we do not need to check multiple channel statues for + // cooperative closes. ChanStatusCoopBroadcasted ChannelStatus = 1 << 4 + + // ChanStatusLocalCloseInitiator indicates that we initiated closing + // the channel. + ChanStatusLocalCloseInitiator ChannelStatus = 1 << 5 + + // ChanStatusRemoteCloseInitiator indicates that the remote node + // initiated closing the channel. + ChanStatusRemoteCloseInitiator ChannelStatus = 1 << 6 ) // chanStatusStrings maps a ChannelStatus to a human friendly string that // describes that status. var chanStatusStrings = map[ChannelStatus]string{ - ChanStatusDefault: "ChanStatusDefault", - ChanStatusBorked: "ChanStatusBorked", - ChanStatusCommitBroadcasted: "ChanStatusCommitBroadcasted", - ChanStatusLocalDataLoss: "ChanStatusLocalDataLoss", - ChanStatusRestored: "ChanStatusRestored", - ChanStatusCoopBroadcasted: "ChanStatusCoopBroadcasted", + ChanStatusDefault: "ChanStatusDefault", + ChanStatusBorked: "ChanStatusBorked", + ChanStatusCommitBroadcasted: "ChanStatusCommitBroadcasted", + ChanStatusLocalDataLoss: "ChanStatusLocalDataLoss", + ChanStatusRestored: "ChanStatusRestored", + ChanStatusCoopBroadcasted: "ChanStatusCoopBroadcasted", + ChanStatusLocalCloseInitiator: "ChanStatusLocalCloseInitiator", + ChanStatusRemoteCloseInitiator: "ChanStatusRemoteCloseInitiator", } // orderedChanStatusFlags is an in-order list of all that channel status flags. @@ -425,6 +440,8 @@ var orderedChanStatusFlags = []ChannelStatus{ ChanStatusLocalDataLoss, ChanStatusRestored, ChanStatusCoopBroadcasted, + ChanStatusLocalCloseInitiator, + ChanStatusRemoteCloseInitiator, } // String returns a human-readable representation of the ChannelStatus. @@ -974,30 +991,37 @@ func (c *OpenChannel) isBorked(chanBucket *bbolt.Bucket) (bool, error) { // closing tx _we believe_ will appear in the chain. This is only used to // republish this tx at startup to ensure propagation, and we should still // handle the case where a different tx actually hits the chain. -func (c *OpenChannel) MarkCommitmentBroadcasted(closeTx *wire.MsgTx) error { +func (c *OpenChannel) MarkCommitmentBroadcasted(closeTx *wire.MsgTx, + locallyInitiated bool) error { + return c.markBroadcasted( ChanStatusCommitBroadcasted, forceCloseTxKey, closeTx, + locallyInitiated, ) } // MarkCoopBroadcasted marks the channel to indicate that a cooperative close // transaction has been broadcast, either our own or the remote, and that we -// should wach the chain for it to confirm before taking further action. It +// should watch the chain for it to confirm before taking further action. It // takes as argument a cooperative close tx that could appear on chain, and -// should be rebroadcast upon startup. This is only used to republish and ensure -// propagation, and we should still handle the case where a different tx +// should be rebroadcast upon startup. This is only used to republish and +// ensure propagation, and we should still handle the case where a different tx // actually hits the chain. -func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx) error { +func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx, + locallyInitiated bool) error { + return c.markBroadcasted( ChanStatusCoopBroadcasted, coopCloseTxKey, closeTx, + locallyInitiated, ) } // markBroadcasted is a helper function which modifies the channel status of the // receiving channel and inserts a close transaction under the requested key, -// which should specify either a coop or force close. +// which should specify either a coop or force close. It adds a status which +// indicates the party that initiated the channel close. func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte, - closeTx *wire.MsgTx) error { + closeTx *wire.MsgTx, locallyInitiated bool) error { c.Lock() defer c.Unlock() @@ -1016,6 +1040,15 @@ func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte, } } + // Add the initiator status to the status provided. These statuses are + // set in addition to the broadcast status so that we do not need to + // migrate the original logic which does not store initiator. + if locallyInitiated { + status |= ChanStatusLocalCloseInitiator + } else { + status |= ChanStatusRemoteCloseInitiator + } + return c.putChanStatus(status, putClosingTx) } diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index cb29b52131..ad7a69755b 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -1089,13 +1089,13 @@ func TestFetchWaitingCloseChannels(t *testing.T) { }, ) - if err := channel.MarkCommitmentBroadcasted(closeTx); err != nil { + if err := channel.MarkCommitmentBroadcasted(closeTx, true); err != nil { t.Fatalf("unable to mark commitment broadcast: %v", err) } // Now try to marking a coop close with a nil tx. This should // succeed, but it shouldn't exit when queried. - if err = channel.MarkCoopBroadcasted(nil); err != nil { + if err = channel.MarkCoopBroadcasted(nil, true); err != nil { t.Fatalf("unable to mark nil coop broadcast: %v", err) } _, err := channel.BroadcastedCooperative() @@ -1107,7 +1107,7 @@ func TestFetchWaitingCloseChannels(t *testing.T) { // it as coop closed. Later we will test that distinct // transactions are returned for both coop and force closes. closeTx.TxIn[0].PreviousOutPoint.Index ^= 1 - if err := channel.MarkCoopBroadcasted(closeTx); err != nil { + if err := channel.MarkCoopBroadcasted(closeTx, true); err != nil { t.Fatalf("unable to mark coop broadcast: %v", err) } } @@ -1255,3 +1255,105 @@ func TestRefreshShortChanID(t *testing.T) { t.Fatalf("channel pending state wasn't updated: want false got true") } } + +// TestCloseInitiator tests the setting of close initiator statuses for +// cooperative closes and local force closes. +func TestCloseInitiator(t *testing.T) { + tests := []struct { + name string + // updateChannel is called to update the channel as broadcast, + // cooperatively or not, based on the test's requirements. + updateChannel func(c *OpenChannel) error + expectedStatuses []ChannelStatus + }{ + { + name: "local coop close", + // Mark the channel as cooperatively closed, initiated + // by the local party. + updateChannel: func(c *OpenChannel) error { + return c.MarkCoopBroadcasted( + &wire.MsgTx{}, true, + ) + }, + expectedStatuses: []ChannelStatus{ + ChanStatusLocalCloseInitiator, + ChanStatusCoopBroadcasted, + }, + }, + { + name: "remote coop close", + // Mark the channel as cooperatively closed, initiated + // by the remote party. + updateChannel: func(c *OpenChannel) error { + return c.MarkCoopBroadcasted( + &wire.MsgTx{}, false, + ) + }, + expectedStatuses: []ChannelStatus{ + ChanStatusRemoteCloseInitiator, + ChanStatusCoopBroadcasted, + }, + }, + { + name: "local force close", + // Mark the channel's commitment as broadcast with + // local initiator. + updateChannel: func(c *OpenChannel) error { + return c.MarkCommitmentBroadcasted( + &wire.MsgTx{}, true, + ) + }, + expectedStatuses: []ChannelStatus{ + ChanStatusLocalCloseInitiator, + ChanStatusCommitBroadcasted, + }, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + cdb, cleanUp, err := makeTestDB() + if err != nil { + t.Fatalf("unable to make test database: %v", + err) + } + defer cleanUp() + + // Create an open channel. + channel := createTestChannel( + t, cdb, openChannelOption(), + ) + + err = test.updateChannel(channel) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + // Lookup open channels in the database. + dbChans, err := fetchChannels( + cdb, pendingChannelFilter(false), + ) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(dbChans) != 1 { + t.Fatalf("expected 1 channel, got: %v", + len(dbChans)) + } + + // Check that the statuses that we expect were written + // to disk. + for _, status := range test.expectedStatuses { + if !dbChans[0].HasChanStatus(status) { + t.Fatalf("expected channel to have "+ + "status: %v, has status: %v", + status, dbChans[0].chanStatus) + } + } + }) + } +} diff --git a/channeldb/db_test.go b/channeldb/db_test.go index 4d678303aa..e678d2a504 100644 --- a/channeldb/db_test.go +++ b/channeldb/db_test.go @@ -647,7 +647,7 @@ func TestFetchChannels(t *testing.T) { channelIDOption(pendingWaitingChan), ) - err = pendingClosing.MarkCoopBroadcasted(nil) + err = pendingClosing.MarkCoopBroadcasted(nil, true) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -667,7 +667,7 @@ func TestFetchChannels(t *testing.T) { channelIDOption(openWaitingChan), openChannelOption(), ) - err = openClosing.MarkCoopBroadcasted(nil) + err = openClosing.MarkCoopBroadcasted(nil, true) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/contractcourt/chain_arbitrator_test.go b/contractcourt/chain_arbitrator_test.go index 5710b14ae3..0ac7484a50 100644 --- a/contractcourt/chain_arbitrator_test.go +++ b/contractcourt/chain_arbitrator_test.go @@ -62,12 +62,12 @@ func TestChainArbitratorRepublishCloses(t *testing.T) { for i := 0; i < numChans/2; i++ { closeTx := channels[i].FundingTxn.Copy() closeTx.TxIn[0].PreviousOutPoint = channels[i].FundingOutpoint - err := channels[i].MarkCommitmentBroadcasted(closeTx) + err := channels[i].MarkCommitmentBroadcasted(closeTx, true) if err != nil { t.Fatal(err) } - err = channels[i].MarkCoopBroadcasted(closeTx) + err = channels[i].MarkCoopBroadcasted(closeTx, true) if err != nil { t.Fatal(err) } diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index b11c81aab9..6db666c909 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -98,7 +98,7 @@ type ChannelArbitratorConfig struct { // MarkCommitmentBroadcasted should mark the channel as the commitment // being broadcast, and we are waiting for the commitment to confirm. - MarkCommitmentBroadcasted func(*wire.MsgTx) error + MarkCommitmentBroadcasted func(*wire.MsgTx, bool) error // MarkChannelClosed marks the channel closed in the database, with the // passed close summary. After this method successfully returns we can @@ -797,8 +797,10 @@ func (c *ChannelArbitrator) stateStep( // Before publishing the transaction, we store it to the // database, such that we can re-publish later in case it - // didn't propagate. - if err := c.cfg.MarkCommitmentBroadcasted(closeTx); err != nil { + // didn't propagate. We initiated the force close, so we + // mark broadcast with local initiator set to true. + err = c.cfg.MarkCommitmentBroadcasted(closeTx, true) + if err != nil { log.Errorf("ChannelArbitrator(%v): unable to "+ "mark commitment broadcasted: %v", c.cfg.ChanPoint, err) diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index 9375d895bb..0abfb381a2 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -339,7 +339,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog) (*chanArbTestC } return summary, nil }, - MarkCommitmentBroadcasted: func(_ *wire.MsgTx) error { + MarkCommitmentBroadcasted: func(_ *wire.MsgTx, _ bool) error { return nil }, MarkChannelClosed: func(*channeldb.ChannelCloseSummary) error { diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 08ec5ebcaf..fa96f8c4a0 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -6433,22 +6433,28 @@ func (lc *LightningChannel) MarkBorked() error { // MarkCommitmentBroadcasted marks the channel as a commitment transaction has // been broadcast, either our own or the remote, and we should watch the chain -// for it to confirm before taking any further action. -func (lc *LightningChannel) MarkCommitmentBroadcasted(tx *wire.MsgTx) error { +// for it to confirm before taking any further action. It takes a boolean which +// indicates whether we initiated the close. +func (lc *LightningChannel) MarkCommitmentBroadcasted(tx *wire.MsgTx, + locallyInitiated bool) error { + lc.Lock() defer lc.Unlock() - return lc.channelState.MarkCommitmentBroadcasted(tx) + return lc.channelState.MarkCommitmentBroadcasted(tx, locallyInitiated) } // MarkCoopBroadcasted marks the channel as a cooperative close transaction has // been broadcast, and that we should watch the chain for it to confirm before -// taking any further action. -func (lc *LightningChannel) MarkCoopBroadcasted(tx *wire.MsgTx) error { +// taking any further action. It takes a locally initiated bool which is true +// if we initiated the cooperative close. +func (lc *LightningChannel) MarkCoopBroadcasted(tx *wire.MsgTx, + localInitiated bool) error { + lc.Lock() defer lc.Unlock() - return lc.channelState.MarkCoopBroadcasted(tx) + return lc.channelState.MarkCoopBroadcasted(tx, localInitiated) } // MarkDataLoss marks sets the channel status to LocalDataLoss and stores the diff --git a/peer.go b/peer.go index ea482d1f51..02544fe4f2 100644 --- a/peer.go +++ b/peer.go @@ -2119,6 +2119,7 @@ func (p *peer) fetchActiveChanCloser(chanID lnwire.ChannelID) (*channelCloser, e feePerKw, uint32(startingHeight), nil, + false, ) p.activeChanCloses[chanID] = chanCloser } @@ -2231,6 +2232,7 @@ func (p *peer) handleLocalCloseReq(req *htlcswitch.ChanClose) { req.TargetFeePerKw, uint32(startingHeight), req, + true, ) p.activeChanCloses[chanID] = chanCloser From 11d975bd131bc0a5e49903e67714c74d6bd0d0a3 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 21 Feb 2020 13:24:23 +0200 Subject: [PATCH 107/562] channeldb: save channel status on channel close Add an optional channel status CloseChannel which will be stored on the hitsorical channel which is persisted at channel close. This status is used to set the close initiator for channels that do not complete the funding flow or we abandon. In follow up commits, this status will be used to record force and breach closes. The value is written to the historical channel bucket for diplay over rpc. --- channeldb/channel.go | 13 +++++++++++-- channeldb/channel_test.go | 36 ++++++++++++++++++++++++++++++++++++ channeldb/db.go | 5 +++-- fundingmanager.go | 12 ++++++++++-- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index bc20548866..0914f24244 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -2382,8 +2382,12 @@ type ChannelCloseSummary struct { // entails deleting all saved state within the database concerning this // channel. This method also takes a struct that summarizes the state of the // channel at closing, this compact representation will be the only component -// of a channel left over after a full closing. -func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary) error { +// of a channel left over after a full closing. It takes an optional set of +// channel statuses which will be written to the historical channel bucket. +// These statuses are used to record close initiators. +func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary, + statuses ...ChannelStatus) error { + c.Lock() defer c.Unlock() @@ -2461,6 +2465,11 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary) error { return err } + // Apply any additional statuses to the channel state. + for _, status := range statuses { + chanState.chanStatus |= status + } + err = putOpenChannel(historicalChanBucket, chanState) if err != nil { return err diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index ad7a69755b..bd2ab8b732 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -1357,3 +1357,39 @@ func TestCloseInitiator(t *testing.T) { }) } } + +// TestCloseChannelStatus tests setting of a channel status on the historical +// channel on channel close. +func TestCloseChannelStatus(t *testing.T) { + cdb, cleanUp, err := makeTestDB() + if err != nil { + t.Fatalf("unable to make test database: %v", + err) + } + defer cleanUp() + + // Create an open channel. + channel := createTestChannel( + t, cdb, openChannelOption(), + ) + + if err := channel.CloseChannel( + &ChannelCloseSummary{ + ChanPoint: channel.FundingOutpoint, + RemotePub: channel.IdentityPub, + }, ChanStatusRemoteCloseInitiator, + ); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + histChan, err := channel.Db.FetchHistoricalChannel( + &channel.FundingOutpoint, + ) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !histChan.HasChanStatus(ChanStatusRemoteCloseInitiator) { + t.Fatalf("channel should have status") + } +} diff --git a/channeldb/db.go b/channeldb/db.go index 6377df63a3..c1cf46ba80 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -1159,8 +1159,9 @@ func (d *DB) AbandonChannel(chanPoint *wire.OutPoint, bestHeight uint32) error { } // Finally, we'll close the channel in the DB, and return back to the - // caller. - return dbChan.CloseChannel(summary) + // caller. We set ourselves as the close initiator because we abandoned + // the channel. + return dbChan.CloseChannel(summary, ChanStatusLocalCloseInitiator) } // syncVersions function is used for safe db version synchronization. It diff --git a/fundingmanager.go b/fundingmanager.go index 8484b94554..7913a11f66 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -1009,7 +1009,11 @@ func (f *fundingManager) advancePendingChannelState( LocalChanConfig: ch.LocalChanCfg, } - if err := ch.CloseChannel(closeInfo); err != nil { + // Close the channel with us as the initiator because we are + // timing the channel out. + if err := ch.CloseChannel( + closeInfo, channeldb.ChanStatusLocalCloseInitiator, + ); err != nil { return fmt.Errorf("failed closing channel "+ "%v: %v", ch.FundingOutpoint, err) } @@ -1639,7 +1643,11 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { LocalChanConfig: completeChan.LocalChanCfg, } - if err := completeChan.CloseChannel(closeInfo); err != nil { + // Close the channel with us as the initiator because we are + // deciding to exit the funding flow due to an internal error. + if err := completeChan.CloseChannel( + closeInfo, channeldb.ChanStatusLocalCloseInitiator, + ); err != nil { fndgLog.Errorf("Failed closing channel %v: %v", completeChan.FundingOutpoint, err) } From c9915e027e02b21e01222c40afd8e6259592ab34 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 21 Feb 2020 13:24:23 +0200 Subject: [PATCH 108/562] contractcourt/test: replace timeouts with constants --- contractcourt/channel_arbitrator_test.go | 68 +++++++++++++----------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index 0abfb381a2..2e7d40632a 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -21,6 +21,14 @@ import ( "github.com/lightningnetwork/lnd/lnwire" ) +const ( + defaultTimeout = time.Second * 5 + + // stateTimeout is the timeout we allow when waiting for state + // transitions. + stateTimeout = time.Second * 15 +) + type mockArbitratorLog struct { state ArbitratorState newStates chan ArbitratorState @@ -221,7 +229,7 @@ func (c *chanArbTestCtx) AssertStateTransitions(expectedStates ...ArbitratorStat var state ArbitratorState select { case state = <-newStatesChan: - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): c.t.Fatalf("new state not received") } @@ -441,7 +449,7 @@ func TestChannelArbitratorCooperativeClose(t *testing.T) { if c.CloseType != channeldb.CooperativeClose { t.Fatalf("expected cooperative close, got %v", c.CloseType) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("timeout waiting for channel close") } @@ -449,7 +457,7 @@ func TestChannelArbitratorCooperativeClose(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("contract was not resolved") } } @@ -504,7 +512,7 @@ func TestChannelArbitratorRemoteForceClose(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("contract was not resolved") } } @@ -566,7 +574,7 @@ func TestChannelArbitratorLocalForceClose(t *testing.T) { if state != StateBroadcastCommit { t.Fatalf("state during PublishTx was %v", state) } - case <-time.After(15 * time.Second): + case <-time.After(stateTimeout): t.Fatalf("did not get state update") } @@ -576,7 +584,7 @@ func TestChannelArbitratorLocalForceClose(t *testing.T) { select { case <-respChan: - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -585,7 +593,7 @@ func TestChannelArbitratorLocalForceClose(t *testing.T) { if err != nil { t.Fatalf("error force closing channel: %v", err) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -610,7 +618,7 @@ func TestChannelArbitratorLocalForceClose(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("contract was not resolved") } } @@ -654,7 +662,7 @@ func TestChannelArbitratorBreachClose(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("contract was not resolved") } } @@ -738,7 +746,7 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) { ) select { case <-respChan: - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -747,7 +755,7 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) { if err != nil { t.Fatalf("error force closing channel: %v", err) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -825,7 +833,7 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) { t.Fatalf("wrong htlc index: expected %v, got %v", outgoingDustHtlc.HtlcIndex, msgs[0].HtlcIndex) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("resolution msgs not sent") } @@ -887,7 +895,7 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) { // htlcTimeoutResolver and should send the contract off for incubation. select { case <-chanArbCtx.incubationRequests: - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -907,7 +915,7 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) { t.Fatalf("wrong htlc index: expected %v, got %v", htlc.HtlcIndex, msgs[0].HtlcIndex) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("resolution msgs not sent") } @@ -927,7 +935,7 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) { chanArbCtxNew.AssertStateTransitions(StateFullyResolved) select { case <-chanArbCtxNew.resolvedChan: - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("contract was not resolved") } } @@ -989,7 +997,7 @@ func TestChannelArbitratorLocalForceCloseRemoteConfirmed(t *testing.T) { if state != StateBroadcastCommit { t.Fatalf("state during PublishTx was %v", state) } - case <-time.After(15 * time.Second): + case <-time.After(stateTimeout): t.Fatalf("no state update received") } @@ -1000,7 +1008,7 @@ func TestChannelArbitratorLocalForceCloseRemoteConfirmed(t *testing.T) { // Wait for a response to the force close. select { case <-respChan: - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -1009,7 +1017,7 @@ func TestChannelArbitratorLocalForceCloseRemoteConfirmed(t *testing.T) { if err != nil { t.Fatalf("error force closing channel: %v", err) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -1035,7 +1043,7 @@ func TestChannelArbitratorLocalForceCloseRemoteConfirmed(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(15 * time.Second): + case <-time.After(stateTimeout): t.Fatalf("contract was not resolved") } } @@ -1097,7 +1105,7 @@ func TestChannelArbitratorLocalForceDoubleSpend(t *testing.T) { if state != StateBroadcastCommit { t.Fatalf("state during PublishTx was %v", state) } - case <-time.After(15 * time.Second): + case <-time.After(stateTimeout): t.Fatalf("no state update received") } @@ -1108,7 +1116,7 @@ func TestChannelArbitratorLocalForceDoubleSpend(t *testing.T) { // Wait for a response to the force close. select { case <-respChan: - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -1117,7 +1125,7 @@ func TestChannelArbitratorLocalForceDoubleSpend(t *testing.T) { if err != nil { t.Fatalf("error force closing channel: %v", err) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -1143,7 +1151,7 @@ func TestChannelArbitratorLocalForceDoubleSpend(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(15 * time.Second): + case <-time.After(stateTimeout): t.Fatalf("contract was not resolved") } } @@ -1264,7 +1272,7 @@ func TestChannelArbitratorPersistence(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("contract was not resolved") } } @@ -1328,7 +1336,7 @@ func TestChannelArbitratorForceCloseBreachedChannel(t *testing.T) { if state != StateBroadcastCommit { t.Fatalf("state during PublishTx was %v", state) } - case <-time.After(15 * time.Second): + case <-time.After(stateTimeout): t.Fatalf("no state update received") } @@ -1339,7 +1347,7 @@ func TestChannelArbitratorForceCloseBreachedChannel(t *testing.T) { t.Fatalf("unexpected error force closing channel: %v", err) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("no response received") } @@ -1363,7 +1371,7 @@ func TestChannelArbitratorForceCloseBreachedChannel(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("contract was not resolved") } } @@ -1467,7 +1475,7 @@ func TestChannelArbitratorCommitFailure(t *testing.T) { select { case <-closed: - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("channel was not marked closed") } @@ -1501,7 +1509,7 @@ func TestChannelArbitratorCommitFailure(t *testing.T) { select { case <-chanArbCtx.resolvedChan: // Expected. - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("contract was not resolved") } } @@ -1805,7 +1813,7 @@ func TestChannelArbitratorDanglingCommitForceClose(t *testing.T) { t.Fatalf("wrong htlc index: expected %v, got %v", htlcIndex, msgs[0].HtlcIndex) } - case <-time.After(5 * time.Second): + case <-time.After(defaultTimeout): t.Fatalf("resolution msgs not sent") } From 4eb3036f6773a5b0881ea007e3022e8fd05a59b4 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 21 Feb 2020 13:49:12 +0200 Subject: [PATCH 109/562] contractcourt: record force and breach close initiator --- contractcourt/chain_arbitrator.go | 7 +- contractcourt/chain_watcher.go | 4 +- contractcourt/channel_arbitrator.go | 11 +- contractcourt/channel_arbitrator_test.go | 194 ++++++++++++++++++++++- 4 files changed, 202 insertions(+), 14 deletions(-) diff --git a/contractcourt/chain_arbitrator.go b/contractcourt/chain_arbitrator.go index 552549f463..7a9cb3095c 100644 --- a/contractcourt/chain_arbitrator.go +++ b/contractcourt/chain_arbitrator.go @@ -284,8 +284,11 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel, return chanMachine.ForceClose() }, MarkCommitmentBroadcasted: channel.MarkCommitmentBroadcasted, - MarkChannelClosed: func(summary *channeldb.ChannelCloseSummary) error { - if err := channel.CloseChannel(summary); err != nil { + MarkChannelClosed: func(summary *channeldb.ChannelCloseSummary, + statuses ...channeldb.ChannelStatus) error { + + err := channel.CloseChannel(summary, statuses...) + if err != nil { return err } c.cfg.NotifyClosedChannel(summary.ChanPoint) diff --git a/contractcourt/chain_watcher.go b/contractcourt/chain_watcher.go index c08916d010..3012376b39 100644 --- a/contractcourt/chain_watcher.go +++ b/contractcourt/chain_watcher.go @@ -985,7 +985,9 @@ func (c *chainWatcher) dispatchContractBreach(spendEvent *chainntnfs.SpendDetail closeSummary.LastChanSyncMsg = chanSync } - if err := c.cfg.chanState.CloseChannel(&closeSummary); err != nil { + if err := c.cfg.chanState.CloseChannel( + &closeSummary, channeldb.ChanStatusRemoteCloseInitiator, + ); err != nil { return err } diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 6db666c909..2a58ea523e 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -104,8 +104,10 @@ type ChannelArbitratorConfig struct { // passed close summary. After this method successfully returns we can // no longer expect to receive chain events for this channel, and must // be able to recover from a failure without getting the close event - // again. - MarkChannelClosed func(*channeldb.ChannelCloseSummary) error + // again. It takes an optional channel status which will update the + // channel status in the record that we keep of historical channels. + MarkChannelClosed func(*channeldb.ChannelCloseSummary, + ...channeldb.ChannelStatus) error // IsPendingClose is a boolean indicating whether the channel is marked // as pending close in the database. @@ -2178,7 +2180,10 @@ func (c *ChannelArbitrator) channelAttendant(bestHeight int32) { // transition into StateContractClosed based on the // close status of the channel. closeSummary := &uniClosure.ChannelCloseSummary - err = c.cfg.MarkChannelClosed(closeSummary) + err = c.cfg.MarkChannelClosed( + closeSummary, + channeldb.ChanStatusRemoteCloseInitiator, + ) if err != nil { log.Errorf("Unable to mark channel closed: %v", err) diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index 2e7d40632a..0a73cd5e90 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" @@ -274,7 +275,26 @@ func (c *chanArbTestCtx) Restart(restartClosure func(*chanArbTestCtx)) (*chanArb return newCtx, nil } -func createTestChannelArbitrator(t *testing.T, log ArbitratorLog) (*chanArbTestCtx, error) { +// testChanArbOption applies custom settings to a channel arbitrator config for +// testing purposes. +type testChanArbOption func(cfg *ChannelArbitratorConfig) + +// remoteInitiatorOption sets the MarkChannelClosed function in the +// Channel Arbitrator's config. +func withMarkClosed(markClosed func(*channeldb.ChannelCloseSummary, + ...channeldb.ChannelStatus) error) testChanArbOption { + + return func(cfg *ChannelArbitratorConfig) { + cfg.MarkChannelClosed = markClosed + } +} + +// createTestChannelArbitrator returns a channel arbitrator test context which +// contains a channel arbitrator with default values. These values can be +// changed by providing options which overwrite the default config. +func createTestChannelArbitrator(t *testing.T, log ArbitratorLog, + opts ...testChanArbOption) (*chanArbTestCtx, error) { + blockEpochs := make(chan *chainntnfs.BlockEpoch) blockEpoch := &chainntnfs.BlockEpochEvent{ Epochs: blockEpochs, @@ -332,7 +352,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog) (*chanArbTestC // Next we'll create the matching configuration struct that contains // all interfaces and methods the arbitrator needs to do its job. - arbCfg := ChannelArbitratorConfig{ + arbCfg := &ChannelArbitratorConfig{ ChanPoint: chanPoint, ShortChanID: shortChanID, BlockEpochs: blockEpoch, @@ -350,7 +370,8 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog) (*chanArbTestC MarkCommitmentBroadcasted: func(_ *wire.MsgTx, _ bool) error { return nil }, - MarkChannelClosed: func(*channeldb.ChannelCloseSummary) error { + MarkChannelClosed: func(*channeldb.ChannelCloseSummary, + ...channeldb.ChannelStatus) error { return nil }, IsPendingClose: false, @@ -358,6 +379,11 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog) (*chanArbTestC ChainEvents: chanEvents, } + // Apply all custom options to the config struct. + for _, option := range opts { + option(arbCfg) + } + var cleanUp func() if log == nil { dbDir, err := ioutil.TempDir("", "chanArb") @@ -371,7 +397,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog) (*chanArbTestC } backingLog, err := newBoltArbitratorLog( - db, arbCfg, chainhash.Hash{}, chanPoint, + db, *arbCfg, chainhash.Hash{}, chanPoint, ) if err != nil { return nil, err @@ -389,7 +415,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog) (*chanArbTestC htlcSets := make(map[HtlcSetKey]htlcSet) - chanArb := NewChannelArbitrator(arbCfg, htlcSets, log) + chanArb := NewChannelArbitrator(*arbCfg, htlcSets, log) return &chanArbTestCtx{ t: t, @@ -432,7 +458,9 @@ func TestChannelArbitratorCooperativeClose(t *testing.T) { // We set up a channel to detect when MarkChannelClosed is called. closeInfos := make(chan *channeldb.ChannelCloseSummary) chanArbCtx.chanArb.cfg.MarkChannelClosed = func( - closeInfo *channeldb.ChannelCloseSummary) error { + closeInfo *channeldb.ChannelCloseSummary, + statuses ...channeldb.ChannelStatus) error { + closeInfos <- closeInfo return nil } @@ -1213,7 +1241,9 @@ func TestChannelArbitratorPersistence(t *testing.T) { // Now we make the log succeed writing the resolutions, but fail when // attempting to close the channel. log.failLog = false - chanArb.cfg.MarkChannelClosed = func(*channeldb.ChannelCloseSummary) error { + chanArb.cfg.MarkChannelClosed = func(*channeldb.ChannelCloseSummary, + ...channeldb.ChannelStatus) error { + return fmt.Errorf("intentional close error") } @@ -1465,7 +1495,8 @@ func TestChannelArbitratorCommitFailure(t *testing.T) { closed := make(chan struct{}) chanArb.cfg.MarkChannelClosed = func( - *channeldb.ChannelCloseSummary) error { + *channeldb.ChannelCloseSummary, + ...channeldb.ChannelStatus) error { close(closed) return nil } @@ -1910,3 +1941,150 @@ func TestChannelArbitratorPendingExpiredHTLC(t *testing.T) { StateCommitmentBroadcasted, ) } + +// TestRemoteCloseInitiator tests the setting of close initiator statuses +// for remote force closes and breaches. +func TestRemoteCloseInitiator(t *testing.T) { + // getCloseSummary returns a unilateral close summary for the channel + // provided. + getCloseSummary := func(channel *channeldb.OpenChannel) *RemoteUnilateralCloseInfo { + return &RemoteUnilateralCloseInfo{ + UnilateralCloseSummary: &lnwallet.UnilateralCloseSummary{ + SpendDetail: &chainntnfs.SpendDetail{ + SpenderTxHash: &chainhash.Hash{}, + SpendingTx: &wire.MsgTx{ + TxIn: []*wire.TxIn{}, + TxOut: []*wire.TxOut{}, + }, + }, + ChannelCloseSummary: channeldb.ChannelCloseSummary{ + ChanPoint: channel.FundingOutpoint, + RemotePub: channel.IdentityPub, + SettledBalance: btcutil.Amount(500), + TimeLockedBalance: btcutil.Amount(10000), + IsPending: false, + }, + HtlcResolutions: &lnwallet.HtlcResolutions{}, + }, + } + } + + tests := []struct { + name string + + // notifyClose sends the appropriate chain event to indicate + // that the channel has closed. The event subscription channel + // is expected to be buffered, as is the default for test + // channel arbitrators. + notifyClose func(sub *ChainEventSubscription, + channel *channeldb.OpenChannel) + + // expectedStates is the set of states we expect the arbitrator + // to progress through. + expectedStates []ArbitratorState + }{ + { + name: "force close", + notifyClose: func(sub *ChainEventSubscription, + channel *channeldb.OpenChannel) { + + s := getCloseSummary(channel) + sub.RemoteUnilateralClosure <- s + }, + expectedStates: []ArbitratorState{ + StateContractClosed, StateFullyResolved, + }, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + // First, create alice's channel. + alice, _, cleanUp, err := lnwallet.CreateTestChannels( + true, + ) + if err != nil { + t.Fatalf("unable to create test channels: %v", + err) + } + defer cleanUp() + + // Create a mock log which will not block the test's + // expected number of transitions transitions, and has + // no commit resolutions so that the channel will + // resolve immediately. + log := &mockArbitratorLog{ + state: StateDefault, + newStates: make(chan ArbitratorState, + len(test.expectedStates)), + resolutions: &ContractResolutions{ + CommitHash: chainhash.Hash{}, + CommitResolution: nil, + }, + } + + // Mock marking the channel as closed, we only care + // about setting of channel status. + mockMarkClosed := func(_ *channeldb.ChannelCloseSummary, + statuses ...channeldb.ChannelStatus) error { + for _, status := range statuses { + err := alice.State().ApplyChanStatus(status) + if err != nil { + return err + } + } + return nil + } + + chanArbCtx, err := createTestChannelArbitrator( + t, log, withMarkClosed(mockMarkClosed), + ) + if err != nil { + t.Fatalf("unable to create "+ + "ChannelArbitrator: %v", err) + } + chanArb := chanArbCtx.chanArb + + if err := chanArb.Start(); err != nil { + t.Fatalf("unable to start "+ + "ChannelArbitrator: %v", err) + } + defer func() { + if err := chanArb.Stop(); err != nil { + t.Fatal(err) + } + }() + + // It should start out in the default state. + chanArbCtx.AssertState(StateDefault) + + // Notify the close event. + test.notifyClose(chanArb.cfg.ChainEvents, alice.State()) + + // Check that the channel transitions as expected. + chanArbCtx.AssertStateTransitions( + test.expectedStates..., + ) + + // It should also mark the channel as resolved. + select { + case <-chanArbCtx.resolvedChan: + // Expected. + case <-time.After(defaultTimeout): + t.Fatalf("contract was not resolved") + } + + // Check that alice has the status we expect. + if !alice.State().HasChanStatus( + channeldb.ChanStatusRemoteCloseInitiator, + ) { + t.Fatalf("expected remote close initiator, "+ + "got: %v", alice.State().ChanStatus()) + } + }) + } +} From b55470e9a9076c7f3a07a84318b7af7e138da1d8 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 21 Feb 2020 13:24:24 +0200 Subject: [PATCH 110/562] lnrpc: add open and close initiator to close summary Add an initiator enum which allows up to display an unknown value for channels that are not in the historical chan bucket, rather than having and ambiguous false value also representing no-value. A both option is added to cover the case where both parties initiated a close on chain. --- lnrpc/rpc.pb.go | 1304 +++++++++++++++++++++------------------- lnrpc/rpc.proto | 23 + lnrpc/rpc.swagger.json | 18 + 3 files changed, 724 insertions(+), 621 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index fa2d711766..7ee3b08b6e 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -194,6 +194,37 @@ func (ChannelCloseSummary_ClosureType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_77a6da22d6a3feb1, []int{43, 0} } +type ChannelCloseSummary_Initiator int32 + +const ( + ChannelCloseSummary_UNKNOWN ChannelCloseSummary_Initiator = 0 + ChannelCloseSummary_LOCAL ChannelCloseSummary_Initiator = 1 + ChannelCloseSummary_REMOTE ChannelCloseSummary_Initiator = 2 + ChannelCloseSummary_BOTH ChannelCloseSummary_Initiator = 3 +) + +var ChannelCloseSummary_Initiator_name = map[int32]string{ + 0: "UNKNOWN", + 1: "LOCAL", + 2: "REMOTE", + 3: "BOTH", +} + +var ChannelCloseSummary_Initiator_value = map[string]int32{ + "UNKNOWN": 0, + "LOCAL": 1, + "REMOTE": 2, + "BOTH": 3, +} + +func (x ChannelCloseSummary_Initiator) String() string { + return proto.EnumName(ChannelCloseSummary_Initiator_name, int32(x)) +} + +func (ChannelCloseSummary_Initiator) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{43, 1} +} + type Peer_SyncType int32 const ( @@ -3188,10 +3219,22 @@ type ChannelCloseSummary struct { /// The sum of all the time-locked outputs at the time of channel closure TimeLockedBalance int64 `protobuf:"varint,9,opt,name=time_locked_balance,proto3" json:"time_locked_balance,omitempty"` /// Details on how the channel was closed. - CloseType ChannelCloseSummary_ClosureType `protobuf:"varint,10,opt,name=close_type,proto3,enum=lnrpc.ChannelCloseSummary_ClosureType" json:"close_type,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + CloseType ChannelCloseSummary_ClosureType `protobuf:"varint,10,opt,name=close_type,proto3,enum=lnrpc.ChannelCloseSummary_ClosureType" json:"close_type,omitempty"` + //* + //Open initiator is the party that initiated opening the channel. Note that + //this value may be unknown if the channel was closed before we migrated to + //store open channel information after close. + OpenInitiator ChannelCloseSummary_Initiator `protobuf:"varint,11,opt,name=open_initiator,proto3,enum=lnrpc.ChannelCloseSummary_Initiator" json:"open_initiator,omitempty"` + //* + //Close initiator indicates which party initiated the close. This value will + //be unknown for channels that were cooperatively closed before we started + //tracking cooperative close initiators. Note that this indicates which party + //initiated a close, and it is possible for both to initiate cooperative or + //force closes, although only one party's close will be confirmed on chain. + CloseInitiator ChannelCloseSummary_Initiator `protobuf:"varint,12,opt,name=close_initiator,proto3,enum=lnrpc.ChannelCloseSummary_Initiator" json:"close_initiator,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ChannelCloseSummary) Reset() { *m = ChannelCloseSummary{} } @@ -3289,6 +3332,20 @@ func (m *ChannelCloseSummary) GetCloseType() ChannelCloseSummary_ClosureType { return ChannelCloseSummary_COOPERATIVE_CLOSE } +func (m *ChannelCloseSummary) GetOpenInitiator() ChannelCloseSummary_Initiator { + if m != nil { + return m.OpenInitiator + } + return ChannelCloseSummary_UNKNOWN +} + +func (m *ChannelCloseSummary) GetCloseInitiator() ChannelCloseSummary_Initiator { + if m != nil { + return m.CloseInitiator + } + return ChannelCloseSummary_UNKNOWN +} + type ClosedChannelsRequest struct { Cooperative bool `protobuf:"varint,1,opt,name=cooperative,proto3" json:"cooperative,omitempty"` LocalForce bool `protobuf:"varint,2,opt,name=local_force,json=localForce,proto3" json:"local_force,omitempty"` @@ -10397,6 +10454,7 @@ func init() { proto.RegisterEnum("lnrpc.InvoiceHTLCState", InvoiceHTLCState_name, InvoiceHTLCState_value) proto.RegisterEnum("lnrpc.FeatureBit", FeatureBit_name, FeatureBit_value) proto.RegisterEnum("lnrpc.ChannelCloseSummary_ClosureType", ChannelCloseSummary_ClosureType_name, ChannelCloseSummary_ClosureType_value) + proto.RegisterEnum("lnrpc.ChannelCloseSummary_Initiator", ChannelCloseSummary_Initiator_name, ChannelCloseSummary_Initiator_value) proto.RegisterEnum("lnrpc.Peer_SyncType", Peer_SyncType_name, Peer_SyncType_value) proto.RegisterEnum("lnrpc.PeerEvent_EventType", PeerEvent_EventType_name, PeerEvent_EventType_value) proto.RegisterEnum("lnrpc.ChannelEventUpdate_UpdateType", ChannelEventUpdate_UpdateType_name, ChannelEventUpdate_UpdateType_value) @@ -10570,624 +10628,628 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 9864 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x6c, 0x1c, 0xd9, - 0x95, 0x98, 0xaa, 0x1f, 0x64, 0xf7, 0xe9, 0x07, 0x9b, 0x97, 0x14, 0xd9, 0x6a, 0x3d, 0x46, 0x53, - 0xd6, 0xce, 0xc8, 0xf2, 0x98, 0xd2, 0xd0, 0xf6, 0xac, 0x76, 0x94, 0xf5, 0x9a, 0x2f, 0x89, 0x9c, - 0xa1, 0x48, 0xba, 0x48, 0x59, 0x6b, 0x3b, 0x8b, 0x72, 0xb1, 0xfb, 0x92, 0x2c, 0xab, 0xbb, 0xaa, - 0xa7, 0xaa, 0x9a, 0x14, 0xed, 0x4c, 0x3e, 0x82, 0x24, 0x08, 0xf2, 0x13, 0x18, 0x8b, 0x00, 0xd9, - 0x3c, 0xb0, 0x80, 0x37, 0x41, 0x10, 0x04, 0x48, 0xf2, 0x15, 0x6c, 0x02, 0xe7, 0x2b, 0x1f, 0x9b, - 0x9f, 0x20, 0x1f, 0x09, 0x10, 0x20, 0x01, 0x02, 0x2c, 0x36, 0x1f, 0x59, 0x04, 0xc8, 0x57, 0x92, - 0xef, 0xe0, 0x9e, 0xfb, 0xa8, 0x7b, 0xab, 0xaa, 0x29, 0x8d, 0xed, 0xcc, 0x8f, 0xc4, 0x7b, 0xce, - 0xad, 0xfb, 0x3c, 0xe7, 0xdc, 0xf3, 0xba, 0xb7, 0xa1, 0x1e, 0x8d, 0xfb, 0x2b, 0xe3, 0x28, 0x4c, - 0x42, 0x52, 0x1d, 0x06, 0xd1, 0xb8, 0xdf, 0xbb, 0x75, 0x1a, 0x86, 0xa7, 0x43, 0xfa, 0xd0, 0x1b, - 0xfb, 0x0f, 0xbd, 0x20, 0x08, 0x13, 0x2f, 0xf1, 0xc3, 0x20, 0xe6, 0x95, 0xec, 0x1f, 0x41, 0xfb, - 0x19, 0x0d, 0x0e, 0x29, 0x1d, 0x38, 0xf4, 0xb3, 0x09, 0x8d, 0x13, 0xf2, 0x35, 0x98, 0xf7, 0xe8, - 0x4f, 0x28, 0x1d, 0xb8, 0x63, 0x2f, 0x8e, 0xc7, 0x67, 0x91, 0x17, 0xd3, 0xae, 0x75, 0xd7, 0xba, - 0xdf, 0x74, 0x3a, 0x1c, 0x71, 0xa0, 0xe0, 0xe4, 0x5d, 0x68, 0xc6, 0xac, 0x2a, 0x0d, 0x92, 0x28, - 0x1c, 0x5f, 0x76, 0x4b, 0x58, 0xaf, 0xc1, 0x60, 0x5b, 0x1c, 0x64, 0x0f, 0x61, 0x4e, 0xf5, 0x10, - 0x8f, 0xc3, 0x20, 0xa6, 0xe4, 0x11, 0x2c, 0xf6, 0xfd, 0xf1, 0x19, 0x8d, 0x5c, 0xfc, 0x78, 0x14, - 0xd0, 0x51, 0x18, 0xf8, 0xfd, 0xae, 0x75, 0xb7, 0x7c, 0xbf, 0xee, 0x10, 0x8e, 0x63, 0x5f, 0x3c, - 0x17, 0x18, 0xf2, 0x3e, 0xcc, 0xd1, 0x80, 0xc3, 0xe9, 0x00, 0xbf, 0x12, 0x5d, 0xb5, 0x53, 0x30, - 0xfb, 0xc0, 0xfe, 0x1b, 0x25, 0x98, 0xdf, 0x09, 0xfc, 0xe4, 0xa5, 0x37, 0x1c, 0xd2, 0x44, 0xce, - 0xe9, 0x7d, 0x98, 0xbb, 0x40, 0x00, 0xce, 0xe9, 0x22, 0x8c, 0x06, 0x62, 0x46, 0x6d, 0x0e, 0x3e, - 0x10, 0xd0, 0xa9, 0x23, 0x2b, 0x4d, 0x1d, 0x59, 0xe1, 0x72, 0x95, 0xa7, 0x2c, 0xd7, 0xfb, 0x30, - 0x17, 0xd1, 0x7e, 0x78, 0x4e, 0xa3, 0x4b, 0xf7, 0xc2, 0x0f, 0x06, 0xe1, 0x45, 0xb7, 0x72, 0xd7, - 0xba, 0x5f, 0x75, 0xda, 0x12, 0xfc, 0x12, 0xa1, 0x64, 0x1d, 0xe6, 0xfa, 0x67, 0x5e, 0x10, 0xd0, - 0xa1, 0x7b, 0xec, 0xf5, 0x5f, 0x4d, 0xc6, 0x71, 0xb7, 0x7a, 0xd7, 0xba, 0xdf, 0x58, 0xbd, 0xb1, - 0x82, 0xbb, 0xba, 0xb2, 0x71, 0xe6, 0x05, 0xeb, 0x88, 0x39, 0x0c, 0xbc, 0x71, 0x7c, 0x16, 0x26, - 0x4e, 0x5b, 0x7c, 0xc1, 0xc1, 0xb1, 0xbd, 0x08, 0x44, 0x5f, 0x09, 0xbe, 0xf6, 0xf6, 0x3f, 0xb5, - 0x60, 0xe1, 0x45, 0x30, 0x0c, 0xfb, 0xaf, 0x7e, 0xc9, 0x25, 0x2a, 0x98, 0x43, 0xe9, 0x6d, 0xe7, - 0x50, 0xfe, 0xa2, 0x73, 0x58, 0x82, 0x45, 0x73, 0xb0, 0x62, 0x16, 0x14, 0xae, 0xb3, 0xaf, 0x4f, - 0xa9, 0x1c, 0x96, 0x9c, 0xc6, 0x57, 0xa1, 0xd3, 0x9f, 0x44, 0x11, 0x0d, 0x72, 0xf3, 0x98, 0x13, - 0x70, 0x35, 0x91, 0x77, 0xa1, 0x19, 0xd0, 0x8b, 0xb4, 0x9a, 0xa0, 0xdd, 0x80, 0x5e, 0xc8, 0x2a, - 0x76, 0x17, 0x96, 0xb2, 0xdd, 0x88, 0x01, 0xfc, 0xa9, 0x05, 0x95, 0x17, 0xc9, 0xeb, 0x90, 0xac, - 0x40, 0x25, 0xb9, 0x1c, 0x73, 0x0e, 0x69, 0xaf, 0x12, 0x31, 0xb5, 0xb5, 0xc1, 0x20, 0xa2, 0x71, - 0x7c, 0x74, 0x39, 0xa6, 0x4e, 0xd3, 0xe3, 0x05, 0x97, 0xd5, 0x23, 0x5d, 0x98, 0x15, 0x65, 0xec, - 0xb0, 0xee, 0xc8, 0x22, 0xb9, 0x03, 0xe0, 0x8d, 0xc2, 0x49, 0x90, 0xb8, 0xb1, 0x97, 0xe0, 0x52, - 0x95, 0x1d, 0x0d, 0x42, 0x6e, 0x41, 0x7d, 0xfc, 0xca, 0x8d, 0xfb, 0x91, 0x3f, 0x4e, 0x90, 0x6c, - 0xea, 0x4e, 0x0a, 0x20, 0x5f, 0x83, 0x5a, 0x38, 0x49, 0xc6, 0xa1, 0x1f, 0x24, 0x82, 0x54, 0xe6, - 0xc4, 0x58, 0xf6, 0x27, 0xc9, 0x01, 0x03, 0x3b, 0xaa, 0x02, 0xb9, 0x07, 0xad, 0x7e, 0x18, 0x9c, - 0xf8, 0xd1, 0x88, 0x0b, 0x83, 0xee, 0x0c, 0xf6, 0x66, 0x02, 0xed, 0x7f, 0x55, 0x82, 0xc6, 0x51, - 0xe4, 0x05, 0xb1, 0xd7, 0x67, 0x00, 0x36, 0xf4, 0xe4, 0xb5, 0x7b, 0xe6, 0xc5, 0x67, 0x38, 0xdb, - 0xba, 0x23, 0x8b, 0x64, 0x09, 0x66, 0xf8, 0x40, 0x71, 0x4e, 0x65, 0x47, 0x94, 0xc8, 0x07, 0x30, - 0x1f, 0x4c, 0x46, 0xae, 0xd9, 0x57, 0x19, 0xa9, 0x25, 0x8f, 0x60, 0x0b, 0x70, 0xcc, 0xf6, 0x9a, - 0x77, 0xc1, 0x67, 0xa8, 0x41, 0x88, 0x0d, 0x4d, 0x51, 0xa2, 0xfe, 0xe9, 0x19, 0x9f, 0x66, 0xd5, - 0x31, 0x60, 0xac, 0x8d, 0xc4, 0x1f, 0x51, 0x37, 0x4e, 0xbc, 0xd1, 0x58, 0x4c, 0x4b, 0x83, 0x20, - 0x3e, 0x4c, 0xbc, 0xa1, 0x7b, 0x42, 0x69, 0xdc, 0x9d, 0x15, 0x78, 0x05, 0x21, 0xef, 0x41, 0x7b, - 0x40, 0xe3, 0xc4, 0x15, 0x9b, 0x42, 0xe3, 0x6e, 0x0d, 0x59, 0x3f, 0x03, 0x65, 0xed, 0x44, 0xde, - 0x85, 0xcb, 0x16, 0x80, 0xbe, 0xee, 0xd6, 0xf9, 0x58, 0x53, 0x08, 0xa3, 0x9c, 0x67, 0x34, 0xd1, - 0x56, 0x2f, 0x16, 0x14, 0x6a, 0xef, 0x02, 0xd1, 0xc0, 0x9b, 0x34, 0xf1, 0xfc, 0x61, 0x4c, 0x3e, - 0x82, 0x66, 0xa2, 0x55, 0x46, 0x51, 0xd8, 0x50, 0xe4, 0xa4, 0x7d, 0xe0, 0x18, 0xf5, 0xec, 0x33, - 0xa8, 0x3d, 0xa5, 0x74, 0xd7, 0x1f, 0xf9, 0x09, 0x59, 0x82, 0xea, 0x89, 0xff, 0x9a, 0x72, 0x82, - 0x2f, 0x6f, 0x5f, 0x73, 0x78, 0x91, 0xbc, 0x03, 0x80, 0x7f, 0xb8, 0x23, 0x45, 0x58, 0xdb, 0xd7, - 0x9c, 0x3a, 0xc2, 0x9e, 0x33, 0xca, 0xea, 0xc1, 0xec, 0x98, 0x46, 0x7d, 0x2a, 0xf7, 0x6f, 0xfb, - 0x9a, 0x23, 0x01, 0xeb, 0xb3, 0x50, 0x1d, 0xb2, 0xd6, 0xed, 0x3f, 0xa9, 0x42, 0xe3, 0x90, 0x06, - 0x8a, 0xd3, 0x08, 0x54, 0xd8, 0x9a, 0x08, 0xee, 0xc2, 0xbf, 0xc9, 0x57, 0xa0, 0x81, 0xeb, 0x14, - 0x27, 0x91, 0x1f, 0x9c, 0x72, 0x02, 0x5f, 0x2f, 0x75, 0x2d, 0x07, 0x18, 0xf8, 0x10, 0xa1, 0xa4, - 0x03, 0x65, 0x6f, 0x24, 0x09, 0x9c, 0xfd, 0x49, 0x6e, 0x40, 0xcd, 0x1b, 0x25, 0x7c, 0x78, 0x4d, - 0x04, 0xcf, 0x7a, 0xa3, 0x04, 0x87, 0xf6, 0x2e, 0x34, 0xc7, 0xde, 0xe5, 0x88, 0xf1, 0xb3, 0xa2, - 0x8a, 0xa6, 0xd3, 0x10, 0xb0, 0x6d, 0x46, 0x16, 0xab, 0xb0, 0xa0, 0x57, 0x91, 0x9d, 0x57, 0x55, - 0xe7, 0xf3, 0x5a, 0x6d, 0x31, 0x86, 0xf7, 0x61, 0x4e, 0x7e, 0x13, 0xf1, 0xf9, 0x20, 0xad, 0xd4, - 0x9d, 0xb6, 0x00, 0xcb, 0x59, 0xde, 0x87, 0xce, 0x89, 0x1f, 0x78, 0x43, 0xb7, 0x3f, 0x4c, 0xce, - 0xdd, 0x01, 0x1d, 0x26, 0x1e, 0x52, 0x4d, 0xd5, 0x69, 0x23, 0x7c, 0x63, 0x98, 0x9c, 0x6f, 0x32, - 0x28, 0xf9, 0x00, 0xea, 0x27, 0x94, 0xba, 0xb8, 0x58, 0xdd, 0x9a, 0xc1, 0x81, 0x72, 0x87, 0x9c, - 0xda, 0x89, 0xdc, 0xab, 0x0f, 0xa0, 0x13, 0x4e, 0x92, 0xd3, 0xd0, 0x0f, 0x4e, 0x5d, 0x26, 0xf3, - 0x5c, 0x7f, 0x80, 0x54, 0x54, 0x59, 0x2f, 0x3d, 0xb2, 0x9c, 0xb6, 0xc4, 0x31, 0xe9, 0xb3, 0x33, - 0x20, 0xef, 0xc1, 0xdc, 0xd0, 0x8b, 0x13, 0xf7, 0x2c, 0x1c, 0xbb, 0xe3, 0xc9, 0xf1, 0x2b, 0x7a, - 0xd9, 0x6d, 0xe1, 0x42, 0xb4, 0x18, 0x78, 0x3b, 0x1c, 0x1f, 0x20, 0x90, 0xdc, 0x06, 0xc0, 0x71, - 0xf2, 0x41, 0xc0, 0x5d, 0xeb, 0x7e, 0xcb, 0xa9, 0x33, 0x08, 0xef, 0xf4, 0xfb, 0xb0, 0x80, 0xdb, - 0xd3, 0x9f, 0xc4, 0x49, 0x38, 0x72, 0x99, 0xbc, 0x8e, 0x06, 0x71, 0xb7, 0x81, 0xb4, 0xf6, 0x55, - 0x31, 0x58, 0x6d, 0x8f, 0x57, 0x36, 0x69, 0x9c, 0x6c, 0x60, 0x65, 0x87, 0xd7, 0x65, 0x87, 0xfa, - 0xa5, 0x33, 0x3f, 0xc8, 0xc2, 0xc9, 0x07, 0x40, 0xbc, 0xe1, 0x30, 0xbc, 0x70, 0x63, 0x3a, 0x3c, - 0x71, 0xc5, 0x22, 0x76, 0xdb, 0x77, 0xad, 0xfb, 0x35, 0xa7, 0x83, 0x98, 0x43, 0x3a, 0x3c, 0x39, - 0xe0, 0x70, 0xf2, 0x11, 0xb4, 0x70, 0x20, 0x27, 0xd4, 0x4b, 0x26, 0x11, 0x8d, 0xbb, 0x73, 0x77, - 0xcb, 0xf7, 0xdb, 0xab, 0xf3, 0x6a, 0xbd, 0x10, 0xbc, 0xee, 0x27, 0x4e, 0x93, 0xd5, 0x13, 0xe5, - 0xb8, 0xb7, 0x09, 0x4b, 0xc5, 0x43, 0x62, 0x44, 0xc5, 0x56, 0x85, 0x11, 0x63, 0xc5, 0x61, 0x7f, - 0x92, 0x45, 0xa8, 0x9e, 0x7b, 0xc3, 0x09, 0x15, 0x72, 0x9d, 0x17, 0x3e, 0x2e, 0x3d, 0xb6, 0xec, - 0x3f, 0xb6, 0xa0, 0xc9, 0x67, 0x29, 0xf4, 0x91, 0x7b, 0xd0, 0x92, 0xd4, 0x40, 0xa3, 0x28, 0x8c, - 0x84, 0x78, 0x33, 0x81, 0xe4, 0x01, 0x74, 0x24, 0x60, 0x1c, 0x51, 0x7f, 0xe4, 0x9d, 0xca, 0xb6, - 0x73, 0x70, 0xb2, 0x9a, 0xb6, 0x18, 0x85, 0x93, 0x84, 0x8a, 0x93, 0xaf, 0x29, 0x26, 0xe8, 0x30, - 0x98, 0x63, 0x56, 0x61, 0xe2, 0xad, 0x80, 0xd4, 0x0d, 0x98, 0xfd, 0xb7, 0x2d, 0x20, 0x6c, 0xe8, - 0x47, 0x21, 0x6f, 0x42, 0x50, 0x69, 0x96, 0x4b, 0xac, 0xb7, 0xe6, 0x92, 0xd2, 0x55, 0x5c, 0x62, - 0x43, 0x95, 0x8f, 0xbe, 0x52, 0x30, 0x7a, 0x8e, 0xfa, 0xa4, 0x52, 0x2b, 0x77, 0x2a, 0xf6, 0x7f, - 0x29, 0xc3, 0xe2, 0x06, 0x3f, 0xba, 0xd7, 0xfa, 0x7d, 0x3a, 0x56, 0xfc, 0xf3, 0x0e, 0x34, 0x82, - 0x70, 0x40, 0x25, 0xd5, 0xf2, 0x81, 0x01, 0x03, 0x69, 0x24, 0x7b, 0xe6, 0xf9, 0x01, 0x1f, 0x38, - 0x5f, 0xcf, 0x3a, 0x42, 0x70, 0xd8, 0xef, 0xc1, 0xdc, 0x98, 0x06, 0x03, 0x9d, 0x4d, 0xb8, 0x72, - 0xd5, 0x12, 0x60, 0xc1, 0x21, 0xef, 0x40, 0xe3, 0x64, 0xc2, 0xeb, 0x31, 0xe1, 0x52, 0x41, 0x3a, - 0x00, 0x01, 0x5a, 0xe3, 0x32, 0x66, 0x3c, 0x89, 0xcf, 0x10, 0x5b, 0x45, 0xec, 0x2c, 0x2b, 0x33, - 0xd4, 0x6d, 0x80, 0xc1, 0x24, 0x4e, 0x04, 0xd7, 0xcc, 0x20, 0xb2, 0xce, 0x20, 0x9c, 0x6b, 0xbe, - 0x0e, 0x0b, 0x23, 0xef, 0xb5, 0x8b, 0xf4, 0xe3, 0xfa, 0x81, 0x7b, 0x32, 0xc4, 0xd3, 0x67, 0x16, - 0xeb, 0x75, 0x46, 0xde, 0xeb, 0xef, 0x31, 0xcc, 0x4e, 0xf0, 0x14, 0xe1, 0x4c, 0xb4, 0x48, 0xb5, - 0x27, 0xa2, 0x31, 0x8d, 0xce, 0x29, 0x4a, 0x83, 0x8a, 0xd2, 0x6d, 0x1c, 0x0e, 0x65, 0x23, 0x1a, - 0xb1, 0x79, 0x27, 0xc3, 0x3e, 0x67, 0x7d, 0x67, 0x76, 0xe4, 0x07, 0xdb, 0xc9, 0xb0, 0x4f, 0x6e, - 0x01, 0x30, 0x59, 0x32, 0xa6, 0x91, 0xfb, 0xea, 0x02, 0xf9, 0xb8, 0x82, 0xb2, 0xe3, 0x80, 0x46, - 0x9f, 0x5e, 0x90, 0x9b, 0x50, 0xef, 0xc7, 0x28, 0x8c, 0xbc, 0xcb, 0x6e, 0x03, 0x99, 0xbc, 0xd6, - 0x8f, 0x99, 0x18, 0xf2, 0x2e, 0x19, 0x23, 0xb2, 0xd1, 0x7a, 0xb8, 0x0b, 0x74, 0x80, 0xcd, 0xc7, - 0x28, 0x55, 0x5b, 0x38, 0xd8, 0x35, 0x81, 0x60, 0xfd, 0xc4, 0xe4, 0x2b, 0xd0, 0x92, 0x83, 0x3d, - 0x19, 0x7a, 0xa7, 0x31, 0x8a, 0x95, 0x96, 0xd3, 0x14, 0xc0, 0xa7, 0x0c, 0x66, 0xbf, 0xe4, 0xca, - 0x96, 0xb6, 0xb7, 0x82, 0x6f, 0xd8, 0xb1, 0x8f, 0x10, 0xdc, 0xd7, 0x9a, 0x23, 0x4a, 0x45, 0x9b, - 0x56, 0x2a, 0xd8, 0x34, 0xfb, 0xe7, 0x16, 0x34, 0x45, 0xcb, 0xa8, 0xa1, 0x90, 0x47, 0x40, 0xe4, - 0x2e, 0x26, 0xaf, 0xfd, 0x81, 0x7b, 0x7c, 0x99, 0xd0, 0x98, 0x13, 0xcd, 0xf6, 0x35, 0xa7, 0x00, - 0xc7, 0xe4, 0xa8, 0x01, 0x8d, 0x93, 0x88, 0xd3, 0xf4, 0xf6, 0x35, 0x27, 0x87, 0x61, 0x2c, 0xc6, - 0x74, 0xa0, 0x49, 0xe2, 0xfa, 0xc1, 0x80, 0xbe, 0x46, 0x52, 0x6a, 0x39, 0x06, 0x6c, 0xbd, 0x0d, - 0x4d, 0xfd, 0x3b, 0xfb, 0xc7, 0x50, 0x93, 0x1a, 0x14, 0x6a, 0x0f, 0x99, 0x71, 0x39, 0x1a, 0x84, - 0xf4, 0xa0, 0x66, 0x8e, 0xc2, 0xa9, 0x7d, 0x91, 0xbe, 0xed, 0x6f, 0x43, 0x67, 0x97, 0x11, 0x51, - 0xc0, 0x88, 0x56, 0xa8, 0x85, 0x4b, 0x30, 0xa3, 0x31, 0x4f, 0xdd, 0x11, 0x25, 0x76, 0xfe, 0x9e, - 0x85, 0x71, 0x22, 0xfa, 0xc1, 0xbf, 0xed, 0x3f, 0xb1, 0x80, 0x6c, 0xc5, 0x89, 0x3f, 0xf2, 0x12, - 0xfa, 0x94, 0x2a, 0xf1, 0xb0, 0x0f, 0x4d, 0xd6, 0xda, 0x51, 0xb8, 0xc6, 0x95, 0x34, 0xae, 0x5c, - 0x7c, 0x4d, 0xb0, 0x73, 0xfe, 0x83, 0x15, 0xbd, 0x36, 0x17, 0xf9, 0x46, 0x03, 0x8c, 0xdb, 0x12, - 0x2f, 0x3a, 0xa5, 0x09, 0x6a, 0x70, 0x42, 0xff, 0x07, 0x0e, 0xda, 0x08, 0x83, 0x93, 0xde, 0xef, - 0xc0, 0x7c, 0xae, 0x0d, 0x5d, 0x46, 0xd7, 0x0b, 0x64, 0x74, 0x59, 0x97, 0xd1, 0x7d, 0x58, 0x30, - 0xc6, 0x25, 0x28, 0xae, 0x0b, 0xb3, 0x8c, 0x31, 0x98, 0xa2, 0x60, 0x71, 0x45, 0x41, 0x14, 0xc9, - 0x2a, 0x2c, 0x9e, 0x50, 0x1a, 0x79, 0x09, 0x16, 0x91, 0x75, 0xd8, 0x9e, 0x88, 0x96, 0x0b, 0x71, - 0xf6, 0x9f, 0x59, 0x30, 0xc7, 0xa4, 0xe9, 0x73, 0x2f, 0xb8, 0x94, 0x6b, 0xb5, 0x5b, 0xb8, 0x56, - 0xf7, 0xb5, 0xc3, 0x51, 0xab, 0xfd, 0x45, 0x17, 0xaa, 0x9c, 0x5d, 0x28, 0x72, 0x17, 0x9a, 0xc6, - 0x70, 0xab, 0x5c, 0x23, 0x8d, 0xbd, 0xe4, 0x80, 0x46, 0xeb, 0x97, 0x09, 0xfd, 0xd5, 0x97, 0xf2, - 0x3d, 0xe8, 0xa4, 0xc3, 0x16, 0xeb, 0x48, 0xa0, 0xc2, 0x08, 0x53, 0x34, 0x80, 0x7f, 0xdb, 0x7f, - 0xdf, 0xe2, 0x15, 0x37, 0x42, 0x5f, 0x69, 0xab, 0xac, 0x22, 0x53, 0x7a, 0x65, 0x45, 0xf6, 0xf7, - 0x54, 0x6d, 0xff, 0x57, 0x9f, 0x2c, 0x93, 0x89, 0x31, 0x0d, 0x06, 0xae, 0x37, 0x1c, 0xa2, 0x20, - 0xae, 0x39, 0xb3, 0xac, 0xbc, 0x36, 0x1c, 0xda, 0xef, 0xc3, 0xbc, 0x36, 0xba, 0x2b, 0xe6, 0xb1, - 0x07, 0x64, 0xd7, 0x8f, 0x93, 0x17, 0x41, 0x3c, 0xd6, 0x14, 0xb9, 0x9b, 0x50, 0x67, 0xd2, 0x96, - 0x8d, 0x8c, 0x73, 0x6e, 0xd5, 0x61, 0xe2, 0x97, 0x8d, 0x2b, 0x46, 0xa4, 0xf7, 0x5a, 0x20, 0x4b, - 0x02, 0xe9, 0xbd, 0x46, 0xa4, 0xfd, 0x18, 0x16, 0x8c, 0xf6, 0x44, 0xd7, 0xef, 0x42, 0x75, 0x92, - 0xbc, 0x0e, 0xa5, 0xaa, 0xde, 0x10, 0x14, 0xc2, 0x8c, 0x42, 0x87, 0x63, 0xec, 0x27, 0x30, 0xbf, - 0x47, 0x2f, 0x04, 0x23, 0xcb, 0x81, 0xbc, 0xf7, 0x46, 0x83, 0x11, 0xf1, 0xf6, 0x0a, 0x10, 0xfd, - 0xe3, 0x94, 0x01, 0xa4, 0xf9, 0x68, 0x19, 0xe6, 0xa3, 0xfd, 0x1e, 0x90, 0x43, 0xff, 0x34, 0x78, - 0x4e, 0xe3, 0xd8, 0x3b, 0x55, 0xac, 0xdf, 0x81, 0xf2, 0x28, 0x3e, 0x15, 0xa2, 0x8a, 0xfd, 0x69, - 0x7f, 0x03, 0x16, 0x8c, 0x7a, 0xa2, 0xe1, 0x5b, 0x50, 0x8f, 0xfd, 0xd3, 0x00, 0x15, 0x2d, 0xd1, - 0x74, 0x0a, 0xb0, 0x9f, 0xc2, 0xe2, 0xf7, 0x68, 0xe4, 0x9f, 0x5c, 0xbe, 0xa9, 0x79, 0xb3, 0x9d, - 0x52, 0xb6, 0x9d, 0x2d, 0xb8, 0x9e, 0x69, 0x47, 0x74, 0xcf, 0xc9, 0x57, 0xec, 0x64, 0xcd, 0xe1, - 0x05, 0x4d, 0xf6, 0x95, 0x74, 0xd9, 0x67, 0xbf, 0x00, 0xb2, 0x11, 0x06, 0x01, 0xed, 0x27, 0x07, - 0x94, 0x46, 0xa9, 0xe7, 0x2a, 0xa5, 0xd5, 0xc6, 0xea, 0xb2, 0x58, 0xd9, 0xac, 0x40, 0x15, 0x44, - 0x4c, 0xa0, 0x32, 0xa6, 0xd1, 0x08, 0x1b, 0xae, 0x39, 0xf8, 0xb7, 0x7d, 0x1d, 0x16, 0x8c, 0x66, - 0x85, 0xad, 0xff, 0x21, 0x5c, 0xdf, 0xf4, 0xe3, 0x7e, 0xbe, 0xc3, 0x2e, 0xcc, 0x8e, 0x27, 0xc7, - 0x6e, 0xca, 0x89, 0xb2, 0xc8, 0xcc, 0xbf, 0xec, 0x27, 0xa2, 0xb1, 0xbf, 0x6e, 0x41, 0x65, 0xfb, - 0x68, 0x77, 0x83, 0x9d, 0x15, 0x7e, 0xd0, 0x0f, 0x47, 0x4c, 0x0b, 0xe3, 0x93, 0x56, 0xe5, 0xa9, - 0x1c, 0x76, 0x0b, 0xea, 0xa8, 0xbc, 0x31, 0x8b, 0x57, 0xe8, 0x41, 0x29, 0x80, 0x59, 0xdb, 0xf4, - 0xf5, 0xd8, 0x8f, 0xd0, 0x9c, 0x96, 0x46, 0x72, 0x05, 0x8f, 0x99, 0x3c, 0xc2, 0xfe, 0x77, 0xb3, - 0x30, 0x2b, 0x0e, 0x5f, 0x7e, 0x90, 0x27, 0xfe, 0x39, 0x4d, 0x0f, 0x72, 0x56, 0x62, 0x8a, 0x71, - 0x44, 0x47, 0x61, 0xa2, 0xf4, 0x37, 0xbe, 0x0d, 0x26, 0x10, 0xbd, 0x09, 0x42, 0x89, 0xe0, 0xfe, - 0x87, 0x32, 0xaf, 0x65, 0x00, 0xc9, 0x2d, 0x98, 0x95, 0xca, 0x40, 0x45, 0x19, 0x3a, 0x12, 0xc4, - 0x56, 0xa3, 0xef, 0x8d, 0xbd, 0xbe, 0x9f, 0x5c, 0x0a, 0xb1, 0xa0, 0xca, 0xac, 0xfd, 0x61, 0xd8, - 0xf7, 0x86, 0xee, 0xb1, 0x37, 0xf4, 0x82, 0x3e, 0x95, 0xde, 0x0a, 0x03, 0xc8, 0x2c, 0x77, 0x31, - 0x2c, 0x59, 0x8d, 0x5b, 0xf7, 0x19, 0x28, 0x3b, 0xc3, 0xfb, 0xe1, 0x68, 0xe4, 0x33, 0xeb, 0x83, - 0xab, 0x66, 0x65, 0x47, 0x83, 0x70, 0xdf, 0x08, 0x96, 0x2e, 0xf8, 0x0a, 0xd6, 0xa5, 0x6f, 0x44, - 0x03, 0xb2, 0x56, 0x32, 0x1a, 0x5a, 0xd9, 0xd1, 0x20, 0x6c, 0x2f, 0x26, 0x41, 0x4c, 0x93, 0x64, - 0x48, 0x07, 0x6a, 0x40, 0x0d, 0xac, 0x96, 0x47, 0x90, 0x47, 0xb0, 0xc0, 0x7d, 0x10, 0xb1, 0x97, - 0x84, 0xf1, 0x99, 0x1f, 0xbb, 0x31, 0x33, 0x9f, 0xb8, 0x2d, 0x5c, 0x84, 0x22, 0x8f, 0x61, 0x39, - 0x03, 0x8e, 0x68, 0x9f, 0xfa, 0xe7, 0x74, 0x80, 0x2a, 0x5c, 0xd9, 0x99, 0x86, 0x26, 0x77, 0xa1, - 0x11, 0x4c, 0x46, 0xee, 0x64, 0x3c, 0xf0, 0x98, 0x12, 0xd3, 0x46, 0xe5, 0x52, 0x07, 0x91, 0x0f, - 0x41, 0xea, 0x69, 0x42, 0x7b, 0x9c, 0x33, 0x24, 0x1c, 0xa3, 0x5e, 0xc7, 0xac, 0xc1, 0x08, 0x33, - 0x55, 0x49, 0x3b, 0xc2, 0xee, 0x94, 0x00, 0xe4, 0x93, 0xc8, 0x3f, 0xf7, 0x12, 0xda, 0x9d, 0xe7, - 0x42, 0x5d, 0x14, 0xd9, 0x77, 0x7e, 0xe0, 0x27, 0xbe, 0x97, 0x84, 0x51, 0x97, 0x20, 0x2e, 0x05, - 0xb0, 0x45, 0x44, 0xfa, 0x88, 0x13, 0x2f, 0x99, 0xc4, 0x42, 0x43, 0x5d, 0x40, 0xe2, 0xca, 0x23, - 0xc8, 0x47, 0xb0, 0xc4, 0x29, 0x02, 0x51, 0x42, 0xf7, 0x46, 0x55, 0x61, 0x11, 0x57, 0x64, 0x0a, - 0x96, 0x2d, 0xa5, 0x20, 0x91, 0xdc, 0x87, 0xd7, 0xf9, 0x52, 0x4e, 0x41, 0xb3, 0xf1, 0xb1, 0x11, - 0xf8, 0x7d, 0x57, 0xd4, 0x60, 0x2c, 0xb2, 0x84, 0xb3, 0xc8, 0x23, 0x18, 0x89, 0x0f, 0xfd, 0x13, - 0x9a, 0xf8, 0x23, 0xda, 0x5d, 0xe6, 0x24, 0x2e, 0xcb, 0x8c, 0x01, 0x27, 0x63, 0xc4, 0x74, 0x39, - 0xc3, 0xf3, 0x12, 0x12, 0xe3, 0x30, 0x8c, 0xa9, 0xf4, 0x3c, 0x75, 0x6f, 0x08, 0xd6, 0xd2, 0x81, - 0xf6, 0x1f, 0x5a, 0xfc, 0x88, 0x12, 0xec, 0x1c, 0x6b, 0xc6, 0x17, 0x67, 0x64, 0x37, 0x0c, 0x86, - 0x97, 0x82, 0xb7, 0x81, 0x83, 0xf6, 0x83, 0xe1, 0x25, 0x53, 0xff, 0xfd, 0x40, 0xaf, 0xc2, 0xa5, - 0x61, 0x53, 0x02, 0xb1, 0xd2, 0x3b, 0xd0, 0x18, 0x4f, 0x8e, 0x87, 0x7e, 0x9f, 0x57, 0x29, 0xf3, - 0x56, 0x38, 0x08, 0x2b, 0x30, 0xeb, 0x93, 0xef, 0x27, 0xaf, 0x51, 0xc1, 0x1a, 0x0d, 0x01, 0x63, - 0x55, 0xec, 0x75, 0x58, 0x34, 0x07, 0x28, 0xc4, 0xfe, 0x03, 0xa8, 0x09, 0x29, 0x21, 0xdd, 0x10, - 0x6d, 0xcd, 0x39, 0xcc, 0x8c, 0x25, 0x85, 0xb7, 0xff, 0x75, 0x05, 0x16, 0x04, 0x74, 0x83, 0x4d, - 0xff, 0x70, 0x32, 0x1a, 0x79, 0x51, 0x81, 0xf8, 0xb1, 0xde, 0x20, 0x7e, 0x4a, 0x79, 0xf1, 0x73, - 0xc7, 0xb0, 0x42, 0xb9, 0xfc, 0xd2, 0x20, 0xe4, 0x3e, 0xcc, 0xb1, 0x25, 0xe7, 0x46, 0x81, 0xee, - 0x9f, 0xcc, 0x82, 0xf3, 0x22, 0xb3, 0x5a, 0x24, 0x32, 0x75, 0x71, 0x37, 0x93, 0x11, 0x77, 0x36, - 0x34, 0xf9, 0xf6, 0x0a, 0x09, 0x3e, 0x2b, 0x4c, 0x32, 0x0d, 0xc6, 0xc6, 0x93, 0x15, 0x2e, 0x5c, - 0x92, 0xcd, 0x15, 0x89, 0x16, 0x7f, 0x44, 0xf1, 0x84, 0xd0, 0x6a, 0xd7, 0x85, 0x68, 0xc9, 0xa3, - 0xc8, 0x53, 0x00, 0xde, 0x17, 0xaa, 0x29, 0x80, 0x6a, 0xca, 0x7b, 0xe6, 0xae, 0xe8, 0xeb, 0xbf, - 0xc2, 0x0a, 0x93, 0x88, 0xa2, 0xea, 0xa2, 0x7d, 0x69, 0xff, 0x4d, 0x0b, 0x1a, 0x1a, 0x8e, 0x5c, - 0x87, 0xf9, 0x8d, 0xfd, 0xfd, 0x83, 0x2d, 0x67, 0xed, 0x68, 0xe7, 0x7b, 0x5b, 0xee, 0xc6, 0xee, - 0xfe, 0xe1, 0x56, 0xe7, 0x1a, 0x03, 0xef, 0xee, 0x6f, 0xac, 0xed, 0xba, 0x4f, 0xf7, 0x9d, 0x0d, - 0x09, 0xb6, 0xc8, 0x12, 0x10, 0x67, 0xeb, 0xf9, 0xfe, 0xd1, 0x96, 0x01, 0x2f, 0x91, 0x0e, 0x34, - 0xd7, 0x9d, 0xad, 0xb5, 0x8d, 0x6d, 0x01, 0x29, 0x93, 0x45, 0xe8, 0x3c, 0x7d, 0xb1, 0xb7, 0xb9, - 0xb3, 0xf7, 0xcc, 0xdd, 0x58, 0xdb, 0xdb, 0xd8, 0xda, 0xdd, 0xda, 0xec, 0x54, 0x48, 0x0b, 0xea, - 0x6b, 0xeb, 0x6b, 0x7b, 0x9b, 0xfb, 0x7b, 0x5b, 0x9b, 0x9d, 0xaa, 0xfd, 0xdf, 0x2c, 0xb8, 0x8e, - 0xa3, 0x1e, 0x64, 0x99, 0xe4, 0x2e, 0x34, 0xfa, 0x61, 0x38, 0x66, 0xe6, 0x41, 0x7a, 0x00, 0xea, - 0x20, 0xc6, 0x00, 0x5c, 0x74, 0x9c, 0x84, 0x51, 0x9f, 0x0a, 0x1e, 0x01, 0x04, 0x3d, 0x65, 0x10, - 0xc6, 0x00, 0x62, 0x7b, 0x79, 0x0d, 0xce, 0x22, 0x0d, 0x0e, 0xe3, 0x55, 0x96, 0x60, 0xe6, 0x38, - 0xa2, 0x5e, 0xff, 0x4c, 0x70, 0x87, 0x28, 0x91, 0xaf, 0xa6, 0xf6, 0x6b, 0x9f, 0xad, 0xfe, 0x90, - 0x0e, 0x90, 0x62, 0x6a, 0xce, 0x9c, 0x80, 0x6f, 0x08, 0x30, 0x93, 0x95, 0xde, 0xb1, 0x17, 0x0c, - 0xc2, 0x80, 0x0e, 0x84, 0x72, 0x9c, 0x02, 0xec, 0x03, 0x58, 0xca, 0xce, 0x4f, 0xf0, 0xd8, 0x47, - 0x1a, 0x8f, 0x71, 0x5d, 0xb5, 0x37, 0x7d, 0x37, 0x35, 0x7e, 0xfb, 0xb3, 0x32, 0x54, 0x98, 0xea, - 0x32, 0x5d, 0xcd, 0xd1, 0xb5, 0xd1, 0x72, 0x2e, 0x98, 0x81, 0x26, 0x31, 0x3f, 0xc8, 0x84, 0x3b, - 0x26, 0x85, 0xa4, 0xf8, 0x88, 0xf6, 0xcf, 0x85, 0x43, 0x46, 0x83, 0x30, 0x06, 0x61, 0xa6, 0x02, - 0x7e, 0x2d, 0x18, 0x44, 0x96, 0x25, 0x0e, 0xbf, 0x9c, 0x4d, 0x71, 0xf8, 0x5d, 0x17, 0x66, 0xfd, - 0xe0, 0x38, 0x9c, 0x04, 0x03, 0x64, 0x88, 0x9a, 0x23, 0x8b, 0x18, 0x3e, 0x41, 0x46, 0x65, 0x52, - 0x96, 0x93, 0x7f, 0x0a, 0x20, 0xab, 0x50, 0x8f, 0x2f, 0x83, 0xbe, 0x4e, 0xf3, 0x8b, 0x62, 0x95, - 0xd8, 0x1a, 0xac, 0x1c, 0x5e, 0x06, 0x7d, 0xa4, 0xf0, 0xb4, 0x1a, 0xf9, 0x16, 0xd4, 0x94, 0x03, - 0x93, 0x0b, 0xaf, 0x1b, 0xfa, 0x27, 0xd2, 0x6b, 0xc9, 0xed, 0x42, 0x55, 0xb5, 0xf7, 0x29, 0xb4, - 0x0c, 0x94, 0x6e, 0xcc, 0xb5, 0xb8, 0x31, 0x77, 0x4f, 0x37, 0xe6, 0x52, 0x99, 0x28, 0x3e, 0xd3, - 0x8d, 0xbb, 0xdf, 0x81, 0x9a, 0x1c, 0x1a, 0x63, 0x8d, 0x17, 0x7b, 0x9f, 0xee, 0xed, 0xbf, 0xdc, - 0x73, 0x0f, 0xbf, 0xbf, 0xb7, 0xd1, 0xb9, 0x46, 0xe6, 0xa0, 0xb1, 0xb6, 0x81, 0xdc, 0x86, 0x00, - 0x8b, 0x55, 0x39, 0x58, 0x3b, 0x3c, 0x54, 0x90, 0x92, 0x4d, 0xa0, 0xc3, 0x24, 0x33, 0x1b, 0xb1, - 0x0a, 0x51, 0x7c, 0x04, 0xf3, 0x1a, 0x2c, 0xb5, 0x77, 0xc6, 0x0c, 0x90, 0xb1, 0x77, 0x50, 0xb9, - 0xe5, 0x18, 0x7b, 0x19, 0xae, 0xb3, 0xe2, 0xd6, 0x39, 0x0d, 0x92, 0xc3, 0xc9, 0x31, 0x8f, 0x4c, - 0xf9, 0x61, 0x60, 0xff, 0x35, 0x0b, 0xea, 0x0a, 0x73, 0x05, 0x3d, 0xc9, 0x60, 0x5a, 0x09, 0x37, - 0xa0, 0xa7, 0x75, 0x81, 0x5f, 0xae, 0xe0, 0xbf, 0x86, 0x8d, 0x54, 0x57, 0x20, 0x36, 0xd9, 0x83, - 0xad, 0x2d, 0xc7, 0xdd, 0xdf, 0xdb, 0xdd, 0xd9, 0x63, 0x92, 0x85, 0x4d, 0x16, 0x01, 0x4f, 0x9f, - 0x22, 0xc4, 0xb2, 0x3b, 0xd0, 0x7e, 0x46, 0x93, 0x9d, 0xe0, 0x24, 0x94, 0x53, 0xfd, 0xbf, 0x55, - 0x98, 0x53, 0xa0, 0xd4, 0xc6, 0x3a, 0xa7, 0x51, 0xec, 0x87, 0x01, 0x6a, 0x47, 0x75, 0x47, 0x16, - 0x99, 0xd8, 0xf5, 0x07, 0x34, 0x48, 0xfc, 0xe4, 0xd2, 0x35, 0x9c, 0x32, 0x59, 0x30, 0xb3, 0x67, - 0xbc, 0xa1, 0xef, 0xc9, 0x20, 0x1f, 0x2f, 0x30, 0x68, 0x3f, 0x1c, 0x86, 0x11, 0xaa, 0x41, 0x75, - 0x87, 0x17, 0xc8, 0x2a, 0x2c, 0x32, 0xf5, 0x4b, 0x77, 0x99, 0x21, 0xb3, 0x72, 0x0f, 0x51, 0x21, - 0x8e, 0x89, 0x75, 0x06, 0x17, 0x67, 0xb7, 0xfa, 0x84, 0x6b, 0xfb, 0x45, 0x28, 0xf2, 0x4d, 0xb8, - 0xce, 0xc0, 0xea, 0xbc, 0x57, 0xdf, 0xcc, 0xe1, 0x37, 0xc5, 0x48, 0xc6, 0x35, 0xbc, 0x7f, 0xb6, - 0xf3, 0x55, 0xae, 0xd8, 0x29, 0x40, 0x2e, 0x22, 0x37, 0xc3, 0x8f, 0xaa, 0x6c, 0x44, 0x4e, 0x8b, - 0xea, 0xd5, 0x72, 0x51, 0xbd, 0x6f, 0xc2, 0xf5, 0x63, 0x1a, 0x27, 0xee, 0x19, 0xf5, 0x06, 0x34, - 0x42, 0x6e, 0xe4, 0xc1, 0x3b, 0xae, 0xc7, 0x16, 0x23, 0xf1, 0x00, 0xbc, 0x0c, 0xfa, 0x74, 0xe0, - 0x26, 0xa1, 0x8b, 0x07, 0x35, 0xf2, 0x74, 0xcd, 0xc9, 0x82, 0xcd, 0x9a, 0xa7, 0x91, 0x37, 0x3e, - 0x13, 0x8a, 0x66, 0x16, 0xcc, 0x54, 0x84, 0x84, 0xc6, 0x49, 0x40, 0x79, 0xe8, 0xa4, 0x86, 0x6e, - 0x71, 0x09, 0x22, 0xf7, 0x60, 0x06, 0x1b, 0x8c, 0xbb, 0x1d, 0x64, 0x80, 0x66, 0x2a, 0x44, 0xfd, - 0xc0, 0x11, 0x38, 0x66, 0x56, 0x4e, 0x22, 0x3f, 0xee, 0x36, 0x31, 0x6a, 0x88, 0x7f, 0x93, 0xef, - 0x68, 0x72, 0x62, 0x01, 0xbf, 0xbd, 0x27, 0xbe, 0xcd, 0x50, 0xde, 0x97, 0x22, 0x32, 0x3e, 0xa9, - 0xd4, 0x1a, 0x9d, 0xa6, 0xfd, 0x9b, 0x50, 0xc5, 0x91, 0x23, 0x4d, 0xe2, 0xfa, 0x59, 0x82, 0x26, - 0x11, 0xda, 0x85, 0xd9, 0x80, 0x26, 0x17, 0x61, 0xf4, 0x4a, 0x86, 0xa9, 0x45, 0xd1, 0xfe, 0x09, - 0xda, 0xde, 0x2a, 0x6c, 0xfb, 0x02, 0x8d, 0x06, 0x72, 0x13, 0xea, 0x7c, 0x4f, 0xe3, 0x33, 0x4f, - 0xb8, 0x03, 0x6a, 0x08, 0x38, 0x3c, 0xf3, 0xd8, 0xf9, 0x68, 0x90, 0x09, 0xf7, 0xb0, 0x34, 0x10, - 0xb6, 0xcd, 0xa9, 0xe4, 0x1e, 0xb4, 0x65, 0x40, 0x38, 0x76, 0x87, 0xf4, 0x24, 0x91, 0xfe, 0xd1, - 0x60, 0x32, 0x42, 0x37, 0xcc, 0x2e, 0x3d, 0x49, 0xec, 0x3d, 0x98, 0x17, 0x67, 0xd6, 0xfe, 0x98, - 0xca, 0xae, 0x7f, 0xab, 0x48, 0xff, 0x6b, 0xac, 0x2e, 0x98, 0x87, 0x1c, 0x0f, 0x81, 0x9b, 0x35, - 0x6d, 0x07, 0x88, 0x7e, 0x06, 0x8a, 0x06, 0x85, 0x02, 0x26, 0x3d, 0xc0, 0x62, 0x3a, 0x06, 0x8c, - 0xad, 0x4f, 0x3c, 0xe9, 0xf7, 0x65, 0x18, 0xbf, 0xe6, 0xc8, 0xa2, 0xfd, 0x9f, 0x2c, 0x58, 0xc0, - 0xd6, 0xa4, 0x06, 0x2b, 0xf4, 0x8c, 0xc7, 0x5f, 0x60, 0x98, 0xd2, 0xff, 0xce, 0xbd, 0xce, 0x8b, - 0x50, 0xd5, 0x35, 0x0f, 0x5e, 0xf8, 0xe2, 0xde, 0xb6, 0x4a, 0xce, 0xdb, 0xf6, 0x00, 0x3a, 0x03, - 0x3a, 0xf4, 0x31, 0x95, 0x43, 0x9e, 0xe3, 0x5c, 0x5d, 0xcd, 0xc1, 0xed, 0xbf, 0x63, 0xc1, 0x3c, - 0x57, 0x14, 0xd0, 0xe6, 0x12, 0x4b, 0xf5, 0x17, 0xa4, 0x7d, 0x22, 0x04, 0x94, 0x98, 0x54, 0x7a, - 0x74, 0x22, 0x94, 0x57, 0xde, 0xbe, 0xe6, 0x98, 0x95, 0xc9, 0x13, 0xd4, 0xba, 0x03, 0x17, 0xa1, - 0x05, 0xc9, 0x21, 0xe6, 0xbe, 0x6c, 0x5f, 0x73, 0xb4, 0xea, 0xeb, 0x35, 0x66, 0x32, 0x31, 0xb8, - 0xfd, 0x0c, 0x5a, 0x46, 0x47, 0x86, 0x57, 0xb0, 0xc9, 0xbd, 0x82, 0x39, 0xf7, 0x7b, 0xa9, 0xc0, - 0xfd, 0xfe, 0xfb, 0x15, 0x20, 0x8c, 0xb0, 0x32, 0x3b, 0x77, 0xd7, 0x8c, 0x61, 0xc9, 0x3c, 0x91, - 0x14, 0x44, 0x56, 0x81, 0x68, 0x45, 0x19, 0x5b, 0x2b, 0xab, 0xd8, 0x5a, 0x01, 0x96, 0x49, 0x7d, - 0xa1, 0x55, 0xaa, 0xb8, 0x15, 0x7a, 0x7c, 0xf8, 0x36, 0x15, 0xe2, 0x98, 0xe6, 0x83, 0x41, 0x2c, - 0x66, 0x9b, 0x0a, 0x2f, 0x89, 0x2c, 0x67, 0xe9, 0x61, 0xe6, 0x8d, 0xf4, 0x30, 0x9b, 0xa3, 0x07, - 0xcd, 0x4e, 0xaf, 0x99, 0x76, 0xfa, 0x3d, 0x68, 0xc9, 0x58, 0x15, 0x0f, 0xd3, 0x0b, 0xa7, 0x88, - 0x01, 0x64, 0xf4, 0x24, 0x4d, 0x65, 0xe5, 0x0c, 0xe0, 0x41, 0xe8, 0x1c, 0x9c, 0x1d, 0x2c, 0xa9, - 0x3f, 0xb6, 0x81, 0x83, 0x4d, 0x01, 0x68, 0x59, 0x33, 0x2a, 0x71, 0x27, 0x81, 0xc8, 0x11, 0xa1, - 0x03, 0x74, 0x87, 0x30, 0xcb, 0x3a, 0x8b, 0xc8, 0x5b, 0xc9, 0xad, 0x02, 0x2b, 0x99, 0x7c, 0x94, - 0x06, 0x76, 0xe2, 0x33, 0x7f, 0x84, 0x67, 0x7b, 0x9a, 0x62, 0xf1, 0x94, 0xa3, 0x0e, 0xcf, 0xfc, - 0x91, 0x63, 0xd4, 0xb3, 0x7f, 0x61, 0x41, 0x87, 0x51, 0x85, 0x41, 0xf8, 0x1f, 0x03, 0xf2, 0xe8, - 0x5b, 0xd2, 0xbd, 0x51, 0x97, 0x3c, 0x86, 0x3a, 0x96, 0xc3, 0x31, 0x0d, 0x04, 0xd5, 0x77, 0x4d, - 0xaa, 0x4f, 0xa5, 0xdb, 0xf6, 0x35, 0x27, 0xad, 0xcc, 0xce, 0xb2, 0x6c, 0x60, 0x8d, 0x47, 0x89, - 0xb3, 0x60, 0x8d, 0x3b, 0xb6, 0x01, 0x3e, 0xa5, 0x97, 0xbb, 0x61, 0x1f, 0x5d, 0x2a, 0xb7, 0x01, - 0x18, 0x0d, 0x9e, 0x78, 0x23, 0x5f, 0x78, 0x04, 0xaa, 0x4e, 0xfd, 0x15, 0xbd, 0x7c, 0x8a, 0x00, - 0x26, 0xc6, 0x19, 0x3a, 0x65, 0x91, 0xaa, 0x53, 0x7b, 0x45, 0x2f, 0x77, 0x90, 0x3d, 0x5c, 0x68, - 0x7d, 0x4a, 0x2f, 0x37, 0x29, 0xd7, 0xeb, 0xc2, 0x88, 0xd8, 0xd0, 0x8a, 0xbc, 0x0b, 0xa6, 0xb9, - 0x19, 0x11, 0xb1, 0x46, 0xe4, 0x5d, 0x7c, 0x4a, 0x2f, 0xd7, 0x31, 0x24, 0xf6, 0x00, 0x66, 0x19, - 0x7e, 0x18, 0xf6, 0xc5, 0xc9, 0x24, 0x83, 0xfc, 0xe9, 0xa0, 0x9c, 0x99, 0x57, 0xf8, 0xb7, 0xfd, - 0x1f, 0x2c, 0x68, 0xb1, 0x15, 0x40, 0xb1, 0xc7, 0x76, 0x42, 0xe6, 0x8a, 0x58, 0x69, 0xae, 0xc8, - 0xaa, 0x90, 0x19, 0x5c, 0x86, 0x96, 0xa6, 0xcb, 0x50, 0x5c, 0x36, 0x2e, 0x40, 0x3f, 0x84, 0x3a, - 0x67, 0x27, 0xc6, 0xbe, 0x65, 0x63, 0xa7, 0x8c, 0x09, 0x39, 0x35, 0xac, 0xf6, 0x29, 0x0f, 0x4b, - 0x6b, 0x3e, 0x1d, 0xbe, 0xc8, 0x75, 0x0e, 0x61, 0xe8, 0x82, 0x08, 0x67, 0xb5, 0x28, 0xc2, 0xf9, - 0x02, 0x1a, 0x1a, 0x61, 0x91, 0x6f, 0xf3, 0xd8, 0x30, 0x1f, 0x3c, 0xa7, 0x42, 0x93, 0x70, 0x8c, - 0xd9, 0xa3, 0xc0, 0xd4, 0x01, 0xeb, 0x33, 0x50, 0x41, 0x92, 0x7c, 0x02, 0xf3, 0x5a, 0xb3, 0xdc, - 0x42, 0x2c, 0x1a, 0x93, 0x55, 0x34, 0xa6, 0x3f, 0xb0, 0x60, 0x51, 0x7c, 0x8d, 0x79, 0x45, 0x3e, - 0x3b, 0xc6, 0x9f, 0xc7, 0xa7, 0xec, 0x20, 0x65, 0xad, 0xbb, 0x11, 0x3d, 0xf5, 0xe3, 0x84, 0x4a, - 0x47, 0x7a, 0x01, 0x87, 0x30, 0x92, 0x66, 0x55, 0x1d, 0x51, 0x93, 0x3c, 0x81, 0x06, 0x7e, 0xca, - 0x6d, 0x58, 0xb1, 0x2d, 0xdd, 0xfc, 0x87, 0x7c, 0xa8, 0x4c, 0x92, 0xc7, 0xaa, 0xb4, 0x5e, 0x87, - 0xd9, 0x24, 0xf2, 0x4f, 0x4f, 0x69, 0x64, 0x2f, 0xa9, 0xa1, 0x31, 0x6e, 0xa3, 0x87, 0x09, 0x1d, - 0x33, 0xe5, 0x88, 0x51, 0x46, 0x43, 0x30, 0xd5, 0x2f, 0xed, 0x3c, 0xef, 0x69, 0x19, 0x72, 0xdc, - 0x5a, 0x4d, 0x13, 0xe2, 0xee, 0xc3, 0xdc, 0x88, 0x29, 0x4a, 0x4c, 0x83, 0x37, 0x1c, 0xe7, 0x59, - 0x30, 0x53, 0xbc, 0x51, 0x6f, 0x89, 0xdd, 0xc4, 0x1f, 0xba, 0x12, 0x2b, 0x72, 0xd1, 0x8a, 0x50, - 0xec, 0xf8, 0x8e, 0x13, 0xef, 0x94, 0x0a, 0xed, 0x98, 0x17, 0xec, 0x2e, 0x2c, 0x1d, 0xa4, 0xdb, - 0xa2, 0x39, 0x24, 0xec, 0x7f, 0xde, 0x82, 0xe5, 0x1c, 0x4a, 0x65, 0xce, 0x0a, 0x6f, 0xf0, 0xd0, - 0x1f, 0x1d, 0x87, 0xca, 0x9b, 0x63, 0xe9, 0x8e, 0x62, 0x03, 0x45, 0x4e, 0xe1, 0xba, 0xa4, 0x0a, - 0x26, 0x42, 0x52, 0xb5, 0xbf, 0x84, 0x9a, 0xe8, 0x87, 0xa6, 0xc4, 0xca, 0x76, 0x28, 0xe1, 0xfa, - 0xa9, 0x58, 0xdc, 0x1e, 0x39, 0x83, 0xae, 0x22, 0x3f, 0xa1, 0x29, 0x69, 0x96, 0x0c, 0xeb, 0xeb, - 0x83, 0x37, 0xf4, 0x65, 0xf8, 0x2f, 0x9c, 0xa9, 0xad, 0x91, 0x4b, 0xb8, 0x23, 0x71, 0xa8, 0x0a, - 0xe5, 0xfb, 0xab, 0xbc, 0xd5, 0xdc, 0xd0, 0x33, 0x63, 0x76, 0xfa, 0x86, 0x86, 0xc9, 0x8f, 0x61, - 0xe9, 0xc2, 0xf3, 0x13, 0x39, 0x2c, 0xcd, 0x8a, 0xaa, 0x62, 0x97, 0xab, 0x6f, 0xe8, 0xf2, 0x25, - 0xff, 0xd8, 0xd0, 0x0f, 0xa7, 0xb4, 0xd8, 0xfb, 0x45, 0x09, 0xda, 0x66, 0x3b, 0x8c, 0x4c, 0x85, - 0x54, 0x92, 0x0a, 0x85, 0xb4, 0x3f, 0x33, 0xe0, 0xbc, 0x53, 0xb4, 0x54, 0xe4, 0x14, 0xd5, 0xdd, - 0x90, 0xe5, 0x37, 0x45, 0x5d, 0x2a, 0x6f, 0x17, 0x75, 0xa9, 0x16, 0x46, 0x5d, 0xa6, 0x3b, 0xe7, - 0x67, 0x7e, 0x59, 0xe7, 0xfc, 0xec, 0x95, 0xce, 0xf9, 0xde, 0xff, 0xb1, 0x80, 0xe4, 0xa9, 0x97, - 0x3c, 0xe3, 0x7e, 0xe0, 0x80, 0x0e, 0x85, 0x78, 0xfb, 0xfa, 0xdb, 0x71, 0x80, 0xdc, 0x2d, 0xf9, - 0x35, 0x63, 0x45, 0x3d, 0x7d, 0x55, 0xb7, 0x6d, 0x5a, 0x4e, 0x11, 0x2a, 0x13, 0x79, 0xaa, 0xbc, - 0x39, 0xf2, 0x54, 0x7d, 0x73, 0xe4, 0x69, 0x26, 0x1b, 0x79, 0xea, 0xfd, 0x55, 0x0b, 0x16, 0x0a, - 0xc8, 0xec, 0xd7, 0x37, 0x71, 0x46, 0x18, 0x86, 0xf4, 0x29, 0x09, 0xc2, 0xd0, 0x81, 0xbd, 0xbf, - 0x04, 0x2d, 0x83, 0xb5, 0x7e, 0x7d, 0xfd, 0x67, 0xcd, 0x33, 0x4e, 0xd9, 0x06, 0xac, 0xf7, 0x3f, - 0x4b, 0x40, 0xf2, 0xec, 0xfd, 0xa5, 0x8e, 0x21, 0xbf, 0x4e, 0xe5, 0x82, 0x75, 0xfa, 0xff, 0x7a, - 0xf2, 0x7c, 0x00, 0xf3, 0x22, 0x27, 0x5f, 0xf3, 0xfc, 0x73, 0x8a, 0xc9, 0x23, 0x98, 0x81, 0x6a, - 0x86, 0xfd, 0x6a, 0x46, 0x0e, 0xb2, 0x76, 0xfc, 0x66, 0xa2, 0x7f, 0x76, 0x0f, 0xba, 0x62, 0x85, - 0xf2, 0xae, 0xbf, 0xbf, 0x57, 0x51, 0x36, 0x36, 0x22, 0x85, 0xfe, 0xfc, 0x4d, 0x68, 0xea, 0xc7, - 0x87, 0xd8, 0x8e, 0x4c, 0xf0, 0x87, 0xa9, 0x19, 0x7a, 0x2d, 0xb2, 0x09, 0x6d, 0x14, 0x92, 0x03, - 0xf5, 0x1d, 0xd7, 0x34, 0xae, 0x70, 0x68, 0x6f, 0x5f, 0x73, 0x32, 0xdf, 0x90, 0xdf, 0x86, 0xb6, - 0xe9, 0xe6, 0x12, 0x3a, 0x61, 0x91, 0x1a, 0xc9, 0x3e, 0x37, 0x2b, 0x93, 0x35, 0xe8, 0x64, 0xfd, - 0x64, 0x22, 0x41, 0x72, 0x4a, 0x03, 0xb9, 0xea, 0xe4, 0x13, 0x58, 0x2c, 0x3a, 0x44, 0x71, 0x6f, - 0xa6, 0x5b, 0x11, 0x85, 0xdf, 0x90, 0xc7, 0xc2, 0x67, 0x5a, 0x45, 0x9f, 0xe9, 0x3d, 0x73, 0x08, - 0xda, 0x92, 0xaf, 0xf0, 0xff, 0x34, 0xef, 0xe9, 0x39, 0x40, 0x0a, 0x23, 0x1d, 0x68, 0xee, 0x1f, - 0x6c, 0xed, 0xb9, 0x1b, 0xdb, 0x6b, 0x7b, 0x7b, 0x5b, 0xbb, 0x9d, 0x6b, 0x84, 0x40, 0x1b, 0x63, - 0x2c, 0x9b, 0x0a, 0x66, 0x31, 0x98, 0xf0, 0x28, 0x4b, 0x58, 0x89, 0x2c, 0x42, 0x67, 0x67, 0x2f, - 0x03, 0x2d, 0x93, 0x2e, 0x2c, 0x1e, 0x6c, 0xf1, 0xb0, 0x8c, 0xd1, 0x6e, 0x85, 0xe9, 0x7b, 0x62, - 0xf0, 0x4c, 0xdf, 0xe3, 0x37, 0x3b, 0xd6, 0x39, 0x11, 0x4a, 0x1d, 0xe8, 0x1f, 0x58, 0x70, 0x3d, - 0x83, 0x48, 0x73, 0x75, 0xb9, 0x9a, 0x63, 0xea, 0x3e, 0x26, 0x10, 0x23, 0xc7, 0xd2, 0x3c, 0xcc, - 0xc8, 0xa9, 0x3c, 0x82, 0x71, 0x96, 0x66, 0x4e, 0x66, 0xf8, 0xb5, 0x08, 0x65, 0x2f, 0xab, 0x94, - 0xc8, 0xcc, 0xc0, 0x4f, 0xf8, 0x8d, 0x11, 0x1d, 0x91, 0x7a, 0x95, 0xcd, 0x21, 0xcb, 0x22, 0x59, - 0xcd, 0x50, 0x83, 0x39, 0xde, 0x42, 0x9c, 0xfd, 0xcf, 0x66, 0x80, 0x7c, 0x77, 0x42, 0xa3, 0x4b, - 0x4c, 0xc6, 0x55, 0xc1, 0xac, 0xe5, 0xac, 0x6b, 0x7d, 0x66, 0x3c, 0x39, 0x66, 0x06, 0x8b, 0x30, - 0xa4, 0x4a, 0x6f, 0x95, 0x74, 0x5f, 0x94, 0xf4, 0x5e, 0x79, 0x73, 0xd2, 0x7b, 0xf5, 0x4d, 0x49, - 0xef, 0x5f, 0x81, 0x96, 0x7f, 0x1a, 0x84, 0x4c, 0xe8, 0x30, 0x45, 0x25, 0xee, 0xce, 0xdc, 0x2d, - 0xdf, 0x6f, 0x3a, 0x4d, 0x01, 0xdc, 0x63, 0x30, 0xf2, 0x24, 0xad, 0x44, 0x07, 0xa7, 0x78, 0x49, - 0x43, 0x17, 0x43, 0x5b, 0x83, 0x53, 0x2a, 0xec, 0x46, 0x74, 0xad, 0xc8, 0x8f, 0x19, 0x3c, 0x26, - 0xf7, 0xa0, 0x1d, 0x87, 0x13, 0xa6, 0xba, 0xc9, 0x65, 0xe0, 0x0e, 0xe7, 0x26, 0x87, 0x1e, 0xf0, - 0xc5, 0x58, 0x81, 0x85, 0x49, 0x4c, 0xdd, 0x91, 0x1f, 0xc7, 0xec, 0x78, 0xee, 0x87, 0x41, 0x12, - 0x85, 0x43, 0xe1, 0x40, 0x9e, 0x9f, 0xc4, 0xf4, 0x39, 0xc7, 0x6c, 0x70, 0x04, 0xf9, 0x66, 0x3a, - 0xa4, 0xb1, 0xe7, 0x47, 0x71, 0x17, 0x70, 0x48, 0x72, 0xa6, 0x6c, 0xdc, 0x07, 0x9e, 0x1f, 0xa9, - 0xb1, 0xb0, 0x42, 0x9c, 0x49, 0xc6, 0x6f, 0x64, 0x93, 0xf1, 0x7f, 0x54, 0x9c, 0x8c, 0xdf, 0xc2, - 0xa6, 0x1f, 0x89, 0xa6, 0xf3, 0x5b, 0xfc, 0x85, 0x72, 0xf2, 0xf3, 0x77, 0x0c, 0xda, 0x5f, 0xe4, - 0x8e, 0xc1, 0x5c, 0xd1, 0x1d, 0x83, 0x0f, 0xa1, 0x81, 0x99, 0xdf, 0xee, 0x99, 0x1f, 0x24, 0xd2, - 0x19, 0xde, 0xd1, 0x53, 0xc3, 0xb7, 0x99, 0xf9, 0x0d, 0x91, 0xfc, 0x33, 0xce, 0xa7, 0xfb, 0xcf, - 0x7f, 0x89, 0xe9, 0xfe, 0x22, 0x43, 0x7d, 0x05, 0x6a, 0x72, 0x9f, 0x08, 0x81, 0xca, 0x49, 0x14, - 0x8e, 0xa4, 0x7f, 0x90, 0xfd, 0x4d, 0xda, 0x50, 0x4a, 0x42, 0xf1, 0x71, 0x29, 0x09, 0xed, 0xdf, - 0x83, 0x86, 0x46, 0x6a, 0xe4, 0x5d, 0xee, 0x76, 0x60, 0xaa, 0xb3, 0xb0, 0xab, 0xf9, 0x2a, 0xd6, - 0x05, 0x74, 0x67, 0x40, 0xbe, 0x06, 0xf3, 0x03, 0x3f, 0xa2, 0x78, 0x31, 0xc7, 0x8d, 0xe8, 0x39, - 0x8d, 0x62, 0xe9, 0xb2, 0xed, 0x28, 0x84, 0xc3, 0xe1, 0xb6, 0x0b, 0x0b, 0xc6, 0xde, 0x2a, 0xe9, - 0x36, 0x83, 0xeb, 0x26, 0xa3, 0x6c, 0x66, 0xca, 0xbd, 0xc0, 0x31, 0xed, 0x43, 0x78, 0x9b, 0xdd, - 0x71, 0x14, 0x1e, 0x63, 0x27, 0x96, 0x63, 0xc0, 0xec, 0xff, 0x51, 0x86, 0xf2, 0x76, 0x38, 0xd6, - 0xf3, 0x1e, 0xac, 0x7c, 0xde, 0x83, 0x30, 0x13, 0x5c, 0x65, 0x05, 0x08, 0x5d, 0xce, 0x00, 0x92, - 0x07, 0xd0, 0x66, 0xa2, 0x22, 0x09, 0x99, 0x59, 0x74, 0xe1, 0x45, 0x3c, 0x07, 0xbf, 0x8c, 0xfc, - 0x97, 0xc1, 0x90, 0x45, 0x28, 0x2b, 0xed, 0x16, 0x2b, 0xb0, 0x22, 0xb3, 0xc9, 0x31, 0x03, 0xed, - 0x52, 0xc4, 0x90, 0x44, 0x89, 0x49, 0x5e, 0xf3, 0x7b, 0x2e, 0x8f, 0xb8, 0x8e, 0x52, 0x84, 0x62, - 0x26, 0x0b, 0x93, 0x38, 0xa3, 0xd4, 0x02, 0x50, 0x65, 0x3d, 0xb0, 0x58, 0x33, 0x03, 0x8b, 0x77, - 0xa1, 0x91, 0x0c, 0xcf, 0xdd, 0xb1, 0x77, 0x39, 0x0c, 0xbd, 0x81, 0xe0, 0x74, 0x1d, 0x44, 0x1e, - 0x01, 0x8c, 0xc6, 0x63, 0xc1, 0x86, 0xe8, 0xb5, 0x4c, 0xa9, 0xfa, 0xf9, 0xc1, 0x01, 0xa7, 0x3e, - 0x47, 0xab, 0x43, 0xb6, 0xa0, 0x5d, 0x78, 0x91, 0xe6, 0xb6, 0xcc, 0x93, 0x0a, 0xc7, 0x2b, 0x05, - 0x8c, 0x9a, 0xf9, 0xa8, 0xf7, 0x1d, 0x20, 0xbf, 0xe2, 0x7d, 0x96, 0x97, 0x50, 0x57, 0x23, 0xd4, - 0x6f, 0x91, 0x60, 0x32, 0x64, 0xc3, 0xbc, 0x45, 0x82, 0xb9, 0x8f, 0xef, 0x41, 0x9b, 0x1f, 0x97, - 0xea, 0x00, 0xe0, 0x09, 0x6c, 0x19, 0xa8, 0xfd, 0xe7, 0x16, 0x54, 0x91, 0xf2, 0x98, 0x96, 0xca, - 0x71, 0x2a, 0x61, 0x44, 0xc4, 0x9e, 0xb2, 0x60, 0x62, 0x1b, 0x17, 0xec, 0x4a, 0x8a, 0x0c, 0xf4, - 0x4b, 0x76, 0x77, 0xa1, 0xae, 0x7a, 0xd2, 0x48, 0x29, 0x05, 0x92, 0x3b, 0x50, 0x39, 0x0b, 0xc7, - 0xd2, 0x90, 0x87, 0x74, 0x45, 0x1d, 0x84, 0xa7, 0xe3, 0x61, 0xed, 0xf1, 0x29, 0x70, 0x63, 0x29, - 0x0b, 0x2e, 0x98, 0xeb, 0x4c, 0xe1, 0x5c, 0x5f, 0xc0, 0x1c, 0x93, 0x0f, 0x5a, 0x6c, 0x78, 0xfa, - 0x61, 0xfa, 0x55, 0xa6, 0x01, 0xf6, 0x87, 0x93, 0x01, 0xd5, 0xdd, 0x29, 0x18, 0x53, 0x14, 0x70, - 0x69, 0x48, 0xd8, 0xff, 0xc2, 0xe2, 0x72, 0x87, 0xb5, 0x4b, 0xee, 0x43, 0x85, 0x9d, 0x7b, 0x19, - 0x9f, 0x9f, 0x4a, 0x50, 0x65, 0xf5, 0x1c, 0xac, 0xc1, 0x76, 0x11, 0xc3, 0x61, 0x7a, 0xeb, 0x3c, - 0x18, 0x96, 0xfa, 0x22, 0xd4, 0xcc, 0x32, 0x26, 0x7c, 0x06, 0x4a, 0x56, 0xb4, 0xfc, 0x8f, 0x8a, - 0x71, 0x96, 0x4a, 0x25, 0x71, 0x70, 0x4a, 0xb5, 0xbc, 0x8f, 0x7f, 0x59, 0x82, 0x96, 0x31, 0x26, - 0xc6, 0x3d, 0x78, 0x34, 0x70, 0x8f, 0xb2, 0xd8, 0x79, 0x1d, 0xa4, 0x73, 0x5e, 0xc9, 0xe4, 0x3c, - 0x15, 0x08, 0x2f, 0xeb, 0x81, 0xf0, 0x47, 0x50, 0x4f, 0x6f, 0x58, 0x9a, 0x83, 0x62, 0x3d, 0xca, - 0x54, 0xdd, 0xb4, 0x52, 0x1a, 0x3a, 0xaf, 0xea, 0xa1, 0xf3, 0x6f, 0x6b, 0xa1, 0xd5, 0x19, 0x6c, - 0xc6, 0x2e, 0x5a, 0xd5, 0x2f, 0x27, 0x17, 0xe3, 0x09, 0x34, 0xb4, 0xc1, 0xeb, 0x21, 0x54, 0xcb, - 0x08, 0xa1, 0xaa, 0xa4, 0xfa, 0x52, 0x9a, 0x54, 0x6f, 0xff, 0xac, 0x04, 0x2d, 0xc6, 0x6b, 0x7e, - 0x70, 0x7a, 0x10, 0x0e, 0xfd, 0xfe, 0x25, 0xd2, 0xb8, 0x64, 0x2b, 0xa1, 0x84, 0x49, 0x9e, 0x33, - 0xc1, 0x4c, 0x26, 0xaa, 0x9b, 0x44, 0x5c, 0x80, 0xab, 0x32, 0x93, 0xf0, 0x4c, 0x3e, 0x1e, 0x7b, - 0x31, 0xd5, 0xee, 0x7f, 0x3a, 0x26, 0x90, 0xc9, 0x61, 0x06, 0xc0, 0x2b, 0x12, 0x23, 0x7f, 0x38, - 0xf4, 0x79, 0x5d, 0xee, 0xa3, 0x28, 0x42, 0xb1, 0x3e, 0x07, 0x7e, 0xec, 0x1d, 0xa7, 0x09, 0x4b, - 0xaa, 0x8c, 0xd1, 0x22, 0xef, 0xb5, 0x16, 0x2d, 0xe2, 0x77, 0xaa, 0x4c, 0x60, 0x96, 0xaa, 0x66, - 0x73, 0x54, 0x65, 0xff, 0xdb, 0x12, 0x34, 0x34, 0x1a, 0x65, 0xb2, 0xa5, 0xf0, 0x10, 0xd6, 0xa0, - 0x22, 0x93, 0x2f, 0x30, 0xbc, 0x5e, 0x1a, 0x84, 0xdc, 0x33, 0x7b, 0xc5, 0x28, 0x33, 0x4a, 0x1f, - 0x83, 0x9e, 0x6f, 0x41, 0x9d, 0xf1, 0xe1, 0x87, 0xe8, 0x62, 0x13, 0x77, 0xad, 0x15, 0x40, 0x62, - 0x57, 0x11, 0x5b, 0x4d, 0xb1, 0x08, 0xb8, 0x32, 0xb7, 0xef, 0x31, 0x34, 0x45, 0x33, 0xb8, 0xc7, - 0x38, 0xe9, 0x54, 0x12, 0x18, 0xfb, 0xef, 0x18, 0x35, 0xe5, 0x97, 0xab, 0xf2, 0xcb, 0xda, 0x9b, - 0xbe, 0x94, 0x35, 0xed, 0x67, 0x2a, 0x6d, 0xf2, 0x59, 0xe4, 0x8d, 0xcf, 0xa4, 0x74, 0x7b, 0x04, - 0x0b, 0x52, 0x88, 0x4d, 0x02, 0x2f, 0x08, 0xc2, 0x49, 0xd0, 0xa7, 0x32, 0xff, 0xbe, 0x08, 0x65, - 0x0f, 0xd4, 0x6d, 0x2d, 0x6c, 0x88, 0x3c, 0x80, 0x2a, 0x57, 0xe3, 0xb9, 0xae, 0x52, 0x2c, 0xcf, - 0x78, 0x15, 0x72, 0x1f, 0xaa, 0x5c, 0x9b, 0x2f, 0x4d, 0x95, 0x40, 0xbc, 0x82, 0xbd, 0x02, 0x73, - 0xa8, 0x91, 0x6a, 0x82, 0xf8, 0x66, 0x91, 0x0e, 0x33, 0xd3, 0xe7, 0xe1, 0x8c, 0x45, 0x20, 0x7b, - 0x9c, 0xaf, 0xf4, 0xbc, 0x9e, 0x3f, 0x2f, 0x43, 0x43, 0x03, 0x33, 0x61, 0x89, 0x49, 0x1e, 0xee, - 0xc0, 0xf7, 0x46, 0x54, 0x06, 0x37, 0x5a, 0x4e, 0x06, 0xca, 0xea, 0x79, 0xe7, 0xa7, 0x6e, 0x38, - 0x49, 0xdc, 0x01, 0x3d, 0x8d, 0x28, 0x15, 0xca, 0x55, 0x06, 0xca, 0xea, 0x31, 0x6a, 0xd6, 0xea, - 0xf1, 0x7c, 0x85, 0x0c, 0x54, 0xe6, 0xcf, 0xf0, 0x75, 0xaa, 0xa4, 0xf9, 0x33, 0x7c, 0x55, 0xb2, - 0x62, 0xbe, 0x5a, 0x20, 0xe6, 0x3f, 0x82, 0x25, 0x2e, 0xd0, 0x85, 0xf4, 0x70, 0x33, 0xc4, 0x35, - 0x05, 0x4b, 0x1e, 0x40, 0x87, 0x8d, 0x59, 0xb2, 0x46, 0xec, 0xff, 0x84, 0xf3, 0x98, 0xe5, 0xe4, - 0xe0, 0xac, 0x2e, 0xc6, 0x5e, 0xf5, 0xba, 0x3c, 0x9f, 0x34, 0x07, 0xc7, 0xba, 0xde, 0x6b, 0xb3, - 0x6e, 0x5d, 0xd4, 0xcd, 0xc0, 0xc9, 0x63, 0x58, 0x1e, 0xd1, 0x81, 0xef, 0x99, 0x4d, 0xb8, 0xa9, - 0xc6, 0x31, 0x0d, 0xcd, 0x7a, 0x61, 0xab, 0xf0, 0x93, 0x70, 0x74, 0xec, 0xf3, 0x53, 0x96, 0x47, - 0x89, 0x2b, 0x4e, 0x0e, 0x6e, 0xb7, 0xa0, 0x71, 0x98, 0x84, 0x63, 0xb9, 0xf5, 0x6d, 0x68, 0xf2, - 0xa2, 0xb8, 0x71, 0x71, 0x13, 0x6e, 0x20, 0xbd, 0x1e, 0x85, 0xe3, 0x70, 0x18, 0x9e, 0x5e, 0x1a, - 0xee, 0xa9, 0x7f, 0x6f, 0xc1, 0x82, 0x81, 0x4d, 0xfd, 0x53, 0xe8, 0x4b, 0x97, 0x69, 0xf2, 0x9c, - 0xc4, 0xe7, 0xb5, 0x33, 0x8a, 0x57, 0xe4, 0x79, 0x00, 0x2f, 0x44, 0xe6, 0xfc, 0x5a, 0x7a, 0xf7, - 0x53, 0x7e, 0xc8, 0xe9, 0xbd, 0x9b, 0xa7, 0x77, 0xf1, 0xbd, 0xbc, 0x15, 0x2a, 0x9b, 0xf8, 0x6d, - 0x91, 0xfd, 0x3b, 0x10, 0x93, 0x2e, 0x9b, 0x19, 0x9b, 0xba, 0x3b, 0x53, 0x8e, 0xa0, 0xaf, 0x80, - 0xb1, 0xfd, 0x73, 0x0b, 0x20, 0x1d, 0x1d, 0xe6, 0x8c, 0xaa, 0x73, 0x96, 0x3f, 0xaf, 0xa2, 0x9d, - 0xa9, 0xef, 0x42, 0x53, 0xe5, 0xad, 0xa5, 0x47, 0x77, 0x43, 0xc2, 0x98, 0xaa, 0xf3, 0x3e, 0xcc, - 0x9d, 0x0e, 0xc3, 0x63, 0x54, 0xa9, 0xc4, 0x39, 0xcb, 0xef, 0x9d, 0xb4, 0x39, 0x58, 0x9e, 0x9e, - 0xe9, 0x39, 0x5f, 0x29, 0x4c, 0x78, 0xd3, 0x4f, 0x6d, 0x76, 0xd6, 0xcd, 0xe7, 0x56, 0xe2, 0x4a, - 0x2e, 0xff, 0xa5, 0xc2, 0xbe, 0x57, 0x45, 0x37, 0x9e, 0x40, 0x3b, 0xe2, 0x32, 0x53, 0x0a, 0xd4, - 0xca, 0x15, 0x02, 0xb5, 0x15, 0x19, 0x27, 0xf3, 0x57, 0xa1, 0xe3, 0x0d, 0xce, 0x69, 0x94, 0xf8, - 0xe8, 0xed, 0x45, 0x9d, 0x8e, 0x4f, 0x70, 0x4e, 0x83, 0xa3, 0xea, 0xf4, 0x3e, 0xcc, 0x89, 0x5b, - 0x40, 0xaa, 0xa6, 0x78, 0x68, 0x20, 0x05, 0xb3, 0x8a, 0xf6, 0x3f, 0x96, 0x69, 0x43, 0xe6, 0xee, - 0x5e, 0xbd, 0x2a, 0xfa, 0x0c, 0x4b, 0x99, 0x19, 0x7e, 0x45, 0x24, 0x45, 0x0c, 0xa4, 0x5b, 0xb9, - 0xac, 0xe5, 0x91, 0x0f, 0x44, 0xda, 0x95, 0xb9, 0xac, 0x95, 0xb7, 0x59, 0x56, 0xfb, 0x3f, 0x5b, - 0x30, 0xbb, 0x1d, 0x8e, 0x99, 0x69, 0x8f, 0x3a, 0x0e, 0x63, 0x13, 0x75, 0x05, 0x4f, 0x16, 0xdf, - 0x90, 0x6f, 0x5f, 0xa8, 0x95, 0xb4, 0xb2, 0x5a, 0xc9, 0x77, 0xe0, 0x26, 0x06, 0x36, 0xa2, 0x70, - 0x1c, 0x46, 0x8c, 0x5d, 0xbd, 0x21, 0x57, 0x41, 0xc2, 0x20, 0x39, 0x93, 0xe2, 0xf4, 0xaa, 0x2a, - 0xe8, 0x07, 0x1c, 0x26, 0xe7, 0x2e, 0x37, 0x37, 0x85, 0x16, 0xc5, 0xa5, 0x6c, 0x1e, 0x61, 0xff, - 0x16, 0xd4, 0x95, 0x03, 0x83, 0x7c, 0x00, 0xf5, 0xb3, 0x70, 0x2c, 0xbc, 0x1c, 0x96, 0x71, 0x37, - 0x41, 0xcc, 0xde, 0x49, 0x2b, 0xd8, 0xff, 0x6b, 0x16, 0x66, 0x77, 0x82, 0xf3, 0xd0, 0xef, 0x63, - 0xfa, 0xd1, 0x88, 0x8e, 0x42, 0x79, 0x29, 0x91, 0xfd, 0x8d, 0xef, 0x85, 0xa4, 0xcf, 0x06, 0x70, - 0x16, 0xd2, 0x20, 0xcc, 0x40, 0x8e, 0xf4, 0x6b, 0xff, 0xa2, 0x94, 0x5a, 0x7d, 0x55, 0xed, 0x5a, - 0x27, 0x6b, 0x8d, 0x5f, 0x47, 0xc7, 0xb5, 0xe3, 0x97, 0x49, 0x34, 0x08, 0x5b, 0x7c, 0x71, 0x0f, - 0x80, 0x27, 0x8a, 0xf3, 0x4c, 0x46, 0x01, 0x42, 0xa3, 0x3f, 0xa2, 0x3c, 0x34, 0xa5, 0x54, 0x2f, - 0x66, 0xf4, 0xeb, 0x40, 0xa6, 0x9e, 0xf1, 0x0f, 0x78, 0x1d, 0x7e, 0x1c, 0xe8, 0x20, 0xcc, 0x46, - 0xc9, 0x3c, 0xa2, 0xc1, 0x1f, 0x42, 0xc9, 0x82, 0x79, 0xa2, 0x99, 0x12, 0xba, 0x7c, 0x9e, 0xc0, - 0x9f, 0x4e, 0xc8, 0xc2, 0x35, 0x57, 0x01, 0xbf, 0x2e, 0x25, 0x5d, 0x05, 0x8c, 0x64, 0xbc, 0xe1, - 0xf0, 0xd8, 0xeb, 0xbf, 0xe2, 0x96, 0x6d, 0x93, 0x47, 0x34, 0x0d, 0x20, 0x66, 0xf3, 0xa7, 0xfb, - 0x8a, 0x89, 0x40, 0x15, 0x47, 0x07, 0x91, 0x55, 0xd3, 0x7f, 0xd5, 0x9e, 0xe2, 0xbf, 0xd2, 0x2b, - 0xe9, 0x89, 0x51, 0x73, 0xb9, 0x0b, 0x4c, 0xde, 0x60, 0x20, 0x12, 0x66, 0x3a, 0xfc, 0xe9, 0x00, - 0x05, 0x40, 0x47, 0x0d, 0x5f, 0x30, 0x5e, 0x61, 0x1e, 0x2b, 0x18, 0x30, 0x72, 0x87, 0xfb, 0x61, - 0xc7, 0x9e, 0x3f, 0xc0, 0xc4, 0x54, 0x6e, 0x0b, 0x2b, 0x18, 0x6b, 0x43, 0xfe, 0x8d, 0x07, 0xe7, - 0x02, 0xae, 0x8a, 0x01, 0x63, 0x6b, 0xa3, 0xca, 0xa3, 0xf4, 0xc6, 0x93, 0x09, 0x24, 0x1f, 0x62, - 0x22, 0x42, 0x42, 0xf1, 0x5a, 0x53, 0x7b, 0xf5, 0xa6, 0x98, 0xb3, 0x20, 0x5b, 0xf9, 0x3f, 0x26, - 0x5e, 0x38, 0xbc, 0x26, 0x53, 0xdb, 0x78, 0x2c, 0x68, 0xc9, 0x50, 0xdb, 0x44, 0x55, 0x8c, 0x05, - 0xf1, 0x0a, 0xe4, 0xb1, 0x66, 0x89, 0x75, 0xb1, 0xf2, 0xad, 0x4c, 0xfb, 0x53, 0x6c, 0x30, 0x46, - 0xcc, 0x7e, 0xcc, 0xce, 0x9f, 0x98, 0x06, 0x03, 0xbc, 0xe0, 0x54, 0x73, 0x34, 0xc8, 0xaf, 0xd7, - 0x46, 0x5b, 0x83, 0xa6, 0x3e, 0x4f, 0x52, 0x83, 0xca, 0xfe, 0xc1, 0xd6, 0x5e, 0xe7, 0x1a, 0x69, - 0xc0, 0xec, 0xe1, 0xd6, 0xd1, 0xd1, 0xee, 0xd6, 0x66, 0xc7, 0x22, 0x4d, 0xa8, 0xa9, 0xbb, 0x24, - 0x25, 0x56, 0x5a, 0xdb, 0xd8, 0xd8, 0x3a, 0x38, 0xda, 0xda, 0xec, 0x94, 0x3f, 0xa9, 0xd4, 0x4a, - 0x9d, 0x32, 0x2a, 0x98, 0xda, 0x32, 0xbc, 0xc1, 0xcf, 0x76, 0x07, 0x00, 0x0d, 0x9f, 0x34, 0xb1, - 0xaa, 0xe2, 0x68, 0x10, 0x26, 0xc8, 0x95, 0x7f, 0xa2, 0xcc, 0x9f, 0x7b, 0x90, 0x65, 0xdc, 0x5c, - 0x7c, 0x57, 0x41, 0x8f, 0x0f, 0x56, 0x1d, 0x13, 0xc8, 0x08, 0x5f, 0x00, 0xf0, 0x82, 0x03, 0x17, - 0x17, 0x3a, 0x88, 0x11, 0x52, 0x44, 0xe3, 0x70, 0x78, 0x4e, 0x79, 0x15, 0xae, 0x3e, 0x1a, 0x30, - 0xd6, 0x97, 0x90, 0x88, 0xda, 0xe5, 0xa3, 0xaa, 0x63, 0x02, 0xc9, 0xd7, 0x25, 0x21, 0xd5, 0x90, - 0x90, 0x96, 0xf3, 0x54, 0x61, 0x10, 0xd1, 0xf3, 0x9c, 0xa3, 0xac, 0x8e, 0x04, 0xf2, 0x1b, 0xf9, - 0xef, 0xde, 0xc2, 0x61, 0x46, 0x56, 0x80, 0x8c, 0xc6, 0x63, 0xb7, 0xc0, 0x83, 0x55, 0x71, 0x0a, - 0x30, 0xbf, 0x06, 0x07, 0x5b, 0x02, 0x64, 0x6d, 0x30, 0x10, 0xc3, 0xd4, 0x5f, 0xbf, 0x88, 0xf4, - 0xe7, 0x56, 0xa4, 0xc8, 0x2e, 0x10, 0x8b, 0xa5, 0x62, 0xb1, 0x78, 0xa5, 0xf0, 0xb0, 0x77, 0xa0, - 0x71, 0xa0, 0x3d, 0xe0, 0x62, 0xb3, 0x13, 0x44, 0x3e, 0xdd, 0xc2, 0xcf, 0x16, 0xee, 0x58, 0x4b, - 0xa1, 0xda, 0x90, 0x4a, 0xfa, 0x90, 0xec, 0x7f, 0x68, 0xf1, 0x3b, 0xf1, 0x6a, 0x0a, 0xbc, 0x7f, - 0x1b, 0x9a, 0x2a, 0xb8, 0x94, 0x5e, 0x10, 0x34, 0x60, 0xac, 0x0e, 0x0e, 0xc7, 0x0d, 0x4f, 0x4e, - 0x62, 0x2a, 0xaf, 0xf2, 0x18, 0x30, 0xa9, 0xac, 0x33, 0xf5, 0xdf, 0xe7, 0x3d, 0xc4, 0xe2, 0x4a, - 0x4f, 0x0e, 0xce, 0x28, 0x5d, 0xf8, 0xc6, 0xe5, 0x25, 0x26, 0x55, 0x56, 0xf7, 0x18, 0xb3, 0x2b, - 0xfd, 0x00, 0x6a, 0xaa, 0x5d, 0xf3, 0x24, 0x96, 0x35, 0x15, 0x9e, 0x9d, 0xf8, 0x68, 0xc8, 0x1b, - 0x83, 0xe6, 0x0c, 0x97, 0x47, 0x30, 0x5a, 0x3a, 0xf1, 0xa3, 0x6c, 0x75, 0xce, 0x81, 0x05, 0x18, - 0xfb, 0x25, 0x2c, 0x48, 0xf1, 0xa1, 0x59, 0x11, 0xe6, 0x46, 0x5a, 0x6f, 0x3a, 0x05, 0x4a, 0xf9, - 0x53, 0xc0, 0xfe, 0x37, 0x15, 0x98, 0x95, 0xaf, 0x23, 0xd9, 0x05, 0xaf, 0xf9, 0xd4, 0xcd, 0x87, - 0x80, 0x48, 0xd7, 0x78, 0xee, 0x01, 0x09, 0x41, 0xe8, 0x06, 0xf7, 0xb3, 0xa7, 0x7b, 0xea, 0x60, - 0xcd, 0x9c, 0xf0, 0x4b, 0x50, 0x19, 0x7b, 0xc9, 0x19, 0xfa, 0xdf, 0x38, 0x2d, 0x61, 0x59, 0xba, - 0xf0, 0xab, 0xa6, 0x0b, 0xbf, 0xe8, 0xf9, 0x23, 0xae, 0xca, 0xe6, 0x9f, 0x3f, 0xba, 0x05, 0x75, - 0xae, 0x8d, 0xa4, 0x5e, 0xfa, 0x14, 0x90, 0xd1, 0x5e, 0x6a, 0x39, 0xed, 0xe5, 0xed, 0xf5, 0x8a, - 0x6f, 0xc2, 0x0c, 0xbf, 0x02, 0x2c, 0xae, 0x6c, 0xc9, 0x23, 0x47, 0xac, 0xa4, 0xfc, 0x9f, 0x67, - 0xee, 0x3a, 0xa2, 0xae, 0xfe, 0x88, 0x48, 0xc3, 0x7c, 0x44, 0x44, 0x0f, 0x2e, 0x34, 0x33, 0xc1, - 0x85, 0x07, 0xd0, 0x51, 0xcb, 0x87, 0x0e, 0xb8, 0x20, 0x16, 0x57, 0x54, 0x72, 0xf0, 0xf4, 0xd8, - 0x6c, 0x1b, 0xc7, 0x26, 0x93, 0x70, 0x6b, 0x49, 0x42, 0x47, 0xe3, 0x44, 0x1c, 0x9b, 0xf6, 0x53, - 0x68, 0x19, 0x83, 0x64, 0xc7, 0x90, 0xb8, 0xc4, 0xd5, 0xb9, 0x46, 0x5a, 0x50, 0xdf, 0xd9, 0x73, - 0x9f, 0xee, 0xee, 0x3c, 0xdb, 0x3e, 0xea, 0x58, 0xac, 0x78, 0xf8, 0x62, 0x63, 0x63, 0x6b, 0x6b, - 0x13, 0x8f, 0x25, 0x80, 0x99, 0xa7, 0x6b, 0x3b, 0xec, 0x88, 0x2a, 0xdb, 0xff, 0xdb, 0x82, 0x86, - 0xd6, 0x3c, 0xf9, 0x96, 0x5a, 0x19, 0xfe, 0xce, 0xc4, 0xed, 0xfc, 0x10, 0x56, 0xa4, 0xa0, 0xd6, - 0x96, 0x46, 0xbd, 0xf8, 0x54, 0x9a, 0xfa, 0xe2, 0x13, 0xdb, 0x1e, 0x8f, 0xb7, 0xa0, 0xd6, 0x81, - 0x5b, 0x57, 0x59, 0x30, 0x4f, 0x57, 0x4b, 0x4f, 0x17, 0x56, 0x93, 0x7b, 0x14, 0xb3, 0x60, 0xfb, - 0x23, 0x80, 0x74, 0x34, 0xe6, 0xb4, 0xaf, 0x99, 0xd3, 0xb6, 0xb4, 0x69, 0x97, 0xec, 0x4d, 0x2e, - 0x30, 0xc4, 0x12, 0xaa, 0x30, 0xf8, 0xd7, 0x81, 0x48, 0x07, 0x16, 0xa6, 0x85, 0x8e, 0x87, 0x34, - 0x91, 0x57, 0x3b, 0xe7, 0x05, 0x66, 0x47, 0x21, 0xe4, 0xed, 0xe4, 0xb4, 0x95, 0x54, 0xee, 0x08, - 0x8a, 0xcb, 0xca, 0x1d, 0x51, 0xd5, 0x51, 0x78, 0xbb, 0x07, 0xdd, 0x4d, 0xca, 0x5a, 0x5b, 0x1b, - 0x0e, 0x33, 0xc3, 0xb1, 0x6f, 0xc2, 0x8d, 0x02, 0x9c, 0x70, 0x4f, 0x7c, 0x17, 0xae, 0xaf, 0xf1, - 0x5b, 0x9c, 0xbf, 0xae, 0x0b, 0x23, 0x76, 0x17, 0x96, 0xb2, 0x4d, 0x8a, 0xce, 0x9e, 0xc2, 0xfc, - 0x26, 0x3d, 0x9e, 0x9c, 0xee, 0xd2, 0xf3, 0xb4, 0x23, 0x02, 0x95, 0xf8, 0x2c, 0xbc, 0x10, 0xeb, - 0x83, 0x7f, 0x93, 0xdb, 0x00, 0x43, 0x56, 0xc7, 0x8d, 0xc7, 0xb4, 0x2f, 0xdf, 0xf1, 0x40, 0xc8, - 0xe1, 0x98, 0xf6, 0xed, 0x8f, 0x80, 0xe8, 0xed, 0x88, 0xf5, 0x62, 0x26, 0xc3, 0xe4, 0xd8, 0x8d, - 0x2f, 0xe3, 0x84, 0x8e, 0xe4, 0x03, 0x25, 0x3a, 0xc8, 0x7e, 0x1f, 0x9a, 0x07, 0xde, 0xa5, 0x43, - 0x3f, 0x13, 0x2f, 0x8c, 0x2d, 0xc3, 0xec, 0xd8, 0xbb, 0x64, 0xfc, 0xac, 0x42, 0x2c, 0x88, 0xb6, - 0xff, 0xb8, 0x02, 0x33, 0xbc, 0x26, 0x6b, 0x75, 0x40, 0xe3, 0xc4, 0x0f, 0x90, 0xc7, 0x64, 0xab, - 0x1a, 0x28, 0x27, 0x30, 0x4b, 0x05, 0x02, 0x53, 0xb8, 0xda, 0xe4, 0x7b, 0x08, 0x82, 0x64, 0x0d, - 0x18, 0x13, 0x5b, 0xe9, 0xf5, 0x33, 0x4e, 0xa9, 0x29, 0x20, 0x13, 0xc3, 0x4c, 0x0d, 0x13, 0x3e, - 0x3e, 0x79, 0x16, 0x08, 0x99, 0xa8, 0x83, 0x0a, 0xcd, 0x9f, 0x59, 0x79, 0xcf, 0x26, 0x63, 0xfe, - 0xe4, 0xcc, 0x9c, 0xda, 0x5b, 0x98, 0x39, 0xdc, 0xff, 0x76, 0x95, 0x99, 0x03, 0x6f, 0x63, 0xe6, - 0xbc, 0x4d, 0xec, 0xb0, 0x07, 0x35, 0x3c, 0xd3, 0x35, 0x11, 0x29, 0xcb, 0xe4, 0x37, 0x35, 0x1b, - 0x80, 0xe7, 0x31, 0xdc, 0x4c, 0xf9, 0xc5, 0xa1, 0x9f, 0x7d, 0x39, 0x61, 0x98, 0x1f, 0xc2, 0xac, - 0x80, 0x32, 0xca, 0x0e, 0xbc, 0x91, 0x7c, 0x87, 0x06, 0xff, 0x66, 0x4b, 0x87, 0xcf, 0x61, 0x7c, - 0x36, 0xf1, 0x23, 0x3a, 0x90, 0x77, 0xb5, 0x35, 0x10, 0x26, 0x97, 0xc7, 0xee, 0xab, 0x20, 0xbc, - 0x08, 0xc4, 0x6d, 0x6d, 0x55, 0xb6, 0x09, 0x74, 0xf0, 0x3d, 0xaa, 0x71, 0x18, 0xc9, 0xa7, 0x85, - 0xec, 0x3f, 0xb0, 0xa0, 0x23, 0x18, 0x4d, 0xe1, 0x64, 0xc2, 0xc0, 0x55, 0x4f, 0x12, 0xdc, 0x83, - 0x16, 0xfa, 0x3a, 0xd4, 0x91, 0x23, 0x82, 0xef, 0x06, 0x90, 0x8d, 0x57, 0x66, 0x77, 0x8e, 0xfc, - 0xa1, 0xa0, 0x5b, 0x1d, 0x24, 0x4f, 0xad, 0xc8, 0x13, 0x97, 0xbc, 0x2c, 0x47, 0x95, 0xed, 0x5f, - 0x58, 0x30, 0xaf, 0x0d, 0x58, 0x30, 0xea, 0x13, 0x68, 0xaa, 0x67, 0xdf, 0xa8, 0x52, 0xaa, 0x96, - 0x4d, 0xc9, 0x92, 0x7e, 0x66, 0x54, 0x46, 0x7a, 0xf7, 0x2e, 0x71, 0x80, 0xf1, 0x64, 0x24, 0xb4, - 0x19, 0x1d, 0xc4, 0xe8, 0xe8, 0x82, 0xd2, 0x57, 0xaa, 0x0a, 0xd7, 0xa7, 0x0c, 0x18, 0xc6, 0x88, - 0xc2, 0x20, 0x39, 0x53, 0x95, 0x2a, 0x22, 0x46, 0xa4, 0x03, 0xed, 0xff, 0x5a, 0x82, 0x05, 0xee, - 0x74, 0x13, 0xce, 0x4e, 0xf5, 0xf2, 0xce, 0x0c, 0xf7, 0x3f, 0x72, 0xa1, 0xb5, 0x7d, 0xcd, 0x11, - 0x65, 0xf2, 0xad, 0xb7, 0x74, 0x14, 0xaa, 0xdb, 0x64, 0x53, 0xf6, 0xa2, 0x5c, 0xb4, 0x17, 0x57, - 0xac, 0x74, 0x51, 0xb8, 0xae, 0x5a, 0x1c, 0xae, 0x7b, 0xbb, 0xf0, 0x58, 0xee, 0xca, 0xd5, 0xac, - 0xa8, 0x65, 0x5c, 0xb9, 0x5a, 0x85, 0x65, 0x03, 0x80, 0xf2, 0xda, 0x3f, 0xf1, 0xa9, 0xbc, 0xff, - 0x3e, 0x1f, 0xd3, 0xc4, 0x35, 0xaa, 0xac, 0xcf, 0x42, 0x35, 0xee, 0x87, 0x63, 0x6a, 0x2f, 0xc1, - 0xa2, 0xb9, 0xb8, 0xe2, 0x94, 0xf8, 0xb9, 0x05, 0xdd, 0xa7, 0x3c, 0xe9, 0xc2, 0x0f, 0x4e, 0xb7, - 0xfd, 0x38, 0x09, 0x23, 0xf5, 0x40, 0xda, 0x1d, 0x80, 0x38, 0xf1, 0x22, 0x61, 0x67, 0x72, 0x65, - 0x57, 0x83, 0xb0, 0x35, 0xa2, 0xc1, 0x80, 0x63, 0x39, 0x6d, 0xa8, 0x72, 0xce, 0x98, 0x10, 0x2e, - 0x49, 0x43, 0x25, 0x7f, 0x8f, 0xdf, 0x04, 0x65, 0x8b, 0x41, 0xcf, 0xf1, 0xe8, 0xe5, 0x7e, 0xbe, - 0x0c, 0xd4, 0xfe, 0xc3, 0x12, 0xcc, 0xa5, 0x83, 0xe4, 0x37, 0xcb, 0x0d, 0x01, 0x2e, 0xf4, 0xf0, - 0x54, 0x80, 0x8b, 0xf0, 0xa1, 0xeb, 0x33, 0xc5, 0x5c, 0xf3, 0x4a, 0x6a, 0x50, 0x72, 0x0f, 0x1a, - 0xb2, 0x14, 0x4e, 0x12, 0xed, 0xa5, 0x22, 0x1d, 0xcc, 0xaf, 0x98, 0x30, 0xd3, 0x40, 0x98, 0x39, - 0xa2, 0x84, 0xef, 0x21, 0x8c, 0x12, 0xfc, 0x92, 0xef, 0xa9, 0x2c, 0x32, 0x81, 0xc6, 0x74, 0x6a, - 0xbe, 0x87, 0xa8, 0x4f, 0xeb, 0xba, 0x66, 0x4d, 0xbd, 0xf0, 0xa8, 0x78, 0x9e, 0xb7, 0x98, 0x5e, - 0xb6, 0xab, 0x38, 0x3a, 0x48, 0x7a, 0x85, 0xc2, 0x89, 0x61, 0xfe, 0x1a, 0x30, 0xfb, 0x6f, 0x59, - 0x70, 0xa3, 0x60, 0x1b, 0x85, 0x0c, 0xd8, 0x84, 0xf9, 0x13, 0x85, 0x94, 0x4b, 0xcd, 0x05, 0xc1, - 0x92, 0x14, 0xae, 0xe6, 0xf2, 0x3a, 0xf9, 0x0f, 0x94, 0xb9, 0xc5, 0x37, 0xcf, 0xb8, 0x5b, 0x99, - 0x47, 0xd8, 0x07, 0xd0, 0xdb, 0x7a, 0xcd, 0x44, 0xca, 0x86, 0xfe, 0xcc, 0xb7, 0xa4, 0xac, 0xd5, - 0x9c, 0xc8, 0x7c, 0xb3, 0x33, 0xfa, 0x84, 0xdf, 0x18, 0x53, 0x6d, 0x91, 0x6f, 0xbc, 0x6d, 0x23, - 0x3a, 0xf7, 0xdf, 0x15, 0xbb, 0xce, 0xdf, 0x29, 0x97, 0x37, 0x3c, 0x35, 0x90, 0x7d, 0x0e, 0x73, - 0xcf, 0x27, 0xc3, 0xc4, 0x4f, 0xdf, 0x2c, 0x27, 0xdf, 0x12, 0x1f, 0x61, 0x13, 0x72, 0xe9, 0x0a, - 0xbb, 0xd2, 0xeb, 0xb1, 0x15, 0x1b, 0xb1, 0x96, 0xdc, 0x7c, 0x8f, 0x79, 0x84, 0x7d, 0x03, 0x96, - 0xd3, 0x2e, 0xf9, 0xda, 0xc9, 0x63, 0xe7, 0x8f, 0x2c, 0x9e, 0x59, 0x6d, 0x3e, 0xa1, 0x4e, 0x9e, - 0xc1, 0x42, 0xec, 0x07, 0xa7, 0x43, 0xaa, 0xb7, 0x13, 0x8b, 0x95, 0xb8, 0x6e, 0x0e, 0x4f, 0x3c, - 0xb3, 0xee, 0x14, 0x7d, 0xc1, 0x08, 0xa4, 0x78, 0xa0, 0x29, 0x81, 0x64, 0x96, 0xa4, 0x68, 0x02, - 0x9f, 0x40, 0xdb, 0xec, 0x8c, 0x3c, 0x16, 0x57, 0x27, 0xd3, 0x91, 0x95, 0x33, 0x37, 0xe0, 0x52, - 0xca, 0x30, 0x6a, 0xda, 0x3f, 0xb3, 0xa0, 0xeb, 0x50, 0x46, 0xc6, 0x54, 0xeb, 0x54, 0x50, 0xcf, - 0x93, 0x5c, 0xb3, 0xd3, 0x27, 0xac, 0xae, 0x64, 0xca, 0xb9, 0xae, 0x4c, 0xdd, 0x94, 0xed, 0x6b, - 0x05, 0xb3, 0x5a, 0xaf, 0xc1, 0x8c, 0x98, 0xdf, 0x32, 0x5c, 0x17, 0x43, 0x92, 0xc3, 0x49, 0xc3, - 0x8e, 0x46, 0xa7, 0x46, 0xd8, 0xb1, 0x07, 0x5d, 0xfe, 0x0e, 0x9e, 0x3e, 0x0f, 0xf1, 0xe1, 0x26, - 0x90, 0xe7, 0x5e, 0xdf, 0x8b, 0xc2, 0x30, 0x38, 0xa0, 0x91, 0x48, 0x52, 0x45, 0xed, 0x13, 0xa3, - 0x72, 0x52, 0x51, 0xe6, 0x25, 0xf9, 0x74, 0x5b, 0x18, 0xc8, 0x27, 0xf2, 0x78, 0xc9, 0x76, 0x60, - 0x61, 0xdd, 0x7b, 0x45, 0x65, 0x4b, 0xe9, 0x2a, 0x35, 0xc6, 0xaa, 0x51, 0xb9, 0xf6, 0xf2, 0xce, - 0x75, 0xbe, 0x5b, 0x47, 0xaf, 0x6d, 0xaf, 0xc2, 0xa2, 0xd9, 0xa6, 0x10, 0x25, 0x3d, 0xa8, 0x8d, - 0x04, 0x4c, 0x8c, 0x4e, 0x95, 0x1f, 0x7c, 0x0e, 0x0d, 0xed, 0x6d, 0x43, 0xb2, 0x0c, 0x0b, 0x2f, - 0x77, 0x8e, 0xf6, 0xb6, 0x0e, 0x0f, 0xdd, 0x83, 0x17, 0xeb, 0x9f, 0x6e, 0x7d, 0xdf, 0xdd, 0x5e, - 0x3b, 0xdc, 0xee, 0x5c, 0x23, 0x4b, 0x40, 0xf6, 0xb6, 0x0e, 0x8f, 0xb6, 0x36, 0x0d, 0xb8, 0x45, - 0xee, 0x40, 0xef, 0xc5, 0xde, 0x8b, 0xc3, 0xad, 0x4d, 0xb7, 0xe8, 0xbb, 0x12, 0xb9, 0x0d, 0x37, - 0x04, 0xbe, 0xe0, 0xf3, 0xf2, 0x83, 0x27, 0xd0, 0xc9, 0xba, 0x25, 0x0d, 0x77, 0xee, 0x55, 0x7e, - 0xdf, 0x07, 0xff, 0xa8, 0x0c, 0x90, 0x26, 0xa7, 0x92, 0x2e, 0x2c, 0x6e, 0xae, 0x1d, 0xad, 0xed, - 0xee, 0xb3, 0x41, 0x38, 0xfb, 0x47, 0x5b, 0x1b, 0x47, 0xae, 0xb3, 0xf5, 0xdd, 0xce, 0xb5, 0x42, - 0xcc, 0xfe, 0x01, 0x33, 0xd9, 0x97, 0x61, 0x61, 0x67, 0x6f, 0xe7, 0x68, 0x67, 0x6d, 0xd7, 0x75, - 0xf6, 0x5f, 0xec, 0xec, 0x3d, 0xe3, 0xef, 0xae, 0x94, 0xc9, 0x3b, 0x70, 0xf3, 0xc5, 0xc1, 0x53, - 0x67, 0x7f, 0xef, 0xc8, 0x3d, 0xdc, 0x7e, 0x71, 0xb4, 0x89, 0xaf, 0xb6, 0x6c, 0x38, 0x3b, 0x07, - 0xbc, 0xcd, 0xca, 0x55, 0x15, 0x58, 0xd3, 0x55, 0xb6, 0x62, 0xcf, 0xf6, 0x0f, 0x0f, 0x77, 0x0e, - 0xdc, 0xef, 0xbe, 0xd8, 0x72, 0x76, 0xb6, 0x0e, 0xf1, 0xc3, 0x99, 0x02, 0x38, 0xab, 0x3f, 0x4b, - 0xe6, 0xa1, 0x75, 0xb4, 0xfb, 0x3d, 0x77, 0x7f, 0x6f, 0x67, 0x7f, 0x0f, 0xab, 0xd6, 0x4c, 0x10, - 0xab, 0x55, 0x27, 0x3d, 0x58, 0xda, 0xfa, 0xdd, 0x23, 0xb7, 0xa0, 0x65, 0x98, 0x82, 0x63, 0xdf, - 0x35, 0xc8, 0x0d, 0xb8, 0x7e, 0x78, 0xb4, 0x76, 0xb4, 0xb3, 0xe1, 0x8a, 0x67, 0x9b, 0xd8, 0x26, - 0xb0, 0xcf, 0x9a, 0xc5, 0x28, 0xf6, 0x55, 0x8b, 0x2c, 0x42, 0xe7, 0x60, 0xed, 0xfb, 0xcf, 0xb7, - 0xf6, 0x8e, 0xdc, 0xb5, 0xcd, 0x4d, 0x07, 0x3f, 0x68, 0xe7, 0xa0, 0xac, 0xee, 0x1c, 0xdb, 0xa8, - 0xe7, 0x07, 0x07, 0x58, 0xa5, 0x23, 0x0b, 0x0c, 0x33, 0xbf, 0xfa, 0xb3, 0x32, 0xb4, 0xf9, 0x6d, - 0x01, 0xfe, 0x63, 0x11, 0x34, 0x22, 0xcf, 0x61, 0x56, 0xfc, 0xea, 0x08, 0xb9, 0xae, 0x1e, 0xdb, - 0xd0, 0x7f, 0xe7, 0xa4, 0xb7, 0x94, 0x05, 0x0b, 0xf6, 0x5b, 0xf8, 0x2b, 0xff, 0xf1, 0xbf, 0xff, - 0x7e, 0xa9, 0x45, 0x1a, 0x0f, 0xcf, 0x3f, 0x7c, 0x78, 0x4a, 0x83, 0x98, 0xb5, 0xf1, 0x17, 0x01, - 0xd2, 0xdf, 0xd2, 0x20, 0x5d, 0xe5, 0x7d, 0xcc, 0xfc, 0xd0, 0x48, 0xef, 0x46, 0x01, 0x46, 0xb4, - 0x7b, 0x03, 0xdb, 0x5d, 0xb0, 0xdb, 0xac, 0x5d, 0x3f, 0xf0, 0x13, 0xfe, 0xbb, 0x1a, 0x1f, 0x5b, - 0x0f, 0xc8, 0x00, 0x9a, 0xfa, 0xaf, 0x5c, 0x10, 0x19, 0xed, 0x2f, 0xf8, 0x9d, 0x8e, 0xde, 0xcd, - 0x42, 0x9c, 0x94, 0x39, 0xd8, 0xc7, 0x75, 0xbb, 0xc3, 0xfa, 0x98, 0x60, 0x8d, 0xb4, 0x97, 0x21, - 0x97, 0xc4, 0xe9, 0x8f, 0x59, 0x90, 0x5b, 0x9a, 0x70, 0xcc, 0xfd, 0x94, 0x46, 0xef, 0xf6, 0x14, - 0xac, 0xe8, 0xeb, 0x36, 0xf6, 0xb5, 0x6c, 0x13, 0xd6, 0x57, 0x1f, 0xeb, 0xc8, 0x9f, 0xd2, 0xf8, - 0xd8, 0x7a, 0xb0, 0xfa, 0xa7, 0xf7, 0xa1, 0xae, 0x32, 0x81, 0xc8, 0x8f, 0xa1, 0x65, 0x5c, 0xe7, - 0x20, 0x72, 0x1a, 0x45, 0xb7, 0x3f, 0x7a, 0xb7, 0x8a, 0x91, 0xa2, 0xe3, 0x3b, 0xd8, 0x71, 0x97, - 0x2c, 0xb1, 0x8e, 0xc5, 0x7d, 0x88, 0x87, 0x78, 0xfd, 0x89, 0x3f, 0x5d, 0xf2, 0x4a, 0x3b, 0x71, - 0x78, 0x67, 0xb7, 0xb2, 0x87, 0x80, 0xd1, 0xdb, 0xed, 0x29, 0x58, 0xd1, 0xdd, 0x2d, 0xec, 0x6e, - 0x89, 0x2c, 0xea, 0xdd, 0xa9, 0xec, 0x1c, 0x8a, 0xcf, 0x07, 0xe9, 0xbf, 0xf3, 0x40, 0x6e, 0xa7, - 0x8f, 0xbb, 0x14, 0xfc, 0xfe, 0x83, 0x22, 0x91, 0xfc, 0x8f, 0x40, 0xd8, 0x5d, 0xec, 0x8a, 0x10, - 0xdc, 0x3e, 0xfd, 0x67, 0x1e, 0xc8, 0x31, 0x34, 0xb4, 0xe7, 0x90, 0xc9, 0x8d, 0xa9, 0x4f, 0x37, - 0xf7, 0x7a, 0x45, 0xa8, 0xa2, 0xa9, 0xe8, 0xed, 0x3f, 0x64, 0x0a, 0xe9, 0x0f, 0xa1, 0xae, 0x1e, - 0xd8, 0x25, 0xcb, 0xda, 0x83, 0xc7, 0xfa, 0x83, 0xc0, 0xbd, 0x6e, 0x1e, 0x51, 0x44, 0x7c, 0x7a, - 0xeb, 0x8c, 0xf8, 0x5e, 0x42, 0x43, 0x7b, 0x44, 0x57, 0x4d, 0x20, 0xff, 0x50, 0xaf, 0x9a, 0x40, - 0xc1, 0x9b, 0xbb, 0xf6, 0x3c, 0x76, 0xd1, 0x20, 0x75, 0xa4, 0xef, 0xe4, 0x75, 0x18, 0x93, 0x5d, - 0xb8, 0x2e, 0x4e, 0xd6, 0x63, 0xfa, 0x45, 0xb6, 0xa1, 0xe0, 0xa7, 0x35, 0x1e, 0x59, 0xe4, 0x09, - 0xd4, 0xe4, 0x5b, 0xc9, 0x64, 0xa9, 0xf8, 0xcd, 0xe7, 0xde, 0x72, 0x0e, 0x2e, 0x8e, 0xc1, 0xef, - 0x03, 0xa4, 0x2f, 0xf6, 0x2a, 0x21, 0x91, 0x7b, 0x01, 0x58, 0x51, 0x40, 0xfe, 0x79, 0x5f, 0x7b, - 0x09, 0x27, 0xd8, 0x21, 0x28, 0x24, 0x02, 0x7a, 0x21, 0xdf, 0xae, 0xf8, 0x11, 0x34, 0xb4, 0x47, - 0x7b, 0xd5, 0xf2, 0xe5, 0x1f, 0xfc, 0x55, 0xcb, 0x57, 0xf0, 0xc6, 0xaf, 0xdd, 0xc3, 0xd6, 0x17, - 0xed, 0x39, 0xd6, 0x7a, 0xec, 0x9f, 0x06, 0x23, 0x5e, 0x81, 0x6d, 0xd0, 0x19, 0xb4, 0x8c, 0x97, - 0x79, 0x15, 0x87, 0x16, 0xbd, 0xfb, 0xab, 0x38, 0xb4, 0xf0, 0x31, 0x5f, 0x49, 0x67, 0xf6, 0x3c, - 0xeb, 0xe7, 0x1c, 0xab, 0x68, 0x3d, 0xfd, 0x00, 0x1a, 0xda, 0x2b, 0xbb, 0x6a, 0x2e, 0xf9, 0x07, - 0x7d, 0xd5, 0x5c, 0x8a, 0x1e, 0xe5, 0x5d, 0xc4, 0x3e, 0xda, 0x36, 0x92, 0x02, 0xbe, 0x46, 0xc5, - 0xda, 0xfe, 0x31, 0xb4, 0xcd, 0x77, 0x77, 0x15, 0xef, 0x17, 0xbe, 0xe0, 0xab, 0x78, 0x7f, 0xca, - 0x63, 0xbd, 0x82, 0xa4, 0x1f, 0x2c, 0xa8, 0x4e, 0x1e, 0xfe, 0x54, 0x24, 0x36, 0x7f, 0x4e, 0xbe, - 0xcb, 0x04, 0x9c, 0x78, 0x25, 0x8d, 0x2c, 0x6b, 0x54, 0xab, 0xbf, 0xa5, 0xa6, 0xf8, 0x25, 0xf7, - 0xa0, 0x9a, 0x49, 0xcc, 0xfc, 0x3d, 0xad, 0x67, 0xb0, 0xa0, 0x88, 0x59, 0xbd, 0x7a, 0x16, 0xab, - 0x39, 0x14, 0x3e, 0xae, 0xd6, 0xeb, 0x64, 0xb1, 0x8f, 0x2c, 0x7e, 0xfc, 0xe1, 0xdb, 0x52, 0xda, - 0xf1, 0xa7, 0x3f, 0x7c, 0xa6, 0x1d, 0x7f, 0xc6, 0x13, 0x54, 0xd9, 0xe3, 0x2f, 0xf1, 0x59, 0x1b, - 0x01, 0xcc, 0x65, 0x6e, 0xc8, 0x2a, 0xf6, 0x2a, 0x7e, 0xc4, 0xa0, 0x77, 0xe7, 0xea, 0x8b, 0xb5, - 0xa6, 0x28, 0x92, 0xd2, 0xf4, 0xa1, 0x7c, 0x21, 0xe5, 0xf7, 0xa0, 0xa9, 0x3f, 0x17, 0x4a, 0x74, - 0x99, 0x90, 0xed, 0xe9, 0x66, 0x21, 0xce, 0xa4, 0x12, 0xd2, 0xd4, 0xbb, 0x21, 0xdf, 0x83, 0x25, - 0xb5, 0xcc, 0xfa, 0x45, 0xc9, 0x98, 0xbc, 0x53, 0x70, 0x7d, 0xd2, 0x58, 0xec, 0x1b, 0x53, 0xef, - 0x57, 0x3e, 0xb2, 0x18, 0xf5, 0x99, 0x6f, 0x30, 0xa6, 0x27, 0x4f, 0xd1, 0xd3, 0x93, 0xe9, 0xc9, - 0x53, 0xf8, 0x70, 0xa3, 0xa4, 0x3e, 0xb2, 0x60, 0xac, 0x11, 0xcf, 0xdf, 0x22, 0x3f, 0x80, 0x39, - 0xed, 0x5a, 0xfb, 0xe1, 0x65, 0xd0, 0x57, 0x9c, 0x94, 0x7f, 0xc2, 0xa8, 0x57, 0x64, 0x96, 0xda, - 0xcb, 0xd8, 0xfe, 0xbc, 0x6d, 0x2c, 0x0e, 0xe3, 0xa2, 0x0d, 0x68, 0xe8, 0x57, 0xe6, 0xaf, 0x68, - 0x77, 0x59, 0x43, 0xe9, 0xef, 0xe3, 0x3c, 0xb2, 0xc8, 0x2e, 0x74, 0xb2, 0x4f, 0x79, 0x28, 0x99, - 0x52, 0xf4, 0xfc, 0x48, 0x2f, 0x83, 0x34, 0x1e, 0x00, 0x21, 0x07, 0x3c, 0x2b, 0x58, 0xfd, 0x06, - 0x45, 0x18, 0x65, 0x4f, 0x75, 0xf3, 0xb7, 0x29, 0x54, 0x6b, 0x45, 0xbf, 0x4a, 0x72, 0xdf, 0x7a, - 0x64, 0x91, 0xbf, 0x6b, 0x41, 0xd3, 0xb8, 0x20, 0x6f, 0xe4, 0x58, 0x66, 0xe6, 0xd9, 0xd5, 0x71, - 0xfa, 0x44, 0x6d, 0x07, 0x17, 0x71, 0xf7, 0xc1, 0x27, 0xc6, 0x26, 0xfd, 0xd4, 0xf0, 0xf4, 0xae, - 0x64, 0x7f, 0x88, 0xe2, 0xf3, 0x6c, 0x05, 0xfd, 0x19, 0xaa, 0xcf, 0x1f, 0x59, 0xe4, 0x9f, 0x58, - 0xd0, 0x36, 0x43, 0x38, 0x6a, 0xba, 0x85, 0xc1, 0x22, 0x45, 0x4a, 0x53, 0xe2, 0x3e, 0x3f, 0xc0, - 0x51, 0x1e, 0x3d, 0x70, 0x8c, 0x51, 0x8a, 0xd7, 0x43, 0x7f, 0xb5, 0xd1, 0x92, 0x8f, 0xf9, 0xef, - 0x42, 0xc9, 0xe8, 0x35, 0xc9, 0xff, 0x8e, 0x90, 0x22, 0x3f, 0xfd, 0x57, 0x77, 0x70, 0x13, 0x7e, - 0xc4, 0x7f, 0x80, 0x41, 0x86, 0x40, 0x19, 0x15, 0xbf, 0xed, 0xf7, 0xf6, 0x3d, 0x9c, 0xd3, 0x1d, - 0xfb, 0x86, 0x31, 0xa7, 0xac, 0xe2, 0xb1, 0xc6, 0x47, 0x27, 0x7e, 0x30, 0x27, 0x3d, 0x39, 0x73, - 0x3f, 0xa2, 0x33, 0x7d, 0x90, 0x23, 0x3e, 0x48, 0x51, 0xdd, 0x60, 0xb5, 0xb7, 0x6c, 0xc6, 0x7e, - 0x80, 0x63, 0xbd, 0x67, 0xbf, 0x33, 0x75, 0xac, 0x0f, 0x31, 0x10, 0xc3, 0x46, 0x7c, 0x00, 0x90, - 0x66, 0x9b, 0x90, 0x4c, 0xa6, 0x83, 0x12, 0x40, 0xf9, 0x84, 0x14, 0x93, 0x9f, 0x65, 0x42, 0x04, - 0x6b, 0xf1, 0x87, 0x5c, 0x9c, 0xee, 0xc8, 0x1c, 0x09, 0x5d, 0xfb, 0x32, 0x53, 0x42, 0x0c, 0xed, - 0x2b, 0xdb, 0xbe, 0x21, 0x4c, 0x55, 0xc2, 0xc5, 0x0b, 0x68, 0xed, 0x86, 0xe1, 0xab, 0xc9, 0x58, - 0xa5, 0x3f, 0x9a, 0x31, 0xd2, 0x6d, 0x2f, 0x3e, 0xeb, 0x65, 0x66, 0x61, 0xdf, 0xc5, 0xa6, 0x7a, - 0xa4, 0xab, 0x35, 0xf5, 0xf0, 0xa7, 0x69, 0x26, 0xcb, 0xe7, 0xc4, 0x83, 0x79, 0x25, 0xa3, 0xd5, + // 9926 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5d, 0x6c, 0x1c, 0xd9, + 0x95, 0x18, 0xac, 0xea, 0x1f, 0xb2, 0xfb, 0xf4, 0x0f, 0x9b, 0x97, 0x14, 0xd9, 0x6a, 0xfd, 0x8c, + 0xa6, 0x2c, 0xcf, 0xc8, 0xf2, 0x98, 0xd2, 0xd0, 0xf6, 0xac, 0x3c, 0xfa, 0xd6, 0x6b, 0xfe, 0x49, + 0xe4, 0x0c, 0x45, 0xd2, 0x45, 0xca, 0x5a, 0xdb, 0xdf, 0xa2, 0x5c, 0xec, 0xbe, 0x24, 0xcb, 0xea, + 0xae, 0xea, 0xa9, 0xaa, 0x26, 0x45, 0x3b, 0x93, 0x87, 0x20, 0x09, 0x82, 0xbc, 0x04, 0x86, 0x11, + 0x20, 0x9b, 0x1f, 0x2c, 0xe0, 0x4d, 0x10, 0x04, 0x01, 0x92, 0x3c, 0x05, 0x1b, 0xc0, 0x79, 0xca, + 0xc3, 0xe6, 0x25, 0xc8, 0x43, 0x02, 0x04, 0x48, 0x80, 0x00, 0x8b, 0xcd, 0x43, 0x16, 0x01, 0xf2, + 0x94, 0xe4, 0x39, 0xb8, 0xe7, 0xfe, 0xd4, 0xbd, 0x55, 0xd5, 0x94, 0xc6, 0x76, 0xfc, 0x22, 0xf1, + 0x9e, 0x7b, 0xea, 0xfe, 0x9e, 0x73, 0xee, 0xf9, 0xb9, 0xe7, 0x36, 0xd4, 0xa3, 0x71, 0x7f, 0x65, + 0x1c, 0x85, 0x49, 0x48, 0xaa, 0xc3, 0x20, 0x1a, 0xf7, 0x7b, 0xb7, 0x4e, 0xc3, 0xf0, 0x74, 0x48, + 0x1f, 0x7a, 0x63, 0xff, 0xa1, 0x17, 0x04, 0x61, 0xe2, 0x25, 0x7e, 0x18, 0xc4, 0x1c, 0xc9, 0xfe, + 0x11, 0xb4, 0x9f, 0xd1, 0xe0, 0x90, 0xd2, 0x81, 0x43, 0x3f, 0x9b, 0xd0, 0x38, 0x21, 0x5f, 0x85, + 0x79, 0x8f, 0xfe, 0x84, 0xd2, 0x81, 0x3b, 0xf6, 0xe2, 0x78, 0x7c, 0x16, 0x79, 0x31, 0xed, 0x5a, + 0x77, 0xad, 0xfb, 0x4d, 0xa7, 0xc3, 0x2b, 0x0e, 0x14, 0x9c, 0xbc, 0x0b, 0xcd, 0x98, 0xa1, 0xd2, + 0x20, 0x89, 0xc2, 0xf1, 0x65, 0xb7, 0x84, 0x78, 0x0d, 0x06, 0xdb, 0xe2, 0x20, 0x7b, 0x08, 0x73, + 0xaa, 0x87, 0x78, 0x1c, 0x06, 0x31, 0x25, 0x8f, 0x60, 0xb1, 0xef, 0x8f, 0xcf, 0x68, 0xe4, 0xe2, + 0xc7, 0xa3, 0x80, 0x8e, 0xc2, 0xc0, 0xef, 0x77, 0xad, 0xbb, 0xe5, 0xfb, 0x75, 0x87, 0xf0, 0x3a, + 0xf6, 0xc5, 0x73, 0x51, 0x43, 0xde, 0x87, 0x39, 0x1a, 0x70, 0x38, 0x1d, 0xe0, 0x57, 0xa2, 0xab, + 0x76, 0x0a, 0x66, 0x1f, 0xd8, 0x7f, 0xa3, 0x04, 0xf3, 0x3b, 0x81, 0x9f, 0xbc, 0xf4, 0x86, 0x43, + 0x9a, 0xc8, 0x39, 0xbd, 0x0f, 0x73, 0x17, 0x08, 0xc0, 0x39, 0x5d, 0x84, 0xd1, 0x40, 0xcc, 0xa8, + 0xcd, 0xc1, 0x07, 0x02, 0x3a, 0x75, 0x64, 0xa5, 0xa9, 0x23, 0x2b, 0x5c, 0xae, 0xf2, 0x94, 0xe5, + 0x7a, 0x1f, 0xe6, 0x22, 0xda, 0x0f, 0xcf, 0x69, 0x74, 0xe9, 0x5e, 0xf8, 0xc1, 0x20, 0xbc, 0xe8, + 0x56, 0xee, 0x5a, 0xf7, 0xab, 0x4e, 0x5b, 0x82, 0x5f, 0x22, 0x94, 0xac, 0xc3, 0x5c, 0xff, 0xcc, + 0x0b, 0x02, 0x3a, 0x74, 0x8f, 0xbd, 0xfe, 0xab, 0xc9, 0x38, 0xee, 0x56, 0xef, 0x5a, 0xf7, 0x1b, + 0xab, 0x37, 0x56, 0x70, 0x57, 0x57, 0x36, 0xce, 0xbc, 0x60, 0x1d, 0x6b, 0x0e, 0x03, 0x6f, 0x1c, + 0x9f, 0x85, 0x89, 0xd3, 0x16, 0x5f, 0x70, 0x70, 0x6c, 0x2f, 0x02, 0xd1, 0x57, 0x82, 0xaf, 0xbd, + 0xfd, 0x4f, 0x2d, 0x58, 0x78, 0x11, 0x0c, 0xc3, 0xfe, 0xab, 0x5f, 0x71, 0x89, 0x0a, 0xe6, 0x50, + 0x7a, 0xdb, 0x39, 0x94, 0xbf, 0xe8, 0x1c, 0x96, 0x60, 0xd1, 0x1c, 0xac, 0x98, 0x05, 0x85, 0xeb, + 0xec, 0xeb, 0x53, 0x2a, 0x87, 0x25, 0xa7, 0xf1, 0x15, 0xe8, 0xf4, 0x27, 0x51, 0x44, 0x83, 0xdc, + 0x3c, 0xe6, 0x04, 0x5c, 0x4d, 0xe4, 0x5d, 0x68, 0x06, 0xf4, 0x22, 0x45, 0x13, 0xb4, 0x1b, 0xd0, + 0x0b, 0x89, 0x62, 0x77, 0x61, 0x29, 0xdb, 0x8d, 0x18, 0xc0, 0x9f, 0x59, 0x50, 0x79, 0x91, 0xbc, + 0x0e, 0xc9, 0x0a, 0x54, 0x92, 0xcb, 0x31, 0xe7, 0x90, 0xf6, 0x2a, 0x11, 0x53, 0x5b, 0x1b, 0x0c, + 0x22, 0x1a, 0xc7, 0x47, 0x97, 0x63, 0xea, 0x34, 0x3d, 0x5e, 0x70, 0x19, 0x1e, 0xe9, 0xc2, 0xac, + 0x28, 0x63, 0x87, 0x75, 0x47, 0x16, 0xc9, 0x1d, 0x00, 0x6f, 0x14, 0x4e, 0x82, 0xc4, 0x8d, 0xbd, + 0x04, 0x97, 0xaa, 0xec, 0x68, 0x10, 0x72, 0x0b, 0xea, 0xe3, 0x57, 0x6e, 0xdc, 0x8f, 0xfc, 0x71, + 0x82, 0x64, 0x53, 0x77, 0x52, 0x00, 0xf9, 0x2a, 0xd4, 0xc2, 0x49, 0x32, 0x0e, 0xfd, 0x20, 0x11, + 0xa4, 0x32, 0x27, 0xc6, 0xb2, 0x3f, 0x49, 0x0e, 0x18, 0xd8, 0x51, 0x08, 0xe4, 0x1e, 0xb4, 0xfa, + 0x61, 0x70, 0xe2, 0x47, 0x23, 0x2e, 0x0c, 0xba, 0x33, 0xd8, 0x9b, 0x09, 0xb4, 0xff, 0x55, 0x09, + 0x1a, 0x47, 0x91, 0x17, 0xc4, 0x5e, 0x9f, 0x01, 0xd8, 0xd0, 0x93, 0xd7, 0xee, 0x99, 0x17, 0x9f, + 0xe1, 0x6c, 0xeb, 0x8e, 0x2c, 0x92, 0x25, 0x98, 0xe1, 0x03, 0xc5, 0x39, 0x95, 0x1d, 0x51, 0x22, + 0x1f, 0xc0, 0x7c, 0x30, 0x19, 0xb9, 0x66, 0x5f, 0x65, 0xa4, 0x96, 0x7c, 0x05, 0x5b, 0x80, 0x63, + 0xb6, 0xd7, 0xbc, 0x0b, 0x3e, 0x43, 0x0d, 0x42, 0x6c, 0x68, 0x8a, 0x12, 0xf5, 0x4f, 0xcf, 0xf8, + 0x34, 0xab, 0x8e, 0x01, 0x63, 0x6d, 0x24, 0xfe, 0x88, 0xba, 0x71, 0xe2, 0x8d, 0xc6, 0x62, 0x5a, + 0x1a, 0x04, 0xeb, 0xc3, 0xc4, 0x1b, 0xba, 0x27, 0x94, 0xc6, 0xdd, 0x59, 0x51, 0xaf, 0x20, 0xe4, + 0x3d, 0x68, 0x0f, 0x68, 0x9c, 0xb8, 0x62, 0x53, 0x68, 0xdc, 0xad, 0x21, 0xeb, 0x67, 0xa0, 0xac, + 0x9d, 0xc8, 0xbb, 0x70, 0xd9, 0x02, 0xd0, 0xd7, 0xdd, 0x3a, 0x1f, 0x6b, 0x0a, 0x61, 0x94, 0xf3, + 0x8c, 0x26, 0xda, 0xea, 0xc5, 0x82, 0x42, 0xed, 0x5d, 0x20, 0x1a, 0x78, 0x93, 0x26, 0x9e, 0x3f, + 0x8c, 0xc9, 0x47, 0xd0, 0x4c, 0x34, 0x64, 0x14, 0x85, 0x0d, 0x45, 0x4e, 0xda, 0x07, 0x8e, 0x81, + 0x67, 0x9f, 0x41, 0xed, 0x29, 0xa5, 0xbb, 0xfe, 0xc8, 0x4f, 0xc8, 0x12, 0x54, 0x4f, 0xfc, 0xd7, + 0x94, 0x13, 0x7c, 0x79, 0xfb, 0x9a, 0xc3, 0x8b, 0xe4, 0x1d, 0x00, 0xfc, 0xc3, 0x1d, 0x29, 0xc2, + 0xda, 0xbe, 0xe6, 0xd4, 0x11, 0xf6, 0x9c, 0x51, 0x56, 0x0f, 0x66, 0xc7, 0x34, 0xea, 0x53, 0xb9, + 0x7f, 0xdb, 0xd7, 0x1c, 0x09, 0x58, 0x9f, 0x85, 0xea, 0x90, 0xb5, 0x6e, 0xff, 0x69, 0x15, 0x1a, + 0x87, 0x34, 0x50, 0x9c, 0x46, 0xa0, 0xc2, 0xd6, 0x44, 0x70, 0x17, 0xfe, 0x4d, 0xbe, 0x04, 0x0d, + 0x5c, 0xa7, 0x38, 0x89, 0xfc, 0xe0, 0x94, 0x13, 0xf8, 0x7a, 0xa9, 0x6b, 0x39, 0xc0, 0xc0, 0x87, + 0x08, 0x25, 0x1d, 0x28, 0x7b, 0x23, 0x49, 0xe0, 0xec, 0x4f, 0x72, 0x03, 0x6a, 0xde, 0x28, 0xe1, + 0xc3, 0x6b, 0x22, 0x78, 0xd6, 0x1b, 0x25, 0x38, 0xb4, 0x77, 0xa1, 0x39, 0xf6, 0x2e, 0x47, 0x8c, + 0x9f, 0x15, 0x55, 0x34, 0x9d, 0x86, 0x80, 0x6d, 0x33, 0xb2, 0x58, 0x85, 0x05, 0x1d, 0x45, 0x76, + 0x5e, 0x55, 0x9d, 0xcf, 0x6b, 0xd8, 0x62, 0x0c, 0xef, 0xc3, 0x9c, 0xfc, 0x26, 0xe2, 0xf3, 0x41, + 0x5a, 0xa9, 0x3b, 0x6d, 0x01, 0x96, 0xb3, 0xbc, 0x0f, 0x9d, 0x13, 0x3f, 0xf0, 0x86, 0x6e, 0x7f, + 0x98, 0x9c, 0xbb, 0x03, 0x3a, 0x4c, 0x3c, 0xa4, 0x9a, 0xaa, 0xd3, 0x46, 0xf8, 0xc6, 0x30, 0x39, + 0xdf, 0x64, 0x50, 0xf2, 0x01, 0xd4, 0x4f, 0x28, 0x75, 0x71, 0xb1, 0xba, 0x35, 0x83, 0x03, 0xe5, + 0x0e, 0x39, 0xb5, 0x13, 0xb9, 0x57, 0x1f, 0x40, 0x27, 0x9c, 0x24, 0xa7, 0xa1, 0x1f, 0x9c, 0xba, + 0x4c, 0xe6, 0xb9, 0xfe, 0x00, 0xa9, 0xa8, 0xb2, 0x5e, 0x7a, 0x64, 0x39, 0x6d, 0x59, 0xc7, 0xa4, + 0xcf, 0xce, 0x80, 0xbc, 0x07, 0x73, 0x43, 0x2f, 0x4e, 0xdc, 0xb3, 0x70, 0xec, 0x8e, 0x27, 0xc7, + 0xaf, 0xe8, 0x65, 0xb7, 0x85, 0x0b, 0xd1, 0x62, 0xe0, 0xed, 0x70, 0x7c, 0x80, 0x40, 0x72, 0x1b, + 0x00, 0xc7, 0xc9, 0x07, 0x01, 0x77, 0xad, 0xfb, 0x2d, 0xa7, 0xce, 0x20, 0xbc, 0xd3, 0xef, 0xc3, + 0x02, 0x6e, 0x4f, 0x7f, 0x12, 0x27, 0xe1, 0xc8, 0x65, 0xf2, 0x3a, 0x1a, 0xc4, 0xdd, 0x06, 0xd2, + 0xda, 0x57, 0xc4, 0x60, 0xb5, 0x3d, 0x5e, 0xd9, 0xa4, 0x71, 0xb2, 0x81, 0xc8, 0x0e, 0xc7, 0x65, + 0x87, 0xfa, 0xa5, 0x33, 0x3f, 0xc8, 0xc2, 0xc9, 0x07, 0x40, 0xbc, 0xe1, 0x30, 0xbc, 0x70, 0x63, + 0x3a, 0x3c, 0x71, 0xc5, 0x22, 0x76, 0xdb, 0x77, 0xad, 0xfb, 0x35, 0xa7, 0x83, 0x35, 0x87, 0x74, + 0x78, 0x72, 0xc0, 0xe1, 0xe4, 0x23, 0x68, 0xe1, 0x40, 0x4e, 0xa8, 0x97, 0x4c, 0x22, 0x1a, 0x77, + 0xe7, 0xee, 0x96, 0xef, 0xb7, 0x57, 0xe7, 0xd5, 0x7a, 0x21, 0x78, 0xdd, 0x4f, 0x9c, 0x26, 0xc3, + 0x13, 0xe5, 0xb8, 0xb7, 0x09, 0x4b, 0xc5, 0x43, 0x62, 0x44, 0xc5, 0x56, 0x85, 0x11, 0x63, 0xc5, + 0x61, 0x7f, 0x92, 0x45, 0xa8, 0x9e, 0x7b, 0xc3, 0x09, 0x15, 0x72, 0x9d, 0x17, 0x3e, 0x2e, 0x3d, + 0xb6, 0xec, 0x3f, 0xb1, 0xa0, 0xc9, 0x67, 0x29, 0xf4, 0x91, 0x7b, 0xd0, 0x92, 0xd4, 0x40, 0xa3, + 0x28, 0x8c, 0x84, 0x78, 0x33, 0x81, 0xe4, 0x01, 0x74, 0x24, 0x60, 0x1c, 0x51, 0x7f, 0xe4, 0x9d, + 0xca, 0xb6, 0x73, 0x70, 0xb2, 0x9a, 0xb6, 0x18, 0x85, 0x93, 0x84, 0x8a, 0x93, 0xaf, 0x29, 0x26, + 0xe8, 0x30, 0x98, 0x63, 0xa2, 0x30, 0xf1, 0x56, 0x40, 0xea, 0x06, 0xcc, 0xfe, 0xdb, 0x16, 0x10, + 0x36, 0xf4, 0xa3, 0x90, 0x37, 0x21, 0xa8, 0x34, 0xcb, 0x25, 0xd6, 0x5b, 0x73, 0x49, 0xe9, 0x2a, + 0x2e, 0xb1, 0xa1, 0xca, 0x47, 0x5f, 0x29, 0x18, 0x3d, 0xaf, 0xfa, 0xa4, 0x52, 0x2b, 0x77, 0x2a, + 0xf6, 0x7f, 0x2e, 0xc3, 0xe2, 0x06, 0x3f, 0xba, 0xd7, 0xfa, 0x7d, 0x3a, 0x56, 0xfc, 0xf3, 0x0e, + 0x34, 0x82, 0x70, 0x40, 0x25, 0xd5, 0xf2, 0x81, 0x01, 0x03, 0x69, 0x24, 0x7b, 0xe6, 0xf9, 0x01, + 0x1f, 0x38, 0x5f, 0xcf, 0x3a, 0x42, 0x70, 0xd8, 0xef, 0xc1, 0xdc, 0x98, 0x06, 0x03, 0x9d, 0x4d, + 0xb8, 0x72, 0xd5, 0x12, 0x60, 0xc1, 0x21, 0xef, 0x40, 0xe3, 0x64, 0xc2, 0xf1, 0x98, 0x70, 0xa9, + 0x20, 0x1d, 0x80, 0x00, 0xad, 0x71, 0x19, 0x33, 0x9e, 0xc4, 0x67, 0x58, 0x5b, 0xc5, 0xda, 0x59, + 0x56, 0x66, 0x55, 0xb7, 0x01, 0x06, 0x93, 0x38, 0x11, 0x5c, 0x33, 0x83, 0x95, 0x75, 0x06, 0xe1, + 0x5c, 0xf3, 0x35, 0x58, 0x18, 0x79, 0xaf, 0x5d, 0xa4, 0x1f, 0xd7, 0x0f, 0xdc, 0x93, 0x21, 0x9e, + 0x3e, 0xb3, 0x88, 0xd7, 0x19, 0x79, 0xaf, 0xbf, 0xc7, 0x6a, 0x76, 0x82, 0xa7, 0x08, 0x67, 0xa2, + 0x45, 0xaa, 0x3d, 0x11, 0x8d, 0x69, 0x74, 0x4e, 0x51, 0x1a, 0x54, 0x94, 0x6e, 0xe3, 0x70, 0x28, + 0x1b, 0xd1, 0x88, 0xcd, 0x3b, 0x19, 0xf6, 0x39, 0xeb, 0x3b, 0xb3, 0x23, 0x3f, 0xd8, 0x4e, 0x86, + 0x7d, 0x72, 0x0b, 0x80, 0xc9, 0x92, 0x31, 0x8d, 0xdc, 0x57, 0x17, 0xc8, 0xc7, 0x15, 0x94, 0x1d, + 0x07, 0x34, 0xfa, 0xf4, 0x82, 0xdc, 0x84, 0x7a, 0x3f, 0x46, 0x61, 0xe4, 0x5d, 0x76, 0x1b, 0xc8, + 0xe4, 0xb5, 0x7e, 0xcc, 0xc4, 0x90, 0x77, 0xc9, 0x18, 0x91, 0x8d, 0xd6, 0xc3, 0x5d, 0xa0, 0x03, + 0x6c, 0x3e, 0x46, 0xa9, 0xda, 0xc2, 0xc1, 0xae, 0x89, 0x0a, 0xd6, 0x4f, 0x4c, 0xbe, 0x04, 0x2d, + 0x39, 0xd8, 0x93, 0xa1, 0x77, 0x1a, 0xa3, 0x58, 0x69, 0x39, 0x4d, 0x01, 0x7c, 0xca, 0x60, 0xf6, + 0x4b, 0xae, 0x6c, 0x69, 0x7b, 0x2b, 0xf8, 0x86, 0x1d, 0xfb, 0x08, 0xc1, 0x7d, 0xad, 0x39, 0xa2, + 0x54, 0xb4, 0x69, 0xa5, 0x82, 0x4d, 0xb3, 0x7f, 0x61, 0x41, 0x53, 0xb4, 0x8c, 0x1a, 0x0a, 0x79, + 0x04, 0x44, 0xee, 0x62, 0xf2, 0xda, 0x1f, 0xb8, 0xc7, 0x97, 0x09, 0x8d, 0x39, 0xd1, 0x6c, 0x5f, + 0x73, 0x0a, 0xea, 0x98, 0x1c, 0x35, 0xa0, 0x71, 0x12, 0x71, 0x9a, 0xde, 0xbe, 0xe6, 0xe4, 0x6a, + 0x18, 0x8b, 0x31, 0x1d, 0x68, 0x92, 0xb8, 0x7e, 0x30, 0xa0, 0xaf, 0x91, 0x94, 0x5a, 0x8e, 0x01, + 0x5b, 0x6f, 0x43, 0x53, 0xff, 0xce, 0xfe, 0x31, 0xd4, 0xa4, 0x06, 0x85, 0xda, 0x43, 0x66, 0x5c, + 0x8e, 0x06, 0x21, 0x3d, 0xa8, 0x99, 0xa3, 0x70, 0x6a, 0x5f, 0xa4, 0x6f, 0xfb, 0xdb, 0xd0, 0xd9, + 0x65, 0x44, 0x14, 0x30, 0xa2, 0x15, 0x6a, 0xe1, 0x12, 0xcc, 0x68, 0xcc, 0x53, 0x77, 0x44, 0x89, + 0x9d, 0xbf, 0x67, 0x61, 0x9c, 0x88, 0x7e, 0xf0, 0x6f, 0xfb, 0x4f, 0x2d, 0x20, 0x5b, 0x71, 0xe2, + 0x8f, 0xbc, 0x84, 0x3e, 0xa5, 0x4a, 0x3c, 0xec, 0x43, 0x93, 0xb5, 0x76, 0x14, 0xae, 0x71, 0x25, + 0x8d, 0x2b, 0x17, 0x5f, 0x15, 0xec, 0x9c, 0xff, 0x60, 0x45, 0xc7, 0xe6, 0x22, 0xdf, 0x68, 0x80, + 0x71, 0x5b, 0xe2, 0x45, 0xa7, 0x34, 0x41, 0x0d, 0x4e, 0xe8, 0xff, 0xc0, 0x41, 0x1b, 0x61, 0x70, + 0xd2, 0xfb, 0x3d, 0x98, 0xcf, 0xb5, 0xa1, 0xcb, 0xe8, 0x7a, 0x81, 0x8c, 0x2e, 0xeb, 0x32, 0xba, + 0x0f, 0x0b, 0xc6, 0xb8, 0x04, 0xc5, 0x75, 0x61, 0x96, 0x31, 0x06, 0x53, 0x14, 0x2c, 0xae, 0x28, + 0x88, 0x22, 0x59, 0x85, 0xc5, 0x13, 0x4a, 0x23, 0x2f, 0xc1, 0x22, 0xb2, 0x0e, 0xdb, 0x13, 0xd1, + 0x72, 0x61, 0x9d, 0xfd, 0xe7, 0x16, 0xcc, 0x31, 0x69, 0xfa, 0xdc, 0x0b, 0x2e, 0xe5, 0x5a, 0xed, + 0x16, 0xae, 0xd5, 0x7d, 0xed, 0x70, 0xd4, 0xb0, 0xbf, 0xe8, 0x42, 0x95, 0xb3, 0x0b, 0x45, 0xee, + 0x42, 0xd3, 0x18, 0x6e, 0x95, 0x6b, 0xa4, 0xb1, 0x97, 0x1c, 0xd0, 0x68, 0xfd, 0x32, 0xa1, 0xbf, + 0xfe, 0x52, 0xbe, 0x07, 0x9d, 0x74, 0xd8, 0x62, 0x1d, 0x09, 0x54, 0x18, 0x61, 0x8a, 0x06, 0xf0, + 0x6f, 0xfb, 0xef, 0x5b, 0x1c, 0x71, 0x23, 0xf4, 0x95, 0xb6, 0xca, 0x10, 0x99, 0xd2, 0x2b, 0x11, + 0xd9, 0xdf, 0x53, 0xb5, 0xfd, 0x5f, 0x7f, 0xb2, 0x4c, 0x26, 0xc6, 0x34, 0x18, 0xb8, 0xde, 0x70, + 0x88, 0x82, 0xb8, 0xe6, 0xcc, 0xb2, 0xf2, 0xda, 0x70, 0x68, 0xbf, 0x0f, 0xf3, 0xda, 0xe8, 0xae, + 0x98, 0xc7, 0x1e, 0x90, 0x5d, 0x3f, 0x4e, 0x5e, 0x04, 0xf1, 0x58, 0x53, 0xe4, 0x6e, 0x42, 0x9d, + 0x49, 0x5b, 0x36, 0x32, 0xce, 0xb9, 0x55, 0x87, 0x89, 0x5f, 0x36, 0xae, 0x18, 0x2b, 0xbd, 0xd7, + 0xa2, 0xb2, 0x24, 0x2a, 0xbd, 0xd7, 0x58, 0x69, 0x3f, 0x86, 0x05, 0xa3, 0x3d, 0xd1, 0xf5, 0xbb, + 0x50, 0x9d, 0x24, 0xaf, 0x43, 0xa9, 0xaa, 0x37, 0x04, 0x85, 0x30, 0xa3, 0xd0, 0xe1, 0x35, 0xf6, + 0x13, 0x98, 0xdf, 0xa3, 0x17, 0x82, 0x91, 0xe5, 0x40, 0xde, 0x7b, 0xa3, 0xc1, 0x88, 0xf5, 0xf6, + 0x0a, 0x10, 0xfd, 0xe3, 0x94, 0x01, 0xa4, 0xf9, 0x68, 0x19, 0xe6, 0xa3, 0xfd, 0x1e, 0x90, 0x43, + 0xff, 0x34, 0x78, 0x4e, 0xe3, 0xd8, 0x3b, 0x55, 0xac, 0xdf, 0x81, 0xf2, 0x28, 0x3e, 0x15, 0xa2, + 0x8a, 0xfd, 0x69, 0x7f, 0x1d, 0x16, 0x0c, 0x3c, 0xd1, 0xf0, 0x2d, 0xa8, 0xc7, 0xfe, 0x69, 0x80, + 0x8a, 0x96, 0x68, 0x3a, 0x05, 0xd8, 0x4f, 0x61, 0xf1, 0x7b, 0x34, 0xf2, 0x4f, 0x2e, 0xdf, 0xd4, + 0xbc, 0xd9, 0x4e, 0x29, 0xdb, 0xce, 0x16, 0x5c, 0xcf, 0xb4, 0x23, 0xba, 0xe7, 0xe4, 0x2b, 0x76, + 0xb2, 0xe6, 0xf0, 0x82, 0x26, 0xfb, 0x4a, 0xba, 0xec, 0xb3, 0x5f, 0x00, 0xd9, 0x08, 0x83, 0x80, + 0xf6, 0x93, 0x03, 0x4a, 0xa3, 0xd4, 0x73, 0x95, 0xd2, 0x6a, 0x63, 0x75, 0x59, 0xac, 0x6c, 0x56, + 0xa0, 0x0a, 0x22, 0x26, 0x50, 0x19, 0xd3, 0x68, 0x84, 0x0d, 0xd7, 0x1c, 0xfc, 0xdb, 0xbe, 0x0e, + 0x0b, 0x46, 0xb3, 0xc2, 0xd6, 0xff, 0x10, 0xae, 0x6f, 0xfa, 0x71, 0x3f, 0xdf, 0x61, 0x17, 0x66, + 0xc7, 0x93, 0x63, 0x37, 0xe5, 0x44, 0x59, 0x64, 0xe6, 0x5f, 0xf6, 0x13, 0xd1, 0xd8, 0x5f, 0xb7, + 0xa0, 0xb2, 0x7d, 0xb4, 0xbb, 0xc1, 0xce, 0x0a, 0x3f, 0xe8, 0x87, 0x23, 0xa6, 0x85, 0xf1, 0x49, + 0xab, 0xf2, 0x54, 0x0e, 0xbb, 0x05, 0x75, 0x54, 0xde, 0x98, 0xc5, 0x2b, 0xf4, 0xa0, 0x14, 0xc0, + 0xac, 0x6d, 0xfa, 0x7a, 0xec, 0x47, 0x68, 0x4e, 0x4b, 0x23, 0xb9, 0x82, 0xc7, 0x4c, 0xbe, 0xc2, + 0xfe, 0xb7, 0xb3, 0x30, 0x2b, 0x0e, 0x5f, 0x7e, 0x90, 0x27, 0xfe, 0x39, 0x4d, 0x0f, 0x72, 0x56, + 0x62, 0x8a, 0x71, 0x44, 0x47, 0x61, 0xa2, 0xf4, 0x37, 0xbe, 0x0d, 0x26, 0x10, 0xbd, 0x09, 0x42, + 0x89, 0xe0, 0xfe, 0x87, 0x32, 0xc7, 0x32, 0x80, 0xe4, 0x16, 0xcc, 0x4a, 0x65, 0xa0, 0xa2, 0x0c, + 0x1d, 0x09, 0x62, 0xab, 0xd1, 0xf7, 0xc6, 0x5e, 0xdf, 0x4f, 0x2e, 0x85, 0x58, 0x50, 0x65, 0xd6, + 0xfe, 0x30, 0xec, 0x7b, 0x43, 0xf7, 0xd8, 0x1b, 0x7a, 0x41, 0x9f, 0x4a, 0x6f, 0x85, 0x01, 0x64, + 0x96, 0xbb, 0x18, 0x96, 0x44, 0xe3, 0xd6, 0x7d, 0x06, 0xca, 0xce, 0xf0, 0x7e, 0x38, 0x1a, 0xf9, + 0xcc, 0xfa, 0xe0, 0xaa, 0x59, 0xd9, 0xd1, 0x20, 0xdc, 0x37, 0x82, 0xa5, 0x0b, 0xbe, 0x82, 0x75, + 0xe9, 0x1b, 0xd1, 0x80, 0xac, 0x95, 0x8c, 0x86, 0x56, 0x76, 0x34, 0x08, 0xdb, 0x8b, 0x49, 0x10, + 0xd3, 0x24, 0x19, 0xd2, 0x81, 0x1a, 0x50, 0x03, 0xd1, 0xf2, 0x15, 0xe4, 0x11, 0x2c, 0x70, 0x1f, + 0x44, 0xec, 0x25, 0x61, 0x7c, 0xe6, 0xc7, 0x6e, 0xcc, 0xcc, 0x27, 0x6e, 0x0b, 0x17, 0x55, 0x91, + 0xc7, 0xb0, 0x9c, 0x01, 0x47, 0xb4, 0x4f, 0xfd, 0x73, 0x3a, 0x40, 0x15, 0xae, 0xec, 0x4c, 0xab, + 0x26, 0x77, 0xa1, 0x11, 0x4c, 0x46, 0xee, 0x64, 0x3c, 0xf0, 0x98, 0x12, 0xd3, 0x46, 0xe5, 0x52, + 0x07, 0x91, 0x0f, 0x41, 0xea, 0x69, 0x42, 0x7b, 0x9c, 0x33, 0x24, 0x1c, 0xa3, 0x5e, 0xc7, 0xc4, + 0x60, 0x84, 0x99, 0xaa, 0xa4, 0x1d, 0x61, 0x77, 0x4a, 0x00, 0xf2, 0x49, 0xe4, 0x9f, 0x7b, 0x09, + 0xed, 0xce, 0x73, 0xa1, 0x2e, 0x8a, 0xec, 0x3b, 0x3f, 0xf0, 0x13, 0xdf, 0x4b, 0xc2, 0xa8, 0x4b, + 0xb0, 0x2e, 0x05, 0xb0, 0x45, 0x44, 0xfa, 0x88, 0x13, 0x2f, 0x99, 0xc4, 0x42, 0x43, 0x5d, 0x40, + 0xe2, 0xca, 0x57, 0x90, 0x8f, 0x60, 0x89, 0x53, 0x04, 0x56, 0x09, 0xdd, 0x1b, 0x55, 0x85, 0x45, + 0x5c, 0x91, 0x29, 0xb5, 0x6c, 0x29, 0x05, 0x89, 0xe4, 0x3e, 0xbc, 0xce, 0x97, 0x72, 0x4a, 0x35, + 0x1b, 0x1f, 0x1b, 0x81, 0xdf, 0x77, 0x05, 0x06, 0x63, 0x91, 0x25, 0x9c, 0x45, 0xbe, 0x82, 0x91, + 0xf8, 0xd0, 0x3f, 0xa1, 0x89, 0x3f, 0xa2, 0xdd, 0x65, 0x4e, 0xe2, 0xb2, 0xcc, 0x18, 0x70, 0x32, + 0xc6, 0x9a, 0x2e, 0x67, 0x78, 0x5e, 0x42, 0x62, 0x1c, 0x86, 0x31, 0x95, 0x9e, 0xa7, 0xee, 0x0d, + 0xc1, 0x5a, 0x3a, 0xd0, 0xfe, 0x23, 0x8b, 0x1f, 0x51, 0x82, 0x9d, 0x63, 0xcd, 0xf8, 0xe2, 0x8c, + 0xec, 0x86, 0xc1, 0xf0, 0x52, 0xf0, 0x36, 0x70, 0xd0, 0x7e, 0x30, 0xbc, 0x64, 0xea, 0xbf, 0x1f, + 0xe8, 0x28, 0x5c, 0x1a, 0x36, 0x25, 0x10, 0x91, 0xde, 0x81, 0xc6, 0x78, 0x72, 0x3c, 0xf4, 0xfb, + 0x1c, 0xa5, 0xcc, 0x5b, 0xe1, 0x20, 0x44, 0x60, 0xd6, 0x27, 0xdf, 0x4f, 0x8e, 0x51, 0x41, 0x8c, + 0x86, 0x80, 0x31, 0x14, 0x7b, 0x1d, 0x16, 0xcd, 0x01, 0x0a, 0xb1, 0xff, 0x00, 0x6a, 0x42, 0x4a, + 0x48, 0x37, 0x44, 0x5b, 0x73, 0x0e, 0x33, 0x63, 0x49, 0xd5, 0xdb, 0x3f, 0x9f, 0x81, 0x05, 0x01, + 0xdd, 0x60, 0xd3, 0x3f, 0x9c, 0x8c, 0x46, 0x5e, 0x54, 0x20, 0x7e, 0xac, 0x37, 0x88, 0x9f, 0x52, + 0x5e, 0xfc, 0xdc, 0x31, 0xac, 0x50, 0x2e, 0xbf, 0x34, 0x08, 0xb9, 0x0f, 0x73, 0x6c, 0xc9, 0xb9, + 0x51, 0xa0, 0xfb, 0x27, 0xb3, 0xe0, 0xbc, 0xc8, 0xac, 0x16, 0x89, 0x4c, 0x5d, 0xdc, 0xcd, 0x64, + 0xc4, 0x9d, 0x0d, 0x4d, 0xbe, 0xbd, 0x42, 0x82, 0xcf, 0x0a, 0x93, 0x4c, 0x83, 0xb1, 0xf1, 0x64, + 0x85, 0x0b, 0x97, 0x64, 0x73, 0x45, 0xa2, 0xc5, 0x1f, 0x51, 0x3c, 0x21, 0x34, 0xec, 0xba, 0x10, + 0x2d, 0xf9, 0x2a, 0xf2, 0x14, 0x80, 0xf7, 0x85, 0x6a, 0x0a, 0xa0, 0x9a, 0xf2, 0x9e, 0xb9, 0x2b, + 0xfa, 0xfa, 0xaf, 0xb0, 0xc2, 0x24, 0xa2, 0xa8, 0xba, 0x68, 0x5f, 0x92, 0x5d, 0x68, 0x87, 0x63, + 0x1a, 0xb8, 0x29, 0x83, 0x37, 0xb0, 0xad, 0x7b, 0x57, 0xb4, 0xb5, 0x23, 0x71, 0x9d, 0xcc, 0xb7, + 0x64, 0x8f, 0xef, 0x00, 0xd5, 0x9a, 0x6b, 0x7e, 0x81, 0xe6, 0xb2, 0x1f, 0xdb, 0x7f, 0xd3, 0x82, + 0x86, 0x36, 0x72, 0x72, 0x1d, 0xe6, 0x37, 0xf6, 0xf7, 0x0f, 0xb6, 0x9c, 0xb5, 0xa3, 0x9d, 0xef, + 0x6d, 0xb9, 0x1b, 0xbb, 0xfb, 0x87, 0x5b, 0x9d, 0x6b, 0x0c, 0xbc, 0xbb, 0xbf, 0xb1, 0xb6, 0xeb, + 0x3e, 0xdd, 0x77, 0x36, 0x24, 0xd8, 0x22, 0x4b, 0x40, 0x9c, 0xad, 0xe7, 0xfb, 0x47, 0x5b, 0x06, + 0xbc, 0x44, 0x3a, 0xd0, 0x5c, 0x77, 0xb6, 0xd6, 0x36, 0xb6, 0x05, 0xa4, 0x4c, 0x16, 0xa1, 0xf3, + 0xf4, 0xc5, 0xde, 0xe6, 0xce, 0xde, 0x33, 0x77, 0x63, 0x6d, 0x6f, 0x63, 0x6b, 0x77, 0x6b, 0xb3, + 0x53, 0x21, 0x2d, 0xa8, 0xaf, 0xad, 0xaf, 0xed, 0x6d, 0xee, 0xef, 0x6d, 0x6d, 0x76, 0xaa, 0xf6, + 0xb7, 0xa0, 0xae, 0x86, 0x4a, 0x1a, 0x30, 0xfb, 0x62, 0xef, 0xd3, 0xbd, 0xfd, 0x97, 0x7b, 0x9d, + 0x6b, 0xa4, 0x0e, 0x55, 0xec, 0xbf, 0x63, 0x11, 0x80, 0x19, 0xde, 0x67, 0xa7, 0x44, 0x6a, 0x50, + 0x59, 0xdf, 0x3f, 0xda, 0xee, 0x94, 0xed, 0xff, 0x6a, 0xc1, 0x75, 0x9c, 0xf3, 0x20, 0xcb, 0xfd, + 0x77, 0xa1, 0xd1, 0x0f, 0xc3, 0x31, 0xb3, 0x7b, 0xd2, 0x93, 0x5d, 0x07, 0x31, 0xce, 0xe6, 0x32, + 0xf1, 0x24, 0x8c, 0xfa, 0x54, 0x30, 0x3f, 0x20, 0xe8, 0x29, 0x83, 0x30, 0xce, 0x16, 0x74, 0xcb, + 0x31, 0x38, 0xef, 0x37, 0x38, 0x8c, 0xa3, 0x2c, 0xc1, 0xcc, 0x71, 0x44, 0xbd, 0xfe, 0x99, 0x60, + 0x7b, 0x51, 0x22, 0x5f, 0x49, 0x0d, 0xf3, 0x3e, 0x23, 0xab, 0x21, 0x1d, 0x20, 0x2b, 0xd4, 0x9c, + 0x39, 0x01, 0xdf, 0x10, 0x60, 0x76, 0x08, 0x78, 0xc7, 0x5e, 0x30, 0x08, 0x03, 0x3a, 0x10, 0x5a, + 0x7f, 0x0a, 0xb0, 0x0f, 0x60, 0x29, 0x3b, 0x3f, 0x21, 0x3c, 0x3e, 0xd2, 0x84, 0x07, 0x57, 0xc2, + 0x7b, 0xd3, 0x69, 0x41, 0x13, 0x24, 0x7f, 0x5e, 0x86, 0x0a, 0xd3, 0xc9, 0xa6, 0xeb, 0x6f, 0xba, + 0x9a, 0x5d, 0xce, 0x45, 0x69, 0xd0, 0xd6, 0xe7, 0x27, 0xb4, 0xf0, 0x33, 0xa5, 0x90, 0xb4, 0x3e, + 0xa2, 0xfd, 0x73, 0xe1, 0x69, 0xd2, 0x20, 0x8c, 0xf3, 0x99, 0x0d, 0x84, 0x5f, 0x0b, 0xce, 0x97, + 0x65, 0x59, 0x87, 0x5f, 0xce, 0xa6, 0x75, 0xf8, 0x5d, 0x17, 0x66, 0xfd, 0xe0, 0x38, 0x9c, 0x04, + 0x03, 0xe4, 0xf4, 0x9a, 0x23, 0x8b, 0x18, 0x17, 0x42, 0x09, 0xc4, 0x8e, 0x0f, 0xce, 0xd7, 0x29, + 0x80, 0xac, 0x42, 0x3d, 0xbe, 0x0c, 0xfa, 0x3a, 0x33, 0x2f, 0x8a, 0x55, 0x62, 0x6b, 0xb0, 0x72, + 0x78, 0x19, 0xf4, 0x91, 0x75, 0x53, 0x34, 0xf2, 0x4d, 0xa8, 0x29, 0xcf, 0x2c, 0x97, 0xca, 0x37, + 0xf4, 0x4f, 0xa4, 0x3b, 0x96, 0x1b, 0xbc, 0x0a, 0xb5, 0xf7, 0x29, 0xb4, 0x8c, 0x2a, 0xdd, 0x4a, + 0x6d, 0x71, 0x2b, 0xf5, 0x9e, 0x6e, 0xa5, 0xa6, 0xc2, 0x5e, 0x7c, 0xa6, 0x5b, 0xad, 0xbf, 0x07, + 0x35, 0x39, 0x34, 0xc6, 0x55, 0x82, 0x23, 0xdc, 0xc3, 0xef, 0xef, 0x6d, 0x74, 0xae, 0x91, 0x39, + 0x68, 0xac, 0x6d, 0x20, 0xa3, 0x22, 0xc0, 0x62, 0x28, 0x07, 0x6b, 0x87, 0x87, 0x0a, 0x52, 0xb2, + 0x09, 0x74, 0xd8, 0x91, 0xc3, 0x46, 0xac, 0x62, 0x2f, 0x1f, 0xc1, 0xbc, 0x06, 0x4b, 0x0d, 0xb9, + 0x31, 0x03, 0x64, 0x0c, 0x39, 0xd4, 0xda, 0x79, 0x8d, 0xbd, 0x0c, 0xd7, 0x59, 0x71, 0xeb, 0x9c, + 0x06, 0xc9, 0xe1, 0xe4, 0x98, 0x87, 0xdc, 0xfc, 0x30, 0xb0, 0xff, 0x9a, 0x05, 0x75, 0x55, 0x73, + 0x05, 0x3d, 0xc9, 0x28, 0x61, 0x09, 0x37, 0xa0, 0xa7, 0x75, 0x81, 0x5f, 0xae, 0xe0, 0xbf, 0x86, + 0xf1, 0x57, 0x57, 0x20, 0x36, 0xd9, 0x83, 0xad, 0x2d, 0xc7, 0xdd, 0xdf, 0xdb, 0xdd, 0xd9, 0x63, + 0x42, 0x89, 0x4d, 0x16, 0x01, 0x4f, 0x9f, 0x22, 0xc4, 0xb2, 0x3b, 0xd0, 0x7e, 0x46, 0x93, 0x9d, + 0xe0, 0x24, 0x94, 0x53, 0xfd, 0x3f, 0x55, 0x98, 0x53, 0xa0, 0xd4, 0x78, 0x3c, 0xa7, 0x51, 0xec, + 0x87, 0x01, 0xaa, 0x7d, 0x75, 0x47, 0x16, 0xd9, 0x79, 0xe2, 0x0f, 0x68, 0x90, 0xf8, 0xc9, 0xa5, + 0x6b, 0x78, 0x9b, 0xb2, 0x60, 0x66, 0xa8, 0x79, 0x43, 0xdf, 0x93, 0xd1, 0x4b, 0x5e, 0x60, 0xd0, + 0x7e, 0x38, 0x0c, 0x23, 0xd4, 0xef, 0xea, 0x0e, 0x2f, 0x90, 0x55, 0x58, 0x64, 0x7a, 0xa5, 0xee, + 0x0b, 0x44, 0x66, 0xe5, 0xae, 0xaf, 0xc2, 0x3a, 0x76, 0x5e, 0x31, 0xb8, 0x50, 0x4a, 0xd4, 0x27, + 0xdc, 0x8c, 0x29, 0xaa, 0x22, 0xdf, 0x80, 0xeb, 0x0c, 0xac, 0x14, 0x19, 0xf5, 0xcd, 0x1c, 0x7e, + 0x53, 0x5c, 0xc9, 0xb8, 0x86, 0xf7, 0xcf, 0x76, 0xbe, 0xca, 0x35, 0x56, 0x05, 0xc8, 0x85, 0x1a, + 0x67, 0xf8, 0x19, 0x9c, 0x0d, 0x35, 0x6a, 0xe1, 0xca, 0x5a, 0x2e, 0x5c, 0xf9, 0x0d, 0xb8, 0x7e, + 0x4c, 0xe3, 0xc4, 0x3d, 0xa3, 0xde, 0x80, 0x46, 0xc8, 0x8d, 0x3c, 0x2a, 0xc9, 0x15, 0xf4, 0xe2, + 0x4a, 0x3c, 0xd9, 0x2f, 0x83, 0x3e, 0x1d, 0xb8, 0x49, 0xe8, 0xa2, 0x06, 0x82, 0x3c, 0x5d, 0x73, + 0xb2, 0x60, 0x13, 0xf3, 0x34, 0xf2, 0xc6, 0x67, 0x42, 0x83, 0xce, 0x82, 0x99, 0xee, 0x93, 0xd0, + 0x38, 0x09, 0x28, 0x8f, 0x09, 0xd5, 0xd0, 0xdf, 0x2f, 0x41, 0xe4, 0x1e, 0xcc, 0x60, 0x83, 0x71, + 0xb7, 0x83, 0x0c, 0xd0, 0x4c, 0x85, 0xa8, 0x1f, 0x38, 0xa2, 0x8e, 0xd9, 0xcb, 0x93, 0xc8, 0x8f, + 0xbb, 0x4d, 0x0c, 0x87, 0xe2, 0xdf, 0xe4, 0x3b, 0x9a, 0x9c, 0x58, 0xc0, 0x6f, 0xe5, 0x61, 0x9c, + 0xa1, 0xbc, 0xdf, 0x8a, 0xc8, 0xf8, 0xa4, 0x52, 0x6b, 0x74, 0x9a, 0xf6, 0xef, 0x40, 0x15, 0x47, + 0x8e, 0x34, 0x89, 0xeb, 0x67, 0x09, 0x9a, 0x44, 0x68, 0x17, 0x66, 0x03, 0x9a, 0x5c, 0x84, 0xd1, + 0x2b, 0x19, 0x7f, 0x17, 0x45, 0xfb, 0x27, 0xe8, 0x54, 0x50, 0xf1, 0xe8, 0x17, 0x68, 0x0d, 0x91, + 0x9b, 0x50, 0xe7, 0x7b, 0x1a, 0x9f, 0x79, 0xc2, 0xcf, 0x51, 0x43, 0xc0, 0xe1, 0x99, 0xc7, 0xce, + 0x47, 0x83, 0x4c, 0xb8, 0xeb, 0xa8, 0x81, 0xb0, 0x6d, 0x4e, 0x25, 0xf7, 0xa0, 0x2d, 0x23, 0xdd, + 0xb1, 0x3b, 0xa4, 0x27, 0x89, 0x74, 0xfc, 0x06, 0x93, 0x11, 0xfa, 0x97, 0x76, 0xe9, 0x49, 0x62, + 0xef, 0xc1, 0xbc, 0x38, 0xb3, 0xf6, 0xc7, 0x54, 0x76, 0xfd, 0xad, 0x22, 0xc5, 0xb6, 0xb1, 0xba, + 0x60, 0x1e, 0x72, 0x3c, 0xb6, 0x6f, 0x62, 0xda, 0x0e, 0x10, 0xfd, 0x0c, 0x14, 0x0d, 0x0a, 0xcd, + 0x52, 0xba, 0xb6, 0xc5, 0x74, 0x0c, 0x18, 0x5b, 0x9f, 0x78, 0xd2, 0xef, 0xcb, 0xfb, 0x09, 0x35, + 0x47, 0x16, 0xed, 0xff, 0x68, 0xc1, 0x02, 0xb6, 0x26, 0x55, 0x73, 0xa1, 0x67, 0x3c, 0xfe, 0x02, + 0xc3, 0x94, 0x81, 0x05, 0xee, 0x4e, 0x5f, 0x84, 0xaa, 0xae, 0x79, 0xf0, 0xc2, 0x17, 0x77, 0x23, + 0x56, 0x72, 0x6e, 0xc4, 0x07, 0xd0, 0x19, 0xd0, 0xa1, 0x8f, 0x77, 0x54, 0xe4, 0x39, 0xce, 0xf5, + 0xf0, 0x1c, 0xdc, 0xfe, 0x3b, 0x16, 0xcc, 0x73, 0x45, 0x01, 0x8d, 0x49, 0xb1, 0x54, 0xff, 0x9f, + 0x34, 0xbc, 0x84, 0x80, 0x12, 0x93, 0x4a, 0x8f, 0x4e, 0x84, 0x72, 0xe4, 0xed, 0x6b, 0x8e, 0x89, + 0x4c, 0x9e, 0xa0, 0x39, 0x11, 0xb8, 0x08, 0x2d, 0xb8, 0xf5, 0x62, 0xee, 0xcb, 0xf6, 0x35, 0x47, + 0x43, 0x5f, 0xaf, 0x31, 0x5b, 0x90, 0xc1, 0xed, 0x67, 0xd0, 0x32, 0x3a, 0x32, 0xdc, 0x9d, 0x4d, + 0xee, 0xee, 0xcc, 0xc5, 0x15, 0x4a, 0x05, 0x71, 0x85, 0x9f, 0x57, 0x80, 0x30, 0xc2, 0xca, 0xec, + 0xdc, 0x5d, 0x33, 0x38, 0x27, 0x2f, 0xc0, 0xa4, 0x20, 0xb2, 0x0a, 0x44, 0x2b, 0xca, 0xa0, 0x61, + 0x59, 0x05, 0x0d, 0x0b, 0x6a, 0x99, 0xd4, 0x17, 0x5a, 0xa5, 0x0a, 0xc8, 0xa1, 0x2b, 0x8b, 0x6f, + 0x53, 0x61, 0x1d, 0xd3, 0x7c, 0x30, 0x3a, 0xc7, 0x8c, 0x6e, 0xe1, 0xfe, 0x91, 0xe5, 0x2c, 0x3d, + 0xcc, 0xbc, 0x91, 0x1e, 0x66, 0x73, 0xf4, 0xa0, 0x39, 0x20, 0x6a, 0xa6, 0x03, 0xe2, 0x1e, 0xb4, + 0x64, 0x10, 0x8e, 0xdf, 0x3f, 0x10, 0xde, 0x1e, 0x03, 0xc8, 0xe8, 0x49, 0xfa, 0x00, 0x94, 0x97, + 0x83, 0x47, 0xd7, 0x73, 0x70, 0x76, 0xb0, 0xa4, 0x8e, 0xe6, 0x06, 0x0e, 0x36, 0x05, 0xa0, 0xcb, + 0x80, 0x51, 0x89, 0x3b, 0x09, 0xc4, 0xe5, 0x17, 0x3a, 0x40, 0x43, 0xa6, 0xe6, 0xe4, 0x2b, 0xf2, + 0xe6, 0x7f, 0xab, 0xc0, 0xfc, 0x27, 0x1f, 0xa5, 0x11, 0xab, 0xf8, 0xcc, 0x1f, 0xe1, 0xd9, 0x9e, + 0xde, 0x1d, 0x79, 0xca, 0xab, 0x0e, 0xcf, 0xfc, 0x91, 0x63, 0xe0, 0xd9, 0xbf, 0xb4, 0xa0, 0xc3, + 0xa8, 0xc2, 0x20, 0xfc, 0x8f, 0x01, 0x79, 0xf4, 0x2d, 0xe9, 0xde, 0xc0, 0x25, 0x8f, 0xa1, 0x8e, + 0x65, 0x66, 0xba, 0x09, 0xaa, 0xef, 0x9a, 0x54, 0x9f, 0x4a, 0xb7, 0xed, 0x6b, 0x4e, 0x8a, 0xcc, + 0xce, 0xb2, 0x6c, 0xc4, 0x90, 0x87, 0xbf, 0xb3, 0x60, 0x8d, 0x3b, 0xb6, 0x01, 0x3e, 0xa5, 0x97, + 0xbb, 0x61, 0x1f, 0xad, 0xa6, 0xdb, 0x00, 0x8c, 0x06, 0x4f, 0xbc, 0x91, 0x2f, 0x5c, 0x1d, 0x55, + 0xa7, 0xfe, 0x8a, 0x5e, 0x3e, 0x45, 0x00, 0x13, 0xe3, 0xac, 0x3a, 0x65, 0x91, 0xaa, 0x53, 0x7b, + 0x45, 0x2f, 0x77, 0x90, 0x3d, 0x5c, 0x68, 0x7d, 0x4a, 0x2f, 0x37, 0x29, 0xd7, 0xeb, 0xc2, 0x88, + 0xd8, 0xd0, 0x8a, 0xbc, 0x0b, 0xa6, 0xb9, 0x19, 0xa1, 0xbe, 0x46, 0xe4, 0x5d, 0x7c, 0x4a, 0x2f, + 0xd7, 0x31, 0xd6, 0xf7, 0x00, 0x66, 0x59, 0xfd, 0x30, 0xec, 0x8b, 0x93, 0x49, 0xde, 0x5e, 0x48, + 0x07, 0xe5, 0xcc, 0xbc, 0xc2, 0xbf, 0xed, 0x7f, 0x6f, 0x41, 0x8b, 0xad, 0x00, 0x8a, 0x3d, 0xb6, + 0x13, 0xf2, 0x12, 0x8c, 0x95, 0x5e, 0x82, 0x59, 0x15, 0x32, 0x83, 0xcb, 0xd0, 0xd2, 0x74, 0x19, + 0x8a, 0xcb, 0xc6, 0x05, 0xe8, 0x87, 0x50, 0xe7, 0xec, 0xc4, 0xd8, 0xb7, 0x6c, 0xec, 0x94, 0x31, + 0x21, 0xa7, 0x86, 0x68, 0x9f, 0xf2, 0x78, 0xbb, 0xe6, 0xac, 0xe2, 0x8b, 0x5c, 0xe7, 0x10, 0x56, + 0x5d, 0x10, 0xba, 0xad, 0x16, 0x85, 0x6e, 0x5f, 0x40, 0x43, 0x23, 0x2c, 0xf2, 0x6d, 0x1e, 0xf4, + 0xe6, 0x83, 0xe7, 0x54, 0x68, 0x12, 0x8e, 0x31, 0x7b, 0x14, 0x98, 0x3a, 0x60, 0x7d, 0x06, 0x2a, + 0x48, 0x92, 0x4f, 0x60, 0x5e, 0x6b, 0x96, 0x5b, 0x88, 0x45, 0x63, 0xb2, 0x8a, 0xc6, 0xf4, 0x87, + 0x16, 0x2c, 0x8a, 0xaf, 0xf1, 0xc2, 0x94, 0xcf, 0x8e, 0xf1, 0xe7, 0xf1, 0x29, 0x3b, 0x48, 0x59, + 0xeb, 0x6e, 0x44, 0x4f, 0xfd, 0x38, 0xa1, 0x32, 0x42, 0x50, 0xc0, 0x21, 0x8c, 0xa4, 0x19, 0xaa, + 0x23, 0x30, 0xc9, 0x13, 0x68, 0xe0, 0xa7, 0xdc, 0x86, 0x15, 0xdb, 0xd2, 0xcd, 0x7f, 0xc8, 0x87, + 0xca, 0x24, 0x79, 0xac, 0x4a, 0xeb, 0x75, 0x98, 0x4d, 0x22, 0xff, 0xf4, 0x94, 0x46, 0xf6, 0x92, + 0x1a, 0x1a, 0xe3, 0x36, 0x7a, 0x98, 0xd0, 0x31, 0x53, 0x8e, 0x18, 0x65, 0x34, 0x04, 0x53, 0xfd, + 0xca, 0x51, 0x81, 0x9e, 0x76, 0xf5, 0x8f, 0x5b, 0xab, 0xe9, 0x4d, 0xbf, 0xfb, 0x30, 0x37, 0x62, + 0x8a, 0x12, 0xd3, 0xe0, 0x8d, 0x88, 0x40, 0x16, 0xcc, 0x14, 0x6f, 0xd4, 0x5b, 0x62, 0x37, 0xf1, + 0x87, 0xae, 0xac, 0x15, 0x97, 0xec, 0x8a, 0xaa, 0xd8, 0xf1, 0x1d, 0x27, 0xde, 0x29, 0x15, 0xda, + 0x31, 0x2f, 0xd8, 0x5d, 0x58, 0x3a, 0x48, 0xb7, 0x45, 0x73, 0x48, 0xd8, 0xff, 0xbc, 0x05, 0xcb, + 0xb9, 0x2a, 0x75, 0x25, 0x58, 0xb8, 0xb9, 0x87, 0xfe, 0xe8, 0x38, 0x54, 0x6e, 0x2a, 0x4b, 0xf7, + 0x80, 0x1b, 0x55, 0xe4, 0x14, 0xae, 0x4b, 0xaa, 0x40, 0x57, 0x91, 0x52, 0xfb, 0x4b, 0xa8, 0x89, + 0x7e, 0x68, 0x4a, 0xac, 0x6c, 0x87, 0x12, 0xae, 0x9f, 0x8a, 0xc5, 0xed, 0x91, 0x33, 0xe8, 0x2a, + 0xf2, 0x13, 0x9a, 0x92, 0x66, 0xc9, 0xb0, 0xbe, 0x3e, 0x78, 0x43, 0x5f, 0x86, 0xff, 0xc2, 0x99, + 0xda, 0x1a, 0xb9, 0x84, 0x3b, 0xb2, 0x0e, 0x55, 0xa1, 0x7c, 0x7f, 0x95, 0xb7, 0x9a, 0x1b, 0x7a, + 0x66, 0xcc, 0x4e, 0xdf, 0xd0, 0x30, 0xf9, 0x31, 0x2c, 0x5d, 0x78, 0x7e, 0x22, 0x87, 0xa5, 0x59, + 0x51, 0x55, 0xec, 0x72, 0xf5, 0x0d, 0x5d, 0xbe, 0xe4, 0x1f, 0x1b, 0xfa, 0xe1, 0x94, 0x16, 0x7b, + 0xbf, 0x2c, 0x41, 0xdb, 0x6c, 0x87, 0x91, 0xa9, 0x90, 0x4a, 0x52, 0xa1, 0x90, 0xf6, 0x67, 0x06, + 0x9c, 0xf7, 0xf6, 0x96, 0x8a, 0xbc, 0xbd, 0xba, 0x7f, 0xb5, 0xfc, 0xa6, 0x70, 0x52, 0xe5, 0xed, + 0xc2, 0x49, 0xd5, 0xc2, 0x70, 0xd2, 0xf4, 0xa8, 0xc3, 0xcc, 0xaf, 0x1a, 0x75, 0x98, 0xbd, 0x32, + 0xea, 0xd0, 0xfb, 0xdf, 0x16, 0x90, 0x3c, 0xf5, 0x92, 0x67, 0xdc, 0xc1, 0x1d, 0xd0, 0xa1, 0x10, + 0x6f, 0x5f, 0x7b, 0x3b, 0x0e, 0x90, 0xbb, 0x25, 0xbf, 0x66, 0xac, 0xa8, 0xdf, 0xcb, 0xd5, 0x6d, + 0x9b, 0x96, 0x53, 0x54, 0x95, 0x09, 0xa9, 0x55, 0xde, 0x1c, 0x52, 0xab, 0xbe, 0x39, 0xa4, 0x36, + 0x93, 0x0d, 0xa9, 0xf5, 0xfe, 0xaa, 0x05, 0x0b, 0x05, 0x64, 0xf6, 0x9b, 0x9b, 0x38, 0x23, 0x0c, + 0x43, 0xfa, 0x94, 0x04, 0x61, 0xe8, 0xc0, 0xde, 0x5f, 0x82, 0x96, 0xc1, 0x5a, 0xbf, 0xb9, 0xfe, + 0xb3, 0xe6, 0x19, 0xa7, 0x6c, 0x03, 0xd6, 0xfb, 0x1f, 0x25, 0x20, 0x79, 0xf6, 0xfe, 0xad, 0x8e, + 0x21, 0xbf, 0x4e, 0xe5, 0x82, 0x75, 0xfa, 0x7f, 0x7a, 0xf2, 0x7c, 0x00, 0xf3, 0x22, 0xd9, 0x40, + 0x0b, 0x69, 0x70, 0x8a, 0xc9, 0x57, 0x30, 0x03, 0xd5, 0x8c, 0x67, 0xd6, 0x8c, 0xcb, 0xd5, 0xda, + 0xf1, 0x9b, 0x09, 0x6b, 0xda, 0x3d, 0xe8, 0x8a, 0x15, 0xca, 0xbb, 0xfe, 0xfe, 0x5e, 0x45, 0xd9, + 0xd8, 0x58, 0x29, 0xf4, 0xe7, 0x6f, 0x40, 0x53, 0x3f, 0x3e, 0xc4, 0x76, 0x64, 0xa2, 0x5a, 0x4c, + 0xcd, 0xd0, 0xb1, 0xc8, 0x26, 0xb4, 0x51, 0x48, 0x0e, 0xd4, 0x77, 0x5c, 0xd3, 0xb8, 0xc2, 0xa1, + 0xbd, 0x7d, 0xcd, 0xc9, 0x7c, 0x43, 0x7e, 0x17, 0xda, 0xa6, 0x9b, 0x4b, 0xe8, 0x84, 0x45, 0x6a, + 0x24, 0xfb, 0xdc, 0x44, 0x26, 0x6b, 0xd0, 0xc9, 0xfa, 0xc9, 0xc4, 0xcd, 0xcf, 0x29, 0x0d, 0xe4, + 0xd0, 0xc9, 0x27, 0xb0, 0x58, 0x74, 0x88, 0xe2, 0xde, 0x4c, 0xb7, 0x22, 0x0a, 0xbf, 0x21, 0x8f, + 0x85, 0xcf, 0xb4, 0x5a, 0x14, 0xe6, 0xd1, 0x96, 0x7c, 0x85, 0xff, 0xa7, 0x79, 0x4f, 0xcf, 0x01, + 0x52, 0x18, 0xe9, 0x40, 0x73, 0xff, 0x60, 0x6b, 0xcf, 0xdd, 0xd8, 0x5e, 0xdb, 0xdb, 0xdb, 0xda, + 0xed, 0x5c, 0x23, 0x04, 0xda, 0x18, 0x9e, 0xd9, 0x54, 0x30, 0x8b, 0xc1, 0x84, 0x47, 0x59, 0xc2, + 0x4a, 0x64, 0x11, 0x3a, 0x3b, 0x7b, 0x19, 0x68, 0x99, 0x74, 0x61, 0xf1, 0x60, 0x8b, 0x47, 0x74, + 0x8c, 0x76, 0x2b, 0x4c, 0xdf, 0x13, 0x83, 0x67, 0xfa, 0x1e, 0x4f, 0x59, 0x59, 0xe7, 0x44, 0x28, + 0x75, 0xa0, 0x7f, 0x60, 0xc1, 0xf5, 0x4c, 0x45, 0x7a, 0x09, 0x99, 0xab, 0x39, 0xa6, 0xee, 0x63, + 0x02, 0x31, 0x24, 0x2e, 0xcd, 0xc3, 0x8c, 0x9c, 0xca, 0x57, 0x30, 0xce, 0xd2, 0xcc, 0xc9, 0x0c, + 0xbf, 0x16, 0x55, 0xd9, 0xcb, 0xea, 0xae, 0x67, 0x66, 0xe0, 0x27, 0x3c, 0x15, 0x46, 0xaf, 0x48, + 0xbd, 0xca, 0xe6, 0x90, 0x65, 0x91, 0xac, 0x66, 0xa8, 0xc1, 0x1c, 0x6f, 0x61, 0x9d, 0xfd, 0xcf, + 0x66, 0x80, 0x7c, 0x77, 0x42, 0xa3, 0x4b, 0xbc, 0x65, 0xac, 0x82, 0x59, 0xcb, 0x59, 0xd7, 0xfa, + 0xcc, 0x78, 0x72, 0xcc, 0x0c, 0x16, 0x61, 0x48, 0x95, 0xde, 0x2a, 0x9b, 0xa0, 0xe8, 0x36, 0x7f, + 0xe5, 0xcd, 0xb7, 0xf9, 0xab, 0x6f, 0xba, 0xcd, 0xff, 0x25, 0x68, 0xf9, 0xa7, 0x41, 0xc8, 0x84, + 0x0e, 0x53, 0x54, 0xe2, 0xee, 0xcc, 0xdd, 0xf2, 0xfd, 0xa6, 0xd3, 0x14, 0xc0, 0x3d, 0x06, 0x23, + 0x4f, 0x52, 0x24, 0x3a, 0x38, 0xc5, 0xec, 0x13, 0x5d, 0x0c, 0x6d, 0x0d, 0x4e, 0xa9, 0xb0, 0x1b, + 0xd1, 0xb5, 0x22, 0x3f, 0x66, 0xf0, 0x98, 0xdc, 0x83, 0x76, 0x1c, 0x4e, 0x98, 0xea, 0x26, 0x97, + 0x81, 0x3b, 0x9c, 0x9b, 0x1c, 0x7a, 0xc0, 0x17, 0x63, 0x05, 0x16, 0x26, 0x31, 0x75, 0x47, 0x7e, + 0x1c, 0xb3, 0xe3, 0xb9, 0x1f, 0x06, 0x49, 0x14, 0x0e, 0x85, 0x03, 0x79, 0x7e, 0x12, 0xd3, 0xe7, + 0xbc, 0x66, 0x83, 0x57, 0x90, 0x6f, 0xa4, 0x43, 0x1a, 0x7b, 0x7e, 0x14, 0x77, 0x01, 0x87, 0x24, + 0x67, 0xca, 0xc6, 0x7d, 0xe0, 0xf9, 0x91, 0x1a, 0x0b, 0x2b, 0xc4, 0x99, 0x2c, 0x83, 0x46, 0x36, + 0xcb, 0xe0, 0x47, 0xc5, 0x59, 0x06, 0x2d, 0x6c, 0xfa, 0x91, 0x68, 0x3a, 0xbf, 0xc5, 0x5f, 0x28, + 0xd9, 0x20, 0x9f, 0x3c, 0xd1, 0xfe, 0x22, 0xc9, 0x13, 0x73, 0x45, 0xc9, 0x13, 0x1f, 0x42, 0x03, + 0xaf, 0xb4, 0xbb, 0x67, 0x7e, 0x90, 0x48, 0x67, 0x78, 0x47, 0xbf, 0xf3, 0xbe, 0xcd, 0xcc, 0x6f, + 0x88, 0xe4, 0x9f, 0x71, 0x3e, 0x8f, 0x61, 0xfe, 0xb7, 0x98, 0xc7, 0x20, 0xae, 0xde, 0xaf, 0x40, + 0x4d, 0xee, 0x13, 0x21, 0x50, 0x39, 0x89, 0xc2, 0x91, 0xf4, 0x0f, 0xb2, 0xbf, 0x49, 0x1b, 0x4a, + 0x49, 0x28, 0x3e, 0x2e, 0x25, 0xa1, 0xfd, 0x07, 0xd0, 0xd0, 0x48, 0x8d, 0xbc, 0xcb, 0xdd, 0x0e, + 0x4c, 0x75, 0x16, 0x76, 0x35, 0x5f, 0xc5, 0xba, 0x80, 0xee, 0x0c, 0xc8, 0x57, 0x61, 0x7e, 0xe0, + 0x47, 0x14, 0x33, 0x8e, 0xdc, 0x88, 0x9e, 0xd3, 0x28, 0x96, 0x2e, 0xdb, 0x8e, 0xaa, 0x70, 0x38, + 0xdc, 0x76, 0x61, 0xc1, 0xd8, 0x5b, 0x25, 0xdd, 0x66, 0x70, 0xdd, 0x64, 0x94, 0xcd, 0xcc, 0x25, + 0x10, 0x75, 0x4c, 0xfb, 0x10, 0xde, 0x66, 0x77, 0x1c, 0x85, 0xc7, 0xd8, 0x89, 0xe5, 0x18, 0x30, + 0xfb, 0xbf, 0x97, 0xa1, 0xbc, 0x1d, 0x8e, 0xf5, 0x0b, 0x1d, 0x56, 0xfe, 0x42, 0x87, 0x30, 0x13, + 0x5c, 0x65, 0x05, 0x08, 0x5d, 0xce, 0x00, 0x92, 0x07, 0xd0, 0x66, 0xa2, 0x22, 0x09, 0x99, 0x59, + 0x74, 0xe1, 0x45, 0x3c, 0xb9, 0xa0, 0x8c, 0xfc, 0x97, 0xa9, 0x21, 0x8b, 0x50, 0x56, 0xda, 0x2d, + 0x22, 0xb0, 0x22, 0xb3, 0xc9, 0xf1, 0x6a, 0xdd, 0xa5, 0x88, 0x21, 0x89, 0x12, 0x93, 0xbc, 0xe6, + 0xf7, 0x5c, 0x1e, 0x71, 0x1d, 0xa5, 0xa8, 0x8a, 0x99, 0x2c, 0x4c, 0xe2, 0x8c, 0x52, 0x0b, 0x40, + 0x95, 0xf5, 0xc0, 0x62, 0xcd, 0x0c, 0x2c, 0xde, 0x85, 0x46, 0x32, 0x3c, 0x77, 0xc7, 0xde, 0xe5, + 0x30, 0xf4, 0x06, 0x82, 0xd3, 0x75, 0x10, 0x79, 0x04, 0x30, 0x1a, 0x8f, 0x05, 0x1b, 0xa2, 0xd7, + 0x32, 0xa5, 0xea, 0xe7, 0x07, 0x07, 0x9c, 0xfa, 0x1c, 0x0d, 0x87, 0x6c, 0x41, 0xbb, 0x30, 0x43, + 0xe8, 0xb6, 0xbc, 0x00, 0x16, 0x8e, 0x57, 0x0a, 0x18, 0x35, 0xf3, 0x51, 0xef, 0x3b, 0x40, 0x7e, + 0xcd, 0x44, 0x9d, 0x97, 0x50, 0x57, 0x23, 0xd4, 0xd3, 0x63, 0xf0, 0x96, 0x67, 0xc3, 0x4c, 0x8f, + 0xc1, 0x4b, 0x9d, 0xef, 0x41, 0x9b, 0x1f, 0x97, 0xea, 0x00, 0xe0, 0x37, 0xf3, 0x32, 0x50, 0xfb, + 0x2f, 0x2c, 0xa8, 0x22, 0xe5, 0x31, 0x2d, 0x95, 0xd7, 0xa9, 0x9b, 0x30, 0x22, 0xf6, 0x94, 0x05, + 0x13, 0xdb, 0xc8, 0x1c, 0x2c, 0x29, 0x32, 0xd0, 0xb3, 0x07, 0xef, 0x42, 0x5d, 0xf5, 0xa4, 0x91, + 0x52, 0x0a, 0x24, 0x77, 0xa0, 0x72, 0x16, 0x8e, 0xa5, 0x21, 0x0f, 0xe9, 0x8a, 0x3a, 0x08, 0x4f, + 0xc7, 0xc3, 0xda, 0xe3, 0x53, 0xe0, 0xc6, 0x52, 0x16, 0x5c, 0x30, 0xd7, 0x99, 0xc2, 0xb9, 0xbe, + 0x80, 0x39, 0x26, 0x1f, 0xb4, 0xd8, 0xf0, 0xf4, 0xc3, 0xf4, 0x2b, 0x4c, 0x03, 0xec, 0x0f, 0x27, + 0x03, 0xaa, 0xbb, 0x53, 0x30, 0xa6, 0x28, 0xe0, 0xd2, 0x90, 0xb0, 0xff, 0x85, 0xc5, 0xe5, 0x0e, + 0x6b, 0x97, 0xdc, 0x87, 0x0a, 0x3b, 0xf7, 0x32, 0x3e, 0x3f, 0x75, 0xf3, 0x96, 0xe1, 0x39, 0x88, + 0xc1, 0x76, 0x11, 0xc3, 0x61, 0x7a, 0xeb, 0x3c, 0x18, 0x96, 0xfa, 0x22, 0xd4, 0xcc, 0x32, 0x26, + 0x7c, 0x06, 0x4a, 0x56, 0xb4, 0xfb, 0x1f, 0x15, 0xe3, 0x2c, 0x95, 0x4a, 0xe2, 0xe0, 0x94, 0x6a, + 0xf7, 0x3e, 0xfe, 0x65, 0x09, 0x5a, 0xc6, 0x98, 0x18, 0xf7, 0xe0, 0xd1, 0xc0, 0x3d, 0xca, 0x62, + 0xe7, 0x75, 0x90, 0xce, 0x79, 0x25, 0x93, 0xf3, 0x54, 0x20, 0xbc, 0xac, 0x07, 0xc2, 0x1f, 0x41, + 0x3d, 0x4d, 0x1d, 0x35, 0x07, 0xc5, 0x7a, 0x94, 0x77, 0x90, 0x53, 0xa4, 0x34, 0x74, 0x5e, 0xd5, + 0x43, 0xe7, 0xdf, 0xd6, 0x42, 0xab, 0x33, 0xd8, 0x8c, 0x5d, 0xb4, 0xaa, 0xbf, 0x9d, 0xbb, 0x18, + 0x4f, 0xa0, 0xa1, 0x0d, 0x5e, 0x0f, 0xa1, 0x5a, 0x46, 0x08, 0x55, 0x65, 0x0b, 0x94, 0xd2, 0x6c, + 0x01, 0xfb, 0x67, 0x25, 0x68, 0x31, 0x5e, 0xf3, 0x83, 0xd3, 0x83, 0x70, 0xe8, 0xf7, 0x2f, 0x91, + 0xc6, 0x25, 0x5b, 0x09, 0x25, 0x4c, 0xf2, 0x9c, 0x09, 0x66, 0x32, 0x51, 0xa5, 0x48, 0x71, 0x01, + 0xae, 0xca, 0x4c, 0xc2, 0x33, 0xf9, 0x78, 0xec, 0xc5, 0x54, 0x4b, 0x6c, 0x75, 0x4c, 0x20, 0x93, + 0xc3, 0x0c, 0x80, 0xb9, 0x1f, 0x23, 0x7f, 0x38, 0xf4, 0x39, 0x2e, 0xf7, 0x51, 0x14, 0x55, 0xb1, + 0x3e, 0x07, 0x7e, 0xec, 0x1d, 0xa7, 0x17, 0x96, 0x54, 0x19, 0xa3, 0x45, 0xde, 0x6b, 0x2d, 0x5a, + 0xc4, 0x93, 0xc5, 0x4c, 0x60, 0x96, 0xaa, 0x66, 0x73, 0x54, 0x65, 0xff, 0x9b, 0x12, 0x34, 0x34, + 0x1a, 0x65, 0xb2, 0xa5, 0xf0, 0x10, 0xd6, 0xa0, 0xe2, 0x8a, 0x62, 0x60, 0x78, 0xbd, 0x34, 0x08, + 0xb9, 0x67, 0xf6, 0x8a, 0x51, 0x66, 0x94, 0x3e, 0x06, 0x3d, 0xdf, 0x82, 0x3a, 0xe3, 0xc3, 0x0f, + 0xd1, 0xc5, 0x26, 0x92, 0xc8, 0x15, 0x40, 0xd6, 0xae, 0x62, 0x6d, 0x35, 0xad, 0x45, 0xc0, 0x95, + 0x97, 0x16, 0x1f, 0x43, 0x53, 0x34, 0x83, 0x7b, 0x8c, 0x93, 0x4e, 0x25, 0x81, 0xb1, 0xff, 0x8e, + 0x81, 0x29, 0xbf, 0x5c, 0x95, 0x5f, 0xd6, 0xde, 0xf4, 0xa5, 0xc4, 0xb4, 0x9f, 0xa9, 0xfb, 0xa0, + 0xcf, 0x22, 0x6f, 0x7c, 0x26, 0xa5, 0xdb, 0x23, 0x58, 0x90, 0x42, 0x6c, 0x12, 0x78, 0x41, 0x10, + 0x4e, 0x82, 0x3e, 0x95, 0x89, 0x05, 0x45, 0x55, 0xf6, 0x40, 0xa5, 0xa1, 0x61, 0x43, 0xe4, 0x01, + 0x54, 0xb9, 0x1a, 0xcf, 0x75, 0x95, 0x62, 0x79, 0xc6, 0x51, 0xc8, 0x7d, 0xa8, 0x72, 0x6d, 0xbe, + 0x34, 0x55, 0x02, 0x71, 0x04, 0x7b, 0x05, 0xe6, 0x50, 0x23, 0xd5, 0x04, 0xf1, 0xcd, 0x22, 0x1d, + 0x66, 0xa6, 0xcf, 0xc3, 0x19, 0x8b, 0x40, 0xf6, 0x38, 0x5f, 0xe9, 0xf7, 0x7a, 0xfe, 0xa2, 0x0c, + 0x0d, 0x0d, 0xcc, 0x84, 0x25, 0x5e, 0xf2, 0x70, 0x07, 0xbe, 0x37, 0xa2, 0x32, 0xb8, 0xd1, 0x72, + 0x32, 0x50, 0x86, 0xe7, 0x9d, 0x9f, 0xba, 0xe1, 0x24, 0x71, 0x07, 0xf4, 0x34, 0xa2, 0x54, 0x28, + 0x57, 0x19, 0x28, 0xc3, 0x63, 0xd4, 0xac, 0xe1, 0xf1, 0xfb, 0x0a, 0x19, 0xa8, 0xbc, 0x3f, 0xc3, + 0xd7, 0xa9, 0x92, 0xde, 0x9f, 0xe1, 0xab, 0x92, 0x15, 0xf3, 0xd5, 0x02, 0x31, 0xff, 0x11, 0x2c, + 0x71, 0x81, 0x2e, 0xa4, 0x87, 0x9b, 0x21, 0xae, 0x29, 0xb5, 0xe4, 0x01, 0x74, 0xd8, 0x98, 0x25, + 0x6b, 0xc4, 0xfe, 0x4f, 0x38, 0x8f, 0x59, 0x4e, 0x0e, 0xce, 0x70, 0x31, 0xf6, 0xaa, 0xe3, 0xf2, + 0x8b, 0xb2, 0x39, 0x38, 0xe2, 0x7a, 0xaf, 0x4d, 0xdc, 0xba, 0xc0, 0xcd, 0xc0, 0xc9, 0x63, 0x58, + 0x1e, 0xd1, 0x81, 0xef, 0x99, 0x4d, 0xb8, 0xa9, 0xc6, 0x31, 0xad, 0x9a, 0xf5, 0xc2, 0x56, 0xe1, + 0x27, 0xe1, 0xe8, 0xd8, 0xe7, 0xa7, 0x2c, 0x8f, 0x12, 0x57, 0x9c, 0x1c, 0xdc, 0x6e, 0x41, 0xe3, + 0x30, 0x09, 0xc7, 0x72, 0xeb, 0xdb, 0xd0, 0xe4, 0x45, 0x91, 0x4a, 0x72, 0x13, 0x6e, 0x20, 0xbd, + 0x1e, 0x85, 0xe3, 0x70, 0x18, 0x9e, 0x5e, 0x1a, 0xee, 0xa9, 0x7f, 0x67, 0xc1, 0x82, 0x51, 0x9b, + 0xfa, 0xa7, 0xd0, 0x97, 0x2e, 0xef, 0xff, 0x73, 0x12, 0x9f, 0xd7, 0xce, 0x28, 0x8e, 0xc8, 0xef, + 0x01, 0xbc, 0x10, 0x29, 0x01, 0x6b, 0x69, 0x52, 0xab, 0xfc, 0x90, 0xd3, 0x7b, 0x37, 0x4f, 0xef, + 0xe2, 0x7b, 0x99, 0xee, 0x2a, 0x9b, 0xf8, 0x5d, 0x71, 0xad, 0x79, 0x20, 0x26, 0x5d, 0x36, 0x6f, + 0x6c, 0xea, 0xee, 0x4c, 0x39, 0x82, 0xbe, 0x02, 0xc6, 0xf6, 0x2f, 0x2c, 0x80, 0x74, 0x74, 0x78, + 0x67, 0x54, 0x9d, 0xb3, 0xfc, 0xdd, 0x18, 0xed, 0x4c, 0x7d, 0x17, 0x9a, 0xea, 0xde, 0x5a, 0x7a, + 0x74, 0x37, 0x24, 0x8c, 0xa9, 0x3a, 0xef, 0xc3, 0xdc, 0xe9, 0x30, 0x3c, 0x46, 0x95, 0x4a, 0x9c, + 0xb3, 0x3c, 0xa1, 0xa6, 0xcd, 0xc1, 0xf2, 0xf4, 0x4c, 0xcf, 0xf9, 0x4a, 0xe1, 0x85, 0x37, 0xfd, + 0xd4, 0x66, 0x67, 0xdd, 0x7c, 0x6e, 0x25, 0xae, 0xe4, 0xf2, 0x5f, 0x29, 0xec, 0x7b, 0x55, 0x74, + 0xe3, 0x09, 0xb4, 0x23, 0x2e, 0x33, 0xa5, 0x40, 0xad, 0x5c, 0x21, 0x50, 0x5b, 0x91, 0x71, 0x32, + 0x7f, 0x05, 0x3a, 0xde, 0xe0, 0x9c, 0x46, 0x89, 0x8f, 0xde, 0x5e, 0xd4, 0xe9, 0xf8, 0x04, 0xe7, + 0x34, 0x38, 0xaa, 0x4e, 0xef, 0xc3, 0x9c, 0x48, 0x6f, 0x52, 0x98, 0xe2, 0x05, 0x85, 0x14, 0xcc, + 0x10, 0xed, 0x7f, 0x2c, 0xaf, 0x0d, 0x99, 0xbb, 0x7b, 0xf5, 0xaa, 0xe8, 0x33, 0x2c, 0x65, 0x66, + 0xf8, 0x25, 0x71, 0x29, 0x62, 0x20, 0xdd, 0xca, 0x65, 0xed, 0x82, 0xfc, 0x40, 0x5c, 0xbb, 0x32, + 0x97, 0xb5, 0xf2, 0x36, 0xcb, 0x6a, 0xff, 0x27, 0x0b, 0x66, 0xb7, 0xc3, 0x31, 0x33, 0xed, 0x51, + 0xc7, 0x61, 0x6c, 0xa2, 0x72, 0x0b, 0x65, 0xf1, 0x0d, 0x89, 0x04, 0x85, 0x5a, 0x49, 0x2b, 0xab, + 0x95, 0x7c, 0x07, 0x6e, 0x62, 0x60, 0x23, 0x0a, 0xc7, 0x61, 0xc4, 0xd8, 0xd5, 0x1b, 0x72, 0x15, + 0x24, 0x0c, 0x92, 0x33, 0x29, 0x4e, 0xaf, 0x42, 0x41, 0x3f, 0xe0, 0x30, 0x39, 0x77, 0xb9, 0xb9, + 0x29, 0xb4, 0x28, 0x2e, 0x65, 0xf3, 0x15, 0xf6, 0xb7, 0xa0, 0xae, 0x1c, 0x18, 0xe4, 0x03, 0xa8, + 0x9f, 0x85, 0x63, 0xe1, 0xe5, 0xb0, 0x8c, 0xa4, 0x0b, 0x31, 0x7b, 0x27, 0x45, 0xb0, 0xff, 0xe7, + 0x2c, 0xcc, 0xee, 0x04, 0xe7, 0xa1, 0xdf, 0xc7, 0xeb, 0x47, 0x23, 0x3a, 0x0a, 0x65, 0xb6, 0x25, + 0xfb, 0x1b, 0x1f, 0x42, 0x49, 0xdf, 0x43, 0xe0, 0x2c, 0xa4, 0x41, 0x98, 0x81, 0x1c, 0xe9, 0xef, + 0x19, 0x88, 0x52, 0x6a, 0xf5, 0x55, 0xb5, 0x7c, 0x55, 0xd6, 0x1a, 0xcf, 0xb3, 0xc7, 0xb5, 0xe3, + 0x59, 0x32, 0x1a, 0x84, 0x2d, 0xbe, 0x48, 0x70, 0xe0, 0x17, 0xc5, 0xf9, 0x4d, 0x46, 0x01, 0x42, + 0xa3, 0x3f, 0xa2, 0x3c, 0x34, 0xa5, 0x54, 0x2f, 0x66, 0xf4, 0xeb, 0x40, 0xa6, 0x9e, 0xf1, 0x0f, + 0x38, 0x0e, 0x3f, 0x0e, 0x74, 0x10, 0xde, 0x46, 0xc9, 0xbc, 0x0e, 0xc2, 0x5f, 0x78, 0xc9, 0x82, + 0xf9, 0x45, 0x33, 0x25, 0x74, 0xf9, 0x3c, 0x81, 0xbf, 0x09, 0x91, 0x85, 0x6b, 0xae, 0x02, 0x9e, + 0x07, 0x26, 0x5d, 0x05, 0x8c, 0x64, 0xbc, 0xe1, 0xf0, 0xd8, 0xeb, 0xbf, 0xe2, 0x96, 0x6d, 0x93, + 0x47, 0x34, 0x0d, 0x20, 0xde, 0xe6, 0x4f, 0xf7, 0x15, 0x2f, 0x02, 0x55, 0x1c, 0x1d, 0x44, 0x56, + 0x4d, 0xff, 0x55, 0x7b, 0x8a, 0xff, 0x4a, 0x47, 0xd2, 0x2f, 0x46, 0xcd, 0xe5, 0x32, 0xb3, 0xbc, + 0xc1, 0x40, 0x5c, 0x98, 0xe9, 0xf0, 0x37, 0x11, 0x14, 0x00, 0x1d, 0x35, 0x7c, 0xc1, 0x38, 0xc2, + 0x3c, 0x22, 0x18, 0x30, 0x72, 0x87, 0xfb, 0x61, 0xc7, 0x9e, 0x3f, 0xc0, 0x8b, 0xa9, 0xdc, 0x16, + 0x56, 0x30, 0xd6, 0x86, 0xfc, 0x1b, 0x0f, 0xce, 0x05, 0x5c, 0x15, 0x03, 0xc6, 0xd6, 0x46, 0x95, + 0x47, 0x69, 0x2a, 0x97, 0x09, 0x24, 0x1f, 0xe2, 0x45, 0x84, 0x84, 0x62, 0xbe, 0x56, 0x7b, 0xf5, + 0xa6, 0x98, 0xb3, 0x20, 0x5b, 0xf9, 0x3f, 0x5e, 0xbc, 0x70, 0x38, 0x26, 0x53, 0xdb, 0x78, 0x2c, + 0x68, 0xc9, 0x50, 0xdb, 0x04, 0x2a, 0xc6, 0x82, 0x38, 0x02, 0x79, 0xac, 0x59, 0x62, 0x5d, 0x44, + 0xbe, 0x95, 0x69, 0x7f, 0x8a, 0x0d, 0xc6, 0x88, 0xd9, 0x8f, 0xd9, 0xf9, 0x13, 0xd3, 0x60, 0x80, + 0x99, 0x5b, 0x35, 0x47, 0x83, 0xfc, 0x66, 0x6d, 0xb4, 0x35, 0x68, 0xea, 0xf3, 0x24, 0x35, 0xa8, + 0xec, 0x1f, 0x6c, 0xed, 0x75, 0xae, 0x91, 0x06, 0xcc, 0x1e, 0x6e, 0x1d, 0x1d, 0xed, 0x6e, 0x6d, + 0x76, 0x2c, 0xd2, 0x84, 0x9a, 0x4a, 0x43, 0x29, 0xb1, 0xd2, 0xda, 0xc6, 0xc6, 0xd6, 0xc1, 0xd1, + 0xd6, 0x66, 0xa7, 0xfc, 0x49, 0xa5, 0x56, 0xea, 0x94, 0x51, 0xc1, 0xd4, 0x96, 0xe1, 0x0d, 0x7e, + 0xb6, 0x3b, 0x00, 0x68, 0xf8, 0xa4, 0x17, 0xab, 0x2a, 0x8e, 0x06, 0x61, 0x82, 0x5c, 0xf9, 0x27, + 0xca, 0xfc, 0x1d, 0x0b, 0x59, 0xc6, 0xcd, 0xc5, 0x07, 0x23, 0xf4, 0xf8, 0x60, 0xd5, 0x31, 0x81, + 0x8c, 0xf0, 0x05, 0x00, 0x13, 0x1c, 0xb8, 0xb8, 0xd0, 0x41, 0x8c, 0x90, 0x22, 0x1a, 0x87, 0xc3, + 0x73, 0xca, 0x51, 0xb8, 0xfa, 0x68, 0xc0, 0x58, 0x5f, 0x42, 0x22, 0x6a, 0x59, 0x55, 0x55, 0xc7, + 0x04, 0x92, 0xaf, 0x49, 0x42, 0xaa, 0x21, 0x21, 0x2d, 0xe7, 0xa9, 0xc2, 0x20, 0xa2, 0xe7, 0x39, + 0x47, 0x59, 0x1d, 0x09, 0xe4, 0xcb, 0xf9, 0xef, 0xde, 0xc2, 0x61, 0x46, 0x56, 0x80, 0x8c, 0xc6, + 0x63, 0xb7, 0xc0, 0x83, 0x55, 0x71, 0x0a, 0x6a, 0x7e, 0x03, 0x0e, 0xb6, 0x04, 0xc8, 0xda, 0x60, + 0x20, 0x86, 0xa9, 0x3f, 0xeb, 0x11, 0xe9, 0xef, 0xc8, 0x48, 0x91, 0x5d, 0x20, 0x16, 0x4b, 0xc5, + 0x62, 0xf1, 0x4a, 0xe1, 0x61, 0xef, 0x40, 0xe3, 0x40, 0x7b, 0x99, 0xc6, 0x66, 0x27, 0x88, 0x7c, + 0x93, 0x86, 0x9f, 0x2d, 0xdc, 0xb1, 0x96, 0x42, 0xb5, 0x21, 0x95, 0xf4, 0x21, 0xd9, 0xff, 0xd0, + 0xe2, 0xc9, 0xfe, 0x6a, 0x0a, 0xbc, 0x7f, 0x1b, 0x9a, 0x2a, 0xb8, 0x94, 0x66, 0x3e, 0x1a, 0x30, + 0x86, 0x83, 0xc3, 0x71, 0xc3, 0x93, 0x93, 0x98, 0xca, 0x54, 0x1e, 0x03, 0x26, 0x95, 0x75, 0xa6, + 0xfe, 0xfb, 0xbc, 0x87, 0x58, 0xa4, 0xf4, 0xe4, 0xe0, 0x8c, 0xd2, 0x85, 0x6f, 0x5c, 0x26, 0x31, + 0xa9, 0xb2, 0x4a, 0xd0, 0xcc, 0xae, 0xf4, 0x03, 0xa8, 0xa9, 0x76, 0xcd, 0x93, 0x58, 0x62, 0xaa, + 0x7a, 0x76, 0xe2, 0xa3, 0x21, 0x6f, 0x0c, 0x9a, 0x33, 0x5c, 0xbe, 0x82, 0xd1, 0xd2, 0x89, 0x1f, + 0x65, 0xd1, 0x39, 0x07, 0x16, 0xd4, 0xd8, 0x2f, 0x61, 0x41, 0x8a, 0x0f, 0xcd, 0x8a, 0x30, 0x37, + 0xd2, 0x7a, 0xd3, 0x29, 0x50, 0xca, 0x9f, 0x02, 0xf6, 0xbf, 0xae, 0xc0, 0xac, 0x7c, 0xf6, 0xc9, + 0x2e, 0x78, 0xa6, 0xa8, 0x6e, 0xbe, 0x70, 0x44, 0xba, 0xc6, 0x3b, 0x16, 0x48, 0x08, 0x42, 0x37, + 0xb8, 0x9f, 0x3d, 0xdd, 0x53, 0x07, 0x6b, 0xe6, 0x84, 0x5f, 0x82, 0xca, 0xd8, 0x4b, 0xce, 0xd0, + 0xff, 0xc6, 0x69, 0x09, 0xcb, 0xd2, 0x85, 0x5f, 0x35, 0x5d, 0xf8, 0x45, 0xef, 0x3a, 0x71, 0x55, + 0x36, 0xff, 0xae, 0xd3, 0x2d, 0xa8, 0x73, 0x6d, 0x24, 0xf5, 0xd2, 0xa7, 0x80, 0x8c, 0xf6, 0x52, + 0xcb, 0x69, 0x2f, 0x6f, 0xaf, 0x57, 0x7c, 0x03, 0x66, 0x78, 0x6e, 0xb3, 0x48, 0xd9, 0x92, 0x47, + 0x8e, 0x58, 0x49, 0xf9, 0x3f, 0xbf, 0xb9, 0xeb, 0x08, 0x5c, 0xfd, 0x75, 0x94, 0x86, 0xf9, 0x3a, + 0x8a, 0x1e, 0x5c, 0x68, 0x66, 0x82, 0x0b, 0x0f, 0xa0, 0xa3, 0x96, 0x0f, 0x1d, 0x70, 0x41, 0x2c, + 0x52, 0x54, 0x72, 0xf0, 0xf4, 0xd8, 0x6c, 0x1b, 0xc7, 0x26, 0x93, 0x70, 0x6b, 0x49, 0x42, 0x47, + 0xe3, 0x44, 0x1c, 0x9b, 0xf6, 0x53, 0x68, 0x19, 0x83, 0x34, 0xd3, 0x1a, 0x5b, 0x50, 0xdf, 0xd9, + 0x73, 0x9f, 0xee, 0xee, 0x3c, 0xdb, 0x3e, 0xea, 0x58, 0xac, 0x78, 0xf8, 0x62, 0x63, 0x63, 0x6b, + 0x6b, 0x13, 0x8f, 0x25, 0x80, 0x99, 0xa7, 0x6b, 0x3b, 0xec, 0x88, 0x2a, 0xdb, 0xff, 0xcb, 0x82, + 0x86, 0xd6, 0x3c, 0xf9, 0xa6, 0x5a, 0x19, 0xfe, 0x80, 0xc6, 0xed, 0xfc, 0x10, 0x56, 0xa4, 0xa0, + 0xd6, 0x96, 0x46, 0x3d, 0x65, 0x55, 0x9a, 0xfa, 0x94, 0x15, 0xdb, 0x1e, 0x8f, 0xb7, 0xa0, 0xd6, + 0x81, 0x5b, 0x57, 0x59, 0x30, 0xbf, 0xae, 0x96, 0x9e, 0x2e, 0x0c, 0x93, 0x7b, 0x14, 0xb3, 0x60, + 0xfb, 0x23, 0x80, 0x74, 0x34, 0xe6, 0xb4, 0xaf, 0x99, 0xd3, 0xb6, 0xb4, 0x69, 0x97, 0xec, 0x4d, + 0x2e, 0x30, 0xc4, 0x12, 0xaa, 0x30, 0xf8, 0xd7, 0x80, 0x48, 0x07, 0x16, 0x5e, 0x0b, 0x1d, 0x0f, + 0x69, 0x22, 0x53, 0x3b, 0xe7, 0x45, 0xcd, 0x8e, 0xaa, 0x90, 0x69, 0xd7, 0x69, 0x2b, 0xa9, 0xdc, + 0x11, 0x14, 0x97, 0x95, 0x3b, 0x02, 0xd5, 0x51, 0xf5, 0x76, 0x0f, 0xba, 0x9b, 0x94, 0xb5, 0xb6, + 0x36, 0x1c, 0x66, 0x86, 0x63, 0xdf, 0x84, 0x1b, 0x05, 0x75, 0xc2, 0x3d, 0xf1, 0x5d, 0xb8, 0xbe, + 0xc6, 0xb3, 0x38, 0x7f, 0x53, 0x09, 0x23, 0x76, 0x17, 0x96, 0xb2, 0x4d, 0x8a, 0xce, 0x9e, 0xc2, + 0xfc, 0x26, 0x3d, 0x9e, 0x9c, 0xee, 0xd2, 0xf3, 0xb4, 0x23, 0x02, 0x95, 0xf8, 0x2c, 0xbc, 0x10, + 0xeb, 0x83, 0x7f, 0x93, 0xdb, 0x00, 0x43, 0x86, 0xe3, 0xc6, 0x63, 0xda, 0x97, 0x0f, 0x94, 0x20, + 0xe4, 0x70, 0x4c, 0xfb, 0xf6, 0x47, 0x40, 0xf4, 0x76, 0xc4, 0x7a, 0x31, 0x93, 0x61, 0x72, 0xec, + 0xc6, 0x97, 0x71, 0x42, 0x47, 0xf2, 0xe5, 0x15, 0x1d, 0x64, 0xbf, 0x0f, 0xcd, 0x03, 0xef, 0xd2, + 0xa1, 0x9f, 0x89, 0xa7, 0xd3, 0x96, 0x61, 0x76, 0xec, 0x5d, 0x32, 0x7e, 0x56, 0x21, 0x16, 0xac, + 0xb6, 0xff, 0xa4, 0x02, 0x33, 0x1c, 0x93, 0xb5, 0x3a, 0xa0, 0x71, 0xe2, 0x07, 0xc8, 0x63, 0xb2, + 0x55, 0x0d, 0x94, 0x13, 0x98, 0xa5, 0x02, 0x81, 0x29, 0x5c, 0x6d, 0xf2, 0xa1, 0x07, 0x41, 0xb2, + 0x06, 0x8c, 0x89, 0xad, 0x34, 0xfd, 0x8c, 0x53, 0x6a, 0x0a, 0xc8, 0xc4, 0x30, 0x53, 0xc3, 0x84, + 0x8f, 0x4f, 0x9e, 0x05, 0x42, 0x26, 0xea, 0xa0, 0x42, 0xf3, 0x67, 0x56, 0xe6, 0xd9, 0x64, 0xcc, + 0x9f, 0x9c, 0x99, 0x53, 0x7b, 0x0b, 0x33, 0x87, 0xfb, 0xdf, 0xae, 0x32, 0x73, 0xe0, 0x6d, 0xcc, + 0x9c, 0xb7, 0x89, 0x1d, 0xf6, 0xa0, 0x86, 0x67, 0xba, 0x26, 0x22, 0x65, 0x99, 0xfc, 0x8e, 0x66, + 0x03, 0xf0, 0x7b, 0x0c, 0x37, 0x53, 0x7e, 0x71, 0xe8, 0x67, 0xbf, 0x9d, 0x30, 0xcc, 0x0f, 0x61, + 0x56, 0x40, 0x19, 0x65, 0x07, 0xde, 0x48, 0x3e, 0xb0, 0x83, 0x7f, 0xb3, 0xa5, 0xc3, 0x77, 0x3e, + 0x3e, 0x9b, 0xf8, 0x11, 0x1d, 0xc8, 0x5c, 0x6d, 0x0d, 0x84, 0x97, 0xcb, 0x63, 0xf7, 0x55, 0x10, + 0x5e, 0x04, 0x22, 0x5b, 0x5b, 0x95, 0x6d, 0x02, 0x1d, 0x7c, 0x68, 0x6b, 0x1c, 0x46, 0xf2, 0xcd, + 0x24, 0xfb, 0x0f, 0x2d, 0xe8, 0x08, 0x46, 0x53, 0x75, 0xf2, 0xc2, 0xc0, 0x55, 0x6f, 0x2d, 0xdc, + 0x83, 0x16, 0xfa, 0x3a, 0xd4, 0x91, 0x23, 0x82, 0xef, 0x06, 0x90, 0x8d, 0x57, 0xde, 0xee, 0x1c, + 0xf9, 0x43, 0x41, 0xb7, 0x3a, 0x48, 0x9e, 0x5a, 0x91, 0x27, 0x92, 0xbc, 0x2c, 0x47, 0x95, 0xed, + 0x5f, 0x5a, 0x30, 0xaf, 0x0d, 0x58, 0x30, 0xea, 0x13, 0x68, 0xaa, 0xf7, 0xec, 0xa8, 0x52, 0xaa, + 0x96, 0x4d, 0xc9, 0x92, 0x7e, 0x66, 0x20, 0x23, 0xbd, 0x7b, 0x97, 0x38, 0xc0, 0x78, 0x32, 0x12, + 0xda, 0x8c, 0x0e, 0x62, 0x74, 0x74, 0x41, 0xe9, 0x2b, 0x85, 0xc2, 0xf5, 0x29, 0x03, 0x86, 0x31, + 0xa2, 0x30, 0x48, 0xce, 0x14, 0x52, 0x45, 0xc4, 0x88, 0x74, 0xa0, 0xfd, 0x5f, 0x4a, 0xb0, 0xc0, + 0x9d, 0x6e, 0xc2, 0xd9, 0xa9, 0x9e, 0x14, 0x9a, 0xe1, 0xfe, 0x47, 0x2e, 0xb4, 0xb6, 0xaf, 0x39, + 0xa2, 0x4c, 0xbe, 0xf9, 0x96, 0x8e, 0x42, 0x95, 0x4d, 0x36, 0x65, 0x2f, 0xca, 0x45, 0x7b, 0x71, + 0xc5, 0x4a, 0x17, 0x85, 0xeb, 0xaa, 0xc5, 0xe1, 0xba, 0xb7, 0x0b, 0x8f, 0xe5, 0x52, 0xae, 0x66, + 0x05, 0x96, 0x91, 0x72, 0xb5, 0x0a, 0xcb, 0x06, 0x00, 0xe5, 0xb5, 0x7f, 0xe2, 0x53, 0x99, 0xff, + 0x3e, 0x1f, 0xd3, 0xc4, 0x35, 0x50, 0xd6, 0x67, 0xa1, 0x1a, 0xf7, 0xc3, 0x31, 0xb5, 0x97, 0x60, + 0xd1, 0x5c, 0x5c, 0x71, 0x4a, 0xfc, 0xc2, 0x82, 0xee, 0x53, 0x7e, 0xe9, 0xc2, 0x0f, 0x4e, 0xb7, + 0xfd, 0x38, 0x09, 0x23, 0xf5, 0xf2, 0xdb, 0x1d, 0x80, 0x38, 0xf1, 0x22, 0x61, 0x67, 0x72, 0x65, + 0x57, 0x83, 0xb0, 0x35, 0xa2, 0xc1, 0x80, 0xd7, 0x72, 0xda, 0x50, 0xe5, 0x9c, 0x31, 0x21, 0x5c, + 0x92, 0x86, 0x4a, 0xfe, 0x1e, 0xcf, 0x04, 0x65, 0x8b, 0x41, 0xcf, 0xf1, 0xe8, 0xe5, 0x7e, 0xbe, + 0x0c, 0xd4, 0xfe, 0xa3, 0x12, 0xcc, 0xa5, 0x83, 0xe4, 0x99, 0xe5, 0x86, 0x00, 0x17, 0x7a, 0x78, + 0x2a, 0xc0, 0x45, 0xf8, 0xd0, 0xf5, 0x99, 0x62, 0xae, 0x79, 0x25, 0x35, 0x28, 0xb9, 0x07, 0x0d, + 0x59, 0x0a, 0x27, 0x89, 0xf6, 0x04, 0x93, 0x0e, 0xe6, 0x29, 0x26, 0xcc, 0x34, 0x10, 0x66, 0x8e, + 0x28, 0xe1, 0x7b, 0x08, 0xa3, 0x04, 0xbf, 0xe4, 0x7b, 0x2a, 0x8b, 0x4c, 0xa0, 0x31, 0x9d, 0x9a, + 0xef, 0x21, 0xea, 0xd3, 0xba, 0xae, 0x59, 0x53, 0x4f, 0x57, 0x2a, 0x9e, 0xe7, 0x2d, 0xa6, 0xc9, + 0x76, 0x15, 0x47, 0x07, 0x49, 0xaf, 0x50, 0x38, 0x31, 0xcc, 0x5f, 0x03, 0x66, 0xff, 0x2d, 0x0b, + 0x6e, 0x14, 0x6c, 0xa3, 0x90, 0x01, 0x9b, 0x30, 0x7f, 0xa2, 0x2a, 0xe5, 0x52, 0x73, 0x41, 0xb0, + 0x24, 0x85, 0xab, 0xb9, 0xbc, 0x4e, 0xfe, 0x03, 0x65, 0x6e, 0xf1, 0xcd, 0x33, 0x72, 0x2b, 0xf3, + 0x15, 0xf6, 0x01, 0xf4, 0xb6, 0x5e, 0x33, 0x91, 0xb2, 0xa1, 0xbf, 0x5f, 0x2e, 0x29, 0x6b, 0x35, + 0x27, 0x32, 0xdf, 0xec, 0x8c, 0x3e, 0xe1, 0x19, 0x63, 0xaa, 0x2d, 0xf2, 0xf5, 0xb7, 0x6d, 0x44, + 0xe7, 0xfe, 0xbb, 0x62, 0xd7, 0xf9, 0x03, 0xec, 0x32, 0xc3, 0x53, 0x03, 0xd9, 0xe7, 0x30, 0xf7, + 0x7c, 0x32, 0x4c, 0xfc, 0xf4, 0x31, 0x76, 0xf2, 0x4d, 0xf1, 0x11, 0x36, 0x21, 0x97, 0xae, 0xb0, + 0x2b, 0x1d, 0x8f, 0xad, 0xd8, 0x88, 0xb5, 0xe4, 0xe6, 0x7b, 0xcc, 0x57, 0xd8, 0x37, 0x60, 0x39, + 0xed, 0x92, 0xaf, 0x9d, 0x3c, 0x76, 0xfe, 0xd8, 0xe2, 0x37, 0xab, 0xcd, 0xb7, 0xe1, 0xc9, 0x33, + 0x58, 0x88, 0xfd, 0xe0, 0x74, 0x48, 0xf5, 0x76, 0x62, 0xb1, 0x12, 0xd7, 0xcd, 0xe1, 0x89, 0xf7, + 0xe3, 0x9d, 0xa2, 0x2f, 0x18, 0x81, 0x14, 0x0f, 0x34, 0x25, 0x90, 0xcc, 0x92, 0x14, 0x4d, 0xe0, + 0x13, 0x68, 0x9b, 0x9d, 0x91, 0xc7, 0x22, 0x75, 0x32, 0x1d, 0x59, 0x39, 0x93, 0x01, 0x97, 0x52, + 0x86, 0x81, 0x69, 0xff, 0xcc, 0x82, 0xae, 0x43, 0x19, 0x19, 0x53, 0xad, 0x53, 0x41, 0x3d, 0x4f, + 0x72, 0xcd, 0x4e, 0x9f, 0xb0, 0x4a, 0xc9, 0x94, 0x73, 0x5d, 0x99, 0xba, 0x29, 0xdb, 0xd7, 0x0a, + 0x66, 0xb5, 0x5e, 0x83, 0x19, 0x31, 0xbf, 0x65, 0xb8, 0x2e, 0x86, 0x24, 0x87, 0x93, 0x86, 0x1d, + 0x8d, 0x4e, 0x8d, 0xb0, 0x63, 0x0f, 0xba, 0xfc, 0x81, 0x3f, 0x7d, 0x1e, 0xe2, 0xc3, 0x4d, 0x20, + 0xcf, 0xbd, 0xbe, 0x17, 0x85, 0x61, 0x70, 0x40, 0x23, 0x71, 0x49, 0x15, 0xb5, 0x4f, 0x8c, 0xca, + 0x49, 0x45, 0x99, 0x97, 0xe4, 0x9b, 0x74, 0x61, 0x20, 0xdf, 0xfe, 0xe3, 0x25, 0xdb, 0x81, 0x85, + 0x75, 0xef, 0x15, 0x95, 0x2d, 0xa5, 0xab, 0xd4, 0x18, 0xab, 0x46, 0xe5, 0xda, 0xcb, 0x9c, 0xeb, + 0x7c, 0xb7, 0x8e, 0x8e, 0x6d, 0xaf, 0xc2, 0xa2, 0xd9, 0xa6, 0x10, 0x25, 0x3d, 0xa8, 0x8d, 0x04, + 0x4c, 0x8c, 0x4e, 0x95, 0x1f, 0x7c, 0x0e, 0x0d, 0xed, 0xd1, 0x46, 0xb2, 0x0c, 0x0b, 0x2f, 0x77, + 0x8e, 0xf6, 0xb6, 0x0e, 0x0f, 0xdd, 0x83, 0x17, 0xeb, 0x9f, 0x6e, 0x7d, 0xdf, 0xdd, 0x5e, 0x3b, + 0xdc, 0xee, 0x5c, 0x23, 0x4b, 0x40, 0xf6, 0xb6, 0x0e, 0x8f, 0xb6, 0x36, 0x0d, 0xb8, 0x45, 0xee, + 0x40, 0xef, 0xc5, 0xde, 0x8b, 0xc3, 0xad, 0x4d, 0xb7, 0xe8, 0xbb, 0x12, 0xb9, 0x0d, 0x37, 0x44, + 0x7d, 0xc1, 0xe7, 0xe5, 0x07, 0x4f, 0xa0, 0x93, 0x75, 0x4b, 0x1a, 0xee, 0xdc, 0xab, 0xfc, 0xbe, + 0x0f, 0xfe, 0x51, 0x19, 0x20, 0xbd, 0x9c, 0x4a, 0xba, 0xb0, 0xb8, 0xb9, 0x76, 0xb4, 0xb6, 0xbb, + 0xcf, 0x06, 0xe1, 0xec, 0x1f, 0x6d, 0x6d, 0x1c, 0xb9, 0xce, 0xd6, 0x77, 0x3b, 0xd7, 0x0a, 0x6b, + 0xf6, 0x0f, 0x98, 0xc9, 0xbe, 0x0c, 0x0b, 0x3b, 0x7b, 0x3b, 0x47, 0x3b, 0x6b, 0xbb, 0xae, 0xb3, + 0xff, 0x62, 0x67, 0xef, 0x19, 0x7f, 0x77, 0xa5, 0x4c, 0xde, 0x81, 0x9b, 0x2f, 0x0e, 0x9e, 0x3a, + 0xfb, 0x7b, 0x47, 0xee, 0xe1, 0xf6, 0x8b, 0xa3, 0x4d, 0x7c, 0xb5, 0x65, 0xc3, 0xd9, 0x39, 0xe0, + 0x6d, 0x56, 0xae, 0x42, 0x60, 0x4d, 0x57, 0xd9, 0x8a, 0x3d, 0xdb, 0x3f, 0x3c, 0xdc, 0x39, 0x70, + 0xbf, 0xfb, 0x62, 0xcb, 0xd9, 0xd9, 0x3a, 0xc4, 0x0f, 0x67, 0x0a, 0xe0, 0x0c, 0x7f, 0x96, 0xcc, + 0x43, 0xeb, 0x68, 0xf7, 0x7b, 0xee, 0xfe, 0xde, 0xce, 0xfe, 0x1e, 0xa2, 0xd6, 0x4c, 0x10, 0xc3, + 0xaa, 0x93, 0x1e, 0x2c, 0x6d, 0xfd, 0xfe, 0x91, 0x5b, 0xd0, 0x32, 0x4c, 0xa9, 0x63, 0xdf, 0x35, + 0xc8, 0x0d, 0xb8, 0x7e, 0x78, 0xb4, 0x76, 0xb4, 0xb3, 0xe1, 0x8a, 0x17, 0x9f, 0xd8, 0x26, 0xb0, + 0xcf, 0x9a, 0xc5, 0x55, 0xec, 0xab, 0x16, 0x59, 0x84, 0xce, 0xc1, 0xda, 0xf7, 0x9f, 0x6f, 0xed, + 0x1d, 0xb9, 0x6b, 0x9b, 0x9b, 0x0e, 0x7e, 0xd0, 0xce, 0x41, 0x19, 0xee, 0x1c, 0xdb, 0xa8, 0xe7, + 0x07, 0x07, 0x88, 0xd2, 0x91, 0x05, 0x56, 0x33, 0xbf, 0xfa, 0xb3, 0x32, 0xb4, 0x79, 0xb6, 0x00, + 0xff, 0x15, 0x0c, 0x1a, 0x91, 0xe7, 0x30, 0x2b, 0x7e, 0x4e, 0x85, 0x5c, 0x57, 0x8f, 0x6d, 0xe8, + 0x3f, 0xe0, 0xd2, 0x5b, 0xca, 0x82, 0x05, 0xfb, 0x2d, 0xfc, 0x95, 0xff, 0xf0, 0xdf, 0x7e, 0x5e, + 0x6a, 0x91, 0xc6, 0xc3, 0xf3, 0x0f, 0x1f, 0x9e, 0xd2, 0x20, 0x66, 0x6d, 0xfc, 0xff, 0x00, 0xe9, + 0x8f, 0x84, 0x90, 0xae, 0xf2, 0x3e, 0x66, 0x7e, 0x41, 0xa5, 0x77, 0xa3, 0xa0, 0x46, 0xb4, 0x7b, + 0x03, 0xdb, 0x5d, 0xb0, 0xdb, 0xac, 0x5d, 0x3f, 0xf0, 0x13, 0xfe, 0x83, 0x21, 0x1f, 0x5b, 0x0f, + 0xc8, 0x00, 0x9a, 0xfa, 0xcf, 0x77, 0x10, 0x19, 0xed, 0x2f, 0xf8, 0x01, 0x92, 0xde, 0xcd, 0xc2, + 0x3a, 0x29, 0x73, 0xb0, 0x8f, 0xeb, 0x76, 0x87, 0xf5, 0x31, 0x41, 0x8c, 0xb4, 0x97, 0x21, 0x97, + 0xc4, 0xe9, 0xaf, 0x74, 0x90, 0x5b, 0x9a, 0x70, 0xcc, 0xfd, 0x46, 0x48, 0xef, 0xf6, 0x94, 0x5a, + 0xd1, 0xd7, 0x6d, 0xec, 0x6b, 0xd9, 0x26, 0xac, 0xaf, 0x3e, 0xe2, 0xc8, 0xdf, 0x08, 0xf9, 0xd8, + 0x7a, 0xb0, 0xfa, 0x67, 0xf7, 0xa1, 0xae, 0x6e, 0x02, 0x91, 0x1f, 0x43, 0xcb, 0x48, 0xe7, 0x20, + 0x72, 0x1a, 0x45, 0xd9, 0x1f, 0xbd, 0x5b, 0xc5, 0x95, 0xa2, 0xe3, 0x3b, 0xd8, 0x71, 0x97, 0x2c, + 0xb1, 0x8e, 0x45, 0x3e, 0xc4, 0x43, 0x4c, 0x7f, 0xe2, 0x4f, 0x97, 0xbc, 0xd2, 0x4e, 0x1c, 0xde, + 0xd9, 0xad, 0xec, 0x21, 0x60, 0xf4, 0x76, 0x7b, 0x4a, 0xad, 0xe8, 0xee, 0x16, 0x76, 0xb7, 0x44, + 0x16, 0xf5, 0xee, 0xd4, 0xed, 0x1c, 0x8a, 0xcf, 0x07, 0xe9, 0x3f, 0x60, 0x41, 0x6e, 0xa7, 0x8f, + 0xbb, 0x14, 0xfc, 0xb0, 0x85, 0x22, 0x91, 0xfc, 0xaf, 0x5b, 0xd8, 0x5d, 0xec, 0x8a, 0x10, 0xdc, + 0x3e, 0xfd, 0xf7, 0x2b, 0xc8, 0x31, 0x34, 0xb4, 0x77, 0x9e, 0xc9, 0x8d, 0xa9, 0x6f, 0x52, 0xf7, + 0x7a, 0x45, 0x55, 0x45, 0x53, 0xd1, 0xdb, 0x7f, 0xc8, 0x14, 0xd2, 0x1f, 0x42, 0x5d, 0xbd, 0x1c, + 0x4c, 0x96, 0xb5, 0x97, 0x9c, 0xf5, 0x97, 0x8e, 0x7b, 0xdd, 0x7c, 0x45, 0x11, 0xf1, 0xe9, 0xad, + 0x33, 0xe2, 0x7b, 0x09, 0x0d, 0xed, 0x75, 0x60, 0x35, 0x81, 0xfc, 0x0b, 0xc4, 0x6a, 0x02, 0x05, + 0x8f, 0x09, 0xdb, 0xf3, 0xd8, 0x45, 0x83, 0xd4, 0x91, 0xbe, 0x93, 0xd7, 0x61, 0x4c, 0x76, 0xe1, + 0xba, 0x38, 0x59, 0x8f, 0xe9, 0x17, 0xd9, 0x86, 0x82, 0xdf, 0x0c, 0x79, 0x64, 0x91, 0x27, 0x50, + 0x93, 0x8f, 0x40, 0x93, 0xa5, 0xe2, 0xc7, 0xac, 0x7b, 0xcb, 0x39, 0xb8, 0x38, 0x06, 0xbf, 0x0f, + 0x90, 0x3e, 0x45, 0xac, 0x84, 0x44, 0xee, 0x69, 0x63, 0x45, 0x01, 0xf9, 0x77, 0x8b, 0xed, 0x25, + 0x9c, 0x60, 0x87, 0xa0, 0x90, 0x08, 0xe8, 0x85, 0x7c, 0xbb, 0xe2, 0x47, 0xd0, 0xd0, 0x5e, 0x23, + 0x56, 0xcb, 0x97, 0x7f, 0xc9, 0x58, 0x2d, 0x5f, 0xc1, 0xe3, 0xc5, 0x76, 0x0f, 0x5b, 0x5f, 0xb4, + 0xe7, 0x58, 0xeb, 0xb1, 0x7f, 0x1a, 0x8c, 0x38, 0x02, 0xdb, 0xa0, 0x33, 0x68, 0x19, 0x4f, 0x0e, + 0x2b, 0x0e, 0x2d, 0x7a, 0xd0, 0x58, 0x71, 0x68, 0xe1, 0x2b, 0xc5, 0x92, 0xce, 0xec, 0x79, 0xd6, + 0xcf, 0x39, 0xa2, 0x68, 0x3d, 0xfd, 0x00, 0x1a, 0xda, 0xf3, 0xc1, 0x6a, 0x2e, 0xf9, 0x97, 0x8a, + 0xd5, 0x5c, 0x8a, 0x5e, 0x1b, 0x5e, 0xc4, 0x3e, 0xda, 0x36, 0x92, 0x02, 0xbe, 0x46, 0xc5, 0xda, + 0xfe, 0x31, 0xb4, 0xcd, 0x07, 0x85, 0x15, 0xef, 0x17, 0x3e, 0x4d, 0xac, 0x78, 0x7f, 0xca, 0x2b, + 0xc4, 0x82, 0xa4, 0x1f, 0x2c, 0xa8, 0x4e, 0x1e, 0xfe, 0x54, 0x5c, 0x6c, 0xfe, 0x9c, 0x7c, 0x97, + 0x09, 0x38, 0xf1, 0x4a, 0x1a, 0x59, 0xd6, 0xa8, 0x56, 0x7f, 0x4b, 0x4d, 0xf1, 0x4b, 0xee, 0x41, + 0x35, 0x93, 0x98, 0xf9, 0x7b, 0x5a, 0xcf, 0x60, 0x41, 0x11, 0xb3, 0x7a, 0xf5, 0x2c, 0x56, 0x73, + 0x28, 0x7c, 0x5c, 0xad, 0xd7, 0xc9, 0xd6, 0x3e, 0xb2, 0xf8, 0xf1, 0x87, 0x6f, 0x4b, 0x69, 0xc7, + 0x9f, 0xfe, 0xf0, 0x99, 0x76, 0xfc, 0x19, 0x4f, 0x50, 0x65, 0x8f, 0xbf, 0xc4, 0x67, 0x6d, 0x04, + 0x30, 0x97, 0xc9, 0x90, 0x55, 0xec, 0x55, 0xfc, 0x88, 0x41, 0xef, 0xce, 0xd5, 0x89, 0xb5, 0xa6, + 0x28, 0x92, 0xd2, 0xf4, 0xa1, 0x7c, 0x21, 0xe5, 0x0f, 0xa0, 0xa9, 0xbf, 0x83, 0x4a, 0x74, 0x99, + 0x90, 0xed, 0xe9, 0x66, 0x61, 0x9d, 0x49, 0x25, 0xa4, 0xa9, 0x77, 0x43, 0xbe, 0x07, 0x4b, 0x6a, + 0x99, 0xf5, 0x44, 0xc9, 0x98, 0xbc, 0x53, 0x90, 0x3e, 0x69, 0x2c, 0xf6, 0x8d, 0xa9, 0xf9, 0x95, + 0x8f, 0x2c, 0x46, 0x7d, 0xe6, 0x1b, 0x8c, 0xe9, 0xc9, 0x53, 0xf4, 0xf4, 0x64, 0x7a, 0xf2, 0x14, + 0x3e, 0xdc, 0x28, 0xa9, 0x8f, 0x2c, 0x18, 0x6b, 0xc4, 0xef, 0x6f, 0x91, 0x1f, 0xc0, 0x9c, 0x96, + 0xd6, 0x7e, 0x78, 0x19, 0xf4, 0x15, 0x27, 0xe5, 0x9f, 0x30, 0xea, 0x15, 0x99, 0xa5, 0xf6, 0x32, + 0xb6, 0x3f, 0x6f, 0x1b, 0x8b, 0xc3, 0xb8, 0x68, 0x03, 0x1a, 0x7a, 0xca, 0xfc, 0x15, 0xed, 0x2e, + 0x6b, 0x55, 0xfa, 0xfb, 0x38, 0x8f, 0x2c, 0xb2, 0x0b, 0x9d, 0xec, 0x53, 0x1e, 0x4a, 0xa6, 0x14, + 0x3d, 0x3f, 0xd2, 0xcb, 0x54, 0x1a, 0x0f, 0x80, 0x90, 0x03, 0x7e, 0x2b, 0x58, 0xfd, 0xb8, 0x46, + 0x18, 0x65, 0x4f, 0x75, 0xf3, 0x47, 0x37, 0x54, 0x6b, 0x45, 0x3f, 0xb7, 0x72, 0xdf, 0x7a, 0x64, + 0x91, 0xbf, 0x6b, 0x41, 0xd3, 0x48, 0x90, 0x37, 0xee, 0x58, 0x66, 0xe6, 0xd9, 0xd5, 0xeb, 0xf4, + 0x89, 0xda, 0x0e, 0x2e, 0xe2, 0xee, 0x83, 0x4f, 0x8c, 0x4d, 0xfa, 0xa9, 0xe1, 0xe9, 0x5d, 0xc9, + 0xfe, 0xc2, 0xc6, 0xe7, 0x59, 0x04, 0xfd, 0x19, 0xaa, 0xcf, 0x1f, 0x59, 0xe4, 0x9f, 0x58, 0xd0, + 0x36, 0x43, 0x38, 0x6a, 0xba, 0x85, 0xc1, 0x22, 0x45, 0x4a, 0x53, 0xe2, 0x3e, 0x3f, 0xc0, 0x51, + 0x1e, 0x3d, 0x70, 0x8c, 0x51, 0x8a, 0xd7, 0x43, 0x7f, 0xbd, 0xd1, 0x92, 0x8f, 0xf9, 0x0f, 0x5e, + 0xc9, 0xe8, 0x35, 0xc9, 0xff, 0x40, 0x92, 0x22, 0x3f, 0xfd, 0xe7, 0x84, 0x70, 0x13, 0x7e, 0xc4, + 0x7f, 0x59, 0x42, 0x86, 0x40, 0x19, 0x15, 0xbf, 0xed, 0xf7, 0xf6, 0x3d, 0x9c, 0xd3, 0x1d, 0xfb, + 0x86, 0x31, 0xa7, 0xac, 0xe2, 0xb1, 0xc6, 0x47, 0x27, 0x7e, 0x09, 0x28, 0x3d, 0x39, 0x73, 0xbf, + 0x0e, 0x34, 0x7d, 0x90, 0x23, 0x3e, 0x48, 0x81, 0x6e, 0xb0, 0xda, 0x5b, 0x36, 0x63, 0x3f, 0xc0, + 0xb1, 0xde, 0xb3, 0xdf, 0x99, 0x3a, 0xd6, 0x87, 0x18, 0x88, 0x61, 0x23, 0x3e, 0x00, 0x48, 0x6f, + 0x9b, 0x90, 0xcc, 0x4d, 0x07, 0x25, 0x80, 0xf2, 0x17, 0x52, 0x4c, 0x7e, 0x96, 0x17, 0x22, 0x58, + 0x8b, 0x3f, 0xe4, 0xe2, 0x74, 0x47, 0xde, 0x91, 0xd0, 0xb5, 0x2f, 0xf3, 0x4a, 0x88, 0xa1, 0x7d, + 0x65, 0xdb, 0x37, 0x84, 0xa9, 0xba, 0x70, 0xf1, 0x02, 0x5a, 0xbb, 0x61, 0xf8, 0x6a, 0x32, 0x56, + 0xd7, 0x1f, 0xcd, 0x18, 0xe9, 0xb6, 0x17, 0x9f, 0xf5, 0x32, 0xb3, 0xb0, 0xef, 0x62, 0x53, 0x3d, + 0xd2, 0xd5, 0x9a, 0x7a, 0xf8, 0xd3, 0xf4, 0x26, 0xcb, 0xe7, 0xc4, 0x83, 0x79, 0x25, 0xa3, 0xd5, 0xc0, 0x7b, 0x66, 0x33, 0x86, 0x64, 0xce, 0x76, 0x61, 0x98, 0x09, 0x72, 0xb4, 0x0f, 0x63, 0xd9, - 0xe6, 0x23, 0x8b, 0x1c, 0x40, 0x73, 0x93, 0xf6, 0xf1, 0x52, 0x28, 0x06, 0x1a, 0x17, 0x8c, 0x60, - 0x15, 0x8f, 0x50, 0xf6, 0x5a, 0x06, 0xd0, 0x3c, 0xb7, 0xc6, 0xde, 0x65, 0x44, 0x3f, 0x7b, 0xf8, - 0x53, 0x11, 0xc2, 0xfc, 0x5c, 0x9e, 0x5b, 0x32, 0xc6, 0x6b, 0x9c, 0x5b, 0x99, 0xa0, 0xb0, 0x71, - 0x6e, 0xe5, 0x82, 0xc2, 0xc6, 0x52, 0xcb, 0x18, 0x33, 0x19, 0xc2, 0x7c, 0x2e, 0x8e, 0xac, 0x8e, - 0xac, 0x69, 0xd1, 0xe7, 0xde, 0xdd, 0xe9, 0x15, 0xcc, 0xde, 0x1e, 0x98, 0xbd, 0x1d, 0x42, 0x8b, - 0x3f, 0x8d, 0x75, 0x4c, 0xf9, 0x7d, 0x8f, 0xcc, 0x2b, 0x0b, 0xfa, 0x6d, 0x92, 0xec, 0x01, 0x83, - 0x38, 0x53, 0xc3, 0xe1, 0x6f, 0x6c, 0xfe, 0x10, 0x1a, 0xcf, 0x68, 0x22, 0x2f, 0x78, 0x28, 0x1d, - 0x3b, 0x73, 0xe3, 0xa3, 0x57, 0x70, 0x3f, 0xc4, 0xa4, 0x19, 0x6c, 0xed, 0x21, 0x1d, 0x9c, 0x52, - 0x2e, 0x9c, 0x5c, 0x7f, 0xf0, 0x39, 0xf9, 0x5d, 0x6c, 0x5c, 0x5d, 0xb7, 0x5b, 0xd2, 0xb2, 0xf5, - 0xf5, 0xc6, 0xe7, 0x32, 0xf0, 0xa2, 0x96, 0x83, 0x70, 0x40, 0x35, 0x5d, 0x2f, 0x80, 0x86, 0x76, - 0x5d, 0x57, 0x31, 0x50, 0xfe, 0x7a, 0xb6, 0x62, 0xa0, 0x82, 0xdb, 0xbd, 0xf6, 0x7d, 0xec, 0xc7, - 0x26, 0x77, 0xd3, 0x7e, 0xf8, 0x8d, 0xde, 0xb4, 0xa7, 0x87, 0x3f, 0xf5, 0x46, 0xc9, 0xe7, 0xe4, - 0x25, 0x3e, 0x54, 0xab, 0x5f, 0x60, 0x49, 0x8d, 0x86, 0xec, 0x5d, 0x17, 0xb5, 0x58, 0x1a, 0xca, - 0x34, 0x24, 0x78, 0x57, 0xa8, 0xc9, 0x7d, 0x0b, 0xe0, 0x30, 0x09, 0xc7, 0x9b, 0x1e, 0x1d, 0x85, - 0x41, 0x2a, 0x6b, 0xd3, 0xeb, 0x13, 0xa9, 0xfc, 0xd2, 0xee, 0x50, 0x90, 0x97, 0x9a, 0x95, 0x65, - 0xdc, 0x01, 0x92, 0xc4, 0x35, 0xf5, 0x86, 0x85, 0x5a, 0x90, 0x82, 0x5b, 0x16, 0x8f, 0x2c, 0xb2, - 0x06, 0x90, 0x26, 0x12, 0x28, 0x9b, 0x29, 0x97, 0xa3, 0xa0, 0xc4, 0x5e, 0x41, 0xd6, 0xc1, 0x01, - 0xd4, 0xd3, 0xb0, 0xeb, 0x72, 0xfa, 0xfa, 0x80, 0x11, 0xa4, 0x55, 0x27, 0x78, 0x2e, 0x18, 0x6a, - 0x77, 0x70, 0xa9, 0x80, 0xd4, 0xd8, 0x52, 0x61, 0x84, 0xd3, 0x87, 0x05, 0x3e, 0x40, 0xa5, 0x2e, - 0x61, 0xda, 0xbf, 0x7a, 0x8f, 0x38, 0x1f, 0x90, 0x54, 0xdc, 0x5c, 0x18, 0x4f, 0x33, 0x5c, 0x3f, - 0x8c, 0x5a, 0xf9, 0x95, 0x03, 0x26, 0x9a, 0x47, 0x30, 0x9f, 0x0b, 0xd1, 0x28, 0x96, 0x9e, 0x16, - 0x83, 0x53, 0x2c, 0x3d, 0x35, 0xba, 0x63, 0x5f, 0xc7, 0x2e, 0xe7, 0x6c, 0x40, 0x53, 0xef, 0xc2, - 0x4f, 0xfa, 0x67, 0xac, 0xbb, 0x3f, 0xb2, 0x60, 0xa1, 0x20, 0x02, 0x43, 0xde, 0x95, 0x5e, 0x83, - 0xa9, 0xd1, 0x99, 0x5e, 0xa1, 0x83, 0xde, 0x3e, 0xc4, 0x7e, 0x9e, 0x93, 0x4f, 0x8d, 0x83, 0x8d, - 0xfb, 0xc6, 0x05, 0x67, 0x5e, 0xa9, 0x54, 0x14, 0x6a, 0x14, 0x9f, 0xc1, 0x32, 0x1f, 0xc8, 0xda, - 0x70, 0x98, 0x09, 0x1e, 0xdc, 0xc9, 0xfd, 0x76, 0xac, 0x11, 0x14, 0xe9, 0x4d, 0xff, 0x6d, 0xd9, - 0x29, 0xea, 0x34, 0x1f, 0x2a, 0x99, 0x40, 0x27, 0xeb, 0x90, 0x27, 0xd3, 0xdb, 0xea, 0xbd, 0x63, - 0xd8, 0xbf, 0x05, 0x4e, 0xfc, 0xdf, 0xc0, 0xce, 0xde, 0xb1, 0x7b, 0x45, 0xeb, 0xc2, 0x4d, 0x62, - 0xb6, 0x1f, 0x7f, 0x59, 0x45, 0x0f, 0x32, 0xf3, 0x94, 0x1d, 0x4c, 0x0b, 0x77, 0x28, 0x0b, 0xbc, - 0x38, 0xf8, 0xf0, 0x1e, 0x76, 0x7f, 0xd7, 0xbe, 0x59, 0xd4, 0x7d, 0xc4, 0x3f, 0xe1, 0xb6, 0xf8, - 0x72, 0x96, 0xaf, 0xe5, 0x08, 0xee, 0x16, 0xed, 0xf7, 0x54, 0x5b, 0x28, 0xb3, 0xd6, 0xd7, 0x50, - 0xb7, 0x6b, 0xea, 0xd1, 0x02, 0xc5, 0x3e, 0x05, 0x61, 0x09, 0xc5, 0x3e, 0x45, 0xe1, 0x05, 0x53, - 0xaf, 0x91, 0x81, 0x85, 0x8f, 0xad, 0x07, 0xeb, 0xef, 0xff, 0xe0, 0x37, 0x4e, 0xfd, 0xe4, 0x6c, - 0x72, 0xbc, 0xd2, 0x0f, 0x47, 0x0f, 0x87, 0xd2, 0xdb, 0x28, 0xae, 0xc2, 0x3d, 0x1c, 0x06, 0x83, - 0x87, 0xd8, 0xec, 0xf1, 0x0c, 0xfe, 0xd8, 0xf5, 0x37, 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x18, 0xa4, 0xd2, 0x33, 0x1e, 0x7b, 0x00, 0x00, + 0xe6, 0x23, 0x8b, 0x1c, 0x40, 0x73, 0x93, 0xf6, 0x31, 0x29, 0x14, 0x03, 0x8d, 0x0b, 0x46, 0xb0, + 0x8a, 0x47, 0x28, 0x7b, 0x2d, 0x03, 0x68, 0x9e, 0x5b, 0x63, 0xef, 0x32, 0xa2, 0x9f, 0x3d, 0xfc, + 0xa9, 0x08, 0x61, 0x7e, 0x2e, 0xcf, 0x2d, 0x19, 0xe3, 0x35, 0xce, 0xad, 0x4c, 0x50, 0xd8, 0x38, + 0xb7, 0x72, 0x41, 0x61, 0x63, 0xa9, 0x65, 0x8c, 0x99, 0x0c, 0x61, 0x3e, 0x17, 0x47, 0x56, 0x47, + 0xd6, 0xb4, 0xe8, 0x73, 0xef, 0xee, 0x74, 0x04, 0xb3, 0xb7, 0x07, 0x66, 0x6f, 0x87, 0xd0, 0xe2, + 0x4f, 0x63, 0x1d, 0x53, 0x9e, 0xef, 0x91, 0x79, 0x65, 0x41, 0xcf, 0x26, 0xc9, 0x1e, 0x30, 0x58, + 0x67, 0x6a, 0x38, 0xfc, 0x8d, 0xcd, 0x1f, 0x42, 0xe3, 0x19, 0x4d, 0x64, 0x82, 0x87, 0xd2, 0xb1, + 0x33, 0x19, 0x1f, 0xbd, 0x82, 0xfc, 0x10, 0x93, 0x66, 0xb0, 0xb5, 0x87, 0x74, 0x70, 0x4a, 0xb9, + 0x70, 0x72, 0xfd, 0xc1, 0xe7, 0xe4, 0xf7, 0xb1, 0x71, 0x95, 0x6e, 0xb7, 0xa4, 0xdd, 0xd6, 0xd7, + 0x1b, 0x9f, 0xcb, 0xc0, 0x8b, 0x5a, 0x0e, 0xc2, 0x01, 0xd5, 0x74, 0xbd, 0x00, 0x1a, 0x5a, 0xba, + 0xae, 0x62, 0xa0, 0x7c, 0x7a, 0xb6, 0x62, 0xa0, 0x82, 0xec, 0x5e, 0xfb, 0x3e, 0xf6, 0x63, 0x93, + 0xbb, 0x69, 0x3f, 0x3c, 0xa3, 0x37, 0xed, 0xe9, 0xe1, 0x4f, 0xbd, 0x51, 0xf2, 0x39, 0x79, 0x89, + 0x0f, 0xd5, 0xea, 0x09, 0x2c, 0xa9, 0xd1, 0x90, 0xcd, 0x75, 0x51, 0x8b, 0xa5, 0x55, 0x99, 0x86, + 0x04, 0xef, 0x0a, 0x35, 0xb9, 0x6f, 0x02, 0x1c, 0x26, 0xe1, 0x78, 0xd3, 0xa3, 0xa3, 0x30, 0x48, + 0x65, 0x6d, 0x9a, 0x3e, 0x91, 0xca, 0x2f, 0x2d, 0x87, 0x82, 0xbc, 0xd4, 0xac, 0x2c, 0x23, 0x07, + 0x48, 0x12, 0xd7, 0xd4, 0x0c, 0x0b, 0xb5, 0x20, 0x05, 0x59, 0x16, 0x8f, 0x2c, 0xb2, 0x06, 0x90, + 0x5e, 0x24, 0x50, 0x36, 0x53, 0xee, 0x8e, 0x82, 0x12, 0x7b, 0x05, 0xb7, 0x0e, 0x0e, 0xa0, 0x9e, + 0x86, 0x5d, 0x97, 0xd3, 0xd7, 0x07, 0x8c, 0x20, 0xad, 0x3a, 0xc1, 0x73, 0xc1, 0x50, 0xbb, 0x83, + 0x4b, 0x05, 0xa4, 0xc6, 0x96, 0x0a, 0x23, 0x9c, 0x3e, 0x2c, 0xf0, 0x01, 0x2a, 0x75, 0x09, 0xaf, + 0xfd, 0xab, 0xf7, 0x88, 0xf3, 0x01, 0x49, 0xc5, 0xcd, 0x85, 0xf1, 0x34, 0xc3, 0xf5, 0xc3, 0xa8, + 0x95, 0xa7, 0x1c, 0x30, 0xd1, 0x3c, 0x82, 0xf9, 0x5c, 0x88, 0x46, 0xb1, 0xf4, 0xb4, 0x18, 0x9c, + 0x62, 0xe9, 0xa9, 0xd1, 0x1d, 0xfb, 0x3a, 0x76, 0x39, 0x67, 0x03, 0x9a, 0x7a, 0x17, 0x7e, 0xd2, + 0x3f, 0x63, 0xdd, 0xfd, 0xb1, 0x05, 0x0b, 0x05, 0x11, 0x18, 0xf2, 0xae, 0xf4, 0x1a, 0x4c, 0x8d, + 0xce, 0xf4, 0x0a, 0x1d, 0xf4, 0xf6, 0x21, 0xf6, 0xf3, 0x9c, 0x7c, 0x6a, 0x1c, 0x6c, 0xdc, 0x37, + 0x2e, 0x38, 0xf3, 0x4a, 0xa5, 0xa2, 0x50, 0xa3, 0xf8, 0x0c, 0x96, 0xf9, 0x40, 0xd6, 0x86, 0xc3, + 0x4c, 0xf0, 0xe0, 0x4e, 0xee, 0x47, 0x71, 0x8d, 0xa0, 0x48, 0x6f, 0xfa, 0x8f, 0xe6, 0x4e, 0x51, + 0xa7, 0xf9, 0x50, 0xc9, 0x04, 0x3a, 0x59, 0x87, 0x3c, 0x99, 0xde, 0x56, 0xef, 0x1d, 0xc3, 0xfe, + 0x2d, 0x70, 0xe2, 0x7f, 0x19, 0x3b, 0x7b, 0xc7, 0xee, 0x15, 0xad, 0x0b, 0x37, 0x89, 0xd9, 0x7e, + 0xfc, 0x65, 0x15, 0x3d, 0xc8, 0xcc, 0x53, 0x76, 0x30, 0x2d, 0xdc, 0xa1, 0x2c, 0xf0, 0xe2, 0xe0, + 0xc3, 0x7b, 0xd8, 0xfd, 0x5d, 0xfb, 0x66, 0x51, 0xf7, 0x11, 0xff, 0x84, 0xdb, 0xe2, 0xcb, 0x59, + 0xbe, 0x96, 0x23, 0xb8, 0x5b, 0xb4, 0xdf, 0x53, 0x6d, 0xa1, 0xcc, 0x5a, 0x5f, 0x43, 0xdd, 0xae, + 0xa9, 0x47, 0x0b, 0x14, 0xfb, 0x14, 0x84, 0x25, 0x14, 0xfb, 0x14, 0x85, 0x17, 0x4c, 0xbd, 0x46, + 0x06, 0x16, 0x3e, 0xb6, 0x1e, 0xac, 0xbf, 0xff, 0x83, 0x2f, 0x9f, 0xfa, 0xc9, 0xd9, 0xe4, 0x78, + 0xa5, 0x1f, 0x8e, 0x1e, 0x0e, 0xa5, 0xb7, 0x51, 0xa4, 0xc2, 0x3d, 0x1c, 0x06, 0x83, 0x87, 0xd8, + 0xec, 0xf1, 0x0c, 0xfe, 0x8a, 0xf7, 0xd7, 0xff, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x6d, + 0x27, 0xff, 0xf7, 0x7b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 37a68dc2cd..8e48440be8 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1430,6 +1430,29 @@ message ChannelCloseSummary { /// Details on how the channel was closed. ClosureType close_type = 10 [json_name = "close_type"]; + + enum Initiator { + UNKNOWN = 0; + LOCAL = 1; + REMOTE = 2; + BOTH = 3; + } + + /** + Open initiator is the party that initiated opening the channel. Note that + this value may be unknown if the channel was closed before we migrated to + store open channel information after close. + */ + Initiator open_initiator = 11 [json_name = "open_initiator"]; + + /** + Close initiator indicates which party initiated the close. This value will + be unknown for channels that were cooperatively closed before we started + tracking cooperative close initiators. Note that this indicates which party + initiated a close, and it is possible for both to initiate cooperative or + force closes, although only one party's close will be confirmed on chain. + */ + Initiator close_initiator = 12 [json_name = "close_initiator"]; } message ClosedChannelsRequest { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 701d43ccf2..d4c2af0e36 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1461,6 +1461,16 @@ ], "default": "COOPERATIVE_CLOSE" }, + "ChannelCloseSummaryInitiator": { + "type": "string", + "enum": [ + "UNKNOWN", + "LOCAL", + "REMOTE", + "BOTH" + ], + "default": "UNKNOWN" + }, "ChannelEventUpdateUpdateType": { "type": "string", "enum": [ @@ -2059,6 +2069,14 @@ "close_type": { "$ref": "#/definitions/ChannelCloseSummaryClosureType", "description": "/ Details on how the channel was closed." + }, + "open_initiator": { + "$ref": "#/definitions/ChannelCloseSummaryInitiator", + "description": "*\nOpen initiator is the party that initiated opening the channel. Note that\nthis value may be unknown if the channel was closed before we migrated to\nstore open channel information after close." + }, + "close_initiator": { + "$ref": "#/definitions/ChannelCloseSummaryInitiator", + "description": "*\nClose initiator indicates which party initiated the close. This value will\nbe unknown for channels that were cooperatively closed before we started\ntracking cooperative close initiators. Note that this indicates which party\ninitiated a close, and it is possible for both to initiate cooperative or\nforce closes, although only one party's close will be confirmed on chain." } } }, From e74b6f88b76334ad9185f70fb2216a086efa0f1a Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 21 Feb 2020 13:24:24 +0200 Subject: [PATCH 111/562] rpcserver: display open and close initiator --- rpcserver.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 305ddc95c0..a653741ef7 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2922,7 +2922,11 @@ func (r *rpcServer) ClosedChannels(ctx context.Context, } } - channel := createRPCClosedChannel(dbChannel) + channel, err := r.createRPCClosedChannel(dbChannel) + if err != nil { + return nil, err + } + resp.Channels = append(resp.Channels, channel) } @@ -3137,13 +3141,29 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, // createRPCClosedChannel creates an *lnrpc.ClosedChannelSummary from a // *channeldb.ChannelCloseSummary. -func createRPCClosedChannel( - dbChannel *channeldb.ChannelCloseSummary) *lnrpc.ChannelCloseSummary { +func (r *rpcServer) createRPCClosedChannel( + dbChannel *channeldb.ChannelCloseSummary) (*lnrpc.ChannelCloseSummary, error) { nodePub := dbChannel.RemotePub nodeID := hex.EncodeToString(nodePub.SerializeCompressed()) - var closeType lnrpc.ChannelCloseSummary_ClosureType + var ( + closeType lnrpc.ChannelCloseSummary_ClosureType + openInit lnrpc.ChannelCloseSummary_Initiator + closeInitiator lnrpc.ChannelCloseSummary_Initiator + err error + ) + + // Lookup local and remote cooperative initiators. If these values + // are not known they will just return unknown. + openInit, closeInitiator, err = r.getInitiators( + &dbChannel.ChanPoint, + ) + if err != nil { + return nil, err + } + + // Convert the close type to rpc type. switch dbChannel.CloseType { case channeldb.CooperativeClose: closeType = lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE @@ -3170,7 +3190,75 @@ func createRPCClosedChannel( TimeLockedBalance: int64(dbChannel.TimeLockedBalance), ChainHash: dbChannel.ChainHash.String(), ClosingTxHash: dbChannel.ClosingTXID.String(), + OpenInitiator: openInit, + CloseInitiator: closeInitiator, + }, nil +} + +// getInitiators returns an initiator enum that provides information about the +// party that initiated channel's open and close. This information is obtained +// from the historical channel bucket, so unknown values are returned when the +// channel is not present (which indicates that it was closed before we started +// writing channels to the historical close bucket). +func (r *rpcServer) getInitiators(chanPoint *wire.OutPoint) ( + lnrpc.ChannelCloseSummary_Initiator, + lnrpc.ChannelCloseSummary_Initiator, error) { + + var ( + openInitiator = lnrpc.ChannelCloseSummary_UNKNOWN + closeInitiator = lnrpc.ChannelCloseSummary_UNKNOWN + ) + + // To get the close initiator for cooperative closes, we need + // to get the channel status from the historical channel bucket. + histChan, err := r.server.chanDB.FetchHistoricalChannel(chanPoint) + switch { + // The node has upgraded from a version where we did not store + // historical channels, and has not closed a channel since. Do + // not return an error, initiator values are unknown. + case err == channeldb.ErrNoHistoricalBucket: + return openInitiator, closeInitiator, nil + + // The channel was closed before we started storing historical + // channels. Do not return an error, initiator values are unknown. + case err == channeldb.ErrChannelNotFound: + return openInitiator, closeInitiator, nil + + case err != nil: + return 0, 0, err + } + + // If we successfully looked up the channel, determine initiator based + // on channels status. + if histChan.IsInitiator { + openInitiator = lnrpc.ChannelCloseSummary_LOCAL + } else { + openInitiator = lnrpc.ChannelCloseSummary_REMOTE + } + + localInit := histChan.HasChanStatus( + channeldb.ChanStatusLocalCloseInitiator, + ) + + remoteInit := histChan.HasChanStatus( + channeldb.ChanStatusRemoteCloseInitiator, + ) + + switch { + // There is a possible case where closes were attempted by both parties. + // We return the initiator as both in this case to provide full + // information about the close. + case localInit && remoteInit: + closeInitiator = lnrpc.ChannelCloseSummary_BOTH + + case localInit: + closeInitiator = lnrpc.ChannelCloseSummary_LOCAL + + case remoteInit: + closeInitiator = lnrpc.ChannelCloseSummary_REMOTE } + + return openInitiator, closeInitiator, nil } // SubscribeChannelEvents returns a uni-directional stream (server -> client) @@ -3222,7 +3310,13 @@ func (r *rpcServer) SubscribeChannelEvents(req *lnrpc.ChannelEventSubscription, } case channelnotifier.ClosedChannelEvent: - closedChannel := createRPCClosedChannel(event.CloseSummary) + closedChannel, err := r.createRPCClosedChannel( + event.CloseSummary, + ) + if err != nil { + return err + } + update = &lnrpc.ChannelEventUpdate{ Type: lnrpc.ChannelEventUpdate_CLOSED_CHANNEL, Channel: &lnrpc.ChannelEventUpdate_ClosedChannel{ From b3e6395635f1e674a88b19e660ae12588304e9cb Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 21 Feb 2020 13:24:24 +0200 Subject: [PATCH 112/562] lntest: check close initiator in basic channel itest Update channel updates and subscription itest to check that close initiator is appropriately set for cooperative and force closes for the local and remote party. --- lntest/itest/lnd_test.go | 65 ++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index c18b60d9a8..665426a30f 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -6382,7 +6382,8 @@ func subscribeChannelNotifications(ctxb context.Context, t *harnessTest, // verifyCloseUpdate is used to verify that a closed channel update is of the // expected type. func verifyCloseUpdate(chanUpdate *lnrpc.ChannelEventUpdate, - force bool, forceType lnrpc.ChannelCloseSummary_ClosureType) error { + closeType lnrpc.ChannelCloseSummary_ClosureType, + closeInitiator lnrpc.ChannelCloseSummary_Initiator) error { // We should receive one inactive and one closed notification // for each channel. @@ -6401,23 +6402,19 @@ func verifyCloseUpdate(chanUpdate *lnrpc.ChannelEventUpdate, chanUpdate.Type) } - switch force { - case true: - if update.ClosedChannel.CloseType != forceType { - return fmt.Errorf("channel closure type mismatch: "+ - "expected %v, got %v", - forceType, - update.ClosedChannel.CloseType) - } - case false: - if update.ClosedChannel.CloseType != - lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE { - return fmt.Errorf("channel closure type "+ - "mismatch: expected %v, got %v", - lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE, - update.ClosedChannel.CloseType) - } + if update.ClosedChannel.CloseType != closeType { + return fmt.Errorf("channel closure type "+ + "mismatch: expected %v, got %v", + closeType, + update.ClosedChannel.CloseType) } + + if update.ClosedChannel.CloseInitiator != closeInitiator { + return fmt.Errorf("expected close intiator: %v, got: %v", + closeInitiator, + update.ClosedChannel.CloseInitiator) + } + default: return fmt.Errorf("channel update channel of wrong type, "+ "expected closed channel, got %T", @@ -6529,18 +6526,29 @@ func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTe // verifyCloseUpdatesReceived is used to verify that Alice and Bob // receive the correct channel updates in order. verifyCloseUpdatesReceived := func(sub channelSubscription, - forceType lnrpc.ChannelCloseSummary_ClosureType) error { + forceType lnrpc.ChannelCloseSummary_ClosureType, + closeInitiator lnrpc.ChannelCloseSummary_Initiator) error { // Ensure one inactive and one closed notification is received for each // closed channel. numChannelUpds := 0 for numChannelUpds < 2*numChannels { - // Every other channel should be force closed. + expectedCloseType := lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE + + // Every other channel should be force closed. If this + // channel was force closed, set the expected close type + // the the type passed in. force := (numChannelUpds/2)%2 == 0 + if force { + expectedCloseType = forceType + } select { case chanUpdate := <-sub.updateChan: - err := verifyCloseUpdate(chanUpdate, force, forceType) + err := verifyCloseUpdate( + chanUpdate, expectedCloseType, + closeInitiator, + ) if err != nil { return err } @@ -6549,9 +6557,10 @@ func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTe case err := <-sub.errChan: return err case <-time.After(time.Second * 10): - return fmt.Errorf("timeout waiting for channel "+ - "notifications, only received %d/%d "+ - "chanupds", numChannelUpds, 2*numChannels) + return fmt.Errorf("timeout waiting "+ + "for channel notifications, only "+ + "received %d/%d chanupds", + numChannelUpds, 2*numChannels) } } @@ -6560,15 +6569,21 @@ func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTe // Verify Bob receives all closed channel notifications. He should // receive a remote force close notification for force closed channels. + // All channels (cooperatively and force closed) should have a remote + // close initiator because Alice closed the channels. if err := verifyCloseUpdatesReceived(bobChanSub, - lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE); err != nil { + lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE, + lnrpc.ChannelCloseSummary_REMOTE); err != nil { t.Fatalf("errored verifying close updates: %v", err) } // Verify Alice receives all closed channel notifications. She should // receive a remote force close notification for force closed channels. + // All channels (cooperatively and force closed) should have a local + // close initiator because Alice closed the channels. if err := verifyCloseUpdatesReceived(aliceChanSub, - lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE); err != nil { + lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE, + lnrpc.ChannelCloseSummary_LOCAL); err != nil { t.Fatalf("errored verifying close updates: %v", err) } } From 926d4ba52e4277ab3e8178e3c0024958f54de51b Mon Sep 17 00:00:00 2001 From: bitromortac Date: Thu, 6 Feb 2020 08:03:28 +0100 Subject: [PATCH 113/562] lncli: change listinvoices reversed flag to paginate-forwards This commit renames the `reversed` pagination flag to `paginate-forwards`, which is off by default. In order to access older invoices one can set the paginate-forwards flag, which is more intuitive than setting the reversed flag to false. --- cmd/lncli/commands.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 4e10dd3f8e..08725f1f35 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -2819,10 +2819,10 @@ var listInvoicesCommand = cli.Command{ allowing users to query for specific invoices through their add_index. This can be done by using either the first_index_offset or last_index_offset fields included in the response as the index_offset of - the next request. The reversed flag is set by default in order to - paginate backwards. If you wish to paginate forwards, you must - explicitly set the flag to false. If none of the parameters are - specified, then the last 100 invoices will be returned. + the next request. Backward pagination is enabled by default to receive + current invoices first. If you wish to paginate forwards, set the + paginate-forwards flag. If none of the parameters are specified, then + the last 100 invoices will be returned. For example: if you have 200 invoices, "lncli listinvoices" will return the last 100 created. If you wish to retrieve the previous 100, the @@ -2845,11 +2845,10 @@ var listInvoicesCommand = cli.Command{ Name: "max_invoices", Usage: "the max number of invoices to return", }, - cli.BoolTFlag{ - Name: "reversed", - Usage: "if set, the invoices returned precede the " + - "given index_offset, allowing backwards " + - "pagination", + cli.BoolFlag{ + Name: "paginate-forwards", + Usage: "if set, invoices succeeding the " + + "index_offset will be returned", }, }, Action: actionDecorator(listInvoices), @@ -2863,7 +2862,7 @@ func listInvoices(ctx *cli.Context) error { PendingOnly: ctx.Bool("pending_only"), IndexOffset: ctx.Uint64("index_offset"), NumMaxInvoices: ctx.Uint64("max_invoices"), - Reversed: ctx.Bool("reversed"), + Reversed: !ctx.Bool("paginate-forwards"), } invoices, err := client.ListInvoices(context.Background(), req) From 5ff017664c47801db5c4808cb8b8e467ebcc937a Mon Sep 17 00:00:00 2001 From: elkanatovey Date: Thu, 27 Feb 2020 15:22:00 +0200 Subject: [PATCH 114/562] fix typo --- routing/pathfind.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing/pathfind.go b/routing/pathfind.go index f2ea782d9b..d9125cc4c8 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -573,7 +573,7 @@ func findPathInternal( edgesExpanded++ - // Calculate amount that the candidate node would have to sent + // Calculate amount that the candidate node would have to send // out. amountToSend := toNodeDist.amountToReceive From ccafee40eefde715ad6e1b967a6403d37f3379f4 Mon Sep 17 00:00:00 2001 From: Danny Paz Date: Thu, 27 Feb 2020 06:23:14 -0800 Subject: [PATCH 115/562] README: change slack link from invite to lightning.engineering --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c62b2e2d17..62c93f54eb 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ resources including talks, articles, and example applications can be found at: [dev.lightning.community](https://dev.lightning.community). Finally, we also have an active -[Slack](https://join.slack.com/t/lightningcommunity/shared_invite/enQtODY1NTI2MjY5MjAzLTQxYjBmNTcxNTA1YzZkZDQ1ZDNlYzJmZWMwYjg4MTI3OTkyZTU4ZDYzNTFjYzgyMWM0ZmZlYzVlZWI1YzhkNDI) where protocol developers, application developers, testers and users gather to +[Slack](https://lightning.engineering/slack.html) where protocol developers, application developers, testers and users gather to discuss various aspects of `lnd` and also Lightning in general. ## Installation @@ -68,7 +68,7 @@ discuss various aspects of `lnd` and also Lightning in general. ## Docker To run lnd from Docker, please see the main [Docker instructions](docs/DOCKER.md) - + ## IRC * irc.freenode.net * channel #lnd From 7b9e0c889ee7a6817e971f35c5986836341c96d7 Mon Sep 17 00:00:00 2001 From: nsa Date: Mon, 3 Feb 2020 20:43:01 -0500 Subject: [PATCH 116/562] docs: add fuzz.md --- docs/fuzz.md | 54 +++++++++++++++++++ docs/go-fuzz/README.md | 106 ------------------------------------- docs/go-fuzz/corpus.tar.gz | Bin 8850 -> 0 bytes docs/go-fuzz/wirefuzz.go | 54 ------------------- 4 files changed, 54 insertions(+), 160 deletions(-) create mode 100644 docs/fuzz.md delete mode 100644 docs/go-fuzz/README.md delete mode 100644 docs/go-fuzz/corpus.tar.gz delete mode 100644 docs/go-fuzz/wirefuzz.go diff --git a/docs/fuzz.md b/docs/fuzz.md new file mode 100644 index 0000000000..1763446288 --- /dev/null +++ b/docs/fuzz.md @@ -0,0 +1,54 @@ +# Fuzzing LND # + +The `fuzz` package is organized into subpackages which are named after the `lnd` package they test. Each subpackage has its own set of fuzz targets. + +### Setup and Installation ### +This section will cover setup and installation of `go-fuzz` and fuzzing binaries. + +* First, we must get `go-fuzz`. +``` +$ go get -u github.com/dvyukov/go-fuzz/... +``` +* The following is a command to build all fuzzing harnesses for a specific package. +``` +$ cd fuzz/ +$ find * -maxdepth 1 -regex '[A-Za-z0-9\-_.]'* -not -name fuzz_utils.go | sed 's/\.go$//1' | xargs -I % sh -c 'go-fuzz-build -func Fuzz_% -o -%-fuzz.zip github.com/lightningnetwork/lnd/fuzz/' +``` + +* This may take a while since this will create zip files associated with each fuzzing target. + +* Now, run `go-fuzz` with `workdir` set as below! +``` +$ go-fuzz -bin=<.zip archive here> -workdir= -procs= +``` + +`go-fuzz` will print out log lines every couple of seconds. Example output: +``` +2017/09/19 17:44:23 workers: 8, corpus: 23 (3s ago), crashers: 1, restarts: 1/748, execs: 400690 (16694/sec), cover: 394, uptime: 24s +``` +Corpus is the number of items in the corpus. `go-fuzz` may add valid inputs to +the corpus in an attempt to gain more coverage. Crashers is the number of inputs +resulting in a crash. The inputs, and their outputs are logged in: +`fuzz///crashers`. `go-fuzz` also creates a `suppressions` directory +of stacktraces to ignore so that it doesn't create duplicate stacktraces. +Cover is a number representing edge coverage of the program being fuzzed. + +### Brontide ### +The brontide fuzzers need to be run with a `-timeout` flag of 20 seconds or greater since there is a lot of machine state that must be printed on panic. + +### Corpus ### +Fuzzing generally works best with a corpus that is of minimal size while achieving the maximum coverage. However, `go-fuzz` automatically minimizes the corpus in-memory before fuzzing so a large corpus shouldn't make a difference - edge coverage is all that really matters. + +### Test Harness ### +If you take a look at the test harnesses that are used, you will see that they all consist of one function: +``` +func Fuzz(data []byte) int +``` +If: + +- `-1` is returned, the fuzzing input is ignored +- `0` is returned, `go-fuzz` will add the input to the corpus and deprioritize it in future mutations. +- `1` is returned, `go-fuzz` will add the input to the corpus and prioritize it in future mutations. + +### Conclusion ### +Citizens, do your part and `go-fuzz` `lnd` today! diff --git a/docs/go-fuzz/README.md b/docs/go-fuzz/README.md deleted file mode 100644 index 38f9e80670..0000000000 --- a/docs/go-fuzz/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# How to fuzz the Lightning Network Daemon's wire protocol using go-fuzz # - -This document will describe how to use the fuzz-testing library `go-fuzz` on -the `lnd` wire protocol. - -### Introduction ### - -Lnd uses its own wire protocol to send and receive messages of all types. There -are 22 different message types, each with their own specific format. If a -message is not in the correct format, `lnd` should logically reject the message -and throw an error. But what if it doesn't? What if we could sneakily craft a -custom message that could pass all the necessary checks and cause an error to -go undetected? Chaos would ensue. However, crafting such a message would require -an in-depth understanding of the many different cogs that make the wire protocol -tick. - -A better solution is fuzz-testing. Fuzz-testing or fuzzing is when a program -known as a fuzzer generates many, many inputs to a function or program in an -attempt to cause it to crash. Fuzzing is surprisingly effective at finding bugs -and a particular fuzzing program `AFL` is well-known for the amount of bugs it -has found with its learned approach. The library we will be using, `go-fuzz`, is -based on `AFL` and has quite a track record of finding bugs in a diverse set of -go programs. `go-fuzz` takes a coverage-guided approach in an attempt to cover -as many code paths as possible on an attack surface. We give `go-fuzz` real, -valid inputs and it will essentially change bits until it achieves a crash! -After reading this document, you too may be able to find errors in `lnd` with -`go-fuzz`! - -### Setup and Installation ### -This section will cover setup and installation of `go-fuzz`. - -* First, we must get `go-fuzz`: -``` -$ go get github.com/dvyukov/go-fuzz/go-fuzz -$ go get github.com/dvyukov/go-fuzz/go-fuzz-build -``` -* Next, create a folder in the `lnwire` package. You can name it whatever. -``` -$ mkdir lnwire/ -``` -* Unzip `corpus.tar.gz` in the `docs/go-fuzz` folder and move it to the folder you just made. -``` -$ tar -xzf docs/go-fuzz/corpus.tar.gz -$ mv corpus lnwire/ -``` -* Now, move `wirefuzz.go` to the same folder you just created. -``` -$ mv docs/go-fuzz/wirefuzz.go lnwire/ -``` -* Change the package name in `wirefuzz.go` from `wirefuzz` to ``. -* Build the test program - this produces a `-fuzz.zip` (archive) file. -``` -$ go-fuzz-build github.com/lightningnetwork/lnd/lnwire/ -``` -* Now, run `go-fuzz`!!! -``` -$ go-fuzz -bin=<.zip archive here> -workdir=lnwire/ -``` - -`go-fuzz` will print out log lines every couple of seconds. Example output: -``` -2017/09/19 17:44:23 slaves: 8, corpus: 23 (3s ago), crashers: 1, restarts: 1/748, execs: 400690 (16694/sec), cover: 394, uptime: 24s -``` -Corpus is the number of items in the corpus. `go-fuzz` may add valid inputs to -the corpus in an attempt to gain more coverage. Crashers is the number of inputs -resulting in a crash. The inputs, and their outputs are logged in: -`/crashers`. `go-fuzz` also creates a `suppressions` directory -of stacktraces to ignore so that it doesn't create duplicate stacktraces. -Cover is a number representing coverage of the program being fuzzed. When I ran -this earlier, `go-fuzz` found two bugs ([#310](https://github.com/lightningnetwork/lnd/pull/310) and [#312](https://github.com/lightningnetwork/lnd/pull/312)) within minutes! - -### Corpus Notes ### -You may wonder how I made the corpus that you unzipped in the previous step. -It's quite simple really. For every message type that `lnwire_test.go` -processed in `TestLightningWireProtocol`, I logged it (in `[]byte` format) to -a .txt file. Within minutes, I had a corpus of valid `lnwire` messages that -I could use with `go-fuzz`! `go-fuzz` will alter these valid messages to create -the sneakily crafted message that I described in the introduction that manages -to bypass validation checks and crash the program. I ran `go-fuzz` for several -hours on the corpus I generated and found two bugs. I believe I have exhausted -the current corpus, but there are still perhaps possible malicious inputs that -`go-fuzz` has not yet reached and could reach with a slightly different generated -corpus. - -### Test Harness ### -If you take a look at the test harness that I used, `wirefuzz.go`, you will see -that it consists of one function: `func Fuzz(data []byte) int`. `go-fuzz` requires -that each input in the corpus is in `[]byte` format. The test harness is also -quite simple. It reads in `[]byte` messages into `lnwire.Message` objects, -serializes them into a buffer, deserializes them back into `lnwire.Message` objects -and asserts their equality. If the pre-serialization and post-deserialization -`lnwire.Message` objects are not equal, the wire protocol has encountered a bug. -Wherever a `0` is returned, `go-fuzz` will ignore that input as it has reached -an unimportant code path caused by the parser catching the error. If a `1` is -returned, the `[]byte` input was parsed successfully and the two `lnwire.Message` -objects were indeed equal. This `[]byte` input is then added to the corpus as -a valid message. If a `panic` is reached, serialization or deserialization failed -and `go-fuzz` may have found a bug. - -### Conclusion ### -Fuzzing is a powerful and quick way to find bugs in programs that works especially -well with protocols where there is a strict format with validation rules. Fuzzing -is important as an automated security tool and can find real bugs in real-world -software. The fuzzing of `lnd` is by no means complete and there exist probably -many more bugs in the software that may `go` undetected if left unfuzzed. Citizens, -do your part and `go-fuzz` `lnd` today! diff --git a/docs/go-fuzz/corpus.tar.gz b/docs/go-fuzz/corpus.tar.gz deleted file mode 100644 index da6a0ea683366f1c7468adacc308362636b7d75e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8850 zcmV;DB5mCtiwFS3e8E`&1MPhWm=#63_5=h)Br}pENKSeti^LU_9Hm>kL2!U7rix(( zhCu`*i6BT=5UQY?jC5nSk|aqG$r&YsC`c3ulCui;tr0K!|Ib~X`v^04-Sh3b<1*)* z?)vI`Q_VR;hm_Q=J-R<1@+d112*k(6mPr2^_uJP%RLpN*?^TJ&=*YN0RD4`ibaaV8 zWK?uiAf!a>BfYD8)uVe_LMm=0xqHIDd>kG|>A(2?y>Q|}#$f+rX zQ(|9h{^siNqRrl`x2wUNDc=m7J>(KSJK)f>c^{jptr(J6b?BV#{c~0ddv3$+gR4j1 znLYID%kM5O@b*jn>(skl|CK{+V^b#QKXUB)tne1AQ=)%PW{vI^oYwwSOp~YmWqDJI z9Xp<7WVh2fRvlXx9lpu95M?Buo73w+i@=paKTqpY==D5@k9^g>Ow|VM26l=3I@F4t0#YX*(|JXoGEbt!}A0HjWe@0Yj`1l*c zay(ffXRD?a>{c!2WxJEKZ(#SSMO$9$z4zluEB8L1l=sNUh@8crj304q1uI|lSl?;= z=%Cl~71}v!+~n_P$aagjO#d=G|IK&zR~YkH{bxEHxw@j_(7bs%JzJzx$o`5sXBTK3 zzLN0@RZ7qKtIyBuPW?UW9{%qs|L-)=g(RmvJOX$C{v#FUf5(4hr1F39k%2%E{~1xC zA(@Tq%zl1I4~H;997#1vG~K0^Yiq}R!@CWw zPIC{`ztZ|(>GfL<zP485LD}RhWNd;nuV-W?y{c*R(UmkG@~2`9}+;xBI-`yf? z#YYDDKO-tM?62}?%Rw(Xd6qtZ{@mD}eTuZ2RG`Dr)8|49-x%Dkb$jv3e3_KuRCpz@ zF?&{RfH|OQ|2G!rEYhKHl}<12$WfwF%QE{uXqVX?_|LB2@t>5^oh5ft@sD)OX#7Y1 zA^$~1rQ<(75Ff;UhE(~6+vbkHGIYT08M|Iyw5!_-Kd*ZureumWC}--l53A*!IzFuA z*3xU;4ymsO^V{FCe#d`Gmo6*~@PF9YSM{L$7lm*BH~wP-3jcxF;Q3F+)O(BGIMC|* zz@UaZS4=z@5gA9n4~e*OV%w5SZ@w^z%sNz|dx67eTlK%Qa$Iy~-*~VdM%}|d?UCFO z`L9DNNl1I>0r0`+KllA#bRbIo{4Wq4^nV#s&qiNAardoyW84y5OGUk$GPlAV`$A%i zTe+SK%d&gc(<}0ZXYV{D%b|S*a$alJuwUyLjXRFYePF`6c757>HvYrbGdt}n(Rfi% z-~WB<&-hPD>Cib7&VK^Y_wgSU`0f2aLHuV-m9D*O$mvb5jEf%XkE=*dPnnQ!sIdR> zUg4LYsGRoZkvGQo3qRg$bfwT~2@$nVh{dI+eV*^hjyoS8{@j%VXP$p)VED*fB(ql# ztiMoy#(yTA|Hj<+|Iz91|BQ_fLoK?g)8|rqzR9wW$yu)Y z<(ifAy|(MfGi!tD{&%i>_-D!NA->_~|EYhC|HuH;{yzR=;#B?*#01~}lQES$+d`&u z?irr%G3i;prMsTw2J>8@S<;fy(F~pYx@X(OHB2fkO}9;M5#~@=;{Qv@9nI7oX%e9^ z$%IBtow%lL+8!f#VTW46qL!<1*EKZVHKni(;Yrt*mM(lw8J^7@-{90E#5Xk0cce{h zS2u+(HJj?Dwro~4`2 z^mWT;%o4ukP{TEuEo|R543nu>Wn8z3;bXm~p=*xRZQs>hyt2VHW@^IqY~A$GciXZo z?&(DMXob{pA6Oe&V+hk@25}ijAAF`!O*5Imc2j9;I(3*sDDi!U?nsYWoLIW_9PFSe zuq#~iZOhh(p}U4|n!f2cjzOvC5$1B&@ri>Qvkfer*rs9lo)i=f(JW>&iazKTZkw7G zH?TcSs#RE$aL#aROfx-0w_TxQ+-$1Z2BDgdg&4Ns;0{cIXWO1IOwZ<;CvZ(u8aAO! z_wnbxL)BZVh(Mb>W=rN#hf*JV?c1E%j_rHIu^hrRtiYAT*L)XuB$%*m^-e8rGmBV+ z>(r23nzn12j_$f>kAtaV)RWjSY=WT~)G>U4v9obyK{=OLv8OSOIhMh()dtgC$%SiT zptz3NFl~%6*966^c-VXgUB{?!BB|kU!VT<~qypX7FlDx55Fag+nyH~JLi32lG4i&< zhzaPJhNCe{3g&1wS2tl}XbkD-nx|%!Tej!u7XGVKpJ32!(;|`)jHYe5Oyg>h4B-%_ zJ1!6{&>=KImkj*{qOc&~S~?Cfgzj71F->k*1np$DrlG^w7e?_~wgrF+onc-y4Pd}Z zG&PLaC<74Zm@X-FKpI`6CesLaO)eP5pL3I7Hz<_~`ov)jBY{E;$u5p z%ncfD8JchSriUHz1el8o!*`fYbzxe#2glQ08@GpjcL6hIavu~%xrKp|rU1QgbX!Pf zx!7F_ZeYX#NC~!w8lGnn-Lh?L0A3hdix#*Z(;Ohra4d#@2kITrssl`F9xkrClnCjA zWq@JFrPRcXff*U@Li0V)lLhXeHmJZyXEpGU>v1k9Q+wp%xf;VVbWhkqmO*%IC z3{ci^E564)&BFfxx?n_462={%kP=gxI-24Do0{$s8;k+i14oui)d&LV9`42RFas_| z2^^?+%CS9+kLG|vJ)Ht-QUEoY^r?$ka(sq0QVOGCSe=W>Bj1X8g=SH~>c9$rnV)o|Z4HDXcq7E4`it`FukO-r{injl~- zMPO?vBfjUF)TJOmM^`ff0)!fI&jwwhMV1ThG{9MoguFPmMh(renVMc~f)3i({PeeF za`f5fm@_D$M|H02lu6-f#C4!a7+InN5yCPo@UsmlyA0Z7;@aG_Oc$gI5Q1O8B!ojg z2SMxbDT%{tExwyJ-LcFk7KpMBz_Hryv>8AXRD0~bB_|}DHK}W%yz9l3Y z=K;?UPKPLURcde8AW95}pddHM3+|F*rwrGJGU}WGzi@FxSX!7T^o{6HUQnLxgR7)KLxC2o)-i1?SN9z0VD@yzu`veZ#^E3lQ!lNe=!k%#noAU+p<&2&u3Es1O6KO7j+0eWdr ziAE4igDn{6u7+U-{XuGcVR3M`Viq(8&@wb-?%>LFVAG&BzU$g}GF%O;1_QG}&!~&n zgagE_a0s!0r0cq_f%*sp-vMC)5*Tp@3%8(|P*O*vmq9FJ-a=O80ngRg*} zl*9mA>FLf3@&her2IP#GKKNV;i{NfF!9ieX5p}>4wuAyx=*ap5?+9LdyYCkepc}BfFcceuT%e`thE`Y-{lk!OVRA4&{tc>Ox)cvbN5JYZ zGe9ULl1a>~14~a~SFnrN1}sl{K0FU-8qY$z(F@!M=+(w60Yxx&Tp$6!zc{c&0@mGE z+6<#Fl|%L5>}+5U3j_OG)bwr00EASaX=tB<4~&bUNY?Qj_;p>wwXi!T1X>3KfK=Pl zpw&L?9LI2*c(_f$54v($%)zL_0Ko=8T)^i*m&z9!;4YN)F&XoC`m-$#iP3#qu_^Ws zl*M%2^DyKJsUEigJ2c*vI+PUHz@KxBxXFCj4m{sL=cwXa<^#vJ3v=hF#abGWCxt*W z4B$>h4ckCU!U{0e>Ym^i)v7^su=l$1oHm*Zs>Jle@VXdT(^PZdLP}uFG&nUl4Tz}H z8w@DJKEryekfSLh4^OFr5o|pI4h$(Yge&7hJ%F1D1N%)F+?^xTh66EZybFcHPJuCD z)*R)gBn%Ilg$}w>eW(G8=P-cq7mzB0giI;Z~IuPd| zK@8nA;Nsz$5M!V;jz(0*!i@qEaHhz8t_42D=7FKGO1N{Nkip@@u^1Fg4qhf4t`)Wm z#t;~Rm}qzna1?Bbr^FO02ZnYecm%*k8i4QA6=g9)iY_41wKrDOA?N0H`TMkcS$>^xDv9*ir%Z2ESov0Um=w z7BE~=5am;VFN$D}nX@2dU^vJGM9IQ4m77BPL-TsgKoI>#480(b-$^6i@7d#(dO zFi;L2hlQjYW=pjcf}ze5;0j?D5bfaqVZoI+5J(KXBVr$x16O4#Jo!FCD*TzpFb3E( zL~1Mr8V?OJVI(~l2}3Bugn@8~8fUf3K$|5nr8+o@tB>_S?VuQ7RAhJ!+=d$yo|mqN zTv`}MWwv0Jk$XUh*l*wyvQjv+4}I>}z4O21l#b-leE2Wqf#?4*Q89u0=YMhP{67wV z7CisUhzbq;tLOXKZbH0tbxxqt12i384km)w9P~}OC#9*fnaS`?C@rz128MtRsKYu) z2mB($6@;PtkYjbGXZbo(9e9f1MO0=c9DFW>uWU0&Sa=2upru|PQpOE%F1Qp>_I=kk zZNs);JSEfvcF**LN{O!J(ch?xD`Nm7Z2-~mUocZt#XF@)3{*@MUm{38OQ3+LiP-CPyxu~$l~kdyEggzP{z1zbKtIoOuN zXqpbh1YQq3%~TsHqyoDjRp!Q1gvTL5U`E(LgbC`|itg08D&!je+Dy-g9s-4ptcIQ- zEn1pt8#V>TkP&1-gkTs6j0FT)N1r@y<9Uel5M`pY7gP$@B2~mkjDqWS5E>wuw(<|i zGp`18f-CS z5T*t+u3@*8?J?A6HEmZS$EnTJb&AY~6(IuZ7(1ImNhMMN+uBlkz3#=31w55Zf zqP(Jj12I$s0aLh3wVyDh7Ce!OJp>CN5eqm6sbZxA!-1VvNzB9xfEjF96ll7l6gXuH zDSrNv+X{1zCoxP2;Dmv<(G3gtZm6SW z4dFo|cc^nx+e6U9pd!|D8&78j)?fjkU|)oE51Z;y0gyV(GhN5UaHtVCQ$Arhk5NS7dgGyR|o4^yE^YKB@B01Y>5 zIywP6QP4M#D#7uEo+V);mXzz%G!4xK|bFfH}tDFi|oX}w>{Inp>^!mfWAq#s5$J()N;3azI3wX z6Cq)1s@rYmoZ44;cGFv*Pnt9R!Z+lw4F9!Q;fR<*^(MdGQkFg+vFN#SMo3s_e>jm6 zBg0CBKK1$FkCZR@;JNUw-D5(UXRB4b?E2h>qW{r95|b_XoVB7=sl&CB!gp=FyY!G}Pvv7dd^WJ_4wxK1@m*L_-3IMMl;a6>lz|5`FvHuYHS+Y+H2flUui*s}S~PiKY{3r$+rycKqQ5 z`Q{h?@p%2LHzUSvsrT`PlAk47w|0gPYIZEXZ0;P{8&!RwN8MjSR?W;_pzd%Iv!f)+4Ta_)jHorF13<$sH3qbbjbO@Zk6V-~aqiO#1tO zV`HO&{y$@C@V;yVw;hn%TeWO`a>B%IGn*bOFr?V+t7r8WS58aJ-SWdTZ~XAg%an@TNfO^eE;$pb%qzJ{mTM9EU={3k*ZPF;OUnSmAct~ZM7puqHB!k z{6W?W-JX2v)Qdg5%wA!z{zcuxfA_>5X&qB~CO;An@Id|l!|#8IiBq5djfsyA`u~in za_zwtr;pD{Jyka&GW_vf>W96z*@<{ z?#cbqivBhHe(ztjOGb^`xNhIFL%TmczI;qXs5x(4&FOjSmMctV~?vF7o@*|$G&0C>>cgaVSJG6eO)ZY1Z7Y=JW=<{J`dS-n(@7Hrymzh7hbmG37gR1mR zh^gFQ%A5OhkEk;$!pe1~=X0lKF3k6`SGC*otFKS0ai>uEf8^VG!ik?BN?7RKy%pEp z(N@$bS2gFwa4T=*rwd1HihSWr-ih_S!Fx{?Z?lb@I$dMaq36p#Yj5tk@!IBjXBV%_ z`ph%KCfC_gd+UwPmkOQF!gK7He7AXc@rYTe-#k4(Vw1P|VD%zjeDKbWTFLMAZ+m{3 zJ#1Nxerv`p$Uk=8_RcNrrc-NFSeUKIe0%!J#qT$omwiA&pht~S=iX_#Z1|x`p@*}Q zf_wUZJFLmx7D)@Q)J$IcL-wCqEh@ITR>JKr@n7yaTPkwjt?-gRMI8RR+Lxtcdmrrm z*p}Us2d=E-PR&<%dR*3}bxJRP^0_9Bhps+e_ZTht%$%zUTZazJo~6yPi1|mxtXcG} zdo9aYbKJhN3xAw;K1V`<>4hh}SUm4H1=@tgxdrt*^(@qBR-wwDg^qrf zuHxAW-CXd=TRW@mf457K7k(X8q2|d`$EqgHnY?!R>~#eyB(8ko!>r!deJ>ZQyZ2o6 zOJi5J`=WoDF)x(5-M-1#SqsMuerMbH#-4j8>fHh0l;& zGi!#79QyuejehCVqTr1u=1r?p>Tty=Uan@%3cs3VOk%a4D@DJ%>rlgMi{EokeiQmr z;_djheRGG*JQ3PwQT3ur8?4wFT5`pV>>c~=xRX6sXSe9-dYcZ!l$@^r^VRY-UaA_K z<$9F`G_72gbJt5YDY&FT+ohxHADVl0)~qW_PNfV!JinFyMgQ|xt|t!pI_Ivi$_ z2VSo|VfFspA8$!JJFUzc<(6*Ey+3yF%`Oc~SDd?Wa-e?isZGDBUo2bQ=@Mwmq>|8GfKyLc>)uX?o~9Eos7r;S)d3ai)F#t=%KETrIY@oWCTwQtP&#=APX4 z@_{pLj(_lBtHP@b)i2fV#j1C+jrpO^S1adDT{iO5GcTIjiR_ootP2y_2bOKtaDA_C zJ9n-hzG3y+DX#xg>4kMg(;Y`5W7e&Er_1!~dB%NH_scqCj*Sn^maV{wZ8yqYS~b6U z`+V<@`});Sex7||dWj`kzv3mMUfWT&^|wWP>p$kGRWz*7x+g}AT%nUJvxk5C(hJ$! zYb*05l#K0K`|Oe#+w&JmwwKrKy#1Xwa!u}*cJT1ria+NJ^xe~=^k#EO^^{#yS=!yoFOE>*=>-vApTyn;ldZAB|N@tf>wE5k&m7a^d znlkUpALz!@NB3kqWsa{kwZx;K|3B$JO<+lnzyLhZ|Hs|`{C{j@eERSIi4DI0FJo%Z zrDa?06d!+O)8VWwmmJSOvB$KuhTRUbJ)eDFYl&CxRgbTlb8UIS1}nY|$=at$_*=*K zWcCdQ>tWXahyN}KNi-$33wel1;DP6Vk$>?2G3xw3K0Z1wi2n?!_b1;u{X+Q(v}=PJ zqYj@L7UDlW{@V64Ey&?_YgWou;d#4CYSj4M)6OI}e(bwn=g#Q(YqcJgx5o4?d#+Kh z$>Y1q@eOBP%aPXZqlpLIRi`q0DZ%>R*ProE9{S(?pz4A8|A*iI9vhqf`+ow#_y1>5 z4SVHU{iivjgMd@5$giEDe$UkLuyd4J3L zGyZ!dQI_=3Bfx|8|33cX0!shmVuOGGX9m@~6ORTqRW0+@hRBW)-LHk7NX(mW-Fb8J zmbxT#in%s?{ooOF-`HZ8TCe}*r}A@s+N|csh40AWmp9Zu-M7J(vAI6G((2`sdi9>) zUC-==1S?p<3RbX!6|7(dD_Fq_R msg.MaxPayloadLength(0) { - // Ignore this input - max payload constraint violated - return 0 - } - - // Deserialize the message from the serialized bytes buffer and - // assert that the original message is equal to the newly deserialized message. - newMsg, err := lnwire.ReadMessage(&b, 0) - if err != nil { - // Could not deserialize message from bytes buffer, panic - panic(err) - } - if !reflect.DeepEqual(msg, newMsg) { - // Deserialized message and original message are not deeply equal - panic(fmt.Errorf("Deserialized message and original message " + - "are not deeply equal.")) - } - - return 1 -} From 5a03fe572f8076dcd78d508af979915cae76c71b Mon Sep 17 00:00:00 2001 From: nsa Date: Mon, 3 Feb 2020 20:43:22 -0500 Subject: [PATCH 117/562] lnwire: move zero-length queryBody check to zlib case --- lnwire/query_short_chan_ids.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lnwire/query_short_chan_ids.go b/lnwire/query_short_chan_ids.go index 91f25227a4..76729364ec 100644 --- a/lnwire/query_short_chan_ids.go +++ b/lnwire/query_short_chan_ids.go @@ -148,13 +148,6 @@ func decodeShortChanIDs(r io.Reader) (ShortChanIDEncoding, []ShortChannelID, err // as that was just the encoding type. queryBody = queryBody[1:] - // At this point, if there's no body remaining, then only the encoding - // type was specified, meaning that there're no further bytes to be - // parsed. - if len(queryBody) == 0 { - return encodingType, nil, nil - } - // Otherwise, depending on the encoding type, we'll decode the encode // short channel ID's in a different manner. switch encodingType { @@ -210,6 +203,13 @@ func decodeShortChanIDs(r io.Reader) (ShortChanIDEncoding, []ShortChannelID, err zlibDecodeMtx.Lock() defer zlibDecodeMtx.Unlock() + // At this point, if there's no body remaining, then only the encoding + // type was specified, meaning that there're no further bytes to be + // parsed. + if len(queryBody) == 0 { + return encodingType, nil, nil + } + // Before we start to decode, we'll create a limit reader over // the current reader. This will ensure that we can control how // much memory we're allocating during the decoding process. From 363bdc42b0d8690447080f5c2de11be14a760f95 Mon Sep 17 00:00:00 2001 From: nsa Date: Mon, 3 Feb 2020 20:44:22 -0500 Subject: [PATCH 118/562] fuzz/lnwire: adding fuzz harnesses for all lnwire messages + zlib --- fuzz/lnwire/accept_channel.go | 135 +++++++++++++++++++ fuzz/lnwire/announce_signatures.go | 20 +++ fuzz/lnwire/channel_announcement.go | 20 +++ fuzz/lnwire/channel_reestablish.go | 20 +++ fuzz/lnwire/channel_update.go | 20 +++ fuzz/lnwire/closing_signed.go | 20 +++ fuzz/lnwire/commit_sig.go | 20 +++ fuzz/lnwire/error.go | 20 +++ fuzz/lnwire/funding_created.go | 20 +++ fuzz/lnwire/funding_locked.go | 20 +++ fuzz/lnwire/funding_signed.go | 20 +++ fuzz/lnwire/fuzz_utils.go | 72 +++++++++++ fuzz/lnwire/gossip_timestamp_range.go | 20 +++ fuzz/lnwire/init.go | 20 +++ fuzz/lnwire/node_announcement.go | 112 ++++++++++++++++ fuzz/lnwire/open_channel.go | 151 ++++++++++++++++++++++ fuzz/lnwire/ping.go | 20 +++ fuzz/lnwire/pong.go | 20 +++ fuzz/lnwire/query_channel_range.go | 20 +++ fuzz/lnwire/query_short_chan_ids.go | 20 +++ fuzz/lnwire/query_short_chan_ids_zlib.go | 51 ++++++++ fuzz/lnwire/reply_channel_range.go | 20 +++ fuzz/lnwire/reply_channel_range_zlib.go | 59 +++++++++ fuzz/lnwire/reply_short_chan_ids_end.go | 20 +++ fuzz/lnwire/revoke_and_ack.go | 20 +++ fuzz/lnwire/shutdown.go | 20 +++ fuzz/lnwire/update_add_htlc.go | 20 +++ fuzz/lnwire/update_fail_htlc.go | 20 +++ fuzz/lnwire/update_fail_malformed_htlc.go | 20 +++ fuzz/lnwire/update_fee.go | 20 +++ fuzz/lnwire/update_fulfill_htlc.go | 20 +++ 31 files changed, 1080 insertions(+) create mode 100644 fuzz/lnwire/accept_channel.go create mode 100644 fuzz/lnwire/announce_signatures.go create mode 100644 fuzz/lnwire/channel_announcement.go create mode 100644 fuzz/lnwire/channel_reestablish.go create mode 100644 fuzz/lnwire/channel_update.go create mode 100644 fuzz/lnwire/closing_signed.go create mode 100644 fuzz/lnwire/commit_sig.go create mode 100644 fuzz/lnwire/error.go create mode 100644 fuzz/lnwire/funding_created.go create mode 100644 fuzz/lnwire/funding_locked.go create mode 100644 fuzz/lnwire/funding_signed.go create mode 100644 fuzz/lnwire/fuzz_utils.go create mode 100644 fuzz/lnwire/gossip_timestamp_range.go create mode 100644 fuzz/lnwire/init.go create mode 100644 fuzz/lnwire/node_announcement.go create mode 100644 fuzz/lnwire/open_channel.go create mode 100644 fuzz/lnwire/ping.go create mode 100644 fuzz/lnwire/pong.go create mode 100644 fuzz/lnwire/query_channel_range.go create mode 100644 fuzz/lnwire/query_short_chan_ids.go create mode 100644 fuzz/lnwire/query_short_chan_ids_zlib.go create mode 100644 fuzz/lnwire/reply_channel_range.go create mode 100644 fuzz/lnwire/reply_channel_range_zlib.go create mode 100644 fuzz/lnwire/reply_short_chan_ids_end.go create mode 100644 fuzz/lnwire/revoke_and_ack.go create mode 100644 fuzz/lnwire/shutdown.go create mode 100644 fuzz/lnwire/update_add_htlc.go create mode 100644 fuzz/lnwire/update_fail_htlc.go create mode 100644 fuzz/lnwire/update_fail_malformed_htlc.go create mode 100644 fuzz/lnwire/update_fee.go create mode 100644 fuzz/lnwire/update_fulfill_htlc.go diff --git a/fuzz/lnwire/accept_channel.go b/fuzz/lnwire/accept_channel.go new file mode 100644 index 0000000000..1f70282508 --- /dev/null +++ b/fuzz/lnwire/accept_channel.go @@ -0,0 +1,135 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "bytes" + + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_accept_channel is used by go-fuzz. +func Fuzz_accept_channel(data []byte) int { + // Prefix with MsgAcceptChannel. + data = prefixWithMsgType(data, lnwire.MsgAcceptChannel) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.AcceptChannel{} + + // We have to do this here instead of in fuzz.Harness so that + // reflect.DeepEqual isn't called. Because of the UpfrontShutdownScript + // encoding, the first message and second message aren't deeply equal since + // the first has a nil slice and the other has an empty slice. + + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Make sure byte array length (excluding 2 bytes for message type) is + // less than max payload size for the wire message. We check this because + // otherwise `go-fuzz` will keep creating inputs that crash on ReadMessage + // due to a large message size. + payloadLen := uint32(len(data)) - 2 + if payloadLen > emptyMsg.MaxPayloadLength(0) { + // Ignore this input - max payload constraint violated. + return -1 + } + + msg, err := lnwire.ReadMessage(r, 0) + if err != nil { + // go-fuzz generated []byte that cannot be represented as a + // wire message but we will return 0 so go-fuzz can modify the + // input. + return 0 + } + + // We will serialize the message into a new bytes buffer. + var b bytes.Buffer + if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil { + // Could not serialize message into bytes buffer, panic + panic(err) + } + + // Deserialize the message from the serialized bytes buffer, and then + // assert that the original message is equal to the newly deserialized + // message. + newMsg, err := lnwire.ReadMessage(&b, 0) + if err != nil { + // Could not deserialize message from bytes buffer, panic + panic(err) + } + + // Now compare every field instead of using reflect.DeepEqual. + // For UpfrontShutdownScript, we only compare bytes. This probably takes + // up more branches than necessary, but that's fine for now. + var shouldPanic bool + first := msg.(*lnwire.AcceptChannel) + second := newMsg.(*lnwire.AcceptChannel) + + if !bytes.Equal(first.PendingChannelID[:], second.PendingChannelID[:]) { + shouldPanic = true + } + + if first.DustLimit != second.DustLimit { + shouldPanic = true + } + + if first.MaxValueInFlight != second.MaxValueInFlight { + shouldPanic = true + } + + if first.ChannelReserve != second.ChannelReserve { + shouldPanic = true + } + + if first.HtlcMinimum != second.HtlcMinimum { + shouldPanic = true + } + + if first.MinAcceptDepth != second.MinAcceptDepth { + shouldPanic = true + } + + if first.CsvDelay != second.CsvDelay { + shouldPanic = true + } + + if first.MaxAcceptedHTLCs != second.MaxAcceptedHTLCs { + shouldPanic = true + } + + if !first.FundingKey.IsEqual(second.FundingKey) { + shouldPanic = true + } + + if !first.RevocationPoint.IsEqual(second.RevocationPoint) { + shouldPanic = true + } + + if !first.PaymentPoint.IsEqual(second.PaymentPoint) { + shouldPanic = true + } + + if !first.DelayedPaymentPoint.IsEqual(second.DelayedPaymentPoint) { + shouldPanic = true + } + + if !first.HtlcPoint.IsEqual(second.HtlcPoint) { + shouldPanic = true + } + + if !first.FirstCommitmentPoint.IsEqual(second.FirstCommitmentPoint) { + shouldPanic = true + } + + if !bytes.Equal(first.UpfrontShutdownScript, second.UpfrontShutdownScript) { + shouldPanic = true + } + + if shouldPanic { + panic("original message and deserialized message are not equal") + } + + // Add this input to the corpus. + return 1 +} diff --git a/fuzz/lnwire/announce_signatures.go b/fuzz/lnwire/announce_signatures.go new file mode 100644 index 0000000000..048cf5abe5 --- /dev/null +++ b/fuzz/lnwire/announce_signatures.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_announce_signatures is used by go-fuzz. +func Fuzz_announce_signatures(data []byte) int { + // Prefix with MsgAnnounceSignatures. + data = prefixWithMsgType(data, lnwire.MsgAnnounceSignatures) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.AnnounceSignatures{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/channel_announcement.go b/fuzz/lnwire/channel_announcement.go new file mode 100644 index 0000000000..771df5d1ca --- /dev/null +++ b/fuzz/lnwire/channel_announcement.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_channel_announcement is used by go-fuzz. +func Fuzz_channel_announcement(data []byte) int { + // Prefix with MsgChannelAnnouncement. + data = prefixWithMsgType(data, lnwire.MsgChannelAnnouncement) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.ChannelAnnouncement{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/channel_reestablish.go b/fuzz/lnwire/channel_reestablish.go new file mode 100644 index 0000000000..08cca9a560 --- /dev/null +++ b/fuzz/lnwire/channel_reestablish.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_channel_reestablish is used by go-fuzz. +func Fuzz_channel_reestablish(data []byte) int { + // Prefix with MsgChannelReestablish. + data = prefixWithMsgType(data, lnwire.MsgChannelReestablish) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.ChannelReestablish{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/channel_update.go b/fuzz/lnwire/channel_update.go new file mode 100644 index 0000000000..993181f7be --- /dev/null +++ b/fuzz/lnwire/channel_update.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_channel_update is used by go-fuzz. +func Fuzz_channel_update(data []byte) int { + // Prefix with MsgChannelUpdate. + data = prefixWithMsgType(data, lnwire.MsgChannelUpdate) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.ChannelUpdate{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/closing_signed.go b/fuzz/lnwire/closing_signed.go new file mode 100644 index 0000000000..b6898a7cb8 --- /dev/null +++ b/fuzz/lnwire/closing_signed.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_closing_signed is used by go-fuzz. +func Fuzz_closing_signed(data []byte) int { + // Prefix with MsgClosingSigned. + data = prefixWithMsgType(data, lnwire.MsgClosingSigned) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.ClosingSigned{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/commit_sig.go b/fuzz/lnwire/commit_sig.go new file mode 100644 index 0000000000..6f9c76ec10 --- /dev/null +++ b/fuzz/lnwire/commit_sig.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_commit_sig is used by go-fuzz. +func Fuzz_commit_sig(data []byte) int { + // Prefix with MsgCommitSig. + data = prefixWithMsgType(data, lnwire.MsgCommitSig) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.CommitSig{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/error.go b/fuzz/lnwire/error.go new file mode 100644 index 0000000000..8b5dd671a1 --- /dev/null +++ b/fuzz/lnwire/error.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_error is used by go-fuzz. +func Fuzz_error(data []byte) int { + // Prefix with MsgError. + data = prefixWithMsgType(data, lnwire.MsgError) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.Error{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/funding_created.go b/fuzz/lnwire/funding_created.go new file mode 100644 index 0000000000..ffdb3390a2 --- /dev/null +++ b/fuzz/lnwire/funding_created.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_funding_created is used by go-fuzz. +func Fuzz_funding_created(data []byte) int { + // Prefix with MsgFundingCreated. + data = prefixWithMsgType(data, lnwire.MsgFundingCreated) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.FundingCreated{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/funding_locked.go b/fuzz/lnwire/funding_locked.go new file mode 100644 index 0000000000..aa5d2c26d2 --- /dev/null +++ b/fuzz/lnwire/funding_locked.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_funding_locked is used by go-fuzz. +func Fuzz_funding_locked(data []byte) int { + // Prefix with MsgFundingLocked. + data = prefixWithMsgType(data, lnwire.MsgFundingLocked) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.FundingLocked{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/funding_signed.go b/fuzz/lnwire/funding_signed.go new file mode 100644 index 0000000000..47f2bfd061 --- /dev/null +++ b/fuzz/lnwire/funding_signed.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_funding_signed is used by go-fuzz. +func Fuzz_funding_signed(data []byte) int { + // Prefix with MsgFundingSigned. + prefixWithMsgType(data, lnwire.MsgFundingSigned) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.FundingSigned{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/fuzz_utils.go b/fuzz/lnwire/fuzz_utils.go new file mode 100644 index 0000000000..767f602abb --- /dev/null +++ b/fuzz/lnwire/fuzz_utils.go @@ -0,0 +1,72 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "bytes" + "encoding/binary" + "reflect" + + "github.com/lightningnetwork/lnd/lnwire" +) + +// prefixWithMsgType takes []byte and adds a wire protocol prefix +// to make the []byte into an actual message to be used in fuzzing. +func prefixWithMsgType(data []byte, prefix lnwire.MessageType) []byte { + var prefixBytes [2]byte + binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix)) + data = append(prefixBytes[:], data...) + return data +} + +// harness performs the actual fuzz testing of the appropriate wire message. +// This function will check that the passed-in message passes wire length checks, +// is a valid message once deserialized, and passes a sequence of serialization +// and deserialization checks. Returns an int that determines whether the input +// is unique or not. +func harness(data []byte, emptyMsg lnwire.Message) int { + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Make sure byte array length (excluding 2 bytes for message type) is + // less than max payload size for the wire message. We check this because + // otherwise `go-fuzz` will keep creating inputs that crash on ReadMessage + // due to a large message size. + payloadLen := uint32(len(data)) - 2 + if payloadLen > emptyMsg.MaxPayloadLength(0) { + // Ignore this input - max payload constraint violated. + return -1 + } + + msg, err := lnwire.ReadMessage(r, 0) + if err != nil { + // go-fuzz generated []byte that cannot be represented as a + // wire message but we will return 0 so go-fuzz can modify the + // input. + return 0 + } + + // We will serialize the message into a new bytes buffer. + var b bytes.Buffer + if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil { + // Could not serialize message into bytes buffer, panic + panic(err) + } + + // Deserialize the message from the serialized bytes buffer, and then + // assert that the original message is equal to the newly deserialized + // message. + newMsg, err := lnwire.ReadMessage(&b, 0) + if err != nil { + // Could not deserialize message from bytes buffer, panic + panic(err) + } + + if !reflect.DeepEqual(msg, newMsg) { + // Deserialized message and original message are not deeply equal. + panic("original message and deserialized message are not deeply equal") + } + + // Add this input to the corpus. + return 1 +} diff --git a/fuzz/lnwire/gossip_timestamp_range.go b/fuzz/lnwire/gossip_timestamp_range.go new file mode 100644 index 0000000000..9e5e4f11aa --- /dev/null +++ b/fuzz/lnwire/gossip_timestamp_range.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_gossip_timestamp_range is used by go-fuzz. +func Fuzz_gossip_timestamp_range(data []byte) int { + // Prefix with MsgGossipTimestampRange. + data = prefixWithMsgType(data, lnwire.MsgGossipTimestampRange) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.GossipTimestampRange{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/init.go b/fuzz/lnwire/init.go new file mode 100644 index 0000000000..b2be1aba3e --- /dev/null +++ b/fuzz/lnwire/init.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_init is used by go-fuzz. +func Fuzz_init(data []byte) int { + // Prefix with MsgInit. + data = prefixWithMsgType(data, lnwire.MsgInit) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.Init{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/node_announcement.go b/fuzz/lnwire/node_announcement.go new file mode 100644 index 0000000000..76eabe351c --- /dev/null +++ b/fuzz/lnwire/node_announcement.go @@ -0,0 +1,112 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "bytes" + "reflect" + + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_node_announcement is used by go-fuzz. +func Fuzz_node_announcement(data []byte) int { + // Prefix with MsgNodeAnnouncement. + data = prefixWithMsgType(data, lnwire.MsgNodeAnnouncement) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.NodeAnnouncement{} + + // We have to do this here instead of in fuzz.Harness so that + // reflect.DeepEqual isn't called. Address (de)serialization messes up + // the fuzzing assertions. + + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Make sure byte array length (excluding 2 bytes for message type) is + // less than max payload size for the wire message. We check this because + // otherwise `go-fuzz` will keep creating inputs that crash on ReadMessage + // due to a large message size. + payloadLen := uint32(len(data)) - 2 + if payloadLen > emptyMsg.MaxPayloadLength(0) { + // Ignore this input - max payload constraint violated. + return -1 + } + + msg, err := lnwire.ReadMessage(r, 0) + if err != nil { + // go-fuzz generated []byte that cannot be represented as a + // wire message but we will return 0 so go-fuzz can modify the + // input. + return 0 + } + + // We will serialize the message into a new bytes buffer. + var b bytes.Buffer + if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil { + // Could not serialize message into bytes buffer, panic + panic(err) + } + + // Deserialize the message from the serialized bytes buffer, and then + // assert that the original message is equal to the newly deserialized + // message. + newMsg, err := lnwire.ReadMessage(&b, 0) + if err != nil { + // Could not deserialize message from bytes buffer, panic + panic(err) + } + + // Now compare every field instead of using reflect.DeepEqual for the + // Addresses field. + var shouldPanic bool + first := msg.(*lnwire.NodeAnnouncement) + second := newMsg.(*lnwire.NodeAnnouncement) + if !bytes.Equal(first.Signature[:], second.Signature[:]) { + shouldPanic = true + } + + if !reflect.DeepEqual(first.Features, second.Features) { + shouldPanic = true + } + + if first.Timestamp != second.Timestamp { + shouldPanic = true + } + + if !bytes.Equal(first.NodeID[:], second.NodeID[:]) { + shouldPanic = true + } + + if !reflect.DeepEqual(first.RGBColor, second.RGBColor) { + shouldPanic = true + } + + if !bytes.Equal(first.Alias[:], second.Alias[:]) { + shouldPanic = true + } + + if len(first.Addresses) != len(second.Addresses) { + shouldPanic = true + } + + for i := range first.Addresses { + if first.Addresses[i].String() != second.Addresses[i].String() { + shouldPanic = true + break + } + } + + if !reflect.DeepEqual(first.ExtraOpaqueData, second.ExtraOpaqueData) { + shouldPanic = true + } + + if shouldPanic { + panic("original message and deserialized message are not equal") + } + + // Add this input to the corpus. + return 1 +} diff --git a/fuzz/lnwire/open_channel.go b/fuzz/lnwire/open_channel.go new file mode 100644 index 0000000000..ddd268cc28 --- /dev/null +++ b/fuzz/lnwire/open_channel.go @@ -0,0 +1,151 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "bytes" + + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_open_channel is used by go-fuzz. +func Fuzz_open_channel(data []byte) int { + // Prefix with MsgOpenChannel. + data = prefixWithMsgType(data, lnwire.MsgOpenChannel) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.OpenChannel{} + + // We have to do this here instead of in fuzz.Harness so that + // reflect.DeepEqual isn't called. Because of the UpfrontShutdownScript + // encoding, the first message and second message aren't deeply equal since + // the first has a nil slice and the other has an empty slice. + + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Make sure byte array length (excluding 2 bytes for message type) is + // less than max payload size for the wire message. We check this because + // otherwise `go-fuzz` will keep creating inputs that crash on ReadMessage + // due to a large message size. + payloadLen := uint32(len(data)) - 2 + if payloadLen > emptyMsg.MaxPayloadLength(0) { + // Ignore this input - max payload constraint violated. + return -1 + } + + msg, err := lnwire.ReadMessage(r, 0) + if err != nil { + // go-fuzz generated []byte that cannot be represented as a + // wire message but we will return 0 so go-fuzz can modify the + // input. + return 0 + } + + // We will serialize the message into a new bytes buffer. + var b bytes.Buffer + if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil { + // Could not serialize message into bytes buffer, panic + panic(err) + } + + // Deserialize the message from the serialized bytes buffer, and then + // assert that the original message is equal to the newly deserialized + // message. + newMsg, err := lnwire.ReadMessage(&b, 0) + if err != nil { + // Could not deserialize message from bytes buffer, panic + panic(err) + } + + // Now compare every field instead of using reflect.DeepEqual. + // For UpfrontShutdownScript, we only compare bytes. This probably takes + // up more branches than necessary, but that's fine for now. + var shouldPanic bool + first := msg.(*lnwire.OpenChannel) + second := newMsg.(*lnwire.OpenChannel) + + if !first.ChainHash.IsEqual(&second.ChainHash) { + shouldPanic = true + } + + if !bytes.Equal(first.PendingChannelID[:], second.PendingChannelID[:]) { + shouldPanic = true + } + + if first.FundingAmount != second.FundingAmount { + shouldPanic = true + } + + if first.PushAmount != second.PushAmount { + shouldPanic = true + } + + if first.DustLimit != second.DustLimit { + shouldPanic = true + } + + if first.MaxValueInFlight != second.MaxValueInFlight { + shouldPanic = true + } + + if first.ChannelReserve != second.ChannelReserve { + shouldPanic = true + } + + if first.HtlcMinimum != second.HtlcMinimum { + shouldPanic = true + } + + if first.FeePerKiloWeight != second.FeePerKiloWeight { + shouldPanic = true + } + + if first.CsvDelay != second.CsvDelay { + shouldPanic = true + } + + if first.MaxAcceptedHTLCs != second.MaxAcceptedHTLCs { + shouldPanic = true + } + + if !first.FundingKey.IsEqual(second.FundingKey) { + shouldPanic = true + } + + if !first.RevocationPoint.IsEqual(second.RevocationPoint) { + shouldPanic = true + } + + if !first.PaymentPoint.IsEqual(second.PaymentPoint) { + shouldPanic = true + } + + if !first.DelayedPaymentPoint.IsEqual(second.DelayedPaymentPoint) { + shouldPanic = true + } + + if !first.HtlcPoint.IsEqual(second.HtlcPoint) { + shouldPanic = true + } + + if !first.FirstCommitmentPoint.IsEqual(second.FirstCommitmentPoint) { + shouldPanic = true + } + + if first.ChannelFlags != second.ChannelFlags { + shouldPanic = true + } + + if !bytes.Equal(first.UpfrontShutdownScript, second.UpfrontShutdownScript) { + shouldPanic = true + } + + if shouldPanic { + panic("original message and deserialized message are not equal") + } + + // Add this input to the corpus. + return 1 +} diff --git a/fuzz/lnwire/ping.go b/fuzz/lnwire/ping.go new file mode 100644 index 0000000000..87e893e060 --- /dev/null +++ b/fuzz/lnwire/ping.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_ping is used by go-fuzz. +func Fuzz_ping(data []byte) int { + // Prefix with MsgPing. + data = prefixWithMsgType(data, lnwire.MsgPing) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.Ping{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/pong.go b/fuzz/lnwire/pong.go new file mode 100644 index 0000000000..b51e315249 --- /dev/null +++ b/fuzz/lnwire/pong.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_pong is used by go-fuzz. +func Fuzz_pong(data []byte) int { + // Prefix with MsgPong. + data = prefixWithMsgType(data, lnwire.MsgPong) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.Pong{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/query_channel_range.go b/fuzz/lnwire/query_channel_range.go new file mode 100644 index 0000000000..38f5f4d7b6 --- /dev/null +++ b/fuzz/lnwire/query_channel_range.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_query_channel_range is used by go-fuzz. +func Fuzz_query_channel_range(data []byte) int { + // Prefix with MsgQueryChannelRange. + data = prefixWithMsgType(data, lnwire.MsgQueryChannelRange) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.QueryChannelRange{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/query_short_chan_ids.go b/fuzz/lnwire/query_short_chan_ids.go new file mode 100644 index 0000000000..b0adb87920 --- /dev/null +++ b/fuzz/lnwire/query_short_chan_ids.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_query_short_chan_ids is used by go-fuzz. +func Fuzz_query_short_chan_ids(data []byte) int { + // Prefix with MsgQueryShortChanIDs. + data = prefixWithMsgType(data, lnwire.MsgQueryShortChanIDs) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.QueryShortChanIDs{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/query_short_chan_ids_zlib.go b/fuzz/lnwire/query_short_chan_ids_zlib.go new file mode 100644 index 0000000000..7b2061d77d --- /dev/null +++ b/fuzz/lnwire/query_short_chan_ids_zlib.go @@ -0,0 +1,51 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "bytes" + "compress/zlib" + "encoding/binary" + + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_query_short_chan_ids_zlib is used by go-fuzz. +func Fuzz_query_short_chan_ids_zlib(data []byte) int { + + var buf bytes.Buffer + zlibWriter := zlib.NewWriter(&buf) + _, err := zlibWriter.Write(data) + if err != nil { + // Zlib bug? + panic(err) + } + + if err := zlibWriter.Close(); err != nil { + // Zlib bug? + panic(err) + } + + compressedPayload := buf.Bytes() + + chainhash := []byte("00000000000000000000000000000000") + numBytesInBody := len(compressedPayload) + 1 + zlibByte := []byte("\x01") + + bodyBytes := make([]byte, 2) + binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody)) + + payload := append(chainhash, bodyBytes...) + payload = append(payload, zlibByte...) + payload = append(payload, compressedPayload...) + + // Prefix with MsgQueryShortChanIDs. + payload = prefixWithMsgType(payload, lnwire.MsgQueryShortChanIDs) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.QueryShortChanIDs{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(payload, &emptyMsg) +} diff --git a/fuzz/lnwire/reply_channel_range.go b/fuzz/lnwire/reply_channel_range.go new file mode 100644 index 0000000000..3bfdbf3623 --- /dev/null +++ b/fuzz/lnwire/reply_channel_range.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_reply_channel_range is used by go-fuzz. +func Fuzz_reply_channel_range(data []byte) int { + // Prefix with MsgReplyChannelRange. + data = prefixWithMsgType(data, lnwire.MsgReplyChannelRange) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.ReplyChannelRange{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/reply_channel_range_zlib.go b/fuzz/lnwire/reply_channel_range_zlib.go new file mode 100644 index 0000000000..944d1fa1af --- /dev/null +++ b/fuzz/lnwire/reply_channel_range_zlib.go @@ -0,0 +1,59 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "bytes" + "compress/zlib" + "encoding/binary" + + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_reply_channel_range_zlib is used by go-fuzz. +func Fuzz_reply_channel_range_zlib(data []byte) int { + + var buf bytes.Buffer + zlibWriter := zlib.NewWriter(&buf) + _, err := zlibWriter.Write(data) + if err != nil { + // Zlib bug? + panic(err) + } + + if err := zlibWriter.Close(); err != nil { + // Zlib bug? + panic(err) + } + + compressedPayload := buf.Bytes() + + // Initialize some []byte vars which will prefix our payload + chainhash := []byte("00000000000000000000000000000000") + firstBlockHeight := []byte("\x00\x00\x00\x00") + numBlocks := []byte("\x00\x00\x00\x00") + completeByte := []byte("\x00") + + numBytesInBody := len(compressedPayload) + 1 + zlibByte := []byte("\x01") + + bodyBytes := make([]byte, 2) + binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody)) + + payload := append(chainhash, firstBlockHeight...) + payload = append(payload, numBlocks...) + payload = append(payload, completeByte...) + payload = append(payload, bodyBytes...) + payload = append(payload, zlibByte...) + payload = append(payload, compressedPayload...) + + // Prefix with MsgReplyChannelRange. + payload = prefixWithMsgType(payload, lnwire.MsgReplyChannelRange) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.ReplyChannelRange{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(payload, &emptyMsg) +} diff --git a/fuzz/lnwire/reply_short_chan_ids_end.go b/fuzz/lnwire/reply_short_chan_ids_end.go new file mode 100644 index 0000000000..c09282d9a5 --- /dev/null +++ b/fuzz/lnwire/reply_short_chan_ids_end.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_reply_short_chan_ids_end is used by go-fuzz. +func Fuzz_reply_short_chan_ids_end(data []byte) int { + // Prefix with MsgReplyShortChanIDsEnd. + data = prefixWithMsgType(data, lnwire.MsgReplyShortChanIDsEnd) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.ReplyShortChanIDsEnd{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/revoke_and_ack.go b/fuzz/lnwire/revoke_and_ack.go new file mode 100644 index 0000000000..23951c356e --- /dev/null +++ b/fuzz/lnwire/revoke_and_ack.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_revoke_and_ack is used by go-fuzz. +func Fuzz_revoke_and_ack(data []byte) int { + // Prefix with MsgRevokeAndAck. + data = prefixWithMsgType(data, lnwire.MsgRevokeAndAck) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.RevokeAndAck{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/shutdown.go b/fuzz/lnwire/shutdown.go new file mode 100644 index 0000000000..1ffd86606e --- /dev/null +++ b/fuzz/lnwire/shutdown.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_shutdown is used by go-fuzz. +func Fuzz_shutdown(data []byte) int { + // Prefix with MsgShutdown. + data = prefixWithMsgType(data, lnwire.MsgShutdown) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.Shutdown{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/update_add_htlc.go b/fuzz/lnwire/update_add_htlc.go new file mode 100644 index 0000000000..570de7418f --- /dev/null +++ b/fuzz/lnwire/update_add_htlc.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_update_add_htlc is used by go-fuzz. +func Fuzz_update_add_htlc(data []byte) int { + // Prefix with MsgUpdateAddHTLC. + data = prefixWithMsgType(data, lnwire.MsgUpdateAddHTLC) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.UpdateAddHTLC{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/update_fail_htlc.go b/fuzz/lnwire/update_fail_htlc.go new file mode 100644 index 0000000000..4ef9ab88d7 --- /dev/null +++ b/fuzz/lnwire/update_fail_htlc.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_update_fail_htlc is used by go-fuzz. +func Fuzz_update_fail_htlc(data []byte) int { + // Prefix with MsgUpdateFailHTLC. + data = prefixWithMsgType(data, lnwire.MsgUpdateFailHTLC) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.UpdateFailHTLC{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/update_fail_malformed_htlc.go b/fuzz/lnwire/update_fail_malformed_htlc.go new file mode 100644 index 0000000000..0a0d45a6f5 --- /dev/null +++ b/fuzz/lnwire/update_fail_malformed_htlc.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_update_fail_malformed_htlc is used by go-fuzz. +func Fuzz_update_fail_malformed_htlc(data []byte) int { + // Prefix with MsgUpdateFailMalformedHTLC. + data = prefixWithMsgType(data, lnwire.MsgUpdateFailMalformedHTLC) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.UpdateFailMalformedHTLC{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/update_fee.go b/fuzz/lnwire/update_fee.go new file mode 100644 index 0000000000..bb82c5c19f --- /dev/null +++ b/fuzz/lnwire/update_fee.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_update_fee is used by go-fuzz. +func Fuzz_update_fee(data []byte) int { + // Prefix with MsgUpdateFee. + data = prefixWithMsgType(data, lnwire.MsgUpdateFee) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.UpdateFee{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} diff --git a/fuzz/lnwire/update_fulfill_htlc.go b/fuzz/lnwire/update_fulfill_htlc.go new file mode 100644 index 0000000000..de28dfbe1a --- /dev/null +++ b/fuzz/lnwire/update_fulfill_htlc.go @@ -0,0 +1,20 @@ +// +build gofuzz + +package lnwirefuzz + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// Fuzz_update_fulfill_htlc is used by go-fuzz. +func Fuzz_update_fulfill_htlc(data []byte) int { + // Prefix with MsgUpdateFulfillHTLC. + data = prefixWithMsgType(data, lnwire.MsgUpdateFulfillHTLC) + + // Create an empty message so that the FuzzHarness func can check + // if the max payload constraint is violated. + emptyMsg := lnwire.UpdateFulfillHTLC{} + + // Pass the message into our general fuzz harness for wire messages! + return harness(data, &emptyMsg) +} From 03a070659315b18a9c350f9d8498e22e9681d16e Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 25 Feb 2020 12:20:17 -0300 Subject: [PATCH 119/562] chancloser: unregister channel before db modification This fixes a race during channel closing, where the last channel state update was still not finished when we set the channel close bit in the database. This lead to a flake during integration tests, where the last state update would not finish, and the channel wasn't closes successfully. We fix it by first unregistering the channel, making sure it is removed fully from the link before doing the db modification. --- chancloser.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/chancloser.go b/chancloser.go index 00dff1bf74..bcd0ec8bde 100644 --- a/chancloser.go +++ b/chancloser.go @@ -223,6 +223,10 @@ func (c *channelCloser) initChanShutdown() (*lnwire.Shutdown, error) { "close: %v", c.chanPoint, err) } + // Before returning the shutdown message, we'll unregister the channel + // to ensure that it isn't seen as usable within the system. + c.cfg.unregisterChannel(c.cid) + // Before continuing, mark the channel as cooperatively closed with a // nil txn. Even though we haven't negotiated the final txn, this // guarantees that our listchannels rpc will be externally consistent, @@ -233,12 +237,6 @@ func (c *channelCloser) initChanShutdown() (*lnwire.Shutdown, error) { return nil, err } - // Before returning the shutdown message, we'll unregister the channel - // to ensure that it isn't seen as usable within the system. - // - // TODO(roasbeef): fail if err? - c.cfg.unregisterChannel(c.cid) - peerLog.Infof("ChannelPoint(%v): sending shutdown message", c.chanPoint) return shutdown, nil From d8c62c37a85a2b9e366ce9f9e940537e805f0bcf Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 10 Feb 2020 11:37:44 +0100 Subject: [PATCH 120/562] channel_notifier: update backup on pending chan To fix the discrepancy between getting the channel backups via RPC where all pending channels are included, we also update the channel.backup file on disk whenever we get a pending channel event notification. --- channel_notifier.go | 69 ++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/channel_notifier.go b/channel_notifier.go index 36a2224a0b..960ba0d9da 100644 --- a/channel_notifier.go +++ b/channel_notifier.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chanbackup" + "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channelnotifier" ) @@ -51,6 +52,35 @@ func (c *channelNotifier) SubscribeChans(startingChans map[wire.OutPoint]struct{ quit := make(chan struct{}) chanUpdates := make(chan chanbackup.ChannelEvent, 1) + // sendChanOpenUpdate is a closure that sends a ChannelEvent to the + // chanUpdates channel to inform subscribers about new pending or + // confirmed channels. + sendChanOpenUpdate := func(newOrPendingChan *channeldb.OpenChannel) { + nodeAddrs, err := c.addrs.AddrsForNode( + newOrPendingChan.IdentityPub, + ) + if err != nil { + pub := newOrPendingChan.IdentityPub + ltndLog.Errorf("unable to fetch addrs for %x: %v", + pub.SerializeCompressed(), err) + } + + chanEvent := chanbackup.ChannelEvent{ + NewChans: []chanbackup.ChannelWithAddrs{ + { + OpenChannel: newOrPendingChan, + Addrs: nodeAddrs, + }, + }, + } + + select { + case chanUpdates <- chanEvent: + case <-quit: + return + } + } + // In order to adhere to the interface, we'll proxy the events from the // channel notifier to the sub-swapper in a format it understands. go func() { @@ -74,37 +104,18 @@ func (c *channelNotifier) SubscribeChans(startingChans map[wire.OutPoint]struct{ // TODO(roasbeef): batch dispatch ntnfs switch event := e.(type) { - - // A new channel has been opened, we'll obtain - // the node address, then send to the + // A new channel has been opened and is still + // pending. We can still create a backup, even + // if the final channel ID is not yet available. + case channelnotifier.PendingOpenChannelEvent: + pendingChan := event.PendingChannel + sendChanOpenUpdate(pendingChan) + + // A new channel has been confirmed, we'll + // obtain the node address, then send to the // sub-swapper. case channelnotifier.OpenChannelEvent: - nodeAddrs, err := c.addrs.AddrsForNode( - event.Channel.IdentityPub, - ) - if err != nil { - pub := event.Channel.IdentityPub - ltndLog.Errorf("unable to "+ - "fetch addrs for %x: %v", - pub.SerializeCompressed(), - err) - } - - channel := event.Channel - chanEvent := chanbackup.ChannelEvent{ - NewChans: []chanbackup.ChannelWithAddrs{ - { - OpenChannel: channel, - Addrs: nodeAddrs, - }, - }, - } - - select { - case chanUpdates <- chanEvent: - case <-quit: - return - } + sendChanOpenUpdate(event.Channel) // An existing channel has been closed, we'll // send only the chanPoint of the closed From 8a2c02f8eadb2a392853ca67162a23f9684d8cc3 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 10 Feb 2020 17:04:25 +0100 Subject: [PATCH 121/562] itest: test unconfirmed channel backup file --- lntest/itest/lnd_test.go | 63 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index c18b60d9a8..dfe5ee1004 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -13987,6 +13987,21 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness, t.Fatalf("couldn't open pending channel: %v", err) } + // Give the pubsub some time to update the channel backup. + err = wait.NoError(func() error { + fi, err := os.Stat(dave.ChanBackupPath()) + if err != nil { + return err + } + if fi.Size() <= chanbackup.NilMultiSizePacked { + return fmt.Errorf("backup file empty") + } + return nil + }, defaultTimeout) + if err != nil { + t.Fatalf("channel backup not updated in time: %v", err) + } + default: ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) chanPoint := openChannelAndAssert( @@ -14203,7 +14218,7 @@ func testChannelBackupRestore(net *lntest.NetworkHarness, t *harnessTest) { mnemonic []string) (nodeRestorer, error) { // Read the entire Multi backup stored within - // this node's chaannels.backup file. + // this node's channels.backup file. multi, err := ioutil.ReadFile(backupFilePath) if err != nil { return nil, err @@ -14312,7 +14327,7 @@ func testChannelBackupRestore(net *lntest.NetworkHarness, t *harnessTest) { mnemonic []string) (nodeRestorer, error) { // Read the entire Multi backup stored within - // this node's chaannels.backup file. + // this node's channels.backup file. multi, err := ioutil.ReadFile(backupFilePath) if err != nil { return nil, err @@ -14367,10 +14382,48 @@ func testChannelBackupRestore(net *lntest.NetworkHarness, t *harnessTest) { }, }, - // Create a backup from an unconfirmed channel and make sure - // recovery works as well. + // Use the channel backup file that contains an unconfirmed + // channel and make sure recovery works as well. + { + name: "restore unconfirmed channel file", + channelsUpdated: false, + initiator: true, + private: false, + unconfirmed: true, + restoreMethod: func(oldNode *lntest.HarnessNode, + backupFilePath string, + mnemonic []string) (nodeRestorer, error) { + + // Read the entire Multi backup stored within + // this node's channels.backup file. + multi, err := ioutil.ReadFile(backupFilePath) + if err != nil { + return nil, err + } + + // Let's assume time passes, the channel + // confirms in the meantime but for some reason + // the backup we made while it was still + // unconfirmed is the only backup we have. We + // should still be able to restore it. To + // simulate time passing, we mine some blocks + // to get the channel confirmed _after_ we saved + // the backup. + mineBlocks(t, net, 6, 1) + + // In our nodeRestorer function, we'll restore + // the node from seed, then manually recover + // the channel backup. + return chanRestoreViaRPC( + net, password, mnemonic, multi, + ) + }, + }, + + // Create a backup using RPC that contains an unconfirmed + // channel and make sure recovery works as well. { - name: "restore unconfirmed channel", + name: "restore unconfirmed channel RPC", channelsUpdated: false, initiator: true, private: false, From 4e0c276154024aae36d5bdf2b3ece6ce45fc9783 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 12 Feb 2020 13:41:48 +0100 Subject: [PATCH 122/562] rpcserver: don't skip pending channels in backup subscription The synchronous call to get all channel backups also include channels that are pending at the moment of the call. A previous commit added pending channels to the file based backup as well. So this is the last backup method that needs to be adjusted to also contain unconfirmed channels. --- lntest/itest/lnd_test.go | 6 +++--- rpcserver.go | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index dfe5ee1004..69de39145d 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -13675,9 +13675,9 @@ func testChannelBackupUpdates(net *lntest.NetworkHarness, t *harnessTest) { } } - // As these two channels were just open, we should've got two - // notifications for channel backups. - assertBackupNtfns(2) + // As these two channels were just opened, we should've got two times + // the pending and open notifications for channel backups. + assertBackupNtfns(2 * 2) // The on disk file should also exactly match the latest backup that we // have. diff --git a/rpcserver.go b/rpcserver.go index f4e13cd65f..d7a27d90d7 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -5605,7 +5605,7 @@ func (r *rpcServer) SubscribeChannelBackups(req *lnrpc.ChannelBackupSubscription updateStream lnrpc.Lightning_SubscribeChannelBackupsServer) error { // First, we'll subscribe to the primary channel notifier so we can - // obtain events for new opened/closed channels. + // obtain events for new pending/opened/closed channels. chanSubscription, err := r.server.channelNotifier.SubscribeChannelEvents() if err != nil { return err @@ -5622,9 +5622,10 @@ func (r *rpcServer) SubscribeChannelBackups(req *lnrpc.ChannelBackupSubscription switch e.(type) { // We only care about new/closed channels, so we'll - // skip any events for pending/active/inactive channels. - case channelnotifier.PendingOpenChannelEvent: - continue + // skip any events for active/inactive channels. + // To make the subscription behave the same way as the + // synchronous call and the file based backup, we also + // include pending channels in the update. case channelnotifier.ActiveChannelEvent: continue case channelnotifier.InactiveChannelEvent: From ab024b98eed9cced304d9b3e87544bf746fc63a9 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 4 Mar 2020 10:57:06 +0100 Subject: [PATCH 123/562] rpcserver+itest: remove channel from backup when abandoning it --- lntest/itest/lnd_test.go | 19 +++++++++++++++++++ rpcserver.go | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 69de39145d..31142497cc 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -13303,6 +13303,15 @@ func testAbandonChannel(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("unable to find channel") } + // To make sure the channel is removed from the backup file as well when + // being abandoned, grab a backup snapshot so we can compare it with the + // later state. + bkupBefore, err := ioutil.ReadFile(net.Alice.ChanBackupPath()) + if err != nil { + t.Fatalf("could not get channel backup before abandoning "+ + "channel: %v", err) + } + // Send request to abandon channel. abandonChannelRequest := &lnrpc.AbandonChannelRequest{ ChannelPoint: chanPoint, @@ -13373,6 +13382,16 @@ func testAbandonChannel(net *lntest.NetworkHarness, t *harnessTest) { "graph!") } + // Make sure the channel is no longer in the channel backup list. + bkupAfter, err := ioutil.ReadFile(net.Alice.ChanBackupPath()) + if err != nil { + t.Fatalf("could not get channel backup before abandoning "+ + "channel: %v", err) + } + if len(bkupAfter) >= len(bkupBefore) { + t.Fatalf("channel wasn't removed from channel backup file") + } + // Calling AbandonChannel again, should result in no new errors, as the // channel has already been removed. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) diff --git a/rpcserver.go b/rpcserver.go index d7a27d90d7..1759dd08ce 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2254,6 +2254,10 @@ func (r *rpcServer) AbandonChannel(ctx context.Context, return nil, err } + // Finally, notify the backup listeners that the channel can be removed + // from any channel backups. + r.server.channelNotifier.NotifyClosedChannelEvent(*chanPoint) + return &lnrpc.AbandonChannelResponse{}, nil } From be74d94c48498459814cd690be58efb06f5bd285 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 4 Mar 2020 08:00:09 -0800 Subject: [PATCH 124/562] lnwallet/size_test: add test exercising nested input count bug This commit modifies the NP2WKH and NP2WSH input tests to ensure the input count is properly incremented and accounted for in the size estimate. 253 is chosen because it is the lowest value that, when serialized, occupies more than one byte on the wire. --- lnwallet/size_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lnwallet/size_test.go b/lnwallet/size_test.go index 36dac258dc..cf8cbb68ec 100644 --- a/lnwallet/size_test.go +++ b/lnwallet/size_test.go @@ -97,11 +97,11 @@ func TestTxWeightEstimator(t *testing.T) { numP2SHOutputs: 1, }, { - numNestedP2WKHInputs: 1, + numNestedP2WKHInputs: 253, numP2WKHOutputs: 1, }, { - numNestedP2WSHInputs: 1, + numNestedP2WSHInputs: 253, numP2WKHOutputs: 1, }, } From 6eb7f2800dc251c388e6ef5210f408ac5bffea78 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 4 Mar 2020 08:00:33 -0800 Subject: [PATCH 125/562] input/size: correct NP2WKH and NP2SH input count This commit corrects a bug in TxWeightEstimator that could result in underestimations for transactions involving NestedP2WPKH and NestedP2WSH inputs. The scriptSig data push is now accounted for in a proper size constant, and the input count is now incremented in both. This would only be detectable in the event that the number of non-nested inputs and the total number of inputs straddle the discontinuities in the CompactSize encoding, e.g. 253, 2^16-1, or 2^32-1. --- input/size.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/input/size.go b/input/size.go index 68fa85e4e6..a9406f8a9c 100644 --- a/input/size.go +++ b/input/size.go @@ -25,12 +25,22 @@ const ( // - PublicKeyHASH160: 20 bytes P2WPKHSize = 1 + 1 + 20 + // NestedP2WPKHSize 23 bytes + // - OP_DATA: 1 byte (P2WPKHSize) + // - P2WPKHWitnessProgram: 22 bytes + NestedP2WPKHSize = 1 + P2WPKHSize + // P2WSHSize 34 bytes // - OP_0: 1 byte // - OP_DATA: 1 byte (WitnessScriptSHA256 length) // - WitnessScriptSHA256: 32 bytes P2WSHSize = 1 + 1 + 32 + // NestedP2WSHSize 35 bytes + // - OP_DATA: 1 byte (P2WSHSize) + // - P2WSHWitnessProgram: 35 bytes + NestedP2WSHSize = 1 + P2WSHSize + // P2PKHOutputSize 34 bytes // - value: 8 bytes // - var_int: 1 byte (pkscript_length) @@ -417,9 +427,9 @@ func (twe *TxWeightEstimator) AddWitnessInput(witnessSize int) *TxWeightEstimato // AddNestedP2WKHInput updates the weight estimate to account for an additional // input spending a P2SH output with a nested P2WKH redeem script. func (twe *TxWeightEstimator) AddNestedP2WKHInput() *TxWeightEstimator { - twe.inputSize += InputSize + P2WPKHSize + twe.inputSize += InputSize + NestedP2WPKHSize twe.inputWitnessSize += P2WKHWitnessSize - twe.inputSize++ + twe.inputCount++ twe.hasWitness = true return twe @@ -428,9 +438,9 @@ func (twe *TxWeightEstimator) AddNestedP2WKHInput() *TxWeightEstimator { // AddNestedP2WSHInput updates the weight estimate to account for an additional // input spending a P2SH output with a nested P2WSH redeem script. func (twe *TxWeightEstimator) AddNestedP2WSHInput(witnessSize int) *TxWeightEstimator { - twe.inputSize += InputSize + P2WSHSize + twe.inputSize += InputSize + NestedP2WSHSize twe.inputWitnessSize += witnessSize - twe.inputSize++ + twe.inputCount++ twe.hasWitness = true return twe From 4c402ab9d470aba23321b2ac75dcf307be2c0ad4 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 4 Mar 2020 08:00:48 -0800 Subject: [PATCH 126/562] lnwallet/size_test: refactor and expand unit tests --- lnwallet/size_test.go | 95 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/lnwallet/size_test.go b/lnwallet/size_test.go index cf8cbb68ec..acc83b965f 100644 --- a/lnwallet/size_test.go +++ b/lnwallet/size_test.go @@ -68,6 +68,68 @@ func TestTxWeightEstimator(t *testing.T) { numP2WSHOutputs int numP2SHOutputs int }{ + // Assert base txn size. + {}, + + // Assert single input/output sizes. + { + numP2PKHInputs: 1, + }, + { + numP2WKHInputs: 1, + }, + { + numP2WSHInputs: 1, + }, + { + numNestedP2WKHInputs: 1, + }, + { + numNestedP2WSHInputs: 1, + }, + { + numP2WKHOutputs: 1, + }, + { + numP2PKHOutputs: 1, + }, + { + numP2WSHOutputs: 1, + }, + { + numP2SHOutputs: 1, + }, + + // Assert each input/output increments input/output counts. + { + numP2PKHInputs: 253, + }, + { + numP2WKHInputs: 253, + }, + { + numP2WSHInputs: 253, + }, + { + numNestedP2WKHInputs: 253, + }, + { + numNestedP2WSHInputs: 253, + }, + { + numP2WKHOutputs: 253, + }, + { + numP2PKHOutputs: 253, + }, + { + numP2WSHOutputs: 253, + }, + { + numP2SHOutputs: 253, + }, + + // Assert basic combinations of inputs and outputs. { numP2PKHInputs: 1, numP2PKHOutputs: 2, @@ -97,13 +159,42 @@ func TestTxWeightEstimator(t *testing.T) { numP2SHOutputs: 1, }, { - numNestedP2WKHInputs: 253, + numNestedP2WKHInputs: 1, numP2WKHOutputs: 1, }, { - numNestedP2WSHInputs: 253, + numNestedP2WSHInputs: 1, + numP2WKHOutputs: 1, + }, + + // Assert disparate input/output types increment total + // input/output counts. + { + numP2PKHInputs: 50, + numP2WKHInputs: 50, + numP2WSHInputs: 51, + numNestedP2WKHInputs: 51, + numNestedP2WSHInputs: 51, numP2WKHOutputs: 1, }, + { + numP2WKHInputs: 1, + numP2WKHOutputs: 63, + numP2PKHOutputs: 63, + numP2WSHOutputs: 63, + numP2SHOutputs: 64, + }, + { + numP2PKHInputs: 50, + numP2WKHInputs: 50, + numP2WSHInputs: 51, + numNestedP2WKHInputs: 51, + numNestedP2WSHInputs: 51, + numP2WKHOutputs: 63, + numP2PKHOutputs: 63, + numP2WSHOutputs: 63, + numP2SHOutputs: 64, + }, } for i, test := range testCases { From 4c2bc7bc79c25b47cc7037b1fea684d102a4bce6 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 4 Mar 2020 08:01:37 -0800 Subject: [PATCH 127/562] lnwallet+input: move size_test.go to input pkg --- {lnwallet => input}/size_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {lnwallet => input}/size_test.go (99%) diff --git a/lnwallet/size_test.go b/input/size_test.go similarity index 99% rename from lnwallet/size_test.go rename to input/size_test.go index acc83b965f..9164340225 100644 --- a/lnwallet/size_test.go +++ b/input/size_test.go @@ -1,4 +1,4 @@ -package lnwallet_test +package input_test import ( "testing" From 5c9b336a61827dc7f7bf77cddb24b97cf5f51497 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 2 Mar 2020 06:59:26 -0300 Subject: [PATCH 128/562] lnrpc+rpcserver: expose short chan id on feereport This commit adds each channel's short chan id to the `feereport` rpc. Without this, it can be tedious to lookup more info about a particular channel since most rpcs only accept short chan ids and not channel points. For instance, now one can take a channel id from `feereport` and look it up directly via `getchaninfo` to examine the policy in more detail. --- lnrpc/rpc.pb.go | 857 +++++++++++++++++++++-------------------- lnrpc/rpc.proto | 3 + lnrpc/rpc.swagger.json | 5 + rpcserver.go | 1 + 4 files changed, 442 insertions(+), 424 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 7ee3b08b6e..fda0e7ae16 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -9348,6 +9348,8 @@ func (m *FeeReportRequest) XXX_DiscardUnknown() { var xxx_messageInfo_FeeReportRequest proto.InternalMessageInfo type ChannelFeeReport struct { + /// The short channel id that this fee report belongs to. + ChanId uint64 `protobuf:"varint,5,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` /// The channel that this fee report belongs to. ChanPoint string `protobuf:"bytes,1,opt,name=chan_point,json=channel_point,proto3" json:"chan_point,omitempty"` /// The base fee charged regardless of the number of milli-satoshis sent. @@ -9386,6 +9388,13 @@ func (m *ChannelFeeReport) XXX_DiscardUnknown() { var xxx_messageInfo_ChannelFeeReport proto.InternalMessageInfo +func (m *ChannelFeeReport) GetChanId() uint64 { + if m != nil { + return m.ChanId + } + return 0 +} + func (m *ChannelFeeReport) GetChanPoint() string { if m != nil { return m.ChanPoint @@ -10628,265 +10637,265 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 9926 bytes of a gzipped FileDescriptorProto + // 9934 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5d, 0x6c, 0x1c, 0xd9, 0x95, 0x18, 0xac, 0xea, 0x1f, 0xb2, 0xfb, 0xf4, 0x0f, 0x9b, 0x97, 0x14, 0xd9, 0x6a, 0xfd, 0x8c, 0xa6, 0x2c, 0xcf, 0xc8, 0xf2, 0x98, 0xd2, 0xd0, 0xf6, 0xac, 0x3c, 0xfa, 0xd6, 0x6b, 0xfe, 0x49, 0xe4, 0x0c, 0x45, 0xd2, 0x45, 0xca, 0x5a, 0xdb, 0xdf, 0xa2, 0x5c, 0xec, 0xbe, 0x24, 0xcb, 0xea, 0xae, 0xea, 0xa9, 0xaa, 0x26, 0x45, 0x3b, 0x93, 0x87, 0x20, 0x09, 0x82, 0xbc, 0x04, 0x86, 0x11, - 0x20, 0x9b, 0x1f, 0x2c, 0xe0, 0x4d, 0x10, 0x04, 0x01, 0x92, 0x3c, 0x05, 0x1b, 0xc0, 0x79, 0xca, - 0xc3, 0xe6, 0x25, 0xc8, 0x43, 0x02, 0x04, 0x48, 0x80, 0x00, 0x8b, 0xcd, 0x43, 0x16, 0x01, 0xf2, - 0x94, 0xe4, 0x39, 0xb8, 0xe7, 0xfe, 0xd4, 0xbd, 0x55, 0xd5, 0x94, 0xc6, 0x76, 0xfc, 0x22, 0xf1, - 0x9e, 0x7b, 0xea, 0xfe, 0x9e, 0x73, 0xee, 0xf9, 0xb9, 0xe7, 0x36, 0xd4, 0xa3, 0x71, 0x7f, 0x65, - 0x1c, 0x85, 0x49, 0x48, 0xaa, 0xc3, 0x20, 0x1a, 0xf7, 0x7b, 0xb7, 0x4e, 0xc3, 0xf0, 0x74, 0x48, - 0x1f, 0x7a, 0x63, 0xff, 0xa1, 0x17, 0x04, 0x61, 0xe2, 0x25, 0x7e, 0x18, 0xc4, 0x1c, 0xc9, 0xfe, - 0x11, 0xb4, 0x9f, 0xd1, 0xe0, 0x90, 0xd2, 0x81, 0x43, 0x3f, 0x9b, 0xd0, 0x38, 0x21, 0x5f, 0x85, - 0x79, 0x8f, 0xfe, 0x84, 0xd2, 0x81, 0x3b, 0xf6, 0xe2, 0x78, 0x7c, 0x16, 0x79, 0x31, 0xed, 0x5a, - 0x77, 0xad, 0xfb, 0x4d, 0xa7, 0xc3, 0x2b, 0x0e, 0x14, 0x9c, 0xbc, 0x0b, 0xcd, 0x98, 0xa1, 0xd2, - 0x20, 0x89, 0xc2, 0xf1, 0x65, 0xb7, 0x84, 0x78, 0x0d, 0x06, 0xdb, 0xe2, 0x20, 0x7b, 0x08, 0x73, - 0xaa, 0x87, 0x78, 0x1c, 0x06, 0x31, 0x25, 0x8f, 0x60, 0xb1, 0xef, 0x8f, 0xcf, 0x68, 0xe4, 0xe2, - 0xc7, 0xa3, 0x80, 0x8e, 0xc2, 0xc0, 0xef, 0x77, 0xad, 0xbb, 0xe5, 0xfb, 0x75, 0x87, 0xf0, 0x3a, - 0xf6, 0xc5, 0x73, 0x51, 0x43, 0xde, 0x87, 0x39, 0x1a, 0x70, 0x38, 0x1d, 0xe0, 0x57, 0xa2, 0xab, - 0x76, 0x0a, 0x66, 0x1f, 0xd8, 0x7f, 0xa3, 0x04, 0xf3, 0x3b, 0x81, 0x9f, 0xbc, 0xf4, 0x86, 0x43, - 0x9a, 0xc8, 0x39, 0xbd, 0x0f, 0x73, 0x17, 0x08, 0xc0, 0x39, 0x5d, 0x84, 0xd1, 0x40, 0xcc, 0xa8, - 0xcd, 0xc1, 0x07, 0x02, 0x3a, 0x75, 0x64, 0xa5, 0xa9, 0x23, 0x2b, 0x5c, 0xae, 0xf2, 0x94, 0xe5, - 0x7a, 0x1f, 0xe6, 0x22, 0xda, 0x0f, 0xcf, 0x69, 0x74, 0xe9, 0x5e, 0xf8, 0xc1, 0x20, 0xbc, 0xe8, - 0x56, 0xee, 0x5a, 0xf7, 0xab, 0x4e, 0x5b, 0x82, 0x5f, 0x22, 0x94, 0xac, 0xc3, 0x5c, 0xff, 0xcc, - 0x0b, 0x02, 0x3a, 0x74, 0x8f, 0xbd, 0xfe, 0xab, 0xc9, 0x38, 0xee, 0x56, 0xef, 0x5a, 0xf7, 0x1b, - 0xab, 0x37, 0x56, 0x70, 0x57, 0x57, 0x36, 0xce, 0xbc, 0x60, 0x1d, 0x6b, 0x0e, 0x03, 0x6f, 0x1c, - 0x9f, 0x85, 0x89, 0xd3, 0x16, 0x5f, 0x70, 0x70, 0x6c, 0x2f, 0x02, 0xd1, 0x57, 0x82, 0xaf, 0xbd, - 0xfd, 0x4f, 0x2d, 0x58, 0x78, 0x11, 0x0c, 0xc3, 0xfe, 0xab, 0x5f, 0x71, 0x89, 0x0a, 0xe6, 0x50, - 0x7a, 0xdb, 0x39, 0x94, 0xbf, 0xe8, 0x1c, 0x96, 0x60, 0xd1, 0x1c, 0xac, 0x98, 0x05, 0x85, 0xeb, - 0xec, 0xeb, 0x53, 0x2a, 0x87, 0x25, 0xa7, 0xf1, 0x15, 0xe8, 0xf4, 0x27, 0x51, 0x44, 0x83, 0xdc, - 0x3c, 0xe6, 0x04, 0x5c, 0x4d, 0xe4, 0x5d, 0x68, 0x06, 0xf4, 0x22, 0x45, 0x13, 0xb4, 0x1b, 0xd0, - 0x0b, 0x89, 0x62, 0x77, 0x61, 0x29, 0xdb, 0x8d, 0x18, 0xc0, 0x9f, 0x59, 0x50, 0x79, 0x91, 0xbc, - 0x0e, 0xc9, 0x0a, 0x54, 0x92, 0xcb, 0x31, 0xe7, 0x90, 0xf6, 0x2a, 0x11, 0x53, 0x5b, 0x1b, 0x0c, - 0x22, 0x1a, 0xc7, 0x47, 0x97, 0x63, 0xea, 0x34, 0x3d, 0x5e, 0x70, 0x19, 0x1e, 0xe9, 0xc2, 0xac, - 0x28, 0x63, 0x87, 0x75, 0x47, 0x16, 0xc9, 0x1d, 0x00, 0x6f, 0x14, 0x4e, 0x82, 0xc4, 0x8d, 0xbd, - 0x04, 0x97, 0xaa, 0xec, 0x68, 0x10, 0x72, 0x0b, 0xea, 0xe3, 0x57, 0x6e, 0xdc, 0x8f, 0xfc, 0x71, - 0x82, 0x64, 0x53, 0x77, 0x52, 0x00, 0xf9, 0x2a, 0xd4, 0xc2, 0x49, 0x32, 0x0e, 0xfd, 0x20, 0x11, - 0xa4, 0x32, 0x27, 0xc6, 0xb2, 0x3f, 0x49, 0x0e, 0x18, 0xd8, 0x51, 0x08, 0xe4, 0x1e, 0xb4, 0xfa, - 0x61, 0x70, 0xe2, 0x47, 0x23, 0x2e, 0x0c, 0xba, 0x33, 0xd8, 0x9b, 0x09, 0xb4, 0xff, 0x55, 0x09, - 0x1a, 0x47, 0x91, 0x17, 0xc4, 0x5e, 0x9f, 0x01, 0xd8, 0xd0, 0x93, 0xd7, 0xee, 0x99, 0x17, 0x9f, - 0xe1, 0x6c, 0xeb, 0x8e, 0x2c, 0x92, 0x25, 0x98, 0xe1, 0x03, 0xc5, 0x39, 0x95, 0x1d, 0x51, 0x22, - 0x1f, 0xc0, 0x7c, 0x30, 0x19, 0xb9, 0x66, 0x5f, 0x65, 0xa4, 0x96, 0x7c, 0x05, 0x5b, 0x80, 0x63, - 0xb6, 0xd7, 0xbc, 0x0b, 0x3e, 0x43, 0x0d, 0x42, 0x6c, 0x68, 0x8a, 0x12, 0xf5, 0x4f, 0xcf, 0xf8, - 0x34, 0xab, 0x8e, 0x01, 0x63, 0x6d, 0x24, 0xfe, 0x88, 0xba, 0x71, 0xe2, 0x8d, 0xc6, 0x62, 0x5a, - 0x1a, 0x04, 0xeb, 0xc3, 0xc4, 0x1b, 0xba, 0x27, 0x94, 0xc6, 0xdd, 0x59, 0x51, 0xaf, 0x20, 0xe4, - 0x3d, 0x68, 0x0f, 0x68, 0x9c, 0xb8, 0x62, 0x53, 0x68, 0xdc, 0xad, 0x21, 0xeb, 0x67, 0xa0, 0xac, - 0x9d, 0xc8, 0xbb, 0x70, 0xd9, 0x02, 0xd0, 0xd7, 0xdd, 0x3a, 0x1f, 0x6b, 0x0a, 0x61, 0x94, 0xf3, - 0x8c, 0x26, 0xda, 0xea, 0xc5, 0x82, 0x42, 0xed, 0x5d, 0x20, 0x1a, 0x78, 0x93, 0x26, 0x9e, 0x3f, - 0x8c, 0xc9, 0x47, 0xd0, 0x4c, 0x34, 0x64, 0x14, 0x85, 0x0d, 0x45, 0x4e, 0xda, 0x07, 0x8e, 0x81, - 0x67, 0x9f, 0x41, 0xed, 0x29, 0xa5, 0xbb, 0xfe, 0xc8, 0x4f, 0xc8, 0x12, 0x54, 0x4f, 0xfc, 0xd7, - 0x94, 0x13, 0x7c, 0x79, 0xfb, 0x9a, 0xc3, 0x8b, 0xe4, 0x1d, 0x00, 0xfc, 0xc3, 0x1d, 0x29, 0xc2, - 0xda, 0xbe, 0xe6, 0xd4, 0x11, 0xf6, 0x9c, 0x51, 0x56, 0x0f, 0x66, 0xc7, 0x34, 0xea, 0x53, 0xb9, - 0x7f, 0xdb, 0xd7, 0x1c, 0x09, 0x58, 0x9f, 0x85, 0xea, 0x90, 0xb5, 0x6e, 0xff, 0x69, 0x15, 0x1a, - 0x87, 0x34, 0x50, 0x9c, 0x46, 0xa0, 0xc2, 0xd6, 0x44, 0x70, 0x17, 0xfe, 0x4d, 0xbe, 0x04, 0x0d, - 0x5c, 0xa7, 0x38, 0x89, 0xfc, 0xe0, 0x94, 0x13, 0xf8, 0x7a, 0xa9, 0x6b, 0x39, 0xc0, 0xc0, 0x87, - 0x08, 0x25, 0x1d, 0x28, 0x7b, 0x23, 0x49, 0xe0, 0xec, 0x4f, 0x72, 0x03, 0x6a, 0xde, 0x28, 0xe1, - 0xc3, 0x6b, 0x22, 0x78, 0xd6, 0x1b, 0x25, 0x38, 0xb4, 0x77, 0xa1, 0x39, 0xf6, 0x2e, 0x47, 0x8c, - 0x9f, 0x15, 0x55, 0x34, 0x9d, 0x86, 0x80, 0x6d, 0x33, 0xb2, 0x58, 0x85, 0x05, 0x1d, 0x45, 0x76, - 0x5e, 0x55, 0x9d, 0xcf, 0x6b, 0xd8, 0x62, 0x0c, 0xef, 0xc3, 0x9c, 0xfc, 0x26, 0xe2, 0xf3, 0x41, - 0x5a, 0xa9, 0x3b, 0x6d, 0x01, 0x96, 0xb3, 0xbc, 0x0f, 0x9d, 0x13, 0x3f, 0xf0, 0x86, 0x6e, 0x7f, - 0x98, 0x9c, 0xbb, 0x03, 0x3a, 0x4c, 0x3c, 0xa4, 0x9a, 0xaa, 0xd3, 0x46, 0xf8, 0xc6, 0x30, 0x39, - 0xdf, 0x64, 0x50, 0xf2, 0x01, 0xd4, 0x4f, 0x28, 0x75, 0x71, 0xb1, 0xba, 0x35, 0x83, 0x03, 0xe5, - 0x0e, 0x39, 0xb5, 0x13, 0xb9, 0x57, 0x1f, 0x40, 0x27, 0x9c, 0x24, 0xa7, 0xa1, 0x1f, 0x9c, 0xba, - 0x4c, 0xe6, 0xb9, 0xfe, 0x00, 0xa9, 0xa8, 0xb2, 0x5e, 0x7a, 0x64, 0x39, 0x6d, 0x59, 0xc7, 0xa4, - 0xcf, 0xce, 0x80, 0xbc, 0x07, 0x73, 0x43, 0x2f, 0x4e, 0xdc, 0xb3, 0x70, 0xec, 0x8e, 0x27, 0xc7, - 0xaf, 0xe8, 0x65, 0xb7, 0x85, 0x0b, 0xd1, 0x62, 0xe0, 0xed, 0x70, 0x7c, 0x80, 0x40, 0x72, 0x1b, - 0x00, 0xc7, 0xc9, 0x07, 0x01, 0x77, 0xad, 0xfb, 0x2d, 0xa7, 0xce, 0x20, 0xbc, 0xd3, 0xef, 0xc3, - 0x02, 0x6e, 0x4f, 0x7f, 0x12, 0x27, 0xe1, 0xc8, 0x65, 0xf2, 0x3a, 0x1a, 0xc4, 0xdd, 0x06, 0xd2, - 0xda, 0x57, 0xc4, 0x60, 0xb5, 0x3d, 0x5e, 0xd9, 0xa4, 0x71, 0xb2, 0x81, 0xc8, 0x0e, 0xc7, 0x65, - 0x87, 0xfa, 0xa5, 0x33, 0x3f, 0xc8, 0xc2, 0xc9, 0x07, 0x40, 0xbc, 0xe1, 0x30, 0xbc, 0x70, 0x63, - 0x3a, 0x3c, 0x71, 0xc5, 0x22, 0x76, 0xdb, 0x77, 0xad, 0xfb, 0x35, 0xa7, 0x83, 0x35, 0x87, 0x74, - 0x78, 0x72, 0xc0, 0xe1, 0xe4, 0x23, 0x68, 0xe1, 0x40, 0x4e, 0xa8, 0x97, 0x4c, 0x22, 0x1a, 0x77, - 0xe7, 0xee, 0x96, 0xef, 0xb7, 0x57, 0xe7, 0xd5, 0x7a, 0x21, 0x78, 0xdd, 0x4f, 0x9c, 0x26, 0xc3, - 0x13, 0xe5, 0xb8, 0xb7, 0x09, 0x4b, 0xc5, 0x43, 0x62, 0x44, 0xc5, 0x56, 0x85, 0x11, 0x63, 0xc5, - 0x61, 0x7f, 0x92, 0x45, 0xa8, 0x9e, 0x7b, 0xc3, 0x09, 0x15, 0x72, 0x9d, 0x17, 0x3e, 0x2e, 0x3d, - 0xb6, 0xec, 0x3f, 0xb1, 0xa0, 0xc9, 0x67, 0x29, 0xf4, 0x91, 0x7b, 0xd0, 0x92, 0xd4, 0x40, 0xa3, - 0x28, 0x8c, 0x84, 0x78, 0x33, 0x81, 0xe4, 0x01, 0x74, 0x24, 0x60, 0x1c, 0x51, 0x7f, 0xe4, 0x9d, - 0xca, 0xb6, 0x73, 0x70, 0xb2, 0x9a, 0xb6, 0x18, 0x85, 0x93, 0x84, 0x8a, 0x93, 0xaf, 0x29, 0x26, - 0xe8, 0x30, 0x98, 0x63, 0xa2, 0x30, 0xf1, 0x56, 0x40, 0xea, 0x06, 0xcc, 0xfe, 0xdb, 0x16, 0x10, - 0x36, 0xf4, 0xa3, 0x90, 0x37, 0x21, 0xa8, 0x34, 0xcb, 0x25, 0xd6, 0x5b, 0x73, 0x49, 0xe9, 0x2a, - 0x2e, 0xb1, 0xa1, 0xca, 0x47, 0x5f, 0x29, 0x18, 0x3d, 0xaf, 0xfa, 0xa4, 0x52, 0x2b, 0x77, 0x2a, - 0xf6, 0x7f, 0x2e, 0xc3, 0xe2, 0x06, 0x3f, 0xba, 0xd7, 0xfa, 0x7d, 0x3a, 0x56, 0xfc, 0xf3, 0x0e, - 0x34, 0x82, 0x70, 0x40, 0x25, 0xd5, 0xf2, 0x81, 0x01, 0x03, 0x69, 0x24, 0x7b, 0xe6, 0xf9, 0x01, - 0x1f, 0x38, 0x5f, 0xcf, 0x3a, 0x42, 0x70, 0xd8, 0xef, 0xc1, 0xdc, 0x98, 0x06, 0x03, 0x9d, 0x4d, - 0xb8, 0x72, 0xd5, 0x12, 0x60, 0xc1, 0x21, 0xef, 0x40, 0xe3, 0x64, 0xc2, 0xf1, 0x98, 0x70, 0xa9, - 0x20, 0x1d, 0x80, 0x00, 0xad, 0x71, 0x19, 0x33, 0x9e, 0xc4, 0x67, 0x58, 0x5b, 0xc5, 0xda, 0x59, - 0x56, 0x66, 0x55, 0xb7, 0x01, 0x06, 0x93, 0x38, 0x11, 0x5c, 0x33, 0x83, 0x95, 0x75, 0x06, 0xe1, - 0x5c, 0xf3, 0x35, 0x58, 0x18, 0x79, 0xaf, 0x5d, 0xa4, 0x1f, 0xd7, 0x0f, 0xdc, 0x93, 0x21, 0x9e, - 0x3e, 0xb3, 0x88, 0xd7, 0x19, 0x79, 0xaf, 0xbf, 0xc7, 0x6a, 0x76, 0x82, 0xa7, 0x08, 0x67, 0xa2, - 0x45, 0xaa, 0x3d, 0x11, 0x8d, 0x69, 0x74, 0x4e, 0x51, 0x1a, 0x54, 0x94, 0x6e, 0xe3, 0x70, 0x28, - 0x1b, 0xd1, 0x88, 0xcd, 0x3b, 0x19, 0xf6, 0x39, 0xeb, 0x3b, 0xb3, 0x23, 0x3f, 0xd8, 0x4e, 0x86, - 0x7d, 0x72, 0x0b, 0x80, 0xc9, 0x92, 0x31, 0x8d, 0xdc, 0x57, 0x17, 0xc8, 0xc7, 0x15, 0x94, 0x1d, - 0x07, 0x34, 0xfa, 0xf4, 0x82, 0xdc, 0x84, 0x7a, 0x3f, 0x46, 0x61, 0xe4, 0x5d, 0x76, 0x1b, 0xc8, - 0xe4, 0xb5, 0x7e, 0xcc, 0xc4, 0x90, 0x77, 0xc9, 0x18, 0x91, 0x8d, 0xd6, 0xc3, 0x5d, 0xa0, 0x03, - 0x6c, 0x3e, 0x46, 0xa9, 0xda, 0xc2, 0xc1, 0xae, 0x89, 0x0a, 0xd6, 0x4f, 0x4c, 0xbe, 0x04, 0x2d, - 0x39, 0xd8, 0x93, 0xa1, 0x77, 0x1a, 0xa3, 0x58, 0x69, 0x39, 0x4d, 0x01, 0x7c, 0xca, 0x60, 0xf6, - 0x4b, 0xae, 0x6c, 0x69, 0x7b, 0x2b, 0xf8, 0x86, 0x1d, 0xfb, 0x08, 0xc1, 0x7d, 0xad, 0x39, 0xa2, - 0x54, 0xb4, 0x69, 0xa5, 0x82, 0x4d, 0xb3, 0x7f, 0x61, 0x41, 0x53, 0xb4, 0x8c, 0x1a, 0x0a, 0x79, - 0x04, 0x44, 0xee, 0x62, 0xf2, 0xda, 0x1f, 0xb8, 0xc7, 0x97, 0x09, 0x8d, 0x39, 0xd1, 0x6c, 0x5f, - 0x73, 0x0a, 0xea, 0x98, 0x1c, 0x35, 0xa0, 0x71, 0x12, 0x71, 0x9a, 0xde, 0xbe, 0xe6, 0xe4, 0x6a, - 0x18, 0x8b, 0x31, 0x1d, 0x68, 0x92, 0xb8, 0x7e, 0x30, 0xa0, 0xaf, 0x91, 0x94, 0x5a, 0x8e, 0x01, - 0x5b, 0x6f, 0x43, 0x53, 0xff, 0xce, 0xfe, 0x31, 0xd4, 0xa4, 0x06, 0x85, 0xda, 0x43, 0x66, 0x5c, - 0x8e, 0x06, 0x21, 0x3d, 0xa8, 0x99, 0xa3, 0x70, 0x6a, 0x5f, 0xa4, 0x6f, 0xfb, 0xdb, 0xd0, 0xd9, - 0x65, 0x44, 0x14, 0x30, 0xa2, 0x15, 0x6a, 0xe1, 0x12, 0xcc, 0x68, 0xcc, 0x53, 0x77, 0x44, 0x89, - 0x9d, 0xbf, 0x67, 0x61, 0x9c, 0x88, 0x7e, 0xf0, 0x6f, 0xfb, 0x4f, 0x2d, 0x20, 0x5b, 0x71, 0xe2, - 0x8f, 0xbc, 0x84, 0x3e, 0xa5, 0x4a, 0x3c, 0xec, 0x43, 0x93, 0xb5, 0x76, 0x14, 0xae, 0x71, 0x25, - 0x8d, 0x2b, 0x17, 0x5f, 0x15, 0xec, 0x9c, 0xff, 0x60, 0x45, 0xc7, 0xe6, 0x22, 0xdf, 0x68, 0x80, - 0x71, 0x5b, 0xe2, 0x45, 0xa7, 0x34, 0x41, 0x0d, 0x4e, 0xe8, 0xff, 0xc0, 0x41, 0x1b, 0x61, 0x70, - 0xd2, 0xfb, 0x3d, 0x98, 0xcf, 0xb5, 0xa1, 0xcb, 0xe8, 0x7a, 0x81, 0x8c, 0x2e, 0xeb, 0x32, 0xba, - 0x0f, 0x0b, 0xc6, 0xb8, 0x04, 0xc5, 0x75, 0x61, 0x96, 0x31, 0x06, 0x53, 0x14, 0x2c, 0xae, 0x28, - 0x88, 0x22, 0x59, 0x85, 0xc5, 0x13, 0x4a, 0x23, 0x2f, 0xc1, 0x22, 0xb2, 0x0e, 0xdb, 0x13, 0xd1, - 0x72, 0x61, 0x9d, 0xfd, 0xe7, 0x16, 0xcc, 0x31, 0x69, 0xfa, 0xdc, 0x0b, 0x2e, 0xe5, 0x5a, 0xed, - 0x16, 0xae, 0xd5, 0x7d, 0xed, 0x70, 0xd4, 0xb0, 0xbf, 0xe8, 0x42, 0x95, 0xb3, 0x0b, 0x45, 0xee, - 0x42, 0xd3, 0x18, 0x6e, 0x95, 0x6b, 0xa4, 0xb1, 0x97, 0x1c, 0xd0, 0x68, 0xfd, 0x32, 0xa1, 0xbf, - 0xfe, 0x52, 0xbe, 0x07, 0x9d, 0x74, 0xd8, 0x62, 0x1d, 0x09, 0x54, 0x18, 0x61, 0x8a, 0x06, 0xf0, - 0x6f, 0xfb, 0xef, 0x5b, 0x1c, 0x71, 0x23, 0xf4, 0x95, 0xb6, 0xca, 0x10, 0x99, 0xd2, 0x2b, 0x11, - 0xd9, 0xdf, 0x53, 0xb5, 0xfd, 0x5f, 0x7f, 0xb2, 0x4c, 0x26, 0xc6, 0x34, 0x18, 0xb8, 0xde, 0x70, - 0x88, 0x82, 0xb8, 0xe6, 0xcc, 0xb2, 0xf2, 0xda, 0x70, 0x68, 0xbf, 0x0f, 0xf3, 0xda, 0xe8, 0xae, - 0x98, 0xc7, 0x1e, 0x90, 0x5d, 0x3f, 0x4e, 0x5e, 0x04, 0xf1, 0x58, 0x53, 0xe4, 0x6e, 0x42, 0x9d, - 0x49, 0x5b, 0x36, 0x32, 0xce, 0xb9, 0x55, 0x87, 0x89, 0x5f, 0x36, 0xae, 0x18, 0x2b, 0xbd, 0xd7, - 0xa2, 0xb2, 0x24, 0x2a, 0xbd, 0xd7, 0x58, 0x69, 0x3f, 0x86, 0x05, 0xa3, 0x3d, 0xd1, 0xf5, 0xbb, - 0x50, 0x9d, 0x24, 0xaf, 0x43, 0xa9, 0xaa, 0x37, 0x04, 0x85, 0x30, 0xa3, 0xd0, 0xe1, 0x35, 0xf6, - 0x13, 0x98, 0xdf, 0xa3, 0x17, 0x82, 0x91, 0xe5, 0x40, 0xde, 0x7b, 0xa3, 0xc1, 0x88, 0xf5, 0xf6, - 0x0a, 0x10, 0xfd, 0xe3, 0x94, 0x01, 0xa4, 0xf9, 0x68, 0x19, 0xe6, 0xa3, 0xfd, 0x1e, 0x90, 0x43, - 0xff, 0x34, 0x78, 0x4e, 0xe3, 0xd8, 0x3b, 0x55, 0xac, 0xdf, 0x81, 0xf2, 0x28, 0x3e, 0x15, 0xa2, - 0x8a, 0xfd, 0x69, 0x7f, 0x1d, 0x16, 0x0c, 0x3c, 0xd1, 0xf0, 0x2d, 0xa8, 0xc7, 0xfe, 0x69, 0x80, - 0x8a, 0x96, 0x68, 0x3a, 0x05, 0xd8, 0x4f, 0x61, 0xf1, 0x7b, 0x34, 0xf2, 0x4f, 0x2e, 0xdf, 0xd4, - 0xbc, 0xd9, 0x4e, 0x29, 0xdb, 0xce, 0x16, 0x5c, 0xcf, 0xb4, 0x23, 0xba, 0xe7, 0xe4, 0x2b, 0x76, - 0xb2, 0xe6, 0xf0, 0x82, 0x26, 0xfb, 0x4a, 0xba, 0xec, 0xb3, 0x5f, 0x00, 0xd9, 0x08, 0x83, 0x80, - 0xf6, 0x93, 0x03, 0x4a, 0xa3, 0xd4, 0x73, 0x95, 0xd2, 0x6a, 0x63, 0x75, 0x59, 0xac, 0x6c, 0x56, - 0xa0, 0x0a, 0x22, 0x26, 0x50, 0x19, 0xd3, 0x68, 0x84, 0x0d, 0xd7, 0x1c, 0xfc, 0xdb, 0xbe, 0x0e, - 0x0b, 0x46, 0xb3, 0xc2, 0xd6, 0xff, 0x10, 0xae, 0x6f, 0xfa, 0x71, 0x3f, 0xdf, 0x61, 0x17, 0x66, - 0xc7, 0x93, 0x63, 0x37, 0xe5, 0x44, 0x59, 0x64, 0xe6, 0x5f, 0xf6, 0x13, 0xd1, 0xd8, 0x5f, 0xb7, - 0xa0, 0xb2, 0x7d, 0xb4, 0xbb, 0xc1, 0xce, 0x0a, 0x3f, 0xe8, 0x87, 0x23, 0xa6, 0x85, 0xf1, 0x49, - 0xab, 0xf2, 0x54, 0x0e, 0xbb, 0x05, 0x75, 0x54, 0xde, 0x98, 0xc5, 0x2b, 0xf4, 0xa0, 0x14, 0xc0, - 0xac, 0x6d, 0xfa, 0x7a, 0xec, 0x47, 0x68, 0x4e, 0x4b, 0x23, 0xb9, 0x82, 0xc7, 0x4c, 0xbe, 0xc2, - 0xfe, 0xb7, 0xb3, 0x30, 0x2b, 0x0e, 0x5f, 0x7e, 0x90, 0x27, 0xfe, 0x39, 0x4d, 0x0f, 0x72, 0x56, - 0x62, 0x8a, 0x71, 0x44, 0x47, 0x61, 0xa2, 0xf4, 0x37, 0xbe, 0x0d, 0x26, 0x10, 0xbd, 0x09, 0x42, - 0x89, 0xe0, 0xfe, 0x87, 0x32, 0xc7, 0x32, 0x80, 0xe4, 0x16, 0xcc, 0x4a, 0x65, 0xa0, 0xa2, 0x0c, - 0x1d, 0x09, 0x62, 0xab, 0xd1, 0xf7, 0xc6, 0x5e, 0xdf, 0x4f, 0x2e, 0x85, 0x58, 0x50, 0x65, 0xd6, - 0xfe, 0x30, 0xec, 0x7b, 0x43, 0xf7, 0xd8, 0x1b, 0x7a, 0x41, 0x9f, 0x4a, 0x6f, 0x85, 0x01, 0x64, - 0x96, 0xbb, 0x18, 0x96, 0x44, 0xe3, 0xd6, 0x7d, 0x06, 0xca, 0xce, 0xf0, 0x7e, 0x38, 0x1a, 0xf9, - 0xcc, 0xfa, 0xe0, 0xaa, 0x59, 0xd9, 0xd1, 0x20, 0xdc, 0x37, 0x82, 0xa5, 0x0b, 0xbe, 0x82, 0x75, - 0xe9, 0x1b, 0xd1, 0x80, 0xac, 0x95, 0x8c, 0x86, 0x56, 0x76, 0x34, 0x08, 0xdb, 0x8b, 0x49, 0x10, - 0xd3, 0x24, 0x19, 0xd2, 0x81, 0x1a, 0x50, 0x03, 0xd1, 0xf2, 0x15, 0xe4, 0x11, 0x2c, 0x70, 0x1f, - 0x44, 0xec, 0x25, 0x61, 0x7c, 0xe6, 0xc7, 0x6e, 0xcc, 0xcc, 0x27, 0x6e, 0x0b, 0x17, 0x55, 0x91, - 0xc7, 0xb0, 0x9c, 0x01, 0x47, 0xb4, 0x4f, 0xfd, 0x73, 0x3a, 0x40, 0x15, 0xae, 0xec, 0x4c, 0xab, - 0x26, 0x77, 0xa1, 0x11, 0x4c, 0x46, 0xee, 0x64, 0x3c, 0xf0, 0x98, 0x12, 0xd3, 0x46, 0xe5, 0x52, - 0x07, 0x91, 0x0f, 0x41, 0xea, 0x69, 0x42, 0x7b, 0x9c, 0x33, 0x24, 0x1c, 0xa3, 0x5e, 0xc7, 0xc4, - 0x60, 0x84, 0x99, 0xaa, 0xa4, 0x1d, 0x61, 0x77, 0x4a, 0x00, 0xf2, 0x49, 0xe4, 0x9f, 0x7b, 0x09, - 0xed, 0xce, 0x73, 0xa1, 0x2e, 0x8a, 0xec, 0x3b, 0x3f, 0xf0, 0x13, 0xdf, 0x4b, 0xc2, 0xa8, 0x4b, - 0xb0, 0x2e, 0x05, 0xb0, 0x45, 0x44, 0xfa, 0x88, 0x13, 0x2f, 0x99, 0xc4, 0x42, 0x43, 0x5d, 0x40, - 0xe2, 0xca, 0x57, 0x90, 0x8f, 0x60, 0x89, 0x53, 0x04, 0x56, 0x09, 0xdd, 0x1b, 0x55, 0x85, 0x45, - 0x5c, 0x91, 0x29, 0xb5, 0x6c, 0x29, 0x05, 0x89, 0xe4, 0x3e, 0xbc, 0xce, 0x97, 0x72, 0x4a, 0x35, - 0x1b, 0x1f, 0x1b, 0x81, 0xdf, 0x77, 0x05, 0x06, 0x63, 0x91, 0x25, 0x9c, 0x45, 0xbe, 0x82, 0x91, - 0xf8, 0xd0, 0x3f, 0xa1, 0x89, 0x3f, 0xa2, 0xdd, 0x65, 0x4e, 0xe2, 0xb2, 0xcc, 0x18, 0x70, 0x32, - 0xc6, 0x9a, 0x2e, 0x67, 0x78, 0x5e, 0x42, 0x62, 0x1c, 0x86, 0x31, 0x95, 0x9e, 0xa7, 0xee, 0x0d, - 0xc1, 0x5a, 0x3a, 0xd0, 0xfe, 0x23, 0x8b, 0x1f, 0x51, 0x82, 0x9d, 0x63, 0xcd, 0xf8, 0xe2, 0x8c, - 0xec, 0x86, 0xc1, 0xf0, 0x52, 0xf0, 0x36, 0x70, 0xd0, 0x7e, 0x30, 0xbc, 0x64, 0xea, 0xbf, 0x1f, - 0xe8, 0x28, 0x5c, 0x1a, 0x36, 0x25, 0x10, 0x91, 0xde, 0x81, 0xc6, 0x78, 0x72, 0x3c, 0xf4, 0xfb, - 0x1c, 0xa5, 0xcc, 0x5b, 0xe1, 0x20, 0x44, 0x60, 0xd6, 0x27, 0xdf, 0x4f, 0x8e, 0x51, 0x41, 0x8c, - 0x86, 0x80, 0x31, 0x14, 0x7b, 0x1d, 0x16, 0xcd, 0x01, 0x0a, 0xb1, 0xff, 0x00, 0x6a, 0x42, 0x4a, - 0x48, 0x37, 0x44, 0x5b, 0x73, 0x0e, 0x33, 0x63, 0x49, 0xd5, 0xdb, 0x3f, 0x9f, 0x81, 0x05, 0x01, - 0xdd, 0x60, 0xd3, 0x3f, 0x9c, 0x8c, 0x46, 0x5e, 0x54, 0x20, 0x7e, 0xac, 0x37, 0x88, 0x9f, 0x52, - 0x5e, 0xfc, 0xdc, 0x31, 0xac, 0x50, 0x2e, 0xbf, 0x34, 0x08, 0xb9, 0x0f, 0x73, 0x6c, 0xc9, 0xb9, - 0x51, 0xa0, 0xfb, 0x27, 0xb3, 0xe0, 0xbc, 0xc8, 0xac, 0x16, 0x89, 0x4c, 0x5d, 0xdc, 0xcd, 0x64, - 0xc4, 0x9d, 0x0d, 0x4d, 0xbe, 0xbd, 0x42, 0x82, 0xcf, 0x0a, 0x93, 0x4c, 0x83, 0xb1, 0xf1, 0x64, - 0x85, 0x0b, 0x97, 0x64, 0x73, 0x45, 0xa2, 0xc5, 0x1f, 0x51, 0x3c, 0x21, 0x34, 0xec, 0xba, 0x10, - 0x2d, 0xf9, 0x2a, 0xf2, 0x14, 0x80, 0xf7, 0x85, 0x6a, 0x0a, 0xa0, 0x9a, 0xf2, 0x9e, 0xb9, 0x2b, - 0xfa, 0xfa, 0xaf, 0xb0, 0xc2, 0x24, 0xa2, 0xa8, 0xba, 0x68, 0x5f, 0x92, 0x5d, 0x68, 0x87, 0x63, - 0x1a, 0xb8, 0x29, 0x83, 0x37, 0xb0, 0xad, 0x7b, 0x57, 0xb4, 0xb5, 0x23, 0x71, 0x9d, 0xcc, 0xb7, - 0x64, 0x8f, 0xef, 0x00, 0xd5, 0x9a, 0x6b, 0x7e, 0x81, 0xe6, 0xb2, 0x1f, 0xdb, 0x7f, 0xd3, 0x82, - 0x86, 0x36, 0x72, 0x72, 0x1d, 0xe6, 0x37, 0xf6, 0xf7, 0x0f, 0xb6, 0x9c, 0xb5, 0xa3, 0x9d, 0xef, - 0x6d, 0xb9, 0x1b, 0xbb, 0xfb, 0x87, 0x5b, 0x9d, 0x6b, 0x0c, 0xbc, 0xbb, 0xbf, 0xb1, 0xb6, 0xeb, - 0x3e, 0xdd, 0x77, 0x36, 0x24, 0xd8, 0x22, 0x4b, 0x40, 0x9c, 0xad, 0xe7, 0xfb, 0x47, 0x5b, 0x06, - 0xbc, 0x44, 0x3a, 0xd0, 0x5c, 0x77, 0xb6, 0xd6, 0x36, 0xb6, 0x05, 0xa4, 0x4c, 0x16, 0xa1, 0xf3, - 0xf4, 0xc5, 0xde, 0xe6, 0xce, 0xde, 0x33, 0x77, 0x63, 0x6d, 0x6f, 0x63, 0x6b, 0x77, 0x6b, 0xb3, - 0x53, 0x21, 0x2d, 0xa8, 0xaf, 0xad, 0xaf, 0xed, 0x6d, 0xee, 0xef, 0x6d, 0x6d, 0x76, 0xaa, 0xf6, - 0xb7, 0xa0, 0xae, 0x86, 0x4a, 0x1a, 0x30, 0xfb, 0x62, 0xef, 0xd3, 0xbd, 0xfd, 0x97, 0x7b, 0x9d, - 0x6b, 0xa4, 0x0e, 0x55, 0xec, 0xbf, 0x63, 0x11, 0x80, 0x19, 0xde, 0x67, 0xa7, 0x44, 0x6a, 0x50, - 0x59, 0xdf, 0x3f, 0xda, 0xee, 0x94, 0xed, 0xff, 0x6a, 0xc1, 0x75, 0x9c, 0xf3, 0x20, 0xcb, 0xfd, - 0x77, 0xa1, 0xd1, 0x0f, 0xc3, 0x31, 0xb3, 0x7b, 0xd2, 0x93, 0x5d, 0x07, 0x31, 0xce, 0xe6, 0x32, - 0xf1, 0x24, 0x8c, 0xfa, 0x54, 0x30, 0x3f, 0x20, 0xe8, 0x29, 0x83, 0x30, 0xce, 0x16, 0x74, 0xcb, - 0x31, 0x38, 0xef, 0x37, 0x38, 0x8c, 0xa3, 0x2c, 0xc1, 0xcc, 0x71, 0x44, 0xbd, 0xfe, 0x99, 0x60, - 0x7b, 0x51, 0x22, 0x5f, 0x49, 0x0d, 0xf3, 0x3e, 0x23, 0xab, 0x21, 0x1d, 0x20, 0x2b, 0xd4, 0x9c, - 0x39, 0x01, 0xdf, 0x10, 0x60, 0x76, 0x08, 0x78, 0xc7, 0x5e, 0x30, 0x08, 0x03, 0x3a, 0x10, 0x5a, - 0x7f, 0x0a, 0xb0, 0x0f, 0x60, 0x29, 0x3b, 0x3f, 0x21, 0x3c, 0x3e, 0xd2, 0x84, 0x07, 0x57, 0xc2, - 0x7b, 0xd3, 0x69, 0x41, 0x13, 0x24, 0x7f, 0x5e, 0x86, 0x0a, 0xd3, 0xc9, 0xa6, 0xeb, 0x6f, 0xba, - 0x9a, 0x5d, 0xce, 0x45, 0x69, 0xd0, 0xd6, 0xe7, 0x27, 0xb4, 0xf0, 0x33, 0xa5, 0x90, 0xb4, 0x3e, - 0xa2, 0xfd, 0x73, 0xe1, 0x69, 0xd2, 0x20, 0x8c, 0xf3, 0x99, 0x0d, 0x84, 0x5f, 0x0b, 0xce, 0x97, - 0x65, 0x59, 0x87, 0x5f, 0xce, 0xa6, 0x75, 0xf8, 0x5d, 0x17, 0x66, 0xfd, 0xe0, 0x38, 0x9c, 0x04, - 0x03, 0xe4, 0xf4, 0x9a, 0x23, 0x8b, 0x18, 0x17, 0x42, 0x09, 0xc4, 0x8e, 0x0f, 0xce, 0xd7, 0x29, - 0x80, 0xac, 0x42, 0x3d, 0xbe, 0x0c, 0xfa, 0x3a, 0x33, 0x2f, 0x8a, 0x55, 0x62, 0x6b, 0xb0, 0x72, - 0x78, 0x19, 0xf4, 0x91, 0x75, 0x53, 0x34, 0xf2, 0x4d, 0xa8, 0x29, 0xcf, 0x2c, 0x97, 0xca, 0x37, - 0xf4, 0x4f, 0xa4, 0x3b, 0x96, 0x1b, 0xbc, 0x0a, 0xb5, 0xf7, 0x29, 0xb4, 0x8c, 0x2a, 0xdd, 0x4a, - 0x6d, 0x71, 0x2b, 0xf5, 0x9e, 0x6e, 0xa5, 0xa6, 0xc2, 0x5e, 0x7c, 0xa6, 0x5b, 0xad, 0xbf, 0x07, - 0x35, 0x39, 0x34, 0xc6, 0x55, 0x82, 0x23, 0xdc, 0xc3, 0xef, 0xef, 0x6d, 0x74, 0xae, 0x91, 0x39, - 0x68, 0xac, 0x6d, 0x20, 0xa3, 0x22, 0xc0, 0x62, 0x28, 0x07, 0x6b, 0x87, 0x87, 0x0a, 0x52, 0xb2, - 0x09, 0x74, 0xd8, 0x91, 0xc3, 0x46, 0xac, 0x62, 0x2f, 0x1f, 0xc1, 0xbc, 0x06, 0x4b, 0x0d, 0xb9, - 0x31, 0x03, 0x64, 0x0c, 0x39, 0xd4, 0xda, 0x79, 0x8d, 0xbd, 0x0c, 0xd7, 0x59, 0x71, 0xeb, 0x9c, - 0x06, 0xc9, 0xe1, 0xe4, 0x98, 0x87, 0xdc, 0xfc, 0x30, 0xb0, 0xff, 0x9a, 0x05, 0x75, 0x55, 0x73, - 0x05, 0x3d, 0xc9, 0x28, 0x61, 0x09, 0x37, 0xa0, 0xa7, 0x75, 0x81, 0x5f, 0xae, 0xe0, 0xbf, 0x86, - 0xf1, 0x57, 0x57, 0x20, 0x36, 0xd9, 0x83, 0xad, 0x2d, 0xc7, 0xdd, 0xdf, 0xdb, 0xdd, 0xd9, 0x63, - 0x42, 0x89, 0x4d, 0x16, 0x01, 0x4f, 0x9f, 0x22, 0xc4, 0xb2, 0x3b, 0xd0, 0x7e, 0x46, 0x93, 0x9d, - 0xe0, 0x24, 0x94, 0x53, 0xfd, 0x3f, 0x55, 0x98, 0x53, 0xa0, 0xd4, 0x78, 0x3c, 0xa7, 0x51, 0xec, - 0x87, 0x01, 0xaa, 0x7d, 0x75, 0x47, 0x16, 0xd9, 0x79, 0xe2, 0x0f, 0x68, 0x90, 0xf8, 0xc9, 0xa5, - 0x6b, 0x78, 0x9b, 0xb2, 0x60, 0x66, 0xa8, 0x79, 0x43, 0xdf, 0x93, 0xd1, 0x4b, 0x5e, 0x60, 0xd0, - 0x7e, 0x38, 0x0c, 0x23, 0xd4, 0xef, 0xea, 0x0e, 0x2f, 0x90, 0x55, 0x58, 0x64, 0x7a, 0xa5, 0xee, - 0x0b, 0x44, 0x66, 0xe5, 0xae, 0xaf, 0xc2, 0x3a, 0x76, 0x5e, 0x31, 0xb8, 0x50, 0x4a, 0xd4, 0x27, - 0xdc, 0x8c, 0x29, 0xaa, 0x22, 0xdf, 0x80, 0xeb, 0x0c, 0xac, 0x14, 0x19, 0xf5, 0xcd, 0x1c, 0x7e, - 0x53, 0x5c, 0xc9, 0xb8, 0x86, 0xf7, 0xcf, 0x76, 0xbe, 0xca, 0x35, 0x56, 0x05, 0xc8, 0x85, 0x1a, - 0x67, 0xf8, 0x19, 0x9c, 0x0d, 0x35, 0x6a, 0xe1, 0xca, 0x5a, 0x2e, 0x5c, 0xf9, 0x0d, 0xb8, 0x7e, - 0x4c, 0xe3, 0xc4, 0x3d, 0xa3, 0xde, 0x80, 0x46, 0xc8, 0x8d, 0x3c, 0x2a, 0xc9, 0x15, 0xf4, 0xe2, - 0x4a, 0x3c, 0xd9, 0x2f, 0x83, 0x3e, 0x1d, 0xb8, 0x49, 0xe8, 0xa2, 0x06, 0x82, 0x3c, 0x5d, 0x73, - 0xb2, 0x60, 0x13, 0xf3, 0x34, 0xf2, 0xc6, 0x67, 0x42, 0x83, 0xce, 0x82, 0x99, 0xee, 0x93, 0xd0, - 0x38, 0x09, 0x28, 0x8f, 0x09, 0xd5, 0xd0, 0xdf, 0x2f, 0x41, 0xe4, 0x1e, 0xcc, 0x60, 0x83, 0x71, - 0xb7, 0x83, 0x0c, 0xd0, 0x4c, 0x85, 0xa8, 0x1f, 0x38, 0xa2, 0x8e, 0xd9, 0xcb, 0x93, 0xc8, 0x8f, - 0xbb, 0x4d, 0x0c, 0x87, 0xe2, 0xdf, 0xe4, 0x3b, 0x9a, 0x9c, 0x58, 0xc0, 0x6f, 0xe5, 0x61, 0x9c, - 0xa1, 0xbc, 0xdf, 0x8a, 0xc8, 0xf8, 0xa4, 0x52, 0x6b, 0x74, 0x9a, 0xf6, 0xef, 0x40, 0x15, 0x47, - 0x8e, 0x34, 0x89, 0xeb, 0x67, 0x09, 0x9a, 0x44, 0x68, 0x17, 0x66, 0x03, 0x9a, 0x5c, 0x84, 0xd1, - 0x2b, 0x19, 0x7f, 0x17, 0x45, 0xfb, 0x27, 0xe8, 0x54, 0x50, 0xf1, 0xe8, 0x17, 0x68, 0x0d, 0x91, - 0x9b, 0x50, 0xe7, 0x7b, 0x1a, 0x9f, 0x79, 0xc2, 0xcf, 0x51, 0x43, 0xc0, 0xe1, 0x99, 0xc7, 0xce, - 0x47, 0x83, 0x4c, 0xb8, 0xeb, 0xa8, 0x81, 0xb0, 0x6d, 0x4e, 0x25, 0xf7, 0xa0, 0x2d, 0x23, 0xdd, - 0xb1, 0x3b, 0xa4, 0x27, 0x89, 0x74, 0xfc, 0x06, 0x93, 0x11, 0xfa, 0x97, 0x76, 0xe9, 0x49, 0x62, - 0xef, 0xc1, 0xbc, 0x38, 0xb3, 0xf6, 0xc7, 0x54, 0x76, 0xfd, 0xad, 0x22, 0xc5, 0xb6, 0xb1, 0xba, - 0x60, 0x1e, 0x72, 0x3c, 0xb6, 0x6f, 0x62, 0xda, 0x0e, 0x10, 0xfd, 0x0c, 0x14, 0x0d, 0x0a, 0xcd, - 0x52, 0xba, 0xb6, 0xc5, 0x74, 0x0c, 0x18, 0x5b, 0x9f, 0x78, 0xd2, 0xef, 0xcb, 0xfb, 0x09, 0x35, - 0x47, 0x16, 0xed, 0xff, 0x68, 0xc1, 0x02, 0xb6, 0x26, 0x55, 0x73, 0xa1, 0x67, 0x3c, 0xfe, 0x02, - 0xc3, 0x94, 0x81, 0x05, 0xee, 0x4e, 0x5f, 0x84, 0xaa, 0xae, 0x79, 0xf0, 0xc2, 0x17, 0x77, 0x23, - 0x56, 0x72, 0x6e, 0xc4, 0x07, 0xd0, 0x19, 0xd0, 0xa1, 0x8f, 0x77, 0x54, 0xe4, 0x39, 0xce, 0xf5, - 0xf0, 0x1c, 0xdc, 0xfe, 0x3b, 0x16, 0xcc, 0x73, 0x45, 0x01, 0x8d, 0x49, 0xb1, 0x54, 0xff, 0x9f, - 0x34, 0xbc, 0x84, 0x80, 0x12, 0x93, 0x4a, 0x8f, 0x4e, 0x84, 0x72, 0xe4, 0xed, 0x6b, 0x8e, 0x89, - 0x4c, 0x9e, 0xa0, 0x39, 0x11, 0xb8, 0x08, 0x2d, 0xb8, 0xf5, 0x62, 0xee, 0xcb, 0xf6, 0x35, 0x47, - 0x43, 0x5f, 0xaf, 0x31, 0x5b, 0x90, 0xc1, 0xed, 0x67, 0xd0, 0x32, 0x3a, 0x32, 0xdc, 0x9d, 0x4d, - 0xee, 0xee, 0xcc, 0xc5, 0x15, 0x4a, 0x05, 0x71, 0x85, 0x9f, 0x57, 0x80, 0x30, 0xc2, 0xca, 0xec, - 0xdc, 0x5d, 0x33, 0x38, 0x27, 0x2f, 0xc0, 0xa4, 0x20, 0xb2, 0x0a, 0x44, 0x2b, 0xca, 0xa0, 0x61, - 0x59, 0x05, 0x0d, 0x0b, 0x6a, 0x99, 0xd4, 0x17, 0x5a, 0xa5, 0x0a, 0xc8, 0xa1, 0x2b, 0x8b, 0x6f, - 0x53, 0x61, 0x1d, 0xd3, 0x7c, 0x30, 0x3a, 0xc7, 0x8c, 0x6e, 0xe1, 0xfe, 0x91, 0xe5, 0x2c, 0x3d, - 0xcc, 0xbc, 0x91, 0x1e, 0x66, 0x73, 0xf4, 0xa0, 0x39, 0x20, 0x6a, 0xa6, 0x03, 0xe2, 0x1e, 0xb4, - 0x64, 0x10, 0x8e, 0xdf, 0x3f, 0x10, 0xde, 0x1e, 0x03, 0xc8, 0xe8, 0x49, 0xfa, 0x00, 0x94, 0x97, - 0x83, 0x47, 0xd7, 0x73, 0x70, 0x76, 0xb0, 0xa4, 0x8e, 0xe6, 0x06, 0x0e, 0x36, 0x05, 0xa0, 0xcb, - 0x80, 0x51, 0x89, 0x3b, 0x09, 0xc4, 0xe5, 0x17, 0x3a, 0x40, 0x43, 0xa6, 0xe6, 0xe4, 0x2b, 0xf2, - 0xe6, 0x7f, 0xab, 0xc0, 0xfc, 0x27, 0x1f, 0xa5, 0x11, 0xab, 0xf8, 0xcc, 0x1f, 0xe1, 0xd9, 0x9e, - 0xde, 0x1d, 0x79, 0xca, 0xab, 0x0e, 0xcf, 0xfc, 0x91, 0x63, 0xe0, 0xd9, 0xbf, 0xb4, 0xa0, 0xc3, - 0xa8, 0xc2, 0x20, 0xfc, 0x8f, 0x01, 0x79, 0xf4, 0x2d, 0xe9, 0xde, 0xc0, 0x25, 0x8f, 0xa1, 0x8e, - 0x65, 0x66, 0xba, 0x09, 0xaa, 0xef, 0x9a, 0x54, 0x9f, 0x4a, 0xb7, 0xed, 0x6b, 0x4e, 0x8a, 0xcc, - 0xce, 0xb2, 0x6c, 0xc4, 0x90, 0x87, 0xbf, 0xb3, 0x60, 0x8d, 0x3b, 0xb6, 0x01, 0x3e, 0xa5, 0x97, - 0xbb, 0x61, 0x1f, 0xad, 0xa6, 0xdb, 0x00, 0x8c, 0x06, 0x4f, 0xbc, 0x91, 0x2f, 0x5c, 0x1d, 0x55, - 0xa7, 0xfe, 0x8a, 0x5e, 0x3e, 0x45, 0x00, 0x13, 0xe3, 0xac, 0x3a, 0x65, 0x91, 0xaa, 0x53, 0x7b, - 0x45, 0x2f, 0x77, 0x90, 0x3d, 0x5c, 0x68, 0x7d, 0x4a, 0x2f, 0x37, 0x29, 0xd7, 0xeb, 0xc2, 0x88, - 0xd8, 0xd0, 0x8a, 0xbc, 0x0b, 0xa6, 0xb9, 0x19, 0xa1, 0xbe, 0x46, 0xe4, 0x5d, 0x7c, 0x4a, 0x2f, - 0xd7, 0x31, 0xd6, 0xf7, 0x00, 0x66, 0x59, 0xfd, 0x30, 0xec, 0x8b, 0x93, 0x49, 0xde, 0x5e, 0x48, - 0x07, 0xe5, 0xcc, 0xbc, 0xc2, 0xbf, 0xed, 0x7f, 0x6f, 0x41, 0x8b, 0xad, 0x00, 0x8a, 0x3d, 0xb6, - 0x13, 0xf2, 0x12, 0x8c, 0x95, 0x5e, 0x82, 0x59, 0x15, 0x32, 0x83, 0xcb, 0xd0, 0xd2, 0x74, 0x19, - 0x8a, 0xcb, 0xc6, 0x05, 0xe8, 0x87, 0x50, 0xe7, 0xec, 0xc4, 0xd8, 0xb7, 0x6c, 0xec, 0x94, 0x31, - 0x21, 0xa7, 0x86, 0x68, 0x9f, 0xf2, 0x78, 0xbb, 0xe6, 0xac, 0xe2, 0x8b, 0x5c, 0xe7, 0x10, 0x56, - 0x5d, 0x10, 0xba, 0xad, 0x16, 0x85, 0x6e, 0x5f, 0x40, 0x43, 0x23, 0x2c, 0xf2, 0x6d, 0x1e, 0xf4, - 0xe6, 0x83, 0xe7, 0x54, 0x68, 0x12, 0x8e, 0x31, 0x7b, 0x14, 0x98, 0x3a, 0x60, 0x7d, 0x06, 0x2a, - 0x48, 0x92, 0x4f, 0x60, 0x5e, 0x6b, 0x96, 0x5b, 0x88, 0x45, 0x63, 0xb2, 0x8a, 0xc6, 0xf4, 0x87, + 0x20, 0xbf, 0x58, 0xc0, 0x9b, 0x20, 0x08, 0x02, 0x24, 0x41, 0x1e, 0x82, 0x0d, 0xe0, 0x3c, 0xe5, + 0x61, 0xf3, 0x12, 0xe4, 0x21, 0x01, 0x02, 0x24, 0x40, 0x80, 0xc5, 0xe6, 0x21, 0x8b, 0x00, 0x79, + 0x4a, 0xf2, 0x1c, 0xdc, 0x73, 0x7f, 0xea, 0xde, 0xaa, 0x6a, 0x4a, 0x63, 0x3b, 0x7e, 0x91, 0x78, + 0xcf, 0x3d, 0x75, 0x7f, 0xcf, 0x39, 0xf7, 0xfc, 0xdc, 0x73, 0x1b, 0xea, 0xd1, 0xb8, 0xbf, 0x32, + 0x8e, 0xc2, 0x24, 0x24, 0xd5, 0x61, 0x10, 0x8d, 0xfb, 0xbd, 0x5b, 0xa7, 0x61, 0x78, 0x3a, 0xa4, + 0x0f, 0xbd, 0xb1, 0xff, 0xd0, 0x0b, 0x82, 0x30, 0xf1, 0x12, 0x3f, 0x0c, 0x62, 0x8e, 0x64, 0xff, + 0x08, 0xda, 0xcf, 0x68, 0x70, 0x48, 0xe9, 0xc0, 0xa1, 0x9f, 0x4d, 0x68, 0x9c, 0x90, 0xaf, 0xc2, + 0xbc, 0x47, 0x7f, 0x42, 0xe9, 0xc0, 0x1d, 0x7b, 0x71, 0x3c, 0x3e, 0x8b, 0xbc, 0x98, 0x76, 0xad, + 0xbb, 0xd6, 0xfd, 0xa6, 0xd3, 0xe1, 0x15, 0x07, 0x0a, 0x4e, 0xde, 0x85, 0x66, 0xcc, 0x50, 0x69, + 0x90, 0x44, 0xe1, 0xf8, 0xb2, 0x5b, 0x42, 0xbc, 0x06, 0x83, 0x6d, 0x71, 0x90, 0x3d, 0x84, 0x39, + 0xd5, 0x43, 0x3c, 0x0e, 0x83, 0x98, 0x92, 0x47, 0xb0, 0xd8, 0xf7, 0xc7, 0x67, 0x34, 0x72, 0xf1, + 0xe3, 0x51, 0x40, 0x47, 0x61, 0xe0, 0xf7, 0xbb, 0xd6, 0xdd, 0xf2, 0xfd, 0xba, 0x43, 0x78, 0x1d, + 0xfb, 0xe2, 0xb9, 0xa8, 0x21, 0xef, 0xc3, 0x1c, 0x0d, 0x38, 0x9c, 0x0e, 0xf0, 0x2b, 0xd1, 0x55, + 0x3b, 0x05, 0xb3, 0x0f, 0xec, 0xbf, 0x56, 0x82, 0xf9, 0x9d, 0xc0, 0x4f, 0x5e, 0x7a, 0xc3, 0x21, + 0x4d, 0xe4, 0x9c, 0xde, 0x87, 0xb9, 0x0b, 0x04, 0xe0, 0x9c, 0x2e, 0xc2, 0x68, 0x20, 0x66, 0xd4, + 0xe6, 0xe0, 0x03, 0x01, 0x9d, 0x3a, 0xb2, 0xd2, 0xd4, 0x91, 0x15, 0x2e, 0x57, 0x79, 0xca, 0x72, + 0xbd, 0x0f, 0x73, 0x11, 0xed, 0x87, 0xe7, 0x34, 0xba, 0x74, 0x2f, 0xfc, 0x60, 0x10, 0x5e, 0x74, + 0x2b, 0x77, 0xad, 0xfb, 0x55, 0xa7, 0x2d, 0xc1, 0x2f, 0x11, 0x4a, 0xd6, 0x61, 0xae, 0x7f, 0xe6, + 0x05, 0x01, 0x1d, 0xba, 0xc7, 0x5e, 0xff, 0xd5, 0x64, 0x1c, 0x77, 0xab, 0x77, 0xad, 0xfb, 0x8d, + 0xd5, 0x1b, 0x2b, 0xb8, 0xab, 0x2b, 0x1b, 0x67, 0x5e, 0xb0, 0x8e, 0x35, 0x87, 0x81, 0x37, 0x8e, + 0xcf, 0xc2, 0xc4, 0x69, 0x8b, 0x2f, 0x38, 0x38, 0xb6, 0x17, 0x81, 0xe8, 0x2b, 0xc1, 0xd7, 0xde, + 0xfe, 0x27, 0x16, 0x2c, 0xbc, 0x08, 0x86, 0x61, 0xff, 0xd5, 0xaf, 0xb8, 0x44, 0x05, 0x73, 0x28, + 0xbd, 0xed, 0x1c, 0xca, 0x5f, 0x74, 0x0e, 0x4b, 0xb0, 0x68, 0x0e, 0x56, 0xcc, 0x82, 0xc2, 0x75, + 0xf6, 0xf5, 0x29, 0x95, 0xc3, 0x92, 0xd3, 0xf8, 0x0a, 0x74, 0xfa, 0x93, 0x28, 0xa2, 0x41, 0x6e, + 0x1e, 0x73, 0x02, 0xae, 0x26, 0xf2, 0x2e, 0x34, 0x03, 0x7a, 0x91, 0xa2, 0x09, 0xda, 0x0d, 0xe8, + 0x85, 0x44, 0xb1, 0xbb, 0xb0, 0x94, 0xed, 0x46, 0x0c, 0xe0, 0x4f, 0x2d, 0xa8, 0xbc, 0x48, 0x5e, + 0x87, 0x64, 0x05, 0x2a, 0xc9, 0xe5, 0x98, 0x73, 0x48, 0x7b, 0x95, 0x88, 0xa9, 0xad, 0x0d, 0x06, + 0x11, 0x8d, 0xe3, 0xa3, 0xcb, 0x31, 0x75, 0x9a, 0x1e, 0x2f, 0xb8, 0x0c, 0x8f, 0x74, 0x61, 0x56, + 0x94, 0xb1, 0xc3, 0xba, 0x23, 0x8b, 0xe4, 0x0e, 0x80, 0x37, 0x0a, 0x27, 0x41, 0xe2, 0xc6, 0x5e, + 0x82, 0x4b, 0x55, 0x76, 0x34, 0x08, 0xb9, 0x05, 0xf5, 0xf1, 0x2b, 0x37, 0xee, 0x47, 0xfe, 0x38, + 0x41, 0xb2, 0xa9, 0x3b, 0x29, 0x80, 0x7c, 0x15, 0x6a, 0xe1, 0x24, 0x19, 0x87, 0x7e, 0x90, 0x08, + 0x52, 0x99, 0x13, 0x63, 0xd9, 0x9f, 0x24, 0x07, 0x0c, 0xec, 0x28, 0x04, 0x72, 0x0f, 0x5a, 0xfd, + 0x30, 0x38, 0xf1, 0xa3, 0x11, 0x17, 0x06, 0xdd, 0x19, 0xec, 0xcd, 0x04, 0xda, 0xff, 0xaa, 0x04, + 0x8d, 0xa3, 0xc8, 0x0b, 0x62, 0xaf, 0xcf, 0x00, 0x6c, 0xe8, 0xc9, 0x6b, 0xf7, 0xcc, 0x8b, 0xcf, + 0x70, 0xb6, 0x75, 0x47, 0x16, 0xc9, 0x12, 0xcc, 0xf0, 0x81, 0xe2, 0x9c, 0xca, 0x8e, 0x28, 0x91, + 0x0f, 0x60, 0x3e, 0x98, 0x8c, 0x5c, 0xb3, 0xaf, 0x32, 0x52, 0x4b, 0xbe, 0x82, 0x2d, 0xc0, 0x31, + 0xdb, 0x6b, 0xde, 0x05, 0x9f, 0xa1, 0x06, 0x21, 0x36, 0x34, 0x45, 0x89, 0xfa, 0xa7, 0x67, 0x7c, + 0x9a, 0x55, 0xc7, 0x80, 0xb1, 0x36, 0x12, 0x7f, 0x44, 0xdd, 0x38, 0xf1, 0x46, 0x63, 0x31, 0x2d, + 0x0d, 0x82, 0xf5, 0x61, 0xe2, 0x0d, 0xdd, 0x13, 0x4a, 0xe3, 0xee, 0xac, 0xa8, 0x57, 0x10, 0xf2, + 0x1e, 0xb4, 0x07, 0x34, 0x4e, 0x5c, 0xb1, 0x29, 0x34, 0xee, 0xd6, 0x90, 0xf5, 0x33, 0x50, 0xd6, + 0x4e, 0xe4, 0x5d, 0xb8, 0x6c, 0x01, 0xe8, 0xeb, 0x6e, 0x9d, 0x8f, 0x35, 0x85, 0x30, 0xca, 0x79, + 0x46, 0x13, 0x6d, 0xf5, 0x62, 0x41, 0xa1, 0xf6, 0x2e, 0x10, 0x0d, 0xbc, 0x49, 0x13, 0xcf, 0x1f, + 0xc6, 0xe4, 0x23, 0x68, 0x26, 0x1a, 0x32, 0x8a, 0xc2, 0x86, 0x22, 0x27, 0xed, 0x03, 0xc7, 0xc0, + 0xb3, 0xcf, 0xa0, 0xf6, 0x94, 0xd2, 0x5d, 0x7f, 0xe4, 0x27, 0x64, 0x09, 0xaa, 0x27, 0xfe, 0x6b, + 0xca, 0x09, 0xbe, 0xbc, 0x7d, 0xcd, 0xe1, 0x45, 0xf2, 0x0e, 0x00, 0xfe, 0xe1, 0x8e, 0x14, 0x61, + 0x6d, 0x5f, 0x73, 0xea, 0x08, 0x7b, 0xce, 0x28, 0xab, 0x07, 0xb3, 0x63, 0x1a, 0xf5, 0xa9, 0xdc, + 0xbf, 0xed, 0x6b, 0x8e, 0x04, 0xac, 0xcf, 0x42, 0x75, 0xc8, 0x5a, 0xb7, 0xff, 0xa4, 0x0a, 0x8d, + 0x43, 0x1a, 0x28, 0x4e, 0x23, 0x50, 0x61, 0x6b, 0x22, 0xb8, 0x0b, 0xff, 0x26, 0x5f, 0x82, 0x06, + 0xae, 0x53, 0x9c, 0x44, 0x7e, 0x70, 0xca, 0x09, 0x7c, 0xbd, 0xd4, 0xb5, 0x1c, 0x60, 0xe0, 0x43, + 0x84, 0x92, 0x0e, 0x94, 0xbd, 0x91, 0x24, 0x70, 0xf6, 0x27, 0xb9, 0x01, 0x35, 0x6f, 0x94, 0xf0, + 0xe1, 0x35, 0x11, 0x3c, 0xeb, 0x8d, 0x12, 0x1c, 0xda, 0xbb, 0xd0, 0x1c, 0x7b, 0x97, 0x23, 0xc6, + 0xcf, 0x8a, 0x2a, 0x9a, 0x4e, 0x43, 0xc0, 0xb6, 0x19, 0x59, 0xac, 0xc2, 0x82, 0x8e, 0x22, 0x3b, + 0xaf, 0xaa, 0xce, 0xe7, 0x35, 0x6c, 0x31, 0x86, 0xf7, 0x61, 0x4e, 0x7e, 0x13, 0xf1, 0xf9, 0x20, + 0xad, 0xd4, 0x9d, 0xb6, 0x00, 0xcb, 0x59, 0xde, 0x87, 0xce, 0x89, 0x1f, 0x78, 0x43, 0xb7, 0x3f, + 0x4c, 0xce, 0xdd, 0x01, 0x1d, 0x26, 0x1e, 0x52, 0x4d, 0xd5, 0x69, 0x23, 0x7c, 0x63, 0x98, 0x9c, + 0x6f, 0x32, 0x28, 0xf9, 0x00, 0xea, 0x27, 0x94, 0xba, 0xb8, 0x58, 0xdd, 0x9a, 0xc1, 0x81, 0x72, + 0x87, 0x9c, 0xda, 0x89, 0xdc, 0xab, 0x0f, 0xa0, 0x13, 0x4e, 0x92, 0xd3, 0xd0, 0x0f, 0x4e, 0x5d, + 0x26, 0xf3, 0x5c, 0x7f, 0x80, 0x54, 0x54, 0x59, 0x2f, 0x3d, 0xb2, 0x9c, 0xb6, 0xac, 0x63, 0xd2, + 0x67, 0x67, 0x40, 0xde, 0x83, 0xb9, 0xa1, 0x17, 0x27, 0xee, 0x59, 0x38, 0x76, 0xc7, 0x93, 0xe3, + 0x57, 0xf4, 0xb2, 0xdb, 0xc2, 0x85, 0x68, 0x31, 0xf0, 0x76, 0x38, 0x3e, 0x40, 0x20, 0xb9, 0x0d, + 0x80, 0xe3, 0xe4, 0x83, 0x80, 0xbb, 0xd6, 0xfd, 0x96, 0x53, 0x67, 0x10, 0xde, 0xe9, 0xf7, 0x61, + 0x01, 0xb7, 0xa7, 0x3f, 0x89, 0x93, 0x70, 0xe4, 0x32, 0x79, 0x1d, 0x0d, 0xe2, 0x6e, 0x03, 0x69, + 0xed, 0x2b, 0x62, 0xb0, 0xda, 0x1e, 0xaf, 0x6c, 0xd2, 0x38, 0xd9, 0x40, 0x64, 0x87, 0xe3, 0xb2, + 0x43, 0xfd, 0xd2, 0x99, 0x1f, 0x64, 0xe1, 0xe4, 0x03, 0x20, 0xde, 0x70, 0x18, 0x5e, 0xb8, 0x31, + 0x1d, 0x9e, 0xb8, 0x62, 0x11, 0xbb, 0xed, 0xbb, 0xd6, 0xfd, 0x9a, 0xd3, 0xc1, 0x9a, 0x43, 0x3a, + 0x3c, 0x39, 0xe0, 0x70, 0xf2, 0x11, 0xb4, 0x70, 0x20, 0x27, 0xd4, 0x4b, 0x26, 0x11, 0x8d, 0xbb, + 0x73, 0x77, 0xcb, 0xf7, 0xdb, 0xab, 0xf3, 0x6a, 0xbd, 0x10, 0xbc, 0xee, 0x27, 0x4e, 0x93, 0xe1, + 0x89, 0x72, 0xdc, 0xdb, 0x84, 0xa5, 0xe2, 0x21, 0x31, 0xa2, 0x62, 0xab, 0xc2, 0x88, 0xb1, 0xe2, + 0xb0, 0x3f, 0xc9, 0x22, 0x54, 0xcf, 0xbd, 0xe1, 0x84, 0x0a, 0xb9, 0xce, 0x0b, 0x1f, 0x97, 0x1e, + 0x5b, 0xf6, 0x1f, 0x5b, 0xd0, 0xe4, 0xb3, 0x14, 0xfa, 0xc8, 0x3d, 0x68, 0x49, 0x6a, 0xa0, 0x51, + 0x14, 0x46, 0x42, 0xbc, 0x99, 0x40, 0xf2, 0x00, 0x3a, 0x12, 0x30, 0x8e, 0xa8, 0x3f, 0xf2, 0x4e, + 0x65, 0xdb, 0x39, 0x38, 0x59, 0x4d, 0x5b, 0x8c, 0xc2, 0x49, 0x42, 0xc5, 0xc9, 0xd7, 0x14, 0x13, + 0x74, 0x18, 0xcc, 0x31, 0x51, 0x98, 0x78, 0x2b, 0x20, 0x75, 0x03, 0x66, 0xff, 0x4d, 0x0b, 0x08, + 0x1b, 0xfa, 0x51, 0xc8, 0x9b, 0x10, 0x54, 0x9a, 0xe5, 0x12, 0xeb, 0xad, 0xb9, 0xa4, 0x74, 0x15, + 0x97, 0xd8, 0x50, 0xe5, 0xa3, 0xaf, 0x14, 0x8c, 0x9e, 0x57, 0x7d, 0x52, 0xa9, 0x95, 0x3b, 0x15, + 0xfb, 0x3f, 0x97, 0x61, 0x71, 0x83, 0x1f, 0xdd, 0x6b, 0xfd, 0x3e, 0x1d, 0x2b, 0xfe, 0x79, 0x07, + 0x1a, 0x41, 0x38, 0xa0, 0x92, 0x6a, 0xf9, 0xc0, 0x80, 0x81, 0x34, 0x92, 0x3d, 0xf3, 0xfc, 0x80, + 0x0f, 0x9c, 0xaf, 0x67, 0x1d, 0x21, 0x38, 0xec, 0xf7, 0x60, 0x6e, 0x4c, 0x83, 0x81, 0xce, 0x26, + 0x5c, 0xb9, 0x6a, 0x09, 0xb0, 0xe0, 0x90, 0x77, 0xa0, 0x71, 0x32, 0xe1, 0x78, 0x4c, 0xb8, 0x54, + 0x90, 0x0e, 0x40, 0x80, 0xd6, 0xb8, 0x8c, 0x19, 0x4f, 0xe2, 0x33, 0xac, 0xad, 0x62, 0xed, 0x2c, + 0x2b, 0xb3, 0xaa, 0xdb, 0x00, 0x83, 0x49, 0x9c, 0x08, 0xae, 0x99, 0xc1, 0xca, 0x3a, 0x83, 0x70, + 0xae, 0xf9, 0x1a, 0x2c, 0x8c, 0xbc, 0xd7, 0x2e, 0xd2, 0x8f, 0xeb, 0x07, 0xee, 0xc9, 0x10, 0x4f, + 0x9f, 0x59, 0xc4, 0xeb, 0x8c, 0xbc, 0xd7, 0xdf, 0x63, 0x35, 0x3b, 0xc1, 0x53, 0x84, 0x33, 0xd1, + 0x22, 0xd5, 0x9e, 0x88, 0xc6, 0x34, 0x3a, 0xa7, 0x28, 0x0d, 0x2a, 0x4a, 0xb7, 0x71, 0x38, 0x94, + 0x8d, 0x68, 0xc4, 0xe6, 0x9d, 0x0c, 0xfb, 0x9c, 0xf5, 0x9d, 0xd9, 0x91, 0x1f, 0x6c, 0x27, 0xc3, + 0x3e, 0xb9, 0x05, 0xc0, 0x64, 0xc9, 0x98, 0x46, 0xee, 0xab, 0x0b, 0xe4, 0xe3, 0x0a, 0xca, 0x8e, + 0x03, 0x1a, 0x7d, 0x7a, 0x41, 0x6e, 0x42, 0xbd, 0x1f, 0xa3, 0x30, 0xf2, 0x2e, 0xbb, 0x0d, 0x64, + 0xf2, 0x5a, 0x3f, 0x66, 0x62, 0xc8, 0xbb, 0x64, 0x8c, 0xc8, 0x46, 0xeb, 0xe1, 0x2e, 0xd0, 0x01, + 0x36, 0x1f, 0xa3, 0x54, 0x6d, 0xe1, 0x60, 0xd7, 0x44, 0x05, 0xeb, 0x27, 0x26, 0x5f, 0x82, 0x96, + 0x1c, 0xec, 0xc9, 0xd0, 0x3b, 0x8d, 0x51, 0xac, 0xb4, 0x9c, 0xa6, 0x00, 0x3e, 0x65, 0x30, 0xfb, + 0x25, 0x57, 0xb6, 0xb4, 0xbd, 0x15, 0x7c, 0xc3, 0x8e, 0x7d, 0x84, 0xe0, 0xbe, 0xd6, 0x1c, 0x51, + 0x2a, 0xda, 0xb4, 0x52, 0xc1, 0xa6, 0xd9, 0xbf, 0xb0, 0xa0, 0x29, 0x5a, 0x46, 0x0d, 0x85, 0x3c, + 0x02, 0x22, 0x77, 0x31, 0x79, 0xed, 0x0f, 0xdc, 0xe3, 0xcb, 0x84, 0xc6, 0x9c, 0x68, 0xb6, 0xaf, + 0x39, 0x05, 0x75, 0x4c, 0x8e, 0x1a, 0xd0, 0x38, 0x89, 0x38, 0x4d, 0x6f, 0x5f, 0x73, 0x72, 0x35, + 0x8c, 0xc5, 0x98, 0x0e, 0x34, 0x49, 0x5c, 0x3f, 0x18, 0xd0, 0xd7, 0x48, 0x4a, 0x2d, 0xc7, 0x80, + 0xad, 0xb7, 0xa1, 0xa9, 0x7f, 0x67, 0xff, 0x18, 0x6a, 0x52, 0x83, 0x42, 0xed, 0x21, 0x33, 0x2e, + 0x47, 0x83, 0x90, 0x1e, 0xd4, 0xcc, 0x51, 0x38, 0xb5, 0x2f, 0xd2, 0xb7, 0xfd, 0x6d, 0xe8, 0xec, + 0x32, 0x22, 0x0a, 0x18, 0xd1, 0x0a, 0xb5, 0x70, 0x09, 0x66, 0x34, 0xe6, 0xa9, 0x3b, 0xa2, 0xc4, + 0xce, 0xdf, 0xb3, 0x30, 0x4e, 0x44, 0x3f, 0xf8, 0xb7, 0xfd, 0x27, 0x16, 0x90, 0xad, 0x38, 0xf1, + 0x47, 0x5e, 0x42, 0x9f, 0x52, 0x25, 0x1e, 0xf6, 0xa1, 0xc9, 0x5a, 0x3b, 0x0a, 0xd7, 0xb8, 0x92, + 0xc6, 0x95, 0x8b, 0xaf, 0x0a, 0x76, 0xce, 0x7f, 0xb0, 0xa2, 0x63, 0x73, 0x91, 0x6f, 0x34, 0xc0, + 0xb8, 0x2d, 0xf1, 0xa2, 0x53, 0x9a, 0xa0, 0x06, 0x27, 0xf4, 0x7f, 0xe0, 0xa0, 0x8d, 0x30, 0x38, + 0xe9, 0xfd, 0x1e, 0xcc, 0xe7, 0xda, 0xd0, 0x65, 0x74, 0xbd, 0x40, 0x46, 0x97, 0x75, 0x19, 0xdd, + 0x87, 0x05, 0x63, 0x5c, 0x82, 0xe2, 0xba, 0x30, 0xcb, 0x18, 0x83, 0x29, 0x0a, 0x16, 0x57, 0x14, + 0x44, 0x91, 0xac, 0xc2, 0xe2, 0x09, 0xa5, 0x91, 0x97, 0x60, 0x11, 0x59, 0x87, 0xed, 0x89, 0x68, + 0xb9, 0xb0, 0xce, 0xfe, 0x33, 0x0b, 0xe6, 0x98, 0x34, 0x7d, 0xee, 0x05, 0x97, 0x72, 0xad, 0x76, + 0x0b, 0xd7, 0xea, 0xbe, 0x76, 0x38, 0x6a, 0xd8, 0x5f, 0x74, 0xa1, 0xca, 0xd9, 0x85, 0x22, 0x77, + 0xa1, 0x69, 0x0c, 0xb7, 0xca, 0x35, 0xd2, 0xd8, 0x4b, 0x0e, 0x68, 0xb4, 0x7e, 0x99, 0xd0, 0x5f, + 0x7f, 0x29, 0xdf, 0x83, 0x4e, 0x3a, 0x6c, 0xb1, 0x8e, 0x04, 0x2a, 0x8c, 0x30, 0x45, 0x03, 0xf8, + 0xb7, 0xfd, 0xf7, 0x2c, 0x8e, 0xb8, 0x11, 0xfa, 0x4a, 0x5b, 0x65, 0x88, 0x4c, 0xe9, 0x95, 0x88, + 0xec, 0xef, 0xa9, 0xda, 0xfe, 0xaf, 0x3f, 0x59, 0x26, 0x13, 0x63, 0x1a, 0x0c, 0x5c, 0x6f, 0x38, + 0x44, 0x41, 0x5c, 0x73, 0x66, 0x59, 0x79, 0x6d, 0x38, 0xb4, 0xdf, 0x87, 0x79, 0x6d, 0x74, 0x57, + 0xcc, 0x63, 0x0f, 0xc8, 0xae, 0x1f, 0x27, 0x2f, 0x82, 0x78, 0xac, 0x29, 0x72, 0x37, 0xa1, 0xce, + 0xa4, 0x2d, 0x1b, 0x19, 0xe7, 0xdc, 0xaa, 0xc3, 0xc4, 0x2f, 0x1b, 0x57, 0x8c, 0x95, 0xde, 0x6b, + 0x51, 0x59, 0x12, 0x95, 0xde, 0x6b, 0xac, 0xb4, 0x1f, 0xc3, 0x82, 0xd1, 0x9e, 0xe8, 0xfa, 0x5d, + 0xa8, 0x4e, 0x92, 0xd7, 0xa1, 0x54, 0xd5, 0x1b, 0x82, 0x42, 0x98, 0x51, 0xe8, 0xf0, 0x1a, 0xfb, + 0x09, 0xcc, 0xef, 0xd1, 0x0b, 0xc1, 0xc8, 0x72, 0x20, 0xef, 0xbd, 0xd1, 0x60, 0xc4, 0x7a, 0x7b, + 0x05, 0x88, 0xfe, 0x71, 0xca, 0x00, 0xd2, 0x7c, 0xb4, 0x0c, 0xf3, 0xd1, 0x7e, 0x0f, 0xc8, 0xa1, + 0x7f, 0x1a, 0x3c, 0xa7, 0x71, 0xec, 0x9d, 0x2a, 0xd6, 0xef, 0x40, 0x79, 0x14, 0x9f, 0x0a, 0x51, + 0xc5, 0xfe, 0xb4, 0xbf, 0x0e, 0x0b, 0x06, 0x9e, 0x68, 0xf8, 0x16, 0xd4, 0x63, 0xff, 0x34, 0x40, + 0x45, 0x4b, 0x34, 0x9d, 0x02, 0xec, 0xa7, 0xb0, 0xf8, 0x3d, 0x1a, 0xf9, 0x27, 0x97, 0x6f, 0x6a, + 0xde, 0x6c, 0xa7, 0x94, 0x6d, 0x67, 0x0b, 0xae, 0x67, 0xda, 0x11, 0xdd, 0x73, 0xf2, 0x15, 0x3b, + 0x59, 0x73, 0x78, 0x41, 0x93, 0x7d, 0x25, 0x5d, 0xf6, 0xd9, 0x2f, 0x80, 0x6c, 0x84, 0x41, 0x40, + 0xfb, 0xc9, 0x01, 0xa5, 0x51, 0xea, 0xb9, 0x4a, 0x69, 0xb5, 0xb1, 0xba, 0x2c, 0x56, 0x36, 0x2b, + 0x50, 0x05, 0x11, 0x13, 0xa8, 0x8c, 0x69, 0x34, 0xc2, 0x86, 0x6b, 0x0e, 0xfe, 0x6d, 0x5f, 0x87, + 0x05, 0xa3, 0x59, 0x61, 0xeb, 0x7f, 0x08, 0xd7, 0x37, 0xfd, 0xb8, 0x9f, 0xef, 0xb0, 0x0b, 0xb3, + 0xe3, 0xc9, 0xb1, 0x9b, 0x72, 0xa2, 0x2c, 0x32, 0xf3, 0x2f, 0xfb, 0x89, 0x68, 0xec, 0xaf, 0x5a, + 0x50, 0xd9, 0x3e, 0xda, 0xdd, 0x60, 0x67, 0x85, 0x1f, 0xf4, 0xc3, 0x11, 0xd3, 0xc2, 0xf8, 0xa4, + 0x55, 0x79, 0x2a, 0x87, 0xdd, 0x82, 0x3a, 0x2a, 0x6f, 0xcc, 0xe2, 0x15, 0x7a, 0x50, 0x0a, 0x60, + 0xd6, 0x36, 0x7d, 0x3d, 0xf6, 0x23, 0x34, 0xa7, 0xa5, 0x91, 0x5c, 0xc1, 0x63, 0x26, 0x5f, 0x61, + 0xff, 0xdb, 0x59, 0x98, 0x15, 0x87, 0x2f, 0x3f, 0xc8, 0x13, 0xff, 0x9c, 0xa6, 0x07, 0x39, 0x2b, + 0x31, 0xc5, 0x38, 0xa2, 0xa3, 0x30, 0x51, 0xfa, 0x1b, 0xdf, 0x06, 0x13, 0x88, 0xde, 0x04, 0xa1, + 0x44, 0x70, 0xff, 0x43, 0x99, 0x63, 0x19, 0x40, 0x72, 0x0b, 0x66, 0xa5, 0x32, 0x50, 0x51, 0x86, + 0x8e, 0x04, 0xb1, 0xd5, 0xe8, 0x7b, 0x63, 0xaf, 0xef, 0x27, 0x97, 0x42, 0x2c, 0xa8, 0x32, 0x6b, + 0x7f, 0x18, 0xf6, 0xbd, 0xa1, 0x7b, 0xec, 0x0d, 0xbd, 0xa0, 0x4f, 0xa5, 0xb7, 0xc2, 0x00, 0x32, + 0xcb, 0x5d, 0x0c, 0x4b, 0xa2, 0x71, 0xeb, 0x3e, 0x03, 0x65, 0x67, 0x78, 0x3f, 0x1c, 0x8d, 0x7c, + 0x66, 0x7d, 0x70, 0xd5, 0xac, 0xec, 0x68, 0x10, 0xee, 0x1b, 0xc1, 0xd2, 0x05, 0x5f, 0xc1, 0xba, + 0xf4, 0x8d, 0x68, 0x40, 0xd6, 0x4a, 0x46, 0x43, 0x2b, 0x3b, 0x1a, 0x84, 0xed, 0xc5, 0x24, 0x88, + 0x69, 0x92, 0x0c, 0xe9, 0x40, 0x0d, 0xa8, 0x81, 0x68, 0xf9, 0x0a, 0xf2, 0x08, 0x16, 0xb8, 0x0f, + 0x22, 0xf6, 0x92, 0x30, 0x3e, 0xf3, 0x63, 0x37, 0x66, 0xe6, 0x13, 0xb7, 0x85, 0x8b, 0xaa, 0xc8, + 0x63, 0x58, 0xce, 0x80, 0x23, 0xda, 0xa7, 0xfe, 0x39, 0x1d, 0xa0, 0x0a, 0x57, 0x76, 0xa6, 0x55, + 0x93, 0xbb, 0xd0, 0x08, 0x26, 0x23, 0x77, 0x32, 0x1e, 0x78, 0x4c, 0x89, 0x69, 0xa3, 0x72, 0xa9, + 0x83, 0xc8, 0x87, 0x20, 0xf5, 0x34, 0xa1, 0x3d, 0xce, 0x19, 0x12, 0x8e, 0x51, 0xaf, 0x63, 0x62, + 0x30, 0xc2, 0x4c, 0x55, 0xd2, 0x8e, 0xb0, 0x3b, 0x25, 0x00, 0xf9, 0x24, 0xf2, 0xcf, 0xbd, 0x84, + 0x76, 0xe7, 0xb9, 0x50, 0x17, 0x45, 0xf6, 0x9d, 0x1f, 0xf8, 0x89, 0xef, 0x25, 0x61, 0xd4, 0x25, + 0x58, 0x97, 0x02, 0xd8, 0x22, 0x22, 0x7d, 0xc4, 0x89, 0x97, 0x4c, 0x62, 0xa1, 0xa1, 0x2e, 0x20, + 0x71, 0xe5, 0x2b, 0xc8, 0x47, 0xb0, 0xc4, 0x29, 0x02, 0xab, 0x84, 0xee, 0x8d, 0xaa, 0xc2, 0x22, + 0xae, 0xc8, 0x94, 0x5a, 0xb6, 0x94, 0x82, 0x44, 0x72, 0x1f, 0x5e, 0xe7, 0x4b, 0x39, 0xa5, 0x9a, + 0x8d, 0x8f, 0x8d, 0xc0, 0xef, 0xbb, 0x02, 0x83, 0xb1, 0xc8, 0x12, 0xce, 0x22, 0x5f, 0xc1, 0x48, + 0x7c, 0xe8, 0x9f, 0xd0, 0xc4, 0x1f, 0xd1, 0xee, 0x32, 0x27, 0x71, 0x59, 0x66, 0x0c, 0x38, 0x19, + 0x63, 0x4d, 0x97, 0x33, 0x3c, 0x2f, 0x21, 0x31, 0x0e, 0xc3, 0x98, 0x4a, 0xcf, 0x53, 0xf7, 0x86, + 0x60, 0x2d, 0x1d, 0x68, 0xff, 0xa1, 0xc5, 0x8f, 0x28, 0xc1, 0xce, 0xb1, 0x66, 0x7c, 0x71, 0x46, + 0x76, 0xc3, 0x60, 0x78, 0x29, 0x78, 0x1b, 0x38, 0x68, 0x3f, 0x18, 0x5e, 0x32, 0xf5, 0xdf, 0x0f, + 0x74, 0x14, 0x2e, 0x0d, 0x9b, 0x12, 0x88, 0x48, 0xef, 0x40, 0x63, 0x3c, 0x39, 0x1e, 0xfa, 0x7d, + 0x8e, 0x52, 0xe6, 0xad, 0x70, 0x10, 0x22, 0x30, 0xeb, 0x93, 0xef, 0x27, 0xc7, 0xa8, 0x20, 0x46, + 0x43, 0xc0, 0x18, 0x8a, 0xbd, 0x0e, 0x8b, 0xe6, 0x00, 0x85, 0xd8, 0x7f, 0x00, 0x35, 0x21, 0x25, + 0xa4, 0x1b, 0xa2, 0xad, 0x39, 0x87, 0x99, 0xb1, 0xa4, 0xea, 0xed, 0x9f, 0xcf, 0xc0, 0x82, 0x80, + 0x6e, 0xb0, 0xe9, 0x1f, 0x4e, 0x46, 0x23, 0x2f, 0x2a, 0x10, 0x3f, 0xd6, 0x1b, 0xc4, 0x4f, 0x29, + 0x2f, 0x7e, 0xee, 0x18, 0x56, 0x28, 0x97, 0x5f, 0x1a, 0x84, 0xdc, 0x87, 0x39, 0xb6, 0xe4, 0xdc, + 0x28, 0xd0, 0xfd, 0x93, 0x59, 0x70, 0x5e, 0x64, 0x56, 0x8b, 0x44, 0xa6, 0x2e, 0xee, 0x66, 0x32, + 0xe2, 0xce, 0x86, 0x26, 0xdf, 0x5e, 0x21, 0xc1, 0x67, 0x85, 0x49, 0xa6, 0xc1, 0xd8, 0x78, 0xb2, + 0xc2, 0x85, 0x4b, 0xb2, 0xb9, 0x22, 0xd1, 0xe2, 0x8f, 0x28, 0x9e, 0x10, 0x1a, 0x76, 0x5d, 0x88, + 0x96, 0x7c, 0x15, 0x79, 0x0a, 0xc0, 0xfb, 0x42, 0x35, 0x05, 0x50, 0x4d, 0x79, 0xcf, 0xdc, 0x15, + 0x7d, 0xfd, 0x57, 0x58, 0x61, 0x12, 0x51, 0x54, 0x5d, 0xb4, 0x2f, 0xc9, 0x2e, 0xb4, 0xc3, 0x31, + 0x0d, 0xdc, 0x94, 0xc1, 0x1b, 0xd8, 0xd6, 0xbd, 0x2b, 0xda, 0xda, 0x91, 0xb8, 0x4e, 0xe6, 0x5b, + 0xb2, 0xc7, 0x77, 0x80, 0x6a, 0xcd, 0x35, 0xbf, 0x40, 0x73, 0xd9, 0x8f, 0xed, 0xbf, 0x6e, 0x41, + 0x43, 0x1b, 0x39, 0xb9, 0x0e, 0xf3, 0x1b, 0xfb, 0xfb, 0x07, 0x5b, 0xce, 0xda, 0xd1, 0xce, 0xf7, + 0xb6, 0xdc, 0x8d, 0xdd, 0xfd, 0xc3, 0xad, 0xce, 0x35, 0x06, 0xde, 0xdd, 0xdf, 0x58, 0xdb, 0x75, + 0x9f, 0xee, 0x3b, 0x1b, 0x12, 0x6c, 0x91, 0x25, 0x20, 0xce, 0xd6, 0xf3, 0xfd, 0xa3, 0x2d, 0x03, + 0x5e, 0x22, 0x1d, 0x68, 0xae, 0x3b, 0x5b, 0x6b, 0x1b, 0xdb, 0x02, 0x52, 0x26, 0x8b, 0xd0, 0x79, + 0xfa, 0x62, 0x6f, 0x73, 0x67, 0xef, 0x99, 0xbb, 0xb1, 0xb6, 0xb7, 0xb1, 0xb5, 0xbb, 0xb5, 0xd9, + 0xa9, 0x90, 0x16, 0xd4, 0xd7, 0xd6, 0xd7, 0xf6, 0x36, 0xf7, 0xf7, 0xb6, 0x36, 0x3b, 0x55, 0xfb, + 0x5b, 0x50, 0x57, 0x43, 0x25, 0x0d, 0x98, 0x7d, 0xb1, 0xf7, 0xe9, 0xde, 0xfe, 0xcb, 0xbd, 0xce, + 0x35, 0x52, 0x87, 0x2a, 0xf6, 0xdf, 0xb1, 0x08, 0xc0, 0x0c, 0xef, 0xb3, 0x53, 0x22, 0x35, 0xa8, + 0xac, 0xef, 0x1f, 0x6d, 0x77, 0xca, 0xf6, 0x7f, 0xb5, 0xe0, 0x3a, 0xce, 0x79, 0x90, 0xe5, 0xfe, + 0xbb, 0xd0, 0xe8, 0x87, 0xe1, 0x98, 0xd9, 0x3d, 0xe9, 0xc9, 0xae, 0x83, 0x18, 0x67, 0x73, 0x99, + 0x78, 0x12, 0x46, 0x7d, 0x2a, 0x98, 0x1f, 0x10, 0xf4, 0x94, 0x41, 0x18, 0x67, 0x0b, 0xba, 0xe5, + 0x18, 0x9c, 0xf7, 0x1b, 0x1c, 0xc6, 0x51, 0x96, 0x60, 0xe6, 0x38, 0xa2, 0x5e, 0xff, 0x4c, 0xb0, + 0xbd, 0x28, 0x91, 0xaf, 0xa4, 0x86, 0x79, 0x9f, 0x91, 0xd5, 0x90, 0x0e, 0x90, 0x15, 0x6a, 0xce, + 0x9c, 0x80, 0x6f, 0x08, 0x30, 0x3b, 0x04, 0xbc, 0x63, 0x2f, 0x18, 0x84, 0x01, 0x1d, 0x08, 0xad, + 0x3f, 0x05, 0xd8, 0x07, 0xb0, 0x94, 0x9d, 0x9f, 0x10, 0x1e, 0x1f, 0x69, 0xc2, 0x83, 0x2b, 0xe1, + 0xbd, 0xe9, 0xb4, 0xa0, 0x09, 0x92, 0x3f, 0x2b, 0x43, 0x85, 0xe9, 0x64, 0xd3, 0xf5, 0x37, 0x5d, + 0xcd, 0x2e, 0xe7, 0xa2, 0x34, 0x68, 0xeb, 0xf3, 0x13, 0x5a, 0xf8, 0x99, 0x52, 0x48, 0x5a, 0x1f, + 0xd1, 0xfe, 0xb9, 0xf0, 0x34, 0x69, 0x10, 0xc6, 0xf9, 0xcc, 0x06, 0xc2, 0xaf, 0x05, 0xe7, 0xcb, + 0xb2, 0xac, 0xc3, 0x2f, 0x67, 0xd3, 0x3a, 0xfc, 0xae, 0x0b, 0xb3, 0x7e, 0x70, 0x1c, 0x4e, 0x82, + 0x01, 0x72, 0x7a, 0xcd, 0x91, 0x45, 0x8c, 0x0b, 0xa1, 0x04, 0x62, 0xc7, 0x07, 0xe7, 0xeb, 0x14, + 0x40, 0x56, 0xa1, 0x1e, 0x5f, 0x06, 0x7d, 0x9d, 0x99, 0x17, 0xc5, 0x2a, 0xb1, 0x35, 0x58, 0x39, + 0xbc, 0x0c, 0xfa, 0xc8, 0xba, 0x29, 0x1a, 0xf9, 0x26, 0xd4, 0x94, 0x67, 0x96, 0x4b, 0xe5, 0x1b, + 0xfa, 0x27, 0xd2, 0x1d, 0xcb, 0x0d, 0x5e, 0x85, 0xda, 0xfb, 0x14, 0x5a, 0x46, 0x95, 0x6e, 0xa5, + 0xb6, 0xb8, 0x95, 0x7a, 0x4f, 0xb7, 0x52, 0x53, 0x61, 0x2f, 0x3e, 0xd3, 0xad, 0xd6, 0xdf, 0x83, + 0x9a, 0x1c, 0x1a, 0xe3, 0x2a, 0xc1, 0x11, 0xee, 0xe1, 0xf7, 0xf7, 0x36, 0x3a, 0xd7, 0xc8, 0x1c, + 0x34, 0xd6, 0x36, 0x90, 0x51, 0x11, 0x60, 0x31, 0x94, 0x83, 0xb5, 0xc3, 0x43, 0x05, 0x29, 0xd9, + 0x04, 0x3a, 0xec, 0xc8, 0x61, 0x23, 0x56, 0xb1, 0x97, 0x8f, 0x60, 0x5e, 0x83, 0xa5, 0x86, 0xdc, + 0x98, 0x01, 0x32, 0x86, 0x1c, 0x6a, 0xed, 0xbc, 0xc6, 0x5e, 0x86, 0xeb, 0xac, 0xb8, 0x75, 0x4e, + 0x83, 0xe4, 0x70, 0x72, 0xcc, 0x43, 0x6e, 0x7e, 0x18, 0xd8, 0x7f, 0xc5, 0x82, 0xba, 0xaa, 0xb9, + 0x82, 0x9e, 0x64, 0x94, 0xb0, 0x84, 0x1b, 0xd0, 0xd3, 0xba, 0xc0, 0x2f, 0x57, 0xf0, 0x5f, 0xc3, + 0xf8, 0xab, 0x2b, 0x10, 0x9b, 0xec, 0xc1, 0xd6, 0x96, 0xe3, 0xee, 0xef, 0xed, 0xee, 0xec, 0x31, + 0xa1, 0xc4, 0x26, 0x8b, 0x80, 0xa7, 0x4f, 0x11, 0x62, 0xd9, 0x1d, 0x68, 0x3f, 0xa3, 0xc9, 0x4e, + 0x70, 0x12, 0xca, 0xa9, 0xfe, 0x9f, 0x2a, 0xcc, 0x29, 0x50, 0x6a, 0x3c, 0x9e, 0xd3, 0x28, 0xf6, + 0xc3, 0x00, 0xd5, 0xbe, 0xba, 0x23, 0x8b, 0xec, 0x3c, 0xf1, 0x07, 0x34, 0x48, 0xfc, 0xe4, 0xd2, + 0x35, 0xbc, 0x4d, 0x59, 0x30, 0x33, 0xd4, 0xbc, 0xa1, 0xef, 0xc9, 0xe8, 0x25, 0x2f, 0x30, 0x68, + 0x3f, 0x1c, 0x86, 0x11, 0xea, 0x77, 0x75, 0x87, 0x17, 0xc8, 0x2a, 0x2c, 0x32, 0xbd, 0x52, 0xf7, + 0x05, 0x22, 0xb3, 0x72, 0xd7, 0x57, 0x61, 0x1d, 0x3b, 0xaf, 0x18, 0x5c, 0x28, 0x25, 0xea, 0x13, + 0x6e, 0xc6, 0x14, 0x55, 0x91, 0x6f, 0xc0, 0x75, 0x06, 0x56, 0x8a, 0x8c, 0xfa, 0x66, 0x0e, 0xbf, + 0x29, 0xae, 0x64, 0x5c, 0xc3, 0xfb, 0x67, 0x3b, 0x5f, 0xe5, 0x1a, 0xab, 0x02, 0xe4, 0x42, 0x8d, + 0x33, 0xfc, 0x0c, 0xce, 0x86, 0x1a, 0xb5, 0x70, 0x65, 0x2d, 0x17, 0xae, 0xfc, 0x06, 0x5c, 0x3f, + 0xa6, 0x71, 0xe2, 0x9e, 0x51, 0x6f, 0x40, 0x23, 0xe4, 0x46, 0x1e, 0x95, 0xe4, 0x0a, 0x7a, 0x71, + 0x25, 0x9e, 0xec, 0x97, 0x41, 0x9f, 0x0e, 0xdc, 0x24, 0x74, 0x51, 0x03, 0x41, 0x9e, 0xae, 0x39, + 0x59, 0xb0, 0x89, 0x79, 0x1a, 0x79, 0xe3, 0x33, 0xa1, 0x41, 0x67, 0xc1, 0x4c, 0xf7, 0x49, 0x68, + 0x9c, 0x04, 0x94, 0xc7, 0x84, 0x6a, 0xe8, 0xef, 0x97, 0x20, 0x72, 0x0f, 0x66, 0xb0, 0xc1, 0xb8, + 0xdb, 0x41, 0x06, 0x68, 0xa6, 0x42, 0xd4, 0x0f, 0x1c, 0x51, 0xc7, 0xec, 0xe5, 0x49, 0xe4, 0xc7, + 0xdd, 0x26, 0x86, 0x43, 0xf1, 0x6f, 0xf2, 0x1d, 0x4d, 0x4e, 0x2c, 0xe0, 0xb7, 0xf2, 0x30, 0xce, + 0x50, 0xde, 0x6f, 0x45, 0x64, 0x7c, 0x52, 0xa9, 0x35, 0x3a, 0x4d, 0xfb, 0x77, 0xa0, 0x8a, 0x23, + 0x47, 0x9a, 0xc4, 0xf5, 0xb3, 0x04, 0x4d, 0x22, 0xb4, 0x0b, 0xb3, 0x01, 0x4d, 0x2e, 0xc2, 0xe8, + 0x95, 0x8c, 0xbf, 0x8b, 0xa2, 0xfd, 0x13, 0x74, 0x2a, 0xa8, 0x78, 0xf4, 0x0b, 0xb4, 0x86, 0xc8, + 0x4d, 0xa8, 0xf3, 0x3d, 0x8d, 0xcf, 0x3c, 0xe1, 0xe7, 0xa8, 0x21, 0xe0, 0xf0, 0xcc, 0x63, 0xe7, + 0xa3, 0x41, 0x26, 0xdc, 0x75, 0xd4, 0x40, 0xd8, 0x36, 0xa7, 0x92, 0x7b, 0xd0, 0x96, 0x91, 0xee, + 0xd8, 0x1d, 0xd2, 0x93, 0x44, 0x3a, 0x7e, 0x83, 0xc9, 0x08, 0xfd, 0x4b, 0xbb, 0xf4, 0x24, 0xb1, + 0xf7, 0x60, 0x5e, 0x9c, 0x59, 0xfb, 0x63, 0x2a, 0xbb, 0xfe, 0x56, 0x91, 0x62, 0xdb, 0x58, 0x5d, + 0x30, 0x0f, 0x39, 0x1e, 0xdb, 0x37, 0x31, 0x6d, 0x07, 0x88, 0x7e, 0x06, 0x8a, 0x06, 0x85, 0x66, + 0x29, 0x5d, 0xdb, 0x62, 0x3a, 0x06, 0x8c, 0xad, 0x4f, 0x3c, 0xe9, 0xf7, 0xe5, 0xfd, 0x84, 0x9a, + 0x23, 0x8b, 0xf6, 0x7f, 0xb4, 0x60, 0x01, 0x5b, 0x93, 0xaa, 0xb9, 0xd0, 0x33, 0x1e, 0x7f, 0x81, + 0x61, 0xca, 0xc0, 0x02, 0x77, 0xa7, 0x2f, 0x42, 0x55, 0xd7, 0x3c, 0x78, 0xe1, 0x8b, 0xbb, 0x11, + 0x2b, 0x39, 0x37, 0xe2, 0x03, 0xe8, 0x0c, 0xe8, 0xd0, 0xc7, 0x3b, 0x2a, 0xf2, 0x1c, 0xe7, 0x7a, + 0x78, 0x0e, 0x6e, 0xff, 0x2d, 0x0b, 0xe6, 0xb9, 0xa2, 0x80, 0xc6, 0xa4, 0x58, 0xaa, 0xff, 0x4f, + 0x1a, 0x5e, 0x42, 0x40, 0x89, 0x49, 0xa5, 0x47, 0x27, 0x42, 0x39, 0xf2, 0xf6, 0x35, 0xc7, 0x44, + 0x26, 0x4f, 0xd0, 0x9c, 0x08, 0x5c, 0x84, 0x16, 0xdc, 0x7a, 0x31, 0xf7, 0x65, 0xfb, 0x9a, 0xa3, + 0xa1, 0xaf, 0xd7, 0x98, 0x2d, 0xc8, 0xe0, 0xf6, 0x33, 0x68, 0x19, 0x1d, 0x19, 0xee, 0xce, 0x26, + 0x77, 0x77, 0xe6, 0xe2, 0x0a, 0xa5, 0x82, 0xb8, 0xc2, 0xcf, 0x2b, 0x40, 0x18, 0x61, 0x65, 0x76, + 0xee, 0xae, 0x19, 0x9c, 0x93, 0x17, 0x60, 0x52, 0x10, 0x59, 0x05, 0xa2, 0x15, 0x65, 0xd0, 0xb0, + 0xac, 0x82, 0x86, 0x05, 0xb5, 0x4c, 0xea, 0x0b, 0xad, 0x52, 0x05, 0xe4, 0xd0, 0x95, 0xc5, 0xb7, + 0xa9, 0xb0, 0x8e, 0x69, 0x3e, 0x18, 0x9d, 0x63, 0x46, 0xb7, 0x70, 0xff, 0xc8, 0x72, 0x96, 0x1e, + 0x66, 0xde, 0x48, 0x0f, 0xb3, 0x39, 0x7a, 0xd0, 0x1c, 0x10, 0x35, 0xd3, 0x01, 0x71, 0x0f, 0x5a, + 0x32, 0x08, 0xc7, 0xef, 0x1f, 0x08, 0x6f, 0x8f, 0x01, 0x64, 0xf4, 0x24, 0x7d, 0x00, 0xca, 0xcb, + 0xc1, 0xa3, 0xeb, 0x39, 0x38, 0x3b, 0x58, 0x52, 0x47, 0x73, 0x03, 0x07, 0x9b, 0x02, 0xd0, 0x65, + 0xc0, 0xa8, 0xc4, 0x9d, 0x04, 0xe2, 0xf2, 0x0b, 0x1d, 0xa0, 0x21, 0x53, 0x73, 0xf2, 0x15, 0x79, + 0xf3, 0xbf, 0x55, 0x60, 0xfe, 0x93, 0x8f, 0xd2, 0x88, 0x55, 0x7c, 0xe6, 0x8f, 0xf0, 0x6c, 0x4f, + 0xef, 0x8e, 0x3c, 0xe5, 0x55, 0x87, 0x67, 0xfe, 0xc8, 0x31, 0xf0, 0xec, 0x5f, 0x5a, 0xd0, 0x61, + 0x54, 0x61, 0x10, 0xfe, 0xc7, 0x80, 0x3c, 0xfa, 0x96, 0x74, 0x6f, 0xe0, 0x92, 0xc7, 0x50, 0xc7, + 0x32, 0x33, 0xdd, 0x04, 0xd5, 0x77, 0x4d, 0xaa, 0x4f, 0xa5, 0xdb, 0xf6, 0x35, 0x27, 0x45, 0x66, + 0x67, 0x59, 0x36, 0x62, 0xc8, 0xc3, 0xdf, 0x59, 0xb0, 0xc6, 0x1d, 0xdb, 0x00, 0x9f, 0xd2, 0xcb, + 0xdd, 0xb0, 0x8f, 0x56, 0xd3, 0x6d, 0x00, 0x46, 0x83, 0x27, 0xde, 0xc8, 0x17, 0xae, 0x8e, 0xaa, + 0x53, 0x7f, 0x45, 0x2f, 0x9f, 0x22, 0x80, 0x89, 0x71, 0x56, 0x9d, 0xb2, 0x48, 0xd5, 0xa9, 0xbd, + 0xa2, 0x97, 0x3b, 0xc8, 0x1e, 0x2e, 0xb4, 0x3e, 0xa5, 0x97, 0x9b, 0x94, 0xeb, 0x75, 0x61, 0x44, + 0x6c, 0x68, 0x45, 0xde, 0x05, 0xd3, 0xdc, 0x8c, 0x50, 0x5f, 0x23, 0xf2, 0x2e, 0x3e, 0xa5, 0x97, + 0xeb, 0x18, 0xeb, 0x7b, 0x00, 0xb3, 0xac, 0x7e, 0x18, 0xf6, 0xc5, 0xc9, 0x24, 0x6f, 0x2f, 0xa4, + 0x83, 0x72, 0x66, 0x5e, 0xe1, 0xdf, 0xf6, 0xbf, 0xb7, 0xa0, 0xc5, 0x56, 0x00, 0xc5, 0x1e, 0xdb, + 0x09, 0x79, 0x09, 0xc6, 0x4a, 0x2f, 0xc1, 0xac, 0x0a, 0x99, 0xc1, 0x65, 0x68, 0x69, 0xba, 0x0c, + 0xc5, 0x65, 0xe3, 0x02, 0xf4, 0x43, 0xa8, 0x73, 0x76, 0x62, 0xec, 0x5b, 0x36, 0x76, 0xca, 0x98, + 0x90, 0x53, 0x43, 0xb4, 0x4f, 0x79, 0xbc, 0x5d, 0x73, 0x56, 0xf1, 0x45, 0xae, 0x73, 0x08, 0xab, + 0x2e, 0x08, 0xdd, 0x56, 0x8b, 0x42, 0xb7, 0x2f, 0xa0, 0xa1, 0x11, 0x16, 0xf9, 0x36, 0x0f, 0x7a, + 0xf3, 0xc1, 0x73, 0x2a, 0x34, 0x09, 0xc7, 0x98, 0x3d, 0x0a, 0x4c, 0x1d, 0xb0, 0x3e, 0x03, 0x15, + 0x24, 0xc9, 0x27, 0x30, 0xaf, 0x35, 0xcb, 0x2d, 0xc4, 0xa2, 0x31, 0x59, 0x45, 0x63, 0xfa, 0xdb, 0x16, 0x2c, 0x8a, 0xaf, 0xf1, 0xc2, 0x94, 0xcf, 0x8e, 0xf1, 0xe7, 0xf1, 0x29, 0x3b, 0x48, 0x59, 0xeb, 0x6e, 0x44, 0x4f, 0xfd, 0x38, 0xa1, 0x32, 0x42, 0x50, 0xc0, 0x21, 0x8c, 0xa4, 0x19, 0xaa, 0x23, 0x30, 0xc9, 0x13, 0x68, 0xe0, 0xa7, 0xdc, 0x86, 0x15, 0xdb, 0xd2, 0xcd, 0x7f, 0xc8, 0x87, @@ -10895,7 +10904,7 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xca, 0x51, 0x81, 0x9e, 0x76, 0xf5, 0x8f, 0x5b, 0xab, 0xe9, 0x4d, 0xbf, 0xfb, 0x30, 0x37, 0x62, 0x8a, 0x12, 0xd3, 0xe0, 0x8d, 0x88, 0x40, 0x16, 0xcc, 0x14, 0x6f, 0xd4, 0x5b, 0x62, 0x37, 0xf1, 0x87, 0xae, 0xac, 0x15, 0x97, 0xec, 0x8a, 0xaa, 0xd8, 0xf1, 0x1d, 0x27, 0xde, 0x29, 0x15, 0xda, - 0x31, 0x2f, 0xd8, 0x5d, 0x58, 0x3a, 0x48, 0xb7, 0x45, 0x73, 0x48, 0xd8, 0xff, 0xbc, 0x05, 0xcb, + 0x31, 0x2f, 0xd8, 0x5d, 0x58, 0x3a, 0x48, 0xb7, 0x45, 0x73, 0x48, 0xd8, 0xff, 0xac, 0x05, 0xcb, 0xb9, 0x2a, 0x75, 0x25, 0x58, 0xb8, 0xb9, 0x87, 0xfe, 0xe8, 0x38, 0x54, 0x6e, 0x2a, 0x4b, 0xf7, 0x80, 0x1b, 0x55, 0xe4, 0x14, 0xae, 0x4b, 0xaa, 0x40, 0x57, 0x91, 0x52, 0xfb, 0x4b, 0xa8, 0x89, 0x7e, 0x68, 0x4a, 0xac, 0x6c, 0x87, 0x12, 0xae, 0x9f, 0x8a, 0xc5, 0xed, 0x91, 0x33, 0xe8, 0x2a, @@ -10909,12 +10918,12 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xea, 0xd0, 0xfb, 0xdf, 0x16, 0x90, 0x3c, 0xf5, 0x92, 0x67, 0xdc, 0xc1, 0x1d, 0xd0, 0xa1, 0x10, 0x6f, 0x5f, 0x7b, 0x3b, 0x0e, 0x90, 0xbb, 0x25, 0xbf, 0x66, 0xac, 0xa8, 0xdf, 0xcb, 0xd5, 0x6d, 0x9b, 0x96, 0x53, 0x54, 0x95, 0x09, 0xa9, 0x55, 0xde, 0x1c, 0x52, 0xab, 0xbe, 0x39, 0xa4, 0x36, - 0x93, 0x0d, 0xa9, 0xf5, 0xfe, 0xaa, 0x05, 0x0b, 0x05, 0x64, 0xf6, 0x9b, 0x9b, 0x38, 0x23, 0x0c, - 0x43, 0xfa, 0x94, 0x04, 0x61, 0xe8, 0xc0, 0xde, 0x5f, 0x82, 0x96, 0xc1, 0x5a, 0xbf, 0xb9, 0xfe, + 0x93, 0x0d, 0xa9, 0xf5, 0xfe, 0xb2, 0x05, 0x0b, 0x05, 0x64, 0xf6, 0x9b, 0x9b, 0x38, 0x23, 0x0c, + 0x43, 0xfa, 0x94, 0x04, 0x61, 0xe8, 0xc0, 0xde, 0x5f, 0x80, 0x96, 0xc1, 0x5a, 0xbf, 0xb9, 0xfe, 0xb3, 0xe6, 0x19, 0xa7, 0x6c, 0x03, 0xd6, 0xfb, 0x1f, 0x25, 0x20, 0x79, 0xf6, 0xfe, 0xad, 0x8e, 0x21, 0xbf, 0x4e, 0xe5, 0x82, 0x75, 0xfa, 0x7f, 0x7a, 0xf2, 0x7c, 0x00, 0xf3, 0x22, 0xd9, 0x40, 0x0b, 0x69, 0x70, 0x8a, 0xc9, 0x57, 0x30, 0x03, 0xd5, 0x8c, 0x67, 0xd6, 0x8c, 0xcb, 0xd5, 0xda, - 0xf1, 0x9b, 0x09, 0x6b, 0xda, 0x3d, 0xe8, 0x8a, 0x15, 0xca, 0xbb, 0xfe, 0xfe, 0x5e, 0x45, 0xd9, + 0xf1, 0x9b, 0x09, 0x6b, 0xda, 0x3d, 0xe8, 0x8a, 0x15, 0xca, 0xbb, 0xfe, 0xfe, 0x6e, 0x45, 0xd9, 0xd8, 0x58, 0x29, 0xf4, 0xe7, 0x6f, 0x40, 0x53, 0x3f, 0x3e, 0xc4, 0x76, 0x64, 0xa2, 0x5a, 0x4c, 0xcd, 0xd0, 0xb1, 0xc8, 0x26, 0xb4, 0x51, 0x48, 0x0e, 0xd4, 0x77, 0x5c, 0xd3, 0xb8, 0xc2, 0xa1, 0xbd, 0x7d, 0xcd, 0xc9, 0x7c, 0x43, 0x7e, 0x17, 0xda, 0xa6, 0x9b, 0x4b, 0xe8, 0x84, 0x45, 0x6a, @@ -10925,11 +10934,11 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xed, 0x5c, 0x23, 0x04, 0xda, 0x18, 0x9e, 0xd9, 0x54, 0x30, 0x8b, 0xc1, 0x84, 0x47, 0x59, 0xc2, 0x4a, 0x64, 0x11, 0x3a, 0x3b, 0x7b, 0x19, 0x68, 0x99, 0x74, 0x61, 0xf1, 0x60, 0x8b, 0x47, 0x74, 0x8c, 0x76, 0x2b, 0x4c, 0xdf, 0x13, 0x83, 0x67, 0xfa, 0x1e, 0x4f, 0x59, 0x59, 0xe7, 0x44, 0x28, - 0x75, 0xa0, 0x7f, 0x60, 0xc1, 0xf5, 0x4c, 0x45, 0x7a, 0x09, 0x99, 0xab, 0x39, 0xa6, 0xee, 0x63, + 0x75, 0xa0, 0xbf, 0x6f, 0xc1, 0xf5, 0x4c, 0x45, 0x7a, 0x09, 0x99, 0xab, 0x39, 0xa6, 0xee, 0x63, 0x02, 0x31, 0x24, 0x2e, 0xcd, 0xc3, 0x8c, 0x9c, 0xca, 0x57, 0x30, 0xce, 0xd2, 0xcc, 0xc9, 0x0c, 0xbf, 0x16, 0x55, 0xd9, 0xcb, 0xea, 0xae, 0x67, 0x66, 0xe0, 0x27, 0x3c, 0x15, 0x46, 0xaf, 0x48, - 0xbd, 0xca, 0xe6, 0x90, 0x65, 0x91, 0xac, 0x66, 0xa8, 0xc1, 0x1c, 0x6f, 0x61, 0x9d, 0xfd, 0xcf, - 0x66, 0x80, 0x7c, 0x77, 0x42, 0xa3, 0x4b, 0xbc, 0x65, 0xac, 0x82, 0x59, 0xcb, 0x59, 0xd7, 0xfa, + 0xbd, 0xca, 0xe6, 0x90, 0x65, 0x91, 0xac, 0x66, 0xa8, 0xc1, 0x1c, 0x6f, 0x61, 0x9d, 0xfd, 0x4f, + 0x67, 0x80, 0x7c, 0x77, 0x42, 0xa3, 0x4b, 0xbc, 0x65, 0xac, 0x82, 0x59, 0xcb, 0x59, 0xd7, 0xfa, 0xcc, 0x78, 0x72, 0xcc, 0x0c, 0x16, 0x61, 0x48, 0x95, 0xde, 0x2a, 0x9b, 0xa0, 0xe8, 0x36, 0x7f, 0xe5, 0xcd, 0xb7, 0xf9, 0xab, 0x6f, 0xba, 0xcd, 0xff, 0x25, 0x68, 0xf9, 0xa7, 0x41, 0xc8, 0x84, 0x0e, 0x53, 0x54, 0xe2, 0xee, 0xcc, 0xdd, 0xf2, 0xfd, 0xa6, 0xd3, 0x14, 0xc0, 0x3d, 0x06, 0x23, @@ -10960,12 +10969,12 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xe8, 0xb6, 0xbc, 0x00, 0x16, 0x8e, 0x57, 0x0a, 0x18, 0x35, 0xf3, 0x51, 0xef, 0x3b, 0x40, 0x7e, 0xcd, 0x44, 0x9d, 0x97, 0x50, 0x57, 0x23, 0xd4, 0xd3, 0x63, 0xf0, 0x96, 0x67, 0xc3, 0x4c, 0x8f, 0xc1, 0x4b, 0x9d, 0xef, 0x41, 0x9b, 0x1f, 0x97, 0xea, 0x00, 0xe0, 0x37, 0xf3, 0x32, 0x50, 0xfb, - 0x2f, 0x2c, 0xa8, 0x22, 0xe5, 0x31, 0x2d, 0x95, 0xd7, 0xa9, 0x9b, 0x30, 0x22, 0xf6, 0x94, 0x05, + 0xcf, 0x2d, 0xa8, 0x22, 0xe5, 0x31, 0x2d, 0x95, 0xd7, 0xa9, 0x9b, 0x30, 0x22, 0xf6, 0x94, 0x05, 0x13, 0xdb, 0xc8, 0x1c, 0x2c, 0x29, 0x32, 0xd0, 0xb3, 0x07, 0xef, 0x42, 0x5d, 0xf5, 0xa4, 0x91, 0x52, 0x0a, 0x24, 0x77, 0xa0, 0x72, 0x16, 0x8e, 0xa5, 0x21, 0x0f, 0xe9, 0x8a, 0x3a, 0x08, 0x4f, 0xc7, 0xc3, 0xda, 0xe3, 0x53, 0xe0, 0xc6, 0x52, 0x16, 0x5c, 0x30, 0xd7, 0x99, 0xc2, 0xb9, 0xbe, 0x80, 0x39, 0x26, 0x1f, 0xb4, 0xd8, 0xf0, 0xf4, 0xc3, 0xf4, 0x2b, 0x4c, 0x03, 0xec, 0x0f, 0x27, - 0x03, 0xaa, 0xbb, 0x53, 0x30, 0xa6, 0x28, 0xe0, 0xd2, 0x90, 0xb0, 0xff, 0x85, 0xc5, 0xe5, 0x0e, + 0x03, 0xaa, 0xbb, 0x53, 0x30, 0xa6, 0x28, 0xe0, 0xd2, 0x90, 0xb0, 0xff, 0xb9, 0xc5, 0xe5, 0x0e, 0x6b, 0x97, 0xdc, 0x87, 0x0a, 0x3b, 0xf7, 0x32, 0x3e, 0x3f, 0x75, 0xf3, 0x96, 0xe1, 0x39, 0x88, 0xc1, 0x76, 0x11, 0xc3, 0x61, 0x7a, 0xeb, 0x3c, 0x18, 0x96, 0xfa, 0x22, 0xd4, 0xcc, 0x32, 0x26, 0x7c, 0x06, 0x4a, 0x56, 0xb4, 0xfb, 0x1f, 0x15, 0xe3, 0x2c, 0x95, 0x4a, 0xe2, 0xe0, 0x94, 0x6a, @@ -10989,7 +10998,7 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0x4e, 0x82, 0x3e, 0x95, 0x89, 0x05, 0x45, 0x55, 0xf6, 0x40, 0xa5, 0xa1, 0x61, 0x43, 0xe4, 0x01, 0x54, 0xb9, 0x1a, 0xcf, 0x75, 0x95, 0x62, 0x79, 0xc6, 0x51, 0xc8, 0x7d, 0xa8, 0x72, 0x6d, 0xbe, 0x34, 0x55, 0x02, 0x71, 0x04, 0x7b, 0x05, 0xe6, 0x50, 0x23, 0xd5, 0x04, 0xf1, 0xcd, 0x22, 0x1d, - 0x66, 0xa6, 0xcf, 0xc3, 0x19, 0x8b, 0x40, 0xf6, 0x38, 0x5f, 0xe9, 0xf7, 0x7a, 0xfe, 0xa2, 0x0c, + 0x66, 0xa6, 0xcf, 0xc3, 0x19, 0x8b, 0x40, 0xf6, 0x38, 0x5f, 0xe9, 0xf7, 0x7a, 0xfe, 0xbc, 0x0c, 0x0d, 0x0d, 0xcc, 0x84, 0x25, 0x5e, 0xf2, 0x70, 0x07, 0xbe, 0x37, 0xa2, 0x32, 0xb8, 0xd1, 0x72, 0x32, 0x50, 0x86, 0xe7, 0x9d, 0x9f, 0xba, 0xe1, 0x24, 0x71, 0x07, 0xf4, 0x34, 0xa2, 0x54, 0x28, 0x57, 0x19, 0x28, 0xc3, 0x63, 0xd4, 0xac, 0xe1, 0xf1, 0xfb, 0x0a, 0x19, 0xa8, 0xbc, 0x3f, 0xc3, @@ -11012,7 +11021,7 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xe3, 0x09, 0xb4, 0x23, 0x2e, 0x33, 0xa5, 0x40, 0xad, 0x5c, 0x21, 0x50, 0x5b, 0x91, 0x71, 0x32, 0x7f, 0x05, 0x3a, 0xde, 0xe0, 0x9c, 0x46, 0x89, 0x8f, 0xde, 0x5e, 0xd4, 0xe9, 0xf8, 0x04, 0xe7, 0x34, 0x38, 0xaa, 0x4e, 0xef, 0xc3, 0x9c, 0x48, 0x6f, 0x52, 0x98, 0xe2, 0x05, 0x85, 0x14, 0xcc, - 0x10, 0xed, 0x7f, 0x2c, 0xaf, 0x0d, 0x99, 0xbb, 0x7b, 0xf5, 0xaa, 0xe8, 0x33, 0x2c, 0x65, 0x66, + 0x10, 0xed, 0x7f, 0x24, 0xaf, 0x0d, 0x99, 0xbb, 0x7b, 0xf5, 0xaa, 0xe8, 0x33, 0x2c, 0x65, 0x66, 0xf8, 0x25, 0x71, 0x29, 0x62, 0x20, 0xdd, 0xca, 0x65, 0xed, 0x82, 0xfc, 0x40, 0x5c, 0xbb, 0x32, 0x97, 0xb5, 0xf2, 0x36, 0xcb, 0x6a, 0xff, 0x27, 0x0b, 0x66, 0xb7, 0xc3, 0x31, 0x33, 0xed, 0x51, 0xc7, 0x61, 0x6c, 0xa2, 0x72, 0x0b, 0x65, 0xf1, 0x0d, 0x89, 0x04, 0x85, 0x5a, 0x49, 0x2b, 0xab, @@ -11050,7 +11059,7 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0x63, 0xb7, 0xc0, 0x83, 0x55, 0x71, 0x0a, 0x6a, 0x7e, 0x03, 0x0e, 0xb6, 0x04, 0xc8, 0xda, 0x60, 0x20, 0x86, 0xa9, 0x3f, 0xeb, 0x11, 0xe9, 0xef, 0xc8, 0x48, 0x91, 0x5d, 0x20, 0x16, 0x4b, 0xc5, 0x62, 0xf1, 0x4a, 0xe1, 0x61, 0xef, 0x40, 0xe3, 0x40, 0x7b, 0x99, 0xc6, 0x66, 0x27, 0x88, 0x7c, - 0x93, 0x86, 0x9f, 0x2d, 0xdc, 0xb1, 0x96, 0x42, 0xb5, 0x21, 0x95, 0xf4, 0x21, 0xd9, 0xff, 0xd0, + 0x93, 0x86, 0x9f, 0x2d, 0xdc, 0xb1, 0x96, 0x42, 0xb5, 0x21, 0x95, 0xf4, 0x21, 0xd9, 0xff, 0xc0, 0xe2, 0xc9, 0xfe, 0x6a, 0x0a, 0xbc, 0x7f, 0x1b, 0x9a, 0x2a, 0xb8, 0x94, 0x66, 0x3e, 0x1a, 0x30, 0x86, 0x83, 0xc3, 0x71, 0xc3, 0x93, 0x93, 0x98, 0xca, 0x54, 0x1e, 0x03, 0x26, 0x95, 0x75, 0xa6, 0xfe, 0xfb, 0xbc, 0x87, 0x58, 0xa4, 0xf4, 0xe4, 0xe0, 0x8c, 0xd2, 0x85, 0x6f, 0x5c, 0x26, 0x31, @@ -11083,7 +11092,7 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xe4, 0x70, 0x4c, 0xfb, 0xf6, 0x47, 0x40, 0xf4, 0x76, 0xc4, 0x7a, 0x31, 0x93, 0x61, 0x72, 0xec, 0xc6, 0x97, 0x71, 0x42, 0x47, 0xf2, 0xe5, 0x15, 0x1d, 0x64, 0xbf, 0x0f, 0xcd, 0x03, 0xef, 0xd2, 0xa1, 0x9f, 0x89, 0xa7, 0xd3, 0x96, 0x61, 0x76, 0xec, 0x5d, 0x32, 0x7e, 0x56, 0x21, 0x16, 0xac, - 0xb6, 0xff, 0xa4, 0x02, 0x33, 0x1c, 0x93, 0xb5, 0x3a, 0xa0, 0x71, 0xe2, 0x07, 0xc8, 0x63, 0xb2, + 0xb6, 0xff, 0xb8, 0x02, 0x33, 0x1c, 0x93, 0xb5, 0x3a, 0xa0, 0x71, 0xe2, 0x07, 0xc8, 0x63, 0xb2, 0x55, 0x0d, 0x94, 0x13, 0x98, 0xa5, 0x02, 0x81, 0x29, 0x5c, 0x6d, 0xf2, 0xa1, 0x07, 0x41, 0xb2, 0x06, 0x8c, 0x89, 0xad, 0x34, 0xfd, 0x8c, 0x53, 0x6a, 0x0a, 0xc8, 0xc4, 0x30, 0x53, 0xc3, 0x84, 0x8f, 0x4f, 0x9e, 0x05, 0x42, 0x26, 0xea, 0xa0, 0x42, 0xf3, 0x67, 0x56, 0xe6, 0xd9, 0x64, 0xcc, @@ -11093,163 +11102,163 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0x56, 0x40, 0x19, 0x65, 0x07, 0xde, 0x48, 0x3e, 0xb0, 0x83, 0x7f, 0xb3, 0xa5, 0xc3, 0x77, 0x3e, 0x3e, 0x9b, 0xf8, 0x11, 0x1d, 0xc8, 0x5c, 0x6d, 0x0d, 0x84, 0x97, 0xcb, 0x63, 0xf7, 0x55, 0x10, 0x5e, 0x04, 0x22, 0x5b, 0x5b, 0x95, 0x6d, 0x02, 0x1d, 0x7c, 0x68, 0x6b, 0x1c, 0x46, 0xf2, 0xcd, - 0x24, 0xfb, 0x0f, 0x2d, 0xe8, 0x08, 0x46, 0x53, 0x75, 0xf2, 0xc2, 0xc0, 0x55, 0x6f, 0x2d, 0xdc, - 0x83, 0x16, 0xfa, 0x3a, 0xd4, 0x91, 0x23, 0x82, 0xef, 0x06, 0x90, 0x8d, 0x57, 0xde, 0xee, 0x1c, - 0xf9, 0x43, 0x41, 0xb7, 0x3a, 0x48, 0x9e, 0x5a, 0x91, 0x27, 0x92, 0xbc, 0x2c, 0x47, 0x95, 0xed, - 0x5f, 0x5a, 0x30, 0xaf, 0x0d, 0x58, 0x30, 0xea, 0x13, 0x68, 0xaa, 0xf7, 0xec, 0xa8, 0x52, 0xaa, - 0x96, 0x4d, 0xc9, 0x92, 0x7e, 0x66, 0x20, 0x23, 0xbd, 0x7b, 0x97, 0x38, 0xc0, 0x78, 0x32, 0x12, - 0xda, 0x8c, 0x0e, 0x62, 0x74, 0x74, 0x41, 0xe9, 0x2b, 0x85, 0xc2, 0xf5, 0x29, 0x03, 0x86, 0x31, - 0xa2, 0x30, 0x48, 0xce, 0x14, 0x52, 0x45, 0xc4, 0x88, 0x74, 0xa0, 0xfd, 0x5f, 0x4a, 0xb0, 0xc0, - 0x9d, 0x6e, 0xc2, 0xd9, 0xa9, 0x9e, 0x14, 0x9a, 0xe1, 0xfe, 0x47, 0x2e, 0xb4, 0xb6, 0xaf, 0x39, - 0xa2, 0x4c, 0xbe, 0xf9, 0x96, 0x8e, 0x42, 0x95, 0x4d, 0x36, 0x65, 0x2f, 0xca, 0x45, 0x7b, 0x71, - 0xc5, 0x4a, 0x17, 0x85, 0xeb, 0xaa, 0xc5, 0xe1, 0xba, 0xb7, 0x0b, 0x8f, 0xe5, 0x52, 0xae, 0x66, - 0x05, 0x96, 0x91, 0x72, 0xb5, 0x0a, 0xcb, 0x06, 0x00, 0xe5, 0xb5, 0x7f, 0xe2, 0x53, 0x99, 0xff, - 0x3e, 0x1f, 0xd3, 0xc4, 0x35, 0x50, 0xd6, 0x67, 0xa1, 0x1a, 0xf7, 0xc3, 0x31, 0xb5, 0x97, 0x60, - 0xd1, 0x5c, 0x5c, 0x71, 0x4a, 0xfc, 0xc2, 0x82, 0xee, 0x53, 0x7e, 0xe9, 0xc2, 0x0f, 0x4e, 0xb7, - 0xfd, 0x38, 0x09, 0x23, 0xf5, 0xf2, 0xdb, 0x1d, 0x80, 0x38, 0xf1, 0x22, 0x61, 0x67, 0x72, 0x65, - 0x57, 0x83, 0xb0, 0x35, 0xa2, 0xc1, 0x80, 0xd7, 0x72, 0xda, 0x50, 0xe5, 0x9c, 0x31, 0x21, 0x5c, - 0x92, 0x86, 0x4a, 0xfe, 0x1e, 0xcf, 0x04, 0x65, 0x8b, 0x41, 0xcf, 0xf1, 0xe8, 0xe5, 0x7e, 0xbe, - 0x0c, 0xd4, 0xfe, 0xa3, 0x12, 0xcc, 0xa5, 0x83, 0xe4, 0x99, 0xe5, 0x86, 0x00, 0x17, 0x7a, 0x78, - 0x2a, 0xc0, 0x45, 0xf8, 0xd0, 0xf5, 0x99, 0x62, 0xae, 0x79, 0x25, 0x35, 0x28, 0xb9, 0x07, 0x0d, - 0x59, 0x0a, 0x27, 0x89, 0xf6, 0x04, 0x93, 0x0e, 0xe6, 0x29, 0x26, 0xcc, 0x34, 0x10, 0x66, 0x8e, - 0x28, 0xe1, 0x7b, 0x08, 0xa3, 0x04, 0xbf, 0xe4, 0x7b, 0x2a, 0x8b, 0x4c, 0xa0, 0x31, 0x9d, 0x9a, - 0xef, 0x21, 0xea, 0xd3, 0xba, 0xae, 0x59, 0x53, 0x4f, 0x57, 0x2a, 0x9e, 0xe7, 0x2d, 0xa6, 0xc9, - 0x76, 0x15, 0x47, 0x07, 0x49, 0xaf, 0x50, 0x38, 0x31, 0xcc, 0x5f, 0x03, 0x66, 0xff, 0x2d, 0x0b, - 0x6e, 0x14, 0x6c, 0xa3, 0x90, 0x01, 0x9b, 0x30, 0x7f, 0xa2, 0x2a, 0xe5, 0x52, 0x73, 0x41, 0xb0, - 0x24, 0x85, 0xab, 0xb9, 0xbc, 0x4e, 0xfe, 0x03, 0x65, 0x6e, 0xf1, 0xcd, 0x33, 0x72, 0x2b, 0xf3, - 0x15, 0xf6, 0x01, 0xf4, 0xb6, 0x5e, 0x33, 0x91, 0xb2, 0xa1, 0xbf, 0x5f, 0x2e, 0x29, 0x6b, 0x35, - 0x27, 0x32, 0xdf, 0xec, 0x8c, 0x3e, 0xe1, 0x19, 0x63, 0xaa, 0x2d, 0xf2, 0xf5, 0xb7, 0x6d, 0x44, - 0xe7, 0xfe, 0xbb, 0x62, 0xd7, 0xf9, 0x03, 0xec, 0x32, 0xc3, 0x53, 0x03, 0xd9, 0xe7, 0x30, 0xf7, - 0x7c, 0x32, 0x4c, 0xfc, 0xf4, 0x31, 0x76, 0xf2, 0x4d, 0xf1, 0x11, 0x36, 0x21, 0x97, 0xae, 0xb0, - 0x2b, 0x1d, 0x8f, 0xad, 0xd8, 0x88, 0xb5, 0xe4, 0xe6, 0x7b, 0xcc, 0x57, 0xd8, 0x37, 0x60, 0x39, - 0xed, 0x92, 0xaf, 0x9d, 0x3c, 0x76, 0xfe, 0xd8, 0xe2, 0x37, 0xab, 0xcd, 0xb7, 0xe1, 0xc9, 0x33, - 0x58, 0x88, 0xfd, 0xe0, 0x74, 0x48, 0xf5, 0x76, 0x62, 0xb1, 0x12, 0xd7, 0xcd, 0xe1, 0x89, 0xf7, - 0xe3, 0x9d, 0xa2, 0x2f, 0x18, 0x81, 0x14, 0x0f, 0x34, 0x25, 0x90, 0xcc, 0x92, 0x14, 0x4d, 0xe0, - 0x13, 0x68, 0x9b, 0x9d, 0x91, 0xc7, 0x22, 0x75, 0x32, 0x1d, 0x59, 0x39, 0x93, 0x01, 0x97, 0x52, - 0x86, 0x81, 0x69, 0xff, 0xcc, 0x82, 0xae, 0x43, 0x19, 0x19, 0x53, 0xad, 0x53, 0x41, 0x3d, 0x4f, - 0x72, 0xcd, 0x4e, 0x9f, 0xb0, 0x4a, 0xc9, 0x94, 0x73, 0x5d, 0x99, 0xba, 0x29, 0xdb, 0xd7, 0x0a, - 0x66, 0xb5, 0x5e, 0x83, 0x19, 0x31, 0xbf, 0x65, 0xb8, 0x2e, 0x86, 0x24, 0x87, 0x93, 0x86, 0x1d, - 0x8d, 0x4e, 0x8d, 0xb0, 0x63, 0x0f, 0xba, 0xfc, 0x81, 0x3f, 0x7d, 0x1e, 0xe2, 0xc3, 0x4d, 0x20, - 0xcf, 0xbd, 0xbe, 0x17, 0x85, 0x61, 0x70, 0x40, 0x23, 0x71, 0x49, 0x15, 0xb5, 0x4f, 0x8c, 0xca, - 0x49, 0x45, 0x99, 0x97, 0xe4, 0x9b, 0x74, 0x61, 0x20, 0xdf, 0xfe, 0xe3, 0x25, 0xdb, 0x81, 0x85, - 0x75, 0xef, 0x15, 0x95, 0x2d, 0xa5, 0xab, 0xd4, 0x18, 0xab, 0x46, 0xe5, 0xda, 0xcb, 0x9c, 0xeb, - 0x7c, 0xb7, 0x8e, 0x8e, 0x6d, 0xaf, 0xc2, 0xa2, 0xd9, 0xa6, 0x10, 0x25, 0x3d, 0xa8, 0x8d, 0x04, - 0x4c, 0x8c, 0x4e, 0x95, 0x1f, 0x7c, 0x0e, 0x0d, 0xed, 0xd1, 0x46, 0xb2, 0x0c, 0x0b, 0x2f, 0x77, - 0x8e, 0xf6, 0xb6, 0x0e, 0x0f, 0xdd, 0x83, 0x17, 0xeb, 0x9f, 0x6e, 0x7d, 0xdf, 0xdd, 0x5e, 0x3b, - 0xdc, 0xee, 0x5c, 0x23, 0x4b, 0x40, 0xf6, 0xb6, 0x0e, 0x8f, 0xb6, 0x36, 0x0d, 0xb8, 0x45, 0xee, - 0x40, 0xef, 0xc5, 0xde, 0x8b, 0xc3, 0xad, 0x4d, 0xb7, 0xe8, 0xbb, 0x12, 0xb9, 0x0d, 0x37, 0x44, - 0x7d, 0xc1, 0xe7, 0xe5, 0x07, 0x4f, 0xa0, 0x93, 0x75, 0x4b, 0x1a, 0xee, 0xdc, 0xab, 0xfc, 0xbe, - 0x0f, 0xfe, 0x51, 0x19, 0x20, 0xbd, 0x9c, 0x4a, 0xba, 0xb0, 0xb8, 0xb9, 0x76, 0xb4, 0xb6, 0xbb, - 0xcf, 0x06, 0xe1, 0xec, 0x1f, 0x6d, 0x6d, 0x1c, 0xb9, 0xce, 0xd6, 0x77, 0x3b, 0xd7, 0x0a, 0x6b, - 0xf6, 0x0f, 0x98, 0xc9, 0xbe, 0x0c, 0x0b, 0x3b, 0x7b, 0x3b, 0x47, 0x3b, 0x6b, 0xbb, 0xae, 0xb3, - 0xff, 0x62, 0x67, 0xef, 0x19, 0x7f, 0x77, 0xa5, 0x4c, 0xde, 0x81, 0x9b, 0x2f, 0x0e, 0x9e, 0x3a, - 0xfb, 0x7b, 0x47, 0xee, 0xe1, 0xf6, 0x8b, 0xa3, 0x4d, 0x7c, 0xb5, 0x65, 0xc3, 0xd9, 0x39, 0xe0, - 0x6d, 0x56, 0xae, 0x42, 0x60, 0x4d, 0x57, 0xd9, 0x8a, 0x3d, 0xdb, 0x3f, 0x3c, 0xdc, 0x39, 0x70, - 0xbf, 0xfb, 0x62, 0xcb, 0xd9, 0xd9, 0x3a, 0xc4, 0x0f, 0x67, 0x0a, 0xe0, 0x0c, 0x7f, 0x96, 0xcc, - 0x43, 0xeb, 0x68, 0xf7, 0x7b, 0xee, 0xfe, 0xde, 0xce, 0xfe, 0x1e, 0xa2, 0xd6, 0x4c, 0x10, 0xc3, - 0xaa, 0x93, 0x1e, 0x2c, 0x6d, 0xfd, 0xfe, 0x91, 0x5b, 0xd0, 0x32, 0x4c, 0xa9, 0x63, 0xdf, 0x35, - 0xc8, 0x0d, 0xb8, 0x7e, 0x78, 0xb4, 0x76, 0xb4, 0xb3, 0xe1, 0x8a, 0x17, 0x9f, 0xd8, 0x26, 0xb0, - 0xcf, 0x9a, 0xc5, 0x55, 0xec, 0xab, 0x16, 0x59, 0x84, 0xce, 0xc1, 0xda, 0xf7, 0x9f, 0x6f, 0xed, - 0x1d, 0xb9, 0x6b, 0x9b, 0x9b, 0x0e, 0x7e, 0xd0, 0xce, 0x41, 0x19, 0xee, 0x1c, 0xdb, 0xa8, 0xe7, - 0x07, 0x07, 0x88, 0xd2, 0x91, 0x05, 0x56, 0x33, 0xbf, 0xfa, 0xb3, 0x32, 0xb4, 0x79, 0xb6, 0x00, - 0xff, 0x15, 0x0c, 0x1a, 0x91, 0xe7, 0x30, 0x2b, 0x7e, 0x4e, 0x85, 0x5c, 0x57, 0x8f, 0x6d, 0xe8, - 0x3f, 0xe0, 0xd2, 0x5b, 0xca, 0x82, 0x05, 0xfb, 0x2d, 0xfc, 0x95, 0xff, 0xf0, 0xdf, 0x7e, 0x5e, - 0x6a, 0x91, 0xc6, 0xc3, 0xf3, 0x0f, 0x1f, 0x9e, 0xd2, 0x20, 0x66, 0x6d, 0xfc, 0xff, 0x00, 0xe9, - 0x8f, 0x84, 0x90, 0xae, 0xf2, 0x3e, 0x66, 0x7e, 0x41, 0xa5, 0x77, 0xa3, 0xa0, 0x46, 0xb4, 0x7b, - 0x03, 0xdb, 0x5d, 0xb0, 0xdb, 0xac, 0x5d, 0x3f, 0xf0, 0x13, 0xfe, 0x83, 0x21, 0x1f, 0x5b, 0x0f, - 0xc8, 0x00, 0x9a, 0xfa, 0xcf, 0x77, 0x10, 0x19, 0xed, 0x2f, 0xf8, 0x01, 0x92, 0xde, 0xcd, 0xc2, - 0x3a, 0x29, 0x73, 0xb0, 0x8f, 0xeb, 0x76, 0x87, 0xf5, 0x31, 0x41, 0x8c, 0xb4, 0x97, 0x21, 0x97, - 0xc4, 0xe9, 0xaf, 0x74, 0x90, 0x5b, 0x9a, 0x70, 0xcc, 0xfd, 0x46, 0x48, 0xef, 0xf6, 0x94, 0x5a, - 0xd1, 0xd7, 0x6d, 0xec, 0x6b, 0xd9, 0x26, 0xac, 0xaf, 0x3e, 0xe2, 0xc8, 0xdf, 0x08, 0xf9, 0xd8, - 0x7a, 0xb0, 0xfa, 0x67, 0xf7, 0xa1, 0xae, 0x6e, 0x02, 0x91, 0x1f, 0x43, 0xcb, 0x48, 0xe7, 0x20, - 0x72, 0x1a, 0x45, 0xd9, 0x1f, 0xbd, 0x5b, 0xc5, 0x95, 0xa2, 0xe3, 0x3b, 0xd8, 0x71, 0x97, 0x2c, - 0xb1, 0x8e, 0x45, 0x3e, 0xc4, 0x43, 0x4c, 0x7f, 0xe2, 0x4f, 0x97, 0xbc, 0xd2, 0x4e, 0x1c, 0xde, - 0xd9, 0xad, 0xec, 0x21, 0x60, 0xf4, 0x76, 0x7b, 0x4a, 0xad, 0xe8, 0xee, 0x16, 0x76, 0xb7, 0x44, - 0x16, 0xf5, 0xee, 0xd4, 0xed, 0x1c, 0x8a, 0xcf, 0x07, 0xe9, 0x3f, 0x60, 0x41, 0x6e, 0xa7, 0x8f, - 0xbb, 0x14, 0xfc, 0xb0, 0x85, 0x22, 0x91, 0xfc, 0xaf, 0x5b, 0xd8, 0x5d, 0xec, 0x8a, 0x10, 0xdc, - 0x3e, 0xfd, 0xf7, 0x2b, 0xc8, 0x31, 0x34, 0xb4, 0x77, 0x9e, 0xc9, 0x8d, 0xa9, 0x6f, 0x52, 0xf7, - 0x7a, 0x45, 0x55, 0x45, 0x53, 0xd1, 0xdb, 0x7f, 0xc8, 0x14, 0xd2, 0x1f, 0x42, 0x5d, 0xbd, 0x1c, - 0x4c, 0x96, 0xb5, 0x97, 0x9c, 0xf5, 0x97, 0x8e, 0x7b, 0xdd, 0x7c, 0x45, 0x11, 0xf1, 0xe9, 0xad, - 0x33, 0xe2, 0x7b, 0x09, 0x0d, 0xed, 0x75, 0x60, 0x35, 0x81, 0xfc, 0x0b, 0xc4, 0x6a, 0x02, 0x05, - 0x8f, 0x09, 0xdb, 0xf3, 0xd8, 0x45, 0x83, 0xd4, 0x91, 0xbe, 0x93, 0xd7, 0x61, 0x4c, 0x76, 0xe1, - 0xba, 0x38, 0x59, 0x8f, 0xe9, 0x17, 0xd9, 0x86, 0x82, 0xdf, 0x0c, 0x79, 0x64, 0x91, 0x27, 0x50, - 0x93, 0x8f, 0x40, 0x93, 0xa5, 0xe2, 0xc7, 0xac, 0x7b, 0xcb, 0x39, 0xb8, 0x38, 0x06, 0xbf, 0x0f, - 0x90, 0x3e, 0x45, 0xac, 0x84, 0x44, 0xee, 0x69, 0x63, 0x45, 0x01, 0xf9, 0x77, 0x8b, 0xed, 0x25, - 0x9c, 0x60, 0x87, 0xa0, 0x90, 0x08, 0xe8, 0x85, 0x7c, 0xbb, 0xe2, 0x47, 0xd0, 0xd0, 0x5e, 0x23, - 0x56, 0xcb, 0x97, 0x7f, 0xc9, 0x58, 0x2d, 0x5f, 0xc1, 0xe3, 0xc5, 0x76, 0x0f, 0x5b, 0x5f, 0xb4, - 0xe7, 0x58, 0xeb, 0xb1, 0x7f, 0x1a, 0x8c, 0x38, 0x02, 0xdb, 0xa0, 0x33, 0x68, 0x19, 0x4f, 0x0e, - 0x2b, 0x0e, 0x2d, 0x7a, 0xd0, 0x58, 0x71, 0x68, 0xe1, 0x2b, 0xc5, 0x92, 0xce, 0xec, 0x79, 0xd6, - 0xcf, 0x39, 0xa2, 0x68, 0x3d, 0xfd, 0x00, 0x1a, 0xda, 0xf3, 0xc1, 0x6a, 0x2e, 0xf9, 0x97, 0x8a, - 0xd5, 0x5c, 0x8a, 0x5e, 0x1b, 0x5e, 0xc4, 0x3e, 0xda, 0x36, 0x92, 0x02, 0xbe, 0x46, 0xc5, 0xda, - 0xfe, 0x31, 0xb4, 0xcd, 0x07, 0x85, 0x15, 0xef, 0x17, 0x3e, 0x4d, 0xac, 0x78, 0x7f, 0xca, 0x2b, - 0xc4, 0x82, 0xa4, 0x1f, 0x2c, 0xa8, 0x4e, 0x1e, 0xfe, 0x54, 0x5c, 0x6c, 0xfe, 0x9c, 0x7c, 0x97, - 0x09, 0x38, 0xf1, 0x4a, 0x1a, 0x59, 0xd6, 0xa8, 0x56, 0x7f, 0x4b, 0x4d, 0xf1, 0x4b, 0xee, 0x41, - 0x35, 0x93, 0x98, 0xf9, 0x7b, 0x5a, 0xcf, 0x60, 0x41, 0x11, 0xb3, 0x7a, 0xf5, 0x2c, 0x56, 0x73, - 0x28, 0x7c, 0x5c, 0xad, 0xd7, 0xc9, 0xd6, 0x3e, 0xb2, 0xf8, 0xf1, 0x87, 0x6f, 0x4b, 0x69, 0xc7, - 0x9f, 0xfe, 0xf0, 0x99, 0x76, 0xfc, 0x19, 0x4f, 0x50, 0x65, 0x8f, 0xbf, 0xc4, 0x67, 0x6d, 0x04, - 0x30, 0x97, 0xc9, 0x90, 0x55, 0xec, 0x55, 0xfc, 0x88, 0x41, 0xef, 0xce, 0xd5, 0x89, 0xb5, 0xa6, - 0x28, 0x92, 0xd2, 0xf4, 0xa1, 0x7c, 0x21, 0xe5, 0x0f, 0xa0, 0xa9, 0xbf, 0x83, 0x4a, 0x74, 0x99, - 0x90, 0xed, 0xe9, 0x66, 0x61, 0x9d, 0x49, 0x25, 0xa4, 0xa9, 0x77, 0x43, 0xbe, 0x07, 0x4b, 0x6a, - 0x99, 0xf5, 0x44, 0xc9, 0x98, 0xbc, 0x53, 0x90, 0x3e, 0x69, 0x2c, 0xf6, 0x8d, 0xa9, 0xf9, 0x95, - 0x8f, 0x2c, 0x46, 0x7d, 0xe6, 0x1b, 0x8c, 0xe9, 0xc9, 0x53, 0xf4, 0xf4, 0x64, 0x7a, 0xf2, 0x14, - 0x3e, 0xdc, 0x28, 0xa9, 0x8f, 0x2c, 0x18, 0x6b, 0xc4, 0xef, 0x6f, 0x91, 0x1f, 0xc0, 0x9c, 0x96, - 0xd6, 0x7e, 0x78, 0x19, 0xf4, 0x15, 0x27, 0xe5, 0x9f, 0x30, 0xea, 0x15, 0x99, 0xa5, 0xf6, 0x32, - 0xb6, 0x3f, 0x6f, 0x1b, 0x8b, 0xc3, 0xb8, 0x68, 0x03, 0x1a, 0x7a, 0xca, 0xfc, 0x15, 0xed, 0x2e, - 0x6b, 0x55, 0xfa, 0xfb, 0x38, 0x8f, 0x2c, 0xb2, 0x0b, 0x9d, 0xec, 0x53, 0x1e, 0x4a, 0xa6, 0x14, - 0x3d, 0x3f, 0xd2, 0xcb, 0x54, 0x1a, 0x0f, 0x80, 0x90, 0x03, 0x7e, 0x2b, 0x58, 0xfd, 0xb8, 0x46, - 0x18, 0x65, 0x4f, 0x75, 0xf3, 0x47, 0x37, 0x54, 0x6b, 0x45, 0x3f, 0xb7, 0x72, 0xdf, 0x7a, 0x64, - 0x91, 0xbf, 0x6b, 0x41, 0xd3, 0x48, 0x90, 0x37, 0xee, 0x58, 0x66, 0xe6, 0xd9, 0xd5, 0xeb, 0xf4, - 0x89, 0xda, 0x0e, 0x2e, 0xe2, 0xee, 0x83, 0x4f, 0x8c, 0x4d, 0xfa, 0xa9, 0xe1, 0xe9, 0x5d, 0xc9, - 0xfe, 0xc2, 0xc6, 0xe7, 0x59, 0x04, 0xfd, 0x19, 0xaa, 0xcf, 0x1f, 0x59, 0xe4, 0x9f, 0x58, 0xd0, - 0x36, 0x43, 0x38, 0x6a, 0xba, 0x85, 0xc1, 0x22, 0x45, 0x4a, 0x53, 0xe2, 0x3e, 0x3f, 0xc0, 0x51, - 0x1e, 0x3d, 0x70, 0x8c, 0x51, 0x8a, 0xd7, 0x43, 0x7f, 0xbd, 0xd1, 0x92, 0x8f, 0xf9, 0x0f, 0x5e, - 0xc9, 0xe8, 0x35, 0xc9, 0xff, 0x40, 0x92, 0x22, 0x3f, 0xfd, 0xe7, 0x84, 0x70, 0x13, 0x7e, 0xc4, - 0x7f, 0x59, 0x42, 0x86, 0x40, 0x19, 0x15, 0xbf, 0xed, 0xf7, 0xf6, 0x3d, 0x9c, 0xd3, 0x1d, 0xfb, - 0x86, 0x31, 0xa7, 0xac, 0xe2, 0xb1, 0xc6, 0x47, 0x27, 0x7e, 0x09, 0x28, 0x3d, 0x39, 0x73, 0xbf, - 0x0e, 0x34, 0x7d, 0x90, 0x23, 0x3e, 0x48, 0x81, 0x6e, 0xb0, 0xda, 0x5b, 0x36, 0x63, 0x3f, 0xc0, - 0xb1, 0xde, 0xb3, 0xdf, 0x99, 0x3a, 0xd6, 0x87, 0x18, 0x88, 0x61, 0x23, 0x3e, 0x00, 0x48, 0x6f, - 0x9b, 0x90, 0xcc, 0x4d, 0x07, 0x25, 0x80, 0xf2, 0x17, 0x52, 0x4c, 0x7e, 0x96, 0x17, 0x22, 0x58, - 0x8b, 0x3f, 0xe4, 0xe2, 0x74, 0x47, 0xde, 0x91, 0xd0, 0xb5, 0x2f, 0xf3, 0x4a, 0x88, 0xa1, 0x7d, - 0x65, 0xdb, 0x37, 0x84, 0xa9, 0xba, 0x70, 0xf1, 0x02, 0x5a, 0xbb, 0x61, 0xf8, 0x6a, 0x32, 0x56, - 0xd7, 0x1f, 0xcd, 0x18, 0xe9, 0xb6, 0x17, 0x9f, 0xf5, 0x32, 0xb3, 0xb0, 0xef, 0x62, 0x53, 0x3d, - 0xd2, 0xd5, 0x9a, 0x7a, 0xf8, 0xd3, 0xf4, 0x26, 0xcb, 0xe7, 0xc4, 0x83, 0x79, 0x25, 0xa3, 0xd5, - 0xc0, 0x7b, 0x66, 0x33, 0x86, 0x64, 0xce, 0x76, 0x61, 0x98, 0x09, 0x72, 0xb4, 0x0f, 0x63, 0xd9, - 0xe6, 0x23, 0x8b, 0x1c, 0x40, 0x73, 0x93, 0xf6, 0x31, 0x29, 0x14, 0x03, 0x8d, 0x0b, 0x46, 0xb0, - 0x8a, 0x47, 0x28, 0x7b, 0x2d, 0x03, 0x68, 0x9e, 0x5b, 0x63, 0xef, 0x32, 0xa2, 0x9f, 0x3d, 0xfc, - 0xa9, 0x08, 0x61, 0x7e, 0x2e, 0xcf, 0x2d, 0x19, 0xe3, 0x35, 0xce, 0xad, 0x4c, 0x50, 0xd8, 0x38, - 0xb7, 0x72, 0x41, 0x61, 0x63, 0xa9, 0x65, 0x8c, 0x99, 0x0c, 0x61, 0x3e, 0x17, 0x47, 0x56, 0x47, - 0xd6, 0xb4, 0xe8, 0x73, 0xef, 0xee, 0x74, 0x04, 0xb3, 0xb7, 0x07, 0x66, 0x6f, 0x87, 0xd0, 0xe2, - 0x4f, 0x63, 0x1d, 0x53, 0x9e, 0xef, 0x91, 0x79, 0x65, 0x41, 0xcf, 0x26, 0xc9, 0x1e, 0x30, 0x58, - 0x67, 0x6a, 0x38, 0xfc, 0x8d, 0xcd, 0x1f, 0x42, 0xe3, 0x19, 0x4d, 0x64, 0x82, 0x87, 0xd2, 0xb1, - 0x33, 0x19, 0x1f, 0xbd, 0x82, 0xfc, 0x10, 0x93, 0x66, 0xb0, 0xb5, 0x87, 0x74, 0x70, 0x4a, 0xb9, - 0x70, 0x72, 0xfd, 0xc1, 0xe7, 0xe4, 0xf7, 0xb1, 0x71, 0x95, 0x6e, 0xb7, 0xa4, 0xdd, 0xd6, 0xd7, - 0x1b, 0x9f, 0xcb, 0xc0, 0x8b, 0x5a, 0x0e, 0xc2, 0x01, 0xd5, 0x74, 0xbd, 0x00, 0x1a, 0x5a, 0xba, - 0xae, 0x62, 0xa0, 0x7c, 0x7a, 0xb6, 0x62, 0xa0, 0x82, 0xec, 0x5e, 0xfb, 0x3e, 0xf6, 0x63, 0x93, - 0xbb, 0x69, 0x3f, 0x3c, 0xa3, 0x37, 0xed, 0xe9, 0xe1, 0x4f, 0xbd, 0x51, 0xf2, 0x39, 0x79, 0x89, - 0x0f, 0xd5, 0xea, 0x09, 0x2c, 0xa9, 0xd1, 0x90, 0xcd, 0x75, 0x51, 0x8b, 0xa5, 0x55, 0x99, 0x86, - 0x04, 0xef, 0x0a, 0x35, 0xb9, 0x6f, 0x02, 0x1c, 0x26, 0xe1, 0x78, 0xd3, 0xa3, 0xa3, 0x30, 0x48, - 0x65, 0x6d, 0x9a, 0x3e, 0x91, 0xca, 0x2f, 0x2d, 0x87, 0x82, 0xbc, 0xd4, 0xac, 0x2c, 0x23, 0x07, - 0x48, 0x12, 0xd7, 0xd4, 0x0c, 0x0b, 0xb5, 0x20, 0x05, 0x59, 0x16, 0x8f, 0x2c, 0xb2, 0x06, 0x90, - 0x5e, 0x24, 0x50, 0x36, 0x53, 0xee, 0x8e, 0x82, 0x12, 0x7b, 0x05, 0xb7, 0x0e, 0x0e, 0xa0, 0x9e, - 0x86, 0x5d, 0x97, 0xd3, 0xd7, 0x07, 0x8c, 0x20, 0xad, 0x3a, 0xc1, 0x73, 0xc1, 0x50, 0xbb, 0x83, - 0x4b, 0x05, 0xa4, 0xc6, 0x96, 0x0a, 0x23, 0x9c, 0x3e, 0x2c, 0xf0, 0x01, 0x2a, 0x75, 0x09, 0xaf, - 0xfd, 0xab, 0xf7, 0x88, 0xf3, 0x01, 0x49, 0xc5, 0xcd, 0x85, 0xf1, 0x34, 0xc3, 0xf5, 0xc3, 0xa8, - 0x95, 0xa7, 0x1c, 0x30, 0xd1, 0x3c, 0x82, 0xf9, 0x5c, 0x88, 0x46, 0xb1, 0xf4, 0xb4, 0x18, 0x9c, - 0x62, 0xe9, 0xa9, 0xd1, 0x1d, 0xfb, 0x3a, 0x76, 0x39, 0x67, 0x03, 0x9a, 0x7a, 0x17, 0x7e, 0xd2, - 0x3f, 0x63, 0xdd, 0xfd, 0xb1, 0x05, 0x0b, 0x05, 0x11, 0x18, 0xf2, 0xae, 0xf4, 0x1a, 0x4c, 0x8d, - 0xce, 0xf4, 0x0a, 0x1d, 0xf4, 0xf6, 0x21, 0xf6, 0xf3, 0x9c, 0x7c, 0x6a, 0x1c, 0x6c, 0xdc, 0x37, - 0x2e, 0x38, 0xf3, 0x4a, 0xa5, 0xa2, 0x50, 0xa3, 0xf8, 0x0c, 0x96, 0xf9, 0x40, 0xd6, 0x86, 0xc3, - 0x4c, 0xf0, 0xe0, 0x4e, 0xee, 0x47, 0x71, 0x8d, 0xa0, 0x48, 0x6f, 0xfa, 0x8f, 0xe6, 0x4e, 0x51, - 0xa7, 0xf9, 0x50, 0xc9, 0x04, 0x3a, 0x59, 0x87, 0x3c, 0x99, 0xde, 0x56, 0xef, 0x1d, 0xc3, 0xfe, - 0x2d, 0x70, 0xe2, 0x7f, 0x19, 0x3b, 0x7b, 0xc7, 0xee, 0x15, 0xad, 0x0b, 0x37, 0x89, 0xd9, 0x7e, - 0xfc, 0x65, 0x15, 0x3d, 0xc8, 0xcc, 0x53, 0x76, 0x30, 0x2d, 0xdc, 0xa1, 0x2c, 0xf0, 0xe2, 0xe0, - 0xc3, 0x7b, 0xd8, 0xfd, 0x5d, 0xfb, 0x66, 0x51, 0xf7, 0x11, 0xff, 0x84, 0xdb, 0xe2, 0xcb, 0x59, - 0xbe, 0x96, 0x23, 0xb8, 0x5b, 0xb4, 0xdf, 0x53, 0x6d, 0xa1, 0xcc, 0x5a, 0x5f, 0x43, 0xdd, 0xae, - 0xa9, 0x47, 0x0b, 0x14, 0xfb, 0x14, 0x84, 0x25, 0x14, 0xfb, 0x14, 0x85, 0x17, 0x4c, 0xbd, 0x46, - 0x06, 0x16, 0x3e, 0xb6, 0x1e, 0xac, 0xbf, 0xff, 0x83, 0x2f, 0x9f, 0xfa, 0xc9, 0xd9, 0xe4, 0x78, - 0xa5, 0x1f, 0x8e, 0x1e, 0x0e, 0xa5, 0xb7, 0x51, 0xa4, 0xc2, 0x3d, 0x1c, 0x06, 0x83, 0x87, 0xd8, - 0xec, 0xf1, 0x0c, 0xfe, 0x8a, 0xf7, 0xd7, 0xff, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x6d, - 0x27, 0xff, 0xf7, 0x7b, 0x00, 0x00, + 0x24, 0xfb, 0x5f, 0x58, 0xd0, 0x11, 0x8c, 0xa6, 0xea, 0x18, 0x65, 0xeb, 0x99, 0x01, 0x15, 0xe5, + 0xb3, 0x79, 0xd7, 0x70, 0xb9, 0x14, 0x3e, 0xc2, 0x70, 0x0f, 0x5a, 0xe8, 0x04, 0x51, 0x67, 0x91, + 0x88, 0xca, 0x1b, 0x40, 0x36, 0x11, 0x79, 0xed, 0x73, 0xe4, 0x0f, 0x05, 0x41, 0xeb, 0x20, 0x79, + 0x9c, 0x45, 0x9e, 0xc8, 0xfe, 0xb2, 0x1c, 0x55, 0xb6, 0x7f, 0x69, 0xc1, 0xbc, 0x36, 0x13, 0xc1, + 0xc1, 0x4f, 0xa0, 0xa9, 0x1e, 0xba, 0xa3, 0x4a, 0xdb, 0x5a, 0x36, 0x45, 0x4e, 0xfa, 0x99, 0x81, + 0x8c, 0x8c, 0xe0, 0x5d, 0xe2, 0x00, 0xe3, 0xc9, 0x48, 0xa8, 0x39, 0x3a, 0x88, 0x11, 0xd8, 0x05, + 0xa5, 0xaf, 0x14, 0x0a, 0x57, 0xb4, 0x0c, 0x18, 0x06, 0x8f, 0xc2, 0x20, 0x39, 0x53, 0x48, 0x15, + 0x11, 0x3c, 0xd2, 0x81, 0xf6, 0x7f, 0x29, 0xc1, 0x02, 0xf7, 0xc6, 0x09, 0x2f, 0xa8, 0x7a, 0x6b, + 0x68, 0x86, 0x3b, 0x26, 0xb9, 0x34, 0xdb, 0xbe, 0xe6, 0x88, 0x32, 0xf9, 0xe6, 0x5b, 0x7a, 0x10, + 0x55, 0x9a, 0xd9, 0x94, 0xbd, 0x28, 0x17, 0xed, 0xc5, 0x15, 0x2b, 0x5d, 0x14, 0xc7, 0xab, 0x16, + 0xc7, 0xf1, 0xde, 0x2e, 0x6e, 0x96, 0xcb, 0xc5, 0x9a, 0x15, 0x58, 0x46, 0x2e, 0xd6, 0x2a, 0x2c, + 0x1b, 0x00, 0x14, 0xe4, 0xfe, 0x89, 0x4f, 0x65, 0x62, 0xfc, 0x7c, 0x4c, 0x13, 0xd7, 0x40, 0x59, + 0x9f, 0x85, 0x6a, 0xdc, 0x0f, 0xc7, 0xd4, 0x5e, 0x82, 0x45, 0x73, 0x71, 0xc5, 0xf1, 0xf1, 0x0b, + 0x0b, 0xba, 0x4f, 0xf9, 0x6d, 0x0c, 0x3f, 0x38, 0xdd, 0xf6, 0xe3, 0x24, 0x8c, 0xd4, 0x93, 0x70, + 0x77, 0x00, 0xe2, 0xc4, 0x8b, 0x84, 0x01, 0xca, 0xb5, 0x60, 0x0d, 0xc2, 0xd6, 0x88, 0x06, 0x03, + 0x5e, 0xcb, 0x69, 0x43, 0x95, 0x73, 0x56, 0x86, 0xf0, 0x55, 0x1a, 0xba, 0xfa, 0x7b, 0x3c, 0x45, + 0x94, 0x2d, 0x06, 0x3d, 0xc7, 0x33, 0x99, 0x3b, 0x00, 0x33, 0x50, 0xfb, 0x0f, 0x4b, 0x30, 0x97, + 0x0e, 0x92, 0xa7, 0x9c, 0x1b, 0x92, 0x5d, 0x28, 0xe8, 0xa9, 0x64, 0x17, 0x71, 0x45, 0xd7, 0x67, + 0x1a, 0xbb, 0xe6, 0xae, 0xd4, 0xa0, 0xe4, 0x1e, 0x34, 0x64, 0x29, 0x9c, 0x24, 0xda, 0xdb, 0x4c, + 0x3a, 0x98, 0xe7, 0x9e, 0x30, 0x9b, 0x41, 0x32, 0x3d, 0x2f, 0xe1, 0x43, 0x09, 0xa3, 0x04, 0xbf, + 0xe4, 0x7b, 0x2a, 0x8b, 0x4c, 0xd2, 0x31, 0x65, 0x9b, 0xef, 0x21, 0x2a, 0xda, 0xba, 0x12, 0x5a, + 0x53, 0x6f, 0x5a, 0x2a, 0x9e, 0xe7, 0x2d, 0xa6, 0x59, 0x78, 0x15, 0x47, 0x07, 0x49, 0x77, 0x51, + 0x38, 0x31, 0xec, 0x62, 0x03, 0x66, 0xff, 0x0d, 0x0b, 0x6e, 0x14, 0x6c, 0xa3, 0x90, 0x01, 0x9b, + 0x30, 0x7f, 0xa2, 0x2a, 0xe5, 0x52, 0x73, 0x41, 0xb0, 0x24, 0xa5, 0xae, 0xb9, 0xbc, 0x4e, 0xfe, + 0x03, 0x65, 0x87, 0xf1, 0xcd, 0x33, 0x92, 0x2e, 0xf3, 0x15, 0xf6, 0x01, 0xf4, 0xb6, 0x5e, 0x33, + 0x91, 0xb2, 0xa1, 0x3f, 0x6c, 0x2e, 0x29, 0x6b, 0x35, 0x27, 0x32, 0xdf, 0xec, 0xa5, 0x3e, 0xe1, + 0xa9, 0x64, 0xaa, 0x2d, 0xf2, 0xf5, 0xb7, 0x6d, 0x44, 0xe7, 0xfe, 0xbb, 0x62, 0xd7, 0xf9, 0xcb, + 0xec, 0x32, 0xf5, 0x53, 0x03, 0xd9, 0xe7, 0x30, 0xf7, 0x7c, 0x32, 0x4c, 0xfc, 0xf4, 0x95, 0x76, + 0xf2, 0x4d, 0xf1, 0x11, 0x36, 0x21, 0x97, 0xae, 0xb0, 0x2b, 0x1d, 0x8f, 0xad, 0xd8, 0x88, 0xb5, + 0xe4, 0xe6, 0x7b, 0xcc, 0x57, 0xd8, 0x37, 0x60, 0x39, 0xed, 0x92, 0xaf, 0x9d, 0x3c, 0x8f, 0xfe, + 0xc8, 0xe2, 0x57, 0xae, 0xcd, 0x47, 0xe3, 0xc9, 0x33, 0x58, 0x88, 0xfd, 0xe0, 0x74, 0x48, 0xf5, + 0x76, 0x62, 0xb1, 0x12, 0xd7, 0xcd, 0xe1, 0x89, 0x87, 0xe5, 0x9d, 0xa2, 0x2f, 0x18, 0x81, 0x14, + 0x0f, 0x34, 0x25, 0x90, 0xcc, 0x92, 0x14, 0x4d, 0xe0, 0x13, 0x68, 0x9b, 0x9d, 0x91, 0xc7, 0x22, + 0xa7, 0x32, 0x1d, 0x59, 0x39, 0x93, 0x1a, 0x97, 0x52, 0x86, 0x81, 0x69, 0xff, 0xcc, 0x82, 0xae, + 0x43, 0x19, 0x19, 0x53, 0xad, 0x53, 0x41, 0x3d, 0x4f, 0x72, 0xcd, 0x4e, 0x9f, 0xb0, 0xca, 0xd5, + 0x94, 0x73, 0x5d, 0x99, 0xba, 0x29, 0xdb, 0xd7, 0x0a, 0x66, 0xb5, 0x5e, 0x83, 0x19, 0x31, 0xbf, + 0x65, 0xb8, 0x2e, 0x86, 0x24, 0x87, 0x93, 0xc6, 0x23, 0x8d, 0x4e, 0x8d, 0x78, 0x64, 0x0f, 0xba, + 0xfc, 0xe5, 0x3f, 0x7d, 0x1e, 0xe2, 0xc3, 0x4d, 0x20, 0xcf, 0xbd, 0xbe, 0x17, 0x85, 0x61, 0x70, + 0x40, 0x23, 0x71, 0x7b, 0x15, 0xd5, 0x52, 0x0c, 0xd7, 0x49, 0x0d, 0x9a, 0x97, 0xe4, 0x63, 0x75, + 0x61, 0x20, 0x1f, 0x05, 0xe4, 0x25, 0xdb, 0x81, 0x85, 0x75, 0xef, 0x15, 0x95, 0x2d, 0xa5, 0xab, + 0xd4, 0x18, 0xab, 0x46, 0xe5, 0xda, 0xcb, 0x64, 0xec, 0x7c, 0xb7, 0x8e, 0x8e, 0x6d, 0xaf, 0xc2, + 0xa2, 0xd9, 0xa6, 0x10, 0x25, 0x3d, 0xa8, 0x8d, 0x04, 0x4c, 0x8c, 0x4e, 0x95, 0x1f, 0x7c, 0x0e, + 0x0d, 0xed, 0x35, 0x47, 0xb2, 0x0c, 0x0b, 0x2f, 0x77, 0x8e, 0xf6, 0xb6, 0x0e, 0x0f, 0xdd, 0x83, + 0x17, 0xeb, 0x9f, 0x6e, 0x7d, 0xdf, 0xdd, 0x5e, 0x3b, 0xdc, 0xee, 0x5c, 0x23, 0x4b, 0x40, 0xf6, + 0xb6, 0x0e, 0x8f, 0xb6, 0x36, 0x0d, 0xb8, 0x45, 0xee, 0x40, 0xef, 0xc5, 0xde, 0x8b, 0xc3, 0xad, + 0x4d, 0xb7, 0xe8, 0xbb, 0x12, 0xb9, 0x0d, 0x37, 0x44, 0x7d, 0xc1, 0xe7, 0xe5, 0x07, 0x4f, 0xa0, + 0x93, 0xf5, 0x57, 0x1a, 0x7e, 0xde, 0xab, 0x1c, 0xc2, 0x0f, 0xfe, 0x61, 0x19, 0x20, 0xbd, 0xb5, + 0x4a, 0xba, 0xb0, 0xb8, 0xb9, 0x76, 0xb4, 0xb6, 0xbb, 0xcf, 0x06, 0xe1, 0xec, 0x1f, 0x6d, 0x6d, + 0x1c, 0xb9, 0xce, 0xd6, 0x77, 0x3b, 0xd7, 0x0a, 0x6b, 0xf6, 0x0f, 0x98, 0x2d, 0xbf, 0x0c, 0x0b, + 0x3b, 0x7b, 0x3b, 0x47, 0x3b, 0x6b, 0xbb, 0xae, 0xb3, 0xff, 0x62, 0x67, 0xef, 0x19, 0x7f, 0x90, + 0xa5, 0x4c, 0xde, 0x81, 0x9b, 0x2f, 0x0e, 0x9e, 0x3a, 0xfb, 0x7b, 0x47, 0xee, 0xe1, 0xf6, 0x8b, + 0xa3, 0x4d, 0x7c, 0xce, 0x65, 0xc3, 0xd9, 0x39, 0xe0, 0x6d, 0x56, 0xae, 0x42, 0x60, 0x4d, 0x57, + 0xd9, 0x8a, 0x3d, 0xdb, 0x3f, 0x3c, 0xdc, 0x39, 0x70, 0xbf, 0xfb, 0x62, 0xcb, 0xd9, 0xd9, 0x3a, + 0xc4, 0x0f, 0x67, 0x0a, 0xe0, 0x0c, 0x7f, 0x96, 0xcc, 0x43, 0xeb, 0x68, 0xf7, 0x7b, 0xee, 0xfe, + 0xde, 0xce, 0xfe, 0x1e, 0xa2, 0xd6, 0x4c, 0x10, 0xc3, 0xaa, 0x93, 0x1e, 0x2c, 0x6d, 0xfd, 0xfe, + 0x91, 0x5b, 0xd0, 0x32, 0x4c, 0xa9, 0x63, 0xdf, 0x35, 0xc8, 0x0d, 0xb8, 0x7e, 0x78, 0xb4, 0x76, + 0xb4, 0xb3, 0xe1, 0x8a, 0xa7, 0xa0, 0xd8, 0x26, 0xb0, 0xcf, 0x9a, 0xc5, 0x55, 0xec, 0xab, 0x16, + 0x59, 0x84, 0xce, 0xc1, 0xda, 0xf7, 0x9f, 0x6f, 0xed, 0x1d, 0xb9, 0x6b, 0x9b, 0x9b, 0x0e, 0x7e, + 0xd0, 0xce, 0x41, 0x19, 0xee, 0x1c, 0xdb, 0xa8, 0xe7, 0x07, 0x07, 0x88, 0xd2, 0x91, 0x05, 0x56, + 0x33, 0xbf, 0xfa, 0xb3, 0x32, 0xb4, 0x79, 0x1a, 0x01, 0xff, 0x79, 0x0c, 0x1a, 0x91, 0xe7, 0x30, + 0x2b, 0x7e, 0x67, 0x85, 0x5c, 0x57, 0xaf, 0x70, 0xe8, 0xbf, 0xec, 0xd2, 0x5b, 0xca, 0x82, 0x05, + 0xfb, 0x2d, 0xfc, 0xa5, 0xff, 0xf0, 0xdf, 0x7e, 0x5e, 0x6a, 0x91, 0xc6, 0xc3, 0xf3, 0x0f, 0x1f, + 0x9e, 0xd2, 0x20, 0x66, 0x6d, 0xfc, 0xff, 0x00, 0xe9, 0xaf, 0x87, 0x90, 0xae, 0x72, 0x4b, 0x66, + 0x7e, 0x5a, 0xa5, 0x77, 0xa3, 0xa0, 0x46, 0xb4, 0x7b, 0x03, 0xdb, 0x5d, 0xb0, 0xdb, 0xac, 0x5d, + 0x3f, 0xf0, 0x13, 0xfe, 0x4b, 0x22, 0x1f, 0x5b, 0x0f, 0xc8, 0x00, 0x9a, 0xfa, 0xef, 0x7a, 0x10, + 0x79, 0x0d, 0xa0, 0xe0, 0x97, 0x49, 0x7a, 0x37, 0x0b, 0xeb, 0xa4, 0xcc, 0xc1, 0x3e, 0xae, 0xdb, + 0x1d, 0xd6, 0xc7, 0x04, 0x31, 0xd2, 0x5e, 0x86, 0x5c, 0x12, 0xa7, 0x3f, 0xdf, 0x41, 0x6e, 0x69, + 0xc2, 0x31, 0xf7, 0xe3, 0x21, 0xbd, 0xdb, 0x53, 0x6a, 0x45, 0x5f, 0xb7, 0xb1, 0xaf, 0x65, 0x9b, + 0xb0, 0xbe, 0xfa, 0x88, 0x23, 0x7f, 0x3c, 0xe4, 0x63, 0xeb, 0xc1, 0xea, 0x9f, 0xde, 0x87, 0xba, + 0xba, 0x22, 0x44, 0x7e, 0x0c, 0x2d, 0x23, 0xcf, 0x83, 0xc8, 0x69, 0x14, 0xa5, 0x85, 0xf4, 0x6e, + 0x15, 0x57, 0x8a, 0x8e, 0xef, 0x60, 0xc7, 0x5d, 0xb2, 0xc4, 0x3a, 0x16, 0x89, 0x12, 0x0f, 0x31, + 0x2f, 0x8a, 0xbf, 0x69, 0xf2, 0x4a, 0x3b, 0x71, 0x78, 0x67, 0xb7, 0xb2, 0x87, 0x80, 0xd1, 0xdb, + 0xed, 0x29, 0xb5, 0xa2, 0xbb, 0x5b, 0xd8, 0xdd, 0x12, 0x59, 0xd4, 0xbb, 0x53, 0xd7, 0x76, 0x28, + 0xbe, 0x2b, 0xa4, 0xff, 0xb2, 0x05, 0xb9, 0x9d, 0xbe, 0xfa, 0x52, 0xf0, 0x8b, 0x17, 0x8a, 0x44, + 0xf2, 0x3f, 0x7b, 0x61, 0x77, 0xb1, 0x2b, 0x42, 0x70, 0xfb, 0xf4, 0x1f, 0xb6, 0x20, 0xc7, 0xd0, + 0xd0, 0x1e, 0x80, 0x26, 0x37, 0xa6, 0x3e, 0x56, 0xdd, 0xeb, 0x15, 0x55, 0x15, 0x4d, 0x45, 0x6f, + 0xff, 0x21, 0x53, 0x48, 0x7f, 0x08, 0x75, 0xf5, 0xa4, 0x30, 0x59, 0xd6, 0x9e, 0x78, 0xd6, 0x9f, + 0x40, 0xee, 0x75, 0xf3, 0x15, 0x45, 0xc4, 0xa7, 0xb7, 0xce, 0x88, 0xef, 0x25, 0x34, 0xb4, 0x67, + 0x83, 0xd5, 0x04, 0xf2, 0x4f, 0x13, 0xab, 0x09, 0x14, 0xbc, 0x32, 0x6c, 0xcf, 0x63, 0x17, 0x0d, + 0x52, 0x47, 0xfa, 0x4e, 0x5e, 0x87, 0x31, 0xd9, 0x85, 0xeb, 0xe2, 0x64, 0x3d, 0xa6, 0x5f, 0x64, + 0x1b, 0x0a, 0x7e, 0x4c, 0xe4, 0x91, 0x45, 0x9e, 0x40, 0x4d, 0xbe, 0x0e, 0x4d, 0x96, 0x8a, 0x5f, + 0xb9, 0xee, 0x2d, 0xe7, 0xe0, 0xe2, 0x18, 0xfc, 0x3e, 0x40, 0xfa, 0x46, 0xb1, 0x12, 0x12, 0xb9, + 0x37, 0x8f, 0x15, 0x05, 0xe4, 0x1f, 0x34, 0xb6, 0x97, 0x70, 0x82, 0x1d, 0x82, 0x42, 0x22, 0xa0, + 0x17, 0xf2, 0x51, 0x8b, 0x1f, 0x41, 0x43, 0x7b, 0xa6, 0x58, 0x2d, 0x5f, 0xfe, 0x89, 0x63, 0xb5, + 0x7c, 0x05, 0xaf, 0x1a, 0xdb, 0x3d, 0x6c, 0x7d, 0xd1, 0x9e, 0x63, 0xad, 0xc7, 0xfe, 0x69, 0x30, + 0xe2, 0x08, 0x6c, 0x83, 0xce, 0xa0, 0x65, 0xbc, 0x45, 0xac, 0x38, 0xb4, 0xe8, 0xa5, 0x63, 0xc5, + 0xa1, 0x85, 0xcf, 0x17, 0x4b, 0x3a, 0xb3, 0xe7, 0x59, 0x3f, 0xe7, 0x88, 0xa2, 0xf5, 0xf4, 0x03, + 0x68, 0x68, 0xef, 0x0a, 0xab, 0xb9, 0xe4, 0x9f, 0x30, 0x56, 0x73, 0x29, 0x7a, 0x86, 0x78, 0x11, + 0xfb, 0x68, 0xdb, 0x48, 0x0a, 0xf8, 0x4c, 0x15, 0x6b, 0xfb, 0xc7, 0xd0, 0x36, 0x5f, 0x1a, 0x56, + 0xbc, 0x5f, 0xf8, 0x66, 0xb1, 0xe2, 0xfd, 0x29, 0xcf, 0x13, 0x0b, 0x92, 0x7e, 0xb0, 0xa0, 0x3a, + 0x79, 0xf8, 0x53, 0x71, 0xe3, 0xf9, 0x73, 0xf2, 0x5d, 0x26, 0xe0, 0xc4, 0xf3, 0x69, 0x64, 0x59, + 0xa3, 0x5a, 0xfd, 0x91, 0x35, 0xc5, 0x2f, 0xb9, 0x97, 0xd6, 0x4c, 0x62, 0xe6, 0x0f, 0x6d, 0x3d, + 0x83, 0x05, 0x45, 0xcc, 0xea, 0x39, 0xb4, 0x58, 0xcd, 0xa1, 0xf0, 0xd5, 0xb5, 0x5e, 0x27, 0x5b, + 0xfb, 0xc8, 0xe2, 0xc7, 0x1f, 0x3e, 0x3a, 0xa5, 0x1d, 0x7f, 0xfa, 0x8b, 0x68, 0xda, 0xf1, 0x67, + 0xbc, 0x4d, 0x95, 0x3d, 0xfe, 0x12, 0x9f, 0xb5, 0x11, 0xc0, 0x5c, 0x26, 0x75, 0x56, 0xb1, 0x57, + 0xf1, 0xeb, 0x06, 0xbd, 0x3b, 0x57, 0x67, 0xdc, 0x9a, 0xa2, 0x48, 0x4a, 0xd3, 0x87, 0xf2, 0xe9, + 0x94, 0x3f, 0x80, 0xa6, 0xfe, 0x40, 0x2a, 0xd1, 0x65, 0x42, 0xb6, 0xa7, 0x9b, 0x85, 0x75, 0x26, + 0x95, 0x90, 0xa6, 0xde, 0x0d, 0xf9, 0x1e, 0x2c, 0xa9, 0x65, 0xd6, 0x33, 0x28, 0x63, 0xf2, 0x4e, + 0x41, 0x5e, 0xa5, 0xb1, 0xd8, 0x37, 0xa6, 0x26, 0x5e, 0x3e, 0xb2, 0x18, 0xf5, 0x99, 0x8f, 0x33, + 0xa6, 0x27, 0x4f, 0xd1, 0x9b, 0x94, 0xe9, 0xc9, 0x53, 0xf8, 0xa2, 0xa3, 0xa4, 0x3e, 0xb2, 0x60, + 0xac, 0x11, 0xbf, 0xd8, 0x45, 0x7e, 0x00, 0x73, 0x5a, 0xbe, 0xfb, 0xe1, 0x65, 0xd0, 0x57, 0x9c, + 0x94, 0x7f, 0xdb, 0xa8, 0x57, 0x64, 0x96, 0xda, 0xcb, 0xd8, 0xfe, 0xbc, 0x6d, 0x2c, 0x0e, 0xe3, + 0xa2, 0x0d, 0x68, 0xe8, 0xb9, 0xf4, 0x57, 0xb4, 0xbb, 0xac, 0x55, 0xe9, 0x0f, 0xe7, 0x3c, 0xb2, + 0xc8, 0x2e, 0x74, 0xb2, 0x6f, 0x7c, 0x28, 0x99, 0x52, 0xf4, 0x2e, 0x49, 0x2f, 0x53, 0x69, 0xbc, + 0x0c, 0x42, 0x0e, 0xf8, 0x75, 0x61, 0xf5, 0xab, 0x1b, 0x61, 0x94, 0x3d, 0xd5, 0xcd, 0x5f, 0xe3, + 0x50, 0xad, 0x15, 0xfd, 0x0e, 0xcb, 0x7d, 0xeb, 0x91, 0x45, 0xfe, 0x8e, 0x05, 0x4d, 0x23, 0x73, + 0xde, 0xb8, 0x7c, 0x99, 0x99, 0x67, 0x57, 0xaf, 0xd3, 0x27, 0x6a, 0x3b, 0xb8, 0x88, 0xbb, 0x0f, + 0x3e, 0x31, 0x36, 0xe9, 0xa7, 0x86, 0xa7, 0x77, 0x25, 0xfb, 0xd3, 0x1b, 0x9f, 0x67, 0x11, 0xf4, + 0xf7, 0xa9, 0x3e, 0x7f, 0x64, 0x91, 0x7f, 0x6c, 0x41, 0xdb, 0x8c, 0xed, 0xa8, 0xe9, 0x16, 0x46, + 0x91, 0x14, 0x29, 0x4d, 0x09, 0x08, 0xfd, 0x00, 0x47, 0x79, 0xf4, 0xc0, 0x31, 0x46, 0x29, 0x9e, + 0x15, 0xfd, 0xf5, 0x46, 0x4b, 0x3e, 0xe6, 0xbf, 0x84, 0x25, 0xc3, 0xda, 0x24, 0xff, 0xcb, 0x49, + 0x8a, 0xfc, 0xf4, 0xdf, 0x19, 0xc2, 0x4d, 0xf8, 0x11, 0xff, 0xc9, 0x09, 0x19, 0x1b, 0x65, 0x54, + 0xfc, 0xb6, 0xdf, 0xdb, 0xf7, 0x70, 0x4e, 0x77, 0xec, 0x1b, 0xc6, 0x9c, 0xb2, 0x8a, 0xc7, 0x1a, + 0x1f, 0x9d, 0xf8, 0x89, 0xa0, 0xf4, 0xe4, 0xcc, 0xfd, 0x6c, 0xd0, 0xf4, 0x41, 0x8e, 0xf8, 0x20, + 0x05, 0xba, 0xc1, 0x6a, 0x6f, 0xd9, 0x8c, 0xfd, 0x00, 0xc7, 0x7a, 0xcf, 0x7e, 0x67, 0xea, 0x58, + 0x1f, 0x62, 0x84, 0x86, 0x8d, 0xf8, 0x00, 0x20, 0xbd, 0x86, 0x42, 0x32, 0x57, 0x20, 0x94, 0x00, + 0xca, 0xdf, 0x54, 0x31, 0xf9, 0x59, 0xde, 0x94, 0x60, 0x2d, 0xfe, 0x90, 0x8b, 0xd3, 0x1d, 0x79, + 0x79, 0x42, 0xd7, 0xbe, 0xcc, 0xbb, 0x22, 0x86, 0xf6, 0x95, 0x6d, 0xdf, 0x10, 0xa6, 0xea, 0x26, + 0xc6, 0x0b, 0x68, 0xed, 0x86, 0xe1, 0xab, 0xc9, 0x58, 0xdd, 0x8b, 0x34, 0x83, 0xa7, 0xdb, 0x5e, + 0x7c, 0xd6, 0xcb, 0xcc, 0xc2, 0xbe, 0x8b, 0x4d, 0xf5, 0x48, 0x57, 0x6b, 0xea, 0xe1, 0x4f, 0xd3, + 0x2b, 0x2e, 0x9f, 0x13, 0x0f, 0xe6, 0x95, 0x8c, 0x56, 0x03, 0xef, 0x99, 0xcd, 0x18, 0x92, 0x39, + 0xdb, 0x85, 0x61, 0x26, 0xc8, 0xd1, 0x3e, 0x8c, 0x65, 0x9b, 0x8f, 0x2c, 0x72, 0x00, 0xcd, 0x4d, + 0xda, 0xc7, 0x6c, 0x51, 0x8c, 0x40, 0x2e, 0x18, 0x51, 0x2c, 0x1e, 0xba, 0xec, 0xb5, 0x0c, 0xa0, + 0x79, 0x6e, 0x8d, 0xbd, 0xcb, 0x88, 0x7e, 0xf6, 0xf0, 0xa7, 0x22, 0xb6, 0xf9, 0xb9, 0x3c, 0xb7, + 0x64, 0xf0, 0xd7, 0x38, 0xb7, 0x32, 0xd1, 0x62, 0xe3, 0xdc, 0xca, 0x45, 0x8b, 0x8d, 0xa5, 0x96, + 0xc1, 0x67, 0x32, 0x84, 0xf9, 0x5c, 0x80, 0x59, 0x1d, 0x59, 0xd3, 0xc2, 0xd2, 0xbd, 0xbb, 0xd3, + 0x11, 0xcc, 0xde, 0x1e, 0x98, 0xbd, 0x1d, 0x42, 0x8b, 0xbf, 0x99, 0x75, 0x4c, 0x79, 0x22, 0x48, + 0xe6, 0xf9, 0x05, 0x3d, 0xcd, 0x24, 0x7b, 0xc0, 0x60, 0x9d, 0xa9, 0xe1, 0xf0, 0xc7, 0x37, 0x7f, + 0x08, 0x8d, 0x67, 0x34, 0x91, 0x99, 0x1f, 0x4a, 0xc7, 0xce, 0xa4, 0x82, 0xf4, 0x0a, 0x12, 0x47, + 0x4c, 0x9a, 0xc1, 0xd6, 0x1e, 0xd2, 0xc1, 0x29, 0xe5, 0xc2, 0xc9, 0xf5, 0x07, 0x9f, 0x93, 0xdf, + 0xc7, 0xc6, 0x55, 0x1e, 0xde, 0x92, 0x76, 0x8d, 0x5f, 0x6f, 0x7c, 0x2e, 0x03, 0x2f, 0x6a, 0x39, + 0x08, 0x07, 0x54, 0xd3, 0xf5, 0x02, 0x68, 0x68, 0x79, 0xbc, 0x8a, 0x81, 0xf2, 0x79, 0xdb, 0x8a, + 0x81, 0x0a, 0xd2, 0x7e, 0xed, 0xfb, 0xd8, 0x8f, 0x4d, 0xee, 0xa6, 0xfd, 0xf0, 0x54, 0xdf, 0xb4, + 0xa7, 0x87, 0x3f, 0xf5, 0x46, 0xc9, 0xe7, 0xe4, 0x25, 0xbe, 0x60, 0xab, 0x67, 0xb6, 0xa4, 0x46, + 0x43, 0x36, 0x09, 0x46, 0x2d, 0x96, 0x56, 0x65, 0x1a, 0x12, 0xbc, 0x2b, 0xd4, 0xe4, 0xbe, 0x09, + 0x70, 0x98, 0x84, 0xe3, 0x4d, 0x8f, 0x8e, 0xc2, 0x20, 0x95, 0xb5, 0x69, 0x5e, 0x45, 0x2a, 0xbf, + 0xb4, 0xe4, 0x0a, 0xf2, 0x52, 0xb3, 0xb2, 0x8c, 0xe4, 0x20, 0x49, 0x5c, 0x53, 0x53, 0x2f, 0xd4, + 0x82, 0x14, 0xa4, 0x5f, 0x3c, 0xb2, 0xc8, 0x1a, 0x40, 0x7a, 0xc3, 0x40, 0xd9, 0x4c, 0xb9, 0xcb, + 0x0b, 0x4a, 0xec, 0x15, 0x5c, 0x47, 0x38, 0x80, 0xba, 0x16, 0x8f, 0x4d, 0x9f, 0x25, 0x30, 0xa2, + 0xb7, 0xea, 0x04, 0xcf, 0x05, 0x43, 0xed, 0x0e, 0x2e, 0x15, 0x90, 0x1a, 0x5b, 0x2a, 0x8c, 0x70, + 0xfa, 0xb0, 0xc0, 0x07, 0xa8, 0xd4, 0x25, 0xcc, 0x07, 0x50, 0x0f, 0x15, 0xe7, 0x03, 0x92, 0x8a, + 0x9b, 0x0b, 0xe3, 0x69, 0x86, 0xeb, 0x87, 0x51, 0x2b, 0xcf, 0x45, 0x60, 0xa2, 0x79, 0x04, 0xf3, + 0xb9, 0x10, 0x8d, 0x62, 0xe9, 0x69, 0x31, 0x38, 0xc5, 0xd2, 0x53, 0xa3, 0x3b, 0xf6, 0x75, 0xec, + 0x72, 0xce, 0x06, 0x34, 0xf5, 0x2e, 0xfc, 0xa4, 0x7f, 0xc6, 0xba, 0xfb, 0x23, 0x0b, 0x16, 0x0a, + 0x22, 0x30, 0xe4, 0x5d, 0xe9, 0x35, 0x98, 0x1a, 0x9d, 0xe9, 0x15, 0x3a, 0xe8, 0xed, 0x43, 0xec, + 0xe7, 0x39, 0xf9, 0xd4, 0x38, 0xd8, 0xb8, 0x6f, 0x5c, 0x70, 0xe6, 0x95, 0x4a, 0x45, 0xa1, 0x46, + 0xf1, 0x19, 0x2c, 0xf3, 0x81, 0xac, 0x0d, 0x87, 0x99, 0xe0, 0xc1, 0x9d, 0xdc, 0xaf, 0xe5, 0x1a, + 0x41, 0x91, 0xde, 0xf4, 0x5f, 0xd3, 0x9d, 0xa2, 0x4e, 0xf3, 0xa1, 0x92, 0x09, 0x74, 0xb2, 0x0e, + 0x79, 0x32, 0xbd, 0xad, 0xde, 0x3b, 0x86, 0xfd, 0x5b, 0xe0, 0xc4, 0xff, 0x32, 0x76, 0xf6, 0x8e, + 0xdd, 0x2b, 0x5a, 0x17, 0x6e, 0x12, 0xb3, 0xfd, 0xf8, 0x8b, 0x2a, 0x7a, 0x90, 0x99, 0xa7, 0xec, + 0x60, 0x5a, 0xb8, 0x43, 0x59, 0xe0, 0xc5, 0xc1, 0x87, 0xf7, 0xb0, 0xfb, 0xbb, 0xf6, 0xcd, 0xa2, + 0xee, 0x23, 0xfe, 0x09, 0xb7, 0xc5, 0x97, 0xb3, 0x7c, 0x2d, 0x47, 0x70, 0xb7, 0x68, 0xbf, 0xa7, + 0xda, 0x42, 0x99, 0xb5, 0xbe, 0x86, 0xba, 0x5d, 0x53, 0x8f, 0x16, 0x28, 0xf6, 0x29, 0x08, 0x4b, + 0x28, 0xf6, 0x29, 0x0a, 0x2f, 0x98, 0x7a, 0x8d, 0x0c, 0x2c, 0x7c, 0x6c, 0x3d, 0x58, 0x7f, 0xff, + 0x07, 0x5f, 0x3e, 0xf5, 0x93, 0xb3, 0xc9, 0xf1, 0x4a, 0x3f, 0x1c, 0x3d, 0x1c, 0x4a, 0x6f, 0xa3, + 0xc8, 0x91, 0x7b, 0x38, 0x0c, 0x06, 0x0f, 0xb1, 0xd9, 0xe3, 0x19, 0xfc, 0x79, 0xef, 0xaf, 0xff, + 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x6b, 0xfa, 0x86, 0x10, 0x7c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 8e48440be8..8e39cf6d1a 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2895,6 +2895,9 @@ message Feature { message FeeReportRequest {} message ChannelFeeReport { + /// The short channel id that this fee report belongs to. + uint64 chan_id = 5 [jstype = JS_STRING]; + /// The channel that this fee report belongs to. string chan_point = 1 [json_name = "channel_point"]; diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index d4c2af0e36..1adabfb989 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -2179,6 +2179,11 @@ "lnrpcChannelFeeReport": { "type": "object", "properties": { + "chan_id": { + "type": "string", + "format": "uint64", + "description": "/ The short channel id that this fee report belongs to." + }, "chan_point": { "type": "string", "description": "/ The channel that this fee report belongs to." diff --git a/rpcserver.go b/rpcserver.go index a653741ef7..e0639aef58 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -5129,6 +5129,7 @@ func (r *rpcServer) FeeReport(ctx context.Context, // TODO(roasbeef): also add stats for revenue for each channel feeReports = append(feeReports, &lnrpc.ChannelFeeReport{ + ChanId: chanInfo.ChannelID, ChanPoint: chanInfo.ChannelPoint.String(), BaseFeeMsat: int64(edgePolicy.FeeBaseMSat), FeePerMil: int64(feeRateFixedPoint), From bf5ccce78604962532b524d6ece76d2660a1bb0e Mon Sep 17 00:00:00 2001 From: Ediz Turcan <0x6564697a@turcan.de> Date: Thu, 5 Mar 2020 20:22:02 +0100 Subject: [PATCH 129/562] sample-lnd.conf: remove deprecated wtclient option --- sample-lnd.conf | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sample-lnd.conf b/sample-lnd.conf index a66edb9581..13080dc924 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -380,12 +380,9 @@ litecoin.node=ltcd ; watchtower.writetimeout=15s [wtclient] -; Configure the private tower to which lnd will connect to backup encrypted -; justice transactions. The format should be pubkey@host:port, where the port is -; optional and assumed to be 9911 otherwise. At most one private tower URI is -; supported at this time; if none are provided then the watchtower client will -; be inactive. -; wtclient.private-tower-uris= +; Activate Watchtower Client. To get more information or configure watchtowers +; run `lncli wtclient -h` +; wtclient.active=true ; Specify the fee rate with which justice transactions will be signed. This fee ; rate should be chosen as a maximum fee rate one is willing to pay in order to From a520008960194294edd2ec625d0e945313637c6c Mon Sep 17 00:00:00 2001 From: Ediz Turcan <0x6564697a@turcan.de> Date: Thu, 5 Mar 2020 22:08:38 +0100 Subject: [PATCH 130/562] sample-lnd.conf: missing full stop added (typo) --- sample-lnd.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample-lnd.conf b/sample-lnd.conf index 13080dc924..ee3ce7cf0f 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -381,7 +381,7 @@ litecoin.node=ltcd [wtclient] ; Activate Watchtower Client. To get more information or configure watchtowers -; run `lncli wtclient -h` +; run `lncli wtclient -h`. ; wtclient.active=true ; Specify the fee rate with which justice transactions will be signed. This fee From 11532df5f3de7fe8caa73be18489f50b20cd0fd8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 3 Mar 2020 05:11:33 -0800 Subject: [PATCH 131/562] cmd/lncli: add --peer flag to list channels This commit adds a flag to listchannels that filters by remote pubkey. --- cmd/lncli/commands.go | 23 +- lnrpc/rpc.pb.go | 1264 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 6 + lnrpc/rpc.swagger.json | 8 + rpcserver.go | 12 + 5 files changed, 685 insertions(+), 628 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 08725f1f35..281fbed95e 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1990,6 +1990,12 @@ var listChannelsCommand = cli.Command{ Name: "private_only", Usage: "only list channels which are currently private", }, + cli.StringFlag{ + Name: "peer", + Usage: "(optional) only display channels with a " + + "particular peer, accepts 66-byte, " + + "hex-encoded pubkeys", + }, }, Action: actionDecorator(listChannels), } @@ -1999,11 +2005,26 @@ func listChannels(ctx *cli.Context) error { client, cleanUp := getClient(ctx) defer cleanUp() + peer := ctx.String("peer") + + // If the user requested channels with a particular key, parse the + // provided pubkey. + var peerKey []byte + if len(peer) > 0 { + pk, err := route.NewVertexFromStr(peer) + if err != nil { + return fmt.Errorf("invalid --peer pubkey: %v", err) + } + + peerKey = pk[:] + } + req := &lnrpc.ListChannelsRequest{ ActiveOnly: ctx.Bool("active_only"), InactiveOnly: ctx.Bool("inactive_only"), PublicOnly: ctx.Bool("public_only"), PrivateOnly: ctx.Bool("private_only"), + Peer: peerKey, } resp, err := client.ListChannels(ctxb, req) @@ -2011,8 +2032,6 @@ func listChannels(ctx *cli.Context) error { return err } - // TODO(roasbeef): defer close the client for the all - printRespJSON(resp) return nil diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index fda0e7ae16..131af41fe4 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -3097,10 +3097,14 @@ func (m *Channel) GetCloseAddress() string { } type ListChannelsRequest struct { - ActiveOnly bool `protobuf:"varint,1,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` - InactiveOnly bool `protobuf:"varint,2,opt,name=inactive_only,json=inactiveOnly,proto3" json:"inactive_only,omitempty"` - PublicOnly bool `protobuf:"varint,3,opt,name=public_only,json=publicOnly,proto3" json:"public_only,omitempty"` - PrivateOnly bool `protobuf:"varint,4,opt,name=private_only,json=privateOnly,proto3" json:"private_only,omitempty"` + ActiveOnly bool `protobuf:"varint,1,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` + InactiveOnly bool `protobuf:"varint,2,opt,name=inactive_only,json=inactiveOnly,proto3" json:"inactive_only,omitempty"` + PublicOnly bool `protobuf:"varint,3,opt,name=public_only,json=publicOnly,proto3" json:"public_only,omitempty"` + PrivateOnly bool `protobuf:"varint,4,opt,name=private_only,json=privateOnly,proto3" json:"private_only,omitempty"` + //* + //Filters the response for channels with a target peer's pubkey. If peer is + //empty, all channels will be returned. + Peer []byte `protobuf:"bytes,5,opt,name=peer,proto3" json:"peer,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -3159,6 +3163,13 @@ func (m *ListChannelsRequest) GetPrivateOnly() bool { return false } +func (m *ListChannelsRequest) GetPeer() []byte { + if m != nil { + return m.Peer + } + return nil +} + type ListChannelsResponse struct { /// The list of active channels Channels []*Channel `protobuf:"bytes,11,rep,name=channels,proto3" json:"channels,omitempty"` @@ -10637,628 +10648,629 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 9934 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5d, 0x6c, 0x1c, 0xd9, - 0x95, 0x18, 0xac, 0xea, 0x1f, 0xb2, 0xfb, 0xf4, 0x0f, 0x9b, 0x97, 0x14, 0xd9, 0x6a, 0xfd, 0x8c, - 0xa6, 0x2c, 0xcf, 0xc8, 0xf2, 0x98, 0xd2, 0xd0, 0xf6, 0xac, 0x3c, 0xfa, 0xd6, 0x6b, 0xfe, 0x49, - 0xe4, 0x0c, 0x45, 0xd2, 0x45, 0xca, 0x5a, 0xdb, 0xdf, 0xa2, 0x5c, 0xec, 0xbe, 0x24, 0xcb, 0xea, - 0xae, 0xea, 0xa9, 0xaa, 0x26, 0x45, 0x3b, 0x93, 0x87, 0x20, 0x09, 0x82, 0xbc, 0x04, 0x86, 0x11, - 0x20, 0xbf, 0x58, 0xc0, 0x9b, 0x20, 0x08, 0x02, 0x24, 0x41, 0x1e, 0x82, 0x0d, 0xe0, 0x3c, 0xe5, - 0x61, 0xf3, 0x12, 0xe4, 0x21, 0x01, 0x02, 0x24, 0x40, 0x80, 0xc5, 0xe6, 0x21, 0x8b, 0x00, 0x79, - 0x4a, 0xf2, 0x1c, 0xdc, 0x73, 0x7f, 0xea, 0xde, 0xaa, 0x6a, 0x4a, 0x63, 0x3b, 0x7e, 0x91, 0x78, - 0xcf, 0x3d, 0x75, 0x7f, 0xcf, 0x39, 0xf7, 0xfc, 0xdc, 0x73, 0x1b, 0xea, 0xd1, 0xb8, 0xbf, 0x32, - 0x8e, 0xc2, 0x24, 0x24, 0xd5, 0x61, 0x10, 0x8d, 0xfb, 0xbd, 0x5b, 0xa7, 0x61, 0x78, 0x3a, 0xa4, - 0x0f, 0xbd, 0xb1, 0xff, 0xd0, 0x0b, 0x82, 0x30, 0xf1, 0x12, 0x3f, 0x0c, 0x62, 0x8e, 0x64, 0xff, - 0x08, 0xda, 0xcf, 0x68, 0x70, 0x48, 0xe9, 0xc0, 0xa1, 0x9f, 0x4d, 0x68, 0x9c, 0x90, 0xaf, 0xc2, - 0xbc, 0x47, 0x7f, 0x42, 0xe9, 0xc0, 0x1d, 0x7b, 0x71, 0x3c, 0x3e, 0x8b, 0xbc, 0x98, 0x76, 0xad, - 0xbb, 0xd6, 0xfd, 0xa6, 0xd3, 0xe1, 0x15, 0x07, 0x0a, 0x4e, 0xde, 0x85, 0x66, 0xcc, 0x50, 0x69, - 0x90, 0x44, 0xe1, 0xf8, 0xb2, 0x5b, 0x42, 0xbc, 0x06, 0x83, 0x6d, 0x71, 0x90, 0x3d, 0x84, 0x39, - 0xd5, 0x43, 0x3c, 0x0e, 0x83, 0x98, 0x92, 0x47, 0xb0, 0xd8, 0xf7, 0xc7, 0x67, 0x34, 0x72, 0xf1, - 0xe3, 0x51, 0x40, 0x47, 0x61, 0xe0, 0xf7, 0xbb, 0xd6, 0xdd, 0xf2, 0xfd, 0xba, 0x43, 0x78, 0x1d, - 0xfb, 0xe2, 0xb9, 0xa8, 0x21, 0xef, 0xc3, 0x1c, 0x0d, 0x38, 0x9c, 0x0e, 0xf0, 0x2b, 0xd1, 0x55, - 0x3b, 0x05, 0xb3, 0x0f, 0xec, 0xbf, 0x56, 0x82, 0xf9, 0x9d, 0xc0, 0x4f, 0x5e, 0x7a, 0xc3, 0x21, - 0x4d, 0xe4, 0x9c, 0xde, 0x87, 0xb9, 0x0b, 0x04, 0xe0, 0x9c, 0x2e, 0xc2, 0x68, 0x20, 0x66, 0xd4, - 0xe6, 0xe0, 0x03, 0x01, 0x9d, 0x3a, 0xb2, 0xd2, 0xd4, 0x91, 0x15, 0x2e, 0x57, 0x79, 0xca, 0x72, - 0xbd, 0x0f, 0x73, 0x11, 0xed, 0x87, 0xe7, 0x34, 0xba, 0x74, 0x2f, 0xfc, 0x60, 0x10, 0x5e, 0x74, - 0x2b, 0x77, 0xad, 0xfb, 0x55, 0xa7, 0x2d, 0xc1, 0x2f, 0x11, 0x4a, 0xd6, 0x61, 0xae, 0x7f, 0xe6, - 0x05, 0x01, 0x1d, 0xba, 0xc7, 0x5e, 0xff, 0xd5, 0x64, 0x1c, 0x77, 0xab, 0x77, 0xad, 0xfb, 0x8d, - 0xd5, 0x1b, 0x2b, 0xb8, 0xab, 0x2b, 0x1b, 0x67, 0x5e, 0xb0, 0x8e, 0x35, 0x87, 0x81, 0x37, 0x8e, - 0xcf, 0xc2, 0xc4, 0x69, 0x8b, 0x2f, 0x38, 0x38, 0xb6, 0x17, 0x81, 0xe8, 0x2b, 0xc1, 0xd7, 0xde, - 0xfe, 0x27, 0x16, 0x2c, 0xbc, 0x08, 0x86, 0x61, 0xff, 0xd5, 0xaf, 0xb8, 0x44, 0x05, 0x73, 0x28, - 0xbd, 0xed, 0x1c, 0xca, 0x5f, 0x74, 0x0e, 0x4b, 0xb0, 0x68, 0x0e, 0x56, 0xcc, 0x82, 0xc2, 0x75, - 0xf6, 0xf5, 0x29, 0x95, 0xc3, 0x92, 0xd3, 0xf8, 0x0a, 0x74, 0xfa, 0x93, 0x28, 0xa2, 0x41, 0x6e, - 0x1e, 0x73, 0x02, 0xae, 0x26, 0xf2, 0x2e, 0x34, 0x03, 0x7a, 0x91, 0xa2, 0x09, 0xda, 0x0d, 0xe8, - 0x85, 0x44, 0xb1, 0xbb, 0xb0, 0x94, 0xed, 0x46, 0x0c, 0xe0, 0x4f, 0x2d, 0xa8, 0xbc, 0x48, 0x5e, - 0x87, 0x64, 0x05, 0x2a, 0xc9, 0xe5, 0x98, 0x73, 0x48, 0x7b, 0x95, 0x88, 0xa9, 0xad, 0x0d, 0x06, - 0x11, 0x8d, 0xe3, 0xa3, 0xcb, 0x31, 0x75, 0x9a, 0x1e, 0x2f, 0xb8, 0x0c, 0x8f, 0x74, 0x61, 0x56, - 0x94, 0xb1, 0xc3, 0xba, 0x23, 0x8b, 0xe4, 0x0e, 0x80, 0x37, 0x0a, 0x27, 0x41, 0xe2, 0xc6, 0x5e, - 0x82, 0x4b, 0x55, 0x76, 0x34, 0x08, 0xb9, 0x05, 0xf5, 0xf1, 0x2b, 0x37, 0xee, 0x47, 0xfe, 0x38, - 0x41, 0xb2, 0xa9, 0x3b, 0x29, 0x80, 0x7c, 0x15, 0x6a, 0xe1, 0x24, 0x19, 0x87, 0x7e, 0x90, 0x08, - 0x52, 0x99, 0x13, 0x63, 0xd9, 0x9f, 0x24, 0x07, 0x0c, 0xec, 0x28, 0x04, 0x72, 0x0f, 0x5a, 0xfd, - 0x30, 0x38, 0xf1, 0xa3, 0x11, 0x17, 0x06, 0xdd, 0x19, 0xec, 0xcd, 0x04, 0xda, 0xff, 0xaa, 0x04, - 0x8d, 0xa3, 0xc8, 0x0b, 0x62, 0xaf, 0xcf, 0x00, 0x6c, 0xe8, 0xc9, 0x6b, 0xf7, 0xcc, 0x8b, 0xcf, - 0x70, 0xb6, 0x75, 0x47, 0x16, 0xc9, 0x12, 0xcc, 0xf0, 0x81, 0xe2, 0x9c, 0xca, 0x8e, 0x28, 0x91, - 0x0f, 0x60, 0x3e, 0x98, 0x8c, 0x5c, 0xb3, 0xaf, 0x32, 0x52, 0x4b, 0xbe, 0x82, 0x2d, 0xc0, 0x31, - 0xdb, 0x6b, 0xde, 0x05, 0x9f, 0xa1, 0x06, 0x21, 0x36, 0x34, 0x45, 0x89, 0xfa, 0xa7, 0x67, 0x7c, - 0x9a, 0x55, 0xc7, 0x80, 0xb1, 0x36, 0x12, 0x7f, 0x44, 0xdd, 0x38, 0xf1, 0x46, 0x63, 0x31, 0x2d, - 0x0d, 0x82, 0xf5, 0x61, 0xe2, 0x0d, 0xdd, 0x13, 0x4a, 0xe3, 0xee, 0xac, 0xa8, 0x57, 0x10, 0xf2, - 0x1e, 0xb4, 0x07, 0x34, 0x4e, 0x5c, 0xb1, 0x29, 0x34, 0xee, 0xd6, 0x90, 0xf5, 0x33, 0x50, 0xd6, - 0x4e, 0xe4, 0x5d, 0xb8, 0x6c, 0x01, 0xe8, 0xeb, 0x6e, 0x9d, 0x8f, 0x35, 0x85, 0x30, 0xca, 0x79, - 0x46, 0x13, 0x6d, 0xf5, 0x62, 0x41, 0xa1, 0xf6, 0x2e, 0x10, 0x0d, 0xbc, 0x49, 0x13, 0xcf, 0x1f, - 0xc6, 0xe4, 0x23, 0x68, 0x26, 0x1a, 0x32, 0x8a, 0xc2, 0x86, 0x22, 0x27, 0xed, 0x03, 0xc7, 0xc0, - 0xb3, 0xcf, 0xa0, 0xf6, 0x94, 0xd2, 0x5d, 0x7f, 0xe4, 0x27, 0x64, 0x09, 0xaa, 0x27, 0xfe, 0x6b, - 0xca, 0x09, 0xbe, 0xbc, 0x7d, 0xcd, 0xe1, 0x45, 0xf2, 0x0e, 0x00, 0xfe, 0xe1, 0x8e, 0x14, 0x61, - 0x6d, 0x5f, 0x73, 0xea, 0x08, 0x7b, 0xce, 0x28, 0xab, 0x07, 0xb3, 0x63, 0x1a, 0xf5, 0xa9, 0xdc, - 0xbf, 0xed, 0x6b, 0x8e, 0x04, 0xac, 0xcf, 0x42, 0x75, 0xc8, 0x5a, 0xb7, 0xff, 0xa4, 0x0a, 0x8d, - 0x43, 0x1a, 0x28, 0x4e, 0x23, 0x50, 0x61, 0x6b, 0x22, 0xb8, 0x0b, 0xff, 0x26, 0x5f, 0x82, 0x06, - 0xae, 0x53, 0x9c, 0x44, 0x7e, 0x70, 0xca, 0x09, 0x7c, 0xbd, 0xd4, 0xb5, 0x1c, 0x60, 0xe0, 0x43, - 0x84, 0x92, 0x0e, 0x94, 0xbd, 0x91, 0x24, 0x70, 0xf6, 0x27, 0xb9, 0x01, 0x35, 0x6f, 0x94, 0xf0, - 0xe1, 0x35, 0x11, 0x3c, 0xeb, 0x8d, 0x12, 0x1c, 0xda, 0xbb, 0xd0, 0x1c, 0x7b, 0x97, 0x23, 0xc6, - 0xcf, 0x8a, 0x2a, 0x9a, 0x4e, 0x43, 0xc0, 0xb6, 0x19, 0x59, 0xac, 0xc2, 0x82, 0x8e, 0x22, 0x3b, - 0xaf, 0xaa, 0xce, 0xe7, 0x35, 0x6c, 0x31, 0x86, 0xf7, 0x61, 0x4e, 0x7e, 0x13, 0xf1, 0xf9, 0x20, - 0xad, 0xd4, 0x9d, 0xb6, 0x00, 0xcb, 0x59, 0xde, 0x87, 0xce, 0x89, 0x1f, 0x78, 0x43, 0xb7, 0x3f, - 0x4c, 0xce, 0xdd, 0x01, 0x1d, 0x26, 0x1e, 0x52, 0x4d, 0xd5, 0x69, 0x23, 0x7c, 0x63, 0x98, 0x9c, - 0x6f, 0x32, 0x28, 0xf9, 0x00, 0xea, 0x27, 0x94, 0xba, 0xb8, 0x58, 0xdd, 0x9a, 0xc1, 0x81, 0x72, - 0x87, 0x9c, 0xda, 0x89, 0xdc, 0xab, 0x0f, 0xa0, 0x13, 0x4e, 0x92, 0xd3, 0xd0, 0x0f, 0x4e, 0x5d, - 0x26, 0xf3, 0x5c, 0x7f, 0x80, 0x54, 0x54, 0x59, 0x2f, 0x3d, 0xb2, 0x9c, 0xb6, 0xac, 0x63, 0xd2, - 0x67, 0x67, 0x40, 0xde, 0x83, 0xb9, 0xa1, 0x17, 0x27, 0xee, 0x59, 0x38, 0x76, 0xc7, 0x93, 0xe3, - 0x57, 0xf4, 0xb2, 0xdb, 0xc2, 0x85, 0x68, 0x31, 0xf0, 0x76, 0x38, 0x3e, 0x40, 0x20, 0xb9, 0x0d, - 0x80, 0xe3, 0xe4, 0x83, 0x80, 0xbb, 0xd6, 0xfd, 0x96, 0x53, 0x67, 0x10, 0xde, 0xe9, 0xf7, 0x61, - 0x01, 0xb7, 0xa7, 0x3f, 0x89, 0x93, 0x70, 0xe4, 0x32, 0x79, 0x1d, 0x0d, 0xe2, 0x6e, 0x03, 0x69, - 0xed, 0x2b, 0x62, 0xb0, 0xda, 0x1e, 0xaf, 0x6c, 0xd2, 0x38, 0xd9, 0x40, 0x64, 0x87, 0xe3, 0xb2, - 0x43, 0xfd, 0xd2, 0x99, 0x1f, 0x64, 0xe1, 0xe4, 0x03, 0x20, 0xde, 0x70, 0x18, 0x5e, 0xb8, 0x31, - 0x1d, 0x9e, 0xb8, 0x62, 0x11, 0xbb, 0xed, 0xbb, 0xd6, 0xfd, 0x9a, 0xd3, 0xc1, 0x9a, 0x43, 0x3a, - 0x3c, 0x39, 0xe0, 0x70, 0xf2, 0x11, 0xb4, 0x70, 0x20, 0x27, 0xd4, 0x4b, 0x26, 0x11, 0x8d, 0xbb, - 0x73, 0x77, 0xcb, 0xf7, 0xdb, 0xab, 0xf3, 0x6a, 0xbd, 0x10, 0xbc, 0xee, 0x27, 0x4e, 0x93, 0xe1, - 0x89, 0x72, 0xdc, 0xdb, 0x84, 0xa5, 0xe2, 0x21, 0x31, 0xa2, 0x62, 0xab, 0xc2, 0x88, 0xb1, 0xe2, - 0xb0, 0x3f, 0xc9, 0x22, 0x54, 0xcf, 0xbd, 0xe1, 0x84, 0x0a, 0xb9, 0xce, 0x0b, 0x1f, 0x97, 0x1e, - 0x5b, 0xf6, 0x1f, 0x5b, 0xd0, 0xe4, 0xb3, 0x14, 0xfa, 0xc8, 0x3d, 0x68, 0x49, 0x6a, 0xa0, 0x51, - 0x14, 0x46, 0x42, 0xbc, 0x99, 0x40, 0xf2, 0x00, 0x3a, 0x12, 0x30, 0x8e, 0xa8, 0x3f, 0xf2, 0x4e, - 0x65, 0xdb, 0x39, 0x38, 0x59, 0x4d, 0x5b, 0x8c, 0xc2, 0x49, 0x42, 0xc5, 0xc9, 0xd7, 0x14, 0x13, - 0x74, 0x18, 0xcc, 0x31, 0x51, 0x98, 0x78, 0x2b, 0x20, 0x75, 0x03, 0x66, 0xff, 0x4d, 0x0b, 0x08, - 0x1b, 0xfa, 0x51, 0xc8, 0x9b, 0x10, 0x54, 0x9a, 0xe5, 0x12, 0xeb, 0xad, 0xb9, 0xa4, 0x74, 0x15, - 0x97, 0xd8, 0x50, 0xe5, 0xa3, 0xaf, 0x14, 0x8c, 0x9e, 0x57, 0x7d, 0x52, 0xa9, 0x95, 0x3b, 0x15, - 0xfb, 0x3f, 0x97, 0x61, 0x71, 0x83, 0x1f, 0xdd, 0x6b, 0xfd, 0x3e, 0x1d, 0x2b, 0xfe, 0x79, 0x07, - 0x1a, 0x41, 0x38, 0xa0, 0x92, 0x6a, 0xf9, 0xc0, 0x80, 0x81, 0x34, 0x92, 0x3d, 0xf3, 0xfc, 0x80, - 0x0f, 0x9c, 0xaf, 0x67, 0x1d, 0x21, 0x38, 0xec, 0xf7, 0x60, 0x6e, 0x4c, 0x83, 0x81, 0xce, 0x26, - 0x5c, 0xb9, 0x6a, 0x09, 0xb0, 0xe0, 0x90, 0x77, 0xa0, 0x71, 0x32, 0xe1, 0x78, 0x4c, 0xb8, 0x54, - 0x90, 0x0e, 0x40, 0x80, 0xd6, 0xb8, 0x8c, 0x19, 0x4f, 0xe2, 0x33, 0xac, 0xad, 0x62, 0xed, 0x2c, - 0x2b, 0xb3, 0xaa, 0xdb, 0x00, 0x83, 0x49, 0x9c, 0x08, 0xae, 0x99, 0xc1, 0xca, 0x3a, 0x83, 0x70, - 0xae, 0xf9, 0x1a, 0x2c, 0x8c, 0xbc, 0xd7, 0x2e, 0xd2, 0x8f, 0xeb, 0x07, 0xee, 0xc9, 0x10, 0x4f, - 0x9f, 0x59, 0xc4, 0xeb, 0x8c, 0xbc, 0xd7, 0xdf, 0x63, 0x35, 0x3b, 0xc1, 0x53, 0x84, 0x33, 0xd1, - 0x22, 0xd5, 0x9e, 0x88, 0xc6, 0x34, 0x3a, 0xa7, 0x28, 0x0d, 0x2a, 0x4a, 0xb7, 0x71, 0x38, 0x94, - 0x8d, 0x68, 0xc4, 0xe6, 0x9d, 0x0c, 0xfb, 0x9c, 0xf5, 0x9d, 0xd9, 0x91, 0x1f, 0x6c, 0x27, 0xc3, - 0x3e, 0xb9, 0x05, 0xc0, 0x64, 0xc9, 0x98, 0x46, 0xee, 0xab, 0x0b, 0xe4, 0xe3, 0x0a, 0xca, 0x8e, - 0x03, 0x1a, 0x7d, 0x7a, 0x41, 0x6e, 0x42, 0xbd, 0x1f, 0xa3, 0x30, 0xf2, 0x2e, 0xbb, 0x0d, 0x64, - 0xf2, 0x5a, 0x3f, 0x66, 0x62, 0xc8, 0xbb, 0x64, 0x8c, 0xc8, 0x46, 0xeb, 0xe1, 0x2e, 0xd0, 0x01, - 0x36, 0x1f, 0xa3, 0x54, 0x6d, 0xe1, 0x60, 0xd7, 0x44, 0x05, 0xeb, 0x27, 0x26, 0x5f, 0x82, 0x96, - 0x1c, 0xec, 0xc9, 0xd0, 0x3b, 0x8d, 0x51, 0xac, 0xb4, 0x9c, 0xa6, 0x00, 0x3e, 0x65, 0x30, 0xfb, - 0x25, 0x57, 0xb6, 0xb4, 0xbd, 0x15, 0x7c, 0xc3, 0x8e, 0x7d, 0x84, 0xe0, 0xbe, 0xd6, 0x1c, 0x51, - 0x2a, 0xda, 0xb4, 0x52, 0xc1, 0xa6, 0xd9, 0xbf, 0xb0, 0xa0, 0x29, 0x5a, 0x46, 0x0d, 0x85, 0x3c, - 0x02, 0x22, 0x77, 0x31, 0x79, 0xed, 0x0f, 0xdc, 0xe3, 0xcb, 0x84, 0xc6, 0x9c, 0x68, 0xb6, 0xaf, - 0x39, 0x05, 0x75, 0x4c, 0x8e, 0x1a, 0xd0, 0x38, 0x89, 0x38, 0x4d, 0x6f, 0x5f, 0x73, 0x72, 0x35, - 0x8c, 0xc5, 0x98, 0x0e, 0x34, 0x49, 0x5c, 0x3f, 0x18, 0xd0, 0xd7, 0x48, 0x4a, 0x2d, 0xc7, 0x80, - 0xad, 0xb7, 0xa1, 0xa9, 0x7f, 0x67, 0xff, 0x18, 0x6a, 0x52, 0x83, 0x42, 0xed, 0x21, 0x33, 0x2e, - 0x47, 0x83, 0x90, 0x1e, 0xd4, 0xcc, 0x51, 0x38, 0xb5, 0x2f, 0xd2, 0xb7, 0xfd, 0x6d, 0xe8, 0xec, - 0x32, 0x22, 0x0a, 0x18, 0xd1, 0x0a, 0xb5, 0x70, 0x09, 0x66, 0x34, 0xe6, 0xa9, 0x3b, 0xa2, 0xc4, - 0xce, 0xdf, 0xb3, 0x30, 0x4e, 0x44, 0x3f, 0xf8, 0xb7, 0xfd, 0x27, 0x16, 0x90, 0xad, 0x38, 0xf1, - 0x47, 0x5e, 0x42, 0x9f, 0x52, 0x25, 0x1e, 0xf6, 0xa1, 0xc9, 0x5a, 0x3b, 0x0a, 0xd7, 0xb8, 0x92, - 0xc6, 0x95, 0x8b, 0xaf, 0x0a, 0x76, 0xce, 0x7f, 0xb0, 0xa2, 0x63, 0x73, 0x91, 0x6f, 0x34, 0xc0, - 0xb8, 0x2d, 0xf1, 0xa2, 0x53, 0x9a, 0xa0, 0x06, 0x27, 0xf4, 0x7f, 0xe0, 0xa0, 0x8d, 0x30, 0x38, - 0xe9, 0xfd, 0x1e, 0xcc, 0xe7, 0xda, 0xd0, 0x65, 0x74, 0xbd, 0x40, 0x46, 0x97, 0x75, 0x19, 0xdd, - 0x87, 0x05, 0x63, 0x5c, 0x82, 0xe2, 0xba, 0x30, 0xcb, 0x18, 0x83, 0x29, 0x0a, 0x16, 0x57, 0x14, - 0x44, 0x91, 0xac, 0xc2, 0xe2, 0x09, 0xa5, 0x91, 0x97, 0x60, 0x11, 0x59, 0x87, 0xed, 0x89, 0x68, - 0xb9, 0xb0, 0xce, 0xfe, 0x33, 0x0b, 0xe6, 0x98, 0x34, 0x7d, 0xee, 0x05, 0x97, 0x72, 0xad, 0x76, - 0x0b, 0xd7, 0xea, 0xbe, 0x76, 0x38, 0x6a, 0xd8, 0x5f, 0x74, 0xa1, 0xca, 0xd9, 0x85, 0x22, 0x77, - 0xa1, 0x69, 0x0c, 0xb7, 0xca, 0x35, 0xd2, 0xd8, 0x4b, 0x0e, 0x68, 0xb4, 0x7e, 0x99, 0xd0, 0x5f, - 0x7f, 0x29, 0xdf, 0x83, 0x4e, 0x3a, 0x6c, 0xb1, 0x8e, 0x04, 0x2a, 0x8c, 0x30, 0x45, 0x03, 0xf8, - 0xb7, 0xfd, 0xf7, 0x2c, 0x8e, 0xb8, 0x11, 0xfa, 0x4a, 0x5b, 0x65, 0x88, 0x4c, 0xe9, 0x95, 0x88, - 0xec, 0xef, 0xa9, 0xda, 0xfe, 0xaf, 0x3f, 0x59, 0x26, 0x13, 0x63, 0x1a, 0x0c, 0x5c, 0x6f, 0x38, - 0x44, 0x41, 0x5c, 0x73, 0x66, 0x59, 0x79, 0x6d, 0x38, 0xb4, 0xdf, 0x87, 0x79, 0x6d, 0x74, 0x57, - 0xcc, 0x63, 0x0f, 0xc8, 0xae, 0x1f, 0x27, 0x2f, 0x82, 0x78, 0xac, 0x29, 0x72, 0x37, 0xa1, 0xce, - 0xa4, 0x2d, 0x1b, 0x19, 0xe7, 0xdc, 0xaa, 0xc3, 0xc4, 0x2f, 0x1b, 0x57, 0x8c, 0x95, 0xde, 0x6b, - 0x51, 0x59, 0x12, 0x95, 0xde, 0x6b, 0xac, 0xb4, 0x1f, 0xc3, 0x82, 0xd1, 0x9e, 0xe8, 0xfa, 0x5d, - 0xa8, 0x4e, 0x92, 0xd7, 0xa1, 0x54, 0xd5, 0x1b, 0x82, 0x42, 0x98, 0x51, 0xe8, 0xf0, 0x1a, 0xfb, - 0x09, 0xcc, 0xef, 0xd1, 0x0b, 0xc1, 0xc8, 0x72, 0x20, 0xef, 0xbd, 0xd1, 0x60, 0xc4, 0x7a, 0x7b, - 0x05, 0x88, 0xfe, 0x71, 0xca, 0x00, 0xd2, 0x7c, 0xb4, 0x0c, 0xf3, 0xd1, 0x7e, 0x0f, 0xc8, 0xa1, - 0x7f, 0x1a, 0x3c, 0xa7, 0x71, 0xec, 0x9d, 0x2a, 0xd6, 0xef, 0x40, 0x79, 0x14, 0x9f, 0x0a, 0x51, - 0xc5, 0xfe, 0xb4, 0xbf, 0x0e, 0x0b, 0x06, 0x9e, 0x68, 0xf8, 0x16, 0xd4, 0x63, 0xff, 0x34, 0x40, - 0x45, 0x4b, 0x34, 0x9d, 0x02, 0xec, 0xa7, 0xb0, 0xf8, 0x3d, 0x1a, 0xf9, 0x27, 0x97, 0x6f, 0x6a, - 0xde, 0x6c, 0xa7, 0x94, 0x6d, 0x67, 0x0b, 0xae, 0x67, 0xda, 0x11, 0xdd, 0x73, 0xf2, 0x15, 0x3b, - 0x59, 0x73, 0x78, 0x41, 0x93, 0x7d, 0x25, 0x5d, 0xf6, 0xd9, 0x2f, 0x80, 0x6c, 0x84, 0x41, 0x40, - 0xfb, 0xc9, 0x01, 0xa5, 0x51, 0xea, 0xb9, 0x4a, 0x69, 0xb5, 0xb1, 0xba, 0x2c, 0x56, 0x36, 0x2b, - 0x50, 0x05, 0x11, 0x13, 0xa8, 0x8c, 0x69, 0x34, 0xc2, 0x86, 0x6b, 0x0e, 0xfe, 0x6d, 0x5f, 0x87, - 0x05, 0xa3, 0x59, 0x61, 0xeb, 0x7f, 0x08, 0xd7, 0x37, 0xfd, 0xb8, 0x9f, 0xef, 0xb0, 0x0b, 0xb3, - 0xe3, 0xc9, 0xb1, 0x9b, 0x72, 0xa2, 0x2c, 0x32, 0xf3, 0x2f, 0xfb, 0x89, 0x68, 0xec, 0xaf, 0x5a, - 0x50, 0xd9, 0x3e, 0xda, 0xdd, 0x60, 0x67, 0x85, 0x1f, 0xf4, 0xc3, 0x11, 0xd3, 0xc2, 0xf8, 0xa4, - 0x55, 0x79, 0x2a, 0x87, 0xdd, 0x82, 0x3a, 0x2a, 0x6f, 0xcc, 0xe2, 0x15, 0x7a, 0x50, 0x0a, 0x60, - 0xd6, 0x36, 0x7d, 0x3d, 0xf6, 0x23, 0x34, 0xa7, 0xa5, 0x91, 0x5c, 0xc1, 0x63, 0x26, 0x5f, 0x61, - 0xff, 0xdb, 0x59, 0x98, 0x15, 0x87, 0x2f, 0x3f, 0xc8, 0x13, 0xff, 0x9c, 0xa6, 0x07, 0x39, 0x2b, - 0x31, 0xc5, 0x38, 0xa2, 0xa3, 0x30, 0x51, 0xfa, 0x1b, 0xdf, 0x06, 0x13, 0x88, 0xde, 0x04, 0xa1, - 0x44, 0x70, 0xff, 0x43, 0x99, 0x63, 0x19, 0x40, 0x72, 0x0b, 0x66, 0xa5, 0x32, 0x50, 0x51, 0x86, - 0x8e, 0x04, 0xb1, 0xd5, 0xe8, 0x7b, 0x63, 0xaf, 0xef, 0x27, 0x97, 0x42, 0x2c, 0xa8, 0x32, 0x6b, - 0x7f, 0x18, 0xf6, 0xbd, 0xa1, 0x7b, 0xec, 0x0d, 0xbd, 0xa0, 0x4f, 0xa5, 0xb7, 0xc2, 0x00, 0x32, - 0xcb, 0x5d, 0x0c, 0x4b, 0xa2, 0x71, 0xeb, 0x3e, 0x03, 0x65, 0x67, 0x78, 0x3f, 0x1c, 0x8d, 0x7c, - 0x66, 0x7d, 0x70, 0xd5, 0xac, 0xec, 0x68, 0x10, 0xee, 0x1b, 0xc1, 0xd2, 0x05, 0x5f, 0xc1, 0xba, - 0xf4, 0x8d, 0x68, 0x40, 0xd6, 0x4a, 0x46, 0x43, 0x2b, 0x3b, 0x1a, 0x84, 0xed, 0xc5, 0x24, 0x88, - 0x69, 0x92, 0x0c, 0xe9, 0x40, 0x0d, 0xa8, 0x81, 0x68, 0xf9, 0x0a, 0xf2, 0x08, 0x16, 0xb8, 0x0f, - 0x22, 0xf6, 0x92, 0x30, 0x3e, 0xf3, 0x63, 0x37, 0x66, 0xe6, 0x13, 0xb7, 0x85, 0x8b, 0xaa, 0xc8, - 0x63, 0x58, 0xce, 0x80, 0x23, 0xda, 0xa7, 0xfe, 0x39, 0x1d, 0xa0, 0x0a, 0x57, 0x76, 0xa6, 0x55, - 0x93, 0xbb, 0xd0, 0x08, 0x26, 0x23, 0x77, 0x32, 0x1e, 0x78, 0x4c, 0x89, 0x69, 0xa3, 0x72, 0xa9, - 0x83, 0xc8, 0x87, 0x20, 0xf5, 0x34, 0xa1, 0x3d, 0xce, 0x19, 0x12, 0x8e, 0x51, 0xaf, 0x63, 0x62, - 0x30, 0xc2, 0x4c, 0x55, 0xd2, 0x8e, 0xb0, 0x3b, 0x25, 0x00, 0xf9, 0x24, 0xf2, 0xcf, 0xbd, 0x84, - 0x76, 0xe7, 0xb9, 0x50, 0x17, 0x45, 0xf6, 0x9d, 0x1f, 0xf8, 0x89, 0xef, 0x25, 0x61, 0xd4, 0x25, - 0x58, 0x97, 0x02, 0xd8, 0x22, 0x22, 0x7d, 0xc4, 0x89, 0x97, 0x4c, 0x62, 0xa1, 0xa1, 0x2e, 0x20, - 0x71, 0xe5, 0x2b, 0xc8, 0x47, 0xb0, 0xc4, 0x29, 0x02, 0xab, 0x84, 0xee, 0x8d, 0xaa, 0xc2, 0x22, - 0xae, 0xc8, 0x94, 0x5a, 0xb6, 0x94, 0x82, 0x44, 0x72, 0x1f, 0x5e, 0xe7, 0x4b, 0x39, 0xa5, 0x9a, - 0x8d, 0x8f, 0x8d, 0xc0, 0xef, 0xbb, 0x02, 0x83, 0xb1, 0xc8, 0x12, 0xce, 0x22, 0x5f, 0xc1, 0x48, - 0x7c, 0xe8, 0x9f, 0xd0, 0xc4, 0x1f, 0xd1, 0xee, 0x32, 0x27, 0x71, 0x59, 0x66, 0x0c, 0x38, 0x19, - 0x63, 0x4d, 0x97, 0x33, 0x3c, 0x2f, 0x21, 0x31, 0x0e, 0xc3, 0x98, 0x4a, 0xcf, 0x53, 0xf7, 0x86, - 0x60, 0x2d, 0x1d, 0x68, 0xff, 0xa1, 0xc5, 0x8f, 0x28, 0xc1, 0xce, 0xb1, 0x66, 0x7c, 0x71, 0x46, - 0x76, 0xc3, 0x60, 0x78, 0x29, 0x78, 0x1b, 0x38, 0x68, 0x3f, 0x18, 0x5e, 0x32, 0xf5, 0xdf, 0x0f, - 0x74, 0x14, 0x2e, 0x0d, 0x9b, 0x12, 0x88, 0x48, 0xef, 0x40, 0x63, 0x3c, 0x39, 0x1e, 0xfa, 0x7d, - 0x8e, 0x52, 0xe6, 0xad, 0x70, 0x10, 0x22, 0x30, 0xeb, 0x93, 0xef, 0x27, 0xc7, 0xa8, 0x20, 0x46, - 0x43, 0xc0, 0x18, 0x8a, 0xbd, 0x0e, 0x8b, 0xe6, 0x00, 0x85, 0xd8, 0x7f, 0x00, 0x35, 0x21, 0x25, - 0xa4, 0x1b, 0xa2, 0xad, 0x39, 0x87, 0x99, 0xb1, 0xa4, 0xea, 0xed, 0x9f, 0xcf, 0xc0, 0x82, 0x80, - 0x6e, 0xb0, 0xe9, 0x1f, 0x4e, 0x46, 0x23, 0x2f, 0x2a, 0x10, 0x3f, 0xd6, 0x1b, 0xc4, 0x4f, 0x29, - 0x2f, 0x7e, 0xee, 0x18, 0x56, 0x28, 0x97, 0x5f, 0x1a, 0x84, 0xdc, 0x87, 0x39, 0xb6, 0xe4, 0xdc, - 0x28, 0xd0, 0xfd, 0x93, 0x59, 0x70, 0x5e, 0x64, 0x56, 0x8b, 0x44, 0xa6, 0x2e, 0xee, 0x66, 0x32, - 0xe2, 0xce, 0x86, 0x26, 0xdf, 0x5e, 0x21, 0xc1, 0x67, 0x85, 0x49, 0xa6, 0xc1, 0xd8, 0x78, 0xb2, - 0xc2, 0x85, 0x4b, 0xb2, 0xb9, 0x22, 0xd1, 0xe2, 0x8f, 0x28, 0x9e, 0x10, 0x1a, 0x76, 0x5d, 0x88, - 0x96, 0x7c, 0x15, 0x79, 0x0a, 0xc0, 0xfb, 0x42, 0x35, 0x05, 0x50, 0x4d, 0x79, 0xcf, 0xdc, 0x15, - 0x7d, 0xfd, 0x57, 0x58, 0x61, 0x12, 0x51, 0x54, 0x5d, 0xb4, 0x2f, 0xc9, 0x2e, 0xb4, 0xc3, 0x31, - 0x0d, 0xdc, 0x94, 0xc1, 0x1b, 0xd8, 0xd6, 0xbd, 0x2b, 0xda, 0xda, 0x91, 0xb8, 0x4e, 0xe6, 0x5b, - 0xb2, 0xc7, 0x77, 0x80, 0x6a, 0xcd, 0x35, 0xbf, 0x40, 0x73, 0xd9, 0x8f, 0xed, 0xbf, 0x6e, 0x41, - 0x43, 0x1b, 0x39, 0xb9, 0x0e, 0xf3, 0x1b, 0xfb, 0xfb, 0x07, 0x5b, 0xce, 0xda, 0xd1, 0xce, 0xf7, - 0xb6, 0xdc, 0x8d, 0xdd, 0xfd, 0xc3, 0xad, 0xce, 0x35, 0x06, 0xde, 0xdd, 0xdf, 0x58, 0xdb, 0x75, - 0x9f, 0xee, 0x3b, 0x1b, 0x12, 0x6c, 0x91, 0x25, 0x20, 0xce, 0xd6, 0xf3, 0xfd, 0xa3, 0x2d, 0x03, - 0x5e, 0x22, 0x1d, 0x68, 0xae, 0x3b, 0x5b, 0x6b, 0x1b, 0xdb, 0x02, 0x52, 0x26, 0x8b, 0xd0, 0x79, - 0xfa, 0x62, 0x6f, 0x73, 0x67, 0xef, 0x99, 0xbb, 0xb1, 0xb6, 0xb7, 0xb1, 0xb5, 0xbb, 0xb5, 0xd9, - 0xa9, 0x90, 0x16, 0xd4, 0xd7, 0xd6, 0xd7, 0xf6, 0x36, 0xf7, 0xf7, 0xb6, 0x36, 0x3b, 0x55, 0xfb, - 0x5b, 0x50, 0x57, 0x43, 0x25, 0x0d, 0x98, 0x7d, 0xb1, 0xf7, 0xe9, 0xde, 0xfe, 0xcb, 0xbd, 0xce, - 0x35, 0x52, 0x87, 0x2a, 0xf6, 0xdf, 0xb1, 0x08, 0xc0, 0x0c, 0xef, 0xb3, 0x53, 0x22, 0x35, 0xa8, - 0xac, 0xef, 0x1f, 0x6d, 0x77, 0xca, 0xf6, 0x7f, 0xb5, 0xe0, 0x3a, 0xce, 0x79, 0x90, 0xe5, 0xfe, - 0xbb, 0xd0, 0xe8, 0x87, 0xe1, 0x98, 0xd9, 0x3d, 0xe9, 0xc9, 0xae, 0x83, 0x18, 0x67, 0x73, 0x99, - 0x78, 0x12, 0x46, 0x7d, 0x2a, 0x98, 0x1f, 0x10, 0xf4, 0x94, 0x41, 0x18, 0x67, 0x0b, 0xba, 0xe5, - 0x18, 0x9c, 0xf7, 0x1b, 0x1c, 0xc6, 0x51, 0x96, 0x60, 0xe6, 0x38, 0xa2, 0x5e, 0xff, 0x4c, 0xb0, - 0xbd, 0x28, 0x91, 0xaf, 0xa4, 0x86, 0x79, 0x9f, 0x91, 0xd5, 0x90, 0x0e, 0x90, 0x15, 0x6a, 0xce, - 0x9c, 0x80, 0x6f, 0x08, 0x30, 0x3b, 0x04, 0xbc, 0x63, 0x2f, 0x18, 0x84, 0x01, 0x1d, 0x08, 0xad, - 0x3f, 0x05, 0xd8, 0x07, 0xb0, 0x94, 0x9d, 0x9f, 0x10, 0x1e, 0x1f, 0x69, 0xc2, 0x83, 0x2b, 0xe1, - 0xbd, 0xe9, 0xb4, 0xa0, 0x09, 0x92, 0x3f, 0x2b, 0x43, 0x85, 0xe9, 0x64, 0xd3, 0xf5, 0x37, 0x5d, - 0xcd, 0x2e, 0xe7, 0xa2, 0x34, 0x68, 0xeb, 0xf3, 0x13, 0x5a, 0xf8, 0x99, 0x52, 0x48, 0x5a, 0x1f, - 0xd1, 0xfe, 0xb9, 0xf0, 0x34, 0x69, 0x10, 0xc6, 0xf9, 0xcc, 0x06, 0xc2, 0xaf, 0x05, 0xe7, 0xcb, - 0xb2, 0xac, 0xc3, 0x2f, 0x67, 0xd3, 0x3a, 0xfc, 0xae, 0x0b, 0xb3, 0x7e, 0x70, 0x1c, 0x4e, 0x82, - 0x01, 0x72, 0x7a, 0xcd, 0x91, 0x45, 0x8c, 0x0b, 0xa1, 0x04, 0x62, 0xc7, 0x07, 0xe7, 0xeb, 0x14, - 0x40, 0x56, 0xa1, 0x1e, 0x5f, 0x06, 0x7d, 0x9d, 0x99, 0x17, 0xc5, 0x2a, 0xb1, 0x35, 0x58, 0x39, - 0xbc, 0x0c, 0xfa, 0xc8, 0xba, 0x29, 0x1a, 0xf9, 0x26, 0xd4, 0x94, 0x67, 0x96, 0x4b, 0xe5, 0x1b, - 0xfa, 0x27, 0xd2, 0x1d, 0xcb, 0x0d, 0x5e, 0x85, 0xda, 0xfb, 0x14, 0x5a, 0x46, 0x95, 0x6e, 0xa5, - 0xb6, 0xb8, 0x95, 0x7a, 0x4f, 0xb7, 0x52, 0x53, 0x61, 0x2f, 0x3e, 0xd3, 0xad, 0xd6, 0xdf, 0x83, - 0x9a, 0x1c, 0x1a, 0xe3, 0x2a, 0xc1, 0x11, 0xee, 0xe1, 0xf7, 0xf7, 0x36, 0x3a, 0xd7, 0xc8, 0x1c, - 0x34, 0xd6, 0x36, 0x90, 0x51, 0x11, 0x60, 0x31, 0x94, 0x83, 0xb5, 0xc3, 0x43, 0x05, 0x29, 0xd9, - 0x04, 0x3a, 0xec, 0xc8, 0x61, 0x23, 0x56, 0xb1, 0x97, 0x8f, 0x60, 0x5e, 0x83, 0xa5, 0x86, 0xdc, - 0x98, 0x01, 0x32, 0x86, 0x1c, 0x6a, 0xed, 0xbc, 0xc6, 0x5e, 0x86, 0xeb, 0xac, 0xb8, 0x75, 0x4e, - 0x83, 0xe4, 0x70, 0x72, 0xcc, 0x43, 0x6e, 0x7e, 0x18, 0xd8, 0x7f, 0xc5, 0x82, 0xba, 0xaa, 0xb9, - 0x82, 0x9e, 0x64, 0x94, 0xb0, 0x84, 0x1b, 0xd0, 0xd3, 0xba, 0xc0, 0x2f, 0x57, 0xf0, 0x5f, 0xc3, - 0xf8, 0xab, 0x2b, 0x10, 0x9b, 0xec, 0xc1, 0xd6, 0x96, 0xe3, 0xee, 0xef, 0xed, 0xee, 0xec, 0x31, - 0xa1, 0xc4, 0x26, 0x8b, 0x80, 0xa7, 0x4f, 0x11, 0x62, 0xd9, 0x1d, 0x68, 0x3f, 0xa3, 0xc9, 0x4e, - 0x70, 0x12, 0xca, 0xa9, 0xfe, 0x9f, 0x2a, 0xcc, 0x29, 0x50, 0x6a, 0x3c, 0x9e, 0xd3, 0x28, 0xf6, - 0xc3, 0x00, 0xd5, 0xbe, 0xba, 0x23, 0x8b, 0xec, 0x3c, 0xf1, 0x07, 0x34, 0x48, 0xfc, 0xe4, 0xd2, - 0x35, 0xbc, 0x4d, 0x59, 0x30, 0x33, 0xd4, 0xbc, 0xa1, 0xef, 0xc9, 0xe8, 0x25, 0x2f, 0x30, 0x68, - 0x3f, 0x1c, 0x86, 0x11, 0xea, 0x77, 0x75, 0x87, 0x17, 0xc8, 0x2a, 0x2c, 0x32, 0xbd, 0x52, 0xf7, - 0x05, 0x22, 0xb3, 0x72, 0xd7, 0x57, 0x61, 0x1d, 0x3b, 0xaf, 0x18, 0x5c, 0x28, 0x25, 0xea, 0x13, - 0x6e, 0xc6, 0x14, 0x55, 0x91, 0x6f, 0xc0, 0x75, 0x06, 0x56, 0x8a, 0x8c, 0xfa, 0x66, 0x0e, 0xbf, - 0x29, 0xae, 0x64, 0x5c, 0xc3, 0xfb, 0x67, 0x3b, 0x5f, 0xe5, 0x1a, 0xab, 0x02, 0xe4, 0x42, 0x8d, - 0x33, 0xfc, 0x0c, 0xce, 0x86, 0x1a, 0xb5, 0x70, 0x65, 0x2d, 0x17, 0xae, 0xfc, 0x06, 0x5c, 0x3f, - 0xa6, 0x71, 0xe2, 0x9e, 0x51, 0x6f, 0x40, 0x23, 0xe4, 0x46, 0x1e, 0x95, 0xe4, 0x0a, 0x7a, 0x71, - 0x25, 0x9e, 0xec, 0x97, 0x41, 0x9f, 0x0e, 0xdc, 0x24, 0x74, 0x51, 0x03, 0x41, 0x9e, 0xae, 0x39, - 0x59, 0xb0, 0x89, 0x79, 0x1a, 0x79, 0xe3, 0x33, 0xa1, 0x41, 0x67, 0xc1, 0x4c, 0xf7, 0x49, 0x68, - 0x9c, 0x04, 0x94, 0xc7, 0x84, 0x6a, 0xe8, 0xef, 0x97, 0x20, 0x72, 0x0f, 0x66, 0xb0, 0xc1, 0xb8, - 0xdb, 0x41, 0x06, 0x68, 0xa6, 0x42, 0xd4, 0x0f, 0x1c, 0x51, 0xc7, 0xec, 0xe5, 0x49, 0xe4, 0xc7, - 0xdd, 0x26, 0x86, 0x43, 0xf1, 0x6f, 0xf2, 0x1d, 0x4d, 0x4e, 0x2c, 0xe0, 0xb7, 0xf2, 0x30, 0xce, - 0x50, 0xde, 0x6f, 0x45, 0x64, 0x7c, 0x52, 0xa9, 0x35, 0x3a, 0x4d, 0xfb, 0x77, 0xa0, 0x8a, 0x23, - 0x47, 0x9a, 0xc4, 0xf5, 0xb3, 0x04, 0x4d, 0x22, 0xb4, 0x0b, 0xb3, 0x01, 0x4d, 0x2e, 0xc2, 0xe8, - 0x95, 0x8c, 0xbf, 0x8b, 0xa2, 0xfd, 0x13, 0x74, 0x2a, 0xa8, 0x78, 0xf4, 0x0b, 0xb4, 0x86, 0xc8, - 0x4d, 0xa8, 0xf3, 0x3d, 0x8d, 0xcf, 0x3c, 0xe1, 0xe7, 0xa8, 0x21, 0xe0, 0xf0, 0xcc, 0x63, 0xe7, - 0xa3, 0x41, 0x26, 0xdc, 0x75, 0xd4, 0x40, 0xd8, 0x36, 0xa7, 0x92, 0x7b, 0xd0, 0x96, 0x91, 0xee, - 0xd8, 0x1d, 0xd2, 0x93, 0x44, 0x3a, 0x7e, 0x83, 0xc9, 0x08, 0xfd, 0x4b, 0xbb, 0xf4, 0x24, 0xb1, - 0xf7, 0x60, 0x5e, 0x9c, 0x59, 0xfb, 0x63, 0x2a, 0xbb, 0xfe, 0x56, 0x91, 0x62, 0xdb, 0x58, 0x5d, - 0x30, 0x0f, 0x39, 0x1e, 0xdb, 0x37, 0x31, 0x6d, 0x07, 0x88, 0x7e, 0x06, 0x8a, 0x06, 0x85, 0x66, - 0x29, 0x5d, 0xdb, 0x62, 0x3a, 0x06, 0x8c, 0xad, 0x4f, 0x3c, 0xe9, 0xf7, 0xe5, 0xfd, 0x84, 0x9a, - 0x23, 0x8b, 0xf6, 0x7f, 0xb4, 0x60, 0x01, 0x5b, 0x93, 0xaa, 0xb9, 0xd0, 0x33, 0x1e, 0x7f, 0x81, - 0x61, 0xca, 0xc0, 0x02, 0x77, 0xa7, 0x2f, 0x42, 0x55, 0xd7, 0x3c, 0x78, 0xe1, 0x8b, 0xbb, 0x11, - 0x2b, 0x39, 0x37, 0xe2, 0x03, 0xe8, 0x0c, 0xe8, 0xd0, 0xc7, 0x3b, 0x2a, 0xf2, 0x1c, 0xe7, 0x7a, - 0x78, 0x0e, 0x6e, 0xff, 0x2d, 0x0b, 0xe6, 0xb9, 0xa2, 0x80, 0xc6, 0xa4, 0x58, 0xaa, 0xff, 0x4f, - 0x1a, 0x5e, 0x42, 0x40, 0x89, 0x49, 0xa5, 0x47, 0x27, 0x42, 0x39, 0xf2, 0xf6, 0x35, 0xc7, 0x44, - 0x26, 0x4f, 0xd0, 0x9c, 0x08, 0x5c, 0x84, 0x16, 0xdc, 0x7a, 0x31, 0xf7, 0x65, 0xfb, 0x9a, 0xa3, - 0xa1, 0xaf, 0xd7, 0x98, 0x2d, 0xc8, 0xe0, 0xf6, 0x33, 0x68, 0x19, 0x1d, 0x19, 0xee, 0xce, 0x26, - 0x77, 0x77, 0xe6, 0xe2, 0x0a, 0xa5, 0x82, 0xb8, 0xc2, 0xcf, 0x2b, 0x40, 0x18, 0x61, 0x65, 0x76, - 0xee, 0xae, 0x19, 0x9c, 0x93, 0x17, 0x60, 0x52, 0x10, 0x59, 0x05, 0xa2, 0x15, 0x65, 0xd0, 0xb0, - 0xac, 0x82, 0x86, 0x05, 0xb5, 0x4c, 0xea, 0x0b, 0xad, 0x52, 0x05, 0xe4, 0xd0, 0x95, 0xc5, 0xb7, - 0xa9, 0xb0, 0x8e, 0x69, 0x3e, 0x18, 0x9d, 0x63, 0x46, 0xb7, 0x70, 0xff, 0xc8, 0x72, 0x96, 0x1e, - 0x66, 0xde, 0x48, 0x0f, 0xb3, 0x39, 0x7a, 0xd0, 0x1c, 0x10, 0x35, 0xd3, 0x01, 0x71, 0x0f, 0x5a, - 0x32, 0x08, 0xc7, 0xef, 0x1f, 0x08, 0x6f, 0x8f, 0x01, 0x64, 0xf4, 0x24, 0x7d, 0x00, 0xca, 0xcb, - 0xc1, 0xa3, 0xeb, 0x39, 0x38, 0x3b, 0x58, 0x52, 0x47, 0x73, 0x03, 0x07, 0x9b, 0x02, 0xd0, 0x65, - 0xc0, 0xa8, 0xc4, 0x9d, 0x04, 0xe2, 0xf2, 0x0b, 0x1d, 0xa0, 0x21, 0x53, 0x73, 0xf2, 0x15, 0x79, - 0xf3, 0xbf, 0x55, 0x60, 0xfe, 0x93, 0x8f, 0xd2, 0x88, 0x55, 0x7c, 0xe6, 0x8f, 0xf0, 0x6c, 0x4f, - 0xef, 0x8e, 0x3c, 0xe5, 0x55, 0x87, 0x67, 0xfe, 0xc8, 0x31, 0xf0, 0xec, 0x5f, 0x5a, 0xd0, 0x61, - 0x54, 0x61, 0x10, 0xfe, 0xc7, 0x80, 0x3c, 0xfa, 0x96, 0x74, 0x6f, 0xe0, 0x92, 0xc7, 0x50, 0xc7, - 0x32, 0x33, 0xdd, 0x04, 0xd5, 0x77, 0x4d, 0xaa, 0x4f, 0xa5, 0xdb, 0xf6, 0x35, 0x27, 0x45, 0x66, - 0x67, 0x59, 0x36, 0x62, 0xc8, 0xc3, 0xdf, 0x59, 0xb0, 0xc6, 0x1d, 0xdb, 0x00, 0x9f, 0xd2, 0xcb, - 0xdd, 0xb0, 0x8f, 0x56, 0xd3, 0x6d, 0x00, 0x46, 0x83, 0x27, 0xde, 0xc8, 0x17, 0xae, 0x8e, 0xaa, - 0x53, 0x7f, 0x45, 0x2f, 0x9f, 0x22, 0x80, 0x89, 0x71, 0x56, 0x9d, 0xb2, 0x48, 0xd5, 0xa9, 0xbd, - 0xa2, 0x97, 0x3b, 0xc8, 0x1e, 0x2e, 0xb4, 0x3e, 0xa5, 0x97, 0x9b, 0x94, 0xeb, 0x75, 0x61, 0x44, - 0x6c, 0x68, 0x45, 0xde, 0x05, 0xd3, 0xdc, 0x8c, 0x50, 0x5f, 0x23, 0xf2, 0x2e, 0x3e, 0xa5, 0x97, - 0xeb, 0x18, 0xeb, 0x7b, 0x00, 0xb3, 0xac, 0x7e, 0x18, 0xf6, 0xc5, 0xc9, 0x24, 0x6f, 0x2f, 0xa4, - 0x83, 0x72, 0x66, 0x5e, 0xe1, 0xdf, 0xf6, 0xbf, 0xb7, 0xa0, 0xc5, 0x56, 0x00, 0xc5, 0x1e, 0xdb, - 0x09, 0x79, 0x09, 0xc6, 0x4a, 0x2f, 0xc1, 0xac, 0x0a, 0x99, 0xc1, 0x65, 0x68, 0x69, 0xba, 0x0c, - 0xc5, 0x65, 0xe3, 0x02, 0xf4, 0x43, 0xa8, 0x73, 0x76, 0x62, 0xec, 0x5b, 0x36, 0x76, 0xca, 0x98, - 0x90, 0x53, 0x43, 0xb4, 0x4f, 0x79, 0xbc, 0x5d, 0x73, 0x56, 0xf1, 0x45, 0xae, 0x73, 0x08, 0xab, - 0x2e, 0x08, 0xdd, 0x56, 0x8b, 0x42, 0xb7, 0x2f, 0xa0, 0xa1, 0x11, 0x16, 0xf9, 0x36, 0x0f, 0x7a, - 0xf3, 0xc1, 0x73, 0x2a, 0x34, 0x09, 0xc7, 0x98, 0x3d, 0x0a, 0x4c, 0x1d, 0xb0, 0x3e, 0x03, 0x15, - 0x24, 0xc9, 0x27, 0x30, 0xaf, 0x35, 0xcb, 0x2d, 0xc4, 0xa2, 0x31, 0x59, 0x45, 0x63, 0xfa, 0xdb, - 0x16, 0x2c, 0x8a, 0xaf, 0xf1, 0xc2, 0x94, 0xcf, 0x8e, 0xf1, 0xe7, 0xf1, 0x29, 0x3b, 0x48, 0x59, - 0xeb, 0x6e, 0x44, 0x4f, 0xfd, 0x38, 0xa1, 0x32, 0x42, 0x50, 0xc0, 0x21, 0x8c, 0xa4, 0x19, 0xaa, - 0x23, 0x30, 0xc9, 0x13, 0x68, 0xe0, 0xa7, 0xdc, 0x86, 0x15, 0xdb, 0xd2, 0xcd, 0x7f, 0xc8, 0x87, - 0xca, 0x24, 0x79, 0xac, 0x4a, 0xeb, 0x75, 0x98, 0x4d, 0x22, 0xff, 0xf4, 0x94, 0x46, 0xf6, 0x92, - 0x1a, 0x1a, 0xe3, 0x36, 0x7a, 0x98, 0xd0, 0x31, 0x53, 0x8e, 0x18, 0x65, 0x34, 0x04, 0x53, 0xfd, - 0xca, 0x51, 0x81, 0x9e, 0x76, 0xf5, 0x8f, 0x5b, 0xab, 0xe9, 0x4d, 0xbf, 0xfb, 0x30, 0x37, 0x62, - 0x8a, 0x12, 0xd3, 0xe0, 0x8d, 0x88, 0x40, 0x16, 0xcc, 0x14, 0x6f, 0xd4, 0x5b, 0x62, 0x37, 0xf1, - 0x87, 0xae, 0xac, 0x15, 0x97, 0xec, 0x8a, 0xaa, 0xd8, 0xf1, 0x1d, 0x27, 0xde, 0x29, 0x15, 0xda, - 0x31, 0x2f, 0xd8, 0x5d, 0x58, 0x3a, 0x48, 0xb7, 0x45, 0x73, 0x48, 0xd8, 0xff, 0xac, 0x05, 0xcb, - 0xb9, 0x2a, 0x75, 0x25, 0x58, 0xb8, 0xb9, 0x87, 0xfe, 0xe8, 0x38, 0x54, 0x6e, 0x2a, 0x4b, 0xf7, - 0x80, 0x1b, 0x55, 0xe4, 0x14, 0xae, 0x4b, 0xaa, 0x40, 0x57, 0x91, 0x52, 0xfb, 0x4b, 0xa8, 0x89, - 0x7e, 0x68, 0x4a, 0xac, 0x6c, 0x87, 0x12, 0xae, 0x9f, 0x8a, 0xc5, 0xed, 0x91, 0x33, 0xe8, 0x2a, - 0xf2, 0x13, 0x9a, 0x92, 0x66, 0xc9, 0xb0, 0xbe, 0x3e, 0x78, 0x43, 0x5f, 0x86, 0xff, 0xc2, 0x99, - 0xda, 0x1a, 0xb9, 0x84, 0x3b, 0xb2, 0x0e, 0x55, 0xa1, 0x7c, 0x7f, 0x95, 0xb7, 0x9a, 0x1b, 0x7a, - 0x66, 0xcc, 0x4e, 0xdf, 0xd0, 0x30, 0xf9, 0x31, 0x2c, 0x5d, 0x78, 0x7e, 0x22, 0x87, 0xa5, 0x59, - 0x51, 0x55, 0xec, 0x72, 0xf5, 0x0d, 0x5d, 0xbe, 0xe4, 0x1f, 0x1b, 0xfa, 0xe1, 0x94, 0x16, 0x7b, - 0xbf, 0x2c, 0x41, 0xdb, 0x6c, 0x87, 0x91, 0xa9, 0x90, 0x4a, 0x52, 0xa1, 0x90, 0xf6, 0x67, 0x06, - 0x9c, 0xf7, 0xf6, 0x96, 0x8a, 0xbc, 0xbd, 0xba, 0x7f, 0xb5, 0xfc, 0xa6, 0x70, 0x52, 0xe5, 0xed, - 0xc2, 0x49, 0xd5, 0xc2, 0x70, 0xd2, 0xf4, 0xa8, 0xc3, 0xcc, 0xaf, 0x1a, 0x75, 0x98, 0xbd, 0x32, - 0xea, 0xd0, 0xfb, 0xdf, 0x16, 0x90, 0x3c, 0xf5, 0x92, 0x67, 0xdc, 0xc1, 0x1d, 0xd0, 0xa1, 0x10, - 0x6f, 0x5f, 0x7b, 0x3b, 0x0e, 0x90, 0xbb, 0x25, 0xbf, 0x66, 0xac, 0xa8, 0xdf, 0xcb, 0xd5, 0x6d, - 0x9b, 0x96, 0x53, 0x54, 0x95, 0x09, 0xa9, 0x55, 0xde, 0x1c, 0x52, 0xab, 0xbe, 0x39, 0xa4, 0x36, - 0x93, 0x0d, 0xa9, 0xf5, 0xfe, 0xb2, 0x05, 0x0b, 0x05, 0x64, 0xf6, 0x9b, 0x9b, 0x38, 0x23, 0x0c, - 0x43, 0xfa, 0x94, 0x04, 0x61, 0xe8, 0xc0, 0xde, 0x5f, 0x80, 0x96, 0xc1, 0x5a, 0xbf, 0xb9, 0xfe, - 0xb3, 0xe6, 0x19, 0xa7, 0x6c, 0x03, 0xd6, 0xfb, 0x1f, 0x25, 0x20, 0x79, 0xf6, 0xfe, 0xad, 0x8e, - 0x21, 0xbf, 0x4e, 0xe5, 0x82, 0x75, 0xfa, 0x7f, 0x7a, 0xf2, 0x7c, 0x00, 0xf3, 0x22, 0xd9, 0x40, - 0x0b, 0x69, 0x70, 0x8a, 0xc9, 0x57, 0x30, 0x03, 0xd5, 0x8c, 0x67, 0xd6, 0x8c, 0xcb, 0xd5, 0xda, - 0xf1, 0x9b, 0x09, 0x6b, 0xda, 0x3d, 0xe8, 0x8a, 0x15, 0xca, 0xbb, 0xfe, 0xfe, 0x6e, 0x45, 0xd9, - 0xd8, 0x58, 0x29, 0xf4, 0xe7, 0x6f, 0x40, 0x53, 0x3f, 0x3e, 0xc4, 0x76, 0x64, 0xa2, 0x5a, 0x4c, - 0xcd, 0xd0, 0xb1, 0xc8, 0x26, 0xb4, 0x51, 0x48, 0x0e, 0xd4, 0x77, 0x5c, 0xd3, 0xb8, 0xc2, 0xa1, - 0xbd, 0x7d, 0xcd, 0xc9, 0x7c, 0x43, 0x7e, 0x17, 0xda, 0xa6, 0x9b, 0x4b, 0xe8, 0x84, 0x45, 0x6a, - 0x24, 0xfb, 0xdc, 0x44, 0x26, 0x6b, 0xd0, 0xc9, 0xfa, 0xc9, 0xc4, 0xcd, 0xcf, 0x29, 0x0d, 0xe4, - 0xd0, 0xc9, 0x27, 0xb0, 0x58, 0x74, 0x88, 0xe2, 0xde, 0x4c, 0xb7, 0x22, 0x0a, 0xbf, 0x21, 0x8f, - 0x85, 0xcf, 0xb4, 0x5a, 0x14, 0xe6, 0xd1, 0x96, 0x7c, 0x85, 0xff, 0xa7, 0x79, 0x4f, 0xcf, 0x01, - 0x52, 0x18, 0xe9, 0x40, 0x73, 0xff, 0x60, 0x6b, 0xcf, 0xdd, 0xd8, 0x5e, 0xdb, 0xdb, 0xdb, 0xda, - 0xed, 0x5c, 0x23, 0x04, 0xda, 0x18, 0x9e, 0xd9, 0x54, 0x30, 0x8b, 0xc1, 0x84, 0x47, 0x59, 0xc2, - 0x4a, 0x64, 0x11, 0x3a, 0x3b, 0x7b, 0x19, 0x68, 0x99, 0x74, 0x61, 0xf1, 0x60, 0x8b, 0x47, 0x74, - 0x8c, 0x76, 0x2b, 0x4c, 0xdf, 0x13, 0x83, 0x67, 0xfa, 0x1e, 0x4f, 0x59, 0x59, 0xe7, 0x44, 0x28, - 0x75, 0xa0, 0xbf, 0x6f, 0xc1, 0xf5, 0x4c, 0x45, 0x7a, 0x09, 0x99, 0xab, 0x39, 0xa6, 0xee, 0x63, - 0x02, 0x31, 0x24, 0x2e, 0xcd, 0xc3, 0x8c, 0x9c, 0xca, 0x57, 0x30, 0xce, 0xd2, 0xcc, 0xc9, 0x0c, - 0xbf, 0x16, 0x55, 0xd9, 0xcb, 0xea, 0xae, 0x67, 0x66, 0xe0, 0x27, 0x3c, 0x15, 0x46, 0xaf, 0x48, - 0xbd, 0xca, 0xe6, 0x90, 0x65, 0x91, 0xac, 0x66, 0xa8, 0xc1, 0x1c, 0x6f, 0x61, 0x9d, 0xfd, 0x4f, - 0x67, 0x80, 0x7c, 0x77, 0x42, 0xa3, 0x4b, 0xbc, 0x65, 0xac, 0x82, 0x59, 0xcb, 0x59, 0xd7, 0xfa, - 0xcc, 0x78, 0x72, 0xcc, 0x0c, 0x16, 0x61, 0x48, 0x95, 0xde, 0x2a, 0x9b, 0xa0, 0xe8, 0x36, 0x7f, - 0xe5, 0xcd, 0xb7, 0xf9, 0xab, 0x6f, 0xba, 0xcd, 0xff, 0x25, 0x68, 0xf9, 0xa7, 0x41, 0xc8, 0x84, - 0x0e, 0x53, 0x54, 0xe2, 0xee, 0xcc, 0xdd, 0xf2, 0xfd, 0xa6, 0xd3, 0x14, 0xc0, 0x3d, 0x06, 0x23, - 0x4f, 0x52, 0x24, 0x3a, 0x38, 0xc5, 0xec, 0x13, 0x5d, 0x0c, 0x6d, 0x0d, 0x4e, 0xa9, 0xb0, 0x1b, - 0xd1, 0xb5, 0x22, 0x3f, 0x66, 0xf0, 0x98, 0xdc, 0x83, 0x76, 0x1c, 0x4e, 0x98, 0xea, 0x26, 0x97, - 0x81, 0x3b, 0x9c, 0x9b, 0x1c, 0x7a, 0xc0, 0x17, 0x63, 0x05, 0x16, 0x26, 0x31, 0x75, 0x47, 0x7e, - 0x1c, 0xb3, 0xe3, 0xb9, 0x1f, 0x06, 0x49, 0x14, 0x0e, 0x85, 0x03, 0x79, 0x7e, 0x12, 0xd3, 0xe7, - 0xbc, 0x66, 0x83, 0x57, 0x90, 0x6f, 0xa4, 0x43, 0x1a, 0x7b, 0x7e, 0x14, 0x77, 0x01, 0x87, 0x24, - 0x67, 0xca, 0xc6, 0x7d, 0xe0, 0xf9, 0x91, 0x1a, 0x0b, 0x2b, 0xc4, 0x99, 0x2c, 0x83, 0x46, 0x36, - 0xcb, 0xe0, 0x47, 0xc5, 0x59, 0x06, 0x2d, 0x6c, 0xfa, 0x91, 0x68, 0x3a, 0xbf, 0xc5, 0x5f, 0x28, - 0xd9, 0x20, 0x9f, 0x3c, 0xd1, 0xfe, 0x22, 0xc9, 0x13, 0x73, 0x45, 0xc9, 0x13, 0x1f, 0x42, 0x03, - 0xaf, 0xb4, 0xbb, 0x67, 0x7e, 0x90, 0x48, 0x67, 0x78, 0x47, 0xbf, 0xf3, 0xbe, 0xcd, 0xcc, 0x6f, - 0x88, 0xe4, 0x9f, 0x71, 0x3e, 0x8f, 0x61, 0xfe, 0xb7, 0x98, 0xc7, 0x20, 0xae, 0xde, 0xaf, 0x40, - 0x4d, 0xee, 0x13, 0x21, 0x50, 0x39, 0x89, 0xc2, 0x91, 0xf4, 0x0f, 0xb2, 0xbf, 0x49, 0x1b, 0x4a, - 0x49, 0x28, 0x3e, 0x2e, 0x25, 0xa1, 0xfd, 0x07, 0xd0, 0xd0, 0x48, 0x8d, 0xbc, 0xcb, 0xdd, 0x0e, - 0x4c, 0x75, 0x16, 0x76, 0x35, 0x5f, 0xc5, 0xba, 0x80, 0xee, 0x0c, 0xc8, 0x57, 0x61, 0x7e, 0xe0, - 0x47, 0x14, 0x33, 0x8e, 0xdc, 0x88, 0x9e, 0xd3, 0x28, 0x96, 0x2e, 0xdb, 0x8e, 0xaa, 0x70, 0x38, - 0xdc, 0x76, 0x61, 0xc1, 0xd8, 0x5b, 0x25, 0xdd, 0x66, 0x70, 0xdd, 0x64, 0x94, 0xcd, 0xcc, 0x25, - 0x10, 0x75, 0x4c, 0xfb, 0x10, 0xde, 0x66, 0x77, 0x1c, 0x85, 0xc7, 0xd8, 0x89, 0xe5, 0x18, 0x30, - 0xfb, 0xbf, 0x97, 0xa1, 0xbc, 0x1d, 0x8e, 0xf5, 0x0b, 0x1d, 0x56, 0xfe, 0x42, 0x87, 0x30, 0x13, - 0x5c, 0x65, 0x05, 0x08, 0x5d, 0xce, 0x00, 0x92, 0x07, 0xd0, 0x66, 0xa2, 0x22, 0x09, 0x99, 0x59, - 0x74, 0xe1, 0x45, 0x3c, 0xb9, 0xa0, 0x8c, 0xfc, 0x97, 0xa9, 0x21, 0x8b, 0x50, 0x56, 0xda, 0x2d, - 0x22, 0xb0, 0x22, 0xb3, 0xc9, 0xf1, 0x6a, 0xdd, 0xa5, 0x88, 0x21, 0x89, 0x12, 0x93, 0xbc, 0xe6, - 0xf7, 0x5c, 0x1e, 0x71, 0x1d, 0xa5, 0xa8, 0x8a, 0x99, 0x2c, 0x4c, 0xe2, 0x8c, 0x52, 0x0b, 0x40, - 0x95, 0xf5, 0xc0, 0x62, 0xcd, 0x0c, 0x2c, 0xde, 0x85, 0x46, 0x32, 0x3c, 0x77, 0xc7, 0xde, 0xe5, - 0x30, 0xf4, 0x06, 0x82, 0xd3, 0x75, 0x10, 0x79, 0x04, 0x30, 0x1a, 0x8f, 0x05, 0x1b, 0xa2, 0xd7, - 0x32, 0xa5, 0xea, 0xe7, 0x07, 0x07, 0x9c, 0xfa, 0x1c, 0x0d, 0x87, 0x6c, 0x41, 0xbb, 0x30, 0x43, - 0xe8, 0xb6, 0xbc, 0x00, 0x16, 0x8e, 0x57, 0x0a, 0x18, 0x35, 0xf3, 0x51, 0xef, 0x3b, 0x40, 0x7e, - 0xcd, 0x44, 0x9d, 0x97, 0x50, 0x57, 0x23, 0xd4, 0xd3, 0x63, 0xf0, 0x96, 0x67, 0xc3, 0x4c, 0x8f, - 0xc1, 0x4b, 0x9d, 0xef, 0x41, 0x9b, 0x1f, 0x97, 0xea, 0x00, 0xe0, 0x37, 0xf3, 0x32, 0x50, 0xfb, - 0xcf, 0x2d, 0xa8, 0x22, 0xe5, 0x31, 0x2d, 0x95, 0xd7, 0xa9, 0x9b, 0x30, 0x22, 0xf6, 0x94, 0x05, - 0x13, 0xdb, 0xc8, 0x1c, 0x2c, 0x29, 0x32, 0xd0, 0xb3, 0x07, 0xef, 0x42, 0x5d, 0xf5, 0xa4, 0x91, - 0x52, 0x0a, 0x24, 0x77, 0xa0, 0x72, 0x16, 0x8e, 0xa5, 0x21, 0x0f, 0xe9, 0x8a, 0x3a, 0x08, 0x4f, - 0xc7, 0xc3, 0xda, 0xe3, 0x53, 0xe0, 0xc6, 0x52, 0x16, 0x5c, 0x30, 0xd7, 0x99, 0xc2, 0xb9, 0xbe, - 0x80, 0x39, 0x26, 0x1f, 0xb4, 0xd8, 0xf0, 0xf4, 0xc3, 0xf4, 0x2b, 0x4c, 0x03, 0xec, 0x0f, 0x27, - 0x03, 0xaa, 0xbb, 0x53, 0x30, 0xa6, 0x28, 0xe0, 0xd2, 0x90, 0xb0, 0xff, 0xb9, 0xc5, 0xe5, 0x0e, - 0x6b, 0x97, 0xdc, 0x87, 0x0a, 0x3b, 0xf7, 0x32, 0x3e, 0x3f, 0x75, 0xf3, 0x96, 0xe1, 0x39, 0x88, - 0xc1, 0x76, 0x11, 0xc3, 0x61, 0x7a, 0xeb, 0x3c, 0x18, 0x96, 0xfa, 0x22, 0xd4, 0xcc, 0x32, 0x26, - 0x7c, 0x06, 0x4a, 0x56, 0xb4, 0xfb, 0x1f, 0x15, 0xe3, 0x2c, 0x95, 0x4a, 0xe2, 0xe0, 0x94, 0x6a, - 0xf7, 0x3e, 0xfe, 0x65, 0x09, 0x5a, 0xc6, 0x98, 0x18, 0xf7, 0xe0, 0xd1, 0xc0, 0x3d, 0xca, 0x62, - 0xe7, 0x75, 0x90, 0xce, 0x79, 0x25, 0x93, 0xf3, 0x54, 0x20, 0xbc, 0xac, 0x07, 0xc2, 0x1f, 0x41, - 0x3d, 0x4d, 0x1d, 0x35, 0x07, 0xc5, 0x7a, 0x94, 0x77, 0x90, 0x53, 0xa4, 0x34, 0x74, 0x5e, 0xd5, - 0x43, 0xe7, 0xdf, 0xd6, 0x42, 0xab, 0x33, 0xd8, 0x8c, 0x5d, 0xb4, 0xaa, 0xbf, 0x9d, 0xbb, 0x18, - 0x4f, 0xa0, 0xa1, 0x0d, 0x5e, 0x0f, 0xa1, 0x5a, 0x46, 0x08, 0x55, 0x65, 0x0b, 0x94, 0xd2, 0x6c, - 0x01, 0xfb, 0x67, 0x25, 0x68, 0x31, 0x5e, 0xf3, 0x83, 0xd3, 0x83, 0x70, 0xe8, 0xf7, 0x2f, 0x91, - 0xc6, 0x25, 0x5b, 0x09, 0x25, 0x4c, 0xf2, 0x9c, 0x09, 0x66, 0x32, 0x51, 0xa5, 0x48, 0x71, 0x01, - 0xae, 0xca, 0x4c, 0xc2, 0x33, 0xf9, 0x78, 0xec, 0xc5, 0x54, 0x4b, 0x6c, 0x75, 0x4c, 0x20, 0x93, - 0xc3, 0x0c, 0x80, 0xb9, 0x1f, 0x23, 0x7f, 0x38, 0xf4, 0x39, 0x2e, 0xf7, 0x51, 0x14, 0x55, 0xb1, - 0x3e, 0x07, 0x7e, 0xec, 0x1d, 0xa7, 0x17, 0x96, 0x54, 0x19, 0xa3, 0x45, 0xde, 0x6b, 0x2d, 0x5a, - 0xc4, 0x93, 0xc5, 0x4c, 0x60, 0x96, 0xaa, 0x66, 0x73, 0x54, 0x65, 0xff, 0x9b, 0x12, 0x34, 0x34, - 0x1a, 0x65, 0xb2, 0xa5, 0xf0, 0x10, 0xd6, 0xa0, 0xe2, 0x8a, 0x62, 0x60, 0x78, 0xbd, 0x34, 0x08, - 0xb9, 0x67, 0xf6, 0x8a, 0x51, 0x66, 0x94, 0x3e, 0x06, 0x3d, 0xdf, 0x82, 0x3a, 0xe3, 0xc3, 0x0f, - 0xd1, 0xc5, 0x26, 0x92, 0xc8, 0x15, 0x40, 0xd6, 0xae, 0x62, 0x6d, 0x35, 0xad, 0x45, 0xc0, 0x95, - 0x97, 0x16, 0x1f, 0x43, 0x53, 0x34, 0x83, 0x7b, 0x8c, 0x93, 0x4e, 0x25, 0x81, 0xb1, 0xff, 0x8e, - 0x81, 0x29, 0xbf, 0x5c, 0x95, 0x5f, 0xd6, 0xde, 0xf4, 0xa5, 0xc4, 0xb4, 0x9f, 0xa9, 0xfb, 0xa0, - 0xcf, 0x22, 0x6f, 0x7c, 0x26, 0xa5, 0xdb, 0x23, 0x58, 0x90, 0x42, 0x6c, 0x12, 0x78, 0x41, 0x10, - 0x4e, 0x82, 0x3e, 0x95, 0x89, 0x05, 0x45, 0x55, 0xf6, 0x40, 0xa5, 0xa1, 0x61, 0x43, 0xe4, 0x01, - 0x54, 0xb9, 0x1a, 0xcf, 0x75, 0x95, 0x62, 0x79, 0xc6, 0x51, 0xc8, 0x7d, 0xa8, 0x72, 0x6d, 0xbe, - 0x34, 0x55, 0x02, 0x71, 0x04, 0x7b, 0x05, 0xe6, 0x50, 0x23, 0xd5, 0x04, 0xf1, 0xcd, 0x22, 0x1d, - 0x66, 0xa6, 0xcf, 0xc3, 0x19, 0x8b, 0x40, 0xf6, 0x38, 0x5f, 0xe9, 0xf7, 0x7a, 0xfe, 0xbc, 0x0c, - 0x0d, 0x0d, 0xcc, 0x84, 0x25, 0x5e, 0xf2, 0x70, 0x07, 0xbe, 0x37, 0xa2, 0x32, 0xb8, 0xd1, 0x72, - 0x32, 0x50, 0x86, 0xe7, 0x9d, 0x9f, 0xba, 0xe1, 0x24, 0x71, 0x07, 0xf4, 0x34, 0xa2, 0x54, 0x28, - 0x57, 0x19, 0x28, 0xc3, 0x63, 0xd4, 0xac, 0xe1, 0xf1, 0xfb, 0x0a, 0x19, 0xa8, 0xbc, 0x3f, 0xc3, - 0xd7, 0xa9, 0x92, 0xde, 0x9f, 0xe1, 0xab, 0x92, 0x15, 0xf3, 0xd5, 0x02, 0x31, 0xff, 0x11, 0x2c, - 0x71, 0x81, 0x2e, 0xa4, 0x87, 0x9b, 0x21, 0xae, 0x29, 0xb5, 0xe4, 0x01, 0x74, 0xd8, 0x98, 0x25, - 0x6b, 0xc4, 0xfe, 0x4f, 0x38, 0x8f, 0x59, 0x4e, 0x0e, 0xce, 0x70, 0x31, 0xf6, 0xaa, 0xe3, 0xf2, - 0x8b, 0xb2, 0x39, 0x38, 0xe2, 0x7a, 0xaf, 0x4d, 0xdc, 0xba, 0xc0, 0xcd, 0xc0, 0xc9, 0x63, 0x58, - 0x1e, 0xd1, 0x81, 0xef, 0x99, 0x4d, 0xb8, 0xa9, 0xc6, 0x31, 0xad, 0x9a, 0xf5, 0xc2, 0x56, 0xe1, - 0x27, 0xe1, 0xe8, 0xd8, 0xe7, 0xa7, 0x2c, 0x8f, 0x12, 0x57, 0x9c, 0x1c, 0xdc, 0x6e, 0x41, 0xe3, - 0x30, 0x09, 0xc7, 0x72, 0xeb, 0xdb, 0xd0, 0xe4, 0x45, 0x91, 0x4a, 0x72, 0x13, 0x6e, 0x20, 0xbd, - 0x1e, 0x85, 0xe3, 0x70, 0x18, 0x9e, 0x5e, 0x1a, 0xee, 0xa9, 0x7f, 0x67, 0xc1, 0x82, 0x51, 0x9b, - 0xfa, 0xa7, 0xd0, 0x97, 0x2e, 0xef, 0xff, 0x73, 0x12, 0x9f, 0xd7, 0xce, 0x28, 0x8e, 0xc8, 0xef, - 0x01, 0xbc, 0x10, 0x29, 0x01, 0x6b, 0x69, 0x52, 0xab, 0xfc, 0x90, 0xd3, 0x7b, 0x37, 0x4f, 0xef, - 0xe2, 0x7b, 0x99, 0xee, 0x2a, 0x9b, 0xf8, 0x5d, 0x71, 0xad, 0x79, 0x20, 0x26, 0x5d, 0x36, 0x6f, - 0x6c, 0xea, 0xee, 0x4c, 0x39, 0x82, 0xbe, 0x02, 0xc6, 0xf6, 0x2f, 0x2c, 0x80, 0x74, 0x74, 0x78, - 0x67, 0x54, 0x9d, 0xb3, 0xfc, 0xdd, 0x18, 0xed, 0x4c, 0x7d, 0x17, 0x9a, 0xea, 0xde, 0x5a, 0x7a, - 0x74, 0x37, 0x24, 0x8c, 0xa9, 0x3a, 0xef, 0xc3, 0xdc, 0xe9, 0x30, 0x3c, 0x46, 0x95, 0x4a, 0x9c, - 0xb3, 0x3c, 0xa1, 0xa6, 0xcd, 0xc1, 0xf2, 0xf4, 0x4c, 0xcf, 0xf9, 0x4a, 0xe1, 0x85, 0x37, 0xfd, - 0xd4, 0x66, 0x67, 0xdd, 0x7c, 0x6e, 0x25, 0xae, 0xe4, 0xf2, 0x5f, 0x29, 0xec, 0x7b, 0x55, 0x74, - 0xe3, 0x09, 0xb4, 0x23, 0x2e, 0x33, 0xa5, 0x40, 0xad, 0x5c, 0x21, 0x50, 0x5b, 0x91, 0x71, 0x32, - 0x7f, 0x05, 0x3a, 0xde, 0xe0, 0x9c, 0x46, 0x89, 0x8f, 0xde, 0x5e, 0xd4, 0xe9, 0xf8, 0x04, 0xe7, - 0x34, 0x38, 0xaa, 0x4e, 0xef, 0xc3, 0x9c, 0x48, 0x6f, 0x52, 0x98, 0xe2, 0x05, 0x85, 0x14, 0xcc, - 0x10, 0xed, 0x7f, 0x24, 0xaf, 0x0d, 0x99, 0xbb, 0x7b, 0xf5, 0xaa, 0xe8, 0x33, 0x2c, 0x65, 0x66, - 0xf8, 0x25, 0x71, 0x29, 0x62, 0x20, 0xdd, 0xca, 0x65, 0xed, 0x82, 0xfc, 0x40, 0x5c, 0xbb, 0x32, - 0x97, 0xb5, 0xf2, 0x36, 0xcb, 0x6a, 0xff, 0x27, 0x0b, 0x66, 0xb7, 0xc3, 0x31, 0x33, 0xed, 0x51, - 0xc7, 0x61, 0x6c, 0xa2, 0x72, 0x0b, 0x65, 0xf1, 0x0d, 0x89, 0x04, 0x85, 0x5a, 0x49, 0x2b, 0xab, - 0x95, 0x7c, 0x07, 0x6e, 0x62, 0x60, 0x23, 0x0a, 0xc7, 0x61, 0xc4, 0xd8, 0xd5, 0x1b, 0x72, 0x15, - 0x24, 0x0c, 0x92, 0x33, 0x29, 0x4e, 0xaf, 0x42, 0x41, 0x3f, 0xe0, 0x30, 0x39, 0x77, 0xb9, 0xb9, - 0x29, 0xb4, 0x28, 0x2e, 0x65, 0xf3, 0x15, 0xf6, 0xb7, 0xa0, 0xae, 0x1c, 0x18, 0xe4, 0x03, 0xa8, - 0x9f, 0x85, 0x63, 0xe1, 0xe5, 0xb0, 0x8c, 0xa4, 0x0b, 0x31, 0x7b, 0x27, 0x45, 0xb0, 0xff, 0xe7, - 0x2c, 0xcc, 0xee, 0x04, 0xe7, 0xa1, 0xdf, 0xc7, 0xeb, 0x47, 0x23, 0x3a, 0x0a, 0x65, 0xb6, 0x25, - 0xfb, 0x1b, 0x1f, 0x42, 0x49, 0xdf, 0x43, 0xe0, 0x2c, 0xa4, 0x41, 0x98, 0x81, 0x1c, 0xe9, 0xef, - 0x19, 0x88, 0x52, 0x6a, 0xf5, 0x55, 0xb5, 0x7c, 0x55, 0xd6, 0x1a, 0xcf, 0xb3, 0xc7, 0xb5, 0xe3, - 0x59, 0x32, 0x1a, 0x84, 0x2d, 0xbe, 0x48, 0x70, 0xe0, 0x17, 0xc5, 0xf9, 0x4d, 0x46, 0x01, 0x42, - 0xa3, 0x3f, 0xa2, 0x3c, 0x34, 0xa5, 0x54, 0x2f, 0x66, 0xf4, 0xeb, 0x40, 0xa6, 0x9e, 0xf1, 0x0f, - 0x38, 0x0e, 0x3f, 0x0e, 0x74, 0x10, 0xde, 0x46, 0xc9, 0xbc, 0x0e, 0xc2, 0x5f, 0x78, 0xc9, 0x82, - 0xf9, 0x45, 0x33, 0x25, 0x74, 0xf9, 0x3c, 0x81, 0xbf, 0x09, 0x91, 0x85, 0x6b, 0xae, 0x02, 0x9e, - 0x07, 0x26, 0x5d, 0x05, 0x8c, 0x64, 0xbc, 0xe1, 0xf0, 0xd8, 0xeb, 0xbf, 0xe2, 0x96, 0x6d, 0x93, - 0x47, 0x34, 0x0d, 0x20, 0xde, 0xe6, 0x4f, 0xf7, 0x15, 0x2f, 0x02, 0x55, 0x1c, 0x1d, 0x44, 0x56, - 0x4d, 0xff, 0x55, 0x7b, 0x8a, 0xff, 0x4a, 0x47, 0xd2, 0x2f, 0x46, 0xcd, 0xe5, 0x32, 0xb3, 0xbc, - 0xc1, 0x40, 0x5c, 0x98, 0xe9, 0xf0, 0x37, 0x11, 0x14, 0x00, 0x1d, 0x35, 0x7c, 0xc1, 0x38, 0xc2, - 0x3c, 0x22, 0x18, 0x30, 0x72, 0x87, 0xfb, 0x61, 0xc7, 0x9e, 0x3f, 0xc0, 0x8b, 0xa9, 0xdc, 0x16, - 0x56, 0x30, 0xd6, 0x86, 0xfc, 0x1b, 0x0f, 0xce, 0x05, 0x5c, 0x15, 0x03, 0xc6, 0xd6, 0x46, 0x95, - 0x47, 0x69, 0x2a, 0x97, 0x09, 0x24, 0x1f, 0xe2, 0x45, 0x84, 0x84, 0x62, 0xbe, 0x56, 0x7b, 0xf5, - 0xa6, 0x98, 0xb3, 0x20, 0x5b, 0xf9, 0x3f, 0x5e, 0xbc, 0x70, 0x38, 0x26, 0x53, 0xdb, 0x78, 0x2c, - 0x68, 0xc9, 0x50, 0xdb, 0x04, 0x2a, 0xc6, 0x82, 0x38, 0x02, 0x79, 0xac, 0x59, 0x62, 0x5d, 0x44, - 0xbe, 0x95, 0x69, 0x7f, 0x8a, 0x0d, 0xc6, 0x88, 0xd9, 0x8f, 0xd9, 0xf9, 0x13, 0xd3, 0x60, 0x80, - 0x99, 0x5b, 0x35, 0x47, 0x83, 0xfc, 0x66, 0x6d, 0xb4, 0x35, 0x68, 0xea, 0xf3, 0x24, 0x35, 0xa8, - 0xec, 0x1f, 0x6c, 0xed, 0x75, 0xae, 0x91, 0x06, 0xcc, 0x1e, 0x6e, 0x1d, 0x1d, 0xed, 0x6e, 0x6d, - 0x76, 0x2c, 0xd2, 0x84, 0x9a, 0x4a, 0x43, 0x29, 0xb1, 0xd2, 0xda, 0xc6, 0xc6, 0xd6, 0xc1, 0xd1, - 0xd6, 0x66, 0xa7, 0xfc, 0x49, 0xa5, 0x56, 0xea, 0x94, 0x51, 0xc1, 0xd4, 0x96, 0xe1, 0x0d, 0x7e, - 0xb6, 0x3b, 0x00, 0x68, 0xf8, 0xa4, 0x17, 0xab, 0x2a, 0x8e, 0x06, 0x61, 0x82, 0x5c, 0xf9, 0x27, - 0xca, 0xfc, 0x1d, 0x0b, 0x59, 0xc6, 0xcd, 0xc5, 0x07, 0x23, 0xf4, 0xf8, 0x60, 0xd5, 0x31, 0x81, - 0x8c, 0xf0, 0x05, 0x00, 0x13, 0x1c, 0xb8, 0xb8, 0xd0, 0x41, 0x8c, 0x90, 0x22, 0x1a, 0x87, 0xc3, - 0x73, 0xca, 0x51, 0xb8, 0xfa, 0x68, 0xc0, 0x58, 0x5f, 0x42, 0x22, 0x6a, 0x59, 0x55, 0x55, 0xc7, - 0x04, 0x92, 0xaf, 0x49, 0x42, 0xaa, 0x21, 0x21, 0x2d, 0xe7, 0xa9, 0xc2, 0x20, 0xa2, 0xe7, 0x39, - 0x47, 0x59, 0x1d, 0x09, 0xe4, 0xcb, 0xf9, 0xef, 0xde, 0xc2, 0x61, 0x46, 0x56, 0x80, 0x8c, 0xc6, - 0x63, 0xb7, 0xc0, 0x83, 0x55, 0x71, 0x0a, 0x6a, 0x7e, 0x03, 0x0e, 0xb6, 0x04, 0xc8, 0xda, 0x60, - 0x20, 0x86, 0xa9, 0x3f, 0xeb, 0x11, 0xe9, 0xef, 0xc8, 0x48, 0x91, 0x5d, 0x20, 0x16, 0x4b, 0xc5, - 0x62, 0xf1, 0x4a, 0xe1, 0x61, 0xef, 0x40, 0xe3, 0x40, 0x7b, 0x99, 0xc6, 0x66, 0x27, 0x88, 0x7c, - 0x93, 0x86, 0x9f, 0x2d, 0xdc, 0xb1, 0x96, 0x42, 0xb5, 0x21, 0x95, 0xf4, 0x21, 0xd9, 0xff, 0xc0, - 0xe2, 0xc9, 0xfe, 0x6a, 0x0a, 0xbc, 0x7f, 0x1b, 0x9a, 0x2a, 0xb8, 0x94, 0x66, 0x3e, 0x1a, 0x30, - 0x86, 0x83, 0xc3, 0x71, 0xc3, 0x93, 0x93, 0x98, 0xca, 0x54, 0x1e, 0x03, 0x26, 0x95, 0x75, 0xa6, - 0xfe, 0xfb, 0xbc, 0x87, 0x58, 0xa4, 0xf4, 0xe4, 0xe0, 0x8c, 0xd2, 0x85, 0x6f, 0x5c, 0x26, 0x31, - 0xa9, 0xb2, 0x4a, 0xd0, 0xcc, 0xae, 0xf4, 0x03, 0xa8, 0xa9, 0x76, 0xcd, 0x93, 0x58, 0x62, 0xaa, - 0x7a, 0x76, 0xe2, 0xa3, 0x21, 0x6f, 0x0c, 0x9a, 0x33, 0x5c, 0xbe, 0x82, 0xd1, 0xd2, 0x89, 0x1f, - 0x65, 0xd1, 0x39, 0x07, 0x16, 0xd4, 0xd8, 0x2f, 0x61, 0x41, 0x8a, 0x0f, 0xcd, 0x8a, 0x30, 0x37, - 0xd2, 0x7a, 0xd3, 0x29, 0x50, 0xca, 0x9f, 0x02, 0xf6, 0xbf, 0xae, 0xc0, 0xac, 0x7c, 0xf6, 0xc9, - 0x2e, 0x78, 0xa6, 0xa8, 0x6e, 0xbe, 0x70, 0x44, 0xba, 0xc6, 0x3b, 0x16, 0x48, 0x08, 0x42, 0x37, - 0xb8, 0x9f, 0x3d, 0xdd, 0x53, 0x07, 0x6b, 0xe6, 0x84, 0x5f, 0x82, 0xca, 0xd8, 0x4b, 0xce, 0xd0, - 0xff, 0xc6, 0x69, 0x09, 0xcb, 0xd2, 0x85, 0x5f, 0x35, 0x5d, 0xf8, 0x45, 0xef, 0x3a, 0x71, 0x55, - 0x36, 0xff, 0xae, 0xd3, 0x2d, 0xa8, 0x73, 0x6d, 0x24, 0xf5, 0xd2, 0xa7, 0x80, 0x8c, 0xf6, 0x52, - 0xcb, 0x69, 0x2f, 0x6f, 0xaf, 0x57, 0x7c, 0x03, 0x66, 0x78, 0x6e, 0xb3, 0x48, 0xd9, 0x92, 0x47, - 0x8e, 0x58, 0x49, 0xf9, 0x3f, 0xbf, 0xb9, 0xeb, 0x08, 0x5c, 0xfd, 0x75, 0x94, 0x86, 0xf9, 0x3a, - 0x8a, 0x1e, 0x5c, 0x68, 0x66, 0x82, 0x0b, 0x0f, 0xa0, 0xa3, 0x96, 0x0f, 0x1d, 0x70, 0x41, 0x2c, - 0x52, 0x54, 0x72, 0xf0, 0xf4, 0xd8, 0x6c, 0x1b, 0xc7, 0x26, 0x93, 0x70, 0x6b, 0x49, 0x42, 0x47, - 0xe3, 0x44, 0x1c, 0x9b, 0xf6, 0x53, 0x68, 0x19, 0x83, 0x34, 0xd3, 0x1a, 0x5b, 0x50, 0xdf, 0xd9, - 0x73, 0x9f, 0xee, 0xee, 0x3c, 0xdb, 0x3e, 0xea, 0x58, 0xac, 0x78, 0xf8, 0x62, 0x63, 0x63, 0x6b, - 0x6b, 0x13, 0x8f, 0x25, 0x80, 0x99, 0xa7, 0x6b, 0x3b, 0xec, 0x88, 0x2a, 0xdb, 0xff, 0xcb, 0x82, - 0x86, 0xd6, 0x3c, 0xf9, 0xa6, 0x5a, 0x19, 0xfe, 0x80, 0xc6, 0xed, 0xfc, 0x10, 0x56, 0xa4, 0xa0, - 0xd6, 0x96, 0x46, 0x3d, 0x65, 0x55, 0x9a, 0xfa, 0x94, 0x15, 0xdb, 0x1e, 0x8f, 0xb7, 0xa0, 0xd6, - 0x81, 0x5b, 0x57, 0x59, 0x30, 0xbf, 0xae, 0x96, 0x9e, 0x2e, 0x0c, 0x93, 0x7b, 0x14, 0xb3, 0x60, - 0xfb, 0x23, 0x80, 0x74, 0x34, 0xe6, 0xb4, 0xaf, 0x99, 0xd3, 0xb6, 0xb4, 0x69, 0x97, 0xec, 0x4d, - 0x2e, 0x30, 0xc4, 0x12, 0xaa, 0x30, 0xf8, 0xd7, 0x80, 0x48, 0x07, 0x16, 0x5e, 0x0b, 0x1d, 0x0f, - 0x69, 0x22, 0x53, 0x3b, 0xe7, 0x45, 0xcd, 0x8e, 0xaa, 0x90, 0x69, 0xd7, 0x69, 0x2b, 0xa9, 0xdc, - 0x11, 0x14, 0x97, 0x95, 0x3b, 0x02, 0xd5, 0x51, 0xf5, 0x76, 0x0f, 0xba, 0x9b, 0x94, 0xb5, 0xb6, - 0x36, 0x1c, 0x66, 0x86, 0x63, 0xdf, 0x84, 0x1b, 0x05, 0x75, 0xc2, 0x3d, 0xf1, 0x5d, 0xb8, 0xbe, - 0xc6, 0xb3, 0x38, 0x7f, 0x53, 0x09, 0x23, 0x76, 0x17, 0x96, 0xb2, 0x4d, 0x8a, 0xce, 0x9e, 0xc2, - 0xfc, 0x26, 0x3d, 0x9e, 0x9c, 0xee, 0xd2, 0xf3, 0xb4, 0x23, 0x02, 0x95, 0xf8, 0x2c, 0xbc, 0x10, - 0xeb, 0x83, 0x7f, 0x93, 0xdb, 0x00, 0x43, 0x86, 0xe3, 0xc6, 0x63, 0xda, 0x97, 0x0f, 0x94, 0x20, - 0xe4, 0x70, 0x4c, 0xfb, 0xf6, 0x47, 0x40, 0xf4, 0x76, 0xc4, 0x7a, 0x31, 0x93, 0x61, 0x72, 0xec, - 0xc6, 0x97, 0x71, 0x42, 0x47, 0xf2, 0xe5, 0x15, 0x1d, 0x64, 0xbf, 0x0f, 0xcd, 0x03, 0xef, 0xd2, - 0xa1, 0x9f, 0x89, 0xa7, 0xd3, 0x96, 0x61, 0x76, 0xec, 0x5d, 0x32, 0x7e, 0x56, 0x21, 0x16, 0xac, - 0xb6, 0xff, 0xb8, 0x02, 0x33, 0x1c, 0x93, 0xb5, 0x3a, 0xa0, 0x71, 0xe2, 0x07, 0xc8, 0x63, 0xb2, - 0x55, 0x0d, 0x94, 0x13, 0x98, 0xa5, 0x02, 0x81, 0x29, 0x5c, 0x6d, 0xf2, 0xa1, 0x07, 0x41, 0xb2, - 0x06, 0x8c, 0x89, 0xad, 0x34, 0xfd, 0x8c, 0x53, 0x6a, 0x0a, 0xc8, 0xc4, 0x30, 0x53, 0xc3, 0x84, - 0x8f, 0x4f, 0x9e, 0x05, 0x42, 0x26, 0xea, 0xa0, 0x42, 0xf3, 0x67, 0x56, 0xe6, 0xd9, 0x64, 0xcc, - 0x9f, 0x9c, 0x99, 0x53, 0x7b, 0x0b, 0x33, 0x87, 0xfb, 0xdf, 0xae, 0x32, 0x73, 0xe0, 0x6d, 0xcc, - 0x9c, 0xb7, 0x89, 0x1d, 0xf6, 0xa0, 0x86, 0x67, 0xba, 0x26, 0x22, 0x65, 0x99, 0xfc, 0x8e, 0x66, - 0x03, 0xf0, 0x7b, 0x0c, 0x37, 0x53, 0x7e, 0x71, 0xe8, 0x67, 0xbf, 0x9d, 0x30, 0xcc, 0x0f, 0x61, - 0x56, 0x40, 0x19, 0x65, 0x07, 0xde, 0x48, 0x3e, 0xb0, 0x83, 0x7f, 0xb3, 0xa5, 0xc3, 0x77, 0x3e, - 0x3e, 0x9b, 0xf8, 0x11, 0x1d, 0xc8, 0x5c, 0x6d, 0x0d, 0x84, 0x97, 0xcb, 0x63, 0xf7, 0x55, 0x10, - 0x5e, 0x04, 0x22, 0x5b, 0x5b, 0x95, 0x6d, 0x02, 0x1d, 0x7c, 0x68, 0x6b, 0x1c, 0x46, 0xf2, 0xcd, - 0x24, 0xfb, 0x5f, 0x58, 0xd0, 0x11, 0x8c, 0xa6, 0xea, 0x18, 0x65, 0xeb, 0x99, 0x01, 0x15, 0xe5, - 0xb3, 0x79, 0xd7, 0x70, 0xb9, 0x14, 0x3e, 0xc2, 0x70, 0x0f, 0x5a, 0xe8, 0x04, 0x51, 0x67, 0x91, - 0x88, 0xca, 0x1b, 0x40, 0x36, 0x11, 0x79, 0xed, 0x73, 0xe4, 0x0f, 0x05, 0x41, 0xeb, 0x20, 0x79, - 0x9c, 0x45, 0x9e, 0xc8, 0xfe, 0xb2, 0x1c, 0x55, 0xb6, 0x7f, 0x69, 0xc1, 0xbc, 0x36, 0x13, 0xc1, - 0xc1, 0x4f, 0xa0, 0xa9, 0x1e, 0xba, 0xa3, 0x4a, 0xdb, 0x5a, 0x36, 0x45, 0x4e, 0xfa, 0x99, 0x81, - 0x8c, 0x8c, 0xe0, 0x5d, 0xe2, 0x00, 0xe3, 0xc9, 0x48, 0xa8, 0x39, 0x3a, 0x88, 0x11, 0xd8, 0x05, - 0xa5, 0xaf, 0x14, 0x0a, 0x57, 0xb4, 0x0c, 0x18, 0x06, 0x8f, 0xc2, 0x20, 0x39, 0x53, 0x48, 0x15, - 0x11, 0x3c, 0xd2, 0x81, 0xf6, 0x7f, 0x29, 0xc1, 0x02, 0xf7, 0xc6, 0x09, 0x2f, 0xa8, 0x7a, 0x6b, - 0x68, 0x86, 0x3b, 0x26, 0xb9, 0x34, 0xdb, 0xbe, 0xe6, 0x88, 0x32, 0xf9, 0xe6, 0x5b, 0x7a, 0x10, - 0x55, 0x9a, 0xd9, 0x94, 0xbd, 0x28, 0x17, 0xed, 0xc5, 0x15, 0x2b, 0x5d, 0x14, 0xc7, 0xab, 0x16, - 0xc7, 0xf1, 0xde, 0x2e, 0x6e, 0x96, 0xcb, 0xc5, 0x9a, 0x15, 0x58, 0x46, 0x2e, 0xd6, 0x2a, 0x2c, - 0x1b, 0x00, 0x14, 0xe4, 0xfe, 0x89, 0x4f, 0x65, 0x62, 0xfc, 0x7c, 0x4c, 0x13, 0xd7, 0x40, 0x59, - 0x9f, 0x85, 0x6a, 0xdc, 0x0f, 0xc7, 0xd4, 0x5e, 0x82, 0x45, 0x73, 0x71, 0xc5, 0xf1, 0xf1, 0x0b, - 0x0b, 0xba, 0x4f, 0xf9, 0x6d, 0x0c, 0x3f, 0x38, 0xdd, 0xf6, 0xe3, 0x24, 0x8c, 0xd4, 0x93, 0x70, - 0x77, 0x00, 0xe2, 0xc4, 0x8b, 0x84, 0x01, 0xca, 0xb5, 0x60, 0x0d, 0xc2, 0xd6, 0x88, 0x06, 0x03, - 0x5e, 0xcb, 0x69, 0x43, 0x95, 0x73, 0x56, 0x86, 0xf0, 0x55, 0x1a, 0xba, 0xfa, 0x7b, 0x3c, 0x45, - 0x94, 0x2d, 0x06, 0x3d, 0xc7, 0x33, 0x99, 0x3b, 0x00, 0x33, 0x50, 0xfb, 0x0f, 0x4b, 0x30, 0x97, - 0x0e, 0x92, 0xa7, 0x9c, 0x1b, 0x92, 0x5d, 0x28, 0xe8, 0xa9, 0x64, 0x17, 0x71, 0x45, 0xd7, 0x67, - 0x1a, 0xbb, 0xe6, 0xae, 0xd4, 0xa0, 0xe4, 0x1e, 0x34, 0x64, 0x29, 0x9c, 0x24, 0xda, 0xdb, 0x4c, - 0x3a, 0x98, 0xe7, 0x9e, 0x30, 0x9b, 0x41, 0x32, 0x3d, 0x2f, 0xe1, 0x43, 0x09, 0xa3, 0x04, 0xbf, - 0xe4, 0x7b, 0x2a, 0x8b, 0x4c, 0xd2, 0x31, 0x65, 0x9b, 0xef, 0x21, 0x2a, 0xda, 0xba, 0x12, 0x5a, - 0x53, 0x6f, 0x5a, 0x2a, 0x9e, 0xe7, 0x2d, 0xa6, 0x59, 0x78, 0x15, 0x47, 0x07, 0x49, 0x77, 0x51, - 0x38, 0x31, 0xec, 0x62, 0x03, 0x66, 0xff, 0x0d, 0x0b, 0x6e, 0x14, 0x6c, 0xa3, 0x90, 0x01, 0x9b, - 0x30, 0x7f, 0xa2, 0x2a, 0xe5, 0x52, 0x73, 0x41, 0xb0, 0x24, 0xa5, 0xae, 0xb9, 0xbc, 0x4e, 0xfe, - 0x03, 0x65, 0x87, 0xf1, 0xcd, 0x33, 0x92, 0x2e, 0xf3, 0x15, 0xf6, 0x01, 0xf4, 0xb6, 0x5e, 0x33, - 0x91, 0xb2, 0xa1, 0x3f, 0x6c, 0x2e, 0x29, 0x6b, 0x35, 0x27, 0x32, 0xdf, 0xec, 0xa5, 0x3e, 0xe1, - 0xa9, 0x64, 0xaa, 0x2d, 0xf2, 0xf5, 0xb7, 0x6d, 0x44, 0xe7, 0xfe, 0xbb, 0x62, 0xd7, 0xf9, 0xcb, - 0xec, 0x32, 0xf5, 0x53, 0x03, 0xd9, 0xe7, 0x30, 0xf7, 0x7c, 0x32, 0x4c, 0xfc, 0xf4, 0x95, 0x76, - 0xf2, 0x4d, 0xf1, 0x11, 0x36, 0x21, 0x97, 0xae, 0xb0, 0x2b, 0x1d, 0x8f, 0xad, 0xd8, 0x88, 0xb5, - 0xe4, 0xe6, 0x7b, 0xcc, 0x57, 0xd8, 0x37, 0x60, 0x39, 0xed, 0x92, 0xaf, 0x9d, 0x3c, 0x8f, 0xfe, - 0xc8, 0xe2, 0x57, 0xae, 0xcd, 0x47, 0xe3, 0xc9, 0x33, 0x58, 0x88, 0xfd, 0xe0, 0x74, 0x48, 0xf5, - 0x76, 0x62, 0xb1, 0x12, 0xd7, 0xcd, 0xe1, 0x89, 0x87, 0xe5, 0x9d, 0xa2, 0x2f, 0x18, 0x81, 0x14, - 0x0f, 0x34, 0x25, 0x90, 0xcc, 0x92, 0x14, 0x4d, 0xe0, 0x13, 0x68, 0x9b, 0x9d, 0x91, 0xc7, 0x22, - 0xa7, 0x32, 0x1d, 0x59, 0x39, 0x93, 0x1a, 0x97, 0x52, 0x86, 0x81, 0x69, 0xff, 0xcc, 0x82, 0xae, - 0x43, 0x19, 0x19, 0x53, 0xad, 0x53, 0x41, 0x3d, 0x4f, 0x72, 0xcd, 0x4e, 0x9f, 0xb0, 0xca, 0xd5, - 0x94, 0x73, 0x5d, 0x99, 0xba, 0x29, 0xdb, 0xd7, 0x0a, 0x66, 0xb5, 0x5e, 0x83, 0x19, 0x31, 0xbf, - 0x65, 0xb8, 0x2e, 0x86, 0x24, 0x87, 0x93, 0xc6, 0x23, 0x8d, 0x4e, 0x8d, 0x78, 0x64, 0x0f, 0xba, - 0xfc, 0xe5, 0x3f, 0x7d, 0x1e, 0xe2, 0xc3, 0x4d, 0x20, 0xcf, 0xbd, 0xbe, 0x17, 0x85, 0x61, 0x70, - 0x40, 0x23, 0x71, 0x7b, 0x15, 0xd5, 0x52, 0x0c, 0xd7, 0x49, 0x0d, 0x9a, 0x97, 0xe4, 0x63, 0x75, - 0x61, 0x20, 0x1f, 0x05, 0xe4, 0x25, 0xdb, 0x81, 0x85, 0x75, 0xef, 0x15, 0x95, 0x2d, 0xa5, 0xab, - 0xd4, 0x18, 0xab, 0x46, 0xe5, 0xda, 0xcb, 0x64, 0xec, 0x7c, 0xb7, 0x8e, 0x8e, 0x6d, 0xaf, 0xc2, - 0xa2, 0xd9, 0xa6, 0x10, 0x25, 0x3d, 0xa8, 0x8d, 0x04, 0x4c, 0x8c, 0x4e, 0x95, 0x1f, 0x7c, 0x0e, - 0x0d, 0xed, 0x35, 0x47, 0xb2, 0x0c, 0x0b, 0x2f, 0x77, 0x8e, 0xf6, 0xb6, 0x0e, 0x0f, 0xdd, 0x83, - 0x17, 0xeb, 0x9f, 0x6e, 0x7d, 0xdf, 0xdd, 0x5e, 0x3b, 0xdc, 0xee, 0x5c, 0x23, 0x4b, 0x40, 0xf6, - 0xb6, 0x0e, 0x8f, 0xb6, 0x36, 0x0d, 0xb8, 0x45, 0xee, 0x40, 0xef, 0xc5, 0xde, 0x8b, 0xc3, 0xad, - 0x4d, 0xb7, 0xe8, 0xbb, 0x12, 0xb9, 0x0d, 0x37, 0x44, 0x7d, 0xc1, 0xe7, 0xe5, 0x07, 0x4f, 0xa0, - 0x93, 0xf5, 0x57, 0x1a, 0x7e, 0xde, 0xab, 0x1c, 0xc2, 0x0f, 0xfe, 0x61, 0x19, 0x20, 0xbd, 0xb5, - 0x4a, 0xba, 0xb0, 0xb8, 0xb9, 0x76, 0xb4, 0xb6, 0xbb, 0xcf, 0x06, 0xe1, 0xec, 0x1f, 0x6d, 0x6d, - 0x1c, 0xb9, 0xce, 0xd6, 0x77, 0x3b, 0xd7, 0x0a, 0x6b, 0xf6, 0x0f, 0x98, 0x2d, 0xbf, 0x0c, 0x0b, - 0x3b, 0x7b, 0x3b, 0x47, 0x3b, 0x6b, 0xbb, 0xae, 0xb3, 0xff, 0x62, 0x67, 0xef, 0x19, 0x7f, 0x90, - 0xa5, 0x4c, 0xde, 0x81, 0x9b, 0x2f, 0x0e, 0x9e, 0x3a, 0xfb, 0x7b, 0x47, 0xee, 0xe1, 0xf6, 0x8b, - 0xa3, 0x4d, 0x7c, 0xce, 0x65, 0xc3, 0xd9, 0x39, 0xe0, 0x6d, 0x56, 0xae, 0x42, 0x60, 0x4d, 0x57, - 0xd9, 0x8a, 0x3d, 0xdb, 0x3f, 0x3c, 0xdc, 0x39, 0x70, 0xbf, 0xfb, 0x62, 0xcb, 0xd9, 0xd9, 0x3a, - 0xc4, 0x0f, 0x67, 0x0a, 0xe0, 0x0c, 0x7f, 0x96, 0xcc, 0x43, 0xeb, 0x68, 0xf7, 0x7b, 0xee, 0xfe, - 0xde, 0xce, 0xfe, 0x1e, 0xa2, 0xd6, 0x4c, 0x10, 0xc3, 0xaa, 0x93, 0x1e, 0x2c, 0x6d, 0xfd, 0xfe, - 0x91, 0x5b, 0xd0, 0x32, 0x4c, 0xa9, 0x63, 0xdf, 0x35, 0xc8, 0x0d, 0xb8, 0x7e, 0x78, 0xb4, 0x76, - 0xb4, 0xb3, 0xe1, 0x8a, 0xa7, 0xa0, 0xd8, 0x26, 0xb0, 0xcf, 0x9a, 0xc5, 0x55, 0xec, 0xab, 0x16, - 0x59, 0x84, 0xce, 0xc1, 0xda, 0xf7, 0x9f, 0x6f, 0xed, 0x1d, 0xb9, 0x6b, 0x9b, 0x9b, 0x0e, 0x7e, - 0xd0, 0xce, 0x41, 0x19, 0xee, 0x1c, 0xdb, 0xa8, 0xe7, 0x07, 0x07, 0x88, 0xd2, 0x91, 0x05, 0x56, - 0x33, 0xbf, 0xfa, 0xb3, 0x32, 0xb4, 0x79, 0x1a, 0x01, 0xff, 0x79, 0x0c, 0x1a, 0x91, 0xe7, 0x30, - 0x2b, 0x7e, 0x67, 0x85, 0x5c, 0x57, 0xaf, 0x70, 0xe8, 0xbf, 0xec, 0xd2, 0x5b, 0xca, 0x82, 0x05, - 0xfb, 0x2d, 0xfc, 0xa5, 0xff, 0xf0, 0xdf, 0x7e, 0x5e, 0x6a, 0x91, 0xc6, 0xc3, 0xf3, 0x0f, 0x1f, - 0x9e, 0xd2, 0x20, 0x66, 0x6d, 0xfc, 0xff, 0x00, 0xe9, 0xaf, 0x87, 0x90, 0xae, 0x72, 0x4b, 0x66, - 0x7e, 0x5a, 0xa5, 0x77, 0xa3, 0xa0, 0x46, 0xb4, 0x7b, 0x03, 0xdb, 0x5d, 0xb0, 0xdb, 0xac, 0x5d, - 0x3f, 0xf0, 0x13, 0xfe, 0x4b, 0x22, 0x1f, 0x5b, 0x0f, 0xc8, 0x00, 0x9a, 0xfa, 0xef, 0x7a, 0x10, - 0x79, 0x0d, 0xa0, 0xe0, 0x97, 0x49, 0x7a, 0x37, 0x0b, 0xeb, 0xa4, 0xcc, 0xc1, 0x3e, 0xae, 0xdb, - 0x1d, 0xd6, 0xc7, 0x04, 0x31, 0xd2, 0x5e, 0x86, 0x5c, 0x12, 0xa7, 0x3f, 0xdf, 0x41, 0x6e, 0x69, - 0xc2, 0x31, 0xf7, 0xe3, 0x21, 0xbd, 0xdb, 0x53, 0x6a, 0x45, 0x5f, 0xb7, 0xb1, 0xaf, 0x65, 0x9b, - 0xb0, 0xbe, 0xfa, 0x88, 0x23, 0x7f, 0x3c, 0xe4, 0x63, 0xeb, 0xc1, 0xea, 0x9f, 0xde, 0x87, 0xba, - 0xba, 0x22, 0x44, 0x7e, 0x0c, 0x2d, 0x23, 0xcf, 0x83, 0xc8, 0x69, 0x14, 0xa5, 0x85, 0xf4, 0x6e, - 0x15, 0x57, 0x8a, 0x8e, 0xef, 0x60, 0xc7, 0x5d, 0xb2, 0xc4, 0x3a, 0x16, 0x89, 0x12, 0x0f, 0x31, - 0x2f, 0x8a, 0xbf, 0x69, 0xf2, 0x4a, 0x3b, 0x71, 0x78, 0x67, 0xb7, 0xb2, 0x87, 0x80, 0xd1, 0xdb, - 0xed, 0x29, 0xb5, 0xa2, 0xbb, 0x5b, 0xd8, 0xdd, 0x12, 0x59, 0xd4, 0xbb, 0x53, 0xd7, 0x76, 0x28, - 0xbe, 0x2b, 0xa4, 0xff, 0xb2, 0x05, 0xb9, 0x9d, 0xbe, 0xfa, 0x52, 0xf0, 0x8b, 0x17, 0x8a, 0x44, - 0xf2, 0x3f, 0x7b, 0x61, 0x77, 0xb1, 0x2b, 0x42, 0x70, 0xfb, 0xf4, 0x1f, 0xb6, 0x20, 0xc7, 0xd0, - 0xd0, 0x1e, 0x80, 0x26, 0x37, 0xa6, 0x3e, 0x56, 0xdd, 0xeb, 0x15, 0x55, 0x15, 0x4d, 0x45, 0x6f, - 0xff, 0x21, 0x53, 0x48, 0x7f, 0x08, 0x75, 0xf5, 0xa4, 0x30, 0x59, 0xd6, 0x9e, 0x78, 0xd6, 0x9f, - 0x40, 0xee, 0x75, 0xf3, 0x15, 0x45, 0xc4, 0xa7, 0xb7, 0xce, 0x88, 0xef, 0x25, 0x34, 0xb4, 0x67, - 0x83, 0xd5, 0x04, 0xf2, 0x4f, 0x13, 0xab, 0x09, 0x14, 0xbc, 0x32, 0x6c, 0xcf, 0x63, 0x17, 0x0d, - 0x52, 0x47, 0xfa, 0x4e, 0x5e, 0x87, 0x31, 0xd9, 0x85, 0xeb, 0xe2, 0x64, 0x3d, 0xa6, 0x5f, 0x64, - 0x1b, 0x0a, 0x7e, 0x4c, 0xe4, 0x91, 0x45, 0x9e, 0x40, 0x4d, 0xbe, 0x0e, 0x4d, 0x96, 0x8a, 0x5f, - 0xb9, 0xee, 0x2d, 0xe7, 0xe0, 0xe2, 0x18, 0xfc, 0x3e, 0x40, 0xfa, 0x46, 0xb1, 0x12, 0x12, 0xb9, - 0x37, 0x8f, 0x15, 0x05, 0xe4, 0x1f, 0x34, 0xb6, 0x97, 0x70, 0x82, 0x1d, 0x82, 0x42, 0x22, 0xa0, - 0x17, 0xf2, 0x51, 0x8b, 0x1f, 0x41, 0x43, 0x7b, 0xa6, 0x58, 0x2d, 0x5f, 0xfe, 0x89, 0x63, 0xb5, - 0x7c, 0x05, 0xaf, 0x1a, 0xdb, 0x3d, 0x6c, 0x7d, 0xd1, 0x9e, 0x63, 0xad, 0xc7, 0xfe, 0x69, 0x30, - 0xe2, 0x08, 0x6c, 0x83, 0xce, 0xa0, 0x65, 0xbc, 0x45, 0xac, 0x38, 0xb4, 0xe8, 0xa5, 0x63, 0xc5, - 0xa1, 0x85, 0xcf, 0x17, 0x4b, 0x3a, 0xb3, 0xe7, 0x59, 0x3f, 0xe7, 0x88, 0xa2, 0xf5, 0xf4, 0x03, - 0x68, 0x68, 0xef, 0x0a, 0xab, 0xb9, 0xe4, 0x9f, 0x30, 0x56, 0x73, 0x29, 0x7a, 0x86, 0x78, 0x11, - 0xfb, 0x68, 0xdb, 0x48, 0x0a, 0xf8, 0x4c, 0x15, 0x6b, 0xfb, 0xc7, 0xd0, 0x36, 0x5f, 0x1a, 0x56, - 0xbc, 0x5f, 0xf8, 0x66, 0xb1, 0xe2, 0xfd, 0x29, 0xcf, 0x13, 0x0b, 0x92, 0x7e, 0xb0, 0xa0, 0x3a, - 0x79, 0xf8, 0x53, 0x71, 0xe3, 0xf9, 0x73, 0xf2, 0x5d, 0x26, 0xe0, 0xc4, 0xf3, 0x69, 0x64, 0x59, - 0xa3, 0x5a, 0xfd, 0x91, 0x35, 0xc5, 0x2f, 0xb9, 0x97, 0xd6, 0x4c, 0x62, 0xe6, 0x0f, 0x6d, 0x3d, - 0x83, 0x05, 0x45, 0xcc, 0xea, 0x39, 0xb4, 0x58, 0xcd, 0xa1, 0xf0, 0xd5, 0xb5, 0x5e, 0x27, 0x5b, - 0xfb, 0xc8, 0xe2, 0xc7, 0x1f, 0x3e, 0x3a, 0xa5, 0x1d, 0x7f, 0xfa, 0x8b, 0x68, 0xda, 0xf1, 0x67, - 0xbc, 0x4d, 0x95, 0x3d, 0xfe, 0x12, 0x9f, 0xb5, 0x11, 0xc0, 0x5c, 0x26, 0x75, 0x56, 0xb1, 0x57, - 0xf1, 0xeb, 0x06, 0xbd, 0x3b, 0x57, 0x67, 0xdc, 0x9a, 0xa2, 0x48, 0x4a, 0xd3, 0x87, 0xf2, 0xe9, - 0x94, 0x3f, 0x80, 0xa6, 0xfe, 0x40, 0x2a, 0xd1, 0x65, 0x42, 0xb6, 0xa7, 0x9b, 0x85, 0x75, 0x26, - 0x95, 0x90, 0xa6, 0xde, 0x0d, 0xf9, 0x1e, 0x2c, 0xa9, 0x65, 0xd6, 0x33, 0x28, 0x63, 0xf2, 0x4e, - 0x41, 0x5e, 0xa5, 0xb1, 0xd8, 0x37, 0xa6, 0x26, 0x5e, 0x3e, 0xb2, 0x18, 0xf5, 0x99, 0x8f, 0x33, - 0xa6, 0x27, 0x4f, 0xd1, 0x9b, 0x94, 0xe9, 0xc9, 0x53, 0xf8, 0xa2, 0xa3, 0xa4, 0x3e, 0xb2, 0x60, - 0xac, 0x11, 0xbf, 0xd8, 0x45, 0x7e, 0x00, 0x73, 0x5a, 0xbe, 0xfb, 0xe1, 0x65, 0xd0, 0x57, 0x9c, - 0x94, 0x7f, 0xdb, 0xa8, 0x57, 0x64, 0x96, 0xda, 0xcb, 0xd8, 0xfe, 0xbc, 0x6d, 0x2c, 0x0e, 0xe3, - 0xa2, 0x0d, 0x68, 0xe8, 0xb9, 0xf4, 0x57, 0xb4, 0xbb, 0xac, 0x55, 0xe9, 0x0f, 0xe7, 0x3c, 0xb2, - 0xc8, 0x2e, 0x74, 0xb2, 0x6f, 0x7c, 0x28, 0x99, 0x52, 0xf4, 0x2e, 0x49, 0x2f, 0x53, 0x69, 0xbc, - 0x0c, 0x42, 0x0e, 0xf8, 0x75, 0x61, 0xf5, 0xab, 0x1b, 0x61, 0x94, 0x3d, 0xd5, 0xcd, 0x5f, 0xe3, - 0x50, 0xad, 0x15, 0xfd, 0x0e, 0xcb, 0x7d, 0xeb, 0x91, 0x45, 0xfe, 0x8e, 0x05, 0x4d, 0x23, 0x73, - 0xde, 0xb8, 0x7c, 0x99, 0x99, 0x67, 0x57, 0xaf, 0xd3, 0x27, 0x6a, 0x3b, 0xb8, 0x88, 0xbb, 0x0f, - 0x3e, 0x31, 0x36, 0xe9, 0xa7, 0x86, 0xa7, 0x77, 0x25, 0xfb, 0xd3, 0x1b, 0x9f, 0x67, 0x11, 0xf4, - 0xf7, 0xa9, 0x3e, 0x7f, 0x64, 0x91, 0x7f, 0x6c, 0x41, 0xdb, 0x8c, 0xed, 0xa8, 0xe9, 0x16, 0x46, - 0x91, 0x14, 0x29, 0x4d, 0x09, 0x08, 0xfd, 0x00, 0x47, 0x79, 0xf4, 0xc0, 0x31, 0x46, 0x29, 0x9e, - 0x15, 0xfd, 0xf5, 0x46, 0x4b, 0x3e, 0xe6, 0xbf, 0x84, 0x25, 0xc3, 0xda, 0x24, 0xff, 0xcb, 0x49, - 0x8a, 0xfc, 0xf4, 0xdf, 0x19, 0xc2, 0x4d, 0xf8, 0x11, 0xff, 0xc9, 0x09, 0x19, 0x1b, 0x65, 0x54, - 0xfc, 0xb6, 0xdf, 0xdb, 0xf7, 0x70, 0x4e, 0x77, 0xec, 0x1b, 0xc6, 0x9c, 0xb2, 0x8a, 0xc7, 0x1a, - 0x1f, 0x9d, 0xf8, 0x89, 0xa0, 0xf4, 0xe4, 0xcc, 0xfd, 0x6c, 0xd0, 0xf4, 0x41, 0x8e, 0xf8, 0x20, - 0x05, 0xba, 0xc1, 0x6a, 0x6f, 0xd9, 0x8c, 0xfd, 0x00, 0xc7, 0x7a, 0xcf, 0x7e, 0x67, 0xea, 0x58, - 0x1f, 0x62, 0x84, 0x86, 0x8d, 0xf8, 0x00, 0x20, 0xbd, 0x86, 0x42, 0x32, 0x57, 0x20, 0x94, 0x00, - 0xca, 0xdf, 0x54, 0x31, 0xf9, 0x59, 0xde, 0x94, 0x60, 0x2d, 0xfe, 0x90, 0x8b, 0xd3, 0x1d, 0x79, - 0x79, 0x42, 0xd7, 0xbe, 0xcc, 0xbb, 0x22, 0x86, 0xf6, 0x95, 0x6d, 0xdf, 0x10, 0xa6, 0xea, 0x26, - 0xc6, 0x0b, 0x68, 0xed, 0x86, 0xe1, 0xab, 0xc9, 0x58, 0xdd, 0x8b, 0x34, 0x83, 0xa7, 0xdb, 0x5e, - 0x7c, 0xd6, 0xcb, 0xcc, 0xc2, 0xbe, 0x8b, 0x4d, 0xf5, 0x48, 0x57, 0x6b, 0xea, 0xe1, 0x4f, 0xd3, - 0x2b, 0x2e, 0x9f, 0x13, 0x0f, 0xe6, 0x95, 0x8c, 0x56, 0x03, 0xef, 0x99, 0xcd, 0x18, 0x92, 0x39, - 0xdb, 0x85, 0x61, 0x26, 0xc8, 0xd1, 0x3e, 0x8c, 0x65, 0x9b, 0x8f, 0x2c, 0x72, 0x00, 0xcd, 0x4d, - 0xda, 0xc7, 0x6c, 0x51, 0x8c, 0x40, 0x2e, 0x18, 0x51, 0x2c, 0x1e, 0xba, 0xec, 0xb5, 0x0c, 0xa0, - 0x79, 0x6e, 0x8d, 0xbd, 0xcb, 0x88, 0x7e, 0xf6, 0xf0, 0xa7, 0x22, 0xb6, 0xf9, 0xb9, 0x3c, 0xb7, - 0x64, 0xf0, 0xd7, 0x38, 0xb7, 0x32, 0xd1, 0x62, 0xe3, 0xdc, 0xca, 0x45, 0x8b, 0x8d, 0xa5, 0x96, - 0xc1, 0x67, 0x32, 0x84, 0xf9, 0x5c, 0x80, 0x59, 0x1d, 0x59, 0xd3, 0xc2, 0xd2, 0xbd, 0xbb, 0xd3, - 0x11, 0xcc, 0xde, 0x1e, 0x98, 0xbd, 0x1d, 0x42, 0x8b, 0xbf, 0x99, 0x75, 0x4c, 0x79, 0x22, 0x48, - 0xe6, 0xf9, 0x05, 0x3d, 0xcd, 0x24, 0x7b, 0xc0, 0x60, 0x9d, 0xa9, 0xe1, 0xf0, 0xc7, 0x37, 0x7f, - 0x08, 0x8d, 0x67, 0x34, 0x91, 0x99, 0x1f, 0x4a, 0xc7, 0xce, 0xa4, 0x82, 0xf4, 0x0a, 0x12, 0x47, - 0x4c, 0x9a, 0xc1, 0xd6, 0x1e, 0xd2, 0xc1, 0x29, 0xe5, 0xc2, 0xc9, 0xf5, 0x07, 0x9f, 0x93, 0xdf, - 0xc7, 0xc6, 0x55, 0x1e, 0xde, 0x92, 0x76, 0x8d, 0x5f, 0x6f, 0x7c, 0x2e, 0x03, 0x2f, 0x6a, 0x39, - 0x08, 0x07, 0x54, 0xd3, 0xf5, 0x02, 0x68, 0x68, 0x79, 0xbc, 0x8a, 0x81, 0xf2, 0x79, 0xdb, 0x8a, - 0x81, 0x0a, 0xd2, 0x7e, 0xed, 0xfb, 0xd8, 0x8f, 0x4d, 0xee, 0xa6, 0xfd, 0xf0, 0x54, 0xdf, 0xb4, - 0xa7, 0x87, 0x3f, 0xf5, 0x46, 0xc9, 0xe7, 0xe4, 0x25, 0xbe, 0x60, 0xab, 0x67, 0xb6, 0xa4, 0x46, - 0x43, 0x36, 0x09, 0x46, 0x2d, 0x96, 0x56, 0x65, 0x1a, 0x12, 0xbc, 0x2b, 0xd4, 0xe4, 0xbe, 0x09, - 0x70, 0x98, 0x84, 0xe3, 0x4d, 0x8f, 0x8e, 0xc2, 0x20, 0x95, 0xb5, 0x69, 0x5e, 0x45, 0x2a, 0xbf, - 0xb4, 0xe4, 0x0a, 0xf2, 0x52, 0xb3, 0xb2, 0x8c, 0xe4, 0x20, 0x49, 0x5c, 0x53, 0x53, 0x2f, 0xd4, - 0x82, 0x14, 0xa4, 0x5f, 0x3c, 0xb2, 0xc8, 0x1a, 0x40, 0x7a, 0xc3, 0x40, 0xd9, 0x4c, 0xb9, 0xcb, - 0x0b, 0x4a, 0xec, 0x15, 0x5c, 0x47, 0x38, 0x80, 0xba, 0x16, 0x8f, 0x4d, 0x9f, 0x25, 0x30, 0xa2, - 0xb7, 0xea, 0x04, 0xcf, 0x05, 0x43, 0xed, 0x0e, 0x2e, 0x15, 0x90, 0x1a, 0x5b, 0x2a, 0x8c, 0x70, - 0xfa, 0xb0, 0xc0, 0x07, 0xa8, 0xd4, 0x25, 0xcc, 0x07, 0x50, 0x0f, 0x15, 0xe7, 0x03, 0x92, 0x8a, - 0x9b, 0x0b, 0xe3, 0x69, 0x86, 0xeb, 0x87, 0x51, 0x2b, 0xcf, 0x45, 0x60, 0xa2, 0x79, 0x04, 0xf3, - 0xb9, 0x10, 0x8d, 0x62, 0xe9, 0x69, 0x31, 0x38, 0xc5, 0xd2, 0x53, 0xa3, 0x3b, 0xf6, 0x75, 0xec, - 0x72, 0xce, 0x06, 0x34, 0xf5, 0x2e, 0xfc, 0xa4, 0x7f, 0xc6, 0xba, 0xfb, 0x23, 0x0b, 0x16, 0x0a, - 0x22, 0x30, 0xe4, 0x5d, 0xe9, 0x35, 0x98, 0x1a, 0x9d, 0xe9, 0x15, 0x3a, 0xe8, 0xed, 0x43, 0xec, - 0xe7, 0x39, 0xf9, 0xd4, 0x38, 0xd8, 0xb8, 0x6f, 0x5c, 0x70, 0xe6, 0x95, 0x4a, 0x45, 0xa1, 0x46, - 0xf1, 0x19, 0x2c, 0xf3, 0x81, 0xac, 0x0d, 0x87, 0x99, 0xe0, 0xc1, 0x9d, 0xdc, 0xaf, 0xe5, 0x1a, - 0x41, 0x91, 0xde, 0xf4, 0x5f, 0xd3, 0x9d, 0xa2, 0x4e, 0xf3, 0xa1, 0x92, 0x09, 0x74, 0xb2, 0x0e, - 0x79, 0x32, 0xbd, 0xad, 0xde, 0x3b, 0x86, 0xfd, 0x5b, 0xe0, 0xc4, 0xff, 0x32, 0x76, 0xf6, 0x8e, - 0xdd, 0x2b, 0x5a, 0x17, 0x6e, 0x12, 0xb3, 0xfd, 0xf8, 0x8b, 0x2a, 0x7a, 0x90, 0x99, 0xa7, 0xec, - 0x60, 0x5a, 0xb8, 0x43, 0x59, 0xe0, 0xc5, 0xc1, 0x87, 0xf7, 0xb0, 0xfb, 0xbb, 0xf6, 0xcd, 0xa2, - 0xee, 0x23, 0xfe, 0x09, 0xb7, 0xc5, 0x97, 0xb3, 0x7c, 0x2d, 0x47, 0x70, 0xb7, 0x68, 0xbf, 0xa7, - 0xda, 0x42, 0x99, 0xb5, 0xbe, 0x86, 0xba, 0x5d, 0x53, 0x8f, 0x16, 0x28, 0xf6, 0x29, 0x08, 0x4b, - 0x28, 0xf6, 0x29, 0x0a, 0x2f, 0x98, 0x7a, 0x8d, 0x0c, 0x2c, 0x7c, 0x6c, 0x3d, 0x58, 0x7f, 0xff, - 0x07, 0x5f, 0x3e, 0xf5, 0x93, 0xb3, 0xc9, 0xf1, 0x4a, 0x3f, 0x1c, 0x3d, 0x1c, 0x4a, 0x6f, 0xa3, - 0xc8, 0x91, 0x7b, 0x38, 0x0c, 0x06, 0x0f, 0xb1, 0xd9, 0xe3, 0x19, 0xfc, 0x79, 0xef, 0xaf, 0xff, - 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x6b, 0xfa, 0x86, 0x10, 0x7c, 0x00, 0x00, + // 9943 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x6c, 0x1c, 0xd9, + 0x95, 0x98, 0xaa, 0x1f, 0x64, 0xf7, 0xe9, 0x07, 0x9b, 0x97, 0x14, 0xd9, 0x6a, 0x3d, 0x46, 0x53, + 0xd6, 0xce, 0xc8, 0xf2, 0x98, 0xd2, 0xd0, 0xf6, 0xac, 0x3c, 0xca, 0x7a, 0xcd, 0x97, 0x44, 0xce, + 0x50, 0x24, 0x5d, 0xa4, 0xac, 0xb5, 0x9d, 0x45, 0xb9, 0xd8, 0x7d, 0x49, 0x96, 0xd5, 0x5d, 0xd5, + 0x53, 0x55, 0x4d, 0x8a, 0x76, 0x26, 0x1f, 0x41, 0x12, 0x04, 0xf9, 0x09, 0x0c, 0x23, 0x40, 0x9e, + 0x58, 0xc0, 0x9b, 0x20, 0x08, 0x02, 0x24, 0x01, 0x02, 0x2c, 0x36, 0x80, 0xf3, 0x95, 0x8f, 0xcd, + 0x4f, 0x90, 0x8f, 0x04, 0x08, 0x90, 0x00, 0x01, 0x16, 0x9b, 0x8f, 0x2c, 0x02, 0xe4, 0x2b, 0xc9, + 0x77, 0x70, 0xcf, 0x7d, 0xd4, 0xbd, 0x55, 0xd5, 0x94, 0xc6, 0x76, 0xfc, 0x23, 0xf1, 0x9e, 0x7b, + 0xea, 0x3e, 0xcf, 0x39, 0xf7, 0x3c, 0xee, 0xb9, 0x0d, 0xf5, 0x68, 0xdc, 0x5f, 0x19, 0x47, 0x61, + 0x12, 0x92, 0xea, 0x30, 0x88, 0xc6, 0xfd, 0xde, 0xad, 0xd3, 0x30, 0x3c, 0x1d, 0xd2, 0x87, 0xde, + 0xd8, 0x7f, 0xe8, 0x05, 0x41, 0x98, 0x78, 0x89, 0x1f, 0x06, 0x31, 0x47, 0xb2, 0x7f, 0x08, 0xed, + 0x67, 0x34, 0x38, 0xa4, 0x74, 0xe0, 0xd0, 0xcf, 0x26, 0x34, 0x4e, 0xc8, 0x57, 0x60, 0xde, 0xa3, + 0x3f, 0xa6, 0x74, 0xe0, 0x8e, 0xbd, 0x38, 0x1e, 0x9f, 0x45, 0x5e, 0x4c, 0xbb, 0xd6, 0x5d, 0xeb, + 0x7e, 0xd3, 0xe9, 0xf0, 0x8a, 0x03, 0x05, 0x27, 0xef, 0x42, 0x33, 0x66, 0xa8, 0x34, 0x48, 0xa2, + 0x70, 0x7c, 0xd9, 0x2d, 0x21, 0x5e, 0x83, 0xc1, 0xb6, 0x38, 0xc8, 0x1e, 0xc2, 0x9c, 0xea, 0x21, + 0x1e, 0x87, 0x41, 0x4c, 0xc9, 0x23, 0x58, 0xec, 0xfb, 0xe3, 0x33, 0x1a, 0xb9, 0xf8, 0xf1, 0x28, + 0xa0, 0xa3, 0x30, 0xf0, 0xfb, 0x5d, 0xeb, 0x6e, 0xf9, 0x7e, 0xdd, 0x21, 0xbc, 0x8e, 0x7d, 0xf1, + 0x5c, 0xd4, 0x90, 0xf7, 0x61, 0x8e, 0x06, 0x1c, 0x4e, 0x07, 0xf8, 0x95, 0xe8, 0xaa, 0x9d, 0x82, + 0xd9, 0x07, 0xf6, 0xdf, 0x28, 0xc1, 0xfc, 0x4e, 0xe0, 0x27, 0x2f, 0xbd, 0xe1, 0x90, 0x26, 0x72, + 0x4e, 0xef, 0xc3, 0xdc, 0x05, 0x02, 0x70, 0x4e, 0x17, 0x61, 0x34, 0x10, 0x33, 0x6a, 0x73, 0xf0, + 0x81, 0x80, 0x4e, 0x1d, 0x59, 0x69, 0xea, 0xc8, 0x0a, 0x97, 0xab, 0x3c, 0x65, 0xb9, 0xde, 0x87, + 0xb9, 0x88, 0xf6, 0xc3, 0x73, 0x1a, 0x5d, 0xba, 0x17, 0x7e, 0x30, 0x08, 0x2f, 0xba, 0x95, 0xbb, + 0xd6, 0xfd, 0xaa, 0xd3, 0x96, 0xe0, 0x97, 0x08, 0x25, 0xeb, 0x30, 0xd7, 0x3f, 0xf3, 0x82, 0x80, + 0x0e, 0xdd, 0x63, 0xaf, 0xff, 0x6a, 0x32, 0x8e, 0xbb, 0xd5, 0xbb, 0xd6, 0xfd, 0xc6, 0xea, 0x8d, + 0x15, 0xdc, 0xd5, 0x95, 0x8d, 0x33, 0x2f, 0x58, 0xc7, 0x9a, 0xc3, 0xc0, 0x1b, 0xc7, 0x67, 0x61, + 0xe2, 0xb4, 0xc5, 0x17, 0x1c, 0x1c, 0xdb, 0x8b, 0x40, 0xf4, 0x95, 0xe0, 0x6b, 0x6f, 0xff, 0x33, + 0x0b, 0x16, 0x5e, 0x04, 0xc3, 0xb0, 0xff, 0xea, 0x97, 0x5c, 0xa2, 0x82, 0x39, 0x94, 0xde, 0x76, + 0x0e, 0xe5, 0x2f, 0x3a, 0x87, 0x25, 0x58, 0x34, 0x07, 0x2b, 0x66, 0x41, 0xe1, 0x3a, 0xfb, 0xfa, + 0x94, 0xca, 0x61, 0xc9, 0x69, 0x7c, 0x19, 0x3a, 0xfd, 0x49, 0x14, 0xd1, 0x20, 0x37, 0x8f, 0x39, + 0x01, 0x57, 0x13, 0x79, 0x17, 0x9a, 0x01, 0xbd, 0x48, 0xd1, 0x04, 0xed, 0x06, 0xf4, 0x42, 0xa2, + 0xd8, 0x5d, 0x58, 0xca, 0x76, 0x23, 0x06, 0xf0, 0xa7, 0x16, 0x54, 0x5e, 0x24, 0xaf, 0x43, 0xb2, + 0x02, 0x95, 0xe4, 0x72, 0xcc, 0x39, 0xa4, 0xbd, 0x4a, 0xc4, 0xd4, 0xd6, 0x06, 0x83, 0x88, 0xc6, + 0xf1, 0xd1, 0xe5, 0x98, 0x3a, 0x4d, 0x8f, 0x17, 0x5c, 0x86, 0x47, 0xba, 0x30, 0x2b, 0xca, 0xd8, + 0x61, 0xdd, 0x91, 0x45, 0x72, 0x07, 0xc0, 0x1b, 0x85, 0x93, 0x20, 0x71, 0x63, 0x2f, 0xc1, 0xa5, + 0x2a, 0x3b, 0x1a, 0x84, 0xdc, 0x82, 0xfa, 0xf8, 0x95, 0x1b, 0xf7, 0x23, 0x7f, 0x9c, 0x20, 0xd9, + 0xd4, 0x9d, 0x14, 0x40, 0xbe, 0x02, 0xb5, 0x70, 0x92, 0x8c, 0x43, 0x3f, 0x48, 0x04, 0xa9, 0xcc, + 0x89, 0xb1, 0xec, 0x4f, 0x92, 0x03, 0x06, 0x76, 0x14, 0x02, 0xb9, 0x07, 0xad, 0x7e, 0x18, 0x9c, + 0xf8, 0xd1, 0x88, 0x0b, 0x83, 0xee, 0x0c, 0xf6, 0x66, 0x02, 0xed, 0x7f, 0x5d, 0x82, 0xc6, 0x51, + 0xe4, 0x05, 0xb1, 0xd7, 0x67, 0x00, 0x36, 0xf4, 0xe4, 0xb5, 0x7b, 0xe6, 0xc5, 0x67, 0x38, 0xdb, + 0xba, 0x23, 0x8b, 0x64, 0x09, 0x66, 0xf8, 0x40, 0x71, 0x4e, 0x65, 0x47, 0x94, 0xc8, 0x07, 0x30, + 0x1f, 0x4c, 0x46, 0xae, 0xd9, 0x57, 0x19, 0xa9, 0x25, 0x5f, 0xc1, 0x16, 0xe0, 0x98, 0xed, 0x35, + 0xef, 0x82, 0xcf, 0x50, 0x83, 0x10, 0x1b, 0x9a, 0xa2, 0x44, 0xfd, 0xd3, 0x33, 0x3e, 0xcd, 0xaa, + 0x63, 0xc0, 0x58, 0x1b, 0x89, 0x3f, 0xa2, 0x6e, 0x9c, 0x78, 0xa3, 0xb1, 0x98, 0x96, 0x06, 0xc1, + 0xfa, 0x30, 0xf1, 0x86, 0xee, 0x09, 0xa5, 0x71, 0x77, 0x56, 0xd4, 0x2b, 0x08, 0x79, 0x0f, 0xda, + 0x03, 0x1a, 0x27, 0xae, 0xd8, 0x14, 0x1a, 0x77, 0x6b, 0xc8, 0xfa, 0x19, 0x28, 0x6b, 0x27, 0xf2, + 0x2e, 0x5c, 0xb6, 0x00, 0xf4, 0x75, 0xb7, 0xce, 0xc7, 0x9a, 0x42, 0x18, 0xe5, 0x3c, 0xa3, 0x89, + 0xb6, 0x7a, 0xb1, 0xa0, 0x50, 0x7b, 0x17, 0x88, 0x06, 0xde, 0xa4, 0x89, 0xe7, 0x0f, 0x63, 0xf2, + 0x11, 0x34, 0x13, 0x0d, 0x19, 0x45, 0x61, 0x43, 0x91, 0x93, 0xf6, 0x81, 0x63, 0xe0, 0xd9, 0x67, + 0x50, 0x7b, 0x4a, 0xe9, 0xae, 0x3f, 0xf2, 0x13, 0xb2, 0x04, 0xd5, 0x13, 0xff, 0x35, 0xe5, 0x04, + 0x5f, 0xde, 0xbe, 0xe6, 0xf0, 0x22, 0x79, 0x07, 0x00, 0xff, 0x70, 0x47, 0x8a, 0xb0, 0xb6, 0xaf, + 0x39, 0x75, 0x84, 0x3d, 0x67, 0x94, 0xd5, 0x83, 0xd9, 0x31, 0x8d, 0xfa, 0x54, 0xee, 0xdf, 0xf6, + 0x35, 0x47, 0x02, 0xd6, 0x67, 0xa1, 0x3a, 0x64, 0xad, 0xdb, 0x7f, 0x52, 0x85, 0xc6, 0x21, 0x0d, + 0x14, 0xa7, 0x11, 0xa8, 0xb0, 0x35, 0x11, 0xdc, 0x85, 0x7f, 0x93, 0x2f, 0x41, 0x03, 0xd7, 0x29, + 0x4e, 0x22, 0x3f, 0x38, 0xe5, 0x04, 0xbe, 0x5e, 0xea, 0x5a, 0x0e, 0x30, 0xf0, 0x21, 0x42, 0x49, + 0x07, 0xca, 0xde, 0x48, 0x12, 0x38, 0xfb, 0x93, 0xdc, 0x80, 0x9a, 0x37, 0x4a, 0xf8, 0xf0, 0x9a, + 0x08, 0x9e, 0xf5, 0x46, 0x09, 0x0e, 0xed, 0x5d, 0x68, 0x8e, 0xbd, 0xcb, 0x11, 0xe3, 0x67, 0x45, + 0x15, 0x4d, 0xa7, 0x21, 0x60, 0xdb, 0x8c, 0x2c, 0x56, 0x61, 0x41, 0x47, 0x91, 0x9d, 0x57, 0x55, + 0xe7, 0xf3, 0x1a, 0xb6, 0x18, 0xc3, 0xfb, 0x30, 0x27, 0xbf, 0x89, 0xf8, 0x7c, 0x90, 0x56, 0xea, + 0x4e, 0x5b, 0x80, 0xe5, 0x2c, 0xef, 0x43, 0xe7, 0xc4, 0x0f, 0xbc, 0xa1, 0xdb, 0x1f, 0x26, 0xe7, + 0xee, 0x80, 0x0e, 0x13, 0x0f, 0xa9, 0xa6, 0xea, 0xb4, 0x11, 0xbe, 0x31, 0x4c, 0xce, 0x37, 0x19, + 0x94, 0x7c, 0x00, 0xf5, 0x13, 0x4a, 0x5d, 0x5c, 0xac, 0x6e, 0xcd, 0xe0, 0x40, 0xb9, 0x43, 0x4e, + 0xed, 0x44, 0xee, 0xd5, 0x07, 0xd0, 0x09, 0x27, 0xc9, 0x69, 0xe8, 0x07, 0xa7, 0x2e, 0x93, 0x79, + 0xae, 0x3f, 0x40, 0x2a, 0xaa, 0xac, 0x97, 0x1e, 0x59, 0x4e, 0x5b, 0xd6, 0x31, 0xe9, 0xb3, 0x33, + 0x20, 0xef, 0xc1, 0xdc, 0xd0, 0x8b, 0x13, 0xf7, 0x2c, 0x1c, 0xbb, 0xe3, 0xc9, 0xf1, 0x2b, 0x7a, + 0xd9, 0x6d, 0xe1, 0x42, 0xb4, 0x18, 0x78, 0x3b, 0x1c, 0x1f, 0x20, 0x90, 0xdc, 0x06, 0xc0, 0x71, + 0xf2, 0x41, 0xc0, 0x5d, 0xeb, 0x7e, 0xcb, 0xa9, 0x33, 0x08, 0xef, 0xf4, 0x7b, 0xb0, 0x80, 0xdb, + 0xd3, 0x9f, 0xc4, 0x49, 0x38, 0x72, 0x99, 0xbc, 0x8e, 0x06, 0x71, 0xb7, 0x81, 0xb4, 0xf6, 0x65, + 0x31, 0x58, 0x6d, 0x8f, 0x57, 0x36, 0x69, 0x9c, 0x6c, 0x20, 0xb2, 0xc3, 0x71, 0xd9, 0xa1, 0x7e, + 0xe9, 0xcc, 0x0f, 0xb2, 0x70, 0xf2, 0x01, 0x10, 0x6f, 0x38, 0x0c, 0x2f, 0xdc, 0x98, 0x0e, 0x4f, + 0x5c, 0xb1, 0x88, 0xdd, 0xf6, 0x5d, 0xeb, 0x7e, 0xcd, 0xe9, 0x60, 0xcd, 0x21, 0x1d, 0x9e, 0x1c, + 0x70, 0x38, 0xf9, 0x08, 0x5a, 0x38, 0x90, 0x13, 0xea, 0x25, 0x93, 0x88, 0xc6, 0xdd, 0xb9, 0xbb, + 0xe5, 0xfb, 0xed, 0xd5, 0x79, 0xb5, 0x5e, 0x08, 0x5e, 0xf7, 0x13, 0xa7, 0xc9, 0xf0, 0x44, 0x39, + 0xee, 0x6d, 0xc2, 0x52, 0xf1, 0x90, 0x18, 0x51, 0xb1, 0x55, 0x61, 0xc4, 0x58, 0x71, 0xd8, 0x9f, + 0x64, 0x11, 0xaa, 0xe7, 0xde, 0x70, 0x42, 0x85, 0x5c, 0xe7, 0x85, 0x8f, 0x4b, 0x8f, 0x2d, 0xfb, + 0x8f, 0x2d, 0x68, 0xf2, 0x59, 0x0a, 0x7d, 0xe4, 0x1e, 0xb4, 0x24, 0x35, 0xd0, 0x28, 0x0a, 0x23, + 0x21, 0xde, 0x4c, 0x20, 0x79, 0x00, 0x1d, 0x09, 0x18, 0x47, 0xd4, 0x1f, 0x79, 0xa7, 0xb2, 0xed, + 0x1c, 0x9c, 0xac, 0xa6, 0x2d, 0x46, 0xe1, 0x24, 0xa1, 0xe2, 0xe4, 0x6b, 0x8a, 0x09, 0x3a, 0x0c, + 0xe6, 0x98, 0x28, 0x4c, 0xbc, 0x15, 0x90, 0xba, 0x01, 0xb3, 0xff, 0xb6, 0x05, 0x84, 0x0d, 0xfd, + 0x28, 0xe4, 0x4d, 0x08, 0x2a, 0xcd, 0x72, 0x89, 0xf5, 0xd6, 0x5c, 0x52, 0xba, 0x8a, 0x4b, 0x6c, + 0xa8, 0xf2, 0xd1, 0x57, 0x0a, 0x46, 0xcf, 0xab, 0x3e, 0xa9, 0xd4, 0xca, 0x9d, 0x8a, 0xfd, 0x5f, + 0xca, 0xb0, 0xb8, 0xc1, 0x8f, 0xee, 0xb5, 0x7e, 0x9f, 0x8e, 0x15, 0xff, 0xbc, 0x03, 0x8d, 0x20, + 0x1c, 0x50, 0x49, 0xb5, 0x7c, 0x60, 0xc0, 0x40, 0x1a, 0xc9, 0x9e, 0x79, 0x7e, 0xc0, 0x07, 0xce, + 0xd7, 0xb3, 0x8e, 0x10, 0x1c, 0xf6, 0x7b, 0x30, 0x37, 0xa6, 0xc1, 0x40, 0x67, 0x13, 0xae, 0x5c, + 0xb5, 0x04, 0x58, 0x70, 0xc8, 0x3b, 0xd0, 0x38, 0x99, 0x70, 0x3c, 0x26, 0x5c, 0x2a, 0x48, 0x07, + 0x20, 0x40, 0x6b, 0x5c, 0xc6, 0x8c, 0x27, 0xf1, 0x19, 0xd6, 0x56, 0xb1, 0x76, 0x96, 0x95, 0x59, + 0xd5, 0x6d, 0x80, 0xc1, 0x24, 0x4e, 0x04, 0xd7, 0xcc, 0x60, 0x65, 0x9d, 0x41, 0x38, 0xd7, 0x7c, + 0x15, 0x16, 0x46, 0xde, 0x6b, 0x17, 0xe9, 0xc7, 0xf5, 0x03, 0xf7, 0x64, 0x88, 0xa7, 0xcf, 0x2c, + 0xe2, 0x75, 0x46, 0xde, 0xeb, 0xef, 0xb2, 0x9a, 0x9d, 0xe0, 0x29, 0xc2, 0x99, 0x68, 0x91, 0x6a, + 0x4f, 0x44, 0x63, 0x1a, 0x9d, 0x53, 0x94, 0x06, 0x15, 0xa5, 0xdb, 0x38, 0x1c, 0xca, 0x46, 0x34, + 0x62, 0xf3, 0x4e, 0x86, 0x7d, 0xce, 0xfa, 0xce, 0xec, 0xc8, 0x0f, 0xb6, 0x93, 0x61, 0x9f, 0xdc, + 0x02, 0x60, 0xb2, 0x64, 0x4c, 0x23, 0xf7, 0xd5, 0x05, 0xf2, 0x71, 0x05, 0x65, 0xc7, 0x01, 0x8d, + 0x3e, 0xbd, 0x20, 0x37, 0xa1, 0xde, 0x8f, 0x51, 0x18, 0x79, 0x97, 0xdd, 0x06, 0x32, 0x79, 0xad, + 0x1f, 0x33, 0x31, 0xe4, 0x5d, 0x32, 0x46, 0x64, 0xa3, 0xf5, 0x70, 0x17, 0xe8, 0x00, 0x9b, 0x8f, + 0x51, 0xaa, 0xb6, 0x70, 0xb0, 0x6b, 0xa2, 0x82, 0xf5, 0x13, 0x93, 0x2f, 0x41, 0x4b, 0x0e, 0xf6, + 0x64, 0xe8, 0x9d, 0xc6, 0x28, 0x56, 0x5a, 0x4e, 0x53, 0x00, 0x9f, 0x32, 0x98, 0xfd, 0x92, 0x2b, + 0x5b, 0xda, 0xde, 0x0a, 0xbe, 0x61, 0xc7, 0x3e, 0x42, 0x70, 0x5f, 0x6b, 0x8e, 0x28, 0x15, 0x6d, + 0x5a, 0xa9, 0x60, 0xd3, 0xec, 0x9f, 0x5b, 0xd0, 0x14, 0x2d, 0xa3, 0x86, 0x42, 0x1e, 0x01, 0x91, + 0xbb, 0x98, 0xbc, 0xf6, 0x07, 0xee, 0xf1, 0x65, 0x42, 0x63, 0x4e, 0x34, 0xdb, 0xd7, 0x9c, 0x82, + 0x3a, 0x26, 0x47, 0x0d, 0x68, 0x9c, 0x44, 0x9c, 0xa6, 0xb7, 0xaf, 0x39, 0xb9, 0x1a, 0xc6, 0x62, + 0x4c, 0x07, 0x9a, 0x24, 0xae, 0x1f, 0x0c, 0xe8, 0x6b, 0x24, 0xa5, 0x96, 0x63, 0xc0, 0xd6, 0xdb, + 0xd0, 0xd4, 0xbf, 0xb3, 0x7f, 0x04, 0x35, 0xa9, 0x41, 0xa1, 0xf6, 0x90, 0x19, 0x97, 0xa3, 0x41, + 0x48, 0x0f, 0x6a, 0xe6, 0x28, 0x9c, 0xda, 0x17, 0xe9, 0xdb, 0xfe, 0x16, 0x74, 0x76, 0x19, 0x11, + 0x05, 0x8c, 0x68, 0x85, 0x5a, 0xb8, 0x04, 0x33, 0x1a, 0xf3, 0xd4, 0x1d, 0x51, 0x62, 0xe7, 0xef, + 0x59, 0x18, 0x27, 0xa2, 0x1f, 0xfc, 0xdb, 0xfe, 0x13, 0x0b, 0xc8, 0x56, 0x9c, 0xf8, 0x23, 0x2f, + 0xa1, 0x4f, 0xa9, 0x12, 0x0f, 0xfb, 0xd0, 0x64, 0xad, 0x1d, 0x85, 0x6b, 0x5c, 0x49, 0xe3, 0xca, + 0xc5, 0x57, 0x04, 0x3b, 0xe7, 0x3f, 0x58, 0xd1, 0xb1, 0xb9, 0xc8, 0x37, 0x1a, 0x60, 0xdc, 0x96, + 0x78, 0xd1, 0x29, 0x4d, 0x50, 0x83, 0x13, 0xfa, 0x3f, 0x70, 0xd0, 0x46, 0x18, 0x9c, 0xf4, 0x7e, + 0x17, 0xe6, 0x73, 0x6d, 0xe8, 0x32, 0xba, 0x5e, 0x20, 0xa3, 0xcb, 0xba, 0x8c, 0xee, 0xc3, 0x82, + 0x31, 0x2e, 0x41, 0x71, 0x5d, 0x98, 0x65, 0x8c, 0xc1, 0x14, 0x05, 0x8b, 0x2b, 0x0a, 0xa2, 0x48, + 0x56, 0x61, 0xf1, 0x84, 0xd2, 0xc8, 0x4b, 0xb0, 0x88, 0xac, 0xc3, 0xf6, 0x44, 0xb4, 0x5c, 0x58, + 0x67, 0xff, 0x99, 0x05, 0x73, 0x4c, 0x9a, 0x3e, 0xf7, 0x82, 0x4b, 0xb9, 0x56, 0xbb, 0x85, 0x6b, + 0x75, 0x5f, 0x3b, 0x1c, 0x35, 0xec, 0x2f, 0xba, 0x50, 0xe5, 0xec, 0x42, 0x91, 0xbb, 0xd0, 0x34, + 0x86, 0x5b, 0xe5, 0x1a, 0x69, 0xec, 0x25, 0x07, 0x34, 0x5a, 0xbf, 0x4c, 0xe8, 0xaf, 0xbe, 0x94, + 0xef, 0x41, 0x27, 0x1d, 0xb6, 0x58, 0x47, 0x02, 0x15, 0x46, 0x98, 0xa2, 0x01, 0xfc, 0xdb, 0xfe, + 0x07, 0x16, 0x47, 0xdc, 0x08, 0x7d, 0xa5, 0xad, 0x32, 0x44, 0xa6, 0xf4, 0x4a, 0x44, 0xf6, 0xf7, + 0x54, 0x6d, 0xff, 0x57, 0x9f, 0x2c, 0x93, 0x89, 0x31, 0x0d, 0x06, 0xae, 0x37, 0x1c, 0xa2, 0x20, + 0xae, 0x39, 0xb3, 0xac, 0xbc, 0x36, 0x1c, 0xda, 0xef, 0xc3, 0xbc, 0x36, 0xba, 0x2b, 0xe6, 0xb1, + 0x07, 0x64, 0xd7, 0x8f, 0x93, 0x17, 0x41, 0x3c, 0xd6, 0x14, 0xb9, 0x9b, 0x50, 0x67, 0xd2, 0x96, + 0x8d, 0x8c, 0x73, 0x6e, 0xd5, 0x61, 0xe2, 0x97, 0x8d, 0x2b, 0xc6, 0x4a, 0xef, 0xb5, 0xa8, 0x2c, + 0x89, 0x4a, 0xef, 0x35, 0x56, 0xda, 0x8f, 0x61, 0xc1, 0x68, 0x4f, 0x74, 0xfd, 0x2e, 0x54, 0x27, + 0xc9, 0xeb, 0x50, 0xaa, 0xea, 0x0d, 0x41, 0x21, 0xcc, 0x28, 0x74, 0x78, 0x8d, 0xfd, 0x04, 0xe6, + 0xf7, 0xe8, 0x85, 0x60, 0x64, 0x39, 0x90, 0xf7, 0xde, 0x68, 0x30, 0x62, 0xbd, 0xbd, 0x02, 0x44, + 0xff, 0x38, 0x65, 0x00, 0x69, 0x3e, 0x5a, 0x86, 0xf9, 0x68, 0xbf, 0x07, 0xe4, 0xd0, 0x3f, 0x0d, + 0x9e, 0xd3, 0x38, 0xf6, 0x4e, 0x15, 0xeb, 0x77, 0xa0, 0x3c, 0x8a, 0x4f, 0x85, 0xa8, 0x62, 0x7f, + 0xda, 0x5f, 0x83, 0x05, 0x03, 0x4f, 0x34, 0x7c, 0x0b, 0xea, 0xb1, 0x7f, 0x1a, 0xa0, 0xa2, 0x25, + 0x9a, 0x4e, 0x01, 0xf6, 0x53, 0x58, 0xfc, 0x2e, 0x8d, 0xfc, 0x93, 0xcb, 0x37, 0x35, 0x6f, 0xb6, + 0x53, 0xca, 0xb6, 0xb3, 0x05, 0xd7, 0x33, 0xed, 0x88, 0xee, 0x39, 0xf9, 0x8a, 0x9d, 0xac, 0x39, + 0xbc, 0xa0, 0xc9, 0xbe, 0x92, 0x2e, 0xfb, 0xec, 0x17, 0x40, 0x36, 0xc2, 0x20, 0xa0, 0xfd, 0xe4, + 0x80, 0xd2, 0x28, 0xf5, 0x5c, 0xa5, 0xb4, 0xda, 0x58, 0x5d, 0x16, 0x2b, 0x9b, 0x15, 0xa8, 0x82, + 0x88, 0x09, 0x54, 0xc6, 0x34, 0x1a, 0x61, 0xc3, 0x35, 0x07, 0xff, 0xb6, 0xaf, 0xc3, 0x82, 0xd1, + 0xac, 0xb0, 0xf5, 0x3f, 0x84, 0xeb, 0x9b, 0x7e, 0xdc, 0xcf, 0x77, 0xd8, 0x85, 0xd9, 0xf1, 0xe4, + 0xd8, 0x4d, 0x39, 0x51, 0x16, 0x99, 0xf9, 0x97, 0xfd, 0x44, 0x34, 0xf6, 0xd7, 0x2d, 0xa8, 0x6c, + 0x1f, 0xed, 0x6e, 0xb0, 0xb3, 0xc2, 0x0f, 0xfa, 0xe1, 0x88, 0x69, 0x61, 0x7c, 0xd2, 0xaa, 0x3c, + 0x95, 0xc3, 0x6e, 0x41, 0x1d, 0x95, 0x37, 0x66, 0xf1, 0x0a, 0x3d, 0x28, 0x05, 0x30, 0x6b, 0x9b, + 0xbe, 0x1e, 0xfb, 0x11, 0x9a, 0xd3, 0xd2, 0x48, 0xae, 0xe0, 0x31, 0x93, 0xaf, 0xb0, 0xff, 0xdd, + 0x2c, 0xcc, 0x8a, 0xc3, 0x97, 0x1f, 0xe4, 0x89, 0x7f, 0x4e, 0xd3, 0x83, 0x9c, 0x95, 0x98, 0x62, + 0x1c, 0xd1, 0x51, 0x98, 0x28, 0xfd, 0x8d, 0x6f, 0x83, 0x09, 0x44, 0x6f, 0x82, 0x50, 0x22, 0xb8, + 0xff, 0xa1, 0xcc, 0xb1, 0x0c, 0x20, 0xb9, 0x05, 0xb3, 0x52, 0x19, 0xa8, 0x28, 0x43, 0x47, 0x82, + 0xd8, 0x6a, 0xf4, 0xbd, 0xb1, 0xd7, 0xf7, 0x93, 0x4b, 0x21, 0x16, 0x54, 0x99, 0xb5, 0x3f, 0x0c, + 0xfb, 0xde, 0xd0, 0x3d, 0xf6, 0x86, 0x5e, 0xd0, 0xa7, 0xd2, 0x5b, 0x61, 0x00, 0x99, 0xe5, 0x2e, + 0x86, 0x25, 0xd1, 0xb8, 0x75, 0x9f, 0x81, 0xb2, 0x33, 0xbc, 0x1f, 0x8e, 0x46, 0x3e, 0xb3, 0x3e, + 0xb8, 0x6a, 0x56, 0x76, 0x34, 0x08, 0xf7, 0x8d, 0x60, 0xe9, 0x82, 0xaf, 0x60, 0x5d, 0xfa, 0x46, + 0x34, 0x20, 0x6b, 0x25, 0xa3, 0xa1, 0x95, 0x1d, 0x0d, 0xc2, 0xf6, 0x62, 0x12, 0xc4, 0x34, 0x49, + 0x86, 0x74, 0xa0, 0x06, 0xd4, 0x40, 0xb4, 0x7c, 0x05, 0x79, 0x04, 0x0b, 0xdc, 0x07, 0x11, 0x7b, + 0x49, 0x18, 0x9f, 0xf9, 0xb1, 0x1b, 0x33, 0xf3, 0x89, 0xdb, 0xc2, 0x45, 0x55, 0xe4, 0x31, 0x2c, + 0x67, 0xc0, 0x11, 0xed, 0x53, 0xff, 0x9c, 0x0e, 0x50, 0x85, 0x2b, 0x3b, 0xd3, 0xaa, 0xc9, 0x5d, + 0x68, 0x04, 0x93, 0x91, 0x3b, 0x19, 0x0f, 0x3c, 0xa6, 0xc4, 0xb4, 0x51, 0xb9, 0xd4, 0x41, 0xe4, + 0x43, 0x90, 0x7a, 0x9a, 0xd0, 0x1e, 0xe7, 0x0c, 0x09, 0xc7, 0xa8, 0xd7, 0x31, 0x31, 0x18, 0x61, + 0xa6, 0x2a, 0x69, 0x47, 0xd8, 0x9d, 0x12, 0x80, 0x7c, 0x12, 0xf9, 0xe7, 0x5e, 0x42, 0xbb, 0xf3, + 0x5c, 0xa8, 0x8b, 0x22, 0xfb, 0xce, 0x0f, 0xfc, 0xc4, 0xf7, 0x92, 0x30, 0xea, 0x12, 0xac, 0x4b, + 0x01, 0x6c, 0x11, 0x91, 0x3e, 0xe2, 0xc4, 0x4b, 0x26, 0xb1, 0xd0, 0x50, 0x17, 0x90, 0xb8, 0xf2, + 0x15, 0xe4, 0x23, 0x58, 0xe2, 0x14, 0x81, 0x55, 0x42, 0xf7, 0x46, 0x55, 0x61, 0x11, 0x57, 0x64, + 0x4a, 0x2d, 0x5b, 0x4a, 0x41, 0x22, 0xb9, 0x0f, 0xaf, 0xf3, 0xa5, 0x9c, 0x52, 0xcd, 0xc6, 0xc7, + 0x46, 0xe0, 0xf7, 0x5d, 0x81, 0xc1, 0x58, 0x64, 0x09, 0x67, 0x91, 0xaf, 0x60, 0x24, 0x3e, 0xf4, + 0x4f, 0x68, 0xe2, 0x8f, 0x68, 0x77, 0x99, 0x93, 0xb8, 0x2c, 0x33, 0x06, 0x9c, 0x8c, 0xb1, 0xa6, + 0xcb, 0x19, 0x9e, 0x97, 0x90, 0x18, 0x87, 0x61, 0x4c, 0xa5, 0xe7, 0xa9, 0x7b, 0x43, 0xb0, 0x96, + 0x0e, 0xb4, 0xff, 0x95, 0xc5, 0x8f, 0x28, 0xc1, 0xce, 0xb1, 0x66, 0x7c, 0x71, 0x46, 0x76, 0xc3, + 0x60, 0x78, 0x29, 0x78, 0x1b, 0x38, 0x68, 0x3f, 0x18, 0x5e, 0x32, 0xf5, 0xdf, 0x0f, 0x74, 0x14, + 0x2e, 0x0d, 0x9b, 0x12, 0x88, 0x48, 0xef, 0x40, 0x63, 0x3c, 0x39, 0x1e, 0xfa, 0x7d, 0x8e, 0x52, + 0xe6, 0xad, 0x70, 0x10, 0x22, 0x30, 0xeb, 0x93, 0xef, 0x27, 0xc7, 0xa8, 0x20, 0x46, 0x43, 0xc0, + 0x10, 0x05, 0xa5, 0x2d, 0x8d, 0x90, 0xb5, 0x9b, 0x0e, 0xfe, 0x6d, 0xaf, 0xc3, 0xa2, 0x39, 0x68, + 0x71, 0x14, 0x3c, 0x80, 0x9a, 0x90, 0x1c, 0xd2, 0x35, 0xd1, 0xd6, 0x1c, 0xc6, 0xcc, 0x80, 0x52, + 0xf5, 0xf6, 0xcf, 0x66, 0x60, 0x41, 0x40, 0x37, 0xd8, 0x92, 0x1c, 0x4e, 0x46, 0x23, 0x2f, 0x2a, + 0x10, 0x49, 0xd6, 0x1b, 0x44, 0x52, 0x29, 0x2f, 0x92, 0xee, 0x18, 0x96, 0x29, 0x97, 0x69, 0x1a, + 0x84, 0xdc, 0x87, 0x39, 0xb6, 0x0d, 0xdc, 0x50, 0xd0, 0x7d, 0x96, 0x59, 0x70, 0x5e, 0x8c, 0x56, + 0x8b, 0xc4, 0xa8, 0x2e, 0x02, 0x67, 0x32, 0x22, 0xd0, 0x86, 0x26, 0xdf, 0x72, 0x21, 0xd5, 0x67, + 0x85, 0x99, 0xa6, 0xc1, 0xd8, 0x78, 0xb2, 0x02, 0x87, 0x4b, 0xb7, 0xb9, 0x22, 0x71, 0xe3, 0x8f, + 0x28, 0x9e, 0x1a, 0x1a, 0x76, 0x5d, 0x88, 0x9b, 0x7c, 0x15, 0x79, 0x0a, 0xc0, 0xfb, 0x42, 0xd5, + 0x05, 0x50, 0x75, 0x79, 0xcf, 0xdc, 0x15, 0x7d, 0xfd, 0x57, 0x58, 0x61, 0x12, 0x51, 0x54, 0x67, + 0xb4, 0x2f, 0xc9, 0x2e, 0xb4, 0xc3, 0x31, 0x0d, 0xdc, 0x94, 0xe9, 0x1b, 0xd8, 0xd6, 0xbd, 0x2b, + 0xda, 0xda, 0x91, 0xb8, 0x4e, 0xe6, 0x5b, 0xb2, 0xc7, 0x77, 0x80, 0x6a, 0xcd, 0x35, 0xbf, 0x40, + 0x73, 0xd9, 0x8f, 0xed, 0xbf, 0x69, 0x41, 0x43, 0x1b, 0x39, 0xb9, 0x0e, 0xf3, 0x1b, 0xfb, 0xfb, + 0x07, 0x5b, 0xce, 0xda, 0xd1, 0xce, 0x77, 0xb7, 0xdc, 0x8d, 0xdd, 0xfd, 0xc3, 0xad, 0xce, 0x35, + 0x06, 0xde, 0xdd, 0xdf, 0x58, 0xdb, 0x75, 0x9f, 0xee, 0x3b, 0x1b, 0x12, 0x6c, 0x91, 0x25, 0x20, + 0xce, 0xd6, 0xf3, 0xfd, 0xa3, 0x2d, 0x03, 0x5e, 0x22, 0x1d, 0x68, 0xae, 0x3b, 0x5b, 0x6b, 0x1b, + 0xdb, 0x02, 0x52, 0x26, 0x8b, 0xd0, 0x79, 0xfa, 0x62, 0x6f, 0x73, 0x67, 0xef, 0x99, 0xbb, 0xb1, + 0xb6, 0xb7, 0xb1, 0xb5, 0xbb, 0xb5, 0xd9, 0xa9, 0x90, 0x16, 0xd4, 0xd7, 0xd6, 0xd7, 0xf6, 0x36, + 0xf7, 0xf7, 0xb6, 0x36, 0x3b, 0x55, 0xfb, 0x9b, 0x50, 0x57, 0x43, 0x25, 0x0d, 0x98, 0x7d, 0xb1, + 0xf7, 0xe9, 0xde, 0xfe, 0xcb, 0xbd, 0xce, 0x35, 0x52, 0x87, 0x2a, 0xf6, 0xdf, 0xb1, 0x08, 0xc0, + 0x0c, 0xef, 0xb3, 0x53, 0x22, 0x35, 0xa8, 0xac, 0xef, 0x1f, 0x6d, 0x77, 0xca, 0xf6, 0x7f, 0xb3, + 0xe0, 0x3a, 0xce, 0x79, 0x90, 0x95, 0x08, 0x77, 0xa1, 0xd1, 0x0f, 0xc3, 0x31, 0xb3, 0x85, 0xd2, + 0xd3, 0x5e, 0x07, 0x31, 0x6e, 0xe7, 0x72, 0xf2, 0x24, 0x8c, 0xfa, 0x54, 0x08, 0x04, 0x40, 0xd0, + 0x53, 0x06, 0x61, 0xdc, 0x2e, 0xe8, 0x96, 0x63, 0x70, 0x79, 0xd0, 0xe0, 0x30, 0x8e, 0xb2, 0x04, + 0x33, 0xc7, 0x11, 0xf5, 0xfa, 0x67, 0x42, 0x14, 0x88, 0x12, 0xf9, 0x72, 0x6a, 0xac, 0xf7, 0x19, + 0x59, 0x0d, 0xe9, 0x00, 0x59, 0xa1, 0xe6, 0xcc, 0x09, 0xf8, 0x86, 0x00, 0xb3, 0x83, 0xc1, 0x3b, + 0xf6, 0x82, 0x41, 0x18, 0xd0, 0x81, 0xb0, 0x04, 0x52, 0x80, 0x7d, 0x00, 0x4b, 0xd9, 0xf9, 0x09, + 0xe1, 0xf1, 0x91, 0x26, 0x3c, 0xb8, 0x62, 0xde, 0x9b, 0x4e, 0x0b, 0x9a, 0x20, 0xf9, 0xb3, 0x32, + 0x54, 0x98, 0x9e, 0x36, 0x5d, 0xa7, 0xd3, 0x55, 0xef, 0x72, 0x2e, 0x72, 0x83, 0xf6, 0x3f, 0x3f, + 0xb5, 0x85, 0xef, 0x29, 0x85, 0xa4, 0xf5, 0x11, 0xed, 0x9f, 0x0b, 0xef, 0x93, 0x06, 0x61, 0x9c, + 0xcf, 0xec, 0x22, 0xfc, 0x5a, 0x70, 0xbe, 0x2c, 0xcb, 0x3a, 0xfc, 0x72, 0x36, 0xad, 0xc3, 0xef, + 0xba, 0x30, 0xeb, 0x07, 0xc7, 0xe1, 0x24, 0x18, 0x20, 0xa7, 0xd7, 0x1c, 0x59, 0xc4, 0x58, 0x11, + 0x4a, 0x20, 0x76, 0xa4, 0x70, 0xbe, 0x4e, 0x01, 0x64, 0x15, 0xea, 0xf1, 0x65, 0xd0, 0xd7, 0x99, + 0x79, 0x51, 0xac, 0x12, 0x5b, 0x83, 0x95, 0xc3, 0xcb, 0xa0, 0x8f, 0xac, 0x9b, 0xa2, 0x91, 0x6f, + 0x40, 0x4d, 0x79, 0x6b, 0xb9, 0x54, 0xbe, 0xa1, 0x7f, 0x22, 0x5d, 0xb4, 0xdc, 0x08, 0x56, 0xa8, + 0xbd, 0x4f, 0xa1, 0x65, 0x54, 0xe9, 0x96, 0x6b, 0x8b, 0x5b, 0xae, 0xf7, 0x74, 0xcb, 0x35, 0x15, + 0xf6, 0xe2, 0x33, 0xdd, 0x92, 0xfd, 0x5d, 0xa8, 0xc9, 0xa1, 0x31, 0xae, 0x12, 0x1c, 0xe1, 0x1e, + 0x7e, 0x6f, 0x6f, 0xa3, 0x73, 0x8d, 0xcc, 0x41, 0x63, 0x6d, 0x03, 0x19, 0x15, 0x01, 0x16, 0x43, + 0x39, 0x58, 0x3b, 0x3c, 0x54, 0x90, 0x92, 0x4d, 0xa0, 0xc3, 0x8e, 0x1c, 0x36, 0x62, 0x15, 0x8f, + 0xf9, 0x08, 0xe6, 0x35, 0x58, 0x6a, 0xdc, 0xb1, 0x33, 0x2a, 0x6b, 0xdc, 0xa1, 0x26, 0xcf, 0x6b, + 0xec, 0x65, 0xb8, 0xce, 0x8a, 0x5b, 0xe7, 0x34, 0x48, 0x0e, 0x27, 0xc7, 0x3c, 0x0c, 0xe7, 0x87, + 0x81, 0xfd, 0xd7, 0x2c, 0xa8, 0xab, 0x9a, 0x2b, 0xe8, 0x49, 0x46, 0x0e, 0x4b, 0xb8, 0x01, 0x3d, + 0xad, 0x0b, 0xfc, 0x72, 0x05, 0xff, 0x35, 0x0c, 0xc2, 0xba, 0x02, 0xb1, 0xc9, 0x1e, 0x6c, 0x6d, + 0x39, 0xee, 0xfe, 0xde, 0xee, 0xce, 0x1e, 0x13, 0x4a, 0x6c, 0xb2, 0x08, 0x78, 0xfa, 0x14, 0x21, + 0x96, 0xdd, 0x81, 0xf6, 0x33, 0x9a, 0xec, 0x04, 0x27, 0xa1, 0x9c, 0xea, 0xff, 0xad, 0xc2, 0x9c, + 0x02, 0xa5, 0x06, 0xe5, 0x39, 0x8d, 0x62, 0x3f, 0x0c, 0x50, 0x15, 0xac, 0x3b, 0xb2, 0xc8, 0xce, + 0x13, 0x7f, 0x40, 0x83, 0xc4, 0x4f, 0x2e, 0x5d, 0xc3, 0x03, 0x95, 0x05, 0x33, 0xe3, 0xcd, 0x1b, + 0xfa, 0x9e, 0x8c, 0x68, 0xf2, 0x02, 0x83, 0xf6, 0xc3, 0x61, 0x18, 0xa1, 0xce, 0x57, 0x77, 0x78, + 0x81, 0xac, 0xc2, 0x22, 0xd3, 0x35, 0x75, 0xff, 0x20, 0x32, 0x2b, 0x77, 0x87, 0x15, 0xd6, 0xb1, + 0xf3, 0x8a, 0xc1, 0x85, 0xa2, 0xa2, 0x3e, 0xe1, 0xa6, 0x4d, 0x51, 0x15, 0xf9, 0x3a, 0x5c, 0x67, + 0x60, 0xa5, 0xdc, 0xa8, 0x6f, 0xe6, 0xf0, 0x9b, 0xe2, 0x4a, 0xc6, 0x35, 0xbc, 0x7f, 0xb6, 0xf3, + 0x55, 0xae, 0xc5, 0x2a, 0x40, 0x2e, 0xfc, 0x38, 0xc3, 0xcf, 0xe0, 0x6c, 0xf8, 0x51, 0x0b, 0x61, + 0xd6, 0x72, 0x21, 0xcc, 0xaf, 0xc3, 0xf5, 0x63, 0x1a, 0x27, 0xee, 0x19, 0xf5, 0x06, 0x34, 0x42, + 0x6e, 0xe4, 0x91, 0x4a, 0xae, 0xb4, 0x17, 0x57, 0xe2, 0xc9, 0x7e, 0x19, 0xf4, 0xe9, 0xc0, 0x4d, + 0x42, 0x17, 0x35, 0x10, 0xe4, 0xe9, 0x9a, 0x93, 0x05, 0x9b, 0x98, 0xa7, 0x91, 0x37, 0x3e, 0x13, + 0x5a, 0x75, 0x16, 0xcc, 0x74, 0x9f, 0x84, 0xc6, 0x49, 0x40, 0x79, 0x9c, 0xa8, 0x86, 0x31, 0x00, + 0x09, 0x22, 0xf7, 0x60, 0x06, 0x1b, 0x8c, 0xbb, 0x1d, 0x64, 0x80, 0x66, 0x2a, 0x44, 0xfd, 0xc0, + 0x11, 0x75, 0x4c, 0xab, 0x9b, 0x44, 0x7e, 0xdc, 0x6d, 0x62, 0x88, 0x14, 0xff, 0x26, 0xdf, 0xd6, + 0xe4, 0xc4, 0x02, 0x7e, 0x2b, 0x0f, 0xe3, 0x0c, 0xe5, 0xfd, 0x46, 0x44, 0xc6, 0x27, 0x95, 0x5a, + 0xa3, 0xd3, 0xb4, 0x7f, 0x1b, 0xaa, 0x38, 0x72, 0xa4, 0x49, 0x5c, 0x3f, 0x4b, 0xd0, 0x24, 0x42, + 0xbb, 0x30, 0x1b, 0xd0, 0xe4, 0x22, 0x8c, 0x5e, 0xc9, 0x98, 0xbc, 0x28, 0xda, 0x3f, 0x46, 0x47, + 0x83, 0x8a, 0x51, 0xbf, 0x40, 0x0b, 0x89, 0xdc, 0x84, 0x3a, 0xdf, 0xd3, 0xf8, 0xcc, 0x13, 0xbe, + 0x8f, 0x1a, 0x02, 0x0e, 0xcf, 0x3c, 0x76, 0x3e, 0x1a, 0x64, 0xc2, 0xdd, 0x49, 0x0d, 0x84, 0x6d, + 0x73, 0x2a, 0xb9, 0x07, 0x6d, 0x19, 0xfd, 0x8e, 0xdd, 0x21, 0x3d, 0x49, 0xa4, 0x33, 0x38, 0x98, + 0x8c, 0xd0, 0xe7, 0xb4, 0x4b, 0x4f, 0x12, 0x7b, 0x0f, 0xe6, 0xc5, 0x99, 0xb5, 0x3f, 0xa6, 0xb2, + 0xeb, 0x6f, 0x16, 0x29, 0xb6, 0x8d, 0xd5, 0x05, 0xf3, 0x90, 0xe3, 0xf1, 0x7e, 0x13, 0xd3, 0x76, + 0x80, 0xe8, 0x67, 0xa0, 0x68, 0x50, 0x68, 0x96, 0xd2, 0xdd, 0x2d, 0xa6, 0x63, 0xc0, 0xd8, 0xfa, + 0xc4, 0x93, 0x7e, 0x5f, 0xde, 0x59, 0xa8, 0x39, 0xb2, 0x68, 0xff, 0x27, 0x0b, 0x16, 0xb0, 0x35, + 0xa9, 0x9a, 0x0b, 0x3d, 0xe3, 0xf1, 0x17, 0x18, 0xa6, 0x0c, 0x36, 0x70, 0x17, 0xfb, 0x22, 0x54, + 0x75, 0xcd, 0x83, 0x17, 0xbe, 0xb8, 0x6b, 0xb1, 0x92, 0x73, 0x2d, 0x3e, 0x80, 0xce, 0x80, 0x0e, + 0x7d, 0xbc, 0xb7, 0x22, 0xcf, 0x71, 0xae, 0x87, 0xe7, 0xe0, 0xf6, 0xdf, 0xb1, 0x60, 0x9e, 0x2b, + 0x0a, 0x68, 0x60, 0x8a, 0xa5, 0xfa, 0x0b, 0xd2, 0x18, 0x13, 0x02, 0x4a, 0x4c, 0x2a, 0x3d, 0x3a, + 0x11, 0xca, 0x91, 0xb7, 0xaf, 0x39, 0x26, 0x32, 0x79, 0x82, 0xe6, 0x44, 0xe0, 0x22, 0xb4, 0xe0, + 0x26, 0x8c, 0xb9, 0x2f, 0xdb, 0xd7, 0x1c, 0x0d, 0x7d, 0xbd, 0xc6, 0xec, 0x43, 0x06, 0xb7, 0x9f, + 0x41, 0xcb, 0xe8, 0xc8, 0x70, 0x81, 0x36, 0xb9, 0x0b, 0x34, 0x17, 0x6b, 0x28, 0x15, 0xc4, 0x1a, + 0x7e, 0x56, 0x01, 0xc2, 0x08, 0x2b, 0xb3, 0x73, 0x77, 0xcd, 0x80, 0x9d, 0xbc, 0x14, 0x93, 0x82, + 0xc8, 0x2a, 0x10, 0xad, 0x28, 0x03, 0x89, 0x65, 0x15, 0x48, 0x2c, 0xa8, 0x65, 0x52, 0x5f, 0x68, + 0x95, 0x2a, 0x48, 0x87, 0xee, 0x2d, 0xbe, 0x4d, 0x85, 0x75, 0x4c, 0xf3, 0xc1, 0x88, 0x1d, 0x33, + 0xc4, 0x85, 0x4b, 0x48, 0x96, 0xb3, 0xf4, 0x30, 0xf3, 0x46, 0x7a, 0x98, 0xcd, 0xd1, 0x83, 0xe6, + 0x94, 0xa8, 0x99, 0x4e, 0x89, 0x7b, 0xd0, 0x92, 0x81, 0x39, 0x7e, 0x27, 0x41, 0x78, 0x80, 0x0c, + 0x20, 0xa3, 0x27, 0xe9, 0x17, 0x50, 0x9e, 0x0f, 0x1e, 0x71, 0xcf, 0xc1, 0xd9, 0xc1, 0x92, 0x3a, + 0x9f, 0x1b, 0x38, 0xd8, 0x14, 0x80, 0x6e, 0x04, 0x46, 0x25, 0xee, 0x24, 0x10, 0x17, 0x62, 0xe8, + 0x00, 0x0d, 0x99, 0x9a, 0x93, 0xaf, 0xc8, 0xbb, 0x04, 0x5a, 0x05, 0x2e, 0x01, 0xf2, 0x51, 0x1a, + 0xc5, 0x8a, 0xcf, 0xfc, 0x11, 0x9e, 0xed, 0xe9, 0x7d, 0x92, 0xa7, 0xbc, 0xea, 0xf0, 0xcc, 0x1f, + 0x39, 0x06, 0x9e, 0xfd, 0x0b, 0x0b, 0x3a, 0x8c, 0x2a, 0x0c, 0xc2, 0xff, 0x18, 0x90, 0x47, 0xdf, + 0x92, 0xee, 0x0d, 0x5c, 0xf2, 0x18, 0xea, 0x58, 0x66, 0xa6, 0x9b, 0xa0, 0xfa, 0xae, 0x49, 0xf5, + 0xa9, 0x74, 0xdb, 0xbe, 0xe6, 0xa4, 0xc8, 0xec, 0x2c, 0xcb, 0x46, 0x11, 0x79, 0x48, 0x3c, 0x0b, + 0xd6, 0xb8, 0x63, 0x1b, 0xe0, 0x53, 0x7a, 0xb9, 0x1b, 0xf6, 0xd1, 0x6a, 0xba, 0x0d, 0xc0, 0x68, + 0xf0, 0xc4, 0x1b, 0xf9, 0xc2, 0xfd, 0x51, 0x75, 0xea, 0xaf, 0xe8, 0xe5, 0x53, 0x04, 0x30, 0x31, + 0xce, 0xaa, 0x53, 0x16, 0xa9, 0x3a, 0xb5, 0x57, 0xf4, 0x72, 0x07, 0xd9, 0xc3, 0x85, 0xd6, 0xa7, + 0xf4, 0x72, 0x93, 0x72, 0xbd, 0x2e, 0x8c, 0x88, 0x0d, 0xad, 0xc8, 0xbb, 0x60, 0x9a, 0x9b, 0x11, + 0xfe, 0x6b, 0x44, 0xde, 0xc5, 0xa7, 0xf4, 0x72, 0x1d, 0xe3, 0x7f, 0x0f, 0x60, 0x96, 0xd5, 0x0f, + 0xc3, 0xbe, 0x38, 0x99, 0xe4, 0x8d, 0x86, 0x74, 0x50, 0xce, 0xcc, 0x2b, 0xfc, 0xdb, 0xfe, 0x0f, + 0x16, 0xb4, 0xd8, 0x0a, 0xa0, 0xd8, 0x63, 0x3b, 0x21, 0x2f, 0xc6, 0x58, 0xe9, 0xc5, 0x98, 0x55, + 0x21, 0x33, 0xb8, 0x0c, 0x2d, 0x4d, 0x97, 0xa1, 0xb8, 0x6c, 0x5c, 0x80, 0x7e, 0x08, 0x75, 0xce, + 0x4e, 0x8c, 0x7d, 0xcb, 0xc6, 0x4e, 0x19, 0x13, 0x72, 0x6a, 0x88, 0xf6, 0x29, 0x8f, 0xc1, 0x6b, + 0x0e, 0x2c, 0xbe, 0xc8, 0x75, 0x0e, 0x61, 0xd5, 0x05, 0xe1, 0xdc, 0x6a, 0x51, 0x38, 0xf7, 0x05, + 0x34, 0x34, 0xc2, 0x22, 0xdf, 0xe2, 0x81, 0x70, 0x3e, 0x78, 0x4e, 0x85, 0x26, 0xe1, 0x18, 0xb3, + 0x47, 0x81, 0xa9, 0x03, 0xd6, 0x67, 0xa0, 0x82, 0x24, 0xf9, 0x04, 0xe6, 0xb5, 0x66, 0xb9, 0x85, + 0x58, 0x34, 0x26, 0xab, 0x68, 0x4c, 0x7f, 0xd7, 0x82, 0x45, 0xf1, 0x35, 0x5e, 0xa2, 0xf2, 0xd9, + 0x31, 0xfe, 0x3c, 0x3e, 0x65, 0x07, 0x29, 0x6b, 0xdd, 0x8d, 0xe8, 0xa9, 0x1f, 0x27, 0x54, 0x46, + 0x0d, 0x0a, 0x38, 0x84, 0x91, 0x34, 0x43, 0x75, 0x04, 0x26, 0x79, 0x02, 0x0d, 0xfc, 0x94, 0xdb, + 0xb0, 0x62, 0x5b, 0xba, 0xf9, 0x0f, 0xf9, 0x50, 0x99, 0x24, 0x8f, 0x55, 0x69, 0xbd, 0x0e, 0xb3, + 0x49, 0xe4, 0x9f, 0x9e, 0xd2, 0xc8, 0x5e, 0x52, 0x43, 0x63, 0xdc, 0x46, 0x0f, 0x13, 0x3a, 0x66, + 0xca, 0x11, 0xa3, 0x8c, 0x86, 0x60, 0xaa, 0x5f, 0x3a, 0x52, 0xd0, 0xd3, 0xae, 0x03, 0x72, 0x6b, + 0x35, 0xbd, 0xfd, 0x77, 0x1f, 0xe6, 0x46, 0x4c, 0x51, 0x62, 0x1a, 0xbc, 0x11, 0x25, 0xc8, 0x82, + 0x99, 0xe2, 0x8d, 0x7a, 0x4b, 0xec, 0x26, 0xfe, 0xd0, 0x95, 0xb5, 0xe2, 0xe2, 0x5d, 0x51, 0x15, + 0x3b, 0xbe, 0xe3, 0xc4, 0x3b, 0xa5, 0x42, 0x3b, 0xe6, 0x05, 0xbb, 0x0b, 0x4b, 0x07, 0xe9, 0xb6, + 0x68, 0x0e, 0x09, 0xfb, 0x5f, 0xb4, 0x60, 0x39, 0x57, 0xa5, 0xae, 0x09, 0x0b, 0xd7, 0xf7, 0xd0, + 0x1f, 0x1d, 0x87, 0xca, 0x4d, 0x65, 0xe9, 0x5e, 0x71, 0xa3, 0x8a, 0x9c, 0xc2, 0x75, 0x49, 0x15, + 0xe8, 0x2a, 0x52, 0x6a, 0x7f, 0x09, 0x35, 0xd1, 0x0f, 0x4d, 0x89, 0x95, 0xed, 0x50, 0xc2, 0xf5, + 0x53, 0xb1, 0xb8, 0x3d, 0x72, 0x06, 0x5d, 0x45, 0x7e, 0x42, 0x53, 0xd2, 0x2c, 0x19, 0xd6, 0xd7, + 0x07, 0x6f, 0xe8, 0xcb, 0xf0, 0x5f, 0x38, 0x53, 0x5b, 0x23, 0x97, 0x70, 0x47, 0xd6, 0xa1, 0x2a, + 0x94, 0xef, 0xaf, 0xf2, 0x56, 0x73, 0x43, 0xcf, 0x8c, 0xd9, 0xe9, 0x1b, 0x1a, 0x26, 0x3f, 0x82, + 0xa5, 0x0b, 0xcf, 0x4f, 0xe4, 0xb0, 0x34, 0x2b, 0xaa, 0x8a, 0x5d, 0xae, 0xbe, 0xa1, 0xcb, 0x97, + 0xfc, 0x63, 0x43, 0x3f, 0x9c, 0xd2, 0x62, 0xef, 0x17, 0x25, 0x68, 0x9b, 0xed, 0x30, 0x32, 0x15, + 0x52, 0x49, 0x2a, 0x14, 0xd2, 0xfe, 0xcc, 0x80, 0xf3, 0xde, 0xde, 0x52, 0x91, 0xb7, 0x57, 0xf7, + 0xaf, 0x96, 0xdf, 0x14, 0x62, 0xaa, 0xbc, 0x5d, 0x88, 0xa9, 0x5a, 0x18, 0x62, 0x9a, 0x1e, 0x89, + 0x98, 0xf9, 0x65, 0x23, 0x11, 0xb3, 0x57, 0x46, 0x22, 0x7a, 0xff, 0xc7, 0x02, 0x92, 0xa7, 0x5e, + 0xf2, 0x8c, 0x3b, 0xb8, 0x03, 0x3a, 0x14, 0xe2, 0xed, 0xab, 0x6f, 0xc7, 0x01, 0x72, 0xb7, 0xe4, + 0xd7, 0x8c, 0x15, 0xf5, 0xbb, 0xba, 0xba, 0x6d, 0xd3, 0x72, 0x8a, 0xaa, 0x32, 0x61, 0xb6, 0xca, + 0x9b, 0xc3, 0x6c, 0xd5, 0x37, 0x87, 0xd9, 0x66, 0xb2, 0x61, 0xb6, 0xde, 0x5f, 0xb5, 0x60, 0xa1, + 0x80, 0xcc, 0x7e, 0x7d, 0x13, 0x67, 0x84, 0x61, 0x48, 0x9f, 0x92, 0x20, 0x0c, 0x1d, 0xd8, 0xfb, + 0x4b, 0xd0, 0x32, 0x58, 0xeb, 0xd7, 0xd7, 0x7f, 0xd6, 0x3c, 0xe3, 0x94, 0x6d, 0xc0, 0x7a, 0xff, + 0xb3, 0x04, 0x24, 0xcf, 0xde, 0xbf, 0xd1, 0x31, 0xe4, 0xd7, 0xa9, 0x5c, 0xb0, 0x4e, 0xff, 0x5f, + 0x4f, 0x9e, 0x0f, 0x60, 0x5e, 0x24, 0x20, 0x68, 0x21, 0x0d, 0x4e, 0x31, 0xf9, 0x0a, 0x66, 0xa0, + 0x9a, 0x31, 0xce, 0x9a, 0x71, 0xe1, 0x5a, 0x3b, 0x7e, 0x33, 0xa1, 0x4e, 0xbb, 0x07, 0x5d, 0xb1, + 0x42, 0x79, 0xd7, 0xdf, 0xdf, 0xaf, 0x28, 0x1b, 0x1b, 0x2b, 0x85, 0xfe, 0xfc, 0x75, 0x68, 0xea, + 0xc7, 0x87, 0xd8, 0x8e, 0x4c, 0x54, 0x8b, 0xa9, 0x19, 0x3a, 0x16, 0xd9, 0x84, 0x36, 0x0a, 0xc9, + 0x81, 0xfa, 0x8e, 0x6b, 0x1a, 0x57, 0x38, 0xb4, 0xb7, 0xaf, 0x39, 0x99, 0x6f, 0xc8, 0xef, 0x40, + 0xdb, 0x74, 0x73, 0x09, 0x9d, 0xb0, 0x48, 0x8d, 0x64, 0x9f, 0x9b, 0xc8, 0x64, 0x0d, 0x3a, 0x59, + 0x3f, 0x99, 0xb8, 0x0d, 0x3a, 0xa5, 0x81, 0x1c, 0x3a, 0xf9, 0x04, 0x16, 0x8b, 0x0e, 0x51, 0xdc, + 0x9b, 0xe9, 0x56, 0x44, 0xe1, 0x37, 0xe4, 0xb1, 0xf0, 0x99, 0x56, 0x8b, 0xc2, 0x3c, 0xda, 0x92, + 0xaf, 0xf0, 0xff, 0x34, 0xef, 0xe9, 0x39, 0x40, 0x0a, 0x23, 0x1d, 0x68, 0xee, 0x1f, 0x6c, 0xed, + 0xb9, 0x1b, 0xdb, 0x6b, 0x7b, 0x7b, 0x5b, 0xbb, 0x9d, 0x6b, 0x84, 0x40, 0x1b, 0xc3, 0x33, 0x9b, + 0x0a, 0x66, 0x31, 0x98, 0xf0, 0x28, 0x4b, 0x58, 0x89, 0x2c, 0x42, 0x67, 0x67, 0x2f, 0x03, 0x2d, + 0x93, 0x2e, 0x2c, 0x1e, 0x6c, 0xf1, 0x88, 0x8e, 0xd1, 0x6e, 0x85, 0xe9, 0x7b, 0x62, 0xf0, 0x4c, + 0xdf, 0xe3, 0x69, 0x2c, 0xeb, 0x9c, 0x08, 0xa5, 0x0e, 0xf4, 0x0f, 0x2d, 0xb8, 0x9e, 0xa9, 0x48, + 0x2f, 0x26, 0x73, 0x35, 0xc7, 0xd4, 0x7d, 0x4c, 0x20, 0x86, 0xc9, 0xa5, 0x79, 0x98, 0x91, 0x53, + 0xf9, 0x0a, 0xc6, 0x59, 0x9a, 0x39, 0x99, 0xe1, 0xd7, 0xa2, 0x2a, 0x7b, 0x59, 0xdd, 0xff, 0xcc, + 0x0c, 0xfc, 0x84, 0xa7, 0xc7, 0xe8, 0x15, 0xa9, 0x57, 0xd9, 0x1c, 0xb2, 0x2c, 0x92, 0xd5, 0x0c, + 0x35, 0x98, 0xe3, 0x2d, 0xac, 0xb3, 0xff, 0xf9, 0x0c, 0x90, 0xef, 0x4c, 0x68, 0x74, 0x89, 0x37, + 0x8f, 0x55, 0x30, 0x6b, 0x39, 0xeb, 0x5a, 0x9f, 0x19, 0x4f, 0x8e, 0x99, 0xc1, 0x22, 0x0c, 0xa9, + 0xd2, 0x5b, 0x65, 0x18, 0x14, 0xdd, 0xf0, 0xaf, 0xbc, 0xf9, 0x86, 0x7f, 0xf5, 0x4d, 0x37, 0xfc, + 0xbf, 0x04, 0x2d, 0xff, 0x34, 0x08, 0x99, 0xd0, 0x61, 0x8a, 0x4a, 0xdc, 0x9d, 0xb9, 0x5b, 0xbe, + 0xdf, 0x74, 0x9a, 0x02, 0xb8, 0xc7, 0x60, 0xe4, 0x49, 0x8a, 0x44, 0x07, 0xa7, 0x98, 0x91, 0xa2, + 0x8b, 0xa1, 0xad, 0xc1, 0x29, 0x15, 0x76, 0x23, 0xba, 0x56, 0xe4, 0xc7, 0x0c, 0x1e, 0x93, 0x7b, + 0xd0, 0x8e, 0xc3, 0x09, 0x53, 0xdd, 0xe4, 0x32, 0x70, 0x87, 0x73, 0x93, 0x43, 0x0f, 0xf8, 0x62, + 0xac, 0xc0, 0xc2, 0x24, 0xa6, 0xee, 0xc8, 0x8f, 0x63, 0x76, 0x3c, 0xf7, 0xc3, 0x20, 0x89, 0xc2, + 0xa1, 0x70, 0x20, 0xcf, 0x4f, 0x62, 0xfa, 0x9c, 0xd7, 0x6c, 0xf0, 0x0a, 0xf2, 0xf5, 0x74, 0x48, + 0x63, 0xcf, 0x8f, 0xe2, 0x2e, 0xe0, 0x90, 0xe4, 0x4c, 0xd9, 0xb8, 0x0f, 0x3c, 0x3f, 0x52, 0x63, + 0x61, 0x85, 0x38, 0x93, 0x79, 0xd0, 0xc8, 0x66, 0x1e, 0xfc, 0xb0, 0x38, 0xf3, 0xa0, 0x85, 0x4d, + 0x3f, 0x12, 0x4d, 0xe7, 0xb7, 0xf8, 0x0b, 0x25, 0x20, 0xe4, 0x13, 0x2a, 0xda, 0x5f, 0x24, 0xa1, + 0x62, 0xae, 0x28, 0xa1, 0xe2, 0x43, 0x68, 0xe0, 0x35, 0x77, 0xf7, 0xcc, 0x0f, 0x12, 0xe9, 0x0c, + 0xef, 0xe8, 0xf7, 0xe0, 0xb7, 0x99, 0xf9, 0x0d, 0x91, 0xfc, 0x33, 0xce, 0xe7, 0x36, 0xcc, 0xff, + 0x06, 0x73, 0x1b, 0xc4, 0x75, 0xfc, 0x15, 0xa8, 0xc9, 0x7d, 0x22, 0x04, 0x2a, 0x27, 0x51, 0x38, + 0x92, 0xfe, 0x41, 0xf6, 0x37, 0x69, 0x43, 0x29, 0x09, 0xc5, 0xc7, 0xa5, 0x24, 0xb4, 0x7f, 0x1f, + 0x1a, 0x1a, 0xa9, 0x91, 0x77, 0xb9, 0xdb, 0x81, 0xa9, 0xce, 0xc2, 0xae, 0xe6, 0xab, 0x58, 0x17, + 0xd0, 0x9d, 0x01, 0xf9, 0x0a, 0xcc, 0x0f, 0xfc, 0x88, 0x62, 0x16, 0x92, 0x1b, 0xd1, 0x73, 0x1a, + 0xc5, 0xd2, 0x65, 0xdb, 0x51, 0x15, 0x0e, 0x87, 0xdb, 0x2e, 0x2c, 0x18, 0x7b, 0xab, 0xa4, 0xdb, + 0x0c, 0xae, 0x9b, 0x8c, 0xb2, 0x99, 0xf9, 0x05, 0xa2, 0x8e, 0x69, 0x1f, 0xc2, 0xdb, 0xec, 0x8e, + 0xa3, 0xf0, 0x18, 0x3b, 0xb1, 0x1c, 0x03, 0x66, 0xff, 0x8f, 0x32, 0x94, 0xb7, 0xc3, 0xb1, 0x7e, + 0xa1, 0xc3, 0xca, 0x5f, 0xe8, 0x10, 0x66, 0x82, 0xab, 0xac, 0x00, 0xa1, 0xcb, 0x19, 0x40, 0xf2, + 0x00, 0xda, 0x4c, 0x54, 0x24, 0x21, 0x33, 0x8b, 0x2e, 0xbc, 0x88, 0x27, 0x1c, 0x94, 0x91, 0xff, + 0x32, 0x35, 0x64, 0x11, 0xca, 0x4a, 0xbb, 0x45, 0x04, 0x56, 0x64, 0x36, 0x39, 0x5e, 0xb7, 0xbb, + 0x14, 0x31, 0x24, 0x51, 0x62, 0x92, 0xd7, 0xfc, 0x9e, 0xcb, 0x23, 0xae, 0xa3, 0x14, 0x55, 0x31, + 0x93, 0x85, 0x49, 0x9c, 0x51, 0x6a, 0x01, 0xa8, 0xb2, 0x1e, 0x58, 0xac, 0x99, 0x81, 0xc5, 0xbb, + 0xd0, 0x48, 0x86, 0xe7, 0xee, 0xd8, 0xbb, 0x1c, 0x86, 0xde, 0x40, 0x70, 0xba, 0x0e, 0x22, 0x8f, + 0x00, 0x46, 0xe3, 0xb1, 0x60, 0x43, 0xf4, 0x5a, 0xa6, 0x54, 0xfd, 0xfc, 0xe0, 0x80, 0x53, 0x9f, + 0xa3, 0xe1, 0x90, 0x2d, 0x68, 0x17, 0x66, 0x0d, 0xdd, 0x96, 0x97, 0xc2, 0xc2, 0xf1, 0x4a, 0x01, + 0xa3, 0x66, 0x3e, 0xea, 0x7d, 0x1b, 0xc8, 0xaf, 0x98, 0xbc, 0xf3, 0x12, 0xea, 0x6a, 0x84, 0x7a, + 0xca, 0x0c, 0xde, 0xfc, 0x6c, 0x98, 0x29, 0x33, 0x78, 0xd1, 0xf3, 0x3d, 0x68, 0xf3, 0xe3, 0x52, + 0x1d, 0x00, 0xfc, 0xb6, 0x5e, 0x06, 0x6a, 0xff, 0xb9, 0x05, 0x55, 0xa4, 0x3c, 0xa6, 0xa5, 0xf2, + 0x3a, 0x75, 0x13, 0x46, 0xc4, 0x9e, 0xb2, 0x60, 0x62, 0x1b, 0xd9, 0x84, 0x25, 0x45, 0x06, 0x7a, + 0x46, 0xe1, 0x5d, 0xa8, 0xab, 0x9e, 0x34, 0x52, 0x4a, 0x81, 0xe4, 0x0e, 0x54, 0xce, 0xc2, 0xb1, + 0x34, 0xe4, 0x21, 0x5d, 0x51, 0x07, 0xe1, 0xe9, 0x78, 0x58, 0x7b, 0x7c, 0x0a, 0xdc, 0x58, 0xca, + 0x82, 0x0b, 0xe6, 0x3a, 0x53, 0x38, 0xd7, 0x17, 0x30, 0xc7, 0xe4, 0x83, 0x16, 0x1b, 0x9e, 0x7e, + 0x98, 0x7e, 0x99, 0x69, 0x80, 0xfd, 0xe1, 0x64, 0x40, 0x75, 0x77, 0x0a, 0xc6, 0x14, 0x05, 0x5c, + 0x1a, 0x12, 0xf6, 0xbf, 0xb4, 0xb8, 0xdc, 0x61, 0xed, 0x92, 0xfb, 0x50, 0x61, 0xe7, 0x5e, 0xc6, + 0xe7, 0xa7, 0x6e, 0xe3, 0x32, 0x3c, 0x07, 0x31, 0xd8, 0x2e, 0x62, 0x38, 0x4c, 0x6f, 0x9d, 0x07, + 0xc3, 0x52, 0x5f, 0x84, 0x9a, 0x59, 0xc6, 0x84, 0xcf, 0x40, 0xc9, 0x8a, 0x76, 0xff, 0xa3, 0x62, + 0x9c, 0xa5, 0x52, 0x49, 0x1c, 0x9c, 0x52, 0xed, 0xde, 0xc7, 0x1f, 0x95, 0xa0, 0x65, 0x8c, 0x89, + 0x71, 0x0f, 0x1e, 0x0d, 0xdc, 0xa3, 0x2c, 0x76, 0x5e, 0x07, 0xe9, 0x9c, 0x57, 0x32, 0x39, 0x4f, + 0x05, 0xc2, 0xcb, 0x7a, 0x20, 0xfc, 0x11, 0xd4, 0xd3, 0x74, 0x52, 0x73, 0x50, 0xac, 0x47, 0x79, + 0x2f, 0x39, 0x45, 0x4a, 0x43, 0xe7, 0x55, 0x3d, 0x74, 0xfe, 0x2d, 0x2d, 0xb4, 0x3a, 0x83, 0xcd, + 0xd8, 0x45, 0xab, 0xfa, 0x9b, 0xb9, 0x8b, 0xf1, 0x04, 0x1a, 0xda, 0xe0, 0xf5, 0x10, 0xaa, 0x65, + 0x84, 0x50, 0x55, 0x06, 0x41, 0x29, 0xcd, 0x20, 0xb0, 0x7f, 0x5a, 0x82, 0x16, 0xe3, 0x35, 0x3f, + 0x38, 0x3d, 0x08, 0x87, 0x7e, 0xff, 0x12, 0x69, 0x5c, 0xb2, 0x95, 0x50, 0xc2, 0x24, 0xcf, 0x99, + 0x60, 0x26, 0x13, 0x55, 0xda, 0x14, 0x17, 0xe0, 0xaa, 0xcc, 0x24, 0x3c, 0x93, 0x8f, 0xc7, 0x5e, + 0x4c, 0xb5, 0x64, 0x57, 0xc7, 0x04, 0x32, 0x39, 0xcc, 0x00, 0x98, 0x0f, 0x32, 0xf2, 0x87, 0x43, + 0x9f, 0xe3, 0x72, 0x1f, 0x45, 0x51, 0x15, 0xeb, 0x73, 0xe0, 0xc7, 0xde, 0x71, 0x7a, 0x61, 0x49, + 0x95, 0x31, 0x5a, 0xe4, 0xbd, 0xd6, 0xa2, 0x45, 0x3c, 0x81, 0xcc, 0x04, 0x66, 0xa9, 0x6a, 0x36, + 0x47, 0x55, 0xf6, 0xbf, 0x2d, 0x41, 0x43, 0xa3, 0x51, 0x26, 0x5b, 0x0a, 0x0f, 0x61, 0x0d, 0x2a, + 0xae, 0x28, 0x06, 0x86, 0xd7, 0x4b, 0x83, 0x90, 0x7b, 0x66, 0xaf, 0x18, 0x65, 0x46, 0xe9, 0x63, + 0xd0, 0xf3, 0x2d, 0xa8, 0x33, 0x3e, 0xfc, 0x10, 0x5d, 0x6c, 0x22, 0xb1, 0x5c, 0x01, 0x64, 0xed, + 0x2a, 0xd6, 0x56, 0xd3, 0x5a, 0x04, 0x5c, 0x79, 0x69, 0xf1, 0x31, 0x34, 0x45, 0x33, 0xb8, 0xc7, + 0x38, 0xe9, 0x54, 0x12, 0x18, 0xfb, 0xef, 0x18, 0x98, 0xf2, 0xcb, 0x55, 0xf9, 0x65, 0xed, 0x4d, + 0x5f, 0x4a, 0x4c, 0xfb, 0x99, 0xba, 0x0f, 0xfa, 0x2c, 0xf2, 0xc6, 0x67, 0x52, 0xba, 0x3d, 0x82, + 0x05, 0x29, 0xc4, 0x26, 0x81, 0x17, 0x04, 0xe1, 0x24, 0xe8, 0x53, 0x99, 0x6c, 0x50, 0x54, 0x65, + 0x0f, 0x54, 0x6a, 0x1a, 0x36, 0x44, 0x1e, 0x40, 0x95, 0xab, 0xf1, 0x5c, 0x57, 0x29, 0x96, 0x67, + 0x1c, 0x85, 0xdc, 0x87, 0x2a, 0xd7, 0xe6, 0x4b, 0x53, 0x25, 0x10, 0x47, 0xb0, 0x57, 0x60, 0x0e, + 0x35, 0x52, 0x4d, 0x10, 0xdf, 0x2c, 0xd2, 0x61, 0x66, 0xfa, 0x3c, 0x9c, 0xb1, 0x08, 0x64, 0x8f, + 0xf3, 0x95, 0x7e, 0xaf, 0xe7, 0xcf, 0xcb, 0xd0, 0xd0, 0xc0, 0x4c, 0x58, 0xe2, 0x25, 0x0f, 0x77, + 0xe0, 0x7b, 0x23, 0x2a, 0x83, 0x1b, 0x2d, 0x27, 0x03, 0x65, 0x78, 0xde, 0xf9, 0xa9, 0x1b, 0x4e, + 0x12, 0x77, 0x40, 0x4f, 0x23, 0x4a, 0x85, 0x72, 0x95, 0x81, 0x32, 0x3c, 0x46, 0xcd, 0x1a, 0x1e, + 0xbf, 0xaf, 0x90, 0x81, 0xca, 0xfb, 0x33, 0x7c, 0x9d, 0x2a, 0xe9, 0xfd, 0x19, 0xbe, 0x2a, 0x59, + 0x31, 0x5f, 0x2d, 0x10, 0xf3, 0x1f, 0xc1, 0x12, 0x17, 0xe8, 0x42, 0x7a, 0xb8, 0x19, 0xe2, 0x9a, + 0x52, 0x4b, 0x1e, 0x40, 0x87, 0x8d, 0x59, 0xb2, 0x46, 0xec, 0xff, 0x98, 0xf3, 0x98, 0xe5, 0xe4, + 0xe0, 0x0c, 0x17, 0x63, 0xaf, 0x3a, 0x2e, 0xbf, 0x28, 0x9b, 0x83, 0x23, 0xae, 0xf7, 0xda, 0xc4, + 0xad, 0x0b, 0xdc, 0x0c, 0x9c, 0x3c, 0x86, 0xe5, 0x11, 0x1d, 0xf8, 0x9e, 0xd9, 0x84, 0x9b, 0x6a, + 0x1c, 0xd3, 0xaa, 0x59, 0x2f, 0x6c, 0x15, 0x7e, 0x1c, 0x8e, 0x8e, 0x7d, 0x7e, 0xca, 0xf2, 0x28, + 0x71, 0xc5, 0xc9, 0xc1, 0xed, 0x16, 0x34, 0x0e, 0x93, 0x70, 0x2c, 0xb7, 0xbe, 0x0d, 0x4d, 0x5e, + 0x14, 0xe9, 0x25, 0x37, 0xe1, 0x06, 0xd2, 0xeb, 0x51, 0x38, 0x0e, 0x87, 0xe1, 0xe9, 0xa5, 0xe1, + 0x9e, 0xfa, 0xf7, 0x16, 0x2c, 0x18, 0xb5, 0xa9, 0x7f, 0x0a, 0x7d, 0xe9, 0x32, 0x27, 0x80, 0x93, + 0xf8, 0xbc, 0x76, 0x46, 0x71, 0x44, 0x7e, 0x0f, 0xe0, 0x85, 0x48, 0x13, 0x58, 0x4b, 0x13, 0x5d, + 0xe5, 0x87, 0x9c, 0xde, 0xbb, 0x79, 0x7a, 0x17, 0xdf, 0xcb, 0x14, 0x58, 0xd9, 0xc4, 0xef, 0x88, + 0x6b, 0xcd, 0x03, 0x31, 0xe9, 0xb2, 0x79, 0x63, 0x53, 0x77, 0x67, 0xca, 0x11, 0xf4, 0x15, 0x30, + 0xb6, 0x7f, 0x6e, 0x01, 0xa4, 0xa3, 0xc3, 0x3b, 0xa3, 0xea, 0x9c, 0xe5, 0x6f, 0xc9, 0x68, 0x67, + 0xea, 0xbb, 0xd0, 0x54, 0xf7, 0xd6, 0xd2, 0xa3, 0xbb, 0x21, 0x61, 0x4c, 0xd5, 0x79, 0x1f, 0xe6, + 0x4e, 0x87, 0xe1, 0x31, 0xaa, 0x54, 0xe2, 0x9c, 0xe5, 0x49, 0x36, 0x6d, 0x0e, 0x96, 0xa7, 0x67, + 0x7a, 0xce, 0x57, 0x0a, 0x2f, 0xbc, 0xe9, 0xa7, 0x36, 0x3b, 0xeb, 0xe6, 0x73, 0x2b, 0x71, 0x25, + 0x97, 0xff, 0x52, 0x61, 0xdf, 0xab, 0xa2, 0x1b, 0x4f, 0xa0, 0x1d, 0x71, 0x99, 0x29, 0x05, 0x6a, + 0xe5, 0x0a, 0x81, 0xda, 0x8a, 0x8c, 0x93, 0xf9, 0xcb, 0xd0, 0xf1, 0x06, 0xe7, 0x34, 0x4a, 0x7c, + 0xf4, 0xf6, 0xa2, 0x4e, 0xc7, 0x27, 0x38, 0xa7, 0xc1, 0x51, 0x75, 0x7a, 0x1f, 0xe6, 0x44, 0xca, + 0x93, 0xc2, 0x14, 0xaf, 0x2a, 0xa4, 0x60, 0x86, 0x68, 0xff, 0x13, 0x79, 0x6d, 0xc8, 0xdc, 0xdd, + 0xab, 0x57, 0x45, 0x9f, 0x61, 0x29, 0x33, 0xc3, 0x2f, 0x89, 0x4b, 0x11, 0x03, 0xe9, 0x56, 0x2e, + 0x6b, 0x17, 0xe4, 0x07, 0xe2, 0xda, 0x95, 0xb9, 0xac, 0x95, 0xb7, 0x59, 0x56, 0xfb, 0x3f, 0x5b, + 0x30, 0xbb, 0x1d, 0x8e, 0x99, 0x69, 0x8f, 0x3a, 0x0e, 0x63, 0x13, 0x95, 0x6f, 0x28, 0x8b, 0x6f, + 0x48, 0x24, 0x28, 0xd4, 0x4a, 0x5a, 0x59, 0xad, 0xe4, 0xdb, 0x70, 0x13, 0x03, 0x1b, 0x51, 0x38, + 0x0e, 0x23, 0xc6, 0xae, 0xde, 0x90, 0xab, 0x20, 0x61, 0x90, 0x9c, 0x49, 0x71, 0x7a, 0x15, 0x0a, + 0xfa, 0x01, 0x87, 0xc9, 0xb9, 0xcb, 0xcd, 0x4d, 0xa1, 0x45, 0x71, 0x29, 0x9b, 0xaf, 0xb0, 0xbf, + 0x09, 0x75, 0xe5, 0xc0, 0x20, 0x1f, 0x40, 0xfd, 0x2c, 0x1c, 0x0b, 0x2f, 0x87, 0x65, 0x24, 0x5d, + 0x88, 0xd9, 0x3b, 0x29, 0x82, 0xfd, 0xbf, 0x66, 0x61, 0x76, 0x27, 0x38, 0x0f, 0xfd, 0x3e, 0x5e, + 0x3f, 0x1a, 0xd1, 0x51, 0x28, 0x33, 0x30, 0xd9, 0xdf, 0xf8, 0x38, 0x4a, 0xfa, 0x46, 0x02, 0x67, + 0x21, 0x0d, 0xc2, 0x0c, 0xe4, 0x48, 0x7f, 0xe3, 0x40, 0x94, 0x52, 0xab, 0xaf, 0xaa, 0xe5, 0xb0, + 0xb2, 0xd6, 0x78, 0xee, 0x3d, 0xae, 0x1d, 0xcf, 0x9c, 0xd1, 0x20, 0x6c, 0xf1, 0x45, 0x82, 0x03, + 0xbf, 0x28, 0xce, 0x6f, 0x32, 0x0a, 0x10, 0x1a, 0xfd, 0x11, 0xe5, 0xa1, 0x29, 0xa5, 0x7a, 0x31, + 0xa3, 0x5f, 0x07, 0x32, 0xf5, 0x8c, 0x7f, 0xc0, 0x71, 0xf8, 0x71, 0xa0, 0x83, 0xf0, 0x36, 0x4a, + 0xe6, 0xc5, 0x10, 0xfe, 0xea, 0x4b, 0x16, 0xcc, 0x2f, 0x9a, 0x29, 0xa1, 0xcb, 0xe7, 0x09, 0xfc, + 0x9d, 0x88, 0x2c, 0x5c, 0x73, 0x15, 0xf0, 0xdc, 0x30, 0xe9, 0x2a, 0x60, 0x24, 0xe3, 0x0d, 0x87, + 0xc7, 0x5e, 0xff, 0x15, 0xb7, 0x6c, 0x9b, 0x3c, 0xa2, 0x69, 0x00, 0xf1, 0x36, 0x7f, 0xba, 0xaf, + 0x78, 0x11, 0xa8, 0xe2, 0xe8, 0x20, 0xb2, 0x6a, 0xfa, 0xaf, 0xda, 0x53, 0xfc, 0x57, 0x3a, 0x92, + 0x7e, 0x31, 0x6a, 0x2e, 0x97, 0xad, 0xe5, 0x0d, 0x06, 0xe2, 0xc2, 0x4c, 0x87, 0xbf, 0x93, 0xa0, + 0x00, 0xe8, 0xa8, 0xe1, 0x0b, 0xc6, 0x11, 0xe6, 0x11, 0xc1, 0x80, 0x91, 0x3b, 0xdc, 0x0f, 0x3b, + 0xf6, 0xfc, 0x01, 0x5e, 0x4c, 0xe5, 0xb6, 0xb0, 0x82, 0xb1, 0x36, 0xe4, 0xdf, 0x78, 0x70, 0x2e, + 0xe0, 0xaa, 0x18, 0x30, 0xb6, 0x36, 0xaa, 0x3c, 0x4a, 0xd3, 0xbb, 0x4c, 0x20, 0xf9, 0x10, 0x2f, + 0x22, 0x24, 0x14, 0x73, 0xb8, 0xda, 0xab, 0x37, 0xc5, 0x9c, 0x05, 0xd9, 0xca, 0xff, 0xf1, 0xe2, + 0x85, 0xc3, 0x31, 0x99, 0xda, 0xc6, 0x63, 0x41, 0x4b, 0x86, 0xda, 0x26, 0x50, 0x31, 0x16, 0xc4, + 0x11, 0xc8, 0x63, 0xcd, 0x12, 0xeb, 0x22, 0xf2, 0xad, 0x4c, 0xfb, 0x53, 0x6c, 0x30, 0x46, 0xcc, + 0x7e, 0xcc, 0xce, 0x9f, 0x98, 0x06, 0x03, 0xcc, 0xe6, 0xaa, 0x39, 0x1a, 0xe4, 0xd7, 0x6b, 0xa3, + 0xad, 0x41, 0x53, 0x9f, 0x27, 0xa9, 0x41, 0x65, 0xff, 0x60, 0x6b, 0xaf, 0x73, 0x8d, 0x34, 0x60, + 0xf6, 0x70, 0xeb, 0xe8, 0x68, 0x77, 0x6b, 0xb3, 0x63, 0x91, 0x26, 0xd4, 0x54, 0x1a, 0x4a, 0x89, + 0x95, 0xd6, 0x36, 0x36, 0xb6, 0x0e, 0x8e, 0xb6, 0x36, 0x3b, 0xe5, 0x4f, 0x2a, 0xb5, 0x52, 0xa7, + 0x8c, 0x0a, 0xa6, 0xb6, 0x0c, 0x6f, 0xf0, 0xb3, 0xdd, 0x01, 0x40, 0xc3, 0x27, 0xbd, 0x58, 0x55, + 0x71, 0x34, 0x08, 0x13, 0xe4, 0xca, 0x3f, 0x51, 0xe6, 0x6f, 0x5b, 0xc8, 0x32, 0x6e, 0x2e, 0x3e, + 0x22, 0xa1, 0xc7, 0x07, 0xab, 0x8e, 0x09, 0x64, 0x84, 0x2f, 0x00, 0x98, 0xe0, 0xc0, 0xc5, 0x85, + 0x0e, 0x62, 0x84, 0x14, 0xd1, 0x38, 0x1c, 0x9e, 0x53, 0x8e, 0xc2, 0xd5, 0x47, 0x03, 0xc6, 0xfa, + 0x12, 0x12, 0x51, 0xcb, 0xaa, 0xaa, 0x3a, 0x26, 0x90, 0x7c, 0x55, 0x12, 0x52, 0x0d, 0x09, 0x69, + 0x39, 0x4f, 0x15, 0x06, 0x11, 0x3d, 0xcf, 0x39, 0xca, 0xea, 0x48, 0x20, 0xbf, 0x95, 0xff, 0xee, + 0x2d, 0x1c, 0x66, 0x64, 0x05, 0xc8, 0x68, 0x3c, 0x76, 0x0b, 0x3c, 0x58, 0x15, 0xa7, 0xa0, 0xe6, + 0xd7, 0xe0, 0x60, 0x4b, 0x80, 0xac, 0x0d, 0x06, 0x62, 0x98, 0xfa, 0x53, 0x1f, 0x91, 0xfe, 0xb6, + 0x8c, 0x14, 0xd9, 0x05, 0x62, 0xb1, 0x54, 0x2c, 0x16, 0xaf, 0x14, 0x1e, 0xf6, 0x0e, 0x34, 0x0e, + 0xb4, 0xd7, 0x6a, 0x6c, 0x76, 0x82, 0xc8, 0x77, 0x6a, 0xf8, 0xd9, 0xc2, 0x1d, 0x6b, 0x29, 0x54, + 0x1b, 0x52, 0x49, 0x1f, 0x92, 0xfd, 0x8f, 0x2c, 0xfe, 0x00, 0x80, 0x9a, 0x02, 0xef, 0xdf, 0x86, + 0xa6, 0x0a, 0x2e, 0xa5, 0xd9, 0x90, 0x06, 0x8c, 0xe1, 0xe0, 0x70, 0xdc, 0xf0, 0xe4, 0x24, 0xa6, + 0x32, 0x95, 0xc7, 0x80, 0x49, 0x65, 0x9d, 0xa9, 0xff, 0x3e, 0xef, 0x21, 0x16, 0x29, 0x3d, 0x39, + 0x38, 0xa3, 0x74, 0xe1, 0x1b, 0x97, 0x49, 0x4c, 0xaa, 0x6c, 0xff, 0x81, 0x48, 0xda, 0xcc, 0xae, + 0xf4, 0x03, 0xa8, 0xa9, 0x76, 0xcd, 0x93, 0x58, 0x62, 0xaa, 0x7a, 0x76, 0xe2, 0xa3, 0x21, 0x6f, + 0x0c, 0x9a, 0x33, 0x5c, 0xbe, 0x82, 0xd1, 0xd2, 0x89, 0x1f, 0x65, 0xd1, 0x39, 0x07, 0x16, 0xd4, + 0xd8, 0x2f, 0x61, 0x41, 0x8a, 0x0f, 0xcd, 0x8a, 0x30, 0x37, 0xd2, 0x7a, 0xd3, 0x29, 0x50, 0xca, + 0x9f, 0x02, 0xf6, 0xbf, 0xa9, 0xc0, 0xac, 0x7c, 0x0a, 0xca, 0x2e, 0x78, 0xba, 0xa8, 0x6e, 0xbe, + 0x7a, 0x44, 0xba, 0xc6, 0xdb, 0x16, 0x48, 0x08, 0x42, 0x37, 0xb8, 0x9f, 0x3d, 0xdd, 0x53, 0x07, + 0x6b, 0xe6, 0x84, 0x5f, 0x82, 0xca, 0xd8, 0x4b, 0xce, 0xd0, 0xff, 0xc6, 0x69, 0x09, 0xcb, 0xd2, + 0x85, 0x5f, 0x35, 0x5d, 0xf8, 0x45, 0x6f, 0x3d, 0x71, 0x55, 0x36, 0xff, 0xd6, 0xd3, 0x2d, 0xa8, + 0x73, 0x6d, 0x24, 0xf5, 0xd2, 0xa7, 0x80, 0x8c, 0xf6, 0x52, 0xcb, 0x69, 0x2f, 0x6f, 0xaf, 0x57, + 0x7c, 0x1d, 0x66, 0x78, 0xbe, 0xb3, 0x48, 0xd9, 0x92, 0x47, 0x8e, 0x58, 0x49, 0xf9, 0x3f, 0xbf, + 0xb9, 0xeb, 0x08, 0x5c, 0xfd, 0xc5, 0x94, 0x86, 0xf9, 0x62, 0x8a, 0x1e, 0x5c, 0x68, 0x66, 0x82, + 0x0b, 0x0f, 0xa0, 0xa3, 0x96, 0x0f, 0x1d, 0x70, 0x41, 0x2c, 0x52, 0x54, 0x72, 0xf0, 0xf4, 0xd8, + 0x6c, 0x1b, 0xc7, 0x26, 0x93, 0x70, 0x6b, 0x49, 0x42, 0x47, 0xe3, 0x44, 0x1c, 0x9b, 0xf6, 0x53, + 0x68, 0x19, 0x83, 0x34, 0xd3, 0x1a, 0x5b, 0x50, 0xdf, 0xd9, 0x73, 0x9f, 0xee, 0xee, 0x3c, 0xdb, + 0x3e, 0xea, 0x58, 0xac, 0x78, 0xf8, 0x62, 0x63, 0x63, 0x6b, 0x6b, 0x13, 0x8f, 0x25, 0x80, 0x99, + 0xa7, 0x6b, 0x3b, 0xec, 0x88, 0x2a, 0xdb, 0xff, 0xdb, 0x82, 0x86, 0xd6, 0x3c, 0xf9, 0x86, 0x5a, + 0x19, 0xfe, 0xa8, 0xc6, 0xed, 0xfc, 0x10, 0x56, 0xa4, 0xa0, 0xd6, 0x96, 0x46, 0x3d, 0x6f, 0x55, + 0x9a, 0xfa, 0xbc, 0x15, 0xdb, 0x1e, 0x8f, 0xb7, 0xa0, 0xd6, 0x81, 0x5b, 0x57, 0x59, 0x30, 0xbf, + 0xae, 0x96, 0x9e, 0x2e, 0x0c, 0x93, 0x7b, 0x14, 0xb3, 0x60, 0xfb, 0x23, 0x80, 0x74, 0x34, 0xe6, + 0xb4, 0xaf, 0x99, 0xd3, 0xb6, 0xb4, 0x69, 0x97, 0xec, 0x4d, 0x2e, 0x30, 0xc4, 0x12, 0xaa, 0x30, + 0xf8, 0x57, 0x81, 0x48, 0x07, 0x16, 0x5e, 0x0b, 0x1d, 0x0f, 0x69, 0x22, 0x53, 0x3b, 0xe7, 0x45, + 0xcd, 0x8e, 0xaa, 0x90, 0x69, 0xd7, 0x69, 0x2b, 0xa9, 0xdc, 0x11, 0x14, 0x97, 0x95, 0x3b, 0x02, + 0xd5, 0x51, 0xf5, 0x76, 0x0f, 0xba, 0x9b, 0x94, 0xb5, 0xb6, 0x36, 0x1c, 0x66, 0x86, 0x63, 0xdf, + 0x84, 0x1b, 0x05, 0x75, 0xc2, 0x3d, 0xf1, 0x1d, 0xb8, 0xbe, 0xc6, 0xb3, 0x38, 0x7f, 0x5d, 0x09, + 0x23, 0x76, 0x17, 0x96, 0xb2, 0x4d, 0x8a, 0xce, 0x9e, 0xc2, 0xfc, 0x26, 0x3d, 0x9e, 0x9c, 0xee, + 0xd2, 0xf3, 0xb4, 0x23, 0x02, 0x95, 0xf8, 0x2c, 0xbc, 0x10, 0xeb, 0x83, 0x7f, 0x93, 0xdb, 0x00, + 0x43, 0x86, 0xe3, 0xc6, 0x63, 0xda, 0x97, 0x8f, 0x96, 0x20, 0xe4, 0x70, 0x4c, 0xfb, 0xf6, 0x47, + 0x40, 0xf4, 0x76, 0xc4, 0x7a, 0x31, 0x93, 0x61, 0x72, 0xec, 0xc6, 0x97, 0x71, 0x42, 0x47, 0xf2, + 0x35, 0x16, 0x1d, 0x64, 0xbf, 0x0f, 0xcd, 0x03, 0xef, 0xd2, 0xa1, 0x9f, 0x89, 0xe7, 0xd4, 0x96, + 0x61, 0x76, 0xec, 0x5d, 0x32, 0x7e, 0x56, 0x21, 0x16, 0xac, 0xb6, 0xff, 0xb8, 0x02, 0x33, 0x1c, + 0x93, 0xb5, 0x3a, 0xa0, 0x71, 0xe2, 0x07, 0xc8, 0x63, 0xb2, 0x55, 0x0d, 0x94, 0x13, 0x98, 0xa5, + 0x02, 0x81, 0x29, 0x5c, 0x6d, 0xf2, 0xf1, 0x07, 0x41, 0xb2, 0x06, 0x8c, 0x89, 0xad, 0x34, 0xfd, + 0x8c, 0x53, 0x6a, 0x0a, 0xc8, 0xc4, 0x30, 0x53, 0xc3, 0x84, 0x8f, 0x4f, 0x9e, 0x05, 0x42, 0x26, + 0xea, 0xa0, 0x42, 0xf3, 0x67, 0x56, 0xe6, 0xd9, 0x64, 0xcc, 0x9f, 0x9c, 0x99, 0x53, 0x7b, 0x0b, + 0x33, 0x87, 0xfb, 0xdf, 0xae, 0x32, 0x73, 0xe0, 0x6d, 0xcc, 0x9c, 0xb7, 0x89, 0x1d, 0xf6, 0xa0, + 0x86, 0x67, 0xba, 0x26, 0x22, 0x65, 0x99, 0xfc, 0xb6, 0x66, 0x03, 0xf0, 0x7b, 0x0c, 0x37, 0x53, + 0x7e, 0x71, 0xe8, 0x67, 0xbf, 0x99, 0x30, 0xcc, 0x0f, 0x60, 0x56, 0x40, 0x19, 0x65, 0x07, 0xde, + 0x48, 0x3e, 0xba, 0x83, 0x7f, 0xb3, 0xa5, 0xc3, 0xb7, 0x3f, 0x3e, 0x9b, 0xf8, 0x11, 0x1d, 0xc8, + 0x5c, 0x6d, 0x0d, 0x84, 0x97, 0xcb, 0x63, 0xf7, 0x55, 0x10, 0x5e, 0x04, 0x22, 0x5b, 0x5b, 0x95, + 0x6d, 0x02, 0x1d, 0x7c, 0x7c, 0x6b, 0x1c, 0x46, 0xf2, 0x1d, 0x25, 0xfb, 0x8f, 0x2c, 0xe8, 0x08, + 0x46, 0x53, 0x75, 0xba, 0xdf, 0xa6, 0x9a, 0xf3, 0xdb, 0xbc, 0x6b, 0xb8, 0x5d, 0x0a, 0x1f, 0x62, + 0xb8, 0x07, 0x2d, 0x74, 0x84, 0xa8, 0xf3, 0x48, 0x44, 0xe6, 0x0d, 0x20, 0x9b, 0x8c, 0xbc, 0xfa, + 0x39, 0xf2, 0x87, 0x82, 0xa8, 0x75, 0x90, 0x3c, 0xd2, 0x22, 0x4f, 0x64, 0x80, 0x59, 0x8e, 0x2a, + 0xdb, 0xbf, 0xb0, 0x60, 0x5e, 0x9b, 0x8d, 0xe0, 0xe2, 0x27, 0xd0, 0x54, 0x0f, 0xe0, 0x51, 0xa5, + 0x71, 0x2d, 0x9b, 0x62, 0x27, 0xfd, 0xcc, 0x40, 0x46, 0x66, 0xf0, 0x2e, 0x71, 0x80, 0xf1, 0x64, + 0x24, 0x54, 0x1d, 0x1d, 0xc4, 0x88, 0xec, 0x82, 0xd2, 0x57, 0x0a, 0x85, 0x2b, 0x5b, 0x06, 0x0c, + 0x03, 0x48, 0x61, 0x90, 0x9c, 0x29, 0xa4, 0x8a, 0x08, 0x20, 0xe9, 0x40, 0xfb, 0xbf, 0x96, 0x60, + 0x81, 0x7b, 0xe4, 0x84, 0x27, 0x54, 0xbd, 0x41, 0x34, 0xc3, 0x9d, 0x93, 0x5c, 0xa2, 0x6d, 0x5f, + 0x73, 0x44, 0x99, 0x7c, 0xe3, 0x2d, 0xbd, 0x88, 0x2a, 0xd5, 0x6c, 0xca, 0x5e, 0x94, 0x8b, 0xf6, + 0xe2, 0x8a, 0x95, 0x2e, 0x8a, 0xe5, 0x55, 0x8b, 0x63, 0x79, 0x6f, 0x17, 0x3b, 0xcb, 0xe5, 0x63, + 0xcd, 0x0a, 0x2c, 0x23, 0x1f, 0x6b, 0x15, 0x96, 0x0d, 0x00, 0x0a, 0x73, 0xff, 0xc4, 0xa7, 0x32, + 0x39, 0x7e, 0x3e, 0xa6, 0x89, 0x6b, 0xa0, 0xac, 0xcf, 0x42, 0x35, 0xee, 0x87, 0x63, 0x6a, 0x2f, + 0xc1, 0xa2, 0xb9, 0xb8, 0xe2, 0x08, 0xf9, 0xb9, 0x05, 0xdd, 0xa7, 0xfc, 0x46, 0x86, 0x1f, 0x9c, + 0x6e, 0xfb, 0x71, 0x12, 0x46, 0xea, 0xa9, 0xb8, 0x3b, 0x00, 0x71, 0xe2, 0x45, 0xc2, 0x08, 0xe5, + 0x9a, 0xb0, 0x06, 0x61, 0x6b, 0x44, 0x83, 0x01, 0xaf, 0xe5, 0xb4, 0xa1, 0xca, 0x39, 0x4b, 0x43, + 0xf8, 0x2b, 0x0d, 0x7d, 0xfd, 0x3d, 0x9e, 0x26, 0xca, 0x16, 0x83, 0x9e, 0xe3, 0xb9, 0xcc, 0x9d, + 0x80, 0x19, 0xa8, 0xfd, 0x07, 0x25, 0x98, 0x4b, 0x07, 0xc9, 0xd3, 0xce, 0x0d, 0xe9, 0x2e, 0x94, + 0xf4, 0x54, 0xba, 0x8b, 0xd8, 0xa2, 0xeb, 0x33, 0xad, 0x5d, 0x73, 0x59, 0x6a, 0x50, 0x72, 0x0f, + 0x1a, 0xb2, 0x14, 0x4e, 0x12, 0xed, 0xcd, 0x26, 0x1d, 0xcc, 0xf3, 0x4f, 0x98, 0xdd, 0x20, 0x6c, + 0x20, 0x51, 0xc2, 0xc7, 0x12, 0x46, 0x09, 0x7e, 0xc9, 0xf7, 0x54, 0x16, 0x99, 0xb4, 0x63, 0x0a, + 0x37, 0xdf, 0x43, 0x54, 0xb6, 0x75, 0x45, 0xb4, 0xa6, 0xde, 0xba, 0x54, 0x3c, 0xcf, 0x5b, 0x4c, + 0x33, 0xf1, 0x2a, 0x8e, 0x0e, 0x92, 0x2e, 0xa3, 0x70, 0x62, 0xd8, 0xc6, 0x06, 0xcc, 0xfe, 0x5b, + 0x16, 0xdc, 0x28, 0xd8, 0x46, 0x21, 0x03, 0x36, 0x61, 0xfe, 0x44, 0x55, 0xca, 0xa5, 0xe6, 0x82, + 0x60, 0x49, 0x4a, 0x5e, 0x73, 0x79, 0x9d, 0xfc, 0x07, 0xca, 0x16, 0xe3, 0x9b, 0x67, 0x24, 0x5e, + 0xe6, 0x2b, 0xec, 0x03, 0xe8, 0x6d, 0xbd, 0x66, 0x22, 0x65, 0x43, 0x7f, 0xf0, 0x5c, 0x52, 0xd6, + 0x6a, 0x4e, 0x64, 0xbe, 0xd9, 0x53, 0x7d, 0xc2, 0xd3, 0xc9, 0x54, 0x5b, 0xe4, 0x6b, 0x6f, 0xdb, + 0x88, 0xce, 0xfd, 0x77, 0xc5, 0xae, 0xf3, 0x17, 0xdb, 0x65, 0xfa, 0xa7, 0x06, 0xb2, 0xcf, 0x61, + 0xee, 0xf9, 0x64, 0x98, 0xf8, 0xe9, 0xeb, 0xed, 0xe4, 0x1b, 0xe2, 0x23, 0x6c, 0x42, 0x2e, 0x5d, + 0x61, 0x57, 0x3a, 0x1e, 0x5b, 0xb1, 0x11, 0x6b, 0xc9, 0xcd, 0xf7, 0x98, 0xaf, 0xb0, 0x6f, 0xc0, + 0x72, 0xda, 0x25, 0x5f, 0x3b, 0x79, 0x26, 0xfd, 0xa1, 0xc5, 0xaf, 0x5d, 0x9b, 0x8f, 0xc9, 0x93, + 0x67, 0xb0, 0x10, 0xfb, 0xc1, 0xe9, 0x90, 0xea, 0xed, 0xc4, 0x62, 0x25, 0xae, 0x9b, 0xc3, 0x13, + 0x0f, 0xce, 0x3b, 0x45, 0x5f, 0x30, 0x02, 0x29, 0x1e, 0x68, 0x4a, 0x20, 0x99, 0x25, 0x29, 0x9a, + 0xc0, 0x27, 0xd0, 0x36, 0x3b, 0x23, 0x8f, 0x45, 0x5e, 0x65, 0x3a, 0xb2, 0x72, 0x26, 0x3d, 0x2e, + 0xa5, 0x0c, 0x03, 0xd3, 0xfe, 0xa9, 0x05, 0x5d, 0x87, 0x32, 0x32, 0xa6, 0x5a, 0xa7, 0x82, 0x7a, + 0x9e, 0xe4, 0x9a, 0x9d, 0x3e, 0x61, 0x95, 0xaf, 0x29, 0xe7, 0xba, 0x32, 0x75, 0x53, 0xb6, 0xaf, + 0x15, 0xcc, 0x6a, 0xbd, 0x06, 0x33, 0x62, 0x7e, 0xcb, 0x70, 0x5d, 0x0c, 0x49, 0x0e, 0x27, 0x8d, + 0x49, 0x1a, 0x9d, 0x1a, 0x31, 0xc9, 0x1e, 0x74, 0xf9, 0x8b, 0x80, 0xfa, 0x3c, 0xc4, 0x87, 0x9b, + 0x40, 0x9e, 0x7b, 0x7d, 0x2f, 0x0a, 0xc3, 0xe0, 0x80, 0x46, 0xe2, 0x06, 0x2b, 0xaa, 0xa6, 0x18, + 0xb2, 0x93, 0x5a, 0x34, 0x2f, 0xc9, 0x47, 0xec, 0xc2, 0x40, 0x3e, 0x16, 0xc8, 0x4b, 0xb6, 0x03, + 0x0b, 0xeb, 0xde, 0x2b, 0x2a, 0x5b, 0x4a, 0x57, 0xa9, 0x31, 0x56, 0x8d, 0xca, 0xb5, 0x97, 0x09, + 0xd9, 0xf9, 0x6e, 0x1d, 0x1d, 0xdb, 0x5e, 0x85, 0x45, 0xb3, 0x4d, 0x21, 0x4a, 0x7a, 0x50, 0x1b, + 0x09, 0x98, 0x18, 0x9d, 0x2a, 0x3f, 0xf8, 0x1c, 0x1a, 0xda, 0x2b, 0x8f, 0x64, 0x19, 0x16, 0x5e, + 0xee, 0x1c, 0xed, 0x6d, 0x1d, 0x1e, 0xba, 0x07, 0x2f, 0xd6, 0x3f, 0xdd, 0xfa, 0x9e, 0xbb, 0xbd, + 0x76, 0xb8, 0xdd, 0xb9, 0x46, 0x96, 0x80, 0xec, 0x6d, 0x1d, 0x1e, 0x6d, 0x6d, 0x1a, 0x70, 0x8b, + 0xdc, 0x81, 0xde, 0x8b, 0xbd, 0x17, 0x87, 0x5b, 0x9b, 0x6e, 0xd1, 0x77, 0x25, 0x72, 0x1b, 0x6e, + 0x88, 0xfa, 0x82, 0xcf, 0xcb, 0x0f, 0x9e, 0x40, 0x27, 0xeb, 0xb3, 0x34, 0x7c, 0xbd, 0x57, 0x39, + 0x85, 0x1f, 0xfc, 0xe3, 0x32, 0x40, 0x7a, 0x73, 0x95, 0x74, 0x61, 0x71, 0x73, 0xed, 0x68, 0x6d, + 0x77, 0x9f, 0x0d, 0xc2, 0xd9, 0x3f, 0xda, 0xda, 0x38, 0x72, 0x9d, 0xad, 0xef, 0x74, 0xae, 0x15, + 0xd6, 0xec, 0x1f, 0x30, 0x7b, 0x7e, 0x19, 0x16, 0x76, 0xf6, 0x76, 0x8e, 0x76, 0xd6, 0x76, 0x5d, + 0x67, 0xff, 0xc5, 0xce, 0xde, 0x33, 0xfe, 0x28, 0x4b, 0x99, 0xbc, 0x03, 0x37, 0x5f, 0x1c, 0x3c, + 0x75, 0xf6, 0xf7, 0x8e, 0xdc, 0xc3, 0xed, 0x17, 0x47, 0x9b, 0xf8, 0xa4, 0xcb, 0x86, 0xb3, 0x73, + 0xc0, 0xdb, 0xac, 0x5c, 0x85, 0xc0, 0x9a, 0xae, 0xb2, 0x15, 0x7b, 0xb6, 0x7f, 0x78, 0xb8, 0x73, + 0xe0, 0x7e, 0xe7, 0xc5, 0x96, 0xb3, 0xb3, 0x75, 0x88, 0x1f, 0xce, 0x14, 0xc0, 0x19, 0xfe, 0x2c, + 0x99, 0x87, 0xd6, 0xd1, 0xee, 0x77, 0xdd, 0xfd, 0xbd, 0x9d, 0xfd, 0x3d, 0x44, 0xad, 0x99, 0x20, + 0x86, 0x55, 0x27, 0x3d, 0x58, 0xda, 0xfa, 0xbd, 0x23, 0xb7, 0xa0, 0x65, 0x98, 0x52, 0xc7, 0xbe, + 0x6b, 0x90, 0x1b, 0x70, 0xfd, 0xf0, 0x68, 0xed, 0x68, 0x67, 0xc3, 0x15, 0xcf, 0x41, 0xb1, 0x4d, + 0x60, 0x9f, 0x35, 0x8b, 0xab, 0xd8, 0x57, 0x2d, 0xb2, 0x08, 0x9d, 0x83, 0xb5, 0xef, 0x3d, 0xdf, + 0xda, 0x3b, 0x72, 0xd7, 0x36, 0x37, 0x1d, 0xfc, 0xa0, 0x9d, 0x83, 0x32, 0xdc, 0x39, 0xb6, 0x51, + 0xcf, 0x0f, 0x0e, 0x10, 0xa5, 0x23, 0x0b, 0xac, 0x66, 0x7e, 0xf5, 0xa7, 0x65, 0x68, 0xf3, 0x54, + 0x02, 0xfe, 0xb3, 0x19, 0x34, 0x22, 0xcf, 0x61, 0x56, 0xfc, 0xfe, 0x0a, 0xb9, 0xae, 0x5e, 0xe2, + 0xd0, 0x7f, 0xf1, 0xa5, 0xb7, 0x94, 0x05, 0x0b, 0xf6, 0x5b, 0xf8, 0x2b, 0xff, 0xf1, 0xbf, 0xff, + 0xac, 0xd4, 0x22, 0x8d, 0x87, 0xe7, 0x1f, 0x3e, 0x3c, 0xa5, 0x41, 0xcc, 0xda, 0xf8, 0x8b, 0x00, + 0xe9, 0xaf, 0x8a, 0x90, 0xae, 0x72, 0x4d, 0x66, 0x7e, 0x72, 0xa5, 0x77, 0xa3, 0xa0, 0x46, 0xb4, + 0x7b, 0x03, 0xdb, 0x5d, 0xb0, 0xdb, 0xac, 0x5d, 0x3f, 0xf0, 0x13, 0xfe, 0x0b, 0x23, 0x1f, 0x5b, + 0x0f, 0xc8, 0x00, 0x9a, 0xfa, 0xef, 0x7d, 0x10, 0x79, 0x15, 0xa0, 0xe0, 0x17, 0x4b, 0x7a, 0x37, + 0x0b, 0xeb, 0xa4, 0xcc, 0xc1, 0x3e, 0xae, 0xdb, 0x1d, 0xd6, 0xc7, 0x04, 0x31, 0xd2, 0x5e, 0x86, + 0x5c, 0x12, 0xa7, 0x3f, 0xeb, 0x41, 0x6e, 0x69, 0xc2, 0x31, 0xf7, 0xa3, 0x22, 0xbd, 0xdb, 0x53, + 0x6a, 0x45, 0x5f, 0xb7, 0xb1, 0xaf, 0x65, 0x9b, 0xb0, 0xbe, 0xfa, 0x88, 0x23, 0x7f, 0x54, 0xe4, + 0x63, 0xeb, 0xc1, 0xea, 0x9f, 0xde, 0x87, 0xba, 0xba, 0x26, 0x44, 0x7e, 0x04, 0x2d, 0x23, 0xd7, + 0x83, 0xc8, 0x69, 0x14, 0xa5, 0x86, 0xf4, 0x6e, 0x15, 0x57, 0x8a, 0x8e, 0xef, 0x60, 0xc7, 0x5d, + 0xb2, 0xc4, 0x3a, 0x16, 0xc9, 0x12, 0x0f, 0x31, 0x37, 0x8a, 0xbf, 0x6b, 0xf2, 0x4a, 0x3b, 0x71, + 0x78, 0x67, 0xb7, 0xb2, 0x87, 0x80, 0xd1, 0xdb, 0xed, 0x29, 0xb5, 0xa2, 0xbb, 0x5b, 0xd8, 0xdd, + 0x12, 0x59, 0xd4, 0xbb, 0x53, 0x57, 0x77, 0x28, 0xbe, 0x2d, 0xa4, 0xff, 0xe2, 0x05, 0xb9, 0x9d, + 0xbe, 0xfc, 0x52, 0xf0, 0x4b, 0x18, 0x8a, 0x44, 0xf2, 0x3f, 0x87, 0x61, 0x77, 0xb1, 0x2b, 0x42, + 0x70, 0xfb, 0xf4, 0x1f, 0xbc, 0x20, 0xc7, 0xd0, 0xd0, 0x1e, 0x86, 0x26, 0x37, 0xa6, 0x3e, 0x62, + 0xdd, 0xeb, 0x15, 0x55, 0x15, 0x4d, 0x45, 0x6f, 0xff, 0x21, 0x53, 0x48, 0x7f, 0x00, 0x75, 0xf5, + 0xd4, 0x30, 0x59, 0xd6, 0x9e, 0x7e, 0xd6, 0x9f, 0x46, 0xee, 0x75, 0xf3, 0x15, 0x45, 0xc4, 0xa7, + 0xb7, 0xce, 0x88, 0xef, 0x25, 0x34, 0xb4, 0xe7, 0x84, 0xd5, 0x04, 0xf2, 0x4f, 0x16, 0xab, 0x09, + 0x14, 0xbc, 0x3e, 0x6c, 0xcf, 0x63, 0x17, 0x0d, 0x52, 0x47, 0xfa, 0x4e, 0x5e, 0x87, 0x31, 0xd9, + 0x85, 0xeb, 0xe2, 0x64, 0x3d, 0xa6, 0x5f, 0x64, 0x1b, 0x0a, 0x7e, 0x64, 0xe4, 0x91, 0x45, 0x9e, + 0x40, 0x4d, 0xbe, 0x1a, 0x4d, 0x96, 0x8a, 0x5f, 0xbf, 0xee, 0x2d, 0xe7, 0xe0, 0xe2, 0x18, 0xfc, + 0x1e, 0x40, 0xfa, 0x76, 0xb1, 0x12, 0x12, 0xb9, 0xb7, 0x90, 0x15, 0x05, 0xe4, 0x1f, 0x3a, 0xb6, + 0x97, 0x70, 0x82, 0x1d, 0x82, 0x42, 0x22, 0xa0, 0x17, 0xf2, 0x61, 0x8b, 0x1f, 0x42, 0x43, 0x7b, + 0xbe, 0x58, 0x2d, 0x5f, 0xfe, 0xe9, 0x63, 0xb5, 0x7c, 0x05, 0xaf, 0x1d, 0xdb, 0x3d, 0x6c, 0x7d, + 0xd1, 0x9e, 0x63, 0xad, 0xc7, 0xfe, 0x69, 0x30, 0xe2, 0x08, 0x6c, 0x83, 0xce, 0xa0, 0x65, 0xbc, + 0x51, 0xac, 0x38, 0xb4, 0xe8, 0x05, 0x64, 0xc5, 0xa1, 0x85, 0xcf, 0x1a, 0x4b, 0x3a, 0xb3, 0xe7, + 0x59, 0x3f, 0xe7, 0x88, 0xa2, 0xf5, 0xf4, 0x7d, 0x68, 0x68, 0xef, 0x0d, 0xab, 0xb9, 0xe4, 0x9f, + 0x36, 0x56, 0x73, 0x29, 0x7a, 0x9e, 0x78, 0x11, 0xfb, 0x68, 0xdb, 0x48, 0x0a, 0xf8, 0x54, 0x15, + 0x6b, 0xfb, 0x47, 0xd0, 0x36, 0x5f, 0x20, 0x56, 0xbc, 0x5f, 0xf8, 0x96, 0xb1, 0xe2, 0xfd, 0x29, + 0xcf, 0x16, 0x0b, 0x92, 0x7e, 0xb0, 0xa0, 0x3a, 0x79, 0xf8, 0x13, 0x71, 0xeb, 0xf9, 0x73, 0xf2, + 0x1d, 0x26, 0xe0, 0xc4, 0x13, 0x6a, 0x64, 0x59, 0xa3, 0x5a, 0xfd, 0xa1, 0x35, 0xc5, 0x2f, 0xb9, + 0xd7, 0xd6, 0x4c, 0x62, 0xe6, 0x8f, 0x6d, 0x3d, 0x83, 0x05, 0x45, 0xcc, 0xea, 0x49, 0xb4, 0x58, + 0xcd, 0xa1, 0xf0, 0xe5, 0xb5, 0x5e, 0x27, 0x5b, 0xfb, 0xc8, 0xe2, 0xc7, 0x1f, 0x3e, 0x3c, 0xa5, + 0x1d, 0x7f, 0xfa, 0xab, 0x68, 0xda, 0xf1, 0x67, 0xbc, 0x4f, 0x95, 0x3d, 0xfe, 0x12, 0x9f, 0xb5, + 0x11, 0xc0, 0x5c, 0x26, 0x7d, 0x56, 0xb1, 0x57, 0xf1, 0x0b, 0x07, 0xbd, 0x3b, 0x57, 0x67, 0xdd, + 0x9a, 0xa2, 0x48, 0x4a, 0xd3, 0x87, 0xf2, 0xf9, 0x94, 0xdf, 0x87, 0xa6, 0xfe, 0x48, 0x2a, 0xd1, + 0x65, 0x42, 0xb6, 0xa7, 0x9b, 0x85, 0x75, 0x26, 0x95, 0x90, 0xa6, 0xde, 0x0d, 0xf9, 0x2e, 0x2c, + 0xa9, 0x65, 0xd6, 0xb3, 0x28, 0x63, 0xf2, 0x4e, 0x41, 0x6e, 0xa5, 0xb1, 0xd8, 0x37, 0xa6, 0x26, + 0x5f, 0x3e, 0xb2, 0x18, 0xf5, 0x99, 0x0f, 0x34, 0xa6, 0x27, 0x4f, 0xd1, 0xbb, 0x94, 0xe9, 0xc9, + 0x53, 0xf8, 0xaa, 0xa3, 0xa4, 0x3e, 0xb2, 0x60, 0xac, 0x11, 0xbf, 0xdc, 0x45, 0xbe, 0x0f, 0x73, + 0x5a, 0xce, 0xfb, 0xe1, 0x65, 0xd0, 0x57, 0x9c, 0x94, 0x7f, 0xdf, 0xa8, 0x57, 0x64, 0x96, 0xda, + 0xcb, 0xd8, 0xfe, 0xbc, 0x6d, 0x2c, 0x0e, 0xe3, 0xa2, 0x0d, 0x68, 0xe8, 0xf9, 0xf4, 0x57, 0xb4, + 0xbb, 0xac, 0x55, 0xe9, 0x8f, 0xe7, 0x3c, 0xb2, 0xc8, 0x2e, 0x74, 0xb2, 0xef, 0x7c, 0x28, 0x99, + 0x52, 0xf4, 0x36, 0x49, 0x2f, 0x53, 0x69, 0xbc, 0x0e, 0x42, 0x0e, 0xf8, 0x95, 0x61, 0xf5, 0x6b, + 0x1c, 0x61, 0x94, 0x3d, 0xd5, 0xcd, 0x5f, 0xe9, 0x50, 0xad, 0x15, 0xfd, 0x3e, 0xcb, 0x7d, 0xeb, + 0x91, 0x45, 0xfe, 0x9e, 0x05, 0x4d, 0x23, 0x7b, 0xde, 0xb8, 0x80, 0x99, 0x99, 0x67, 0x57, 0xaf, + 0xd3, 0x27, 0x6a, 0x3b, 0xb8, 0x88, 0xbb, 0x0f, 0x3e, 0x31, 0x36, 0xe9, 0x27, 0x86, 0xa7, 0x77, + 0x25, 0xfb, 0x93, 0x1c, 0x9f, 0x67, 0x11, 0xf4, 0x37, 0xaa, 0x3e, 0x7f, 0x64, 0x91, 0x7f, 0x6a, + 0x41, 0xdb, 0x8c, 0xef, 0xa8, 0xe9, 0x16, 0x46, 0x92, 0x14, 0x29, 0x4d, 0x09, 0x0a, 0x7d, 0x1f, + 0x47, 0x79, 0xf4, 0xc0, 0x31, 0x46, 0x29, 0x9e, 0x16, 0xfd, 0xd5, 0x46, 0x4b, 0x3e, 0xe6, 0xbf, + 0x90, 0x25, 0x43, 0xdb, 0x24, 0xff, 0x8b, 0x4a, 0x8a, 0xfc, 0xf4, 0xdf, 0x1f, 0xc2, 0x4d, 0xf8, + 0x21, 0xff, 0x29, 0x0a, 0x19, 0x1f, 0x65, 0x54, 0xfc, 0xb6, 0xdf, 0xdb, 0xf7, 0x70, 0x4e, 0x77, + 0xec, 0x1b, 0xc6, 0x9c, 0xb2, 0x8a, 0xc7, 0x1a, 0x1f, 0x9d, 0xf8, 0xe9, 0xa0, 0xf4, 0xe4, 0xcc, + 0xfd, 0x9c, 0xd0, 0xf4, 0x41, 0x8e, 0xf8, 0x20, 0x05, 0xba, 0xc1, 0x6a, 0x6f, 0xd9, 0x8c, 0xfd, + 0x00, 0xc7, 0x7a, 0xcf, 0x7e, 0x67, 0xea, 0x58, 0x1f, 0x62, 0x94, 0x86, 0x8d, 0xf8, 0x00, 0x20, + 0xbd, 0x8a, 0x42, 0x32, 0xd7, 0x20, 0x94, 0x00, 0xca, 0xdf, 0x56, 0x31, 0xf9, 0x59, 0xde, 0x96, + 0x60, 0x2d, 0xfe, 0x80, 0x8b, 0xd3, 0x1d, 0x79, 0x81, 0x42, 0xd7, 0xbe, 0xcc, 0xfb, 0x22, 0x86, + 0xf6, 0x95, 0x6d, 0xdf, 0x10, 0xa6, 0xea, 0x36, 0xc6, 0x0b, 0x68, 0xed, 0x86, 0xe1, 0xab, 0xc9, + 0x58, 0xdd, 0x8d, 0x34, 0x03, 0xa8, 0xdb, 0x5e, 0x7c, 0xd6, 0xcb, 0xcc, 0xc2, 0xbe, 0x8b, 0x4d, + 0xf5, 0x48, 0x57, 0x6b, 0xea, 0xe1, 0x4f, 0xd2, 0x6b, 0x2e, 0x9f, 0x13, 0x0f, 0xe6, 0x95, 0x8c, + 0x56, 0x03, 0xef, 0x99, 0xcd, 0x18, 0x92, 0x39, 0xdb, 0x85, 0x61, 0x26, 0xc8, 0xd1, 0x3e, 0x8c, + 0x65, 0x9b, 0x8f, 0x2c, 0x72, 0x00, 0xcd, 0x4d, 0xda, 0xc7, 0x8c, 0x51, 0x8c, 0x42, 0x2e, 0x18, + 0x91, 0x2c, 0x1e, 0xbe, 0xec, 0xb5, 0x0c, 0xa0, 0x79, 0x6e, 0x8d, 0xbd, 0xcb, 0x88, 0x7e, 0xf6, + 0xf0, 0x27, 0x22, 0xbe, 0xf9, 0xb9, 0x3c, 0xb7, 0x64, 0x00, 0xd8, 0x38, 0xb7, 0x32, 0x11, 0x63, + 0xe3, 0xdc, 0xca, 0x45, 0x8c, 0x8d, 0xa5, 0x96, 0x01, 0x68, 0x32, 0x84, 0xf9, 0x5c, 0x90, 0x59, + 0x1d, 0x59, 0xd3, 0x42, 0xd3, 0xbd, 0xbb, 0xd3, 0x11, 0xcc, 0xde, 0x1e, 0x98, 0xbd, 0x1d, 0x42, + 0x8b, 0xbf, 0x9b, 0x75, 0x4c, 0x79, 0x32, 0x48, 0xe6, 0x09, 0x06, 0x3d, 0xd5, 0x24, 0x7b, 0xc0, + 0x60, 0x9d, 0xa9, 0xe1, 0xf0, 0x07, 0x38, 0x7f, 0x00, 0x8d, 0x67, 0x34, 0x91, 0xd9, 0x1f, 0x4a, + 0xc7, 0xce, 0xa4, 0x83, 0xf4, 0x0a, 0x92, 0x47, 0x4c, 0x9a, 0xc1, 0xd6, 0x1e, 0xd2, 0xc1, 0x29, + 0xe5, 0xc2, 0xc9, 0xf5, 0x07, 0x9f, 0x93, 0xdf, 0xc3, 0xc6, 0x55, 0x2e, 0xde, 0x92, 0x76, 0x95, + 0x5f, 0x6f, 0x7c, 0x2e, 0x03, 0x2f, 0x6a, 0x39, 0x08, 0x07, 0x54, 0xd3, 0xf5, 0x02, 0x68, 0x68, + 0xb9, 0xbc, 0x8a, 0x81, 0xf2, 0xb9, 0xdb, 0x8a, 0x81, 0x0a, 0x52, 0x7f, 0xed, 0xfb, 0xd8, 0x8f, + 0x4d, 0xee, 0xa6, 0xfd, 0xf0, 0x74, 0xdf, 0xb4, 0xa7, 0x87, 0x3f, 0xf1, 0x46, 0xc9, 0xe7, 0xe4, + 0x25, 0xbe, 0x62, 0xab, 0x67, 0xb7, 0xa4, 0x46, 0x43, 0x36, 0x11, 0x46, 0x2d, 0x96, 0x56, 0x65, + 0x1a, 0x12, 0xbc, 0x2b, 0xd4, 0xe4, 0xbe, 0x01, 0x70, 0x98, 0x84, 0xe3, 0x4d, 0x8f, 0x8e, 0xc2, + 0x20, 0x95, 0xb5, 0x69, 0x6e, 0x45, 0x2a, 0xbf, 0xb4, 0x04, 0x0b, 0xf2, 0x52, 0xb3, 0xb2, 0x8c, + 0x04, 0x21, 0x49, 0x5c, 0x53, 0xd3, 0x2f, 0xd4, 0x82, 0x14, 0xa4, 0x60, 0x3c, 0xb2, 0xc8, 0x1a, + 0x40, 0x7a, 0xcb, 0x40, 0xd9, 0x4c, 0xb9, 0x0b, 0x0c, 0x4a, 0xec, 0x15, 0x5c, 0x49, 0x38, 0x80, + 0x7a, 0x1a, 0x93, 0x5d, 0x4e, 0x9f, 0x26, 0x30, 0x22, 0xb8, 0xea, 0x04, 0xcf, 0x05, 0x43, 0xed, + 0x0e, 0x2e, 0x15, 0x90, 0x1a, 0x5b, 0x2a, 0x8c, 0x70, 0xfa, 0xb0, 0xc0, 0x07, 0xa8, 0xd4, 0x25, + 0xcc, 0x09, 0x50, 0x8f, 0x15, 0xe7, 0x03, 0x92, 0x8a, 0x9b, 0x0b, 0xe3, 0x69, 0x86, 0xeb, 0x87, + 0x51, 0x2b, 0xcf, 0x47, 0x60, 0xa2, 0x79, 0x04, 0xf3, 0xb9, 0x10, 0x8d, 0x62, 0xe9, 0x69, 0x31, + 0x38, 0xc5, 0xd2, 0x53, 0xa3, 0x3b, 0xf6, 0x75, 0xec, 0x72, 0xce, 0x06, 0x34, 0xf5, 0x2e, 0xfc, + 0xa4, 0x7f, 0xc6, 0xba, 0xfb, 0x43, 0x0b, 0x16, 0x0a, 0x22, 0x30, 0xe4, 0x5d, 0xe9, 0x35, 0x98, + 0x1a, 0x9d, 0xe9, 0x15, 0x3a, 0xe8, 0xed, 0x43, 0xec, 0xe7, 0x39, 0xf9, 0xd4, 0x38, 0xd8, 0xb8, + 0x6f, 0x5c, 0x70, 0xe6, 0x95, 0x4a, 0x45, 0xa1, 0x46, 0xf1, 0x19, 0x2c, 0xf3, 0x81, 0xac, 0x0d, + 0x87, 0x99, 0xe0, 0xc1, 0x9d, 0xdc, 0xaf, 0xe8, 0x1a, 0x41, 0x91, 0xde, 0xf4, 0x5f, 0xd9, 0x9d, + 0xa2, 0x4e, 0xf3, 0xa1, 0x92, 0x09, 0x74, 0xb2, 0x0e, 0x79, 0x32, 0xbd, 0xad, 0xde, 0x3b, 0x86, + 0xfd, 0x5b, 0xe0, 0xc4, 0xff, 0x2d, 0xec, 0xec, 0x1d, 0xbb, 0x57, 0xb4, 0x2e, 0xdc, 0x24, 0x66, + 0xfb, 0xf1, 0x97, 0x55, 0xf4, 0x20, 0x33, 0x4f, 0xd9, 0xc1, 0xb4, 0x70, 0x87, 0xb2, 0xc0, 0x8b, + 0x83, 0x0f, 0xef, 0x61, 0xf7, 0x77, 0xed, 0x9b, 0x45, 0xdd, 0x47, 0xfc, 0x13, 0x6e, 0x8b, 0x2f, + 0x67, 0xf9, 0x5a, 0x8e, 0xe0, 0x6e, 0xd1, 0x7e, 0x4f, 0xb5, 0x85, 0x32, 0x6b, 0x7d, 0x0d, 0x75, + 0xbb, 0xa6, 0x1e, 0x2d, 0x50, 0xec, 0x53, 0x10, 0x96, 0x50, 0xec, 0x53, 0x14, 0x5e, 0x30, 0xf5, + 0x1a, 0x19, 0x58, 0xf8, 0xd8, 0x7a, 0xb0, 0xfe, 0xfe, 0xf7, 0x7f, 0xeb, 0xd4, 0x4f, 0xce, 0x26, + 0xc7, 0x2b, 0xfd, 0x70, 0xf4, 0x70, 0x28, 0xbd, 0x8d, 0x22, 0x4f, 0xee, 0xe1, 0x30, 0x18, 0x3c, + 0xc4, 0x66, 0x8f, 0x67, 0xf0, 0x67, 0xbf, 0xbf, 0xf6, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xd5, + 0x81, 0xeb, 0xf5, 0x28, 0x7c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 8e39cf6d1a..d1723014cd 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1385,6 +1385,12 @@ message ListChannelsRequest { bool inactive_only = 2; bool public_only = 3; bool private_only = 4; + + /** + Filters the response for channels with a target peer's pubkey. If peer is + empty, all channels will be returned. + */ + bytes peer = 5; } message ListChannelsResponse { /// The list of active channels diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 1adabfb989..795c91d4a6 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -116,6 +116,14 @@ "required": false, "type": "boolean", "format": "boolean" + }, + { + "name": "peer", + "description": "*\nFilters the response for channels with a target peer's pubkey. If peer is\nempty, all channels will be returned.", + "in": "query", + "required": false, + "type": "string", + "format": "byte" } ], "tags": [ diff --git a/rpcserver.go b/rpcserver.go index e0639aef58..232a865106 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2948,6 +2948,11 @@ func (r *rpcServer) ListChannels(ctx context.Context, "`private_only` can be set, but not both") } + if len(in.Peer) > 0 && len(in.Peer) != 33 { + _, err := route.NewVertexFromBytes(in.Peer) + return nil, fmt.Errorf("invalid `peer` key: %v", err) + } + resp := &lnrpc.ListChannelsResponse{} graph := r.server.chanDB.ChannelGraph() @@ -2962,8 +2967,15 @@ func (r *rpcServer) ListChannels(ctx context.Context, for _, dbChannel := range dbChannels { nodePub := dbChannel.IdentityPub + nodePubBytes := nodePub.SerializeCompressed() chanPoint := dbChannel.FundingOutpoint + // If the caller requested channels for a target node, skip any + // that don't match the provided pubkey. + if len(in.Peer) > 0 && !bytes.Equal(nodePubBytes, in.Peer) { + continue + } + var peerOnline bool if _, err := r.server.FindPeer(nodePub); err == nil { peerOnline = true From e4090c3c67fb486d5f317e480c75f1e4e97b9a29 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 6 Mar 2020 13:33:09 -0800 Subject: [PATCH 132/562] peer: remove unused failedChannels channels map --- peer.go | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/peer.go b/peer.go index 02544fe4f2..4c8369f1de 100644 --- a/peer.go +++ b/peer.go @@ -210,14 +210,6 @@ type peer struct { // the connection handshake. remoteFeatures *lnwire.FeatureVector - // failedChannels is a set that tracks channels we consider `failed`. - // This is a temporary measure until we have implemented real failure - // handling at the link level, to handle the case where we reconnect to - // a peer and try to re-sync a failed channel, triggering a disconnect - // loop. - // TODO(halseth): remove when link failure is properly handled. - failedChannels map[lnwire.ChannelID]struct{} - // writePool is the task pool to that manages reuse of write buffers. // Write tasks are submitted to the pool in order to conserve the total // number of write buffers allocated at any one time, and decouple write @@ -274,7 +266,6 @@ func newPeer(conn net.Conn, connReq *connmgr.ConnReq, server *server, localCloseChanReqs: make(chan *htlcswitch.ChanClose), linkFailures: make(chan linkFailureReport), chanCloseMsgs: make(chan *closeMsg), - failedChannels: make(map[lnwire.ChannelID]struct{}), chanActiveTimeout: chanActiveTimeout, @@ -488,14 +479,6 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) ( continue } - // Also skip adding any channel marked as `failed` for this - // session. - if _, ok := p.failedChannels[chanID]; ok { - peerLog.Warnf("ChannelPoint(%v) is failed, won't "+ - "start.", chanPoint) - continue - } - _, currentHeight, err := p.server.cc.chainIO.GetBestBlock() if err != nil { return nil, err @@ -1203,12 +1186,8 @@ func (p *peer) handleError(msg *lnwire.Error) bool { // In the case of an all-zero channel ID we want to forward the error to // all channels with this peer. case msg.ChanID == lnwire.ConnectionWideID: - for chanID, chanStream := range p.activeMsgStreams { + for _, chanStream := range p.activeMsgStreams { chanStream.AddMsg(msg) - - // Also marked this channel as failed, so we won't try - // to restart it on reconnect with this peer. - p.failedChannels[chanID] = struct{}{} } return false @@ -1220,9 +1199,6 @@ func (p *peer) handleError(msg *lnwire.Error) bool { // If not we hand the error to the channel link for this channel. case p.isActiveChannel(msg.ChanID): - // Mark this channel as failed, so we won't try to restart it on - // reconnect with this peer. - p.failedChannels[msg.ChanID] = struct{}{} return true default: From 46f4da0b6b768e7d361acd465c665d8357533495 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 6 Mar 2020 16:01:47 -0800 Subject: [PATCH 133/562] tor: move AddOnion to its own file --- tor/add_onion.go | 149 ++++++++++++++++++++++++++++++++++++++++++++++ tor/controller.go | 142 ------------------------------------------- 2 files changed, 149 insertions(+), 142 deletions(-) create mode 100644 tor/add_onion.go diff --git a/tor/add_onion.go b/tor/add_onion.go new file mode 100644 index 0000000000..8825144e06 --- /dev/null +++ b/tor/add_onion.go @@ -0,0 +1,149 @@ +package tor + +import ( + "errors" + "fmt" + "io/ioutil" + "os" +) + +// OnionType denotes the type of the onion service. +type OnionType int + +const ( + // V2 denotes that the onion service is V2. + V2 OnionType = iota + + // V3 denotes that the onion service is V3. + V3 +) + +// AddOnionConfig houses all of the required parameters in order to successfully +// create a new onion service or restore an existing one. +type AddOnionConfig struct { + // Type denotes the type of the onion service that should be created. + Type OnionType + + // VirtualPort is the externally reachable port of the onion address. + VirtualPort int + + // TargetPorts is the set of ports that the service will be listening on + // locally. The Tor server will use choose a random port from this set + // to forward the traffic from the virtual port. + // + // NOTE: If nil/empty, the virtual port will be used as the only target + // port. + TargetPorts []int + + // PrivateKeyPath is the full path to where the onion service's private + // key is stored. This can be used to restore an existing onion service. + PrivateKeyPath string +} + +// AddOnion creates an onion service and returns its onion address. Once +// created, the new onion service will remain active until the connection +// between the controller and the Tor server is closed. +func (c *Controller) AddOnion(cfg AddOnionConfig) (*OnionAddr, error) { + // Before sending the request to create an onion service to the Tor + // server, we'll make sure that it supports V3 onion services if that + // was the type requested. + if cfg.Type == V3 { + if err := supportsV3(c.version); err != nil { + return nil, err + } + } + + // We'll start off by checking if the file containing the private key + // exists. If it does not, then we should request the server to create + // a new onion service and return its private key. Otherwise, we'll + // request the server to recreate the onion server from our private key. + var keyParam string + if _, err := os.Stat(cfg.PrivateKeyPath); os.IsNotExist(err) { + switch cfg.Type { + case V2: + keyParam = "NEW:RSA1024" + case V3: + keyParam = "NEW:ED25519-V3" + } + } else { + privateKey, err := ioutil.ReadFile(cfg.PrivateKeyPath) + if err != nil { + return nil, err + } + keyParam = string(privateKey) + } + + // Now, we'll create a mapping from the virtual port to each target + // port. If no target ports were specified, we'll use the virtual port + // to provide a one-to-one mapping. + var portParam string + + // Helper function which appends the correct Port param depending on + // whether the user chose to use a custom target IP address or not. + pushPortParam := func(targetPort int) { + if c.targetIPAddress == "" { + portParam += fmt.Sprintf("Port=%d,%d ", cfg.VirtualPort, + targetPort) + } else { + portParam += fmt.Sprintf("Port=%d,%s:%d ", cfg.VirtualPort, + c.targetIPAddress, targetPort) + } + } + + if len(cfg.TargetPorts) == 0 { + pushPortParam(cfg.VirtualPort) + } else { + for _, targetPort := range cfg.TargetPorts { + pushPortParam(targetPort) + } + } + + // Send the command to create the onion service to the Tor server and + // await its response. + cmd := fmt.Sprintf("ADD_ONION %s %s", keyParam, portParam) + _, reply, err := c.sendCommand(cmd) + if err != nil { + return nil, err + } + + // If successful, the reply from the server should be of the following + // format, depending on whether a private key has been requested: + // + // C: ADD_ONION RSA1024:[Blob Redacted] Port=80,8080 + // S: 250-ServiceID=testonion1234567 + // S: 250 OK + // + // C: ADD_ONION NEW:RSA1024 Port=80,8080 + // S: 250-ServiceID=testonion1234567 + // S: 250-PrivateKey=RSA1024:[Blob Redacted] + // S: 250 OK + // + // We're interested in retrieving the service ID, which is the public + // name of the service, and the private key if requested. + replyParams := parseTorReply(reply) + serviceID, ok := replyParams["ServiceID"] + if !ok { + return nil, errors.New("service id not found in reply") + } + + // If a new onion service was created, we'll write its private key to + // disk under strict permissions in the event that it needs to be + // recreated later on. + if privateKey, ok := replyParams["PrivateKey"]; ok { + err := ioutil.WriteFile( + cfg.PrivateKeyPath, []byte(privateKey), 0600, + ) + if err != nil { + return nil, fmt.Errorf("unable to write private key "+ + "to file: %v", err) + } + } + + // Finally, we'll return the onion address composed of the service ID, + // along with the onion suffix, and the port this onion service can be + // reached at externally. + return &OnionAddr{ + OnionService: serviceID + ".onion", + Port: cfg.VirtualPort, + }, nil +} diff --git a/tor/controller.go b/tor/controller.go index 149e766b41..48d71c6525 100644 --- a/tor/controller.go +++ b/tor/controller.go @@ -10,7 +10,6 @@ import ( "fmt" "io/ioutil" "net/textproto" - "os" "strconv" "strings" "sync/atomic" @@ -403,144 +402,3 @@ func (c *Controller) ProtocolInfo() ([]string, string, string, error) { return authMethods, cookieFilePath, torVersion, nil } - -// OnionType denotes the type of the onion service. -type OnionType int - -const ( - // V2 denotes that the onion service is V2. - V2 OnionType = iota - - // V3 denotes that the onion service is V3. - V3 -) - -// AddOnionConfig houses all of the required parameters in order to successfully -// create a new onion service or restore an existing one. -type AddOnionConfig struct { - // Type denotes the type of the onion service that should be created. - Type OnionType - - // VirtualPort is the externally reachable port of the onion address. - VirtualPort int - - // TargetPorts is the set of ports that the service will be listening on - // locally. The Tor server will use choose a random port from this set - // to forward the traffic from the virtual port. - // - // NOTE: If nil/empty, the virtual port will be used as the only target - // port. - TargetPorts []int - - // PrivateKeyPath is the full path to where the onion service's private - // key is stored. This can be used to restore an existing onion service. - PrivateKeyPath string -} - -// AddOnion creates an onion service and returns its onion address. Once -// created, the new onion service will remain active until the connection -// between the controller and the Tor server is closed. -func (c *Controller) AddOnion(cfg AddOnionConfig) (*OnionAddr, error) { - // Before sending the request to create an onion service to the Tor - // server, we'll make sure that it supports V3 onion services if that - // was the type requested. - if cfg.Type == V3 { - if err := supportsV3(c.version); err != nil { - return nil, err - } - } - - // We'll start off by checking if the file containing the private key - // exists. If it does not, then we should request the server to create - // a new onion service and return its private key. Otherwise, we'll - // request the server to recreate the onion server from our private key. - var keyParam string - if _, err := os.Stat(cfg.PrivateKeyPath); os.IsNotExist(err) { - switch cfg.Type { - case V2: - keyParam = "NEW:RSA1024" - case V3: - keyParam = "NEW:ED25519-V3" - } - } else { - privateKey, err := ioutil.ReadFile(cfg.PrivateKeyPath) - if err != nil { - return nil, err - } - keyParam = string(privateKey) - } - - // Now, we'll create a mapping from the virtual port to each target - // port. If no target ports were specified, we'll use the virtual port - // to provide a one-to-one mapping. - var portParam string - - // Helper function which appends the correct Port param depending on - // whether the user chose to use a custom target IP address or not. - pushPortParam := func(targetPort int) { - if c.targetIPAddress == "" { - portParam += fmt.Sprintf("Port=%d,%d ", cfg.VirtualPort, - targetPort) - } else { - portParam += fmt.Sprintf("Port=%d,%s:%d ", cfg.VirtualPort, - c.targetIPAddress, targetPort) - } - } - - if len(cfg.TargetPorts) == 0 { - pushPortParam(cfg.VirtualPort) - } else { - for _, targetPort := range cfg.TargetPorts { - pushPortParam(targetPort) - } - } - - // Send the command to create the onion service to the Tor server and - // await its response. - cmd := fmt.Sprintf("ADD_ONION %s %s", keyParam, portParam) - _, reply, err := c.sendCommand(cmd) - if err != nil { - return nil, err - } - - // If successful, the reply from the server should be of the following - // format, depending on whether a private key has been requested: - // - // C: ADD_ONION RSA1024:[Blob Redacted] Port=80,8080 - // S: 250-ServiceID=testonion1234567 - // S: 250 OK - // - // C: ADD_ONION NEW:RSA1024 Port=80,8080 - // S: 250-ServiceID=testonion1234567 - // S: 250-PrivateKey=RSA1024:[Blob Redacted] - // S: 250 OK - // - // We're interested in retrieving the service ID, which is the public - // name of the service, and the private key if requested. - replyParams := parseTorReply(reply) - serviceID, ok := replyParams["ServiceID"] - if !ok { - return nil, errors.New("service id not found in reply") - } - - // If a new onion service was created, we'll write its private key to - // disk under strict permissions in the event that it needs to be - // recreated later on. - if privateKey, ok := replyParams["PrivateKey"]; ok { - err := ioutil.WriteFile( - cfg.PrivateKeyPath, []byte(privateKey), 0600, - ) - if err != nil { - return nil, fmt.Errorf("unable to write private key "+ - "to file: %v", err) - } - } - - // Finally, we'll return the onion address composed of the service ID, - // along with the onion suffix, and the port this onion service can be - // reached at externally. - return &OnionAddr{ - OnionService: serviceID + ".onion", - Port: cfg.VirtualPort, - }, nil -} From 2dfd6a7a3e28b3269b8c2ecb5cb387e114242724 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 6 Mar 2020 16:26:51 -0800 Subject: [PATCH 134/562] tor+server: add OnionStore to AddOnionConfig with file-based impl In this commit, we modify the AddOnionConfig struct to include an abstract OnionStore, which will be responsible for storing all relevant information of an onion service. We also add a file-based implementation of the interface to maintain the same behavior of storing an onion service's private key in a file. --- server.go | 6 +-- tor/add_onion.go | 114 +++++++++++++++++++++++++++++++++--------- tor/add_onion_test.go | 51 +++++++++++++++++++ 3 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 tor/add_onion_test.go diff --git a/server.go b/server.go index bde65671ad..5c6fce5513 100644 --- a/server.go +++ b/server.go @@ -1965,9 +1965,9 @@ func (s *server) initTorController() error { // create our onion service. The service's private key will be saved to // disk in order to regain access to this service when restarting `lnd`. onionCfg := tor.AddOnionConfig{ - VirtualPort: defaultPeerPort, - TargetPorts: listenPorts, - PrivateKeyPath: cfg.Tor.PrivateKeyPath, + VirtualPort: defaultPeerPort, + TargetPorts: listenPorts, + Store: tor.NewOnionFile(cfg.Tor.PrivateKeyPath, 0600), } switch { diff --git a/tor/add_onion.go b/tor/add_onion.go index 8825144e06..aca433ad40 100644 --- a/tor/add_onion.go +++ b/tor/add_onion.go @@ -7,6 +7,12 @@ import ( "os" ) +var ( + // ErrNoPrivateKey is an error returned by the OnionStore.PrivateKey + // method when a private key hasn't yet been stored. + ErrNoPrivateKey = errors.New("private key not found") +) + // OnionType denotes the type of the onion service. type OnionType int @@ -18,6 +24,60 @@ const ( V3 ) +// OnionStore is a store containing information about a particular onion +// service. +type OnionStore interface { + // StorePrivateKey stores the private key according to the + // implementation of the OnionStore interface. + StorePrivateKey(OnionType, []byte) error + + // PrivateKey retrieves a stored private key. If it is not found, then + // ErrNoPrivateKey should be returned. + PrivateKey(OnionType) ([]byte, error) + + // DeletePrivateKey securely removes the private key from the store. + DeletePrivateKey(OnionType) error +} + +// OnionFile is a file-based implementation of the OnionStore interface that +// stores an onion service's private key. +type OnionFile struct { + privateKeyPath string + privateKeyPerm os.FileMode +} + +// A compile-time constraint to ensure OnionFile satisfies the OnionStore +// interface. +var _ OnionStore = (*OnionFile)(nil) + +// NewOnionFile creates a file-based implementation of the OnionStore interface +// to store an onion service's private key. +func NewOnionFile(privateKeyPath string, privateKeyPerm os.FileMode) *OnionFile { + return &OnionFile{ + privateKeyPath: privateKeyPath, + privateKeyPerm: privateKeyPerm, + } +} + +// StorePrivateKey stores the private key at its expected path. +func (f *OnionFile) StorePrivateKey(_ OnionType, privateKey []byte) error { + return ioutil.WriteFile(f.privateKeyPath, privateKey, f.privateKeyPerm) +} + +// PrivateKey retrieves the private key from its expected path. If the file does +// not exist, then ErrNoPrivateKey is returned. +func (f *OnionFile) PrivateKey(_ OnionType) ([]byte, error) { + if _, err := os.Stat(f.privateKeyPath); os.IsNotExist(err) { + return nil, ErrNoPrivateKey + } + return ioutil.ReadFile(f.privateKeyPath) +} + +// DeletePrivateKey removes the file containing the private key. +func (f *OnionFile) DeletePrivateKey(_ OnionType) error { + return os.Remove(f.privateKeyPath) +} + // AddOnionConfig houses all of the required parameters in order to successfully // create a new onion service or restore an existing one. type AddOnionConfig struct { @@ -35,9 +95,12 @@ type AddOnionConfig struct { // port. TargetPorts []int - // PrivateKeyPath is the full path to where the onion service's private - // key is stored. This can be used to restore an existing onion service. - PrivateKeyPath string + // Store is responsible for storing all onion service related + // information. + // + // NOTE: If not specified, then nothing will be stored, making onion + // services unrecoverable after shutdown. + Store OnionStore } // AddOnion creates an onion service and returns its onion address. Once @@ -53,24 +116,31 @@ func (c *Controller) AddOnion(cfg AddOnionConfig) (*OnionAddr, error) { } } - // We'll start off by checking if the file containing the private key - // exists. If it does not, then we should request the server to create - // a new onion service and return its private key. Otherwise, we'll + // We'll start off by checking if the store contains an existing private + // key. If it does not, then we should request the server to create a + // new onion service and return its private key. Otherwise, we'll // request the server to recreate the onion server from our private key. var keyParam string - if _, err := os.Stat(cfg.PrivateKeyPath); os.IsNotExist(err) { - switch cfg.Type { - case V2: - keyParam = "NEW:RSA1024" - case V3: - keyParam = "NEW:ED25519-V3" - } - } else { - privateKey, err := ioutil.ReadFile(cfg.PrivateKeyPath) - if err != nil { + switch cfg.Type { + case V2: + keyParam = "NEW:RSA1024" + case V3: + keyParam = "NEW:ED25519-V3" + } + + if cfg.Store != nil { + privateKey, err := cfg.Store.PrivateKey(cfg.Type) + switch err { + // Proceed to request a new onion service. + case ErrNoPrivateKey: + + // Recover the onion service with the private key found. + case nil: + keyParam = string(privateKey) + + default: return nil, err } - keyParam = string(privateKey) } // Now, we'll create a mapping from the virtual port to each target @@ -126,13 +196,11 @@ func (c *Controller) AddOnion(cfg AddOnionConfig) (*OnionAddr, error) { return nil, errors.New("service id not found in reply") } - // If a new onion service was created, we'll write its private key to - // disk under strict permissions in the event that it needs to be + // If a new onion service was created and an onion store was provided, + // we'll store its private key to disk in the event that it needs to be // recreated later on. - if privateKey, ok := replyParams["PrivateKey"]; ok { - err := ioutil.WriteFile( - cfg.PrivateKeyPath, []byte(privateKey), 0600, - ) + if privateKey, ok := replyParams["PrivateKey"]; cfg.Store != nil && ok { + err := cfg.Store.StorePrivateKey(cfg.Type, []byte(privateKey)) if err != nil { return nil, fmt.Errorf("unable to write private key "+ "to file: %v", err) diff --git a/tor/add_onion_test.go b/tor/add_onion_test.go new file mode 100644 index 0000000000..9cd255d323 --- /dev/null +++ b/tor/add_onion_test.go @@ -0,0 +1,51 @@ +package tor + +import ( + "bytes" + "io/ioutil" + "path/filepath" + "testing" +) + +// TestOnionFile tests that the OnionFile implementation of the OnionStore +// interface behaves as expected. +func TestOnionFile(t *testing.T) { + t.Parallel() + + tempDir, err := ioutil.TempDir("", "onion_store") + if err != nil { + t.Fatalf("unable to create temp dir: %v", err) + } + + privateKey := []byte("hide_me_plz") + privateKeyPath := filepath.Join(tempDir, "secret") + + // Create a new file-based onion store. A private key should not exist + // yet. + onionFile := NewOnionFile(privateKeyPath, 0600) + if _, err := onionFile.PrivateKey(V2); err != ErrNoPrivateKey { + t.Fatalf("expected ErrNoPrivateKey, got \"%v\"", err) + } + + // Store the private key and ensure what's stored matches. + if err := onionFile.StorePrivateKey(V2, privateKey); err != nil { + t.Fatalf("unable to store private key: %v", err) + } + storePrivateKey, err := onionFile.PrivateKey(V2) + if err != nil { + t.Fatalf("unable to retrieve private key: %v", err) + } + if !bytes.Equal(storePrivateKey, privateKey) { + t.Fatalf("expected private key \"%v\", got \"%v\"", + string(privateKey), string(storePrivateKey)) + } + + // Finally, delete the private key. We should no longer be able to + // retrieve it. + if err := onionFile.DeletePrivateKey(V2); err != nil { + t.Fatalf("unable to delete private key: %v", err) + } + if _, err := onionFile.PrivateKey(V2); err != ErrNoPrivateKey { + t.Fatal("found deleted private key") + } +} From 165769ea8262590231515bc14e807a50040258fe Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 14:11:48 +0100 Subject: [PATCH 135/562] lncli: use printRespJSON for probability response --- cmd/lncli/cmd_query_probability.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lncli/cmd_query_probability.go b/cmd/lncli/cmd_query_probability.go index 139a228f55..58c8ba1b42 100644 --- a/cmd/lncli/cmd_query_probability.go +++ b/cmd/lncli/cmd_query_probability.go @@ -64,7 +64,7 @@ func queryProb(ctx *cli.Context) error { return err } - printJSON(response) + printRespJSON(response) return nil } From e435cd5fc6326c7e8c13962b394fd48e59c80bf6 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 14:07:27 +0100 Subject: [PATCH 136/562] lncli: use original snake_case names for JSON serializing Because we now use printRespJSON everywhere where we print RPC responses as JSON, we can simply instruct the jsonpb marshaler to use the original snake_case name specified in the proto file for the JSON field names and not the default camelCase. --- cmd/lncli/commands.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 281fbed95e..608b8d3f8b 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -57,6 +57,7 @@ func printJSON(resp interface{}) { func printRespJSON(resp proto.Message) { jsonMarshaler := &jsonpb.Marshaler{ EmitDefaults: true, + OrigName: true, Indent: " ", } From b99a457dd029c7023376e267cda45486d018a20d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 13:53:39 +0100 Subject: [PATCH 137/562] lnrpc: format rpc.proto and remove json_name fields We now use the jsonpb marshaler to convert the RPC responses to JSON in lncli and REST. The jsonpb has a setting to use the original name as defined in the proto file and the explicit json_name definition is not necessary any more. The jsonpb setting is called OrigName and needs to be true. --- lnrpc/rpc.pb.go | 1829 ++++++++++++++++++++++++----------------------- lnrpc/rpc.proto | 949 ++++++++++++------------ 2 files changed, 1408 insertions(+), 1370 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 131af41fe4..04298df145 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -836,13 +836,13 @@ var xxx_messageInfo_ChangePasswordResponse proto.InternalMessageInfo type Utxo struct { /// The type of address - Type AddressType `protobuf:"varint,1,opt,name=type,json=address_type,proto3,enum=lnrpc.AddressType" json:"type,omitempty"` + Type AddressType `protobuf:"varint,1,opt,name=type,proto3,enum=lnrpc.AddressType" json:"type,omitempty"` /// The address Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` /// The value of the unspent coin in satoshis - AmountSat int64 `protobuf:"varint,3,opt,name=amount_sat,proto3" json:"amount_sat,omitempty"` + AmountSat int64 `protobuf:"varint,3,opt,name=amount_sat,json=amountSat,proto3" json:"amount_sat,omitempty"` /// The pkscript in hex - PkScript string `protobuf:"bytes,4,opt,name=pk_script,proto3" json:"pk_script,omitempty"` + PkScript string `protobuf:"bytes,4,opt,name=pk_script,json=pkScript,proto3" json:"pk_script,omitempty"` /// The outpoint in format txid:n Outpoint *OutPoint `protobuf:"bytes,5,opt,name=outpoint,proto3" json:"outpoint,omitempty"` /// The number of confirmations for the Utxo @@ -921,23 +921,23 @@ func (m *Utxo) GetConfirmations() int64 { type Transaction struct { /// The transaction hash - TxHash string `protobuf:"bytes,1,opt,name=tx_hash,proto3" json:"tx_hash,omitempty"` + TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` /// The transaction amount, denominated in satoshis Amount int64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` /// The number of confirmations - NumConfirmations int32 `protobuf:"varint,3,opt,name=num_confirmations,proto3" json:"num_confirmations,omitempty"` + NumConfirmations int32 `protobuf:"varint,3,opt,name=num_confirmations,json=numConfirmations,proto3" json:"num_confirmations,omitempty"` /// The hash of the block this transaction was included in - BlockHash string `protobuf:"bytes,4,opt,name=block_hash,proto3" json:"block_hash,omitempty"` + BlockHash string `protobuf:"bytes,4,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` /// The height of the block this transaction was included in - BlockHeight int32 `protobuf:"varint,5,opt,name=block_height,proto3" json:"block_height,omitempty"` + BlockHeight int32 `protobuf:"varint,5,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` /// Timestamp of this transaction - TimeStamp int64 `protobuf:"varint,6,opt,name=time_stamp,proto3" json:"time_stamp,omitempty"` + TimeStamp int64 `protobuf:"varint,6,opt,name=time_stamp,json=timeStamp,proto3" json:"time_stamp,omitempty"` /// Fees paid for this transaction - TotalFees int64 `protobuf:"varint,7,opt,name=total_fees,proto3" json:"total_fees,omitempty"` + TotalFees int64 `protobuf:"varint,7,opt,name=total_fees,json=totalFees,proto3" json:"total_fees,omitempty"` /// Addresses that received funds for this transaction - DestAddresses []string `protobuf:"bytes,8,rep,name=dest_addresses,proto3" json:"dest_addresses,omitempty"` + DestAddresses []string `protobuf:"bytes,8,rep,name=dest_addresses,json=destAddresses,proto3" json:"dest_addresses,omitempty"` /// The raw transaction hex. - RawTxHex string `protobuf:"bytes,9,opt,name=raw_tx_hex,proto3" json:"raw_tx_hex,omitempty"` + RawTxHex string `protobuf:"bytes,9,opt,name=raw_tx_hex,json=rawTxHex,proto3" json:"raw_tx_hex,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1405,10 +1405,10 @@ func (m *SendRequest) GetDestFeatures() []FeatureBit { } type SendResponse struct { - PaymentError string `protobuf:"bytes,1,opt,name=payment_error,proto3" json:"payment_error,omitempty"` - PaymentPreimage []byte `protobuf:"bytes,2,opt,name=payment_preimage,proto3" json:"payment_preimage,omitempty"` - PaymentRoute *Route `protobuf:"bytes,3,opt,name=payment_route,proto3" json:"payment_route,omitempty"` - PaymentHash []byte `protobuf:"bytes,4,opt,name=payment_hash,proto3" json:"payment_hash,omitempty"` + PaymentError string `protobuf:"bytes,1,opt,name=payment_error,json=paymentError,proto3" json:"payment_error,omitempty"` + PaymentPreimage []byte `protobuf:"bytes,2,opt,name=payment_preimage,json=paymentPreimage,proto3" json:"payment_preimage,omitempty"` + PaymentRoute *Route `protobuf:"bytes,3,opt,name=payment_route,json=paymentRoute,proto3" json:"payment_route,omitempty"` + PaymentHash []byte `protobuf:"bytes,4,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1735,7 +1735,7 @@ type ChannelPoint struct { // *ChannelPoint_FundingTxidStr FundingTxid isChannelPoint_FundingTxid `protobuf_oneof:"funding_txid"` /// The index of the output of the funding transaction - OutputIndex uint32 `protobuf:"varint,3,opt,name=output_index,proto3" json:"output_index,omitempty"` + OutputIndex uint32 `protobuf:"varint,3,opt,name=output_index,json=outputIndex,proto3" json:"output_index,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1771,11 +1771,11 @@ type isChannelPoint_FundingTxid interface { } type ChannelPoint_FundingTxidBytes struct { - FundingTxidBytes []byte `protobuf:"bytes,1,opt,name=funding_txid_bytes,proto3,oneof"` + FundingTxidBytes []byte `protobuf:"bytes,1,opt,name=funding_txid_bytes,json=fundingTxidBytes,proto3,oneof"` } type ChannelPoint_FundingTxidStr struct { - FundingTxidStr string `protobuf:"bytes,2,opt,name=funding_txid_str,proto3,oneof"` + FundingTxidStr string `protobuf:"bytes,2,opt,name=funding_txid_str,json=fundingTxidStr,proto3,oneof"` } func (*ChannelPoint_FundingTxidBytes) isChannelPoint_FundingTxid() {} @@ -1820,11 +1820,11 @@ func (*ChannelPoint) XXX_OneofWrappers() []interface{} { type OutPoint struct { /// Raw bytes representing the transaction id. - TxidBytes []byte `protobuf:"bytes,1,opt,name=txid_bytes,proto3" json:"txid_bytes,omitempty"` + TxidBytes []byte `protobuf:"bytes,1,opt,name=txid_bytes,json=txidBytes,proto3" json:"txid_bytes,omitempty"` /// Reversed, hex-encoded string representing the transaction id. - TxidStr string `protobuf:"bytes,2,opt,name=txid_str,proto3" json:"txid_str,omitempty"` + TxidStr string `protobuf:"bytes,2,opt,name=txid_str,json=txidStr,proto3" json:"txid_str,omitempty"` /// The index of the output on the transaction. - OutputIndex uint32 `protobuf:"varint,3,opt,name=output_index,proto3" json:"output_index,omitempty"` + OutputIndex uint32 `protobuf:"varint,3,opt,name=output_index,json=outputIndex,proto3" json:"output_index,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1976,9 +1976,9 @@ func (m *EstimateFeeRequest) GetTargetConf() int32 { type EstimateFeeResponse struct { /// The total fee in satoshis. - FeeSat int64 `protobuf:"varint,1,opt,name=fee_sat,proto3" json:"fee_sat,omitempty"` + FeeSat int64 `protobuf:"varint,1,opt,name=fee_sat,json=feeSat,proto3" json:"fee_sat,omitempty"` /// The fee rate in satoshi/byte. - FeerateSatPerByte int64 `protobuf:"varint,2,opt,name=feerate_sat_per_byte,proto3" json:"feerate_sat_per_byte,omitempty"` + FeerateSatPerByte int64 `protobuf:"varint,2,opt,name=feerate_sat_per_byte,json=feerateSatPerByte,proto3" json:"feerate_sat_per_byte,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2674,7 +2674,7 @@ var xxx_messageInfo_ConnectPeerResponse proto.InternalMessageInfo type DisconnectPeerRequest struct { /// The pubkey of the node to disconnect from - PubKey string `protobuf:"bytes,1,opt,name=pub_key,proto3" json:"pub_key,omitempty"` + PubKey string `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2746,8 +2746,8 @@ var xxx_messageInfo_DisconnectPeerResponse proto.InternalMessageInfo type HTLC struct { Incoming bool `protobuf:"varint,1,opt,name=incoming,proto3" json:"incoming,omitempty"` Amount int64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` - HashLock []byte `protobuf:"bytes,3,opt,name=hash_lock,proto3" json:"hash_lock,omitempty"` - ExpirationHeight uint32 `protobuf:"varint,4,opt,name=expiration_height,proto3" json:"expiration_height,omitempty"` + HashLock []byte `protobuf:"bytes,3,opt,name=hash_lock,json=hashLock,proto3" json:"hash_lock,omitempty"` + ExpirationHeight uint32 `protobuf:"varint,4,opt,name=expiration_height,json=expirationHeight,proto3" json:"expiration_height,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2810,71 +2810,71 @@ type Channel struct { /// Whether this channel is active or not Active bool `protobuf:"varint,1,opt,name=active,proto3" json:"active,omitempty"` /// The identity pubkey of the remote node - RemotePubkey string `protobuf:"bytes,2,opt,name=remote_pubkey,proto3" json:"remote_pubkey,omitempty"` + RemotePubkey string `protobuf:"bytes,2,opt,name=remote_pubkey,json=remotePubkey,proto3" json:"remote_pubkey,omitempty"` //* //The outpoint (txid:index) of the funding transaction. With this value, Bob //will be able to generate a signature for Alice's version of the commitment //transaction. - ChannelPoint string `protobuf:"bytes,3,opt,name=channel_point,proto3" json:"channel_point,omitempty"` + ChannelPoint string `protobuf:"bytes,3,opt,name=channel_point,json=channelPoint,proto3" json:"channel_point,omitempty"` //* //The unique channel ID for the channel. The first 3 bytes are the block //height, the next 3 the index within the block, and the last 2 bytes are the //output index for the channel. - ChanId uint64 `protobuf:"varint,4,opt,name=chan_id,proto3" json:"chan_id,omitempty"` + ChanId uint64 `protobuf:"varint,4,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` /// The total amount of funds held in this channel Capacity int64 `protobuf:"varint,5,opt,name=capacity,proto3" json:"capacity,omitempty"` /// This node's current balance in this channel - LocalBalance int64 `protobuf:"varint,6,opt,name=local_balance,proto3" json:"local_balance,omitempty"` + LocalBalance int64 `protobuf:"varint,6,opt,name=local_balance,json=localBalance,proto3" json:"local_balance,omitempty"` /// The counterparty's current balance in this channel - RemoteBalance int64 `protobuf:"varint,7,opt,name=remote_balance,proto3" json:"remote_balance,omitempty"` + RemoteBalance int64 `protobuf:"varint,7,opt,name=remote_balance,json=remoteBalance,proto3" json:"remote_balance,omitempty"` //* //The amount calculated to be paid in fees for the current set of commitment //transactions. The fee amount is persisted with the channel in order to //allow the fee amount to be removed and recalculated with each channel state //update, including updates that happen after a system restart. - CommitFee int64 `protobuf:"varint,8,opt,name=commit_fee,proto3" json:"commit_fee,omitempty"` + CommitFee int64 `protobuf:"varint,8,opt,name=commit_fee,json=commitFee,proto3" json:"commit_fee,omitempty"` /// The weight of the commitment transaction - CommitWeight int64 `protobuf:"varint,9,opt,name=commit_weight,proto3" json:"commit_weight,omitempty"` + CommitWeight int64 `protobuf:"varint,9,opt,name=commit_weight,json=commitWeight,proto3" json:"commit_weight,omitempty"` //* //The required number of satoshis per kilo-weight that the requester will pay //at all times, for both the funding transaction and commitment transaction. //This value can later be updated once the channel is open. - FeePerKw int64 `protobuf:"varint,10,opt,name=fee_per_kw,proto3" json:"fee_per_kw,omitempty"` + FeePerKw int64 `protobuf:"varint,10,opt,name=fee_per_kw,json=feePerKw,proto3" json:"fee_per_kw,omitempty"` /// The unsettled balance in this channel - UnsettledBalance int64 `protobuf:"varint,11,opt,name=unsettled_balance,proto3" json:"unsettled_balance,omitempty"` + UnsettledBalance int64 `protobuf:"varint,11,opt,name=unsettled_balance,json=unsettledBalance,proto3" json:"unsettled_balance,omitempty"` //* //The total number of satoshis we've sent within this channel. - TotalSatoshisSent int64 `protobuf:"varint,12,opt,name=total_satoshis_sent,proto3" json:"total_satoshis_sent,omitempty"` + TotalSatoshisSent int64 `protobuf:"varint,12,opt,name=total_satoshis_sent,json=totalSatoshisSent,proto3" json:"total_satoshis_sent,omitempty"` //* //The total number of satoshis we've received within this channel. - TotalSatoshisReceived int64 `protobuf:"varint,13,opt,name=total_satoshis_received,proto3" json:"total_satoshis_received,omitempty"` + TotalSatoshisReceived int64 `protobuf:"varint,13,opt,name=total_satoshis_received,json=totalSatoshisReceived,proto3" json:"total_satoshis_received,omitempty"` //* //The total number of updates conducted within this channel. - NumUpdates uint64 `protobuf:"varint,14,opt,name=num_updates,proto3" json:"num_updates,omitempty"` + NumUpdates uint64 `protobuf:"varint,14,opt,name=num_updates,json=numUpdates,proto3" json:"num_updates,omitempty"` //* //The list of active, uncleared HTLCs currently pending within the channel. - PendingHtlcs []*HTLC `protobuf:"bytes,15,rep,name=pending_htlcs,proto3" json:"pending_htlcs,omitempty"` + PendingHtlcs []*HTLC `protobuf:"bytes,15,rep,name=pending_htlcs,json=pendingHtlcs,proto3" json:"pending_htlcs,omitempty"` //* //The CSV delay expressed in relative blocks. If the channel is force closed, //we will need to wait for this many blocks before we can regain our funds. - CsvDelay uint32 `protobuf:"varint,16,opt,name=csv_delay,proto3" json:"csv_delay,omitempty"` + CsvDelay uint32 `protobuf:"varint,16,opt,name=csv_delay,json=csvDelay,proto3" json:"csv_delay,omitempty"` /// Whether this channel is advertised to the network or not. Private bool `protobuf:"varint,17,opt,name=private,proto3" json:"private,omitempty"` /// True if we were the ones that created the channel. Initiator bool `protobuf:"varint,18,opt,name=initiator,proto3" json:"initiator,omitempty"` /// A set of flags showing the current state of the channel. - ChanStatusFlags string `protobuf:"bytes,19,opt,name=chan_status_flags,proto3" json:"chan_status_flags,omitempty"` + ChanStatusFlags string `protobuf:"bytes,19,opt,name=chan_status_flags,json=chanStatusFlags,proto3" json:"chan_status_flags,omitempty"` /// The minimum satoshis this node is required to reserve in its balance. - LocalChanReserveSat int64 `protobuf:"varint,20,opt,name=local_chan_reserve_sat,proto3" json:"local_chan_reserve_sat,omitempty"` + LocalChanReserveSat int64 `protobuf:"varint,20,opt,name=local_chan_reserve_sat,json=localChanReserveSat,proto3" json:"local_chan_reserve_sat,omitempty"` //* //The minimum satoshis the other node is required to reserve in its balance. - RemoteChanReserveSat int64 `protobuf:"varint,21,opt,name=remote_chan_reserve_sat,proto3" json:"remote_chan_reserve_sat,omitempty"` + RemoteChanReserveSat int64 `protobuf:"varint,21,opt,name=remote_chan_reserve_sat,json=remoteChanReserveSat,proto3" json:"remote_chan_reserve_sat,omitempty"` //* //If true, then this channel uses the modern commitment format where the key //in the output of the remote party does not change each state. This makes //back up and recovery easier as when the channel is closed, the funds go //directly to that key. - StaticRemoteKey bool `protobuf:"varint,22,opt,name=static_remote_key,proto3" json:"static_remote_key,omitempty"` + StaticRemoteKey bool `protobuf:"varint,22,opt,name=static_remote_key,json=staticRemoteKey,proto3" json:"static_remote_key,omitempty"` //* //The number of seconds that the channel has been monitored by the channel //scoring system. Scores are currently not persisted, so this value may be @@ -2890,7 +2890,7 @@ type Channel struct { //value can be set on channel open by setting close_address in an open channel //request. If this value is not set, you can still choose a payout address by //cooperatively closing with the delivery_address field set. - CloseAddress string `protobuf:"bytes,25,opt,name=close_address,proto3" json:"close_address,omitempty"` + CloseAddress string `protobuf:"bytes,25,opt,name=close_address,json=closeAddress,proto3" json:"close_address,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -3212,37 +3212,37 @@ func (m *ListChannelsResponse) GetChannels() []*Channel { type ChannelCloseSummary struct { /// The outpoint (txid:index) of the funding transaction. - ChannelPoint string `protobuf:"bytes,1,opt,name=channel_point,proto3" json:"channel_point,omitempty"` + ChannelPoint string `protobuf:"bytes,1,opt,name=channel_point,json=channelPoint,proto3" json:"channel_point,omitempty"` /// The unique channel ID for the channel. - ChanId uint64 `protobuf:"varint,2,opt,name=chan_id,proto3" json:"chan_id,omitempty"` + ChanId uint64 `protobuf:"varint,2,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` /// The hash of the genesis block that this channel resides within. - ChainHash string `protobuf:"bytes,3,opt,name=chain_hash,proto3" json:"chain_hash,omitempty"` + ChainHash string `protobuf:"bytes,3,opt,name=chain_hash,json=chainHash,proto3" json:"chain_hash,omitempty"` /// The txid of the transaction which ultimately closed this channel. - ClosingTxHash string `protobuf:"bytes,4,opt,name=closing_tx_hash,proto3" json:"closing_tx_hash,omitempty"` + ClosingTxHash string `protobuf:"bytes,4,opt,name=closing_tx_hash,json=closingTxHash,proto3" json:"closing_tx_hash,omitempty"` /// Public key of the remote peer that we formerly had a channel with. - RemotePubkey string `protobuf:"bytes,5,opt,name=remote_pubkey,proto3" json:"remote_pubkey,omitempty"` + RemotePubkey string `protobuf:"bytes,5,opt,name=remote_pubkey,json=remotePubkey,proto3" json:"remote_pubkey,omitempty"` /// Total capacity of the channel. Capacity int64 `protobuf:"varint,6,opt,name=capacity,proto3" json:"capacity,omitempty"` /// Height at which the funding transaction was spent. - CloseHeight uint32 `protobuf:"varint,7,opt,name=close_height,proto3" json:"close_height,omitempty"` + CloseHeight uint32 `protobuf:"varint,7,opt,name=close_height,json=closeHeight,proto3" json:"close_height,omitempty"` /// Settled balance at the time of channel closure - SettledBalance int64 `protobuf:"varint,8,opt,name=settled_balance,proto3" json:"settled_balance,omitempty"` + SettledBalance int64 `protobuf:"varint,8,opt,name=settled_balance,json=settledBalance,proto3" json:"settled_balance,omitempty"` /// The sum of all the time-locked outputs at the time of channel closure - TimeLockedBalance int64 `protobuf:"varint,9,opt,name=time_locked_balance,proto3" json:"time_locked_balance,omitempty"` + TimeLockedBalance int64 `protobuf:"varint,9,opt,name=time_locked_balance,json=timeLockedBalance,proto3" json:"time_locked_balance,omitempty"` /// Details on how the channel was closed. - CloseType ChannelCloseSummary_ClosureType `protobuf:"varint,10,opt,name=close_type,proto3,enum=lnrpc.ChannelCloseSummary_ClosureType" json:"close_type,omitempty"` + CloseType ChannelCloseSummary_ClosureType `protobuf:"varint,10,opt,name=close_type,json=closeType,proto3,enum=lnrpc.ChannelCloseSummary_ClosureType" json:"close_type,omitempty"` //* //Open initiator is the party that initiated opening the channel. Note that //this value may be unknown if the channel was closed before we migrated to //store open channel information after close. - OpenInitiator ChannelCloseSummary_Initiator `protobuf:"varint,11,opt,name=open_initiator,proto3,enum=lnrpc.ChannelCloseSummary_Initiator" json:"open_initiator,omitempty"` + OpenInitiator ChannelCloseSummary_Initiator `protobuf:"varint,11,opt,name=open_initiator,json=openInitiator,proto3,enum=lnrpc.ChannelCloseSummary_Initiator" json:"open_initiator,omitempty"` //* //Close initiator indicates which party initiated the close. This value will //be unknown for channels that were cooperatively closed before we started //tracking cooperative close initiators. Note that this indicates which party //initiated a close, and it is possible for both to initiate cooperative or //force closes, although only one party's close will be confirmed on chain. - CloseInitiator ChannelCloseSummary_Initiator `protobuf:"varint,12,opt,name=close_initiator,proto3,enum=lnrpc.ChannelCloseSummary_Initiator" json:"close_initiator,omitempty"` + CloseInitiator ChannelCloseSummary_Initiator `protobuf:"varint,12,opt,name=close_initiator,json=closeInitiator,proto3,enum=lnrpc.ChannelCloseSummary_Initiator" json:"close_initiator,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -3477,23 +3477,23 @@ func (m *ClosedChannelsResponse) GetChannels() []*ChannelCloseSummary { type Peer struct { /// The identity pubkey of the peer - PubKey string `protobuf:"bytes,1,opt,name=pub_key,proto3" json:"pub_key,omitempty"` + PubKey string `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` /// Network address of the peer; eg `127.0.0.1:10011` Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"` /// Bytes of data transmitted to this peer - BytesSent uint64 `protobuf:"varint,4,opt,name=bytes_sent,proto3" json:"bytes_sent,omitempty"` + BytesSent uint64 `protobuf:"varint,4,opt,name=bytes_sent,json=bytesSent,proto3" json:"bytes_sent,omitempty"` /// Bytes of data transmitted from this peer - BytesRecv uint64 `protobuf:"varint,5,opt,name=bytes_recv,proto3" json:"bytes_recv,omitempty"` + BytesRecv uint64 `protobuf:"varint,5,opt,name=bytes_recv,json=bytesRecv,proto3" json:"bytes_recv,omitempty"` /// Satoshis sent to this peer - SatSent int64 `protobuf:"varint,6,opt,name=sat_sent,proto3" json:"sat_sent,omitempty"` + SatSent int64 `protobuf:"varint,6,opt,name=sat_sent,json=satSent,proto3" json:"sat_sent,omitempty"` /// Satoshis received from this peer - SatRecv int64 `protobuf:"varint,7,opt,name=sat_recv,proto3" json:"sat_recv,omitempty"` + SatRecv int64 `protobuf:"varint,7,opt,name=sat_recv,json=satRecv,proto3" json:"sat_recv,omitempty"` /// A channel is inbound if the counterparty initiated the channel Inbound bool `protobuf:"varint,8,opt,name=inbound,proto3" json:"inbound,omitempty"` /// Ping time to this peer - PingTime int64 `protobuf:"varint,9,opt,name=ping_time,proto3" json:"ping_time,omitempty"` + PingTime int64 `protobuf:"varint,9,opt,name=ping_time,json=pingTime,proto3" json:"ping_time,omitempty"` // The type of sync we are currently performing with this peer. - SyncType Peer_SyncType `protobuf:"varint,10,opt,name=sync_type,proto3,enum=lnrpc.Peer_SyncType" json:"sync_type,omitempty"` + SyncType Peer_SyncType `protobuf:"varint,10,opt,name=sync_type,json=syncType,proto3,enum=lnrpc.Peer_SyncType" json:"sync_type,omitempty"` /// Features advertised by the remote peer in their init message. Features map[uint32]*Feature `protobuf:"bytes,11,rep,name=features,proto3" json:"features,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -3700,7 +3700,7 @@ var xxx_messageInfo_PeerEventSubscription proto.InternalMessageInfo type PeerEvent struct { /// The identity pubkey of the peer. - PubKey string `protobuf:"bytes,1,opt,name=pub_key,proto3" json:"pub_key,omitempty"` + PubKey string `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` Type PeerEvent_EventType `protobuf:"varint,2,opt,name=type,proto3,enum=lnrpc.PeerEvent_EventType" json:"type,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -3781,29 +3781,29 @@ type GetInfoResponse struct { /// The version of the LND software that the node is running. Version string `protobuf:"bytes,14,opt,name=version,proto3" json:"version,omitempty"` /// The identity pubkey of the current node. - IdentityPubkey string `protobuf:"bytes,1,opt,name=identity_pubkey,proto3" json:"identity_pubkey,omitempty"` + IdentityPubkey string `protobuf:"bytes,1,opt,name=identity_pubkey,json=identityPubkey,proto3" json:"identity_pubkey,omitempty"` /// If applicable, the alias of the current node, e.g. "bob" Alias string `protobuf:"bytes,2,opt,name=alias,proto3" json:"alias,omitempty"` /// The color of the current node in hex code format Color string `protobuf:"bytes,17,opt,name=color,proto3" json:"color,omitempty"` /// Number of pending channels - NumPendingChannels uint32 `protobuf:"varint,3,opt,name=num_pending_channels,proto3" json:"num_pending_channels,omitempty"` + NumPendingChannels uint32 `protobuf:"varint,3,opt,name=num_pending_channels,json=numPendingChannels,proto3" json:"num_pending_channels,omitempty"` /// Number of active channels - NumActiveChannels uint32 `protobuf:"varint,4,opt,name=num_active_channels,proto3" json:"num_active_channels,omitempty"` + NumActiveChannels uint32 `protobuf:"varint,4,opt,name=num_active_channels,json=numActiveChannels,proto3" json:"num_active_channels,omitempty"` /// Number of inactive channels - NumInactiveChannels uint32 `protobuf:"varint,15,opt,name=num_inactive_channels,proto3" json:"num_inactive_channels,omitempty"` + NumInactiveChannels uint32 `protobuf:"varint,15,opt,name=num_inactive_channels,json=numInactiveChannels,proto3" json:"num_inactive_channels,omitempty"` /// Number of peers - NumPeers uint32 `protobuf:"varint,5,opt,name=num_peers,proto3" json:"num_peers,omitempty"` + NumPeers uint32 `protobuf:"varint,5,opt,name=num_peers,json=numPeers,proto3" json:"num_peers,omitempty"` /// The node's current view of the height of the best block - BlockHeight uint32 `protobuf:"varint,6,opt,name=block_height,proto3" json:"block_height,omitempty"` + BlockHeight uint32 `protobuf:"varint,6,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` /// The node's current view of the hash of the best block - BlockHash string `protobuf:"bytes,8,opt,name=block_hash,proto3" json:"block_hash,omitempty"` + BlockHash string `protobuf:"bytes,8,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` /// Timestamp of the block best known to the wallet - BestHeaderTimestamp int64 `protobuf:"varint,13,opt,name=best_header_timestamp,proto3" json:"best_header_timestamp,omitempty"` + BestHeaderTimestamp int64 `protobuf:"varint,13,opt,name=best_header_timestamp,json=bestHeaderTimestamp,proto3" json:"best_header_timestamp,omitempty"` /// Whether the wallet's view is synced to the main chain - SyncedToChain bool `protobuf:"varint,9,opt,name=synced_to_chain,proto3" json:"synced_to_chain,omitempty"` + SyncedToChain bool `protobuf:"varint,9,opt,name=synced_to_chain,json=syncedToChain,proto3" json:"synced_to_chain,omitempty"` // Whether we consider ourselves synced with the public channel graph. - SyncedToGraph bool `protobuf:"varint,18,opt,name=synced_to_graph,proto3" json:"synced_to_graph,omitempty"` + SyncedToGraph bool `protobuf:"varint,18,opt,name=synced_to_graph,json=syncedToGraph,proto3" json:"synced_to_graph,omitempty"` //* //Whether the current node is connected to testnet. This field is //deprecated and the network field should be used instead @@ -4071,7 +4071,7 @@ func (m *ConfirmationUpdate) GetNumConfsLeft() uint32 { } type ChannelOpenUpdate struct { - ChannelPoint *ChannelPoint `protobuf:"bytes,1,opt,name=channel_point,proto3" json:"channel_point,omitempty"` + ChannelPoint *ChannelPoint `protobuf:"bytes,1,opt,name=channel_point,json=channelPoint,proto3" json:"channel_point,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -4110,7 +4110,7 @@ func (m *ChannelOpenUpdate) GetChannelPoint() *ChannelPoint { } type ChannelCloseUpdate struct { - ClosingTxid []byte `protobuf:"bytes,1,opt,name=closing_txid,proto3" json:"closing_txid,omitempty"` + ClosingTxid []byte `protobuf:"bytes,1,opt,name=closing_txid,json=closingTxid,proto3" json:"closing_txid,omitempty"` Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -4173,7 +4173,7 @@ type CloseChannelRequest struct { //If the channel was opened with an upfront shutdown script and this field //is set, the request to close will fail because the channel must pay out //to the upfront shutdown addresss. - DeliveryAddress string `protobuf:"bytes,5,opt,name=delivery_address,proto3" json:"delivery_address,omitempty"` + DeliveryAddress string `protobuf:"bytes,5,opt,name=delivery_address,json=deliveryAddress,proto3" json:"delivery_address,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -4279,11 +4279,11 @@ type isCloseStatusUpdate_Update interface { } type CloseStatusUpdate_ClosePending struct { - ClosePending *PendingUpdate `protobuf:"bytes,1,opt,name=close_pending,proto3,oneof"` + ClosePending *PendingUpdate `protobuf:"bytes,1,opt,name=close_pending,json=closePending,proto3,oneof"` } type CloseStatusUpdate_ChanClose struct { - ChanClose *ChannelCloseUpdate `protobuf:"bytes,3,opt,name=chan_close,proto3,oneof"` + ChanClose *ChannelCloseUpdate `protobuf:"bytes,3,opt,name=chan_close,json=chanClose,proto3,oneof"` } func (*CloseStatusUpdate_ClosePending) isCloseStatusUpdate_Update() {} @@ -4321,7 +4321,7 @@ func (*CloseStatusUpdate) XXX_OneofWrappers() []interface{} { type PendingUpdate struct { Txid []byte `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` - OutputIndex uint32 `protobuf:"varint,2,opt,name=output_index,proto3" json:"output_index,omitempty"` + OutputIndex uint32 `protobuf:"varint,2,opt,name=output_index,json=outputIndex,proto3" json:"output_index,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -4370,15 +4370,15 @@ type OpenChannelRequest struct { //* //The pubkey of the node to open a channel with. When using REST, this field //must be encoded as base64. - NodePubkey []byte `protobuf:"bytes,2,opt,name=node_pubkey,proto3" json:"node_pubkey,omitempty"` + NodePubkey []byte `protobuf:"bytes,2,opt,name=node_pubkey,json=nodePubkey,proto3" json:"node_pubkey,omitempty"` //* //The hex encoded pubkey of the node to open a channel with. Deprecated now //that the REST gateway supports base64 encoding of bytes fields. - NodePubkeyString string `protobuf:"bytes,3,opt,name=node_pubkey_string,proto3" json:"node_pubkey_string,omitempty"` // Deprecated: Do not use. + NodePubkeyString string `protobuf:"bytes,3,opt,name=node_pubkey_string,json=nodePubkeyString,proto3" json:"node_pubkey_string,omitempty"` // Deprecated: Do not use. /// The number of satoshis the wallet should commit to the channel - LocalFundingAmount int64 `protobuf:"varint,4,opt,name=local_funding_amount,proto3" json:"local_funding_amount,omitempty"` + LocalFundingAmount int64 `protobuf:"varint,4,opt,name=local_funding_amount,json=localFundingAmount,proto3" json:"local_funding_amount,omitempty"` /// The number of satoshis to push to the remote side as part of the initial commitment state - PushSat int64 `protobuf:"varint,5,opt,name=push_sat,proto3" json:"push_sat,omitempty"` + PushSat int64 `protobuf:"varint,5,opt,name=push_sat,json=pushSat,proto3" json:"push_sat,omitempty"` /// The target number of blocks that the funding transaction should be confirmed by. TargetConf int32 `protobuf:"varint,6,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` /// A manual fee rate set in sat/byte that should be used when crafting the funding transaction. @@ -4386,13 +4386,13 @@ type OpenChannelRequest struct { /// Whether this channel should be private, not announced to the greater network. Private bool `protobuf:"varint,8,opt,name=private,proto3" json:"private,omitempty"` /// The minimum value in millisatoshi we will require for incoming HTLCs on the channel. - MinHtlcMsat int64 `protobuf:"varint,9,opt,name=min_htlc_msat,proto3" json:"min_htlc_msat,omitempty"` + MinHtlcMsat int64 `protobuf:"varint,9,opt,name=min_htlc_msat,json=minHtlcMsat,proto3" json:"min_htlc_msat,omitempty"` /// The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size. - RemoteCsvDelay uint32 `protobuf:"varint,10,opt,name=remote_csv_delay,proto3" json:"remote_csv_delay,omitempty"` + RemoteCsvDelay uint32 `protobuf:"varint,10,opt,name=remote_csv_delay,json=remoteCsvDelay,proto3" json:"remote_csv_delay,omitempty"` /// The minimum number of confirmations each one of your outputs used for the funding transaction must satisfy. - MinConfs int32 `protobuf:"varint,11,opt,name=min_confs,proto3" json:"min_confs,omitempty"` + MinConfs int32 `protobuf:"varint,11,opt,name=min_confs,json=minConfs,proto3" json:"min_confs,omitempty"` /// Whether unconfirmed outputs should be used as inputs for the funding transaction. - SpendUnconfirmed bool `protobuf:"varint,12,opt,name=spend_unconfirmed,proto3" json:"spend_unconfirmed,omitempty"` + SpendUnconfirmed bool `protobuf:"varint,12,opt,name=spend_unconfirmed,json=spendUnconfirmed,proto3" json:"spend_unconfirmed,omitempty"` // //Close address is an optional address which specifies the address to which //funds should be paid out to upon cooperative close. This field may only be @@ -4402,14 +4402,14 @@ type OpenChannelRequest struct { // //Note: If this value is set on channel creation, you will *not* be able to //cooperatively close out to a different address. - CloseAddress string `protobuf:"bytes,13,opt,name=close_address,proto3" json:"close_address,omitempty"` + CloseAddress string `protobuf:"bytes,13,opt,name=close_address,json=closeAddress,proto3" json:"close_address,omitempty"` //* //Funding shims are an optional argument that allow the caller to intercept //certain funding functionality. For example, a shim can be provided to use a //particular key for the commitment key (ideally cold) rather than use one //that is generated by the wallet as normal, or signal that signing will be //carried out in an interactive manner (PSBT based). - FundingShim *FundingShim `protobuf:"bytes,14,opt,name=funding_shim,proto3" json:"funding_shim,omitempty"` + FundingShim *FundingShim `protobuf:"bytes,14,opt,name=funding_shim,json=fundingShim,proto3" json:"funding_shim,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -4540,7 +4540,7 @@ type OpenStatusUpdate struct { //* //The pending channel ID of the created channel. This value may be used to //further the funding flow manually via the FundingStateStep method. - PendingChanId []byte `protobuf:"bytes,4,opt,name=pending_chan_id,proto3" json:"pending_chan_id,omitempty"` + PendingChanId []byte `protobuf:"bytes,4,opt,name=pending_chan_id,json=pendingChanId,proto3" json:"pending_chan_id,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -4576,11 +4576,11 @@ type isOpenStatusUpdate_Update interface { } type OpenStatusUpdate_ChanPending struct { - ChanPending *PendingUpdate `protobuf:"bytes,1,opt,name=chan_pending,proto3,oneof"` + ChanPending *PendingUpdate `protobuf:"bytes,1,opt,name=chan_pending,json=chanPending,proto3,oneof"` } type OpenStatusUpdate_ChanOpen struct { - ChanOpen *ChannelOpenUpdate `protobuf:"bytes,3,opt,name=chan_open,proto3,oneof"` + ChanOpen *ChannelOpenUpdate `protobuf:"bytes,3,opt,name=chan_open,json=chanOpen,proto3,oneof"` } func (*OpenStatusUpdate_ChanPending) isOpenStatusUpdate_Update() {} @@ -5029,12 +5029,12 @@ type PendingHTLC struct { /// The final output to be swept back to the user's wallet Outpoint string `protobuf:"bytes,3,opt,name=outpoint,proto3" json:"outpoint,omitempty"` /// The next block height at which we can spend the current stage - MaturityHeight uint32 `protobuf:"varint,4,opt,name=maturity_height,proto3" json:"maturity_height,omitempty"` + MaturityHeight uint32 `protobuf:"varint,4,opt,name=maturity_height,json=maturityHeight,proto3" json:"maturity_height,omitempty"` //* //The number of blocks remaining until the current stage can be swept. //Negative values indicate how many blocks have passed since becoming //mature. - BlocksTilMaturity int32 `protobuf:"varint,5,opt,name=blocks_til_maturity,proto3" json:"blocks_til_maturity,omitempty"` + BlocksTilMaturity int32 `protobuf:"varint,5,opt,name=blocks_til_maturity,json=blocksTilMaturity,proto3" json:"blocks_til_maturity,omitempty"` /// Indicates whether the htlc is in its first or second stage of recovery Stage uint32 `protobuf:"varint,6,opt,name=stage,proto3" json:"stage,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -5142,15 +5142,15 @@ var xxx_messageInfo_PendingChannelsRequest proto.InternalMessageInfo type PendingChannelsResponse struct { /// The balance in satoshis encumbered in pending channels - TotalLimboBalance int64 `protobuf:"varint,1,opt,name=total_limbo_balance,proto3" json:"total_limbo_balance,omitempty"` + TotalLimboBalance int64 `protobuf:"varint,1,opt,name=total_limbo_balance,json=totalLimboBalance,proto3" json:"total_limbo_balance,omitempty"` /// Channels pending opening - PendingOpenChannels []*PendingChannelsResponse_PendingOpenChannel `protobuf:"bytes,2,rep,name=pending_open_channels,proto3" json:"pending_open_channels,omitempty"` + PendingOpenChannels []*PendingChannelsResponse_PendingOpenChannel `protobuf:"bytes,2,rep,name=pending_open_channels,json=pendingOpenChannels,proto3" json:"pending_open_channels,omitempty"` /// Channels pending closing - PendingClosingChannels []*PendingChannelsResponse_ClosedChannel `protobuf:"bytes,3,rep,name=pending_closing_channels,proto3" json:"pending_closing_channels,omitempty"` + PendingClosingChannels []*PendingChannelsResponse_ClosedChannel `protobuf:"bytes,3,rep,name=pending_closing_channels,json=pendingClosingChannels,proto3" json:"pending_closing_channels,omitempty"` /// Channels pending force closing - PendingForceClosingChannels []*PendingChannelsResponse_ForceClosedChannel `protobuf:"bytes,4,rep,name=pending_force_closing_channels,proto3" json:"pending_force_closing_channels,omitempty"` + PendingForceClosingChannels []*PendingChannelsResponse_ForceClosedChannel `protobuf:"bytes,4,rep,name=pending_force_closing_channels,json=pendingForceClosingChannels,proto3" json:"pending_force_closing_channels,omitempty"` /// Channels waiting for closing tx to confirm - WaitingCloseChannels []*PendingChannelsResponse_WaitingCloseChannel `protobuf:"bytes,5,rep,name=waiting_close_channels,proto3" json:"waiting_close_channels,omitempty"` + WaitingCloseChannels []*PendingChannelsResponse_WaitingCloseChannel `protobuf:"bytes,5,rep,name=waiting_close_channels,json=waitingCloseChannels,proto3" json:"waiting_close_channels,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5217,17 +5217,17 @@ func (m *PendingChannelsResponse) GetWaitingCloseChannels() []*PendingChannelsRe } type PendingChannelsResponse_PendingChannel struct { - RemoteNodePub string `protobuf:"bytes,1,opt,name=remote_node_pub,proto3" json:"remote_node_pub,omitempty"` - ChannelPoint string `protobuf:"bytes,2,opt,name=channel_point,proto3" json:"channel_point,omitempty"` + RemoteNodePub string `protobuf:"bytes,1,opt,name=remote_node_pub,json=remoteNodePub,proto3" json:"remote_node_pub,omitempty"` + ChannelPoint string `protobuf:"bytes,2,opt,name=channel_point,json=channelPoint,proto3" json:"channel_point,omitempty"` Capacity int64 `protobuf:"varint,3,opt,name=capacity,proto3" json:"capacity,omitempty"` - LocalBalance int64 `protobuf:"varint,4,opt,name=local_balance,proto3" json:"local_balance,omitempty"` - RemoteBalance int64 `protobuf:"varint,5,opt,name=remote_balance,proto3" json:"remote_balance,omitempty"` + LocalBalance int64 `protobuf:"varint,4,opt,name=local_balance,json=localBalance,proto3" json:"local_balance,omitempty"` + RemoteBalance int64 `protobuf:"varint,5,opt,name=remote_balance,json=remoteBalance,proto3" json:"remote_balance,omitempty"` /// The minimum satoshis this node is required to reserve in its balance. - LocalChanReserveSat int64 `protobuf:"varint,6,opt,name=local_chan_reserve_sat,proto3" json:"local_chan_reserve_sat,omitempty"` + LocalChanReserveSat int64 `protobuf:"varint,6,opt,name=local_chan_reserve_sat,json=localChanReserveSat,proto3" json:"local_chan_reserve_sat,omitempty"` //* //The minimum satoshis the other node is required to reserve in its //balance. - RemoteChanReserveSat int64 `protobuf:"varint,7,opt,name=remote_chan_reserve_sat,proto3" json:"remote_chan_reserve_sat,omitempty"` + RemoteChanReserveSat int64 `protobuf:"varint,7,opt,name=remote_chan_reserve_sat,json=remoteChanReserveSat,proto3" json:"remote_chan_reserve_sat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5313,21 +5313,21 @@ type PendingChannelsResponse_PendingOpenChannel struct { /// The pending channel Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` /// The height at which this channel will be confirmed - ConfirmationHeight uint32 `protobuf:"varint,2,opt,name=confirmation_height,proto3" json:"confirmation_height,omitempty"` + ConfirmationHeight uint32 `protobuf:"varint,2,opt,name=confirmation_height,json=confirmationHeight,proto3" json:"confirmation_height,omitempty"` //* //The amount calculated to be paid in fees for the current set of //commitment transactions. The fee amount is persisted with the channel //in order to allow the fee amount to be removed and recalculated with //each channel state update, including updates that happen after a system //restart. - CommitFee int64 `protobuf:"varint,4,opt,name=commit_fee,proto3" json:"commit_fee,omitempty"` + CommitFee int64 `protobuf:"varint,4,opt,name=commit_fee,json=commitFee,proto3" json:"commit_fee,omitempty"` /// The weight of the commitment transaction - CommitWeight int64 `protobuf:"varint,5,opt,name=commit_weight,proto3" json:"commit_weight,omitempty"` + CommitWeight int64 `protobuf:"varint,5,opt,name=commit_weight,json=commitWeight,proto3" json:"commit_weight,omitempty"` //* //The required number of satoshis per kilo-weight that the requester will //pay at all times, for both the funding transaction and commitment //transaction. This value can later be updated once the channel is open. - FeePerKw int64 `protobuf:"varint,6,opt,name=fee_per_kw,proto3" json:"fee_per_kw,omitempty"` + FeePerKw int64 `protobuf:"varint,6,opt,name=fee_per_kw,json=feePerKw,proto3" json:"fee_per_kw,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5401,7 +5401,7 @@ type PendingChannelsResponse_WaitingCloseChannel struct { /// The pending channel waiting for closing tx to confirm Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` /// The balance in satoshis encumbered in this channel - LimboBalance int64 `protobuf:"varint,2,opt,name=limbo_balance,proto3" json:"limbo_balance,omitempty"` + LimboBalance int64 `protobuf:"varint,2,opt,name=limbo_balance,json=limboBalance,proto3" json:"limbo_balance,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5454,7 +5454,7 @@ type PendingChannelsResponse_ClosedChannel struct { /// The pending channel to be closed Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` /// The transaction id of the closing transaction - ClosingTxid string `protobuf:"bytes,2,opt,name=closing_txid,proto3" json:"closing_txid,omitempty"` + ClosingTxid string `protobuf:"bytes,2,opt,name=closing_txid,json=closingTxid,proto3" json:"closing_txid,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5503,19 +5503,19 @@ type PendingChannelsResponse_ForceClosedChannel struct { /// The pending channel to be force closed Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` /// The transaction id of the closing transaction - ClosingTxid string `protobuf:"bytes,2,opt,name=closing_txid,proto3" json:"closing_txid,omitempty"` + ClosingTxid string `protobuf:"bytes,2,opt,name=closing_txid,json=closingTxid,proto3" json:"closing_txid,omitempty"` /// The balance in satoshis encumbered in this pending channel - LimboBalance int64 `protobuf:"varint,3,opt,name=limbo_balance,proto3" json:"limbo_balance,omitempty"` + LimboBalance int64 `protobuf:"varint,3,opt,name=limbo_balance,json=limboBalance,proto3" json:"limbo_balance,omitempty"` /// The height at which funds can be swept into the wallet - MaturityHeight uint32 `protobuf:"varint,4,opt,name=maturity_height,proto3" json:"maturity_height,omitempty"` + MaturityHeight uint32 `protobuf:"varint,4,opt,name=maturity_height,json=maturityHeight,proto3" json:"maturity_height,omitempty"` // //Remaining # of blocks until the commitment output can be swept. //Negative values indicate how many blocks have passed since becoming //mature. - BlocksTilMaturity int32 `protobuf:"varint,5,opt,name=blocks_til_maturity,proto3" json:"blocks_til_maturity,omitempty"` + BlocksTilMaturity int32 `protobuf:"varint,5,opt,name=blocks_til_maturity,json=blocksTilMaturity,proto3" json:"blocks_til_maturity,omitempty"` /// The total value of funds successfully recovered from this channel - RecoveredBalance int64 `protobuf:"varint,6,opt,name=recovered_balance,proto3" json:"recovered_balance,omitempty"` - PendingHtlcs []*PendingHTLC `protobuf:"bytes,8,rep,name=pending_htlcs,proto3" json:"pending_htlcs,omitempty"` + RecoveredBalance int64 `protobuf:"varint,6,opt,name=recovered_balance,json=recoveredBalance,proto3" json:"recovered_balance,omitempty"` + PendingHtlcs []*PendingHTLC `protobuf:"bytes,8,rep,name=pending_htlcs,json=pendingHtlcs,proto3" json:"pending_htlcs,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5674,23 +5674,23 @@ type isChannelEventUpdate_Channel interface { } type ChannelEventUpdate_OpenChannel struct { - OpenChannel *Channel `protobuf:"bytes,1,opt,name=open_channel,proto3,oneof"` + OpenChannel *Channel `protobuf:"bytes,1,opt,name=open_channel,json=openChannel,proto3,oneof"` } type ChannelEventUpdate_ClosedChannel struct { - ClosedChannel *ChannelCloseSummary `protobuf:"bytes,2,opt,name=closed_channel,proto3,oneof"` + ClosedChannel *ChannelCloseSummary `protobuf:"bytes,2,opt,name=closed_channel,json=closedChannel,proto3,oneof"` } type ChannelEventUpdate_ActiveChannel struct { - ActiveChannel *ChannelPoint `protobuf:"bytes,3,opt,name=active_channel,proto3,oneof"` + ActiveChannel *ChannelPoint `protobuf:"bytes,3,opt,name=active_channel,json=activeChannel,proto3,oneof"` } type ChannelEventUpdate_InactiveChannel struct { - InactiveChannel *ChannelPoint `protobuf:"bytes,4,opt,name=inactive_channel,proto3,oneof"` + InactiveChannel *ChannelPoint `protobuf:"bytes,4,opt,name=inactive_channel,json=inactiveChannel,proto3,oneof"` } type ChannelEventUpdate_PendingOpenChannel struct { - PendingOpenChannel *PendingUpdate `protobuf:"bytes,6,opt,name=pending_open_channel,proto3,oneof"` + PendingOpenChannel *PendingUpdate `protobuf:"bytes,6,opt,name=pending_open_channel,json=pendingOpenChannel,proto3,oneof"` } func (*ChannelEventUpdate_OpenChannel) isChannelEventUpdate_Channel() {} @@ -5796,11 +5796,11 @@ var xxx_messageInfo_WalletBalanceRequest proto.InternalMessageInfo type WalletBalanceResponse struct { /// The balance of the wallet - TotalBalance int64 `protobuf:"varint,1,opt,name=total_balance,proto3" json:"total_balance,omitempty"` + TotalBalance int64 `protobuf:"varint,1,opt,name=total_balance,json=totalBalance,proto3" json:"total_balance,omitempty"` /// The confirmed balance of a wallet(with >= 1 confirmations) - ConfirmedBalance int64 `protobuf:"varint,2,opt,name=confirmed_balance,proto3" json:"confirmed_balance,omitempty"` + ConfirmedBalance int64 `protobuf:"varint,2,opt,name=confirmed_balance,json=confirmedBalance,proto3" json:"confirmed_balance,omitempty"` /// The unconfirmed balance of a wallet(with 0 confirmations) - UnconfirmedBalance int64 `protobuf:"varint,3,opt,name=unconfirmed_balance,proto3" json:"unconfirmed_balance,omitempty"` + UnconfirmedBalance int64 `protobuf:"varint,3,opt,name=unconfirmed_balance,json=unconfirmedBalance,proto3" json:"unconfirmed_balance,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5887,7 +5887,7 @@ type ChannelBalanceResponse struct { /// Sum of channels balances denominated in satoshis Balance int64 `protobuf:"varint,1,opt,name=balance,proto3" json:"balance,omitempty"` /// Sum of channels pending balances denominated in satoshis - PendingOpenBalance int64 `protobuf:"varint,2,opt,name=pending_open_balance,proto3" json:"pending_open_balance,omitempty"` + PendingOpenBalance int64 `protobuf:"varint,2,opt,name=pending_open_balance,json=pendingOpenBalance,proto3" json:"pending_open_balance,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6263,7 +6263,7 @@ type QueryRoutesResponse struct { //* //The success probability of the returned route based on the current mission //control state. [EXPERIMENTAL] - SuccessProb float64 `protobuf:"fixed64,2,opt,name=success_prob,proto3" json:"success_prob,omitempty"` + SuccessProb float64 `protobuf:"fixed64,2,opt,name=success_prob,json=successProb,proto3" json:"success_prob,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6313,33 +6313,33 @@ type Hop struct { //The unique channel ID for the channel. The first 3 bytes are the block //height, the next 3 the index within the block, and the last 2 bytes are the //output index for the channel. - ChanId uint64 `protobuf:"varint,1,opt,name=chan_id,proto3" json:"chan_id,omitempty"` - ChanCapacity int64 `protobuf:"varint,2,opt,name=chan_capacity,proto3" json:"chan_capacity,omitempty"` - AmtToForward int64 `protobuf:"varint,3,opt,name=amt_to_forward,proto3" json:"amt_to_forward,omitempty"` // Deprecated: Do not use. - Fee int64 `protobuf:"varint,4,opt,name=fee,proto3" json:"fee,omitempty"` // Deprecated: Do not use. + ChanId uint64 `protobuf:"varint,1,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` + ChanCapacity int64 `protobuf:"varint,2,opt,name=chan_capacity,json=chanCapacity,proto3" json:"chan_capacity,omitempty"` + AmtToForward int64 `protobuf:"varint,3,opt,name=amt_to_forward,json=amtToForward,proto3" json:"amt_to_forward,omitempty"` // Deprecated: Do not use. + Fee int64 `protobuf:"varint,4,opt,name=fee,proto3" json:"fee,omitempty"` // Deprecated: Do not use. Expiry uint32 `protobuf:"varint,5,opt,name=expiry,proto3" json:"expiry,omitempty"` - AmtToForwardMsat int64 `protobuf:"varint,6,opt,name=amt_to_forward_msat,proto3" json:"amt_to_forward_msat,omitempty"` - FeeMsat int64 `protobuf:"varint,7,opt,name=fee_msat,proto3" json:"fee_msat,omitempty"` + AmtToForwardMsat int64 `protobuf:"varint,6,opt,name=amt_to_forward_msat,json=amtToForwardMsat,proto3" json:"amt_to_forward_msat,omitempty"` + FeeMsat int64 `protobuf:"varint,7,opt,name=fee_msat,json=feeMsat,proto3" json:"fee_msat,omitempty"` //* //An optional public key of the hop. If the public key is given, the payment //can be executed without relying on a copy of the channel graph. - PubKey string `protobuf:"bytes,8,opt,name=pub_key,proto3" json:"pub_key,omitempty"` + PubKey string `protobuf:"bytes,8,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` //* //If set to true, then this hop will be encoded using the new variable length //TLV format. Note that if any custom tlv_records below are specified, then //this field MUST be set to true for them to be encoded properly. - TlvPayload bool `protobuf:"varint,9,opt,name=tlv_payload,proto3" json:"tlv_payload,omitempty"` + TlvPayload bool `protobuf:"varint,9,opt,name=tlv_payload,json=tlvPayload,proto3" json:"tlv_payload,omitempty"` //* //An optional TLV record tha singals 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. - MppRecord *MPPRecord `protobuf:"bytes,10,opt,name=mpp_record,proto3" json:"mpp_record,omitempty"` + MppRecord *MPPRecord `protobuf:"bytes,10,opt,name=mpp_record,json=mppRecord,proto3" json:"mpp_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. - CustomRecords map[uint64][]byte `protobuf:"bytes,11,rep,name=custom_records,proto3" json:"custom_records,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + CustomRecords map[uint64][]byte `protobuf:"bytes,11,rep,name=custom_records,json=customRecords,proto3" json:"custom_records,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6455,13 +6455,13 @@ type MPPRecord struct { //payer of a multi-path payment. The payment_addr must be the same for all //subpayments, and match the payment_addr provided in the receiver's invoice. //The same payment_addr must be used on all subpayments. - PaymentAddr []byte `protobuf:"bytes,11,opt,name=payment_addr,proto3" json:"payment_addr,omitempty"` + PaymentAddr []byte `protobuf:"bytes,11,opt,name=payment_addr,json=paymentAddr,proto3" json:"payment_addr,omitempty"` //* //The total amount in milli-satoshis being sent as part of a larger multi-path //payment. The caller is responsible for ensuring subpayments to the same node //and payment_hash sum exactly to total_amt_msat. The same //total_amt_msat must be used on all subpayments. - TotalAmtMsat int64 `protobuf:"varint,10,opt,name=total_amt_msat,proto3" json:"total_amt_msat,omitempty"` + TotalAmtMsat int64 `protobuf:"varint,10,opt,name=total_amt_msat,json=totalAmtMsat,proto3" json:"total_amt_msat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6518,28 +6518,28 @@ type Route struct { //value that should be extended to the first hop in the route. All other hops //will decrement the time-lock as advertised, leaving enough time for all //hops to wait for or present the payment preimage to complete the payment. - TotalTimeLock uint32 `protobuf:"varint,1,opt,name=total_time_lock,proto3" json:"total_time_lock,omitempty"` + TotalTimeLock uint32 `protobuf:"varint,1,opt,name=total_time_lock,json=totalTimeLock,proto3" json:"total_time_lock,omitempty"` //* //The sum of the fees paid at each hop within the final route. In the case //of a one-hop payment, this value will be zero as we don't need to pay a fee //to ourselves. - TotalFees int64 `protobuf:"varint,2,opt,name=total_fees,proto3" json:"total_fees,omitempty"` // Deprecated: Do not use. + TotalFees int64 `protobuf:"varint,2,opt,name=total_fees,json=totalFees,proto3" json:"total_fees,omitempty"` // Deprecated: Do not use. //* //The total amount of funds required to complete a payment over this route. //This value includes the cumulative fees at each hop. As a result, the HTLC //extended to the first-hop in the route will need to have at least this many //satoshis, otherwise the route will fail at an intermediate node due to an //insufficient amount of fees. - TotalAmt int64 `protobuf:"varint,3,opt,name=total_amt,proto3" json:"total_amt,omitempty"` // Deprecated: Do not use. + TotalAmt int64 `protobuf:"varint,3,opt,name=total_amt,json=totalAmt,proto3" json:"total_amt,omitempty"` // Deprecated: Do not use. //* //Contains details concerning the specific forwarding details at each hop. Hops []*Hop `protobuf:"bytes,4,rep,name=hops,proto3" json:"hops,omitempty"` //* //The total fees in millisatoshis. - TotalFeesMsat int64 `protobuf:"varint,5,opt,name=total_fees_msat,proto3" json:"total_fees_msat,omitempty"` + TotalFeesMsat int64 `protobuf:"varint,5,opt,name=total_fees_msat,json=totalFeesMsat,proto3" json:"total_fees_msat,omitempty"` //* //The total amount in millisatoshis. - TotalAmtMsat int64 `protobuf:"varint,6,opt,name=total_amt_msat,proto3" json:"total_amt_msat,omitempty"` + TotalAmtMsat int64 `protobuf:"varint,6,opt,name=total_amt_msat,json=totalAmtMsat,proto3" json:"total_amt_msat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6671,9 +6671,9 @@ type NodeInfo struct { //it for each outgoing edge. Node *LightningNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` /// The total number of channels for the node. - NumChannels uint32 `protobuf:"varint,2,opt,name=num_channels,proto3" json:"num_channels,omitempty"` + NumChannels uint32 `protobuf:"varint,2,opt,name=num_channels,json=numChannels,proto3" json:"num_channels,omitempty"` /// The sum of all channels capacity for the node, denominated in satoshis. - TotalCapacity int64 `protobuf:"varint,3,opt,name=total_capacity,proto3" json:"total_capacity,omitempty"` + TotalCapacity int64 `protobuf:"varint,3,opt,name=total_capacity,json=totalCapacity,proto3" json:"total_capacity,omitempty"` /// A list of all public channels for the node. Channels []*ChannelEdge `protobuf:"bytes,4,rep,name=channels,proto3" json:"channels,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -6740,8 +6740,8 @@ func (m *NodeInfo) GetChannels() []*ChannelEdge { //graph is directed, a node will also have an incoming edge attached to it for //each outgoing edge. type LightningNode struct { - LastUpdate uint32 `protobuf:"varint,1,opt,name=last_update,proto3" json:"last_update,omitempty"` - PubKey string `protobuf:"bytes,2,opt,name=pub_key,proto3" json:"pub_key,omitempty"` + LastUpdate uint32 `protobuf:"varint,1,opt,name=last_update,json=lastUpdate,proto3" json:"last_update,omitempty"` + PubKey string `protobuf:"bytes,2,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` Alias string `protobuf:"bytes,3,opt,name=alias,proto3" json:"alias,omitempty"` Addresses []*NodeAddress `protobuf:"bytes,4,rep,name=addresses,proto3" json:"addresses,omitempty"` Color string `protobuf:"bytes,5,opt,name=color,proto3" json:"color,omitempty"` @@ -6866,13 +6866,13 @@ func (m *NodeAddress) GetAddr() string { } type RoutingPolicy struct { - TimeLockDelta uint32 `protobuf:"varint,1,opt,name=time_lock_delta,proto3" json:"time_lock_delta,omitempty"` - MinHtlc int64 `protobuf:"varint,2,opt,name=min_htlc,proto3" json:"min_htlc,omitempty"` - FeeBaseMsat int64 `protobuf:"varint,3,opt,name=fee_base_msat,proto3" json:"fee_base_msat,omitempty"` - FeeRateMilliMsat int64 `protobuf:"varint,4,opt,name=fee_rate_milli_msat,proto3" json:"fee_rate_milli_msat,omitempty"` + TimeLockDelta uint32 `protobuf:"varint,1,opt,name=time_lock_delta,json=timeLockDelta,proto3" json:"time_lock_delta,omitempty"` + MinHtlc int64 `protobuf:"varint,2,opt,name=min_htlc,json=minHtlc,proto3" json:"min_htlc,omitempty"` + FeeBaseMsat int64 `protobuf:"varint,3,opt,name=fee_base_msat,json=feeBaseMsat,proto3" json:"fee_base_msat,omitempty"` + FeeRateMilliMsat int64 `protobuf:"varint,4,opt,name=fee_rate_milli_msat,json=feeRateMilliMsat,proto3" json:"fee_rate_milli_msat,omitempty"` Disabled bool `protobuf:"varint,5,opt,name=disabled,proto3" json:"disabled,omitempty"` - MaxHtlcMsat uint64 `protobuf:"varint,6,opt,name=max_htlc_msat,proto3" json:"max_htlc_msat,omitempty"` - LastUpdate uint32 `protobuf:"varint,7,opt,name=last_update,proto3" json:"last_update,omitempty"` + MaxHtlcMsat uint64 `protobuf:"varint,6,opt,name=max_htlc_msat,json=maxHtlcMsat,proto3" json:"max_htlc_msat,omitempty"` + LastUpdate uint32 `protobuf:"varint,7,opt,name=last_update,json=lastUpdate,proto3" json:"last_update,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6963,14 +6963,14 @@ type ChannelEdge struct { //The unique channel ID for the channel. The first 3 bytes are the block //height, the next 3 the index within the block, and the last 2 bytes are the //output index for the channel. - ChannelId uint64 `protobuf:"varint,1,opt,name=channel_id,proto3" json:"channel_id,omitempty"` - ChanPoint string `protobuf:"bytes,2,opt,name=chan_point,proto3" json:"chan_point,omitempty"` - LastUpdate uint32 `protobuf:"varint,3,opt,name=last_update,proto3" json:"last_update,omitempty"` // Deprecated: Do not use. - Node1Pub string `protobuf:"bytes,4,opt,name=node1_pub,proto3" json:"node1_pub,omitempty"` - Node2Pub string `protobuf:"bytes,5,opt,name=node2_pub,proto3" json:"node2_pub,omitempty"` + ChannelId uint64 `protobuf:"varint,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` + ChanPoint string `protobuf:"bytes,2,opt,name=chan_point,json=chanPoint,proto3" json:"chan_point,omitempty"` + LastUpdate uint32 `protobuf:"varint,3,opt,name=last_update,json=lastUpdate,proto3" json:"last_update,omitempty"` // Deprecated: Do not use. + Node1Pub string `protobuf:"bytes,4,opt,name=node1_pub,json=node1Pub,proto3" json:"node1_pub,omitempty"` + Node2Pub string `protobuf:"bytes,5,opt,name=node2_pub,json=node2Pub,proto3" json:"node2_pub,omitempty"` Capacity int64 `protobuf:"varint,6,opt,name=capacity,proto3" json:"capacity,omitempty"` - Node1Policy *RoutingPolicy `protobuf:"bytes,7,opt,name=node1_policy,proto3" json:"node1_policy,omitempty"` - Node2Policy *RoutingPolicy `protobuf:"bytes,8,opt,name=node2_policy,proto3" json:"node2_policy,omitempty"` + Node1Policy *RoutingPolicy `protobuf:"bytes,7,opt,name=node1_policy,json=node1Policy,proto3" json:"node1_policy,omitempty"` + Node2Policy *RoutingPolicy `protobuf:"bytes,8,opt,name=node2_policy,json=node2Policy,proto3" json:"node2_policy,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -7063,7 +7063,7 @@ type ChannelGraphRequest struct { //Whether unannounced channels are included in the response or not. If set, //unannounced channels are included. Unannounced channels are both private //channels, and public channels that are not yet announced to the network. - IncludeUnannounced bool `protobuf:"varint,1,opt,name=include_unannounced,proto3" json:"include_unannounced,omitempty"` + IncludeUnannounced bool `protobuf:"varint,1,opt,name=include_unannounced,json=includeUnannounced,proto3" json:"include_unannounced,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -7226,18 +7226,18 @@ func (m *NetworkInfoRequest) XXX_DiscardUnknown() { var xxx_messageInfo_NetworkInfoRequest proto.InternalMessageInfo type NetworkInfo struct { - GraphDiameter uint32 `protobuf:"varint,1,opt,name=graph_diameter,proto3" json:"graph_diameter,omitempty"` - AvgOutDegree float64 `protobuf:"fixed64,2,opt,name=avg_out_degree,proto3" json:"avg_out_degree,omitempty"` - MaxOutDegree uint32 `protobuf:"varint,3,opt,name=max_out_degree,proto3" json:"max_out_degree,omitempty"` - NumNodes uint32 `protobuf:"varint,4,opt,name=num_nodes,proto3" json:"num_nodes,omitempty"` - NumChannels uint32 `protobuf:"varint,5,opt,name=num_channels,proto3" json:"num_channels,omitempty"` - TotalNetworkCapacity int64 `protobuf:"varint,6,opt,name=total_network_capacity,proto3" json:"total_network_capacity,omitempty"` - AvgChannelSize float64 `protobuf:"fixed64,7,opt,name=avg_channel_size,proto3" json:"avg_channel_size,omitempty"` - MinChannelSize int64 `protobuf:"varint,8,opt,name=min_channel_size,proto3" json:"min_channel_size,omitempty"` - MaxChannelSize int64 `protobuf:"varint,9,opt,name=max_channel_size,proto3" json:"max_channel_size,omitempty"` - MedianChannelSizeSat int64 `protobuf:"varint,10,opt,name=median_channel_size_sat,proto3" json:"median_channel_size_sat,omitempty"` + GraphDiameter uint32 `protobuf:"varint,1,opt,name=graph_diameter,json=graphDiameter,proto3" json:"graph_diameter,omitempty"` + AvgOutDegree float64 `protobuf:"fixed64,2,opt,name=avg_out_degree,json=avgOutDegree,proto3" json:"avg_out_degree,omitempty"` + MaxOutDegree uint32 `protobuf:"varint,3,opt,name=max_out_degree,json=maxOutDegree,proto3" json:"max_out_degree,omitempty"` + NumNodes uint32 `protobuf:"varint,4,opt,name=num_nodes,json=numNodes,proto3" json:"num_nodes,omitempty"` + NumChannels uint32 `protobuf:"varint,5,opt,name=num_channels,json=numChannels,proto3" json:"num_channels,omitempty"` + TotalNetworkCapacity int64 `protobuf:"varint,6,opt,name=total_network_capacity,json=totalNetworkCapacity,proto3" json:"total_network_capacity,omitempty"` + AvgChannelSize float64 `protobuf:"fixed64,7,opt,name=avg_channel_size,json=avgChannelSize,proto3" json:"avg_channel_size,omitempty"` + MinChannelSize int64 `protobuf:"varint,8,opt,name=min_channel_size,json=minChannelSize,proto3" json:"min_channel_size,omitempty"` + MaxChannelSize int64 `protobuf:"varint,9,opt,name=max_channel_size,json=maxChannelSize,proto3" json:"max_channel_size,omitempty"` + MedianChannelSizeSat int64 `protobuf:"varint,10,opt,name=median_channel_size_sat,json=medianChannelSizeSat,proto3" json:"median_channel_size_sat,omitempty"` // The number of edges marked as zombies. - NumZombieChans uint64 `protobuf:"varint,11,opt,name=num_zombie_chans,proto3" json:"num_zombie_chans,omitempty"` + NumZombieChans uint64 `protobuf:"varint,11,opt,name=num_zombie_chans,json=numZombieChans,proto3" json:"num_zombie_chans,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -7716,17 +7716,17 @@ func (m *ClosedChannelUpdate) GetChanPoint() *ChannelPoint { type HopHint struct { /// The public key of the node at the start of the channel. - NodeId string `protobuf:"bytes,1,opt,name=node_id,proto3" json:"node_id,omitempty"` + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` /// The unique identifier of the channel. - ChanId uint64 `protobuf:"varint,2,opt,name=chan_id,proto3" json:"chan_id,omitempty"` + ChanId uint64 `protobuf:"varint,2,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` /// The base fee of the channel denominated in millisatoshis. - FeeBaseMsat uint32 `protobuf:"varint,3,opt,name=fee_base_msat,proto3" json:"fee_base_msat,omitempty"` + FeeBaseMsat uint32 `protobuf:"varint,3,opt,name=fee_base_msat,json=feeBaseMsat,proto3" json:"fee_base_msat,omitempty"` //* //The fee rate of the channel for sending one satoshi across it denominated in //millionths of a satoshi. - FeeProportionalMillionths uint32 `protobuf:"varint,4,opt,name=fee_proportional_millionths,proto3" json:"fee_proportional_millionths,omitempty"` + FeeProportionalMillionths uint32 `protobuf:"varint,4,opt,name=fee_proportional_millionths,json=feeProportionalMillionths,proto3" json:"fee_proportional_millionths,omitempty"` /// The time-lock delta of the channel. - CltvExpiryDelta uint32 `protobuf:"varint,5,opt,name=cltv_expiry_delta,proto3" json:"cltv_expiry_delta,omitempty"` + CltvExpiryDelta uint32 `protobuf:"varint,5,opt,name=cltv_expiry_delta,json=cltvExpiryDelta,proto3" json:"cltv_expiry_delta,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -7796,7 +7796,7 @@ type RouteHint struct { //* //A list of hop hints that when chained together can assist in reaching a //specific destination. - HopHints []*HopHint `protobuf:"bytes,1,rep,name=hop_hints,proto3" json:"hop_hints,omitempty"` + HopHints []*HopHint `protobuf:"bytes,1,rep,name=hop_hints,json=hopHints,proto3" json:"hop_hints,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -7845,11 +7845,11 @@ type Invoice struct { //The hex-encoded preimage (32 byte) which will allow settling an incoming //HTLC payable to this preimage. When using REST, this field must be encoded //as base64. - RPreimage []byte `protobuf:"bytes,3,opt,name=r_preimage,proto3" json:"r_preimage,omitempty"` + RPreimage []byte `protobuf:"bytes,3,opt,name=r_preimage,json=rPreimage,proto3" json:"r_preimage,omitempty"` //* //The hash of the preimage. When using REST, this field must be encoded as //base64. - RHash []byte `protobuf:"bytes,4,opt,name=r_hash,proto3" json:"r_hash,omitempty"` + RHash []byte `protobuf:"bytes,4,opt,name=r_hash,json=rHash,proto3" json:"r_hash,omitempty"` //* //The value of this invoice in satoshis // @@ -7859,34 +7859,34 @@ type Invoice struct { //The value of this invoice in millisatoshis // //The fields value and value_msat are mutually exclusive. - ValueMsat int64 `protobuf:"varint,23,opt,name=value_msat,proto3" json:"value_msat,omitempty"` + ValueMsat int64 `protobuf:"varint,23,opt,name=value_msat,json=valueMsat,proto3" json:"value_msat,omitempty"` /// Whether this invoice has been fulfilled Settled bool `protobuf:"varint,6,opt,name=settled,proto3" json:"settled,omitempty"` // Deprecated: Do not use. /// When this invoice was created - CreationDate int64 `protobuf:"varint,7,opt,name=creation_date,proto3" json:"creation_date,omitempty"` + CreationDate int64 `protobuf:"varint,7,opt,name=creation_date,json=creationDate,proto3" json:"creation_date,omitempty"` /// When this invoice was settled - SettleDate int64 `protobuf:"varint,8,opt,name=settle_date,proto3" json:"settle_date,omitempty"` + SettleDate int64 `protobuf:"varint,8,opt,name=settle_date,json=settleDate,proto3" json:"settle_date,omitempty"` //* //A bare-bones invoice for a payment within the Lightning Network. With the //details of the invoice, the sender has all the data necessary to send a //payment to the recipient. - PaymentRequest string `protobuf:"bytes,9,opt,name=payment_request,proto3" json:"payment_request,omitempty"` + PaymentRequest string `protobuf:"bytes,9,opt,name=payment_request,json=paymentRequest,proto3" json:"payment_request,omitempty"` //* //Hash (SHA-256) of a description of the payment. Used if the description of //payment (memo) is too long to naturally fit within the description field //of an encoded payment request. When using REST, this field must be encoded //as base64. - DescriptionHash []byte `protobuf:"bytes,10,opt,name=description_hash,proto3" json:"description_hash,omitempty"` + DescriptionHash []byte `protobuf:"bytes,10,opt,name=description_hash,json=descriptionHash,proto3" json:"description_hash,omitempty"` /// Payment request expiry time in seconds. Default is 3600 (1 hour). Expiry int64 `protobuf:"varint,11,opt,name=expiry,proto3" json:"expiry,omitempty"` /// Fallback on-chain address. - FallbackAddr string `protobuf:"bytes,12,opt,name=fallback_addr,proto3" json:"fallback_addr,omitempty"` + FallbackAddr string `protobuf:"bytes,12,opt,name=fallback_addr,json=fallbackAddr,proto3" json:"fallback_addr,omitempty"` /// Delta to use for the time-lock of the CLTV extended to the final hop. - CltvExpiry uint64 `protobuf:"varint,13,opt,name=cltv_expiry,proto3" json:"cltv_expiry,omitempty"` + CltvExpiry uint64 `protobuf:"varint,13,opt,name=cltv_expiry,json=cltvExpiry,proto3" json:"cltv_expiry,omitempty"` //* //Route hints that can each be individually used to assist in reaching the //invoice's destination. - RouteHints []*RouteHint `protobuf:"bytes,14,rep,name=route_hints,proto3" json:"route_hints,omitempty"` + RouteHints []*RouteHint `protobuf:"bytes,14,rep,name=route_hints,json=routeHints,proto3" json:"route_hints,omitempty"` /// Whether this invoice should include routing hints for private channels. Private bool `protobuf:"varint,15,opt,name=private,proto3" json:"private,omitempty"` //* @@ -7894,15 +7894,15 @@ type Invoice struct { //this index making it monotonically increasing. Callers to the //SubscribeInvoices call can use this to instantly get notified of all added //invoices with an add_index greater than this one. - AddIndex uint64 `protobuf:"varint,16,opt,name=add_index,proto3" json:"add_index,omitempty"` + AddIndex uint64 `protobuf:"varint,16,opt,name=add_index,json=addIndex,proto3" json:"add_index,omitempty"` //* //The "settle" index of this invoice. Each newly settled invoice will //increment this index making it monotonically increasing. Callers to the //SubscribeInvoices call can use this to instantly get notified of all //settled invoices with an settle_index greater than this one. - SettleIndex uint64 `protobuf:"varint,17,opt,name=settle_index,proto3" json:"settle_index,omitempty"` + SettleIndex uint64 `protobuf:"varint,17,opt,name=settle_index,json=settleIndex,proto3" json:"settle_index,omitempty"` /// Deprecated, use amt_paid_sat or amt_paid_msat. - AmtPaid int64 `protobuf:"varint,18,opt,name=amt_paid,proto3" json:"amt_paid,omitempty"` // Deprecated: Do not use. + AmtPaid int64 `protobuf:"varint,18,opt,name=amt_paid,json=amtPaid,proto3" json:"amt_paid,omitempty"` // Deprecated: Do not use. //* //The amount that was accepted for this invoice, in satoshis. This will ONLY //be set if this invoice has been settled. We provide this field as if the @@ -7910,7 +7910,7 @@ type Invoice struct { //was ultimately accepted. Additionally, it's possible that the sender paid //MORE that was specified in the original invoice. So we'll record that here //as well. - AmtPaidSat int64 `protobuf:"varint,19,opt,name=amt_paid_sat,proto3" json:"amt_paid_sat,omitempty"` + AmtPaidSat int64 `protobuf:"varint,19,opt,name=amt_paid_sat,json=amtPaidSat,proto3" json:"amt_paid_sat,omitempty"` //* //The amount that was accepted for this invoice, in millisatoshis. This will //ONLY be set if this invoice has been settled. We provide this field as if @@ -7918,7 +7918,7 @@ type Invoice struct { //amount was ultimately accepted. Additionally, it's possible that the sender //paid MORE that was specified in the original invoice. So we'll record that //here as well. - AmtPaidMsat int64 `protobuf:"varint,20,opt,name=amt_paid_msat,proto3" json:"amt_paid_msat,omitempty"` + AmtPaidMsat int64 `protobuf:"varint,20,opt,name=amt_paid_msat,json=amtPaidMsat,proto3" json:"amt_paid_msat,omitempty"` //* //The state the invoice is in. State Invoice_InvoiceState `protobuf:"varint,21,opt,name=state,proto3,enum=lnrpc.Invoice_InvoiceState" json:"state,omitempty"` @@ -7929,7 +7929,7 @@ type Invoice struct { //* //Indicates if this invoice was a spontaneous payment that arrived via keysend //[EXPERIMENTAL]. - IsKeysend bool `protobuf:"varint,25,opt,name=is_keysend,proto3" json:"is_keysend,omitempty"` + IsKeysend bool `protobuf:"varint,25,opt,name=is_keysend,json=isKeysend,proto3" json:"is_keysend,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -8133,25 +8133,25 @@ func (m *Invoice) GetIsKeysend() bool { /// Details of an HTLC that paid to an invoice type InvoiceHTLC struct { /// Short channel id over which the htlc was received. - ChanId uint64 `protobuf:"varint,1,opt,name=chan_id,proto3" json:"chan_id,omitempty"` + ChanId uint64 `protobuf:"varint,1,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` /// Index identifying the htlc on the channel. - HtlcIndex uint64 `protobuf:"varint,2,opt,name=htlc_index,proto3" json:"htlc_index,omitempty"` + HtlcIndex uint64 `protobuf:"varint,2,opt,name=htlc_index,json=htlcIndex,proto3" json:"htlc_index,omitempty"` /// The amount of the htlc in msat. - AmtMsat uint64 `protobuf:"varint,3,opt,name=amt_msat,proto3" json:"amt_msat,omitempty"` + AmtMsat uint64 `protobuf:"varint,3,opt,name=amt_msat,json=amtMsat,proto3" json:"amt_msat,omitempty"` /// Block height at which this htlc was accepted. - AcceptHeight int32 `protobuf:"varint,4,opt,name=accept_height,proto3" json:"accept_height,omitempty"` + AcceptHeight int32 `protobuf:"varint,4,opt,name=accept_height,json=acceptHeight,proto3" json:"accept_height,omitempty"` /// Time at which this htlc was accepted. - AcceptTime int64 `protobuf:"varint,5,opt,name=accept_time,proto3" json:"accept_time,omitempty"` + AcceptTime int64 `protobuf:"varint,5,opt,name=accept_time,json=acceptTime,proto3" json:"accept_time,omitempty"` /// Time at which this htlc was settled or canceled. - ResolveTime int64 `protobuf:"varint,6,opt,name=resolve_time,proto3" json:"resolve_time,omitempty"` + ResolveTime int64 `protobuf:"varint,6,opt,name=resolve_time,json=resolveTime,proto3" json:"resolve_time,omitempty"` /// Block height at which this htlc expires. - ExpiryHeight int32 `protobuf:"varint,7,opt,name=expiry_height,proto3" json:"expiry_height,omitempty"` + ExpiryHeight int32 `protobuf:"varint,7,opt,name=expiry_height,json=expiryHeight,proto3" json:"expiry_height,omitempty"` /// Current state the htlc is in. State InvoiceHTLCState `protobuf:"varint,8,opt,name=state,proto3,enum=lnrpc.InvoiceHTLCState" json:"state,omitempty"` /// Custom tlv records. - CustomRecords map[uint64][]byte `protobuf:"bytes,9,rep,name=custom_records,proto3" json:"custom_records,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + CustomRecords map[uint64][]byte `protobuf:"bytes,9,rep,name=custom_records,json=customRecords,proto3" json:"custom_records,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` /// The total amount of the mpp payment in msat. - MppTotalAmtMsat uint64 `protobuf:"varint,10,opt,name=mpp_total_amt_msat,proto3" json:"mpp_total_amt_msat,omitempty"` + MppTotalAmtMsat uint64 `protobuf:"varint,10,opt,name=mpp_total_amt_msat,json=mppTotalAmtMsat,proto3" json:"mpp_total_amt_msat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -8253,18 +8253,18 @@ func (m *InvoiceHTLC) GetMppTotalAmtMsat() uint64 { } type AddInvoiceResponse struct { - RHash []byte `protobuf:"bytes,1,opt,name=r_hash,proto3" json:"r_hash,omitempty"` + RHash []byte `protobuf:"bytes,1,opt,name=r_hash,json=rHash,proto3" json:"r_hash,omitempty"` //* //A bare-bones invoice for a payment within the Lightning Network. With the //details of the invoice, the sender has all the data necessary to send a //payment to the recipient. - PaymentRequest string `protobuf:"bytes,2,opt,name=payment_request,proto3" json:"payment_request,omitempty"` + PaymentRequest string `protobuf:"bytes,2,opt,name=payment_request,json=paymentRequest,proto3" json:"payment_request,omitempty"` //* //The "add" index of this invoice. Each newly created invoice will increment //this index making it monotonically increasing. Callers to the //SubscribeInvoices call can use this to instantly get notified of all added //invoices with an add_index greater than this one. - AddIndex uint64 `protobuf:"varint,16,opt,name=add_index,proto3" json:"add_index,omitempty"` + AddIndex uint64 `protobuf:"varint,16,opt,name=add_index,json=addIndex,proto3" json:"add_index,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -8322,11 +8322,11 @@ type PaymentHash struct { //payment hash must be exactly 32 bytes, otherwise an error is returned. //Deprecated now that the REST gateway supports base64 encoding of bytes //fields. - RHashStr string `protobuf:"bytes,1,opt,name=r_hash_str,proto3" json:"r_hash_str,omitempty"` // Deprecated: Do not use. + RHashStr string `protobuf:"bytes,1,opt,name=r_hash_str,json=rHashStr,proto3" json:"r_hash_str,omitempty"` // Deprecated: Do not use. //* //The payment hash of the invoice to be looked up. When using REST, this field //must be encoded as base64. - RHash []byte `protobuf:"bytes,2,opt,name=r_hash,proto3" json:"r_hash,omitempty"` + RHash []byte `protobuf:"bytes,2,opt,name=r_hash,json=rHash,proto3" json:"r_hash,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -8376,13 +8376,13 @@ type ListInvoiceRequest struct { //* //If set, only invoices that are not settled and not canceled will be returned //in the response. - PendingOnly bool `protobuf:"varint,1,opt,name=pending_only,proto3" json:"pending_only,omitempty"` + PendingOnly bool `protobuf:"varint,1,opt,name=pending_only,json=pendingOnly,proto3" json:"pending_only,omitempty"` //* //The index of an invoice that will be used as either the start or end of a //query to determine which invoices should be returned in the response. - IndexOffset uint64 `protobuf:"varint,4,opt,name=index_offset,proto3" json:"index_offset,omitempty"` + IndexOffset uint64 `protobuf:"varint,4,opt,name=index_offset,json=indexOffset,proto3" json:"index_offset,omitempty"` /// The max number of invoices to return in the response to this query. - NumMaxInvoices uint64 `protobuf:"varint,5,opt,name=num_max_invoices,proto3" json:"num_max_invoices,omitempty"` + NumMaxInvoices uint64 `protobuf:"varint,5,opt,name=num_max_invoices,json=numMaxInvoices,proto3" json:"num_max_invoices,omitempty"` //* //If set, the invoices returned will result from seeking backwards from the //specified index offset. This can be used to paginate backwards. @@ -8453,11 +8453,11 @@ type ListInvoiceResponse struct { //* //The index of the last item in the set of returned invoices. This can be used //to seek further, pagination style. - LastIndexOffset uint64 `protobuf:"varint,2,opt,name=last_index_offset,proto3" json:"last_index_offset,omitempty"` + LastIndexOffset uint64 `protobuf:"varint,2,opt,name=last_index_offset,json=lastIndexOffset,proto3" json:"last_index_offset,omitempty"` //* //The index of the last item in the set of returned invoices. This can be used //to seek backwards, pagination style. - FirstIndexOffset uint64 `protobuf:"varint,3,opt,name=first_index_offset,proto3" json:"first_index_offset,omitempty"` + FirstIndexOffset uint64 `protobuf:"varint,3,opt,name=first_index_offset,json=firstIndexOffset,proto3" json:"first_index_offset,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -8515,13 +8515,13 @@ type InvoiceSubscription struct { //notifications for all added indexes with an add_index greater than this //value. This allows callers to catch up on any events they missed while they //weren't connected to the streaming RPC. - AddIndex uint64 `protobuf:"varint,1,opt,name=add_index,proto3" json:"add_index,omitempty"` + AddIndex uint64 `protobuf:"varint,1,opt,name=add_index,json=addIndex,proto3" json:"add_index,omitempty"` //* //If specified (non-zero), then we'll first start by sending out //notifications for all settled indexes with an settle_index greater than //this value. This allows callers to catch up on any events they missed while //they weren't connected to the streaming RPC. - SettleIndex uint64 `protobuf:"varint,2,opt,name=settle_index,proto3" json:"settle_index,omitempty"` + SettleIndex uint64 `protobuf:"varint,2,opt,name=settle_index,json=settleIndex,proto3" json:"settle_index,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -8568,31 +8568,31 @@ func (m *InvoiceSubscription) GetSettleIndex() uint64 { type Payment struct { /// The payment hash - PaymentHash string `protobuf:"bytes,1,opt,name=payment_hash,proto3" json:"payment_hash,omitempty"` + PaymentHash string `protobuf:"bytes,1,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"` /// Deprecated, use value_sat or value_msat. Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` // Deprecated: Do not use. /// Deprecated, use creation_time_ns - CreationDate int64 `protobuf:"varint,3,opt,name=creation_date,proto3" json:"creation_date,omitempty"` // Deprecated: Do not use. + CreationDate int64 `protobuf:"varint,3,opt,name=creation_date,json=creationDate,proto3" json:"creation_date,omitempty"` // Deprecated: Do not use. /// The path this payment took. Path []string `protobuf:"bytes,4,rep,name=path,proto3" json:"path,omitempty"` // Deprecated: Do not use. /// Deprecated, use fee_sat or fee_msat. Fee int64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` // Deprecated: Do not use. /// The payment preimage - PaymentPreimage string `protobuf:"bytes,6,opt,name=payment_preimage,proto3" json:"payment_preimage,omitempty"` + PaymentPreimage string `protobuf:"bytes,6,opt,name=payment_preimage,json=paymentPreimage,proto3" json:"payment_preimage,omitempty"` /// The value of the payment in satoshis - ValueSat int64 `protobuf:"varint,7,opt,name=value_sat,proto3" json:"value_sat,omitempty"` + ValueSat int64 `protobuf:"varint,7,opt,name=value_sat,json=valueSat,proto3" json:"value_sat,omitempty"` /// The value of the payment in milli-satoshis - ValueMsat int64 `protobuf:"varint,8,opt,name=value_msat,proto3" json:"value_msat,omitempty"` + ValueMsat int64 `protobuf:"varint,8,opt,name=value_msat,json=valueMsat,proto3" json:"value_msat,omitempty"` /// The optional payment request being fulfilled. - PaymentRequest string `protobuf:"bytes,9,opt,name=payment_request,proto3" json:"payment_request,omitempty"` + PaymentRequest string `protobuf:"bytes,9,opt,name=payment_request,json=paymentRequest,proto3" json:"payment_request,omitempty"` // The status of the payment. Status Payment_PaymentStatus `protobuf:"varint,10,opt,name=status,proto3,enum=lnrpc.Payment_PaymentStatus" json:"status,omitempty"` /// The fee paid for this payment in satoshis - FeeSat int64 `protobuf:"varint,11,opt,name=fee_sat,proto3" json:"fee_sat,omitempty"` + FeeSat int64 `protobuf:"varint,11,opt,name=fee_sat,json=feeSat,proto3" json:"fee_sat,omitempty"` /// The fee paid for this payment in milli-satoshis - FeeMsat int64 `protobuf:"varint,12,opt,name=fee_msat,proto3" json:"fee_msat,omitempty"` + FeeMsat int64 `protobuf:"varint,12,opt,name=fee_msat,json=feeMsat,proto3" json:"fee_msat,omitempty"` /// The time in UNIX nanoseconds at which the payment was created. - CreationTimeNs int64 `protobuf:"varint,13,opt,name=creation_time_ns,proto3" json:"creation_time_ns,omitempty"` + CreationTimeNs int64 `protobuf:"varint,13,opt,name=creation_time_ns,json=creationTimeNs,proto3" json:"creation_time_ns,omitempty"` /// The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. Htlcs []*HTLCAttempt `protobuf:"bytes,14,rep,name=htlcs,proto3" json:"htlcs,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -8733,11 +8733,11 @@ type HTLCAttempt struct { /// The route taken by this HTLC. Route *Route `protobuf:"bytes,2,opt,name=route,proto3" json:"route,omitempty"` /// The time in UNIX nanoseconds at which this HTLC was sent. - AttemptTimeNs int64 `protobuf:"varint,3,opt,name=attempt_time_ns,proto3" json:"attempt_time_ns,omitempty"` + AttemptTimeNs int64 `protobuf:"varint,3,opt,name=attempt_time_ns,json=attemptTimeNs,proto3" json:"attempt_time_ns,omitempty"` //* //The time in UNIX nanoseconds at which this HTLC was settled or failed. //This value will not be set if the HTLC is still IN_FLIGHT. - ResolveTimeNs int64 `protobuf:"varint,4,opt,name=resolve_time_ns,proto3" json:"resolve_time_ns,omitempty"` + ResolveTimeNs int64 `protobuf:"varint,4,opt,name=resolve_time_ns,json=resolveTimeNs,proto3" json:"resolve_time_ns,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9059,7 +9059,7 @@ func (m *DebugLevelRequest) GetLevelSpec() string { } type DebugLevelResponse struct { - SubSystems string `protobuf:"bytes,1,opt,name=sub_systems,proto3" json:"sub_systems,omitempty"` + SubSystems string `protobuf:"bytes,1,opt,name=sub_systems,json=subSystems,proto3" json:"sub_systems,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9139,17 +9139,17 @@ func (m *PayReqString) GetPayReq() string { type PayReq struct { Destination string `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"` - PaymentHash string `protobuf:"bytes,2,opt,name=payment_hash,proto3" json:"payment_hash,omitempty"` - NumSatoshis int64 `protobuf:"varint,3,opt,name=num_satoshis,proto3" json:"num_satoshis,omitempty"` + PaymentHash string `protobuf:"bytes,2,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"` + NumSatoshis int64 `protobuf:"varint,3,opt,name=num_satoshis,json=numSatoshis,proto3" json:"num_satoshis,omitempty"` Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Expiry int64 `protobuf:"varint,5,opt,name=expiry,proto3" json:"expiry,omitempty"` Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` - DescriptionHash string `protobuf:"bytes,7,opt,name=description_hash,proto3" json:"description_hash,omitempty"` - FallbackAddr string `protobuf:"bytes,8,opt,name=fallback_addr,proto3" json:"fallback_addr,omitempty"` - CltvExpiry int64 `protobuf:"varint,9,opt,name=cltv_expiry,proto3" json:"cltv_expiry,omitempty"` - RouteHints []*RouteHint `protobuf:"bytes,10,rep,name=route_hints,proto3" json:"route_hints,omitempty"` - PaymentAddr []byte `protobuf:"bytes,11,opt,name=payment_addr,proto3" json:"payment_addr,omitempty"` - NumMsat int64 `protobuf:"varint,12,opt,name=num_msat,proto3" json:"num_msat,omitempty"` + DescriptionHash string `protobuf:"bytes,7,opt,name=description_hash,json=descriptionHash,proto3" json:"description_hash,omitempty"` + FallbackAddr string `protobuf:"bytes,8,opt,name=fallback_addr,json=fallbackAddr,proto3" json:"fallback_addr,omitempty"` + CltvExpiry int64 `protobuf:"varint,9,opt,name=cltv_expiry,json=cltvExpiry,proto3" json:"cltv_expiry,omitempty"` + RouteHints []*RouteHint `protobuf:"bytes,10,rep,name=route_hints,json=routeHints,proto3" json:"route_hints,omitempty"` + PaymentAddr []byte `protobuf:"bytes,11,opt,name=payment_addr,json=paymentAddr,proto3" json:"payment_addr,omitempty"` + NumMsat int64 `protobuf:"varint,12,opt,name=num_msat,json=numMsat,proto3" json:"num_msat,omitempty"` Features map[uint32]*Feature `protobuf:"bytes,13,rep,name=features,proto3" json:"features,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -9274,8 +9274,8 @@ func (m *PayReq) GetFeatures() map[uint32]*Feature { type Feature struct { Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - IsRequired bool `protobuf:"varint,3,opt,name=is_required,proto3" json:"is_required,omitempty"` - IsKnown bool `protobuf:"varint,4,opt,name=is_known,proto3" json:"is_known,omitempty"` + IsRequired bool `protobuf:"varint,3,opt,name=is_required,json=isRequired,proto3" json:"is_required,omitempty"` + IsKnown bool `protobuf:"varint,4,opt,name=is_known,json=isKnown,proto3" json:"is_known,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9362,13 +9362,13 @@ type ChannelFeeReport struct { /// The short channel id that this fee report belongs to. ChanId uint64 `protobuf:"varint,5,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` /// The channel that this fee report belongs to. - ChanPoint string `protobuf:"bytes,1,opt,name=chan_point,json=channel_point,proto3" json:"chan_point,omitempty"` + ChanPoint string `protobuf:"bytes,1,opt,name=chan_point,json=chanPoint,proto3" json:"chan_point,omitempty"` /// The base fee charged regardless of the number of milli-satoshis sent. - BaseFeeMsat int64 `protobuf:"varint,2,opt,name=base_fee_msat,proto3" json:"base_fee_msat,omitempty"` + BaseFeeMsat int64 `protobuf:"varint,2,opt,name=base_fee_msat,json=baseFeeMsat,proto3" json:"base_fee_msat,omitempty"` /// The amount charged per milli-satoshis transferred expressed in millionths of a satoshi. - FeePerMil int64 `protobuf:"varint,3,opt,name=fee_per_mil,proto3" json:"fee_per_mil,omitempty"` + FeePerMil int64 `protobuf:"varint,3,opt,name=fee_per_mil,json=feePerMil,proto3" json:"fee_per_mil,omitempty"` /// The effective fee rate in milli-satoshis. Computed by dividing the fee_per_mil value by 1 million. - FeeRate float64 `protobuf:"fixed64,4,opt,name=fee_rate,proto3" json:"fee_rate,omitempty"` + FeeRate float64 `protobuf:"fixed64,4,opt,name=fee_rate,json=feeRate,proto3" json:"fee_rate,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9436,13 +9436,13 @@ func (m *ChannelFeeReport) GetFeeRate() float64 { type FeeReportResponse struct { /// An array of channel fee reports which describes the current fee schedule for each channel. - ChannelFees []*ChannelFeeReport `protobuf:"bytes,1,rep,name=channel_fees,proto3" json:"channel_fees,omitempty"` + ChannelFees []*ChannelFeeReport `protobuf:"bytes,1,rep,name=channel_fees,json=channelFees,proto3" json:"channel_fees,omitempty"` /// The total amount of fee revenue (in satoshis) the switch has collected over the past 24 hrs. - DayFeeSum uint64 `protobuf:"varint,2,opt,name=day_fee_sum,proto3" json:"day_fee_sum,omitempty"` + DayFeeSum uint64 `protobuf:"varint,2,opt,name=day_fee_sum,json=dayFeeSum,proto3" json:"day_fee_sum,omitempty"` /// The total amount of fee revenue (in satoshis) the switch has collected over the past 1 week. - WeekFeeSum uint64 `protobuf:"varint,3,opt,name=week_fee_sum,proto3" json:"week_fee_sum,omitempty"` + WeekFeeSum uint64 `protobuf:"varint,3,opt,name=week_fee_sum,json=weekFeeSum,proto3" json:"week_fee_sum,omitempty"` /// The total amount of fee revenue (in satoshis) the switch has collected over the past 1 month. - MonthFeeSum uint64 `protobuf:"varint,4,opt,name=month_fee_sum,proto3" json:"month_fee_sum,omitempty"` + MonthFeeSum uint64 `protobuf:"varint,4,opt,name=month_fee_sum,json=monthFeeSum,proto3" json:"month_fee_sum,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9507,17 +9507,17 @@ type PolicyUpdateRequest struct { // *PolicyUpdateRequest_ChanPoint Scope isPolicyUpdateRequest_Scope `protobuf_oneof:"scope"` /// The base fee charged regardless of the number of milli-satoshis sent. - BaseFeeMsat int64 `protobuf:"varint,3,opt,name=base_fee_msat,proto3" json:"base_fee_msat,omitempty"` + BaseFeeMsat int64 `protobuf:"varint,3,opt,name=base_fee_msat,json=baseFeeMsat,proto3" json:"base_fee_msat,omitempty"` /// The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6. - FeeRate float64 `protobuf:"fixed64,4,opt,name=fee_rate,proto3" json:"fee_rate,omitempty"` + FeeRate float64 `protobuf:"fixed64,4,opt,name=fee_rate,json=feeRate,proto3" json:"fee_rate,omitempty"` /// The required timelock delta for HTLCs forwarded over the channel. - TimeLockDelta uint32 `protobuf:"varint,5,opt,name=time_lock_delta,proto3" json:"time_lock_delta,omitempty"` + TimeLockDelta uint32 `protobuf:"varint,5,opt,name=time_lock_delta,json=timeLockDelta,proto3" json:"time_lock_delta,omitempty"` /// If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged. - MaxHtlcMsat uint64 `protobuf:"varint,6,opt,name=max_htlc_msat,proto3" json:"max_htlc_msat,omitempty"` + MaxHtlcMsat uint64 `protobuf:"varint,6,opt,name=max_htlc_msat,json=maxHtlcMsat,proto3" json:"max_htlc_msat,omitempty"` /// The minimum HTLC size in milli-satoshis. Only applied if min_htlc_msat_specified is true. - MinHtlcMsat uint64 `protobuf:"varint,7,opt,name=min_htlc_msat,proto3" json:"min_htlc_msat,omitempty"` + MinHtlcMsat uint64 `protobuf:"varint,7,opt,name=min_htlc_msat,json=minHtlcMsat,proto3" json:"min_htlc_msat,omitempty"` /// If true, min_htlc_msat is applied. - MinHtlcMsatSpecified bool `protobuf:"varint,8,opt,name=min_htlc_msat_specified,json=set_min_htlc_msat,proto3" json:"min_htlc_msat_specified,omitempty"` + MinHtlcMsatSpecified bool `protobuf:"varint,8,opt,name=min_htlc_msat_specified,json=minHtlcMsatSpecified,proto3" json:"min_htlc_msat_specified,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9557,7 +9557,7 @@ type PolicyUpdateRequest_Global struct { } type PolicyUpdateRequest_ChanPoint struct { - ChanPoint *ChannelPoint `protobuf:"bytes,2,opt,name=chan_point,proto3,oneof"` + ChanPoint *ChannelPoint `protobuf:"bytes,2,opt,name=chan_point,json=chanPoint,proto3,oneof"` } func (*PolicyUpdateRequest_Global) isPolicyUpdateRequest_Scope() {} @@ -9668,13 +9668,13 @@ var xxx_messageInfo_PolicyUpdateResponse proto.InternalMessageInfo type ForwardingHistoryRequest struct { /// Start time is the starting point of the forwarding history request. All records beyond this point will be included, respecting the end time, and the index offset. - StartTime uint64 `protobuf:"varint,1,opt,name=start_time,proto3" json:"start_time,omitempty"` + StartTime uint64 `protobuf:"varint,1,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` /// End time is the end point of the forwarding history request. The response will carry at most 50k records between the start time and the end time. The index offset can be used to implement pagination. - EndTime uint64 `protobuf:"varint,2,opt,name=end_time,proto3" json:"end_time,omitempty"` + EndTime uint64 `protobuf:"varint,2,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` /// Index offset is the offset in the time series to start at. As each response can only contain 50k records, callers can use this to skip around within a packed time series. - IndexOffset uint32 `protobuf:"varint,3,opt,name=index_offset,proto3" json:"index_offset,omitempty"` + IndexOffset uint32 `protobuf:"varint,3,opt,name=index_offset,json=indexOffset,proto3" json:"index_offset,omitempty"` /// The max number of events to return in the response to this query. - NumMaxEvents uint32 `protobuf:"varint,4,opt,name=num_max_events,proto3" json:"num_max_events,omitempty"` + NumMaxEvents uint32 `protobuf:"varint,4,opt,name=num_max_events,json=numMaxEvents,proto3" json:"num_max_events,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9737,21 +9737,21 @@ type ForwardingEvent struct { /// Timestamp is the time (unix epoch offset) that this circuit was completed. Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` /// The incoming channel ID that carried the HTLC that created the circuit. - ChanIdIn uint64 `protobuf:"varint,2,opt,name=chan_id_in,proto3" json:"chan_id_in,omitempty"` + ChanIdIn uint64 `protobuf:"varint,2,opt,name=chan_id_in,json=chanIdIn,proto3" json:"chan_id_in,omitempty"` /// The outgoing channel ID that carried the preimage that completed the circuit. - ChanIdOut uint64 `protobuf:"varint,4,opt,name=chan_id_out,proto3" json:"chan_id_out,omitempty"` + ChanIdOut uint64 `protobuf:"varint,4,opt,name=chan_id_out,json=chanIdOut,proto3" json:"chan_id_out,omitempty"` /// The total amount (in satoshis) of the incoming HTLC that created half the circuit. - AmtIn uint64 `protobuf:"varint,5,opt,name=amt_in,proto3" json:"amt_in,omitempty"` + AmtIn uint64 `protobuf:"varint,5,opt,name=amt_in,json=amtIn,proto3" json:"amt_in,omitempty"` /// The total amount (in satoshis) of the outgoing HTLC that created the second half of the circuit. - AmtOut uint64 `protobuf:"varint,6,opt,name=amt_out,proto3" json:"amt_out,omitempty"` + AmtOut uint64 `protobuf:"varint,6,opt,name=amt_out,json=amtOut,proto3" json:"amt_out,omitempty"` /// The total fee (in satoshis) that this payment circuit carried. Fee uint64 `protobuf:"varint,7,opt,name=fee,proto3" json:"fee,omitempty"` /// The total fee (in milli-satoshis) that this payment circuit carried. - FeeMsat uint64 `protobuf:"varint,8,opt,name=fee_msat,proto3" json:"fee_msat,omitempty"` + FeeMsat uint64 `protobuf:"varint,8,opt,name=fee_msat,json=feeMsat,proto3" json:"fee_msat,omitempty"` /// The total amount (in milli-satoshis) of the incoming HTLC that created half the circuit. - AmtInMsat uint64 `protobuf:"varint,9,opt,name=amt_in_msat,proto3" json:"amt_in_msat,omitempty"` + AmtInMsat uint64 `protobuf:"varint,9,opt,name=amt_in_msat,json=amtInMsat,proto3" json:"amt_in_msat,omitempty"` /// The total amount (in milli-satoshis) of the outgoing HTLC that created the second half of the circuit. - AmtOutMsat uint64 `protobuf:"varint,10,opt,name=amt_out_msat,proto3" json:"amt_out_msat,omitempty"` + AmtOutMsat uint64 `protobuf:"varint,10,opt,name=amt_out_msat,json=amtOutMsat,proto3" json:"amt_out_msat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9847,9 +9847,9 @@ func (m *ForwardingEvent) GetAmtOutMsat() uint64 { type ForwardingHistoryResponse struct { /// A list of forwarding events from the time slice of the time series specified in the request. - ForwardingEvents []*ForwardingEvent `protobuf:"bytes,1,rep,name=forwarding_events,proto3" json:"forwarding_events,omitempty"` + ForwardingEvents []*ForwardingEvent `protobuf:"bytes,1,rep,name=forwarding_events,json=forwardingEvents,proto3" json:"forwarding_events,omitempty"` /// The index of the last time in the set of returned forwarding events. Can be used to seek further, pagination style. - LastOffsetIndex uint32 `protobuf:"varint,2,opt,name=last_offset_index,proto3" json:"last_offset_index,omitempty"` + LastOffsetIndex uint32 `protobuf:"varint,2,opt,name=last_offset_index,json=lastOffsetIndex,proto3" json:"last_offset_index,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9937,13 +9937,13 @@ func (m *ExportChannelBackupRequest) GetChanPoint() *ChannelPoint { type ChannelBackup struct { //* //Identifies the channel that this backup belongs to. - ChanPoint *ChannelPoint `protobuf:"bytes,1,opt,name=chan_point,proto3" json:"chan_point,omitempty"` + ChanPoint *ChannelPoint `protobuf:"bytes,1,opt,name=chan_point,json=chanPoint,proto3" json:"chan_point,omitempty"` //* //Is an encrypted single-chan backup. this can be passed to //RestoreChannelBackups, or the WalletUnlocker Init and Unlock methods in //order to trigger the recovery protocol. When using REST, this field must be //encoded as base64. - ChanBackup []byte `protobuf:"bytes,2,opt,name=chan_backup,proto3" json:"chan_backup,omitempty"` + ChanBackup []byte `protobuf:"bytes,2,opt,name=chan_backup,json=chanBackup,proto3" json:"chan_backup,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9991,13 +9991,13 @@ func (m *ChannelBackup) GetChanBackup() []byte { type MultiChanBackup struct { //* //Is the set of all channels that are included in this multi-channel backup. - ChanPoints []*ChannelPoint `protobuf:"bytes,1,rep,name=chan_points,proto3" json:"chan_points,omitempty"` + ChanPoints []*ChannelPoint `protobuf:"bytes,1,rep,name=chan_points,json=chanPoints,proto3" json:"chan_points,omitempty"` //* //A single encrypted blob containing all the static channel backups of the //channel listed above. This can be stored as a single file or blob, and //safely be replaced with any prior/future versions. When using REST, this //field must be encoded as base64. - MultiChanBackup []byte `protobuf:"bytes,2,opt,name=multi_chan_backup,proto3" json:"multi_chan_backup,omitempty"` + MultiChanBackup []byte `protobuf:"bytes,2,opt,name=multi_chan_backup,json=multiChanBackup,proto3" json:"multi_chan_backup,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -10077,11 +10077,11 @@ type ChanBackupSnapshot struct { //* //The set of new channels that have been added since the last channel backup //snapshot was requested. - SingleChanBackups *ChannelBackups `protobuf:"bytes,1,opt,name=single_chan_backups,proto3" json:"single_chan_backups,omitempty"` + SingleChanBackups *ChannelBackups `protobuf:"bytes,1,opt,name=single_chan_backups,json=singleChanBackups,proto3" json:"single_chan_backups,omitempty"` //* //A multi-channel backup that covers all open channels currently known to //lnd. - MultiChanBackup *MultiChanBackup `protobuf:"bytes,2,opt,name=multi_chan_backup,proto3" json:"multi_chan_backup,omitempty"` + MultiChanBackup *MultiChanBackup `protobuf:"bytes,2,opt,name=multi_chan_backup,json=multiChanBackup,proto3" json:"multi_chan_backup,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -10129,7 +10129,7 @@ func (m *ChanBackupSnapshot) GetMultiChanBackup() *MultiChanBackup { type ChannelBackups struct { //* //A set of single-chan static channel backups. - ChanBackups []*ChannelBackup `protobuf:"bytes,1,rep,name=chan_backups,proto3" json:"chan_backups,omitempty"` + ChanBackups []*ChannelBackup `protobuf:"bytes,1,rep,name=chan_backups,json=chanBackups,proto3" json:"chan_backups,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -10207,11 +10207,11 @@ type isRestoreChanBackupRequest_Backup interface { } type RestoreChanBackupRequest_ChanBackups struct { - ChanBackups *ChannelBackups `protobuf:"bytes,1,opt,name=chan_backups,proto3,oneof"` + ChanBackups *ChannelBackups `protobuf:"bytes,1,opt,name=chan_backups,json=chanBackups,proto3,oneof"` } type RestoreChanBackupRequest_MultiChanBackup struct { - MultiChanBackup []byte `protobuf:"bytes,2,opt,name=multi_chan_backup,proto3,oneof"` + MultiChanBackup []byte `protobuf:"bytes,2,opt,name=multi_chan_backup,json=multiChanBackup,proto3,oneof"` } func (*RestoreChanBackupRequest_ChanBackups) isRestoreChanBackupRequest_Backup() {} @@ -10648,629 +10648,660 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 9943 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x6c, 0x1c, 0xd9, - 0x95, 0x98, 0xaa, 0x1f, 0x64, 0xf7, 0xe9, 0x07, 0x9b, 0x97, 0x14, 0xd9, 0x6a, 0x3d, 0x46, 0x53, - 0xd6, 0xce, 0xc8, 0xf2, 0x98, 0xd2, 0xd0, 0xf6, 0xac, 0x3c, 0xca, 0x7a, 0xcd, 0x97, 0x44, 0xce, - 0x50, 0x24, 0x5d, 0xa4, 0xac, 0xb5, 0x9d, 0x45, 0xb9, 0xd8, 0x7d, 0x49, 0x96, 0xd5, 0x5d, 0xd5, - 0x53, 0x55, 0x4d, 0x8a, 0x76, 0x26, 0x1f, 0x41, 0x12, 0x04, 0xf9, 0x09, 0x0c, 0x23, 0x40, 0x9e, - 0x58, 0xc0, 0x9b, 0x20, 0x08, 0x02, 0x24, 0x01, 0x02, 0x2c, 0x36, 0x80, 0xf3, 0x95, 0x8f, 0xcd, - 0x4f, 0x90, 0x8f, 0x04, 0x08, 0x90, 0x00, 0x01, 0x16, 0x9b, 0x8f, 0x2c, 0x02, 0xe4, 0x2b, 0xc9, - 0x77, 0x70, 0xcf, 0x7d, 0xd4, 0xbd, 0x55, 0xd5, 0x94, 0xc6, 0x76, 0xfc, 0x23, 0xf1, 0x9e, 0x7b, - 0xea, 0x3e, 0xcf, 0x39, 0xf7, 0x3c, 0xee, 0xb9, 0x0d, 0xf5, 0x68, 0xdc, 0x5f, 0x19, 0x47, 0x61, - 0x12, 0x92, 0xea, 0x30, 0x88, 0xc6, 0xfd, 0xde, 0xad, 0xd3, 0x30, 0x3c, 0x1d, 0xd2, 0x87, 0xde, - 0xd8, 0x7f, 0xe8, 0x05, 0x41, 0x98, 0x78, 0x89, 0x1f, 0x06, 0x31, 0x47, 0xb2, 0x7f, 0x08, 0xed, - 0x67, 0x34, 0x38, 0xa4, 0x74, 0xe0, 0xd0, 0xcf, 0x26, 0x34, 0x4e, 0xc8, 0x57, 0x60, 0xde, 0xa3, - 0x3f, 0xa6, 0x74, 0xe0, 0x8e, 0xbd, 0x38, 0x1e, 0x9f, 0x45, 0x5e, 0x4c, 0xbb, 0xd6, 0x5d, 0xeb, - 0x7e, 0xd3, 0xe9, 0xf0, 0x8a, 0x03, 0x05, 0x27, 0xef, 0x42, 0x33, 0x66, 0xa8, 0x34, 0x48, 0xa2, - 0x70, 0x7c, 0xd9, 0x2d, 0x21, 0x5e, 0x83, 0xc1, 0xb6, 0x38, 0xc8, 0x1e, 0xc2, 0x9c, 0xea, 0x21, - 0x1e, 0x87, 0x41, 0x4c, 0xc9, 0x23, 0x58, 0xec, 0xfb, 0xe3, 0x33, 0x1a, 0xb9, 0xf8, 0xf1, 0x28, - 0xa0, 0xa3, 0x30, 0xf0, 0xfb, 0x5d, 0xeb, 0x6e, 0xf9, 0x7e, 0xdd, 0x21, 0xbc, 0x8e, 0x7d, 0xf1, - 0x5c, 0xd4, 0x90, 0xf7, 0x61, 0x8e, 0x06, 0x1c, 0x4e, 0x07, 0xf8, 0x95, 0xe8, 0xaa, 0x9d, 0x82, - 0xd9, 0x07, 0xf6, 0xdf, 0x28, 0xc1, 0xfc, 0x4e, 0xe0, 0x27, 0x2f, 0xbd, 0xe1, 0x90, 0x26, 0x72, - 0x4e, 0xef, 0xc3, 0xdc, 0x05, 0x02, 0x70, 0x4e, 0x17, 0x61, 0x34, 0x10, 0x33, 0x6a, 0x73, 0xf0, - 0x81, 0x80, 0x4e, 0x1d, 0x59, 0x69, 0xea, 0xc8, 0x0a, 0x97, 0xab, 0x3c, 0x65, 0xb9, 0xde, 0x87, - 0xb9, 0x88, 0xf6, 0xc3, 0x73, 0x1a, 0x5d, 0xba, 0x17, 0x7e, 0x30, 0x08, 0x2f, 0xba, 0x95, 0xbb, - 0xd6, 0xfd, 0xaa, 0xd3, 0x96, 0xe0, 0x97, 0x08, 0x25, 0xeb, 0x30, 0xd7, 0x3f, 0xf3, 0x82, 0x80, - 0x0e, 0xdd, 0x63, 0xaf, 0xff, 0x6a, 0x32, 0x8e, 0xbb, 0xd5, 0xbb, 0xd6, 0xfd, 0xc6, 0xea, 0x8d, - 0x15, 0xdc, 0xd5, 0x95, 0x8d, 0x33, 0x2f, 0x58, 0xc7, 0x9a, 0xc3, 0xc0, 0x1b, 0xc7, 0x67, 0x61, - 0xe2, 0xb4, 0xc5, 0x17, 0x1c, 0x1c, 0xdb, 0x8b, 0x40, 0xf4, 0x95, 0xe0, 0x6b, 0x6f, 0xff, 0x33, - 0x0b, 0x16, 0x5e, 0x04, 0xc3, 0xb0, 0xff, 0xea, 0x97, 0x5c, 0xa2, 0x82, 0x39, 0x94, 0xde, 0x76, - 0x0e, 0xe5, 0x2f, 0x3a, 0x87, 0x25, 0x58, 0x34, 0x07, 0x2b, 0x66, 0x41, 0xe1, 0x3a, 0xfb, 0xfa, - 0x94, 0xca, 0x61, 0xc9, 0x69, 0x7c, 0x19, 0x3a, 0xfd, 0x49, 0x14, 0xd1, 0x20, 0x37, 0x8f, 0x39, - 0x01, 0x57, 0x13, 0x79, 0x17, 0x9a, 0x01, 0xbd, 0x48, 0xd1, 0x04, 0xed, 0x06, 0xf4, 0x42, 0xa2, - 0xd8, 0x5d, 0x58, 0xca, 0x76, 0x23, 0x06, 0xf0, 0xa7, 0x16, 0x54, 0x5e, 0x24, 0xaf, 0x43, 0xb2, - 0x02, 0x95, 0xe4, 0x72, 0xcc, 0x39, 0xa4, 0xbd, 0x4a, 0xc4, 0xd4, 0xd6, 0x06, 0x83, 0x88, 0xc6, - 0xf1, 0xd1, 0xe5, 0x98, 0x3a, 0x4d, 0x8f, 0x17, 0x5c, 0x86, 0x47, 0xba, 0x30, 0x2b, 0xca, 0xd8, - 0x61, 0xdd, 0x91, 0x45, 0x72, 0x07, 0xc0, 0x1b, 0x85, 0x93, 0x20, 0x71, 0x63, 0x2f, 0xc1, 0xa5, - 0x2a, 0x3b, 0x1a, 0x84, 0xdc, 0x82, 0xfa, 0xf8, 0x95, 0x1b, 0xf7, 0x23, 0x7f, 0x9c, 0x20, 0xd9, - 0xd4, 0x9d, 0x14, 0x40, 0xbe, 0x02, 0xb5, 0x70, 0x92, 0x8c, 0x43, 0x3f, 0x48, 0x04, 0xa9, 0xcc, - 0x89, 0xb1, 0xec, 0x4f, 0x92, 0x03, 0x06, 0x76, 0x14, 0x02, 0xb9, 0x07, 0xad, 0x7e, 0x18, 0x9c, - 0xf8, 0xd1, 0x88, 0x0b, 0x83, 0xee, 0x0c, 0xf6, 0x66, 0x02, 0xed, 0x7f, 0x5d, 0x82, 0xc6, 0x51, - 0xe4, 0x05, 0xb1, 0xd7, 0x67, 0x00, 0x36, 0xf4, 0xe4, 0xb5, 0x7b, 0xe6, 0xc5, 0x67, 0x38, 0xdb, - 0xba, 0x23, 0x8b, 0x64, 0x09, 0x66, 0xf8, 0x40, 0x71, 0x4e, 0x65, 0x47, 0x94, 0xc8, 0x07, 0x30, - 0x1f, 0x4c, 0x46, 0xae, 0xd9, 0x57, 0x19, 0xa9, 0x25, 0x5f, 0xc1, 0x16, 0xe0, 0x98, 0xed, 0x35, - 0xef, 0x82, 0xcf, 0x50, 0x83, 0x10, 0x1b, 0x9a, 0xa2, 0x44, 0xfd, 0xd3, 0x33, 0x3e, 0xcd, 0xaa, - 0x63, 0xc0, 0x58, 0x1b, 0x89, 0x3f, 0xa2, 0x6e, 0x9c, 0x78, 0xa3, 0xb1, 0x98, 0x96, 0x06, 0xc1, - 0xfa, 0x30, 0xf1, 0x86, 0xee, 0x09, 0xa5, 0x71, 0x77, 0x56, 0xd4, 0x2b, 0x08, 0x79, 0x0f, 0xda, - 0x03, 0x1a, 0x27, 0xae, 0xd8, 0x14, 0x1a, 0x77, 0x6b, 0xc8, 0xfa, 0x19, 0x28, 0x6b, 0x27, 0xf2, - 0x2e, 0x5c, 0xb6, 0x00, 0xf4, 0x75, 0xb7, 0xce, 0xc7, 0x9a, 0x42, 0x18, 0xe5, 0x3c, 0xa3, 0x89, - 0xb6, 0x7a, 0xb1, 0xa0, 0x50, 0x7b, 0x17, 0x88, 0x06, 0xde, 0xa4, 0x89, 0xe7, 0x0f, 0x63, 0xf2, - 0x11, 0x34, 0x13, 0x0d, 0x19, 0x45, 0x61, 0x43, 0x91, 0x93, 0xf6, 0x81, 0x63, 0xe0, 0xd9, 0x67, - 0x50, 0x7b, 0x4a, 0xe9, 0xae, 0x3f, 0xf2, 0x13, 0xb2, 0x04, 0xd5, 0x13, 0xff, 0x35, 0xe5, 0x04, - 0x5f, 0xde, 0xbe, 0xe6, 0xf0, 0x22, 0x79, 0x07, 0x00, 0xff, 0x70, 0x47, 0x8a, 0xb0, 0xb6, 0xaf, - 0x39, 0x75, 0x84, 0x3d, 0x67, 0x94, 0xd5, 0x83, 0xd9, 0x31, 0x8d, 0xfa, 0x54, 0xee, 0xdf, 0xf6, - 0x35, 0x47, 0x02, 0xd6, 0x67, 0xa1, 0x3a, 0x64, 0xad, 0xdb, 0x7f, 0x52, 0x85, 0xc6, 0x21, 0x0d, - 0x14, 0xa7, 0x11, 0xa8, 0xb0, 0x35, 0x11, 0xdc, 0x85, 0x7f, 0x93, 0x2f, 0x41, 0x03, 0xd7, 0x29, - 0x4e, 0x22, 0x3f, 0x38, 0xe5, 0x04, 0xbe, 0x5e, 0xea, 0x5a, 0x0e, 0x30, 0xf0, 0x21, 0x42, 0x49, - 0x07, 0xca, 0xde, 0x48, 0x12, 0x38, 0xfb, 0x93, 0xdc, 0x80, 0x9a, 0x37, 0x4a, 0xf8, 0xf0, 0x9a, - 0x08, 0x9e, 0xf5, 0x46, 0x09, 0x0e, 0xed, 0x5d, 0x68, 0x8e, 0xbd, 0xcb, 0x11, 0xe3, 0x67, 0x45, - 0x15, 0x4d, 0xa7, 0x21, 0x60, 0xdb, 0x8c, 0x2c, 0x56, 0x61, 0x41, 0x47, 0x91, 0x9d, 0x57, 0x55, - 0xe7, 0xf3, 0x1a, 0xb6, 0x18, 0xc3, 0xfb, 0x30, 0x27, 0xbf, 0x89, 0xf8, 0x7c, 0x90, 0x56, 0xea, - 0x4e, 0x5b, 0x80, 0xe5, 0x2c, 0xef, 0x43, 0xe7, 0xc4, 0x0f, 0xbc, 0xa1, 0xdb, 0x1f, 0x26, 0xe7, - 0xee, 0x80, 0x0e, 0x13, 0x0f, 0xa9, 0xa6, 0xea, 0xb4, 0x11, 0xbe, 0x31, 0x4c, 0xce, 0x37, 0x19, - 0x94, 0x7c, 0x00, 0xf5, 0x13, 0x4a, 0x5d, 0x5c, 0xac, 0x6e, 0xcd, 0xe0, 0x40, 0xb9, 0x43, 0x4e, - 0xed, 0x44, 0xee, 0xd5, 0x07, 0xd0, 0x09, 0x27, 0xc9, 0x69, 0xe8, 0x07, 0xa7, 0x2e, 0x93, 0x79, - 0xae, 0x3f, 0x40, 0x2a, 0xaa, 0xac, 0x97, 0x1e, 0x59, 0x4e, 0x5b, 0xd6, 0x31, 0xe9, 0xb3, 0x33, - 0x20, 0xef, 0xc1, 0xdc, 0xd0, 0x8b, 0x13, 0xf7, 0x2c, 0x1c, 0xbb, 0xe3, 0xc9, 0xf1, 0x2b, 0x7a, - 0xd9, 0x6d, 0xe1, 0x42, 0xb4, 0x18, 0x78, 0x3b, 0x1c, 0x1f, 0x20, 0x90, 0xdc, 0x06, 0xc0, 0x71, - 0xf2, 0x41, 0xc0, 0x5d, 0xeb, 0x7e, 0xcb, 0xa9, 0x33, 0x08, 0xef, 0xf4, 0x7b, 0xb0, 0x80, 0xdb, - 0xd3, 0x9f, 0xc4, 0x49, 0x38, 0x72, 0x99, 0xbc, 0x8e, 0x06, 0x71, 0xb7, 0x81, 0xb4, 0xf6, 0x65, - 0x31, 0x58, 0x6d, 0x8f, 0x57, 0x36, 0x69, 0x9c, 0x6c, 0x20, 0xb2, 0xc3, 0x71, 0xd9, 0xa1, 0x7e, - 0xe9, 0xcc, 0x0f, 0xb2, 0x70, 0xf2, 0x01, 0x10, 0x6f, 0x38, 0x0c, 0x2f, 0xdc, 0x98, 0x0e, 0x4f, - 0x5c, 0xb1, 0x88, 0xdd, 0xf6, 0x5d, 0xeb, 0x7e, 0xcd, 0xe9, 0x60, 0xcd, 0x21, 0x1d, 0x9e, 0x1c, - 0x70, 0x38, 0xf9, 0x08, 0x5a, 0x38, 0x90, 0x13, 0xea, 0x25, 0x93, 0x88, 0xc6, 0xdd, 0xb9, 0xbb, - 0xe5, 0xfb, 0xed, 0xd5, 0x79, 0xb5, 0x5e, 0x08, 0x5e, 0xf7, 0x13, 0xa7, 0xc9, 0xf0, 0x44, 0x39, - 0xee, 0x6d, 0xc2, 0x52, 0xf1, 0x90, 0x18, 0x51, 0xb1, 0x55, 0x61, 0xc4, 0x58, 0x71, 0xd8, 0x9f, - 0x64, 0x11, 0xaa, 0xe7, 0xde, 0x70, 0x42, 0x85, 0x5c, 0xe7, 0x85, 0x8f, 0x4b, 0x8f, 0x2d, 0xfb, - 0x8f, 0x2d, 0x68, 0xf2, 0x59, 0x0a, 0x7d, 0xe4, 0x1e, 0xb4, 0x24, 0x35, 0xd0, 0x28, 0x0a, 0x23, - 0x21, 0xde, 0x4c, 0x20, 0x79, 0x00, 0x1d, 0x09, 0x18, 0x47, 0xd4, 0x1f, 0x79, 0xa7, 0xb2, 0xed, - 0x1c, 0x9c, 0xac, 0xa6, 0x2d, 0x46, 0xe1, 0x24, 0xa1, 0xe2, 0xe4, 0x6b, 0x8a, 0x09, 0x3a, 0x0c, - 0xe6, 0x98, 0x28, 0x4c, 0xbc, 0x15, 0x90, 0xba, 0x01, 0xb3, 0xff, 0xb6, 0x05, 0x84, 0x0d, 0xfd, - 0x28, 0xe4, 0x4d, 0x08, 0x2a, 0xcd, 0x72, 0x89, 0xf5, 0xd6, 0x5c, 0x52, 0xba, 0x8a, 0x4b, 0x6c, - 0xa8, 0xf2, 0xd1, 0x57, 0x0a, 0x46, 0xcf, 0xab, 0x3e, 0xa9, 0xd4, 0xca, 0x9d, 0x8a, 0xfd, 0x5f, - 0xca, 0xb0, 0xb8, 0xc1, 0x8f, 0xee, 0xb5, 0x7e, 0x9f, 0x8e, 0x15, 0xff, 0xbc, 0x03, 0x8d, 0x20, - 0x1c, 0x50, 0x49, 0xb5, 0x7c, 0x60, 0xc0, 0x40, 0x1a, 0xc9, 0x9e, 0x79, 0x7e, 0xc0, 0x07, 0xce, - 0xd7, 0xb3, 0x8e, 0x10, 0x1c, 0xf6, 0x7b, 0x30, 0x37, 0xa6, 0xc1, 0x40, 0x67, 0x13, 0xae, 0x5c, - 0xb5, 0x04, 0x58, 0x70, 0xc8, 0x3b, 0xd0, 0x38, 0x99, 0x70, 0x3c, 0x26, 0x5c, 0x2a, 0x48, 0x07, - 0x20, 0x40, 0x6b, 0x5c, 0xc6, 0x8c, 0x27, 0xf1, 0x19, 0xd6, 0x56, 0xb1, 0x76, 0x96, 0x95, 0x59, - 0xd5, 0x6d, 0x80, 0xc1, 0x24, 0x4e, 0x04, 0xd7, 0xcc, 0x60, 0x65, 0x9d, 0x41, 0x38, 0xd7, 0x7c, - 0x15, 0x16, 0x46, 0xde, 0x6b, 0x17, 0xe9, 0xc7, 0xf5, 0x03, 0xf7, 0x64, 0x88, 0xa7, 0xcf, 0x2c, - 0xe2, 0x75, 0x46, 0xde, 0xeb, 0xef, 0xb2, 0x9a, 0x9d, 0xe0, 0x29, 0xc2, 0x99, 0x68, 0x91, 0x6a, - 0x4f, 0x44, 0x63, 0x1a, 0x9d, 0x53, 0x94, 0x06, 0x15, 0xa5, 0xdb, 0x38, 0x1c, 0xca, 0x46, 0x34, - 0x62, 0xf3, 0x4e, 0x86, 0x7d, 0xce, 0xfa, 0xce, 0xec, 0xc8, 0x0f, 0xb6, 0x93, 0x61, 0x9f, 0xdc, - 0x02, 0x60, 0xb2, 0x64, 0x4c, 0x23, 0xf7, 0xd5, 0x05, 0xf2, 0x71, 0x05, 0x65, 0xc7, 0x01, 0x8d, - 0x3e, 0xbd, 0x20, 0x37, 0xa1, 0xde, 0x8f, 0x51, 0x18, 0x79, 0x97, 0xdd, 0x06, 0x32, 0x79, 0xad, - 0x1f, 0x33, 0x31, 0xe4, 0x5d, 0x32, 0x46, 0x64, 0xa3, 0xf5, 0x70, 0x17, 0xe8, 0x00, 0x9b, 0x8f, - 0x51, 0xaa, 0xb6, 0x70, 0xb0, 0x6b, 0xa2, 0x82, 0xf5, 0x13, 0x93, 0x2f, 0x41, 0x4b, 0x0e, 0xf6, - 0x64, 0xe8, 0x9d, 0xc6, 0x28, 0x56, 0x5a, 0x4e, 0x53, 0x00, 0x9f, 0x32, 0x98, 0xfd, 0x92, 0x2b, - 0x5b, 0xda, 0xde, 0x0a, 0xbe, 0x61, 0xc7, 0x3e, 0x42, 0x70, 0x5f, 0x6b, 0x8e, 0x28, 0x15, 0x6d, - 0x5a, 0xa9, 0x60, 0xd3, 0xec, 0x9f, 0x5b, 0xd0, 0x14, 0x2d, 0xa3, 0x86, 0x42, 0x1e, 0x01, 0x91, - 0xbb, 0x98, 0xbc, 0xf6, 0x07, 0xee, 0xf1, 0x65, 0x42, 0x63, 0x4e, 0x34, 0xdb, 0xd7, 0x9c, 0x82, - 0x3a, 0x26, 0x47, 0x0d, 0x68, 0x9c, 0x44, 0x9c, 0xa6, 0xb7, 0xaf, 0x39, 0xb9, 0x1a, 0xc6, 0x62, - 0x4c, 0x07, 0x9a, 0x24, 0xae, 0x1f, 0x0c, 0xe8, 0x6b, 0x24, 0xa5, 0x96, 0x63, 0xc0, 0xd6, 0xdb, - 0xd0, 0xd4, 0xbf, 0xb3, 0x7f, 0x04, 0x35, 0xa9, 0x41, 0xa1, 0xf6, 0x90, 0x19, 0x97, 0xa3, 0x41, - 0x48, 0x0f, 0x6a, 0xe6, 0x28, 0x9c, 0xda, 0x17, 0xe9, 0xdb, 0xfe, 0x16, 0x74, 0x76, 0x19, 0x11, - 0x05, 0x8c, 0x68, 0x85, 0x5a, 0xb8, 0x04, 0x33, 0x1a, 0xf3, 0xd4, 0x1d, 0x51, 0x62, 0xe7, 0xef, - 0x59, 0x18, 0x27, 0xa2, 0x1f, 0xfc, 0xdb, 0xfe, 0x13, 0x0b, 0xc8, 0x56, 0x9c, 0xf8, 0x23, 0x2f, - 0xa1, 0x4f, 0xa9, 0x12, 0x0f, 0xfb, 0xd0, 0x64, 0xad, 0x1d, 0x85, 0x6b, 0x5c, 0x49, 0xe3, 0xca, - 0xc5, 0x57, 0x04, 0x3b, 0xe7, 0x3f, 0x58, 0xd1, 0xb1, 0xb9, 0xc8, 0x37, 0x1a, 0x60, 0xdc, 0x96, - 0x78, 0xd1, 0x29, 0x4d, 0x50, 0x83, 0x13, 0xfa, 0x3f, 0x70, 0xd0, 0x46, 0x18, 0x9c, 0xf4, 0x7e, - 0x17, 0xe6, 0x73, 0x6d, 0xe8, 0x32, 0xba, 0x5e, 0x20, 0xa3, 0xcb, 0xba, 0x8c, 0xee, 0xc3, 0x82, - 0x31, 0x2e, 0x41, 0x71, 0x5d, 0x98, 0x65, 0x8c, 0xc1, 0x14, 0x05, 0x8b, 0x2b, 0x0a, 0xa2, 0x48, - 0x56, 0x61, 0xf1, 0x84, 0xd2, 0xc8, 0x4b, 0xb0, 0x88, 0xac, 0xc3, 0xf6, 0x44, 0xb4, 0x5c, 0x58, - 0x67, 0xff, 0x99, 0x05, 0x73, 0x4c, 0x9a, 0x3e, 0xf7, 0x82, 0x4b, 0xb9, 0x56, 0xbb, 0x85, 0x6b, - 0x75, 0x5f, 0x3b, 0x1c, 0x35, 0xec, 0x2f, 0xba, 0x50, 0xe5, 0xec, 0x42, 0x91, 0xbb, 0xd0, 0x34, - 0x86, 0x5b, 0xe5, 0x1a, 0x69, 0xec, 0x25, 0x07, 0x34, 0x5a, 0xbf, 0x4c, 0xe8, 0xaf, 0xbe, 0x94, - 0xef, 0x41, 0x27, 0x1d, 0xb6, 0x58, 0x47, 0x02, 0x15, 0x46, 0x98, 0xa2, 0x01, 0xfc, 0xdb, 0xfe, - 0x07, 0x16, 0x47, 0xdc, 0x08, 0x7d, 0xa5, 0xad, 0x32, 0x44, 0xa6, 0xf4, 0x4a, 0x44, 0xf6, 0xf7, - 0x54, 0x6d, 0xff, 0x57, 0x9f, 0x2c, 0x93, 0x89, 0x31, 0x0d, 0x06, 0xae, 0x37, 0x1c, 0xa2, 0x20, - 0xae, 0x39, 0xb3, 0xac, 0xbc, 0x36, 0x1c, 0xda, 0xef, 0xc3, 0xbc, 0x36, 0xba, 0x2b, 0xe6, 0xb1, - 0x07, 0x64, 0xd7, 0x8f, 0x93, 0x17, 0x41, 0x3c, 0xd6, 0x14, 0xb9, 0x9b, 0x50, 0x67, 0xd2, 0x96, - 0x8d, 0x8c, 0x73, 0x6e, 0xd5, 0x61, 0xe2, 0x97, 0x8d, 0x2b, 0xc6, 0x4a, 0xef, 0xb5, 0xa8, 0x2c, - 0x89, 0x4a, 0xef, 0x35, 0x56, 0xda, 0x8f, 0x61, 0xc1, 0x68, 0x4f, 0x74, 0xfd, 0x2e, 0x54, 0x27, - 0xc9, 0xeb, 0x50, 0xaa, 0xea, 0x0d, 0x41, 0x21, 0xcc, 0x28, 0x74, 0x78, 0x8d, 0xfd, 0x04, 0xe6, - 0xf7, 0xe8, 0x85, 0x60, 0x64, 0x39, 0x90, 0xf7, 0xde, 0x68, 0x30, 0x62, 0xbd, 0xbd, 0x02, 0x44, - 0xff, 0x38, 0x65, 0x00, 0x69, 0x3e, 0x5a, 0x86, 0xf9, 0x68, 0xbf, 0x07, 0xe4, 0xd0, 0x3f, 0x0d, - 0x9e, 0xd3, 0x38, 0xf6, 0x4e, 0x15, 0xeb, 0x77, 0xa0, 0x3c, 0x8a, 0x4f, 0x85, 0xa8, 0x62, 0x7f, - 0xda, 0x5f, 0x83, 0x05, 0x03, 0x4f, 0x34, 0x7c, 0x0b, 0xea, 0xb1, 0x7f, 0x1a, 0xa0, 0xa2, 0x25, - 0x9a, 0x4e, 0x01, 0xf6, 0x53, 0x58, 0xfc, 0x2e, 0x8d, 0xfc, 0x93, 0xcb, 0x37, 0x35, 0x6f, 0xb6, - 0x53, 0xca, 0xb6, 0xb3, 0x05, 0xd7, 0x33, 0xed, 0x88, 0xee, 0x39, 0xf9, 0x8a, 0x9d, 0xac, 0x39, - 0xbc, 0xa0, 0xc9, 0xbe, 0x92, 0x2e, 0xfb, 0xec, 0x17, 0x40, 0x36, 0xc2, 0x20, 0xa0, 0xfd, 0xe4, - 0x80, 0xd2, 0x28, 0xf5, 0x5c, 0xa5, 0xb4, 0xda, 0x58, 0x5d, 0x16, 0x2b, 0x9b, 0x15, 0xa8, 0x82, - 0x88, 0x09, 0x54, 0xc6, 0x34, 0x1a, 0x61, 0xc3, 0x35, 0x07, 0xff, 0xb6, 0xaf, 0xc3, 0x82, 0xd1, - 0xac, 0xb0, 0xf5, 0x3f, 0x84, 0xeb, 0x9b, 0x7e, 0xdc, 0xcf, 0x77, 0xd8, 0x85, 0xd9, 0xf1, 0xe4, - 0xd8, 0x4d, 0x39, 0x51, 0x16, 0x99, 0xf9, 0x97, 0xfd, 0x44, 0x34, 0xf6, 0xd7, 0x2d, 0xa8, 0x6c, - 0x1f, 0xed, 0x6e, 0xb0, 0xb3, 0xc2, 0x0f, 0xfa, 0xe1, 0x88, 0x69, 0x61, 0x7c, 0xd2, 0xaa, 0x3c, - 0x95, 0xc3, 0x6e, 0x41, 0x1d, 0x95, 0x37, 0x66, 0xf1, 0x0a, 0x3d, 0x28, 0x05, 0x30, 0x6b, 0x9b, - 0xbe, 0x1e, 0xfb, 0x11, 0x9a, 0xd3, 0xd2, 0x48, 0xae, 0xe0, 0x31, 0x93, 0xaf, 0xb0, 0xff, 0xdd, - 0x2c, 0xcc, 0x8a, 0xc3, 0x97, 0x1f, 0xe4, 0x89, 0x7f, 0x4e, 0xd3, 0x83, 0x9c, 0x95, 0x98, 0x62, - 0x1c, 0xd1, 0x51, 0x98, 0x28, 0xfd, 0x8d, 0x6f, 0x83, 0x09, 0x44, 0x6f, 0x82, 0x50, 0x22, 0xb8, - 0xff, 0xa1, 0xcc, 0xb1, 0x0c, 0x20, 0xb9, 0x05, 0xb3, 0x52, 0x19, 0xa8, 0x28, 0x43, 0x47, 0x82, - 0xd8, 0x6a, 0xf4, 0xbd, 0xb1, 0xd7, 0xf7, 0x93, 0x4b, 0x21, 0x16, 0x54, 0x99, 0xb5, 0x3f, 0x0c, - 0xfb, 0xde, 0xd0, 0x3d, 0xf6, 0x86, 0x5e, 0xd0, 0xa7, 0xd2, 0x5b, 0x61, 0x00, 0x99, 0xe5, 0x2e, - 0x86, 0x25, 0xd1, 0xb8, 0x75, 0x9f, 0x81, 0xb2, 0x33, 0xbc, 0x1f, 0x8e, 0x46, 0x3e, 0xb3, 0x3e, - 0xb8, 0x6a, 0x56, 0x76, 0x34, 0x08, 0xf7, 0x8d, 0x60, 0xe9, 0x82, 0xaf, 0x60, 0x5d, 0xfa, 0x46, - 0x34, 0x20, 0x6b, 0x25, 0xa3, 0xa1, 0x95, 0x1d, 0x0d, 0xc2, 0xf6, 0x62, 0x12, 0xc4, 0x34, 0x49, - 0x86, 0x74, 0xa0, 0x06, 0xd4, 0x40, 0xb4, 0x7c, 0x05, 0x79, 0x04, 0x0b, 0xdc, 0x07, 0x11, 0x7b, - 0x49, 0x18, 0x9f, 0xf9, 0xb1, 0x1b, 0x33, 0xf3, 0x89, 0xdb, 0xc2, 0x45, 0x55, 0xe4, 0x31, 0x2c, - 0x67, 0xc0, 0x11, 0xed, 0x53, 0xff, 0x9c, 0x0e, 0x50, 0x85, 0x2b, 0x3b, 0xd3, 0xaa, 0xc9, 0x5d, - 0x68, 0x04, 0x93, 0x91, 0x3b, 0x19, 0x0f, 0x3c, 0xa6, 0xc4, 0xb4, 0x51, 0xb9, 0xd4, 0x41, 0xe4, - 0x43, 0x90, 0x7a, 0x9a, 0xd0, 0x1e, 0xe7, 0x0c, 0x09, 0xc7, 0xa8, 0xd7, 0x31, 0x31, 0x18, 0x61, - 0xa6, 0x2a, 0x69, 0x47, 0xd8, 0x9d, 0x12, 0x80, 0x7c, 0x12, 0xf9, 0xe7, 0x5e, 0x42, 0xbb, 0xf3, - 0x5c, 0xa8, 0x8b, 0x22, 0xfb, 0xce, 0x0f, 0xfc, 0xc4, 0xf7, 0x92, 0x30, 0xea, 0x12, 0xac, 0x4b, - 0x01, 0x6c, 0x11, 0x91, 0x3e, 0xe2, 0xc4, 0x4b, 0x26, 0xb1, 0xd0, 0x50, 0x17, 0x90, 0xb8, 0xf2, - 0x15, 0xe4, 0x23, 0x58, 0xe2, 0x14, 0x81, 0x55, 0x42, 0xf7, 0x46, 0x55, 0x61, 0x11, 0x57, 0x64, - 0x4a, 0x2d, 0x5b, 0x4a, 0x41, 0x22, 0xb9, 0x0f, 0xaf, 0xf3, 0xa5, 0x9c, 0x52, 0xcd, 0xc6, 0xc7, - 0x46, 0xe0, 0xf7, 0x5d, 0x81, 0xc1, 0x58, 0x64, 0x09, 0x67, 0x91, 0xaf, 0x60, 0x24, 0x3e, 0xf4, - 0x4f, 0x68, 0xe2, 0x8f, 0x68, 0x77, 0x99, 0x93, 0xb8, 0x2c, 0x33, 0x06, 0x9c, 0x8c, 0xb1, 0xa6, - 0xcb, 0x19, 0x9e, 0x97, 0x90, 0x18, 0x87, 0x61, 0x4c, 0xa5, 0xe7, 0xa9, 0x7b, 0x43, 0xb0, 0x96, - 0x0e, 0xb4, 0xff, 0x95, 0xc5, 0x8f, 0x28, 0xc1, 0xce, 0xb1, 0x66, 0x7c, 0x71, 0x46, 0x76, 0xc3, - 0x60, 0x78, 0x29, 0x78, 0x1b, 0x38, 0x68, 0x3f, 0x18, 0x5e, 0x32, 0xf5, 0xdf, 0x0f, 0x74, 0x14, - 0x2e, 0x0d, 0x9b, 0x12, 0x88, 0x48, 0xef, 0x40, 0x63, 0x3c, 0x39, 0x1e, 0xfa, 0x7d, 0x8e, 0x52, - 0xe6, 0xad, 0x70, 0x10, 0x22, 0x30, 0xeb, 0x93, 0xef, 0x27, 0xc7, 0xa8, 0x20, 0x46, 0x43, 0xc0, - 0x10, 0x05, 0xa5, 0x2d, 0x8d, 0x90, 0xb5, 0x9b, 0x0e, 0xfe, 0x6d, 0xaf, 0xc3, 0xa2, 0x39, 0x68, - 0x71, 0x14, 0x3c, 0x80, 0x9a, 0x90, 0x1c, 0xd2, 0x35, 0xd1, 0xd6, 0x1c, 0xc6, 0xcc, 0x80, 0x52, - 0xf5, 0xf6, 0xcf, 0x66, 0x60, 0x41, 0x40, 0x37, 0xd8, 0x92, 0x1c, 0x4e, 0x46, 0x23, 0x2f, 0x2a, - 0x10, 0x49, 0xd6, 0x1b, 0x44, 0x52, 0x29, 0x2f, 0x92, 0xee, 0x18, 0x96, 0x29, 0x97, 0x69, 0x1a, - 0x84, 0xdc, 0x87, 0x39, 0xb6, 0x0d, 0xdc, 0x50, 0xd0, 0x7d, 0x96, 0x59, 0x70, 0x5e, 0x8c, 0x56, - 0x8b, 0xc4, 0xa8, 0x2e, 0x02, 0x67, 0x32, 0x22, 0xd0, 0x86, 0x26, 0xdf, 0x72, 0x21, 0xd5, 0x67, - 0x85, 0x99, 0xa6, 0xc1, 0xd8, 0x78, 0xb2, 0x02, 0x87, 0x4b, 0xb7, 0xb9, 0x22, 0x71, 0xe3, 0x8f, - 0x28, 0x9e, 0x1a, 0x1a, 0x76, 0x5d, 0x88, 0x9b, 0x7c, 0x15, 0x79, 0x0a, 0xc0, 0xfb, 0x42, 0xd5, - 0x05, 0x50, 0x75, 0x79, 0xcf, 0xdc, 0x15, 0x7d, 0xfd, 0x57, 0x58, 0x61, 0x12, 0x51, 0x54, 0x67, - 0xb4, 0x2f, 0xc9, 0x2e, 0xb4, 0xc3, 0x31, 0x0d, 0xdc, 0x94, 0xe9, 0x1b, 0xd8, 0xd6, 0xbd, 0x2b, - 0xda, 0xda, 0x91, 0xb8, 0x4e, 0xe6, 0x5b, 0xb2, 0xc7, 0x77, 0x80, 0x6a, 0xcd, 0x35, 0xbf, 0x40, - 0x73, 0xd9, 0x8f, 0xed, 0xbf, 0x69, 0x41, 0x43, 0x1b, 0x39, 0xb9, 0x0e, 0xf3, 0x1b, 0xfb, 0xfb, - 0x07, 0x5b, 0xce, 0xda, 0xd1, 0xce, 0x77, 0xb7, 0xdc, 0x8d, 0xdd, 0xfd, 0xc3, 0xad, 0xce, 0x35, - 0x06, 0xde, 0xdd, 0xdf, 0x58, 0xdb, 0x75, 0x9f, 0xee, 0x3b, 0x1b, 0x12, 0x6c, 0x91, 0x25, 0x20, - 0xce, 0xd6, 0xf3, 0xfd, 0xa3, 0x2d, 0x03, 0x5e, 0x22, 0x1d, 0x68, 0xae, 0x3b, 0x5b, 0x6b, 0x1b, - 0xdb, 0x02, 0x52, 0x26, 0x8b, 0xd0, 0x79, 0xfa, 0x62, 0x6f, 0x73, 0x67, 0xef, 0x99, 0xbb, 0xb1, - 0xb6, 0xb7, 0xb1, 0xb5, 0xbb, 0xb5, 0xd9, 0xa9, 0x90, 0x16, 0xd4, 0xd7, 0xd6, 0xd7, 0xf6, 0x36, - 0xf7, 0xf7, 0xb6, 0x36, 0x3b, 0x55, 0xfb, 0x9b, 0x50, 0x57, 0x43, 0x25, 0x0d, 0x98, 0x7d, 0xb1, - 0xf7, 0xe9, 0xde, 0xfe, 0xcb, 0xbd, 0xce, 0x35, 0x52, 0x87, 0x2a, 0xf6, 0xdf, 0xb1, 0x08, 0xc0, - 0x0c, 0xef, 0xb3, 0x53, 0x22, 0x35, 0xa8, 0xac, 0xef, 0x1f, 0x6d, 0x77, 0xca, 0xf6, 0x7f, 0xb3, - 0xe0, 0x3a, 0xce, 0x79, 0x90, 0x95, 0x08, 0x77, 0xa1, 0xd1, 0x0f, 0xc3, 0x31, 0xb3, 0x85, 0xd2, - 0xd3, 0x5e, 0x07, 0x31, 0x6e, 0xe7, 0x72, 0xf2, 0x24, 0x8c, 0xfa, 0x54, 0x08, 0x04, 0x40, 0xd0, - 0x53, 0x06, 0x61, 0xdc, 0x2e, 0xe8, 0x96, 0x63, 0x70, 0x79, 0xd0, 0xe0, 0x30, 0x8e, 0xb2, 0x04, - 0x33, 0xc7, 0x11, 0xf5, 0xfa, 0x67, 0x42, 0x14, 0x88, 0x12, 0xf9, 0x72, 0x6a, 0xac, 0xf7, 0x19, - 0x59, 0x0d, 0xe9, 0x00, 0x59, 0xa1, 0xe6, 0xcc, 0x09, 0xf8, 0x86, 0x00, 0xb3, 0x83, 0xc1, 0x3b, - 0xf6, 0x82, 0x41, 0x18, 0xd0, 0x81, 0xb0, 0x04, 0x52, 0x80, 0x7d, 0x00, 0x4b, 0xd9, 0xf9, 0x09, - 0xe1, 0xf1, 0x91, 0x26, 0x3c, 0xb8, 0x62, 0xde, 0x9b, 0x4e, 0x0b, 0x9a, 0x20, 0xf9, 0xb3, 0x32, - 0x54, 0x98, 0x9e, 0x36, 0x5d, 0xa7, 0xd3, 0x55, 0xef, 0x72, 0x2e, 0x72, 0x83, 0xf6, 0x3f, 0x3f, - 0xb5, 0x85, 0xef, 0x29, 0x85, 0xa4, 0xf5, 0x11, 0xed, 0x9f, 0x0b, 0xef, 0x93, 0x06, 0x61, 0x9c, - 0xcf, 0xec, 0x22, 0xfc, 0x5a, 0x70, 0xbe, 0x2c, 0xcb, 0x3a, 0xfc, 0x72, 0x36, 0xad, 0xc3, 0xef, - 0xba, 0x30, 0xeb, 0x07, 0xc7, 0xe1, 0x24, 0x18, 0x20, 0xa7, 0xd7, 0x1c, 0x59, 0xc4, 0x58, 0x11, - 0x4a, 0x20, 0x76, 0xa4, 0x70, 0xbe, 0x4e, 0x01, 0x64, 0x15, 0xea, 0xf1, 0x65, 0xd0, 0xd7, 0x99, - 0x79, 0x51, 0xac, 0x12, 0x5b, 0x83, 0x95, 0xc3, 0xcb, 0xa0, 0x8f, 0xac, 0x9b, 0xa2, 0x91, 0x6f, - 0x40, 0x4d, 0x79, 0x6b, 0xb9, 0x54, 0xbe, 0xa1, 0x7f, 0x22, 0x5d, 0xb4, 0xdc, 0x08, 0x56, 0xa8, - 0xbd, 0x4f, 0xa1, 0x65, 0x54, 0xe9, 0x96, 0x6b, 0x8b, 0x5b, 0xae, 0xf7, 0x74, 0xcb, 0x35, 0x15, - 0xf6, 0xe2, 0x33, 0xdd, 0x92, 0xfd, 0x5d, 0xa8, 0xc9, 0xa1, 0x31, 0xae, 0x12, 0x1c, 0xe1, 0x1e, - 0x7e, 0x6f, 0x6f, 0xa3, 0x73, 0x8d, 0xcc, 0x41, 0x63, 0x6d, 0x03, 0x19, 0x15, 0x01, 0x16, 0x43, - 0x39, 0x58, 0x3b, 0x3c, 0x54, 0x90, 0x92, 0x4d, 0xa0, 0xc3, 0x8e, 0x1c, 0x36, 0x62, 0x15, 0x8f, - 0xf9, 0x08, 0xe6, 0x35, 0x58, 0x6a, 0xdc, 0xb1, 0x33, 0x2a, 0x6b, 0xdc, 0xa1, 0x26, 0xcf, 0x6b, - 0xec, 0x65, 0xb8, 0xce, 0x8a, 0x5b, 0xe7, 0x34, 0x48, 0x0e, 0x27, 0xc7, 0x3c, 0x0c, 0xe7, 0x87, - 0x81, 0xfd, 0xd7, 0x2c, 0xa8, 0xab, 0x9a, 0x2b, 0xe8, 0x49, 0x46, 0x0e, 0x4b, 0xb8, 0x01, 0x3d, - 0xad, 0x0b, 0xfc, 0x72, 0x05, 0xff, 0x35, 0x0c, 0xc2, 0xba, 0x02, 0xb1, 0xc9, 0x1e, 0x6c, 0x6d, - 0x39, 0xee, 0xfe, 0xde, 0xee, 0xce, 0x1e, 0x13, 0x4a, 0x6c, 0xb2, 0x08, 0x78, 0xfa, 0x14, 0x21, - 0x96, 0xdd, 0x81, 0xf6, 0x33, 0x9a, 0xec, 0x04, 0x27, 0xa1, 0x9c, 0xea, 0xff, 0xad, 0xc2, 0x9c, - 0x02, 0xa5, 0x06, 0xe5, 0x39, 0x8d, 0x62, 0x3f, 0x0c, 0x50, 0x15, 0xac, 0x3b, 0xb2, 0xc8, 0xce, - 0x13, 0x7f, 0x40, 0x83, 0xc4, 0x4f, 0x2e, 0x5d, 0xc3, 0x03, 0x95, 0x05, 0x33, 0xe3, 0xcd, 0x1b, - 0xfa, 0x9e, 0x8c, 0x68, 0xf2, 0x02, 0x83, 0xf6, 0xc3, 0x61, 0x18, 0xa1, 0xce, 0x57, 0x77, 0x78, - 0x81, 0xac, 0xc2, 0x22, 0xd3, 0x35, 0x75, 0xff, 0x20, 0x32, 0x2b, 0x77, 0x87, 0x15, 0xd6, 0xb1, - 0xf3, 0x8a, 0xc1, 0x85, 0xa2, 0xa2, 0x3e, 0xe1, 0xa6, 0x4d, 0x51, 0x15, 0xf9, 0x3a, 0x5c, 0x67, - 0x60, 0xa5, 0xdc, 0xa8, 0x6f, 0xe6, 0xf0, 0x9b, 0xe2, 0x4a, 0xc6, 0x35, 0xbc, 0x7f, 0xb6, 0xf3, - 0x55, 0xae, 0xc5, 0x2a, 0x40, 0x2e, 0xfc, 0x38, 0xc3, 0xcf, 0xe0, 0x6c, 0xf8, 0x51, 0x0b, 0x61, - 0xd6, 0x72, 0x21, 0xcc, 0xaf, 0xc3, 0xf5, 0x63, 0x1a, 0x27, 0xee, 0x19, 0xf5, 0x06, 0x34, 0x42, - 0x6e, 0xe4, 0x91, 0x4a, 0xae, 0xb4, 0x17, 0x57, 0xe2, 0xc9, 0x7e, 0x19, 0xf4, 0xe9, 0xc0, 0x4d, - 0x42, 0x17, 0x35, 0x10, 0xe4, 0xe9, 0x9a, 0x93, 0x05, 0x9b, 0x98, 0xa7, 0x91, 0x37, 0x3e, 0x13, - 0x5a, 0x75, 0x16, 0xcc, 0x74, 0x9f, 0x84, 0xc6, 0x49, 0x40, 0x79, 0x9c, 0xa8, 0x86, 0x31, 0x00, - 0x09, 0x22, 0xf7, 0x60, 0x06, 0x1b, 0x8c, 0xbb, 0x1d, 0x64, 0x80, 0x66, 0x2a, 0x44, 0xfd, 0xc0, - 0x11, 0x75, 0x4c, 0xab, 0x9b, 0x44, 0x7e, 0xdc, 0x6d, 0x62, 0x88, 0x14, 0xff, 0x26, 0xdf, 0xd6, - 0xe4, 0xc4, 0x02, 0x7e, 0x2b, 0x0f, 0xe3, 0x0c, 0xe5, 0xfd, 0x46, 0x44, 0xc6, 0x27, 0x95, 0x5a, - 0xa3, 0xd3, 0xb4, 0x7f, 0x1b, 0xaa, 0x38, 0x72, 0xa4, 0x49, 0x5c, 0x3f, 0x4b, 0xd0, 0x24, 0x42, - 0xbb, 0x30, 0x1b, 0xd0, 0xe4, 0x22, 0x8c, 0x5e, 0xc9, 0x98, 0xbc, 0x28, 0xda, 0x3f, 0x46, 0x47, - 0x83, 0x8a, 0x51, 0xbf, 0x40, 0x0b, 0x89, 0xdc, 0x84, 0x3a, 0xdf, 0xd3, 0xf8, 0xcc, 0x13, 0xbe, - 0x8f, 0x1a, 0x02, 0x0e, 0xcf, 0x3c, 0x76, 0x3e, 0x1a, 0x64, 0xc2, 0xdd, 0x49, 0x0d, 0x84, 0x6d, - 0x73, 0x2a, 0xb9, 0x07, 0x6d, 0x19, 0xfd, 0x8e, 0xdd, 0x21, 0x3d, 0x49, 0xa4, 0x33, 0x38, 0x98, - 0x8c, 0xd0, 0xe7, 0xb4, 0x4b, 0x4f, 0x12, 0x7b, 0x0f, 0xe6, 0xc5, 0x99, 0xb5, 0x3f, 0xa6, 0xb2, - 0xeb, 0x6f, 0x16, 0x29, 0xb6, 0x8d, 0xd5, 0x05, 0xf3, 0x90, 0xe3, 0xf1, 0x7e, 0x13, 0xd3, 0x76, - 0x80, 0xe8, 0x67, 0xa0, 0x68, 0x50, 0x68, 0x96, 0xd2, 0xdd, 0x2d, 0xa6, 0x63, 0xc0, 0xd8, 0xfa, - 0xc4, 0x93, 0x7e, 0x5f, 0xde, 0x59, 0xa8, 0x39, 0xb2, 0x68, 0xff, 0x27, 0x0b, 0x16, 0xb0, 0x35, - 0xa9, 0x9a, 0x0b, 0x3d, 0xe3, 0xf1, 0x17, 0x18, 0xa6, 0x0c, 0x36, 0x70, 0x17, 0xfb, 0x22, 0x54, - 0x75, 0xcd, 0x83, 0x17, 0xbe, 0xb8, 0x6b, 0xb1, 0x92, 0x73, 0x2d, 0x3e, 0x80, 0xce, 0x80, 0x0e, - 0x7d, 0xbc, 0xb7, 0x22, 0xcf, 0x71, 0xae, 0x87, 0xe7, 0xe0, 0xf6, 0xdf, 0xb1, 0x60, 0x9e, 0x2b, - 0x0a, 0x68, 0x60, 0x8a, 0xa5, 0xfa, 0x0b, 0xd2, 0x18, 0x13, 0x02, 0x4a, 0x4c, 0x2a, 0x3d, 0x3a, - 0x11, 0xca, 0x91, 0xb7, 0xaf, 0x39, 0x26, 0x32, 0x79, 0x82, 0xe6, 0x44, 0xe0, 0x22, 0xb4, 0xe0, - 0x26, 0x8c, 0xb9, 0x2f, 0xdb, 0xd7, 0x1c, 0x0d, 0x7d, 0xbd, 0xc6, 0xec, 0x43, 0x06, 0xb7, 0x9f, - 0x41, 0xcb, 0xe8, 0xc8, 0x70, 0x81, 0x36, 0xb9, 0x0b, 0x34, 0x17, 0x6b, 0x28, 0x15, 0xc4, 0x1a, - 0x7e, 0x56, 0x01, 0xc2, 0x08, 0x2b, 0xb3, 0x73, 0x77, 0xcd, 0x80, 0x9d, 0xbc, 0x14, 0x93, 0x82, - 0xc8, 0x2a, 0x10, 0xad, 0x28, 0x03, 0x89, 0x65, 0x15, 0x48, 0x2c, 0xa8, 0x65, 0x52, 0x5f, 0x68, - 0x95, 0x2a, 0x48, 0x87, 0xee, 0x2d, 0xbe, 0x4d, 0x85, 0x75, 0x4c, 0xf3, 0xc1, 0x88, 0x1d, 0x33, - 0xc4, 0x85, 0x4b, 0x48, 0x96, 0xb3, 0xf4, 0x30, 0xf3, 0x46, 0x7a, 0x98, 0xcd, 0xd1, 0x83, 0xe6, - 0x94, 0xa8, 0x99, 0x4e, 0x89, 0x7b, 0xd0, 0x92, 0x81, 0x39, 0x7e, 0x27, 0x41, 0x78, 0x80, 0x0c, - 0x20, 0xa3, 0x27, 0xe9, 0x17, 0x50, 0x9e, 0x0f, 0x1e, 0x71, 0xcf, 0xc1, 0xd9, 0xc1, 0x92, 0x3a, - 0x9f, 0x1b, 0x38, 0xd8, 0x14, 0x80, 0x6e, 0x04, 0x46, 0x25, 0xee, 0x24, 0x10, 0x17, 0x62, 0xe8, - 0x00, 0x0d, 0x99, 0x9a, 0x93, 0xaf, 0xc8, 0xbb, 0x04, 0x5a, 0x05, 0x2e, 0x01, 0xf2, 0x51, 0x1a, - 0xc5, 0x8a, 0xcf, 0xfc, 0x11, 0x9e, 0xed, 0xe9, 0x7d, 0x92, 0xa7, 0xbc, 0xea, 0xf0, 0xcc, 0x1f, - 0x39, 0x06, 0x9e, 0xfd, 0x0b, 0x0b, 0x3a, 0x8c, 0x2a, 0x0c, 0xc2, 0xff, 0x18, 0x90, 0x47, 0xdf, - 0x92, 0xee, 0x0d, 0x5c, 0xf2, 0x18, 0xea, 0x58, 0x66, 0xa6, 0x9b, 0xa0, 0xfa, 0xae, 0x49, 0xf5, - 0xa9, 0x74, 0xdb, 0xbe, 0xe6, 0xa4, 0xc8, 0xec, 0x2c, 0xcb, 0x46, 0x11, 0x79, 0x48, 0x3c, 0x0b, - 0xd6, 0xb8, 0x63, 0x1b, 0xe0, 0x53, 0x7a, 0xb9, 0x1b, 0xf6, 0xd1, 0x6a, 0xba, 0x0d, 0xc0, 0x68, - 0xf0, 0xc4, 0x1b, 0xf9, 0xc2, 0xfd, 0x51, 0x75, 0xea, 0xaf, 0xe8, 0xe5, 0x53, 0x04, 0x30, 0x31, - 0xce, 0xaa, 0x53, 0x16, 0xa9, 0x3a, 0xb5, 0x57, 0xf4, 0x72, 0x07, 0xd9, 0xc3, 0x85, 0xd6, 0xa7, - 0xf4, 0x72, 0x93, 0x72, 0xbd, 0x2e, 0x8c, 0x88, 0x0d, 0xad, 0xc8, 0xbb, 0x60, 0x9a, 0x9b, 0x11, - 0xfe, 0x6b, 0x44, 0xde, 0xc5, 0xa7, 0xf4, 0x72, 0x1d, 0xe3, 0x7f, 0x0f, 0x60, 0x96, 0xd5, 0x0f, - 0xc3, 0xbe, 0x38, 0x99, 0xe4, 0x8d, 0x86, 0x74, 0x50, 0xce, 0xcc, 0x2b, 0xfc, 0xdb, 0xfe, 0x0f, - 0x16, 0xb4, 0xd8, 0x0a, 0xa0, 0xd8, 0x63, 0x3b, 0x21, 0x2f, 0xc6, 0x58, 0xe9, 0xc5, 0x98, 0x55, - 0x21, 0x33, 0xb8, 0x0c, 0x2d, 0x4d, 0x97, 0xa1, 0xb8, 0x6c, 0x5c, 0x80, 0x7e, 0x08, 0x75, 0xce, - 0x4e, 0x8c, 0x7d, 0xcb, 0xc6, 0x4e, 0x19, 0x13, 0x72, 0x6a, 0x88, 0xf6, 0x29, 0x8f, 0xc1, 0x6b, - 0x0e, 0x2c, 0xbe, 0xc8, 0x75, 0x0e, 0x61, 0xd5, 0x05, 0xe1, 0xdc, 0x6a, 0x51, 0x38, 0xf7, 0x05, - 0x34, 0x34, 0xc2, 0x22, 0xdf, 0xe2, 0x81, 0x70, 0x3e, 0x78, 0x4e, 0x85, 0x26, 0xe1, 0x18, 0xb3, - 0x47, 0x81, 0xa9, 0x03, 0xd6, 0x67, 0xa0, 0x82, 0x24, 0xf9, 0x04, 0xe6, 0xb5, 0x66, 0xb9, 0x85, - 0x58, 0x34, 0x26, 0xab, 0x68, 0x4c, 0x7f, 0xd7, 0x82, 0x45, 0xf1, 0x35, 0x5e, 0xa2, 0xf2, 0xd9, - 0x31, 0xfe, 0x3c, 0x3e, 0x65, 0x07, 0x29, 0x6b, 0xdd, 0x8d, 0xe8, 0xa9, 0x1f, 0x27, 0x54, 0x46, - 0x0d, 0x0a, 0x38, 0x84, 0x91, 0x34, 0x43, 0x75, 0x04, 0x26, 0x79, 0x02, 0x0d, 0xfc, 0x94, 0xdb, - 0xb0, 0x62, 0x5b, 0xba, 0xf9, 0x0f, 0xf9, 0x50, 0x99, 0x24, 0x8f, 0x55, 0x69, 0xbd, 0x0e, 0xb3, - 0x49, 0xe4, 0x9f, 0x9e, 0xd2, 0xc8, 0x5e, 0x52, 0x43, 0x63, 0xdc, 0x46, 0x0f, 0x13, 0x3a, 0x66, - 0xca, 0x11, 0xa3, 0x8c, 0x86, 0x60, 0xaa, 0x5f, 0x3a, 0x52, 0xd0, 0xd3, 0xae, 0x03, 0x72, 0x6b, - 0x35, 0xbd, 0xfd, 0x77, 0x1f, 0xe6, 0x46, 0x4c, 0x51, 0x62, 0x1a, 0xbc, 0x11, 0x25, 0xc8, 0x82, - 0x99, 0xe2, 0x8d, 0x7a, 0x4b, 0xec, 0x26, 0xfe, 0xd0, 0x95, 0xb5, 0xe2, 0xe2, 0x5d, 0x51, 0x15, - 0x3b, 0xbe, 0xe3, 0xc4, 0x3b, 0xa5, 0x42, 0x3b, 0xe6, 0x05, 0xbb, 0x0b, 0x4b, 0x07, 0xe9, 0xb6, - 0x68, 0x0e, 0x09, 0xfb, 0x5f, 0xb4, 0x60, 0x39, 0x57, 0xa5, 0xae, 0x09, 0x0b, 0xd7, 0xf7, 0xd0, - 0x1f, 0x1d, 0x87, 0xca, 0x4d, 0x65, 0xe9, 0x5e, 0x71, 0xa3, 0x8a, 0x9c, 0xc2, 0x75, 0x49, 0x15, - 0xe8, 0x2a, 0x52, 0x6a, 0x7f, 0x09, 0x35, 0xd1, 0x0f, 0x4d, 0x89, 0x95, 0xed, 0x50, 0xc2, 0xf5, - 0x53, 0xb1, 0xb8, 0x3d, 0x72, 0x06, 0x5d, 0x45, 0x7e, 0x42, 0x53, 0xd2, 0x2c, 0x19, 0xd6, 0xd7, - 0x07, 0x6f, 0xe8, 0xcb, 0xf0, 0x5f, 0x38, 0x53, 0x5b, 0x23, 0x97, 0x70, 0x47, 0xd6, 0xa1, 0x2a, - 0x94, 0xef, 0xaf, 0xf2, 0x56, 0x73, 0x43, 0xcf, 0x8c, 0xd9, 0xe9, 0x1b, 0x1a, 0x26, 0x3f, 0x82, - 0xa5, 0x0b, 0xcf, 0x4f, 0xe4, 0xb0, 0x34, 0x2b, 0xaa, 0x8a, 0x5d, 0xae, 0xbe, 0xa1, 0xcb, 0x97, - 0xfc, 0x63, 0x43, 0x3f, 0x9c, 0xd2, 0x62, 0xef, 0x17, 0x25, 0x68, 0x9b, 0xed, 0x30, 0x32, 0x15, - 0x52, 0x49, 0x2a, 0x14, 0xd2, 0xfe, 0xcc, 0x80, 0xf3, 0xde, 0xde, 0x52, 0x91, 0xb7, 0x57, 0xf7, - 0xaf, 0x96, 0xdf, 0x14, 0x62, 0xaa, 0xbc, 0x5d, 0x88, 0xa9, 0x5a, 0x18, 0x62, 0x9a, 0x1e, 0x89, - 0x98, 0xf9, 0x65, 0x23, 0x11, 0xb3, 0x57, 0x46, 0x22, 0x7a, 0xff, 0xc7, 0x02, 0x92, 0xa7, 0x5e, - 0xf2, 0x8c, 0x3b, 0xb8, 0x03, 0x3a, 0x14, 0xe2, 0xed, 0xab, 0x6f, 0xc7, 0x01, 0x72, 0xb7, 0xe4, - 0xd7, 0x8c, 0x15, 0xf5, 0xbb, 0xba, 0xba, 0x6d, 0xd3, 0x72, 0x8a, 0xaa, 0x32, 0x61, 0xb6, 0xca, - 0x9b, 0xc3, 0x6c, 0xd5, 0x37, 0x87, 0xd9, 0x66, 0xb2, 0x61, 0xb6, 0xde, 0x5f, 0xb5, 0x60, 0xa1, - 0x80, 0xcc, 0x7e, 0x7d, 0x13, 0x67, 0x84, 0x61, 0x48, 0x9f, 0x92, 0x20, 0x0c, 0x1d, 0xd8, 0xfb, - 0x4b, 0xd0, 0x32, 0x58, 0xeb, 0xd7, 0xd7, 0x7f, 0xd6, 0x3c, 0xe3, 0x94, 0x6d, 0xc0, 0x7a, 0xff, - 0xb3, 0x04, 0x24, 0xcf, 0xde, 0xbf, 0xd1, 0x31, 0xe4, 0xd7, 0xa9, 0x5c, 0xb0, 0x4e, 0xff, 0x5f, - 0x4f, 0x9e, 0x0f, 0x60, 0x5e, 0x24, 0x20, 0x68, 0x21, 0x0d, 0x4e, 0x31, 0xf9, 0x0a, 0x66, 0xa0, - 0x9a, 0x31, 0xce, 0x9a, 0x71, 0xe1, 0x5a, 0x3b, 0x7e, 0x33, 0xa1, 0x4e, 0xbb, 0x07, 0x5d, 0xb1, - 0x42, 0x79, 0xd7, 0xdf, 0xdf, 0xaf, 0x28, 0x1b, 0x1b, 0x2b, 0x85, 0xfe, 0xfc, 0x75, 0x68, 0xea, - 0xc7, 0x87, 0xd8, 0x8e, 0x4c, 0x54, 0x8b, 0xa9, 0x19, 0x3a, 0x16, 0xd9, 0x84, 0x36, 0x0a, 0xc9, - 0x81, 0xfa, 0x8e, 0x6b, 0x1a, 0x57, 0x38, 0xb4, 0xb7, 0xaf, 0x39, 0x99, 0x6f, 0xc8, 0xef, 0x40, - 0xdb, 0x74, 0x73, 0x09, 0x9d, 0xb0, 0x48, 0x8d, 0x64, 0x9f, 0x9b, 0xc8, 0x64, 0x0d, 0x3a, 0x59, - 0x3f, 0x99, 0xb8, 0x0d, 0x3a, 0xa5, 0x81, 0x1c, 0x3a, 0xf9, 0x04, 0x16, 0x8b, 0x0e, 0x51, 0xdc, - 0x9b, 0xe9, 0x56, 0x44, 0xe1, 0x37, 0xe4, 0xb1, 0xf0, 0x99, 0x56, 0x8b, 0xc2, 0x3c, 0xda, 0x92, - 0xaf, 0xf0, 0xff, 0x34, 0xef, 0xe9, 0x39, 0x40, 0x0a, 0x23, 0x1d, 0x68, 0xee, 0x1f, 0x6c, 0xed, - 0xb9, 0x1b, 0xdb, 0x6b, 0x7b, 0x7b, 0x5b, 0xbb, 0x9d, 0x6b, 0x84, 0x40, 0x1b, 0xc3, 0x33, 0x9b, - 0x0a, 0x66, 0x31, 0x98, 0xf0, 0x28, 0x4b, 0x58, 0x89, 0x2c, 0x42, 0x67, 0x67, 0x2f, 0x03, 0x2d, - 0x93, 0x2e, 0x2c, 0x1e, 0x6c, 0xf1, 0x88, 0x8e, 0xd1, 0x6e, 0x85, 0xe9, 0x7b, 0x62, 0xf0, 0x4c, - 0xdf, 0xe3, 0x69, 0x2c, 0xeb, 0x9c, 0x08, 0xa5, 0x0e, 0xf4, 0x0f, 0x2d, 0xb8, 0x9e, 0xa9, 0x48, - 0x2f, 0x26, 0x73, 0x35, 0xc7, 0xd4, 0x7d, 0x4c, 0x20, 0x86, 0xc9, 0xa5, 0x79, 0x98, 0x91, 0x53, - 0xf9, 0x0a, 0xc6, 0x59, 0x9a, 0x39, 0x99, 0xe1, 0xd7, 0xa2, 0x2a, 0x7b, 0x59, 0xdd, 0xff, 0xcc, - 0x0c, 0xfc, 0x84, 0xa7, 0xc7, 0xe8, 0x15, 0xa9, 0x57, 0xd9, 0x1c, 0xb2, 0x2c, 0x92, 0xd5, 0x0c, - 0x35, 0x98, 0xe3, 0x2d, 0xac, 0xb3, 0xff, 0xf9, 0x0c, 0x90, 0xef, 0x4c, 0x68, 0x74, 0x89, 0x37, - 0x8f, 0x55, 0x30, 0x6b, 0x39, 0xeb, 0x5a, 0x9f, 0x19, 0x4f, 0x8e, 0x99, 0xc1, 0x22, 0x0c, 0xa9, - 0xd2, 0x5b, 0x65, 0x18, 0x14, 0xdd, 0xf0, 0xaf, 0xbc, 0xf9, 0x86, 0x7f, 0xf5, 0x4d, 0x37, 0xfc, - 0xbf, 0x04, 0x2d, 0xff, 0x34, 0x08, 0x99, 0xd0, 0x61, 0x8a, 0x4a, 0xdc, 0x9d, 0xb9, 0x5b, 0xbe, - 0xdf, 0x74, 0x9a, 0x02, 0xb8, 0xc7, 0x60, 0xe4, 0x49, 0x8a, 0x44, 0x07, 0xa7, 0x98, 0x91, 0xa2, - 0x8b, 0xa1, 0xad, 0xc1, 0x29, 0x15, 0x76, 0x23, 0xba, 0x56, 0xe4, 0xc7, 0x0c, 0x1e, 0x93, 0x7b, - 0xd0, 0x8e, 0xc3, 0x09, 0x53, 0xdd, 0xe4, 0x32, 0x70, 0x87, 0x73, 0x93, 0x43, 0x0f, 0xf8, 0x62, - 0xac, 0xc0, 0xc2, 0x24, 0xa6, 0xee, 0xc8, 0x8f, 0x63, 0x76, 0x3c, 0xf7, 0xc3, 0x20, 0x89, 0xc2, - 0xa1, 0x70, 0x20, 0xcf, 0x4f, 0x62, 0xfa, 0x9c, 0xd7, 0x6c, 0xf0, 0x0a, 0xf2, 0xf5, 0x74, 0x48, - 0x63, 0xcf, 0x8f, 0xe2, 0x2e, 0xe0, 0x90, 0xe4, 0x4c, 0xd9, 0xb8, 0x0f, 0x3c, 0x3f, 0x52, 0x63, - 0x61, 0x85, 0x38, 0x93, 0x79, 0xd0, 0xc8, 0x66, 0x1e, 0xfc, 0xb0, 0x38, 0xf3, 0xa0, 0x85, 0x4d, - 0x3f, 0x12, 0x4d, 0xe7, 0xb7, 0xf8, 0x0b, 0x25, 0x20, 0xe4, 0x13, 0x2a, 0xda, 0x5f, 0x24, 0xa1, - 0x62, 0xae, 0x28, 0xa1, 0xe2, 0x43, 0x68, 0xe0, 0x35, 0x77, 0xf7, 0xcc, 0x0f, 0x12, 0xe9, 0x0c, - 0xef, 0xe8, 0xf7, 0xe0, 0xb7, 0x99, 0xf9, 0x0d, 0x91, 0xfc, 0x33, 0xce, 0xe7, 0x36, 0xcc, 0xff, - 0x06, 0x73, 0x1b, 0xc4, 0x75, 0xfc, 0x15, 0xa8, 0xc9, 0x7d, 0x22, 0x04, 0x2a, 0x27, 0x51, 0x38, - 0x92, 0xfe, 0x41, 0xf6, 0x37, 0x69, 0x43, 0x29, 0x09, 0xc5, 0xc7, 0xa5, 0x24, 0xb4, 0x7f, 0x1f, - 0x1a, 0x1a, 0xa9, 0x91, 0x77, 0xb9, 0xdb, 0x81, 0xa9, 0xce, 0xc2, 0xae, 0xe6, 0xab, 0x58, 0x17, - 0xd0, 0x9d, 0x01, 0xf9, 0x0a, 0xcc, 0x0f, 0xfc, 0x88, 0x62, 0x16, 0x92, 0x1b, 0xd1, 0x73, 0x1a, - 0xc5, 0xd2, 0x65, 0xdb, 0x51, 0x15, 0x0e, 0x87, 0xdb, 0x2e, 0x2c, 0x18, 0x7b, 0xab, 0xa4, 0xdb, - 0x0c, 0xae, 0x9b, 0x8c, 0xb2, 0x99, 0xf9, 0x05, 0xa2, 0x8e, 0x69, 0x1f, 0xc2, 0xdb, 0xec, 0x8e, - 0xa3, 0xf0, 0x18, 0x3b, 0xb1, 0x1c, 0x03, 0x66, 0xff, 0x8f, 0x32, 0x94, 0xb7, 0xc3, 0xb1, 0x7e, - 0xa1, 0xc3, 0xca, 0x5f, 0xe8, 0x10, 0x66, 0x82, 0xab, 0xac, 0x00, 0xa1, 0xcb, 0x19, 0x40, 0xf2, - 0x00, 0xda, 0x4c, 0x54, 0x24, 0x21, 0x33, 0x8b, 0x2e, 0xbc, 0x88, 0x27, 0x1c, 0x94, 0x91, 0xff, - 0x32, 0x35, 0x64, 0x11, 0xca, 0x4a, 0xbb, 0x45, 0x04, 0x56, 0x64, 0x36, 0x39, 0x5e, 0xb7, 0xbb, - 0x14, 0x31, 0x24, 0x51, 0x62, 0x92, 0xd7, 0xfc, 0x9e, 0xcb, 0x23, 0xae, 0xa3, 0x14, 0x55, 0x31, - 0x93, 0x85, 0x49, 0x9c, 0x51, 0x6a, 0x01, 0xa8, 0xb2, 0x1e, 0x58, 0xac, 0x99, 0x81, 0xc5, 0xbb, - 0xd0, 0x48, 0x86, 0xe7, 0xee, 0xd8, 0xbb, 0x1c, 0x86, 0xde, 0x40, 0x70, 0xba, 0x0e, 0x22, 0x8f, - 0x00, 0x46, 0xe3, 0xb1, 0x60, 0x43, 0xf4, 0x5a, 0xa6, 0x54, 0xfd, 0xfc, 0xe0, 0x80, 0x53, 0x9f, - 0xa3, 0xe1, 0x90, 0x2d, 0x68, 0x17, 0x66, 0x0d, 0xdd, 0x96, 0x97, 0xc2, 0xc2, 0xf1, 0x4a, 0x01, - 0xa3, 0x66, 0x3e, 0xea, 0x7d, 0x1b, 0xc8, 0xaf, 0x98, 0xbc, 0xf3, 0x12, 0xea, 0x6a, 0x84, 0x7a, - 0xca, 0x0c, 0xde, 0xfc, 0x6c, 0x98, 0x29, 0x33, 0x78, 0xd1, 0xf3, 0x3d, 0x68, 0xf3, 0xe3, 0x52, - 0x1d, 0x00, 0xfc, 0xb6, 0x5e, 0x06, 0x6a, 0xff, 0xb9, 0x05, 0x55, 0xa4, 0x3c, 0xa6, 0xa5, 0xf2, - 0x3a, 0x75, 0x13, 0x46, 0xc4, 0x9e, 0xb2, 0x60, 0x62, 0x1b, 0xd9, 0x84, 0x25, 0x45, 0x06, 0x7a, - 0x46, 0xe1, 0x5d, 0xa8, 0xab, 0x9e, 0x34, 0x52, 0x4a, 0x81, 0xe4, 0x0e, 0x54, 0xce, 0xc2, 0xb1, - 0x34, 0xe4, 0x21, 0x5d, 0x51, 0x07, 0xe1, 0xe9, 0x78, 0x58, 0x7b, 0x7c, 0x0a, 0xdc, 0x58, 0xca, - 0x82, 0x0b, 0xe6, 0x3a, 0x53, 0x38, 0xd7, 0x17, 0x30, 0xc7, 0xe4, 0x83, 0x16, 0x1b, 0x9e, 0x7e, - 0x98, 0x7e, 0x99, 0x69, 0x80, 0xfd, 0xe1, 0x64, 0x40, 0x75, 0x77, 0x0a, 0xc6, 0x14, 0x05, 0x5c, - 0x1a, 0x12, 0xf6, 0xbf, 0xb4, 0xb8, 0xdc, 0x61, 0xed, 0x92, 0xfb, 0x50, 0x61, 0xe7, 0x5e, 0xc6, - 0xe7, 0xa7, 0x6e, 0xe3, 0x32, 0x3c, 0x07, 0x31, 0xd8, 0x2e, 0x62, 0x38, 0x4c, 0x6f, 0x9d, 0x07, - 0xc3, 0x52, 0x5f, 0x84, 0x9a, 0x59, 0xc6, 0x84, 0xcf, 0x40, 0xc9, 0x8a, 0x76, 0xff, 0xa3, 0x62, - 0x9c, 0xa5, 0x52, 0x49, 0x1c, 0x9c, 0x52, 0xed, 0xde, 0xc7, 0x1f, 0x95, 0xa0, 0x65, 0x8c, 0x89, - 0x71, 0x0f, 0x1e, 0x0d, 0xdc, 0xa3, 0x2c, 0x76, 0x5e, 0x07, 0xe9, 0x9c, 0x57, 0x32, 0x39, 0x4f, - 0x05, 0xc2, 0xcb, 0x7a, 0x20, 0xfc, 0x11, 0xd4, 0xd3, 0x74, 0x52, 0x73, 0x50, 0xac, 0x47, 0x79, - 0x2f, 0x39, 0x45, 0x4a, 0x43, 0xe7, 0x55, 0x3d, 0x74, 0xfe, 0x2d, 0x2d, 0xb4, 0x3a, 0x83, 0xcd, - 0xd8, 0x45, 0xab, 0xfa, 0x9b, 0xb9, 0x8b, 0xf1, 0x04, 0x1a, 0xda, 0xe0, 0xf5, 0x10, 0xaa, 0x65, - 0x84, 0x50, 0x55, 0x06, 0x41, 0x29, 0xcd, 0x20, 0xb0, 0x7f, 0x5a, 0x82, 0x16, 0xe3, 0x35, 0x3f, - 0x38, 0x3d, 0x08, 0x87, 0x7e, 0xff, 0x12, 0x69, 0x5c, 0xb2, 0x95, 0x50, 0xc2, 0x24, 0xcf, 0x99, - 0x60, 0x26, 0x13, 0x55, 0xda, 0x14, 0x17, 0xe0, 0xaa, 0xcc, 0x24, 0x3c, 0x93, 0x8f, 0xc7, 0x5e, - 0x4c, 0xb5, 0x64, 0x57, 0xc7, 0x04, 0x32, 0x39, 0xcc, 0x00, 0x98, 0x0f, 0x32, 0xf2, 0x87, 0x43, - 0x9f, 0xe3, 0x72, 0x1f, 0x45, 0x51, 0x15, 0xeb, 0x73, 0xe0, 0xc7, 0xde, 0x71, 0x7a, 0x61, 0x49, - 0x95, 0x31, 0x5a, 0xe4, 0xbd, 0xd6, 0xa2, 0x45, 0x3c, 0x81, 0xcc, 0x04, 0x66, 0xa9, 0x6a, 0x36, - 0x47, 0x55, 0xf6, 0xbf, 0x2d, 0x41, 0x43, 0xa3, 0x51, 0x26, 0x5b, 0x0a, 0x0f, 0x61, 0x0d, 0x2a, - 0xae, 0x28, 0x06, 0x86, 0xd7, 0x4b, 0x83, 0x90, 0x7b, 0x66, 0xaf, 0x18, 0x65, 0x46, 0xe9, 0x63, - 0xd0, 0xf3, 0x2d, 0xa8, 0x33, 0x3e, 0xfc, 0x10, 0x5d, 0x6c, 0x22, 0xb1, 0x5c, 0x01, 0x64, 0xed, - 0x2a, 0xd6, 0x56, 0xd3, 0x5a, 0x04, 0x5c, 0x79, 0x69, 0xf1, 0x31, 0x34, 0x45, 0x33, 0xb8, 0xc7, - 0x38, 0xe9, 0x54, 0x12, 0x18, 0xfb, 0xef, 0x18, 0x98, 0xf2, 0xcb, 0x55, 0xf9, 0x65, 0xed, 0x4d, - 0x5f, 0x4a, 0x4c, 0xfb, 0x99, 0xba, 0x0f, 0xfa, 0x2c, 0xf2, 0xc6, 0x67, 0x52, 0xba, 0x3d, 0x82, - 0x05, 0x29, 0xc4, 0x26, 0x81, 0x17, 0x04, 0xe1, 0x24, 0xe8, 0x53, 0x99, 0x6c, 0x50, 0x54, 0x65, - 0x0f, 0x54, 0x6a, 0x1a, 0x36, 0x44, 0x1e, 0x40, 0x95, 0xab, 0xf1, 0x5c, 0x57, 0x29, 0x96, 0x67, - 0x1c, 0x85, 0xdc, 0x87, 0x2a, 0xd7, 0xe6, 0x4b, 0x53, 0x25, 0x10, 0x47, 0xb0, 0x57, 0x60, 0x0e, - 0x35, 0x52, 0x4d, 0x10, 0xdf, 0x2c, 0xd2, 0x61, 0x66, 0xfa, 0x3c, 0x9c, 0xb1, 0x08, 0x64, 0x8f, - 0xf3, 0x95, 0x7e, 0xaf, 0xe7, 0xcf, 0xcb, 0xd0, 0xd0, 0xc0, 0x4c, 0x58, 0xe2, 0x25, 0x0f, 0x77, - 0xe0, 0x7b, 0x23, 0x2a, 0x83, 0x1b, 0x2d, 0x27, 0x03, 0x65, 0x78, 0xde, 0xf9, 0xa9, 0x1b, 0x4e, - 0x12, 0x77, 0x40, 0x4f, 0x23, 0x4a, 0x85, 0x72, 0x95, 0x81, 0x32, 0x3c, 0x46, 0xcd, 0x1a, 0x1e, - 0xbf, 0xaf, 0x90, 0x81, 0xca, 0xfb, 0x33, 0x7c, 0x9d, 0x2a, 0xe9, 0xfd, 0x19, 0xbe, 0x2a, 0x59, - 0x31, 0x5f, 0x2d, 0x10, 0xf3, 0x1f, 0xc1, 0x12, 0x17, 0xe8, 0x42, 0x7a, 0xb8, 0x19, 0xe2, 0x9a, - 0x52, 0x4b, 0x1e, 0x40, 0x87, 0x8d, 0x59, 0xb2, 0x46, 0xec, 0xff, 0x98, 0xf3, 0x98, 0xe5, 0xe4, - 0xe0, 0x0c, 0x17, 0x63, 0xaf, 0x3a, 0x2e, 0xbf, 0x28, 0x9b, 0x83, 0x23, 0xae, 0xf7, 0xda, 0xc4, - 0xad, 0x0b, 0xdc, 0x0c, 0x9c, 0x3c, 0x86, 0xe5, 0x11, 0x1d, 0xf8, 0x9e, 0xd9, 0x84, 0x9b, 0x6a, - 0x1c, 0xd3, 0xaa, 0x59, 0x2f, 0x6c, 0x15, 0x7e, 0x1c, 0x8e, 0x8e, 0x7d, 0x7e, 0xca, 0xf2, 0x28, - 0x71, 0xc5, 0xc9, 0xc1, 0xed, 0x16, 0x34, 0x0e, 0x93, 0x70, 0x2c, 0xb7, 0xbe, 0x0d, 0x4d, 0x5e, - 0x14, 0xe9, 0x25, 0x37, 0xe1, 0x06, 0xd2, 0xeb, 0x51, 0x38, 0x0e, 0x87, 0xe1, 0xe9, 0xa5, 0xe1, - 0x9e, 0xfa, 0xf7, 0x16, 0x2c, 0x18, 0xb5, 0xa9, 0x7f, 0x0a, 0x7d, 0xe9, 0x32, 0x27, 0x80, 0x93, - 0xf8, 0xbc, 0x76, 0x46, 0x71, 0x44, 0x7e, 0x0f, 0xe0, 0x85, 0x48, 0x13, 0x58, 0x4b, 0x13, 0x5d, - 0xe5, 0x87, 0x9c, 0xde, 0xbb, 0x79, 0x7a, 0x17, 0xdf, 0xcb, 0x14, 0x58, 0xd9, 0xc4, 0xef, 0x88, - 0x6b, 0xcd, 0x03, 0x31, 0xe9, 0xb2, 0x79, 0x63, 0x53, 0x77, 0x67, 0xca, 0x11, 0xf4, 0x15, 0x30, - 0xb6, 0x7f, 0x6e, 0x01, 0xa4, 0xa3, 0xc3, 0x3b, 0xa3, 0xea, 0x9c, 0xe5, 0x6f, 0xc9, 0x68, 0x67, - 0xea, 0xbb, 0xd0, 0x54, 0xf7, 0xd6, 0xd2, 0xa3, 0xbb, 0x21, 0x61, 0x4c, 0xd5, 0x79, 0x1f, 0xe6, - 0x4e, 0x87, 0xe1, 0x31, 0xaa, 0x54, 0xe2, 0x9c, 0xe5, 0x49, 0x36, 0x6d, 0x0e, 0x96, 0xa7, 0x67, - 0x7a, 0xce, 0x57, 0x0a, 0x2f, 0xbc, 0xe9, 0xa7, 0x36, 0x3b, 0xeb, 0xe6, 0x73, 0x2b, 0x71, 0x25, - 0x97, 0xff, 0x52, 0x61, 0xdf, 0xab, 0xa2, 0x1b, 0x4f, 0xa0, 0x1d, 0x71, 0x99, 0x29, 0x05, 0x6a, - 0xe5, 0x0a, 0x81, 0xda, 0x8a, 0x8c, 0x93, 0xf9, 0xcb, 0xd0, 0xf1, 0x06, 0xe7, 0x34, 0x4a, 0x7c, - 0xf4, 0xf6, 0xa2, 0x4e, 0xc7, 0x27, 0x38, 0xa7, 0xc1, 0x51, 0x75, 0x7a, 0x1f, 0xe6, 0x44, 0xca, - 0x93, 0xc2, 0x14, 0xaf, 0x2a, 0xa4, 0x60, 0x86, 0x68, 0xff, 0x13, 0x79, 0x6d, 0xc8, 0xdc, 0xdd, - 0xab, 0x57, 0x45, 0x9f, 0x61, 0x29, 0x33, 0xc3, 0x2f, 0x89, 0x4b, 0x11, 0x03, 0xe9, 0x56, 0x2e, - 0x6b, 0x17, 0xe4, 0x07, 0xe2, 0xda, 0x95, 0xb9, 0xac, 0x95, 0xb7, 0x59, 0x56, 0xfb, 0x3f, 0x5b, - 0x30, 0xbb, 0x1d, 0x8e, 0x99, 0x69, 0x8f, 0x3a, 0x0e, 0x63, 0x13, 0x95, 0x6f, 0x28, 0x8b, 0x6f, - 0x48, 0x24, 0x28, 0xd4, 0x4a, 0x5a, 0x59, 0xad, 0xe4, 0xdb, 0x70, 0x13, 0x03, 0x1b, 0x51, 0x38, - 0x0e, 0x23, 0xc6, 0xae, 0xde, 0x90, 0xab, 0x20, 0x61, 0x90, 0x9c, 0x49, 0x71, 0x7a, 0x15, 0x0a, - 0xfa, 0x01, 0x87, 0xc9, 0xb9, 0xcb, 0xcd, 0x4d, 0xa1, 0x45, 0x71, 0x29, 0x9b, 0xaf, 0xb0, 0xbf, - 0x09, 0x75, 0xe5, 0xc0, 0x20, 0x1f, 0x40, 0xfd, 0x2c, 0x1c, 0x0b, 0x2f, 0x87, 0x65, 0x24, 0x5d, - 0x88, 0xd9, 0x3b, 0x29, 0x82, 0xfd, 0xbf, 0x66, 0x61, 0x76, 0x27, 0x38, 0x0f, 0xfd, 0x3e, 0x5e, - 0x3f, 0x1a, 0xd1, 0x51, 0x28, 0x33, 0x30, 0xd9, 0xdf, 0xf8, 0x38, 0x4a, 0xfa, 0x46, 0x02, 0x67, - 0x21, 0x0d, 0xc2, 0x0c, 0xe4, 0x48, 0x7f, 0xe3, 0x40, 0x94, 0x52, 0xab, 0xaf, 0xaa, 0xe5, 0xb0, - 0xb2, 0xd6, 0x78, 0xee, 0x3d, 0xae, 0x1d, 0xcf, 0x9c, 0xd1, 0x20, 0x6c, 0xf1, 0x45, 0x82, 0x03, - 0xbf, 0x28, 0xce, 0x6f, 0x32, 0x0a, 0x10, 0x1a, 0xfd, 0x11, 0xe5, 0xa1, 0x29, 0xa5, 0x7a, 0x31, - 0xa3, 0x5f, 0x07, 0x32, 0xf5, 0x8c, 0x7f, 0xc0, 0x71, 0xf8, 0x71, 0xa0, 0x83, 0xf0, 0x36, 0x4a, - 0xe6, 0xc5, 0x10, 0xfe, 0xea, 0x4b, 0x16, 0xcc, 0x2f, 0x9a, 0x29, 0xa1, 0xcb, 0xe7, 0x09, 0xfc, - 0x9d, 0x88, 0x2c, 0x5c, 0x73, 0x15, 0xf0, 0xdc, 0x30, 0xe9, 0x2a, 0x60, 0x24, 0xe3, 0x0d, 0x87, - 0xc7, 0x5e, 0xff, 0x15, 0xb7, 0x6c, 0x9b, 0x3c, 0xa2, 0x69, 0x00, 0xf1, 0x36, 0x7f, 0xba, 0xaf, - 0x78, 0x11, 0xa8, 0xe2, 0xe8, 0x20, 0xb2, 0x6a, 0xfa, 0xaf, 0xda, 0x53, 0xfc, 0x57, 0x3a, 0x92, - 0x7e, 0x31, 0x6a, 0x2e, 0x97, 0xad, 0xe5, 0x0d, 0x06, 0xe2, 0xc2, 0x4c, 0x87, 0xbf, 0x93, 0xa0, - 0x00, 0xe8, 0xa8, 0xe1, 0x0b, 0xc6, 0x11, 0xe6, 0x11, 0xc1, 0x80, 0x91, 0x3b, 0xdc, 0x0f, 0x3b, - 0xf6, 0xfc, 0x01, 0x5e, 0x4c, 0xe5, 0xb6, 0xb0, 0x82, 0xb1, 0x36, 0xe4, 0xdf, 0x78, 0x70, 0x2e, - 0xe0, 0xaa, 0x18, 0x30, 0xb6, 0x36, 0xaa, 0x3c, 0x4a, 0xd3, 0xbb, 0x4c, 0x20, 0xf9, 0x10, 0x2f, - 0x22, 0x24, 0x14, 0x73, 0xb8, 0xda, 0xab, 0x37, 0xc5, 0x9c, 0x05, 0xd9, 0xca, 0xff, 0xf1, 0xe2, - 0x85, 0xc3, 0x31, 0x99, 0xda, 0xc6, 0x63, 0x41, 0x4b, 0x86, 0xda, 0x26, 0x50, 0x31, 0x16, 0xc4, - 0x11, 0xc8, 0x63, 0xcd, 0x12, 0xeb, 0x22, 0xf2, 0xad, 0x4c, 0xfb, 0x53, 0x6c, 0x30, 0x46, 0xcc, - 0x7e, 0xcc, 0xce, 0x9f, 0x98, 0x06, 0x03, 0xcc, 0xe6, 0xaa, 0x39, 0x1a, 0xe4, 0xd7, 0x6b, 0xa3, - 0xad, 0x41, 0x53, 0x9f, 0x27, 0xa9, 0x41, 0x65, 0xff, 0x60, 0x6b, 0xaf, 0x73, 0x8d, 0x34, 0x60, - 0xf6, 0x70, 0xeb, 0xe8, 0x68, 0x77, 0x6b, 0xb3, 0x63, 0x91, 0x26, 0xd4, 0x54, 0x1a, 0x4a, 0x89, - 0x95, 0xd6, 0x36, 0x36, 0xb6, 0x0e, 0x8e, 0xb6, 0x36, 0x3b, 0xe5, 0x4f, 0x2a, 0xb5, 0x52, 0xa7, - 0x8c, 0x0a, 0xa6, 0xb6, 0x0c, 0x6f, 0xf0, 0xb3, 0xdd, 0x01, 0x40, 0xc3, 0x27, 0xbd, 0x58, 0x55, - 0x71, 0x34, 0x08, 0x13, 0xe4, 0xca, 0x3f, 0x51, 0xe6, 0x6f, 0x5b, 0xc8, 0x32, 0x6e, 0x2e, 0x3e, - 0x22, 0xa1, 0xc7, 0x07, 0xab, 0x8e, 0x09, 0x64, 0x84, 0x2f, 0x00, 0x98, 0xe0, 0xc0, 0xc5, 0x85, - 0x0e, 0x62, 0x84, 0x14, 0xd1, 0x38, 0x1c, 0x9e, 0x53, 0x8e, 0xc2, 0xd5, 0x47, 0x03, 0xc6, 0xfa, - 0x12, 0x12, 0x51, 0xcb, 0xaa, 0xaa, 0x3a, 0x26, 0x90, 0x7c, 0x55, 0x12, 0x52, 0x0d, 0x09, 0x69, - 0x39, 0x4f, 0x15, 0x06, 0x11, 0x3d, 0xcf, 0x39, 0xca, 0xea, 0x48, 0x20, 0xbf, 0x95, 0xff, 0xee, - 0x2d, 0x1c, 0x66, 0x64, 0x05, 0xc8, 0x68, 0x3c, 0x76, 0x0b, 0x3c, 0x58, 0x15, 0xa7, 0xa0, 0xe6, - 0xd7, 0xe0, 0x60, 0x4b, 0x80, 0xac, 0x0d, 0x06, 0x62, 0x98, 0xfa, 0x53, 0x1f, 0x91, 0xfe, 0xb6, - 0x8c, 0x14, 0xd9, 0x05, 0x62, 0xb1, 0x54, 0x2c, 0x16, 0xaf, 0x14, 0x1e, 0xf6, 0x0e, 0x34, 0x0e, - 0xb4, 0xd7, 0x6a, 0x6c, 0x76, 0x82, 0xc8, 0x77, 0x6a, 0xf8, 0xd9, 0xc2, 0x1d, 0x6b, 0x29, 0x54, - 0x1b, 0x52, 0x49, 0x1f, 0x92, 0xfd, 0x8f, 0x2c, 0xfe, 0x00, 0x80, 0x9a, 0x02, 0xef, 0xdf, 0x86, - 0xa6, 0x0a, 0x2e, 0xa5, 0xd9, 0x90, 0x06, 0x8c, 0xe1, 0xe0, 0x70, 0xdc, 0xf0, 0xe4, 0x24, 0xa6, - 0x32, 0x95, 0xc7, 0x80, 0x49, 0x65, 0x9d, 0xa9, 0xff, 0x3e, 0xef, 0x21, 0x16, 0x29, 0x3d, 0x39, - 0x38, 0xa3, 0x74, 0xe1, 0x1b, 0x97, 0x49, 0x4c, 0xaa, 0x6c, 0xff, 0x81, 0x48, 0xda, 0xcc, 0xae, - 0xf4, 0x03, 0xa8, 0xa9, 0x76, 0xcd, 0x93, 0x58, 0x62, 0xaa, 0x7a, 0x76, 0xe2, 0xa3, 0x21, 0x6f, - 0x0c, 0x9a, 0x33, 0x5c, 0xbe, 0x82, 0xd1, 0xd2, 0x89, 0x1f, 0x65, 0xd1, 0x39, 0x07, 0x16, 0xd4, - 0xd8, 0x2f, 0x61, 0x41, 0x8a, 0x0f, 0xcd, 0x8a, 0x30, 0x37, 0xd2, 0x7a, 0xd3, 0x29, 0x50, 0xca, - 0x9f, 0x02, 0xf6, 0xbf, 0xa9, 0xc0, 0xac, 0x7c, 0x0a, 0xca, 0x2e, 0x78, 0xba, 0xa8, 0x6e, 0xbe, - 0x7a, 0x44, 0xba, 0xc6, 0xdb, 0x16, 0x48, 0x08, 0x42, 0x37, 0xb8, 0x9f, 0x3d, 0xdd, 0x53, 0x07, - 0x6b, 0xe6, 0x84, 0x5f, 0x82, 0xca, 0xd8, 0x4b, 0xce, 0xd0, 0xff, 0xc6, 0x69, 0x09, 0xcb, 0xd2, - 0x85, 0x5f, 0x35, 0x5d, 0xf8, 0x45, 0x6f, 0x3d, 0x71, 0x55, 0x36, 0xff, 0xd6, 0xd3, 0x2d, 0xa8, - 0x73, 0x6d, 0x24, 0xf5, 0xd2, 0xa7, 0x80, 0x8c, 0xf6, 0x52, 0xcb, 0x69, 0x2f, 0x6f, 0xaf, 0x57, - 0x7c, 0x1d, 0x66, 0x78, 0xbe, 0xb3, 0x48, 0xd9, 0x92, 0x47, 0x8e, 0x58, 0x49, 0xf9, 0x3f, 0xbf, - 0xb9, 0xeb, 0x08, 0x5c, 0xfd, 0xc5, 0x94, 0x86, 0xf9, 0x62, 0x8a, 0x1e, 0x5c, 0x68, 0x66, 0x82, - 0x0b, 0x0f, 0xa0, 0xa3, 0x96, 0x0f, 0x1d, 0x70, 0x41, 0x2c, 0x52, 0x54, 0x72, 0xf0, 0xf4, 0xd8, - 0x6c, 0x1b, 0xc7, 0x26, 0x93, 0x70, 0x6b, 0x49, 0x42, 0x47, 0xe3, 0x44, 0x1c, 0x9b, 0xf6, 0x53, - 0x68, 0x19, 0x83, 0x34, 0xd3, 0x1a, 0x5b, 0x50, 0xdf, 0xd9, 0x73, 0x9f, 0xee, 0xee, 0x3c, 0xdb, - 0x3e, 0xea, 0x58, 0xac, 0x78, 0xf8, 0x62, 0x63, 0x63, 0x6b, 0x6b, 0x13, 0x8f, 0x25, 0x80, 0x99, - 0xa7, 0x6b, 0x3b, 0xec, 0x88, 0x2a, 0xdb, 0xff, 0xdb, 0x82, 0x86, 0xd6, 0x3c, 0xf9, 0x86, 0x5a, - 0x19, 0xfe, 0xa8, 0xc6, 0xed, 0xfc, 0x10, 0x56, 0xa4, 0xa0, 0xd6, 0x96, 0x46, 0x3d, 0x6f, 0x55, - 0x9a, 0xfa, 0xbc, 0x15, 0xdb, 0x1e, 0x8f, 0xb7, 0xa0, 0xd6, 0x81, 0x5b, 0x57, 0x59, 0x30, 0xbf, - 0xae, 0x96, 0x9e, 0x2e, 0x0c, 0x93, 0x7b, 0x14, 0xb3, 0x60, 0xfb, 0x23, 0x80, 0x74, 0x34, 0xe6, - 0xb4, 0xaf, 0x99, 0xd3, 0xb6, 0xb4, 0x69, 0x97, 0xec, 0x4d, 0x2e, 0x30, 0xc4, 0x12, 0xaa, 0x30, - 0xf8, 0x57, 0x81, 0x48, 0x07, 0x16, 0x5e, 0x0b, 0x1d, 0x0f, 0x69, 0x22, 0x53, 0x3b, 0xe7, 0x45, - 0xcd, 0x8e, 0xaa, 0x90, 0x69, 0xd7, 0x69, 0x2b, 0xa9, 0xdc, 0x11, 0x14, 0x97, 0x95, 0x3b, 0x02, - 0xd5, 0x51, 0xf5, 0x76, 0x0f, 0xba, 0x9b, 0x94, 0xb5, 0xb6, 0x36, 0x1c, 0x66, 0x86, 0x63, 0xdf, - 0x84, 0x1b, 0x05, 0x75, 0xc2, 0x3d, 0xf1, 0x1d, 0xb8, 0xbe, 0xc6, 0xb3, 0x38, 0x7f, 0x5d, 0x09, - 0x23, 0x76, 0x17, 0x96, 0xb2, 0x4d, 0x8a, 0xce, 0x9e, 0xc2, 0xfc, 0x26, 0x3d, 0x9e, 0x9c, 0xee, - 0xd2, 0xf3, 0xb4, 0x23, 0x02, 0x95, 0xf8, 0x2c, 0xbc, 0x10, 0xeb, 0x83, 0x7f, 0x93, 0xdb, 0x00, - 0x43, 0x86, 0xe3, 0xc6, 0x63, 0xda, 0x97, 0x8f, 0x96, 0x20, 0xe4, 0x70, 0x4c, 0xfb, 0xf6, 0x47, - 0x40, 0xf4, 0x76, 0xc4, 0x7a, 0x31, 0x93, 0x61, 0x72, 0xec, 0xc6, 0x97, 0x71, 0x42, 0x47, 0xf2, - 0x35, 0x16, 0x1d, 0x64, 0xbf, 0x0f, 0xcd, 0x03, 0xef, 0xd2, 0xa1, 0x9f, 0x89, 0xe7, 0xd4, 0x96, - 0x61, 0x76, 0xec, 0x5d, 0x32, 0x7e, 0x56, 0x21, 0x16, 0xac, 0xb6, 0xff, 0xb8, 0x02, 0x33, 0x1c, - 0x93, 0xb5, 0x3a, 0xa0, 0x71, 0xe2, 0x07, 0xc8, 0x63, 0xb2, 0x55, 0x0d, 0x94, 0x13, 0x98, 0xa5, - 0x02, 0x81, 0x29, 0x5c, 0x6d, 0xf2, 0xf1, 0x07, 0x41, 0xb2, 0x06, 0x8c, 0x89, 0xad, 0x34, 0xfd, - 0x8c, 0x53, 0x6a, 0x0a, 0xc8, 0xc4, 0x30, 0x53, 0xc3, 0x84, 0x8f, 0x4f, 0x9e, 0x05, 0x42, 0x26, - 0xea, 0xa0, 0x42, 0xf3, 0x67, 0x56, 0xe6, 0xd9, 0x64, 0xcc, 0x9f, 0x9c, 0x99, 0x53, 0x7b, 0x0b, - 0x33, 0x87, 0xfb, 0xdf, 0xae, 0x32, 0x73, 0xe0, 0x6d, 0xcc, 0x9c, 0xb7, 0x89, 0x1d, 0xf6, 0xa0, - 0x86, 0x67, 0xba, 0x26, 0x22, 0x65, 0x99, 0xfc, 0xb6, 0x66, 0x03, 0xf0, 0x7b, 0x0c, 0x37, 0x53, - 0x7e, 0x71, 0xe8, 0x67, 0xbf, 0x99, 0x30, 0xcc, 0x0f, 0x60, 0x56, 0x40, 0x19, 0x65, 0x07, 0xde, - 0x48, 0x3e, 0xba, 0x83, 0x7f, 0xb3, 0xa5, 0xc3, 0xb7, 0x3f, 0x3e, 0x9b, 0xf8, 0x11, 0x1d, 0xc8, - 0x5c, 0x6d, 0x0d, 0x84, 0x97, 0xcb, 0x63, 0xf7, 0x55, 0x10, 0x5e, 0x04, 0x22, 0x5b, 0x5b, 0x95, - 0x6d, 0x02, 0x1d, 0x7c, 0x7c, 0x6b, 0x1c, 0x46, 0xf2, 0x1d, 0x25, 0xfb, 0x8f, 0x2c, 0xe8, 0x08, - 0x46, 0x53, 0x75, 0xba, 0xdf, 0xa6, 0x9a, 0xf3, 0xdb, 0xbc, 0x6b, 0xb8, 0x5d, 0x0a, 0x1f, 0x62, - 0xb8, 0x07, 0x2d, 0x74, 0x84, 0xa8, 0xf3, 0x48, 0x44, 0xe6, 0x0d, 0x20, 0x9b, 0x8c, 0xbc, 0xfa, - 0x39, 0xf2, 0x87, 0x82, 0xa8, 0x75, 0x90, 0x3c, 0xd2, 0x22, 0x4f, 0x64, 0x80, 0x59, 0x8e, 0x2a, - 0xdb, 0xbf, 0xb0, 0x60, 0x5e, 0x9b, 0x8d, 0xe0, 0xe2, 0x27, 0xd0, 0x54, 0x0f, 0xe0, 0x51, 0xa5, - 0x71, 0x2d, 0x9b, 0x62, 0x27, 0xfd, 0xcc, 0x40, 0x46, 0x66, 0xf0, 0x2e, 0x71, 0x80, 0xf1, 0x64, - 0x24, 0x54, 0x1d, 0x1d, 0xc4, 0x88, 0xec, 0x82, 0xd2, 0x57, 0x0a, 0x85, 0x2b, 0x5b, 0x06, 0x0c, - 0x03, 0x48, 0x61, 0x90, 0x9c, 0x29, 0xa4, 0x8a, 0x08, 0x20, 0xe9, 0x40, 0xfb, 0xbf, 0x96, 0x60, - 0x81, 0x7b, 0xe4, 0x84, 0x27, 0x54, 0xbd, 0x41, 0x34, 0xc3, 0x9d, 0x93, 0x5c, 0xa2, 0x6d, 0x5f, - 0x73, 0x44, 0x99, 0x7c, 0xe3, 0x2d, 0xbd, 0x88, 0x2a, 0xd5, 0x6c, 0xca, 0x5e, 0x94, 0x8b, 0xf6, - 0xe2, 0x8a, 0x95, 0x2e, 0x8a, 0xe5, 0x55, 0x8b, 0x63, 0x79, 0x6f, 0x17, 0x3b, 0xcb, 0xe5, 0x63, - 0xcd, 0x0a, 0x2c, 0x23, 0x1f, 0x6b, 0x15, 0x96, 0x0d, 0x00, 0x0a, 0x73, 0xff, 0xc4, 0xa7, 0x32, - 0x39, 0x7e, 0x3e, 0xa6, 0x89, 0x6b, 0xa0, 0xac, 0xcf, 0x42, 0x35, 0xee, 0x87, 0x63, 0x6a, 0x2f, - 0xc1, 0xa2, 0xb9, 0xb8, 0xe2, 0x08, 0xf9, 0xb9, 0x05, 0xdd, 0xa7, 0xfc, 0x46, 0x86, 0x1f, 0x9c, - 0x6e, 0xfb, 0x71, 0x12, 0x46, 0xea, 0xa9, 0xb8, 0x3b, 0x00, 0x71, 0xe2, 0x45, 0xc2, 0x08, 0xe5, - 0x9a, 0xb0, 0x06, 0x61, 0x6b, 0x44, 0x83, 0x01, 0xaf, 0xe5, 0xb4, 0xa1, 0xca, 0x39, 0x4b, 0x43, - 0xf8, 0x2b, 0x0d, 0x7d, 0xfd, 0x3d, 0x9e, 0x26, 0xca, 0x16, 0x83, 0x9e, 0xe3, 0xb9, 0xcc, 0x9d, - 0x80, 0x19, 0xa8, 0xfd, 0x07, 0x25, 0x98, 0x4b, 0x07, 0xc9, 0xd3, 0xce, 0x0d, 0xe9, 0x2e, 0x94, - 0xf4, 0x54, 0xba, 0x8b, 0xd8, 0xa2, 0xeb, 0x33, 0xad, 0x5d, 0x73, 0x59, 0x6a, 0x50, 0x72, 0x0f, - 0x1a, 0xb2, 0x14, 0x4e, 0x12, 0xed, 0xcd, 0x26, 0x1d, 0xcc, 0xf3, 0x4f, 0x98, 0xdd, 0x20, 0x6c, - 0x20, 0x51, 0xc2, 0xc7, 0x12, 0x46, 0x09, 0x7e, 0xc9, 0xf7, 0x54, 0x16, 0x99, 0xb4, 0x63, 0x0a, - 0x37, 0xdf, 0x43, 0x54, 0xb6, 0x75, 0x45, 0xb4, 0xa6, 0xde, 0xba, 0x54, 0x3c, 0xcf, 0x5b, 0x4c, - 0x33, 0xf1, 0x2a, 0x8e, 0x0e, 0x92, 0x2e, 0xa3, 0x70, 0x62, 0xd8, 0xc6, 0x06, 0xcc, 0xfe, 0x5b, - 0x16, 0xdc, 0x28, 0xd8, 0x46, 0x21, 0x03, 0x36, 0x61, 0xfe, 0x44, 0x55, 0xca, 0xa5, 0xe6, 0x82, - 0x60, 0x49, 0x4a, 0x5e, 0x73, 0x79, 0x9d, 0xfc, 0x07, 0xca, 0x16, 0xe3, 0x9b, 0x67, 0x24, 0x5e, - 0xe6, 0x2b, 0xec, 0x03, 0xe8, 0x6d, 0xbd, 0x66, 0x22, 0x65, 0x43, 0x7f, 0xf0, 0x5c, 0x52, 0xd6, - 0x6a, 0x4e, 0x64, 0xbe, 0xd9, 0x53, 0x7d, 0xc2, 0xd3, 0xc9, 0x54, 0x5b, 0xe4, 0x6b, 0x6f, 0xdb, - 0x88, 0xce, 0xfd, 0x77, 0xc5, 0xae, 0xf3, 0x17, 0xdb, 0x65, 0xfa, 0xa7, 0x06, 0xb2, 0xcf, 0x61, - 0xee, 0xf9, 0x64, 0x98, 0xf8, 0xe9, 0xeb, 0xed, 0xe4, 0x1b, 0xe2, 0x23, 0x6c, 0x42, 0x2e, 0x5d, - 0x61, 0x57, 0x3a, 0x1e, 0x5b, 0xb1, 0x11, 0x6b, 0xc9, 0xcd, 0xf7, 0x98, 0xaf, 0xb0, 0x6f, 0xc0, - 0x72, 0xda, 0x25, 0x5f, 0x3b, 0x79, 0x26, 0xfd, 0xa1, 0xc5, 0xaf, 0x5d, 0x9b, 0x8f, 0xc9, 0x93, - 0x67, 0xb0, 0x10, 0xfb, 0xc1, 0xe9, 0x90, 0xea, 0xed, 0xc4, 0x62, 0x25, 0xae, 0x9b, 0xc3, 0x13, - 0x0f, 0xce, 0x3b, 0x45, 0x5f, 0x30, 0x02, 0x29, 0x1e, 0x68, 0x4a, 0x20, 0x99, 0x25, 0x29, 0x9a, - 0xc0, 0x27, 0xd0, 0x36, 0x3b, 0x23, 0x8f, 0x45, 0x5e, 0x65, 0x3a, 0xb2, 0x72, 0x26, 0x3d, 0x2e, - 0xa5, 0x0c, 0x03, 0xd3, 0xfe, 0xa9, 0x05, 0x5d, 0x87, 0x32, 0x32, 0xa6, 0x5a, 0xa7, 0x82, 0x7a, - 0x9e, 0xe4, 0x9a, 0x9d, 0x3e, 0x61, 0x95, 0xaf, 0x29, 0xe7, 0xba, 0x32, 0x75, 0x53, 0xb6, 0xaf, - 0x15, 0xcc, 0x6a, 0xbd, 0x06, 0x33, 0x62, 0x7e, 0xcb, 0x70, 0x5d, 0x0c, 0x49, 0x0e, 0x27, 0x8d, - 0x49, 0x1a, 0x9d, 0x1a, 0x31, 0xc9, 0x1e, 0x74, 0xf9, 0x8b, 0x80, 0xfa, 0x3c, 0xc4, 0x87, 0x9b, - 0x40, 0x9e, 0x7b, 0x7d, 0x2f, 0x0a, 0xc3, 0xe0, 0x80, 0x46, 0xe2, 0x06, 0x2b, 0xaa, 0xa6, 0x18, - 0xb2, 0x93, 0x5a, 0x34, 0x2f, 0xc9, 0x47, 0xec, 0xc2, 0x40, 0x3e, 0x16, 0xc8, 0x4b, 0xb6, 0x03, - 0x0b, 0xeb, 0xde, 0x2b, 0x2a, 0x5b, 0x4a, 0x57, 0xa9, 0x31, 0x56, 0x8d, 0xca, 0xb5, 0x97, 0x09, - 0xd9, 0xf9, 0x6e, 0x1d, 0x1d, 0xdb, 0x5e, 0x85, 0x45, 0xb3, 0x4d, 0x21, 0x4a, 0x7a, 0x50, 0x1b, - 0x09, 0x98, 0x18, 0x9d, 0x2a, 0x3f, 0xf8, 0x1c, 0x1a, 0xda, 0x2b, 0x8f, 0x64, 0x19, 0x16, 0x5e, - 0xee, 0x1c, 0xed, 0x6d, 0x1d, 0x1e, 0xba, 0x07, 0x2f, 0xd6, 0x3f, 0xdd, 0xfa, 0x9e, 0xbb, 0xbd, - 0x76, 0xb8, 0xdd, 0xb9, 0x46, 0x96, 0x80, 0xec, 0x6d, 0x1d, 0x1e, 0x6d, 0x6d, 0x1a, 0x70, 0x8b, - 0xdc, 0x81, 0xde, 0x8b, 0xbd, 0x17, 0x87, 0x5b, 0x9b, 0x6e, 0xd1, 0x77, 0x25, 0x72, 0x1b, 0x6e, - 0x88, 0xfa, 0x82, 0xcf, 0xcb, 0x0f, 0x9e, 0x40, 0x27, 0xeb, 0xb3, 0x34, 0x7c, 0xbd, 0x57, 0x39, - 0x85, 0x1f, 0xfc, 0xe3, 0x32, 0x40, 0x7a, 0x73, 0x95, 0x74, 0x61, 0x71, 0x73, 0xed, 0x68, 0x6d, - 0x77, 0x9f, 0x0d, 0xc2, 0xd9, 0x3f, 0xda, 0xda, 0x38, 0x72, 0x9d, 0xad, 0xef, 0x74, 0xae, 0x15, - 0xd6, 0xec, 0x1f, 0x30, 0x7b, 0x7e, 0x19, 0x16, 0x76, 0xf6, 0x76, 0x8e, 0x76, 0xd6, 0x76, 0x5d, - 0x67, 0xff, 0xc5, 0xce, 0xde, 0x33, 0xfe, 0x28, 0x4b, 0x99, 0xbc, 0x03, 0x37, 0x5f, 0x1c, 0x3c, - 0x75, 0xf6, 0xf7, 0x8e, 0xdc, 0xc3, 0xed, 0x17, 0x47, 0x9b, 0xf8, 0xa4, 0xcb, 0x86, 0xb3, 0x73, - 0xc0, 0xdb, 0xac, 0x5c, 0x85, 0xc0, 0x9a, 0xae, 0xb2, 0x15, 0x7b, 0xb6, 0x7f, 0x78, 0xb8, 0x73, - 0xe0, 0x7e, 0xe7, 0xc5, 0x96, 0xb3, 0xb3, 0x75, 0x88, 0x1f, 0xce, 0x14, 0xc0, 0x19, 0xfe, 0x2c, - 0x99, 0x87, 0xd6, 0xd1, 0xee, 0x77, 0xdd, 0xfd, 0xbd, 0x9d, 0xfd, 0x3d, 0x44, 0xad, 0x99, 0x20, - 0x86, 0x55, 0x27, 0x3d, 0x58, 0xda, 0xfa, 0xbd, 0x23, 0xb7, 0xa0, 0x65, 0x98, 0x52, 0xc7, 0xbe, - 0x6b, 0x90, 0x1b, 0x70, 0xfd, 0xf0, 0x68, 0xed, 0x68, 0x67, 0xc3, 0x15, 0xcf, 0x41, 0xb1, 0x4d, - 0x60, 0x9f, 0x35, 0x8b, 0xab, 0xd8, 0x57, 0x2d, 0xb2, 0x08, 0x9d, 0x83, 0xb5, 0xef, 0x3d, 0xdf, - 0xda, 0x3b, 0x72, 0xd7, 0x36, 0x37, 0x1d, 0xfc, 0xa0, 0x9d, 0x83, 0x32, 0xdc, 0x39, 0xb6, 0x51, - 0xcf, 0x0f, 0x0e, 0x10, 0xa5, 0x23, 0x0b, 0xac, 0x66, 0x7e, 0xf5, 0xa7, 0x65, 0x68, 0xf3, 0x54, - 0x02, 0xfe, 0xb3, 0x19, 0x34, 0x22, 0xcf, 0x61, 0x56, 0xfc, 0xfe, 0x0a, 0xb9, 0xae, 0x5e, 0xe2, - 0xd0, 0x7f, 0xf1, 0xa5, 0xb7, 0x94, 0x05, 0x0b, 0xf6, 0x5b, 0xf8, 0x2b, 0xff, 0xf1, 0xbf, 0xff, - 0xac, 0xd4, 0x22, 0x8d, 0x87, 0xe7, 0x1f, 0x3e, 0x3c, 0xa5, 0x41, 0xcc, 0xda, 0xf8, 0x8b, 0x00, - 0xe9, 0xaf, 0x8a, 0x90, 0xae, 0x72, 0x4d, 0x66, 0x7e, 0x72, 0xa5, 0x77, 0xa3, 0xa0, 0x46, 0xb4, - 0x7b, 0x03, 0xdb, 0x5d, 0xb0, 0xdb, 0xac, 0x5d, 0x3f, 0xf0, 0x13, 0xfe, 0x0b, 0x23, 0x1f, 0x5b, - 0x0f, 0xc8, 0x00, 0x9a, 0xfa, 0xef, 0x7d, 0x10, 0x79, 0x15, 0xa0, 0xe0, 0x17, 0x4b, 0x7a, 0x37, - 0x0b, 0xeb, 0xa4, 0xcc, 0xc1, 0x3e, 0xae, 0xdb, 0x1d, 0xd6, 0xc7, 0x04, 0x31, 0xd2, 0x5e, 0x86, - 0x5c, 0x12, 0xa7, 0x3f, 0xeb, 0x41, 0x6e, 0x69, 0xc2, 0x31, 0xf7, 0xa3, 0x22, 0xbd, 0xdb, 0x53, - 0x6a, 0x45, 0x5f, 0xb7, 0xb1, 0xaf, 0x65, 0x9b, 0xb0, 0xbe, 0xfa, 0x88, 0x23, 0x7f, 0x54, 0xe4, - 0x63, 0xeb, 0xc1, 0xea, 0x9f, 0xde, 0x87, 0xba, 0xba, 0x26, 0x44, 0x7e, 0x04, 0x2d, 0x23, 0xd7, - 0x83, 0xc8, 0x69, 0x14, 0xa5, 0x86, 0xf4, 0x6e, 0x15, 0x57, 0x8a, 0x8e, 0xef, 0x60, 0xc7, 0x5d, - 0xb2, 0xc4, 0x3a, 0x16, 0xc9, 0x12, 0x0f, 0x31, 0x37, 0x8a, 0xbf, 0x6b, 0xf2, 0x4a, 0x3b, 0x71, - 0x78, 0x67, 0xb7, 0xb2, 0x87, 0x80, 0xd1, 0xdb, 0xed, 0x29, 0xb5, 0xa2, 0xbb, 0x5b, 0xd8, 0xdd, - 0x12, 0x59, 0xd4, 0xbb, 0x53, 0x57, 0x77, 0x28, 0xbe, 0x2d, 0xa4, 0xff, 0xe2, 0x05, 0xb9, 0x9d, - 0xbe, 0xfc, 0x52, 0xf0, 0x4b, 0x18, 0x8a, 0x44, 0xf2, 0x3f, 0x87, 0x61, 0x77, 0xb1, 0x2b, 0x42, - 0x70, 0xfb, 0xf4, 0x1f, 0xbc, 0x20, 0xc7, 0xd0, 0xd0, 0x1e, 0x86, 0x26, 0x37, 0xa6, 0x3e, 0x62, - 0xdd, 0xeb, 0x15, 0x55, 0x15, 0x4d, 0x45, 0x6f, 0xff, 0x21, 0x53, 0x48, 0x7f, 0x00, 0x75, 0xf5, - 0xd4, 0x30, 0x59, 0xd6, 0x9e, 0x7e, 0xd6, 0x9f, 0x46, 0xee, 0x75, 0xf3, 0x15, 0x45, 0xc4, 0xa7, - 0xb7, 0xce, 0x88, 0xef, 0x25, 0x34, 0xb4, 0xe7, 0x84, 0xd5, 0x04, 0xf2, 0x4f, 0x16, 0xab, 0x09, - 0x14, 0xbc, 0x3e, 0x6c, 0xcf, 0x63, 0x17, 0x0d, 0x52, 0x47, 0xfa, 0x4e, 0x5e, 0x87, 0x31, 0xd9, - 0x85, 0xeb, 0xe2, 0x64, 0x3d, 0xa6, 0x5f, 0x64, 0x1b, 0x0a, 0x7e, 0x64, 0xe4, 0x91, 0x45, 0x9e, - 0x40, 0x4d, 0xbe, 0x1a, 0x4d, 0x96, 0x8a, 0x5f, 0xbf, 0xee, 0x2d, 0xe7, 0xe0, 0xe2, 0x18, 0xfc, - 0x1e, 0x40, 0xfa, 0x76, 0xb1, 0x12, 0x12, 0xb9, 0xb7, 0x90, 0x15, 0x05, 0xe4, 0x1f, 0x3a, 0xb6, - 0x97, 0x70, 0x82, 0x1d, 0x82, 0x42, 0x22, 0xa0, 0x17, 0xf2, 0x61, 0x8b, 0x1f, 0x42, 0x43, 0x7b, - 0xbe, 0x58, 0x2d, 0x5f, 0xfe, 0xe9, 0x63, 0xb5, 0x7c, 0x05, 0xaf, 0x1d, 0xdb, 0x3d, 0x6c, 0x7d, - 0xd1, 0x9e, 0x63, 0xad, 0xc7, 0xfe, 0x69, 0x30, 0xe2, 0x08, 0x6c, 0x83, 0xce, 0xa0, 0x65, 0xbc, - 0x51, 0xac, 0x38, 0xb4, 0xe8, 0x05, 0x64, 0xc5, 0xa1, 0x85, 0xcf, 0x1a, 0x4b, 0x3a, 0xb3, 0xe7, - 0x59, 0x3f, 0xe7, 0x88, 0xa2, 0xf5, 0xf4, 0x7d, 0x68, 0x68, 0xef, 0x0d, 0xab, 0xb9, 0xe4, 0x9f, - 0x36, 0x56, 0x73, 0x29, 0x7a, 0x9e, 0x78, 0x11, 0xfb, 0x68, 0xdb, 0x48, 0x0a, 0xf8, 0x54, 0x15, - 0x6b, 0xfb, 0x47, 0xd0, 0x36, 0x5f, 0x20, 0x56, 0xbc, 0x5f, 0xf8, 0x96, 0xb1, 0xe2, 0xfd, 0x29, - 0xcf, 0x16, 0x0b, 0x92, 0x7e, 0xb0, 0xa0, 0x3a, 0x79, 0xf8, 0x13, 0x71, 0xeb, 0xf9, 0x73, 0xf2, - 0x1d, 0x26, 0xe0, 0xc4, 0x13, 0x6a, 0x64, 0x59, 0xa3, 0x5a, 0xfd, 0xa1, 0x35, 0xc5, 0x2f, 0xb9, - 0xd7, 0xd6, 0x4c, 0x62, 0xe6, 0x8f, 0x6d, 0x3d, 0x83, 0x05, 0x45, 0xcc, 0xea, 0x49, 0xb4, 0x58, - 0xcd, 0xa1, 0xf0, 0xe5, 0xb5, 0x5e, 0x27, 0x5b, 0xfb, 0xc8, 0xe2, 0xc7, 0x1f, 0x3e, 0x3c, 0xa5, - 0x1d, 0x7f, 0xfa, 0xab, 0x68, 0xda, 0xf1, 0x67, 0xbc, 0x4f, 0x95, 0x3d, 0xfe, 0x12, 0x9f, 0xb5, - 0x11, 0xc0, 0x5c, 0x26, 0x7d, 0x56, 0xb1, 0x57, 0xf1, 0x0b, 0x07, 0xbd, 0x3b, 0x57, 0x67, 0xdd, - 0x9a, 0xa2, 0x48, 0x4a, 0xd3, 0x87, 0xf2, 0xf9, 0x94, 0xdf, 0x87, 0xa6, 0xfe, 0x48, 0x2a, 0xd1, - 0x65, 0x42, 0xb6, 0xa7, 0x9b, 0x85, 0x75, 0x26, 0x95, 0x90, 0xa6, 0xde, 0x0d, 0xf9, 0x2e, 0x2c, - 0xa9, 0x65, 0xd6, 0xb3, 0x28, 0x63, 0xf2, 0x4e, 0x41, 0x6e, 0xa5, 0xb1, 0xd8, 0x37, 0xa6, 0x26, - 0x5f, 0x3e, 0xb2, 0x18, 0xf5, 0x99, 0x0f, 0x34, 0xa6, 0x27, 0x4f, 0xd1, 0xbb, 0x94, 0xe9, 0xc9, - 0x53, 0xf8, 0xaa, 0xa3, 0xa4, 0x3e, 0xb2, 0x60, 0xac, 0x11, 0xbf, 0xdc, 0x45, 0xbe, 0x0f, 0x73, - 0x5a, 0xce, 0xfb, 0xe1, 0x65, 0xd0, 0x57, 0x9c, 0x94, 0x7f, 0xdf, 0xa8, 0x57, 0x64, 0x96, 0xda, - 0xcb, 0xd8, 0xfe, 0xbc, 0x6d, 0x2c, 0x0e, 0xe3, 0xa2, 0x0d, 0x68, 0xe8, 0xf9, 0xf4, 0x57, 0xb4, - 0xbb, 0xac, 0x55, 0xe9, 0x8f, 0xe7, 0x3c, 0xb2, 0xc8, 0x2e, 0x74, 0xb2, 0xef, 0x7c, 0x28, 0x99, - 0x52, 0xf4, 0x36, 0x49, 0x2f, 0x53, 0x69, 0xbc, 0x0e, 0x42, 0x0e, 0xf8, 0x95, 0x61, 0xf5, 0x6b, - 0x1c, 0x61, 0x94, 0x3d, 0xd5, 0xcd, 0x5f, 0xe9, 0x50, 0xad, 0x15, 0xfd, 0x3e, 0xcb, 0x7d, 0xeb, - 0x91, 0x45, 0xfe, 0x9e, 0x05, 0x4d, 0x23, 0x7b, 0xde, 0xb8, 0x80, 0x99, 0x99, 0x67, 0x57, 0xaf, - 0xd3, 0x27, 0x6a, 0x3b, 0xb8, 0x88, 0xbb, 0x0f, 0x3e, 0x31, 0x36, 0xe9, 0x27, 0x86, 0xa7, 0x77, - 0x25, 0xfb, 0x93, 0x1c, 0x9f, 0x67, 0x11, 0xf4, 0x37, 0xaa, 0x3e, 0x7f, 0x64, 0x91, 0x7f, 0x6a, - 0x41, 0xdb, 0x8c, 0xef, 0xa8, 0xe9, 0x16, 0x46, 0x92, 0x14, 0x29, 0x4d, 0x09, 0x0a, 0x7d, 0x1f, - 0x47, 0x79, 0xf4, 0xc0, 0x31, 0x46, 0x29, 0x9e, 0x16, 0xfd, 0xd5, 0x46, 0x4b, 0x3e, 0xe6, 0xbf, - 0x90, 0x25, 0x43, 0xdb, 0x24, 0xff, 0x8b, 0x4a, 0x8a, 0xfc, 0xf4, 0xdf, 0x1f, 0xc2, 0x4d, 0xf8, - 0x21, 0xff, 0x29, 0x0a, 0x19, 0x1f, 0x65, 0x54, 0xfc, 0xb6, 0xdf, 0xdb, 0xf7, 0x70, 0x4e, 0x77, - 0xec, 0x1b, 0xc6, 0x9c, 0xb2, 0x8a, 0xc7, 0x1a, 0x1f, 0x9d, 0xf8, 0xe9, 0xa0, 0xf4, 0xe4, 0xcc, - 0xfd, 0x9c, 0xd0, 0xf4, 0x41, 0x8e, 0xf8, 0x20, 0x05, 0xba, 0xc1, 0x6a, 0x6f, 0xd9, 0x8c, 0xfd, - 0x00, 0xc7, 0x7a, 0xcf, 0x7e, 0x67, 0xea, 0x58, 0x1f, 0x62, 0x94, 0x86, 0x8d, 0xf8, 0x00, 0x20, - 0xbd, 0x8a, 0x42, 0x32, 0xd7, 0x20, 0x94, 0x00, 0xca, 0xdf, 0x56, 0x31, 0xf9, 0x59, 0xde, 0x96, - 0x60, 0x2d, 0xfe, 0x80, 0x8b, 0xd3, 0x1d, 0x79, 0x81, 0x42, 0xd7, 0xbe, 0xcc, 0xfb, 0x22, 0x86, - 0xf6, 0x95, 0x6d, 0xdf, 0x10, 0xa6, 0xea, 0x36, 0xc6, 0x0b, 0x68, 0xed, 0x86, 0xe1, 0xab, 0xc9, - 0x58, 0xdd, 0x8d, 0x34, 0x03, 0xa8, 0xdb, 0x5e, 0x7c, 0xd6, 0xcb, 0xcc, 0xc2, 0xbe, 0x8b, 0x4d, - 0xf5, 0x48, 0x57, 0x6b, 0xea, 0xe1, 0x4f, 0xd2, 0x6b, 0x2e, 0x9f, 0x13, 0x0f, 0xe6, 0x95, 0x8c, - 0x56, 0x03, 0xef, 0x99, 0xcd, 0x18, 0x92, 0x39, 0xdb, 0x85, 0x61, 0x26, 0xc8, 0xd1, 0x3e, 0x8c, - 0x65, 0x9b, 0x8f, 0x2c, 0x72, 0x00, 0xcd, 0x4d, 0xda, 0xc7, 0x8c, 0x51, 0x8c, 0x42, 0x2e, 0x18, - 0x91, 0x2c, 0x1e, 0xbe, 0xec, 0xb5, 0x0c, 0xa0, 0x79, 0x6e, 0x8d, 0xbd, 0xcb, 0x88, 0x7e, 0xf6, - 0xf0, 0x27, 0x22, 0xbe, 0xf9, 0xb9, 0x3c, 0xb7, 0x64, 0x00, 0xd8, 0x38, 0xb7, 0x32, 0x11, 0x63, - 0xe3, 0xdc, 0xca, 0x45, 0x8c, 0x8d, 0xa5, 0x96, 0x01, 0x68, 0x32, 0x84, 0xf9, 0x5c, 0x90, 0x59, - 0x1d, 0x59, 0xd3, 0x42, 0xd3, 0xbd, 0xbb, 0xd3, 0x11, 0xcc, 0xde, 0x1e, 0x98, 0xbd, 0x1d, 0x42, - 0x8b, 0xbf, 0x9b, 0x75, 0x4c, 0x79, 0x32, 0x48, 0xe6, 0x09, 0x06, 0x3d, 0xd5, 0x24, 0x7b, 0xc0, - 0x60, 0x9d, 0xa9, 0xe1, 0xf0, 0x07, 0x38, 0x7f, 0x00, 0x8d, 0x67, 0x34, 0x91, 0xd9, 0x1f, 0x4a, - 0xc7, 0xce, 0xa4, 0x83, 0xf4, 0x0a, 0x92, 0x47, 0x4c, 0x9a, 0xc1, 0xd6, 0x1e, 0xd2, 0xc1, 0x29, - 0xe5, 0xc2, 0xc9, 0xf5, 0x07, 0x9f, 0x93, 0xdf, 0xc3, 0xc6, 0x55, 0x2e, 0xde, 0x92, 0x76, 0x95, - 0x5f, 0x6f, 0x7c, 0x2e, 0x03, 0x2f, 0x6a, 0x39, 0x08, 0x07, 0x54, 0xd3, 0xf5, 0x02, 0x68, 0x68, - 0xb9, 0xbc, 0x8a, 0x81, 0xf2, 0xb9, 0xdb, 0x8a, 0x81, 0x0a, 0x52, 0x7f, 0xed, 0xfb, 0xd8, 0x8f, - 0x4d, 0xee, 0xa6, 0xfd, 0xf0, 0x74, 0xdf, 0xb4, 0xa7, 0x87, 0x3f, 0xf1, 0x46, 0xc9, 0xe7, 0xe4, - 0x25, 0xbe, 0x62, 0xab, 0x67, 0xb7, 0xa4, 0x46, 0x43, 0x36, 0x11, 0x46, 0x2d, 0x96, 0x56, 0x65, - 0x1a, 0x12, 0xbc, 0x2b, 0xd4, 0xe4, 0xbe, 0x01, 0x70, 0x98, 0x84, 0xe3, 0x4d, 0x8f, 0x8e, 0xc2, - 0x20, 0x95, 0xb5, 0x69, 0x6e, 0x45, 0x2a, 0xbf, 0xb4, 0x04, 0x0b, 0xf2, 0x52, 0xb3, 0xb2, 0x8c, - 0x04, 0x21, 0x49, 0x5c, 0x53, 0xd3, 0x2f, 0xd4, 0x82, 0x14, 0xa4, 0x60, 0x3c, 0xb2, 0xc8, 0x1a, - 0x40, 0x7a, 0xcb, 0x40, 0xd9, 0x4c, 0xb9, 0x0b, 0x0c, 0x4a, 0xec, 0x15, 0x5c, 0x49, 0x38, 0x80, - 0x7a, 0x1a, 0x93, 0x5d, 0x4e, 0x9f, 0x26, 0x30, 0x22, 0xb8, 0xea, 0x04, 0xcf, 0x05, 0x43, 0xed, - 0x0e, 0x2e, 0x15, 0x90, 0x1a, 0x5b, 0x2a, 0x8c, 0x70, 0xfa, 0xb0, 0xc0, 0x07, 0xa8, 0xd4, 0x25, - 0xcc, 0x09, 0x50, 0x8f, 0x15, 0xe7, 0x03, 0x92, 0x8a, 0x9b, 0x0b, 0xe3, 0x69, 0x86, 0xeb, 0x87, - 0x51, 0x2b, 0xcf, 0x47, 0x60, 0xa2, 0x79, 0x04, 0xf3, 0xb9, 0x10, 0x8d, 0x62, 0xe9, 0x69, 0x31, - 0x38, 0xc5, 0xd2, 0x53, 0xa3, 0x3b, 0xf6, 0x75, 0xec, 0x72, 0xce, 0x06, 0x34, 0xf5, 0x2e, 0xfc, - 0xa4, 0x7f, 0xc6, 0xba, 0xfb, 0x43, 0x0b, 0x16, 0x0a, 0x22, 0x30, 0xe4, 0x5d, 0xe9, 0x35, 0x98, - 0x1a, 0x9d, 0xe9, 0x15, 0x3a, 0xe8, 0xed, 0x43, 0xec, 0xe7, 0x39, 0xf9, 0xd4, 0x38, 0xd8, 0xb8, - 0x6f, 0x5c, 0x70, 0xe6, 0x95, 0x4a, 0x45, 0xa1, 0x46, 0xf1, 0x19, 0x2c, 0xf3, 0x81, 0xac, 0x0d, - 0x87, 0x99, 0xe0, 0xc1, 0x9d, 0xdc, 0xaf, 0xe8, 0x1a, 0x41, 0x91, 0xde, 0xf4, 0x5f, 0xd9, 0x9d, - 0xa2, 0x4e, 0xf3, 0xa1, 0x92, 0x09, 0x74, 0xb2, 0x0e, 0x79, 0x32, 0xbd, 0xad, 0xde, 0x3b, 0x86, - 0xfd, 0x5b, 0xe0, 0xc4, 0xff, 0x2d, 0xec, 0xec, 0x1d, 0xbb, 0x57, 0xb4, 0x2e, 0xdc, 0x24, 0x66, - 0xfb, 0xf1, 0x97, 0x55, 0xf4, 0x20, 0x33, 0x4f, 0xd9, 0xc1, 0xb4, 0x70, 0x87, 0xb2, 0xc0, 0x8b, - 0x83, 0x0f, 0xef, 0x61, 0xf7, 0x77, 0xed, 0x9b, 0x45, 0xdd, 0x47, 0xfc, 0x13, 0x6e, 0x8b, 0x2f, - 0x67, 0xf9, 0x5a, 0x8e, 0xe0, 0x6e, 0xd1, 0x7e, 0x4f, 0xb5, 0x85, 0x32, 0x6b, 0x7d, 0x0d, 0x75, - 0xbb, 0xa6, 0x1e, 0x2d, 0x50, 0xec, 0x53, 0x10, 0x96, 0x50, 0xec, 0x53, 0x14, 0x5e, 0x30, 0xf5, - 0x1a, 0x19, 0x58, 0xf8, 0xd8, 0x7a, 0xb0, 0xfe, 0xfe, 0xf7, 0x7f, 0xeb, 0xd4, 0x4f, 0xce, 0x26, - 0xc7, 0x2b, 0xfd, 0x70, 0xf4, 0x70, 0x28, 0xbd, 0x8d, 0x22, 0x4f, 0xee, 0xe1, 0x30, 0x18, 0x3c, - 0xc4, 0x66, 0x8f, 0x67, 0xf0, 0x67, 0xbf, 0xbf, 0xf6, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xd5, - 0x81, 0xeb, 0xf5, 0x28, 0x7c, 0x00, 0x00, + // 10441 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x1c, 0x57, + 0x76, 0x18, 0xfb, 0x35, 0xdd, 0x7d, 0xfa, 0x31, 0x3d, 0x77, 0x86, 0x33, 0xcd, 0xa6, 0x28, 0x52, + 0x25, 0xad, 0x48, 0x51, 0x12, 0x49, 0x71, 0xa5, 0x95, 0x2c, 0x25, 0x6b, 0xcf, 0x53, 0x33, 0xcb, + 0x79, 0xa9, 0x7a, 0xb8, 0xb2, 0x76, 0xe3, 0xd4, 0xd6, 0x74, 0xdf, 0x99, 0x29, 0xb3, 0xbb, 0xaa, + 0x55, 0x55, 0x3d, 0x8f, 0x15, 0x94, 0x0f, 0x79, 0x18, 0x41, 0x12, 0x04, 0x30, 0x12, 0x07, 0x88, + 0x13, 0x23, 0x41, 0x82, 0x20, 0x08, 0x92, 0x18, 0x0e, 0xec, 0x00, 0xf9, 0x90, 0xef, 0xfe, 0x92, + 0xc0, 0x1f, 0x9c, 0x20, 0x40, 0xb0, 0x30, 0x60, 0xc4, 0xc8, 0x67, 0xff, 0x84, 0xe0, 0x9e, 0x73, + 0xef, 0xad, 0x5b, 0xdd, 0xd5, 0x24, 0xa5, 0xdd, 0xec, 0x17, 0x72, 0xea, 0xdc, 0x73, 0xdf, 0xe7, + 0x9e, 0x7b, 0x9e, 0xb7, 0xa1, 0x1a, 0x8e, 0x7a, 0x0f, 0x46, 0x61, 0x10, 0x07, 0xac, 0x34, 0xf0, + 0xc3, 0x51, 0xaf, 0xf3, 0xca, 0x69, 0x10, 0x9c, 0x0e, 0xf8, 0x43, 0x77, 0xe4, 0x3d, 0x74, 0x7d, + 0x3f, 0x88, 0xdd, 0xd8, 0x0b, 0xfc, 0x88, 0x90, 0xac, 0x9f, 0x40, 0xf3, 0x53, 0xee, 0x77, 0x39, + 0xef, 0xdb, 0xfc, 0xcb, 0x31, 0x8f, 0x62, 0xf6, 0x36, 0x2c, 0xb8, 0xfc, 0xa7, 0x9c, 0xf7, 0x9d, + 0x91, 0x1b, 0x45, 0xa3, 0xb3, 0xd0, 0x8d, 0x78, 0x3b, 0x77, 0x27, 0x77, 0xaf, 0x6e, 0xb7, 0xa8, + 0xe0, 0x50, 0xc3, 0xd9, 0x6b, 0x50, 0x8f, 0x04, 0x2a, 0xf7, 0xe3, 0x30, 0x18, 0x5d, 0xb5, 0xf3, + 0x88, 0x57, 0x13, 0xb0, 0x4d, 0x02, 0x59, 0x03, 0x98, 0xd7, 0x3d, 0x44, 0xa3, 0xc0, 0x8f, 0x38, + 0x7b, 0x04, 0x4b, 0x3d, 0x6f, 0x74, 0xc6, 0x43, 0x07, 0x2b, 0x0f, 0x7d, 0x3e, 0x0c, 0x7c, 0xaf, + 0xd7, 0xce, 0xdd, 0x29, 0xdc, 0xab, 0xda, 0x8c, 0xca, 0x44, 0x8d, 0x3d, 0x59, 0xc2, 0xee, 0xc2, + 0x3c, 0xf7, 0x09, 0xce, 0xfb, 0x58, 0x4b, 0x76, 0xd5, 0x4c, 0xc0, 0xa2, 0x82, 0xf5, 0x77, 0xf3, + 0xb0, 0xb0, 0xe3, 0x7b, 0xf1, 0xe7, 0xee, 0x60, 0xc0, 0x63, 0x35, 0xa7, 0xbb, 0x30, 0x7f, 0x81, + 0x00, 0x9c, 0xd3, 0x45, 0x10, 0xf6, 0xe5, 0x8c, 0x9a, 0x04, 0x3e, 0x94, 0xd0, 0x99, 0x23, 0xcb, + 0xcf, 0x1c, 0x59, 0xe6, 0x72, 0x15, 0x66, 0x2c, 0xd7, 0x5d, 0x98, 0x0f, 0x79, 0x2f, 0x38, 0xe7, + 0xe1, 0x95, 0x73, 0xe1, 0xf9, 0xfd, 0xe0, 0xa2, 0x5d, 0xbc, 0x93, 0xbb, 0x57, 0xb2, 0x9b, 0x0a, + 0xfc, 0x39, 0x42, 0xd9, 0x1a, 0xcc, 0xf7, 0xce, 0x5c, 0xdf, 0xe7, 0x03, 0xe7, 0xd8, 0xed, 0x3d, + 0x1b, 0x8f, 0xa2, 0x76, 0xe9, 0x4e, 0xee, 0x5e, 0xed, 0xf1, 0x8d, 0x07, 0xb8, 0xab, 0x0f, 0xd6, + 0xcf, 0x5c, 0x7f, 0x0d, 0x4b, 0xba, 0xbe, 0x3b, 0x8a, 0xce, 0x82, 0xd8, 0x6e, 0xca, 0x1a, 0x04, + 0x8e, 0xac, 0x25, 0x60, 0xe6, 0x4a, 0xd0, 0xda, 0x5b, 0xff, 0x3e, 0x07, 0x8b, 0x4f, 0xfd, 0x41, + 0xd0, 0x7b, 0xf6, 0x2d, 0x97, 0x28, 0x63, 0x0e, 0xf9, 0x97, 0x9d, 0x43, 0xe1, 0x9b, 0xce, 0x61, + 0x19, 0x96, 0xd2, 0x83, 0x95, 0xb3, 0xe0, 0x70, 0x5d, 0xd4, 0x3e, 0xe5, 0x6a, 0x58, 0x6a, 0x1a, + 0x6f, 0x41, 0xab, 0x37, 0x0e, 0x43, 0xee, 0x4f, 0xcd, 0x63, 0x5e, 0xc2, 0xf5, 0x44, 0x5e, 0x83, + 0xba, 0xcf, 0x2f, 0x12, 0x34, 0x49, 0xbb, 0x3e, 0xbf, 0x50, 0x28, 0x56, 0x1b, 0x96, 0x27, 0xbb, + 0x91, 0x03, 0xf8, 0x5f, 0x39, 0x28, 0x3e, 0x8d, 0x2f, 0x03, 0xf6, 0x26, 0x14, 0xe3, 0xab, 0x11, + 0x9d, 0x90, 0xe6, 0x63, 0x26, 0xa7, 0xb6, 0xda, 0xef, 0x87, 0x3c, 0x8a, 0x8e, 0xae, 0x46, 0xdc, + 0xc6, 0x72, 0xd6, 0x86, 0xb2, 0x4b, 0x40, 0xec, 0xa8, 0x6a, 0xab, 0x4f, 0x76, 0x0b, 0xc0, 0x1d, + 0x06, 0x63, 0x3f, 0x76, 0x22, 0x37, 0xc6, 0x25, 0x2a, 0xd8, 0x55, 0x82, 0x74, 0xdd, 0x98, 0xdd, + 0x84, 0xea, 0xe8, 0x99, 0x13, 0xf5, 0x42, 0x6f, 0x14, 0x23, 0xb5, 0x54, 0xed, 0xca, 0xe8, 0x59, + 0x17, 0xbf, 0xd9, 0xdb, 0x50, 0x09, 0xc6, 0xf1, 0x28, 0xf0, 0xfc, 0x58, 0x12, 0xc8, 0xbc, 0x1c, + 0xc1, 0xc1, 0x38, 0x3e, 0x14, 0x60, 0x5b, 0x23, 0xb0, 0x37, 0xa0, 0xd1, 0x0b, 0xfc, 0x13, 0x2f, + 0x1c, 0x12, 0x0b, 0x68, 0xcf, 0x61, 0x5f, 0x69, 0xa0, 0xf5, 0x07, 0x79, 0xa8, 0x1d, 0x85, 0xae, + 0x1f, 0xb9, 0x3d, 0x01, 0x60, 0x2b, 0x50, 0x8e, 0x2f, 0x9d, 0x33, 0x37, 0x3a, 0xc3, 0x39, 0x56, + 0xed, 0xb9, 0xf8, 0x72, 0xdb, 0x8d, 0xce, 0xd8, 0x32, 0xcc, 0xd1, 0x28, 0x71, 0x42, 0x05, 0x5b, + 0x7e, 0x89, 0x13, 0xe1, 0x8f, 0x87, 0x4e, 0xba, 0xab, 0x02, 0x92, 0x48, 0xcb, 0x1f, 0x0f, 0xd7, + 0x4d, 0xb8, 0x98, 0xfc, 0xb1, 0xd8, 0x5f, 0xea, 0x80, 0xa6, 0x57, 0x45, 0x08, 0xf6, 0xf1, 0x1a, + 0xd4, 0x65, 0x31, 0xf7, 0x4e, 0xcf, 0x68, 0x8e, 0x25, 0xbb, 0x46, 0x08, 0x08, 0x12, 0x2d, 0xc4, + 0xde, 0x90, 0x3b, 0x51, 0xec, 0x0e, 0x47, 0x72, 0x4a, 0x55, 0x01, 0xe9, 0x0a, 0x00, 0x16, 0x07, + 0xb1, 0x3b, 0x70, 0x4e, 0x38, 0x8f, 0xda, 0x65, 0x59, 0x2c, 0x20, 0x5b, 0x9c, 0x47, 0xec, 0x3b, + 0xd0, 0xec, 0xf3, 0x28, 0x76, 0xe4, 0x66, 0xf0, 0xa8, 0x5d, 0xc1, 0xa3, 0xde, 0x10, 0xd0, 0x55, + 0x05, 0x64, 0xaf, 0x00, 0x84, 0xee, 0x85, 0x23, 0x16, 0x82, 0x5f, 0xb6, 0xab, 0xb4, 0x0b, 0xa1, + 0x7b, 0x71, 0x74, 0xb9, 0xcd, 0x2f, 0x05, 0x99, 0x7c, 0xca, 0x63, 0x63, 0xd1, 0x22, 0x49, 0x8e, + 0xd6, 0x2e, 0x30, 0x03, 0xbc, 0xc1, 0x63, 0xd7, 0x1b, 0x44, 0xec, 0x7b, 0x50, 0x8f, 0x0d, 0x64, + 0xe4, 0x7b, 0x35, 0x4d, 0x3b, 0x46, 0x05, 0x3b, 0x85, 0x67, 0x9d, 0x41, 0x65, 0x8b, 0xf3, 0x5d, + 0x6f, 0xe8, 0xc5, 0x6c, 0x19, 0x4a, 0x27, 0xde, 0x25, 0x27, 0xea, 0x2e, 0x6c, 0x5f, 0xb3, 0xe9, + 0x93, 0xdd, 0x06, 0xc0, 0x3f, 0x9c, 0xa1, 0xa6, 0xa6, 0xed, 0x6b, 0x76, 0x15, 0x61, 0x7b, 0x91, + 0x1b, 0xb3, 0x0e, 0x94, 0x47, 0x3c, 0xec, 0x71, 0xb5, 0x6f, 0xdb, 0xd7, 0x6c, 0x05, 0x58, 0x2b, + 0x43, 0x69, 0x20, 0x5a, 0xb7, 0xfe, 0xb8, 0x04, 0xb5, 0x2e, 0xf7, 0xf5, 0xb1, 0x62, 0x50, 0x14, + 0x0b, 0x22, 0x8f, 0x12, 0xfe, 0xcd, 0x5e, 0x87, 0x1a, 0x2e, 0x5d, 0x14, 0x87, 0x9e, 0x7f, 0x4a, + 0x54, 0xbd, 0x96, 0x6f, 0xe7, 0x6c, 0x10, 0xe0, 0x2e, 0x42, 0x59, 0x0b, 0x0a, 0xee, 0x50, 0x51, + 0xb5, 0xf8, 0x93, 0xdd, 0x80, 0x8a, 0x3b, 0x8c, 0x69, 0x78, 0x75, 0x04, 0x97, 0xdd, 0x61, 0x8c, + 0x43, 0x7b, 0x0d, 0xea, 0x23, 0xf7, 0x6a, 0x28, 0x0e, 0xaf, 0x26, 0x87, 0xba, 0x5d, 0x93, 0x30, + 0x24, 0x88, 0xc7, 0xb0, 0x68, 0xa2, 0xa8, 0xce, 0x4b, 0xba, 0xf3, 0x05, 0x03, 0x5b, 0x8e, 0xe1, + 0x2e, 0xcc, 0xab, 0x3a, 0x21, 0xcd, 0x07, 0xc9, 0xa4, 0x6a, 0x37, 0x25, 0x58, 0xcd, 0xf2, 0x1e, + 0xb4, 0x4e, 0x3c, 0xdf, 0x1d, 0x38, 0xbd, 0x41, 0x7c, 0xee, 0xf4, 0xf9, 0x20, 0x76, 0x91, 0x62, + 0x4a, 0x76, 0x13, 0xe1, 0xeb, 0x83, 0xf8, 0x7c, 0x43, 0x40, 0xd9, 0x3b, 0x50, 0x3d, 0xe1, 0xdc, + 0xc1, 0xc5, 0x6a, 0x57, 0x52, 0x07, 0x4f, 0xed, 0x90, 0x5d, 0x39, 0x51, 0x7b, 0xf5, 0x0e, 0xb4, + 0x82, 0x71, 0x7c, 0x1a, 0x78, 0xfe, 0xa9, 0x23, 0x18, 0x9c, 0xe3, 0xf5, 0x91, 0x86, 0x8a, 0x6b, + 0xf9, 0x47, 0x39, 0xbb, 0xa9, 0xca, 0x04, 0xab, 0xd9, 0xe9, 0xb3, 0x37, 0x61, 0x7e, 0xe0, 0x46, + 0xb1, 0x73, 0x16, 0x8c, 0x9c, 0xd1, 0xf8, 0xf8, 0x19, 0xbf, 0x6a, 0x37, 0x70, 0x21, 0x1a, 0x02, + 0xbc, 0x1d, 0x8c, 0x0e, 0x11, 0x28, 0x28, 0x1b, 0xc7, 0x49, 0x83, 0x80, 0x3b, 0xb9, 0x7b, 0x0d, + 0xbb, 0x2a, 0x20, 0xd4, 0xe9, 0x17, 0xb0, 0x88, 0xdb, 0xd3, 0x1b, 0x47, 0x71, 0x30, 0x74, 0x04, + 0x73, 0x0e, 0xfb, 0x51, 0xbb, 0x86, 0xb4, 0xf6, 0x96, 0x1c, 0xac, 0xb1, 0xc7, 0x0f, 0x36, 0x78, + 0x14, 0xaf, 0x23, 0xb2, 0x4d, 0xb8, 0xe2, 0x06, 0xbf, 0xb2, 0x17, 0xfa, 0x93, 0x70, 0xf6, 0x0e, + 0x30, 0x77, 0x30, 0x08, 0x2e, 0x9c, 0x88, 0x0f, 0x4e, 0x1c, 0xb9, 0x88, 0xed, 0xe6, 0x9d, 0xdc, + 0xbd, 0x8a, 0xdd, 0xc2, 0x92, 0x2e, 0x1f, 0x9c, 0x1c, 0x12, 0x9c, 0x7d, 0x0f, 0xf0, 0x30, 0x39, + 0x27, 0xdc, 0x8d, 0xc7, 0x21, 0x8f, 0xda, 0xf3, 0x77, 0x0a, 0xf7, 0x9a, 0x8f, 0x17, 0xf4, 0x7a, + 0x21, 0x78, 0xcd, 0x8b, 0xed, 0xba, 0xc0, 0x93, 0xdf, 0x51, 0x67, 0x03, 0x96, 0xb3, 0x87, 0x24, + 0x88, 0x4a, 0xac, 0x8a, 0x20, 0xc6, 0xa2, 0x2d, 0xfe, 0x64, 0x4b, 0x50, 0x3a, 0x77, 0x07, 0x63, + 0x2e, 0x99, 0x38, 0x7d, 0x7c, 0x9c, 0xff, 0x28, 0x67, 0xfd, 0x51, 0x0e, 0xea, 0x34, 0x4b, 0x29, + 0x7c, 0xbc, 0x0e, 0x0d, 0x45, 0x0d, 0x3c, 0x0c, 0x83, 0x50, 0x72, 0x35, 0x45, 0x79, 0x9b, 0x02, + 0x26, 0xae, 0x11, 0x85, 0x34, 0x0a, 0xb9, 0x37, 0x74, 0x4f, 0x55, 0xd3, 0x8a, 0x94, 0x0e, 0x25, + 0x98, 0xbd, 0x97, 0xb4, 0x17, 0x06, 0xe3, 0x98, 0xcb, 0x4b, 0xae, 0x2e, 0xa7, 0x67, 0x0b, 0x98, + 0x6e, 0x1d, 0xbf, 0x5e, 0x82, 0xce, 0xad, 0xdf, 0xc9, 0x01, 0x13, 0xc3, 0x3e, 0x0a, 0xa8, 0x01, + 0x49, 0xa1, 0x93, 0x35, 0x73, 0x2f, 0x7d, 0x42, 0xf2, 0xcf, 0x3b, 0x21, 0x16, 0x94, 0x68, 0xec, + 0xc5, 0x8c, 0xb1, 0x53, 0xd1, 0x0f, 0x8a, 0x95, 0x42, 0xab, 0x68, 0xfd, 0xef, 0x02, 0x2c, 0xad, + 0xd3, 0x1d, 0xbd, 0xda, 0xeb, 0xf1, 0x91, 0x3e, 0x3b, 0xb7, 0xa1, 0xe6, 0x07, 0x7d, 0xae, 0x28, + 0x96, 0x06, 0x06, 0x02, 0x64, 0x90, 0xeb, 0x99, 0xeb, 0xf9, 0x34, 0x70, 0x5a, 0xcc, 0x2a, 0x42, + 0x70, 0xd8, 0x6f, 0xc2, 0xfc, 0x88, 0xfb, 0x7d, 0xf3, 0x88, 0x90, 0x14, 0xd5, 0x90, 0x60, 0x79, + 0x3a, 0x6e, 0x43, 0xed, 0x64, 0x4c, 0x78, 0x82, 0xb1, 0x14, 0x91, 0x06, 0x40, 0x82, 0x56, 0x89, + 0xbf, 0x8c, 0xc6, 0xd1, 0x19, 0x96, 0x96, 0xb0, 0xb4, 0x2c, 0xbe, 0x45, 0xd1, 0x2d, 0x80, 0xfe, + 0x38, 0x8a, 0xe5, 0x89, 0x99, 0xc3, 0xc2, 0xaa, 0x80, 0xd0, 0x89, 0x79, 0x17, 0x16, 0x87, 0xee, + 0xa5, 0x83, 0xb4, 0xe3, 0x78, 0xbe, 0x73, 0x32, 0xc0, 0x3b, 0xa7, 0x8c, 0x78, 0xad, 0xa1, 0x7b, + 0xf9, 0x43, 0x51, 0xb2, 0xe3, 0x6f, 0x21, 0x5c, 0xb0, 0x15, 0x25, 0xdf, 0x84, 0x3c, 0xe2, 0xe1, + 0x39, 0x47, 0x4e, 0x50, 0xd4, 0x42, 0x8c, 0x4d, 0x50, 0x31, 0xa2, 0xa1, 0x98, 0x77, 0x3c, 0xe8, + 0xd1, 0xb1, 0xb7, 0xcb, 0x43, 0xcf, 0xdf, 0x8e, 0x07, 0x3d, 0x71, 0xaf, 0x08, 0x3e, 0x32, 0xe2, + 0xa1, 0xf3, 0xec, 0x02, 0xcf, 0x70, 0x11, 0xf9, 0xc6, 0x21, 0x0f, 0x9f, 0x5c, 0x88, 0xab, 0xbf, + 0x17, 0x21, 0x23, 0x72, 0xaf, 0xda, 0x35, 0x3c, 0xe0, 0x95, 0x5e, 0x24, 0x58, 0x90, 0x7b, 0x25, + 0x0e, 0xa1, 0x18, 0xad, 0x8b, 0xbb, 0xc0, 0xfb, 0xd8, 0x7c, 0x84, 0x1c, 0xb5, 0x81, 0x83, 0x5d, + 0x95, 0x05, 0xa2, 0x9f, 0x48, 0x50, 0xbd, 0x1a, 0xec, 0xc9, 0xc0, 0x3d, 0x8d, 0x90, 0xa5, 0x34, + 0xec, 0xba, 0x04, 0x6e, 0x09, 0x98, 0xf5, 0x39, 0x49, 0x55, 0xc6, 0xde, 0xca, 0x33, 0x23, 0xae, + 0x7a, 0x84, 0xe0, 0xbe, 0x56, 0x6c, 0xf9, 0x95, 0xb5, 0x69, 0xf9, 0x8c, 0x4d, 0xb3, 0x7e, 0x2f, + 0x07, 0x75, 0xd9, 0x32, 0x0a, 0x25, 0xec, 0x01, 0x30, 0xb5, 0x8b, 0xf1, 0xa5, 0xd7, 0x77, 0x8e, + 0xaf, 0x62, 0x1e, 0x11, 0xd1, 0x6c, 0x5f, 0xb3, 0x5b, 0xb2, 0xec, 0xe8, 0xd2, 0xeb, 0xaf, 0x89, + 0x12, 0x76, 0x1f, 0x5a, 0x29, 0xfc, 0x28, 0x0e, 0x89, 0xa2, 0xb7, 0xaf, 0xd9, 0x4d, 0x03, 0xbb, + 0x1b, 0x87, 0xe2, 0x8c, 0x08, 0x91, 0x67, 0x1c, 0x3b, 0x9e, 0xdf, 0xe7, 0x97, 0x48, 0x46, 0x0d, + 0xbb, 0x46, 0xb0, 0x1d, 0x01, 0x5a, 0x6b, 0x42, 0xdd, 0x6c, 0xce, 0x3a, 0x85, 0x8a, 0x92, 0x97, + 0x50, 0x60, 0x98, 0x18, 0x92, 0x5d, 0x8d, 0xf5, 0x48, 0x6e, 0x40, 0x25, 0x3d, 0x02, 0xbb, 0x1c, + 0xbf, 0x74, 0xc7, 0xd6, 0xf7, 0xa1, 0xb5, 0x2b, 0x88, 0xc7, 0x17, 0xc4, 0x2a, 0xe5, 0xbf, 0x65, + 0x98, 0x33, 0x0e, 0x4d, 0xd5, 0x96, 0x5f, 0xe2, 0xce, 0x3d, 0x0b, 0xa2, 0x58, 0xf6, 0x82, 0x7f, + 0x5b, 0x7f, 0x9c, 0x03, 0xb6, 0x19, 0xc5, 0xde, 0xd0, 0x8d, 0xf9, 0x16, 0xd7, 0x6c, 0xe1, 0x00, + 0xea, 0xa2, 0xb5, 0xa3, 0x60, 0x95, 0x04, 0x32, 0x12, 0x28, 0xde, 0x96, 0xc7, 0x78, 0xba, 0xc2, + 0x03, 0x13, 0x9b, 0xd8, 0x7c, 0xaa, 0x01, 0x71, 0xca, 0x62, 0x37, 0x3c, 0xe5, 0x31, 0x8a, 0x71, + 0x52, 0xc0, 0x07, 0x02, 0x09, 0x01, 0xae, 0xf3, 0xab, 0xb0, 0x30, 0xd5, 0x86, 0xc9, 0x97, 0xab, + 0x19, 0x7c, 0xb9, 0x60, 0xf2, 0x65, 0x07, 0x16, 0x53, 0xe3, 0x92, 0x94, 0xb6, 0x02, 0x65, 0x71, + 0x20, 0x84, 0x70, 0x90, 0x23, 0xa9, 0xf2, 0x84, 0x73, 0x21, 0x06, 0x3f, 0x84, 0xa5, 0x13, 0xce, + 0x43, 0x37, 0xc6, 0x42, 0x3c, 0x31, 0x62, 0x87, 0x64, 0xc3, 0x0b, 0xb2, 0xac, 0xeb, 0xc6, 0x87, + 0x3c, 0x14, 0x3b, 0x65, 0xfd, 0x9f, 0x1c, 0xcc, 0x0b, 0x0e, 0xba, 0xe7, 0xfa, 0x57, 0x6a, 0x9d, + 0x76, 0x33, 0xd7, 0xe9, 0x9e, 0x71, 0x19, 0x1a, 0xd8, 0xdf, 0x74, 0x91, 0x0a, 0x93, 0x8b, 0xc4, + 0xee, 0x40, 0x3d, 0x35, 0xd6, 0x12, 0x8e, 0x15, 0x22, 0x3d, 0xc8, 0x9f, 0x7f, 0x19, 0xdf, 0x84, + 0x56, 0x32, 0x6c, 0xb9, 0x86, 0x0c, 0x8a, 0x82, 0x24, 0x65, 0x03, 0xf8, 0xb7, 0xf5, 0xcf, 0x73, + 0x84, 0xb8, 0x1e, 0x78, 0x5a, 0x3a, 0x15, 0x88, 0x42, 0xee, 0x55, 0x88, 0xe2, 0xef, 0x99, 0x52, + 0xfd, 0xcf, 0x3f, 0x59, 0x71, 0x74, 0x22, 0xee, 0xf7, 0x1d, 0x77, 0x30, 0x40, 0xe6, 0x5b, 0xb1, + 0xcb, 0xe2, 0x7b, 0x75, 0x30, 0xb0, 0xee, 0xc2, 0x82, 0x31, 0xba, 0xe7, 0xcc, 0x63, 0x1f, 0xd8, + 0xae, 0x17, 0xc5, 0x4f, 0xfd, 0x68, 0x64, 0x08, 0x6e, 0x37, 0xa1, 0x2a, 0x38, 0xac, 0x18, 0x19, + 0x1d, 0xd9, 0x92, 0x2d, 0x58, 0xae, 0x18, 0x57, 0x84, 0x85, 0xee, 0xa5, 0x2c, 0xcc, 0xcb, 0x42, + 0xf7, 0x12, 0x0b, 0xad, 0x8f, 0x60, 0x31, 0xd5, 0x9e, 0xec, 0xfa, 0x35, 0x28, 0x8d, 0xe3, 0xcb, + 0x40, 0x89, 0xe6, 0x35, 0x49, 0x21, 0x42, 0xe3, 0xb3, 0xa9, 0xc4, 0xfa, 0x04, 0x16, 0xf6, 0xf9, + 0x85, 0x3c, 0xc4, 0x6a, 0x20, 0x2f, 0xa9, 0x0d, 0x5a, 0x0f, 0x80, 0x99, 0x95, 0x65, 0xaf, 0x86, + 0x8e, 0x98, 0x4b, 0xe9, 0x88, 0xd6, 0x9b, 0xc0, 0xba, 0xde, 0xa9, 0xbf, 0xc7, 0xa3, 0xc8, 0x3d, + 0xd5, 0xc7, 0xbe, 0x05, 0x85, 0x61, 0x74, 0x2a, 0x79, 0x94, 0xf8, 0xd3, 0xfa, 0x2e, 0x2c, 0xa6, + 0xf0, 0x64, 0xc3, 0xaf, 0x40, 0x35, 0xf2, 0x4e, 0x7d, 0x14, 0xac, 0x64, 0xd3, 0x09, 0xc0, 0xda, + 0x82, 0xa5, 0x1f, 0xf2, 0xd0, 0x3b, 0xb9, 0x7a, 0x51, 0xf3, 0xe9, 0x76, 0xf2, 0x93, 0xed, 0x6c, + 0xc2, 0xf5, 0x89, 0x76, 0x64, 0xf7, 0x44, 0xbe, 0x72, 0x27, 0x2b, 0x36, 0x7d, 0x18, 0x7c, 0x2f, + 0x6f, 0xf2, 0x3d, 0xeb, 0x29, 0xb0, 0xf5, 0xc0, 0xf7, 0x79, 0x2f, 0x3e, 0xe4, 0x3c, 0x4c, 0xcc, + 0x52, 0x09, 0xad, 0xd6, 0x1e, 0xaf, 0xc8, 0x95, 0x9d, 0x64, 0xa6, 0x92, 0x88, 0x19, 0x14, 0x47, + 0x3c, 0x1c, 0x62, 0xc3, 0x15, 0x1b, 0xff, 0xb6, 0xae, 0xc3, 0x62, 0xaa, 0x59, 0xa9, 0xc8, 0x3f, + 0x82, 0xeb, 0x1b, 0x5e, 0xd4, 0x9b, 0xee, 0x70, 0x05, 0xca, 0xa3, 0xf1, 0xb1, 0x93, 0xe6, 0xcb, + 0x4f, 0xf8, 0x95, 0xd0, 0xf6, 0x26, 0x6b, 0xc8, 0xb6, 0xfe, 0x76, 0x0e, 0x8a, 0xdb, 0x47, 0xbb, + 0xeb, 0xac, 0x03, 0x15, 0xcf, 0xef, 0x05, 0x43, 0x21, 0x78, 0xd1, 0x9c, 0xf5, 0xf7, 0xcc, 0x03, + 0x76, 0x13, 0xaa, 0x28, 0xaf, 0x09, 0xd5, 0x56, 0x8a, 0x3e, 0x15, 0x01, 0xd8, 0x0d, 0x7a, 0xcf, + 0x84, 0x4e, 0xcd, 0x2f, 0x47, 0x5e, 0x88, 0x5a, 0xb3, 0x52, 0x86, 0x8b, 0x74, 0xd7, 0x27, 0x05, + 0xa4, 0x11, 0x5b, 0xff, 0xa1, 0x0c, 0x65, 0x79, 0xdb, 0xd2, 0xcd, 0x1d, 0x7b, 0xe7, 0x3c, 0xb9, + 0xb9, 0xc5, 0x97, 0x90, 0x07, 0x42, 0x3e, 0x0c, 0x62, 0x2d, 0xb0, 0xd1, 0x1e, 0xd4, 0x09, 0x28, + 0x45, 0x36, 0x43, 0x68, 0x20, 0x13, 0x43, 0x81, 0x90, 0x7a, 0xe6, 0x55, 0x7e, 0x13, 0xca, 0xea, + 0xee, 0x2f, 0x6a, 0x9d, 0x66, 0xae, 0x47, 0xd2, 0x5a, 0x07, 0x2a, 0x3d, 0x77, 0xe4, 0xf6, 0xbc, + 0xf8, 0x4a, 0x32, 0x04, 0xfd, 0x2d, 0x5a, 0x1f, 0x04, 0x3d, 0x77, 0xe0, 0x1c, 0xbb, 0x03, 0xd7, + 0xef, 0x71, 0xa9, 0xbb, 0xd7, 0x11, 0xb8, 0x46, 0x30, 0xa1, 0x9f, 0xcb, 0x71, 0x2a, 0x2c, 0x52, + 0xe1, 0xe5, 0xe8, 0x15, 0x9a, 0x10, 0x2e, 0x83, 0xe1, 0xd0, 0x13, 0x5a, 0x06, 0x89, 0x61, 0x05, + 0xbb, 0x4a, 0x90, 0x2d, 0x8e, 0xb3, 0x95, 0xc5, 0x17, 0xb4, 0x74, 0x55, 0xea, 0x8a, 0x80, 0x9f, + 0x93, 0x21, 0x61, 0x5a, 0x16, 0x2b, 0x18, 0xb2, 0xd8, 0xdb, 0xb0, 0x30, 0xf6, 0x23, 0x1e, 0xc7, + 0x03, 0xde, 0xd7, 0x63, 0xa9, 0x21, 0x52, 0x4b, 0x17, 0xa8, 0xe1, 0x3c, 0x80, 0x45, 0x32, 0x3a, + 0x44, 0x6e, 0x1c, 0x44, 0x67, 0x5e, 0xe4, 0x44, 0x42, 0x43, 0x22, 0x75, 0x77, 0x01, 0x8b, 0xba, + 0xb2, 0xa4, 0x4b, 0x2a, 0xd2, 0xca, 0x04, 0x7e, 0xc8, 0x7b, 0xdc, 0x3b, 0xe7, 0x7d, 0x94, 0xd3, + 0x0a, 0xf6, 0xf5, 0x54, 0x1d, 0x5b, 0x16, 0xa2, 0xd0, 0x3d, 0x1e, 0x3a, 0xe3, 0x51, 0xdf, 0x15, + 0xc2, 0x4a, 0x93, 0x84, 0x61, 0x7f, 0x3c, 0x7c, 0x4a, 0x10, 0xf6, 0x08, 0x94, 0x24, 0x26, 0xe5, + 0xc3, 0xf9, 0x14, 0x3f, 0x13, 0xc4, 0x6a, 0xd7, 0x25, 0x06, 0x09, 0x8a, 0x29, 0x99, 0xb3, 0x35, + 0x21, 0x73, 0xb6, 0xa1, 0x3c, 0x0a, 0xbd, 0x73, 0x37, 0xe6, 0xed, 0x05, 0x62, 0xe0, 0xf2, 0x53, + 0x70, 0x06, 0xcf, 0xf7, 0x62, 0xcf, 0x8d, 0x83, 0xb0, 0xcd, 0xb0, 0x2c, 0x01, 0xb0, 0xfb, 0xb0, + 0x80, 0x34, 0x12, 0xc5, 0x6e, 0x3c, 0x8e, 0xa4, 0x04, 0xba, 0x88, 0xc4, 0x84, 0x32, 0x74, 0x17, + 0xe1, 0x28, 0x84, 0xb2, 0xef, 0xc2, 0x32, 0x91, 0x05, 0xd6, 0x90, 0x92, 0x35, 0x0a, 0x04, 0x4b, + 0xb8, 0x14, 0x8b, 0x58, 0x2a, 0xe8, 0x5b, 0xca, 0xd7, 0x42, 0x3a, 0xf8, 0x00, 0x56, 0x24, 0x99, + 0x4c, 0xd5, 0xba, 0x8e, 0xb5, 0x96, 0xa8, 0x78, 0xa2, 0xda, 0x7d, 0x58, 0x10, 0x43, 0xf2, 0x7a, + 0x8e, 0xac, 0x2d, 0x4e, 0xc2, 0x32, 0x8e, 0x7e, 0x9e, 0x0a, 0x6c, 0x84, 0x3f, 0xe1, 0x57, 0x82, + 0x94, 0x07, 0xde, 0x09, 0x8f, 0xbd, 0x21, 0x6f, 0xaf, 0x10, 0x71, 0xa8, 0x6f, 0x71, 0xca, 0xc6, + 0x23, 0x2c, 0x69, 0xd3, 0x99, 0xa6, 0x2f, 0xa4, 0xbb, 0x41, 0x10, 0x71, 0x65, 0x5e, 0x6a, 0xdf, + 0x90, 0x07, 0x48, 0x00, 0x25, 0xcb, 0xb2, 0xfe, 0x30, 0x47, 0x77, 0x90, 0x3c, 0xb2, 0x91, 0xa1, + 0x51, 0xd1, 0x61, 0x75, 0x02, 0x7f, 0x70, 0x25, 0xcf, 0x2f, 0x10, 0xe8, 0xc0, 0x1f, 0xe0, 0x01, + 0xf2, 0x7c, 0x13, 0x85, 0xd8, 0x5d, 0x5d, 0x01, 0x11, 0xe9, 0x36, 0xd4, 0x46, 0xe3, 0xe3, 0x81, + 0xd7, 0x23, 0x94, 0x02, 0xb5, 0x42, 0x20, 0x44, 0x10, 0x2a, 0x25, 0x6d, 0x22, 0x61, 0x14, 0x11, + 0xa3, 0x26, 0x61, 0x88, 0x82, 0xec, 0x94, 0x87, 0x78, 0x82, 0xeb, 0x36, 0xfe, 0x6d, 0xad, 0xc1, + 0x52, 0x7a, 0xd0, 0x92, 0xd7, 0xdf, 0x87, 0x8a, 0x64, 0x0f, 0xca, 0xd6, 0xd0, 0x34, 0xcc, 0xbd, + 0x42, 0x2b, 0xd2, 0xe5, 0xd6, 0x6f, 0xcd, 0xc1, 0xa2, 0x84, 0xae, 0x8b, 0x15, 0xe9, 0x8e, 0x87, + 0x43, 0x37, 0xcc, 0xe0, 0x3b, 0xb9, 0xe7, 0xf3, 0x9d, 0xfc, 0x14, 0xdf, 0x49, 0x2b, 0x9b, 0xc4, + 0xb6, 0xd2, 0xca, 0xa6, 0xd8, 0x02, 0x92, 0xff, 0x4d, 0xd3, 0x63, 0x43, 0x82, 0x8f, 0xc8, 0xc4, + 0x39, 0xc5, 0x25, 0x4b, 0x19, 0x5c, 0xd2, 0xe4, 0x71, 0x73, 0x13, 0x3c, 0xee, 0x35, 0xa0, 0xbd, + 0x56, 0x2c, 0xbb, 0x4c, 0x2a, 0x01, 0xc2, 0xa4, 0xfd, 0xf2, 0x2e, 0xcc, 0x4f, 0xb2, 0x15, 0xe2, + 0x5f, 0xcd, 0x0c, 0xa6, 0xe2, 0x0d, 0x39, 0x5e, 0x10, 0x06, 0x72, 0x55, 0x32, 0x15, 0x6f, 0xc8, + 0x77, 0xb1, 0x44, 0xe1, 0x6f, 0x02, 0x50, 0xdf, 0x28, 0x91, 0x00, 0x4a, 0x24, 0x6f, 0xa6, 0xf7, + 0xc2, 0x5c, 0xf5, 0x07, 0xe2, 0x63, 0x1c, 0x72, 0x94, 0x52, 0xaa, 0x58, 0x53, 0xfc, 0xc9, 0x9e, + 0x40, 0x33, 0x18, 0x71, 0xdf, 0x49, 0x8e, 0x77, 0x0d, 0x9b, 0x7a, 0xe3, 0x39, 0x4d, 0xed, 0x28, + 0x5c, 0xbb, 0x21, 0xea, 0xea, 0x4f, 0xb6, 0x47, 0x0b, 0xcf, 0x8d, 0xd6, 0xea, 0xdf, 0xa0, 0xb5, + 0x26, 0x56, 0xd6, 0xdf, 0xd6, 0xdf, 0xcb, 0x41, 0xcd, 0x18, 0x36, 0xbb, 0x0e, 0x0b, 0xeb, 0x07, + 0x07, 0x87, 0x9b, 0xf6, 0xea, 0xd1, 0xce, 0x0f, 0x37, 0x9d, 0xf5, 0xdd, 0x83, 0xee, 0x66, 0xeb, + 0x9a, 0x00, 0xef, 0x1e, 0xac, 0xaf, 0xee, 0x3a, 0x5b, 0x07, 0xf6, 0xba, 0x02, 0xe7, 0xd8, 0x32, + 0x30, 0x7b, 0x73, 0xef, 0xe0, 0x68, 0x33, 0x05, 0xcf, 0xb3, 0x16, 0xd4, 0xd7, 0xec, 0xcd, 0xd5, + 0xf5, 0x6d, 0x09, 0x29, 0xb0, 0x25, 0x68, 0x6d, 0x3d, 0xdd, 0xdf, 0xd8, 0xd9, 0xff, 0xd4, 0x59, + 0x5f, 0xdd, 0x5f, 0xdf, 0xdc, 0xdd, 0xdc, 0x68, 0x15, 0x59, 0x03, 0xaa, 0xab, 0x6b, 0xab, 0xfb, + 0x1b, 0x07, 0xfb, 0x9b, 0x1b, 0xad, 0x92, 0xf5, 0x2b, 0x50, 0x4d, 0x26, 0x5a, 0x83, 0xf2, 0xd3, + 0xfd, 0x27, 0xfb, 0x07, 0x9f, 0xef, 0xb7, 0xae, 0xb1, 0x2a, 0x94, 0xb0, 0xff, 0x56, 0x8e, 0x01, + 0xcc, 0x51, 0x9f, 0xad, 0x3c, 0xab, 0x40, 0x71, 0xed, 0xe0, 0x68, 0xbb, 0x55, 0xb0, 0xfe, 0x2c, + 0x07, 0xd7, 0x71, 0xca, 0xfd, 0x49, 0x26, 0x70, 0x07, 0x6a, 0xbd, 0x20, 0x18, 0x09, 0xe5, 0x26, + 0xb9, 0xc4, 0x4d, 0x90, 0x38, 0xe0, 0xc4, 0x2f, 0x4f, 0x82, 0xb0, 0xc7, 0x25, 0x0f, 0x00, 0x04, + 0x6d, 0x09, 0x88, 0xa0, 0x41, 0x49, 0xc4, 0x84, 0x41, 0x2c, 0xa0, 0x46, 0x30, 0x42, 0x59, 0x86, + 0xb9, 0xe3, 0x90, 0xbb, 0xbd, 0x33, 0x79, 0xfa, 0xe5, 0x17, 0x7b, 0x2b, 0x51, 0xbb, 0x7b, 0x82, + 0xa6, 0x06, 0xbc, 0x8f, 0x47, 0xa0, 0x62, 0xcf, 0x4b, 0xf8, 0xba, 0x04, 0x8b, 0x0b, 0xc0, 0x3d, + 0x76, 0xfd, 0x7e, 0xe0, 0xf3, 0xbe, 0x94, 0xee, 0x13, 0x80, 0x75, 0x08, 0xcb, 0x93, 0xf3, 0x93, + 0xfc, 0xe2, 0x7b, 0x06, 0xbf, 0x20, 0x61, 0xbb, 0x33, 0x9b, 0x14, 0x0c, 0xde, 0xf1, 0xb3, 0x02, + 0x14, 0x85, 0xf0, 0x35, 0x53, 0x4e, 0x33, 0xa5, 0xe9, 0xc2, 0x94, 0xc7, 0x05, 0xb5, 0x7b, 0xba, + 0x95, 0xc9, 0x84, 0x54, 0x45, 0x08, 0xde, 0xc6, 0xba, 0x38, 0xe4, 0xbd, 0x73, 0x69, 0x43, 0xa2, + 0x62, 0x9b, 0xf7, 0xce, 0x51, 0x8d, 0x71, 0x63, 0xaa, 0x4b, 0xe7, 0xbd, 0x1c, 0xb9, 0x31, 0xd6, + 0x94, 0x45, 0x58, 0xaf, 0xac, 0x8b, 0xb0, 0x56, 0x1b, 0xca, 0x9e, 0x7f, 0x1c, 0x8c, 0xfd, 0x3e, + 0x1e, 0xef, 0x8a, 0xad, 0x3e, 0xd1, 0xc1, 0x83, 0x9c, 0x48, 0xdc, 0x1f, 0x74, 0x9a, 0x2b, 0x02, + 0x70, 0x24, 0x6e, 0x90, 0xf7, 0xa0, 0x1a, 0x5d, 0xf9, 0x3d, 0xf3, 0x0c, 0x2f, 0xc9, 0xf5, 0x11, + 0xb3, 0x7f, 0xd0, 0xbd, 0xf2, 0x7b, 0x78, 0x62, 0x2b, 0x91, 0xfc, 0x8b, 0x7d, 0x00, 0x15, 0x6d, + 0x6a, 0x25, 0x0e, 0x7c, 0xc3, 0xac, 0xa1, 0xec, 0xab, 0xa4, 0xd1, 0x6a, 0xd4, 0xce, 0x13, 0x68, + 0xa4, 0x8a, 0x4c, 0x35, 0xb4, 0x41, 0x6a, 0xe8, 0x1b, 0xa6, 0x1a, 0x9a, 0x30, 0x76, 0x59, 0xcd, + 0x54, 0x4b, 0x7f, 0x15, 0x2a, 0x6a, 0x64, 0xe2, 0x38, 0xc9, 0xa3, 0xe0, 0x74, 0xbf, 0xd8, 0x5f, + 0x6f, 0x5d, 0x63, 0xf3, 0x50, 0x5b, 0x5d, 0xc7, 0x13, 0x8a, 0x80, 0x9c, 0x40, 0x39, 0x5c, 0xed, + 0x76, 0x35, 0x24, 0x6f, 0x31, 0x68, 0x89, 0xeb, 0x45, 0x8c, 0x58, 0x3b, 0x53, 0xbe, 0x07, 0x0b, + 0x06, 0x2c, 0xd1, 0xd4, 0xc4, 0x7d, 0x34, 0xa9, 0xa9, 0xa1, 0x5c, 0x4e, 0x25, 0xd6, 0x0a, 0x5c, + 0x17, 0x9f, 0x9b, 0xe7, 0xdc, 0x8f, 0xbb, 0xe3, 0x63, 0x72, 0xa5, 0x79, 0x81, 0x2f, 0xe4, 0xf5, + 0xaa, 0x2e, 0x99, 0x4d, 0x48, 0x0f, 0xa4, 0x52, 0x97, 0xc7, 0xe5, 0xef, 0x18, 0x3d, 0x60, 0xc5, + 0x07, 0xf8, 0x6f, 0x4a, 0xb9, 0xab, 0x6a, 0x90, 0x98, 0xeb, 0xe1, 0xe6, 0xa6, 0xed, 0x1c, 0xec, + 0xef, 0xee, 0xec, 0x0b, 0x66, 0x24, 0xe6, 0x8a, 0x80, 0xad, 0x2d, 0x84, 0xe4, 0xac, 0x16, 0x34, + 0x3f, 0xe5, 0xf1, 0x8e, 0x7f, 0x12, 0xa8, 0x99, 0xfe, 0xdf, 0x12, 0xcc, 0x6b, 0x50, 0xa2, 0x1c, + 0x9e, 0xf3, 0x30, 0xf2, 0x02, 0x1f, 0xe5, 0xbc, 0xaa, 0xad, 0x3e, 0xc5, 0x0d, 0xe2, 0xf5, 0xb9, + 0x1f, 0x7b, 0xf1, 0x95, 0x93, 0xb2, 0x24, 0x35, 0x15, 0x58, 0xde, 0x54, 0x4b, 0x50, 0x72, 0x07, + 0x9e, 0xab, 0x3c, 0x90, 0xf4, 0x21, 0xa0, 0xbd, 0x60, 0x10, 0x84, 0x28, 0xd2, 0x55, 0x6d, 0xfa, + 0x60, 0x8f, 0x60, 0x49, 0x88, 0x96, 0xa6, 0x79, 0x0f, 0xcf, 0x28, 0x19, 0xb5, 0x98, 0x3f, 0x1e, + 0x1e, 0x26, 0x26, 0x3e, 0x51, 0x22, 0xee, 0x27, 0x51, 0x43, 0x0a, 0x24, 0xba, 0x02, 0x69, 0x29, + 0x0b, 0xfe, 0x78, 0xb8, 0x8a, 0x25, 0x1a, 0xff, 0x31, 0x5c, 0x17, 0xf8, 0x5a, 0x84, 0xd1, 0x35, + 0xe6, 0xb1, 0x86, 0x68, 0x6c, 0x47, 0x96, 0xe9, 0x3a, 0x37, 0xa1, 0x4a, 0xa3, 0x12, 0x3b, 0x5e, + 0x22, 0xe9, 0x14, 0x87, 0xc2, 0xc3, 0x68, 0xca, 0x59, 0x38, 0x47, 0x97, 0xed, 0x84, 0xb3, 0xd0, + 0x70, 0x37, 0x56, 0x26, 0xdd, 0x8d, 0x8f, 0xe1, 0xfa, 0x31, 0x8f, 0x62, 0xe7, 0x8c, 0xbb, 0x7d, + 0x1e, 0xe2, 0x89, 0x24, 0xb7, 0x22, 0x49, 0xe1, 0x8b, 0xa2, 0x70, 0x1b, 0xcb, 0x8e, 0x54, 0x91, + 0x90, 0x25, 0xc4, 0xd1, 0xe3, 0x7d, 0x27, 0x0e, 0x1c, 0x14, 0x31, 0xf0, 0x10, 0x57, 0xec, 0x06, + 0x81, 0x8f, 0x82, 0x75, 0x01, 0x4c, 0xe3, 0x9d, 0x86, 0xee, 0xe8, 0x4c, 0xca, 0xc9, 0x1a, 0xef, + 0x53, 0x01, 0x64, 0xaf, 0x40, 0x39, 0xe6, 0x51, 0xec, 0x73, 0xf2, 0xe9, 0x54, 0xd0, 0x66, 0xaf, + 0x40, 0xec, 0x0d, 0x98, 0xc3, 0x3e, 0xa2, 0x76, 0x0b, 0xe9, 0xbd, 0x9e, 0x30, 0x4b, 0xcf, 0xb7, + 0x65, 0x99, 0x10, 0xd8, 0xc6, 0xa1, 0x17, 0xb5, 0xeb, 0xe8, 0xcb, 0xc4, 0xbf, 0xd9, 0xaf, 0x19, + 0x6c, 0x61, 0x11, 0xeb, 0xaa, 0x3b, 0x77, 0x82, 0xd2, 0x7e, 0x29, 0x1c, 0xe2, 0x07, 0xc5, 0x4a, + 0xad, 0x55, 0xb7, 0x3e, 0x84, 0x12, 0xad, 0x8e, 0x20, 0x42, 0x5c, 0xbb, 0x9c, 0x24, 0x42, 0x84, + 0xb6, 0xa1, 0xec, 0xf3, 0xf8, 0x22, 0x08, 0x9f, 0x29, 0x5b, 0xab, 0xfc, 0xb4, 0x7e, 0x8a, 0x46, + 0x02, 0xed, 0x48, 0x26, 0x7d, 0x47, 0x90, 0x07, 0x6d, 0x6f, 0x74, 0xe6, 0x4a, 0xbb, 0x45, 0x05, + 0x01, 0xdd, 0x33, 0x77, 0x8a, 0x3c, 0xf2, 0xd3, 0xbe, 0xe4, 0x37, 0xa0, 0xa9, 0x5c, 0xd7, 0x91, + 0x33, 0xe0, 0x27, 0xb1, 0x24, 0xf7, 0xba, 0xf4, 0x5b, 0x47, 0xbb, 0xfc, 0x24, 0xb6, 0xf6, 0x60, + 0x41, 0x12, 0xe4, 0xc1, 0x88, 0xab, 0xae, 0x3f, 0xca, 0x92, 0x59, 0x6b, 0x8f, 0x17, 0xd3, 0x97, + 0x19, 0xb9, 0xe4, 0x53, 0x82, 0xac, 0xf5, 0x19, 0x30, 0xf3, 0xaa, 0x93, 0xed, 0x49, 0xc9, 0x51, + 0x99, 0xa8, 0x95, 0xa7, 0x47, 0xcb, 0xa7, 0x5e, 0x5f, 0xac, 0x4e, 0x34, 0xee, 0xf5, 0x54, 0x48, + 0x41, 0xc5, 0x56, 0x9f, 0xd6, 0x9f, 0xe6, 0x60, 0x11, 0x1b, 0x53, 0x32, 0xb7, 0x94, 0x26, 0xbe, + 0xf5, 0x20, 0xc5, 0xfe, 0x98, 0xf2, 0x05, 0x7d, 0x7c, 0x73, 0xa3, 0x60, 0x71, 0xca, 0x28, 0xf8, + 0x16, 0xb4, 0xfa, 0x7c, 0xe0, 0x61, 0x38, 0x89, 0xba, 0xae, 0x49, 0xca, 0x9e, 0x57, 0x70, 0xa5, + 0x28, 0xfd, 0x93, 0x1c, 0x2c, 0x90, 0x34, 0x80, 0xea, 0xa2, 0x5c, 0xa8, 0x4f, 0x94, 0x8e, 0x25, + 0x59, 0x95, 0x9c, 0x53, 0x72, 0x4b, 0x22, 0x94, 0x90, 0xb7, 0xaf, 0x49, 0xdd, 0x4b, 0x42, 0xd9, + 0xc7, 0xa8, 0x27, 0xf8, 0x0e, 0x02, 0x33, 0xc2, 0x53, 0xd2, 0x9b, 0xb2, 0x7d, 0x0d, 0x95, 0x08, + 0x1f, 0x41, 0x6b, 0x15, 0xa1, 0xf4, 0x09, 0xb0, 0xb5, 0x05, 0x8d, 0x54, 0x37, 0x29, 0xcb, 0x65, + 0x9d, 0x2c, 0x97, 0x53, 0xde, 0x81, 0xfc, 0xb4, 0x77, 0xe0, 0xef, 0x14, 0x81, 0x09, 0x92, 0x9a, + 0xd8, 0xb5, 0x09, 0xd7, 0x5a, 0x7e, 0xca, 0xb5, 0xf6, 0x08, 0x98, 0x81, 0xa0, 0x3c, 0x7e, 0x05, + 0xed, 0xf1, 0x6b, 0x25, 0xb8, 0xd2, 0xe1, 0xf7, 0x08, 0x96, 0xa4, 0xd0, 0xa8, 0x7d, 0x69, 0x68, + 0x92, 0xa2, 0xfd, 0x61, 0x24, 0x3d, 0x2a, 0x9f, 0x1a, 0x9a, 0xa7, 0x94, 0x5b, 0x4d, 0xa8, 0xd4, + 0x64, 0xc9, 0x41, 0xb7, 0x9a, 0xd0, 0xa2, 0x27, 0xa8, 0x60, 0xee, 0x85, 0x54, 0x50, 0x9e, 0xa2, + 0x02, 0xc3, 0xb0, 0x50, 0x49, 0x1b, 0x16, 0x2c, 0x68, 0x28, 0xe7, 0x19, 0xc5, 0x0c, 0x90, 0x84, + 0x54, 0x93, 0x1e, 0x34, 0x8c, 0x1b, 0xb8, 0x07, 0x2d, 0xa5, 0xfd, 0x6b, 0xd3, 0x05, 0xf9, 0xc3, + 0xa5, 0xf1, 0x68, 0x5d, 0x19, 0x30, 0x52, 0x86, 0xe2, 0xda, 0x84, 0xa1, 0xf8, 0x6d, 0x58, 0x88, + 0x04, 0x11, 0x39, 0x63, 0x5f, 0x06, 0xaf, 0xf0, 0x3e, 0xaa, 0x27, 0x15, 0xbb, 0x85, 0x05, 0x4f, + 0x13, 0xf8, 0xb4, 0x6a, 0xdf, 0x98, 0x56, 0xed, 0xd9, 0x07, 0x89, 0x9f, 0x29, 0x3a, 0xf3, 0x86, + 0x78, 0x71, 0x27, 0x81, 0x1e, 0x72, 0x81, 0xbb, 0x67, 0xde, 0xd0, 0x56, 0x4e, 0x4d, 0xf1, 0x61, + 0xfd, 0x97, 0x1c, 0xb4, 0x04, 0x1d, 0xa4, 0xe8, 0xfc, 0x57, 0x00, 0x4f, 0xe4, 0x4b, 0x92, 0x79, + 0x4d, 0xe0, 0x2a, 0x2a, 0xff, 0x10, 0x90, 0x6c, 0x1d, 0xa1, 0x8b, 0x49, 0x22, 0x6f, 0xa7, 0x89, + 0x3c, 0x61, 0x64, 0xdb, 0xd7, 0x48, 0xc8, 0x16, 0x90, 0x2c, 0xff, 0x5e, 0x31, 0xc3, 0xbf, 0x67, + 0x1c, 0x85, 0x6d, 0x80, 0x27, 0xfc, 0x6a, 0x37, 0xe8, 0xa1, 0x16, 0x74, 0x0b, 0x40, 0x10, 0xe4, + 0x89, 0x3b, 0xf4, 0xa4, 0x05, 0xa3, 0x64, 0x57, 0x9f, 0xf1, 0xab, 0x2d, 0x04, 0x88, 0xdd, 0x10, + 0xc5, 0xc9, 0x79, 0x28, 0xd9, 0x95, 0x67, 0xfc, 0x8a, 0x0e, 0x83, 0x03, 0x8d, 0x27, 0xfc, 0x6a, + 0x83, 0x93, 0xb8, 0x16, 0x84, 0x82, 0x12, 0x42, 0xf7, 0x42, 0xc8, 0x67, 0x29, 0xdf, 0x5c, 0x2d, + 0x74, 0x2f, 0x9e, 0xf0, 0x2b, 0xe5, 0x27, 0x2c, 0x8b, 0xf2, 0x41, 0xd0, 0x93, 0x37, 0x90, 0x8a, + 0x32, 0x48, 0x06, 0x65, 0xcf, 0x3d, 0xc3, 0xbf, 0xad, 0x3f, 0xc9, 0x41, 0x43, 0x8c, 0x1f, 0x19, + 0x9c, 0x58, 0x77, 0x15, 0xac, 0x92, 0x4b, 0x82, 0x55, 0x1e, 0x4b, 0xfe, 0x40, 0xdc, 0x32, 0x3f, + 0x9b, 0x5b, 0xe2, 0x02, 0x13, 0xab, 0x7c, 0x0f, 0xaa, 0x74, 0xb6, 0xc4, 0x61, 0x2d, 0xa4, 0x76, + 0x29, 0x35, 0x21, 0xbb, 0x82, 0x68, 0x4f, 0xc8, 0x37, 0x6e, 0x18, 0xa0, 0x68, 0x89, 0xab, 0xa1, + 0x36, 0x3d, 0x65, 0x6c, 0x43, 0x29, 0xcb, 0xcd, 0xfa, 0x14, 0x6a, 0x06, 0x4d, 0xb1, 0xef, 0x93, + 0x83, 0x9a, 0x06, 0x4f, 0x04, 0x98, 0x26, 0x9a, 0xd4, 0xec, 0xb7, 0xaf, 0xd9, 0x8d, 0x9e, 0x09, + 0x58, 0x9b, 0x83, 0xa2, 0xa8, 0x64, 0x7d, 0x02, 0x0b, 0x46, 0xb3, 0xa4, 0xf1, 0x65, 0x8d, 0x29, + 0x97, 0x35, 0xa6, 0x7f, 0x9a, 0x83, 0x25, 0x59, 0x1b, 0x03, 0x9b, 0x3c, 0x71, 0x5d, 0xef, 0x45, + 0xa7, 0xec, 0x57, 0xa0, 0x21, 0x5a, 0x77, 0x42, 0x7e, 0xea, 0x45, 0x31, 0x57, 0x96, 0xfd, 0x8c, + 0xc3, 0x21, 0xb8, 0xb6, 0x40, 0xb5, 0x25, 0x26, 0xfb, 0x04, 0x6a, 0x58, 0x95, 0x74, 0x52, 0xb9, + 0x2d, 0xed, 0xe9, 0x8a, 0x34, 0xd4, 0xed, 0x6b, 0x36, 0x44, 0xfa, 0x6b, 0xad, 0x0a, 0xe5, 0x38, + 0xf4, 0x4e, 0x4f, 0x79, 0x68, 0x2d, 0xeb, 0xa1, 0x89, 0x93, 0xc6, 0xbb, 0x31, 0x1f, 0x09, 0x21, + 0xc8, 0xfa, 0x6f, 0x39, 0xa8, 0xc9, 0xb3, 0xf3, 0xad, 0xcd, 0xf9, 0x1d, 0x23, 0x32, 0x8f, 0xd4, + 0xcf, 0x24, 0x10, 0xef, 0x2e, 0xcc, 0x0f, 0x85, 0x40, 0x24, 0x04, 0xf6, 0x94, 0x2d, 0xbf, 0xa9, + 0xc0, 0x52, 0x1e, 0x79, 0x00, 0x8b, 0x28, 0x9e, 0x44, 0x4e, 0xec, 0x0d, 0x1c, 0x55, 0x28, 0xa3, + 0xe0, 0x16, 0xa8, 0xe8, 0xc8, 0x1b, 0xec, 0xc9, 0x02, 0x71, 0x4b, 0x47, 0xb1, 0x7b, 0xca, 0xa5, + 0xe8, 0x4b, 0x1f, 0x56, 0x1b, 0x96, 0x27, 0x64, 0x75, 0xa5, 0x67, 0xfc, 0xfd, 0x06, 0xac, 0x4c, + 0x15, 0x49, 0x7d, 0x43, 0xdb, 0xb0, 0x07, 0xde, 0xf0, 0x38, 0xd0, 0xe6, 0xa6, 0x9c, 0x61, 0xc3, + 0xde, 0x15, 0x25, 0xca, 0xdc, 0xc4, 0xe1, 0xba, 0x22, 0x08, 0xb4, 0x17, 0x69, 0x71, 0x3e, 0x8f, + 0xc2, 0xe6, 0x7b, 0x69, 0x46, 0x35, 0xd9, 0x9d, 0x82, 0x9b, 0xd7, 0xdf, 0xe2, 0x68, 0x0a, 0x16, + 0xb1, 0x13, 0x68, 0x6b, 0xba, 0x93, 0xf2, 0x91, 0xa1, 0x9b, 0x88, 0x9e, 0xde, 0x79, 0x41, 0x4f, + 0x29, 0x43, 0x84, 0xbd, 0xac, 0xc8, 0x95, 0x1a, 0xd3, 0xfd, 0x9c, 0xc3, 0xab, 0xaa, 0x1f, 0x94, + 0x75, 0xa6, 0x7b, 0x2b, 0xbe, 0xd4, 0xbc, 0xd0, 0xc0, 0x92, 0xee, 0xf2, 0xa6, 0x6c, 0x58, 0x17, + 0x99, 0xfd, 0x9e, 0xc1, 0xf2, 0x85, 0xeb, 0xc5, 0x6a, 0x7e, 0x86, 0x5a, 0x54, 0xc2, 0xfe, 0x1e, + 0xbf, 0xa0, 0xbf, 0xcf, 0xa9, 0x72, 0x4a, 0xfa, 0x5b, 0xba, 0x98, 0x06, 0x46, 0x9d, 0xff, 0x94, + 0x87, 0x66, 0xba, 0x15, 0x71, 0xa8, 0x25, 0x1f, 0x52, 0xf2, 0x84, 0x94, 0xc7, 0xa5, 0x19, 0x74, + 0x9f, 0xe4, 0x88, 0x69, 0x03, 0x6d, 0x3e, 0xc3, 0x40, 0x6b, 0xda, 0x45, 0x0b, 0x2f, 0xf2, 0xfd, + 0x14, 0x5f, 0xca, 0xf7, 0x53, 0xca, 0xf2, 0xfd, 0xcc, 0x76, 0x18, 0xcc, 0x7d, 0x2b, 0x87, 0x41, + 0x79, 0xb6, 0xc3, 0xa0, 0xf3, 0x97, 0x39, 0x60, 0xd3, 0x94, 0xca, 0x3e, 0x25, 0x5b, 0xb4, 0xcf, + 0x07, 0x92, 0x8b, 0xbd, 0xfb, 0x72, 0xd4, 0xae, 0x36, 0x48, 0xd5, 0x66, 0x0f, 0x61, 0xd1, 0x8c, + 0x9b, 0x35, 0x55, 0x95, 0x86, 0xcd, 0xcc, 0xa2, 0x44, 0xa1, 0x35, 0x1c, 0x5f, 0xc5, 0x17, 0x3a, + 0xbe, 0x4a, 0x2f, 0x74, 0x7c, 0xcd, 0xa5, 0x1d, 0x5f, 0x9d, 0xbf, 0x95, 0x83, 0xc5, 0x0c, 0xa2, + 0xfa, 0xc5, 0xcd, 0x59, 0xd0, 0x42, 0x8a, 0xc5, 0xe4, 0x25, 0x2d, 0x18, 0xdc, 0xa5, 0xf3, 0x15, + 0x34, 0x52, 0x87, 0xe8, 0x17, 0xd7, 0xfd, 0xa4, 0xa2, 0x45, 0xa4, 0x6c, 0x2a, 0x5a, 0x9d, 0xbf, + 0xc8, 0x03, 0x9b, 0x3e, 0xc7, 0xbf, 0xcc, 0x21, 0x4c, 0x2f, 0x52, 0x61, 0x7a, 0x91, 0xfe, 0xff, + 0xdd, 0x2b, 0x6f, 0xc3, 0x82, 0x0c, 0xee, 0x37, 0x1c, 0x0f, 0x44, 0x28, 0x2d, 0x5d, 0xa0, 0x46, + 0xf1, 0xe1, 0xa4, 0xcf, 0xb1, 0x92, 0x0a, 0x6f, 0x36, 0x2e, 0xd6, 0xb4, 0xeb, 0xd1, 0xea, 0x40, + 0x5b, 0x2e, 0xcd, 0xb4, 0xa9, 0xee, 0x77, 0x8a, 0x5a, 0x4b, 0xc6, 0x42, 0x29, 0x14, 0x7f, 0x17, + 0xea, 0xe6, 0x65, 0x23, 0xf7, 0x61, 0xc2, 0xe3, 0x24, 0xc4, 0xe1, 0xc0, 0x38, 0xad, 0xeb, 0x40, + 0x7e, 0x84, 0xbe, 0xae, 0x46, 0x12, 0xc4, 0x73, 0x0c, 0xcf, 0x28, 0x1c, 0xa5, 0x36, 0xff, 0xaf, + 0x40, 0x33, 0x6d, 0xb7, 0x92, 0xa2, 0x5e, 0x96, 0x74, 0x28, 0x6a, 0xa7, 0x0c, 0x59, 0xec, 0xd7, + 0xa0, 0x35, 0x69, 0xf7, 0x92, 0xb1, 0x97, 0x33, 0xea, 0xcf, 0x7b, 0x69, 0x53, 0x18, 0xdb, 0x86, + 0xa5, 0xac, 0xeb, 0x16, 0x77, 0x65, 0xb6, 0x5a, 0xc0, 0xa6, 0xaf, 0x54, 0xf6, 0x91, 0x34, 0x6f, + 0x96, 0xb2, 0x1c, 0x31, 0xc6, 0x62, 0x3f, 0xa0, 0xff, 0x0c, 0x43, 0xe7, 0x39, 0x40, 0x02, 0x63, + 0x2d, 0xa8, 0x1f, 0x1c, 0x6e, 0xee, 0x3b, 0xeb, 0xdb, 0xab, 0xfb, 0xfb, 0x9b, 0xbb, 0xad, 0x6b, + 0x8c, 0x41, 0x13, 0x3d, 0x28, 0x1b, 0x1a, 0x96, 0x13, 0x30, 0x69, 0xfb, 0x55, 0xb0, 0x3c, 0x5b, + 0x82, 0xd6, 0xce, 0xfe, 0x04, 0xb4, 0xc0, 0xda, 0xb0, 0x74, 0xb8, 0x49, 0x4e, 0x97, 0x54, 0xbb, + 0x45, 0x21, 0xc2, 0xc9, 0xe9, 0x0a, 0x11, 0x8e, 0x52, 0x43, 0x24, 0xf5, 0x29, 0xc9, 0xe6, 0x77, + 0x73, 0x70, 0x7d, 0xa2, 0x20, 0x89, 0xff, 0x25, 0xb9, 0x26, 0x2d, 0xd1, 0xd4, 0x11, 0xa8, 0x68, + 0xf8, 0x6d, 0x58, 0xd0, 0xaa, 0xde, 0x04, 0x5f, 0x6a, 0xe9, 0x02, 0x85, 0xfc, 0x10, 0x16, 0x0d, + 0x8d, 0x71, 0xe2, 0x84, 0x32, 0xa3, 0x48, 0x56, 0xb0, 0x56, 0x74, 0x9c, 0xe5, 0xc4, 0xa8, 0xfb, + 0x94, 0x6f, 0x62, 0x16, 0x24, 0xd6, 0xdf, 0xf4, 0x78, 0xd5, 0xa7, 0x50, 0xe5, 0x53, 0x84, 0x90, + 0x1e, 0xad, 0xb9, 0xe1, 0xaa, 0xfb, 0xdf, 0x9f, 0x03, 0xf6, 0xd9, 0x98, 0x87, 0x57, 0x18, 0xdf, + 0x1b, 0xbd, 0x28, 0xe0, 0x45, 0xa9, 0x45, 0xf9, 0x97, 0x8a, 0xe1, 0xcf, 0x8a, 0xa1, 0x2f, 0xbe, + 0x38, 0x86, 0xbe, 0xf4, 0xa2, 0x18, 0xfa, 0xd7, 0xa1, 0xe1, 0x9d, 0xfa, 0x81, 0x60, 0x40, 0x42, + 0x36, 0x89, 0xda, 0x73, 0x77, 0x0a, 0xf7, 0xea, 0x76, 0x5d, 0x02, 0x85, 0x64, 0x12, 0xb1, 0x4f, + 0x12, 0x24, 0xde, 0x3f, 0xc5, 0x7c, 0x0f, 0x93, 0xf5, 0x6c, 0xf6, 0x4f, 0xb9, 0xd4, 0x02, 0xd1, + 0x2e, 0xa2, 0x2a, 0x0b, 0x78, 0xc4, 0xde, 0x80, 0x66, 0x14, 0x8c, 0x85, 0xa8, 0xa7, 0x96, 0x81, + 0xec, 0xc3, 0x75, 0x82, 0x1e, 0x2a, 0x67, 0xc0, 0xe2, 0x38, 0xe2, 0xce, 0xd0, 0x8b, 0x22, 0x71, + 0x41, 0xf7, 0x02, 0x3f, 0x0e, 0x83, 0x81, 0x34, 0xf9, 0x2e, 0x8c, 0x23, 0xbe, 0x47, 0x25, 0xeb, + 0x54, 0xc0, 0xde, 0x4f, 0x86, 0x34, 0x72, 0xbd, 0x30, 0x6a, 0x03, 0x0e, 0x49, 0xcd, 0x14, 0x25, + 0x2a, 0xd7, 0x0b, 0xf5, 0x58, 0xc4, 0x47, 0x34, 0x11, 0xdb, 0x5f, 0x9b, 0x8c, 0xed, 0xff, 0x49, + 0x76, 0x6c, 0x7f, 0x03, 0x9b, 0x7e, 0x24, 0x9b, 0x9e, 0xde, 0xe2, 0x6f, 0x14, 0xe2, 0x3f, 0x9d, + 0xb2, 0xd0, 0xfc, 0x26, 0x29, 0x0b, 0xf3, 0x59, 0x29, 0x0b, 0xef, 0x41, 0x0d, 0x83, 0xc9, 0x9d, + 0x33, 0xcf, 0x8f, 0x95, 0x09, 0xbb, 0x65, 0x46, 0x9b, 0x6f, 0x0b, 0x65, 0x1a, 0x42, 0xf5, 0x67, + 0x34, 0x9d, 0x3d, 0xb0, 0xf0, 0x4b, 0xcc, 0x1e, 0x90, 0x41, 0xef, 0x0f, 0xa0, 0xa2, 0xf6, 0x89, + 0x31, 0x28, 0x9e, 0x84, 0xc1, 0x50, 0x99, 0xf6, 0xc4, 0xdf, 0xac, 0x09, 0xf9, 0x38, 0x90, 0x95, + 0xf3, 0x71, 0x60, 0xfd, 0x06, 0xd4, 0x0c, 0x52, 0x63, 0xaf, 0x91, 0x11, 0x41, 0x48, 0xcb, 0x52, + 0x4b, 0xa6, 0x55, 0xac, 0x4a, 0xe8, 0x4e, 0x5f, 0xf0, 0x9b, 0xbe, 0x17, 0x72, 0xcc, 0xf3, 0x71, + 0x42, 0x7e, 0xce, 0xc3, 0x48, 0x99, 0x5a, 0x5b, 0xba, 0xc0, 0x26, 0xb8, 0xf5, 0xd7, 0x61, 0x31, + 0xb5, 0xb7, 0x92, 0x45, 0xbc, 0x01, 0x73, 0xb8, 0x6e, 0xca, 0x15, 0x96, 0x8e, 0xe2, 0x97, 0x65, + 0x98, 0xb1, 0x49, 0x56, 0x62, 0x67, 0x14, 0x06, 0xc7, 0xd8, 0x49, 0xce, 0xae, 0x49, 0xd8, 0x61, + 0x18, 0x1c, 0x5b, 0x3f, 0x2b, 0x40, 0x61, 0x3b, 0x18, 0x99, 0x11, 0x16, 0xb9, 0xa9, 0x08, 0x0b, + 0xa9, 0x02, 0x38, 0x5a, 0xc4, 0x97, 0x52, 0x1b, 0xda, 0x47, 0x95, 0x98, 0x7f, 0x0f, 0x9a, 0x82, + 0x4f, 0xc4, 0x81, 0xd0, 0xa1, 0x2e, 0xdc, 0x90, 0x62, 0xfa, 0x0b, 0x74, 0xf8, 0xdc, 0x61, 0x7c, + 0x14, 0x6c, 0x11, 0x9c, 0x2d, 0x41, 0x41, 0x0b, 0xb0, 0x58, 0x2c, 0x3e, 0x85, 0x72, 0x8d, 0xd1, + 0x6d, 0x57, 0xd2, 0xd7, 0x23, 0xbf, 0xd8, 0xbb, 0xb0, 0x98, 0x6e, 0x97, 0x58, 0x91, 0x94, 0x48, + 0xcc, 0x86, 0x91, 0x27, 0xdd, 0x00, 0xc1, 0x47, 0x08, 0x47, 0xba, 0x65, 0x4f, 0x38, 0xc7, 0x22, + 0x83, 0xe9, 0x55, 0x52, 0x4c, 0xef, 0x36, 0xd4, 0xe2, 0xc1, 0xb9, 0x33, 0x72, 0xaf, 0x06, 0x81, + 0xdb, 0x97, 0xe7, 0x1b, 0xe2, 0xc1, 0xf9, 0x21, 0x41, 0xd8, 0x43, 0x80, 0xe1, 0x68, 0x24, 0xcf, + 0x1e, 0x9a, 0x1b, 0x13, 0x52, 0xde, 0x3b, 0x3c, 0x24, 0x92, 0xb3, 0xab, 0xc3, 0xd1, 0x88, 0xfe, + 0x64, 0x1b, 0xd0, 0xcc, 0xcc, 0xc5, 0xb9, 0xa5, 0x82, 0xb1, 0x82, 0xd1, 0x83, 0x8c, 0xc3, 0xd9, + 0xe8, 0x99, 0xb0, 0xce, 0xaf, 0x01, 0xfb, 0x39, 0x33, 0x62, 0x8e, 0xa0, 0xaa, 0xc7, 0x67, 0x26, + 0x94, 0x60, 0x78, 0x65, 0x2d, 0x95, 0x50, 0xb2, 0xda, 0xef, 0x87, 0x82, 0x2f, 0xd2, 0x85, 0xa9, + 0x59, 0x3e, 0x18, 0x37, 0xe6, 0x2a, 0xf1, 0x7d, 0xeb, 0xcf, 0x73, 0x50, 0xa2, 0xec, 0x96, 0x37, + 0x61, 0x9e, 0xf0, 0x75, 0xb4, 0x8a, 0xf4, 0x10, 0xd1, 0xbd, 0x7b, 0x24, 0x03, 0x55, 0xc4, 0xb1, + 0x30, 0x32, 0xf3, 0xf2, 0x7a, 0xe7, 0x8d, 0xec, 0xbc, 0xdb, 0x50, 0xd5, 0x5d, 0x1b, 0xa4, 0x53, + 0x51, 0x3d, 0xb3, 0x57, 0xa1, 0x78, 0x16, 0x8c, 0x94, 0x2e, 0x0e, 0xc9, 0x4a, 0xda, 0x08, 0x4f, + 0xc6, 0x22, 0xfa, 0xa0, 0xc1, 0x4b, 0x1d, 0x52, 0x77, 0x82, 0x64, 0x30, 0x3d, 0xc7, 0xb9, 0x8c, + 0x39, 0x3e, 0x85, 0x79, 0xc1, 0x07, 0x0c, 0x4f, 0xed, 0xec, 0x4b, 0xf3, 0x2d, 0x21, 0xe1, 0xf5, + 0x06, 0xe3, 0x3e, 0x37, 0x2d, 0x21, 0x18, 0x3a, 0x21, 0xe1, 0x4a, 0x3d, 0xb0, 0x7e, 0x3f, 0x47, + 0xfc, 0x45, 0xb4, 0xcb, 0xee, 0x41, 0x51, 0xdc, 0x6f, 0x13, 0x96, 0x3a, 0x1d, 0xe7, 0x2a, 0xf0, + 0x6c, 0xc4, 0xc0, 0xfc, 0xd5, 0xf1, 0x30, 0xdd, 0x7a, 0xc3, 0xae, 0xf9, 0xe3, 0xa1, 0x36, 0x26, + 0x7c, 0x47, 0x4d, 0x6b, 0x42, 0x11, 0xa7, 0xd9, 0xeb, 0x63, 0xfa, 0xc0, 0x88, 0xc1, 0x28, 0xa6, + 0x6e, 0x4c, 0x25, 0x05, 0xf6, 0x4f, 0xb9, 0x11, 0x7b, 0xf1, 0x47, 0x79, 0x68, 0xa4, 0x46, 0x84, + 0x41, 0x28, 0xe2, 0x02, 0x20, 0x2b, 0xb0, 0xdc, 0x6f, 0x10, 0x20, 0x29, 0xa8, 0x1b, 0xeb, 0x94, + 0x4f, 0xad, 0x93, 0xf6, 0x49, 0x17, 0x4c, 0x9f, 0xf4, 0x23, 0xa8, 0x26, 0x19, 0x99, 0xe9, 0x21, + 0x89, 0xfe, 0x54, 0xb4, 0x6f, 0x82, 0x94, 0x78, 0xb1, 0x4b, 0xa6, 0x17, 0xfb, 0xfb, 0x86, 0xd3, + 0x73, 0x0e, 0x9b, 0xb1, 0xb2, 0x56, 0xf4, 0x97, 0x13, 0x14, 0xf1, 0x09, 0xd4, 0x8c, 0xc1, 0x9b, + 0xce, 0xcd, 0x5c, 0xca, 0xb9, 0xa9, 0xe3, 0xf2, 0xf3, 0x49, 0x5c, 0xbe, 0xf5, 0x5b, 0x79, 0x68, + 0x88, 0xf3, 0xe5, 0xf9, 0xa7, 0x87, 0xc1, 0xc0, 0xeb, 0xa1, 0x55, 0x58, 0x9f, 0x30, 0x29, 0x68, + 0xa9, 0x73, 0x26, 0x8f, 0x18, 0xc9, 0x59, 0x66, 0xfa, 0x11, 0x31, 0x69, 0x9d, 0x7e, 0x64, 0x41, + 0x43, 0x30, 0xc6, 0x63, 0x37, 0xe2, 0x46, 0xbe, 0xa8, 0x5d, 0x3b, 0xe1, 0x7c, 0xcd, 0x8d, 0x88, + 0x43, 0xbe, 0x0b, 0x8b, 0x02, 0x07, 0x33, 0x2f, 0x86, 0xde, 0x60, 0xe0, 0x11, 0x26, 0x99, 0x1a, + 0x5a, 0x27, 0x9c, 0xdb, 0x6e, 0xcc, 0xf7, 0x44, 0x81, 0x4c, 0x2f, 0xad, 0xf4, 0xbd, 0xc8, 0x3d, + 0x4e, 0x42, 0x85, 0xf4, 0x37, 0xfa, 0x72, 0xdc, 0x4b, 0xc3, 0x97, 0x43, 0x29, 0x58, 0xb5, 0xa1, + 0x7b, 0xa9, 0x7d, 0x39, 0x13, 0x94, 0x54, 0x9e, 0xa4, 0x24, 0xeb, 0xbf, 0xe6, 0xa1, 0x66, 0x90, + 0xe5, 0xcb, 0xdc, 0xae, 0xb7, 0xa6, 0xac, 0xf8, 0x55, 0xd3, 0x60, 0xff, 0x7a, 0xba, 0x4b, 0x74, + 0xf9, 0x52, 0x22, 0xab, 0x41, 0xc0, 0x37, 0xa1, 0x2a, 0x4e, 0xdd, 0x7b, 0x68, 0x14, 0x93, 0x69, + 0xd8, 0x08, 0x38, 0x1c, 0x1f, 0xab, 0xc2, 0xc7, 0x58, 0x58, 0x4a, 0x0a, 0x1f, 0x8b, 0xc2, 0xe7, + 0xc5, 0x07, 0x7e, 0x08, 0x75, 0xd9, 0x2a, 0xee, 0x29, 0x4e, 0x37, 0x39, 0xf5, 0xa9, 0xfd, 0xb6, + 0x6b, 0xd4, 0x1d, 0x6d, 0xbe, 0xac, 0xf8, 0x58, 0x55, 0xac, 0xbc, 0xa8, 0xe2, 0x63, 0xfa, 0xb0, + 0xb6, 0x74, 0xc8, 0x25, 0x86, 0x1b, 0x28, 0x3e, 0xf6, 0x10, 0x16, 0x15, 0xbb, 0x1a, 0xfb, 0xae, + 0xef, 0x07, 0x63, 0xbf, 0xc7, 0x55, 0xc0, 0x3e, 0x93, 0x45, 0x4f, 0x93, 0x12, 0xab, 0xaf, 0x33, + 0xba, 0x28, 0x6c, 0xe1, 0x3e, 0x94, 0x48, 0x2e, 0x27, 0xe1, 0x23, 0x9b, 0x71, 0x11, 0x0a, 0xbb, + 0x07, 0x25, 0x12, 0xcf, 0xf3, 0x33, 0x99, 0x0d, 0x21, 0x58, 0x0f, 0x60, 0x1e, 0x45, 0x4c, 0x83, + 0xe3, 0x3e, 0x4f, 0x2a, 0xb1, 0x96, 0x80, 0xed, 0xd3, 0x21, 0x32, 0xc3, 0x69, 0xfe, 0x67, 0x01, + 0x6a, 0x06, 0x58, 0xb0, 0x45, 0x0c, 0xc0, 0x70, 0xfa, 0x9e, 0x3b, 0xe4, 0xca, 0xf7, 0xd0, 0xb0, + 0x1b, 0x08, 0xdd, 0x90, 0x40, 0x71, 0x29, 0xb8, 0xe7, 0xa7, 0x4e, 0x30, 0x8e, 0x9d, 0x3e, 0x3f, + 0x0d, 0x39, 0x97, 0xc2, 0x52, 0xdd, 0x3d, 0x3f, 0x3d, 0x18, 0xc7, 0x1b, 0x08, 0x13, 0x58, 0x82, + 0xa8, 0x0d, 0x2c, 0x19, 0x33, 0x30, 0x74, 0x2f, 0x13, 0x2c, 0x19, 0xb8, 0x42, 0x4b, 0x54, 0xd4, + 0x81, 0x2b, 0xa4, 0xb6, 0x4c, 0x72, 0xf2, 0xd2, 0x34, 0x27, 0x7f, 0x1f, 0x96, 0x89, 0x93, 0x4b, + 0x1e, 0xe1, 0x4c, 0x90, 0xd4, 0x12, 0x96, 0xca, 0x49, 0x1a, 0xf2, 0x57, 0x4b, 0xcc, 0x40, 0x9d, + 0x8f, 0xc8, 0xfb, 0x29, 0x9d, 0xa8, 0x9c, 0x2d, 0x66, 0x26, 0x1b, 0xef, 0x7a, 0x3f, 0xe5, 0x02, + 0x13, 0x1d, 0xa3, 0x26, 0xa6, 0x0c, 0x43, 0x1d, 0x7a, 0xfe, 0x24, 0xa6, 0x7b, 0x99, 0xc6, 0xac, + 0x4a, 0x4c, 0xf7, 0xd2, 0xc4, 0xfc, 0x00, 0x56, 0x86, 0xbc, 0xef, 0xb9, 0xe9, 0x66, 0x9d, 0x44, + 0x82, 0x58, 0xa2, 0x62, 0xa3, 0x4e, 0x97, 0x34, 0x48, 0xb1, 0x1a, 0x3f, 0x0d, 0x86, 0xc7, 0x1e, + 0x5d, 0x9e, 0xe4, 0xaa, 0x2d, 0xda, 0x4d, 0x7f, 0x3c, 0xfc, 0x11, 0x82, 0x45, 0x95, 0xc8, 0x6a, + 0x40, 0xad, 0x1b, 0x07, 0x23, 0xb5, 0xcd, 0x4d, 0xa8, 0xd3, 0xa7, 0x4c, 0xc7, 0xb8, 0x09, 0x37, + 0x90, 0x36, 0x8f, 0x82, 0x51, 0x30, 0x08, 0x4e, 0xaf, 0x52, 0x06, 0xa5, 0xff, 0x9e, 0x83, 0xc5, + 0x54, 0xa9, 0x3c, 0xe7, 0xef, 0xd3, 0xc1, 0xd2, 0x31, 0xf5, 0x44, 0xce, 0x0b, 0xc6, 0xe5, 0x43, + 0x88, 0x74, 0xaa, 0x54, 0x9c, 0xfd, 0x6a, 0x92, 0x0b, 0xaa, 0x2a, 0x12, 0x6d, 0xb7, 0xa7, 0x69, + 0x5b, 0xd6, 0x57, 0x59, 0xa2, 0xaa, 0x89, 0xbf, 0x2a, 0x43, 0x85, 0xfb, 0x72, 0xca, 0x85, 0x74, + 0x30, 0xa4, 0x69, 0x7c, 0x52, 0x23, 0x48, 0x2c, 0x52, 0x91, 0xf5, 0xaf, 0x72, 0x00, 0xc9, 0xe8, + 0x30, 0x1c, 0x53, 0x5f, 0xa0, 0xf4, 0xae, 0x8a, 0x71, 0x59, 0xbe, 0x06, 0x75, 0x1d, 0x31, 0x96, + 0x5c, 0xc9, 0x35, 0x05, 0x13, 0xf7, 0xf2, 0x5d, 0x98, 0x3f, 0x1d, 0x04, 0xc7, 0x28, 0x3a, 0xc9, + 0x0b, 0x94, 0x92, 0x52, 0x9a, 0x04, 0x56, 0xd7, 0x62, 0x72, 0x81, 0x17, 0x33, 0x83, 0xca, 0xcc, + 0xeb, 0xd8, 0xfa, 0xed, 0xbc, 0x0e, 0x9d, 0x49, 0x56, 0xe2, 0xf9, 0x7a, 0xc6, 0xb7, 0xf1, 0xc0, + 0x3e, 0xcf, 0xf3, 0xf0, 0x09, 0x34, 0x43, 0xe2, 0x8e, 0x8a, 0x75, 0x16, 0x9f, 0xc3, 0x3a, 0x1b, + 0x61, 0xea, 0xca, 0x7d, 0x0b, 0x5a, 0x6e, 0xff, 0x9c, 0x87, 0xb1, 0x87, 0xc6, 0x5a, 0x14, 0xd4, + 0x64, 0xb0, 0x8a, 0x01, 0x47, 0x89, 0xe8, 0x2e, 0xcc, 0xcb, 0x14, 0x21, 0x8d, 0x29, 0x1f, 0x1d, + 0x48, 0xc0, 0x02, 0xd1, 0xfa, 0xb7, 0x2a, 0x56, 0x27, 0xbd, 0xbb, 0xcf, 0x5f, 0x15, 0x73, 0x86, + 0xf9, 0x69, 0xdf, 0x8a, 0x24, 0x24, 0x69, 0x03, 0x96, 0xfc, 0x88, 0x80, 0xd2, 0x02, 0x9c, 0x5e, + 0xd6, 0xe2, 0xcb, 0x2c, 0xab, 0xf5, 0x27, 0x39, 0x28, 0x6f, 0x07, 0x23, 0xa1, 0x97, 0x0b, 0x79, + 0x0e, 0x8f, 0x89, 0x4e, 0xcf, 0x9b, 0x13, 0x9f, 0x3b, 0xfd, 0xe7, 0x87, 0xe5, 0x67, 0xca, 0x1b, + 0x8d, 0xb4, 0xbc, 0xf1, 0x7d, 0xb8, 0x89, 0xde, 0x88, 0x30, 0x18, 0x05, 0xa1, 0x38, 0xaa, 0xee, + 0x80, 0xe4, 0x8e, 0xc0, 0x8f, 0xcf, 0x14, 0xef, 0xbc, 0x71, 0xc2, 0xf9, 0xa1, 0x81, 0xb1, 0xa7, + 0x11, 0x30, 0xd7, 0x64, 0x10, 0x9f, 0x3b, 0xa4, 0x2a, 0x4a, 0xc1, 0x88, 0x38, 0xea, 0xbc, 0x28, + 0xd8, 0x44, 0x38, 0x8a, 0x46, 0xd6, 0x47, 0x50, 0xd5, 0x56, 0x07, 0xf6, 0x36, 0x54, 0xcf, 0x82, + 0x91, 0x34, 0x4d, 0xe4, 0x52, 0xa9, 0x0b, 0x72, 0xd6, 0x76, 0xe5, 0x8c, 0xfe, 0x88, 0xac, 0x9f, + 0x95, 0xa1, 0xbc, 0xe3, 0x9f, 0x07, 0x5e, 0x0f, 0xa3, 0x7d, 0x86, 0x7c, 0x18, 0xa8, 0x3c, 0x45, + 0xf1, 0x37, 0x7a, 0xf4, 0x93, 0xa7, 0x03, 0x0a, 0xd2, 0xa3, 0xaf, 0x1f, 0x0d, 0xb8, 0x0e, 0x73, + 0xa1, 0x99, 0xfb, 0x5f, 0x0a, 0x31, 0xfe, 0x50, 0x2b, 0x6d, 0x25, 0x23, 0xcf, 0x53, 0xb4, 0x45, + 0x39, 0xe9, 0xb8, 0x64, 0x94, 0x7b, 0x52, 0x45, 0x08, 0x2e, 0xd8, 0x2b, 0x50, 0x96, 0x99, 0x02, + 0x14, 0x77, 0x4d, 0x01, 0x83, 0x12, 0x84, 0xd4, 0x10, 0x72, 0xf2, 0x26, 0x69, 0x89, 0x4a, 0xe8, + 0xe9, 0x12, 0xb8, 0x21, 0x68, 0xed, 0x36, 0xd4, 0x08, 0x9f, 0x50, 0x2a, 0x32, 0x3e, 0x07, 0x41, + 0x88, 0x90, 0xf1, 0x84, 0x46, 0x35, 0xf3, 0x09, 0x0d, 0x0c, 0xe7, 0xd2, 0x5c, 0x96, 0xa6, 0x08, + 0xf4, 0x70, 0x82, 0x01, 0x57, 0xef, 0xc7, 0x48, 0xe5, 0x9e, 0xd2, 0xa8, 0x94, 0x72, 0xff, 0x3a, + 0x34, 0x4e, 0xdc, 0xc1, 0xe0, 0xd8, 0xed, 0x3d, 0x23, 0x9d, 0xb4, 0x4e, 0x66, 0x38, 0x05, 0x44, + 0xa5, 0xf4, 0x36, 0xd4, 0x8c, 0x5d, 0xc6, 0xe0, 0x9b, 0xa2, 0x0d, 0xc9, 0xfe, 0x4e, 0x9a, 0x9a, + 0x9a, 0x2f, 0x61, 0x6a, 0x32, 0x82, 0x90, 0xe6, 0xd3, 0x41, 0x48, 0x37, 0x91, 0x9b, 0xca, 0x40, + 0x95, 0x16, 0x65, 0xe9, 0xbb, 0xfd, 0x3e, 0x06, 0xaa, 0xd0, 0x1b, 0x58, 0xb8, 0x78, 0x54, 0xbe, + 0x40, 0x42, 0x2d, 0xc1, 0x08, 0xe5, 0x16, 0xd9, 0x4b, 0x47, 0xae, 0xd7, 0xc7, 0xa0, 0x4f, 0x52, + 0x63, 0xcb, 0xee, 0x30, 0x3e, 0x74, 0xbd, 0x3e, 0xbb, 0x03, 0x75, 0x55, 0x8c, 0xb7, 0xe3, 0x22, + 0xad, 0xbf, 0x2c, 0x16, 0x77, 0xa2, 0x05, 0x0d, 0x8d, 0x31, 0x4c, 0x72, 0xa1, 0x6a, 0x12, 0x05, + 0xe9, 0xe0, 0x3d, 0x74, 0xfe, 0xc7, 0x1c, 0x33, 0x9e, 0x9a, 0x8f, 0x6f, 0xca, 0xb9, 0x4a, 0x2a, + 0x55, 0xff, 0x63, 0xa4, 0x83, 0x4d, 0x98, 0x42, 0x10, 0x23, 0x17, 0xcd, 0x72, 0x4a, 0x10, 0x93, + 0xa8, 0xe8, 0xa2, 0x21, 0x04, 0xf6, 0x91, 0xa1, 0x48, 0xb5, 0x11, 0xf9, 0x95, 0x89, 0xf6, 0x67, + 0xa8, 0x50, 0x82, 0x7a, 0xbd, 0x48, 0xdc, 0x32, 0x11, 0xf7, 0xfb, 0x98, 0x00, 0x55, 0xb1, 0xab, + 0x5e, 0xf4, 0x84, 0x00, 0xbf, 0x58, 0x0d, 0x6b, 0x15, 0xea, 0xe6, 0x34, 0x59, 0x05, 0x8a, 0x07, + 0x87, 0x9b, 0xfb, 0xad, 0x6b, 0xac, 0x06, 0xe5, 0xee, 0xe6, 0xd1, 0xd1, 0xee, 0xe6, 0x46, 0x2b, + 0xc7, 0xea, 0x50, 0xd1, 0x69, 0x1c, 0x79, 0xf1, 0xb5, 0xba, 0xbe, 0xbe, 0x79, 0x78, 0xb4, 0xb9, + 0xd1, 0x2a, 0xfc, 0xa0, 0x58, 0xc9, 0xb7, 0x0a, 0xd6, 0x9f, 0x15, 0xa0, 0x66, 0xac, 0xc2, 0xf3, + 0x99, 0xf1, 0x2d, 0x00, 0x54, 0x69, 0x92, 0x38, 0xa6, 0xa2, 0x5d, 0x15, 0x10, 0xda, 0x7c, 0xd3, + 0x58, 0x5e, 0xa0, 0xe7, 0x1f, 0x94, 0xb1, 0xfc, 0x75, 0x68, 0xd0, 0x4b, 0x0a, 0xa6, 0xbb, 0xae, + 0x64, 0xd7, 0x09, 0x28, 0x59, 0x35, 0xe6, 0x81, 0x21, 0x12, 0x66, 0x08, 0xc8, 0xbc, 0x6a, 0x02, + 0x61, 0x8e, 0x00, 0x26, 0x78, 0x44, 0xc1, 0xe0, 0x9c, 0x13, 0x06, 0x49, 0x84, 0x35, 0x09, 0x3b, + 0x92, 0x89, 0x68, 0x92, 0x1f, 0x1a, 0x89, 0x48, 0x25, 0xbb, 0x4e, 0x40, 0xd9, 0xd1, 0xbb, 0x8a, + 0x80, 0x2a, 0x48, 0x40, 0x2b, 0xd3, 0xd4, 0x90, 0x22, 0x9e, 0xdd, 0x29, 0x7b, 0x56, 0x15, 0x09, + 0xe3, 0x3b, 0xd3, 0xf5, 0x5e, 0x6c, 0xd7, 0x62, 0x6f, 0x03, 0x1b, 0x8e, 0x46, 0x4e, 0x86, 0xa5, + 0xa9, 0x68, 0xcf, 0x0f, 0x47, 0xa3, 0x23, 0xc3, 0x10, 0xf3, 0x0b, 0x30, 0x82, 0x7d, 0x09, 0x6c, + 0x55, 0x1c, 0x60, 0x1c, 0xa2, 0x36, 0xa1, 0x26, 0x6c, 0x39, 0x67, 0xb2, 0xe5, 0x0c, 0xee, 0x97, + 0xcf, 0xe4, 0x7e, 0xcf, 0xe3, 0x13, 0xd6, 0x16, 0xd4, 0x0e, 0x8d, 0x77, 0x5a, 0xee, 0x88, 0x1b, + 0x42, 0xbd, 0xd0, 0x42, 0x77, 0x07, 0x19, 0xb7, 0x42, 0xf9, 0x30, 0x8b, 0x31, 0x9a, 0xbc, 0x31, + 0x1a, 0xeb, 0x5f, 0xe6, 0x28, 0x07, 0x5e, 0x0f, 0x3e, 0x79, 0x1a, 0x46, 0xf9, 0x81, 0x92, 0x7c, + 0xc1, 0x9a, 0xf2, 0xff, 0xc8, 0x54, 0x3f, 0x1c, 0x9a, 0x13, 0x9c, 0x9c, 0x44, 0x5c, 0x65, 0xbe, + 0xd4, 0x10, 0x76, 0x80, 0x20, 0x25, 0x7c, 0x0b, 0x09, 0xdf, 0xa3, 0xf6, 0x23, 0x99, 0x01, 0x23, + 0x84, 0xef, 0x3d, 0xf7, 0x52, 0xf6, 0x1a, 0x09, 0x11, 0x44, 0x1a, 0xaa, 0x55, 0xbe, 0x8f, 0xfe, + 0xb6, 0xfe, 0x99, 0x4c, 0x69, 0x9c, 0x5c, 0xdf, 0xfb, 0x50, 0xd1, 0xad, 0xa6, 0x6f, 0x58, 0x85, + 0xa9, 0xcb, 0xc5, 0x3d, 0x8e, 0x5a, 0x79, 0x6a, 0xc4, 0x74, 0xb8, 0xd0, 0xd9, 0xb0, 0x63, 0x8c, + 0xfa, 0x1d, 0x60, 0x27, 0x5e, 0x38, 0x89, 0x4c, 0x87, 0xad, 0x85, 0x25, 0x06, 0xb6, 0xf5, 0x14, + 0x16, 0x15, 0x97, 0x30, 0x34, 0x82, 0xf4, 0xe6, 0xe5, 0x5e, 0xc0, 0xe4, 0xf3, 0x53, 0x4c, 0xde, + 0xfa, 0xc3, 0x22, 0x94, 0xd5, 0x9b, 0x47, 0x59, 0xef, 0xf4, 0x54, 0xd3, 0xef, 0xf4, 0xb4, 0x53, + 0x6f, 0x3a, 0xe0, 0xd6, 0xcb, 0xfb, 0xfe, 0xee, 0xe4, 0x95, 0x6d, 0x18, 0xcd, 0x53, 0xd7, 0xf6, + 0x32, 0x14, 0x47, 0x6e, 0x7c, 0x86, 0x06, 0x32, 0x22, 0x1e, 0xfc, 0x56, 0xc6, 0xf4, 0x52, 0xda, + 0x98, 0x9e, 0xf5, 0xa6, 0x11, 0x89, 0xa4, 0x53, 0x6f, 0x1a, 0xdd, 0x04, 0x92, 0x2f, 0x8c, 0x78, + 0x98, 0x0a, 0x02, 0xc4, 0x5d, 0x94, 0x16, 0x47, 0x2a, 0x93, 0xe2, 0xc8, 0x4b, 0x8b, 0x0a, 0xef, + 0xc3, 0x1c, 0xe5, 0x03, 0xcb, 0xbc, 0x26, 0x75, 0xa1, 0xc8, 0x35, 0x54, 0xff, 0x53, 0x10, 0xac, + 0x2d, 0x71, 0xcd, 0x07, 0x42, 0x6a, 0xa9, 0x07, 0x42, 0x4c, 0x23, 0x7f, 0x3d, 0x6d, 0xe4, 0xbf, + 0x07, 0x2d, 0xbd, 0xa0, 0x68, 0x32, 0xf3, 0x23, 0x99, 0xd1, 0xd1, 0x54, 0x70, 0xc1, 0x25, 0xf7, + 0xa3, 0xe4, 0x42, 0x6c, 0xa6, 0x2e, 0x44, 0xc1, 0xc3, 0x56, 0xe3, 0x98, 0x0f, 0x47, 0xb1, 0xbc, + 0x10, 0x31, 0xe6, 0xdb, 0x1c, 0x60, 0x3a, 0xe3, 0xaf, 0x01, 0xd5, 0x9d, 0x7d, 0x67, 0x6b, 0x77, + 0xe7, 0xd3, 0xed, 0xa3, 0x56, 0x4e, 0x7c, 0x76, 0x9f, 0xae, 0xaf, 0x6f, 0x6e, 0x6e, 0xe0, 0x8d, + 0x03, 0x30, 0xb7, 0xb5, 0xba, 0x23, 0x6e, 0x9f, 0x82, 0xf5, 0x97, 0x39, 0xa8, 0x19, 0xcd, 0xb3, + 0x0f, 0xf4, 0xaa, 0xd0, 0x1b, 0x12, 0xb7, 0xa6, 0x87, 0xf0, 0x40, 0xb1, 0x62, 0x63, 0x59, 0xf4, + 0x0b, 0x4e, 0xf9, 0x99, 0x2f, 0x38, 0xb1, 0x37, 0x61, 0xde, 0xa5, 0x16, 0xf4, 0x2a, 0x48, 0x73, + 0xb0, 0x04, 0xcb, 0x45, 0xc0, 0x28, 0xb0, 0xe4, 0x3e, 0x11, 0x78, 0x45, 0x15, 0x78, 0xa5, 0xaf, + 0x94, 0xfd, 0xc8, 0xfa, 0x1e, 0x40, 0x32, 0x92, 0xf4, 0x94, 0xaf, 0xa5, 0xa7, 0x9c, 0x33, 0xa6, + 0x9c, 0xb7, 0x36, 0x88, 0x39, 0xc8, 0xe5, 0xd3, 0xfe, 0xe7, 0x77, 0x41, 0xd9, 0x99, 0x1c, 0x8c, + 0xae, 0x1c, 0x0d, 0x78, 0xac, 0x32, 0x1e, 0x17, 0x64, 0xc9, 0x8e, 0x2e, 0x50, 0x09, 0xc8, 0x49, + 0x2b, 0x09, 0x8f, 0x91, 0x84, 0x36, 0xc9, 0x63, 0x24, 0xaa, 0xad, 0xcb, 0xad, 0x0e, 0xb4, 0x37, + 0xb8, 0x68, 0x6d, 0x75, 0x30, 0x98, 0x18, 0x8e, 0x75, 0x13, 0x6e, 0x64, 0x94, 0x49, 0xd3, 0xc2, + 0x67, 0x70, 0x7d, 0x95, 0x92, 0x1b, 0x7f, 0x51, 0x19, 0x16, 0x56, 0x1b, 0x96, 0x27, 0x9b, 0x94, + 0x9d, 0x6d, 0xc1, 0xc2, 0x06, 0x3f, 0x1e, 0x9f, 0xee, 0xf2, 0xf3, 0xa4, 0x23, 0x06, 0xc5, 0xe8, + 0x2c, 0xb8, 0x90, 0xeb, 0x83, 0x7f, 0x8b, 0x93, 0x39, 0x10, 0x38, 0x4e, 0x34, 0xe2, 0x3d, 0x65, + 0xe7, 0x44, 0x48, 0x77, 0xc4, 0x7b, 0xd6, 0x07, 0xc0, 0xcc, 0x76, 0xe4, 0x7a, 0x09, 0xd9, 0x7f, + 0x7c, 0xec, 0x44, 0x57, 0x51, 0xcc, 0x87, 0xea, 0xe1, 0x11, 0x88, 0xc6, 0xc7, 0x5d, 0x82, 0x58, + 0x77, 0xa1, 0x7e, 0xe8, 0x5e, 0xd9, 0xfc, 0x4b, 0x99, 0x3b, 0xb0, 0x02, 0xe5, 0x91, 0x7b, 0x25, + 0x0e, 0xb7, 0x76, 0x79, 0x60, 0xb1, 0xf5, 0x07, 0x45, 0x98, 0x23, 0x4c, 0x76, 0x87, 0xde, 0x06, + 0xf4, 0x7c, 0x3c, 0x5c, 0x8a, 0xfd, 0x19, 0xa0, 0x29, 0x0e, 0x99, 0x9f, 0xe6, 0x90, 0xd2, 0x2c, + 0xa6, 0xde, 0x44, 0x50, 0xc6, 0x69, 0x7f, 0x3c, 0x54, 0x0f, 0x21, 0xb0, 0x57, 0xa0, 0x9a, 0x24, + 0x69, 0x15, 0x93, 0xb7, 0x1f, 0x29, 0x35, 0x2b, 0xed, 0x3e, 0x4c, 0x34, 0x0c, 0x1a, 0x9d, 0x62, + 0xfc, 0x92, 0x09, 0x9a, 0xa0, 0x4c, 0x35, 0xa6, 0xac, 0xb2, 0x52, 0xd2, 0x6a, 0xcc, 0x94, 0xba, + 0x52, 0x79, 0xb1, 0xba, 0x42, 0xf6, 0xb2, 0xe7, 0xa8, 0x2b, 0xf0, 0x12, 0xea, 0xca, 0x4b, 0xb8, + 0xee, 0x6e, 0x40, 0x05, 0x6f, 0x73, 0x83, 0x27, 0x8a, 0x5b, 0x5c, 0xf0, 0xc4, 0x0f, 0x0d, 0x81, + 0x9e, 0xe2, 0x06, 0x6e, 0x26, 0xc7, 0xc4, 0xe6, 0x5f, 0xfe, 0x72, 0x5c, 0x22, 0x5f, 0x40, 0x59, + 0x42, 0x05, 0x41, 0xfb, 0xee, 0x50, 0x3d, 0x2b, 0x83, 0x7f, 0x8b, 0x65, 0xc3, 0xb7, 0x30, 0xbe, + 0x1c, 0x7b, 0x21, 0xef, 0xab, 0xc7, 0x0b, 0x3c, 0x3c, 0xa3, 0x02, 0x22, 0x26, 0x28, 0x94, 0x0b, + 0x3f, 0xb8, 0xf0, 0x65, 0xea, 0x72, 0xd9, 0x8b, 0x9e, 0x88, 0x4f, 0x8b, 0x41, 0x0b, 0x1f, 0x96, + 0x1a, 0x05, 0xa1, 0xba, 0x72, 0xac, 0xff, 0x98, 0x83, 0x96, 0x3c, 0x5d, 0xba, 0xcc, 0x94, 0xed, + 0x4b, 0x33, 0x1e, 0x12, 0xf0, 0x53, 0xef, 0x10, 0x18, 0x96, 0x26, 0x0b, 0x1a, 0x68, 0xcc, 0xd0, + 0x37, 0x0f, 0x19, 0x63, 0x6a, 0x02, 0xb8, 0x25, 0x6f, 0x9f, 0x57, 0xa1, 0xa6, 0xc2, 0x2b, 0x87, + 0xde, 0x40, 0x3d, 0xf0, 0x4a, 0xf1, 0x95, 0x7b, 0xde, 0x40, 0x5d, 0x5c, 0xa1, 0x2b, 0xf3, 0xa3, + 0x72, 0x78, 0x71, 0xd9, 0x6e, 0xcc, 0xad, 0xff, 0x9c, 0x83, 0x05, 0x63, 0x12, 0xf2, 0xc4, 0x7e, + 0x0c, 0x75, 0xfd, 0x96, 0x1b, 0xd7, 0x92, 0xd4, 0x4a, 0x9a, 0xc5, 0x24, 0xd5, 0x6a, 0x3d, 0x0d, + 0x89, 0xc4, 0x60, 0xfa, 0xee, 0x15, 0x8e, 0x37, 0x1a, 0x0f, 0x95, 0xb2, 0xd2, 0x77, 0xaf, 0xb6, + 0x38, 0xef, 0x8e, 0x87, 0x42, 0x15, 0xbd, 0xe0, 0xfc, 0x99, 0x46, 0x20, 0x19, 0x0a, 0x04, 0x4c, + 0x62, 0x58, 0xd0, 0x18, 0x06, 0x7e, 0x7c, 0xa6, 0x51, 0xa4, 0x14, 0x89, 0x40, 0xc2, 0xb1, 0xfe, + 0x47, 0x1e, 0x16, 0xc9, 0x64, 0x26, 0x4d, 0x95, 0x92, 0x69, 0xb5, 0x61, 0x8e, 0xac, 0x87, 0xc4, + 0xb6, 0xb6, 0xaf, 0xd9, 0xf2, 0x9b, 0xbd, 0xff, 0x92, 0x66, 0x3e, 0x95, 0x82, 0x35, 0x63, 0xf9, + 0x0b, 0xd3, 0xcb, 0x3f, 0x7b, 0x79, 0xb3, 0x3c, 0x68, 0xa5, 0x2c, 0x0f, 0xda, 0xcb, 0xf8, 0xad, + 0xa6, 0xf2, 0x94, 0xca, 0x12, 0xc7, 0xc8, 0x53, 0xfa, 0x00, 0x56, 0x52, 0x38, 0xc8, 0xa7, 0xbd, + 0x13, 0x8f, 0xab, 0x9c, 0xf0, 0x25, 0x03, 0xbb, 0xab, 0xca, 0xd6, 0xca, 0x50, 0x8a, 0x7a, 0xc1, + 0x88, 0x5b, 0xcb, 0xb0, 0x94, 0x5e, 0x55, 0x79, 0x41, 0xfc, 0x5e, 0x0e, 0xda, 0x32, 0xde, 0xc1, + 0xf3, 0x4f, 0xb7, 0xbd, 0x28, 0x0e, 0x42, 0xfd, 0xe6, 0xd9, 0x2d, 0x80, 0x28, 0x76, 0x43, 0xa9, + 0x3d, 0x92, 0x5c, 0x5b, 0x45, 0x08, 0x6a, 0x86, 0x37, 0xa0, 0xc2, 0xfd, 0x3e, 0x15, 0x12, 0x35, + 0x94, 0xb9, 0xdf, 0x57, 0x7a, 0xe5, 0x94, 0x3c, 0xdd, 0x48, 0xab, 0x0b, 0x32, 0x61, 0x52, 0xac, + 0x0e, 0x3f, 0xc7, 0x2b, 0xb7, 0xa8, 0x13, 0x26, 0xf7, 0xdc, 0x4b, 0x8c, 0x1e, 0x8c, 0xac, 0x7f, + 0x9c, 0x87, 0xf9, 0x64, 0x7c, 0x94, 0x6d, 0x9d, 0xe2, 0xdc, 0x72, 0x54, 0x09, 0xe7, 0xbe, 0x23, + 0xc9, 0xc1, 0x13, 0xf2, 0xb8, 0x61, 0x48, 0xac, 0xd0, 0xb1, 0xdc, 0xf1, 0x99, 0x05, 0x35, 0x85, + 0x11, 0x8c, 0x63, 0xe3, 0xe9, 0xa1, 0x2a, 0xa1, 0x1c, 0x8c, 0x63, 0xa1, 0x40, 0x09, 0x4d, 0xd2, + 0xf3, 0xa5, 0x0a, 0x53, 0x72, 0x87, 0xf1, 0x0e, 0xbe, 0x68, 0x2c, 0xc0, 0xa2, 0x1a, 0x6d, 0xa4, + 0xc0, 0x12, 0xf8, 0x2d, 0x92, 0x9b, 0x69, 0xe7, 0x50, 0x66, 0x36, 0x85, 0x4a, 0x7a, 0xdc, 0x51, + 0x0b, 0x95, 0xaf, 0x42, 0x8d, 0x1a, 0x4f, 0xd2, 0xd2, 0x8a, 0x76, 0x15, 0x7b, 0xc0, 0x72, 0x69, + 0xd4, 0x09, 0xc6, 0x29, 0x55, 0x16, 0xa8, 0x2b, 0x0c, 0x27, 0xf8, 0x07, 0x39, 0xb8, 0x91, 0xb1, + 0x6d, 0xf2, 0x94, 0xaf, 0xc3, 0xc2, 0x89, 0x2e, 0x54, 0xab, 0x4b, 0x47, 0x7d, 0x59, 0x31, 0xd4, + 0xf4, 0x9a, 0xda, 0xad, 0x93, 0x34, 0x20, 0x51, 0xa2, 0x68, 0x07, 0x53, 0x99, 0x87, 0xa8, 0x44, + 0xd1, 0x36, 0x92, 0xfe, 0x72, 0x08, 0x9d, 0xcd, 0x4b, 0xc1, 0x31, 0xd6, 0xcd, 0x37, 0xb8, 0x15, + 0x19, 0x3d, 0x9e, 0x62, 0x84, 0x2f, 0x36, 0x18, 0xf7, 0x29, 0xc1, 0x4a, 0xb7, 0xf5, 0x6d, 0x1a, + 0xc1, 0xab, 0x53, 0xd4, 0xa1, 0x37, 0xc4, 0x55, 0xf6, 0x63, 0x4f, 0xbf, 0x1d, 0x6e, 0x45, 0x30, + 0xbf, 0x37, 0x1e, 0xc4, 0x5e, 0xf2, 0x9c, 0x38, 0x7b, 0x5f, 0xd6, 0xc1, 0x7e, 0xd4, 0xaa, 0x65, + 0x76, 0x04, 0xba, 0x23, 0x5c, 0xac, 0xa1, 0x68, 0xc8, 0x99, 0xee, 0x6f, 0x7e, 0x98, 0xee, 0xc1, + 0xba, 0x01, 0x2b, 0xc9, 0x17, 0x2d, 0x9b, 0xba, 0x64, 0xfe, 0x45, 0x8e, 0x42, 0x95, 0xd3, 0x4f, + 0x9b, 0xb3, 0x4d, 0x58, 0x8c, 0x3c, 0xff, 0x74, 0xc0, 0xcd, 0xe6, 0x23, 0xb9, 0x08, 0xd7, 0xd3, + 0x63, 0x93, 0xcf, 0x9f, 0xdb, 0x0b, 0x54, 0x23, 0x69, 0x2d, 0x62, 0x6b, 0xb3, 0x06, 0x99, 0x90, + 0xc5, 0xc4, 0x6a, 0x4c, 0x0f, 0x7e, 0x07, 0x9a, 0xe9, 0x8e, 0xd8, 0x87, 0x32, 0xb9, 0x30, 0x19, + 0x55, 0x61, 0x22, 0x4f, 0x2c, 0x21, 0x88, 0x5a, 0xb2, 0xf6, 0x91, 0xf5, 0x0f, 0x73, 0xd0, 0xb6, + 0xb9, 0xa0, 0x5c, 0x63, 0x94, 0x8a, 0x66, 0x3e, 0x9e, 0x6a, 0x75, 0xf6, 0x5c, 0x55, 0xce, 0xa2, + 0x1a, 0xd1, 0x3b, 0x33, 0x37, 0x63, 0xfb, 0xda, 0xd4, 0x8c, 0xd6, 0x2a, 0x30, 0x47, 0x28, 0xd6, + 0x0a, 0x5c, 0x97, 0xe3, 0x51, 0x63, 0x49, 0xbc, 0x81, 0xa9, 0x1e, 0x53, 0xde, 0xc0, 0x0e, 0xb4, + 0xe9, 0xe9, 0x3a, 0x73, 0x12, 0xb2, 0xe2, 0x06, 0xb0, 0x3d, 0xb7, 0xe7, 0x86, 0x41, 0xe0, 0x1f, + 0xf2, 0x50, 0x06, 0x7e, 0xa2, 0x6c, 0x89, 0xce, 0x32, 0x25, 0x04, 0xd3, 0x97, 0x7a, 0x70, 0x2d, + 0xf0, 0x55, 0x9c, 0x0b, 0x7d, 0x59, 0x36, 0x2c, 0xae, 0xb9, 0xcf, 0xb8, 0x6a, 0x49, 0x2d, 0xd1, + 0x27, 0x50, 0x1b, 0xe9, 0x46, 0xd5, 0xba, 0xab, 0x0c, 0xe4, 0xe9, 0x6e, 0x6d, 0x13, 0xdb, 0x7a, + 0x0c, 0x4b, 0xe9, 0x36, 0x25, 0xeb, 0xe8, 0x40, 0x65, 0x28, 0x61, 0x72, 0x74, 0xfa, 0xfb, 0xfe, + 0xd7, 0x50, 0x33, 0x9e, 0x23, 0x64, 0x2b, 0xb0, 0xf8, 0xf9, 0xce, 0xd1, 0xfe, 0x66, 0xb7, 0xeb, + 0x1c, 0x3e, 0x5d, 0x7b, 0xb2, 0xf9, 0x85, 0xb3, 0xbd, 0xda, 0xdd, 0x6e, 0x5d, 0x63, 0xcb, 0xc0, + 0xf6, 0x37, 0xbb, 0x47, 0x9b, 0x1b, 0x29, 0x78, 0x8e, 0xbd, 0x0a, 0x9d, 0xa7, 0xfb, 0x4f, 0xbb, + 0x9b, 0x1b, 0x4e, 0x56, 0xbd, 0x3c, 0xbb, 0x05, 0x37, 0x64, 0x79, 0x46, 0xf5, 0xc2, 0xfd, 0x4f, + 0xa0, 0x35, 0x69, 0x4f, 0x4c, 0x19, 0x60, 0x9f, 0x67, 0xa9, 0xbd, 0xff, 0x6f, 0x0a, 0x00, 0x49, + 0xc0, 0x27, 0x6b, 0xc3, 0xd2, 0xc6, 0xea, 0xd1, 0xea, 0xee, 0x81, 0x18, 0x84, 0x7d, 0x70, 0xb4, + 0xb9, 0x7e, 0xe4, 0xd8, 0x9b, 0x9f, 0xb5, 0xae, 0x65, 0x96, 0x1c, 0x1c, 0x0a, 0x4d, 0x7c, 0x05, + 0x16, 0x77, 0xf6, 0x77, 0x8e, 0x76, 0x56, 0x77, 0x1d, 0xfb, 0xe0, 0xe9, 0xce, 0xfe, 0xa7, 0xf4, + 0xe0, 0x48, 0x81, 0xdd, 0x86, 0x9b, 0x4f, 0x0f, 0xb7, 0xec, 0x83, 0xfd, 0x23, 0xa7, 0xbb, 0xfd, + 0xf4, 0x68, 0x03, 0x9f, 0x2b, 0x59, 0xb7, 0x77, 0x0e, 0xa9, 0xcd, 0xe2, 0xf3, 0x10, 0x44, 0xd3, + 0x25, 0xb1, 0x62, 0x9f, 0x1e, 0x74, 0xbb, 0x3b, 0x87, 0xce, 0x67, 0x4f, 0x37, 0xed, 0x9d, 0xcd, + 0x2e, 0x56, 0x9c, 0xcb, 0x80, 0x0b, 0xfc, 0x32, 0x5b, 0x80, 0xc6, 0xd1, 0xee, 0x0f, 0x9d, 0x83, + 0xfd, 0x9d, 0x83, 0x7d, 0x44, 0xad, 0xa4, 0x41, 0x02, 0xab, 0xca, 0x3a, 0xb0, 0xbc, 0xf9, 0xeb, + 0x47, 0x4e, 0x46, 0xcb, 0x30, 0xa3, 0x4c, 0xd4, 0xab, 0xb1, 0x1b, 0x70, 0xbd, 0x7b, 0xb4, 0x7a, + 0xb4, 0xb3, 0xee, 0xc8, 0x37, 0x8e, 0xc4, 0x26, 0x88, 0x6a, 0xf5, 0xec, 0x22, 0x51, 0xab, 0xc1, + 0x96, 0xa0, 0x75, 0xb8, 0xfa, 0xc5, 0xde, 0xe6, 0xfe, 0x91, 0xb3, 0xba, 0xb1, 0x61, 0x63, 0x85, + 0xe6, 0x14, 0x54, 0xe0, 0xce, 0x8b, 0x8d, 0xda, 0x3b, 0x3c, 0x44, 0x94, 0x96, 0xfa, 0x10, 0x25, + 0x0b, 0x8f, 0x7f, 0xbb, 0x00, 0x4d, 0x0a, 0xbe, 0xa7, 0x1f, 0x6f, 0xe0, 0x21, 0xdb, 0x83, 0xb2, + 0xfc, 0x15, 0x10, 0x76, 0x5d, 0x3f, 0x3b, 0x61, 0xfe, 0xee, 0x48, 0x67, 0x79, 0x12, 0x2c, 0x8f, + 0xdf, 0xe2, 0xdf, 0xfc, 0xd3, 0xbf, 0xf8, 0x47, 0xf9, 0x06, 0xab, 0x3d, 0x3c, 0x7f, 0xef, 0xe1, + 0x29, 0xf7, 0x23, 0xd1, 0xc6, 0x5f, 0x03, 0x48, 0x7e, 0xdb, 0x82, 0xb5, 0xb5, 0x11, 0x71, 0xe2, + 0x87, 0x3f, 0x3a, 0x37, 0x32, 0x4a, 0x64, 0xbb, 0x37, 0xb0, 0xdd, 0x45, 0xab, 0x29, 0xda, 0xf5, + 0x7c, 0x2f, 0xa6, 0xdf, 0xb9, 0xf8, 0x38, 0x77, 0x9f, 0xf5, 0xa1, 0x6e, 0xfe, 0xea, 0x04, 0x53, + 0x4e, 0xf8, 0x8c, 0xdf, 0xcd, 0xe8, 0xdc, 0xcc, 0x2c, 0x53, 0x3c, 0x07, 0xfb, 0xb8, 0x6e, 0xb5, + 0x44, 0x1f, 0x63, 0xc4, 0x48, 0x7a, 0x19, 0x10, 0x17, 0x4e, 0x7e, 0x5c, 0x82, 0xbd, 0x62, 0x70, + 0xc6, 0xa9, 0x9f, 0xb6, 0xe8, 0xdc, 0x9a, 0x51, 0x2a, 0xfb, 0xba, 0x85, 0x7d, 0xad, 0x58, 0x4c, + 0xf4, 0xd5, 0x43, 0x1c, 0xf5, 0xd3, 0x16, 0x1f, 0xe7, 0xee, 0x3f, 0xfe, 0xf3, 0x7b, 0x50, 0xd5, + 0xc1, 0x38, 0xec, 0x37, 0xa1, 0x91, 0xca, 0x8e, 0x60, 0x6a, 0x1a, 0x59, 0xc9, 0x14, 0x9d, 0x57, + 0xb2, 0x0b, 0x65, 0xc7, 0xaf, 0x62, 0xc7, 0x6d, 0xb6, 0x2c, 0x3a, 0x96, 0xd9, 0x07, 0x0f, 0x31, + 0x87, 0x88, 0x1e, 0xf1, 0x78, 0x66, 0xdc, 0x36, 0xd4, 0xd9, 0x2b, 0x93, 0x37, 0x40, 0xaa, 0xb7, + 0x5b, 0x33, 0x4a, 0x65, 0x77, 0xaf, 0x60, 0x77, 0xcb, 0x6c, 0xc9, 0xec, 0x4e, 0x85, 0xce, 0x30, + 0x8e, 0x0f, 0xe7, 0x98, 0x3f, 0xc5, 0xc0, 0x6e, 0x25, 0xcf, 0x9c, 0x64, 0xfc, 0x44, 0x83, 0x26, + 0x91, 0xe9, 0xdf, 0x69, 0xb0, 0xda, 0xd8, 0x15, 0x63, 0xb8, 0x7d, 0xe6, 0x2f, 0x31, 0xb0, 0x63, + 0xa8, 0x19, 0xaf, 0x17, 0xb3, 0x1b, 0x33, 0x5f, 0x5a, 0xee, 0x74, 0xb2, 0x8a, 0xb2, 0xa6, 0x62, + 0xb6, 0xff, 0x50, 0xc8, 0x9e, 0x3f, 0x86, 0xaa, 0x7e, 0x13, 0x97, 0xad, 0x18, 0x6f, 0x14, 0x9b, + 0x6f, 0xf8, 0x76, 0xda, 0xd3, 0x05, 0x59, 0xc4, 0x67, 0xb6, 0x2e, 0x88, 0xef, 0x73, 0xa8, 0x19, + 0xef, 0xde, 0xea, 0x09, 0x4c, 0xbf, 0xad, 0xab, 0x27, 0x90, 0xf1, 0x4c, 0xae, 0xb5, 0x80, 0x5d, + 0xd4, 0x58, 0x15, 0xe9, 0x3b, 0xbe, 0x0c, 0x22, 0xb6, 0x0b, 0xd7, 0xe5, 0xcd, 0x7a, 0xcc, 0xbf, + 0xc9, 0x36, 0x64, 0xfc, 0xfa, 0xc5, 0xa3, 0x1c, 0xfb, 0x04, 0x2a, 0xea, 0x79, 0x63, 0xb6, 0x9c, + 0xfd, 0x4c, 0x73, 0x67, 0x65, 0x0a, 0x2e, 0xaf, 0xc1, 0x2f, 0x00, 0x92, 0x47, 0x76, 0x35, 0x93, + 0x98, 0x7a, 0xb4, 0x57, 0x53, 0xc0, 0xf4, 0x8b, 0xbc, 0xd6, 0x32, 0x4e, 0xb0, 0xc5, 0x90, 0x49, + 0xf8, 0xfc, 0x42, 0xbd, 0x20, 0xf6, 0x13, 0xa8, 0x19, 0xef, 0xec, 0xea, 0xe5, 0x9b, 0x7e, 0xa3, + 0x57, 0x2f, 0x5f, 0xc6, 0xb3, 0xbc, 0x56, 0x07, 0x5b, 0x5f, 0xb2, 0xe6, 0x45, 0xeb, 0x91, 0x77, + 0xea, 0x0f, 0x09, 0x41, 0x6c, 0xd0, 0x19, 0x34, 0x52, 0x8f, 0xe9, 0xea, 0x13, 0x9a, 0xf5, 0x54, + 0xaf, 0x3e, 0xa1, 0x99, 0xef, 0xef, 0x2a, 0x3a, 0xb3, 0x16, 0x44, 0x3f, 0xe7, 0x88, 0x62, 0xf4, + 0xf4, 0x23, 0xa8, 0x19, 0x0f, 0xe3, 0xea, 0xb9, 0x4c, 0xbf, 0xc1, 0xab, 0xe7, 0x92, 0xf5, 0x8e, + 0xee, 0x12, 0xf6, 0xd1, 0xb4, 0x90, 0x14, 0xf0, 0x7d, 0x26, 0xd1, 0xf6, 0x6f, 0x42, 0x33, 0xfd, + 0x56, 0xae, 0x3e, 0xfb, 0x99, 0x8f, 0xee, 0xea, 0xb3, 0x3f, 0xe3, 0x81, 0x5d, 0x49, 0xd2, 0xf7, + 0x17, 0x75, 0x27, 0x0f, 0xbf, 0x92, 0x61, 0xc5, 0x5f, 0xb3, 0xcf, 0x04, 0x83, 0x93, 0xcf, 0x83, + 0xb1, 0x15, 0x83, 0x6a, 0xcd, 0x47, 0xc4, 0xf4, 0x79, 0x99, 0x7a, 0x49, 0x2c, 0x4d, 0xcc, 0xd8, + 0x38, 0xfb, 0x14, 0x16, 0x35, 0x31, 0xeb, 0xf7, 0xbe, 0x22, 0x3d, 0x87, 0xcc, 0x57, 0xc5, 0x3a, + 0xad, 0xc9, 0xd2, 0x47, 0x39, 0xba, 0xfe, 0xf0, 0x95, 0x25, 0xe3, 0xfa, 0x33, 0x9f, 0xfc, 0x32, + 0xae, 0xbf, 0xd4, 0x63, 0x4c, 0x93, 0xd7, 0x5f, 0xec, 0x89, 0x36, 0x7c, 0x98, 0x9f, 0x7c, 0x7d, + 0xeb, 0xd6, 0xac, 0xdc, 0x53, 0x6a, 0xfe, 0xd5, 0xe7, 0xa7, 0xa6, 0xa6, 0x59, 0x91, 0xe2, 0xa6, + 0x0f, 0xa5, 0xf3, 0x90, 0xfd, 0x06, 0xd4, 0xcd, 0xc7, 0x3e, 0x99, 0xc9, 0x13, 0x26, 0x7b, 0xba, + 0x99, 0x59, 0x96, 0xa6, 0x12, 0x56, 0x37, 0xbb, 0x61, 0x3f, 0x84, 0x65, 0xbd, 0xcc, 0x66, 0xde, + 0x61, 0xc4, 0x6e, 0x67, 0x64, 0x23, 0xa6, 0x16, 0xfb, 0xc6, 0xcc, 0x74, 0xc5, 0x47, 0x39, 0x41, + 0x7d, 0xe9, 0x57, 0x07, 0x93, 0x9b, 0x27, 0xeb, 0xb1, 0xc5, 0xe4, 0xe6, 0xc9, 0x7c, 0xaa, 0x50, + 0x51, 0x1f, 0x5b, 0x4c, 0xad, 0x11, 0x85, 0x55, 0xb1, 0x1f, 0xc1, 0xbc, 0x91, 0x54, 0xd9, 0xbd, + 0xf2, 0x7b, 0xfa, 0x24, 0x4d, 0x3f, 0xe9, 0xd3, 0xc9, 0xd2, 0x45, 0xad, 0x15, 0x6c, 0x7f, 0xc1, + 0x4a, 0x2d, 0x8e, 0x38, 0x45, 0xeb, 0x50, 0x33, 0x13, 0x36, 0x9f, 0xd3, 0xee, 0x8a, 0x51, 0x64, + 0xbe, 0x1e, 0xf3, 0x28, 0xc7, 0x76, 0xa1, 0x35, 0xf9, 0xd8, 0x85, 0xe6, 0x29, 0x59, 0x0f, 0x74, + 0x74, 0x26, 0x0a, 0x53, 0x4f, 0x64, 0xb0, 0x43, 0x0a, 0xcc, 0xd5, 0x3f, 0x15, 0x11, 0x84, 0x93, + 0xb7, 0x7a, 0xfa, 0x27, 0x24, 0x74, 0x6b, 0x59, 0x3f, 0x1e, 0x72, 0x2f, 0xf7, 0x28, 0xc7, 0x7e, + 0x37, 0x07, 0xf5, 0x54, 0x82, 0x79, 0x2a, 0xf4, 0x71, 0x62, 0x9e, 0x6d, 0xb3, 0xcc, 0x9c, 0xa8, + 0x65, 0xe3, 0x22, 0xee, 0xde, 0xff, 0x41, 0x6a, 0x93, 0xbe, 0x4a, 0x39, 0x65, 0x1e, 0x4c, 0xfe, + 0x96, 0xc4, 0xd7, 0x93, 0x08, 0xe6, 0x4b, 0x4d, 0x5f, 0x3f, 0xca, 0xb1, 0x7f, 0x97, 0x83, 0x66, + 0xda, 0x3b, 0xa3, 0xa7, 0x9b, 0xe9, 0x07, 0xd2, 0xa4, 0x34, 0xc3, 0xa5, 0xf3, 0x23, 0x1c, 0xe5, + 0xd1, 0x7d, 0x3b, 0x35, 0x4a, 0xf9, 0x5e, 0xe6, 0xcf, 0x37, 0x5a, 0xf6, 0x31, 0xfd, 0x74, 0x93, + 0x72, 0x45, 0xb3, 0xe9, 0x9f, 0xfa, 0xd1, 0xe4, 0x67, 0xfe, 0x30, 0x0e, 0x6e, 0xc2, 0x4f, 0xe8, + 0x37, 0x13, 0x94, 0x67, 0x53, 0x50, 0xf1, 0xcb, 0xd6, 0xb7, 0xde, 0xc0, 0x39, 0xbd, 0x6a, 0xdd, + 0x48, 0xcd, 0x69, 0x52, 0xf0, 0x58, 0xa5, 0xd1, 0xc9, 0xdf, 0xb5, 0x49, 0x6e, 0xce, 0xa9, 0xdf, + 0xba, 0x99, 0x3d, 0xc8, 0x21, 0x0d, 0x52, 0xa2, 0xa7, 0x8e, 0xda, 0x4b, 0x36, 0x63, 0xdd, 0xc7, + 0xb1, 0xbe, 0x61, 0xdd, 0x9e, 0x39, 0xd6, 0x87, 0xe8, 0x69, 0x11, 0x23, 0x3e, 0x04, 0x48, 0x42, + 0x45, 0xd8, 0x44, 0xc0, 0x82, 0x66, 0x40, 0xd3, 0xd1, 0x24, 0xe9, 0xf3, 0xac, 0xe2, 0x1a, 0x44, + 0x8b, 0x3f, 0x26, 0x76, 0xaa, 0x43, 0x29, 0x4c, 0xe9, 0x2b, 0x1d, 0xd5, 0x91, 0x92, 0xbe, 0x26, + 0xdb, 0x4f, 0x31, 0x53, 0x1d, 0x37, 0xf1, 0x14, 0x1a, 0xbb, 0x41, 0xf0, 0x6c, 0x3c, 0xd2, 0xe1, + 0x89, 0x69, 0xf7, 0xe7, 0xb6, 0x1b, 0x9d, 0x75, 0x26, 0x66, 0x61, 0xdd, 0xc1, 0xa6, 0x3a, 0xac, + 0x6d, 0x34, 0xf5, 0xf0, 0xab, 0x24, 0x3e, 0xe5, 0x6b, 0xe6, 0xc2, 0x82, 0xe6, 0xd1, 0x49, 0x0c, + 0x48, 0xba, 0x99, 0x14, 0x67, 0x9e, 0xec, 0x22, 0xa5, 0x26, 0xa8, 0xd1, 0x3e, 0x8c, 0x54, 0x9b, + 0x8f, 0x72, 0xec, 0x10, 0xea, 0x1b, 0xbc, 0x87, 0x89, 0x96, 0xe8, 0x44, 0x5c, 0x4c, 0x39, 0xa4, + 0xc8, 0xfb, 0xd8, 0x69, 0xa4, 0x80, 0xe9, 0x7b, 0x6b, 0xe4, 0x5e, 0x85, 0xfc, 0xcb, 0x87, 0x5f, + 0x49, 0xf7, 0xe4, 0xd7, 0xea, 0xde, 0x52, 0xee, 0xdb, 0xd4, 0xbd, 0x35, 0xe1, 0xef, 0x4d, 0xdd, + 0x5b, 0x53, 0xfe, 0xde, 0xd4, 0x52, 0x2b, 0xf7, 0x31, 0x1b, 0xc0, 0xc2, 0x94, 0x8b, 0x58, 0x5f, + 0x59, 0xb3, 0x1c, 0xcb, 0x9d, 0x3b, 0xb3, 0x11, 0xd2, 0xbd, 0xdd, 0x4f, 0xf7, 0xd6, 0x85, 0x06, + 0x3d, 0x1e, 0x75, 0xcc, 0x29, 0xe5, 0x62, 0xe2, 0xbd, 0x02, 0x33, 0x9f, 0x63, 0xf2, 0x82, 0xc1, + 0xb2, 0xb4, 0x84, 0x83, 0xb9, 0x0e, 0xec, 0xc7, 0x50, 0xfb, 0x94, 0xc7, 0x2a, 0xc7, 0x42, 0xcb, + 0xd8, 0x13, 0x49, 0x17, 0x9d, 0x8c, 0x14, 0x8d, 0x34, 0xcd, 0x60, 0x6b, 0x0f, 0x79, 0xff, 0x94, + 0x13, 0x73, 0x72, 0xbc, 0xfe, 0xd7, 0xec, 0xd7, 0xb1, 0x71, 0x9d, 0xda, 0xb6, 0x6c, 0x04, 0xd1, + 0x9b, 0x8d, 0xcf, 0x4f, 0xc0, 0xb3, 0x5a, 0xf6, 0x83, 0x3e, 0x37, 0x64, 0x3d, 0x1f, 0x6a, 0x46, + 0x0a, 0xac, 0x3e, 0x40, 0xd3, 0x29, 0xcf, 0xfa, 0x00, 0x65, 0x64, 0xcc, 0x5a, 0xf7, 0xb0, 0x1f, + 0x8b, 0xdd, 0x49, 0xfa, 0xa1, 0x2c, 0xd9, 0xa4, 0xa7, 0x87, 0x5f, 0xb9, 0xc3, 0xf8, 0x6b, 0xf6, + 0x39, 0x3e, 0xd1, 0x6a, 0xe6, 0x90, 0x24, 0x4a, 0xc3, 0x64, 0xba, 0x89, 0x5e, 0x2c, 0xa3, 0x28, + 0xad, 0x48, 0x50, 0x57, 0x28, 0xc9, 0x7d, 0x00, 0xd0, 0x8d, 0x83, 0xd1, 0x86, 0xcb, 0x87, 0x81, + 0x9f, 0xf0, 0xda, 0x24, 0xab, 0x21, 0xe1, 0x5f, 0x46, 0x6a, 0x03, 0xfb, 0xdc, 0xd0, 0xb2, 0x52, + 0x69, 0x38, 0x8a, 0xb8, 0x66, 0x26, 0x3e, 0xe8, 0x05, 0xc9, 0x48, 0x7e, 0x78, 0x94, 0x63, 0xab, + 0x00, 0x49, 0x8c, 0x80, 0xd6, 0x99, 0xa6, 0xc2, 0x0f, 0x34, 0xdb, 0xcb, 0x08, 0x28, 0x38, 0x84, + 0x6a, 0xe2, 0x5c, 0x5d, 0x49, 0x32, 0xfa, 0x53, 0xae, 0x58, 0x7d, 0x83, 0x4f, 0xb9, 0x37, 0xad, + 0x16, 0x2e, 0x15, 0xb0, 0x8a, 0x58, 0xaa, 0x13, 0xce, 0x23, 0xe6, 0xc1, 0x22, 0x0d, 0x50, 0x8b, + 0x4b, 0x18, 0x8d, 0xaf, 0x5f, 0xe2, 0x9d, 0xf6, 0x34, 0xea, 0xd3, 0x9c, 0xe9, 0x2f, 0x4b, 0x99, + 0x7e, 0x04, 0xb5, 0x52, 0x26, 0x80, 0x60, 0xcd, 0x43, 0x58, 0x98, 0x72, 0xc9, 0xe8, 0x23, 0x3d, + 0xcb, 0xc7, 0xa6, 0x8f, 0xf4, 0x4c, 0x6f, 0x8e, 0x75, 0x1d, 0xbb, 0x9c, 0xb7, 0x00, 0x55, 0xbd, + 0x0b, 0x2f, 0xee, 0x9d, 0x89, 0xee, 0xfe, 0x75, 0x0e, 0x16, 0x33, 0x9c, 0x2e, 0xec, 0x35, 0x65, + 0x35, 0x98, 0xe9, 0x90, 0xe9, 0x64, 0x1a, 0xe7, 0xad, 0x2e, 0xf6, 0xb3, 0xc7, 0x9e, 0xa4, 0x2e, + 0x36, 0xb2, 0x8d, 0xcb, 0x93, 0xf9, 0x5c, 0xa1, 0x22, 0x53, 0xa2, 0xf8, 0x12, 0x56, 0x68, 0x20, + 0xab, 0x83, 0xc1, 0x84, 0xe3, 0xe0, 0xd5, 0xa9, 0xdf, 0x72, 0x4d, 0x39, 0x43, 0x3a, 0xb3, 0x7f, + 0xeb, 0x75, 0x86, 0x38, 0x4d, 0x43, 0x65, 0x63, 0x68, 0x4d, 0x1a, 0xe4, 0xd9, 0xec, 0xb6, 0x3a, + 0xb7, 0x53, 0xfa, 0x6f, 0x86, 0x11, 0xff, 0x3b, 0xd8, 0xd9, 0x6d, 0xab, 0x93, 0xb5, 0x2e, 0xa4, + 0x12, 0x8b, 0xfd, 0xf8, 0x1b, 0xda, 0x7b, 0x30, 0x31, 0x4f, 0xd5, 0xc1, 0x2c, 0x5f, 0x87, 0xd6, + 0xc0, 0xb3, 0x9d, 0x0f, 0x6f, 0x62, 0xf7, 0x77, 0xac, 0x9b, 0x59, 0xdd, 0x87, 0x54, 0x85, 0x74, + 0xf1, 0x95, 0xc9, 0x73, 0xad, 0x46, 0x70, 0x27, 0x6b, 0xbf, 0x67, 0xea, 0x42, 0x13, 0x6b, 0x7d, + 0x0d, 0x65, 0xbb, 0xba, 0xe9, 0x2d, 0xd0, 0xc7, 0x27, 0xc3, 0x2d, 0xa1, 0x8f, 0x4f, 0x96, 0x7b, + 0x21, 0x2d, 0xd7, 0x28, 0xc7, 0xc2, 0xc7, 0xb9, 0xfb, 0x6b, 0x77, 0x7f, 0xf4, 0x9d, 0x53, 0x2f, + 0x3e, 0x1b, 0x1f, 0x3f, 0xe8, 0x05, 0xc3, 0x87, 0x03, 0x65, 0x6d, 0x94, 0x29, 0x6b, 0x0f, 0x07, + 0x7e, 0xff, 0x21, 0x36, 0x7b, 0x3c, 0x87, 0x3f, 0x3e, 0xfd, 0xdd, 0xff, 0x17, 0x00, 0x00, 0xff, + 0xff, 0xa6, 0xaa, 0x20, 0x1e, 0xae, 0x7a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index d1723014cd..060c7d8384 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -41,7 +41,7 @@ service WalletUnlocker { method should be used to commit the newly generated seed, and create the wallet. */ - rpc GenSeed(GenSeedRequest) returns (GenSeedResponse) { + rpc GenSeed (GenSeedRequest) returns (GenSeedResponse) { option (google.api.http) = { get: "/v1/genseed" }; @@ -61,7 +61,7 @@ service WalletUnlocker { seed, then present it to the user. Once it has been verified by the user, the seed can be fed into this RPC in order to commit the new wallet. */ - rpc InitWallet(InitWalletRequest) returns (InitWalletResponse) { + rpc InitWallet (InitWalletRequest) returns (InitWalletResponse) { option (google.api.http) = { post: "/v1/initwallet" body: "*" @@ -72,7 +72,7 @@ service WalletUnlocker { UnlockWallet is used at startup of lnd to provide a password to unlock the wallet database. */ - rpc UnlockWallet(UnlockWalletRequest) returns (UnlockWalletResponse) { + rpc UnlockWallet (UnlockWalletRequest) returns (UnlockWalletResponse) { option (google.api.http) = { post: "/v1/unlockwallet" body: "*" @@ -195,7 +195,8 @@ message UnlockWalletRequest { */ ChanBackupSnapshot channel_backups = 3; } -message UnlockWalletResponse {} +message UnlockWalletResponse { +} message ChangePasswordRequest { /** @@ -210,7 +211,8 @@ message ChangePasswordRequest { */ bytes new_password = 2; } -message ChangePasswordResponse {} +message ChangePasswordResponse { +} service Lightning { /** lncli: `walletbalance` @@ -418,7 +420,6 @@ service Lightning { }; } - /** OpenChannelSync is a synchronous version of the OpenChannel RPC call. This call is meant to be consumed by clients to the REST proxy. As with all @@ -454,7 +455,7 @@ service Lightning { Alternatively, this can be used to interactively drive PSBT signing for funding for partially complete funding transactions. */ - rpc FundingStateStep(FundingTransitionMsg) returns (FundingStateStepResp); + rpc FundingStateStep (FundingTransitionMsg) returns (FundingStateStepResp); /** ChannelAcceptor dispatches a bi-directional streaming RPC in which @@ -492,7 +493,6 @@ service Lightning { }; } - /** lncli: `sendpayment` SendPayment dispatches a bi-directional streaming RPC for sending payments through the Lightning Network. A single RPC invocation creates a persistent @@ -520,7 +520,7 @@ service Lightning { allows users to specify a full route manually. This can be used for things like rebalancing, and atomic swaps. */ - rpc SendToRoute(stream SendToRouteRequest) returns (stream SendResponse); + rpc SendToRoute (stream SendToRouteRequest) returns (stream SendResponse); /** SendToRouteSync is a synchronous version of SendToRoute. It Will block @@ -660,7 +660,7 @@ service Lightning { send an HTLC, also including the necessary information that should be present within the Sphinx packet encapsulated within the HTLC. */ - rpc QueryRoutes(QueryRoutesRequest) returns (QueryRoutesResponse) { + rpc QueryRoutes (QueryRoutesRequest) returns (QueryRoutesResponse) { option (google.api.http) = { get: "/v1/graph/routes/{pub_key}/{amt}" }; @@ -680,7 +680,7 @@ service Lightning { StopDaemon will send a shutdown request to the interrupt handler, triggering a graceful shutdown of the daemon. */ - rpc StopDaemon(StopRequest) returns (StopResponse); + rpc StopDaemon (StopRequest) returns (StopResponse); /** SubscribeChannelGraph launches a streaming RPC that allows the caller to @@ -690,7 +690,7 @@ service Lightning { channels being advertised, updates in the routing policy for a directional channel edge, and when channels are closed on-chain. */ - rpc SubscribeChannelGraph(GraphTopologySubscription) returns (stream GraphTopologyUpdate); + rpc SubscribeChannelGraph (GraphTopologySubscription) returns (stream GraphTopologyUpdate); /** lncli: `debuglevel` DebugLevel allows a caller to programmatically set the logging verbosity of @@ -704,7 +704,7 @@ service Lightning { FeeReport allows the caller to obtain a report detailing the current fee schedule enforced by the node globally for each channel. */ - rpc FeeReport(FeeReportRequest) returns (FeeReportResponse) { + rpc FeeReport (FeeReportRequest) returns (FeeReportResponse) { option (google.api.http) = { get: "/v1/fees" }; @@ -714,7 +714,7 @@ service Lightning { UpdateChannelPolicy allows the caller to update the fee schedule and channel policies for all channels globally, or a particular channel. */ - rpc UpdateChannelPolicy(PolicyUpdateRequest) returns (PolicyUpdateResponse) { + rpc UpdateChannelPolicy (PolicyUpdateRequest) returns (PolicyUpdateResponse) { option (google.api.http) = { post: "/v1/chanpolicy" body: "*" @@ -733,7 +733,7 @@ service Lightning { the index offset of the last entry. The index offset can be provided to the request to allow the caller to skip a series of records. */ - rpc ForwardingHistory(ForwardingHistoryRequest) returns (ForwardingHistoryResponse) { + rpc ForwardingHistory (ForwardingHistoryRequest) returns (ForwardingHistoryResponse) { option (google.api.http) = { post: "/v1/switch" body: "*" @@ -748,7 +748,7 @@ service Lightning { method once lnd is running, or via the InitWallet and UnlockWallet methods from the WalletUnlocker service. */ - rpc ExportChannelBackup(ExportChannelBackupRequest) returns (ChannelBackup) { + rpc ExportChannelBackup (ExportChannelBackupRequest) returns (ChannelBackup) { option (google.api.http) = { get: "/v1/channels/backup/{chan_point.funding_txid_str}/{chan_point.output_index}" }; @@ -761,7 +761,7 @@ service Lightning { as well, which contains a single encrypted blob containing the backups of each channel. */ - rpc ExportAllChannelBackups(ChanBackupExportRequest) returns (ChanBackupSnapshot) { + rpc ExportAllChannelBackups (ChanBackupExportRequest) returns (ChanBackupSnapshot) { option (google.api.http) = { get: "/v1/channels/backup" }; @@ -772,7 +772,7 @@ service Lightning { snapshot. This method will accept either a packed Single or a packed Multi. Specifying both will result in an error. */ - rpc VerifyChanBackup(ChanBackupSnapshot) returns (VerifyChanBackupResponse) { + rpc VerifyChanBackup (ChanBackupSnapshot) returns (VerifyChanBackupResponse) { option (google.api.http) = { post: "/v1/channels/backup/verify" body: "*" @@ -785,7 +785,7 @@ service Lightning { remaining within the channel. If we are able to unpack the backup, then the new channel will be shown under listchannels, as well as pending channels. */ - rpc RestoreChannelBackups(RestoreChanBackupRequest) returns (RestoreBackupResponse) { + rpc RestoreChannelBackups (RestoreChanBackupRequest) returns (RestoreBackupResponse) { option (google.api.http) = { post: "/v1/channels/backup/restore" body: "*" @@ -801,7 +801,7 @@ service Lightning { ups, but the updated set of encrypted multi-chan backups with the closed channel(s) removed. */ - rpc SubscribeChannelBackups(ChannelBackupSubscription) returns (stream ChanBackupSnapshot) { + rpc SubscribeChannelBackups (ChannelBackupSubscription) returns (stream ChanBackupSnapshot) { }; /** lncli: `bakemacaroon` @@ -809,7 +809,7 @@ service Lightning { write permissions. No first-party caveats are added since this can be done offline. */ - rpc BakeMacaroon(BakeMacaroonRequest) returns (BakeMacaroonResponse) { + rpc BakeMacaroon (BakeMacaroonRequest) returns (BakeMacaroonResponse) { option (google.api.http) = { post: "/v1/macaroon" body: "*" @@ -819,57 +819,57 @@ service Lightning { message Utxo { /// The type of address - AddressType type = 1 [json_name = "address_type"]; + AddressType type = 1; /// The address - string address = 2 [json_name = "address"]; + string address = 2; /// The value of the unspent coin in satoshis - int64 amount_sat = 3 [json_name = "amount_sat"]; + int64 amount_sat = 3; /// The pkscript in hex - string pk_script = 4 [json_name = "pk_script"]; + string pk_script = 4; /// The outpoint in format txid:n - OutPoint outpoint = 5 [json_name = "outpoint"]; + OutPoint outpoint = 5; /// The number of confirmations for the Utxo - int64 confirmations = 6 [json_name = "confirmations"]; + int64 confirmations = 6; } message Transaction { /// The transaction hash - string tx_hash = 1 [ json_name = "tx_hash" ]; + string tx_hash = 1; /// The transaction amount, denominated in satoshis - int64 amount = 2 [ json_name = "amount" ]; + int64 amount = 2; /// The number of confirmations - int32 num_confirmations = 3 [ json_name = "num_confirmations" ]; + int32 num_confirmations = 3; /// The hash of the block this transaction was included in - string block_hash = 4 [ json_name = "block_hash" ]; + string block_hash = 4; /// The height of the block this transaction was included in - int32 block_height = 5 [ json_name = "block_height" ]; + int32 block_height = 5; /// Timestamp of this transaction - int64 time_stamp = 6 [ json_name = "time_stamp" ]; + int64 time_stamp = 6; /// Fees paid for this transaction - int64 total_fees = 7 [ json_name = "total_fees" ]; + int64 total_fees = 7; /// Addresses that received funds for this transaction - repeated string dest_addresses = 8 [ json_name = "dest_addresses" ]; + repeated string dest_addresses = 8; /// The raw transaction hex. - string raw_tx_hex = 9 [ json_name = "raw_tx_hex" ]; + string raw_tx_hex = 9; } message GetTransactionsRequest { } message TransactionDetails { /// The list of transactions relevant to the wallet. - repeated Transaction transactions = 1 [json_name = "transactions"]; + repeated Transaction transactions = 1; } message FeeLimit { @@ -994,10 +994,10 @@ message SendRequest { } message SendResponse { - string payment_error = 1 [json_name = "payment_error"]; - bytes payment_preimage = 2 [json_name = "payment_preimage"]; - Route payment_route = 3 [json_name = "payment_route"]; - bytes payment_hash = 4 [json_name = "payment_hash"]; + string payment_error = 1; + bytes payment_preimage = 2; + Route payment_route = 3; + bytes payment_hash = 4; } message SendToRouteRequest { @@ -1077,36 +1077,36 @@ message ChannelPoint { Txid of the funding transaction. When using REST, this field must be encoded as base64. */ - bytes funding_txid_bytes = 1 [json_name = "funding_txid_bytes"]; + bytes funding_txid_bytes = 1; /** Hex-encoded string representing the byte-reversed hash of the funding transaction. */ - string funding_txid_str = 2 [json_name = "funding_txid_str"]; + string funding_txid_str = 2; } /// The index of the output of the funding transaction - uint32 output_index = 3 [json_name = "output_index"]; + uint32 output_index = 3; } message OutPoint { /// Raw bytes representing the transaction id. - bytes txid_bytes = 1 [json_name = "txid_bytes"]; + bytes txid_bytes = 1; /// Reversed, hex-encoded string representing the transaction id. - string txid_str = 2 [json_name = "txid_str"]; + string txid_str = 2; /// The index of the output on the transaction. - uint32 output_index = 3 [json_name = "output_index"]; + uint32 output_index = 3; } message LightningAddress { /// The identity pubkey of the Lightning node - string pubkey = 1 [json_name = "pubkey"]; + string pubkey = 1; /// The network location of the lightning node, e.g. `69.69.69.69:1337` or `localhost:10011` - string host = 2 [json_name = "host"]; + string host = 2; } message EstimateFeeRequest { @@ -1119,10 +1119,10 @@ message EstimateFeeRequest { message EstimateFeeResponse { /// The total fee in satoshis. - int64 fee_sat = 1 [json_name = "fee_sat"]; + int64 fee_sat = 1; /// The fee rate in satoshi/byte. - int64 feerate_sat_per_byte = 2 [json_name = "feerate_sat_per_byte"]; + int64 feerate_sat_per_byte = 2; } message SendManyRequest { @@ -1137,7 +1137,7 @@ message SendManyRequest { } message SendManyResponse { /// The id of the transaction - string txid = 1 [json_name = "txid"]; + string txid = 1; } message SendCoinsRequest { @@ -1158,11 +1158,11 @@ message SendCoinsRequest { send all the coins under control of the internal wallet to the specified address. */ - bool send_all = 6; + bool send_all = 6; } message SendCoinsResponse { /// The transaction ID of the transaction - string txid = 1 [json_name = "txid"]; + string txid = 1; } message ListUnspentRequest { @@ -1174,7 +1174,7 @@ message ListUnspentRequest { } message ListUnspentResponse { /// A list of utxos - repeated Utxo utxos = 1 [json_name = "utxos"]; + repeated Utxo utxos = 1; } /** @@ -1184,10 +1184,10 @@ message ListUnspentResponse { - `np2wkh`: Pay to nested witness key hash (`NESTED_PUBKEY_HASH` = 1) */ enum AddressType { - WITNESS_PUBKEY_HASH = 0; - NESTED_PUBKEY_HASH = 1; - UNUSED_WITNESS_PUBKEY_HASH = 2; - UNUSED_NESTED_PUBKEY_HASH = 3; + WITNESS_PUBKEY_HASH = 0; + NESTED_PUBKEY_HASH = 1; + UNUSED_WITNESS_PUBKEY_HASH = 2; + UNUSED_NESTED_PUBKEY_HASH = 3; } message NewAddressRequest { @@ -1196,7 +1196,7 @@ message NewAddressRequest { } message NewAddressResponse { /// The newly generated wallet address - string address = 1 [json_name = "address"]; + string address = 1; } message SignMessageRequest { @@ -1204,11 +1204,11 @@ message SignMessageRequest { The message to be signed. When using REST, this field must be encoded as base64. */ - bytes msg = 1 [ json_name = "msg" ]; + bytes msg = 1; } message SignMessageResponse { /// The signature for the given message - string signature = 1 [ json_name = "signature" ]; + string signature = 1; } message VerifyMessageRequest { @@ -1216,17 +1216,17 @@ message VerifyMessageRequest { The message over which the signature is to be verified. When using REST, this field must be encoded as base64. */ - bytes msg = 1 [ json_name = "msg" ]; + bytes msg = 1; /// The signature to be verified over the given message - string signature = 2 [ json_name = "signature" ]; + string signature = 2; } message VerifyMessageResponse { /// Whether the signature was valid over the given message - bool valid = 1 [ json_name = "valid" ]; + bool valid = 1; /// The pubkey recovered from the signature - string pubkey = 2 [ json_name = "pubkey" ]; + string pubkey = 2; } message ConnectPeerRequest { @@ -1242,47 +1242,47 @@ message ConnectPeerResponse { message DisconnectPeerRequest { /// The pubkey of the node to disconnect from - string pub_key = 1 [json_name = "pub_key"]; + string pub_key = 1; } message DisconnectPeerResponse { } message HTLC { - bool incoming = 1 [json_name = "incoming"]; - int64 amount = 2 [json_name = "amount"]; - bytes hash_lock = 3 [json_name = "hash_lock"]; - uint32 expiration_height = 4 [json_name = "expiration_height"]; + bool incoming = 1; + int64 amount = 2; + bytes hash_lock = 3; + uint32 expiration_height = 4; } message Channel { /// Whether this channel is active or not - bool active = 1 [json_name = "active"]; + bool active = 1; /// The identity pubkey of the remote node - string remote_pubkey = 2 [json_name = "remote_pubkey"]; + string remote_pubkey = 2; /** The outpoint (txid:index) of the funding transaction. With this value, Bob will be able to generate a signature for Alice's version of the commitment transaction. */ - string channel_point = 3 [json_name = "channel_point"]; + string channel_point = 3; /** The unique channel ID for the channel. The first 3 bytes are the block height, the next 3 the index within the block, and the last 2 bytes are the output index for the channel. */ - uint64 chan_id = 4 [json_name = "chan_id", jstype = JS_STRING]; + uint64 chan_id = 4 [jstype = JS_STRING]; /// The total amount of funds held in this channel - int64 capacity = 5 [json_name = "capacity"]; + int64 capacity = 5; /// This node's current balance in this channel - int64 local_balance = 6 [json_name = "local_balance"]; + int64 local_balance = 6; /// The counterparty's current balance in this channel - int64 remote_balance = 7 [json_name = "remote_balance"]; + int64 remote_balance = 7; /** The amount calculated to be paid in fees for the current set of commitment @@ -1290,63 +1290,63 @@ message Channel { allow the fee amount to be removed and recalculated with each channel state update, including updates that happen after a system restart. */ - int64 commit_fee = 8 [json_name = "commit_fee"]; + int64 commit_fee = 8; /// The weight of the commitment transaction - int64 commit_weight = 9 [json_name = "commit_weight"]; + int64 commit_weight = 9; /** The required number of satoshis per kilo-weight that the requester will pay at all times, for both the funding transaction and commitment transaction. This value can later be updated once the channel is open. */ - int64 fee_per_kw = 10 [json_name = "fee_per_kw"]; + int64 fee_per_kw = 10; /// The unsettled balance in this channel - int64 unsettled_balance = 11 [json_name = "unsettled_balance"]; + int64 unsettled_balance = 11; /** The total number of satoshis we've sent within this channel. */ - int64 total_satoshis_sent = 12 [json_name = "total_satoshis_sent"]; + int64 total_satoshis_sent = 12; /** The total number of satoshis we've received within this channel. */ - int64 total_satoshis_received = 13 [json_name = "total_satoshis_received"]; + int64 total_satoshis_received = 13; /** The total number of updates conducted within this channel. */ - uint64 num_updates = 14 [json_name = "num_updates"]; + uint64 num_updates = 14; /** The list of active, uncleared HTLCs currently pending within the channel. */ - repeated HTLC pending_htlcs = 15 [json_name = "pending_htlcs"]; + repeated HTLC pending_htlcs = 15; /** The CSV delay expressed in relative blocks. If the channel is force closed, we will need to wait for this many blocks before we can regain our funds. */ - uint32 csv_delay = 16 [json_name = "csv_delay"]; + uint32 csv_delay = 16; /// Whether this channel is advertised to the network or not. - bool private = 17 [json_name = "private"]; + bool private = 17; /// True if we were the ones that created the channel. - bool initiator = 18 [json_name = "initiator"]; + bool initiator = 18; /// A set of flags showing the current state of the channel. - string chan_status_flags = 19 [json_name = "chan_status_flags"]; + string chan_status_flags = 19; /// The minimum satoshis this node is required to reserve in its balance. - int64 local_chan_reserve_sat = 20 [json_name = "local_chan_reserve_sat"]; + int64 local_chan_reserve_sat = 20; /** The minimum satoshis the other node is required to reserve in its balance. */ - int64 remote_chan_reserve_sat = 21 [json_name = "remote_chan_reserve_sat"]; + int64 remote_chan_reserve_sat = 21; /** If true, then this channel uses the modern commitment format where the key @@ -1354,20 +1354,20 @@ message Channel { back up and recovery easier as when the channel is closed, the funds go directly to that key. */ - bool static_remote_key = 22 [json_name = "static_remote_key"]; + bool static_remote_key = 22; /** The number of seconds that the channel has been monitored by the channel scoring system. Scores are currently not persisted, so this value may be less than the lifetime of the channel [EXPERIMENTAL]. */ - int64 lifetime = 23 [json_name = "lifetime"]; + int64 lifetime = 23; /** The number of seconds that the remote peer has been observed as being online by the channel scoring system over the lifetime of the channel [EXPERIMENTAL]. */ - int64 uptime = 24 [json_name = "uptime"]; + int64 uptime = 24; /** Close address is the address that we will enforce payout to on cooperative @@ -1376,7 +1376,7 @@ message Channel { request. If this value is not set, you can still choose a payout address by cooperatively closing with the delivery_address field set. */ - string close_address = 25 [json_name ="close_address"]; + string close_address = 25; } @@ -1394,36 +1394,36 @@ message ListChannelsRequest { } message ListChannelsResponse { /// The list of active channels - repeated Channel channels = 11 [json_name = "channels"]; + repeated Channel channels = 11; } message ChannelCloseSummary { /// The outpoint (txid:index) of the funding transaction. - string channel_point = 1 [json_name = "channel_point"]; + string channel_point = 1; /// The unique channel ID for the channel. - uint64 chan_id = 2 [json_name = "chan_id", jstype = JS_STRING]; + uint64 chan_id = 2 [jstype = JS_STRING]; /// The hash of the genesis block that this channel resides within. - string chain_hash = 3 [json_name = "chain_hash"]; + string chain_hash = 3; /// The txid of the transaction which ultimately closed this channel. - string closing_tx_hash = 4 [json_name = "closing_tx_hash"]; + string closing_tx_hash = 4; /// Public key of the remote peer that we formerly had a channel with. - string remote_pubkey = 5 [json_name = "remote_pubkey"]; + string remote_pubkey = 5; /// Total capacity of the channel. - int64 capacity = 6 [json_name = "capacity"]; + int64 capacity = 6; /// Height at which the funding transaction was spent. - uint32 close_height = 7 [json_name = "close_height"]; + uint32 close_height = 7; /// Settled balance at the time of channel closure - int64 settled_balance = 8 [json_name = "settled_balance"]; + int64 settled_balance = 8; /// The sum of all the time-locked outputs at the time of channel closure - int64 time_locked_balance = 9 [json_name = "time_locked_balance"]; + int64 time_locked_balance = 9; enum ClosureType { COOPERATIVE_CLOSE = 0; @@ -1435,7 +1435,7 @@ message ChannelCloseSummary { } /// Details on how the channel was closed. - ClosureType close_type = 10 [json_name = "close_type"]; + ClosureType close_type = 10; enum Initiator { UNKNOWN = 0; @@ -1449,7 +1449,7 @@ message ChannelCloseSummary { this value may be unknown if the channel was closed before we migrated to store open channel information after close. */ - Initiator open_initiator = 11 [json_name = "open_initiator"]; + Initiator open_initiator = 11; /** Close initiator indicates which party initiated the close. This value will @@ -1458,7 +1458,7 @@ message ChannelCloseSummary { initiated a close, and it is possible for both to initiate cooperative or force closes, although only one party's close will be confirmed on chain. */ - Initiator close_initiator = 12 [json_name = "close_initiator"]; + Initiator close_initiator = 12; } message ClosedChannelsRequest { @@ -1470,34 +1470,34 @@ message ClosedChannelsRequest { bool abandoned = 6; } -message ClosedChannelsResponse { - repeated ChannelCloseSummary channels = 1 [json_name = "channels"]; +message ClosedChannelsResponse { + repeated ChannelCloseSummary channels = 1; } message Peer { /// The identity pubkey of the peer - string pub_key = 1 [json_name = "pub_key"]; + string pub_key = 1; /// Network address of the peer; eg `127.0.0.1:10011` - string address = 3 [json_name = "address"]; + string address = 3; /// Bytes of data transmitted to this peer - uint64 bytes_sent = 4 [json_name = "bytes_sent"]; + uint64 bytes_sent = 4; /// Bytes of data transmitted from this peer - uint64 bytes_recv = 5 [json_name = "bytes_recv"]; + uint64 bytes_recv = 5; /// Satoshis sent to this peer - int64 sat_sent = 6 [json_name = "sat_sent"]; + int64 sat_sent = 6; /// Satoshis received from this peer - int64 sat_recv = 7 [json_name = "sat_recv"]; + int64 sat_recv = 7; /// A channel is inbound if the counterparty initiated the channel - bool inbound = 8 [json_name = "inbound"]; + bool inbound = 8; /// Ping time to this peer - int64 ping_time = 9 [json_name = "ping_time"]; + int64 ping_time = 9; enum SyncType { /** @@ -1517,17 +1517,17 @@ message Peer { } // The type of sync we are currently performing with this peer. - SyncType sync_type = 10 [json_name = "sync_type"]; + SyncType sync_type = 10; /// Features advertised by the remote peer in their init message. - map features = 11 [json_name = "features"]; + map features = 11; } message ListPeersRequest { } message ListPeersResponse { /// The list of currently connected peers - repeated Peer peers = 1 [json_name = "peers"]; + repeated Peer peers = 1; } message PeerEventSubscription { @@ -1535,14 +1535,14 @@ message PeerEventSubscription { message PeerEvent { /// The identity pubkey of the peer. - string pub_key = 1 [json_name = "pub_key"]; + string pub_key = 1; enum EventType { PEER_ONLINE = 0; PEER_OFFLINE = 1; } - EventType type = 2 [ json_name = "type" ]; + EventType type = 2; } message GetInfoRequest { @@ -1550,71 +1550,71 @@ message GetInfoRequest { message GetInfoResponse { /// The version of the LND software that the node is running. - string version = 14 [ json_name = "version" ]; + string version = 14; /// The identity pubkey of the current node. - string identity_pubkey = 1 [json_name = "identity_pubkey"]; + string identity_pubkey = 1; /// If applicable, the alias of the current node, e.g. "bob" - string alias = 2 [json_name = "alias"]; + string alias = 2; /// The color of the current node in hex code format - string color = 17 [json_name = "color"]; + string color = 17; /// Number of pending channels - uint32 num_pending_channels = 3 [json_name = "num_pending_channels"]; + uint32 num_pending_channels = 3; /// Number of active channels - uint32 num_active_channels = 4 [json_name = "num_active_channels"]; + uint32 num_active_channels = 4; /// Number of inactive channels - uint32 num_inactive_channels = 15 [json_name = "num_inactive_channels"]; + uint32 num_inactive_channels = 15; /// Number of peers - uint32 num_peers = 5 [json_name = "num_peers"]; + uint32 num_peers = 5; /// The node's current view of the height of the best block - uint32 block_height = 6 [json_name = "block_height"]; + uint32 block_height = 6; /// The node's current view of the hash of the best block - string block_hash = 8 [json_name = "block_hash"]; + string block_hash = 8; /// Timestamp of the block best known to the wallet - int64 best_header_timestamp = 13 [ json_name = "best_header_timestamp" ]; + int64 best_header_timestamp = 13; /// Whether the wallet's view is synced to the main chain - bool synced_to_chain = 9 [json_name = "synced_to_chain"]; + bool synced_to_chain = 9; // Whether we consider ourselves synced with the public channel graph. - bool synced_to_graph = 18 [json_name = "synced_to_graph"]; + bool synced_to_graph = 18; /** Whether the current node is connected to testnet. This field is deprecated and the network field should be used instead **/ - bool testnet = 10 [json_name = "testnet", deprecated = true]; + bool testnet = 10 [deprecated = true]; reserved 11; /// A list of active chains the node is connected to - repeated Chain chains = 16 [json_name = "chains"]; + repeated Chain chains = 16; /// The URIs of the current node. - repeated string uris = 12 [json_name = "uris"]; + repeated string uris = 12; /* Features that our node has advertised in our init message, node announcements and invoices. */ - map features = 19 [json_name = "features"]; + map features = 19; } message Chain { /// The blockchain the node is on (eg bitcoin, litecoin) - string chain = 1 [json_name = "chain"]; + string chain = 1; /// The network the node is on (eg regtest, testnet, mainnet) - string network = 2 [json_name = "network"]; + string network = 2; } message ConfirmationUpdate { @@ -1625,13 +1625,13 @@ message ConfirmationUpdate { } message ChannelOpenUpdate { - ChannelPoint channel_point = 1 [json_name = "channel_point"]; + ChannelPoint channel_point = 1; } message ChannelCloseUpdate { - bytes closing_txid = 1 [json_name = "closing_txid"]; + bytes closing_txid = 1; - bool success = 2 [json_name = "success"]; + bool success = 2; } message CloseChannelRequest { @@ -1657,19 +1657,19 @@ message CloseChannelRequest { is set, the request to close will fail because the channel must pay out to the upfront shutdown addresss. */ - string delivery_address = 5 [json_name = "delivery_address"]; + string delivery_address = 5; } message CloseStatusUpdate { oneof update { - PendingUpdate close_pending = 1 [json_name = "close_pending"]; - ChannelCloseUpdate chan_close = 3 [json_name = "chan_close"]; + PendingUpdate close_pending = 1; + ChannelCloseUpdate chan_close = 3; } } message PendingUpdate { - bytes txid = 1 [json_name = "txid"]; - uint32 output_index = 2 [json_name = "output_index"]; + bytes txid = 1; + uint32 output_index = 2; } message OpenChannelRequest { @@ -1677,19 +1677,19 @@ message OpenChannelRequest { The pubkey of the node to open a channel with. When using REST, this field must be encoded as base64. */ - bytes node_pubkey = 2 [json_name = "node_pubkey"]; + bytes node_pubkey = 2; /** The hex encoded pubkey of the node to open a channel with. Deprecated now that the REST gateway supports base64 encoding of bytes fields. */ - string node_pubkey_string = 3 [json_name = "node_pubkey_string", deprecated = true]; + string node_pubkey_string = 3 [deprecated = true]; /// The number of satoshis the wallet should commit to the channel - int64 local_funding_amount = 4 [json_name = "local_funding_amount"]; + int64 local_funding_amount = 4; /// The number of satoshis to push to the remote side as part of the initial commitment state - int64 push_sat = 5 [json_name = "push_sat"]; + int64 push_sat = 5; /// The target number of blocks that the funding transaction should be confirmed by. int32 target_conf = 6; @@ -1698,19 +1698,19 @@ message OpenChannelRequest { int64 sat_per_byte = 7; /// Whether this channel should be private, not announced to the greater network. - bool private = 8 [json_name = "private"]; + bool private = 8; /// The minimum value in millisatoshi we will require for incoming HTLCs on the channel. - int64 min_htlc_msat = 9 [json_name = "min_htlc_msat"]; + int64 min_htlc_msat = 9; /// The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size. - uint32 remote_csv_delay = 10 [json_name = "remote_csv_delay"]; + uint32 remote_csv_delay = 10; /// The minimum number of confirmations each one of your outputs used for the funding transaction must satisfy. - int32 min_confs = 11 [json_name = "min_confs"]; + int32 min_confs = 11; /// Whether unconfirmed outputs should be used as inputs for the funding transaction. - bool spend_unconfirmed = 12 [json_name = "spend_unconfirmed"]; + bool spend_unconfirmed = 12; /* Close address is an optional address which specifies the address to which @@ -1722,7 +1722,7 @@ message OpenChannelRequest { Note: If this value is set on channel creation, you will *not* be able to cooperatively close out to a different address. */ - string close_address = 13 [json_name = "close_address"]; + string close_address = 13; /** Funding shims are an optional argument that allow the caller to intercept @@ -1731,19 +1731,19 @@ message OpenChannelRequest { that is generated by the wallet as normal, or signal that signing will be carried out in an interactive manner (PSBT based). */ - FundingShim funding_shim = 14 [json_name = "funding_shim"]; + FundingShim funding_shim = 14; } message OpenStatusUpdate { oneof update { - PendingUpdate chan_pending = 1 [json_name = "chan_pending"]; - ChannelOpenUpdate chan_open = 3 [json_name = "chan_open"]; - } + PendingUpdate chan_pending = 1; + ChannelOpenUpdate chan_open = 3; + } /** The pending channel ID of the created channel. This value may be used to further the funding flow manually via the FundingStateStep method. */ - bytes pending_chan_id = 4 [json_name = "pending_chan_id"]; + bytes pending_chan_id = 4; } message KeyLocator { @@ -1755,15 +1755,15 @@ message KeyLocator { } message KeyDescriptor { - /** - The raw bytes of the key being identified. - */ - bytes raw_key_bytes = 1; + /** + The raw bytes of the key being identified. + */ + bytes raw_key_bytes = 1; - /** - The key locator that identifies which key to use for signing. - */ - KeyLocator key_loc = 2; + /** + The key locator that identifies which key to use for signing. + */ + KeyLocator key_loc = 2; } message ChanPointShim { @@ -1822,55 +1822,56 @@ message FundingStateStepResp { message PendingHTLC { /// The direction within the channel that the htlc was sent - bool incoming = 1 [ json_name = "incoming" ]; + bool incoming = 1; /// The total value of the htlc - int64 amount = 2 [ json_name = "amount" ]; + int64 amount = 2; /// The final output to be swept back to the user's wallet - string outpoint = 3 [ json_name = "outpoint" ]; + string outpoint = 3; /// The next block height at which we can spend the current stage - uint32 maturity_height = 4 [ json_name = "maturity_height" ]; + uint32 maturity_height = 4; /** The number of blocks remaining until the current stage can be swept. Negative values indicate how many blocks have passed since becoming mature. */ - int32 blocks_til_maturity = 5 [ json_name = "blocks_til_maturity" ]; + int32 blocks_til_maturity = 5; /// Indicates whether the htlc is in its first or second stage of recovery - uint32 stage = 6 [ json_name = "stage" ]; + uint32 stage = 6; } -message PendingChannelsRequest {} +message PendingChannelsRequest { +} message PendingChannelsResponse { message PendingChannel { - string remote_node_pub = 1 [ json_name = "remote_node_pub" ]; - string channel_point = 2 [ json_name = "channel_point" ]; + string remote_node_pub = 1; + string channel_point = 2; + + int64 capacity = 3; - int64 capacity = 3 [ json_name = "capacity" ]; + int64 local_balance = 4; + int64 remote_balance = 5; - int64 local_balance = 4 [ json_name = "local_balance" ]; - int64 remote_balance = 5 [ json_name = "remote_balance" ]; - /// The minimum satoshis this node is required to reserve in its balance. - int64 local_chan_reserve_sat = 6 [json_name = "local_chan_reserve_sat"]; + int64 local_chan_reserve_sat = 6; /** The minimum satoshis the other node is required to reserve in its balance. */ - int64 remote_chan_reserve_sat = 7 [json_name = "remote_chan_reserve_sat"]; + int64 remote_chan_reserve_sat = 7; } message PendingOpenChannel { /// The pending channel - PendingChannel channel = 1 [ json_name = "channel" ]; + PendingChannel channel = 1; /// The height at which this channel will be confirmed - uint32 confirmation_height = 2 [ json_name = "confirmation_height" ]; + uint32 confirmation_height = 2; /** The amount calculated to be paid in fees for the current set of @@ -1879,17 +1880,17 @@ message PendingChannelsResponse { each channel state update, including updates that happen after a system restart. */ - int64 commit_fee = 4 [json_name = "commit_fee" ]; + int64 commit_fee = 4; /// The weight of the commitment transaction - int64 commit_weight = 5 [ json_name = "commit_weight" ]; + int64 commit_weight = 5; /** The required number of satoshis per kilo-weight that the requester will pay at all times, for both the funding transaction and commitment transaction. This value can later be updated once the channel is open. */ - int64 fee_per_kw = 6 [ json_name = "fee_per_kw" ]; + int64 fee_per_kw = 6; } message WaitingCloseChannel { @@ -1897,7 +1898,7 @@ message PendingChannelsResponse { PendingChannel channel = 1; /// The balance in satoshis encumbered in this channel - int64 limbo_balance = 2 [ json_name = "limbo_balance" ]; + int64 limbo_balance = 2; } message ClosedChannel { @@ -1905,49 +1906,49 @@ message PendingChannelsResponse { PendingChannel channel = 1; /// The transaction id of the closing transaction - string closing_txid = 2 [ json_name = "closing_txid" ]; + string closing_txid = 2; } message ForceClosedChannel { /// The pending channel to be force closed - PendingChannel channel = 1 [ json_name = "channel" ]; + PendingChannel channel = 1; /// The transaction id of the closing transaction - string closing_txid = 2 [ json_name = "closing_txid" ]; + string closing_txid = 2; /// The balance in satoshis encumbered in this pending channel - int64 limbo_balance = 3 [ json_name = "limbo_balance" ]; + int64 limbo_balance = 3; /// The height at which funds can be swept into the wallet - uint32 maturity_height = 4 [ json_name = "maturity_height" ]; + uint32 maturity_height = 4; /* Remaining # of blocks until the commitment output can be swept. Negative values indicate how many blocks have passed since becoming mature. */ - int32 blocks_til_maturity = 5 [ json_name = "blocks_til_maturity" ]; + int32 blocks_til_maturity = 5; /// The total value of funds successfully recovered from this channel - int64 recovered_balance = 6 [ json_name = "recovered_balance" ]; + int64 recovered_balance = 6; - repeated PendingHTLC pending_htlcs = 8 [ json_name = "pending_htlcs" ]; + repeated PendingHTLC pending_htlcs = 8; } /// The balance in satoshis encumbered in pending channels - int64 total_limbo_balance = 1 [ json_name = "total_limbo_balance" ]; + int64 total_limbo_balance = 1; /// Channels pending opening - repeated PendingOpenChannel pending_open_channels = 2 [ json_name = "pending_open_channels" ]; + repeated PendingOpenChannel pending_open_channels = 2; /// Channels pending closing - repeated ClosedChannel pending_closing_channels = 3 [ json_name = "pending_closing_channels" ]; + repeated ClosedChannel pending_closing_channels = 3; /// Channels pending force closing - repeated ForceClosedChannel pending_force_closing_channels = 4 [ json_name = "pending_force_closing_channels" ]; + repeated ForceClosedChannel pending_force_closing_channels = 4; /// Channels waiting for closing tx to confirm - repeated WaitingCloseChannel waiting_close_channels = 5 [ json_name = "waiting_close_channels" ]; + repeated WaitingCloseChannel waiting_close_channels = 5; } message ChannelEventSubscription { @@ -1955,45 +1956,45 @@ message ChannelEventSubscription { message ChannelEventUpdate { oneof channel { - Channel open_channel = 1 [ json_name = "open_channel" ]; - ChannelCloseSummary closed_channel = 2 [ json_name = "closed_channel" ]; - ChannelPoint active_channel = 3 [ json_name = "active_channel" ]; - ChannelPoint inactive_channel = 4 [ json_name = "inactive_channel" ]; - PendingUpdate pending_open_channel = 6 [json_name = "pending_open_channel"]; + Channel open_channel = 1; + ChannelCloseSummary closed_channel = 2; + ChannelPoint active_channel = 3; + ChannelPoint inactive_channel = 4; + PendingUpdate pending_open_channel = 6; } enum UpdateType { - OPEN_CHANNEL = 0; - CLOSED_CHANNEL = 1; - ACTIVE_CHANNEL = 2; - INACTIVE_CHANNEL = 3; - PENDING_OPEN_CHANNEL = 4; + OPEN_CHANNEL = 0; + CLOSED_CHANNEL = 1; + ACTIVE_CHANNEL = 2; + INACTIVE_CHANNEL = 3; + PENDING_OPEN_CHANNEL = 4; } - UpdateType type = 5 [ json_name = "type" ]; + UpdateType type = 5; } message WalletBalanceRequest { } message WalletBalanceResponse { /// The balance of the wallet - int64 total_balance = 1 [json_name = "total_balance"]; + int64 total_balance = 1; /// The confirmed balance of a wallet(with >= 1 confirmations) - int64 confirmed_balance = 2 [json_name = "confirmed_balance"]; + int64 confirmed_balance = 2; /// The unconfirmed balance of a wallet(with 0 confirmations) - int64 unconfirmed_balance = 3 [json_name = "unconfirmed_balance"]; + int64 unconfirmed_balance = 3; } message ChannelBalanceRequest { } message ChannelBalanceResponse { /// Sum of channels balances denominated in satoshis - int64 balance = 1 [json_name = "balance"]; + int64 balance = 1; /// Sum of channels pending balances denominated in satoshis - int64 pending_open_balance = 2 [json_name = "pending_open_balance"]; + int64 pending_open_balance = 2; } message QueryRoutesRequest { @@ -2136,13 +2137,13 @@ message QueryRoutesResponse { The route that results from the path finding operation. This is still a repeated field to retain backwards compatibility. */ - repeated Route routes = 1 [json_name = "routes"]; + repeated Route routes = 1; /** The success probability of the returned route based on the current mission control state. [EXPERIMENTAL] */ - double success_prob = 2 [json_name = "success_prob"]; + double success_prob = 2; } message Hop { @@ -2151,26 +2152,26 @@ message Hop { height, the next 3 the index within the block, and the last 2 bytes are the output index for the channel. */ - uint64 chan_id = 1 [json_name = "chan_id", jstype = JS_STRING]; - int64 chan_capacity = 2 [json_name = "chan_capacity"]; - int64 amt_to_forward = 3 [json_name = "amt_to_forward", deprecated = true]; - int64 fee = 4 [json_name = "fee", deprecated = true]; - uint32 expiry = 5 [json_name = "expiry"]; - int64 amt_to_forward_msat = 6 [json_name = "amt_to_forward_msat"]; - int64 fee_msat = 7 [json_name = "fee_msat"]; + uint64 chan_id = 1 [jstype = JS_STRING]; + int64 chan_capacity = 2; + int64 amt_to_forward = 3 [deprecated = true]; + int64 fee = 4 [deprecated = true]; + uint32 expiry = 5; + int64 amt_to_forward_msat = 6; + int64 fee_msat = 7; /** An optional public key of the hop. If the public key is given, the payment can be executed without relying on a copy of the channel graph. */ - string pub_key = 8 [json_name = "pub_key"]; + string pub_key = 8; /** If set to true, then this hop will be encoded using the new variable length TLV format. Note that if any custom tlv_records below are specified, then this field MUST be set to true for them to be encoded properly. */ - bool tlv_payload = 9 [json_name = "tlv_payload"]; + bool tlv_payload = 9; /** An optional TLV record tha singals the use of an MPP payment. If present, @@ -2178,14 +2179,14 @@ message Hop { 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 [json_name = "mpp_record"]; + MPPRecord mpp_record = 10; /** 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. */ - map custom_records = 11 [json_name = "custom_records"]; + map custom_records = 11; } message MPPRecord { @@ -2195,7 +2196,7 @@ message MPPRecord { subpayments, and match the payment_addr provided in the receiver's invoice. The same payment_addr must be used on all subpayments. */ - bytes payment_addr = 11 [json_name = "payment_addr"]; + bytes payment_addr = 11; /** The total amount in milli-satoshis being sent as part of a larger multi-path @@ -2203,7 +2204,7 @@ message MPPRecord { and payment_hash sum exactly to total_amt_msat. The same total_amt_msat must be used on all subpayments. */ - int64 total_amt_msat = 10 [json_name = "total_amt_msat"]; + int64 total_amt_msat = 10; } /** @@ -2221,14 +2222,14 @@ message Route { will decrement the time-lock as advertised, leaving enough time for all hops to wait for or present the payment preimage to complete the payment. */ - uint32 total_time_lock = 1 [json_name = "total_time_lock"]; + uint32 total_time_lock = 1; /** The sum of the fees paid at each hop within the final route. In the case of a one-hop payment, this value will be zero as we don't need to pay a fee to ourselves. */ - int64 total_fees = 2 [json_name = "total_fees", deprecated = true]; + int64 total_fees = 2 [deprecated = true]; /** The total amount of funds required to complete a payment over this route. @@ -2237,22 +2238,22 @@ message Route { satoshis, otherwise the route will fail at an intermediate node due to an insufficient amount of fees. */ - int64 total_amt = 3 [json_name = "total_amt", deprecated = true]; + int64 total_amt = 3 [deprecated = true]; /** Contains details concerning the specific forwarding details at each hop. */ - repeated Hop hops = 4 [json_name = "hops"]; - + repeated Hop hops = 4; + /** The total fees in millisatoshis. */ - int64 total_fees_msat = 5 [json_name = "total_fees_msat"]; - + int64 total_fees_msat = 5; + /** The total amount in millisatoshis. */ - int64 total_amt_msat = 6 [json_name = "total_amt_msat"]; + int64 total_amt_msat = 6; } message NodeInfoRequest { @@ -2271,16 +2272,16 @@ message NodeInfo { the graph is directed, a node will also have an incoming edge attached to it for each outgoing edge. */ - LightningNode node = 1 [json_name = "node"]; + LightningNode node = 1; /// The total number of channels for the node. - uint32 num_channels = 2 [json_name = "num_channels"]; + uint32 num_channels = 2; /// The sum of all channels capacity for the node, denominated in satoshis. - int64 total_capacity = 3 [json_name = "total_capacity"]; + int64 total_capacity = 3; /// A list of all public channels for the node. - repeated ChannelEdge channels = 4 [json_name = "channels"]; + repeated ChannelEdge channels = 4; } /** @@ -2290,27 +2291,27 @@ graph is directed, a node will also have an incoming edge attached to it for each outgoing edge. */ message LightningNode { - uint32 last_update = 1 [ json_name = "last_update" ]; - string pub_key = 2 [ json_name = "pub_key" ]; - string alias = 3 [ json_name = "alias" ]; - repeated NodeAddress addresses = 4 [ json_name = "addresses" ]; - string color = 5 [ json_name = "color" ]; - map features = 6 [ json_name = "features" ]; + uint32 last_update = 1; + string pub_key = 2; + string alias = 3; + repeated NodeAddress addresses = 4; + string color = 5; + map features = 6; } message NodeAddress { - string network = 1 [ json_name = "network" ]; - string addr = 2 [ json_name = "addr" ]; + string network = 1; + string addr = 2; } message RoutingPolicy { - uint32 time_lock_delta = 1 [json_name = "time_lock_delta"]; - int64 min_htlc = 2 [json_name = "min_htlc"]; - int64 fee_base_msat = 3 [json_name = "fee_base_msat"]; - int64 fee_rate_milli_msat = 4 [json_name = "fee_rate_milli_msat"]; - bool disabled = 5 [json_name = "disabled"]; - uint64 max_htlc_msat = 6 [json_name = "max_htlc_msat"]; - uint32 last_update = 7 [json_name = "last_update"]; + uint32 time_lock_delta = 1; + int64 min_htlc = 2; + int64 fee_base_msat = 3; + int64 fee_rate_milli_msat = 4; + bool disabled = 5; + uint64 max_htlc_msat = 6; + uint32 last_update = 7; } /** @@ -2327,36 +2328,36 @@ message ChannelEdge { height, the next 3 the index within the block, and the last 2 bytes are the output index for the channel. */ - uint64 channel_id = 1 [json_name = "channel_id", jstype = JS_STRING]; - string chan_point = 2 [json_name = "chan_point"]; + uint64 channel_id = 1 [jstype = JS_STRING]; + string chan_point = 2; - uint32 last_update = 3 [json_name = "last_update", deprecated = true]; + uint32 last_update = 3 [deprecated = true]; - string node1_pub = 4 [json_name = "node1_pub"]; - string node2_pub = 5 [json_name = "node2_pub"]; + string node1_pub = 4; + string node2_pub = 5; - int64 capacity = 6 [json_name = "capacity"]; + int64 capacity = 6; - RoutingPolicy node1_policy = 7 [json_name = "node1_policy"]; - RoutingPolicy node2_policy = 8 [json_name = "node2_policy"]; + RoutingPolicy node1_policy = 7; + RoutingPolicy node2_policy = 8; } message ChannelGraphRequest { - /** - Whether unannounced channels are included in the response or not. If set, - unannounced channels are included. Unannounced channels are both private - channels, and public channels that are not yet announced to the network. - */ - bool include_unannounced = 1 [json_name = "include_unannounced"]; + /** + Whether unannounced channels are included in the response or not. If set, + unannounced channels are included. Unannounced channels are both private + channels, and public channels that are not yet announced to the network. + */ + bool include_unannounced = 1; } /// Returns a new instance of the directed channel graph. message ChannelGraph { /// The list of `LightningNode`s in this channel graph - repeated LightningNode nodes = 1 [json_name = "nodes"]; + repeated LightningNode nodes = 1; /// The list of `ChannelEdge`s in this channel graph - repeated ChannelEdge edges = 2 [json_name = "edges"]; + repeated ChannelEdge edges = 2; } message ChanInfoRequest { @@ -2371,31 +2372,34 @@ message ChanInfoRequest { message NetworkInfoRequest { } message NetworkInfo { - uint32 graph_diameter = 1 [json_name = "graph_diameter"]; - double avg_out_degree = 2 [json_name = "avg_out_degree"]; - uint32 max_out_degree = 3 [json_name = "max_out_degree"]; + uint32 graph_diameter = 1; + double avg_out_degree = 2; + uint32 max_out_degree = 3; - uint32 num_nodes = 4 [json_name = "num_nodes"]; - uint32 num_channels = 5 [json_name = "num_channels"]; + uint32 num_nodes = 4; + uint32 num_channels = 5; - int64 total_network_capacity = 6 [json_name = "total_network_capacity"]; + int64 total_network_capacity = 6; - double avg_channel_size = 7 [json_name = "avg_channel_size"]; - int64 min_channel_size = 8 [json_name = "min_channel_size"]; - int64 max_channel_size = 9 [json_name = "max_channel_size"]; - int64 median_channel_size_sat = 10 [json_name = "median_channel_size_sat"]; + double avg_channel_size = 7; + int64 min_channel_size = 8; + int64 max_channel_size = 9; + int64 median_channel_size_sat = 10; // The number of edges marked as zombies. - uint64 num_zombie_chans = 11 [json_name = "num_zombie_chans"]; + uint64 num_zombie_chans = 11; // TODO(roasbeef): fee rate info, expiry // * also additional RPC for tracking fee info once in } -message StopRequest{} -message StopResponse{} +message StopRequest { +} +message StopResponse { +} -message GraphTopologySubscription {} +message GraphTopologySubscription { +} message GraphTopologyUpdate { repeated NodeUpdate node_updates = 1; repeated ChannelEdgeUpdate channel_updates = 2; @@ -2420,9 +2424,9 @@ message ChannelEdgeUpdate { int64 capacity = 3; - RoutingPolicy routing_policy = 4; + RoutingPolicy routing_policy = 4; - string advertising_node = 5; + string advertising_node = 5; string connecting_node = 6; } message ClosedChannelUpdate { @@ -2439,22 +2443,22 @@ message ClosedChannelUpdate { message HopHint { /// The public key of the node at the start of the channel. - string node_id = 1 [json_name = "node_id"]; + string node_id = 1; /// The unique identifier of the channel. - uint64 chan_id = 2 [json_name = "chan_id", jstype = JS_STRING]; + uint64 chan_id = 2 [jstype = JS_STRING]; /// The base fee of the channel denominated in millisatoshis. - uint32 fee_base_msat = 3 [json_name = "fee_base_msat"]; + uint32 fee_base_msat = 3; /** The fee rate of the channel for sending one satoshi across it denominated in millionths of a satoshi. */ - uint32 fee_proportional_millionths = 4 [json_name = "fee_proportional_millionths"]; + uint32 fee_proportional_millionths = 4; /// The time-lock delta of the channel. - uint32 cltv_expiry_delta = 5 [json_name = "cltv_expiry_delta"]; + uint32 cltv_expiry_delta = 5; } message RouteHint { @@ -2462,7 +2466,7 @@ message RouteHint { A list of hop hints that when chained together can assist in reaching a specific destination. */ - repeated HopHint hop_hints = 1 [json_name = "hop_hints"]; + repeated HopHint hop_hints = 1; } message Invoice { @@ -2472,7 +2476,7 @@ message Invoice { field of the encoded payment request if the description_hash field is not being used. */ - string memo = 1 [json_name = "memo"]; + string memo = 1; reserved 2; @@ -2481,43 +2485,43 @@ message Invoice { HTLC payable to this preimage. When using REST, this field must be encoded as base64. */ - bytes r_preimage = 3 [json_name = "r_preimage"]; + bytes r_preimage = 3; /** The hash of the preimage. When using REST, this field must be encoded as base64. */ - bytes r_hash = 4 [json_name = "r_hash"]; + bytes r_hash = 4; /** The value of this invoice in satoshis The fields value and value_msat are mutually exclusive. */ - int64 value = 5 [json_name = "value"]; + int64 value = 5; /** The value of this invoice in millisatoshis The fields value and value_msat are mutually exclusive. */ - int64 value_msat = 23 [json_name = "value_msat"]; + int64 value_msat = 23; /// Whether this invoice has been fulfilled - bool settled = 6 [json_name = "settled", deprecated = true]; + bool settled = 6 [deprecated = true]; /// When this invoice was created - int64 creation_date = 7 [json_name = "creation_date"]; + int64 creation_date = 7; /// When this invoice was settled - int64 settle_date = 8 [json_name = "settle_date"]; + int64 settle_date = 8; /** A bare-bones invoice for a payment within the Lightning Network. With the details of the invoice, the sender has all the data necessary to send a payment to the recipient. */ - string payment_request = 9 [json_name = "payment_request"]; + string payment_request = 9; /** Hash (SHA-256) of a description of the payment. Used if the description of @@ -2525,25 +2529,25 @@ message Invoice { of an encoded payment request. When using REST, this field must be encoded as base64. */ - bytes description_hash = 10 [json_name = "description_hash"]; + bytes description_hash = 10; /// Payment request expiry time in seconds. Default is 3600 (1 hour). - int64 expiry = 11 [json_name = "expiry"]; + int64 expiry = 11; /// Fallback on-chain address. - string fallback_addr = 12 [json_name = "fallback_addr"]; + string fallback_addr = 12; /// Delta to use for the time-lock of the CLTV extended to the final hop. - uint64 cltv_expiry = 13 [json_name = "cltv_expiry"]; + uint64 cltv_expiry = 13; /** Route hints that can each be individually used to assist in reaching the invoice's destination. */ - repeated RouteHint route_hints = 14 [json_name = "route_hints"]; + repeated RouteHint route_hints = 14; /// Whether this invoice should include routing hints for private channels. - bool private = 15 [json_name = "private"]; + bool private = 15; /** The "add" index of this invoice. Each newly created invoice will increment @@ -2551,7 +2555,7 @@ message Invoice { SubscribeInvoices call can use this to instantly get notified of all added invoices with an add_index greater than this one. */ - uint64 add_index = 16 [json_name = "add_index"]; + uint64 add_index = 16; /** The "settle" index of this invoice. Each newly settled invoice will @@ -2559,10 +2563,10 @@ message Invoice { SubscribeInvoices call can use this to instantly get notified of all settled invoices with an settle_index greater than this one. */ - uint64 settle_index = 17 [json_name = "settle_index"]; + uint64 settle_index = 17; /// Deprecated, use amt_paid_sat or amt_paid_msat. - int64 amt_paid = 18 [json_name = "amt_paid", deprecated = true]; + int64 amt_paid = 18 [deprecated = true]; /** The amount that was accepted for this invoice, in satoshis. This will ONLY @@ -2572,7 +2576,7 @@ message Invoice { MORE that was specified in the original invoice. So we'll record that here as well. */ - int64 amt_paid_sat = 19 [json_name = "amt_paid_sat"]; + int64 amt_paid_sat = 19; /** The amount that was accepted for this invoice, in millisatoshis. This will @@ -2582,7 +2586,7 @@ message Invoice { paid MORE that was specified in the original invoice. So we'll record that here as well. */ - int64 amt_paid_msat = 20 [json_name = "amt_paid_msat"]; + int64 amt_paid_msat = 20; enum InvoiceState { OPEN = 0; @@ -2594,19 +2598,19 @@ message Invoice { /** The state the invoice is in. */ - InvoiceState state = 21 [json_name = "state"]; + InvoiceState state = 21; /// List of HTLCs paying to this invoice [EXPERIMENTAL]. - repeated InvoiceHTLC htlcs = 22 [json_name = "htlcs"]; + repeated InvoiceHTLC htlcs = 22; /// List of features advertised on the invoice. - map features = 24 [json_name = "features"]; - + map features = 24; + /** Indicates if this invoice was a spontaneous payment that arrived via keysend [EXPERIMENTAL]. */ - bool is_keysend = 25 [json_name = "is_keysend"]; + bool is_keysend = 25; } enum InvoiceHTLCState { @@ -2618,45 +2622,45 @@ enum InvoiceHTLCState { /// Details of an HTLC that paid to an invoice message InvoiceHTLC { /// Short channel id over which the htlc was received. - uint64 chan_id = 1 [json_name = "chan_id", jstype = JS_STRING]; + uint64 chan_id = 1 [jstype = JS_STRING]; /// Index identifying the htlc on the channel. - uint64 htlc_index = 2 [json_name = "htlc_index"]; + uint64 htlc_index = 2; /// The amount of the htlc in msat. - uint64 amt_msat = 3 [json_name = "amt_msat"]; + uint64 amt_msat = 3; /// Block height at which this htlc was accepted. - int32 accept_height = 4 [json_name = "accept_height"]; + int32 accept_height = 4; /// Time at which this htlc was accepted. - int64 accept_time = 5 [json_name = "accept_time"]; + int64 accept_time = 5; /// Time at which this htlc was settled or canceled. - int64 resolve_time = 6 [json_name = "resolve_time"]; - + int64 resolve_time = 6; + /// Block height at which this htlc expires. - int32 expiry_height = 7 [json_name = "expiry_height"]; + int32 expiry_height = 7; /// Current state the htlc is in. - InvoiceHTLCState state = 8 [json_name = "state"]; + InvoiceHTLCState state = 8; /// Custom tlv records. - map custom_records = 9 [json_name = "custom_records"]; + map custom_records = 9; /// The total amount of the mpp payment in msat. - uint64 mpp_total_amt_msat = 10 [json_name = "mpp_total_amt_msat"]; + uint64 mpp_total_amt_msat = 10; } message AddInvoiceResponse { - bytes r_hash = 1 [json_name = "r_hash"]; + bytes r_hash = 1; /** A bare-bones invoice for a payment within the Lightning Network. With the details of the invoice, the sender has all the data necessary to send a payment to the recipient. */ - string payment_request = 2 [json_name = "payment_request"]; + string payment_request = 2; /** The "add" index of this invoice. Each newly created invoice will increment @@ -2664,7 +2668,7 @@ message AddInvoiceResponse { SubscribeInvoices call can use this to instantly get notified of all added invoices with an add_index greater than this one. */ - uint64 add_index = 16 [json_name = "add_index"]; + uint64 add_index = 16; } message PaymentHash { /** @@ -2673,13 +2677,13 @@ message PaymentHash { Deprecated now that the REST gateway supports base64 encoding of bytes fields. */ - string r_hash_str = 1 [json_name = "r_hash_str", deprecated = true]; + string r_hash_str = 1 [deprecated = true]; /** The payment hash of the invoice to be looked up. When using REST, this field must be encoded as base64. */ - bytes r_hash = 2 [json_name = "r_hash"]; + bytes r_hash = 2; } message ListInvoiceRequest { @@ -2687,41 +2691,41 @@ message ListInvoiceRequest { If set, only invoices that are not settled and not canceled will be returned in the response. */ - bool pending_only = 1 [json_name = "pending_only"]; + bool pending_only = 1; /** The index of an invoice that will be used as either the start or end of a query to determine which invoices should be returned in the response. */ - uint64 index_offset = 4 [json_name = "index_offset"]; + uint64 index_offset = 4; /// The max number of invoices to return in the response to this query. - uint64 num_max_invoices = 5 [json_name = "num_max_invoices"]; + uint64 num_max_invoices = 5; /** If set, the invoices returned will result from seeking backwards from the specified index offset. This can be used to paginate backwards. */ - bool reversed = 6 [json_name = "reversed"]; + bool reversed = 6; } message ListInvoiceResponse { /** A list of invoices from the time slice of the time series specified in the request. */ - repeated Invoice invoices = 1 [json_name = "invoices"]; + repeated Invoice invoices = 1; /** The index of the last item in the set of returned invoices. This can be used to seek further, pagination style. */ - uint64 last_index_offset = 2 [json_name = "last_index_offset"]; + uint64 last_index_offset = 2; /** The index of the last item in the set of returned invoices. This can be used to seek backwards, pagination style. */ - uint64 first_index_offset = 3 [json_name = "first_index_offset"]; + uint64 first_index_offset = 3; } message InvoiceSubscription { @@ -2731,7 +2735,7 @@ message InvoiceSubscription { value. This allows callers to catch up on any events they missed while they weren't connected to the streaming RPC. */ - uint64 add_index = 1 [json_name = "add_index"]; + uint64 add_index = 1; /** If specified (non-zero), then we'll first start by sending out @@ -2739,37 +2743,37 @@ message InvoiceSubscription { this value. This allows callers to catch up on any events they missed while they weren't connected to the streaming RPC. */ - uint64 settle_index = 2 [json_name = "settle_index"]; + uint64 settle_index = 2; } message Payment { /// The payment hash - string payment_hash = 1 [json_name = "payment_hash"]; + string payment_hash = 1; /// Deprecated, use value_sat or value_msat. - int64 value = 2 [json_name = "value", deprecated = true]; + int64 value = 2 [deprecated = true]; /// Deprecated, use creation_time_ns - int64 creation_date = 3 [json_name = "creation_date", deprecated = true]; + int64 creation_date = 3 [deprecated = true]; /// The path this payment took. - repeated string path = 4 [json_name = "path", deprecated = true]; + repeated string path = 4 [deprecated = true]; /// Deprecated, use fee_sat or fee_msat. - int64 fee = 5 [json_name = "fee", deprecated = true]; + int64 fee = 5 [deprecated = true]; /// The payment preimage - string payment_preimage = 6 [json_name = "payment_preimage"]; + string payment_preimage = 6; /// The value of the payment in satoshis - int64 value_sat = 7 [json_name = "value_sat"]; + int64 value_sat = 7; /// The value of the payment in milli-satoshis - int64 value_msat = 8 [json_name = "value_msat"]; + int64 value_msat = 8; /// The optional payment request being fulfilled. - string payment_request = 9 [json_name = "payment_request"]; + string payment_request = 9; enum PaymentStatus { UNKNOWN = 0; @@ -2779,42 +2783,42 @@ message Payment { } // The status of the payment. - PaymentStatus status = 10 [json_name = "status"]; + PaymentStatus status = 10; /// The fee paid for this payment in satoshis - int64 fee_sat = 11 [json_name = "fee_sat"]; + int64 fee_sat = 11; /// The fee paid for this payment in milli-satoshis - int64 fee_msat = 12 [json_name = "fee_msat"]; + int64 fee_msat = 12; /// The time in UNIX nanoseconds at which the payment was created. - int64 creation_time_ns = 13 [json_name = "creation_time_ns"]; + int64 creation_time_ns = 13; /// The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. - repeated HTLCAttempt htlcs = 14 [json_name = "htlcs"]; + repeated HTLCAttempt htlcs = 14; } message HTLCAttempt { - enum HTLCStatus { - IN_FLIGHT = 0; - SUCCEEDED = 1; - FAILED = 2; - } + enum HTLCStatus { + IN_FLIGHT = 0; + SUCCEEDED = 1; + FAILED = 2; + } - /// The status of the HTLC. - HTLCStatus status = 1 [json_name = "status"]; + /// The status of the HTLC. + HTLCStatus status = 1; - /// The route taken by this HTLC. - Route route = 2 [json_name = "route"]; + /// The route taken by this HTLC. + Route route = 2; - /// The time in UNIX nanoseconds at which this HTLC was sent. - int64 attempt_time_ns = 3 [json_name = "attempt_time_ns"]; + /// The time in UNIX nanoseconds at which this HTLC was sent. + int64 attempt_time_ns = 3; - /** - The time in UNIX nanoseconds at which this HTLC was settled or failed. - This value will not be set if the HTLC is still IN_FLIGHT. - */ - int64 resolve_time_ns = 4 [json_name = "resolve_time_ns"]; + /** + The time in UNIX nanoseconds at which this HTLC was settled or failed. + This value will not be set if the HTLC is still IN_FLIGHT. + */ + int64 resolve_time_ns = 4; } message ListPaymentsRequest { @@ -2828,7 +2832,7 @@ message ListPaymentsRequest { message ListPaymentsResponse { /// The list of payments - repeated Payment payments = 1 [json_name = "payments"]; + repeated Payment payments = 1; } message DeleteAllPaymentsRequest { @@ -2850,7 +2854,7 @@ message DebugLevelRequest { string level_spec = 2; } message DebugLevelResponse { - string sub_systems = 1 [json_name = "sub_systems"]; + string sub_systems = 1; } message PayReqString { @@ -2858,160 +2862,160 @@ message PayReqString { string pay_req = 1; } message PayReq { - string destination = 1 [json_name = "destination"]; - string payment_hash = 2 [json_name = "payment_hash"]; - int64 num_satoshis = 3 [json_name = "num_satoshis"]; - int64 timestamp = 4 [json_name = "timestamp"]; - int64 expiry = 5 [json_name = "expiry"]; - string description = 6 [json_name = "description"]; - string description_hash = 7 [json_name = "description_hash"]; - string fallback_addr = 8 [json_name = "fallback_addr"]; - int64 cltv_expiry = 9 [json_name = "cltv_expiry"]; - repeated RouteHint route_hints = 10 [json_name = "route_hints"]; - bytes payment_addr = 11 [json_name = "payment_addr"]; - int64 num_msat = 12 [json_name = "num_msat"]; - map features = 13 [json_name = "features"]; + string destination = 1; + string payment_hash = 2; + int64 num_satoshis = 3; + int64 timestamp = 4; + int64 expiry = 5; + string description = 6; + string description_hash = 7; + string fallback_addr = 8; + int64 cltv_expiry = 9; + repeated RouteHint route_hints = 10; + bytes payment_addr = 11; + int64 num_msat = 12; + map features = 13; } enum FeatureBit { - DATALOSS_PROTECT_REQ = 0; - DATALOSS_PROTECT_OPT = 1; - INITIAL_ROUING_SYNC = 3; - UPFRONT_SHUTDOWN_SCRIPT_REQ = 4; - UPFRONT_SHUTDOWN_SCRIPT_OPT = 5; - GOSSIP_QUERIES_REQ = 6; - GOSSIP_QUERIES_OPT = 7; - TLV_ONION_REQ = 8; - TLV_ONION_OPT = 9; - EXT_GOSSIP_QUERIES_REQ = 10; - EXT_GOSSIP_QUERIES_OPT = 11; - STATIC_REMOTE_KEY_REQ = 12; - STATIC_REMOTE_KEY_OPT = 13; - PAYMENT_ADDR_REQ = 14; - PAYMENT_ADDR_OPT = 15; - MPP_REQ = 16; - MPP_OPT = 17; + DATALOSS_PROTECT_REQ = 0; + DATALOSS_PROTECT_OPT = 1; + INITIAL_ROUING_SYNC = 3; + UPFRONT_SHUTDOWN_SCRIPT_REQ = 4; + UPFRONT_SHUTDOWN_SCRIPT_OPT = 5; + GOSSIP_QUERIES_REQ = 6; + GOSSIP_QUERIES_OPT = 7; + TLV_ONION_REQ = 8; + TLV_ONION_OPT = 9; + EXT_GOSSIP_QUERIES_REQ = 10; + EXT_GOSSIP_QUERIES_OPT = 11; + STATIC_REMOTE_KEY_REQ = 12; + STATIC_REMOTE_KEY_OPT = 13; + PAYMENT_ADDR_REQ = 14; + PAYMENT_ADDR_OPT = 15; + MPP_REQ = 16; + MPP_OPT = 17; } message Feature { - string name = 2 [json_name = "name"]; - bool is_required = 3 [json_name = "is_required"]; - bool is_known = 4 [json_name = "is_known"]; + string name = 2; + bool is_required = 3; + bool is_known = 4; } -message FeeReportRequest {} +message FeeReportRequest { +} message ChannelFeeReport { /// The short channel id that this fee report belongs to. uint64 chan_id = 5 [jstype = JS_STRING]; /// The channel that this fee report belongs to. - string chan_point = 1 [json_name = "channel_point"]; + string chan_point = 1; /// The base fee charged regardless of the number of milli-satoshis sent. - int64 base_fee_msat = 2 [json_name = "base_fee_msat"]; + int64 base_fee_msat = 2; /// The amount charged per milli-satoshis transferred expressed in millionths of a satoshi. - int64 fee_per_mil = 3 [json_name = "fee_per_mil"]; + int64 fee_per_mil = 3; /// The effective fee rate in milli-satoshis. Computed by dividing the fee_per_mil value by 1 million. - double fee_rate = 4 [json_name = "fee_rate"]; + double fee_rate = 4; } message FeeReportResponse { /// An array of channel fee reports which describes the current fee schedule for each channel. - repeated ChannelFeeReport channel_fees = 1 [json_name = "channel_fees"]; + repeated ChannelFeeReport channel_fees = 1; /// The total amount of fee revenue (in satoshis) the switch has collected over the past 24 hrs. - uint64 day_fee_sum = 2 [json_name = "day_fee_sum"]; + uint64 day_fee_sum = 2; /// The total amount of fee revenue (in satoshis) the switch has collected over the past 1 week. - uint64 week_fee_sum = 3 [json_name = "week_fee_sum"]; + uint64 week_fee_sum = 3; /// The total amount of fee revenue (in satoshis) the switch has collected over the past 1 month. - uint64 month_fee_sum = 4 [json_name = "month_fee_sum"]; + uint64 month_fee_sum = 4; } message PolicyUpdateRequest { oneof scope { /// If set, then this update applies to all currently active channels. - bool global = 1 [json_name = "global"] ; + bool global = 1; /// If set, this update will target a specific channel. - ChannelPoint chan_point = 2 [json_name = "chan_point"]; + ChannelPoint chan_point = 2; } /// The base fee charged regardless of the number of milli-satoshis sent. - int64 base_fee_msat = 3 [json_name = "base_fee_msat"]; + int64 base_fee_msat = 3; /// The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6. - double fee_rate = 4 [json_name = "fee_rate"]; + double fee_rate = 4; /// The required timelock delta for HTLCs forwarded over the channel. - uint32 time_lock_delta = 5 [json_name = "time_lock_delta"]; + uint32 time_lock_delta = 5; /// If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged. - uint64 max_htlc_msat = 6 [json_name = "max_htlc_msat"]; + uint64 max_htlc_msat = 6; /// The minimum HTLC size in milli-satoshis. Only applied if min_htlc_msat_specified is true. - uint64 min_htlc_msat = 7 [json_name = "min_htlc_msat"]; + uint64 min_htlc_msat = 7; /// If true, min_htlc_msat is applied. - bool min_htlc_msat_specified = 8 [json_name = "set_min_htlc_msat"]; + bool min_htlc_msat_specified = 8; } message PolicyUpdateResponse { } message ForwardingHistoryRequest { /// Start time is the starting point of the forwarding history request. All records beyond this point will be included, respecting the end time, and the index offset. - uint64 start_time = 1 [json_name = "start_time"]; + uint64 start_time = 1; /// End time is the end point of the forwarding history request. The response will carry at most 50k records between the start time and the end time. The index offset can be used to implement pagination. - uint64 end_time = 2 [json_name = "end_time"]; + uint64 end_time = 2; /// Index offset is the offset in the time series to start at. As each response can only contain 50k records, callers can use this to skip around within a packed time series. - uint32 index_offset = 3 [json_name = "index_offset"]; + uint32 index_offset = 3; /// The max number of events to return in the response to this query. - uint32 num_max_events = 4 [json_name = "num_max_events"]; + uint32 num_max_events = 4; } message ForwardingEvent { /// Timestamp is the time (unix epoch offset) that this circuit was completed. - uint64 timestamp = 1 [json_name = "timestamp"]; + uint64 timestamp = 1; /// The incoming channel ID that carried the HTLC that created the circuit. - uint64 chan_id_in = 2 [json_name = "chan_id_in", jstype = JS_STRING]; + uint64 chan_id_in = 2 [jstype = JS_STRING]; /// The outgoing channel ID that carried the preimage that completed the circuit. - uint64 chan_id_out = 4 [json_name = "chan_id_out", jstype = JS_STRING]; + uint64 chan_id_out = 4 [jstype = JS_STRING]; /// The total amount (in satoshis) of the incoming HTLC that created half the circuit. - uint64 amt_in = 5 [json_name = "amt_in"]; + uint64 amt_in = 5; /// The total amount (in satoshis) of the outgoing HTLC that created the second half of the circuit. - uint64 amt_out = 6 [json_name = "amt_out"]; + uint64 amt_out = 6; /// The total fee (in satoshis) that this payment circuit carried. - uint64 fee = 7 [json_name = "fee"]; + uint64 fee = 7; /// The total fee (in milli-satoshis) that this payment circuit carried. - uint64 fee_msat = 8 [json_name = "fee_msat"]; + uint64 fee_msat = 8; /// The total amount (in milli-satoshis) of the incoming HTLC that created half the circuit. - uint64 amt_in_msat = 9 [json_name = "amt_in_msat"]; + uint64 amt_in_msat = 9; /// The total amount (in milli-satoshis) of the outgoing HTLC that created the second half of the circuit. - uint64 amt_out_msat = 10 [json_name = "amt_out_msat"]; - + uint64 amt_out_msat = 10; // TODO(roasbeef): add settlement latency? // * use FPE on the chan id? // * also list failures? } message ForwardingHistoryResponse { - /// A list of forwarding events from the time slice of the time series specified in the request. - repeated ForwardingEvent forwarding_events = 1 [json_name = "forwarding_events"]; + /// A list of forwarding events from the time slice of the time series specified in the request. + repeated ForwardingEvent forwarding_events = 1; - /// The index of the last time in the set of returned forwarding events. Can be used to seek further, pagination style. - uint32 last_offset_index = 2 [json_name = "last_offset_index"]; + /// The index of the last time in the set of returned forwarding events. Can be used to seek further, pagination style. + uint32 last_offset_index = 2; } message ExportChannelBackupRequest { @@ -3023,7 +3027,7 @@ message ChannelBackup { /** Identifies the channel that this backup belongs to. */ - ChannelPoint chan_point = 1 [ json_name = "chan_point" ]; + ChannelPoint chan_point = 1; /** Is an encrypted single-chan backup. this can be passed to @@ -3031,14 +3035,14 @@ message ChannelBackup { order to trigger the recovery protocol. When using REST, this field must be encoded as base64. */ - bytes chan_backup = 2 [ json_name = "chan_backup" ]; + bytes chan_backup = 2; } message MultiChanBackup { /** Is the set of all channels that are included in this multi-channel backup. */ - repeated ChannelPoint chan_points = 1 [ json_name = "chan_points" ]; + repeated ChannelPoint chan_points = 1; /** A single encrypted blob containing all the static channel backups of the @@ -3046,29 +3050,30 @@ message MultiChanBackup { safely be replaced with any prior/future versions. When using REST, this field must be encoded as base64. */ - bytes multi_chan_backup = 2 [ json_name = "multi_chan_backup" ]; + bytes multi_chan_backup = 2; } -message ChanBackupExportRequest {} -message ChanBackupSnapshot { +message ChanBackupExportRequest { +} +message ChanBackupSnapshot { /** The set of new channels that have been added since the last channel backup snapshot was requested. */ - ChannelBackups single_chan_backups = 1 [ json_name = "single_chan_backups" ]; + ChannelBackups single_chan_backups = 1; /** A multi-channel backup that covers all open channels currently known to lnd. */ - MultiChanBackup multi_chan_backup = 2 [ json_name = "multi_chan_backup" ]; + MultiChanBackup multi_chan_backup = 2; } message ChannelBackups { /** A set of single-chan static channel backups. */ - repeated ChannelBackup chan_backups = 1 [ json_name = "chan_backups" ]; + repeated ChannelBackup chan_backups = 1; } message RestoreChanBackupRequest { @@ -3076,34 +3081,36 @@ message RestoreChanBackupRequest { /** The channels to restore as a list of channel/backup pairs. */ - ChannelBackups chan_backups = 1 [ json_name = "chan_backups" ]; + ChannelBackups chan_backups = 1; /** The channels to restore in the packed multi backup format. When using REST, this field must be encoded as base64. */ - bytes multi_chan_backup = 2 [ json_name = "multi_chan_backup" ]; + bytes multi_chan_backup = 2; } } -message RestoreBackupResponse {} +message RestoreBackupResponse { +} -message ChannelBackupSubscription {} +message ChannelBackupSubscription { +} message VerifyChanBackupResponse { } message MacaroonPermission { /// The entity a permission grants access to. - string entity = 1 [json_name = "entity"]; + string entity = 1; /// The action that is granted. - string action = 2 [json_name = "action"]; + string action = 2; } message BakeMacaroonRequest { /// The list of permissions the new macaroon should grant. - repeated MacaroonPermission permissions = 1 [json_name = "permissions"]; + repeated MacaroonPermission permissions = 1; } message BakeMacaroonResponse { /// The hex encoded macaroon, serialized in binary format. - string macaroon = 1 [json_name = "macaroon"]; + string macaroon = 1; } From bcfe92cee1cf8ed106b9662adc5632194c3f4c35 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 13:56:08 +0100 Subject: [PATCH 138/562] autopilotrpc: format autopilot.proto and remove json_name fields We now use the jsonpb marshaler to convert the RPC responses to JSON in lncli and REST. The jsonpb has a setting to use the original name as defined in the proto file and the explicit json_name definition is not necessary any more. The jsonpb setting is called OrigName and needs to be true. --- lnrpc/autopilotrpc/autopilot.pb.go | 63 +++++++++++++++--------------- lnrpc/autopilotrpc/autopilot.proto | 42 ++++++++++---------- 2 files changed, 54 insertions(+), 51 deletions(-) diff --git a/lnrpc/autopilotrpc/autopilot.pb.go b/lnrpc/autopilotrpc/autopilot.pb.go index e5bb41cb0b..7b6c77449b 100644 --- a/lnrpc/autopilotrpc/autopilot.pb.go +++ b/lnrpc/autopilotrpc/autopilot.pb.go @@ -167,7 +167,7 @@ var xxx_messageInfo_ModifyStatusResponse proto.InternalMessageInfo type QueryScoresRequest struct { Pubkeys []string `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"` /// If set, we will ignore the local channel state when calculating scores. - IgnoreLocalState bool `protobuf:"varint,2,opt,name=ignore_local_state,json=no_state,proto3" json:"ignore_local_state,omitempty"` + IgnoreLocalState bool `protobuf:"varint,2,opt,name=ignore_local_state,json=ignoreLocalState,proto3" json:"ignore_local_state,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -397,36 +397,37 @@ func init() { func init() { proto.RegisterFile("autopilotrpc/autopilot.proto", fileDescriptor_e0b9dc347a92e084) } var fileDescriptor_e0b9dc347a92e084 = []byte{ - // 463 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xcf, 0x6f, 0xd3, 0x30, - 0x14, 0xc7, 0x95, 0x4c, 0x74, 0xcb, 0xeb, 0x60, 0xc3, 0x9d, 0xa6, 0x28, 0x54, 0xd0, 0x45, 0x1c, - 0x2a, 0x24, 0x52, 0x51, 0x38, 0x00, 0x12, 0x07, 0x86, 0x90, 0x90, 0x80, 0x03, 0x2e, 0xbb, 0x70, - 0x99, 0xd2, 0xcc, 0xb4, 0x56, 0x8d, 0x1d, 0xec, 0xe7, 0xa1, 0xfc, 0x43, 0x5c, 0xf9, 0x1b, 0x38, - 0xf2, 0x5f, 0xa1, 0xc5, 0x49, 0x49, 0xaa, 0x12, 0x84, 0xb4, 0x5b, 0xde, 0x8f, 0x7c, 0x9e, 0xdf, - 0xd7, 0x5f, 0x19, 0x86, 0xa9, 0x45, 0x95, 0x73, 0xa1, 0x50, 0xe7, 0xd9, 0x64, 0x1d, 0x24, 0xb9, - 0x56, 0xa8, 0xc8, 0x7e, 0xb3, 0x1a, 0x1f, 0xc0, 0xcd, 0x19, 0xa6, 0x68, 0x0d, 0x65, 0x5f, 0x2d, - 0x33, 0x18, 0x8f, 0xe1, 0x56, 0x9d, 0x30, 0xb9, 0x92, 0x86, 0x91, 0x63, 0xe8, 0xa5, 0x19, 0xf2, - 0x4b, 0x16, 0x7a, 0x23, 0x6f, 0xbc, 0x47, 0xab, 0x28, 0x7e, 0x08, 0x83, 0xf7, 0xea, 0x82, 0x7f, - 0x2e, 0x5a, 0x80, 0xab, 0x76, 0x26, 0xd3, 0xb9, 0x58, 0xb7, 0xbb, 0x28, 0x3e, 0x86, 0xa3, 0x76, - 0xbb, 0xc3, 0xc7, 0x1f, 0x81, 0x7c, 0xb0, 0x4c, 0x17, 0xb3, 0x4c, 0x69, 0xb6, 0xa6, 0x84, 0xb0, - 0x9b, 0xdb, 0xf9, 0x8a, 0x15, 0x26, 0xf4, 0x46, 0x3b, 0xe3, 0x80, 0xd6, 0x21, 0xb9, 0x0f, 0x84, - 0x2f, 0xa4, 0xd2, 0xec, 0x5c, 0xa8, 0x2c, 0x15, 0xe7, 0x06, 0x53, 0x64, 0xa1, 0x5f, 0xce, 0xda, - 0x93, 0xca, 0xc5, 0xf1, 0x77, 0x1f, 0x06, 0x2d, 0x6c, 0xb5, 0xcc, 0x5b, 0xd8, 0xd5, 0xcc, 0x58, - 0x81, 0x8e, 0xdb, 0x9f, 0x3e, 0x4a, 0x9a, 0x7a, 0x24, 0x5b, 0xfe, 0x49, 0xde, 0x30, 0xab, 0xb9, - 0x41, 0x9e, 0xd1, 0xf2, 0x4f, 0x5a, 0x13, 0xa2, 0x9f, 0x1e, 0x1c, 0x6c, 0x14, 0xc9, 0x10, 0x82, - 0x65, 0x9d, 0x2a, 0x15, 0x08, 0xe8, 0x9f, 0x04, 0x39, 0x83, 0x9e, 0x29, 0xe1, 0xa1, 0x5f, 0x4e, - 0x7f, 0xf1, 0xdf, 0xd3, 0x13, 0x57, 0x7e, 0x2d, 0x51, 0x17, 0xb4, 0x82, 0x45, 0xcf, 0xa0, 0xdf, - 0x48, 0x93, 0x43, 0xd8, 0x59, 0xb1, 0xa2, 0x9a, 0x7e, 0xf5, 0x49, 0x8e, 0xe0, 0xc6, 0x65, 0x2a, - 0xac, 0xd3, 0xc9, 0xa3, 0x2e, 0x78, 0xee, 0x3f, 0xf5, 0xe2, 0x1f, 0x1e, 0x1c, 0xce, 0x18, 0xb6, - 0xd5, 0xef, 0x5e, 0xe2, 0x74, 0x63, 0x89, 0x07, 0xed, 0x25, 0x36, 0x69, 0xd7, 0x7d, 0xe2, 0x01, - 0xdc, 0x6e, 0x8c, 0x70, 0x2a, 0x4d, 0x7f, 0xf9, 0x10, 0xbc, 0xac, 0x4f, 0x41, 0x5e, 0x41, 0xcf, - 0xb9, 0x8c, 0xdc, 0xd9, 0x38, 0x5b, 0xd3, 0xaa, 0xd1, 0x70, 0x7b, 0xb1, 0xb2, 0xca, 0x19, 0xec, - 0x37, 0x0d, 0x4b, 0x4e, 0xda, 0xdd, 0x5b, 0xbc, 0x1f, 0xc5, 0x5d, 0x2d, 0x15, 0x96, 0x42, 0xbf, - 0x71, 0xcd, 0x64, 0xd4, 0xe1, 0x00, 0x07, 0x3d, 0xf9, 0xa7, 0x47, 0xc8, 0x3b, 0x08, 0xd6, 0x92, - 0x90, 0xbb, 0xdd, 0xd7, 0x11, 0xdd, 0xfb, 0x6b, 0xdd, 0xd1, 0x4e, 0x9f, 0x7c, 0x9a, 0x2e, 0x38, - 0x2e, 0xed, 0x3c, 0xc9, 0xd4, 0x97, 0x89, 0xe0, 0x8b, 0x25, 0x4a, 0x2e, 0x17, 0x92, 0xe1, 0x37, - 0xa5, 0x57, 0x13, 0x21, 0x2f, 0x26, 0x42, 0xb6, 0x9e, 0x16, 0x9d, 0x67, 0xf3, 0x5e, 0xf9, 0xbc, - 0x3c, 0xfe, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x4e, 0x74, 0x27, 0x7e, 0x04, 0x00, 0x00, + // 468 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xcf, 0x8b, 0xd3, 0x40, + 0x14, 0xc7, 0x49, 0x16, 0xbb, 0xe6, 0x75, 0x75, 0xeb, 0x74, 0x59, 0x42, 0x2c, 0xda, 0xcd, 0xa9, + 0x88, 0xa6, 0x58, 0x3d, 0xa8, 0xe0, 0xc1, 0x15, 0x41, 0x70, 0x3d, 0x38, 0x65, 0x2f, 0x22, 0x2c, + 0x69, 0x76, 0x6c, 0x87, 0x8e, 0x33, 0x71, 0xe6, 0xcd, 0x4a, 0xfe, 0x21, 0xaf, 0xfe, 0x0d, 0x1e, + 0xfd, 0xaf, 0xa4, 0x99, 0xa4, 0x26, 0xa5, 0x56, 0x84, 0xbd, 0xe5, 0xbd, 0xef, 0x9b, 0xcf, 0x9b, + 0xf7, 0x23, 0x03, 0x83, 0xd4, 0xa2, 0xca, 0xb9, 0x50, 0xa8, 0xf3, 0x6c, 0xbc, 0x36, 0x92, 0x5c, + 0x2b, 0x54, 0xe4, 0xa0, 0xa9, 0xc6, 0x87, 0x70, 0x6b, 0x8a, 0x29, 0x5a, 0x43, 0xd9, 0x57, 0xcb, + 0x0c, 0xc6, 0x23, 0xb8, 0x5d, 0x3b, 0x4c, 0xae, 0xa4, 0x61, 0xe4, 0x18, 0x3a, 0x69, 0x86, 0xfc, + 0x8a, 0x85, 0xde, 0xd0, 0x1b, 0xdd, 0xa4, 0x95, 0x15, 0x3f, 0x82, 0xfe, 0x7b, 0x75, 0xc9, 0x3f, + 0x17, 0x2d, 0xc0, 0x2a, 0x9c, 0xc9, 0x74, 0x26, 0xd6, 0xe1, 0xce, 0x8a, 0x8f, 0xe1, 0xa8, 0x1d, + 0xee, 0xf0, 0xf1, 0x27, 0x20, 0x1f, 0x2c, 0xd3, 0xc5, 0x34, 0x53, 0x9a, 0xad, 0x29, 0x21, 0xec, + 0xe7, 0x76, 0xb6, 0x64, 0x85, 0x09, 0xbd, 0xe1, 0xde, 0x28, 0xa0, 0xb5, 0x49, 0x1e, 0x02, 0xe1, + 0x73, 0xa9, 0x34, 0xbb, 0x10, 0x2a, 0x4b, 0xc5, 0x85, 0xc1, 0x14, 0x59, 0xe8, 0x97, 0xb9, 0x7a, + 0x4e, 0x39, 0x5b, 0x09, 0xab, 0x34, 0x2c, 0xfe, 0xee, 0x43, 0xbf, 0x85, 0xaf, 0x8a, 0x7a, 0x07, + 0xfb, 0x9a, 0x19, 0x2b, 0xd0, 0xf1, 0xbb, 0x93, 0xc7, 0x49, 0xb3, 0x2f, 0xc9, 0x96, 0x33, 0xc9, + 0x5b, 0x66, 0x35, 0x37, 0xc8, 0x33, 0x5a, 0x9e, 0xa4, 0x35, 0x21, 0xfa, 0xe9, 0xc1, 0xe1, 0x86, + 0x48, 0x06, 0x10, 0x2c, 0x6a, 0x57, 0xd9, 0x89, 0x80, 0xfe, 0x71, 0x90, 0x73, 0xe8, 0x98, 0x12, + 0x1e, 0xfa, 0x65, 0xf6, 0x97, 0xff, 0x9d, 0x3d, 0x71, 0xf2, 0x1b, 0x89, 0xba, 0xa0, 0x15, 0x2c, + 0x7a, 0x0e, 0xdd, 0x86, 0x9b, 0xf4, 0x60, 0x6f, 0xc9, 0x8a, 0x2a, 0xfb, 0xea, 0x93, 0x1c, 0xc1, + 0x8d, 0xab, 0x54, 0x58, 0xd7, 0x2f, 0x8f, 0x3a, 0xe3, 0x85, 0xff, 0xcc, 0x8b, 0x7f, 0x78, 0xd0, + 0x9b, 0x32, 0x6c, 0x4f, 0x61, 0x77, 0x11, 0xa7, 0x1b, 0x45, 0x3c, 0x68, 0x17, 0xb1, 0x49, 0xbb, + 0xee, 0x1b, 0xf7, 0xe1, 0x4e, 0x23, 0x85, 0xeb, 0xd2, 0xe4, 0x97, 0x0f, 0xc1, 0xab, 0xfa, 0x16, + 0xe4, 0x35, 0x74, 0xdc, 0xb6, 0x91, 0xbb, 0x1b, 0x77, 0x6b, 0xae, 0x6c, 0x34, 0xd8, 0x2e, 0x56, + 0xab, 0x72, 0x0e, 0x07, 0xcd, 0xc5, 0x25, 0x27, 0xed, 0xe8, 0x2d, 0xff, 0x40, 0x14, 0xef, 0x0a, + 0xa9, 0xb0, 0x14, 0xba, 0x8d, 0x31, 0x93, 0xe1, 0x8e, 0x0d, 0x70, 0xd0, 0x93, 0x7f, 0xee, 0x08, + 0x39, 0x83, 0x60, 0xdd, 0x12, 0x72, 0x6f, 0xf7, 0x38, 0xa2, 0xfb, 0x7f, 0xd5, 0x1d, 0xed, 0xf4, + 0xe9, 0xc7, 0xc9, 0x9c, 0xe3, 0xc2, 0xce, 0x92, 0x4c, 0x7d, 0x19, 0x0b, 0x3e, 0x5f, 0xa0, 0xe4, + 0x72, 0x2e, 0x19, 0x7e, 0x53, 0x7a, 0x39, 0x16, 0xf2, 0x72, 0x2c, 0x64, 0xeb, 0x89, 0xd1, 0x79, + 0x36, 0xeb, 0x94, 0xcf, 0xcc, 0x93, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf8, 0xb6, 0x25, 0xd7, + 0x86, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/autopilotrpc/autopilot.proto b/lnrpc/autopilotrpc/autopilot.proto index 9570136cf4..614b5e75f8 100644 --- a/lnrpc/autopilotrpc/autopilot.proto +++ b/lnrpc/autopilotrpc/autopilot.proto @@ -11,68 +11,70 @@ service Autopilot { /** Status returns whether the daemon's autopilot agent is active. */ - rpc Status(StatusRequest) returns (StatusResponse); + rpc Status (StatusRequest) returns (StatusResponse); /** ModifyStatus is used to modify the status of the autopilot agent, like enabling or disabling it. */ - rpc ModifyStatus(ModifyStatusRequest) returns (ModifyStatusResponse); + rpc ModifyStatus (ModifyStatusRequest) returns (ModifyStatusResponse); /** QueryScores queries all available autopilot heuristics, in addition to any active combination of these heruristics, for the scores they would give to the given nodes. */ - rpc QueryScores(QueryScoresRequest) returns (QueryScoresResponse); + rpc QueryScores (QueryScoresRequest) returns (QueryScoresResponse); /** SetScores attempts to set the scores used by the running autopilot agent, if the external scoring heuristic is enabled. */ - rpc SetScores(SetScoresRequest) returns (SetScoresResponse); + rpc SetScores (SetScoresRequest) returns (SetScoresResponse); } -message StatusRequest{ +message StatusRequest { } -message StatusResponse{ +message StatusResponse { /// Indicates whether the autopilot is active or not. - bool active = 1 [json_name = "active"]; + bool active = 1; } -message ModifyStatusRequest{ +message ModifyStatusRequest { /// Whether the autopilot agent should be enabled or not. - bool enable = 1 [json_name = "enable"]; + bool enable = 1; } -message ModifyStatusResponse {} +message ModifyStatusResponse { +} -message QueryScoresRequest{ - repeated string pubkeys = 1 [json_name = "pubkeys"]; +message QueryScoresRequest { + repeated string pubkeys = 1; /// If set, we will ignore the local channel state when calculating scores. - bool ignore_local_state = 2 [json_name = "no_state"]; + bool ignore_local_state = 2; } message QueryScoresResponse { message HeuristicResult { - string heuristic = 1 [json_name = "heuristic"]; - map scores= 2 [json_name = "scores"]; + string heuristic = 1; + map scores = 2; } - repeated HeuristicResult results = 1 [json_name = "results"]; + repeated HeuristicResult results = 1; } -message SetScoresRequest{ +message SetScoresRequest { /// The name of the heuristic to provide scores to. - string heuristic = 1 [json_name = "heuristic"]; + string heuristic = 1; /** A map from hex-encoded public keys to scores. Scores must be in the range [0.0, 1.0]. */ - map scores = 2 [json_name = "scores"]; + map scores = 2; } -message SetScoresResponse {} +message SetScoresResponse { +} From 23f5472cd37b441cedc0a6780f40aa861fba088a Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 13:56:47 +0100 Subject: [PATCH 139/562] chainrpc: format chainnotifier.proto --- lnrpc/chainrpc/chainnotifier.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lnrpc/chainrpc/chainnotifier.proto b/lnrpc/chainrpc/chainnotifier.proto index 2014c29081..a0d07951cc 100644 --- a/lnrpc/chainrpc/chainnotifier.proto +++ b/lnrpc/chainrpc/chainnotifier.proto @@ -150,7 +150,7 @@ service ChainNotifier { particular transaction by its hash or for an output script by specifying a zero hash. */ - rpc RegisterConfirmationsNtfn(ConfRequest) returns (stream ConfEvent); + rpc RegisterConfirmationsNtfn (ConfRequest) returns (stream ConfEvent); /* RegisterSpendNtfn is a synchronous response-streaming RPC that registers an @@ -160,7 +160,7 @@ service ChainNotifier { A client can specify whether the spend request should be for a particular outpoint or for an output script by specifying a zero outpoint. */ - rpc RegisterSpendNtfn(SpendRequest) returns (stream SpendEvent); + rpc RegisterSpendNtfn (SpendRequest) returns (stream SpendEvent); /* RegisterBlockEpochNtfn is a synchronous response-streaming RPC that @@ -173,5 +173,5 @@ service ChainNotifier { point. This allows clients to be idempotent by ensuring that they do not missing processing a single block within the chain. */ - rpc RegisterBlockEpochNtfn(BlockEpoch) returns (stream BlockEpoch); + rpc RegisterBlockEpochNtfn (BlockEpoch) returns (stream BlockEpoch); } From 5a6fea31d9eea8d240f5c4f534c7b7dc2b281cce Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 13:57:40 +0100 Subject: [PATCH 140/562] invoicesrpc: format invoices.proto and remove json_name fields We now use the jsonpb marshaler to convert the RPC responses to JSON in lncli and REST. The jsonpb has a setting to use the original name as defined in the proto file and the explicit json_name definition is not necessary any more. The jsonpb setting is called OrigName and needs to be true. --- lnrpc/invoicesrpc/invoices.pb.go | 81 ++++++++++++++++---------------- lnrpc/invoicesrpc/invoices.proto | 42 +++++++++-------- 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/lnrpc/invoicesrpc/invoices.pb.go b/lnrpc/invoicesrpc/invoices.pb.go index a1e8805413..97c25467c8 100644 --- a/lnrpc/invoicesrpc/invoices.pb.go +++ b/lnrpc/invoicesrpc/invoices.pb.go @@ -113,22 +113,22 @@ type AddHoldInvoiceRequest struct { //The value of this invoice in millisatoshis // //The fields value and value_msat are mutually exclusive. - ValueMsat int64 `protobuf:"varint,10,opt,name=value_msat,proto3" json:"value_msat,omitempty"` + ValueMsat int64 `protobuf:"varint,10,opt,name=value_msat,json=valueMsat,proto3" json:"value_msat,omitempty"` //* //Hash (SHA-256) of a description of the payment. Used if the description of //payment (memo) is too long to naturally fit within the description field //of an encoded payment request. - DescriptionHash []byte `protobuf:"bytes,4,opt,name=description_hash,proto3" json:"description_hash,omitempty"` + DescriptionHash []byte `protobuf:"bytes,4,opt,name=description_hash,json=descriptionHash,proto3" json:"description_hash,omitempty"` /// Payment request expiry time in seconds. Default is 3600 (1 hour). Expiry int64 `protobuf:"varint,5,opt,name=expiry,proto3" json:"expiry,omitempty"` /// Fallback on-chain address. - FallbackAddr string `protobuf:"bytes,6,opt,name=fallback_addr,proto3" json:"fallback_addr,omitempty"` + FallbackAddr string `protobuf:"bytes,6,opt,name=fallback_addr,json=fallbackAddr,proto3" json:"fallback_addr,omitempty"` /// Delta to use for the time-lock of the CLTV extended to the final hop. - CltvExpiry uint64 `protobuf:"varint,7,opt,name=cltv_expiry,proto3" json:"cltv_expiry,omitempty"` + CltvExpiry uint64 `protobuf:"varint,7,opt,name=cltv_expiry,json=cltvExpiry,proto3" json:"cltv_expiry,omitempty"` //* //Route hints that can each be individually used to assist in reaching the //invoice's destination. - RouteHints []*lnrpc.RouteHint `protobuf:"bytes,8,rep,name=route_hints,proto3" json:"route_hints,omitempty"` + RouteHints []*lnrpc.RouteHint `protobuf:"bytes,8,rep,name=route_hints,json=routeHints,proto3" json:"route_hints,omitempty"` /// Whether this invoice should include routing hints for private channels. Private bool `protobuf:"varint,9,opt,name=private,proto3" json:"private,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -236,7 +236,7 @@ type AddHoldInvoiceResp struct { //A bare-bones invoice for a payment within the Lightning Network. With the //details of the invoice, the sender has all the data necessary to send a //payment to the recipient. - PaymentRequest string `protobuf:"bytes,1,opt,name=payment_request,proto3" json:"payment_request,omitempty"` + PaymentRequest string `protobuf:"bytes,1,opt,name=payment_request,json=paymentRequest,proto3" json:"payment_request,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -347,7 +347,7 @@ var xxx_messageInfo_SettleInvoiceResp proto.InternalMessageInfo type SubscribeSingleInvoiceRequest struct { /// Hash corresponding to the (hold) invoice to subscribe to. - RHash []byte `protobuf:"bytes,2,opt,name=r_hash,proto3" json:"r_hash,omitempty"` + RHash []byte `protobuf:"bytes,2,opt,name=r_hash,json=rHash,proto3" json:"r_hash,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -398,40 +398,41 @@ func init() { func init() { proto.RegisterFile("invoicesrpc/invoices.proto", fileDescriptor_090ab9c4958b987d) } var fileDescriptor_090ab9c4958b987d = []byte{ - // 519 bytes of a gzipped FileDescriptorProto + // 541 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xc1, 0x6e, 0xd3, 0x40, - 0x10, 0x95, 0xd3, 0x34, 0x4d, 0x27, 0x6d, 0x09, 0x0b, 0x54, 0x96, 0x45, 0x8b, 0xb1, 0x38, 0x58, - 0x3d, 0xd8, 0x90, 0x8a, 0x23, 0x48, 0xc0, 0x25, 0x20, 0xc1, 0xc1, 0x11, 0x1c, 0xb8, 0x58, 0x1b, - 0x7b, 0xb1, 0x57, 0x5d, 0xef, 0x2e, 0xbb, 0x9b, 0x40, 0xbf, 0x92, 0x33, 0x7f, 0x83, 0xbc, 0x76, - 0x2a, 0xdb, 0x2d, 0xbd, 0xcd, 0xbc, 0x99, 0x79, 0x1e, 0xbf, 0x37, 0x0b, 0x1e, 0xe5, 0x5b, 0x41, - 0x33, 0xa2, 0x95, 0xcc, 0xe2, 0x5d, 0x1c, 0x49, 0x25, 0x8c, 0x40, 0xb3, 0x4e, 0xcd, 0x7b, 0x5a, - 0x08, 0x51, 0x30, 0x12, 0x63, 0x49, 0x63, 0xcc, 0xb9, 0x30, 0xd8, 0x50, 0xc1, 0xdb, 0x56, 0xef, - 0x50, 0xc9, 0xac, 0x09, 0x83, 0xd7, 0x30, 0xff, 0x80, 0x79, 0x46, 0xd8, 0xc7, 0x66, 0xfa, 0xb3, - 0x2e, 0xd0, 0x73, 0x38, 0x92, 0xf8, 0xba, 0x22, 0xdc, 0xa4, 0x25, 0xd6, 0xa5, 0xeb, 0xf8, 0x4e, - 0x78, 0x94, 0xcc, 0x5a, 0x6c, 0x89, 0x75, 0x19, 0x3c, 0x82, 0x87, 0xbd, 0xb1, 0x84, 0x68, 0x19, - 0xfc, 0x19, 0xc1, 0x93, 0x77, 0x79, 0xbe, 0x14, 0x2c, 0xbf, 0x81, 0x7f, 0x6e, 0x88, 0x36, 0x08, - 0xc1, 0xb8, 0x22, 0x95, 0xb0, 0x4c, 0x87, 0x89, 0x8d, 0x6b, 0xcc, 0xb2, 0x8f, 0x2c, 0xbb, 0x8d, - 0xd1, 0x63, 0xd8, 0xdf, 0x62, 0xb6, 0x21, 0xee, 0x9e, 0xef, 0x84, 0x7b, 0x49, 0x93, 0xa0, 0x73, - 0x00, 0x1b, 0xa4, 0x95, 0xc6, 0xc6, 0x05, 0x5b, 0xea, 0x20, 0xe8, 0x02, 0xe6, 0x39, 0xd1, 0x99, - 0xa2, 0xb2, 0xfe, 0xc9, 0x66, 0xe7, 0xb1, 0x65, 0xbd, 0x85, 0xa3, 0x53, 0x98, 0x90, 0xdf, 0x92, - 0xaa, 0x6b, 0x77, 0xdf, 0xf2, 0xb4, 0x19, 0x7a, 0x01, 0xc7, 0x3f, 0x30, 0x63, 0x6b, 0x9c, 0x5d, - 0xa5, 0x38, 0xcf, 0x95, 0x3b, 0xb1, 0xab, 0xf6, 0x41, 0xe4, 0xc3, 0x2c, 0x63, 0x66, 0x9b, 0xb6, - 0x14, 0x07, 0xbe, 0x13, 0x8e, 0x93, 0x2e, 0x84, 0x16, 0x30, 0x53, 0x62, 0x63, 0x48, 0x5a, 0x52, - 0x6e, 0xb4, 0x3b, 0xf5, 0xf7, 0xc2, 0xd9, 0x62, 0x1e, 0x31, 0x5e, 0x4b, 0x9e, 0xd4, 0x95, 0x25, - 0xe5, 0x26, 0xe9, 0x36, 0x21, 0x17, 0x0e, 0xa4, 0xa2, 0x5b, 0x6c, 0x88, 0x7b, 0xe8, 0x3b, 0xe1, - 0x34, 0xd9, 0xa5, 0xc1, 0x5b, 0x40, 0x43, 0x41, 0xb5, 0x44, 0x21, 0x3c, 0xd8, 0xf9, 0xa3, 0x1a, - 0x81, 0x5b, 0x61, 0x87, 0x70, 0x10, 0xc1, 0x7c, 0x45, 0x8c, 0x61, 0xa4, 0xe3, 0xae, 0x07, 0x53, - 0xa9, 0x08, 0xad, 0x70, 0x41, 0x5a, 0x67, 0x6f, 0xf2, 0xda, 0xd6, 0x5e, 0xbf, 0xb5, 0xf5, 0x0d, - 0x9c, 0xad, 0x36, 0xeb, 0x5a, 0xc7, 0x35, 0x59, 0x51, 0x5e, 0x74, 0xaa, 0x8d, 0xbb, 0xa7, 0x30, - 0x51, 0x69, 0xc7, 0xcb, 0x36, 0xfb, 0x34, 0x9e, 0x3a, 0xf3, 0xd1, 0xe2, 0xef, 0x08, 0xa6, 0xed, - 0x80, 0x46, 0xdf, 0xe0, 0xf4, 0x6e, 0x2e, 0x74, 0x11, 0x75, 0xee, 0x37, 0xba, 0xf7, 0x83, 0xde, - 0x49, 0xab, 0x67, 0x0b, 0xbf, 0x74, 0xd0, 0x17, 0x38, 0xee, 0xdd, 0x23, 0x3a, 0xeb, 0xd1, 0x0d, - 0x4f, 0xdc, 0x3b, 0xff, 0x7f, 0xd9, 0x4a, 0xfc, 0x15, 0x4e, 0xfa, 0xc2, 0xa3, 0xa0, 0x37, 0x71, - 0xe7, 0x99, 0x7b, 0xcf, 0xee, 0xed, 0xd1, 0xb2, 0x5e, 0xb3, 0xa7, 0xef, 0x60, 0xcd, 0xa1, 0x57, - 0x83, 0x35, 0x6f, 0x59, 0xf3, 0xfe, 0xf2, 0xfb, 0xab, 0x82, 0x9a, 0x72, 0xb3, 0x8e, 0x32, 0x51, - 0xc5, 0x8c, 0x16, 0xa5, 0xe1, 0x94, 0x17, 0x9c, 0x98, 0x5f, 0x42, 0x5d, 0xc5, 0x8c, 0xe7, 0xb1, - 0x55, 0x2a, 0xee, 0xd0, 0xac, 0x27, 0xf6, 0xe5, 0x5f, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x1b, - 0x3c, 0xda, 0x98, 0x4d, 0x04, 0x00, 0x00, + 0x10, 0x95, 0xd3, 0x34, 0x4d, 0x26, 0x69, 0x1a, 0x16, 0x5a, 0x59, 0x16, 0xa1, 0xc1, 0x1c, 0x08, + 0x1c, 0x6c, 0xda, 0x8a, 0x1b, 0x1c, 0x0a, 0x42, 0x0a, 0x48, 0xe5, 0xe0, 0x08, 0x0e, 0x5c, 0xac, + 0x8d, 0xbd, 0xd8, 0xab, 0xda, 0xbb, 0xcb, 0xee, 0x26, 0xd0, 0x5f, 0xe4, 0x0f, 0xf8, 0x1b, 0xe4, + 0xf5, 0xa6, 0xb2, 0x43, 0xe9, 0x6d, 0xe6, 0xcd, 0xec, 0xcb, 0xcb, 0x7b, 0x63, 0xf0, 0x28, 0xdb, + 0x70, 0x9a, 0x10, 0x25, 0x45, 0x12, 0x6e, 0xeb, 0x40, 0x48, 0xae, 0x39, 0x1a, 0x36, 0x66, 0xde, + 0xe3, 0x8c, 0xf3, 0xac, 0x20, 0x21, 0x16, 0x34, 0xc4, 0x8c, 0x71, 0x8d, 0x35, 0xe5, 0xcc, 0xae, + 0x7a, 0x03, 0x29, 0x92, 0xba, 0xf4, 0x5f, 0xc3, 0xe4, 0x3d, 0x66, 0x09, 0x29, 0x3e, 0xd6, 0xaf, + 0xaf, 0x54, 0x86, 0x9e, 0xc2, 0x48, 0xe0, 0x9b, 0x92, 0x30, 0x1d, 0xe7, 0x58, 0xe5, 0xae, 0x33, + 0x73, 0xe6, 0xa3, 0x68, 0x68, 0xb1, 0x05, 0x56, 0xb9, 0xff, 0x10, 0x1e, 0xb4, 0x9e, 0x45, 0x44, + 0x09, 0xff, 0x77, 0x07, 0x8e, 0x2f, 0xd3, 0x74, 0xc1, 0x8b, 0xf4, 0x16, 0xfe, 0xb1, 0x26, 0x4a, + 0x23, 0x04, 0xdd, 0x92, 0x94, 0xdc, 0x30, 0x0d, 0x22, 0x53, 0x57, 0x98, 0x61, 0xef, 0x18, 0x76, + 0x53, 0xa3, 0x47, 0xb0, 0xbf, 0xc1, 0xc5, 0x9a, 0xb8, 0x7b, 0x33, 0x67, 0xbe, 0x17, 0xd5, 0x0d, + 0x9a, 0x02, 0x98, 0x22, 0x2e, 0x15, 0xd6, 0x2e, 0x98, 0xd1, 0xc0, 0x20, 0x57, 0x0a, 0x6b, 0xf4, + 0x02, 0x26, 0x29, 0x51, 0x89, 0xa4, 0xa2, 0xfa, 0x8f, 0xb5, 0xe4, 0xae, 0x21, 0x3d, 0x6a, 0xe0, + 0x95, 0x6c, 0x74, 0x02, 0x3d, 0xf2, 0x4b, 0x50, 0x79, 0xe3, 0xee, 0x1b, 0x16, 0xdb, 0xa1, 0x67, + 0x70, 0xf8, 0x1d, 0x17, 0xc5, 0x0a, 0x27, 0xd7, 0x31, 0x4e, 0x53, 0xe9, 0xf6, 0x8c, 0xd0, 0xd1, + 0x16, 0xbc, 0x4c, 0x53, 0x89, 0x4e, 0x61, 0x98, 0x14, 0x7a, 0x13, 0x5b, 0x86, 0x83, 0x99, 0x33, + 0xef, 0x46, 0x50, 0x41, 0x1f, 0x6a, 0x96, 0x33, 0x18, 0x4a, 0xbe, 0xd6, 0x24, 0xce, 0x29, 0xd3, + 0xca, 0xed, 0xcf, 0xf6, 0xe6, 0xc3, 0xf3, 0x49, 0x50, 0xb0, 0xca, 0xee, 0xa8, 0x9a, 0x2c, 0x28, + 0xd3, 0x11, 0xc8, 0x6d, 0xa9, 0x90, 0x0b, 0x07, 0x42, 0xd2, 0x0d, 0xd6, 0xc4, 0x1d, 0xcc, 0x9c, + 0x79, 0x3f, 0xda, 0xb6, 0xfe, 0x5b, 0x40, 0xbb, 0x5e, 0x2a, 0x81, 0x9e, 0xc3, 0xd1, 0x36, 0x1a, + 0x59, 0x7b, 0x6b, 0x3d, 0x1d, 0x5b, 0xd8, 0x3a, 0xee, 0x07, 0x30, 0x59, 0x12, 0xad, 0x0b, 0xd2, + 0xc8, 0xd5, 0x83, 0xbe, 0x90, 0x84, 0x96, 0x38, 0x23, 0x36, 0xd3, 0xdb, 0xbe, 0x0a, 0xb4, 0xb5, + 0x6f, 0x02, 0x7d, 0x03, 0xd3, 0xe5, 0x7a, 0x55, 0x59, 0xb8, 0x22, 0x4b, 0xca, 0xb2, 0xc6, 0xb4, + 0xce, 0xf5, 0x18, 0x7a, 0x32, 0x6e, 0xa4, 0xb8, 0x2f, 0x2b, 0x9b, 0x3f, 0x75, 0xfb, 0xce, 0xa4, + 0x73, 0xfe, 0xa7, 0x03, 0x7d, 0xbb, 0xaf, 0xd0, 0x57, 0x38, 0xb9, 0x9b, 0x0a, 0xbd, 0x0c, 0x1a, + 0x87, 0x1b, 0xdc, 0xfb, 0x7b, 0xde, 0xd8, 0x9a, 0x69, 0xe1, 0x57, 0x0e, 0xfa, 0x0c, 0x87, 0xad, + 0x43, 0x44, 0xd3, 0x16, 0xdd, 0xee, 0x6d, 0x7b, 0x4f, 0xfe, 0x3f, 0x36, 0x06, 0x7f, 0x81, 0x71, + 0xdb, 0x76, 0xe4, 0xb7, 0x5e, 0xdc, 0x79, 0xdf, 0xde, 0xe9, 0xbd, 0x3b, 0x4a, 0x54, 0x32, 0x5b, + 0xf6, 0xee, 0xc8, 0xdc, 0x8d, 0x6a, 0x47, 0xe6, 0x3f, 0xc9, 0xbc, 0xbb, 0xf8, 0x76, 0x96, 0x51, + 0x9d, 0xaf, 0x57, 0x41, 0xc2, 0xcb, 0xb0, 0xa0, 0x59, 0xae, 0x19, 0x65, 0x19, 0x23, 0xfa, 0x27, + 0x97, 0xd7, 0x61, 0xc1, 0xd2, 0xd0, 0x38, 0x15, 0x36, 0x68, 0x56, 0x3d, 0xf3, 0xc9, 0x5f, 0xfc, + 0x0d, 0x00, 0x00, 0xff, 0xff, 0x56, 0x22, 0x58, 0xe6, 0x46, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/invoicesrpc/invoices.proto b/lnrpc/invoicesrpc/invoices.proto index 00d380d3fa..4876cb44b3 100644 --- a/lnrpc/invoicesrpc/invoices.proto +++ b/lnrpc/invoicesrpc/invoices.proto @@ -22,26 +22,27 @@ service Invoices { canceled, this call will succeed. If the invoice is already settled, it will fail. */ - rpc CancelInvoice(CancelInvoiceMsg) returns (CancelInvoiceResp); + rpc CancelInvoice (CancelInvoiceMsg) returns (CancelInvoiceResp); /** AddHoldInvoice creates a hold invoice. It ties the invoice to the hash supplied in the request. */ - rpc AddHoldInvoice(AddHoldInvoiceRequest) returns (AddHoldInvoiceResp); - + rpc AddHoldInvoice (AddHoldInvoiceRequest) returns (AddHoldInvoiceResp); + /** SettleInvoice settles an accepted invoice. If the invoice is already settled, this call will succeed. */ - rpc SettleInvoice(SettleInvoiceMsg) returns (SettleInvoiceResp); + rpc SettleInvoice (SettleInvoiceMsg) returns (SettleInvoiceResp); } message CancelInvoiceMsg { /// Hash corresponding to the (hold) invoice to cancel. bytes payment_hash = 1; -} -message CancelInvoiceResp {} +} +message CancelInvoiceResp { +} message AddHoldInvoiceRequest { /** @@ -50,49 +51,49 @@ message AddHoldInvoiceRequest { field of the encoded payment request if the description_hash field is not being used. */ - string memo = 1 [json_name = "memo"]; + string memo = 1; /// The hash of the preimage - bytes hash = 2 [json_name = "hash"]; + bytes hash = 2; /** The value of this invoice in satoshis The fields value and value_msat are mutually exclusive. */ - int64 value = 3 [json_name = "value"]; + int64 value = 3; /** The value of this invoice in millisatoshis The fields value and value_msat are mutually exclusive. */ - int64 value_msat = 10 [json_name = "value_msat"]; + int64 value_msat = 10; /** Hash (SHA-256) of a description of the payment. Used if the description of payment (memo) is too long to naturally fit within the description field of an encoded payment request. */ - bytes description_hash = 4 [json_name = "description_hash"]; + bytes description_hash = 4; /// Payment request expiry time in seconds. Default is 3600 (1 hour). - int64 expiry = 5 [json_name = "expiry"]; + int64 expiry = 5; /// Fallback on-chain address. - string fallback_addr = 6 [json_name = "fallback_addr"]; + string fallback_addr = 6; /// Delta to use for the time-lock of the CLTV extended to the final hop. - uint64 cltv_expiry = 7 [json_name = "cltv_expiry"]; + uint64 cltv_expiry = 7; /** Route hints that can each be individually used to assist in reaching the invoice's destination. */ - repeated lnrpc.RouteHint route_hints = 8 [json_name = "route_hints"]; + repeated lnrpc.RouteHint route_hints = 8; /// Whether this invoice should include routing hints for private channels. - bool private = 9 [json_name = "private"]; + bool private = 9; } message AddHoldInvoiceResp { @@ -101,19 +102,20 @@ message AddHoldInvoiceResp { details of the invoice, the sender has all the data necessary to send a payment to the recipient. */ - string payment_request = 1 [json_name = "payment_request"]; + string payment_request = 1; } message SettleInvoiceMsg { /// Externally discovered pre-image that should be used to settle the hold invoice. bytes preimage = 1; -} +} -message SettleInvoiceResp {} +message SettleInvoiceResp { +} message SubscribeSingleInvoiceRequest { reserved 1; /// Hash corresponding to the (hold) invoice to subscribe to. - bytes r_hash = 2 [json_name = "r_hash"]; + bytes r_hash = 2; } From 1b543f0d50e03ed2901ef7fa3440ead7b1de0d20 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 13:58:45 +0100 Subject: [PATCH 141/562] routerrpc: format router.proto and remove json_name fields We now use the jsonpb marshaler to convert the RPC responses to JSON in lncli and REST. The jsonpb has a setting to use the original name as defined in the proto file and the explicit json_name definition is not necessary any more. The jsonpb setting is called OrigName and needs to be true. --- lnrpc/routerrpc/router.pb.go | 291 ++++++++++++++++++----------------- lnrpc/routerrpc/router.proto | 92 +++++------ 2 files changed, 193 insertions(+), 190 deletions(-) diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 25aa0b0911..fe0b3bafd8 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -248,7 +248,7 @@ type SendPaymentRequest struct { CltvLimit int32 `protobuf:"varint,9,opt,name=cltv_limit,json=cltvLimit,proto3" json:"cltv_limit,omitempty"` //* //Optional route hints to reach the destination through private channels. - RouteHints []*lnrpc.RouteHint `protobuf:"bytes,10,rep,name=route_hints,proto3" json:"route_hints,omitempty"` + RouteHints []*lnrpc.RouteHint `protobuf:"bytes,10,rep,name=route_hints,json=routeHints,proto3" json:"route_hints,omitempty"` //* //An optional field that can be used to pass an arbitrary set of TLV records //to a peer which understands the new records. This can be used to pass @@ -1134,9 +1134,9 @@ func (m *QueryMissionControlResponse) GetPairs() []*PairHistory { /// PairHistory contains the mission control state for a particular node pair. type PairHistory struct { /// The source node pubkey of the pair. - NodeFrom []byte `protobuf:"bytes,1,opt,name=node_from,proto3" json:"node_from,omitempty"` + NodeFrom []byte `protobuf:"bytes,1,opt,name=node_from,json=nodeFrom,proto3" json:"node_from,omitempty"` /// The destination node pubkey of the pair. - NodeTo []byte `protobuf:"bytes,2,opt,name=node_to,proto3" json:"node_to,omitempty"` + NodeTo []byte `protobuf:"bytes,2,opt,name=node_to,json=nodeTo,proto3" json:"node_to,omitempty"` History *PairData `protobuf:"bytes,7,opt,name=history,proto3" json:"history,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -1191,21 +1191,21 @@ func (m *PairHistory) GetHistory() *PairData { type PairData struct { /// Time of last failure. - FailTime int64 `protobuf:"varint,1,opt,name=fail_time,proto3" json:"fail_time,omitempty"` + FailTime int64 `protobuf:"varint,1,opt,name=fail_time,json=failTime,proto3" json:"fail_time,omitempty"` //* //Lowest amount that failed to forward rounded to whole sats. This may be //set to zero if the failure is independent of amount. - FailAmtSat int64 `protobuf:"varint,2,opt,name=fail_amt_sat,proto3" json:"fail_amt_sat,omitempty"` + FailAmtSat int64 `protobuf:"varint,2,opt,name=fail_amt_sat,json=failAmtSat,proto3" json:"fail_amt_sat,omitempty"` //* //Lowest amount that failed to forward in millisats. This may be //set to zero if the failure is independent of amount. - FailAmtMsat int64 `protobuf:"varint,4,opt,name=fail_amt_msat,proto3" json:"fail_amt_msat,omitempty"` + FailAmtMsat int64 `protobuf:"varint,4,opt,name=fail_amt_msat,json=failAmtMsat,proto3" json:"fail_amt_msat,omitempty"` /// Time of last success. - SuccessTime int64 `protobuf:"varint,5,opt,name=success_time,proto3" json:"success_time,omitempty"` + SuccessTime int64 `protobuf:"varint,5,opt,name=success_time,json=successTime,proto3" json:"success_time,omitempty"` /// Highest amount that we could successfully forward rounded to whole sats. - SuccessAmtSat int64 `protobuf:"varint,6,opt,name=success_amt_sat,proto3" json:"success_amt_sat,omitempty"` + SuccessAmtSat int64 `protobuf:"varint,6,opt,name=success_amt_sat,json=successAmtSat,proto3" json:"success_amt_sat,omitempty"` /// Highest amount that we could successfully forward in millisats. - SuccessAmtMsat int64 `protobuf:"varint,7,opt,name=success_amt_msat,proto3" json:"success_amt_msat,omitempty"` + SuccessAmtMsat int64 `protobuf:"varint,7,opt,name=success_amt_msat,json=successAmtMsat,proto3" json:"success_amt_msat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1280,11 +1280,11 @@ func (m *PairData) GetSuccessAmtMsat() int64 { type QueryProbabilityRequest struct { /// The source node pubkey of the pair. - FromNode []byte `protobuf:"bytes,1,opt,name=from_node,proto3" json:"from_node,omitempty"` + FromNode []byte `protobuf:"bytes,1,opt,name=from_node,json=fromNode,proto3" json:"from_node,omitempty"` /// The destination node pubkey of the pair. - ToNode []byte `protobuf:"bytes,2,opt,name=to_node,proto3" json:"to_node,omitempty"` + ToNode []byte `protobuf:"bytes,2,opt,name=to_node,json=toNode,proto3" json:"to_node,omitempty"` /// The amount for which to calculate a probability. - AmtMsat int64 `protobuf:"varint,3,opt,name=amt_msat,proto3" json:"amt_msat,omitempty"` + AmtMsat int64 `protobuf:"varint,3,opt,name=amt_msat,json=amtMsat,proto3" json:"amt_msat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1529,139 +1529,140 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2102 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xcb, 0x73, 0xdb, 0xc6, - 0x19, 0x0f, 0xc4, 0xf7, 0xc7, 0x17, 0xb4, 0x92, 0x65, 0x98, 0xb2, 0x62, 0x05, 0x76, 0x1d, 0x8e, - 0xc7, 0x91, 0x5c, 0xb5, 0xf1, 0x78, 0x7a, 0x68, 0x87, 0x22, 0xc1, 0x08, 0x32, 0x09, 0xca, 0x4b, - 0xd2, 0x89, 0x9b, 0xc3, 0x0e, 0x44, 0xae, 0x44, 0x8c, 0x40, 0x80, 0x01, 0x96, 0x8e, 0xf5, 0x0f, - 0xf4, 0xd4, 0xff, 0xa3, 0xbd, 0xb4, 0x97, 0x9e, 0xfb, 0xef, 0xb4, 0xf7, 0xde, 0x7a, 0xeb, 0xec, - 0x2e, 0x40, 0x82, 0x14, 0xe5, 0xf4, 0x44, 0xec, 0xef, 0x7b, 0xed, 0xee, 0xb7, 0xdf, 0x8b, 0xb0, - 0x17, 0xf8, 0x73, 0x46, 0x83, 0x60, 0x36, 0x3a, 0x96, 0x5f, 0x47, 0xb3, 0xc0, 0x67, 0x3e, 0x2a, - 0x2c, 0xf0, 0x5a, 0x21, 0x98, 0x8d, 0x24, 0xaa, 0xff, 0x37, 0x03, 0xa8, 0x4f, 0xbd, 0xf1, 0x85, - 0x7d, 0x3b, 0xa5, 0x1e, 0xc3, 0xf4, 0xa7, 0x39, 0x0d, 0x19, 0x42, 0x90, 0x1e, 0xd3, 0x90, 0x69, - 0xca, 0xa1, 0x52, 0x2f, 0x61, 0xf1, 0x8d, 0x54, 0x48, 0xd9, 0x53, 0xa6, 0x6d, 0x1d, 0x2a, 0xf5, - 0x14, 0xe6, 0x9f, 0xe8, 0x11, 0xe4, 0xed, 0x29, 0x23, 0xd3, 0xd0, 0x66, 0x5a, 0x49, 0xc0, 0x39, - 0x7b, 0xca, 0xba, 0xa1, 0xcd, 0xd0, 0x57, 0x50, 0x9a, 0x49, 0x95, 0x64, 0x62, 0x87, 0x13, 0x2d, - 0x25, 0x14, 0x15, 0x23, 0xec, 0xcc, 0x0e, 0x27, 0xa8, 0x0e, 0xea, 0x95, 0xe3, 0xd9, 0x2e, 0x19, - 0xb9, 0xec, 0x23, 0x19, 0x53, 0x97, 0xd9, 0x5a, 0xfa, 0x50, 0xa9, 0x67, 0x70, 0x45, 0xe0, 0x4d, - 0x97, 0x7d, 0x6c, 0x71, 0x14, 0x7d, 0x0d, 0xd5, 0x58, 0x59, 0x20, 0x37, 0xa8, 0x65, 0x0e, 0x95, - 0x7a, 0x01, 0x57, 0x66, 0xab, 0xdb, 0xfe, 0x1a, 0xaa, 0xcc, 0x99, 0x52, 0x7f, 0xce, 0x48, 0x48, - 0x47, 0xbe, 0x37, 0x0e, 0xb5, 0xac, 0xd4, 0x18, 0xc1, 0x7d, 0x89, 0x22, 0x1d, 0xca, 0x57, 0x94, - 0x12, 0xd7, 0x99, 0x3a, 0x8c, 0xf0, 0xed, 0xe7, 0xc4, 0xf6, 0x8b, 0x57, 0x94, 0x76, 0x38, 0xd6, - 0xb7, 0x19, 0x7a, 0x06, 0x95, 0x25, 0x8f, 0x38, 0x63, 0x59, 0x30, 0x95, 0x62, 0x26, 0x71, 0xd0, - 0x97, 0xa0, 0xfa, 0x73, 0x76, 0xed, 0x3b, 0xde, 0x35, 0x19, 0x4d, 0x6c, 0x8f, 0x38, 0x63, 0x2d, - 0x7f, 0xa8, 0xd4, 0xd3, 0xa7, 0x5b, 0xaf, 0x14, 0x5c, 0x89, 0x69, 0xcd, 0x89, 0xed, 0x99, 0x63, - 0xf4, 0x1c, 0xaa, 0xae, 0x1d, 0x32, 0x32, 0xf1, 0x67, 0x64, 0x36, 0xbf, 0xbc, 0xa1, 0xb7, 0x5a, - 0x45, 0xdc, 0x4c, 0x99, 0xc3, 0x67, 0xfe, 0xec, 0x42, 0x80, 0xe8, 0x00, 0x40, 0xdc, 0x8a, 0x30, - 0xae, 0x15, 0xc4, 0x19, 0x0a, 0x1c, 0x11, 0x86, 0xd1, 0x09, 0x14, 0x85, 0x37, 0xc9, 0xc4, 0xf1, - 0x58, 0xa8, 0xc1, 0x61, 0xaa, 0x5e, 0x3c, 0x51, 0x8f, 0x5c, 0x8f, 0x3b, 0x16, 0x73, 0xca, 0x99, - 0xe3, 0x31, 0x9c, 0x64, 0x42, 0x63, 0xd8, 0xe1, 0x6e, 0x24, 0xa3, 0x79, 0xc8, 0xfc, 0x29, 0x09, - 0xe8, 0xc8, 0x0f, 0xc6, 0xa1, 0x56, 0x14, 0xb2, 0xbf, 0x3d, 0x5a, 0xbc, 0x8e, 0xa3, 0xbb, 0xcf, - 0xe1, 0xa8, 0x45, 0x43, 0xd6, 0x14, 0x72, 0x58, 0x8a, 0x19, 0x1e, 0x0b, 0x6e, 0xf1, 0xf6, 0x78, - 0x1d, 0x47, 0x2f, 0x01, 0xd9, 0xae, 0xeb, 0xff, 0x4c, 0x42, 0xea, 0x5e, 0x91, 0xc8, 0x3d, 0x5a, - 0xf5, 0x50, 0xa9, 0xe7, 0xb1, 0x2a, 0x28, 0x7d, 0xea, 0x5e, 0x45, 0xea, 0xd1, 0x6b, 0x28, 0x8b, - 0x3d, 0x5d, 0x51, 0x9b, 0xcd, 0x03, 0x1a, 0x6a, 0xea, 0x61, 0xaa, 0x5e, 0x39, 0xd9, 0x8e, 0x4e, - 0xd2, 0x96, 0xf0, 0xa9, 0xc3, 0x70, 0x89, 0xf3, 0x45, 0xeb, 0xb0, 0xd6, 0x82, 0xbd, 0xcd, 0x5b, - 0xe2, 0x8f, 0x94, 0x5f, 0x2a, 0x7f, 0xb7, 0x69, 0xcc, 0x3f, 0xd1, 0x2e, 0x64, 0x3e, 0xda, 0xee, - 0x9c, 0x8a, 0x87, 0x5b, 0xc2, 0x72, 0xf1, 0xbb, 0xad, 0x37, 0x8a, 0xfe, 0x06, 0x76, 0x06, 0x81, - 0x3d, 0xba, 0x59, 0x7b, 0xfb, 0xeb, 0x4f, 0x57, 0xb9, 0xf3, 0x74, 0xf5, 0xbf, 0x2a, 0x50, 0x8e, - 0xa4, 0xfa, 0xcc, 0x66, 0xf3, 0x10, 0x7d, 0x03, 0x99, 0x90, 0xd9, 0x8c, 0x0a, 0xee, 0xca, 0xc9, - 0xc3, 0xc4, 0x7d, 0x26, 0x18, 0x29, 0x96, 0x5c, 0xa8, 0x06, 0xf9, 0x59, 0x40, 0x9d, 0xa9, 0x7d, - 0x1d, 0xef, 0x6b, 0xb1, 0x46, 0x3a, 0x64, 0x84, 0xb0, 0x88, 0x99, 0xe2, 0x49, 0x29, 0xe9, 0x56, - 0x2c, 0x49, 0xa8, 0x0e, 0x99, 0x09, 0x73, 0x47, 0xa1, 0x96, 0x16, 0xee, 0x43, 0x11, 0xcf, 0xd9, - 0xa0, 0xd3, 0x6c, 0x30, 0x46, 0xa7, 0x33, 0x86, 0x25, 0x83, 0xfe, 0x7b, 0xa8, 0x0a, 0xc9, 0x36, - 0xa5, 0x9f, 0x0b, 0xee, 0x87, 0xc0, 0x43, 0x57, 0x84, 0x82, 0x0c, 0xf0, 0xac, 0x3d, 0xe5, 0x51, - 0xa0, 0x8f, 0x41, 0x5d, 0xca, 0x87, 0x33, 0xdf, 0x0b, 0xb9, 0x75, 0x95, 0x6f, 0x83, 0x3f, 0x79, - 0x1e, 0x21, 0x22, 0x36, 0x14, 0x21, 0x55, 0x89, 0xf0, 0x36, 0xa5, 0x22, 0x3a, 0x9e, 0xcb, 0x80, - 0x24, 0xae, 0x3f, 0xba, 0xe1, 0x21, 0x6e, 0xdf, 0x46, 0xea, 0xcb, 0x1c, 0xee, 0xf8, 0xa3, 0x9b, - 0x16, 0x07, 0xf5, 0x1f, 0x65, 0x16, 0x1a, 0xf8, 0xf2, 0x94, 0xff, 0xb7, 0x27, 0x96, 0x97, 0xb5, - 0x75, 0xef, 0x65, 0xe9, 0x04, 0x76, 0x56, 0x94, 0x47, 0xa7, 0x48, 0xfa, 0x40, 0x59, 0xf3, 0xc1, - 0x4b, 0xc8, 0x5d, 0xd9, 0x8e, 0x3b, 0x0f, 0x62, 0xc5, 0x28, 0xe1, 0xd0, 0xb6, 0xa4, 0xe0, 0x98, - 0x45, 0xff, 0x53, 0x1e, 0x72, 0x11, 0x88, 0x4e, 0x20, 0x3d, 0xf2, 0xc7, 0xf1, 0x3b, 0xf8, 0xf2, - 0xae, 0x58, 0xfc, 0xdb, 0xf4, 0xc7, 0x14, 0x0b, 0x5e, 0xf4, 0x07, 0xa8, 0xf0, 0xd4, 0xe1, 0x51, - 0x97, 0xcc, 0x67, 0x63, 0x7b, 0xe1, 0x7a, 0x2d, 0x21, 0xdd, 0x94, 0x0c, 0x43, 0x41, 0xc7, 0xe5, - 0x51, 0x72, 0x89, 0xf6, 0xa1, 0xc0, 0xbd, 0x2d, 0x3d, 0x91, 0x16, 0x6f, 0x3f, 0xcf, 0x01, 0xe1, - 0x03, 0x1d, 0xca, 0xbe, 0xe7, 0xf8, 0x1e, 0x09, 0x27, 0x36, 0x39, 0xf9, 0xf6, 0xb5, 0xc8, 0x9d, - 0x25, 0x5c, 0x14, 0x60, 0x7f, 0x62, 0x9f, 0x7c, 0xfb, 0x1a, 0x3d, 0x81, 0xa2, 0xc8, 0x37, 0xf4, - 0xd3, 0xcc, 0x09, 0x6e, 0x45, 0xd2, 0x2c, 0x63, 0x91, 0x82, 0x0c, 0x81, 0xf0, 0x28, 0xba, 0x72, - 0xed, 0xeb, 0x50, 0x24, 0xca, 0x32, 0x96, 0x0b, 0xf4, 0x0a, 0x76, 0xa3, 0x3b, 0x20, 0xa1, 0x3f, - 0x0f, 0x46, 0x94, 0x38, 0xde, 0x98, 0x7e, 0x12, 0x09, 0xb0, 0x8c, 0x51, 0x44, 0xeb, 0x0b, 0x92, - 0xc9, 0x29, 0x68, 0x0f, 0xb2, 0x13, 0xea, 0x5c, 0x4f, 0x64, 0x52, 0x2b, 0xe3, 0x68, 0xa5, 0xff, - 0x33, 0x03, 0xc5, 0xc4, 0xc5, 0xa0, 0x12, 0xe4, 0xb1, 0xd1, 0x37, 0xf0, 0x7b, 0xa3, 0xa5, 0x7e, - 0x81, 0xea, 0xf0, 0xcc, 0xb4, 0x9a, 0x3d, 0x8c, 0x8d, 0xe6, 0x80, 0xf4, 0x30, 0x19, 0x5a, 0x6f, - 0xad, 0xde, 0xf7, 0x16, 0xb9, 0x68, 0x7c, 0xe8, 0x1a, 0xd6, 0x80, 0xb4, 0x8c, 0x41, 0xc3, 0xec, - 0xf4, 0x55, 0x05, 0x3d, 0x06, 0x6d, 0xc9, 0x19, 0x93, 0x1b, 0xdd, 0xde, 0xd0, 0x1a, 0xa8, 0x5b, - 0xe8, 0x09, 0xec, 0xb7, 0x4d, 0xab, 0xd1, 0x21, 0x4b, 0x9e, 0x66, 0x67, 0xf0, 0x9e, 0x18, 0x3f, - 0x5c, 0x98, 0xf8, 0x83, 0x9a, 0xda, 0xc4, 0xc0, 0x63, 0x2a, 0xd6, 0x90, 0x46, 0x8f, 0xe0, 0x81, - 0x64, 0x90, 0x22, 0x64, 0xd0, 0xeb, 0x91, 0x7e, 0xaf, 0x67, 0xa9, 0x19, 0xb4, 0x0d, 0x65, 0xd3, - 0x7a, 0xdf, 0xe8, 0x98, 0x2d, 0x82, 0x8d, 0x46, 0xa7, 0xab, 0x66, 0xd1, 0x0e, 0x54, 0xd7, 0xf9, - 0x72, 0x5c, 0x45, 0xcc, 0xd7, 0xb3, 0xcc, 0x9e, 0x45, 0xde, 0x1b, 0xb8, 0x6f, 0xf6, 0x2c, 0x35, - 0x8f, 0xf6, 0x00, 0xad, 0x92, 0xce, 0xba, 0x8d, 0xa6, 0x5a, 0x40, 0x0f, 0x60, 0x7b, 0x15, 0x7f, - 0x6b, 0x7c, 0x50, 0x01, 0x69, 0xb0, 0x2b, 0x37, 0x46, 0x4e, 0x8d, 0x4e, 0xef, 0x7b, 0xd2, 0x35, - 0x2d, 0xb3, 0x3b, 0xec, 0xaa, 0x45, 0xb4, 0x0b, 0x6a, 0xdb, 0x30, 0x88, 0x69, 0xf5, 0x87, 0xed, - 0xb6, 0xd9, 0x34, 0x0d, 0x6b, 0xa0, 0x96, 0xa4, 0xe5, 0x4d, 0x07, 0x2f, 0x73, 0x81, 0xe6, 0x59, - 0xc3, 0xb2, 0x8c, 0x0e, 0x69, 0x99, 0xfd, 0xc6, 0x69, 0xc7, 0x68, 0xa9, 0x15, 0x74, 0x00, 0x8f, - 0x06, 0x46, 0xf7, 0xa2, 0x87, 0x1b, 0xf8, 0x03, 0x89, 0xe9, 0xed, 0x86, 0xd9, 0x19, 0x62, 0x43, - 0xad, 0xa2, 0xaf, 0xe0, 0x00, 0x1b, 0xef, 0x86, 0x26, 0x36, 0x5a, 0xc4, 0xea, 0xb5, 0x0c, 0xd2, - 0x36, 0x1a, 0x83, 0x21, 0x36, 0x48, 0xd7, 0xec, 0xf7, 0x4d, 0xeb, 0x3b, 0x55, 0x45, 0xcf, 0xe0, - 0x70, 0xc1, 0xb2, 0x50, 0xb0, 0xc6, 0xb5, 0xcd, 0xcf, 0x17, 0xbb, 0xd4, 0x32, 0x7e, 0x18, 0x90, - 0x0b, 0xc3, 0xc0, 0x2a, 0x42, 0x35, 0xd8, 0x5b, 0x9a, 0x97, 0x06, 0x22, 0xdb, 0x3b, 0x9c, 0x76, - 0x61, 0xe0, 0x6e, 0xc3, 0xe2, 0x0e, 0x5e, 0xa1, 0xed, 0xf2, 0x6d, 0x2f, 0x69, 0xeb, 0xdb, 0x7e, - 0x80, 0x10, 0x54, 0x12, 0x5e, 0x69, 0x37, 0xb0, 0xba, 0x87, 0xaa, 0x50, 0xec, 0x5e, 0x5c, 0x90, - 0x81, 0xd9, 0x35, 0x7a, 0xc3, 0x81, 0xfa, 0x10, 0xed, 0x42, 0x35, 0xde, 0x52, 0x2c, 0xf9, 0xaf, - 0x1c, 0x7a, 0x08, 0x68, 0x68, 0x61, 0xa3, 0xd1, 0xe2, 0x37, 0xb4, 0x20, 0xfc, 0x3b, 0x77, 0x9e, - 0xce, 0x6f, 0xa9, 0x29, 0xfd, 0x1f, 0x29, 0x28, 0xaf, 0x04, 0x2a, 0x7a, 0x0c, 0x85, 0xd0, 0xb9, - 0xf6, 0x44, 0xdd, 0x8a, 0xb2, 0xcc, 0x12, 0x10, 0x65, 0x7e, 0x62, 0x3b, 0x9e, 0x4c, 0x6f, 0xb2, - 0x10, 0x14, 0x04, 0x22, 0x92, 0xdb, 0x3e, 0xe4, 0xe2, 0x96, 0x22, 0xb5, 0x68, 0x29, 0xb2, 0x23, - 0xd9, 0x4a, 0x3c, 0x86, 0x02, 0xcf, 0xa1, 0x21, 0xb3, 0xa7, 0x33, 0x11, 0xf3, 0x65, 0xbc, 0x04, - 0xd0, 0x53, 0x28, 0x4f, 0x69, 0x18, 0xda, 0xd7, 0x94, 0xc8, 0xb8, 0x05, 0xc1, 0x51, 0x8a, 0xc0, - 0xb6, 0x08, 0xdf, 0xa7, 0x10, 0xe7, 0x91, 0x88, 0x29, 0x23, 0x99, 0x22, 0x50, 0x32, 0xad, 0xa7, - 0x70, 0x66, 0x47, 0xe9, 0x21, 0x99, 0xc2, 0x99, 0x8d, 0x5e, 0xc0, 0xb6, 0xcc, 0x41, 0x8e, 0xe7, - 0x4c, 0xe7, 0x53, 0x99, 0x8b, 0x72, 0x22, 0x17, 0x55, 0x45, 0x2e, 0x92, 0xb8, 0x48, 0x49, 0x8f, - 0x20, 0x7f, 0x69, 0x87, 0x94, 0x57, 0x8f, 0x28, 0x57, 0xe4, 0xf8, 0xba, 0x4d, 0x29, 0x27, 0xf1, - 0x9a, 0x12, 0xf0, 0x2c, 0x28, 0x53, 0x44, 0xee, 0x8a, 0x52, 0xcc, 0xef, 0x72, 0x61, 0xc1, 0xfe, - 0xb4, 0xb4, 0x50, 0x4c, 0x58, 0x90, 0xb8, 0xb0, 0xf0, 0x02, 0xb6, 0xe9, 0x27, 0x16, 0xd8, 0xc4, - 0x9f, 0xd9, 0x3f, 0xcd, 0x29, 0x19, 0xdb, 0xcc, 0x16, 0x3d, 0x6a, 0x09, 0x57, 0x05, 0xa1, 0x27, - 0xf0, 0x96, 0xcd, 0x6c, 0xfd, 0x31, 0xd4, 0x30, 0x0d, 0x29, 0xeb, 0x3a, 0x61, 0xe8, 0xf8, 0x5e, - 0xd3, 0xf7, 0x58, 0xe0, 0xbb, 0x51, 0x11, 0xd2, 0x0f, 0x60, 0x7f, 0x23, 0x55, 0x56, 0x11, 0x2e, - 0xfc, 0x6e, 0x4e, 0x83, 0xdb, 0xcd, 0xc2, 0xef, 0x60, 0x7f, 0x23, 0x35, 0x2a, 0x41, 0x2f, 0x21, - 0x33, 0xb3, 0x9d, 0x20, 0xd4, 0xb6, 0x44, 0x19, 0xdf, 0x5b, 0xe9, 0x1a, 0x9c, 0xe0, 0xcc, 0x09, - 0x99, 0x1f, 0xdc, 0x62, 0xc9, 0x74, 0x9e, 0xce, 0x2b, 0xea, 0x96, 0xfe, 0x67, 0x05, 0x8a, 0x09, - 0x22, 0x7f, 0x07, 0x9e, 0x3f, 0xa6, 0xe4, 0x2a, 0xf0, 0xa7, 0xf1, 0x0b, 0x5b, 0x00, 0x48, 0x83, - 0x9c, 0x58, 0x30, 0x3f, 0x7a, 0x5e, 0xf1, 0x12, 0x7d, 0x03, 0xb9, 0x89, 0x54, 0x21, 0xbc, 0x54, - 0x3c, 0xd9, 0x59, 0xb3, 0xce, 0xef, 0x06, 0xc7, 0x3c, 0xe7, 0xe9, 0x7c, 0x4a, 0x4d, 0x9f, 0xa7, - 0xf3, 0x69, 0x35, 0x73, 0x9e, 0xce, 0x67, 0xd4, 0xec, 0x79, 0x3a, 0x9f, 0x55, 0x73, 0xfa, 0x7f, - 0x14, 0xc8, 0xc7, 0xdc, 0x7c, 0x2f, 0x3c, 0xe7, 0x13, 0xfe, 0x32, 0xa2, 0x8e, 0x60, 0x09, 0x20, - 0x1d, 0x4a, 0x62, 0xb1, 0xda, 0x68, 0xac, 0x60, 0xe8, 0x19, 0x94, 0x17, 0xeb, 0x45, 0x35, 0x4b, - 0xe1, 0x55, 0x90, 0x6b, 0x0a, 0xe7, 0xa3, 0x11, 0x0d, 0x43, 0x69, 0x2a, 0x23, 0x35, 0x25, 0x31, - 0x54, 0x87, 0x6a, 0xbc, 0x8e, 0x0d, 0x66, 0x05, 0xdb, 0x3a, 0x8c, 0x5e, 0x80, 0x9a, 0x84, 0xa6, - 0xcb, 0x79, 0xe0, 0x0e, 0x2e, 0xaf, 0x41, 0x9f, 0xc2, 0x43, 0xe1, 0xd6, 0x8b, 0xc0, 0xbf, 0xb4, - 0x2f, 0x1d, 0xd7, 0x61, 0xb7, 0x71, 0xcf, 0xc2, 0xaf, 0x20, 0xf0, 0xa7, 0xc4, 0x8b, 0x9b, 0x80, - 0x12, 0x5e, 0x02, 0xdc, 0x1d, 0xcc, 0x97, 0xb4, 0xc8, 0x1d, 0xd1, 0x92, 0x77, 0x23, 0x0b, 0xe3, - 0x29, 0x61, 0x7c, 0xb1, 0xd6, 0x6f, 0x40, 0xbb, 0x6b, 0x2e, 0x7a, 0x42, 0x87, 0x50, 0x9c, 0x2d, - 0x61, 0x61, 0x51, 0xc1, 0x49, 0x28, 0xe9, 0xe8, 0xad, 0x5f, 0x76, 0xb4, 0xfe, 0x17, 0x05, 0xb6, - 0x4f, 0xe7, 0x8e, 0x3b, 0x5e, 0x69, 0xc5, 0x92, 0xa3, 0x9e, 0xb2, 0x3a, 0xea, 0x6d, 0x9a, 0xe3, - 0xb6, 0x36, 0xce, 0x71, 0x9b, 0x66, 0xa5, 0xd4, 0xbd, 0xb3, 0xd2, 0x13, 0x28, 0x2e, 0xc7, 0x24, - 0xd9, 0xe9, 0x96, 0x30, 0x4c, 0xe2, 0x19, 0x29, 0xd4, 0xdf, 0x00, 0x4a, 0x6e, 0x34, 0xba, 0x90, - 0x45, 0x47, 0xa8, 0xdc, 0xdb, 0x11, 0xbe, 0xf8, 0xbb, 0x02, 0xa5, 0x64, 0x5b, 0x8e, 0xca, 0x50, - 0x30, 0x2d, 0xd2, 0xee, 0x98, 0xdf, 0x9d, 0x0d, 0xd4, 0x2f, 0xf8, 0xb2, 0x3f, 0x6c, 0x36, 0x0d, - 0xa3, 0x65, 0xb4, 0x54, 0x85, 0x17, 0x0c, 0x9e, 0xea, 0x8d, 0xd6, 0xa2, 0x3e, 0x6c, 0xf1, 0xd2, - 0x1e, 0x61, 0x56, 0x8f, 0xe0, 0xde, 0x70, 0x60, 0xa8, 0x29, 0xa4, 0x42, 0x29, 0x02, 0x0d, 0x8c, - 0x7b, 0x58, 0x4d, 0xf3, 0xfa, 0x17, 0x21, 0x77, 0xdb, 0x92, 0xb8, 0x6b, 0xc9, 0x88, 0xb6, 0x23, - 0xe6, 0x5a, 0x56, 0x6c, 0x72, 0xda, 0xe8, 0x34, 0xac, 0xa6, 0xa1, 0x66, 0x4f, 0xfe, 0x96, 0x81, - 0xac, 0x38, 0x41, 0x80, 0xce, 0xa0, 0x98, 0x98, 0xd0, 0xd0, 0xc1, 0x67, 0x27, 0xb7, 0x9a, 0xb6, - 0x79, 0x10, 0x99, 0x87, 0xaf, 0x14, 0x74, 0x0e, 0xa5, 0xe4, 0xfc, 0x83, 0x92, 0xcd, 0xea, 0x86, - 0xc1, 0xe8, 0xb3, 0xba, 0xde, 0x82, 0x6a, 0x84, 0xcc, 0x99, 0xf2, 0xe6, 0x34, 0x1a, 0x17, 0x50, - 0x2d, 0xc1, 0xbf, 0x36, 0x83, 0xd4, 0xf6, 0x37, 0xd2, 0x22, 0x17, 0x76, 0xe4, 0x11, 0xa3, 0x86, - 0xfd, 0xce, 0x11, 0x57, 0xa7, 0x84, 0xda, 0x97, 0xf7, 0x91, 0x23, 0x6d, 0x63, 0xd8, 0xd9, 0x90, - 0xc0, 0xd1, 0xaf, 0x92, 0x3b, 0xb8, 0x37, 0xfd, 0xd7, 0x9e, 0xff, 0x12, 0xdb, 0xd2, 0xca, 0x86, - 0x4c, 0xbf, 0x62, 0xe5, 0xfe, 0x3a, 0xb1, 0x62, 0xe5, 0x73, 0x05, 0xe3, 0x47, 0x50, 0xd7, 0x33, - 0x01, 0xd2, 0xd7, 0x65, 0xef, 0x66, 0xa5, 0xda, 0xd3, 0xcf, 0xf2, 0x44, 0xca, 0x4d, 0x80, 0x65, - 0x3c, 0xa1, 0xc7, 0x09, 0x91, 0x3b, 0xf9, 0xa0, 0x76, 0x70, 0x0f, 0x55, 0xaa, 0x3a, 0xfd, 0xf5, - 0x1f, 0x8f, 0xaf, 0x1d, 0x36, 0x99, 0x5f, 0x1e, 0x8d, 0xfc, 0xe9, 0xb1, 0xcb, 0x5b, 0x7c, 0xcf, - 0xf1, 0xae, 0x3d, 0xca, 0x7e, 0xf6, 0x83, 0x9b, 0x63, 0xd7, 0x1b, 0x1f, 0x8b, 0xb0, 0x3c, 0x5e, - 0x68, 0xb9, 0xcc, 0x8a, 0x3f, 0xa4, 0x7e, 0xf3, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x10, 0xf6, - 0xab, 0x74, 0xc0, 0x12, 0x00, 0x00, + // 2126 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xcd, 0x76, 0xdb, 0xc6, + 0x15, 0x0e, 0xc4, 0x5f, 0x5d, 0xfe, 0x41, 0x23, 0x45, 0xa2, 0x29, 0x2b, 0x61, 0x10, 0xd7, 0xe1, + 0xf1, 0x71, 0x24, 0x47, 0x6d, 0x7c, 0x7c, 0xba, 0x68, 0x0f, 0x45, 0x82, 0x11, 0x64, 0x12, 0x94, + 0x87, 0xa4, 0x13, 0x37, 0x8b, 0x39, 0x10, 0x39, 0x12, 0x51, 0xe1, 0x87, 0x01, 0x86, 0x8e, 0xf5, + 0x02, 0x5d, 0xf4, 0x45, 0xda, 0x4d, 0xbb, 0xe9, 0xba, 0xaf, 0xd3, 0xf6, 0x11, 0xba, 0xec, 0x99, + 0x19, 0x80, 0x04, 0x29, 0xca, 0xe9, 0x4a, 0xc4, 0x77, 0xbf, 0xb9, 0x77, 0x66, 0xee, 0xdc, 0x3f, + 0xc1, 0x7e, 0xe0, 0xcf, 0x19, 0x0d, 0x82, 0xd9, 0xf8, 0x44, 0xfe, 0x3a, 0x9e, 0x05, 0x3e, 0xf3, + 0xd1, 0xf6, 0x02, 0xaf, 0x6d, 0x07, 0xb3, 0xb1, 0x44, 0xb5, 0xff, 0x66, 0x00, 0x0d, 0xa8, 0x37, + 0xb9, 0xb4, 0xee, 0x5c, 0xea, 0x31, 0x4c, 0x7f, 0x9a, 0xd3, 0x90, 0x21, 0x04, 0xe9, 0x09, 0x0d, + 0x59, 0x55, 0xa9, 0x2b, 0x8d, 0x22, 0x16, 0xbf, 0x91, 0x0a, 0x29, 0xcb, 0x65, 0xd5, 0xad, 0xba, + 0xd2, 0x48, 0x61, 0xfe, 0x13, 0x3d, 0x82, 0xbc, 0xe5, 0x32, 0xe2, 0x86, 0x16, 0xab, 0x16, 0x05, + 0x9c, 0xb3, 0x5c, 0xd6, 0x0b, 0x2d, 0x86, 0xbe, 0x80, 0xe2, 0x4c, 0xaa, 0x24, 0x53, 0x2b, 0x9c, + 0x56, 0x53, 0x42, 0x51, 0x21, 0xc2, 0xce, 0xad, 0x70, 0x8a, 0x1a, 0xa0, 0x5e, 0xdb, 0x9e, 0xe5, + 0x90, 0xb1, 0xc3, 0xde, 0x93, 0x09, 0x75, 0x98, 0x55, 0x4d, 0xd7, 0x95, 0x46, 0x06, 0x97, 0x05, + 0xde, 0x72, 0xd8, 0xfb, 0x36, 0x47, 0xd1, 0x57, 0x50, 0x89, 0x95, 0x05, 0x72, 0x83, 0xd5, 0x4c, + 0x5d, 0x69, 0x6c, 0xe3, 0xf2, 0x6c, 0x75, 0xdb, 0x5f, 0x41, 0x85, 0xd9, 0x2e, 0xf5, 0xe7, 0x8c, + 0x84, 0x74, 0xec, 0x7b, 0x93, 0xb0, 0x9a, 0x95, 0x1a, 0x23, 0x78, 0x20, 0x51, 0xa4, 0x41, 0xe9, + 0x9a, 0x52, 0xe2, 0xd8, 0xae, 0xcd, 0x08, 0xdf, 0x7e, 0x4e, 0x6c, 0xbf, 0x70, 0x4d, 0x69, 0x97, + 0x63, 0x03, 0x8b, 0xa1, 0x27, 0x50, 0x5e, 0x72, 0xc4, 0x19, 0x4b, 0x82, 0x54, 0x8c, 0x49, 0xe2, + 0xa0, 0xcf, 0x41, 0xf5, 0xe7, 0xec, 0xc6, 0xb7, 0xbd, 0x1b, 0x32, 0x9e, 0x5a, 0x1e, 0xb1, 0x27, + 0xd5, 0x7c, 0x5d, 0x69, 0xa4, 0xcf, 0xb6, 0x5e, 0x28, 0xb8, 0x1c, 0xcb, 0x5a, 0x53, 0xcb, 0x33, + 0x26, 0xe8, 0x29, 0x54, 0x1c, 0x2b, 0x64, 0x64, 0xea, 0xcf, 0xc8, 0x6c, 0x7e, 0x75, 0x4b, 0xef, + 0xaa, 0x65, 0x71, 0x33, 0x25, 0x0e, 0x9f, 0xfb, 0xb3, 0x4b, 0x01, 0xa2, 0x23, 0x00, 0x71, 0x2b, + 0xc2, 0x78, 0x75, 0x5b, 0x9c, 0x61, 0x9b, 0x23, 0xc2, 0x30, 0xfa, 0x06, 0x0a, 0xc2, 0x9b, 0x64, + 0x6a, 0x7b, 0x2c, 0xac, 0x42, 0x3d, 0xd5, 0x28, 0x9c, 0xaa, 0xc7, 0x8e, 0xc7, 0x1d, 0x8b, 0xb9, + 0xe4, 0xdc, 0xf6, 0x18, 0x86, 0x20, 0xfe, 0x19, 0xa2, 0x09, 0xec, 0x72, 0x2f, 0x92, 0xf1, 0x3c, + 0x64, 0xbe, 0x4b, 0x02, 0x3a, 0xf6, 0x83, 0x49, 0x58, 0x2d, 0x88, 0xa5, 0xbf, 0x39, 0x5e, 0x3c, + 0x8e, 0xe3, 0xfb, 0xaf, 0xe1, 0xb8, 0x4d, 0x43, 0xd6, 0x12, 0xeb, 0xb0, 0x5c, 0xa6, 0x7b, 0x2c, + 0xb8, 0xc3, 0x3b, 0x93, 0x75, 0x1c, 0x3d, 0x07, 0x64, 0x39, 0x8e, 0xff, 0x33, 0x09, 0xa9, 0x73, + 0x4d, 0x22, 0xef, 0x54, 0x2b, 0x75, 0xa5, 0x91, 0xc7, 0xaa, 0x90, 0x0c, 0xa8, 0x73, 0x1d, 0xa9, + 0x47, 0x2f, 0xa1, 0x24, 0xf6, 0x74, 0x4d, 0x2d, 0x36, 0x0f, 0x68, 0x58, 0x55, 0xeb, 0xa9, 0x46, + 0xf9, 0x74, 0x27, 0x3a, 0x48, 0x47, 0xc2, 0x67, 0x36, 0xc3, 0x45, 0xce, 0x8b, 0xbe, 0xc3, 0x5a, + 0x1b, 0xf6, 0x37, 0x6f, 0x89, 0xbf, 0x51, 0x7e, 0xa7, 0xfc, 0xd9, 0xa6, 0x31, 0xff, 0x89, 0xf6, + 0x20, 0xf3, 0xde, 0x72, 0xe6, 0x54, 0xbc, 0xdb, 0x22, 0x96, 0x1f, 0xbf, 0xdd, 0x7a, 0xa5, 0x68, + 0xaf, 0x60, 0x77, 0x18, 0x58, 0xe3, 0xdb, 0xb5, 0xa7, 0xbf, 0xfe, 0x72, 0x95, 0x7b, 0x2f, 0x57, + 0xfb, 0xab, 0x02, 0xa5, 0x68, 0xd5, 0x80, 0x59, 0x6c, 0x1e, 0xa2, 0xaf, 0x21, 0x13, 0x32, 0x8b, + 0x51, 0xc1, 0x2e, 0x9f, 0x1e, 0x24, 0xee, 0x33, 0x41, 0xa4, 0x58, 0xb2, 0x50, 0x0d, 0xf2, 0xb3, + 0x80, 0xda, 0xae, 0x75, 0x13, 0xef, 0x6b, 0xf1, 0x8d, 0x34, 0xc8, 0x88, 0xc5, 0x22, 0x64, 0x0a, + 0xa7, 0xc5, 0xa4, 0x57, 0xb1, 0x14, 0xa1, 0x06, 0x64, 0xa6, 0xcc, 0x19, 0x87, 0xd5, 0xb4, 0x70, + 0x1f, 0x8a, 0x38, 0xe7, 0xc3, 0x6e, 0xab, 0xc9, 0x18, 0x75, 0x67, 0x0c, 0x4b, 0x82, 0xf6, 0x3b, + 0xa8, 0x88, 0x95, 0x1d, 0x4a, 0x3f, 0x16, 0xdb, 0x07, 0xc0, 0x23, 0x57, 0x44, 0x82, 0x8c, 0xef, + 0xac, 0xe5, 0xf2, 0x20, 0xd0, 0x26, 0xa0, 0x2e, 0xd7, 0x87, 0x33, 0xdf, 0x0b, 0xb9, 0x75, 0x95, + 0x6f, 0x83, 0xbf, 0x78, 0x1e, 0x20, 0x22, 0x34, 0x14, 0xb1, 0xaa, 0x1c, 0xe1, 0x1d, 0x4a, 0x45, + 0x70, 0x3c, 0x95, 0xf1, 0x48, 0x1c, 0x7f, 0x7c, 0xcb, 0x23, 0xdc, 0xba, 0x8b, 0xd4, 0x97, 0x38, + 0xdc, 0xf5, 0xc7, 0xb7, 0x6d, 0x0e, 0x6a, 0x3f, 0xca, 0x24, 0x34, 0xf4, 0xe5, 0x29, 0xff, 0x6f, + 0x4f, 0x2c, 0x2f, 0x6b, 0xeb, 0xc1, 0xcb, 0xd2, 0x08, 0xec, 0xae, 0x28, 0x8f, 0x4e, 0x91, 0xf4, + 0x81, 0xb2, 0xe6, 0x83, 0xe7, 0x90, 0xbb, 0xb6, 0x6c, 0x67, 0x1e, 0xc4, 0x8a, 0x51, 0xc2, 0xa1, + 0x1d, 0x29, 0xc1, 0x31, 0x45, 0xfb, 0x53, 0x1e, 0x72, 0x11, 0x88, 0x4e, 0x21, 0x3d, 0xf6, 0x27, + 0xf1, 0x3b, 0xf8, 0xec, 0xfe, 0xb2, 0xf8, 0x6f, 0xcb, 0x9f, 0x50, 0x2c, 0xb8, 0xe8, 0xf7, 0x50, + 0xe6, 0x99, 0xc3, 0xa3, 0x0e, 0x99, 0xcf, 0x26, 0xd6, 0xc2, 0xf5, 0xd5, 0xc4, 0xea, 0x96, 0x24, + 0x8c, 0x84, 0x1c, 0x97, 0xc6, 0xc9, 0x4f, 0x74, 0x08, 0xdb, 0xdc, 0xdb, 0xd2, 0x13, 0x69, 0xf1, + 0xf6, 0xf3, 0x1c, 0x10, 0x3e, 0xd0, 0xa0, 0xe4, 0x7b, 0xb6, 0xef, 0x91, 0x70, 0x6a, 0x91, 0xd3, + 0x6f, 0x5f, 0x8a, 0xd4, 0x59, 0xc4, 0x05, 0x01, 0x0e, 0xa6, 0xd6, 0xe9, 0xb7, 0x2f, 0xd1, 0xe7, + 0x50, 0x10, 0xe9, 0x86, 0x7e, 0x98, 0xd9, 0xc1, 0x9d, 0xc8, 0x99, 0x25, 0x2c, 0x32, 0x90, 0x2e, + 0x10, 0x1e, 0x45, 0xd7, 0x8e, 0x75, 0x13, 0x8a, 0x3c, 0x59, 0xc2, 0xf2, 0x03, 0xbd, 0x80, 0xbd, + 0xe8, 0x0e, 0x48, 0xe8, 0xcf, 0x83, 0x31, 0x25, 0xb6, 0x37, 0xa1, 0x1f, 0x44, 0xfe, 0x2b, 0x61, + 0x14, 0xc9, 0x06, 0x42, 0x64, 0x70, 0x09, 0xda, 0x87, 0xec, 0x94, 0xda, 0x37, 0x53, 0x99, 0xd3, + 0x4a, 0x38, 0xfa, 0xd2, 0xfe, 0x99, 0x81, 0x42, 0xe2, 0x62, 0x50, 0x11, 0xf2, 0x58, 0x1f, 0xe8, + 0xf8, 0xad, 0xde, 0x56, 0x3f, 0x41, 0x0d, 0x78, 0x62, 0x98, 0xad, 0x3e, 0xc6, 0x7a, 0x6b, 0x48, + 0xfa, 0x98, 0x8c, 0xcc, 0xd7, 0x66, 0xff, 0x7b, 0x93, 0x5c, 0x36, 0xdf, 0xf5, 0x74, 0x73, 0x48, + 0xda, 0xfa, 0xb0, 0x69, 0x74, 0x07, 0xaa, 0x82, 0x1e, 0x43, 0x75, 0xc9, 0x8c, 0xc5, 0xcd, 0x5e, + 0x7f, 0x64, 0x0e, 0xd5, 0x2d, 0xf4, 0x39, 0x1c, 0x76, 0x0c, 0xb3, 0xd9, 0x25, 0x4b, 0x4e, 0xab, + 0x3b, 0x7c, 0x4b, 0xf4, 0x1f, 0x2e, 0x0d, 0xfc, 0x4e, 0x4d, 0x6d, 0x22, 0xf0, 0x98, 0x8a, 0x35, + 0xa4, 0xd1, 0x23, 0xf8, 0x54, 0x12, 0xe4, 0x12, 0x32, 0xec, 0xf7, 0xc9, 0xa0, 0xdf, 0x37, 0xd5, + 0x0c, 0xda, 0x81, 0x92, 0x61, 0xbe, 0x6d, 0x76, 0x8d, 0x36, 0xc1, 0x7a, 0xb3, 0xdb, 0x53, 0xb3, + 0x68, 0x17, 0x2a, 0xeb, 0xbc, 0x1c, 0x57, 0x11, 0xf3, 0xfa, 0xa6, 0xd1, 0x37, 0xc9, 0x5b, 0x1d, + 0x0f, 0x8c, 0xbe, 0xa9, 0xe6, 0xd1, 0x3e, 0xa0, 0x55, 0xd1, 0x79, 0xaf, 0xd9, 0x52, 0xb7, 0xd1, + 0xa7, 0xb0, 0xb3, 0x8a, 0xbf, 0xd6, 0xdf, 0xa9, 0x80, 0xaa, 0xb0, 0x27, 0x37, 0x46, 0xce, 0xf4, + 0x6e, 0xff, 0x7b, 0xd2, 0x33, 0x4c, 0xa3, 0x37, 0xea, 0xa9, 0x05, 0xb4, 0x07, 0x6a, 0x47, 0xd7, + 0x89, 0x61, 0x0e, 0x46, 0x9d, 0x8e, 0xd1, 0x32, 0x74, 0x73, 0xa8, 0x16, 0xa5, 0xe5, 0x4d, 0x07, + 0x2f, 0xf1, 0x05, 0xad, 0xf3, 0xa6, 0x69, 0xea, 0x5d, 0xd2, 0x36, 0x06, 0xcd, 0xb3, 0xae, 0xde, + 0x56, 0xcb, 0xe8, 0x08, 0x1e, 0x0d, 0xf5, 0xde, 0x65, 0x1f, 0x37, 0xf1, 0x3b, 0x12, 0xcb, 0x3b, + 0x4d, 0xa3, 0x3b, 0xc2, 0xba, 0x5a, 0x41, 0x5f, 0xc0, 0x11, 0xd6, 0xdf, 0x8c, 0x0c, 0xac, 0xb7, + 0x89, 0xd9, 0x6f, 0xeb, 0xa4, 0xa3, 0x37, 0x87, 0x23, 0xac, 0x93, 0x9e, 0x31, 0x18, 0x18, 0xe6, + 0x77, 0xaa, 0x8a, 0x9e, 0x40, 0x7d, 0x41, 0x59, 0x28, 0x58, 0x63, 0xed, 0xf0, 0xf3, 0xc5, 0x2e, + 0x35, 0xf5, 0x1f, 0x86, 0xe4, 0x52, 0xd7, 0xb1, 0x8a, 0x50, 0x0d, 0xf6, 0x97, 0xe6, 0xa5, 0x81, + 0xc8, 0xf6, 0x2e, 0x97, 0x5d, 0xea, 0xb8, 0xd7, 0x34, 0xb9, 0x83, 0x57, 0x64, 0x7b, 0x7c, 0xdb, + 0x4b, 0xd9, 0xfa, 0xb6, 0x3f, 0x45, 0x08, 0xca, 0x09, 0xaf, 0x74, 0x9a, 0x58, 0xdd, 0x47, 0x15, + 0x28, 0xf4, 0x2e, 0x2f, 0xc9, 0xd0, 0xe8, 0xe9, 0xfd, 0xd1, 0x50, 0x3d, 0x40, 0x7b, 0x50, 0x89, + 0xb7, 0x14, 0xaf, 0xfc, 0x57, 0x0e, 0x1d, 0x00, 0x1a, 0x99, 0x58, 0x6f, 0xb6, 0xf9, 0x0d, 0x2d, + 0x04, 0xff, 0xce, 0x5d, 0xa4, 0xf3, 0x5b, 0x6a, 0x4a, 0xfb, 0x47, 0x0a, 0x4a, 0x2b, 0x81, 0x8a, + 0x1e, 0xc3, 0x76, 0x68, 0xdf, 0x78, 0xa2, 0x6e, 0x45, 0x59, 0x66, 0x09, 0x88, 0x2a, 0x3f, 0xb5, + 0x6c, 0x4f, 0xa6, 0x37, 0x59, 0x08, 0xb6, 0x05, 0x22, 0x92, 0xdb, 0x21, 0xe4, 0xe2, 0x8e, 0x22, + 0xb5, 0xe8, 0x28, 0xb2, 0x63, 0xd9, 0x49, 0x3c, 0x86, 0x6d, 0x9e, 0x43, 0x43, 0x66, 0xb9, 0x33, + 0x11, 0xf3, 0x25, 0xbc, 0x04, 0xd0, 0x97, 0x50, 0x72, 0x69, 0x18, 0x5a, 0x37, 0x94, 0xc8, 0xb8, + 0x05, 0xc1, 0x28, 0x46, 0x60, 0x47, 0x84, 0xef, 0x97, 0x10, 0xe7, 0x91, 0x88, 0x94, 0x91, 0xa4, + 0x08, 0x94, 0xa4, 0xf5, 0x14, 0xce, 0xac, 0x28, 0x3d, 0x24, 0x53, 0x38, 0xb3, 0xd0, 0x33, 0xd8, + 0x91, 0x39, 0xc8, 0xf6, 0x6c, 0x77, 0xee, 0xca, 0x5c, 0x94, 0x13, 0xb9, 0xa8, 0x22, 0x72, 0x91, + 0xc4, 0x45, 0x4a, 0x7a, 0x04, 0xf9, 0x2b, 0x2b, 0xa4, 0xbc, 0x7a, 0x44, 0xb9, 0x22, 0xc7, 0xbf, + 0x3b, 0x94, 0x72, 0x11, 0xaf, 0x29, 0x01, 0xcf, 0x82, 0x32, 0x45, 0xe4, 0xae, 0x29, 0xc5, 0xfc, + 0x2e, 0x17, 0x16, 0xac, 0x0f, 0x4b, 0x0b, 0x85, 0x84, 0x05, 0x89, 0x0b, 0x0b, 0xcf, 0x60, 0x87, + 0x7e, 0x60, 0x81, 0x45, 0xfc, 0x99, 0xf5, 0xd3, 0x9c, 0x92, 0x89, 0xc5, 0x2c, 0xd1, 0xa2, 0x16, + 0x71, 0x45, 0x08, 0xfa, 0x02, 0x6f, 0x5b, 0xcc, 0xd2, 0x1e, 0x43, 0x0d, 0xd3, 0x90, 0xb2, 0x9e, + 0x1d, 0x86, 0xb6, 0xef, 0xb5, 0x7c, 0x8f, 0x05, 0xbe, 0x13, 0x15, 0x21, 0xed, 0x08, 0x0e, 0x37, + 0x4a, 0x65, 0x15, 0xe1, 0x8b, 0xdf, 0xcc, 0x69, 0x70, 0xb7, 0x79, 0xf1, 0x1b, 0x38, 0xdc, 0x28, + 0x8d, 0x4a, 0xd0, 0x73, 0xc8, 0xcc, 0x2c, 0x3b, 0x08, 0xab, 0x5b, 0xa2, 0x8c, 0xef, 0xaf, 0x74, + 0x0d, 0x76, 0x70, 0x6e, 0x87, 0xcc, 0x0f, 0xee, 0xb0, 0x24, 0x5d, 0xa4, 0xf3, 0x8a, 0xba, 0xa5, + 0xfd, 0x59, 0x81, 0x42, 0x42, 0xc8, 0x73, 0xbf, 0xe7, 0x4f, 0x28, 0xb9, 0x0e, 0x7c, 0x37, 0xae, + 0x63, 0x1c, 0xe8, 0x04, 0xbe, 0xcb, 0xcb, 0xba, 0x10, 0x32, 0x3f, 0x7a, 0x5d, 0x59, 0xfe, 0x39, + 0xf4, 0xd1, 0xd7, 0x90, 0x9b, 0x4a, 0x05, 0xc2, 0x47, 0x85, 0xd3, 0xdd, 0x35, 0xdb, 0xfc, 0x66, + 0x70, 0xcc, 0xb9, 0x48, 0xe7, 0x53, 0x6a, 0xfa, 0x22, 0x9d, 0x4f, 0xab, 0x99, 0x8b, 0x74, 0x3e, + 0xa3, 0x66, 0x2f, 0xd2, 0xf9, 0xac, 0x9a, 0xd3, 0xfe, 0xa3, 0x40, 0x3e, 0x66, 0xf3, 0x9d, 0xf0, + 0x8c, 0x4f, 0xf8, 0xbb, 0x88, 0xfa, 0x81, 0x3c, 0x07, 0x86, 0xb6, 0x4b, 0x51, 0x1d, 0x8a, 0x42, + 0xb8, 0xda, 0x65, 0x00, 0xc7, 0x9a, 0xa2, 0xd3, 0x10, 0x2d, 0x79, 0xcc, 0x58, 0x14, 0x32, 0xde, + 0x92, 0x4b, 0x4a, 0x3c, 0x55, 0x84, 0xf3, 0xf1, 0x98, 0x86, 0xa1, 0xb4, 0x92, 0x91, 0x94, 0x08, + 0x13, 0x86, 0x9e, 0x42, 0x25, 0xa6, 0xc4, 0xb6, 0xb2, 0xb2, 0xe5, 0x88, 0xe0, 0xc8, 0x5c, 0x03, + 0xd4, 0x24, 0xcf, 0x5d, 0x0e, 0x01, 0xe5, 0x25, 0x91, 0x1b, 0x95, 0x87, 0xd7, 0xfe, 0x08, 0x07, + 0xc2, 0x95, 0x97, 0x81, 0x7f, 0x65, 0x5d, 0xd9, 0x8e, 0xcd, 0xee, 0xe2, 0x3e, 0x85, 0x1f, 0x3c, + 0xf0, 0x5d, 0xe2, 0xc5, 0x85, 0xbf, 0x88, 0xf3, 0x1c, 0x30, 0x79, 0x25, 0x3b, 0x80, 0x1c, 0xf3, + 0xa5, 0x28, 0x72, 0x01, 0xf3, 0x85, 0x20, 0x39, 0x3c, 0xa5, 0x56, 0x86, 0x27, 0xed, 0x16, 0xaa, + 0xf7, 0x6d, 0x45, 0x6f, 0xa6, 0x0e, 0x85, 0xd9, 0x12, 0x16, 0xe6, 0x14, 0x9c, 0x84, 0x92, 0xbe, + 0xdd, 0xfa, 0x65, 0xdf, 0x6a, 0x7f, 0x51, 0x60, 0xe7, 0x6c, 0x6e, 0x3b, 0x93, 0x95, 0xde, 0x2b, + 0xb9, 0x3b, 0x65, 0x75, 0xb4, 0xdb, 0x34, 0xb7, 0x6d, 0x6d, 0x9c, 0xdb, 0x36, 0xcd, 0x46, 0xa9, + 0x07, 0x67, 0xa3, 0xcf, 0xa1, 0xb0, 0x1c, 0x8b, 0x64, 0x6b, 0x5b, 0xc4, 0x30, 0x8d, 0x67, 0xa2, + 0x50, 0x7b, 0x05, 0x28, 0xb9, 0xd1, 0xe8, 0x42, 0x16, 0x2d, 0xa0, 0xf2, 0x60, 0x0b, 0xf8, 0xec, + 0xef, 0x0a, 0x14, 0x93, 0x7d, 0x38, 0x2a, 0xc1, 0xb6, 0x61, 0x92, 0x4e, 0xd7, 0xf8, 0xee, 0x7c, + 0xa8, 0x7e, 0xc2, 0x3f, 0x07, 0xa3, 0x56, 0x4b, 0xd7, 0xdb, 0x7a, 0x5b, 0x55, 0x78, 0x85, 0xe0, + 0xb9, 0x5d, 0x6f, 0x2f, 0x0a, 0xc2, 0x16, 0xaf, 0xe5, 0x11, 0x66, 0xf6, 0x09, 0xee, 0x8f, 0x86, + 0xba, 0x9a, 0x42, 0x2a, 0x14, 0x23, 0x50, 0xc7, 0xb8, 0x8f, 0xd5, 0x34, 0x2f, 0x78, 0x11, 0x72, + 0xbf, 0x0f, 0x89, 0xdb, 0x94, 0x8c, 0xe8, 0x33, 0x62, 0xd6, 0xb2, 0x44, 0x93, 0xb3, 0x66, 0xb7, + 0x69, 0xb6, 0x74, 0x35, 0x7b, 0xfa, 0xb7, 0x0c, 0x64, 0xc5, 0x09, 0x02, 0x74, 0x0e, 0x85, 0xc4, + 0x48, 0x86, 0x8e, 0x3e, 0x3a, 0xaa, 0xd5, 0xaa, 0x9b, 0x27, 0x8f, 0x79, 0xf8, 0x42, 0x41, 0x17, + 0x50, 0x4c, 0x0e, 0x3c, 0x28, 0xd9, 0x9d, 0x6e, 0x98, 0x84, 0x3e, 0xaa, 0xeb, 0x35, 0xa8, 0x7a, + 0xc8, 0x6c, 0x97, 0x77, 0xa3, 0xd1, 0x7c, 0x80, 0x6a, 0x09, 0xfe, 0xda, 0xd0, 0x51, 0x3b, 0xdc, + 0x28, 0x8b, 0x5c, 0xd8, 0x95, 0x47, 0x8c, 0x3a, 0xf4, 0x7b, 0x47, 0x5c, 0x1d, 0x0b, 0x6a, 0x9f, + 0x3d, 0x24, 0x8e, 0xb4, 0x4d, 0x60, 0x77, 0x43, 0xc6, 0x46, 0xbf, 0x4a, 0xee, 0xe0, 0xc1, 0x7c, + 0x5f, 0x7b, 0xfa, 0x4b, 0xb4, 0xa5, 0x95, 0x0d, 0xa9, 0x7d, 0xc5, 0xca, 0xc3, 0x85, 0x61, 0xc5, + 0xca, 0xc7, 0x2a, 0xc4, 0x8f, 0xa0, 0xae, 0x67, 0x02, 0xa4, 0xad, 0xaf, 0xbd, 0x9f, 0x92, 0x6a, + 0x5f, 0x7e, 0x94, 0x13, 0x29, 0x37, 0x00, 0x96, 0xf1, 0x84, 0x1e, 0x27, 0x96, 0xdc, 0xcb, 0x07, + 0xb5, 0xa3, 0x07, 0xa4, 0x52, 0xd5, 0xd9, 0x37, 0x7f, 0x38, 0xb9, 0xb1, 0xd9, 0x74, 0x7e, 0x75, + 0x3c, 0xf6, 0xdd, 0x13, 0x87, 0xf7, 0xf4, 0x9e, 0xed, 0xdd, 0x78, 0x94, 0xfd, 0xec, 0x07, 0xb7, + 0x27, 0x8e, 0x37, 0x39, 0x11, 0x61, 0x79, 0xb2, 0xd0, 0x72, 0x95, 0x15, 0xff, 0x80, 0xfa, 0xf5, + 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x77, 0x3e, 0x21, 0x8e, 0xb0, 0x12, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index bc5ad74d62..2f4d4d69ea 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -26,7 +26,7 @@ message SendPaymentRequest { /// The hash to use within the payment's HTLC bytes payment_hash = 3; - + /** The CLTV delta from the current height that should be used to set the timelock for the final hop. @@ -60,15 +60,15 @@ message SendPaymentRequest { */ int64 fee_limit_sat = 7; - /** - The maximum number of millisatoshis that will be paid as a fee of the - payment. If this field is left to the default value of 0, only zero-fee - routes will be considered. This usually means single hop routes connecting - directly to the destination. To send the payment without a fee limit, use - max int here. - - The fields fee_limit_sat and fee_limit_msat are mutually exclusive. - */ + /** + The maximum number of millisatoshis that will be paid as a fee of the + payment. If this field is left to the default value of 0, only zero-fee + routes will be considered. This usually means single hop routes connecting + directly to the destination. To send the payment without a fee limit, use + max int here. + + The fields fee_limit_sat and fee_limit_msat are mutually exclusive. + */ int64 fee_limit_msat = 13; /** @@ -92,7 +92,7 @@ message SendPaymentRequest { /** Optional route hints to reach the destination through private channels. */ - repeated lnrpc.RouteHint route_hints = 10 [json_name = "route_hints"]; + repeated lnrpc.RouteHint route_hints = 10; /** An optional field that can be used to pass an arbitrary set of TLV records @@ -136,7 +136,7 @@ enum PaymentState { There are more routes to try, but the payment timeout was exceeded. */ FAILED_TIMEOUT = 2; - + /** All possible routes were tried and failed permanently. Or were no routes to the destination at all. @@ -368,12 +368,12 @@ message ChannelUpdate { The fee rate that will be charged per millionth of a satoshi. */ uint32 fee_rate = 9; - + /** The maximum HTLC value which will be accepted. */ uint64 htlc_maximum_msat = 11; - + /** The set of data that was appended to this message, some of which we may not actually know how to iterate or parse. By holding onto this data, we @@ -383,78 +383,81 @@ message ChannelUpdate { */ bytes extra_opaque_data = 12; } -message ResetMissionControlRequest{} +message ResetMissionControlRequest { +} -message ResetMissionControlResponse{} +message ResetMissionControlResponse { +} -message QueryMissionControlRequest {} +message QueryMissionControlRequest { +} /// QueryMissionControlResponse contains mission control state. message QueryMissionControlResponse { reserved 1; /// Node pair-level mission control state. - repeated PairHistory pairs = 2 [json_name = "pairs"]; + repeated PairHistory pairs = 2; } /// PairHistory contains the mission control state for a particular node pair. message PairHistory { /// The source node pubkey of the pair. - bytes node_from = 1 [json_name ="node_from"]; - + bytes node_from = 1; + /// The destination node pubkey of the pair. - bytes node_to = 2 [json_name="node_to"]; + bytes node_to = 2; reserved 3, 4, 5, 6; - PairData history = 7 [json_name="history"]; + PairData history = 7; } message PairData { /// Time of last failure. - int64 fail_time = 1 [json_name = "fail_time"]; + int64 fail_time = 1; /** Lowest amount that failed to forward rounded to whole sats. This may be set to zero if the failure is independent of amount. */ - int64 fail_amt_sat = 2 [json_name = "fail_amt_sat"]; + int64 fail_amt_sat = 2; /** Lowest amount that failed to forward in millisats. This may be set to zero if the failure is independent of amount. */ - int64 fail_amt_msat = 4 [json_name = "fail_amt_msat"]; + int64 fail_amt_msat = 4; reserved 3; /// Time of last success. - int64 success_time = 5 [json_name = "success_time"]; + int64 success_time = 5; /// Highest amount that we could successfully forward rounded to whole sats. - int64 success_amt_sat = 6 [json_name = "success_amt_sat"]; + int64 success_amt_sat = 6; /// Highest amount that we could successfully forward in millisats. - int64 success_amt_msat = 7 [json_name = "success_amt_msat"]; + int64 success_amt_msat = 7; } -message QueryProbabilityRequest{ +message QueryProbabilityRequest { /// The source node pubkey of the pair. - bytes from_node = 1 [json_name = "from_node"]; + bytes from_node = 1; /// The destination node pubkey of the pair. - bytes to_node = 2 [json_name = "to_node"]; + bytes to_node = 2; /// The amount for which to calculate a probability. - int64 amt_msat = 3 [json_name = "amt_msat"]; + int64 amt_msat = 3; } -message QueryProbabilityResponse{ +message QueryProbabilityResponse { /// The success probability for the requested pair. - double probability = 1 [json_name = "probability"]; + double probability = 1; /// The historical data for the requested pair. - PairData history = 2 [json_name = "history"]; + PairData history = 2; } message BuildRouteRequest { @@ -496,50 +499,49 @@ service Router { PaymentRequest to the final destination. The call returns a stream of payment status updates. */ - rpc SendPayment(SendPaymentRequest) returns (stream PaymentStatus); + rpc SendPayment (SendPaymentRequest) returns (stream PaymentStatus); /** TrackPayment returns an update stream for the payment identified by the payment hash. */ - rpc TrackPayment(TrackPaymentRequest) returns (stream PaymentStatus); - + rpc TrackPayment (TrackPaymentRequest) returns (stream PaymentStatus); /** EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it may cost to send an HTLC to the target end destination. */ - rpc EstimateRouteFee(RouteFeeRequest) returns (RouteFeeResponse); + rpc EstimateRouteFee (RouteFeeRequest) returns (RouteFeeResponse); /** SendToRoute attempts to make a payment via the specified route. This method differs from SendPayment in that it allows users to specify a full route manually. This can be used for things like rebalancing, and atomic swaps. */ - rpc SendToRoute(SendToRouteRequest) returns (SendToRouteResponse); + rpc SendToRoute (SendToRouteRequest) returns (SendToRouteResponse); /** ResetMissionControl clears all mission control state and starts with a clean slate. */ - rpc ResetMissionControl(ResetMissionControlRequest) returns (ResetMissionControlResponse); - + rpc ResetMissionControl (ResetMissionControlRequest) returns (ResetMissionControlResponse); + /** QueryMissionControl exposes the internal mission control state to callers. It is a development feature. */ - rpc QueryMissionControl(QueryMissionControlRequest) returns (QueryMissionControlResponse); + rpc QueryMissionControl (QueryMissionControlRequest) returns (QueryMissionControlResponse); /** QueryProbability returns the current success probability estimate for a given node pair and amount. */ - rpc QueryProbability(QueryProbabilityRequest) returns (QueryProbabilityResponse); + rpc QueryProbability (QueryProbabilityRequest) returns (QueryProbabilityResponse); /** BuildRoute builds a fully specified route based on a list of hop public keys. It retrieves the relevant channel policies from the graph in order to calculate the correct fees and time locks. */ - rpc BuildRoute(BuildRouteRequest) returns (BuildRouteResponse); + rpc BuildRoute (BuildRouteRequest) returns (BuildRouteResponse); } From 5a35ffa395aca01ffcc3f222fcb1e795394a0528 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 13:59:22 +0100 Subject: [PATCH 142/562] signrpc: format signer.proto --- lnrpc/signrpc/signer.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnrpc/signrpc/signer.proto b/lnrpc/signrpc/signer.proto index 6c86acfd57..04422feb9f 100644 --- a/lnrpc/signrpc/signer.proto +++ b/lnrpc/signrpc/signer.proto @@ -154,7 +154,7 @@ message VerifyMessageResp { message SharedKeyRequest { // The ephemeral public key to use for the DH key derivation. bytes ephemeral_pubkey = 1; - + /** The optional key locator of the local key that should be used. If this parameter is not set then the node's identity private key will be used. From 54fede0ae9e166acde846580f68cd40f082fdd41 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 14:00:41 +0100 Subject: [PATCH 143/562] walletrpc: format walletkit.proto and remove json_name fields We now use the jsonpb marshaler to convert the RPC responses to JSON in lncli and REST. The jsonpb has a setting to use the original name as defined in the proto file and the explicit json_name definition is not necessary any more. The jsonpb setting is called OrigName and needs to be true. --- lnrpc/walletrpc/walletkit.pb.go | 153 ++++++++++++++++---------------- lnrpc/walletrpc/walletkit.proto | 46 +++++----- 2 files changed, 100 insertions(+), 99 deletions(-) diff --git a/lnrpc/walletrpc/walletkit.pb.go b/lnrpc/walletrpc/walletkit.pb.go index e2ded0cc0c..a8b5623679 100644 --- a/lnrpc/walletrpc/walletkit.pb.go +++ b/lnrpc/walletrpc/walletkit.pb.go @@ -518,24 +518,24 @@ type PendingSweep struct { // The outpoint of the output we're attempting to sweep. Outpoint *lnrpc.OutPoint `protobuf:"bytes,1,opt,name=outpoint,proto3" json:"outpoint,omitempty"` // The witness type of the output we're attempting to sweep. - WitnessType WitnessType `protobuf:"varint,2,opt,name=witness_type,proto3,enum=walletrpc.WitnessType" json:"witness_type,omitempty"` + WitnessType WitnessType `protobuf:"varint,2,opt,name=witness_type,json=witnessType,proto3,enum=walletrpc.WitnessType" json:"witness_type,omitempty"` // The value of the output we're attempting to sweep. - AmountSat uint32 `protobuf:"varint,3,opt,name=amount_sat,proto3" json:"amount_sat,omitempty"` + AmountSat uint32 `protobuf:"varint,3,opt,name=amount_sat,json=amountSat,proto3" json:"amount_sat,omitempty"` // //The fee rate we'll use to sweep the output. The fee rate is only determined //once a sweeping transaction for the output is created, so it's possible for //this to be 0 before this. - SatPerByte uint32 `protobuf:"varint,4,opt,name=sat_per_byte,proto3" json:"sat_per_byte,omitempty"` + SatPerByte uint32 `protobuf:"varint,4,opt,name=sat_per_byte,json=satPerByte,proto3" json:"sat_per_byte,omitempty"` // The number of broadcast attempts we've made to sweep the output. - BroadcastAttempts uint32 `protobuf:"varint,5,opt,name=broadcast_attempts,proto3" json:"broadcast_attempts,omitempty"` + BroadcastAttempts uint32 `protobuf:"varint,5,opt,name=broadcast_attempts,json=broadcastAttempts,proto3" json:"broadcast_attempts,omitempty"` // //The next height of the chain at which we'll attempt to broadcast the //sweep transaction of the output. - NextBroadcastHeight uint32 `protobuf:"varint,6,opt,name=next_broadcast_height,proto3" json:"next_broadcast_height,omitempty"` + NextBroadcastHeight uint32 `protobuf:"varint,6,opt,name=next_broadcast_height,json=nextBroadcastHeight,proto3" json:"next_broadcast_height,omitempty"` // The requested confirmation target for this output. - RequestedConfTarget uint32 `protobuf:"varint,8,opt,name=requested_conf_target,proto3" json:"requested_conf_target,omitempty"` + RequestedConfTarget uint32 `protobuf:"varint,8,opt,name=requested_conf_target,json=requestedConfTarget,proto3" json:"requested_conf_target,omitempty"` // The requested fee rate, expressed in sat/byte, for this output. - RequestedSatPerByte uint32 `protobuf:"varint,9,opt,name=requested_sat_per_byte,proto3" json:"requested_sat_per_byte,omitempty"` + RequestedSatPerByte uint32 `protobuf:"varint,9,opt,name=requested_sat_per_byte,json=requestedSatPerByte,proto3" json:"requested_sat_per_byte,omitempty"` //* //Whether this input must be force-swept. This means that it is swept even //if it has a negative yield. @@ -667,7 +667,7 @@ var xxx_messageInfo_PendingSweepsRequest proto.InternalMessageInfo type PendingSweepsResponse struct { // //The set of outputs currently being swept by lnd's central batching engine. - PendingSweeps []*PendingSweep `protobuf:"bytes,1,rep,name=pending_sweeps,proto3" json:"pending_sweeps,omitempty"` + PendingSweeps []*PendingSweep `protobuf:"bytes,1,rep,name=pending_sweeps,json=pendingSweeps,proto3" json:"pending_sweeps,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -709,11 +709,11 @@ type BumpFeeRequest struct { // The input we're attempting to bump the fee of. Outpoint *lnrpc.OutPoint `protobuf:"bytes,1,opt,name=outpoint,proto3" json:"outpoint,omitempty"` // The target number of blocks that the input should be spent within. - TargetConf uint32 `protobuf:"varint,2,opt,name=target_conf,proto3" json:"target_conf,omitempty"` + TargetConf uint32 `protobuf:"varint,2,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` // //The fee rate, expressed in sat/byte, that should be used to spend the input //with. - SatPerByte uint32 `protobuf:"varint,3,opt,name=sat_per_byte,proto3" json:"sat_per_byte,omitempty"` + SatPerByte uint32 `protobuf:"varint,3,opt,name=sat_per_byte,json=satPerByte,proto3" json:"sat_per_byte,omitempty"` //* //Whether this input must be force-swept. This means that it is swept even //if it has a negative yield. @@ -828,72 +828,73 @@ func init() { func init() { proto.RegisterFile("walletrpc/walletkit.proto", fileDescriptor_6cc6942ac78249e5) } var fileDescriptor_6cc6942ac78249e5 = []byte{ - // 1026 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x6d, 0x6f, 0xe2, 0xc6, - 0x13, 0xff, 0x13, 0x12, 0x02, 0x03, 0x24, 0xce, 0xe6, 0xc9, 0xc7, 0xe5, 0x2e, 0xfc, 0xdd, 0x07, - 0xa1, 0xb6, 0x02, 0x35, 0xd7, 0x9e, 0xaa, 0xf6, 0x45, 0x9b, 0x23, 0x8e, 0x12, 0x41, 0x30, 0xb5, - 0x9d, 0x4b, 0xaf, 0xaa, 0xb4, 0x72, 0x60, 0x03, 0x16, 0x60, 0xfb, 0xd6, 0x4b, 0x81, 0xb7, 0xfd, - 0x16, 0xfd, 0x00, 0xfd, 0x12, 0xfd, 0x74, 0x95, 0xd7, 0x0f, 0x59, 0xf3, 0x50, 0xa9, 0xaf, 0x82, - 0x7f, 0xbf, 0xdf, 0xcc, 0xce, 0xce, 0xcc, 0xce, 0x04, 0x5e, 0xcc, 0xac, 0xf1, 0x98, 0x30, 0xea, - 0xf5, 0x1a, 0xe1, 0xaf, 0x91, 0xcd, 0xea, 0x1e, 0x75, 0x99, 0x8b, 0x0a, 0x09, 0x55, 0x29, 0x50, - 0xaf, 0x17, 0xa2, 0x95, 0x23, 0xdf, 0x1e, 0x38, 0x81, 0x3c, 0xf8, 0x4b, 0x68, 0x88, 0x2a, 0x3f, - 0x43, 0xae, 0x45, 0x16, 0x3a, 0xf9, 0x88, 0x6a, 0x20, 0x8d, 0xc8, 0x02, 0x3f, 0xd9, 0xce, 0x80, - 0x50, 0xec, 0x51, 0xdb, 0x61, 0x72, 0xa6, 0x9a, 0xa9, 0xed, 0xe8, 0x7b, 0x23, 0xb2, 0xb8, 0xe6, - 0x70, 0x37, 0x40, 0xd1, 0x2b, 0x00, 0xae, 0xb4, 0x26, 0xf6, 0x78, 0x21, 0x6f, 0x71, 0x4d, 0x21, - 0xd0, 0x70, 0x40, 0x29, 0x43, 0xf1, 0xb2, 0xdf, 0xa7, 0x3a, 0xf9, 0x38, 0x25, 0x3e, 0x53, 0x14, - 0x28, 0x85, 0x9f, 0xbe, 0xe7, 0x3a, 0x3e, 0x41, 0x08, 0xb6, 0xad, 0x7e, 0x9f, 0x72, 0xdf, 0x05, - 0x9d, 0xff, 0x56, 0x3e, 0x85, 0xa2, 0x49, 0x2d, 0xc7, 0xb7, 0x7a, 0xcc, 0x76, 0x1d, 0x74, 0x0c, - 0x39, 0x36, 0xc7, 0x43, 0x32, 0xe7, 0xa2, 0x92, 0xbe, 0xc3, 0xe6, 0x37, 0x64, 0xae, 0xbc, 0x85, - 0xfd, 0xee, 0xf4, 0x71, 0x6c, 0xfb, 0xc3, 0xc4, 0xd9, 0x27, 0x50, 0xf6, 0x42, 0x08, 0x13, 0x4a, - 0xdd, 0xd8, 0x6b, 0x29, 0x02, 0xd5, 0x00, 0x53, 0x7e, 0x03, 0x64, 0x10, 0xa7, 0xaf, 0x4d, 0x99, - 0x37, 0x65, 0x7e, 0x14, 0x17, 0x3a, 0x03, 0xf0, 0x2d, 0x86, 0x3d, 0x42, 0xf1, 0x68, 0xc6, 0xed, - 0xb2, 0x7a, 0xde, 0xb7, 0x58, 0x97, 0xd0, 0xd6, 0x0c, 0xd5, 0x60, 0xd7, 0x0d, 0xf5, 0xf2, 0x56, - 0x35, 0x5b, 0x2b, 0x5e, 0xec, 0xd5, 0xa3, 0xfc, 0xd5, 0xcd, 0xb9, 0x36, 0x65, 0x7a, 0x4c, 0x2b, - 0x5f, 0xc1, 0x61, 0xca, 0x7b, 0x14, 0xd9, 0x31, 0xe4, 0xa8, 0x35, 0xc3, 0x2c, 0xb9, 0x03, 0xb5, - 0x66, 0xe6, 0x5c, 0xf9, 0x16, 0x90, 0xea, 0x33, 0x7b, 0x62, 0x31, 0x72, 0x4d, 0x48, 0x1c, 0xcb, - 0x39, 0x14, 0x7b, 0xae, 0xf3, 0x84, 0x99, 0x45, 0x07, 0x24, 0x4e, 0x3b, 0x04, 0x90, 0xc9, 0x11, - 0xe5, 0x0d, 0x1c, 0xa6, 0xcc, 0xa2, 0x43, 0xfe, 0xf5, 0x0e, 0xca, 0x5f, 0x59, 0x28, 0x75, 0x89, - 0xd3, 0xb7, 0x9d, 0x81, 0x31, 0x23, 0xc4, 0x43, 0x5f, 0x42, 0x3e, 0x88, 0xda, 0x8d, 0x4b, 0x5b, - 0xbc, 0xd8, 0xaf, 0x8f, 0xf9, 0x9d, 0xb4, 0x29, 0xeb, 0x06, 0xb0, 0x9e, 0x08, 0xd0, 0xf7, 0x50, - 0x9a, 0xd9, 0xcc, 0x21, 0xbe, 0x8f, 0xd9, 0xc2, 0x23, 0xbc, 0xce, 0x7b, 0x17, 0x27, 0xf5, 0xa4, - 0xb9, 0xea, 0x0f, 0x21, 0x6d, 0x2e, 0x3c, 0xa2, 0xa7, 0xb4, 0xe8, 0x35, 0x80, 0x35, 0x71, 0xa7, - 0x0e, 0xc3, 0xbe, 0xc5, 0xe4, 0x6c, 0x35, 0x53, 0x2b, 0xeb, 0x02, 0x82, 0x14, 0x28, 0xc5, 0x71, - 0x3f, 0x2e, 0x18, 0x91, 0xb7, 0xb9, 0x22, 0x85, 0xa1, 0x3a, 0xa0, 0x47, 0xea, 0x5a, 0xfd, 0x9e, - 0xe5, 0x33, 0x6c, 0x31, 0x46, 0x26, 0x1e, 0xf3, 0xe5, 0x1d, 0xae, 0x5c, 0xc3, 0xa0, 0x6f, 0xe0, - 0xd8, 0x21, 0x73, 0x86, 0x9f, 0xa9, 0x21, 0xb1, 0x07, 0x43, 0x26, 0xe7, 0xb8, 0xc9, 0x7a, 0x32, - 0xb0, 0xa2, 0x61, 0x11, 0x48, 0x1f, 0x8b, 0x35, 0xc8, 0x87, 0x56, 0x6b, 0x49, 0xf4, 0x16, 0x4e, - 0x9e, 0x89, 0xd4, 0x4d, 0x0a, 0xdc, 0x6c, 0x03, 0x8b, 0x8e, 0x60, 0xe7, 0xc9, 0xa5, 0x3d, 0x22, - 0xef, 0x56, 0x33, 0xb5, 0xbc, 0x1e, 0x7e, 0x28, 0x27, 0x70, 0x24, 0x96, 0x29, 0xee, 0x50, 0xe5, - 0x17, 0x38, 0x5e, 0xc2, 0xa3, 0xb2, 0xff, 0x08, 0x7b, 0x5e, 0x48, 0x60, 0x9f, 0x33, 0x72, 0x86, - 0xf7, 0xe8, 0xa9, 0x50, 0x1c, 0xd1, 0x52, 0x5f, 0x92, 0x2b, 0x7f, 0x66, 0x60, 0xef, 0xdd, 0x74, - 0xe2, 0x09, 0x2d, 0xf8, 0x9f, 0x7a, 0xa3, 0x0a, 0xc5, 0x30, 0x13, 0x3c, 0x2b, 0xbc, 0x35, 0xca, - 0xba, 0x08, 0xad, 0x54, 0x38, 0xbb, 0xa6, 0xc2, 0x49, 0x36, 0xb6, 0xc5, 0x6c, 0x1c, 0xc0, 0x7e, - 0x12, 0x5a, 0x78, 0xdf, 0x2f, 0xfe, 0xc8, 0x42, 0x51, 0x68, 0x36, 0x74, 0x08, 0xfb, 0xf7, 0x9d, - 0x56, 0x47, 0x7b, 0xe8, 0xe0, 0x87, 0x5b, 0xb3, 0xa3, 0x1a, 0x86, 0xf4, 0x3f, 0x24, 0xc3, 0x51, - 0x53, 0xbb, 0xbb, 0xbb, 0x35, 0xef, 0xd4, 0x8e, 0x89, 0xcd, 0xdb, 0x3b, 0x15, 0xb7, 0xb5, 0x66, - 0x4b, 0xca, 0xa0, 0x53, 0x38, 0x14, 0x98, 0x8e, 0x86, 0xaf, 0xd4, 0xf6, 0xe5, 0x07, 0x69, 0x0b, - 0x1d, 0xc3, 0x81, 0x40, 0xe8, 0xea, 0x7b, 0xad, 0xa5, 0x4a, 0xd9, 0x40, 0x7f, 0x63, 0xb6, 0x9b, - 0x58, 0xbb, 0xbe, 0x56, 0x75, 0xf5, 0x2a, 0x26, 0xb6, 0x83, 0x23, 0x38, 0x71, 0xd9, 0x6c, 0xaa, - 0x5d, 0xf3, 0x99, 0xd9, 0x41, 0x9f, 0xc1, 0xff, 0x53, 0x26, 0xc1, 0xf1, 0xda, 0xbd, 0x89, 0x0d, - 0xb5, 0xa9, 0x75, 0xae, 0x70, 0x5b, 0x7d, 0xaf, 0xb6, 0xa5, 0x1c, 0xfa, 0x1c, 0x94, 0xb4, 0x03, - 0xe3, 0xbe, 0xd9, 0x54, 0x0d, 0x23, 0xad, 0xdb, 0x45, 0xe7, 0xf0, 0x72, 0x29, 0x82, 0x3b, 0xcd, - 0x54, 0x63, 0xaf, 0x52, 0x1e, 0x55, 0xe1, 0x6c, 0x39, 0x12, 0xae, 0x88, 0xfc, 0x49, 0x05, 0x74, - 0x06, 0x32, 0x57, 0x88, 0x9e, 0xe3, 0x78, 0x01, 0x1d, 0x81, 0x14, 0x65, 0x0e, 0xb7, 0xd4, 0x0f, - 0xf8, 0xe6, 0xd2, 0xb8, 0x91, 0x8a, 0xe8, 0x25, 0x9c, 0x76, 0x54, 0x23, 0x70, 0xb7, 0x42, 0x96, - 0x2e, 0xfe, 0xde, 0x86, 0xc2, 0x03, 0x6f, 0xaf, 0x96, 0x1d, 0x4c, 0x87, 0xf2, 0x15, 0xa1, 0xf6, - 0xef, 0xa4, 0x43, 0xe6, 0xac, 0x45, 0x16, 0xe8, 0x40, 0xe8, 0xbd, 0x70, 0xa3, 0x54, 0x4e, 0x92, - 0x91, 0xd9, 0x22, 0x8b, 0x2b, 0xe2, 0xf7, 0xa8, 0xed, 0x31, 0x97, 0xa2, 0xef, 0xa0, 0x10, 0xda, - 0x06, 0x76, 0x87, 0xa2, 0xa8, 0xed, 0xf6, 0x2c, 0xe6, 0xd2, 0x8d, 0x96, 0x3f, 0x40, 0x3e, 0x38, - 0x2f, 0xd8, 0x27, 0x48, 0x9c, 0x44, 0xc2, 0xbe, 0xa9, 0x9c, 0xae, 0xe0, 0xd1, 0xab, 0xb9, 0x01, - 0x14, 0xad, 0x0f, 0x71, 0xd7, 0x88, 0x6e, 0x04, 0xbc, 0x52, 0x11, 0xdf, 0xd2, 0xd2, 0xd6, 0x69, - 0x43, 0x51, 0x18, 0xf9, 0xe8, 0x95, 0x20, 0x5d, 0x5d, 0x34, 0x95, 0xd7, 0x9b, 0xe8, 0x67, 0x6f, - 0xc2, 0x6c, 0x4f, 0x79, 0x5b, 0x5d, 0x15, 0x29, 0x6f, 0xeb, 0x56, 0x82, 0x0e, 0xe5, 0xd4, 0xd0, - 0x40, 0xe7, 0x1b, 0x86, 0x42, 0x12, 0x5f, 0x75, 0xb3, 0x20, 0xf2, 0xf9, 0x13, 0xec, 0x46, 0x4f, - 0x12, 0xbd, 0x10, 0xc4, 0xe9, 0x09, 0x92, 0xca, 0xd8, 0xd2, 0x0b, 0x7e, 0xf7, 0xf5, 0xaf, 0x8d, - 0x81, 0xcd, 0x86, 0xd3, 0xc7, 0x7a, 0xcf, 0x9d, 0x34, 0xc6, 0xc1, 0xe8, 0x75, 0x6c, 0x67, 0xe0, - 0x10, 0x36, 0x73, 0xe9, 0xa8, 0x31, 0x76, 0xfa, 0x0d, 0x3e, 0x6c, 0x1a, 0x89, 0x8b, 0xc7, 0x1c, - 0xff, 0x07, 0xe5, 0xcd, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5a, 0x4e, 0xaf, 0xaf, 0xe9, 0x08, - 0x00, 0x00, + // 1047 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x6b, 0x6f, 0xea, 0x46, + 0x10, 0x2d, 0x21, 0x21, 0x30, 0x40, 0x42, 0x96, 0x3c, 0x7c, 0xb9, 0xb9, 0x0d, 0x75, 0x1f, 0x42, + 0x7d, 0x80, 0x9a, 0xa8, 0x55, 0x1f, 0x52, 0xd5, 0x84, 0x38, 0x22, 0x82, 0x60, 0x6a, 0x3b, 0x37, + 0xba, 0x55, 0xa5, 0x95, 0x03, 0x1b, 0x62, 0x01, 0xb6, 0xef, 0x7a, 0x29, 0xf8, 0x6b, 0x7f, 0x44, + 0xa5, 0xfe, 0x95, 0xfe, 0xba, 0xca, 0xeb, 0x07, 0x6b, 0x68, 0x2a, 0xf5, 0x53, 0xf0, 0x39, 0x67, + 0x8e, 0x67, 0x67, 0xc7, 0x33, 0x81, 0x57, 0x0b, 0x73, 0x3a, 0x25, 0x8c, 0xba, 0xc3, 0x56, 0xf8, + 0x6b, 0x62, 0xb1, 0xa6, 0x4b, 0x1d, 0xe6, 0xa0, 0x42, 0x42, 0xd5, 0x0a, 0xd4, 0x1d, 0x86, 0x68, + 0xed, 0xd0, 0xb3, 0xc6, 0x76, 0x20, 0x0f, 0xfe, 0x12, 0x1a, 0xa2, 0xf2, 0x2f, 0x90, 0xeb, 0x12, + 0x5f, 0x23, 0xef, 0x51, 0x03, 0x2a, 0x13, 0xe2, 0xe3, 0x27, 0xcb, 0x1e, 0x13, 0x8a, 0x5d, 0x6a, + 0xd9, 0x4c, 0xca, 0xd4, 0x33, 0x8d, 0x1d, 0x6d, 0x6f, 0x42, 0xfc, 0x1b, 0x0e, 0x0f, 0x02, 0x14, + 0xbd, 0x01, 0xe0, 0x4a, 0x73, 0x66, 0x4d, 0x7d, 0x69, 0x8b, 0x6b, 0x0a, 0x81, 0x86, 0x03, 0x72, + 0x19, 0x8a, 0x97, 0xa3, 0x11, 0xd5, 0xc8, 0xfb, 0x39, 0xf1, 0x98, 0x2c, 0x43, 0x29, 0x7c, 0xf4, + 0x5c, 0xc7, 0xf6, 0x08, 0x42, 0xb0, 0x6d, 0x8e, 0x46, 0x94, 0x7b, 0x17, 0x34, 0xfe, 0x5b, 0xfe, + 0x04, 0x8a, 0x06, 0x35, 0x6d, 0xcf, 0x1c, 0x32, 0xcb, 0xb1, 0xd1, 0x11, 0xe4, 0xd8, 0x12, 0x3f, + 0x93, 0x25, 0x17, 0x95, 0xb4, 0x1d, 0xb6, 0xec, 0x90, 0xa5, 0xfc, 0x2d, 0xec, 0x0f, 0xe6, 0x8f, + 0x53, 0xcb, 0x7b, 0x4e, 0xcc, 0x3e, 0x86, 0xb2, 0x1b, 0x42, 0x98, 0x50, 0xea, 0xc4, 0xae, 0xa5, + 0x08, 0x54, 0x02, 0x4c, 0xfe, 0x0d, 0x90, 0x4e, 0xec, 0x91, 0x3a, 0x67, 0xee, 0x9c, 0x79, 0x51, + 0x5e, 0xe8, 0x14, 0xc0, 0x33, 0x19, 0x76, 0x09, 0xc5, 0x93, 0x05, 0x8f, 0xcb, 0x6a, 0x79, 0xcf, + 0x64, 0x03, 0x42, 0xbb, 0x0b, 0xd4, 0x80, 0x5d, 0x27, 0xd4, 0x4b, 0x5b, 0xf5, 0x6c, 0xa3, 0x78, + 0xbe, 0xd7, 0x8c, 0xea, 0xd7, 0x34, 0x96, 0xea, 0x9c, 0x69, 0x31, 0x2d, 0x7f, 0x09, 0xd5, 0x94, + 0x7b, 0x94, 0xd9, 0x11, 0xe4, 0xa8, 0xb9, 0xc0, 0x2c, 0x39, 0x03, 0x35, 0x17, 0xc6, 0x52, 0xfe, + 0x06, 0x90, 0xe2, 0x31, 0x6b, 0x66, 0x32, 0x72, 0x43, 0x48, 0x9c, 0xcb, 0x19, 0x14, 0x87, 0x8e, + 0xfd, 0x84, 0x99, 0x49, 0xc7, 0x24, 0x2e, 0x3b, 0x04, 0x90, 0xc1, 0x11, 0xf9, 0x02, 0xaa, 0xa9, + 0xb0, 0xe8, 0x25, 0xff, 0x79, 0x06, 0xf9, 0xaf, 0x2c, 0x94, 0x06, 0xc4, 0x1e, 0x59, 0xf6, 0x58, + 0x5f, 0x10, 0xe2, 0xa2, 0x2f, 0x20, 0x1f, 0x64, 0xed, 0xc4, 0x57, 0x5b, 0x3c, 0xdf, 0x6f, 0x4e, + 0xf9, 0x99, 0xd4, 0x39, 0x1b, 0x04, 0xb0, 0x96, 0x08, 0xd0, 0xf7, 0x50, 0x5a, 0x58, 0xcc, 0x26, + 0x9e, 0x87, 0x99, 0xef, 0x12, 0x7e, 0xcf, 0x7b, 0xe7, 0xc7, 0xcd, 0xa4, 0xb9, 0x9a, 0x0f, 0x21, + 0x6d, 0xf8, 0x2e, 0xd1, 0x8a, 0x8b, 0xd5, 0x43, 0xd0, 0x20, 0xe6, 0xcc, 0x99, 0xdb, 0x0c, 0x7b, + 0x26, 0x93, 0xb2, 0xf5, 0x4c, 0xa3, 0xac, 0x15, 0x42, 0x44, 0x37, 0x19, 0xaa, 0x43, 0x29, 0xce, + 0xfa, 0xd1, 0x67, 0x44, 0xda, 0xe6, 0x02, 0x08, 0xf3, 0xbe, 0xf2, 0x19, 0x41, 0x5f, 0x01, 0x7a, + 0xa4, 0x8e, 0x39, 0x1a, 0x9a, 0x1e, 0xc3, 0x26, 0x63, 0x64, 0xe6, 0x32, 0x4f, 0xda, 0xe1, 0xba, + 0x83, 0x84, 0xb9, 0x8c, 0x08, 0x74, 0x0e, 0x47, 0x36, 0x59, 0x32, 0xbc, 0x8a, 0x79, 0x26, 0xd6, + 0xf8, 0x99, 0x49, 0x39, 0x1e, 0x51, 0x0d, 0xc8, 0xab, 0x98, 0xeb, 0x70, 0x2a, 0x88, 0xa1, 0x61, + 0xf5, 0xc9, 0x08, 0x8b, 0xc5, 0xcf, 0x87, 0x31, 0x09, 0xd9, 0x4e, 0x6e, 0x01, 0x5d, 0xc0, 0xf1, + 0x2a, 0x26, 0x75, 0x84, 0xc2, 0x5a, 0x90, 0xbe, 0x3a, 0xcb, 0x21, 0xec, 0x3c, 0x39, 0x74, 0x48, + 0xa4, 0xdd, 0x7a, 0xa6, 0x91, 0xd7, 0xc2, 0x07, 0xf9, 0x18, 0x0e, 0xc5, 0xab, 0x89, 0xbb, 0x52, + 0x7e, 0x80, 0xa3, 0x35, 0x3c, 0xba, 0xea, 0x9f, 0x60, 0xcf, 0x0d, 0x09, 0xec, 0x71, 0x46, 0xca, + 0xf0, 0xbe, 0x3c, 0x11, 0x2e, 0x44, 0x8c, 0xd4, 0xca, 0xae, 0xe8, 0x23, 0xff, 0x99, 0x81, 0xbd, + 0xab, 0xf9, 0xcc, 0x15, 0xba, 0xee, 0x7f, 0xb5, 0xc3, 0x19, 0x14, 0xc3, 0x02, 0xf1, 0x62, 0xf1, + 0x6e, 0x28, 0x6b, 0x10, 0x42, 0x41, 0x89, 0x36, 0x6e, 0x35, 0xbb, 0x71, 0xab, 0x49, 0x25, 0xb6, + 0xc5, 0x4a, 0x1c, 0xc0, 0x7e, 0x92, 0x57, 0x78, 0xd6, 0xcf, 0xff, 0xc8, 0x42, 0x51, 0x68, 0x2e, + 0x54, 0x85, 0xfd, 0xfb, 0x7e, 0xb7, 0xaf, 0x3e, 0xf4, 0xf1, 0xc3, 0xad, 0xd1, 0x57, 0x74, 0xbd, + 0xf2, 0x01, 0x92, 0xe0, 0xb0, 0xad, 0xde, 0xdd, 0xdd, 0x1a, 0x77, 0x4a, 0xdf, 0xc0, 0xc6, 0xed, + 0x9d, 0x82, 0x7b, 0x6a, 0xbb, 0x5b, 0xc9, 0xa0, 0x13, 0xa8, 0x0a, 0x4c, 0x5f, 0xc5, 0xd7, 0x4a, + 0xef, 0xf2, 0x5d, 0x65, 0x0b, 0x1d, 0xc1, 0x81, 0x40, 0x68, 0xca, 0x5b, 0xb5, 0xab, 0x54, 0xb2, + 0x81, 0xbe, 0x63, 0xf4, 0xda, 0x58, 0xbd, 0xb9, 0x51, 0x34, 0xe5, 0x3a, 0x26, 0xb6, 0x83, 0x57, + 0x70, 0xe2, 0xb2, 0xdd, 0x56, 0x06, 0xc6, 0x8a, 0xd9, 0x41, 0x9f, 0xc2, 0x47, 0xa9, 0x90, 0xe0, + 0xf5, 0xea, 0xbd, 0x81, 0x75, 0xa5, 0xad, 0xf6, 0xaf, 0x71, 0x4f, 0x79, 0xab, 0xf4, 0x2a, 0x39, + 0xf4, 0x19, 0xc8, 0x69, 0x03, 0xfd, 0xbe, 0xdd, 0x56, 0x74, 0x3d, 0xad, 0xdb, 0x45, 0x67, 0xf0, + 0x7a, 0x2d, 0x83, 0x3b, 0xd5, 0x50, 0x62, 0xd7, 0x4a, 0x1e, 0xd5, 0xe1, 0x74, 0x3d, 0x13, 0xae, + 0x88, 0xfc, 0x2a, 0x05, 0x74, 0x0a, 0x12, 0x57, 0x88, 0xce, 0x71, 0xbe, 0x80, 0x0e, 0xa1, 0x12, + 0x55, 0x0e, 0x77, 0x95, 0x77, 0xb8, 0x73, 0xa9, 0x77, 0x2a, 0x45, 0xf4, 0x1a, 0x4e, 0xfa, 0x8a, + 0x1e, 0xd8, 0x6d, 0x90, 0xa5, 0xf3, 0xbf, 0xb7, 0xa1, 0xf0, 0xc0, 0x5b, 0xab, 0x6b, 0x31, 0xf4, + 0x03, 0x94, 0xaf, 0x09, 0xb5, 0x7e, 0x27, 0x7d, 0xb2, 0x64, 0x5d, 0xe2, 0xa3, 0x03, 0xa1, 0xef, + 0xc2, 0x0d, 0x52, 0x3b, 0x4e, 0x46, 0x64, 0x97, 0xf8, 0xd7, 0xc4, 0x1b, 0x52, 0xcb, 0x65, 0x0e, + 0x45, 0xdf, 0x41, 0x21, 0x8c, 0x0d, 0xe2, 0xaa, 0xa2, 0xa8, 0xe7, 0x0c, 0x4d, 0xe6, 0xd0, 0x17, + 0x23, 0x7f, 0x84, 0x7c, 0xf0, 0xbe, 0x60, 0x7f, 0x20, 0x71, 0xf2, 0x08, 0xfb, 0xa5, 0x76, 0xb2, + 0x81, 0x47, 0x5f, 0x4c, 0x07, 0x50, 0xb4, 0x2e, 0xc4, 0xdd, 0x22, 0xda, 0x08, 0x78, 0xad, 0x26, + 0x7e, 0x47, 0x6b, 0x5b, 0xa6, 0x07, 0x45, 0x61, 0xc4, 0xa3, 0x37, 0x82, 0x74, 0x73, 0xb1, 0xd4, + 0x3e, 0x7c, 0x89, 0x5e, 0xb9, 0x09, 0xb3, 0x3c, 0xe5, 0xb6, 0xb9, 0x1a, 0x52, 0x6e, 0xff, 0xb6, + 0x02, 0x34, 0x28, 0xa7, 0x06, 0x06, 0x3a, 0x7b, 0x61, 0x20, 0x24, 0xf9, 0xd5, 0x5f, 0x16, 0x44, + 0x9e, 0x3f, 0xc3, 0x6e, 0xf4, 0x49, 0xa2, 0x57, 0x82, 0x38, 0x3d, 0x3e, 0x52, 0x15, 0x5b, 0xfb, + 0x82, 0xaf, 0xbe, 0xfe, 0xb5, 0x35, 0xb6, 0xd8, 0xf3, 0xfc, 0xb1, 0x39, 0x74, 0x66, 0xad, 0x69, + 0x30, 0x71, 0x6d, 0xcb, 0x1e, 0xdb, 0x84, 0x2d, 0x1c, 0x3a, 0x69, 0x4d, 0xed, 0x51, 0x8b, 0x4f, + 0x9a, 0x56, 0x62, 0xf1, 0x98, 0xe3, 0xff, 0x90, 0x5c, 0xfc, 0x13, 0x00, 0x00, 0xff, 0xff, 0x3b, + 0x08, 0xac, 0xe2, 0xd9, 0x08, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/walletrpc/walletkit.proto b/lnrpc/walletrpc/walletkit.proto index 446e79fe32..7f2313f93f 100644 --- a/lnrpc/walletrpc/walletkit.proto +++ b/lnrpc/walletrpc/walletkit.proto @@ -22,7 +22,7 @@ message KeyReq { int32 key_family = 2; } -message AddrRequest{ +message AddrRequest { // No fields, as we always give out a p2wkh address. } message AddrResponse { @@ -168,41 +168,41 @@ enum WitnessType { message PendingSweep { // The outpoint of the output we're attempting to sweep. - lnrpc.OutPoint outpoint = 1 [json_name = "outpoint"]; + lnrpc.OutPoint outpoint = 1; // The witness type of the output we're attempting to sweep. - WitnessType witness_type = 2 [json_name = "witness_type"]; + WitnessType witness_type = 2; // The value of the output we're attempting to sweep. - uint32 amount_sat = 3 [json_name = "amount_sat"]; + uint32 amount_sat = 3; /* The fee rate we'll use to sweep the output. The fee rate is only determined once a sweeping transaction for the output is created, so it's possible for this to be 0 before this. */ - uint32 sat_per_byte = 4 [json_name = "sat_per_byte"]; + uint32 sat_per_byte = 4; // The number of broadcast attempts we've made to sweep the output. - uint32 broadcast_attempts = 5 [json_name = "broadcast_attempts"]; + uint32 broadcast_attempts = 5; /* The next height of the chain at which we'll attempt to broadcast the sweep transaction of the output. */ - uint32 next_broadcast_height = 6 [json_name = "next_broadcast_height"]; + uint32 next_broadcast_height = 6; // The requested confirmation target for this output. - uint32 requested_conf_target = 8 [json_name = "requested_conf_target"]; + uint32 requested_conf_target = 8; // The requested fee rate, expressed in sat/byte, for this output. - uint32 requested_sat_per_byte = 9 [json_name = "requested_sat_per_byte"]; + uint32 requested_sat_per_byte = 9; /** Whether this input must be force-swept. This means that it is swept even if it has a negative yield. */ - bool force = 7 [json_name = "force"]; + bool force = 7; } message PendingSweepsRequest { @@ -212,27 +212,27 @@ message PendingSweepsResponse { /* The set of outputs currently being swept by lnd's central batching engine. */ - repeated PendingSweep pending_sweeps = 1 [json_name = "pending_sweeps"]; + repeated PendingSweep pending_sweeps = 1; } message BumpFeeRequest { // The input we're attempting to bump the fee of. - lnrpc.OutPoint outpoint = 1 [json_name = "outpoint"]; + lnrpc.OutPoint outpoint = 1; // The target number of blocks that the input should be spent within. - uint32 target_conf = 2 [json_name = "target_conf"]; + uint32 target_conf = 2; /* The fee rate, expressed in sat/byte, that should be used to spend the input with. */ - uint32 sat_per_byte = 3 [json_name = "sat_per_byte"]; + uint32 sat_per_byte = 3; /** Whether this input must be force-swept. This means that it is swept even if it has a negative yield. */ - bool force = 4 [json_name = "force"]; + bool force = 4; } message BumpFeeResponse { @@ -244,18 +244,18 @@ service WalletKit { (account in BIP43) specified. This method should return the next external child within this branch. */ - rpc DeriveNextKey(KeyReq) returns (signrpc.KeyDescriptor); + rpc DeriveNextKey (KeyReq) returns (signrpc.KeyDescriptor); /** DeriveKey attempts to derive an arbitrary key specified by the passed KeyLocator. */ - rpc DeriveKey(signrpc.KeyLocator) returns (signrpc.KeyDescriptor); + rpc DeriveKey (signrpc.KeyLocator) returns (signrpc.KeyDescriptor); /** NextAddr returns the next unused address within the wallet. */ - rpc NextAddr(AddrRequest) returns (AddrResponse); + rpc NextAddr (AddrRequest) returns (AddrResponse); /** PublishTransaction attempts to publish the passed transaction to the @@ -263,21 +263,21 @@ service WalletKit { attempt to re-broadcast the transaction on start up, until it enters the chain. */ - rpc PublishTransaction(Transaction) returns (PublishResponse); + rpc PublishTransaction (Transaction) returns (PublishResponse); /** SendOutputs is similar to the existing sendmany call in Bitcoind, and allows the caller to create a transaction that sends to several outputs at once. This is ideal when wanting to batch create a set of transactions. */ - rpc SendOutputs(SendOutputsRequest) returns (SendOutputsResponse); + rpc SendOutputs (SendOutputsRequest) returns (SendOutputsResponse); /** EstimateFee attempts to query the internal fee estimator of the wallet to determine the fee (in sat/kw) to attach to a transaction in order to achieve the confirmation target. */ - rpc EstimateFee(EstimateFeeRequest) returns (EstimateFeeResponse); + rpc EstimateFee (EstimateFeeRequest) returns (EstimateFeeResponse); /* PendingSweeps returns lists of on-chain outputs that lnd is currently @@ -289,7 +289,7 @@ service WalletKit { remain supported. This is an advanced API that depends on the internals of the UtxoSweeper, so things may change. */ - rpc PendingSweeps(PendingSweepsRequest) returns (PendingSweepsResponse); + rpc PendingSweeps (PendingSweepsRequest) returns (PendingSweepsResponse); /* BumpFee bumps the fee of an arbitrary input within a transaction. This RPC @@ -318,5 +318,5 @@ service WalletKit { fee preference being provided. For now, the responsibility of ensuring that the new fee preference is sufficient is delegated to the user. */ - rpc BumpFee(BumpFeeRequest) returns (BumpFeeResponse); + rpc BumpFee (BumpFeeRequest) returns (BumpFeeResponse); } From ad0fba548fb32c87d3087118039f03df9a8b9297 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 14:05:42 +0100 Subject: [PATCH 144/562] watchtowerrpc: format watchtower.proto and remove json_name fields We now use the jsonpb marshaler to convert the RPC responses to JSON in lncli and REST. The jsonpb has a setting to use the original name as defined in the proto file and the explicit json_name definition is not necessary any more. The jsonpb setting is called OrigName and needs to be true. --- lnrpc/watchtowerrpc/watchtower.proto | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lnrpc/watchtowerrpc/watchtower.proto b/lnrpc/watchtowerrpc/watchtower.proto index 71c7648636..b79b52b005 100644 --- a/lnrpc/watchtowerrpc/watchtower.proto +++ b/lnrpc/watchtowerrpc/watchtower.proto @@ -5,24 +5,24 @@ package watchtowerrpc; option go_package = "github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc"; service Watchtower { - /** lncli: tower info - GetInfo returns general information concerning the companion watchtower - including it's public key and URIs where the server is currently - listening for clients. - */ - rpc GetInfo(GetInfoRequest) returns (GetInfoResponse); + /** lncli: tower info + GetInfo returns general information concerning the companion watchtower + including it's public key and URIs where the server is currently + listening for clients. + */ + rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); } -message GetInfoRequest{ +message GetInfoRequest { } message GetInfoResponse { - /// The public key of the watchtower. - bytes pubkey = 1 [json_name = "pubkey"]; + /// The public key of the watchtower. + bytes pubkey = 1; - /// The listening addresses of the watchtower. - repeated string listeners = 2 [json_name = "listeners"]; + /// The listening addresses of the watchtower. + repeated string listeners = 2; - /// The URIs of the watchtower. - repeated string uris = 3 [json_name = "uris" ]; + /// The URIs of the watchtower. + repeated string uris = 3; } From 3a5348ea8b16c9a5217849929bf72513d348dcac Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2020 14:06:44 +0100 Subject: [PATCH 145/562] wtclientrpc: format wtclient.proto and remove json_name fields We now use the jsonpb marshaler to convert the RPC responses to JSON in lncli and REST. The jsonpb has a setting to use the original name as defined in the proto file and the explicit json_name definition is not necessary any more. The jsonpb setting is called OrigName and needs to be true. --- lnrpc/wtclientrpc/wtclient.pb.go | 115 ++++++++++++++++--------------- lnrpc/wtclientrpc/wtclient.proto | 60 ++++++++-------- 2 files changed, 89 insertions(+), 86 deletions(-) diff --git a/lnrpc/wtclientrpc/wtclient.pb.go b/lnrpc/wtclientrpc/wtclient.pb.go index f99dbc6e32..3ccff8d3a8 100644 --- a/lnrpc/wtclientrpc/wtclient.pb.go +++ b/lnrpc/wtclientrpc/wtclient.pb.go @@ -189,7 +189,7 @@ type GetTowerInfoRequest struct { // The identifying public key of the watchtower to retrieve information for. Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` // Whether we should include sessions with the watchtower in the response. - IncludeSessions bool `protobuf:"varint,2,opt,name=include_sessions,proto3" json:"include_sessions,omitempty"` + IncludeSessions bool `protobuf:"varint,2,opt,name=include_sessions,json=includeSessions,proto3" json:"include_sessions,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -238,17 +238,17 @@ type TowerSession struct { // //The total number of successful backups that have been made to the //watchtower session. - NumBackups uint32 `protobuf:"varint,1,opt,name=num_backups,proto3" json:"num_backups,omitempty"` + NumBackups uint32 `protobuf:"varint,1,opt,name=num_backups,json=numBackups,proto3" json:"num_backups,omitempty"` // //The total number of backups in the session that are currently pending to be //acknowledged by the watchtower. - NumPendingBackups uint32 `protobuf:"varint,2,opt,name=num_pending_backups,proto3" json:"num_pending_backups,omitempty"` + NumPendingBackups uint32 `protobuf:"varint,2,opt,name=num_pending_backups,json=numPendingBackups,proto3" json:"num_pending_backups,omitempty"` // The maximum number of backups allowed by the watchtower session. - MaxBackups uint32 `protobuf:"varint,3,opt,name=max_backups,proto3" json:"max_backups,omitempty"` + MaxBackups uint32 `protobuf:"varint,3,opt,name=max_backups,json=maxBackups,proto3" json:"max_backups,omitempty"` // //The fee rate, in satoshis per vbyte, that will be used by the watchtower for //the justice transaction in the event of a channel breach. - SweepSatPerByte uint32 `protobuf:"varint,4,opt,name=sweep_sat_per_byte,proto3" json:"sweep_sat_per_byte,omitempty"` + SweepSatPerByte uint32 `protobuf:"varint,4,opt,name=sweep_sat_per_byte,json=sweepSatPerByte,proto3" json:"sweep_sat_per_byte,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -313,9 +313,9 @@ type Tower struct { // The list of addresses the watchtower is reachable over. Addresses []string `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"` // Whether the watchtower is currently a candidate for new sessions. - ActiveSessionCandidate bool `protobuf:"varint,3,opt,name=active_session_candidate,proto3" json:"active_session_candidate,omitempty"` + ActiveSessionCandidate bool `protobuf:"varint,3,opt,name=active_session_candidate,json=activeSessionCandidate,proto3" json:"active_session_candidate,omitempty"` // The number of sessions that have been negotiated with the watchtower. - NumSessions uint32 `protobuf:"varint,4,opt,name=num_sessions,proto3" json:"num_sessions,omitempty"` + NumSessions uint32 `protobuf:"varint,4,opt,name=num_sessions,json=numSessions,proto3" json:"num_sessions,omitempty"` // The list of sessions that have been negotiated with the watchtower. Sessions []*TowerSession `protobuf:"bytes,5,rep,name=sessions,proto3" json:"sessions,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -385,7 +385,7 @@ func (m *Tower) GetSessions() []*TowerSession { type ListTowersRequest struct { // Whether we should include sessions with the watchtower in the response. - IncludeSessions bool `protobuf:"varint,1,opt,name=include_sessions,proto3" json:"include_sessions,omitempty"` + IncludeSessions bool `protobuf:"varint,1,opt,name=include_sessions,json=includeSessions,proto3" json:"include_sessions,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -498,19 +498,19 @@ type StatsResponse struct { // //The total number of backups made to all active and exhausted watchtower //sessions. - NumBackups uint32 `protobuf:"varint,1,opt,name=num_backups,proto3" json:"num_backups,omitempty"` + NumBackups uint32 `protobuf:"varint,1,opt,name=num_backups,json=numBackups,proto3" json:"num_backups,omitempty"` // //The total number of backups that are pending to be acknowledged by all //active and exhausted watchtower sessions. - NumPendingBackups uint32 `protobuf:"varint,2,opt,name=num_pending_backups,proto3" json:"num_pending_backups,omitempty"` + NumPendingBackups uint32 `protobuf:"varint,2,opt,name=num_pending_backups,json=numPendingBackups,proto3" json:"num_pending_backups,omitempty"` // //The total number of backups that all active and exhausted watchtower //sessions have failed to acknowledge. - NumFailedBackups uint32 `protobuf:"varint,3,opt,name=num_failed_backups,proto3" json:"num_failed_backups,omitempty"` + NumFailedBackups uint32 `protobuf:"varint,3,opt,name=num_failed_backups,json=numFailedBackups,proto3" json:"num_failed_backups,omitempty"` // The total number of new sessions made to watchtowers. - NumSessionsAcquired uint32 `protobuf:"varint,4,opt,name=num_sessions_acquired,proto3" json:"num_sessions_acquired,omitempty"` + NumSessionsAcquired uint32 `protobuf:"varint,4,opt,name=num_sessions_acquired,json=numSessionsAcquired,proto3" json:"num_sessions_acquired,omitempty"` // The total number of watchtower sessions that have been exhausted. - NumSessionsExhausted uint32 `protobuf:"varint,5,opt,name=num_sessions_exhausted,proto3" json:"num_sessions_exhausted,omitempty"` + NumSessionsExhausted uint32 `protobuf:"varint,5,opt,name=num_sessions_exhausted,json=numSessionsExhausted,proto3" json:"num_sessions_exhausted,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -611,11 +611,11 @@ type PolicyResponse struct { // //The maximum number of updates each session we negotiate with watchtowers //should allow. - MaxUpdates uint32 `protobuf:"varint,1,opt,name=max_updates,proto3" json:"max_updates,omitempty"` + MaxUpdates uint32 `protobuf:"varint,1,opt,name=max_updates,json=maxUpdates,proto3" json:"max_updates,omitempty"` // //The fee rate, in satoshis per vbyte, that will be used by watchtowers for //justice transactions in response to channel breaches. - SweepSatPerByte uint32 `protobuf:"varint,2,opt,name=sweep_sat_per_byte,proto3" json:"sweep_sat_per_byte,omitempty"` + SweepSatPerByte uint32 `protobuf:"varint,2,opt,name=sweep_sat_per_byte,json=sweepSatPerByte,proto3" json:"sweep_sat_per_byte,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -679,47 +679,50 @@ func init() { func init() { proto.RegisterFile("wtclientrpc/wtclient.proto", fileDescriptor_b5f4e7d95a641af2) } var fileDescriptor_b5f4e7d95a641af2 = []byte{ - // 634 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcb, 0x6e, 0xd3, 0x40, - 0x14, 0x95, 0x13, 0x12, 0xd2, 0x9b, 0xf4, 0xc1, 0xad, 0x5a, 0x19, 0x53, 0x68, 0xe4, 0x55, 0xd4, - 0x45, 0x02, 0x2d, 0xb0, 0x60, 0x01, 0x94, 0x22, 0x2a, 0x24, 0x90, 0x2a, 0x17, 0x09, 0xc1, 0xc6, - 0xf2, 0x63, 0x9a, 0x8c, 0xea, 0x8c, 0x5d, 0xcf, 0xb8, 0x69, 0x97, 0xfc, 0x13, 0xbf, 0xc0, 0x1f, - 0xf0, 0x41, 0xc8, 0xe3, 0x47, 0xc6, 0x8d, 0x2d, 0x16, 0x88, 0x5d, 0xe6, 0x9c, 0x93, 0x33, 0x37, - 0xf7, 0x9e, 0xdc, 0x01, 0x63, 0x21, 0xbc, 0x80, 0x12, 0x26, 0xe2, 0xc8, 0x9b, 0x14, 0x9f, 0xc7, - 0x51, 0x1c, 0x8a, 0x10, 0xfb, 0x0a, 0x67, 0x9e, 0xc0, 0xe6, 0xb1, 0xef, 0x7f, 0x09, 0x17, 0x24, - 0xb6, 0xc8, 0x55, 0x42, 0xb8, 0xc0, 0x5d, 0xe8, 0x46, 0x89, 0x7b, 0x49, 0x6e, 0x75, 0x6d, 0xa8, - 0x8d, 0x06, 0x56, 0x7e, 0x42, 0x1d, 0xee, 0x3b, 0xbe, 0x1f, 0x13, 0xce, 0xf5, 0xd6, 0x50, 0x1b, - 0xad, 0x59, 0xc5, 0xd1, 0x44, 0xd8, 0x5a, 0x9a, 0xf0, 0x28, 0x64, 0x9c, 0x98, 0x1f, 0x00, 0x2d, - 0x32, 0x0f, 0xaf, 0xc9, 0x3f, 0x7a, 0xef, 0xc0, 0x76, 0xc5, 0x27, 0xb7, 0xff, 0x06, 0xdb, 0xa7, - 0x44, 0x48, 0xec, 0x23, 0xbb, 0x08, 0xff, 0xe6, 0x7f, 0x00, 0x5b, 0x94, 0x79, 0x41, 0xe2, 0x13, - 0x9b, 0x13, 0xce, 0x69, 0xc8, 0xb2, 0x8b, 0x7a, 0xd6, 0x0a, 0x6e, 0xfe, 0xd4, 0x60, 0x20, 0x8d, - 0xcf, 0x33, 0x04, 0x87, 0xd0, 0x67, 0xc9, 0xdc, 0x76, 0x1d, 0xef, 0x32, 0x89, 0xb8, 0x74, 0x5e, - 0xb7, 0x54, 0x08, 0x9f, 0xc2, 0x76, 0x7a, 0x8c, 0x08, 0xf3, 0x29, 0x9b, 0x96, 0xca, 0x96, 0x54, - 0xd6, 0x51, 0xa9, 0xe7, 0xdc, 0xb9, 0x29, 0x95, 0xed, 0xcc, 0x53, 0x81, 0x70, 0x0c, 0xc8, 0x17, - 0x84, 0x44, 0x36, 0x77, 0x84, 0x1d, 0x91, 0xd8, 0x76, 0x6f, 0x05, 0xd1, 0xef, 0x49, 0x61, 0x0d, - 0x63, 0xfe, 0xd6, 0xa0, 0x23, 0xcb, 0x6e, 0x6c, 0xc2, 0x1e, 0xac, 0xe5, 0x5d, 0x25, 0x69, 0x6d, - 0xed, 0xd1, 0x9a, 0xb5, 0x04, 0xf0, 0x15, 0xe8, 0x8e, 0x27, 0xe8, 0x75, 0xd9, 0x09, 0xdb, 0x73, - 0x98, 0x4f, 0x7d, 0x47, 0x10, 0x59, 0x5e, 0xcf, 0x6a, 0xe4, 0xd1, 0x84, 0x41, 0xfa, 0x23, 0xcb, - 0xd6, 0x66, 0x55, 0x56, 0x30, 0x7c, 0x01, 0xbd, 0x92, 0xef, 0x0c, 0xdb, 0xa3, 0xfe, 0xe1, 0xc3, - 0xb1, 0x92, 0xc4, 0xb1, 0xda, 0x72, 0xab, 0x94, 0x9a, 0x6f, 0xe0, 0xc1, 0x27, 0xca, 0xb3, 0x49, - 0xf3, 0x62, 0xcc, 0x75, 0xe3, 0xd4, 0x1a, 0xc6, 0xf9, 0x16, 0x50, 0x35, 0xc8, 0xf2, 0x83, 0x07, - 0xd0, 0x15, 0x12, 0xd1, 0x35, 0x59, 0x0b, 0xae, 0xd6, 0x62, 0xe5, 0x0a, 0x73, 0x03, 0x06, 0xe7, - 0xc2, 0x11, 0xc5, 0xed, 0xe6, 0x8f, 0x16, 0xac, 0xe7, 0x40, 0xee, 0xf6, 0x3f, 0x12, 0x32, 0x06, - 0x4c, 0xe1, 0x0b, 0x87, 0x06, 0xc4, 0xbf, 0x13, 0x94, 0x1a, 0x06, 0x9f, 0xc3, 0x8e, 0xda, 0x6f, - 0xdb, 0xf1, 0xae, 0x12, 0x1a, 0x13, 0x3f, 0x1f, 0x46, 0x3d, 0x89, 0x2f, 0x61, 0xb7, 0x42, 0x90, - 0x9b, 0x99, 0x93, 0x70, 0x41, 0x7c, 0xbd, 0x23, 0xbf, 0xd6, 0xc0, 0x9a, 0x9b, 0xb0, 0x7e, 0x16, - 0x06, 0xd4, 0xbb, 0x2d, 0x9a, 0xe2, 0xc2, 0x46, 0x01, 0x2c, 0x9b, 0x92, 0xe6, 0x39, 0x89, 0xd2, - 0x88, 0x94, 0x4d, 0x51, 0xa0, 0x86, 0x88, 0xb7, 0x9a, 0x22, 0x7e, 0xf8, 0xab, 0x0d, 0x5b, 0x5f, - 0x1d, 0xe1, 0xcd, 0xe4, 0x60, 0x4e, 0xe4, 0xb8, 0xf0, 0x14, 0x7a, 0xc5, 0xf2, 0xc1, 0xbd, 0xca, - 0x14, 0xef, 0x2c, 0x36, 0xe3, 0x71, 0x03, 0x9b, 0xd7, 0x7b, 0x06, 0x7d, 0x65, 0xd3, 0xe0, 0x7e, - 0x45, 0xbd, 0xba, 0xcb, 0x8c, 0x61, 0xb3, 0x20, 0x77, 0xfc, 0x0c, 0xb0, 0x8c, 0x1e, 0x3e, 0xa9, - 0xe8, 0x57, 0x42, 0x6d, 0xec, 0x37, 0xf2, 0xb9, 0xdd, 0x7b, 0x18, 0xa8, 0x3b, 0x0f, 0xab, 0x05, - 0xd4, 0xac, 0x43, 0xa3, 0x26, 0xd5, 0xf8, 0x1a, 0x3a, 0x32, 0xbc, 0x58, 0xfd, 0xfb, 0xa9, 0x09, - 0x37, 0x8c, 0x3a, 0x2a, 0xaf, 0xe2, 0x18, 0xba, 0xd9, 0xa0, 0xb1, 0xaa, 0xaa, 0xc4, 0xc1, 0x78, - 0x54, 0xcb, 0x65, 0x16, 0xef, 0x8e, 0xbe, 0x3f, 0x9b, 0x52, 0x31, 0x4b, 0xdc, 0xb1, 0x17, 0xce, - 0x27, 0x01, 0x9d, 0xce, 0x04, 0xa3, 0x6c, 0xca, 0x88, 0x58, 0x84, 0xf1, 0xe5, 0x24, 0x60, 0xfe, - 0x24, 0x60, 0xea, 0xcb, 0x15, 0x47, 0x9e, 0xdb, 0x95, 0xaf, 0xd7, 0xd1, 0x9f, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xdd, 0x33, 0x97, 0x54, 0xdb, 0x06, 0x00, 0x00, + // 682 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x95, 0x1b, 0x12, 0xd2, 0x49, 0xda, 0xa4, 0x1b, 0x5a, 0x19, 0x53, 0x48, 0xf0, 0x29, 0x7c, + 0x28, 0x11, 0x2d, 0x48, 0x9c, 0x2a, 0xda, 0x42, 0x2b, 0x24, 0x90, 0x22, 0x17, 0x04, 0xe2, 0x80, + 0xb5, 0xb1, 0xb7, 0x89, 0x55, 0x7b, 0xed, 0x7a, 0xd7, 0x4d, 0xf2, 0xa3, 0xf8, 0x19, 0xfc, 0x00, + 0xfe, 0x0d, 0x47, 0xe4, 0xf5, 0xda, 0xb1, 0x1b, 0x47, 0x1c, 0xe0, 0x16, 0xcf, 0x7b, 0xfb, 0x3c, + 0x7e, 0xf3, 0x32, 0x0b, 0xda, 0x8c, 0x5b, 0xae, 0x43, 0x28, 0x0f, 0x03, 0x6b, 0x98, 0xfe, 0x1e, + 0x04, 0xa1, 0xcf, 0x7d, 0xd4, 0xc8, 0x61, 0xfa, 0x29, 0xb4, 0x8e, 0x6d, 0xfb, 0x93, 0x3f, 0x23, + 0xa1, 0x41, 0xae, 0x23, 0xc2, 0x38, 0xda, 0x83, 0x5a, 0x10, 0x8d, 0xaf, 0xc8, 0x42, 0x55, 0x7a, + 0x4a, 0xbf, 0x69, 0xc8, 0x27, 0xa4, 0xc2, 0x5d, 0x6c, 0xdb, 0x21, 0x61, 0x4c, 0xdd, 0xe8, 0x29, + 0xfd, 0x4d, 0x23, 0x7d, 0xd4, 0x11, 0xb4, 0x97, 0x22, 0x2c, 0xf0, 0x29, 0x23, 0xfa, 0x19, 0x20, + 0x83, 0x78, 0xfe, 0x0d, 0xf9, 0x47, 0xed, 0x5d, 0xe8, 0x14, 0x74, 0xa4, 0xfc, 0x57, 0xe8, 0x9c, + 0x13, 0x2e, 0x6a, 0xef, 0xe9, 0xa5, 0xff, 0x37, 0xfd, 0x27, 0xd0, 0x76, 0xa8, 0xe5, 0x46, 0x36, + 0x31, 0x19, 0x61, 0xcc, 0xf1, 0x69, 0xf2, 0xa2, 0xba, 0xd1, 0x92, 0xf5, 0x0b, 0x59, 0xd6, 0x7f, + 0x28, 0xd0, 0x14, 0xba, 0xb2, 0x82, 0xba, 0xd0, 0xa0, 0x91, 0x67, 0x8e, 0xb1, 0x75, 0x15, 0x05, + 0x4c, 0x08, 0x6f, 0x19, 0x40, 0x23, 0xef, 0x24, 0xa9, 0xa0, 0x01, 0x74, 0x62, 0x42, 0x40, 0xa8, + 0xed, 0xd0, 0x49, 0x46, 0xdc, 0x10, 0xc4, 0x1d, 0x1a, 0x79, 0xa3, 0x04, 0x49, 0xf9, 0x5d, 0x68, + 0x78, 0x78, 0x9e, 0xf1, 0x2a, 0x89, 0xa0, 0x87, 0xe7, 0x29, 0xe1, 0x19, 0x20, 0x36, 0x23, 0x24, + 0x30, 0x19, 0xe6, 0x66, 0x40, 0x42, 0x73, 0xbc, 0xe0, 0x44, 0xbd, 0x23, 0x78, 0x2d, 0x81, 0x5c, + 0x60, 0x3e, 0x22, 0xe1, 0xc9, 0x82, 0x13, 0xfd, 0x97, 0x02, 0x55, 0xd1, 0xef, 0xda, 0x8f, 0xdf, + 0x87, 0x4d, 0xe9, 0x26, 0x89, 0xbb, 0xaa, 0xf4, 0x37, 0x8d, 0x65, 0x01, 0xbd, 0x06, 0x15, 0x5b, + 0xdc, 0xb9, 0xc9, 0x9c, 0x31, 0x2d, 0x4c, 0x6d, 0xc7, 0xc6, 0x9c, 0x88, 0xd6, 0xea, 0xc6, 0x5e, + 0x82, 0x4b, 0x3f, 0x4e, 0x53, 0x14, 0x3d, 0x86, 0x66, 0xfc, 0xdd, 0x99, 0xa1, 0x49, 0x83, 0xb1, + 0x59, 0xa9, 0x99, 0xe8, 0x15, 0xd4, 0x33, 0xb8, 0xda, 0xab, 0xf4, 0x1b, 0x07, 0xf7, 0x07, 0xb9, + 0xf8, 0x0d, 0xf2, 0x46, 0x1b, 0x19, 0x55, 0x3f, 0x82, 0x9d, 0x0f, 0x0e, 0x4b, 0xc6, 0xcb, 0xd2, + 0xd9, 0x96, 0xcd, 0x50, 0x29, 0x9f, 0xe1, 0x1b, 0x40, 0xf9, 0xf3, 0x49, 0x66, 0xd0, 0x53, 0xa8, + 0x71, 0x51, 0x51, 0x15, 0xd1, 0x0a, 0x5a, 0x6d, 0xc5, 0x90, 0x0c, 0x7d, 0x1b, 0x9a, 0x17, 0x1c, + 0xf3, 0xf4, 0xe5, 0xfa, 0x6f, 0x05, 0xb6, 0x64, 0x41, 0xaa, 0xfd, 0xf7, 0x58, 0x3c, 0x07, 0x14, + 0xf3, 0x2f, 0xb1, 0xe3, 0x12, 0xfb, 0x56, 0x3a, 0xda, 0x34, 0xf2, 0xce, 0x04, 0x90, 0xb2, 0x0f, + 0x60, 0x37, 0x6f, 0xbe, 0x89, 0xad, 0xeb, 0xc8, 0x09, 0x89, 0x2d, 0xa7, 0xd0, 0xc9, 0x4d, 0xe1, + 0x58, 0x42, 0xe8, 0x25, 0xec, 0x15, 0xce, 0x90, 0xf9, 0x14, 0x47, 0x8c, 0x13, 0x5b, 0xad, 0x8a, + 0x43, 0xf7, 0x72, 0x87, 0xde, 0xa5, 0x98, 0xde, 0x82, 0xad, 0x91, 0xef, 0x3a, 0xd6, 0x22, 0xf5, + 0xe2, 0x3b, 0x6c, 0xa7, 0x85, 0xa5, 0x17, 0x71, 0xa2, 0xa3, 0x20, 0xce, 0x45, 0xe6, 0x85, 0x87, + 0xe7, 0x9f, 0x93, 0xca, 0x9a, 0x44, 0x6f, 0x94, 0x26, 0xfa, 0xe0, 0x67, 0x05, 0xda, 0x5f, 0x30, + 0xb7, 0xa6, 0x62, 0x16, 0xa7, 0x62, 0x42, 0xe8, 0x1c, 0xea, 0xe9, 0x8e, 0x41, 0xfb, 0x85, 0xc1, + 0xdd, 0xda, 0x5f, 0xda, 0xc3, 0x35, 0xa8, 0xec, 0x75, 0x04, 0x8d, 0xdc, 0x42, 0x41, 0xdd, 0x02, + 0x7b, 0x75, 0x65, 0x69, 0xbd, 0xf5, 0x04, 0xa9, 0xf8, 0x11, 0x60, 0x99, 0x36, 0xf4, 0xa8, 0xc0, + 0x5f, 0x89, 0xb1, 0xd6, 0x5d, 0x8b, 0x4b, 0xb9, 0xb7, 0xd0, 0xcc, 0xaf, 0x36, 0x54, 0x6c, 0xa0, + 0x64, 0xeb, 0x69, 0x25, 0x41, 0x46, 0x47, 0x50, 0x15, 0x79, 0x45, 0xc5, 0x3f, 0x5c, 0x3e, 0xd4, + 0x9a, 0x56, 0x06, 0xc9, 0x2e, 0x8e, 0xa1, 0x96, 0x0c, 0x19, 0x15, 0x59, 0x85, 0x28, 0x68, 0x0f, + 0x4a, 0xb1, 0x44, 0xe2, 0xe4, 0xf0, 0xdb, 0x8b, 0x89, 0xc3, 0xa7, 0xd1, 0x78, 0x60, 0xf9, 0xde, + 0xd0, 0x75, 0x26, 0x53, 0x4e, 0x1d, 0x3a, 0xa1, 0x84, 0xcf, 0xfc, 0xf0, 0x6a, 0xe8, 0x52, 0x7b, + 0xe8, 0xd2, 0xfc, 0x05, 0x15, 0x06, 0xd6, 0xb8, 0x26, 0x2e, 0xa9, 0xc3, 0x3f, 0x01, 0x00, 0x00, + 0xff, 0xff, 0x5d, 0xba, 0x03, 0x17, 0xc2, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/wtclientrpc/wtclient.proto b/lnrpc/wtclientrpc/wtclient.proto index fa2910e938..138a836707 100644 --- a/lnrpc/wtclientrpc/wtclient.proto +++ b/lnrpc/wtclientrpc/wtclient.proto @@ -6,10 +6,10 @@ option go_package = "github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"; message AddTowerRequest { // The identifying public key of the watchtower to add. - bytes pubkey = 1 [json_name = "pubkey"]; + bytes pubkey = 1; // A network address the watchtower is reachable over. - string address = 2 [json_name = "address"]; + string address = 2; } message AddTowerResponse { @@ -17,14 +17,14 @@ message AddTowerResponse { message RemoveTowerRequest { // The identifying public key of the watchtower to remove. - bytes pubkey = 1 [json_name = "pubkey"]; + bytes pubkey = 1; /* If set, then the record for this address will be removed, indicating that is is stale. Otherwise, the watchtower will no longer be used for future session negotiations and backups. */ - string address = 2 [json_name = "address"]; + string address = 2; } message RemoveTowerResponse { @@ -32,10 +32,10 @@ message RemoveTowerResponse { message GetTowerInfoRequest { // The identifying public key of the watchtower to retrieve information for. - bytes pubkey = 1 [json_name = "pubkey"]; + bytes pubkey = 1; // Whether we should include sessions with the watchtower in the response. - bool include_sessions = 2 [json_name = "include_sessions"]; + bool include_sessions = 2; } message TowerSession { @@ -43,49 +43,49 @@ message TowerSession { The total number of successful backups that have been made to the watchtower session. */ - uint32 num_backups = 1 [json_name = "num_backups"]; + uint32 num_backups = 1; /* The total number of backups in the session that are currently pending to be acknowledged by the watchtower. */ - uint32 num_pending_backups = 2 [json_name = "num_pending_backups"]; + uint32 num_pending_backups = 2; // The maximum number of backups allowed by the watchtower session. - uint32 max_backups = 3 [json_name = "max_backups"]; + uint32 max_backups = 3; /* The fee rate, in satoshis per vbyte, that will be used by the watchtower for the justice transaction in the event of a channel breach. */ - uint32 sweep_sat_per_byte = 4 [json_name = "sweep_sat_per_byte"]; + uint32 sweep_sat_per_byte = 4; } message Tower { // The identifying public key of the watchtower. - bytes pubkey = 1 [json_name = "pubkey"]; + bytes pubkey = 1; // The list of addresses the watchtower is reachable over. - repeated string addresses = 2 [json_name = "addresses"]; + repeated string addresses = 2; // Whether the watchtower is currently a candidate for new sessions. - bool active_session_candidate = 3 [json_name = "active_session_candidate"]; + bool active_session_candidate = 3; // The number of sessions that have been negotiated with the watchtower. - uint32 num_sessions = 4 [json_name = "num_sessions"]; + uint32 num_sessions = 4; // The list of sessions that have been negotiated with the watchtower. - repeated TowerSession sessions = 5 [json_name = "sessions"]; + repeated TowerSession sessions = 5; } message ListTowersRequest { // Whether we should include sessions with the watchtower in the response. - bool include_sessions = 1 [json_name = "include_sessions"]; + bool include_sessions = 1; } message ListTowersResponse { // The list of watchtowers available for new backups. - repeated Tower towers = 1 [json_name = "towers"]; + repeated Tower towers = 1; } message StatsRequest { @@ -96,25 +96,25 @@ message StatsResponse { The total number of backups made to all active and exhausted watchtower sessions. */ - uint32 num_backups = 1 [json_name = "num_backups"]; + uint32 num_backups = 1; /* The total number of backups that are pending to be acknowledged by all active and exhausted watchtower sessions. */ - uint32 num_pending_backups = 2 [json_name = "num_pending_backups"]; + uint32 num_pending_backups = 2; /* The total number of backups that all active and exhausted watchtower sessions have failed to acknowledge. */ - uint32 num_failed_backups = 3 [json_name = "num_failed_backups"]; + uint32 num_failed_backups = 3; // The total number of new sessions made to watchtowers. - uint32 num_sessions_acquired = 4 [json_name = "num_sessions_acquired"]; + uint32 num_sessions_acquired = 4; // The total number of watchtower sessions that have been exhausted. - uint32 num_sessions_exhausted = 5 [json_name = "num_sessions_exhausted"]; + uint32 num_sessions_exhausted = 5; } message PolicyRequest { @@ -125,13 +125,13 @@ message PolicyResponse { The maximum number of updates each session we negotiate with watchtowers should allow. */ - uint32 max_updates = 1 [json_name = "max_updates"]; + uint32 max_updates = 1; /* The fee rate, in satoshis per vbyte, that will be used by watchtowers for justice transactions in response to channel breaches. */ - uint32 sweep_sat_per_byte = 2 [json_name = "sweep_sat_per_byte"]; + uint32 sweep_sat_per_byte = 2; } service WatchtowerClient { @@ -141,7 +141,7 @@ service WatchtowerClient { any new addresses included will be considered when dialing it for session negotiations and backups. */ - rpc AddTower(AddTowerRequest) returns (AddTowerResponse); + rpc AddTower (AddTowerRequest) returns (AddTowerResponse); /* RemoveTower removes a watchtower from being considered for future session @@ -149,17 +149,17 @@ service WatchtowerClient { again. If an address is provided, then this RPC only serves as a way of removing the address from the watchtower instead. */ - rpc RemoveTower(RemoveTowerRequest) returns (RemoveTowerResponse); + rpc RemoveTower (RemoveTowerRequest) returns (RemoveTowerResponse); // ListTowers returns the list of watchtowers registered with the client. - rpc ListTowers(ListTowersRequest) returns (ListTowersResponse); + rpc ListTowers (ListTowersRequest) returns (ListTowersResponse); // GetTowerInfo retrieves information for a registered watchtower. - rpc GetTowerInfo(GetTowerInfoRequest) returns (Tower); + rpc GetTowerInfo (GetTowerInfoRequest) returns (Tower); // Stats returns the in-memory statistics of the client since startup. - rpc Stats(StatsRequest) returns (StatsResponse); + rpc Stats (StatsRequest) returns (StatsResponse); // Policy returns the active watchtower client policy configuration. - rpc Policy(PolicyRequest) returns (PolicyResponse); + rpc Policy (PolicyRequest) returns (PolicyResponse); } From 9aff896b10ad0d84fff7512f8891d2fda35bf371 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 12 Feb 2020 16:13:07 +0100 Subject: [PATCH 146/562] lnrpc+rpcserver+lncli: rename RPC fields to previous JSON name --- cmd/lncli/types.go | 2 +- lnrpc/rpc.pb.go | 1320 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 4 +- lnrpc/rpc.swagger.json | 4 +- rpcserver.go | 12 +- 5 files changed, 671 insertions(+), 671 deletions(-) diff --git a/cmd/lncli/types.go b/cmd/lncli/types.go index 30d559a7e5..28f494742e 100644 --- a/cmd/lncli/types.go +++ b/cmd/lncli/types.go @@ -58,7 +58,7 @@ type Utxo struct { // printed in base64. func NewUtxoFromProto(utxo *lnrpc.Utxo) *Utxo { return &Utxo{ - Type: utxo.Type, + Type: utxo.AddressType, Address: utxo.Address, AmountSat: utxo.AmountSat, PkScript: utxo.PkScript, diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 04298df145..36727add24 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -836,7 +836,7 @@ var xxx_messageInfo_ChangePasswordResponse proto.InternalMessageInfo type Utxo struct { /// The type of address - Type AddressType `protobuf:"varint,1,opt,name=type,proto3,enum=lnrpc.AddressType" json:"type,omitempty"` + AddressType AddressType `protobuf:"varint,1,opt,name=address_type,json=addressType,proto3,enum=lnrpc.AddressType" json:"address_type,omitempty"` /// The address Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` /// The value of the unspent coin in satoshis @@ -877,9 +877,9 @@ func (m *Utxo) XXX_DiscardUnknown() { var xxx_messageInfo_Utxo proto.InternalMessageInfo -func (m *Utxo) GetType() AddressType { +func (m *Utxo) GetAddressType() AddressType { if m != nil { - return m.Type + return m.AddressType } return AddressType_WITNESS_PUBKEY_HASH } @@ -9362,7 +9362,7 @@ type ChannelFeeReport struct { /// The short channel id that this fee report belongs to. ChanId uint64 `protobuf:"varint,5,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` /// The channel that this fee report belongs to. - ChanPoint string `protobuf:"bytes,1,opt,name=chan_point,json=chanPoint,proto3" json:"chan_point,omitempty"` + ChannelPoint string `protobuf:"bytes,1,opt,name=channel_point,json=channelPoint,proto3" json:"channel_point,omitempty"` /// The base fee charged regardless of the number of milli-satoshis sent. BaseFeeMsat int64 `protobuf:"varint,2,opt,name=base_fee_msat,json=baseFeeMsat,proto3" json:"base_fee_msat,omitempty"` /// The amount charged per milli-satoshis transferred expressed in millionths of a satoshi. @@ -9406,9 +9406,9 @@ func (m *ChannelFeeReport) GetChanId() uint64 { return 0 } -func (m *ChannelFeeReport) GetChanPoint() string { +func (m *ChannelFeeReport) GetChannelPoint() string { if m != nil { - return m.ChanPoint + return m.ChannelPoint } return "" } @@ -10648,660 +10648,660 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 10441 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x1c, 0x57, - 0x76, 0x18, 0xfb, 0x35, 0xdd, 0x7d, 0xfa, 0x31, 0x3d, 0x77, 0x86, 0x33, 0xcd, 0xa6, 0x28, 0x52, - 0x25, 0xad, 0x48, 0x51, 0x12, 0x49, 0x71, 0xa5, 0x95, 0x2c, 0x25, 0x6b, 0xcf, 0x53, 0x33, 0xcb, - 0x79, 0xa9, 0x7a, 0xb8, 0xb2, 0x76, 0xe3, 0xd4, 0xd6, 0x74, 0xdf, 0x99, 0x29, 0xb3, 0xbb, 0xaa, - 0x55, 0x55, 0x3d, 0x8f, 0x15, 0x94, 0x0f, 0x79, 0x18, 0x41, 0x12, 0x04, 0x30, 0x12, 0x07, 0x88, - 0x13, 0x23, 0x41, 0x82, 0x20, 0x08, 0x92, 0x18, 0x0e, 0xec, 0x00, 0xf9, 0x90, 0xef, 0xfe, 0x92, - 0xc0, 0x1f, 0x9c, 0x20, 0x40, 0xb0, 0x30, 0x60, 0xc4, 0xc8, 0x67, 0xff, 0x84, 0xe0, 0x9e, 0x73, - 0xef, 0xad, 0x5b, 0xdd, 0xd5, 0x24, 0xa5, 0xdd, 0xec, 0x17, 0x72, 0xea, 0xdc, 0x73, 0xdf, 0xe7, - 0x9e, 0x7b, 0x9e, 0xb7, 0xa1, 0x1a, 0x8e, 0x7a, 0x0f, 0x46, 0x61, 0x10, 0x07, 0xac, 0x34, 0xf0, - 0xc3, 0x51, 0xaf, 0xf3, 0xca, 0x69, 0x10, 0x9c, 0x0e, 0xf8, 0x43, 0x77, 0xe4, 0x3d, 0x74, 0x7d, - 0x3f, 0x88, 0xdd, 0xd8, 0x0b, 0xfc, 0x88, 0x90, 0xac, 0x9f, 0x40, 0xf3, 0x53, 0xee, 0x77, 0x39, - 0xef, 0xdb, 0xfc, 0xcb, 0x31, 0x8f, 0x62, 0xf6, 0x36, 0x2c, 0xb8, 0xfc, 0xa7, 0x9c, 0xf7, 0x9d, - 0x91, 0x1b, 0x45, 0xa3, 0xb3, 0xd0, 0x8d, 0x78, 0x3b, 0x77, 0x27, 0x77, 0xaf, 0x6e, 0xb7, 0xa8, - 0xe0, 0x50, 0xc3, 0xd9, 0x6b, 0x50, 0x8f, 0x04, 0x2a, 0xf7, 0xe3, 0x30, 0x18, 0x5d, 0xb5, 0xf3, - 0x88, 0x57, 0x13, 0xb0, 0x4d, 0x02, 0x59, 0x03, 0x98, 0xd7, 0x3d, 0x44, 0xa3, 0xc0, 0x8f, 0x38, - 0x7b, 0x04, 0x4b, 0x3d, 0x6f, 0x74, 0xc6, 0x43, 0x07, 0x2b, 0x0f, 0x7d, 0x3e, 0x0c, 0x7c, 0xaf, - 0xd7, 0xce, 0xdd, 0x29, 0xdc, 0xab, 0xda, 0x8c, 0xca, 0x44, 0x8d, 0x3d, 0x59, 0xc2, 0xee, 0xc2, - 0x3c, 0xf7, 0x09, 0xce, 0xfb, 0x58, 0x4b, 0x76, 0xd5, 0x4c, 0xc0, 0xa2, 0x82, 0xf5, 0x77, 0xf3, - 0xb0, 0xb0, 0xe3, 0x7b, 0xf1, 0xe7, 0xee, 0x60, 0xc0, 0x63, 0x35, 0xa7, 0xbb, 0x30, 0x7f, 0x81, - 0x00, 0x9c, 0xd3, 0x45, 0x10, 0xf6, 0xe5, 0x8c, 0x9a, 0x04, 0x3e, 0x94, 0xd0, 0x99, 0x23, 0xcb, - 0xcf, 0x1c, 0x59, 0xe6, 0x72, 0x15, 0x66, 0x2c, 0xd7, 0x5d, 0x98, 0x0f, 0x79, 0x2f, 0x38, 0xe7, - 0xe1, 0x95, 0x73, 0xe1, 0xf9, 0xfd, 0xe0, 0xa2, 0x5d, 0xbc, 0x93, 0xbb, 0x57, 0xb2, 0x9b, 0x0a, - 0xfc, 0x39, 0x42, 0xd9, 0x1a, 0xcc, 0xf7, 0xce, 0x5c, 0xdf, 0xe7, 0x03, 0xe7, 0xd8, 0xed, 0x3d, - 0x1b, 0x8f, 0xa2, 0x76, 0xe9, 0x4e, 0xee, 0x5e, 0xed, 0xf1, 0x8d, 0x07, 0xb8, 0xab, 0x0f, 0xd6, - 0xcf, 0x5c, 0x7f, 0x0d, 0x4b, 0xba, 0xbe, 0x3b, 0x8a, 0xce, 0x82, 0xd8, 0x6e, 0xca, 0x1a, 0x04, - 0x8e, 0xac, 0x25, 0x60, 0xe6, 0x4a, 0xd0, 0xda, 0x5b, 0xff, 0x3e, 0x07, 0x8b, 0x4f, 0xfd, 0x41, - 0xd0, 0x7b, 0xf6, 0x2d, 0x97, 0x28, 0x63, 0x0e, 0xf9, 0x97, 0x9d, 0x43, 0xe1, 0x9b, 0xce, 0x61, - 0x19, 0x96, 0xd2, 0x83, 0x95, 0xb3, 0xe0, 0x70, 0x5d, 0xd4, 0x3e, 0xe5, 0x6a, 0x58, 0x6a, 0x1a, - 0x6f, 0x41, 0xab, 0x37, 0x0e, 0x43, 0xee, 0x4f, 0xcd, 0x63, 0x5e, 0xc2, 0xf5, 0x44, 0x5e, 0x83, - 0xba, 0xcf, 0x2f, 0x12, 0x34, 0x49, 0xbb, 0x3e, 0xbf, 0x50, 0x28, 0x56, 0x1b, 0x96, 0x27, 0xbb, - 0x91, 0x03, 0xf8, 0x5f, 0x39, 0x28, 0x3e, 0x8d, 0x2f, 0x03, 0xf6, 0x26, 0x14, 0xe3, 0xab, 0x11, - 0x9d, 0x90, 0xe6, 0x63, 0x26, 0xa7, 0xb6, 0xda, 0xef, 0x87, 0x3c, 0x8a, 0x8e, 0xae, 0x46, 0xdc, - 0xc6, 0x72, 0xd6, 0x86, 0xb2, 0x4b, 0x40, 0xec, 0xa8, 0x6a, 0xab, 0x4f, 0x76, 0x0b, 0xc0, 0x1d, - 0x06, 0x63, 0x3f, 0x76, 0x22, 0x37, 0xc6, 0x25, 0x2a, 0xd8, 0x55, 0x82, 0x74, 0xdd, 0x98, 0xdd, - 0x84, 0xea, 0xe8, 0x99, 0x13, 0xf5, 0x42, 0x6f, 0x14, 0x23, 0xb5, 0x54, 0xed, 0xca, 0xe8, 0x59, - 0x17, 0xbf, 0xd9, 0xdb, 0x50, 0x09, 0xc6, 0xf1, 0x28, 0xf0, 0xfc, 0x58, 0x12, 0xc8, 0xbc, 0x1c, - 0xc1, 0xc1, 0x38, 0x3e, 0x14, 0x60, 0x5b, 0x23, 0xb0, 0x37, 0xa0, 0xd1, 0x0b, 0xfc, 0x13, 0x2f, - 0x1c, 0x12, 0x0b, 0x68, 0xcf, 0x61, 0x5f, 0x69, 0xa0, 0xf5, 0x07, 0x79, 0xa8, 0x1d, 0x85, 0xae, - 0x1f, 0xb9, 0x3d, 0x01, 0x60, 0x2b, 0x50, 0x8e, 0x2f, 0x9d, 0x33, 0x37, 0x3a, 0xc3, 0x39, 0x56, - 0xed, 0xb9, 0xf8, 0x72, 0xdb, 0x8d, 0xce, 0xd8, 0x32, 0xcc, 0xd1, 0x28, 0x71, 0x42, 0x05, 0x5b, - 0x7e, 0x89, 0x13, 0xe1, 0x8f, 0x87, 0x4e, 0xba, 0xab, 0x02, 0x92, 0x48, 0xcb, 0x1f, 0x0f, 0xd7, - 0x4d, 0xb8, 0x98, 0xfc, 0xb1, 0xd8, 0x5f, 0xea, 0x80, 0xa6, 0x57, 0x45, 0x08, 0xf6, 0xf1, 0x1a, - 0xd4, 0x65, 0x31, 0xf7, 0x4e, 0xcf, 0x68, 0x8e, 0x25, 0xbb, 0x46, 0x08, 0x08, 0x12, 0x2d, 0xc4, - 0xde, 0x90, 0x3b, 0x51, 0xec, 0x0e, 0x47, 0x72, 0x4a, 0x55, 0x01, 0xe9, 0x0a, 0x00, 0x16, 0x07, - 0xb1, 0x3b, 0x70, 0x4e, 0x38, 0x8f, 0xda, 0x65, 0x59, 0x2c, 0x20, 0x5b, 0x9c, 0x47, 0xec, 0x3b, - 0xd0, 0xec, 0xf3, 0x28, 0x76, 0xe4, 0x66, 0xf0, 0xa8, 0x5d, 0xc1, 0xa3, 0xde, 0x10, 0xd0, 0x55, - 0x05, 0x64, 0xaf, 0x00, 0x84, 0xee, 0x85, 0x23, 0x16, 0x82, 0x5f, 0xb6, 0xab, 0xb4, 0x0b, 0xa1, - 0x7b, 0x71, 0x74, 0xb9, 0xcd, 0x2f, 0x05, 0x99, 0x7c, 0xca, 0x63, 0x63, 0xd1, 0x22, 0x49, 0x8e, - 0xd6, 0x2e, 0x30, 0x03, 0xbc, 0xc1, 0x63, 0xd7, 0x1b, 0x44, 0xec, 0x7b, 0x50, 0x8f, 0x0d, 0x64, - 0xe4, 0x7b, 0x35, 0x4d, 0x3b, 0x46, 0x05, 0x3b, 0x85, 0x67, 0x9d, 0x41, 0x65, 0x8b, 0xf3, 0x5d, - 0x6f, 0xe8, 0xc5, 0x6c, 0x19, 0x4a, 0x27, 0xde, 0x25, 0x27, 0xea, 0x2e, 0x6c, 0x5f, 0xb3, 0xe9, - 0x93, 0xdd, 0x06, 0xc0, 0x3f, 0x9c, 0xa1, 0xa6, 0xa6, 0xed, 0x6b, 0x76, 0x15, 0x61, 0x7b, 0x91, - 0x1b, 0xb3, 0x0e, 0x94, 0x47, 0x3c, 0xec, 0x71, 0xb5, 0x6f, 0xdb, 0xd7, 0x6c, 0x05, 0x58, 0x2b, - 0x43, 0x69, 0x20, 0x5a, 0xb7, 0xfe, 0xb8, 0x04, 0xb5, 0x2e, 0xf7, 0xf5, 0xb1, 0x62, 0x50, 0x14, - 0x0b, 0x22, 0x8f, 0x12, 0xfe, 0xcd, 0x5e, 0x87, 0x1a, 0x2e, 0x5d, 0x14, 0x87, 0x9e, 0x7f, 0x4a, - 0x54, 0xbd, 0x96, 0x6f, 0xe7, 0x6c, 0x10, 0xe0, 0x2e, 0x42, 0x59, 0x0b, 0x0a, 0xee, 0x50, 0x51, - 0xb5, 0xf8, 0x93, 0xdd, 0x80, 0x8a, 0x3b, 0x8c, 0x69, 0x78, 0x75, 0x04, 0x97, 0xdd, 0x61, 0x8c, - 0x43, 0x7b, 0x0d, 0xea, 0x23, 0xf7, 0x6a, 0x28, 0x0e, 0xaf, 0x26, 0x87, 0xba, 0x5d, 0x93, 0x30, - 0x24, 0x88, 0xc7, 0xb0, 0x68, 0xa2, 0xa8, 0xce, 0x4b, 0xba, 0xf3, 0x05, 0x03, 0x5b, 0x8e, 0xe1, - 0x2e, 0xcc, 0xab, 0x3a, 0x21, 0xcd, 0x07, 0xc9, 0xa4, 0x6a, 0x37, 0x25, 0x58, 0xcd, 0xf2, 0x1e, - 0xb4, 0x4e, 0x3c, 0xdf, 0x1d, 0x38, 0xbd, 0x41, 0x7c, 0xee, 0xf4, 0xf9, 0x20, 0x76, 0x91, 0x62, - 0x4a, 0x76, 0x13, 0xe1, 0xeb, 0x83, 0xf8, 0x7c, 0x43, 0x40, 0xd9, 0x3b, 0x50, 0x3d, 0xe1, 0xdc, - 0xc1, 0xc5, 0x6a, 0x57, 0x52, 0x07, 0x4f, 0xed, 0x90, 0x5d, 0x39, 0x51, 0x7b, 0xf5, 0x0e, 0xb4, - 0x82, 0x71, 0x7c, 0x1a, 0x78, 0xfe, 0xa9, 0x23, 0x18, 0x9c, 0xe3, 0xf5, 0x91, 0x86, 0x8a, 0x6b, - 0xf9, 0x47, 0x39, 0xbb, 0xa9, 0xca, 0x04, 0xab, 0xd9, 0xe9, 0xb3, 0x37, 0x61, 0x7e, 0xe0, 0x46, - 0xb1, 0x73, 0x16, 0x8c, 0x9c, 0xd1, 0xf8, 0xf8, 0x19, 0xbf, 0x6a, 0x37, 0x70, 0x21, 0x1a, 0x02, - 0xbc, 0x1d, 0x8c, 0x0e, 0x11, 0x28, 0x28, 0x1b, 0xc7, 0x49, 0x83, 0x80, 0x3b, 0xb9, 0x7b, 0x0d, - 0xbb, 0x2a, 0x20, 0xd4, 0xe9, 0x17, 0xb0, 0x88, 0xdb, 0xd3, 0x1b, 0x47, 0x71, 0x30, 0x74, 0x04, - 0x73, 0x0e, 0xfb, 0x51, 0xbb, 0x86, 0xb4, 0xf6, 0x96, 0x1c, 0xac, 0xb1, 0xc7, 0x0f, 0x36, 0x78, - 0x14, 0xaf, 0x23, 0xb2, 0x4d, 0xb8, 0xe2, 0x06, 0xbf, 0xb2, 0x17, 0xfa, 0x93, 0x70, 0xf6, 0x0e, - 0x30, 0x77, 0x30, 0x08, 0x2e, 0x9c, 0x88, 0x0f, 0x4e, 0x1c, 0xb9, 0x88, 0xed, 0xe6, 0x9d, 0xdc, - 0xbd, 0x8a, 0xdd, 0xc2, 0x92, 0x2e, 0x1f, 0x9c, 0x1c, 0x12, 0x9c, 0x7d, 0x0f, 0xf0, 0x30, 0x39, - 0x27, 0xdc, 0x8d, 0xc7, 0x21, 0x8f, 0xda, 0xf3, 0x77, 0x0a, 0xf7, 0x9a, 0x8f, 0x17, 0xf4, 0x7a, - 0x21, 0x78, 0xcd, 0x8b, 0xed, 0xba, 0xc0, 0x93, 0xdf, 0x51, 0x67, 0x03, 0x96, 0xb3, 0x87, 0x24, - 0x88, 0x4a, 0xac, 0x8a, 0x20, 0xc6, 0xa2, 0x2d, 0xfe, 0x64, 0x4b, 0x50, 0x3a, 0x77, 0x07, 0x63, - 0x2e, 0x99, 0x38, 0x7d, 0x7c, 0x9c, 0xff, 0x28, 0x67, 0xfd, 0x51, 0x0e, 0xea, 0x34, 0x4b, 0x29, - 0x7c, 0xbc, 0x0e, 0x0d, 0x45, 0x0d, 0x3c, 0x0c, 0x83, 0x50, 0x72, 0x35, 0x45, 0x79, 0x9b, 0x02, - 0x26, 0xae, 0x11, 0x85, 0x34, 0x0a, 0xb9, 0x37, 0x74, 0x4f, 0x55, 0xd3, 0x8a, 0x94, 0x0e, 0x25, - 0x98, 0xbd, 0x97, 0xb4, 0x17, 0x06, 0xe3, 0x98, 0xcb, 0x4b, 0xae, 0x2e, 0xa7, 0x67, 0x0b, 0x98, - 0x6e, 0x1d, 0xbf, 0x5e, 0x82, 0xce, 0xad, 0xdf, 0xc9, 0x01, 0x13, 0xc3, 0x3e, 0x0a, 0xa8, 0x01, - 0x49, 0xa1, 0x93, 0x35, 0x73, 0x2f, 0x7d, 0x42, 0xf2, 0xcf, 0x3b, 0x21, 0x16, 0x94, 0x68, 0xec, - 0xc5, 0x8c, 0xb1, 0x53, 0xd1, 0x0f, 0x8a, 0x95, 0x42, 0xab, 0x68, 0xfd, 0xef, 0x02, 0x2c, 0xad, - 0xd3, 0x1d, 0xbd, 0xda, 0xeb, 0xf1, 0x91, 0x3e, 0x3b, 0xb7, 0xa1, 0xe6, 0x07, 0x7d, 0xae, 0x28, - 0x96, 0x06, 0x06, 0x02, 0x64, 0x90, 0xeb, 0x99, 0xeb, 0xf9, 0x34, 0x70, 0x5a, 0xcc, 0x2a, 0x42, - 0x70, 0xd8, 0x6f, 0xc2, 0xfc, 0x88, 0xfb, 0x7d, 0xf3, 0x88, 0x90, 0x14, 0xd5, 0x90, 0x60, 0x79, - 0x3a, 0x6e, 0x43, 0xed, 0x64, 0x4c, 0x78, 0x82, 0xb1, 0x14, 0x91, 0x06, 0x40, 0x82, 0x56, 0x89, - 0xbf, 0x8c, 0xc6, 0xd1, 0x19, 0x96, 0x96, 0xb0, 0xb4, 0x2c, 0xbe, 0x45, 0xd1, 0x2d, 0x80, 0xfe, - 0x38, 0x8a, 0xe5, 0x89, 0x99, 0xc3, 0xc2, 0xaa, 0x80, 0xd0, 0x89, 0x79, 0x17, 0x16, 0x87, 0xee, - 0xa5, 0x83, 0xb4, 0xe3, 0x78, 0xbe, 0x73, 0x32, 0xc0, 0x3b, 0xa7, 0x8c, 0x78, 0xad, 0xa1, 0x7b, - 0xf9, 0x43, 0x51, 0xb2, 0xe3, 0x6f, 0x21, 0x5c, 0xb0, 0x15, 0x25, 0xdf, 0x84, 0x3c, 0xe2, 0xe1, - 0x39, 0x47, 0x4e, 0x50, 0xd4, 0x42, 0x8c, 0x4d, 0x50, 0x31, 0xa2, 0xa1, 0x98, 0x77, 0x3c, 0xe8, - 0xd1, 0xb1, 0xb7, 0xcb, 0x43, 0xcf, 0xdf, 0x8e, 0x07, 0x3d, 0x71, 0xaf, 0x08, 0x3e, 0x32, 0xe2, - 0xa1, 0xf3, 0xec, 0x02, 0xcf, 0x70, 0x11, 0xf9, 0xc6, 0x21, 0x0f, 0x9f, 0x5c, 0x88, 0xab, 0xbf, - 0x17, 0x21, 0x23, 0x72, 0xaf, 0xda, 0x35, 0x3c, 0xe0, 0x95, 0x5e, 0x24, 0x58, 0x90, 0x7b, 0x25, - 0x0e, 0xa1, 0x18, 0xad, 0x8b, 0xbb, 0xc0, 0xfb, 0xd8, 0x7c, 0x84, 0x1c, 0xb5, 0x81, 0x83, 0x5d, - 0x95, 0x05, 0xa2, 0x9f, 0x48, 0x50, 0xbd, 0x1a, 0xec, 0xc9, 0xc0, 0x3d, 0x8d, 0x90, 0xa5, 0x34, - 0xec, 0xba, 0x04, 0x6e, 0x09, 0x98, 0xf5, 0x39, 0x49, 0x55, 0xc6, 0xde, 0xca, 0x33, 0x23, 0xae, - 0x7a, 0x84, 0xe0, 0xbe, 0x56, 0x6c, 0xf9, 0x95, 0xb5, 0x69, 0xf9, 0x8c, 0x4d, 0xb3, 0x7e, 0x2f, - 0x07, 0x75, 0xd9, 0x32, 0x0a, 0x25, 0xec, 0x01, 0x30, 0xb5, 0x8b, 0xf1, 0xa5, 0xd7, 0x77, 0x8e, - 0xaf, 0x62, 0x1e, 0x11, 0xd1, 0x6c, 0x5f, 0xb3, 0x5b, 0xb2, 0xec, 0xe8, 0xd2, 0xeb, 0xaf, 0x89, - 0x12, 0x76, 0x1f, 0x5a, 0x29, 0xfc, 0x28, 0x0e, 0x89, 0xa2, 0xb7, 0xaf, 0xd9, 0x4d, 0x03, 0xbb, - 0x1b, 0x87, 0xe2, 0x8c, 0x08, 0x91, 0x67, 0x1c, 0x3b, 0x9e, 0xdf, 0xe7, 0x97, 0x48, 0x46, 0x0d, - 0xbb, 0x46, 0xb0, 0x1d, 0x01, 0x5a, 0x6b, 0x42, 0xdd, 0x6c, 0xce, 0x3a, 0x85, 0x8a, 0x92, 0x97, - 0x50, 0x60, 0x98, 0x18, 0x92, 0x5d, 0x8d, 0xf5, 0x48, 0x6e, 0x40, 0x25, 0x3d, 0x02, 0xbb, 0x1c, - 0xbf, 0x74, 0xc7, 0xd6, 0xf7, 0xa1, 0xb5, 0x2b, 0x88, 0xc7, 0x17, 0xc4, 0x2a, 0xe5, 0xbf, 0x65, - 0x98, 0x33, 0x0e, 0x4d, 0xd5, 0x96, 0x5f, 0xe2, 0xce, 0x3d, 0x0b, 0xa2, 0x58, 0xf6, 0x82, 0x7f, - 0x5b, 0x7f, 0x9c, 0x03, 0xb6, 0x19, 0xc5, 0xde, 0xd0, 0x8d, 0xf9, 0x16, 0xd7, 0x6c, 0xe1, 0x00, - 0xea, 0xa2, 0xb5, 0xa3, 0x60, 0x95, 0x04, 0x32, 0x12, 0x28, 0xde, 0x96, 0xc7, 0x78, 0xba, 0xc2, - 0x03, 0x13, 0x9b, 0xd8, 0x7c, 0xaa, 0x01, 0x71, 0xca, 0x62, 0x37, 0x3c, 0xe5, 0x31, 0x8a, 0x71, - 0x52, 0xc0, 0x07, 0x02, 0x09, 0x01, 0xae, 0xf3, 0xab, 0xb0, 0x30, 0xd5, 0x86, 0xc9, 0x97, 0xab, - 0x19, 0x7c, 0xb9, 0x60, 0xf2, 0x65, 0x07, 0x16, 0x53, 0xe3, 0x92, 0x94, 0xb6, 0x02, 0x65, 0x71, - 0x20, 0x84, 0x70, 0x90, 0x23, 0xa9, 0xf2, 0x84, 0x73, 0x21, 0x06, 0x3f, 0x84, 0xa5, 0x13, 0xce, - 0x43, 0x37, 0xc6, 0x42, 0x3c, 0x31, 0x62, 0x87, 0x64, 0xc3, 0x0b, 0xb2, 0xac, 0xeb, 0xc6, 0x87, - 0x3c, 0x14, 0x3b, 0x65, 0xfd, 0x9f, 0x1c, 0xcc, 0x0b, 0x0e, 0xba, 0xe7, 0xfa, 0x57, 0x6a, 0x9d, - 0x76, 0x33, 0xd7, 0xe9, 0x9e, 0x71, 0x19, 0x1a, 0xd8, 0xdf, 0x74, 0x91, 0x0a, 0x93, 0x8b, 0xc4, - 0xee, 0x40, 0x3d, 0x35, 0xd6, 0x12, 0x8e, 0x15, 0x22, 0x3d, 0xc8, 0x9f, 0x7f, 0x19, 0xdf, 0x84, - 0x56, 0x32, 0x6c, 0xb9, 0x86, 0x0c, 0x8a, 0x82, 0x24, 0x65, 0x03, 0xf8, 0xb7, 0xf5, 0xcf, 0x73, - 0x84, 0xb8, 0x1e, 0x78, 0x5a, 0x3a, 0x15, 0x88, 0x42, 0xee, 0x55, 0x88, 0xe2, 0xef, 0x99, 0x52, - 0xfd, 0xcf, 0x3f, 0x59, 0x71, 0x74, 0x22, 0xee, 0xf7, 0x1d, 0x77, 0x30, 0x40, 0xe6, 0x5b, 0xb1, - 0xcb, 0xe2, 0x7b, 0x75, 0x30, 0xb0, 0xee, 0xc2, 0x82, 0x31, 0xba, 0xe7, 0xcc, 0x63, 0x1f, 0xd8, - 0xae, 0x17, 0xc5, 0x4f, 0xfd, 0x68, 0x64, 0x08, 0x6e, 0x37, 0xa1, 0x2a, 0x38, 0xac, 0x18, 0x19, - 0x1d, 0xd9, 0x92, 0x2d, 0x58, 0xae, 0x18, 0x57, 0x84, 0x85, 0xee, 0xa5, 0x2c, 0xcc, 0xcb, 0x42, - 0xf7, 0x12, 0x0b, 0xad, 0x8f, 0x60, 0x31, 0xd5, 0x9e, 0xec, 0xfa, 0x35, 0x28, 0x8d, 0xe3, 0xcb, - 0x40, 0x89, 0xe6, 0x35, 0x49, 0x21, 0x42, 0xe3, 0xb3, 0xa9, 0xc4, 0xfa, 0x04, 0x16, 0xf6, 0xf9, - 0x85, 0x3c, 0xc4, 0x6a, 0x20, 0x2f, 0xa9, 0x0d, 0x5a, 0x0f, 0x80, 0x99, 0x95, 0x65, 0xaf, 0x86, - 0x8e, 0x98, 0x4b, 0xe9, 0x88, 0xd6, 0x9b, 0xc0, 0xba, 0xde, 0xa9, 0xbf, 0xc7, 0xa3, 0xc8, 0x3d, - 0xd5, 0xc7, 0xbe, 0x05, 0x85, 0x61, 0x74, 0x2a, 0x79, 0x94, 0xf8, 0xd3, 0xfa, 0x2e, 0x2c, 0xa6, - 0xf0, 0x64, 0xc3, 0xaf, 0x40, 0x35, 0xf2, 0x4e, 0x7d, 0x14, 0xac, 0x64, 0xd3, 0x09, 0xc0, 0xda, - 0x82, 0xa5, 0x1f, 0xf2, 0xd0, 0x3b, 0xb9, 0x7a, 0x51, 0xf3, 0xe9, 0x76, 0xf2, 0x93, 0xed, 0x6c, - 0xc2, 0xf5, 0x89, 0x76, 0x64, 0xf7, 0x44, 0xbe, 0x72, 0x27, 0x2b, 0x36, 0x7d, 0x18, 0x7c, 0x2f, - 0x6f, 0xf2, 0x3d, 0xeb, 0x29, 0xb0, 0xf5, 0xc0, 0xf7, 0x79, 0x2f, 0x3e, 0xe4, 0x3c, 0x4c, 0xcc, - 0x52, 0x09, 0xad, 0xd6, 0x1e, 0xaf, 0xc8, 0x95, 0x9d, 0x64, 0xa6, 0x92, 0x88, 0x19, 0x14, 0x47, - 0x3c, 0x1c, 0x62, 0xc3, 0x15, 0x1b, 0xff, 0xb6, 0xae, 0xc3, 0x62, 0xaa, 0x59, 0xa9, 0xc8, 0x3f, - 0x82, 0xeb, 0x1b, 0x5e, 0xd4, 0x9b, 0xee, 0x70, 0x05, 0xca, 0xa3, 0xf1, 0xb1, 0x93, 0xe6, 0xcb, - 0x4f, 0xf8, 0x95, 0xd0, 0xf6, 0x26, 0x6b, 0xc8, 0xb6, 0xfe, 0x76, 0x0e, 0x8a, 0xdb, 0x47, 0xbb, - 0xeb, 0xac, 0x03, 0x15, 0xcf, 0xef, 0x05, 0x43, 0x21, 0x78, 0xd1, 0x9c, 0xf5, 0xf7, 0xcc, 0x03, - 0x76, 0x13, 0xaa, 0x28, 0xaf, 0x09, 0xd5, 0x56, 0x8a, 0x3e, 0x15, 0x01, 0xd8, 0x0d, 0x7a, 0xcf, - 0x84, 0x4e, 0xcd, 0x2f, 0x47, 0x5e, 0x88, 0x5a, 0xb3, 0x52, 0x86, 0x8b, 0x74, 0xd7, 0x27, 0x05, - 0xa4, 0x11, 0x5b, 0xff, 0xa1, 0x0c, 0x65, 0x79, 0xdb, 0xd2, 0xcd, 0x1d, 0x7b, 0xe7, 0x3c, 0xb9, - 0xb9, 0xc5, 0x97, 0x90, 0x07, 0x42, 0x3e, 0x0c, 0x62, 0x2d, 0xb0, 0xd1, 0x1e, 0xd4, 0x09, 0x28, - 0x45, 0x36, 0x43, 0x68, 0x20, 0x13, 0x43, 0x81, 0x90, 0x7a, 0xe6, 0x55, 0x7e, 0x13, 0xca, 0xea, - 0xee, 0x2f, 0x6a, 0x9d, 0x66, 0xae, 0x47, 0xd2, 0x5a, 0x07, 0x2a, 0x3d, 0x77, 0xe4, 0xf6, 0xbc, - 0xf8, 0x4a, 0x32, 0x04, 0xfd, 0x2d, 0x5a, 0x1f, 0x04, 0x3d, 0x77, 0xe0, 0x1c, 0xbb, 0x03, 0xd7, - 0xef, 0x71, 0xa9, 0xbb, 0xd7, 0x11, 0xb8, 0x46, 0x30, 0xa1, 0x9f, 0xcb, 0x71, 0x2a, 0x2c, 0x52, - 0xe1, 0xe5, 0xe8, 0x15, 0x9a, 0x10, 0x2e, 0x83, 0xe1, 0xd0, 0x13, 0x5a, 0x06, 0x89, 0x61, 0x05, - 0xbb, 0x4a, 0x90, 0x2d, 0x8e, 0xb3, 0x95, 0xc5, 0x17, 0xb4, 0x74, 0x55, 0xea, 0x8a, 0x80, 0x9f, - 0x93, 0x21, 0x61, 0x5a, 0x16, 0x2b, 0x18, 0xb2, 0xd8, 0xdb, 0xb0, 0x30, 0xf6, 0x23, 0x1e, 0xc7, - 0x03, 0xde, 0xd7, 0x63, 0xa9, 0x21, 0x52, 0x4b, 0x17, 0xa8, 0xe1, 0x3c, 0x80, 0x45, 0x32, 0x3a, - 0x44, 0x6e, 0x1c, 0x44, 0x67, 0x5e, 0xe4, 0x44, 0x42, 0x43, 0x22, 0x75, 0x77, 0x01, 0x8b, 0xba, - 0xb2, 0xa4, 0x4b, 0x2a, 0xd2, 0xca, 0x04, 0x7e, 0xc8, 0x7b, 0xdc, 0x3b, 0xe7, 0x7d, 0x94, 0xd3, - 0x0a, 0xf6, 0xf5, 0x54, 0x1d, 0x5b, 0x16, 0xa2, 0xd0, 0x3d, 0x1e, 0x3a, 0xe3, 0x51, 0xdf, 0x15, - 0xc2, 0x4a, 0x93, 0x84, 0x61, 0x7f, 0x3c, 0x7c, 0x4a, 0x10, 0xf6, 0x08, 0x94, 0x24, 0x26, 0xe5, - 0xc3, 0xf9, 0x14, 0x3f, 0x13, 0xc4, 0x6a, 0xd7, 0x25, 0x06, 0x09, 0x8a, 0x29, 0x99, 0xb3, 0x35, - 0x21, 0x73, 0xb6, 0xa1, 0x3c, 0x0a, 0xbd, 0x73, 0x37, 0xe6, 0xed, 0x05, 0x62, 0xe0, 0xf2, 0x53, - 0x70, 0x06, 0xcf, 0xf7, 0x62, 0xcf, 0x8d, 0x83, 0xb0, 0xcd, 0xb0, 0x2c, 0x01, 0xb0, 0xfb, 0xb0, - 0x80, 0x34, 0x12, 0xc5, 0x6e, 0x3c, 0x8e, 0xa4, 0x04, 0xba, 0x88, 0xc4, 0x84, 0x32, 0x74, 0x17, - 0xe1, 0x28, 0x84, 0xb2, 0xef, 0xc2, 0x32, 0x91, 0x05, 0xd6, 0x90, 0x92, 0x35, 0x0a, 0x04, 0x4b, - 0xb8, 0x14, 0x8b, 0x58, 0x2a, 0xe8, 0x5b, 0xca, 0xd7, 0x42, 0x3a, 0xf8, 0x00, 0x56, 0x24, 0x99, - 0x4c, 0xd5, 0xba, 0x8e, 0xb5, 0x96, 0xa8, 0x78, 0xa2, 0xda, 0x7d, 0x58, 0x10, 0x43, 0xf2, 0x7a, - 0x8e, 0xac, 0x2d, 0x4e, 0xc2, 0x32, 0x8e, 0x7e, 0x9e, 0x0a, 0x6c, 0x84, 0x3f, 0xe1, 0x57, 0x82, - 0x94, 0x07, 0xde, 0x09, 0x8f, 0xbd, 0x21, 0x6f, 0xaf, 0x10, 0x71, 0xa8, 0x6f, 0x71, 0xca, 0xc6, - 0x23, 0x2c, 0x69, 0xd3, 0x99, 0xa6, 0x2f, 0xa4, 0xbb, 0x41, 0x10, 0x71, 0x65, 0x5e, 0x6a, 0xdf, - 0x90, 0x07, 0x48, 0x00, 0x25, 0xcb, 0xb2, 0xfe, 0x30, 0x47, 0x77, 0x90, 0x3c, 0xb2, 0x91, 0xa1, - 0x51, 0xd1, 0x61, 0x75, 0x02, 0x7f, 0x70, 0x25, 0xcf, 0x2f, 0x10, 0xe8, 0xc0, 0x1f, 0xe0, 0x01, - 0xf2, 0x7c, 0x13, 0x85, 0xd8, 0x5d, 0x5d, 0x01, 0x11, 0xe9, 0x36, 0xd4, 0x46, 0xe3, 0xe3, 0x81, - 0xd7, 0x23, 0x94, 0x02, 0xb5, 0x42, 0x20, 0x44, 0x10, 0x2a, 0x25, 0x6d, 0x22, 0x61, 0x14, 0x11, - 0xa3, 0x26, 0x61, 0x88, 0x82, 0xec, 0x94, 0x87, 0x78, 0x82, 0xeb, 0x36, 0xfe, 0x6d, 0xad, 0xc1, - 0x52, 0x7a, 0xd0, 0x92, 0xd7, 0xdf, 0x87, 0x8a, 0x64, 0x0f, 0xca, 0xd6, 0xd0, 0x34, 0xcc, 0xbd, - 0x42, 0x2b, 0xd2, 0xe5, 0xd6, 0x6f, 0xcd, 0xc1, 0xa2, 0x84, 0xae, 0x8b, 0x15, 0xe9, 0x8e, 0x87, - 0x43, 0x37, 0xcc, 0xe0, 0x3b, 0xb9, 0xe7, 0xf3, 0x9d, 0xfc, 0x14, 0xdf, 0x49, 0x2b, 0x9b, 0xc4, - 0xb6, 0xd2, 0xca, 0xa6, 0xd8, 0x02, 0x92, 0xff, 0x4d, 0xd3, 0x63, 0x43, 0x82, 0x8f, 0xc8, 0xc4, - 0x39, 0xc5, 0x25, 0x4b, 0x19, 0x5c, 0xd2, 0xe4, 0x71, 0x73, 0x13, 0x3c, 0xee, 0x35, 0xa0, 0xbd, - 0x56, 0x2c, 0xbb, 0x4c, 0x2a, 0x01, 0xc2, 0xa4, 0xfd, 0xf2, 0x2e, 0xcc, 0x4f, 0xb2, 0x15, 0xe2, - 0x5f, 0xcd, 0x0c, 0xa6, 0xe2, 0x0d, 0x39, 0x5e, 0x10, 0x06, 0x72, 0x55, 0x32, 0x15, 0x6f, 0xc8, - 0x77, 0xb1, 0x44, 0xe1, 0x6f, 0x02, 0x50, 0xdf, 0x28, 0x91, 0x00, 0x4a, 0x24, 0x6f, 0xa6, 0xf7, - 0xc2, 0x5c, 0xf5, 0x07, 0xe2, 0x63, 0x1c, 0x72, 0x94, 0x52, 0xaa, 0x58, 0x53, 0xfc, 0xc9, 0x9e, - 0x40, 0x33, 0x18, 0x71, 0xdf, 0x49, 0x8e, 0x77, 0x0d, 0x9b, 0x7a, 0xe3, 0x39, 0x4d, 0xed, 0x28, - 0x5c, 0xbb, 0x21, 0xea, 0xea, 0x4f, 0xb6, 0x47, 0x0b, 0xcf, 0x8d, 0xd6, 0xea, 0xdf, 0xa0, 0xb5, - 0x26, 0x56, 0xd6, 0xdf, 0xd6, 0xdf, 0xcb, 0x41, 0xcd, 0x18, 0x36, 0xbb, 0x0e, 0x0b, 0xeb, 0x07, - 0x07, 0x87, 0x9b, 0xf6, 0xea, 0xd1, 0xce, 0x0f, 0x37, 0x9d, 0xf5, 0xdd, 0x83, 0xee, 0x66, 0xeb, - 0x9a, 0x00, 0xef, 0x1e, 0xac, 0xaf, 0xee, 0x3a, 0x5b, 0x07, 0xf6, 0xba, 0x02, 0xe7, 0xd8, 0x32, - 0x30, 0x7b, 0x73, 0xef, 0xe0, 0x68, 0x33, 0x05, 0xcf, 0xb3, 0x16, 0xd4, 0xd7, 0xec, 0xcd, 0xd5, - 0xf5, 0x6d, 0x09, 0x29, 0xb0, 0x25, 0x68, 0x6d, 0x3d, 0xdd, 0xdf, 0xd8, 0xd9, 0xff, 0xd4, 0x59, - 0x5f, 0xdd, 0x5f, 0xdf, 0xdc, 0xdd, 0xdc, 0x68, 0x15, 0x59, 0x03, 0xaa, 0xab, 0x6b, 0xab, 0xfb, - 0x1b, 0x07, 0xfb, 0x9b, 0x1b, 0xad, 0x92, 0xf5, 0x2b, 0x50, 0x4d, 0x26, 0x5a, 0x83, 0xf2, 0xd3, - 0xfd, 0x27, 0xfb, 0x07, 0x9f, 0xef, 0xb7, 0xae, 0xb1, 0x2a, 0x94, 0xb0, 0xff, 0x56, 0x8e, 0x01, - 0xcc, 0x51, 0x9f, 0xad, 0x3c, 0xab, 0x40, 0x71, 0xed, 0xe0, 0x68, 0xbb, 0x55, 0xb0, 0xfe, 0x2c, - 0x07, 0xd7, 0x71, 0xca, 0xfd, 0x49, 0x26, 0x70, 0x07, 0x6a, 0xbd, 0x20, 0x18, 0x09, 0xe5, 0x26, - 0xb9, 0xc4, 0x4d, 0x90, 0x38, 0xe0, 0xc4, 0x2f, 0x4f, 0x82, 0xb0, 0xc7, 0x25, 0x0f, 0x00, 0x04, - 0x6d, 0x09, 0x88, 0xa0, 0x41, 0x49, 0xc4, 0x84, 0x41, 0x2c, 0xa0, 0x46, 0x30, 0x42, 0x59, 0x86, - 0xb9, 0xe3, 0x90, 0xbb, 0xbd, 0x33, 0x79, 0xfa, 0xe5, 0x17, 0x7b, 0x2b, 0x51, 0xbb, 0x7b, 0x82, - 0xa6, 0x06, 0xbc, 0x8f, 0x47, 0xa0, 0x62, 0xcf, 0x4b, 0xf8, 0xba, 0x04, 0x8b, 0x0b, 0xc0, 0x3d, - 0x76, 0xfd, 0x7e, 0xe0, 0xf3, 0xbe, 0x94, 0xee, 0x13, 0x80, 0x75, 0x08, 0xcb, 0x93, 0xf3, 0x93, - 0xfc, 0xe2, 0x7b, 0x06, 0xbf, 0x20, 0x61, 0xbb, 0x33, 0x9b, 0x14, 0x0c, 0xde, 0xf1, 0xb3, 0x02, - 0x14, 0x85, 0xf0, 0x35, 0x53, 0x4e, 0x33, 0xa5, 0xe9, 0xc2, 0x94, 0xc7, 0x05, 0xb5, 0x7b, 0xba, - 0x95, 0xc9, 0x84, 0x54, 0x45, 0x08, 0xde, 0xc6, 0xba, 0x38, 0xe4, 0xbd, 0x73, 0x69, 0x43, 0xa2, - 0x62, 0x9b, 0xf7, 0xce, 0x51, 0x8d, 0x71, 0x63, 0xaa, 0x4b, 0xe7, 0xbd, 0x1c, 0xb9, 0x31, 0xd6, - 0x94, 0x45, 0x58, 0xaf, 0xac, 0x8b, 0xb0, 0x56, 0x1b, 0xca, 0x9e, 0x7f, 0x1c, 0x8c, 0xfd, 0x3e, - 0x1e, 0xef, 0x8a, 0xad, 0x3e, 0xd1, 0xc1, 0x83, 0x9c, 0x48, 0xdc, 0x1f, 0x74, 0x9a, 0x2b, 0x02, - 0x70, 0x24, 0x6e, 0x90, 0xf7, 0xa0, 0x1a, 0x5d, 0xf9, 0x3d, 0xf3, 0x0c, 0x2f, 0xc9, 0xf5, 0x11, - 0xb3, 0x7f, 0xd0, 0xbd, 0xf2, 0x7b, 0x78, 0x62, 0x2b, 0x91, 0xfc, 0x8b, 0x7d, 0x00, 0x15, 0x6d, - 0x6a, 0x25, 0x0e, 0x7c, 0xc3, 0xac, 0xa1, 0xec, 0xab, 0xa4, 0xd1, 0x6a, 0xd4, 0xce, 0x13, 0x68, - 0xa4, 0x8a, 0x4c, 0x35, 0xb4, 0x41, 0x6a, 0xe8, 0x1b, 0xa6, 0x1a, 0x9a, 0x30, 0x76, 0x59, 0xcd, - 0x54, 0x4b, 0x7f, 0x15, 0x2a, 0x6a, 0x64, 0xe2, 0x38, 0xc9, 0xa3, 0xe0, 0x74, 0xbf, 0xd8, 0x5f, - 0x6f, 0x5d, 0x63, 0xf3, 0x50, 0x5b, 0x5d, 0xc7, 0x13, 0x8a, 0x80, 0x9c, 0x40, 0x39, 0x5c, 0xed, - 0x76, 0x35, 0x24, 0x6f, 0x31, 0x68, 0x89, 0xeb, 0x45, 0x8c, 0x58, 0x3b, 0x53, 0xbe, 0x07, 0x0b, - 0x06, 0x2c, 0xd1, 0xd4, 0xc4, 0x7d, 0x34, 0xa9, 0xa9, 0xa1, 0x5c, 0x4e, 0x25, 0xd6, 0x0a, 0x5c, - 0x17, 0x9f, 0x9b, 0xe7, 0xdc, 0x8f, 0xbb, 0xe3, 0x63, 0x72, 0xa5, 0x79, 0x81, 0x2f, 0xe4, 0xf5, - 0xaa, 0x2e, 0x99, 0x4d, 0x48, 0x0f, 0xa4, 0x52, 0x97, 0xc7, 0xe5, 0xef, 0x18, 0x3d, 0x60, 0xc5, - 0x07, 0xf8, 0x6f, 0x4a, 0xb9, 0xab, 0x6a, 0x90, 0x98, 0xeb, 0xe1, 0xe6, 0xa6, 0xed, 0x1c, 0xec, - 0xef, 0xee, 0xec, 0x0b, 0x66, 0x24, 0xe6, 0x8a, 0x80, 0xad, 0x2d, 0x84, 0xe4, 0xac, 0x16, 0x34, - 0x3f, 0xe5, 0xf1, 0x8e, 0x7f, 0x12, 0xa8, 0x99, 0xfe, 0xdf, 0x12, 0xcc, 0x6b, 0x50, 0xa2, 0x1c, - 0x9e, 0xf3, 0x30, 0xf2, 0x02, 0x1f, 0xe5, 0xbc, 0xaa, 0xad, 0x3e, 0xc5, 0x0d, 0xe2, 0xf5, 0xb9, - 0x1f, 0x7b, 0xf1, 0x95, 0x93, 0xb2, 0x24, 0x35, 0x15, 0x58, 0xde, 0x54, 0x4b, 0x50, 0x72, 0x07, - 0x9e, 0xab, 0x3c, 0x90, 0xf4, 0x21, 0xa0, 0xbd, 0x60, 0x10, 0x84, 0x28, 0xd2, 0x55, 0x6d, 0xfa, - 0x60, 0x8f, 0x60, 0x49, 0x88, 0x96, 0xa6, 0x79, 0x0f, 0xcf, 0x28, 0x19, 0xb5, 0x98, 0x3f, 0x1e, - 0x1e, 0x26, 0x26, 0x3e, 0x51, 0x22, 0xee, 0x27, 0x51, 0x43, 0x0a, 0x24, 0xba, 0x02, 0x69, 0x29, - 0x0b, 0xfe, 0x78, 0xb8, 0x8a, 0x25, 0x1a, 0xff, 0x31, 0x5c, 0x17, 0xf8, 0x5a, 0x84, 0xd1, 0x35, - 0xe6, 0xb1, 0x86, 0x68, 0x6c, 0x47, 0x96, 0xe9, 0x3a, 0x37, 0xa1, 0x4a, 0xa3, 0x12, 0x3b, 0x5e, - 0x22, 0xe9, 0x14, 0x87, 0xc2, 0xc3, 0x68, 0xca, 0x59, 0x38, 0x47, 0x97, 0xed, 0x84, 0xb3, 0xd0, - 0x70, 0x37, 0x56, 0x26, 0xdd, 0x8d, 0x8f, 0xe1, 0xfa, 0x31, 0x8f, 0x62, 0xe7, 0x8c, 0xbb, 0x7d, - 0x1e, 0xe2, 0x89, 0x24, 0xb7, 0x22, 0x49, 0xe1, 0x8b, 0xa2, 0x70, 0x1b, 0xcb, 0x8e, 0x54, 0x91, - 0x90, 0x25, 0xc4, 0xd1, 0xe3, 0x7d, 0x27, 0x0e, 0x1c, 0x14, 0x31, 0xf0, 0x10, 0x57, 0xec, 0x06, - 0x81, 0x8f, 0x82, 0x75, 0x01, 0x4c, 0xe3, 0x9d, 0x86, 0xee, 0xe8, 0x4c, 0xca, 0xc9, 0x1a, 0xef, - 0x53, 0x01, 0x64, 0xaf, 0x40, 0x39, 0xe6, 0x51, 0xec, 0x73, 0xf2, 0xe9, 0x54, 0xd0, 0x66, 0xaf, - 0x40, 0xec, 0x0d, 0x98, 0xc3, 0x3e, 0xa2, 0x76, 0x0b, 0xe9, 0xbd, 0x9e, 0x30, 0x4b, 0xcf, 0xb7, - 0x65, 0x99, 0x10, 0xd8, 0xc6, 0xa1, 0x17, 0xb5, 0xeb, 0xe8, 0xcb, 0xc4, 0xbf, 0xd9, 0xaf, 0x19, - 0x6c, 0x61, 0x11, 0xeb, 0xaa, 0x3b, 0x77, 0x82, 0xd2, 0x7e, 0x29, 0x1c, 0xe2, 0x07, 0xc5, 0x4a, - 0xad, 0x55, 0xb7, 0x3e, 0x84, 0x12, 0xad, 0x8e, 0x20, 0x42, 0x5c, 0xbb, 0x9c, 0x24, 0x42, 0x84, - 0xb6, 0xa1, 0xec, 0xf3, 0xf8, 0x22, 0x08, 0x9f, 0x29, 0x5b, 0xab, 0xfc, 0xb4, 0x7e, 0x8a, 0x46, - 0x02, 0xed, 0x48, 0x26, 0x7d, 0x47, 0x90, 0x07, 0x6d, 0x6f, 0x74, 0xe6, 0x4a, 0xbb, 0x45, 0x05, - 0x01, 0xdd, 0x33, 0x77, 0x8a, 0x3c, 0xf2, 0xd3, 0xbe, 0xe4, 0x37, 0xa0, 0xa9, 0x5c, 0xd7, 0x91, - 0x33, 0xe0, 0x27, 0xb1, 0x24, 0xf7, 0xba, 0xf4, 0x5b, 0x47, 0xbb, 0xfc, 0x24, 0xb6, 0xf6, 0x60, - 0x41, 0x12, 0xe4, 0xc1, 0x88, 0xab, 0xae, 0x3f, 0xca, 0x92, 0x59, 0x6b, 0x8f, 0x17, 0xd3, 0x97, - 0x19, 0xb9, 0xe4, 0x53, 0x82, 0xac, 0xf5, 0x19, 0x30, 0xf3, 0xaa, 0x93, 0xed, 0x49, 0xc9, 0x51, - 0x99, 0xa8, 0x95, 0xa7, 0x47, 0xcb, 0xa7, 0x5e, 0x5f, 0xac, 0x4e, 0x34, 0xee, 0xf5, 0x54, 0x48, - 0x41, 0xc5, 0x56, 0x9f, 0xd6, 0x9f, 0xe6, 0x60, 0x11, 0x1b, 0x53, 0x32, 0xb7, 0x94, 0x26, 0xbe, - 0xf5, 0x20, 0xc5, 0xfe, 0x98, 0xf2, 0x05, 0x7d, 0x7c, 0x73, 0xa3, 0x60, 0x71, 0xca, 0x28, 0xf8, - 0x16, 0xb4, 0xfa, 0x7c, 0xe0, 0x61, 0x38, 0x89, 0xba, 0xae, 0x49, 0xca, 0x9e, 0x57, 0x70, 0xa5, - 0x28, 0xfd, 0x93, 0x1c, 0x2c, 0x90, 0x34, 0x80, 0xea, 0xa2, 0x5c, 0xa8, 0x4f, 0x94, 0x8e, 0x25, - 0x59, 0x95, 0x9c, 0x53, 0x72, 0x4b, 0x22, 0x94, 0x90, 0xb7, 0xaf, 0x49, 0xdd, 0x4b, 0x42, 0xd9, - 0xc7, 0xa8, 0x27, 0xf8, 0x0e, 0x02, 0x33, 0xc2, 0x53, 0xd2, 0x9b, 0xb2, 0x7d, 0x0d, 0x95, 0x08, - 0x1f, 0x41, 0x6b, 0x15, 0xa1, 0xf4, 0x09, 0xb0, 0xb5, 0x05, 0x8d, 0x54, 0x37, 0x29, 0xcb, 0x65, - 0x9d, 0x2c, 0x97, 0x53, 0xde, 0x81, 0xfc, 0xb4, 0x77, 0xe0, 0xef, 0x14, 0x81, 0x09, 0x92, 0x9a, - 0xd8, 0xb5, 0x09, 0xd7, 0x5a, 0x7e, 0xca, 0xb5, 0xf6, 0x08, 0x98, 0x81, 0xa0, 0x3c, 0x7e, 0x05, - 0xed, 0xf1, 0x6b, 0x25, 0xb8, 0xd2, 0xe1, 0xf7, 0x08, 0x96, 0xa4, 0xd0, 0xa8, 0x7d, 0x69, 0x68, - 0x92, 0xa2, 0xfd, 0x61, 0x24, 0x3d, 0x2a, 0x9f, 0x1a, 0x9a, 0xa7, 0x94, 0x5b, 0x4d, 0xa8, 0xd4, - 0x64, 0xc9, 0x41, 0xb7, 0x9a, 0xd0, 0xa2, 0x27, 0xa8, 0x60, 0xee, 0x85, 0x54, 0x50, 0x9e, 0xa2, - 0x02, 0xc3, 0xb0, 0x50, 0x49, 0x1b, 0x16, 0x2c, 0x68, 0x28, 0xe7, 0x19, 0xc5, 0x0c, 0x90, 0x84, - 0x54, 0x93, 0x1e, 0x34, 0x8c, 0x1b, 0xb8, 0x07, 0x2d, 0xa5, 0xfd, 0x6b, 0xd3, 0x05, 0xf9, 0xc3, - 0xa5, 0xf1, 0x68, 0x5d, 0x19, 0x30, 0x52, 0x86, 0xe2, 0xda, 0x84, 0xa1, 0xf8, 0x6d, 0x58, 0x88, - 0x04, 0x11, 0x39, 0x63, 0x5f, 0x06, 0xaf, 0xf0, 0x3e, 0xaa, 0x27, 0x15, 0xbb, 0x85, 0x05, 0x4f, - 0x13, 0xf8, 0xb4, 0x6a, 0xdf, 0x98, 0x56, 0xed, 0xd9, 0x07, 0x89, 0x9f, 0x29, 0x3a, 0xf3, 0x86, - 0x78, 0x71, 0x27, 0x81, 0x1e, 0x72, 0x81, 0xbb, 0x67, 0xde, 0xd0, 0x56, 0x4e, 0x4d, 0xf1, 0x61, - 0xfd, 0x97, 0x1c, 0xb4, 0x04, 0x1d, 0xa4, 0xe8, 0xfc, 0x57, 0x00, 0x4f, 0xe4, 0x4b, 0x92, 0x79, - 0x4d, 0xe0, 0x2a, 0x2a, 0xff, 0x10, 0x90, 0x6c, 0x1d, 0xa1, 0x8b, 0x49, 0x22, 0x6f, 0xa7, 0x89, - 0x3c, 0x61, 0x64, 0xdb, 0xd7, 0x48, 0xc8, 0x16, 0x90, 0x2c, 0xff, 0x5e, 0x31, 0xc3, 0xbf, 0x67, - 0x1c, 0x85, 0x6d, 0x80, 0x27, 0xfc, 0x6a, 0x37, 0xe8, 0xa1, 0x16, 0x74, 0x0b, 0x40, 0x10, 0xe4, - 0x89, 0x3b, 0xf4, 0xa4, 0x05, 0xa3, 0x64, 0x57, 0x9f, 0xf1, 0xab, 0x2d, 0x04, 0x88, 0xdd, 0x10, - 0xc5, 0xc9, 0x79, 0x28, 0xd9, 0x95, 0x67, 0xfc, 0x8a, 0x0e, 0x83, 0x03, 0x8d, 0x27, 0xfc, 0x6a, - 0x83, 0x93, 0xb8, 0x16, 0x84, 0x82, 0x12, 0x42, 0xf7, 0x42, 0xc8, 0x67, 0x29, 0xdf, 0x5c, 0x2d, - 0x74, 0x2f, 0x9e, 0xf0, 0x2b, 0xe5, 0x27, 0x2c, 0x8b, 0xf2, 0x41, 0xd0, 0x93, 0x37, 0x90, 0x8a, - 0x32, 0x48, 0x06, 0x65, 0xcf, 0x3d, 0xc3, 0xbf, 0xad, 0x3f, 0xc9, 0x41, 0x43, 0x8c, 0x1f, 0x19, - 0x9c, 0x58, 0x77, 0x15, 0xac, 0x92, 0x4b, 0x82, 0x55, 0x1e, 0x4b, 0xfe, 0x40, 0xdc, 0x32, 0x3f, - 0x9b, 0x5b, 0xe2, 0x02, 0x13, 0xab, 0x7c, 0x0f, 0xaa, 0x74, 0xb6, 0xc4, 0x61, 0x2d, 0xa4, 0x76, - 0x29, 0x35, 0x21, 0xbb, 0x82, 0x68, 0x4f, 0xc8, 0x37, 0x6e, 0x18, 0xa0, 0x68, 0x89, 0xab, 0xa1, - 0x36, 0x3d, 0x65, 0x6c, 0x43, 0x29, 0xcb, 0xcd, 0xfa, 0x14, 0x6a, 0x06, 0x4d, 0xb1, 0xef, 0x93, - 0x83, 0x9a, 0x06, 0x4f, 0x04, 0x98, 0x26, 0x9a, 0xd4, 0xec, 0xb7, 0xaf, 0xd9, 0x8d, 0x9e, 0x09, - 0x58, 0x9b, 0x83, 0xa2, 0xa8, 0x64, 0x7d, 0x02, 0x0b, 0x46, 0xb3, 0xa4, 0xf1, 0x65, 0x8d, 0x29, - 0x97, 0x35, 0xa6, 0x7f, 0x9a, 0x83, 0x25, 0x59, 0x1b, 0x03, 0x9b, 0x3c, 0x71, 0x5d, 0xef, 0x45, - 0xa7, 0xec, 0x57, 0xa0, 0x21, 0x5a, 0x77, 0x42, 0x7e, 0xea, 0x45, 0x31, 0x57, 0x96, 0xfd, 0x8c, - 0xc3, 0x21, 0xb8, 0xb6, 0x40, 0xb5, 0x25, 0x26, 0xfb, 0x04, 0x6a, 0x58, 0x95, 0x74, 0x52, 0xb9, - 0x2d, 0xed, 0xe9, 0x8a, 0x34, 0xd4, 0xed, 0x6b, 0x36, 0x44, 0xfa, 0x6b, 0xad, 0x0a, 0xe5, 0x38, - 0xf4, 0x4e, 0x4f, 0x79, 0x68, 0x2d, 0xeb, 0xa1, 0x89, 0x93, 0xc6, 0xbb, 0x31, 0x1f, 0x09, 0x21, - 0xc8, 0xfa, 0x6f, 0x39, 0xa8, 0xc9, 0xb3, 0xf3, 0xad, 0xcd, 0xf9, 0x1d, 0x23, 0x32, 0x8f, 0xd4, - 0xcf, 0x24, 0x10, 0xef, 0x2e, 0xcc, 0x0f, 0x85, 0x40, 0x24, 0x04, 0xf6, 0x94, 0x2d, 0xbf, 0xa9, - 0xc0, 0x52, 0x1e, 0x79, 0x00, 0x8b, 0x28, 0x9e, 0x44, 0x4e, 0xec, 0x0d, 0x1c, 0x55, 0x28, 0xa3, - 0xe0, 0x16, 0xa8, 0xe8, 0xc8, 0x1b, 0xec, 0xc9, 0x02, 0x71, 0x4b, 0x47, 0xb1, 0x7b, 0xca, 0xa5, - 0xe8, 0x4b, 0x1f, 0x56, 0x1b, 0x96, 0x27, 0x64, 0x75, 0xa5, 0x67, 0xfc, 0xfd, 0x06, 0xac, 0x4c, - 0x15, 0x49, 0x7d, 0x43, 0xdb, 0xb0, 0x07, 0xde, 0xf0, 0x38, 0xd0, 0xe6, 0xa6, 0x9c, 0x61, 0xc3, - 0xde, 0x15, 0x25, 0xca, 0xdc, 0xc4, 0xe1, 0xba, 0x22, 0x08, 0xb4, 0x17, 0x69, 0x71, 0x3e, 0x8f, - 0xc2, 0xe6, 0x7b, 0x69, 0x46, 0x35, 0xd9, 0x9d, 0x82, 0x9b, 0xd7, 0xdf, 0xe2, 0x68, 0x0a, 0x16, - 0xb1, 0x13, 0x68, 0x6b, 0xba, 0x93, 0xf2, 0x91, 0xa1, 0x9b, 0x88, 0x9e, 0xde, 0x79, 0x41, 0x4f, - 0x29, 0x43, 0x84, 0xbd, 0xac, 0xc8, 0x95, 0x1a, 0xd3, 0xfd, 0x9c, 0xc3, 0xab, 0xaa, 0x1f, 0x94, - 0x75, 0xa6, 0x7b, 0x2b, 0xbe, 0xd4, 0xbc, 0xd0, 0xc0, 0x92, 0xee, 0xf2, 0xa6, 0x6c, 0x58, 0x17, - 0x99, 0xfd, 0x9e, 0xc1, 0xf2, 0x85, 0xeb, 0xc5, 0x6a, 0x7e, 0x86, 0x5a, 0x54, 0xc2, 0xfe, 0x1e, - 0xbf, 0xa0, 0xbf, 0xcf, 0xa9, 0x72, 0x4a, 0xfa, 0x5b, 0xba, 0x98, 0x06, 0x46, 0x9d, 0xff, 0x94, - 0x87, 0x66, 0xba, 0x15, 0x71, 0xa8, 0x25, 0x1f, 0x52, 0xf2, 0x84, 0x94, 0xc7, 0xa5, 0x19, 0x74, - 0x9f, 0xe4, 0x88, 0x69, 0x03, 0x6d, 0x3e, 0xc3, 0x40, 0x6b, 0xda, 0x45, 0x0b, 0x2f, 0xf2, 0xfd, - 0x14, 0x5f, 0xca, 0xf7, 0x53, 0xca, 0xf2, 0xfd, 0xcc, 0x76, 0x18, 0xcc, 0x7d, 0x2b, 0x87, 0x41, - 0x79, 0xb6, 0xc3, 0xa0, 0xf3, 0x97, 0x39, 0x60, 0xd3, 0x94, 0xca, 0x3e, 0x25, 0x5b, 0xb4, 0xcf, - 0x07, 0x92, 0x8b, 0xbd, 0xfb, 0x72, 0xd4, 0xae, 0x36, 0x48, 0xd5, 0x66, 0x0f, 0x61, 0xd1, 0x8c, - 0x9b, 0x35, 0x55, 0x95, 0x86, 0xcd, 0xcc, 0xa2, 0x44, 0xa1, 0x35, 0x1c, 0x5f, 0xc5, 0x17, 0x3a, - 0xbe, 0x4a, 0x2f, 0x74, 0x7c, 0xcd, 0xa5, 0x1d, 0x5f, 0x9d, 0xbf, 0x95, 0x83, 0xc5, 0x0c, 0xa2, - 0xfa, 0xc5, 0xcd, 0x59, 0xd0, 0x42, 0x8a, 0xc5, 0xe4, 0x25, 0x2d, 0x18, 0xdc, 0xa5, 0xf3, 0x15, - 0x34, 0x52, 0x87, 0xe8, 0x17, 0xd7, 0xfd, 0xa4, 0xa2, 0x45, 0xa4, 0x6c, 0x2a, 0x5a, 0x9d, 0xbf, - 0xc8, 0x03, 0x9b, 0x3e, 0xc7, 0xbf, 0xcc, 0x21, 0x4c, 0x2f, 0x52, 0x61, 0x7a, 0x91, 0xfe, 0xff, - 0xdd, 0x2b, 0x6f, 0xc3, 0x82, 0x0c, 0xee, 0x37, 0x1c, 0x0f, 0x44, 0x28, 0x2d, 0x5d, 0xa0, 0x46, - 0xf1, 0xe1, 0xa4, 0xcf, 0xb1, 0x92, 0x0a, 0x6f, 0x36, 0x2e, 0xd6, 0xb4, 0xeb, 0xd1, 0xea, 0x40, - 0x5b, 0x2e, 0xcd, 0xb4, 0xa9, 0xee, 0x77, 0x8a, 0x5a, 0x4b, 0xc6, 0x42, 0x29, 0x14, 0x7f, 0x17, - 0xea, 0xe6, 0x65, 0x23, 0xf7, 0x61, 0xc2, 0xe3, 0x24, 0xc4, 0xe1, 0xc0, 0x38, 0xad, 0xeb, 0x40, - 0x7e, 0x84, 0xbe, 0xae, 0x46, 0x12, 0xc4, 0x73, 0x0c, 0xcf, 0x28, 0x1c, 0xa5, 0x36, 0xff, 0xaf, - 0x40, 0x33, 0x6d, 0xb7, 0x92, 0xa2, 0x5e, 0x96, 0x74, 0x28, 0x6a, 0xa7, 0x0c, 0x59, 0xec, 0xd7, - 0xa0, 0x35, 0x69, 0xf7, 0x92, 0xb1, 0x97, 0x33, 0xea, 0xcf, 0x7b, 0x69, 0x53, 0x18, 0xdb, 0x86, - 0xa5, 0xac, 0xeb, 0x16, 0x77, 0x65, 0xb6, 0x5a, 0xc0, 0xa6, 0xaf, 0x54, 0xf6, 0x91, 0x34, 0x6f, - 0x96, 0xb2, 0x1c, 0x31, 0xc6, 0x62, 0x3f, 0xa0, 0xff, 0x0c, 0x43, 0xe7, 0x39, 0x40, 0x02, 0x63, - 0x2d, 0xa8, 0x1f, 0x1c, 0x6e, 0xee, 0x3b, 0xeb, 0xdb, 0xab, 0xfb, 0xfb, 0x9b, 0xbb, 0xad, 0x6b, - 0x8c, 0x41, 0x13, 0x3d, 0x28, 0x1b, 0x1a, 0x96, 0x13, 0x30, 0x69, 0xfb, 0x55, 0xb0, 0x3c, 0x5b, - 0x82, 0xd6, 0xce, 0xfe, 0x04, 0xb4, 0xc0, 0xda, 0xb0, 0x74, 0xb8, 0x49, 0x4e, 0x97, 0x54, 0xbb, - 0x45, 0x21, 0xc2, 0xc9, 0xe9, 0x0a, 0x11, 0x8e, 0x52, 0x43, 0x24, 0xf5, 0x29, 0xc9, 0xe6, 0x77, - 0x73, 0x70, 0x7d, 0xa2, 0x20, 0x89, 0xff, 0x25, 0xb9, 0x26, 0x2d, 0xd1, 0xd4, 0x11, 0xa8, 0x68, - 0xf8, 0x6d, 0x58, 0xd0, 0xaa, 0xde, 0x04, 0x5f, 0x6a, 0xe9, 0x02, 0x85, 0xfc, 0x10, 0x16, 0x0d, - 0x8d, 0x71, 0xe2, 0x84, 0x32, 0xa3, 0x48, 0x56, 0xb0, 0x56, 0x74, 0x9c, 0xe5, 0xc4, 0xa8, 0xfb, - 0x94, 0x6f, 0x62, 0x16, 0x24, 0xd6, 0xdf, 0xf4, 0x78, 0xd5, 0xa7, 0x50, 0xe5, 0x53, 0x84, 0x90, - 0x1e, 0xad, 0xb9, 0xe1, 0xaa, 0xfb, 0xdf, 0x9f, 0x03, 0xf6, 0xd9, 0x98, 0x87, 0x57, 0x18, 0xdf, - 0x1b, 0xbd, 0x28, 0xe0, 0x45, 0xa9, 0x45, 0xf9, 0x97, 0x8a, 0xe1, 0xcf, 0x8a, 0xa1, 0x2f, 0xbe, - 0x38, 0x86, 0xbe, 0xf4, 0xa2, 0x18, 0xfa, 0xd7, 0xa1, 0xe1, 0x9d, 0xfa, 0x81, 0x60, 0x40, 0x42, - 0x36, 0x89, 0xda, 0x73, 0x77, 0x0a, 0xf7, 0xea, 0x76, 0x5d, 0x02, 0x85, 0x64, 0x12, 0xb1, 0x4f, - 0x12, 0x24, 0xde, 0x3f, 0xc5, 0x7c, 0x0f, 0x93, 0xf5, 0x6c, 0xf6, 0x4f, 0xb9, 0xd4, 0x02, 0xd1, - 0x2e, 0xa2, 0x2a, 0x0b, 0x78, 0xc4, 0xde, 0x80, 0x66, 0x14, 0x8c, 0x85, 0xa8, 0xa7, 0x96, 0x81, - 0xec, 0xc3, 0x75, 0x82, 0x1e, 0x2a, 0x67, 0xc0, 0xe2, 0x38, 0xe2, 0xce, 0xd0, 0x8b, 0x22, 0x71, - 0x41, 0xf7, 0x02, 0x3f, 0x0e, 0x83, 0x81, 0x34, 0xf9, 0x2e, 0x8c, 0x23, 0xbe, 0x47, 0x25, 0xeb, - 0x54, 0xc0, 0xde, 0x4f, 0x86, 0x34, 0x72, 0xbd, 0x30, 0x6a, 0x03, 0x0e, 0x49, 0xcd, 0x14, 0x25, - 0x2a, 0xd7, 0x0b, 0xf5, 0x58, 0xc4, 0x47, 0x34, 0x11, 0xdb, 0x5f, 0x9b, 0x8c, 0xed, 0xff, 0x49, - 0x76, 0x6c, 0x7f, 0x03, 0x9b, 0x7e, 0x24, 0x9b, 0x9e, 0xde, 0xe2, 0x6f, 0x14, 0xe2, 0x3f, 0x9d, - 0xb2, 0xd0, 0xfc, 0x26, 0x29, 0x0b, 0xf3, 0x59, 0x29, 0x0b, 0xef, 0x41, 0x0d, 0x83, 0xc9, 0x9d, - 0x33, 0xcf, 0x8f, 0x95, 0x09, 0xbb, 0x65, 0x46, 0x9b, 0x6f, 0x0b, 0x65, 0x1a, 0x42, 0xf5, 0x67, - 0x34, 0x9d, 0x3d, 0xb0, 0xf0, 0x4b, 0xcc, 0x1e, 0x90, 0x41, 0xef, 0x0f, 0xa0, 0xa2, 0xf6, 0x89, - 0x31, 0x28, 0x9e, 0x84, 0xc1, 0x50, 0x99, 0xf6, 0xc4, 0xdf, 0xac, 0x09, 0xf9, 0x38, 0x90, 0x95, - 0xf3, 0x71, 0x60, 0xfd, 0x06, 0xd4, 0x0c, 0x52, 0x63, 0xaf, 0x91, 0x11, 0x41, 0x48, 0xcb, 0x52, - 0x4b, 0xa6, 0x55, 0xac, 0x4a, 0xe8, 0x4e, 0x5f, 0xf0, 0x9b, 0xbe, 0x17, 0x72, 0xcc, 0xf3, 0x71, - 0x42, 0x7e, 0xce, 0xc3, 0x48, 0x99, 0x5a, 0x5b, 0xba, 0xc0, 0x26, 0xb8, 0xf5, 0xd7, 0x61, 0x31, - 0xb5, 0xb7, 0x92, 0x45, 0xbc, 0x01, 0x73, 0xb8, 0x6e, 0xca, 0x15, 0x96, 0x8e, 0xe2, 0x97, 0x65, - 0x98, 0xb1, 0x49, 0x56, 0x62, 0x67, 0x14, 0x06, 0xc7, 0xd8, 0x49, 0xce, 0xae, 0x49, 0xd8, 0x61, - 0x18, 0x1c, 0x5b, 0x3f, 0x2b, 0x40, 0x61, 0x3b, 0x18, 0x99, 0x11, 0x16, 0xb9, 0xa9, 0x08, 0x0b, - 0xa9, 0x02, 0x38, 0x5a, 0xc4, 0x97, 0x52, 0x1b, 0xda, 0x47, 0x95, 0x98, 0x7f, 0x0f, 0x9a, 0x82, - 0x4f, 0xc4, 0x81, 0xd0, 0xa1, 0x2e, 0xdc, 0x90, 0x62, 0xfa, 0x0b, 0x74, 0xf8, 0xdc, 0x61, 0x7c, - 0x14, 0x6c, 0x11, 0x9c, 0x2d, 0x41, 0x41, 0x0b, 0xb0, 0x58, 0x2c, 0x3e, 0x85, 0x72, 0x8d, 0xd1, - 0x6d, 0x57, 0xd2, 0xd7, 0x23, 0xbf, 0xd8, 0xbb, 0xb0, 0x98, 0x6e, 0x97, 0x58, 0x91, 0x94, 0x48, - 0xcc, 0x86, 0x91, 0x27, 0xdd, 0x00, 0xc1, 0x47, 0x08, 0x47, 0xba, 0x65, 0x4f, 0x38, 0xc7, 0x22, - 0x83, 0xe9, 0x55, 0x52, 0x4c, 0xef, 0x36, 0xd4, 0xe2, 0xc1, 0xb9, 0x33, 0x72, 0xaf, 0x06, 0x81, - 0xdb, 0x97, 0xe7, 0x1b, 0xe2, 0xc1, 0xf9, 0x21, 0x41, 0xd8, 0x43, 0x80, 0xe1, 0x68, 0x24, 0xcf, - 0x1e, 0x9a, 0x1b, 0x13, 0x52, 0xde, 0x3b, 0x3c, 0x24, 0x92, 0xb3, 0xab, 0xc3, 0xd1, 0x88, 0xfe, - 0x64, 0x1b, 0xd0, 0xcc, 0xcc, 0xc5, 0xb9, 0xa5, 0x82, 0xb1, 0x82, 0xd1, 0x83, 0x8c, 0xc3, 0xd9, - 0xe8, 0x99, 0xb0, 0xce, 0xaf, 0x01, 0xfb, 0x39, 0x33, 0x62, 0x8e, 0xa0, 0xaa, 0xc7, 0x67, 0x26, - 0x94, 0x60, 0x78, 0x65, 0x2d, 0x95, 0x50, 0xb2, 0xda, 0xef, 0x87, 0x82, 0x2f, 0xd2, 0x85, 0xa9, - 0x59, 0x3e, 0x18, 0x37, 0xe6, 0x2a, 0xf1, 0x7d, 0xeb, 0xcf, 0x73, 0x50, 0xa2, 0xec, 0x96, 0x37, - 0x61, 0x9e, 0xf0, 0x75, 0xb4, 0x8a, 0xf4, 0x10, 0xd1, 0xbd, 0x7b, 0x24, 0x03, 0x55, 0xc4, 0xb1, - 0x30, 0x32, 0xf3, 0xf2, 0x7a, 0xe7, 0x8d, 0xec, 0xbc, 0xdb, 0x50, 0xd5, 0x5d, 0x1b, 0xa4, 0x53, - 0x51, 0x3d, 0xb3, 0x57, 0xa1, 0x78, 0x16, 0x8c, 0x94, 0x2e, 0x0e, 0xc9, 0x4a, 0xda, 0x08, 0x4f, - 0xc6, 0x22, 0xfa, 0xa0, 0xc1, 0x4b, 0x1d, 0x52, 0x77, 0x82, 0x64, 0x30, 0x3d, 0xc7, 0xb9, 0x8c, - 0x39, 0x3e, 0x85, 0x79, 0xc1, 0x07, 0x0c, 0x4f, 0xed, 0xec, 0x4b, 0xf3, 0x2d, 0x21, 0xe1, 0xf5, - 0x06, 0xe3, 0x3e, 0x37, 0x2d, 0x21, 0x18, 0x3a, 0x21, 0xe1, 0x4a, 0x3d, 0xb0, 0x7e, 0x3f, 0x47, - 0xfc, 0x45, 0xb4, 0xcb, 0xee, 0x41, 0x51, 0xdc, 0x6f, 0x13, 0x96, 0x3a, 0x1d, 0xe7, 0x2a, 0xf0, - 0x6c, 0xc4, 0xc0, 0xfc, 0xd5, 0xf1, 0x30, 0xdd, 0x7a, 0xc3, 0xae, 0xf9, 0xe3, 0xa1, 0x36, 0x26, - 0x7c, 0x47, 0x4d, 0x6b, 0x42, 0x11, 0xa7, 0xd9, 0xeb, 0x63, 0xfa, 0xc0, 0x88, 0xc1, 0x28, 0xa6, - 0x6e, 0x4c, 0x25, 0x05, 0xf6, 0x4f, 0xb9, 0x11, 0x7b, 0xf1, 0x47, 0x79, 0x68, 0xa4, 0x46, 0x84, - 0x41, 0x28, 0xe2, 0x02, 0x20, 0x2b, 0xb0, 0xdc, 0x6f, 0x10, 0x20, 0x29, 0xa8, 0x1b, 0xeb, 0x94, - 0x4f, 0xad, 0x93, 0xf6, 0x49, 0x17, 0x4c, 0x9f, 0xf4, 0x23, 0xa8, 0x26, 0x19, 0x99, 0xe9, 0x21, - 0x89, 0xfe, 0x54, 0xb4, 0x6f, 0x82, 0x94, 0x78, 0xb1, 0x4b, 0xa6, 0x17, 0xfb, 0xfb, 0x86, 0xd3, - 0x73, 0x0e, 0x9b, 0xb1, 0xb2, 0x56, 0xf4, 0x97, 0x13, 0x14, 0xf1, 0x09, 0xd4, 0x8c, 0xc1, 0x9b, - 0xce, 0xcd, 0x5c, 0xca, 0xb9, 0xa9, 0xe3, 0xf2, 0xf3, 0x49, 0x5c, 0xbe, 0xf5, 0x5b, 0x79, 0x68, - 0x88, 0xf3, 0xe5, 0xf9, 0xa7, 0x87, 0xc1, 0xc0, 0xeb, 0xa1, 0x55, 0x58, 0x9f, 0x30, 0x29, 0x68, - 0xa9, 0x73, 0x26, 0x8f, 0x18, 0xc9, 0x59, 0x66, 0xfa, 0x11, 0x31, 0x69, 0x9d, 0x7e, 0x64, 0x41, - 0x43, 0x30, 0xc6, 0x63, 0x37, 0xe2, 0x46, 0xbe, 0xa8, 0x5d, 0x3b, 0xe1, 0x7c, 0xcd, 0x8d, 0x88, - 0x43, 0xbe, 0x0b, 0x8b, 0x02, 0x07, 0x33, 0x2f, 0x86, 0xde, 0x60, 0xe0, 0x11, 0x26, 0x99, 0x1a, - 0x5a, 0x27, 0x9c, 0xdb, 0x6e, 0xcc, 0xf7, 0x44, 0x81, 0x4c, 0x2f, 0xad, 0xf4, 0xbd, 0xc8, 0x3d, - 0x4e, 0x42, 0x85, 0xf4, 0x37, 0xfa, 0x72, 0xdc, 0x4b, 0xc3, 0x97, 0x43, 0x29, 0x58, 0xb5, 0xa1, - 0x7b, 0xa9, 0x7d, 0x39, 0x13, 0x94, 0x54, 0x9e, 0xa4, 0x24, 0xeb, 0xbf, 0xe6, 0xa1, 0x66, 0x90, - 0xe5, 0xcb, 0xdc, 0xae, 0xb7, 0xa6, 0xac, 0xf8, 0x55, 0xd3, 0x60, 0xff, 0x7a, 0xba, 0x4b, 0x74, - 0xf9, 0x52, 0x22, 0xab, 0x41, 0xc0, 0x37, 0xa1, 0x2a, 0x4e, 0xdd, 0x7b, 0x68, 0x14, 0x93, 0x69, - 0xd8, 0x08, 0x38, 0x1c, 0x1f, 0xab, 0xc2, 0xc7, 0x58, 0x58, 0x4a, 0x0a, 0x1f, 0x8b, 0xc2, 0xe7, - 0xc5, 0x07, 0x7e, 0x08, 0x75, 0xd9, 0x2a, 0xee, 0x29, 0x4e, 0x37, 0x39, 0xf5, 0xa9, 0xfd, 0xb6, - 0x6b, 0xd4, 0x1d, 0x6d, 0xbe, 0xac, 0xf8, 0x58, 0x55, 0xac, 0xbc, 0xa8, 0xe2, 0x63, 0xfa, 0xb0, - 0xb6, 0x74, 0xc8, 0x25, 0x86, 0x1b, 0x28, 0x3e, 0xf6, 0x10, 0x16, 0x15, 0xbb, 0x1a, 0xfb, 0xae, - 0xef, 0x07, 0x63, 0xbf, 0xc7, 0x55, 0xc0, 0x3e, 0x93, 0x45, 0x4f, 0x93, 0x12, 0xab, 0xaf, 0x33, - 0xba, 0x28, 0x6c, 0xe1, 0x3e, 0x94, 0x48, 0x2e, 0x27, 0xe1, 0x23, 0x9b, 0x71, 0x11, 0x0a, 0xbb, - 0x07, 0x25, 0x12, 0xcf, 0xf3, 0x33, 0x99, 0x0d, 0x21, 0x58, 0x0f, 0x60, 0x1e, 0x45, 0x4c, 0x83, - 0xe3, 0x3e, 0x4f, 0x2a, 0xb1, 0x96, 0x80, 0xed, 0xd3, 0x21, 0x32, 0xc3, 0x69, 0xfe, 0x67, 0x01, - 0x6a, 0x06, 0x58, 0xb0, 0x45, 0x0c, 0xc0, 0x70, 0xfa, 0x9e, 0x3b, 0xe4, 0xca, 0xf7, 0xd0, 0xb0, - 0x1b, 0x08, 0xdd, 0x90, 0x40, 0x71, 0x29, 0xb8, 0xe7, 0xa7, 0x4e, 0x30, 0x8e, 0x9d, 0x3e, 0x3f, - 0x0d, 0x39, 0x97, 0xc2, 0x52, 0xdd, 0x3d, 0x3f, 0x3d, 0x18, 0xc7, 0x1b, 0x08, 0x13, 0x58, 0x82, - 0xa8, 0x0d, 0x2c, 0x19, 0x33, 0x30, 0x74, 0x2f, 0x13, 0x2c, 0x19, 0xb8, 0x42, 0x4b, 0x54, 0xd4, - 0x81, 0x2b, 0xa4, 0xb6, 0x4c, 0x72, 0xf2, 0xd2, 0x34, 0x27, 0x7f, 0x1f, 0x96, 0x89, 0x93, 0x4b, - 0x1e, 0xe1, 0x4c, 0x90, 0xd4, 0x12, 0x96, 0xca, 0x49, 0x1a, 0xf2, 0x57, 0x4b, 0xcc, 0x40, 0x9d, - 0x8f, 0xc8, 0xfb, 0x29, 0x9d, 0xa8, 0x9c, 0x2d, 0x66, 0x26, 0x1b, 0xef, 0x7a, 0x3f, 0xe5, 0x02, - 0x13, 0x1d, 0xa3, 0x26, 0xa6, 0x0c, 0x43, 0x1d, 0x7a, 0xfe, 0x24, 0xa6, 0x7b, 0x99, 0xc6, 0xac, - 0x4a, 0x4c, 0xf7, 0xd2, 0xc4, 0xfc, 0x00, 0x56, 0x86, 0xbc, 0xef, 0xb9, 0xe9, 0x66, 0x9d, 0x44, - 0x82, 0x58, 0xa2, 0x62, 0xa3, 0x4e, 0x97, 0x34, 0x48, 0xb1, 0x1a, 0x3f, 0x0d, 0x86, 0xc7, 0x1e, - 0x5d, 0x9e, 0xe4, 0xaa, 0x2d, 0xda, 0x4d, 0x7f, 0x3c, 0xfc, 0x11, 0x82, 0x45, 0x95, 0xc8, 0x6a, - 0x40, 0xad, 0x1b, 0x07, 0x23, 0xb5, 0xcd, 0x4d, 0xa8, 0xd3, 0xa7, 0x4c, 0xc7, 0xb8, 0x09, 0x37, - 0x90, 0x36, 0x8f, 0x82, 0x51, 0x30, 0x08, 0x4e, 0xaf, 0x52, 0x06, 0xa5, 0xff, 0x9e, 0x83, 0xc5, - 0x54, 0xa9, 0x3c, 0xe7, 0xef, 0xd3, 0xc1, 0xd2, 0x31, 0xf5, 0x44, 0xce, 0x0b, 0xc6, 0xe5, 0x43, - 0x88, 0x74, 0xaa, 0x54, 0x9c, 0xfd, 0x6a, 0x92, 0x0b, 0xaa, 0x2a, 0x12, 0x6d, 0xb7, 0xa7, 0x69, - 0x5b, 0xd6, 0x57, 0x59, 0xa2, 0xaa, 0x89, 0xbf, 0x2a, 0x43, 0x85, 0xfb, 0x72, 0xca, 0x85, 0x74, - 0x30, 0xa4, 0x69, 0x7c, 0x52, 0x23, 0x48, 0x2c, 0x52, 0x91, 0xf5, 0xaf, 0x72, 0x00, 0xc9, 0xe8, - 0x30, 0x1c, 0x53, 0x5f, 0xa0, 0xf4, 0xae, 0x8a, 0x71, 0x59, 0xbe, 0x06, 0x75, 0x1d, 0x31, 0x96, - 0x5c, 0xc9, 0x35, 0x05, 0x13, 0xf7, 0xf2, 0x5d, 0x98, 0x3f, 0x1d, 0x04, 0xc7, 0x28, 0x3a, 0xc9, - 0x0b, 0x94, 0x92, 0x52, 0x9a, 0x04, 0x56, 0xd7, 0x62, 0x72, 0x81, 0x17, 0x33, 0x83, 0xca, 0xcc, - 0xeb, 0xd8, 0xfa, 0xed, 0xbc, 0x0e, 0x9d, 0x49, 0x56, 0xe2, 0xf9, 0x7a, 0xc6, 0xb7, 0xf1, 0xc0, - 0x3e, 0xcf, 0xf3, 0xf0, 0x09, 0x34, 0x43, 0xe2, 0x8e, 0x8a, 0x75, 0x16, 0x9f, 0xc3, 0x3a, 0x1b, - 0x61, 0xea, 0xca, 0x7d, 0x0b, 0x5a, 0x6e, 0xff, 0x9c, 0x87, 0xb1, 0x87, 0xc6, 0x5a, 0x14, 0xd4, - 0x64, 0xb0, 0x8a, 0x01, 0x47, 0x89, 0xe8, 0x2e, 0xcc, 0xcb, 0x14, 0x21, 0x8d, 0x29, 0x1f, 0x1d, - 0x48, 0xc0, 0x02, 0xd1, 0xfa, 0xb7, 0x2a, 0x56, 0x27, 0xbd, 0xbb, 0xcf, 0x5f, 0x15, 0x73, 0x86, - 0xf9, 0x69, 0xdf, 0x8a, 0x24, 0x24, 0x69, 0x03, 0x96, 0xfc, 0x88, 0x80, 0xd2, 0x02, 0x9c, 0x5e, - 0xd6, 0xe2, 0xcb, 0x2c, 0xab, 0xf5, 0x27, 0x39, 0x28, 0x6f, 0x07, 0x23, 0xa1, 0x97, 0x0b, 0x79, - 0x0e, 0x8f, 0x89, 0x4e, 0xcf, 0x9b, 0x13, 0x9f, 0x3b, 0xfd, 0xe7, 0x87, 0xe5, 0x67, 0xca, 0x1b, - 0x8d, 0xb4, 0xbc, 0xf1, 0x7d, 0xb8, 0x89, 0xde, 0x88, 0x30, 0x18, 0x05, 0xa1, 0x38, 0xaa, 0xee, - 0x80, 0xe4, 0x8e, 0xc0, 0x8f, 0xcf, 0x14, 0xef, 0xbc, 0x71, 0xc2, 0xf9, 0xa1, 0x81, 0xb1, 0xa7, - 0x11, 0x30, 0xd7, 0x64, 0x10, 0x9f, 0x3b, 0xa4, 0x2a, 0x4a, 0xc1, 0x88, 0x38, 0xea, 0xbc, 0x28, - 0xd8, 0x44, 0x38, 0x8a, 0x46, 0xd6, 0x47, 0x50, 0xd5, 0x56, 0x07, 0xf6, 0x36, 0x54, 0xcf, 0x82, - 0x91, 0x34, 0x4d, 0xe4, 0x52, 0xa9, 0x0b, 0x72, 0xd6, 0x76, 0xe5, 0x8c, 0xfe, 0x88, 0xac, 0x9f, - 0x95, 0xa1, 0xbc, 0xe3, 0x9f, 0x07, 0x5e, 0x0f, 0xa3, 0x7d, 0x86, 0x7c, 0x18, 0xa8, 0x3c, 0x45, - 0xf1, 0x37, 0x7a, 0xf4, 0x93, 0xa7, 0x03, 0x0a, 0xd2, 0xa3, 0xaf, 0x1f, 0x0d, 0xb8, 0x0e, 0x73, - 0xa1, 0x99, 0xfb, 0x5f, 0x0a, 0x31, 0xfe, 0x50, 0x2b, 0x6d, 0x25, 0x23, 0xcf, 0x53, 0xb4, 0x45, - 0x39, 0xe9, 0xb8, 0x64, 0x94, 0x7b, 0x52, 0x45, 0x08, 0x2e, 0xd8, 0x2b, 0x50, 0x96, 0x99, 0x02, - 0x14, 0x77, 0x4d, 0x01, 0x83, 0x12, 0x84, 0xd4, 0x10, 0x72, 0xf2, 0x26, 0x69, 0x89, 0x4a, 0xe8, - 0xe9, 0x12, 0xb8, 0x21, 0x68, 0xed, 0x36, 0xd4, 0x08, 0x9f, 0x50, 0x2a, 0x32, 0x3e, 0x07, 0x41, - 0x88, 0x90, 0xf1, 0x84, 0x46, 0x35, 0xf3, 0x09, 0x0d, 0x0c, 0xe7, 0xd2, 0x5c, 0x96, 0xa6, 0x08, - 0xf4, 0x70, 0x82, 0x01, 0x57, 0xef, 0xc7, 0x48, 0xe5, 0x9e, 0xd2, 0xa8, 0x94, 0x72, 0xff, 0x3a, - 0x34, 0x4e, 0xdc, 0xc1, 0xe0, 0xd8, 0xed, 0x3d, 0x23, 0x9d, 0xb4, 0x4e, 0x66, 0x38, 0x05, 0x44, - 0xa5, 0xf4, 0x36, 0xd4, 0x8c, 0x5d, 0xc6, 0xe0, 0x9b, 0xa2, 0x0d, 0xc9, 0xfe, 0x4e, 0x9a, 0x9a, - 0x9a, 0x2f, 0x61, 0x6a, 0x32, 0x82, 0x90, 0xe6, 0xd3, 0x41, 0x48, 0x37, 0x91, 0x9b, 0xca, 0x40, - 0x95, 0x16, 0x65, 0xe9, 0xbb, 0xfd, 0x3e, 0x06, 0xaa, 0xd0, 0x1b, 0x58, 0xb8, 0x78, 0x54, 0xbe, - 0x40, 0x42, 0x2d, 0xc1, 0x08, 0xe5, 0x16, 0xd9, 0x4b, 0x47, 0xae, 0xd7, 0xc7, 0xa0, 0x4f, 0x52, - 0x63, 0xcb, 0xee, 0x30, 0x3e, 0x74, 0xbd, 0x3e, 0xbb, 0x03, 0x75, 0x55, 0x8c, 0xb7, 0xe3, 0x22, - 0xad, 0xbf, 0x2c, 0x16, 0x77, 0xa2, 0x05, 0x0d, 0x8d, 0x31, 0x4c, 0x72, 0xa1, 0x6a, 0x12, 0x05, - 0xe9, 0xe0, 0x3d, 0x74, 0xfe, 0xc7, 0x1c, 0x33, 0x9e, 0x9a, 0x8f, 0x6f, 0xca, 0xb9, 0x4a, 0x2a, - 0x55, 0xff, 0x63, 0xa4, 0x83, 0x4d, 0x98, 0x42, 0x10, 0x23, 0x17, 0xcd, 0x72, 0x4a, 0x10, 0x93, - 0xa8, 0xe8, 0xa2, 0x21, 0x04, 0xf6, 0x91, 0xa1, 0x48, 0xb5, 0x11, 0xf9, 0x95, 0x89, 0xf6, 0x67, - 0xa8, 0x50, 0x82, 0x7a, 0xbd, 0x48, 0xdc, 0x32, 0x11, 0xf7, 0xfb, 0x98, 0x00, 0x55, 0xb1, 0xab, - 0x5e, 0xf4, 0x84, 0x00, 0xbf, 0x58, 0x0d, 0x6b, 0x15, 0xea, 0xe6, 0x34, 0x59, 0x05, 0x8a, 0x07, - 0x87, 0x9b, 0xfb, 0xad, 0x6b, 0xac, 0x06, 0xe5, 0xee, 0xe6, 0xd1, 0xd1, 0xee, 0xe6, 0x46, 0x2b, - 0xc7, 0xea, 0x50, 0xd1, 0x69, 0x1c, 0x79, 0xf1, 0xb5, 0xba, 0xbe, 0xbe, 0x79, 0x78, 0xb4, 0xb9, - 0xd1, 0x2a, 0xfc, 0xa0, 0x58, 0xc9, 0xb7, 0x0a, 0xd6, 0x9f, 0x15, 0xa0, 0x66, 0xac, 0xc2, 0xf3, - 0x99, 0xf1, 0x2d, 0x00, 0x54, 0x69, 0x92, 0x38, 0xa6, 0xa2, 0x5d, 0x15, 0x10, 0xda, 0x7c, 0xd3, - 0x58, 0x5e, 0xa0, 0xe7, 0x1f, 0x94, 0xb1, 0xfc, 0x75, 0x68, 0xd0, 0x4b, 0x0a, 0xa6, 0xbb, 0xae, - 0x64, 0xd7, 0x09, 0x28, 0x59, 0x35, 0xe6, 0x81, 0x21, 0x12, 0x66, 0x08, 0xc8, 0xbc, 0x6a, 0x02, - 0x61, 0x8e, 0x00, 0x26, 0x78, 0x44, 0xc1, 0xe0, 0x9c, 0x13, 0x06, 0x49, 0x84, 0x35, 0x09, 0x3b, - 0x92, 0x89, 0x68, 0x92, 0x1f, 0x1a, 0x89, 0x48, 0x25, 0xbb, 0x4e, 0x40, 0xd9, 0xd1, 0xbb, 0x8a, - 0x80, 0x2a, 0x48, 0x40, 0x2b, 0xd3, 0xd4, 0x90, 0x22, 0x9e, 0xdd, 0x29, 0x7b, 0x56, 0x15, 0x09, - 0xe3, 0x3b, 0xd3, 0xf5, 0x5e, 0x6c, 0xd7, 0x62, 0x6f, 0x03, 0x1b, 0x8e, 0x46, 0x4e, 0x86, 0xa5, - 0xa9, 0x68, 0xcf, 0x0f, 0x47, 0xa3, 0x23, 0xc3, 0x10, 0xf3, 0x0b, 0x30, 0x82, 0x7d, 0x09, 0x6c, - 0x55, 0x1c, 0x60, 0x1c, 0xa2, 0x36, 0xa1, 0x26, 0x6c, 0x39, 0x67, 0xb2, 0xe5, 0x0c, 0xee, 0x97, - 0xcf, 0xe4, 0x7e, 0xcf, 0xe3, 0x13, 0xd6, 0x16, 0xd4, 0x0e, 0x8d, 0x77, 0x5a, 0xee, 0x88, 0x1b, - 0x42, 0xbd, 0xd0, 0x42, 0x77, 0x07, 0x19, 0xb7, 0x42, 0xf9, 0x30, 0x8b, 0x31, 0x9a, 0xbc, 0x31, - 0x1a, 0xeb, 0x5f, 0xe6, 0x28, 0x07, 0x5e, 0x0f, 0x3e, 0x79, 0x1a, 0x46, 0xf9, 0x81, 0x92, 0x7c, - 0xc1, 0x9a, 0xf2, 0xff, 0xc8, 0x54, 0x3f, 0x1c, 0x9a, 0x13, 0x9c, 0x9c, 0x44, 0x5c, 0x65, 0xbe, - 0xd4, 0x10, 0x76, 0x80, 0x20, 0x25, 0x7c, 0x0b, 0x09, 0xdf, 0xa3, 0xf6, 0x23, 0x99, 0x01, 0x23, - 0x84, 0xef, 0x3d, 0xf7, 0x52, 0xf6, 0x1a, 0x09, 0x11, 0x44, 0x1a, 0xaa, 0x55, 0xbe, 0x8f, 0xfe, - 0xb6, 0xfe, 0x99, 0x4c, 0x69, 0x9c, 0x5c, 0xdf, 0xfb, 0x50, 0xd1, 0xad, 0xa6, 0x6f, 0x58, 0x85, - 0xa9, 0xcb, 0xc5, 0x3d, 0x8e, 0x5a, 0x79, 0x6a, 0xc4, 0x74, 0xb8, 0xd0, 0xd9, 0xb0, 0x63, 0x8c, - 0xfa, 0x1d, 0x60, 0x27, 0x5e, 0x38, 0x89, 0x4c, 0x87, 0xad, 0x85, 0x25, 0x06, 0xb6, 0xf5, 0x14, - 0x16, 0x15, 0x97, 0x30, 0x34, 0x82, 0xf4, 0xe6, 0xe5, 0x5e, 0xc0, 0xe4, 0xf3, 0x53, 0x4c, 0xde, - 0xfa, 0xc3, 0x22, 0x94, 0xd5, 0x9b, 0x47, 0x59, 0xef, 0xf4, 0x54, 0xd3, 0xef, 0xf4, 0xb4, 0x53, - 0x6f, 0x3a, 0xe0, 0xd6, 0xcb, 0xfb, 0xfe, 0xee, 0xe4, 0x95, 0x6d, 0x18, 0xcd, 0x53, 0xd7, 0xf6, - 0x32, 0x14, 0x47, 0x6e, 0x7c, 0x86, 0x06, 0x32, 0x22, 0x1e, 0xfc, 0x56, 0xc6, 0xf4, 0x52, 0xda, - 0x98, 0x9e, 0xf5, 0xa6, 0x11, 0x89, 0xa4, 0x53, 0x6f, 0x1a, 0xdd, 0x04, 0x92, 0x2f, 0x8c, 0x78, - 0x98, 0x0a, 0x02, 0xc4, 0x5d, 0x94, 0x16, 0x47, 0x2a, 0x93, 0xe2, 0xc8, 0x4b, 0x8b, 0x0a, 0xef, - 0xc3, 0x1c, 0xe5, 0x03, 0xcb, 0xbc, 0x26, 0x75, 0xa1, 0xc8, 0x35, 0x54, 0xff, 0x53, 0x10, 0xac, - 0x2d, 0x71, 0xcd, 0x07, 0x42, 0x6a, 0xa9, 0x07, 0x42, 0x4c, 0x23, 0x7f, 0x3d, 0x6d, 0xe4, 0xbf, - 0x07, 0x2d, 0xbd, 0xa0, 0x68, 0x32, 0xf3, 0x23, 0x99, 0xd1, 0xd1, 0x54, 0x70, 0xc1, 0x25, 0xf7, - 0xa3, 0xe4, 0x42, 0x6c, 0xa6, 0x2e, 0x44, 0xc1, 0xc3, 0x56, 0xe3, 0x98, 0x0f, 0x47, 0xb1, 0xbc, - 0x10, 0x31, 0xe6, 0xdb, 0x1c, 0x60, 0x3a, 0xe3, 0xaf, 0x01, 0xd5, 0x9d, 0x7d, 0x67, 0x6b, 0x77, - 0xe7, 0xd3, 0xed, 0xa3, 0x56, 0x4e, 0x7c, 0x76, 0x9f, 0xae, 0xaf, 0x6f, 0x6e, 0x6e, 0xe0, 0x8d, - 0x03, 0x30, 0xb7, 0xb5, 0xba, 0x23, 0x6e, 0x9f, 0x82, 0xf5, 0x97, 0x39, 0xa8, 0x19, 0xcd, 0xb3, - 0x0f, 0xf4, 0xaa, 0xd0, 0x1b, 0x12, 0xb7, 0xa6, 0x87, 0xf0, 0x40, 0xb1, 0x62, 0x63, 0x59, 0xf4, - 0x0b, 0x4e, 0xf9, 0x99, 0x2f, 0x38, 0xb1, 0x37, 0x61, 0xde, 0xa5, 0x16, 0xf4, 0x2a, 0x48, 0x73, - 0xb0, 0x04, 0xcb, 0x45, 0xc0, 0x28, 0xb0, 0xe4, 0x3e, 0x11, 0x78, 0x45, 0x15, 0x78, 0xa5, 0xaf, - 0x94, 0xfd, 0xc8, 0xfa, 0x1e, 0x40, 0x32, 0x92, 0xf4, 0x94, 0xaf, 0xa5, 0xa7, 0x9c, 0x33, 0xa6, - 0x9c, 0xb7, 0x36, 0x88, 0x39, 0xc8, 0xe5, 0xd3, 0xfe, 0xe7, 0x77, 0x41, 0xd9, 0x99, 0x1c, 0x8c, - 0xae, 0x1c, 0x0d, 0x78, 0xac, 0x32, 0x1e, 0x17, 0x64, 0xc9, 0x8e, 0x2e, 0x50, 0x09, 0xc8, 0x49, - 0x2b, 0x09, 0x8f, 0x91, 0x84, 0x36, 0xc9, 0x63, 0x24, 0xaa, 0xad, 0xcb, 0xad, 0x0e, 0xb4, 0x37, - 0xb8, 0x68, 0x6d, 0x75, 0x30, 0x98, 0x18, 0x8e, 0x75, 0x13, 0x6e, 0x64, 0x94, 0x49, 0xd3, 0xc2, - 0x67, 0x70, 0x7d, 0x95, 0x92, 0x1b, 0x7f, 0x51, 0x19, 0x16, 0x56, 0x1b, 0x96, 0x27, 0x9b, 0x94, - 0x9d, 0x6d, 0xc1, 0xc2, 0x06, 0x3f, 0x1e, 0x9f, 0xee, 0xf2, 0xf3, 0xa4, 0x23, 0x06, 0xc5, 0xe8, - 0x2c, 0xb8, 0x90, 0xeb, 0x83, 0x7f, 0x8b, 0x93, 0x39, 0x10, 0x38, 0x4e, 0x34, 0xe2, 0x3d, 0x65, - 0xe7, 0x44, 0x48, 0x77, 0xc4, 0x7b, 0xd6, 0x07, 0xc0, 0xcc, 0x76, 0xe4, 0x7a, 0x09, 0xd9, 0x7f, - 0x7c, 0xec, 0x44, 0x57, 0x51, 0xcc, 0x87, 0xea, 0xe1, 0x11, 0x88, 0xc6, 0xc7, 0x5d, 0x82, 0x58, - 0x77, 0xa1, 0x7e, 0xe8, 0x5e, 0xd9, 0xfc, 0x4b, 0x99, 0x3b, 0xb0, 0x02, 0xe5, 0x91, 0x7b, 0x25, - 0x0e, 0xb7, 0x76, 0x79, 0x60, 0xb1, 0xf5, 0x07, 0x45, 0x98, 0x23, 0x4c, 0x76, 0x87, 0xde, 0x06, - 0xf4, 0x7c, 0x3c, 0x5c, 0x8a, 0xfd, 0x19, 0xa0, 0x29, 0x0e, 0x99, 0x9f, 0xe6, 0x90, 0xd2, 0x2c, - 0xa6, 0xde, 0x44, 0x50, 0xc6, 0x69, 0x7f, 0x3c, 0x54, 0x0f, 0x21, 0xb0, 0x57, 0xa0, 0x9a, 0x24, - 0x69, 0x15, 0x93, 0xb7, 0x1f, 0x29, 0x35, 0x2b, 0xed, 0x3e, 0x4c, 0x34, 0x0c, 0x1a, 0x9d, 0x62, - 0xfc, 0x92, 0x09, 0x9a, 0xa0, 0x4c, 0x35, 0xa6, 0xac, 0xb2, 0x52, 0xd2, 0x6a, 0xcc, 0x94, 0xba, - 0x52, 0x79, 0xb1, 0xba, 0x42, 0xf6, 0xb2, 0xe7, 0xa8, 0x2b, 0xf0, 0x12, 0xea, 0xca, 0x4b, 0xb8, - 0xee, 0x6e, 0x40, 0x05, 0x6f, 0x73, 0x83, 0x27, 0x8a, 0x5b, 0x5c, 0xf0, 0xc4, 0x0f, 0x0d, 0x81, - 0x9e, 0xe2, 0x06, 0x6e, 0x26, 0xc7, 0xc4, 0xe6, 0x5f, 0xfe, 0x72, 0x5c, 0x22, 0x5f, 0x40, 0x59, - 0x42, 0x05, 0x41, 0xfb, 0xee, 0x50, 0x3d, 0x2b, 0x83, 0x7f, 0x8b, 0x65, 0xc3, 0xb7, 0x30, 0xbe, - 0x1c, 0x7b, 0x21, 0xef, 0xab, 0xc7, 0x0b, 0x3c, 0x3c, 0xa3, 0x02, 0x22, 0x26, 0x28, 0x94, 0x0b, - 0x3f, 0xb8, 0xf0, 0x65, 0xea, 0x72, 0xd9, 0x8b, 0x9e, 0x88, 0x4f, 0x8b, 0x41, 0x0b, 0x1f, 0x96, - 0x1a, 0x05, 0xa1, 0xba, 0x72, 0xac, 0xff, 0x98, 0x83, 0x96, 0x3c, 0x5d, 0xba, 0xcc, 0x94, 0xed, - 0x4b, 0x33, 0x1e, 0x12, 0xf0, 0x53, 0xef, 0x10, 0x18, 0x96, 0x26, 0x0b, 0x1a, 0x68, 0xcc, 0xd0, - 0x37, 0x0f, 0x19, 0x63, 0x6a, 0x02, 0xb8, 0x25, 0x6f, 0x9f, 0x57, 0xa1, 0xa6, 0xc2, 0x2b, 0x87, - 0xde, 0x40, 0x3d, 0xf0, 0x4a, 0xf1, 0x95, 0x7b, 0xde, 0x40, 0x5d, 0x5c, 0xa1, 0x2b, 0xf3, 0xa3, - 0x72, 0x78, 0x71, 0xd9, 0x6e, 0xcc, 0xad, 0xff, 0x9c, 0x83, 0x05, 0x63, 0x12, 0xf2, 0xc4, 0x7e, - 0x0c, 0x75, 0xfd, 0x96, 0x1b, 0xd7, 0x92, 0xd4, 0x4a, 0x9a, 0xc5, 0x24, 0xd5, 0x6a, 0x3d, 0x0d, - 0x89, 0xc4, 0x60, 0xfa, 0xee, 0x15, 0x8e, 0x37, 0x1a, 0x0f, 0x95, 0xb2, 0xd2, 0x77, 0xaf, 0xb6, - 0x38, 0xef, 0x8e, 0x87, 0x42, 0x15, 0xbd, 0xe0, 0xfc, 0x99, 0x46, 0x20, 0x19, 0x0a, 0x04, 0x4c, - 0x62, 0x58, 0xd0, 0x18, 0x06, 0x7e, 0x7c, 0xa6, 0x51, 0xa4, 0x14, 0x89, 0x40, 0xc2, 0xb1, 0xfe, - 0x47, 0x1e, 0x16, 0xc9, 0x64, 0x26, 0x4d, 0x95, 0x92, 0x69, 0xb5, 0x61, 0x8e, 0xac, 0x87, 0xc4, - 0xb6, 0xb6, 0xaf, 0xd9, 0xf2, 0x9b, 0xbd, 0xff, 0x92, 0x66, 0x3e, 0x95, 0x82, 0x35, 0x63, 0xf9, - 0x0b, 0xd3, 0xcb, 0x3f, 0x7b, 0x79, 0xb3, 0x3c, 0x68, 0xa5, 0x2c, 0x0f, 0xda, 0xcb, 0xf8, 0xad, - 0xa6, 0xf2, 0x94, 0xca, 0x12, 0xc7, 0xc8, 0x53, 0xfa, 0x00, 0x56, 0x52, 0x38, 0xc8, 0xa7, 0xbd, - 0x13, 0x8f, 0xab, 0x9c, 0xf0, 0x25, 0x03, 0xbb, 0xab, 0xca, 0xd6, 0xca, 0x50, 0x8a, 0x7a, 0xc1, - 0x88, 0x5b, 0xcb, 0xb0, 0x94, 0x5e, 0x55, 0x79, 0x41, 0xfc, 0x5e, 0x0e, 0xda, 0x32, 0xde, 0xc1, - 0xf3, 0x4f, 0xb7, 0xbd, 0x28, 0x0e, 0x42, 0xfd, 0xe6, 0xd9, 0x2d, 0x80, 0x28, 0x76, 0x43, 0xa9, - 0x3d, 0x92, 0x5c, 0x5b, 0x45, 0x08, 0x6a, 0x86, 0x37, 0xa0, 0xc2, 0xfd, 0x3e, 0x15, 0x12, 0x35, - 0x94, 0xb9, 0xdf, 0x57, 0x7a, 0xe5, 0x94, 0x3c, 0xdd, 0x48, 0xab, 0x0b, 0x32, 0x61, 0x52, 0xac, - 0x0e, 0x3f, 0xc7, 0x2b, 0xb7, 0xa8, 0x13, 0x26, 0xf7, 0xdc, 0x4b, 0x8c, 0x1e, 0x8c, 0xac, 0x7f, - 0x9c, 0x87, 0xf9, 0x64, 0x7c, 0x94, 0x6d, 0x9d, 0xe2, 0xdc, 0x72, 0x54, 0x09, 0xe7, 0xbe, 0x23, - 0xc9, 0xc1, 0x13, 0xf2, 0xb8, 0x61, 0x48, 0xac, 0xd0, 0xb1, 0xdc, 0xf1, 0x99, 0x05, 0x35, 0x85, - 0x11, 0x8c, 0x63, 0xe3, 0xe9, 0xa1, 0x2a, 0xa1, 0x1c, 0x8c, 0x63, 0xa1, 0x40, 0x09, 0x4d, 0xd2, - 0xf3, 0xa5, 0x0a, 0x53, 0x72, 0x87, 0xf1, 0x0e, 0xbe, 0x68, 0x2c, 0xc0, 0xa2, 0x1a, 0x6d, 0xa4, - 0xc0, 0x12, 0xf8, 0x2d, 0x92, 0x9b, 0x69, 0xe7, 0x50, 0x66, 0x36, 0x85, 0x4a, 0x7a, 0xdc, 0x51, - 0x0b, 0x95, 0xaf, 0x42, 0x8d, 0x1a, 0x4f, 0xd2, 0xd2, 0x8a, 0x76, 0x15, 0x7b, 0xc0, 0x72, 0x69, - 0xd4, 0x09, 0xc6, 0x29, 0x55, 0x16, 0xa8, 0x2b, 0x0c, 0x27, 0xf8, 0x07, 0x39, 0xb8, 0x91, 0xb1, - 0x6d, 0xf2, 0x94, 0xaf, 0xc3, 0xc2, 0x89, 0x2e, 0x54, 0xab, 0x4b, 0x47, 0x7d, 0x59, 0x31, 0xd4, - 0xf4, 0x9a, 0xda, 0xad, 0x93, 0x34, 0x20, 0x51, 0xa2, 0x68, 0x07, 0x53, 0x99, 0x87, 0xa8, 0x44, - 0xd1, 0x36, 0x92, 0xfe, 0x72, 0x08, 0x9d, 0xcd, 0x4b, 0xc1, 0x31, 0xd6, 0xcd, 0x37, 0xb8, 0x15, - 0x19, 0x3d, 0x9e, 0x62, 0x84, 0x2f, 0x36, 0x18, 0xf7, 0x29, 0xc1, 0x4a, 0xb7, 0xf5, 0x6d, 0x1a, - 0xc1, 0xab, 0x53, 0xd4, 0xa1, 0x37, 0xc4, 0x55, 0xf6, 0x63, 0x4f, 0xbf, 0x1d, 0x6e, 0x45, 0x30, - 0xbf, 0x37, 0x1e, 0xc4, 0x5e, 0xf2, 0x9c, 0x38, 0x7b, 0x5f, 0xd6, 0xc1, 0x7e, 0xd4, 0xaa, 0x65, - 0x76, 0x04, 0xba, 0x23, 0x5c, 0xac, 0xa1, 0x68, 0xc8, 0x99, 0xee, 0x6f, 0x7e, 0x98, 0xee, 0xc1, - 0xba, 0x01, 0x2b, 0xc9, 0x17, 0x2d, 0x9b, 0xba, 0x64, 0xfe, 0x45, 0x8e, 0x42, 0x95, 0xd3, 0x4f, - 0x9b, 0xb3, 0x4d, 0x58, 0x8c, 0x3c, 0xff, 0x74, 0xc0, 0xcd, 0xe6, 0x23, 0xb9, 0x08, 0xd7, 0xd3, - 0x63, 0x93, 0xcf, 0x9f, 0xdb, 0x0b, 0x54, 0x23, 0x69, 0x2d, 0x62, 0x6b, 0xb3, 0x06, 0x99, 0x90, - 0xc5, 0xc4, 0x6a, 0x4c, 0x0f, 0x7e, 0x07, 0x9a, 0xe9, 0x8e, 0xd8, 0x87, 0x32, 0xb9, 0x30, 0x19, - 0x55, 0x61, 0x22, 0x4f, 0x2c, 0x21, 0x88, 0x5a, 0xb2, 0xf6, 0x91, 0xf5, 0x0f, 0x73, 0xd0, 0xb6, - 0xb9, 0xa0, 0x5c, 0x63, 0x94, 0x8a, 0x66, 0x3e, 0x9e, 0x6a, 0x75, 0xf6, 0x5c, 0x55, 0xce, 0xa2, - 0x1a, 0xd1, 0x3b, 0x33, 0x37, 0x63, 0xfb, 0xda, 0xd4, 0x8c, 0xd6, 0x2a, 0x30, 0x47, 0x28, 0xd6, - 0x0a, 0x5c, 0x97, 0xe3, 0x51, 0x63, 0x49, 0xbc, 0x81, 0xa9, 0x1e, 0x53, 0xde, 0xc0, 0x0e, 0xb4, - 0xe9, 0xe9, 0x3a, 0x73, 0x12, 0xb2, 0xe2, 0x06, 0xb0, 0x3d, 0xb7, 0xe7, 0x86, 0x41, 0xe0, 0x1f, - 0xf2, 0x50, 0x06, 0x7e, 0xa2, 0x6c, 0x89, 0xce, 0x32, 0x25, 0x04, 0xd3, 0x97, 0x7a, 0x70, 0x2d, - 0xf0, 0x55, 0x9c, 0x0b, 0x7d, 0x59, 0x36, 0x2c, 0xae, 0xb9, 0xcf, 0xb8, 0x6a, 0x49, 0x2d, 0xd1, - 0x27, 0x50, 0x1b, 0xe9, 0x46, 0xd5, 0xba, 0xab, 0x0c, 0xe4, 0xe9, 0x6e, 0x6d, 0x13, 0xdb, 0x7a, - 0x0c, 0x4b, 0xe9, 0x36, 0x25, 0xeb, 0xe8, 0x40, 0x65, 0x28, 0x61, 0x72, 0x74, 0xfa, 0xfb, 0xfe, - 0xd7, 0x50, 0x33, 0x9e, 0x23, 0x64, 0x2b, 0xb0, 0xf8, 0xf9, 0xce, 0xd1, 0xfe, 0x66, 0xb7, 0xeb, - 0x1c, 0x3e, 0x5d, 0x7b, 0xb2, 0xf9, 0x85, 0xb3, 0xbd, 0xda, 0xdd, 0x6e, 0x5d, 0x63, 0xcb, 0xc0, - 0xf6, 0x37, 0xbb, 0x47, 0x9b, 0x1b, 0x29, 0x78, 0x8e, 0xbd, 0x0a, 0x9d, 0xa7, 0xfb, 0x4f, 0xbb, - 0x9b, 0x1b, 0x4e, 0x56, 0xbd, 0x3c, 0xbb, 0x05, 0x37, 0x64, 0x79, 0x46, 0xf5, 0xc2, 0xfd, 0x4f, - 0xa0, 0x35, 0x69, 0x4f, 0x4c, 0x19, 0x60, 0x9f, 0x67, 0xa9, 0xbd, 0xff, 0x6f, 0x0a, 0x00, 0x49, - 0xc0, 0x27, 0x6b, 0xc3, 0xd2, 0xc6, 0xea, 0xd1, 0xea, 0xee, 0x81, 0x18, 0x84, 0x7d, 0x70, 0xb4, - 0xb9, 0x7e, 0xe4, 0xd8, 0x9b, 0x9f, 0xb5, 0xae, 0x65, 0x96, 0x1c, 0x1c, 0x0a, 0x4d, 0x7c, 0x05, - 0x16, 0x77, 0xf6, 0x77, 0x8e, 0x76, 0x56, 0x77, 0x1d, 0xfb, 0xe0, 0xe9, 0xce, 0xfe, 0xa7, 0xf4, - 0xe0, 0x48, 0x81, 0xdd, 0x86, 0x9b, 0x4f, 0x0f, 0xb7, 0xec, 0x83, 0xfd, 0x23, 0xa7, 0xbb, 0xfd, - 0xf4, 0x68, 0x03, 0x9f, 0x2b, 0x59, 0xb7, 0x77, 0x0e, 0xa9, 0xcd, 0xe2, 0xf3, 0x10, 0x44, 0xd3, - 0x25, 0xb1, 0x62, 0x9f, 0x1e, 0x74, 0xbb, 0x3b, 0x87, 0xce, 0x67, 0x4f, 0x37, 0xed, 0x9d, 0xcd, - 0x2e, 0x56, 0x9c, 0xcb, 0x80, 0x0b, 0xfc, 0x32, 0x5b, 0x80, 0xc6, 0xd1, 0xee, 0x0f, 0x9d, 0x83, - 0xfd, 0x9d, 0x83, 0x7d, 0x44, 0xad, 0xa4, 0x41, 0x02, 0xab, 0xca, 0x3a, 0xb0, 0xbc, 0xf9, 0xeb, - 0x47, 0x4e, 0x46, 0xcb, 0x30, 0xa3, 0x4c, 0xd4, 0xab, 0xb1, 0x1b, 0x70, 0xbd, 0x7b, 0xb4, 0x7a, - 0xb4, 0xb3, 0xee, 0xc8, 0x37, 0x8e, 0xc4, 0x26, 0x88, 0x6a, 0xf5, 0xec, 0x22, 0x51, 0xab, 0xc1, - 0x96, 0xa0, 0x75, 0xb8, 0xfa, 0xc5, 0xde, 0xe6, 0xfe, 0x91, 0xb3, 0xba, 0xb1, 0x61, 0x63, 0x85, - 0xe6, 0x14, 0x54, 0xe0, 0xce, 0x8b, 0x8d, 0xda, 0x3b, 0x3c, 0x44, 0x94, 0x96, 0xfa, 0x10, 0x25, - 0x0b, 0x8f, 0x7f, 0xbb, 0x00, 0x4d, 0x0a, 0xbe, 0xa7, 0x1f, 0x6f, 0xe0, 0x21, 0xdb, 0x83, 0xb2, - 0xfc, 0x15, 0x10, 0x76, 0x5d, 0x3f, 0x3b, 0x61, 0xfe, 0xee, 0x48, 0x67, 0x79, 0x12, 0x2c, 0x8f, - 0xdf, 0xe2, 0xdf, 0xfc, 0xd3, 0xbf, 0xf8, 0x47, 0xf9, 0x06, 0xab, 0x3d, 0x3c, 0x7f, 0xef, 0xe1, - 0x29, 0xf7, 0x23, 0xd1, 0xc6, 0x5f, 0x03, 0x48, 0x7e, 0xdb, 0x82, 0xb5, 0xb5, 0x11, 0x71, 0xe2, - 0x87, 0x3f, 0x3a, 0x37, 0x32, 0x4a, 0x64, 0xbb, 0x37, 0xb0, 0xdd, 0x45, 0xab, 0x29, 0xda, 0xf5, - 0x7c, 0x2f, 0xa6, 0xdf, 0xb9, 0xf8, 0x38, 0x77, 0x9f, 0xf5, 0xa1, 0x6e, 0xfe, 0xea, 0x04, 0x53, - 0x4e, 0xf8, 0x8c, 0xdf, 0xcd, 0xe8, 0xdc, 0xcc, 0x2c, 0x53, 0x3c, 0x07, 0xfb, 0xb8, 0x6e, 0xb5, - 0x44, 0x1f, 0x63, 0xc4, 0x48, 0x7a, 0x19, 0x10, 0x17, 0x4e, 0x7e, 0x5c, 0x82, 0xbd, 0x62, 0x70, - 0xc6, 0xa9, 0x9f, 0xb6, 0xe8, 0xdc, 0x9a, 0x51, 0x2a, 0xfb, 0xba, 0x85, 0x7d, 0xad, 0x58, 0x4c, - 0xf4, 0xd5, 0x43, 0x1c, 0xf5, 0xd3, 0x16, 0x1f, 0xe7, 0xee, 0x3f, 0xfe, 0xf3, 0x7b, 0x50, 0xd5, - 0xc1, 0x38, 0xec, 0x37, 0xa1, 0x91, 0xca, 0x8e, 0x60, 0x6a, 0x1a, 0x59, 0xc9, 0x14, 0x9d, 0x57, - 0xb2, 0x0b, 0x65, 0xc7, 0xaf, 0x62, 0xc7, 0x6d, 0xb6, 0x2c, 0x3a, 0x96, 0xd9, 0x07, 0x0f, 0x31, - 0x87, 0x88, 0x1e, 0xf1, 0x78, 0x66, 0xdc, 0x36, 0xd4, 0xd9, 0x2b, 0x93, 0x37, 0x40, 0xaa, 0xb7, - 0x5b, 0x33, 0x4a, 0x65, 0x77, 0xaf, 0x60, 0x77, 0xcb, 0x6c, 0xc9, 0xec, 0x4e, 0x85, 0xce, 0x30, - 0x8e, 0x0f, 0xe7, 0x98, 0x3f, 0xc5, 0xc0, 0x6e, 0x25, 0xcf, 0x9c, 0x64, 0xfc, 0x44, 0x83, 0x26, - 0x91, 0xe9, 0xdf, 0x69, 0xb0, 0xda, 0xd8, 0x15, 0x63, 0xb8, 0x7d, 0xe6, 0x2f, 0x31, 0xb0, 0x63, - 0xa8, 0x19, 0xaf, 0x17, 0xb3, 0x1b, 0x33, 0x5f, 0x5a, 0xee, 0x74, 0xb2, 0x8a, 0xb2, 0xa6, 0x62, - 0xb6, 0xff, 0x50, 0xc8, 0x9e, 0x3f, 0x86, 0xaa, 0x7e, 0x13, 0x97, 0xad, 0x18, 0x6f, 0x14, 0x9b, - 0x6f, 0xf8, 0x76, 0xda, 0xd3, 0x05, 0x59, 0xc4, 0x67, 0xb6, 0x2e, 0x88, 0xef, 0x73, 0xa8, 0x19, - 0xef, 0xde, 0xea, 0x09, 0x4c, 0xbf, 0xad, 0xab, 0x27, 0x90, 0xf1, 0x4c, 0xae, 0xb5, 0x80, 0x5d, - 0xd4, 0x58, 0x15, 0xe9, 0x3b, 0xbe, 0x0c, 0x22, 0xb6, 0x0b, 0xd7, 0xe5, 0xcd, 0x7a, 0xcc, 0xbf, - 0xc9, 0x36, 0x64, 0xfc, 0xfa, 0xc5, 0xa3, 0x1c, 0xfb, 0x04, 0x2a, 0xea, 0x79, 0x63, 0xb6, 0x9c, - 0xfd, 0x4c, 0x73, 0x67, 0x65, 0x0a, 0x2e, 0xaf, 0xc1, 0x2f, 0x00, 0x92, 0x47, 0x76, 0x35, 0x93, - 0x98, 0x7a, 0xb4, 0x57, 0x53, 0xc0, 0xf4, 0x8b, 0xbc, 0xd6, 0x32, 0x4e, 0xb0, 0xc5, 0x90, 0x49, - 0xf8, 0xfc, 0x42, 0xbd, 0x20, 0xf6, 0x13, 0xa8, 0x19, 0xef, 0xec, 0xea, 0xe5, 0x9b, 0x7e, 0xa3, - 0x57, 0x2f, 0x5f, 0xc6, 0xb3, 0xbc, 0x56, 0x07, 0x5b, 0x5f, 0xb2, 0xe6, 0x45, 0xeb, 0x91, 0x77, - 0xea, 0x0f, 0x09, 0x41, 0x6c, 0xd0, 0x19, 0x34, 0x52, 0x8f, 0xe9, 0xea, 0x13, 0x9a, 0xf5, 0x54, - 0xaf, 0x3e, 0xa1, 0x99, 0xef, 0xef, 0x2a, 0x3a, 0xb3, 0x16, 0x44, 0x3f, 0xe7, 0x88, 0x62, 0xf4, - 0xf4, 0x23, 0xa8, 0x19, 0x0f, 0xe3, 0xea, 0xb9, 0x4c, 0xbf, 0xc1, 0xab, 0xe7, 0x92, 0xf5, 0x8e, - 0xee, 0x12, 0xf6, 0xd1, 0xb4, 0x90, 0x14, 0xf0, 0x7d, 0x26, 0xd1, 0xf6, 0x6f, 0x42, 0x33, 0xfd, - 0x56, 0xae, 0x3e, 0xfb, 0x99, 0x8f, 0xee, 0xea, 0xb3, 0x3f, 0xe3, 0x81, 0x5d, 0x49, 0xd2, 0xf7, - 0x17, 0x75, 0x27, 0x0f, 0xbf, 0x92, 0x61, 0xc5, 0x5f, 0xb3, 0xcf, 0x04, 0x83, 0x93, 0xcf, 0x83, - 0xb1, 0x15, 0x83, 0x6a, 0xcd, 0x47, 0xc4, 0xf4, 0x79, 0x99, 0x7a, 0x49, 0x2c, 0x4d, 0xcc, 0xd8, - 0x38, 0xfb, 0x14, 0x16, 0x35, 0x31, 0xeb, 0xf7, 0xbe, 0x22, 0x3d, 0x87, 0xcc, 0x57, 0xc5, 0x3a, - 0xad, 0xc9, 0xd2, 0x47, 0x39, 0xba, 0xfe, 0xf0, 0x95, 0x25, 0xe3, 0xfa, 0x33, 0x9f, 0xfc, 0x32, - 0xae, 0xbf, 0xd4, 0x63, 0x4c, 0x93, 0xd7, 0x5f, 0xec, 0x89, 0x36, 0x7c, 0x98, 0x9f, 0x7c, 0x7d, - 0xeb, 0xd6, 0xac, 0xdc, 0x53, 0x6a, 0xfe, 0xd5, 0xe7, 0xa7, 0xa6, 0xa6, 0x59, 0x91, 0xe2, 0xa6, - 0x0f, 0xa5, 0xf3, 0x90, 0xfd, 0x06, 0xd4, 0xcd, 0xc7, 0x3e, 0x99, 0xc9, 0x13, 0x26, 0x7b, 0xba, - 0x99, 0x59, 0x96, 0xa6, 0x12, 0x56, 0x37, 0xbb, 0x61, 0x3f, 0x84, 0x65, 0xbd, 0xcc, 0x66, 0xde, - 0x61, 0xc4, 0x6e, 0x67, 0x64, 0x23, 0xa6, 0x16, 0xfb, 0xc6, 0xcc, 0x74, 0xc5, 0x47, 0x39, 0x41, - 0x7d, 0xe9, 0x57, 0x07, 0x93, 0x9b, 0x27, 0xeb, 0xb1, 0xc5, 0xe4, 0xe6, 0xc9, 0x7c, 0xaa, 0x50, - 0x51, 0x1f, 0x5b, 0x4c, 0xad, 0x11, 0x85, 0x55, 0xb1, 0x1f, 0xc1, 0xbc, 0x91, 0x54, 0xd9, 0xbd, - 0xf2, 0x7b, 0xfa, 0x24, 0x4d, 0x3f, 0xe9, 0xd3, 0xc9, 0xd2, 0x45, 0xad, 0x15, 0x6c, 0x7f, 0xc1, - 0x4a, 0x2d, 0x8e, 0x38, 0x45, 0xeb, 0x50, 0x33, 0x13, 0x36, 0x9f, 0xd3, 0xee, 0x8a, 0x51, 0x64, - 0xbe, 0x1e, 0xf3, 0x28, 0xc7, 0x76, 0xa1, 0x35, 0xf9, 0xd8, 0x85, 0xe6, 0x29, 0x59, 0x0f, 0x74, - 0x74, 0x26, 0x0a, 0x53, 0x4f, 0x64, 0xb0, 0x43, 0x0a, 0xcc, 0xd5, 0x3f, 0x15, 0x11, 0x84, 0x93, - 0xb7, 0x7a, 0xfa, 0x27, 0x24, 0x74, 0x6b, 0x59, 0x3f, 0x1e, 0x72, 0x2f, 0xf7, 0x28, 0xc7, 0x7e, - 0x37, 0x07, 0xf5, 0x54, 0x82, 0x79, 0x2a, 0xf4, 0x71, 0x62, 0x9e, 0x6d, 0xb3, 0xcc, 0x9c, 0xa8, - 0x65, 0xe3, 0x22, 0xee, 0xde, 0xff, 0x41, 0x6a, 0x93, 0xbe, 0x4a, 0x39, 0x65, 0x1e, 0x4c, 0xfe, - 0x96, 0xc4, 0xd7, 0x93, 0x08, 0xe6, 0x4b, 0x4d, 0x5f, 0x3f, 0xca, 0xb1, 0x7f, 0x97, 0x83, 0x66, - 0xda, 0x3b, 0xa3, 0xa7, 0x9b, 0xe9, 0x07, 0xd2, 0xa4, 0x34, 0xc3, 0xa5, 0xf3, 0x23, 0x1c, 0xe5, - 0xd1, 0x7d, 0x3b, 0x35, 0x4a, 0xf9, 0x5e, 0xe6, 0xcf, 0x37, 0x5a, 0xf6, 0x31, 0xfd, 0x74, 0x93, - 0x72, 0x45, 0xb3, 0xe9, 0x9f, 0xfa, 0xd1, 0xe4, 0x67, 0xfe, 0x30, 0x0e, 0x6e, 0xc2, 0x4f, 0xe8, - 0x37, 0x13, 0x94, 0x67, 0x53, 0x50, 0xf1, 0xcb, 0xd6, 0xb7, 0xde, 0xc0, 0x39, 0xbd, 0x6a, 0xdd, - 0x48, 0xcd, 0x69, 0x52, 0xf0, 0x58, 0xa5, 0xd1, 0xc9, 0xdf, 0xb5, 0x49, 0x6e, 0xce, 0xa9, 0xdf, - 0xba, 0x99, 0x3d, 0xc8, 0x21, 0x0d, 0x52, 0xa2, 0xa7, 0x8e, 0xda, 0x4b, 0x36, 0x63, 0xdd, 0xc7, - 0xb1, 0xbe, 0x61, 0xdd, 0x9e, 0x39, 0xd6, 0x87, 0xe8, 0x69, 0x11, 0x23, 0x3e, 0x04, 0x48, 0x42, - 0x45, 0xd8, 0x44, 0xc0, 0x82, 0x66, 0x40, 0xd3, 0xd1, 0x24, 0xe9, 0xf3, 0xac, 0xe2, 0x1a, 0x44, - 0x8b, 0x3f, 0x26, 0x76, 0xaa, 0x43, 0x29, 0x4c, 0xe9, 0x2b, 0x1d, 0xd5, 0x91, 0x92, 0xbe, 0x26, - 0xdb, 0x4f, 0x31, 0x53, 0x1d, 0x37, 0xf1, 0x14, 0x1a, 0xbb, 0x41, 0xf0, 0x6c, 0x3c, 0xd2, 0xe1, - 0x89, 0x69, 0xf7, 0xe7, 0xb6, 0x1b, 0x9d, 0x75, 0x26, 0x66, 0x61, 0xdd, 0xc1, 0xa6, 0x3a, 0xac, - 0x6d, 0x34, 0xf5, 0xf0, 0xab, 0x24, 0x3e, 0xe5, 0x6b, 0xe6, 0xc2, 0x82, 0xe6, 0xd1, 0x49, 0x0c, - 0x48, 0xba, 0x99, 0x14, 0x67, 0x9e, 0xec, 0x22, 0xa5, 0x26, 0xa8, 0xd1, 0x3e, 0x8c, 0x54, 0x9b, - 0x8f, 0x72, 0xec, 0x10, 0xea, 0x1b, 0xbc, 0x87, 0x89, 0x96, 0xe8, 0x44, 0x5c, 0x4c, 0x39, 0xa4, - 0xc8, 0xfb, 0xd8, 0x69, 0xa4, 0x80, 0xe9, 0x7b, 0x6b, 0xe4, 0x5e, 0x85, 0xfc, 0xcb, 0x87, 0x5f, - 0x49, 0xf7, 0xe4, 0xd7, 0xea, 0xde, 0x52, 0xee, 0xdb, 0xd4, 0xbd, 0x35, 0xe1, 0xef, 0x4d, 0xdd, - 0x5b, 0x53, 0xfe, 0xde, 0xd4, 0x52, 0x2b, 0xf7, 0x31, 0x1b, 0xc0, 0xc2, 0x94, 0x8b, 0x58, 0x5f, - 0x59, 0xb3, 0x1c, 0xcb, 0x9d, 0x3b, 0xb3, 0x11, 0xd2, 0xbd, 0xdd, 0x4f, 0xf7, 0xd6, 0x85, 0x06, - 0x3d, 0x1e, 0x75, 0xcc, 0x29, 0xe5, 0x62, 0xe2, 0xbd, 0x02, 0x33, 0x9f, 0x63, 0xf2, 0x82, 0xc1, - 0xb2, 0xb4, 0x84, 0x83, 0xb9, 0x0e, 0xec, 0xc7, 0x50, 0xfb, 0x94, 0xc7, 0x2a, 0xc7, 0x42, 0xcb, - 0xd8, 0x13, 0x49, 0x17, 0x9d, 0x8c, 0x14, 0x8d, 0x34, 0xcd, 0x60, 0x6b, 0x0f, 0x79, 0xff, 0x94, - 0x13, 0x73, 0x72, 0xbc, 0xfe, 0xd7, 0xec, 0xd7, 0xb1, 0x71, 0x9d, 0xda, 0xb6, 0x6c, 0x04, 0xd1, - 0x9b, 0x8d, 0xcf, 0x4f, 0xc0, 0xb3, 0x5a, 0xf6, 0x83, 0x3e, 0x37, 0x64, 0x3d, 0x1f, 0x6a, 0x46, - 0x0a, 0xac, 0x3e, 0x40, 0xd3, 0x29, 0xcf, 0xfa, 0x00, 0x65, 0x64, 0xcc, 0x5a, 0xf7, 0xb0, 0x1f, - 0x8b, 0xdd, 0x49, 0xfa, 0xa1, 0x2c, 0xd9, 0xa4, 0xa7, 0x87, 0x5f, 0xb9, 0xc3, 0xf8, 0x6b, 0xf6, - 0x39, 0x3e, 0xd1, 0x6a, 0xe6, 0x90, 0x24, 0x4a, 0xc3, 0x64, 0xba, 0x89, 0x5e, 0x2c, 0xa3, 0x28, - 0xad, 0x48, 0x50, 0x57, 0x28, 0xc9, 0x7d, 0x00, 0xd0, 0x8d, 0x83, 0xd1, 0x86, 0xcb, 0x87, 0x81, - 0x9f, 0xf0, 0xda, 0x24, 0xab, 0x21, 0xe1, 0x5f, 0x46, 0x6a, 0x03, 0xfb, 0xdc, 0xd0, 0xb2, 0x52, - 0x69, 0x38, 0x8a, 0xb8, 0x66, 0x26, 0x3e, 0xe8, 0x05, 0xc9, 0x48, 0x7e, 0x78, 0x94, 0x63, 0xab, - 0x00, 0x49, 0x8c, 0x80, 0xd6, 0x99, 0xa6, 0xc2, 0x0f, 0x34, 0xdb, 0xcb, 0x08, 0x28, 0x38, 0x84, - 0x6a, 0xe2, 0x5c, 0x5d, 0x49, 0x32, 0xfa, 0x53, 0xae, 0x58, 0x7d, 0x83, 0x4f, 0xb9, 0x37, 0xad, - 0x16, 0x2e, 0x15, 0xb0, 0x8a, 0x58, 0xaa, 0x13, 0xce, 0x23, 0xe6, 0xc1, 0x22, 0x0d, 0x50, 0x8b, - 0x4b, 0x18, 0x8d, 0xaf, 0x5f, 0xe2, 0x9d, 0xf6, 0x34, 0xea, 0xd3, 0x9c, 0xe9, 0x2f, 0x4b, 0x99, - 0x7e, 0x04, 0xb5, 0x52, 0x26, 0x80, 0x60, 0xcd, 0x43, 0x58, 0x98, 0x72, 0xc9, 0xe8, 0x23, 0x3d, - 0xcb, 0xc7, 0xa6, 0x8f, 0xf4, 0x4c, 0x6f, 0x8e, 0x75, 0x1d, 0xbb, 0x9c, 0xb7, 0x00, 0x55, 0xbd, - 0x0b, 0x2f, 0xee, 0x9d, 0x89, 0xee, 0xfe, 0x75, 0x0e, 0x16, 0x33, 0x9c, 0x2e, 0xec, 0x35, 0x65, - 0x35, 0x98, 0xe9, 0x90, 0xe9, 0x64, 0x1a, 0xe7, 0xad, 0x2e, 0xf6, 0xb3, 0xc7, 0x9e, 0xa4, 0x2e, - 0x36, 0xb2, 0x8d, 0xcb, 0x93, 0xf9, 0x5c, 0xa1, 0x22, 0x53, 0xa2, 0xf8, 0x12, 0x56, 0x68, 0x20, - 0xab, 0x83, 0xc1, 0x84, 0xe3, 0xe0, 0xd5, 0xa9, 0xdf, 0x72, 0x4d, 0x39, 0x43, 0x3a, 0xb3, 0x7f, - 0xeb, 0x75, 0x86, 0x38, 0x4d, 0x43, 0x65, 0x63, 0x68, 0x4d, 0x1a, 0xe4, 0xd9, 0xec, 0xb6, 0x3a, - 0xb7, 0x53, 0xfa, 0x6f, 0x86, 0x11, 0xff, 0x3b, 0xd8, 0xd9, 0x6d, 0xab, 0x93, 0xb5, 0x2e, 0xa4, - 0x12, 0x8b, 0xfd, 0xf8, 0x1b, 0xda, 0x7b, 0x30, 0x31, 0x4f, 0xd5, 0xc1, 0x2c, 0x5f, 0x87, 0xd6, - 0xc0, 0xb3, 0x9d, 0x0f, 0x6f, 0x62, 0xf7, 0x77, 0xac, 0x9b, 0x59, 0xdd, 0x87, 0x54, 0x85, 0x74, - 0xf1, 0x95, 0xc9, 0x73, 0xad, 0x46, 0x70, 0x27, 0x6b, 0xbf, 0x67, 0xea, 0x42, 0x13, 0x6b, 0x7d, - 0x0d, 0x65, 0xbb, 0xba, 0xe9, 0x2d, 0xd0, 0xc7, 0x27, 0xc3, 0x2d, 0xa1, 0x8f, 0x4f, 0x96, 0x7b, - 0x21, 0x2d, 0xd7, 0x28, 0xc7, 0xc2, 0xc7, 0xb9, 0xfb, 0x6b, 0x77, 0x7f, 0xf4, 0x9d, 0x53, 0x2f, - 0x3e, 0x1b, 0x1f, 0x3f, 0xe8, 0x05, 0xc3, 0x87, 0x03, 0x65, 0x6d, 0x94, 0x29, 0x6b, 0x0f, 0x07, - 0x7e, 0xff, 0x21, 0x36, 0x7b, 0x3c, 0x87, 0x3f, 0x3e, 0xfd, 0xdd, 0xff, 0x17, 0x00, 0x00, 0xff, - 0xff, 0xa6, 0xaa, 0x20, 0x1e, 0xae, 0x7a, 0x00, 0x00, + // 10447 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x24, 0x47, + 0x76, 0x18, 0x3c, 0x75, 0xeb, 0xaa, 0x3a, 0x75, 0xe9, 0xea, 0xe8, 0x9e, 0xee, 0x9a, 0x1a, 0x0e, + 0x67, 0x98, 0xe4, 0x72, 0x86, 0x43, 0x72, 0x66, 0x38, 0x4b, 0x2e, 0x29, 0xf2, 0xfb, 0x56, 0xea, + 0x2b, 0xbb, 0x77, 0xfa, 0xc6, 0xac, 0x9e, 0xa5, 0xb8, 0x6b, 0x39, 0x37, 0xbb, 0x2a, 0xba, 0x3b, + 0x35, 0x55, 0x99, 0xc5, 0xcc, 0xac, 0xbe, 0x2c, 0x41, 0x3f, 0xf8, 0x22, 0x18, 0xb6, 0x61, 0x40, + 0xb0, 0x65, 0xc0, 0xb2, 0x05, 0x1b, 0x36, 0x0c, 0xc3, 0xb0, 0x21, 0xc8, 0x58, 0x19, 0xf0, 0x83, + 0xdf, 0xf5, 0x62, 0x43, 0x0f, 0xb2, 0x5f, 0x8c, 0x85, 0x00, 0xc1, 0x82, 0x9e, 0xf5, 0x13, 0x8c, + 0x38, 0x27, 0x22, 0x32, 0xb2, 0x2a, 0x6b, 0x66, 0xc8, 0x5d, 0xef, 0xcb, 0x4c, 0xe7, 0x89, 0x13, + 0xf7, 0x13, 0x27, 0xce, 0x35, 0x0a, 0xaa, 0xe1, 0xa8, 0xf7, 0x60, 0x14, 0x06, 0x71, 0xc0, 0x4a, + 0x03, 0x3f, 0x1c, 0xf5, 0x3a, 0xaf, 0x9c, 0x06, 0xc1, 0xe9, 0x80, 0x3f, 0x74, 0x47, 0xde, 0x43, + 0xd7, 0xf7, 0x83, 0xd8, 0x8d, 0xbd, 0xc0, 0x8f, 0x08, 0xc9, 0xfa, 0x09, 0x34, 0x3f, 0xe5, 0x7e, + 0x97, 0xf3, 0xbe, 0xcd, 0xbf, 0x1c, 0xf3, 0x28, 0x66, 0x6f, 0xc3, 0x82, 0xcb, 0x7f, 0xca, 0x79, + 0xdf, 0x19, 0xb9, 0x51, 0x34, 0x3a, 0x0b, 0xdd, 0x88, 0xb7, 0x73, 0x77, 0x72, 0xf7, 0xea, 0x76, + 0x8b, 0x0a, 0x0e, 0x35, 0x9c, 0xbd, 0x06, 0xf5, 0x48, 0xa0, 0x72, 0x3f, 0x0e, 0x83, 0xd1, 0x55, + 0x3b, 0x8f, 0x78, 0x35, 0x01, 0xdb, 0x24, 0x90, 0x35, 0x80, 0x79, 0xdd, 0x43, 0x34, 0x0a, 0xfc, + 0x88, 0xb3, 0x47, 0xb0, 0xd4, 0xf3, 0x46, 0x67, 0x3c, 0x74, 0xb0, 0xf2, 0xd0, 0xe7, 0xc3, 0xc0, + 0xf7, 0x7a, 0xed, 0xdc, 0x9d, 0xc2, 0xbd, 0xaa, 0xcd, 0xa8, 0x4c, 0xd4, 0xd8, 0x93, 0x25, 0xec, + 0x2e, 0xcc, 0x73, 0x9f, 0xe0, 0xbc, 0x8f, 0xb5, 0x64, 0x57, 0xcd, 0x04, 0x2c, 0x2a, 0x58, 0x7f, + 0x3f, 0x0f, 0x0b, 0x3b, 0xbe, 0x17, 0x7f, 0xee, 0x0e, 0x06, 0x3c, 0x56, 0x73, 0xba, 0x0b, 0xf3, + 0x17, 0x08, 0xc0, 0x39, 0x5d, 0x04, 0x61, 0x5f, 0xce, 0xa8, 0x49, 0xe0, 0x43, 0x09, 0x9d, 0x39, + 0xb2, 0xfc, 0xcc, 0x91, 0x65, 0x2e, 0x57, 0x61, 0xc6, 0x72, 0xdd, 0x85, 0xf9, 0x90, 0xf7, 0x82, + 0x73, 0x1e, 0x5e, 0x39, 0x17, 0x9e, 0xdf, 0x0f, 0x2e, 0xda, 0xc5, 0x3b, 0xb9, 0x7b, 0x25, 0xbb, + 0xa9, 0xc0, 0x9f, 0x23, 0x94, 0xad, 0xc1, 0x7c, 0xef, 0xcc, 0xf5, 0x7d, 0x3e, 0x70, 0x8e, 0xdd, + 0xde, 0xb3, 0xf1, 0x28, 0x6a, 0x97, 0xee, 0xe4, 0xee, 0xd5, 0x1e, 0xdf, 0x78, 0x80, 0xbb, 0xfa, + 0x60, 0xfd, 0xcc, 0xf5, 0xd7, 0xb0, 0xa4, 0xeb, 0xbb, 0xa3, 0xe8, 0x2c, 0x88, 0xed, 0xa6, 0xac, + 0x41, 0xe0, 0xc8, 0x5a, 0x02, 0x66, 0xae, 0x04, 0xad, 0xbd, 0xf5, 0x1f, 0x73, 0xb0, 0xf8, 0xd4, + 0x1f, 0x04, 0xbd, 0x67, 0xdf, 0x72, 0x89, 0x32, 0xe6, 0x90, 0x7f, 0xd9, 0x39, 0x14, 0xbe, 0xe9, + 0x1c, 0x96, 0x61, 0x29, 0x3d, 0x58, 0x39, 0x0b, 0x0e, 0xd7, 0x45, 0xed, 0x53, 0xae, 0x86, 0xa5, + 0xa6, 0xf1, 0x16, 0xb4, 0x7a, 0xe3, 0x30, 0xe4, 0xfe, 0xd4, 0x3c, 0xe6, 0x25, 0x5c, 0x4f, 0xe4, + 0x35, 0xa8, 0xfb, 0xfc, 0x22, 0x41, 0x93, 0xb4, 0xeb, 0xf3, 0x0b, 0x85, 0x62, 0xb5, 0x61, 0x79, + 0xb2, 0x1b, 0x39, 0x80, 0xbf, 0xca, 0x41, 0xf1, 0x69, 0x7c, 0x19, 0xb0, 0x0f, 0xa0, 0xee, 0xf6, + 0xfb, 0x21, 0x8f, 0x22, 0x27, 0xbe, 0x1a, 0xd1, 0x49, 0x69, 0x3e, 0x66, 0x72, 0x8a, 0xab, 0x54, + 0x74, 0x74, 0x35, 0xe2, 0x76, 0xcd, 0x4d, 0x3e, 0x58, 0x1b, 0xca, 0xf2, 0x13, 0xfb, 0xad, 0xda, + 0xea, 0x93, 0xdd, 0x02, 0x70, 0x87, 0xc1, 0xd8, 0x8f, 0x9d, 0xc8, 0x8d, 0x71, 0xc5, 0x0a, 0x76, + 0x95, 0x20, 0x5d, 0x37, 0x66, 0x37, 0xa1, 0x3a, 0x7a, 0xe6, 0x44, 0xbd, 0xd0, 0x1b, 0xc5, 0x48, + 0x3c, 0x55, 0xbb, 0x32, 0x7a, 0xd6, 0xc5, 0x6f, 0xf6, 0x36, 0x54, 0x82, 0x71, 0x3c, 0x0a, 0x3c, + 0x3f, 0x96, 0xf4, 0x32, 0x2f, 0x07, 0x72, 0x30, 0x8e, 0x0f, 0x05, 0xd8, 0xd6, 0x08, 0xec, 0x0d, + 0x68, 0xf4, 0x02, 0xff, 0xc4, 0x0b, 0x87, 0xc4, 0x11, 0xda, 0x73, 0xd8, 0x57, 0x1a, 0x68, 0xfd, + 0x51, 0x1e, 0x6a, 0x47, 0xa1, 0xeb, 0x47, 0x6e, 0x4f, 0x00, 0xd8, 0x0a, 0x94, 0xe3, 0x4b, 0xe7, + 0xcc, 0x8d, 0xce, 0x70, 0xaa, 0x55, 0x7b, 0x2e, 0xbe, 0xdc, 0x76, 0xa3, 0x33, 0xb6, 0x0c, 0x73, + 0x34, 0x4a, 0x9c, 0x50, 0xc1, 0x96, 0x5f, 0xe2, 0x80, 0xf8, 0xe3, 0xa1, 0x93, 0xee, 0xaa, 0x80, + 0x14, 0xd3, 0xf2, 0xc7, 0xc3, 0x75, 0x13, 0x2e, 0x26, 0x7f, 0x2c, 0xb6, 0x9b, 0x3a, 0xa0, 0xe9, + 0x55, 0x11, 0x82, 0x7d, 0xbc, 0x06, 0x75, 0x59, 0xcc, 0xbd, 0xd3, 0x33, 0x9a, 0x63, 0xc9, 0xae, + 0x11, 0x02, 0x82, 0x44, 0x0b, 0xb1, 0x37, 0xe4, 0x4e, 0x14, 0xbb, 0xc3, 0x91, 0x9c, 0x52, 0x55, + 0x40, 0xba, 0x02, 0x80, 0xc5, 0x41, 0xec, 0x0e, 0x9c, 0x13, 0xce, 0xa3, 0x76, 0x59, 0x16, 0x0b, + 0xc8, 0x16, 0xe7, 0x11, 0xfb, 0x0e, 0x34, 0xfb, 0x3c, 0x8a, 0x1d, 0xb9, 0x19, 0x3c, 0x6a, 0x57, + 0xf0, 0xe4, 0x37, 0x04, 0x74, 0x55, 0x01, 0xd9, 0x2b, 0x00, 0xa1, 0x7b, 0xe1, 0x88, 0x85, 0xe0, + 0x97, 0xed, 0x2a, 0xed, 0x42, 0xe8, 0x5e, 0x1c, 0x5d, 0x6e, 0xf3, 0x4b, 0x41, 0x35, 0x9f, 0xf2, + 0xd8, 0x58, 0xb4, 0x48, 0x52, 0xa7, 0xb5, 0x0b, 0xcc, 0x00, 0x6f, 0xf0, 0xd8, 0xf5, 0x06, 0x11, + 0xfb, 0x1e, 0xd4, 0x63, 0x03, 0x19, 0xd9, 0x60, 0x4d, 0x93, 0x90, 0x51, 0xc1, 0x4e, 0xe1, 0x59, + 0x67, 0x50, 0xd9, 0xe2, 0x7c, 0xd7, 0x1b, 0x7a, 0x31, 0x5b, 0x86, 0xd2, 0x89, 0x77, 0xc9, 0x89, + 0xd8, 0x0b, 0xdb, 0xd7, 0x6c, 0xfa, 0x64, 0xb7, 0x01, 0xf0, 0x0f, 0x67, 0xa8, 0xa9, 0x69, 0xfb, + 0x9a, 0x5d, 0x45, 0xd8, 0x5e, 0xe4, 0xc6, 0xac, 0x03, 0xe5, 0x11, 0x0f, 0x7b, 0x5c, 0xed, 0xdb, + 0xf6, 0x35, 0x5b, 0x01, 0xd6, 0xca, 0x50, 0x1a, 0x88, 0xd6, 0xad, 0x3f, 0x29, 0x41, 0xad, 0xcb, + 0x7d, 0x7d, 0xca, 0x18, 0x14, 0xc5, 0x82, 0xc8, 0x93, 0x85, 0x7f, 0xb3, 0xd7, 0xa1, 0x86, 0x4b, + 0x17, 0xc5, 0xa1, 0xe7, 0x9f, 0x12, 0x55, 0xaf, 0xe5, 0xdb, 0x39, 0x1b, 0x04, 0xb8, 0x8b, 0x50, + 0xd6, 0x82, 0x82, 0x3b, 0x54, 0x54, 0x2d, 0xfe, 0x64, 0x37, 0xa0, 0xe2, 0x0e, 0x63, 0x1a, 0x5e, + 0x1d, 0xc1, 0x65, 0x77, 0x18, 0xe3, 0xd0, 0x5e, 0x83, 0xfa, 0xc8, 0xbd, 0x1a, 0x8a, 0xb3, 0xac, + 0xc9, 0xa1, 0x6e, 0xd7, 0x24, 0x0c, 0x09, 0xe2, 0x31, 0x2c, 0x9a, 0x28, 0xaa, 0xf3, 0x92, 0xee, + 0x7c, 0xc1, 0xc0, 0x96, 0x63, 0xb8, 0x0b, 0xf3, 0xaa, 0x4e, 0x48, 0xf3, 0x41, 0x32, 0xa9, 0xda, + 0x4d, 0x09, 0x56, 0xb3, 0xbc, 0x07, 0xad, 0x13, 0xcf, 0x77, 0x07, 0x4e, 0x6f, 0x10, 0x9f, 0x3b, + 0x7d, 0x3e, 0x88, 0x5d, 0xa4, 0x98, 0x92, 0xdd, 0x44, 0xf8, 0xfa, 0x20, 0x3e, 0xdf, 0x10, 0x50, + 0xf6, 0x0e, 0x54, 0x4f, 0x38, 0x77, 0x70, 0xb1, 0xda, 0x95, 0xd4, 0xc1, 0x53, 0x3b, 0x64, 0x57, + 0x4e, 0xd4, 0x5e, 0xbd, 0x03, 0xad, 0x60, 0x1c, 0x9f, 0x06, 0x9e, 0x7f, 0xea, 0x08, 0x7e, 0xe7, + 0x78, 0x7d, 0xa4, 0xa1, 0xe2, 0x5a, 0xfe, 0x51, 0xce, 0x6e, 0xaa, 0x32, 0xc1, 0x79, 0x76, 0xfa, + 0xec, 0x4d, 0x98, 0x1f, 0xb8, 0x51, 0xec, 0x9c, 0x05, 0x23, 0x67, 0x34, 0x3e, 0x7e, 0xc6, 0xaf, + 0xda, 0x0d, 0x5c, 0x88, 0x86, 0x00, 0x6f, 0x07, 0xa3, 0x43, 0x04, 0x0a, 0xca, 0xc6, 0x71, 0xd2, + 0x20, 0xe0, 0x4e, 0xee, 0x5e, 0xc3, 0xae, 0x0a, 0x08, 0x75, 0xfa, 0x05, 0x2c, 0xe2, 0xf6, 0xf4, + 0xc6, 0x51, 0x1c, 0x0c, 0x1d, 0xc1, 0xab, 0xc3, 0x7e, 0xd4, 0xae, 0x21, 0xad, 0xbd, 0x25, 0x07, + 0x6b, 0xec, 0xf1, 0x83, 0x0d, 0x1e, 0xc5, 0xeb, 0x88, 0x6c, 0x13, 0xae, 0xb8, 0xd0, 0xaf, 0xec, + 0x85, 0xfe, 0x24, 0x9c, 0xbd, 0x03, 0xcc, 0x1d, 0x0c, 0x82, 0x0b, 0x27, 0xe2, 0x83, 0x13, 0x47, + 0x2e, 0x62, 0xbb, 0x79, 0x27, 0x77, 0xaf, 0x62, 0xb7, 0xb0, 0xa4, 0xcb, 0x07, 0x27, 0x87, 0x04, + 0x67, 0xdf, 0x03, 0x3c, 0x4c, 0xce, 0x09, 0x77, 0xe3, 0x71, 0xc8, 0xa3, 0xf6, 0xfc, 0x9d, 0xc2, + 0xbd, 0xe6, 0xe3, 0x05, 0xbd, 0x5e, 0x08, 0x5e, 0xf3, 0x62, 0xbb, 0x2e, 0xf0, 0xe4, 0x77, 0xd4, + 0xd9, 0x80, 0xe5, 0xec, 0x21, 0x09, 0xa2, 0x12, 0xab, 0x22, 0x88, 0xb1, 0x68, 0x8b, 0x3f, 0xd9, + 0x12, 0x94, 0xce, 0xdd, 0xc1, 0x98, 0x4b, 0x9e, 0x4e, 0x1f, 0x1f, 0xe7, 0x3f, 0xca, 0x59, 0x7f, + 0x9c, 0x83, 0x3a, 0xcd, 0x52, 0xca, 0x22, 0xaf, 0x43, 0x43, 0x51, 0x03, 0x0f, 0xc3, 0x20, 0x94, + 0x5c, 0x4d, 0x51, 0xde, 0xa6, 0x80, 0x89, 0x5b, 0x45, 0x21, 0x8d, 0x42, 0xee, 0x0d, 0xdd, 0x53, + 0xd5, 0xb4, 0x22, 0xa5, 0x43, 0x09, 0x66, 0xef, 0x25, 0xed, 0x85, 0xc1, 0x38, 0xe6, 0xf2, 0xce, + 0xab, 0xcb, 0xe9, 0xd9, 0x02, 0xa6, 0x5b, 0xc7, 0xaf, 0x97, 0xa0, 0x73, 0xeb, 0xf7, 0x72, 0xc0, + 0xc4, 0xb0, 0x8f, 0x02, 0x6a, 0x40, 0x52, 0xe8, 0x64, 0xcd, 0xdc, 0x4b, 0x9f, 0x90, 0xfc, 0xf3, + 0x4e, 0x88, 0x05, 0x25, 0x1a, 0x7b, 0x31, 0x63, 0xec, 0x54, 0xf4, 0x83, 0x62, 0xa5, 0xd0, 0x2a, + 0x5a, 0xff, 0xbb, 0x00, 0x4b, 0xeb, 0x74, 0x65, 0xaf, 0xf6, 0x7a, 0x7c, 0xa4, 0xcf, 0xce, 0x6d, + 0xa8, 0xf9, 0x41, 0x9f, 0x2b, 0x8a, 0xa5, 0x81, 0x81, 0x00, 0x19, 0xe4, 0x7a, 0xe6, 0x7a, 0x3e, + 0x0d, 0x9c, 0x16, 0xb3, 0x8a, 0x10, 0x1c, 0xf6, 0x9b, 0x30, 0x3f, 0xe2, 0x7e, 0xdf, 0x3c, 0x22, + 0x24, 0x54, 0x35, 0x24, 0x58, 0x9e, 0x8e, 0xdb, 0x50, 0x3b, 0x19, 0x13, 0x9e, 0x60, 0x2c, 0x45, + 0xa4, 0x01, 0x90, 0xa0, 0x55, 0xe2, 0x2f, 0xa3, 0x71, 0x74, 0x86, 0xa5, 0x25, 0x2c, 0x2d, 0x8b, + 0x6f, 0x51, 0x74, 0x0b, 0xa0, 0x3f, 0x8e, 0x62, 0x79, 0x62, 0xe6, 0xb0, 0xb0, 0x2a, 0x20, 0x74, + 0x62, 0xde, 0x85, 0xc5, 0xa1, 0x7b, 0xe9, 0x20, 0xed, 0x38, 0x9e, 0xef, 0x9c, 0x0c, 0xf0, 0xce, + 0x29, 0x23, 0x5e, 0x6b, 0xe8, 0x5e, 0xfe, 0x50, 0x94, 0xec, 0xf8, 0x5b, 0x08, 0x17, 0x6c, 0x45, + 0x89, 0x3b, 0x21, 0x8f, 0x78, 0x78, 0xce, 0x91, 0x13, 0x14, 0xb5, 0x4c, 0x63, 0x13, 0x54, 0x8c, + 0x68, 0x28, 0xe6, 0x1d, 0x0f, 0x7a, 0x74, 0xec, 0xed, 0xf2, 0xd0, 0xf3, 0xb7, 0xe3, 0x41, 0x4f, + 0xdc, 0x2b, 0x82, 0x8f, 0x8c, 0x78, 0xe8, 0x3c, 0xbb, 0xc0, 0x33, 0x5c, 0x44, 0xbe, 0x71, 0xc8, + 0xc3, 0x27, 0x17, 0xe2, 0xea, 0xef, 0x45, 0xc8, 0x88, 0xdc, 0xab, 0x76, 0x0d, 0x0f, 0x78, 0xa5, + 0x17, 0x09, 0x16, 0xe4, 0x5e, 0x89, 0x43, 0x28, 0x46, 0xeb, 0xe2, 0x2e, 0xf0, 0x3e, 0x36, 0x1f, + 0x21, 0x47, 0x6d, 0xe0, 0x60, 0x57, 0x65, 0x81, 0xe8, 0x27, 0x12, 0x54, 0xaf, 0x06, 0x7b, 0x32, + 0x70, 0x4f, 0x23, 0x64, 0x29, 0x0d, 0xbb, 0x2e, 0x81, 0x5b, 0x02, 0x66, 0x7d, 0x4e, 0x42, 0x96, + 0xb1, 0xb7, 0xf2, 0xcc, 0x88, 0xab, 0x1e, 0x21, 0xb8, 0xaf, 0x15, 0x5b, 0x7e, 0x65, 0x6d, 0x5a, + 0x3e, 0x63, 0xd3, 0xac, 0x3f, 0xc8, 0x41, 0x5d, 0xb6, 0x8c, 0x42, 0x09, 0x7b, 0x00, 0x4c, 0xed, + 0x62, 0x7c, 0xe9, 0xf5, 0x9d, 0xe3, 0xab, 0x98, 0x47, 0x44, 0x34, 0xdb, 0xd7, 0xec, 0x96, 0x2c, + 0x3b, 0xba, 0xf4, 0xfa, 0x6b, 0xa2, 0x84, 0xdd, 0x87, 0x56, 0x0a, 0x3f, 0x8a, 0x43, 0xa2, 0xe8, + 0xed, 0x6b, 0x76, 0xd3, 0xc0, 0xee, 0xc6, 0xa1, 0x38, 0x23, 0x42, 0xe4, 0x19, 0xc7, 0x8e, 0xe7, + 0xf7, 0xf9, 0x25, 0x92, 0x51, 0xc3, 0xae, 0x11, 0x6c, 0x47, 0x80, 0xd6, 0x9a, 0x50, 0x37, 0x9b, + 0xb3, 0x4e, 0xa1, 0xa2, 0xe4, 0x25, 0x14, 0x18, 0x26, 0x86, 0x64, 0x57, 0x63, 0x3d, 0x92, 0x1b, + 0x50, 0x49, 0x8f, 0xc0, 0x2e, 0xc7, 0x2f, 0xdd, 0xb1, 0xf5, 0x7d, 0x68, 0xed, 0x0a, 0xe2, 0xf1, + 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x19, 0xe6, 0x8c, 0x43, 0x53, 0xb5, 0xe5, 0x97, 0xb8, 0x73, 0xcf, + 0x82, 0x28, 0x96, 0xbd, 0xe0, 0xdf, 0xd6, 0x9f, 0xe4, 0x80, 0x6d, 0x46, 0xb1, 0x37, 0x74, 0x63, + 0xbe, 0xc5, 0x35, 0x5b, 0x38, 0x80, 0xba, 0x68, 0xed, 0x28, 0x58, 0x25, 0x81, 0x8c, 0x04, 0x8a, + 0xb7, 0xe5, 0x31, 0x9e, 0xae, 0xf0, 0xc0, 0xc4, 0x26, 0x36, 0x9f, 0x6a, 0x40, 0x9c, 0xb2, 0xd8, + 0x0d, 0x4f, 0x79, 0x8c, 0x62, 0x9c, 0x94, 0xf7, 0x81, 0x40, 0x42, 0x80, 0xeb, 0xfc, 0x3a, 0x2c, + 0x4c, 0xb5, 0x61, 0xf2, 0xe5, 0x6a, 0x06, 0x5f, 0x2e, 0x98, 0x7c, 0xd9, 0x81, 0xc5, 0xd4, 0xb8, + 0x24, 0xa5, 0xad, 0x40, 0x59, 0x1c, 0x08, 0x21, 0x1c, 0xe4, 0x48, 0xaa, 0x3c, 0xe1, 0x5c, 0x88, + 0xc1, 0x0f, 0x61, 0xe9, 0x84, 0xf3, 0xd0, 0x8d, 0xb1, 0x10, 0x4f, 0x8c, 0xd8, 0x21, 0xd9, 0xf0, + 0x82, 0x2c, 0xeb, 0xba, 0xf1, 0x21, 0x0f, 0xc5, 0x4e, 0x59, 0xff, 0x27, 0x07, 0xf3, 0x82, 0x83, + 0xee, 0xb9, 0xfe, 0x95, 0x5a, 0xa7, 0xdd, 0xcc, 0x75, 0xba, 0x67, 0x5c, 0x86, 0x06, 0xf6, 0x37, + 0x5d, 0xa4, 0xc2, 0xe4, 0x22, 0xb1, 0x3b, 0x50, 0x4f, 0x8d, 0xb5, 0x84, 0x63, 0x85, 0x48, 0x0f, + 0xf2, 0x17, 0x5f, 0xc6, 0x37, 0xa1, 0x95, 0x0c, 0x5b, 0xae, 0x21, 0x83, 0xa2, 0x20, 0x49, 0xd9, + 0x00, 0xfe, 0x6d, 0xfd, 0xcb, 0x1c, 0x21, 0xae, 0x07, 0x9e, 0x96, 0x4e, 0x05, 0xa2, 0x90, 0x7b, + 0x15, 0xa2, 0xf8, 0x7b, 0xa6, 0x54, 0xff, 0x8b, 0x4f, 0x56, 0x1c, 0x9d, 0x88, 0xfb, 0x7d, 0xc7, + 0x1d, 0x0c, 0x90, 0xf9, 0x56, 0xec, 0xb2, 0xf8, 0x5e, 0x1d, 0x0c, 0xac, 0xbb, 0xb0, 0x60, 0x8c, + 0xee, 0x39, 0xf3, 0xd8, 0x07, 0xb6, 0xeb, 0x45, 0xf1, 0x53, 0x3f, 0x1a, 0x19, 0x82, 0xdb, 0x4d, + 0xa8, 0x0a, 0x0e, 0x2b, 0x46, 0x46, 0x47, 0xb6, 0x64, 0x0b, 0x96, 0x2b, 0xc6, 0x15, 0x61, 0xa1, + 0x7b, 0x29, 0x0b, 0xf3, 0xb2, 0xd0, 0xbd, 0xc4, 0x42, 0xeb, 0x23, 0x58, 0x4c, 0xb5, 0x27, 0xbb, + 0x7e, 0x0d, 0x4a, 0xe3, 0xf8, 0x32, 0x50, 0xa2, 0x79, 0x4d, 0x52, 0x88, 0x50, 0x00, 0x6d, 0x2a, + 0xb1, 0x3e, 0x81, 0x85, 0x7d, 0x7e, 0x21, 0x0f, 0xb1, 0x1a, 0xc8, 0x9b, 0x50, 0x7c, 0x81, 0x52, + 0x88, 0xe5, 0xd6, 0x03, 0x60, 0x66, 0x65, 0xd9, 0xab, 0xa1, 0x23, 0xe6, 0x52, 0x3a, 0xa2, 0xf5, + 0x26, 0xb0, 0xae, 0x77, 0xea, 0xef, 0xf1, 0x28, 0x72, 0x4f, 0xf5, 0xb1, 0x6f, 0x41, 0x61, 0x18, + 0x9d, 0x4a, 0x1e, 0x25, 0xfe, 0xb4, 0xbe, 0x0b, 0x8b, 0x29, 0x3c, 0xd9, 0xf0, 0x2b, 0x50, 0x8d, + 0xbc, 0x53, 0x1f, 0x05, 0x2b, 0xd9, 0x74, 0x02, 0xb0, 0xb6, 0x60, 0xe9, 0x87, 0x3c, 0xf4, 0x4e, + 0xae, 0x5e, 0xd4, 0x7c, 0xba, 0x9d, 0xfc, 0x64, 0x3b, 0x9b, 0x70, 0x7d, 0xa2, 0x1d, 0xd9, 0x3d, + 0x91, 0xaf, 0xdc, 0xc9, 0x8a, 0x4d, 0x1f, 0x06, 0xdf, 0xcb, 0x9b, 0x7c, 0xcf, 0x7a, 0x0a, 0x6c, + 0x3d, 0xf0, 0x7d, 0xde, 0x8b, 0x0f, 0x39, 0x0f, 0x13, 0x2b, 0x55, 0x42, 0xab, 0xb5, 0xc7, 0x2b, + 0x72, 0x65, 0x27, 0x99, 0xa9, 0x24, 0x62, 0x06, 0xc5, 0x11, 0x0f, 0x87, 0xd8, 0x70, 0xc5, 0xc6, + 0xbf, 0xad, 0xeb, 0xb0, 0x98, 0x6a, 0x56, 0xea, 0xf5, 0x8f, 0xe0, 0xfa, 0x86, 0x17, 0xf5, 0xa6, + 0x3b, 0x5c, 0x81, 0xf2, 0x68, 0x7c, 0xec, 0xa4, 0xf9, 0xf2, 0x13, 0x7e, 0x25, 0xb4, 0xbd, 0xc9, + 0x1a, 0xb2, 0xad, 0xbf, 0x9b, 0x83, 0xe2, 0xf6, 0xd1, 0xee, 0x3a, 0xeb, 0x40, 0xc5, 0xf3, 0x7b, + 0xc1, 0x50, 0x08, 0x5e, 0x34, 0x67, 0xfd, 0x3d, 0xf3, 0x80, 0xdd, 0x84, 0x2a, 0xca, 0x6b, 0x42, + 0xb5, 0x95, 0xa2, 0x4f, 0x45, 0x00, 0x76, 0x83, 0xde, 0x33, 0xa1, 0x53, 0xf3, 0xcb, 0x91, 0x17, + 0xa2, 0xd6, 0xac, 0x94, 0xe1, 0x22, 0xdd, 0xf5, 0x49, 0x01, 0x69, 0xc4, 0xd6, 0x7f, 0x2a, 0x43, + 0x59, 0xde, 0xb6, 0x74, 0x73, 0xc7, 0xde, 0x39, 0x4f, 0x6e, 0x6e, 0xf1, 0x25, 0xe4, 0x81, 0x90, + 0x0f, 0x83, 0x58, 0x0b, 0x6c, 0xb4, 0x07, 0x75, 0x02, 0x4a, 0x91, 0xcd, 0x10, 0x1a, 0xc8, 0xc4, + 0x50, 0x20, 0xa4, 0x9e, 0x79, 0x95, 0xdf, 0x84, 0xb2, 0xba, 0xfb, 0x8b, 0x5a, 0xa7, 0x99, 0xeb, + 0x91, 0xb4, 0xd6, 0x81, 0x4a, 0xcf, 0x1d, 0xb9, 0x3d, 0x2f, 0xbe, 0x92, 0x0c, 0x41, 0x7f, 0x8b, + 0xd6, 0x07, 0x41, 0xcf, 0x1d, 0x38, 0xc7, 0xee, 0xc0, 0xf5, 0x7b, 0x5c, 0xea, 0xee, 0x75, 0x04, + 0xae, 0x11, 0x4c, 0xe8, 0xe7, 0x72, 0x9c, 0x0a, 0x8b, 0x54, 0x78, 0x39, 0x7a, 0x85, 0x26, 0x84, + 0xcb, 0x60, 0x38, 0xf4, 0x84, 0x96, 0x41, 0x62, 0x58, 0xc1, 0xae, 0x12, 0x64, 0x8b, 0xe3, 0x6c, + 0x65, 0xf1, 0x05, 0x2d, 0x5d, 0x95, 0xba, 0x22, 0xe0, 0xe7, 0x64, 0x48, 0x98, 0x96, 0xc5, 0x0a, + 0x86, 0x2c, 0xf6, 0x36, 0x2c, 0x8c, 0xfd, 0x88, 0xc7, 0xf1, 0x80, 0xf7, 0xf5, 0x58, 0x6a, 0x88, + 0xd4, 0xd2, 0x05, 0x6a, 0x38, 0x0f, 0x60, 0x91, 0x8c, 0x0e, 0x91, 0x1b, 0x07, 0xd1, 0x99, 0x17, + 0x39, 0x91, 0xd0, 0x90, 0x48, 0xdd, 0x5d, 0xc0, 0xa2, 0xae, 0x2c, 0xe9, 0x92, 0x8a, 0xb4, 0x32, + 0x81, 0x1f, 0xf2, 0x1e, 0xf7, 0xce, 0x79, 0x1f, 0xe5, 0xb4, 0x82, 0x7d, 0x3d, 0x55, 0xc7, 0x96, + 0x85, 0x28, 0x74, 0x8f, 0x87, 0xce, 0x78, 0xd4, 0x77, 0x85, 0xb0, 0xd2, 0x24, 0x61, 0xd8, 0x1f, + 0x0f, 0x9f, 0x12, 0x84, 0x3d, 0x02, 0x25, 0x89, 0x49, 0xf9, 0x70, 0x3e, 0xc5, 0xcf, 0x04, 0xb1, + 0xda, 0x75, 0x89, 0x41, 0x82, 0x62, 0x4a, 0xe6, 0x6c, 0x4d, 0xc8, 0x9c, 0x6d, 0x28, 0x8f, 0x42, + 0xef, 0xdc, 0x8d, 0x79, 0x7b, 0x81, 0x18, 0xb8, 0xfc, 0x14, 0x9c, 0xc1, 0xf3, 0xbd, 0xd8, 0x73, + 0xe3, 0x20, 0x6c, 0x33, 0x2c, 0x4b, 0x00, 0xec, 0x3e, 0x2c, 0x20, 0x8d, 0x44, 0xb1, 0x1b, 0x8f, + 0x23, 0x29, 0x81, 0x2e, 0x22, 0x31, 0xa1, 0x0c, 0xdd, 0x45, 0x38, 0x0a, 0xa1, 0xec, 0xbb, 0xb0, + 0x4c, 0x64, 0x81, 0x35, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x12, 0x2e, 0xc5, 0x22, 0x96, 0x0a, 0xfa, + 0x96, 0xf2, 0xb5, 0x90, 0x0e, 0x3e, 0x80, 0x15, 0x49, 0x26, 0x53, 0xb5, 0xae, 0x63, 0xad, 0x25, + 0x2a, 0x9e, 0xa8, 0x76, 0x1f, 0x16, 0xc4, 0x90, 0xbc, 0x9e, 0x23, 0x6b, 0x8b, 0x93, 0xb0, 0x8c, + 0xa3, 0x9f, 0xa7, 0x02, 0x1b, 0xe1, 0x4f, 0xf8, 0x95, 0x20, 0xe5, 0x81, 0x77, 0xc2, 0x63, 0x6f, + 0xc8, 0xdb, 0x2b, 0x44, 0x1c, 0xea, 0x5b, 0x9c, 0xb2, 0xf1, 0x08, 0x4b, 0xda, 0x74, 0xa6, 0xe9, + 0x0b, 0xe9, 0x6e, 0x10, 0x44, 0x5c, 0x99, 0x97, 0xda, 0x37, 0xe4, 0x01, 0x12, 0x40, 0xc9, 0xb2, + 0xac, 0x9f, 0xe5, 0xe8, 0x0e, 0x92, 0x47, 0x36, 0x32, 0x34, 0x2a, 0x3a, 0xac, 0x4e, 0xe0, 0x0f, + 0xae, 0xe4, 0xf9, 0x05, 0x02, 0x1d, 0xf8, 0x03, 0x3c, 0x40, 0x9e, 0x6f, 0xa2, 0x10, 0xbb, 0xab, + 0x2b, 0x20, 0x22, 0xdd, 0x86, 0xda, 0x68, 0x7c, 0x3c, 0xf0, 0x7a, 0x84, 0x52, 0xa0, 0x56, 0x08, + 0x84, 0x08, 0x42, 0xa5, 0xa4, 0x4d, 0x24, 0x8c, 0x22, 0x62, 0xd4, 0x24, 0x0c, 0x51, 0x90, 0x9d, + 0xf2, 0x10, 0x4f, 0x70, 0xdd, 0xc6, 0xbf, 0xad, 0x35, 0x58, 0x4a, 0x0f, 0x5a, 0xf2, 0xfa, 0xfb, + 0x50, 0x91, 0xec, 0x41, 0xd9, 0x1a, 0x9a, 0x86, 0xf5, 0x57, 0x68, 0x45, 0xba, 0xdc, 0xfa, 0x9d, + 0x39, 0x58, 0x94, 0xd0, 0x75, 0xb1, 0x22, 0xdd, 0xf1, 0x70, 0xe8, 0x86, 0x19, 0x7c, 0x27, 0xf7, + 0x7c, 0xbe, 0x93, 0x9f, 0xe2, 0x3b, 0x69, 0x65, 0x93, 0xd8, 0x56, 0x5a, 0xd9, 0x14, 0x5b, 0x40, + 0xf2, 0xbf, 0x69, 0x7a, 0x6c, 0x48, 0xf0, 0x11, 0x99, 0x38, 0xa7, 0xb8, 0x64, 0x29, 0x83, 0x4b, + 0x9a, 0x3c, 0x6e, 0x6e, 0x82, 0xc7, 0xbd, 0x06, 0xb4, 0xd7, 0x8a, 0x65, 0x97, 0x49, 0x25, 0x40, + 0x98, 0xb4, 0x5f, 0xde, 0x85, 0xf9, 0x49, 0xb6, 0x42, 0xfc, 0xab, 0x99, 0xc1, 0x54, 0xbc, 0x21, + 0xc7, 0x0b, 0xc2, 0x40, 0xae, 0x4a, 0xa6, 0xe2, 0x0d, 0xf9, 0x2e, 0x96, 0x28, 0xfc, 0x4d, 0x00, + 0xea, 0x1b, 0x25, 0x12, 0x40, 0x89, 0xe4, 0xcd, 0xf4, 0x5e, 0x98, 0xab, 0xfe, 0x40, 0x7c, 0x8c, + 0x43, 0x8e, 0x52, 0x4a, 0x15, 0x6b, 0xa2, 0xe1, 0xfa, 0x09, 0x34, 0x83, 0x11, 0xf7, 0x9d, 0xe4, + 0x78, 0xd7, 0xb0, 0xa9, 0x37, 0x9e, 0xd3, 0xd4, 0x8e, 0xc2, 0xb5, 0x1b, 0xa2, 0xae, 0xfe, 0x64, + 0x7b, 0xb4, 0xf0, 0xdc, 0x68, 0xad, 0xfe, 0x0d, 0x5a, 0x6b, 0x62, 0x65, 0xfd, 0x6d, 0xfd, 0x83, + 0x1c, 0xd4, 0x8c, 0x61, 0xb3, 0xeb, 0xb0, 0xb0, 0x7e, 0x70, 0x70, 0xb8, 0x69, 0xaf, 0x1e, 0xed, + 0xfc, 0x70, 0xd3, 0x59, 0xdf, 0x3d, 0xe8, 0x6e, 0xb6, 0xae, 0x09, 0xf0, 0xee, 0xc1, 0xfa, 0xea, + 0xae, 0xb3, 0x75, 0x60, 0xaf, 0x2b, 0x70, 0x8e, 0x2d, 0x03, 0xb3, 0x37, 0xf7, 0x0e, 0x8e, 0x36, + 0x53, 0xf0, 0x3c, 0x6b, 0x41, 0x7d, 0xcd, 0xde, 0x5c, 0x5d, 0xdf, 0x96, 0x90, 0x02, 0x5b, 0x82, + 0xd6, 0xd6, 0xd3, 0xfd, 0x8d, 0x9d, 0xfd, 0x4f, 0x9d, 0xf5, 0xd5, 0xfd, 0xf5, 0xcd, 0xdd, 0xcd, + 0x8d, 0x56, 0x91, 0x35, 0xa0, 0xba, 0xba, 0xb6, 0xba, 0xbf, 0x71, 0xb0, 0xbf, 0xb9, 0xd1, 0x2a, + 0x59, 0xbf, 0x06, 0xd5, 0x64, 0xa2, 0x35, 0x28, 0x3f, 0xdd, 0x7f, 0xb2, 0x7f, 0xf0, 0xf9, 0x7e, + 0xeb, 0x1a, 0xab, 0x42, 0x09, 0xfb, 0x6f, 0xe5, 0x18, 0xc0, 0x1c, 0xf5, 0xd9, 0xca, 0xb3, 0x0a, + 0x14, 0xd7, 0x0e, 0x8e, 0xb6, 0x5b, 0x05, 0xeb, 0xcf, 0x73, 0x70, 0x1d, 0xa7, 0xdc, 0x9f, 0x64, + 0x02, 0x77, 0xa0, 0xd6, 0x0b, 0x82, 0x91, 0x50, 0x6e, 0x92, 0x4b, 0xdc, 0x04, 0x89, 0x03, 0x4e, + 0xfc, 0xf2, 0x24, 0x08, 0x7b, 0x5c, 0xf2, 0x00, 0x40, 0xd0, 0x96, 0x80, 0x08, 0x1a, 0x94, 0x44, + 0x4c, 0x18, 0xc4, 0x02, 0x6a, 0x04, 0x23, 0x94, 0x65, 0x98, 0x3b, 0x0e, 0xb9, 0xdb, 0x3b, 0x93, + 0xa7, 0x5f, 0x7e, 0xb1, 0xb7, 0x12, 0xb5, 0xbb, 0x27, 0x68, 0x6a, 0xc0, 0xfb, 0x78, 0x04, 0x2a, + 0xf6, 0xbc, 0x84, 0xaf, 0x4b, 0xb0, 0xb8, 0x00, 0xdc, 0x63, 0xd7, 0xef, 0x07, 0x3e, 0xef, 0x4b, + 0xe9, 0x3e, 0x01, 0x58, 0x87, 0xb0, 0x3c, 0x39, 0x3f, 0xc9, 0x2f, 0xbe, 0x67, 0xf0, 0x0b, 0x12, + 0xb6, 0x3b, 0xb3, 0x49, 0xc1, 0xe0, 0x1d, 0x3f, 0x2f, 0x40, 0x51, 0x08, 0x5f, 0x33, 0xe5, 0x34, + 0x53, 0x9a, 0x2e, 0x4c, 0x79, 0x5c, 0x50, 0xbb, 0xa7, 0x5b, 0x99, 0x4c, 0x48, 0x55, 0x84, 0xe0, + 0x6d, 0xac, 0x8b, 0x43, 0xde, 0x3b, 0x97, 0x36, 0x24, 0x2a, 0xb6, 0x79, 0xef, 0x1c, 0xd5, 0x18, + 0x37, 0xa6, 0xba, 0x74, 0xde, 0xcb, 0x91, 0x1b, 0x63, 0x4d, 0x59, 0x84, 0xf5, 0xca, 0xba, 0x08, + 0x6b, 0xb5, 0xa1, 0xec, 0xf9, 0xc7, 0xc1, 0xd8, 0xef, 0xe3, 0xf1, 0xae, 0xd8, 0xea, 0x13, 0x1d, + 0x3c, 0xc8, 0x89, 0xc4, 0xfd, 0x41, 0xa7, 0xb9, 0x22, 0x00, 0x47, 0xe2, 0x06, 0x79, 0x0f, 0xaa, + 0xd1, 0x95, 0xdf, 0x33, 0xcf, 0xf0, 0x92, 0x5c, 0x1f, 0x31, 0xfb, 0x07, 0xdd, 0x2b, 0xbf, 0x87, + 0x27, 0xb6, 0x12, 0xc9, 0xbf, 0xd8, 0x07, 0x50, 0xd1, 0xa6, 0x56, 0xe2, 0xc0, 0x37, 0xcc, 0x1a, + 0xca, 0xbe, 0x4a, 0x1a, 0xad, 0x46, 0xed, 0x3c, 0x81, 0x46, 0xaa, 0xc8, 0x54, 0x43, 0x1b, 0xa4, + 0x86, 0xbe, 0x61, 0xaa, 0xa1, 0x09, 0x63, 0x97, 0xd5, 0x4c, 0xb5, 0xf4, 0xd7, 0xa1, 0xa2, 0x46, + 0x26, 0x8e, 0x93, 0x3c, 0x0a, 0x4e, 0xf7, 0x8b, 0xfd, 0xf5, 0xd6, 0x35, 0x36, 0x0f, 0xb5, 0xd5, + 0x75, 0x3c, 0xa1, 0x08, 0xc8, 0x09, 0x94, 0xc3, 0xd5, 0x6e, 0x57, 0x43, 0xf2, 0x16, 0x83, 0x96, + 0xb8, 0x5e, 0xc4, 0x88, 0xb5, 0x33, 0xe5, 0x7b, 0xb0, 0x60, 0xc0, 0x12, 0x4d, 0x4d, 0xdc, 0x47, + 0x93, 0x9a, 0x1a, 0xca, 0xe5, 0x54, 0x62, 0xad, 0xc0, 0x75, 0xf1, 0xb9, 0x79, 0xce, 0xfd, 0xb8, + 0x3b, 0x3e, 0x26, 0x57, 0x9a, 0x17, 0xf8, 0x42, 0x5e, 0xaf, 0xea, 0x92, 0xd9, 0x84, 0xf4, 0x40, + 0x2a, 0x75, 0x79, 0x5c, 0xfe, 0x8e, 0xd1, 0x03, 0x56, 0x7c, 0x80, 0xff, 0xa6, 0x94, 0xbb, 0xaa, + 0x06, 0x89, 0xb9, 0x1e, 0x6e, 0x6e, 0xda, 0xce, 0xc1, 0xfe, 0xee, 0xce, 0xbe, 0x60, 0x46, 0x62, + 0xae, 0x08, 0xd8, 0xda, 0x42, 0x48, 0xce, 0x6a, 0x41, 0xf3, 0x53, 0x1e, 0xef, 0xf8, 0x27, 0x81, + 0x9a, 0xe9, 0x5f, 0x95, 0x60, 0x5e, 0x83, 0x12, 0xe5, 0xf0, 0x9c, 0x87, 0x91, 0x17, 0xf8, 0x28, + 0xe7, 0x55, 0x6d, 0xf5, 0x29, 0x6e, 0x10, 0xaf, 0xcf, 0xfd, 0xd8, 0x8b, 0xaf, 0x9c, 0x94, 0x25, + 0xa9, 0xa9, 0xc0, 0xf2, 0xa6, 0x5a, 0x82, 0x92, 0x3b, 0xf0, 0x5c, 0xe5, 0x81, 0xa4, 0x0f, 0x01, + 0xed, 0x05, 0x83, 0x20, 0x44, 0x91, 0xae, 0x6a, 0xd3, 0x07, 0x7b, 0x04, 0x4b, 0x42, 0xb4, 0x34, + 0xcd, 0x7b, 0x78, 0x46, 0xc9, 0xa8, 0xc5, 0xfc, 0xf1, 0xf0, 0x30, 0x31, 0xf1, 0x89, 0x12, 0x71, + 0x3f, 0x89, 0x1a, 0x52, 0x20, 0xd1, 0x15, 0x48, 0x4b, 0x59, 0xf0, 0xc7, 0xc3, 0x55, 0x2c, 0xd1, + 0xf8, 0x8f, 0xe1, 0xba, 0xc0, 0xd7, 0x22, 0x8c, 0xae, 0x31, 0x8f, 0x35, 0x44, 0x63, 0x3b, 0xb2, + 0x4c, 0xd7, 0xb9, 0x09, 0x55, 0x1a, 0x95, 0xd8, 0xf1, 0x12, 0x49, 0xa7, 0x38, 0x14, 0x1e, 0x46, + 0x53, 0xce, 0xc2, 0x39, 0xba, 0x6c, 0x27, 0x9c, 0x85, 0x86, 0xbb, 0xb1, 0x32, 0xe9, 0x6e, 0x7c, + 0x0c, 0xd7, 0x8f, 0x79, 0x14, 0x3b, 0x67, 0xdc, 0xed, 0xf3, 0x10, 0x4f, 0x24, 0xb9, 0x15, 0x49, + 0x0a, 0x5f, 0x14, 0x85, 0xdb, 0x58, 0x76, 0xa4, 0x8a, 0x84, 0x2c, 0x21, 0x8e, 0x1e, 0xef, 0x3b, + 0x71, 0xe0, 0xa0, 0x88, 0x81, 0x87, 0xb8, 0x62, 0x37, 0x08, 0x7c, 0x14, 0xac, 0x0b, 0x60, 0x1a, + 0xef, 0x34, 0x74, 0x47, 0x67, 0x52, 0x4e, 0xd6, 0x78, 0x9f, 0x0a, 0x20, 0x7b, 0x05, 0xca, 0x31, + 0x8f, 0x62, 0x9f, 0x93, 0x4f, 0xa7, 0x82, 0x36, 0x7b, 0x05, 0x62, 0x6f, 0xc0, 0x1c, 0xf6, 0x11, + 0xb5, 0x5b, 0x48, 0xef, 0xf5, 0x84, 0x59, 0x7a, 0xbe, 0x2d, 0xcb, 0x84, 0xc0, 0x36, 0x0e, 0xbd, + 0xa8, 0x5d, 0x47, 0x5f, 0x26, 0xfe, 0xcd, 0x7e, 0xc3, 0x60, 0x0b, 0x8b, 0x58, 0x57, 0xdd, 0xb9, + 0x13, 0x94, 0xf6, 0x2b, 0xe1, 0x10, 0x3f, 0x28, 0x56, 0x6a, 0xad, 0xba, 0xf5, 0x21, 0x94, 0x68, + 0x75, 0x04, 0x11, 0xe2, 0xda, 0xe5, 0x24, 0x11, 0x22, 0xb4, 0x0d, 0x65, 0x9f, 0xc7, 0x17, 0x41, + 0xf8, 0x4c, 0xd9, 0x5a, 0xe5, 0xa7, 0xf5, 0x53, 0x34, 0x12, 0x68, 0x47, 0x32, 0xe9, 0x3b, 0x82, + 0x3c, 0x68, 0x7b, 0xa3, 0x33, 0x57, 0xda, 0x2d, 0x2a, 0x08, 0xe8, 0x9e, 0xb9, 0x53, 0xe4, 0x91, + 0x9f, 0xf6, 0x25, 0xbf, 0x01, 0x4d, 0xe5, 0xba, 0x8e, 0x9c, 0x01, 0x3f, 0x89, 0x25, 0xb9, 0xd7, + 0xa5, 0xdf, 0x3a, 0xda, 0xe5, 0x27, 0xb1, 0xb5, 0x07, 0x0b, 0x92, 0x20, 0x0f, 0x46, 0x5c, 0x75, + 0xfd, 0x51, 0x96, 0xcc, 0x5a, 0x7b, 0xbc, 0x98, 0xbe, 0xcc, 0xc8, 0x25, 0x9f, 0x12, 0x64, 0xad, + 0xcf, 0x80, 0x99, 0x57, 0x9d, 0x6c, 0x4f, 0x4a, 0x8e, 0xca, 0x44, 0xad, 0x3c, 0x3d, 0x5a, 0x3e, + 0xf5, 0xfa, 0x62, 0x75, 0xa2, 0x71, 0xaf, 0xa7, 0x42, 0x0a, 0x2a, 0xb6, 0xfa, 0xb4, 0xfe, 0x2c, + 0x07, 0x8b, 0xd8, 0x98, 0x92, 0xb9, 0xa5, 0x34, 0xf1, 0xad, 0x07, 0x29, 0xf6, 0xc7, 0x94, 0x2f, + 0xe8, 0xe3, 0x9b, 0x1b, 0x05, 0x8b, 0x53, 0x46, 0xc1, 0xb7, 0xa0, 0xd5, 0xe7, 0x03, 0x0f, 0xa3, + 0x4b, 0xd4, 0x75, 0x4d, 0x52, 0xf6, 0xbc, 0x82, 0x2b, 0x45, 0xe9, 0x9f, 0xe5, 0x60, 0x81, 0xa4, + 0x01, 0x54, 0x17, 0xe5, 0x42, 0x7d, 0xa2, 0x74, 0x2c, 0xc9, 0xaa, 0xe4, 0x9c, 0x92, 0x5b, 0x12, + 0xa1, 0x84, 0xbc, 0x7d, 0x4d, 0xea, 0x5e, 0x12, 0xca, 0x3e, 0x46, 0x3d, 0xc1, 0x77, 0x10, 0x98, + 0x11, 0xad, 0x92, 0xde, 0x94, 0xed, 0x6b, 0xa8, 0x44, 0xf8, 0x08, 0x5a, 0xab, 0x08, 0xa5, 0x4f, + 0x80, 0xad, 0x2d, 0x68, 0xa4, 0xba, 0x49, 0x59, 0x2e, 0xeb, 0x64, 0xb9, 0x9c, 0xf2, 0x0e, 0xe4, + 0xa7, 0xbd, 0x03, 0x7f, 0xaf, 0x08, 0x4c, 0x90, 0xd4, 0xc4, 0xae, 0x4d, 0xb8, 0xd6, 0xf2, 0x53, + 0xae, 0xb5, 0x47, 0xc0, 0x0c, 0x04, 0xe5, 0xf1, 0x2b, 0x68, 0x8f, 0x5f, 0x2b, 0xc1, 0x95, 0x0e, + 0xbf, 0x47, 0xb0, 0x24, 0x85, 0x46, 0xed, 0x4b, 0x43, 0x93, 0x14, 0xed, 0x0f, 0x23, 0xe9, 0x51, + 0xf9, 0xd4, 0xd0, 0x3c, 0xa5, 0xdc, 0x6a, 0x42, 0xa5, 0x26, 0x4b, 0x0e, 0xba, 0xd5, 0x84, 0x16, + 0x3d, 0x41, 0x05, 0x73, 0x2f, 0xa4, 0x82, 0xf2, 0x14, 0x15, 0x18, 0x86, 0x85, 0x4a, 0xda, 0xb0, + 0x60, 0x41, 0x43, 0x39, 0xcf, 0x28, 0x66, 0x80, 0x24, 0xa4, 0x9a, 0xf4, 0xa0, 0x61, 0xdc, 0xc0, + 0x3d, 0x68, 0x29, 0xed, 0x5f, 0x9b, 0x2e, 0xc8, 0x1f, 0x2e, 0x8d, 0x47, 0xeb, 0xca, 0x80, 0x91, + 0x32, 0x14, 0xd7, 0x26, 0x0c, 0xc5, 0x6f, 0xc3, 0x42, 0x24, 0x88, 0xc8, 0x19, 0xfb, 0x32, 0x78, + 0x85, 0xf7, 0x51, 0x3d, 0xa9, 0xd8, 0x2d, 0x2c, 0x78, 0x9a, 0xc0, 0xa7, 0x55, 0xfb, 0xc6, 0xb4, + 0x6a, 0xcf, 0x3e, 0x48, 0xfc, 0x4c, 0xd1, 0x99, 0x37, 0xc4, 0x8b, 0x3b, 0x09, 0xf4, 0x90, 0x0b, + 0xdc, 0x3d, 0xf3, 0x86, 0xb6, 0x72, 0x6a, 0x8a, 0x0f, 0xeb, 0xbf, 0xe6, 0xa0, 0x25, 0xe8, 0x20, + 0x45, 0xe7, 0xbf, 0x06, 0x78, 0x22, 0x5f, 0x92, 0xcc, 0x6b, 0x02, 0x57, 0x51, 0xf9, 0x87, 0x80, + 0x64, 0xeb, 0x08, 0x5d, 0x4c, 0x12, 0x79, 0x3b, 0x4d, 0xe4, 0x09, 0x23, 0xdb, 0xbe, 0x46, 0x42, + 0xb6, 0x80, 0x64, 0xf9, 0xf7, 0x8a, 0x19, 0xfe, 0x3d, 0xe3, 0x28, 0x6c, 0x03, 0x3c, 0xe1, 0x57, + 0xbb, 0x41, 0x0f, 0xb5, 0xa0, 0x5b, 0x00, 0x82, 0x20, 0x4f, 0xdc, 0xa1, 0x27, 0x2d, 0x18, 0x25, + 0xbb, 0xfa, 0x8c, 0x5f, 0x6d, 0x21, 0x40, 0xec, 0x86, 0x28, 0x4e, 0xce, 0x43, 0xc9, 0xae, 0x3c, + 0xe3, 0x57, 0x74, 0x18, 0x1c, 0x68, 0x3c, 0xe1, 0x57, 0x1b, 0x9c, 0xc4, 0xb5, 0x20, 0x14, 0x94, + 0x10, 0xba, 0x17, 0x42, 0x3e, 0x4b, 0xf9, 0xe6, 0x6a, 0xa1, 0x7b, 0xf1, 0x84, 0x5f, 0x29, 0x3f, + 0x61, 0x59, 0x94, 0x0f, 0x82, 0x9e, 0xbc, 0x81, 0x54, 0x94, 0x41, 0x32, 0x28, 0x7b, 0xee, 0x19, + 0xfe, 0x6d, 0xfd, 0x69, 0x0e, 0x1a, 0x62, 0xfc, 0xc8, 0xe0, 0xc4, 0xba, 0xab, 0x60, 0x95, 0x5c, + 0x12, 0xac, 0xf2, 0x58, 0xf2, 0x07, 0xe2, 0x96, 0xf9, 0xd9, 0xdc, 0x12, 0x17, 0x98, 0x58, 0xe5, + 0x7b, 0x50, 0xa5, 0xb3, 0x25, 0x0e, 0x6b, 0x21, 0xb5, 0x4b, 0xa9, 0x09, 0xd9, 0x15, 0x44, 0x7b, + 0x42, 0xbe, 0x71, 0xc3, 0x00, 0x45, 0x4b, 0x5c, 0x0d, 0xb5, 0xe9, 0x29, 0x63, 0x1b, 0x4a, 0x59, + 0x6e, 0xd6, 0xa7, 0x50, 0x33, 0x68, 0x8a, 0x7d, 0x9f, 0x1c, 0xd4, 0x34, 0x78, 0x22, 0xc0, 0x34, + 0xd1, 0xa4, 0x66, 0xbf, 0x7d, 0xcd, 0x6e, 0xf4, 0x4c, 0xc0, 0xda, 0x1c, 0x14, 0x45, 0x25, 0xeb, + 0x13, 0x58, 0x30, 0x9a, 0x25, 0x8d, 0x2f, 0x6b, 0x4c, 0xb9, 0xac, 0x31, 0xfd, 0xf3, 0x1c, 0x2c, + 0xc9, 0xda, 0x18, 0xd8, 0xe4, 0x89, 0xeb, 0x7a, 0x2f, 0x3a, 0x65, 0xbf, 0x06, 0x0d, 0xd1, 0xba, + 0x13, 0xf2, 0x53, 0x2f, 0x8a, 0xb9, 0xb2, 0xec, 0x67, 0x1c, 0x0e, 0xc1, 0xb5, 0x05, 0xaa, 0x2d, + 0x31, 0xd9, 0x27, 0x50, 0xc3, 0xaa, 0xa4, 0x93, 0xca, 0x6d, 0x69, 0x4f, 0x57, 0xa4, 0xa1, 0x6e, + 0x5f, 0xb3, 0x21, 0xd2, 0x5f, 0x6b, 0x55, 0x28, 0xc7, 0xa1, 0x77, 0x7a, 0xca, 0x43, 0x6b, 0x59, + 0x0f, 0x4d, 0x9c, 0x34, 0xde, 0x8d, 0xf9, 0x48, 0x08, 0x41, 0xd6, 0x7f, 0xcf, 0x41, 0x4d, 0x9e, + 0x9d, 0x6f, 0x6d, 0xce, 0xef, 0x18, 0x91, 0x79, 0xa4, 0x7e, 0x26, 0x81, 0x78, 0x77, 0x61, 0x7e, + 0x28, 0x04, 0x22, 0x21, 0xb0, 0xa7, 0x6c, 0xf9, 0x4d, 0x05, 0x96, 0xf2, 0xc8, 0x03, 0x58, 0x44, + 0xf1, 0x24, 0x72, 0x62, 0x6f, 0xe0, 0xa8, 0x42, 0x19, 0x05, 0xb7, 0x40, 0x45, 0x47, 0xde, 0x60, + 0x4f, 0x16, 0x88, 0x5b, 0x3a, 0x8a, 0xdd, 0x53, 0x2e, 0x45, 0x5f, 0xfa, 0xb0, 0xda, 0xb0, 0x3c, + 0x21, 0xab, 0x2b, 0x3d, 0xe3, 0x1f, 0x36, 0x60, 0x65, 0xaa, 0x48, 0xea, 0x1b, 0xda, 0x86, 0x3d, + 0xf0, 0x86, 0xc7, 0x81, 0x36, 0x37, 0xe5, 0x0c, 0x1b, 0xf6, 0xae, 0x28, 0x51, 0xe6, 0x26, 0x0e, + 0xd7, 0x15, 0x41, 0xa0, 0xbd, 0x48, 0x8b, 0xf3, 0x79, 0x14, 0x36, 0xdf, 0x4b, 0x33, 0xaa, 0xc9, + 0xee, 0x14, 0xdc, 0xbc, 0xfe, 0x16, 0x47, 0x53, 0xb0, 0x88, 0x9d, 0x40, 0x5b, 0xd3, 0x9d, 0x94, + 0x8f, 0x0c, 0xdd, 0x44, 0xf4, 0xf4, 0xce, 0x0b, 0x7a, 0x4a, 0x19, 0x22, 0xec, 0x65, 0x45, 0xae, + 0xd4, 0x98, 0xee, 0xe7, 0x1c, 0x5e, 0x55, 0xfd, 0xa0, 0xac, 0x33, 0xdd, 0x5b, 0xf1, 0xa5, 0xe6, + 0x85, 0x06, 0x96, 0x74, 0x97, 0x37, 0x65, 0xc3, 0xba, 0xc8, 0xec, 0xf7, 0x0c, 0x96, 0x2f, 0x5c, + 0x2f, 0x56, 0xf3, 0x33, 0xd4, 0xa2, 0x12, 0xf6, 0xf7, 0xf8, 0x05, 0xfd, 0x7d, 0x4e, 0x95, 0x53, + 0xd2, 0xdf, 0xd2, 0xc5, 0x34, 0x30, 0xea, 0xfc, 0xe7, 0x3c, 0x34, 0xd3, 0xad, 0x88, 0x43, 0x2d, + 0xf9, 0x90, 0x92, 0x27, 0xa4, 0x3c, 0x2e, 0xcd, 0xa0, 0xfb, 0x24, 0x47, 0x4c, 0x1b, 0x68, 0xf3, + 0x19, 0x06, 0x5a, 0xd3, 0x2e, 0x5a, 0x78, 0x91, 0xef, 0xa7, 0xf8, 0x52, 0xbe, 0x9f, 0x52, 0x96, + 0xef, 0x67, 0xb6, 0xc3, 0x60, 0xee, 0x5b, 0x39, 0x0c, 0xca, 0xb3, 0x1d, 0x06, 0x9d, 0xbf, 0xce, + 0x01, 0x9b, 0xa6, 0x54, 0xf6, 0x29, 0xd9, 0xa2, 0x7d, 0x3e, 0x90, 0x5c, 0xec, 0xdd, 0x97, 0xa3, + 0x76, 0xb5, 0x41, 0xaa, 0x36, 0x7b, 0x08, 0x8b, 0x66, 0xdc, 0xac, 0xa9, 0xaa, 0x34, 0x6c, 0x66, + 0x16, 0x25, 0x0a, 0xad, 0xe1, 0xf8, 0x2a, 0xbe, 0xd0, 0xf1, 0x55, 0x7a, 0xa1, 0xe3, 0x6b, 0x2e, + 0xed, 0xf8, 0xea, 0xfc, 0x9d, 0x1c, 0x2c, 0x66, 0x10, 0xd5, 0x2f, 0x6f, 0xce, 0x82, 0x16, 0x52, + 0x2c, 0x26, 0x2f, 0x69, 0xc1, 0xe0, 0x2e, 0x9d, 0xaf, 0xa0, 0x91, 0x3a, 0x44, 0xbf, 0xbc, 0xee, + 0x27, 0x15, 0x2d, 0x22, 0x65, 0x53, 0xd1, 0xea, 0xfc, 0x65, 0x1e, 0xd8, 0xf4, 0x39, 0xfe, 0x55, + 0x0e, 0x61, 0x7a, 0x91, 0x0a, 0xd3, 0x8b, 0xf4, 0xff, 0xee, 0x5e, 0x79, 0x1b, 0x16, 0x64, 0xac, + 0xbf, 0xe1, 0x78, 0x20, 0x42, 0x69, 0xe9, 0x02, 0x35, 0x8a, 0x0f, 0x27, 0x7d, 0x8e, 0x95, 0x54, + 0x78, 0xb3, 0x71, 0xb1, 0xa6, 0x5d, 0x8f, 0x56, 0x07, 0xda, 0x72, 0x69, 0xa6, 0x4d, 0x75, 0xbf, + 0x57, 0xd4, 0x5a, 0x32, 0x16, 0x4a, 0xa1, 0xf8, 0xbb, 0x50, 0x37, 0x2f, 0x1b, 0xb9, 0x0f, 0x13, + 0x1e, 0x27, 0x21, 0x0e, 0x07, 0xc6, 0x69, 0x5d, 0x07, 0xf2, 0x23, 0xf4, 0x75, 0x35, 0x92, 0x20, + 0x9e, 0x63, 0x78, 0x46, 0xe1, 0x28, 0xb5, 0xf9, 0xff, 0x1f, 0x34, 0xd3, 0x76, 0x2b, 0x29, 0xea, + 0x65, 0x49, 0x87, 0xa2, 0x76, 0xca, 0x90, 0xc5, 0x7e, 0x03, 0x5a, 0x93, 0x76, 0x2f, 0x19, 0x7b, + 0x39, 0xa3, 0xfe, 0xbc, 0x97, 0x36, 0x85, 0xb1, 0x6d, 0x58, 0xca, 0xba, 0x6e, 0x71, 0x57, 0x66, + 0xab, 0x05, 0x6c, 0xfa, 0x4a, 0x65, 0x1f, 0x49, 0xf3, 0x66, 0x29, 0xcb, 0x11, 0x63, 0x2c, 0xf6, + 0x03, 0xfa, 0xcf, 0x30, 0x74, 0x9e, 0x03, 0x24, 0x30, 0xd6, 0x82, 0xfa, 0xc1, 0xe1, 0xe6, 0xbe, + 0xb3, 0xbe, 0xbd, 0xba, 0xbf, 0xbf, 0xb9, 0xdb, 0xba, 0xc6, 0x18, 0x34, 0xd1, 0x83, 0xb2, 0xa1, + 0x61, 0x39, 0x01, 0x93, 0xb6, 0x5f, 0x05, 0xcb, 0xb3, 0x25, 0x68, 0xed, 0xec, 0x4f, 0x40, 0x0b, + 0xac, 0x0d, 0x4b, 0x87, 0x9b, 0xe4, 0x74, 0x49, 0xb5, 0x5b, 0x14, 0x22, 0x9c, 0x9c, 0xae, 0x10, + 0xe1, 0x28, 0x53, 0x44, 0x52, 0x9f, 0x92, 0x6c, 0x7e, 0x3f, 0x07, 0xd7, 0x27, 0x0a, 0x92, 0xf8, + 0x5f, 0x92, 0x6b, 0xd2, 0x12, 0x4d, 0x1d, 0x81, 0x8a, 0x86, 0xdf, 0x86, 0x05, 0xad, 0xea, 0x4d, + 0xf0, 0xa5, 0x96, 0x2e, 0x50, 0xc8, 0x0f, 0x61, 0xd1, 0xd0, 0x18, 0x27, 0x4e, 0x28, 0x33, 0x8a, + 0x64, 0x05, 0x6b, 0x45, 0xc7, 0x59, 0x4e, 0x8c, 0xba, 0x4f, 0xe9, 0x27, 0x66, 0x41, 0x62, 0xfd, + 0x4d, 0x8f, 0x57, 0x7d, 0x0a, 0x55, 0x3e, 0x45, 0x08, 0xe9, 0xd1, 0x9a, 0x1b, 0xae, 0xba, 0xff, + 0xc3, 0x39, 0x60, 0x9f, 0x8d, 0x79, 0x78, 0x85, 0xf1, 0xbd, 0xd1, 0x8b, 0x02, 0x5e, 0x94, 0x5a, + 0x94, 0x7f, 0xa9, 0x18, 0xfe, 0xac, 0x18, 0xfa, 0xe2, 0x8b, 0x63, 0xe8, 0x4b, 0x2f, 0x8a, 0xa1, + 0x7f, 0x1d, 0x1a, 0xde, 0xa9, 0x1f, 0x08, 0x06, 0x24, 0x64, 0x93, 0xa8, 0x3d, 0x77, 0xa7, 0x70, + 0xaf, 0x6e, 0xd7, 0x25, 0x50, 0x48, 0x26, 0x11, 0xfb, 0x24, 0x41, 0xe2, 0xfd, 0x53, 0xcc, 0xf7, + 0x30, 0x59, 0xcf, 0x66, 0xff, 0x94, 0x4b, 0x2d, 0x10, 0xed, 0x22, 0xaa, 0xb2, 0x80, 0x47, 0xec, + 0x0d, 0x68, 0x46, 0xc1, 0x58, 0x88, 0x7a, 0x6a, 0x19, 0xc8, 0x3e, 0x5c, 0x27, 0xe8, 0xa1, 0x72, + 0x06, 0x2c, 0x8e, 0x23, 0xee, 0x0c, 0xbd, 0x28, 0x12, 0x17, 0x74, 0x2f, 0xf0, 0xe3, 0x30, 0x18, + 0x48, 0x93, 0xef, 0xc2, 0x38, 0xe2, 0x7b, 0x54, 0xb2, 0x4e, 0x05, 0xec, 0xfd, 0x64, 0x48, 0x23, + 0xd7, 0x0b, 0xa3, 0x36, 0xe0, 0x90, 0xd4, 0x4c, 0x51, 0xa2, 0x72, 0xbd, 0x50, 0x8f, 0x45, 0x7c, + 0x44, 0x13, 0xb1, 0xfd, 0xb5, 0xc9, 0xd8, 0xfe, 0x9f, 0x64, 0xc7, 0xf6, 0x37, 0xb0, 0xe9, 0x47, + 0xb2, 0xe9, 0xe9, 0x2d, 0xfe, 0x46, 0x21, 0xfe, 0xd3, 0x29, 0x0b, 0xcd, 0x6f, 0x92, 0xb2, 0x30, + 0x9f, 0x95, 0xb2, 0xf0, 0x1e, 0xd4, 0x30, 0x98, 0xdc, 0x39, 0xf3, 0xfc, 0x58, 0x99, 0xb0, 0x5b, + 0x66, 0xb4, 0xf9, 0xb6, 0x50, 0xa6, 0x21, 0x54, 0x7f, 0x46, 0xd3, 0xd9, 0x03, 0x0b, 0xbf, 0xc2, + 0xec, 0x01, 0x19, 0xf4, 0xfe, 0x00, 0x2a, 0x6a, 0x9f, 0x18, 0x83, 0xe2, 0x49, 0x18, 0x0c, 0x95, + 0x69, 0x4f, 0xfc, 0xcd, 0x9a, 0x90, 0x8f, 0x03, 0x59, 0x39, 0x1f, 0x07, 0xd6, 0x6f, 0x41, 0xcd, + 0x20, 0x35, 0xf6, 0x1a, 0x19, 0x11, 0x84, 0xb4, 0x2c, 0xb5, 0x64, 0x5a, 0xc5, 0xaa, 0x84, 0xee, + 0xf4, 0x05, 0xbf, 0xe9, 0x7b, 0x21, 0xc7, 0x3c, 0x1f, 0x27, 0xe4, 0xe7, 0x3c, 0x8c, 0x94, 0xa9, + 0xb5, 0xa5, 0x0b, 0x6c, 0x82, 0x5b, 0x7f, 0x13, 0x16, 0x53, 0x7b, 0x2b, 0x59, 0xc4, 0x1b, 0x30, + 0x87, 0xeb, 0xa6, 0x5c, 0x61, 0xe9, 0x28, 0x7e, 0x59, 0x86, 0x09, 0x9c, 0x64, 0x25, 0x76, 0x46, + 0x61, 0x70, 0x8c, 0x9d, 0xe4, 0xec, 0x9a, 0x84, 0x1d, 0x86, 0xc1, 0xb1, 0xf5, 0xf3, 0x02, 0x14, + 0xb6, 0x83, 0x91, 0x19, 0x61, 0x91, 0x9b, 0x8a, 0xb0, 0x90, 0x2a, 0x80, 0xa3, 0x45, 0x7c, 0x29, + 0xb5, 0xa1, 0x7d, 0x54, 0x89, 0xf9, 0xf7, 0xa0, 0x29, 0xf8, 0x44, 0x1c, 0x08, 0x1d, 0xea, 0xc2, + 0x0d, 0x29, 0xa6, 0xbf, 0x40, 0x87, 0xcf, 0x1d, 0xc6, 0x47, 0xc1, 0x16, 0xc1, 0xd9, 0x12, 0x14, + 0xb4, 0x00, 0x8b, 0xc5, 0xe2, 0x53, 0x28, 0xd7, 0x18, 0xdd, 0x76, 0x25, 0x7d, 0x3d, 0xf2, 0x8b, + 0xbd, 0x0b, 0x8b, 0xe9, 0x76, 0x89, 0x15, 0x49, 0x89, 0xc4, 0x6c, 0x18, 0x79, 0xd2, 0x0d, 0x10, + 0x7c, 0x84, 0x70, 0xa4, 0x5b, 0xf6, 0x84, 0x73, 0x2c, 0x32, 0x98, 0x5e, 0x25, 0xc5, 0xf4, 0x6e, + 0x43, 0x2d, 0x1e, 0x9c, 0x3b, 0x23, 0xf7, 0x6a, 0x10, 0xb8, 0x7d, 0x79, 0xbe, 0x21, 0x1e, 0x9c, + 0x1f, 0x12, 0x84, 0x3d, 0x04, 0x18, 0x8e, 0x46, 0xf2, 0xec, 0xa1, 0xb9, 0x31, 0x21, 0xe5, 0xbd, + 0xc3, 0x43, 0x22, 0x39, 0xbb, 0x3a, 0x1c, 0x8d, 0xe8, 0x4f, 0xb6, 0x01, 0xcd, 0xcc, 0x5c, 0x9c, + 0x5b, 0x2a, 0x18, 0x2b, 0x18, 0x3d, 0xc8, 0x38, 0x9c, 0x8d, 0x9e, 0x09, 0xeb, 0xfc, 0x06, 0xb0, + 0x5f, 0x30, 0x23, 0xe6, 0x08, 0xaa, 0x7a, 0x7c, 0x66, 0x42, 0x09, 0x86, 0x57, 0xd6, 0x52, 0x09, + 0x25, 0xab, 0xfd, 0x7e, 0x28, 0xf8, 0x22, 0x5d, 0x98, 0x9a, 0xe5, 0x83, 0x71, 0x63, 0xae, 0x12, + 0xdf, 0xb7, 0xfe, 0x22, 0x07, 0x25, 0xca, 0x6e, 0x79, 0x13, 0xe6, 0x09, 0x5f, 0x47, 0xab, 0x48, + 0x0f, 0x11, 0xdd, 0xbb, 0x47, 0x32, 0x50, 0x45, 0x1c, 0x0b, 0x23, 0x33, 0x2f, 0xaf, 0x77, 0xde, + 0xc8, 0xce, 0xbb, 0x0d, 0x55, 0xdd, 0xb5, 0x41, 0x3a, 0x15, 0xd5, 0x33, 0x7b, 0x15, 0x8a, 0x67, + 0xc1, 0x48, 0xe9, 0xe2, 0x90, 0xac, 0xa4, 0x8d, 0xf0, 0x64, 0x2c, 0xa2, 0x0f, 0x1a, 0xbc, 0xd4, + 0x21, 0x75, 0x27, 0x48, 0x06, 0xd3, 0x73, 0x9c, 0xcb, 0x98, 0xe3, 0x53, 0x98, 0x17, 0x7c, 0xc0, + 0xf0, 0xd4, 0xce, 0xbe, 0x34, 0xdf, 0x12, 0x12, 0x5e, 0x6f, 0x30, 0xee, 0x73, 0xd3, 0x12, 0x82, + 0xa1, 0x13, 0x12, 0xae, 0xd4, 0x03, 0xeb, 0x0f, 0x73, 0xc4, 0x5f, 0x44, 0xbb, 0xec, 0x1e, 0x14, + 0xc5, 0xfd, 0x36, 0x61, 0xa9, 0xd3, 0x71, 0xae, 0x02, 0xcf, 0x46, 0x0c, 0x4c, 0x67, 0x1d, 0x0f, + 0xd3, 0xad, 0x37, 0xec, 0x9a, 0x3f, 0x1e, 0x6a, 0x63, 0xc2, 0x77, 0xd4, 0xb4, 0x26, 0x14, 0x71, + 0x9a, 0xbd, 0x3e, 0xa6, 0x0f, 0x8c, 0x18, 0x8c, 0x62, 0xea, 0xc6, 0x54, 0x52, 0x60, 0xff, 0x94, + 0x1b, 0xb1, 0x17, 0x7f, 0x9c, 0x87, 0x46, 0x6a, 0x44, 0x18, 0x84, 0x22, 0x2e, 0x00, 0xb2, 0x02, + 0xcb, 0xfd, 0x06, 0x01, 0x92, 0x82, 0xba, 0xb1, 0x4e, 0xf9, 0xd4, 0x3a, 0x69, 0x9f, 0x74, 0xc1, + 0xf4, 0x49, 0x3f, 0x82, 0x6a, 0x92, 0x91, 0x99, 0x1e, 0x92, 0xe8, 0x4f, 0x45, 0xfb, 0x26, 0x48, + 0x89, 0x17, 0xbb, 0x64, 0x7a, 0xb1, 0xbf, 0x6f, 0x38, 0x3d, 0xe7, 0xb0, 0x19, 0x2b, 0x6b, 0x45, + 0x7f, 0x35, 0x41, 0x11, 0x9f, 0x40, 0xcd, 0x18, 0xbc, 0xe9, 0xdc, 0xcc, 0xa5, 0x9c, 0x9b, 0x3a, + 0x2e, 0x3f, 0x9f, 0xc4, 0xe5, 0x5b, 0xbf, 0x93, 0x87, 0x86, 0x38, 0x5f, 0x9e, 0x7f, 0x7a, 0x18, + 0x0c, 0xbc, 0x1e, 0x5a, 0x85, 0xf5, 0x09, 0x93, 0x82, 0x96, 0x3a, 0x67, 0xf2, 0x88, 0x91, 0x9c, + 0x65, 0xa6, 0x1f, 0x11, 0x93, 0xd6, 0xe9, 0x47, 0x16, 0x34, 0x04, 0x63, 0x3c, 0x76, 0x23, 0x6e, + 0xe4, 0x8b, 0xda, 0xb5, 0x13, 0xce, 0xd7, 0xdc, 0x88, 0x38, 0xe4, 0xbb, 0xb0, 0x28, 0x70, 0x30, + 0xf3, 0x62, 0xe8, 0x0d, 0x06, 0x1e, 0x61, 0x92, 0xa9, 0xa1, 0x75, 0xc2, 0xb9, 0xed, 0xc6, 0x7c, + 0x4f, 0x14, 0xc8, 0xf4, 0xd2, 0x4a, 0xdf, 0x8b, 0xdc, 0xe3, 0x24, 0x54, 0x48, 0x7f, 0xa3, 0x2f, + 0xc7, 0xbd, 0x34, 0x7c, 0x39, 0x94, 0x82, 0x55, 0x1b, 0xba, 0x97, 0xda, 0x97, 0x33, 0x41, 0x49, + 0xe5, 0x49, 0x4a, 0xb2, 0xfe, 0x5b, 0x1e, 0x6a, 0x06, 0x59, 0xbe, 0xcc, 0xed, 0x7a, 0x6b, 0xca, + 0x8a, 0x5f, 0x35, 0x0d, 0xf6, 0xaf, 0xa7, 0xbb, 0x44, 0x97, 0x2f, 0x25, 0xb2, 0x1a, 0x04, 0x7c, + 0x13, 0xaa, 0xe2, 0xd4, 0xbd, 0x87, 0x46, 0x31, 0x99, 0x86, 0x8d, 0x80, 0xc3, 0xf1, 0xb1, 0x2a, + 0x7c, 0x8c, 0x85, 0xa5, 0xa4, 0xf0, 0xb1, 0x28, 0x7c, 0x5e, 0x7c, 0xe0, 0x87, 0x50, 0x97, 0xad, + 0xe2, 0x9e, 0xe2, 0x74, 0x93, 0x53, 0x9f, 0xda, 0x6f, 0xbb, 0x46, 0xdd, 0xd1, 0xe6, 0xcb, 0x8a, + 0x8f, 0x55, 0xc5, 0xca, 0x8b, 0x2a, 0x3e, 0xa6, 0x0f, 0x6b, 0x4b, 0x87, 0x5c, 0x62, 0xb8, 0x81, + 0xe2, 0x63, 0x0f, 0x61, 0x51, 0xb1, 0xab, 0xb1, 0xef, 0xfa, 0x7e, 0x30, 0xf6, 0x7b, 0x5c, 0x05, + 0xec, 0x33, 0x59, 0xf4, 0x34, 0x29, 0xb1, 0xfa, 0x3a, 0xa3, 0x8b, 0xc2, 0x16, 0xee, 0x43, 0x89, + 0xe4, 0x72, 0x12, 0x3e, 0xb2, 0x19, 0x17, 0xa1, 0xb0, 0x7b, 0x50, 0x22, 0xf1, 0x3c, 0x3f, 0x93, + 0xd9, 0x10, 0x82, 0xf5, 0x00, 0xe6, 0x51, 0xc4, 0x34, 0x38, 0xee, 0xf3, 0xa4, 0x12, 0x6b, 0x09, + 0xd8, 0x3e, 0x1d, 0x22, 0x33, 0x9c, 0xe6, 0x7f, 0x15, 0xa0, 0x66, 0x80, 0x05, 0x5b, 0xc4, 0x00, + 0x0c, 0xa7, 0xef, 0xb9, 0x43, 0xae, 0x7c, 0x0f, 0x0d, 0xbb, 0x81, 0xd0, 0x0d, 0x09, 0x14, 0x97, + 0x82, 0x7b, 0x7e, 0xea, 0x04, 0xe3, 0xd8, 0xe9, 0xf3, 0xd3, 0x90, 0x73, 0x29, 0x2c, 0xd5, 0xdd, + 0xf3, 0xd3, 0x83, 0x71, 0xbc, 0x81, 0x30, 0x81, 0x25, 0x88, 0xda, 0xc0, 0x92, 0x31, 0x03, 0x43, + 0xf7, 0x32, 0xc1, 0x92, 0x81, 0x2b, 0xb4, 0x44, 0x45, 0x1d, 0xb8, 0x42, 0x6a, 0xcb, 0x24, 0x27, + 0x2f, 0x4d, 0x73, 0xf2, 0xf7, 0x61, 0x99, 0x38, 0xb9, 0xe4, 0x11, 0xce, 0x04, 0x49, 0x2d, 0x61, + 0xa9, 0x9c, 0xa4, 0x21, 0x7f, 0xb5, 0xc4, 0x0c, 0xd4, 0xf9, 0x88, 0xbc, 0x9f, 0xd2, 0x89, 0xca, + 0xd9, 0x62, 0x66, 0xb2, 0xf1, 0xae, 0xf7, 0x53, 0x2e, 0x30, 0xd1, 0x31, 0x6a, 0x62, 0xca, 0x30, + 0xd4, 0xa1, 0xe7, 0x4f, 0x62, 0xba, 0x97, 0x69, 0xcc, 0xaa, 0xc4, 0x74, 0x2f, 0x4d, 0xcc, 0x0f, + 0x60, 0x65, 0xc8, 0xfb, 0x9e, 0x9b, 0x6e, 0xd6, 0x49, 0x24, 0x88, 0x25, 0x2a, 0x36, 0xea, 0x74, + 0x49, 0x83, 0x14, 0xab, 0xf1, 0xd3, 0x60, 0x78, 0xec, 0xd1, 0xe5, 0x49, 0xae, 0xda, 0xa2, 0xdd, + 0xf4, 0xc7, 0xc3, 0x1f, 0x21, 0x58, 0x54, 0x89, 0xac, 0x06, 0xd4, 0xba, 0x71, 0x30, 0x52, 0xdb, + 0xdc, 0x84, 0x3a, 0x7d, 0xca, 0x74, 0x8c, 0x9b, 0x70, 0x03, 0x69, 0xf3, 0x28, 0x18, 0x05, 0x83, + 0xe0, 0xf4, 0x2a, 0x65, 0x50, 0xfa, 0x1f, 0x39, 0x58, 0x4c, 0x95, 0xca, 0x73, 0xfe, 0x3e, 0x1d, + 0x2c, 0x1d, 0x53, 0x4f, 0xe4, 0xbc, 0x60, 0x5c, 0x3e, 0x84, 0x48, 0xa7, 0x4a, 0xc5, 0xd9, 0xaf, + 0x26, 0xb9, 0xa0, 0xaa, 0x22, 0xd1, 0x76, 0x7b, 0x9a, 0xb6, 0x65, 0x7d, 0x95, 0x25, 0xaa, 0x9a, + 0xf8, 0xff, 0x65, 0xa8, 0x70, 0x5f, 0x4e, 0xb9, 0x90, 0x0e, 0x86, 0x34, 0x8d, 0x4f, 0x6a, 0x04, + 0x89, 0x45, 0x2a, 0xb2, 0xfe, 0x4d, 0x0e, 0x20, 0x19, 0x1d, 0x86, 0x63, 0xea, 0x0b, 0x94, 0x9e, + 0x59, 0x31, 0x2e, 0xcb, 0xd7, 0xa0, 0xae, 0x23, 0xc6, 0x92, 0x2b, 0xb9, 0xa6, 0x60, 0xe2, 0x5e, + 0xbe, 0x0b, 0xf3, 0xa7, 0x83, 0xe0, 0x18, 0x45, 0x27, 0x79, 0x81, 0x52, 0x52, 0x4a, 0x93, 0xc0, + 0xea, 0x5a, 0x4c, 0x2e, 0xf0, 0x62, 0x66, 0x50, 0x99, 0x79, 0x1d, 0x5b, 0xbf, 0x9b, 0xd7, 0xa1, + 0x33, 0xc9, 0x4a, 0x3c, 0x5f, 0xcf, 0xf8, 0x36, 0x1e, 0xd8, 0xe7, 0x79, 0x1e, 0x3e, 0x81, 0x66, + 0x48, 0xdc, 0x51, 0xb1, 0xce, 0xe2, 0x73, 0x58, 0x67, 0x23, 0x4c, 0x5d, 0xb9, 0x6f, 0x41, 0xcb, + 0xed, 0x9f, 0xf3, 0x30, 0xf6, 0xd0, 0x58, 0x8b, 0x82, 0x9a, 0x0c, 0x56, 0x31, 0xe0, 0x28, 0x11, + 0xdd, 0x85, 0x79, 0x99, 0x22, 0xa4, 0x31, 0xe5, 0xa3, 0x03, 0x09, 0x58, 0x20, 0x5a, 0xff, 0x5e, + 0xc5, 0xea, 0xa4, 0x77, 0xf7, 0xf9, 0xab, 0x62, 0xce, 0x30, 0x3f, 0xed, 0x5b, 0x91, 0x84, 0x24, + 0x6d, 0xc0, 0x92, 0x1f, 0x11, 0x50, 0x5a, 0x80, 0xd3, 0xcb, 0x5a, 0x7c, 0x99, 0x65, 0xb5, 0xfe, + 0x34, 0x07, 0xe5, 0xed, 0x60, 0x24, 0xf4, 0x72, 0x21, 0xcf, 0xe1, 0x31, 0xd1, 0xe9, 0x79, 0x73, + 0xe2, 0x73, 0xa7, 0xff, 0xfc, 0xb0, 0xfc, 0x4c, 0x79, 0xa3, 0x91, 0x96, 0x37, 0xbe, 0x0f, 0x37, + 0xd1, 0x1b, 0x11, 0x06, 0xa3, 0x20, 0x14, 0x47, 0xd5, 0x1d, 0x90, 0xdc, 0x11, 0xf8, 0xf1, 0x99, + 0xe2, 0x9d, 0x37, 0x4e, 0x38, 0x3f, 0x34, 0x30, 0xf6, 0x34, 0x02, 0xe6, 0x9a, 0x0c, 0xe2, 0x73, + 0x87, 0x54, 0x45, 0x29, 0x18, 0x11, 0x47, 0x9d, 0x17, 0x05, 0x9b, 0x08, 0x47, 0xd1, 0xc8, 0xfa, + 0x08, 0xaa, 0xda, 0xea, 0xc0, 0xde, 0x86, 0xea, 0x59, 0x30, 0x92, 0xa6, 0x89, 0x5c, 0x2a, 0x75, + 0x41, 0xce, 0xda, 0xae, 0x9c, 0xd1, 0x1f, 0x91, 0xf5, 0xf3, 0x32, 0x94, 0x77, 0xfc, 0xf3, 0xc0, + 0xeb, 0x61, 0xb4, 0xcf, 0x90, 0x0f, 0x03, 0x95, 0xa7, 0x28, 0xfe, 0x46, 0x8f, 0x7e, 0xf2, 0x74, + 0x40, 0x41, 0x7a, 0xf4, 0xf5, 0xa3, 0x01, 0xd7, 0x61, 0x2e, 0x34, 0x73, 0xff, 0x4b, 0x21, 0xc6, + 0x1f, 0x6a, 0xa5, 0xad, 0x64, 0xe4, 0x79, 0x8a, 0xb6, 0x28, 0x27, 0x1d, 0x97, 0x8c, 0x72, 0x4f, + 0xaa, 0x08, 0xc1, 0x05, 0x7b, 0x05, 0xca, 0x32, 0x53, 0x80, 0xe2, 0xae, 0x29, 0x60, 0x50, 0x82, + 0x90, 0x1a, 0x42, 0x4e, 0xde, 0x24, 0x2d, 0x51, 0x09, 0x3d, 0x5d, 0x02, 0x37, 0x04, 0xad, 0xdd, + 0x86, 0x1a, 0xe1, 0x13, 0x4a, 0x45, 0xc6, 0xe7, 0x20, 0x08, 0x11, 0x32, 0x9e, 0xd0, 0xa8, 0x66, + 0x3e, 0xa1, 0x81, 0xe1, 0x5c, 0x9a, 0xcb, 0xd2, 0x14, 0x81, 0x1e, 0x4e, 0x30, 0xe0, 0xea, 0xfd, + 0x18, 0xa9, 0xdc, 0x53, 0x1a, 0x95, 0x52, 0xee, 0x5f, 0x87, 0xc6, 0x89, 0x3b, 0x18, 0x1c, 0xbb, + 0xbd, 0x67, 0xa4, 0x93, 0xd6, 0xc9, 0x0c, 0xa7, 0x80, 0xa8, 0x94, 0xde, 0x86, 0x9a, 0xb1, 0xcb, + 0x18, 0x7c, 0x53, 0xb4, 0x21, 0xd9, 0xdf, 0x49, 0x53, 0x53, 0xf3, 0x25, 0x4c, 0x4d, 0x46, 0x10, + 0xd2, 0x7c, 0x3a, 0x08, 0xe9, 0x26, 0x72, 0x53, 0x19, 0xa8, 0xd2, 0xa2, 0x2c, 0x7d, 0xb7, 0xdf, + 0xc7, 0x40, 0x15, 0x7a, 0x12, 0x0b, 0x17, 0x8f, 0xca, 0x17, 0x48, 0xa8, 0x25, 0x18, 0xa1, 0xdc, + 0x22, 0x7b, 0xe9, 0xc8, 0xf5, 0xfa, 0x18, 0xf4, 0x49, 0x6a, 0x6c, 0xd9, 0x1d, 0xc6, 0x87, 0xae, + 0xd7, 0x67, 0x77, 0xa0, 0xae, 0x8a, 0xf1, 0x76, 0x5c, 0xa4, 0xf5, 0x97, 0xc5, 0xe2, 0x4e, 0xb4, + 0xa0, 0xa1, 0x31, 0x86, 0x49, 0x2e, 0x54, 0x4d, 0xa2, 0x20, 0x1d, 0xbc, 0x87, 0xce, 0xff, 0x98, + 0x63, 0xc6, 0x53, 0xf3, 0xf1, 0x4d, 0x39, 0x57, 0x49, 0xa5, 0xea, 0x7f, 0x8c, 0x74, 0xb0, 0x09, + 0x53, 0x08, 0x62, 0xe4, 0xa2, 0x59, 0x4e, 0x09, 0x62, 0x12, 0x15, 0x5d, 0x34, 0x84, 0xc0, 0x3e, + 0x32, 0x14, 0xa9, 0x36, 0x22, 0xbf, 0x32, 0xd1, 0xfe, 0x0c, 0x15, 0x4a, 0x50, 0xaf, 0x17, 0x89, + 0x5b, 0x26, 0xe2, 0x7e, 0x1f, 0x13, 0xa0, 0x2a, 0x76, 0xd5, 0x8b, 0x9e, 0x10, 0xe0, 0x97, 0xab, + 0x61, 0xad, 0x42, 0xdd, 0x9c, 0x26, 0xab, 0x40, 0xf1, 0xe0, 0x70, 0x73, 0xbf, 0x75, 0x8d, 0xd5, + 0xa0, 0xdc, 0xdd, 0x3c, 0x3a, 0xda, 0xdd, 0xdc, 0x68, 0xe5, 0x58, 0x1d, 0x2a, 0x3a, 0x8d, 0x23, + 0x2f, 0xbe, 0x56, 0xd7, 0xd7, 0x37, 0x0f, 0x8f, 0x36, 0x37, 0x5a, 0x85, 0x1f, 0x14, 0x2b, 0xf9, + 0x56, 0xc1, 0xfa, 0xf3, 0x02, 0xd4, 0x8c, 0x55, 0x78, 0x3e, 0x33, 0xbe, 0x05, 0x80, 0x2a, 0x4d, + 0x12, 0xc7, 0x54, 0xb4, 0xab, 0x02, 0x42, 0x9b, 0x6f, 0x1a, 0xcb, 0x0b, 0xf4, 0xfc, 0x83, 0x32, + 0x96, 0xbf, 0x0e, 0x0d, 0x7a, 0x49, 0xc1, 0x74, 0xd7, 0x95, 0xec, 0x3a, 0x01, 0x25, 0xab, 0xc6, + 0x3c, 0x30, 0x44, 0xc2, 0x0c, 0x01, 0x99, 0x57, 0x4d, 0x20, 0xcc, 0x11, 0xc0, 0x04, 0x8f, 0x28, + 0x18, 0x9c, 0x73, 0xc2, 0x20, 0x89, 0xb0, 0x26, 0x61, 0x47, 0x32, 0x11, 0x4d, 0xf2, 0x43, 0x23, + 0x11, 0xa9, 0x64, 0xd7, 0x09, 0x28, 0x3b, 0x7a, 0x57, 0x11, 0x50, 0x05, 0x09, 0x68, 0x65, 0x9a, + 0x1a, 0x52, 0xc4, 0xb3, 0x3b, 0x65, 0xcf, 0xaa, 0x22, 0x61, 0x7c, 0x67, 0xba, 0xde, 0x8b, 0xed, + 0x5a, 0xec, 0x6d, 0x60, 0xc3, 0xd1, 0xc8, 0xc9, 0xb0, 0x34, 0x15, 0xed, 0xf9, 0xe1, 0x68, 0x74, + 0x64, 0x18, 0x62, 0x7e, 0x09, 0x46, 0xb0, 0x2f, 0x81, 0xad, 0x8a, 0x03, 0x8c, 0x43, 0xd4, 0x26, + 0xd4, 0x84, 0x2d, 0xe7, 0x4c, 0xb6, 0x9c, 0xc1, 0xfd, 0xf2, 0x99, 0xdc, 0xef, 0x79, 0x7c, 0xc2, + 0xda, 0x82, 0xda, 0xa1, 0xf1, 0x4e, 0xcb, 0x1d, 0x71, 0x43, 0xa8, 0x17, 0x5a, 0xe8, 0xee, 0x20, + 0xe3, 0x56, 0x28, 0x1f, 0x66, 0x31, 0x46, 0x93, 0x37, 0x46, 0x63, 0xfd, 0xeb, 0x1c, 0xe5, 0xc0, + 0xeb, 0xc1, 0x27, 0x4f, 0xc3, 0x28, 0x3f, 0x50, 0x92, 0x2f, 0x58, 0x53, 0xfe, 0x1f, 0x99, 0xea, + 0x87, 0x43, 0x73, 0x82, 0x93, 0x93, 0x88, 0xab, 0xcc, 0x97, 0x1a, 0xc2, 0x0e, 0x10, 0xa4, 0x84, + 0x6f, 0x21, 0xe1, 0x7b, 0xd4, 0x7e, 0x24, 0x33, 0x60, 0x84, 0xf0, 0xbd, 0xe7, 0x5e, 0xca, 0x5e, + 0x23, 0x21, 0x82, 0x48, 0x43, 0xb5, 0xca, 0xf7, 0xd1, 0xdf, 0xd6, 0xbf, 0x90, 0x29, 0x8d, 0x93, + 0xeb, 0x7b, 0x1f, 0x2a, 0xba, 0xd5, 0xf4, 0x0d, 0xab, 0x30, 0x75, 0xb9, 0xb8, 0xc7, 0x51, 0x2b, + 0x4f, 0x8d, 0x98, 0x0e, 0x17, 0x3a, 0x1b, 0x76, 0x8c, 0x51, 0xbf, 0x03, 0xec, 0xc4, 0x0b, 0x27, + 0x91, 0xe9, 0xb0, 0xb5, 0xb0, 0xc4, 0xc0, 0xb6, 0x9e, 0xc2, 0xa2, 0xe2, 0x12, 0x86, 0x46, 0x90, + 0xde, 0xbc, 0xdc, 0x0b, 0x98, 0x7c, 0x7e, 0x8a, 0xc9, 0x5b, 0x3f, 0x2b, 0x42, 0x59, 0xbd, 0x79, + 0x94, 0xf5, 0x4e, 0x4f, 0x35, 0xfd, 0x4e, 0x4f, 0x3b, 0xf5, 0xa6, 0x03, 0x6e, 0xbd, 0xbc, 0xef, + 0xef, 0x4e, 0x5e, 0xd9, 0x86, 0xd1, 0x3c, 0x75, 0x6d, 0x2f, 0x43, 0x71, 0xe4, 0xc6, 0x67, 0x68, + 0x20, 0x23, 0xe2, 0xc1, 0x6f, 0x65, 0x4c, 0x2f, 0xa5, 0x8d, 0xe9, 0x59, 0x6f, 0x1a, 0x91, 0x48, + 0x3a, 0xf5, 0xa6, 0xd1, 0x4d, 0x20, 0xf9, 0xc2, 0x88, 0x87, 0xa9, 0x20, 0x40, 0xdc, 0x45, 0x69, + 0x71, 0xa4, 0x32, 0x29, 0x8e, 0xbc, 0xb4, 0xa8, 0xf0, 0x3e, 0xcc, 0x51, 0x3e, 0xb0, 0xcc, 0x6b, + 0x52, 0x17, 0x8a, 0x5c, 0x43, 0xf5, 0x3f, 0x05, 0xc1, 0xda, 0x12, 0xd7, 0x7c, 0x20, 0xa4, 0x96, + 0x7a, 0x20, 0xc4, 0x34, 0xf2, 0xd7, 0xd3, 0x46, 0xfe, 0x7b, 0xd0, 0xd2, 0x0b, 0x8a, 0x26, 0x33, + 0x3f, 0x92, 0x19, 0x1d, 0x4d, 0x05, 0x17, 0x5c, 0x72, 0x3f, 0x4a, 0x2e, 0xc4, 0x66, 0xea, 0x42, + 0x14, 0x3c, 0x6c, 0x35, 0x8e, 0xf9, 0x70, 0x14, 0xcb, 0x0b, 0x11, 0x63, 0xbe, 0xcd, 0x01, 0xa6, + 0x33, 0xfe, 0x1a, 0x50, 0xdd, 0xd9, 0x77, 0xb6, 0x76, 0x77, 0x3e, 0xdd, 0x3e, 0x6a, 0xe5, 0xc4, + 0x67, 0xf7, 0xe9, 0xfa, 0xfa, 0xe6, 0xe6, 0x06, 0xde, 0x38, 0x00, 0x73, 0x5b, 0xab, 0x3b, 0xe2, + 0xf6, 0x29, 0x58, 0x7f, 0x9d, 0x83, 0x9a, 0xd1, 0x3c, 0xfb, 0x40, 0xaf, 0x0a, 0xbd, 0x21, 0x71, + 0x6b, 0x7a, 0x08, 0x0f, 0x14, 0x2b, 0x36, 0x96, 0x45, 0xbf, 0xe0, 0x94, 0x9f, 0xf9, 0x82, 0x13, + 0x7b, 0x13, 0xe6, 0x5d, 0x6a, 0x41, 0xaf, 0x82, 0x34, 0x07, 0x4b, 0xb0, 0x5c, 0x04, 0x8c, 0x02, + 0x4b, 0xee, 0x13, 0x81, 0x57, 0x54, 0x81, 0x57, 0xfa, 0x4a, 0xd9, 0x8f, 0xac, 0xef, 0x01, 0x24, + 0x23, 0x49, 0x4f, 0xf9, 0x5a, 0x7a, 0xca, 0x39, 0x63, 0xca, 0x79, 0x6b, 0x83, 0x98, 0x83, 0x5c, + 0x3e, 0xed, 0x7f, 0x7e, 0x17, 0x94, 0x9d, 0xc9, 0xc1, 0xe8, 0xca, 0xd1, 0x80, 0xc7, 0x2a, 0xe3, + 0x71, 0x41, 0x96, 0xec, 0xe8, 0x02, 0x95, 0x80, 0x9c, 0xb4, 0x92, 0xf0, 0x18, 0x49, 0x68, 0x93, + 0x3c, 0x46, 0xa2, 0xda, 0xba, 0xdc, 0xea, 0x40, 0x7b, 0x83, 0x8b, 0xd6, 0x56, 0x07, 0x83, 0x89, + 0xe1, 0x58, 0x37, 0xe1, 0x46, 0x46, 0x99, 0x34, 0x2d, 0x7c, 0x06, 0xd7, 0x57, 0x29, 0xb9, 0xf1, + 0x97, 0x95, 0x61, 0x61, 0xb5, 0x61, 0x79, 0xb2, 0x49, 0xd9, 0xd9, 0x16, 0x2c, 0x6c, 0xf0, 0xe3, + 0xf1, 0xe9, 0x2e, 0x3f, 0x4f, 0x3a, 0x62, 0x50, 0x8c, 0xce, 0x82, 0x0b, 0xb9, 0x3e, 0xf8, 0xb7, + 0x38, 0x99, 0x03, 0x81, 0xe3, 0x44, 0x23, 0xde, 0x53, 0x76, 0x4e, 0x84, 0x74, 0x47, 0xbc, 0x67, + 0x7d, 0x00, 0xcc, 0x6c, 0x47, 0xae, 0x97, 0x90, 0xfd, 0xc7, 0xc7, 0x4e, 0x74, 0x15, 0xc5, 0x7c, + 0xa8, 0x1e, 0x1e, 0x81, 0x68, 0x7c, 0xdc, 0x25, 0x88, 0x75, 0x17, 0xea, 0x87, 0xee, 0x95, 0xcd, + 0xbf, 0x94, 0xb9, 0x03, 0x2b, 0x50, 0x1e, 0xb9, 0x57, 0xe2, 0x70, 0x6b, 0x97, 0x07, 0x16, 0x5b, + 0x7f, 0x54, 0x84, 0x39, 0xc2, 0x64, 0x77, 0xe8, 0x6d, 0x40, 0xcf, 0xc7, 0xc3, 0xa5, 0xd8, 0x9f, + 0x01, 0x9a, 0xe2, 0x90, 0xf9, 0x69, 0x0e, 0x29, 0xcd, 0x62, 0xea, 0x4d, 0x04, 0x65, 0x9c, 0xf6, + 0xc7, 0x43, 0xf5, 0x10, 0x02, 0x7b, 0x05, 0xaa, 0x49, 0x92, 0x56, 0x31, 0x79, 0xfb, 0x91, 0x52, + 0xb3, 0xd2, 0xee, 0xc3, 0x44, 0xc3, 0xa0, 0xd1, 0x29, 0xc6, 0x2f, 0x99, 0xa0, 0x09, 0xca, 0x54, + 0x63, 0xca, 0x2a, 0x2b, 0x25, 0xad, 0xc6, 0x4c, 0xa9, 0x2b, 0x95, 0x17, 0xab, 0x2b, 0x64, 0x2f, + 0x7b, 0x8e, 0xba, 0x02, 0x2f, 0xa1, 0xae, 0xbc, 0x84, 0xeb, 0xee, 0x06, 0x54, 0xf0, 0x36, 0x37, + 0x78, 0xa2, 0xb8, 0xc5, 0x05, 0x4f, 0xfc, 0xd0, 0x10, 0xe8, 0x29, 0x6e, 0xe0, 0x66, 0x72, 0x4c, + 0x6c, 0xfe, 0xe5, 0xaf, 0xc6, 0x25, 0xf2, 0x05, 0x94, 0x25, 0x54, 0x10, 0xb4, 0xef, 0x0e, 0xd5, + 0xb3, 0x32, 0xf8, 0xb7, 0x58, 0x36, 0x7c, 0x0b, 0xe3, 0xcb, 0xb1, 0x17, 0xf2, 0xbe, 0x7a, 0xbc, + 0xc0, 0xc3, 0x33, 0x2a, 0x20, 0x62, 0x82, 0x42, 0xb9, 0xf0, 0x83, 0x0b, 0x5f, 0xa6, 0x2e, 0x97, + 0xbd, 0xe8, 0x89, 0xf8, 0xb4, 0x18, 0xb4, 0xf0, 0x61, 0xa9, 0x51, 0x10, 0xaa, 0x2b, 0xc7, 0xfa, + 0x59, 0x0e, 0x5a, 0xf2, 0x74, 0xe9, 0x32, 0x53, 0xb6, 0x2f, 0xcd, 0x72, 0x73, 0x3f, 0xff, 0x29, + 0x02, 0x0b, 0x1a, 0x68, 0xd2, 0xd0, 0xf7, 0x0f, 0x99, 0x64, 0x6a, 0x02, 0xb8, 0x25, 0xef, 0xa0, + 0x57, 0xa1, 0xa6, 0x82, 0x2c, 0x87, 0xde, 0x40, 0x3d, 0xf3, 0x4a, 0x51, 0x96, 0x7b, 0xde, 0x40, + 0x5d, 0x5f, 0xa1, 0x2b, 0xb3, 0xa4, 0x72, 0x78, 0x7d, 0xd9, 0x6e, 0xcc, 0xad, 0xff, 0x92, 0x83, + 0x05, 0x63, 0x2a, 0xf2, 0xdc, 0x7e, 0x0c, 0x75, 0xfd, 0xa2, 0x1b, 0xd7, 0xf2, 0xd4, 0x4a, 0x9a, + 0xd1, 0x24, 0xd5, 0x6a, 0x3d, 0x0d, 0x89, 0xc4, 0x60, 0xfa, 0xee, 0x15, 0x8e, 0x37, 0x1a, 0x0f, + 0x95, 0xca, 0xd2, 0x77, 0xaf, 0xb6, 0x38, 0xef, 0x8e, 0x87, 0x42, 0x21, 0xbd, 0xe0, 0xfc, 0x99, + 0x46, 0x20, 0x49, 0x0a, 0x04, 0x4c, 0x62, 0x58, 0xd0, 0x18, 0x06, 0x7e, 0x7c, 0xa6, 0x51, 0xa4, + 0x2c, 0x89, 0x40, 0xc2, 0xb1, 0xfe, 0x67, 0x1e, 0x16, 0xc9, 0x70, 0x26, 0x0d, 0x96, 0x92, 0x75, + 0xb5, 0x61, 0x8e, 0x6c, 0x88, 0xc4, 0xbc, 0xb6, 0xaf, 0xd9, 0xf2, 0x9b, 0xbd, 0xff, 0x92, 0xc6, + 0x3e, 0x95, 0x88, 0x35, 0x63, 0xf9, 0x0b, 0xd3, 0xcb, 0x3f, 0x7b, 0x79, 0xb3, 0xfc, 0x68, 0xa5, + 0x2c, 0x3f, 0xda, 0xcb, 0x78, 0xaf, 0xa6, 0xb2, 0x95, 0xca, 0x12, 0xc7, 0xc8, 0x56, 0xfa, 0x00, + 0x56, 0x52, 0x38, 0xc8, 0xad, 0xbd, 0x13, 0x8f, 0xab, 0xcc, 0xf0, 0x25, 0x03, 0xbb, 0xab, 0xca, + 0xd6, 0xca, 0x50, 0x8a, 0x7a, 0xc1, 0x88, 0x5b, 0xcb, 0xb0, 0x94, 0x5e, 0x55, 0x79, 0x4d, 0xfc, + 0x41, 0x0e, 0xda, 0x32, 0xea, 0xc1, 0xf3, 0x4f, 0xb7, 0xbd, 0x28, 0x0e, 0x42, 0xfd, 0xf2, 0xd9, + 0x2d, 0x80, 0x28, 0x76, 0x43, 0xa9, 0x43, 0x92, 0x74, 0x5b, 0x45, 0x08, 0xea, 0x87, 0x37, 0xa0, + 0xc2, 0xfd, 0x3e, 0x15, 0x12, 0x35, 0x94, 0xb9, 0xdf, 0x57, 0xda, 0xe5, 0x94, 0x54, 0xdd, 0x48, + 0x2b, 0x0d, 0x32, 0x6d, 0x52, 0xac, 0x0e, 0x3f, 0xc7, 0x8b, 0xb7, 0xa8, 0xd3, 0x26, 0xf7, 0xdc, + 0x4b, 0x8c, 0x21, 0x8c, 0xac, 0x7f, 0x9a, 0x87, 0xf9, 0x64, 0x7c, 0x94, 0x73, 0x9d, 0xe2, 0xdf, + 0x72, 0x54, 0x09, 0xff, 0xbe, 0x23, 0xc9, 0xc1, 0x13, 0x52, 0xb9, 0x61, 0x4e, 0xac, 0xd0, 0xe1, + 0xdc, 0xf1, 0x99, 0x05, 0x35, 0x85, 0x11, 0x8c, 0x63, 0xe3, 0x01, 0xa2, 0x2a, 0xa1, 0x1c, 0x8c, + 0x63, 0xa1, 0x46, 0x09, 0x7d, 0xd2, 0xf3, 0xa5, 0x22, 0x53, 0x72, 0x87, 0xf1, 0x0e, 0xbe, 0x6b, + 0x2c, 0xc0, 0xa2, 0x1a, 0x6d, 0xa4, 0xc0, 0x12, 0xf8, 0x2d, 0x92, 0x9e, 0x69, 0xe7, 0x50, 0x72, + 0x36, 0x45, 0x4b, 0x7a, 0xe2, 0x51, 0x8b, 0x96, 0xaf, 0x42, 0x8d, 0x1a, 0x4f, 0x92, 0xd3, 0x8a, + 0x76, 0x15, 0x7b, 0xc0, 0x72, 0x69, 0xda, 0x09, 0xc6, 0x29, 0x85, 0x16, 0xa8, 0x2b, 0x0c, 0x2a, + 0xf8, 0x47, 0x39, 0xb8, 0x91, 0xb1, 0x6d, 0xf2, 0x94, 0xaf, 0xc3, 0xc2, 0x89, 0x2e, 0x54, 0xab, + 0x4b, 0x47, 0x7d, 0x59, 0xb1, 0xd5, 0xf4, 0x9a, 0xda, 0xad, 0x93, 0x34, 0x20, 0x51, 0xa5, 0x68, + 0x07, 0x53, 0xf9, 0x87, 0xa8, 0x4a, 0xd1, 0x36, 0x92, 0x16, 0x73, 0x08, 0x9d, 0xcd, 0x4b, 0xc1, + 0x31, 0xd6, 0xcd, 0x87, 0xb9, 0x15, 0x19, 0xa5, 0xcd, 0xc6, 0xb9, 0x97, 0x32, 0x1b, 0xf7, 0x29, + 0xcd, 0x4a, 0xb7, 0xf5, 0x6d, 0x1a, 0xc1, 0x0b, 0x54, 0xd4, 0xa1, 0x87, 0xc5, 0x55, 0x0e, 0x64, + 0x4f, 0x3f, 0x28, 0x6e, 0x45, 0x30, 0xbf, 0x37, 0x1e, 0xc4, 0x5e, 0xf2, 0xc6, 0x38, 0x7b, 0x5f, + 0xd6, 0xc1, 0x7e, 0xd4, 0xaa, 0x65, 0x76, 0x04, 0xba, 0x23, 0x5c, 0xac, 0xa1, 0x68, 0xc8, 0x99, + 0xee, 0x6f, 0x7e, 0x98, 0xee, 0xc1, 0xba, 0x01, 0x2b, 0xc9, 0x17, 0x2d, 0x9b, 0xba, 0x6a, 0xfe, + 0x55, 0x8e, 0x02, 0x96, 0xd3, 0xef, 0x9d, 0xb3, 0x4d, 0x58, 0x8c, 0x3c, 0xff, 0x74, 0xc0, 0xcd, + 0xe6, 0x23, 0xb9, 0x08, 0xd7, 0xd3, 0x63, 0x93, 0x6f, 0xa2, 0xdb, 0x0b, 0x54, 0x23, 0x69, 0x2d, + 0x62, 0x6b, 0xb3, 0x06, 0x99, 0x90, 0xc5, 0xc4, 0x6a, 0x4c, 0x0f, 0x7e, 0x07, 0x9a, 0xe9, 0x8e, + 0xd8, 0x87, 0x32, 0xc5, 0x30, 0x19, 0x55, 0x61, 0x22, 0x5b, 0x2c, 0x21, 0x88, 0x5a, 0xb2, 0xf6, + 0x91, 0xf5, 0x8f, 0x73, 0xd0, 0xb6, 0xb9, 0xa0, 0x5c, 0x63, 0x94, 0x8a, 0x66, 0x3e, 0x9e, 0x6a, + 0x75, 0xf6, 0x5c, 0x55, 0xe6, 0xa2, 0x1a, 0xd1, 0x3b, 0x33, 0x37, 0x63, 0xfb, 0xda, 0xd4, 0x8c, + 0xd6, 0x2a, 0x30, 0x47, 0x28, 0xd6, 0x0a, 0x5c, 0x97, 0xe3, 0x51, 0x63, 0x49, 0x7c, 0x82, 0xa9, + 0x1e, 0x53, 0x3e, 0xc1, 0x0e, 0xb4, 0xe9, 0x01, 0x3b, 0x73, 0x12, 0xb2, 0xe2, 0x06, 0xb0, 0x3d, + 0xb7, 0xe7, 0x86, 0x41, 0xe0, 0x1f, 0xf2, 0x50, 0x86, 0x7f, 0xa2, 0x84, 0x89, 0x2e, 0x33, 0x25, + 0x0a, 0xd3, 0x97, 0x7a, 0x76, 0x2d, 0xf0, 0x55, 0xb4, 0x0b, 0x7d, 0x59, 0x36, 0x2c, 0xae, 0xb9, + 0xcf, 0xb8, 0x6a, 0x49, 0x2d, 0xd1, 0x27, 0x50, 0x1b, 0xe9, 0x46, 0xd5, 0xba, 0xab, 0x3c, 0xe4, + 0xe9, 0x6e, 0x6d, 0x13, 0xdb, 0x7a, 0x0c, 0x4b, 0xe9, 0x36, 0x25, 0xeb, 0xe8, 0x40, 0x65, 0x28, + 0x61, 0x72, 0x74, 0xfa, 0xfb, 0xfe, 0xd7, 0x50, 0x33, 0x1e, 0x25, 0x64, 0x2b, 0xb0, 0xf8, 0xf9, + 0xce, 0xd1, 0xfe, 0x66, 0xb7, 0xeb, 0x1c, 0x3e, 0x5d, 0x7b, 0xb2, 0xf9, 0x85, 0xb3, 0xbd, 0xda, + 0xdd, 0x6e, 0x5d, 0x63, 0xcb, 0xc0, 0xf6, 0x37, 0xbb, 0x47, 0x9b, 0x1b, 0x29, 0x78, 0x8e, 0xbd, + 0x0a, 0x9d, 0xa7, 0xfb, 0x4f, 0xbb, 0x9b, 0x1b, 0x4e, 0x56, 0xbd, 0x3c, 0xbb, 0x05, 0x37, 0x64, + 0x79, 0x46, 0xf5, 0xc2, 0xfd, 0x4f, 0xa0, 0x35, 0x69, 0x55, 0x4c, 0x99, 0x61, 0x9f, 0x67, 0xaf, + 0xbd, 0xff, 0xef, 0x0a, 0x00, 0x49, 0xd8, 0x27, 0x6b, 0xc3, 0xd2, 0xc6, 0xea, 0xd1, 0xea, 0xee, + 0x81, 0x18, 0x84, 0x7d, 0x70, 0xb4, 0xb9, 0x7e, 0xe4, 0xd8, 0x9b, 0x9f, 0xb5, 0xae, 0x65, 0x96, + 0x1c, 0x1c, 0x0a, 0x7d, 0x7c, 0x05, 0x16, 0x77, 0xf6, 0x77, 0x8e, 0x76, 0x56, 0x77, 0x1d, 0xfb, + 0xe0, 0xe9, 0xce, 0xfe, 0xa7, 0xf4, 0xec, 0x48, 0x81, 0xdd, 0x86, 0x9b, 0x4f, 0x0f, 0xb7, 0xec, + 0x83, 0xfd, 0x23, 0xa7, 0xbb, 0xfd, 0xf4, 0x68, 0x03, 0x1f, 0x2d, 0x59, 0xb7, 0x77, 0x0e, 0xa9, + 0xcd, 0xe2, 0xf3, 0x10, 0x44, 0xd3, 0x25, 0xb1, 0x62, 0x9f, 0x1e, 0x74, 0xbb, 0x3b, 0x87, 0xce, + 0x67, 0x4f, 0x37, 0xed, 0x9d, 0xcd, 0x2e, 0x56, 0x9c, 0xcb, 0x80, 0x0b, 0xfc, 0x32, 0x5b, 0x80, + 0xc6, 0xd1, 0xee, 0x0f, 0x9d, 0x83, 0xfd, 0x9d, 0x83, 0x7d, 0x44, 0xad, 0xa4, 0x41, 0x02, 0xab, + 0xca, 0x3a, 0xb0, 0xbc, 0xf9, 0x9b, 0x47, 0x4e, 0x46, 0xcb, 0x30, 0xa3, 0x4c, 0xd4, 0xab, 0xb1, + 0x1b, 0x70, 0xbd, 0x7b, 0xb4, 0x7a, 0xb4, 0xb3, 0xee, 0xc8, 0x97, 0x8e, 0xc4, 0x26, 0x88, 0x6a, + 0xf5, 0xec, 0x22, 0x51, 0xab, 0xc1, 0x96, 0xa0, 0x75, 0xb8, 0xfa, 0xc5, 0xde, 0xe6, 0xfe, 0x91, + 0xb3, 0xba, 0xb1, 0x61, 0x63, 0x85, 0xe6, 0x14, 0x54, 0xe0, 0xce, 0x8b, 0x8d, 0xda, 0x3b, 0x3c, + 0x44, 0x94, 0x96, 0xfa, 0x10, 0x25, 0x0b, 0x8f, 0x7f, 0xb7, 0x00, 0x4d, 0x0a, 0xc1, 0xa7, 0x5f, + 0x74, 0xe0, 0x21, 0xdb, 0x83, 0xb2, 0xfc, 0x69, 0x10, 0x76, 0x5d, 0x3f, 0x3e, 0x61, 0xfe, 0x18, + 0x49, 0x67, 0x79, 0x12, 0x2c, 0x8f, 0xdf, 0xe2, 0xdf, 0xfe, 0xb3, 0xbf, 0xfc, 0x27, 0xf9, 0x06, + 0xab, 0x3d, 0x3c, 0x7f, 0xef, 0xe1, 0x29, 0xf7, 0x23, 0xd1, 0xc6, 0xdf, 0x00, 0x48, 0x7e, 0xf0, + 0x82, 0xb5, 0xb5, 0x29, 0x71, 0xe2, 0xd7, 0x40, 0x3a, 0x37, 0x32, 0x4a, 0x64, 0xbb, 0x37, 0xb0, + 0xdd, 0x45, 0xab, 0x29, 0xda, 0xf5, 0x7c, 0x2f, 0xa6, 0x1f, 0xbf, 0xf8, 0x38, 0x77, 0x9f, 0xf5, + 0xa1, 0x6e, 0xfe, 0x14, 0x05, 0x53, 0xae, 0xf8, 0x8c, 0x1f, 0xd3, 0xe8, 0xdc, 0xcc, 0x2c, 0x53, + 0x3c, 0x07, 0xfb, 0xb8, 0x6e, 0xb5, 0x44, 0x1f, 0x63, 0xc4, 0x48, 0x7a, 0x19, 0x10, 0x17, 0x4e, + 0x7e, 0x71, 0x82, 0xbd, 0x62, 0x70, 0xc6, 0xa9, 0xdf, 0xbb, 0xe8, 0xdc, 0x9a, 0x51, 0x2a, 0xfb, + 0xba, 0x85, 0x7d, 0xad, 0x58, 0x4c, 0xf4, 0xd5, 0x43, 0x1c, 0xf5, 0x7b, 0x17, 0x1f, 0xe7, 0xee, + 0x3f, 0xfe, 0x8b, 0x7b, 0x50, 0xd5, 0x21, 0x39, 0xec, 0xb7, 0xa1, 0x91, 0xca, 0x91, 0x60, 0x6a, + 0x1a, 0x59, 0x29, 0x15, 0x9d, 0x57, 0xb2, 0x0b, 0x65, 0xc7, 0xaf, 0x62, 0xc7, 0x6d, 0xb6, 0x2c, + 0x3a, 0x96, 0x39, 0x08, 0x0f, 0x31, 0x93, 0x88, 0x9e, 0xf2, 0x78, 0x66, 0xdc, 0x36, 0xd4, 0xd9, + 0x2b, 0x93, 0x37, 0x40, 0xaa, 0xb7, 0x5b, 0x33, 0x4a, 0x65, 0x77, 0xaf, 0x60, 0x77, 0xcb, 0x6c, + 0xc9, 0xec, 0x4e, 0x05, 0xd0, 0x30, 0x8e, 0xcf, 0xe7, 0x98, 0x3f, 0xc8, 0xc0, 0x6e, 0x25, 0x8f, + 0x9d, 0x64, 0xfc, 0x50, 0x83, 0x26, 0x91, 0xe9, 0x5f, 0x6b, 0xb0, 0xda, 0xd8, 0x15, 0x63, 0xb8, + 0x7d, 0xe6, 0xef, 0x31, 0xb0, 0x63, 0xa8, 0x19, 0x6f, 0x18, 0xb3, 0x1b, 0x33, 0xdf, 0x5b, 0xee, + 0x74, 0xb2, 0x8a, 0xb2, 0xa6, 0x62, 0xb6, 0xff, 0x50, 0xc8, 0x9e, 0x3f, 0x86, 0xaa, 0x7e, 0x19, + 0x97, 0xad, 0x18, 0x2f, 0x15, 0x9b, 0x2f, 0xf9, 0x76, 0xda, 0xd3, 0x05, 0x59, 0xc4, 0x67, 0xb6, + 0x2e, 0x88, 0xef, 0x73, 0xa8, 0x19, 0xaf, 0xdf, 0xea, 0x09, 0x4c, 0xbf, 0xb0, 0xab, 0x27, 0x90, + 0xf1, 0x58, 0xae, 0xb5, 0x80, 0x5d, 0xd4, 0x58, 0x15, 0xe9, 0x3b, 0xbe, 0x0c, 0x22, 0xb6, 0x0b, + 0xd7, 0xe5, 0xcd, 0x7a, 0xcc, 0xbf, 0xc9, 0x36, 0x64, 0xfc, 0x06, 0xc6, 0xa3, 0x1c, 0xfb, 0x04, + 0x2a, 0xea, 0x91, 0x63, 0xb6, 0x9c, 0xfd, 0x58, 0x73, 0x67, 0x65, 0x0a, 0x2e, 0xaf, 0xc1, 0x2f, + 0x00, 0x92, 0xa7, 0x76, 0x35, 0x93, 0x98, 0x7a, 0xba, 0x57, 0x53, 0xc0, 0xf4, 0xbb, 0xbc, 0xd6, + 0x32, 0x4e, 0xb0, 0xc5, 0x90, 0x49, 0xf8, 0xfc, 0x42, 0xbd, 0x23, 0xf6, 0x13, 0xa8, 0x19, 0xaf, + 0xed, 0xea, 0xe5, 0x9b, 0x7e, 0xa9, 0x57, 0x2f, 0x5f, 0xc6, 0xe3, 0xbc, 0x56, 0x07, 0x5b, 0x5f, + 0xb2, 0xe6, 0x45, 0xeb, 0x91, 0x77, 0xea, 0x0f, 0x09, 0x41, 0x6c, 0xd0, 0x19, 0x34, 0x52, 0x4f, + 0xea, 0xea, 0x13, 0x9a, 0xf5, 0x60, 0xaf, 0x3e, 0xa1, 0x99, 0xaf, 0xf0, 0x2a, 0x3a, 0xb3, 0x16, + 0x44, 0x3f, 0xe7, 0x88, 0x62, 0xf4, 0xf4, 0x23, 0xa8, 0x19, 0xcf, 0xe3, 0xea, 0xb9, 0x4c, 0xbf, + 0xc4, 0xab, 0xe7, 0x92, 0xf5, 0x9a, 0xee, 0x12, 0xf6, 0xd1, 0xb4, 0x90, 0x14, 0xf0, 0x95, 0x26, + 0xd1, 0xf6, 0x6f, 0x43, 0x33, 0xfd, 0x62, 0xae, 0x3e, 0xfb, 0x99, 0x4f, 0xef, 0xea, 0xb3, 0x3f, + 0xe3, 0x99, 0x5d, 0x49, 0xd2, 0xf7, 0x17, 0x75, 0x27, 0x0f, 0xbf, 0x92, 0xc1, 0xc5, 0x5f, 0xb3, + 0xcf, 0x04, 0x83, 0x93, 0x8f, 0x84, 0xb1, 0x15, 0x83, 0x6a, 0xcd, 0xa7, 0xc4, 0xf4, 0x79, 0x99, + 0x7a, 0x4f, 0x2c, 0x4d, 0xcc, 0xd8, 0x38, 0xfb, 0x14, 0x16, 0x35, 0x31, 0xeb, 0x57, 0xbf, 0x22, + 0x3d, 0x87, 0xcc, 0xb7, 0xc5, 0x3a, 0xad, 0xc9, 0xd2, 0x47, 0x39, 0xba, 0xfe, 0xf0, 0xad, 0x25, + 0xe3, 0xfa, 0x33, 0x1f, 0xfe, 0x32, 0xae, 0xbf, 0xd4, 0x93, 0x4c, 0x93, 0xd7, 0x5f, 0xec, 0x89, + 0x36, 0x7c, 0x98, 0x9f, 0x7c, 0x83, 0xeb, 0xd6, 0xac, 0x0c, 0x54, 0x6a, 0xfe, 0xd5, 0xe7, 0x27, + 0xa8, 0xa6, 0x59, 0x91, 0xe2, 0xa6, 0x0f, 0xa5, 0x0b, 0x91, 0xfd, 0x16, 0xd4, 0xcd, 0x27, 0x3f, + 0x99, 0xc9, 0x13, 0x26, 0x7b, 0xba, 0x99, 0x59, 0x96, 0xa6, 0x12, 0x56, 0x37, 0xbb, 0x61, 0x3f, + 0x84, 0x65, 0xbd, 0xcc, 0x66, 0xf6, 0x61, 0xc4, 0x6e, 0x67, 0xe4, 0x24, 0xa6, 0x16, 0xfb, 0xc6, + 0xcc, 0xa4, 0xc5, 0x47, 0x39, 0x41, 0x7d, 0xe9, 0xb7, 0x07, 0x93, 0x9b, 0x27, 0xeb, 0xc9, 0xc5, + 0xe4, 0xe6, 0xc9, 0x7c, 0xb0, 0x50, 0x51, 0x1f, 0x5b, 0x4c, 0xad, 0x11, 0x05, 0x57, 0xb1, 0x1f, + 0xc1, 0xbc, 0x91, 0x5a, 0xd9, 0xbd, 0xf2, 0x7b, 0xfa, 0x24, 0x4d, 0x3f, 0xec, 0xd3, 0xc9, 0xd2, + 0x45, 0xad, 0x15, 0x6c, 0x7f, 0xc1, 0x4a, 0x2d, 0x8e, 0x38, 0x45, 0xeb, 0x50, 0x33, 0xd3, 0x36, + 0x9f, 0xd3, 0xee, 0x8a, 0x51, 0x64, 0xbe, 0x21, 0xf3, 0x28, 0xc7, 0x76, 0xa1, 0x35, 0xf9, 0xe4, + 0x85, 0xe6, 0x29, 0x59, 0xcf, 0x74, 0x74, 0x26, 0x0a, 0x53, 0x0f, 0x65, 0xb0, 0x43, 0x0a, 0xcf, + 0xd5, 0x3f, 0x18, 0x11, 0x84, 0x93, 0xb7, 0x7a, 0xfa, 0x87, 0x24, 0x74, 0x6b, 0x59, 0x3f, 0x21, + 0x72, 0x2f, 0xf7, 0x28, 0xc7, 0x7e, 0x3f, 0x07, 0xf5, 0x54, 0x9a, 0x79, 0x2a, 0x00, 0x72, 0x62, + 0x9e, 0x6d, 0xb3, 0xcc, 0x9c, 0xa8, 0x65, 0xe3, 0x22, 0xee, 0xde, 0xff, 0x41, 0x6a, 0x93, 0xbe, + 0x4a, 0x99, 0x72, 0x1f, 0x4c, 0xfe, 0xa2, 0xc4, 0xd7, 0x93, 0x08, 0xe6, 0x7b, 0x4d, 0x5f, 0x3f, + 0xca, 0xb1, 0xff, 0x90, 0x83, 0x66, 0xda, 0x47, 0xa3, 0xa7, 0x9b, 0xe9, 0x0d, 0xd2, 0xa4, 0x34, + 0xc3, 0xb1, 0xf3, 0x23, 0x1c, 0xe5, 0xd1, 0x7d, 0x3b, 0x35, 0x4a, 0xf9, 0x6a, 0xe6, 0x2f, 0x36, + 0x5a, 0xf6, 0x31, 0xfd, 0x80, 0x93, 0x72, 0x48, 0xb3, 0xe9, 0x1f, 0xfc, 0xd1, 0xe4, 0x67, 0xfe, + 0x3c, 0x0e, 0x6e, 0xc2, 0x4f, 0xe8, 0x97, 0x13, 0x94, 0x7f, 0x53, 0x50, 0xf1, 0xcb, 0xd6, 0xb7, + 0xde, 0xc0, 0x39, 0xbd, 0x6a, 0xdd, 0x48, 0xcd, 0x69, 0x52, 0xf0, 0x58, 0xa5, 0xd1, 0xc9, 0x5f, + 0xb7, 0x49, 0x6e, 0xce, 0xa9, 0x5f, 0xbc, 0x99, 0x3d, 0xc8, 0x21, 0x0d, 0x52, 0xa2, 0xa7, 0x8e, + 0xda, 0x4b, 0x36, 0x63, 0xdd, 0xc7, 0xb1, 0xbe, 0x61, 0xdd, 0x9e, 0x39, 0xd6, 0x87, 0xe8, 0x6f, + 0x11, 0x23, 0x3e, 0x04, 0x48, 0x02, 0x46, 0xd8, 0x44, 0xd8, 0x82, 0x66, 0x40, 0xd3, 0x31, 0x25, + 0xe9, 0xf3, 0xac, 0xa2, 0x1b, 0x44, 0x8b, 0x3f, 0x26, 0x76, 0xaa, 0x03, 0x2a, 0x4c, 0xe9, 0x2b, + 0x1d, 0xdb, 0x91, 0x92, 0xbe, 0x26, 0xdb, 0x4f, 0x31, 0x53, 0x1d, 0x3d, 0xf1, 0x14, 0x1a, 0xbb, + 0x41, 0xf0, 0x6c, 0x3c, 0xd2, 0x41, 0x8a, 0x69, 0x27, 0xe8, 0xb6, 0x1b, 0x9d, 0x75, 0x26, 0x66, + 0x61, 0xdd, 0xc1, 0xa6, 0x3a, 0xac, 0x6d, 0x34, 0xf5, 0xf0, 0xab, 0x24, 0x4a, 0xe5, 0x6b, 0xe6, + 0xc2, 0x82, 0xe6, 0xd1, 0x49, 0x24, 0x48, 0xba, 0x99, 0x14, 0x67, 0x9e, 0xec, 0x22, 0xa5, 0x26, + 0xa8, 0xd1, 0x3e, 0x8c, 0x54, 0x9b, 0x8f, 0x72, 0xec, 0x10, 0xea, 0x1b, 0xbc, 0x87, 0xe9, 0x96, + 0xe8, 0x4a, 0x5c, 0x4c, 0xb9, 0xa5, 0xc8, 0x07, 0xd9, 0x69, 0xa4, 0x80, 0xe9, 0x7b, 0x6b, 0xe4, + 0x5e, 0x85, 0xfc, 0xcb, 0x87, 0x5f, 0x49, 0x27, 0xe5, 0xd7, 0xea, 0xde, 0x52, 0x4e, 0xdc, 0xd4, + 0xbd, 0x35, 0xe1, 0xf5, 0x4d, 0xdd, 0x5b, 0x53, 0x5e, 0xdf, 0xd4, 0x52, 0x2b, 0x27, 0x32, 0x1b, + 0xc0, 0xc2, 0x94, 0xa3, 0x58, 0x5f, 0x59, 0xb3, 0xdc, 0xcb, 0x9d, 0x3b, 0xb3, 0x11, 0xd2, 0xbd, + 0xdd, 0x4f, 0xf7, 0xd6, 0x85, 0x06, 0x3d, 0x21, 0x75, 0xcc, 0x29, 0xf1, 0x62, 0xe2, 0xd5, 0x02, + 0x33, 0xab, 0x63, 0xf2, 0x82, 0xc1, 0xb2, 0xb4, 0x84, 0x83, 0x19, 0x0f, 0xec, 0xc7, 0x50, 0xfb, + 0x94, 0xc7, 0x2a, 0xd3, 0x42, 0xcb, 0xd8, 0x13, 0xa9, 0x17, 0x9d, 0x8c, 0x44, 0x8d, 0x34, 0xcd, + 0x60, 0x6b, 0x0f, 0x79, 0xff, 0x94, 0x13, 0x73, 0x72, 0xbc, 0xfe, 0xd7, 0xec, 0x37, 0xb1, 0x71, + 0x9d, 0xe0, 0xb6, 0x6c, 0x84, 0xd2, 0x9b, 0x8d, 0xcf, 0x4f, 0xc0, 0xb3, 0x5a, 0xf6, 0x83, 0x3e, + 0x37, 0x64, 0x3d, 0x1f, 0x6a, 0x46, 0x22, 0xac, 0x3e, 0x40, 0xd3, 0x89, 0xcf, 0xfa, 0x00, 0x65, + 0xe4, 0xcd, 0x5a, 0xf7, 0xb0, 0x1f, 0x8b, 0xdd, 0x49, 0xfa, 0xa1, 0x5c, 0xd9, 0xa4, 0xa7, 0x87, + 0x5f, 0xb9, 0xc3, 0xf8, 0x6b, 0xf6, 0x39, 0x3e, 0xd4, 0x6a, 0x66, 0x92, 0x24, 0x4a, 0xc3, 0x64, + 0xd2, 0x89, 0x5e, 0x2c, 0xa3, 0x28, 0xad, 0x48, 0x50, 0x57, 0x28, 0xc9, 0x7d, 0x00, 0xd0, 0x8d, + 0x83, 0xd1, 0x86, 0xcb, 0x87, 0x81, 0x9f, 0xf0, 0xda, 0x24, 0xb7, 0x21, 0xe1, 0x5f, 0x46, 0x82, + 0x03, 0xfb, 0xdc, 0xd0, 0xb2, 0x52, 0xc9, 0x38, 0x8a, 0xb8, 0x66, 0xa6, 0x3f, 0xe8, 0x05, 0xc9, + 0x48, 0x81, 0x78, 0x94, 0x63, 0xab, 0x00, 0x49, 0xa4, 0x80, 0xd6, 0x99, 0xa6, 0x82, 0x10, 0x34, + 0xdb, 0xcb, 0x08, 0x2b, 0x38, 0x84, 0x6a, 0xe2, 0x62, 0x5d, 0x49, 0xf2, 0xfa, 0x53, 0x0e, 0x59, + 0x7d, 0x83, 0x4f, 0xb9, 0x37, 0xad, 0x16, 0x2e, 0x15, 0xb0, 0x8a, 0x58, 0xaa, 0x13, 0xce, 0x23, + 0xe6, 0xc1, 0x22, 0x0d, 0x50, 0x8b, 0x4b, 0x18, 0x93, 0xaf, 0xdf, 0xe3, 0x9d, 0xf6, 0x34, 0xea, + 0xd3, 0x9c, 0xe9, 0x2f, 0x4b, 0x99, 0x7e, 0x04, 0xb5, 0x52, 0x3e, 0x80, 0x60, 0xcd, 0x43, 0x58, + 0x98, 0x72, 0xc9, 0xe8, 0x23, 0x3d, 0xcb, 0xc7, 0xa6, 0x8f, 0xf4, 0x4c, 0x6f, 0x8e, 0x75, 0x1d, + 0xbb, 0x9c, 0xb7, 0x00, 0x55, 0xbd, 0x0b, 0x2f, 0xee, 0x9d, 0x89, 0xee, 0xfe, 0x6d, 0x0e, 0x16, + 0x33, 0x9c, 0x2e, 0xec, 0x35, 0x65, 0x35, 0x98, 0xe9, 0x90, 0xe9, 0x64, 0x1a, 0xe7, 0xad, 0x2e, + 0xf6, 0xb3, 0xc7, 0x9e, 0xa4, 0x2e, 0x36, 0xb2, 0x8d, 0xcb, 0x93, 0xf9, 0x5c, 0xa1, 0x22, 0x53, + 0xa2, 0xf8, 0x12, 0x56, 0x68, 0x20, 0xab, 0x83, 0xc1, 0x84, 0xe3, 0xe0, 0xd5, 0xa9, 0x1f, 0x78, + 0x4d, 0x39, 0x43, 0x3a, 0xb3, 0x7f, 0x00, 0x76, 0x86, 0x38, 0x4d, 0x43, 0x65, 0x63, 0x68, 0x4d, + 0x1a, 0xe4, 0xd9, 0xec, 0xb6, 0x3a, 0xb7, 0x53, 0xfa, 0x6f, 0x86, 0x11, 0xff, 0x3b, 0xd8, 0xd9, + 0x6d, 0xab, 0x93, 0xb5, 0x2e, 0xa4, 0x12, 0x8b, 0xfd, 0xf8, 0x5b, 0xda, 0x7b, 0x30, 0x31, 0x4f, + 0xd5, 0xc1, 0x2c, 0x5f, 0x87, 0xd6, 0xc0, 0xb3, 0x9d, 0x0f, 0x6f, 0x62, 0xf7, 0x77, 0xac, 0x9b, + 0x59, 0xdd, 0x87, 0x54, 0x85, 0x74, 0xf1, 0x95, 0xc9, 0x73, 0xad, 0x46, 0x70, 0x27, 0x6b, 0xbf, + 0x67, 0xea, 0x42, 0x13, 0x6b, 0x7d, 0x0d, 0x65, 0xbb, 0xba, 0xe9, 0x2d, 0xd0, 0xc7, 0x27, 0xc3, + 0x2d, 0xa1, 0x8f, 0x4f, 0x96, 0x7b, 0x21, 0x2d, 0xd7, 0x28, 0xc7, 0xc2, 0xc7, 0xb9, 0xfb, 0x6b, + 0x77, 0x7f, 0xf4, 0x9d, 0x53, 0x2f, 0x3e, 0x1b, 0x1f, 0x3f, 0xe8, 0x05, 0xc3, 0x87, 0x03, 0x65, + 0x6d, 0x94, 0x89, 0x6b, 0x0f, 0x07, 0x7e, 0xff, 0x21, 0x36, 0x7b, 0x3c, 0x87, 0xbf, 0x48, 0xfd, + 0xdd, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x7d, 0xa1, 0xab, 0x8e, 0xc3, 0x7a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 060c7d8384..6965d3ee82 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -819,7 +819,7 @@ service Lightning { message Utxo { /// The type of address - AddressType type = 1; + AddressType address_type = 1; /// The address string address = 2; @@ -2910,7 +2910,7 @@ message ChannelFeeReport { uint64 chan_id = 5 [jstype = JS_STRING]; /// The channel that this fee report belongs to. - string chan_point = 1; + string channel_point = 1; /// The base fee charged regardless of the number of milli-satoshis sent. int64 base_fee_msat = 2; diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 795c91d4a6..8bffa4a8c1 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -2192,7 +2192,7 @@ "format": "uint64", "description": "/ The short channel id that this fee report belongs to." }, - "chan_point": { + "channel_point": { "type": "string", "description": "/ The channel that this fee report belongs to." }, @@ -4196,7 +4196,7 @@ "lnrpcUtxo": { "type": "object", "properties": { - "type": { + "address_type": { "$ref": "#/definitions/lnrpcAddressType", "title": "/ The type of address" }, diff --git a/rpcserver.go b/rpcserver.go index 232a865106..024bfb8404 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -943,7 +943,7 @@ func (r *rpcServer) ListUnspent(ctx context.Context, } utxoResp := lnrpc.Utxo{ - Type: addrType, + AddressType: addrType, AmountSat: int64(utxo.Value), PkScript: hex.EncodeToString(utxo.PkScript), Outpoint: outpoint, @@ -5141,11 +5141,11 @@ func (r *rpcServer) FeeReport(ctx context.Context, // TODO(roasbeef): also add stats for revenue for each channel feeReports = append(feeReports, &lnrpc.ChannelFeeReport{ - ChanId: chanInfo.ChannelID, - ChanPoint: chanInfo.ChannelPoint.String(), - BaseFeeMsat: int64(edgePolicy.FeeBaseMSat), - FeePerMil: int64(feeRateFixedPoint), - FeeRate: feeRate, + ChanId: chanInfo.ChannelID, + ChannelPoint: chanInfo.ChannelPoint.String(), + BaseFeeMsat: int64(edgePolicy.FeeBaseMSat), + FeePerMil: int64(feeRateFixedPoint), + FeeRate: feeRate, }) return nil From 967b4b2dc307046f8668a5241e0739b7fa1943f5 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 19 Feb 2020 09:53:13 +0100 Subject: [PATCH 147/562] channeldb: remove redundant MPPaymentCreationInfo struct MPPaymentCreationInfo and PaymentCreationInfo are identical except for the naming of CreationTime/CreationDate. --- channeldb/mp_payment.go | 23 +++-------------------- channeldb/payment_control_test.go | 2 +- channeldb/payments.go | 12 ++++++------ channeldb/payments_test.go | 2 +- routing/control_tower_test.go | 2 +- routing/router.go | 4 ++-- 6 files changed, 14 insertions(+), 31 deletions(-) diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index 9a26cdbda1..bee267590a 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -5,26 +5,9 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/lightningnetwork/lnd/lntypes" - "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) -// MPPaymentCreationInfo is the information necessary to have ready when -// initiating a payment, moving it into state InFlight. -type MPPaymentCreationInfo struct { - // PaymentHash is the hash this payment is paying to. - PaymentHash lntypes.Hash - - // Value is the amount we are paying. - Value lnwire.MilliSatoshi - - // CreatingTime is the time at which this payment was started. - CreationTime time.Time - - // PaymentRequest is the full payment request, if any. - PaymentRequest []byte -} - // HTLCAttempt contains information about a specific HTLC attempt for a given // payment. This information is used by the router to handle any errors coming // back after an attempt is made, and to query the switch about the status of a @@ -74,8 +57,8 @@ type HTLCFailInfo struct { FailTime time.Time } -// MPPayment is a wrapper around a payment's MPPaymentCreationInfo and -// HTLCAttempts. All payments will have the MPPPaymentCreationInfo set, any +// MPPayment is a wrapper around a payment's PaymentCreationInfo and +// HTLCAttempts. All payments will have the PaymentCreationInfo set, any // HTLCs made in attempts to be completed will populated in the HTLCs slice. // Each populated HTLCAttempt represents an attempted HTLC, each of which may // have the associated Settle or Fail struct populated if the HTLC is no longer @@ -87,7 +70,7 @@ type MPPayment struct { // Info holds all static information about this payment, and is // populated when the payment is initiated. - Info *MPPaymentCreationInfo + Info *PaymentCreationInfo // HTLCs holds the information about individual HTLCs that we send in // order to make the payment. diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 7be04c6b12..bb1458aef2 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -51,7 +51,7 @@ func genInfo() (*PaymentCreationInfo, *PaymentAttemptInfo, return &PaymentCreationInfo{ PaymentHash: rhash, Value: 1, - CreationDate: time.Unix(time.Now().Unix(), 0), + CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte("hola"), }, &PaymentAttemptInfo{ diff --git a/channeldb/payments.go b/channeldb/payments.go index a03c9e0c75..0800b99838 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -178,8 +178,8 @@ type PaymentCreationInfo struct { // Value is the amount we are paying. Value lnwire.MilliSatoshi - // CreatingDate is the time when this payment was initiated. - CreationDate time.Time + // CreationTime is the time when this payment was initiated. + CreationTime time.Time // PaymentRequest is the full payment request, if any. PaymentRequest []byte @@ -283,10 +283,10 @@ func (p *Payment) ToMPPayment() *MPPayment { return &MPPayment{ sequenceNum: p.sequenceNum, - Info: &MPPaymentCreationInfo{ + Info: &PaymentCreationInfo{ PaymentHash: p.Info.PaymentHash, Value: p.Info.Value, - CreationTime: p.Info.CreationDate, + CreationTime: p.Info.CreationTime, PaymentRequest: p.Info.PaymentRequest, }, HTLCs: htlcs, @@ -475,7 +475,7 @@ func serializePaymentCreationInfo(w io.Writer, c *PaymentCreationInfo) error { return err } - byteOrder.PutUint64(scratch[:], uint64(c.CreationDate.Unix())) + byteOrder.PutUint64(scratch[:], uint64(c.CreationTime.Unix())) if _, err := w.Write(scratch[:]); err != nil { return err } @@ -509,7 +509,7 @@ func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) { if _, err := io.ReadFull(r, scratch[:]); err != nil { return nil, err } - c.CreationDate = time.Unix(int64(byteOrder.Uint64(scratch[:])), 0) + c.CreationTime = time.Unix(int64(byteOrder.Uint64(scratch[:])), 0) if _, err := io.ReadFull(r, scratch[:4]); err != nil { return nil, err diff --git a/channeldb/payments_test.go b/channeldb/payments_test.go index 16e952df4f..fb3de6cea3 100644 --- a/channeldb/payments_test.go +++ b/channeldb/payments_test.go @@ -62,7 +62,7 @@ func makeFakeInfo() (*PaymentCreationInfo, *PaymentAttemptInfo) { Value: 1000, // Use single second precision to avoid false positive test // failures due to the monotonic time component. - CreationDate: time.Unix(time.Now().Unix(), 0), + CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte(""), } diff --git a/routing/control_tower_test.go b/routing/control_tower_test.go index e326e98c07..9fa5ec5b0b 100644 --- a/routing/control_tower_test.go +++ b/routing/control_tower_test.go @@ -311,7 +311,7 @@ func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.PaymentAttemptInfo, return &channeldb.PaymentCreationInfo{ PaymentHash: rhash, Value: 1, - CreationDate: time.Unix(time.Now().Unix(), 0), + CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte("hola"), }, &channeldb.PaymentAttemptInfo{ diff --git a/routing/router.go b/routing/router.go index e42ce7a0e8..d30191b5d4 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1680,7 +1680,7 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) ( info := &channeldb.PaymentCreationInfo{ PaymentHash: payment.PaymentHash, Value: payment.Amount, - CreationDate: time.Now(), + CreationTime: time.Now(), PaymentRequest: payment.PaymentRequest, } @@ -1709,7 +1709,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( info := &channeldb.PaymentCreationInfo{ PaymentHash: hash, Value: amt, - CreationDate: time.Now(), + CreationTime: time.Now(), PaymentRequest: nil, } From bee2380441e4b7344c9539dce1673cab5454fa14 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 7 Feb 2020 10:31:27 +0100 Subject: [PATCH 148/562] channeldb: rename PaymentAttemptInfo to HTLCAttemptInfo To better distinguish payments from HTLCs, we rename the attempt info struct to HTLCAttemptInfo. We also embed it into the HTLCAttempt struct, to avoid having to duplicate this information. The paymentID term is renamed to attemptID. --- channeldb/mp_payment.go | 26 +++++++++++------- channeldb/payment_control.go | 12 ++++----- channeldb/payment_control_test.go | 16 +++++------ channeldb/payments.go | 45 +++++++++---------------------- channeldb/payments_test.go | 12 ++++----- routing/control_tower.go | 8 +++--- routing/control_tower_test.go | 6 ++--- routing/mock_test.go | 4 +-- routing/payment_lifecycle.go | 34 +++++++++++------------ routing/router.go | 2 +- 10 files changed, 76 insertions(+), 89 deletions(-) diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index bee267590a..4220e7aab7 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -8,16 +8,15 @@ import ( "github.com/lightningnetwork/lnd/routing/route" ) -// HTLCAttempt contains information about a specific HTLC attempt for a given -// payment. This information is used by the router to handle any errors coming -// back after an attempt is made, and to query the switch about the status of a -// payment. For settled payment this will be the information for the succeeding -// payment attempt. -type HTLCAttempt struct { - // PaymentID is the unique ID used for this attempt. - PaymentID uint64 - - // SessionKey is the ephemeral key used for this payment attempt. +// HTLCAttemptInfo contains static information about a specific HTLC attempt +// for a payment. This information is used by the router to handle any errors +// coming back after an attempt is made, and to query the switch about the +// status of the attempt. +type HTLCAttemptInfo struct { + // AttemptID is the unique ID used for this attempt. + AttemptID uint64 + + // SessionKey is the ephemeral key used for this attempt. SessionKey *btcec.PrivateKey // Route is the route attempted to send the HTLC. @@ -25,6 +24,13 @@ type HTLCAttempt struct { // AttemptTime is the time at which this HTLC was attempted. AttemptTime time.Time +} + +// HTLCAttempt contains information about a specific HTLC attempt for a given +// payment. It contains the HTLCAttemptInfo used to send the HTLC, as well +// as a timestamp and any known outcome of the attempt. +type HTLCAttempt struct { + HTLCAttemptInfo // Settle is the preimage of a successful payment. This serves as a // proof of payment. It will only be non-nil for settled payments. diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 63be23a2eb..b6bcd5a11d 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -143,14 +143,14 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, return updateErr } -// RegisterAttempt atomically records the provided PaymentAttemptInfo to the +// RegisterAttempt atomically records the provided HTLCAttemptInfo to the // DB. func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, - attempt *PaymentAttemptInfo) error { + attempt *HTLCAttemptInfo) error { // Serialize the information before opening the db transaction. var a bytes.Buffer - if err := serializePaymentAttemptInfo(&a, attempt); err != nil { + if err := serializeHTLCAttemptInfo(&a, attempt); err != nil { return err } attemptBytes := a.Bytes() @@ -405,14 +405,14 @@ func ensureInFlight(bucket *bbolt.Bucket) error { } // fetchPaymentAttempt fetches the payment attempt from the bucket. -func fetchPaymentAttempt(bucket *bbolt.Bucket) (*PaymentAttemptInfo, error) { +func fetchPaymentAttempt(bucket *bbolt.Bucket) (*HTLCAttemptInfo, error) { attemptData := bucket.Get(paymentAttemptInfoKey) if attemptData == nil { return nil, errNoAttemptInfo } r := bytes.NewReader(attemptData) - return deserializePaymentAttemptInfo(r) + return deserializeHTLCAttemptInfo(r) } // InFlightPayment is a wrapper around a payment that has status InFlight. @@ -424,7 +424,7 @@ type InFlightPayment struct { // made to this payment hash. // // NOTE: Might be nil. - Attempt *PaymentAttemptInfo + Attempt *HTLCAttemptInfo } // FetchInFlightPayments returns all payments with status InFlight. diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index bb1458aef2..2910063101 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -38,7 +38,7 @@ func genPreimage() ([32]byte, error) { return preimage, nil } -func genInfo() (*PaymentCreationInfo, *PaymentAttemptInfo, +func genInfo() (*PaymentCreationInfo, *HTLCAttemptInfo, lntypes.Preimage, error) { preimage, err := genPreimage() @@ -54,8 +54,8 @@ func genInfo() (*PaymentCreationInfo, *PaymentAttemptInfo, CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte("hola"), }, - &PaymentAttemptInfo{ - PaymentID: 1, + &HTLCAttemptInfo{ + AttemptID: 1, SessionKey: priv, Route: testRoute, }, preimage, nil @@ -119,7 +119,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { ) // Record a new attempt. - attempt.PaymentID = 2 + attempt.AttemptID = 2 err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) @@ -445,7 +445,7 @@ func checkPaymentCreationInfo(bucket *bbolt.Bucket, c *PaymentCreationInfo) erro return nil } -func checkPaymentAttemptInfo(bucket *bbolt.Bucket, a *PaymentAttemptInfo) error { +func checkHTLCAttemptInfo(bucket *bbolt.Bucket, a *HTLCAttemptInfo) error { b := bucket.Get(paymentAttemptInfoKey) switch { case b == nil && a == nil: @@ -457,7 +457,7 @@ func checkPaymentAttemptInfo(bucket *bbolt.Bucket, a *PaymentAttemptInfo) error } r := bytes.NewReader(b) - a2, err := deserializePaymentAttemptInfo(r) + a2, err := deserializeHTLCAttemptInfo(r) if err != nil { return err } @@ -508,7 +508,7 @@ func checkFailInfo(bucket *bbolt.Bucket, failReason *FailureReason) error { } func assertPaymentInfo(t *testing.T, db *DB, hash lntypes.Hash, - c *PaymentCreationInfo, a *PaymentAttemptInfo, s lntypes.Preimage, + c *PaymentCreationInfo, a *HTLCAttemptInfo, s lntypes.Preimage, f *FailureReason) { t.Helper() @@ -535,7 +535,7 @@ func assertPaymentInfo(t *testing.T, db *DB, hash lntypes.Hash, return err } - if err := checkPaymentAttemptInfo(bucket, a); err != nil { + if err := checkHTLCAttemptInfo(bucket, a); err != nil { return err } diff --git a/channeldb/payments.go b/channeldb/payments.go index 0800b99838..ae6d8abd17 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -8,7 +8,6 @@ import ( "sort" "time" - "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/lntypes" @@ -185,25 +184,9 @@ type PaymentCreationInfo struct { PaymentRequest []byte } -// PaymentAttemptInfo contains information about a specific payment attempt for -// a given payment. This information is used by the router to handle any errors -// coming back after an attempt is made, and to query the switch about the -// status of a payment. For settled payment this will be the information for -// the succeeding payment attempt. -type PaymentAttemptInfo struct { - // PaymentID is the unique ID used for this attempt. - PaymentID uint64 - - // SessionKey is the ephemeral key used for this payment attempt. - SessionKey *btcec.PrivateKey - - // Route is the route attempted to send the HTLC. - Route route.Route -} - // Payment is a wrapper around a payment's PaymentCreationInfo, -// PaymentAttemptInfo, and preimage. All payments will have the -// PaymentCreationInfo set, the PaymentAttemptInfo will be set only if at least +// HTLCAttemptInfo, and preimage. All payments will have the +// PaymentCreationInfo set, the HTLCAttemptInfo will be set only if at least // one payment attempt has been made, while only completed payments will have a // non-zero payment preimage. type Payment struct { @@ -221,7 +204,7 @@ type Payment struct { // Attempt is the information about the last payment attempt made. // // NOTE: Can be nil if no attempt is yet made. - Attempt *PaymentAttemptInfo + Attempt *HTLCAttemptInfo // Preimage is the preimage of a successful payment. This serves as a // proof of payment. It will only be non-nil for settled payments. @@ -272,11 +255,9 @@ func (p *Payment) ToMPPayment() *MPPayment { // NOTE: AttemptTime is not set for legacy payments. htlcs = []HTLCAttempt{ { - PaymentID: p.Attempt.PaymentID, - SessionKey: p.Attempt.SessionKey, - Route: p.Attempt.Route, - Settle: settle, - Failure: failure, + HTLCAttemptInfo: *p.Attempt, + Settle: settle, + Failure: failure, }, } } @@ -392,11 +373,11 @@ func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) { } - // Get the PaymentAttemptInfo. This can be unset. + // Get the HTLCAttemptInfo. This can be unset. b = bucket.Get(paymentAttemptInfoKey) if b != nil { r = bytes.NewReader(b) - p.Attempt, err = deserializePaymentAttemptInfo(r) + p.Attempt, err = deserializeHTLCAttemptInfo(r) if err != nil { return nil, err } @@ -527,8 +508,8 @@ func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) { return c, nil } -func serializePaymentAttemptInfo(w io.Writer, a *PaymentAttemptInfo) error { - if err := WriteElements(w, a.PaymentID, a.SessionKey); err != nil { +func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error { + if err := WriteElements(w, a.AttemptID, a.SessionKey); err != nil { return err } @@ -539,9 +520,9 @@ func serializePaymentAttemptInfo(w io.Writer, a *PaymentAttemptInfo) error { return nil } -func deserializePaymentAttemptInfo(r io.Reader) (*PaymentAttemptInfo, error) { - a := &PaymentAttemptInfo{} - err := ReadElements(r, &a.PaymentID, &a.SessionKey) +func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) { + a := &HTLCAttemptInfo{} + err := ReadElements(r, &a.AttemptID, &a.SessionKey) if err != nil { return nil, err } diff --git a/channeldb/payments_test.go b/channeldb/payments_test.go index fb3de6cea3..26148a1ecd 100644 --- a/channeldb/payments_test.go +++ b/channeldb/payments_test.go @@ -53,7 +53,7 @@ var ( } ) -func makeFakeInfo() (*PaymentCreationInfo, *PaymentAttemptInfo) { +func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) { var preimg lntypes.Preimage copy(preimg[:], rev[:]) @@ -66,8 +66,8 @@ func makeFakeInfo() (*PaymentCreationInfo, *PaymentAttemptInfo) { PaymentRequest: []byte(""), } - a := &PaymentAttemptInfo{ - PaymentID: 44, + a := &HTLCAttemptInfo{ + AttemptID: 44, SessionKey: priv, Route: testRoute, } @@ -109,11 +109,11 @@ func TestSentPaymentSerialization(t *testing.T) { } b.Reset() - if err := serializePaymentAttemptInfo(&b, s); err != nil { + if err := serializeHTLCAttemptInfo(&b, s); err != nil { t.Fatalf("unable to serialize info: %v", err) } - newAttemptInfo, err := deserializePaymentAttemptInfo(&b) + newAttemptInfo, err := deserializeHTLCAttemptInfo(&b) if err != nil { t.Fatalf("unable to deserialize info: %v", err) } @@ -144,7 +144,7 @@ func TestSentPaymentSerialization(t *testing.T) { // they are not equal. func assertRouteEqual(a, b *route.Route) error { if !reflect.DeepEqual(a, b) { - return fmt.Errorf("PaymentAttemptInfos don't match: %v vs %v", + return fmt.Errorf("HTLCAttemptInfos don't match: %v vs %v", spew.Sdump(a), spew.Sdump(b)) } diff --git a/routing/control_tower.go b/routing/control_tower.go index 4cf6839ff1..0dffa7c633 100644 --- a/routing/control_tower.go +++ b/routing/control_tower.go @@ -19,8 +19,8 @@ type ControlTower interface { // hash. InitPayment(lntypes.Hash, *channeldb.PaymentCreationInfo) error - // RegisterAttempt atomically records the provided PaymentAttemptInfo. - RegisterAttempt(lntypes.Hash, *channeldb.PaymentAttemptInfo) error + // RegisterAttempt atomically records the provided HTLCAttemptInfo. + RegisterAttempt(lntypes.Hash, *channeldb.HTLCAttemptInfo) error // Success transitions a payment into the Succeeded state. After // invoking this method, InitPayment should always return an error to @@ -91,10 +91,10 @@ func (p *controlTower) InitPayment(paymentHash lntypes.Hash, return p.db.InitPayment(paymentHash, info) } -// RegisterAttempt atomically records the provided PaymentAttemptInfo to the +// RegisterAttempt atomically records the provided HTLCAttemptInfo to the // DB. func (p *controlTower) RegisterAttempt(paymentHash lntypes.Hash, - attempt *channeldb.PaymentAttemptInfo) error { + attempt *channeldb.HTLCAttemptInfo) error { return p.db.RegisterAttempt(paymentHash, attempt) } diff --git a/routing/control_tower_test.go b/routing/control_tower_test.go index 9fa5ec5b0b..d4399ced4f 100644 --- a/routing/control_tower_test.go +++ b/routing/control_tower_test.go @@ -298,7 +298,7 @@ func initDB() (*channeldb.DB, error) { return db, err } -func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.PaymentAttemptInfo, +func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.HTLCAttemptInfo, lntypes.Preimage, error) { preimage, err := genPreimage() @@ -314,8 +314,8 @@ func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.PaymentAttemptInfo, CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte("hola"), }, - &channeldb.PaymentAttemptInfo{ - PaymentID: 1, + &channeldb.HTLCAttemptInfo{ + AttemptID: 1, SessionKey: priv, Route: testRoute, }, preimage, nil diff --git a/routing/mock_test.go b/routing/mock_test.go index fac67aa9f2..a840d73861 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -178,7 +178,7 @@ type initArgs struct { } type registerArgs struct { - a *channeldb.PaymentAttemptInfo + a *channeldb.HTLCAttemptInfo } type successArgs struct { @@ -238,7 +238,7 @@ func (m *mockControlTower) InitPayment(phash lntypes.Hash, } func (m *mockControlTower) RegisterAttempt(phash lntypes.Hash, - a *channeldb.PaymentAttemptInfo) error { + a *channeldb.HTLCAttemptInfo) error { m.Lock() defer m.Unlock() diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 2283ca057d..13d59370cd 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -35,7 +35,7 @@ type paymentLifecycle struct { timeoutChan <-chan time.Time currentHeight int32 finalCLTVDelta uint16 - attempt *channeldb.PaymentAttemptInfo + attempt *channeldb.HTLCAttemptInfo circuit *sphinx.Circuit lastError error } @@ -97,17 +97,17 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // Now ask the switch to return the result of the payment when // available. resultChan, err := p.router.cfg.Payer.GetPaymentResult( - p.attempt.PaymentID, p.payment.PaymentHash, errorDecryptor, + p.attempt.AttemptID, p.payment.PaymentHash, errorDecryptor, ) switch { - // If this payment ID is unknown to the Switch, it means it was + // If this attempt ID is unknown to the Switch, it means it was // never checkpointed and forwarded by the switch before a // restart. In this case we can safely send a new payment // attempt, and wait for its result to be available. case err == htlcswitch.ErrPaymentIDNotFound: log.Debugf("Payment ID %v for hash %x not found in "+ - "the Switch, retrying.", p.attempt.PaymentID, + "the Switch, retrying.", p.attempt.AttemptID, p.payment.PaymentHash) // Reset the attempt to indicate we want to make a new @@ -117,8 +117,8 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // A critical, unexpected error was encountered. case err != nil: - log.Errorf("Failed getting result for paymentID %d "+ - "from switch: %v", p.attempt.PaymentID, err) + log.Errorf("Failed getting result for attemptID %d "+ + "from switch: %v", p.attempt.AttemptID, err) return [32]byte{}, nil, err } @@ -161,11 +161,11 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // We successfully got a payment result back from the switch. log.Debugf("Payment %x succeeded with pid=%v", - p.payment.PaymentHash, p.attempt.PaymentID) + p.payment.PaymentHash, p.attempt.AttemptID) // Report success to mission control. err = p.router.cfg.MissionControl.ReportPaymentSuccess( - p.attempt.PaymentID, &p.attempt.Route, + p.attempt.AttemptID, &p.attempt.Route, ) if err != nil { log.Errorf("Error reporting payment success to mc: %v", @@ -331,21 +331,21 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, // We generate a new, unique payment ID that we will use for // this HTLC. - paymentID, err := p.router.cfg.NextPaymentID() + attemptID, err := p.router.cfg.NextPaymentID() if err != nil { return lnwire.ShortChannelID{}, nil, err } // We now have all the information needed to populate // the current attempt information. - p.attempt = &channeldb.PaymentAttemptInfo{ - PaymentID: paymentID, + p.attempt = &channeldb.HTLCAttemptInfo{ + AttemptID: attemptID, SessionKey: sessionKey, Route: *rt, } // Before sending this HTLC to the switch, we checkpoint the - // fresh paymentID and route to the DB. This lets us know on + // fresh attemptID and route to the DB. This lets us know on // startup the ID of the payment that we attempted to send, // such that we can query the Switch for its whereabouts. The // route is needed to handle the result when it eventually @@ -363,7 +363,7 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, htlcAdd *lnwire.UpdateAddHTLC) error { log.Tracef("Attempting to send payment %x (pid=%v), "+ - "using route: %v", p.payment.PaymentHash, p.attempt.PaymentID, + "using route: %v", p.payment.PaymentHash, p.attempt.AttemptID, newLogClosure(func() string { return spew.Sdump(p.attempt.Route) }), @@ -374,17 +374,17 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, // such that we can resume waiting for the result after a // restart. err := p.router.cfg.Payer.SendHTLC( - firstHop, p.attempt.PaymentID, htlcAdd, + firstHop, p.attempt.AttemptID, htlcAdd, ) if err != nil { log.Errorf("Failed sending attempt %d for payment "+ - "%x to switch: %v", p.attempt.PaymentID, + "%x to switch: %v", p.attempt.AttemptID, p.payment.PaymentHash, err) return err } log.Debugf("Payment %x (pid=%v) successfully sent to switch, route: %v", - p.payment.PaymentHash, p.attempt.PaymentID, &p.attempt.Route) + p.payment.PaymentHash, p.attempt.AttemptID, &p.attempt.Route) return nil } @@ -394,7 +394,7 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, func (p *paymentLifecycle) handleSendError(sendErr error) error { reason := p.router.processSendError( - p.attempt.PaymentID, &p.attempt.Route, sendErr, + p.attempt.AttemptID, &p.attempt.Route, sendErr, ) if reason == nil { // Save the forwarding error so it can be returned if diff --git a/routing/router.go b/routing/router.go index d30191b5d4..8dbb45de5a 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1768,7 +1768,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( // router will call this method for every payment still in-flight according to // the ControlTower. func (r *ChannelRouter) sendPayment( - existingAttempt *channeldb.PaymentAttemptInfo, + existingAttempt *channeldb.HTLCAttemptInfo, payment *LightningPayment, paySession PaymentSession) ( [32]byte, *route.Route, error) { From c29b74168fafd3abce174f3cd647da78d6df104a Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 20 Feb 2020 14:43:25 +0100 Subject: [PATCH 149/562] channeldb/test: refactor payment control test Previously this was tested as a white box. Database access methods were duplicated as test code and compared to the return value of the code under test. This approaches leads to brittle test because it relies heavily on implementation details. This commit changes this and prepares for additional test coverage being added in later commits. --- channeldb/payment_control_test.go | 239 +++++++++--------------------- 1 file changed, 70 insertions(+), 169 deletions(-) diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 2910063101..5272ec79a6 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -1,7 +1,6 @@ package channeldb import ( - "bytes" "crypto/rand" "fmt" "io" @@ -11,7 +10,6 @@ import ( "time" "github.com/btcsuite/fastsha256" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/lntypes" ) @@ -85,9 +83,9 @@ func TestPaymentControlSwitchFail(t *testing.T) { t.Fatalf("unable to send htlc message: %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusInFlight) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, db, info.PaymentHash, info, nil, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, nil, lntypes.Preimage{}, nil, ) @@ -99,9 +97,9 @@ func TestPaymentControlSwitchFail(t *testing.T) { } // Verify the status is indeed Failed. - assertPaymentStatus(t, db, info.PaymentHash, StatusFailed) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusFailed) assertPaymentInfo( - t, db, info.PaymentHash, info, nil, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, nil, lntypes.Preimage{}, &failReason, ) @@ -112,9 +110,9 @@ func TestPaymentControlSwitchFail(t *testing.T) { t.Fatalf("unable to send htlc message: %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusInFlight) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, db, info.PaymentHash, info, nil, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, nil, lntypes.Preimage{}, nil, ) @@ -124,9 +122,9 @@ func TestPaymentControlSwitchFail(t *testing.T) { if err != nil { t.Fatalf("unable to send htlc message: %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusInFlight) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, db, info.PaymentHash, info, attempt, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, attempt, lntypes.Preimage{}, nil, ) @@ -149,8 +147,8 @@ func TestPaymentControlSwitchFail(t *testing.T) { spew.Sdump(payment.HTLCs[0].Route), err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusSucceeded) - assertPaymentInfo(t, db, info.PaymentHash, info, attempt, preimg, nil) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) + assertPaymentInfo(t, pControl, info.PaymentHash, info, attempt, preimg, nil) // Attempt a final payment, which should now fail since the prior // payment succeed. @@ -184,9 +182,9 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { t.Fatalf("unable to send htlc message: %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusInFlight) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, db, info.PaymentHash, info, nil, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, nil, lntypes.Preimage{}, nil, ) @@ -204,9 +202,9 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { if err != nil { t.Fatalf("unable to send htlc message: %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusInFlight) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, db, info.PaymentHash, info, attempt, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, attempt, lntypes.Preimage{}, nil, ) @@ -221,8 +219,8 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { if _, err := pControl.Success(info.PaymentHash, preimg); err != nil { t.Fatalf("error shouldn't have been received, got: %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusSucceeded) - assertPaymentInfo(t, db, info.PaymentHash, info, attempt, preimg, nil) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) + assertPaymentInfo(t, pControl, info.PaymentHash, info, attempt, preimg, nil) err = pControl.InitPayment(info.PaymentHash, info) if err != ErrAlreadyPaid { @@ -253,11 +251,7 @@ func TestPaymentControlSuccessesWithoutInFlight(t *testing.T) { t.Fatalf("expected ErrPaymentNotInitiated, got %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusUnknown) - assertPaymentInfo( - t, db, info.PaymentHash, nil, nil, lntypes.Preimage{}, - nil, - ) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusUnknown) } // TestPaymentControlFailsWithoutInFlight checks that a strict payment @@ -283,10 +277,7 @@ func TestPaymentControlFailsWithoutInFlight(t *testing.T) { t.Fatalf("expected ErrPaymentNotInitiated, got %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusUnknown) - assertPaymentInfo( - t, db, info.PaymentHash, nil, nil, lntypes.Preimage{}, nil, - ) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusUnknown) } // TestPaymentControlDeleteNonInFlight checks that calling DeletaPayments only @@ -344,9 +335,9 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { } // Verify the status is indeed Failed. - assertPaymentStatus(t, db, info.PaymentHash, StatusFailed) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusFailed) assertPaymentInfo( - t, db, info.PaymentHash, info, attempt, + t, pControl, info.PaymentHash, info, attempt, lntypes.Preimage{}, &failReason, ) } else if p.success { @@ -356,14 +347,14 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { t.Fatalf("error shouldn't have been received, got: %v", err) } - assertPaymentStatus(t, db, info.PaymentHash, StatusSucceeded) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) assertPaymentInfo( - t, db, info.PaymentHash, info, attempt, preimg, nil, + t, pControl, info.PaymentHash, info, attempt, preimg, nil, ) } else { - assertPaymentStatus(t, db, info.PaymentHash, StatusInFlight) + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, db, info.PaymentHash, info, attempt, + t, pControl, info.PaymentHash, info, attempt, lntypes.Preimage{}, nil, ) } @@ -390,166 +381,76 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { } } -func assertPaymentStatus(t *testing.T, db *DB, - hash [32]byte, expStatus PaymentStatus) { +// assertPaymentStatus retrieves the status of the payment referred to by hash +// and compares it with the expected state. +func assertPaymentStatus(t *testing.T, p *PaymentControl, + hash lntypes.Hash, expStatus PaymentStatus) { t.Helper() - var paymentStatus = StatusUnknown - err := db.View(func(tx *bbolt.Tx) error { - payments := tx.Bucket(paymentsRootBucket) - if payments == nil { - return nil - } - - bucket := payments.Bucket(hash[:]) - if bucket == nil { - return nil - } - - // Get the existing status of this payment, if any. - paymentStatus = fetchPaymentStatus(bucket) - return nil - }) + payment, err := p.FetchPayment(hash) + if expStatus == StatusUnknown && err == ErrPaymentNotInitiated { + return + } if err != nil { - t.Fatalf("unable to fetch payment status: %v", err) + t.Fatal(err) } - if paymentStatus != expStatus { + if payment.Status != expStatus { t.Fatalf("payment status mismatch: expected %v, got %v", - expStatus, paymentStatus) + expStatus, payment.Status) } } -func checkPaymentCreationInfo(bucket *bbolt.Bucket, c *PaymentCreationInfo) error { - b := bucket.Get(paymentCreationInfoKey) - switch { - case b == nil && c == nil: - return nil - case b == nil: - return fmt.Errorf("expected creation info not found") - case c == nil: - return fmt.Errorf("unexpected creation info found") - } - - r := bytes.NewReader(b) - c2, err := deserializePaymentCreationInfo(r) - if err != nil { - return err - } - if !reflect.DeepEqual(c, c2) { - return fmt.Errorf("PaymentCreationInfos don't match: %v vs %v", - spew.Sdump(c), spew.Sdump(c2)) - } - - return nil -} +// assertPaymentInfo retrieves the payment referred to by hash and verifies the +// expected values. +func assertPaymentInfo(t *testing.T, p *PaymentControl, hash lntypes.Hash, + c *PaymentCreationInfo, a *HTLCAttemptInfo, s lntypes.Preimage, + f *FailureReason) { -func checkHTLCAttemptInfo(bucket *bbolt.Bucket, a *HTLCAttemptInfo) error { - b := bucket.Get(paymentAttemptInfoKey) - switch { - case b == nil && a == nil: - return nil - case b == nil: - return fmt.Errorf("expected attempt info not found") - case a == nil: - return fmt.Errorf("unexpected attempt info found") - } + t.Helper() - r := bytes.NewReader(b) - a2, err := deserializeHTLCAttemptInfo(r) + payment, err := p.FetchPayment(hash) if err != nil { - return err - } - - return assertRouteEqual(&a.Route, &a2.Route) -} - -func checkSettleInfo(bucket *bbolt.Bucket, preimg lntypes.Preimage) error { - zero := lntypes.Preimage{} - b := bucket.Get(paymentSettleInfoKey) - switch { - case b == nil && preimg == zero: - return nil - case b == nil: - return fmt.Errorf("expected preimage not found") - case preimg == zero: - return fmt.Errorf("unexpected preimage found") - } - - var pre2 lntypes.Preimage - copy(pre2[:], b[:]) - if preimg != pre2 { - return fmt.Errorf("Preimages don't match: %x vs %x", - preimg, pre2) - } - - return nil -} - -func checkFailInfo(bucket *bbolt.Bucket, failReason *FailureReason) error { - b := bucket.Get(paymentFailInfoKey) - switch { - case b == nil && failReason == nil: - return nil - case b == nil: - return fmt.Errorf("expected fail info not found") - case failReason == nil: - return fmt.Errorf("unexpected fail info found") + t.Fatal(err) } - failReason2 := FailureReason(b[0]) - if *failReason != failReason2 { - return fmt.Errorf("Failure infos don't match: %v vs %v", - *failReason, failReason2) + if !reflect.DeepEqual(payment.Info, c) { + t.Fatalf("PaymentCreationInfos don't match: %v vs %v", + spew.Sdump(payment.Info), spew.Sdump(c)) } - return nil -} - -func assertPaymentInfo(t *testing.T, db *DB, hash lntypes.Hash, - c *PaymentCreationInfo, a *HTLCAttemptInfo, s lntypes.Preimage, - f *FailureReason) { - - t.Helper() - - err := db.View(func(tx *bbolt.Tx) error { - payments := tx.Bucket(paymentsRootBucket) - if payments == nil && c == nil { - return nil - } - if payments == nil { - return fmt.Errorf("sent payments not found") - } - - bucket := payments.Bucket(hash[:]) - if bucket == nil && c == nil { - return nil + if f != nil { + if *payment.FailureReason != *f { + t.Fatal("unexpected failure reason") } - - if bucket == nil { - return fmt.Errorf("payment not found") + } else { + if payment.FailureReason != nil { + t.Fatal("unexpected failure reason") } + } - if err := checkPaymentCreationInfo(bucket, c); err != nil { - return err + if a == nil { + if len(payment.HTLCs) > 0 { + t.Fatal("expected no htlcs") } + return + } - if err := checkHTLCAttemptInfo(bucket, a); err != nil { - return err - } + htlc := payment.HTLCs[0] + if err := assertRouteEqual(&htlc.Route, &a.Route); err != nil { + t.Fatal("routes do not match") + } - if err := checkSettleInfo(bucket, s); err != nil { - return err + var zeroPreimage = lntypes.Preimage{} + if s != zeroPreimage { + if htlc.Settle.Preimage != s { + t.Fatalf("Preimages don't match: %x vs %x", + htlc.Settle.Preimage, s) } - - if err := checkFailInfo(bucket, f); err != nil { - return err + } else { + if htlc.Settle != nil { + t.Fatal("expected no settle info") } - return nil - }) - if err != nil { - t.Fatalf("assert payment info failed: %v", err) } - } From cc5e18c487a87f7be36c2303d81c9fb8c0ff4b44 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 19 Feb 2020 14:34:27 +0100 Subject: [PATCH 150/562] channeldb: isolate duplicate payments Duplicate payments is legacy that we keep alive for accounting purposes. This commit isolates the deserialization logic for duplicate payments in its own file, so that regular payment logic and db structure can evolve without needing to handle/migrate the legacy data. --- channeldb/duplicate_payments.go | 246 ++++++++++++++++++++++++++++++++ channeldb/payments.go | 33 +---- 2 files changed, 252 insertions(+), 27 deletions(-) create mode 100644 channeldb/duplicate_payments.go diff --git a/channeldb/duplicate_payments.go b/channeldb/duplicate_payments.go new file mode 100644 index 0000000000..da9e969b0f --- /dev/null +++ b/channeldb/duplicate_payments.go @@ -0,0 +1,246 @@ +package channeldb + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "time" + + "github.com/btcsuite/btcd/btcec" + "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" +) + +var ( + // duplicatePaymentsBucket is the name of a optional sub-bucket within + // the payment hash bucket, that is used to hold duplicate payments to a + // payment hash. This is needed to support information from earlier + // versions of lnd, where it was possible to pay to a payment hash more + // than once. + duplicatePaymentsBucket = []byte("payment-duplicate-bucket") + + // duplicatePaymentSettleInfoKey is a key used in the payment's + // sub-bucket to store the settle info of the payment. + duplicatePaymentSettleInfoKey = []byte("payment-settle-info") + + // duplicatePaymentAttemptInfoKey is a key used in the payment's + // sub-bucket to store the info about the latest attempt that was done + // for the payment in question. + duplicatePaymentAttemptInfoKey = []byte("payment-attempt-info") + + // duplicatePaymentCreationInfoKey is a key used in the payment's + // sub-bucket to store the creation info of the payment. + duplicatePaymentCreationInfoKey = []byte("payment-creation-info") + + // duplicatePaymentFailInfoKey is a key used in the payment's sub-bucket + // to store information about the reason a payment failed. + duplicatePaymentFailInfoKey = []byte("payment-fail-info") + + // duplicatePaymentSequenceKey is a key used in the payment's sub-bucket + // to store the sequence number of the payment. + duplicatePaymentSequenceKey = []byte("payment-sequence-key") +) + +// duplicateHTLCAttemptInfo contains static information about a specific HTLC +// attempt for a payment. This information is used by the router to handle any +// errors coming back after an attempt is made, and to query the switch about +// the status of the attempt. +type duplicateHTLCAttemptInfo struct { + // attemptID is the unique ID used for this attempt. + attemptID uint64 + + // sessionKey is the ephemeral key used for this attempt. + sessionKey *btcec.PrivateKey + + // route is the route attempted to send the HTLC. + route route.Route +} + +// fetchDuplicatePaymentStatus fetches the payment status of the payment. If the +// payment isn't found, it will default to "StatusUnknown". +func fetchDuplicatePaymentStatus(bucket *bbolt.Bucket) PaymentStatus { + if bucket.Get(duplicatePaymentSettleInfoKey) != nil { + return StatusSucceeded + } + + if bucket.Get(duplicatePaymentFailInfoKey) != nil { + return StatusFailed + } + + if bucket.Get(duplicatePaymentCreationInfoKey) != nil { + return StatusInFlight + } + + return StatusUnknown +} + +func deserializeDuplicateHTLCAttemptInfo(r io.Reader) ( + *duplicateHTLCAttemptInfo, error) { + + a := &duplicateHTLCAttemptInfo{} + err := ReadElements(r, &a.attemptID, &a.sessionKey) + if err != nil { + return nil, err + } + a.route, err = DeserializeRoute(r) + if err != nil { + return nil, err + } + return a, nil +} + +func deserializeDuplicatePaymentCreationInfo(r io.Reader) ( + *PaymentCreationInfo, error) { + + var scratch [8]byte + + c := &PaymentCreationInfo{} + + if _, err := io.ReadFull(r, c.PaymentHash[:]); err != nil { + return nil, err + } + + if _, err := io.ReadFull(r, scratch[:]); err != nil { + return nil, err + } + c.Value = lnwire.MilliSatoshi(byteOrder.Uint64(scratch[:])) + + if _, err := io.ReadFull(r, scratch[:]); err != nil { + return nil, err + } + c.CreationTime = time.Unix(int64(byteOrder.Uint64(scratch[:])), 0) + + if _, err := io.ReadFull(r, scratch[:4]); err != nil { + return nil, err + } + + reqLen := byteOrder.Uint32(scratch[:4]) + payReq := make([]byte, reqLen) + if reqLen > 0 { + if _, err := io.ReadFull(r, payReq); err != nil { + return nil, err + } + } + c.PaymentRequest = payReq + + return c, nil +} + +func fetchDuplicatePayment(bucket *bbolt.Bucket) (*MPPayment, error) { + seqBytes := bucket.Get(duplicatePaymentSequenceKey) + if seqBytes == nil { + return nil, fmt.Errorf("sequence number not found") + } + + sequenceNum := binary.BigEndian.Uint64(seqBytes) + + // Get the payment status. + paymentStatus := fetchDuplicatePaymentStatus(bucket) + + // Get the PaymentCreationInfo. + b := bucket.Get(duplicatePaymentCreationInfoKey) + if b == nil { + return nil, fmt.Errorf("creation info not found") + } + + r := bytes.NewReader(b) + creationInfo, err := deserializeDuplicatePaymentCreationInfo(r) + if err != nil { + return nil, err + + } + + // Get failure reason if available. + var failureReason *FailureReason + b = bucket.Get(duplicatePaymentFailInfoKey) + if b != nil { + reason := FailureReason(b[0]) + failureReason = &reason + } + + payment := &MPPayment{ + sequenceNum: sequenceNum, + Info: creationInfo, + FailureReason: failureReason, + Status: paymentStatus, + } + + // Get the HTLCAttemptInfo. It can be absent. + b = bucket.Get(duplicatePaymentAttemptInfoKey) + if b != nil { + r = bytes.NewReader(b) + attempt, err := deserializeDuplicateHTLCAttemptInfo(r) + if err != nil { + return nil, err + } + + htlc := HTLCAttempt{ + HTLCAttemptInfo: HTLCAttemptInfo{ + AttemptID: attempt.attemptID, + Route: attempt.route, + SessionKey: attempt.sessionKey, + }, + } + + // Get the payment preimage. This is only found for + // successful payments. + b = bucket.Get(duplicatePaymentSettleInfoKey) + if b != nil { + var preimg lntypes.Preimage + copy(preimg[:], b) + + htlc.Settle = &HTLCSettleInfo{ + Preimage: preimg, + SettleTime: time.Time{}, + } + } else { + // Otherwise the payment must have failed. + htlc.Failure = &HTLCFailInfo{ + FailTime: time.Time{}, + } + } + + payment.HTLCs = []HTLCAttempt{htlc} + } + + return payment, nil +} + +func fetchDuplicatePayments(paymentHashBucket *bbolt.Bucket) ([]*MPPayment, + error) { + + var payments []*MPPayment + + // For older versions of lnd, duplicate payments to a payment has was + // possible. These will be found in a sub-bucket indexed by their + // sequence number if available. + dup := paymentHashBucket.Bucket(duplicatePaymentsBucket) + if dup == nil { + return nil, nil + } + + err := dup.ForEach(func(k, v []byte) error { + subBucket := dup.Bucket(k) + if subBucket == nil { + // We one bucket for each duplicate to be found. + return fmt.Errorf("non bucket element" + + "in duplicate bucket") + } + + p, err := fetchDuplicatePayment(subBucket) + if err != nil { + return err + } + + payments = append(payments, p) + return nil + }) + if err != nil { + return nil, err + } + + return payments, nil +} diff --git a/channeldb/payments.go b/channeldb/payments.go index ae6d8abd17..64f4f1c7c0 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -54,13 +54,6 @@ var ( // paymentsRootBucket = []byte("payments-root-bucket") - // paymentDublicateBucket is the name of a optional sub-bucket within - // the payment hash bucket, that is used to hold duplicate payments to - // a payment hash. This is needed to support information from earlier - // versions of lnd, where it was possible to pay to a payment hash more - // than once. - paymentDuplicateBucket = []byte("payment-duplicate-bucket") - // paymentSequenceKey is a key used in the payment's sub-bucket to // store the sequence number of the payment. paymentSequenceKey = []byte("payment-sequence-key") @@ -308,28 +301,14 @@ func (db *DB) FetchPayments() ([]*MPPayment, error) { // payment has was possible. These will be found in a // sub-bucket indexed by their sequence number if // available. - dup := bucket.Bucket(paymentDuplicateBucket) - if dup == nil { - return nil + duplicatePayments, err := fetchDuplicatePayments(bucket) + if err != nil { + return err } - return dup.ForEach(func(k, v []byte) error { - subBucket := dup.Bucket(k) - if subBucket == nil { - // We one bucket for each duplicate to - // be found. - return fmt.Errorf("non bucket element" + - "in duplicate bucket") - } - - p, err := fetchPayment(subBucket) - if err != nil { - return err - } - - payments = append(payments, p) - return nil - }) + payments = append(payments, duplicatePayments...) + + return nil }) }) if err != nil { From 6aab6c0bac14d5989b488b435a8bddae838805aa Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 13 Feb 2020 11:40:51 +0100 Subject: [PATCH 151/562] routerrpc+lnrpc: move htlc failure messages In a later commit, htlc raw failure messages will be exposed through the main rpc. This is a preparation for that. --- lnrpc/routerrpc/router.pb.go | 639 ++--------- lnrpc/routerrpc/router.proto | 160 +-- lnrpc/routerrpc/router_server.go | 58 +- lnrpc/rpc.pb.go | 1734 +++++++++++++++++++----------- lnrpc/rpc.proto | 160 +++ 5 files changed, 1374 insertions(+), 1377 deletions(-) diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index fe0b3bafd8..5951e4e958 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -79,112 +79,6 @@ func (PaymentState) EnumDescriptor() ([]byte, []int) { return fileDescriptor_7a0613f69d37b0a5, []int{0} } -type Failure_FailureCode int32 - -const ( - //* - //The numbers assigned in this enumeration match the failure codes as - //defined in BOLT #4. Because protobuf 3 requires enums to start with 0, - //a RESERVED value is added. - Failure_RESERVED Failure_FailureCode = 0 - Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS Failure_FailureCode = 1 - Failure_INCORRECT_PAYMENT_AMOUNT Failure_FailureCode = 2 - Failure_FINAL_INCORRECT_CLTV_EXPIRY Failure_FailureCode = 3 - Failure_FINAL_INCORRECT_HTLC_AMOUNT Failure_FailureCode = 4 - Failure_FINAL_EXPIRY_TOO_SOON Failure_FailureCode = 5 - Failure_INVALID_REALM Failure_FailureCode = 6 - Failure_EXPIRY_TOO_SOON Failure_FailureCode = 7 - Failure_INVALID_ONION_VERSION Failure_FailureCode = 8 - Failure_INVALID_ONION_HMAC Failure_FailureCode = 9 - Failure_INVALID_ONION_KEY Failure_FailureCode = 10 - Failure_AMOUNT_BELOW_MINIMUM Failure_FailureCode = 11 - Failure_FEE_INSUFFICIENT Failure_FailureCode = 12 - Failure_INCORRECT_CLTV_EXPIRY Failure_FailureCode = 13 - Failure_CHANNEL_DISABLED Failure_FailureCode = 14 - Failure_TEMPORARY_CHANNEL_FAILURE Failure_FailureCode = 15 - Failure_REQUIRED_NODE_FEATURE_MISSING Failure_FailureCode = 16 - Failure_REQUIRED_CHANNEL_FEATURE_MISSING Failure_FailureCode = 17 - Failure_UNKNOWN_NEXT_PEER Failure_FailureCode = 18 - Failure_TEMPORARY_NODE_FAILURE Failure_FailureCode = 19 - Failure_PERMANENT_NODE_FAILURE Failure_FailureCode = 20 - Failure_PERMANENT_CHANNEL_FAILURE Failure_FailureCode = 21 - Failure_EXPIRY_TOO_FAR Failure_FailureCode = 22 - Failure_MPP_TIMEOUT Failure_FailureCode = 23 - //* - //The error source is known, but the failure itself couldn't be decoded. - Failure_UNKNOWN_FAILURE Failure_FailureCode = 998 - //* - //An unreadable failure result is returned if the received failure message - //cannot be decrypted. In that case the error source is unknown. - Failure_UNREADABLE_FAILURE Failure_FailureCode = 999 -) - -var Failure_FailureCode_name = map[int32]string{ - 0: "RESERVED", - 1: "INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS", - 2: "INCORRECT_PAYMENT_AMOUNT", - 3: "FINAL_INCORRECT_CLTV_EXPIRY", - 4: "FINAL_INCORRECT_HTLC_AMOUNT", - 5: "FINAL_EXPIRY_TOO_SOON", - 6: "INVALID_REALM", - 7: "EXPIRY_TOO_SOON", - 8: "INVALID_ONION_VERSION", - 9: "INVALID_ONION_HMAC", - 10: "INVALID_ONION_KEY", - 11: "AMOUNT_BELOW_MINIMUM", - 12: "FEE_INSUFFICIENT", - 13: "INCORRECT_CLTV_EXPIRY", - 14: "CHANNEL_DISABLED", - 15: "TEMPORARY_CHANNEL_FAILURE", - 16: "REQUIRED_NODE_FEATURE_MISSING", - 17: "REQUIRED_CHANNEL_FEATURE_MISSING", - 18: "UNKNOWN_NEXT_PEER", - 19: "TEMPORARY_NODE_FAILURE", - 20: "PERMANENT_NODE_FAILURE", - 21: "PERMANENT_CHANNEL_FAILURE", - 22: "EXPIRY_TOO_FAR", - 23: "MPP_TIMEOUT", - 998: "UNKNOWN_FAILURE", - 999: "UNREADABLE_FAILURE", -} - -var Failure_FailureCode_value = map[string]int32{ - "RESERVED": 0, - "INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS": 1, - "INCORRECT_PAYMENT_AMOUNT": 2, - "FINAL_INCORRECT_CLTV_EXPIRY": 3, - "FINAL_INCORRECT_HTLC_AMOUNT": 4, - "FINAL_EXPIRY_TOO_SOON": 5, - "INVALID_REALM": 6, - "EXPIRY_TOO_SOON": 7, - "INVALID_ONION_VERSION": 8, - "INVALID_ONION_HMAC": 9, - "INVALID_ONION_KEY": 10, - "AMOUNT_BELOW_MINIMUM": 11, - "FEE_INSUFFICIENT": 12, - "INCORRECT_CLTV_EXPIRY": 13, - "CHANNEL_DISABLED": 14, - "TEMPORARY_CHANNEL_FAILURE": 15, - "REQUIRED_NODE_FEATURE_MISSING": 16, - "REQUIRED_CHANNEL_FEATURE_MISSING": 17, - "UNKNOWN_NEXT_PEER": 18, - "TEMPORARY_NODE_FAILURE": 19, - "PERMANENT_NODE_FAILURE": 20, - "PERMANENT_CHANNEL_FAILURE": 21, - "EXPIRY_TOO_FAR": 22, - "MPP_TIMEOUT": 23, - "UNKNOWN_FAILURE": 998, - "UNREADABLE_FAILURE": 999, -} - -func (x Failure_FailureCode) String() string { - return proto.EnumName(Failure_FailureCode_name, int32(x)) -} - -func (Failure_FailureCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{7, 0} -} - type SendPaymentRequest struct { /// The identity pubkey of the payment recipient Dest []byte `protobuf:"bytes,1,opt,name=dest,proto3" json:"dest,omitempty"` @@ -675,10 +569,10 @@ type SendToRouteResponse struct { /// The preimage obtained by making the payment. Preimage []byte `protobuf:"bytes,1,opt,name=preimage,proto3" json:"preimage,omitempty"` /// The failure message in case the payment failed. - Failure *Failure `protobuf:"bytes,2,opt,name=failure,proto3" json:"failure,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Failure *lnrpc.Failure `protobuf:"bytes,2,opt,name=failure,proto3" json:"failure,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *SendToRouteResponse) Reset() { *m = SendToRouteResponse{} } @@ -713,290 +607,13 @@ func (m *SendToRouteResponse) GetPreimage() []byte { return nil } -func (m *SendToRouteResponse) GetFailure() *Failure { +func (m *SendToRouteResponse) GetFailure() *lnrpc.Failure { if m != nil { return m.Failure } return nil } -type Failure struct { - /// Failure code as defined in the Lightning spec - Code Failure_FailureCode `protobuf:"varint,1,opt,name=code,proto3,enum=routerrpc.Failure_FailureCode" json:"code,omitempty"` - /// An optional channel update message. - ChannelUpdate *ChannelUpdate `protobuf:"bytes,3,opt,name=channel_update,json=channelUpdate,proto3" json:"channel_update,omitempty"` - /// A failure type-dependent htlc value. - HtlcMsat uint64 `protobuf:"varint,4,opt,name=htlc_msat,json=htlcMsat,proto3" json:"htlc_msat,omitempty"` - /// The sha256 sum of the onion payload. - OnionSha_256 []byte `protobuf:"bytes,5,opt,name=onion_sha_256,json=onionSha256,proto3" json:"onion_sha_256,omitempty"` - /// A failure type-dependent cltv expiry value. - CltvExpiry uint32 `protobuf:"varint,6,opt,name=cltv_expiry,json=cltvExpiry,proto3" json:"cltv_expiry,omitempty"` - /// A failure type-dependent flags value. - Flags uint32 `protobuf:"varint,7,opt,name=flags,proto3" json:"flags,omitempty"` - //* - //The position in the path of the intermediate or final node that generated - //the failure message. Position zero is the sender node. - FailureSourceIndex uint32 `protobuf:"varint,8,opt,name=failure_source_index,json=failureSourceIndex,proto3" json:"failure_source_index,omitempty"` - /// A failure type-dependent block height. - Height uint32 `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -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_7a0613f69d37b0a5, []int{7} -} - -func (m *Failure) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Failure.Unmarshal(m, b) -} -func (m *Failure) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Failure.Marshal(b, m, deterministic) -} -func (m *Failure) XXX_Merge(src proto.Message) { - xxx_messageInfo_Failure.Merge(m, src) -} -func (m *Failure) XXX_Size() int { - return xxx_messageInfo_Failure.Size(m) -} -func (m *Failure) XXX_DiscardUnknown() { - xxx_messageInfo_Failure.DiscardUnknown(m) -} - -var xxx_messageInfo_Failure proto.InternalMessageInfo - -func (m *Failure) GetCode() Failure_FailureCode { - if m != nil { - return m.Code - } - return Failure_RESERVED -} - -func (m *Failure) GetChannelUpdate() *ChannelUpdate { - if m != nil { - return m.ChannelUpdate - } - return nil -} - -func (m *Failure) GetHtlcMsat() uint64 { - if m != nil { - return m.HtlcMsat - } - return 0 -} - -func (m *Failure) GetOnionSha_256() []byte { - if m != nil { - return m.OnionSha_256 - } - return nil -} - -func (m *Failure) GetCltvExpiry() uint32 { - if m != nil { - return m.CltvExpiry - } - return 0 -} - -func (m *Failure) GetFlags() uint32 { - if m != nil { - return m.Flags - } - return 0 -} - -func (m *Failure) GetFailureSourceIndex() uint32 { - if m != nil { - return m.FailureSourceIndex - } - return 0 -} - -func (m *Failure) GetHeight() uint32 { - if m != nil { - return m.Height - } - return 0 -} - -type ChannelUpdate struct { - //* - //The signature that validates the announced data and proves the ownership - //of node id. - Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` - //* - //The target chain that this channel was opened within. This value - //should be the genesis hash of the target chain. Along with the short - //channel ID, this uniquely identifies the channel globally in a - //blockchain. - ChainHash []byte `protobuf:"bytes,2,opt,name=chain_hash,json=chainHash,proto3" json:"chain_hash,omitempty"` - //* - //The unique description of the funding transaction. - ChanId uint64 `protobuf:"varint,3,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` - //* - //A timestamp that allows ordering in the case of multiple announcements. - //We should ignore the message if timestamp is not greater than the - //last-received. - Timestamp uint32 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - //* - //The bitfield that describes whether optional fields are present in this - //update. Currently, the least-significant bit must be set to 1 if the - //optional field MaxHtlc is present. - MessageFlags uint32 `protobuf:"varint,10,opt,name=message_flags,json=messageFlags,proto3" json:"message_flags,omitempty"` - //* - //The bitfield that describes additional meta-data concerning how the - //update is to be interpreted. Currently, the least-significant bit must be - //set to 0 if the creating node corresponds to the first node in the - //previously sent channel announcement and 1 otherwise. If the second bit - //is set, then the channel is set to be disabled. - ChannelFlags uint32 `protobuf:"varint,5,opt,name=channel_flags,json=channelFlags,proto3" json:"channel_flags,omitempty"` - //* - //The minimum number of blocks this node requires to be added to the expiry - //of HTLCs. This is a security parameter determined by the node operator. - //This value represents the required gap between the time locks of the - //incoming and outgoing HTLC's set to this node. - TimeLockDelta uint32 `protobuf:"varint,6,opt,name=time_lock_delta,json=timeLockDelta,proto3" json:"time_lock_delta,omitempty"` - //* - //The minimum HTLC value which will be accepted. - HtlcMinimumMsat uint64 `protobuf:"varint,7,opt,name=htlc_minimum_msat,json=htlcMinimumMsat,proto3" json:"htlc_minimum_msat,omitempty"` - //* - //The base fee that must be used for incoming HTLC's to this particular - //channel. This value will be tacked onto the required for a payment - //independent of the size of the payment. - BaseFee uint32 `protobuf:"varint,8,opt,name=base_fee,json=baseFee,proto3" json:"base_fee,omitempty"` - //* - //The fee rate that will be charged per millionth of a satoshi. - FeeRate uint32 `protobuf:"varint,9,opt,name=fee_rate,json=feeRate,proto3" json:"fee_rate,omitempty"` - //* - //The maximum HTLC value which will be accepted. - HtlcMaximumMsat uint64 `protobuf:"varint,11,opt,name=htlc_maximum_msat,json=htlcMaximumMsat,proto3" json:"htlc_maximum_msat,omitempty"` - //* - //The set of data that was appended to this message, some of which we may - //not actually know how to iterate or parse. By holding onto this data, we - //ensure that we're able to properly validate the set of signatures that - //cover these new fields, and ensure we're able to make upgrades to the - //network in a forwards compatible manner. - ExtraOpaqueData []byte `protobuf:"bytes,12,opt,name=extra_opaque_data,json=extraOpaqueData,proto3" json:"extra_opaque_data,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -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_7a0613f69d37b0a5, []int{8} -} - -func (m *ChannelUpdate) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ChannelUpdate.Unmarshal(m, b) -} -func (m *ChannelUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ChannelUpdate.Marshal(b, m, deterministic) -} -func (m *ChannelUpdate) XXX_Merge(src proto.Message) { - xxx_messageInfo_ChannelUpdate.Merge(m, src) -} -func (m *ChannelUpdate) XXX_Size() int { - return xxx_messageInfo_ChannelUpdate.Size(m) -} -func (m *ChannelUpdate) XXX_DiscardUnknown() { - xxx_messageInfo_ChannelUpdate.DiscardUnknown(m) -} - -var xxx_messageInfo_ChannelUpdate proto.InternalMessageInfo - -func (m *ChannelUpdate) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -func (m *ChannelUpdate) GetChainHash() []byte { - if m != nil { - return m.ChainHash - } - return nil -} - -func (m *ChannelUpdate) GetChanId() uint64 { - if m != nil { - return m.ChanId - } - return 0 -} - -func (m *ChannelUpdate) GetTimestamp() uint32 { - if m != nil { - return m.Timestamp - } - return 0 -} - -func (m *ChannelUpdate) GetMessageFlags() uint32 { - if m != nil { - return m.MessageFlags - } - return 0 -} - -func (m *ChannelUpdate) GetChannelFlags() uint32 { - if m != nil { - return m.ChannelFlags - } - return 0 -} - -func (m *ChannelUpdate) GetTimeLockDelta() uint32 { - if m != nil { - return m.TimeLockDelta - } - return 0 -} - -func (m *ChannelUpdate) GetHtlcMinimumMsat() uint64 { - if m != nil { - return m.HtlcMinimumMsat - } - return 0 -} - -func (m *ChannelUpdate) GetBaseFee() uint32 { - if m != nil { - return m.BaseFee - } - return 0 -} - -func (m *ChannelUpdate) GetFeeRate() uint32 { - if m != nil { - return m.FeeRate - } - return 0 -} - -func (m *ChannelUpdate) GetHtlcMaximumMsat() uint64 { - if m != nil { - return m.HtlcMaximumMsat - } - return 0 -} - -func (m *ChannelUpdate) GetExtraOpaqueData() []byte { - if m != nil { - return m.ExtraOpaqueData - } - return nil -} - type ResetMissionControlRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -1007,7 +624,7 @@ func (m *ResetMissionControlRequest) Reset() { *m = ResetMissionControlR func (m *ResetMissionControlRequest) String() string { return proto.CompactTextString(m) } func (*ResetMissionControlRequest) ProtoMessage() {} func (*ResetMissionControlRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{9} + return fileDescriptor_7a0613f69d37b0a5, []int{7} } func (m *ResetMissionControlRequest) XXX_Unmarshal(b []byte) error { @@ -1038,7 +655,7 @@ func (m *ResetMissionControlResponse) Reset() { *m = ResetMissionControl func (m *ResetMissionControlResponse) String() string { return proto.CompactTextString(m) } func (*ResetMissionControlResponse) ProtoMessage() {} func (*ResetMissionControlResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{10} + return fileDescriptor_7a0613f69d37b0a5, []int{8} } func (m *ResetMissionControlResponse) XXX_Unmarshal(b []byte) error { @@ -1069,7 +686,7 @@ func (m *QueryMissionControlRequest) Reset() { *m = QueryMissionControlR func (m *QueryMissionControlRequest) String() string { return proto.CompactTextString(m) } func (*QueryMissionControlRequest) ProtoMessage() {} func (*QueryMissionControlRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{11} + return fileDescriptor_7a0613f69d37b0a5, []int{9} } func (m *QueryMissionControlRequest) XXX_Unmarshal(b []byte) error { @@ -1103,7 +720,7 @@ func (m *QueryMissionControlResponse) Reset() { *m = QueryMissionControl func (m *QueryMissionControlResponse) String() string { return proto.CompactTextString(m) } func (*QueryMissionControlResponse) ProtoMessage() {} func (*QueryMissionControlResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{12} + return fileDescriptor_7a0613f69d37b0a5, []int{10} } func (m *QueryMissionControlResponse) XXX_Unmarshal(b []byte) error { @@ -1147,7 +764,7 @@ func (m *PairHistory) Reset() { *m = PairHistory{} } func (m *PairHistory) String() string { return proto.CompactTextString(m) } func (*PairHistory) ProtoMessage() {} func (*PairHistory) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{13} + return fileDescriptor_7a0613f69d37b0a5, []int{11} } func (m *PairHistory) XXX_Unmarshal(b []byte) error { @@ -1215,7 +832,7 @@ func (m *PairData) Reset() { *m = PairData{} } func (m *PairData) String() string { return proto.CompactTextString(m) } func (*PairData) ProtoMessage() {} func (*PairData) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{14} + return fileDescriptor_7a0613f69d37b0a5, []int{12} } func (m *PairData) XXX_Unmarshal(b []byte) error { @@ -1294,7 +911,7 @@ func (m *QueryProbabilityRequest) Reset() { *m = QueryProbabilityRequest func (m *QueryProbabilityRequest) String() string { return proto.CompactTextString(m) } func (*QueryProbabilityRequest) ProtoMessage() {} func (*QueryProbabilityRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{15} + return fileDescriptor_7a0613f69d37b0a5, []int{13} } func (m *QueryProbabilityRequest) XXX_Unmarshal(b []byte) error { @@ -1350,7 +967,7 @@ func (m *QueryProbabilityResponse) Reset() { *m = QueryProbabilityRespon func (m *QueryProbabilityResponse) String() string { return proto.CompactTextString(m) } func (*QueryProbabilityResponse) ProtoMessage() {} func (*QueryProbabilityResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{16} + return fileDescriptor_7a0613f69d37b0a5, []int{14} } func (m *QueryProbabilityResponse) XXX_Unmarshal(b []byte) error { @@ -1411,7 +1028,7 @@ func (m *BuildRouteRequest) Reset() { *m = BuildRouteRequest{} } func (m *BuildRouteRequest) String() string { return proto.CompactTextString(m) } func (*BuildRouteRequest) ProtoMessage() {} func (*BuildRouteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{17} + return fileDescriptor_7a0613f69d37b0a5, []int{15} } func (m *BuildRouteRequest) XXX_Unmarshal(b []byte) error { @@ -1473,7 +1090,7 @@ func (m *BuildRouteResponse) Reset() { *m = BuildRouteResponse{} } func (m *BuildRouteResponse) String() string { return proto.CompactTextString(m) } func (*BuildRouteResponse) ProtoMessage() {} func (*BuildRouteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{18} + return fileDescriptor_7a0613f69d37b0a5, []int{16} } func (m *BuildRouteResponse) XXX_Unmarshal(b []byte) error { @@ -1503,7 +1120,6 @@ func (m *BuildRouteResponse) GetRoute() *lnrpc.Route { func init() { proto.RegisterEnum("routerrpc.PaymentState", PaymentState_name, PaymentState_value) - proto.RegisterEnum("routerrpc.Failure_FailureCode", Failure_FailureCode_name, Failure_FailureCode_value) proto.RegisterType((*SendPaymentRequest)(nil), "routerrpc.SendPaymentRequest") proto.RegisterMapType((map[uint64][]byte)(nil), "routerrpc.SendPaymentRequest.DestCustomRecordsEntry") proto.RegisterType((*TrackPaymentRequest)(nil), "routerrpc.TrackPaymentRequest") @@ -1512,8 +1128,6 @@ func init() { proto.RegisterType((*RouteFeeResponse)(nil), "routerrpc.RouteFeeResponse") proto.RegisterType((*SendToRouteRequest)(nil), "routerrpc.SendToRouteRequest") proto.RegisterType((*SendToRouteResponse)(nil), "routerrpc.SendToRouteResponse") - proto.RegisterType((*Failure)(nil), "routerrpc.Failure") - proto.RegisterType((*ChannelUpdate)(nil), "routerrpc.ChannelUpdate") proto.RegisterType((*ResetMissionControlRequest)(nil), "routerrpc.ResetMissionControlRequest") proto.RegisterType((*ResetMissionControlResponse)(nil), "routerrpc.ResetMissionControlResponse") proto.RegisterType((*QueryMissionControlRequest)(nil), "routerrpc.QueryMissionControlRequest") @@ -1529,140 +1143,95 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2126 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xcd, 0x76, 0xdb, 0xc6, - 0x15, 0x0e, 0xc4, 0x5f, 0x5d, 0xfe, 0x41, 0x23, 0x45, 0xa2, 0x29, 0x2b, 0x61, 0x10, 0xd7, 0xe1, - 0xf1, 0x71, 0x24, 0x47, 0x6d, 0x7c, 0x7c, 0xba, 0x68, 0x0f, 0x45, 0x82, 0x11, 0x64, 0x12, 0x94, - 0x87, 0xa4, 0x13, 0x37, 0x8b, 0x39, 0x10, 0x39, 0x12, 0x51, 0xe1, 0x87, 0x01, 0x86, 0x8e, 0xf5, - 0x02, 0x5d, 0xf4, 0x45, 0xda, 0x4d, 0xbb, 0xe9, 0xba, 0xaf, 0xd3, 0xf6, 0x11, 0xba, 0xec, 0x99, - 0x19, 0x80, 0x04, 0x29, 0xca, 0xe9, 0x4a, 0xc4, 0x77, 0xbf, 0xb9, 0x77, 0x66, 0xee, 0xdc, 0x3f, - 0xc1, 0x7e, 0xe0, 0xcf, 0x19, 0x0d, 0x82, 0xd9, 0xf8, 0x44, 0xfe, 0x3a, 0x9e, 0x05, 0x3e, 0xf3, - 0xd1, 0xf6, 0x02, 0xaf, 0x6d, 0x07, 0xb3, 0xb1, 0x44, 0xb5, 0xff, 0x66, 0x00, 0x0d, 0xa8, 0x37, - 0xb9, 0xb4, 0xee, 0x5c, 0xea, 0x31, 0x4c, 0x7f, 0x9a, 0xd3, 0x90, 0x21, 0x04, 0xe9, 0x09, 0x0d, - 0x59, 0x55, 0xa9, 0x2b, 0x8d, 0x22, 0x16, 0xbf, 0x91, 0x0a, 0x29, 0xcb, 0x65, 0xd5, 0xad, 0xba, - 0xd2, 0x48, 0x61, 0xfe, 0x13, 0x3d, 0x82, 0xbc, 0xe5, 0x32, 0xe2, 0x86, 0x16, 0xab, 0x16, 0x05, - 0x9c, 0xb3, 0x5c, 0xd6, 0x0b, 0x2d, 0x86, 0xbe, 0x80, 0xe2, 0x4c, 0xaa, 0x24, 0x53, 0x2b, 0x9c, - 0x56, 0x53, 0x42, 0x51, 0x21, 0xc2, 0xce, 0xad, 0x70, 0x8a, 0x1a, 0xa0, 0x5e, 0xdb, 0x9e, 0xe5, - 0x90, 0xb1, 0xc3, 0xde, 0x93, 0x09, 0x75, 0x98, 0x55, 0x4d, 0xd7, 0x95, 0x46, 0x06, 0x97, 0x05, - 0xde, 0x72, 0xd8, 0xfb, 0x36, 0x47, 0xd1, 0x57, 0x50, 0x89, 0x95, 0x05, 0x72, 0x83, 0xd5, 0x4c, - 0x5d, 0x69, 0x6c, 0xe3, 0xf2, 0x6c, 0x75, 0xdb, 0x5f, 0x41, 0x85, 0xd9, 0x2e, 0xf5, 0xe7, 0x8c, - 0x84, 0x74, 0xec, 0x7b, 0x93, 0xb0, 0x9a, 0x95, 0x1a, 0x23, 0x78, 0x20, 0x51, 0xa4, 0x41, 0xe9, - 0x9a, 0x52, 0xe2, 0xd8, 0xae, 0xcd, 0x08, 0xdf, 0x7e, 0x4e, 0x6c, 0xbf, 0x70, 0x4d, 0x69, 0x97, - 0x63, 0x03, 0x8b, 0xa1, 0x27, 0x50, 0x5e, 0x72, 0xc4, 0x19, 0x4b, 0x82, 0x54, 0x8c, 0x49, 0xe2, - 0xa0, 0xcf, 0x41, 0xf5, 0xe7, 0xec, 0xc6, 0xb7, 0xbd, 0x1b, 0x32, 0x9e, 0x5a, 0x1e, 0xb1, 0x27, - 0xd5, 0x7c, 0x5d, 0x69, 0xa4, 0xcf, 0xb6, 0x5e, 0x28, 0xb8, 0x1c, 0xcb, 0x5a, 0x53, 0xcb, 0x33, - 0x26, 0xe8, 0x29, 0x54, 0x1c, 0x2b, 0x64, 0x64, 0xea, 0xcf, 0xc8, 0x6c, 0x7e, 0x75, 0x4b, 0xef, - 0xaa, 0x65, 0x71, 0x33, 0x25, 0x0e, 0x9f, 0xfb, 0xb3, 0x4b, 0x01, 0xa2, 0x23, 0x00, 0x71, 0x2b, - 0xc2, 0x78, 0x75, 0x5b, 0x9c, 0x61, 0x9b, 0x23, 0xc2, 0x30, 0xfa, 0x06, 0x0a, 0xc2, 0x9b, 0x64, - 0x6a, 0x7b, 0x2c, 0xac, 0x42, 0x3d, 0xd5, 0x28, 0x9c, 0xaa, 0xc7, 0x8e, 0xc7, 0x1d, 0x8b, 0xb9, - 0xe4, 0xdc, 0xf6, 0x18, 0x86, 0x20, 0xfe, 0x19, 0xa2, 0x09, 0xec, 0x72, 0x2f, 0x92, 0xf1, 0x3c, - 0x64, 0xbe, 0x4b, 0x02, 0x3a, 0xf6, 0x83, 0x49, 0x58, 0x2d, 0x88, 0xa5, 0xbf, 0x39, 0x5e, 0x3c, - 0x8e, 0xe3, 0xfb, 0xaf, 0xe1, 0xb8, 0x4d, 0x43, 0xd6, 0x12, 0xeb, 0xb0, 0x5c, 0xa6, 0x7b, 0x2c, - 0xb8, 0xc3, 0x3b, 0x93, 0x75, 0x1c, 0x3d, 0x07, 0x64, 0x39, 0x8e, 0xff, 0x33, 0x09, 0xa9, 0x73, - 0x4d, 0x22, 0xef, 0x54, 0x2b, 0x75, 0xa5, 0x91, 0xc7, 0xaa, 0x90, 0x0c, 0xa8, 0x73, 0x1d, 0xa9, - 0x47, 0x2f, 0xa1, 0x24, 0xf6, 0x74, 0x4d, 0x2d, 0x36, 0x0f, 0x68, 0x58, 0x55, 0xeb, 0xa9, 0x46, - 0xf9, 0x74, 0x27, 0x3a, 0x48, 0x47, 0xc2, 0x67, 0x36, 0xc3, 0x45, 0xce, 0x8b, 0xbe, 0xc3, 0x5a, - 0x1b, 0xf6, 0x37, 0x6f, 0x89, 0xbf, 0x51, 0x7e, 0xa7, 0xfc, 0xd9, 0xa6, 0x31, 0xff, 0x89, 0xf6, - 0x20, 0xf3, 0xde, 0x72, 0xe6, 0x54, 0xbc, 0xdb, 0x22, 0x96, 0x1f, 0xbf, 0xdd, 0x7a, 0xa5, 0x68, - 0xaf, 0x60, 0x77, 0x18, 0x58, 0xe3, 0xdb, 0xb5, 0xa7, 0xbf, 0xfe, 0x72, 0x95, 0x7b, 0x2f, 0x57, - 0xfb, 0xab, 0x02, 0xa5, 0x68, 0xd5, 0x80, 0x59, 0x6c, 0x1e, 0xa2, 0xaf, 0x21, 0x13, 0x32, 0x8b, - 0x51, 0xc1, 0x2e, 0x9f, 0x1e, 0x24, 0xee, 0x33, 0x41, 0xa4, 0x58, 0xb2, 0x50, 0x0d, 0xf2, 0xb3, - 0x80, 0xda, 0xae, 0x75, 0x13, 0xef, 0x6b, 0xf1, 0x8d, 0x34, 0xc8, 0x88, 0xc5, 0x22, 0x64, 0x0a, - 0xa7, 0xc5, 0xa4, 0x57, 0xb1, 0x14, 0xa1, 0x06, 0x64, 0xa6, 0xcc, 0x19, 0x87, 0xd5, 0xb4, 0x70, - 0x1f, 0x8a, 0x38, 0xe7, 0xc3, 0x6e, 0xab, 0xc9, 0x18, 0x75, 0x67, 0x0c, 0x4b, 0x82, 0xf6, 0x3b, - 0xa8, 0x88, 0x95, 0x1d, 0x4a, 0x3f, 0x16, 0xdb, 0x07, 0xc0, 0x23, 0x57, 0x44, 0x82, 0x8c, 0xef, - 0xac, 0xe5, 0xf2, 0x20, 0xd0, 0x26, 0xa0, 0x2e, 0xd7, 0x87, 0x33, 0xdf, 0x0b, 0xb9, 0x75, 0x95, - 0x6f, 0x83, 0xbf, 0x78, 0x1e, 0x20, 0x22, 0x34, 0x14, 0xb1, 0xaa, 0x1c, 0xe1, 0x1d, 0x4a, 0x45, - 0x70, 0x3c, 0x95, 0xf1, 0x48, 0x1c, 0x7f, 0x7c, 0xcb, 0x23, 0xdc, 0xba, 0x8b, 0xd4, 0x97, 0x38, - 0xdc, 0xf5, 0xc7, 0xb7, 0x6d, 0x0e, 0x6a, 0x3f, 0xca, 0x24, 0x34, 0xf4, 0xe5, 0x29, 0xff, 0x6f, - 0x4f, 0x2c, 0x2f, 0x6b, 0xeb, 0xc1, 0xcb, 0xd2, 0x08, 0xec, 0xae, 0x28, 0x8f, 0x4e, 0x91, 0xf4, - 0x81, 0xb2, 0xe6, 0x83, 0xe7, 0x90, 0xbb, 0xb6, 0x6c, 0x67, 0x1e, 0xc4, 0x8a, 0x51, 0xc2, 0xa1, - 0x1d, 0x29, 0xc1, 0x31, 0x45, 0xfb, 0x53, 0x1e, 0x72, 0x11, 0x88, 0x4e, 0x21, 0x3d, 0xf6, 0x27, - 0xf1, 0x3b, 0xf8, 0xec, 0xfe, 0xb2, 0xf8, 0x6f, 0xcb, 0x9f, 0x50, 0x2c, 0xb8, 0xe8, 0xf7, 0x50, - 0xe6, 0x99, 0xc3, 0xa3, 0x0e, 0x99, 0xcf, 0x26, 0xd6, 0xc2, 0xf5, 0xd5, 0xc4, 0xea, 0x96, 0x24, - 0x8c, 0x84, 0x1c, 0x97, 0xc6, 0xc9, 0x4f, 0x74, 0x08, 0xdb, 0xdc, 0xdb, 0xd2, 0x13, 0x69, 0xf1, - 0xf6, 0xf3, 0x1c, 0x10, 0x3e, 0xd0, 0xa0, 0xe4, 0x7b, 0xb6, 0xef, 0x91, 0x70, 0x6a, 0x91, 0xd3, - 0x6f, 0x5f, 0x8a, 0xd4, 0x59, 0xc4, 0x05, 0x01, 0x0e, 0xa6, 0xd6, 0xe9, 0xb7, 0x2f, 0xd1, 0xe7, - 0x50, 0x10, 0xe9, 0x86, 0x7e, 0x98, 0xd9, 0xc1, 0x9d, 0xc8, 0x99, 0x25, 0x2c, 0x32, 0x90, 0x2e, - 0x10, 0x1e, 0x45, 0xd7, 0x8e, 0x75, 0x13, 0x8a, 0x3c, 0x59, 0xc2, 0xf2, 0x03, 0xbd, 0x80, 0xbd, - 0xe8, 0x0e, 0x48, 0xe8, 0xcf, 0x83, 0x31, 0x25, 0xb6, 0x37, 0xa1, 0x1f, 0x44, 0xfe, 0x2b, 0x61, - 0x14, 0xc9, 0x06, 0x42, 0x64, 0x70, 0x09, 0xda, 0x87, 0xec, 0x94, 0xda, 0x37, 0x53, 0x99, 0xd3, - 0x4a, 0x38, 0xfa, 0xd2, 0xfe, 0x99, 0x81, 0x42, 0xe2, 0x62, 0x50, 0x11, 0xf2, 0x58, 0x1f, 0xe8, - 0xf8, 0xad, 0xde, 0x56, 0x3f, 0x41, 0x0d, 0x78, 0x62, 0x98, 0xad, 0x3e, 0xc6, 0x7a, 0x6b, 0x48, - 0xfa, 0x98, 0x8c, 0xcc, 0xd7, 0x66, 0xff, 0x7b, 0x93, 0x5c, 0x36, 0xdf, 0xf5, 0x74, 0x73, 0x48, - 0xda, 0xfa, 0xb0, 0x69, 0x74, 0x07, 0xaa, 0x82, 0x1e, 0x43, 0x75, 0xc9, 0x8c, 0xc5, 0xcd, 0x5e, - 0x7f, 0x64, 0x0e, 0xd5, 0x2d, 0xf4, 0x39, 0x1c, 0x76, 0x0c, 0xb3, 0xd9, 0x25, 0x4b, 0x4e, 0xab, - 0x3b, 0x7c, 0x4b, 0xf4, 0x1f, 0x2e, 0x0d, 0xfc, 0x4e, 0x4d, 0x6d, 0x22, 0xf0, 0x98, 0x8a, 0x35, - 0xa4, 0xd1, 0x23, 0xf8, 0x54, 0x12, 0xe4, 0x12, 0x32, 0xec, 0xf7, 0xc9, 0xa0, 0xdf, 0x37, 0xd5, - 0x0c, 0xda, 0x81, 0x92, 0x61, 0xbe, 0x6d, 0x76, 0x8d, 0x36, 0xc1, 0x7a, 0xb3, 0xdb, 0x53, 0xb3, - 0x68, 0x17, 0x2a, 0xeb, 0xbc, 0x1c, 0x57, 0x11, 0xf3, 0xfa, 0xa6, 0xd1, 0x37, 0xc9, 0x5b, 0x1d, - 0x0f, 0x8c, 0xbe, 0xa9, 0xe6, 0xd1, 0x3e, 0xa0, 0x55, 0xd1, 0x79, 0xaf, 0xd9, 0x52, 0xb7, 0xd1, - 0xa7, 0xb0, 0xb3, 0x8a, 0xbf, 0xd6, 0xdf, 0xa9, 0x80, 0xaa, 0xb0, 0x27, 0x37, 0x46, 0xce, 0xf4, - 0x6e, 0xff, 0x7b, 0xd2, 0x33, 0x4c, 0xa3, 0x37, 0xea, 0xa9, 0x05, 0xb4, 0x07, 0x6a, 0x47, 0xd7, - 0x89, 0x61, 0x0e, 0x46, 0x9d, 0x8e, 0xd1, 0x32, 0x74, 0x73, 0xa8, 0x16, 0xa5, 0xe5, 0x4d, 0x07, - 0x2f, 0xf1, 0x05, 0xad, 0xf3, 0xa6, 0x69, 0xea, 0x5d, 0xd2, 0x36, 0x06, 0xcd, 0xb3, 0xae, 0xde, - 0x56, 0xcb, 0xe8, 0x08, 0x1e, 0x0d, 0xf5, 0xde, 0x65, 0x1f, 0x37, 0xf1, 0x3b, 0x12, 0xcb, 0x3b, - 0x4d, 0xa3, 0x3b, 0xc2, 0xba, 0x5a, 0x41, 0x5f, 0xc0, 0x11, 0xd6, 0xdf, 0x8c, 0x0c, 0xac, 0xb7, - 0x89, 0xd9, 0x6f, 0xeb, 0xa4, 0xa3, 0x37, 0x87, 0x23, 0xac, 0x93, 0x9e, 0x31, 0x18, 0x18, 0xe6, - 0x77, 0xaa, 0x8a, 0x9e, 0x40, 0x7d, 0x41, 0x59, 0x28, 0x58, 0x63, 0xed, 0xf0, 0xf3, 0xc5, 0x2e, - 0x35, 0xf5, 0x1f, 0x86, 0xe4, 0x52, 0xd7, 0xb1, 0x8a, 0x50, 0x0d, 0xf6, 0x97, 0xe6, 0xa5, 0x81, - 0xc8, 0xf6, 0x2e, 0x97, 0x5d, 0xea, 0xb8, 0xd7, 0x34, 0xb9, 0x83, 0x57, 0x64, 0x7b, 0x7c, 0xdb, - 0x4b, 0xd9, 0xfa, 0xb6, 0x3f, 0x45, 0x08, 0xca, 0x09, 0xaf, 0x74, 0x9a, 0x58, 0xdd, 0x47, 0x15, - 0x28, 0xf4, 0x2e, 0x2f, 0xc9, 0xd0, 0xe8, 0xe9, 0xfd, 0xd1, 0x50, 0x3d, 0x40, 0x7b, 0x50, 0x89, - 0xb7, 0x14, 0xaf, 0xfc, 0x57, 0x0e, 0x1d, 0x00, 0x1a, 0x99, 0x58, 0x6f, 0xb6, 0xf9, 0x0d, 0x2d, - 0x04, 0xff, 0xce, 0x5d, 0xa4, 0xf3, 0x5b, 0x6a, 0x4a, 0xfb, 0x47, 0x0a, 0x4a, 0x2b, 0x81, 0x8a, - 0x1e, 0xc3, 0x76, 0x68, 0xdf, 0x78, 0xa2, 0x6e, 0x45, 0x59, 0x66, 0x09, 0x88, 0x2a, 0x3f, 0xb5, - 0x6c, 0x4f, 0xa6, 0x37, 0x59, 0x08, 0xb6, 0x05, 0x22, 0x92, 0xdb, 0x21, 0xe4, 0xe2, 0x8e, 0x22, - 0xb5, 0xe8, 0x28, 0xb2, 0x63, 0xd9, 0x49, 0x3c, 0x86, 0x6d, 0x9e, 0x43, 0x43, 0x66, 0xb9, 0x33, - 0x11, 0xf3, 0x25, 0xbc, 0x04, 0xd0, 0x97, 0x50, 0x72, 0x69, 0x18, 0x5a, 0x37, 0x94, 0xc8, 0xb8, - 0x05, 0xc1, 0x28, 0x46, 0x60, 0x47, 0x84, 0xef, 0x97, 0x10, 0xe7, 0x91, 0x88, 0x94, 0x91, 0xa4, - 0x08, 0x94, 0xa4, 0xf5, 0x14, 0xce, 0xac, 0x28, 0x3d, 0x24, 0x53, 0x38, 0xb3, 0xd0, 0x33, 0xd8, - 0x91, 0x39, 0xc8, 0xf6, 0x6c, 0x77, 0xee, 0xca, 0x5c, 0x94, 0x13, 0xb9, 0xa8, 0x22, 0x72, 0x91, - 0xc4, 0x45, 0x4a, 0x7a, 0x04, 0xf9, 0x2b, 0x2b, 0xa4, 0xbc, 0x7a, 0x44, 0xb9, 0x22, 0xc7, 0xbf, - 0x3b, 0x94, 0x72, 0x11, 0xaf, 0x29, 0x01, 0xcf, 0x82, 0x32, 0x45, 0xe4, 0xae, 0x29, 0xc5, 0xfc, - 0x2e, 0x17, 0x16, 0xac, 0x0f, 0x4b, 0x0b, 0x85, 0x84, 0x05, 0x89, 0x0b, 0x0b, 0xcf, 0x60, 0x87, - 0x7e, 0x60, 0x81, 0x45, 0xfc, 0x99, 0xf5, 0xd3, 0x9c, 0x92, 0x89, 0xc5, 0x2c, 0xd1, 0xa2, 0x16, - 0x71, 0x45, 0x08, 0xfa, 0x02, 0x6f, 0x5b, 0xcc, 0xd2, 0x1e, 0x43, 0x0d, 0xd3, 0x90, 0xb2, 0x9e, - 0x1d, 0x86, 0xb6, 0xef, 0xb5, 0x7c, 0x8f, 0x05, 0xbe, 0x13, 0x15, 0x21, 0xed, 0x08, 0x0e, 0x37, - 0x4a, 0x65, 0x15, 0xe1, 0x8b, 0xdf, 0xcc, 0x69, 0x70, 0xb7, 0x79, 0xf1, 0x1b, 0x38, 0xdc, 0x28, - 0x8d, 0x4a, 0xd0, 0x73, 0xc8, 0xcc, 0x2c, 0x3b, 0x08, 0xab, 0x5b, 0xa2, 0x8c, 0xef, 0xaf, 0x74, - 0x0d, 0x76, 0x70, 0x6e, 0x87, 0xcc, 0x0f, 0xee, 0xb0, 0x24, 0x5d, 0xa4, 0xf3, 0x8a, 0xba, 0xa5, - 0xfd, 0x59, 0x81, 0x42, 0x42, 0xc8, 0x73, 0xbf, 0xe7, 0x4f, 0x28, 0xb9, 0x0e, 0x7c, 0x37, 0xae, - 0x63, 0x1c, 0xe8, 0x04, 0xbe, 0xcb, 0xcb, 0xba, 0x10, 0x32, 0x3f, 0x7a, 0x5d, 0x59, 0xfe, 0x39, - 0xf4, 0xd1, 0xd7, 0x90, 0x9b, 0x4a, 0x05, 0xc2, 0x47, 0x85, 0xd3, 0xdd, 0x35, 0xdb, 0xfc, 0x66, - 0x70, 0xcc, 0xb9, 0x48, 0xe7, 0x53, 0x6a, 0xfa, 0x22, 0x9d, 0x4f, 0xab, 0x99, 0x8b, 0x74, 0x3e, - 0xa3, 0x66, 0x2f, 0xd2, 0xf9, 0xac, 0x9a, 0xd3, 0xfe, 0xa3, 0x40, 0x3e, 0x66, 0xf3, 0x9d, 0xf0, - 0x8c, 0x4f, 0xf8, 0xbb, 0x88, 0xfa, 0x81, 0x3c, 0x07, 0x86, 0xb6, 0x4b, 0x51, 0x1d, 0x8a, 0x42, - 0xb8, 0xda, 0x65, 0x00, 0xc7, 0x9a, 0xa2, 0xd3, 0x10, 0x2d, 0x79, 0xcc, 0x58, 0x14, 0x32, 0xde, - 0x92, 0x4b, 0x4a, 0x3c, 0x55, 0x84, 0xf3, 0xf1, 0x98, 0x86, 0xa1, 0xb4, 0x92, 0x91, 0x94, 0x08, - 0x13, 0x86, 0x9e, 0x42, 0x25, 0xa6, 0xc4, 0xb6, 0xb2, 0xb2, 0xe5, 0x88, 0xe0, 0xc8, 0x5c, 0x03, - 0xd4, 0x24, 0xcf, 0x5d, 0x0e, 0x01, 0xe5, 0x25, 0x91, 0x1b, 0x95, 0x87, 0xd7, 0xfe, 0x08, 0x07, - 0xc2, 0x95, 0x97, 0x81, 0x7f, 0x65, 0x5d, 0xd9, 0x8e, 0xcd, 0xee, 0xe2, 0x3e, 0x85, 0x1f, 0x3c, - 0xf0, 0x5d, 0xe2, 0xc5, 0x85, 0xbf, 0x88, 0xf3, 0x1c, 0x30, 0x79, 0x25, 0x3b, 0x80, 0x1c, 0xf3, - 0xa5, 0x28, 0x72, 0x01, 0xf3, 0x85, 0x20, 0x39, 0x3c, 0xa5, 0x56, 0x86, 0x27, 0xed, 0x16, 0xaa, - 0xf7, 0x6d, 0x45, 0x6f, 0xa6, 0x0e, 0x85, 0xd9, 0x12, 0x16, 0xe6, 0x14, 0x9c, 0x84, 0x92, 0xbe, - 0xdd, 0xfa, 0x65, 0xdf, 0x6a, 0x7f, 0x51, 0x60, 0xe7, 0x6c, 0x6e, 0x3b, 0x93, 0x95, 0xde, 0x2b, - 0xb9, 0x3b, 0x65, 0x75, 0xb4, 0xdb, 0x34, 0xb7, 0x6d, 0x6d, 0x9c, 0xdb, 0x36, 0xcd, 0x46, 0xa9, - 0x07, 0x67, 0xa3, 0xcf, 0xa1, 0xb0, 0x1c, 0x8b, 0x64, 0x6b, 0x5b, 0xc4, 0x30, 0x8d, 0x67, 0xa2, - 0x50, 0x7b, 0x05, 0x28, 0xb9, 0xd1, 0xe8, 0x42, 0x16, 0x2d, 0xa0, 0xf2, 0x60, 0x0b, 0xf8, 0xec, - 0xef, 0x0a, 0x14, 0x93, 0x7d, 0x38, 0x2a, 0xc1, 0xb6, 0x61, 0x92, 0x4e, 0xd7, 0xf8, 0xee, 0x7c, - 0xa8, 0x7e, 0xc2, 0x3f, 0x07, 0xa3, 0x56, 0x4b, 0xd7, 0xdb, 0x7a, 0x5b, 0x55, 0x78, 0x85, 0xe0, - 0xb9, 0x5d, 0x6f, 0x2f, 0x0a, 0xc2, 0x16, 0xaf, 0xe5, 0x11, 0x66, 0xf6, 0x09, 0xee, 0x8f, 0x86, - 0xba, 0x9a, 0x42, 0x2a, 0x14, 0x23, 0x50, 0xc7, 0xb8, 0x8f, 0xd5, 0x34, 0x2f, 0x78, 0x11, 0x72, - 0xbf, 0x0f, 0x89, 0xdb, 0x94, 0x8c, 0xe8, 0x33, 0x62, 0xd6, 0xb2, 0x44, 0x93, 0xb3, 0x66, 0xb7, - 0x69, 0xb6, 0x74, 0x35, 0x7b, 0xfa, 0xb7, 0x0c, 0x64, 0xc5, 0x09, 0x02, 0x74, 0x0e, 0x85, 0xc4, - 0x48, 0x86, 0x8e, 0x3e, 0x3a, 0xaa, 0xd5, 0xaa, 0x9b, 0x27, 0x8f, 0x79, 0xf8, 0x42, 0x41, 0x17, - 0x50, 0x4c, 0x0e, 0x3c, 0x28, 0xd9, 0x9d, 0x6e, 0x98, 0x84, 0x3e, 0xaa, 0xeb, 0x35, 0xa8, 0x7a, - 0xc8, 0x6c, 0x97, 0x77, 0xa3, 0xd1, 0x7c, 0x80, 0x6a, 0x09, 0xfe, 0xda, 0xd0, 0x51, 0x3b, 0xdc, - 0x28, 0x8b, 0x5c, 0xd8, 0x95, 0x47, 0x8c, 0x3a, 0xf4, 0x7b, 0x47, 0x5c, 0x1d, 0x0b, 0x6a, 0x9f, - 0x3d, 0x24, 0x8e, 0xb4, 0x4d, 0x60, 0x77, 0x43, 0xc6, 0x46, 0xbf, 0x4a, 0xee, 0xe0, 0xc1, 0x7c, - 0x5f, 0x7b, 0xfa, 0x4b, 0xb4, 0xa5, 0x95, 0x0d, 0xa9, 0x7d, 0xc5, 0xca, 0xc3, 0x85, 0x61, 0xc5, - 0xca, 0xc7, 0x2a, 0xc4, 0x8f, 0xa0, 0xae, 0x67, 0x02, 0xa4, 0xad, 0xaf, 0xbd, 0x9f, 0x92, 0x6a, - 0x5f, 0x7e, 0x94, 0x13, 0x29, 0x37, 0x00, 0x96, 0xf1, 0x84, 0x1e, 0x27, 0x96, 0xdc, 0xcb, 0x07, - 0xb5, 0xa3, 0x07, 0xa4, 0x52, 0xd5, 0xd9, 0x37, 0x7f, 0x38, 0xb9, 0xb1, 0xd9, 0x74, 0x7e, 0x75, - 0x3c, 0xf6, 0xdd, 0x13, 0x87, 0xf7, 0xf4, 0x9e, 0xed, 0xdd, 0x78, 0x94, 0xfd, 0xec, 0x07, 0xb7, - 0x27, 0x8e, 0x37, 0x39, 0x11, 0x61, 0x79, 0xb2, 0xd0, 0x72, 0x95, 0x15, 0xff, 0x80, 0xfa, 0xf5, - 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x77, 0x3e, 0x21, 0x8e, 0xb0, 0x12, 0x00, 0x00, + // 1404 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdb, 0x52, 0xdb, 0xd6, + 0x1a, 0xde, 0xf2, 0x09, 0xf3, 0xdb, 0x18, 0x65, 0xb1, 0x27, 0xd1, 0x36, 0x21, 0xf1, 0xd6, 0xce, + 0x26, 0x9e, 0x4e, 0x02, 0x09, 0xed, 0x74, 0x32, 0xbd, 0xe8, 0x0c, 0xf8, 0x50, 0x4c, 0xcd, 0x21, + 0xcb, 0xe6, 0xa2, 0xcd, 0x85, 0x46, 0x58, 0xcb, 0x58, 0x45, 0xd2, 0x72, 0xb5, 0x96, 0x92, 0xe1, + 0x15, 0xfa, 0x22, 0xed, 0x4d, 0xfb, 0x5c, 0x7d, 0x84, 0x5e, 0x76, 0xd6, 0x41, 0x58, 0x36, 0x36, + 0xe9, 0x9d, 0xf5, 0xfd, 0xdf, 0x7f, 0x5a, 0xff, 0x09, 0xe0, 0x71, 0x4c, 0x13, 0x4e, 0xe2, 0x78, + 0x3a, 0xda, 0x57, 0xbf, 0xf6, 0xa6, 0x31, 0xe5, 0x14, 0xad, 0xdf, 0xe1, 0xf5, 0xf5, 0x78, 0x3a, + 0x52, 0xa8, 0xfd, 0x57, 0x11, 0xd0, 0x80, 0x44, 0xde, 0x85, 0x7b, 0x1b, 0x92, 0x88, 0x63, 0xf2, + 0x73, 0x42, 0x18, 0x47, 0x08, 0x0a, 0x1e, 0x61, 0xdc, 0x32, 0x1a, 0x46, 0xb3, 0x8a, 0xe5, 0x6f, + 0x64, 0x42, 0xde, 0x0d, 0xb9, 0x95, 0x6b, 0x18, 0xcd, 0x3c, 0x16, 0x3f, 0xd1, 0x7f, 0xa0, 0xec, + 0x86, 0xdc, 0x09, 0x99, 0xcb, 0xad, 0xaa, 0x84, 0xd7, 0xdc, 0x90, 0x9f, 0x32, 0x97, 0xa3, 0xff, + 0x42, 0x75, 0xaa, 0x4c, 0x3a, 0x13, 0x97, 0x4d, 0xac, 0xbc, 0x34, 0x54, 0xd1, 0xd8, 0xb1, 0xcb, + 0x26, 0xa8, 0x09, 0xe6, 0xd8, 0x8f, 0xdc, 0xc0, 0x19, 0x05, 0xfc, 0xa3, 0xe3, 0x91, 0x80, 0xbb, + 0x56, 0xa1, 0x61, 0x34, 0x8b, 0xb8, 0x26, 0xf1, 0x56, 0xc0, 0x3f, 0xb6, 0x05, 0x8a, 0x5e, 0xc2, + 0x66, 0x6a, 0x2c, 0x56, 0x01, 0x5a, 0xc5, 0x86, 0xd1, 0x5c, 0xc7, 0xb5, 0xe9, 0x7c, 0xd8, 0x2f, + 0x61, 0x93, 0xfb, 0x21, 0xa1, 0x09, 0x77, 0x18, 0x19, 0xd1, 0xc8, 0x63, 0x56, 0x49, 0x59, 0xd4, + 0xf0, 0x40, 0xa1, 0xc8, 0x86, 0x8d, 0x31, 0x21, 0x4e, 0xe0, 0x87, 0x3e, 0x77, 0x44, 0xf8, 0x6b, + 0x32, 0xfc, 0xca, 0x98, 0x90, 0xbe, 0xc0, 0x06, 0x2e, 0x47, 0x2f, 0xa0, 0x36, 0xe3, 0xc8, 0x1c, + 0x37, 0x24, 0xa9, 0x9a, 0x92, 0x64, 0xa2, 0xaf, 0xc0, 0xa4, 0x09, 0xbf, 0xa6, 0x7e, 0x74, 0xed, + 0x8c, 0x26, 0x6e, 0xe4, 0xf8, 0x9e, 0x55, 0x6e, 0x18, 0xcd, 0xc2, 0x51, 0xee, 0x8d, 0x81, 0x6b, + 0xa9, 0xac, 0x35, 0x71, 0xa3, 0x9e, 0x87, 0x76, 0x61, 0x33, 0x70, 0x19, 0x77, 0x26, 0x74, 0xea, + 0x4c, 0x93, 0xab, 0x1b, 0x72, 0x6b, 0xd5, 0xe4, 0xcb, 0x6c, 0x08, 0xf8, 0x98, 0x4e, 0x2f, 0x24, + 0x88, 0x76, 0x00, 0xe4, 0xab, 0x48, 0xe7, 0xd6, 0xba, 0xcc, 0x61, 0x5d, 0x20, 0xd2, 0x31, 0x7a, + 0x0b, 0x15, 0x59, 0x4d, 0x67, 0xe2, 0x47, 0x9c, 0x59, 0xd0, 0xc8, 0x37, 0x2b, 0x07, 0xe6, 0x5e, + 0x10, 0x89, 0xc2, 0x62, 0x21, 0x39, 0xf6, 0x23, 0x8e, 0x21, 0x4e, 0x7f, 0x32, 0xe4, 0xc1, 0x96, + 0xa8, 0xa2, 0x33, 0x4a, 0x18, 0xa7, 0xa1, 0x13, 0x93, 0x11, 0x8d, 0x3d, 0x66, 0x55, 0xa4, 0xea, + 0x57, 0x7b, 0x77, 0xcd, 0xb1, 0x77, 0xbf, 0x1b, 0xf6, 0xda, 0x84, 0xf1, 0x96, 0xd4, 0xc3, 0x4a, + 0xad, 0x13, 0xf1, 0xf8, 0x16, 0x3f, 0xf2, 0x16, 0x71, 0xf4, 0x0a, 0x90, 0x1b, 0x04, 0xf4, 0x93, + 0xc3, 0x48, 0x30, 0x76, 0x74, 0x75, 0xac, 0xcd, 0x86, 0xd1, 0x2c, 0x63, 0x53, 0x4a, 0x06, 0x24, + 0x18, 0x6b, 0xf3, 0xe8, 0x6b, 0xd8, 0x90, 0x31, 0x8d, 0x89, 0xcb, 0x93, 0x98, 0x30, 0xcb, 0x6c, + 0xe4, 0x9b, 0xb5, 0x83, 0x47, 0x3a, 0x91, 0xae, 0x82, 0x8f, 0x7c, 0x8e, 0xab, 0x82, 0xa7, 0xbf, + 0x59, 0xbd, 0x0d, 0x8f, 0x97, 0x87, 0x24, 0x7a, 0x54, 0xbc, 0xa9, 0x68, 0xdb, 0x02, 0x16, 0x3f, + 0xd1, 0xbf, 0xa1, 0xf8, 0xd1, 0x0d, 0x12, 0x22, 0xfb, 0xb6, 0x8a, 0xd5, 0xc7, 0x37, 0xb9, 0x77, + 0x86, 0xfd, 0x0e, 0xb6, 0x86, 0xb1, 0x3b, 0xba, 0x59, 0x68, 0xfd, 0xc5, 0xce, 0x35, 0xee, 0x75, + 0xae, 0xfd, 0x9b, 0x01, 0x1b, 0x5a, 0x6b, 0xc0, 0x5d, 0x9e, 0x30, 0xf4, 0x1a, 0x8a, 0x8c, 0xbb, + 0x9c, 0x48, 0x76, 0xed, 0xe0, 0x49, 0xe6, 0x3d, 0x33, 0x44, 0x82, 0x15, 0x0b, 0xd5, 0xa1, 0x3c, + 0x8d, 0x89, 0x1f, 0xba, 0xd7, 0x69, 0x5c, 0x77, 0xdf, 0xc8, 0x86, 0xa2, 0x54, 0x96, 0x23, 0x53, + 0x39, 0xa8, 0x66, 0xab, 0x8a, 0x95, 0x08, 0x35, 0xa1, 0x38, 0xe1, 0xc1, 0x88, 0x59, 0x05, 0x59, + 0x3e, 0xa4, 0x39, 0xc7, 0xc3, 0x7e, 0xeb, 0x90, 0x73, 0x12, 0x4e, 0x39, 0x56, 0x04, 0xfb, 0x5b, + 0xd8, 0x94, 0x9a, 0x5d, 0x42, 0x1e, 0x9a, 0xed, 0x27, 0x20, 0x26, 0x57, 0x4e, 0x82, 0x9a, 0xef, + 0x92, 0x1b, 0x8a, 0x21, 0xb0, 0x3d, 0x30, 0x67, 0xfa, 0x6c, 0x4a, 0x23, 0x26, 0xbc, 0x9b, 0x22, + 0x0c, 0xd1, 0xf1, 0x62, 0x40, 0xe4, 0x68, 0x18, 0x52, 0xab, 0xa6, 0xf1, 0x2e, 0x21, 0x72, 0x38, + 0x76, 0xd5, 0x3c, 0x3a, 0x01, 0x1d, 0xdd, 0x88, 0x09, 0x77, 0x6f, 0xb5, 0xf9, 0x0d, 0x01, 0xf7, + 0xe9, 0xe8, 0xa6, 0x2d, 0x40, 0xfb, 0x83, 0x5a, 0x42, 0x43, 0xaa, 0xb2, 0xfc, 0xc7, 0x95, 0x98, + 0x3d, 0x56, 0x6e, 0xe5, 0x63, 0xd9, 0x1f, 0x60, 0x6b, 0xce, 0xb8, 0xce, 0x22, 0x5b, 0x03, 0x63, + 0xa1, 0x06, 0x4d, 0x58, 0x1b, 0xbb, 0x7e, 0x90, 0xc4, 0xa9, 0xe1, 0x5a, 0xda, 0x92, 0x0a, 0xc5, + 0xa9, 0xd8, 0x7e, 0x0a, 0x75, 0x4c, 0x18, 0xe1, 0xa7, 0x3e, 0x63, 0x3e, 0x8d, 0x5a, 0x34, 0xe2, + 0x31, 0x0d, 0x74, 0x06, 0xf6, 0x0e, 0x6c, 0x2f, 0x95, 0xaa, 0x10, 0x84, 0xf2, 0xfb, 0x84, 0xc4, + 0xb7, 0xcb, 0x95, 0xdf, 0xc3, 0xf6, 0x52, 0xa9, 0x8e, 0xff, 0x15, 0x14, 0xa7, 0xae, 0x1f, 0x33, + 0x2b, 0x27, 0x7b, 0xe0, 0xf1, 0x5c, 0xcb, 0xf9, 0xf1, 0xb1, 0xcf, 0x38, 0x8d, 0x6f, 0xb1, 0x22, + 0x9d, 0x14, 0xca, 0x86, 0x99, 0xb3, 0x7f, 0x31, 0xa0, 0x92, 0x11, 0xa2, 0x6d, 0x58, 0x8f, 0xa8, + 0x47, 0x9c, 0x71, 0x4c, 0xc3, 0xf4, 0x11, 0x04, 0xd0, 0x8d, 0x69, 0x28, 0x7a, 0x42, 0x0a, 0x39, + 0xd5, 0x3d, 0x5a, 0x12, 0x9f, 0x43, 0x8a, 0x5e, 0xc3, 0xda, 0x44, 0x19, 0x90, 0x6b, 0xb3, 0x72, + 0xb0, 0xb5, 0xe0, 0xbb, 0xed, 0x72, 0x17, 0xa7, 0x9c, 0x93, 0x42, 0x39, 0x6f, 0x16, 0x4e, 0x0a, + 0xe5, 0x82, 0x59, 0x3c, 0x29, 0x94, 0x8b, 0x66, 0xe9, 0xa4, 0x50, 0x2e, 0x99, 0x6b, 0xf6, 0x9f, + 0x06, 0x94, 0x53, 0xb6, 0x88, 0x44, 0x3c, 0xa9, 0x23, 0xfa, 0x42, 0x37, 0x53, 0x59, 0x00, 0x43, + 0x3f, 0x24, 0xa8, 0x01, 0x55, 0x29, 0x9c, 0x6f, 0x51, 0x10, 0xd8, 0xa1, 0x6c, 0x53, 0xb9, 0xcf, + 0x53, 0x86, 0xec, 0xc7, 0x82, 0xde, 0xe7, 0x8a, 0x92, 0x9e, 0x24, 0x96, 0x8c, 0x46, 0x84, 0x31, + 0xe5, 0xa5, 0xa8, 0x28, 0x1a, 0x93, 0x8e, 0x76, 0x61, 0x33, 0xa5, 0xa4, 0xbe, 0x4a, 0xaa, 0x5f, + 0x35, 0xac, 0xdd, 0x35, 0xc1, 0xcc, 0xf2, 0xc2, 0xd9, 0x05, 0xa9, 0xcd, 0x88, 0xc2, 0xa9, 0x4a, + 0xde, 0xfe, 0x09, 0x9e, 0xc8, 0x52, 0x5e, 0xc4, 0xf4, 0xca, 0xbd, 0xf2, 0x03, 0x9f, 0xdf, 0xa6, + 0x4d, 0x2e, 0x12, 0x8f, 0x69, 0xe8, 0x88, 0xb7, 0x4d, 0x4b, 0x20, 0x80, 0x33, 0xea, 0x11, 0x51, + 0x02, 0x4e, 0x95, 0x48, 0x97, 0x80, 0x53, 0x29, 0xc8, 0x5e, 0xde, 0xfc, 0xdc, 0xe5, 0xb5, 0x6f, + 0xc0, 0xba, 0xef, 0x4b, 0xf7, 0x4c, 0x03, 0x2a, 0xd3, 0x19, 0x2c, 0xdd, 0x19, 0x38, 0x0b, 0x65, + 0x6b, 0x9b, 0xfb, 0x7c, 0x6d, 0xed, 0x5f, 0x0d, 0x78, 0x74, 0x94, 0xf8, 0x81, 0x37, 0x37, 0xb8, + 0xd9, 0xe8, 0x8c, 0xf9, 0xbf, 0x0b, 0x96, 0x1d, 0xfd, 0xdc, 0xd2, 0xa3, 0xbf, 0xec, 0xb0, 0xe6, + 0x57, 0x1e, 0xd6, 0xe7, 0x50, 0x99, 0xdd, 0x54, 0xb5, 0x17, 0xab, 0x18, 0x26, 0xe9, 0x41, 0x65, + 0xf6, 0x3b, 0x40, 0xd9, 0x40, 0xf5, 0x83, 0xdc, 0xed, 0x0f, 0x63, 0xe5, 0xfe, 0xf8, 0xe2, 0x0f, + 0x03, 0xaa, 0xd9, 0x25, 0x8e, 0x36, 0x60, 0xbd, 0x77, 0xe6, 0x74, 0xfb, 0xbd, 0xef, 0x8e, 0x87, + 0xe6, 0xbf, 0xc4, 0xe7, 0xe0, 0xb2, 0xd5, 0xea, 0x74, 0xda, 0x9d, 0xb6, 0x69, 0x20, 0x04, 0xb5, + 0xee, 0x61, 0xaf, 0xdf, 0x69, 0x3b, 0xc3, 0xde, 0x69, 0xe7, 0xfc, 0x72, 0x68, 0xe6, 0xd0, 0x16, + 0x6c, 0x6a, 0xec, 0xec, 0xdc, 0xc1, 0xe7, 0x97, 0xc3, 0x8e, 0x99, 0x47, 0x26, 0x54, 0x35, 0xd8, + 0xc1, 0xf8, 0x1c, 0x9b, 0x05, 0xf4, 0x02, 0x1a, 0x1a, 0xe9, 0x9d, 0xb5, 0xce, 0x31, 0xee, 0xb4, + 0x86, 0xce, 0xc5, 0xe1, 0x0f, 0xa7, 0x9d, 0xb3, 0xa1, 0xd3, 0xee, 0x0c, 0x0f, 0x7b, 0xfd, 0x81, + 0x59, 0x44, 0xcf, 0x61, 0xfb, 0x8e, 0x35, 0xb8, 0xec, 0x76, 0x7b, 0xad, 0x9e, 0x20, 0x1c, 0x1d, + 0xf6, 0x0f, 0xcf, 0x5a, 0x1d, 0xb3, 0x74, 0xf0, 0x7b, 0x11, 0x4a, 0x32, 0x83, 0x18, 0x1d, 0x43, + 0x25, 0x73, 0xcf, 0xd1, 0xce, 0x83, 0x77, 0xbe, 0x6e, 0x2d, 0x3f, 0x5b, 0x09, 0x7b, 0x63, 0xa0, + 0x13, 0xa8, 0x66, 0xaf, 0x25, 0x7a, 0x96, 0xe1, 0x2e, 0x39, 0xa3, 0x0f, 0xda, 0xfa, 0x1e, 0xcc, + 0x0e, 0xe3, 0x7e, 0x28, 0x2e, 0xa2, 0x3e, 0x2e, 0xa8, 0x9e, 0xe1, 0x2f, 0x5c, 0xac, 0xfa, 0xf6, + 0x52, 0x99, 0x2e, 0x61, 0x5f, 0xa5, 0xa8, 0xd7, 0xfb, 0xbd, 0x14, 0xe7, 0x6f, 0x4a, 0xfd, 0xd9, + 0x2a, 0xb1, 0xb6, 0xe6, 0xc1, 0xd6, 0x92, 0x8d, 0x8d, 0xfe, 0x9f, 0x8d, 0x60, 0xe5, 0xbe, 0xaf, + 0xef, 0x7e, 0x8e, 0x36, 0xf3, 0xb2, 0x64, 0xb5, 0xcf, 0x79, 0x59, 0x7d, 0x18, 0xe6, 0xbc, 0x3c, + 0x74, 0x21, 0x3e, 0x80, 0xb9, 0xb8, 0x09, 0x90, 0xbd, 0xa8, 0x7b, 0x7f, 0x25, 0xd5, 0xff, 0xf7, + 0x20, 0x47, 0x1b, 0xef, 0x01, 0xcc, 0xe6, 0x09, 0x3d, 0xcd, 0xa8, 0xdc, 0xdb, 0x07, 0xf5, 0x9d, + 0x15, 0x52, 0x65, 0xea, 0xe8, 0xed, 0x8f, 0xfb, 0xd7, 0x3e, 0x9f, 0x24, 0x57, 0x7b, 0x23, 0x1a, + 0xee, 0x07, 0xfe, 0xf5, 0x84, 0x47, 0x7e, 0x74, 0x1d, 0x11, 0xfe, 0x89, 0xc6, 0x37, 0xfb, 0x41, + 0xe4, 0xed, 0xcb, 0xb1, 0xdc, 0xbf, 0xb3, 0x72, 0x55, 0x92, 0xff, 0xbd, 0x7c, 0xf9, 0x77, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x30, 0x2f, 0x8a, 0x5c, 0xed, 0x0c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 2f4d4d69ea..21f6ab668e 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -222,167 +222,9 @@ message SendToRouteResponse { bytes preimage = 1; /// The failure message in case the payment failed. - Failure failure = 2; + lnrpc.Failure failure = 2; } -message Failure { - enum FailureCode { - /** - The numbers assigned in this enumeration match the failure codes as - defined in BOLT #4. Because protobuf 3 requires enums to start with 0, - a RESERVED value is added. - */ - RESERVED = 0; - - INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS = 1; - INCORRECT_PAYMENT_AMOUNT = 2; - FINAL_INCORRECT_CLTV_EXPIRY = 3; - FINAL_INCORRECT_HTLC_AMOUNT = 4; - FINAL_EXPIRY_TOO_SOON = 5; - INVALID_REALM = 6; - EXPIRY_TOO_SOON = 7; - INVALID_ONION_VERSION = 8; - INVALID_ONION_HMAC = 9; - INVALID_ONION_KEY = 10; - AMOUNT_BELOW_MINIMUM = 11; - FEE_INSUFFICIENT = 12; - INCORRECT_CLTV_EXPIRY = 13; - CHANNEL_DISABLED = 14; - TEMPORARY_CHANNEL_FAILURE = 15; - REQUIRED_NODE_FEATURE_MISSING = 16; - REQUIRED_CHANNEL_FEATURE_MISSING = 17; - UNKNOWN_NEXT_PEER = 18; - TEMPORARY_NODE_FAILURE = 19; - PERMANENT_NODE_FAILURE = 20; - PERMANENT_CHANNEL_FAILURE = 21; - EXPIRY_TOO_FAR = 22; - MPP_TIMEOUT = 23; - - /** - The error source is known, but the failure itself couldn't be decoded. - */ - UNKNOWN_FAILURE = 998; - - /** - An unreadable failure result is returned if the received failure message - cannot be decrypted. In that case the error source is unknown. - */ - UNREADABLE_FAILURE = 999; - } - - /// Failure code as defined in the Lightning spec - FailureCode code = 1; - - reserved 2; - - /// An optional channel update message. - ChannelUpdate channel_update = 3; - - /// A failure type-dependent htlc value. - uint64 htlc_msat = 4; - - /// The sha256 sum of the onion payload. - bytes onion_sha_256 = 5; - - /// A failure type-dependent cltv expiry value. - uint32 cltv_expiry = 6; - - /// A failure type-dependent flags value. - uint32 flags = 7; - - /** - The position in the path of the intermediate or final node that generated - the failure message. Position zero is the sender node. - **/ - uint32 failure_source_index = 8; - - /// A failure type-dependent block height. - uint32 height = 9; -} - - -message ChannelUpdate { - /** - The signature that validates the announced data and proves the ownership - of node id. - */ - bytes signature = 1; - - /** - The target chain that this channel was opened within. This value - should be the genesis hash of the target chain. Along with the short - channel ID, this uniquely identifies the channel globally in a - blockchain. - */ - bytes chain_hash = 2; - - /** - The unique description of the funding transaction. - */ - uint64 chan_id = 3 [jstype = JS_STRING]; - - /** - A timestamp that allows ordering in the case of multiple announcements. - We should ignore the message if timestamp is not greater than the - last-received. - */ - uint32 timestamp = 4; - - /** - The bitfield that describes whether optional fields are present in this - update. Currently, the least-significant bit must be set to 1 if the - optional field MaxHtlc is present. - */ - uint32 message_flags = 10; - - /** - The bitfield that describes additional meta-data concerning how the - update is to be interpreted. Currently, the least-significant bit must be - set to 0 if the creating node corresponds to the first node in the - previously sent channel announcement and 1 otherwise. If the second bit - is set, then the channel is set to be disabled. - */ - uint32 channel_flags = 5; - - /** - The minimum number of blocks this node requires to be added to the expiry - of HTLCs. This is a security parameter determined by the node operator. - This value represents the required gap between the time locks of the - incoming and outgoing HTLC's set to this node. - */ - uint32 time_lock_delta = 6; - - /** - The minimum HTLC value which will be accepted. - */ - uint64 htlc_minimum_msat = 7; - - /** - The base fee that must be used for incoming HTLC's to this particular - channel. This value will be tacked onto the required for a payment - independent of the size of the payment. - */ - uint32 base_fee = 8; - - /** - The fee rate that will be charged per millionth of a satoshi. - */ - uint32 fee_rate = 9; - - /** - The maximum HTLC value which will be accepted. - */ - uint64 htlc_maximum_msat = 11; - - /** - The set of data that was appended to this message, some of which we may - not actually know how to iterate or parse. By holding onto this data, we - ensure that we're able to properly validate the set of signatures that - cover these new fields, and ensure we're able to make upgrades to the - network in a forwards compatible manner. - */ - bytes extra_opaque_data = 12; -} message ResetMissionControlRequest { } diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index a1b7948c10..069b145c9f 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -318,11 +318,11 @@ func (s *Server) SendToRoute(ctx context.Context, // Because of difficulties with using protobuf oneof constructs in some // languages, the decision was made here to use a single message format for all // failure messages with some fields left empty depending on the failure type. -func marshallError(sendError error) (*Failure, error) { - response := &Failure{} +func marshallError(sendError error) (*lnrpc.Failure, error) { + response := &lnrpc.Failure{} if sendError == htlcswitch.ErrUnreadableFailureMessage { - response.Code = Failure_UNREADABLE_FAILURE + response.Code = lnrpc.Failure_UNREADABLE_FAILURE return response, nil } @@ -334,92 +334,92 @@ func marshallError(sendError error) (*Failure, error) { switch onionErr := rtErr.WireMessage().(type) { case *lnwire.FailIncorrectDetails: - response.Code = Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS + response.Code = lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS response.Height = onionErr.Height() case *lnwire.FailIncorrectPaymentAmount: - response.Code = Failure_INCORRECT_PAYMENT_AMOUNT + response.Code = lnrpc.Failure_INCORRECT_PAYMENT_AMOUNT case *lnwire.FailFinalIncorrectCltvExpiry: - response.Code = Failure_FINAL_INCORRECT_CLTV_EXPIRY + response.Code = lnrpc.Failure_FINAL_INCORRECT_CLTV_EXPIRY response.CltvExpiry = onionErr.CltvExpiry case *lnwire.FailFinalIncorrectHtlcAmount: - response.Code = Failure_FINAL_INCORRECT_HTLC_AMOUNT + response.Code = lnrpc.Failure_FINAL_INCORRECT_HTLC_AMOUNT response.HtlcMsat = uint64(onionErr.IncomingHTLCAmount) case *lnwire.FailFinalExpiryTooSoon: - response.Code = Failure_FINAL_EXPIRY_TOO_SOON + response.Code = lnrpc.Failure_FINAL_EXPIRY_TOO_SOON case *lnwire.FailInvalidRealm: - response.Code = Failure_INVALID_REALM + response.Code = lnrpc.Failure_INVALID_REALM case *lnwire.FailExpiryTooSoon: - response.Code = Failure_EXPIRY_TOO_SOON + response.Code = lnrpc.Failure_EXPIRY_TOO_SOON response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) case *lnwire.FailExpiryTooFar: - response.Code = Failure_EXPIRY_TOO_FAR + response.Code = lnrpc.Failure_EXPIRY_TOO_FAR case *lnwire.FailInvalidOnionVersion: - response.Code = Failure_INVALID_ONION_VERSION + response.Code = lnrpc.Failure_INVALID_ONION_VERSION response.OnionSha_256 = onionErr.OnionSHA256[:] case *lnwire.FailInvalidOnionHmac: - response.Code = Failure_INVALID_ONION_HMAC + response.Code = lnrpc.Failure_INVALID_ONION_HMAC response.OnionSha_256 = onionErr.OnionSHA256[:] case *lnwire.FailInvalidOnionKey: - response.Code = Failure_INVALID_ONION_KEY + response.Code = lnrpc.Failure_INVALID_ONION_KEY response.OnionSha_256 = onionErr.OnionSHA256[:] case *lnwire.FailAmountBelowMinimum: - response.Code = Failure_AMOUNT_BELOW_MINIMUM + response.Code = lnrpc.Failure_AMOUNT_BELOW_MINIMUM response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) response.HtlcMsat = uint64(onionErr.HtlcMsat) case *lnwire.FailFeeInsufficient: - response.Code = Failure_FEE_INSUFFICIENT + response.Code = lnrpc.Failure_FEE_INSUFFICIENT response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) response.HtlcMsat = uint64(onionErr.HtlcMsat) case *lnwire.FailIncorrectCltvExpiry: - response.Code = Failure_INCORRECT_CLTV_EXPIRY + response.Code = lnrpc.Failure_INCORRECT_CLTV_EXPIRY response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) response.CltvExpiry = onionErr.CltvExpiry case *lnwire.FailChannelDisabled: - response.Code = Failure_CHANNEL_DISABLED + response.Code = lnrpc.Failure_CHANNEL_DISABLED response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) response.Flags = uint32(onionErr.Flags) case *lnwire.FailTemporaryChannelFailure: - response.Code = Failure_TEMPORARY_CHANNEL_FAILURE + response.Code = lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE response.ChannelUpdate = marshallChannelUpdate(onionErr.Update) case *lnwire.FailRequiredNodeFeatureMissing: - response.Code = Failure_REQUIRED_NODE_FEATURE_MISSING + response.Code = lnrpc.Failure_REQUIRED_NODE_FEATURE_MISSING case *lnwire.FailRequiredChannelFeatureMissing: - response.Code = Failure_REQUIRED_CHANNEL_FEATURE_MISSING + response.Code = lnrpc.Failure_REQUIRED_CHANNEL_FEATURE_MISSING case *lnwire.FailUnknownNextPeer: - response.Code = Failure_UNKNOWN_NEXT_PEER + response.Code = lnrpc.Failure_UNKNOWN_NEXT_PEER case *lnwire.FailTemporaryNodeFailure: - response.Code = Failure_TEMPORARY_NODE_FAILURE + response.Code = lnrpc.Failure_TEMPORARY_NODE_FAILURE case *lnwire.FailPermanentNodeFailure: - response.Code = Failure_PERMANENT_NODE_FAILURE + response.Code = lnrpc.Failure_PERMANENT_NODE_FAILURE case *lnwire.FailPermanentChannelFailure: - response.Code = Failure_PERMANENT_CHANNEL_FAILURE + response.Code = lnrpc.Failure_PERMANENT_CHANNEL_FAILURE case *lnwire.FailMPPTimeout: - response.Code = Failure_MPP_TIMEOUT + response.Code = lnrpc.Failure_MPP_TIMEOUT case nil: - response.Code = Failure_UNKNOWN_FAILURE + response.Code = lnrpc.Failure_UNKNOWN_FAILURE default: return nil, fmt.Errorf("cannot marshall failure %T", onionErr) @@ -441,12 +441,12 @@ func marshallError(sendError error) (*Failure, error) { // marshallChannelUpdate marshalls a channel update as received over the wire to // the router rpc format. -func marshallChannelUpdate(update *lnwire.ChannelUpdate) *ChannelUpdate { +func marshallChannelUpdate(update *lnwire.ChannelUpdate) *lnrpc.ChannelUpdate { if update == nil { return nil } - return &ChannelUpdate{ + return &lnrpc.ChannelUpdate{ Signature: update.Signature[:], ChainHash: update.ChainHash[:], ChanId: update.ShortChannelID.ToUint64(), diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 36727add24..0da66bfdfe 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -408,6 +408,112 @@ func (HTLCAttempt_HTLCStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor_77a6da22d6a3feb1, []int{113, 0} } +type Failure_FailureCode int32 + +const ( + //* + //The numbers assigned in this enumeration match the failure codes as + //defined in BOLT #4. Because protobuf 3 requires enums to start with 0, + //a RESERVED value is added. + Failure_RESERVED Failure_FailureCode = 0 + Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS Failure_FailureCode = 1 + Failure_INCORRECT_PAYMENT_AMOUNT Failure_FailureCode = 2 + Failure_FINAL_INCORRECT_CLTV_EXPIRY Failure_FailureCode = 3 + Failure_FINAL_INCORRECT_HTLC_AMOUNT Failure_FailureCode = 4 + Failure_FINAL_EXPIRY_TOO_SOON Failure_FailureCode = 5 + Failure_INVALID_REALM Failure_FailureCode = 6 + Failure_EXPIRY_TOO_SOON Failure_FailureCode = 7 + Failure_INVALID_ONION_VERSION Failure_FailureCode = 8 + Failure_INVALID_ONION_HMAC Failure_FailureCode = 9 + Failure_INVALID_ONION_KEY Failure_FailureCode = 10 + Failure_AMOUNT_BELOW_MINIMUM Failure_FailureCode = 11 + Failure_FEE_INSUFFICIENT Failure_FailureCode = 12 + Failure_INCORRECT_CLTV_EXPIRY Failure_FailureCode = 13 + Failure_CHANNEL_DISABLED Failure_FailureCode = 14 + Failure_TEMPORARY_CHANNEL_FAILURE Failure_FailureCode = 15 + Failure_REQUIRED_NODE_FEATURE_MISSING Failure_FailureCode = 16 + Failure_REQUIRED_CHANNEL_FEATURE_MISSING Failure_FailureCode = 17 + Failure_UNKNOWN_NEXT_PEER Failure_FailureCode = 18 + Failure_TEMPORARY_NODE_FAILURE Failure_FailureCode = 19 + Failure_PERMANENT_NODE_FAILURE Failure_FailureCode = 20 + Failure_PERMANENT_CHANNEL_FAILURE Failure_FailureCode = 21 + Failure_EXPIRY_TOO_FAR Failure_FailureCode = 22 + Failure_MPP_TIMEOUT Failure_FailureCode = 23 + //* + //The error source is known, but the failure itself couldn't be decoded. + Failure_UNKNOWN_FAILURE Failure_FailureCode = 998 + //* + //An unreadable failure result is returned if the received failure message + //cannot be decrypted. In that case the error source is unknown. + Failure_UNREADABLE_FAILURE Failure_FailureCode = 999 +) + +var Failure_FailureCode_name = map[int32]string{ + 0: "RESERVED", + 1: "INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS", + 2: "INCORRECT_PAYMENT_AMOUNT", + 3: "FINAL_INCORRECT_CLTV_EXPIRY", + 4: "FINAL_INCORRECT_HTLC_AMOUNT", + 5: "FINAL_EXPIRY_TOO_SOON", + 6: "INVALID_REALM", + 7: "EXPIRY_TOO_SOON", + 8: "INVALID_ONION_VERSION", + 9: "INVALID_ONION_HMAC", + 10: "INVALID_ONION_KEY", + 11: "AMOUNT_BELOW_MINIMUM", + 12: "FEE_INSUFFICIENT", + 13: "INCORRECT_CLTV_EXPIRY", + 14: "CHANNEL_DISABLED", + 15: "TEMPORARY_CHANNEL_FAILURE", + 16: "REQUIRED_NODE_FEATURE_MISSING", + 17: "REQUIRED_CHANNEL_FEATURE_MISSING", + 18: "UNKNOWN_NEXT_PEER", + 19: "TEMPORARY_NODE_FAILURE", + 20: "PERMANENT_NODE_FAILURE", + 21: "PERMANENT_CHANNEL_FAILURE", + 22: "EXPIRY_TOO_FAR", + 23: "MPP_TIMEOUT", + 998: "UNKNOWN_FAILURE", + 999: "UNREADABLE_FAILURE", +} + +var Failure_FailureCode_value = map[string]int32{ + "RESERVED": 0, + "INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS": 1, + "INCORRECT_PAYMENT_AMOUNT": 2, + "FINAL_INCORRECT_CLTV_EXPIRY": 3, + "FINAL_INCORRECT_HTLC_AMOUNT": 4, + "FINAL_EXPIRY_TOO_SOON": 5, + "INVALID_REALM": 6, + "EXPIRY_TOO_SOON": 7, + "INVALID_ONION_VERSION": 8, + "INVALID_ONION_HMAC": 9, + "INVALID_ONION_KEY": 10, + "AMOUNT_BELOW_MINIMUM": 11, + "FEE_INSUFFICIENT": 12, + "INCORRECT_CLTV_EXPIRY": 13, + "CHANNEL_DISABLED": 14, + "TEMPORARY_CHANNEL_FAILURE": 15, + "REQUIRED_NODE_FEATURE_MISSING": 16, + "REQUIRED_CHANNEL_FEATURE_MISSING": 17, + "UNKNOWN_NEXT_PEER": 18, + "TEMPORARY_NODE_FAILURE": 19, + "PERMANENT_NODE_FAILURE": 20, + "PERMANENT_CHANNEL_FAILURE": 21, + "EXPIRY_TOO_FAR": 22, + "MPP_TIMEOUT": 23, + "UNKNOWN_FAILURE": 998, + "UNREADABLE_FAILURE": 999, +} + +func (x Failure_FailureCode) String() string { + return proto.EnumName(Failure_FailureCode_name, int32(x)) +} + +func (Failure_FailureCode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{146, 0} +} + type GenSeedRequest struct { //* //aezeed_passphrase is an optional user provided passphrase that will be used @@ -10469,6 +10575,283 @@ func (m *BakeMacaroonResponse) GetMacaroon() string { return "" } +type Failure struct { + /// Failure code as defined in the Lightning spec + Code Failure_FailureCode `protobuf:"varint,1,opt,name=code,proto3,enum=lnrpc.Failure_FailureCode" json:"code,omitempty"` + /// An optional channel update message. + ChannelUpdate *ChannelUpdate `protobuf:"bytes,3,opt,name=channel_update,json=channelUpdate,proto3" json:"channel_update,omitempty"` + /// A failure type-dependent htlc value. + HtlcMsat uint64 `protobuf:"varint,4,opt,name=htlc_msat,json=htlcMsat,proto3" json:"htlc_msat,omitempty"` + /// The sha256 sum of the onion payload. + OnionSha_256 []byte `protobuf:"bytes,5,opt,name=onion_sha_256,json=onionSha256,proto3" json:"onion_sha_256,omitempty"` + /// A failure type-dependent cltv expiry value. + CltvExpiry uint32 `protobuf:"varint,6,opt,name=cltv_expiry,json=cltvExpiry,proto3" json:"cltv_expiry,omitempty"` + /// A failure type-dependent flags value. + Flags uint32 `protobuf:"varint,7,opt,name=flags,proto3" json:"flags,omitempty"` + //* + //The position in the path of the intermediate or final node that generated + //the failure message. Position zero is the sender node. + FailureSourceIndex uint32 `protobuf:"varint,8,opt,name=failure_source_index,json=failureSourceIndex,proto3" json:"failure_source_index,omitempty"` + /// A failure type-dependent block height. + Height uint32 `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +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{146} +} + +func (m *Failure) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Failure.Unmarshal(m, b) +} +func (m *Failure) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Failure.Marshal(b, m, deterministic) +} +func (m *Failure) XXX_Merge(src proto.Message) { + xxx_messageInfo_Failure.Merge(m, src) +} +func (m *Failure) XXX_Size() int { + return xxx_messageInfo_Failure.Size(m) +} +func (m *Failure) XXX_DiscardUnknown() { + xxx_messageInfo_Failure.DiscardUnknown(m) +} + +var xxx_messageInfo_Failure proto.InternalMessageInfo + +func (m *Failure) GetCode() Failure_FailureCode { + if m != nil { + return m.Code + } + return Failure_RESERVED +} + +func (m *Failure) GetChannelUpdate() *ChannelUpdate { + if m != nil { + return m.ChannelUpdate + } + return nil +} + +func (m *Failure) GetHtlcMsat() uint64 { + if m != nil { + return m.HtlcMsat + } + return 0 +} + +func (m *Failure) GetOnionSha_256() []byte { + if m != nil { + return m.OnionSha_256 + } + return nil +} + +func (m *Failure) GetCltvExpiry() uint32 { + if m != nil { + return m.CltvExpiry + } + return 0 +} + +func (m *Failure) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + +func (m *Failure) GetFailureSourceIndex() uint32 { + if m != nil { + return m.FailureSourceIndex + } + return 0 +} + +func (m *Failure) GetHeight() uint32 { + if m != nil { + return m.Height + } + return 0 +} + +type ChannelUpdate struct { + //* + //The signature that validates the announced data and proves the ownership + //of node id. + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + //* + //The target chain that this channel was opened within. This value + //should be the genesis hash of the target chain. Along with the short + //channel ID, this uniquely identifies the channel globally in a + //blockchain. + ChainHash []byte `protobuf:"bytes,2,opt,name=chain_hash,json=chainHash,proto3" json:"chain_hash,omitempty"` + //* + //The unique description of the funding transaction. + ChanId uint64 `protobuf:"varint,3,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` + //* + //A timestamp that allows ordering in the case of multiple announcements. + //We should ignore the message if timestamp is not greater than the + //last-received. + Timestamp uint32 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + //* + //The bitfield that describes whether optional fields are present in this + //update. Currently, the least-significant bit must be set to 1 if the + //optional field MaxHtlc is present. + MessageFlags uint32 `protobuf:"varint,10,opt,name=message_flags,json=messageFlags,proto3" json:"message_flags,omitempty"` + //* + //The bitfield that describes additional meta-data concerning how the + //update is to be interpreted. Currently, the least-significant bit must be + //set to 0 if the creating node corresponds to the first node in the + //previously sent channel announcement and 1 otherwise. If the second bit + //is set, then the channel is set to be disabled. + ChannelFlags uint32 `protobuf:"varint,5,opt,name=channel_flags,json=channelFlags,proto3" json:"channel_flags,omitempty"` + //* + //The minimum number of blocks this node requires to be added to the expiry + //of HTLCs. This is a security parameter determined by the node operator. + //This value represents the required gap between the time locks of the + //incoming and outgoing HTLC's set to this node. + TimeLockDelta uint32 `protobuf:"varint,6,opt,name=time_lock_delta,json=timeLockDelta,proto3" json:"time_lock_delta,omitempty"` + //* + //The minimum HTLC value which will be accepted. + HtlcMinimumMsat uint64 `protobuf:"varint,7,opt,name=htlc_minimum_msat,json=htlcMinimumMsat,proto3" json:"htlc_minimum_msat,omitempty"` + //* + //The base fee that must be used for incoming HTLC's to this particular + //channel. This value will be tacked onto the required for a payment + //independent of the size of the payment. + BaseFee uint32 `protobuf:"varint,8,opt,name=base_fee,json=baseFee,proto3" json:"base_fee,omitempty"` + //* + //The fee rate that will be charged per millionth of a satoshi. + FeeRate uint32 `protobuf:"varint,9,opt,name=fee_rate,json=feeRate,proto3" json:"fee_rate,omitempty"` + //* + //The maximum HTLC value which will be accepted. + HtlcMaximumMsat uint64 `protobuf:"varint,11,opt,name=htlc_maximum_msat,json=htlcMaximumMsat,proto3" json:"htlc_maximum_msat,omitempty"` + //* + //The set of data that was appended to this message, some of which we may + //not actually know how to iterate or parse. By holding onto this data, we + //ensure that we're able to properly validate the set of signatures that + //cover these new fields, and ensure we're able to make upgrades to the + //network in a forwards compatible manner. + ExtraOpaqueData []byte `protobuf:"bytes,12,opt,name=extra_opaque_data,json=extraOpaqueData,proto3" json:"extra_opaque_data,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +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{147} +} + +func (m *ChannelUpdate) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ChannelUpdate.Unmarshal(m, b) +} +func (m *ChannelUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ChannelUpdate.Marshal(b, m, deterministic) +} +func (m *ChannelUpdate) XXX_Merge(src proto.Message) { + xxx_messageInfo_ChannelUpdate.Merge(m, src) +} +func (m *ChannelUpdate) XXX_Size() int { + return xxx_messageInfo_ChannelUpdate.Size(m) +} +func (m *ChannelUpdate) XXX_DiscardUnknown() { + xxx_messageInfo_ChannelUpdate.DiscardUnknown(m) +} + +var xxx_messageInfo_ChannelUpdate proto.InternalMessageInfo + +func (m *ChannelUpdate) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *ChannelUpdate) GetChainHash() []byte { + if m != nil { + return m.ChainHash + } + return nil +} + +func (m *ChannelUpdate) GetChanId() uint64 { + if m != nil { + return m.ChanId + } + return 0 +} + +func (m *ChannelUpdate) GetTimestamp() uint32 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *ChannelUpdate) GetMessageFlags() uint32 { + if m != nil { + return m.MessageFlags + } + return 0 +} + +func (m *ChannelUpdate) GetChannelFlags() uint32 { + if m != nil { + return m.ChannelFlags + } + return 0 +} + +func (m *ChannelUpdate) GetTimeLockDelta() uint32 { + if m != nil { + return m.TimeLockDelta + } + return 0 +} + +func (m *ChannelUpdate) GetHtlcMinimumMsat() uint64 { + if m != nil { + return m.HtlcMinimumMsat + } + return 0 +} + +func (m *ChannelUpdate) GetBaseFee() uint32 { + if m != nil { + return m.BaseFee + } + return 0 +} + +func (m *ChannelUpdate) GetFeeRate() uint32 { + if m != nil { + return m.FeeRate + } + return 0 +} + +func (m *ChannelUpdate) GetHtlcMaximumMsat() uint64 { + if m != nil { + return m.HtlcMaximumMsat + } + return 0 +} + +func (m *ChannelUpdate) GetExtraOpaqueData() []byte { + if m != nil { + return m.ExtraOpaqueData + } + return nil +} + func init() { proto.RegisterEnum("lnrpc.AddressType", AddressType_name, AddressType_value) proto.RegisterEnum("lnrpc.InvoiceHTLCState", InvoiceHTLCState_name, InvoiceHTLCState_value) @@ -10481,6 +10864,7 @@ func init() { proto.RegisterEnum("lnrpc.Invoice_InvoiceState", Invoice_InvoiceState_name, Invoice_InvoiceState_value) proto.RegisterEnum("lnrpc.Payment_PaymentStatus", Payment_PaymentStatus_name, Payment_PaymentStatus_value) proto.RegisterEnum("lnrpc.HTLCAttempt_HTLCStatus", HTLCAttempt_HTLCStatus_name, HTLCAttempt_HTLCStatus_value) + proto.RegisterEnum("lnrpc.Failure_FailureCode", Failure_FailureCode_name, Failure_FailureCode_value) proto.RegisterType((*GenSeedRequest)(nil), "lnrpc.GenSeedRequest") proto.RegisterType((*GenSeedResponse)(nil), "lnrpc.GenSeedResponse") proto.RegisterType((*InitWalletRequest)(nil), "lnrpc.InitWalletRequest") @@ -10643,665 +11027,707 @@ func init() { proto.RegisterType((*MacaroonPermission)(nil), "lnrpc.MacaroonPermission") proto.RegisterType((*BakeMacaroonRequest)(nil), "lnrpc.BakeMacaroonRequest") proto.RegisterType((*BakeMacaroonResponse)(nil), "lnrpc.BakeMacaroonResponse") + proto.RegisterType((*Failure)(nil), "lnrpc.Failure") + proto.RegisterType((*ChannelUpdate)(nil), "lnrpc.ChannelUpdate") } func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 10447 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x24, 0x47, - 0x76, 0x18, 0x3c, 0x75, 0xeb, 0xaa, 0x3a, 0x75, 0xe9, 0xea, 0xe8, 0x9e, 0xee, 0x9a, 0x1a, 0x0e, - 0x67, 0x98, 0xe4, 0x72, 0x86, 0x43, 0x72, 0x66, 0x38, 0x4b, 0x2e, 0x29, 0xf2, 0xfb, 0x56, 0xea, - 0x2b, 0xbb, 0x77, 0xfa, 0xc6, 0xac, 0x9e, 0xa5, 0xb8, 0x6b, 0x39, 0x37, 0xbb, 0x2a, 0xba, 0x3b, - 0x35, 0x55, 0x99, 0xc5, 0xcc, 0xac, 0xbe, 0x2c, 0x41, 0x3f, 0xf8, 0x22, 0x18, 0xb6, 0x61, 0x40, - 0xb0, 0x65, 0xc0, 0xb2, 0x05, 0x1b, 0x36, 0x0c, 0xc3, 0xb0, 0x21, 0xc8, 0x58, 0x19, 0xf0, 0x83, - 0xdf, 0xf5, 0x62, 0x43, 0x0f, 0xb2, 0x5f, 0x8c, 0x85, 0x00, 0xc1, 0x82, 0x9e, 0xf5, 0x13, 0x8c, - 0x38, 0x27, 0x22, 0x32, 0xb2, 0x2a, 0x6b, 0x66, 0xc8, 0x5d, 0xef, 0xcb, 0x4c, 0xe7, 0x89, 0x13, - 0xf7, 0x13, 0x27, 0xce, 0x35, 0x0a, 0xaa, 0xe1, 0xa8, 0xf7, 0x60, 0x14, 0x06, 0x71, 0xc0, 0x4a, - 0x03, 0x3f, 0x1c, 0xf5, 0x3a, 0xaf, 0x9c, 0x06, 0xc1, 0xe9, 0x80, 0x3f, 0x74, 0x47, 0xde, 0x43, - 0xd7, 0xf7, 0x83, 0xd8, 0x8d, 0xbd, 0xc0, 0x8f, 0x08, 0xc9, 0xfa, 0x09, 0x34, 0x3f, 0xe5, 0x7e, - 0x97, 0xf3, 0xbe, 0xcd, 0xbf, 0x1c, 0xf3, 0x28, 0x66, 0x6f, 0xc3, 0x82, 0xcb, 0x7f, 0xca, 0x79, - 0xdf, 0x19, 0xb9, 0x51, 0x34, 0x3a, 0x0b, 0xdd, 0x88, 0xb7, 0x73, 0x77, 0x72, 0xf7, 0xea, 0x76, - 0x8b, 0x0a, 0x0e, 0x35, 0x9c, 0xbd, 0x06, 0xf5, 0x48, 0xa0, 0x72, 0x3f, 0x0e, 0x83, 0xd1, 0x55, - 0x3b, 0x8f, 0x78, 0x35, 0x01, 0xdb, 0x24, 0x90, 0x35, 0x80, 0x79, 0xdd, 0x43, 0x34, 0x0a, 0xfc, - 0x88, 0xb3, 0x47, 0xb0, 0xd4, 0xf3, 0x46, 0x67, 0x3c, 0x74, 0xb0, 0xf2, 0xd0, 0xe7, 0xc3, 0xc0, - 0xf7, 0x7a, 0xed, 0xdc, 0x9d, 0xc2, 0xbd, 0xaa, 0xcd, 0xa8, 0x4c, 0xd4, 0xd8, 0x93, 0x25, 0xec, - 0x2e, 0xcc, 0x73, 0x9f, 0xe0, 0xbc, 0x8f, 0xb5, 0x64, 0x57, 0xcd, 0x04, 0x2c, 0x2a, 0x58, 0x7f, - 0x3f, 0x0f, 0x0b, 0x3b, 0xbe, 0x17, 0x7f, 0xee, 0x0e, 0x06, 0x3c, 0x56, 0x73, 0xba, 0x0b, 0xf3, - 0x17, 0x08, 0xc0, 0x39, 0x5d, 0x04, 0x61, 0x5f, 0xce, 0xa8, 0x49, 0xe0, 0x43, 0x09, 0x9d, 0x39, - 0xb2, 0xfc, 0xcc, 0x91, 0x65, 0x2e, 0x57, 0x61, 0xc6, 0x72, 0xdd, 0x85, 0xf9, 0x90, 0xf7, 0x82, - 0x73, 0x1e, 0x5e, 0x39, 0x17, 0x9e, 0xdf, 0x0f, 0x2e, 0xda, 0xc5, 0x3b, 0xb9, 0x7b, 0x25, 0xbb, - 0xa9, 0xc0, 0x9f, 0x23, 0x94, 0xad, 0xc1, 0x7c, 0xef, 0xcc, 0xf5, 0x7d, 0x3e, 0x70, 0x8e, 0xdd, - 0xde, 0xb3, 0xf1, 0x28, 0x6a, 0x97, 0xee, 0xe4, 0xee, 0xd5, 0x1e, 0xdf, 0x78, 0x80, 0xbb, 0xfa, - 0x60, 0xfd, 0xcc, 0xf5, 0xd7, 0xb0, 0xa4, 0xeb, 0xbb, 0xa3, 0xe8, 0x2c, 0x88, 0xed, 0xa6, 0xac, - 0x41, 0xe0, 0xc8, 0x5a, 0x02, 0x66, 0xae, 0x04, 0xad, 0xbd, 0xf5, 0x1f, 0x73, 0xb0, 0xf8, 0xd4, - 0x1f, 0x04, 0xbd, 0x67, 0xdf, 0x72, 0x89, 0x32, 0xe6, 0x90, 0x7f, 0xd9, 0x39, 0x14, 0xbe, 0xe9, - 0x1c, 0x96, 0x61, 0x29, 0x3d, 0x58, 0x39, 0x0b, 0x0e, 0xd7, 0x45, 0xed, 0x53, 0xae, 0x86, 0xa5, - 0xa6, 0xf1, 0x16, 0xb4, 0x7a, 0xe3, 0x30, 0xe4, 0xfe, 0xd4, 0x3c, 0xe6, 0x25, 0x5c, 0x4f, 0xe4, - 0x35, 0xa8, 0xfb, 0xfc, 0x22, 0x41, 0x93, 0xb4, 0xeb, 0xf3, 0x0b, 0x85, 0x62, 0xb5, 0x61, 0x79, - 0xb2, 0x1b, 0x39, 0x80, 0xbf, 0xca, 0x41, 0xf1, 0x69, 0x7c, 0x19, 0xb0, 0x0f, 0xa0, 0xee, 0xf6, - 0xfb, 0x21, 0x8f, 0x22, 0x27, 0xbe, 0x1a, 0xd1, 0x49, 0x69, 0x3e, 0x66, 0x72, 0x8a, 0xab, 0x54, - 0x74, 0x74, 0x35, 0xe2, 0x76, 0xcd, 0x4d, 0x3e, 0x58, 0x1b, 0xca, 0xf2, 0x13, 0xfb, 0xad, 0xda, - 0xea, 0x93, 0xdd, 0x02, 0x70, 0x87, 0xc1, 0xd8, 0x8f, 0x9d, 0xc8, 0x8d, 0x71, 0xc5, 0x0a, 0x76, - 0x95, 0x20, 0x5d, 0x37, 0x66, 0x37, 0xa1, 0x3a, 0x7a, 0xe6, 0x44, 0xbd, 0xd0, 0x1b, 0xc5, 0x48, - 0x3c, 0x55, 0xbb, 0x32, 0x7a, 0xd6, 0xc5, 0x6f, 0xf6, 0x36, 0x54, 0x82, 0x71, 0x3c, 0x0a, 0x3c, - 0x3f, 0x96, 0xf4, 0x32, 0x2f, 0x07, 0x72, 0x30, 0x8e, 0x0f, 0x05, 0xd8, 0xd6, 0x08, 0xec, 0x0d, - 0x68, 0xf4, 0x02, 0xff, 0xc4, 0x0b, 0x87, 0xc4, 0x11, 0xda, 0x73, 0xd8, 0x57, 0x1a, 0x68, 0xfd, - 0x51, 0x1e, 0x6a, 0x47, 0xa1, 0xeb, 0x47, 0x6e, 0x4f, 0x00, 0xd8, 0x0a, 0x94, 0xe3, 0x4b, 0xe7, - 0xcc, 0x8d, 0xce, 0x70, 0xaa, 0x55, 0x7b, 0x2e, 0xbe, 0xdc, 0x76, 0xa3, 0x33, 0xb6, 0x0c, 0x73, - 0x34, 0x4a, 0x9c, 0x50, 0xc1, 0x96, 0x5f, 0xe2, 0x80, 0xf8, 0xe3, 0xa1, 0x93, 0xee, 0xaa, 0x80, - 0x14, 0xd3, 0xf2, 0xc7, 0xc3, 0x75, 0x13, 0x2e, 0x26, 0x7f, 0x2c, 0xb6, 0x9b, 0x3a, 0xa0, 0xe9, - 0x55, 0x11, 0x82, 0x7d, 0xbc, 0x06, 0x75, 0x59, 0xcc, 0xbd, 0xd3, 0x33, 0x9a, 0x63, 0xc9, 0xae, - 0x11, 0x02, 0x82, 0x44, 0x0b, 0xb1, 0x37, 0xe4, 0x4e, 0x14, 0xbb, 0xc3, 0x91, 0x9c, 0x52, 0x55, - 0x40, 0xba, 0x02, 0x80, 0xc5, 0x41, 0xec, 0x0e, 0x9c, 0x13, 0xce, 0xa3, 0x76, 0x59, 0x16, 0x0b, - 0xc8, 0x16, 0xe7, 0x11, 0xfb, 0x0e, 0x34, 0xfb, 0x3c, 0x8a, 0x1d, 0xb9, 0x19, 0x3c, 0x6a, 0x57, - 0xf0, 0xe4, 0x37, 0x04, 0x74, 0x55, 0x01, 0xd9, 0x2b, 0x00, 0xa1, 0x7b, 0xe1, 0x88, 0x85, 0xe0, - 0x97, 0xed, 0x2a, 0xed, 0x42, 0xe8, 0x5e, 0x1c, 0x5d, 0x6e, 0xf3, 0x4b, 0x41, 0x35, 0x9f, 0xf2, - 0xd8, 0x58, 0xb4, 0x48, 0x52, 0xa7, 0xb5, 0x0b, 0xcc, 0x00, 0x6f, 0xf0, 0xd8, 0xf5, 0x06, 0x11, - 0xfb, 0x1e, 0xd4, 0x63, 0x03, 0x19, 0xd9, 0x60, 0x4d, 0x93, 0x90, 0x51, 0xc1, 0x4e, 0xe1, 0x59, - 0x67, 0x50, 0xd9, 0xe2, 0x7c, 0xd7, 0x1b, 0x7a, 0x31, 0x5b, 0x86, 0xd2, 0x89, 0x77, 0xc9, 0x89, - 0xd8, 0x0b, 0xdb, 0xd7, 0x6c, 0xfa, 0x64, 0xb7, 0x01, 0xf0, 0x0f, 0x67, 0xa8, 0xa9, 0x69, 0xfb, - 0x9a, 0x5d, 0x45, 0xd8, 0x5e, 0xe4, 0xc6, 0xac, 0x03, 0xe5, 0x11, 0x0f, 0x7b, 0x5c, 0xed, 0xdb, - 0xf6, 0x35, 0x5b, 0x01, 0xd6, 0xca, 0x50, 0x1a, 0x88, 0xd6, 0xad, 0x3f, 0x29, 0x41, 0xad, 0xcb, - 0x7d, 0x7d, 0xca, 0x18, 0x14, 0xc5, 0x82, 0xc8, 0x93, 0x85, 0x7f, 0xb3, 0xd7, 0xa1, 0x86, 0x4b, - 0x17, 0xc5, 0xa1, 0xe7, 0x9f, 0x12, 0x55, 0xaf, 0xe5, 0xdb, 0x39, 0x1b, 0x04, 0xb8, 0x8b, 0x50, - 0xd6, 0x82, 0x82, 0x3b, 0x54, 0x54, 0x2d, 0xfe, 0x64, 0x37, 0xa0, 0xe2, 0x0e, 0x63, 0x1a, 0x5e, - 0x1d, 0xc1, 0x65, 0x77, 0x18, 0xe3, 0xd0, 0x5e, 0x83, 0xfa, 0xc8, 0xbd, 0x1a, 0x8a, 0xb3, 0xac, - 0xc9, 0xa1, 0x6e, 0xd7, 0x24, 0x0c, 0x09, 0xe2, 0x31, 0x2c, 0x9a, 0x28, 0xaa, 0xf3, 0x92, 0xee, - 0x7c, 0xc1, 0xc0, 0x96, 0x63, 0xb8, 0x0b, 0xf3, 0xaa, 0x4e, 0x48, 0xf3, 0x41, 0x32, 0xa9, 0xda, - 0x4d, 0x09, 0x56, 0xb3, 0xbc, 0x07, 0xad, 0x13, 0xcf, 0x77, 0x07, 0x4e, 0x6f, 0x10, 0x9f, 0x3b, - 0x7d, 0x3e, 0x88, 0x5d, 0xa4, 0x98, 0x92, 0xdd, 0x44, 0xf8, 0xfa, 0x20, 0x3e, 0xdf, 0x10, 0x50, - 0xf6, 0x0e, 0x54, 0x4f, 0x38, 0x77, 0x70, 0xb1, 0xda, 0x95, 0xd4, 0xc1, 0x53, 0x3b, 0x64, 0x57, - 0x4e, 0xd4, 0x5e, 0xbd, 0x03, 0xad, 0x60, 0x1c, 0x9f, 0x06, 0x9e, 0x7f, 0xea, 0x08, 0x7e, 0xe7, - 0x78, 0x7d, 0xa4, 0xa1, 0xe2, 0x5a, 0xfe, 0x51, 0xce, 0x6e, 0xaa, 0x32, 0xc1, 0x79, 0x76, 0xfa, - 0xec, 0x4d, 0x98, 0x1f, 0xb8, 0x51, 0xec, 0x9c, 0x05, 0x23, 0x67, 0x34, 0x3e, 0x7e, 0xc6, 0xaf, - 0xda, 0x0d, 0x5c, 0x88, 0x86, 0x00, 0x6f, 0x07, 0xa3, 0x43, 0x04, 0x0a, 0xca, 0xc6, 0x71, 0xd2, - 0x20, 0xe0, 0x4e, 0xee, 0x5e, 0xc3, 0xae, 0x0a, 0x08, 0x75, 0xfa, 0x05, 0x2c, 0xe2, 0xf6, 0xf4, - 0xc6, 0x51, 0x1c, 0x0c, 0x1d, 0xc1, 0xab, 0xc3, 0x7e, 0xd4, 0xae, 0x21, 0xad, 0xbd, 0x25, 0x07, - 0x6b, 0xec, 0xf1, 0x83, 0x0d, 0x1e, 0xc5, 0xeb, 0x88, 0x6c, 0x13, 0xae, 0xb8, 0xd0, 0xaf, 0xec, - 0x85, 0xfe, 0x24, 0x9c, 0xbd, 0x03, 0xcc, 0x1d, 0x0c, 0x82, 0x0b, 0x27, 0xe2, 0x83, 0x13, 0x47, - 0x2e, 0x62, 0xbb, 0x79, 0x27, 0x77, 0xaf, 0x62, 0xb7, 0xb0, 0xa4, 0xcb, 0x07, 0x27, 0x87, 0x04, - 0x67, 0xdf, 0x03, 0x3c, 0x4c, 0xce, 0x09, 0x77, 0xe3, 0x71, 0xc8, 0xa3, 0xf6, 0xfc, 0x9d, 0xc2, - 0xbd, 0xe6, 0xe3, 0x05, 0xbd, 0x5e, 0x08, 0x5e, 0xf3, 0x62, 0xbb, 0x2e, 0xf0, 0xe4, 0x77, 0xd4, - 0xd9, 0x80, 0xe5, 0xec, 0x21, 0x09, 0xa2, 0x12, 0xab, 0x22, 0x88, 0xb1, 0x68, 0x8b, 0x3f, 0xd9, - 0x12, 0x94, 0xce, 0xdd, 0xc1, 0x98, 0x4b, 0x9e, 0x4e, 0x1f, 0x1f, 0xe7, 0x3f, 0xca, 0x59, 0x7f, - 0x9c, 0x83, 0x3a, 0xcd, 0x52, 0xca, 0x22, 0xaf, 0x43, 0x43, 0x51, 0x03, 0x0f, 0xc3, 0x20, 0x94, - 0x5c, 0x4d, 0x51, 0xde, 0xa6, 0x80, 0x89, 0x5b, 0x45, 0x21, 0x8d, 0x42, 0xee, 0x0d, 0xdd, 0x53, - 0xd5, 0xb4, 0x22, 0xa5, 0x43, 0x09, 0x66, 0xef, 0x25, 0xed, 0x85, 0xc1, 0x38, 0xe6, 0xf2, 0xce, - 0xab, 0xcb, 0xe9, 0xd9, 0x02, 0xa6, 0x5b, 0xc7, 0xaf, 0x97, 0xa0, 0x73, 0xeb, 0xf7, 0x72, 0xc0, - 0xc4, 0xb0, 0x8f, 0x02, 0x6a, 0x40, 0x52, 0xe8, 0x64, 0xcd, 0xdc, 0x4b, 0x9f, 0x90, 0xfc, 0xf3, - 0x4e, 0x88, 0x05, 0x25, 0x1a, 0x7b, 0x31, 0x63, 0xec, 0x54, 0xf4, 0x83, 0x62, 0xa5, 0xd0, 0x2a, - 0x5a, 0xff, 0xbb, 0x00, 0x4b, 0xeb, 0x74, 0x65, 0xaf, 0xf6, 0x7a, 0x7c, 0xa4, 0xcf, 0xce, 0x6d, - 0xa8, 0xf9, 0x41, 0x9f, 0x2b, 0x8a, 0xa5, 0x81, 0x81, 0x00, 0x19, 0xe4, 0x7a, 0xe6, 0x7a, 0x3e, - 0x0d, 0x9c, 0x16, 0xb3, 0x8a, 0x10, 0x1c, 0xf6, 0x9b, 0x30, 0x3f, 0xe2, 0x7e, 0xdf, 0x3c, 0x22, - 0x24, 0x54, 0x35, 0x24, 0x58, 0x9e, 0x8e, 0xdb, 0x50, 0x3b, 0x19, 0x13, 0x9e, 0x60, 0x2c, 0x45, - 0xa4, 0x01, 0x90, 0xa0, 0x55, 0xe2, 0x2f, 0xa3, 0x71, 0x74, 0x86, 0xa5, 0x25, 0x2c, 0x2d, 0x8b, - 0x6f, 0x51, 0x74, 0x0b, 0xa0, 0x3f, 0x8e, 0x62, 0x79, 0x62, 0xe6, 0xb0, 0xb0, 0x2a, 0x20, 0x74, - 0x62, 0xde, 0x85, 0xc5, 0xa1, 0x7b, 0xe9, 0x20, 0xed, 0x38, 0x9e, 0xef, 0x9c, 0x0c, 0xf0, 0xce, - 0x29, 0x23, 0x5e, 0x6b, 0xe8, 0x5e, 0xfe, 0x50, 0x94, 0xec, 0xf8, 0x5b, 0x08, 0x17, 0x6c, 0x45, - 0x89, 0x3b, 0x21, 0x8f, 0x78, 0x78, 0xce, 0x91, 0x13, 0x14, 0xb5, 0x4c, 0x63, 0x13, 0x54, 0x8c, - 0x68, 0x28, 0xe6, 0x1d, 0x0f, 0x7a, 0x74, 0xec, 0xed, 0xf2, 0xd0, 0xf3, 0xb7, 0xe3, 0x41, 0x4f, - 0xdc, 0x2b, 0x82, 0x8f, 0x8c, 0x78, 0xe8, 0x3c, 0xbb, 0xc0, 0x33, 0x5c, 0x44, 0xbe, 0x71, 0xc8, - 0xc3, 0x27, 0x17, 0xe2, 0xea, 0xef, 0x45, 0xc8, 0x88, 0xdc, 0xab, 0x76, 0x0d, 0x0f, 0x78, 0xa5, - 0x17, 0x09, 0x16, 0xe4, 0x5e, 0x89, 0x43, 0x28, 0x46, 0xeb, 0xe2, 0x2e, 0xf0, 0x3e, 0x36, 0x1f, - 0x21, 0x47, 0x6d, 0xe0, 0x60, 0x57, 0x65, 0x81, 0xe8, 0x27, 0x12, 0x54, 0xaf, 0x06, 0x7b, 0x32, - 0x70, 0x4f, 0x23, 0x64, 0x29, 0x0d, 0xbb, 0x2e, 0x81, 0x5b, 0x02, 0x66, 0x7d, 0x4e, 0x42, 0x96, - 0xb1, 0xb7, 0xf2, 0xcc, 0x88, 0xab, 0x1e, 0x21, 0xb8, 0xaf, 0x15, 0x5b, 0x7e, 0x65, 0x6d, 0x5a, - 0x3e, 0x63, 0xd3, 0xac, 0x3f, 0xc8, 0x41, 0x5d, 0xb6, 0x8c, 0x42, 0x09, 0x7b, 0x00, 0x4c, 0xed, - 0x62, 0x7c, 0xe9, 0xf5, 0x9d, 0xe3, 0xab, 0x98, 0x47, 0x44, 0x34, 0xdb, 0xd7, 0xec, 0x96, 0x2c, - 0x3b, 0xba, 0xf4, 0xfa, 0x6b, 0xa2, 0x84, 0xdd, 0x87, 0x56, 0x0a, 0x3f, 0x8a, 0x43, 0xa2, 0xe8, - 0xed, 0x6b, 0x76, 0xd3, 0xc0, 0xee, 0xc6, 0xa1, 0x38, 0x23, 0x42, 0xe4, 0x19, 0xc7, 0x8e, 0xe7, - 0xf7, 0xf9, 0x25, 0x92, 0x51, 0xc3, 0xae, 0x11, 0x6c, 0x47, 0x80, 0xd6, 0x9a, 0x50, 0x37, 0x9b, - 0xb3, 0x4e, 0xa1, 0xa2, 0xe4, 0x25, 0x14, 0x18, 0x26, 0x86, 0x64, 0x57, 0x63, 0x3d, 0x92, 0x1b, - 0x50, 0x49, 0x8f, 0xc0, 0x2e, 0xc7, 0x2f, 0xdd, 0xb1, 0xf5, 0x7d, 0x68, 0xed, 0x0a, 0xe2, 0xf1, - 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x19, 0xe6, 0x8c, 0x43, 0x53, 0xb5, 0xe5, 0x97, 0xb8, 0x73, 0xcf, - 0x82, 0x28, 0x96, 0xbd, 0xe0, 0xdf, 0xd6, 0x9f, 0xe4, 0x80, 0x6d, 0x46, 0xb1, 0x37, 0x74, 0x63, - 0xbe, 0xc5, 0x35, 0x5b, 0x38, 0x80, 0xba, 0x68, 0xed, 0x28, 0x58, 0x25, 0x81, 0x8c, 0x04, 0x8a, - 0xb7, 0xe5, 0x31, 0x9e, 0xae, 0xf0, 0xc0, 0xc4, 0x26, 0x36, 0x9f, 0x6a, 0x40, 0x9c, 0xb2, 0xd8, - 0x0d, 0x4f, 0x79, 0x8c, 0x62, 0x9c, 0x94, 0xf7, 0x81, 0x40, 0x42, 0x80, 0xeb, 0xfc, 0x3a, 0x2c, - 0x4c, 0xb5, 0x61, 0xf2, 0xe5, 0x6a, 0x06, 0x5f, 0x2e, 0x98, 0x7c, 0xd9, 0x81, 0xc5, 0xd4, 0xb8, - 0x24, 0xa5, 0xad, 0x40, 0x59, 0x1c, 0x08, 0x21, 0x1c, 0xe4, 0x48, 0xaa, 0x3c, 0xe1, 0x5c, 0x88, - 0xc1, 0x0f, 0x61, 0xe9, 0x84, 0xf3, 0xd0, 0x8d, 0xb1, 0x10, 0x4f, 0x8c, 0xd8, 0x21, 0xd9, 0xf0, - 0x82, 0x2c, 0xeb, 0xba, 0xf1, 0x21, 0x0f, 0xc5, 0x4e, 0x59, 0xff, 0x27, 0x07, 0xf3, 0x82, 0x83, - 0xee, 0xb9, 0xfe, 0x95, 0x5a, 0xa7, 0xdd, 0xcc, 0x75, 0xba, 0x67, 0x5c, 0x86, 0x06, 0xf6, 0x37, - 0x5d, 0xa4, 0xc2, 0xe4, 0x22, 0xb1, 0x3b, 0x50, 0x4f, 0x8d, 0xb5, 0x84, 0x63, 0x85, 0x48, 0x0f, - 0xf2, 0x17, 0x5f, 0xc6, 0x37, 0xa1, 0x95, 0x0c, 0x5b, 0xae, 0x21, 0x83, 0xa2, 0x20, 0x49, 0xd9, - 0x00, 0xfe, 0x6d, 0xfd, 0xcb, 0x1c, 0x21, 0xae, 0x07, 0x9e, 0x96, 0x4e, 0x05, 0xa2, 0x90, 0x7b, - 0x15, 0xa2, 0xf8, 0x7b, 0xa6, 0x54, 0xff, 0x8b, 0x4f, 0x56, 0x1c, 0x9d, 0x88, 0xfb, 0x7d, 0xc7, - 0x1d, 0x0c, 0x90, 0xf9, 0x56, 0xec, 0xb2, 0xf8, 0x5e, 0x1d, 0x0c, 0xac, 0xbb, 0xb0, 0x60, 0x8c, - 0xee, 0x39, 0xf3, 0xd8, 0x07, 0xb6, 0xeb, 0x45, 0xf1, 0x53, 0x3f, 0x1a, 0x19, 0x82, 0xdb, 0x4d, - 0xa8, 0x0a, 0x0e, 0x2b, 0x46, 0x46, 0x47, 0xb6, 0x64, 0x0b, 0x96, 0x2b, 0xc6, 0x15, 0x61, 0xa1, - 0x7b, 0x29, 0x0b, 0xf3, 0xb2, 0xd0, 0xbd, 0xc4, 0x42, 0xeb, 0x23, 0x58, 0x4c, 0xb5, 0x27, 0xbb, - 0x7e, 0x0d, 0x4a, 0xe3, 0xf8, 0x32, 0x50, 0xa2, 0x79, 0x4d, 0x52, 0x88, 0x50, 0x00, 0x6d, 0x2a, - 0xb1, 0x3e, 0x81, 0x85, 0x7d, 0x7e, 0x21, 0x0f, 0xb1, 0x1a, 0xc8, 0x9b, 0x50, 0x7c, 0x81, 0x52, - 0x88, 0xe5, 0xd6, 0x03, 0x60, 0x66, 0x65, 0xd9, 0xab, 0xa1, 0x23, 0xe6, 0x52, 0x3a, 0xa2, 0xf5, - 0x26, 0xb0, 0xae, 0x77, 0xea, 0xef, 0xf1, 0x28, 0x72, 0x4f, 0xf5, 0xb1, 0x6f, 0x41, 0x61, 0x18, - 0x9d, 0x4a, 0x1e, 0x25, 0xfe, 0xb4, 0xbe, 0x0b, 0x8b, 0x29, 0x3c, 0xd9, 0xf0, 0x2b, 0x50, 0x8d, - 0xbc, 0x53, 0x1f, 0x05, 0x2b, 0xd9, 0x74, 0x02, 0xb0, 0xb6, 0x60, 0xe9, 0x87, 0x3c, 0xf4, 0x4e, - 0xae, 0x5e, 0xd4, 0x7c, 0xba, 0x9d, 0xfc, 0x64, 0x3b, 0x9b, 0x70, 0x7d, 0xa2, 0x1d, 0xd9, 0x3d, - 0x91, 0xaf, 0xdc, 0xc9, 0x8a, 0x4d, 0x1f, 0x06, 0xdf, 0xcb, 0x9b, 0x7c, 0xcf, 0x7a, 0x0a, 0x6c, - 0x3d, 0xf0, 0x7d, 0xde, 0x8b, 0x0f, 0x39, 0x0f, 0x13, 0x2b, 0x55, 0x42, 0xab, 0xb5, 0xc7, 0x2b, - 0x72, 0x65, 0x27, 0x99, 0xa9, 0x24, 0x62, 0x06, 0xc5, 0x11, 0x0f, 0x87, 0xd8, 0x70, 0xc5, 0xc6, - 0xbf, 0xad, 0xeb, 0xb0, 0x98, 0x6a, 0x56, 0xea, 0xf5, 0x8f, 0xe0, 0xfa, 0x86, 0x17, 0xf5, 0xa6, - 0x3b, 0x5c, 0x81, 0xf2, 0x68, 0x7c, 0xec, 0xa4, 0xf9, 0xf2, 0x13, 0x7e, 0x25, 0xb4, 0xbd, 0xc9, - 0x1a, 0xb2, 0xad, 0xbf, 0x9b, 0x83, 0xe2, 0xf6, 0xd1, 0xee, 0x3a, 0xeb, 0x40, 0xc5, 0xf3, 0x7b, - 0xc1, 0x50, 0x08, 0x5e, 0x34, 0x67, 0xfd, 0x3d, 0xf3, 0x80, 0xdd, 0x84, 0x2a, 0xca, 0x6b, 0x42, - 0xb5, 0x95, 0xa2, 0x4f, 0x45, 0x00, 0x76, 0x83, 0xde, 0x33, 0xa1, 0x53, 0xf3, 0xcb, 0x91, 0x17, - 0xa2, 0xd6, 0xac, 0x94, 0xe1, 0x22, 0xdd, 0xf5, 0x49, 0x01, 0x69, 0xc4, 0xd6, 0x7f, 0x2a, 0x43, - 0x59, 0xde, 0xb6, 0x74, 0x73, 0xc7, 0xde, 0x39, 0x4f, 0x6e, 0x6e, 0xf1, 0x25, 0xe4, 0x81, 0x90, - 0x0f, 0x83, 0x58, 0x0b, 0x6c, 0xb4, 0x07, 0x75, 0x02, 0x4a, 0x91, 0xcd, 0x10, 0x1a, 0xc8, 0xc4, - 0x50, 0x20, 0xa4, 0x9e, 0x79, 0x95, 0xdf, 0x84, 0xb2, 0xba, 0xfb, 0x8b, 0x5a, 0xa7, 0x99, 0xeb, - 0x91, 0xb4, 0xd6, 0x81, 0x4a, 0xcf, 0x1d, 0xb9, 0x3d, 0x2f, 0xbe, 0x92, 0x0c, 0x41, 0x7f, 0x8b, - 0xd6, 0x07, 0x41, 0xcf, 0x1d, 0x38, 0xc7, 0xee, 0xc0, 0xf5, 0x7b, 0x5c, 0xea, 0xee, 0x75, 0x04, - 0xae, 0x11, 0x4c, 0xe8, 0xe7, 0x72, 0x9c, 0x0a, 0x8b, 0x54, 0x78, 0x39, 0x7a, 0x85, 0x26, 0x84, - 0xcb, 0x60, 0x38, 0xf4, 0x84, 0x96, 0x41, 0x62, 0x58, 0xc1, 0xae, 0x12, 0x64, 0x8b, 0xe3, 0x6c, - 0x65, 0xf1, 0x05, 0x2d, 0x5d, 0x95, 0xba, 0x22, 0xe0, 0xe7, 0x64, 0x48, 0x98, 0x96, 0xc5, 0x0a, - 0x86, 0x2c, 0xf6, 0x36, 0x2c, 0x8c, 0xfd, 0x88, 0xc7, 0xf1, 0x80, 0xf7, 0xf5, 0x58, 0x6a, 0x88, - 0xd4, 0xd2, 0x05, 0x6a, 0x38, 0x0f, 0x60, 0x91, 0x8c, 0x0e, 0x91, 0x1b, 0x07, 0xd1, 0x99, 0x17, - 0x39, 0x91, 0xd0, 0x90, 0x48, 0xdd, 0x5d, 0xc0, 0xa2, 0xae, 0x2c, 0xe9, 0x92, 0x8a, 0xb4, 0x32, - 0x81, 0x1f, 0xf2, 0x1e, 0xf7, 0xce, 0x79, 0x1f, 0xe5, 0xb4, 0x82, 0x7d, 0x3d, 0x55, 0xc7, 0x96, - 0x85, 0x28, 0x74, 0x8f, 0x87, 0xce, 0x78, 0xd4, 0x77, 0x85, 0xb0, 0xd2, 0x24, 0x61, 0xd8, 0x1f, - 0x0f, 0x9f, 0x12, 0x84, 0x3d, 0x02, 0x25, 0x89, 0x49, 0xf9, 0x70, 0x3e, 0xc5, 0xcf, 0x04, 0xb1, - 0xda, 0x75, 0x89, 0x41, 0x82, 0x62, 0x4a, 0xe6, 0x6c, 0x4d, 0xc8, 0x9c, 0x6d, 0x28, 0x8f, 0x42, - 0xef, 0xdc, 0x8d, 0x79, 0x7b, 0x81, 0x18, 0xb8, 0xfc, 0x14, 0x9c, 0xc1, 0xf3, 0xbd, 0xd8, 0x73, - 0xe3, 0x20, 0x6c, 0x33, 0x2c, 0x4b, 0x00, 0xec, 0x3e, 0x2c, 0x20, 0x8d, 0x44, 0xb1, 0x1b, 0x8f, - 0x23, 0x29, 0x81, 0x2e, 0x22, 0x31, 0xa1, 0x0c, 0xdd, 0x45, 0x38, 0x0a, 0xa1, 0xec, 0xbb, 0xb0, - 0x4c, 0x64, 0x81, 0x35, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x12, 0x2e, 0xc5, 0x22, 0x96, 0x0a, 0xfa, - 0x96, 0xf2, 0xb5, 0x90, 0x0e, 0x3e, 0x80, 0x15, 0x49, 0x26, 0x53, 0xb5, 0xae, 0x63, 0xad, 0x25, - 0x2a, 0x9e, 0xa8, 0x76, 0x1f, 0x16, 0xc4, 0x90, 0xbc, 0x9e, 0x23, 0x6b, 0x8b, 0x93, 0xb0, 0x8c, - 0xa3, 0x9f, 0xa7, 0x02, 0x1b, 0xe1, 0x4f, 0xf8, 0x95, 0x20, 0xe5, 0x81, 0x77, 0xc2, 0x63, 0x6f, - 0xc8, 0xdb, 0x2b, 0x44, 0x1c, 0xea, 0x5b, 0x9c, 0xb2, 0xf1, 0x08, 0x4b, 0xda, 0x74, 0xa6, 0xe9, - 0x0b, 0xe9, 0x6e, 0x10, 0x44, 0x5c, 0x99, 0x97, 0xda, 0x37, 0xe4, 0x01, 0x12, 0x40, 0xc9, 0xb2, - 0xac, 0x9f, 0xe5, 0xe8, 0x0e, 0x92, 0x47, 0x36, 0x32, 0x34, 0x2a, 0x3a, 0xac, 0x4e, 0xe0, 0x0f, - 0xae, 0xe4, 0xf9, 0x05, 0x02, 0x1d, 0xf8, 0x03, 0x3c, 0x40, 0x9e, 0x6f, 0xa2, 0x10, 0xbb, 0xab, - 0x2b, 0x20, 0x22, 0xdd, 0x86, 0xda, 0x68, 0x7c, 0x3c, 0xf0, 0x7a, 0x84, 0x52, 0xa0, 0x56, 0x08, - 0x84, 0x08, 0x42, 0xa5, 0xa4, 0x4d, 0x24, 0x8c, 0x22, 0x62, 0xd4, 0x24, 0x0c, 0x51, 0x90, 0x9d, - 0xf2, 0x10, 0x4f, 0x70, 0xdd, 0xc6, 0xbf, 0xad, 0x35, 0x58, 0x4a, 0x0f, 0x5a, 0xf2, 0xfa, 0xfb, - 0x50, 0x91, 0xec, 0x41, 0xd9, 0x1a, 0x9a, 0x86, 0xf5, 0x57, 0x68, 0x45, 0xba, 0xdc, 0xfa, 0x9d, - 0x39, 0x58, 0x94, 0xd0, 0x75, 0xb1, 0x22, 0xdd, 0xf1, 0x70, 0xe8, 0x86, 0x19, 0x7c, 0x27, 0xf7, - 0x7c, 0xbe, 0x93, 0x9f, 0xe2, 0x3b, 0x69, 0x65, 0x93, 0xd8, 0x56, 0x5a, 0xd9, 0x14, 0x5b, 0x40, - 0xf2, 0xbf, 0x69, 0x7a, 0x6c, 0x48, 0xf0, 0x11, 0x99, 0x38, 0xa7, 0xb8, 0x64, 0x29, 0x83, 0x4b, - 0x9a, 0x3c, 0x6e, 0x6e, 0x82, 0xc7, 0xbd, 0x06, 0xb4, 0xd7, 0x8a, 0x65, 0x97, 0x49, 0x25, 0x40, - 0x98, 0xb4, 0x5f, 0xde, 0x85, 0xf9, 0x49, 0xb6, 0x42, 0xfc, 0xab, 0x99, 0xc1, 0x54, 0xbc, 0x21, - 0xc7, 0x0b, 0xc2, 0x40, 0xae, 0x4a, 0xa6, 0xe2, 0x0d, 0xf9, 0x2e, 0x96, 0x28, 0xfc, 0x4d, 0x00, - 0xea, 0x1b, 0x25, 0x12, 0x40, 0x89, 0xe4, 0xcd, 0xf4, 0x5e, 0x98, 0xab, 0xfe, 0x40, 0x7c, 0x8c, - 0x43, 0x8e, 0x52, 0x4a, 0x15, 0x6b, 0xa2, 0xe1, 0xfa, 0x09, 0x34, 0x83, 0x11, 0xf7, 0x9d, 0xe4, - 0x78, 0xd7, 0xb0, 0xa9, 0x37, 0x9e, 0xd3, 0xd4, 0x8e, 0xc2, 0xb5, 0x1b, 0xa2, 0xae, 0xfe, 0x64, - 0x7b, 0xb4, 0xf0, 0xdc, 0x68, 0xad, 0xfe, 0x0d, 0x5a, 0x6b, 0x62, 0x65, 0xfd, 0x6d, 0xfd, 0x83, - 0x1c, 0xd4, 0x8c, 0x61, 0xb3, 0xeb, 0xb0, 0xb0, 0x7e, 0x70, 0x70, 0xb8, 0x69, 0xaf, 0x1e, 0xed, - 0xfc, 0x70, 0xd3, 0x59, 0xdf, 0x3d, 0xe8, 0x6e, 0xb6, 0xae, 0x09, 0xf0, 0xee, 0xc1, 0xfa, 0xea, - 0xae, 0xb3, 0x75, 0x60, 0xaf, 0x2b, 0x70, 0x8e, 0x2d, 0x03, 0xb3, 0x37, 0xf7, 0x0e, 0x8e, 0x36, - 0x53, 0xf0, 0x3c, 0x6b, 0x41, 0x7d, 0xcd, 0xde, 0x5c, 0x5d, 0xdf, 0x96, 0x90, 0x02, 0x5b, 0x82, - 0xd6, 0xd6, 0xd3, 0xfd, 0x8d, 0x9d, 0xfd, 0x4f, 0x9d, 0xf5, 0xd5, 0xfd, 0xf5, 0xcd, 0xdd, 0xcd, - 0x8d, 0x56, 0x91, 0x35, 0xa0, 0xba, 0xba, 0xb6, 0xba, 0xbf, 0x71, 0xb0, 0xbf, 0xb9, 0xd1, 0x2a, - 0x59, 0xbf, 0x06, 0xd5, 0x64, 0xa2, 0x35, 0x28, 0x3f, 0xdd, 0x7f, 0xb2, 0x7f, 0xf0, 0xf9, 0x7e, - 0xeb, 0x1a, 0xab, 0x42, 0x09, 0xfb, 0x6f, 0xe5, 0x18, 0xc0, 0x1c, 0xf5, 0xd9, 0xca, 0xb3, 0x0a, - 0x14, 0xd7, 0x0e, 0x8e, 0xb6, 0x5b, 0x05, 0xeb, 0xcf, 0x73, 0x70, 0x1d, 0xa7, 0xdc, 0x9f, 0x64, - 0x02, 0x77, 0xa0, 0xd6, 0x0b, 0x82, 0x91, 0x50, 0x6e, 0x92, 0x4b, 0xdc, 0x04, 0x89, 0x03, 0x4e, - 0xfc, 0xf2, 0x24, 0x08, 0x7b, 0x5c, 0xf2, 0x00, 0x40, 0xd0, 0x96, 0x80, 0x08, 0x1a, 0x94, 0x44, - 0x4c, 0x18, 0xc4, 0x02, 0x6a, 0x04, 0x23, 0x94, 0x65, 0x98, 0x3b, 0x0e, 0xb9, 0xdb, 0x3b, 0x93, - 0xa7, 0x5f, 0x7e, 0xb1, 0xb7, 0x12, 0xb5, 0xbb, 0x27, 0x68, 0x6a, 0xc0, 0xfb, 0x78, 0x04, 0x2a, - 0xf6, 0xbc, 0x84, 0xaf, 0x4b, 0xb0, 0xb8, 0x00, 0xdc, 0x63, 0xd7, 0xef, 0x07, 0x3e, 0xef, 0x4b, - 0xe9, 0x3e, 0x01, 0x58, 0x87, 0xb0, 0x3c, 0x39, 0x3f, 0xc9, 0x2f, 0xbe, 0x67, 0xf0, 0x0b, 0x12, - 0xb6, 0x3b, 0xb3, 0x49, 0xc1, 0xe0, 0x1d, 0x3f, 0x2f, 0x40, 0x51, 0x08, 0x5f, 0x33, 0xe5, 0x34, - 0x53, 0x9a, 0x2e, 0x4c, 0x79, 0x5c, 0x50, 0xbb, 0xa7, 0x5b, 0x99, 0x4c, 0x48, 0x55, 0x84, 0xe0, - 0x6d, 0xac, 0x8b, 0x43, 0xde, 0x3b, 0x97, 0x36, 0x24, 0x2a, 0xb6, 0x79, 0xef, 0x1c, 0xd5, 0x18, - 0x37, 0xa6, 0xba, 0x74, 0xde, 0xcb, 0x91, 0x1b, 0x63, 0x4d, 0x59, 0x84, 0xf5, 0xca, 0xba, 0x08, - 0x6b, 0xb5, 0xa1, 0xec, 0xf9, 0xc7, 0xc1, 0xd8, 0xef, 0xe3, 0xf1, 0xae, 0xd8, 0xea, 0x13, 0x1d, - 0x3c, 0xc8, 0x89, 0xc4, 0xfd, 0x41, 0xa7, 0xb9, 0x22, 0x00, 0x47, 0xe2, 0x06, 0x79, 0x0f, 0xaa, - 0xd1, 0x95, 0xdf, 0x33, 0xcf, 0xf0, 0x92, 0x5c, 0x1f, 0x31, 0xfb, 0x07, 0xdd, 0x2b, 0xbf, 0x87, - 0x27, 0xb6, 0x12, 0xc9, 0xbf, 0xd8, 0x07, 0x50, 0xd1, 0xa6, 0x56, 0xe2, 0xc0, 0x37, 0xcc, 0x1a, - 0xca, 0xbe, 0x4a, 0x1a, 0xad, 0x46, 0xed, 0x3c, 0x81, 0x46, 0xaa, 0xc8, 0x54, 0x43, 0x1b, 0xa4, - 0x86, 0xbe, 0x61, 0xaa, 0xa1, 0x09, 0x63, 0x97, 0xd5, 0x4c, 0xb5, 0xf4, 0xd7, 0xa1, 0xa2, 0x46, - 0x26, 0x8e, 0x93, 0x3c, 0x0a, 0x4e, 0xf7, 0x8b, 0xfd, 0xf5, 0xd6, 0x35, 0x36, 0x0f, 0xb5, 0xd5, - 0x75, 0x3c, 0xa1, 0x08, 0xc8, 0x09, 0x94, 0xc3, 0xd5, 0x6e, 0x57, 0x43, 0xf2, 0x16, 0x83, 0x96, - 0xb8, 0x5e, 0xc4, 0x88, 0xb5, 0x33, 0xe5, 0x7b, 0xb0, 0x60, 0xc0, 0x12, 0x4d, 0x4d, 0xdc, 0x47, - 0x93, 0x9a, 0x1a, 0xca, 0xe5, 0x54, 0x62, 0xad, 0xc0, 0x75, 0xf1, 0xb9, 0x79, 0xce, 0xfd, 0xb8, - 0x3b, 0x3e, 0x26, 0x57, 0x9a, 0x17, 0xf8, 0x42, 0x5e, 0xaf, 0xea, 0x92, 0xd9, 0x84, 0xf4, 0x40, - 0x2a, 0x75, 0x79, 0x5c, 0xfe, 0x8e, 0xd1, 0x03, 0x56, 0x7c, 0x80, 0xff, 0xa6, 0x94, 0xbb, 0xaa, - 0x06, 0x89, 0xb9, 0x1e, 0x6e, 0x6e, 0xda, 0xce, 0xc1, 0xfe, 0xee, 0xce, 0xbe, 0x60, 0x46, 0x62, - 0xae, 0x08, 0xd8, 0xda, 0x42, 0x48, 0xce, 0x6a, 0x41, 0xf3, 0x53, 0x1e, 0xef, 0xf8, 0x27, 0x81, - 0x9a, 0xe9, 0x5f, 0x95, 0x60, 0x5e, 0x83, 0x12, 0xe5, 0xf0, 0x9c, 0x87, 0x91, 0x17, 0xf8, 0x28, - 0xe7, 0x55, 0x6d, 0xf5, 0x29, 0x6e, 0x10, 0xaf, 0xcf, 0xfd, 0xd8, 0x8b, 0xaf, 0x9c, 0x94, 0x25, - 0xa9, 0xa9, 0xc0, 0xf2, 0xa6, 0x5a, 0x82, 0x92, 0x3b, 0xf0, 0x5c, 0xe5, 0x81, 0xa4, 0x0f, 0x01, - 0xed, 0x05, 0x83, 0x20, 0x44, 0x91, 0xae, 0x6a, 0xd3, 0x07, 0x7b, 0x04, 0x4b, 0x42, 0xb4, 0x34, - 0xcd, 0x7b, 0x78, 0x46, 0xc9, 0xa8, 0xc5, 0xfc, 0xf1, 0xf0, 0x30, 0x31, 0xf1, 0x89, 0x12, 0x71, - 0x3f, 0x89, 0x1a, 0x52, 0x20, 0xd1, 0x15, 0x48, 0x4b, 0x59, 0xf0, 0xc7, 0xc3, 0x55, 0x2c, 0xd1, - 0xf8, 0x8f, 0xe1, 0xba, 0xc0, 0xd7, 0x22, 0x8c, 0xae, 0x31, 0x8f, 0x35, 0x44, 0x63, 0x3b, 0xb2, - 0x4c, 0xd7, 0xb9, 0x09, 0x55, 0x1a, 0x95, 0xd8, 0xf1, 0x12, 0x49, 0xa7, 0x38, 0x14, 0x1e, 0x46, - 0x53, 0xce, 0xc2, 0x39, 0xba, 0x6c, 0x27, 0x9c, 0x85, 0x86, 0xbb, 0xb1, 0x32, 0xe9, 0x6e, 0x7c, - 0x0c, 0xd7, 0x8f, 0x79, 0x14, 0x3b, 0x67, 0xdc, 0xed, 0xf3, 0x10, 0x4f, 0x24, 0xb9, 0x15, 0x49, - 0x0a, 0x5f, 0x14, 0x85, 0xdb, 0x58, 0x76, 0xa4, 0x8a, 0x84, 0x2c, 0x21, 0x8e, 0x1e, 0xef, 0x3b, - 0x71, 0xe0, 0xa0, 0x88, 0x81, 0x87, 0xb8, 0x62, 0x37, 0x08, 0x7c, 0x14, 0xac, 0x0b, 0x60, 0x1a, - 0xef, 0x34, 0x74, 0x47, 0x67, 0x52, 0x4e, 0xd6, 0x78, 0x9f, 0x0a, 0x20, 0x7b, 0x05, 0xca, 0x31, - 0x8f, 0x62, 0x9f, 0x93, 0x4f, 0xa7, 0x82, 0x36, 0x7b, 0x05, 0x62, 0x6f, 0xc0, 0x1c, 0xf6, 0x11, - 0xb5, 0x5b, 0x48, 0xef, 0xf5, 0x84, 0x59, 0x7a, 0xbe, 0x2d, 0xcb, 0x84, 0xc0, 0x36, 0x0e, 0xbd, - 0xa8, 0x5d, 0x47, 0x5f, 0x26, 0xfe, 0xcd, 0x7e, 0xc3, 0x60, 0x0b, 0x8b, 0x58, 0x57, 0xdd, 0xb9, - 0x13, 0x94, 0xf6, 0x2b, 0xe1, 0x10, 0x3f, 0x28, 0x56, 0x6a, 0xad, 0xba, 0xf5, 0x21, 0x94, 0x68, - 0x75, 0x04, 0x11, 0xe2, 0xda, 0xe5, 0x24, 0x11, 0x22, 0xb4, 0x0d, 0x65, 0x9f, 0xc7, 0x17, 0x41, - 0xf8, 0x4c, 0xd9, 0x5a, 0xe5, 0xa7, 0xf5, 0x53, 0x34, 0x12, 0x68, 0x47, 0x32, 0xe9, 0x3b, 0x82, - 0x3c, 0x68, 0x7b, 0xa3, 0x33, 0x57, 0xda, 0x2d, 0x2a, 0x08, 0xe8, 0x9e, 0xb9, 0x53, 0xe4, 0x91, - 0x9f, 0xf6, 0x25, 0xbf, 0x01, 0x4d, 0xe5, 0xba, 0x8e, 0x9c, 0x01, 0x3f, 0x89, 0x25, 0xb9, 0xd7, - 0xa5, 0xdf, 0x3a, 0xda, 0xe5, 0x27, 0xb1, 0xb5, 0x07, 0x0b, 0x92, 0x20, 0x0f, 0x46, 0x5c, 0x75, - 0xfd, 0x51, 0x96, 0xcc, 0x5a, 0x7b, 0xbc, 0x98, 0xbe, 0xcc, 0xc8, 0x25, 0x9f, 0x12, 0x64, 0xad, - 0xcf, 0x80, 0x99, 0x57, 0x9d, 0x6c, 0x4f, 0x4a, 0x8e, 0xca, 0x44, 0xad, 0x3c, 0x3d, 0x5a, 0x3e, - 0xf5, 0xfa, 0x62, 0x75, 0xa2, 0x71, 0xaf, 0xa7, 0x42, 0x0a, 0x2a, 0xb6, 0xfa, 0xb4, 0xfe, 0x2c, - 0x07, 0x8b, 0xd8, 0x98, 0x92, 0xb9, 0xa5, 0x34, 0xf1, 0xad, 0x07, 0x29, 0xf6, 0xc7, 0x94, 0x2f, - 0xe8, 0xe3, 0x9b, 0x1b, 0x05, 0x8b, 0x53, 0x46, 0xc1, 0xb7, 0xa0, 0xd5, 0xe7, 0x03, 0x0f, 0xa3, - 0x4b, 0xd4, 0x75, 0x4d, 0x52, 0xf6, 0xbc, 0x82, 0x2b, 0x45, 0xe9, 0x9f, 0xe5, 0x60, 0x81, 0xa4, - 0x01, 0x54, 0x17, 0xe5, 0x42, 0x7d, 0xa2, 0x74, 0x2c, 0xc9, 0xaa, 0xe4, 0x9c, 0x92, 0x5b, 0x12, - 0xa1, 0x84, 0xbc, 0x7d, 0x4d, 0xea, 0x5e, 0x12, 0xca, 0x3e, 0x46, 0x3d, 0xc1, 0x77, 0x10, 0x98, - 0x11, 0xad, 0x92, 0xde, 0x94, 0xed, 0x6b, 0xa8, 0x44, 0xf8, 0x08, 0x5a, 0xab, 0x08, 0xa5, 0x4f, - 0x80, 0xad, 0x2d, 0x68, 0xa4, 0xba, 0x49, 0x59, 0x2e, 0xeb, 0x64, 0xb9, 0x9c, 0xf2, 0x0e, 0xe4, - 0xa7, 0xbd, 0x03, 0x7f, 0xaf, 0x08, 0x4c, 0x90, 0xd4, 0xc4, 0xae, 0x4d, 0xb8, 0xd6, 0xf2, 0x53, - 0xae, 0xb5, 0x47, 0xc0, 0x0c, 0x04, 0xe5, 0xf1, 0x2b, 0x68, 0x8f, 0x5f, 0x2b, 0xc1, 0x95, 0x0e, - 0xbf, 0x47, 0xb0, 0x24, 0x85, 0x46, 0xed, 0x4b, 0x43, 0x93, 0x14, 0xed, 0x0f, 0x23, 0xe9, 0x51, - 0xf9, 0xd4, 0xd0, 0x3c, 0xa5, 0xdc, 0x6a, 0x42, 0xa5, 0x26, 0x4b, 0x0e, 0xba, 0xd5, 0x84, 0x16, - 0x3d, 0x41, 0x05, 0x73, 0x2f, 0xa4, 0x82, 0xf2, 0x14, 0x15, 0x18, 0x86, 0x85, 0x4a, 0xda, 0xb0, - 0x60, 0x41, 0x43, 0x39, 0xcf, 0x28, 0x66, 0x80, 0x24, 0xa4, 0x9a, 0xf4, 0xa0, 0x61, 0xdc, 0xc0, - 0x3d, 0x68, 0x29, 0xed, 0x5f, 0x9b, 0x2e, 0xc8, 0x1f, 0x2e, 0x8d, 0x47, 0xeb, 0xca, 0x80, 0x91, - 0x32, 0x14, 0xd7, 0x26, 0x0c, 0xc5, 0x6f, 0xc3, 0x42, 0x24, 0x88, 0xc8, 0x19, 0xfb, 0x32, 0x78, - 0x85, 0xf7, 0x51, 0x3d, 0xa9, 0xd8, 0x2d, 0x2c, 0x78, 0x9a, 0xc0, 0xa7, 0x55, 0xfb, 0xc6, 0xb4, - 0x6a, 0xcf, 0x3e, 0x48, 0xfc, 0x4c, 0xd1, 0x99, 0x37, 0xc4, 0x8b, 0x3b, 0x09, 0xf4, 0x90, 0x0b, - 0xdc, 0x3d, 0xf3, 0x86, 0xb6, 0x72, 0x6a, 0x8a, 0x0f, 0xeb, 0xbf, 0xe6, 0xa0, 0x25, 0xe8, 0x20, - 0x45, 0xe7, 0xbf, 0x06, 0x78, 0x22, 0x5f, 0x92, 0xcc, 0x6b, 0x02, 0x57, 0x51, 0xf9, 0x87, 0x80, - 0x64, 0xeb, 0x08, 0x5d, 0x4c, 0x12, 0x79, 0x3b, 0x4d, 0xe4, 0x09, 0x23, 0xdb, 0xbe, 0x46, 0x42, - 0xb6, 0x80, 0x64, 0xf9, 0xf7, 0x8a, 0x19, 0xfe, 0x3d, 0xe3, 0x28, 0x6c, 0x03, 0x3c, 0xe1, 0x57, - 0xbb, 0x41, 0x0f, 0xb5, 0xa0, 0x5b, 0x00, 0x82, 0x20, 0x4f, 0xdc, 0xa1, 0x27, 0x2d, 0x18, 0x25, - 0xbb, 0xfa, 0x8c, 0x5f, 0x6d, 0x21, 0x40, 0xec, 0x86, 0x28, 0x4e, 0xce, 0x43, 0xc9, 0xae, 0x3c, - 0xe3, 0x57, 0x74, 0x18, 0x1c, 0x68, 0x3c, 0xe1, 0x57, 0x1b, 0x9c, 0xc4, 0xb5, 0x20, 0x14, 0x94, - 0x10, 0xba, 0x17, 0x42, 0x3e, 0x4b, 0xf9, 0xe6, 0x6a, 0xa1, 0x7b, 0xf1, 0x84, 0x5f, 0x29, 0x3f, - 0x61, 0x59, 0x94, 0x0f, 0x82, 0x9e, 0xbc, 0x81, 0x54, 0x94, 0x41, 0x32, 0x28, 0x7b, 0xee, 0x19, - 0xfe, 0x6d, 0xfd, 0x69, 0x0e, 0x1a, 0x62, 0xfc, 0xc8, 0xe0, 0xc4, 0xba, 0xab, 0x60, 0x95, 0x5c, - 0x12, 0xac, 0xf2, 0x58, 0xf2, 0x07, 0xe2, 0x96, 0xf9, 0xd9, 0xdc, 0x12, 0x17, 0x98, 0x58, 0xe5, - 0x7b, 0x50, 0xa5, 0xb3, 0x25, 0x0e, 0x6b, 0x21, 0xb5, 0x4b, 0xa9, 0x09, 0xd9, 0x15, 0x44, 0x7b, - 0x42, 0xbe, 0x71, 0xc3, 0x00, 0x45, 0x4b, 0x5c, 0x0d, 0xb5, 0xe9, 0x29, 0x63, 0x1b, 0x4a, 0x59, - 0x6e, 0xd6, 0xa7, 0x50, 0x33, 0x68, 0x8a, 0x7d, 0x9f, 0x1c, 0xd4, 0x34, 0x78, 0x22, 0xc0, 0x34, - 0xd1, 0xa4, 0x66, 0xbf, 0x7d, 0xcd, 0x6e, 0xf4, 0x4c, 0xc0, 0xda, 0x1c, 0x14, 0x45, 0x25, 0xeb, - 0x13, 0x58, 0x30, 0x9a, 0x25, 0x8d, 0x2f, 0x6b, 0x4c, 0xb9, 0xac, 0x31, 0xfd, 0xf3, 0x1c, 0x2c, - 0xc9, 0xda, 0x18, 0xd8, 0xe4, 0x89, 0xeb, 0x7a, 0x2f, 0x3a, 0x65, 0xbf, 0x06, 0x0d, 0xd1, 0xba, - 0x13, 0xf2, 0x53, 0x2f, 0x8a, 0xb9, 0xb2, 0xec, 0x67, 0x1c, 0x0e, 0xc1, 0xb5, 0x05, 0xaa, 0x2d, - 0x31, 0xd9, 0x27, 0x50, 0xc3, 0xaa, 0xa4, 0x93, 0xca, 0x6d, 0x69, 0x4f, 0x57, 0xa4, 0xa1, 0x6e, - 0x5f, 0xb3, 0x21, 0xd2, 0x5f, 0x6b, 0x55, 0x28, 0xc7, 0xa1, 0x77, 0x7a, 0xca, 0x43, 0x6b, 0x59, - 0x0f, 0x4d, 0x9c, 0x34, 0xde, 0x8d, 0xf9, 0x48, 0x08, 0x41, 0xd6, 0x7f, 0xcf, 0x41, 0x4d, 0x9e, - 0x9d, 0x6f, 0x6d, 0xce, 0xef, 0x18, 0x91, 0x79, 0xa4, 0x7e, 0x26, 0x81, 0x78, 0x77, 0x61, 0x7e, - 0x28, 0x04, 0x22, 0x21, 0xb0, 0xa7, 0x6c, 0xf9, 0x4d, 0x05, 0x96, 0xf2, 0xc8, 0x03, 0x58, 0x44, - 0xf1, 0x24, 0x72, 0x62, 0x6f, 0xe0, 0xa8, 0x42, 0x19, 0x05, 0xb7, 0x40, 0x45, 0x47, 0xde, 0x60, - 0x4f, 0x16, 0x88, 0x5b, 0x3a, 0x8a, 0xdd, 0x53, 0x2e, 0x45, 0x5f, 0xfa, 0xb0, 0xda, 0xb0, 0x3c, - 0x21, 0xab, 0x2b, 0x3d, 0xe3, 0x1f, 0x36, 0x60, 0x65, 0xaa, 0x48, 0xea, 0x1b, 0xda, 0x86, 0x3d, - 0xf0, 0x86, 0xc7, 0x81, 0x36, 0x37, 0xe5, 0x0c, 0x1b, 0xf6, 0xae, 0x28, 0x51, 0xe6, 0x26, 0x0e, - 0xd7, 0x15, 0x41, 0xa0, 0xbd, 0x48, 0x8b, 0xf3, 0x79, 0x14, 0x36, 0xdf, 0x4b, 0x33, 0xaa, 0xc9, - 0xee, 0x14, 0xdc, 0xbc, 0xfe, 0x16, 0x47, 0x53, 0xb0, 0x88, 0x9d, 0x40, 0x5b, 0xd3, 0x9d, 0x94, - 0x8f, 0x0c, 0xdd, 0x44, 0xf4, 0xf4, 0xce, 0x0b, 0x7a, 0x4a, 0x19, 0x22, 0xec, 0x65, 0x45, 0xae, - 0xd4, 0x98, 0xee, 0xe7, 0x1c, 0x5e, 0x55, 0xfd, 0xa0, 0xac, 0x33, 0xdd, 0x5b, 0xf1, 0xa5, 0xe6, - 0x85, 0x06, 0x96, 0x74, 0x97, 0x37, 0x65, 0xc3, 0xba, 0xc8, 0xec, 0xf7, 0x0c, 0x96, 0x2f, 0x5c, - 0x2f, 0x56, 0xf3, 0x33, 0xd4, 0xa2, 0x12, 0xf6, 0xf7, 0xf8, 0x05, 0xfd, 0x7d, 0x4e, 0x95, 0x53, - 0xd2, 0xdf, 0xd2, 0xc5, 0x34, 0x30, 0xea, 0xfc, 0xe7, 0x3c, 0x34, 0xd3, 0xad, 0x88, 0x43, 0x2d, - 0xf9, 0x90, 0x92, 0x27, 0xa4, 0x3c, 0x2e, 0xcd, 0xa0, 0xfb, 0x24, 0x47, 0x4c, 0x1b, 0x68, 0xf3, - 0x19, 0x06, 0x5a, 0xd3, 0x2e, 0x5a, 0x78, 0x91, 0xef, 0xa7, 0xf8, 0x52, 0xbe, 0x9f, 0x52, 0x96, - 0xef, 0x67, 0xb6, 0xc3, 0x60, 0xee, 0x5b, 0x39, 0x0c, 0xca, 0xb3, 0x1d, 0x06, 0x9d, 0xbf, 0xce, - 0x01, 0x9b, 0xa6, 0x54, 0xf6, 0x29, 0xd9, 0xa2, 0x7d, 0x3e, 0x90, 0x5c, 0xec, 0xdd, 0x97, 0xa3, - 0x76, 0xb5, 0x41, 0xaa, 0x36, 0x7b, 0x08, 0x8b, 0x66, 0xdc, 0xac, 0xa9, 0xaa, 0x34, 0x6c, 0x66, - 0x16, 0x25, 0x0a, 0xad, 0xe1, 0xf8, 0x2a, 0xbe, 0xd0, 0xf1, 0x55, 0x7a, 0xa1, 0xe3, 0x6b, 0x2e, - 0xed, 0xf8, 0xea, 0xfc, 0x9d, 0x1c, 0x2c, 0x66, 0x10, 0xd5, 0x2f, 0x6f, 0xce, 0x82, 0x16, 0x52, - 0x2c, 0x26, 0x2f, 0x69, 0xc1, 0xe0, 0x2e, 0x9d, 0xaf, 0xa0, 0x91, 0x3a, 0x44, 0xbf, 0xbc, 0xee, - 0x27, 0x15, 0x2d, 0x22, 0x65, 0x53, 0xd1, 0xea, 0xfc, 0x65, 0x1e, 0xd8, 0xf4, 0x39, 0xfe, 0x55, - 0x0e, 0x61, 0x7a, 0x91, 0x0a, 0xd3, 0x8b, 0xf4, 0xff, 0xee, 0x5e, 0x79, 0x1b, 0x16, 0x64, 0xac, - 0xbf, 0xe1, 0x78, 0x20, 0x42, 0x69, 0xe9, 0x02, 0x35, 0x8a, 0x0f, 0x27, 0x7d, 0x8e, 0x95, 0x54, - 0x78, 0xb3, 0x71, 0xb1, 0xa6, 0x5d, 0x8f, 0x56, 0x07, 0xda, 0x72, 0x69, 0xa6, 0x4d, 0x75, 0xbf, - 0x57, 0xd4, 0x5a, 0x32, 0x16, 0x4a, 0xa1, 0xf8, 0xbb, 0x50, 0x37, 0x2f, 0x1b, 0xb9, 0x0f, 0x13, - 0x1e, 0x27, 0x21, 0x0e, 0x07, 0xc6, 0x69, 0x5d, 0x07, 0xf2, 0x23, 0xf4, 0x75, 0x35, 0x92, 0x20, - 0x9e, 0x63, 0x78, 0x46, 0xe1, 0x28, 0xb5, 0xf9, 0xff, 0x1f, 0x34, 0xd3, 0x76, 0x2b, 0x29, 0xea, - 0x65, 0x49, 0x87, 0xa2, 0x76, 0xca, 0x90, 0xc5, 0x7e, 0x03, 0x5a, 0x93, 0x76, 0x2f, 0x19, 0x7b, - 0x39, 0xa3, 0xfe, 0xbc, 0x97, 0x36, 0x85, 0xb1, 0x6d, 0x58, 0xca, 0xba, 0x6e, 0x71, 0x57, 0x66, - 0xab, 0x05, 0x6c, 0xfa, 0x4a, 0x65, 0x1f, 0x49, 0xf3, 0x66, 0x29, 0xcb, 0x11, 0x63, 0x2c, 0xf6, - 0x03, 0xfa, 0xcf, 0x30, 0x74, 0x9e, 0x03, 0x24, 0x30, 0xd6, 0x82, 0xfa, 0xc1, 0xe1, 0xe6, 0xbe, - 0xb3, 0xbe, 0xbd, 0xba, 0xbf, 0xbf, 0xb9, 0xdb, 0xba, 0xc6, 0x18, 0x34, 0xd1, 0x83, 0xb2, 0xa1, - 0x61, 0x39, 0x01, 0x93, 0xb6, 0x5f, 0x05, 0xcb, 0xb3, 0x25, 0x68, 0xed, 0xec, 0x4f, 0x40, 0x0b, - 0xac, 0x0d, 0x4b, 0x87, 0x9b, 0xe4, 0x74, 0x49, 0xb5, 0x5b, 0x14, 0x22, 0x9c, 0x9c, 0xae, 0x10, - 0xe1, 0x28, 0x53, 0x44, 0x52, 0x9f, 0x92, 0x6c, 0x7e, 0x3f, 0x07, 0xd7, 0x27, 0x0a, 0x92, 0xf8, - 0x5f, 0x92, 0x6b, 0xd2, 0x12, 0x4d, 0x1d, 0x81, 0x8a, 0x86, 0xdf, 0x86, 0x05, 0xad, 0xea, 0x4d, - 0xf0, 0xa5, 0x96, 0x2e, 0x50, 0xc8, 0x0f, 0x61, 0xd1, 0xd0, 0x18, 0x27, 0x4e, 0x28, 0x33, 0x8a, - 0x64, 0x05, 0x6b, 0x45, 0xc7, 0x59, 0x4e, 0x8c, 0xba, 0x4f, 0xe9, 0x27, 0x66, 0x41, 0x62, 0xfd, - 0x4d, 0x8f, 0x57, 0x7d, 0x0a, 0x55, 0x3e, 0x45, 0x08, 0xe9, 0xd1, 0x9a, 0x1b, 0xae, 0xba, 0xff, - 0xc3, 0x39, 0x60, 0x9f, 0x8d, 0x79, 0x78, 0x85, 0xf1, 0xbd, 0xd1, 0x8b, 0x02, 0x5e, 0x94, 0x5a, - 0x94, 0x7f, 0xa9, 0x18, 0xfe, 0xac, 0x18, 0xfa, 0xe2, 0x8b, 0x63, 0xe8, 0x4b, 0x2f, 0x8a, 0xa1, - 0x7f, 0x1d, 0x1a, 0xde, 0xa9, 0x1f, 0x08, 0x06, 0x24, 0x64, 0x93, 0xa8, 0x3d, 0x77, 0xa7, 0x70, - 0xaf, 0x6e, 0xd7, 0x25, 0x50, 0x48, 0x26, 0x11, 0xfb, 0x24, 0x41, 0xe2, 0xfd, 0x53, 0xcc, 0xf7, - 0x30, 0x59, 0xcf, 0x66, 0xff, 0x94, 0x4b, 0x2d, 0x10, 0xed, 0x22, 0xaa, 0xb2, 0x80, 0x47, 0xec, - 0x0d, 0x68, 0x46, 0xc1, 0x58, 0x88, 0x7a, 0x6a, 0x19, 0xc8, 0x3e, 0x5c, 0x27, 0xe8, 0xa1, 0x72, - 0x06, 0x2c, 0x8e, 0x23, 0xee, 0x0c, 0xbd, 0x28, 0x12, 0x17, 0x74, 0x2f, 0xf0, 0xe3, 0x30, 0x18, - 0x48, 0x93, 0xef, 0xc2, 0x38, 0xe2, 0x7b, 0x54, 0xb2, 0x4e, 0x05, 0xec, 0xfd, 0x64, 0x48, 0x23, - 0xd7, 0x0b, 0xa3, 0x36, 0xe0, 0x90, 0xd4, 0x4c, 0x51, 0xa2, 0x72, 0xbd, 0x50, 0x8f, 0x45, 0x7c, - 0x44, 0x13, 0xb1, 0xfd, 0xb5, 0xc9, 0xd8, 0xfe, 0x9f, 0x64, 0xc7, 0xf6, 0x37, 0xb0, 0xe9, 0x47, - 0xb2, 0xe9, 0xe9, 0x2d, 0xfe, 0x46, 0x21, 0xfe, 0xd3, 0x29, 0x0b, 0xcd, 0x6f, 0x92, 0xb2, 0x30, - 0x9f, 0x95, 0xb2, 0xf0, 0x1e, 0xd4, 0x30, 0x98, 0xdc, 0x39, 0xf3, 0xfc, 0x58, 0x99, 0xb0, 0x5b, - 0x66, 0xb4, 0xf9, 0xb6, 0x50, 0xa6, 0x21, 0x54, 0x7f, 0x46, 0xd3, 0xd9, 0x03, 0x0b, 0xbf, 0xc2, - 0xec, 0x01, 0x19, 0xf4, 0xfe, 0x00, 0x2a, 0x6a, 0x9f, 0x18, 0x83, 0xe2, 0x49, 0x18, 0x0c, 0x95, - 0x69, 0x4f, 0xfc, 0xcd, 0x9a, 0x90, 0x8f, 0x03, 0x59, 0x39, 0x1f, 0x07, 0xd6, 0x6f, 0x41, 0xcd, - 0x20, 0x35, 0xf6, 0x1a, 0x19, 0x11, 0x84, 0xb4, 0x2c, 0xb5, 0x64, 0x5a, 0xc5, 0xaa, 0x84, 0xee, - 0xf4, 0x05, 0xbf, 0xe9, 0x7b, 0x21, 0xc7, 0x3c, 0x1f, 0x27, 0xe4, 0xe7, 0x3c, 0x8c, 0x94, 0xa9, - 0xb5, 0xa5, 0x0b, 0x6c, 0x82, 0x5b, 0x7f, 0x13, 0x16, 0x53, 0x7b, 0x2b, 0x59, 0xc4, 0x1b, 0x30, - 0x87, 0xeb, 0xa6, 0x5c, 0x61, 0xe9, 0x28, 0x7e, 0x59, 0x86, 0x09, 0x9c, 0x64, 0x25, 0x76, 0x46, - 0x61, 0x70, 0x8c, 0x9d, 0xe4, 0xec, 0x9a, 0x84, 0x1d, 0x86, 0xc1, 0xb1, 0xf5, 0xf3, 0x02, 0x14, - 0xb6, 0x83, 0x91, 0x19, 0x61, 0x91, 0x9b, 0x8a, 0xb0, 0x90, 0x2a, 0x80, 0xa3, 0x45, 0x7c, 0x29, - 0xb5, 0xa1, 0x7d, 0x54, 0x89, 0xf9, 0xf7, 0xa0, 0x29, 0xf8, 0x44, 0x1c, 0x08, 0x1d, 0xea, 0xc2, - 0x0d, 0x29, 0xa6, 0xbf, 0x40, 0x87, 0xcf, 0x1d, 0xc6, 0x47, 0xc1, 0x16, 0xc1, 0xd9, 0x12, 0x14, - 0xb4, 0x00, 0x8b, 0xc5, 0xe2, 0x53, 0x28, 0xd7, 0x18, 0xdd, 0x76, 0x25, 0x7d, 0x3d, 0xf2, 0x8b, - 0xbd, 0x0b, 0x8b, 0xe9, 0x76, 0x89, 0x15, 0x49, 0x89, 0xc4, 0x6c, 0x18, 0x79, 0xd2, 0x0d, 0x10, - 0x7c, 0x84, 0x70, 0xa4, 0x5b, 0xf6, 0x84, 0x73, 0x2c, 0x32, 0x98, 0x5e, 0x25, 0xc5, 0xf4, 0x6e, - 0x43, 0x2d, 0x1e, 0x9c, 0x3b, 0x23, 0xf7, 0x6a, 0x10, 0xb8, 0x7d, 0x79, 0xbe, 0x21, 0x1e, 0x9c, - 0x1f, 0x12, 0x84, 0x3d, 0x04, 0x18, 0x8e, 0x46, 0xf2, 0xec, 0xa1, 0xb9, 0x31, 0x21, 0xe5, 0xbd, - 0xc3, 0x43, 0x22, 0x39, 0xbb, 0x3a, 0x1c, 0x8d, 0xe8, 0x4f, 0xb6, 0x01, 0xcd, 0xcc, 0x5c, 0x9c, - 0x5b, 0x2a, 0x18, 0x2b, 0x18, 0x3d, 0xc8, 0x38, 0x9c, 0x8d, 0x9e, 0x09, 0xeb, 0xfc, 0x06, 0xb0, - 0x5f, 0x30, 0x23, 0xe6, 0x08, 0xaa, 0x7a, 0x7c, 0x66, 0x42, 0x09, 0x86, 0x57, 0xd6, 0x52, 0x09, - 0x25, 0xab, 0xfd, 0x7e, 0x28, 0xf8, 0x22, 0x5d, 0x98, 0x9a, 0xe5, 0x83, 0x71, 0x63, 0xae, 0x12, - 0xdf, 0xb7, 0xfe, 0x22, 0x07, 0x25, 0xca, 0x6e, 0x79, 0x13, 0xe6, 0x09, 0x5f, 0x47, 0xab, 0x48, - 0x0f, 0x11, 0xdd, 0xbb, 0x47, 0x32, 0x50, 0x45, 0x1c, 0x0b, 0x23, 0x33, 0x2f, 0xaf, 0x77, 0xde, - 0xc8, 0xce, 0xbb, 0x0d, 0x55, 0xdd, 0xb5, 0x41, 0x3a, 0x15, 0xd5, 0x33, 0x7b, 0x15, 0x8a, 0x67, - 0xc1, 0x48, 0xe9, 0xe2, 0x90, 0xac, 0xa4, 0x8d, 0xf0, 0x64, 0x2c, 0xa2, 0x0f, 0x1a, 0xbc, 0xd4, - 0x21, 0x75, 0x27, 0x48, 0x06, 0xd3, 0x73, 0x9c, 0xcb, 0x98, 0xe3, 0x53, 0x98, 0x17, 0x7c, 0xc0, - 0xf0, 0xd4, 0xce, 0xbe, 0x34, 0xdf, 0x12, 0x12, 0x5e, 0x6f, 0x30, 0xee, 0x73, 0xd3, 0x12, 0x82, - 0xa1, 0x13, 0x12, 0xae, 0xd4, 0x03, 0xeb, 0x0f, 0x73, 0xc4, 0x5f, 0x44, 0xbb, 0xec, 0x1e, 0x14, - 0xc5, 0xfd, 0x36, 0x61, 0xa9, 0xd3, 0x71, 0xae, 0x02, 0xcf, 0x46, 0x0c, 0x4c, 0x67, 0x1d, 0x0f, - 0xd3, 0xad, 0x37, 0xec, 0x9a, 0x3f, 0x1e, 0x6a, 0x63, 0xc2, 0x77, 0xd4, 0xb4, 0x26, 0x14, 0x71, - 0x9a, 0xbd, 0x3e, 0xa6, 0x0f, 0x8c, 0x18, 0x8c, 0x62, 0xea, 0xc6, 0x54, 0x52, 0x60, 0xff, 0x94, - 0x1b, 0xb1, 0x17, 0x7f, 0x9c, 0x87, 0x46, 0x6a, 0x44, 0x18, 0x84, 0x22, 0x2e, 0x00, 0xb2, 0x02, - 0xcb, 0xfd, 0x06, 0x01, 0x92, 0x82, 0xba, 0xb1, 0x4e, 0xf9, 0xd4, 0x3a, 0x69, 0x9f, 0x74, 0xc1, - 0xf4, 0x49, 0x3f, 0x82, 0x6a, 0x92, 0x91, 0x99, 0x1e, 0x92, 0xe8, 0x4f, 0x45, 0xfb, 0x26, 0x48, - 0x89, 0x17, 0xbb, 0x64, 0x7a, 0xb1, 0xbf, 0x6f, 0x38, 0x3d, 0xe7, 0xb0, 0x19, 0x2b, 0x6b, 0x45, - 0x7f, 0x35, 0x41, 0x11, 0x9f, 0x40, 0xcd, 0x18, 0xbc, 0xe9, 0xdc, 0xcc, 0xa5, 0x9c, 0x9b, 0x3a, - 0x2e, 0x3f, 0x9f, 0xc4, 0xe5, 0x5b, 0xbf, 0x93, 0x87, 0x86, 0x38, 0x5f, 0x9e, 0x7f, 0x7a, 0x18, - 0x0c, 0xbc, 0x1e, 0x5a, 0x85, 0xf5, 0x09, 0x93, 0x82, 0x96, 0x3a, 0x67, 0xf2, 0x88, 0x91, 0x9c, - 0x65, 0xa6, 0x1f, 0x11, 0x93, 0xd6, 0xe9, 0x47, 0x16, 0x34, 0x04, 0x63, 0x3c, 0x76, 0x23, 0x6e, - 0xe4, 0x8b, 0xda, 0xb5, 0x13, 0xce, 0xd7, 0xdc, 0x88, 0x38, 0xe4, 0xbb, 0xb0, 0x28, 0x70, 0x30, - 0xf3, 0x62, 0xe8, 0x0d, 0x06, 0x1e, 0x61, 0x92, 0xa9, 0xa1, 0x75, 0xc2, 0xb9, 0xed, 0xc6, 0x7c, - 0x4f, 0x14, 0xc8, 0xf4, 0xd2, 0x4a, 0xdf, 0x8b, 0xdc, 0xe3, 0x24, 0x54, 0x48, 0x7f, 0xa3, 0x2f, - 0xc7, 0xbd, 0x34, 0x7c, 0x39, 0x94, 0x82, 0x55, 0x1b, 0xba, 0x97, 0xda, 0x97, 0x33, 0x41, 0x49, - 0xe5, 0x49, 0x4a, 0xb2, 0xfe, 0x5b, 0x1e, 0x6a, 0x06, 0x59, 0xbe, 0xcc, 0xed, 0x7a, 0x6b, 0xca, - 0x8a, 0x5f, 0x35, 0x0d, 0xf6, 0xaf, 0xa7, 0xbb, 0x44, 0x97, 0x2f, 0x25, 0xb2, 0x1a, 0x04, 0x7c, - 0x13, 0xaa, 0xe2, 0xd4, 0xbd, 0x87, 0x46, 0x31, 0x99, 0x86, 0x8d, 0x80, 0xc3, 0xf1, 0xb1, 0x2a, - 0x7c, 0x8c, 0x85, 0xa5, 0xa4, 0xf0, 0xb1, 0x28, 0x7c, 0x5e, 0x7c, 0xe0, 0x87, 0x50, 0x97, 0xad, - 0xe2, 0x9e, 0xe2, 0x74, 0x93, 0x53, 0x9f, 0xda, 0x6f, 0xbb, 0x46, 0xdd, 0xd1, 0xe6, 0xcb, 0x8a, - 0x8f, 0x55, 0xc5, 0xca, 0x8b, 0x2a, 0x3e, 0xa6, 0x0f, 0x6b, 0x4b, 0x87, 0x5c, 0x62, 0xb8, 0x81, - 0xe2, 0x63, 0x0f, 0x61, 0x51, 0xb1, 0xab, 0xb1, 0xef, 0xfa, 0x7e, 0x30, 0xf6, 0x7b, 0x5c, 0x05, - 0xec, 0x33, 0x59, 0xf4, 0x34, 0x29, 0xb1, 0xfa, 0x3a, 0xa3, 0x8b, 0xc2, 0x16, 0xee, 0x43, 0x89, - 0xe4, 0x72, 0x12, 0x3e, 0xb2, 0x19, 0x17, 0xa1, 0xb0, 0x7b, 0x50, 0x22, 0xf1, 0x3c, 0x3f, 0x93, - 0xd9, 0x10, 0x82, 0xf5, 0x00, 0xe6, 0x51, 0xc4, 0x34, 0x38, 0xee, 0xf3, 0xa4, 0x12, 0x6b, 0x09, - 0xd8, 0x3e, 0x1d, 0x22, 0x33, 0x9c, 0xe6, 0x7f, 0x15, 0xa0, 0x66, 0x80, 0x05, 0x5b, 0xc4, 0x00, - 0x0c, 0xa7, 0xef, 0xb9, 0x43, 0xae, 0x7c, 0x0f, 0x0d, 0xbb, 0x81, 0xd0, 0x0d, 0x09, 0x14, 0x97, - 0x82, 0x7b, 0x7e, 0xea, 0x04, 0xe3, 0xd8, 0xe9, 0xf3, 0xd3, 0x90, 0x73, 0x29, 0x2c, 0xd5, 0xdd, - 0xf3, 0xd3, 0x83, 0x71, 0xbc, 0x81, 0x30, 0x81, 0x25, 0x88, 0xda, 0xc0, 0x92, 0x31, 0x03, 0x43, - 0xf7, 0x32, 0xc1, 0x92, 0x81, 0x2b, 0xb4, 0x44, 0x45, 0x1d, 0xb8, 0x42, 0x6a, 0xcb, 0x24, 0x27, - 0x2f, 0x4d, 0x73, 0xf2, 0xf7, 0x61, 0x99, 0x38, 0xb9, 0xe4, 0x11, 0xce, 0x04, 0x49, 0x2d, 0x61, - 0xa9, 0x9c, 0xa4, 0x21, 0x7f, 0xb5, 0xc4, 0x0c, 0xd4, 0xf9, 0x88, 0xbc, 0x9f, 0xd2, 0x89, 0xca, - 0xd9, 0x62, 0x66, 0xb2, 0xf1, 0xae, 0xf7, 0x53, 0x2e, 0x30, 0xd1, 0x31, 0x6a, 0x62, 0xca, 0x30, - 0xd4, 0xa1, 0xe7, 0x4f, 0x62, 0xba, 0x97, 0x69, 0xcc, 0xaa, 0xc4, 0x74, 0x2f, 0x4d, 0xcc, 0x0f, - 0x60, 0x65, 0xc8, 0xfb, 0x9e, 0x9b, 0x6e, 0xd6, 0x49, 0x24, 0x88, 0x25, 0x2a, 0x36, 0xea, 0x74, - 0x49, 0x83, 0x14, 0xab, 0xf1, 0xd3, 0x60, 0x78, 0xec, 0xd1, 0xe5, 0x49, 0xae, 0xda, 0xa2, 0xdd, - 0xf4, 0xc7, 0xc3, 0x1f, 0x21, 0x58, 0x54, 0x89, 0xac, 0x06, 0xd4, 0xba, 0x71, 0x30, 0x52, 0xdb, - 0xdc, 0x84, 0x3a, 0x7d, 0xca, 0x74, 0x8c, 0x9b, 0x70, 0x03, 0x69, 0xf3, 0x28, 0x18, 0x05, 0x83, - 0xe0, 0xf4, 0x2a, 0x65, 0x50, 0xfa, 0x1f, 0x39, 0x58, 0x4c, 0x95, 0xca, 0x73, 0xfe, 0x3e, 0x1d, - 0x2c, 0x1d, 0x53, 0x4f, 0xe4, 0xbc, 0x60, 0x5c, 0x3e, 0x84, 0x48, 0xa7, 0x4a, 0xc5, 0xd9, 0xaf, - 0x26, 0xb9, 0xa0, 0xaa, 0x22, 0xd1, 0x76, 0x7b, 0x9a, 0xb6, 0x65, 0x7d, 0x95, 0x25, 0xaa, 0x9a, - 0xf8, 0xff, 0x65, 0xa8, 0x70, 0x5f, 0x4e, 0xb9, 0x90, 0x0e, 0x86, 0x34, 0x8d, 0x4f, 0x6a, 0x04, - 0x89, 0x45, 0x2a, 0xb2, 0xfe, 0x4d, 0x0e, 0x20, 0x19, 0x1d, 0x86, 0x63, 0xea, 0x0b, 0x94, 0x9e, - 0x59, 0x31, 0x2e, 0xcb, 0xd7, 0xa0, 0xae, 0x23, 0xc6, 0x92, 0x2b, 0xb9, 0xa6, 0x60, 0xe2, 0x5e, - 0xbe, 0x0b, 0xf3, 0xa7, 0x83, 0xe0, 0x18, 0x45, 0x27, 0x79, 0x81, 0x52, 0x52, 0x4a, 0x93, 0xc0, - 0xea, 0x5a, 0x4c, 0x2e, 0xf0, 0x62, 0x66, 0x50, 0x99, 0x79, 0x1d, 0x5b, 0xbf, 0x9b, 0xd7, 0xa1, - 0x33, 0xc9, 0x4a, 0x3c, 0x5f, 0xcf, 0xf8, 0x36, 0x1e, 0xd8, 0xe7, 0x79, 0x1e, 0x3e, 0x81, 0x66, - 0x48, 0xdc, 0x51, 0xb1, 0xce, 0xe2, 0x73, 0x58, 0x67, 0x23, 0x4c, 0x5d, 0xb9, 0x6f, 0x41, 0xcb, - 0xed, 0x9f, 0xf3, 0x30, 0xf6, 0xd0, 0x58, 0x8b, 0x82, 0x9a, 0x0c, 0x56, 0x31, 0xe0, 0x28, 0x11, - 0xdd, 0x85, 0x79, 0x99, 0x22, 0xa4, 0x31, 0xe5, 0xa3, 0x03, 0x09, 0x58, 0x20, 0x5a, 0xff, 0x5e, - 0xc5, 0xea, 0xa4, 0x77, 0xf7, 0xf9, 0xab, 0x62, 0xce, 0x30, 0x3f, 0xed, 0x5b, 0x91, 0x84, 0x24, - 0x6d, 0xc0, 0x92, 0x1f, 0x11, 0x50, 0x5a, 0x80, 0xd3, 0xcb, 0x5a, 0x7c, 0x99, 0x65, 0xb5, 0xfe, - 0x34, 0x07, 0xe5, 0xed, 0x60, 0x24, 0xf4, 0x72, 0x21, 0xcf, 0xe1, 0x31, 0xd1, 0xe9, 0x79, 0x73, - 0xe2, 0x73, 0xa7, 0xff, 0xfc, 0xb0, 0xfc, 0x4c, 0x79, 0xa3, 0x91, 0x96, 0x37, 0xbe, 0x0f, 0x37, - 0xd1, 0x1b, 0x11, 0x06, 0xa3, 0x20, 0x14, 0x47, 0xd5, 0x1d, 0x90, 0xdc, 0x11, 0xf8, 0xf1, 0x99, - 0xe2, 0x9d, 0x37, 0x4e, 0x38, 0x3f, 0x34, 0x30, 0xf6, 0x34, 0x02, 0xe6, 0x9a, 0x0c, 0xe2, 0x73, - 0x87, 0x54, 0x45, 0x29, 0x18, 0x11, 0x47, 0x9d, 0x17, 0x05, 0x9b, 0x08, 0x47, 0xd1, 0xc8, 0xfa, - 0x08, 0xaa, 0xda, 0xea, 0xc0, 0xde, 0x86, 0xea, 0x59, 0x30, 0x92, 0xa6, 0x89, 0x5c, 0x2a, 0x75, - 0x41, 0xce, 0xda, 0xae, 0x9c, 0xd1, 0x1f, 0x91, 0xf5, 0xf3, 0x32, 0x94, 0x77, 0xfc, 0xf3, 0xc0, - 0xeb, 0x61, 0xb4, 0xcf, 0x90, 0x0f, 0x03, 0x95, 0xa7, 0x28, 0xfe, 0x46, 0x8f, 0x7e, 0xf2, 0x74, - 0x40, 0x41, 0x7a, 0xf4, 0xf5, 0xa3, 0x01, 0xd7, 0x61, 0x2e, 0x34, 0x73, 0xff, 0x4b, 0x21, 0xc6, - 0x1f, 0x6a, 0xa5, 0xad, 0x64, 0xe4, 0x79, 0x8a, 0xb6, 0x28, 0x27, 0x1d, 0x97, 0x8c, 0x72, 0x4f, - 0xaa, 0x08, 0xc1, 0x05, 0x7b, 0x05, 0xca, 0x32, 0x53, 0x80, 0xe2, 0xae, 0x29, 0x60, 0x50, 0x82, - 0x90, 0x1a, 0x42, 0x4e, 0xde, 0x24, 0x2d, 0x51, 0x09, 0x3d, 0x5d, 0x02, 0x37, 0x04, 0xad, 0xdd, - 0x86, 0x1a, 0xe1, 0x13, 0x4a, 0x45, 0xc6, 0xe7, 0x20, 0x08, 0x11, 0x32, 0x9e, 0xd0, 0xa8, 0x66, - 0x3e, 0xa1, 0x81, 0xe1, 0x5c, 0x9a, 0xcb, 0xd2, 0x14, 0x81, 0x1e, 0x4e, 0x30, 0xe0, 0xea, 0xfd, - 0x18, 0xa9, 0xdc, 0x53, 0x1a, 0x95, 0x52, 0xee, 0x5f, 0x87, 0xc6, 0x89, 0x3b, 0x18, 0x1c, 0xbb, - 0xbd, 0x67, 0xa4, 0x93, 0xd6, 0xc9, 0x0c, 0xa7, 0x80, 0xa8, 0x94, 0xde, 0x86, 0x9a, 0xb1, 0xcb, - 0x18, 0x7c, 0x53, 0xb4, 0x21, 0xd9, 0xdf, 0x49, 0x53, 0x53, 0xf3, 0x25, 0x4c, 0x4d, 0x46, 0x10, - 0xd2, 0x7c, 0x3a, 0x08, 0xe9, 0x26, 0x72, 0x53, 0x19, 0xa8, 0xd2, 0xa2, 0x2c, 0x7d, 0xb7, 0xdf, - 0xc7, 0x40, 0x15, 0x7a, 0x12, 0x0b, 0x17, 0x8f, 0xca, 0x17, 0x48, 0xa8, 0x25, 0x18, 0xa1, 0xdc, - 0x22, 0x7b, 0xe9, 0xc8, 0xf5, 0xfa, 0x18, 0xf4, 0x49, 0x6a, 0x6c, 0xd9, 0x1d, 0xc6, 0x87, 0xae, - 0xd7, 0x67, 0x77, 0xa0, 0xae, 0x8a, 0xf1, 0x76, 0x5c, 0xa4, 0xf5, 0x97, 0xc5, 0xe2, 0x4e, 0xb4, - 0xa0, 0xa1, 0x31, 0x86, 0x49, 0x2e, 0x54, 0x4d, 0xa2, 0x20, 0x1d, 0xbc, 0x87, 0xce, 0xff, 0x98, - 0x63, 0xc6, 0x53, 0xf3, 0xf1, 0x4d, 0x39, 0x57, 0x49, 0xa5, 0xea, 0x7f, 0x8c, 0x74, 0xb0, 0x09, - 0x53, 0x08, 0x62, 0xe4, 0xa2, 0x59, 0x4e, 0x09, 0x62, 0x12, 0x15, 0x5d, 0x34, 0x84, 0xc0, 0x3e, - 0x32, 0x14, 0xa9, 0x36, 0x22, 0xbf, 0x32, 0xd1, 0xfe, 0x0c, 0x15, 0x4a, 0x50, 0xaf, 0x17, 0x89, - 0x5b, 0x26, 0xe2, 0x7e, 0x1f, 0x13, 0xa0, 0x2a, 0x76, 0xd5, 0x8b, 0x9e, 0x10, 0xe0, 0x97, 0xab, - 0x61, 0xad, 0x42, 0xdd, 0x9c, 0x26, 0xab, 0x40, 0xf1, 0xe0, 0x70, 0x73, 0xbf, 0x75, 0x8d, 0xd5, - 0xa0, 0xdc, 0xdd, 0x3c, 0x3a, 0xda, 0xdd, 0xdc, 0x68, 0xe5, 0x58, 0x1d, 0x2a, 0x3a, 0x8d, 0x23, - 0x2f, 0xbe, 0x56, 0xd7, 0xd7, 0x37, 0x0f, 0x8f, 0x36, 0x37, 0x5a, 0x85, 0x1f, 0x14, 0x2b, 0xf9, - 0x56, 0xc1, 0xfa, 0xf3, 0x02, 0xd4, 0x8c, 0x55, 0x78, 0x3e, 0x33, 0xbe, 0x05, 0x80, 0x2a, 0x4d, - 0x12, 0xc7, 0x54, 0xb4, 0xab, 0x02, 0x42, 0x9b, 0x6f, 0x1a, 0xcb, 0x0b, 0xf4, 0xfc, 0x83, 0x32, - 0x96, 0xbf, 0x0e, 0x0d, 0x7a, 0x49, 0xc1, 0x74, 0xd7, 0x95, 0xec, 0x3a, 0x01, 0x25, 0xab, 0xc6, - 0x3c, 0x30, 0x44, 0xc2, 0x0c, 0x01, 0x99, 0x57, 0x4d, 0x20, 0xcc, 0x11, 0xc0, 0x04, 0x8f, 0x28, - 0x18, 0x9c, 0x73, 0xc2, 0x20, 0x89, 0xb0, 0x26, 0x61, 0x47, 0x32, 0x11, 0x4d, 0xf2, 0x43, 0x23, - 0x11, 0xa9, 0x64, 0xd7, 0x09, 0x28, 0x3b, 0x7a, 0x57, 0x11, 0x50, 0x05, 0x09, 0x68, 0x65, 0x9a, - 0x1a, 0x52, 0xc4, 0xb3, 0x3b, 0x65, 0xcf, 0xaa, 0x22, 0x61, 0x7c, 0x67, 0xba, 0xde, 0x8b, 0xed, - 0x5a, 0xec, 0x6d, 0x60, 0xc3, 0xd1, 0xc8, 0xc9, 0xb0, 0x34, 0x15, 0xed, 0xf9, 0xe1, 0x68, 0x74, - 0x64, 0x18, 0x62, 0x7e, 0x09, 0x46, 0xb0, 0x2f, 0x81, 0xad, 0x8a, 0x03, 0x8c, 0x43, 0xd4, 0x26, - 0xd4, 0x84, 0x2d, 0xe7, 0x4c, 0xb6, 0x9c, 0xc1, 0xfd, 0xf2, 0x99, 0xdc, 0xef, 0x79, 0x7c, 0xc2, - 0xda, 0x82, 0xda, 0xa1, 0xf1, 0x4e, 0xcb, 0x1d, 0x71, 0x43, 0xa8, 0x17, 0x5a, 0xe8, 0xee, 0x20, - 0xe3, 0x56, 0x28, 0x1f, 0x66, 0x31, 0x46, 0x93, 0x37, 0x46, 0x63, 0xfd, 0xeb, 0x1c, 0xe5, 0xc0, - 0xeb, 0xc1, 0x27, 0x4f, 0xc3, 0x28, 0x3f, 0x50, 0x92, 0x2f, 0x58, 0x53, 0xfe, 0x1f, 0x99, 0xea, - 0x87, 0x43, 0x73, 0x82, 0x93, 0x93, 0x88, 0xab, 0xcc, 0x97, 0x1a, 0xc2, 0x0e, 0x10, 0xa4, 0x84, - 0x6f, 0x21, 0xe1, 0x7b, 0xd4, 0x7e, 0x24, 0x33, 0x60, 0x84, 0xf0, 0xbd, 0xe7, 0x5e, 0xca, 0x5e, - 0x23, 0x21, 0x82, 0x48, 0x43, 0xb5, 0xca, 0xf7, 0xd1, 0xdf, 0xd6, 0xbf, 0x90, 0x29, 0x8d, 0x93, - 0xeb, 0x7b, 0x1f, 0x2a, 0xba, 0xd5, 0xf4, 0x0d, 0xab, 0x30, 0x75, 0xb9, 0xb8, 0xc7, 0x51, 0x2b, - 0x4f, 0x8d, 0x98, 0x0e, 0x17, 0x3a, 0x1b, 0x76, 0x8c, 0x51, 0xbf, 0x03, 0xec, 0xc4, 0x0b, 0x27, - 0x91, 0xe9, 0xb0, 0xb5, 0xb0, 0xc4, 0xc0, 0xb6, 0x9e, 0xc2, 0xa2, 0xe2, 0x12, 0x86, 0x46, 0x90, - 0xde, 0xbc, 0xdc, 0x0b, 0x98, 0x7c, 0x7e, 0x8a, 0xc9, 0x5b, 0x3f, 0x2b, 0x42, 0x59, 0xbd, 0x79, - 0x94, 0xf5, 0x4e, 0x4f, 0x35, 0xfd, 0x4e, 0x4f, 0x3b, 0xf5, 0xa6, 0x03, 0x6e, 0xbd, 0xbc, 0xef, - 0xef, 0x4e, 0x5e, 0xd9, 0x86, 0xd1, 0x3c, 0x75, 0x6d, 0x2f, 0x43, 0x71, 0xe4, 0xc6, 0x67, 0x68, - 0x20, 0x23, 0xe2, 0xc1, 0x6f, 0x65, 0x4c, 0x2f, 0xa5, 0x8d, 0xe9, 0x59, 0x6f, 0x1a, 0x91, 0x48, - 0x3a, 0xf5, 0xa6, 0xd1, 0x4d, 0x20, 0xf9, 0xc2, 0x88, 0x87, 0xa9, 0x20, 0x40, 0xdc, 0x45, 0x69, - 0x71, 0xa4, 0x32, 0x29, 0x8e, 0xbc, 0xb4, 0xa8, 0xf0, 0x3e, 0xcc, 0x51, 0x3e, 0xb0, 0xcc, 0x6b, - 0x52, 0x17, 0x8a, 0x5c, 0x43, 0xf5, 0x3f, 0x05, 0xc1, 0xda, 0x12, 0xd7, 0x7c, 0x20, 0xa4, 0x96, - 0x7a, 0x20, 0xc4, 0x34, 0xf2, 0xd7, 0xd3, 0x46, 0xfe, 0x7b, 0xd0, 0xd2, 0x0b, 0x8a, 0x26, 0x33, - 0x3f, 0x92, 0x19, 0x1d, 0x4d, 0x05, 0x17, 0x5c, 0x72, 0x3f, 0x4a, 0x2e, 0xc4, 0x66, 0xea, 0x42, - 0x14, 0x3c, 0x6c, 0x35, 0x8e, 0xf9, 0x70, 0x14, 0xcb, 0x0b, 0x11, 0x63, 0xbe, 0xcd, 0x01, 0xa6, - 0x33, 0xfe, 0x1a, 0x50, 0xdd, 0xd9, 0x77, 0xb6, 0x76, 0x77, 0x3e, 0xdd, 0x3e, 0x6a, 0xe5, 0xc4, - 0x67, 0xf7, 0xe9, 0xfa, 0xfa, 0xe6, 0xe6, 0x06, 0xde, 0x38, 0x00, 0x73, 0x5b, 0xab, 0x3b, 0xe2, - 0xf6, 0x29, 0x58, 0x7f, 0x9d, 0x83, 0x9a, 0xd1, 0x3c, 0xfb, 0x40, 0xaf, 0x0a, 0xbd, 0x21, 0x71, - 0x6b, 0x7a, 0x08, 0x0f, 0x14, 0x2b, 0x36, 0x96, 0x45, 0xbf, 0xe0, 0x94, 0x9f, 0xf9, 0x82, 0x13, - 0x7b, 0x13, 0xe6, 0x5d, 0x6a, 0x41, 0xaf, 0x82, 0x34, 0x07, 0x4b, 0xb0, 0x5c, 0x04, 0x8c, 0x02, - 0x4b, 0xee, 0x13, 0x81, 0x57, 0x54, 0x81, 0x57, 0xfa, 0x4a, 0xd9, 0x8f, 0xac, 0xef, 0x01, 0x24, - 0x23, 0x49, 0x4f, 0xf9, 0x5a, 0x7a, 0xca, 0x39, 0x63, 0xca, 0x79, 0x6b, 0x83, 0x98, 0x83, 0x5c, - 0x3e, 0xed, 0x7f, 0x7e, 0x17, 0x94, 0x9d, 0xc9, 0xc1, 0xe8, 0xca, 0xd1, 0x80, 0xc7, 0x2a, 0xe3, - 0x71, 0x41, 0x96, 0xec, 0xe8, 0x02, 0x95, 0x80, 0x9c, 0xb4, 0x92, 0xf0, 0x18, 0x49, 0x68, 0x93, - 0x3c, 0x46, 0xa2, 0xda, 0xba, 0xdc, 0xea, 0x40, 0x7b, 0x83, 0x8b, 0xd6, 0x56, 0x07, 0x83, 0x89, - 0xe1, 0x58, 0x37, 0xe1, 0x46, 0x46, 0x99, 0x34, 0x2d, 0x7c, 0x06, 0xd7, 0x57, 0x29, 0xb9, 0xf1, - 0x97, 0x95, 0x61, 0x61, 0xb5, 0x61, 0x79, 0xb2, 0x49, 0xd9, 0xd9, 0x16, 0x2c, 0x6c, 0xf0, 0xe3, - 0xf1, 0xe9, 0x2e, 0x3f, 0x4f, 0x3a, 0x62, 0x50, 0x8c, 0xce, 0x82, 0x0b, 0xb9, 0x3e, 0xf8, 0xb7, - 0x38, 0x99, 0x03, 0x81, 0xe3, 0x44, 0x23, 0xde, 0x53, 0x76, 0x4e, 0x84, 0x74, 0x47, 0xbc, 0x67, - 0x7d, 0x00, 0xcc, 0x6c, 0x47, 0xae, 0x97, 0x90, 0xfd, 0xc7, 0xc7, 0x4e, 0x74, 0x15, 0xc5, 0x7c, - 0xa8, 0x1e, 0x1e, 0x81, 0x68, 0x7c, 0xdc, 0x25, 0x88, 0x75, 0x17, 0xea, 0x87, 0xee, 0x95, 0xcd, - 0xbf, 0x94, 0xb9, 0x03, 0x2b, 0x50, 0x1e, 0xb9, 0x57, 0xe2, 0x70, 0x6b, 0x97, 0x07, 0x16, 0x5b, - 0x7f, 0x54, 0x84, 0x39, 0xc2, 0x64, 0x77, 0xe8, 0x6d, 0x40, 0xcf, 0xc7, 0xc3, 0xa5, 0xd8, 0x9f, - 0x01, 0x9a, 0xe2, 0x90, 0xf9, 0x69, 0x0e, 0x29, 0xcd, 0x62, 0xea, 0x4d, 0x04, 0x65, 0x9c, 0xf6, - 0xc7, 0x43, 0xf5, 0x10, 0x02, 0x7b, 0x05, 0xaa, 0x49, 0x92, 0x56, 0x31, 0x79, 0xfb, 0x91, 0x52, - 0xb3, 0xd2, 0xee, 0xc3, 0x44, 0xc3, 0xa0, 0xd1, 0x29, 0xc6, 0x2f, 0x99, 0xa0, 0x09, 0xca, 0x54, - 0x63, 0xca, 0x2a, 0x2b, 0x25, 0xad, 0xc6, 0x4c, 0xa9, 0x2b, 0x95, 0x17, 0xab, 0x2b, 0x64, 0x2f, - 0x7b, 0x8e, 0xba, 0x02, 0x2f, 0xa1, 0xae, 0xbc, 0x84, 0xeb, 0xee, 0x06, 0x54, 0xf0, 0x36, 0x37, - 0x78, 0xa2, 0xb8, 0xc5, 0x05, 0x4f, 0xfc, 0xd0, 0x10, 0xe8, 0x29, 0x6e, 0xe0, 0x66, 0x72, 0x4c, - 0x6c, 0xfe, 0xe5, 0xaf, 0xc6, 0x25, 0xf2, 0x05, 0x94, 0x25, 0x54, 0x10, 0xb4, 0xef, 0x0e, 0xd5, - 0xb3, 0x32, 0xf8, 0xb7, 0x58, 0x36, 0x7c, 0x0b, 0xe3, 0xcb, 0xb1, 0x17, 0xf2, 0xbe, 0x7a, 0xbc, - 0xc0, 0xc3, 0x33, 0x2a, 0x20, 0x62, 0x82, 0x42, 0xb9, 0xf0, 0x83, 0x0b, 0x5f, 0xa6, 0x2e, 0x97, - 0xbd, 0xe8, 0x89, 0xf8, 0xb4, 0x18, 0xb4, 0xf0, 0x61, 0xa9, 0x51, 0x10, 0xaa, 0x2b, 0xc7, 0xfa, - 0x59, 0x0e, 0x5a, 0xf2, 0x74, 0xe9, 0x32, 0x53, 0xb6, 0x2f, 0xcd, 0x72, 0x73, 0x3f, 0xff, 0x29, - 0x02, 0x0b, 0x1a, 0x68, 0xd2, 0xd0, 0xf7, 0x0f, 0x99, 0x64, 0x6a, 0x02, 0xb8, 0x25, 0xef, 0xa0, - 0x57, 0xa1, 0xa6, 0x82, 0x2c, 0x87, 0xde, 0x40, 0x3d, 0xf3, 0x4a, 0x51, 0x96, 0x7b, 0xde, 0x40, - 0x5d, 0x5f, 0xa1, 0x2b, 0xb3, 0xa4, 0x72, 0x78, 0x7d, 0xd9, 0x6e, 0xcc, 0xad, 0xff, 0x92, 0x83, - 0x05, 0x63, 0x2a, 0xf2, 0xdc, 0x7e, 0x0c, 0x75, 0xfd, 0xa2, 0x1b, 0xd7, 0xf2, 0xd4, 0x4a, 0x9a, - 0xd1, 0x24, 0xd5, 0x6a, 0x3d, 0x0d, 0x89, 0xc4, 0x60, 0xfa, 0xee, 0x15, 0x8e, 0x37, 0x1a, 0x0f, - 0x95, 0xca, 0xd2, 0x77, 0xaf, 0xb6, 0x38, 0xef, 0x8e, 0x87, 0x42, 0x21, 0xbd, 0xe0, 0xfc, 0x99, - 0x46, 0x20, 0x49, 0x0a, 0x04, 0x4c, 0x62, 0x58, 0xd0, 0x18, 0x06, 0x7e, 0x7c, 0xa6, 0x51, 0xa4, - 0x2c, 0x89, 0x40, 0xc2, 0xb1, 0xfe, 0x67, 0x1e, 0x16, 0xc9, 0x70, 0x26, 0x0d, 0x96, 0x92, 0x75, - 0xb5, 0x61, 0x8e, 0x6c, 0x88, 0xc4, 0xbc, 0xb6, 0xaf, 0xd9, 0xf2, 0x9b, 0xbd, 0xff, 0x92, 0xc6, - 0x3e, 0x95, 0x88, 0x35, 0x63, 0xf9, 0x0b, 0xd3, 0xcb, 0x3f, 0x7b, 0x79, 0xb3, 0xfc, 0x68, 0xa5, - 0x2c, 0x3f, 0xda, 0xcb, 0x78, 0xaf, 0xa6, 0xb2, 0x95, 0xca, 0x12, 0xc7, 0xc8, 0x56, 0xfa, 0x00, - 0x56, 0x52, 0x38, 0xc8, 0xad, 0xbd, 0x13, 0x8f, 0xab, 0xcc, 0xf0, 0x25, 0x03, 0xbb, 0xab, 0xca, - 0xd6, 0xca, 0x50, 0x8a, 0x7a, 0xc1, 0x88, 0x5b, 0xcb, 0xb0, 0x94, 0x5e, 0x55, 0x79, 0x4d, 0xfc, - 0x41, 0x0e, 0xda, 0x32, 0xea, 0xc1, 0xf3, 0x4f, 0xb7, 0xbd, 0x28, 0x0e, 0x42, 0xfd, 0xf2, 0xd9, - 0x2d, 0x80, 0x28, 0x76, 0x43, 0xa9, 0x43, 0x92, 0x74, 0x5b, 0x45, 0x08, 0xea, 0x87, 0x37, 0xa0, - 0xc2, 0xfd, 0x3e, 0x15, 0x12, 0x35, 0x94, 0xb9, 0xdf, 0x57, 0xda, 0xe5, 0x94, 0x54, 0xdd, 0x48, - 0x2b, 0x0d, 0x32, 0x6d, 0x52, 0xac, 0x0e, 0x3f, 0xc7, 0x8b, 0xb7, 0xa8, 0xd3, 0x26, 0xf7, 0xdc, - 0x4b, 0x8c, 0x21, 0x8c, 0xac, 0x7f, 0x9a, 0x87, 0xf9, 0x64, 0x7c, 0x94, 0x73, 0x9d, 0xe2, 0xdf, - 0x72, 0x54, 0x09, 0xff, 0xbe, 0x23, 0xc9, 0xc1, 0x13, 0x52, 0xb9, 0x61, 0x4e, 0xac, 0xd0, 0xe1, - 0xdc, 0xf1, 0x99, 0x05, 0x35, 0x85, 0x11, 0x8c, 0x63, 0xe3, 0x01, 0xa2, 0x2a, 0xa1, 0x1c, 0x8c, - 0x63, 0xa1, 0x46, 0x09, 0x7d, 0xd2, 0xf3, 0xa5, 0x22, 0x53, 0x72, 0x87, 0xf1, 0x0e, 0xbe, 0x6b, - 0x2c, 0xc0, 0xa2, 0x1a, 0x6d, 0xa4, 0xc0, 0x12, 0xf8, 0x2d, 0x92, 0x9e, 0x69, 0xe7, 0x50, 0x72, - 0x36, 0x45, 0x4b, 0x7a, 0xe2, 0x51, 0x8b, 0x96, 0xaf, 0x42, 0x8d, 0x1a, 0x4f, 0x92, 0xd3, 0x8a, - 0x76, 0x15, 0x7b, 0xc0, 0x72, 0x69, 0xda, 0x09, 0xc6, 0x29, 0x85, 0x16, 0xa8, 0x2b, 0x0c, 0x2a, - 0xf8, 0x47, 0x39, 0xb8, 0x91, 0xb1, 0x6d, 0xf2, 0x94, 0xaf, 0xc3, 0xc2, 0x89, 0x2e, 0x54, 0xab, - 0x4b, 0x47, 0x7d, 0x59, 0xb1, 0xd5, 0xf4, 0x9a, 0xda, 0xad, 0x93, 0x34, 0x20, 0x51, 0xa5, 0x68, - 0x07, 0x53, 0xf9, 0x87, 0xa8, 0x4a, 0xd1, 0x36, 0x92, 0x16, 0x73, 0x08, 0x9d, 0xcd, 0x4b, 0xc1, - 0x31, 0xd6, 0xcd, 0x87, 0xb9, 0x15, 0x19, 0xa5, 0xcd, 0xc6, 0xb9, 0x97, 0x32, 0x1b, 0xf7, 0x29, - 0xcd, 0x4a, 0xb7, 0xf5, 0x6d, 0x1a, 0xc1, 0x0b, 0x54, 0xd4, 0xa1, 0x87, 0xc5, 0x55, 0x0e, 0x64, - 0x4f, 0x3f, 0x28, 0x6e, 0x45, 0x30, 0xbf, 0x37, 0x1e, 0xc4, 0x5e, 0xf2, 0xc6, 0x38, 0x7b, 0x5f, - 0xd6, 0xc1, 0x7e, 0xd4, 0xaa, 0x65, 0x76, 0x04, 0xba, 0x23, 0x5c, 0xac, 0xa1, 0x68, 0xc8, 0x99, - 0xee, 0x6f, 0x7e, 0x98, 0xee, 0xc1, 0xba, 0x01, 0x2b, 0xc9, 0x17, 0x2d, 0x9b, 0xba, 0x6a, 0xfe, - 0x55, 0x8e, 0x02, 0x96, 0xd3, 0xef, 0x9d, 0xb3, 0x4d, 0x58, 0x8c, 0x3c, 0xff, 0x74, 0xc0, 0xcd, - 0xe6, 0x23, 0xb9, 0x08, 0xd7, 0xd3, 0x63, 0x93, 0x6f, 0xa2, 0xdb, 0x0b, 0x54, 0x23, 0x69, 0x2d, - 0x62, 0x6b, 0xb3, 0x06, 0x99, 0x90, 0xc5, 0xc4, 0x6a, 0x4c, 0x0f, 0x7e, 0x07, 0x9a, 0xe9, 0x8e, - 0xd8, 0x87, 0x32, 0xc5, 0x30, 0x19, 0x55, 0x61, 0x22, 0x5b, 0x2c, 0x21, 0x88, 0x5a, 0xb2, 0xf6, - 0x91, 0xf5, 0x8f, 0x73, 0xd0, 0xb6, 0xb9, 0xa0, 0x5c, 0x63, 0x94, 0x8a, 0x66, 0x3e, 0x9e, 0x6a, - 0x75, 0xf6, 0x5c, 0x55, 0xe6, 0xa2, 0x1a, 0xd1, 0x3b, 0x33, 0x37, 0x63, 0xfb, 0xda, 0xd4, 0x8c, - 0xd6, 0x2a, 0x30, 0x47, 0x28, 0xd6, 0x0a, 0x5c, 0x97, 0xe3, 0x51, 0x63, 0x49, 0x7c, 0x82, 0xa9, - 0x1e, 0x53, 0x3e, 0xc1, 0x0e, 0xb4, 0xe9, 0x01, 0x3b, 0x73, 0x12, 0xb2, 0xe2, 0x06, 0xb0, 0x3d, - 0xb7, 0xe7, 0x86, 0x41, 0xe0, 0x1f, 0xf2, 0x50, 0x86, 0x7f, 0xa2, 0x84, 0x89, 0x2e, 0x33, 0x25, - 0x0a, 0xd3, 0x97, 0x7a, 0x76, 0x2d, 0xf0, 0x55, 0xb4, 0x0b, 0x7d, 0x59, 0x36, 0x2c, 0xae, 0xb9, - 0xcf, 0xb8, 0x6a, 0x49, 0x2d, 0xd1, 0x27, 0x50, 0x1b, 0xe9, 0x46, 0xd5, 0xba, 0xab, 0x3c, 0xe4, - 0xe9, 0x6e, 0x6d, 0x13, 0xdb, 0x7a, 0x0c, 0x4b, 0xe9, 0x36, 0x25, 0xeb, 0xe8, 0x40, 0x65, 0x28, - 0x61, 0x72, 0x74, 0xfa, 0xfb, 0xfe, 0xd7, 0x50, 0x33, 0x1e, 0x25, 0x64, 0x2b, 0xb0, 0xf8, 0xf9, - 0xce, 0xd1, 0xfe, 0x66, 0xb7, 0xeb, 0x1c, 0x3e, 0x5d, 0x7b, 0xb2, 0xf9, 0x85, 0xb3, 0xbd, 0xda, - 0xdd, 0x6e, 0x5d, 0x63, 0xcb, 0xc0, 0xf6, 0x37, 0xbb, 0x47, 0x9b, 0x1b, 0x29, 0x78, 0x8e, 0xbd, - 0x0a, 0x9d, 0xa7, 0xfb, 0x4f, 0xbb, 0x9b, 0x1b, 0x4e, 0x56, 0xbd, 0x3c, 0xbb, 0x05, 0x37, 0x64, - 0x79, 0x46, 0xf5, 0xc2, 0xfd, 0x4f, 0xa0, 0x35, 0x69, 0x55, 0x4c, 0x99, 0x61, 0x9f, 0x67, 0xaf, - 0xbd, 0xff, 0xef, 0x0a, 0x00, 0x49, 0xd8, 0x27, 0x6b, 0xc3, 0xd2, 0xc6, 0xea, 0xd1, 0xea, 0xee, - 0x81, 0x18, 0x84, 0x7d, 0x70, 0xb4, 0xb9, 0x7e, 0xe4, 0xd8, 0x9b, 0x9f, 0xb5, 0xae, 0x65, 0x96, - 0x1c, 0x1c, 0x0a, 0x7d, 0x7c, 0x05, 0x16, 0x77, 0xf6, 0x77, 0x8e, 0x76, 0x56, 0x77, 0x1d, 0xfb, - 0xe0, 0xe9, 0xce, 0xfe, 0xa7, 0xf4, 0xec, 0x48, 0x81, 0xdd, 0x86, 0x9b, 0x4f, 0x0f, 0xb7, 0xec, - 0x83, 0xfd, 0x23, 0xa7, 0xbb, 0xfd, 0xf4, 0x68, 0x03, 0x1f, 0x2d, 0x59, 0xb7, 0x77, 0x0e, 0xa9, - 0xcd, 0xe2, 0xf3, 0x10, 0x44, 0xd3, 0x25, 0xb1, 0x62, 0x9f, 0x1e, 0x74, 0xbb, 0x3b, 0x87, 0xce, - 0x67, 0x4f, 0x37, 0xed, 0x9d, 0xcd, 0x2e, 0x56, 0x9c, 0xcb, 0x80, 0x0b, 0xfc, 0x32, 0x5b, 0x80, - 0xc6, 0xd1, 0xee, 0x0f, 0x9d, 0x83, 0xfd, 0x9d, 0x83, 0x7d, 0x44, 0xad, 0xa4, 0x41, 0x02, 0xab, - 0xca, 0x3a, 0xb0, 0xbc, 0xf9, 0x9b, 0x47, 0x4e, 0x46, 0xcb, 0x30, 0xa3, 0x4c, 0xd4, 0xab, 0xb1, - 0x1b, 0x70, 0xbd, 0x7b, 0xb4, 0x7a, 0xb4, 0xb3, 0xee, 0xc8, 0x97, 0x8e, 0xc4, 0x26, 0x88, 0x6a, - 0xf5, 0xec, 0x22, 0x51, 0xab, 0xc1, 0x96, 0xa0, 0x75, 0xb8, 0xfa, 0xc5, 0xde, 0xe6, 0xfe, 0x91, - 0xb3, 0xba, 0xb1, 0x61, 0x63, 0x85, 0xe6, 0x14, 0x54, 0xe0, 0xce, 0x8b, 0x8d, 0xda, 0x3b, 0x3c, - 0x44, 0x94, 0x96, 0xfa, 0x10, 0x25, 0x0b, 0x8f, 0x7f, 0xb7, 0x00, 0x4d, 0x0a, 0xc1, 0xa7, 0x5f, - 0x74, 0xe0, 0x21, 0xdb, 0x83, 0xb2, 0xfc, 0x69, 0x10, 0x76, 0x5d, 0x3f, 0x3e, 0x61, 0xfe, 0x18, - 0x49, 0x67, 0x79, 0x12, 0x2c, 0x8f, 0xdf, 0xe2, 0xdf, 0xfe, 0xb3, 0xbf, 0xfc, 0x27, 0xf9, 0x06, - 0xab, 0x3d, 0x3c, 0x7f, 0xef, 0xe1, 0x29, 0xf7, 0x23, 0xd1, 0xc6, 0xdf, 0x00, 0x48, 0x7e, 0xf0, - 0x82, 0xb5, 0xb5, 0x29, 0x71, 0xe2, 0xd7, 0x40, 0x3a, 0x37, 0x32, 0x4a, 0x64, 0xbb, 0x37, 0xb0, - 0xdd, 0x45, 0xab, 0x29, 0xda, 0xf5, 0x7c, 0x2f, 0xa6, 0x1f, 0xbf, 0xf8, 0x38, 0x77, 0x9f, 0xf5, - 0xa1, 0x6e, 0xfe, 0x14, 0x05, 0x53, 0xae, 0xf8, 0x8c, 0x1f, 0xd3, 0xe8, 0xdc, 0xcc, 0x2c, 0x53, - 0x3c, 0x07, 0xfb, 0xb8, 0x6e, 0xb5, 0x44, 0x1f, 0x63, 0xc4, 0x48, 0x7a, 0x19, 0x10, 0x17, 0x4e, - 0x7e, 0x71, 0x82, 0xbd, 0x62, 0x70, 0xc6, 0xa9, 0xdf, 0xbb, 0xe8, 0xdc, 0x9a, 0x51, 0x2a, 0xfb, - 0xba, 0x85, 0x7d, 0xad, 0x58, 0x4c, 0xf4, 0xd5, 0x43, 0x1c, 0xf5, 0x7b, 0x17, 0x1f, 0xe7, 0xee, - 0x3f, 0xfe, 0x8b, 0x7b, 0x50, 0xd5, 0x21, 0x39, 0xec, 0xb7, 0xa1, 0x91, 0xca, 0x91, 0x60, 0x6a, - 0x1a, 0x59, 0x29, 0x15, 0x9d, 0x57, 0xb2, 0x0b, 0x65, 0xc7, 0xaf, 0x62, 0xc7, 0x6d, 0xb6, 0x2c, - 0x3a, 0x96, 0x39, 0x08, 0x0f, 0x31, 0x93, 0x88, 0x9e, 0xf2, 0x78, 0x66, 0xdc, 0x36, 0xd4, 0xd9, - 0x2b, 0x93, 0x37, 0x40, 0xaa, 0xb7, 0x5b, 0x33, 0x4a, 0x65, 0x77, 0xaf, 0x60, 0x77, 0xcb, 0x6c, - 0xc9, 0xec, 0x4e, 0x05, 0xd0, 0x30, 0x8e, 0xcf, 0xe7, 0x98, 0x3f, 0xc8, 0xc0, 0x6e, 0x25, 0x8f, - 0x9d, 0x64, 0xfc, 0x50, 0x83, 0x26, 0x91, 0xe9, 0x5f, 0x6b, 0xb0, 0xda, 0xd8, 0x15, 0x63, 0xb8, - 0x7d, 0xe6, 0xef, 0x31, 0xb0, 0x63, 0xa8, 0x19, 0x6f, 0x18, 0xb3, 0x1b, 0x33, 0xdf, 0x5b, 0xee, - 0x74, 0xb2, 0x8a, 0xb2, 0xa6, 0x62, 0xb6, 0xff, 0x50, 0xc8, 0x9e, 0x3f, 0x86, 0xaa, 0x7e, 0x19, - 0x97, 0xad, 0x18, 0x2f, 0x15, 0x9b, 0x2f, 0xf9, 0x76, 0xda, 0xd3, 0x05, 0x59, 0xc4, 0x67, 0xb6, - 0x2e, 0x88, 0xef, 0x73, 0xa8, 0x19, 0xaf, 0xdf, 0xea, 0x09, 0x4c, 0xbf, 0xb0, 0xab, 0x27, 0x90, - 0xf1, 0x58, 0xae, 0xb5, 0x80, 0x5d, 0xd4, 0x58, 0x15, 0xe9, 0x3b, 0xbe, 0x0c, 0x22, 0xb6, 0x0b, - 0xd7, 0xe5, 0xcd, 0x7a, 0xcc, 0xbf, 0xc9, 0x36, 0x64, 0xfc, 0x06, 0xc6, 0xa3, 0x1c, 0xfb, 0x04, - 0x2a, 0xea, 0x91, 0x63, 0xb6, 0x9c, 0xfd, 0x58, 0x73, 0x67, 0x65, 0x0a, 0x2e, 0xaf, 0xc1, 0x2f, - 0x00, 0x92, 0xa7, 0x76, 0x35, 0x93, 0x98, 0x7a, 0xba, 0x57, 0x53, 0xc0, 0xf4, 0xbb, 0xbc, 0xd6, - 0x32, 0x4e, 0xb0, 0xc5, 0x90, 0x49, 0xf8, 0xfc, 0x42, 0xbd, 0x23, 0xf6, 0x13, 0xa8, 0x19, 0xaf, - 0xed, 0xea, 0xe5, 0x9b, 0x7e, 0xa9, 0x57, 0x2f, 0x5f, 0xc6, 0xe3, 0xbc, 0x56, 0x07, 0x5b, 0x5f, - 0xb2, 0xe6, 0x45, 0xeb, 0x91, 0x77, 0xea, 0x0f, 0x09, 0x41, 0x6c, 0xd0, 0x19, 0x34, 0x52, 0x4f, - 0xea, 0xea, 0x13, 0x9a, 0xf5, 0x60, 0xaf, 0x3e, 0xa1, 0x99, 0xaf, 0xf0, 0x2a, 0x3a, 0xb3, 0x16, - 0x44, 0x3f, 0xe7, 0x88, 0x62, 0xf4, 0xf4, 0x23, 0xa8, 0x19, 0xcf, 0xe3, 0xea, 0xb9, 0x4c, 0xbf, - 0xc4, 0xab, 0xe7, 0x92, 0xf5, 0x9a, 0xee, 0x12, 0xf6, 0xd1, 0xb4, 0x90, 0x14, 0xf0, 0x95, 0x26, - 0xd1, 0xf6, 0x6f, 0x43, 0x33, 0xfd, 0x62, 0xae, 0x3e, 0xfb, 0x99, 0x4f, 0xef, 0xea, 0xb3, 0x3f, - 0xe3, 0x99, 0x5d, 0x49, 0xd2, 0xf7, 0x17, 0x75, 0x27, 0x0f, 0xbf, 0x92, 0xc1, 0xc5, 0x5f, 0xb3, - 0xcf, 0x04, 0x83, 0x93, 0x8f, 0x84, 0xb1, 0x15, 0x83, 0x6a, 0xcd, 0xa7, 0xc4, 0xf4, 0x79, 0x99, - 0x7a, 0x4f, 0x2c, 0x4d, 0xcc, 0xd8, 0x38, 0xfb, 0x14, 0x16, 0x35, 0x31, 0xeb, 0x57, 0xbf, 0x22, - 0x3d, 0x87, 0xcc, 0xb7, 0xc5, 0x3a, 0xad, 0xc9, 0xd2, 0x47, 0x39, 0xba, 0xfe, 0xf0, 0xad, 0x25, - 0xe3, 0xfa, 0x33, 0x1f, 0xfe, 0x32, 0xae, 0xbf, 0xd4, 0x93, 0x4c, 0x93, 0xd7, 0x5f, 0xec, 0x89, - 0x36, 0x7c, 0x98, 0x9f, 0x7c, 0x83, 0xeb, 0xd6, 0xac, 0x0c, 0x54, 0x6a, 0xfe, 0xd5, 0xe7, 0x27, - 0xa8, 0xa6, 0x59, 0x91, 0xe2, 0xa6, 0x0f, 0xa5, 0x0b, 0x91, 0xfd, 0x16, 0xd4, 0xcd, 0x27, 0x3f, - 0x99, 0xc9, 0x13, 0x26, 0x7b, 0xba, 0x99, 0x59, 0x96, 0xa6, 0x12, 0x56, 0x37, 0xbb, 0x61, 0x3f, - 0x84, 0x65, 0xbd, 0xcc, 0x66, 0xf6, 0x61, 0xc4, 0x6e, 0x67, 0xe4, 0x24, 0xa6, 0x16, 0xfb, 0xc6, - 0xcc, 0xa4, 0xc5, 0x47, 0x39, 0x41, 0x7d, 0xe9, 0xb7, 0x07, 0x93, 0x9b, 0x27, 0xeb, 0xc9, 0xc5, - 0xe4, 0xe6, 0xc9, 0x7c, 0xb0, 0x50, 0x51, 0x1f, 0x5b, 0x4c, 0xad, 0x11, 0x05, 0x57, 0xb1, 0x1f, - 0xc1, 0xbc, 0x91, 0x5a, 0xd9, 0xbd, 0xf2, 0x7b, 0xfa, 0x24, 0x4d, 0x3f, 0xec, 0xd3, 0xc9, 0xd2, - 0x45, 0xad, 0x15, 0x6c, 0x7f, 0xc1, 0x4a, 0x2d, 0x8e, 0x38, 0x45, 0xeb, 0x50, 0x33, 0xd3, 0x36, - 0x9f, 0xd3, 0xee, 0x8a, 0x51, 0x64, 0xbe, 0x21, 0xf3, 0x28, 0xc7, 0x76, 0xa1, 0x35, 0xf9, 0xe4, - 0x85, 0xe6, 0x29, 0x59, 0xcf, 0x74, 0x74, 0x26, 0x0a, 0x53, 0x0f, 0x65, 0xb0, 0x43, 0x0a, 0xcf, - 0xd5, 0x3f, 0x18, 0x11, 0x84, 0x93, 0xb7, 0x7a, 0xfa, 0x87, 0x24, 0x74, 0x6b, 0x59, 0x3f, 0x21, - 0x72, 0x2f, 0xf7, 0x28, 0xc7, 0x7e, 0x3f, 0x07, 0xf5, 0x54, 0x9a, 0x79, 0x2a, 0x00, 0x72, 0x62, - 0x9e, 0x6d, 0xb3, 0xcc, 0x9c, 0xa8, 0x65, 0xe3, 0x22, 0xee, 0xde, 0xff, 0x41, 0x6a, 0x93, 0xbe, - 0x4a, 0x99, 0x72, 0x1f, 0x4c, 0xfe, 0xa2, 0xc4, 0xd7, 0x93, 0x08, 0xe6, 0x7b, 0x4d, 0x5f, 0x3f, - 0xca, 0xb1, 0xff, 0x90, 0x83, 0x66, 0xda, 0x47, 0xa3, 0xa7, 0x9b, 0xe9, 0x0d, 0xd2, 0xa4, 0x34, - 0xc3, 0xb1, 0xf3, 0x23, 0x1c, 0xe5, 0xd1, 0x7d, 0x3b, 0x35, 0x4a, 0xf9, 0x6a, 0xe6, 0x2f, 0x36, - 0x5a, 0xf6, 0x31, 0xfd, 0x80, 0x93, 0x72, 0x48, 0xb3, 0xe9, 0x1f, 0xfc, 0xd1, 0xe4, 0x67, 0xfe, - 0x3c, 0x0e, 0x6e, 0xc2, 0x4f, 0xe8, 0x97, 0x13, 0x94, 0x7f, 0x53, 0x50, 0xf1, 0xcb, 0xd6, 0xb7, - 0xde, 0xc0, 0x39, 0xbd, 0x6a, 0xdd, 0x48, 0xcd, 0x69, 0x52, 0xf0, 0x58, 0xa5, 0xd1, 0xc9, 0x5f, - 0xb7, 0x49, 0x6e, 0xce, 0xa9, 0x5f, 0xbc, 0x99, 0x3d, 0xc8, 0x21, 0x0d, 0x52, 0xa2, 0xa7, 0x8e, - 0xda, 0x4b, 0x36, 0x63, 0xdd, 0xc7, 0xb1, 0xbe, 0x61, 0xdd, 0x9e, 0x39, 0xd6, 0x87, 0xe8, 0x6f, - 0x11, 0x23, 0x3e, 0x04, 0x48, 0x02, 0x46, 0xd8, 0x44, 0xd8, 0x82, 0x66, 0x40, 0xd3, 0x31, 0x25, - 0xe9, 0xf3, 0xac, 0xa2, 0x1b, 0x44, 0x8b, 0x3f, 0x26, 0x76, 0xaa, 0x03, 0x2a, 0x4c, 0xe9, 0x2b, - 0x1d, 0xdb, 0x91, 0x92, 0xbe, 0x26, 0xdb, 0x4f, 0x31, 0x53, 0x1d, 0x3d, 0xf1, 0x14, 0x1a, 0xbb, - 0x41, 0xf0, 0x6c, 0x3c, 0xd2, 0x41, 0x8a, 0x69, 0x27, 0xe8, 0xb6, 0x1b, 0x9d, 0x75, 0x26, 0x66, - 0x61, 0xdd, 0xc1, 0xa6, 0x3a, 0xac, 0x6d, 0x34, 0xf5, 0xf0, 0xab, 0x24, 0x4a, 0xe5, 0x6b, 0xe6, - 0xc2, 0x82, 0xe6, 0xd1, 0x49, 0x24, 0x48, 0xba, 0x99, 0x14, 0x67, 0x9e, 0xec, 0x22, 0xa5, 0x26, - 0xa8, 0xd1, 0x3e, 0x8c, 0x54, 0x9b, 0x8f, 0x72, 0xec, 0x10, 0xea, 0x1b, 0xbc, 0x87, 0xe9, 0x96, - 0xe8, 0x4a, 0x5c, 0x4c, 0xb9, 0xa5, 0xc8, 0x07, 0xd9, 0x69, 0xa4, 0x80, 0xe9, 0x7b, 0x6b, 0xe4, - 0x5e, 0x85, 0xfc, 0xcb, 0x87, 0x5f, 0x49, 0x27, 0xe5, 0xd7, 0xea, 0xde, 0x52, 0x4e, 0xdc, 0xd4, - 0xbd, 0x35, 0xe1, 0xf5, 0x4d, 0xdd, 0x5b, 0x53, 0x5e, 0xdf, 0xd4, 0x52, 0x2b, 0x27, 0x32, 0x1b, - 0xc0, 0xc2, 0x94, 0xa3, 0x58, 0x5f, 0x59, 0xb3, 0xdc, 0xcb, 0x9d, 0x3b, 0xb3, 0x11, 0xd2, 0xbd, - 0xdd, 0x4f, 0xf7, 0xd6, 0x85, 0x06, 0x3d, 0x21, 0x75, 0xcc, 0x29, 0xf1, 0x62, 0xe2, 0xd5, 0x02, - 0x33, 0xab, 0x63, 0xf2, 0x82, 0xc1, 0xb2, 0xb4, 0x84, 0x83, 0x19, 0x0f, 0xec, 0xc7, 0x50, 0xfb, - 0x94, 0xc7, 0x2a, 0xd3, 0x42, 0xcb, 0xd8, 0x13, 0xa9, 0x17, 0x9d, 0x8c, 0x44, 0x8d, 0x34, 0xcd, - 0x60, 0x6b, 0x0f, 0x79, 0xff, 0x94, 0x13, 0x73, 0x72, 0xbc, 0xfe, 0xd7, 0xec, 0x37, 0xb1, 0x71, - 0x9d, 0xe0, 0xb6, 0x6c, 0x84, 0xd2, 0x9b, 0x8d, 0xcf, 0x4f, 0xc0, 0xb3, 0x5a, 0xf6, 0x83, 0x3e, - 0x37, 0x64, 0x3d, 0x1f, 0x6a, 0x46, 0x22, 0xac, 0x3e, 0x40, 0xd3, 0x89, 0xcf, 0xfa, 0x00, 0x65, - 0xe4, 0xcd, 0x5a, 0xf7, 0xb0, 0x1f, 0x8b, 0xdd, 0x49, 0xfa, 0xa1, 0x5c, 0xd9, 0xa4, 0xa7, 0x87, - 0x5f, 0xb9, 0xc3, 0xf8, 0x6b, 0xf6, 0x39, 0x3e, 0xd4, 0x6a, 0x66, 0x92, 0x24, 0x4a, 0xc3, 0x64, - 0xd2, 0x89, 0x5e, 0x2c, 0xa3, 0x28, 0xad, 0x48, 0x50, 0x57, 0x28, 0xc9, 0x7d, 0x00, 0xd0, 0x8d, - 0x83, 0xd1, 0x86, 0xcb, 0x87, 0x81, 0x9f, 0xf0, 0xda, 0x24, 0xb7, 0x21, 0xe1, 0x5f, 0x46, 0x82, - 0x03, 0xfb, 0xdc, 0xd0, 0xb2, 0x52, 0xc9, 0x38, 0x8a, 0xb8, 0x66, 0xa6, 0x3f, 0xe8, 0x05, 0xc9, - 0x48, 0x81, 0x78, 0x94, 0x63, 0xab, 0x00, 0x49, 0xa4, 0x80, 0xd6, 0x99, 0xa6, 0x82, 0x10, 0x34, - 0xdb, 0xcb, 0x08, 0x2b, 0x38, 0x84, 0x6a, 0xe2, 0x62, 0x5d, 0x49, 0xf2, 0xfa, 0x53, 0x0e, 0x59, - 0x7d, 0x83, 0x4f, 0xb9, 0x37, 0xad, 0x16, 0x2e, 0x15, 0xb0, 0x8a, 0x58, 0xaa, 0x13, 0xce, 0x23, - 0xe6, 0xc1, 0x22, 0x0d, 0x50, 0x8b, 0x4b, 0x18, 0x93, 0xaf, 0xdf, 0xe3, 0x9d, 0xf6, 0x34, 0xea, - 0xd3, 0x9c, 0xe9, 0x2f, 0x4b, 0x99, 0x7e, 0x04, 0xb5, 0x52, 0x3e, 0x80, 0x60, 0xcd, 0x43, 0x58, - 0x98, 0x72, 0xc9, 0xe8, 0x23, 0x3d, 0xcb, 0xc7, 0xa6, 0x8f, 0xf4, 0x4c, 0x6f, 0x8e, 0x75, 0x1d, - 0xbb, 0x9c, 0xb7, 0x00, 0x55, 0xbd, 0x0b, 0x2f, 0xee, 0x9d, 0x89, 0xee, 0xfe, 0x6d, 0x0e, 0x16, - 0x33, 0x9c, 0x2e, 0xec, 0x35, 0x65, 0x35, 0x98, 0xe9, 0x90, 0xe9, 0x64, 0x1a, 0xe7, 0xad, 0x2e, - 0xf6, 0xb3, 0xc7, 0x9e, 0xa4, 0x2e, 0x36, 0xb2, 0x8d, 0xcb, 0x93, 0xf9, 0x5c, 0xa1, 0x22, 0x53, - 0xa2, 0xf8, 0x12, 0x56, 0x68, 0x20, 0xab, 0x83, 0xc1, 0x84, 0xe3, 0xe0, 0xd5, 0xa9, 0x1f, 0x78, - 0x4d, 0x39, 0x43, 0x3a, 0xb3, 0x7f, 0x00, 0x76, 0x86, 0x38, 0x4d, 0x43, 0x65, 0x63, 0x68, 0x4d, - 0x1a, 0xe4, 0xd9, 0xec, 0xb6, 0x3a, 0xb7, 0x53, 0xfa, 0x6f, 0x86, 0x11, 0xff, 0x3b, 0xd8, 0xd9, - 0x6d, 0xab, 0x93, 0xb5, 0x2e, 0xa4, 0x12, 0x8b, 0xfd, 0xf8, 0x5b, 0xda, 0x7b, 0x30, 0x31, 0x4f, - 0xd5, 0xc1, 0x2c, 0x5f, 0x87, 0xd6, 0xc0, 0xb3, 0x9d, 0x0f, 0x6f, 0x62, 0xf7, 0x77, 0xac, 0x9b, - 0x59, 0xdd, 0x87, 0x54, 0x85, 0x74, 0xf1, 0x95, 0xc9, 0x73, 0xad, 0x46, 0x70, 0x27, 0x6b, 0xbf, - 0x67, 0xea, 0x42, 0x13, 0x6b, 0x7d, 0x0d, 0x65, 0xbb, 0xba, 0xe9, 0x2d, 0xd0, 0xc7, 0x27, 0xc3, - 0x2d, 0xa1, 0x8f, 0x4f, 0x96, 0x7b, 0x21, 0x2d, 0xd7, 0x28, 0xc7, 0xc2, 0xc7, 0xb9, 0xfb, 0x6b, - 0x77, 0x7f, 0xf4, 0x9d, 0x53, 0x2f, 0x3e, 0x1b, 0x1f, 0x3f, 0xe8, 0x05, 0xc3, 0x87, 0x03, 0x65, - 0x6d, 0x94, 0x89, 0x6b, 0x0f, 0x07, 0x7e, 0xff, 0x21, 0x36, 0x7b, 0x3c, 0x87, 0xbf, 0x48, 0xfd, - 0xdd, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x7d, 0xa1, 0xab, 0x8e, 0xc3, 0x7a, 0x00, 0x00, + // 11084 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x1b, 0x57, + 0x96, 0x98, 0xf8, 0x6a, 0x92, 0x87, 0x8f, 0x66, 0xdf, 0x7e, 0x51, 0x2d, 0xc9, 0x92, 0xcb, 0x1e, + 0x4b, 0x96, 0x6d, 0x49, 0xd6, 0xf8, 0xb5, 0x76, 0x32, 0xbb, 0xec, 0x6e, 0xb6, 0x9a, 0xa3, 0x7e, + 0xb9, 0xc8, 0xb6, 0xc7, 0x33, 0xd9, 0xd4, 0x54, 0x93, 0xb7, 0xbb, 0x6b, 0x45, 0x56, 0xd1, 0x55, + 0xc5, 0x7e, 0x8c, 0xe1, 0x7c, 0xc8, 0x63, 0x11, 0x24, 0x41, 0x80, 0x45, 0xb2, 0x01, 0xb2, 0xc9, + 0x22, 0x41, 0x82, 0x20, 0x08, 0x12, 0x2c, 0x36, 0x98, 0x0d, 0x90, 0x0f, 0xc9, 0xe7, 0xfd, 0x92, + 0x60, 0x3f, 0x6c, 0xf2, 0x25, 0x18, 0x2c, 0xb0, 0xc8, 0x62, 0xf2, 0x75, 0x7f, 0x41, 0x10, 0xdc, + 0x73, 0xee, 0xad, 0xba, 0x45, 0x56, 0x4b, 0xb2, 0x67, 0x32, 0x5f, 0xa4, 0xae, 0x73, 0xce, 0x7d, + 0x9f, 0x7b, 0xee, 0x79, 0xdd, 0x4b, 0x28, 0xfb, 0xe3, 0xfe, 0x83, 0xb1, 0xef, 0x85, 0x1e, 0x2b, + 0x0c, 0x5d, 0x7f, 0xdc, 0x5f, 0xbb, 0x79, 0xe2, 0x79, 0x27, 0x43, 0xfe, 0xd0, 0x1e, 0x3b, 0x0f, + 0x6d, 0xd7, 0xf5, 0x42, 0x3b, 0x74, 0x3c, 0x37, 0x20, 0x22, 0xe3, 0xc7, 0x50, 0x7f, 0xc2, 0xdd, + 0x2e, 0xe7, 0x03, 0x93, 0x7f, 0x39, 0xe1, 0x41, 0xc8, 0xde, 0x82, 0x05, 0x9b, 0xff, 0x84, 0xf3, + 0x81, 0x35, 0xb6, 0x83, 0x60, 0x7c, 0xea, 0xdb, 0x01, 0x6f, 0x66, 0xee, 0x64, 0xee, 0x55, 0xcd, + 0x06, 0x21, 0x0e, 0x22, 0x38, 0x7b, 0x15, 0xaa, 0x81, 0x20, 0xe5, 0x6e, 0xe8, 0x7b, 0xe3, 0xcb, + 0x66, 0x16, 0xe9, 0x2a, 0x02, 0xd6, 0x26, 0x90, 0x31, 0x84, 0xf9, 0xa8, 0x85, 0x60, 0xec, 0xb9, + 0x01, 0x67, 0x8f, 0x60, 0xa9, 0xef, 0x8c, 0x4f, 0xb9, 0x6f, 0x61, 0xe1, 0x91, 0xcb, 0x47, 0x9e, + 0xeb, 0xf4, 0x9b, 0x99, 0x3b, 0xb9, 0x7b, 0x65, 0x93, 0x11, 0x4e, 0x94, 0xd8, 0x95, 0x18, 0x76, + 0x17, 0xe6, 0xb9, 0x4b, 0x70, 0x3e, 0xc0, 0x52, 0xb2, 0xa9, 0x7a, 0x0c, 0x16, 0x05, 0x8c, 0xbf, + 0x9b, 0x85, 0x85, 0x8e, 0xeb, 0x84, 0x9f, 0xdb, 0xc3, 0x21, 0x0f, 0xd5, 0x98, 0xee, 0xc2, 0xfc, + 0x39, 0x02, 0x70, 0x4c, 0xe7, 0x9e, 0x3f, 0x90, 0x23, 0xaa, 0x13, 0xf8, 0x40, 0x42, 0xaf, 0xec, + 0x59, 0xf6, 0xca, 0x9e, 0xa5, 0x4e, 0x57, 0xee, 0x8a, 0xe9, 0xba, 0x0b, 0xf3, 0x3e, 0xef, 0x7b, + 0x67, 0xdc, 0xbf, 0xb4, 0xce, 0x1d, 0x77, 0xe0, 0x9d, 0x37, 0xf3, 0x77, 0x32, 0xf7, 0x0a, 0x66, + 0x5d, 0x81, 0x3f, 0x47, 0x28, 0x5b, 0x87, 0xf9, 0xfe, 0xa9, 0xed, 0xba, 0x7c, 0x68, 0x1d, 0xd9, + 0xfd, 0x67, 0x93, 0x71, 0xd0, 0x2c, 0xdc, 0xc9, 0xdc, 0xab, 0x3c, 0xbe, 0xfe, 0x00, 0x57, 0xf5, + 0xc1, 0xc6, 0xa9, 0xed, 0xae, 0x23, 0xa6, 0xeb, 0xda, 0xe3, 0xe0, 0xd4, 0x0b, 0xcd, 0xba, 0x2c, + 0x41, 0xe0, 0xc0, 0x58, 0x02, 0xa6, 0xcf, 0x04, 0xcd, 0xbd, 0xf1, 0xef, 0x33, 0xb0, 0x78, 0xe8, + 0x0e, 0xbd, 0xfe, 0xb3, 0x6f, 0x39, 0x45, 0x29, 0x63, 0xc8, 0xbe, 0xec, 0x18, 0x72, 0xdf, 0x74, + 0x0c, 0x2b, 0xb0, 0x94, 0xec, 0xac, 0x1c, 0x05, 0x87, 0x65, 0x51, 0xfa, 0x84, 0xab, 0x6e, 0xa9, + 0x61, 0xbc, 0x09, 0x8d, 0xfe, 0xc4, 0xf7, 0xb9, 0x3b, 0x33, 0x8e, 0x79, 0x09, 0x8f, 0x06, 0xf2, + 0x2a, 0x54, 0x5d, 0x7e, 0x1e, 0x93, 0x49, 0xde, 0x75, 0xf9, 0xb9, 0x22, 0x31, 0x9a, 0xb0, 0x32, + 0xdd, 0x8c, 0xec, 0xc0, 0xcf, 0x33, 0x90, 0x3f, 0x0c, 0x2f, 0x3c, 0xf6, 0x3e, 0x54, 0xed, 0xc1, + 0xc0, 0xe7, 0x41, 0x60, 0x85, 0x97, 0x63, 0xda, 0x29, 0xf5, 0xc7, 0x4c, 0x0e, 0xb1, 0x45, 0xa8, + 0xde, 0xe5, 0x98, 0x9b, 0x15, 0x3b, 0xfe, 0x60, 0x4d, 0x28, 0xca, 0x4f, 0x6c, 0xb7, 0x6c, 0xaa, + 0x4f, 0x76, 0x0b, 0xc0, 0x1e, 0x79, 0x13, 0x37, 0xb4, 0x02, 0x3b, 0xc4, 0x19, 0xcb, 0x99, 0x65, + 0x82, 0x74, 0xed, 0x90, 0xdd, 0x80, 0xf2, 0xf8, 0x99, 0x15, 0xf4, 0x7d, 0x67, 0x1c, 0x22, 0xf3, + 0x94, 0xcd, 0xd2, 0xf8, 0x59, 0x17, 0xbf, 0xd9, 0x5b, 0x50, 0xf2, 0x26, 0xe1, 0xd8, 0x73, 0xdc, + 0x50, 0xf2, 0xcb, 0xbc, 0xec, 0xc8, 0xfe, 0x24, 0x3c, 0x10, 0x60, 0x33, 0x22, 0x60, 0xaf, 0x43, + 0xad, 0xef, 0xb9, 0xc7, 0x8e, 0x3f, 0x22, 0x89, 0xd0, 0x9c, 0xc3, 0xb6, 0x92, 0x40, 0xe3, 0x0f, + 0xb3, 0x50, 0xe9, 0xf9, 0xb6, 0x1b, 0xd8, 0x7d, 0x01, 0x60, 0xab, 0x50, 0x0c, 0x2f, 0xac, 0x53, + 0x3b, 0x38, 0xc5, 0xa1, 0x96, 0xcd, 0xb9, 0xf0, 0x62, 0xdb, 0x0e, 0x4e, 0xd9, 0x0a, 0xcc, 0x51, + 0x2f, 0x71, 0x40, 0x39, 0x53, 0x7e, 0x89, 0x0d, 0xe2, 0x4e, 0x46, 0x56, 0xb2, 0xa9, 0x1c, 0x72, + 0x4c, 0xc3, 0x9d, 0x8c, 0x36, 0x74, 0xb8, 0x18, 0xfc, 0x91, 0x58, 0x6e, 0x6a, 0x80, 0x86, 0x57, + 0x46, 0x08, 0xb6, 0xf1, 0x2a, 0x54, 0x25, 0x9a, 0x3b, 0x27, 0xa7, 0x34, 0xc6, 0x82, 0x59, 0x21, + 0x02, 0x04, 0x89, 0x1a, 0x42, 0x67, 0xc4, 0xad, 0x20, 0xb4, 0x47, 0x63, 0x39, 0xa4, 0xb2, 0x80, + 0x74, 0x05, 0x00, 0xd1, 0x5e, 0x68, 0x0f, 0xad, 0x63, 0xce, 0x83, 0x66, 0x51, 0xa2, 0x05, 0x64, + 0x8b, 0xf3, 0x80, 0x7d, 0x07, 0xea, 0x03, 0x1e, 0x84, 0x96, 0x5c, 0x0c, 0x1e, 0x34, 0x4b, 0xb8, + 0xf3, 0x6b, 0x02, 0xda, 0x52, 0x40, 0x76, 0x13, 0xc0, 0xb7, 0xcf, 0x2d, 0x31, 0x11, 0xfc, 0xa2, + 0x59, 0xa6, 0x55, 0xf0, 0xed, 0xf3, 0xde, 0xc5, 0x36, 0xbf, 0x10, 0x5c, 0xf3, 0x84, 0x87, 0xda, + 0xa4, 0x05, 0x92, 0x3b, 0x8d, 0x1d, 0x60, 0x1a, 0x78, 0x93, 0x87, 0xb6, 0x33, 0x0c, 0xd8, 0x07, + 0x50, 0x0d, 0x35, 0x62, 0x14, 0x83, 0x95, 0x88, 0x85, 0xb4, 0x02, 0x66, 0x82, 0xce, 0x38, 0x85, + 0xd2, 0x16, 0xe7, 0x3b, 0xce, 0xc8, 0x09, 0xd9, 0x0a, 0x14, 0x8e, 0x9d, 0x0b, 0x4e, 0xcc, 0x9e, + 0xdb, 0xbe, 0x66, 0xd2, 0x27, 0xbb, 0x0d, 0x80, 0x7f, 0x58, 0xa3, 0x88, 0x9b, 0xb6, 0xaf, 0x99, + 0x65, 0x84, 0xed, 0x06, 0x76, 0xc8, 0xd6, 0xa0, 0x38, 0xe6, 0x7e, 0x9f, 0xab, 0x75, 0xdb, 0xbe, + 0x66, 0x2a, 0xc0, 0x7a, 0x11, 0x0a, 0x43, 0x51, 0xbb, 0xf1, 0xc7, 0x05, 0xa8, 0x74, 0xb9, 0x1b, + 0xed, 0x32, 0x06, 0x79, 0x31, 0x21, 0x72, 0x67, 0xe1, 0xdf, 0xec, 0x35, 0xa8, 0xe0, 0xd4, 0x05, + 0xa1, 0xef, 0xb8, 0x27, 0xc4, 0xd5, 0xeb, 0xd9, 0x66, 0xc6, 0x04, 0x01, 0xee, 0x22, 0x94, 0x35, + 0x20, 0x67, 0x8f, 0x14, 0x57, 0x8b, 0x3f, 0xd9, 0x75, 0x28, 0xd9, 0xa3, 0x90, 0xba, 0x57, 0x45, + 0x70, 0xd1, 0x1e, 0x85, 0xd8, 0xb5, 0x57, 0xa1, 0x3a, 0xb6, 0x2f, 0x47, 0x62, 0x2f, 0x47, 0xec, + 0x50, 0x35, 0x2b, 0x12, 0x86, 0x0c, 0xf1, 0x18, 0x16, 0x75, 0x12, 0xd5, 0x78, 0x21, 0x6a, 0x7c, + 0x41, 0xa3, 0x96, 0x7d, 0xb8, 0x0b, 0xf3, 0xaa, 0x8c, 0x4f, 0xe3, 0x41, 0x36, 0x29, 0x9b, 0x75, + 0x09, 0x56, 0xa3, 0xbc, 0x07, 0x8d, 0x63, 0xc7, 0xb5, 0x87, 0x56, 0x7f, 0x18, 0x9e, 0x59, 0x03, + 0x3e, 0x0c, 0x6d, 0xe4, 0x98, 0x82, 0x59, 0x47, 0xf8, 0xc6, 0x30, 0x3c, 0xdb, 0x14, 0x50, 0xf6, + 0x36, 0x94, 0x8f, 0x39, 0xb7, 0x70, 0xb2, 0x9a, 0xa5, 0xc4, 0xc6, 0x53, 0x2b, 0x64, 0x96, 0x8e, + 0xd5, 0x5a, 0xbd, 0x0d, 0x0d, 0x6f, 0x12, 0x9e, 0x78, 0x8e, 0x7b, 0x62, 0x09, 0x79, 0x67, 0x39, + 0x03, 0xe4, 0xa1, 0xfc, 0x7a, 0xf6, 0x51, 0xc6, 0xac, 0x2b, 0x9c, 0x90, 0x3c, 0x9d, 0x01, 0x7b, + 0x03, 0xe6, 0x87, 0x76, 0x10, 0x5a, 0xa7, 0xde, 0xd8, 0x1a, 0x4f, 0x8e, 0x9e, 0xf1, 0xcb, 0x66, + 0x0d, 0x27, 0xa2, 0x26, 0xc0, 0xdb, 0xde, 0xf8, 0x00, 0x81, 0x82, 0xb3, 0xb1, 0x9f, 0xd4, 0x09, + 0xb8, 0x93, 0xb9, 0x57, 0x33, 0xcb, 0x02, 0x42, 0x8d, 0x7e, 0x01, 0x8b, 0xb8, 0x3c, 0xfd, 0x49, + 0x10, 0x7a, 0x23, 0x4b, 0xc8, 0x6a, 0x7f, 0x10, 0x34, 0x2b, 0xc8, 0x6b, 0x6f, 0xca, 0xce, 0x6a, + 0x6b, 0xfc, 0x60, 0x93, 0x07, 0xe1, 0x06, 0x12, 0x9b, 0x44, 0x2b, 0x0e, 0xf4, 0x4b, 0x73, 0x61, + 0x30, 0x0d, 0x67, 0x6f, 0x03, 0xb3, 0x87, 0x43, 0xef, 0xdc, 0x0a, 0xf8, 0xf0, 0xd8, 0x92, 0x93, + 0xd8, 0xac, 0xdf, 0xc9, 0xdc, 0x2b, 0x99, 0x0d, 0xc4, 0x74, 0xf9, 0xf0, 0xf8, 0x80, 0xe0, 0xec, + 0x03, 0xc0, 0xcd, 0x64, 0x1d, 0x73, 0x3b, 0x9c, 0xf8, 0x3c, 0x68, 0xce, 0xdf, 0xc9, 0xdd, 0xab, + 0x3f, 0x5e, 0x88, 0xe6, 0x0b, 0xc1, 0xeb, 0x4e, 0x68, 0x56, 0x05, 0x9d, 0xfc, 0x0e, 0xd6, 0x36, + 0x61, 0x25, 0xbd, 0x4b, 0x82, 0xa9, 0xc4, 0xac, 0x08, 0x66, 0xcc, 0x9b, 0xe2, 0x4f, 0xb6, 0x04, + 0x85, 0x33, 0x7b, 0x38, 0xe1, 0x52, 0xa6, 0xd3, 0xc7, 0xc7, 0xd9, 0x8f, 0x32, 0xc6, 0x1f, 0x65, + 0xa0, 0x4a, 0xa3, 0x94, 0xba, 0xc8, 0x6b, 0x50, 0x53, 0xdc, 0xc0, 0x7d, 0xdf, 0xf3, 0xa5, 0x54, + 0x53, 0x9c, 0xd7, 0x16, 0x30, 0x71, 0xaa, 0x28, 0xa2, 0xb1, 0xcf, 0x9d, 0x91, 0x7d, 0xa2, 0xaa, + 0x56, 0xac, 0x74, 0x20, 0xc1, 0xec, 0xdd, 0xb8, 0x3e, 0xdf, 0x9b, 0x84, 0x5c, 0x9e, 0x79, 0x55, + 0x39, 0x3c, 0x53, 0xc0, 0xa2, 0xda, 0xf1, 0xeb, 0x25, 0xf8, 0xdc, 0xf8, 0xdd, 0x0c, 0x30, 0xd1, + 0xed, 0x9e, 0x47, 0x15, 0x48, 0x0e, 0x9d, 0x2e, 0x99, 0x79, 0xe9, 0x1d, 0x92, 0x7d, 0xde, 0x0e, + 0x31, 0xa0, 0x40, 0x7d, 0xcf, 0xa7, 0xf4, 0x9d, 0x50, 0xdf, 0xcf, 0x97, 0x72, 0x8d, 0xbc, 0xf1, + 0xbf, 0x72, 0xb0, 0xb4, 0x41, 0x47, 0x76, 0xab, 0xdf, 0xe7, 0xe3, 0x68, 0xef, 0xdc, 0x86, 0x8a, + 0xeb, 0x0d, 0xb8, 0xe2, 0x58, 0xea, 0x18, 0x08, 0x90, 0xc6, 0xae, 0xa7, 0xb6, 0xe3, 0x52, 0xc7, + 0x69, 0x32, 0xcb, 0x08, 0xc1, 0x6e, 0xbf, 0x01, 0xf3, 0x63, 0xee, 0x0e, 0xf4, 0x2d, 0x42, 0x4a, + 0x55, 0x4d, 0x82, 0xe5, 0xee, 0xb8, 0x0d, 0x95, 0xe3, 0x09, 0xd1, 0x09, 0xc1, 0x92, 0x47, 0x1e, + 0x00, 0x09, 0x6a, 0x91, 0x7c, 0x19, 0x4f, 0x82, 0x53, 0xc4, 0x16, 0x10, 0x5b, 0x14, 0xdf, 0x02, + 0x75, 0x0b, 0x60, 0x30, 0x09, 0x42, 0xb9, 0x63, 0xe6, 0x10, 0x59, 0x16, 0x10, 0xda, 0x31, 0xef, + 0xc0, 0xe2, 0xc8, 0xbe, 0xb0, 0x90, 0x77, 0x2c, 0xc7, 0xb5, 0x8e, 0x87, 0x78, 0xe6, 0x14, 0x91, + 0xae, 0x31, 0xb2, 0x2f, 0x3e, 0x13, 0x98, 0x8e, 0xbb, 0x85, 0x70, 0x21, 0x56, 0x94, 0xba, 0xe3, + 0xf3, 0x80, 0xfb, 0x67, 0x1c, 0x25, 0x41, 0x3e, 0xd2, 0x69, 0x4c, 0x82, 0x8a, 0x1e, 0x8d, 0xc4, + 0xb8, 0xc3, 0x61, 0x9f, 0xb6, 0xbd, 0x59, 0x1c, 0x39, 0xee, 0x76, 0x38, 0xec, 0x8b, 0x73, 0x45, + 0xc8, 0x91, 0x31, 0xf7, 0xad, 0x67, 0xe7, 0xb8, 0x87, 0xf3, 0x28, 0x37, 0x0e, 0xb8, 0xff, 0xf4, + 0x5c, 0x1c, 0xfd, 0xfd, 0x00, 0x05, 0x91, 0x7d, 0xd9, 0xac, 0xe0, 0x06, 0x2f, 0xf5, 0x03, 0x21, + 0x82, 0xec, 0x4b, 0xb1, 0x09, 0x45, 0x6f, 0x6d, 0x5c, 0x05, 0x3e, 0xc0, 0xea, 0x03, 0x94, 0xa8, + 0x35, 0xec, 0x6c, 0x4b, 0x22, 0x44, 0x3b, 0x81, 0xe0, 0x7a, 0xd5, 0xd9, 0xe3, 0xa1, 0x7d, 0x12, + 0xa0, 0x48, 0xa9, 0x99, 0x55, 0x09, 0xdc, 0x12, 0x30, 0xe3, 0x73, 0x52, 0xb2, 0xb4, 0xb5, 0x95, + 0x7b, 0x46, 0x1c, 0xf5, 0x08, 0xc1, 0x75, 0x2d, 0x99, 0xf2, 0x2b, 0x6d, 0xd1, 0xb2, 0x29, 0x8b, + 0x66, 0xfc, 0x7e, 0x06, 0xaa, 0xb2, 0x66, 0x54, 0x4a, 0xd8, 0x03, 0x60, 0x6a, 0x15, 0xc3, 0x0b, + 0x67, 0x60, 0x1d, 0x5d, 0x86, 0x3c, 0x20, 0xa6, 0xd9, 0xbe, 0x66, 0x36, 0x24, 0xae, 0x77, 0xe1, + 0x0c, 0xd6, 0x05, 0x86, 0xdd, 0x87, 0x46, 0x82, 0x3e, 0x08, 0x7d, 0xe2, 0xe8, 0xed, 0x6b, 0x66, + 0x5d, 0xa3, 0xee, 0x86, 0xbe, 0xd8, 0x23, 0x42, 0xe5, 0x99, 0x84, 0x96, 0xe3, 0x0e, 0xf8, 0x05, + 0xb2, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x23, 0x40, 0xeb, 0x75, 0xa8, 0xea, 0xd5, 0x19, 0x27, 0x50, + 0x52, 0xfa, 0x12, 0x2a, 0x0c, 0x53, 0x5d, 0x32, 0xcb, 0x61, 0xd4, 0x93, 0xeb, 0x50, 0x4a, 0xf6, + 0xc0, 0x2c, 0x86, 0x2f, 0xdd, 0xb0, 0xf1, 0x3d, 0x68, 0xec, 0x08, 0xe6, 0x71, 0x05, 0xb3, 0x4a, + 0xfd, 0x6f, 0x05, 0xe6, 0xb4, 0x4d, 0x53, 0x36, 0xe5, 0x97, 0x38, 0x73, 0x4f, 0xbd, 0x20, 0x94, + 0xad, 0xe0, 0xdf, 0xc6, 0x1f, 0x67, 0x80, 0xb5, 0x83, 0xd0, 0x19, 0xd9, 0x21, 0xdf, 0xe2, 0x91, + 0x58, 0xd8, 0x87, 0xaa, 0xa8, 0xad, 0xe7, 0xb5, 0x48, 0x21, 0x23, 0x85, 0xe2, 0x2d, 0xb9, 0x8d, + 0x67, 0x0b, 0x3c, 0xd0, 0xa9, 0x49, 0xcc, 0x27, 0x2a, 0x10, 0xbb, 0x2c, 0xb4, 0xfd, 0x13, 0x1e, + 0xa2, 0x1a, 0x27, 0xf5, 0x7d, 0x20, 0x90, 0x50, 0xe0, 0xd6, 0x7e, 0x1d, 0x16, 0x66, 0xea, 0xd0, + 0xe5, 0x72, 0x39, 0x45, 0x2e, 0xe7, 0x74, 0xb9, 0x6c, 0xc1, 0x62, 0xa2, 0x5f, 0x92, 0xd3, 0x56, + 0xa1, 0x28, 0x36, 0x84, 0x50, 0x0e, 0x32, 0xa4, 0x55, 0x1e, 0x73, 0x2e, 0xd4, 0xe0, 0x87, 0xb0, + 0x74, 0xcc, 0xb9, 0x6f, 0x87, 0x88, 0xc4, 0x1d, 0x23, 0x56, 0x48, 0x56, 0xbc, 0x20, 0x71, 0x5d, + 0x3b, 0x3c, 0xe0, 0xbe, 0x58, 0x29, 0xe3, 0x7f, 0x67, 0x60, 0x5e, 0x48, 0xd0, 0x5d, 0xdb, 0xbd, + 0x54, 0xf3, 0xb4, 0x93, 0x3a, 0x4f, 0xf7, 0xb4, 0xc3, 0x50, 0xa3, 0xfe, 0xa6, 0x93, 0x94, 0x9b, + 0x9e, 0x24, 0x76, 0x07, 0xaa, 0x89, 0xbe, 0x16, 0xb0, 0xaf, 0x10, 0x44, 0x9d, 0xfc, 0xc5, 0xa7, + 0xf1, 0x0d, 0x68, 0xc4, 0xdd, 0x96, 0x73, 0xc8, 0x20, 0x2f, 0x58, 0x52, 0x56, 0x80, 0x7f, 0x1b, + 0xff, 0x3c, 0x43, 0x84, 0x1b, 0x9e, 0x13, 0x69, 0xa7, 0x82, 0x50, 0xe8, 0xbd, 0x8a, 0x50, 0xfc, + 0x7d, 0xa5, 0x56, 0xff, 0x8b, 0x0f, 0x56, 0x6c, 0x9d, 0x80, 0xbb, 0x03, 0xcb, 0x1e, 0x0e, 0x51, + 0xf8, 0x96, 0xcc, 0xa2, 0xf8, 0x6e, 0x0d, 0x87, 0xc6, 0x5d, 0x58, 0xd0, 0x7a, 0xf7, 0x9c, 0x71, + 0xec, 0x01, 0xdb, 0x71, 0x82, 0xf0, 0xd0, 0x0d, 0xc6, 0x9a, 0xe2, 0x76, 0x03, 0xca, 0x42, 0xc2, + 0x8a, 0x9e, 0xd1, 0x96, 0x2d, 0x98, 0x42, 0xe4, 0x8a, 0x7e, 0x05, 0x88, 0xb4, 0x2f, 0x24, 0x32, + 0x2b, 0x91, 0xf6, 0x05, 0x22, 0x8d, 0x8f, 0x60, 0x31, 0x51, 0x9f, 0x6c, 0xfa, 0x55, 0x28, 0x4c, + 0xc2, 0x0b, 0x4f, 0xa9, 0xe6, 0x15, 0xc9, 0x21, 0xc2, 0x00, 0x34, 0x09, 0x63, 0x7c, 0x02, 0x0b, + 0x7b, 0xfc, 0x5c, 0x6e, 0x62, 0xd5, 0x91, 0x37, 0x20, 0xff, 0x02, 0xa3, 0x10, 0xf1, 0xc6, 0x03, + 0x60, 0x7a, 0x61, 0xd9, 0xaa, 0x66, 0x23, 0x66, 0x12, 0x36, 0xa2, 0xf1, 0x06, 0xb0, 0xae, 0x73, + 0xe2, 0xee, 0xf2, 0x20, 0xb0, 0x4f, 0xa2, 0x6d, 0xdf, 0x80, 0xdc, 0x28, 0x38, 0x91, 0x32, 0x4a, + 0xfc, 0x69, 0x7c, 0x17, 0x16, 0x13, 0x74, 0xb2, 0xe2, 0x9b, 0x50, 0x0e, 0x9c, 0x13, 0x17, 0x15, + 0x2b, 0x59, 0x75, 0x0c, 0x30, 0xb6, 0x60, 0xe9, 0x33, 0xee, 0x3b, 0xc7, 0x97, 0x2f, 0xaa, 0x3e, + 0x59, 0x4f, 0x76, 0xba, 0x9e, 0x36, 0x2c, 0x4f, 0xd5, 0x23, 0x9b, 0x27, 0xf6, 0x95, 0x2b, 0x59, + 0x32, 0xe9, 0x43, 0x93, 0x7b, 0x59, 0x5d, 0xee, 0x19, 0x87, 0xc0, 0x36, 0x3c, 0xd7, 0xe5, 0xfd, + 0xf0, 0x80, 0x73, 0x3f, 0xf6, 0x52, 0xc5, 0xbc, 0x5a, 0x79, 0xbc, 0x2a, 0x67, 0x76, 0x5a, 0x98, + 0x4a, 0x26, 0x66, 0x90, 0x1f, 0x73, 0x7f, 0x84, 0x15, 0x97, 0x4c, 0xfc, 0xdb, 0x58, 0x86, 0xc5, + 0x44, 0xb5, 0xd2, 0xae, 0x7f, 0x04, 0xcb, 0x9b, 0x4e, 0xd0, 0x9f, 0x6d, 0x70, 0x15, 0x8a, 0xe3, + 0xc9, 0x91, 0x95, 0x94, 0xcb, 0x4f, 0xf9, 0xa5, 0xb0, 0xf6, 0xa6, 0x4b, 0xc8, 0xba, 0xfe, 0x76, + 0x06, 0xf2, 0xdb, 0xbd, 0x9d, 0x0d, 0xb6, 0x06, 0x25, 0xc7, 0xed, 0x7b, 0x23, 0xa1, 0x78, 0xd1, + 0x98, 0xa3, 0xef, 0x2b, 0x37, 0xd8, 0x0d, 0x28, 0xa3, 0xbe, 0x26, 0x4c, 0x5b, 0xa9, 0xfa, 0x94, + 0x04, 0x60, 0xc7, 0xeb, 0x3f, 0x13, 0x36, 0x35, 0xbf, 0x18, 0x3b, 0x3e, 0x5a, 0xcd, 0xca, 0x18, + 0xce, 0xd3, 0x59, 0x1f, 0x23, 0xc8, 0x22, 0x36, 0xfe, 0x43, 0x11, 0x8a, 0xf2, 0xb4, 0xa5, 0x93, + 0x3b, 0x74, 0xce, 0x78, 0x7c, 0x72, 0x8b, 0x2f, 0xa1, 0x0f, 0xf8, 0x7c, 0xe4, 0x85, 0x91, 0xc2, + 0x46, 0x6b, 0x50, 0x25, 0xa0, 0x54, 0xd9, 0x34, 0xa5, 0x81, 0x5c, 0x0c, 0x39, 0x22, 0xea, 0xeb, + 0x47, 0xf9, 0x0d, 0x28, 0xaa, 0xb3, 0x3f, 0x1f, 0xd9, 0x34, 0x73, 0x7d, 0xd2, 0xd6, 0xd6, 0xa0, + 0xd4, 0xb7, 0xc7, 0x76, 0xdf, 0x09, 0x2f, 0xa5, 0x40, 0x88, 0xbe, 0x45, 0xed, 0x43, 0xaf, 0x6f, + 0x0f, 0xad, 0x23, 0x7b, 0x68, 0xbb, 0x7d, 0x2e, 0x6d, 0xf7, 0x2a, 0x02, 0xd7, 0x09, 0x26, 0xec, + 0x73, 0xd9, 0x4f, 0x45, 0x45, 0x26, 0xbc, 0xec, 0xbd, 0x22, 0x13, 0xca, 0xa5, 0x37, 0x1a, 0x39, + 0xc2, 0xca, 0x20, 0x35, 0x2c, 0x67, 0x96, 0x09, 0xb2, 0xc5, 0x71, 0xb4, 0x12, 0x7d, 0x4e, 0x53, + 0x57, 0xa6, 0xa6, 0x08, 0xf8, 0x39, 0x39, 0x12, 0x66, 0x75, 0xb1, 0x9c, 0xa6, 0x8b, 0xbd, 0x05, + 0x0b, 0x13, 0x37, 0xe0, 0x61, 0x38, 0xe4, 0x83, 0xa8, 0x2f, 0x15, 0x24, 0x6a, 0x44, 0x08, 0xd5, + 0x9d, 0x07, 0xb0, 0x48, 0x4e, 0x87, 0xc0, 0x0e, 0xbd, 0xe0, 0xd4, 0x09, 0xac, 0x40, 0x58, 0x48, + 0x64, 0xee, 0x2e, 0x20, 0xaa, 0x2b, 0x31, 0x5d, 0x32, 0x91, 0x56, 0xa7, 0xe8, 0x7d, 0xde, 0xe7, + 0xce, 0x19, 0x1f, 0xa0, 0x9e, 0x96, 0x33, 0x97, 0x13, 0x65, 0x4c, 0x89, 0x44, 0xa5, 0x7b, 0x32, + 0xb2, 0x26, 0xe3, 0x81, 0x2d, 0x94, 0x95, 0x3a, 0x29, 0xc3, 0xee, 0x64, 0x74, 0x48, 0x10, 0xf6, + 0x08, 0x94, 0x26, 0x26, 0xf5, 0xc3, 0xf9, 0x84, 0x3c, 0x13, 0xcc, 0x6a, 0x56, 0x25, 0x05, 0x29, + 0x8a, 0x09, 0x9d, 0xb3, 0x31, 0xa5, 0x73, 0x36, 0xa1, 0x38, 0xf6, 0x9d, 0x33, 0x3b, 0xe4, 0xcd, + 0x05, 0x12, 0xe0, 0xf2, 0x53, 0x48, 0x06, 0xc7, 0x75, 0x42, 0xc7, 0x0e, 0x3d, 0xbf, 0xc9, 0x10, + 0x17, 0x03, 0xd8, 0x7d, 0x58, 0x40, 0x1e, 0x09, 0x42, 0x3b, 0x9c, 0x04, 0x52, 0x03, 0x5d, 0x44, + 0x66, 0x42, 0x1d, 0xba, 0x8b, 0x70, 0x54, 0x42, 0xd9, 0x77, 0x61, 0x85, 0xd8, 0x02, 0x4b, 0x48, + 0xcd, 0x1a, 0x15, 0x82, 0x25, 0x9c, 0x8a, 0x45, 0xc4, 0x0a, 0xfe, 0x96, 0xfa, 0xb5, 0xd0, 0x0e, + 0xde, 0x87, 0x55, 0xc9, 0x26, 0x33, 0xa5, 0x96, 0xb1, 0xd4, 0x12, 0xa1, 0xa7, 0x8a, 0xdd, 0x87, + 0x05, 0xd1, 0x25, 0xa7, 0x6f, 0xc9, 0xd2, 0x62, 0x27, 0xac, 0x60, 0xef, 0xe7, 0x09, 0x61, 0x22, + 0xfc, 0x29, 0xbf, 0x14, 0xac, 0x3c, 0x74, 0x8e, 0x79, 0xe8, 0x8c, 0x78, 0x73, 0x95, 0x98, 0x43, + 0x7d, 0x8b, 0x5d, 0x36, 0x19, 0x23, 0xa6, 0x49, 0x7b, 0x9a, 0xbe, 0x90, 0xef, 0x86, 0x5e, 0xc0, + 0x95, 0x7b, 0xa9, 0x79, 0x5d, 0x6e, 0x20, 0x01, 0x94, 0x22, 0xcb, 0xf8, 0x69, 0x86, 0xce, 0x20, + 0xb9, 0x65, 0x03, 0xcd, 0xa2, 0xa2, 0xcd, 0x6a, 0x79, 0xee, 0xf0, 0x52, 0xee, 0x5f, 0x20, 0xd0, + 0xbe, 0x3b, 0xc4, 0x0d, 0xe4, 0xb8, 0x3a, 0x09, 0x89, 0xbb, 0xaa, 0x02, 0x22, 0xd1, 0x6d, 0xa8, + 0x8c, 0x27, 0x47, 0x43, 0xa7, 0x4f, 0x24, 0x39, 0xaa, 0x85, 0x40, 0x48, 0x20, 0x4c, 0x4a, 0x5a, + 0x44, 0xa2, 0xc8, 0x23, 0x45, 0x45, 0xc2, 0x90, 0x04, 0xc5, 0x29, 0xf7, 0x71, 0x07, 0x57, 0x4d, + 0xfc, 0xdb, 0x58, 0x87, 0xa5, 0x64, 0xa7, 0xa5, 0xac, 0xbf, 0x0f, 0x25, 0x29, 0x1e, 0x94, 0xaf, + 0xa1, 0xae, 0x79, 0x7f, 0x85, 0x55, 0x14, 0xe1, 0x8d, 0xdf, 0x9e, 0x83, 0x45, 0x09, 0xdd, 0x10, + 0x33, 0xd2, 0x9d, 0x8c, 0x46, 0xb6, 0x9f, 0x22, 0x77, 0x32, 0xcf, 0x97, 0x3b, 0xd9, 0x19, 0xb9, + 0x93, 0x34, 0x36, 0x49, 0x6c, 0x25, 0x8d, 0x4d, 0xb1, 0x04, 0xa4, 0xff, 0xeb, 0xae, 0xc7, 0x9a, + 0x04, 0xf7, 0xc8, 0xc5, 0x39, 0x23, 0x25, 0x0b, 0x29, 0x52, 0x52, 0x97, 0x71, 0x73, 0x53, 0x32, + 0xee, 0x55, 0xa0, 0xb5, 0x56, 0x22, 0xbb, 0x48, 0x26, 0x01, 0xc2, 0xa4, 0xff, 0xf2, 0x2e, 0xcc, + 0x4f, 0x8b, 0x15, 0x92, 0x5f, 0xf5, 0x14, 0xa1, 0xe2, 0x8c, 0x38, 0x1e, 0x10, 0x1a, 0x71, 0x59, + 0x0a, 0x15, 0x67, 0xc4, 0x77, 0x10, 0xa3, 0xe8, 0xdb, 0x00, 0xd4, 0x36, 0x6a, 0x24, 0x80, 0x1a, + 0xc9, 0x1b, 0xc9, 0xb5, 0xd0, 0x67, 0xfd, 0x81, 0xf8, 0x98, 0xf8, 0x1c, 0xb5, 0x94, 0x32, 0x96, + 0x44, 0xc7, 0xf5, 0x53, 0xa8, 0x7b, 0x63, 0xee, 0x5a, 0xf1, 0xf6, 0xae, 0x60, 0x55, 0xaf, 0x3f, + 0xa7, 0xaa, 0x8e, 0xa2, 0x35, 0x6b, 0xa2, 0x6c, 0xf4, 0xc9, 0x76, 0x69, 0xe2, 0xb9, 0x56, 0x5b, + 0xf5, 0x1b, 0xd4, 0x56, 0xc7, 0xc2, 0xd1, 0xb7, 0xf1, 0xf7, 0x32, 0x50, 0xd1, 0xba, 0xcd, 0x96, + 0x61, 0x61, 0x63, 0x7f, 0xff, 0xa0, 0x6d, 0xb6, 0x7a, 0x9d, 0xcf, 0xda, 0xd6, 0xc6, 0xce, 0x7e, + 0xb7, 0xdd, 0xb8, 0x26, 0xc0, 0x3b, 0xfb, 0x1b, 0xad, 0x1d, 0x6b, 0x6b, 0xdf, 0xdc, 0x50, 0xe0, + 0x0c, 0x5b, 0x01, 0x66, 0xb6, 0x77, 0xf7, 0x7b, 0xed, 0x04, 0x3c, 0xcb, 0x1a, 0x50, 0x5d, 0x37, + 0xdb, 0xad, 0x8d, 0x6d, 0x09, 0xc9, 0xb1, 0x25, 0x68, 0x6c, 0x1d, 0xee, 0x6d, 0x76, 0xf6, 0x9e, + 0x58, 0x1b, 0xad, 0xbd, 0x8d, 0xf6, 0x4e, 0x7b, 0xb3, 0x91, 0x67, 0x35, 0x28, 0xb7, 0xd6, 0x5b, + 0x7b, 0x9b, 0xfb, 0x7b, 0xed, 0xcd, 0x46, 0xc1, 0xf8, 0x35, 0x28, 0xc7, 0x03, 0xad, 0x40, 0xf1, + 0x70, 0xef, 0xe9, 0xde, 0xfe, 0xe7, 0x7b, 0x8d, 0x6b, 0xac, 0x0c, 0x05, 0x6c, 0xbf, 0x91, 0x61, + 0x00, 0x73, 0xd4, 0x66, 0x23, 0xcb, 0x4a, 0x90, 0x5f, 0xdf, 0xef, 0x6d, 0x37, 0x72, 0xc6, 0x9f, + 0x65, 0x60, 0x19, 0x87, 0x3c, 0x98, 0x16, 0x02, 0x77, 0xa0, 0xd2, 0xf7, 0xbc, 0xb1, 0x30, 0x6e, + 0xe2, 0x43, 0x5c, 0x07, 0x89, 0x0d, 0x4e, 0xf2, 0xf2, 0xd8, 0xf3, 0xfb, 0x5c, 0xca, 0x00, 0x40, + 0xd0, 0x96, 0x80, 0x08, 0x1e, 0x94, 0x4c, 0x4c, 0x14, 0x24, 0x02, 0x2a, 0x04, 0x23, 0x92, 0x15, + 0x98, 0x3b, 0xf2, 0xb9, 0xdd, 0x3f, 0x95, 0xbb, 0x5f, 0x7e, 0xb1, 0x37, 0x63, 0xb3, 0xbb, 0x2f, + 0x78, 0x6a, 0xc8, 0x07, 0xb8, 0x05, 0x4a, 0xe6, 0xbc, 0x84, 0x6f, 0x48, 0xb0, 0x38, 0x00, 0xec, + 0x23, 0xdb, 0x1d, 0x78, 0x2e, 0x1f, 0x48, 0xed, 0x3e, 0x06, 0x18, 0x07, 0xb0, 0x32, 0x3d, 0x3e, + 0x29, 0x2f, 0x3e, 0xd0, 0xe4, 0x05, 0x29, 0xdb, 0x6b, 0x57, 0xb3, 0x82, 0x26, 0x3b, 0x7e, 0x96, + 0x83, 0xbc, 0x50, 0xbe, 0xae, 0xd4, 0xd3, 0x74, 0x6d, 0x3a, 0x37, 0x13, 0x71, 0x41, 0xeb, 0x9e, + 0x4e, 0x65, 0x72, 0x21, 0x95, 0x11, 0x82, 0xa7, 0x71, 0x84, 0xf6, 0x79, 0xff, 0x4c, 0xfa, 0x90, + 0x08, 0x6d, 0xf2, 0xfe, 0x19, 0x9a, 0x31, 0x76, 0x48, 0x65, 0x69, 0xbf, 0x17, 0x03, 0x3b, 0xc4, + 0x92, 0x12, 0x85, 0xe5, 0x8a, 0x11, 0x0a, 0x4b, 0x35, 0xa1, 0xe8, 0xb8, 0x47, 0xde, 0xc4, 0x1d, + 0xe0, 0xf6, 0x2e, 0x99, 0xea, 0x13, 0x03, 0x3c, 0x28, 0x89, 0xc4, 0xf9, 0x41, 0xbb, 0xb9, 0x24, + 0x00, 0x3d, 0x71, 0x82, 0xbc, 0x0b, 0xe5, 0xe0, 0xd2, 0xed, 0xeb, 0x7b, 0x78, 0x49, 0xce, 0x8f, + 0x18, 0xfd, 0x83, 0xee, 0xa5, 0xdb, 0xc7, 0x1d, 0x5b, 0x0a, 0xe4, 0x5f, 0xec, 0x7d, 0x28, 0x45, + 0xae, 0x56, 0x92, 0xc0, 0xd7, 0xf5, 0x12, 0xca, 0xbf, 0x4a, 0x16, 0x6d, 0x44, 0xba, 0xf6, 0x14, + 0x6a, 0x09, 0x94, 0x6e, 0x86, 0xd6, 0xc8, 0x0c, 0x7d, 0x5d, 0x37, 0x43, 0x63, 0xc1, 0x2e, 0x8b, + 0xe9, 0x66, 0xe9, 0xaf, 0x43, 0x49, 0xf5, 0x4c, 0x6c, 0x27, 0xb9, 0x15, 0xac, 0xee, 0x17, 0x7b, + 0x1b, 0x8d, 0x6b, 0x6c, 0x1e, 0x2a, 0xad, 0x0d, 0xdc, 0xa1, 0x08, 0xc8, 0x08, 0x92, 0x83, 0x56, + 0xb7, 0x1b, 0x41, 0xb2, 0x06, 0x83, 0x86, 0x38, 0x5e, 0x44, 0x8f, 0xa3, 0x60, 0xca, 0x07, 0xb0, + 0xa0, 0xc1, 0x62, 0x4b, 0x4d, 0x9c, 0x47, 0xd3, 0x96, 0x1a, 0xea, 0xe5, 0x84, 0x31, 0x56, 0x61, + 0x59, 0x7c, 0xb6, 0xcf, 0xb8, 0x1b, 0x76, 0x27, 0x47, 0x14, 0x4a, 0x73, 0x3c, 0x57, 0xe8, 0xeb, + 0xe5, 0x08, 0x73, 0x35, 0x23, 0x3d, 0x90, 0x46, 0x5d, 0x16, 0xa7, 0x7f, 0x4d, 0x6b, 0x01, 0x0b, + 0x3e, 0xc0, 0x7f, 0x13, 0xc6, 0x5d, 0x39, 0x02, 0x89, 0xb1, 0x1e, 0xb4, 0xdb, 0xa6, 0xb5, 0xbf, + 0xb7, 0xd3, 0xd9, 0x13, 0xc2, 0x48, 0x8c, 0x15, 0x01, 0x5b, 0x5b, 0x08, 0xc9, 0x18, 0x0d, 0xa8, + 0x3f, 0xe1, 0x61, 0xc7, 0x3d, 0xf6, 0xd4, 0x48, 0x7f, 0x5e, 0x80, 0xf9, 0x08, 0x14, 0x1b, 0x87, + 0x67, 0xdc, 0x0f, 0x1c, 0xcf, 0x45, 0x3d, 0xaf, 0x6c, 0xaa, 0x4f, 0x71, 0x82, 0x38, 0x03, 0xee, + 0x86, 0x4e, 0x78, 0x69, 0x25, 0x3c, 0x49, 0x75, 0x05, 0x96, 0x27, 0xd5, 0x12, 0x14, 0xec, 0xa1, + 0x63, 0xab, 0x08, 0x24, 0x7d, 0x08, 0x68, 0xdf, 0x1b, 0x7a, 0x3e, 0xaa, 0x74, 0x65, 0x93, 0x3e, + 0xd8, 0x23, 0x58, 0x12, 0xaa, 0xa5, 0xee, 0xde, 0xc3, 0x3d, 0x4a, 0x4e, 0x2d, 0xe6, 0x4e, 0x46, + 0x07, 0xb1, 0x8b, 0x4f, 0x60, 0xc4, 0xf9, 0x24, 0x4a, 0x48, 0x85, 0x24, 0x2a, 0x40, 0x56, 0xca, + 0x82, 0x3b, 0x19, 0xb5, 0x10, 0x13, 0xd1, 0x3f, 0x86, 0x65, 0x41, 0x1f, 0xa9, 0x30, 0x51, 0x89, + 0x79, 0x2c, 0x21, 0x2a, 0xeb, 0x48, 0x5c, 0x54, 0xe6, 0x06, 0x94, 0xa9, 0x57, 0x62, 0xc5, 0x0b, + 0xa4, 0x9d, 0x62, 0x57, 0xb8, 0x1f, 0xcc, 0x04, 0x0b, 0xe7, 0xe8, 0xb0, 0x9d, 0x0a, 0x16, 0x6a, + 0xe1, 0xc6, 0xd2, 0x74, 0xb8, 0xf1, 0x31, 0x2c, 0x1f, 0xf1, 0x20, 0xb4, 0x4e, 0xb9, 0x3d, 0xe0, + 0x3e, 0xee, 0x48, 0x0a, 0x2b, 0x92, 0x16, 0xbe, 0x28, 0x90, 0xdb, 0x88, 0xeb, 0x29, 0x94, 0xd0, + 0x25, 0xc4, 0xd6, 0xe3, 0x03, 0x2b, 0xf4, 0x2c, 0x54, 0x31, 0x70, 0x13, 0x97, 0xcc, 0x1a, 0x81, + 0x7b, 0xde, 0x86, 0x00, 0x26, 0xe9, 0x4e, 0x7c, 0x7b, 0x7c, 0x2a, 0xf5, 0xe4, 0x88, 0xee, 0x89, + 0x00, 0xb2, 0x9b, 0x50, 0x0c, 0x79, 0x10, 0xba, 0x9c, 0x62, 0x3a, 0x25, 0xf4, 0xd9, 0x2b, 0x10, + 0x7b, 0x1d, 0xe6, 0xb0, 0x8d, 0xa0, 0xd9, 0x40, 0x7e, 0xaf, 0xc6, 0xc2, 0xd2, 0x71, 0x4d, 0x89, + 0x13, 0x0a, 0xdb, 0xc4, 0x77, 0x82, 0x66, 0x15, 0x63, 0x99, 0xf8, 0x37, 0xfb, 0x0d, 0x4d, 0x2c, + 0x2c, 0x62, 0x59, 0x75, 0xe6, 0x4e, 0x71, 0xda, 0xaf, 0x44, 0x42, 0x7c, 0x3f, 0x5f, 0xaa, 0x34, + 0xaa, 0xc6, 0x87, 0x50, 0xa0, 0xd9, 0x11, 0x4c, 0x88, 0x73, 0x97, 0x91, 0x4c, 0x88, 0xd0, 0x26, + 0x14, 0x5d, 0x1e, 0x9e, 0x7b, 0xfe, 0x33, 0xe5, 0x6b, 0x95, 0x9f, 0xc6, 0x4f, 0xd0, 0x49, 0x10, + 0x05, 0x92, 0xc9, 0xde, 0x11, 0xec, 0x41, 0xcb, 0x1b, 0x9c, 0xda, 0xd2, 0x6f, 0x51, 0x42, 0x40, + 0xf7, 0xd4, 0x9e, 0x61, 0x8f, 0xec, 0x6c, 0x2c, 0xf9, 0x75, 0xa8, 0xab, 0xd0, 0x75, 0x60, 0x0d, + 0xf9, 0x71, 0x28, 0xd9, 0xbd, 0x2a, 0xe3, 0xd6, 0xc1, 0x0e, 0x3f, 0x0e, 0x8d, 0x5d, 0x58, 0x90, + 0x0c, 0xb9, 0x3f, 0xe6, 0xaa, 0xe9, 0x8f, 0xd2, 0x74, 0xd6, 0xca, 0xe3, 0xc5, 0xe4, 0x61, 0x46, + 0x21, 0xf9, 0x84, 0x22, 0x6b, 0x7c, 0x0a, 0x4c, 0x3f, 0xea, 0x64, 0x7d, 0x52, 0x73, 0x54, 0x2e, + 0x6a, 0x15, 0xe9, 0x89, 0xf4, 0x53, 0x67, 0x20, 0x66, 0x27, 0x98, 0xf4, 0xfb, 0x2a, 0xa5, 0xa0, + 0x64, 0xaa, 0x4f, 0xe3, 0x4f, 0x33, 0xb0, 0x88, 0x95, 0x29, 0x9d, 0x5b, 0x6a, 0x13, 0xdf, 0xba, + 0x93, 0x62, 0x7d, 0x74, 0xfd, 0x82, 0x3e, 0xbe, 0xb9, 0x53, 0x30, 0x3f, 0xe3, 0x14, 0x7c, 0x13, + 0x1a, 0x03, 0x3e, 0x74, 0x30, 0xbb, 0x44, 0x1d, 0xd7, 0xa4, 0x65, 0xcf, 0x2b, 0xb8, 0x32, 0x94, + 0xfe, 0x49, 0x06, 0x16, 0x48, 0x1b, 0x40, 0x73, 0x51, 0x4e, 0xd4, 0x27, 0xca, 0xc6, 0x92, 0xa2, + 0x4a, 0x8e, 0x29, 0x3e, 0x25, 0x11, 0x4a, 0xc4, 0xdb, 0xd7, 0xa4, 0xed, 0x25, 0xa1, 0xec, 0x63, + 0xb4, 0x13, 0x5c, 0x0b, 0x81, 0x29, 0xd9, 0x2a, 0xc9, 0x45, 0xd9, 0xbe, 0x86, 0x46, 0x84, 0x8b, + 0xa0, 0xf5, 0x92, 0x30, 0xfa, 0x04, 0xd8, 0xd8, 0x82, 0x5a, 0xa2, 0x99, 0x84, 0xe7, 0xb2, 0x4a, + 0x9e, 0xcb, 0x99, 0xe8, 0x40, 0x76, 0x36, 0x3a, 0xf0, 0x77, 0xf2, 0xc0, 0x04, 0x4b, 0x4d, 0xad, + 0xda, 0x54, 0x68, 0x2d, 0x3b, 0x13, 0x5a, 0x7b, 0x04, 0x4c, 0x23, 0x50, 0x11, 0xbf, 0x5c, 0x14, + 0xf1, 0x6b, 0xc4, 0xb4, 0x32, 0xe0, 0xf7, 0x08, 0x96, 0xa4, 0xd2, 0x18, 0xc5, 0xd2, 0xd0, 0x25, + 0x45, 0xeb, 0xc3, 0x48, 0x7b, 0x54, 0x31, 0x35, 0x74, 0x4f, 0xa9, 0xb0, 0x9a, 0x30, 0xa9, 0xc9, + 0x93, 0x83, 0x61, 0x35, 0x61, 0x45, 0x4f, 0x71, 0xc1, 0xdc, 0x0b, 0xb9, 0xa0, 0x38, 0xc3, 0x05, + 0x9a, 0x63, 0xa1, 0x94, 0x74, 0x2c, 0x18, 0x50, 0x53, 0xc1, 0x33, 0xca, 0x19, 0x20, 0x0d, 0xa9, + 0x22, 0x23, 0x68, 0x98, 0x37, 0x70, 0x0f, 0x1a, 0xca, 0xfa, 0x8f, 0x5c, 0x17, 0x14, 0x0f, 0x97, + 0xce, 0xa3, 0x0d, 0xe5, 0xc0, 0x48, 0x38, 0x8a, 0x2b, 0x53, 0x8e, 0xe2, 0xb7, 0x60, 0x21, 0x10, + 0x4c, 0x64, 0x4d, 0x5c, 0x99, 0xbc, 0xc2, 0x07, 0x68, 0x9e, 0x94, 0xcc, 0x06, 0x22, 0x0e, 0x63, + 0xf8, 0xac, 0x69, 0x5f, 0x9b, 0x35, 0xed, 0xd9, 0xfb, 0x71, 0x9c, 0x29, 0x38, 0x75, 0x46, 0x78, + 0x70, 0xc7, 0x89, 0x1e, 0x72, 0x82, 0xbb, 0xa7, 0xce, 0xc8, 0x54, 0x41, 0x4d, 0xf1, 0x61, 0xfc, + 0xe7, 0x0c, 0x34, 0x04, 0x1f, 0x24, 0xf8, 0xfc, 0xd7, 0x00, 0x77, 0xe4, 0x4b, 0xb2, 0x79, 0x45, + 0xd0, 0x2a, 0x2e, 0xff, 0x10, 0x90, 0x6d, 0x2d, 0x61, 0x8b, 0x49, 0x26, 0x6f, 0x26, 0x99, 0x3c, + 0x16, 0x64, 0xdb, 0xd7, 0x48, 0xc9, 0x16, 0x90, 0xb4, 0xf8, 0x5e, 0x3e, 0x25, 0xbe, 0xa7, 0x6d, + 0x85, 0x6d, 0x80, 0xa7, 0xfc, 0x72, 0xc7, 0xeb, 0xa3, 0x15, 0x74, 0x0b, 0x40, 0x30, 0xe4, 0xb1, + 0x3d, 0x72, 0xa4, 0x07, 0xa3, 0x60, 0x96, 0x9f, 0xf1, 0xcb, 0x2d, 0x04, 0x88, 0xd5, 0x10, 0xe8, + 0x78, 0x3f, 0x14, 0xcc, 0xd2, 0x33, 0x7e, 0x49, 0x9b, 0xc1, 0x82, 0xda, 0x53, 0x7e, 0xb9, 0xc9, + 0x49, 0x5d, 0xf3, 0x7c, 0xc1, 0x09, 0xbe, 0x7d, 0x2e, 0xf4, 0xb3, 0x44, 0x6c, 0xae, 0xe2, 0xdb, + 0xe7, 0x4f, 0xf9, 0xa5, 0x8a, 0x13, 0x16, 0x05, 0x7e, 0xe8, 0xf5, 0xe5, 0x09, 0xa4, 0xb2, 0x0c, + 0xe2, 0x4e, 0x99, 0x73, 0xcf, 0xf0, 0x6f, 0xe3, 0x4f, 0x32, 0x50, 0x13, 0xfd, 0x47, 0x01, 0x27, + 0xe6, 0x5d, 0x25, 0xab, 0x64, 0xe2, 0x64, 0x95, 0xc7, 0x52, 0x3e, 0x90, 0xb4, 0xcc, 0x5e, 0x2d, + 0x2d, 0x71, 0x82, 0x49, 0x54, 0xbe, 0x0b, 0x65, 0xda, 0x5b, 0x62, 0xb3, 0xe6, 0x12, 0xab, 0x94, + 0x18, 0x90, 0x59, 0x42, 0xb2, 0xa7, 0x14, 0x1b, 0xd7, 0x1c, 0x50, 0x34, 0xc5, 0x65, 0x3f, 0x72, + 0x3d, 0xa5, 0x2c, 0x43, 0x21, 0x2d, 0xcc, 0x7a, 0x08, 0x15, 0x8d, 0xa7, 0xd8, 0xf7, 0x28, 0x40, + 0x4d, 0x9d, 0x27, 0x06, 0x4c, 0x32, 0x4d, 0x62, 0xf4, 0xdb, 0xd7, 0xcc, 0x5a, 0x5f, 0x07, 0xac, + 0xcf, 0x41, 0x5e, 0x14, 0x32, 0x3e, 0x81, 0x05, 0xad, 0x5a, 0xb2, 0xf8, 0xd2, 0xfa, 0x94, 0x49, + 0xeb, 0xd3, 0x3f, 0xcd, 0xc0, 0x92, 0x2c, 0x8d, 0x89, 0x4d, 0x8e, 0x38, 0xae, 0x77, 0x83, 0x13, + 0xf6, 0x6b, 0x50, 0x13, 0xb5, 0x5b, 0x3e, 0x3f, 0x71, 0x82, 0x90, 0x2b, 0xcf, 0x7e, 0xca, 0xe6, + 0x10, 0x52, 0x5b, 0x90, 0x9a, 0x92, 0x92, 0x7d, 0x02, 0x15, 0x2c, 0x4a, 0x36, 0xa9, 0x5c, 0x96, + 0xe6, 0x6c, 0x41, 0xea, 0xea, 0xf6, 0x35, 0x13, 0x82, 0xe8, 0x6b, 0xbd, 0x0c, 0xc5, 0xd0, 0x77, + 0x4e, 0x4e, 0xb8, 0x6f, 0xac, 0x44, 0x5d, 0x13, 0x3b, 0x8d, 0x77, 0x43, 0x3e, 0x16, 0x4a, 0x90, + 0xf1, 0xdf, 0x32, 0x50, 0x91, 0x7b, 0xe7, 0x5b, 0xbb, 0xf3, 0xd7, 0xb4, 0xcc, 0x3c, 0x32, 0x3f, + 0xe3, 0x44, 0xbc, 0xbb, 0x30, 0x3f, 0x12, 0x0a, 0x91, 0x50, 0xd8, 0x13, 0xbe, 0xfc, 0xba, 0x02, + 0x4b, 0x7d, 0xe4, 0x01, 0x2c, 0xa2, 0x7a, 0x12, 0x58, 0xa1, 0x33, 0xb4, 0x14, 0x52, 0x66, 0xc1, + 0x2d, 0x10, 0xaa, 0xe7, 0x0c, 0x77, 0x25, 0x42, 0x9c, 0xd2, 0x41, 0x68, 0x9f, 0x70, 0xa9, 0xfa, + 0xd2, 0x87, 0xd1, 0x84, 0x95, 0x29, 0x5d, 0x5d, 0xd9, 0x19, 0x7f, 0xbf, 0x06, 0xab, 0x33, 0x28, + 0x69, 0x6f, 0x44, 0x3e, 0xec, 0xa1, 0x33, 0x3a, 0xf2, 0x22, 0x77, 0x53, 0x46, 0xf3, 0x61, 0xef, + 0x08, 0x8c, 0x72, 0x37, 0x71, 0x58, 0x56, 0x0c, 0x81, 0xfe, 0xa2, 0x48, 0x9d, 0xcf, 0xa2, 0xb2, + 0xf9, 0x6e, 0x52, 0x50, 0x4d, 0x37, 0xa7, 0xe0, 0xfa, 0xf1, 0xb7, 0x38, 0x9e, 0x81, 0x05, 0xec, + 0x18, 0x9a, 0x11, 0xdf, 0x49, 0xfd, 0x48, 0xb3, 0x4d, 0x44, 0x4b, 0x6f, 0xbf, 0xa0, 0xa5, 0x84, + 0x23, 0xc2, 0x5c, 0x51, 0xec, 0x4a, 0x95, 0x45, 0xed, 0x9c, 0xc1, 0x2b, 0xaa, 0x1d, 0xd4, 0x75, + 0x66, 0x5b, 0xcb, 0xbf, 0xd4, 0xb8, 0xd0, 0xc1, 0x92, 0x6c, 0xf2, 0x86, 0xac, 0x38, 0x42, 0xe9, + 0xed, 0x9e, 0xc2, 0xca, 0xb9, 0xed, 0x84, 0x6a, 0x7c, 0x9a, 0x59, 0x54, 0xc0, 0xf6, 0x1e, 0xbf, + 0xa0, 0xbd, 0xcf, 0xa9, 0x70, 0x42, 0xfb, 0x5b, 0x3a, 0x9f, 0x05, 0x06, 0x6b, 0xff, 0x31, 0x0b, + 0xf5, 0x64, 0x2d, 0x62, 0x53, 0x4b, 0x39, 0xa4, 0xf4, 0x09, 0xa9, 0x8f, 0x4b, 0x37, 0xe8, 0x1e, + 0xe9, 0x11, 0xb3, 0x0e, 0xda, 0x6c, 0x8a, 0x83, 0x56, 0xf7, 0x8b, 0xe6, 0x5e, 0x14, 0xfb, 0xc9, + 0xbf, 0x54, 0xec, 0xa7, 0x90, 0x16, 0xfb, 0xb9, 0x3a, 0x60, 0x30, 0xf7, 0xad, 0x02, 0x06, 0xc5, + 0xab, 0x03, 0x06, 0x6b, 0x7f, 0x99, 0x01, 0x36, 0xcb, 0xa9, 0xec, 0x09, 0xf9, 0xa2, 0x5d, 0x3e, + 0x94, 0x52, 0xec, 0x9d, 0x97, 0xe3, 0x76, 0xb5, 0x40, 0xaa, 0x34, 0x7b, 0x08, 0x8b, 0x7a, 0xde, + 0xac, 0x6e, 0xaa, 0xd4, 0x4c, 0xa6, 0xa3, 0x62, 0x83, 0x56, 0x0b, 0x7c, 0xe5, 0x5f, 0x18, 0xf8, + 0x2a, 0xbc, 0x30, 0xf0, 0x35, 0x97, 0x0c, 0x7c, 0xad, 0xfd, 0xad, 0x0c, 0x2c, 0xa6, 0x30, 0xd5, + 0x2f, 0x6f, 0xcc, 0x82, 0x17, 0x12, 0x22, 0x26, 0x2b, 0x79, 0x41, 0x93, 0x2e, 0x6b, 0x5f, 0x41, + 0x2d, 0xb1, 0x89, 0x7e, 0x79, 0xcd, 0x4f, 0x1b, 0x5a, 0xc4, 0xca, 0xba, 0xa1, 0xb5, 0xf6, 0x17, + 0x59, 0x60, 0xb3, 0xfb, 0xf8, 0x57, 0xd9, 0x85, 0xd9, 0x49, 0xca, 0xcd, 0x4e, 0xd2, 0xff, 0xbf, + 0x73, 0xe5, 0x2d, 0x58, 0x90, 0xb9, 0xfe, 0x5a, 0xe0, 0x81, 0x18, 0xa5, 0x11, 0x21, 0x54, 0x2f, + 0x3e, 0x9c, 0x8e, 0x39, 0x96, 0x12, 0xe9, 0xcd, 0xda, 0xc1, 0x9a, 0x0c, 0x3d, 0x1a, 0x6b, 0xd0, + 0x94, 0x53, 0x33, 0xeb, 0xaa, 0xfb, 0xdd, 0x7c, 0x64, 0x25, 0x23, 0x52, 0x2a, 0xc5, 0xdf, 0x85, + 0xaa, 0x7e, 0xd8, 0xc8, 0x75, 0x98, 0x8a, 0x38, 0x09, 0x75, 0xd8, 0xd3, 0x76, 0xeb, 0x06, 0x50, + 0x1c, 0x61, 0x10, 0x15, 0x23, 0x0d, 0xe2, 0x39, 0x8e, 0x67, 0x54, 0x8e, 0x12, 0x8b, 0xff, 0x57, + 0xa0, 0x9e, 0xf4, 0x5b, 0x49, 0x55, 0x2f, 0x4d, 0x3b, 0x14, 0xa5, 0x13, 0x8e, 0x2c, 0xf6, 0x1b, + 0xd0, 0x98, 0xf6, 0x7b, 0xc9, 0xdc, 0xcb, 0x2b, 0xca, 0xcf, 0x3b, 0x49, 0x57, 0x18, 0xdb, 0x86, + 0xa5, 0xb4, 0xe3, 0x16, 0x57, 0xe5, 0x6a, 0xb3, 0x80, 0xcd, 0x1e, 0xa9, 0xec, 0x23, 0xe9, 0xde, + 0x2c, 0xa4, 0x05, 0x62, 0xb4, 0xc9, 0x7e, 0x40, 0xff, 0x69, 0x8e, 0xce, 0x33, 0x80, 0x18, 0xc6, + 0x1a, 0x50, 0xdd, 0x3f, 0x68, 0xef, 0x59, 0x1b, 0xdb, 0xad, 0xbd, 0xbd, 0xf6, 0x4e, 0xe3, 0x1a, + 0x63, 0x50, 0xc7, 0x08, 0xca, 0x66, 0x04, 0xcb, 0x08, 0x98, 0xf4, 0xfd, 0x2a, 0x58, 0x96, 0x2d, + 0x41, 0xa3, 0xb3, 0x37, 0x05, 0xcd, 0xb1, 0x26, 0x2c, 0x1d, 0xb4, 0x29, 0xe8, 0x92, 0xa8, 0x37, + 0x2f, 0x54, 0x38, 0x39, 0x5c, 0xa1, 0xc2, 0xd1, 0x4d, 0x11, 0xc9, 0x7d, 0x4a, 0xb3, 0xf9, 0xbd, + 0x0c, 0x2c, 0x4f, 0x21, 0xe2, 0xfc, 0x5f, 0xd2, 0x6b, 0x92, 0x1a, 0x4d, 0x15, 0x81, 0x8a, 0x87, + 0xdf, 0x82, 0x85, 0xc8, 0xd4, 0x9b, 0x92, 0x4b, 0x8d, 0x08, 0xa1, 0x88, 0x1f, 0xc2, 0xa2, 0x66, + 0x31, 0x4e, 0xed, 0x50, 0xa6, 0xa1, 0x64, 0x01, 0x63, 0x35, 0xca, 0xb3, 0x9c, 0xea, 0xf5, 0x80, + 0xae, 0x9f, 0xe8, 0x88, 0xd8, 0xfb, 0x9b, 0xec, 0xaf, 0xfa, 0x14, 0xa6, 0x7c, 0x82, 0x11, 0x92, + 0xbd, 0xd5, 0x17, 0x5c, 0x35, 0xff, 0x07, 0x73, 0xc0, 0x3e, 0x9d, 0x70, 0xff, 0x12, 0xf3, 0x7b, + 0x83, 0x17, 0x25, 0xbc, 0x28, 0xb3, 0x28, 0xfb, 0x52, 0x39, 0xfc, 0x69, 0x39, 0xf4, 0xf9, 0x17, + 0xe7, 0xd0, 0x17, 0x5e, 0x94, 0x43, 0xff, 0x1a, 0xd4, 0x9c, 0x13, 0xd7, 0x13, 0x02, 0x48, 0xe8, + 0x26, 0x41, 0x73, 0xee, 0x4e, 0xee, 0x5e, 0xd5, 0xac, 0x4a, 0xa0, 0xd0, 0x4c, 0x02, 0xf6, 0x49, + 0x4c, 0xc4, 0x07, 0x27, 0x78, 0xdf, 0x43, 0x17, 0x3d, 0xed, 0xc1, 0x09, 0x97, 0x56, 0x20, 0xfa, + 0x45, 0x54, 0x61, 0x01, 0x0f, 0xd8, 0xeb, 0x50, 0x0f, 0xbc, 0x89, 0x50, 0xf5, 0xd4, 0x34, 0x90, + 0x7f, 0xb8, 0x4a, 0xd0, 0x03, 0x15, 0x0c, 0x58, 0x9c, 0x04, 0xdc, 0x1a, 0x39, 0x41, 0x20, 0x0e, + 0xe8, 0xbe, 0xe7, 0x86, 0xbe, 0x37, 0x94, 0x2e, 0xdf, 0x85, 0x49, 0xc0, 0x77, 0x09, 0xb3, 0x41, + 0x08, 0xf6, 0x5e, 0xdc, 0xa5, 0xb1, 0xed, 0xf8, 0x41, 0x13, 0xb0, 0x4b, 0x6a, 0xa4, 0xa8, 0x51, + 0xd9, 0x8e, 0x1f, 0xf5, 0x45, 0x7c, 0x04, 0x53, 0xb9, 0xfd, 0x95, 0xe9, 0xdc, 0xfe, 0x1f, 0xa7, + 0xe7, 0xf6, 0xd7, 0xb0, 0xea, 0x47, 0xb2, 0xea, 0xd9, 0x25, 0xfe, 0x46, 0x29, 0xfe, 0xb3, 0x57, + 0x16, 0xea, 0xdf, 0xe4, 0xca, 0xc2, 0x7c, 0xda, 0x95, 0x85, 0x77, 0xa1, 0x82, 0xc9, 0xe4, 0xd6, + 0xa9, 0xe3, 0x86, 0xca, 0x85, 0xdd, 0xd0, 0xb3, 0xcd, 0xb7, 0x85, 0x31, 0x0d, 0xbe, 0xfa, 0x33, + 0x98, 0xbd, 0x3d, 0xb0, 0xf0, 0x2b, 0xbc, 0x3d, 0x20, 0x93, 0xde, 0x1f, 0x40, 0x49, 0xad, 0x13, + 0x63, 0x90, 0x3f, 0xf6, 0xbd, 0x91, 0x72, 0xed, 0x89, 0xbf, 0x59, 0x1d, 0xb2, 0xa1, 0x27, 0x0b, + 0x67, 0x43, 0xcf, 0xf8, 0x4d, 0xa8, 0x68, 0xac, 0xc6, 0x5e, 0x25, 0x27, 0x82, 0xd0, 0x96, 0xa5, + 0x95, 0x4c, 0xb3, 0x58, 0x96, 0xd0, 0xce, 0x40, 0xc8, 0x9b, 0x81, 0xe3, 0x73, 0xbc, 0xe7, 0x63, + 0xf9, 0xfc, 0x8c, 0xfb, 0x81, 0x72, 0xb5, 0x36, 0x22, 0x84, 0x49, 0x70, 0xe3, 0xaf, 0xc3, 0x62, + 0x62, 0x6d, 0xa5, 0x88, 0x78, 0x1d, 0xe6, 0x70, 0xde, 0x54, 0x28, 0x2c, 0x99, 0xc5, 0x2f, 0x71, + 0x78, 0x81, 0x93, 0xbc, 0xc4, 0xd6, 0xd8, 0xf7, 0x8e, 0xb0, 0x91, 0x8c, 0x59, 0x91, 0xb0, 0x03, + 0xdf, 0x3b, 0x32, 0x7e, 0x96, 0x83, 0xdc, 0xb6, 0x37, 0xd6, 0x33, 0x2c, 0x32, 0x33, 0x19, 0x16, + 0xd2, 0x04, 0xb0, 0x22, 0x15, 0x5f, 0x6a, 0x6d, 0xe8, 0x1f, 0x55, 0x6a, 0xfe, 0x3d, 0xa8, 0x0b, + 0x39, 0x11, 0x7a, 0xc2, 0x86, 0x3a, 0xb7, 0x7d, 0xca, 0xe9, 0xcf, 0xd1, 0xe6, 0xb3, 0x47, 0x61, + 0xcf, 0xdb, 0x22, 0x38, 0x5b, 0x82, 0x5c, 0xa4, 0xc0, 0x22, 0x5a, 0x7c, 0x0a, 0xe3, 0x1a, 0xb3, + 0xdb, 0x2e, 0x65, 0xac, 0x47, 0x7e, 0xb1, 0x77, 0x60, 0x31, 0x59, 0x2f, 0x89, 0x22, 0xa9, 0x91, + 0xe8, 0x15, 0xa3, 0x4c, 0xba, 0x0e, 0x42, 0x8e, 0x10, 0x8d, 0x0c, 0xcb, 0x1e, 0x73, 0x8e, 0x28, + 0x4d, 0xe8, 0x95, 0x12, 0x42, 0xef, 0x36, 0x54, 0xc2, 0xe1, 0x99, 0x35, 0xb6, 0x2f, 0x87, 0x9e, + 0x3d, 0x90, 0xfb, 0x1b, 0xc2, 0xe1, 0xd9, 0x01, 0x41, 0xd8, 0x43, 0x80, 0xd1, 0x78, 0x2c, 0xf7, + 0x1e, 0xba, 0x1b, 0x63, 0x56, 0xde, 0x3d, 0x38, 0x20, 0x96, 0x33, 0xcb, 0xa3, 0xf1, 0x98, 0xfe, + 0x64, 0x9b, 0x50, 0x4f, 0xbd, 0x8b, 0x73, 0x4b, 0x25, 0x63, 0x79, 0xe3, 0x07, 0x29, 0x9b, 0xb3, + 0xd6, 0xd7, 0x61, 0x6b, 0xbf, 0x01, 0xec, 0x17, 0xbc, 0x11, 0xd3, 0x83, 0x72, 0xd4, 0x3f, 0xfd, + 0x42, 0x09, 0xa6, 0x57, 0x56, 0x12, 0x17, 0x4a, 0x5a, 0x83, 0x81, 0x2f, 0xe4, 0x22, 0x1d, 0x98, + 0x91, 0xc8, 0x07, 0xed, 0xc4, 0x6c, 0x91, 0xdc, 0x37, 0xfe, 0x3c, 0x03, 0x05, 0xba, 0xdd, 0xf2, + 0x06, 0xcc, 0x13, 0x7d, 0x94, 0xad, 0x22, 0x23, 0x44, 0x74, 0xee, 0xf6, 0x64, 0xa2, 0x8a, 0xd8, + 0x16, 0xda, 0xcd, 0xbc, 0x6c, 0xb4, 0xf2, 0xda, 0xed, 0xbc, 0xdb, 0x50, 0x8e, 0x9a, 0xd6, 0x58, + 0xa7, 0xa4, 0x5a, 0x66, 0xaf, 0x40, 0xfe, 0xd4, 0x1b, 0x2b, 0x5b, 0x1c, 0xe2, 0x99, 0x34, 0x11, + 0x1e, 0xf7, 0x45, 0xb4, 0x41, 0x9d, 0x97, 0x36, 0x64, 0xd4, 0x08, 0xb2, 0xc1, 0xec, 0x18, 0xe7, + 0x52, 0xc6, 0x78, 0x08, 0xf3, 0x42, 0x0e, 0x68, 0x91, 0xda, 0xab, 0x0f, 0xcd, 0x37, 0x85, 0x86, + 0xd7, 0x1f, 0x4e, 0x06, 0x5c, 0xf7, 0x84, 0x60, 0xea, 0x84, 0x84, 0x2b, 0xf3, 0xc0, 0xf8, 0x83, + 0x0c, 0xc9, 0x17, 0x51, 0x2f, 0xbb, 0x07, 0x79, 0x71, 0xbe, 0x4d, 0x79, 0xea, 0xa2, 0x3c, 0x57, + 0x41, 0x67, 0x22, 0x05, 0x5e, 0x67, 0x9d, 0x8c, 0x92, 0xb5, 0xd7, 0xcc, 0x8a, 0x3b, 0x19, 0x45, + 0xce, 0x84, 0xef, 0xa8, 0x61, 0x4d, 0x19, 0xe2, 0x34, 0xfa, 0x68, 0x9b, 0x3e, 0xd0, 0x72, 0x30, + 0xf2, 0x89, 0x13, 0x53, 0x69, 0x81, 0x83, 0x13, 0xae, 0xe5, 0x5e, 0xfc, 0x51, 0x16, 0x6a, 0x89, + 0x1e, 0x61, 0x12, 0x8a, 0x38, 0x00, 0xc8, 0x0b, 0x2c, 0xd7, 0x1b, 0x04, 0x48, 0x2a, 0xea, 0xda, + 0x3c, 0x65, 0x13, 0xf3, 0x14, 0xc5, 0xa4, 0x73, 0x7a, 0x4c, 0xfa, 0x11, 0x94, 0xe3, 0x1b, 0x99, + 0xc9, 0x2e, 0x89, 0xf6, 0x54, 0xb6, 0x6f, 0x4c, 0x14, 0x47, 0xb1, 0x0b, 0x7a, 0x14, 0xfb, 0x7b, + 0x5a, 0xd0, 0x73, 0x0e, 0xab, 0x31, 0xd2, 0x66, 0xf4, 0x57, 0x93, 0x14, 0xf1, 0x09, 0x54, 0xb4, + 0xce, 0xeb, 0xc1, 0xcd, 0x4c, 0x22, 0xb8, 0x19, 0xe5, 0xe5, 0x67, 0xe3, 0xbc, 0x7c, 0xe3, 0xb7, + 0xb3, 0x50, 0x13, 0xfb, 0xcb, 0x71, 0x4f, 0x0e, 0xbc, 0xa1, 0xd3, 0x47, 0xaf, 0x70, 0xb4, 0xc3, + 0xa4, 0xa2, 0xa5, 0xf6, 0x99, 0xdc, 0x62, 0xa4, 0x67, 0xe9, 0xd7, 0x8f, 0x48, 0x48, 0x47, 0xd7, + 0x8f, 0x0c, 0xa8, 0x09, 0xc1, 0x78, 0x64, 0x07, 0x5c, 0xbb, 0x2f, 0x6a, 0x56, 0x8e, 0x39, 0x5f, + 0xb7, 0x03, 0x92, 0x90, 0xef, 0xc0, 0xa2, 0xa0, 0xc1, 0x9b, 0x17, 0x23, 0x67, 0x38, 0x74, 0x88, + 0x92, 0x5c, 0x0d, 0x8d, 0x63, 0xce, 0x4d, 0x3b, 0xe4, 0xbb, 0x02, 0x21, 0xaf, 0x97, 0x96, 0x06, + 0x4e, 0x60, 0x1f, 0xc5, 0xa9, 0x42, 0xd1, 0x37, 0xc6, 0x72, 0xec, 0x0b, 0x2d, 0x96, 0x43, 0x57, + 0xb0, 0x2a, 0x23, 0xfb, 0x22, 0x8a, 0xe5, 0x4c, 0x71, 0x52, 0x71, 0x9a, 0x93, 0x8c, 0xff, 0x92, + 0x85, 0x8a, 0xc6, 0x96, 0x2f, 0x73, 0xba, 0xde, 0x9a, 0xf1, 0xe2, 0x97, 0x75, 0x87, 0xfd, 0x6b, + 0xc9, 0x26, 0x31, 0xe4, 0x4b, 0x17, 0x59, 0x35, 0x06, 0xbe, 0x01, 0x65, 0xb1, 0xeb, 0xde, 0x45, + 0xa7, 0x98, 0xbc, 0x86, 0x8d, 0x80, 0x83, 0xc9, 0x91, 0x42, 0x3e, 0x46, 0x64, 0x21, 0x46, 0x3e, + 0x16, 0xc8, 0xe7, 0xe5, 0x07, 0x7e, 0x08, 0x55, 0x59, 0x2b, 0xae, 0x29, 0x0e, 0x37, 0xde, 0xf5, + 0x89, 0xf5, 0x36, 0x2b, 0xd4, 0x1c, 0x2d, 0xbe, 0x2c, 0xf8, 0x58, 0x15, 0x2c, 0xbd, 0xa8, 0xe0, + 0x63, 0xfa, 0x30, 0xb6, 0xa2, 0x94, 0x4b, 0x4c, 0x37, 0x50, 0x72, 0xec, 0x21, 0x2c, 0x2a, 0x71, + 0x35, 0x71, 0x6d, 0xd7, 0xf5, 0x26, 0x6e, 0x9f, 0xab, 0x84, 0x7d, 0x26, 0x51, 0x87, 0x31, 0xc6, + 0x18, 0x44, 0x37, 0xba, 0x28, 0x6d, 0xe1, 0x3e, 0x14, 0x48, 0x2f, 0x27, 0xe5, 0x23, 0x5d, 0x70, + 0x11, 0x09, 0xbb, 0x07, 0x05, 0x52, 0xcf, 0xb3, 0x57, 0x0a, 0x1b, 0x22, 0x30, 0x1e, 0xc0, 0x3c, + 0xaa, 0x98, 0x9a, 0xc4, 0x7d, 0x9e, 0x56, 0x62, 0x2c, 0x01, 0xdb, 0xa3, 0x4d, 0xa4, 0xa7, 0xd3, + 0xfc, 0xcf, 0x1c, 0x54, 0x34, 0xb0, 0x10, 0x8b, 0x98, 0x80, 0x61, 0x0d, 0x1c, 0x7b, 0xc4, 0x55, + 0xec, 0xa1, 0x66, 0xd6, 0x10, 0xba, 0x29, 0x81, 0xe2, 0x50, 0xb0, 0xcf, 0x4e, 0x2c, 0x6f, 0x12, + 0x5a, 0x03, 0x7e, 0xe2, 0x73, 0x2e, 0x95, 0xa5, 0xaa, 0x7d, 0x76, 0xb2, 0x3f, 0x09, 0x37, 0x11, + 0x26, 0xa8, 0x04, 0x53, 0x6b, 0x54, 0x32, 0x67, 0x60, 0x64, 0x5f, 0xc4, 0x54, 0x32, 0x71, 0x85, + 0xa6, 0x28, 0x1f, 0x25, 0xae, 0x90, 0xd9, 0x32, 0x2d, 0xc9, 0x0b, 0xb3, 0x92, 0xfc, 0x3d, 0x58, + 0x21, 0x49, 0x2e, 0x65, 0x84, 0x35, 0xc5, 0x52, 0x4b, 0x88, 0x95, 0x83, 0xd4, 0xf4, 0xaf, 0x86, + 0x18, 0x81, 0xda, 0x1f, 0x81, 0xf3, 0x13, 0xda, 0x51, 0x19, 0x53, 0x8c, 0x4c, 0x56, 0xde, 0x75, + 0x7e, 0xc2, 0x05, 0x25, 0x06, 0x46, 0x75, 0x4a, 0x99, 0x86, 0x3a, 0x72, 0xdc, 0x69, 0x4a, 0xfb, + 0x22, 0x49, 0x59, 0x96, 0x94, 0xf6, 0x85, 0x4e, 0xf9, 0x3e, 0xac, 0x8e, 0xf8, 0xc0, 0xb1, 0x93, + 0xd5, 0x5a, 0xb1, 0x06, 0xb1, 0x44, 0x68, 0xad, 0x4c, 0x97, 0x2c, 0x48, 0x31, 0x1b, 0x3f, 0xf1, + 0x46, 0x47, 0x0e, 0x1d, 0x9e, 0x14, 0xaa, 0xcd, 0x9b, 0x75, 0x77, 0x32, 0xfa, 0x21, 0x82, 0x45, + 0x91, 0xc0, 0xa8, 0x41, 0xa5, 0x1b, 0x7a, 0x63, 0xb5, 0xcc, 0x75, 0xa8, 0xd2, 0xa7, 0xbc, 0x8e, + 0x71, 0x03, 0xae, 0x23, 0x6f, 0xf6, 0xbc, 0xb1, 0x37, 0xf4, 0x4e, 0x2e, 0x13, 0x0e, 0xa5, 0xff, + 0x9e, 0x81, 0xc5, 0x04, 0x56, 0xee, 0xf3, 0xf7, 0x68, 0x63, 0x45, 0x39, 0xf5, 0xc4, 0xce, 0x0b, + 0xda, 0xe1, 0x43, 0x84, 0xb4, 0xab, 0x54, 0x9e, 0x7d, 0x2b, 0xbe, 0x0b, 0xaa, 0x0a, 0x12, 0x6f, + 0x37, 0x67, 0x79, 0x5b, 0x96, 0x57, 0xb7, 0x44, 0x55, 0x15, 0x7f, 0x55, 0xa6, 0x0a, 0x0f, 0xe4, + 0x90, 0x73, 0xc9, 0x64, 0x48, 0xdd, 0xf9, 0xa4, 0x7a, 0x10, 0x7b, 0xa4, 0x02, 0xe3, 0x5f, 0x65, + 0x00, 0xe2, 0xde, 0x61, 0x3a, 0x66, 0x74, 0x80, 0xd2, 0x33, 0x2b, 0xda, 0x61, 0xf9, 0x2a, 0x54, + 0xa3, 0x8c, 0xb1, 0xf8, 0x48, 0xae, 0x28, 0x98, 0x38, 0x97, 0xef, 0xc2, 0xfc, 0xc9, 0xd0, 0x3b, + 0x42, 0xd5, 0x49, 0x1e, 0xa0, 0x74, 0x29, 0xa5, 0x4e, 0x60, 0x75, 0x2c, 0xc6, 0x07, 0x78, 0x3e, + 0x35, 0xa9, 0x4c, 0x3f, 0x8e, 0x8d, 0xdf, 0xc9, 0x46, 0xa9, 0x33, 0xf1, 0x4c, 0x3c, 0xdf, 0xce, + 0xf8, 0x36, 0x11, 0xd8, 0xe7, 0x45, 0x1e, 0x3e, 0x81, 0xba, 0x4f, 0xd2, 0x51, 0x89, 0xce, 0xfc, + 0x73, 0x44, 0x67, 0xcd, 0x4f, 0x1c, 0xb9, 0x6f, 0x42, 0xc3, 0x1e, 0x9c, 0x71, 0x3f, 0x74, 0xd0, + 0x59, 0x8b, 0x8a, 0x9a, 0x4c, 0x56, 0xd1, 0xe0, 0xa8, 0x11, 0xdd, 0x85, 0x79, 0x79, 0x45, 0x28, + 0xa2, 0x94, 0x8f, 0x0e, 0xc4, 0x60, 0x41, 0x68, 0xfc, 0x5b, 0x95, 0xab, 0x93, 0x5c, 0xdd, 0xe7, + 0xcf, 0x8a, 0x3e, 0xc2, 0xec, 0x6c, 0x6c, 0x45, 0x32, 0x92, 0xf4, 0x01, 0x4b, 0x79, 0x44, 0x40, + 0xe9, 0x01, 0x4e, 0x4e, 0x6b, 0xfe, 0x65, 0xa6, 0xd5, 0xf8, 0x93, 0x0c, 0x14, 0xb7, 0xbd, 0xb1, + 0xb0, 0xcb, 0x85, 0x3e, 0x87, 0xdb, 0x24, 0xba, 0x9e, 0x37, 0x27, 0x3e, 0x3b, 0x83, 0xe7, 0xa7, + 0xe5, 0xa7, 0xea, 0x1b, 0xb5, 0xa4, 0xbe, 0xf1, 0x3d, 0xb8, 0x81, 0xd1, 0x08, 0xdf, 0x1b, 0x7b, + 0xbe, 0xd8, 0xaa, 0xf6, 0x90, 0xf4, 0x0e, 0xcf, 0x0d, 0x4f, 0x95, 0xec, 0xbc, 0x7e, 0xcc, 0xf9, + 0x81, 0x46, 0xb1, 0x1b, 0x11, 0xe0, 0x5d, 0x93, 0x61, 0x78, 0x66, 0x91, 0xa9, 0x28, 0x15, 0x23, + 0x92, 0xa8, 0xf3, 0x02, 0xd1, 0x46, 0x38, 0xaa, 0x46, 0xc6, 0x47, 0x50, 0x8e, 0xbc, 0x0e, 0xec, + 0x2d, 0x28, 0x9f, 0x7a, 0x63, 0xe9, 0x9a, 0xc8, 0x24, 0xae, 0x2e, 0xc8, 0x51, 0x9b, 0xa5, 0x53, + 0xfa, 0x23, 0x30, 0x7e, 0x56, 0x84, 0x62, 0xc7, 0x3d, 0xf3, 0x9c, 0x3e, 0x66, 0xfb, 0x8c, 0xf8, + 0xc8, 0x53, 0xf7, 0x14, 0xc5, 0xdf, 0x18, 0xd1, 0x8f, 0x9f, 0x0e, 0xc8, 0xc9, 0x88, 0x7e, 0xf4, + 0x68, 0xc0, 0x32, 0xcc, 0xf9, 0xfa, 0xdd, 0xff, 0x82, 0x8f, 0xf9, 0x87, 0x91, 0xd1, 0x56, 0xd0, + 0xee, 0x79, 0x8a, 0xba, 0xe8, 0x4e, 0x3a, 0x4e, 0x19, 0xdd, 0x3d, 0x29, 0x23, 0x04, 0x27, 0xec, + 0x26, 0x14, 0xe5, 0x4d, 0x01, 0xca, 0xbb, 0xa6, 0x84, 0x41, 0x09, 0x42, 0x6e, 0xf0, 0x39, 0x45, + 0x93, 0x22, 0x8d, 0x4a, 0xd8, 0xe9, 0x12, 0xb8, 0x29, 0x78, 0xed, 0x36, 0x54, 0x88, 0x9e, 0x48, + 0x4a, 0x32, 0x3f, 0x07, 0x41, 0x48, 0x90, 0xf2, 0x84, 0x46, 0x39, 0xf5, 0x09, 0x0d, 0x4c, 0xe7, + 0x8a, 0xa4, 0x2c, 0x0d, 0x11, 0xe8, 0xe1, 0x04, 0x0d, 0xae, 0xde, 0x8f, 0x91, 0xc6, 0x3d, 0x5d, + 0xa3, 0x52, 0xc6, 0xfd, 0x6b, 0x50, 0x3b, 0xb6, 0x87, 0xc3, 0x23, 0xbb, 0xff, 0x8c, 0x6c, 0xd2, + 0x2a, 0xb9, 0xe1, 0x14, 0x10, 0x8d, 0xd2, 0xdb, 0x50, 0xd1, 0x56, 0x19, 0x93, 0x6f, 0xf2, 0x26, + 0xc4, 0xeb, 0x3b, 0xed, 0x6a, 0xaa, 0xbf, 0x84, 0xab, 0x49, 0x4b, 0x42, 0x9a, 0x4f, 0x26, 0x21, + 0xdd, 0x40, 0x69, 0x2a, 0x13, 0x55, 0x1a, 0x74, 0x4b, 0xdf, 0x1e, 0x0c, 0x30, 0x51, 0x85, 0x9e, + 0xc4, 0xc2, 0xc9, 0x23, 0xfc, 0x02, 0x29, 0xb5, 0x04, 0x23, 0x92, 0x5b, 0xe4, 0x2f, 0x1d, 0xdb, + 0xce, 0x00, 0x93, 0x3e, 0xc9, 0x8c, 0x2d, 0xda, 0xa3, 0xf0, 0xc0, 0x76, 0x06, 0xec, 0x0e, 0x54, + 0x15, 0x1a, 0x4f, 0xc7, 0x45, 0x9a, 0x7f, 0x89, 0x16, 0x67, 0xa2, 0x01, 0xb5, 0x88, 0x62, 0x14, + 0xdf, 0x85, 0xaa, 0x48, 0x12, 0xe4, 0x83, 0x77, 0x31, 0xf8, 0x1f, 0x72, 0xbc, 0xf1, 0x54, 0x7f, + 0x7c, 0x43, 0x8e, 0x55, 0x72, 0xa9, 0xfa, 0x1f, 0x33, 0x1d, 0x4c, 0xa2, 0x14, 0x8a, 0x18, 0x85, + 0x68, 0x56, 0x12, 0x8a, 0x98, 0x24, 0xc5, 0x10, 0x0d, 0x11, 0xb0, 0x8f, 0x34, 0x43, 0xaa, 0x89, + 0xc4, 0x37, 0xa7, 0xea, 0xbf, 0xc2, 0x84, 0x12, 0xdc, 0xeb, 0x04, 0xe2, 0x94, 0x09, 0xb8, 0x3b, + 0xc0, 0x0b, 0x50, 0x25, 0xb3, 0xec, 0x04, 0x4f, 0x09, 0xf0, 0xcb, 0xb5, 0xb0, 0x5a, 0x50, 0xd5, + 0x87, 0xc9, 0x4a, 0x90, 0xdf, 0x3f, 0x68, 0xef, 0x35, 0xae, 0xb1, 0x0a, 0x14, 0xbb, 0xed, 0x5e, + 0x6f, 0xa7, 0xbd, 0xd9, 0xc8, 0xb0, 0x2a, 0x94, 0xa2, 0x6b, 0x1c, 0x59, 0xf1, 0xd5, 0xda, 0xd8, + 0x68, 0x1f, 0xf4, 0xda, 0x9b, 0x8d, 0xdc, 0xf7, 0xf3, 0xa5, 0x6c, 0x23, 0x67, 0xfc, 0x59, 0x0e, + 0x2a, 0xda, 0x2c, 0x3c, 0x5f, 0x18, 0xdf, 0x02, 0x40, 0x93, 0x26, 0xce, 0x63, 0xca, 0x9b, 0x65, + 0x01, 0xa1, 0xc5, 0xd7, 0x9d, 0xe5, 0x39, 0x7a, 0xfe, 0x41, 0x39, 0xcb, 0x5f, 0x83, 0x1a, 0xbd, + 0xa4, 0xa0, 0x87, 0xeb, 0x0a, 0x66, 0x95, 0x80, 0x52, 0x54, 0xe3, 0x3d, 0x30, 0x24, 0xc2, 0x1b, + 0x02, 0xf2, 0x5e, 0x35, 0x81, 0xf0, 0x8e, 0x00, 0x5e, 0xf0, 0x08, 0xbc, 0xe1, 0x19, 0x27, 0x0a, + 0xd2, 0x08, 0x2b, 0x12, 0xd6, 0x93, 0x17, 0xd1, 0xa4, 0x3c, 0xd4, 0x2e, 0x22, 0x15, 0xcc, 0x2a, + 0x01, 0x65, 0x43, 0xef, 0x28, 0x06, 0x2a, 0x21, 0x03, 0xad, 0xce, 0x72, 0x43, 0x82, 0x79, 0x76, + 0x66, 0xfc, 0x59, 0x65, 0x64, 0x8c, 0xef, 0xcc, 0x96, 0x7b, 0xb1, 0x5f, 0x8b, 0xbd, 0x05, 0x6c, + 0x34, 0x1e, 0x5b, 0x29, 0x9e, 0xa6, 0xbc, 0x39, 0x3f, 0x1a, 0x8f, 0x7b, 0x9a, 0x23, 0xe6, 0x97, + 0xe0, 0x04, 0xfb, 0x12, 0x58, 0x4b, 0x6c, 0x60, 0xec, 0x62, 0xe4, 0x42, 0x8d, 0xc5, 0x72, 0x46, + 0x17, 0xcb, 0x29, 0xd2, 0x2f, 0x9b, 0x2a, 0xfd, 0x9e, 0x27, 0x27, 0x8c, 0x2d, 0xa8, 0x1c, 0x68, + 0xef, 0xb4, 0xdc, 0x11, 0x27, 0x84, 0x7a, 0xa1, 0x85, 0xce, 0x0e, 0x72, 0x6e, 0xf9, 0xf2, 0x61, + 0x16, 0xad, 0x37, 0x59, 0xad, 0x37, 0xc6, 0xbf, 0xcc, 0xd0, 0x1d, 0xf8, 0xa8, 0xf3, 0xf1, 0xd3, + 0x30, 0x2a, 0x0e, 0x14, 0xdf, 0x17, 0xac, 0xa8, 0xf8, 0x8f, 0xbc, 0xea, 0x87, 0x5d, 0xb3, 0xbc, + 0xe3, 0xe3, 0x80, 0xab, 0x9b, 0x2f, 0x15, 0x84, 0xed, 0x23, 0x48, 0x29, 0xdf, 0x42, 0xc3, 0x77, + 0xa8, 0xfe, 0x40, 0xde, 0x80, 0x11, 0xca, 0xf7, 0xae, 0x7d, 0x21, 0x5b, 0x0d, 0x84, 0x0a, 0x22, + 0x1d, 0xd5, 0xea, 0xbe, 0x4f, 0xf4, 0x6d, 0xfc, 0x33, 0x79, 0xa5, 0x71, 0x7a, 0x7e, 0xef, 0x43, + 0x29, 0xaa, 0x35, 0x79, 0xc2, 0x2a, 0xca, 0x08, 0x2f, 0xce, 0x71, 0xb4, 0xca, 0x13, 0x3d, 0xa6, + 0xcd, 0x85, 0xc1, 0x86, 0x8e, 0xd6, 0xeb, 0xb7, 0x81, 0x1d, 0x3b, 0xfe, 0x34, 0x31, 0x6d, 0xb6, + 0x06, 0x62, 0x34, 0x6a, 0xe3, 0x10, 0x16, 0x95, 0x94, 0xd0, 0x2c, 0x82, 0xe4, 0xe2, 0x65, 0x5e, + 0x20, 0xe4, 0xb3, 0x33, 0x42, 0xde, 0xf8, 0x69, 0x1e, 0x8a, 0xea, 0xcd, 0xa3, 0xb4, 0x77, 0x7a, + 0xca, 0xc9, 0x77, 0x7a, 0x9a, 0x89, 0x37, 0x1d, 0x70, 0xe9, 0xe5, 0x79, 0x7f, 0x77, 0xfa, 0xc8, + 0xd6, 0x9c, 0xe6, 0x89, 0x63, 0x7b, 0x05, 0xf2, 0x63, 0x3b, 0x3c, 0x45, 0x07, 0x19, 0x31, 0x0f, + 0x7e, 0x2b, 0x67, 0x7a, 0x21, 0xe9, 0x4c, 0x4f, 0x7b, 0xd3, 0x88, 0x54, 0xd2, 0x99, 0x37, 0x8d, + 0x6e, 0x00, 0xe9, 0x17, 0x5a, 0x3e, 0x4c, 0x09, 0x01, 0xe2, 0x2c, 0x4a, 0xaa, 0x23, 0xa5, 0x69, + 0x75, 0xe4, 0xa5, 0x55, 0x85, 0xf7, 0x60, 0x8e, 0xee, 0x03, 0xcb, 0x7b, 0x4d, 0xea, 0x40, 0x91, + 0x73, 0xa8, 0xfe, 0xa7, 0x24, 0x58, 0x53, 0xd2, 0xea, 0x0f, 0x84, 0x54, 0x12, 0x0f, 0x84, 0xe8, + 0x4e, 0xfe, 0x6a, 0xd2, 0xc9, 0x7f, 0x0f, 0x1a, 0xd1, 0x84, 0xa2, 0xcb, 0xcc, 0x0d, 0xe4, 0x8d, + 0x8e, 0xba, 0x82, 0x0b, 0x29, 0xb9, 0x17, 0xc4, 0x07, 0x62, 0x3d, 0x71, 0x20, 0x0a, 0x19, 0xd6, + 0x0a, 0x43, 0x3e, 0x1a, 0x87, 0xf2, 0x40, 0xc4, 0x9c, 0x6f, 0xbd, 0x83, 0xc9, 0x1b, 0x7f, 0x35, + 0x28, 0x77, 0xf6, 0xac, 0xad, 0x9d, 0xce, 0x93, 0xed, 0x5e, 0x23, 0x23, 0x3e, 0xbb, 0x87, 0x1b, + 0x1b, 0xed, 0xf6, 0x26, 0x9e, 0x38, 0x00, 0x73, 0x5b, 0xad, 0x8e, 0x38, 0x7d, 0x72, 0xc6, 0x5f, + 0x66, 0xa0, 0xa2, 0x55, 0xcf, 0xde, 0x8f, 0x66, 0x85, 0xde, 0x90, 0xb8, 0x35, 0xdb, 0x85, 0x07, + 0x4a, 0x14, 0x6b, 0xd3, 0x12, 0xbd, 0xe0, 0x94, 0xbd, 0xf2, 0x05, 0x27, 0xf6, 0x06, 0xcc, 0xdb, + 0x54, 0x43, 0x34, 0x0b, 0xd2, 0x1d, 0x2c, 0xc1, 0x72, 0x12, 0x30, 0x0b, 0x2c, 0x3e, 0x4f, 0x04, + 0x5d, 0x5e, 0x25, 0x5e, 0x45, 0x47, 0xca, 0x5e, 0x60, 0x7c, 0x00, 0x10, 0xf7, 0x24, 0x39, 0xe4, + 0x6b, 0xc9, 0x21, 0x67, 0xb4, 0x21, 0x67, 0x8d, 0x4d, 0x12, 0x0e, 0x72, 0xfa, 0xa2, 0xf8, 0xf3, + 0x3b, 0xa0, 0xfc, 0x4c, 0x16, 0x66, 0x57, 0x8e, 0x87, 0x3c, 0x54, 0x37, 0x1e, 0x17, 0x24, 0xa6, + 0x13, 0x21, 0xd4, 0x05, 0xe4, 0xb8, 0x96, 0x58, 0xc6, 0x48, 0x46, 0x9b, 0x96, 0x31, 0x92, 0xd4, + 0x8c, 0xf0, 0xc6, 0x1a, 0x34, 0x37, 0xb9, 0xa8, 0xad, 0x35, 0x1c, 0x4e, 0x75, 0xc7, 0xb8, 0x01, + 0xd7, 0x53, 0x70, 0xd2, 0xb5, 0xf0, 0x29, 0x2c, 0xb7, 0xe8, 0x72, 0xe3, 0x2f, 0xeb, 0x86, 0x85, + 0xd1, 0x84, 0x95, 0xe9, 0x2a, 0x65, 0x63, 0x5b, 0xb0, 0xb0, 0xc9, 0x8f, 0x26, 0x27, 0x3b, 0xfc, + 0x2c, 0x6e, 0x88, 0x41, 0x3e, 0x38, 0xf5, 0xce, 0xe5, 0xfc, 0xe0, 0xdf, 0x62, 0x67, 0x0e, 0x05, + 0x8d, 0x15, 0x8c, 0x79, 0x5f, 0xf9, 0x39, 0x11, 0xd2, 0x1d, 0xf3, 0xbe, 0xf1, 0x3e, 0x30, 0xbd, + 0x1e, 0x39, 0x5f, 0x42, 0xf7, 0x9f, 0x1c, 0x59, 0xc1, 0x65, 0x10, 0xf2, 0x91, 0x7a, 0x78, 0x04, + 0x82, 0xc9, 0x51, 0x97, 0x20, 0xc6, 0x5d, 0xa8, 0x1e, 0xd8, 0x97, 0x26, 0xff, 0x52, 0xde, 0x1d, + 0x58, 0x85, 0xe2, 0xd8, 0xbe, 0x14, 0x9b, 0x3b, 0x0a, 0x79, 0x20, 0xda, 0xf8, 0xc3, 0x3c, 0xcc, + 0x11, 0x25, 0xbb, 0x43, 0x6f, 0x03, 0x3a, 0x2e, 0x6e, 0x2e, 0x25, 0xfe, 0x34, 0xd0, 0x8c, 0x84, + 0xcc, 0xce, 0x4a, 0x48, 0xe9, 0x16, 0x53, 0x6f, 0x22, 0x28, 0xe7, 0xb4, 0x3b, 0x19, 0xa9, 0x87, + 0x10, 0xd8, 0x4d, 0x28, 0xc7, 0x97, 0xb4, 0xf2, 0xf1, 0xdb, 0x8f, 0x74, 0x35, 0x2b, 0x19, 0x3e, + 0x8c, 0x2d, 0x0c, 0xea, 0x9d, 0x12, 0xfc, 0x52, 0x08, 0xea, 0xa0, 0x54, 0x33, 0xa6, 0xa8, 0x6e, + 0xa5, 0x24, 0xcd, 0x98, 0x19, 0x73, 0xa5, 0xf4, 0x62, 0x73, 0x85, 0xfc, 0x65, 0xcf, 0x31, 0x57, + 0xe0, 0x25, 0xcc, 0x95, 0x97, 0x08, 0xdd, 0x5d, 0x87, 0x12, 0x9e, 0xe6, 0x9a, 0x4c, 0x14, 0xa7, + 0xb8, 0x90, 0x89, 0x1f, 0x6a, 0x0a, 0x3d, 0xe5, 0x0d, 0xdc, 0x88, 0xb7, 0x89, 0xc9, 0xbf, 0xfc, + 0xd5, 0x84, 0x44, 0xbe, 0x80, 0xa2, 0x84, 0x0a, 0x86, 0x76, 0xed, 0x91, 0x7a, 0x56, 0x06, 0xff, + 0x16, 0xd3, 0x86, 0x6f, 0x61, 0x7c, 0x39, 0x71, 0x7c, 0x3e, 0x50, 0x8f, 0x17, 0x38, 0xb8, 0x47, + 0x05, 0x44, 0x0c, 0x50, 0x18, 0x17, 0xae, 0x77, 0xee, 0xca, 0xab, 0xcb, 0x45, 0x27, 0x78, 0x2a, + 0x3e, 0x0d, 0x06, 0x0d, 0x7c, 0x58, 0x6a, 0xec, 0xf9, 0xea, 0xc8, 0x31, 0x7e, 0x9a, 0x81, 0x86, + 0xdc, 0x5d, 0x11, 0x4e, 0xd7, 0xed, 0x0b, 0x57, 0x85, 0xb9, 0x9f, 0xff, 0x14, 0x81, 0x01, 0x35, + 0x74, 0x69, 0x44, 0xe7, 0x0f, 0xb9, 0x64, 0x2a, 0x02, 0xb8, 0x25, 0xcf, 0xa0, 0x57, 0xa0, 0xa2, + 0x92, 0x2c, 0x47, 0xce, 0x50, 0x3d, 0xf3, 0x4a, 0x59, 0x96, 0xbb, 0xce, 0x50, 0x1d, 0x5f, 0xbe, + 0x2d, 0x6f, 0x49, 0x65, 0xf0, 0xf8, 0x32, 0xed, 0x90, 0x1b, 0xff, 0x29, 0x03, 0x0b, 0xda, 0x50, + 0xe4, 0xbe, 0xfd, 0x18, 0xaa, 0xd1, 0x8b, 0x6e, 0x3c, 0xd2, 0xa7, 0x56, 0x93, 0x82, 0x26, 0x2e, + 0x56, 0xe9, 0x47, 0x90, 0x40, 0x74, 0x66, 0x60, 0x5f, 0x62, 0x7f, 0x83, 0xc9, 0x48, 0x99, 0x2c, + 0x03, 0xfb, 0x72, 0x8b, 0xf3, 0xee, 0x64, 0x24, 0x0c, 0xd2, 0x73, 0xce, 0x9f, 0x45, 0x04, 0xa4, + 0x49, 0x81, 0x80, 0x49, 0x0a, 0x03, 0x6a, 0x23, 0xcf, 0x0d, 0x4f, 0x23, 0x12, 0xa9, 0x4b, 0x22, + 0x90, 0x68, 0x8c, 0xff, 0x91, 0x85, 0x45, 0x72, 0x9c, 0x49, 0x87, 0xa5, 0x14, 0x5d, 0x4d, 0x98, + 0x23, 0x1f, 0x22, 0x09, 0xaf, 0xed, 0x6b, 0xa6, 0xfc, 0x66, 0xef, 0xbd, 0xa4, 0xb3, 0x4f, 0x5d, + 0xc4, 0xba, 0x62, 0xfa, 0x73, 0xb3, 0xd3, 0x7f, 0xf5, 0xf4, 0xa6, 0xc5, 0xd1, 0x0a, 0x69, 0x71, + 0xb4, 0x97, 0x89, 0x5e, 0xcd, 0xdc, 0x56, 0x2a, 0x4a, 0x1a, 0xed, 0xb6, 0xd2, 0xfb, 0xb0, 0x9a, + 0xa0, 0x41, 0x69, 0xed, 0x1c, 0x3b, 0x5c, 0xdd, 0x0c, 0x5f, 0xd2, 0xa8, 0xbb, 0x0a, 0xb7, 0x5e, + 0x84, 0x42, 0xd0, 0xf7, 0xc6, 0xdc, 0x58, 0x81, 0xa5, 0xe4, 0xac, 0xca, 0x63, 0xe2, 0xf7, 0x33, + 0xd0, 0x94, 0x59, 0x0f, 0x8e, 0x7b, 0xb2, 0xed, 0x04, 0xa1, 0xe7, 0x47, 0x2f, 0x9f, 0xdd, 0x02, + 0x08, 0x42, 0xdb, 0x97, 0x36, 0x24, 0x69, 0xb7, 0x65, 0x84, 0xa0, 0x7d, 0x78, 0x1d, 0x4a, 0xdc, + 0x1d, 0x10, 0x92, 0xb8, 0xa1, 0xc8, 0xdd, 0x81, 0xb2, 0x2e, 0x67, 0xb4, 0xea, 0x5a, 0xd2, 0x68, + 0x90, 0xd7, 0x26, 0xc5, 0xec, 0xf0, 0x33, 0x3c, 0x78, 0xf3, 0xd1, 0xb5, 0xc9, 0x5d, 0xfb, 0x02, + 0x73, 0x08, 0x03, 0xe3, 0x1f, 0x67, 0x61, 0x3e, 0xee, 0x1f, 0xdd, 0xb9, 0x4e, 0xc8, 0x6f, 0xd9, + 0xab, 0x58, 0x7e, 0xdf, 0x91, 0xec, 0xe0, 0x08, 0xad, 0x5c, 0x73, 0x27, 0x96, 0x68, 0x73, 0x76, + 0x5c, 0x66, 0x40, 0x45, 0x51, 0x78, 0x93, 0x50, 0x7b, 0x80, 0xa8, 0x4c, 0x24, 0xfb, 0x93, 0x50, + 0x98, 0x51, 0xc2, 0x9e, 0x74, 0x5c, 0x69, 0xc8, 0x14, 0xec, 0x51, 0xd8, 0xc1, 0x77, 0x8d, 0x05, + 0x58, 0x14, 0xa3, 0x85, 0x14, 0x54, 0x82, 0xbe, 0x41, 0xda, 0x33, 0xad, 0x1c, 0x6a, 0xce, 0xba, + 0x6a, 0x49, 0x4f, 0x3c, 0x46, 0xaa, 0xe5, 0x2b, 0x50, 0xa1, 0xca, 0xe3, 0xcb, 0x69, 0x79, 0xb3, + 0x8c, 0x2d, 0x20, 0x5e, 0xba, 0x76, 0xbc, 0x49, 0xc2, 0xa0, 0x05, 0x6a, 0x0a, 0x93, 0x0a, 0xfe, + 0x41, 0x06, 0xae, 0xa7, 0x2c, 0x9b, 0xdc, 0xe5, 0x1b, 0xb0, 0x70, 0x1c, 0x21, 0xd5, 0xec, 0xd2, + 0x56, 0x5f, 0x51, 0x62, 0x35, 0x39, 0xa7, 0x66, 0xe3, 0x38, 0x09, 0x88, 0x4d, 0x29, 0x5a, 0xc1, + 0xc4, 0xfd, 0x43, 0x34, 0xa5, 0x68, 0x19, 0xc9, 0x8a, 0x39, 0x80, 0xb5, 0xf6, 0x85, 0x90, 0x18, + 0x1b, 0xfa, 0xc3, 0xdc, 0x8a, 0x8d, 0x92, 0x6e, 0xe3, 0xcc, 0x4b, 0xb9, 0x8d, 0x07, 0x74, 0xcd, + 0x2a, 0xaa, 0xeb, 0xdb, 0x54, 0x82, 0x07, 0xa8, 0x28, 0x43, 0x0f, 0x8b, 0xab, 0x3b, 0x90, 0xfd, + 0xe8, 0x41, 0x71, 0x23, 0x80, 0xf9, 0xdd, 0xc9, 0x30, 0x74, 0xe2, 0x37, 0xc6, 0xd9, 0x7b, 0xb2, + 0x0c, 0xb6, 0xa3, 0x66, 0x2d, 0xb5, 0x21, 0x88, 0x1a, 0xc2, 0xc9, 0x1a, 0x89, 0x8a, 0xac, 0xd9, + 0xf6, 0xe6, 0x47, 0xc9, 0x16, 0x8c, 0xeb, 0xb0, 0x1a, 0x7f, 0xd1, 0xb4, 0xa9, 0xa3, 0xe6, 0x5f, + 0x64, 0x28, 0x61, 0x39, 0xf9, 0xde, 0x39, 0x6b, 0xc3, 0x62, 0xe0, 0xb8, 0x27, 0x43, 0xae, 0x57, + 0x1f, 0xc8, 0x49, 0x58, 0x4e, 0xf6, 0x4d, 0xbe, 0x89, 0x6e, 0x2e, 0x50, 0x89, 0xb8, 0xb6, 0x80, + 0xad, 0x5f, 0xd5, 0xc9, 0x98, 0x2d, 0xa6, 0x66, 0x63, 0xb6, 0xf3, 0x1d, 0xa8, 0x27, 0x1b, 0x62, + 0x1f, 0xca, 0x2b, 0x86, 0x71, 0xaf, 0x72, 0x53, 0xb7, 0xc5, 0x62, 0x86, 0xa8, 0xc4, 0x73, 0x1f, + 0x18, 0xff, 0x30, 0x03, 0x4d, 0x93, 0x0b, 0xce, 0xd5, 0x7a, 0xa9, 0x78, 0xe6, 0xe3, 0x99, 0x5a, + 0xaf, 0x1e, 0xab, 0xba, 0xb9, 0xa8, 0x7a, 0xf4, 0xf6, 0x95, 0x8b, 0xb1, 0x7d, 0x6d, 0x66, 0x44, + 0xeb, 0x25, 0x98, 0x23, 0x12, 0x63, 0x15, 0x96, 0x65, 0x7f, 0x54, 0x5f, 0xe2, 0x98, 0x60, 0xa2, + 0xc5, 0x44, 0x4c, 0x70, 0x0d, 0x9a, 0xf4, 0x80, 0x9d, 0x3e, 0x08, 0x59, 0x70, 0x13, 0xd8, 0xae, + 0xdd, 0xb7, 0x7d, 0xcf, 0x73, 0x0f, 0xb8, 0x2f, 0xd3, 0x3f, 0x51, 0xc3, 0xc4, 0x90, 0x99, 0x52, + 0x85, 0xe9, 0x4b, 0x3d, 0xbb, 0xe6, 0xb9, 0x2a, 0xdb, 0x85, 0xbe, 0x0c, 0x13, 0x16, 0xd7, 0xed, + 0x67, 0x5c, 0xd5, 0xa4, 0xa6, 0xe8, 0x13, 0xa8, 0x8c, 0xa3, 0x4a, 0xd5, 0xbc, 0xab, 0x7b, 0xc8, + 0xb3, 0xcd, 0x9a, 0x3a, 0xb5, 0xf1, 0x18, 0x96, 0x92, 0x75, 0x4a, 0xd1, 0xb1, 0x06, 0xa5, 0x91, + 0x84, 0xc9, 0xde, 0x45, 0xdf, 0xc6, 0xff, 0x2d, 0x42, 0x71, 0xcb, 0x76, 0x86, 0x42, 0xf1, 0x7a, + 0x00, 0xf9, 0xbe, 0xca, 0x38, 0x8a, 0x9f, 0xb7, 0x90, 0x58, 0xf5, 0xff, 0x06, 0xe6, 0x1d, 0x09, + 0x3a, 0xf6, 0x09, 0xd4, 0x93, 0xb1, 0xce, 0xa9, 0x4b, 0x8e, 0xc9, 0x20, 0x65, 0xad, 0x3f, 0x15, + 0xd5, 0x2a, 0xc7, 0x87, 0x23, 0xe9, 0x0c, 0xa5, 0x53, 0xed, 0xf4, 0xf4, 0x5c, 0xa1, 0x6f, 0x07, + 0xa7, 0xb6, 0xf5, 0xf8, 0xfd, 0x0f, 0xe4, 0x2d, 0xc7, 0x0a, 0x02, 0xbb, 0xa7, 0xf6, 0xe3, 0xf7, + 0x3f, 0x98, 0xd6, 0xa4, 0xe9, 0xa2, 0x9b, 0xae, 0x49, 0x2f, 0x41, 0x81, 0xde, 0x17, 0xa3, 0xd4, + 0x11, 0xfa, 0x60, 0x8f, 0x60, 0xe9, 0x98, 0x46, 0x62, 0xc9, 0x24, 0x5f, 0x92, 0x82, 0x25, 0xba, + 0x59, 0x23, 0x71, 0x5d, 0x44, 0x91, 0xc7, 0x67, 0x05, 0xe6, 0x4e, 0xe3, 0xc7, 0xe2, 0x6a, 0xa6, + 0xfc, 0x32, 0xfe, 0x6b, 0x01, 0x2a, 0xda, 0xa4, 0xb0, 0x2a, 0x94, 0xcc, 0x76, 0xb7, 0x6d, 0x7e, + 0xd6, 0xde, 0x6c, 0x5c, 0x63, 0xf7, 0xe0, 0xf5, 0xce, 0xde, 0xc6, 0xbe, 0x69, 0xb6, 0x37, 0x7a, + 0xd6, 0xbe, 0x69, 0xa9, 0x97, 0x4f, 0x0e, 0x5a, 0x5f, 0xec, 0xb6, 0xf7, 0x7a, 0xd6, 0x66, 0xbb, + 0xd7, 0xea, 0xec, 0x74, 0x1b, 0x19, 0x76, 0x13, 0x9a, 0x31, 0xa5, 0x42, 0xb7, 0x76, 0xf7, 0x0f, + 0xf7, 0x7a, 0x8d, 0x2c, 0xbb, 0x0d, 0x37, 0xb6, 0x3a, 0x7b, 0xad, 0x1d, 0x2b, 0xa6, 0xd9, 0xd8, + 0xe9, 0x7d, 0x66, 0xb5, 0x7f, 0x70, 0xd0, 0x31, 0xbf, 0x68, 0xe4, 0xd2, 0x08, 0x84, 0x31, 0xae, + 0x6a, 0xc8, 0xb3, 0xeb, 0xb0, 0x4c, 0x04, 0x54, 0xc4, 0xea, 0xed, 0xef, 0x5b, 0xdd, 0xfd, 0xfd, + 0xbd, 0x46, 0x81, 0x2d, 0x40, 0xad, 0xb3, 0xf7, 0x59, 0x6b, 0xa7, 0xb3, 0x69, 0x99, 0xed, 0xd6, + 0xce, 0x6e, 0x63, 0x8e, 0x2d, 0xc2, 0xfc, 0x34, 0x5d, 0x51, 0x54, 0xa1, 0xe8, 0xf6, 0xf7, 0x3a, + 0xfb, 0x7b, 0xd6, 0x67, 0x6d, 0xb3, 0xdb, 0xd9, 0xdf, 0x6b, 0x94, 0xd8, 0x0a, 0xb0, 0x24, 0x6a, + 0x7b, 0xb7, 0xb5, 0xd1, 0x28, 0xb3, 0x65, 0x58, 0x48, 0xc2, 0x9f, 0xb6, 0xbf, 0x68, 0x00, 0x6b, + 0xc2, 0x12, 0x75, 0xcc, 0x5a, 0x6f, 0xef, 0xec, 0x7f, 0x6e, 0xed, 0x76, 0xf6, 0x3a, 0xbb, 0x87, + 0xbb, 0x8d, 0x0a, 0x3e, 0xad, 0xd4, 0x6e, 0x5b, 0x9d, 0xbd, 0xee, 0xe1, 0xd6, 0x56, 0x67, 0xa3, + 0xd3, 0xde, 0xeb, 0x35, 0xaa, 0xd4, 0x72, 0xda, 0xc0, 0x6b, 0xa2, 0x80, 0xbc, 0x09, 0x60, 0x6d, + 0x76, 0xba, 0xad, 0xf5, 0x9d, 0xf6, 0x66, 0xa3, 0xce, 0x6e, 0xc1, 0xf5, 0x5e, 0x7b, 0xf7, 0x60, + 0xdf, 0x6c, 0x99, 0x5f, 0xa8, 0x9b, 0x02, 0xd6, 0x56, 0xab, 0xb3, 0x73, 0x68, 0xb6, 0x1b, 0xf3, + 0xec, 0x55, 0xb8, 0x65, 0xb6, 0x3f, 0x3d, 0xec, 0x98, 0xed, 0x4d, 0x6b, 0x6f, 0x7f, 0xb3, 0x6d, + 0x6d, 0xb5, 0x5b, 0xbd, 0x43, 0xb3, 0x6d, 0xed, 0x76, 0xba, 0xdd, 0xce, 0xde, 0x93, 0x46, 0x83, + 0xbd, 0x0e, 0x77, 0x22, 0x92, 0xa8, 0x82, 0x29, 0xaa, 0x05, 0x31, 0x3e, 0xb5, 0xa4, 0x7b, 0xed, + 0x1f, 0xf4, 0xac, 0x83, 0x76, 0xdb, 0x6c, 0x30, 0xb6, 0x06, 0x2b, 0x71, 0xf3, 0xd4, 0x80, 0x6c, + 0x7b, 0x51, 0xe0, 0x0e, 0xda, 0xe6, 0x6e, 0x6b, 0x4f, 0x2c, 0x70, 0x02, 0xb7, 0x24, 0xba, 0x1d, + 0xe3, 0xa6, 0xbb, 0xbd, 0xcc, 0x18, 0xd4, 0xb5, 0x55, 0xd9, 0x6a, 0x99, 0x8d, 0x15, 0x36, 0x0f, + 0x95, 0xdd, 0x83, 0x03, 0xab, 0xd7, 0xd9, 0x6d, 0xef, 0x1f, 0xf6, 0x1a, 0xab, 0x6c, 0x09, 0xe6, + 0x55, 0x97, 0x54, 0xc9, 0x9f, 0x17, 0xd9, 0x2a, 0xb0, 0xc3, 0x3d, 0xb3, 0xdd, 0xda, 0x14, 0x33, + 0x14, 0x21, 0xfe, 0x4f, 0x51, 0x06, 0x38, 0x7e, 0x9a, 0x8b, 0x4e, 0xe5, 0x38, 0x63, 0x20, 0xf9, + 0x46, 0x68, 0x55, 0x7b, 0xdb, 0xf3, 0x45, 0xaf, 0x77, 0x6b, 0x36, 0x54, 0x6e, 0xc6, 0x86, 0x9a, + 0x31, 0xd2, 0x6b, 0xba, 0x92, 0xf7, 0x1a, 0xd4, 0x46, 0xf4, 0x5e, 0xa8, 0x7c, 0x17, 0x10, 0x64, + 0xfa, 0x0c, 0x01, 0xe9, 0x51, 0xc0, 0x99, 0xe7, 0xab, 0x0b, 0xb3, 0xcf, 0x57, 0xa7, 0x29, 0xf2, + 0x73, 0x69, 0x8a, 0xfc, 0x7d, 0x58, 0x20, 0x19, 0xe4, 0xb8, 0xce, 0x48, 0x99, 0xc7, 0xa4, 0xee, + 0xcd, 0xa3, 0x2c, 0x22, 0xb8, 0xb2, 0x1b, 0x94, 0x6d, 0x21, 0x65, 0x45, 0x51, 0x9a, 0x15, 0x09, + 0x93, 0x82, 0x44, 0x44, 0x64, 0x52, 0x44, 0x2d, 0xd8, 0x17, 0x71, 0x0b, 0x15, 0xad, 0x05, 0x82, + 0x63, 0x0b, 0xf7, 0x61, 0x81, 0x5f, 0x84, 0xbe, 0x6d, 0x79, 0x63, 0xfb, 0xcb, 0x09, 0x46, 0x60, + 0x6d, 0x34, 0xd6, 0xab, 0xe6, 0x3c, 0x22, 0xf6, 0x11, 0xbe, 0x69, 0x87, 0xf6, 0xfd, 0xaf, 0xa1, + 0xa2, 0xbd, 0x25, 0xcb, 0x56, 0x61, 0xf1, 0xf3, 0x4e, 0x6f, 0xaf, 0xdd, 0xed, 0x5a, 0x07, 0x87, + 0xeb, 0x4f, 0xdb, 0x5f, 0x58, 0xdb, 0xad, 0xee, 0x76, 0xe3, 0x9a, 0xd8, 0x9d, 0x7b, 0xed, 0x6e, + 0xaf, 0xbd, 0x99, 0x80, 0x67, 0xd8, 0x2b, 0xb0, 0x76, 0xb8, 0x77, 0xd8, 0x6d, 0x6f, 0x5a, 0x69, + 0xe5, 0xb2, 0x82, 0x1d, 0x25, 0x3e, 0xa5, 0x78, 0xee, 0xfe, 0x27, 0xd0, 0x98, 0x0e, 0x06, 0x25, + 0xa2, 0x67, 0xcf, 0x0b, 0xb3, 0xdd, 0xff, 0x37, 0x39, 0x80, 0x38, 0x5b, 0x5f, 0x48, 0x84, 0xcd, + 0x56, 0xaf, 0xb5, 0xb3, 0x2f, 0x3a, 0x61, 0xee, 0xf7, 0xc4, 0x46, 0x37, 0xdb, 0x9f, 0x36, 0xae, + 0xa5, 0x62, 0xf6, 0x0f, 0x7a, 0x8d, 0x8c, 0x18, 0x6f, 0x67, 0xaf, 0xd3, 0xeb, 0xb4, 0x76, 0x2c, + 0x73, 0xff, 0xb0, 0xb3, 0xf7, 0x84, 0x5e, 0x8b, 0x42, 0x61, 0x78, 0x78, 0xb0, 0x65, 0xee, 0xef, + 0xf5, 0xac, 0xee, 0xf6, 0x61, 0x6f, 0x13, 0xdf, 0x9a, 0xda, 0x30, 0x3b, 0x07, 0x54, 0x67, 0xfe, + 0x79, 0x04, 0xa2, 0xea, 0x82, 0x98, 0xb1, 0x27, 0xfb, 0xdd, 0x6e, 0xe7, 0xc0, 0xfa, 0xf4, 0xb0, + 0x6d, 0x76, 0xda, 0x5d, 0x2c, 0x38, 0x97, 0x02, 0x17, 0xf4, 0x45, 0x21, 0x42, 0x7b, 0x3b, 0x9f, + 0x49, 0x19, 0x27, 0x48, 0x4b, 0x49, 0x90, 0xa0, 0x2a, 0x8b, 0xad, 0x2f, 0x84, 0x44, 0x4a, 0xcd, + 0x70, 0x05, 0x4e, 0x94, 0xab, 0x08, 0xf1, 0xd7, 0xed, 0xb5, 0x7a, 0x9d, 0x0d, 0x4b, 0x3e, 0x50, + 0x27, 0x16, 0x41, 0x14, 0xab, 0xa6, 0xa3, 0x44, 0x29, 0x94, 0x8c, 0xd1, 0x39, 0xb2, 0xb9, 0x69, + 0x62, 0x81, 0xfa, 0x0c, 0x54, 0xd0, 0xce, 0x8b, 0x85, 0x12, 0x52, 0x44, 0x90, 0x34, 0xd4, 0x87, + 0xc0, 0x2c, 0x3c, 0xfe, 0x9d, 0x1c, 0xd4, 0xe9, 0xe6, 0x14, 0xfd, 0x10, 0x0f, 0xf7, 0xd9, 0x2e, + 0x14, 0xe5, 0x2f, 0x3a, 0xb1, 0xe5, 0xe8, 0xcd, 0x20, 0xfd, 0x37, 0xa4, 0xd6, 0x56, 0xa6, 0xc1, + 0x52, 0x6b, 0x5a, 0xfc, 0x9b, 0x7f, 0xfa, 0x17, 0xff, 0x28, 0x5b, 0x63, 0x95, 0x87, 0x67, 0xef, + 0x3e, 0x3c, 0xe1, 0x6e, 0x20, 0xea, 0xf8, 0x6b, 0x00, 0xf1, 0xef, 0x14, 0xb1, 0x66, 0x14, 0x01, + 0x9a, 0xfa, 0x11, 0xa7, 0xb5, 0xeb, 0x29, 0x18, 0x59, 0xef, 0x75, 0xac, 0x77, 0xd1, 0xa8, 0x8b, + 0x7a, 0x1d, 0xd7, 0x09, 0xe9, 0x37, 0x8b, 0x3e, 0xce, 0xdc, 0x67, 0x03, 0xa8, 0xea, 0xbf, 0x20, + 0xc4, 0x94, 0x42, 0x93, 0xf2, 0x1b, 0x48, 0x6b, 0x37, 0x52, 0x71, 0x4a, 0x55, 0xc4, 0x36, 0x96, + 0x8d, 0x86, 0x68, 0x63, 0x82, 0x14, 0x71, 0x2b, 0x43, 0x52, 0x9e, 0xe3, 0x1f, 0x0a, 0x62, 0x37, + 0x35, 0xf5, 0x67, 0xe6, 0x67, 0x8a, 0xd6, 0x6e, 0x5d, 0x81, 0x95, 0x6d, 0xdd, 0xc2, 0xb6, 0x56, + 0x0d, 0x26, 0xda, 0xea, 0x23, 0x8d, 0xfa, 0x99, 0xa2, 0x8f, 0x33, 0xf7, 0x1f, 0xff, 0xf9, 0x3d, + 0x28, 0x47, 0x99, 0x94, 0xec, 0xb7, 0xa0, 0x96, 0xb8, 0xda, 0xc6, 0xd4, 0x30, 0xd2, 0x6e, 0xc2, + 0xad, 0xdd, 0x4c, 0x47, 0xca, 0x86, 0x5f, 0xc1, 0x86, 0x9b, 0x6c, 0x45, 0x34, 0x2c, 0xaf, 0x8e, + 0x3d, 0xc4, 0x0b, 0xa0, 0xf4, 0x02, 0xd3, 0x33, 0xcd, 0x48, 0xa0, 0xc6, 0x6e, 0x4e, 0x2b, 0xee, + 0x89, 0xd6, 0x6e, 0x5d, 0x81, 0x95, 0xcd, 0xdd, 0xc4, 0xe6, 0x56, 0xd8, 0x92, 0xde, 0x9c, 0xca, + 0x7b, 0x64, 0x1c, 0x5f, 0x3d, 0xd3, 0x7f, 0x47, 0x87, 0xdd, 0x8a, 0xdf, 0xa8, 0x4a, 0xf9, 0x7d, + 0x9d, 0x88, 0x45, 0x66, 0x7f, 0x64, 0xc7, 0x68, 0x62, 0x53, 0x8c, 0xe1, 0xf2, 0xe9, 0x3f, 0xa3, + 0xc3, 0x8e, 0xa0, 0xa2, 0x3d, 0x3d, 0xcf, 0xae, 0x5f, 0xf9, 0x4c, 0xfe, 0xda, 0x5a, 0x1a, 0x2a, + 0x6d, 0x28, 0x7a, 0xfd, 0x0f, 0x8f, 0x39, 0x67, 0x3f, 0x82, 0x72, 0xf4, 0xa0, 0x39, 0x5b, 0xd5, + 0x1e, 0x98, 0xd7, 0x1f, 0x60, 0x5f, 0x6b, 0xce, 0x22, 0xd2, 0x98, 0x4f, 0xaf, 0x5d, 0x30, 0xdf, + 0xe7, 0x50, 0xd1, 0x1e, 0x2d, 0x8f, 0x06, 0x30, 0xfb, 0x30, 0x7a, 0x34, 0x80, 0x94, 0x37, 0xce, + 0x8d, 0x05, 0x6c, 0xa2, 0xc2, 0xca, 0xc8, 0xdf, 0xe1, 0x85, 0x17, 0xb0, 0x1d, 0x58, 0x96, 0x06, + 0xd1, 0x11, 0xff, 0x26, 0xcb, 0x90, 0xf2, 0xd3, 0x45, 0x8f, 0x32, 0xec, 0x13, 0x28, 0xa9, 0xb7, + 0xe9, 0xd9, 0x4a, 0xfa, 0x1b, 0xfb, 0x6b, 0xab, 0x33, 0x70, 0x69, 0xbd, 0x7c, 0x01, 0x10, 0xbf, + 0x90, 0x1e, 0x09, 0x89, 0x99, 0x17, 0xd7, 0x23, 0x0e, 0x98, 0x7d, 0x4e, 0xdd, 0x58, 0xc1, 0x01, + 0x36, 0x18, 0x0a, 0x09, 0x97, 0x9f, 0xab, 0xe7, 0x1f, 0x7f, 0x0c, 0x15, 0xed, 0x91, 0xf4, 0x68, + 0xfa, 0x66, 0x1f, 0x58, 0x8f, 0xa6, 0x2f, 0xe5, 0x4d, 0x75, 0x63, 0x0d, 0x6b, 0x5f, 0x32, 0xe6, + 0x45, 0xed, 0x42, 0x51, 0x92, 0x0a, 0x8b, 0x58, 0xa0, 0x53, 0xa8, 0x25, 0x5e, 0x42, 0x8f, 0x76, + 0x68, 0xda, 0x3b, 0xeb, 0xd1, 0x0e, 0x4d, 0x7d, 0x3c, 0x5d, 0xf1, 0x99, 0xb1, 0x20, 0xda, 0x39, + 0x43, 0x12, 0xad, 0xa5, 0x1f, 0x42, 0x45, 0x7b, 0xd5, 0x3c, 0x1a, 0xcb, 0xec, 0x03, 0xea, 0xd1, + 0x58, 0xd2, 0x1e, 0x41, 0x5f, 0xc2, 0x36, 0xea, 0x06, 0xb2, 0x02, 0x3e, 0xae, 0x27, 0xea, 0xfe, + 0x2d, 0xa8, 0x27, 0x1f, 0x3a, 0x8f, 0xf6, 0x7e, 0xea, 0x8b, 0xe9, 0xd1, 0xde, 0xbf, 0xe2, 0x75, + 0x74, 0xc9, 0xd2, 0xf7, 0x17, 0xa3, 0x46, 0x1e, 0x7e, 0x25, 0xef, 0x84, 0x7c, 0xcd, 0x3e, 0x15, + 0x02, 0x4e, 0xbe, 0xed, 0xc8, 0x56, 0x35, 0xae, 0xd5, 0x5f, 0x80, 0x8c, 0xf6, 0xcb, 0xcc, 0x33, + 0x90, 0x49, 0x66, 0xc6, 0xca, 0xd9, 0x13, 0x58, 0x8c, 0x98, 0x39, 0x7a, 0xac, 0x31, 0x88, 0xc6, + 0x90, 0xfa, 0x24, 0xe4, 0x5a, 0x63, 0x1a, 0xfb, 0x28, 0x43, 0xc7, 0x1f, 0x3e, 0x91, 0xa7, 0x1d, + 0x7f, 0xfa, 0x7b, 0x8d, 0xda, 0xf1, 0x97, 0x78, 0x49, 0x6f, 0xfa, 0xf8, 0x0b, 0x1d, 0x51, 0x87, + 0x0b, 0xf3, 0xd3, 0x4f, 0x27, 0xde, 0xba, 0xea, 0xe1, 0x00, 0xaa, 0xfe, 0x95, 0xe7, 0xbf, 0x2b, + 0x90, 0x14, 0x45, 0x4a, 0x9a, 0x3e, 0x94, 0x99, 0x1f, 0xec, 0x37, 0xa1, 0xaa, 0xbf, 0xd4, 0xcc, + 0x74, 0x99, 0x30, 0xdd, 0xd2, 0x8d, 0x54, 0x5c, 0x92, 0x4b, 0x58, 0x55, 0x6f, 0x86, 0x7d, 0x06, + 0x2b, 0xd1, 0x34, 0xeb, 0x97, 0xc6, 0x03, 0x76, 0x3b, 0xe5, 0x2a, 0x79, 0x62, 0xb2, 0xaf, 0x5f, + 0x79, 0xd7, 0xfc, 0x51, 0x46, 0x70, 0x5f, 0xf2, 0xc9, 0xd8, 0xf8, 0xe4, 0x49, 0x7b, 0x29, 0x37, + 0x3e, 0x79, 0x52, 0xdf, 0x99, 0x55, 0xdc, 0xc7, 0x16, 0x13, 0x73, 0x44, 0x39, 0xb1, 0xec, 0x87, + 0x30, 0xaf, 0xdd, 0x88, 0xef, 0x5e, 0xba, 0xfd, 0x68, 0x27, 0xcd, 0xbe, 0xc7, 0xb6, 0x96, 0xe6, + 0x42, 0x34, 0x56, 0xb1, 0xfe, 0x05, 0x23, 0x31, 0x39, 0x62, 0x17, 0x6d, 0x40, 0x45, 0xbf, 0x6d, + 0xff, 0x9c, 0x7a, 0x57, 0x35, 0x94, 0xfe, 0xf4, 0xd7, 0xa3, 0x0c, 0xdb, 0x81, 0xc6, 0xf4, 0x4b, + 0x45, 0x91, 0x4c, 0x49, 0x7b, 0x5d, 0x69, 0x6d, 0x0a, 0x99, 0x78, 0xdf, 0x88, 0x1d, 0xd0, 0xad, + 0x8a, 0xe8, 0x77, 0x7e, 0x3c, 0x7f, 0xfa, 0x54, 0x4f, 0xfe, 0xfe, 0x4f, 0x54, 0x5b, 0xda, 0x2f, + 0x3f, 0xdd, 0xcb, 0x3c, 0xca, 0xb0, 0xdf, 0xcb, 0x40, 0x35, 0xf1, 0x3a, 0x48, 0x22, 0x6f, 0x7d, + 0x6a, 0x9c, 0x4d, 0x1d, 0xa7, 0x0f, 0xd4, 0x30, 0x71, 0x12, 0x77, 0xee, 0x7f, 0x3f, 0xb1, 0x48, + 0x5f, 0x25, 0x22, 0x70, 0x0f, 0xa6, 0x7f, 0x08, 0xe8, 0xeb, 0x69, 0x02, 0xfd, 0x99, 0xbd, 0xaf, + 0x1f, 0x65, 0xd8, 0xbf, 0xcb, 0x40, 0x3d, 0x19, 0x5a, 0x8f, 0x86, 0x9b, 0x1a, 0xc4, 0x8f, 0x58, + 0xe9, 0x8a, 0x78, 0xfc, 0x0f, 0xb1, 0x97, 0xbd, 0xfb, 0x66, 0xa2, 0x97, 0xf2, 0xb1, 0xe3, 0x5f, + 0xac, 0xb7, 0xec, 0x63, 0xfa, 0xdd, 0x3d, 0x95, 0x47, 0xc4, 0x66, 0x7f, 0xa7, 0x2d, 0x62, 0x3f, + 0xfd, 0x57, 0xcd, 0x70, 0x11, 0x7e, 0x4c, 0x3f, 0x78, 0xa3, 0xd2, 0x52, 0x04, 0x17, 0xbf, 0x6c, + 0x79, 0xe3, 0x75, 0x1c, 0xd3, 0x2b, 0xc6, 0xf5, 0xc4, 0x98, 0xa6, 0x15, 0x8f, 0x16, 0xf5, 0x4e, + 0xfe, 0x28, 0x59, 0x7c, 0x72, 0xce, 0xfc, 0x50, 0xd9, 0xd5, 0x9d, 0x1c, 0x51, 0x27, 0x25, 0x79, + 0x62, 0xab, 0xbd, 0x64, 0x35, 0xc6, 0x7d, 0xec, 0xeb, 0xeb, 0xc6, 0xed, 0x2b, 0xfb, 0xfa, 0x10, + 0xc3, 0xe4, 0xa2, 0xc7, 0x07, 0x00, 0x71, 0x9e, 0x1f, 0x9b, 0xca, 0x36, 0x8b, 0x04, 0xd0, 0x6c, + 0x2a, 0x60, 0x72, 0x3f, 0xab, 0xa4, 0x34, 0x51, 0xe3, 0x8f, 0x48, 0x9c, 0x46, 0x79, 0x70, 0xba, + 0xf6, 0x95, 0x4c, 0xc9, 0x4b, 0x68, 0x5f, 0xd3, 0xf5, 0x27, 0x84, 0x69, 0x94, 0xf4, 0x76, 0x08, + 0xb5, 0x1d, 0xcf, 0x7b, 0x36, 0x19, 0x47, 0xb9, 0xe5, 0xc9, 0xdc, 0x95, 0x6d, 0x3b, 0x38, 0x5d, + 0x9b, 0x1a, 0x85, 0x71, 0x07, 0xab, 0x5a, 0x63, 0x4d, 0xad, 0xaa, 0x87, 0x5f, 0xc5, 0xc9, 0x85, + 0x5f, 0x33, 0x1b, 0x16, 0x22, 0x19, 0x1d, 0x27, 0xf0, 0x25, 0xab, 0x49, 0x48, 0xe6, 0xe9, 0x26, + 0x12, 0x66, 0x82, 0xea, 0xed, 0xc3, 0x40, 0xd5, 0xf9, 0x28, 0xc3, 0x0e, 0xa0, 0xba, 0xc9, 0xfb, + 0x78, 0x4b, 0x1e, 0x33, 0x40, 0x16, 0x13, 0xd9, 0x04, 0x94, 0x3a, 0xb2, 0x56, 0x4b, 0x00, 0x93, + 0xe7, 0xd6, 0xd8, 0xbe, 0xf4, 0xf9, 0x97, 0x0f, 0xbf, 0x92, 0xb9, 0x25, 0x5f, 0xab, 0x73, 0x4b, + 0xe5, 0xde, 0x24, 0xce, 0xad, 0xa9, 0x64, 0x9d, 0xc4, 0xb9, 0x35, 0x93, 0xac, 0x93, 0x98, 0x6a, + 0x95, 0xfb, 0xc3, 0x86, 0xb0, 0x30, 0x93, 0xdf, 0x13, 0x1d, 0x59, 0x57, 0x65, 0x05, 0xad, 0xdd, + 0xb9, 0x9a, 0x20, 0xd9, 0xda, 0xfd, 0x64, 0x6b, 0x5d, 0xa8, 0xd1, 0xcb, 0x7f, 0x47, 0x9c, 0xee, + 0xcb, 0x4d, 0x3d, 0x36, 0xa3, 0x5f, 0xc6, 0x9b, 0x3e, 0x60, 0x10, 0x97, 0xd4, 0x70, 0xf0, 0xa2, + 0x1a, 0xfb, 0x11, 0x54, 0x9e, 0xf0, 0x50, 0x5d, 0x90, 0x8b, 0x74, 0xec, 0xa9, 0x1b, 0x73, 0x6b, + 0x29, 0xf7, 0xeb, 0x92, 0x3c, 0x83, 0xb5, 0x3d, 0xe4, 0x83, 0x13, 0x4e, 0xc2, 0xc9, 0x72, 0x06, + 0x5f, 0xb3, 0x1f, 0x60, 0xe5, 0xd1, 0xbd, 0xe4, 0x15, 0xed, 0x06, 0x94, 0x5e, 0xf9, 0xfc, 0x14, + 0x3c, 0xad, 0x66, 0xd7, 0x1b, 0x70, 0x4d, 0xd7, 0x73, 0xa1, 0xa2, 0xbd, 0x5f, 0x10, 0x6d, 0xa0, + 0xd9, 0xf7, 0x2a, 0xa2, 0x0d, 0x94, 0xf2, 0xdc, 0x81, 0x71, 0x0f, 0xdb, 0x31, 0xd8, 0x9d, 0xb8, + 0x1d, 0x7a, 0xe2, 0x20, 0x6e, 0xe9, 0xe1, 0x57, 0xf6, 0x28, 0xfc, 0x9a, 0x7d, 0x8e, 0xef, 0x6b, + 0xeb, 0x17, 0x00, 0x63, 0xa3, 0x61, 0xfa, 0xae, 0x60, 0x34, 0x59, 0x1a, 0x2a, 0x69, 0x48, 0x50, + 0x53, 0xa8, 0xc9, 0xbd, 0x0f, 0xd0, 0x0d, 0xbd, 0xf1, 0xa6, 0xcd, 0x47, 0x9e, 0x1b, 0xcb, 0xda, + 0xf8, 0x4a, 0x5a, 0x2c, 0xbf, 0xb4, 0x7b, 0x69, 0xec, 0x73, 0xcd, 0xca, 0x4a, 0xdc, 0xa1, 0x54, + 0xcc, 0x75, 0xe5, 0xad, 0xb5, 0x68, 0x42, 0x52, 0x6e, 0xae, 0x3d, 0xca, 0xb0, 0x16, 0x40, 0x9c, + 0xe0, 0x15, 0xd9, 0x4c, 0x33, 0xb9, 0x63, 0x91, 0xd8, 0x4b, 0xc9, 0x06, 0x3b, 0x80, 0x72, 0x9c, + 0x19, 0xb3, 0x1a, 0x3f, 0xc7, 0x92, 0xc8, 0xa3, 0x89, 0x4e, 0xf0, 0x99, 0xac, 0x14, 0xa3, 0x81, + 0x53, 0x05, 0xac, 0x24, 0xa6, 0xea, 0x98, 0xf3, 0x80, 0x39, 0xb0, 0x48, 0x1d, 0x8c, 0xd4, 0x25, + 0xbc, 0x4a, 0x15, 0x3d, 0xa3, 0x3e, 0x9b, 0x20, 0x12, 0xed, 0xe6, 0xd4, 0x34, 0x87, 0x84, 0xeb, + 0x47, 0x70, 0x2b, 0x5d, 0xe3, 0x12, 0xa2, 0x79, 0x04, 0x0b, 0x33, 0x91, 0xf4, 0x68, 0x4b, 0x5f, + 0x95, 0x1a, 0x11, 0x6d, 0xe9, 0x2b, 0x83, 0xf0, 0xc6, 0x32, 0x36, 0x39, 0x6f, 0x00, 0x9a, 0x7a, + 0xe7, 0x4e, 0xd8, 0x3f, 0x15, 0xcd, 0xfd, 0xeb, 0x0c, 0x2c, 0xa6, 0xc4, 0xca, 0xd9, 0xab, 0xca, + 0x6b, 0x70, 0x65, 0x1c, 0x7d, 0x2d, 0x35, 0xa6, 0x6a, 0x74, 0xb1, 0x9d, 0x5d, 0xf6, 0x34, 0x71, + 0xb0, 0x51, 0x48, 0x53, 0xee, 0xcc, 0xe7, 0x2a, 0x15, 0xa9, 0x1a, 0xc5, 0x97, 0xb0, 0x4a, 0x1d, + 0x69, 0x0d, 0x87, 0x53, 0xf1, 0xde, 0x57, 0x66, 0x7e, 0x97, 0x3b, 0x11, 0xc3, 0x5e, 0xbb, 0xfa, + 0x77, 0xbb, 0xaf, 0x50, 0xa7, 0xa9, 0xab, 0x6c, 0x02, 0x8d, 0xe9, 0x38, 0x2a, 0xbb, 0xba, 0xae, + 0xb5, 0xdb, 0x09, 0xfb, 0x37, 0x25, 0xf6, 0xfa, 0x1d, 0x6c, 0xec, 0xb6, 0xb1, 0x96, 0x36, 0x2f, + 0x64, 0x12, 0x8b, 0xf5, 0xf8, 0x1b, 0x51, 0xd0, 0x77, 0x6a, 0x9c, 0xaa, 0x81, 0xab, 0x42, 0xd4, + 0x91, 0x05, 0x9e, 0x1e, 0x33, 0x7e, 0x03, 0x9b, 0xbf, 0x63, 0xdc, 0x48, 0x6b, 0xde, 0xa7, 0x22, + 0x64, 0x8b, 0xaf, 0x4e, 0xef, 0x6b, 0xd5, 0x83, 0x3b, 0x69, 0xeb, 0x7d, 0xa5, 0x2d, 0x34, 0x35, + 0xd7, 0xd7, 0x50, 0xb7, 0xab, 0xea, 0x41, 0xde, 0x68, 0xfb, 0xa4, 0x44, 0x93, 0xa3, 0xed, 0x93, + 0x16, 0x15, 0x4e, 0xea, 0x35, 0x2a, 0x1e, 0xfc, 0x71, 0xe6, 0xfe, 0xfa, 0xdd, 0x1f, 0x7e, 0xe7, + 0xc4, 0x09, 0x4f, 0x27, 0x47, 0x0f, 0xfa, 0xde, 0xe8, 0xe1, 0x50, 0x79, 0x1b, 0xe5, 0x7d, 0xe3, + 0x87, 0x43, 0x77, 0xf0, 0x10, 0xab, 0x3d, 0x9a, 0x1b, 0xfb, 0x5e, 0xe8, 0x7d, 0xf7, 0xff, 0x05, + 0x00, 0x00, 0xff, 0xff, 0x41, 0x79, 0x30, 0x63, 0x7a, 0x80, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 6965d3ee82..b5b3ebb01b 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -3114,3 +3114,163 @@ message BakeMacaroonResponse { /// The hex encoded macaroon, serialized in binary format. string macaroon = 1; } + + +message Failure { + enum FailureCode { + /** + The numbers assigned in this enumeration match the failure codes as + defined in BOLT #4. Because protobuf 3 requires enums to start with 0, + a RESERVED value is added. + */ + RESERVED = 0; + + INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS = 1; + INCORRECT_PAYMENT_AMOUNT = 2; + FINAL_INCORRECT_CLTV_EXPIRY = 3; + FINAL_INCORRECT_HTLC_AMOUNT = 4; + FINAL_EXPIRY_TOO_SOON = 5; + INVALID_REALM = 6; + EXPIRY_TOO_SOON = 7; + INVALID_ONION_VERSION = 8; + INVALID_ONION_HMAC = 9; + INVALID_ONION_KEY = 10; + AMOUNT_BELOW_MINIMUM = 11; + FEE_INSUFFICIENT = 12; + INCORRECT_CLTV_EXPIRY = 13; + CHANNEL_DISABLED = 14; + TEMPORARY_CHANNEL_FAILURE = 15; + REQUIRED_NODE_FEATURE_MISSING = 16; + REQUIRED_CHANNEL_FEATURE_MISSING = 17; + UNKNOWN_NEXT_PEER = 18; + TEMPORARY_NODE_FAILURE = 19; + PERMANENT_NODE_FAILURE = 20; + PERMANENT_CHANNEL_FAILURE = 21; + EXPIRY_TOO_FAR = 22; + MPP_TIMEOUT = 23; + + /** + The error source is known, but the failure itself couldn't be decoded. + */ + UNKNOWN_FAILURE = 998; + + /** + An unreadable failure result is returned if the received failure message + cannot be decrypted. In that case the error source is unknown. + */ + UNREADABLE_FAILURE = 999; + } + + /// Failure code as defined in the Lightning spec + FailureCode code = 1; + + reserved 2; + + /// An optional channel update message. + ChannelUpdate channel_update = 3; + + /// A failure type-dependent htlc value. + uint64 htlc_msat = 4; + + /// The sha256 sum of the onion payload. + bytes onion_sha_256 = 5; + + /// A failure type-dependent cltv expiry value. + uint32 cltv_expiry = 6; + + /// A failure type-dependent flags value. + uint32 flags = 7; + + /** + The position in the path of the intermediate or final node that generated + the failure message. Position zero is the sender node. + **/ + uint32 failure_source_index = 8; + + /// A failure type-dependent block height. + uint32 height = 9; +} + + +message ChannelUpdate { + /** + The signature that validates the announced data and proves the ownership + of node id. + */ + bytes signature = 1; + + /** + The target chain that this channel was opened within. This value + should be the genesis hash of the target chain. Along with the short + channel ID, this uniquely identifies the channel globally in a + blockchain. + */ + bytes chain_hash = 2; + + /** + The unique description of the funding transaction. + */ + uint64 chan_id = 3 [jstype = JS_STRING]; + + /** + A timestamp that allows ordering in the case of multiple announcements. + We should ignore the message if timestamp is not greater than the + last-received. + */ + uint32 timestamp = 4; + + /** + The bitfield that describes whether optional fields are present in this + update. Currently, the least-significant bit must be set to 1 if the + optional field MaxHtlc is present. + */ + uint32 message_flags = 10; + + /** + The bitfield that describes additional meta-data concerning how the + update is to be interpreted. Currently, the least-significant bit must be + set to 0 if the creating node corresponds to the first node in the + previously sent channel announcement and 1 otherwise. If the second bit + is set, then the channel is set to be disabled. + */ + uint32 channel_flags = 5; + + /** + The minimum number of blocks this node requires to be added to the expiry + of HTLCs. This is a security parameter determined by the node operator. + This value represents the required gap between the time locks of the + incoming and outgoing HTLC's set to this node. + */ + uint32 time_lock_delta = 6; + + /** + The minimum HTLC value which will be accepted. + */ + uint64 htlc_minimum_msat = 7; + + /** + The base fee that must be used for incoming HTLC's to this particular + channel. This value will be tacked onto the required for a payment + independent of the size of the payment. + */ + uint32 base_fee = 8; + + /** + The fee rate that will be charged per millionth of a satoshi. + */ + uint32 fee_rate = 9; + + /** + The maximum HTLC value which will be accepted. + */ + uint64 htlc_maximum_msat = 11; + + /** + The set of data that was appended to this message, some of which we may + not actually know how to iterate or parse. By holding onto this data, we + ensure that we're able to properly validate the set of signatures that + cover these new fields, and ensure we're able to make upgrades to the + network in a forwards compatible manner. + */ + bytes extra_opaque_data = 12; +} \ No newline at end of file From 3f5ba35deab4412000649231f4e6489f35e7a02b Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 20 Feb 2020 10:45:17 +0100 Subject: [PATCH 152/562] routerrpc: move marshall functions out of conditionally compiled file These functions will (indirectly) be called by the main rpc server and can no longer stay conditionally compiled. --- lnrpc/routerrpc/router_backend.go | 151 ++++++++++++++++++++++++++++++ lnrpc/routerrpc/router_server.go | 151 ------------------------------ 2 files changed, 151 insertions(+), 151 deletions(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 4802902e36..5e9f8f6dd7 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -883,3 +884,153 @@ func MarshalTimeNano(t time.Time) int64 { } return t.UnixNano() } + +// marshallError marshall an error as received from the switch to rpc structs +// suitable for returning to the caller of an rpc method. +// +// Because of difficulties with using protobuf oneof constructs in some +// languages, the decision was made here to use a single message format for all +// failure messages with some fields left empty depending on the failure type. +func marshallError(sendError error) (*lnrpc.Failure, error) { + response := &lnrpc.Failure{} + + if sendError == htlcswitch.ErrUnreadableFailureMessage { + response.Code = lnrpc.Failure_UNREADABLE_FAILURE + return response, nil + } + + rtErr, ok := sendError.(htlcswitch.ClearTextError) + if !ok { + return nil, sendError + } + + switch onionErr := rtErr.WireMessage().(type) { + + case *lnwire.FailIncorrectDetails: + response.Code = lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS + response.Height = onionErr.Height() + + case *lnwire.FailIncorrectPaymentAmount: + response.Code = lnrpc.Failure_INCORRECT_PAYMENT_AMOUNT + + case *lnwire.FailFinalIncorrectCltvExpiry: + response.Code = lnrpc.Failure_FINAL_INCORRECT_CLTV_EXPIRY + response.CltvExpiry = onionErr.CltvExpiry + + case *lnwire.FailFinalIncorrectHtlcAmount: + response.Code = lnrpc.Failure_FINAL_INCORRECT_HTLC_AMOUNT + response.HtlcMsat = uint64(onionErr.IncomingHTLCAmount) + + case *lnwire.FailFinalExpiryTooSoon: + response.Code = lnrpc.Failure_FINAL_EXPIRY_TOO_SOON + + case *lnwire.FailInvalidRealm: + response.Code = lnrpc.Failure_INVALID_REALM + + case *lnwire.FailExpiryTooSoon: + response.Code = lnrpc.Failure_EXPIRY_TOO_SOON + response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) + + case *lnwire.FailExpiryTooFar: + response.Code = lnrpc.Failure_EXPIRY_TOO_FAR + + case *lnwire.FailInvalidOnionVersion: + response.Code = lnrpc.Failure_INVALID_ONION_VERSION + response.OnionSha_256 = onionErr.OnionSHA256[:] + + case *lnwire.FailInvalidOnionHmac: + response.Code = lnrpc.Failure_INVALID_ONION_HMAC + response.OnionSha_256 = onionErr.OnionSHA256[:] + + case *lnwire.FailInvalidOnionKey: + response.Code = lnrpc.Failure_INVALID_ONION_KEY + response.OnionSha_256 = onionErr.OnionSHA256[:] + + case *lnwire.FailAmountBelowMinimum: + response.Code = lnrpc.Failure_AMOUNT_BELOW_MINIMUM + response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) + response.HtlcMsat = uint64(onionErr.HtlcMsat) + + case *lnwire.FailFeeInsufficient: + response.Code = lnrpc.Failure_FEE_INSUFFICIENT + response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) + response.HtlcMsat = uint64(onionErr.HtlcMsat) + + case *lnwire.FailIncorrectCltvExpiry: + response.Code = lnrpc.Failure_INCORRECT_CLTV_EXPIRY + response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) + response.CltvExpiry = onionErr.CltvExpiry + + case *lnwire.FailChannelDisabled: + response.Code = lnrpc.Failure_CHANNEL_DISABLED + response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) + response.Flags = uint32(onionErr.Flags) + + case *lnwire.FailTemporaryChannelFailure: + response.Code = lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE + response.ChannelUpdate = marshallChannelUpdate(onionErr.Update) + + case *lnwire.FailRequiredNodeFeatureMissing: + response.Code = lnrpc.Failure_REQUIRED_NODE_FEATURE_MISSING + + case *lnwire.FailRequiredChannelFeatureMissing: + response.Code = lnrpc.Failure_REQUIRED_CHANNEL_FEATURE_MISSING + + case *lnwire.FailUnknownNextPeer: + response.Code = lnrpc.Failure_UNKNOWN_NEXT_PEER + + case *lnwire.FailTemporaryNodeFailure: + response.Code = lnrpc.Failure_TEMPORARY_NODE_FAILURE + + case *lnwire.FailPermanentNodeFailure: + response.Code = lnrpc.Failure_PERMANENT_NODE_FAILURE + + case *lnwire.FailPermanentChannelFailure: + response.Code = lnrpc.Failure_PERMANENT_CHANNEL_FAILURE + + case *lnwire.FailMPPTimeout: + response.Code = lnrpc.Failure_MPP_TIMEOUT + + case nil: + response.Code = lnrpc.Failure_UNKNOWN_FAILURE + + default: + return nil, fmt.Errorf("cannot marshall failure %T", onionErr) + } + + // If the ClearTextError received is a ForwardingError, the error + // originated from a node along the route, not locally on our outgoing + // link. We set failureSourceIdx to the index of the node where the + // failure occurred. If the error is not a ForwardingError, the failure + // occurred at our node, so we leave the index as 0 to indicate that + // we failed locally. + fErr, ok := rtErr.(*htlcswitch.ForwardingError) + if ok { + response.FailureSourceIndex = uint32(fErr.FailureSourceIdx) + } + + return response, nil +} + +// marshallChannelUpdate marshalls a channel update as received over the wire to +// the router rpc format. +func marshallChannelUpdate(update *lnwire.ChannelUpdate) *lnrpc.ChannelUpdate { + if update == nil { + return nil + } + + return &lnrpc.ChannelUpdate{ + Signature: update.Signature[:], + ChainHash: update.ChainHash[:], + ChanId: update.ShortChannelID.ToUint64(), + Timestamp: update.Timestamp, + MessageFlags: uint32(update.MessageFlags), + ChannelFlags: uint32(update.ChannelFlags), + TimeLockDelta: uint32(update.TimeLockDelta), + HtlcMinimumMsat: uint64(update.HtlcMinimumMsat), + BaseFee: update.BaseFee, + FeeRate: update.FeeRate, + HtlcMaximumMsat: uint64(update.HtlcMaximumMsat), + ExtraOpaqueData: update.ExtraOpaqueData, + } +} diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 069b145c9f..ed02a6fcd0 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -12,7 +12,6 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -312,156 +311,6 @@ func (s *Server) SendToRoute(ctx context.Context, }, nil } -// marshallError marshall an error as received from the switch to rpc structs -// suitable for returning to the caller of an rpc method. -// -// Because of difficulties with using protobuf oneof constructs in some -// languages, the decision was made here to use a single message format for all -// failure messages with some fields left empty depending on the failure type. -func marshallError(sendError error) (*lnrpc.Failure, error) { - response := &lnrpc.Failure{} - - if sendError == htlcswitch.ErrUnreadableFailureMessage { - response.Code = lnrpc.Failure_UNREADABLE_FAILURE - return response, nil - } - - rtErr, ok := sendError.(htlcswitch.ClearTextError) - if !ok { - return nil, sendError - } - - switch onionErr := rtErr.WireMessage().(type) { - - case *lnwire.FailIncorrectDetails: - response.Code = lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS - response.Height = onionErr.Height() - - case *lnwire.FailIncorrectPaymentAmount: - response.Code = lnrpc.Failure_INCORRECT_PAYMENT_AMOUNT - - case *lnwire.FailFinalIncorrectCltvExpiry: - response.Code = lnrpc.Failure_FINAL_INCORRECT_CLTV_EXPIRY - response.CltvExpiry = onionErr.CltvExpiry - - case *lnwire.FailFinalIncorrectHtlcAmount: - response.Code = lnrpc.Failure_FINAL_INCORRECT_HTLC_AMOUNT - response.HtlcMsat = uint64(onionErr.IncomingHTLCAmount) - - case *lnwire.FailFinalExpiryTooSoon: - response.Code = lnrpc.Failure_FINAL_EXPIRY_TOO_SOON - - case *lnwire.FailInvalidRealm: - response.Code = lnrpc.Failure_INVALID_REALM - - case *lnwire.FailExpiryTooSoon: - response.Code = lnrpc.Failure_EXPIRY_TOO_SOON - response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) - - case *lnwire.FailExpiryTooFar: - response.Code = lnrpc.Failure_EXPIRY_TOO_FAR - - case *lnwire.FailInvalidOnionVersion: - response.Code = lnrpc.Failure_INVALID_ONION_VERSION - response.OnionSha_256 = onionErr.OnionSHA256[:] - - case *lnwire.FailInvalidOnionHmac: - response.Code = lnrpc.Failure_INVALID_ONION_HMAC - response.OnionSha_256 = onionErr.OnionSHA256[:] - - case *lnwire.FailInvalidOnionKey: - response.Code = lnrpc.Failure_INVALID_ONION_KEY - response.OnionSha_256 = onionErr.OnionSHA256[:] - - case *lnwire.FailAmountBelowMinimum: - response.Code = lnrpc.Failure_AMOUNT_BELOW_MINIMUM - response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) - response.HtlcMsat = uint64(onionErr.HtlcMsat) - - case *lnwire.FailFeeInsufficient: - response.Code = lnrpc.Failure_FEE_INSUFFICIENT - response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) - response.HtlcMsat = uint64(onionErr.HtlcMsat) - - case *lnwire.FailIncorrectCltvExpiry: - response.Code = lnrpc.Failure_INCORRECT_CLTV_EXPIRY - response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) - response.CltvExpiry = onionErr.CltvExpiry - - case *lnwire.FailChannelDisabled: - response.Code = lnrpc.Failure_CHANNEL_DISABLED - response.ChannelUpdate = marshallChannelUpdate(&onionErr.Update) - response.Flags = uint32(onionErr.Flags) - - case *lnwire.FailTemporaryChannelFailure: - response.Code = lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE - response.ChannelUpdate = marshallChannelUpdate(onionErr.Update) - - case *lnwire.FailRequiredNodeFeatureMissing: - response.Code = lnrpc.Failure_REQUIRED_NODE_FEATURE_MISSING - - case *lnwire.FailRequiredChannelFeatureMissing: - response.Code = lnrpc.Failure_REQUIRED_CHANNEL_FEATURE_MISSING - - case *lnwire.FailUnknownNextPeer: - response.Code = lnrpc.Failure_UNKNOWN_NEXT_PEER - - case *lnwire.FailTemporaryNodeFailure: - response.Code = lnrpc.Failure_TEMPORARY_NODE_FAILURE - - case *lnwire.FailPermanentNodeFailure: - response.Code = lnrpc.Failure_PERMANENT_NODE_FAILURE - - case *lnwire.FailPermanentChannelFailure: - response.Code = lnrpc.Failure_PERMANENT_CHANNEL_FAILURE - - case *lnwire.FailMPPTimeout: - response.Code = lnrpc.Failure_MPP_TIMEOUT - - case nil: - response.Code = lnrpc.Failure_UNKNOWN_FAILURE - - default: - return nil, fmt.Errorf("cannot marshall failure %T", onionErr) - } - - // If the ClearTextError received is a ForwardingError, the error - // originated from a node along the route, not locally on our outgoing - // link. We set failureSourceIdx to the index of the node where the - // failure occurred. If the error is not a ForwardingError, the failure - // occurred at our node, so we leave the index as 0 to indicate that - // we failed locally. - fErr, ok := rtErr.(*htlcswitch.ForwardingError) - if ok { - response.FailureSourceIndex = uint32(fErr.FailureSourceIdx) - } - - return response, nil -} - -// marshallChannelUpdate marshalls a channel update as received over the wire to -// the router rpc format. -func marshallChannelUpdate(update *lnwire.ChannelUpdate) *lnrpc.ChannelUpdate { - if update == nil { - return nil - } - - return &lnrpc.ChannelUpdate{ - Signature: update.Signature[:], - ChainHash: update.ChainHash[:], - ChanId: update.ShortChannelID.ToUint64(), - Timestamp: update.Timestamp, - MessageFlags: uint32(update.MessageFlags), - ChannelFlags: uint32(update.ChannelFlags), - TimeLockDelta: uint32(update.TimeLockDelta), - HtlcMinimumMsat: uint64(update.HtlcMinimumMsat), - BaseFee: update.BaseFee, - FeeRate: update.FeeRate, - HtlcMaximumMsat: uint64(update.HtlcMaximumMsat), - ExtraOpaqueData: update.ExtraOpaqueData, - } -} - // ResetMissionControl clears all mission control state and starts with a clean // slate. func (s *Server) ResetMissionControl(ctx context.Context, From e6e9e44e6f63ea9c7910a7a606931bba223cb3ae Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 19 Feb 2020 17:20:43 +0100 Subject: [PATCH 153/562] routerrpc: extract wire error marshalling Preparation for marshalling wire errors as part of rpc payment lookups. --- lnrpc/routerrpc/router_backend.go | 45 +++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 5e9f8f6dd7..e8957afa9a 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -904,7 +904,35 @@ func marshallError(sendError error) (*lnrpc.Failure, error) { return nil, sendError } - switch onionErr := rtErr.WireMessage().(type) { + err := marshallWireError(rtErr.WireMessage(), response) + if err != nil { + return nil, err + } + + // If the ClearTextError received is a ForwardingError, the error + // originated from a node along the route, not locally on our outgoing + // link. We set failureSourceIdx to the index of the node where the + // failure occurred. If the error is not a ForwardingError, the failure + // occurred at our node, so we leave the index as 0 to indicate that + // we failed locally. + fErr, ok := rtErr.(*htlcswitch.ForwardingError) + if ok { + response.FailureSourceIndex = uint32(fErr.FailureSourceIdx) + } + + return response, nil +} + +// marshallError marshall an error as received from the switch to rpc structs +// suitable for returning to the caller of an rpc method. +// +// Because of difficulties with using protobuf oneof constructs in some +// languages, the decision was made here to use a single message format for all +// failure messages with some fields left empty depending on the failure type. +func marshallWireError(msg lnwire.FailureMessage, + response *lnrpc.Failure) error { + + switch onionErr := msg.(type) { case *lnwire.FailIncorrectDetails: response.Code = lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS @@ -995,21 +1023,10 @@ func marshallError(sendError error) (*lnrpc.Failure, error) { response.Code = lnrpc.Failure_UNKNOWN_FAILURE default: - return nil, fmt.Errorf("cannot marshall failure %T", onionErr) + return fmt.Errorf("cannot marshall failure %T", onionErr) } - // If the ClearTextError received is a ForwardingError, the error - // originated from a node along the route, not locally on our outgoing - // link. We set failureSourceIdx to the index of the node where the - // failure occurred. If the error is not a ForwardingError, the failure - // occurred at our node, so we leave the index as 0 to indicate that - // we failed locally. - fErr, ok := rtErr.(*htlcswitch.ForwardingError) - if ok { - response.FailureSourceIndex = uint32(fErr.FailureSourceIdx) - } - - return response, nil + return nil } // marshallChannelUpdate marshalls a channel update as received over the wire to From fa3a762a2ce090b623d4f96955557ad45f59f580 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 20 Feb 2020 10:13:23 +0100 Subject: [PATCH 154/562] channeldb: add error return value to fetchPaymentStatus Preparation for when we need to return errors in a next commit. --- channeldb/payment_control.go | 31 +++++++++++++++++++------------ channeldb/payments.go | 11 +++++++++-- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index b6bcd5a11d..72c5c1993c 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -76,7 +76,10 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, } // Get the existing status of this payment, if any. - paymentStatus := fetchPaymentStatus(bucket) + paymentStatus, err := fetchPaymentStatus(bucket) + if err != nil { + return err + } switch paymentStatus { @@ -358,27 +361,30 @@ func nextPaymentSequence(tx *bbolt.Tx) ([]byte, error) { // fetchPaymentStatus fetches the payment status of the payment. If the payment // isn't found, it will default to "StatusUnknown". -func fetchPaymentStatus(bucket *bbolt.Bucket) PaymentStatus { +func fetchPaymentStatus(bucket *bbolt.Bucket) (PaymentStatus, error) { if bucket.Get(paymentSettleInfoKey) != nil { - return StatusSucceeded + return StatusSucceeded, nil } if bucket.Get(paymentFailInfoKey) != nil { - return StatusFailed + return StatusFailed, nil } if bucket.Get(paymentCreationInfoKey) != nil { - return StatusInFlight + return StatusInFlight, nil } - return StatusUnknown + return StatusUnknown, nil } // ensureInFlight checks whether the payment found in the given bucket has // status InFlight, and returns an error otherwise. This should be used to // ensure we only mark in-flight payments as succeeded or failed. func ensureInFlight(bucket *bbolt.Bucket) error { - paymentStatus := fetchPaymentStatus(bucket) + paymentStatus, err := fetchPaymentStatus(bucket) + if err != nil { + return err + } switch { @@ -443,15 +449,16 @@ func (p *PaymentControl) FetchInFlightPayments() ([]*InFlightPayment, error) { } // If the status is not InFlight, we can return early. - paymentStatus := fetchPaymentStatus(bucket) + paymentStatus, err := fetchPaymentStatus(bucket) + if err != nil { + return err + } + if paymentStatus != StatusInFlight { return nil } - var ( - inFlight = &InFlightPayment{} - err error - ) + inFlight := &InFlightPayment{} // Get the CreationInfo. b := bucket.Get(paymentCreationInfoKey) diff --git a/channeldb/payments.go b/channeldb/payments.go index 64f4f1c7c0..fc5e38bc20 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -337,7 +337,10 @@ func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) { p.sequenceNum = binary.BigEndian.Uint64(seqBytes) // Get the payment status. - p.Status = fetchPaymentStatus(bucket) + p.Status, err = fetchPaymentStatus(bucket) + if err != nil { + return nil, err + } // Get the PaymentCreationInfo. b := bucket.Get(paymentCreationInfoKey) @@ -401,7 +404,11 @@ func (db *DB) DeletePayments() error { // If the status is InFlight, we cannot safely delete // the payment information, so we return early. - paymentStatus := fetchPaymentStatus(bucket) + paymentStatus, err := fetchPaymentStatus(bucket) + if err != nil { + return err + } + if paymentStatus == StatusInFlight { return nil } From 4c74c0817e7a3e75f8f3de02bd790c7f0854cb6b Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 20 Feb 2020 14:56:24 +0100 Subject: [PATCH 155/562] channeldb/test: extend payment control test with failed attempt --- channeldb/payment_control_test.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 5272ec79a6..063a2e6f5b 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -116,9 +116,18 @@ func TestPaymentControlSwitchFail(t *testing.T) { nil, ) - // Record a new attempt. + // Record a new attempt. In this test scenario, the attempt fails. + // However, this is not communicated to control tower in the current + // implementation. It only registers the initiation of the attempt. attempt.AttemptID = 2 err = pControl.RegisterAttempt(info.PaymentHash, attempt) + if err != nil { + t.Fatalf("unable to register attempt: %v", err) + } + + // Record another attempt. + attempt.AttemptID = 3 + err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) } @@ -128,7 +137,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { nil, ) - // Verifies that status was changed to StatusSucceeded. + // Settle the attempt and verify that status was changed to StatusSucceeded. var payment *MPPayment payment, err = pControl.Success(info.PaymentHash, preimg) if err != nil { From c357511051d23eb47befe2be0f563acdac39f971 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 21 Feb 2020 14:13:40 +0100 Subject: [PATCH 156/562] channeldb/migtest: remove channeldb dependency Removes this unnecessary dependency allowing migration code to use utility functions from channeldb/migtest. --- channeldb/migtest/migtest.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/channeldb/migtest/migtest.go b/channeldb/migtest/migtest.go index b6ecbafade..b2200ebf71 100644 --- a/channeldb/migtest/migtest.go +++ b/channeldb/migtest/migtest.go @@ -7,32 +7,30 @@ import ( "testing" "github.com/coreos/bbolt" - "github.com/lightningnetwork/lnd/channeldb" ) // MakeDB creates a new instance of the ChannelDB for testing purposes. A // callback which cleans up the created temporary directories is also returned // and intended to be executed after the test completes. -func MakeDB() (*channeldb.DB, func(), error) { - // First, create a temporary directory to be used for the duration of - // this test. - tempDirName, err := ioutil.TempDir("", "channeldb") +func MakeDB() (*bbolt.DB, func(), error) { + // Create temporary database for mission control. + file, err := ioutil.TempFile("", "*.db") if err != nil { return nil, nil, err } - // Next, create channeldb for the first time. - cdb, err := channeldb.Open(tempDirName) + dbPath := file.Name() + db, err := bbolt.Open(dbPath, 0600, nil) if err != nil { return nil, nil, err } cleanUp := func() { - cdb.Close() - os.RemoveAll(tempDirName) + db.Close() + os.RemoveAll(dbPath) } - return cdb, cleanUp, nil + return db, cleanUp, nil } // ApplyMigration is a helper test function that encapsulates the general steps From 8558534417add16c4496c8ea759f7984cfa3dfc0 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 5 Mar 2020 13:54:03 +0100 Subject: [PATCH 157/562] routing: add clock to router config --- routing/router.go | 8 ++++++-- routing/router_test.go | 3 +++ server.go | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/routing/router.go b/routing/router.go index 8dbb45de5a..a4b264e1bb 100644 --- a/routing/router.go +++ b/routing/router.go @@ -17,6 +17,7 @@ import ( sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lntypes" @@ -302,6 +303,9 @@ type Config struct { // PathFindingConfig defines global path finding parameters. PathFindingConfig PathFindingConfig + + // Clock is mockable time provider. + Clock clock.Clock } // EdgeLocator is a struct used to identify a specific edge. @@ -1680,7 +1684,7 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) ( info := &channeldb.PaymentCreationInfo{ PaymentHash: payment.PaymentHash, Value: payment.Amount, - CreationTime: time.Now(), + CreationTime: r.cfg.Clock.Now(), PaymentRequest: payment.PaymentRequest, } @@ -1709,7 +1713,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( info := &channeldb.PaymentCreationInfo{ PaymentHash: hash, Value: amt, - CreationTime: time.Now(), + CreationTime: r.cfg.Clock.Now(), PaymentRequest: nil, } diff --git a/routing/router_test.go b/routing/router_test.go index b3470d1c34..dd8908c4dd 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -19,6 +19,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -131,6 +132,7 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr return next, nil }, PathFindingConfig: pathFindingConfig, + Clock: clock.NewTestClock(time.Unix(1, 0)), }) if err != nil { return nil, nil, fmt.Errorf("unable to create router %v", err) @@ -2967,6 +2969,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { next := atomic.AddUint64(&uniquePaymentID, 1) return next, nil }, + Clock: clock.NewTestClock(time.Unix(1, 0)), }) if err != nil { t.Fatalf("unable to create router %v", err) diff --git a/server.go b/server.go index bde65671ad..fd0de26664 100644 --- a/server.go +++ b/server.go @@ -740,6 +740,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, AssumeChannelValid: cfg.Routing.UseAssumeChannelValid(), NextPaymentID: sequencer.NextID, PathFindingConfig: pathFindingConfig, + Clock: clock.NewDefaultClock(), }) if err != nil { return nil, fmt.Errorf("can't create router: %v", err) From 02dd8d23fd1a18c12decf03a22b9c2ca6d2e65e7 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:44 +0100 Subject: [PATCH 158/562] input/size: remove unused constants Since we never attempt to sweep an HTLC we offered with the preimage on the remote's commitment, we never use the constant AcceptedHtlcSuccessWitnessSize for weight estimation. Similarly, we never timout an HTLC offered by the remote on our own commitment, and don't need the constant OfferedHtlcTimeoutWitnessSize. --- input/size.go | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/input/size.go b/input/size.go index 68fa85e4e6..b0d28aa278 100644 --- a/input/size.go +++ b/input/size.go @@ -260,19 +260,6 @@ const ( // - witness_script: (accepted_htlc_script) AcceptedHtlcTimeoutWitnessSize = 1 + 1 + 73 + 1 + 1 + AcceptedHtlcScriptSize - // AcceptedHtlcSuccessWitnessSize 322 bytes - // - number_of_witness_elements: 1 byte - // - nil_length: 1 byte - // - sig_alice_length: 1 byte - // - sig_alice: 73 bytes - // - sig_bob_length: 1 byte - // - sig_bob: 73 bytes - // - preimage_length: 1 byte - // - preimage: 32 bytes - // - witness_script_length: 1 byte - // - witness_script (accepted_htlc_script) - AcceptedHtlcSuccessWitnessSize = 1 + 1 + 73 + 1 + 73 + 1 + 32 + 1 + AcceptedHtlcScriptSize - // AcceptedHtlcPenaltyWitnessSize 249 bytes // - number_of_witness_elements: 1 byte // - revocation_sig_length: 1 byte @@ -317,18 +304,6 @@ const ( // - OP_ENDIF: 1 byte OfferedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 10*1 + 33 + 5*1 + 20 + 4*1 - // OfferedHtlcTimeoutWitnessSize 285 bytes - // - number_of_witness_elements: 1 byte - // - nil_length: 1 byte - // - sig_alice_length: 1 byte - // - sig_alice: 73 bytes - // - sig_bob_length: 1 byte - // - sig_bob: 73 bytes - // - nil_length: 1 byte - // - witness_script_length: 1 byte - // - witness_script (offered_htlc_script) - OfferedHtlcTimeoutWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 1 + OfferedHtlcScriptSize - // OfferedHtlcSuccessWitnessSize 317 bytes // - number_of_witness_elements: 1 byte // - nil_length: 1 byte From 865776c7763833800d375285b7ea9772edf8e675 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:44 +0100 Subject: [PATCH 159/562] lnwallet/channel: use genHtlcScript to create scripts It takes into account the necessary variables and will prepare us for doing commitment type dependent script generation later. --- lnwallet/channel.go | 111 +++++++++++++------------------------------- 1 file changed, 33 insertions(+), 78 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index fa96f8c4a0..c60c591e70 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2157,11 +2157,6 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, // remote commitment transaction. htlcRetributions := make([]HtlcRetribution, 0, len(revokedSnapshot.Htlcs)) for _, htlc := range revokedSnapshot.Htlcs { - var ( - htlcWitnessScript []byte - err error - ) - // If the HTLC is dust, then we'll skip it as it doesn't have // an output on the commitment transaction. if htlcIsDust( @@ -2185,31 +2180,13 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, // If this is an incoming HTLC, then this means that they were // the sender of the HTLC (relative to us). So we'll - // re-generate the sender HTLC script. - if htlc.Incoming { - htlcWitnessScript, err = input.SenderHTLCScript( - keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey, - keyRing.RevocationKey, htlc.RHash[:], - ) - if err != nil { - return nil, err - } - - } else { - // Otherwise, is this was an outgoing HTLC that we - // sent, then from the PoV of the remote commitment - // state, they're the receiver of this HTLC. - htlcWitnessScript, err = input.ReceiverHTLCScript( - htlc.RefundTimeout, keyRing.LocalHtlcKey, - keyRing.RemoteHtlcKey, keyRing.RevocationKey, - htlc.RHash[:], - ) - if err != nil { - return nil, err - } - } - - htlcPkScript, err := input.WitnessScriptHash(htlcWitnessScript) + // re-generate the sender HTLC script. Otherwise, is this was + // an outgoing HTLC that we sent, then from the PoV of the + // remote commitment state, they're the receiver of this HTLC. + htlcPkScript, htlcWitnessScript, err := genHtlcScript( + htlc.Incoming, false, htlc.RefundTimeout, + htlc.RHash, keyRing, + ) if err != nil { return nil, err } @@ -5325,24 +5302,19 @@ func newOutgoingHtlcResolution(signer input.Signer, Index: uint32(htlc.OutputIndex), } + // First, we'll re-generate the script used to send the HTLC to + // the remote party within their commitment transaction. + htlcScriptHash, htlcScript, err := genHtlcScript( + false, localCommit, htlc.RefundTimeout, htlc.RHash, keyRing, + ) + if err != nil { + return nil, err + } + // If we're spending this HTLC output from the remote node's // commitment, then we won't need to go to the second level as our // outputs don't have a CSV delay. if !localCommit { - // First, we'll re-generate the script used to send the HTLC to - // the remote party within their commitment transaction. - htlcReceiverScript, err := input.ReceiverHTLCScript(htlc.RefundTimeout, - keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey, - keyRing.RevocationKey, htlc.RHash[:], - ) - if err != nil { - return nil, err - } - htlcScriptHash, err := input.WitnessScriptHash(htlcReceiverScript) - if err != nil { - return nil, err - } - // With the script generated, we can completely populated the // SignDescriptor needed to sweep the output. return &OutgoingHtlcResolution{ @@ -5351,7 +5323,7 @@ func newOutgoingHtlcResolution(signer input.Signer, SweepSignDesc: input.SignDescriptor{ KeyDesc: localChanCfg.HtlcBasePoint, SingleTweak: keyRing.LocalHtlcKeyTweak, - WitnessScript: htlcReceiverScript, + WitnessScript: htlcScript, Output: &wire.TxOut{ PkScript: htlcScriptHash, Value: int64(htlc.Amt.ToSatoshis()), @@ -5383,15 +5355,10 @@ func newOutgoingHtlcResolution(signer input.Signer, // With the transaction created, we can generate a sign descriptor // that's capable of generating the signature required to spend the // HTLC output using the timeout transaction. - htlcCreationScript, err := input.SenderHTLCScript(keyRing.LocalHtlcKey, - keyRing.RemoteHtlcKey, keyRing.RevocationKey, htlc.RHash[:]) - if err != nil { - return nil, err - } timeoutSignDesc := input.SignDescriptor{ KeyDesc: localChanCfg.HtlcBasePoint, SingleTweak: keyRing.LocalHtlcKeyTweak, - WitnessScript: htlcCreationScript, + WitnessScript: htlcScript, Output: &wire.TxOut{ Value: int64(htlc.Amt.ToSatoshis()), }, @@ -5419,7 +5386,7 @@ func newOutgoingHtlcResolution(signer input.Signer, if err != nil { return nil, err } - htlcScriptHash, err := input.WitnessScriptHash(htlcSweepScript) + htlcSweepScriptHash, err := input.WitnessScriptHash(htlcSweepScript) if err != nil { return nil, err } @@ -5440,7 +5407,7 @@ func newOutgoingHtlcResolution(signer input.Signer, SingleTweak: localDelayTweak, WitnessScript: htlcSweepScript, Output: &wire.TxOut{ - PkScript: htlcScriptHash, + PkScript: htlcSweepScriptHash, Value: int64(secondLevelOutputAmt), }, HashType: txscript.SigHashAll, @@ -5465,23 +5432,18 @@ func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.Chan Index: uint32(htlc.OutputIndex), } + // First, we'll re-generate the script the remote party used to + // send the HTLC to us in their commitment transaction. + htlcScriptHash, htlcScript, err := genHtlcScript( + true, localCommit, htlc.RefundTimeout, htlc.RHash, keyRing, + ) + if err != nil { + return nil, err + } + // If we're spending this output from the remote node's commitment, // then we can skip the second layer and spend the output directly. if !localCommit { - // First, we'll re-generate the script the remote party used to - // send the HTLC to us in their commitment transaction. - htlcSenderScript, err := input.SenderHTLCScript( - keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey, - keyRing.RevocationKey, htlc.RHash[:], - ) - if err != nil { - return nil, err - } - htlcScriptHash, err := input.WitnessScriptHash(htlcSenderScript) - if err != nil { - return nil, err - } - // With the script generated, we can completely populated the // SignDescriptor needed to sweep the output. return &IncomingHtlcResolution{ @@ -5490,7 +5452,7 @@ func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.Chan SweepSignDesc: input.SignDescriptor{ KeyDesc: localChanCfg.HtlcBasePoint, SingleTweak: keyRing.LocalHtlcKeyTweak, - WitnessScript: htlcSenderScript, + WitnessScript: htlcScript, Output: &wire.TxOut{ PkScript: htlcScriptHash, Value: int64(htlc.Amt.ToSatoshis()), @@ -5516,17 +5478,10 @@ func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.Chan // Once we've created the second-level transaction, we'll generate the // SignDesc needed spend the HTLC output using the success transaction. - htlcCreationScript, err := input.ReceiverHTLCScript(htlc.RefundTimeout, - keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey, - keyRing.RevocationKey, htlc.RHash[:], - ) - if err != nil { - return nil, err - } successSignDesc := input.SignDescriptor{ KeyDesc: localChanCfg.HtlcBasePoint, SingleTweak: keyRing.LocalHtlcKeyTweak, - WitnessScript: htlcCreationScript, + WitnessScript: htlcScript, Output: &wire.TxOut{ Value: int64(htlc.Amt.ToSatoshis()), }, @@ -5556,7 +5511,7 @@ func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.Chan if err != nil { return nil, err } - htlcScriptHash, err := input.WitnessScriptHash(htlcSweepScript) + htlcSweepScriptHash, err := input.WitnessScriptHash(htlcSweepScript) if err != nil { return nil, err } @@ -5576,7 +5531,7 @@ func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.Chan SingleTweak: localDelayTweak, WitnessScript: htlcSweepScript, Output: &wire.TxOut{ - PkScript: htlcScriptHash, + PkScript: htlcSweepScriptHash, Value: int64(secondLevelOutputAmt), }, HashType: txscript.SigHashAll, From b56c7e308bb8d3f8a00058b68ba67adacdbbbceb Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:44 +0100 Subject: [PATCH 160/562] input/script_utils_test: extract script execution into assert method This fixes an error case that wouldn't have been caught, since vm.Execute applies more rules than the individual steps (most notably the clean stack rule). Instead we execute the engine as normal, and only step through if we decide that the outcome is unexpected. --- input/script_utils_test.go | 173 ++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 91 deletions(-) diff --git a/input/script_utils_test.go b/input/script_utils_test.go index 1c6c5bc9e5..b716d4dbe7 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -15,6 +15,73 @@ import ( "github.com/lightningnetwork/lnd/keychain" ) +// assertEngineExecution executes the VM returned by the newEngine closure, +// asserting the result matches the validity expectation. In the case where it +// doesn't match the expectation, it executes the script step-by-step and +// prints debug information to stdout. +func assertEngineExecution(t *testing.T, testNum int, valid bool, + newEngine func() (*txscript.Engine, error)) { + t.Helper() + + // Get a new VM to execute. + vm, err := newEngine() + if err != nil { + t.Fatalf("unable to create engine: %v", err) + } + + // Execute the VM, only go on to the step-by-step execution if + // it doesn't validate as expected. + vmErr := vm.Execute() + if valid == (vmErr == nil) { + return + } + + // Now that the execution didn't match what we expected, fetch a new VM + // to step through. + vm, err = newEngine() + if err != nil { + t.Fatalf("unable to create engine: %v", err) + } + + // This buffer will trace execution of the Script, dumping out + // to stdout. + var debugBuf bytes.Buffer + + done := false + for !done { + dis, err := vm.DisasmPC() + if err != nil { + t.Fatalf("stepping (%v)\n", err) + } + debugBuf.WriteString(fmt.Sprintf("stepping %v\n", dis)) + + done, err = vm.Step() + if err != nil && valid { + fmt.Println(debugBuf.String()) + t.Fatalf("spend test case #%v failed, spend "+ + "should be valid: %v", testNum, err) + } else if err == nil && !valid && done { + fmt.Println(debugBuf.String()) + t.Fatalf("spend test case #%v succeed, spend "+ + "should be invalid: %v", testNum, err) + } + + debugBuf.WriteString(fmt.Sprintf("Stack: %v", vm.GetStack())) + debugBuf.WriteString(fmt.Sprintf("AltStack: %v", vm.GetAltStack())) + } + + // If we get to this point the unexpected case was not reached + // during step execution, which happens for some checks, like + // the clean-stack rule. + validity := "invalid" + if valid { + validity = "valid" + } + + fmt.Println(debugBuf.String()) + t.Fatalf("%v spend test case #%v execution ended with: %v", validity, testNum, vmErr) +} + // TestRevocationKeyDerivation tests that given a public key, and a revocation // hash, the homomorphic revocation public and private key derivation work // properly. @@ -308,39 +375,13 @@ func TestHTLCSenderSpendValidation(t *testing.T) { for i, testCase := range testCases { sweepTx.TxIn[0].Witness = testCase.witness() - vm, err := txscript.NewEngine(htlcPkScript, - sweepTx, 0, txscript.StandardVerifyFlags, nil, - nil, int64(paymentAmt)) - if err != nil { - t.Fatalf("unable to create engine: %v", err) + newEngine := func() (*txscript.Engine, error) { + return txscript.NewEngine(htlcPkScript, + sweepTx, 0, txscript.StandardVerifyFlags, nil, + nil, int64(paymentAmt)) } - // This buffer will trace execution of the Script, only dumping - // out to stdout in the case that a test fails. - var debugBuf bytes.Buffer - - done := false - for !done { - dis, err := vm.DisasmPC() - if err != nil { - t.Fatalf("stepping (%v)\n", err) - } - debugBuf.WriteString(fmt.Sprintf("stepping %v\n", dis)) - - done, err = vm.Step() - if err != nil && testCase.valid { - fmt.Println(debugBuf.String()) - t.Fatalf("spend test case #%v failed, spend "+ - "should be valid: %v", i, err) - } else if err == nil && !testCase.valid && done { - fmt.Println(debugBuf.String()) - t.Fatalf("spend test case #%v succeed, spend "+ - "should be invalid: %v", i, err) - } - - debugBuf.WriteString(fmt.Sprintf("Stack: %v", vm.GetStack())) - debugBuf.WriteString(fmt.Sprintf("AltStack: %v", vm.GetAltStack())) - } + assertEngineExecution(t, i, testCase.valid, newEngine) } } @@ -581,37 +622,13 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { for i, testCase := range testCases { sweepTx.TxIn[0].Witness = testCase.witness() - vm, err := txscript.NewEngine(htlcPkScript, - sweepTx, 0, txscript.StandardVerifyFlags, nil, - nil, int64(paymentAmt)) - if err != nil { - t.Fatalf("unable to create engine: %v", err) + newEngine := func() (*txscript.Engine, error) { + return txscript.NewEngine(htlcPkScript, + sweepTx, 0, txscript.StandardVerifyFlags, nil, + nil, int64(paymentAmt)) } - // This buffer will trace execution of the Script, only dumping - // out to stdout in the case that a test fails. - var debugBuf bytes.Buffer - - done := false - for !done { - dis, err := vm.DisasmPC() - if err != nil { - t.Fatalf("stepping (%v)\n", err) - } - debugBuf.WriteString(fmt.Sprintf("stepping %v\n", dis)) - - done, err = vm.Step() - if err != nil && testCase.valid { - fmt.Println(debugBuf.String()) - t.Fatalf("spend test case #%v failed, spend should be valid: %v", i, err) - } else if err == nil && !testCase.valid && done { - fmt.Println(debugBuf.String()) - t.Fatalf("spend test case #%v succeed, spend should be invalid: %v", i, err) - } - - debugBuf.WriteString(fmt.Sprintf("Stack: %v", vm.GetStack())) - debugBuf.WriteString(fmt.Sprintf("AltStack: %v", vm.GetAltStack())) - } + assertEngineExecution(t, i, testCase.valid, newEngine) } } @@ -811,39 +828,13 @@ func TestSecondLevelHtlcSpends(t *testing.T) { for i, testCase := range testCases { sweepTx.TxIn[0].Witness = testCase.witness() - vm, err := txscript.NewEngine(htlcPkScript, - sweepTx, 0, txscript.StandardVerifyFlags, nil, - nil, int64(htlcAmt)) - if err != nil { - t.Fatalf("unable to create engine: %v", err) + newEngine := func() (*txscript.Engine, error) { + return txscript.NewEngine(htlcPkScript, + sweepTx, 0, txscript.StandardVerifyFlags, nil, + nil, int64(htlcAmt)) } - // This buffer will trace execution of the Script, only dumping - // out to stdout in the case that a test fails. - var debugBuf bytes.Buffer - - done := false - for !done { - dis, err := vm.DisasmPC() - if err != nil { - t.Fatalf("stepping (%v)\n", err) - } - debugBuf.WriteString(fmt.Sprintf("stepping %v\n", dis)) - - done, err = vm.Step() - if err != nil && testCase.valid { - fmt.Println(debugBuf.String()) - t.Fatalf("spend test case #%v failed, spend "+ - "should be valid: %v", i, err) - } else if err == nil && !testCase.valid && done { - fmt.Println(debugBuf.String()) - t.Fatalf("spend test case #%v succeed, spend "+ - "should be invalid: %v", i, err) - } - - debugBuf.WriteString(fmt.Sprintf("Stack: %v", vm.GetStack())) - debugBuf.WriteString(fmt.Sprintf("AltStack: %v", vm.GetAltStack())) - } + assertEngineExecution(t, i, testCase.valid, newEngine) } } From b228681a025deeab16fd020095cafdaf966d34be Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:45 +0100 Subject: [PATCH 161/562] input/script_utils_test: refactor TestHTLCSenderSpendValidation To be able to change more than the witness used for each test case, we extract commit and sweep tx generation into own methods that can be called from each test case. We do the same for TestHTLCReceiverSpendValidation --- input/script_utils_test.go | 286 +++++++++++++++++++++++-------------- 1 file changed, 175 insertions(+), 111 deletions(-) diff --git a/input/script_utils_test.go b/input/script_utils_test.go index b716d4dbe7..dcfc9d7d6a 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -212,43 +212,6 @@ func TestHTLCSenderSpendValidation(t *testing.T) { // we'll be using Bob's base point for the revocation key. revocationKey := DeriveRevocationPubkey(bobKeyPub, commitPoint) - // Generate the raw HTLC redemption scripts, and its p2wsh counterpart. - htlcWitnessScript, err := SenderHTLCScript(aliceLocalKey, bobLocalKey, - revocationKey, paymentHash[:]) - if err != nil { - t.Fatalf("unable to create htlc sender script: %v", err) - } - htlcPkScript, err := WitnessScriptHash(htlcWitnessScript) - if err != nil { - t.Fatalf("unable to create p2wsh htlc script: %v", err) - } - - // This will be Alice's commitment transaction. In this scenario Alice - // is sending an HTLC to a node she has a path to (could be Bob, could - // be multiple hops down, it doesn't really matter). - htlcOutput := &wire.TxOut{ - Value: int64(paymentAmt), - PkScript: htlcPkScript, - } - senderCommitTx := wire.NewMsgTx(2) - senderCommitTx.AddTxIn(fakeFundingTxIn) - senderCommitTx.AddTxOut(htlcOutput) - - prevOut := &wire.OutPoint{ - Hash: senderCommitTx.TxHash(), - Index: 0, - } - - sweepTx := wire.NewMsgTx(2) - sweepTx.AddTxIn(wire.NewTxIn(prevOut, nil, nil)) - sweepTx.AddTxOut( - &wire.TxOut{ - PkScript: []byte("doesn't matter"), - Value: 1 * 10e8, - }, - ) - sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx) - bobCommitTweak := SingleTweakBytes(commitPoint, bobKeyPub) aliceCommitTweak := SingleTweakBytes(commitPoint, aliceKeyPub) @@ -258,23 +221,81 @@ func TestHTLCSenderSpendValidation(t *testing.T) { bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}} aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}} - // We'll also generate a signature on the sweep transaction above - // that will act as Bob's signature to Alice for the second level HTLC - // transaction. - bobSignDesc := SignDescriptor{ - KeyDesc: keychain.KeyDescriptor{ - PubKey: bobKeyPub, - }, - SingleTweak: bobCommitTweak, - WitnessScript: htlcWitnessScript, - Output: htlcOutput, - HashType: txscript.SigHashAll, - SigHashes: sweepTxSigHashes, - InputIndex: 0, - } - bobRecvrSig, err := bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) - if err != nil { - t.Fatalf("unable to generate alice signature: %v", err) + var ( + htlcWitnessScript, htlcPkScript []byte + htlcOutput *wire.TxOut + sweepTxSigHashes *txscript.TxSigHashes + senderCommitTx, sweepTx *wire.MsgTx + bobRecvrSig []byte + ) + + // genCommitTx generates a commitment tx. + genCommitTx := func() { + // Generate the raw HTLC redemption scripts, and its p2wsh + // counterpart. + htlcWitnessScript, err = SenderHTLCScript( + aliceLocalKey, bobLocalKey, revocationKey, + paymentHash[:], + ) + if err != nil { + t.Fatalf("unable to create htlc sender script: %v", err) + } + htlcPkScript, err = WitnessScriptHash(htlcWitnessScript) + if err != nil { + t.Fatalf("unable to create p2wsh htlc script: %v", err) + } + + // This will be Alice's commitment transaction. In this + // scenario Alice is sending an HTLC to a node she has a path + // to (could be Bob, could be multiple hops down, it doesn't + // really matter). + htlcOutput = &wire.TxOut{ + Value: int64(paymentAmt), + PkScript: htlcPkScript, + } + senderCommitTx = wire.NewMsgTx(2) + senderCommitTx.AddTxIn(fakeFundingTxIn) + senderCommitTx.AddTxOut(htlcOutput) + } + + // genSweepTx generates a sweep of the senderCommitTx. + genSweepTx := func() { + prevOut := &wire.OutPoint{ + Hash: senderCommitTx.TxHash(), + Index: 0, + } + + sweepTx = wire.NewMsgTx(2) + + sweepTx.AddTxIn(wire.NewTxIn(prevOut, nil, nil)) + + sweepTx.AddTxOut( + &wire.TxOut{ + PkScript: []byte("doesn't matter"), + Value: 1 * 10e8, + }, + ) + + sweepTxSigHashes = txscript.NewTxSigHashes(sweepTx) + + // We'll also generate a signature on the sweep transaction above + // that will act as Bob's signature to Alice for the second level HTLC + // transaction. + bobSignDesc := SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: bobKeyPub, + }, + SingleTweak: bobCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + bobRecvrSig, err = bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) + if err != nil { + t.Fatalf("unable to generate alice signature: %v", err) + } } testCases := []struct { @@ -285,6 +306,9 @@ func TestHTLCSenderSpendValidation(t *testing.T) { // revoke w/ sig // TODO(roasbeef): test invalid revoke makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: bobKeyPub, @@ -305,6 +329,9 @@ func TestHTLCSenderSpendValidation(t *testing.T) { { // HTLC with invalid preimage size makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: bobKeyPub, @@ -328,6 +355,9 @@ func TestHTLCSenderSpendValidation(t *testing.T) { // HTLC with valid preimage size + sig // TODO(roasbeef): invalid preimage makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: bobKeyPub, @@ -350,6 +380,9 @@ func TestHTLCSenderSpendValidation(t *testing.T) { // output with the second level HTLC timeout // transaction. makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: aliceKeyPub, @@ -441,46 +474,6 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { // be using Alice's base point for the revocation key. revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint) - // Generate the raw HTLC redemption scripts, and its p2wsh counterpart. - htlcWitnessScript, err := ReceiverHTLCScript(cltvTimeout, aliceLocalKey, - bobLocalKey, revocationKey, paymentHash[:]) - if err != nil { - t.Fatalf("unable to create htlc sender script: %v", err) - } - htlcPkScript, err := WitnessScriptHash(htlcWitnessScript) - if err != nil { - t.Fatalf("unable to create p2wsh htlc script: %v", err) - } - - // This will be Bob's commitment transaction. In this scenario Alice is - // sending an HTLC to a node she has a path to (could be Bob, could be - // multiple hops down, it doesn't really matter). - htlcOutput := &wire.TxOut{ - Value: int64(paymentAmt), - PkScript: htlcWitnessScript, - } - - receiverCommitTx := wire.NewMsgTx(2) - receiverCommitTx.AddTxIn(fakeFundingTxIn) - receiverCommitTx.AddTxOut(htlcOutput) - - prevOut := &wire.OutPoint{ - Hash: receiverCommitTx.TxHash(), - Index: 0, - } - - sweepTx := wire.NewMsgTx(2) - sweepTx.AddTxIn(&wire.TxIn{ - PreviousOutPoint: *prevOut, - }) - sweepTx.AddTxOut( - &wire.TxOut{ - PkScript: []byte("doesn't matter"), - Value: 1 * 10e8, - }, - ) - sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx) - bobCommitTweak := SingleTweakBytes(commitPoint, bobKeyPub) aliceCommitTweak := SingleTweakBytes(commitPoint, aliceKeyPub) @@ -490,23 +483,79 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}} aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}} - // We'll also generate a signature on the sweep transaction above - // that will act as Alice's signature to Bob for the second level HTLC - // transaction. - aliceSignDesc := SignDescriptor{ - KeyDesc: keychain.KeyDescriptor{ - PubKey: aliceKeyPub, - }, - SingleTweak: aliceCommitTweak, - WitnessScript: htlcWitnessScript, - Output: htlcOutput, - HashType: txscript.SigHashAll, - SigHashes: sweepTxSigHashes, - InputIndex: 0, - } - aliceSenderSig, err := aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) - if err != nil { - t.Fatalf("unable to generate alice signature: %v", err) + var ( + htlcWitnessScript, htlcPkScript []byte + htlcOutput *wire.TxOut + receiverCommitTx, sweepTx *wire.MsgTx + sweepTxSigHashes *txscript.TxSigHashes + aliceSenderSig []byte + ) + + genCommitTx := func() { + // Generate the raw HTLC redemption scripts, and its p2wsh + // counterpart. + htlcWitnessScript, err = ReceiverHTLCScript( + cltvTimeout, aliceLocalKey, bobLocalKey, revocationKey, + paymentHash[:], + ) + if err != nil { + t.Fatalf("unable to create htlc sender script: %v", err) + } + htlcPkScript, err = WitnessScriptHash(htlcWitnessScript) + if err != nil { + t.Fatalf("unable to create p2wsh htlc script: %v", err) + } + + // This will be Bob's commitment transaction. In this scenario Alice is + // sending an HTLC to a node she has a path to (could be Bob, could be + // multiple hops down, it doesn't really matter). + htlcOutput = &wire.TxOut{ + Value: int64(paymentAmt), + PkScript: htlcWitnessScript, + } + + receiverCommitTx = wire.NewMsgTx(2) + receiverCommitTx.AddTxIn(fakeFundingTxIn) + receiverCommitTx.AddTxOut(htlcOutput) + } + + genSweepTx := func() { + prevOut := &wire.OutPoint{ + Hash: receiverCommitTx.TxHash(), + Index: 0, + } + + sweepTx = wire.NewMsgTx(2) + sweepTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: *prevOut, + }) + + sweepTx.AddTxOut( + &wire.TxOut{ + PkScript: []byte("doesn't matter"), + Value: 1 * 10e8, + }, + ) + sweepTxSigHashes = txscript.NewTxSigHashes(sweepTx) + + // We'll also generate a signature on the sweep transaction above + // that will act as Alice's signature to Bob for the second level HTLC + // transaction. + aliceSignDesc := SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: aliceKeyPub, + }, + SingleTweak: aliceCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + aliceSenderSig, err = aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) + if err != nil { + t.Fatalf("unable to generate alice signature: %v", err) + } } // TODO(roasbeef): modify valid to check precise script errors? @@ -517,6 +566,9 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // HTLC redemption w/ invalid preimage size makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: bobKeyPub, @@ -539,6 +591,9 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // HTLC redemption w/ valid preimage size makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: bobKeyPub, @@ -560,6 +615,9 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // revoke w/ sig makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: aliceKeyPub, @@ -580,6 +638,9 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // refund w/ invalid lock time makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: aliceKeyPub, @@ -600,6 +661,9 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // refund w/ valid lock time makeWitnessTestCase(t, func() (wire.TxWitness, error) { + genCommitTx() + genSweepTx() + signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ PubKey: aliceKeyPub, From 6ecb379088b5c5c595cf91bf210ae69ab6cd9a93 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:45 +0100 Subject: [PATCH 162/562] lnwallet: thread chanType down into genHtlcScript, gen[..]SigJobs, create[..]Tx NO FUNCTIONAL CHANGES This is a commit just supplying the channel types to various methods. --- lnwallet/channel.go | 80 +++++++++++++++++++++-------------- lnwallet/commitment.go | 20 ++++++--- lnwallet/transactions.go | 8 ++-- lnwallet/transactions_test.go | 5 ++- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index c60c591e70..79722da89c 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -773,6 +773,7 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, ourWitnessScript, theirWitnessScript []byte pd PaymentDescriptor err error + chanType = lc.channelState.ChanType ) // If the either outputs is dust from the local or remote node's @@ -784,8 +785,9 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, htlc.Amt.ToSatoshis(), lc.channelState.LocalChanCfg.DustLimit) if !isDustLocal && localCommitKeys != nil { ourP2WSH, ourWitnessScript, err = genHtlcScript( - htlc.Incoming, true, htlc.RefundTimeout, htlc.RHash, - localCommitKeys) + chanType, htlc.Incoming, true, htlc.RefundTimeout, + htlc.RHash, localCommitKeys, + ) if err != nil { return pd, err } @@ -794,8 +796,9 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, htlc.Amt.ToSatoshis(), lc.channelState.RemoteChanCfg.DustLimit) if !isDustRemote && remoteCommitKeys != nil { theirP2WSH, theirWitnessScript, err = genHtlcScript( - htlc.Incoming, false, htlc.RefundTimeout, htlc.RHash, - remoteCommitKeys) + chanType, htlc.Incoming, false, htlc.RefundTimeout, + htlc.RHash, remoteCommitKeys, + ) if err != nil { return pd, err } @@ -1410,7 +1413,8 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate, wireMsg.Amount.ToSatoshis(), remoteDustLimit) if !isDustRemote { theirP2WSH, theirWitnessScript, err := genHtlcScript( - false, false, wireMsg.Expiry, wireMsg.PaymentHash, + lc.channelState.ChanType, false, false, + wireMsg.Expiry, wireMsg.PaymentHash, remoteCommitKeys, ) if err != nil { @@ -2184,8 +2188,8 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, // an outgoing HTLC that we sent, then from the PoV of the // remote commitment state, they're the receiver of this HTLC. htlcPkScript, htlcWitnessScript, err := genHtlcScript( - htlc.Incoming, false, htlc.RefundTimeout, - htlc.RHash, keyRing, + chanState.ChanType, htlc.Incoming, false, + htlc.RefundTimeout, htlc.RHash, keyRing, ) if err != nil { return nil, err @@ -2714,6 +2718,7 @@ func processFeeUpdate(feeUpdate *PaymentDescriptor, nextHeight uint64, // signature can be submitted to the sigPool to generate all the signatures // asynchronously and in parallel. func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, + chanType channeldb.ChannelType, localChanCfg, remoteChanCfg *channeldb.ChannelConfig, remoteCommitView *commitment) ([]SignJob, chan struct{}, error) { @@ -2761,7 +2766,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, Index: uint32(htlc.remoteOutputIndex), } sigJob.Tx, err = createHtlcTimeoutTx( - op, outputAmt, htlc.Timeout, + chanType, op, outputAmt, htlc.Timeout, uint32(remoteChanCfg.CsvDelay), keyRing.RevocationKey, keyRing.ToLocalKey, ) @@ -2813,7 +2818,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, Index: uint32(htlc.remoteOutputIndex), } sigJob.Tx, err = createHtlcSuccessTx( - op, outputAmt, uint32(remoteChanCfg.CsvDelay), + chanType, op, outputAmt, uint32(remoteChanCfg.CsvDelay), keyRing.RevocationKey, keyRing.ToLocalKey, ) if err != nil { @@ -3318,7 +3323,8 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig, []ch // need to generate signatures of each of them for the remote party's // commitment state. We do so in two phases: first we generate and // submit the set of signature jobs to the worker pool. - sigBatch, cancelChan, err := genRemoteHtlcSigJobs(keyRing, + sigBatch, cancelChan, err := genRemoteHtlcSigJobs( + keyRing, lc.channelState.ChanType, &lc.channelState.LocalChanCfg, &lc.channelState.RemoteChanCfg, newCommitView, ) @@ -3776,6 +3782,7 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, // directly into the pool of workers. func genHtlcSigValidationJobs(localCommitmentView *commitment, keyRing *CommitmentKeyRing, htlcSigs []lnwire.Sig, + chanType channeldb.ChannelType, localChanCfg, remoteChanCfg *channeldb.ChannelConfig) ([]VerifyJob, error) { txHash := localCommitmentView.txn.TxHash() @@ -3822,9 +3829,11 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment, htlcFee := htlcSuccessFee(feePerKw) outputAmt := htlc.Amount.ToSatoshis() - htlcFee - successTx, err := createHtlcSuccessTx(op, - outputAmt, uint32(localChanCfg.CsvDelay), - keyRing.RevocationKey, keyRing.ToLocalKey) + successTx, err := createHtlcSuccessTx( + chanType, op, outputAmt, + uint32(localChanCfg.CsvDelay), + keyRing.RevocationKey, keyRing.ToLocalKey, + ) if err != nil { return nil, err } @@ -3874,8 +3883,8 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment, htlcFee := htlcTimeoutFee(feePerKw) outputAmt := htlc.Amount.ToSatoshis() - htlcFee - timeoutTx, err := createHtlcTimeoutTx(op, - outputAmt, htlc.Timeout, + timeoutTx, err := createHtlcTimeoutTx( + chanType, op, outputAmt, htlc.Timeout, uint32(localChanCfg.CsvDelay), keyRing.RevocationKey, keyRing.ToLocalKey, ) @@ -4092,7 +4101,8 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig, // generated, we'll submit these jobs to the worker pool. verifyJobs, err := genHtlcSigValidationJobs( localCommitmentView, keyRing, htlcSigs, - &lc.channelState.LocalChanCfg, &lc.channelState.RemoteChanCfg, + lc.channelState.ChanType, &lc.channelState.LocalChanCfg, + &lc.channelState.RemoteChanCfg, ) if err != nil { return err @@ -5100,6 +5110,7 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Si chainfee.SatPerKWeight(remoteCommit.FeePerKw), false, signer, remoteCommit.Htlcs, keyRing, &chanState.LocalChanCfg, &chanState.RemoteChanCfg, *commitSpend.SpenderTxHash, + chanState.ChanType, ) if err != nil { return nil, fmt.Errorf("unable to create htlc "+ @@ -5295,7 +5306,7 @@ func newOutgoingHtlcResolution(signer input.Signer, localChanCfg *channeldb.ChannelConfig, commitHash chainhash.Hash, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing, feePerKw chainfee.SatPerKWeight, csvDelay uint32, - localCommit bool) (*OutgoingHtlcResolution, error) { + localCommit bool, chanType channeldb.ChannelType) (*OutgoingHtlcResolution, error) { op := wire.OutPoint{ Hash: commitHash, @@ -5305,7 +5316,8 @@ func newOutgoingHtlcResolution(signer input.Signer, // First, we'll re-generate the script used to send the HTLC to // the remote party within their commitment transaction. htlcScriptHash, htlcScript, err := genHtlcScript( - false, localCommit, htlc.RefundTimeout, htlc.RHash, keyRing, + chanType, false, localCommit, htlc.RefundTimeout, htlc.RHash, + keyRing, ) if err != nil { return nil, err @@ -5345,8 +5357,8 @@ func newOutgoingHtlcResolution(signer input.Signer, // With the fee calculated, re-construct the second level timeout // transaction. timeoutTx, err := createHtlcTimeoutTx( - op, secondLevelOutputAmt, htlc.RefundTimeout, csvDelay, - keyRing.RevocationKey, keyRing.ToLocalKey, + chanType, op, secondLevelOutputAmt, htlc.RefundTimeout, + csvDelay, keyRing.RevocationKey, keyRing.ToLocalKey, ) if err != nil { return nil, err @@ -5422,10 +5434,11 @@ func newOutgoingHtlcResolution(signer input.Signer, // they can just sweep the output immediately with knowledge of the pre-image. // // TODO(roasbeef) consolidate code with above func -func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.ChannelConfig, - commitHash chainhash.Hash, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing, - feePerKw chainfee.SatPerKWeight, csvDelay uint32, - localCommit bool) (*IncomingHtlcResolution, error) { +func newIncomingHtlcResolution(signer input.Signer, + localChanCfg *channeldb.ChannelConfig, commitHash chainhash.Hash, + htlc *channeldb.HTLC, keyRing *CommitmentKeyRing, + feePerKw chainfee.SatPerKWeight, csvDelay uint32, localCommit bool, + chanType channeldb.ChannelType) (*IncomingHtlcResolution, error) { op := wire.OutPoint{ Hash: commitHash, @@ -5435,7 +5448,8 @@ func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.Chan // First, we'll re-generate the script the remote party used to // send the HTLC to us in their commitment transaction. htlcScriptHash, htlcScript, err := genHtlcScript( - true, localCommit, htlc.RefundTimeout, htlc.RHash, keyRing, + chanType, true, localCommit, htlc.RefundTimeout, htlc.RHash, + keyRing, ) if err != nil { return nil, err @@ -5469,7 +5483,7 @@ func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.Chan htlcFee := htlcSuccessFee(feePerKw) secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee successTx, err := createHtlcSuccessTx( - op, secondLevelOutputAmt, csvDelay, + chanType, op, secondLevelOutputAmt, csvDelay, keyRing.RevocationKey, keyRing.ToLocalKey, ) if err != nil { @@ -5569,7 +5583,8 @@ func (r *OutgoingHtlcResolution) HtlcPoint() wire.OutPoint { func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool, signer input.Signer, htlcs []channeldb.HTLC, keyRing *CommitmentKeyRing, localChanCfg, remoteChanCfg *channeldb.ChannelConfig, - commitHash chainhash.Hash) (*HtlcResolutions, error) { + commitHash chainhash.Hash, chanType channeldb.ChannelType) ( + *HtlcResolutions, error) { // TODO(roasbeef): don't need to swap csv delay? dustLimit := remoteChanCfg.DustLimit @@ -5582,6 +5597,8 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool, incomingResolutions := make([]IncomingHtlcResolution, 0, len(htlcs)) outgoingResolutions := make([]OutgoingHtlcResolution, 0, len(htlcs)) for _, htlc := range htlcs { + htlc := htlc + // We'll skip any HTLC's which were dust on the commitment // transaction, as these don't have a corresponding output // within the commitment transaction. @@ -5596,8 +5613,9 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool, // Otherwise, we'll create an incoming HTLC resolution // as we can satisfy the contract. ihr, err := newIncomingHtlcResolution( - signer, localChanCfg, commitHash, &htlc, keyRing, - feePerKw, uint32(csvDelay), ourCommit, + signer, localChanCfg, commitHash, &htlc, + keyRing, feePerKw, uint32(csvDelay), ourCommit, + chanType, ) if err != nil { return nil, err @@ -5609,7 +5627,7 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool, ohr, err := newOutgoingHtlcResolution( signer, localChanCfg, commitHash, &htlc, keyRing, - feePerKw, uint32(csvDelay), ourCommit, + feePerKw, uint32(csvDelay), ourCommit, chanType, ) if err != nil { return nil, err @@ -5788,7 +5806,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer input.Si htlcResolutions, err := extractHtlcResolutions( chainfee.SatPerKWeight(localCommit.FeePerKw), true, signer, localCommit.Htlcs, keyRing, &chanState.LocalChanCfg, - &chanState.RemoteChanCfg, txHash, + &chanState.RemoteChanCfg, txHash, chanState.ChanType, ) if err != nil { return nil, err diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 459dd83bda..5d56fcd954 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -361,7 +361,10 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, continue } - err := addHTLC(commitTx, isOurs, false, htlc, keyRing) + err := addHTLC( + commitTx, isOurs, false, htlc, keyRing, + cb.chanState.ChanType, + ) if err != nil { return nil, err } @@ -373,7 +376,10 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, continue } - err := addHTLC(commitTx, isOurs, true, htlc, keyRing) + err := addHTLC( + commitTx, isOurs, true, htlc, keyRing, + cb.chanState.ChanType, + ) if err != nil { return nil, err } @@ -485,7 +491,8 @@ func CreateCommitTx(chanType channeldb.ChannelType, // genHtlcScript generates the proper P2WSH public key scripts for the HTLC // output modified by two-bits denoting if this is an incoming HTLC, and if the // HTLC is being applied to their commitment transaction or ours. -func genHtlcScript(isIncoming, ourCommit bool, timeout uint32, rHash [32]byte, +func genHtlcScript(chanType channeldb.ChannelType, isIncoming, ourCommit bool, + timeout uint32, rHash [32]byte, keyRing *CommitmentKeyRing) ([]byte, []byte, error) { var ( @@ -549,13 +556,14 @@ func genHtlcScript(isIncoming, ourCommit bool, timeout uint32, rHash [32]byte, // the descriptor itself. func addHTLC(commitTx *wire.MsgTx, ourCommit bool, isIncoming bool, paymentDesc *PaymentDescriptor, - keyRing *CommitmentKeyRing) error { + keyRing *CommitmentKeyRing, chanType channeldb.ChannelType) error { timeout := paymentDesc.Timeout rHash := paymentDesc.RHash - p2wsh, witnessScript, err := genHtlcScript(isIncoming, ourCommit, - timeout, rHash, keyRing) + p2wsh, witnessScript, err := genHtlcScript( + chanType, isIncoming, ourCommit, timeout, rHash, keyRing, + ) if err != nil { return err } diff --git a/lnwallet/transactions.go b/lnwallet/transactions.go index 7803f752bf..c8f14a9670 100644 --- a/lnwallet/transactions.go +++ b/lnwallet/transactions.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" ) @@ -44,8 +45,8 @@ var ( // In order to spend the HTLC output, the witness for the passed transaction // should be: // * <0> -func createHtlcSuccessTx(htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, - csvDelay uint32, +func createHtlcSuccessTx(chanType channeldb.ChannelType, + htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, csvDelay uint32, revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) { // Create a version two transaction (as the success version of this @@ -97,7 +98,8 @@ func createHtlcSuccessTx(htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, // NOTE: The passed amount for the HTLC should take into account the required // fee rate at the time the HTLC was created. The fee should be able to // entirely pay for this (tiny: 1-in 1-out) transaction. -func createHtlcTimeoutTx(htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, +func createHtlcTimeoutTx(chanType channeldb.ChannelType, + htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, cltvExpiry, csvDelay uint32, revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) { diff --git a/lnwallet/transactions_test.go b/lnwallet/transactions_test.go index 4f5cc65a4b..db5a8dcefd 100644 --- a/lnwallet/transactions_test.go +++ b/lnwallet/transactions_test.go @@ -851,9 +851,10 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) { // Generate second-level HTLC transactions for HTLCs in // commitment tx. htlcResolutions, err := extractHtlcResolutions( - chainfee.SatPerKWeight(test.commitment.FeePerKw), true, signer, - htlcs, keys, &channel.channelState.LocalChanCfg, + chainfee.SatPerKWeight(test.commitment.FeePerKw), true, + signer, htlcs, keys, &channel.channelState.LocalChanCfg, &channel.channelState.RemoteChanCfg, commitTx.TxHash(), + channel.channelState.ChanType, ) if err != nil { t.Errorf("Case %d: Failed to extract HTLC resolutions: %v", i, err) From b25f2fa94b2e49ee901c771d87d73d4ac8d358fa Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:45 +0100 Subject: [PATCH 163/562] channeldb: define AnchorOutputsBit channel type --- channeldb/channel.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/channeldb/channel.go b/channeldb/channel.go index 0914f24244..1ce43ad475 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -176,6 +176,12 @@ const ( // disk. This bit may be on if the funding transaction was crafted by a // wallet external to the primary daemon. NoFundingTxBit ChannelType = 1 << 2 + + // AnchorOutputsBit indicates that the channel makes use of anchor + // outputs to bump the commitment transaction's effective feerate. This + // channel type also uses a delayed to_remote output script. If bit is + // set, we'll find the size of the anchor outputs in the database. + AnchorOutputsBit ChannelType = 1 << 3 ) // IsSingleFunder returns true if the channel type if one of the known single @@ -201,6 +207,12 @@ func (c ChannelType) HasFundingTx() bool { return c&NoFundingTxBit == 0 } +// HasAnchors returns true if this channel type has anchor ouputs on its +// commitment. +func (c ChannelType) HasAnchors() bool { + return c&AnchorOutputsBit == AnchorOutputsBit +} + // ChannelConstraints represents a set of constraints meant to allow a node to // limit their exposure, enact flow control and ensure that all HTLCs are // economically relevant. This struct will be mirrored for both sides of the From 8c0deb81c27d5492e21f33735d4c2ad4bd5c48ce Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:45 +0100 Subject: [PATCH 164/562] input+lnwallet: Add scripts for CSV delayed HTLC outputs We also increase the witness size for these types to account for the 3 extra bytes. The size won't be correct in all cases, but it is just an upper bound in any case. --- input/script_utils.go | 29 +++++++++++++++++++++++++++-- input/script_utils_test.go | 4 ++-- input/size.go | 22 ++++++++++++++-------- lnwallet/commitment.go | 8 ++++---- sweep/txgenerator_test.go | 2 +- 5 files changed, 48 insertions(+), 17 deletions(-) diff --git a/input/script_utils.go b/input/script_utils.go index 8b47b05681..7342e2e666 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -150,6 +150,9 @@ func Ripemd160H(d []byte) []byte { // * The receiver of the HTLC sweeping all the funds in the case that a // revoked commitment transaction bearing this HTLC was broadcast. // +// If confirmedSpend=true, a 1 OP_CSV check will be added to the non-revocation +// cases, to allow sweeping only after confirmation. +// // Possible Input Scripts: // SENDR: <0> <0> (spend using HTLC timeout transaction) // RECVR: @@ -168,9 +171,11 @@ func Ripemd160H(d []byte) []byte { // OP_HASH160 OP_EQUALVERIFY // OP_CHECKSIG // OP_ENDIF +// [1 OP_CHECKSEQUENCEVERIFY OP_DROP] <- if allowing confirmed spend only. // OP_ENDIF func SenderHTLCScript(senderHtlcKey, receiverHtlcKey, - revocationKey *btcec.PublicKey, paymentHash []byte) ([]byte, error) { + revocationKey *btcec.PublicKey, paymentHash []byte, + confirmedSpend bool) ([]byte, error) { builder := txscript.NewScriptBuilder() @@ -243,6 +248,14 @@ func SenderHTLCScript(senderHtlcKey, receiverHtlcKey, // Close out the OP_IF statement above. builder.AddOp(txscript.OP_ENDIF) + // Add 1 block CSV delay if a confirmation is required for the + // non-revocation clauses. + if confirmedSpend { + builder.AddOp(txscript.OP_1) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) + builder.AddOp(txscript.OP_DROP) + } + // Close out the OP_IF statement at the top of the script. builder.AddOp(txscript.OP_ENDIF) @@ -362,6 +375,9 @@ func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer, // * The sender of the HTLC sweeps the HTLC on-chain after the timeout period // of the HTLC has passed. // +// If confirmedSpend=true, a 1 OP_CSV check will be added to the non-revocation +// cases, to allow sweeping only after confirmation. +// // Possible Input Scripts: // RECVR: <0> (spend using HTLC success transaction) // REVOK: @@ -381,10 +397,11 @@ func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer, // OP_DROP OP_CHECKLOCKTIMEVERIFY OP_DROP // OP_CHECKSIG // OP_ENDIF +// [1 OP_CHECKSEQUENCEVERIFY OP_DROP] <- if allowing confirmed spend only. // OP_ENDIF func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey, receiverHtlcKey, revocationKey *btcec.PublicKey, - paymentHash []byte) ([]byte, error) { + paymentHash []byte, confirmedSpend bool) ([]byte, error) { builder := txscript.NewScriptBuilder() @@ -467,6 +484,14 @@ func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey, // Close out the inner if statement. builder.AddOp(txscript.OP_ENDIF) + // Add 1 block CSV delay for non-revocation clauses if confirmation is + // required. + if confirmedSpend { + builder.AddOp(txscript.OP_1) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) + builder.AddOp(txscript.OP_DROP) + } + // Close out the outer if statement. builder.AddOp(txscript.OP_ENDIF) diff --git a/input/script_utils_test.go b/input/script_utils_test.go index dcfc9d7d6a..955cfecd70 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -235,7 +235,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) { // counterpart. htlcWitnessScript, err = SenderHTLCScript( aliceLocalKey, bobLocalKey, revocationKey, - paymentHash[:], + paymentHash[:], false, ) if err != nil { t.Fatalf("unable to create htlc sender script: %v", err) @@ -496,7 +496,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { // counterpart. htlcWitnessScript, err = ReceiverHTLCScript( cltvTimeout, aliceLocalKey, bobLocalKey, revocationKey, - paymentHash[:], + paymentHash[:], false, ) if err != nil { t.Fatalf("unable to create htlc sender script: %v", err) diff --git a/input/size.go b/input/size.go index b0d28aa278..2bea38ce3c 100644 --- a/input/size.go +++ b/input/size.go @@ -213,7 +213,7 @@ const ( // - witness_script (to_local_script) ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize - // AcceptedHtlcScriptSize 139 bytes + // AcceptedHtlcScriptSize 142 bytes // - OP_DUP: 1 byte // - OP_HASH160: 1 byte // - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length) @@ -247,11 +247,14 @@ const ( // - OP_DROP: 1 byte // - OP_CHECKSIG: 1 byte // - OP_ENDIF: 1 byte + // - OP_1: 1 byte // These 3 extra bytes are used for both confirmed and regular + // - OP_CSV: 1 byte // HTLC script types. The size won't be correct in all cases, + // - OP_DROP: 1 byte // but it is just an upper bound used for fee estimation in any case. // - OP_ENDIF: 1 byte AcceptedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 7*1 + 20 + 4*1 + - 33 + 5*1 + 4 + 5*1 + 33 + 5*1 + 4 + 8*1 - // AcceptedHtlcTimeoutWitnessSize 216 + // AcceptedHtlcTimeoutWitnessSize 219 // - number_of_witness_elements: 1 byte // - sender_sig_length: 1 byte // - sender_sig: 73 bytes @@ -260,7 +263,7 @@ const ( // - witness_script: (accepted_htlc_script) AcceptedHtlcTimeoutWitnessSize = 1 + 1 + 73 + 1 + 1 + AcceptedHtlcScriptSize - // AcceptedHtlcPenaltyWitnessSize 249 bytes + // AcceptedHtlcPenaltyWitnessSize 252 bytes // - number_of_witness_elements: 1 byte // - revocation_sig_length: 1 byte // - revocation_sig: 73 bytes @@ -270,7 +273,7 @@ const ( // - witness_script (accepted_htlc_script) AcceptedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + AcceptedHtlcScriptSize - // OfferedHtlcScriptSize 133 bytes + // OfferedHtlcScriptSize 136 bytes // - OP_DUP: 1 byte // - OP_HASH160: 1 byte // - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length) @@ -301,10 +304,13 @@ const ( // - OP_EQUALVERIFY: 1 byte // - OP_CHECKSIG: 1 byte // - OP_ENDIF: 1 byte + // - OP_1: 1 byte + // - OP_CSV: 1 byte + // - OP_DROP: 1 byte // - OP_ENDIF: 1 byte - OfferedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 10*1 + 33 + 5*1 + 20 + 4*1 + OfferedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 10*1 + 33 + 5*1 + 20 + 7*1 - // OfferedHtlcSuccessWitnessSize 317 bytes + // OfferedHtlcSuccessWitnessSize 320 bytes // - number_of_witness_elements: 1 byte // - nil_length: 1 byte // - receiver_sig_length: 1 byte @@ -317,7 +323,7 @@ const ( // - witness_script (offered_htlc_script) OfferedHtlcSuccessWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 32 + 1 + OfferedHtlcScriptSize - // OfferedHtlcPenaltyWitnessSize 243 bytes + // OfferedHtlcPenaltyWitnessSize 246 bytes // - number_of_witness_elements: 1 byte // - revocation_sig_length: 1 byte // - revocation_sig: 73 bytes diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 5d56fcd954..2f8b93ac1c 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -510,28 +510,28 @@ func genHtlcScript(chanType channeldb.ChannelType, isIncoming, ourCommit bool, case isIncoming && ourCommit: witnessScript, err = input.ReceiverHTLCScript(timeout, keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey, - keyRing.RevocationKey, rHash[:]) + keyRing.RevocationKey, rHash[:], false) // We're being paid via an HTLC by the remote party, and the HTLC is // being added to their commitment transaction, so we use the sender's // version of the HTLC script. case isIncoming && !ourCommit: witnessScript, err = input.SenderHTLCScript(keyRing.RemoteHtlcKey, - keyRing.LocalHtlcKey, keyRing.RevocationKey, rHash[:]) + keyRing.LocalHtlcKey, keyRing.RevocationKey, rHash[:], false) // We're sending an HTLC which is being added to our commitment // transaction. Therefore, we need to use the sender's version of the // HTLC script. case !isIncoming && ourCommit: witnessScript, err = input.SenderHTLCScript(keyRing.LocalHtlcKey, - keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:]) + keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:], false) // Finally, we're paying the remote party via an HTLC, which is being // added to their commitment transaction. Therefore, we use the // receiver's version of the HTLC script. case !isIncoming && !ourCommit: witnessScript, err = input.ReceiverHTLCScript(timeout, keyRing.LocalHtlcKey, - keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:]) + keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:], false) } if err != nil { return nil, nil, err diff --git a/sweep/txgenerator_test.go b/sweep/txgenerator_test.go index 84484283df..726347ec84 100644 --- a/sweep/txgenerator_test.go +++ b/sweep/txgenerator_test.go @@ -14,7 +14,7 @@ var ( input.HtlcOfferedRemoteTimeout, input.WitnessKeyHash, } - expectedWeight = int64(1459) + expectedWeight = int64(1462) expectedSummary = "1 CommitmentTimeLock, 1 " + "HtlcAcceptedSuccessSecondLevel, 1 HtlcOfferedRemoteTimeout, " + "1 WitnessKeyHash" From dc271a80cb046590c63912d69304ee2218eefe98 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:45 +0100 Subject: [PATCH 165/562] input/script_utils test: add test cases for delayed HTLC sender script --- input/script_utils_test.go | 148 +++++++++++++++++++++++++++++++++---- 1 file changed, 135 insertions(+), 13 deletions(-) diff --git a/input/script_utils_test.go b/input/script_utils_test.go index 955cfecd70..ad7609bb21 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -229,13 +229,14 @@ func TestHTLCSenderSpendValidation(t *testing.T) { bobRecvrSig []byte ) - // genCommitTx generates a commitment tx. - genCommitTx := func() { + // genCommitTx generates a commitment tx where the htlc output requires + // confirmation to be spent according to 'confirmed'. + genCommitTx := func(confirmed bool) { // Generate the raw HTLC redemption scripts, and its p2wsh // counterpart. htlcWitnessScript, err = SenderHTLCScript( aliceLocalKey, bobLocalKey, revocationKey, - paymentHash[:], false, + paymentHash[:], confirmed, ) if err != nil { t.Fatalf("unable to create htlc sender script: %v", err) @@ -258,8 +259,9 @@ func TestHTLCSenderSpendValidation(t *testing.T) { senderCommitTx.AddTxOut(htlcOutput) } - // genSweepTx generates a sweep of the senderCommitTx. - genSweepTx := func() { + // genSweepTx generates a sweep of the senderCommitTx, and sets the + // sequence if confirmed is true. + genSweepTx := func(confirmed bool) { prevOut := &wire.OutPoint{ Hash: senderCommitTx.TxHash(), Index: 0, @@ -268,6 +270,9 @@ func TestHTLCSenderSpendValidation(t *testing.T) { sweepTx = wire.NewMsgTx(2) sweepTx.AddTxIn(wire.NewTxIn(prevOut, nil, nil)) + if confirmed { + sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1) + } sweepTx.AddTxOut( &wire.TxOut{ @@ -306,8 +311,8 @@ func TestHTLCSenderSpendValidation(t *testing.T) { // revoke w/ sig // TODO(roasbeef): test invalid revoke makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -329,8 +334,8 @@ func TestHTLCSenderSpendValidation(t *testing.T) { { // HTLC with invalid preimage size makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -355,8 +360,36 @@ func TestHTLCSenderSpendValidation(t *testing.T) { // HTLC with valid preimage size + sig // TODO(roasbeef): invalid preimage makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: bobKeyPub, + }, + SingleTweak: bobCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return SenderHtlcSpendRedeem(bobSigner, signDesc, + sweepTx, paymentPreimage) + }), + true, + }, + { + // HTLC with valid preimage size + sig, and with + // enforced locktime in HTLC script. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + // Make a commit tx that needs confirmation for + // HTLC output to be spent. + genCommitTx(true) + + // Generate a sweep with the locktime set. + genSweepTx(true) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -375,13 +408,43 @@ func TestHTLCSenderSpendValidation(t *testing.T) { }), true, }, + { + // HTLC with valid preimage size + sig, but trying to + // spend CSV output without sequence set. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + // Generate commitment tx with 1 CSV locked + // HTLC. + genCommitTx(true) + + // Generate sweep tx that doesn't have locktime + // enabled. + genSweepTx(false) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: bobKeyPub, + }, + SingleTweak: bobCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return SenderHtlcSpendRedeem(bobSigner, signDesc, + sweepTx, paymentPreimage) + }), + false, + }, + { // valid spend to the transition the state of the HTLC // output with the second level HTLC timeout // transaction. makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -400,6 +463,65 @@ func TestHTLCSenderSpendValidation(t *testing.T) { }), true, }, + { + // valid spend to the transition the state of the HTLC + // output with the second level HTLC timeout + // transaction. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + // Make a commit tx that needs confirmation for + // HTLC output to be spent. + genCommitTx(true) + + // Generate a sweep with the locktime set. + genSweepTx(true) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: aliceKeyPub, + }, + SingleTweak: aliceCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner, + signDesc, sweepTx) + }), + true, + }, + { + // valid spend to the transition the state of the HTLC + // output with the second level HTLC timeout + // transaction. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + // Generate commitment tx with 1 CSV locked + // HTLC. + genCommitTx(true) + + // Generate sweep tx that doesn't have locktime + // enabled. + genSweepTx(false) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: aliceKeyPub, + }, + SingleTweak: aliceCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner, + signDesc, sweepTx) + }), + false, + }, } // TODO(roasbeef): set of cases to ensure able to sign w/ keypath and From a309132253eb52fb4d8ae552ce1fd427f1e30f98 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:45 +0100 Subject: [PATCH 166/562] input/script_utils test: add test cases for delayed HTLC receiver scrpts --- input/script_utils_test.go | 146 +++++++++++++++++++++++++++++++++---- 1 file changed, 133 insertions(+), 13 deletions(-) diff --git a/input/script_utils_test.go b/input/script_utils_test.go index ad7609bb21..6f87197990 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -613,12 +613,12 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { aliceSenderSig []byte ) - genCommitTx := func() { + genCommitTx := func(confirmed bool) { // Generate the raw HTLC redemption scripts, and its p2wsh // counterpart. htlcWitnessScript, err = ReceiverHTLCScript( cltvTimeout, aliceLocalKey, bobLocalKey, revocationKey, - paymentHash[:], false, + paymentHash[:], confirmed, ) if err != nil { t.Fatalf("unable to create htlc sender script: %v", err) @@ -641,7 +641,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { receiverCommitTx.AddTxOut(htlcOutput) } - genSweepTx := func() { + genSweepTx := func(confirmed bool) { prevOut := &wire.OutPoint{ Hash: receiverCommitTx.TxHash(), Index: 0, @@ -651,6 +651,9 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { sweepTx.AddTxIn(&wire.TxIn{ PreviousOutPoint: *prevOut, }) + if confirmed { + sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1) + } sweepTx.AddTxOut( &wire.TxOut{ @@ -688,8 +691,8 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // HTLC redemption w/ invalid preimage size makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -713,8 +716,8 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // HTLC redemption w/ valid preimage size makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -737,8 +740,8 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // revoke w/ sig makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -757,11 +760,71 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { }), true, }, + { + // HTLC redemption w/ valid preimage size, and with + // enforced locktime in HTLC scripts. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + // Make a commit tx that needs confirmation for + // HTLC output to be spent. + genCommitTx(true) + + // Generate a sweep with the locktime set. + genSweepTx(true) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: bobKeyPub, + }, + SingleTweak: bobCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return ReceiverHtlcSpendRedeem(aliceSenderSig, + paymentPreimage, bobSigner, + signDesc, sweepTx) + }), + true, + }, + { + // HTLC redemption w/ valid preimage size, but trying + // to spend CSV output without sequence set. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + // Generate commitment tx with 1 CSV locked + // HTLC. + genCommitTx(true) + + // Generate sweep tx that doesn't have locktime + // enabled. + genSweepTx(false) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: bobKeyPub, + }, + SingleTweak: bobCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return ReceiverHtlcSpendRedeem(aliceSenderSig, + paymentPreimage, bobSigner, + signDesc, sweepTx) + }), + false, + }, + { // refund w/ invalid lock time makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -783,8 +846,8 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { { // refund w/ valid lock time makeWitnessTestCase(t, func() (wire.TxWitness, error) { - genCommitTx() - genSweepTx() + genCommitTx(false) + genSweepTx(false) signDesc := &SignDescriptor{ KeyDesc: keychain.KeyDescriptor{ @@ -803,6 +866,63 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { }), true, }, + { + // refund w/ valid lock time, and enforced locktime in + // HTLC scripts. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + // Make a commit tx that needs confirmation for + // HTLC output to be spent. + genCommitTx(true) + + // Generate a sweep with the locktime set. + genSweepTx(true) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: aliceKeyPub, + }, + SingleTweak: aliceCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return ReceiverHtlcSpendTimeout(aliceSigner, signDesc, + sweepTx, int32(cltvTimeout)) + }), + true, + }, + { + // refund w/ valid lock time, but no sequence set in + // sweep tx trying to spend CSV locked HTLC output. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + // Generate commitment tx with 1 CSV locked + // HTLC. + genCommitTx(true) + + // Generate sweep tx that doesn't have locktime + // enabled. + genSweepTx(false) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: aliceKeyPub, + }, + SingleTweak: aliceCommitTweak, + WitnessScript: htlcWitnessScript, + Output: htlcOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return ReceiverHtlcSpendTimeout(aliceSigner, signDesc, + sweepTx, int32(cltvTimeout)) + }), + false, + }, } for i, testCase := range testCases { From 990992ce94b473dfbf2091d136468f232aa28513 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:45 +0100 Subject: [PATCH 167/562] input/script_utils: add delayed to_remote script + tests --- input/script_utils.go | 75 +++++++++++++++++++++----- input/script_utils_test.go | 107 +++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+), 12 deletions(-) diff --git a/input/script_utils.go b/input/script_utils.go index 7342e2e666..8c650c94cb 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -853,18 +853,6 @@ func CommitScriptToSelf(csvTimeout uint32, selfKey, revokeKey *btcec.PublicKey) return builder.Script() } -// CommitScriptUnencumbered constructs the public key script on the commitment -// transaction paying to the "other" party. The constructed output is a normal -// p2wkh output spendable immediately, requiring no contestation period. -func CommitScriptUnencumbered(key *btcec.PublicKey) ([]byte, error) { - // This script goes to the "other" party, and is spendable immediately. - builder := txscript.NewScriptBuilder() - builder.AddOp(txscript.OP_0) - builder.AddData(btcutil.Hash160(key.SerializeCompressed())) - - return builder.Script() -} - // CommitSpendTimeout constructs a valid witness allowing the owner of a // particular commitment transaction to spend the output returning settled // funds back to themselves after a relative block timeout. In order to @@ -973,6 +961,69 @@ func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor, return witness, nil } +// CommitScriptUnencumbered constructs the public key script on the commitment +// transaction paying to the "other" party. The constructed output is a normal +// p2wkh output spendable immediately, requiring no contestation period. +func CommitScriptUnencumbered(key *btcec.PublicKey) ([]byte, error) { + // This script goes to the "other" party, and is spendable immediately. + builder := txscript.NewScriptBuilder() + builder.AddOp(txscript.OP_0) + builder.AddData(btcutil.Hash160(key.SerializeCompressed())) + + return builder.Script() +} + +// CommitScriptToRemoteConfirmed constructs the script for the output on the +// commitment transaction paying to the remote party of said commitment +// transaction. The money can only be spend after one confirmation. +// +// Possible Input Scripts: +// SWEEP: +// +// Output Script: +// OP_CHECKSIGVERIFY +// 1 OP_CHECKSEQUENCEVERIFY +func CommitScriptToRemoteConfirmed(key *btcec.PublicKey) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + // Only the given key can spend the output. + builder.AddData(key.SerializeCompressed()) + builder.AddOp(txscript.OP_CHECKSIGVERIFY) + + // Check that the it has one confirmation. + builder.AddOp(txscript.OP_1) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) + + return builder.Script() +} + +// CommitSpendToRemoteConfirmed constructs a valid witness allowing a node to +// spend their settled output on the counterparty's commitment transaction when +// it has one confirmetion. This is used for the anchor channel type. The +// spending key will always be non-tweaked for this output type. +func CommitSpendToRemoteConfirmed(signer Signer, signDesc *SignDescriptor, + sweepTx *wire.MsgTx) (wire.TxWitness, error) { + + if signDesc.KeyDesc.PubKey == nil { + return nil, fmt.Errorf("cannot generate witness with nil " + + "KeyDesc pubkey") + } + + // Similar to non delayed output, only a signature is needed. + sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc) + if err != nil { + return nil, err + } + + // Finally, we'll manually craft the witness. The witness here is the + // signature and the redeem script. + witnessStack := make([][]byte, 2) + witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[1] = signDesc.WitnessScript + + return witnessStack, nil +} + // SingleTweakBytes computes set of bytes we call the single tweak. The purpose // of the single tweak is to randomize all regular delay and payment base // points. To do this, we generate a hash that binds the commitment point to diff --git a/input/script_utils_test.go b/input/script_utils_test.go index 6f87197990..dcec43a119 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -1144,6 +1144,113 @@ func TestSecondLevelHtlcSpends(t *testing.T) { } } +// TestCommitSpendToRemoteConfirmed checks that the delayed version of the +// to_remote version can only be spent by the owner, and after one +// confirmation. +func TestCommitSpendToRemoteConfirmed(t *testing.T) { + t.Parallel() + + const outputVal = btcutil.Amount(2 * 10e8) + + aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(), + testWalletPrivKey) + + txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) + if err != nil { + t.Fatalf("unable to create txid: %v", err) + } + commitOut := &wire.OutPoint{ + Hash: *txid, + Index: 0, + } + commitScript, err := CommitScriptToRemoteConfirmed(aliceKeyPub) + if err != nil { + t.Fatalf("unable to create htlc script: %v", err) + } + commitPkScript, err := WitnessScriptHash(commitScript) + if err != nil { + t.Fatalf("unable to create htlc output: %v", err) + } + + commitOutput := &wire.TxOut{ + PkScript: commitPkScript, + Value: int64(outputVal), + } + + sweepTx := wire.NewMsgTx(2) + sweepTx.AddTxIn(wire.NewTxIn(commitOut, nil, nil)) + sweepTx.AddTxOut( + &wire.TxOut{ + PkScript: []byte("doesn't matter"), + Value: 1 * 10e8, + }, + ) + + aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}} + + testCases := []struct { + witness func() wire.TxWitness + valid bool + }{ + { + // Alice can spend after the a CSV delay has passed. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 1) + sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: aliceKeyPub, + }, + WitnessScript: commitScript, + Output: commitOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return CommitSpendToRemoteConfirmed(aliceSigner, signDesc, + sweepTx) + }), + true, + }, + { + // Alice cannot spend output without sequence set. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum + sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: aliceKeyPub, + }, + WitnessScript: commitScript, + Output: commitOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return CommitSpendToRemoteConfirmed(aliceSigner, signDesc, + sweepTx) + }), + false, + }, + } + + for i, testCase := range testCases { + sweepTx.TxIn[0].Witness = testCase.witness() + + newEngine := func() (*txscript.Engine, error) { + return txscript.NewEngine(commitPkScript, + sweepTx, 0, txscript.StandardVerifyFlags, nil, + nil, int64(outputVal)) + } + + assertEngineExecution(t, i, testCase.valid, newEngine) + } +} + // TestSpecificationKeyDerivation implements the test vectors provided in // BOLT-03, Appendix E. func TestSpecificationKeyDerivation(t *testing.T) { From 6deb913a8d944166da6073c18d201651bb3ffff3 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:46 +0100 Subject: [PATCH 168/562] input: add CommitmentToRemoteConfirmed witness type --- input/size.go | 16 ++++++++++++++++ input/witnessgen.go | 29 +++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/input/size.go b/input/size.go index 2bea38ce3c..991ac9cfa9 100644 --- a/input/size.go +++ b/input/size.go @@ -213,6 +213,22 @@ const ( // - witness_script (to_local_script) ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize + // ToRemoteConfirmedScriptSize 37 bytes + // - OP_DATA: 1 byte + // - to_remote_key: 33 bytes + // - OP_CHECKSIGVERIFY: 1 byte + // - OP_1: 1 byte + // - OP_CHECKSEQUENCEVERIFY: 1 byte + ToRemoteConfirmedScriptSize = 1 + 33 + 1 + 1 + 1 + + // ToRemoteConfirmedWitnessSize 113 bytes + // - number_of_witness_elements: 1 byte + // - sig_length: 1 byte + // - sig: 73 bytes + // - witness_script_length: 1 byte + // - witness_script (to_remote_delayed_script) + ToRemoteConfirmedWitnessSize = 1 + 1 + 73 + 1 + ToRemoteConfirmedScriptSize + // AcceptedHtlcScriptSize 142 bytes // - OP_DUP: 1 byte // - OP_HASH160: 1 byte diff --git a/input/witnessgen.go b/input/witnessgen.go index 0a2fafb328..7fc509cb61 100644 --- a/input/witnessgen.go +++ b/input/witnessgen.go @@ -48,8 +48,9 @@ type StandardWitnessType uint16 var _ WitnessType = (StandardWitnessType)(0) const ( - // CommitmentTimeLock is a witness that allows us to spend the output of - // a commitment transaction after a relative lock-time lockout. + // CommitmentTimeLock is a witness that allows us to spend our output + // on our local commitment transaction after a relative lock-time + // lockout. CommitmentTimeLock StandardWitnessType = 0 // CommitmentNoDelay is a witness that allows us to spend a settled @@ -119,6 +120,11 @@ const ( // type, but it omits the tweak that randomizes the key we need to // spend with a channel peer supplied set of randomness. CommitSpendNoDelayTweakless StandardWitnessType = 12 + + // CommitmentToRemoteConfirmed is a witness that allows us to spend our + // output on the counterparty's commitment transaction after a + // confirmation. + CommitmentToRemoteConfirmed StandardWitnessType = 13 ) // String returns a human readable version of the target WitnessType. @@ -129,6 +135,9 @@ func (wt StandardWitnessType) String() string { case CommitmentTimeLock: return "CommitmentTimeLock" + case CommitmentToRemoteConfirmed: + return "CommitmentToRemoteConfirmed" + case CommitmentNoDelay: return "CommitmentNoDelay" @@ -197,6 +206,18 @@ func (wt StandardWitnessType) WitnessGenerator(signer Signer, Witness: witness, }, nil + case CommitmentToRemoteConfirmed: + witness, err := CommitSpendToRemoteConfirmed( + signer, desc, tx, + ) + if err != nil { + return nil, err + } + + return &Script{ + Witness: witness, + }, nil + case CommitmentNoDelay: witness, err := CommitSpendNoDelay(signer, desc, tx, false) if err != nil { @@ -323,6 +344,10 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case CommitmentTimeLock: return ToLocalTimeoutWitnessSize, false, nil + // 1 CSV time locked output to us on remote commitment. + case CommitmentToRemoteConfirmed: + return ToRemoteConfirmedWitnessSize, false, nil + // Outgoing second layer HTLC's that have confirmed within the // chain, and the output they produced is now mature enough to // sweep. From 50199aeaf3b758186c564d3b6c7d036bb67272e2 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:46 +0100 Subject: [PATCH 169/562] input/script_utils: add anchor scripts + tests --- input/script_utils.go | 68 +++++++++++++++++++++++ input/script_utils_test.go | 107 +++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) diff --git a/input/script_utils.go b/input/script_utils.go index 8c650c94cb..b0c89a15db 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -1024,6 +1024,74 @@ func CommitSpendToRemoteConfirmed(signer Signer, signDesc *SignDescriptor, return witnessStack, nil } +// CommitScriptAnchor constructs the script for the anchor output spendable by +// the given key immediately, or by anyone after 16 confirmations. +// +// Possible Input Scripts: +// By owner: +// By anyone (after 16 conf): +// +// Output Script: +// OP_CHECKSIG OP_IFDUP +// OP_NOTIF +// OP_16 OP_CSV +// OP_ENDIF +func CommitScriptAnchor(key *btcec.PublicKey) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + // Spend immediately with key. + builder.AddData(key.SerializeCompressed()) + builder.AddOp(txscript.OP_CHECKSIG) + + // Duplicate the value if true, since it will be consumed by the NOTIF. + builder.AddOp(txscript.OP_IFDUP) + + // Otherwise spendable by anyone after 16 confirmations. + builder.AddOp(txscript.OP_NOTIF) + builder.AddOp(txscript.OP_16) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) + builder.AddOp(txscript.OP_ENDIF) + + return builder.Script() +} + +// CommitSpendAnchor constructs a valid witness allowing a node to spend their +// anchor output on the commitment transaction using their funding key. This is +// used for the anchor channel type. +func CommitSpendAnchor(signer Signer, signDesc *SignDescriptor, + sweepTx *wire.MsgTx) (wire.TxWitness, error) { + + if signDesc.KeyDesc.PubKey == nil { + return nil, fmt.Errorf("cannot generate witness with nil " + + "KeyDesc pubkey") + } + + // Create a signature. + sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc) + if err != nil { + return nil, err + } + + // The witness here is just a signature and the redeem script. + witnessStack := make([][]byte, 2) + witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[1] = signDesc.WitnessScript + + return witnessStack, nil +} + +// CommitSpendAnchorAnyone constructs a witness allowing anyone to spend the +// anchor output after it has gotten 16 confirmations. Since no signing is +// required, only knowledge of the redeem script is necessary to spend it. +func CommitSpendAnchorAnyone(script []byte) (wire.TxWitness, error) { + // The witness here is just the redeem script. + witnessStack := make([][]byte, 2) + witnessStack[0] = nil + witnessStack[1] = script + + return witnessStack, nil +} + // SingleTweakBytes computes set of bytes we call the single tweak. The purpose // of the single tweak is to randomize all regular delay and payment base // points. To do this, we generate a hash that binds the commitment point to diff --git a/input/script_utils_test.go b/input/script_utils_test.go index dcec43a119..33b78ee208 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -1251,6 +1251,113 @@ func TestCommitSpendToRemoteConfirmed(t *testing.T) { } } +// TestSpendAnchor checks that we can spend the anchors using the various spend +// paths. +func TestSpendAnchor(t *testing.T) { + t.Parallel() + + const anchorSize = 294 + + // First we'll set up some initial key state for Alice. + aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(), + testWalletPrivKey) + + // Create a fake anchor outpoint that we'll use to generate the + // sweeping transaction. + txid, err := chainhash.NewHash(testHdSeed.CloneBytes()) + if err != nil { + t.Fatalf("unable to create txid: %v", err) + } + anchorOutPoint := &wire.OutPoint{ + Hash: *txid, + Index: 0, + } + + sweepTx := wire.NewMsgTx(2) + sweepTx.AddTxIn(wire.NewTxIn(anchorOutPoint, nil, nil)) + sweepTx.AddTxOut( + &wire.TxOut{ + PkScript: []byte("doesn't matter"), + Value: 1 * 10e8, + }, + ) + + // Generate the anchor script that can be spent by Alice immediately, + // or by anyone after 16 blocks. + anchorScript, err := CommitScriptAnchor(aliceKeyPub) + if err != nil { + t.Fatalf("unable to create htlc script: %v", err) + } + anchorPkScript, err := WitnessScriptHash(anchorScript) + if err != nil { + t.Fatalf("unable to create htlc output: %v", err) + } + + anchorOutput := &wire.TxOut{ + PkScript: anchorPkScript, + Value: int64(anchorSize), + } + + // Create mock signer for Alice. + aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}} + + testCases := []struct { + witness func() wire.TxWitness + valid bool + }{ + { + // Alice can spend immediately. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum + sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx) + + signDesc := &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: aliceKeyPub, + }, + WitnessScript: anchorScript, + Output: anchorOutput, + HashType: txscript.SigHashAll, + SigHashes: sweepTxSigHashes, + InputIndex: 0, + } + + return CommitSpendAnchor(aliceSigner, signDesc, + sweepTx) + }), + true, + }, + { + // Anyone can spend after 16 blocks. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 16) + return CommitSpendAnchorAnyone(anchorScript) + }), + true, + }, + { + // Anyone cannot spend before 16 blocks. + makeWitnessTestCase(t, func() (wire.TxWitness, error) { + sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, 15) + return CommitSpendAnchorAnyone(anchorScript) + }), + false, + }, + } + + for i, testCase := range testCases { + sweepTx.TxIn[0].Witness = testCase.witness() + + newEngine := func() (*txscript.Engine, error) { + return txscript.NewEngine(anchorPkScript, + sweepTx, 0, txscript.StandardVerifyFlags, nil, + nil, int64(anchorSize)) + } + + assertEngineExecution(t, i, testCase.valid, newEngine) + } +} + // TestSpecificationKeyDerivation implements the test vectors provided in // BOLT-03, Appendix E. func TestSpecificationKeyDerivation(t *testing.T) { From af68ff1640125a7e086ae6ac7da858c5b4ae6620 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:46 +0100 Subject: [PATCH 170/562] lnwallet: add anchor commitmenttype With this commitment type, we'll add extra anchor outputs to the commitment transaction if the anchor channel type is active. --- channeldb/channel.go | 6 +- contractcourt/chain_watcher.go | 5 +- lnwallet/channel.go | 22 +++--- lnwallet/commitment.go | 130 +++++++++++++++++++++++++++++---- lnwallet/transactions_test.go | 2 +- lnwallet/wallet.go | 4 +- 6 files changed, 136 insertions(+), 33 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 1ce43ad475..4b97caa63a 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -338,13 +338,15 @@ type ChannelCommitment struct { // LocalBalance is the current available settled balance within the // channel directly spendable by us. // - // NOTE: This is the balance *after* subtracting any commitment fee. + // NOTE: This is the balance *after* subtracting any commitment fee, + // AND anchor output values. LocalBalance lnwire.MilliSatoshi // RemoteBalance is the current available settled balance within the // channel directly spendable by the remote node. // - // NOTE: This is the balance *after* subtracting any commitment fee. + // NOTE: This is the balance *after* subtracting any commitment fee, + // AND anchor output values. RemoteBalance lnwire.MilliSatoshi // CommitFee is the amount calculated to be paid in fees for the diff --git a/contractcourt/chain_watcher.go b/contractcourt/chain_watcher.go index 3012376b39..bbb3cbb1e2 100644 --- a/contractcourt/chain_watcher.go +++ b/contractcourt/chain_watcher.go @@ -351,9 +351,8 @@ func isOurCommitment(localChanCfg, remoteChanCfg channeldb.ChannelConfig, // With the keys derived, we'll construct the remote script that'll be // present if they have a non-dust balance on the commitment. - remoteDelay := uint32(remoteChanCfg.CsvDelay) - remoteScript, err := lnwallet.CommitScriptToRemote( - chanType, remoteDelay, commitKeyRing.ToRemoteKey, + remoteScript, _, err := lnwallet.CommitScriptToRemote( + chanType, commitKeyRing.ToRemoteKey, ) if err != nil { return false, err diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 79722da89c..b62985fc03 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -503,7 +503,8 @@ type commitment struct { // evaluating all the add/remove/settle log entries before the listed // indexes. // - // NOTE: This is the balance *after* subtracting any commitment fee. + // NOTE: This is the balance *after* subtracting any commitment fee, + // AND anchor output values. ourBalance lnwire.MilliSatoshi theirBalance lnwire.MilliSatoshi @@ -2089,9 +2090,8 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, // Since it is the remote breach we are reconstructing, the output going // to us will be a to-remote script with our local params. - ourDelay := uint32(chanState.LocalChanCfg.CsvDelay) - ourScript, err := CommitScriptToRemote( - chanState.ChanType, ourDelay, keyRing.ToRemoteKey, + ourScript, _, err := CommitScriptToRemote( + chanState.ChanType, keyRing.ToRemoteKey, ) if err != nil { return nil, err @@ -5027,8 +5027,8 @@ func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) { } // CommitOutputResolution carries the necessary information required to allow -// us to sweep our direct commitment output in the case that either party goes -// to chain. +// us to sweep our commitment output in the case that either party goes to +// chain. type CommitOutputResolution struct { // SelfOutPoint is the full outpoint that points to out pay-to-self // output within the closing commitment transaction. @@ -5040,8 +5040,7 @@ type CommitOutputResolution struct { // MaturityDelay is the relative time-lock, in blocks for all outputs // that pay to the local party within the broadcast commitment - // transaction. This value will be non-zero iff, this output was on our - // commitment transaction. + // transaction. MaturityDelay uint32 } @@ -5122,9 +5121,8 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Si // Before we can generate the proper sign descriptor, we'll need to // locate the output index of our non-delayed output on the commitment // transaction. - localDelay := uint32(chanState.LocalChanCfg.CsvDelay) - selfScript, err := CommitScriptToRemote( - chanState.ChanType, localDelay, keyRing.ToRemoteKey, + selfScript, maturityDelay, err := CommitScriptToRemote( + chanState.ChanType, keyRing.ToRemoteKey, ) if err != nil { return nil, fmt.Errorf("unable to create self commit "+ @@ -5165,7 +5163,7 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Si }, HashType: txscript.SigHashAll, }, - MaturityDelay: 0, + MaturityDelay: maturityDelay, } } diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 2f8b93ac1c..e3d98cb479 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -13,6 +13,9 @@ import ( "github.com/lightningnetwork/lnd/lnwire" ) +// anchorSize is the constant anchor output size. +const anchorSize = btcutil.Amount(330) + // CommitmentKeyRing holds all derived keys needed to construct commitment and // HTLC transactions. The keys are derived differently depending whether the // commitment transaction is ours or the remote peer's. Private keys associated @@ -183,13 +186,34 @@ type ScriptInfo struct { // CommitScriptToRemote creates the script that will pay to the non-owner of // the commitment transaction, adding a delay to the script based on the -// channel type. -func CommitScriptToRemote(_ channeldb.ChannelType, csvTimeout uint32, - key *btcec.PublicKey) (*ScriptInfo, error) { +// channel type. The second return value is the CSV deleay of the output +// script, what must be satisfied in order to spend the output. +func CommitScriptToRemote(chanType channeldb.ChannelType, + key *btcec.PublicKey) (*ScriptInfo, uint32, error) { + + // If this channel type has anchors, we derive the delayed to_remote + // script. + if chanType.HasAnchors() { + script, err := input.CommitScriptToRemoteConfirmed(key) + if err != nil { + return nil, 0, err + } + + p2wsh, err := input.WitnessScriptHash(script) + if err != nil { + return nil, 0, err + } + + return &ScriptInfo{ + PkScript: p2wsh, + WitnessScript: script, + }, 1, nil + } + // Otherwise the to_remote will be a simple p2wkh. p2wkh, err := input.CommitScriptUnencumbered(key) if err != nil { - return nil, err + return nil, 0, err } // Since this is a regular P2WKH, the WitnessScipt and PkScript should @@ -197,7 +221,47 @@ func CommitScriptToRemote(_ channeldb.ChannelType, csvTimeout uint32, return &ScriptInfo{ WitnessScript: p2wkh, PkScript: p2wkh, - }, nil + }, 0, nil +} + +// CommitScriptAnchors return the scripts to use for the local and remote +// anchor. +func CommitScriptAnchors(localChanCfg, + remoteChanCfg *channeldb.ChannelConfig) (*ScriptInfo, + *ScriptInfo, error) { + + // Helper to create anchor ScriptInfo from key. + anchorScript := func(key *btcec.PublicKey) (*ScriptInfo, error) { + script, err := input.CommitScriptAnchor(key) + if err != nil { + return nil, err + } + + scriptHash, err := input.WitnessScriptHash(script) + if err != nil { + return nil, err + } + + return &ScriptInfo{ + PkScript: scriptHash, + WitnessScript: script, + }, nil + } + + // Get the script used for the anchor output spendable by the local + // node. + localAnchor, err := anchorScript(localChanCfg.MultiSigKey.PubKey) + if err != nil { + return nil, nil, err + } + + // And the anchor spemdable by the remote node. + remoteAnchor, err := anchorScript(remoteChanCfg.MultiSigKey.PubKey) + if err != nil { + return nil, nil, err + } + + return localAnchor, remoteAnchor, nil } // CommitmentBuilder is a type that wraps the type of channel we are dealing @@ -216,6 +280,11 @@ type CommitmentBuilder struct { // NewCommitmentBuilder creates a new CommitmentBuilder from chanState. func NewCommitmentBuilder(chanState *channeldb.OpenChannel) *CommitmentBuilder { + // The anchor channel type MUST be tweakless. + if chanState.ChanType.HasAnchors() && !chanState.ChanType.IsTweakless() { + panic("invalid channel type combination") + } + return &CommitmentBuilder{ chanState: chanState, obfuscator: createStateHintObfuscator(chanState), @@ -248,8 +317,9 @@ type unsignedCommitmentTx struct { // fee is the total fee of the commitment transaction. fee btcutil.Amount - // ourBalance|theirBalance is the balances of this commitment. This can - // be different than the balances before creating the commitment + // ourBalance|theirBalance are the balances of this commitment *after* + // subtracting commitment fees and anchor outputs. This can be + // different than the balances before creating the commitment // transaction as one party must pay the commitment fee. ourBalance lnwire.MilliSatoshi theirBalance lnwire.MilliSatoshi @@ -258,7 +328,7 @@ type unsignedCommitmentTx struct { // createUnsignedCommitmentTx generates the unsigned commitment transaction for // a commitment view and returns it as part of the unsignedCommitmentTx. The // passed in balances should be balances *before* subtracting any commitment -// fees. +// fees, but after anchor outputs. func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, theirBalance lnwire.MilliSatoshi, isOurs bool, feePerKw chainfee.SatPerKWeight, height uint64, @@ -333,12 +403,14 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, cb.chanState.ChanType, fundingTxIn(cb.chanState), keyRing, &cb.chanState.LocalChanCfg, &cb.chanState.RemoteChanCfg, ourBalance.ToSatoshis(), theirBalance.ToSatoshis(), + numHTLCs, ) } else { commitTx, err = CreateCommitTx( cb.chanState.ChanType, fundingTxIn(cb.chanState), keyRing, &cb.chanState.RemoteChanCfg, &cb.chanState.LocalChanCfg, theirBalance.ToSatoshis(), ourBalance.ToSatoshis(), + numHTLCs, ) } if err != nil { @@ -436,7 +508,8 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, func CreateCommitTx(chanType channeldb.ChannelType, fundingOutput wire.TxIn, keyRing *CommitmentKeyRing, localChanCfg, remoteChanCfg *channeldb.ChannelConfig, - amountToLocal, amountToRemote btcutil.Amount) (*wire.MsgTx, error) { + amountToLocal, amountToRemote btcutil.Amount, + numHTLCs int64) (*wire.MsgTx, error) { // First, we create the script for the delayed "pay-to-self" output. // This output has 2 main redemption clauses: either we can redeem the @@ -458,8 +531,8 @@ func CreateCommitTx(chanType channeldb.ChannelType, } // Next, we create the script paying to the remote. - toRemoteScript, err := CommitScriptToRemote( - chanType, uint32(remoteChanCfg.CsvDelay), keyRing.ToRemoteKey, + toRemoteScript, _, err := CommitScriptToRemote( + chanType, keyRing.ToRemoteKey, ) if err != nil { return nil, err @@ -472,19 +545,50 @@ func CreateCommitTx(chanType channeldb.ChannelType, commitTx.AddTxIn(&fundingOutput) // Avoid creating dust outputs within the commitment transaction. - if amountToLocal >= localChanCfg.DustLimit { + localOutput := amountToLocal >= localChanCfg.DustLimit + if localOutput { commitTx.AddTxOut(&wire.TxOut{ PkScript: toLocalScriptHash, Value: int64(amountToLocal), }) } - if amountToRemote >= localChanCfg.DustLimit { + + remoteOutput := amountToRemote >= localChanCfg.DustLimit + if remoteOutput { commitTx.AddTxOut(&wire.TxOut{ PkScript: toRemoteScript.PkScript, Value: int64(amountToRemote), }) } + // If this channel type has anchors, we'll also add those. + if chanType.HasAnchors() { + localAnchor, remoteAnchor, err := CommitScriptAnchors( + localChanCfg, remoteChanCfg, + ) + if err != nil { + return nil, err + } + + // Add local anchor output only if we have a commitment output + // or there are HTLCs. + if localOutput || numHTLCs > 0 { + commitTx.AddTxOut(&wire.TxOut{ + PkScript: localAnchor.PkScript, + Value: int64(anchorSize), + }) + } + + // Add anchor output to remote only if they have a commitment + // output or there are HTLCs. + if remoteOutput || numHTLCs > 0 { + commitTx.AddTxOut(&wire.TxOut{ + PkScript: remoteAnchor.PkScript, + Value: int64(anchorSize), + }) + } + } + return commitTx, nil } diff --git a/lnwallet/transactions_test.go b/lnwallet/transactions_test.go index db5a8dcefd..7a3f08a299 100644 --- a/lnwallet/transactions_test.go +++ b/lnwallet/transactions_test.go @@ -1090,7 +1090,7 @@ func testSpendValidation(t *testing.T, tweakless bool) { } commitmentTx, err := CreateCommitTx( channelType, *fakeFundingTxIn, keyRing, aliceChanCfg, - bobChanCfg, channelBalance, channelBalance, + bobChanCfg, channelBalance, channelBalance, 0, ) if err != nil { t.Fatalf("unable to create commitment transaction: %v", nil) diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 5143b9f5cc..5649b65242 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -784,7 +784,7 @@ func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount, ourCommitTx, err := CreateCommitTx( chanType, fundingTxIn, localCommitmentKeys, ourChanCfg, - theirChanCfg, localBalance, remoteBalance, + theirChanCfg, localBalance, remoteBalance, 0, ) if err != nil { return nil, nil, err @@ -797,7 +797,7 @@ func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount, theirCommitTx, err := CreateCommitTx( chanType, fundingTxIn, remoteCommitmentKeys, theirChanCfg, - ourChanCfg, remoteBalance, localBalance, + ourChanCfg, remoteBalance, localBalance, 0, ) if err != nil { return nil, nil, err From 1f28bd80869ebe7e185659f949ff79a012bc4e6f Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:46 +0100 Subject: [PATCH 171/562] contractcourt/commit_sweep_resolver: set sweep witness type based on witness script We use the fact that we can tell whether the commit is local or remote by inspecting the witness script. We cannot use the maturity delay anymore, as we can have delayed to_remote outputs also now. Co-authored-by: Joost Jager --- contractcourt/commit_sweep_resolver.go | 38 ++++++++++++++++----- contractcourt/commit_sweep_resolver_test.go | 2 ++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/contractcourt/commit_sweep_resolver.go b/contractcourt/commit_sweep_resolver.go index f2061c0fa6..fe09dc09ff 100644 --- a/contractcourt/commit_sweep_resolver.go +++ b/contractcourt/commit_sweep_resolver.go @@ -6,6 +6,7 @@ import ( "io" "sync" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/input" @@ -172,24 +173,45 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) { } } - // We're dealing with our commitment transaction if the delay on the - // resolution isn't zero. - isLocalCommitTx := c.commitResolution.MaturityDelay != 0 - - // There're two types of commitments, those that have tweaks - // for the remote key (us in this case), and those that don't. - // We'll rely on the presence of the commitment tweak to to - // discern which type of commitment this is. + // The output is on our local commitment if the script starts with + // OP_IF for the revocation clause. On the remote commitment it will + // either be a regular P2WKH or a simple sig spend with a CSV delay. + isLocalCommitTx := c.commitResolution.SelfOutputSignDesc.WitnessScript[0] == txscript.OP_IF + isDelayedOutput := c.commitResolution.MaturityDelay != 0 + + c.log.Debugf("isDelayedOutput=%v, isLocalCommitTx=%v", isDelayedOutput, + isLocalCommitTx) + + // There're three types of commitments, those that have tweaks + // for the remote key (us in this case), those that don't, and a third + // where there is no tweak and the output is delayed. On the local + // commitment our output will always be delayed. We'll rely on the + // presence of the commitment tweak to to discern which type of + // commitment this is. var witnessType input.WitnessType switch { + + // Delayed output to us on our local commitment. case isLocalCommitTx: witnessType = input.CommitmentTimeLock + + // A confirmed output to us on the remote commitment. + case isDelayedOutput: + witnessType = input.CommitmentToRemoteConfirmed + + // A non-delayed output on the remote commitment where the key is + // tweakless. case c.commitResolution.SelfOutputSignDesc.SingleTweak == nil: witnessType = input.CommitSpendNoDelayTweakless + + // A non-delayed output on the remote commitment where the key is + // tweaked. default: witnessType = input.CommitmentNoDelay } + c.log.Infof("Sweeping with witness type: %v", witnessType) + // We'll craft an input with all the information required for // the sweeper to create a fully valid sweeping transaction to // recover these coins. diff --git a/contractcourt/commit_sweep_resolver_test.go b/contractcourt/commit_sweep_resolver_test.go index 4ca018334b..c142167e17 100644 --- a/contractcourt/commit_sweep_resolver_test.go +++ b/contractcourt/commit_sweep_resolver_test.go @@ -133,6 +133,7 @@ func TestCommitSweepResolverNoDelay(t *testing.T) { Output: &wire.TxOut{ Value: 100, }, + WitnessScript: []byte{0}, }, } @@ -162,6 +163,7 @@ func TestCommitSweepResolverDelay(t *testing.T) { Output: &wire.TxOut{ Value: amt, }, + WitnessScript: []byte{0}, }, MaturityDelay: 3, SelfOutPoint: outpoint, From ea94dbbe34c8b0adf28651f2c1c6f2efcb1a51e0 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:46 +0100 Subject: [PATCH 172/562] input+lnwallet: use individual commit weight calculations for channel type Based on the channel type, the commitment weight will be calculated. --- input/size.go | 29 +++++++++++++++++++++++++++++ lnwallet/channel.go | 5 +++-- lnwallet/commitment.go | 13 ++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/input/size.go b/input/size.go index 991ac9cfa9..005c227301 100644 --- a/input/size.go +++ b/input/size.go @@ -122,6 +122,12 @@ const ( // - PkScript (P2WPKH) CommitmentKeyHashOutput = 8 + 1 + P2WPKHSize + // CommitmentAnchorOutput 43 bytes + // - Value: 8 bytes + // - VarInt: 1 byte (PkScript length) + // - PkScript (P2WSH) + CommitmentAnchorOutput = 8 + 1 + P2WSHSize + // HTLCSize 43 bytes // - Value: 8 bytes // - VarInt: 1 byte (PkScript length) @@ -159,9 +165,32 @@ const ( // WitnessCommitmentTxWeight 224 weight WitnessCommitmentTxWeight = WitnessHeaderSize + WitnessSize + // BaseAnchorCommitmentTxSize 225 + 43 * num-htlc-outputs bytes + // - Version: 4 bytes + // - WitnessHeader <---- part of the witness data + // - CountTxIn: 1 byte + // - TxIn: 41 bytes + // FundingInput + // - CountTxOut: 3 byte + // - TxOut: 4*43 + 43 * num-htlc-outputs bytes + // OutputPayingToThem, + // OutputPayingToUs, + // AnchorPayingToThem, + // AnchorPayingToUs, + // ....HTLCOutputs... + // - LockTime: 4 bytes + BaseAnchorCommitmentTxSize = 4 + 1 + FundingInputSize + 3 + + 2*CommitmentDelayOutput + 2*CommitmentAnchorOutput + 4 + + // BaseAnchorCommitmentTxWeight 900 weight + BaseAnchorCommitmentTxWeight = witnessScaleFactor * BaseAnchorCommitmentTxSize + // CommitWeight 724 weight CommitWeight = BaseCommitmentTxWeight + WitnessCommitmentTxWeight + // AnchorCommitWeight 1124 weight + AnchorCommitWeight = BaseAnchorCommitmentTxWeight + WitnessCommitmentTxWeight + // HTLCWeight 172 weight HTLCWeight = witnessScaleFactor * HTLCSize diff --git a/lnwallet/channel.go b/lnwallet/channel.go index b62985fc03..148a5a57a8 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -3772,7 +3772,8 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, totalHtlcWeight += input.HTLCWeight } - totalCommitWeight := input.CommitWeight + totalHtlcWeight + totalCommitWeight := CommitWeight(lc.channelState.ChanType) + + totalHtlcWeight return ourBalance, theirBalance, totalCommitWeight, filteredHTLCView, nil } @@ -6322,7 +6323,7 @@ func CreateCooperativeCloseTx(fundingTxIn wire.TxIn, // CalcFee returns the commitment fee to use for the given // fee rate (fee-per-kw). func (lc *LightningChannel) CalcFee(feeRate chainfee.SatPerKWeight) btcutil.Amount { - return feeRate.FeeForWeight(input.CommitWeight) + return feeRate.FeeForWeight(CommitWeight(lc.channelState.ChanType)) } // MaxFeeRate returns the maximum fee rate given an allocation of the channel diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index e3d98cb479..648dbf378d 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -224,6 +224,16 @@ func CommitScriptToRemote(chanType channeldb.ChannelType, }, 0, nil } +// CommitWeight returns the base commitment weight before adding HTLCs. +func CommitWeight(chanType channeldb.ChannelType) int64 { + // If this commitment has anchors, it will be slightly heavier. + if chanType.HasAnchors() { + return input.AnchorCommitWeight + } + + return input.CommitWeight +} + // CommitScriptAnchors return the scripts to use for the local and remote // anchor. func CommitScriptAnchors(localChanCfg, @@ -364,7 +374,8 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, // on its total weight. Once we have the total weight, we'll multiply // by the current fee-per-kw, then divide by 1000 to get the proper // fee. - totalCommitWeight := input.CommitWeight + (input.HTLCWeight * numHTLCs) + totalCommitWeight := CommitWeight(cb.chanState.ChanType) + + input.HTLCWeight*numHTLCs // With the weight known, we can now calculate the commitment fee, // ensuring that we account for any dust outputs trimmed above. From 21c5a957bc0365ea69f7eb99d5c32d694b854dba Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:46 +0100 Subject: [PATCH 173/562] lnwallet/channel: add feerate sanity check --- lnwallet/channel.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 148a5a57a8..d71348a66d 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2372,6 +2372,29 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool, return nil, err } + // We'll assert that there hasn't been a mistake during fee calculation + // leading to a fee too low. + var totalOut btcutil.Amount + for _, txOut := range commitTx.txn.TxOut { + totalOut += btcutil.Amount(txOut.Value) + } + fee := lc.channelState.Capacity - totalOut + + // Since the transaction is not signed yet, we use the witness weight + // used for weight calculation. + uTx := btcutil.NewTx(commitTx.txn) + weight := blockchain.GetTransactionWeight(uTx) + + input.WitnessCommitmentTxWeight + + effFeeRate := chainfee.SatPerKWeight(fee) * 1000 / + chainfee.SatPerKWeight(weight) + if effFeeRate < chainfee.FeePerKwFloor { + return nil, fmt.Errorf("height=%v, for ChannelPoint(%v) "+ + "attempts to create commitment wigh feerate %v: %v", + nextHeight, lc.channelState.FundingOutpoint, + effFeeRate, spew.Sdump(commitTx)) + } + // With the commitment view created, store the resulting balances and // transaction with the other parameters for this height. c := &commitment{ From 6810912c86de4d48f0de282f1841421ea4f71d2f Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:47 +0100 Subject: [PATCH 174/562] lnwallet: choose HTLC scripts based on channel type --- lnwallet/commitment.go | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 648dbf378d..ce609f0c6e 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -615,6 +615,12 @@ func genHtlcScript(chanType channeldb.ChannelType, isIncoming, ourCommit bool, err error ) + // Choose scripts based on channel type. + confirmedHtlcSpends := false + if chanType.HasAnchors() { + confirmedHtlcSpends = true + } + // Generate the proper redeem scripts for the HTLC output modified by // two-bits denoting if this is an incoming HTLC, and if the HTLC is // being applied to their commitment transaction or ours. @@ -623,30 +629,37 @@ func genHtlcScript(chanType channeldb.ChannelType, isIncoming, ourCommit bool, // transaction. So we need to use the receiver's version of HTLC the // script. case isIncoming && ourCommit: - witnessScript, err = input.ReceiverHTLCScript(timeout, - keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey, - keyRing.RevocationKey, rHash[:], false) + witnessScript, err = input.ReceiverHTLCScript( + timeout, keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey, + keyRing.RevocationKey, rHash[:], confirmedHtlcSpends, + ) // We're being paid via an HTLC by the remote party, and the HTLC is // being added to their commitment transaction, so we use the sender's // version of the HTLC script. case isIncoming && !ourCommit: - witnessScript, err = input.SenderHTLCScript(keyRing.RemoteHtlcKey, - keyRing.LocalHtlcKey, keyRing.RevocationKey, rHash[:], false) + witnessScript, err = input.SenderHTLCScript( + keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey, + keyRing.RevocationKey, rHash[:], confirmedHtlcSpends, + ) // We're sending an HTLC which is being added to our commitment // transaction. Therefore, we need to use the sender's version of the // HTLC script. case !isIncoming && ourCommit: - witnessScript, err = input.SenderHTLCScript(keyRing.LocalHtlcKey, - keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:], false) + witnessScript, err = input.SenderHTLCScript( + keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey, + keyRing.RevocationKey, rHash[:], confirmedHtlcSpends, + ) // Finally, we're paying the remote party via an HTLC, which is being // added to their commitment transaction. Therefore, we use the // receiver's version of the HTLC script. case !isIncoming && !ourCommit: - witnessScript, err = input.ReceiverHTLCScript(timeout, keyRing.LocalHtlcKey, - keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:], false) + witnessScript, err = input.ReceiverHTLCScript( + timeout, keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey, + keyRing.RevocationKey, rHash[:], confirmedHtlcSpends, + ) } if err != nil { return nil, nil, err From d1089fb449f6c309545323fd17572f1d501cd9c8 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:47 +0100 Subject: [PATCH 175/562] input/test_utils: make mockSigner use SigHashType from sign descriptor --- input/test_utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/test_utils.go b/input/test_utils.go index 45c11f116e..b9719438dc 100644 --- a/input/test_utils.go +++ b/input/test_utils.go @@ -67,7 +67,7 @@ func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([] sig, err := txscript.RawTxInWitnessSignature(tx, signDesc.SigHashes, signDesc.InputIndex, signDesc.Output.Value, signDesc.WitnessScript, - txscript.SigHashAll, privKey) + signDesc.HashType, privKey) if err != nil { return nil, err } From bddd3e128cd144f038ac294b37835ad713bd5140 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:47 +0100 Subject: [PATCH 176/562] lnwallet: make second level sigs using sighash single|anyonecanpay --- contractcourt/htlc_timeout_resolver_test.go | 7 ++- input/script_utils.go | 17 +++--- input/script_utils_test.go | 64 +++++++++++++++------ lnwallet/channel.go | 17 ++++-- lnwallet/commitment.go | 11 ++++ 5 files changed, 82 insertions(+), 34 deletions(-) diff --git a/contractcourt/htlc_timeout_resolver_test.go b/contractcourt/htlc_timeout_resolver_test.go index 1e3daa59c9..52324698a9 100644 --- a/contractcourt/htlc_timeout_resolver_test.go +++ b/contractcourt/htlc_timeout_resolver_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/input" @@ -144,7 +145,8 @@ func TestHtlcTimeoutResolver(t *testing.T) { timeout: true, txToBroadcast: func() (*wire.MsgTx, error) { witness, err := input.SenderHtlcSpendTimeout( - nil, signer, fakeSignDesc, sweepTx, + nil, txscript.SigHashAll, signer, + fakeSignDesc, sweepTx, ) if err != nil { return nil, err @@ -163,7 +165,8 @@ func TestHtlcTimeoutResolver(t *testing.T) { timeout: false, txToBroadcast: func() (*wire.MsgTx, error) { witness, err := input.ReceiverHtlcSpendRedeem( - nil, fakePreimageBytes, signer, + nil, txscript.SigHashAll, + fakePreimageBytes, signer, fakeSignDesc, sweepTx, ) if err != nil { diff --git a/input/script_utils.go b/input/script_utils.go index b0c89a15db..d8f80f313e 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -343,8 +343,10 @@ func SenderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor, // HTLC to activate the time locked covenant clause of a soon to be expired // HTLC. This script simply spends the multi-sig output using the // pre-generated HTLC timeout transaction. -func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer, - signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) (wire.TxWitness, error) { +func SenderHtlcSpendTimeout(receiverSig []byte, + receiverSigHash txscript.SigHashType, signer Signer, + signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) ( + wire.TxWitness, error) { sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc) if err != nil { @@ -357,7 +359,7 @@ func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer, // original OP_CHECKMULTISIG. witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack[0] = nil - witnessStack[1] = append(receiverSig, byte(txscript.SigHashAll)) + witnessStack[1] = append(receiverSig, byte(receiverSigHash)) witnessStack[2] = append(sweepSig, byte(signDesc.HashType)) witnessStack[3] = nil witnessStack[4] = signDesc.WitnessScript @@ -506,9 +508,10 @@ func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey, // signed has a relative timelock delay enforced by its sequence number. This // delay give the sender of the HTLC enough time to revoke the output if this // is a breach commitment transaction. -func ReceiverHtlcSpendRedeem(senderSig, paymentPreimage []byte, - signer Signer, signDesc *SignDescriptor, - htlcSuccessTx *wire.MsgTx) (wire.TxWitness, error) { +func ReceiverHtlcSpendRedeem(senderSig []byte, + senderSigHash txscript.SigHashType, paymentPreimage []byte, + signer Signer, signDesc *SignDescriptor, htlcSuccessTx *wire.MsgTx) ( + wire.TxWitness, error) { // First, we'll generate a signature for the HTLC success transaction. // The signDesc should be signing with the public key used as the @@ -524,7 +527,7 @@ func ReceiverHtlcSpendRedeem(senderSig, paymentPreimage []byte, // order to consume the extra pop within OP_CHECKMULTISIG. witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack[0] = nil - witnessStack[1] = append(senderSig, byte(txscript.SigHashAll)) + witnessStack[1] = append(senderSig, byte(senderSigHash)) witnessStack[2] = append(sweepSig, byte(signDesc.HashType)) witnessStack[3] = paymentPreimage witnessStack[4] = signDesc.WitnessScript diff --git a/input/script_utils_test.go b/input/script_utils_test.go index 33b78ee208..be1e2d0fbc 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -227,6 +227,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) { sweepTxSigHashes *txscript.TxSigHashes senderCommitTx, sweepTx *wire.MsgTx bobRecvrSig []byte + bobSigHash txscript.SigHashType ) // genCommitTx generates a commitment tx where the htlc output requires @@ -260,7 +261,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) { } // genSweepTx generates a sweep of the senderCommitTx, and sets the - // sequence if confirmed is true. + // sequence and sighash single|anyonecanspend if confirmed is true. genSweepTx := func(confirmed bool) { prevOut := &wire.OutPoint{ Hash: senderCommitTx.TxHash(), @@ -283,6 +284,11 @@ func TestHTLCSenderSpendValidation(t *testing.T) { sweepTxSigHashes = txscript.NewTxSigHashes(sweepTx) + bobSigHash = txscript.SigHashAll + if confirmed { + bobSigHash = txscript.SigHashSingle | txscript.SigHashAnyOneCanPay + } + // We'll also generate a signature on the sweep transaction above // that will act as Bob's signature to Alice for the second level HTLC // transaction. @@ -293,7 +299,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) { SingleTweak: bobCommitTweak, WitnessScript: htlcWitnessScript, Output: htlcOutput, - HashType: txscript.SigHashAll, + HashType: bobSigHash, SigHashes: sweepTxSigHashes, InputIndex: 0, } @@ -458,8 +464,10 @@ func TestHTLCSenderSpendValidation(t *testing.T) { InputIndex: 0, } - return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner, - signDesc, sweepTx) + return SenderHtlcSpendTimeout( + bobRecvrSig, bobSigHash, aliceSigner, + signDesc, sweepTx, + ) }), true, }, @@ -487,8 +495,10 @@ func TestHTLCSenderSpendValidation(t *testing.T) { InputIndex: 0, } - return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner, - signDesc, sweepTx) + return SenderHtlcSpendTimeout( + bobRecvrSig, bobSigHash, aliceSigner, + signDesc, sweepTx, + ) }), true, }, @@ -517,8 +527,10 @@ func TestHTLCSenderSpendValidation(t *testing.T) { InputIndex: 0, } - return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner, - signDesc, sweepTx) + return SenderHtlcSpendTimeout( + bobRecvrSig, bobSigHash, aliceSigner, + signDesc, sweepTx, + ) }), false, }, @@ -611,6 +623,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { receiverCommitTx, sweepTx *wire.MsgTx sweepTxSigHashes *txscript.TxSigHashes aliceSenderSig []byte + aliceSigHash txscript.SigHashType ) genCommitTx := func(confirmed bool) { @@ -663,6 +676,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { ) sweepTxSigHashes = txscript.NewTxSigHashes(sweepTx) + aliceSigHash = txscript.SigHashAll + if confirmed { + aliceSigHash = txscript.SigHashSingle | txscript.SigHashAnyOneCanPay + } + // We'll also generate a signature on the sweep transaction above // that will act as Alice's signature to Bob for the second level HTLC // transaction. @@ -673,7 +691,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { SingleTweak: aliceCommitTweak, WitnessScript: htlcWitnessScript, Output: htlcOutput, - HashType: txscript.SigHashAll, + HashType: aliceSigHash, SigHashes: sweepTxSigHashes, InputIndex: 0, } @@ -706,9 +724,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { InputIndex: 0, } - return ReceiverHtlcSpendRedeem(aliceSenderSig, + return ReceiverHtlcSpendRedeem( + aliceSenderSig, aliceSigHash, bytes.Repeat([]byte{1}, 45), bobSigner, - signDesc, sweepTx) + signDesc, sweepTx, + ) }), false, @@ -731,9 +751,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { InputIndex: 0, } - return ReceiverHtlcSpendRedeem(aliceSenderSig, - paymentPreimage[:], bobSigner, - signDesc, sweepTx) + return ReceiverHtlcSpendRedeem( + aliceSenderSig, aliceSigHash, + paymentPreimage, bobSigner, + signDesc, sweepTx, + ) }), true, }, @@ -783,9 +805,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { InputIndex: 0, } - return ReceiverHtlcSpendRedeem(aliceSenderSig, + return ReceiverHtlcSpendRedeem( + aliceSenderSig, aliceSigHash, paymentPreimage, bobSigner, - signDesc, sweepTx) + signDesc, sweepTx, + ) }), true, }, @@ -813,9 +837,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { InputIndex: 0, } - return ReceiverHtlcSpendRedeem(aliceSenderSig, - paymentPreimage, bobSigner, - signDesc, sweepTx) + return ReceiverHtlcSpendRedeem( + aliceSenderSig, aliceSigHash, + paymentPreimage, bobSigner, signDesc, + sweepTx, + ) }), false, }, diff --git a/lnwallet/channel.go b/lnwallet/channel.go index d71348a66d..dbb2000a92 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2748,6 +2748,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, txHash := remoteCommitView.txn.TxHash() dustLimit := remoteChanCfg.DustLimit feePerKw := remoteCommitView.feePerKw + sigHashType := HtlcSigHashType(chanType) // With the keys generated, we'll make a slice with enough capacity to // hold potentially all the HTLCs. The actual slice may be a bit @@ -2807,7 +2808,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, Output: &wire.TxOut{ Value: int64(htlc.Amount.ToSatoshis()), }, - HashType: txscript.SigHashAll, + HashType: sigHashType, SigHashes: txscript.NewTxSigHashes(sigJob.Tx), InputIndex: 0, } @@ -2858,7 +2859,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, Output: &wire.TxOut{ Value: int64(htlc.Amount.ToSatoshis()), }, - HashType: txscript.SigHashAll, + HashType: sigHashType, SigHashes: txscript.NewTxSigHashes(sigJob.Tx), InputIndex: 0, } @@ -3811,6 +3812,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment, txHash := localCommitmentView.txn.TxHash() feePerKw := localCommitmentView.feePerKw + sigHashType := HtlcSigHashType(chanType) // With the required state generated, we'll create a slice with large // enough capacity to hold verification jobs for all HTLC's in this @@ -3865,7 +3867,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment, hashCache := txscript.NewTxSigHashes(successTx) sigHash, err := txscript.CalcWitnessSigHash( htlc.ourWitnessScript, hashCache, - txscript.SigHashAll, successTx, 0, + sigHashType, successTx, 0, int64(htlc.Amount.ToSatoshis()), ) if err != nil { @@ -3919,7 +3921,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment, hashCache := txscript.NewTxSigHashes(timeoutTx) sigHash, err := txscript.CalcWitnessSigHash( htlc.ourWitnessScript, hashCache, - txscript.SigHashAll, timeoutTx, 0, + sigHashType, timeoutTx, 0, int64(htlc.Amount.ToSatoshis()), ) if err != nil { @@ -5403,8 +5405,9 @@ func newOutgoingHtlcResolution(signer input.Signer, // With the sign desc created, we can now construct the full witness // for the timeout transaction, and populate it as well. + sigHashType := HtlcSigHashType(chanType) timeoutWitness, err := input.SenderHtlcSpendTimeout( - htlc.Signature, signer, &timeoutSignDesc, timeoutTx, + htlc.Signature, sigHashType, signer, &timeoutSignDesc, timeoutTx, ) if err != nil { return nil, err @@ -5530,8 +5533,10 @@ func newIncomingHtlcResolution(signer input.Signer, // the success transaction. Don't specify the preimage yet. The preimage // will be supplied by the contract resolver, either directly or when it // becomes known. + sigHashType := HtlcSigHashType(chanType) successWitness, err := input.ReceiverHtlcSpendRedeem( - htlc.Signature, nil, signer, &successSignDesc, successTx, + htlc.Signature, sigHashType, nil, signer, &successSignDesc, + successTx, ) if err != nil { return nil, err diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index ce609f0c6e..6b1719eee8 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/channeldb" @@ -224,6 +225,16 @@ func CommitScriptToRemote(chanType channeldb.ChannelType, }, 0, nil } +// HtlcSigHashType returns the sighash type to use for HTLC success and timeout +// transactions given the channel type. +func HtlcSigHashType(chanType channeldb.ChannelType) txscript.SigHashType { + if chanType.HasAnchors() { + return txscript.SigHashSingle | txscript.SigHashAnyOneCanPay + } + + return txscript.SigHashAll +} + // CommitWeight returns the base commitment weight before adding HTLCs. func CommitWeight(chanType channeldb.ChannelType) int64 { // If this commitment has anchors, it will be slightly heavier. From c5d58b4762337b43fddcb11b2e8705e549c9a664 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:47 +0100 Subject: [PATCH 177/562] lnwallet: set 2nd level sequence according to channel type --- lnwallet/commitment.go | 10 ++++++++++ lnwallet/transactions.go | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 6b1719eee8..abe9288e41 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -235,6 +235,16 @@ func HtlcSigHashType(chanType channeldb.ChannelType) txscript.SigHashType { return txscript.SigHashAll } +// HtlcSecondLevelInputSequence dictates the sequence number we must use on the +// input to a second level HTLC transaction. +func HtlcSecondLevelInputSequence(chanType channeldb.ChannelType) uint32 { + if chanType.HasAnchors() { + return 1 + } + + return 0 +} + // CommitWeight returns the base commitment weight before adding HTLCs. func CommitWeight(chanType channeldb.ChannelType) int64 { // If this commitment has anchors, it will be slightly heavier. diff --git a/lnwallet/transactions.go b/lnwallet/transactions.go index c8f14a9670..3c37cd8da7 100644 --- a/lnwallet/transactions.go +++ b/lnwallet/transactions.go @@ -54,10 +54,13 @@ func createHtlcSuccessTx(chanType channeldb.ChannelType, successTx := wire.NewMsgTx(2) // The input to the transaction is the outpoint that creates the - // original HTLC on the sender's commitment transaction. - successTx.AddTxIn(&wire.TxIn{ + // original HTLC on the sender's commitment transaction. Set the + // sequence number based on the channel type. + txin := &wire.TxIn{ PreviousOutPoint: htlcOutput, - }) + Sequence: HtlcSecondLevelInputSequence(chanType), + } + successTx.AddTxIn(txin) // Next, we'll generate the script used as the output for all second // level HTLC which forces a covenant w.r.t what can be done with all @@ -110,10 +113,13 @@ func createHtlcTimeoutTx(chanType channeldb.ChannelType, timeoutTx.LockTime = cltvExpiry // The input to the transaction is the outpoint that creates the - // original HTLC on the sender's commitment transaction. - timeoutTx.AddTxIn(&wire.TxIn{ + // original HTLC on the sender's commitment transaction. Set the + // sequence number based on the channel type. + txin := &wire.TxIn{ PreviousOutPoint: htlcOutput, - }) + Sequence: HtlcSecondLevelInputSequence(chanType), + } + timeoutTx.AddTxIn(txin) // Next, we'll generate the script used as the output for all second // level HTLC which forces a covenant w.r.t what can be done with all From 92af2342daaf0cb4220c74794d05cfcf97f20c09 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:47 +0100 Subject: [PATCH 178/562] lnwallet+nursery+input: set sequence=1 for direct HTLC spends --- contractcourt/htlc_success_resolver.go | 1 + input/input.go | 13 +++++++------ lnwallet/channel.go | 9 ++++++--- utxonursery.go | 10 ++++++---- utxonursery_test.go | 3 ++- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/contractcourt/htlc_success_resolver.go b/contractcourt/htlc_success_resolver.go index c13c52e87e..38fa7fd051 100644 --- a/contractcourt/htlc_success_resolver.go +++ b/contractcourt/htlc_success_resolver.go @@ -118,6 +118,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) { &h.htlcResolution.SweepSignDesc, h.htlcResolution.Preimage[:], h.broadcastHeight, + h.htlcResolution.CsvDelay, ) // With the input created, we can now generate the full diff --git a/input/input.go b/input/input.go index 7f5593ec53..38a1651e52 100644 --- a/input/input.go +++ b/input/input.go @@ -156,15 +156,16 @@ type HtlcSucceedInput struct { // MakeHtlcSucceedInput assembles a new redeem input that can be used to // construct a sweep transaction. func MakeHtlcSucceedInput(outpoint *wire.OutPoint, - signDescriptor *SignDescriptor, - preimage []byte, heightHint uint32) HtlcSucceedInput { + signDescriptor *SignDescriptor, preimage []byte, heightHint, + blocksToMaturity uint32) HtlcSucceedInput { return HtlcSucceedInput{ inputKit: inputKit{ - outpoint: *outpoint, - witnessType: HtlcAcceptedRemoteSuccess, - signDesc: *signDescriptor, - heightHint: heightHint, + outpoint: *outpoint, + witnessType: HtlcAcceptedRemoteSuccess, + signDesc: *signDescriptor, + heightHint: heightHint, + blockToMaturity: blocksToMaturity, }, preimage: preimage, } diff --git a/lnwallet/channel.go b/lnwallet/channel.go index dbb2000a92..a348254da5 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -5253,7 +5253,8 @@ type IncomingHtlcResolution struct { // pass after the SignedSuccessTx is confirmed in the chain before the // output can be swept. // - // NOTE: If SignedSuccessTx is nil, then this field isn't needed. + // NOTE: If SignedTimeoutTx is nil, then this field denotes the CSV + // delay needed to spend from the commitment transaction. CsvDelay uint32 // ClaimOutpoint is the final outpoint that needs to be spent in order @@ -5293,7 +5294,8 @@ type OutgoingHtlcResolution struct { // pass after the SignedTimeoutTx is confirmed in the chain before the // output can be swept. // - // NOTE: If SignedTimeoutTx is nil, then this field isn't needed. + // NOTE: If SignedTimeoutTx is nil, then this field denotes the CSV + // delay needed to spend from the commitment transaction. CsvDelay uint32 // ClaimOutpoint is the final outpoint that needs to be spent in order @@ -5366,6 +5368,7 @@ func newOutgoingHtlcResolution(signer input.Signer, }, HashType: txscript.SigHashAll, }, + CsvDelay: HtlcSecondLevelInputSequence(chanType), }, nil } @@ -5487,7 +5490,6 @@ func newIncomingHtlcResolution(signer input.Signer, // SignDescriptor needed to sweep the output. return &IncomingHtlcResolution{ ClaimOutpoint: op, - CsvDelay: csvDelay, SweepSignDesc: input.SignDescriptor{ KeyDesc: localChanCfg.HtlcBasePoint, SingleTweak: keyRing.LocalHtlcKeyTweak, @@ -5498,6 +5500,7 @@ func newIncomingHtlcResolution(signer input.Signer, }, HashType: txscript.SigHashAll, }, + CsvDelay: HtlcSecondLevelInputSequence(chanType), }, nil } diff --git a/utxonursery.go b/utxonursery.go index d05a04ed50..abff354782 100644 --- a/utxonursery.go +++ b/utxonursery.go @@ -397,10 +397,11 @@ func (u *utxoNursery) IncubateOutputs(chanPoint wire.OutPoint, // Otherwise, this is actually a kid output as we can sweep it // once the commitment transaction confirms, and the absolute - // CLTV lock has expired. We set the CSV delay to zero to - // indicate this is actually a CLTV output. + // CLTV lock has expired. We set the CSV delay what the + // resolution encodes, since the sequence number must be set + // accordingly. htlcOutput := makeKidOutput( - &htlcRes.ClaimOutpoint, &chanPoint, 0, + &htlcRes.ClaimOutpoint, &chanPoint, htlcRes.CsvDelay, input.HtlcOfferedRemoteTimeout, &htlcRes.SweepSignDesc, htlcRes.Expiry, ) @@ -1271,7 +1272,8 @@ type kidOutput struct { // output. // // NOTE: This will be set for: commitment outputs, and incoming HTLC's. - // Otherwise, this will be zero. + // Otherwise, this will be zero. It will also be non-zero for + // commitment types which requires confirmed spends. blocksToMaturity uint32 // absoluteMaturity is the absolute height that this output will be diff --git a/utxonursery_test.go b/utxonursery_test.go index 579bddcfef..cbc9126970 100644 --- a/utxonursery_test.go +++ b/utxonursery_test.go @@ -603,7 +603,6 @@ func createOutgoingRes(onLocalCommitment bool) *lnwallet.OutgoingHtlcResolution Value: 10000, }, }, - CsvDelay: 2, } if onLocalCommitment { @@ -620,8 +619,10 @@ func createOutgoingRes(onLocalCommitment bool) *lnwallet.OutgoingHtlcResolution } outgoingRes.SignedTimeoutTx = timeoutTx + outgoingRes.CsvDelay = 2 } else { outgoingRes.ClaimOutpoint = htlcOp + outgoingRes.CsvDelay = 0 } return &outgoingRes From ad8e9f30c6a5c376cb049f2b5f849d91f6f38e4d Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:47 +0100 Subject: [PATCH 179/562] lnwallet+breacharbiter: record local csv delay --- breacharbiter.go | 14 ++++++++++++++ lnwallet/channel.go | 17 +++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/breacharbiter.go b/breacharbiter.go index 3706f3bd49..eeee4f8ec6 100644 --- a/breacharbiter.go +++ b/breacharbiter.go @@ -896,6 +896,13 @@ func (bo *breachedOutput) CraftInputScript(signer input.Signer, txn *wire.MsgTx, // must be built on top of the confirmation height before the output can be // spent. func (bo *breachedOutput) BlocksToMaturity() uint32 { + // If the output is a to_remote output we can claim, and it's of the + // confirmed type, we must wait one block before claiming it. + if bo.witnessType == input.CommitmentToRemoteConfirmed { + return 1 + } + + // All other breached outputs have no CSV delay. return 0 } @@ -952,6 +959,12 @@ func newRetributionInfo(chanPoint *wire.OutPoint, witnessType = input.CommitSpendNoDelayTweakless } + // If the local delay is non-zero, it means this output is of + // the confirmed to_remote type. + if breachInfo.LocalDelay != 0 { + witnessType = input.CommitmentToRemoteConfirmed + } + localOutput := makeBreachedOutput( &breachInfo.LocalOutpoint, witnessType, @@ -1117,6 +1130,7 @@ func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64, for _, input := range inputs { txn.AddTxIn(&wire.TxIn{ PreviousOutPoint: *input.OutPoint(), + Sequence: input.BlocksToMaturity(), }) } diff --git a/lnwallet/channel.go b/lnwallet/channel.go index a348254da5..6b072aded4 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2013,6 +2013,10 @@ type BreachRetribution struct { // party) within the breach transaction. LocalOutpoint wire.OutPoint + // LocalDelay is the CSV delay for the to_remote script on the breached + // commitment. + LocalDelay uint32 + // RemoteOutputSignDesc is a SignDescriptor which is capable of // generating the signature required to claim the funds as described // within the revocation clause of the remote party's commitment @@ -2026,6 +2030,10 @@ type BreachRetribution struct { // party within the breach transaction. RemoteOutpoint wire.OutPoint + // RemoteDelay specifies the CSV delay applied to to-local scripts on + // the breaching commitment transaction. + RemoteDelay uint32 + // HtlcRetributions is a slice of HTLC retributions for each output // active HTLC output within the breached commitment transaction. HtlcRetributions []HtlcRetribution @@ -2034,10 +2042,6 @@ type BreachRetribution struct { // breaching commitment transaction. This allows downstream clients to // have access to the public keys used in the scripts. KeyRing *CommitmentKeyRing - - // RemoteDelay specifies the CSV delay applied to to-local scripts on - // the breaching commitment transaction. - RemoteDelay uint32 } // NewBreachRetribution creates a new fully populated BreachRetribution for the @@ -2090,7 +2094,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, // Since it is the remote breach we are reconstructing, the output going // to us will be a to-remote script with our local params. - ourScript, _, err := CommitScriptToRemote( + ourScript, ourDelay, err := CommitScriptToRemote( chanState.ChanType, keyRing.ToRemoteKey, ) if err != nil { @@ -2226,11 +2230,12 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, PendingHTLCs: revokedSnapshot.Htlcs, LocalOutpoint: ourOutpoint, LocalOutputSignDesc: ourSignDesc, + LocalDelay: ourDelay, RemoteOutpoint: theirOutpoint, RemoteOutputSignDesc: theirSignDesc, + RemoteDelay: theirDelay, HtlcRetributions: htlcRetributions, KeyRing: keyRing, - RemoteDelay: theirDelay, }, nil } From 8741b9372374f5a36867a7f327452961ee830d75 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:48 +0100 Subject: [PATCH 180/562] lnwallet/reservation: add non-initiator balance check If we are the initiator, we check that our starting balance after subtracting fees are not less than two times the default dust limit. This commit adds a similar check for the non-initiator case, checking that the remote party has a starting balance of reasonable size. --- lnwallet/reservation.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index b7b63da557..c371f6f073 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -213,6 +213,16 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, ) } + // Similarly we ensure their balance is reasonable if we are not the + // initiator. + if !initiator && theirBalance.ToSatoshis() <= 2*DefaultDustLimit() { + return nil, ErrFunderBalanceDust( + int64(commitFee), + int64(theirBalance.ToSatoshis()), + int64(2*DefaultDustLimit()), + ) + } + // Next we'll set the channel type based on what we can ascertain about // the balances/push amount within the channel. var chanType channeldb.ChannelType From f95a82bf5f76151af669ca594ca59e24304fd563 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:48 +0100 Subject: [PATCH 181/562] lnwallet+funding: create CommitmentType enum --- fundingmanager.go | 48 ++++++++++++++++++++++++-------------- lnwallet/interface_test.go | 22 ++++++++++------- lnwallet/reservation.go | 30 ++++++++++++++++++++++-- lnwallet/wallet.go | 8 +++---- 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index 7913a11f66..bf4ed31b04 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -1106,6 +1106,28 @@ func (f *fundingManager) processFundingOpen(msg *lnwire.OpenChannel, } } +// commitmentType returns the commitment type to use for the channel, based on +// the features the two peers have available. +func commitmentType(localFeatures, + remoteFeatures *lnwire.FeatureVector) lnwallet.CommitmentType { + + localTweakless := localFeatures.HasFeature( + lnwire.StaticRemoteKeyOptional, + ) + remoteTweakless := remoteFeatures.HasFeature( + lnwire.StaticRemoteKeyOptional, + ) + + // If both nodes are signaling the proper feature bit for tweakless + // copmmitments, we'll use that. + if localTweakless && remoteTweakless { + return lnwallet.CommitmentTypeTweakless + } + + // Otherwise we'll fall back to the legacy type. + return lnwallet.CommitmentTypeLegacy +} + // handleFundingOpen creates an initial 'ChannelReservation' within the wallet, // then responds to the source peer with an accept channel message progressing // the funding workflow. @@ -1228,13 +1250,9 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { // negotiated the new tweakless commitment format. This is only the // case if *both* us and the remote peer are signaling the proper // feature bit. - localTweakless := fmsg.peer.LocalFeatures().HasFeature( - lnwire.StaticRemoteKeyOptional, - ) - remoteTweakless := fmsg.peer.RemoteFeatures().HasFeature( - lnwire.StaticRemoteKeyOptional, + commitType := commitmentType( + fmsg.peer.LocalFeatures(), fmsg.peer.RemoteFeatures(), ) - tweaklessCommitment := localTweakless && remoteTweakless chainHash := chainhash.Hash(msg.ChainHash) req := &lnwallet.InitFundingReserveMsg{ ChainHash: &chainHash, @@ -1248,7 +1266,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { PushMSat: msg.PushAmount, Flags: msg.ChannelFlags, MinConfs: 1, - Tweakless: tweaklessCommitment, + CommitType: commitType, } reservation, err := f.cfg.Wallet.InitChannelReservation(req) @@ -1307,9 +1325,9 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { reservation.SetOurUpfrontShutdown(shutdown) fndgLog.Infof("Requiring %v confirmations for pendingChan(%x): "+ - "amt=%v, push_amt=%v, tweakless=%v, upfrontShutdown=%x", numConfsReq, + "amt=%v, push_amt=%v, committype=%v, upfrontShutdown=%x", numConfsReq, fmsg.msg.PendingChannelID, amt, msg.PushAmount, - tweaklessCommitment, msg.UpfrontShutdownScript) + commitType, msg.UpfrontShutdownScript) // Generate our required constraints for the remote party. remoteCsvDelay := f.cfg.RequiredRemoteDelay(amt) @@ -2904,13 +2922,9 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { // negotiated the new tweakless commitment format. This is only the // case if *both* us and the remote peer are signaling the proper // feature bit. - localTweakless := msg.peer.LocalFeatures().HasFeature( - lnwire.StaticRemoteKeyOptional, - ) - remoteTweakless := msg.peer.RemoteFeatures().HasFeature( - lnwire.StaticRemoteKeyOptional, + commitType := commitmentType( + msg.peer.LocalFeatures(), msg.peer.RemoteFeatures(), ) - tweaklessCommitment := localTweakless && remoteTweakless req := &lnwallet.InitFundingReserveMsg{ ChainHash: &msg.chainHash, PendingChanID: chanID, @@ -2924,7 +2938,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { PushMSat: msg.pushAmt, Flags: channelFlags, MinConfs: msg.minConfs, - Tweakless: tweaklessCommitment, + CommitType: commitType, ChanFunder: msg.chanFunder, } @@ -3012,7 +3026,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(capacity) fndgLog.Infof("Starting funding workflow with %v for pending_id(%x), "+ - "tweakless=%v", msg.peer.Address(), chanID, tweaklessCommitment) + "committype=%v", msg.peer.Address(), chanID, commitType) fundingOpen := lnwire.OpenChannel{ ChainHash: *f.cfg.Wallet.Cfg.NetParams.GenesisHash, diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index db907d5a4e..6ebb7ff9a6 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -700,7 +700,8 @@ func testCancelNonExistentReservation(miner *rpctest.Harness, // Create our own reservation, give it some ID. res, err := lnwallet.NewChannelReservation( 10000, 10000, feePerKw, alice, 22, 10, &testHdSeed, - lnwire.FFAnnounceChannel, true, nil, [32]byte{}, + lnwire.FFAnnounceChannel, lnwallet.CommitmentTypeTweakless, + nil, [32]byte{}, ) if err != nil { t.Fatalf("unable to create res: %v", err) @@ -738,7 +739,7 @@ func testReservationInitiatorBalanceBelowDustCancel(miner *rpctest.Harness, FundingFeePerKw: 1000, PushMSat: 0, Flags: lnwire.FFAnnounceChannel, - Tweakless: true, + CommitType: lnwallet.CommitmentTypeTweakless, } _, err = alice.InitChannelReservation(req) switch { @@ -793,7 +794,8 @@ func assertContributionInitPopulated(t *testing.T, c *lnwallet.ChannelContributi } func testSingleFunderReservationWorkflow(miner *rpctest.Harness, - alice, bob *lnwallet.LightningWallet, t *testing.T, tweakless bool, + alice, bob *lnwallet.LightningWallet, t *testing.T, + commitType lnwallet.CommitmentType, aliceChanFunder chanfunding.Assembler, fetchFundingTx func() *wire.MsgTx, pendingChanID [32]byte) { @@ -823,7 +825,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, FundingFeePerKw: feePerKw, PushMSat: pushAmt, Flags: lnwire.FFAnnounceChannel, - Tweakless: tweakless, + CommitType: commitType, ChanFunder: aliceChanFunder, } aliceChanReservation, err := alice.InitChannelReservation(aliceReq) @@ -874,7 +876,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, FundingFeePerKw: feePerKw, PushMSat: pushAmt, Flags: lnwire.FFAnnounceChannel, - Tweakless: tweakless, + CommitType: commitType, } bobChanReservation, err := bob.InitChannelReservation(bobReq) if err != nil { @@ -2543,7 +2545,8 @@ var walletTests = []walletTestCase{ bob *lnwallet.LightningWallet, t *testing.T) { testSingleFunderReservationWorkflow( - miner, alice, bob, t, false, nil, nil, + miner, alice, bob, t, + lnwallet.CommitmentTypeLegacy, nil, nil, [32]byte{}, ) }, @@ -2554,7 +2557,8 @@ var walletTests = []walletTestCase{ bob *lnwallet.LightningWallet, t *testing.T) { testSingleFunderReservationWorkflow( - miner, alice, bob, t, true, nil, nil, + miner, alice, bob, t, + lnwallet.CommitmentTypeTweakless, nil, nil, [32]byte{}, ) }, @@ -2809,8 +2813,8 @@ func testSingleFunderExternalFundingTx(miner *rpctest.Harness, // pending channel ID generated above to allow Alice and Bob to track // the funding flow externally. testSingleFunderReservationWorkflow( - miner, alice, bob, t, true, aliceExternalFunder, - func() *wire.MsgTx { + miner, alice, bob, t, lnwallet.CommitmentTypeTweakless, + aliceExternalFunder, func() *wire.MsgTx { return fundingTx }, pendingChanID, ) diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index c371f6f073..ba4c631ef6 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -15,6 +15,32 @@ import ( "github.com/lightningnetwork/lnd/lnwire" ) +// CommitmentType is an enum indicating the commitment type we should use for +// the channel we are opening. +type CommitmentType int + +const ( + // CommitmentTypeLegacy is the legacy commitment format with a tweaked + // to_remote key. + CommitmentTypeLegacy = iota + + // CommitmentTypeTweakless is a newer commitment format where the + // to_remote key is static. + CommitmentTypeTweakless +) + +// String returns the name of the CommitmentType. +func (c CommitmentType) String() string { + switch c { + case CommitmentTypeLegacy: + return "legacy" + case CommitmentTypeTweakless: + return "tweakless" + default: + return "invalid" + } +} + // ChannelContribution is the primary constituent of the funding workflow // within lnwallet. Each side first exchanges their respective contributions // along with channel specific parameters like the min fee/KB. Once @@ -136,7 +162,7 @@ type ChannelReservation struct { func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, commitFeePerKw chainfee.SatPerKWeight, wallet *LightningWallet, id uint64, pushMSat lnwire.MilliSatoshi, chainHash *chainhash.Hash, - flags lnwire.FundingFlag, tweaklessCommit bool, + flags lnwire.FundingFlag, commitType CommitmentType, fundingAssembler chanfunding.Assembler, pendingChanID [32]byte) (*ChannelReservation, error) { @@ -231,7 +257,7 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // non-zero push amt (there's no pushing for dual funder), then this is // a single-funder channel. if ourBalance == 0 || theirBalance == 0 || pushMSat != 0 { - if tweaklessCommit { + if commitType == CommitmentTypeTweakless { chanType |= channeldb.SingleFunderTweaklessBit } else { chanType |= channeldb.SingleFunderBit diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 5649b65242..73eaf2178a 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -98,9 +98,9 @@ type InitFundingReserveMsg struct { // output selected to fund the channel should satisfy. MinConfs int32 - // Tweakless indicates if the channel should use the new tweakless - // commitment format or not. - Tweakless bool + // CommitType indicates what type of commitment type the channel should + // be using, like tweakless or anchors. + CommitType CommitmentType // ChanFunder is an optional channel funder that allows the caller to // control exactly how the channel funding is carried out. If not @@ -568,7 +568,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg reservation, err := NewChannelReservation( capacity, localFundingAmt, req.CommitFeePerKw, l, id, req.PushMSat, l.Cfg.NetParams.GenesisHash, req.Flags, - req.Tweakless, req.ChanFunder, req.PendingChanID, + req.CommitType, req.ChanFunder, req.PendingChanID, ) if err != nil { if fundingIntent != nil { From 51c5352ae4b0b4e4d1209f2c4812e61f6d66bb92 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:48 +0100 Subject: [PATCH 182/562] itest: make commit type enum To prepare for adding more commit types to test for basic channel funding, we make the commit type an enum that gets its own set of subtests. --- lntest/itest/lnd_test.go | 66 ++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 665426a30f..fe30590368 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -953,6 +953,43 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) { restoreCheckBalance(6*btcutil.SatoshiPerBitcoin, 6, 20, nil) } +// commitType is a simple enum used to run though the basic funding flow with +// different commitment formats. +type commitType byte + +const ( + // commitTypeLegacy is the old school commitment type. + commitTypeLegacy = iota + + // commiTypeTweakless is the commitment type where the remote key is + // static (non-tweaked). + commitTypeTweakless +) + +// String returns that name of the commitment type. +func (c commitType) String() string { + switch c { + case commitTypeLegacy: + return "legacy" + case commitTypeTweakless: + return "tweakless" + default: + return "invalid" + } +} + +// Args returns the command line flag to supply to enable this commitment type. +func (c commitType) Args() []string { + switch c { + case commitTypeLegacy: + return []string{"--legacyprotocol.committweak"} + case commitTypeTweakless: + return []string{} + } + + return nil +} + // basicChannelFundingTest is a sub-test of the main testBasicChannelFunding // test. Given two nodes: Alice and Bob, it'll assert proper channel creation, // then return a function closure that should be called to assert proper @@ -1049,19 +1086,23 @@ func testBasicChannelFunding(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() + // Run through the test with combinations of all the different + // commitment types. + allTypes := []commitType{ + commitTypeLegacy, + commitTypeTweakless, + } + test: // We'll test all possible combinations of the feature bit presence // that both nodes can signal for this new channel type. We'll make a // new Carol+Dave for each test instance as well. - for _, carolTweakless := range []bool{true, false} { - for _, daveTweakless := range []bool{true, false} { + for _, carolCommitType := range allTypes { + for _, daveCommitType := range allTypes { // Based on the current tweak variable for Carol, we'll // preferentially signal the legacy commitment format. // We do the same for Dave shortly below. - var carolArgs []string - if !carolTweakless { - carolArgs = []string{"--legacyprotocol.committweak"} - } + carolArgs := carolCommitType.Args() carol, err := net.NewNode("Carol", carolArgs) if err != nil { t.Fatalf("unable to create new node: %v", err) @@ -1075,10 +1116,7 @@ test: t.Fatalf("unable to send coins to carol: %v", err) } - var daveArgs []string - if !daveTweakless { - daveArgs = []string{"--legacyprotocol.committweak"} - } + daveArgs := daveCommitType.Args() dave, err := net.NewNode("Dave", daveArgs) if err != nil { t.Fatalf("unable to create new node: %v", err) @@ -1093,8 +1131,8 @@ test: t.Fatalf("unable to connect peers: %v", err) } - testName := fmt.Sprintf("carol_tweak=%v,dave_tweak=%v", - carolTweakless, daveTweakless) + testName := fmt.Sprintf("carol_commit=%v,dave_commit=%v", + carolCommitType, daveCommitType) ht := t success := t.t.Run(testName, func(t *testing.T) { @@ -1105,6 +1143,10 @@ test: t.Fatalf("failed funding flow: %v", err) } + carolTweakless := carolCommitType == commitTypeTweakless + + daveTweakless := daveCommitType == commitTypeTweakless + tweaklessSignalled := carolTweakless && daveTweakless tweaklessChans := (carolChannel.StaticRemoteKey && daveChannel.StaticRemoteKey) From 44756b5811059d65076fbe2eb4cdea8596f73375 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:48 +0100 Subject: [PATCH 183/562] cfg: rename legacyprotocol to protocol Since we are also going to use it for experimental new features. --- config.go | 2 +- lncfg/protocol_legacy_off.go | 14 +++++++------- lncfg/protocol_legacy_on.go | 24 ++++++++++++------------ lntest/itest/lnd_test.go | 4 ++-- server.go | 8 ++++---- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/config.go b/config.go index fd5ee8b62d..5308b58c83 100644 --- a/config.go +++ b/config.go @@ -345,7 +345,7 @@ type config struct { Watchtower *lncfg.Watchtower `group:"watchtower" namespace:"watchtower"` - LegacyProtocol *lncfg.LegacyProtocol `group:"legacyprotocol" namespace:"legacyprotocol"` + ProtocolOptions *lncfg.ProtocolOptions `group:"protocol" namespace:"protocol"` AllowCircularRoute bool `long:"allow-circular-route" description:"If true, our node will allow htlc forwards that arrive and depart on the same channel."` } diff --git a/lncfg/protocol_legacy_off.go b/lncfg/protocol_legacy_off.go index 7e1e47d323..0011bb7fa9 100644 --- a/lncfg/protocol_legacy_off.go +++ b/lncfg/protocol_legacy_off.go @@ -2,21 +2,21 @@ package lncfg -// LegacyProtocol is a struct that we use to be able to test backwards +// ProtocolOptions is a struct that we use to be able to test backwards // compatibility of protocol additions, while defaulting to the latest within -// lnd. -type LegacyProtocol struct { +// lnd, or to enable experimental protocol changes. +type ProtocolOptions struct { } // LegacyOnion returns true if the old legacy onion format should be used when // we're an intermediate or final hop. This controls if we set the // TLVOnionPayloadOptional bit or not. -func (l *LegacyProtocol) LegacyOnion() bool { +func (l *ProtocolOptions) LegacyOnion() bool { return false } -// LegacyOnion returns true if the old commitment format should be used for new -// funded channels. -func (l *LegacyProtocol) LegacyCommitment() bool { +// LegacyCommitment returns true if the old commitment format should be used +// for new funded channels. +func (l *ProtocolOptions) LegacyCommitment() bool { return false } diff --git a/lncfg/protocol_legacy_on.go b/lncfg/protocol_legacy_on.go index d384adc8a9..e091c6a6d2 100644 --- a/lncfg/protocol_legacy_on.go +++ b/lncfg/protocol_legacy_on.go @@ -2,14 +2,14 @@ package lncfg -// LegacyProtocol is a struct that we use to be able to test backwards +// ProtocolOptions is a struct that we use to be able to test backwards // compatibility of protocol additions, while defaulting to the latest within -// lnd. -type LegacyProtocol struct { - // Onion if set to true, then we won't signal TLVOnionPayloadOptional. - // As a result, nodes that include us in the route won't use the new - // modern onion framing. - Onion bool `long:"onion" description:"force node to not advertise the new modern TLV onion format"` +// lnd, or to enable experimental protocol changes. +type ProtocolOptions struct { + // LegacyOnionFormat if set to true, then we won't signal + // TLVOnionPayloadOptional. As a result, nodes that include us in the + // route won't use the new modern onion framing. + LegacyOnionFormat bool `long:"legacyonion" description:"force node to not advertise the new modern TLV onion format"` // CommitmentTweak guards if we should use the old legacy commitment // protocol, or the newer variant that doesn't have a tweak for the @@ -21,12 +21,12 @@ type LegacyProtocol struct { // LegacyOnion returns true if the old legacy onion format should be used when // we're an intermediate or final hop. This controls if we set the // TLVOnionPayloadOptional bit or not. -func (l *LegacyProtocol) LegacyOnion() bool { - return l.Onion +func (l *ProtocolOptions) LegacyOnion() bool { + return l.LegacyOnionFormat } -// LegacyOnion returns true if the old commitment format should be used for new -// funded channels. -func (l *LegacyProtocol) LegacyCommitment() bool { +// LegacyCommitment returns true if the old commitment format should be used +// for new funded channels. +func (l *ProtocolOptions) LegacyCommitment() bool { return l.CommitmentTweak } diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index fe30590368..93358d1026 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -982,7 +982,7 @@ func (c commitType) String() string { func (c commitType) Args() []string { switch c { case commitTypeLegacy: - return []string{"--legacyprotocol.committweak"} + return []string{"--protocol.committweak"} case commitTypeTweakless: return []string{} } @@ -4247,7 +4247,7 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { // // First, we'll create Dave and establish a channel to Alice. Dave will // be running an older node that requires the legacy onion payload. - daveArgs := []string{"--legacyprotocol.onion"} + daveArgs := []string{"--protocol.legacyonion"} dave, err := net.NewNode("Dave", daveArgs) if err != nil { t.Fatalf("unable to create new nodes: %v", err) diff --git a/server.go b/server.go index bde65671ad..a4bff136cf 100644 --- a/server.go +++ b/server.go @@ -336,13 +336,13 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, // Only if we're not being forced to use the legacy onion format, will // we signal our knowledge of the new TLV onion format. - if !cfg.LegacyProtocol.LegacyOnion() { + if !cfg.ProtocolOptions.LegacyOnion() { globalFeatures.Set(lnwire.TLVOnionPayloadOptional) } // Similarly, we default to the new modern commitment format unless the // legacy commitment config is set to true. - if !cfg.LegacyProtocol.LegacyCommitment() { + if !cfg.ProtocolOptions.LegacyCommitment() { globalFeatures.Set(lnwire.StaticRemoteKeyOptional) } @@ -375,8 +375,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, ) featureMgr, err := feature.NewManager(feature.Config{ - NoTLVOnion: cfg.LegacyProtocol.LegacyOnion(), - NoStaticRemoteKey: cfg.LegacyProtocol.LegacyCommitment(), + NoTLVOnion: cfg.ProtocolOptions.LegacyOnion(), + NoStaticRemoteKey: cfg.ProtocolOptions.LegacyCommitment(), }) if err != nil { return nil, err From 21126ab0f301cf6252c0608545e49c325ce8dded Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:48 +0100 Subject: [PATCH 184/562] multi: optionally enable and signal anchor support Defaults to disabled. --- feature/default_sets.go | 4 ++++ feature/deps.go | 3 +++ feature/manager.go | 7 +++++++ lncfg/protocol_legacy_off.go | 12 +++++++++--- lncfg/protocol_legacy_on.go | 16 +++++++++++++--- lnwire/features.go | 12 ++++++++++++ server.go | 16 ++++++++++++---- 7 files changed, 60 insertions(+), 10 deletions(-) diff --git a/feature/default_sets.go b/feature/default_sets.go index 32807654ed..8054894e72 100644 --- a/feature/default_sets.go +++ b/feature/default_sets.go @@ -43,4 +43,8 @@ var defaultSetDesc = setDesc{ SetNodeAnn: {}, // N SetInvoice: {}, // 9 }, + lnwire.AnchorsOptional: { + SetInit: {}, // I + SetNodeAnn: {}, // N + }, } diff --git a/feature/deps.go b/feature/deps.go index 343f3f6043..c2b8f17569 100644 --- a/feature/deps.go +++ b/feature/deps.go @@ -55,6 +55,9 @@ var deps = depDesc{ lnwire.MPPOptional: { lnwire.PaymentAddrOptional: {}, }, + lnwire.AnchorsOptional: { + lnwire.StaticRemoteKeyOptional: {}, + }, } // ValidateDeps asserts that a feature vector sets all features and their diff --git a/feature/manager.go b/feature/manager.go index 01c82123ab..159540c24b 100644 --- a/feature/manager.go +++ b/feature/manager.go @@ -17,6 +17,9 @@ type Config struct { // NoStaticRemoteKey unsets any optional or required StaticRemoteKey // bits from all feature sets. NoStaticRemoteKey bool + + // NoAnchors unsets any bits signaling support for anchor outputs. + NoAnchors bool } // Manager is responsible for generating feature vectors for different requested @@ -76,6 +79,10 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) { raw.Unset(lnwire.StaticRemoteKeyOptional) raw.Unset(lnwire.StaticRemoteKeyRequired) } + if cfg.NoAnchors { + raw.Unset(lnwire.AnchorsOptional) + raw.Unset(lnwire.AnchorsRequired) + } // Ensure that all of our feature sets properly set any // dependent features. diff --git a/lncfg/protocol_legacy_off.go b/lncfg/protocol_legacy_off.go index 0011bb7fa9..bd589c2451 100644 --- a/lncfg/protocol_legacy_off.go +++ b/lncfg/protocol_legacy_off.go @@ -15,8 +15,14 @@ func (l *ProtocolOptions) LegacyOnion() bool { return false } -// LegacyCommitment returns true if the old commitment format should be used -// for new funded channels. -func (l *ProtocolOptions) LegacyCommitment() bool { +// NoStaticRemoteKey returns true if the old commitment format with a tweaked +// remote key should be used for new funded channels. +func (l *ProtocolOptions) NoStaticRemoteKey() bool { + return false +} + +// AnchorCommitments returns true if support for the the anchor commitment type +// should be signaled. +func (l *ProtocolOptions) AnchorCommitments() bool { return false } diff --git a/lncfg/protocol_legacy_on.go b/lncfg/protocol_legacy_on.go index e091c6a6d2..9be0d1d68d 100644 --- a/lncfg/protocol_legacy_on.go +++ b/lncfg/protocol_legacy_on.go @@ -16,6 +16,10 @@ type ProtocolOptions struct { // remote party's output in the commitment. If set to true, then we // won't signal StaticRemoteKeyOptional. CommitmentTweak bool `long:"committweak" description:"force node to not advertise the new commitment format"` + + // Anchors should be set if we want to support opening or accepting + // channels having the anchor commitment type. + Anchors bool `long:"anchors" description:"EXPERIMENTAL: enable experimental support for anchor commitments. Won't work with watchtowers or static channel backups"` } // LegacyOnion returns true if the old legacy onion format should be used when @@ -25,8 +29,14 @@ func (l *ProtocolOptions) LegacyOnion() bool { return l.LegacyOnionFormat } -// LegacyCommitment returns true if the old commitment format should be used -// for new funded channels. -func (l *ProtocolOptions) LegacyCommitment() bool { +// NoStaticRemoteKey returns true if the old commitment format with a tweaked +// remote key should be used for new funded channels. +func (l *ProtocolOptions) NoStaticRemoteKey() bool { return l.CommitmentTweak } + +// AnchorCommitments returns true if support for the the anchor commitment type +// should be signaled. +func (l *ProtocolOptions) AnchorCommitments() bool { + return l.Anchors +} diff --git a/lnwire/features.go b/lnwire/features.go index db170f6df0..4e5899c22c 100644 --- a/lnwire/features.go +++ b/lnwire/features.go @@ -101,6 +101,16 @@ const ( // HTLC. MPPOptional FeatureBit = 17 + // AnchorsRequired is a required feature bit that signals that the node + // requires channels to be made using commitments having anchor + // outputs. + AnchorsRequired FeatureBit = 1336 + + // AnchorsRequired is an optional feature bit that signals that the + // node supports channels to be made using commitments having anchor + // outputs. + AnchorsOptional FeatureBit = 1337 + // maxAllowedSize is a maximum allowed size of feature vector. // // NOTE: Within the protocol, the maximum allowed message size is 65535 @@ -138,6 +148,8 @@ var Features = map[FeatureBit]string{ PaymentAddrRequired: "payment-addr", MPPOptional: "multi-path-payments", MPPRequired: "multi-path-payments", + AnchorsRequired: "anchor-commitments", + AnchorsOptional: "anchor-commitments", } // RawFeatureVector represents a set of feature bits as defined in BOLT-09. A diff --git a/server.go b/server.go index a4bff136cf..103c9aad82 100644 --- a/server.go +++ b/server.go @@ -340,12 +340,19 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, globalFeatures.Set(lnwire.TLVOnionPayloadOptional) } - // Similarly, we default to the new modern commitment format unless the - // legacy commitment config is set to true. - if !cfg.ProtocolOptions.LegacyCommitment() { + // Similarly, we default to supporting the new modern commitment format + // where the remote key is static unless the protocol config is set to + // keep using the older format. + if !cfg.ProtocolOptions.NoStaticRemoteKey() { globalFeatures.Set(lnwire.StaticRemoteKeyOptional) } + // We only signal that we support the experimental anchor commitments + // if explicitly enabled in the config. + if cfg.ProtocolOptions.AnchorCommitments() { + globalFeatures.Set(lnwire.AnchorsOptional) + } + var serializedPubKey [33]byte copy(serializedPubKey[:], privKey.PubKey().SerializeCompressed()) @@ -376,7 +383,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, featureMgr, err := feature.NewManager(feature.Config{ NoTLVOnion: cfg.ProtocolOptions.LegacyOnion(), - NoStaticRemoteKey: cfg.ProtocolOptions.LegacyCommitment(), + NoStaticRemoteKey: cfg.ProtocolOptions.NoStaticRemoteKey(), + NoAnchors: !cfg.ProtocolOptions.AnchorCommitments(), }) if err != nil { return nil, err From fd93c568ea22cdc6b51a56f384f4ee7fab2c2284 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:48 +0100 Subject: [PATCH 185/562] config+link: disable watchtower for anchors --- htlcswitch/link.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index cd2d1fca4c..7c834827d7 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -419,7 +419,12 @@ func (l *channelLink) Start() error { // If the config supplied watchtower client, ensure the channel is // registered before trying to use it during operation. - if l.cfg.TowerClient != nil { + // TODO(halseth): support anchor types for watchtower. + state := l.channel.State() + if l.cfg.TowerClient != nil && state.ChanType.HasAnchors() { + l.log.Warnf("Skipping tower registration for anchor " + + "channel type") + } else if l.cfg.TowerClient != nil && !state.ChanType.HasAnchors() { err := l.cfg.TowerClient.RegisterChannel(l.ChanID()) if err != nil { return err @@ -1883,8 +1888,12 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) { // If we have a tower client, we'll proceed in backing up the // state that was just revoked. - if l.cfg.TowerClient != nil { - state := l.channel.State() + // TODO(halseth): support anchor types for watchtower. + state := l.channel.State() + if l.cfg.TowerClient != nil && state.ChanType.HasAnchors() { + l.log.Warnf("Skipping tower backup for anchor " + + "channel type") + } else if l.cfg.TowerClient != nil && !state.ChanType.HasAnchors() { breachInfo, err := lnwallet.NewBreachRetribution( state, state.RemoteCommitment.CommitHeight-1, 0, ) From 7adb1bcbaa9689e08e1e281d8cf65379adefc589 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:48 +0100 Subject: [PATCH 186/562] chanbackup: disable channel backup for anchor types --- chanbackup/backup.go | 17 ++++++++++++++--- chanbackup/pubsub.go | 6 ++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/chanbackup/backup.go b/chanbackup/backup.go index ca3698a548..406cc1bfe5 100644 --- a/chanbackup/backup.go +++ b/chanbackup/backup.go @@ -62,6 +62,12 @@ func FetchBackupForChan(chanPoint wire.OutPoint, return nil, fmt.Errorf("unable to find target channel") } + // TODO(halseth): support chan backups for anchor types. + if targetChan.ChanType.HasAnchors() { + return nil, fmt.Errorf("channel type does not support " + + "backups yet") + } + // Once we have the target channel, we can assemble the backup using // the source to obtain any extra information that we may need. staticChanBackup, err := assembleChanBackup(chanSource, targetChan) @@ -85,14 +91,19 @@ func FetchStaticChanBackups(chanSource LiveChannelSource) ([]Single, error) { // Now that we have all the channels, we'll use the chanSource to // obtain any auxiliary information we need to craft a backup for each // channel. - staticChanBackups := make([]Single, len(openChans)) - for i, openChan := range openChans { + staticChanBackups := make([]Single, 0, len(openChans)) + for _, openChan := range openChans { + // TODO(halseth): support chan backups for anchor types. + if openChan.ChanType.HasAnchors() { + continue + } + chanBackup, err := assembleChanBackup(chanSource, openChan) if err != nil { return nil, err } - staticChanBackups[i] = *chanBackup + staticChanBackups = append(staticChanBackups, *chanBackup) } return staticChanBackups, nil diff --git a/chanbackup/pubsub.go b/chanbackup/pubsub.go index b9331820e5..2bc74898ec 100644 --- a/chanbackup/pubsub.go +++ b/chanbackup/pubsub.go @@ -213,6 +213,12 @@ func (s *SubSwapper) backupUpdater() { // For all new open channels, we'll create a new SCB // given the required information. for _, newChan := range chanUpdate.NewChans { + // TODO(halseth): support chan backups for + // anchor types. + if newChan.ChanType.HasAnchors() { + continue + } + log.Debugf("Adding channel %v to backup state", newChan.FundingOutpoint) From ea2a58e80f61ccfd28f2b834e022a7a410c1b247 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:49 +0100 Subject: [PATCH 187/562] fundingmanager+lnwallet: enable anchor commitments If both nodes are signalling the feature, make all opened channels using this type. --- fundingmanager.go | 14 ++++++++++++++ lnwallet/reservation.go | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index bf4ed31b04..3e28f2a878 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -1111,6 +1111,20 @@ func (f *fundingManager) processFundingOpen(msg *lnwire.OpenChannel, func commitmentType(localFeatures, remoteFeatures *lnwire.FeatureVector) lnwallet.CommitmentType { + // If both peers are signalling support for anchor commitments, this + // implicitly mean we'll create the channel of this type. Note that + // this also enables tweakless commitments, as anchor commitments are + // always tweakless. + localAnchors := localFeatures.HasFeature( + lnwire.AnchorsOptional, + ) + remoteAnchors := remoteFeatures.HasFeature( + lnwire.AnchorsOptional, + ) + if localAnchors && remoteAnchors { + return lnwallet.CommitmentTypeAnchors + } + localTweakless := localFeatures.HasFeature( lnwire.StaticRemoteKeyOptional, ) diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index ba4c631ef6..823aec4ae3 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -27,6 +27,11 @@ const ( // CommitmentTypeTweakless is a newer commitment format where the // to_remote key is static. CommitmentTypeTweakless + + // CommitmentTypeAnchors is a commitment type that is tweakless, and + // has extra anchor ouputs in order to bump the fee of the commitment + // transaction. + CommitmentTypeAnchors ) // String returns the name of the CommitmentType. @@ -36,6 +41,8 @@ func (c CommitmentType) String() string { return "legacy" case CommitmentTypeTweakless: return "tweakless" + case CommitmentTypeAnchors: + return "anchors" default: return "invalid" } @@ -172,12 +179,25 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, initiator bool ) - commitFee := commitFeePerKw.FeeForWeight(input.CommitWeight) + // Based on the channel type, we determine the initial commit weight + // and fee. + commitWeight := int64(input.CommitWeight) + if commitType == CommitmentTypeAnchors { + commitWeight = input.AnchorCommitWeight + } + commitFee := commitFeePerKw.FeeForWeight(commitWeight) + localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt) // TODO(halseth): make method take remote funding amount directly // instead of inferring it from capacity and local amt. capacityMSat := lnwire.NewMSatFromSatoshis(capacity) + + // The total fee paid by the initiator will be the commitment fee in + // addition to the two anchor outputs. feeMSat := lnwire.NewMSatFromSatoshis(commitFee) + if commitType == CommitmentTypeAnchors { + feeMSat += 2 * lnwire.NewMSatFromSatoshis(anchorSize) + } // If we're the responder to a single-funder reservation, then we have // no initial balance in the channel unless the remote party is pushing @@ -257,7 +277,11 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // non-zero push amt (there's no pushing for dual funder), then this is // a single-funder channel. if ourBalance == 0 || theirBalance == 0 || pushMSat != 0 { - if commitType == CommitmentTypeTweakless { + // Both the tweakless type and the anchor type is tweakless, + // hence set the bit. + if commitType == CommitmentTypeTweakless || + commitType == CommitmentTypeAnchors { + chanType |= channeldb.SingleFunderTweaklessBit } else { chanType |= channeldb.SingleFunderBit @@ -277,6 +301,11 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, chanType |= channeldb.DualFunderBit } + // We are adding anchor outputs to our commitment. + if commitType == CommitmentTypeAnchors { + chanType |= channeldb.AnchorOutputsBit + } + return &ChannelReservation{ ourContribution: &ChannelContribution{ FundingAmount: ourBalance.ToSatoshis(), From b7885dbbae7cf36e1d00fbaf62084f74529bbb11 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:49 +0100 Subject: [PATCH 188/562] lnwallet+size: select HTLC fees based on channel type --- input/size.go | 17 +++++++ lnwallet/channel.go | 102 +++++++++++++++++++++------------------ lnwallet/channel_test.go | 21 +++++--- lnwallet/commitment.go | 49 +++++++++++++++---- 4 files changed, 125 insertions(+), 64 deletions(-) diff --git a/input/size.go b/input/size.go index 005c227301..d5f5e2b064 100644 --- a/input/size.go +++ b/input/size.go @@ -202,6 +202,23 @@ const ( // which will transition an incoming HTLC to the delay-and-claim state. HtlcSuccessWeight = 703 + // HtlcConfirmedScriptOverhead is the extra length of an HTLC script + // that requires confirmation before it can be spent. These extra bytes + // is a result of the extra CSV check. + HtlcConfirmedScriptOverhead = 3 + + // HtlcTimeoutWeightConfirmed is the weight of the HTLC timeout + // transaction which will transition an outgoing HTLC to the + // delay-and-claim state, for the confirmed HTLC outputs. It is 3 bytes + // larger because of the additional CSV check in the input script. + HtlcTimeoutWeightConfirmed = HtlcTimeoutWeight + HtlcConfirmedScriptOverhead + + // HtlcSuccessWeightCOnfirmed is the weight of the HTLC success + // transaction which will transition an incoming HTLC to the + // delay-and-claim state, for the confirmed HTLC outputs. It is 3 bytes + // larger because of the cdditional CSV check in the input script. + HtlcSuccessWeightConfirmed = HtlcSuccessWeight + HtlcConfirmedScriptOverhead + // MaxHTLCNumber is the maximum number HTLCs which can be included in a // commitment transaction. This limit was chosen such that, in the case // of a contract breach, the punishment transaction is able to sweep diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 6b072aded4..aca93b9933 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -596,7 +596,7 @@ func locateOutputIndex(p *PaymentDescriptor, tx *wire.MsgTx, ourCommit bool, // we need to keep track of the indexes of each HTLC in order to properly write // the current state to disk, and also to locate the PaymentDescriptor // corresponding to HTLC outputs in the commitment transaction. -func (c *commitment) populateHtlcIndexes() error { +func (c *commitment) populateHtlcIndexes(chanType channeldb.ChannelType) error { // First, we'll set up some state to allow us to locate the output // index of the all the HTLC's within the commitment transaction. We // must keep this index so we can validate the HTLC signatures sent to @@ -608,8 +608,10 @@ func (c *commitment) populateHtlcIndexes() error { // populateIndex is a helper function that populates the necessary // indexes within the commitment view for a particular HTLC. populateIndex := func(htlc *PaymentDescriptor, incoming bool) error { - isDust := htlcIsDust(incoming, c.isOurs, c.feePerKw, - htlc.Amount.ToSatoshis(), c.dustLimit) + isDust := htlcIsDust( + chanType, incoming, c.isOurs, c.feePerKw, + htlc.Amount.ToSatoshis(), c.dustLimit, + ) var err error switch { @@ -782,8 +784,10 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, // generate them in order to locate the outputs within the commitment // transaction. As we'll mark dust with a special output index in the // on-disk state snapshot. - isDustLocal := htlcIsDust(htlc.Incoming, true, feeRate, - htlc.Amt.ToSatoshis(), lc.channelState.LocalChanCfg.DustLimit) + isDustLocal := htlcIsDust( + chanType, htlc.Incoming, true, feeRate, + htlc.Amt.ToSatoshis(), lc.channelState.LocalChanCfg.DustLimit, + ) if !isDustLocal && localCommitKeys != nil { ourP2WSH, ourWitnessScript, err = genHtlcScript( chanType, htlc.Incoming, true, htlc.RefundTimeout, @@ -793,8 +797,10 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, return pd, err } } - isDustRemote := htlcIsDust(htlc.Incoming, false, feeRate, - htlc.Amt.ToSatoshis(), lc.channelState.RemoteChanCfg.DustLimit) + isDustRemote := htlcIsDust( + chanType, htlc.Incoming, false, feeRate, + htlc.Amt.ToSatoshis(), lc.channelState.RemoteChanCfg.DustLimit, + ) if !isDustRemote && remoteCommitKeys != nil { theirP2WSH, theirWitnessScript, err = genHtlcScript( chanType, htlc.Incoming, false, htlc.RefundTimeout, @@ -930,7 +936,8 @@ func (lc *LightningChannel) diskCommitToMemCommit(isLocal bool, // Finally, we'll re-populate the HTLC index for this state so we can // properly locate each HTLC within the commitment transaction. - if err := commit.populateHtlcIndexes(); err != nil { + err = commit.populateHtlcIndexes(lc.channelState.ChanType) + if err != nil { return nil, err } @@ -1410,8 +1417,10 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate, pd.OnionBlob = make([]byte, len(wireMsg.OnionBlob)) copy(pd.OnionBlob[:], wireMsg.OnionBlob[:]) - isDustRemote := htlcIsDust(false, false, feeRate, - wireMsg.Amount.ToSatoshis(), remoteDustLimit) + isDustRemote := htlcIsDust( + lc.channelState.ChanType, false, false, feeRate, + wireMsg.Amount.ToSatoshis(), remoteDustLimit, + ) if !isDustRemote { theirP2WSH, theirWitnessScript, err := genHtlcScript( lc.channelState.ChanType, false, false, @@ -2168,7 +2177,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, // If the HTLC is dust, then we'll skip it as it doesn't have // an output on the commitment transaction. if htlcIsDust( - htlc.Incoming, false, + chanState.ChanType, htlc.Incoming, false, chainfee.SatPerKWeight(revokedSnapshot.FeePerKw), htlc.Amt.ToSatoshis(), chanState.RemoteChanCfg.DustLimit, ) { @@ -2239,25 +2248,14 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64, }, nil } -// htlcTimeoutFee returns the fee in satoshis required for an HTLC timeout -// transaction based on the current fee rate. -func htlcTimeoutFee(feePerKw chainfee.SatPerKWeight) btcutil.Amount { - return feePerKw.FeeForWeight(input.HtlcTimeoutWeight) -} - -// htlcSuccessFee returns the fee in satoshis required for an HTLC success -// transaction based on the current fee rate. -func htlcSuccessFee(feePerKw chainfee.SatPerKWeight) btcutil.Amount { - return feePerKw.FeeForWeight(input.HtlcSuccessWeight) -} - // htlcIsDust determines if an HTLC output is dust or not depending on two // bits: if the HTLC is incoming and if the HTLC will be placed on our // commitment transaction, or theirs. These two pieces of information are // require as we currently used second-level HTLC transactions as off-chain // covenants. Depending on the two bits, we'll either be using a timeout or // success transaction which have different weights. -func htlcIsDust(incoming, ourCommit bool, feePerKw chainfee.SatPerKWeight, +func htlcIsDust(chanType channeldb.ChannelType, + incoming, ourCommit bool, feePerKw chainfee.SatPerKWeight, htlcAmt, dustLimit btcutil.Amount) bool { // First we'll determine the fee required for this HTLC based on if this is @@ -2269,25 +2267,25 @@ func htlcIsDust(incoming, ourCommit bool, feePerKw chainfee.SatPerKWeight, // If this is an incoming HTLC on our commitment transaction, then the // second-level transaction will be a success transaction. case incoming && ourCommit: - htlcFee = htlcSuccessFee(feePerKw) + htlcFee = HtlcSuccessFee(chanType, feePerKw) // If this is an incoming HTLC on their commitment transaction, then // we'll be using a second-level timeout transaction as they've added // this HTLC. case incoming && !ourCommit: - htlcFee = htlcTimeoutFee(feePerKw) + htlcFee = HtlcTimeoutFee(chanType, feePerKw) // If this is an outgoing HTLC on our commitment transaction, then // we'll be using a timeout transaction as we're the sender of the // HTLC. case !incoming && ourCommit: - htlcFee = htlcTimeoutFee(feePerKw) + htlcFee = HtlcTimeoutFee(chanType, feePerKw) // If this is an outgoing HTLC on their commitment transaction, then // we'll be using an HTLC success transaction as they're the receiver // of this HTLC. case !incoming && !ourCommit: - htlcFee = htlcSuccessFee(feePerKw) + htlcFee = HtlcSuccessFee(chanType, feePerKw) } return (htlcAmt - htlcFee) < dustLimit @@ -2431,7 +2429,7 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool, // Finally, we'll populate all the HTLC indexes so we can track the // locations of each HTLC in the commitment state. - if err := c.populateHtlcIndexes(); err != nil { + if err := c.populateHtlcIndexes(lc.channelState.ChanType); err != nil { return nil, err } @@ -2769,8 +2767,10 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, // dust output after taking into account second-level HTLC fees, then a // sigJob will be generated and appended to the current batch. for _, htlc := range remoteCommitView.incomingHTLCs { - if htlcIsDust(true, false, feePerKw, htlc.Amount.ToSatoshis(), - dustLimit) { + if htlcIsDust( + chanType, true, false, feePerKw, + htlc.Amount.ToSatoshis(), dustLimit, + ) { continue } @@ -2785,7 +2785,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, // HTLC timeout transaction for them. The output of the timeout // transaction needs to account for fees, so we'll compute the // required fee and output now. - htlcFee := htlcTimeoutFee(feePerKw) + htlcFee := HtlcTimeoutFee(chanType, feePerKw) outputAmt := htlc.Amount.ToSatoshis() - htlcFee // With the fee calculate, we can properly create the HTLC @@ -2822,8 +2822,10 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, sigBatch = append(sigBatch, sigJob) } for _, htlc := range remoteCommitView.outgoingHTLCs { - if htlcIsDust(false, false, feePerKw, htlc.Amount.ToSatoshis(), - dustLimit) { + if htlcIsDust( + chanType, false, false, feePerKw, + htlc.Amount.ToSatoshis(), dustLimit, + ) { continue } @@ -2836,7 +2838,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, // HTLC success transaction for them. The output of the timeout // transaction needs to account for fees, so we'll compute the // required fee and output now. - htlcFee := htlcSuccessFee(feePerKw) + htlcFee := HtlcSuccessFee(chanType, feePerKw) outputAmt := htlc.Amount.ToSatoshis() - htlcFee // With the proper output amount calculated, we can now @@ -3785,16 +3787,20 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, // weight, needed to calculate the transaction fee. var totalHtlcWeight int64 for _, htlc := range filteredHTLCView.ourUpdates { - if htlcIsDust(remoteChain, !remoteChain, feePerKw, - htlc.Amount.ToSatoshis(), dustLimit) { + if htlcIsDust( + lc.channelState.ChanType, remoteChain, !remoteChain, + feePerKw, htlc.Amount.ToSatoshis(), dustLimit, + ) { continue } totalHtlcWeight += input.HTLCWeight } for _, htlc := range filteredHTLCView.theirUpdates { - if htlcIsDust(!remoteChain, !remoteChain, feePerKw, - htlc.Amount.ToSatoshis(), dustLimit) { + if htlcIsDust( + lc.channelState.ChanType, !remoteChain, !remoteChain, + feePerKw, htlc.Amount.ToSatoshis(), dustLimit, + ) { continue } @@ -3857,7 +3863,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment, Index: uint32(htlc.localOutputIndex), } - htlcFee := htlcSuccessFee(feePerKw) + htlcFee := HtlcSuccessFee(chanType, feePerKw) outputAmt := htlc.Amount.ToSatoshis() - htlcFee successTx, err := createHtlcSuccessTx( @@ -3911,7 +3917,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment, Index: uint32(htlc.localOutputIndex), } - htlcFee := htlcTimeoutFee(feePerKw) + htlcFee := HtlcTimeoutFee(chanType, feePerKw) outputAmt := htlc.Amount.ToSatoshis() - htlcFee timeoutTx, err := createHtlcTimeoutTx( @@ -5383,7 +5389,7 @@ func newOutgoingHtlcResolution(signer input.Signer, // In order to properly reconstruct the HTLC transaction, we'll need to // re-calculate the fee required at this state, so we can add the // correct output value amount to the transaction. - htlcFee := htlcTimeoutFee(feePerKw) + htlcFee := HtlcTimeoutFee(chanType, feePerKw) secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee // With the fee calculated, re-construct the second level timeout @@ -5513,7 +5519,7 @@ func newIncomingHtlcResolution(signer input.Signer, // First, we'll reconstruct the original HTLC success transaction, // taking into account the fee rate used. - htlcFee := htlcSuccessFee(feePerKw) + htlcFee := HtlcSuccessFee(chanType, feePerKw) secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee successTx, err := createHtlcSuccessTx( chanType, op, secondLevelOutputAmt, csvDelay, @@ -5637,8 +5643,10 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool, // We'll skip any HTLC's which were dust on the commitment // transaction, as these don't have a corresponding output // within the commitment transaction. - if htlcIsDust(htlc.Incoming, ourCommit, feePerKw, - htlc.Amt.ToSatoshis(), dustLimit) { + if htlcIsDust( + chanType, htlc.Incoming, ourCommit, feePerKw, + htlc.Amt.ToSatoshis(), dustLimit, + ) { continue } @@ -6141,7 +6149,7 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView, // For an extra HTLC fee to be paid on our commitment, the HTLC must be // large enough to make a non-dust HTLC timeout transaction. htlcFee := lnwire.NewMSatFromSatoshis( - htlcTimeoutFee(feePerKw), + HtlcTimeoutFee(lc.channelState.ChanType, feePerKw), ) // If we are looking at the remote commitment, we must use the remote @@ -6151,7 +6159,7 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView, lc.channelState.RemoteChanCfg.DustLimit, ) htlcFee = lnwire.NewMSatFromSatoshis( - htlcSuccessFee(feePerKw), + HtlcSuccessFee(lc.channelState.ChanType, feePerKw), ) } diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index c4c886709d..511631bb6f 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -1011,7 +1011,8 @@ func TestHTLCDustLimit(t *testing.T) { // The amount of the HTLC should be above Alice's dust limit and below // Bob's dust limit. - htlcSat := (btcutil.Amount(500) + htlcTimeoutFee( + htlcSat := (btcutil.Amount(500) + HtlcTimeoutFee( + aliceChannel.channelState.ChanType, chainfee.SatPerKWeight( aliceChannel.channelState.LocalCommitment.FeePerKw, ), @@ -1119,8 +1120,12 @@ func TestHTLCSigNumber(t *testing.T) { t.Fatalf("unable to get fee: %v", err) } - belowDust := btcutil.Amount(500) + htlcTimeoutFee(feePerKw) - aboveDust := btcutil.Amount(1400) + htlcSuccessFee(feePerKw) + belowDust := btcutil.Amount(500) + HtlcTimeoutFee( + channeldb.SingleFunderTweaklessBit, feePerKw, + ) + aboveDust := btcutil.Amount(1400) + HtlcSuccessFee( + channeldb.SingleFunderTweaklessBit, feePerKw, + ) // =================================================================== // Test that Bob will reject a commitment if Alice doesn't send enough @@ -1278,7 +1283,8 @@ func TestChannelBalanceDustLimit(t *testing.T) { defaultFee := calcStaticFee(1) aliceBalance := aliceChannel.channelState.LocalCommitment.LocalBalance.ToSatoshis() htlcSat := aliceBalance - defaultFee - htlcSat += htlcSuccessFee( + htlcSat += HtlcSuccessFee( + aliceChannel.channelState.ChanType, chainfee.SatPerKWeight( aliceChannel.channelState.LocalCommitment.FeePerKw, ), @@ -4759,10 +4765,10 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { aliceChannel.channelState.LocalCommitment.CommitFee, ) htlcTimeoutFee := lnwire.NewMSatFromSatoshis( - htlcTimeoutFee(feeRate), + HtlcTimeoutFee(aliceChannel.channelState.ChanType, feeRate), ) htlcSuccessFee := lnwire.NewMSatFromSatoshis( - htlcSuccessFee(feeRate), + HtlcSuccessFee(aliceChannel.channelState.ChanType, feeRate), ) // Helper method to check the current reported balance. @@ -6273,7 +6279,8 @@ func TestChanReserveLocalInitiatorDustHtlc(t *testing.T) { // limit (1300 sat). It is considered dust if the amount remaining // after paying the HTLC fee is below the dustlimit, so we choose a // size of 500+htlcFee. - htlcSat := btcutil.Amount(500) + htlcTimeoutFee( + htlcSat := btcutil.Amount(500) + HtlcTimeoutFee( + aliceChannel.channelState.ChanType, chainfee.SatPerKWeight( aliceChannel.channelState.LocalCommitment.FeePerKw, ), diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index abe9288e41..077b6da9dc 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -255,6 +255,29 @@ func CommitWeight(chanType channeldb.ChannelType) int64 { return input.CommitWeight } +// HtlcTimeoutFee returns the fee in satoshis required for an HTLC timeout +// transaction based on the current fee rate. +func HtlcTimeoutFee(chanType channeldb.ChannelType, + feePerKw chainfee.SatPerKWeight) btcutil.Amount { + + if chanType.HasAnchors() { + return feePerKw.FeeForWeight(input.HtlcTimeoutWeightConfirmed) + } + + return feePerKw.FeeForWeight(input.HtlcTimeoutWeight) +} + +// HtlcSuccessFee returns the fee in satoshis required for an HTLC success +// transaction based on the current fee rate. +func HtlcSuccessFee(chanType channeldb.ChannelType, + feePerKw chainfee.SatPerKWeight) btcutil.Amount { + + if chanType.HasAnchors() { + return feePerKw.FeeForWeight(input.HtlcSuccessWeightConfirmed) + } + return feePerKw.FeeForWeight(input.HtlcSuccessWeight) +} + // CommitScriptAnchors return the scripts to use for the local and remote // anchor. func CommitScriptAnchors(localChanCfg, @@ -373,18 +396,20 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, numHTLCs := int64(0) for _, htlc := range filteredHTLCView.ourUpdates { - if htlcIsDust(false, isOurs, feePerKw, - htlc.Amount.ToSatoshis(), dustLimit) { - + if htlcIsDust( + cb.chanState.ChanType, false, isOurs, feePerKw, + htlc.Amount.ToSatoshis(), dustLimit, + ) { continue } numHTLCs++ } for _, htlc := range filteredHTLCView.theirUpdates { - if htlcIsDust(true, isOurs, feePerKw, - htlc.Amount.ToSatoshis(), dustLimit) { - + if htlcIsDust( + cb.chanState.ChanType, true, isOurs, feePerKw, + htlc.Amount.ToSatoshis(), dustLimit, + ) { continue } @@ -460,8 +485,10 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, // purposes of sorting. cltvs := make([]uint32, len(commitTx.TxOut)) for _, htlc := range filteredHTLCView.ourUpdates { - if htlcIsDust(false, isOurs, feePerKw, - htlc.Amount.ToSatoshis(), dustLimit) { + if htlcIsDust( + cb.chanState.ChanType, false, isOurs, feePerKw, + htlc.Amount.ToSatoshis(), dustLimit, + ) { continue } @@ -475,8 +502,10 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, cltvs = append(cltvs, htlc.Timeout) } for _, htlc := range filteredHTLCView.theirUpdates { - if htlcIsDust(true, isOurs, feePerKw, - htlc.Amount.ToSatoshis(), dustLimit) { + if htlcIsDust( + cb.chanState.ChanType, true, isOurs, feePerKw, + htlc.Amount.ToSatoshis(), dustLimit, + ) { continue } From 48c0e42c26331526731553587808c7f031e04ac9 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 20 Feb 2020 18:08:01 +0100 Subject: [PATCH 189/562] channeldb+routing: store all payment htlcs This commit converts the database structure of a payment so that it can not just store the last htlc attempt, but all attempts that have been made. This is a preparation for mpp sending. In addition to that, we now also persist the fail time of an htlc. In a later commit, the full failure reason will be added as well. A key change is made to the control tower interface. Previously the control tower wasn't aware of individual htlc outcomes. The payment remained in-flight with the latest attempt recorded, but an outcome was only set when the payment finished. With this commit, the outcome of every htlc is expected by the control tower and recorded in the database. Co-authored-by: Johan T. Halseth --- channeldb/mp_payment.go | 86 ++++++++++ channeldb/payment_control.go | 210 +++++++++++++++-------- channeldb/payment_control_test.go | 75 +++++--- channeldb/payments.go | 272 +++++++++++++++--------------- channeldb/payments_test.go | 20 ++- routing/control_tower.go | 47 ++++-- routing/control_tower_test.go | 20 ++- routing/mock_test.go | 17 +- routing/payment_lifecycle.go | 44 ++++- routing/router.go | 9 +- 10 files changed, 538 insertions(+), 262 deletions(-) diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index 4220e7aab7..7c5d97aee1 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -1,6 +1,7 @@ package channeldb import ( + "io" "time" "github.com/btcsuite/btcd/btcec" @@ -92,3 +93,88 @@ type MPPayment struct { // Status is the current PaymentStatus of this payment. Status PaymentStatus } + +// serializeHTLCSettleInfo serializes the details of a settled htlc. +func serializeHTLCSettleInfo(w io.Writer, s *HTLCSettleInfo) error { + if _, err := w.Write(s.Preimage[:]); err != nil { + return err + } + + if err := serializeTime(w, s.SettleTime); err != nil { + return err + } + + return nil +} + +// deserializeHTLCSettleInfo deserializes the details of a settled htlc. +func deserializeHTLCSettleInfo(r io.Reader) (*HTLCSettleInfo, error) { + s := &HTLCSettleInfo{} + if _, err := io.ReadFull(r, s.Preimage[:]); err != nil { + return nil, err + } + + var err error + s.SettleTime, err = deserializeTime(r) + if err != nil { + return nil, err + } + + return s, nil +} + +// serializeHTLCFailInfo serializes the details of a failed htlc including the +// wire failure. +func serializeHTLCFailInfo(w io.Writer, f *HTLCFailInfo) error { + if err := serializeTime(w, f.FailTime); err != nil { + return err + } + + return nil +} + +// deserializeHTLCFailInfo deserializes the details of a failed htlc including +// the wire failure. +func deserializeHTLCFailInfo(r io.Reader) (*HTLCFailInfo, error) { + f := &HTLCFailInfo{} + var err error + f.FailTime, err = deserializeTime(r) + if err != nil { + return nil, err + } + + return f, nil +} + +// deserializeTime deserializes time as unix nanoseconds. +func deserializeTime(r io.Reader) (time.Time, error) { + var scratch [8]byte + if _, err := io.ReadFull(r, scratch[:]); err != nil { + return time.Time{}, err + } + + // Convert to time.Time. Interpret unix nano time zero as a zero + // time.Time value. + unixNano := byteOrder.Uint64(scratch[:]) + if unixNano == 0 { + return time.Time{}, nil + } + + return time.Unix(0, int64(unixNano)), nil +} + +// serializeTime serializes time as unix nanoseconds. +func serializeTime(w io.Writer, t time.Time) error { + var scratch [8]byte + + // Convert to unix nano seconds, but only if time is non-zero. Calling + // UnixNano() on a zero time yields an undefined result. + var unixNano int64 + if !t.IsZero() { + unixNano = t.UnixNano() + } + + byteOrder.PutUint64(scratch[:], uint64(unixNano)) + _, err := w.Write(scratch[:]) + return err +} diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 72c5c1993c..1b65f4bf65 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -127,11 +127,11 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, return err } - // We'll delete any lingering attempt info to start with, in - // case we are initializing a payment that was attempted - // earlier, but left in a state where we could retry. - err = bucket.Delete(paymentAttemptInfoKey) - if err != nil { + // We'll delete any lingering HTLCs to start with, in case we + // are initializing a payment that was attempted earlier, but + // left in a state where we could retry. + err = bucket.DeleteBucket(paymentHtlcsBucket) + if err != nil && err != bbolt.ErrBucketNotFound { return err } @@ -153,76 +153,113 @@ func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, // Serialize the information before opening the db transaction. var a bytes.Buffer - if err := serializeHTLCAttemptInfo(&a, attempt); err != nil { + err := serializeHTLCAttemptInfo(&a, attempt) + if err != nil { return err } - attemptBytes := a.Bytes() + htlcInfoBytes := a.Bytes() - var updateErr error - err := p.db.Batch(func(tx *bbolt.Tx) error { - // Reset the update error, to avoid carrying over an error - // from a previous execution of the batched db transaction. - updateErr = nil + htlcIDBytes := make([]byte, 8) + binary.BigEndian.PutUint64(htlcIDBytes, attempt.AttemptID) + return p.db.Update(func(tx *bbolt.Tx) error { + // Get the payment bucket to register this new attempt in. bucket, err := fetchPaymentBucket(tx, paymentHash) - if err == ErrPaymentNotInitiated { - updateErr = ErrPaymentNotInitiated - return nil - } else if err != nil { + if err != nil { return err } // We can only register attempts for payments that are // in-flight. if err := ensureInFlight(bucket); err != nil { - updateErr = err - return nil + return err } - // Add the payment attempt to the payments bucket. - return bucket.Put(paymentAttemptInfoKey, attemptBytes) + htlcsBucket, err := bucket.CreateBucketIfNotExists( + paymentHtlcsBucket, + ) + if err != nil { + return err + } + + // Create bucket for this attempt. Fail if the bucket already + // exists. + htlcBucket, err := htlcsBucket.CreateBucket(htlcIDBytes) + if err != nil { + return err + } + + return htlcBucket.Put(htlcAttemptInfoKey, htlcInfoBytes) }) - if err != nil { +} + +// SettleAttempt marks the given attempt settled with the preimage. If this is +// a multi shard payment, this might implicitly mean that the full payment +// succeeded. +// +// After invoking this method, InitPayment should always return an error to +// prevent us from making duplicate payments to the same payment hash. The +// provided preimage is atomically saved to the DB for record keeping. +func (p *PaymentControl) SettleAttempt(hash lntypes.Hash, + attemptID uint64, settleInfo *HTLCSettleInfo) (*MPPayment, error) { + + var b bytes.Buffer + if err := serializeHTLCSettleInfo(&b, settleInfo); err != nil { + return nil, err + } + settleBytes := b.Bytes() + + return p.updateHtlcKey(hash, attemptID, htlcSettleInfoKey, settleBytes) +} + +// FailAttempt marks the given payment attempt failed. +func (p *PaymentControl) FailAttempt(hash lntypes.Hash, + attemptID uint64, failInfo *HTLCFailInfo) error { + + var b bytes.Buffer + if err := serializeHTLCFailInfo(&b, failInfo); err != nil { return err } + failBytes := b.Bytes() - return updateErr + _, err := p.updateHtlcKey(hash, attemptID, htlcFailInfoKey, failBytes) + return err } -// Success transitions a payment into the Succeeded state. After invoking this -// method, InitPayment should always return an error to prevent us from making -// duplicate payments to the same payment hash. The provided preimage is -// atomically saved to the DB for record keeping. -func (p *PaymentControl) Success(paymentHash lntypes.Hash, - preimage lntypes.Preimage) (*MPPayment, error) { +// updateHtlcKey updates a database key for the specified htlc. +func (p *PaymentControl) updateHtlcKey(paymentHash lntypes.Hash, + attemptID uint64, key, value []byte) (*MPPayment, error) { - var ( - updateErr error - payment *MPPayment - ) - err := p.db.Batch(func(tx *bbolt.Tx) error { - // Reset the update error, to avoid carrying over an error - // from a previous execution of the batched db transaction. - updateErr = nil - payment = nil + htlcIDBytes := make([]byte, 8) + binary.BigEndian.PutUint64(htlcIDBytes, attemptID) + var payment *MPPayment + err := p.db.Batch(func(tx *bbolt.Tx) error { + // Fetch bucket that contains all information for the payment + // with this hash. bucket, err := fetchPaymentBucket(tx, paymentHash) - if err == ErrPaymentNotInitiated { - updateErr = ErrPaymentNotInitiated - return nil - } else if err != nil { + if err != nil { return err } - // We can only mark in-flight payments as succeeded. + // We can only update keys of in-flight payments. if err := ensureInFlight(bucket); err != nil { - updateErr = err - return nil + return err + } + + htlcsBucket := bucket.Bucket(paymentHtlcsBucket) + if htlcsBucket == nil { + return fmt.Errorf("htlcs bucket not found") } - // Record the successful payment info atomically to the - // payments record. - err = bucket.Put(paymentSettleInfoKey, preimage[:]) + htlcBucket := htlcsBucket.Bucket(htlcIDBytes) + if htlcBucket == nil { + return fmt.Errorf("HTLC with ID %v not registered", + attemptID) + } + + // Add or update the key for this htlc. + err = htlcBucket.Put(key, value) if err != nil { return err } @@ -235,7 +272,7 @@ func (p *PaymentControl) Success(paymentHash lntypes.Hash, return nil, err } - return payment, updateErr + return payment, err } // Fail transitions a payment into the Failed state, and records the reason the @@ -278,7 +315,19 @@ func (p *PaymentControl) Fail(paymentHash lntypes.Hash, // Retrieve attempt info for the notification, if available. payment, err = fetchPayment(bucket) - return err + if err != nil { + return err + } + + // Final sanity check to see if there are no in-flight htlcs. + for _, htlc := range payment.HTLCs { + if htlc.Settle == nil && htlc.Failure == nil { + return errors.New("payment failed with " + + "in-flight htlc(s)") + } + } + + return nil }) if err != nil { return nil, err @@ -338,7 +387,6 @@ func fetchPaymentBucket(tx *bbolt.Tx, paymentHash lntypes.Hash) ( } return bucket, nil - } // nextPaymentSequence returns the next sequence number to store for a new @@ -362,8 +410,21 @@ func nextPaymentSequence(tx *bbolt.Tx) ([]byte, error) { // fetchPaymentStatus fetches the payment status of the payment. If the payment // isn't found, it will default to "StatusUnknown". func fetchPaymentStatus(bucket *bbolt.Bucket) (PaymentStatus, error) { - if bucket.Get(paymentSettleInfoKey) != nil { - return StatusSucceeded, nil + htlcsBucket := bucket.Bucket(paymentHtlcsBucket) + if htlcsBucket != nil { + htlcs, err := fetchHtlcAttempts(htlcsBucket) + if err != nil { + return 0, err + } + + // Go through all HTLCs, and return StatusSucceeded if any of + // them did succeed. + for _, h := range htlcs { + if h.Settle != nil { + return StatusSucceeded, nil + } + } + } if bucket.Get(paymentFailInfoKey) != nil { @@ -410,27 +471,16 @@ func ensureInFlight(bucket *bbolt.Bucket) error { } } -// fetchPaymentAttempt fetches the payment attempt from the bucket. -func fetchPaymentAttempt(bucket *bbolt.Bucket) (*HTLCAttemptInfo, error) { - attemptData := bucket.Get(paymentAttemptInfoKey) - if attemptData == nil { - return nil, errNoAttemptInfo - } - - r := bytes.NewReader(attemptData) - return deserializeHTLCAttemptInfo(r) -} - // InFlightPayment is a wrapper around a payment that has status InFlight. type InFlightPayment struct { // Info is the PaymentCreationInfo of the in-flight payment. Info *PaymentCreationInfo - // Attempt contains information about the last payment attempt that was - // made to this payment hash. + // Attempts is the set of payment attempts that was made to this + // payment hash. // - // NOTE: Might be nil. - Attempt *HTLCAttemptInfo + // NOTE: Might be empty. + Attempts []HTLCAttemptInfo } // FetchInFlightPayments returns all payments with status InFlight. @@ -473,13 +523,31 @@ func (p *PaymentControl) FetchInFlightPayments() ([]*InFlightPayment, error) { return err } - // Now get the attempt info. It could be that there is - // no attempt info yet. - inFlight.Attempt, err = fetchPaymentAttempt(bucket) - if err != nil && err != errNoAttemptInfo { + htlcsBucket := bucket.Bucket(paymentHtlcsBucket) + if htlcsBucket == nil { + return nil + } + + // Fetch all HTLCs attempted for this payment. + htlcs, err := fetchHtlcAttempts(htlcsBucket) + if err != nil { return err } + // We only care about the static info for the HTLCs + // still in flight, so convert the result to a slice of + // HTLCAttemptInfos. + for _, h := range htlcs { + // Skip HTLCs not in flight. + if h.Settle != nil || h.Failure != nil { + continue + } + + inFlight.Attempts = append( + inFlight.Attempts, h.HTLCAttemptInfo, + ) + } + inFlights = append(inFlights, inFlight) return nil }) diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 063a2e6f5b..7856cc1ac1 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -85,7 +85,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, nil, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, 0, nil, lntypes.Preimage{}, nil, ) @@ -99,7 +99,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { // Verify the status is indeed Failed. assertPaymentStatus(t, pControl, info.PaymentHash, StatusFailed) assertPaymentInfo( - t, pControl, info.PaymentHash, info, nil, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, 0, nil, lntypes.Preimage{}, &failReason, ) @@ -112,7 +112,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, nil, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, 0, nil, lntypes.Preimage{}, nil, ) @@ -125,6 +125,13 @@ func TestPaymentControlSwitchFail(t *testing.T) { t.Fatalf("unable to register attempt: %v", err) } + err = pControl.FailAttempt( + info.PaymentHash, 2, &HTLCFailInfo{}, + ) + if err != nil { + t.Fatal(err) + } + // Record another attempt. attempt.AttemptID = 3 err = pControl.RegisterAttempt(info.PaymentHash, attempt) @@ -133,19 +140,24 @@ func TestPaymentControlSwitchFail(t *testing.T) { } assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, attempt, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, 0, attempt, lntypes.Preimage{}, nil, ) // Settle the attempt and verify that status was changed to StatusSucceeded. var payment *MPPayment - payment, err = pControl.Success(info.PaymentHash, preimg) + payment, err = pControl.SettleAttempt( + info.PaymentHash, 3, + &HTLCSettleInfo{ + Preimage: preimg, + }, + ) if err != nil { t.Fatalf("error shouldn't have been received, got: %v", err) } - if len(payment.HTLCs) != 1 { - t.Fatalf("payment should have one htlc, got: %d", + if len(payment.HTLCs) != 2 { + t.Fatalf("payment should have two htlcs, got: %d", len(payment.HTLCs)) } @@ -157,7 +169,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { } assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) - assertPaymentInfo(t, pControl, info.PaymentHash, info, attempt, preimg, nil) + assertPaymentInfo(t, pControl, info.PaymentHash, info, 1, attempt, preimg, nil) // Attempt a final payment, which should now fail since the prior // payment succeed. @@ -193,7 +205,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, nil, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, 0, nil, lntypes.Preimage{}, nil, ) @@ -213,7 +225,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { } assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, attempt, lntypes.Preimage{}, + t, pControl, info.PaymentHash, info, 0, attempt, lntypes.Preimage{}, nil, ) @@ -225,11 +237,17 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { } // After settling, the error should be ErrAlreadyPaid. - if _, err := pControl.Success(info.PaymentHash, preimg); err != nil { + _, err = pControl.SettleAttempt( + info.PaymentHash, 1, + &HTLCSettleInfo{ + Preimage: preimg, + }, + ) + if err != nil { t.Fatalf("error shouldn't have been received, got: %v", err) } assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) - assertPaymentInfo(t, pControl, info.PaymentHash, info, attempt, preimg, nil) + assertPaymentInfo(t, pControl, info.PaymentHash, info, 0, attempt, preimg, nil) err = pControl.InitPayment(info.PaymentHash, info) if err != ErrAlreadyPaid { @@ -255,7 +273,12 @@ func TestPaymentControlSuccessesWithoutInFlight(t *testing.T) { } // Attempt to complete the payment should fail. - _, err = pControl.Success(info.PaymentHash, preimg) + _, err = pControl.SettleAttempt( + info.PaymentHash, 0, + &HTLCSettleInfo{ + Preimage: preimg, + }, + ) if err != ErrPaymentNotInitiated { t.Fatalf("expected ErrPaymentNotInitiated, got %v", err) } @@ -336,6 +359,15 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { } if p.failed { + // Fail the payment attempt. + err := pControl.FailAttempt( + info.PaymentHash, attempt.AttemptID, + &HTLCFailInfo{}, + ) + if err != nil { + t.Fatalf("unable to fail htlc: %v", err) + } + // Fail the payment, which should moved it to Failed. failReason := FailureReasonNoRoute _, err = pControl.Fail(info.PaymentHash, failReason) @@ -346,24 +378,29 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { // Verify the status is indeed Failed. assertPaymentStatus(t, pControl, info.PaymentHash, StatusFailed) assertPaymentInfo( - t, pControl, info.PaymentHash, info, attempt, + t, pControl, info.PaymentHash, info, 0, attempt, lntypes.Preimage{}, &failReason, ) } else if p.success { // Verifies that status was changed to StatusSucceeded. - _, err := pControl.Success(info.PaymentHash, preimg) + _, err := pControl.SettleAttempt( + info.PaymentHash, 1, + &HTLCSettleInfo{ + Preimage: preimg, + }, + ) if err != nil { t.Fatalf("error shouldn't have been received, got: %v", err) } assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) assertPaymentInfo( - t, pControl, info.PaymentHash, info, attempt, preimg, nil, + t, pControl, info.PaymentHash, info, 0, attempt, preimg, nil, ) } else { assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, attempt, + t, pControl, info.PaymentHash, info, 0, attempt, lntypes.Preimage{}, nil, ) } @@ -414,7 +451,7 @@ func assertPaymentStatus(t *testing.T, p *PaymentControl, // assertPaymentInfo retrieves the payment referred to by hash and verifies the // expected values. func assertPaymentInfo(t *testing.T, p *PaymentControl, hash lntypes.Hash, - c *PaymentCreationInfo, a *HTLCAttemptInfo, s lntypes.Preimage, + c *PaymentCreationInfo, aIdx int, a *HTLCAttemptInfo, s lntypes.Preimage, f *FailureReason) { t.Helper() @@ -446,7 +483,7 @@ func assertPaymentInfo(t *testing.T, p *PaymentControl, hash lntypes.Hash, return } - htlc := payment.HTLCs[0] + htlc := payment.HTLCs[aIdx] if err := assertRouteEqual(&htlc.Route, &a.Route); err != nil { t.Fatal("routes do not match") } diff --git a/channeldb/payments.go b/channeldb/payments.go index fc5e38bc20..96fab0a716 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -30,9 +30,19 @@ var ( // |-- // | |--sequence-key: // | |--creation-info-key: - // | |--attempt-info-key: - // | |--settle-info-key: - // | |--fail-info-key: + // | |--fail-info-key: <(optional) fail info> + // | | + // | |--payment-htlcs-bucket (shard-bucket) + // | | | + // | | |-- + // | | | |--htlc-attempt-info-key: + // | | | |--htlc-settle-info-key: <(optional) settle info> + // | | | |--htlc-fail-info-key: <(optional) fail info> + // | | | + // | | |-- + // | | | | + // | | ... ... + // | | // | | // | |--duplicate-bucket (only for old, completed payments) // | | @@ -62,14 +72,21 @@ var ( // store the creation info of the payment. paymentCreationInfoKey = []byte("payment-creation-info") - // paymentAttemptInfoKey is a key used in the payment's sub-bucket to - // store the info about the latest attempt that was done for the - // payment in question. - paymentAttemptInfoKey = []byte("payment-attempt-info") + // paymentHtlcsBucket is a bucket where we'll store the information + // about the HTLCs that were attempted for a payment. + paymentHtlcsBucket = []byte("payment-htlcs-bucket") + + // htlcAttemptInfoKey is a key used in a HTLC's sub-bucket to store the + // info about the attempt that was done for the HTLC in question. + htlcAttemptInfoKey = []byte("htlc-attempt-info") - // paymentSettleInfoKey is a key used in the payment's sub-bucket to - // store the settle info of the payment. - paymentSettleInfoKey = []byte("payment-settle-info") + // htlcSettleInfoKey is a key used in a HTLC's sub-bucket to store the + // settle info, if any. + htlcSettleInfoKey = []byte("htlc-settle-info") + + // htlcFailInfoKey is a key used in a HTLC's sub-bucket to store + // failure information, if any. + htlcFailInfoKey = []byte("htlc-fail-info") // paymentFailInfoKey is a key used in the payment's sub-bucket to // store information about the reason a payment failed. @@ -177,98 +194,6 @@ type PaymentCreationInfo struct { PaymentRequest []byte } -// Payment is a wrapper around a payment's PaymentCreationInfo, -// HTLCAttemptInfo, and preimage. All payments will have the -// PaymentCreationInfo set, the HTLCAttemptInfo will be set only if at least -// one payment attempt has been made, while only completed payments will have a -// non-zero payment preimage. -type Payment struct { - // sequenceNum is a unique identifier used to sort the payments in - // order of creation. - sequenceNum uint64 - - // Status is the current PaymentStatus of this payment. - Status PaymentStatus - - // Info holds all static information about this payment, and is - // populated when the payment is initiated. - Info *PaymentCreationInfo - - // Attempt is the information about the last payment attempt made. - // - // NOTE: Can be nil if no attempt is yet made. - Attempt *HTLCAttemptInfo - - // Preimage is the preimage of a successful payment. This serves as a - // proof of payment. It will only be non-nil for settled payments. - // - // NOTE: Can be nil if payment is not settled. - Preimage *lntypes.Preimage - - // Failure is a failure reason code indicating the reason the payment - // failed. It is only non-nil for failed payments. - // - // NOTE: Can be nil if payment is not failed. - Failure *FailureReason -} - -// ToMPPayment converts a legacy payment into an MPPayment. -func (p *Payment) ToMPPayment() *MPPayment { - var ( - htlcs []HTLCAttempt - reason *FailureReason - settle *HTLCSettleInfo - failure *HTLCFailInfo - ) - - // Promote the payment failure to a proper fail struct, if it exists. - if p.Failure != nil { - // NOTE: FailTime is not set for legacy payments. - failure = &HTLCFailInfo{} - reason = p.Failure - } - - // Promote the payment preimage to proper settle struct, if it exists. - if p.Preimage != nil { - // NOTE: SettleTime is not set for legacy payments. - settle = &HTLCSettleInfo{ - Preimage: *p.Preimage, - } - } - - // Either a settle or a failure may be set, but not both. - if settle != nil && failure != nil { - panic("htlc attempt has both settle and failure info") - } - - // Populate a single HTLC on the MPPayment if an attempt exists on the - // legacy payment. If none exists we will leave the attempt info blank - // since we cannot recover it. - if p.Attempt != nil { - // NOTE: AttemptTime is not set for legacy payments. - htlcs = []HTLCAttempt{ - { - HTLCAttemptInfo: *p.Attempt, - Settle: settle, - Failure: failure, - }, - } - } - - return &MPPayment{ - sequenceNum: p.sequenceNum, - Info: &PaymentCreationInfo{ - PaymentHash: p.Info.PaymentHash, - Value: p.Info.Value, - CreationTime: p.Info.CreationTime, - PaymentRequest: p.Info.PaymentRequest, - }, - HTLCs: htlcs, - FailureReason: reason, - Status: p.Status, - } -} - // FetchPayments returns all sent payments found in the DB. // // nolint: dupl @@ -324,20 +249,15 @@ func (db *DB) FetchPayments() ([]*MPPayment, error) { } func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) { - var ( - err error - p = &Payment{} - ) - seqBytes := bucket.Get(paymentSequenceKey) if seqBytes == nil { return nil, fmt.Errorf("sequence number not found") } - p.sequenceNum = binary.BigEndian.Uint64(seqBytes) + sequenceNum := binary.BigEndian.Uint64(seqBytes) // Get the payment status. - p.Status, err = fetchPaymentStatus(bucket) + paymentStatus, err := fetchPaymentStatus(bucket) if err != nil { return nil, err } @@ -349,39 +269,118 @@ func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) { } r := bytes.NewReader(b) - p.Info, err = deserializePaymentCreationInfo(r) + creationInfo, err := deserializePaymentCreationInfo(r) if err != nil { return nil, err } - // Get the HTLCAttemptInfo. This can be unset. - b = bucket.Get(paymentAttemptInfoKey) - if b != nil { - r = bytes.NewReader(b) - p.Attempt, err = deserializeHTLCAttemptInfo(r) + var htlcs []HTLCAttempt + htlcsBucket := bucket.Bucket(paymentHtlcsBucket) + if htlcsBucket != nil { + // Get the payment attempts. This can be empty. + htlcs, err = fetchHtlcAttempts(htlcsBucket) if err != nil { return nil, err } } - // Get the payment preimage. This is only found for - // completed payments. - b = bucket.Get(paymentSettleInfoKey) - if b != nil { - var preimg lntypes.Preimage - copy(preimg[:], b[:]) - p.Preimage = &preimg - } - // Get failure reason if available. + var failureReason *FailureReason b = bucket.Get(paymentFailInfoKey) if b != nil { reason := FailureReason(b[0]) - p.Failure = &reason + failureReason = &reason } - return p.ToMPPayment(), nil + return &MPPayment{ + sequenceNum: sequenceNum, + Info: creationInfo, + HTLCs: htlcs, + FailureReason: failureReason, + Status: paymentStatus, + }, nil +} + +// fetchHtlcAttempts retrives all htlc attempts made for the payment found in +// the given bucket. +func fetchHtlcAttempts(bucket *bbolt.Bucket) ([]HTLCAttempt, error) { + htlcs := make([]HTLCAttempt, 0) + + err := bucket.ForEach(func(k, _ []byte) error { + aid := byteOrder.Uint64(k) + htlcBucket := bucket.Bucket(k) + + attemptInfo, err := fetchHtlcAttemptInfo( + htlcBucket, + ) + if err != nil { + return err + } + attemptInfo.AttemptID = aid + + htlc := HTLCAttempt{ + HTLCAttemptInfo: *attemptInfo, + } + + // Settle info might be nil. + htlc.Settle, err = fetchHtlcSettleInfo(htlcBucket) + if err != nil { + return err + } + + // Failure info might be nil. + htlc.Failure, err = fetchHtlcFailInfo(htlcBucket) + if err != nil { + return err + } + + htlcs = append(htlcs, htlc) + return nil + }) + if err != nil { + return nil, err + } + + return htlcs, nil +} + +// fetchHtlcAttemptInfo fetches the payment attempt info for this htlc from the +// bucket. +func fetchHtlcAttemptInfo(bucket *bbolt.Bucket) (*HTLCAttemptInfo, error) { + b := bucket.Get(htlcAttemptInfoKey) + if b == nil { + return nil, errNoAttemptInfo + } + + r := bytes.NewReader(b) + return deserializeHTLCAttemptInfo(r) +} + +// fetchHtlcSettleInfo retrieves the settle info for the htlc. If the htlc isn't +// settled, nil is returned. +func fetchHtlcSettleInfo(bucket *bbolt.Bucket) (*HTLCSettleInfo, error) { + b := bucket.Get(htlcSettleInfoKey) + if b == nil { + // Settle info is optional. + return nil, nil + } + + r := bytes.NewReader(b) + return deserializeHTLCSettleInfo(r) +} + +// fetchHtlcFailInfo retrieves the failure info for the htlc. If the htlc hasn't +// failed, nil is returned. +func fetchHtlcFailInfo(bucket *bbolt.Bucket) (*HTLCFailInfo, error) { + b := bucket.Get(htlcFailInfoKey) + if b == nil { + // Fail info is optional. + return nil, nil + } + + r := bytes.NewReader(b) + return deserializeHTLCFailInfo(r) } // DeletePayments deletes all completed and failed payments from the DB. @@ -430,6 +429,7 @@ func (db *DB) DeletePayments() error { }) } +// nolint: dupl func serializePaymentCreationInfo(w io.Writer, c *PaymentCreationInfo) error { var scratch [8]byte @@ -442,8 +442,7 @@ func serializePaymentCreationInfo(w io.Writer, c *PaymentCreationInfo) error { return err } - byteOrder.PutUint64(scratch[:], uint64(c.CreationTime.Unix())) - if _, err := w.Write(scratch[:]); err != nil { + if err := serializeTime(w, c.CreationTime); err != nil { return err } @@ -473,10 +472,11 @@ func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) { } c.Value = lnwire.MilliSatoshi(byteOrder.Uint64(scratch[:])) - if _, err := io.ReadFull(r, scratch[:]); err != nil { + creationTime, err := deserializeTime(r) + if err != nil { return nil, err } - c.CreationTime = time.Unix(int64(byteOrder.Uint64(scratch[:])), 0) + c.CreationTime = creationTime if _, err := io.ReadFull(r, scratch[:4]); err != nil { return nil, err @@ -495,7 +495,7 @@ func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) { } func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error { - if err := WriteElements(w, a.AttemptID, a.SessionKey); err != nil { + if err := WriteElements(w, a.SessionKey); err != nil { return err } @@ -503,12 +503,12 @@ func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error { return err } - return nil + return serializeTime(w, a.AttemptTime) } func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) { a := &HTLCAttemptInfo{} - err := ReadElements(r, &a.AttemptID, &a.SessionKey) + err := ReadElements(r, &a.SessionKey) if err != nil { return nil, err } @@ -516,6 +516,12 @@ func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) { if err != nil { return nil, err } + + a.AttemptTime, err = deserializeTime(r) + if err != nil { + return nil, err + } + return a, nil } diff --git a/channeldb/payments_test.go b/channeldb/payments_test.go index 26148a1ecd..3cf3a4bab3 100644 --- a/channeldb/payments_test.go +++ b/channeldb/payments_test.go @@ -67,9 +67,10 @@ func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) { } a := &HTLCAttemptInfo{ - AttemptID: 44, - SessionKey: priv, - Route: testRoute, + AttemptID: 44, + SessionKey: priv, + Route: testRoute, + AttemptTime: time.Unix(100, 0), } return c, a } @@ -113,29 +114,30 @@ func TestSentPaymentSerialization(t *testing.T) { t.Fatalf("unable to serialize info: %v", err) } - newAttemptInfo, err := deserializeHTLCAttemptInfo(&b) + newWireInfo, err := deserializeHTLCAttemptInfo(&b) if err != nil { t.Fatalf("unable to deserialize info: %v", err) } + newWireInfo.AttemptID = s.AttemptID // First we verify all the records match up porperly, as they aren't // able to be properly compared using reflect.DeepEqual. - err = assertRouteEqual(&s.Route, &newAttemptInfo.Route) + err = assertRouteEqual(&s.Route, &newWireInfo.Route) if err != nil { t.Fatalf("Routes do not match after "+ "serialization/deserialization: %v", err) } // Clear routes to allow DeepEqual to compare the remaining fields. - newAttemptInfo.Route = route.Route{} + newWireInfo.Route = route.Route{} s.Route = route.Route{} - if !reflect.DeepEqual(s, newAttemptInfo) { + if !reflect.DeepEqual(s, newWireInfo) { s.SessionKey.Curve = nil - newAttemptInfo.SessionKey.Curve = nil + newWireInfo.SessionKey.Curve = nil t.Fatalf("Payments do not match after "+ "serialization/deserialization %v vs %v", - spew.Sdump(s), spew.Sdump(newAttemptInfo), + spew.Sdump(s), spew.Sdump(newWireInfo), ) } } diff --git a/routing/control_tower.go b/routing/control_tower.go index 0dffa7c633..5ade611cc8 100644 --- a/routing/control_tower.go +++ b/routing/control_tower.go @@ -14,7 +14,6 @@ import ( // restarts. Payments are transitioned through various payment states, and the // ControlTower interface provides access to driving the state transitions. type ControlTower interface { - // InitPayment atomically moves the payment into the InFlight state. // This method checks that no suceeded payment exist for this payment // hash. InitPayment(lntypes.Hash, *channeldb.PaymentCreationInfo) error @@ -22,17 +21,25 @@ type ControlTower interface { // RegisterAttempt atomically records the provided HTLCAttemptInfo. RegisterAttempt(lntypes.Hash, *channeldb.HTLCAttemptInfo) error - // Success transitions a payment into the Succeeded state. After - // invoking this method, InitPayment should always return an error to - // prevent us from making duplicate payments to the same payment hash. - // The provided preimage is atomically saved to the DB for record - // keeping. - Success(lntypes.Hash, lntypes.Preimage) error + // SettleAttempt marks the given attempt settled with the preimage. If + // this is a multi shard payment, this might implicitly mean the the + // full payment succeeded. + // + // After invoking this method, InitPayment should always return an + // error to prevent us from making duplicate payments to the same + // payment hash. The provided preimage is atomically saved to the DB + // for record keeping. + SettleAttempt(lntypes.Hash, uint64, *channeldb.HTLCSettleInfo) error + + // FailAttempt marks the given payment attempt failed. + FailAttempt(lntypes.Hash, uint64, *channeldb.HTLCFailInfo) error // Fail transitions a payment into the Failed state, and records the - // reason the payment failed. After invoking this method, InitPayment - // should return nil on its next call for this payment hash, allowing - // the switch to make a subsequent payment. + // ultimate reason the payment failed. Note that this should only be + // called when all active active attempts are already failed. After + // invoking this method, InitPayment should return nil on its next call + // for this payment hash, allowing the user to make a subsequent + // payment. Fail(lntypes.Hash, channeldb.FailureReason) error // FetchInFlightPayments returns all payments with status InFlight. @@ -99,14 +106,13 @@ func (p *controlTower) RegisterAttempt(paymentHash lntypes.Hash, return p.db.RegisterAttempt(paymentHash, attempt) } -// Success transitions a payment into the Succeeded state. After invoking this -// method, InitPayment should always return an error to prevent us from making -// duplicate payments to the same payment hash. The provided preimage is -// atomically saved to the DB for record keeping. -func (p *controlTower) Success(paymentHash lntypes.Hash, - preimage lntypes.Preimage) error { +// SettleAttempt marks the given attempt settled with the preimage. If +// this is a multi shard payment, this might implicitly mean the the +// full payment succeeded. +func (p *controlTower) SettleAttempt(paymentHash lntypes.Hash, + attemptID uint64, settleInfo *channeldb.HTLCSettleInfo) error { - payment, err := p.db.Success(paymentHash, preimage) + payment, err := p.db.SettleAttempt(paymentHash, attemptID, settleInfo) if err != nil { return err } @@ -119,6 +125,13 @@ func (p *controlTower) Success(paymentHash lntypes.Hash, return nil } +// FailAttempt marks the given payment attempt failed. +func (p *controlTower) FailAttempt(paymentHash lntypes.Hash, + attemptID uint64, failInfo *channeldb.HTLCFailInfo) error { + + return p.db.FailAttempt(paymentHash, attemptID, failInfo) +} + // createSuccessResult creates a success result to send to subscribers. func createSuccessResult(htlcs []channeldb.HTLCAttempt) *PaymentResult { // Extract any preimage from the list of HTLCs. diff --git a/routing/control_tower_test.go b/routing/control_tower_test.go index d4399ced4f..6bc8ffd7d9 100644 --- a/routing/control_tower_test.go +++ b/routing/control_tower_test.go @@ -13,9 +13,8 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/routing/route" - "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/routing/route" ) var ( @@ -111,7 +110,13 @@ func TestControlTowerSubscribeSuccess(t *testing.T) { } // Mark the payment as successful. - if err := pControl.Success(info.PaymentHash, preimg); err != nil { + err = pControl.SettleAttempt( + info.PaymentHash, attempt.AttemptID, + &channeldb.HTLCSettleInfo{ + Preimage: preimg, + }, + ) + if err != nil { t.Fatal(err) } @@ -213,6 +218,15 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) { if err != nil { t.Fatal(err) } + + // Fail the payment attempt. + err := pControl.FailAttempt( + info.PaymentHash, attempt.AttemptID, + &channeldb.HTLCFailInfo{}, + ) + if err != nil { + t.Fatalf("unable to fail htlc: %v", err) + } } // Mark the payment as failed. diff --git a/routing/mock_test.go b/routing/mock_test.go index a840d73861..6332bea8f6 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -231,7 +231,8 @@ func (m *mockControlTower) InitPayment(phash lntypes.Hash, } m.inflights[phash] = channeldb.InFlightPayment{ - Info: c, + Info: c, + Attempts: make([]channeldb.HTLCAttemptInfo, 0), } return nil @@ -252,20 +253,20 @@ func (m *mockControlTower) RegisterAttempt(phash lntypes.Hash, return fmt.Errorf("not in flight") } - p.Attempt = a + p.Attempts = append(p.Attempts, *a) m.inflights[phash] = p return nil } -func (m *mockControlTower) Success(phash lntypes.Hash, - preimg lntypes.Preimage) error { +func (m *mockControlTower) SettleAttempt(phash lntypes.Hash, + pid uint64, settleInfo *channeldb.HTLCSettleInfo) error { m.Lock() defer m.Unlock() if m.success != nil { - m.success <- successArgs{preimg} + m.success <- successArgs{settleInfo.Preimage} } delete(m.inflights, phash) @@ -310,3 +311,9 @@ func (m *mockControlTower) SubscribePayment(paymentHash lntypes.Hash) ( return false, nil, errors.New("not implemented") } + +func (m *mockControlTower) FailAttempt(hash lntypes.Hash, pid uint64, + failInfo *channeldb.HTLCFailInfo) error { + + return nil +} diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 13d59370cd..565262edd2 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -58,6 +58,13 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // the DB, we send it. sendErr := p.sendPaymentAttempt(firstHop, htlcAdd) if sendErr != nil { + // TODO(joostjager): Distinguish unexpected + // internal errors from real send errors. + err = p.failAttempt() + if err != nil { + return [32]byte{}, nil, err + } + // We must inspect the error to know whether it // was critical or not, to decide whether we // should continue trying. @@ -110,6 +117,11 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { "the Switch, retrying.", p.attempt.AttemptID, p.payment.PaymentHash) + err = p.failAttempt() + if err != nil { + return [32]byte{}, nil, err + } + // Reset the attempt to indicate we want to make a new // attempt. p.attempt = nil @@ -146,6 +158,11 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { log.Errorf("Attempt to send payment %x failed: %v", p.payment.PaymentHash, result.Error) + err = p.failAttempt() + if err != nil { + return [32]byte{}, nil, err + } + // We must inspect the error to know whether it was // critical or not, to decide whether we should // continue trying. @@ -174,7 +191,13 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // In case of success we atomically store the db payment and // move the payment to the success state. - err = p.router.cfg.Control.Success(p.payment.PaymentHash, result.Preimage) + err = p.router.cfg.Control.SettleAttempt( + p.payment.PaymentHash, p.attempt.AttemptID, + &channeldb.HTLCSettleInfo{ + Preimage: result.Preimage, + SettleTime: p.router.cfg.Clock.Now(), + }, + ) if err != nil { log.Errorf("Unable to succeed payment "+ "attempt: %v", err) @@ -339,9 +362,10 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, // We now have all the information needed to populate // the current attempt information. p.attempt = &channeldb.HTLCAttemptInfo{ - AttemptID: attemptID, - SessionKey: sessionKey, - Route: *rt, + AttemptID: attemptID, + AttemptTime: p.router.cfg.Clock.Now(), + SessionKey: sessionKey, + Route: *rt, } // Before sending this HTLC to the switch, we checkpoint the @@ -421,3 +445,15 @@ func (p *paymentLifecycle) handleSendError(sendErr error) error { // Terminal state, return the error we encountered. return sendErr } + +// failAttempt calls control tower to fail the current payment attempt. +func (p *paymentLifecycle) failAttempt() error { + failInfo := &channeldb.HTLCFailInfo{ + FailTime: p.router.cfg.Clock.Now(), + } + + return p.router.cfg.Control.FailAttempt( + p.payment.PaymentHash, p.attempt.AttemptID, + failInfo, + ) +} diff --git a/routing/router.go b/routing/router.go index a4b264e1bb..6751bfaea3 100644 --- a/routing/router.go +++ b/routing/router.go @@ -541,7 +541,14 @@ func (r *ChannelRouter) Start() error { PaymentHash: payment.Info.PaymentHash, } - _, _, err := r.sendPayment(payment.Attempt, lPayment, paySession) + // TODO(joostjager): For mpp, possibly relaunch multiple + // in-flight htlcs here. + var attempt *channeldb.HTLCAttemptInfo + if len(payment.Attempts) > 0 { + attempt = &payment.Attempts[0] + } + + _, _, err := r.sendPayment(attempt, lPayment, paySession) if err != nil { log.Errorf("Resuming payment with hash %v "+ "failed: %v.", payment.Info.PaymentHash, err) From f86e68a1a234c4456a29a3901b37ade6872e7654 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 20 Feb 2020 18:08:01 +0100 Subject: [PATCH 190/562] channeldb+routing: store full htlc failure reason This commit extends the htlc fail info with the full failure reason that was received over the wire. In a later commit, this info will also be exposed on the rpc interface. Furthermore it serves as a building block to make SendToRoute reliable across restarts. --- channeldb/mp_payment.go | 75 ++++++++++++++++++++++++++++++- channeldb/payment_control_test.go | 8 +++- routing/payment_lifecycle.go | 61 ++++++++++++++++++++++--- 3 files changed, 134 insertions(+), 10 deletions(-) diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index 7c5d97aee1..d46e590913 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -1,11 +1,14 @@ package channeldb import ( + "bytes" "io" "time" "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -57,11 +60,45 @@ type HTLCSettleInfo struct { SettleTime time.Time } +// HTLCFailReason is the reason an htlc failed. +type HTLCFailReason byte + +const ( + // HTLCFailUnknown is recorded for htlcs that failed with an unknown + // reason. + HTLCFailUnknown HTLCFailReason = 0 + + // HTLCFailUnknown is recorded for htlcs that had a failure message that + // couldn't be decrypted. + HTLCFailUnreadable HTLCFailReason = 1 + + // HTLCFailInternal is recorded for htlcs that failed because of an + // internal error. + HTLCFailInternal HTLCFailReason = 2 + + // HTLCFailMessage is recorded for htlcs that failed with a network + // failure message. + HTLCFailMessage HTLCFailReason = 3 +) + // HTLCFailInfo encapsulates the information that augments an HTLCAttempt in the // event that the HTLC fails. type HTLCFailInfo struct { // FailTime is the time at which this HTLC was failed. FailTime time.Time + + // Message is the wire message that failed this HTLC. This field will be + // populated when the failure reason is HTLCFailMessage. + Message lnwire.FailureMessage + + // Reason is the failure reason for this HTLC. + Reason HTLCFailReason + + // The position in the path of the intermediate or final node that + // generated the failure message. Position zero is the sender node. This + // field will be populated when the failure reason is either + // HTLCFailMessage or HTLCFailUnknown. + FailureSourceIndex uint32 } // MPPayment is a wrapper around a payment's PaymentCreationInfo and @@ -130,7 +167,20 @@ func serializeHTLCFailInfo(w io.Writer, f *HTLCFailInfo) error { return err } - return nil + // Write failure. If there is no failure message, write an empty + // byte slice. + var messageBytes bytes.Buffer + if f.Message != nil { + err := lnwire.EncodeFailureMessage(&messageBytes, f.Message, 0) + if err != nil { + return err + } + } + if err := wire.WriteVarBytes(w, 0, messageBytes.Bytes()); err != nil { + return err + } + + return WriteElements(w, byte(f.Reason), f.FailureSourceIndex) } // deserializeHTLCFailInfo deserializes the details of a failed htlc including @@ -143,6 +193,29 @@ func deserializeHTLCFailInfo(r io.Reader) (*HTLCFailInfo, error) { return nil, err } + // Read failure. + failureBytes, err := wire.ReadVarBytes( + r, 0, lnwire.FailureMessageLength, "failure", + ) + if err != nil { + return nil, err + } + if len(failureBytes) > 0 { + f.Message, err = lnwire.DecodeFailureMessage( + bytes.NewReader(failureBytes), 0, + ) + if err != nil { + return nil, err + } + } + + var reason byte + err = ReadElements(r, &reason, &f.FailureSourceIndex) + if err != nil { + return nil, err + } + f.Reason = HTLCFailReason(reason) + return f, nil } diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 7856cc1ac1..272de68c9b 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -126,7 +126,9 @@ func TestPaymentControlSwitchFail(t *testing.T) { } err = pControl.FailAttempt( - info.PaymentHash, 2, &HTLCFailInfo{}, + info.PaymentHash, 2, &HTLCFailInfo{ + Reason: HTLCFailUnreadable, + }, ) if err != nil { t.Fatal(err) @@ -362,7 +364,9 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { // Fail the payment attempt. err := pControl.FailAttempt( info.PaymentHash, attempt.AttemptID, - &HTLCFailInfo{}, + &HTLCFailInfo{ + Reason: HTLCFailUnreadable, + }, ) if err != nil { t.Fatalf("unable to fail htlc: %v", err) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 565262edd2..96441d179d 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -60,7 +60,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { if sendErr != nil { // TODO(joostjager): Distinguish unexpected // internal errors from real send errors. - err = p.failAttempt() + err = p.failAttempt(sendErr) if err != nil { return [32]byte{}, nil, err } @@ -117,7 +117,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { "the Switch, retrying.", p.attempt.AttemptID, p.payment.PaymentHash) - err = p.failAttempt() + err = p.failAttempt(err) if err != nil { return [32]byte{}, nil, err } @@ -158,7 +158,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { log.Errorf("Attempt to send payment %x failed: %v", p.payment.PaymentHash, result.Error) - err = p.failAttempt() + err = p.failAttempt(result.Error) if err != nil { return [32]byte{}, nil, err } @@ -447,13 +447,60 @@ func (p *paymentLifecycle) handleSendError(sendErr error) error { } // failAttempt calls control tower to fail the current payment attempt. -func (p *paymentLifecycle) failAttempt() error { - failInfo := &channeldb.HTLCFailInfo{ - FailTime: p.router.cfg.Clock.Now(), - } +func (p *paymentLifecycle) failAttempt(sendError error) error { + failInfo := marshallError( + sendError, + p.router.cfg.Clock.Now(), + ) return p.router.cfg.Control.FailAttempt( p.payment.PaymentHash, p.attempt.AttemptID, failInfo, ) } + +// marshallError marshall an error as received from the switch to a structure +// that is suitable for database storage. +func marshallError(sendError error, time time.Time) *channeldb.HTLCFailInfo { + response := &channeldb.HTLCFailInfo{ + FailTime: time, + } + + switch sendError { + + case htlcswitch.ErrPaymentIDNotFound: + response.Reason = channeldb.HTLCFailInternal + return response + + case htlcswitch.ErrUnreadableFailureMessage: + response.Reason = channeldb.HTLCFailUnreadable + return response + } + + rtErr, ok := sendError.(htlcswitch.ClearTextError) + if !ok { + response.Reason = channeldb.HTLCFailInternal + return response + } + + message := rtErr.WireMessage() + if message != nil { + response.Reason = channeldb.HTLCFailMessage + response.Message = message + } else { + response.Reason = channeldb.HTLCFailUnknown + } + + // If the ClearTextError received is a ForwardingError, the error + // originated from a node along the route, not locally on our outgoing + // link. We set failureSourceIdx to the index of the node where the + // failure occurred. If the error is not a ForwardingError, the failure + // occurred at our node, so we leave the index as 0 to indicate that + // we failed locally. + fErr, ok := rtErr.(*htlcswitch.ForwardingError) + if ok { + response.FailureSourceIndex = uint32(fErr.FailureSourceIdx) + } + + return response +} From 4cea2d5213d301e3f51f4b831f9f8b1dbe2031cb Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 24 Feb 2020 16:27:21 +0100 Subject: [PATCH 191/562] channeldb/migtest: add migration test tools This commit adds test helper code to dump, restore and verify the low-level bbolt database structure. --- channeldb/migtest/raw_db.go | 187 ++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 channeldb/migtest/raw_db.go diff --git a/channeldb/migtest/raw_db.go b/channeldb/migtest/raw_db.go new file mode 100644 index 0000000000..46dc417a85 --- /dev/null +++ b/channeldb/migtest/raw_db.go @@ -0,0 +1,187 @@ +package migtest + +import ( + "bytes" + "encoding/hex" + "errors" + "fmt" + "strings" + + "github.com/coreos/bbolt" +) + +// DumpDB dumps go code describing the contents of the database to stdout. This +// function is only intended for use during development. +// +// Example output: +// +// map[string]interface{}{ +// hex("1234"): map[string]interface{}{ +// "human-readable": hex("102030"), +// hex("1111"): hex("5783492373"), +// }, +// } +func DumpDB(tx *bbolt.Tx, rootKey []byte) error { + bucket := tx.Bucket(rootKey) + if bucket == nil { + return fmt.Errorf("bucket %v not found", string(rootKey)) + } + + return dumpBucket(bucket) +} + +func dumpBucket(bucket *bbolt.Bucket) error { + fmt.Printf("map[string]interface{} {\n") + err := bucket.ForEach(func(k, v []byte) error { + key := toString(k) + fmt.Printf("%v: ", key) + + subBucket := bucket.Bucket(k) + if subBucket != nil { + err := dumpBucket(subBucket) + if err != nil { + return err + } + } else { + fmt.Print(toHex(v)) + } + fmt.Printf(",\n") + + return nil + }) + if err != nil { + return err + } + fmt.Printf("}") + + return nil +} + +// RestoreDB primes the database with the given data set. +func RestoreDB(tx *bbolt.Tx, rootKey []byte, data map[string]interface{}) error { + bucket, err := tx.CreateBucket(rootKey) + if err != nil { + return err + } + + return restoreDB(bucket, data) +} + +func restoreDB(bucket *bbolt.Bucket, data map[string]interface{}) error { + for k, v := range data { + key := []byte(k) + + switch value := v.(type) { + + // Key contains value. + case string: + err := bucket.Put(key, []byte(value)) + if err != nil { + return err + } + + // Key contains a sub-bucket. + case map[string]interface{}: + subBucket, err := bucket.CreateBucket(key) + if err != nil { + return err + } + + if err := restoreDB(subBucket, value); err != nil { + return err + } + + default: + return errors.New("invalid type") + } + } + + return nil +} + +// VerifyDB verifies the database against the given data set. +func VerifyDB(tx *bbolt.Tx, rootKey []byte, data map[string]interface{}) error { + bucket := tx.Bucket(rootKey) + if bucket == nil { + return fmt.Errorf("bucket %v not found", string(rootKey)) + } + + return verifyDB(bucket, data) +} + +func verifyDB(bucket *bbolt.Bucket, data map[string]interface{}) error { + for k, v := range data { + key := []byte(k) + + switch value := v.(type) { + + // Key contains value. + case string: + expectedValue := []byte(value) + dbValue := bucket.Get(key) + + if !bytes.Equal(dbValue, expectedValue) { + return errors.New("value mismatch") + } + + // Key contains a sub-bucket. + case map[string]interface{}: + subBucket := bucket.Bucket(key) + if subBucket == nil { + return fmt.Errorf("bucket %v not found", k) + } + + err := verifyDB(subBucket, value) + if err != nil { + return err + } + + default: + return errors.New("invalid type") + } + } + + keyCount := 0 + err := bucket.ForEach(func(k, v []byte) error { + keyCount++ + return nil + }) + if err != nil { + return err + } + if keyCount != len(data) { + return errors.New("unexpected keys in database") + } + + return nil +} + +func toHex(v []byte) string { + if len(v) == 0 { + return "nil" + } + + return "hex(\"" + hex.EncodeToString(v) + "\")" +} + +func toString(v []byte) string { + readableChars := "abcdefghijklmnopqrstuvwxyz0123456789-" + + for _, c := range v { + if !strings.Contains(readableChars, string(c)) { + return toHex(v) + } + } + + return "\"" + string(v) + "\"" +} + +// Hex is a test helper function to convert readable hex arrays to raw byte +// strings. +func Hex(value string) string { + b, err := hex.DecodeString(value) + if err != nil { + panic(err) + } + return string(b) +} From 866623e84b24efe96664ad549723fa736227ac7b Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 20 Feb 2020 18:08:01 +0100 Subject: [PATCH 192/562] channeldb/migration13: migrate to mpp structure This commit migrates the payments in the database to a new structure that allows for multiple htlcs per payments. The migration introduces a new sub-bucket that contains a list of htlcs and moves the old single htlc into that. --- channeldb/db.go | 6 + channeldb/log.go | 2 + channeldb/migration13/log.go | 14 ++ channeldb/migration13/migration.go | 202 ++++++++++++++++++++++++ channeldb/migration13/migration_test.go | 123 +++++++++++++++ 5 files changed, 347 insertions(+) create mode 100644 channeldb/migration13/log.go create mode 100644 channeldb/migration13/migration.go create mode 100644 channeldb/migration13/migration_test.go diff --git a/channeldb/db.go b/channeldb/db.go index c1cf46ba80..cd4cd7568d 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -14,6 +14,7 @@ import ( "github.com/coreos/bbolt" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb/migration12" + "github.com/lightningnetwork/lnd/channeldb/migration13" "github.com/lightningnetwork/lnd/channeldb/migration_01_to_11" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lnwire" @@ -124,6 +125,11 @@ var ( number: 12, migration: migration12.MigrateInvoiceTLV, }, + { + // Migrate to multi-path payments. + number: 13, + migration: migration13.MigrateMPP, + }, } // Big endian is the preferred byte order, due to cursor scans over diff --git a/channeldb/log.go b/channeldb/log.go index 5229edbfbf..7490c6bf5f 100644 --- a/channeldb/log.go +++ b/channeldb/log.go @@ -4,6 +4,7 @@ import ( "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/channeldb/migration12" + "github.com/lightningnetwork/lnd/channeldb/migration13" "github.com/lightningnetwork/lnd/channeldb/migration_01_to_11" ) @@ -29,4 +30,5 @@ func UseLogger(logger btclog.Logger) { log = logger migration_01_to_11.UseLogger(logger) migration12.UseLogger(logger) + migration13.UseLogger(logger) } diff --git a/channeldb/migration13/log.go b/channeldb/migration13/log.go new file mode 100644 index 0000000000..33ec1812af --- /dev/null +++ b/channeldb/migration13/log.go @@ -0,0 +1,14 @@ +package migration13 + +import ( + "github.com/btcsuite/btclog" +) + +// log is a logger that is initialized as disabled. This means the package will +// not perform any logging by default until a logger is set. +var log = btclog.Disabled + +// UseLogger uses a specified Logger to output package logging info. +func UseLogger(logger btclog.Logger) { + log = logger +} diff --git a/channeldb/migration13/migration.go b/channeldb/migration13/migration.go new file mode 100644 index 0000000000..56fced62de --- /dev/null +++ b/channeldb/migration13/migration.go @@ -0,0 +1,202 @@ +package migration13 + +import ( + "encoding/binary" + "fmt" + + "github.com/coreos/bbolt" +) + +var ( + paymentsRootBucket = []byte("payments-root-bucket") + + // paymentCreationInfoKey is a key used in the payment's sub-bucket to + // store the creation info of the payment. + paymentCreationInfoKey = []byte("payment-creation-info") + + // paymentFailInfoKey is a key used in the payment's sub-bucket to + // store information about the reason a payment failed. + paymentFailInfoKey = []byte("payment-fail-info") + + // paymentAttemptInfoKey is a key used in the payment's sub-bucket to + // store the info about the latest attempt that was done for the + // payment in question. + paymentAttemptInfoKey = []byte("payment-attempt-info") + + // paymentSettleInfoKey is a key used in the payment's sub-bucket to + // store the settle info of the payment. + paymentSettleInfoKey = []byte("payment-settle-info") + + // paymentHtlcsBucket is a bucket where we'll store the information + // about the HTLCs that were attempted for a payment. + paymentHtlcsBucket = []byte("payment-htlcs-bucket") + + // htlcAttemptInfoKey is a key used in a HTLC's sub-bucket to store the + // info about the attempt that was done for the HTLC in question. + htlcAttemptInfoKey = []byte("htlc-attempt-info") + + // htlcSettleInfoKey is a key used in a HTLC's sub-bucket to store the + // settle info, if any. + htlcSettleInfoKey = []byte("htlc-settle-info") + + // htlcFailInfoKey is a key used in a HTLC's sub-bucket to store + // failure information, if any. + htlcFailInfoKey = []byte("htlc-fail-info") + + byteOrder = binary.BigEndian +) + +// MigrateMPP migrates the payments to a new structure that accommodates for mpp +// payments. +func MigrateMPP(tx *bbolt.Tx) error { + log.Infof("Migrating payments to mpp structure") + + // Iterate over all payments and store their indexing keys. This is + // needed, because no modifications are allowed inside a Bucket.ForEach + // loop. + paymentsBucket := tx.Bucket(paymentsRootBucket) + if paymentsBucket == nil { + return nil + } + + var paymentKeys [][]byte + err := paymentsBucket.ForEach(func(k, v []byte) error { + paymentKeys = append(paymentKeys, k) + return nil + }) + if err != nil { + return err + } + + // With all keys retrieved, start the migration. + for _, k := range paymentKeys { + bucket := paymentsBucket.Bucket(k) + + // We only expect sub-buckets to be found in + // this top-level bucket. + if bucket == nil { + return fmt.Errorf("non bucket element in " + + "payments bucket") + } + + // Fetch old format creation info. + creationInfo := bucket.Get(paymentCreationInfoKey) + if creationInfo == nil { + return fmt.Errorf("creation info not found") + } + + // Make a copy because bbolt doesn't allow this value to be + // changed in-place. + newCreationInfo := make([]byte, len(creationInfo)) + copy(newCreationInfo, creationInfo) + + // Convert to nano seconds. + timeBytes := newCreationInfo[32+8 : 32+8+8] + time := byteOrder.Uint64(timeBytes) + timeNs := time * 1000000000 + byteOrder.PutUint64(timeBytes, timeNs) + + // Write back new format creation info. + err := bucket.Put(paymentCreationInfoKey, newCreationInfo) + if err != nil { + return err + } + + // No migration needed if there is no attempt stored. + attemptInfo := bucket.Get(paymentAttemptInfoKey) + if attemptInfo == nil { + continue + } + + // Delete attempt info on the payment level. + if err := bucket.Delete(paymentAttemptInfoKey); err != nil { + return err + } + + // Save attempt id for later use. + attemptID := attemptInfo[:8] + + // Discard attempt id. It will become a bucket key in the new + // structure. + attemptInfo = attemptInfo[8:] + + // Append unknown (zero) attempt time. + var zero [8]byte + attemptInfo = append(attemptInfo, zero[:]...) + + // Create bucket that contains all htlcs. + htlcsBucket, err := bucket.CreateBucket(paymentHtlcsBucket) + if err != nil { + return err + } + + // Create an htlc for this attempt. + htlcBucket, err := htlcsBucket.CreateBucket(attemptID) + if err != nil { + return err + } + + // Save migrated attempt info. + err = htlcBucket.Put(htlcAttemptInfoKey, attemptInfo) + if err != nil { + return err + } + + // Migrate settle info. + settleInfo := bucket.Get(paymentSettleInfoKey) + if settleInfo != nil { + // Payment-level settle info can be deleted. + err := bucket.Delete(paymentSettleInfoKey) + if err != nil { + return err + } + + // Append unknown (zero) settle time. + settleInfo = append(settleInfo, zero[:]...) + + // Save settle info. + err = htlcBucket.Put(htlcSettleInfoKey, settleInfo) + if err != nil { + return err + } + + // Migration for settled htlc completed. + continue + } + + // If there is no payment-level failure reason, the payment is + // still in flight and nothing else needs to be migrated. + // Otherwise the payment-level failure reason can remain + // unchanged. + inFlight := bucket.Get(paymentFailInfoKey) == nil + if inFlight { + continue + } + + // The htlc failed. Add htlc fail info with reason unknown. We + // don't have access to the original failure reason anymore. + failInfo := []byte{ + // Fail time unknown. + 0, 0, 0, 0, 0, 0, 0, 0, + + // Zero length wire message. + 0, + + // Failure reason unknown. + 0, + + // Failure source index zero. + 0, 0, 0, 0, + } + + // Save fail info. + err = htlcBucket.Put(htlcFailInfoKey, failInfo) + if err != nil { + return err + } + } + + log.Infof("Migration of payments to mpp structure complete!") + + return nil +} diff --git a/channeldb/migration13/migration_test.go b/channeldb/migration13/migration_test.go new file mode 100644 index 0000000000..4b3e4f2c75 --- /dev/null +++ b/channeldb/migration13/migration_test.go @@ -0,0 +1,123 @@ +package migration13 + +import ( + "testing" + + "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/migtest" +) + +var ( + hex = migtest.Hex + + zeroTime = hex("0000000000000000") + noFailureMessage = hex("00") + failureReasonUnknown = hex("00") + zeroFailureSourceIdx = hex("00000000") + + hash1 = hex("02acee76ebd53d00824410cf6adecad4f50334dac702bd5a2d3ba01b91709f0e") + creationInfoAmt1 = hex("00000000004c4b40") + creationInfoTime1 = hex("000000005e4fb7ab") // 1582282667 (decimal) + creationInfoTimeNano1 = hex("15f565b3cccaee00") // 1582282667000000000 (decimal) + creationInfoPayReq1 = hex("00000000") + attemptInfo1 = hex("2997a72e129fc9d638ef2fa4e233567d808d4f18a4f087637582427962eb3bf800005ce600000000004c4b402102ec12e83eafe27ce6d03bbe0c0de4b79fe2b9934615c8aa7693f73d2e41b089700000000121028c2dd128c7a6c1a0fceb3e3eb5ed55e0a0ae1a939eb786b097322d830d47db75005ca4000001000000005ce600000000004c4b400000000000") + attemptID1 = hex("0000000000000001") + paymentID1 = hex("0000000000000001") + + hash2 = hex("62eb3f0a48f954e495d0c14ac63df04a67cefa59dafdbcd3d5046d1f5647840c") + preimage2 = hex("479593b7d3cbb45beb22d448451a2f3619b2095adfb38f4d92e9886e96534368") + attemptID2 = hex("00000000000003e8") + paymentID2 = hex("0000000000000002") + attemptInfo2 = hex("8de663f9bb4b8d1ebdb496d22dc1cb657a346215607308549f41b01e2adf2ce900005ce600000000005b8d802102ec12e83eafe27ce6d03bbe0c0de4b79fe2b9934615c8aa7693f73d2e41b089700000000121028c2dd128c7a6c1a0fceb3e3eb5ed55e0a0ae1a939eb786b097322d830d47db75005ca4000001000000005ce600000000005b8d8000000000010000000000000008233d281e2cbe01f0b82dd6750967c9233426b98ae6549c696365f57f86f942a3795b8d80") + creationInfoAmt2 = hex("00000000005b8d80") + creationInfoTime2 = hex("000000005e4fb97f") // 1582283135 (decimal) + creationInfoTimeNano2 = hex("15F56620C3C43600") // 1582283135000000000 (decimal) + creationInfoPayReq2 = hex("000000fc6c6e62637274363075317030796c7774367070357674346e377a6a676c39327766397773633939767630307366666e7561376a656d74376d6535373471336b3337346a387373787164717163717a70677370353835357075743937713863747374776b7735796b306a667278736e746e7a6878326a77786a636d3937346c636437327a3564757339717939717371653872336b3578733379367868667366366d6a6e706d717172306661797a677a63336a6b663571787a6c376866787a6666763578667a7679647564327275767974706571787072376868796830726a747574373033333274737774686661616e303773766b6667716b7174667275") + + hash3 = hex("62eb3f0a48f954e495d0c14ac63df04a67cefa59dafdbcd3d5046d1f5647840d") + attemptInfo3 = hex("53ce0a4c1507cc5ea00ec88b76bd43a3978ac13605497030b821af6ce9c110f300005ce600000000006acfc02102ec12e83eafe27ce6d03bbe0c0de4b79fe2b9934615c8aa7693f73d2e41b089700000000121028c2dd128c7a6c1a0fceb3e3eb5ed55e0a0ae1a939eb786b097322d830d47db75005ca4000001000000005ce600000000006acfc000000000010000000000000008233044f235354472318b381fad3e21eb5a58f5099918868b0610e7b7bcb7a4adc96acfc0") + attemptID3 = hex("00000000000003e9") + paymentID3 = hex("0000000000000003") + creationInfoAmt3 = hex("00000000006acfc0") + creationInfoTime3 = hex("000000005e4fb98d") // 1582283149 + creationInfoTimeNano3 = hex("15F56624063B4200") // 1582283149000000000 (decimal) + creationInfoPayReq3 = hex("000000fc6c6e62637274373075317030796c7776327070357674346e377a6a676c39327766397773633939767630307366666e7561376a656d74376d6535373471336b3337346a387373787364717163717a706773703578707a307964663467336572727a656372376b6e7567307474667630327a7665727a72676b70737375376d6d6564617934687973397179397173717774656479336e666c323534787a36787a75763974746767757a647473356e617a7461616a6735667772686438396b336d70753971726d7a6c3779637a306e30666e6e763077753032726632706e64636c393761646c667636376a7a6e7063677477356434366771323571326e32") + + // pre is the data in the payments root bucket in database version 12 format. + pre = map[string]interface{}{ + // A failed payment. + hash1: map[string]interface{}{ + "payment-attempt-info": attemptID1 + attemptInfo1, + "payment-creation-info": hash1 + creationInfoAmt1 + creationInfoTime1 + creationInfoPayReq1, + "payment-fail-info": hex("03"), + "payment-sequence-key": paymentID1, + }, + + // A settled payment. + hash2: map[string]interface{}{ + "payment-attempt-info": attemptID2 + attemptInfo2, + "payment-creation-info": hash2 + creationInfoAmt2 + creationInfoTime2 + creationInfoPayReq2, + "payment-sequence-key": paymentID2, + "payment-settle-info": preimage2, + }, + + // An in-flight payment. + hash3: map[string]interface{}{ + "payment-attempt-info": attemptID3 + attemptInfo3, + "payment-creation-info": hash3 + creationInfoAmt3 + creationInfoTime3 + creationInfoPayReq3, + "payment-sequence-key": paymentID3, + }, + } + + // post is the expected data after migration. + post = map[string]interface{}{ + hash1: map[string]interface{}{ + "payment-creation-info": hash1 + creationInfoAmt1 + creationInfoTimeNano1 + creationInfoPayReq1, + "payment-fail-info": hex("03"), + "payment-htlcs-bucket": map[string]interface{}{ + attemptID1: map[string]interface{}{ + "htlc-attempt-info": attemptInfo1 + zeroTime, + "htlc-fail-info": zeroTime + noFailureMessage + failureReasonUnknown + zeroFailureSourceIdx, + }, + }, + "payment-sequence-key": paymentID1, + }, + hash2: map[string]interface{}{ + "payment-creation-info": hash2 + creationInfoAmt2 + creationInfoTimeNano2 + creationInfoPayReq2, + "payment-htlcs-bucket": map[string]interface{}{ + attemptID2: map[string]interface{}{ + "htlc-attempt-info": attemptInfo2 + zeroTime, + "htlc-settle-info": preimage2 + zeroTime, + }, + }, + "payment-sequence-key": paymentID2, + }, + hash3: map[string]interface{}{ + "payment-creation-info": hash3 + creationInfoAmt3 + creationInfoTimeNano3 + creationInfoPayReq3, + "payment-htlcs-bucket": map[string]interface{}{ + attemptID3: map[string]interface{}{ + "htlc-attempt-info": attemptInfo3 + zeroTime, + }, + }, + "payment-sequence-key": paymentID3, + }, + } +) + +// TestMigrateMpp asserts that the database is properly migrated to the mpp +// payment structure. +func TestMigrateMpp(t *testing.T) { + var paymentsRootBucket = []byte("payments-root-bucket") + + migtest.ApplyMigration( + t, + func(tx *bbolt.Tx) error { + return migtest.RestoreDB(tx, paymentsRootBucket, pre) + }, + func(tx *bbolt.Tx) error { + return migtest.VerifyDB(tx, paymentsRootBucket, post) + }, + MigrateMPP, + false, + ) +} From c0cb05d7b45034ce3cbb485c935e020e9ec9ce9a Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 19 Feb 2020 17:21:03 +0100 Subject: [PATCH 193/562] lnrpc: expose raw htlc failure Adds a new rpc field to the payment htlc proto message and populates it with data that is now stored in the db. --- lnrpc/routerrpc/router_backend.go | 73 +- lnrpc/rpc.pb.go | 1406 +++++++++++++++-------------- lnrpc/rpc.proto | 8 + lnrpc/rpc.swagger.json | 146 +++ 4 files changed, 920 insertions(+), 713 deletions(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index e8957afa9a..120211b1ed 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -844,35 +844,72 @@ func UnmarshalMPP(reqMPP *lnrpc.MPPRecord) (*record.MPP, error) { func (r *RouterBackend) MarshalHTLCAttempt( htlc channeldb.HTLCAttempt) (*lnrpc.HTLCAttempt, error) { - var ( - status lnrpc.HTLCAttempt_HTLCStatus - resolveTime int64 - ) + route, err := r.MarshallRoute(&htlc.Route) + if err != nil { + return nil, err + } + + rpcAttempt := &lnrpc.HTLCAttempt{ + AttemptTimeNs: MarshalTimeNano(htlc.AttemptTime), + Route: route, + } switch { case htlc.Settle != nil: - status = lnrpc.HTLCAttempt_SUCCEEDED - resolveTime = MarshalTimeNano(htlc.Settle.SettleTime) + rpcAttempt.Status = lnrpc.HTLCAttempt_SUCCEEDED + rpcAttempt.ResolveTimeNs = MarshalTimeNano( + htlc.Settle.SettleTime, + ) case htlc.Failure != nil: - status = lnrpc.HTLCAttempt_FAILED - resolveTime = MarshalTimeNano(htlc.Failure.FailTime) + rpcAttempt.Status = lnrpc.HTLCAttempt_FAILED + rpcAttempt.ResolveTimeNs = MarshalTimeNano( + htlc.Failure.FailTime, + ) + var err error + rpcAttempt.Failure, err = marshallHtlcFailure(htlc.Failure) + if err != nil { + return nil, err + } default: - status = lnrpc.HTLCAttempt_IN_FLIGHT + rpcAttempt.Status = lnrpc.HTLCAttempt_IN_FLIGHT } - route, err := r.MarshallRoute(&htlc.Route) - if err != nil { - return nil, err + return rpcAttempt, nil +} + +// marshallHtlcFailure marshalls htlc fail info from the database to its rpc +// representation. +func marshallHtlcFailure(failure *channeldb.HTLCFailInfo) (*lnrpc.Failure, + error) { + + rpcFailure := &lnrpc.Failure{ + FailureSourceIndex: failure.FailureSourceIndex, } - return &lnrpc.HTLCAttempt{ - Status: status, - Route: route, - AttemptTimeNs: MarshalTimeNano(htlc.AttemptTime), - ResolveTimeNs: resolveTime, - }, nil + switch failure.Reason { + + case channeldb.HTLCFailUnknown: + rpcFailure.Code = lnrpc.Failure_UNKNOWN_FAILURE + + case channeldb.HTLCFailUnreadable: + rpcFailure.Code = lnrpc.Failure_UNREADABLE_FAILURE + + case channeldb.HTLCFailInternal: + rpcFailure.Code = lnrpc.Failure_INTERNAL_FAILURE + + case channeldb.HTLCFailMessage: + err := marshallWireError(failure.Message, rpcFailure) + if err != nil { + return nil, err + } + + default: + return nil, errors.New("unknown htlc failure reason") + } + + return rpcFailure, nil } // MarshalTimeNano converts a time.Time into its nanosecond representation. If diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 0da66bfdfe..905f465a5e 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -440,6 +440,9 @@ const ( Failure_EXPIRY_TOO_FAR Failure_FailureCode = 22 Failure_MPP_TIMEOUT Failure_FailureCode = 23 //* + //An internal error occurred. + Failure_INTERNAL_FAILURE Failure_FailureCode = 997 + //* //The error source is known, but the failure itself couldn't be decoded. Failure_UNKNOWN_FAILURE Failure_FailureCode = 998 //* @@ -473,6 +476,7 @@ var Failure_FailureCode_name = map[int32]string{ 21: "PERMANENT_CHANNEL_FAILURE", 22: "EXPIRY_TOO_FAR", 23: "MPP_TIMEOUT", + 997: "INTERNAL_FAILURE", 998: "UNKNOWN_FAILURE", 999: "UNREADABLE_FAILURE", } @@ -502,6 +506,7 @@ var Failure_FailureCode_value = map[string]int32{ "PERMANENT_CHANNEL_FAILURE": 21, "EXPIRY_TOO_FAR": 22, "MPP_TIMEOUT": 23, + "INTERNAL_FAILURE": 997, "UNKNOWN_FAILURE": 998, "UNREADABLE_FAILURE": 999, } @@ -8843,7 +8848,9 @@ type HTLCAttempt struct { //* //The time in UNIX nanoseconds at which this HTLC was settled or failed. //This value will not be set if the HTLC is still IN_FLIGHT. - ResolveTimeNs int64 `protobuf:"varint,4,opt,name=resolve_time_ns,json=resolveTimeNs,proto3" json:"resolve_time_ns,omitempty"` + ResolveTimeNs int64 `protobuf:"varint,4,opt,name=resolve_time_ns,json=resolveTimeNs,proto3" json:"resolve_time_ns,omitempty"` + // Detailed htlc failure info. + Failure *Failure `protobuf:"bytes,5,opt,name=failure,proto3" json:"failure,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -8902,6 +8909,13 @@ func (m *HTLCAttempt) GetResolveTimeNs() int64 { return 0 } +func (m *HTLCAttempt) GetFailure() *Failure { + if m != nil { + return m.Failure + } + return nil +} + type ListPaymentsRequest struct { //* //If true, then return payments that have not yet fully completed. This means @@ -11034,700 +11048,702 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11084 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x1b, 0x57, - 0x96, 0x98, 0xf8, 0x6a, 0x92, 0x87, 0x8f, 0x66, 0xdf, 0x7e, 0x51, 0x2d, 0xc9, 0x92, 0xcb, 0x1e, - 0x4b, 0x96, 0x6d, 0x49, 0xd6, 0xf8, 0xb5, 0x76, 0x32, 0xbb, 0xec, 0x6e, 0xb6, 0x9a, 0xa3, 0x7e, - 0xb9, 0xc8, 0xb6, 0xc7, 0x33, 0xd9, 0xd4, 0x54, 0x93, 0xb7, 0xbb, 0x6b, 0x45, 0x56, 0xd1, 0x55, - 0xc5, 0x7e, 0x8c, 0xe1, 0x7c, 0xc8, 0x63, 0x11, 0x24, 0x41, 0x80, 0x45, 0xb2, 0x01, 0xb2, 0xc9, - 0x22, 0x41, 0x82, 0x20, 0x08, 0x12, 0x2c, 0x36, 0x98, 0x0d, 0x90, 0x0f, 0xc9, 0xe7, 0xfd, 0x92, - 0x60, 0x3f, 0x6c, 0xf2, 0x25, 0x18, 0x2c, 0xb0, 0xc8, 0x62, 0xf2, 0x75, 0x7f, 0x41, 0x10, 0xdc, - 0x73, 0xee, 0xad, 0xba, 0x45, 0x56, 0x4b, 0xb2, 0x67, 0x32, 0x5f, 0xa4, 0xae, 0x73, 0xce, 0x7d, - 0x9f, 0x7b, 0xee, 0x79, 0xdd, 0x4b, 0x28, 0xfb, 0xe3, 0xfe, 0x83, 0xb1, 0xef, 0x85, 0x1e, 0x2b, - 0x0c, 0x5d, 0x7f, 0xdc, 0x5f, 0xbb, 0x79, 0xe2, 0x79, 0x27, 0x43, 0xfe, 0xd0, 0x1e, 0x3b, 0x0f, - 0x6d, 0xd7, 0xf5, 0x42, 0x3b, 0x74, 0x3c, 0x37, 0x20, 0x22, 0xe3, 0xc7, 0x50, 0x7f, 0xc2, 0xdd, - 0x2e, 0xe7, 0x03, 0x93, 0x7f, 0x39, 0xe1, 0x41, 0xc8, 0xde, 0x82, 0x05, 0x9b, 0xff, 0x84, 0xf3, - 0x81, 0x35, 0xb6, 0x83, 0x60, 0x7c, 0xea, 0xdb, 0x01, 0x6f, 0x66, 0xee, 0x64, 0xee, 0x55, 0xcd, - 0x06, 0x21, 0x0e, 0x22, 0x38, 0x7b, 0x15, 0xaa, 0x81, 0x20, 0xe5, 0x6e, 0xe8, 0x7b, 0xe3, 0xcb, - 0x66, 0x16, 0xe9, 0x2a, 0x02, 0xd6, 0x26, 0x90, 0x31, 0x84, 0xf9, 0xa8, 0x85, 0x60, 0xec, 0xb9, - 0x01, 0x67, 0x8f, 0x60, 0xa9, 0xef, 0x8c, 0x4f, 0xb9, 0x6f, 0x61, 0xe1, 0x91, 0xcb, 0x47, 0x9e, - 0xeb, 0xf4, 0x9b, 0x99, 0x3b, 0xb9, 0x7b, 0x65, 0x93, 0x11, 0x4e, 0x94, 0xd8, 0x95, 0x18, 0x76, - 0x17, 0xe6, 0xb9, 0x4b, 0x70, 0x3e, 0xc0, 0x52, 0xb2, 0xa9, 0x7a, 0x0c, 0x16, 0x05, 0x8c, 0xbf, - 0x9b, 0x85, 0x85, 0x8e, 0xeb, 0x84, 0x9f, 0xdb, 0xc3, 0x21, 0x0f, 0xd5, 0x98, 0xee, 0xc2, 0xfc, - 0x39, 0x02, 0x70, 0x4c, 0xe7, 0x9e, 0x3f, 0x90, 0x23, 0xaa, 0x13, 0xf8, 0x40, 0x42, 0xaf, 0xec, - 0x59, 0xf6, 0xca, 0x9e, 0xa5, 0x4e, 0x57, 0xee, 0x8a, 0xe9, 0xba, 0x0b, 0xf3, 0x3e, 0xef, 0x7b, - 0x67, 0xdc, 0xbf, 0xb4, 0xce, 0x1d, 0x77, 0xe0, 0x9d, 0x37, 0xf3, 0x77, 0x32, 0xf7, 0x0a, 0x66, - 0x5d, 0x81, 0x3f, 0x47, 0x28, 0x5b, 0x87, 0xf9, 0xfe, 0xa9, 0xed, 0xba, 0x7c, 0x68, 0x1d, 0xd9, - 0xfd, 0x67, 0x93, 0x71, 0xd0, 0x2c, 0xdc, 0xc9, 0xdc, 0xab, 0x3c, 0xbe, 0xfe, 0x00, 0x57, 0xf5, - 0xc1, 0xc6, 0xa9, 0xed, 0xae, 0x23, 0xa6, 0xeb, 0xda, 0xe3, 0xe0, 0xd4, 0x0b, 0xcd, 0xba, 0x2c, - 0x41, 0xe0, 0xc0, 0x58, 0x02, 0xa6, 0xcf, 0x04, 0xcd, 0xbd, 0xf1, 0xef, 0x33, 0xb0, 0x78, 0xe8, - 0x0e, 0xbd, 0xfe, 0xb3, 0x6f, 0x39, 0x45, 0x29, 0x63, 0xc8, 0xbe, 0xec, 0x18, 0x72, 0xdf, 0x74, - 0x0c, 0x2b, 0xb0, 0x94, 0xec, 0xac, 0x1c, 0x05, 0x87, 0x65, 0x51, 0xfa, 0x84, 0xab, 0x6e, 0xa9, - 0x61, 0xbc, 0x09, 0x8d, 0xfe, 0xc4, 0xf7, 0xb9, 0x3b, 0x33, 0x8e, 0x79, 0x09, 0x8f, 0x06, 0xf2, - 0x2a, 0x54, 0x5d, 0x7e, 0x1e, 0x93, 0x49, 0xde, 0x75, 0xf9, 0xb9, 0x22, 0x31, 0x9a, 0xb0, 0x32, - 0xdd, 0x8c, 0xec, 0xc0, 0xcf, 0x33, 0x90, 0x3f, 0x0c, 0x2f, 0x3c, 0xf6, 0x3e, 0x54, 0xed, 0xc1, - 0xc0, 0xe7, 0x41, 0x60, 0x85, 0x97, 0x63, 0xda, 0x29, 0xf5, 0xc7, 0x4c, 0x0e, 0xb1, 0x45, 0xa8, - 0xde, 0xe5, 0x98, 0x9b, 0x15, 0x3b, 0xfe, 0x60, 0x4d, 0x28, 0xca, 0x4f, 0x6c, 0xb7, 0x6c, 0xaa, - 0x4f, 0x76, 0x0b, 0xc0, 0x1e, 0x79, 0x13, 0x37, 0xb4, 0x02, 0x3b, 0xc4, 0x19, 0xcb, 0x99, 0x65, - 0x82, 0x74, 0xed, 0x90, 0xdd, 0x80, 0xf2, 0xf8, 0x99, 0x15, 0xf4, 0x7d, 0x67, 0x1c, 0x22, 0xf3, - 0x94, 0xcd, 0xd2, 0xf8, 0x59, 0x17, 0xbf, 0xd9, 0x5b, 0x50, 0xf2, 0x26, 0xe1, 0xd8, 0x73, 0xdc, - 0x50, 0xf2, 0xcb, 0xbc, 0xec, 0xc8, 0xfe, 0x24, 0x3c, 0x10, 0x60, 0x33, 0x22, 0x60, 0xaf, 0x43, - 0xad, 0xef, 0xb9, 0xc7, 0x8e, 0x3f, 0x22, 0x89, 0xd0, 0x9c, 0xc3, 0xb6, 0x92, 0x40, 0xe3, 0x0f, - 0xb3, 0x50, 0xe9, 0xf9, 0xb6, 0x1b, 0xd8, 0x7d, 0x01, 0x60, 0xab, 0x50, 0x0c, 0x2f, 0xac, 0x53, - 0x3b, 0x38, 0xc5, 0xa1, 0x96, 0xcd, 0xb9, 0xf0, 0x62, 0xdb, 0x0e, 0x4e, 0xd9, 0x0a, 0xcc, 0x51, - 0x2f, 0x71, 0x40, 0x39, 0x53, 0x7e, 0x89, 0x0d, 0xe2, 0x4e, 0x46, 0x56, 0xb2, 0xa9, 0x1c, 0x72, - 0x4c, 0xc3, 0x9d, 0x8c, 0x36, 0x74, 0xb8, 0x18, 0xfc, 0x91, 0x58, 0x6e, 0x6a, 0x80, 0x86, 0x57, - 0x46, 0x08, 0xb6, 0xf1, 0x2a, 0x54, 0x25, 0x9a, 0x3b, 0x27, 0xa7, 0x34, 0xc6, 0x82, 0x59, 0x21, - 0x02, 0x04, 0x89, 0x1a, 0x42, 0x67, 0xc4, 0xad, 0x20, 0xb4, 0x47, 0x63, 0x39, 0xa4, 0xb2, 0x80, - 0x74, 0x05, 0x00, 0xd1, 0x5e, 0x68, 0x0f, 0xad, 0x63, 0xce, 0x83, 0x66, 0x51, 0xa2, 0x05, 0x64, - 0x8b, 0xf3, 0x80, 0x7d, 0x07, 0xea, 0x03, 0x1e, 0x84, 0x96, 0x5c, 0x0c, 0x1e, 0x34, 0x4b, 0xb8, - 0xf3, 0x6b, 0x02, 0xda, 0x52, 0x40, 0x76, 0x13, 0xc0, 0xb7, 0xcf, 0x2d, 0x31, 0x11, 0xfc, 0xa2, - 0x59, 0xa6, 0x55, 0xf0, 0xed, 0xf3, 0xde, 0xc5, 0x36, 0xbf, 0x10, 0x5c, 0xf3, 0x84, 0x87, 0xda, - 0xa4, 0x05, 0x92, 0x3b, 0x8d, 0x1d, 0x60, 0x1a, 0x78, 0x93, 0x87, 0xb6, 0x33, 0x0c, 0xd8, 0x07, - 0x50, 0x0d, 0x35, 0x62, 0x14, 0x83, 0x95, 0x88, 0x85, 0xb4, 0x02, 0x66, 0x82, 0xce, 0x38, 0x85, - 0xd2, 0x16, 0xe7, 0x3b, 0xce, 0xc8, 0x09, 0xd9, 0x0a, 0x14, 0x8e, 0x9d, 0x0b, 0x4e, 0xcc, 0x9e, - 0xdb, 0xbe, 0x66, 0xd2, 0x27, 0xbb, 0x0d, 0x80, 0x7f, 0x58, 0xa3, 0x88, 0x9b, 0xb6, 0xaf, 0x99, - 0x65, 0x84, 0xed, 0x06, 0x76, 0xc8, 0xd6, 0xa0, 0x38, 0xe6, 0x7e, 0x9f, 0xab, 0x75, 0xdb, 0xbe, - 0x66, 0x2a, 0xc0, 0x7a, 0x11, 0x0a, 0x43, 0x51, 0xbb, 0xf1, 0xc7, 0x05, 0xa8, 0x74, 0xb9, 0x1b, - 0xed, 0x32, 0x06, 0x79, 0x31, 0x21, 0x72, 0x67, 0xe1, 0xdf, 0xec, 0x35, 0xa8, 0xe0, 0xd4, 0x05, - 0xa1, 0xef, 0xb8, 0x27, 0xc4, 0xd5, 0xeb, 0xd9, 0x66, 0xc6, 0x04, 0x01, 0xee, 0x22, 0x94, 0x35, - 0x20, 0x67, 0x8f, 0x14, 0x57, 0x8b, 0x3f, 0xd9, 0x75, 0x28, 0xd9, 0xa3, 0x90, 0xba, 0x57, 0x45, - 0x70, 0xd1, 0x1e, 0x85, 0xd8, 0xb5, 0x57, 0xa1, 0x3a, 0xb6, 0x2f, 0x47, 0x62, 0x2f, 0x47, 0xec, - 0x50, 0x35, 0x2b, 0x12, 0x86, 0x0c, 0xf1, 0x18, 0x16, 0x75, 0x12, 0xd5, 0x78, 0x21, 0x6a, 0x7c, - 0x41, 0xa3, 0x96, 0x7d, 0xb8, 0x0b, 0xf3, 0xaa, 0x8c, 0x4f, 0xe3, 0x41, 0x36, 0x29, 0x9b, 0x75, - 0x09, 0x56, 0xa3, 0xbc, 0x07, 0x8d, 0x63, 0xc7, 0xb5, 0x87, 0x56, 0x7f, 0x18, 0x9e, 0x59, 0x03, - 0x3e, 0x0c, 0x6d, 0xe4, 0x98, 0x82, 0x59, 0x47, 0xf8, 0xc6, 0x30, 0x3c, 0xdb, 0x14, 0x50, 0xf6, - 0x36, 0x94, 0x8f, 0x39, 0xb7, 0x70, 0xb2, 0x9a, 0xa5, 0xc4, 0xc6, 0x53, 0x2b, 0x64, 0x96, 0x8e, - 0xd5, 0x5a, 0xbd, 0x0d, 0x0d, 0x6f, 0x12, 0x9e, 0x78, 0x8e, 0x7b, 0x62, 0x09, 0x79, 0x67, 0x39, - 0x03, 0xe4, 0xa1, 0xfc, 0x7a, 0xf6, 0x51, 0xc6, 0xac, 0x2b, 0x9c, 0x90, 0x3c, 0x9d, 0x01, 0x7b, - 0x03, 0xe6, 0x87, 0x76, 0x10, 0x5a, 0xa7, 0xde, 0xd8, 0x1a, 0x4f, 0x8e, 0x9e, 0xf1, 0xcb, 0x66, - 0x0d, 0x27, 0xa2, 0x26, 0xc0, 0xdb, 0xde, 0xf8, 0x00, 0x81, 0x82, 0xb3, 0xb1, 0x9f, 0xd4, 0x09, - 0xb8, 0x93, 0xb9, 0x57, 0x33, 0xcb, 0x02, 0x42, 0x8d, 0x7e, 0x01, 0x8b, 0xb8, 0x3c, 0xfd, 0x49, - 0x10, 0x7a, 0x23, 0x4b, 0xc8, 0x6a, 0x7f, 0x10, 0x34, 0x2b, 0xc8, 0x6b, 0x6f, 0xca, 0xce, 0x6a, - 0x6b, 0xfc, 0x60, 0x93, 0x07, 0xe1, 0x06, 0x12, 0x9b, 0x44, 0x2b, 0x0e, 0xf4, 0x4b, 0x73, 0x61, - 0x30, 0x0d, 0x67, 0x6f, 0x03, 0xb3, 0x87, 0x43, 0xef, 0xdc, 0x0a, 0xf8, 0xf0, 0xd8, 0x92, 0x93, - 0xd8, 0xac, 0xdf, 0xc9, 0xdc, 0x2b, 0x99, 0x0d, 0xc4, 0x74, 0xf9, 0xf0, 0xf8, 0x80, 0xe0, 0xec, - 0x03, 0xc0, 0xcd, 0x64, 0x1d, 0x73, 0x3b, 0x9c, 0xf8, 0x3c, 0x68, 0xce, 0xdf, 0xc9, 0xdd, 0xab, - 0x3f, 0x5e, 0x88, 0xe6, 0x0b, 0xc1, 0xeb, 0x4e, 0x68, 0x56, 0x05, 0x9d, 0xfc, 0x0e, 0xd6, 0x36, - 0x61, 0x25, 0xbd, 0x4b, 0x82, 0xa9, 0xc4, 0xac, 0x08, 0x66, 0xcc, 0x9b, 0xe2, 0x4f, 0xb6, 0x04, - 0x85, 0x33, 0x7b, 0x38, 0xe1, 0x52, 0xa6, 0xd3, 0xc7, 0xc7, 0xd9, 0x8f, 0x32, 0xc6, 0x1f, 0x65, - 0xa0, 0x4a, 0xa3, 0x94, 0xba, 0xc8, 0x6b, 0x50, 0x53, 0xdc, 0xc0, 0x7d, 0xdf, 0xf3, 0xa5, 0x54, - 0x53, 0x9c, 0xd7, 0x16, 0x30, 0x71, 0xaa, 0x28, 0xa2, 0xb1, 0xcf, 0x9d, 0x91, 0x7d, 0xa2, 0xaa, - 0x56, 0xac, 0x74, 0x20, 0xc1, 0xec, 0xdd, 0xb8, 0x3e, 0xdf, 0x9b, 0x84, 0x5c, 0x9e, 0x79, 0x55, - 0x39, 0x3c, 0x53, 0xc0, 0xa2, 0xda, 0xf1, 0xeb, 0x25, 0xf8, 0xdc, 0xf8, 0xdd, 0x0c, 0x30, 0xd1, - 0xed, 0x9e, 0x47, 0x15, 0x48, 0x0e, 0x9d, 0x2e, 0x99, 0x79, 0xe9, 0x1d, 0x92, 0x7d, 0xde, 0x0e, - 0x31, 0xa0, 0x40, 0x7d, 0xcf, 0xa7, 0xf4, 0x9d, 0x50, 0xdf, 0xcf, 0x97, 0x72, 0x8d, 0xbc, 0xf1, - 0xbf, 0x72, 0xb0, 0xb4, 0x41, 0x47, 0x76, 0xab, 0xdf, 0xe7, 0xe3, 0x68, 0xef, 0xdc, 0x86, 0x8a, - 0xeb, 0x0d, 0xb8, 0xe2, 0x58, 0xea, 0x18, 0x08, 0x90, 0xc6, 0xae, 0xa7, 0xb6, 0xe3, 0x52, 0xc7, - 0x69, 0x32, 0xcb, 0x08, 0xc1, 0x6e, 0xbf, 0x01, 0xf3, 0x63, 0xee, 0x0e, 0xf4, 0x2d, 0x42, 0x4a, - 0x55, 0x4d, 0x82, 0xe5, 0xee, 0xb8, 0x0d, 0x95, 0xe3, 0x09, 0xd1, 0x09, 0xc1, 0x92, 0x47, 0x1e, - 0x00, 0x09, 0x6a, 0x91, 0x7c, 0x19, 0x4f, 0x82, 0x53, 0xc4, 0x16, 0x10, 0x5b, 0x14, 0xdf, 0x02, - 0x75, 0x0b, 0x60, 0x30, 0x09, 0x42, 0xb9, 0x63, 0xe6, 0x10, 0x59, 0x16, 0x10, 0xda, 0x31, 0xef, - 0xc0, 0xe2, 0xc8, 0xbe, 0xb0, 0x90, 0x77, 0x2c, 0xc7, 0xb5, 0x8e, 0x87, 0x78, 0xe6, 0x14, 0x91, - 0xae, 0x31, 0xb2, 0x2f, 0x3e, 0x13, 0x98, 0x8e, 0xbb, 0x85, 0x70, 0x21, 0x56, 0x94, 0xba, 0xe3, - 0xf3, 0x80, 0xfb, 0x67, 0x1c, 0x25, 0x41, 0x3e, 0xd2, 0x69, 0x4c, 0x82, 0x8a, 0x1e, 0x8d, 0xc4, - 0xb8, 0xc3, 0x61, 0x9f, 0xb6, 0xbd, 0x59, 0x1c, 0x39, 0xee, 0x76, 0x38, 0xec, 0x8b, 0x73, 0x45, - 0xc8, 0x91, 0x31, 0xf7, 0xad, 0x67, 0xe7, 0xb8, 0x87, 0xf3, 0x28, 0x37, 0x0e, 0xb8, 0xff, 0xf4, - 0x5c, 0x1c, 0xfd, 0xfd, 0x00, 0x05, 0x91, 0x7d, 0xd9, 0xac, 0xe0, 0x06, 0x2f, 0xf5, 0x03, 0x21, - 0x82, 0xec, 0x4b, 0xb1, 0x09, 0x45, 0x6f, 0x6d, 0x5c, 0x05, 0x3e, 0xc0, 0xea, 0x03, 0x94, 0xa8, - 0x35, 0xec, 0x6c, 0x4b, 0x22, 0x44, 0x3b, 0x81, 0xe0, 0x7a, 0xd5, 0xd9, 0xe3, 0xa1, 0x7d, 0x12, - 0xa0, 0x48, 0xa9, 0x99, 0x55, 0x09, 0xdc, 0x12, 0x30, 0xe3, 0x73, 0x52, 0xb2, 0xb4, 0xb5, 0x95, - 0x7b, 0x46, 0x1c, 0xf5, 0x08, 0xc1, 0x75, 0x2d, 0x99, 0xf2, 0x2b, 0x6d, 0xd1, 0xb2, 0x29, 0x8b, - 0x66, 0xfc, 0x7e, 0x06, 0xaa, 0xb2, 0x66, 0x54, 0x4a, 0xd8, 0x03, 0x60, 0x6a, 0x15, 0xc3, 0x0b, - 0x67, 0x60, 0x1d, 0x5d, 0x86, 0x3c, 0x20, 0xa6, 0xd9, 0xbe, 0x66, 0x36, 0x24, 0xae, 0x77, 0xe1, - 0x0c, 0xd6, 0x05, 0x86, 0xdd, 0x87, 0x46, 0x82, 0x3e, 0x08, 0x7d, 0xe2, 0xe8, 0xed, 0x6b, 0x66, - 0x5d, 0xa3, 0xee, 0x86, 0xbe, 0xd8, 0x23, 0x42, 0xe5, 0x99, 0x84, 0x96, 0xe3, 0x0e, 0xf8, 0x05, - 0xb2, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x23, 0x40, 0xeb, 0x75, 0xa8, 0xea, 0xd5, 0x19, 0x27, 0x50, - 0x52, 0xfa, 0x12, 0x2a, 0x0c, 0x53, 0x5d, 0x32, 0xcb, 0x61, 0xd4, 0x93, 0xeb, 0x50, 0x4a, 0xf6, - 0xc0, 0x2c, 0x86, 0x2f, 0xdd, 0xb0, 0xf1, 0x3d, 0x68, 0xec, 0x08, 0xe6, 0x71, 0x05, 0xb3, 0x4a, - 0xfd, 0x6f, 0x05, 0xe6, 0xb4, 0x4d, 0x53, 0x36, 0xe5, 0x97, 0x38, 0x73, 0x4f, 0xbd, 0x20, 0x94, - 0xad, 0xe0, 0xdf, 0xc6, 0x1f, 0x67, 0x80, 0xb5, 0x83, 0xd0, 0x19, 0xd9, 0x21, 0xdf, 0xe2, 0x91, - 0x58, 0xd8, 0x87, 0xaa, 0xa8, 0xad, 0xe7, 0xb5, 0x48, 0x21, 0x23, 0x85, 0xe2, 0x2d, 0xb9, 0x8d, - 0x67, 0x0b, 0x3c, 0xd0, 0xa9, 0x49, 0xcc, 0x27, 0x2a, 0x10, 0xbb, 0x2c, 0xb4, 0xfd, 0x13, 0x1e, - 0xa2, 0x1a, 0x27, 0xf5, 0x7d, 0x20, 0x90, 0x50, 0xe0, 0xd6, 0x7e, 0x1d, 0x16, 0x66, 0xea, 0xd0, - 0xe5, 0x72, 0x39, 0x45, 0x2e, 0xe7, 0x74, 0xb9, 0x6c, 0xc1, 0x62, 0xa2, 0x5f, 0x92, 0xd3, 0x56, - 0xa1, 0x28, 0x36, 0x84, 0x50, 0x0e, 0x32, 0xa4, 0x55, 0x1e, 0x73, 0x2e, 0xd4, 0xe0, 0x87, 0xb0, - 0x74, 0xcc, 0xb9, 0x6f, 0x87, 0x88, 0xc4, 0x1d, 0x23, 0x56, 0x48, 0x56, 0xbc, 0x20, 0x71, 0x5d, - 0x3b, 0x3c, 0xe0, 0xbe, 0x58, 0x29, 0xe3, 0x7f, 0x67, 0x60, 0x5e, 0x48, 0xd0, 0x5d, 0xdb, 0xbd, - 0x54, 0xf3, 0xb4, 0x93, 0x3a, 0x4f, 0xf7, 0xb4, 0xc3, 0x50, 0xa3, 0xfe, 0xa6, 0x93, 0x94, 0x9b, - 0x9e, 0x24, 0x76, 0x07, 0xaa, 0x89, 0xbe, 0x16, 0xb0, 0xaf, 0x10, 0x44, 0x9d, 0xfc, 0xc5, 0xa7, - 0xf1, 0x0d, 0x68, 0xc4, 0xdd, 0x96, 0x73, 0xc8, 0x20, 0x2f, 0x58, 0x52, 0x56, 0x80, 0x7f, 0x1b, - 0xff, 0x3c, 0x43, 0x84, 0x1b, 0x9e, 0x13, 0x69, 0xa7, 0x82, 0x50, 0xe8, 0xbd, 0x8a, 0x50, 0xfc, - 0x7d, 0xa5, 0x56, 0xff, 0x8b, 0x0f, 0x56, 0x6c, 0x9d, 0x80, 0xbb, 0x03, 0xcb, 0x1e, 0x0e, 0x51, - 0xf8, 0x96, 0xcc, 0xa2, 0xf8, 0x6e, 0x0d, 0x87, 0xc6, 0x5d, 0x58, 0xd0, 0x7a, 0xf7, 0x9c, 0x71, - 0xec, 0x01, 0xdb, 0x71, 0x82, 0xf0, 0xd0, 0x0d, 0xc6, 0x9a, 0xe2, 0x76, 0x03, 0xca, 0x42, 0xc2, - 0x8a, 0x9e, 0xd1, 0x96, 0x2d, 0x98, 0x42, 0xe4, 0x8a, 0x7e, 0x05, 0x88, 0xb4, 0x2f, 0x24, 0x32, - 0x2b, 0x91, 0xf6, 0x05, 0x22, 0x8d, 0x8f, 0x60, 0x31, 0x51, 0x9f, 0x6c, 0xfa, 0x55, 0x28, 0x4c, - 0xc2, 0x0b, 0x4f, 0xa9, 0xe6, 0x15, 0xc9, 0x21, 0xc2, 0x00, 0x34, 0x09, 0x63, 0x7c, 0x02, 0x0b, - 0x7b, 0xfc, 0x5c, 0x6e, 0x62, 0xd5, 0x91, 0x37, 0x20, 0xff, 0x02, 0xa3, 0x10, 0xf1, 0xc6, 0x03, - 0x60, 0x7a, 0x61, 0xd9, 0xaa, 0x66, 0x23, 0x66, 0x12, 0x36, 0xa2, 0xf1, 0x06, 0xb0, 0xae, 0x73, - 0xe2, 0xee, 0xf2, 0x20, 0xb0, 0x4f, 0xa2, 0x6d, 0xdf, 0x80, 0xdc, 0x28, 0x38, 0x91, 0x32, 0x4a, - 0xfc, 0x69, 0x7c, 0x17, 0x16, 0x13, 0x74, 0xb2, 0xe2, 0x9b, 0x50, 0x0e, 0x9c, 0x13, 0x17, 0x15, - 0x2b, 0x59, 0x75, 0x0c, 0x30, 0xb6, 0x60, 0xe9, 0x33, 0xee, 0x3b, 0xc7, 0x97, 0x2f, 0xaa, 0x3e, - 0x59, 0x4f, 0x76, 0xba, 0x9e, 0x36, 0x2c, 0x4f, 0xd5, 0x23, 0x9b, 0x27, 0xf6, 0x95, 0x2b, 0x59, - 0x32, 0xe9, 0x43, 0x93, 0x7b, 0x59, 0x5d, 0xee, 0x19, 0x87, 0xc0, 0x36, 0x3c, 0xd7, 0xe5, 0xfd, - 0xf0, 0x80, 0x73, 0x3f, 0xf6, 0x52, 0xc5, 0xbc, 0x5a, 0x79, 0xbc, 0x2a, 0x67, 0x76, 0x5a, 0x98, - 0x4a, 0x26, 0x66, 0x90, 0x1f, 0x73, 0x7f, 0x84, 0x15, 0x97, 0x4c, 0xfc, 0xdb, 0x58, 0x86, 0xc5, - 0x44, 0xb5, 0xd2, 0xae, 0x7f, 0x04, 0xcb, 0x9b, 0x4e, 0xd0, 0x9f, 0x6d, 0x70, 0x15, 0x8a, 0xe3, - 0xc9, 0x91, 0x95, 0x94, 0xcb, 0x4f, 0xf9, 0xa5, 0xb0, 0xf6, 0xa6, 0x4b, 0xc8, 0xba, 0xfe, 0x76, - 0x06, 0xf2, 0xdb, 0xbd, 0x9d, 0x0d, 0xb6, 0x06, 0x25, 0xc7, 0xed, 0x7b, 0x23, 0xa1, 0x78, 0xd1, - 0x98, 0xa3, 0xef, 0x2b, 0x37, 0xd8, 0x0d, 0x28, 0xa3, 0xbe, 0x26, 0x4c, 0x5b, 0xa9, 0xfa, 0x94, - 0x04, 0x60, 0xc7, 0xeb, 0x3f, 0x13, 0x36, 0x35, 0xbf, 0x18, 0x3b, 0x3e, 0x5a, 0xcd, 0xca, 0x18, - 0xce, 0xd3, 0x59, 0x1f, 0x23, 0xc8, 0x22, 0x36, 0xfe, 0x43, 0x11, 0x8a, 0xf2, 0xb4, 0xa5, 0x93, - 0x3b, 0x74, 0xce, 0x78, 0x7c, 0x72, 0x8b, 0x2f, 0xa1, 0x0f, 0xf8, 0x7c, 0xe4, 0x85, 0x91, 0xc2, - 0x46, 0x6b, 0x50, 0x25, 0xa0, 0x54, 0xd9, 0x34, 0xa5, 0x81, 0x5c, 0x0c, 0x39, 0x22, 0xea, 0xeb, - 0x47, 0xf9, 0x0d, 0x28, 0xaa, 0xb3, 0x3f, 0x1f, 0xd9, 0x34, 0x73, 0x7d, 0xd2, 0xd6, 0xd6, 0xa0, - 0xd4, 0xb7, 0xc7, 0x76, 0xdf, 0x09, 0x2f, 0xa5, 0x40, 0x88, 0xbe, 0x45, 0xed, 0x43, 0xaf, 0x6f, - 0x0f, 0xad, 0x23, 0x7b, 0x68, 0xbb, 0x7d, 0x2e, 0x6d, 0xf7, 0x2a, 0x02, 0xd7, 0x09, 0x26, 0xec, - 0x73, 0xd9, 0x4f, 0x45, 0x45, 0x26, 0xbc, 0xec, 0xbd, 0x22, 0x13, 0xca, 0xa5, 0x37, 0x1a, 0x39, - 0xc2, 0xca, 0x20, 0x35, 0x2c, 0x67, 0x96, 0x09, 0xb2, 0xc5, 0x71, 0xb4, 0x12, 0x7d, 0x4e, 0x53, - 0x57, 0xa6, 0xa6, 0x08, 0xf8, 0x39, 0x39, 0x12, 0x66, 0x75, 0xb1, 0x9c, 0xa6, 0x8b, 0xbd, 0x05, - 0x0b, 0x13, 0x37, 0xe0, 0x61, 0x38, 0xe4, 0x83, 0xa8, 0x2f, 0x15, 0x24, 0x6a, 0x44, 0x08, 0xd5, - 0x9d, 0x07, 0xb0, 0x48, 0x4e, 0x87, 0xc0, 0x0e, 0xbd, 0xe0, 0xd4, 0x09, 0xac, 0x40, 0x58, 0x48, - 0x64, 0xee, 0x2e, 0x20, 0xaa, 0x2b, 0x31, 0x5d, 0x32, 0x91, 0x56, 0xa7, 0xe8, 0x7d, 0xde, 0xe7, - 0xce, 0x19, 0x1f, 0xa0, 0x9e, 0x96, 0x33, 0x97, 0x13, 0x65, 0x4c, 0x89, 0x44, 0xa5, 0x7b, 0x32, - 0xb2, 0x26, 0xe3, 0x81, 0x2d, 0x94, 0x95, 0x3a, 0x29, 0xc3, 0xee, 0x64, 0x74, 0x48, 0x10, 0xf6, - 0x08, 0x94, 0x26, 0x26, 0xf5, 0xc3, 0xf9, 0x84, 0x3c, 0x13, 0xcc, 0x6a, 0x56, 0x25, 0x05, 0x29, - 0x8a, 0x09, 0x9d, 0xb3, 0x31, 0xa5, 0x73, 0x36, 0xa1, 0x38, 0xf6, 0x9d, 0x33, 0x3b, 0xe4, 0xcd, - 0x05, 0x12, 0xe0, 0xf2, 0x53, 0x48, 0x06, 0xc7, 0x75, 0x42, 0xc7, 0x0e, 0x3d, 0xbf, 0xc9, 0x10, - 0x17, 0x03, 0xd8, 0x7d, 0x58, 0x40, 0x1e, 0x09, 0x42, 0x3b, 0x9c, 0x04, 0x52, 0x03, 0x5d, 0x44, - 0x66, 0x42, 0x1d, 0xba, 0x8b, 0x70, 0x54, 0x42, 0xd9, 0x77, 0x61, 0x85, 0xd8, 0x02, 0x4b, 0x48, - 0xcd, 0x1a, 0x15, 0x82, 0x25, 0x9c, 0x8a, 0x45, 0xc4, 0x0a, 0xfe, 0x96, 0xfa, 0xb5, 0xd0, 0x0e, - 0xde, 0x87, 0x55, 0xc9, 0x26, 0x33, 0xa5, 0x96, 0xb1, 0xd4, 0x12, 0xa1, 0xa7, 0x8a, 0xdd, 0x87, - 0x05, 0xd1, 0x25, 0xa7, 0x6f, 0xc9, 0xd2, 0x62, 0x27, 0xac, 0x60, 0xef, 0xe7, 0x09, 0x61, 0x22, - 0xfc, 0x29, 0xbf, 0x14, 0xac, 0x3c, 0x74, 0x8e, 0x79, 0xe8, 0x8c, 0x78, 0x73, 0x95, 0x98, 0x43, - 0x7d, 0x8b, 0x5d, 0x36, 0x19, 0x23, 0xa6, 0x49, 0x7b, 0x9a, 0xbe, 0x90, 0xef, 0x86, 0x5e, 0xc0, - 0x95, 0x7b, 0xa9, 0x79, 0x5d, 0x6e, 0x20, 0x01, 0x94, 0x22, 0xcb, 0xf8, 0x69, 0x86, 0xce, 0x20, - 0xb9, 0x65, 0x03, 0xcd, 0xa2, 0xa2, 0xcd, 0x6a, 0x79, 0xee, 0xf0, 0x52, 0xee, 0x5f, 0x20, 0xd0, - 0xbe, 0x3b, 0xc4, 0x0d, 0xe4, 0xb8, 0x3a, 0x09, 0x89, 0xbb, 0xaa, 0x02, 0x22, 0xd1, 0x6d, 0xa8, - 0x8c, 0x27, 0x47, 0x43, 0xa7, 0x4f, 0x24, 0x39, 0xaa, 0x85, 0x40, 0x48, 0x20, 0x4c, 0x4a, 0x5a, - 0x44, 0xa2, 0xc8, 0x23, 0x45, 0x45, 0xc2, 0x90, 0x04, 0xc5, 0x29, 0xf7, 0x71, 0x07, 0x57, 0x4d, - 0xfc, 0xdb, 0x58, 0x87, 0xa5, 0x64, 0xa7, 0xa5, 0xac, 0xbf, 0x0f, 0x25, 0x29, 0x1e, 0x94, 0xaf, - 0xa1, 0xae, 0x79, 0x7f, 0x85, 0x55, 0x14, 0xe1, 0x8d, 0xdf, 0x9e, 0x83, 0x45, 0x09, 0xdd, 0x10, - 0x33, 0xd2, 0x9d, 0x8c, 0x46, 0xb6, 0x9f, 0x22, 0x77, 0x32, 0xcf, 0x97, 0x3b, 0xd9, 0x19, 0xb9, - 0x93, 0x34, 0x36, 0x49, 0x6c, 0x25, 0x8d, 0x4d, 0xb1, 0x04, 0xa4, 0xff, 0xeb, 0xae, 0xc7, 0x9a, - 0x04, 0xf7, 0xc8, 0xc5, 0x39, 0x23, 0x25, 0x0b, 0x29, 0x52, 0x52, 0x97, 0x71, 0x73, 0x53, 0x32, - 0xee, 0x55, 0xa0, 0xb5, 0x56, 0x22, 0xbb, 0x48, 0x26, 0x01, 0xc2, 0xa4, 0xff, 0xf2, 0x2e, 0xcc, - 0x4f, 0x8b, 0x15, 0x92, 0x5f, 0xf5, 0x14, 0xa1, 0xe2, 0x8c, 0x38, 0x1e, 0x10, 0x1a, 0x71, 0x59, - 0x0a, 0x15, 0x67, 0xc4, 0x77, 0x10, 0xa3, 0xe8, 0xdb, 0x00, 0xd4, 0x36, 0x6a, 0x24, 0x80, 0x1a, - 0xc9, 0x1b, 0xc9, 0xb5, 0xd0, 0x67, 0xfd, 0x81, 0xf8, 0x98, 0xf8, 0x1c, 0xb5, 0x94, 0x32, 0x96, - 0x44, 0xc7, 0xf5, 0x53, 0xa8, 0x7b, 0x63, 0xee, 0x5a, 0xf1, 0xf6, 0xae, 0x60, 0x55, 0xaf, 0x3f, - 0xa7, 0xaa, 0x8e, 0xa2, 0x35, 0x6b, 0xa2, 0x6c, 0xf4, 0xc9, 0x76, 0x69, 0xe2, 0xb9, 0x56, 0x5b, - 0xf5, 0x1b, 0xd4, 0x56, 0xc7, 0xc2, 0xd1, 0xb7, 0xf1, 0xf7, 0x32, 0x50, 0xd1, 0xba, 0xcd, 0x96, - 0x61, 0x61, 0x63, 0x7f, 0xff, 0xa0, 0x6d, 0xb6, 0x7a, 0x9d, 0xcf, 0xda, 0xd6, 0xc6, 0xce, 0x7e, - 0xb7, 0xdd, 0xb8, 0x26, 0xc0, 0x3b, 0xfb, 0x1b, 0xad, 0x1d, 0x6b, 0x6b, 0xdf, 0xdc, 0x50, 0xe0, - 0x0c, 0x5b, 0x01, 0x66, 0xb6, 0x77, 0xf7, 0x7b, 0xed, 0x04, 0x3c, 0xcb, 0x1a, 0x50, 0x5d, 0x37, - 0xdb, 0xad, 0x8d, 0x6d, 0x09, 0xc9, 0xb1, 0x25, 0x68, 0x6c, 0x1d, 0xee, 0x6d, 0x76, 0xf6, 0x9e, - 0x58, 0x1b, 0xad, 0xbd, 0x8d, 0xf6, 0x4e, 0x7b, 0xb3, 0x91, 0x67, 0x35, 0x28, 0xb7, 0xd6, 0x5b, - 0x7b, 0x9b, 0xfb, 0x7b, 0xed, 0xcd, 0x46, 0xc1, 0xf8, 0x35, 0x28, 0xc7, 0x03, 0xad, 0x40, 0xf1, - 0x70, 0xef, 0xe9, 0xde, 0xfe, 0xe7, 0x7b, 0x8d, 0x6b, 0xac, 0x0c, 0x05, 0x6c, 0xbf, 0x91, 0x61, - 0x00, 0x73, 0xd4, 0x66, 0x23, 0xcb, 0x4a, 0x90, 0x5f, 0xdf, 0xef, 0x6d, 0x37, 0x72, 0xc6, 0x9f, - 0x65, 0x60, 0x19, 0x87, 0x3c, 0x98, 0x16, 0x02, 0x77, 0xa0, 0xd2, 0xf7, 0xbc, 0xb1, 0x30, 0x6e, - 0xe2, 0x43, 0x5c, 0x07, 0x89, 0x0d, 0x4e, 0xf2, 0xf2, 0xd8, 0xf3, 0xfb, 0x5c, 0xca, 0x00, 0x40, - 0xd0, 0x96, 0x80, 0x08, 0x1e, 0x94, 0x4c, 0x4c, 0x14, 0x24, 0x02, 0x2a, 0x04, 0x23, 0x92, 0x15, - 0x98, 0x3b, 0xf2, 0xb9, 0xdd, 0x3f, 0x95, 0xbb, 0x5f, 0x7e, 0xb1, 0x37, 0x63, 0xb3, 0xbb, 0x2f, - 0x78, 0x6a, 0xc8, 0x07, 0xb8, 0x05, 0x4a, 0xe6, 0xbc, 0x84, 0x6f, 0x48, 0xb0, 0x38, 0x00, 0xec, - 0x23, 0xdb, 0x1d, 0x78, 0x2e, 0x1f, 0x48, 0xed, 0x3e, 0x06, 0x18, 0x07, 0xb0, 0x32, 0x3d, 0x3e, - 0x29, 0x2f, 0x3e, 0xd0, 0xe4, 0x05, 0x29, 0xdb, 0x6b, 0x57, 0xb3, 0x82, 0x26, 0x3b, 0x7e, 0x96, - 0x83, 0xbc, 0x50, 0xbe, 0xae, 0xd4, 0xd3, 0x74, 0x6d, 0x3a, 0x37, 0x13, 0x71, 0x41, 0xeb, 0x9e, - 0x4e, 0x65, 0x72, 0x21, 0x95, 0x11, 0x82, 0xa7, 0x71, 0x84, 0xf6, 0x79, 0xff, 0x4c, 0xfa, 0x90, - 0x08, 0x6d, 0xf2, 0xfe, 0x19, 0x9a, 0x31, 0x76, 0x48, 0x65, 0x69, 0xbf, 0x17, 0x03, 0x3b, 0xc4, - 0x92, 0x12, 0x85, 0xe5, 0x8a, 0x11, 0x0a, 0x4b, 0x35, 0xa1, 0xe8, 0xb8, 0x47, 0xde, 0xc4, 0x1d, - 0xe0, 0xf6, 0x2e, 0x99, 0xea, 0x13, 0x03, 0x3c, 0x28, 0x89, 0xc4, 0xf9, 0x41, 0xbb, 0xb9, 0x24, - 0x00, 0x3d, 0x71, 0x82, 0xbc, 0x0b, 0xe5, 0xe0, 0xd2, 0xed, 0xeb, 0x7b, 0x78, 0x49, 0xce, 0x8f, - 0x18, 0xfd, 0x83, 0xee, 0xa5, 0xdb, 0xc7, 0x1d, 0x5b, 0x0a, 0xe4, 0x5f, 0xec, 0x7d, 0x28, 0x45, - 0xae, 0x56, 0x92, 0xc0, 0xd7, 0xf5, 0x12, 0xca, 0xbf, 0x4a, 0x16, 0x6d, 0x44, 0xba, 0xf6, 0x14, - 0x6a, 0x09, 0x94, 0x6e, 0x86, 0xd6, 0xc8, 0x0c, 0x7d, 0x5d, 0x37, 0x43, 0x63, 0xc1, 0x2e, 0x8b, - 0xe9, 0x66, 0xe9, 0xaf, 0x43, 0x49, 0xf5, 0x4c, 0x6c, 0x27, 0xb9, 0x15, 0xac, 0xee, 0x17, 0x7b, - 0x1b, 0x8d, 0x6b, 0x6c, 0x1e, 0x2a, 0xad, 0x0d, 0xdc, 0xa1, 0x08, 0xc8, 0x08, 0x92, 0x83, 0x56, - 0xb7, 0x1b, 0x41, 0xb2, 0x06, 0x83, 0x86, 0x38, 0x5e, 0x44, 0x8f, 0xa3, 0x60, 0xca, 0x07, 0xb0, - 0xa0, 0xc1, 0x62, 0x4b, 0x4d, 0x9c, 0x47, 0xd3, 0x96, 0x1a, 0xea, 0xe5, 0x84, 0x31, 0x56, 0x61, - 0x59, 0x7c, 0xb6, 0xcf, 0xb8, 0x1b, 0x76, 0x27, 0x47, 0x14, 0x4a, 0x73, 0x3c, 0x57, 0xe8, 0xeb, - 0xe5, 0x08, 0x73, 0x35, 0x23, 0x3d, 0x90, 0x46, 0x5d, 0x16, 0xa7, 0x7f, 0x4d, 0x6b, 0x01, 0x0b, - 0x3e, 0xc0, 0x7f, 0x13, 0xc6, 0x5d, 0x39, 0x02, 0x89, 0xb1, 0x1e, 0xb4, 0xdb, 0xa6, 0xb5, 0xbf, - 0xb7, 0xd3, 0xd9, 0x13, 0xc2, 0x48, 0x8c, 0x15, 0x01, 0x5b, 0x5b, 0x08, 0xc9, 0x18, 0x0d, 0xa8, - 0x3f, 0xe1, 0x61, 0xc7, 0x3d, 0xf6, 0xd4, 0x48, 0x7f, 0x5e, 0x80, 0xf9, 0x08, 0x14, 0x1b, 0x87, - 0x67, 0xdc, 0x0f, 0x1c, 0xcf, 0x45, 0x3d, 0xaf, 0x6c, 0xaa, 0x4f, 0x71, 0x82, 0x38, 0x03, 0xee, - 0x86, 0x4e, 0x78, 0x69, 0x25, 0x3c, 0x49, 0x75, 0x05, 0x96, 0x27, 0xd5, 0x12, 0x14, 0xec, 0xa1, - 0x63, 0xab, 0x08, 0x24, 0x7d, 0x08, 0x68, 0xdf, 0x1b, 0x7a, 0x3e, 0xaa, 0x74, 0x65, 0x93, 0x3e, - 0xd8, 0x23, 0x58, 0x12, 0xaa, 0xa5, 0xee, 0xde, 0xc3, 0x3d, 0x4a, 0x4e, 0x2d, 0xe6, 0x4e, 0x46, - 0x07, 0xb1, 0x8b, 0x4f, 0x60, 0xc4, 0xf9, 0x24, 0x4a, 0x48, 0x85, 0x24, 0x2a, 0x40, 0x56, 0xca, - 0x82, 0x3b, 0x19, 0xb5, 0x10, 0x13, 0xd1, 0x3f, 0x86, 0x65, 0x41, 0x1f, 0xa9, 0x30, 0x51, 0x89, - 0x79, 0x2c, 0x21, 0x2a, 0xeb, 0x48, 0x5c, 0x54, 0xe6, 0x06, 0x94, 0xa9, 0x57, 0x62, 0xc5, 0x0b, - 0xa4, 0x9d, 0x62, 0x57, 0xb8, 0x1f, 0xcc, 0x04, 0x0b, 0xe7, 0xe8, 0xb0, 0x9d, 0x0a, 0x16, 0x6a, - 0xe1, 0xc6, 0xd2, 0x74, 0xb8, 0xf1, 0x31, 0x2c, 0x1f, 0xf1, 0x20, 0xb4, 0x4e, 0xb9, 0x3d, 0xe0, - 0x3e, 0xee, 0x48, 0x0a, 0x2b, 0x92, 0x16, 0xbe, 0x28, 0x90, 0xdb, 0x88, 0xeb, 0x29, 0x94, 0xd0, - 0x25, 0xc4, 0xd6, 0xe3, 0x03, 0x2b, 0xf4, 0x2c, 0x54, 0x31, 0x70, 0x13, 0x97, 0xcc, 0x1a, 0x81, - 0x7b, 0xde, 0x86, 0x00, 0x26, 0xe9, 0x4e, 0x7c, 0x7b, 0x7c, 0x2a, 0xf5, 0xe4, 0x88, 0xee, 0x89, - 0x00, 0xb2, 0x9b, 0x50, 0x0c, 0x79, 0x10, 0xba, 0x9c, 0x62, 0x3a, 0x25, 0xf4, 0xd9, 0x2b, 0x10, - 0x7b, 0x1d, 0xe6, 0xb0, 0x8d, 0xa0, 0xd9, 0x40, 0x7e, 0xaf, 0xc6, 0xc2, 0xd2, 0x71, 0x4d, 0x89, - 0x13, 0x0a, 0xdb, 0xc4, 0x77, 0x82, 0x66, 0x15, 0x63, 0x99, 0xf8, 0x37, 0xfb, 0x0d, 0x4d, 0x2c, - 0x2c, 0x62, 0x59, 0x75, 0xe6, 0x4e, 0x71, 0xda, 0xaf, 0x44, 0x42, 0x7c, 0x3f, 0x5f, 0xaa, 0x34, - 0xaa, 0xc6, 0x87, 0x50, 0xa0, 0xd9, 0x11, 0x4c, 0x88, 0x73, 0x97, 0x91, 0x4c, 0x88, 0xd0, 0x26, - 0x14, 0x5d, 0x1e, 0x9e, 0x7b, 0xfe, 0x33, 0xe5, 0x6b, 0x95, 0x9f, 0xc6, 0x4f, 0xd0, 0x49, 0x10, - 0x05, 0x92, 0xc9, 0xde, 0x11, 0xec, 0x41, 0xcb, 0x1b, 0x9c, 0xda, 0xd2, 0x6f, 0x51, 0x42, 0x40, - 0xf7, 0xd4, 0x9e, 0x61, 0x8f, 0xec, 0x6c, 0x2c, 0xf9, 0x75, 0xa8, 0xab, 0xd0, 0x75, 0x60, 0x0d, - 0xf9, 0x71, 0x28, 0xd9, 0xbd, 0x2a, 0xe3, 0xd6, 0xc1, 0x0e, 0x3f, 0x0e, 0x8d, 0x5d, 0x58, 0x90, - 0x0c, 0xb9, 0x3f, 0xe6, 0xaa, 0xe9, 0x8f, 0xd2, 0x74, 0xd6, 0xca, 0xe3, 0xc5, 0xe4, 0x61, 0x46, - 0x21, 0xf9, 0x84, 0x22, 0x6b, 0x7c, 0x0a, 0x4c, 0x3f, 0xea, 0x64, 0x7d, 0x52, 0x73, 0x54, 0x2e, - 0x6a, 0x15, 0xe9, 0x89, 0xf4, 0x53, 0x67, 0x20, 0x66, 0x27, 0x98, 0xf4, 0xfb, 0x2a, 0xa5, 0xa0, - 0x64, 0xaa, 0x4f, 0xe3, 0x4f, 0x33, 0xb0, 0x88, 0x95, 0x29, 0x9d, 0x5b, 0x6a, 0x13, 0xdf, 0xba, - 0x93, 0x62, 0x7d, 0x74, 0xfd, 0x82, 0x3e, 0xbe, 0xb9, 0x53, 0x30, 0x3f, 0xe3, 0x14, 0x7c, 0x13, - 0x1a, 0x03, 0x3e, 0x74, 0x30, 0xbb, 0x44, 0x1d, 0xd7, 0xa4, 0x65, 0xcf, 0x2b, 0xb8, 0x32, 0x94, - 0xfe, 0x49, 0x06, 0x16, 0x48, 0x1b, 0x40, 0x73, 0x51, 0x4e, 0xd4, 0x27, 0xca, 0xc6, 0x92, 0xa2, - 0x4a, 0x8e, 0x29, 0x3e, 0x25, 0x11, 0x4a, 0xc4, 0xdb, 0xd7, 0xa4, 0xed, 0x25, 0xa1, 0xec, 0x63, - 0xb4, 0x13, 0x5c, 0x0b, 0x81, 0x29, 0xd9, 0x2a, 0xc9, 0x45, 0xd9, 0xbe, 0x86, 0x46, 0x84, 0x8b, - 0xa0, 0xf5, 0x92, 0x30, 0xfa, 0x04, 0xd8, 0xd8, 0x82, 0x5a, 0xa2, 0x99, 0x84, 0xe7, 0xb2, 0x4a, - 0x9e, 0xcb, 0x99, 0xe8, 0x40, 0x76, 0x36, 0x3a, 0xf0, 0x77, 0xf2, 0xc0, 0x04, 0x4b, 0x4d, 0xad, - 0xda, 0x54, 0x68, 0x2d, 0x3b, 0x13, 0x5a, 0x7b, 0x04, 0x4c, 0x23, 0x50, 0x11, 0xbf, 0x5c, 0x14, - 0xf1, 0x6b, 0xc4, 0xb4, 0x32, 0xe0, 0xf7, 0x08, 0x96, 0xa4, 0xd2, 0x18, 0xc5, 0xd2, 0xd0, 0x25, - 0x45, 0xeb, 0xc3, 0x48, 0x7b, 0x54, 0x31, 0x35, 0x74, 0x4f, 0xa9, 0xb0, 0x9a, 0x30, 0xa9, 0xc9, - 0x93, 0x83, 0x61, 0x35, 0x61, 0x45, 0x4f, 0x71, 0xc1, 0xdc, 0x0b, 0xb9, 0xa0, 0x38, 0xc3, 0x05, - 0x9a, 0x63, 0xa1, 0x94, 0x74, 0x2c, 0x18, 0x50, 0x53, 0xc1, 0x33, 0xca, 0x19, 0x20, 0x0d, 0xa9, - 0x22, 0x23, 0x68, 0x98, 0x37, 0x70, 0x0f, 0x1a, 0xca, 0xfa, 0x8f, 0x5c, 0x17, 0x14, 0x0f, 0x97, - 0xce, 0xa3, 0x0d, 0xe5, 0xc0, 0x48, 0x38, 0x8a, 0x2b, 0x53, 0x8e, 0xe2, 0xb7, 0x60, 0x21, 0x10, - 0x4c, 0x64, 0x4d, 0x5c, 0x99, 0xbc, 0xc2, 0x07, 0x68, 0x9e, 0x94, 0xcc, 0x06, 0x22, 0x0e, 0x63, - 0xf8, 0xac, 0x69, 0x5f, 0x9b, 0x35, 0xed, 0xd9, 0xfb, 0x71, 0x9c, 0x29, 0x38, 0x75, 0x46, 0x78, - 0x70, 0xc7, 0x89, 0x1e, 0x72, 0x82, 0xbb, 0xa7, 0xce, 0xc8, 0x54, 0x41, 0x4d, 0xf1, 0x61, 0xfc, - 0xe7, 0x0c, 0x34, 0x04, 0x1f, 0x24, 0xf8, 0xfc, 0xd7, 0x00, 0x77, 0xe4, 0x4b, 0xb2, 0x79, 0x45, - 0xd0, 0x2a, 0x2e, 0xff, 0x10, 0x90, 0x6d, 0x2d, 0x61, 0x8b, 0x49, 0x26, 0x6f, 0x26, 0x99, 0x3c, - 0x16, 0x64, 0xdb, 0xd7, 0x48, 0xc9, 0x16, 0x90, 0xb4, 0xf8, 0x5e, 0x3e, 0x25, 0xbe, 0xa7, 0x6d, - 0x85, 0x6d, 0x80, 0xa7, 0xfc, 0x72, 0xc7, 0xeb, 0xa3, 0x15, 0x74, 0x0b, 0x40, 0x30, 0xe4, 0xb1, - 0x3d, 0x72, 0xa4, 0x07, 0xa3, 0x60, 0x96, 0x9f, 0xf1, 0xcb, 0x2d, 0x04, 0x88, 0xd5, 0x10, 0xe8, - 0x78, 0x3f, 0x14, 0xcc, 0xd2, 0x33, 0x7e, 0x49, 0x9b, 0xc1, 0x82, 0xda, 0x53, 0x7e, 0xb9, 0xc9, - 0x49, 0x5d, 0xf3, 0x7c, 0xc1, 0x09, 0xbe, 0x7d, 0x2e, 0xf4, 0xb3, 0x44, 0x6c, 0xae, 0xe2, 0xdb, - 0xe7, 0x4f, 0xf9, 0xa5, 0x8a, 0x13, 0x16, 0x05, 0x7e, 0xe8, 0xf5, 0xe5, 0x09, 0xa4, 0xb2, 0x0c, - 0xe2, 0x4e, 0x99, 0x73, 0xcf, 0xf0, 0x6f, 0xe3, 0x4f, 0x32, 0x50, 0x13, 0xfd, 0x47, 0x01, 0x27, - 0xe6, 0x5d, 0x25, 0xab, 0x64, 0xe2, 0x64, 0x95, 0xc7, 0x52, 0x3e, 0x90, 0xb4, 0xcc, 0x5e, 0x2d, - 0x2d, 0x71, 0x82, 0x49, 0x54, 0xbe, 0x0b, 0x65, 0xda, 0x5b, 0x62, 0xb3, 0xe6, 0x12, 0xab, 0x94, - 0x18, 0x90, 0x59, 0x42, 0xb2, 0xa7, 0x14, 0x1b, 0xd7, 0x1c, 0x50, 0x34, 0xc5, 0x65, 0x3f, 0x72, - 0x3d, 0xa5, 0x2c, 0x43, 0x21, 0x2d, 0xcc, 0x7a, 0x08, 0x15, 0x8d, 0xa7, 0xd8, 0xf7, 0x28, 0x40, - 0x4d, 0x9d, 0x27, 0x06, 0x4c, 0x32, 0x4d, 0x62, 0xf4, 0xdb, 0xd7, 0xcc, 0x5a, 0x5f, 0x07, 0xac, - 0xcf, 0x41, 0x5e, 0x14, 0x32, 0x3e, 0x81, 0x05, 0xad, 0x5a, 0xb2, 0xf8, 0xd2, 0xfa, 0x94, 0x49, - 0xeb, 0xd3, 0x3f, 0xcd, 0xc0, 0x92, 0x2c, 0x8d, 0x89, 0x4d, 0x8e, 0x38, 0xae, 0x77, 0x83, 0x13, - 0xf6, 0x6b, 0x50, 0x13, 0xb5, 0x5b, 0x3e, 0x3f, 0x71, 0x82, 0x90, 0x2b, 0xcf, 0x7e, 0xca, 0xe6, - 0x10, 0x52, 0x5b, 0x90, 0x9a, 0x92, 0x92, 0x7d, 0x02, 0x15, 0x2c, 0x4a, 0x36, 0xa9, 0x5c, 0x96, - 0xe6, 0x6c, 0x41, 0xea, 0xea, 0xf6, 0x35, 0x13, 0x82, 0xe8, 0x6b, 0xbd, 0x0c, 0xc5, 0xd0, 0x77, - 0x4e, 0x4e, 0xb8, 0x6f, 0xac, 0x44, 0x5d, 0x13, 0x3b, 0x8d, 0x77, 0x43, 0x3e, 0x16, 0x4a, 0x90, - 0xf1, 0xdf, 0x32, 0x50, 0x91, 0x7b, 0xe7, 0x5b, 0xbb, 0xf3, 0xd7, 0xb4, 0xcc, 0x3c, 0x32, 0x3f, - 0xe3, 0x44, 0xbc, 0xbb, 0x30, 0x3f, 0x12, 0x0a, 0x91, 0x50, 0xd8, 0x13, 0xbe, 0xfc, 0xba, 0x02, - 0x4b, 0x7d, 0xe4, 0x01, 0x2c, 0xa2, 0x7a, 0x12, 0x58, 0xa1, 0x33, 0xb4, 0x14, 0x52, 0x66, 0xc1, - 0x2d, 0x10, 0xaa, 0xe7, 0x0c, 0x77, 0x25, 0x42, 0x9c, 0xd2, 0x41, 0x68, 0x9f, 0x70, 0xa9, 0xfa, - 0xd2, 0x87, 0xd1, 0x84, 0x95, 0x29, 0x5d, 0x5d, 0xd9, 0x19, 0x7f, 0xbf, 0x06, 0xab, 0x33, 0x28, - 0x69, 0x6f, 0x44, 0x3e, 0xec, 0xa1, 0x33, 0x3a, 0xf2, 0x22, 0x77, 0x53, 0x46, 0xf3, 0x61, 0xef, - 0x08, 0x8c, 0x72, 0x37, 0x71, 0x58, 0x56, 0x0c, 0x81, 0xfe, 0xa2, 0x48, 0x9d, 0xcf, 0xa2, 0xb2, - 0xf9, 0x6e, 0x52, 0x50, 0x4d, 0x37, 0xa7, 0xe0, 0xfa, 0xf1, 0xb7, 0x38, 0x9e, 0x81, 0x05, 0xec, - 0x18, 0x9a, 0x11, 0xdf, 0x49, 0xfd, 0x48, 0xb3, 0x4d, 0x44, 0x4b, 0x6f, 0xbf, 0xa0, 0xa5, 0x84, - 0x23, 0xc2, 0x5c, 0x51, 0xec, 0x4a, 0x95, 0x45, 0xed, 0x9c, 0xc1, 0x2b, 0xaa, 0x1d, 0xd4, 0x75, - 0x66, 0x5b, 0xcb, 0xbf, 0xd4, 0xb8, 0xd0, 0xc1, 0x92, 0x6c, 0xf2, 0x86, 0xac, 0x38, 0x42, 0xe9, - 0xed, 0x9e, 0xc2, 0xca, 0xb9, 0xed, 0x84, 0x6a, 0x7c, 0x9a, 0x59, 0x54, 0xc0, 0xf6, 0x1e, 0xbf, - 0xa0, 0xbd, 0xcf, 0xa9, 0x70, 0x42, 0xfb, 0x5b, 0x3a, 0x9f, 0x05, 0x06, 0x6b, 0xff, 0x31, 0x0b, - 0xf5, 0x64, 0x2d, 0x62, 0x53, 0x4b, 0x39, 0xa4, 0xf4, 0x09, 0xa9, 0x8f, 0x4b, 0x37, 0xe8, 0x1e, - 0xe9, 0x11, 0xb3, 0x0e, 0xda, 0x6c, 0x8a, 0x83, 0x56, 0xf7, 0x8b, 0xe6, 0x5e, 0x14, 0xfb, 0xc9, - 0xbf, 0x54, 0xec, 0xa7, 0x90, 0x16, 0xfb, 0xb9, 0x3a, 0x60, 0x30, 0xf7, 0xad, 0x02, 0x06, 0xc5, - 0xab, 0x03, 0x06, 0x6b, 0x7f, 0x99, 0x01, 0x36, 0xcb, 0xa9, 0xec, 0x09, 0xf9, 0xa2, 0x5d, 0x3e, - 0x94, 0x52, 0xec, 0x9d, 0x97, 0xe3, 0x76, 0xb5, 0x40, 0xaa, 0x34, 0x7b, 0x08, 0x8b, 0x7a, 0xde, - 0xac, 0x6e, 0xaa, 0xd4, 0x4c, 0xa6, 0xa3, 0x62, 0x83, 0x56, 0x0b, 0x7c, 0xe5, 0x5f, 0x18, 0xf8, - 0x2a, 0xbc, 0x30, 0xf0, 0x35, 0x97, 0x0c, 0x7c, 0xad, 0xfd, 0xad, 0x0c, 0x2c, 0xa6, 0x30, 0xd5, - 0x2f, 0x6f, 0xcc, 0x82, 0x17, 0x12, 0x22, 0x26, 0x2b, 0x79, 0x41, 0x93, 0x2e, 0x6b, 0x5f, 0x41, - 0x2d, 0xb1, 0x89, 0x7e, 0x79, 0xcd, 0x4f, 0x1b, 0x5a, 0xc4, 0xca, 0xba, 0xa1, 0xb5, 0xf6, 0x17, - 0x59, 0x60, 0xb3, 0xfb, 0xf8, 0x57, 0xd9, 0x85, 0xd9, 0x49, 0xca, 0xcd, 0x4e, 0xd2, 0xff, 0xbf, - 0x73, 0xe5, 0x2d, 0x58, 0x90, 0xb9, 0xfe, 0x5a, 0xe0, 0x81, 0x18, 0xa5, 0x11, 0x21, 0x54, 0x2f, - 0x3e, 0x9c, 0x8e, 0x39, 0x96, 0x12, 0xe9, 0xcd, 0xda, 0xc1, 0x9a, 0x0c, 0x3d, 0x1a, 0x6b, 0xd0, - 0x94, 0x53, 0x33, 0xeb, 0xaa, 0xfb, 0xdd, 0x7c, 0x64, 0x25, 0x23, 0x52, 0x2a, 0xc5, 0xdf, 0x85, - 0xaa, 0x7e, 0xd8, 0xc8, 0x75, 0x98, 0x8a, 0x38, 0x09, 0x75, 0xd8, 0xd3, 0x76, 0xeb, 0x06, 0x50, - 0x1c, 0x61, 0x10, 0x15, 0x23, 0x0d, 0xe2, 0x39, 0x8e, 0x67, 0x54, 0x8e, 0x12, 0x8b, 0xff, 0x57, - 0xa0, 0x9e, 0xf4, 0x5b, 0x49, 0x55, 0x2f, 0x4d, 0x3b, 0x14, 0xa5, 0x13, 0x8e, 0x2c, 0xf6, 0x1b, - 0xd0, 0x98, 0xf6, 0x7b, 0xc9, 0xdc, 0xcb, 0x2b, 0xca, 0xcf, 0x3b, 0x49, 0x57, 0x18, 0xdb, 0x86, - 0xa5, 0xb4, 0xe3, 0x16, 0x57, 0xe5, 0x6a, 0xb3, 0x80, 0xcd, 0x1e, 0xa9, 0xec, 0x23, 0xe9, 0xde, - 0x2c, 0xa4, 0x05, 0x62, 0xb4, 0xc9, 0x7e, 0x40, 0xff, 0x69, 0x8e, 0xce, 0x33, 0x80, 0x18, 0xc6, - 0x1a, 0x50, 0xdd, 0x3f, 0x68, 0xef, 0x59, 0x1b, 0xdb, 0xad, 0xbd, 0xbd, 0xf6, 0x4e, 0xe3, 0x1a, - 0x63, 0x50, 0xc7, 0x08, 0xca, 0x66, 0x04, 0xcb, 0x08, 0x98, 0xf4, 0xfd, 0x2a, 0x58, 0x96, 0x2d, - 0x41, 0xa3, 0xb3, 0x37, 0x05, 0xcd, 0xb1, 0x26, 0x2c, 0x1d, 0xb4, 0x29, 0xe8, 0x92, 0xa8, 0x37, - 0x2f, 0x54, 0x38, 0x39, 0x5c, 0xa1, 0xc2, 0xd1, 0x4d, 0x11, 0xc9, 0x7d, 0x4a, 0xb3, 0xf9, 0xbd, - 0x0c, 0x2c, 0x4f, 0x21, 0xe2, 0xfc, 0x5f, 0xd2, 0x6b, 0x92, 0x1a, 0x4d, 0x15, 0x81, 0x8a, 0x87, - 0xdf, 0x82, 0x85, 0xc8, 0xd4, 0x9b, 0x92, 0x4b, 0x8d, 0x08, 0xa1, 0x88, 0x1f, 0xc2, 0xa2, 0x66, - 0x31, 0x4e, 0xed, 0x50, 0xa6, 0xa1, 0x64, 0x01, 0x63, 0x35, 0xca, 0xb3, 0x9c, 0xea, 0xf5, 0x80, - 0xae, 0x9f, 0xe8, 0x88, 0xd8, 0xfb, 0x9b, 0xec, 0xaf, 0xfa, 0x14, 0xa6, 0x7c, 0x82, 0x11, 0x92, - 0xbd, 0xd5, 0x17, 0x5c, 0x35, 0xff, 0x07, 0x73, 0xc0, 0x3e, 0x9d, 0x70, 0xff, 0x12, 0xf3, 0x7b, - 0x83, 0x17, 0x25, 0xbc, 0x28, 0xb3, 0x28, 0xfb, 0x52, 0x39, 0xfc, 0x69, 0x39, 0xf4, 0xf9, 0x17, - 0xe7, 0xd0, 0x17, 0x5e, 0x94, 0x43, 0xff, 0x1a, 0xd4, 0x9c, 0x13, 0xd7, 0x13, 0x02, 0x48, 0xe8, - 0x26, 0x41, 0x73, 0xee, 0x4e, 0xee, 0x5e, 0xd5, 0xac, 0x4a, 0xa0, 0xd0, 0x4c, 0x02, 0xf6, 0x49, - 0x4c, 0xc4, 0x07, 0x27, 0x78, 0xdf, 0x43, 0x17, 0x3d, 0xed, 0xc1, 0x09, 0x97, 0x56, 0x20, 0xfa, - 0x45, 0x54, 0x61, 0x01, 0x0f, 0xd8, 0xeb, 0x50, 0x0f, 0xbc, 0x89, 0x50, 0xf5, 0xd4, 0x34, 0x90, - 0x7f, 0xb8, 0x4a, 0xd0, 0x03, 0x15, 0x0c, 0x58, 0x9c, 0x04, 0xdc, 0x1a, 0x39, 0x41, 0x20, 0x0e, - 0xe8, 0xbe, 0xe7, 0x86, 0xbe, 0x37, 0x94, 0x2e, 0xdf, 0x85, 0x49, 0xc0, 0x77, 0x09, 0xb3, 0x41, - 0x08, 0xf6, 0x5e, 0xdc, 0xa5, 0xb1, 0xed, 0xf8, 0x41, 0x13, 0xb0, 0x4b, 0x6a, 0xa4, 0xa8, 0x51, - 0xd9, 0x8e, 0x1f, 0xf5, 0x45, 0x7c, 0x04, 0x53, 0xb9, 0xfd, 0x95, 0xe9, 0xdc, 0xfe, 0x1f, 0xa7, - 0xe7, 0xf6, 0xd7, 0xb0, 0xea, 0x47, 0xb2, 0xea, 0xd9, 0x25, 0xfe, 0x46, 0x29, 0xfe, 0xb3, 0x57, - 0x16, 0xea, 0xdf, 0xe4, 0xca, 0xc2, 0x7c, 0xda, 0x95, 0x85, 0x77, 0xa1, 0x82, 0xc9, 0xe4, 0xd6, - 0xa9, 0xe3, 0x86, 0xca, 0x85, 0xdd, 0xd0, 0xb3, 0xcd, 0xb7, 0x85, 0x31, 0x0d, 0xbe, 0xfa, 0x33, - 0x98, 0xbd, 0x3d, 0xb0, 0xf0, 0x2b, 0xbc, 0x3d, 0x20, 0x93, 0xde, 0x1f, 0x40, 0x49, 0xad, 0x13, - 0x63, 0x90, 0x3f, 0xf6, 0xbd, 0x91, 0x72, 0xed, 0x89, 0xbf, 0x59, 0x1d, 0xb2, 0xa1, 0x27, 0x0b, - 0x67, 0x43, 0xcf, 0xf8, 0x4d, 0xa8, 0x68, 0xac, 0xc6, 0x5e, 0x25, 0x27, 0x82, 0xd0, 0x96, 0xa5, - 0x95, 0x4c, 0xb3, 0x58, 0x96, 0xd0, 0xce, 0x40, 0xc8, 0x9b, 0x81, 0xe3, 0x73, 0xbc, 0xe7, 0x63, - 0xf9, 0xfc, 0x8c, 0xfb, 0x81, 0x72, 0xb5, 0x36, 0x22, 0x84, 0x49, 0x70, 0xe3, 0xaf, 0xc3, 0x62, - 0x62, 0x6d, 0xa5, 0x88, 0x78, 0x1d, 0xe6, 0x70, 0xde, 0x54, 0x28, 0x2c, 0x99, 0xc5, 0x2f, 0x71, - 0x78, 0x81, 0x93, 0xbc, 0xc4, 0xd6, 0xd8, 0xf7, 0x8e, 0xb0, 0x91, 0x8c, 0x59, 0x91, 0xb0, 0x03, - 0xdf, 0x3b, 0x32, 0x7e, 0x96, 0x83, 0xdc, 0xb6, 0x37, 0xd6, 0x33, 0x2c, 0x32, 0x33, 0x19, 0x16, - 0xd2, 0x04, 0xb0, 0x22, 0x15, 0x5f, 0x6a, 0x6d, 0xe8, 0x1f, 0x55, 0x6a, 0xfe, 0x3d, 0xa8, 0x0b, - 0x39, 0x11, 0x7a, 0xc2, 0x86, 0x3a, 0xb7, 0x7d, 0xca, 0xe9, 0xcf, 0xd1, 0xe6, 0xb3, 0x47, 0x61, - 0xcf, 0xdb, 0x22, 0x38, 0x5b, 0x82, 0x5c, 0xa4, 0xc0, 0x22, 0x5a, 0x7c, 0x0a, 0xe3, 0x1a, 0xb3, - 0xdb, 0x2e, 0x65, 0xac, 0x47, 0x7e, 0xb1, 0x77, 0x60, 0x31, 0x59, 0x2f, 0x89, 0x22, 0xa9, 0x91, - 0xe8, 0x15, 0xa3, 0x4c, 0xba, 0x0e, 0x42, 0x8e, 0x10, 0x8d, 0x0c, 0xcb, 0x1e, 0x73, 0x8e, 0x28, - 0x4d, 0xe8, 0x95, 0x12, 0x42, 0xef, 0x36, 0x54, 0xc2, 0xe1, 0x99, 0x35, 0xb6, 0x2f, 0x87, 0x9e, - 0x3d, 0x90, 0xfb, 0x1b, 0xc2, 0xe1, 0xd9, 0x01, 0x41, 0xd8, 0x43, 0x80, 0xd1, 0x78, 0x2c, 0xf7, - 0x1e, 0xba, 0x1b, 0x63, 0x56, 0xde, 0x3d, 0x38, 0x20, 0x96, 0x33, 0xcb, 0xa3, 0xf1, 0x98, 0xfe, - 0x64, 0x9b, 0x50, 0x4f, 0xbd, 0x8b, 0x73, 0x4b, 0x25, 0x63, 0x79, 0xe3, 0x07, 0x29, 0x9b, 0xb3, - 0xd6, 0xd7, 0x61, 0x6b, 0xbf, 0x01, 0xec, 0x17, 0xbc, 0x11, 0xd3, 0x83, 0x72, 0xd4, 0x3f, 0xfd, - 0x42, 0x09, 0xa6, 0x57, 0x56, 0x12, 0x17, 0x4a, 0x5a, 0x83, 0x81, 0x2f, 0xe4, 0x22, 0x1d, 0x98, - 0x91, 0xc8, 0x07, 0xed, 0xc4, 0x6c, 0x91, 0xdc, 0x37, 0xfe, 0x3c, 0x03, 0x05, 0xba, 0xdd, 0xf2, - 0x06, 0xcc, 0x13, 0x7d, 0x94, 0xad, 0x22, 0x23, 0x44, 0x74, 0xee, 0xf6, 0x64, 0xa2, 0x8a, 0xd8, - 0x16, 0xda, 0xcd, 0xbc, 0x6c, 0xb4, 0xf2, 0xda, 0xed, 0xbc, 0xdb, 0x50, 0x8e, 0x9a, 0xd6, 0x58, - 0xa7, 0xa4, 0x5a, 0x66, 0xaf, 0x40, 0xfe, 0xd4, 0x1b, 0x2b, 0x5b, 0x1c, 0xe2, 0x99, 0x34, 0x11, - 0x1e, 0xf7, 0x45, 0xb4, 0x41, 0x9d, 0x97, 0x36, 0x64, 0xd4, 0x08, 0xb2, 0xc1, 0xec, 0x18, 0xe7, - 0x52, 0xc6, 0x78, 0x08, 0xf3, 0x42, 0x0e, 0x68, 0x91, 0xda, 0xab, 0x0f, 0xcd, 0x37, 0x85, 0x86, - 0xd7, 0x1f, 0x4e, 0x06, 0x5c, 0xf7, 0x84, 0x60, 0xea, 0x84, 0x84, 0x2b, 0xf3, 0xc0, 0xf8, 0x83, - 0x0c, 0xc9, 0x17, 0x51, 0x2f, 0xbb, 0x07, 0x79, 0x71, 0xbe, 0x4d, 0x79, 0xea, 0xa2, 0x3c, 0x57, - 0x41, 0x67, 0x22, 0x05, 0x5e, 0x67, 0x9d, 0x8c, 0x92, 0xb5, 0xd7, 0xcc, 0x8a, 0x3b, 0x19, 0x45, - 0xce, 0x84, 0xef, 0xa8, 0x61, 0x4d, 0x19, 0xe2, 0x34, 0xfa, 0x68, 0x9b, 0x3e, 0xd0, 0x72, 0x30, - 0xf2, 0x89, 0x13, 0x53, 0x69, 0x81, 0x83, 0x13, 0xae, 0xe5, 0x5e, 0xfc, 0x51, 0x16, 0x6a, 0x89, - 0x1e, 0x61, 0x12, 0x8a, 0x38, 0x00, 0xc8, 0x0b, 0x2c, 0xd7, 0x1b, 0x04, 0x48, 0x2a, 0xea, 0xda, - 0x3c, 0x65, 0x13, 0xf3, 0x14, 0xc5, 0xa4, 0x73, 0x7a, 0x4c, 0xfa, 0x11, 0x94, 0xe3, 0x1b, 0x99, - 0xc9, 0x2e, 0x89, 0xf6, 0x54, 0xb6, 0x6f, 0x4c, 0x14, 0x47, 0xb1, 0x0b, 0x7a, 0x14, 0xfb, 0x7b, - 0x5a, 0xd0, 0x73, 0x0e, 0xab, 0x31, 0xd2, 0x66, 0xf4, 0x57, 0x93, 0x14, 0xf1, 0x09, 0x54, 0xb4, - 0xce, 0xeb, 0xc1, 0xcd, 0x4c, 0x22, 0xb8, 0x19, 0xe5, 0xe5, 0x67, 0xe3, 0xbc, 0x7c, 0xe3, 0xb7, - 0xb3, 0x50, 0x13, 0xfb, 0xcb, 0x71, 0x4f, 0x0e, 0xbc, 0xa1, 0xd3, 0x47, 0xaf, 0x70, 0xb4, 0xc3, - 0xa4, 0xa2, 0xa5, 0xf6, 0x99, 0xdc, 0x62, 0xa4, 0x67, 0xe9, 0xd7, 0x8f, 0x48, 0x48, 0x47, 0xd7, - 0x8f, 0x0c, 0xa8, 0x09, 0xc1, 0x78, 0x64, 0x07, 0x5c, 0xbb, 0x2f, 0x6a, 0x56, 0x8e, 0x39, 0x5f, - 0xb7, 0x03, 0x92, 0x90, 0xef, 0xc0, 0xa2, 0xa0, 0xc1, 0x9b, 0x17, 0x23, 0x67, 0x38, 0x74, 0x88, - 0x92, 0x5c, 0x0d, 0x8d, 0x63, 0xce, 0x4d, 0x3b, 0xe4, 0xbb, 0x02, 0x21, 0xaf, 0x97, 0x96, 0x06, - 0x4e, 0x60, 0x1f, 0xc5, 0xa9, 0x42, 0xd1, 0x37, 0xc6, 0x72, 0xec, 0x0b, 0x2d, 0x96, 0x43, 0x57, - 0xb0, 0x2a, 0x23, 0xfb, 0x22, 0x8a, 0xe5, 0x4c, 0x71, 0x52, 0x71, 0x9a, 0x93, 0x8c, 0xff, 0x92, - 0x85, 0x8a, 0xc6, 0x96, 0x2f, 0x73, 0xba, 0xde, 0x9a, 0xf1, 0xe2, 0x97, 0x75, 0x87, 0xfd, 0x6b, - 0xc9, 0x26, 0x31, 0xe4, 0x4b, 0x17, 0x59, 0x35, 0x06, 0xbe, 0x01, 0x65, 0xb1, 0xeb, 0xde, 0x45, - 0xa7, 0x98, 0xbc, 0x86, 0x8d, 0x80, 0x83, 0xc9, 0x91, 0x42, 0x3e, 0x46, 0x64, 0x21, 0x46, 0x3e, - 0x16, 0xc8, 0xe7, 0xe5, 0x07, 0x7e, 0x08, 0x55, 0x59, 0x2b, 0xae, 0x29, 0x0e, 0x37, 0xde, 0xf5, - 0x89, 0xf5, 0x36, 0x2b, 0xd4, 0x1c, 0x2d, 0xbe, 0x2c, 0xf8, 0x58, 0x15, 0x2c, 0xbd, 0xa8, 0xe0, - 0x63, 0xfa, 0x30, 0xb6, 0xa2, 0x94, 0x4b, 0x4c, 0x37, 0x50, 0x72, 0xec, 0x21, 0x2c, 0x2a, 0x71, - 0x35, 0x71, 0x6d, 0xd7, 0xf5, 0x26, 0x6e, 0x9f, 0xab, 0x84, 0x7d, 0x26, 0x51, 0x87, 0x31, 0xc6, - 0x18, 0x44, 0x37, 0xba, 0x28, 0x6d, 0xe1, 0x3e, 0x14, 0x48, 0x2f, 0x27, 0xe5, 0x23, 0x5d, 0x70, - 0x11, 0x09, 0xbb, 0x07, 0x05, 0x52, 0xcf, 0xb3, 0x57, 0x0a, 0x1b, 0x22, 0x30, 0x1e, 0xc0, 0x3c, - 0xaa, 0x98, 0x9a, 0xc4, 0x7d, 0x9e, 0x56, 0x62, 0x2c, 0x01, 0xdb, 0xa3, 0x4d, 0xa4, 0xa7, 0xd3, - 0xfc, 0xcf, 0x1c, 0x54, 0x34, 0xb0, 0x10, 0x8b, 0x98, 0x80, 0x61, 0x0d, 0x1c, 0x7b, 0xc4, 0x55, - 0xec, 0xa1, 0x66, 0xd6, 0x10, 0xba, 0x29, 0x81, 0xe2, 0x50, 0xb0, 0xcf, 0x4e, 0x2c, 0x6f, 0x12, - 0x5a, 0x03, 0x7e, 0xe2, 0x73, 0x2e, 0x95, 0xa5, 0xaa, 0x7d, 0x76, 0xb2, 0x3f, 0x09, 0x37, 0x11, - 0x26, 0xa8, 0x04, 0x53, 0x6b, 0x54, 0x32, 0x67, 0x60, 0x64, 0x5f, 0xc4, 0x54, 0x32, 0x71, 0x85, - 0xa6, 0x28, 0x1f, 0x25, 0xae, 0x90, 0xd9, 0x32, 0x2d, 0xc9, 0x0b, 0xb3, 0x92, 0xfc, 0x3d, 0x58, - 0x21, 0x49, 0x2e, 0x65, 0x84, 0x35, 0xc5, 0x52, 0x4b, 0x88, 0x95, 0x83, 0xd4, 0xf4, 0xaf, 0x86, - 0x18, 0x81, 0xda, 0x1f, 0x81, 0xf3, 0x13, 0xda, 0x51, 0x19, 0x53, 0x8c, 0x4c, 0x56, 0xde, 0x75, - 0x7e, 0xc2, 0x05, 0x25, 0x06, 0x46, 0x75, 0x4a, 0x99, 0x86, 0x3a, 0x72, 0xdc, 0x69, 0x4a, 0xfb, - 0x22, 0x49, 0x59, 0x96, 0x94, 0xf6, 0x85, 0x4e, 0xf9, 0x3e, 0xac, 0x8e, 0xf8, 0xc0, 0xb1, 0x93, - 0xd5, 0x5a, 0xb1, 0x06, 0xb1, 0x44, 0x68, 0xad, 0x4c, 0x97, 0x2c, 0x48, 0x31, 0x1b, 0x3f, 0xf1, - 0x46, 0x47, 0x0e, 0x1d, 0x9e, 0x14, 0xaa, 0xcd, 0x9b, 0x75, 0x77, 0x32, 0xfa, 0x21, 0x82, 0x45, - 0x91, 0xc0, 0xa8, 0x41, 0xa5, 0x1b, 0x7a, 0x63, 0xb5, 0xcc, 0x75, 0xa8, 0xd2, 0xa7, 0xbc, 0x8e, - 0x71, 0x03, 0xae, 0x23, 0x6f, 0xf6, 0xbc, 0xb1, 0x37, 0xf4, 0x4e, 0x2e, 0x13, 0x0e, 0xa5, 0xff, - 0x9e, 0x81, 0xc5, 0x04, 0x56, 0xee, 0xf3, 0xf7, 0x68, 0x63, 0x45, 0x39, 0xf5, 0xc4, 0xce, 0x0b, - 0xda, 0xe1, 0x43, 0x84, 0xb4, 0xab, 0x54, 0x9e, 0x7d, 0x2b, 0xbe, 0x0b, 0xaa, 0x0a, 0x12, 0x6f, - 0x37, 0x67, 0x79, 0x5b, 0x96, 0x57, 0xb7, 0x44, 0x55, 0x15, 0x7f, 0x55, 0xa6, 0x0a, 0x0f, 0xe4, - 0x90, 0x73, 0xc9, 0x64, 0x48, 0xdd, 0xf9, 0xa4, 0x7a, 0x10, 0x7b, 0xa4, 0x02, 0xe3, 0x5f, 0x65, - 0x00, 0xe2, 0xde, 0x61, 0x3a, 0x66, 0x74, 0x80, 0xd2, 0x33, 0x2b, 0xda, 0x61, 0xf9, 0x2a, 0x54, - 0xa3, 0x8c, 0xb1, 0xf8, 0x48, 0xae, 0x28, 0x98, 0x38, 0x97, 0xef, 0xc2, 0xfc, 0xc9, 0xd0, 0x3b, - 0x42, 0xd5, 0x49, 0x1e, 0xa0, 0x74, 0x29, 0xa5, 0x4e, 0x60, 0x75, 0x2c, 0xc6, 0x07, 0x78, 0x3e, - 0x35, 0xa9, 0x4c, 0x3f, 0x8e, 0x8d, 0xdf, 0xc9, 0x46, 0xa9, 0x33, 0xf1, 0x4c, 0x3c, 0xdf, 0xce, - 0xf8, 0x36, 0x11, 0xd8, 0xe7, 0x45, 0x1e, 0x3e, 0x81, 0xba, 0x4f, 0xd2, 0x51, 0x89, 0xce, 0xfc, - 0x73, 0x44, 0x67, 0xcd, 0x4f, 0x1c, 0xb9, 0x6f, 0x42, 0xc3, 0x1e, 0x9c, 0x71, 0x3f, 0x74, 0xd0, - 0x59, 0x8b, 0x8a, 0x9a, 0x4c, 0x56, 0xd1, 0xe0, 0xa8, 0x11, 0xdd, 0x85, 0x79, 0x79, 0x45, 0x28, - 0xa2, 0x94, 0x8f, 0x0e, 0xc4, 0x60, 0x41, 0x68, 0xfc, 0x5b, 0x95, 0xab, 0x93, 0x5c, 0xdd, 0xe7, - 0xcf, 0x8a, 0x3e, 0xc2, 0xec, 0x6c, 0x6c, 0x45, 0x32, 0x92, 0xf4, 0x01, 0x4b, 0x79, 0x44, 0x40, - 0xe9, 0x01, 0x4e, 0x4e, 0x6b, 0xfe, 0x65, 0xa6, 0xd5, 0xf8, 0x93, 0x0c, 0x14, 0xb7, 0xbd, 0xb1, - 0xb0, 0xcb, 0x85, 0x3e, 0x87, 0xdb, 0x24, 0xba, 0x9e, 0x37, 0x27, 0x3e, 0x3b, 0x83, 0xe7, 0xa7, - 0xe5, 0xa7, 0xea, 0x1b, 0xb5, 0xa4, 0xbe, 0xf1, 0x3d, 0xb8, 0x81, 0xd1, 0x08, 0xdf, 0x1b, 0x7b, - 0xbe, 0xd8, 0xaa, 0xf6, 0x90, 0xf4, 0x0e, 0xcf, 0x0d, 0x4f, 0x95, 0xec, 0xbc, 0x7e, 0xcc, 0xf9, - 0x81, 0x46, 0xb1, 0x1b, 0x11, 0xe0, 0x5d, 0x93, 0x61, 0x78, 0x66, 0x91, 0xa9, 0x28, 0x15, 0x23, - 0x92, 0xa8, 0xf3, 0x02, 0xd1, 0x46, 0x38, 0xaa, 0x46, 0xc6, 0x47, 0x50, 0x8e, 0xbc, 0x0e, 0xec, - 0x2d, 0x28, 0x9f, 0x7a, 0x63, 0xe9, 0x9a, 0xc8, 0x24, 0xae, 0x2e, 0xc8, 0x51, 0x9b, 0xa5, 0x53, - 0xfa, 0x23, 0x30, 0x7e, 0x56, 0x84, 0x62, 0xc7, 0x3d, 0xf3, 0x9c, 0x3e, 0x66, 0xfb, 0x8c, 0xf8, - 0xc8, 0x53, 0xf7, 0x14, 0xc5, 0xdf, 0x18, 0xd1, 0x8f, 0x9f, 0x0e, 0xc8, 0xc9, 0x88, 0x7e, 0xf4, - 0x68, 0xc0, 0x32, 0xcc, 0xf9, 0xfa, 0xdd, 0xff, 0x82, 0x8f, 0xf9, 0x87, 0x91, 0xd1, 0x56, 0xd0, - 0xee, 0x79, 0x8a, 0xba, 0xe8, 0x4e, 0x3a, 0x4e, 0x19, 0xdd, 0x3d, 0x29, 0x23, 0x04, 0x27, 0xec, - 0x26, 0x14, 0xe5, 0x4d, 0x01, 0xca, 0xbb, 0xa6, 0x84, 0x41, 0x09, 0x42, 0x6e, 0xf0, 0x39, 0x45, - 0x93, 0x22, 0x8d, 0x4a, 0xd8, 0xe9, 0x12, 0xb8, 0x29, 0x78, 0xed, 0x36, 0x54, 0x88, 0x9e, 0x48, - 0x4a, 0x32, 0x3f, 0x07, 0x41, 0x48, 0x90, 0xf2, 0x84, 0x46, 0x39, 0xf5, 0x09, 0x0d, 0x4c, 0xe7, - 0x8a, 0xa4, 0x2c, 0x0d, 0x11, 0xe8, 0xe1, 0x04, 0x0d, 0xae, 0xde, 0x8f, 0x91, 0xc6, 0x3d, 0x5d, - 0xa3, 0x52, 0xc6, 0xfd, 0x6b, 0x50, 0x3b, 0xb6, 0x87, 0xc3, 0x23, 0xbb, 0xff, 0x8c, 0x6c, 0xd2, - 0x2a, 0xb9, 0xe1, 0x14, 0x10, 0x8d, 0xd2, 0xdb, 0x50, 0xd1, 0x56, 0x19, 0x93, 0x6f, 0xf2, 0x26, - 0xc4, 0xeb, 0x3b, 0xed, 0x6a, 0xaa, 0xbf, 0x84, 0xab, 0x49, 0x4b, 0x42, 0x9a, 0x4f, 0x26, 0x21, - 0xdd, 0x40, 0x69, 0x2a, 0x13, 0x55, 0x1a, 0x74, 0x4b, 0xdf, 0x1e, 0x0c, 0x30, 0x51, 0x85, 0x9e, - 0xc4, 0xc2, 0xc9, 0x23, 0xfc, 0x02, 0x29, 0xb5, 0x04, 0x23, 0x92, 0x5b, 0xe4, 0x2f, 0x1d, 0xdb, - 0xce, 0x00, 0x93, 0x3e, 0xc9, 0x8c, 0x2d, 0xda, 0xa3, 0xf0, 0xc0, 0x76, 0x06, 0xec, 0x0e, 0x54, - 0x15, 0x1a, 0x4f, 0xc7, 0x45, 0x9a, 0x7f, 0x89, 0x16, 0x67, 0xa2, 0x01, 0xb5, 0x88, 0x62, 0x14, - 0xdf, 0x85, 0xaa, 0x48, 0x12, 0xe4, 0x83, 0x77, 0x31, 0xf8, 0x1f, 0x72, 0xbc, 0xf1, 0x54, 0x7f, - 0x7c, 0x43, 0x8e, 0x55, 0x72, 0xa9, 0xfa, 0x1f, 0x33, 0x1d, 0x4c, 0xa2, 0x14, 0x8a, 0x18, 0x85, - 0x68, 0x56, 0x12, 0x8a, 0x98, 0x24, 0xc5, 0x10, 0x0d, 0x11, 0xb0, 0x8f, 0x34, 0x43, 0xaa, 0x89, - 0xc4, 0x37, 0xa7, 0xea, 0xbf, 0xc2, 0x84, 0x12, 0xdc, 0xeb, 0x04, 0xe2, 0x94, 0x09, 0xb8, 0x3b, - 0xc0, 0x0b, 0x50, 0x25, 0xb3, 0xec, 0x04, 0x4f, 0x09, 0xf0, 0xcb, 0xb5, 0xb0, 0x5a, 0x50, 0xd5, - 0x87, 0xc9, 0x4a, 0x90, 0xdf, 0x3f, 0x68, 0xef, 0x35, 0xae, 0xb1, 0x0a, 0x14, 0xbb, 0xed, 0x5e, - 0x6f, 0xa7, 0xbd, 0xd9, 0xc8, 0xb0, 0x2a, 0x94, 0xa2, 0x6b, 0x1c, 0x59, 0xf1, 0xd5, 0xda, 0xd8, - 0x68, 0x1f, 0xf4, 0xda, 0x9b, 0x8d, 0xdc, 0xf7, 0xf3, 0xa5, 0x6c, 0x23, 0x67, 0xfc, 0x59, 0x0e, - 0x2a, 0xda, 0x2c, 0x3c, 0x5f, 0x18, 0xdf, 0x02, 0x40, 0x93, 0x26, 0xce, 0x63, 0xca, 0x9b, 0x65, - 0x01, 0xa1, 0xc5, 0xd7, 0x9d, 0xe5, 0x39, 0x7a, 0xfe, 0x41, 0x39, 0xcb, 0x5f, 0x83, 0x1a, 0xbd, - 0xa4, 0xa0, 0x87, 0xeb, 0x0a, 0x66, 0x95, 0x80, 0x52, 0x54, 0xe3, 0x3d, 0x30, 0x24, 0xc2, 0x1b, - 0x02, 0xf2, 0x5e, 0x35, 0x81, 0xf0, 0x8e, 0x00, 0x5e, 0xf0, 0x08, 0xbc, 0xe1, 0x19, 0x27, 0x0a, - 0xd2, 0x08, 0x2b, 0x12, 0xd6, 0x93, 0x17, 0xd1, 0xa4, 0x3c, 0xd4, 0x2e, 0x22, 0x15, 0xcc, 0x2a, - 0x01, 0x65, 0x43, 0xef, 0x28, 0x06, 0x2a, 0x21, 0x03, 0xad, 0xce, 0x72, 0x43, 0x82, 0x79, 0x76, - 0x66, 0xfc, 0x59, 0x65, 0x64, 0x8c, 0xef, 0xcc, 0x96, 0x7b, 0xb1, 0x5f, 0x8b, 0xbd, 0x05, 0x6c, - 0x34, 0x1e, 0x5b, 0x29, 0x9e, 0xa6, 0xbc, 0x39, 0x3f, 0x1a, 0x8f, 0x7b, 0x9a, 0x23, 0xe6, 0x97, - 0xe0, 0x04, 0xfb, 0x12, 0x58, 0x4b, 0x6c, 0x60, 0xec, 0x62, 0xe4, 0x42, 0x8d, 0xc5, 0x72, 0x46, - 0x17, 0xcb, 0x29, 0xd2, 0x2f, 0x9b, 0x2a, 0xfd, 0x9e, 0x27, 0x27, 0x8c, 0x2d, 0xa8, 0x1c, 0x68, - 0xef, 0xb4, 0xdc, 0x11, 0x27, 0x84, 0x7a, 0xa1, 0x85, 0xce, 0x0e, 0x72, 0x6e, 0xf9, 0xf2, 0x61, - 0x16, 0xad, 0x37, 0x59, 0xad, 0x37, 0xc6, 0xbf, 0xcc, 0xd0, 0x1d, 0xf8, 0xa8, 0xf3, 0xf1, 0xd3, - 0x30, 0x2a, 0x0e, 0x14, 0xdf, 0x17, 0xac, 0xa8, 0xf8, 0x8f, 0xbc, 0xea, 0x87, 0x5d, 0xb3, 0xbc, - 0xe3, 0xe3, 0x80, 0xab, 0x9b, 0x2f, 0x15, 0x84, 0xed, 0x23, 0x48, 0x29, 0xdf, 0x42, 0xc3, 0x77, - 0xa8, 0xfe, 0x40, 0xde, 0x80, 0x11, 0xca, 0xf7, 0xae, 0x7d, 0x21, 0x5b, 0x0d, 0x84, 0x0a, 0x22, - 0x1d, 0xd5, 0xea, 0xbe, 0x4f, 0xf4, 0x6d, 0xfc, 0x33, 0x79, 0xa5, 0x71, 0x7a, 0x7e, 0xef, 0x43, - 0x29, 0xaa, 0x35, 0x79, 0xc2, 0x2a, 0xca, 0x08, 0x2f, 0xce, 0x71, 0xb4, 0xca, 0x13, 0x3d, 0xa6, - 0xcd, 0x85, 0xc1, 0x86, 0x8e, 0xd6, 0xeb, 0xb7, 0x81, 0x1d, 0x3b, 0xfe, 0x34, 0x31, 0x6d, 0xb6, - 0x06, 0x62, 0x34, 0x6a, 0xe3, 0x10, 0x16, 0x95, 0x94, 0xd0, 0x2c, 0x82, 0xe4, 0xe2, 0x65, 0x5e, - 0x20, 0xe4, 0xb3, 0x33, 0x42, 0xde, 0xf8, 0x69, 0x1e, 0x8a, 0xea, 0xcd, 0xa3, 0xb4, 0x77, 0x7a, - 0xca, 0xc9, 0x77, 0x7a, 0x9a, 0x89, 0x37, 0x1d, 0x70, 0xe9, 0xe5, 0x79, 0x7f, 0x77, 0xfa, 0xc8, - 0xd6, 0x9c, 0xe6, 0x89, 0x63, 0x7b, 0x05, 0xf2, 0x63, 0x3b, 0x3c, 0x45, 0x07, 0x19, 0x31, 0x0f, - 0x7e, 0x2b, 0x67, 0x7a, 0x21, 0xe9, 0x4c, 0x4f, 0x7b, 0xd3, 0x88, 0x54, 0xd2, 0x99, 0x37, 0x8d, - 0x6e, 0x00, 0xe9, 0x17, 0x5a, 0x3e, 0x4c, 0x09, 0x01, 0xe2, 0x2c, 0x4a, 0xaa, 0x23, 0xa5, 0x69, - 0x75, 0xe4, 0xa5, 0x55, 0x85, 0xf7, 0x60, 0x8e, 0xee, 0x03, 0xcb, 0x7b, 0x4d, 0xea, 0x40, 0x91, - 0x73, 0xa8, 0xfe, 0xa7, 0x24, 0x58, 0x53, 0xd2, 0xea, 0x0f, 0x84, 0x54, 0x12, 0x0f, 0x84, 0xe8, - 0x4e, 0xfe, 0x6a, 0xd2, 0xc9, 0x7f, 0x0f, 0x1a, 0xd1, 0x84, 0xa2, 0xcb, 0xcc, 0x0d, 0xe4, 0x8d, - 0x8e, 0xba, 0x82, 0x0b, 0x29, 0xb9, 0x17, 0xc4, 0x07, 0x62, 0x3d, 0x71, 0x20, 0x0a, 0x19, 0xd6, - 0x0a, 0x43, 0x3e, 0x1a, 0x87, 0xf2, 0x40, 0xc4, 0x9c, 0x6f, 0xbd, 0x83, 0xc9, 0x1b, 0x7f, 0x35, - 0x28, 0x77, 0xf6, 0xac, 0xad, 0x9d, 0xce, 0x93, 0xed, 0x5e, 0x23, 0x23, 0x3e, 0xbb, 0x87, 0x1b, - 0x1b, 0xed, 0xf6, 0x26, 0x9e, 0x38, 0x00, 0x73, 0x5b, 0xad, 0x8e, 0x38, 0x7d, 0x72, 0xc6, 0x5f, - 0x66, 0xa0, 0xa2, 0x55, 0xcf, 0xde, 0x8f, 0x66, 0x85, 0xde, 0x90, 0xb8, 0x35, 0xdb, 0x85, 0x07, - 0x4a, 0x14, 0x6b, 0xd3, 0x12, 0xbd, 0xe0, 0x94, 0xbd, 0xf2, 0x05, 0x27, 0xf6, 0x06, 0xcc, 0xdb, - 0x54, 0x43, 0x34, 0x0b, 0xd2, 0x1d, 0x2c, 0xc1, 0x72, 0x12, 0x30, 0x0b, 0x2c, 0x3e, 0x4f, 0x04, - 0x5d, 0x5e, 0x25, 0x5e, 0x45, 0x47, 0xca, 0x5e, 0x60, 0x7c, 0x00, 0x10, 0xf7, 0x24, 0x39, 0xe4, - 0x6b, 0xc9, 0x21, 0x67, 0xb4, 0x21, 0x67, 0x8d, 0x4d, 0x12, 0x0e, 0x72, 0xfa, 0xa2, 0xf8, 0xf3, - 0x3b, 0xa0, 0xfc, 0x4c, 0x16, 0x66, 0x57, 0x8e, 0x87, 0x3c, 0x54, 0x37, 0x1e, 0x17, 0x24, 0xa6, - 0x13, 0x21, 0xd4, 0x05, 0xe4, 0xb8, 0x96, 0x58, 0xc6, 0x48, 0x46, 0x9b, 0x96, 0x31, 0x92, 0xd4, - 0x8c, 0xf0, 0xc6, 0x1a, 0x34, 0x37, 0xb9, 0xa8, 0xad, 0x35, 0x1c, 0x4e, 0x75, 0xc7, 0xb8, 0x01, - 0xd7, 0x53, 0x70, 0xd2, 0xb5, 0xf0, 0x29, 0x2c, 0xb7, 0xe8, 0x72, 0xe3, 0x2f, 0xeb, 0x86, 0x85, - 0xd1, 0x84, 0x95, 0xe9, 0x2a, 0x65, 0x63, 0x5b, 0xb0, 0xb0, 0xc9, 0x8f, 0x26, 0x27, 0x3b, 0xfc, - 0x2c, 0x6e, 0x88, 0x41, 0x3e, 0x38, 0xf5, 0xce, 0xe5, 0xfc, 0xe0, 0xdf, 0x62, 0x67, 0x0e, 0x05, - 0x8d, 0x15, 0x8c, 0x79, 0x5f, 0xf9, 0x39, 0x11, 0xd2, 0x1d, 0xf3, 0xbe, 0xf1, 0x3e, 0x30, 0xbd, - 0x1e, 0x39, 0x5f, 0x42, 0xf7, 0x9f, 0x1c, 0x59, 0xc1, 0x65, 0x10, 0xf2, 0x91, 0x7a, 0x78, 0x04, - 0x82, 0xc9, 0x51, 0x97, 0x20, 0xc6, 0x5d, 0xa8, 0x1e, 0xd8, 0x97, 0x26, 0xff, 0x52, 0xde, 0x1d, - 0x58, 0x85, 0xe2, 0xd8, 0xbe, 0x14, 0x9b, 0x3b, 0x0a, 0x79, 0x20, 0xda, 0xf8, 0xc3, 0x3c, 0xcc, - 0x11, 0x25, 0xbb, 0x43, 0x6f, 0x03, 0x3a, 0x2e, 0x6e, 0x2e, 0x25, 0xfe, 0x34, 0xd0, 0x8c, 0x84, - 0xcc, 0xce, 0x4a, 0x48, 0xe9, 0x16, 0x53, 0x6f, 0x22, 0x28, 0xe7, 0xb4, 0x3b, 0x19, 0xa9, 0x87, - 0x10, 0xd8, 0x4d, 0x28, 0xc7, 0x97, 0xb4, 0xf2, 0xf1, 0xdb, 0x8f, 0x74, 0x35, 0x2b, 0x19, 0x3e, - 0x8c, 0x2d, 0x0c, 0xea, 0x9d, 0x12, 0xfc, 0x52, 0x08, 0xea, 0xa0, 0x54, 0x33, 0xa6, 0xa8, 0x6e, - 0xa5, 0x24, 0xcd, 0x98, 0x19, 0x73, 0xa5, 0xf4, 0x62, 0x73, 0x85, 0xfc, 0x65, 0xcf, 0x31, 0x57, - 0xe0, 0x25, 0xcc, 0x95, 0x97, 0x08, 0xdd, 0x5d, 0x87, 0x12, 0x9e, 0xe6, 0x9a, 0x4c, 0x14, 0xa7, - 0xb8, 0x90, 0x89, 0x1f, 0x6a, 0x0a, 0x3d, 0xe5, 0x0d, 0xdc, 0x88, 0xb7, 0x89, 0xc9, 0xbf, 0xfc, - 0xd5, 0x84, 0x44, 0xbe, 0x80, 0xa2, 0x84, 0x0a, 0x86, 0x76, 0xed, 0x91, 0x7a, 0x56, 0x06, 0xff, - 0x16, 0xd3, 0x86, 0x6f, 0x61, 0x7c, 0x39, 0x71, 0x7c, 0x3e, 0x50, 0x8f, 0x17, 0x38, 0xb8, 0x47, - 0x05, 0x44, 0x0c, 0x50, 0x18, 0x17, 0xae, 0x77, 0xee, 0xca, 0xab, 0xcb, 0x45, 0x27, 0x78, 0x2a, - 0x3e, 0x0d, 0x06, 0x0d, 0x7c, 0x58, 0x6a, 0xec, 0xf9, 0xea, 0xc8, 0x31, 0x7e, 0x9a, 0x81, 0x86, - 0xdc, 0x5d, 0x11, 0x4e, 0xd7, 0xed, 0x0b, 0x57, 0x85, 0xb9, 0x9f, 0xff, 0x14, 0x81, 0x01, 0x35, - 0x74, 0x69, 0x44, 0xe7, 0x0f, 0xb9, 0x64, 0x2a, 0x02, 0xb8, 0x25, 0xcf, 0xa0, 0x57, 0xa0, 0xa2, - 0x92, 0x2c, 0x47, 0xce, 0x50, 0x3d, 0xf3, 0x4a, 0x59, 0x96, 0xbb, 0xce, 0x50, 0x1d, 0x5f, 0xbe, - 0x2d, 0x6f, 0x49, 0x65, 0xf0, 0xf8, 0x32, 0xed, 0x90, 0x1b, 0xff, 0x29, 0x03, 0x0b, 0xda, 0x50, - 0xe4, 0xbe, 0xfd, 0x18, 0xaa, 0xd1, 0x8b, 0x6e, 0x3c, 0xd2, 0xa7, 0x56, 0x93, 0x82, 0x26, 0x2e, - 0x56, 0xe9, 0x47, 0x90, 0x40, 0x74, 0x66, 0x60, 0x5f, 0x62, 0x7f, 0x83, 0xc9, 0x48, 0x99, 0x2c, - 0x03, 0xfb, 0x72, 0x8b, 0xf3, 0xee, 0x64, 0x24, 0x0c, 0xd2, 0x73, 0xce, 0x9f, 0x45, 0x04, 0xa4, - 0x49, 0x81, 0x80, 0x49, 0x0a, 0x03, 0x6a, 0x23, 0xcf, 0x0d, 0x4f, 0x23, 0x12, 0xa9, 0x4b, 0x22, - 0x90, 0x68, 0x8c, 0xff, 0x91, 0x85, 0x45, 0x72, 0x9c, 0x49, 0x87, 0xa5, 0x14, 0x5d, 0x4d, 0x98, - 0x23, 0x1f, 0x22, 0x09, 0xaf, 0xed, 0x6b, 0xa6, 0xfc, 0x66, 0xef, 0xbd, 0xa4, 0xb3, 0x4f, 0x5d, - 0xc4, 0xba, 0x62, 0xfa, 0x73, 0xb3, 0xd3, 0x7f, 0xf5, 0xf4, 0xa6, 0xc5, 0xd1, 0x0a, 0x69, 0x71, - 0xb4, 0x97, 0x89, 0x5e, 0xcd, 0xdc, 0x56, 0x2a, 0x4a, 0x1a, 0xed, 0xb6, 0xd2, 0xfb, 0xb0, 0x9a, - 0xa0, 0x41, 0x69, 0xed, 0x1c, 0x3b, 0x5c, 0xdd, 0x0c, 0x5f, 0xd2, 0xa8, 0xbb, 0x0a, 0xb7, 0x5e, - 0x84, 0x42, 0xd0, 0xf7, 0xc6, 0xdc, 0x58, 0x81, 0xa5, 0xe4, 0xac, 0xca, 0x63, 0xe2, 0xf7, 0x33, - 0xd0, 0x94, 0x59, 0x0f, 0x8e, 0x7b, 0xb2, 0xed, 0x04, 0xa1, 0xe7, 0x47, 0x2f, 0x9f, 0xdd, 0x02, - 0x08, 0x42, 0xdb, 0x97, 0x36, 0x24, 0x69, 0xb7, 0x65, 0x84, 0xa0, 0x7d, 0x78, 0x1d, 0x4a, 0xdc, - 0x1d, 0x10, 0x92, 0xb8, 0xa1, 0xc8, 0xdd, 0x81, 0xb2, 0x2e, 0x67, 0xb4, 0xea, 0x5a, 0xd2, 0x68, - 0x90, 0xd7, 0x26, 0xc5, 0xec, 0xf0, 0x33, 0x3c, 0x78, 0xf3, 0xd1, 0xb5, 0xc9, 0x5d, 0xfb, 0x02, - 0x73, 0x08, 0x03, 0xe3, 0x1f, 0x67, 0x61, 0x3e, 0xee, 0x1f, 0xdd, 0xb9, 0x4e, 0xc8, 0x6f, 0xd9, - 0xab, 0x58, 0x7e, 0xdf, 0x91, 0xec, 0xe0, 0x08, 0xad, 0x5c, 0x73, 0x27, 0x96, 0x68, 0x73, 0x76, - 0x5c, 0x66, 0x40, 0x45, 0x51, 0x78, 0x93, 0x50, 0x7b, 0x80, 0xa8, 0x4c, 0x24, 0xfb, 0x93, 0x50, - 0x98, 0x51, 0xc2, 0x9e, 0x74, 0x5c, 0x69, 0xc8, 0x14, 0xec, 0x51, 0xd8, 0xc1, 0x77, 0x8d, 0x05, - 0x58, 0x14, 0xa3, 0x85, 0x14, 0x54, 0x82, 0xbe, 0x41, 0xda, 0x33, 0xad, 0x1c, 0x6a, 0xce, 0xba, - 0x6a, 0x49, 0x4f, 0x3c, 0x46, 0xaa, 0xe5, 0x2b, 0x50, 0xa1, 0xca, 0xe3, 0xcb, 0x69, 0x79, 0xb3, - 0x8c, 0x2d, 0x20, 0x5e, 0xba, 0x76, 0xbc, 0x49, 0xc2, 0xa0, 0x05, 0x6a, 0x0a, 0x93, 0x0a, 0xfe, - 0x41, 0x06, 0xae, 0xa7, 0x2c, 0x9b, 0xdc, 0xe5, 0x1b, 0xb0, 0x70, 0x1c, 0x21, 0xd5, 0xec, 0xd2, - 0x56, 0x5f, 0x51, 0x62, 0x35, 0x39, 0xa7, 0x66, 0xe3, 0x38, 0x09, 0x88, 0x4d, 0x29, 0x5a, 0xc1, - 0xc4, 0xfd, 0x43, 0x34, 0xa5, 0x68, 0x19, 0xc9, 0x8a, 0x39, 0x80, 0xb5, 0xf6, 0x85, 0x90, 0x18, - 0x1b, 0xfa, 0xc3, 0xdc, 0x8a, 0x8d, 0x92, 0x6e, 0xe3, 0xcc, 0x4b, 0xb9, 0x8d, 0x07, 0x74, 0xcd, - 0x2a, 0xaa, 0xeb, 0xdb, 0x54, 0x82, 0x07, 0xa8, 0x28, 0x43, 0x0f, 0x8b, 0xab, 0x3b, 0x90, 0xfd, - 0xe8, 0x41, 0x71, 0x23, 0x80, 0xf9, 0xdd, 0xc9, 0x30, 0x74, 0xe2, 0x37, 0xc6, 0xd9, 0x7b, 0xb2, - 0x0c, 0xb6, 0xa3, 0x66, 0x2d, 0xb5, 0x21, 0x88, 0x1a, 0xc2, 0xc9, 0x1a, 0x89, 0x8a, 0xac, 0xd9, - 0xf6, 0xe6, 0x47, 0xc9, 0x16, 0x8c, 0xeb, 0xb0, 0x1a, 0x7f, 0xd1, 0xb4, 0xa9, 0xa3, 0xe6, 0x5f, - 0x64, 0x28, 0x61, 0x39, 0xf9, 0xde, 0x39, 0x6b, 0xc3, 0x62, 0xe0, 0xb8, 0x27, 0x43, 0xae, 0x57, - 0x1f, 0xc8, 0x49, 0x58, 0x4e, 0xf6, 0x4d, 0xbe, 0x89, 0x6e, 0x2e, 0x50, 0x89, 0xb8, 0xb6, 0x80, - 0xad, 0x5f, 0xd5, 0xc9, 0x98, 0x2d, 0xa6, 0x66, 0x63, 0xb6, 0xf3, 0x1d, 0xa8, 0x27, 0x1b, 0x62, - 0x1f, 0xca, 0x2b, 0x86, 0x71, 0xaf, 0x72, 0x53, 0xb7, 0xc5, 0x62, 0x86, 0xa8, 0xc4, 0x73, 0x1f, - 0x18, 0xff, 0x30, 0x03, 0x4d, 0x93, 0x0b, 0xce, 0xd5, 0x7a, 0xa9, 0x78, 0xe6, 0xe3, 0x99, 0x5a, - 0xaf, 0x1e, 0xab, 0xba, 0xb9, 0xa8, 0x7a, 0xf4, 0xf6, 0x95, 0x8b, 0xb1, 0x7d, 0x6d, 0x66, 0x44, - 0xeb, 0x25, 0x98, 0x23, 0x12, 0x63, 0x15, 0x96, 0x65, 0x7f, 0x54, 0x5f, 0xe2, 0x98, 0x60, 0xa2, - 0xc5, 0x44, 0x4c, 0x70, 0x0d, 0x9a, 0xf4, 0x80, 0x9d, 0x3e, 0x08, 0x59, 0x70, 0x13, 0xd8, 0xae, - 0xdd, 0xb7, 0x7d, 0xcf, 0x73, 0x0f, 0xb8, 0x2f, 0xd3, 0x3f, 0x51, 0xc3, 0xc4, 0x90, 0x99, 0x52, - 0x85, 0xe9, 0x4b, 0x3d, 0xbb, 0xe6, 0xb9, 0x2a, 0xdb, 0x85, 0xbe, 0x0c, 0x13, 0x16, 0xd7, 0xed, - 0x67, 0x5c, 0xd5, 0xa4, 0xa6, 0xe8, 0x13, 0xa8, 0x8c, 0xa3, 0x4a, 0xd5, 0xbc, 0xab, 0x7b, 0xc8, - 0xb3, 0xcd, 0x9a, 0x3a, 0xb5, 0xf1, 0x18, 0x96, 0x92, 0x75, 0x4a, 0xd1, 0xb1, 0x06, 0xa5, 0x91, - 0x84, 0xc9, 0xde, 0x45, 0xdf, 0xc6, 0xff, 0x2d, 0x42, 0x71, 0xcb, 0x76, 0x86, 0x42, 0xf1, 0x7a, - 0x00, 0xf9, 0xbe, 0xca, 0x38, 0x8a, 0x9f, 0xb7, 0x90, 0x58, 0xf5, 0xff, 0x06, 0xe6, 0x1d, 0x09, - 0x3a, 0xf6, 0x09, 0xd4, 0x93, 0xb1, 0xce, 0xa9, 0x4b, 0x8e, 0xc9, 0x20, 0x65, 0xad, 0x3f, 0x15, - 0xd5, 0x2a, 0xc7, 0x87, 0x23, 0xe9, 0x0c, 0xa5, 0x53, 0xed, 0xf4, 0xf4, 0x5c, 0xa1, 0x6f, 0x07, - 0xa7, 0xb6, 0xf5, 0xf8, 0xfd, 0x0f, 0xe4, 0x2d, 0xc7, 0x0a, 0x02, 0xbb, 0xa7, 0xf6, 0xe3, 0xf7, - 0x3f, 0x98, 0xd6, 0xa4, 0xe9, 0xa2, 0x9b, 0xae, 0x49, 0x2f, 0x41, 0x81, 0xde, 0x17, 0xa3, 0xd4, - 0x11, 0xfa, 0x60, 0x8f, 0x60, 0xe9, 0x98, 0x46, 0x62, 0xc9, 0x24, 0x5f, 0x92, 0x82, 0x25, 0xba, - 0x59, 0x23, 0x71, 0x5d, 0x44, 0x91, 0xc7, 0x67, 0x05, 0xe6, 0x4e, 0xe3, 0xc7, 0xe2, 0x6a, 0xa6, - 0xfc, 0x32, 0xfe, 0x6b, 0x01, 0x2a, 0xda, 0xa4, 0xb0, 0x2a, 0x94, 0xcc, 0x76, 0xb7, 0x6d, 0x7e, - 0xd6, 0xde, 0x6c, 0x5c, 0x63, 0xf7, 0xe0, 0xf5, 0xce, 0xde, 0xc6, 0xbe, 0x69, 0xb6, 0x37, 0x7a, - 0xd6, 0xbe, 0x69, 0xa9, 0x97, 0x4f, 0x0e, 0x5a, 0x5f, 0xec, 0xb6, 0xf7, 0x7a, 0xd6, 0x66, 0xbb, - 0xd7, 0xea, 0xec, 0x74, 0x1b, 0x19, 0x76, 0x13, 0x9a, 0x31, 0xa5, 0x42, 0xb7, 0x76, 0xf7, 0x0f, - 0xf7, 0x7a, 0x8d, 0x2c, 0xbb, 0x0d, 0x37, 0xb6, 0x3a, 0x7b, 0xad, 0x1d, 0x2b, 0xa6, 0xd9, 0xd8, - 0xe9, 0x7d, 0x66, 0xb5, 0x7f, 0x70, 0xd0, 0x31, 0xbf, 0x68, 0xe4, 0xd2, 0x08, 0x84, 0x31, 0xae, - 0x6a, 0xc8, 0xb3, 0xeb, 0xb0, 0x4c, 0x04, 0x54, 0xc4, 0xea, 0xed, 0xef, 0x5b, 0xdd, 0xfd, 0xfd, - 0xbd, 0x46, 0x81, 0x2d, 0x40, 0xad, 0xb3, 0xf7, 0x59, 0x6b, 0xa7, 0xb3, 0x69, 0x99, 0xed, 0xd6, - 0xce, 0x6e, 0x63, 0x8e, 0x2d, 0xc2, 0xfc, 0x34, 0x5d, 0x51, 0x54, 0xa1, 0xe8, 0xf6, 0xf7, 0x3a, - 0xfb, 0x7b, 0xd6, 0x67, 0x6d, 0xb3, 0xdb, 0xd9, 0xdf, 0x6b, 0x94, 0xd8, 0x0a, 0xb0, 0x24, 0x6a, - 0x7b, 0xb7, 0xb5, 0xd1, 0x28, 0xb3, 0x65, 0x58, 0x48, 0xc2, 0x9f, 0xb6, 0xbf, 0x68, 0x00, 0x6b, - 0xc2, 0x12, 0x75, 0xcc, 0x5a, 0x6f, 0xef, 0xec, 0x7f, 0x6e, 0xed, 0x76, 0xf6, 0x3a, 0xbb, 0x87, - 0xbb, 0x8d, 0x0a, 0x3e, 0xad, 0xd4, 0x6e, 0x5b, 0x9d, 0xbd, 0xee, 0xe1, 0xd6, 0x56, 0x67, 0xa3, - 0xd3, 0xde, 0xeb, 0x35, 0xaa, 0xd4, 0x72, 0xda, 0xc0, 0x6b, 0xa2, 0x80, 0xbc, 0x09, 0x60, 0x6d, - 0x76, 0xba, 0xad, 0xf5, 0x9d, 0xf6, 0x66, 0xa3, 0xce, 0x6e, 0xc1, 0xf5, 0x5e, 0x7b, 0xf7, 0x60, - 0xdf, 0x6c, 0x99, 0x5f, 0xa8, 0x9b, 0x02, 0xd6, 0x56, 0xab, 0xb3, 0x73, 0x68, 0xb6, 0x1b, 0xf3, - 0xec, 0x55, 0xb8, 0x65, 0xb6, 0x3f, 0x3d, 0xec, 0x98, 0xed, 0x4d, 0x6b, 0x6f, 0x7f, 0xb3, 0x6d, - 0x6d, 0xb5, 0x5b, 0xbd, 0x43, 0xb3, 0x6d, 0xed, 0x76, 0xba, 0xdd, 0xce, 0xde, 0x93, 0x46, 0x83, - 0xbd, 0x0e, 0x77, 0x22, 0x92, 0xa8, 0x82, 0x29, 0xaa, 0x05, 0x31, 0x3e, 0xb5, 0xa4, 0x7b, 0xed, - 0x1f, 0xf4, 0xac, 0x83, 0x76, 0xdb, 0x6c, 0x30, 0xb6, 0x06, 0x2b, 0x71, 0xf3, 0xd4, 0x80, 0x6c, - 0x7b, 0x51, 0xe0, 0x0e, 0xda, 0xe6, 0x6e, 0x6b, 0x4f, 0x2c, 0x70, 0x02, 0xb7, 0x24, 0xba, 0x1d, - 0xe3, 0xa6, 0xbb, 0xbd, 0xcc, 0x18, 0xd4, 0xb5, 0x55, 0xd9, 0x6a, 0x99, 0x8d, 0x15, 0x36, 0x0f, - 0x95, 0xdd, 0x83, 0x03, 0xab, 0xd7, 0xd9, 0x6d, 0xef, 0x1f, 0xf6, 0x1a, 0xab, 0x6c, 0x09, 0xe6, - 0x55, 0x97, 0x54, 0xc9, 0x9f, 0x17, 0xd9, 0x2a, 0xb0, 0xc3, 0x3d, 0xb3, 0xdd, 0xda, 0x14, 0x33, - 0x14, 0x21, 0xfe, 0x4f, 0x51, 0x06, 0x38, 0x7e, 0x9a, 0x8b, 0x4e, 0xe5, 0x38, 0x63, 0x20, 0xf9, - 0x46, 0x68, 0x55, 0x7b, 0xdb, 0xf3, 0x45, 0xaf, 0x77, 0x6b, 0x36, 0x54, 0x6e, 0xc6, 0x86, 0x9a, - 0x31, 0xd2, 0x6b, 0xba, 0x92, 0xf7, 0x1a, 0xd4, 0x46, 0xf4, 0x5e, 0xa8, 0x7c, 0x17, 0x10, 0x64, - 0xfa, 0x0c, 0x01, 0xe9, 0x51, 0xc0, 0x99, 0xe7, 0xab, 0x0b, 0xb3, 0xcf, 0x57, 0xa7, 0x29, 0xf2, - 0x73, 0x69, 0x8a, 0xfc, 0x7d, 0x58, 0x20, 0x19, 0xe4, 0xb8, 0xce, 0x48, 0x99, 0xc7, 0xa4, 0xee, - 0xcd, 0xa3, 0x2c, 0x22, 0xb8, 0xb2, 0x1b, 0x94, 0x6d, 0x21, 0x65, 0x45, 0x51, 0x9a, 0x15, 0x09, - 0x93, 0x82, 0x44, 0x44, 0x64, 0x52, 0x44, 0x2d, 0xd8, 0x17, 0x71, 0x0b, 0x15, 0xad, 0x05, 0x82, - 0x63, 0x0b, 0xf7, 0x61, 0x81, 0x5f, 0x84, 0xbe, 0x6d, 0x79, 0x63, 0xfb, 0xcb, 0x09, 0x46, 0x60, - 0x6d, 0x34, 0xd6, 0xab, 0xe6, 0x3c, 0x22, 0xf6, 0x11, 0xbe, 0x69, 0x87, 0xf6, 0xfd, 0xaf, 0xa1, - 0xa2, 0xbd, 0x25, 0xcb, 0x56, 0x61, 0xf1, 0xf3, 0x4e, 0x6f, 0xaf, 0xdd, 0xed, 0x5a, 0x07, 0x87, - 0xeb, 0x4f, 0xdb, 0x5f, 0x58, 0xdb, 0xad, 0xee, 0x76, 0xe3, 0x9a, 0xd8, 0x9d, 0x7b, 0xed, 0x6e, - 0xaf, 0xbd, 0x99, 0x80, 0x67, 0xd8, 0x2b, 0xb0, 0x76, 0xb8, 0x77, 0xd8, 0x6d, 0x6f, 0x5a, 0x69, - 0xe5, 0xb2, 0x82, 0x1d, 0x25, 0x3e, 0xa5, 0x78, 0xee, 0xfe, 0x27, 0xd0, 0x98, 0x0e, 0x06, 0x25, - 0xa2, 0x67, 0xcf, 0x0b, 0xb3, 0xdd, 0xff, 0x37, 0x39, 0x80, 0x38, 0x5b, 0x5f, 0x48, 0x84, 0xcd, - 0x56, 0xaf, 0xb5, 0xb3, 0x2f, 0x3a, 0x61, 0xee, 0xf7, 0xc4, 0x46, 0x37, 0xdb, 0x9f, 0x36, 0xae, - 0xa5, 0x62, 0xf6, 0x0f, 0x7a, 0x8d, 0x8c, 0x18, 0x6f, 0x67, 0xaf, 0xd3, 0xeb, 0xb4, 0x76, 0x2c, - 0x73, 0xff, 0xb0, 0xb3, 0xf7, 0x84, 0x5e, 0x8b, 0x42, 0x61, 0x78, 0x78, 0xb0, 0x65, 0xee, 0xef, - 0xf5, 0xac, 0xee, 0xf6, 0x61, 0x6f, 0x13, 0xdf, 0x9a, 0xda, 0x30, 0x3b, 0x07, 0x54, 0x67, 0xfe, - 0x79, 0x04, 0xa2, 0xea, 0x82, 0x98, 0xb1, 0x27, 0xfb, 0xdd, 0x6e, 0xe7, 0xc0, 0xfa, 0xf4, 0xb0, - 0x6d, 0x76, 0xda, 0x5d, 0x2c, 0x38, 0x97, 0x02, 0x17, 0xf4, 0x45, 0x21, 0x42, 0x7b, 0x3b, 0x9f, - 0x49, 0x19, 0x27, 0x48, 0x4b, 0x49, 0x90, 0xa0, 0x2a, 0x8b, 0xad, 0x2f, 0x84, 0x44, 0x4a, 0xcd, - 0x70, 0x05, 0x4e, 0x94, 0xab, 0x08, 0xf1, 0xd7, 0xed, 0xb5, 0x7a, 0x9d, 0x0d, 0x4b, 0x3e, 0x50, - 0x27, 0x16, 0x41, 0x14, 0xab, 0xa6, 0xa3, 0x44, 0x29, 0x94, 0x8c, 0xd1, 0x39, 0xb2, 0xb9, 0x69, - 0x62, 0x81, 0xfa, 0x0c, 0x54, 0xd0, 0xce, 0x8b, 0x85, 0x12, 0x52, 0x44, 0x90, 0x34, 0xd4, 0x87, - 0xc0, 0x2c, 0x3c, 0xfe, 0x9d, 0x1c, 0xd4, 0xe9, 0xe6, 0x14, 0xfd, 0x10, 0x0f, 0xf7, 0xd9, 0x2e, - 0x14, 0xe5, 0x2f, 0x3a, 0xb1, 0xe5, 0xe8, 0xcd, 0x20, 0xfd, 0x37, 0xa4, 0xd6, 0x56, 0xa6, 0xc1, - 0x52, 0x6b, 0x5a, 0xfc, 0x9b, 0x7f, 0xfa, 0x17, 0xff, 0x28, 0x5b, 0x63, 0x95, 0x87, 0x67, 0xef, - 0x3e, 0x3c, 0xe1, 0x6e, 0x20, 0xea, 0xf8, 0x6b, 0x00, 0xf1, 0xef, 0x14, 0xb1, 0x66, 0x14, 0x01, - 0x9a, 0xfa, 0x11, 0xa7, 0xb5, 0xeb, 0x29, 0x18, 0x59, 0xef, 0x75, 0xac, 0x77, 0xd1, 0xa8, 0x8b, - 0x7a, 0x1d, 0xd7, 0x09, 0xe9, 0x37, 0x8b, 0x3e, 0xce, 0xdc, 0x67, 0x03, 0xa8, 0xea, 0xbf, 0x20, - 0xc4, 0x94, 0x42, 0x93, 0xf2, 0x1b, 0x48, 0x6b, 0x37, 0x52, 0x71, 0x4a, 0x55, 0xc4, 0x36, 0x96, - 0x8d, 0x86, 0x68, 0x63, 0x82, 0x14, 0x71, 0x2b, 0x43, 0x52, 0x9e, 0xe3, 0x1f, 0x0a, 0x62, 0x37, - 0x35, 0xf5, 0x67, 0xe6, 0x67, 0x8a, 0xd6, 0x6e, 0x5d, 0x81, 0x95, 0x6d, 0xdd, 0xc2, 0xb6, 0x56, - 0x0d, 0x26, 0xda, 0xea, 0x23, 0x8d, 0xfa, 0x99, 0xa2, 0x8f, 0x33, 0xf7, 0x1f, 0xff, 0xf9, 0x3d, - 0x28, 0x47, 0x99, 0x94, 0xec, 0xb7, 0xa0, 0x96, 0xb8, 0xda, 0xc6, 0xd4, 0x30, 0xd2, 0x6e, 0xc2, - 0xad, 0xdd, 0x4c, 0x47, 0xca, 0x86, 0x5f, 0xc1, 0x86, 0x9b, 0x6c, 0x45, 0x34, 0x2c, 0xaf, 0x8e, - 0x3d, 0xc4, 0x0b, 0xa0, 0xf4, 0x02, 0xd3, 0x33, 0xcd, 0x48, 0xa0, 0xc6, 0x6e, 0x4e, 0x2b, 0xee, - 0x89, 0xd6, 0x6e, 0x5d, 0x81, 0x95, 0xcd, 0xdd, 0xc4, 0xe6, 0x56, 0xd8, 0x92, 0xde, 0x9c, 0xca, - 0x7b, 0x64, 0x1c, 0x5f, 0x3d, 0xd3, 0x7f, 0x47, 0x87, 0xdd, 0x8a, 0xdf, 0xa8, 0x4a, 0xf9, 0x7d, - 0x9d, 0x88, 0x45, 0x66, 0x7f, 0x64, 0xc7, 0x68, 0x62, 0x53, 0x8c, 0xe1, 0xf2, 0xe9, 0x3f, 0xa3, - 0xc3, 0x8e, 0xa0, 0xa2, 0x3d, 0x3d, 0xcf, 0xae, 0x5f, 0xf9, 0x4c, 0xfe, 0xda, 0x5a, 0x1a, 0x2a, - 0x6d, 0x28, 0x7a, 0xfd, 0x0f, 0x8f, 0x39, 0x67, 0x3f, 0x82, 0x72, 0xf4, 0xa0, 0x39, 0x5b, 0xd5, - 0x1e, 0x98, 0xd7, 0x1f, 0x60, 0x5f, 0x6b, 0xce, 0x22, 0xd2, 0x98, 0x4f, 0xaf, 0x5d, 0x30, 0xdf, - 0xe7, 0x50, 0xd1, 0x1e, 0x2d, 0x8f, 0x06, 0x30, 0xfb, 0x30, 0x7a, 0x34, 0x80, 0x94, 0x37, 0xce, - 0x8d, 0x05, 0x6c, 0xa2, 0xc2, 0xca, 0xc8, 0xdf, 0xe1, 0x85, 0x17, 0xb0, 0x1d, 0x58, 0x96, 0x06, - 0xd1, 0x11, 0xff, 0x26, 0xcb, 0x90, 0xf2, 0xd3, 0x45, 0x8f, 0x32, 0xec, 0x13, 0x28, 0xa9, 0xb7, - 0xe9, 0xd9, 0x4a, 0xfa, 0x1b, 0xfb, 0x6b, 0xab, 0x33, 0x70, 0x69, 0xbd, 0x7c, 0x01, 0x10, 0xbf, - 0x90, 0x1e, 0x09, 0x89, 0x99, 0x17, 0xd7, 0x23, 0x0e, 0x98, 0x7d, 0x4e, 0xdd, 0x58, 0xc1, 0x01, - 0x36, 0x18, 0x0a, 0x09, 0x97, 0x9f, 0xab, 0xe7, 0x1f, 0x7f, 0x0c, 0x15, 0xed, 0x91, 0xf4, 0x68, - 0xfa, 0x66, 0x1f, 0x58, 0x8f, 0xa6, 0x2f, 0xe5, 0x4d, 0x75, 0x63, 0x0d, 0x6b, 0x5f, 0x32, 0xe6, - 0x45, 0xed, 0x42, 0x51, 0x92, 0x0a, 0x8b, 0x58, 0xa0, 0x53, 0xa8, 0x25, 0x5e, 0x42, 0x8f, 0x76, - 0x68, 0xda, 0x3b, 0xeb, 0xd1, 0x0e, 0x4d, 0x7d, 0x3c, 0x5d, 0xf1, 0x99, 0xb1, 0x20, 0xda, 0x39, - 0x43, 0x12, 0xad, 0xa5, 0x1f, 0x42, 0x45, 0x7b, 0xd5, 0x3c, 0x1a, 0xcb, 0xec, 0x03, 0xea, 0xd1, - 0x58, 0xd2, 0x1e, 0x41, 0x5f, 0xc2, 0x36, 0xea, 0x06, 0xb2, 0x02, 0x3e, 0xae, 0x27, 0xea, 0xfe, - 0x2d, 0xa8, 0x27, 0x1f, 0x3a, 0x8f, 0xf6, 0x7e, 0xea, 0x8b, 0xe9, 0xd1, 0xde, 0xbf, 0xe2, 0x75, - 0x74, 0xc9, 0xd2, 0xf7, 0x17, 0xa3, 0x46, 0x1e, 0x7e, 0x25, 0xef, 0x84, 0x7c, 0xcd, 0x3e, 0x15, - 0x02, 0x4e, 0xbe, 0xed, 0xc8, 0x56, 0x35, 0xae, 0xd5, 0x5f, 0x80, 0x8c, 0xf6, 0xcb, 0xcc, 0x33, - 0x90, 0x49, 0x66, 0xc6, 0xca, 0xd9, 0x13, 0x58, 0x8c, 0x98, 0x39, 0x7a, 0xac, 0x31, 0x88, 0xc6, - 0x90, 0xfa, 0x24, 0xe4, 0x5a, 0x63, 0x1a, 0xfb, 0x28, 0x43, 0xc7, 0x1f, 0x3e, 0x91, 0xa7, 0x1d, - 0x7f, 0xfa, 0x7b, 0x8d, 0xda, 0xf1, 0x97, 0x78, 0x49, 0x6f, 0xfa, 0xf8, 0x0b, 0x1d, 0x51, 0x87, - 0x0b, 0xf3, 0xd3, 0x4f, 0x27, 0xde, 0xba, 0xea, 0xe1, 0x00, 0xaa, 0xfe, 0x95, 0xe7, 0xbf, 0x2b, - 0x90, 0x14, 0x45, 0x4a, 0x9a, 0x3e, 0x94, 0x99, 0x1f, 0xec, 0x37, 0xa1, 0xaa, 0xbf, 0xd4, 0xcc, - 0x74, 0x99, 0x30, 0xdd, 0xd2, 0x8d, 0x54, 0x5c, 0x92, 0x4b, 0x58, 0x55, 0x6f, 0x86, 0x7d, 0x06, - 0x2b, 0xd1, 0x34, 0xeb, 0x97, 0xc6, 0x03, 0x76, 0x3b, 0xe5, 0x2a, 0x79, 0x62, 0xb2, 0xaf, 0x5f, - 0x79, 0xd7, 0xfc, 0x51, 0x46, 0x70, 0x5f, 0xf2, 0xc9, 0xd8, 0xf8, 0xe4, 0x49, 0x7b, 0x29, 0x37, - 0x3e, 0x79, 0x52, 0xdf, 0x99, 0x55, 0xdc, 0xc7, 0x16, 0x13, 0x73, 0x44, 0x39, 0xb1, 0xec, 0x87, - 0x30, 0xaf, 0xdd, 0x88, 0xef, 0x5e, 0xba, 0xfd, 0x68, 0x27, 0xcd, 0xbe, 0xc7, 0xb6, 0x96, 0xe6, - 0x42, 0x34, 0x56, 0xb1, 0xfe, 0x05, 0x23, 0x31, 0x39, 0x62, 0x17, 0x6d, 0x40, 0x45, 0xbf, 0x6d, - 0xff, 0x9c, 0x7a, 0x57, 0x35, 0x94, 0xfe, 0xf4, 0xd7, 0xa3, 0x0c, 0xdb, 0x81, 0xc6, 0xf4, 0x4b, - 0x45, 0x91, 0x4c, 0x49, 0x7b, 0x5d, 0x69, 0x6d, 0x0a, 0x99, 0x78, 0xdf, 0x88, 0x1d, 0xd0, 0xad, - 0x8a, 0xe8, 0x77, 0x7e, 0x3c, 0x7f, 0xfa, 0x54, 0x4f, 0xfe, 0xfe, 0x4f, 0x54, 0x5b, 0xda, 0x2f, - 0x3f, 0xdd, 0xcb, 0x3c, 0xca, 0xb0, 0xdf, 0xcb, 0x40, 0x35, 0xf1, 0x3a, 0x48, 0x22, 0x6f, 0x7d, - 0x6a, 0x9c, 0x4d, 0x1d, 0xa7, 0x0f, 0xd4, 0x30, 0x71, 0x12, 0x77, 0xee, 0x7f, 0x3f, 0xb1, 0x48, - 0x5f, 0x25, 0x22, 0x70, 0x0f, 0xa6, 0x7f, 0x08, 0xe8, 0xeb, 0x69, 0x02, 0xfd, 0x99, 0xbd, 0xaf, - 0x1f, 0x65, 0xd8, 0xbf, 0xcb, 0x40, 0x3d, 0x19, 0x5a, 0x8f, 0x86, 0x9b, 0x1a, 0xc4, 0x8f, 0x58, - 0xe9, 0x8a, 0x78, 0xfc, 0x0f, 0xb1, 0x97, 0xbd, 0xfb, 0x66, 0xa2, 0x97, 0xf2, 0xb1, 0xe3, 0x5f, - 0xac, 0xb7, 0xec, 0x63, 0xfa, 0xdd, 0x3d, 0x95, 0x47, 0xc4, 0x66, 0x7f, 0xa7, 0x2d, 0x62, 0x3f, - 0xfd, 0x57, 0xcd, 0x70, 0x11, 0x7e, 0x4c, 0x3f, 0x78, 0xa3, 0xd2, 0x52, 0x04, 0x17, 0xbf, 0x6c, - 0x79, 0xe3, 0x75, 0x1c, 0xd3, 0x2b, 0xc6, 0xf5, 0xc4, 0x98, 0xa6, 0x15, 0x8f, 0x16, 0xf5, 0x4e, - 0xfe, 0x28, 0x59, 0x7c, 0x72, 0xce, 0xfc, 0x50, 0xd9, 0xd5, 0x9d, 0x1c, 0x51, 0x27, 0x25, 0x79, - 0x62, 0xab, 0xbd, 0x64, 0x35, 0xc6, 0x7d, 0xec, 0xeb, 0xeb, 0xc6, 0xed, 0x2b, 0xfb, 0xfa, 0x10, - 0xc3, 0xe4, 0xa2, 0xc7, 0x07, 0x00, 0x71, 0x9e, 0x1f, 0x9b, 0xca, 0x36, 0x8b, 0x04, 0xd0, 0x6c, - 0x2a, 0x60, 0x72, 0x3f, 0xab, 0xa4, 0x34, 0x51, 0xe3, 0x8f, 0x48, 0x9c, 0x46, 0x79, 0x70, 0xba, - 0xf6, 0x95, 0x4c, 0xc9, 0x4b, 0x68, 0x5f, 0xd3, 0xf5, 0x27, 0x84, 0x69, 0x94, 0xf4, 0x76, 0x08, - 0xb5, 0x1d, 0xcf, 0x7b, 0x36, 0x19, 0x47, 0xb9, 0xe5, 0xc9, 0xdc, 0x95, 0x6d, 0x3b, 0x38, 0x5d, - 0x9b, 0x1a, 0x85, 0x71, 0x07, 0xab, 0x5a, 0x63, 0x4d, 0xad, 0xaa, 0x87, 0x5f, 0xc5, 0xc9, 0x85, - 0x5f, 0x33, 0x1b, 0x16, 0x22, 0x19, 0x1d, 0x27, 0xf0, 0x25, 0xab, 0x49, 0x48, 0xe6, 0xe9, 0x26, - 0x12, 0x66, 0x82, 0xea, 0xed, 0xc3, 0x40, 0xd5, 0xf9, 0x28, 0xc3, 0x0e, 0xa0, 0xba, 0xc9, 0xfb, - 0x78, 0x4b, 0x1e, 0x33, 0x40, 0x16, 0x13, 0xd9, 0x04, 0x94, 0x3a, 0xb2, 0x56, 0x4b, 0x00, 0x93, - 0xe7, 0xd6, 0xd8, 0xbe, 0xf4, 0xf9, 0x97, 0x0f, 0xbf, 0x92, 0xb9, 0x25, 0x5f, 0xab, 0x73, 0x4b, - 0xe5, 0xde, 0x24, 0xce, 0xad, 0xa9, 0x64, 0x9d, 0xc4, 0xb9, 0x35, 0x93, 0xac, 0x93, 0x98, 0x6a, - 0x95, 0xfb, 0xc3, 0x86, 0xb0, 0x30, 0x93, 0xdf, 0x13, 0x1d, 0x59, 0x57, 0x65, 0x05, 0xad, 0xdd, - 0xb9, 0x9a, 0x20, 0xd9, 0xda, 0xfd, 0x64, 0x6b, 0x5d, 0xa8, 0xd1, 0xcb, 0x7f, 0x47, 0x9c, 0xee, - 0xcb, 0x4d, 0x3d, 0x36, 0xa3, 0x5f, 0xc6, 0x9b, 0x3e, 0x60, 0x10, 0x97, 0xd4, 0x70, 0xf0, 0xa2, - 0x1a, 0xfb, 0x11, 0x54, 0x9e, 0xf0, 0x50, 0x5d, 0x90, 0x8b, 0x74, 0xec, 0xa9, 0x1b, 0x73, 0x6b, - 0x29, 0xf7, 0xeb, 0x92, 0x3c, 0x83, 0xb5, 0x3d, 0xe4, 0x83, 0x13, 0x4e, 0xc2, 0xc9, 0x72, 0x06, - 0x5f, 0xb3, 0x1f, 0x60, 0xe5, 0xd1, 0xbd, 0xe4, 0x15, 0xed, 0x06, 0x94, 0x5e, 0xf9, 0xfc, 0x14, - 0x3c, 0xad, 0x66, 0xd7, 0x1b, 0x70, 0x4d, 0xd7, 0x73, 0xa1, 0xa2, 0xbd, 0x5f, 0x10, 0x6d, 0xa0, - 0xd9, 0xf7, 0x2a, 0xa2, 0x0d, 0x94, 0xf2, 0xdc, 0x81, 0x71, 0x0f, 0xdb, 0x31, 0xd8, 0x9d, 0xb8, - 0x1d, 0x7a, 0xe2, 0x20, 0x6e, 0xe9, 0xe1, 0x57, 0xf6, 0x28, 0xfc, 0x9a, 0x7d, 0x8e, 0xef, 0x6b, - 0xeb, 0x17, 0x00, 0x63, 0xa3, 0x61, 0xfa, 0xae, 0x60, 0x34, 0x59, 0x1a, 0x2a, 0x69, 0x48, 0x50, - 0x53, 0xa8, 0xc9, 0xbd, 0x0f, 0xd0, 0x0d, 0xbd, 0xf1, 0xa6, 0xcd, 0x47, 0x9e, 0x1b, 0xcb, 0xda, - 0xf8, 0x4a, 0x5a, 0x2c, 0xbf, 0xb4, 0x7b, 0x69, 0xec, 0x73, 0xcd, 0xca, 0x4a, 0xdc, 0xa1, 0x54, - 0xcc, 0x75, 0xe5, 0xad, 0xb5, 0x68, 0x42, 0x52, 0x6e, 0xae, 0x3d, 0xca, 0xb0, 0x16, 0x40, 0x9c, - 0xe0, 0x15, 0xd9, 0x4c, 0x33, 0xb9, 0x63, 0x91, 0xd8, 0x4b, 0xc9, 0x06, 0x3b, 0x80, 0x72, 0x9c, - 0x19, 0xb3, 0x1a, 0x3f, 0xc7, 0x92, 0xc8, 0xa3, 0x89, 0x4e, 0xf0, 0x99, 0xac, 0x14, 0xa3, 0x81, - 0x53, 0x05, 0xac, 0x24, 0xa6, 0xea, 0x98, 0xf3, 0x80, 0x39, 0xb0, 0x48, 0x1d, 0x8c, 0xd4, 0x25, - 0xbc, 0x4a, 0x15, 0x3d, 0xa3, 0x3e, 0x9b, 0x20, 0x12, 0xed, 0xe6, 0xd4, 0x34, 0x87, 0x84, 0xeb, - 0x47, 0x70, 0x2b, 0x5d, 0xe3, 0x12, 0xa2, 0x79, 0x04, 0x0b, 0x33, 0x91, 0xf4, 0x68, 0x4b, 0x5f, - 0x95, 0x1a, 0x11, 0x6d, 0xe9, 0x2b, 0x83, 0xf0, 0xc6, 0x32, 0x36, 0x39, 0x6f, 0x00, 0x9a, 0x7a, - 0xe7, 0x4e, 0xd8, 0x3f, 0x15, 0xcd, 0xfd, 0xeb, 0x0c, 0x2c, 0xa6, 0xc4, 0xca, 0xd9, 0xab, 0xca, - 0x6b, 0x70, 0x65, 0x1c, 0x7d, 0x2d, 0x35, 0xa6, 0x6a, 0x74, 0xb1, 0x9d, 0x5d, 0xf6, 0x34, 0x71, - 0xb0, 0x51, 0x48, 0x53, 0xee, 0xcc, 0xe7, 0x2a, 0x15, 0xa9, 0x1a, 0xc5, 0x97, 0xb0, 0x4a, 0x1d, - 0x69, 0x0d, 0x87, 0x53, 0xf1, 0xde, 0x57, 0x66, 0x7e, 0x97, 0x3b, 0x11, 0xc3, 0x5e, 0xbb, 0xfa, - 0x77, 0xbb, 0xaf, 0x50, 0xa7, 0xa9, 0xab, 0x6c, 0x02, 0x8d, 0xe9, 0x38, 0x2a, 0xbb, 0xba, 0xae, - 0xb5, 0xdb, 0x09, 0xfb, 0x37, 0x25, 0xf6, 0xfa, 0x1d, 0x6c, 0xec, 0xb6, 0xb1, 0x96, 0x36, 0x2f, - 0x64, 0x12, 0x8b, 0xf5, 0xf8, 0x1b, 0x51, 0xd0, 0x77, 0x6a, 0x9c, 0xaa, 0x81, 0xab, 0x42, 0xd4, - 0x91, 0x05, 0x9e, 0x1e, 0x33, 0x7e, 0x03, 0x9b, 0xbf, 0x63, 0xdc, 0x48, 0x6b, 0xde, 0xa7, 0x22, - 0x64, 0x8b, 0xaf, 0x4e, 0xef, 0x6b, 0xd5, 0x83, 0x3b, 0x69, 0xeb, 0x7d, 0xa5, 0x2d, 0x34, 0x35, - 0xd7, 0xd7, 0x50, 0xb7, 0xab, 0xea, 0x41, 0xde, 0x68, 0xfb, 0xa4, 0x44, 0x93, 0xa3, 0xed, 0x93, - 0x16, 0x15, 0x4e, 0xea, 0x35, 0x2a, 0x1e, 0xfc, 0x71, 0xe6, 0xfe, 0xfa, 0xdd, 0x1f, 0x7e, 0xe7, - 0xc4, 0x09, 0x4f, 0x27, 0x47, 0x0f, 0xfa, 0xde, 0xe8, 0xe1, 0x50, 0x79, 0x1b, 0xe5, 0x7d, 0xe3, - 0x87, 0x43, 0x77, 0xf0, 0x10, 0xab, 0x3d, 0x9a, 0x1b, 0xfb, 0x5e, 0xe8, 0x7d, 0xf7, 0xff, 0x05, - 0x00, 0x00, 0xff, 0xff, 0x41, 0x79, 0x30, 0x63, 0x7a, 0x80, 0x00, 0x00, + // 11110 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x1c, 0x47, + 0x96, 0x18, 0xcc, 0xba, 0x75, 0x55, 0x9d, 0xba, 0x74, 0x75, 0xf4, 0xad, 0xd8, 0x24, 0x45, 0x2a, + 0xa5, 0x11, 0x29, 0x4a, 0x22, 0x29, 0x8e, 0x6e, 0x2b, 0x7d, 0xdf, 0xec, 0x56, 0x77, 0x57, 0xb3, + 0x6b, 0xd8, 0x37, 0x65, 0x55, 0x4b, 0xab, 0x19, 0xaf, 0x73, 0xb2, 0xab, 0xa2, 0xbb, 0x73, 0x59, + 0x95, 0x59, 0xca, 0xcc, 0xea, 0xcb, 0x08, 0xf2, 0x83, 0x2f, 0x0b, 0xc3, 0x36, 0x0c, 0x2c, 0xec, + 0x31, 0xe0, 0xb1, 0x17, 0x36, 0x6c, 0x18, 0x86, 0x61, 0x63, 0xb1, 0xc6, 0xac, 0x01, 0x3f, 0xf8, + 0x7d, 0x5f, 0x6c, 0xec, 0xc3, 0xae, 0x5f, 0x8c, 0xc1, 0x02, 0x0b, 0xaf, 0xc7, 0xaf, 0xfe, 0x09, + 0x46, 0x9c, 0x13, 0x91, 0x19, 0x59, 0x95, 0x4d, 0x52, 0x9a, 0xf1, 0xbc, 0x90, 0x9d, 0xe7, 0x9c, + 0xb8, 0x9f, 0x38, 0x71, 0x6e, 0x11, 0x05, 0x65, 0x7f, 0xdc, 0x7f, 0x30, 0xf6, 0xbd, 0xd0, 0x63, + 0x85, 0xa1, 0xeb, 0x8f, 0xfb, 0x6b, 0x37, 0x4f, 0x3c, 0xef, 0x64, 0xc8, 0x1f, 0xda, 0x63, 0xe7, + 0xa1, 0xed, 0xba, 0x5e, 0x68, 0x87, 0x8e, 0xe7, 0x06, 0x44, 0x64, 0xfc, 0x08, 0xea, 0x4f, 0xb8, + 0xdb, 0xe5, 0x7c, 0x60, 0xf2, 0x2f, 0x27, 0x3c, 0x08, 0xd9, 0x5b, 0xb0, 0x60, 0xf3, 0x1f, 0x73, + 0x3e, 0xb0, 0xc6, 0x76, 0x10, 0x8c, 0x4f, 0x7d, 0x3b, 0xe0, 0xcd, 0xcc, 0x9d, 0xcc, 0xbd, 0xaa, + 0xd9, 0x20, 0xc4, 0x41, 0x04, 0x67, 0xaf, 0x42, 0x35, 0x10, 0xa4, 0xdc, 0x0d, 0x7d, 0x6f, 0x7c, + 0xd9, 0xcc, 0x22, 0x5d, 0x45, 0xc0, 0xda, 0x04, 0x32, 0x86, 0x30, 0x1f, 0xb5, 0x10, 0x8c, 0x3d, + 0x37, 0xe0, 0xec, 0x11, 0x2c, 0xf5, 0x9d, 0xf1, 0x29, 0xf7, 0x2d, 0x2c, 0x3c, 0x72, 0xf9, 0xc8, + 0x73, 0x9d, 0x7e, 0x33, 0x73, 0x27, 0x77, 0xaf, 0x6c, 0x32, 0xc2, 0x89, 0x12, 0xbb, 0x12, 0xc3, + 0xee, 0xc2, 0x3c, 0x77, 0x09, 0xce, 0x07, 0x58, 0x4a, 0x36, 0x55, 0x8f, 0xc1, 0xa2, 0x80, 0xf1, + 0x77, 0xb3, 0xb0, 0xd0, 0x71, 0x9d, 0xf0, 0x73, 0x7b, 0x38, 0xe4, 0xa1, 0x1a, 0xd3, 0x5d, 0x98, + 0x3f, 0x47, 0x00, 0x8e, 0xe9, 0xdc, 0xf3, 0x07, 0x72, 0x44, 0x75, 0x02, 0x1f, 0x48, 0xe8, 0x95, + 0x3d, 0xcb, 0x5e, 0xd9, 0xb3, 0xd4, 0xe9, 0xca, 0x5d, 0x31, 0x5d, 0x77, 0x61, 0xde, 0xe7, 0x7d, + 0xef, 0x8c, 0xfb, 0x97, 0xd6, 0xb9, 0xe3, 0x0e, 0xbc, 0xf3, 0x66, 0xfe, 0x4e, 0xe6, 0x5e, 0xc1, + 0xac, 0x2b, 0xf0, 0xe7, 0x08, 0x65, 0xeb, 0x30, 0xdf, 0x3f, 0xb5, 0x5d, 0x97, 0x0f, 0xad, 0x23, + 0xbb, 0xff, 0x6c, 0x32, 0x0e, 0x9a, 0x85, 0x3b, 0x99, 0x7b, 0x95, 0xc7, 0xd7, 0x1f, 0xe0, 0xaa, + 0x3e, 0xd8, 0x38, 0xb5, 0xdd, 0x75, 0xc4, 0x74, 0x5d, 0x7b, 0x1c, 0x9c, 0x7a, 0xa1, 0x59, 0x97, + 0x25, 0x08, 0x1c, 0x18, 0x4b, 0xc0, 0xf4, 0x99, 0xa0, 0xb9, 0x37, 0xfe, 0x7d, 0x06, 0x16, 0x0f, + 0xdd, 0xa1, 0xd7, 0x7f, 0xf6, 0x2d, 0xa7, 0x28, 0x65, 0x0c, 0xd9, 0x97, 0x1d, 0x43, 0xee, 0x9b, + 0x8e, 0x61, 0x05, 0x96, 0x92, 0x9d, 0x95, 0xa3, 0xe0, 0xb0, 0x2c, 0x4a, 0x9f, 0x70, 0xd5, 0x2d, + 0x35, 0x8c, 0x37, 0xa1, 0xd1, 0x9f, 0xf8, 0x3e, 0x77, 0x67, 0xc6, 0x31, 0x2f, 0xe1, 0xd1, 0x40, + 0x5e, 0x85, 0xaa, 0xcb, 0xcf, 0x63, 0x32, 0xc9, 0xbb, 0x2e, 0x3f, 0x57, 0x24, 0x46, 0x13, 0x56, + 0xa6, 0x9b, 0x91, 0x1d, 0xf8, 0x45, 0x06, 0xf2, 0x87, 0xe1, 0x85, 0xc7, 0xde, 0x87, 0xaa, 0x3d, + 0x18, 0xf8, 0x3c, 0x08, 0xac, 0xf0, 0x72, 0x4c, 0x3b, 0xa5, 0xfe, 0x98, 0xc9, 0x21, 0xb6, 0x08, + 0xd5, 0xbb, 0x1c, 0x73, 0xb3, 0x62, 0xc7, 0x1f, 0xac, 0x09, 0x45, 0xf9, 0x89, 0xed, 0x96, 0x4d, + 0xf5, 0xc9, 0x6e, 0x01, 0xd8, 0x23, 0x6f, 0xe2, 0x86, 0x56, 0x60, 0x87, 0x38, 0x63, 0x39, 0xb3, + 0x4c, 0x90, 0xae, 0x1d, 0xb2, 0x1b, 0x50, 0x1e, 0x3f, 0xb3, 0x82, 0xbe, 0xef, 0x8c, 0x43, 0x64, + 0x9e, 0xb2, 0x59, 0x1a, 0x3f, 0xeb, 0xe2, 0x37, 0x7b, 0x0b, 0x4a, 0xde, 0x24, 0x1c, 0x7b, 0x8e, + 0x1b, 0x4a, 0x7e, 0x99, 0x97, 0x1d, 0xd9, 0x9f, 0x84, 0x07, 0x02, 0x6c, 0x46, 0x04, 0xec, 0x75, + 0xa8, 0xf5, 0x3d, 0xf7, 0xd8, 0xf1, 0x47, 0x24, 0x11, 0x9a, 0x73, 0xd8, 0x56, 0x12, 0x68, 0xfc, + 0x51, 0x16, 0x2a, 0x3d, 0xdf, 0x76, 0x03, 0xbb, 0x2f, 0x00, 0x6c, 0x15, 0x8a, 0xe1, 0x85, 0x75, + 0x6a, 0x07, 0xa7, 0x38, 0xd4, 0xb2, 0x39, 0x17, 0x5e, 0x6c, 0xdb, 0xc1, 0x29, 0x5b, 0x81, 0x39, + 0xea, 0x25, 0x0e, 0x28, 0x67, 0xca, 0x2f, 0xb1, 0x41, 0xdc, 0xc9, 0xc8, 0x4a, 0x36, 0x95, 0x43, + 0x8e, 0x69, 0xb8, 0x93, 0xd1, 0x86, 0x0e, 0x17, 0x83, 0x3f, 0x12, 0xcb, 0x4d, 0x0d, 0xd0, 0xf0, + 0xca, 0x08, 0xc1, 0x36, 0x5e, 0x85, 0xaa, 0x44, 0x73, 0xe7, 0xe4, 0x94, 0xc6, 0x58, 0x30, 0x2b, + 0x44, 0x80, 0x20, 0x51, 0x43, 0xe8, 0x8c, 0xb8, 0x15, 0x84, 0xf6, 0x68, 0x2c, 0x87, 0x54, 0x16, + 0x90, 0xae, 0x00, 0x20, 0xda, 0x0b, 0xed, 0xa1, 0x75, 0xcc, 0x79, 0xd0, 0x2c, 0x4a, 0xb4, 0x80, + 0x6c, 0x71, 0x1e, 0xb0, 0xef, 0x40, 0x7d, 0xc0, 0x83, 0xd0, 0x92, 0x8b, 0xc1, 0x83, 0x66, 0x09, + 0x77, 0x7e, 0x4d, 0x40, 0x5b, 0x0a, 0xc8, 0x6e, 0x02, 0xf8, 0xf6, 0xb9, 0x25, 0x26, 0x82, 0x5f, + 0x34, 0xcb, 0xb4, 0x0a, 0xbe, 0x7d, 0xde, 0xbb, 0xd8, 0xe6, 0x17, 0x82, 0x6b, 0x9e, 0xf0, 0x50, + 0x9b, 0xb4, 0x40, 0x72, 0xa7, 0xb1, 0x03, 0x4c, 0x03, 0x6f, 0xf2, 0xd0, 0x76, 0x86, 0x01, 0xfb, + 0x00, 0xaa, 0xa1, 0x46, 0x8c, 0x62, 0xb0, 0x12, 0xb1, 0x90, 0x56, 0xc0, 0x4c, 0xd0, 0x19, 0xa7, + 0x50, 0xda, 0xe2, 0x7c, 0xc7, 0x19, 0x39, 0x21, 0x5b, 0x81, 0xc2, 0xb1, 0x73, 0xc1, 0x89, 0xd9, + 0x73, 0xdb, 0xd7, 0x4c, 0xfa, 0x64, 0xb7, 0x01, 0xf0, 0x0f, 0x6b, 0x14, 0x71, 0xd3, 0xf6, 0x35, + 0xb3, 0x8c, 0xb0, 0xdd, 0xc0, 0x0e, 0xd9, 0x1a, 0x14, 0xc7, 0xdc, 0xef, 0x73, 0xb5, 0x6e, 0xdb, + 0xd7, 0x4c, 0x05, 0x58, 0x2f, 0x42, 0x61, 0x28, 0x6a, 0x37, 0xfe, 0xa4, 0x00, 0x95, 0x2e, 0x77, + 0xa3, 0x5d, 0xc6, 0x20, 0x2f, 0x26, 0x44, 0xee, 0x2c, 0xfc, 0x9b, 0xbd, 0x06, 0x15, 0x9c, 0xba, + 0x20, 0xf4, 0x1d, 0xf7, 0x84, 0xb8, 0x7a, 0x3d, 0xdb, 0xcc, 0x98, 0x20, 0xc0, 0x5d, 0x84, 0xb2, + 0x06, 0xe4, 0xec, 0x91, 0xe2, 0x6a, 0xf1, 0x27, 0xbb, 0x0e, 0x25, 0x7b, 0x14, 0x52, 0xf7, 0xaa, + 0x08, 0x2e, 0xda, 0xa3, 0x10, 0xbb, 0xf6, 0x2a, 0x54, 0xc7, 0xf6, 0xe5, 0x48, 0xec, 0xe5, 0x88, + 0x1d, 0xaa, 0x66, 0x45, 0xc2, 0x90, 0x21, 0x1e, 0xc3, 0xa2, 0x4e, 0xa2, 0x1a, 0x2f, 0x44, 0x8d, + 0x2f, 0x68, 0xd4, 0xb2, 0x0f, 0x77, 0x61, 0x5e, 0x95, 0xf1, 0x69, 0x3c, 0xc8, 0x26, 0x65, 0xb3, + 0x2e, 0xc1, 0x6a, 0x94, 0xf7, 0xa0, 0x71, 0xec, 0xb8, 0xf6, 0xd0, 0xea, 0x0f, 0xc3, 0x33, 0x6b, + 0xc0, 0x87, 0xa1, 0x8d, 0x1c, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x18, 0x86, 0x67, 0x9b, 0x02, 0xca, + 0xde, 0x86, 0xf2, 0x31, 0xe7, 0x16, 0x4e, 0x56, 0xb3, 0x94, 0xd8, 0x78, 0x6a, 0x85, 0xcc, 0xd2, + 0xb1, 0x5a, 0xab, 0xb7, 0xa1, 0xe1, 0x4d, 0xc2, 0x13, 0xcf, 0x71, 0x4f, 0x2c, 0x21, 0xef, 0x2c, + 0x67, 0x80, 0x3c, 0x94, 0x5f, 0xcf, 0x3e, 0xca, 0x98, 0x75, 0x85, 0x13, 0x92, 0xa7, 0x33, 0x60, + 0x6f, 0xc0, 0xfc, 0xd0, 0x0e, 0x42, 0xeb, 0xd4, 0x1b, 0x5b, 0xe3, 0xc9, 0xd1, 0x33, 0x7e, 0xd9, + 0xac, 0xe1, 0x44, 0xd4, 0x04, 0x78, 0xdb, 0x1b, 0x1f, 0x20, 0x50, 0x70, 0x36, 0xf6, 0x93, 0x3a, + 0x01, 0x77, 0x32, 0xf7, 0x6a, 0x66, 0x59, 0x40, 0xa8, 0xd1, 0x2f, 0x60, 0x11, 0x97, 0xa7, 0x3f, + 0x09, 0x42, 0x6f, 0x64, 0x09, 0x59, 0xed, 0x0f, 0x82, 0x66, 0x05, 0x79, 0xed, 0x4d, 0xd9, 0x59, + 0x6d, 0x8d, 0x1f, 0x6c, 0xf2, 0x20, 0xdc, 0x40, 0x62, 0x93, 0x68, 0xc5, 0x81, 0x7e, 0x69, 0x2e, + 0x0c, 0xa6, 0xe1, 0xec, 0x6d, 0x60, 0xf6, 0x70, 0xe8, 0x9d, 0x5b, 0x01, 0x1f, 0x1e, 0x5b, 0x72, + 0x12, 0x9b, 0xf5, 0x3b, 0x99, 0x7b, 0x25, 0xb3, 0x81, 0x98, 0x2e, 0x1f, 0x1e, 0x1f, 0x10, 0x9c, + 0x7d, 0x00, 0xb8, 0x99, 0xac, 0x63, 0x6e, 0x87, 0x13, 0x9f, 0x07, 0xcd, 0xf9, 0x3b, 0xb9, 0x7b, + 0xf5, 0xc7, 0x0b, 0xd1, 0x7c, 0x21, 0x78, 0xdd, 0x09, 0xcd, 0xaa, 0xa0, 0x93, 0xdf, 0xc1, 0xda, + 0x26, 0xac, 0xa4, 0x77, 0x49, 0x30, 0x95, 0x98, 0x15, 0xc1, 0x8c, 0x79, 0x53, 0xfc, 0xc9, 0x96, + 0xa0, 0x70, 0x66, 0x0f, 0x27, 0x5c, 0xca, 0x74, 0xfa, 0xf8, 0x38, 0xfb, 0x51, 0xc6, 0xf8, 0xe3, + 0x0c, 0x54, 0x69, 0x94, 0x52, 0x17, 0x79, 0x0d, 0x6a, 0x8a, 0x1b, 0xb8, 0xef, 0x7b, 0xbe, 0x94, + 0x6a, 0x8a, 0xf3, 0xda, 0x02, 0x26, 0x4e, 0x15, 0x45, 0x34, 0xf6, 0xb9, 0x33, 0xb2, 0x4f, 0x54, + 0xd5, 0x8a, 0x95, 0x0e, 0x24, 0x98, 0xbd, 0x1b, 0xd7, 0xe7, 0x7b, 0x93, 0x90, 0xcb, 0x33, 0xaf, + 0x2a, 0x87, 0x67, 0x0a, 0x58, 0x54, 0x3b, 0x7e, 0xbd, 0x04, 0x9f, 0x1b, 0x3f, 0xc9, 0x00, 0x13, + 0xdd, 0xee, 0x79, 0x54, 0x81, 0xe4, 0xd0, 0xe9, 0x92, 0x99, 0x97, 0xde, 0x21, 0xd9, 0xe7, 0xed, + 0x10, 0x03, 0x0a, 0xd4, 0xf7, 0x7c, 0x4a, 0xdf, 0x09, 0xf5, 0xfd, 0x7c, 0x29, 0xd7, 0xc8, 0x1b, + 0xff, 0x23, 0x07, 0x4b, 0x1b, 0x74, 0x64, 0xb7, 0xfa, 0x7d, 0x3e, 0x8e, 0xf6, 0xce, 0x6d, 0xa8, + 0xb8, 0xde, 0x80, 0x2b, 0x8e, 0xa5, 0x8e, 0x81, 0x00, 0x69, 0xec, 0x7a, 0x6a, 0x3b, 0x2e, 0x75, + 0x9c, 0x26, 0xb3, 0x8c, 0x10, 0xec, 0xf6, 0x1b, 0x30, 0x3f, 0xe6, 0xee, 0x40, 0xdf, 0x22, 0xa4, + 0x54, 0xd5, 0x24, 0x58, 0xee, 0x8e, 0xdb, 0x50, 0x39, 0x9e, 0x10, 0x9d, 0x10, 0x2c, 0x79, 0xe4, + 0x01, 0x90, 0xa0, 0x16, 0xc9, 0x97, 0xf1, 0x24, 0x38, 0x45, 0x6c, 0x01, 0xb1, 0x45, 0xf1, 0x2d, + 0x50, 0xb7, 0x00, 0x06, 0x93, 0x20, 0x94, 0x3b, 0x66, 0x0e, 0x91, 0x65, 0x01, 0xa1, 0x1d, 0xf3, + 0x0e, 0x2c, 0x8e, 0xec, 0x0b, 0x0b, 0x79, 0xc7, 0x72, 0x5c, 0xeb, 0x78, 0x88, 0x67, 0x4e, 0x11, + 0xe9, 0x1a, 0x23, 0xfb, 0xe2, 0x33, 0x81, 0xe9, 0xb8, 0x5b, 0x08, 0x17, 0x62, 0x45, 0xa9, 0x3b, + 0x3e, 0x0f, 0xb8, 0x7f, 0xc6, 0x51, 0x12, 0xe4, 0x23, 0x9d, 0xc6, 0x24, 0xa8, 0xe8, 0xd1, 0x48, + 0x8c, 0x3b, 0x1c, 0xf6, 0x69, 0xdb, 0x9b, 0xc5, 0x91, 0xe3, 0x6e, 0x87, 0xc3, 0xbe, 0x38, 0x57, + 0x84, 0x1c, 0x19, 0x73, 0xdf, 0x7a, 0x76, 0x8e, 0x7b, 0x38, 0x8f, 0x72, 0xe3, 0x80, 0xfb, 0x4f, + 0xcf, 0xc5, 0xd1, 0xdf, 0x0f, 0x50, 0x10, 0xd9, 0x97, 0xcd, 0x0a, 0x6e, 0xf0, 0x52, 0x3f, 0x10, + 0x22, 0xc8, 0xbe, 0x14, 0x9b, 0x50, 0xf4, 0xd6, 0xc6, 0x55, 0xe0, 0x03, 0xac, 0x3e, 0x40, 0x89, + 0x5a, 0xc3, 0xce, 0xb6, 0x24, 0x42, 0xb4, 0x13, 0x08, 0xae, 0x57, 0x9d, 0x3d, 0x1e, 0xda, 0x27, + 0x01, 0x8a, 0x94, 0x9a, 0x59, 0x95, 0xc0, 0x2d, 0x01, 0x33, 0x3e, 0x27, 0x25, 0x4b, 0x5b, 0x5b, + 0xb9, 0x67, 0xc4, 0x51, 0x8f, 0x10, 0x5c, 0xd7, 0x92, 0x29, 0xbf, 0xd2, 0x16, 0x2d, 0x9b, 0xb2, + 0x68, 0xc6, 0x1f, 0x64, 0xa0, 0x2a, 0x6b, 0x46, 0xa5, 0x84, 0x3d, 0x00, 0xa6, 0x56, 0x31, 0xbc, + 0x70, 0x06, 0xd6, 0xd1, 0x65, 0xc8, 0x03, 0x62, 0x9a, 0xed, 0x6b, 0x66, 0x43, 0xe2, 0x7a, 0x17, + 0xce, 0x60, 0x5d, 0x60, 0xd8, 0x7d, 0x68, 0x24, 0xe8, 0x83, 0xd0, 0x27, 0x8e, 0xde, 0xbe, 0x66, + 0xd6, 0x35, 0xea, 0x6e, 0xe8, 0x8b, 0x3d, 0x22, 0x54, 0x9e, 0x49, 0x68, 0x39, 0xee, 0x80, 0x5f, + 0x20, 0x1b, 0xd5, 0xcc, 0x0a, 0xc1, 0x3a, 0x02, 0xb4, 0x5e, 0x87, 0xaa, 0x5e, 0x9d, 0x71, 0x02, + 0x25, 0xa5, 0x2f, 0xa1, 0xc2, 0x30, 0xd5, 0x25, 0xb3, 0x1c, 0x46, 0x3d, 0xb9, 0x0e, 0xa5, 0x64, + 0x0f, 0xcc, 0x62, 0xf8, 0xd2, 0x0d, 0x1b, 0xdf, 0x83, 0xc6, 0x8e, 0x60, 0x1e, 0x57, 0x30, 0xab, + 0xd4, 0xff, 0x56, 0x60, 0x4e, 0xdb, 0x34, 0x65, 0x53, 0x7e, 0x89, 0x33, 0xf7, 0xd4, 0x0b, 0x42, + 0xd9, 0x0a, 0xfe, 0x6d, 0xfc, 0x49, 0x06, 0x58, 0x3b, 0x08, 0x9d, 0x91, 0x1d, 0xf2, 0x2d, 0x1e, + 0x89, 0x85, 0x7d, 0xa8, 0x8a, 0xda, 0x7a, 0x5e, 0x8b, 0x14, 0x32, 0x52, 0x28, 0xde, 0x92, 0xdb, + 0x78, 0xb6, 0xc0, 0x03, 0x9d, 0x9a, 0xc4, 0x7c, 0xa2, 0x02, 0xb1, 0xcb, 0x42, 0xdb, 0x3f, 0xe1, + 0x21, 0xaa, 0x71, 0x52, 0xdf, 0x07, 0x02, 0x09, 0x05, 0x6e, 0xed, 0x37, 0x61, 0x61, 0xa6, 0x0e, + 0x5d, 0x2e, 0x97, 0x53, 0xe4, 0x72, 0x4e, 0x97, 0xcb, 0x16, 0x2c, 0x26, 0xfa, 0x25, 0x39, 0x6d, + 0x15, 0x8a, 0x62, 0x43, 0x08, 0xe5, 0x20, 0x43, 0x5a, 0xe5, 0x31, 0xe7, 0x42, 0x0d, 0x7e, 0x08, + 0x4b, 0xc7, 0x9c, 0xfb, 0x76, 0x88, 0x48, 0xdc, 0x31, 0x62, 0x85, 0x64, 0xc5, 0x0b, 0x12, 0xd7, + 0xb5, 0xc3, 0x03, 0xee, 0x8b, 0x95, 0x32, 0xfe, 0x67, 0x06, 0xe6, 0x85, 0x04, 0xdd, 0xb5, 0xdd, + 0x4b, 0x35, 0x4f, 0x3b, 0xa9, 0xf3, 0x74, 0x4f, 0x3b, 0x0c, 0x35, 0xea, 0x6f, 0x3a, 0x49, 0xb9, + 0xe9, 0x49, 0x62, 0x77, 0xa0, 0x9a, 0xe8, 0x6b, 0x01, 0xfb, 0x0a, 0x41, 0xd4, 0xc9, 0x5f, 0x7e, + 0x1a, 0xdf, 0x80, 0x46, 0xdc, 0x6d, 0x39, 0x87, 0x0c, 0xf2, 0x82, 0x25, 0x65, 0x05, 0xf8, 0xb7, + 0xf1, 0xcf, 0x33, 0x44, 0xb8, 0xe1, 0x39, 0x91, 0x76, 0x2a, 0x08, 0x85, 0xde, 0xab, 0x08, 0xc5, + 0xdf, 0x57, 0x6a, 0xf5, 0xbf, 0xfc, 0x60, 0xc5, 0xd6, 0x09, 0xb8, 0x3b, 0xb0, 0xec, 0xe1, 0x10, + 0x85, 0x6f, 0xc9, 0x2c, 0x8a, 0xef, 0xd6, 0x70, 0x68, 0xdc, 0x85, 0x05, 0xad, 0x77, 0xcf, 0x19, + 0xc7, 0x1e, 0xb0, 0x1d, 0x27, 0x08, 0x0f, 0xdd, 0x60, 0xac, 0x29, 0x6e, 0x37, 0xa0, 0x2c, 0x24, + 0xac, 0xe8, 0x19, 0x6d, 0xd9, 0x82, 0x29, 0x44, 0xae, 0xe8, 0x57, 0x80, 0x48, 0xfb, 0x42, 0x22, + 0xb3, 0x12, 0x69, 0x5f, 0x20, 0xd2, 0xf8, 0x08, 0x16, 0x13, 0xf5, 0xc9, 0xa6, 0x5f, 0x85, 0xc2, + 0x24, 0xbc, 0xf0, 0x94, 0x6a, 0x5e, 0x91, 0x1c, 0x22, 0x0c, 0x40, 0x93, 0x30, 0xc6, 0x27, 0xb0, + 0xb0, 0xc7, 0xcf, 0xe5, 0x26, 0x56, 0x1d, 0x79, 0x03, 0xf2, 0x2f, 0x30, 0x0a, 0x11, 0x6f, 0x3c, + 0x00, 0xa6, 0x17, 0x96, 0xad, 0x6a, 0x36, 0x62, 0x26, 0x61, 0x23, 0x1a, 0x6f, 0x00, 0xeb, 0x3a, + 0x27, 0xee, 0x2e, 0x0f, 0x02, 0xfb, 0x24, 0xda, 0xf6, 0x0d, 0xc8, 0x8d, 0x82, 0x13, 0x29, 0xa3, + 0xc4, 0x9f, 0xc6, 0x77, 0x61, 0x31, 0x41, 0x27, 0x2b, 0xbe, 0x09, 0xe5, 0xc0, 0x39, 0x71, 0x51, + 0xb1, 0x92, 0x55, 0xc7, 0x00, 0x63, 0x0b, 0x96, 0x3e, 0xe3, 0xbe, 0x73, 0x7c, 0xf9, 0xa2, 0xea, + 0x93, 0xf5, 0x64, 0xa7, 0xeb, 0x69, 0xc3, 0xf2, 0x54, 0x3d, 0xb2, 0x79, 0x62, 0x5f, 0xb9, 0x92, + 0x25, 0x93, 0x3e, 0x34, 0xb9, 0x97, 0xd5, 0xe5, 0x9e, 0x71, 0x08, 0x6c, 0xc3, 0x73, 0x5d, 0xde, + 0x0f, 0x0f, 0x38, 0xf7, 0x63, 0x2f, 0x55, 0xcc, 0xab, 0x95, 0xc7, 0xab, 0x72, 0x66, 0xa7, 0x85, + 0xa9, 0x64, 0x62, 0x06, 0xf9, 0x31, 0xf7, 0x47, 0x58, 0x71, 0xc9, 0xc4, 0xbf, 0x8d, 0x65, 0x58, + 0x4c, 0x54, 0x2b, 0xed, 0xfa, 0x47, 0xb0, 0xbc, 0xe9, 0x04, 0xfd, 0xd9, 0x06, 0x57, 0xa1, 0x38, + 0x9e, 0x1c, 0x59, 0x49, 0xb9, 0xfc, 0x94, 0x5f, 0x0a, 0x6b, 0x6f, 0xba, 0x84, 0xac, 0xeb, 0x6f, + 0x67, 0x20, 0xbf, 0xdd, 0xdb, 0xd9, 0x60, 0x6b, 0x50, 0x72, 0xdc, 0xbe, 0x37, 0x12, 0x8a, 0x17, + 0x8d, 0x39, 0xfa, 0xbe, 0x72, 0x83, 0xdd, 0x80, 0x32, 0xea, 0x6b, 0xc2, 0xb4, 0x95, 0xaa, 0x4f, + 0x49, 0x00, 0x76, 0xbc, 0xfe, 0x33, 0x61, 0x53, 0xf3, 0x8b, 0xb1, 0xe3, 0xa3, 0xd5, 0xac, 0x8c, + 0xe1, 0x3c, 0x9d, 0xf5, 0x31, 0x82, 0x2c, 0x62, 0xe3, 0x3f, 0x14, 0xa1, 0x28, 0x4f, 0x5b, 0x3a, + 0xb9, 0x43, 0xe7, 0x8c, 0xc7, 0x27, 0xb7, 0xf8, 0x12, 0xfa, 0x80, 0xcf, 0x47, 0x5e, 0x18, 0x29, + 0x6c, 0xb4, 0x06, 0x55, 0x02, 0x4a, 0x95, 0x4d, 0x53, 0x1a, 0xc8, 0xc5, 0x90, 0x23, 0xa2, 0xbe, + 0x7e, 0x94, 0xdf, 0x80, 0xa2, 0x3a, 0xfb, 0xf3, 0x91, 0x4d, 0x33, 0xd7, 0x27, 0x6d, 0x6d, 0x0d, + 0x4a, 0x7d, 0x7b, 0x6c, 0xf7, 0x9d, 0xf0, 0x52, 0x0a, 0x84, 0xe8, 0x5b, 0xd4, 0x3e, 0xf4, 0xfa, + 0xf6, 0xd0, 0x3a, 0xb2, 0x87, 0xb6, 0xdb, 0xe7, 0xd2, 0x76, 0xaf, 0x22, 0x70, 0x9d, 0x60, 0xc2, + 0x3e, 0x97, 0xfd, 0x54, 0x54, 0x64, 0xc2, 0xcb, 0xde, 0x2b, 0x32, 0xa1, 0x5c, 0x7a, 0xa3, 0x91, + 0x23, 0xac, 0x0c, 0x52, 0xc3, 0x72, 0x66, 0x99, 0x20, 0x5b, 0x1c, 0x47, 0x2b, 0xd1, 0xe7, 0x34, + 0x75, 0x65, 0x6a, 0x8a, 0x80, 0x9f, 0x93, 0x23, 0x61, 0x56, 0x17, 0xcb, 0x69, 0xba, 0xd8, 0x5b, + 0xb0, 0x30, 0x71, 0x03, 0x1e, 0x86, 0x43, 0x3e, 0x88, 0xfa, 0x52, 0x41, 0xa2, 0x46, 0x84, 0x50, + 0xdd, 0x79, 0x00, 0x8b, 0xe4, 0x74, 0x08, 0xec, 0xd0, 0x0b, 0x4e, 0x9d, 0xc0, 0x0a, 0x84, 0x85, + 0x44, 0xe6, 0xee, 0x02, 0xa2, 0xba, 0x12, 0xd3, 0x25, 0x13, 0x69, 0x75, 0x8a, 0xde, 0xe7, 0x7d, + 0xee, 0x9c, 0xf1, 0x01, 0xea, 0x69, 0x39, 0x73, 0x39, 0x51, 0xc6, 0x94, 0x48, 0x54, 0xba, 0x27, + 0x23, 0x6b, 0x32, 0x1e, 0xd8, 0x42, 0x59, 0xa9, 0x93, 0x32, 0xec, 0x4e, 0x46, 0x87, 0x04, 0x61, + 0x8f, 0x40, 0x69, 0x62, 0x52, 0x3f, 0x9c, 0x4f, 0xc8, 0x33, 0xc1, 0xac, 0x66, 0x55, 0x52, 0x90, + 0xa2, 0x98, 0xd0, 0x39, 0x1b, 0x53, 0x3a, 0x67, 0x13, 0x8a, 0x63, 0xdf, 0x39, 0xb3, 0x43, 0xde, + 0x5c, 0x20, 0x01, 0x2e, 0x3f, 0x85, 0x64, 0x70, 0x5c, 0x27, 0x74, 0xec, 0xd0, 0xf3, 0x9b, 0x0c, + 0x71, 0x31, 0x80, 0xdd, 0x87, 0x05, 0xe4, 0x91, 0x20, 0xb4, 0xc3, 0x49, 0x20, 0x35, 0xd0, 0x45, + 0x64, 0x26, 0xd4, 0xa1, 0xbb, 0x08, 0x47, 0x25, 0x94, 0x7d, 0x17, 0x56, 0x88, 0x2d, 0xb0, 0x84, + 0xd4, 0xac, 0x51, 0x21, 0x58, 0xc2, 0xa9, 0x58, 0x44, 0xac, 0xe0, 0x6f, 0xa9, 0x5f, 0x0b, 0xed, + 0xe0, 0x7d, 0x58, 0x95, 0x6c, 0x32, 0x53, 0x6a, 0x19, 0x4b, 0x2d, 0x11, 0x7a, 0xaa, 0xd8, 0x7d, + 0x58, 0x10, 0x5d, 0x72, 0xfa, 0x96, 0x2c, 0x2d, 0x76, 0xc2, 0x0a, 0xf6, 0x7e, 0x9e, 0x10, 0x26, + 0xc2, 0x9f, 0xf2, 0x4b, 0xc1, 0xca, 0x43, 0xe7, 0x98, 0x87, 0xce, 0x88, 0x37, 0x57, 0x89, 0x39, + 0xd4, 0xb7, 0xd8, 0x65, 0x93, 0x31, 0x62, 0x9a, 0xb4, 0xa7, 0xe9, 0x0b, 0xf9, 0x6e, 0xe8, 0x05, + 0x5c, 0xb9, 0x97, 0x9a, 0xd7, 0xe5, 0x06, 0x12, 0x40, 0x29, 0xb2, 0x8c, 0x9f, 0x65, 0xe8, 0x0c, + 0x92, 0x5b, 0x36, 0xd0, 0x2c, 0x2a, 0xda, 0xac, 0x96, 0xe7, 0x0e, 0x2f, 0xe5, 0xfe, 0x05, 0x02, + 0xed, 0xbb, 0x43, 0xdc, 0x40, 0x8e, 0xab, 0x93, 0x90, 0xb8, 0xab, 0x2a, 0x20, 0x12, 0xdd, 0x86, + 0xca, 0x78, 0x72, 0x34, 0x74, 0xfa, 0x44, 0x92, 0xa3, 0x5a, 0x08, 0x84, 0x04, 0xc2, 0xa4, 0xa4, + 0x45, 0x24, 0x8a, 0x3c, 0x52, 0x54, 0x24, 0x0c, 0x49, 0x50, 0x9c, 0x72, 0x1f, 0x77, 0x70, 0xd5, + 0xc4, 0xbf, 0x8d, 0x75, 0x58, 0x4a, 0x76, 0x5a, 0xca, 0xfa, 0xfb, 0x50, 0x92, 0xe2, 0x41, 0xf9, + 0x1a, 0xea, 0x9a, 0xf7, 0x57, 0x58, 0x45, 0x11, 0xde, 0xf8, 0xbd, 0x39, 0x58, 0x94, 0xd0, 0x0d, + 0x31, 0x23, 0xdd, 0xc9, 0x68, 0x64, 0xfb, 0x29, 0x72, 0x27, 0xf3, 0x7c, 0xb9, 0x93, 0x9d, 0x91, + 0x3b, 0x49, 0x63, 0x93, 0xc4, 0x56, 0xd2, 0xd8, 0x14, 0x4b, 0x40, 0xfa, 0xbf, 0xee, 0x7a, 0xac, + 0x49, 0x70, 0x8f, 0x5c, 0x9c, 0x33, 0x52, 0xb2, 0x90, 0x22, 0x25, 0x75, 0x19, 0x37, 0x37, 0x25, + 0xe3, 0x5e, 0x05, 0x5a, 0x6b, 0x25, 0xb2, 0x8b, 0x64, 0x12, 0x20, 0x4c, 0xfa, 0x2f, 0xef, 0xc2, + 0xfc, 0xb4, 0x58, 0x21, 0xf9, 0x55, 0x4f, 0x11, 0x2a, 0xce, 0x88, 0xe3, 0x01, 0xa1, 0x11, 0x97, + 0xa5, 0x50, 0x71, 0x46, 0x7c, 0x07, 0x31, 0x8a, 0xbe, 0x0d, 0x40, 0x6d, 0xa3, 0x46, 0x02, 0xa8, + 0x91, 0xbc, 0x91, 0x5c, 0x0b, 0x7d, 0xd6, 0x1f, 0x88, 0x8f, 0x89, 0xcf, 0x51, 0x4b, 0x29, 0x63, + 0x49, 0x74, 0x5c, 0x3f, 0x85, 0xba, 0x37, 0xe6, 0xae, 0x15, 0x6f, 0xef, 0x0a, 0x56, 0xf5, 0xfa, + 0x73, 0xaa, 0xea, 0x28, 0x5a, 0xb3, 0x26, 0xca, 0x46, 0x9f, 0x6c, 0x97, 0x26, 0x9e, 0x6b, 0xb5, + 0x55, 0xbf, 0x41, 0x6d, 0x75, 0x2c, 0x1c, 0x7d, 0x1b, 0x7f, 0x2f, 0x03, 0x15, 0xad, 0xdb, 0x6c, + 0x19, 0x16, 0x36, 0xf6, 0xf7, 0x0f, 0xda, 0x66, 0xab, 0xd7, 0xf9, 0xac, 0x6d, 0x6d, 0xec, 0xec, + 0x77, 0xdb, 0x8d, 0x6b, 0x02, 0xbc, 0xb3, 0xbf, 0xd1, 0xda, 0xb1, 0xb6, 0xf6, 0xcd, 0x0d, 0x05, + 0xce, 0xb0, 0x15, 0x60, 0x66, 0x7b, 0x77, 0xbf, 0xd7, 0x4e, 0xc0, 0xb3, 0xac, 0x01, 0xd5, 0x75, + 0xb3, 0xdd, 0xda, 0xd8, 0x96, 0x90, 0x1c, 0x5b, 0x82, 0xc6, 0xd6, 0xe1, 0xde, 0x66, 0x67, 0xef, + 0x89, 0xb5, 0xd1, 0xda, 0xdb, 0x68, 0xef, 0xb4, 0x37, 0x1b, 0x79, 0x56, 0x83, 0x72, 0x6b, 0xbd, + 0xb5, 0xb7, 0xb9, 0xbf, 0xd7, 0xde, 0x6c, 0x14, 0x8c, 0xdf, 0x80, 0x72, 0x3c, 0xd0, 0x0a, 0x14, + 0x0f, 0xf7, 0x9e, 0xee, 0xed, 0x7f, 0xbe, 0xd7, 0xb8, 0xc6, 0xca, 0x50, 0xc0, 0xf6, 0x1b, 0x19, + 0x06, 0x30, 0x47, 0x6d, 0x36, 0xb2, 0xac, 0x04, 0xf9, 0xf5, 0xfd, 0xde, 0x76, 0x23, 0x67, 0xfc, + 0x45, 0x06, 0x96, 0x71, 0xc8, 0x83, 0x69, 0x21, 0x70, 0x07, 0x2a, 0x7d, 0xcf, 0x1b, 0x0b, 0xe3, + 0x26, 0x3e, 0xc4, 0x75, 0x90, 0xd8, 0xe0, 0x24, 0x2f, 0x8f, 0x3d, 0xbf, 0xcf, 0xa5, 0x0c, 0x00, + 0x04, 0x6d, 0x09, 0x88, 0xe0, 0x41, 0xc9, 0xc4, 0x44, 0x41, 0x22, 0xa0, 0x42, 0x30, 0x22, 0x59, + 0x81, 0xb9, 0x23, 0x9f, 0xdb, 0xfd, 0x53, 0xb9, 0xfb, 0xe5, 0x17, 0x7b, 0x33, 0x36, 0xbb, 0xfb, + 0x82, 0xa7, 0x86, 0x7c, 0x80, 0x5b, 0xa0, 0x64, 0xce, 0x4b, 0xf8, 0x86, 0x04, 0x8b, 0x03, 0xc0, + 0x3e, 0xb2, 0xdd, 0x81, 0xe7, 0xf2, 0x81, 0xd4, 0xee, 0x63, 0x80, 0x71, 0x00, 0x2b, 0xd3, 0xe3, + 0x93, 0xf2, 0xe2, 0x03, 0x4d, 0x5e, 0x90, 0xb2, 0xbd, 0x76, 0x35, 0x2b, 0x68, 0xb2, 0xe3, 0xe7, + 0x39, 0xc8, 0x0b, 0xe5, 0xeb, 0x4a, 0x3d, 0x4d, 0xd7, 0xa6, 0x73, 0x33, 0x11, 0x17, 0xb4, 0xee, + 0xe9, 0x54, 0x26, 0x17, 0x52, 0x19, 0x21, 0x78, 0x1a, 0x47, 0x68, 0x9f, 0xf7, 0xcf, 0xa4, 0x0f, + 0x89, 0xd0, 0x26, 0xef, 0x9f, 0xa1, 0x19, 0x63, 0x87, 0x54, 0x96, 0xf6, 0x7b, 0x31, 0xb0, 0x43, + 0x2c, 0x29, 0x51, 0x58, 0xae, 0x18, 0xa1, 0xb0, 0x54, 0x13, 0x8a, 0x8e, 0x7b, 0xe4, 0x4d, 0xdc, + 0x01, 0x6e, 0xef, 0x92, 0xa9, 0x3e, 0x31, 0xc0, 0x83, 0x92, 0x48, 0x9c, 0x1f, 0xb4, 0x9b, 0x4b, + 0x02, 0xd0, 0x13, 0x27, 0xc8, 0xbb, 0x50, 0x0e, 0x2e, 0xdd, 0xbe, 0xbe, 0x87, 0x97, 0xe4, 0xfc, + 0x88, 0xd1, 0x3f, 0xe8, 0x5e, 0xba, 0x7d, 0xdc, 0xb1, 0xa5, 0x40, 0xfe, 0xc5, 0xde, 0x87, 0x52, + 0xe4, 0x6a, 0x25, 0x09, 0x7c, 0x5d, 0x2f, 0xa1, 0xfc, 0xab, 0x64, 0xd1, 0x46, 0xa4, 0x6b, 0x4f, + 0xa1, 0x96, 0x40, 0xe9, 0x66, 0x68, 0x8d, 0xcc, 0xd0, 0xd7, 0x75, 0x33, 0x34, 0x16, 0xec, 0xb2, + 0x98, 0x6e, 0x96, 0xfe, 0x26, 0x94, 0x54, 0xcf, 0xc4, 0x76, 0x92, 0x5b, 0xc1, 0xea, 0x7e, 0xb1, + 0xb7, 0xd1, 0xb8, 0xc6, 0xe6, 0xa1, 0xd2, 0xda, 0xc0, 0x1d, 0x8a, 0x80, 0x8c, 0x20, 0x39, 0x68, + 0x75, 0xbb, 0x11, 0x24, 0x6b, 0x30, 0x68, 0x88, 0xe3, 0x45, 0xf4, 0x38, 0x0a, 0xa6, 0x7c, 0x00, + 0x0b, 0x1a, 0x2c, 0xb6, 0xd4, 0xc4, 0x79, 0x34, 0x6d, 0xa9, 0xa1, 0x5e, 0x4e, 0x18, 0x63, 0x15, + 0x96, 0xc5, 0x67, 0xfb, 0x8c, 0xbb, 0x61, 0x77, 0x72, 0x44, 0xa1, 0x34, 0xc7, 0x73, 0x85, 0xbe, + 0x5e, 0x8e, 0x30, 0x57, 0x33, 0xd2, 0x03, 0x69, 0xd4, 0x65, 0x71, 0xfa, 0xd7, 0xb4, 0x16, 0xb0, + 0xe0, 0x03, 0xfc, 0x37, 0x61, 0xdc, 0x95, 0x23, 0x90, 0x18, 0xeb, 0x41, 0xbb, 0x6d, 0x5a, 0xfb, + 0x7b, 0x3b, 0x9d, 0x3d, 0x21, 0x8c, 0xc4, 0x58, 0x11, 0xb0, 0xb5, 0x85, 0x90, 0x8c, 0xd1, 0x80, + 0xfa, 0x13, 0x1e, 0x76, 0xdc, 0x63, 0x4f, 0x8d, 0xf4, 0x17, 0x05, 0x98, 0x8f, 0x40, 0xb1, 0x71, + 0x78, 0xc6, 0xfd, 0xc0, 0xf1, 0x5c, 0xd4, 0xf3, 0xca, 0xa6, 0xfa, 0x14, 0x27, 0x88, 0x33, 0xe0, + 0x6e, 0xe8, 0x84, 0x97, 0x56, 0xc2, 0x93, 0x54, 0x57, 0x60, 0x79, 0x52, 0x2d, 0x41, 0xc1, 0x1e, + 0x3a, 0xb6, 0x8a, 0x40, 0xd2, 0x87, 0x80, 0xf6, 0xbd, 0xa1, 0xe7, 0xa3, 0x4a, 0x57, 0x36, 0xe9, + 0x83, 0x3d, 0x82, 0x25, 0xa1, 0x5a, 0xea, 0xee, 0x3d, 0xdc, 0xa3, 0xe4, 0xd4, 0x62, 0xee, 0x64, + 0x74, 0x10, 0xbb, 0xf8, 0x04, 0x46, 0x9c, 0x4f, 0xa2, 0x84, 0x54, 0x48, 0xa2, 0x02, 0x64, 0xa5, + 0x2c, 0xb8, 0x93, 0x51, 0x0b, 0x31, 0x11, 0xfd, 0x63, 0x58, 0x16, 0xf4, 0x91, 0x0a, 0x13, 0x95, + 0x98, 0xc7, 0x12, 0xa2, 0xb2, 0x8e, 0xc4, 0x45, 0x65, 0x6e, 0x40, 0x99, 0x7a, 0x25, 0x56, 0xbc, + 0x40, 0xda, 0x29, 0x76, 0x85, 0xfb, 0xc1, 0x4c, 0xb0, 0x70, 0x8e, 0x0e, 0xdb, 0xa9, 0x60, 0xa1, + 0x16, 0x6e, 0x2c, 0x4d, 0x87, 0x1b, 0x1f, 0xc3, 0xf2, 0x11, 0x0f, 0x42, 0xeb, 0x94, 0xdb, 0x03, + 0xee, 0xe3, 0x8e, 0xa4, 0xb0, 0x22, 0x69, 0xe1, 0x8b, 0x02, 0xb9, 0x8d, 0xb8, 0x9e, 0x42, 0x09, + 0x5d, 0x42, 0x6c, 0x3d, 0x3e, 0xb0, 0x42, 0xcf, 0x42, 0x15, 0x03, 0x37, 0x71, 0xc9, 0xac, 0x11, + 0xb8, 0xe7, 0x6d, 0x08, 0x60, 0x92, 0xee, 0xc4, 0xb7, 0xc7, 0xa7, 0x52, 0x4f, 0x8e, 0xe8, 0x9e, + 0x08, 0x20, 0xbb, 0x09, 0xc5, 0x90, 0x07, 0xa1, 0xcb, 0x29, 0xa6, 0x53, 0x42, 0x9f, 0xbd, 0x02, + 0xb1, 0xd7, 0x61, 0x0e, 0xdb, 0x08, 0x9a, 0x0d, 0xe4, 0xf7, 0x6a, 0x2c, 0x2c, 0x1d, 0xd7, 0x94, + 0x38, 0xa1, 0xb0, 0x4d, 0x7c, 0x27, 0x68, 0x56, 0x31, 0x96, 0x89, 0x7f, 0xb3, 0xdf, 0xd2, 0xc4, + 0xc2, 0x22, 0x96, 0x55, 0x67, 0xee, 0x14, 0xa7, 0xfd, 0x5a, 0x24, 0xc4, 0xf7, 0xf3, 0xa5, 0x4a, + 0xa3, 0x6a, 0x7c, 0x08, 0x05, 0x9a, 0x1d, 0xc1, 0x84, 0x38, 0x77, 0x19, 0xc9, 0x84, 0x08, 0x6d, + 0x42, 0xd1, 0xe5, 0xe1, 0xb9, 0xe7, 0x3f, 0x53, 0xbe, 0x56, 0xf9, 0x69, 0xfc, 0x18, 0x9d, 0x04, + 0x51, 0x20, 0x99, 0xec, 0x1d, 0xc1, 0x1e, 0xb4, 0xbc, 0xc1, 0xa9, 0x2d, 0xfd, 0x16, 0x25, 0x04, + 0x74, 0x4f, 0xed, 0x19, 0xf6, 0xc8, 0xce, 0xc6, 0x92, 0x5f, 0x87, 0xba, 0x0a, 0x5d, 0x07, 0xd6, + 0x90, 0x1f, 0x87, 0x92, 0xdd, 0xab, 0x32, 0x6e, 0x1d, 0xec, 0xf0, 0xe3, 0xd0, 0xd8, 0x85, 0x05, + 0xc9, 0x90, 0xfb, 0x63, 0xae, 0x9a, 0xfe, 0x28, 0x4d, 0x67, 0xad, 0x3c, 0x5e, 0x4c, 0x1e, 0x66, + 0x14, 0x92, 0x4f, 0x28, 0xb2, 0xc6, 0xa7, 0xc0, 0xf4, 0xa3, 0x4e, 0xd6, 0x27, 0x35, 0x47, 0xe5, + 0xa2, 0x56, 0x91, 0x9e, 0x48, 0x3f, 0x75, 0x06, 0x62, 0x76, 0x82, 0x49, 0xbf, 0xaf, 0x52, 0x0a, + 0x4a, 0xa6, 0xfa, 0x34, 0xfe, 0x2c, 0x03, 0x8b, 0x58, 0x99, 0xd2, 0xb9, 0xa5, 0x36, 0xf1, 0xad, + 0x3b, 0x29, 0xd6, 0x47, 0xd7, 0x2f, 0xe8, 0xe3, 0x9b, 0x3b, 0x05, 0xf3, 0x33, 0x4e, 0xc1, 0x37, + 0xa1, 0x31, 0xe0, 0x43, 0x07, 0xb3, 0x4b, 0xd4, 0x71, 0x4d, 0x5a, 0xf6, 0xbc, 0x82, 0x2b, 0x43, + 0xe9, 0x9f, 0x64, 0x60, 0x81, 0xb4, 0x01, 0x34, 0x17, 0xe5, 0x44, 0x7d, 0xa2, 0x6c, 0x2c, 0x29, + 0xaa, 0xe4, 0x98, 0xe2, 0x53, 0x12, 0xa1, 0x44, 0xbc, 0x7d, 0x4d, 0xda, 0x5e, 0x12, 0xca, 0x3e, + 0x46, 0x3b, 0xc1, 0xb5, 0x10, 0x98, 0x92, 0xad, 0x92, 0x5c, 0x94, 0xed, 0x6b, 0x68, 0x44, 0xb8, + 0x08, 0x5a, 0x2f, 0x09, 0xa3, 0x4f, 0x80, 0x8d, 0x2d, 0xa8, 0x25, 0x9a, 0x49, 0x78, 0x2e, 0xab, + 0xe4, 0xb9, 0x9c, 0x89, 0x0e, 0x64, 0x67, 0xa3, 0x03, 0x7f, 0x27, 0x0f, 0x4c, 0xb0, 0xd4, 0xd4, + 0xaa, 0x4d, 0x85, 0xd6, 0xb2, 0x33, 0xa1, 0xb5, 0x47, 0xc0, 0x34, 0x02, 0x15, 0xf1, 0xcb, 0x45, + 0x11, 0xbf, 0x46, 0x4c, 0x2b, 0x03, 0x7e, 0x8f, 0x60, 0x49, 0x2a, 0x8d, 0x51, 0x2c, 0x0d, 0x5d, + 0x52, 0xb4, 0x3e, 0x8c, 0xb4, 0x47, 0x15, 0x53, 0x43, 0xf7, 0x94, 0x0a, 0xab, 0x09, 0x93, 0x9a, + 0x3c, 0x39, 0x18, 0x56, 0x13, 0x56, 0xf4, 0x14, 0x17, 0xcc, 0xbd, 0x90, 0x0b, 0x8a, 0x33, 0x5c, + 0xa0, 0x39, 0x16, 0x4a, 0x49, 0xc7, 0x82, 0x01, 0x35, 0x15, 0x3c, 0xa3, 0x9c, 0x01, 0xd2, 0x90, + 0x2a, 0x32, 0x82, 0x86, 0x79, 0x03, 0xf7, 0xa0, 0xa1, 0xac, 0xff, 0xc8, 0x75, 0x41, 0xf1, 0x70, + 0xe9, 0x3c, 0xda, 0x50, 0x0e, 0x8c, 0x84, 0xa3, 0xb8, 0x32, 0xe5, 0x28, 0x7e, 0x0b, 0x16, 0x02, + 0xc1, 0x44, 0xd6, 0xc4, 0x95, 0xc9, 0x2b, 0x7c, 0x80, 0xe6, 0x49, 0xc9, 0x6c, 0x20, 0xe2, 0x30, + 0x86, 0xcf, 0x9a, 0xf6, 0xb5, 0x59, 0xd3, 0x9e, 0xbd, 0x1f, 0xc7, 0x99, 0x82, 0x53, 0x67, 0x84, + 0x07, 0x77, 0x9c, 0xe8, 0x21, 0x27, 0xb8, 0x7b, 0xea, 0x8c, 0x4c, 0x15, 0xd4, 0x14, 0x1f, 0xc6, + 0x7f, 0xce, 0x40, 0x43, 0xf0, 0x41, 0x82, 0xcf, 0x7f, 0x03, 0x70, 0x47, 0xbe, 0x24, 0x9b, 0x57, + 0x04, 0xad, 0xe2, 0xf2, 0x0f, 0x01, 0xd9, 0xd6, 0x12, 0xb6, 0x98, 0x64, 0xf2, 0x66, 0x92, 0xc9, + 0x63, 0x41, 0xb6, 0x7d, 0x8d, 0x94, 0x6c, 0x01, 0x49, 0x8b, 0xef, 0xe5, 0x53, 0xe2, 0x7b, 0xda, + 0x56, 0xd8, 0x06, 0x78, 0xca, 0x2f, 0x77, 0xbc, 0x3e, 0x5a, 0x41, 0xb7, 0x00, 0x04, 0x43, 0x1e, + 0xdb, 0x23, 0x47, 0x7a, 0x30, 0x0a, 0x66, 0xf9, 0x19, 0xbf, 0xdc, 0x42, 0x80, 0x58, 0x0d, 0x81, + 0x8e, 0xf7, 0x43, 0xc1, 0x2c, 0x3d, 0xe3, 0x97, 0xb4, 0x19, 0x2c, 0xa8, 0x3d, 0xe5, 0x97, 0x9b, + 0x9c, 0xd4, 0x35, 0xcf, 0x17, 0x9c, 0xe0, 0xdb, 0xe7, 0x42, 0x3f, 0x4b, 0xc4, 0xe6, 0x2a, 0xbe, + 0x7d, 0xfe, 0x94, 0x5f, 0xaa, 0x38, 0x61, 0x51, 0xe0, 0x87, 0x5e, 0x5f, 0x9e, 0x40, 0x2a, 0xcb, + 0x20, 0xee, 0x94, 0x39, 0xf7, 0x0c, 0xff, 0x36, 0xfe, 0x34, 0x03, 0x35, 0xd1, 0x7f, 0x14, 0x70, + 0x62, 0xde, 0x55, 0xb2, 0x4a, 0x26, 0x4e, 0x56, 0x79, 0x2c, 0xe5, 0x03, 0x49, 0xcb, 0xec, 0xd5, + 0xd2, 0x12, 0x27, 0x98, 0x44, 0xe5, 0xbb, 0x50, 0xa6, 0xbd, 0x25, 0x36, 0x6b, 0x2e, 0xb1, 0x4a, + 0x89, 0x01, 0x99, 0x25, 0x24, 0x7b, 0x4a, 0xb1, 0x71, 0xcd, 0x01, 0x45, 0x53, 0x5c, 0xf6, 0x23, + 0xd7, 0x53, 0xca, 0x32, 0x14, 0xd2, 0xc2, 0xac, 0x87, 0x50, 0xd1, 0x78, 0x8a, 0x7d, 0x8f, 0x02, + 0xd4, 0xd4, 0x79, 0x62, 0xc0, 0x24, 0xd3, 0x24, 0x46, 0xbf, 0x7d, 0xcd, 0xac, 0xf5, 0x75, 0xc0, + 0xfa, 0x1c, 0xe4, 0x45, 0x21, 0xe3, 0x13, 0x58, 0xd0, 0xaa, 0x25, 0x8b, 0x2f, 0xad, 0x4f, 0x99, + 0xb4, 0x3e, 0xfd, 0xd3, 0x0c, 0x2c, 0xc9, 0xd2, 0x98, 0xd8, 0xe4, 0x88, 0xe3, 0x7a, 0x37, 0x38, + 0x61, 0xbf, 0x01, 0x35, 0x51, 0xbb, 0xe5, 0xf3, 0x13, 0x27, 0x08, 0xb9, 0xf2, 0xec, 0xa7, 0x6c, + 0x0e, 0x21, 0xb5, 0x05, 0xa9, 0x29, 0x29, 0xd9, 0x27, 0x50, 0xc1, 0xa2, 0x64, 0x93, 0xca, 0x65, + 0x69, 0xce, 0x16, 0xa4, 0xae, 0x6e, 0x5f, 0x33, 0x21, 0x88, 0xbe, 0xd6, 0xcb, 0x50, 0x0c, 0x7d, + 0xe7, 0xe4, 0x84, 0xfb, 0xc6, 0x4a, 0xd4, 0x35, 0xb1, 0xd3, 0x78, 0x37, 0xe4, 0x63, 0xa1, 0x04, + 0x19, 0xff, 0x35, 0x03, 0x15, 0xb9, 0x77, 0xbe, 0xb5, 0x3b, 0x7f, 0x4d, 0xcb, 0xcc, 0x23, 0xf3, + 0x33, 0x4e, 0xc4, 0xbb, 0x0b, 0xf3, 0x23, 0xa1, 0x10, 0x09, 0x85, 0x3d, 0xe1, 0xcb, 0xaf, 0x2b, + 0xb0, 0xd4, 0x47, 0x1e, 0xc0, 0x22, 0xaa, 0x27, 0x81, 0x15, 0x3a, 0x43, 0x4b, 0x21, 0x65, 0x16, + 0xdc, 0x02, 0xa1, 0x7a, 0xce, 0x70, 0x57, 0x22, 0xc4, 0x29, 0x1d, 0x84, 0xf6, 0x09, 0x97, 0xaa, + 0x2f, 0x7d, 0x18, 0x4d, 0x58, 0x99, 0xd2, 0xd5, 0x95, 0x9d, 0xf1, 0xf7, 0x6b, 0xb0, 0x3a, 0x83, + 0x92, 0xf6, 0x46, 0xe4, 0xc3, 0x1e, 0x3a, 0xa3, 0x23, 0x2f, 0x72, 0x37, 0x65, 0x34, 0x1f, 0xf6, + 0x8e, 0xc0, 0x28, 0x77, 0x13, 0x87, 0x65, 0xc5, 0x10, 0xe8, 0x2f, 0x8a, 0xd4, 0xf9, 0x2c, 0x2a, + 0x9b, 0xef, 0x26, 0x05, 0xd5, 0x74, 0x73, 0x0a, 0xae, 0x1f, 0x7f, 0x8b, 0xe3, 0x19, 0x58, 0xc0, + 0x8e, 0xa1, 0x19, 0xf1, 0x9d, 0xd4, 0x8f, 0x34, 0xdb, 0x44, 0xb4, 0xf4, 0xf6, 0x0b, 0x5a, 0x4a, + 0x38, 0x22, 0xcc, 0x15, 0xc5, 0xae, 0x54, 0x59, 0xd4, 0xce, 0x19, 0xbc, 0xa2, 0xda, 0x41, 0x5d, + 0x67, 0xb6, 0xb5, 0xfc, 0x4b, 0x8d, 0x0b, 0x1d, 0x2c, 0xc9, 0x26, 0x6f, 0xc8, 0x8a, 0x23, 0x94, + 0xde, 0xee, 0x29, 0xac, 0x9c, 0xdb, 0x4e, 0xa8, 0xc6, 0xa7, 0x99, 0x45, 0x05, 0x6c, 0xef, 0xf1, + 0x0b, 0xda, 0xfb, 0x9c, 0x0a, 0x27, 0xb4, 0xbf, 0xa5, 0xf3, 0x59, 0x60, 0xb0, 0xf6, 0x1f, 0xb3, + 0x50, 0x4f, 0xd6, 0x22, 0x36, 0xb5, 0x94, 0x43, 0x4a, 0x9f, 0x90, 0xfa, 0xb8, 0x74, 0x83, 0xee, + 0x91, 0x1e, 0x31, 0xeb, 0xa0, 0xcd, 0xa6, 0x38, 0x68, 0x75, 0xbf, 0x68, 0xee, 0x45, 0xb1, 0x9f, + 0xfc, 0x4b, 0xc5, 0x7e, 0x0a, 0x69, 0xb1, 0x9f, 0xab, 0x03, 0x06, 0x73, 0xdf, 0x2a, 0x60, 0x50, + 0xbc, 0x3a, 0x60, 0xb0, 0xf6, 0x7f, 0x32, 0xc0, 0x66, 0x39, 0x95, 0x3d, 0x21, 0x5f, 0xb4, 0xcb, + 0x87, 0x52, 0x8a, 0xbd, 0xf3, 0x72, 0xdc, 0xae, 0x16, 0x48, 0x95, 0x66, 0x0f, 0x61, 0x51, 0xcf, + 0x9b, 0xd5, 0x4d, 0x95, 0x9a, 0xc9, 0x74, 0x54, 0x6c, 0xd0, 0x6a, 0x81, 0xaf, 0xfc, 0x0b, 0x03, + 0x5f, 0x85, 0x17, 0x06, 0xbe, 0xe6, 0x92, 0x81, 0xaf, 0xb5, 0xbf, 0x95, 0x81, 0xc5, 0x14, 0xa6, + 0xfa, 0xd5, 0x8d, 0x59, 0xf0, 0x42, 0x42, 0xc4, 0x64, 0x25, 0x2f, 0x68, 0xd2, 0x65, 0xed, 0x2b, + 0xa8, 0x25, 0x36, 0xd1, 0xaf, 0xae, 0xf9, 0x69, 0x43, 0x8b, 0x58, 0x59, 0x37, 0xb4, 0xd6, 0xfe, + 0x2a, 0x0b, 0x6c, 0x76, 0x1f, 0xff, 0x3a, 0xbb, 0x30, 0x3b, 0x49, 0xb9, 0xd9, 0x49, 0xfa, 0x7f, + 0x77, 0xae, 0xbc, 0x05, 0x0b, 0x32, 0xd7, 0x5f, 0x0b, 0x3c, 0x10, 0xa3, 0x34, 0x22, 0x84, 0xea, + 0xc5, 0x87, 0xd3, 0x31, 0xc7, 0x52, 0x22, 0xbd, 0x59, 0x3b, 0x58, 0x93, 0xa1, 0x47, 0x63, 0x0d, + 0x9a, 0x72, 0x6a, 0x66, 0x5d, 0x75, 0x3f, 0xc9, 0x47, 0x56, 0x32, 0x22, 0xa5, 0x52, 0xfc, 0x5d, + 0xa8, 0xea, 0x87, 0x8d, 0x5c, 0x87, 0xa9, 0x88, 0x93, 0x50, 0x87, 0x3d, 0x6d, 0xb7, 0x6e, 0x00, + 0xc5, 0x11, 0x06, 0x51, 0x31, 0xd2, 0x20, 0x9e, 0xe3, 0x78, 0x46, 0xe5, 0x28, 0xb1, 0xf8, 0xff, + 0x1f, 0xd4, 0x93, 0x7e, 0x2b, 0xa9, 0xea, 0xa5, 0x69, 0x87, 0xa2, 0x74, 0xc2, 0x91, 0xc5, 0x7e, + 0x0b, 0x1a, 0xd3, 0x7e, 0x2f, 0x99, 0x7b, 0x79, 0x45, 0xf9, 0x79, 0x27, 0xe9, 0x0a, 0x63, 0xdb, + 0xb0, 0x94, 0x76, 0xdc, 0xe2, 0xaa, 0x5c, 0x6d, 0x16, 0xb0, 0xd9, 0x23, 0x95, 0x7d, 0x24, 0xdd, + 0x9b, 0x85, 0xb4, 0x40, 0x8c, 0x36, 0xd9, 0x0f, 0xe8, 0x3f, 0xcd, 0xd1, 0x79, 0x06, 0x10, 0xc3, + 0x58, 0x03, 0xaa, 0xfb, 0x07, 0xed, 0x3d, 0x6b, 0x63, 0xbb, 0xb5, 0xb7, 0xd7, 0xde, 0x69, 0x5c, + 0x63, 0x0c, 0xea, 0x18, 0x41, 0xd9, 0x8c, 0x60, 0x19, 0x01, 0x93, 0xbe, 0x5f, 0x05, 0xcb, 0xb2, + 0x25, 0x68, 0x74, 0xf6, 0xa6, 0xa0, 0x39, 0xd6, 0x84, 0xa5, 0x83, 0x36, 0x05, 0x5d, 0x12, 0xf5, + 0xe6, 0x85, 0x0a, 0x27, 0x87, 0x2b, 0x54, 0x38, 0xba, 0x29, 0x22, 0xb9, 0x4f, 0x69, 0x36, 0x3f, + 0xcd, 0xc0, 0xf2, 0x14, 0x22, 0xce, 0xff, 0x25, 0xbd, 0x26, 0xa9, 0xd1, 0x54, 0x11, 0xa8, 0x78, + 0xf8, 0x2d, 0x58, 0x88, 0x4c, 0xbd, 0x29, 0xb9, 0xd4, 0x88, 0x10, 0x8a, 0xf8, 0x21, 0x2c, 0x6a, + 0x16, 0xe3, 0xd4, 0x0e, 0x65, 0x1a, 0x4a, 0x16, 0x30, 0x56, 0xa3, 0x3c, 0xcb, 0xa9, 0x5e, 0x0f, + 0xe8, 0xfa, 0x89, 0x8e, 0x88, 0xbd, 0xbf, 0xc9, 0xfe, 0xaa, 0x4f, 0x61, 0xca, 0x27, 0x18, 0x21, + 0xd9, 0x5b, 0x7d, 0xc1, 0x55, 0xf3, 0x7f, 0x38, 0x07, 0xec, 0xd3, 0x09, 0xf7, 0x2f, 0x31, 0xbf, + 0x37, 0x78, 0x51, 0xc2, 0x8b, 0x32, 0x8b, 0xb2, 0x2f, 0x95, 0xc3, 0x9f, 0x96, 0x43, 0x9f, 0x7f, + 0x71, 0x0e, 0x7d, 0xe1, 0x45, 0x39, 0xf4, 0xaf, 0x41, 0xcd, 0x39, 0x71, 0x3d, 0x21, 0x80, 0x84, + 0x6e, 0x12, 0x34, 0xe7, 0xee, 0xe4, 0xee, 0x55, 0xcd, 0xaa, 0x04, 0x0a, 0xcd, 0x24, 0x60, 0x9f, + 0xc4, 0x44, 0x7c, 0x70, 0x82, 0xf7, 0x3d, 0x74, 0xd1, 0xd3, 0x1e, 0x9c, 0x70, 0x69, 0x05, 0xa2, + 0x5f, 0x44, 0x15, 0x16, 0xf0, 0x80, 0xbd, 0x0e, 0xf5, 0xc0, 0x9b, 0x08, 0x55, 0x4f, 0x4d, 0x03, + 0xf9, 0x87, 0xab, 0x04, 0x3d, 0x50, 0xc1, 0x80, 0xc5, 0x49, 0xc0, 0xad, 0x91, 0x13, 0x04, 0xe2, + 0x80, 0xee, 0x7b, 0x6e, 0xe8, 0x7b, 0x43, 0xe9, 0xf2, 0x5d, 0x98, 0x04, 0x7c, 0x97, 0x30, 0x1b, + 0x84, 0x60, 0xef, 0xc5, 0x5d, 0x1a, 0xdb, 0x8e, 0x1f, 0x34, 0x01, 0xbb, 0xa4, 0x46, 0x8a, 0x1a, + 0x95, 0xed, 0xf8, 0x51, 0x5f, 0xc4, 0x47, 0x30, 0x95, 0xdb, 0x5f, 0x99, 0xce, 0xed, 0xff, 0x51, + 0x7a, 0x6e, 0x7f, 0x0d, 0xab, 0x7e, 0x24, 0xab, 0x9e, 0x5d, 0xe2, 0x6f, 0x94, 0xe2, 0x3f, 0x7b, + 0x65, 0xa1, 0xfe, 0x4d, 0xae, 0x2c, 0xcc, 0xa7, 0x5d, 0x59, 0x78, 0x17, 0x2a, 0x98, 0x4c, 0x6e, + 0x9d, 0x3a, 0x6e, 0xa8, 0x5c, 0xd8, 0x0d, 0x3d, 0xdb, 0x7c, 0x5b, 0x18, 0xd3, 0xe0, 0xab, 0x3f, + 0x83, 0xd9, 0xdb, 0x03, 0x0b, 0xbf, 0xc6, 0xdb, 0x03, 0x32, 0xe9, 0xfd, 0x01, 0x94, 0xd4, 0x3a, + 0x31, 0x06, 0xf9, 0x63, 0xdf, 0x1b, 0x29, 0xd7, 0x9e, 0xf8, 0x9b, 0xd5, 0x21, 0x1b, 0x7a, 0xb2, + 0x70, 0x36, 0xf4, 0x8c, 0xdf, 0x81, 0x8a, 0xc6, 0x6a, 0xec, 0x55, 0x72, 0x22, 0x08, 0x6d, 0x59, + 0x5a, 0xc9, 0x34, 0x8b, 0x65, 0x09, 0xed, 0x0c, 0x84, 0xbc, 0x19, 0x38, 0x3e, 0xc7, 0x7b, 0x3e, + 0x96, 0xcf, 0xcf, 0xb8, 0x1f, 0x28, 0x57, 0x6b, 0x23, 0x42, 0x98, 0x04, 0x37, 0xfe, 0x3a, 0x2c, + 0x26, 0xd6, 0x56, 0x8a, 0x88, 0xd7, 0x61, 0x0e, 0xe7, 0x4d, 0x85, 0xc2, 0x92, 0x59, 0xfc, 0x12, + 0x87, 0x17, 0x38, 0xc9, 0x4b, 0x6c, 0x8d, 0x7d, 0xef, 0x08, 0x1b, 0xc9, 0x98, 0x15, 0x09, 0x3b, + 0xf0, 0xbd, 0x23, 0xe3, 0xe7, 0x39, 0xc8, 0x6d, 0x7b, 0x63, 0x3d, 0xc3, 0x22, 0x33, 0x93, 0x61, + 0x21, 0x4d, 0x00, 0x2b, 0x52, 0xf1, 0xa5, 0xd6, 0x86, 0xfe, 0x51, 0xa5, 0xe6, 0xdf, 0x83, 0xba, + 0x90, 0x13, 0xa1, 0x27, 0x6c, 0xa8, 0x73, 0xdb, 0xa7, 0x9c, 0xfe, 0x1c, 0x6d, 0x3e, 0x7b, 0x14, + 0xf6, 0xbc, 0x2d, 0x82, 0xb3, 0x25, 0xc8, 0x45, 0x0a, 0x2c, 0xa2, 0xc5, 0xa7, 0x30, 0xae, 0x31, + 0xbb, 0xed, 0x52, 0xc6, 0x7a, 0xe4, 0x17, 0x7b, 0x07, 0x16, 0x93, 0xf5, 0x92, 0x28, 0x92, 0x1a, + 0x89, 0x5e, 0x31, 0xca, 0xa4, 0xeb, 0x20, 0xe4, 0x08, 0xd1, 0xc8, 0xb0, 0xec, 0x31, 0xe7, 0x88, + 0xd2, 0x84, 0x5e, 0x29, 0x21, 0xf4, 0x6e, 0x43, 0x25, 0x1c, 0x9e, 0x59, 0x63, 0xfb, 0x72, 0xe8, + 0xd9, 0x03, 0xb9, 0xbf, 0x21, 0x1c, 0x9e, 0x1d, 0x10, 0x84, 0x3d, 0x04, 0x18, 0x8d, 0xc7, 0x72, + 0xef, 0xa1, 0xbb, 0x31, 0x66, 0xe5, 0xdd, 0x83, 0x03, 0x62, 0x39, 0xb3, 0x3c, 0x1a, 0x8f, 0xe9, + 0x4f, 0xb6, 0x09, 0xf5, 0xd4, 0xbb, 0x38, 0xb7, 0x54, 0x32, 0x96, 0x37, 0x7e, 0x90, 0xb2, 0x39, + 0x6b, 0x7d, 0x1d, 0xb6, 0xf6, 0x5b, 0xc0, 0x7e, 0xc9, 0x1b, 0x31, 0x3d, 0x28, 0x47, 0xfd, 0xd3, + 0x2f, 0x94, 0x60, 0x7a, 0x65, 0x25, 0x71, 0xa1, 0xa4, 0x35, 0x18, 0xf8, 0x42, 0x2e, 0xd2, 0x81, + 0x19, 0x89, 0x7c, 0xd0, 0x4e, 0xcc, 0x16, 0xc9, 0x7d, 0xe3, 0x2f, 0x33, 0x50, 0xa0, 0xdb, 0x2d, + 0x6f, 0xc0, 0x3c, 0xd1, 0x47, 0xd9, 0x2a, 0x32, 0x42, 0x44, 0xe7, 0x6e, 0x4f, 0x26, 0xaa, 0x88, + 0x6d, 0xa1, 0xdd, 0xcc, 0xcb, 0x46, 0x2b, 0xaf, 0xdd, 0xce, 0xbb, 0x0d, 0xe5, 0xa8, 0x69, 0x8d, + 0x75, 0x4a, 0xaa, 0x65, 0xf6, 0x0a, 0xe4, 0x4f, 0xbd, 0xb1, 0xb2, 0xc5, 0x21, 0x9e, 0x49, 0x13, + 0xe1, 0x71, 0x5f, 0x44, 0x1b, 0xd4, 0x79, 0x69, 0x43, 0x46, 0x8d, 0x20, 0x1b, 0xcc, 0x8e, 0x71, + 0x2e, 0x65, 0x8c, 0x87, 0x30, 0x2f, 0xe4, 0x80, 0x16, 0xa9, 0xbd, 0xfa, 0xd0, 0x7c, 0x53, 0x68, + 0x78, 0xfd, 0xe1, 0x64, 0xc0, 0x75, 0x4f, 0x08, 0xa6, 0x4e, 0x48, 0xb8, 0x32, 0x0f, 0x8c, 0x3f, + 0xcc, 0x90, 0x7c, 0x11, 0xf5, 0xb2, 0x7b, 0x90, 0x17, 0xe7, 0xdb, 0x94, 0xa7, 0x2e, 0xca, 0x73, + 0x15, 0x74, 0x26, 0x52, 0xe0, 0x75, 0xd6, 0xc9, 0x28, 0x59, 0x7b, 0xcd, 0xac, 0xb8, 0x93, 0x51, + 0xe4, 0x4c, 0xf8, 0x8e, 0x1a, 0xd6, 0x94, 0x21, 0x4e, 0xa3, 0x8f, 0xb6, 0xe9, 0x03, 0x2d, 0x07, + 0x23, 0x9f, 0x38, 0x31, 0x95, 0x16, 0x38, 0x38, 0xe1, 0x5a, 0xee, 0xc5, 0x1f, 0x67, 0xa1, 0x96, + 0xe8, 0x11, 0x26, 0xa1, 0x88, 0x03, 0x80, 0xbc, 0xc0, 0x72, 0xbd, 0x41, 0x80, 0xa4, 0xa2, 0xae, + 0xcd, 0x53, 0x36, 0x31, 0x4f, 0x51, 0x4c, 0x3a, 0xa7, 0xc7, 0xa4, 0x1f, 0x41, 0x39, 0xbe, 0x91, + 0x99, 0xec, 0x92, 0x68, 0x4f, 0x65, 0xfb, 0xc6, 0x44, 0x71, 0x14, 0xbb, 0xa0, 0x47, 0xb1, 0xbf, + 0xa7, 0x05, 0x3d, 0xe7, 0xb0, 0x1a, 0x23, 0x6d, 0x46, 0x7f, 0x3d, 0x49, 0x11, 0x9f, 0x40, 0x45, + 0xeb, 0xbc, 0x1e, 0xdc, 0xcc, 0x24, 0x82, 0x9b, 0x51, 0x5e, 0x7e, 0x36, 0xce, 0xcb, 0x37, 0x7e, + 0x2f, 0x0b, 0x35, 0xb1, 0xbf, 0x1c, 0xf7, 0xe4, 0xc0, 0x1b, 0x3a, 0x7d, 0xf4, 0x0a, 0x47, 0x3b, + 0x4c, 0x2a, 0x5a, 0x6a, 0x9f, 0xc9, 0x2d, 0x46, 0x7a, 0x96, 0x7e, 0xfd, 0x88, 0x84, 0x74, 0x74, + 0xfd, 0xc8, 0x80, 0x9a, 0x10, 0x8c, 0x47, 0x76, 0xc0, 0xb5, 0xfb, 0xa2, 0x66, 0xe5, 0x98, 0xf3, + 0x75, 0x3b, 0x20, 0x09, 0xf9, 0x0e, 0x2c, 0x0a, 0x1a, 0xbc, 0x79, 0x31, 0x72, 0x86, 0x43, 0x87, + 0x28, 0xc9, 0xd5, 0xd0, 0x38, 0xe6, 0xdc, 0xb4, 0x43, 0xbe, 0x2b, 0x10, 0xf2, 0x7a, 0x69, 0x69, + 0xe0, 0x04, 0xf6, 0x51, 0x9c, 0x2a, 0x14, 0x7d, 0x63, 0x2c, 0xc7, 0xbe, 0xd0, 0x62, 0x39, 0x74, + 0x05, 0xab, 0x32, 0xb2, 0x2f, 0xa2, 0x58, 0xce, 0x14, 0x27, 0x15, 0xa7, 0x39, 0xc9, 0xf8, 0x2f, + 0x59, 0xa8, 0x68, 0x6c, 0xf9, 0x32, 0xa7, 0xeb, 0xad, 0x19, 0x2f, 0x7e, 0x59, 0x77, 0xd8, 0xbf, + 0x96, 0x6c, 0x12, 0x43, 0xbe, 0x74, 0x91, 0x55, 0x63, 0xe0, 0x1b, 0x50, 0x16, 0xbb, 0xee, 0x5d, + 0x74, 0x8a, 0xc9, 0x6b, 0xd8, 0x08, 0x38, 0x98, 0x1c, 0x29, 0xe4, 0x63, 0x44, 0x16, 0x62, 0xe4, + 0x63, 0x81, 0x7c, 0x5e, 0x7e, 0xe0, 0x87, 0x50, 0x95, 0xb5, 0xe2, 0x9a, 0xe2, 0x70, 0xe3, 0x5d, + 0x9f, 0x58, 0x6f, 0xb3, 0x42, 0xcd, 0xd1, 0xe2, 0xcb, 0x82, 0x8f, 0x55, 0xc1, 0xd2, 0x8b, 0x0a, + 0x3e, 0xa6, 0x0f, 0x63, 0x2b, 0x4a, 0xb9, 0xc4, 0x74, 0x03, 0x25, 0xc7, 0x1e, 0xc2, 0xa2, 0x12, + 0x57, 0x13, 0xd7, 0x76, 0x5d, 0x6f, 0xe2, 0xf6, 0xb9, 0x4a, 0xd8, 0x67, 0x12, 0x75, 0x18, 0x63, + 0x8c, 0x41, 0x74, 0xa3, 0x8b, 0xd2, 0x16, 0xee, 0x43, 0x81, 0xf4, 0x72, 0x52, 0x3e, 0xd2, 0x05, + 0x17, 0x91, 0xb0, 0x7b, 0x50, 0x20, 0xf5, 0x3c, 0x7b, 0xa5, 0xb0, 0x21, 0x02, 0xe3, 0x01, 0xcc, + 0xa3, 0x8a, 0xa9, 0x49, 0xdc, 0xe7, 0x69, 0x25, 0xc6, 0x12, 0xb0, 0x3d, 0xda, 0x44, 0x7a, 0x3a, + 0xcd, 0x7f, 0xcf, 0x41, 0x45, 0x03, 0x0b, 0xb1, 0x88, 0x09, 0x18, 0xd6, 0xc0, 0xb1, 0x47, 0x5c, + 0xc5, 0x1e, 0x6a, 0x66, 0x0d, 0xa1, 0x9b, 0x12, 0x28, 0x0e, 0x05, 0xfb, 0xec, 0xc4, 0xf2, 0x26, + 0xa1, 0x35, 0xe0, 0x27, 0x3e, 0xe7, 0x52, 0x59, 0xaa, 0xda, 0x67, 0x27, 0xfb, 0x93, 0x70, 0x13, + 0x61, 0x82, 0x4a, 0x30, 0xb5, 0x46, 0x25, 0x73, 0x06, 0x46, 0xf6, 0x45, 0x4c, 0x25, 0x13, 0x57, + 0x68, 0x8a, 0xf2, 0x51, 0xe2, 0x0a, 0x99, 0x2d, 0xd3, 0x92, 0xbc, 0x30, 0x2b, 0xc9, 0xdf, 0x83, + 0x15, 0x92, 0xe4, 0x52, 0x46, 0x58, 0x53, 0x2c, 0xb5, 0x84, 0x58, 0x39, 0x48, 0x4d, 0xff, 0x6a, + 0x88, 0x11, 0xa8, 0xfd, 0x11, 0x38, 0x3f, 0xa6, 0x1d, 0x95, 0x31, 0xc5, 0xc8, 0x64, 0xe5, 0x5d, + 0xe7, 0xc7, 0x5c, 0x50, 0x62, 0x60, 0x54, 0xa7, 0x94, 0x69, 0xa8, 0x23, 0xc7, 0x9d, 0xa6, 0xb4, + 0x2f, 0x92, 0x94, 0x65, 0x49, 0x69, 0x5f, 0xe8, 0x94, 0xef, 0xc3, 0xea, 0x88, 0x0f, 0x1c, 0x3b, + 0x59, 0xad, 0x15, 0x6b, 0x10, 0x4b, 0x84, 0xd6, 0xca, 0x74, 0xc9, 0x82, 0x14, 0xb3, 0xf1, 0x63, + 0x6f, 0x74, 0xe4, 0xd0, 0xe1, 0x49, 0xa1, 0xda, 0xbc, 0x59, 0x77, 0x27, 0xa3, 0x1f, 0x20, 0x58, + 0x14, 0x09, 0x8c, 0x1a, 0x54, 0xba, 0xa1, 0x37, 0x56, 0xcb, 0x5c, 0x87, 0x2a, 0x7d, 0xca, 0xeb, + 0x18, 0x37, 0xe0, 0x3a, 0xf2, 0x66, 0xcf, 0x1b, 0x7b, 0x43, 0xef, 0xe4, 0x32, 0xe1, 0x50, 0xfa, + 0x6f, 0x19, 0x58, 0x4c, 0x60, 0xe5, 0x3e, 0x7f, 0x8f, 0x36, 0x56, 0x94, 0x53, 0x4f, 0xec, 0xbc, + 0xa0, 0x1d, 0x3e, 0x44, 0x48, 0xbb, 0x4a, 0xe5, 0xd9, 0xb7, 0xe2, 0xbb, 0xa0, 0xaa, 0x20, 0xf1, + 0x76, 0x73, 0x96, 0xb7, 0x65, 0x79, 0x75, 0x4b, 0x54, 0x55, 0xf1, 0xff, 0xcb, 0x54, 0xe1, 0x81, + 0x1c, 0x72, 0x2e, 0x99, 0x0c, 0xa9, 0x3b, 0x9f, 0x54, 0x0f, 0x62, 0x8f, 0x54, 0x60, 0xfc, 0xab, + 0x0c, 0x40, 0xdc, 0x3b, 0x4c, 0xc7, 0x8c, 0x0e, 0x50, 0x7a, 0x66, 0x45, 0x3b, 0x2c, 0x5f, 0x85, + 0x6a, 0x94, 0x31, 0x16, 0x1f, 0xc9, 0x15, 0x05, 0x13, 0xe7, 0xf2, 0x5d, 0x98, 0x3f, 0x19, 0x7a, + 0x47, 0xa8, 0x3a, 0xc9, 0x03, 0x94, 0x2e, 0xa5, 0xd4, 0x09, 0xac, 0x8e, 0xc5, 0xf8, 0x00, 0xcf, + 0xa7, 0x26, 0x95, 0xe9, 0xc7, 0xb1, 0xf1, 0xfb, 0xd9, 0x28, 0x75, 0x26, 0x9e, 0x89, 0xe7, 0xdb, + 0x19, 0xdf, 0x26, 0x02, 0xfb, 0xbc, 0xc8, 0xc3, 0x27, 0x50, 0xf7, 0x49, 0x3a, 0x2a, 0xd1, 0x99, + 0x7f, 0x8e, 0xe8, 0xac, 0xf9, 0x89, 0x23, 0xf7, 0x4d, 0x68, 0xd8, 0x83, 0x33, 0xee, 0x87, 0x0e, + 0x3a, 0x6b, 0x51, 0x51, 0x93, 0xc9, 0x2a, 0x1a, 0x1c, 0x35, 0xa2, 0xbb, 0x30, 0x2f, 0xaf, 0x08, + 0x45, 0x94, 0xf2, 0xd1, 0x81, 0x18, 0x2c, 0x08, 0x8d, 0x7f, 0xab, 0x72, 0x75, 0x92, 0xab, 0xfb, + 0xfc, 0x59, 0xd1, 0x47, 0x98, 0x9d, 0x8d, 0xad, 0x48, 0x46, 0x92, 0x3e, 0x60, 0x29, 0x8f, 0x08, + 0x28, 0x3d, 0xc0, 0xc9, 0x69, 0xcd, 0xbf, 0xcc, 0xb4, 0x1a, 0x7f, 0x9a, 0x81, 0xe2, 0xb6, 0x37, + 0x16, 0x76, 0xb9, 0xd0, 0xe7, 0x70, 0x9b, 0x44, 0xd7, 0xf3, 0xe6, 0xc4, 0x67, 0x67, 0xf0, 0xfc, + 0xb4, 0xfc, 0x54, 0x7d, 0xa3, 0x96, 0xd4, 0x37, 0xbe, 0x07, 0x37, 0x30, 0x1a, 0xe1, 0x7b, 0x63, + 0xcf, 0x17, 0x5b, 0xd5, 0x1e, 0x92, 0xde, 0xe1, 0xb9, 0xe1, 0xa9, 0x92, 0x9d, 0xd7, 0x8f, 0x39, + 0x3f, 0xd0, 0x28, 0x76, 0x23, 0x02, 0xbc, 0x6b, 0x32, 0x0c, 0xcf, 0x2c, 0x32, 0x15, 0xa5, 0x62, + 0x44, 0x12, 0x75, 0x5e, 0x20, 0xda, 0x08, 0x47, 0xd5, 0xc8, 0xf8, 0x08, 0xca, 0x91, 0xd7, 0x81, + 0xbd, 0x05, 0xe5, 0x53, 0x6f, 0x2c, 0x5d, 0x13, 0x99, 0xc4, 0xd5, 0x05, 0x39, 0x6a, 0xb3, 0x74, + 0x4a, 0x7f, 0x04, 0xc6, 0xcf, 0x8b, 0x50, 0xec, 0xb8, 0x67, 0x9e, 0xd3, 0xc7, 0x6c, 0x9f, 0x11, + 0x1f, 0x79, 0xea, 0x9e, 0xa2, 0xf8, 0x1b, 0x23, 0xfa, 0xf1, 0xd3, 0x01, 0x39, 0x19, 0xd1, 0x8f, + 0x1e, 0x0d, 0x58, 0x86, 0x39, 0x5f, 0xbf, 0xfb, 0x5f, 0xf0, 0x31, 0xff, 0x30, 0x32, 0xda, 0x0a, + 0xda, 0x3d, 0x4f, 0x51, 0x17, 0xdd, 0x49, 0xc7, 0x29, 0xa3, 0xbb, 0x27, 0x65, 0x84, 0xe0, 0x84, + 0xdd, 0x84, 0xa2, 0xbc, 0x29, 0x40, 0x79, 0xd7, 0x94, 0x30, 0x28, 0x41, 0xc8, 0x0d, 0x3e, 0xa7, + 0x68, 0x52, 0xa4, 0x51, 0x09, 0x3b, 0x5d, 0x02, 0x37, 0x05, 0xaf, 0xdd, 0x86, 0x0a, 0xd1, 0x13, + 0x49, 0x49, 0xe6, 0xe7, 0x20, 0x08, 0x09, 0x52, 0x9e, 0xd0, 0x28, 0xa7, 0x3e, 0xa1, 0x81, 0xe9, + 0x5c, 0x91, 0x94, 0xa5, 0x21, 0x02, 0x3d, 0x9c, 0xa0, 0xc1, 0xd5, 0xfb, 0x31, 0xd2, 0xb8, 0xa7, + 0x6b, 0x54, 0xca, 0xb8, 0x7f, 0x0d, 0x6a, 0xc7, 0xf6, 0x70, 0x78, 0x64, 0xf7, 0x9f, 0x91, 0x4d, + 0x5a, 0x25, 0x37, 0x9c, 0x02, 0xa2, 0x51, 0x7a, 0x1b, 0x2a, 0xda, 0x2a, 0x63, 0xf2, 0x4d, 0xde, + 0x84, 0x78, 0x7d, 0xa7, 0x5d, 0x4d, 0xf5, 0x97, 0x70, 0x35, 0x69, 0x49, 0x48, 0xf3, 0xc9, 0x24, + 0xa4, 0x1b, 0x28, 0x4d, 0x65, 0xa2, 0x4a, 0x83, 0x6e, 0xe9, 0xdb, 0x83, 0x01, 0x26, 0xaa, 0xd0, + 0x93, 0x58, 0x38, 0x79, 0x84, 0x5f, 0x20, 0xa5, 0x96, 0x60, 0x44, 0x72, 0x8b, 0xfc, 0xa5, 0x63, + 0xdb, 0x19, 0x60, 0xd2, 0x27, 0x99, 0xb1, 0x45, 0x7b, 0x14, 0x1e, 0xd8, 0xce, 0x80, 0xdd, 0x81, + 0xaa, 0x42, 0xe3, 0xe9, 0xb8, 0x48, 0xf3, 0x2f, 0xd1, 0xe2, 0x4c, 0x34, 0xa0, 0x16, 0x51, 0x8c, + 0xe2, 0xbb, 0x50, 0x15, 0x49, 0x82, 0x7c, 0xf0, 0x2e, 0x06, 0xff, 0x43, 0x8e, 0x37, 0x9e, 0xea, + 0x8f, 0x6f, 0xc8, 0xb1, 0x4a, 0x2e, 0x55, 0xff, 0x63, 0xa6, 0x83, 0x49, 0x94, 0x42, 0x11, 0xa3, + 0x10, 0xcd, 0x4a, 0x42, 0x11, 0x93, 0xa4, 0x18, 0xa2, 0x21, 0x02, 0xf6, 0x91, 0x66, 0x48, 0x35, + 0x91, 0xf8, 0xe6, 0x54, 0xfd, 0x57, 0x98, 0x50, 0x82, 0x7b, 0x9d, 0x40, 0x9c, 0x32, 0x01, 0x77, + 0x07, 0x78, 0x01, 0xaa, 0x64, 0x96, 0x9d, 0xe0, 0x29, 0x01, 0x7e, 0xb5, 0x16, 0x56, 0x0b, 0xaa, + 0xfa, 0x30, 0x59, 0x09, 0xf2, 0xfb, 0x07, 0xed, 0xbd, 0xc6, 0x35, 0x56, 0x81, 0x62, 0xb7, 0xdd, + 0xeb, 0xed, 0xb4, 0x37, 0x1b, 0x19, 0x56, 0x85, 0x52, 0x74, 0x8d, 0x23, 0x2b, 0xbe, 0x5a, 0x1b, + 0x1b, 0xed, 0x83, 0x5e, 0x7b, 0xb3, 0x91, 0xfb, 0x7e, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0xbf, 0xc8, + 0x41, 0x45, 0x9b, 0x85, 0xe7, 0x0b, 0xe3, 0x5b, 0x00, 0x68, 0xd2, 0xc4, 0x79, 0x4c, 0x79, 0xb3, + 0x2c, 0x20, 0xb4, 0xf8, 0xba, 0xb3, 0x3c, 0x47, 0xcf, 0x3f, 0x28, 0x67, 0xf9, 0x6b, 0x50, 0xa3, + 0x97, 0x14, 0xf4, 0x70, 0x5d, 0xc1, 0xac, 0x12, 0x50, 0x8a, 0x6a, 0xbc, 0x07, 0x86, 0x44, 0x78, + 0x43, 0x40, 0xde, 0xab, 0x26, 0x10, 0xde, 0x11, 0xc0, 0x0b, 0x1e, 0x81, 0x37, 0x3c, 0xe3, 0x44, + 0x41, 0x1a, 0x61, 0x45, 0xc2, 0x7a, 0xf2, 0x22, 0x9a, 0x94, 0x87, 0xda, 0x45, 0xa4, 0x82, 0x59, + 0x25, 0xa0, 0x6c, 0xe8, 0x1d, 0xc5, 0x40, 0x25, 0x64, 0xa0, 0xd5, 0x59, 0x6e, 0x48, 0x30, 0xcf, + 0xce, 0x8c, 0x3f, 0xab, 0x8c, 0x8c, 0xf1, 0x9d, 0xd9, 0x72, 0x2f, 0xf6, 0x6b, 0xb1, 0xb7, 0x80, + 0x8d, 0xc6, 0x63, 0x2b, 0xc5, 0xd3, 0x94, 0x37, 0xe7, 0x47, 0xe3, 0x71, 0x4f, 0x73, 0xc4, 0xfc, + 0x0a, 0x9c, 0x60, 0x5f, 0x02, 0x6b, 0x89, 0x0d, 0x8c, 0x5d, 0x8c, 0x5c, 0xa8, 0xb1, 0x58, 0xce, + 0xe8, 0x62, 0x39, 0x45, 0xfa, 0x65, 0x53, 0xa5, 0xdf, 0xf3, 0xe4, 0x84, 0xb1, 0x05, 0x95, 0x03, + 0xed, 0x9d, 0x96, 0x3b, 0xe2, 0x84, 0x50, 0x2f, 0xb4, 0xd0, 0xd9, 0x41, 0xce, 0x2d, 0x5f, 0x3e, + 0xcc, 0xa2, 0xf5, 0x26, 0xab, 0xf5, 0xc6, 0xf8, 0x97, 0x19, 0xba, 0x03, 0x1f, 0x75, 0x3e, 0x7e, + 0x1a, 0x46, 0xc5, 0x81, 0xe2, 0xfb, 0x82, 0x15, 0x15, 0xff, 0x91, 0x57, 0xfd, 0xb0, 0x6b, 0x96, + 0x77, 0x7c, 0x1c, 0x70, 0x75, 0xf3, 0xa5, 0x82, 0xb0, 0x7d, 0x04, 0x29, 0xe5, 0x5b, 0x68, 0xf8, + 0x0e, 0xd5, 0x1f, 0xc8, 0x1b, 0x30, 0x42, 0xf9, 0xde, 0xb5, 0x2f, 0x64, 0xab, 0x81, 0x50, 0x41, + 0xa4, 0xa3, 0x5a, 0xdd, 0xf7, 0x89, 0xbe, 0x8d, 0x7f, 0x26, 0xaf, 0x34, 0x4e, 0xcf, 0xef, 0x7d, + 0x28, 0x45, 0xb5, 0x26, 0x4f, 0x58, 0x45, 0x19, 0xe1, 0xc5, 0x39, 0x8e, 0x56, 0x79, 0xa2, 0xc7, + 0xb4, 0xb9, 0x30, 0xd8, 0xd0, 0xd1, 0x7a, 0xfd, 0x36, 0xb0, 0x63, 0xc7, 0x9f, 0x26, 0xa6, 0xcd, + 0xd6, 0x40, 0x8c, 0x46, 0x6d, 0x1c, 0xc2, 0xa2, 0x92, 0x12, 0x9a, 0x45, 0x90, 0x5c, 0xbc, 0xcc, + 0x0b, 0x84, 0x7c, 0x76, 0x46, 0xc8, 0x1b, 0x3f, 0xcb, 0x43, 0x51, 0xbd, 0x79, 0x94, 0xf6, 0x4e, + 0x4f, 0x39, 0xf9, 0x4e, 0x4f, 0x33, 0xf1, 0xa6, 0x03, 0x2e, 0xbd, 0x3c, 0xef, 0xef, 0x4e, 0x1f, + 0xd9, 0x9a, 0xd3, 0x3c, 0x71, 0x6c, 0xaf, 0x40, 0x7e, 0x6c, 0x87, 0xa7, 0xe8, 0x20, 0x23, 0xe6, + 0xc1, 0x6f, 0xe5, 0x4c, 0x2f, 0x24, 0x9d, 0xe9, 0x69, 0x6f, 0x1a, 0x91, 0x4a, 0x3a, 0xf3, 0xa6, + 0xd1, 0x0d, 0x20, 0xfd, 0x42, 0xcb, 0x87, 0x29, 0x21, 0x40, 0x9c, 0x45, 0x49, 0x75, 0xa4, 0x34, + 0xad, 0x8e, 0xbc, 0xb4, 0xaa, 0xf0, 0x1e, 0xcc, 0xd1, 0x7d, 0x60, 0x79, 0xaf, 0x49, 0x1d, 0x28, + 0x72, 0x0e, 0xd5, 0xff, 0x94, 0x04, 0x6b, 0x4a, 0x5a, 0xfd, 0x81, 0x90, 0x4a, 0xe2, 0x81, 0x10, + 0xdd, 0xc9, 0x5f, 0x4d, 0x3a, 0xf9, 0xef, 0x41, 0x23, 0x9a, 0x50, 0x74, 0x99, 0xb9, 0x81, 0xbc, + 0xd1, 0x51, 0x57, 0x70, 0x21, 0x25, 0xf7, 0x82, 0xf8, 0x40, 0xac, 0x27, 0x0e, 0x44, 0x21, 0xc3, + 0x5a, 0x61, 0xc8, 0x47, 0xe3, 0x50, 0x1e, 0x88, 0x98, 0xf3, 0xad, 0x77, 0x30, 0x79, 0xe3, 0xaf, + 0x06, 0xe5, 0xce, 0x9e, 0xb5, 0xb5, 0xd3, 0x79, 0xb2, 0xdd, 0x6b, 0x64, 0xc4, 0x67, 0xf7, 0x70, + 0x63, 0xa3, 0xdd, 0xde, 0xc4, 0x13, 0x07, 0x60, 0x6e, 0xab, 0xd5, 0x11, 0xa7, 0x4f, 0xce, 0xf8, + 0x69, 0x16, 0x2a, 0x5a, 0xf5, 0xec, 0xfd, 0x68, 0x56, 0xe8, 0x0d, 0x89, 0x5b, 0xb3, 0x5d, 0x78, + 0xa0, 0x44, 0xb1, 0x36, 0x2d, 0xd1, 0x0b, 0x4e, 0xd9, 0x2b, 0x5f, 0x70, 0x62, 0x6f, 0xc0, 0xbc, + 0x4d, 0x35, 0x44, 0xb3, 0x20, 0xdd, 0xc1, 0x12, 0x2c, 0x27, 0x01, 0xb3, 0xc0, 0xe2, 0xf3, 0x44, + 0xd0, 0xe5, 0x55, 0xe2, 0x55, 0x74, 0xa4, 0xe0, 0x64, 0x15, 0x8f, 0x6d, 0x67, 0x38, 0xf1, 0xb9, + 0x0c, 0xdf, 0x46, 0x27, 0x33, 0x41, 0x4d, 0x85, 0x36, 0x3e, 0x00, 0x88, 0xfb, 0x9c, 0x9c, 0x9c, + 0x6b, 0xc9, 0xc9, 0xc9, 0x68, 0x93, 0x93, 0x35, 0x36, 0x49, 0x8c, 0xc8, 0x89, 0x8e, 0x22, 0xd5, + 0xef, 0x80, 0xf2, 0x48, 0x59, 0x98, 0x87, 0x39, 0x1e, 0xf2, 0x50, 0xdd, 0x8d, 0x5c, 0x90, 0x98, + 0x4e, 0x84, 0x50, 0x57, 0x95, 0xe3, 0x5a, 0x62, 0x69, 0x24, 0x59, 0x72, 0x5a, 0x1a, 0x49, 0x52, + 0x33, 0xc2, 0x1b, 0x6b, 0xd0, 0xdc, 0xe4, 0xa2, 0xb6, 0xd6, 0x70, 0x38, 0xd5, 0x1d, 0xe3, 0x06, + 0x5c, 0x4f, 0xc1, 0x49, 0x27, 0xc4, 0xa7, 0xb0, 0xdc, 0xa2, 0x6b, 0x90, 0xbf, 0xaa, 0xbb, 0x18, + 0x46, 0x13, 0x56, 0xa6, 0xab, 0x94, 0x8d, 0x6d, 0xc1, 0xc2, 0x26, 0x3f, 0x9a, 0x9c, 0xec, 0xf0, + 0xb3, 0xb8, 0x21, 0x06, 0xf9, 0xe0, 0xd4, 0x3b, 0x97, 0xf3, 0x83, 0x7f, 0x8b, 0x3d, 0x3c, 0x14, + 0x34, 0x56, 0x30, 0xe6, 0x7d, 0xe5, 0x11, 0x45, 0x48, 0x77, 0xcc, 0xfb, 0xc6, 0xfb, 0xc0, 0xf4, + 0x7a, 0xe4, 0x7c, 0x09, 0x2b, 0x61, 0x72, 0x64, 0x05, 0x97, 0x41, 0xc8, 0x47, 0xea, 0x89, 0x12, + 0x08, 0x26, 0x47, 0x5d, 0x82, 0x18, 0x77, 0xa1, 0x7a, 0x60, 0x5f, 0x9a, 0xfc, 0x4b, 0x79, 0xcb, + 0x60, 0x15, 0x8a, 0x63, 0xfb, 0x52, 0x88, 0x81, 0x28, 0x38, 0x82, 0x68, 0xe3, 0x8f, 0xf2, 0x30, + 0x47, 0x94, 0xec, 0x0e, 0xbd, 0x22, 0xe8, 0xb8, 0xb8, 0x0d, 0x95, 0xa0, 0xd4, 0x40, 0x33, 0xb2, + 0x34, 0x3b, 0x2b, 0x4b, 0xa5, 0x03, 0x4d, 0xbd, 0x9e, 0xa0, 0xdc, 0xd8, 0xee, 0x64, 0xa4, 0x9e, + 0x4c, 0x60, 0x37, 0xa1, 0x1c, 0x5f, 0xe7, 0xca, 0xc7, 0xaf, 0x44, 0xd2, 0x25, 0xae, 0x64, 0xa0, + 0x31, 0xb6, 0x45, 0xa8, 0x77, 0xea, 0x88, 0x90, 0xe2, 0x52, 0x07, 0xa5, 0x1a, 0x3c, 0x45, 0x75, + 0x7f, 0x25, 0x69, 0xf0, 0xcc, 0x18, 0x36, 0xa5, 0x17, 0x1b, 0x36, 0xe4, 0x59, 0x7b, 0x8e, 0x61, + 0x03, 0x2f, 0x61, 0xd8, 0xbc, 0x44, 0x90, 0xef, 0x3a, 0x94, 0xf0, 0xdc, 0xd7, 0xa4, 0xa7, 0x38, + 0xef, 0x85, 0xf4, 0xfc, 0x50, 0x53, 0xfd, 0x29, 0xc3, 0xe0, 0x46, 0xbc, 0x4d, 0x4c, 0xfe, 0xe5, + 0xaf, 0x27, 0x78, 0xf2, 0x05, 0x14, 0x25, 0x54, 0x30, 0xb4, 0x6b, 0x8f, 0xd4, 0x03, 0x34, 0xf8, + 0xb7, 0x98, 0x36, 0x7c, 0x35, 0xe3, 0xcb, 0x89, 0xe3, 0xf3, 0x81, 0x7a, 0xe6, 0xc0, 0xc1, 0x3d, + 0x2a, 0x20, 0x62, 0x80, 0xc2, 0x0c, 0x71, 0xbd, 0x73, 0x57, 0x5e, 0x72, 0x2e, 0x3a, 0xc1, 0x53, + 0xf1, 0x69, 0x30, 0x68, 0xe0, 0x13, 0x54, 0x63, 0xcf, 0x57, 0x87, 0x93, 0xf1, 0xb3, 0x0c, 0x34, + 0xe4, 0xee, 0x8a, 0x70, 0xba, 0x15, 0x50, 0xb8, 0x2a, 0x20, 0xfe, 0xfc, 0x47, 0x0b, 0x0c, 0xa8, + 0xa1, 0xf3, 0x23, 0x3a, 0xa9, 0xc8, 0x79, 0x53, 0x11, 0xc0, 0x2d, 0x79, 0x5a, 0xbd, 0x02, 0x15, + 0x95, 0x8e, 0x39, 0x72, 0x86, 0xea, 0x41, 0x58, 0xca, 0xc7, 0xdc, 0x75, 0x86, 0xea, 0xa0, 0xf3, + 0x6d, 0x79, 0x9f, 0x2a, 0x83, 0x07, 0x9d, 0x69, 0x87, 0xdc, 0xf8, 0x4f, 0x19, 0x58, 0xd0, 0x86, + 0x22, 0xf7, 0xed, 0xc7, 0x50, 0x8d, 0xde, 0x7e, 0xe3, 0x91, 0xe6, 0xb5, 0x9a, 0x14, 0x34, 0x71, + 0xb1, 0x4a, 0x3f, 0x82, 0x04, 0xa2, 0x33, 0x03, 0xfb, 0x12, 0xfb, 0x1b, 0x4c, 0x46, 0xca, 0xb8, + 0x19, 0xd8, 0x97, 0x5b, 0x9c, 0x77, 0x27, 0x23, 0x61, 0xba, 0x9e, 0x73, 0xfe, 0x2c, 0x22, 0x20, + 0x9d, 0x0b, 0x04, 0x4c, 0x52, 0x18, 0x50, 0x1b, 0x79, 0x6e, 0x78, 0x1a, 0x91, 0x48, 0xad, 0x13, + 0x81, 0x44, 0x63, 0xfc, 0x79, 0x16, 0x16, 0xc9, 0xc5, 0x26, 0x5d, 0x9b, 0x52, 0x74, 0x35, 0x61, + 0x8e, 0xbc, 0x8d, 0x24, 0xbc, 0xb6, 0xaf, 0x99, 0xf2, 0x9b, 0xbd, 0xf7, 0x92, 0x6e, 0x41, 0x75, + 0x65, 0xeb, 0x8a, 0xe9, 0xcf, 0xcd, 0x4e, 0xff, 0xd5, 0xd3, 0x9b, 0x16, 0x71, 0x2b, 0xa4, 0x45, + 0xdc, 0x5e, 0x26, 0xce, 0x35, 0x73, 0xaf, 0xa9, 0x28, 0x69, 0xb4, 0x7b, 0x4d, 0xef, 0xc3, 0x6a, + 0x82, 0x06, 0xa5, 0xb5, 0x73, 0xec, 0x70, 0x75, 0x87, 0x7c, 0x49, 0xa3, 0xee, 0x2a, 0xdc, 0x7a, + 0x11, 0x0a, 0x41, 0xdf, 0x1b, 0x73, 0x63, 0x05, 0x96, 0x92, 0xb3, 0x2a, 0x8f, 0x89, 0x3f, 0xc8, + 0x40, 0x53, 0xe6, 0x47, 0x38, 0xee, 0xc9, 0xb6, 0x13, 0x84, 0x9e, 0x1f, 0xbd, 0x91, 0x76, 0x0b, + 0x20, 0x08, 0x6d, 0x5f, 0x5a, 0x9b, 0xa4, 0x07, 0x97, 0x11, 0x82, 0x96, 0xe4, 0x75, 0x28, 0x71, + 0x77, 0x40, 0x48, 0xe2, 0x86, 0x22, 0x77, 0x07, 0xca, 0x0e, 0x9d, 0xd1, 0xbf, 0x6b, 0x49, 0xf3, + 0x42, 0x5e, 0xb0, 0x14, 0xb3, 0xc3, 0xcf, 0xf0, 0xe0, 0xcd, 0x47, 0x17, 0x2c, 0x77, 0xed, 0x0b, + 0xcc, 0x36, 0x0c, 0x8c, 0x7f, 0x9c, 0x85, 0xf9, 0xb8, 0x7f, 0x74, 0x3b, 0x3b, 0x21, 0xbf, 0x65, + 0xaf, 0x62, 0xf9, 0x7d, 0x47, 0xb2, 0x83, 0x23, 0xf4, 0x77, 0xcd, 0xf1, 0x58, 0xa2, 0xcd, 0xd9, + 0x71, 0x99, 0x01, 0x15, 0x45, 0xe1, 0x4d, 0x42, 0xed, 0xa9, 0xa2, 0x32, 0x91, 0xec, 0x4f, 0x42, + 0x61, 0x70, 0x09, 0xcb, 0xd3, 0x71, 0xa5, 0xc9, 0x53, 0xb0, 0x47, 0x61, 0x07, 0x5f, 0x40, 0x16, + 0x60, 0x51, 0x8c, 0x16, 0x52, 0x50, 0x09, 0xfa, 0x06, 0xe9, 0xd9, 0xb4, 0x72, 0xa8, 0x63, 0xeb, + 0x4a, 0x28, 0x3d, 0x06, 0x19, 0x29, 0xa1, 0xaf, 0x40, 0x85, 0x2a, 0x8f, 0xaf, 0xb1, 0xe5, 0xcd, + 0x32, 0xb6, 0x80, 0x78, 0xe9, 0x04, 0xf2, 0x26, 0x09, 0xd3, 0x17, 0xa8, 0x29, 0x4c, 0x3f, 0xf8, + 0x07, 0x19, 0xb8, 0x9e, 0xb2, 0x6c, 0x72, 0x97, 0x6f, 0xc0, 0xc2, 0x71, 0x84, 0x54, 0xb3, 0x4b, + 0x5b, 0x7d, 0x45, 0x89, 0xd5, 0xe4, 0x9c, 0x9a, 0x8d, 0xe3, 0x24, 0x20, 0x36, 0xba, 0x68, 0x05, + 0x13, 0x37, 0x15, 0xd1, 0xe8, 0xa2, 0x65, 0x24, 0x7b, 0xe7, 0x00, 0xd6, 0xda, 0x17, 0x42, 0x62, + 0x6c, 0xe8, 0x4f, 0x78, 0x2b, 0x36, 0x4a, 0x3a, 0x98, 0x33, 0x2f, 0xe5, 0x60, 0x1e, 0xd0, 0x85, + 0xac, 0xa8, 0xae, 0x6f, 0x53, 0x09, 0x1e, 0xa0, 0xa2, 0x0c, 0x3d, 0x41, 0xae, 0x6e, 0x4b, 0xf6, + 0xa3, 0xa7, 0xc7, 0x8d, 0x00, 0xe6, 0x77, 0x27, 0xc3, 0xd0, 0x89, 0x5f, 0x23, 0x67, 0xef, 0xc9, + 0x32, 0xd8, 0x8e, 0x9a, 0xb5, 0xd4, 0x86, 0x20, 0x6a, 0x08, 0x27, 0x6b, 0x24, 0x2a, 0xb2, 0x66, + 0xdb, 0x9b, 0x1f, 0x25, 0x5b, 0x30, 0xae, 0xc3, 0x6a, 0xfc, 0x45, 0xd3, 0xa6, 0x8e, 0x9a, 0x7f, + 0x91, 0xa1, 0xd4, 0xe6, 0xe4, 0xcb, 0xe8, 0xac, 0x0d, 0x8b, 0x81, 0xe3, 0x9e, 0x0c, 0xb9, 0x5e, + 0x7d, 0x20, 0x27, 0x61, 0x39, 0xd9, 0x37, 0xf9, 0x7a, 0xba, 0xb9, 0x40, 0x25, 0xe2, 0xda, 0x02, + 0xb6, 0x7e, 0x55, 0x27, 0x63, 0xb6, 0x98, 0x9a, 0x8d, 0xd9, 0xce, 0x77, 0xa0, 0x9e, 0x6c, 0x88, + 0x7d, 0x28, 0x2f, 0x23, 0xc6, 0xbd, 0xca, 0x4d, 0xdd, 0x2b, 0x8b, 0x19, 0xa2, 0x12, 0xcf, 0x7d, + 0x60, 0xfc, 0xc3, 0x0c, 0x34, 0x4d, 0x2e, 0x38, 0x57, 0xeb, 0xa5, 0xe2, 0x99, 0x8f, 0x67, 0x6a, + 0xbd, 0x7a, 0xac, 0xea, 0x8e, 0xa3, 0xea, 0xd1, 0xdb, 0x57, 0x2e, 0xc6, 0xf6, 0xb5, 0x99, 0x11, + 0xad, 0x97, 0x60, 0x8e, 0x48, 0x8c, 0x55, 0x58, 0x96, 0xfd, 0x51, 0x7d, 0x89, 0xa3, 0x87, 0x89, + 0x16, 0x13, 0xd1, 0xc3, 0x35, 0x68, 0xd2, 0x53, 0x77, 0xfa, 0x20, 0x64, 0xc1, 0x4d, 0x60, 0xbb, + 0x76, 0xdf, 0xf6, 0x3d, 0xcf, 0x3d, 0xe0, 0xbe, 0x4c, 0x14, 0x45, 0x0d, 0x13, 0x83, 0x6b, 0x4a, + 0x15, 0xa6, 0x2f, 0xf5, 0x40, 0x9b, 0xe7, 0xaa, 0xbc, 0x18, 0xfa, 0x32, 0x4c, 0x58, 0x5c, 0xb7, + 0x9f, 0x71, 0x55, 0x93, 0x9a, 0xa2, 0x4f, 0xa0, 0x32, 0x8e, 0x2a, 0x55, 0xf3, 0xae, 0x6e, 0x2c, + 0xcf, 0x36, 0x6b, 0xea, 0xd4, 0xc6, 0x63, 0x58, 0x4a, 0xd6, 0x29, 0x45, 0xc7, 0x1a, 0x94, 0x46, + 0x12, 0x26, 0x7b, 0x17, 0x7d, 0x1b, 0x3f, 0x29, 0x41, 0x51, 0xda, 0x73, 0xec, 0x01, 0xe4, 0xfb, + 0x2a, 0x37, 0x29, 0x7e, 0x08, 0x43, 0x62, 0xd5, 0xff, 0x1b, 0x98, 0xa1, 0x24, 0xe8, 0xd8, 0x27, + 0x50, 0x4f, 0x46, 0x45, 0xa7, 0xae, 0x43, 0x26, 0xc3, 0x99, 0xb5, 0xfe, 0x54, 0xfc, 0xab, 0x1c, + 0x1f, 0x8e, 0xa4, 0x33, 0x94, 0x4e, 0xb5, 0xd3, 0xd3, 0x73, 0x85, 0xbe, 0x1d, 0x9c, 0xda, 0xd6, + 0xe3, 0xf7, 0x3f, 0x90, 0xf7, 0x21, 0x2b, 0x08, 0xec, 0x9e, 0xda, 0x8f, 0xdf, 0xff, 0x60, 0x5a, + 0x93, 0xa6, 0x2b, 0x71, 0xba, 0x26, 0xbd, 0x04, 0x05, 0x7a, 0x89, 0x8c, 0x92, 0x4c, 0xe8, 0x83, + 0x3d, 0x82, 0x25, 0x69, 0xb6, 0x5a, 0x32, 0x1d, 0x98, 0xa4, 0x60, 0x89, 0xee, 0xe0, 0x48, 0x5c, + 0x17, 0x51, 0xe4, 0x1b, 0x5a, 0x81, 0xb9, 0xd3, 0xf8, 0x59, 0xb9, 0x9a, 0x29, 0xbf, 0x8c, 0x3f, + 0x2f, 0x40, 0x45, 0x9b, 0x14, 0x56, 0x85, 0x92, 0xd9, 0xee, 0xb6, 0xcd, 0xcf, 0xda, 0x9b, 0x8d, + 0x6b, 0xec, 0x1e, 0xbc, 0xde, 0xd9, 0xdb, 0xd8, 0x37, 0xcd, 0xf6, 0x46, 0xcf, 0xda, 0x37, 0x2d, + 0xf5, 0x46, 0xca, 0x41, 0xeb, 0x8b, 0xdd, 0xf6, 0x5e, 0xcf, 0xda, 0x6c, 0xf7, 0x5a, 0x9d, 0x9d, + 0x6e, 0x23, 0xc3, 0x6e, 0x42, 0x33, 0xa6, 0x54, 0xe8, 0xd6, 0xee, 0xfe, 0xe1, 0x5e, 0xaf, 0x91, + 0x65, 0xb7, 0xe1, 0xc6, 0x56, 0x67, 0xaf, 0xb5, 0x63, 0xc5, 0x34, 0x1b, 0x3b, 0xbd, 0xcf, 0xac, + 0xf6, 0x6f, 0x1f, 0x74, 0xcc, 0x2f, 0x1a, 0xb9, 0x34, 0x02, 0x61, 0x8c, 0xab, 0x1a, 0xf2, 0xec, + 0x3a, 0x2c, 0x13, 0x01, 0x15, 0xb1, 0x7a, 0xfb, 0xfb, 0x56, 0x77, 0x7f, 0x7f, 0xaf, 0x51, 0x60, + 0x0b, 0x50, 0xeb, 0xec, 0x7d, 0xd6, 0xda, 0xe9, 0x6c, 0x5a, 0x66, 0xbb, 0xb5, 0xb3, 0xdb, 0x98, + 0x63, 0x8b, 0x30, 0x3f, 0x4d, 0x57, 0x14, 0x55, 0x28, 0xba, 0xfd, 0xbd, 0xce, 0xfe, 0x9e, 0xf5, + 0x59, 0xdb, 0xec, 0x76, 0xf6, 0xf7, 0x1a, 0x25, 0xb6, 0x02, 0x2c, 0x89, 0xda, 0xde, 0x6d, 0x6d, + 0x34, 0xca, 0x6c, 0x19, 0x16, 0x92, 0xf0, 0xa7, 0xed, 0x2f, 0x1a, 0xc0, 0x9a, 0xb0, 0x44, 0x1d, + 0xb3, 0xd6, 0xdb, 0x3b, 0xfb, 0x9f, 0x5b, 0xbb, 0x9d, 0xbd, 0xce, 0xee, 0xe1, 0x6e, 0xa3, 0x82, + 0x8f, 0x30, 0xb5, 0xdb, 0x56, 0x67, 0xaf, 0x7b, 0xb8, 0xb5, 0xd5, 0xd9, 0xe8, 0xb4, 0xf7, 0x7a, + 0x8d, 0x2a, 0xb5, 0x9c, 0x36, 0xf0, 0x9a, 0x28, 0x20, 0xef, 0x0c, 0x58, 0x9b, 0x9d, 0x6e, 0x6b, + 0x7d, 0xa7, 0xbd, 0xd9, 0xa8, 0xb3, 0x5b, 0x70, 0xbd, 0xd7, 0xde, 0x3d, 0xd8, 0x37, 0x5b, 0xe6, + 0x17, 0xea, 0x4e, 0x81, 0xb5, 0xd5, 0xea, 0xec, 0x1c, 0x9a, 0xed, 0xc6, 0x3c, 0x7b, 0x15, 0x6e, + 0x99, 0xed, 0x4f, 0x0f, 0x3b, 0x66, 0x7b, 0xd3, 0xda, 0xdb, 0xdf, 0x6c, 0x5b, 0x5b, 0xed, 0x56, + 0xef, 0xd0, 0x6c, 0x5b, 0xbb, 0x9d, 0x6e, 0xb7, 0xb3, 0xf7, 0xa4, 0xd1, 0x60, 0xaf, 0xc3, 0x9d, + 0x88, 0x24, 0xaa, 0x60, 0x8a, 0x6a, 0x41, 0x8c, 0x4f, 0x2d, 0xe9, 0x5e, 0xfb, 0xb7, 0x7b, 0xd6, + 0x41, 0xbb, 0x6d, 0x36, 0x18, 0x5b, 0x83, 0x95, 0xb8, 0x79, 0x6a, 0x40, 0xb6, 0xbd, 0x28, 0x70, + 0x07, 0x6d, 0x73, 0xb7, 0xb5, 0x27, 0x16, 0x38, 0x81, 0x5b, 0x12, 0xdd, 0x8e, 0x71, 0xd3, 0xdd, + 0x5e, 0x66, 0x0c, 0xea, 0xda, 0xaa, 0x6c, 0xb5, 0xcc, 0xc6, 0x0a, 0x9b, 0x87, 0xca, 0xee, 0xc1, + 0x81, 0xd5, 0xeb, 0xec, 0xb6, 0xf7, 0x0f, 0x7b, 0x8d, 0x55, 0xb6, 0x0c, 0x8d, 0xce, 0x5e, 0xaf, + 0x6d, 0x8a, 0xb5, 0x56, 0x45, 0xff, 0x57, 0x91, 0x2d, 0xc1, 0xbc, 0xea, 0xa9, 0x82, 0xfe, 0xa2, + 0xc8, 0x56, 0x81, 0x1d, 0xee, 0x99, 0xed, 0xd6, 0xa6, 0x98, 0xb8, 0x08, 0xf1, 0xbf, 0x8b, 0x32, + 0x42, 0xf2, 0xb3, 0x5c, 0x74, 0x58, 0xc7, 0x29, 0x07, 0xc9, 0x47, 0x46, 0xab, 0xda, 0xe3, 0xa0, + 0x2f, 0x7a, 0xfe, 0x5b, 0x33, 0xad, 0x72, 0x33, 0xa6, 0xd5, 0x8c, 0xed, 0x5e, 0xd3, 0x75, 0xbf, + 0xd7, 0xa0, 0x36, 0xa2, 0x07, 0x47, 0xe5, 0xc3, 0x82, 0x20, 0xf3, 0x6f, 0x08, 0x48, 0xaf, 0x0a, + 0xce, 0xbc, 0x7f, 0x5d, 0x98, 0x7d, 0xff, 0x3a, 0x4d, 0xbf, 0x9f, 0x4b, 0xd3, 0xef, 0xef, 0xc3, + 0x02, 0x89, 0x26, 0xc7, 0x75, 0x46, 0xca, 0x6a, 0x26, 0x2d, 0x70, 0x1e, 0x45, 0x14, 0xc1, 0x95, + 0x39, 0xa1, 0x4c, 0x0e, 0x29, 0x42, 0x8a, 0xd2, 0xda, 0x48, 0x58, 0x1a, 0x24, 0x39, 0x22, 0x4b, + 0x23, 0x6a, 0xc1, 0xbe, 0x88, 0x5b, 0xa8, 0x68, 0x2d, 0x10, 0x1c, 0x5b, 0xb8, 0x0f, 0x0b, 0xfc, + 0x22, 0xf4, 0x6d, 0xcb, 0x1b, 0xdb, 0x5f, 0x4e, 0x30, 0x84, 0x6b, 0xa3, 0x0d, 0x5f, 0x35, 0xe7, + 0x11, 0xb1, 0x8f, 0xf0, 0x4d, 0x3b, 0xb4, 0xef, 0x7f, 0x0d, 0x15, 0xed, 0x31, 0x5a, 0xb6, 0x0a, + 0x8b, 0x9f, 0x77, 0x7a, 0x7b, 0xed, 0x6e, 0xd7, 0x3a, 0x38, 0x5c, 0x7f, 0xda, 0xfe, 0xc2, 0xda, + 0x6e, 0x75, 0xb7, 0x1b, 0xd7, 0xc4, 0xa6, 0xdd, 0x6b, 0x77, 0x7b, 0xed, 0xcd, 0x04, 0x3c, 0xc3, + 0x5e, 0x81, 0xb5, 0xc3, 0xbd, 0xc3, 0x6e, 0x7b, 0xd3, 0x4a, 0x2b, 0x97, 0x15, 0x5c, 0x2a, 0xf1, + 0x29, 0xc5, 0x73, 0xf7, 0x3f, 0x81, 0xc6, 0x74, 0x34, 0x29, 0x11, 0x7e, 0x7b, 0x5e, 0x9c, 0xee, + 0xfe, 0xbf, 0xc9, 0x01, 0xc4, 0xe9, 0xfe, 0x42, 0x50, 0x6c, 0xb6, 0x7a, 0xad, 0x9d, 0x7d, 0xd1, + 0x09, 0x73, 0xbf, 0x27, 0xf6, 0xbf, 0xd9, 0xfe, 0xb4, 0x71, 0x2d, 0x15, 0xb3, 0x7f, 0xd0, 0x6b, + 0x64, 0xc4, 0x78, 0x3b, 0x7b, 0x9d, 0x5e, 0xa7, 0xb5, 0x63, 0x99, 0xfb, 0x87, 0x9d, 0xbd, 0x27, + 0xf4, 0xdc, 0x14, 0xca, 0xc8, 0xc3, 0x83, 0x2d, 0x73, 0x7f, 0xaf, 0x67, 0x75, 0xb7, 0x0f, 0x7b, + 0x9b, 0xf8, 0x58, 0xd5, 0x86, 0xd9, 0x39, 0xa0, 0x3a, 0xf3, 0xcf, 0x23, 0x10, 0x55, 0x17, 0xc4, + 0x8c, 0x3d, 0xd9, 0xef, 0x76, 0x3b, 0x07, 0xd6, 0xa7, 0x87, 0x6d, 0xb3, 0xd3, 0xee, 0x62, 0xc1, + 0xb9, 0x14, 0xb8, 0xa0, 0x2f, 0x0a, 0xc9, 0xda, 0xdb, 0xf9, 0x4c, 0x8a, 0x3e, 0x41, 0x5a, 0x4a, + 0x82, 0x04, 0x55, 0x59, 0x48, 0x04, 0x21, 0x3b, 0x52, 0x6a, 0x86, 0x2b, 0x70, 0xa2, 0x5c, 0x45, + 0x48, 0xc5, 0x6e, 0xaf, 0xd5, 0xeb, 0x6c, 0x58, 0xf2, 0x85, 0x3b, 0xb1, 0x08, 0xa2, 0x58, 0x35, + 0x1d, 0x25, 0x4a, 0xa1, 0xc0, 0x8c, 0x8e, 0x97, 0xcd, 0x4d, 0x13, 0x0b, 0xd4, 0x67, 0xa0, 0x82, + 0x76, 0x5e, 0x2c, 0x94, 0x10, 0x2e, 0x82, 0xa4, 0xa1, 0x3e, 0x04, 0x66, 0xe1, 0xf1, 0xef, 0xe7, + 0xa0, 0x4e, 0x57, 0xaf, 0xe8, 0x97, 0x7c, 0xb8, 0xcf, 0x76, 0xa1, 0x28, 0x7f, 0x12, 0x8a, 0x2d, + 0x47, 0x8f, 0x0e, 0xe9, 0x3f, 0x42, 0xb5, 0xb6, 0x32, 0x0d, 0x96, 0xca, 0xd4, 0xe2, 0xdf, 0xfc, + 0xb3, 0xbf, 0xfa, 0x47, 0xd9, 0x1a, 0xab, 0x3c, 0x3c, 0x7b, 0xf7, 0xe1, 0x09, 0x77, 0x03, 0x51, + 0xc7, 0x5f, 0x03, 0x88, 0x7f, 0xe8, 0x88, 0x35, 0xa3, 0x10, 0xd2, 0xd4, 0xaf, 0x40, 0xad, 0x5d, + 0x4f, 0xc1, 0xc8, 0x7a, 0xaf, 0x63, 0xbd, 0x8b, 0x46, 0x5d, 0xd4, 0xeb, 0xb8, 0x4e, 0x48, 0x3f, + 0x7a, 0xf4, 0x71, 0xe6, 0x3e, 0x1b, 0x40, 0x55, 0xff, 0x09, 0x22, 0xa6, 0xf4, 0x9c, 0x94, 0x1f, + 0x51, 0x5a, 0xbb, 0x91, 0x8a, 0x53, 0x1a, 0x24, 0xb6, 0xb1, 0x6c, 0x34, 0x44, 0x1b, 0x13, 0xa4, + 0x88, 0x5b, 0x19, 0x92, 0x4e, 0x1d, 0xff, 0xd2, 0x10, 0xbb, 0xa9, 0x69, 0x45, 0x33, 0xbf, 0x73, + 0xb4, 0x76, 0xeb, 0x0a, 0xac, 0x6c, 0xeb, 0x16, 0xb6, 0xb5, 0x6a, 0x30, 0xd1, 0x56, 0x1f, 0x69, + 0xd4, 0xef, 0x1c, 0x7d, 0x9c, 0xb9, 0xff, 0xf8, 0x2f, 0xef, 0x41, 0x39, 0x4a, 0xc5, 0x64, 0xbf, + 0x0b, 0xb5, 0xc4, 0xdd, 0x38, 0xa6, 0x86, 0x91, 0x76, 0x95, 0x6e, 0xed, 0x66, 0x3a, 0x52, 0x36, + 0xfc, 0x0a, 0x36, 0xdc, 0x64, 0x2b, 0xa2, 0x61, 0x79, 0xf7, 0xec, 0x21, 0xde, 0x20, 0xa5, 0x27, + 0x9c, 0x9e, 0x69, 0xb6, 0x03, 0x35, 0x76, 0x73, 0x5a, 0x9f, 0x4f, 0xb4, 0x76, 0xeb, 0x0a, 0xac, + 0x6c, 0xee, 0x26, 0x36, 0xb7, 0xc2, 0x96, 0xf4, 0xe6, 0x54, 0xe2, 0x24, 0xe3, 0xf8, 0x6c, 0x9a, + 0xfe, 0x43, 0x3c, 0xec, 0x56, 0xfc, 0xc8, 0x55, 0xca, 0x0f, 0xf4, 0x44, 0x2c, 0x32, 0xfb, 0x2b, + 0x3d, 0x46, 0x13, 0x9b, 0x62, 0x0c, 0x97, 0x4f, 0xff, 0x1d, 0x1e, 0x76, 0x04, 0x15, 0xed, 0xed, + 0x7a, 0x76, 0xfd, 0xca, 0x77, 0xf6, 0xd7, 0xd6, 0xd2, 0x50, 0x69, 0x43, 0xd1, 0xeb, 0x7f, 0x78, + 0xcc, 0x39, 0xfb, 0x21, 0x94, 0xa3, 0x17, 0xd1, 0xd9, 0xaa, 0xf6, 0x42, 0xbd, 0xfe, 0x82, 0xfb, + 0x5a, 0x73, 0x16, 0x91, 0xc6, 0x7c, 0x7a, 0xed, 0x82, 0xf9, 0x3e, 0x87, 0x8a, 0xf6, 0xea, 0x79, + 0x34, 0x80, 0xd9, 0x97, 0xd5, 0xa3, 0x01, 0xa4, 0x3c, 0x92, 0x6e, 0x2c, 0x60, 0x13, 0x15, 0x56, + 0x46, 0xfe, 0x0e, 0x2f, 0xbc, 0x80, 0xed, 0xc0, 0xb2, 0xb4, 0x93, 0x8e, 0xf8, 0x37, 0x59, 0x86, + 0x94, 0xdf, 0x3e, 0x7a, 0x94, 0x61, 0x9f, 0x40, 0x49, 0x3d, 0x6e, 0xcf, 0x56, 0xd2, 0x1f, 0xe9, + 0x5f, 0x5b, 0x9d, 0x81, 0x4b, 0xa3, 0xe6, 0x0b, 0x80, 0xf8, 0x89, 0xf5, 0x48, 0x48, 0xcc, 0x3c, + 0xd9, 0x1e, 0x71, 0xc0, 0xec, 0x7b, 0xec, 0xc6, 0x0a, 0x0e, 0xb0, 0xc1, 0x50, 0x48, 0xb8, 0xfc, + 0x5c, 0xbd, 0x1f, 0xf9, 0x23, 0xa8, 0x68, 0xaf, 0xac, 0x47, 0xd3, 0x37, 0xfb, 0x42, 0x7b, 0x34, + 0x7d, 0x29, 0x8f, 0xb2, 0x1b, 0x6b, 0x58, 0xfb, 0x92, 0x31, 0x2f, 0x6a, 0x17, 0x8a, 0x92, 0x54, + 0x58, 0xc4, 0x02, 0x9d, 0x42, 0x2d, 0xf1, 0x94, 0x7a, 0xb4, 0x43, 0xd3, 0x1e, 0x6a, 0x8f, 0x76, + 0x68, 0xea, 0xeb, 0xeb, 0x8a, 0xcf, 0x8c, 0x05, 0xd1, 0xce, 0x19, 0x92, 0x68, 0x2d, 0xfd, 0x00, + 0x2a, 0xda, 0xb3, 0xe8, 0xd1, 0x58, 0x66, 0x5f, 0x60, 0x8f, 0xc6, 0x92, 0xf6, 0x8a, 0xfa, 0x12, + 0xb6, 0x51, 0x37, 0x90, 0x15, 0xf0, 0x75, 0x3e, 0x51, 0xf7, 0xef, 0x42, 0x3d, 0xf9, 0x52, 0x7a, + 0xb4, 0xf7, 0x53, 0x9f, 0x5c, 0x8f, 0xf6, 0xfe, 0x15, 0xcf, 0xab, 0x4b, 0x96, 0xbe, 0xbf, 0x18, + 0x35, 0xf2, 0xf0, 0x2b, 0x79, 0xa9, 0xe4, 0x6b, 0xf6, 0xa9, 0x10, 0x70, 0xf2, 0x71, 0x48, 0xb6, + 0xaa, 0x71, 0xad, 0xfe, 0x84, 0x64, 0xb4, 0x5f, 0x66, 0xde, 0x91, 0x4c, 0x32, 0x33, 0x56, 0xce, + 0x9e, 0xc0, 0x62, 0xc4, 0xcc, 0xd1, 0x6b, 0x8f, 0x41, 0x34, 0x86, 0xd4, 0x37, 0x25, 0xd7, 0x1a, + 0xd3, 0xd8, 0x47, 0x19, 0x3a, 0xfe, 0xf0, 0x8d, 0x3d, 0xed, 0xf8, 0xd3, 0x1f, 0x7c, 0xd4, 0x8e, + 0xbf, 0xc4, 0x53, 0x7c, 0xd3, 0xc7, 0x5f, 0xe8, 0x88, 0x3a, 0x5c, 0x98, 0x9f, 0x7e, 0x7b, 0xf1, + 0xd6, 0x55, 0x2f, 0x0f, 0x50, 0xf5, 0xaf, 0x3c, 0xff, 0x61, 0x82, 0xa4, 0x28, 0x52, 0xd2, 0xf4, + 0xa1, 0x4c, 0x1d, 0x61, 0xbf, 0x03, 0x55, 0xfd, 0xa9, 0x67, 0xa6, 0xcb, 0x84, 0xe9, 0x96, 0x6e, + 0xa4, 0xe2, 0x92, 0x5c, 0xc2, 0xaa, 0x7a, 0x33, 0xec, 0x33, 0x58, 0x89, 0xa6, 0x59, 0xbf, 0x75, + 0x1e, 0xb0, 0xdb, 0x29, 0x77, 0xd1, 0x13, 0x93, 0x7d, 0xfd, 0xca, 0xcb, 0xea, 0x8f, 0x32, 0x82, + 0xfb, 0x92, 0x6f, 0xce, 0xc6, 0x27, 0x4f, 0xda, 0x53, 0xbb, 0xf1, 0xc9, 0x93, 0xfa, 0x50, 0xad, + 0xe2, 0x3e, 0xb6, 0x98, 0x98, 0x23, 0x4a, 0xaa, 0x65, 0x3f, 0x80, 0x79, 0xed, 0x4a, 0x7d, 0xf7, + 0xd2, 0xed, 0x47, 0x3b, 0x69, 0xf6, 0x41, 0xb7, 0xb5, 0x34, 0xcf, 0xa2, 0xb1, 0x8a, 0xf5, 0x2f, + 0x18, 0x89, 0xc9, 0x11, 0xbb, 0x68, 0x03, 0x2a, 0xfa, 0x75, 0xfd, 0xe7, 0xd4, 0xbb, 0xaa, 0xa1, + 0xf4, 0xb7, 0xc3, 0x1e, 0x65, 0xd8, 0x0e, 0x34, 0xa6, 0x9f, 0x3a, 0x8a, 0x64, 0x4a, 0xda, 0xf3, + 0x4c, 0x6b, 0x53, 0xc8, 0xc4, 0x03, 0x49, 0xec, 0x80, 0xae, 0x65, 0x44, 0x3f, 0x14, 0xe4, 0xf9, + 0xd3, 0xa7, 0x7a, 0xf2, 0x07, 0x84, 0xa2, 0xda, 0xd2, 0x7e, 0x3a, 0xea, 0x5e, 0xe6, 0x51, 0x86, + 0xfd, 0x34, 0x03, 0xd5, 0xc4, 0xf3, 0x22, 0x89, 0xc4, 0xf7, 0xa9, 0x71, 0x36, 0x75, 0x9c, 0x3e, + 0x50, 0xc3, 0xc4, 0x49, 0xdc, 0xb9, 0xff, 0xfd, 0xc4, 0x22, 0x7d, 0x95, 0x08, 0xcc, 0x3d, 0x98, + 0xfe, 0x25, 0xa1, 0xaf, 0xa7, 0x09, 0xf4, 0x77, 0xfa, 0xbe, 0x7e, 0x94, 0x61, 0xff, 0x2e, 0x03, + 0xf5, 0x64, 0xc4, 0x3d, 0x1a, 0x6e, 0x6a, 0x6c, 0x3f, 0x62, 0xa5, 0x2b, 0xc2, 0xf4, 0x3f, 0xc0, + 0x5e, 0xf6, 0xee, 0x9b, 0x89, 0x5e, 0xca, 0xd7, 0x92, 0x7f, 0xb9, 0xde, 0xb2, 0x8f, 0xe9, 0x87, + 0xfb, 0x54, 0x22, 0x12, 0x9b, 0xfd, 0xa1, 0xb7, 0x88, 0xfd, 0xf4, 0x9f, 0x45, 0xc3, 0x45, 0xf8, + 0x11, 0xfd, 0x62, 0x8e, 0xca, 0x6b, 0x11, 0x5c, 0xfc, 0xb2, 0xe5, 0x8d, 0xd7, 0x71, 0x4c, 0xaf, + 0x18, 0xd7, 0x13, 0x63, 0x9a, 0x56, 0x3c, 0x5a, 0xd4, 0x3b, 0xf9, 0xab, 0x66, 0xf1, 0xc9, 0x39, + 0xf3, 0x4b, 0x67, 0x57, 0x77, 0x72, 0x44, 0x9d, 0x94, 0xe4, 0x89, 0xad, 0xf6, 0x92, 0xd5, 0x18, + 0xf7, 0xb1, 0xaf, 0xaf, 0x1b, 0xb7, 0xaf, 0xec, 0xeb, 0x43, 0x8c, 0x9e, 0x8b, 0x1e, 0x1f, 0x00, + 0xc4, 0x89, 0x82, 0x6c, 0x2a, 0x5d, 0x2d, 0x12, 0x40, 0xb3, 0xb9, 0x84, 0xc9, 0xfd, 0xac, 0xb2, + 0xda, 0x44, 0x8d, 0x3f, 0x24, 0x71, 0x1a, 0x25, 0xd2, 0xe9, 0xda, 0x57, 0x32, 0xa7, 0x2f, 0xa1, + 0x7d, 0x4d, 0xd7, 0x9f, 0x10, 0xa6, 0x51, 0xd6, 0xdc, 0x21, 0xd4, 0x76, 0x3c, 0xef, 0xd9, 0x64, + 0x1c, 0x25, 0xa7, 0x27, 0x53, 0x5a, 0xb6, 0xed, 0xe0, 0x74, 0x6d, 0x6a, 0x14, 0xc6, 0x1d, 0xac, + 0x6a, 0x8d, 0x35, 0xb5, 0xaa, 0x1e, 0x7e, 0x15, 0x67, 0x27, 0x7e, 0xcd, 0x6c, 0x58, 0x88, 0x64, + 0x74, 0x9c, 0x01, 0x98, 0xac, 0x26, 0x21, 0x99, 0xa7, 0x9b, 0x48, 0x98, 0x09, 0xaa, 0xb7, 0x0f, + 0x03, 0x55, 0xe7, 0xa3, 0x0c, 0x3b, 0x80, 0xea, 0x26, 0xef, 0xe3, 0x35, 0x7b, 0x4c, 0x0c, 0x59, + 0x4c, 0x24, 0x19, 0x50, 0x46, 0xc9, 0x5a, 0x2d, 0x01, 0x4c, 0x9e, 0x5b, 0x63, 0xfb, 0xd2, 0xe7, + 0x5f, 0x3e, 0xfc, 0x4a, 0xa6, 0x9c, 0x7c, 0xad, 0xce, 0x2d, 0x95, 0x92, 0x93, 0x38, 0xb7, 0xa6, + 0x72, 0x78, 0x12, 0xe7, 0xd6, 0x4c, 0x0e, 0x4f, 0x62, 0xaa, 0x55, 0x4a, 0x10, 0x1b, 0xc2, 0xc2, + 0x4c, 0xda, 0x4f, 0x74, 0x64, 0x5d, 0x95, 0x2c, 0xb4, 0x76, 0xe7, 0x6a, 0x82, 0x64, 0x6b, 0xf7, + 0x93, 0xad, 0x75, 0xa1, 0x46, 0x4f, 0x07, 0x1e, 0x71, 0xba, 0x70, 0x37, 0xf5, 0x5a, 0x8d, 0x7e, + 0x9b, 0x6f, 0xfa, 0x80, 0x41, 0x5c, 0x52, 0xc3, 0xc1, 0x9b, 0x6e, 0xec, 0x87, 0x50, 0x79, 0xc2, + 0x43, 0x75, 0xc3, 0x2e, 0xd2, 0xb1, 0xa7, 0xae, 0xdc, 0xad, 0xa5, 0x5c, 0xd0, 0x4b, 0xf2, 0x0c, + 0xd6, 0xf6, 0x90, 0x0f, 0x4e, 0x38, 0x09, 0x27, 0xcb, 0x19, 0x7c, 0xcd, 0x7e, 0x1b, 0x2b, 0x8f, + 0x2e, 0x36, 0xaf, 0x68, 0x57, 0xa8, 0xf4, 0xca, 0xe7, 0xa7, 0xe0, 0x69, 0x35, 0xbb, 0xde, 0x80, + 0x6b, 0xba, 0x9e, 0x0b, 0x15, 0xed, 0x01, 0x84, 0x68, 0x03, 0xcd, 0x3e, 0x78, 0x11, 0x6d, 0xa0, + 0x94, 0xf7, 0x12, 0x8c, 0x7b, 0xd8, 0x8e, 0xc1, 0xee, 0xc4, 0xed, 0xd0, 0x1b, 0x09, 0x71, 0x4b, + 0x0f, 0xbf, 0xb2, 0x47, 0xe1, 0xd7, 0xec, 0x73, 0x7c, 0xa0, 0x5b, 0xbf, 0x41, 0x18, 0x1b, 0x0d, + 0xd3, 0x97, 0x0d, 0xa3, 0xc9, 0xd2, 0x50, 0x49, 0x43, 0x82, 0x9a, 0x42, 0x4d, 0xee, 0x7d, 0x80, + 0x6e, 0xe8, 0x8d, 0x37, 0x6d, 0x3e, 0xf2, 0xdc, 0x58, 0xd6, 0xc6, 0x77, 0xda, 0x62, 0xf9, 0xa5, + 0x5d, 0x6c, 0x63, 0x9f, 0x6b, 0x56, 0x56, 0xe2, 0x12, 0xa6, 0x62, 0xae, 0x2b, 0xaf, 0xbd, 0x45, + 0x13, 0x92, 0x72, 0xf5, 0xed, 0x51, 0x86, 0xb5, 0x00, 0xe2, 0xbc, 0xaf, 0xc8, 0x66, 0x9a, 0x49, + 0x29, 0x8b, 0xc4, 0x5e, 0x4a, 0x92, 0xd8, 0x01, 0x94, 0xe3, 0x84, 0x99, 0xd5, 0xf8, 0x3d, 0x97, + 0x44, 0x7a, 0x4d, 0x74, 0x82, 0xcf, 0x24, 0xab, 0x18, 0x0d, 0x9c, 0x2a, 0x60, 0x25, 0x31, 0x55, + 0xc7, 0x9c, 0x07, 0xcc, 0x81, 0x45, 0xea, 0x60, 0xa4, 0x2e, 0xe1, 0x5d, 0xac, 0xe8, 0x1d, 0xf6, + 0xd9, 0xbc, 0x91, 0x68, 0x37, 0xa7, 0x66, 0x3f, 0x24, 0x5c, 0x3f, 0x82, 0x5b, 0xe9, 0x1e, 0x98, + 0x10, 0xcd, 0x23, 0x58, 0x98, 0x09, 0xb0, 0x47, 0x5b, 0xfa, 0xaa, 0x8c, 0x89, 0x68, 0x4b, 0x5f, + 0x19, 0x9b, 0x37, 0x96, 0xb1, 0xc9, 0x79, 0x03, 0xd0, 0xd4, 0x3b, 0x77, 0xc2, 0xfe, 0xa9, 0x68, + 0xee, 0x5f, 0x67, 0x60, 0x31, 0x25, 0x84, 0xce, 0x5e, 0x55, 0x5e, 0x83, 0x2b, 0xc3, 0xeb, 0x6b, + 0xa9, 0xa1, 0x56, 0xa3, 0x8b, 0xed, 0xec, 0xb2, 0xa7, 0x89, 0x83, 0x8d, 0x22, 0x9d, 0x72, 0x67, + 0x3e, 0x57, 0xa9, 0x48, 0xd5, 0x28, 0xbe, 0x84, 0x55, 0xea, 0x48, 0x6b, 0x38, 0x9c, 0x0a, 0x03, + 0xbf, 0x32, 0xf3, 0xc3, 0xde, 0x89, 0xd0, 0xf6, 0xda, 0xd5, 0x3f, 0xfc, 0x7d, 0x85, 0x3a, 0x4d, + 0x5d, 0x65, 0x13, 0x68, 0x4c, 0x87, 0x57, 0xd9, 0xd5, 0x75, 0xad, 0xdd, 0x4e, 0xd8, 0xbf, 0x29, + 0x21, 0xd9, 0xef, 0x60, 0x63, 0xb7, 0x8d, 0xb5, 0xb4, 0x79, 0x21, 0x93, 0x58, 0xac, 0xc7, 0xdf, + 0x88, 0x62, 0xc1, 0x53, 0xe3, 0x54, 0x0d, 0x5c, 0x15, 0xb9, 0x8e, 0x2c, 0xf0, 0xf4, 0x50, 0xf2, + 0x1b, 0xd8, 0xfc, 0x1d, 0xe3, 0x46, 0x5a, 0xf3, 0x3e, 0x15, 0x21, 0x5b, 0x7c, 0x75, 0x7a, 0x5f, + 0xab, 0x1e, 0xdc, 0x49, 0x5b, 0xef, 0x2b, 0x6d, 0xa1, 0xa9, 0xb9, 0xbe, 0x86, 0xba, 0x5d, 0x55, + 0x8f, 0xfd, 0x46, 0xdb, 0x27, 0x25, 0xc8, 0x1c, 0x6d, 0x9f, 0xb4, 0x60, 0x71, 0x52, 0xaf, 0x51, + 0x61, 0xe2, 0x8f, 0x33, 0xf7, 0xd7, 0xef, 0xfe, 0xe0, 0x3b, 0x27, 0x4e, 0x78, 0x3a, 0x39, 0x7a, + 0xd0, 0xf7, 0x46, 0x0f, 0x87, 0xca, 0xdb, 0x28, 0x2f, 0x2c, 0x3f, 0x1c, 0xba, 0x83, 0x87, 0x58, + 0xed, 0xd1, 0xdc, 0xd8, 0xf7, 0x42, 0xef, 0xbb, 0xff, 0x37, 0x00, 0x00, 0xff, 0xff, 0x26, 0x2b, + 0x1e, 0xcb, 0xbb, 0x80, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index b5b3ebb01b..ae6affc5dd 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2819,6 +2819,9 @@ message HTLCAttempt { This value will not be set if the HTLC is still IN_FLIGHT. */ int64 resolve_time_ns = 4; + + // Detailed htlc failure info. + Failure failure = 5; } message ListPaymentsRequest { @@ -3149,6 +3152,11 @@ message Failure { EXPIRY_TOO_FAR = 22; MPP_TIMEOUT = 23; + /** + An internal error occurred. + */ + INTERNAL_FAILURE = 997; + /** The error source is known, but the failure itself couldn't be decoded. */ diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 8bffa4a8c1..66621d03c2 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1490,6 +1490,40 @@ ], "default": "OPEN_CHANNEL" }, + "FailureFailureCode": { + "type": "string", + "enum": [ + "RESERVED", + "INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS", + "INCORRECT_PAYMENT_AMOUNT", + "FINAL_INCORRECT_CLTV_EXPIRY", + "FINAL_INCORRECT_HTLC_AMOUNT", + "FINAL_EXPIRY_TOO_SOON", + "INVALID_REALM", + "EXPIRY_TOO_SOON", + "INVALID_ONION_VERSION", + "INVALID_ONION_HMAC", + "INVALID_ONION_KEY", + "AMOUNT_BELOW_MINIMUM", + "FEE_INSUFFICIENT", + "INCORRECT_CLTV_EXPIRY", + "CHANNEL_DISABLED", + "TEMPORARY_CHANNEL_FAILURE", + "REQUIRED_NODE_FEATURE_MISSING", + "REQUIRED_CHANNEL_FEATURE_MISSING", + "UNKNOWN_NEXT_PEER", + "TEMPORARY_NODE_FAILURE", + "PERMANENT_NODE_FAILURE", + "PERMANENT_CHANNEL_FAILURE", + "EXPIRY_TOO_FAR", + "MPP_TIMEOUT", + "INTERNAL_FAILURE", + "UNKNOWN_FAILURE", + "UNREADABLE_FAILURE" + ], + "default": "RESERVED", + "description": " - RESERVED: *\nThe numbers assigned in this enumeration match the failure codes as\ndefined in BOLT #4. Because protobuf 3 requires enums to start with 0,\na RESERVED value is added.\n - INTERNAL_FAILURE: *\nAn internal error occurred.\n - UNKNOWN_FAILURE: *\nThe error source is known, but the failure itself couldn't be decoded.\n - UNREADABLE_FAILURE: *\nAn unreadable failure result is returned if the received failure message\ncannot be decrypted. In that case the error source is unknown." + }, "HTLCAttemptHTLCStatus": { "type": "string", "enum": [ @@ -2260,6 +2294,71 @@ } } }, + "lnrpcChannelUpdate": { + "type": "object", + "properties": { + "signature": { + "type": "string", + "format": "byte", + "description": "*\nThe signature that validates the announced data and proves the ownership\nof node id." + }, + "chain_hash": { + "type": "string", + "format": "byte", + "description": "*\nThe target chain that this channel was opened within. This value\nshould be the genesis hash of the target chain. Along with the short\nchannel ID, this uniquely identifies the channel globally in a\nblockchain." + }, + "chan_id": { + "type": "string", + "format": "uint64", + "description": "*\nThe unique description of the funding transaction." + }, + "timestamp": { + "type": "integer", + "format": "int64", + "description": "*\nA timestamp that allows ordering in the case of multiple announcements.\nWe should ignore the message if timestamp is not greater than the\nlast-received." + }, + "message_flags": { + "type": "integer", + "format": "int64", + "description": "*\nThe bitfield that describes whether optional fields are present in this\nupdate. Currently, the least-significant bit must be set to 1 if the\noptional field MaxHtlc is present." + }, + "channel_flags": { + "type": "integer", + "format": "int64", + "description": "*\nThe bitfield that describes additional meta-data concerning how the\nupdate is to be interpreted. Currently, the least-significant bit must be\nset to 0 if the creating node corresponds to the first node in the\npreviously sent channel announcement and 1 otherwise. If the second bit\nis set, then the channel is set to be disabled." + }, + "time_lock_delta": { + "type": "integer", + "format": "int64", + "description": "*\nThe minimum number of blocks this node requires to be added to the expiry\nof HTLCs. This is a security parameter determined by the node operator.\nThis value represents the required gap between the time locks of the\nincoming and outgoing HTLC's set to this node." + }, + "htlc_minimum_msat": { + "type": "string", + "format": "uint64", + "description": "*\nThe minimum HTLC value which will be accepted." + }, + "base_fee": { + "type": "integer", + "format": "int64", + "description": "*\nThe base fee that must be used for incoming HTLC's to this particular\nchannel. This value will be tacked onto the required for a payment\nindependent of the size of the payment." + }, + "fee_rate": { + "type": "integer", + "format": "int64", + "description": "*\nThe fee rate that will be charged per millionth of a satoshi." + }, + "htlc_maximum_msat": { + "type": "string", + "format": "uint64", + "description": "*\nThe maximum HTLC value which will be accepted." + }, + "extra_opaque_data": { + "type": "string", + "format": "byte", + "description": "*\nThe set of data that was appended to this message, some of which we may\nnot actually know how to iterate or parse. By holding onto this data, we\nensure that we're able to properly validate the set of signatures that\ncover these new fields, and ensure we're able to make upgrades to the\nnetwork in a forwards compatible manner." + } + } + }, "lnrpcCloseStatusUpdate": { "type": "object", "properties": { @@ -2364,6 +2463,49 @@ } } }, + "lnrpcFailure": { + "type": "object", + "properties": { + "code": { + "$ref": "#/definitions/FailureFailureCode", + "title": "/ Failure code as defined in the Lightning spec" + }, + "channel_update": { + "$ref": "#/definitions/lnrpcChannelUpdate", + "description": "/ An optional channel update message." + }, + "htlc_msat": { + "type": "string", + "format": "uint64", + "description": "/ A failure type-dependent htlc value." + }, + "onion_sha_256": { + "type": "string", + "format": "byte", + "description": "/ The sha256 sum of the onion payload." + }, + "cltv_expiry": { + "type": "integer", + "format": "int64", + "description": "/ A failure type-dependent cltv expiry value." + }, + "flags": { + "type": "integer", + "format": "int64", + "description": "/ A failure type-dependent flags value." + }, + "failure_source_index": { + "type": "integer", + "format": "int64", + "description": "*\nThe position in the path of the intermediate or final node that generated\nthe failure message. Position zero is the sender node." + }, + "height": { + "type": "integer", + "format": "int64", + "description": "/ A failure type-dependent block height." + } + } + }, "lnrpcFeature": { "type": "object", "properties": { @@ -2735,6 +2877,10 @@ "type": "string", "format": "int64", "description": "*\nThe time in UNIX nanoseconds at which this HTLC was settled or failed.\nThis value will not be set if the HTLC is still IN_FLIGHT." + }, + "failure": { + "$ref": "#/definitions/lnrpcFailure", + "description": "Detailed htlc failure info." } } }, From 1589810f07a33a507ae81832d5a5cadbb73419f1 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 9 Mar 2020 12:23:43 -0700 Subject: [PATCH 194/562] build: update to x/crypto version w/o broken poly1305 arm assembly In this commit, we update to a new version of `x/crypto` that drops broken ARM assembly that can cause a segfault in systems like raspis. The broken assembly was removed in this commit to the runtime: https://github.com/golang/go/commit/8b774103d3f833775e7e214bf51a37b3cfa39615. Fixes #4052. --- go.mod | 4 ++-- go.sum | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 63b5e7dbc0..5b2d56eb31 100644 --- a/go.mod +++ b/go.mod @@ -45,8 +45,8 @@ require ( github.com/rogpeppe/fastuuid v1.2.0 // indirect github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 github.com/urfave/cli v1.18.0 - golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 - golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 + golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 + golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 google.golang.org/grpc v1.19.0 diff --git a/go.sum b/go.sum index b8991183ef..c2773b2e59 100644 --- a/go.sum +++ b/go.sum @@ -185,6 +185,9 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9QSINo2CUPM/cySEvw2w8I0= +golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -196,6 +199,8 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80= golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -208,6 +213,8 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 7a1013fb9eb9fa0c6b81c1c629cb88ddf54efcaf Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 22 May 2019 15:24:40 -0700 Subject: [PATCH 195/562] make+travis: verify compiled protos on travis --- .travis.yml | 22 +++++++--- Makefile | 10 +++++ lnrpc/.clang-format | 7 ++++ scripts/install_travis_proto.sh | 72 +++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 lnrpc/.clang-format create mode 100755 scripts/install_travis_proto.sh diff --git a/.travis.yml b/.travis.yml index c996ca51e0..96a7312f81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,14 @@ language: go cache: directories: - ~/bitcoin/bitcoin-0.19.0.1/bin + - $DOWNLOAD_CACHE - $GOCACHE - $GOPATH/pkg/mod - $GOPATH/src/github.com/btcsuite - $GOPATH/src/github.com/golang + - $GOPATH/src/github.com/grpc-ecosystem - $GOPATH/src/gopkg.in/alecthomas + - $GOPATH/src/google.golang.org # Remove Travis' default flag --depth=50 from the git clone command to make sure # we have the whole git history, including the commit we lint against. @@ -19,18 +22,27 @@ go: env: global: - GOCACHE=$HOME/.go-build + - DOWNLOAD_CACHE=$HOME/download_cache sudo: required -before_script: bash ./scripts/install_bitcoind.sh +addons: + apt: + packages: + - clang-format + +before_script: + - bash ./scripts/install_travis_proto.sh + - bash ./scripts/install_bitcoind.sh jobs: include: - stage: Build - script: - - make unit pkg=... case=_NONE_ - - make lint - - make btcd + script: + - make rpc-check + - make unit pkg=... case=_NONE_ + - make lint + - make btcd - stage: Test script: make travis-cover name: Unit Cover diff --git a/Makefile b/Makefile index 9585fdecb4..6d50d6e08c 100644 --- a/Makefile +++ b/Makefile @@ -174,6 +174,14 @@ rpc: @$(call print, "Compiling protos.") cd ./lnrpc; ./gen_protos.sh +rpc-format: + @$(call print, "Formatting protos.") + cd ./lnrpc; find . -name "*.proto" | xargs clang-format --style=file -i + +rpc-check: rpc-format rpc + @$(call print, "Verifying protos.") + if test -n "$$(git describe --dirty | grep dirty)"; then echo "Protos not properly formatted or not compiled with v3.4.0"; git status; git diff; exit 1; fi + mobile-rpc: @$(call print, "Creating mobile RPC from protos.") cd ./mobile; ./gen_bindings.sh @@ -223,6 +231,8 @@ clean: lint \ list \ rpc \ + rpc-format \ + rpc-check \ mobile-rpc \ vendor \ ios \ diff --git a/lnrpc/.clang-format b/lnrpc/.clang-format new file mode 100644 index 0000000000..f19142787d --- /dev/null +++ b/lnrpc/.clang-format @@ -0,0 +1,7 @@ +--- +Language: Proto +BasedOnStyle: Google +IndentWidth: 4 +AllowShortFunctionsOnASingleLine: None +SpaceBeforeParens: Always +CompactNamespaces: false diff --git a/scripts/install_travis_proto.sh b/scripts/install_travis_proto.sh new file mode 100755 index 0000000000..8208bd327c --- /dev/null +++ b/scripts/install_travis_proto.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +# Abort on error (-e) and print commands (-v). +set -ev + +# See README.md in lnrpc why we need these specific versions/commits. +PROTOC_VERSION=3.4.0 +PROTOBUF_VERSION="b5d812f8a3706043e23a9cd5babf2e5423744d30" +GENPROTO_VERSION="a8101f21cf983e773d0c1133ebc5424792003214" +GRPC_GATEWAY_VERSION="v1.8.6" + +# This script is specific to Travis CI so we only need to support linux x64. +PROTOC_URL="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" +PROTOC_DL_CACHE_DIR="${DOWNLOAD_CACHE:-/tmp/download_cache}/protoc" + +# install_protoc copies the cached protoc binary to the $PATH or downloads it +# if no cached version is found. +install_protoc() { + if [ -f "${PROTOC_DL_CACHE_DIR}/bin/protoc" ]; then + echo "Using cached version of protoc" + else + wget -O /tmp/protoc.zip $PROTOC_URL + mkdir -p "${PROTOC_DL_CACHE_DIR}" + unzip -o /tmp/protoc.zip -d "${PROTOC_DL_CACHE_DIR}" + chmod -R a+rx "${PROTOC_DL_CACHE_DIR}/" + fi + sudo cp "${PROTOC_DL_CACHE_DIR}/bin/protoc" /usr/local/bin + sudo cp -r "${PROTOC_DL_CACHE_DIR}/include" /usr/local +} + +# install_protobuf downloads and compiles the Golang protobuf library that +# encodes/decodes all protobuf messages from/to Go structs. +install_protobuf() { + local install_path="$GOPATH/src/github.com/golang/protobuf" + if [ ! -d "$install_path" ]; then + git clone https://github.com/golang/protobuf "$install_path" + fi + pushd "$install_path" + git reset --hard $PROTOBUF_VERSION + make + popd +} + +# install_genproto downloads the Golang protobuf generator that converts the +# .proto files into Go interface stubs. +install_genproto() { + local install_path="$GOPATH/src/google.golang.org/genproto" + if [ ! -d "$install_path" ]; then + git clone https://github.com/google/go-genproto "$install_path" + fi + pushd "$install_path" + git reset --hard $GENPROTO_VERSION + popd +} + +# install_grpc_gateway downloads and installs the gRPC gateway that converts +# .proto files into REST gateway code. +install_grpc_gateway() { + local install_path="$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway" + if [ ! -d "$install_path" ]; then + git clone https://github.com/grpc-ecosystem/grpc-gateway "$install_path" + fi + pushd "$install_path" + git reset --hard $GRPC_GATEWAY_VERSION + GO111MODULE=on go install ./protoc-gen-grpc-gateway ./protoc-gen-swagger + popd +} + +install_protoc +install_protobuf +install_genproto +install_grpc_gateway From ed8924c6c5fdff52daa9377bbe3f335056a3ab57 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 10 Mar 2020 14:19:42 +0100 Subject: [PATCH 196/562] lncli: allow unlock with password from stdin --- cmd/lncli/commands.go | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 608b8d3f8b..1031c25242 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1767,6 +1767,16 @@ var unlockCommand = cli.Command{ "maximum number of consecutive, unused " + "addresses ever generated by the wallet.", }, + cli.BoolFlag{ + Name: "stdin", + Usage: "read password from standard input instead of " + + "prompting for it. THIS IS CONSIDERED TO " + + "BE DANGEROUS if the password is located in " + + "a file that can be read by another user. " + + "This flag should only be used in " + + "combination with some sort of password " + + "manager or secrets vault.", + }, }, Action: actionDecorator(unlock), } @@ -1776,12 +1786,33 @@ func unlock(ctx *cli.Context) error { client, cleanUp := getWalletUnlockerClient(ctx) defer cleanUp() - fmt.Printf("Input wallet password: ") - pw, err := terminal.ReadPassword(int(syscall.Stdin)) + var ( + pw []byte + err error + ) + switch { + // Read the password from standard in as if it were a file. This should + // only be used if the password is piped into lncli from some sort of + // password manager. If the user types the password instead, it will be + // echoed in the console. + case ctx.IsSet("stdin"): + reader := bufio.NewReader(os.Stdin) + pw, err = reader.ReadBytes('\n') + + // Remove carriage return and newline characters. + pw = bytes.Trim(pw, "\r\n") + + // Read the password from a terminal by default. This requires the + // terminal to be a real tty and will fail if a string is piped into + // lncli. + default: + fmt.Printf("Input wallet password: ") + pw, err = terminal.ReadPassword(syscall.Stdin) + fmt.Println() + } if err != nil { return err } - fmt.Println() args := ctx.Args() From 018e8b5b97a1382f09e35c4d6f144cf1b18cf849 Mon Sep 17 00:00:00 2001 From: Tomas Carnecky Date: Sat, 26 Oct 2019 11:00:57 +0200 Subject: [PATCH 197/562] server+tor: add support for Tor HASHEDPASSWORD authentication method This provides users an alternative over the SAFECOOKIE authentication method, which may not be as useful if users are connecting to a remote Tor sevrer due to lnd not being able to retrieve the cookie file. --- config.go | 1 + docs/configuring_tor.md | 25 +++++- server.go | 5 +- tor/README.md | 4 +- tor/controller.go | 194 ++++++++++++++++++++++++---------------- 5 files changed, 146 insertions(+), 83 deletions(-) diff --git a/config.go b/config.go index fd5ee8b62d..c9f593e919 100644 --- a/config.go +++ b/config.go @@ -221,6 +221,7 @@ type torConfig struct { StreamIsolation bool `long:"streamisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"` + Password string `long:"password" description:"The password used to arrive at the HashedControlPassword for the control port. If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` V2 bool `long:"v2" description:"Automatically set up a v2 onion service to listen for inbound connections"` V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` PrivateKeyPath string `long:"privatekeypath" description:"The path to the private key of the onion service being created"` diff --git a/docs/configuring_tor.md b/docs/configuring_tor.md index 02feb535b6..f6372f5947 100644 --- a/docs/configuring_tor.md +++ b/docs/configuring_tor.md @@ -2,7 +2,8 @@ 1. [Overview](#overview) 2. [Getting Started](#getting-started) 3. [Tor Stream Isolation](#tor-stream-isolation) -4. [Listening for Inbound Connections](#listening-for-inbound-connections) +4. [Authentication](#authentication) +5. [Listening for Inbound Connections](#listening-for-inbound-connections) ## Overview @@ -78,6 +79,8 @@ Tor: --tor.dns= The DNS server as host:port that Tor will use for SRV queries - NOTE must have TCP resolution enabled (default: soa.nodes.lightning.directory:53) --tor.streamisolation Enable Tor stream isolation by randomizing user credentials for each connection. --tor.control= The host:port that Tor is listening on for Tor control connections (default: localhost:9051) + --tor.targetipaddress= IP address that Tor should use as the target of the hidden service + --tor.password= The password used to arrive at the HashedControlPassword for the control port. If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one. --tor.v2 Automatically set up a v2 onion service to listen for inbound connections --tor.v3 Automatically set up a v3 onion service to listen for inbound connections --tor.privatekeypath= The path to the private key of the onion service being created @@ -133,6 +136,26 @@ specification of an additional argument: ⛰ ./lnd --tor.active --tor.streamisolation ``` +## Authentication + +In order for `lnd` to communicate with the Tor daemon securely, it must first +establish an authenticated connection. `lnd` supports the following Tor control +authentication methods (arguably, from most to least secure): + +* `SAFECOOKIE`: This authentication method relies on a cookie created and + stored by the Tor daemon and is the default assuming the Tor daemon supports + it by specifying `CookieAuthentication 1` in its configuration file. +* `HASHEDPASSWORD`: This authentication method is stateless as it relies on a + password hash scheme and may be useful if the Tor daemon is operating under a + separate host from the `lnd` node. The password hash can be obtained through + the Tor daemon with `tor --hash-password PASSWORD`, which should then be + specified in Tor's configuration file with `HashedControlPassword + PASSWORD_HASH`. Finally, to use it within `lnd`, the `--tor.password` flag + should be provided with the corresponding password. +* `NULL`: To bypass any authentication at all, this scheme can be used instead. + It doesn't require any additional flags to `lnd` or configuration options to + the Tor daemon. + ## Listening for Inbound Connections In order to listen for inbound connections through Tor, an onion service must be diff --git a/server.go b/server.go index bde65671ad..b62aa27df1 100644 --- a/server.go +++ b/server.go @@ -586,7 +586,10 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, // automatically create an onion service, we'll initiate our Tor // controller and establish a connection to the Tor server. if cfg.Tor.Active && (cfg.Tor.V2 || cfg.Tor.V3) { - s.torController = tor.NewController(cfg.Tor.Control, cfg.Tor.TargetIPAddress) + s.torController = tor.NewController( + cfg.Tor.Control, cfg.Tor.TargetIPAddress, + cfg.Tor.Password, + ) } chanGraph := chanDB.ChannelGraph() diff --git a/tor/README.md b/tor/README.md index 337f0159a4..49590c9a7d 100644 --- a/tor/README.md +++ b/tor/README.md @@ -8,8 +8,8 @@ Tor daemon. So far, supported functions include: * Routing DNS queries over Tor (A, AAAA, SRV). * Limited Tor Control functionality (synchronous messages only). So far, this includes: - * Support for SAFECOOKIE authentication only as a sane default. - * Creating v2 onion services. + * Support for SAFECOOKIE, HASHEDPASSWORD, and NULL authentication methods. + * Creating v2 and v3 onion services. In the future, the Tor Control functionality will be extended to support v3 onion services, asynchronous messages, etc. diff --git a/tor/controller.go b/tor/controller.go index 149e766b41..22a02fa9f2 100644 --- a/tor/controller.go +++ b/tor/controller.go @@ -36,6 +36,16 @@ const ( // must be running on. This is needed in order to create v3 onion // services through Tor's control port. MinTorVersion = "0.3.3.6" + + // authSafeCookie is the name of the SAFECOOKIE authentication method. + authSafeCookie = "SAFECOOKIE" + + // authHashedPassword is the name of the HASHEDPASSWORD authentication + // method. + authHashedPassword = "HASHEDPASSWORD" + + // authNull is the name of the NULL authentication method. + authNull = "NULL" ) var ( @@ -79,19 +89,30 @@ type Controller struct { // controller connections on. controlAddr string + // password, if non-empty, signals that the controller should attempt to + // authenticate itself with the backing Tor daemon through the + // HASHEDPASSWORD authentication method with this value. + password string + // version is the current version of the Tor server. version string - // The IP address which we tell the Tor server to use to connect to the LND node. - // This is required when the Tor server runs on another host, otherwise the service - // will not be reachable. + // targetIPAddress is the IP address which we tell the Tor server to use + // to connect to the LND node. This is required when the Tor server + // runs on another host, otherwise the service will not be reachable. targetIPAddress string } // NewController returns a new Tor controller that will be able to interact with // a Tor server. -func NewController(controlAddr string, targetIPAddress string) *Controller { - return &Controller{controlAddr: controlAddr, targetIPAddress: targetIPAddress} +func NewController(controlAddr string, targetIPAddress string, + password string) *Controller { + + return &Controller{ + controlAddr: controlAddr, + targetIPAddress: targetIPAddress, + password: password, + } } // Start establishes and authenticates the connection between the controller and @@ -168,26 +189,74 @@ func parseTorReply(reply string) map[string]string { } // authenticate authenticates the connection between the controller and the -// Tor server using the SAFECOOKIE or NULL authentication method. +// Tor server using either of the following supported authentication methods +// depending on its configuration: SAFECOOKIE, HASHEDPASSWORD, and NULL. func (c *Controller) authenticate() error { + protocolInfo, err := c.protocolInfo() + if err != nil { + return err + } + + // With the version retrieved, we'll cache it now in case it needs to be + // used later on. + c.version = protocolInfo.version() + + switch { + // If a password was provided, then we should attempt to use the + // HASHEDPASSWORD authentication method. + case c.password != "": + if !protocolInfo.supportsAuthMethod(authHashedPassword) { + return fmt.Errorf("%v authentication method not "+ + "supported", authHashedPassword) + } + + return c.authenticateViaHashedPassword() + + // Otherwise, attempt to authentication via the SAFECOOKIE method as it + // provides the most security. + case protocolInfo.supportsAuthMethod(authSafeCookie): + return c.authenticateViaSafeCookie(protocolInfo) + + // Fallback to the NULL method if any others aren't supported. + case protocolInfo.supportsAuthMethod(authNull): + return c.authenticateViaNull() + + // No supported authentication methods, fail. + default: + return errors.New("the Tor server must be configured with " + + "NULL, SAFECOOKIE, or HASHEDPASSWORD authentication") + } +} + +// authenticateViaNull authenticates the controller with the Tor server using +// the NULL authentication method. +func (c *Controller) authenticateViaNull() error { + _, _, err := c.sendCommand("AUTHENTICATE") + return err +} + +// authenticateViaHashedPassword authenticates the controller with the Tor +// server using the HASHEDPASSWORD authentication method. +func (c *Controller) authenticateViaHashedPassword() error { + cmd := fmt.Sprintf("AUTHENTICATE \"%s\"", c.password) + _, _, err := c.sendCommand(cmd) + return err +} + +// authenticateViaSafeCookie authenticates the controller with the Tor server +// using the SAFECOOKIE authentication method. +func (c *Controller) authenticateViaSafeCookie(info protocolInfo) error { // Before proceeding to authenticate the connection, we'll retrieve // the authentication cookie of the Tor server. This will be used // throughout the authentication routine. We do this before as once the // authentication routine has begun, it is not possible to retrieve it // mid-way. - cookie, err := c.getAuthCookie() + cookie, err := c.getAuthCookie(info) if err != nil { return fmt.Errorf("unable to retrieve authentication cookie: "+ "%v", err) } - // If cookie is empty and there's no error, we have a NULL - // authentication method that we should use instead. - if len(cookie) == 0 { - _, _, err := c.sendCommand("AUTHENTICATE") - return err - } - // Authenticating using the SAFECOOKIE authentication method is a two // step process. We'll kick off the authentication routine by sending // the AUTHCHALLENGE command followed by a hex-encoded 32-byte nonce. @@ -272,36 +341,15 @@ func (c *Controller) authenticate() error { } // getAuthCookie retrieves the authentication cookie in bytes from the Tor -// server. Cookie authentication must be enabled for this to work. The boolean -func (c *Controller) getAuthCookie() ([]byte, error) { - // Retrieve the authentication methods currently supported by the Tor - // server. - authMethods, cookieFilePath, version, err := c.ProtocolInfo() - if err != nil { - return nil, err - } - - // With the version retrieved, we'll cache it now in case it needs to be - // used later on. - c.version = version - - // Ensure that the Tor server supports the SAFECOOKIE authentication - // method or the NULL method. If NULL, we don't need the cookie info - // below this loop, so we just return. - safeCookieSupport := false - for _, authMethod := range authMethods { - if authMethod == "SAFECOOKIE" { - safeCookieSupport = true - } - if authMethod == "NULL" { - return nil, nil - } - } - - if !safeCookieSupport { - return nil, errors.New("the Tor server is currently not " + - "configured for cookie or null authentication") +// server. Cookie authentication must be enabled for this to work. +func (c *Controller) getAuthCookie(info protocolInfo) ([]byte, error) { + // Retrieve the cookie file path from the PROTOCOLINFO reply. + cookieFilePath, ok := info["COOKIEFILE"] + if !ok { + return nil, errors.New("COOKIEFILE not found in PROTOCOLINFO " + + "reply") } + cookieFilePath = strings.Trim(cookieFilePath, "\"") // Read the cookie from the file and ensure it has the correct length. cookie, err := ioutil.ReadFile(cookieFilePath) @@ -360,48 +408,36 @@ func supportsV3(version string) error { return nil } -// ProtocolInfo returns the different authentication methods supported by the -// Tor server and the version of the Tor server. -func (c *Controller) ProtocolInfo() ([]string, string, string, error) { - // We'll start off by sending the "PROTOCOLINFO" command to the Tor - // server. We should receive a reply of the following format: - // - // METHODS=COOKIE,SAFECOOKIE - // COOKIEFILE="/home/user/.tor/control_auth_cookie" - // VERSION Tor="0.3.2.10" - // - // We're interested in retrieving all of these fields, so we'll parse - // our reply to do so. - cmd := fmt.Sprintf("PROTOCOLINFO %d", ProtocolInfoVersion) - _, reply, err := c.sendCommand(cmd) - if err != nil { - return nil, "", "", err - } - - info := parseTorReply(reply) - methods, ok := info["METHODS"] - if !ok { - return nil, "", "", errors.New("auth methods not found in " + - "reply") - } +// protocolInfo is encompasses the details of a response to a PROTOCOLINFO +// command. +type protocolInfo map[string]string - cookieFile, ok := info["COOKIEFILE"] - if !ok && !strings.Contains(methods, "NULL") { - return nil, "", "", errors.New("cookie file path not found " + - "in reply") - } +// version returns the Tor version as reported by the server. +func (i protocolInfo) version() string { + version := i["Tor"] + return strings.Trim(version, "\"") +} - version, ok := info["Tor"] +// supportsAuthMethod determines whether the Tor server supports the given +// authentication method. +func (i protocolInfo) supportsAuthMethod(method string) bool { + methods, ok := i["METHODS"] if !ok { - return nil, "", "", errors.New("Tor version not found in reply") + return false } + return strings.Contains(methods, method) +} - // Finally, we'll clean up the results before returning them. - authMethods := strings.Split(methods, ",") - cookieFilePath := strings.Trim(cookieFile, "\"") - torVersion := strings.Trim(version, "\"") +// protocolInfo sends a "PROTOCOLINFO" command to the Tor server and returns its +// response. +func (c *Controller) protocolInfo() (protocolInfo, error) { + cmd := fmt.Sprintf("PROTOCOLINFO %d", ProtocolInfoVersion) + _, reply, err := c.sendCommand(cmd) + if err != nil { + return nil, err + } - return authMethods, cookieFilePath, torVersion, nil + return protocolInfo(parseTorReply(reply)), nil } // OnionType denotes the type of the onion service. From ae815f221facb67be8f038e16fdf0ed0ab02266d Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 9 Mar 2020 18:34:09 -0700 Subject: [PATCH 198/562] input/size: correct NestedP2WSHSize comment --- input/size.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/size.go b/input/size.go index a9406f8a9c..7f9444b6c1 100644 --- a/input/size.go +++ b/input/size.go @@ -38,7 +38,7 @@ const ( // NestedP2WSHSize 35 bytes // - OP_DATA: 1 byte (P2WSHSize) - // - P2WSHWitnessProgram: 35 bytes + // - P2WSHWitnessProgram: 34 bytes NestedP2WSHSize = 1 + P2WSHSize // P2PKHOutputSize 34 bytes From fdcb30e57f1864f2c9959ba081cadc576ddf81cf Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 Mar 2020 15:35:25 +0100 Subject: [PATCH 199/562] lnrpc: run clang-format --- lnrpc/chainrpc/chainnotifier.pb.go | 3 +- lnrpc/chainrpc/chainnotifier.proto | 3 +- lnrpc/invoicesrpc/invoices.pb.go | 3 +- lnrpc/invoicesrpc/invoices.proto | 8 +- lnrpc/routerrpc/router.proto | 33 ++-- lnrpc/rpc.pb.go | 139 ++++++++++------ lnrpc/rpc.proto | 255 ++++++++++++++++++----------- lnrpc/rpc.swagger.json | 102 ++++++------ lnrpc/signrpc/signer.pb.go | 3 +- lnrpc/signrpc/signer.proto | 17 +- lnrpc/walletrpc/walletkit.proto | 2 +- lnrpc/wtclientrpc/wtclient.proto | 2 +- 12 files changed, 340 insertions(+), 230 deletions(-) diff --git a/lnrpc/chainrpc/chainnotifier.pb.go b/lnrpc/chainrpc/chainnotifier.pb.go index 81cc9276f3..db9c13943c 100644 --- a/lnrpc/chainrpc/chainnotifier.pb.go +++ b/lnrpc/chainrpc/chainnotifier.pb.go @@ -106,7 +106,8 @@ type ConfDetails struct { RawTx []byte `protobuf:"bytes,1,opt,name=raw_tx,json=rawTx,proto3" json:"raw_tx,omitempty"` // The hash of the block in which the confirmed transaction was included in. BlockHash []byte `protobuf:"bytes,2,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - // The height of the block in which the confirmed transaction was included in. + // The height of the block in which the confirmed transaction was included + // in. BlockHeight uint32 `protobuf:"varint,3,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` // The index of the confirmed transaction within the transaction. TxIndex uint32 `protobuf:"varint,4,opt,name=tx_index,json=txIndex,proto3" json:"tx_index,omitempty"` diff --git a/lnrpc/chainrpc/chainnotifier.proto b/lnrpc/chainrpc/chainnotifier.proto index a0d07951cc..5cc8a0da26 100644 --- a/lnrpc/chainrpc/chainnotifier.proto +++ b/lnrpc/chainrpc/chainnotifier.proto @@ -39,7 +39,8 @@ message ConfDetails { // The hash of the block in which the confirmed transaction was included in. bytes block_hash = 2; - // The height of the block in which the confirmed transaction was included in. + // The height of the block in which the confirmed transaction was included + // in. uint32 block_height = 3; // The index of the confirmed transaction within the transaction. diff --git a/lnrpc/invoicesrpc/invoices.pb.go b/lnrpc/invoicesrpc/invoices.pb.go index 97c25467c8..1dbc8ccb2d 100644 --- a/lnrpc/invoicesrpc/invoices.pb.go +++ b/lnrpc/invoicesrpc/invoices.pb.go @@ -275,7 +275,8 @@ func (m *AddHoldInvoiceResp) GetPaymentRequest() string { } type SettleInvoiceMsg struct { - /// Externally discovered pre-image that should be used to settle the hold invoice. + /// Externally discovered pre-image that should be used to settle the hold + /// invoice. Preimage []byte `protobuf:"bytes,1,opt,name=preimage,proto3" json:"preimage,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` diff --git a/lnrpc/invoicesrpc/invoices.proto b/lnrpc/invoicesrpc/invoices.proto index 4876cb44b3..3c92802eae 100644 --- a/lnrpc/invoicesrpc/invoices.proto +++ b/lnrpc/invoicesrpc/invoices.proto @@ -15,10 +15,11 @@ service Invoices { to notify the client of state transitions of the specified invoice. Initially the current invoice state is always sent out. */ - rpc SubscribeSingleInvoice (SubscribeSingleInvoiceRequest) returns (stream lnrpc.Invoice); + rpc SubscribeSingleInvoice (SubscribeSingleInvoiceRequest) + returns (stream lnrpc.Invoice); /** - CancelInvoice cancels a currently open invoice. If the invoice is already + CancelInvoice cancels a currently open invoice. If the invoice is already canceled, this call will succeed. If the invoice is already settled, it will fail. */ @@ -106,7 +107,8 @@ message AddHoldInvoiceResp { } message SettleInvoiceMsg { - /// Externally discovered pre-image that should be used to settle the hold invoice. + /// Externally discovered pre-image that should be used to settle the hold + /// invoice. bytes preimage = 1; } diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 21f6ab668e..d5e53ff91a 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -19,7 +19,7 @@ message SendPaymentRequest { /** Number of millisatoshis to send. - + The fields amt and amt_msat are mutually exclusive. */ int64 amt_msat = 12; @@ -61,14 +61,14 @@ message SendPaymentRequest { int64 fee_limit_sat = 7; /** - The maximum number of millisatoshis that will be paid as a fee of the - payment. If this field is left to the default value of 0, only zero-fee - routes will be considered. This usually means single hop routes connecting - directly to the destination. To send the payment without a fee limit, use - max int here. - - The fields fee_limit_sat and fee_limit_msat are mutually exclusive. - */ + The maximum number of millisatoshis that will be paid as a fee of the + payment. If this field is left to the default value of 0, only zero-fee + routes will be considered. This usually means single hop routes connecting + directly to the destination. To send the payment without a fee limit, use + max int here. + + The fields fee_limit_sat and fee_limit_msat are mutually exclusive. + */ int64 fee_limit_msat = 13; /** @@ -82,7 +82,7 @@ message SendPaymentRequest { */ bytes last_hop_pubkey = 14; - /** + /** An optional maximum total time lock for the route. This should not exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of `--max-cltv-expiry` is enforced. @@ -94,7 +94,7 @@ message SendPaymentRequest { */ repeated lnrpc.RouteHint route_hints = 10; - /** + /** An optional field that can be used to pass an arbitrary set of TLV records to a peer which understands the new records. This can be used to pass application specific data during the payment attempt. Record types are @@ -160,7 +160,6 @@ enum PaymentState { FAILED_INSUFFICIENT_BALANCE = 6; } - message PaymentStatus { /// Current state the payment is in. PaymentState state = 1; @@ -181,7 +180,6 @@ message PaymentStatus { repeated lnrpc.HTLCAttempt htlcs = 4; } - message RouteFeeRequest { /** The destination once wishes to obtain a routing fee quote to. @@ -366,19 +364,22 @@ service Router { ResetMissionControl clears all mission control state and starts with a clean slate. */ - rpc ResetMissionControl (ResetMissionControlRequest) returns (ResetMissionControlResponse); + rpc ResetMissionControl (ResetMissionControlRequest) + returns (ResetMissionControlResponse); /** QueryMissionControl exposes the internal mission control state to callers. It is a development feature. */ - rpc QueryMissionControl (QueryMissionControlRequest) returns (QueryMissionControlResponse); + rpc QueryMissionControl (QueryMissionControlRequest) + returns (QueryMissionControlResponse); /** QueryProbability returns the current success probability estimate for a given node pair and amount. */ - rpc QueryProbability (QueryProbabilityRequest) returns (QueryProbabilityResponse); + rpc QueryProbability (QueryProbabilityRequest) + returns (QueryProbabilityResponse); /** BuildRoute builds a fully specified route based on a list of hop public diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 905f465a5e..1e631bd3b8 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -1648,27 +1648,32 @@ type ChannelAcceptRequest struct { ChainHash []byte `protobuf:"bytes,2,opt,name=chain_hash,json=chainHash,proto3" json:"chain_hash,omitempty"` /// The pending channel id. PendingChanId []byte `protobuf:"bytes,3,opt,name=pending_chan_id,json=pendingChanId,proto3" json:"pending_chan_id,omitempty"` - /// The funding amount in satoshis that initiator wishes to use in the channel. + /// The funding amount in satoshis that initiator wishes to use in the + /// channel. FundingAmt uint64 `protobuf:"varint,4,opt,name=funding_amt,json=fundingAmt,proto3" json:"funding_amt,omitempty"` /// The push amount of the proposed channel in millisatoshis. PushAmt uint64 `protobuf:"varint,5,opt,name=push_amt,json=pushAmt,proto3" json:"push_amt,omitempty"` /// The dust limit of the initiator's commitment tx. DustLimit uint64 `protobuf:"varint,6,opt,name=dust_limit,json=dustLimit,proto3" json:"dust_limit,omitempty"` - /// The maximum amount of coins in millisatoshis that can be pending in this channel. + /// The maximum amount of coins in millisatoshis that can be pending in this + /// channel. MaxValueInFlight uint64 `protobuf:"varint,7,opt,name=max_value_in_flight,json=maxValueInFlight,proto3" json:"max_value_in_flight,omitempty"` - /// The minimum amount of satoshis the initiator requires us to have at all times. + /// The minimum amount of satoshis the initiator requires us to have at all + /// times. ChannelReserve uint64 `protobuf:"varint,8,opt,name=channel_reserve,json=channelReserve,proto3" json:"channel_reserve,omitempty"` /// The smallest HTLC in millisatoshis that the initiator will accept. MinHtlc uint64 `protobuf:"varint,9,opt,name=min_htlc,json=minHtlc,proto3" json:"min_htlc,omitempty"` - /// The initial fee rate that the initiator suggests for both commitment transactions. + /// The initial fee rate that the initiator suggests for both commitment + /// transactions. FeePerKw uint64 `protobuf:"varint,10,opt,name=fee_per_kw,json=feePerKw,proto3" json:"fee_per_kw,omitempty"` //* - //The number of blocks to use for the relative time lock in the pay-to-self output - //of both commitment transactions. + //The number of blocks to use for the relative time lock in the pay-to-self + //output of both commitment transactions. CsvDelay uint32 `protobuf:"varint,11,opt,name=csv_delay,json=csvDelay,proto3" json:"csv_delay,omitempty"` /// The total number of incoming HTLC's that the initiator will accept. MaxAcceptedHtlcs uint32 `protobuf:"varint,12,opt,name=max_accepted_htlcs,json=maxAcceptedHtlcs,proto3" json:"max_accepted_htlcs,omitempty"` - /// A bit-field which the initiator uses to specify proposed channel behavior. + /// A bit-field which the initiator uses to specify proposed channel + /// behavior. ChannelFlags uint32 `protobuf:"varint,13,opt,name=channel_flags,json=channelFlags,proto3" json:"channel_flags,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -1990,7 +1995,8 @@ func (m *OutPoint) GetOutputIndex() uint32 { type LightningAddress struct { /// The identity pubkey of the Lightning node Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` - /// The network location of the lightning node, e.g. `69.69.69.69:1337` or `localhost:10011` + /// The network location of the lightning node, e.g. `69.69.69.69:1337` or + /// `localhost:10011` Host string `protobuf:"bytes,2,opt,name=host,proto3" json:"host,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -2039,7 +2045,8 @@ func (m *LightningAddress) GetHost() string { type EstimateFeeRequest struct { /// The map from addresses to amounts for the transaction. AddrToAmount map[string]int64 `protobuf:"bytes,1,rep,name=AddrToAmount,proto3" json:"AddrToAmount,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` - /// The target number of blocks that this transaction should be confirmed by. + /// The target number of blocks that this transaction should be confirmed + /// by. TargetConf int32 `protobuf:"varint,2,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -2137,9 +2144,11 @@ func (m *EstimateFeeResponse) GetFeerateSatPerByte() int64 { type SendManyRequest struct { /// The map from addresses to amounts AddrToAmount map[string]int64 `protobuf:"bytes,1,rep,name=AddrToAmount,proto3" json:"AddrToAmount,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` - /// The target number of blocks that this transaction should be confirmed by. + /// The target number of blocks that this transaction should be confirmed + /// by. TargetConf int32 `protobuf:"varint,3,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` - /// A manual fee rate set in sat/byte that should be used when crafting the transaction. + /// A manual fee rate set in sat/byte that should be used when crafting the + /// transaction. SatPerByte int64 `protobuf:"varint,5,opt,name=sat_per_byte,json=satPerByte,proto3" json:"sat_per_byte,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -2237,9 +2246,11 @@ type SendCoinsRequest struct { Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` /// The amount in satoshis to send Amount int64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` - /// The target number of blocks that this transaction should be confirmed by. + /// The target number of blocks that this transaction should be confirmed + /// by. TargetConf int32 `protobuf:"varint,3,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` - /// A manual fee rate set in sat/byte that should be used when crafting the transaction. + /// A manual fee rate set in sat/byte that should be used when crafting the + /// transaction. SatPerByte int64 `protobuf:"varint,5,opt,name=sat_per_byte,json=satPerByte,proto3" json:"sat_per_byte,omitempty"` //* //If set, then the amount field will be ignored, and lnd will attempt to @@ -2993,7 +3004,8 @@ type Channel struct { Lifetime int64 `protobuf:"varint,23,opt,name=lifetime,proto3" json:"lifetime,omitempty"` //* //The number of seconds that the remote peer has been observed as being online - //by the channel scoring system over the lifetime of the channel [EXPERIMENTAL]. + //by the channel scoring system over the lifetime of the channel + //[EXPERIMENTAL]. Uptime int64 `protobuf:"varint,24,opt,name=uptime,proto3" json:"uptime,omitempty"` //* //Close address is the address that we will enforce payout to on cooperative @@ -4273,11 +4285,14 @@ type CloseChannelRequest struct { //will be able to generate a signature for Alice's version of the commitment //transaction. ChannelPoint *ChannelPoint `protobuf:"bytes,1,opt,name=channel_point,json=channelPoint,proto3" json:"channel_point,omitempty"` - /// If true, then the channel will be closed forcibly. This means the current commitment transaction will be signed and broadcast. + /// If true, then the channel will be closed forcibly. This means the + /// current commitment transaction will be signed and broadcast. Force bool `protobuf:"varint,2,opt,name=force,proto3" json:"force,omitempty"` - /// The target number of blocks that the closure transaction should be confirmed by. + /// The target number of blocks that the closure transaction should be + /// confirmed by. TargetConf int32 `protobuf:"varint,3,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` - /// A manual fee rate set in sat/byte that should be used when crafting the closure transaction. + /// A manual fee rate set in sat/byte that should be used when crafting the + /// closure transaction. SatPerByte int64 `protobuf:"varint,4,opt,name=sat_per_byte,json=satPerByte,proto3" json:"sat_per_byte,omitempty"` // //An optional address to send funds to in the case of a cooperative close. @@ -4488,21 +4503,29 @@ type OpenChannelRequest struct { NodePubkeyString string `protobuf:"bytes,3,opt,name=node_pubkey_string,json=nodePubkeyString,proto3" json:"node_pubkey_string,omitempty"` // Deprecated: Do not use. /// The number of satoshis the wallet should commit to the channel LocalFundingAmount int64 `protobuf:"varint,4,opt,name=local_funding_amount,json=localFundingAmount,proto3" json:"local_funding_amount,omitempty"` - /// The number of satoshis to push to the remote side as part of the initial commitment state + /// The number of satoshis to push to the remote side as part of the initial + /// commitment state PushSat int64 `protobuf:"varint,5,opt,name=push_sat,json=pushSat,proto3" json:"push_sat,omitempty"` - /// The target number of blocks that the funding transaction should be confirmed by. + /// The target number of blocks that the funding transaction should be + /// confirmed by. TargetConf int32 `protobuf:"varint,6,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` - /// A manual fee rate set in sat/byte that should be used when crafting the funding transaction. + /// A manual fee rate set in sat/byte that should be used when crafting the + /// funding transaction. SatPerByte int64 `protobuf:"varint,7,opt,name=sat_per_byte,json=satPerByte,proto3" json:"sat_per_byte,omitempty"` - /// Whether this channel should be private, not announced to the greater network. + /// Whether this channel should be private, not announced to the greater + /// network. Private bool `protobuf:"varint,8,opt,name=private,proto3" json:"private,omitempty"` - /// The minimum value in millisatoshi we will require for incoming HTLCs on the channel. + /// The minimum value in millisatoshi we will require for incoming HTLCs on + /// the channel. MinHtlcMsat int64 `protobuf:"varint,9,opt,name=min_htlc_msat,json=minHtlcMsat,proto3" json:"min_htlc_msat,omitempty"` - /// The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size. + /// The delay we require on the remote's commitment transaction. If this is + /// not set, it will be scaled automatically with the channel size. RemoteCsvDelay uint32 `protobuf:"varint,10,opt,name=remote_csv_delay,json=remoteCsvDelay,proto3" json:"remote_csv_delay,omitempty"` - /// The minimum number of confirmations each one of your outputs used for the funding transaction must satisfy. + /// The minimum number of confirmations each one of your outputs used for + /// the funding transaction must satisfy. MinConfs int32 `protobuf:"varint,11,opt,name=min_confs,json=minConfs,proto3" json:"min_confs,omitempty"` - /// Whether unconfirmed outputs should be used as inputs for the funding transaction. + /// Whether unconfirmed outputs should be used as inputs for the funding + /// transaction. SpendUnconfirmed bool `protobuf:"varint,12,opt,name=spend_unconfirmed,json=spendUnconfirmed,proto3" json:"spend_unconfirmed,omitempty"` // //Close address is an optional address which specifies the address to which @@ -5333,7 +5356,8 @@ type PendingChannelsResponse_PendingChannel struct { Capacity int64 `protobuf:"varint,3,opt,name=capacity,proto3" json:"capacity,omitempty"` LocalBalance int64 `protobuf:"varint,4,opt,name=local_balance,json=localBalance,proto3" json:"local_balance,omitempty"` RemoteBalance int64 `protobuf:"varint,5,opt,name=remote_balance,json=remoteBalance,proto3" json:"remote_balance,omitempty"` - /// The minimum satoshis this node is required to reserve in its balance. + /// The minimum satoshis this node is required to reserve in its + /// balance. LocalChanReserveSat int64 `protobuf:"varint,6,opt,name=local_chan_reserve_sat,json=localChanReserveSat,proto3" json:"local_chan_reserve_sat,omitempty"` //* //The minimum satoshis the other node is required to reserve in its @@ -9485,9 +9509,11 @@ type ChannelFeeReport struct { ChannelPoint string `protobuf:"bytes,1,opt,name=channel_point,json=channelPoint,proto3" json:"channel_point,omitempty"` /// The base fee charged regardless of the number of milli-satoshis sent. BaseFeeMsat int64 `protobuf:"varint,2,opt,name=base_fee_msat,json=baseFeeMsat,proto3" json:"base_fee_msat,omitempty"` - /// The amount charged per milli-satoshis transferred expressed in millionths of a satoshi. + /// The amount charged per milli-satoshis transferred expressed in + /// millionths of a satoshi. FeePerMil int64 `protobuf:"varint,3,opt,name=fee_per_mil,json=feePerMil,proto3" json:"fee_per_mil,omitempty"` - /// The effective fee rate in milli-satoshis. Computed by dividing the fee_per_mil value by 1 million. + /// The effective fee rate in milli-satoshis. Computed by dividing the + /// fee_per_mil value by 1 million. FeeRate float64 `protobuf:"fixed64,4,opt,name=fee_rate,json=feeRate,proto3" json:"fee_rate,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -9555,13 +9581,17 @@ func (m *ChannelFeeReport) GetFeeRate() float64 { } type FeeReportResponse struct { - /// An array of channel fee reports which describes the current fee schedule for each channel. + /// An array of channel fee reports which describes the current fee schedule + /// for each channel. ChannelFees []*ChannelFeeReport `protobuf:"bytes,1,rep,name=channel_fees,json=channelFees,proto3" json:"channel_fees,omitempty"` - /// The total amount of fee revenue (in satoshis) the switch has collected over the past 24 hrs. + /// The total amount of fee revenue (in satoshis) the switch has collected + /// over the past 24 hrs. DayFeeSum uint64 `protobuf:"varint,2,opt,name=day_fee_sum,json=dayFeeSum,proto3" json:"day_fee_sum,omitempty"` - /// The total amount of fee revenue (in satoshis) the switch has collected over the past 1 week. + /// The total amount of fee revenue (in satoshis) the switch has collected + /// over the past 1 week. WeekFeeSum uint64 `protobuf:"varint,3,opt,name=week_fee_sum,json=weekFeeSum,proto3" json:"week_fee_sum,omitempty"` - /// The total amount of fee revenue (in satoshis) the switch has collected over the past 1 month. + /// The total amount of fee revenue (in satoshis) the switch has collected + /// over the past 1 month. MonthFeeSum uint64 `protobuf:"varint,4,opt,name=month_fee_sum,json=monthFeeSum,proto3" json:"month_fee_sum,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -9628,13 +9658,16 @@ type PolicyUpdateRequest struct { Scope isPolicyUpdateRequest_Scope `protobuf_oneof:"scope"` /// The base fee charged regardless of the number of milli-satoshis sent. BaseFeeMsat int64 `protobuf:"varint,3,opt,name=base_fee_msat,json=baseFeeMsat,proto3" json:"base_fee_msat,omitempty"` - /// The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6. + /// The effective fee rate in milli-satoshis. The precision of this value + /// goes up to 6 decimal places, so 1e-6. FeeRate float64 `protobuf:"fixed64,4,opt,name=fee_rate,json=feeRate,proto3" json:"fee_rate,omitempty"` /// The required timelock delta for HTLCs forwarded over the channel. TimeLockDelta uint32 `protobuf:"varint,5,opt,name=time_lock_delta,json=timeLockDelta,proto3" json:"time_lock_delta,omitempty"` - /// If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged. + /// If set, the maximum HTLC size in milli-satoshis. If unset, the maximum + /// HTLC will be unchanged. MaxHtlcMsat uint64 `protobuf:"varint,6,opt,name=max_htlc_msat,json=maxHtlcMsat,proto3" json:"max_htlc_msat,omitempty"` - /// The minimum HTLC size in milli-satoshis. Only applied if min_htlc_msat_specified is true. + /// The minimum HTLC size in milli-satoshis. Only applied if + /// min_htlc_msat_specified is true. MinHtlcMsat uint64 `protobuf:"varint,7,opt,name=min_htlc_msat,json=minHtlcMsat,proto3" json:"min_htlc_msat,omitempty"` /// If true, min_htlc_msat is applied. MinHtlcMsatSpecified bool `protobuf:"varint,8,opt,name=min_htlc_msat_specified,json=minHtlcMsatSpecified,proto3" json:"min_htlc_msat_specified,omitempty"` @@ -9787,11 +9820,17 @@ func (m *PolicyUpdateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_PolicyUpdateResponse proto.InternalMessageInfo type ForwardingHistoryRequest struct { - /// Start time is the starting point of the forwarding history request. All records beyond this point will be included, respecting the end time, and the index offset. + /// Start time is the starting point of the forwarding history request. All + /// records beyond this point will be included, respecting the end time, and + /// the index offset. StartTime uint64 `protobuf:"varint,1,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` - /// End time is the end point of the forwarding history request. The response will carry at most 50k records between the start time and the end time. The index offset can be used to implement pagination. + /// End time is the end point of the forwarding history request. The + /// response will carry at most 50k records between the start time and the + /// end time. The index offset can be used to implement pagination. EndTime uint64 `protobuf:"varint,2,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` - /// Index offset is the offset in the time series to start at. As each response can only contain 50k records, callers can use this to skip around within a packed time series. + /// Index offset is the offset in the time series to start at. As each + /// response can only contain 50k records, callers can use this to skip + /// around within a packed time series. IndexOffset uint32 `protobuf:"varint,3,opt,name=index_offset,json=indexOffset,proto3" json:"index_offset,omitempty"` /// The max number of events to return in the response to this query. NumMaxEvents uint32 `protobuf:"varint,4,opt,name=num_max_events,json=numMaxEvents,proto3" json:"num_max_events,omitempty"` @@ -9854,23 +9893,29 @@ func (m *ForwardingHistoryRequest) GetNumMaxEvents() uint32 { } type ForwardingEvent struct { - /// Timestamp is the time (unix epoch offset) that this circuit was completed. + /// Timestamp is the time (unix epoch offset) that this circuit was + /// completed. Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` /// The incoming channel ID that carried the HTLC that created the circuit. ChanIdIn uint64 `protobuf:"varint,2,opt,name=chan_id_in,json=chanIdIn,proto3" json:"chan_id_in,omitempty"` - /// The outgoing channel ID that carried the preimage that completed the circuit. + /// The outgoing channel ID that carried the preimage that completed the + /// circuit. ChanIdOut uint64 `protobuf:"varint,4,opt,name=chan_id_out,json=chanIdOut,proto3" json:"chan_id_out,omitempty"` - /// The total amount (in satoshis) of the incoming HTLC that created half the circuit. + /// The total amount (in satoshis) of the incoming HTLC that created half + /// the circuit. AmtIn uint64 `protobuf:"varint,5,opt,name=amt_in,json=amtIn,proto3" json:"amt_in,omitempty"` - /// The total amount (in satoshis) of the outgoing HTLC that created the second half of the circuit. + /// The total amount (in satoshis) of the outgoing HTLC that created the + /// second half of the circuit. AmtOut uint64 `protobuf:"varint,6,opt,name=amt_out,json=amtOut,proto3" json:"amt_out,omitempty"` /// The total fee (in satoshis) that this payment circuit carried. Fee uint64 `protobuf:"varint,7,opt,name=fee,proto3" json:"fee,omitempty"` /// The total fee (in milli-satoshis) that this payment circuit carried. FeeMsat uint64 `protobuf:"varint,8,opt,name=fee_msat,json=feeMsat,proto3" json:"fee_msat,omitempty"` - /// The total amount (in milli-satoshis) of the incoming HTLC that created half the circuit. + /// The total amount (in milli-satoshis) of the incoming HTLC that created + /// half the circuit. AmtInMsat uint64 `protobuf:"varint,9,opt,name=amt_in_msat,json=amtInMsat,proto3" json:"amt_in_msat,omitempty"` - /// The total amount (in milli-satoshis) of the outgoing HTLC that created the second half of the circuit. + /// The total amount (in milli-satoshis) of the outgoing HTLC that created + /// the second half of the circuit. AmtOutMsat uint64 `protobuf:"varint,10,opt,name=amt_out_msat,json=amtOutMsat,proto3" json:"amt_out_msat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -9966,9 +10011,11 @@ func (m *ForwardingEvent) GetAmtOutMsat() uint64 { } type ForwardingHistoryResponse struct { - /// A list of forwarding events from the time slice of the time series specified in the request. + /// A list of forwarding events from the time slice of the time series + /// specified in the request. ForwardingEvents []*ForwardingEvent `protobuf:"bytes,1,rep,name=forwarding_events,json=forwardingEvents,proto3" json:"forwarding_events,omitempty"` - /// The index of the last time in the set of returned forwarding events. Can be used to seek further, pagination style. + /// The index of the last time in the set of returned forwarding events. Can + /// be used to seek further, pagination style. LastOffsetIndex uint32 `protobuf:"varint,2,opt,name=last_offset_index,json=lastOffsetIndex,proto3" json:"last_offset_index,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index ae6affc5dd..913d09c9cd 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -10,19 +10,19 @@ option go_package = "github.com/lightningnetwork/lnd/lnrpc"; * Comments in this file will be directly parsed into the API * Documentation as descriptions of the associated method, message, or field. * These descriptions should go right above the definition of the object, and - * can be in either block or /// comment format. - * + * can be in either block or /// comment format. + * * One edge case exists where a // comment followed by a /// comment in the * next line will cause the description not to show up in the documentation. In * that instance, simply separate the two comments with a blank line. - * + * * An RPC method can be matched to an lncli command by placing a line in the * beginning of the description in exactly the following format: * lncli: `methodname` - * + * * Failure to specify the exact name of the command will cause documentation * generation to fail. - * + * * More information on how exactly the gRPC documentation is generated from * this proto file can be found here: * https://github.com/lightninglabs/lightning-api @@ -47,7 +47,7 @@ service WalletUnlocker { }; } - /** + /** InitWallet is used when lnd is starting up for the first time to fully initialize the daemon and its internal wallet. At the very least a wallet password must be provided. This will be used to encrypt sensitive material @@ -83,7 +83,8 @@ service WalletUnlocker { ChangePassword changes the password of the encrypted wallet. This will automatically unlock the wallet database if successful. */ - rpc ChangePassword (ChangePasswordRequest) returns (ChangePasswordResponse) { + rpc ChangePassword (ChangePasswordRequest) + returns (ChangePasswordResponse) { option (google.api.http) = { post: "/v1/changepassword" body: "*" @@ -230,7 +231,8 @@ service Lightning { ChannelBalance returns the total funds available across all open channels in satoshis. */ - rpc ChannelBalance (ChannelBalanceRequest) returns (ChannelBalanceResponse) { + rpc ChannelBalance (ChannelBalanceRequest) + returns (ChannelBalanceResponse) { option (google.api.http) = { get: "/v1/balance/channels" }; @@ -272,7 +274,7 @@ service Lightning { /** lncli: `listunspent` ListUnspent returns a list of all utxos spendable by the wallet with a - number of confirmations between the specified minimum and maximum. + number of confirmations between the specified minimum and maximum. */ rpc ListUnspent (ListUnspentRequest) returns (ListUnspentResponse) { option (google.api.http) = { @@ -285,7 +287,8 @@ service Lightning { the client in which any newly discovered transactions relevant to the wallet are sent over. */ - rpc SubscribeTransactions (GetTransactionsRequest) returns (stream Transaction); + rpc SubscribeTransactions (GetTransactionsRequest) + returns (stream Transaction); /** lncli: `sendmany` SendMany handles a request for a transaction that creates multiple specified @@ -346,7 +349,8 @@ service Lightning { given pubKey. In the case that we currently have a pending or active channel with the target peer, then this action will be not be allowed. */ - rpc DisconnectPeer (DisconnectPeerRequest) returns (DisconnectPeerResponse) { + rpc DisconnectPeer (DisconnectPeerRequest) + returns (DisconnectPeerResponse) { option (google.api.http) = { delete: "/v1/peers/{pub_key}" }; @@ -386,9 +390,10 @@ service Lightning { workflow and is waiting for confirmations for the funding txn, or is in the process of closure, either initiated cooperatively or non-cooperatively. */ - rpc PendingChannels (PendingChannelsRequest) returns (PendingChannelsResponse) { + rpc PendingChannels (PendingChannelsRequest) + returns (PendingChannelsResponse) { option (google.api.http) = { - get: "/v1/channels/pending" + get: "/v1/channels/pending" }; } @@ -408,13 +413,15 @@ service Lightning { sent over. Events include new active channels, inactive channels, and closed channels. */ - rpc SubscribeChannelEvents (ChannelEventSubscription) returns (stream ChannelEventUpdate); + rpc SubscribeChannelEvents (ChannelEventSubscription) + returns (stream ChannelEventUpdate); /** lncli: `closedchannels` ClosedChannels returns a description of all the closed channels that this node was a participant in. */ - rpc ClosedChannels (ClosedChannelsRequest) returns (ClosedChannelsResponse) { + rpc ClosedChannels (ClosedChannelsRequest) + returns (ClosedChannelsResponse) { option (google.api.http) = { get: "/v1/channels/closed" }; @@ -464,7 +471,8 @@ service Lightning { node operators to specify their own criteria for accepting inbound channels through a single persistent connection. */ - rpc ChannelAcceptor (stream ChannelAcceptResponse) returns (stream ChannelAcceptRequest); + rpc ChannelAcceptor (stream ChannelAcceptResponse) + returns (stream ChannelAcceptRequest); /** lncli: `closechannel` CloseChannel attempts to close an active channel identified by its channel @@ -487,7 +495,8 @@ service Lightning { channels due to bugs fixed in newer versions of lnd. Only available when in debug builds of lnd. */ - rpc AbandonChannel (AbandonChannelRequest) returns (AbandonChannelResponse) { + rpc AbandonChannel (AbandonChannelRequest) + returns (AbandonChannelResponse) { option (google.api.http) = { delete: "/v1/channels/abandon/{channel_point.funding_txid_str}/{channel_point.output_index}" }; @@ -611,7 +620,8 @@ service Lightning { /** DeleteAllPayments deletes all outgoing payments from DB. */ - rpc DeleteAllPayments (DeleteAllPaymentsRequest) returns (DeleteAllPaymentsResponse) { + rpc DeleteAllPayments (DeleteAllPaymentsRequest) + returns (DeleteAllPaymentsResponse) { option (google.api.http) = { delete: "/v1/payments" }; @@ -690,7 +700,8 @@ service Lightning { channels being advertised, updates in the routing policy for a directional channel edge, and when channels are closed on-chain. */ - rpc SubscribeChannelGraph (GraphTopologySubscription) returns (stream GraphTopologyUpdate); + rpc SubscribeChannelGraph (GraphTopologySubscription) + returns (stream GraphTopologyUpdate); /** lncli: `debuglevel` DebugLevel allows a caller to programmatically set the logging verbosity of @@ -714,7 +725,8 @@ service Lightning { UpdateChannelPolicy allows the caller to update the fee schedule and channel policies for all channels globally, or a particular channel. */ - rpc UpdateChannelPolicy (PolicyUpdateRequest) returns (PolicyUpdateResponse) { + rpc UpdateChannelPolicy (PolicyUpdateRequest) + returns (PolicyUpdateResponse) { option (google.api.http) = { post: "/v1/chanpolicy" body: "*" @@ -733,7 +745,8 @@ service Lightning { the index offset of the last entry. The index offset can be provided to the request to allow the caller to skip a series of records. */ - rpc ForwardingHistory (ForwardingHistoryRequest) returns (ForwardingHistoryResponse) { + rpc ForwardingHistory (ForwardingHistoryRequest) + returns (ForwardingHistoryResponse) { option (google.api.http) = { post: "/v1/switch" body: "*" @@ -748,7 +761,8 @@ service Lightning { method once lnd is running, or via the InitWallet and UnlockWallet methods from the WalletUnlocker service. */ - rpc ExportChannelBackup (ExportChannelBackupRequest) returns (ChannelBackup) { + rpc ExportChannelBackup (ExportChannelBackupRequest) + returns (ChannelBackup) { option (google.api.http) = { get: "/v1/channels/backup/{chan_point.funding_txid_str}/{chan_point.output_index}" }; @@ -761,7 +775,8 @@ service Lightning { as well, which contains a single encrypted blob containing the backups of each channel. */ - rpc ExportAllChannelBackups (ChanBackupExportRequest) returns (ChanBackupSnapshot) { + rpc ExportAllChannelBackups (ChanBackupExportRequest) + returns (ChanBackupSnapshot) { option (google.api.http) = { get: "/v1/channels/backup" }; @@ -772,7 +787,8 @@ service Lightning { snapshot. This method will accept either a packed Single or a packed Multi. Specifying both will result in an error. */ - rpc VerifyChanBackup (ChanBackupSnapshot) returns (VerifyChanBackupResponse) { + rpc VerifyChanBackup (ChanBackupSnapshot) + returns (VerifyChanBackupResponse) { option (google.api.http) = { post: "/v1/channels/backup/verify" body: "*" @@ -785,7 +801,8 @@ service Lightning { remaining within the channel. If we are able to unpack the backup, then the new channel will be shown under listchannels, as well as pending channels. */ - rpc RestoreChannelBackups (RestoreChanBackupRequest) returns (RestoreBackupResponse) { + rpc RestoreChannelBackups (RestoreChanBackupRequest) + returns (RestoreBackupResponse) { option (google.api.http) = { post: "/v1/channels/backup/restore" body: "*" @@ -801,7 +818,8 @@ service Lightning { ups, but the updated set of encrypted multi-chan backups with the closed channel(s) removed. */ - rpc SubscribeChannelBackups (ChannelBackupSubscription) returns (stream ChanBackupSnapshot) { + rpc SubscribeChannelBackups (ChannelBackupSubscription) + returns (stream ChanBackupSnapshot) { }; /** lncli: `bakemacaroon` @@ -853,7 +871,7 @@ message Transaction { /// The height of the block this transaction was included in int32 block_height = 5; - /// Timestamp of this transaction + /// Timestamp of this transaction int64 time_stamp = 6; /// Fees paid for this transaction @@ -964,14 +982,14 @@ message SendRequest { */ bytes last_hop_pubkey = 13; - /** + /** An optional maximum total time lock for the route. This should not exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of `--max-cltv-expiry` is enforced. */ uint32 cltv_limit = 10; - /** + /** An optional field that can be used to pass an arbitrary set of TLV records to a peer which understands the new records. This can be used to pass application specific data during the payment attempt. Record types are @@ -1029,7 +1047,8 @@ message ChannelAcceptRequest { /// The pending channel id. bytes pending_chan_id = 3; - /// The funding amount in satoshis that initiator wishes to use in the channel. + /// The funding amount in satoshis that initiator wishes to use in the + /// channel. uint64 funding_amt = 4; /// The push amount of the proposed channel in millisatoshis. @@ -1038,28 +1057,32 @@ message ChannelAcceptRequest { /// The dust limit of the initiator's commitment tx. uint64 dust_limit = 6; - /// The maximum amount of coins in millisatoshis that can be pending in this channel. + /// The maximum amount of coins in millisatoshis that can be pending in this + /// channel. uint64 max_value_in_flight = 7; - /// The minimum amount of satoshis the initiator requires us to have at all times. + /// The minimum amount of satoshis the initiator requires us to have at all + /// times. uint64 channel_reserve = 8; /// The smallest HTLC in millisatoshis that the initiator will accept. uint64 min_htlc = 9; - /// The initial fee rate that the initiator suggests for both commitment transactions. + /// The initial fee rate that the initiator suggests for both commitment + /// transactions. uint64 fee_per_kw = 10; /** - The number of blocks to use for the relative time lock in the pay-to-self output - of both commitment transactions. + The number of blocks to use for the relative time lock in the pay-to-self + output of both commitment transactions. */ uint32 csv_delay = 11; /// The total number of incoming HTLC's that the initiator will accept. uint32 max_accepted_htlcs = 12; - /// A bit-field which the initiator uses to specify proposed channel behavior. + /// A bit-field which the initiator uses to specify proposed channel + /// behavior. uint32 channel_flags = 13; } @@ -1105,7 +1128,8 @@ message LightningAddress { /// The identity pubkey of the Lightning node string pubkey = 1; - /// The network location of the lightning node, e.g. `69.69.69.69:1337` or `localhost:10011` + /// The network location of the lightning node, e.g. `69.69.69.69:1337` or + /// `localhost:10011` string host = 2; } @@ -1113,7 +1137,8 @@ message EstimateFeeRequest { /// The map from addresses to amounts for the transaction. map AddrToAmount = 1; - /// The target number of blocks that this transaction should be confirmed by. + /// The target number of blocks that this transaction should be confirmed + /// by. int32 target_conf = 2; } @@ -1129,10 +1154,12 @@ message SendManyRequest { /// The map from addresses to amounts map AddrToAmount = 1; - /// The target number of blocks that this transaction should be confirmed by. + /// The target number of blocks that this transaction should be confirmed + /// by. int32 target_conf = 3; - /// A manual fee rate set in sat/byte that should be used when crafting the transaction. + /// A manual fee rate set in sat/byte that should be used when crafting the + /// transaction. int64 sat_per_byte = 5; } message SendManyResponse { @@ -1141,16 +1168,18 @@ message SendManyResponse { } message SendCoinsRequest { - /// The address to send coins to + /// The address to send coins to string addr = 1; /// The amount in satoshis to send int64 amount = 2; - /// The target number of blocks that this transaction should be confirmed by. + /// The target number of blocks that this transaction should be confirmed + /// by. int32 target_conf = 3; - /// A manual fee rate set in sat/byte that should be used when crafting the transaction. + /// A manual fee rate set in sat/byte that should be used when crafting the + /// transaction. int64 sat_per_byte = 5; /** @@ -1177,7 +1206,7 @@ message ListUnspentResponse { repeated Utxo utxos = 1; } -/** +/** `AddressType` has to be one of: - `p2wkh`: Pay to witness key hash (`WITNESS_PUBKEY_HASH` = 0) @@ -1352,7 +1381,7 @@ message Channel { If true, then this channel uses the modern commitment format where the key in the output of the remote party does not change each state. This makes back up and recovery easier as when the channel is closed, the funds go - directly to that key. + directly to that key. */ bool static_remote_key = 22; @@ -1365,7 +1394,8 @@ message Channel { /** The number of seconds that the remote peer has been observed as being online - by the channel scoring system over the lifetime of the channel [EXPERIMENTAL]. + by the channel scoring system over the lifetime of the channel + [EXPERIMENTAL]. */ int64 uptime = 24; @@ -1379,7 +1409,6 @@ message Channel { string close_address = 25; } - message ListChannelsRequest { bool active_only = 1; bool inactive_only = 2; @@ -1398,10 +1427,10 @@ message ListChannelsResponse { } message ChannelCloseSummary { - /// The outpoint (txid:index) of the funding transaction. + /// The outpoint (txid:index) of the funding transaction. string channel_point = 1; - /// The unique channel ID for the channel. + /// The unique channel ID for the channel. uint64 chan_id = 2 [jstype = JS_STRING]; /// The hash of the genesis block that this channel resides within. @@ -1548,7 +1577,6 @@ message PeerEvent { message GetInfoRequest { } message GetInfoResponse { - /// The version of the LND software that the node is running. string version = 14; @@ -1588,9 +1616,9 @@ message GetInfoResponse { // Whether we consider ourselves synced with the public channel graph. bool synced_to_graph = 18; - /** - Whether the current node is connected to testnet. This field is - deprecated and the network field should be used instead + /** + Whether the current node is connected to testnet. This field is + deprecated and the network field should be used instead **/ bool testnet = 10 [deprecated = true]; @@ -1642,13 +1670,16 @@ message CloseChannelRequest { */ ChannelPoint channel_point = 1; - /// If true, then the channel will be closed forcibly. This means the current commitment transaction will be signed and broadcast. + /// If true, then the channel will be closed forcibly. This means the + /// current commitment transaction will be signed and broadcast. bool force = 2; - /// The target number of blocks that the closure transaction should be confirmed by. + /// The target number of blocks that the closure transaction should be + /// confirmed by. int32 target_conf = 3; - /// A manual fee rate set in sat/byte that should be used when crafting the closure transaction. + /// A manual fee rate set in sat/byte that should be used when crafting the + /// closure transaction. int64 sat_per_byte = 4; /* @@ -1688,28 +1719,36 @@ message OpenChannelRequest { /// The number of satoshis the wallet should commit to the channel int64 local_funding_amount = 4; - /// The number of satoshis to push to the remote side as part of the initial commitment state + /// The number of satoshis to push to the remote side as part of the initial + /// commitment state int64 push_sat = 5; - /// The target number of blocks that the funding transaction should be confirmed by. + /// The target number of blocks that the funding transaction should be + /// confirmed by. int32 target_conf = 6; - /// A manual fee rate set in sat/byte that should be used when crafting the funding transaction. + /// A manual fee rate set in sat/byte that should be used when crafting the + /// funding transaction. int64 sat_per_byte = 7; - /// Whether this channel should be private, not announced to the greater network. + /// Whether this channel should be private, not announced to the greater + /// network. bool private = 8; - /// The minimum value in millisatoshi we will require for incoming HTLCs on the channel. + /// The minimum value in millisatoshi we will require for incoming HTLCs on + /// the channel. int64 min_htlc_msat = 9; - /// The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size. + /// The delay we require on the remote's commitment transaction. If this is + /// not set, it will be scaled automatically with the channel size. uint32 remote_csv_delay = 10; - /// The minimum number of confirmations each one of your outputs used for the funding transaction must satisfy. + /// The minimum number of confirmations each one of your outputs used for + /// the funding transaction must satisfy. int32 min_confs = 11; - /// Whether unconfirmed outputs should be used as inputs for the funding transaction. + /// Whether unconfirmed outputs should be used as inputs for the funding + /// transaction. bool spend_unconfirmed = 12; /* @@ -1756,12 +1795,12 @@ message KeyLocator { message KeyDescriptor { /** - The raw bytes of the key being identified. + The raw bytes of the key being identified. */ bytes raw_key_bytes = 1; - /** - The key locator that identifies which key to use for signing. + /** + The key locator that identifies which key to use for signing. */ KeyLocator key_loc = 2; } @@ -1820,7 +1859,6 @@ message FundingStateStepResp { } message PendingHTLC { - /// The direction within the channel that the htlc was sent bool incoming = 1; @@ -1856,7 +1894,8 @@ message PendingChannelsResponse { int64 local_balance = 4; int64 remote_balance = 5; - /// The minimum satoshis this node is required to reserve in its balance. + /// The minimum satoshis this node is required to reserve in its + /// balance. int64 local_chan_reserve_sat = 6; /** @@ -2062,14 +2101,14 @@ message QueryRoutesRequest { */ repeated NodePair ignored_pairs = 10; - /** + /** An optional maximum total time lock for the route. If the source is empty or ourselves, this should not exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of `--max-cltv-expiry` is used as the limit. */ uint32 cltv_limit = 11; - /** + /** An optional field that can be used to pass an arbitrary set of TLV records to a peer which understands the new records. This can be used to pass application specific data during the payment attempt. If the destination @@ -2166,7 +2205,7 @@ message Hop { */ string pub_key = 8; - /** + /** If set to true, then this hop will be encoded using the new variable length TLV format. Note that if any custom tlv_records below are specified, then this field MUST be set to true for them to be encoded properly. @@ -2215,7 +2254,6 @@ route is only selected as valid if all the channels have sufficient capacity to carry the initial payment amount after fees are accounted for. */ message Route { - /** The cumulative (final) time lock across the entire route. This is the CLTV value that should be extended to the first hop in the route. All other hops @@ -2257,7 +2295,7 @@ message Route { } message NodeInfoRequest { - /// The 33-byte hex-encoded compressed public of the target node + /// The 33-byte hex-encoded compressed public of the target node string pub_key = 1; /// If true, will include all known channels associated with the node. @@ -2265,7 +2303,6 @@ message NodeInfoRequest { } message NodeInfo { - /** An individual vertex/node within the channel graph. A node is connected to other nodes by one or more channel edges emanating from it. As @@ -2322,7 +2359,6 @@ stored. The other portions relevant to routing policy of a channel are stored within a ChannelEdgePolicy for each direction of the channel. */ message ChannelEdge { - /** The unique channel ID for the channel. The first 3 bytes are the block height, the next 3 the index within the block, and the last 2 bytes are the @@ -2746,7 +2782,6 @@ message InvoiceSubscription { uint64 settle_index = 2; } - message Payment { /// The payment hash string payment_hash = 1; @@ -2851,7 +2886,6 @@ message AbandonChannelRequest { message AbandonChannelResponse { } - message DebugLevelRequest { bool show = 1; string level_spec = 2; @@ -2918,23 +2952,29 @@ message ChannelFeeReport { /// The base fee charged regardless of the number of milli-satoshis sent. int64 base_fee_msat = 2; - /// The amount charged per milli-satoshis transferred expressed in millionths of a satoshi. + /// The amount charged per milli-satoshis transferred expressed in + /// millionths of a satoshi. int64 fee_per_mil = 3; - /// The effective fee rate in milli-satoshis. Computed by dividing the fee_per_mil value by 1 million. + /// The effective fee rate in milli-satoshis. Computed by dividing the + /// fee_per_mil value by 1 million. double fee_rate = 4; } message FeeReportResponse { - /// An array of channel fee reports which describes the current fee schedule for each channel. + /// An array of channel fee reports which describes the current fee schedule + /// for each channel. repeated ChannelFeeReport channel_fees = 1; - /// The total amount of fee revenue (in satoshis) the switch has collected over the past 24 hrs. + /// The total amount of fee revenue (in satoshis) the switch has collected + /// over the past 24 hrs. uint64 day_fee_sum = 2; - /// The total amount of fee revenue (in satoshis) the switch has collected over the past 1 week. + /// The total amount of fee revenue (in satoshis) the switch has collected + /// over the past 1 week. uint64 week_fee_sum = 3; - /// The total amount of fee revenue (in satoshis) the switch has collected over the past 1 month. + /// The total amount of fee revenue (in satoshis) the switch has collected + /// over the past 1 month. uint64 month_fee_sum = 4; } @@ -2950,16 +2990,19 @@ message PolicyUpdateRequest { /// The base fee charged regardless of the number of milli-satoshis sent. int64 base_fee_msat = 3; - /// The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6. + /// The effective fee rate in milli-satoshis. The precision of this value + /// goes up to 6 decimal places, so 1e-6. double fee_rate = 4; /// The required timelock delta for HTLCs forwarded over the channel. uint32 time_lock_delta = 5; - /// If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged. + /// If set, the maximum HTLC size in milli-satoshis. If unset, the maximum + /// HTLC will be unchanged. uint64 max_htlc_msat = 6; - /// The minimum HTLC size in milli-satoshis. Only applied if min_htlc_msat_specified is true. + /// The minimum HTLC size in milli-satoshis. Only applied if + /// min_htlc_msat_specified is true. uint64 min_htlc_msat = 7; /// If true, min_htlc_msat is applied. @@ -2969,32 +3012,42 @@ message PolicyUpdateResponse { } message ForwardingHistoryRequest { - /// Start time is the starting point of the forwarding history request. All records beyond this point will be included, respecting the end time, and the index offset. + /// Start time is the starting point of the forwarding history request. All + /// records beyond this point will be included, respecting the end time, and + /// the index offset. uint64 start_time = 1; - /// End time is the end point of the forwarding history request. The response will carry at most 50k records between the start time and the end time. The index offset can be used to implement pagination. + /// End time is the end point of the forwarding history request. The + /// response will carry at most 50k records between the start time and the + /// end time. The index offset can be used to implement pagination. uint64 end_time = 2; - /// Index offset is the offset in the time series to start at. As each response can only contain 50k records, callers can use this to skip around within a packed time series. + /// Index offset is the offset in the time series to start at. As each + /// response can only contain 50k records, callers can use this to skip + /// around within a packed time series. uint32 index_offset = 3; /// The max number of events to return in the response to this query. uint32 num_max_events = 4; } message ForwardingEvent { - /// Timestamp is the time (unix epoch offset) that this circuit was completed. + /// Timestamp is the time (unix epoch offset) that this circuit was + /// completed. uint64 timestamp = 1; /// The incoming channel ID that carried the HTLC that created the circuit. uint64 chan_id_in = 2 [jstype = JS_STRING]; - /// The outgoing channel ID that carried the preimage that completed the circuit. + /// The outgoing channel ID that carried the preimage that completed the + /// circuit. uint64 chan_id_out = 4 [jstype = JS_STRING]; - /// The total amount (in satoshis) of the incoming HTLC that created half the circuit. + /// The total amount (in satoshis) of the incoming HTLC that created half + /// the circuit. uint64 amt_in = 5; - /// The total amount (in satoshis) of the outgoing HTLC that created the second half of the circuit. + /// The total amount (in satoshis) of the outgoing HTLC that created the + /// second half of the circuit. uint64 amt_out = 6; /// The total fee (in satoshis) that this payment circuit carried. @@ -3003,10 +3056,12 @@ message ForwardingEvent { /// The total fee (in milli-satoshis) that this payment circuit carried. uint64 fee_msat = 8; - /// The total amount (in milli-satoshis) of the incoming HTLC that created half the circuit. + /// The total amount (in milli-satoshis) of the incoming HTLC that created + /// half the circuit. uint64 amt_in_msat = 9; - /// The total amount (in milli-satoshis) of the outgoing HTLC that created the second half of the circuit. + /// The total amount (in milli-satoshis) of the outgoing HTLC that created + /// the second half of the circuit. uint64 amt_out_msat = 10; // TODO(roasbeef): add settlement latency? @@ -3014,10 +3069,12 @@ message ForwardingEvent { // * also list failures? } message ForwardingHistoryResponse { - /// A list of forwarding events from the time slice of the time series specified in the request. + /// A list of forwarding events from the time slice of the time series + /// specified in the request. repeated ForwardingEvent forwarding_events = 1; - /// The index of the last time in the set of returned forwarding events. Can be used to seek further, pagination style. + /// The index of the last time in the set of returned forwarding events. Can + /// be used to seek further, pagination style. uint32 last_offset_index = 2; } @@ -3118,7 +3175,6 @@ message BakeMacaroonResponse { string macaroon = 1; } - message Failure { enum FailureCode { /** @@ -3199,7 +3255,6 @@ message Failure { uint32 height = 9; } - message ChannelUpdate { /** The signature that validates the announced data and proves the ownership diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 66621d03c2..fd769955ef 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -481,7 +481,7 @@ }, { "name": "force", - "description": "/ If true, then the channel will be closed forcibly. This means the current commitment transaction will be signed and broadcast.", + "description": "/ If true, then the channel will be closed forcibly. This means the\n/ current commitment transaction will be signed and broadcast.", "in": "query", "required": false, "type": "boolean", @@ -489,7 +489,7 @@ }, { "name": "target_conf", - "description": "/ The target number of blocks that the closure transaction should be confirmed by.", + "description": "/ The target number of blocks that the closure transaction should be\n/ confirmed by.", "in": "query", "required": false, "type": "integer", @@ -497,7 +497,7 @@ }, { "name": "sat_per_byte", - "description": "/ A manual fee rate set in sat/byte that should be used when crafting the closure transaction.", + "description": "/ A manual fee rate set in sat/byte that should be used when crafting the\n/ closure transaction.", "in": "query", "required": false, "type": "string", @@ -815,7 +815,7 @@ }, { "name": "cltv_limit", - "description": "* \nAn optional maximum total time lock for the route. If the source is empty or\nourselves, this should not exceed lnd's `--max-cltv-expiry` setting. If\nzero, then the value of `--max-cltv-expiry` is used as the limit.", + "description": "*\nAn optional maximum total time lock for the route. If the source is empty or\nourselves, this should not exceed lnd's `--max-cltv-expiry` setting. If\nzero, then the value of `--max-cltv-expiry` is used as the limit.", "in": "query", "required": false, "type": "integer", @@ -875,7 +875,7 @@ }, "/v1/initwallet": { "post": { - "summary": "* \nInitWallet is used when lnd is starting up for the first time to fully\ninitialize the daemon and its internal wallet. At the very least a wallet\npassword must be provided. This will be used to encrypt sensitive material\non disk.", + "summary": "*\nInitWallet is used when lnd is starting up for the first time to fully\ninitialize the daemon and its internal wallet. At the very least a wallet\npassword must be provided. This will be used to encrypt sensitive material\non disk.", "description": "In the case of a recovery scenario, the user can also specify their aezeed\nmnemonic and passphrase. If set, then the daemon will use this prior state\nto initialize its internal wallet.\n\nAlternatively, this can be used along with the GenSeed RPC to obtain a\nseed, then present it to the user. Once it has been verified by the user,\nthe seed can be fed into this RPC in order to commit the new wallet.", "operationId": "InitWallet", "responses": { @@ -1354,7 +1354,7 @@ "parameters": [ { "name": "target_conf", - "description": "/ The target number of blocks that this transaction should be confirmed by.", + "description": "/ The target number of blocks that this transaction should be confirmed\n/ by.", "in": "query", "required": false, "type": "integer", @@ -1647,7 +1647,7 @@ "local_chan_reserve_sat": { "type": "string", "format": "int64", - "description": "/ The minimum satoshis this node is required to reserve in its balance." + "description": "/ The minimum satoshis this node is required to reserve in its\n/ balance." }, "remote_chan_reserve_sat": { "type": "string", @@ -1730,7 +1730,7 @@ ], "default": "WITNESS_PUBKEY_HASH", "description": "- `p2wkh`: Pay to witness key hash (`WITNESS_PUBKEY_HASH` = 0)\n- `np2wkh`: Pay to nested witness key hash (`NESTED_PUBKEY_HASH` = 1)", - "title": "* \n`AddressType` has to be one of:" + "title": "*\n`AddressType` has to be one of:" }, "lnrpcBakeMacaroonRequest": { "type": "object", @@ -1945,7 +1945,7 @@ "uptime": { "type": "string", "format": "int64", - "description": "*\nThe number of seconds that the remote peer has been observed as being online\nby the channel scoring system over the lifetime of the channel [EXPERIMENTAL]." + "description": "*\nThe number of seconds that the remote peer has been observed as being online\nby the channel scoring system over the lifetime of the channel\n[EXPERIMENTAL]." }, "close_address": { "type": "string", @@ -1974,7 +1974,7 @@ "funding_amt": { "type": "string", "format": "uint64", - "description": "/ The funding amount in satoshis that initiator wishes to use in the channel." + "description": "/ The funding amount in satoshis that initiator wishes to use in the\n/ channel." }, "push_amt": { "type": "string", @@ -1989,12 +1989,12 @@ "max_value_in_flight": { "type": "string", "format": "uint64", - "description": "/ The maximum amount of coins in millisatoshis that can be pending in this channel." + "description": "/ The maximum amount of coins in millisatoshis that can be pending in this\n/ channel." }, "channel_reserve": { "type": "string", "format": "uint64", - "description": "/ The minimum amount of satoshis the initiator requires us to have at all times." + "description": "/ The minimum amount of satoshis the initiator requires us to have at all\n/ times." }, "min_htlc": { "type": "string", @@ -2004,12 +2004,12 @@ "fee_per_kw": { "type": "string", "format": "uint64", - "description": "/ The initial fee rate that the initiator suggests for both commitment transactions." + "description": "/ The initial fee rate that the initiator suggests for both commitment\n/ transactions." }, "csv_delay": { "type": "integer", "format": "int64", - "description": "*\nThe number of blocks to use for the relative time lock in the pay-to-self output\nof both commitment transactions." + "description": "*\nThe number of blocks to use for the relative time lock in the pay-to-self\noutput of both commitment transactions." }, "max_accepted_htlcs": { "type": "integer", @@ -2019,7 +2019,7 @@ "channel_flags": { "type": "integer", "format": "int64", - "description": "/ A bit-field which the initiator uses to specify proposed channel behavior." + "description": "/ A bit-field which the initiator uses to specify proposed channel\n/ behavior." } } }, @@ -2238,12 +2238,12 @@ "fee_per_mil": { "type": "string", "format": "int64", - "description": "/ The amount charged per milli-satoshis transferred expressed in millionths of a satoshi." + "description": "/ The amount charged per milli-satoshis transferred expressed in\n/ millionths of a satoshi." }, "fee_rate": { "type": "number", "format": "double", - "description": "/ The effective fee rate in milli-satoshis. Computed by dividing the fee_per_mil value by 1 million." + "description": "/ The effective fee rate in milli-satoshis. Computed by dividing the\n/ fee_per_mil value by 1 million." } } }, @@ -2573,22 +2573,22 @@ "items": { "$ref": "#/definitions/lnrpcChannelFeeReport" }, - "description": "/ An array of channel fee reports which describes the current fee schedule for each channel." + "description": "/ An array of channel fee reports which describes the current fee schedule\n/ for each channel." }, "day_fee_sum": { "type": "string", "format": "uint64", - "description": "/ The total amount of fee revenue (in satoshis) the switch has collected over the past 24 hrs." + "description": "/ The total amount of fee revenue (in satoshis) the switch has collected\n/ over the past 24 hrs." }, "week_fee_sum": { "type": "string", "format": "uint64", - "description": "/ The total amount of fee revenue (in satoshis) the switch has collected over the past 1 week." + "description": "/ The total amount of fee revenue (in satoshis) the switch has collected\n/ over the past 1 week." }, "month_fee_sum": { "type": "string", "format": "uint64", - "description": "/ The total amount of fee revenue (in satoshis) the switch has collected over the past 1 month." + "description": "/ The total amount of fee revenue (in satoshis) the switch has collected\n/ over the past 1 month." } } }, @@ -2598,7 +2598,7 @@ "timestamp": { "type": "string", "format": "uint64", - "description": "/ Timestamp is the time (unix epoch offset) that this circuit was completed." + "description": "/ Timestamp is the time (unix epoch offset) that this circuit was\n/ completed." }, "chan_id_in": { "type": "string", @@ -2608,17 +2608,17 @@ "chan_id_out": { "type": "string", "format": "uint64", - "description": "/ The outgoing channel ID that carried the preimage that completed the circuit." + "description": "/ The outgoing channel ID that carried the preimage that completed the\n/ circuit." }, "amt_in": { "type": "string", "format": "uint64", - "description": "/ The total amount (in satoshis) of the incoming HTLC that created half the circuit." + "description": "/ The total amount (in satoshis) of the incoming HTLC that created half\n/ the circuit." }, "amt_out": { "type": "string", "format": "uint64", - "description": "/ The total amount (in satoshis) of the outgoing HTLC that created the second half of the circuit." + "description": "/ The total amount (in satoshis) of the outgoing HTLC that created the\n/ second half of the circuit." }, "fee": { "type": "string", @@ -2633,12 +2633,12 @@ "amt_in_msat": { "type": "string", "format": "uint64", - "description": "/ The total amount (in milli-satoshis) of the incoming HTLC that created half the circuit." + "description": "/ The total amount (in milli-satoshis) of the incoming HTLC that created\n/ half the circuit." }, "amt_out_msat": { "type": "string", "format": "uint64", - "description": "/ The total amount (in milli-satoshis) of the outgoing HTLC that created the second half of the circuit." + "description": "/ The total amount (in milli-satoshis) of the outgoing HTLC that created\n/ the second half of the circuit." } } }, @@ -2648,17 +2648,17 @@ "start_time": { "type": "string", "format": "uint64", - "description": "/ Start time is the starting point of the forwarding history request. All records beyond this point will be included, respecting the end time, and the index offset." + "description": "/ Start time is the starting point of the forwarding history request. All\n/ records beyond this point will be included, respecting the end time, and\n/ the index offset." }, "end_time": { "type": "string", "format": "uint64", - "description": "/ End time is the end point of the forwarding history request. The response will carry at most 50k records between the start time and the end time. The index offset can be used to implement pagination." + "description": "/ End time is the end point of the forwarding history request. The\n/ response will carry at most 50k records between the start time and the\n/ end time. The index offset can be used to implement pagination." }, "index_offset": { "type": "integer", "format": "int64", - "description": "/ Index offset is the offset in the time series to start at. As each response can only contain 50k records, callers can use this to skip around within a packed time series." + "description": "/ Index offset is the offset in the time series to start at. As each\n/ response can only contain 50k records, callers can use this to skip\n/ around within a packed time series." }, "num_max_events": { "type": "integer", @@ -2675,12 +2675,12 @@ "items": { "$ref": "#/definitions/lnrpcForwardingEvent" }, - "description": "/ A list of forwarding events from the time slice of the time series specified in the request." + "description": "/ A list of forwarding events from the time slice of the time series\n/ specified in the request." }, "last_offset_index": { "type": "integer", "format": "int64", - "description": "/ The index of the last time in the set of returned forwarding events. Can be used to seek further, pagination style." + "description": "/ The index of the last time in the set of returned forwarding events. Can\n/ be used to seek further, pagination style." } } }, @@ -2788,7 +2788,7 @@ "testnet": { "type": "boolean", "format": "boolean", - "title": "* \nWhether the current node is connected to testnet. This field is \ndeprecated and the network field should be used instead" + "title": "*\nWhether the current node is connected to testnet. This field is\ndeprecated and the network field should be used instead" }, "chains": { "type": "array", @@ -2923,7 +2923,7 @@ "tlv_payload": { "type": "boolean", "format": "boolean", - "description": "* \nIf set to true, then this hop will be encoded using the new variable length\nTLV format. Note that if any custom tlv_records below are specified, then\nthis field MUST be set to true for them to be encoded properly." + "description": "*\nIf set to true, then this hop will be encoded using the new variable length\nTLV format. Note that if any custom tlv_records below are specified, then\nthis field MUST be set to true for them to be encoded properly." }, "mpp_record": { "$ref": "#/definitions/lnrpcMPPRecord", @@ -3208,7 +3208,7 @@ }, "key_loc": { "$ref": "#/definitions/lnrpcKeyLocator", - "description": "* \nThe key locator that identifies which key to use for signing." + "description": "*\nThe key locator that identifies which key to use for signing." } } }, @@ -3236,7 +3236,7 @@ }, "host": { "type": "string", - "title": "/ The network location of the lightning node, e.g. `69.69.69.69:1337` or `localhost:10011`" + "title": "/ The network location of the lightning node, e.g. `69.69.69.69:1337` or\n/ `localhost:10011`" } } }, @@ -3541,42 +3541,42 @@ "push_sat": { "type": "string", "format": "int64", - "title": "/ The number of satoshis to push to the remote side as part of the initial commitment state" + "title": "/ The number of satoshis to push to the remote side as part of the initial\n/ commitment state" }, "target_conf": { "type": "integer", "format": "int32", - "description": "/ The target number of blocks that the funding transaction should be confirmed by." + "description": "/ The target number of blocks that the funding transaction should be\n/ confirmed by." }, "sat_per_byte": { "type": "string", "format": "int64", - "description": "/ A manual fee rate set in sat/byte that should be used when crafting the funding transaction." + "description": "/ A manual fee rate set in sat/byte that should be used when crafting the\n/ funding transaction." }, "private": { "type": "boolean", "format": "boolean", - "description": "/ Whether this channel should be private, not announced to the greater network." + "description": "/ Whether this channel should be private, not announced to the greater\n/ network." }, "min_htlc_msat": { "type": "string", "format": "int64", - "description": "/ The minimum value in millisatoshi we will require for incoming HTLCs on the channel." + "description": "/ The minimum value in millisatoshi we will require for incoming HTLCs on\n/ the channel." }, "remote_csv_delay": { "type": "integer", "format": "int64", - "description": "/ The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size." + "description": "/ The delay we require on the remote's commitment transaction. If this is\n/ not set, it will be scaled automatically with the channel size." }, "min_confs": { "type": "integer", "format": "int32", - "description": "/ The minimum number of confirmations each one of your outputs used for the funding transaction must satisfy." + "description": "/ The minimum number of confirmations each one of your outputs used for\n/ the funding transaction must satisfy." }, "spend_unconfirmed": { "type": "boolean", "format": "boolean", - "description": "/ Whether unconfirmed outputs should be used as inputs for the funding transaction." + "description": "/ Whether unconfirmed outputs should be used as inputs for the funding\n/ transaction." }, "close_address": { "type": "string", @@ -3925,7 +3925,7 @@ "fee_rate": { "type": "number", "format": "double", - "description": "/ The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6." + "description": "/ The effective fee rate in milli-satoshis. The precision of this value\n/ goes up to 6 decimal places, so 1e-6." }, "time_lock_delta": { "type": "integer", @@ -3935,12 +3935,12 @@ "max_htlc_msat": { "type": "string", "format": "uint64", - "description": "/ If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged." + "description": "/ If set, the maximum HTLC size in milli-satoshis. If unset, the maximum\n/ HTLC will be unchanged." }, "min_htlc_msat": { "type": "string", "format": "uint64", - "description": "/ The minimum HTLC size in milli-satoshis. Only applied if min_htlc_msat_specified is true." + "description": "/ The minimum HTLC size in milli-satoshis. Only applied if\n/ min_htlc_msat_specified is true." }, "min_htlc_msat_specified": { "type": "boolean", @@ -4084,12 +4084,12 @@ "target_conf": { "type": "integer", "format": "int32", - "description": "/ The target number of blocks that this transaction should be confirmed by." + "description": "/ The target number of blocks that this transaction should be confirmed\n/ by." }, "sat_per_byte": { "type": "string", "format": "int64", - "description": "/ A manual fee rate set in sat/byte that should be used when crafting the transaction." + "description": "/ A manual fee rate set in sat/byte that should be used when crafting the\n/ transaction." }, "send_all": { "type": "boolean", @@ -4173,7 +4173,7 @@ "cltv_limit": { "type": "integer", "format": "int64", - "description": "* \nAn optional maximum total time lock for the route. This should not exceed\nlnd's `--max-cltv-expiry` setting. If zero, then the value of\n`--max-cltv-expiry` is enforced." + "description": "*\nAn optional maximum total time lock for the route. This should not exceed\nlnd's `--max-cltv-expiry` setting. If zero, then the value of\n`--max-cltv-expiry` is enforced." }, "dest_custom_records": { "type": "object", @@ -4181,7 +4181,7 @@ "type": "string", "format": "byte" }, - "description": "* \nAn optional field that can be used to pass an arbitrary set of TLV records\nto a peer which understands the new records. This can be used to pass\napplication specific data during the payment attempt. Record types are\nrequired to be in the custom range \u003e= 65536. When using REST, the values\nmust be encoded as base64." + "description": "*\nAn optional field that can be used to pass an arbitrary set of TLV records\nto a peer which understands the new records. This can be used to pass\napplication specific data during the payment attempt. Record types are\nrequired to be in the custom range \u003e= 65536. When using REST, the values\nmust be encoded as base64." }, "allow_self_payment": { "type": "boolean", diff --git a/lnrpc/signrpc/signer.pb.go b/lnrpc/signrpc/signer.pb.go index a8fd8b93c4..6100237b17 100644 --- a/lnrpc/signrpc/signer.pb.go +++ b/lnrpc/signrpc/signer.pb.go @@ -202,7 +202,8 @@ type SignDescriptor struct { //only be populated if a p2wsh or a p2sh output is being signed. WitnessScript []byte `protobuf:"bytes,4,opt,name=witness_script,json=witnessScript,proto3" json:"witness_script,omitempty"` //* - //A description of the output being spent. The value and script MUST be provided. + //A description of the output being spent. The value and script MUST be + //provided. Output *TxOut `protobuf:"bytes,5,opt,name=output,proto3" json:"output,omitempty"` //* //The target sighash type that should be used when generating the final diff --git a/lnrpc/signrpc/signer.proto b/lnrpc/signrpc/signer.proto index 04422feb9f..346018a958 100644 --- a/lnrpc/signrpc/signer.proto +++ b/lnrpc/signrpc/signer.proto @@ -19,7 +19,7 @@ message KeyDescriptor { */ bytes raw_key_bytes = 1; - /** + /** The key locator that identifies which key to use for signing. Either this or the raw bytes of the target key must be specified. */ @@ -58,7 +58,7 @@ message SignDescriptor { commitment secret from a previously revoked commitment transaction. This value is in combination with two hash values, and the original private key to derive the private key to be used when signing. - + * k = (privKey*sha256(pubKey || tweakPub) + tweakPriv*sha256(tweakPub || pubKey)) mod N */ @@ -71,7 +71,8 @@ message SignDescriptor { bytes witness_script = 4; /** - A description of the output being spent. The value and script MUST be provided. + A description of the output being spent. The value and script MUST be + provided. */ TxOut output = 5; @@ -173,8 +174,8 @@ service Signer { set of inputs/outputs to a transaction. Each request specifies details concerning how the outputs should be signed, which keys they should be signed with, and also any optional tweaks. The return value is a fixed - 64-byte signature (the same format as we use on the wire in Lightning). - + 64-byte signature (the same format as we use on the wire in Lightning). + If we are unable to sign using the specified keys, then an error will be returned. */ @@ -197,7 +198,7 @@ service Signer { /** SignMessage signs a message with the key specified in the key locator. The returned signature is fixed-size LN wire format encoded. - + The main difference to SignMessage in the main RPC is that a specific key is used to sign the message instead of the node identity private key. */ @@ -206,7 +207,7 @@ service Signer { /** VerifyMessage verifies a signature over a message using the public key provided. The signature must be fixed-size LN wire format encoded. - + The main difference to VerifyMessage in the main RPC is that the public key used to sign the message does not have to be a node known to the network. */ @@ -218,7 +219,7 @@ service Signer { key specified in the key_loc parameter (or the node's identity private key if no key locator is specified): P_shared = privKeyNode * ephemeralPubkey - The resulting shared public key is serialized in the compressed format and + The resulting shared public key is serialized in the compressed format and hashed with sha256, resulting in the final key length of 256bit. */ rpc DeriveSharedKey (SharedKeyRequest) returns (SharedKeyResponse); diff --git a/lnrpc/walletrpc/walletkit.proto b/lnrpc/walletrpc/walletkit.proto index 7f2313f93f..267af2fdaf 100644 --- a/lnrpc/walletrpc/walletkit.proto +++ b/lnrpc/walletrpc/walletkit.proto @@ -248,7 +248,7 @@ service WalletKit { /** DeriveKey attempts to derive an arbitrary key specified by the passed - KeyLocator. + KeyLocator. */ rpc DeriveKey (signrpc.KeyLocator) returns (signrpc.KeyDescriptor); diff --git a/lnrpc/wtclientrpc/wtclient.proto b/lnrpc/wtclientrpc/wtclient.proto index 138a836707..d264d4b170 100644 --- a/lnrpc/wtclientrpc/wtclient.proto +++ b/lnrpc/wtclientrpc/wtclient.proto @@ -151,7 +151,7 @@ service WatchtowerClient { */ rpc RemoveTower (RemoveTowerRequest) returns (RemoveTowerResponse); - // ListTowers returns the list of watchtowers registered with the client. + // ListTowers returns the list of watchtowers registered with the client. rpc ListTowers (ListTowersRequest) returns (ListTowersResponse); // GetTowerInfo retrieves information for a registered watchtower. From 1e1b68accf876d34f530bb8a3348d72d113d408c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 Mar 2020 19:08:43 +0100 Subject: [PATCH 200/562] lnrpc: update README to describe new commands --- lnrpc/README.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/lnrpc/README.md b/lnrpc/README.md index c43f5cce58..d07e548ee9 100644 --- a/lnrpc/README.md +++ b/lnrpc/README.md @@ -146,6 +146,17 @@ $ go get -u github.com/lightningnetwork/lnd/lnrpc ## Generate protobuf definitions +### Linux + +For linux there is an easy install script that is also used for the Travis CI +build. Just run the following command (requires `sudo` permissions and the tools +`make`, `go`, `wget` and `unzip` to be installed) from the repository's root +folder: + +`./scripts/install_travis_proto.sh` + +### MacOS / Unix like systems + 1. Download [v.3.4.0](https://github.com/google/protobuf/releases/tag/v3.4.0) of `protoc` for your operating system and add it to your `PATH`. For example, if using macOS: @@ -178,4 +189,24 @@ $ git reset --hard v1.8.6 $ go install ./protoc-gen-grpc-gateway ./protoc-gen-swagger ``` -5. Run [`gen_protos.sh`](https://github.com/lightningnetwork/lnd/blob/master/lnrpc/gen_protos.sh) to generate new protobuf definitions. +5. Run [`gen_protos.sh`](https://github.com/lightningnetwork/lnd/blob/master/lnrpc/gen_protos.sh) +or `make rpc` to generate new protobuf definitions. + +## Format .proto files + +We use `clang-format` to make sure the `.proto` files are formatted correctly. +You can install the formatter on Ubuntu by running `apt install clang-format`. + +Consult [this page](http://releases.llvm.org/download.html) to find binaries +for other operating systems or distributions. + +## Makefile commands + +The following commands are available with `make`: + +* `rpc`: Compile `.proto` files (calls `lnrpc/gen_protos.sh`). +* `rpc-format`: Formats all `.proto` files according to our formatting rules. + Requires `clang-format`, see previous chapter. +* `rpc-check`: Runs both previous commands and makes sure the git work tree is + not dirty. This can be used to check that the `.proto` files are formatted + and compiled properly. From 10e247540f6127eea3d68df4f1e67c58d8b7386b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 3 Mar 2020 16:30:15 +0100 Subject: [PATCH 201/562] watchtowerrpc: fix typo --- lnrpc/watchtowerrpc/watchtower.pb.go | 4 ++-- lnrpc/watchtowerrpc/watchtower.proto | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lnrpc/watchtowerrpc/watchtower.pb.go b/lnrpc/watchtowerrpc/watchtower.pb.go index 2a010f1ca1..3b19e6ee48 100644 --- a/lnrpc/watchtowerrpc/watchtower.pb.go +++ b/lnrpc/watchtowerrpc/watchtower.pb.go @@ -150,7 +150,7 @@ const _ = grpc.SupportPackageIsVersion4 type WatchtowerClient interface { //* lncli: tower info //GetInfo returns general information concerning the companion watchtower - //including it's public key and URIs where the server is currently + //including its public key and URIs where the server is currently //listening for clients. GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) } @@ -176,7 +176,7 @@ func (c *watchtowerClient) GetInfo(ctx context.Context, in *GetInfoRequest, opts type WatchtowerServer interface { //* lncli: tower info //GetInfo returns general information concerning the companion watchtower - //including it's public key and URIs where the server is currently + //including its public key and URIs where the server is currently //listening for clients. GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) } diff --git a/lnrpc/watchtowerrpc/watchtower.proto b/lnrpc/watchtowerrpc/watchtower.proto index b79b52b005..818807ef23 100644 --- a/lnrpc/watchtowerrpc/watchtower.proto +++ b/lnrpc/watchtowerrpc/watchtower.proto @@ -7,7 +7,7 @@ option go_package = "github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc"; service Watchtower { /** lncli: tower info GetInfo returns general information concerning the companion watchtower - including it's public key and URIs where the server is currently + including its public key and URIs where the server is currently listening for clients. */ rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); From 59875b6ec43356b4bdc19c2c9430743f0cf792a3 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 4 Mar 2020 15:24:30 +0100 Subject: [PATCH 202/562] github: add proto formatting to pull request template --- .github/pull_request_template.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 548e5f4e86..25a977366c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -11,6 +11,8 @@ - [ ] Any new logging statements use an appropriate subsystem and logging level - [ ] Code has been formatted with `go fmt` +- [ ] Protobuf files (`lnrpc/**/*.proto`) have been formatted with + `make rpc-format` and compiled with `make rpc` - [ ] For code and documentation: lines are wrapped at 80 characters (the tab character should be counted as 8 characters, not 4, as some IDEs do per default) From 3b8dd4bd632c8874a696222144574f6be6e1662a Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 11 Mar 2020 09:12:52 +0100 Subject: [PATCH 203/562] travis: cross-compile windows --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 96a7312f81..94d28281ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,6 +43,7 @@ jobs: - make unit pkg=... case=_NONE_ - make lint - make btcd + - LNDBUILDSYS=windows-amd64 bash ./build/release/release.sh - stage: Test script: make travis-cover name: Unit Cover From f55860ccd8108a1133c0ba47e1f711267e175a6b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 11 Mar 2020 09:15:04 +0100 Subject: [PATCH 204/562] lncli: fix windows compilation --- cmd/lncli/commands.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 1031c25242..36ebe97dd8 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1807,7 +1807,11 @@ func unlock(ctx *cli.Context) error { // lncli. default: fmt.Printf("Input wallet password: ") - pw, err = terminal.ReadPassword(syscall.Stdin) + + // The variable syscall.Stdin is of a different type in the + // Windows API that's why we need the explicit cast. And of + // course the linter doesn't like it either. + pw, err = terminal.ReadPassword(int(syscall.Stdin)) // nolint:unconvert fmt.Println() } if err != nil { From 7917d22dafb8c78aa48cdb3a69d34cfbaf332b2f Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 11 Mar 2020 10:17:45 +0100 Subject: [PATCH 205/562] Makefile: don't format proto There are different versions of clang-format being installed on different versions of ubuntu that apparently produce different results when formatting the proto files. This is likely too much of a hurdle for new contributors to also manually install the correct version of a command line tool just to format stuff. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6d50d6e08c..d049579350 100644 --- a/Makefile +++ b/Makefile @@ -178,7 +178,7 @@ rpc-format: @$(call print, "Formatting protos.") cd ./lnrpc; find . -name "*.proto" | xargs clang-format --style=file -i -rpc-check: rpc-format rpc +rpc-check: rpc @$(call print, "Verifying protos.") if test -n "$$(git describe --dirty | grep dirty)"; then echo "Protos not properly formatted or not compiled with v3.4.0"; git status; git diff; exit 1; fi From 7b8eae38e54ca87f4760263821762a78577480c6 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 17 Feb 2020 12:47:26 +0100 Subject: [PATCH 206/562] peer: avoid chansync resend loop If a peer receives a channel reestablish message shortly after the channel has been closed, it will resend its own channel reestablish message. In the meantime the other peer could also have seen the channel being closed and will also resend its own message. This leads to a resend loop that never terminates. To avoid two peers getting into this situation, we now allow only one such resent message per conection. --- peer.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/peer.go b/peer.go index 4c8369f1de..5aef5f592a 100644 --- a/peer.go +++ b/peer.go @@ -210,6 +210,12 @@ type peer struct { // the connection handshake. remoteFeatures *lnwire.FeatureVector + // resentChanSyncMsg is a set that keeps track of which channels we + // have re-sent channel reestablishment messages for. This is done to + // avoid getting into loop where both peers will respond to the other + // peer's chansync message with its own over and over again. + resentChanSyncMsg map[lnwire.ChannelID]struct{} + // writePool is the task pool to that manages reuse of write buffers. // Write tasks are submitted to the pool in order to conserve the total // number of write buffers allocated at any one time, and decouple write @@ -266,6 +272,7 @@ func newPeer(conn net.Conn, connReq *connmgr.ConnReq, server *server, localCloseChanReqs: make(chan *htlcswitch.ChanClose), linkFailures: make(chan linkFailureReport), chanCloseMsgs: make(chan *closeMsg), + resentChanSyncMsg: make(map[lnwire.ChannelID]struct{}), chanActiveTimeout: chanActiveTimeout, @@ -2506,6 +2513,12 @@ func (p *peer) sendInitMsg() error { // resendChanSyncMsg will attempt to find a channel sync message for the closed // channel and resend it to our peer. func (p *peer) resendChanSyncMsg(cid lnwire.ChannelID) error { + // If we already re-sent the mssage for this channel, we won't do it + // again. + if _, ok := p.resentChanSyncMsg[cid]; ok { + return nil + } + // Check if we have any channel sync messages stored for this channel. c, err := p.server.chanDB.FetchClosedChannelForID(cid) if err != nil { @@ -2534,6 +2547,10 @@ func (p *peer) resendChanSyncMsg(cid lnwire.ChannelID) error { peerLog.Debugf("Re-sent channel sync message for channel %v to peer "+ "%v", cid, p) + // Note down that we sent the message, so we won't resend it again for + // this connection. + p.resentChanSyncMsg[cid] = struct{}{} + return nil } From c9c667bbf237c5421f01bf68f3f81ccfc9ed59f0 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 11 Mar 2020 12:56:16 +0100 Subject: [PATCH 207/562] pilot: log whether autopilot is active at startup --- pilot.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pilot.go b/pilot.go index 59f05116b0..923c7865a9 100644 --- a/pilot.go +++ b/pilot.go @@ -141,9 +141,10 @@ var _ autopilot.ChannelController = (*chanController)(nil) func initAutoPilot(svr *server, cfg *autoPilotConfig, chainCfg *chainConfig) ( *autopilot.ManagerCfg, error) { - atplLog.Infof("Instantiating autopilot with max_channels=%d, allocation=%f, "+ - "min_chan_size=%d, max_chan_size=%d, private=%t, min_confs=%d, "+ - "conf_target=%d", cfg.MaxChannels, cfg.Allocation, cfg.MinChannelSize, + atplLog.Infof("Instantiating autopilot with active=%v, "+ + "max_channels=%d, allocation=%f, min_chan_size=%d, "+ + "max_chan_size=%d, private=%t, min_confs=%d, conf_target=%d", + cfg.Active, cfg.MaxChannels, cfg.Allocation, cfg.MinChannelSize, cfg.MaxChannelSize, cfg.Private, cfg.MinConfs, cfg.ConfTarget) // Set up the constraints the autopilot heuristics must adhere to. From 67d4bad73fa185a7bb285f3ffa5e06e9215f71ff Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 13 Mar 2020 09:30:16 +0200 Subject: [PATCH 208/562] rpcserver+routerrpc: add subscribe events to router backend Add SubscribeHtlcEvents to RouterBackend in preparation for the addition of a HtlcNotifier stream. --- lnrpc/routerrpc/router_backend.go | 5 +++++ rpcserver.go | 1 + 2 files changed, 6 insertions(+) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 120211b1ed..259f78f7c4 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/routing/route" + "github.com/lightningnetwork/lnd/subscribe" "github.com/lightningnetwork/lnd/zpay32" ) @@ -68,6 +69,10 @@ type RouterBackend struct { // DefaultFinalCltvDelta is the default value used as final cltv delta // when an RPC caller doesn't specify a value. DefaultFinalCltvDelta uint16 + + // SubscribeHtlcEvents returns a subscription client for the node's + // htlc events. + SubscribeHtlcEvents func() (*subscribe.Client, error) } // MissionControl defines the mission control dependencies of routerrpc. diff --git a/rpcserver.go b/rpcserver.go index f2ea166b7f..9725ed550d 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -567,6 +567,7 @@ func newRPCServer(s *server, macService *macaroons.Service, Tower: s.controlTower, MaxTotalTimelock: cfg.MaxOutgoingCltvExpiry, DefaultFinalCltvDelta: uint16(cfg.Bitcoin.TimeLockDelta), + SubscribeHtlcEvents: s.htlcNotifier.SubscribeHtlcEvents, } genInvoiceFeatures := func() *lnwire.FeatureVector { From aa70d5d02ab7129cb93e7b44dffbbbce4efb62e9 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 13 Mar 2020 09:30:16 +0200 Subject: [PATCH 209/562] routerrpc: add quit channel to signal shutdown --- lnrpc/routerrpc/router_server.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index ed02a6fcd0..8bbdb38704 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "os" "path/filepath" + "sync/atomic" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/channeldb" @@ -32,6 +33,8 @@ const ( ) var ( + errServerShuttingDown = errors.New("routerrpc server shutting down") + // macaroonOps are the set of capabilities that our minted macaroon (if // it doesn't already exist) will have. macaroonOps = []bakery.Op{ @@ -90,7 +93,12 @@ var ( // Server is a stand alone sub RPC server which exposes functionality that // allows clients to route arbitrary payment through the Lightning Network. type Server struct { + started int32 // To be used atomically. + shutdown int32 // To be used atomically. + cfg *Config + + quit chan struct{} } // A compile time check to ensure that Server fully implements the RouterServer @@ -150,7 +158,8 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { } routerServer := &Server{ - cfg: cfg, + cfg: cfg, + quit: make(chan struct{}), } return routerServer, macPermissions, nil @@ -160,6 +169,10 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { // // NOTE: This is part of the lnrpc.SubServer interface. func (s *Server) Start() error { + if atomic.AddInt32(&s.started, 1) != 1 { + return nil + } + return nil } @@ -167,6 +180,11 @@ func (s *Server) Start() error { // // NOTE: This is part of the lnrpc.SubServer interface. func (s *Server) Stop() error { + if atomic.AddInt32(&s.shutdown, 1) != 1 { + return nil + } + + close(s.quit) return nil } @@ -513,6 +531,9 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash, return err } + case <-s.quit: + return errServerShuttingDown + case <-stream.Context().Done(): log.Debugf("Payment status stream %v canceled", paymentHash) return stream.Context().Err() From 0a5b918db2e0375c48bb05398dd24a6133982185 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 13 Mar 2020 09:30:16 +0200 Subject: [PATCH 210/562] routerrpc: add htlcnotifier subscription --- lnrpc/routerrpc/router.pb.go | 871 +++++++++++++++++++++++++--- lnrpc/routerrpc/router.proto | 135 +++++ lnrpc/routerrpc/router_server.go | 43 ++ lnrpc/routerrpc/subscribe_events.go | 241 ++++++++ 4 files changed, 1201 insertions(+), 89 deletions(-) create mode 100644 lnrpc/routerrpc/subscribe_events.go diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 5951e4e958..ea4f940fb7 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -79,6 +79,125 @@ func (PaymentState) EnumDescriptor() ([]byte, []int) { return fileDescriptor_7a0613f69d37b0a5, []int{0} } +type FailureDetail int32 + +const ( + FailureDetail_UNKNOWN FailureDetail = 0 + FailureDetail_NO_DETAIL FailureDetail = 1 + FailureDetail_ONION_DECODE FailureDetail = 2 + FailureDetail_LINK_NOT_ELIGIBLE FailureDetail = 3 + FailureDetail_ON_CHAIN_TIMEOUT FailureDetail = 4 + FailureDetail_HTLC_EXCEEDS_MAX FailureDetail = 5 + FailureDetail_INSUFFICIENT_BALANCE FailureDetail = 6 + FailureDetail_INCOMPLETE_FORWARD FailureDetail = 7 + FailureDetail_HTLC_ADD_FAILED FailureDetail = 8 + FailureDetail_FORWARDS_DISABLED FailureDetail = 9 + FailureDetail_INVOICE_CANCELED FailureDetail = 10 + FailureDetail_INVOICE_UNDERPAID FailureDetail = 11 + FailureDetail_INVOICE_EXPIRY_TOO_SOON FailureDetail = 12 + FailureDetail_INVOICE_NOT_OPEN FailureDetail = 13 + FailureDetail_MPP_INVOICE_TIMEOUT FailureDetail = 14 + FailureDetail_ADDRESS_MISMATCH FailureDetail = 15 + FailureDetail_SET_TOTAL_MISMATCH FailureDetail = 16 + FailureDetail_SET_TOTAL_TOO_LOW FailureDetail = 17 + FailureDetail_SET_OVERPAID FailureDetail = 18 + FailureDetail_UNKNOWN_INVOICE FailureDetail = 19 + FailureDetail_INVALID_KEYSEND FailureDetail = 20 + FailureDetail_MPP_IN_PROGRESS FailureDetail = 21 + FailureDetail_CIRCULAR_ROUTE FailureDetail = 22 +) + +var FailureDetail_name = map[int32]string{ + 0: "UNKNOWN", + 1: "NO_DETAIL", + 2: "ONION_DECODE", + 3: "LINK_NOT_ELIGIBLE", + 4: "ON_CHAIN_TIMEOUT", + 5: "HTLC_EXCEEDS_MAX", + 6: "INSUFFICIENT_BALANCE", + 7: "INCOMPLETE_FORWARD", + 8: "HTLC_ADD_FAILED", + 9: "FORWARDS_DISABLED", + 10: "INVOICE_CANCELED", + 11: "INVOICE_UNDERPAID", + 12: "INVOICE_EXPIRY_TOO_SOON", + 13: "INVOICE_NOT_OPEN", + 14: "MPP_INVOICE_TIMEOUT", + 15: "ADDRESS_MISMATCH", + 16: "SET_TOTAL_MISMATCH", + 17: "SET_TOTAL_TOO_LOW", + 18: "SET_OVERPAID", + 19: "UNKNOWN_INVOICE", + 20: "INVALID_KEYSEND", + 21: "MPP_IN_PROGRESS", + 22: "CIRCULAR_ROUTE", +} + +var FailureDetail_value = map[string]int32{ + "UNKNOWN": 0, + "NO_DETAIL": 1, + "ONION_DECODE": 2, + "LINK_NOT_ELIGIBLE": 3, + "ON_CHAIN_TIMEOUT": 4, + "HTLC_EXCEEDS_MAX": 5, + "INSUFFICIENT_BALANCE": 6, + "INCOMPLETE_FORWARD": 7, + "HTLC_ADD_FAILED": 8, + "FORWARDS_DISABLED": 9, + "INVOICE_CANCELED": 10, + "INVOICE_UNDERPAID": 11, + "INVOICE_EXPIRY_TOO_SOON": 12, + "INVOICE_NOT_OPEN": 13, + "MPP_INVOICE_TIMEOUT": 14, + "ADDRESS_MISMATCH": 15, + "SET_TOTAL_MISMATCH": 16, + "SET_TOTAL_TOO_LOW": 17, + "SET_OVERPAID": 18, + "UNKNOWN_INVOICE": 19, + "INVALID_KEYSEND": 20, + "MPP_IN_PROGRESS": 21, + "CIRCULAR_ROUTE": 22, +} + +func (x FailureDetail) String() string { + return proto.EnumName(FailureDetail_name, int32(x)) +} + +func (FailureDetail) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{1} +} + +type HtlcEvent_EventType int32 + +const ( + HtlcEvent_UNKNOWN HtlcEvent_EventType = 0 + HtlcEvent_SEND HtlcEvent_EventType = 1 + HtlcEvent_RECEIVE HtlcEvent_EventType = 2 + HtlcEvent_FORWARD HtlcEvent_EventType = 3 +) + +var HtlcEvent_EventType_name = map[int32]string{ + 0: "UNKNOWN", + 1: "SEND", + 2: "RECEIVE", + 3: "FORWARD", +} + +var HtlcEvent_EventType_value = map[string]int32{ + "UNKNOWN": 0, + "SEND": 1, + "RECEIVE": 2, + "FORWARD": 3, +} + +func (x HtlcEvent_EventType) String() string { + return proto.EnumName(HtlcEvent_EventType_name, int32(x)) +} + +func (HtlcEvent_EventType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{18, 0} +} + type SendPaymentRequest struct { /// The identity pubkey of the payment recipient Dest []byte `protobuf:"bytes,1,opt,name=dest,proto3" json:"dest,omitempty"` @@ -1118,8 +1237,462 @@ func (m *BuildRouteResponse) GetRoute() *lnrpc.Route { return nil } +type SubscribeHtlcEventsRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SubscribeHtlcEventsRequest) Reset() { *m = SubscribeHtlcEventsRequest{} } +func (m *SubscribeHtlcEventsRequest) String() string { return proto.CompactTextString(m) } +func (*SubscribeHtlcEventsRequest) ProtoMessage() {} +func (*SubscribeHtlcEventsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{17} +} + +func (m *SubscribeHtlcEventsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SubscribeHtlcEventsRequest.Unmarshal(m, b) +} +func (m *SubscribeHtlcEventsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SubscribeHtlcEventsRequest.Marshal(b, m, deterministic) +} +func (m *SubscribeHtlcEventsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SubscribeHtlcEventsRequest.Merge(m, src) +} +func (m *SubscribeHtlcEventsRequest) XXX_Size() int { + return xxx_messageInfo_SubscribeHtlcEventsRequest.Size(m) +} +func (m *SubscribeHtlcEventsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SubscribeHtlcEventsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SubscribeHtlcEventsRequest proto.InternalMessageInfo + +//* +//HtlcEvent contains the htlc event that was processed. These are served on a +//best-effort basis; events are not persisted, delivery is not guaranteed +//(in the event of a crash in the switch, forward events may be lost) and +//some events may be replayed upon restart. Events consumed from this package +//should be de-duplicated by the htlc's unique combination of incoming and +//outgoing channel id and htlc id. [EXPERIMENTAL] +type HtlcEvent struct { + //* + //The short channel id that the incoming htlc arrived at our node on. This + //value is zero for sends. + IncomingChannelId uint64 `protobuf:"varint,1,opt,name=incoming_channel_id,json=incomingChannelId,proto3" json:"incoming_channel_id,omitempty"` + //* + //The short channel id that the outgoing htlc left our node on. This value + //is zero for receives. + OutgoingChannelId uint64 `protobuf:"varint,2,opt,name=outgoing_channel_id,json=outgoingChannelId,proto3" json:"outgoing_channel_id,omitempty"` + //* + //Incoming id is the index of the incoming htlc in the incoming channel. + //This value is zero for sends. + IncomingHtlcId uint64 `protobuf:"varint,3,opt,name=incoming_htlc_id,json=incomingHtlcId,proto3" json:"incoming_htlc_id,omitempty"` + //* + //Outgoing id is the index of the outgoing htlc in the outgoing channel. + //This value is zero for receives. + OutgoingHtlcId uint64 `protobuf:"varint,4,opt,name=outgoing_htlc_id,json=outgoingHtlcId,proto3" json:"outgoing_htlc_id,omitempty"` + //* + //The time in unix nanoseconds that the event occurred. + TimestampNs uint64 `protobuf:"varint,5,opt,name=timestamp_ns,json=timestampNs,proto3" json:"timestamp_ns,omitempty"` + //* + //The event type indicates whether the htlc was part of a send, receive or + //forward. + EventType HtlcEvent_EventType `protobuf:"varint,6,opt,name=event_type,json=eventType,proto3,enum=routerrpc.HtlcEvent_EventType" json:"event_type,omitempty"` + // Types that are valid to be assigned to Event: + // *HtlcEvent_ForwardEvent + // *HtlcEvent_ForwardFailEvent + // *HtlcEvent_SettleEvent + // *HtlcEvent_LinkFailEvent + Event isHtlcEvent_Event `protobuf_oneof:"event"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HtlcEvent) Reset() { *m = HtlcEvent{} } +func (m *HtlcEvent) String() string { return proto.CompactTextString(m) } +func (*HtlcEvent) ProtoMessage() {} +func (*HtlcEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{18} +} + +func (m *HtlcEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HtlcEvent.Unmarshal(m, b) +} +func (m *HtlcEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HtlcEvent.Marshal(b, m, deterministic) +} +func (m *HtlcEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_HtlcEvent.Merge(m, src) +} +func (m *HtlcEvent) XXX_Size() int { + return xxx_messageInfo_HtlcEvent.Size(m) +} +func (m *HtlcEvent) XXX_DiscardUnknown() { + xxx_messageInfo_HtlcEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_HtlcEvent proto.InternalMessageInfo + +func (m *HtlcEvent) GetIncomingChannelId() uint64 { + if m != nil { + return m.IncomingChannelId + } + return 0 +} + +func (m *HtlcEvent) GetOutgoingChannelId() uint64 { + if m != nil { + return m.OutgoingChannelId + } + return 0 +} + +func (m *HtlcEvent) GetIncomingHtlcId() uint64 { + if m != nil { + return m.IncomingHtlcId + } + return 0 +} + +func (m *HtlcEvent) GetOutgoingHtlcId() uint64 { + if m != nil { + return m.OutgoingHtlcId + } + return 0 +} + +func (m *HtlcEvent) GetTimestampNs() uint64 { + if m != nil { + return m.TimestampNs + } + return 0 +} + +func (m *HtlcEvent) GetEventType() HtlcEvent_EventType { + if m != nil { + return m.EventType + } + return HtlcEvent_UNKNOWN +} + +type isHtlcEvent_Event interface { + isHtlcEvent_Event() +} + +type HtlcEvent_ForwardEvent struct { + ForwardEvent *ForwardEvent `protobuf:"bytes,7,opt,name=forward_event,json=forwardEvent,proto3,oneof"` +} + +type HtlcEvent_ForwardFailEvent struct { + ForwardFailEvent *ForwardFailEvent `protobuf:"bytes,8,opt,name=forward_fail_event,json=forwardFailEvent,proto3,oneof"` +} + +type HtlcEvent_SettleEvent struct { + SettleEvent *SettleEvent `protobuf:"bytes,9,opt,name=settle_event,json=settleEvent,proto3,oneof"` +} + +type HtlcEvent_LinkFailEvent struct { + LinkFailEvent *LinkFailEvent `protobuf:"bytes,10,opt,name=link_fail_event,json=linkFailEvent,proto3,oneof"` +} + +func (*HtlcEvent_ForwardEvent) isHtlcEvent_Event() {} + +func (*HtlcEvent_ForwardFailEvent) isHtlcEvent_Event() {} + +func (*HtlcEvent_SettleEvent) isHtlcEvent_Event() {} + +func (*HtlcEvent_LinkFailEvent) isHtlcEvent_Event() {} + +func (m *HtlcEvent) GetEvent() isHtlcEvent_Event { + if m != nil { + return m.Event + } + return nil +} + +func (m *HtlcEvent) GetForwardEvent() *ForwardEvent { + if x, ok := m.GetEvent().(*HtlcEvent_ForwardEvent); ok { + return x.ForwardEvent + } + return nil +} + +func (m *HtlcEvent) GetForwardFailEvent() *ForwardFailEvent { + if x, ok := m.GetEvent().(*HtlcEvent_ForwardFailEvent); ok { + return x.ForwardFailEvent + } + return nil +} + +func (m *HtlcEvent) GetSettleEvent() *SettleEvent { + if x, ok := m.GetEvent().(*HtlcEvent_SettleEvent); ok { + return x.SettleEvent + } + return nil +} + +func (m *HtlcEvent) GetLinkFailEvent() *LinkFailEvent { + if x, ok := m.GetEvent().(*HtlcEvent_LinkFailEvent); ok { + return x.LinkFailEvent + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*HtlcEvent) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*HtlcEvent_ForwardEvent)(nil), + (*HtlcEvent_ForwardFailEvent)(nil), + (*HtlcEvent_SettleEvent)(nil), + (*HtlcEvent_LinkFailEvent)(nil), + } +} + +type HtlcInfo struct { + // The timelock on the incoming htlc. + IncomingTimelock uint32 `protobuf:"varint,1,opt,name=incoming_timelock,json=incomingTimelock,proto3" json:"incoming_timelock,omitempty"` + // The timelock on the outgoing htlc. + OutgoingTimelock uint32 `protobuf:"varint,2,opt,name=outgoing_timelock,json=outgoingTimelock,proto3" json:"outgoing_timelock,omitempty"` + // The amount of the incoming htlc. + IncomingAmtMsat uint64 `protobuf:"varint,3,opt,name=incoming_amt_msat,json=incomingAmtMsat,proto3" json:"incoming_amt_msat,omitempty"` + // The amount of the outgoing htlc. + OutgoingAmtMsat uint64 `protobuf:"varint,4,opt,name=outgoing_amt_msat,json=outgoingAmtMsat,proto3" json:"outgoing_amt_msat,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HtlcInfo) Reset() { *m = HtlcInfo{} } +func (m *HtlcInfo) String() string { return proto.CompactTextString(m) } +func (*HtlcInfo) ProtoMessage() {} +func (*HtlcInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{19} +} + +func (m *HtlcInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HtlcInfo.Unmarshal(m, b) +} +func (m *HtlcInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HtlcInfo.Marshal(b, m, deterministic) +} +func (m *HtlcInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_HtlcInfo.Merge(m, src) +} +func (m *HtlcInfo) XXX_Size() int { + return xxx_messageInfo_HtlcInfo.Size(m) +} +func (m *HtlcInfo) XXX_DiscardUnknown() { + xxx_messageInfo_HtlcInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_HtlcInfo proto.InternalMessageInfo + +func (m *HtlcInfo) GetIncomingTimelock() uint32 { + if m != nil { + return m.IncomingTimelock + } + return 0 +} + +func (m *HtlcInfo) GetOutgoingTimelock() uint32 { + if m != nil { + return m.OutgoingTimelock + } + return 0 +} + +func (m *HtlcInfo) GetIncomingAmtMsat() uint64 { + if m != nil { + return m.IncomingAmtMsat + } + return 0 +} + +func (m *HtlcInfo) GetOutgoingAmtMsat() uint64 { + if m != nil { + return m.OutgoingAmtMsat + } + return 0 +} + +type ForwardEvent struct { + // Info contains details about the htlc that was forwarded. + Info *HtlcInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ForwardEvent) Reset() { *m = ForwardEvent{} } +func (m *ForwardEvent) String() string { return proto.CompactTextString(m) } +func (*ForwardEvent) ProtoMessage() {} +func (*ForwardEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{20} +} + +func (m *ForwardEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ForwardEvent.Unmarshal(m, b) +} +func (m *ForwardEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ForwardEvent.Marshal(b, m, deterministic) +} +func (m *ForwardEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_ForwardEvent.Merge(m, src) +} +func (m *ForwardEvent) XXX_Size() int { + return xxx_messageInfo_ForwardEvent.Size(m) +} +func (m *ForwardEvent) XXX_DiscardUnknown() { + xxx_messageInfo_ForwardEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_ForwardEvent proto.InternalMessageInfo + +func (m *ForwardEvent) GetInfo() *HtlcInfo { + if m != nil { + return m.Info + } + return nil +} + +type ForwardFailEvent struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ForwardFailEvent) Reset() { *m = ForwardFailEvent{} } +func (m *ForwardFailEvent) String() string { return proto.CompactTextString(m) } +func (*ForwardFailEvent) ProtoMessage() {} +func (*ForwardFailEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{21} +} + +func (m *ForwardFailEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ForwardFailEvent.Unmarshal(m, b) +} +func (m *ForwardFailEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ForwardFailEvent.Marshal(b, m, deterministic) +} +func (m *ForwardFailEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_ForwardFailEvent.Merge(m, src) +} +func (m *ForwardFailEvent) XXX_Size() int { + return xxx_messageInfo_ForwardFailEvent.Size(m) +} +func (m *ForwardFailEvent) XXX_DiscardUnknown() { + xxx_messageInfo_ForwardFailEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_ForwardFailEvent proto.InternalMessageInfo + +type SettleEvent struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SettleEvent) Reset() { *m = SettleEvent{} } +func (m *SettleEvent) String() string { return proto.CompactTextString(m) } +func (*SettleEvent) ProtoMessage() {} +func (*SettleEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{22} +} + +func (m *SettleEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SettleEvent.Unmarshal(m, b) +} +func (m *SettleEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SettleEvent.Marshal(b, m, deterministic) +} +func (m *SettleEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_SettleEvent.Merge(m, src) +} +func (m *SettleEvent) XXX_Size() int { + return xxx_messageInfo_SettleEvent.Size(m) +} +func (m *SettleEvent) XXX_DiscardUnknown() { + xxx_messageInfo_SettleEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_SettleEvent proto.InternalMessageInfo + +type LinkFailEvent struct { + // Info contains details about the htlc that we failed. + Info *HtlcInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` + // FailureCode is the BOLT error code for the failure. + WireFailure lnrpc.Failure_FailureCode `protobuf:"varint,2,opt,name=wire_failure,json=wireFailure,proto3,enum=lnrpc.Failure_FailureCode" json:"wire_failure,omitempty"` + //* + //FailureDetail provides additional information about the reason for the + //failure. This detail enriches the information provided by the wire message + //and may be 'no detail' if the wire message requires no additional metadata. + FailureDetail FailureDetail `protobuf:"varint,3,opt,name=failure_detail,json=failureDetail,proto3,enum=routerrpc.FailureDetail" json:"failure_detail,omitempty"` + // A string representation of the link failure. + FailureString string `protobuf:"bytes,4,opt,name=failure_string,json=failureString,proto3" json:"failure_string,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LinkFailEvent) Reset() { *m = LinkFailEvent{} } +func (m *LinkFailEvent) String() string { return proto.CompactTextString(m) } +func (*LinkFailEvent) ProtoMessage() {} +func (*LinkFailEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{23} +} + +func (m *LinkFailEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LinkFailEvent.Unmarshal(m, b) +} +func (m *LinkFailEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LinkFailEvent.Marshal(b, m, deterministic) +} +func (m *LinkFailEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_LinkFailEvent.Merge(m, src) +} +func (m *LinkFailEvent) XXX_Size() int { + return xxx_messageInfo_LinkFailEvent.Size(m) +} +func (m *LinkFailEvent) XXX_DiscardUnknown() { + xxx_messageInfo_LinkFailEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_LinkFailEvent proto.InternalMessageInfo + +func (m *LinkFailEvent) GetInfo() *HtlcInfo { + if m != nil { + return m.Info + } + return nil +} + +func (m *LinkFailEvent) GetWireFailure() lnrpc.Failure_FailureCode { + if m != nil { + return m.WireFailure + } + return lnrpc.Failure_RESERVED +} + +func (m *LinkFailEvent) GetFailureDetail() FailureDetail { + if m != nil { + return m.FailureDetail + } + return FailureDetail_UNKNOWN +} + +func (m *LinkFailEvent) GetFailureString() string { + if m != nil { + return m.FailureString + } + return "" +} + func init() { proto.RegisterEnum("routerrpc.PaymentState", PaymentState_name, PaymentState_value) + proto.RegisterEnum("routerrpc.FailureDetail", FailureDetail_name, FailureDetail_value) + proto.RegisterEnum("routerrpc.HtlcEvent_EventType", HtlcEvent_EventType_name, HtlcEvent_EventType_value) proto.RegisterType((*SendPaymentRequest)(nil), "routerrpc.SendPaymentRequest") proto.RegisterMapType((map[uint64][]byte)(nil), "routerrpc.SendPaymentRequest.DestCustomRecordsEntry") proto.RegisterType((*TrackPaymentRequest)(nil), "routerrpc.TrackPaymentRequest") @@ -1138,100 +1711,154 @@ func init() { proto.RegisterType((*QueryProbabilityResponse)(nil), "routerrpc.QueryProbabilityResponse") proto.RegisterType((*BuildRouteRequest)(nil), "routerrpc.BuildRouteRequest") proto.RegisterType((*BuildRouteResponse)(nil), "routerrpc.BuildRouteResponse") + proto.RegisterType((*SubscribeHtlcEventsRequest)(nil), "routerrpc.SubscribeHtlcEventsRequest") + proto.RegisterType((*HtlcEvent)(nil), "routerrpc.HtlcEvent") + proto.RegisterType((*HtlcInfo)(nil), "routerrpc.HtlcInfo") + proto.RegisterType((*ForwardEvent)(nil), "routerrpc.ForwardEvent") + proto.RegisterType((*ForwardFailEvent)(nil), "routerrpc.ForwardFailEvent") + proto.RegisterType((*SettleEvent)(nil), "routerrpc.SettleEvent") + proto.RegisterType((*LinkFailEvent)(nil), "routerrpc.LinkFailEvent") } func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 1404 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdb, 0x52, 0xdb, 0xd6, - 0x1a, 0xde, 0xf2, 0x09, 0xf3, 0xdb, 0x18, 0x65, 0xb1, 0x27, 0xd1, 0x36, 0x21, 0xf1, 0xd6, 0xce, - 0x26, 0x9e, 0x4e, 0x02, 0x09, 0xed, 0x74, 0x32, 0xbd, 0xe8, 0x0c, 0xf8, 0x50, 0x4c, 0xcd, 0x21, - 0xcb, 0xe6, 0xa2, 0xcd, 0x85, 0x46, 0x58, 0xcb, 0x58, 0x45, 0xd2, 0x72, 0xb5, 0x96, 0x92, 0xe1, - 0x15, 0xfa, 0x22, 0xed, 0x4d, 0xfb, 0x5c, 0x7d, 0x84, 0x5e, 0x76, 0xd6, 0x41, 0x58, 0x36, 0x36, - 0xe9, 0x9d, 0xf5, 0xfd, 0xdf, 0x7f, 0x5a, 0xff, 0x09, 0xe0, 0x71, 0x4c, 0x13, 0x4e, 0xe2, 0x78, - 0x3a, 0xda, 0x57, 0xbf, 0xf6, 0xa6, 0x31, 0xe5, 0x14, 0xad, 0xdf, 0xe1, 0xf5, 0xf5, 0x78, 0x3a, - 0x52, 0xa8, 0xfd, 0x57, 0x11, 0xd0, 0x80, 0x44, 0xde, 0x85, 0x7b, 0x1b, 0x92, 0x88, 0x63, 0xf2, - 0x73, 0x42, 0x18, 0x47, 0x08, 0x0a, 0x1e, 0x61, 0xdc, 0x32, 0x1a, 0x46, 0xb3, 0x8a, 0xe5, 0x6f, - 0x64, 0x42, 0xde, 0x0d, 0xb9, 0x95, 0x6b, 0x18, 0xcd, 0x3c, 0x16, 0x3f, 0xd1, 0x7f, 0xa0, 0xec, - 0x86, 0xdc, 0x09, 0x99, 0xcb, 0xad, 0xaa, 0x84, 0xd7, 0xdc, 0x90, 0x9f, 0x32, 0x97, 0xa3, 0xff, - 0x42, 0x75, 0xaa, 0x4c, 0x3a, 0x13, 0x97, 0x4d, 0xac, 0xbc, 0x34, 0x54, 0xd1, 0xd8, 0xb1, 0xcb, - 0x26, 0xa8, 0x09, 0xe6, 0xd8, 0x8f, 0xdc, 0xc0, 0x19, 0x05, 0xfc, 0xa3, 0xe3, 0x91, 0x80, 0xbb, - 0x56, 0xa1, 0x61, 0x34, 0x8b, 0xb8, 0x26, 0xf1, 0x56, 0xc0, 0x3f, 0xb6, 0x05, 0x8a, 0x5e, 0xc2, - 0x66, 0x6a, 0x2c, 0x56, 0x01, 0x5a, 0xc5, 0x86, 0xd1, 0x5c, 0xc7, 0xb5, 0xe9, 0x7c, 0xd8, 0x2f, - 0x61, 0x93, 0xfb, 0x21, 0xa1, 0x09, 0x77, 0x18, 0x19, 0xd1, 0xc8, 0x63, 0x56, 0x49, 0x59, 0xd4, - 0xf0, 0x40, 0xa1, 0xc8, 0x86, 0x8d, 0x31, 0x21, 0x4e, 0xe0, 0x87, 0x3e, 0x77, 0x44, 0xf8, 0x6b, - 0x32, 0xfc, 0xca, 0x98, 0x90, 0xbe, 0xc0, 0x06, 0x2e, 0x47, 0x2f, 0xa0, 0x36, 0xe3, 0xc8, 0x1c, - 0x37, 0x24, 0xa9, 0x9a, 0x92, 0x64, 0xa2, 0xaf, 0xc0, 0xa4, 0x09, 0xbf, 0xa6, 0x7e, 0x74, 0xed, - 0x8c, 0x26, 0x6e, 0xe4, 0xf8, 0x9e, 0x55, 0x6e, 0x18, 0xcd, 0xc2, 0x51, 0xee, 0x8d, 0x81, 0x6b, - 0xa9, 0xac, 0x35, 0x71, 0xa3, 0x9e, 0x87, 0x76, 0x61, 0x33, 0x70, 0x19, 0x77, 0x26, 0x74, 0xea, - 0x4c, 0x93, 0xab, 0x1b, 0x72, 0x6b, 0xd5, 0xe4, 0xcb, 0x6c, 0x08, 0xf8, 0x98, 0x4e, 0x2f, 0x24, - 0x88, 0x76, 0x00, 0xe4, 0xab, 0x48, 0xe7, 0xd6, 0xba, 0xcc, 0x61, 0x5d, 0x20, 0xd2, 0x31, 0x7a, - 0x0b, 0x15, 0x59, 0x4d, 0x67, 0xe2, 0x47, 0x9c, 0x59, 0xd0, 0xc8, 0x37, 0x2b, 0x07, 0xe6, 0x5e, - 0x10, 0x89, 0xc2, 0x62, 0x21, 0x39, 0xf6, 0x23, 0x8e, 0x21, 0x4e, 0x7f, 0x32, 0xe4, 0xc1, 0x96, - 0xa8, 0xa2, 0x33, 0x4a, 0x18, 0xa7, 0xa1, 0x13, 0x93, 0x11, 0x8d, 0x3d, 0x66, 0x55, 0xa4, 0xea, - 0x57, 0x7b, 0x77, 0xcd, 0xb1, 0x77, 0xbf, 0x1b, 0xf6, 0xda, 0x84, 0xf1, 0x96, 0xd4, 0xc3, 0x4a, - 0xad, 0x13, 0xf1, 0xf8, 0x16, 0x3f, 0xf2, 0x16, 0x71, 0xf4, 0x0a, 0x90, 0x1b, 0x04, 0xf4, 0x93, - 0xc3, 0x48, 0x30, 0x76, 0x74, 0x75, 0xac, 0xcd, 0x86, 0xd1, 0x2c, 0x63, 0x53, 0x4a, 0x06, 0x24, - 0x18, 0x6b, 0xf3, 0xe8, 0x6b, 0xd8, 0x90, 0x31, 0x8d, 0x89, 0xcb, 0x93, 0x98, 0x30, 0xcb, 0x6c, - 0xe4, 0x9b, 0xb5, 0x83, 0x47, 0x3a, 0x91, 0xae, 0x82, 0x8f, 0x7c, 0x8e, 0xab, 0x82, 0xa7, 0xbf, - 0x59, 0xbd, 0x0d, 0x8f, 0x97, 0x87, 0x24, 0x7a, 0x54, 0xbc, 0xa9, 0x68, 0xdb, 0x02, 0x16, 0x3f, - 0xd1, 0xbf, 0xa1, 0xf8, 0xd1, 0x0d, 0x12, 0x22, 0xfb, 0xb6, 0x8a, 0xd5, 0xc7, 0x37, 0xb9, 0x77, - 0x86, 0xfd, 0x0e, 0xb6, 0x86, 0xb1, 0x3b, 0xba, 0x59, 0x68, 0xfd, 0xc5, 0xce, 0x35, 0xee, 0x75, - 0xae, 0xfd, 0x9b, 0x01, 0x1b, 0x5a, 0x6b, 0xc0, 0x5d, 0x9e, 0x30, 0xf4, 0x1a, 0x8a, 0x8c, 0xbb, - 0x9c, 0x48, 0x76, 0xed, 0xe0, 0x49, 0xe6, 0x3d, 0x33, 0x44, 0x82, 0x15, 0x0b, 0xd5, 0xa1, 0x3c, - 0x8d, 0x89, 0x1f, 0xba, 0xd7, 0x69, 0x5c, 0x77, 0xdf, 0xc8, 0x86, 0xa2, 0x54, 0x96, 0x23, 0x53, - 0x39, 0xa8, 0x66, 0xab, 0x8a, 0x95, 0x08, 0x35, 0xa1, 0x38, 0xe1, 0xc1, 0x88, 0x59, 0x05, 0x59, - 0x3e, 0xa4, 0x39, 0xc7, 0xc3, 0x7e, 0xeb, 0x90, 0x73, 0x12, 0x4e, 0x39, 0x56, 0x04, 0xfb, 0x5b, - 0xd8, 0x94, 0x9a, 0x5d, 0x42, 0x1e, 0x9a, 0xed, 0x27, 0x20, 0x26, 0x57, 0x4e, 0x82, 0x9a, 0xef, - 0x92, 0x1b, 0x8a, 0x21, 0xb0, 0x3d, 0x30, 0x67, 0xfa, 0x6c, 0x4a, 0x23, 0x26, 0xbc, 0x9b, 0x22, - 0x0c, 0xd1, 0xf1, 0x62, 0x40, 0xe4, 0x68, 0x18, 0x52, 0xab, 0xa6, 0xf1, 0x2e, 0x21, 0x72, 0x38, - 0x76, 0xd5, 0x3c, 0x3a, 0x01, 0x1d, 0xdd, 0x88, 0x09, 0x77, 0x6f, 0xb5, 0xf9, 0x0d, 0x01, 0xf7, - 0xe9, 0xe8, 0xa6, 0x2d, 0x40, 0xfb, 0x83, 0x5a, 0x42, 0x43, 0xaa, 0xb2, 0xfc, 0xc7, 0x95, 0x98, - 0x3d, 0x56, 0x6e, 0xe5, 0x63, 0xd9, 0x1f, 0x60, 0x6b, 0xce, 0xb8, 0xce, 0x22, 0x5b, 0x03, 0x63, - 0xa1, 0x06, 0x4d, 0x58, 0x1b, 0xbb, 0x7e, 0x90, 0xc4, 0xa9, 0xe1, 0x5a, 0xda, 0x92, 0x0a, 0xc5, - 0xa9, 0xd8, 0x7e, 0x0a, 0x75, 0x4c, 0x18, 0xe1, 0xa7, 0x3e, 0x63, 0x3e, 0x8d, 0x5a, 0x34, 0xe2, - 0x31, 0x0d, 0x74, 0x06, 0xf6, 0x0e, 0x6c, 0x2f, 0x95, 0xaa, 0x10, 0x84, 0xf2, 0xfb, 0x84, 0xc4, - 0xb7, 0xcb, 0x95, 0xdf, 0xc3, 0xf6, 0x52, 0xa9, 0x8e, 0xff, 0x15, 0x14, 0xa7, 0xae, 0x1f, 0x33, - 0x2b, 0x27, 0x7b, 0xe0, 0xf1, 0x5c, 0xcb, 0xf9, 0xf1, 0xb1, 0xcf, 0x38, 0x8d, 0x6f, 0xb1, 0x22, - 0x9d, 0x14, 0xca, 0x86, 0x99, 0xb3, 0x7f, 0x31, 0xa0, 0x92, 0x11, 0xa2, 0x6d, 0x58, 0x8f, 0xa8, - 0x47, 0x9c, 0x71, 0x4c, 0xc3, 0xf4, 0x11, 0x04, 0xd0, 0x8d, 0x69, 0x28, 0x7a, 0x42, 0x0a, 0x39, - 0xd5, 0x3d, 0x5a, 0x12, 0x9f, 0x43, 0x8a, 0x5e, 0xc3, 0xda, 0x44, 0x19, 0x90, 0x6b, 0xb3, 0x72, - 0xb0, 0xb5, 0xe0, 0xbb, 0xed, 0x72, 0x17, 0xa7, 0x9c, 0x93, 0x42, 0x39, 0x6f, 0x16, 0x4e, 0x0a, - 0xe5, 0x82, 0x59, 0x3c, 0x29, 0x94, 0x8b, 0x66, 0xe9, 0xa4, 0x50, 0x2e, 0x99, 0x6b, 0xf6, 0x9f, - 0x06, 0x94, 0x53, 0xb6, 0x88, 0x44, 0x3c, 0xa9, 0x23, 0xfa, 0x42, 0x37, 0x53, 0x59, 0x00, 0x43, - 0x3f, 0x24, 0xa8, 0x01, 0x55, 0x29, 0x9c, 0x6f, 0x51, 0x10, 0xd8, 0xa1, 0x6c, 0x53, 0xb9, 0xcf, - 0x53, 0x86, 0xec, 0xc7, 0x82, 0xde, 0xe7, 0x8a, 0x92, 0x9e, 0x24, 0x96, 0x8c, 0x46, 0x84, 0x31, - 0xe5, 0xa5, 0xa8, 0x28, 0x1a, 0x93, 0x8e, 0x76, 0x61, 0x33, 0xa5, 0xa4, 0xbe, 0x4a, 0xaa, 0x5f, - 0x35, 0xac, 0xdd, 0x35, 0xc1, 0xcc, 0xf2, 0xc2, 0xd9, 0x05, 0xa9, 0xcd, 0x88, 0xc2, 0xa9, 0x4a, - 0xde, 0xfe, 0x09, 0x9e, 0xc8, 0x52, 0x5e, 0xc4, 0xf4, 0xca, 0xbd, 0xf2, 0x03, 0x9f, 0xdf, 0xa6, - 0x4d, 0x2e, 0x12, 0x8f, 0x69, 0xe8, 0x88, 0xb7, 0x4d, 0x4b, 0x20, 0x80, 0x33, 0xea, 0x11, 0x51, - 0x02, 0x4e, 0x95, 0x48, 0x97, 0x80, 0x53, 0x29, 0xc8, 0x5e, 0xde, 0xfc, 0xdc, 0xe5, 0xb5, 0x6f, - 0xc0, 0xba, 0xef, 0x4b, 0xf7, 0x4c, 0x03, 0x2a, 0xd3, 0x19, 0x2c, 0xdd, 0x19, 0x38, 0x0b, 0x65, - 0x6b, 0x9b, 0xfb, 0x7c, 0x6d, 0xed, 0x5f, 0x0d, 0x78, 0x74, 0x94, 0xf8, 0x81, 0x37, 0x37, 0xb8, - 0xd9, 0xe8, 0x8c, 0xf9, 0xbf, 0x0b, 0x96, 0x1d, 0xfd, 0xdc, 0xd2, 0xa3, 0xbf, 0xec, 0xb0, 0xe6, - 0x57, 0x1e, 0xd6, 0xe7, 0x50, 0x99, 0xdd, 0x54, 0xb5, 0x17, 0xab, 0x18, 0x26, 0xe9, 0x41, 0x65, - 0xf6, 0x3b, 0x40, 0xd9, 0x40, 0xf5, 0x83, 0xdc, 0xed, 0x0f, 0x63, 0xe5, 0xfe, 0xf8, 0xe2, 0x0f, - 0x03, 0xaa, 0xd9, 0x25, 0x8e, 0x36, 0x60, 0xbd, 0x77, 0xe6, 0x74, 0xfb, 0xbd, 0xef, 0x8e, 0x87, - 0xe6, 0xbf, 0xc4, 0xe7, 0xe0, 0xb2, 0xd5, 0xea, 0x74, 0xda, 0x9d, 0xb6, 0x69, 0x20, 0x04, 0xb5, - 0xee, 0x61, 0xaf, 0xdf, 0x69, 0x3b, 0xc3, 0xde, 0x69, 0xe7, 0xfc, 0x72, 0x68, 0xe6, 0xd0, 0x16, - 0x6c, 0x6a, 0xec, 0xec, 0xdc, 0xc1, 0xe7, 0x97, 0xc3, 0x8e, 0x99, 0x47, 0x26, 0x54, 0x35, 0xd8, - 0xc1, 0xf8, 0x1c, 0x9b, 0x05, 0xf4, 0x02, 0x1a, 0x1a, 0xe9, 0x9d, 0xb5, 0xce, 0x31, 0xee, 0xb4, - 0x86, 0xce, 0xc5, 0xe1, 0x0f, 0xa7, 0x9d, 0xb3, 0xa1, 0xd3, 0xee, 0x0c, 0x0f, 0x7b, 0xfd, 0x81, - 0x59, 0x44, 0xcf, 0x61, 0xfb, 0x8e, 0x35, 0xb8, 0xec, 0x76, 0x7b, 0xad, 0x9e, 0x20, 0x1c, 0x1d, - 0xf6, 0x0f, 0xcf, 0x5a, 0x1d, 0xb3, 0x74, 0xf0, 0x7b, 0x11, 0x4a, 0x32, 0x83, 0x18, 0x1d, 0x43, - 0x25, 0x73, 0xcf, 0xd1, 0xce, 0x83, 0x77, 0xbe, 0x6e, 0x2d, 0x3f, 0x5b, 0x09, 0x7b, 0x63, 0xa0, - 0x13, 0xa8, 0x66, 0xaf, 0x25, 0x7a, 0x96, 0xe1, 0x2e, 0x39, 0xa3, 0x0f, 0xda, 0xfa, 0x1e, 0xcc, - 0x0e, 0xe3, 0x7e, 0x28, 0x2e, 0xa2, 0x3e, 0x2e, 0xa8, 0x9e, 0xe1, 0x2f, 0x5c, 0xac, 0xfa, 0xf6, - 0x52, 0x99, 0x2e, 0x61, 0x5f, 0xa5, 0xa8, 0xd7, 0xfb, 0xbd, 0x14, 0xe7, 0x6f, 0x4a, 0xfd, 0xd9, - 0x2a, 0xb1, 0xb6, 0xe6, 0xc1, 0xd6, 0x92, 0x8d, 0x8d, 0xfe, 0x9f, 0x8d, 0x60, 0xe5, 0xbe, 0xaf, - 0xef, 0x7e, 0x8e, 0x36, 0xf3, 0xb2, 0x64, 0xb5, 0xcf, 0x79, 0x59, 0x7d, 0x18, 0xe6, 0xbc, 0x3c, - 0x74, 0x21, 0x3e, 0x80, 0xb9, 0xb8, 0x09, 0x90, 0xbd, 0xa8, 0x7b, 0x7f, 0x25, 0xd5, 0xff, 0xf7, - 0x20, 0x47, 0x1b, 0xef, 0x01, 0xcc, 0xe6, 0x09, 0x3d, 0xcd, 0xa8, 0xdc, 0xdb, 0x07, 0xf5, 0x9d, - 0x15, 0x52, 0x65, 0xea, 0xe8, 0xed, 0x8f, 0xfb, 0xd7, 0x3e, 0x9f, 0x24, 0x57, 0x7b, 0x23, 0x1a, - 0xee, 0x07, 0xfe, 0xf5, 0x84, 0x47, 0x7e, 0x74, 0x1d, 0x11, 0xfe, 0x89, 0xc6, 0x37, 0xfb, 0x41, - 0xe4, 0xed, 0xcb, 0xb1, 0xdc, 0xbf, 0xb3, 0x72, 0x55, 0x92, 0xff, 0xbd, 0x7c, 0xf9, 0x77, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x30, 0x2f, 0x8a, 0x5c, 0xed, 0x0c, 0x00, 0x00, + // 2155 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xdd, 0x72, 0xdb, 0xc6, + 0x15, 0x36, 0x28, 0x50, 0x22, 0x0f, 0x7f, 0x04, 0xad, 0x1c, 0x99, 0xa5, 0xec, 0x44, 0x41, 0x13, + 0x9b, 0xe3, 0x3a, 0x92, 0xa3, 0x76, 0x5a, 0x4f, 0xdb, 0xa4, 0x43, 0x91, 0x90, 0x09, 0x99, 0x02, + 0x98, 0x25, 0xe4, 0x9f, 0xfa, 0x62, 0x07, 0x22, 0x97, 0x22, 0x2a, 0x10, 0x60, 0x81, 0xa5, 0x3d, + 0xba, 0xec, 0xf4, 0xae, 0x2f, 0xd2, 0x5e, 0xf5, 0x09, 0xfa, 0x2e, 0xbd, 0xed, 0x13, 0x74, 0x7a, + 0xd9, 0xd9, 0xc5, 0x82, 0x04, 0x29, 0xca, 0xc9, 0x8d, 0x4d, 0x7c, 0xe7, 0xdb, 0xb3, 0xe7, 0x77, + 0xcf, 0xae, 0x60, 0x2f, 0x0a, 0x67, 0x8c, 0x46, 0xd1, 0x74, 0x70, 0x94, 0xfc, 0x3a, 0x9c, 0x46, + 0x21, 0x0b, 0x51, 0x71, 0x8e, 0xd7, 0x8b, 0xd1, 0x74, 0x90, 0xa0, 0xfa, 0xff, 0xf2, 0x80, 0xfa, + 0x34, 0x18, 0xf6, 0xdc, 0x9b, 0x09, 0x0d, 0x18, 0xa6, 0x7f, 0x9e, 0xd1, 0x98, 0x21, 0x04, 0xea, + 0x90, 0xc6, 0xac, 0xa6, 0x1c, 0x28, 0x8d, 0x32, 0x16, 0xbf, 0x91, 0x06, 0x1b, 0xee, 0x84, 0xd5, + 0x72, 0x07, 0x4a, 0x63, 0x03, 0xf3, 0x9f, 0xe8, 0x67, 0x50, 0x70, 0x27, 0x8c, 0x4c, 0x62, 0x97, + 0xd5, 0xca, 0x02, 0xde, 0x72, 0x27, 0xec, 0x3c, 0x76, 0x19, 0xfa, 0x12, 0xca, 0xd3, 0x44, 0x25, + 0x19, 0xbb, 0xf1, 0xb8, 0xb6, 0x21, 0x14, 0x95, 0x24, 0xd6, 0x71, 0xe3, 0x31, 0x6a, 0x80, 0x36, + 0xf2, 0x02, 0xd7, 0x27, 0x03, 0x9f, 0x7d, 0x20, 0x43, 0xea, 0x33, 0xb7, 0xa6, 0x1e, 0x28, 0x8d, + 0x3c, 0xae, 0x0a, 0xbc, 0xe5, 0xb3, 0x0f, 0x6d, 0x8e, 0xa2, 0x27, 0xb0, 0x9d, 0x2a, 0x8b, 0x12, + 0x03, 0x6b, 0xf9, 0x03, 0xa5, 0x51, 0xc4, 0xd5, 0xe9, 0xb2, 0xd9, 0x4f, 0x60, 0x9b, 0x79, 0x13, + 0x1a, 0xce, 0x18, 0x89, 0xe9, 0x20, 0x0c, 0x86, 0x71, 0x6d, 0x33, 0xd1, 0x28, 0xe1, 0x7e, 0x82, + 0x22, 0x1d, 0x2a, 0x23, 0x4a, 0x89, 0xef, 0x4d, 0x3c, 0x46, 0xb8, 0xf9, 0x5b, 0xc2, 0xfc, 0xd2, + 0x88, 0xd2, 0x2e, 0xc7, 0xfa, 0x2e, 0x43, 0x5f, 0x41, 0x75, 0xc1, 0x11, 0x3e, 0x56, 0x04, 0xa9, + 0x9c, 0x92, 0x84, 0xa3, 0xcf, 0x40, 0x0b, 0x67, 0xec, 0x2a, 0xf4, 0x82, 0x2b, 0x32, 0x18, 0xbb, + 0x01, 0xf1, 0x86, 0xb5, 0xc2, 0x81, 0xd2, 0x50, 0x4f, 0x72, 0xcf, 0x15, 0x5c, 0x4d, 0x65, 0xad, + 0xb1, 0x1b, 0x98, 0x43, 0xf4, 0x18, 0xb6, 0x7d, 0x37, 0x66, 0x64, 0x1c, 0x4e, 0xc9, 0x74, 0x76, + 0x79, 0x4d, 0x6f, 0x6a, 0x55, 0x11, 0x99, 0x0a, 0x87, 0x3b, 0xe1, 0xb4, 0x27, 0x40, 0xf4, 0x08, + 0x40, 0x44, 0x45, 0x6c, 0x5e, 0x2b, 0x0a, 0x1f, 0x8a, 0x1c, 0x11, 0x1b, 0xa3, 0x6f, 0xa1, 0x24, + 0xb2, 0x49, 0xc6, 0x5e, 0xc0, 0xe2, 0x1a, 0x1c, 0x6c, 0x34, 0x4a, 0xc7, 0xda, 0xa1, 0x1f, 0xf0, + 0xc4, 0x62, 0x2e, 0xe9, 0x78, 0x01, 0xc3, 0x10, 0xa5, 0x3f, 0x63, 0x34, 0x84, 0x5d, 0x9e, 0x45, + 0x32, 0x98, 0xc5, 0x2c, 0x9c, 0x90, 0x88, 0x0e, 0xc2, 0x68, 0x18, 0xd7, 0x4a, 0x62, 0xe9, 0xaf, + 0x0e, 0xe7, 0xc5, 0x71, 0x78, 0xbb, 0x1a, 0x0e, 0xdb, 0x34, 0x66, 0x2d, 0xb1, 0x0e, 0x27, 0xcb, + 0x8c, 0x80, 0x45, 0x37, 0x78, 0x67, 0xb8, 0x8a, 0xa3, 0x67, 0x80, 0x5c, 0xdf, 0x0f, 0x3f, 0x92, + 0x98, 0xfa, 0x23, 0x22, 0xb3, 0x53, 0xdb, 0x3e, 0x50, 0x1a, 0x05, 0xac, 0x09, 0x49, 0x9f, 0xfa, + 0x23, 0xa9, 0x1e, 0xfd, 0x1a, 0x2a, 0xc2, 0xa6, 0x11, 0x75, 0xd9, 0x2c, 0xa2, 0x71, 0x4d, 0x3b, + 0xd8, 0x68, 0x54, 0x8f, 0x77, 0xa4, 0x23, 0xa7, 0x09, 0x7c, 0xe2, 0x31, 0x5c, 0xe6, 0x3c, 0xf9, + 0x1d, 0xd7, 0xdb, 0xb0, 0xb7, 0xde, 0x24, 0x5e, 0xa3, 0x3c, 0xa6, 0xbc, 0x6c, 0x55, 0xcc, 0x7f, + 0xa2, 0xfb, 0x90, 0xff, 0xe0, 0xfa, 0x33, 0x2a, 0xea, 0xb6, 0x8c, 0x93, 0x8f, 0xdf, 0xe6, 0x5e, + 0x28, 0xfa, 0x0b, 0xd8, 0x75, 0x22, 0x77, 0x70, 0xbd, 0x52, 0xfa, 0xab, 0x95, 0xab, 0xdc, 0xaa, + 0x5c, 0xfd, 0x1f, 0x0a, 0x54, 0xe4, 0xaa, 0x3e, 0x73, 0xd9, 0x2c, 0x46, 0xdf, 0x40, 0x3e, 0x66, + 0x2e, 0xa3, 0x82, 0x5d, 0x3d, 0x7e, 0x90, 0x89, 0x67, 0x86, 0x48, 0x71, 0xc2, 0x42, 0x75, 0x28, + 0x4c, 0x23, 0xea, 0x4d, 0xdc, 0xab, 0xd4, 0xae, 0xf9, 0x37, 0xd2, 0x21, 0x2f, 0x16, 0x8b, 0x96, + 0x29, 0x1d, 0x97, 0xb3, 0x59, 0xc5, 0x89, 0x08, 0x35, 0x20, 0x3f, 0x66, 0xfe, 0x20, 0xae, 0xa9, + 0x22, 0x7d, 0x48, 0x72, 0x3a, 0x4e, 0xb7, 0xd5, 0x64, 0x8c, 0x4e, 0xa6, 0x0c, 0x27, 0x04, 0xfd, + 0x7b, 0xd8, 0x16, 0x2b, 0x4f, 0x29, 0xfd, 0x54, 0x6f, 0x3f, 0x00, 0xde, 0xb9, 0xa2, 0x13, 0x92, + 0xfe, 0xde, 0x74, 0x27, 0xbc, 0x09, 0xf4, 0x21, 0x68, 0x8b, 0xf5, 0xf1, 0x34, 0x0c, 0x62, 0xbe, + 0xbb, 0xc6, 0xcd, 0xe0, 0x15, 0xcf, 0x1b, 0x44, 0xb4, 0x86, 0x22, 0x56, 0x55, 0x25, 0x7e, 0x4a, + 0xa9, 0x68, 0x8e, 0xc7, 0x49, 0x3f, 0x12, 0x3f, 0x1c, 0x5c, 0xf3, 0x0e, 0x77, 0x6f, 0xa4, 0xfa, + 0x0a, 0x87, 0xbb, 0xe1, 0xe0, 0xba, 0xcd, 0x41, 0xfd, 0x7d, 0x72, 0x08, 0x39, 0x61, 0xe2, 0xe5, + 0x4f, 0xce, 0xc4, 0x22, 0x58, 0xb9, 0x3b, 0x83, 0xa5, 0xbf, 0x87, 0xdd, 0x25, 0xe5, 0xd2, 0x8b, + 0x6c, 0x0e, 0x94, 0x95, 0x1c, 0x34, 0x60, 0x6b, 0xe4, 0x7a, 0xfe, 0x2c, 0x4a, 0x15, 0x57, 0xd3, + 0x92, 0x4c, 0x50, 0x9c, 0x8a, 0xf5, 0x87, 0x50, 0xc7, 0x34, 0xa6, 0xec, 0xdc, 0x8b, 0x63, 0x2f, + 0x0c, 0x5a, 0x61, 0xc0, 0xa2, 0xd0, 0x97, 0x1e, 0xe8, 0x8f, 0x60, 0x7f, 0xad, 0x34, 0x31, 0x81, + 0x2f, 0xfe, 0x61, 0x46, 0xa3, 0x9b, 0xf5, 0x8b, 0x7f, 0x80, 0xfd, 0xb5, 0x52, 0x69, 0xff, 0x33, + 0xc8, 0x4f, 0x5d, 0x2f, 0x8a, 0x6b, 0x39, 0x51, 0x03, 0x7b, 0x4b, 0x25, 0xe7, 0x45, 0x1d, 0x2f, + 0x66, 0x61, 0x74, 0x83, 0x13, 0xd2, 0x99, 0x5a, 0x50, 0xb4, 0x9c, 0xfe, 0x37, 0x05, 0x4a, 0x19, + 0x21, 0xda, 0x87, 0x62, 0x10, 0x0e, 0x29, 0x19, 0x45, 0xe1, 0x24, 0x0d, 0x02, 0x07, 0x4e, 0xa3, + 0x70, 0xc2, 0x6b, 0x42, 0x08, 0x59, 0x28, 0x6b, 0x74, 0x93, 0x7f, 0x3a, 0x21, 0xfa, 0x06, 0xb6, + 0xc6, 0x89, 0x02, 0x71, 0x6c, 0x96, 0x8e, 0x77, 0x57, 0xf6, 0x6e, 0xbb, 0xcc, 0xc5, 0x29, 0xe7, + 0x4c, 0x2d, 0x6c, 0x68, 0xea, 0x99, 0x5a, 0x50, 0xb5, 0xfc, 0x99, 0x5a, 0xc8, 0x6b, 0x9b, 0x67, + 0x6a, 0x61, 0x53, 0xdb, 0xd2, 0xff, 0xa3, 0x40, 0x21, 0x65, 0x73, 0x4b, 0x78, 0x48, 0x09, 0xaf, + 0x0b, 0x59, 0x4c, 0x05, 0x0e, 0x38, 0xde, 0x84, 0xa2, 0x03, 0x28, 0x0b, 0xe1, 0x72, 0x89, 0x02, + 0xc7, 0x9a, 0xa2, 0x4c, 0xc5, 0x79, 0x9e, 0x32, 0x44, 0x3d, 0xaa, 0xf2, 0x3c, 0x4f, 0x28, 0xe9, + 0x48, 0x8a, 0x67, 0x83, 0x01, 0x8d, 0xe3, 0x64, 0x97, 0x7c, 0x42, 0x91, 0x98, 0xd8, 0xe8, 0x31, + 0x6c, 0xa7, 0x94, 0x74, 0xaf, 0xcd, 0xa4, 0x5e, 0x25, 0x2c, 0xb7, 0x6b, 0x80, 0x96, 0xe5, 0x4d, + 0x16, 0x13, 0xa4, 0xba, 0x20, 0xf2, 0x4d, 0x13, 0xe7, 0xf5, 0x3f, 0xc1, 0x03, 0x91, 0xca, 0x5e, + 0x14, 0x5e, 0xba, 0x97, 0x9e, 0xef, 0xb1, 0x9b, 0xb4, 0xc8, 0xb9, 0xe3, 0x51, 0x38, 0x21, 0x3c, + 0xb6, 0x69, 0x0a, 0x38, 0x60, 0x85, 0x43, 0xca, 0x53, 0xc0, 0xc2, 0x44, 0x24, 0x53, 0xc0, 0x42, + 0x21, 0xc8, 0x4e, 0xde, 0x8d, 0xa5, 0xc9, 0xab, 0x5f, 0x43, 0xed, 0xf6, 0x5e, 0xb2, 0x66, 0x0e, + 0xa0, 0x34, 0x5d, 0xc0, 0x62, 0x3b, 0x05, 0x67, 0xa1, 0x6c, 0x6e, 0x73, 0x3f, 0x9e, 0x5b, 0xfd, + 0xef, 0x0a, 0xec, 0x9c, 0xcc, 0x3c, 0x7f, 0xb8, 0xd4, 0xb8, 0x59, 0xeb, 0x94, 0xe5, 0x7b, 0xc1, + 0xba, 0xa1, 0x9f, 0x5b, 0x3b, 0xf4, 0xd7, 0x0d, 0xd6, 0x8d, 0x3b, 0x07, 0xeb, 0x17, 0x50, 0x5a, + 0xcc, 0xd4, 0xe4, 0x5c, 0x2c, 0x63, 0x18, 0xa7, 0x03, 0x35, 0xd6, 0x5f, 0x00, 0xca, 0x1a, 0x2a, + 0x03, 0x32, 0x3f, 0x3f, 0x94, 0xbb, 0xcf, 0x8f, 0x87, 0x50, 0xef, 0xcf, 0x2e, 0xe3, 0x41, 0xe4, + 0x5d, 0xd2, 0x0e, 0xf3, 0x07, 0xc6, 0x07, 0x1a, 0xb0, 0x38, 0xed, 0xd2, 0xff, 0xaa, 0x50, 0x9c, + 0xa3, 0xe8, 0x10, 0x76, 0xbd, 0x60, 0x10, 0x4e, 0x52, 0xa3, 0x03, 0xea, 0x73, 0xbb, 0x93, 0x79, + 0xb4, 0x93, 0x8a, 0x5a, 0x89, 0xc4, 0x1c, 0x72, 0xfe, 0x92, 0x93, 0x92, 0x9f, 0x4b, 0xf8, 0x59, + 0x1f, 0x13, 0x7e, 0x03, 0xb4, 0xb9, 0x7e, 0x7e, 0xc0, 0xcf, 0x83, 0x82, 0xab, 0x29, 0xce, 0x8d, + 0x49, 0x98, 0x73, 0xcd, 0x29, 0x53, 0x4d, 0x98, 0x29, 0x2e, 0x99, 0x5f, 0x42, 0x99, 0xf7, 0x43, + 0xcc, 0xdc, 0xc9, 0x94, 0x04, 0xb1, 0xe8, 0x0b, 0x15, 0x97, 0xe6, 0x98, 0x15, 0xa3, 0xef, 0x00, + 0x28, 0xf7, 0x8f, 0xb0, 0x9b, 0x29, 0x15, 0x2d, 0x51, 0x3d, 0xfe, 0x3c, 0x53, 0x18, 0xf3, 0x00, + 0x1c, 0x8a, 0x7f, 0x9d, 0x9b, 0x29, 0xc5, 0x45, 0x9a, 0xfe, 0x44, 0xdf, 0x43, 0x65, 0x14, 0x46, + 0x1f, 0xdd, 0x68, 0x48, 0x04, 0x28, 0x8f, 0x8d, 0xec, 0x94, 0x3c, 0x4d, 0xe4, 0x62, 0x79, 0xe7, + 0x1e, 0x2e, 0x8f, 0x32, 0xdf, 0xe8, 0x15, 0xa0, 0x74, 0xbd, 0xe8, 0xf2, 0x44, 0x49, 0x41, 0x28, + 0xd9, 0xbf, 0xad, 0x84, 0x1f, 0xd2, 0xa9, 0x22, 0x6d, 0xb4, 0x82, 0xa1, 0xdf, 0x41, 0x39, 0xa6, + 0x8c, 0xf9, 0x54, 0xaa, 0x29, 0x0a, 0x35, 0x7b, 0x4b, 0x37, 0x20, 0x2e, 0x4e, 0x35, 0x94, 0xe2, + 0xc5, 0x27, 0x3a, 0x81, 0x6d, 0xdf, 0x0b, 0xae, 0xb3, 0x66, 0x80, 0x58, 0x5f, 0xcb, 0xac, 0xef, + 0x7a, 0xc1, 0x75, 0xd6, 0x86, 0x8a, 0x9f, 0x05, 0xf4, 0xdf, 0x43, 0x71, 0x1e, 0x25, 0x54, 0x82, + 0xad, 0x0b, 0xeb, 0x95, 0x65, 0xbf, 0xb1, 0xb4, 0x7b, 0xa8, 0x00, 0x6a, 0xdf, 0xb0, 0xda, 0x9a, + 0xc2, 0x61, 0x6c, 0xb4, 0x0c, 0xf3, 0xb5, 0xa1, 0xe5, 0xf8, 0xc7, 0xa9, 0x8d, 0xdf, 0x34, 0x71, + 0x5b, 0xdb, 0x38, 0xd9, 0x82, 0xbc, 0xd8, 0x57, 0xff, 0x97, 0x02, 0x05, 0x91, 0xc1, 0x60, 0x14, + 0xa2, 0x5f, 0xc0, 0xbc, 0xb8, 0xc4, 0xe1, 0xc6, 0x07, 0xae, 0xa8, 0xba, 0x0a, 0x9e, 0x17, 0x8c, + 0x23, 0x71, 0x4e, 0x9e, 0x97, 0xc6, 0x9c, 0x9c, 0x4b, 0xc8, 0xa9, 0x60, 0x4e, 0x7e, 0x9a, 0xd1, + 0xbc, 0x74, 0xe4, 0xa8, 0x78, 0x3b, 0x15, 0xa4, 0x27, 0xec, 0xd3, 0x8c, 0xe2, 0xa5, 0x93, 0x58, + 0xc5, 0xdb, 0xa9, 0x40, 0x72, 0xf5, 0xdf, 0x40, 0x39, 0x9b, 0x73, 0xf4, 0x04, 0x54, 0x2f, 0x18, + 0x85, 0xb2, 0x11, 0x77, 0x57, 0x8a, 0x8b, 0x3b, 0x89, 0x05, 0x41, 0x47, 0xa0, 0xad, 0xe6, 0x59, + 0xaf, 0x40, 0x29, 0x93, 0x34, 0xfd, 0xdf, 0x0a, 0x54, 0x96, 0x92, 0xf0, 0x93, 0xb5, 0xa3, 0xef, + 0xa0, 0xfc, 0xd1, 0x8b, 0x28, 0xc9, 0x8e, 0xff, 0xea, 0x71, 0x7d, 0x79, 0xfc, 0xa7, 0xff, 0xb7, + 0xc2, 0x21, 0xc5, 0x25, 0xce, 0x97, 0x00, 0xfa, 0x03, 0x54, 0xe5, 0x4a, 0x32, 0xa4, 0xcc, 0xf5, + 0x7c, 0x11, 0xaa, 0xea, 0x52, 0x79, 0x48, 0x6e, 0x5b, 0xc8, 0x71, 0x65, 0x94, 0xfd, 0x44, 0x5f, + 0x2f, 0x14, 0xc4, 0x2c, 0xf2, 0x82, 0x2b, 0x11, 0xbf, 0xe2, 0x9c, 0xd6, 0x17, 0xe0, 0xd3, 0x7f, + 0x2a, 0x50, 0xce, 0x5e, 0x2c, 0x51, 0x05, 0x8a, 0xa6, 0x45, 0x4e, 0xbb, 0xe6, 0xcb, 0x8e, 0xa3, + 0xdd, 0xe3, 0x9f, 0xfd, 0x8b, 0x56, 0xcb, 0x30, 0xda, 0x06, 0x2f, 0x27, 0x04, 0xd5, 0xd3, 0xa6, + 0xd9, 0x35, 0xda, 0xc4, 0x31, 0xcf, 0x0d, 0xfb, 0xc2, 0xd1, 0x72, 0x68, 0x17, 0xb6, 0x25, 0x66, + 0xd9, 0x04, 0xdb, 0x17, 0x8e, 0xa1, 0x6d, 0x20, 0x0d, 0xca, 0x12, 0x34, 0x30, 0xb6, 0xb1, 0xa6, + 0xa2, 0xaf, 0xe0, 0x40, 0x22, 0xa6, 0xd5, 0xb2, 0x31, 0x36, 0x5a, 0x0e, 0xe9, 0x35, 0xdf, 0x9d, + 0x1b, 0x96, 0x43, 0xda, 0x86, 0xd3, 0x34, 0xbb, 0x7d, 0x2d, 0x8f, 0xbe, 0x80, 0xfd, 0x39, 0xab, + 0x7f, 0x71, 0x7a, 0x6a, 0xb6, 0x4c, 0x4e, 0x38, 0x69, 0x76, 0x9b, 0x56, 0xcb, 0xd0, 0x36, 0x9f, + 0xfe, 0x45, 0x85, 0xca, 0x92, 0xe3, 0xcb, 0x95, 0x5f, 0x81, 0xa2, 0x65, 0x4b, 0x7d, 0x9a, 0xc2, + 0xcd, 0xb0, 0x2d, 0xd3, 0xb6, 0x48, 0xdb, 0x68, 0xd9, 0x6d, 0xde, 0x03, 0x9f, 0xc1, 0x4e, 0xd7, + 0xb4, 0x5e, 0x11, 0xcb, 0x76, 0x88, 0xd1, 0x35, 0x5f, 0x9a, 0x27, 0x5d, 0x6e, 0xef, 0x7d, 0xd0, + 0x6c, 0x8b, 0xb4, 0x3a, 0x4d, 0xd3, 0x9a, 0xbb, 0xa6, 0x72, 0x94, 0x5f, 0x85, 0x89, 0xf1, 0x96, + 0x47, 0xa0, 0x4f, 0xce, 0x9b, 0x6f, 0xb5, 0x3c, 0xaa, 0xc1, 0xfd, 0xf5, 0xc6, 0xa1, 0x3d, 0x40, + 0xdc, 0xb9, 0xf3, 0x5e, 0xd7, 0x70, 0x0c, 0x92, 0xf6, 0xda, 0x16, 0x0f, 0x91, 0xd0, 0xd3, 0x6c, + 0xb7, 0x49, 0xe2, 0x9e, 0x56, 0xe0, 0x96, 0x48, 0x46, 0x9f, 0xb4, 0xcd, 0x7e, 0xf3, 0x84, 0xc3, + 0x45, 0xbe, 0xa7, 0x69, 0xbd, 0xb6, 0xcd, 0x96, 0x41, 0x5a, 0x5c, 0x2d, 0x47, 0x81, 0x93, 0x53, + 0xf4, 0xc2, 0x6a, 0x1b, 0xb8, 0xd7, 0x34, 0xdb, 0x5a, 0x09, 0xed, 0xc3, 0x83, 0x14, 0x36, 0xde, + 0xf6, 0x4c, 0xfc, 0x8e, 0x38, 0xb6, 0x4d, 0xfa, 0xb6, 0x6d, 0x69, 0xe5, 0xac, 0x26, 0xee, 0xad, + 0xdd, 0x33, 0x2c, 0xad, 0x82, 0x1e, 0xc0, 0xee, 0x79, 0xaf, 0x47, 0x52, 0x49, 0xea, 0x6c, 0x95, + 0xd3, 0x9b, 0xed, 0x36, 0x36, 0xfa, 0x7d, 0x72, 0x6e, 0xf6, 0xcf, 0x9b, 0x4e, 0xab, 0xa3, 0x6d, + 0x73, 0x97, 0xfa, 0x86, 0x43, 0x1c, 0xdb, 0x69, 0x76, 0x17, 0xb8, 0xc6, 0x0d, 0x5a, 0xe0, 0x7c, + 0xd3, 0xae, 0xfd, 0x46, 0xdb, 0xe1, 0x01, 0xe7, 0xb0, 0xfd, 0x5a, 0x9a, 0x88, 0xb8, 0xef, 0x32, + 0x3d, 0xe9, 0x9e, 0xda, 0x2e, 0x07, 0x4d, 0xeb, 0x75, 0xb3, 0x6b, 0xb6, 0xc9, 0x2b, 0xe3, 0x9d, + 0x38, 0xab, 0xee, 0x73, 0x30, 0xb1, 0x8c, 0xf4, 0xb0, 0xfd, 0x92, 0x1b, 0xa2, 0x7d, 0xc6, 0x2b, + 0xae, 0x65, 0xe2, 0xd6, 0x45, 0xb7, 0x89, 0x65, 0x71, 0xed, 0x1d, 0xff, 0x75, 0x13, 0x36, 0xc5, + 0x64, 0x8d, 0x50, 0x87, 0x37, 0xec, 0xfc, 0x9d, 0x89, 0x1e, 0x7d, 0xf2, 0xfd, 0x59, 0xaf, 0xad, + 0x7f, 0x4e, 0xcd, 0xe2, 0xe7, 0x0a, 0x3a, 0x83, 0x72, 0xf6, 0x15, 0x87, 0xb2, 0x63, 0x69, 0xcd, + 0xf3, 0xee, 0x93, 0xba, 0x5e, 0x81, 0x66, 0xc4, 0xcc, 0x9b, 0xf0, 0x97, 0x9a, 0x7c, 0xf4, 0xa0, + 0x7a, 0x86, 0xbf, 0xf2, 0x92, 0xaa, 0xef, 0xaf, 0x95, 0xc9, 0xab, 0x45, 0x37, 0x71, 0x51, 0x3e, + 0x3b, 0x6e, 0xb9, 0xb8, 0xfc, 0xd6, 0xa9, 0x7f, 0x7e, 0x97, 0x58, 0x6a, 0x1b, 0xc2, 0xee, 0x9a, + 0x97, 0x04, 0xfa, 0x3a, 0x6b, 0xc1, 0x9d, 0xef, 0x90, 0xfa, 0xe3, 0x1f, 0xa3, 0x2d, 0x76, 0x59, + 0xf3, 0xe4, 0x58, 0xda, 0xe5, 0xee, 0x07, 0xcb, 0xd2, 0x2e, 0x9f, 0x7a, 0xb9, 0xbc, 0x07, 0x6d, + 0xf5, 0x86, 0x8a, 0xf4, 0xd5, 0xb5, 0xb7, 0xaf, 0xca, 0xf5, 0x9f, 0x7f, 0x92, 0x23, 0x95, 0x9b, + 0x00, 0x8b, 0x7b, 0x1e, 0x7a, 0x98, 0x59, 0x72, 0xeb, 0x9e, 0x5a, 0x7f, 0x74, 0x87, 0x54, 0xaa, + 0x72, 0x60, 0x77, 0xcd, 0xc5, 0x6f, 0x29, 0x1a, 0x77, 0x5f, 0x0c, 0xeb, 0xf7, 0xd7, 0xdd, 0x8f, + 0x9e, 0x2b, 0x27, 0xdf, 0xfe, 0xf1, 0xe8, 0xca, 0x63, 0xe3, 0xd9, 0xe5, 0xe1, 0x20, 0x9c, 0x1c, + 0xf9, 0xde, 0xd5, 0x98, 0x05, 0x5e, 0x70, 0x15, 0x50, 0xf6, 0x31, 0x8c, 0xae, 0x8f, 0xfc, 0x60, + 0x78, 0x24, 0x86, 0xcd, 0xd1, 0x7c, 0xf9, 0xe5, 0xa6, 0xf8, 0x5b, 0xdd, 0x2f, 0xff, 0x1f, 0x00, + 0x00, 0xff, 0xff, 0xe9, 0x0c, 0xc3, 0x27, 0xdb, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1281,6 +1908,10 @@ type RouterClient interface { //keys. It retrieves the relevant channel policies from the graph in order to //calculate the correct fees and time locks. BuildRoute(ctx context.Context, in *BuildRouteRequest, opts ...grpc.CallOption) (*BuildRouteResponse, error) + //* + //SubscribeHtlcEvents creates a uni-directional stream from the server to + //the client which delivers a stream of htlc events. + SubscribeHtlcEvents(ctx context.Context, in *SubscribeHtlcEventsRequest, opts ...grpc.CallOption) (Router_SubscribeHtlcEventsClient, error) } type routerClient struct { @@ -1409,6 +2040,38 @@ func (c *routerClient) BuildRoute(ctx context.Context, in *BuildRouteRequest, op return out, nil } +func (c *routerClient) SubscribeHtlcEvents(ctx context.Context, in *SubscribeHtlcEventsRequest, opts ...grpc.CallOption) (Router_SubscribeHtlcEventsClient, error) { + stream, err := c.cc.NewStream(ctx, &_Router_serviceDesc.Streams[2], "/routerrpc.Router/SubscribeHtlcEvents", opts...) + if err != nil { + return nil, err + } + x := &routerSubscribeHtlcEventsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Router_SubscribeHtlcEventsClient interface { + Recv() (*HtlcEvent, error) + grpc.ClientStream +} + +type routerSubscribeHtlcEventsClient struct { + grpc.ClientStream +} + +func (x *routerSubscribeHtlcEventsClient) Recv() (*HtlcEvent, error) { + m := new(HtlcEvent) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // RouterServer is the server API for Router service. type RouterServer interface { //* @@ -1446,6 +2109,10 @@ type RouterServer interface { //keys. It retrieves the relevant channel policies from the graph in order to //calculate the correct fees and time locks. BuildRoute(context.Context, *BuildRouteRequest) (*BuildRouteResponse, error) + //* + //SubscribeHtlcEvents creates a uni-directional stream from the server to + //the client which delivers a stream of htlc events. + SubscribeHtlcEvents(*SubscribeHtlcEventsRequest, Router_SubscribeHtlcEventsServer) error } func RegisterRouterServer(s *grpc.Server, srv RouterServer) { @@ -1602,6 +2269,27 @@ func _Router_BuildRoute_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Router_SubscribeHtlcEvents_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SubscribeHtlcEventsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(RouterServer).SubscribeHtlcEvents(m, &routerSubscribeHtlcEventsServer{stream}) +} + +type Router_SubscribeHtlcEventsServer interface { + Send(*HtlcEvent) error + grpc.ServerStream +} + +type routerSubscribeHtlcEventsServer struct { + grpc.ServerStream +} + +func (x *routerSubscribeHtlcEventsServer) Send(m *HtlcEvent) error { + return x.ServerStream.SendMsg(m) +} + var _Router_serviceDesc = grpc.ServiceDesc{ ServiceName: "routerrpc.Router", HandlerType: (*RouterServer)(nil), @@ -1642,6 +2330,11 @@ var _Router_serviceDesc = grpc.ServiceDesc{ Handler: _Router_TrackPayment_Handler, ServerStreams: true, }, + { + StreamName: "SubscribeHtlcEvents", + Handler: _Router_SubscribeHtlcEvents_Handler, + ServerStreams: true, + }, }, Metadata: "routerrpc/router.proto", } diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index d5e53ff91a..027b6c5187 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -333,6 +333,135 @@ message BuildRouteResponse { lnrpc.Route route = 1; } + +message SubscribeHtlcEventsRequest{} + +/** +HtlcEvent contains the htlc event that was processed. These are served on a +best-effort basis; events are not persisted, delivery is not guaranteed +(in the event of a crash in the switch, forward events may be lost) and +some events may be replayed upon restart. Events consumed from this package +should be de-duplicated by the htlc's unique combination of incoming and +outgoing channel id and htlc id. [EXPERIMENTAL] +*/ +message HtlcEvent{ + /** + The short channel id that the incoming htlc arrived at our node on. This + value is zero for sends. + */ + uint64 incoming_channel_id = 1; + + /** + The short channel id that the outgoing htlc left our node on. This value + is zero for receives. + */ + uint64 outgoing_channel_id = 2; + + /** + Incoming id is the index of the incoming htlc in the incoming channel. + This value is zero for sends. + */ + uint64 incoming_htlc_id = 3; + + /** + Outgoing id is the index of the outgoing htlc in the outgoing channel. + This value is zero for receives. + */ + uint64 outgoing_htlc_id = 4; + + /** + The time in unix nanoseconds that the event occurred. + */ + uint64 timestamp_ns = 5; + + enum EventType{ + UNKNOWN = 0; + SEND = 1; + RECEIVE = 2; + FORWARD = 3; + } + + /** + The event type indicates whether the htlc was part of a send, receive or + forward. + */ + EventType event_type = 6; + + oneof event { + ForwardEvent forward_event = 7; + ForwardFailEvent forward_fail_event = 8; + SettleEvent settle_event = 9; + LinkFailEvent link_fail_event = 10; + } +} + +message HtlcInfo{ + // The timelock on the incoming htlc. + uint32 incoming_timelock = 1; + + // The timelock on the outgoing htlc. + uint32 outgoing_timelock = 2; + + // The amount of the incoming htlc. + uint64 incoming_amt_msat = 3; + + // The amount of the outgoing htlc. + uint64 outgoing_amt_msat = 4; +} + +message ForwardEvent{ + // Info contains details about the htlc that was forwarded. + HtlcInfo info = 1; +} + +message ForwardFailEvent{} + +message SettleEvent{} + +message LinkFailEvent{ + // Info contains details about the htlc that we failed. + HtlcInfo info = 1; + + // FailureCode is the BOLT error code for the failure. + lnrpc.Failure.FailureCode wire_failure = 2; + + /** + FailureDetail provides additional information about the reason for the + failure. This detail enriches the information provided by the wire message + and may be 'no detail' if the wire message requires no additional metadata. + */ + FailureDetail failure_detail = 3; + + // A string representation of the link failure. + string failure_string = 4; +} + +enum FailureDetail { + UNKNOWN = 0; + NO_DETAIL = 1; + ONION_DECODE = 2; + LINK_NOT_ELIGIBLE = 3; + ON_CHAIN_TIMEOUT = 4; + HTLC_EXCEEDS_MAX = 5; + INSUFFICIENT_BALANCE =6; + INCOMPLETE_FORWARD = 7; + HTLC_ADD_FAILED = 8; + FORWARDS_DISABLED = 9; + INVOICE_CANCELED = 10; + INVOICE_UNDERPAID = 11; + INVOICE_EXPIRY_TOO_SOON = 12; + INVOICE_NOT_OPEN = 13; + MPP_INVOICE_TIMEOUT = 14; + ADDRESS_MISMATCH = 15; + SET_TOTAL_MISMATCH = 16; + SET_TOTAL_TOO_LOW = 17; + SET_OVERPAID = 18; + UNKNOWN_INVOICE = 19; + INVALID_KEYSEND = 20; + MPP_IN_PROGRESS = 21; + CIRCULAR_ROUTE = 22; +} + service Router { /** SendPayment attempts to route a payment described by the passed @@ -387,4 +516,10 @@ service Router { calculate the correct fees and time locks. */ rpc BuildRoute (BuildRouteRequest) returns (BuildRouteResponse); + + /** + SubscribeHtlcEvents creates a uni-directional stream from the server to + the client which delivers a stream of htlc events. + */ + rpc SubscribeHtlcEvents (SubscribeHtlcEventsRequest) returns (stream HtlcEvent); } diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 8bbdb38704..17434699a8 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -82,6 +82,10 @@ var ( Entity: "offchain", Action: "read", }}, + "/routerrpc.Router/SubscribeHtlcEvents": {{ + Entity: "offchain", + Action: "read", + }}, } // DefaultRouterMacFilename is the default name of the router macaroon @@ -613,3 +617,42 @@ func (s *Server) BuildRoute(ctx context.Context, return routeResp, nil } + +// SubscribeHtlcEvents creates a uni-directional stream from the server to +// the client which delivers a stream of htlc events. +func (s *Server) SubscribeHtlcEvents(req *SubscribeHtlcEventsRequest, + stream Router_SubscribeHtlcEventsServer) error { + + htlcClient, err := s.cfg.RouterBackend.SubscribeHtlcEvents() + if err != nil { + return err + } + defer htlcClient.Cancel() + + for { + select { + case event := <-htlcClient.Updates(): + rpcEvent, err := rpcHtlcEvent(event) + if err != nil { + return err + } + + if err := stream.Send(rpcEvent); err != nil { + return err + } + + // If the stream's context is cancelled, return an error. + case <-stream.Context().Done(): + log.Debugf("htlc event stream cancelled") + return stream.Context().Err() + + // If the subscribe client terminates, exit with an error. + case <-htlcClient.Quit(): + return errors.New("htlc event subscription terminated") + + // If the server has been signalled to shut down, exit. + case <-s.quit: + return errServerShuttingDown + } + } +} diff --git a/lnrpc/routerrpc/subscribe_events.go b/lnrpc/routerrpc/subscribe_events.go new file mode 100644 index 0000000000..ce65a6c8a5 --- /dev/null +++ b/lnrpc/routerrpc/subscribe_events.go @@ -0,0 +1,241 @@ +// +build routerrpc + +package routerrpc + +import ( + "fmt" + "time" + + "github.com/lightningnetwork/lnd/htlcswitch" + "github.com/lightningnetwork/lnd/invoices" + "github.com/lightningnetwork/lnd/lnrpc" +) + +// rpcHtlcEvent returns a rpc htlc event from a htlcswitch event. +func rpcHtlcEvent(htlcEvent interface{}) (*HtlcEvent, error) { + var ( + key htlcswitch.HtlcKey + timestamp time.Time + eventType htlcswitch.HtlcEventType + event isHtlcEvent_Event + ) + + switch e := htlcEvent.(type) { + case *htlcswitch.ForwardingEvent: + event = &HtlcEvent_ForwardEvent{ + ForwardEvent: &ForwardEvent{ + Info: rpcInfo(e.HtlcInfo), + }, + } + + key = e.HtlcKey + eventType = e.HtlcEventType + timestamp = e.Timestamp + + case *htlcswitch.ForwardingFailEvent: + event = &HtlcEvent_ForwardFailEvent{ + ForwardFailEvent: &ForwardFailEvent{}, + } + + key = e.HtlcKey + eventType = e.HtlcEventType + timestamp = e.Timestamp + + case *htlcswitch.LinkFailEvent: + failureCode, failReason, err := rpcFailReason( + e.LinkError, + ) + if err != nil { + return nil, err + } + + event = &HtlcEvent_LinkFailEvent{ + LinkFailEvent: &LinkFailEvent{ + Info: rpcInfo(e.HtlcInfo), + WireFailure: failureCode, + FailureDetail: failReason, + FailureString: e.LinkError.Error(), + }, + } + + key = e.HtlcKey + eventType = e.HtlcEventType + timestamp = e.Timestamp + + case *htlcswitch.SettleEvent: + event = &HtlcEvent_SettleEvent{ + SettleEvent: &SettleEvent{}, + } + + key = e.HtlcKey + eventType = e.HtlcEventType + timestamp = e.Timestamp + + default: + return nil, fmt.Errorf("unknown event type: %T", e) + } + + rpcEvent := &HtlcEvent{ + IncomingChannelId: key.IncomingCircuit.ChanID.ToUint64(), + OutgoingChannelId: key.OutgoingCircuit.ChanID.ToUint64(), + IncomingHtlcId: key.IncomingCircuit.HtlcID, + OutgoingHtlcId: key.OutgoingCircuit.HtlcID, + TimestampNs: uint64(timestamp.UnixNano()), + Event: event, + } + + // Convert the htlc event type to a rpc event. + switch eventType { + case htlcswitch.HtlcEventTypeSend: + rpcEvent.EventType = HtlcEvent_SEND + + case htlcswitch.HtlcEventTypeReceive: + rpcEvent.EventType = HtlcEvent_RECEIVE + + case htlcswitch.HtlcEventTypeForward: + rpcEvent.EventType = HtlcEvent_FORWARD + + default: + return nil, fmt.Errorf("unknown event type: %v", eventType) + } + + return rpcEvent, nil +} + +// rpcInfo returns a rpc struct containing the htlc information from the +// switch's htlc info struct. +func rpcInfo(info htlcswitch.HtlcInfo) *HtlcInfo { + return &HtlcInfo{ + IncomingTimelock: info.IncomingTimeLock, + OutgoingTimelock: info.OutgoingTimeLock, + IncomingAmtMsat: uint64(info.IncomingAmt), + OutgoingAmtMsat: uint64(info.OutgoingAmt), + } +} + +// rpcFailReason maps a lnwire failure message and failure detail to a rpc +// failure code and detail. +func rpcFailReason(linkErr *htlcswitch.LinkError) (lnrpc.Failure_FailureCode, + FailureDetail, error) { + + wireErr, err := marshallError(linkErr) + if err != nil { + return 0, 0, err + } + + switch failureDetail := linkErr.FailureDetail.(type) { + case invoices.FailResolutionResult: + fd, err := rpcFailureResolution(failureDetail) + return wireErr.GetCode(), fd, err + + case htlcswitch.OutgoingFailure: + fd, err := rpcOutgoingFailure(failureDetail) + return wireErr.GetCode(), fd, err + + default: + return 0, 0, fmt.Errorf("unknown failure "+ + "detail type: %T", linkErr.FailureDetail) + + } + +} + +// rpcFailureResolution maps an invoice failure resolution to a rpc failure +// detail. Invoice failures have no zero resolution results (every failure +// is accompanied with a result), so we error if we fail to match the result +// type. +func rpcFailureResolution(invoiceFailure invoices.FailResolutionResult) ( + FailureDetail, error) { + + switch invoiceFailure { + case invoices.ResultReplayToCanceled: + return FailureDetail_INVOICE_CANCELED, nil + + case invoices.ResultInvoiceAlreadyCanceled: + return FailureDetail_INVOICE_CANCELED, nil + + case invoices.ResultAmountTooLow: + return FailureDetail_INVOICE_UNDERPAID, nil + + case invoices.ResultExpiryTooSoon: + return FailureDetail_INVOICE_EXPIRY_TOO_SOON, nil + + case invoices.ResultCanceled: + return FailureDetail_INVOICE_CANCELED, nil + + case invoices.ResultInvoiceNotOpen: + return FailureDetail_INVOICE_NOT_OPEN, nil + + case invoices.ResultMppTimeout: + return FailureDetail_MPP_INVOICE_TIMEOUT, nil + + case invoices.ResultAddressMismatch: + return FailureDetail_ADDRESS_MISMATCH, nil + + case invoices.ResultHtlcSetTotalMismatch: + return FailureDetail_SET_TOTAL_MISMATCH, nil + + case invoices.ResultHtlcSetTotalTooLow: + return FailureDetail_SET_TOTAL_TOO_LOW, nil + + case invoices.ResultHtlcSetOverpayment: + return FailureDetail_SET_OVERPAID, nil + + case invoices.ResultInvoiceNotFound: + return FailureDetail_UNKNOWN_INVOICE, nil + + case invoices.ResultKeySendError: + return FailureDetail_INVALID_KEYSEND, nil + + case invoices.ResultMppInProgress: + return FailureDetail_MPP_IN_PROGRESS, nil + + default: + return 0, fmt.Errorf("unknown fail resolution: %v", + invoiceFailure.FailureString()) + } +} + +// rpcOutgoingFailure maps an outgoing failure to a rpc FailureDetail. If the +// failure detail is FailureDetailNone, which indicates that the failure was +// a wire message which required no further failure detail, we return a no +// detail failure detail to indicate that there was no additional information. +func rpcOutgoingFailure(failureDetail htlcswitch.OutgoingFailure) ( + FailureDetail, error) { + + switch failureDetail { + case htlcswitch.OutgoingFailureNone: + return FailureDetail_NO_DETAIL, nil + + case htlcswitch.OutgoingFailureDecodeError: + return FailureDetail_ONION_DECODE, nil + + case htlcswitch.OutgoingFailureLinkNotEligible: + return FailureDetail_LINK_NOT_ELIGIBLE, nil + + case htlcswitch.OutgoingFailureOnChainTimeout: + return FailureDetail_ON_CHAIN_TIMEOUT, nil + + case htlcswitch.OutgoingFailureHTLCExceedsMax: + return FailureDetail_HTLC_EXCEEDS_MAX, nil + + case htlcswitch.OutgoingFailureInsufficientBalance: + return FailureDetail_INSUFFICIENT_BALANCE, nil + + case htlcswitch.OutgoingFailureCircularRoute: + return FailureDetail_CIRCULAR_ROUTE, nil + + case htlcswitch.OutgoingFailureIncompleteForward: + return FailureDetail_INCOMPLETE_FORWARD, nil + + case htlcswitch.OutgoingFailureDownstreamHtlcAdd: + return FailureDetail_HTLC_ADD_FAILED, nil + + case htlcswitch.OutgoingFailureForwardsDisabled: + return FailureDetail_FORWARDS_DISABLED, nil + + default: + return 0, fmt.Errorf("unknown outgoing failure "+ + "detail: %v", failureDetail.FailureString()) + } +} From 4b8d0d913a4ca0624a38f9c401397835400547cd Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 13 Mar 2020 11:03:00 -0700 Subject: [PATCH 211/562] build: bump travis bitcoind version to v0.19.1 --- .travis.yml | 2 +- scripts/install_bitcoind.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 94d28281ab..32a9f5b560 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: go cache: directories: - - ~/bitcoin/bitcoin-0.19.0.1/bin + - ~/bitcoin/bitcoin-0.19.1/bin - $DOWNLOAD_CACHE - $GOCACHE - $GOPATH/pkg/mod diff --git a/scripts/install_bitcoind.sh b/scripts/install_bitcoind.sh index b304969325..ea3d4e5244 100755 --- a/scripts/install_bitcoind.sh +++ b/scripts/install_bitcoind.sh @@ -2,7 +2,7 @@ set -ev -export BITCOIND_VERSION=0.19.0.1 +export BITCOIND_VERSION=0.19.1 if sudo cp ~/bitcoin/bitcoin-$BITCOIND_VERSION/bin/bitcoind /usr/local/bin/bitcoind then From 7d305fdc46a4262735f5411d50046bacb3705e59 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:28 +0100 Subject: [PATCH 212/562] lnrpc: add commitment_type to listchannels --- lnrpc/rpc.pb.go | 1458 +++++++++++++++++++++------------------- lnrpc/rpc.proto | 37 +- lnrpc/rpc.swagger.json | 16 +- rpcserver.go | 13 +- 4 files changed, 810 insertions(+), 714 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 1e631bd3b8..011ccd40bc 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -59,6 +59,46 @@ func (AddressType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_77a6da22d6a3feb1, []int{0} } +type CommitmentType int32 + +const ( + //* + //A channel using the legacy commitment format having tweaked to_remote + //keys. + CommitmentType_LEGACY CommitmentType = 0 + //* + //A channel that uses the modern commitment format where the key in the + //output of the remote party does not change each state. This makes back + //up and recovery easier as when the channel is closed, the funds go + //directly to that key. + CommitmentType_STATIC_REMOTE_KEY CommitmentType = 1 + //* + //A channel that uses a commitment format that has anchor outputs on the + //commitments, allowing fee bumping after a force close transaction has + //been broadcast. + CommitmentType_ANCHORS CommitmentType = 2 +) + +var CommitmentType_name = map[int32]string{ + 0: "LEGACY", + 1: "STATIC_REMOTE_KEY", + 2: "ANCHORS", +} + +var CommitmentType_value = map[string]int32{ + "LEGACY": 0, + "STATIC_REMOTE_KEY": 1, + "ANCHORS": 2, +} + +func (x CommitmentType) String() string { + return proto.EnumName(CommitmentType_name, int32(x)) +} + +func (CommitmentType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{1} +} + type InvoiceHTLCState int32 const ( @@ -84,7 +124,7 @@ func (x InvoiceHTLCState) String() string { } func (InvoiceHTLCState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{1} + return fileDescriptor_77a6da22d6a3feb1, []int{2} } type FeatureBit int32 @@ -154,7 +194,7 @@ func (x FeatureBit) String() string { } func (FeatureBit) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{2} + return fileDescriptor_77a6da22d6a3feb1, []int{3} } type ChannelCloseSummary_ClosureType int32 @@ -2991,12 +3031,10 @@ type Channel struct { //* //The minimum satoshis the other node is required to reserve in its balance. RemoteChanReserveSat int64 `protobuf:"varint,21,opt,name=remote_chan_reserve_sat,json=remoteChanReserveSat,proto3" json:"remote_chan_reserve_sat,omitempty"` - //* - //If true, then this channel uses the modern commitment format where the key - //in the output of the remote party does not change each state. This makes - //back up and recovery easier as when the channel is closed, the funds go - //directly to that key. - StaticRemoteKey bool `protobuf:"varint,22,opt,name=static_remote_key,json=staticRemoteKey,proto3" json:"static_remote_key,omitempty"` + /// Deprecated. Use commitment_type. + StaticRemoteKey bool `protobuf:"varint,22,opt,name=static_remote_key,json=staticRemoteKey,proto3" json:"static_remote_key,omitempty"` // Deprecated: Do not use. + /// The commitment type used by this channel. + CommitmentType CommitmentType `protobuf:"varint,26,opt,name=commitment_type,json=commitmentType,proto3,enum=lnrpc.CommitmentType" json:"commitment_type,omitempty"` //* //The number of seconds that the channel has been monitored by the channel //scoring system. Scores are currently not persisted, so this value may be @@ -3191,6 +3229,7 @@ func (m *Channel) GetRemoteChanReserveSat() int64 { return 0 } +// Deprecated: Do not use. func (m *Channel) GetStaticRemoteKey() bool { if m != nil { return m.StaticRemoteKey @@ -3198,6 +3237,13 @@ func (m *Channel) GetStaticRemoteKey() bool { return false } +func (m *Channel) GetCommitmentType() CommitmentType { + if m != nil { + return m.CommitmentType + } + return CommitmentType_LEGACY +} + func (m *Channel) GetLifetime() int64 { if m != nil { return m.Lifetime @@ -10915,6 +10961,7 @@ func (m *ChannelUpdate) GetExtraOpaqueData() []byte { func init() { proto.RegisterEnum("lnrpc.AddressType", AddressType_name, AddressType_value) + proto.RegisterEnum("lnrpc.CommitmentType", CommitmentType_name, CommitmentType_value) proto.RegisterEnum("lnrpc.InvoiceHTLCState", InvoiceHTLCState_name, InvoiceHTLCState_value) proto.RegisterEnum("lnrpc.FeatureBit", FeatureBit_name, FeatureBit_value) proto.RegisterEnum("lnrpc.ChannelCloseSummary_ClosureType", ChannelCloseSummary_ClosureType_name, ChannelCloseSummary_ClosureType_value) @@ -11095,702 +11142,705 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11110 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x1c, 0x47, - 0x96, 0x18, 0xcc, 0xba, 0x75, 0x55, 0x9d, 0xba, 0x74, 0x75, 0xf4, 0xad, 0xd8, 0x24, 0x45, 0x2a, - 0xa5, 0x11, 0x29, 0x4a, 0x22, 0x29, 0x8e, 0x6e, 0x2b, 0x7d, 0xdf, 0xec, 0x56, 0x77, 0x57, 0xb3, - 0x6b, 0xd8, 0x37, 0x65, 0x55, 0x4b, 0xab, 0x19, 0xaf, 0x73, 0xb2, 0xab, 0xa2, 0xbb, 0x73, 0x59, - 0x95, 0x59, 0xca, 0xcc, 0xea, 0xcb, 0x08, 0xf2, 0x83, 0x2f, 0x0b, 0xc3, 0x36, 0x0c, 0x2c, 0xec, - 0x31, 0xe0, 0xb1, 0x17, 0x36, 0x6c, 0x18, 0x86, 0x61, 0x63, 0xb1, 0xc6, 0xac, 0x01, 0x3f, 0xf8, - 0x7d, 0x5f, 0x6c, 0xec, 0xc3, 0xae, 0x5f, 0x8c, 0xc1, 0x02, 0x0b, 0xaf, 0xc7, 0xaf, 0xfe, 0x09, - 0x46, 0x9c, 0x13, 0x91, 0x19, 0x59, 0x95, 0x4d, 0x52, 0x9a, 0xf1, 0xbc, 0x90, 0x9d, 0xe7, 0x9c, - 0xb8, 0x9f, 0x38, 0x71, 0x6e, 0x11, 0x05, 0x65, 0x7f, 0xdc, 0x7f, 0x30, 0xf6, 0xbd, 0xd0, 0x63, - 0x85, 0xa1, 0xeb, 0x8f, 0xfb, 0x6b, 0x37, 0x4f, 0x3c, 0xef, 0x64, 0xc8, 0x1f, 0xda, 0x63, 0xe7, - 0xa1, 0xed, 0xba, 0x5e, 0x68, 0x87, 0x8e, 0xe7, 0x06, 0x44, 0x64, 0xfc, 0x08, 0xea, 0x4f, 0xb8, - 0xdb, 0xe5, 0x7c, 0x60, 0xf2, 0x2f, 0x27, 0x3c, 0x08, 0xd9, 0x5b, 0xb0, 0x60, 0xf3, 0x1f, 0x73, - 0x3e, 0xb0, 0xc6, 0x76, 0x10, 0x8c, 0x4f, 0x7d, 0x3b, 0xe0, 0xcd, 0xcc, 0x9d, 0xcc, 0xbd, 0xaa, - 0xd9, 0x20, 0xc4, 0x41, 0x04, 0x67, 0xaf, 0x42, 0x35, 0x10, 0xa4, 0xdc, 0x0d, 0x7d, 0x6f, 0x7c, - 0xd9, 0xcc, 0x22, 0x5d, 0x45, 0xc0, 0xda, 0x04, 0x32, 0x86, 0x30, 0x1f, 0xb5, 0x10, 0x8c, 0x3d, - 0x37, 0xe0, 0xec, 0x11, 0x2c, 0xf5, 0x9d, 0xf1, 0x29, 0xf7, 0x2d, 0x2c, 0x3c, 0x72, 0xf9, 0xc8, - 0x73, 0x9d, 0x7e, 0x33, 0x73, 0x27, 0x77, 0xaf, 0x6c, 0x32, 0xc2, 0x89, 0x12, 0xbb, 0x12, 0xc3, - 0xee, 0xc2, 0x3c, 0x77, 0x09, 0xce, 0x07, 0x58, 0x4a, 0x36, 0x55, 0x8f, 0xc1, 0xa2, 0x80, 0xf1, - 0x77, 0xb3, 0xb0, 0xd0, 0x71, 0x9d, 0xf0, 0x73, 0x7b, 0x38, 0xe4, 0xa1, 0x1a, 0xd3, 0x5d, 0x98, - 0x3f, 0x47, 0x00, 0x8e, 0xe9, 0xdc, 0xf3, 0x07, 0x72, 0x44, 0x75, 0x02, 0x1f, 0x48, 0xe8, 0x95, - 0x3d, 0xcb, 0x5e, 0xd9, 0xb3, 0xd4, 0xe9, 0xca, 0x5d, 0x31, 0x5d, 0x77, 0x61, 0xde, 0xe7, 0x7d, - 0xef, 0x8c, 0xfb, 0x97, 0xd6, 0xb9, 0xe3, 0x0e, 0xbc, 0xf3, 0x66, 0xfe, 0x4e, 0xe6, 0x5e, 0xc1, - 0xac, 0x2b, 0xf0, 0xe7, 0x08, 0x65, 0xeb, 0x30, 0xdf, 0x3f, 0xb5, 0x5d, 0x97, 0x0f, 0xad, 0x23, - 0xbb, 0xff, 0x6c, 0x32, 0x0e, 0x9a, 0x85, 0x3b, 0x99, 0x7b, 0x95, 0xc7, 0xd7, 0x1f, 0xe0, 0xaa, - 0x3e, 0xd8, 0x38, 0xb5, 0xdd, 0x75, 0xc4, 0x74, 0x5d, 0x7b, 0x1c, 0x9c, 0x7a, 0xa1, 0x59, 0x97, - 0x25, 0x08, 0x1c, 0x18, 0x4b, 0xc0, 0xf4, 0x99, 0xa0, 0xb9, 0x37, 0xfe, 0x7d, 0x06, 0x16, 0x0f, - 0xdd, 0xa1, 0xd7, 0x7f, 0xf6, 0x2d, 0xa7, 0x28, 0x65, 0x0c, 0xd9, 0x97, 0x1d, 0x43, 0xee, 0x9b, - 0x8e, 0x61, 0x05, 0x96, 0x92, 0x9d, 0x95, 0xa3, 0xe0, 0xb0, 0x2c, 0x4a, 0x9f, 0x70, 0xd5, 0x2d, - 0x35, 0x8c, 0x37, 0xa1, 0xd1, 0x9f, 0xf8, 0x3e, 0x77, 0x67, 0xc6, 0x31, 0x2f, 0xe1, 0xd1, 0x40, - 0x5e, 0x85, 0xaa, 0xcb, 0xcf, 0x63, 0x32, 0xc9, 0xbb, 0x2e, 0x3f, 0x57, 0x24, 0x46, 0x13, 0x56, - 0xa6, 0x9b, 0x91, 0x1d, 0xf8, 0x45, 0x06, 0xf2, 0x87, 0xe1, 0x85, 0xc7, 0xde, 0x87, 0xaa, 0x3d, - 0x18, 0xf8, 0x3c, 0x08, 0xac, 0xf0, 0x72, 0x4c, 0x3b, 0xa5, 0xfe, 0x98, 0xc9, 0x21, 0xb6, 0x08, - 0xd5, 0xbb, 0x1c, 0x73, 0xb3, 0x62, 0xc7, 0x1f, 0xac, 0x09, 0x45, 0xf9, 0x89, 0xed, 0x96, 0x4d, - 0xf5, 0xc9, 0x6e, 0x01, 0xd8, 0x23, 0x6f, 0xe2, 0x86, 0x56, 0x60, 0x87, 0x38, 0x63, 0x39, 0xb3, - 0x4c, 0x90, 0xae, 0x1d, 0xb2, 0x1b, 0x50, 0x1e, 0x3f, 0xb3, 0x82, 0xbe, 0xef, 0x8c, 0x43, 0x64, - 0x9e, 0xb2, 0x59, 0x1a, 0x3f, 0xeb, 0xe2, 0x37, 0x7b, 0x0b, 0x4a, 0xde, 0x24, 0x1c, 0x7b, 0x8e, - 0x1b, 0x4a, 0x7e, 0x99, 0x97, 0x1d, 0xd9, 0x9f, 0x84, 0x07, 0x02, 0x6c, 0x46, 0x04, 0xec, 0x75, - 0xa8, 0xf5, 0x3d, 0xf7, 0xd8, 0xf1, 0x47, 0x24, 0x11, 0x9a, 0x73, 0xd8, 0x56, 0x12, 0x68, 0xfc, - 0x51, 0x16, 0x2a, 0x3d, 0xdf, 0x76, 0x03, 0xbb, 0x2f, 0x00, 0x6c, 0x15, 0x8a, 0xe1, 0x85, 0x75, - 0x6a, 0x07, 0xa7, 0x38, 0xd4, 0xb2, 0x39, 0x17, 0x5e, 0x6c, 0xdb, 0xc1, 0x29, 0x5b, 0x81, 0x39, - 0xea, 0x25, 0x0e, 0x28, 0x67, 0xca, 0x2f, 0xb1, 0x41, 0xdc, 0xc9, 0xc8, 0x4a, 0x36, 0x95, 0x43, - 0x8e, 0x69, 0xb8, 0x93, 0xd1, 0x86, 0x0e, 0x17, 0x83, 0x3f, 0x12, 0xcb, 0x4d, 0x0d, 0xd0, 0xf0, - 0xca, 0x08, 0xc1, 0x36, 0x5e, 0x85, 0xaa, 0x44, 0x73, 0xe7, 0xe4, 0x94, 0xc6, 0x58, 0x30, 0x2b, - 0x44, 0x80, 0x20, 0x51, 0x43, 0xe8, 0x8c, 0xb8, 0x15, 0x84, 0xf6, 0x68, 0x2c, 0x87, 0x54, 0x16, - 0x90, 0xae, 0x00, 0x20, 0xda, 0x0b, 0xed, 0xa1, 0x75, 0xcc, 0x79, 0xd0, 0x2c, 0x4a, 0xb4, 0x80, - 0x6c, 0x71, 0x1e, 0xb0, 0xef, 0x40, 0x7d, 0xc0, 0x83, 0xd0, 0x92, 0x8b, 0xc1, 0x83, 0x66, 0x09, - 0x77, 0x7e, 0x4d, 0x40, 0x5b, 0x0a, 0xc8, 0x6e, 0x02, 0xf8, 0xf6, 0xb9, 0x25, 0x26, 0x82, 0x5f, - 0x34, 0xcb, 0xb4, 0x0a, 0xbe, 0x7d, 0xde, 0xbb, 0xd8, 0xe6, 0x17, 0x82, 0x6b, 0x9e, 0xf0, 0x50, - 0x9b, 0xb4, 0x40, 0x72, 0xa7, 0xb1, 0x03, 0x4c, 0x03, 0x6f, 0xf2, 0xd0, 0x76, 0x86, 0x01, 0xfb, - 0x00, 0xaa, 0xa1, 0x46, 0x8c, 0x62, 0xb0, 0x12, 0xb1, 0x90, 0x56, 0xc0, 0x4c, 0xd0, 0x19, 0xa7, - 0x50, 0xda, 0xe2, 0x7c, 0xc7, 0x19, 0x39, 0x21, 0x5b, 0x81, 0xc2, 0xb1, 0x73, 0xc1, 0x89, 0xd9, - 0x73, 0xdb, 0xd7, 0x4c, 0xfa, 0x64, 0xb7, 0x01, 0xf0, 0x0f, 0x6b, 0x14, 0x71, 0xd3, 0xf6, 0x35, - 0xb3, 0x8c, 0xb0, 0xdd, 0xc0, 0x0e, 0xd9, 0x1a, 0x14, 0xc7, 0xdc, 0xef, 0x73, 0xb5, 0x6e, 0xdb, - 0xd7, 0x4c, 0x05, 0x58, 0x2f, 0x42, 0x61, 0x28, 0x6a, 0x37, 0xfe, 0xa4, 0x00, 0x95, 0x2e, 0x77, - 0xa3, 0x5d, 0xc6, 0x20, 0x2f, 0x26, 0x44, 0xee, 0x2c, 0xfc, 0x9b, 0xbd, 0x06, 0x15, 0x9c, 0xba, - 0x20, 0xf4, 0x1d, 0xf7, 0x84, 0xb8, 0x7a, 0x3d, 0xdb, 0xcc, 0x98, 0x20, 0xc0, 0x5d, 0x84, 0xb2, - 0x06, 0xe4, 0xec, 0x91, 0xe2, 0x6a, 0xf1, 0x27, 0xbb, 0x0e, 0x25, 0x7b, 0x14, 0x52, 0xf7, 0xaa, - 0x08, 0x2e, 0xda, 0xa3, 0x10, 0xbb, 0xf6, 0x2a, 0x54, 0xc7, 0xf6, 0xe5, 0x48, 0xec, 0xe5, 0x88, - 0x1d, 0xaa, 0x66, 0x45, 0xc2, 0x90, 0x21, 0x1e, 0xc3, 0xa2, 0x4e, 0xa2, 0x1a, 0x2f, 0x44, 0x8d, - 0x2f, 0x68, 0xd4, 0xb2, 0x0f, 0x77, 0x61, 0x5e, 0x95, 0xf1, 0x69, 0x3c, 0xc8, 0x26, 0x65, 0xb3, - 0x2e, 0xc1, 0x6a, 0x94, 0xf7, 0xa0, 0x71, 0xec, 0xb8, 0xf6, 0xd0, 0xea, 0x0f, 0xc3, 0x33, 0x6b, - 0xc0, 0x87, 0xa1, 0x8d, 0x1c, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x18, 0x86, 0x67, 0x9b, 0x02, 0xca, - 0xde, 0x86, 0xf2, 0x31, 0xe7, 0x16, 0x4e, 0x56, 0xb3, 0x94, 0xd8, 0x78, 0x6a, 0x85, 0xcc, 0xd2, - 0xb1, 0x5a, 0xab, 0xb7, 0xa1, 0xe1, 0x4d, 0xc2, 0x13, 0xcf, 0x71, 0x4f, 0x2c, 0x21, 0xef, 0x2c, - 0x67, 0x80, 0x3c, 0x94, 0x5f, 0xcf, 0x3e, 0xca, 0x98, 0x75, 0x85, 0x13, 0x92, 0xa7, 0x33, 0x60, - 0x6f, 0xc0, 0xfc, 0xd0, 0x0e, 0x42, 0xeb, 0xd4, 0x1b, 0x5b, 0xe3, 0xc9, 0xd1, 0x33, 0x7e, 0xd9, - 0xac, 0xe1, 0x44, 0xd4, 0x04, 0x78, 0xdb, 0x1b, 0x1f, 0x20, 0x50, 0x70, 0x36, 0xf6, 0x93, 0x3a, - 0x01, 0x77, 0x32, 0xf7, 0x6a, 0x66, 0x59, 0x40, 0xa8, 0xd1, 0x2f, 0x60, 0x11, 0x97, 0xa7, 0x3f, - 0x09, 0x42, 0x6f, 0x64, 0x09, 0x59, 0xed, 0x0f, 0x82, 0x66, 0x05, 0x79, 0xed, 0x4d, 0xd9, 0x59, - 0x6d, 0x8d, 0x1f, 0x6c, 0xf2, 0x20, 0xdc, 0x40, 0x62, 0x93, 0x68, 0xc5, 0x81, 0x7e, 0x69, 0x2e, - 0x0c, 0xa6, 0xe1, 0xec, 0x6d, 0x60, 0xf6, 0x70, 0xe8, 0x9d, 0x5b, 0x01, 0x1f, 0x1e, 0x5b, 0x72, - 0x12, 0x9b, 0xf5, 0x3b, 0x99, 0x7b, 0x25, 0xb3, 0x81, 0x98, 0x2e, 0x1f, 0x1e, 0x1f, 0x10, 0x9c, - 0x7d, 0x00, 0xb8, 0x99, 0xac, 0x63, 0x6e, 0x87, 0x13, 0x9f, 0x07, 0xcd, 0xf9, 0x3b, 0xb9, 0x7b, - 0xf5, 0xc7, 0x0b, 0xd1, 0x7c, 0x21, 0x78, 0xdd, 0x09, 0xcd, 0xaa, 0xa0, 0x93, 0xdf, 0xc1, 0xda, - 0x26, 0xac, 0xa4, 0x77, 0x49, 0x30, 0x95, 0x98, 0x15, 0xc1, 0x8c, 0x79, 0x53, 0xfc, 0xc9, 0x96, - 0xa0, 0x70, 0x66, 0x0f, 0x27, 0x5c, 0xca, 0x74, 0xfa, 0xf8, 0x38, 0xfb, 0x51, 0xc6, 0xf8, 0xe3, - 0x0c, 0x54, 0x69, 0x94, 0x52, 0x17, 0x79, 0x0d, 0x6a, 0x8a, 0x1b, 0xb8, 0xef, 0x7b, 0xbe, 0x94, - 0x6a, 0x8a, 0xf3, 0xda, 0x02, 0x26, 0x4e, 0x15, 0x45, 0x34, 0xf6, 0xb9, 0x33, 0xb2, 0x4f, 0x54, - 0xd5, 0x8a, 0x95, 0x0e, 0x24, 0x98, 0xbd, 0x1b, 0xd7, 0xe7, 0x7b, 0x93, 0x90, 0xcb, 0x33, 0xaf, - 0x2a, 0x87, 0x67, 0x0a, 0x58, 0x54, 0x3b, 0x7e, 0xbd, 0x04, 0x9f, 0x1b, 0x3f, 0xc9, 0x00, 0x13, - 0xdd, 0xee, 0x79, 0x54, 0x81, 0xe4, 0xd0, 0xe9, 0x92, 0x99, 0x97, 0xde, 0x21, 0xd9, 0xe7, 0xed, - 0x10, 0x03, 0x0a, 0xd4, 0xf7, 0x7c, 0x4a, 0xdf, 0x09, 0xf5, 0xfd, 0x7c, 0x29, 0xd7, 0xc8, 0x1b, - 0xff, 0x23, 0x07, 0x4b, 0x1b, 0x74, 0x64, 0xb7, 0xfa, 0x7d, 0x3e, 0x8e, 0xf6, 0xce, 0x6d, 0xa8, - 0xb8, 0xde, 0x80, 0x2b, 0x8e, 0xa5, 0x8e, 0x81, 0x00, 0x69, 0xec, 0x7a, 0x6a, 0x3b, 0x2e, 0x75, - 0x9c, 0x26, 0xb3, 0x8c, 0x10, 0xec, 0xf6, 0x1b, 0x30, 0x3f, 0xe6, 0xee, 0x40, 0xdf, 0x22, 0xa4, - 0x54, 0xd5, 0x24, 0x58, 0xee, 0x8e, 0xdb, 0x50, 0x39, 0x9e, 0x10, 0x9d, 0x10, 0x2c, 0x79, 0xe4, - 0x01, 0x90, 0xa0, 0x16, 0xc9, 0x97, 0xf1, 0x24, 0x38, 0x45, 0x6c, 0x01, 0xb1, 0x45, 0xf1, 0x2d, - 0x50, 0xb7, 0x00, 0x06, 0x93, 0x20, 0x94, 0x3b, 0x66, 0x0e, 0x91, 0x65, 0x01, 0xa1, 0x1d, 0xf3, - 0x0e, 0x2c, 0x8e, 0xec, 0x0b, 0x0b, 0x79, 0xc7, 0x72, 0x5c, 0xeb, 0x78, 0x88, 0x67, 0x4e, 0x11, - 0xe9, 0x1a, 0x23, 0xfb, 0xe2, 0x33, 0x81, 0xe9, 0xb8, 0x5b, 0x08, 0x17, 0x62, 0x45, 0xa9, 0x3b, - 0x3e, 0x0f, 0xb8, 0x7f, 0xc6, 0x51, 0x12, 0xe4, 0x23, 0x9d, 0xc6, 0x24, 0xa8, 0xe8, 0xd1, 0x48, - 0x8c, 0x3b, 0x1c, 0xf6, 0x69, 0xdb, 0x9b, 0xc5, 0x91, 0xe3, 0x6e, 0x87, 0xc3, 0xbe, 0x38, 0x57, - 0x84, 0x1c, 0x19, 0x73, 0xdf, 0x7a, 0x76, 0x8e, 0x7b, 0x38, 0x8f, 0x72, 0xe3, 0x80, 0xfb, 0x4f, - 0xcf, 0xc5, 0xd1, 0xdf, 0x0f, 0x50, 0x10, 0xd9, 0x97, 0xcd, 0x0a, 0x6e, 0xf0, 0x52, 0x3f, 0x10, - 0x22, 0xc8, 0xbe, 0x14, 0x9b, 0x50, 0xf4, 0xd6, 0xc6, 0x55, 0xe0, 0x03, 0xac, 0x3e, 0x40, 0x89, - 0x5a, 0xc3, 0xce, 0xb6, 0x24, 0x42, 0xb4, 0x13, 0x08, 0xae, 0x57, 0x9d, 0x3d, 0x1e, 0xda, 0x27, - 0x01, 0x8a, 0x94, 0x9a, 0x59, 0x95, 0xc0, 0x2d, 0x01, 0x33, 0x3e, 0x27, 0x25, 0x4b, 0x5b, 0x5b, - 0xb9, 0x67, 0xc4, 0x51, 0x8f, 0x10, 0x5c, 0xd7, 0x92, 0x29, 0xbf, 0xd2, 0x16, 0x2d, 0x9b, 0xb2, - 0x68, 0xc6, 0x1f, 0x64, 0xa0, 0x2a, 0x6b, 0x46, 0xa5, 0x84, 0x3d, 0x00, 0xa6, 0x56, 0x31, 0xbc, - 0x70, 0x06, 0xd6, 0xd1, 0x65, 0xc8, 0x03, 0x62, 0x9a, 0xed, 0x6b, 0x66, 0x43, 0xe2, 0x7a, 0x17, - 0xce, 0x60, 0x5d, 0x60, 0xd8, 0x7d, 0x68, 0x24, 0xe8, 0x83, 0xd0, 0x27, 0x8e, 0xde, 0xbe, 0x66, - 0xd6, 0x35, 0xea, 0x6e, 0xe8, 0x8b, 0x3d, 0x22, 0x54, 0x9e, 0x49, 0x68, 0x39, 0xee, 0x80, 0x5f, - 0x20, 0x1b, 0xd5, 0xcc, 0x0a, 0xc1, 0x3a, 0x02, 0xb4, 0x5e, 0x87, 0xaa, 0x5e, 0x9d, 0x71, 0x02, - 0x25, 0xa5, 0x2f, 0xa1, 0xc2, 0x30, 0xd5, 0x25, 0xb3, 0x1c, 0x46, 0x3d, 0xb9, 0x0e, 0xa5, 0x64, - 0x0f, 0xcc, 0x62, 0xf8, 0xd2, 0x0d, 0x1b, 0xdf, 0x83, 0xc6, 0x8e, 0x60, 0x1e, 0x57, 0x30, 0xab, - 0xd4, 0xff, 0x56, 0x60, 0x4e, 0xdb, 0x34, 0x65, 0x53, 0x7e, 0x89, 0x33, 0xf7, 0xd4, 0x0b, 0x42, - 0xd9, 0x0a, 0xfe, 0x6d, 0xfc, 0x49, 0x06, 0x58, 0x3b, 0x08, 0x9d, 0x91, 0x1d, 0xf2, 0x2d, 0x1e, - 0x89, 0x85, 0x7d, 0xa8, 0x8a, 0xda, 0x7a, 0x5e, 0x8b, 0x14, 0x32, 0x52, 0x28, 0xde, 0x92, 0xdb, - 0x78, 0xb6, 0xc0, 0x03, 0x9d, 0x9a, 0xc4, 0x7c, 0xa2, 0x02, 0xb1, 0xcb, 0x42, 0xdb, 0x3f, 0xe1, - 0x21, 0xaa, 0x71, 0x52, 0xdf, 0x07, 0x02, 0x09, 0x05, 0x6e, 0xed, 0x37, 0x61, 0x61, 0xa6, 0x0e, - 0x5d, 0x2e, 0x97, 0x53, 0xe4, 0x72, 0x4e, 0x97, 0xcb, 0x16, 0x2c, 0x26, 0xfa, 0x25, 0x39, 0x6d, - 0x15, 0x8a, 0x62, 0x43, 0x08, 0xe5, 0x20, 0x43, 0x5a, 0xe5, 0x31, 0xe7, 0x42, 0x0d, 0x7e, 0x08, - 0x4b, 0xc7, 0x9c, 0xfb, 0x76, 0x88, 0x48, 0xdc, 0x31, 0x62, 0x85, 0x64, 0xc5, 0x0b, 0x12, 0xd7, - 0xb5, 0xc3, 0x03, 0xee, 0x8b, 0x95, 0x32, 0xfe, 0x67, 0x06, 0xe6, 0x85, 0x04, 0xdd, 0xb5, 0xdd, - 0x4b, 0x35, 0x4f, 0x3b, 0xa9, 0xf3, 0x74, 0x4f, 0x3b, 0x0c, 0x35, 0xea, 0x6f, 0x3a, 0x49, 0xb9, - 0xe9, 0x49, 0x62, 0x77, 0xa0, 0x9a, 0xe8, 0x6b, 0x01, 0xfb, 0x0a, 0x41, 0xd4, 0xc9, 0x5f, 0x7e, - 0x1a, 0xdf, 0x80, 0x46, 0xdc, 0x6d, 0x39, 0x87, 0x0c, 0xf2, 0x82, 0x25, 0x65, 0x05, 0xf8, 0xb7, - 0xf1, 0xcf, 0x33, 0x44, 0xb8, 0xe1, 0x39, 0x91, 0x76, 0x2a, 0x08, 0x85, 0xde, 0xab, 0x08, 0xc5, - 0xdf, 0x57, 0x6a, 0xf5, 0xbf, 0xfc, 0x60, 0xc5, 0xd6, 0x09, 0xb8, 0x3b, 0xb0, 0xec, 0xe1, 0x10, - 0x85, 0x6f, 0xc9, 0x2c, 0x8a, 0xef, 0xd6, 0x70, 0x68, 0xdc, 0x85, 0x05, 0xad, 0x77, 0xcf, 0x19, - 0xc7, 0x1e, 0xb0, 0x1d, 0x27, 0x08, 0x0f, 0xdd, 0x60, 0xac, 0x29, 0x6e, 0x37, 0xa0, 0x2c, 0x24, - 0xac, 0xe8, 0x19, 0x6d, 0xd9, 0x82, 0x29, 0x44, 0xae, 0xe8, 0x57, 0x80, 0x48, 0xfb, 0x42, 0x22, - 0xb3, 0x12, 0x69, 0x5f, 0x20, 0xd2, 0xf8, 0x08, 0x16, 0x13, 0xf5, 0xc9, 0xa6, 0x5f, 0x85, 0xc2, - 0x24, 0xbc, 0xf0, 0x94, 0x6a, 0x5e, 0x91, 0x1c, 0x22, 0x0c, 0x40, 0x93, 0x30, 0xc6, 0x27, 0xb0, - 0xb0, 0xc7, 0xcf, 0xe5, 0x26, 0x56, 0x1d, 0x79, 0x03, 0xf2, 0x2f, 0x30, 0x0a, 0x11, 0x6f, 0x3c, - 0x00, 0xa6, 0x17, 0x96, 0xad, 0x6a, 0x36, 0x62, 0x26, 0x61, 0x23, 0x1a, 0x6f, 0x00, 0xeb, 0x3a, - 0x27, 0xee, 0x2e, 0x0f, 0x02, 0xfb, 0x24, 0xda, 0xf6, 0x0d, 0xc8, 0x8d, 0x82, 0x13, 0x29, 0xa3, - 0xc4, 0x9f, 0xc6, 0x77, 0x61, 0x31, 0x41, 0x27, 0x2b, 0xbe, 0x09, 0xe5, 0xc0, 0x39, 0x71, 0x51, - 0xb1, 0x92, 0x55, 0xc7, 0x00, 0x63, 0x0b, 0x96, 0x3e, 0xe3, 0xbe, 0x73, 0x7c, 0xf9, 0xa2, 0xea, - 0x93, 0xf5, 0x64, 0xa7, 0xeb, 0x69, 0xc3, 0xf2, 0x54, 0x3d, 0xb2, 0x79, 0x62, 0x5f, 0xb9, 0x92, - 0x25, 0x93, 0x3e, 0x34, 0xb9, 0x97, 0xd5, 0xe5, 0x9e, 0x71, 0x08, 0x6c, 0xc3, 0x73, 0x5d, 0xde, - 0x0f, 0x0f, 0x38, 0xf7, 0x63, 0x2f, 0x55, 0xcc, 0xab, 0x95, 0xc7, 0xab, 0x72, 0x66, 0xa7, 0x85, - 0xa9, 0x64, 0x62, 0x06, 0xf9, 0x31, 0xf7, 0x47, 0x58, 0x71, 0xc9, 0xc4, 0xbf, 0x8d, 0x65, 0x58, - 0x4c, 0x54, 0x2b, 0xed, 0xfa, 0x47, 0xb0, 0xbc, 0xe9, 0x04, 0xfd, 0xd9, 0x06, 0x57, 0xa1, 0x38, - 0x9e, 0x1c, 0x59, 0x49, 0xb9, 0xfc, 0x94, 0x5f, 0x0a, 0x6b, 0x6f, 0xba, 0x84, 0xac, 0xeb, 0x6f, - 0x67, 0x20, 0xbf, 0xdd, 0xdb, 0xd9, 0x60, 0x6b, 0x50, 0x72, 0xdc, 0xbe, 0x37, 0x12, 0x8a, 0x17, - 0x8d, 0x39, 0xfa, 0xbe, 0x72, 0x83, 0xdd, 0x80, 0x32, 0xea, 0x6b, 0xc2, 0xb4, 0x95, 0xaa, 0x4f, - 0x49, 0x00, 0x76, 0xbc, 0xfe, 0x33, 0x61, 0x53, 0xf3, 0x8b, 0xb1, 0xe3, 0xa3, 0xd5, 0xac, 0x8c, - 0xe1, 0x3c, 0x9d, 0xf5, 0x31, 0x82, 0x2c, 0x62, 0xe3, 0x3f, 0x14, 0xa1, 0x28, 0x4f, 0x5b, 0x3a, - 0xb9, 0x43, 0xe7, 0x8c, 0xc7, 0x27, 0xb7, 0xf8, 0x12, 0xfa, 0x80, 0xcf, 0x47, 0x5e, 0x18, 0x29, - 0x6c, 0xb4, 0x06, 0x55, 0x02, 0x4a, 0x95, 0x4d, 0x53, 0x1a, 0xc8, 0xc5, 0x90, 0x23, 0xa2, 0xbe, - 0x7e, 0x94, 0xdf, 0x80, 0xa2, 0x3a, 0xfb, 0xf3, 0x91, 0x4d, 0x33, 0xd7, 0x27, 0x6d, 0x6d, 0x0d, - 0x4a, 0x7d, 0x7b, 0x6c, 0xf7, 0x9d, 0xf0, 0x52, 0x0a, 0x84, 0xe8, 0x5b, 0xd4, 0x3e, 0xf4, 0xfa, - 0xf6, 0xd0, 0x3a, 0xb2, 0x87, 0xb6, 0xdb, 0xe7, 0xd2, 0x76, 0xaf, 0x22, 0x70, 0x9d, 0x60, 0xc2, - 0x3e, 0x97, 0xfd, 0x54, 0x54, 0x64, 0xc2, 0xcb, 0xde, 0x2b, 0x32, 0xa1, 0x5c, 0x7a, 0xa3, 0x91, - 0x23, 0xac, 0x0c, 0x52, 0xc3, 0x72, 0x66, 0x99, 0x20, 0x5b, 0x1c, 0x47, 0x2b, 0xd1, 0xe7, 0x34, - 0x75, 0x65, 0x6a, 0x8a, 0x80, 0x9f, 0x93, 0x23, 0x61, 0x56, 0x17, 0xcb, 0x69, 0xba, 0xd8, 0x5b, - 0xb0, 0x30, 0x71, 0x03, 0x1e, 0x86, 0x43, 0x3e, 0x88, 0xfa, 0x52, 0x41, 0xa2, 0x46, 0x84, 0x50, - 0xdd, 0x79, 0x00, 0x8b, 0xe4, 0x74, 0x08, 0xec, 0xd0, 0x0b, 0x4e, 0x9d, 0xc0, 0x0a, 0x84, 0x85, - 0x44, 0xe6, 0xee, 0x02, 0xa2, 0xba, 0x12, 0xd3, 0x25, 0x13, 0x69, 0x75, 0x8a, 0xde, 0xe7, 0x7d, - 0xee, 0x9c, 0xf1, 0x01, 0xea, 0x69, 0x39, 0x73, 0x39, 0x51, 0xc6, 0x94, 0x48, 0x54, 0xba, 0x27, - 0x23, 0x6b, 0x32, 0x1e, 0xd8, 0x42, 0x59, 0xa9, 0x93, 0x32, 0xec, 0x4e, 0x46, 0x87, 0x04, 0x61, - 0x8f, 0x40, 0x69, 0x62, 0x52, 0x3f, 0x9c, 0x4f, 0xc8, 0x33, 0xc1, 0xac, 0x66, 0x55, 0x52, 0x90, - 0xa2, 0x98, 0xd0, 0x39, 0x1b, 0x53, 0x3a, 0x67, 0x13, 0x8a, 0x63, 0xdf, 0x39, 0xb3, 0x43, 0xde, - 0x5c, 0x20, 0x01, 0x2e, 0x3f, 0x85, 0x64, 0x70, 0x5c, 0x27, 0x74, 0xec, 0xd0, 0xf3, 0x9b, 0x0c, - 0x71, 0x31, 0x80, 0xdd, 0x87, 0x05, 0xe4, 0x91, 0x20, 0xb4, 0xc3, 0x49, 0x20, 0x35, 0xd0, 0x45, - 0x64, 0x26, 0xd4, 0xa1, 0xbb, 0x08, 0x47, 0x25, 0x94, 0x7d, 0x17, 0x56, 0x88, 0x2d, 0xb0, 0x84, - 0xd4, 0xac, 0x51, 0x21, 0x58, 0xc2, 0xa9, 0x58, 0x44, 0xac, 0xe0, 0x6f, 0xa9, 0x5f, 0x0b, 0xed, - 0xe0, 0x7d, 0x58, 0x95, 0x6c, 0x32, 0x53, 0x6a, 0x19, 0x4b, 0x2d, 0x11, 0x7a, 0xaa, 0xd8, 0x7d, - 0x58, 0x10, 0x5d, 0x72, 0xfa, 0x96, 0x2c, 0x2d, 0x76, 0xc2, 0x0a, 0xf6, 0x7e, 0x9e, 0x10, 0x26, - 0xc2, 0x9f, 0xf2, 0x4b, 0xc1, 0xca, 0x43, 0xe7, 0x98, 0x87, 0xce, 0x88, 0x37, 0x57, 0x89, 0x39, - 0xd4, 0xb7, 0xd8, 0x65, 0x93, 0x31, 0x62, 0x9a, 0xb4, 0xa7, 0xe9, 0x0b, 0xf9, 0x6e, 0xe8, 0x05, - 0x5c, 0xb9, 0x97, 0x9a, 0xd7, 0xe5, 0x06, 0x12, 0x40, 0x29, 0xb2, 0x8c, 0x9f, 0x65, 0xe8, 0x0c, - 0x92, 0x5b, 0x36, 0xd0, 0x2c, 0x2a, 0xda, 0xac, 0x96, 0xe7, 0x0e, 0x2f, 0xe5, 0xfe, 0x05, 0x02, - 0xed, 0xbb, 0x43, 0xdc, 0x40, 0x8e, 0xab, 0x93, 0x90, 0xb8, 0xab, 0x2a, 0x20, 0x12, 0xdd, 0x86, - 0xca, 0x78, 0x72, 0x34, 0x74, 0xfa, 0x44, 0x92, 0xa3, 0x5a, 0x08, 0x84, 0x04, 0xc2, 0xa4, 0xa4, - 0x45, 0x24, 0x8a, 0x3c, 0x52, 0x54, 0x24, 0x0c, 0x49, 0x50, 0x9c, 0x72, 0x1f, 0x77, 0x70, 0xd5, - 0xc4, 0xbf, 0x8d, 0x75, 0x58, 0x4a, 0x76, 0x5a, 0xca, 0xfa, 0xfb, 0x50, 0x92, 0xe2, 0x41, 0xf9, - 0x1a, 0xea, 0x9a, 0xf7, 0x57, 0x58, 0x45, 0x11, 0xde, 0xf8, 0xbd, 0x39, 0x58, 0x94, 0xd0, 0x0d, - 0x31, 0x23, 0xdd, 0xc9, 0x68, 0x64, 0xfb, 0x29, 0x72, 0x27, 0xf3, 0x7c, 0xb9, 0x93, 0x9d, 0x91, - 0x3b, 0x49, 0x63, 0x93, 0xc4, 0x56, 0xd2, 0xd8, 0x14, 0x4b, 0x40, 0xfa, 0xbf, 0xee, 0x7a, 0xac, - 0x49, 0x70, 0x8f, 0x5c, 0x9c, 0x33, 0x52, 0xb2, 0x90, 0x22, 0x25, 0x75, 0x19, 0x37, 0x37, 0x25, - 0xe3, 0x5e, 0x05, 0x5a, 0x6b, 0x25, 0xb2, 0x8b, 0x64, 0x12, 0x20, 0x4c, 0xfa, 0x2f, 0xef, 0xc2, - 0xfc, 0xb4, 0x58, 0x21, 0xf9, 0x55, 0x4f, 0x11, 0x2a, 0xce, 0x88, 0xe3, 0x01, 0xa1, 0x11, 0x97, - 0xa5, 0x50, 0x71, 0x46, 0x7c, 0x07, 0x31, 0x8a, 0xbe, 0x0d, 0x40, 0x6d, 0xa3, 0x46, 0x02, 0xa8, - 0x91, 0xbc, 0x91, 0x5c, 0x0b, 0x7d, 0xd6, 0x1f, 0x88, 0x8f, 0x89, 0xcf, 0x51, 0x4b, 0x29, 0x63, - 0x49, 0x74, 0x5c, 0x3f, 0x85, 0xba, 0x37, 0xe6, 0xae, 0x15, 0x6f, 0xef, 0x0a, 0x56, 0xf5, 0xfa, - 0x73, 0xaa, 0xea, 0x28, 0x5a, 0xb3, 0x26, 0xca, 0x46, 0x9f, 0x6c, 0x97, 0x26, 0x9e, 0x6b, 0xb5, - 0x55, 0xbf, 0x41, 0x6d, 0x75, 0x2c, 0x1c, 0x7d, 0x1b, 0x7f, 0x2f, 0x03, 0x15, 0xad, 0xdb, 0x6c, - 0x19, 0x16, 0x36, 0xf6, 0xf7, 0x0f, 0xda, 0x66, 0xab, 0xd7, 0xf9, 0xac, 0x6d, 0x6d, 0xec, 0xec, - 0x77, 0xdb, 0x8d, 0x6b, 0x02, 0xbc, 0xb3, 0xbf, 0xd1, 0xda, 0xb1, 0xb6, 0xf6, 0xcd, 0x0d, 0x05, - 0xce, 0xb0, 0x15, 0x60, 0x66, 0x7b, 0x77, 0xbf, 0xd7, 0x4e, 0xc0, 0xb3, 0xac, 0x01, 0xd5, 0x75, - 0xb3, 0xdd, 0xda, 0xd8, 0x96, 0x90, 0x1c, 0x5b, 0x82, 0xc6, 0xd6, 0xe1, 0xde, 0x66, 0x67, 0xef, - 0x89, 0xb5, 0xd1, 0xda, 0xdb, 0x68, 0xef, 0xb4, 0x37, 0x1b, 0x79, 0x56, 0x83, 0x72, 0x6b, 0xbd, - 0xb5, 0xb7, 0xb9, 0xbf, 0xd7, 0xde, 0x6c, 0x14, 0x8c, 0xdf, 0x80, 0x72, 0x3c, 0xd0, 0x0a, 0x14, - 0x0f, 0xf7, 0x9e, 0xee, 0xed, 0x7f, 0xbe, 0xd7, 0xb8, 0xc6, 0xca, 0x50, 0xc0, 0xf6, 0x1b, 0x19, - 0x06, 0x30, 0x47, 0x6d, 0x36, 0xb2, 0xac, 0x04, 0xf9, 0xf5, 0xfd, 0xde, 0x76, 0x23, 0x67, 0xfc, - 0x45, 0x06, 0x96, 0x71, 0xc8, 0x83, 0x69, 0x21, 0x70, 0x07, 0x2a, 0x7d, 0xcf, 0x1b, 0x0b, 0xe3, - 0x26, 0x3e, 0xc4, 0x75, 0x90, 0xd8, 0xe0, 0x24, 0x2f, 0x8f, 0x3d, 0xbf, 0xcf, 0xa5, 0x0c, 0x00, - 0x04, 0x6d, 0x09, 0x88, 0xe0, 0x41, 0xc9, 0xc4, 0x44, 0x41, 0x22, 0xa0, 0x42, 0x30, 0x22, 0x59, - 0x81, 0xb9, 0x23, 0x9f, 0xdb, 0xfd, 0x53, 0xb9, 0xfb, 0xe5, 0x17, 0x7b, 0x33, 0x36, 0xbb, 0xfb, - 0x82, 0xa7, 0x86, 0x7c, 0x80, 0x5b, 0xa0, 0x64, 0xce, 0x4b, 0xf8, 0x86, 0x04, 0x8b, 0x03, 0xc0, - 0x3e, 0xb2, 0xdd, 0x81, 0xe7, 0xf2, 0x81, 0xd4, 0xee, 0x63, 0x80, 0x71, 0x00, 0x2b, 0xd3, 0xe3, - 0x93, 0xf2, 0xe2, 0x03, 0x4d, 0x5e, 0x90, 0xb2, 0xbd, 0x76, 0x35, 0x2b, 0x68, 0xb2, 0xe3, 0xe7, - 0x39, 0xc8, 0x0b, 0xe5, 0xeb, 0x4a, 0x3d, 0x4d, 0xd7, 0xa6, 0x73, 0x33, 0x11, 0x17, 0xb4, 0xee, - 0xe9, 0x54, 0x26, 0x17, 0x52, 0x19, 0x21, 0x78, 0x1a, 0x47, 0x68, 0x9f, 0xf7, 0xcf, 0xa4, 0x0f, - 0x89, 0xd0, 0x26, 0xef, 0x9f, 0xa1, 0x19, 0x63, 0x87, 0x54, 0x96, 0xf6, 0x7b, 0x31, 0xb0, 0x43, - 0x2c, 0x29, 0x51, 0x58, 0xae, 0x18, 0xa1, 0xb0, 0x54, 0x13, 0x8a, 0x8e, 0x7b, 0xe4, 0x4d, 0xdc, - 0x01, 0x6e, 0xef, 0x92, 0xa9, 0x3e, 0x31, 0xc0, 0x83, 0x92, 0x48, 0x9c, 0x1f, 0xb4, 0x9b, 0x4b, - 0x02, 0xd0, 0x13, 0x27, 0xc8, 0xbb, 0x50, 0x0e, 0x2e, 0xdd, 0xbe, 0xbe, 0x87, 0x97, 0xe4, 0xfc, - 0x88, 0xd1, 0x3f, 0xe8, 0x5e, 0xba, 0x7d, 0xdc, 0xb1, 0xa5, 0x40, 0xfe, 0xc5, 0xde, 0x87, 0x52, - 0xe4, 0x6a, 0x25, 0x09, 0x7c, 0x5d, 0x2f, 0xa1, 0xfc, 0xab, 0x64, 0xd1, 0x46, 0xa4, 0x6b, 0x4f, - 0xa1, 0x96, 0x40, 0xe9, 0x66, 0x68, 0x8d, 0xcc, 0xd0, 0xd7, 0x75, 0x33, 0x34, 0x16, 0xec, 0xb2, - 0x98, 0x6e, 0x96, 0xfe, 0x26, 0x94, 0x54, 0xcf, 0xc4, 0x76, 0x92, 0x5b, 0xc1, 0xea, 0x7e, 0xb1, - 0xb7, 0xd1, 0xb8, 0xc6, 0xe6, 0xa1, 0xd2, 0xda, 0xc0, 0x1d, 0x8a, 0x80, 0x8c, 0x20, 0x39, 0x68, - 0x75, 0xbb, 0x11, 0x24, 0x6b, 0x30, 0x68, 0x88, 0xe3, 0x45, 0xf4, 0x38, 0x0a, 0xa6, 0x7c, 0x00, - 0x0b, 0x1a, 0x2c, 0xb6, 0xd4, 0xc4, 0x79, 0x34, 0x6d, 0xa9, 0xa1, 0x5e, 0x4e, 0x18, 0x63, 0x15, - 0x96, 0xc5, 0x67, 0xfb, 0x8c, 0xbb, 0x61, 0x77, 0x72, 0x44, 0xa1, 0x34, 0xc7, 0x73, 0x85, 0xbe, - 0x5e, 0x8e, 0x30, 0x57, 0x33, 0xd2, 0x03, 0x69, 0xd4, 0x65, 0x71, 0xfa, 0xd7, 0xb4, 0x16, 0xb0, - 0xe0, 0x03, 0xfc, 0x37, 0x61, 0xdc, 0x95, 0x23, 0x90, 0x18, 0xeb, 0x41, 0xbb, 0x6d, 0x5a, 0xfb, - 0x7b, 0x3b, 0x9d, 0x3d, 0x21, 0x8c, 0xc4, 0x58, 0x11, 0xb0, 0xb5, 0x85, 0x90, 0x8c, 0xd1, 0x80, - 0xfa, 0x13, 0x1e, 0x76, 0xdc, 0x63, 0x4f, 0x8d, 0xf4, 0x17, 0x05, 0x98, 0x8f, 0x40, 0xb1, 0x71, - 0x78, 0xc6, 0xfd, 0xc0, 0xf1, 0x5c, 0xd4, 0xf3, 0xca, 0xa6, 0xfa, 0x14, 0x27, 0x88, 0x33, 0xe0, - 0x6e, 0xe8, 0x84, 0x97, 0x56, 0xc2, 0x93, 0x54, 0x57, 0x60, 0x79, 0x52, 0x2d, 0x41, 0xc1, 0x1e, - 0x3a, 0xb6, 0x8a, 0x40, 0xd2, 0x87, 0x80, 0xf6, 0xbd, 0xa1, 0xe7, 0xa3, 0x4a, 0x57, 0x36, 0xe9, - 0x83, 0x3d, 0x82, 0x25, 0xa1, 0x5a, 0xea, 0xee, 0x3d, 0xdc, 0xa3, 0xe4, 0xd4, 0x62, 0xee, 0x64, - 0x74, 0x10, 0xbb, 0xf8, 0x04, 0x46, 0x9c, 0x4f, 0xa2, 0x84, 0x54, 0x48, 0xa2, 0x02, 0x64, 0xa5, - 0x2c, 0xb8, 0x93, 0x51, 0x0b, 0x31, 0x11, 0xfd, 0x63, 0x58, 0x16, 0xf4, 0x91, 0x0a, 0x13, 0x95, - 0x98, 0xc7, 0x12, 0xa2, 0xb2, 0x8e, 0xc4, 0x45, 0x65, 0x6e, 0x40, 0x99, 0x7a, 0x25, 0x56, 0xbc, - 0x40, 0xda, 0x29, 0x76, 0x85, 0xfb, 0xc1, 0x4c, 0xb0, 0x70, 0x8e, 0x0e, 0xdb, 0xa9, 0x60, 0xa1, - 0x16, 0x6e, 0x2c, 0x4d, 0x87, 0x1b, 0x1f, 0xc3, 0xf2, 0x11, 0x0f, 0x42, 0xeb, 0x94, 0xdb, 0x03, - 0xee, 0xe3, 0x8e, 0xa4, 0xb0, 0x22, 0x69, 0xe1, 0x8b, 0x02, 0xb9, 0x8d, 0xb8, 0x9e, 0x42, 0x09, - 0x5d, 0x42, 0x6c, 0x3d, 0x3e, 0xb0, 0x42, 0xcf, 0x42, 0x15, 0x03, 0x37, 0x71, 0xc9, 0xac, 0x11, - 0xb8, 0xe7, 0x6d, 0x08, 0x60, 0x92, 0xee, 0xc4, 0xb7, 0xc7, 0xa7, 0x52, 0x4f, 0x8e, 0xe8, 0x9e, - 0x08, 0x20, 0xbb, 0x09, 0xc5, 0x90, 0x07, 0xa1, 0xcb, 0x29, 0xa6, 0x53, 0x42, 0x9f, 0xbd, 0x02, - 0xb1, 0xd7, 0x61, 0x0e, 0xdb, 0x08, 0x9a, 0x0d, 0xe4, 0xf7, 0x6a, 0x2c, 0x2c, 0x1d, 0xd7, 0x94, - 0x38, 0xa1, 0xb0, 0x4d, 0x7c, 0x27, 0x68, 0x56, 0x31, 0x96, 0x89, 0x7f, 0xb3, 0xdf, 0xd2, 0xc4, - 0xc2, 0x22, 0x96, 0x55, 0x67, 0xee, 0x14, 0xa7, 0xfd, 0x5a, 0x24, 0xc4, 0xf7, 0xf3, 0xa5, 0x4a, - 0xa3, 0x6a, 0x7c, 0x08, 0x05, 0x9a, 0x1d, 0xc1, 0x84, 0x38, 0x77, 0x19, 0xc9, 0x84, 0x08, 0x6d, - 0x42, 0xd1, 0xe5, 0xe1, 0xb9, 0xe7, 0x3f, 0x53, 0xbe, 0x56, 0xf9, 0x69, 0xfc, 0x18, 0x9d, 0x04, - 0x51, 0x20, 0x99, 0xec, 0x1d, 0xc1, 0x1e, 0xb4, 0xbc, 0xc1, 0xa9, 0x2d, 0xfd, 0x16, 0x25, 0x04, - 0x74, 0x4f, 0xed, 0x19, 0xf6, 0xc8, 0xce, 0xc6, 0x92, 0x5f, 0x87, 0xba, 0x0a, 0x5d, 0x07, 0xd6, - 0x90, 0x1f, 0x87, 0x92, 0xdd, 0xab, 0x32, 0x6e, 0x1d, 0xec, 0xf0, 0xe3, 0xd0, 0xd8, 0x85, 0x05, - 0xc9, 0x90, 0xfb, 0x63, 0xae, 0x9a, 0xfe, 0x28, 0x4d, 0x67, 0xad, 0x3c, 0x5e, 0x4c, 0x1e, 0x66, - 0x14, 0x92, 0x4f, 0x28, 0xb2, 0xc6, 0xa7, 0xc0, 0xf4, 0xa3, 0x4e, 0xd6, 0x27, 0x35, 0x47, 0xe5, - 0xa2, 0x56, 0x91, 0x9e, 0x48, 0x3f, 0x75, 0x06, 0x62, 0x76, 0x82, 0x49, 0xbf, 0xaf, 0x52, 0x0a, - 0x4a, 0xa6, 0xfa, 0x34, 0xfe, 0x2c, 0x03, 0x8b, 0x58, 0x99, 0xd2, 0xb9, 0xa5, 0x36, 0xf1, 0xad, - 0x3b, 0x29, 0xd6, 0x47, 0xd7, 0x2f, 0xe8, 0xe3, 0x9b, 0x3b, 0x05, 0xf3, 0x33, 0x4e, 0xc1, 0x37, - 0xa1, 0x31, 0xe0, 0x43, 0x07, 0xb3, 0x4b, 0xd4, 0x71, 0x4d, 0x5a, 0xf6, 0xbc, 0x82, 0x2b, 0x43, - 0xe9, 0x9f, 0x64, 0x60, 0x81, 0xb4, 0x01, 0x34, 0x17, 0xe5, 0x44, 0x7d, 0xa2, 0x6c, 0x2c, 0x29, - 0xaa, 0xe4, 0x98, 0xe2, 0x53, 0x12, 0xa1, 0x44, 0xbc, 0x7d, 0x4d, 0xda, 0x5e, 0x12, 0xca, 0x3e, - 0x46, 0x3b, 0xc1, 0xb5, 0x10, 0x98, 0x92, 0xad, 0x92, 0x5c, 0x94, 0xed, 0x6b, 0x68, 0x44, 0xb8, - 0x08, 0x5a, 0x2f, 0x09, 0xa3, 0x4f, 0x80, 0x8d, 0x2d, 0xa8, 0x25, 0x9a, 0x49, 0x78, 0x2e, 0xab, - 0xe4, 0xb9, 0x9c, 0x89, 0x0e, 0x64, 0x67, 0xa3, 0x03, 0x7f, 0x27, 0x0f, 0x4c, 0xb0, 0xd4, 0xd4, - 0xaa, 0x4d, 0x85, 0xd6, 0xb2, 0x33, 0xa1, 0xb5, 0x47, 0xc0, 0x34, 0x02, 0x15, 0xf1, 0xcb, 0x45, - 0x11, 0xbf, 0x46, 0x4c, 0x2b, 0x03, 0x7e, 0x8f, 0x60, 0x49, 0x2a, 0x8d, 0x51, 0x2c, 0x0d, 0x5d, - 0x52, 0xb4, 0x3e, 0x8c, 0xb4, 0x47, 0x15, 0x53, 0x43, 0xf7, 0x94, 0x0a, 0xab, 0x09, 0x93, 0x9a, - 0x3c, 0x39, 0x18, 0x56, 0x13, 0x56, 0xf4, 0x14, 0x17, 0xcc, 0xbd, 0x90, 0x0b, 0x8a, 0x33, 0x5c, - 0xa0, 0x39, 0x16, 0x4a, 0x49, 0xc7, 0x82, 0x01, 0x35, 0x15, 0x3c, 0xa3, 0x9c, 0x01, 0xd2, 0x90, - 0x2a, 0x32, 0x82, 0x86, 0x79, 0x03, 0xf7, 0xa0, 0xa1, 0xac, 0xff, 0xc8, 0x75, 0x41, 0xf1, 0x70, - 0xe9, 0x3c, 0xda, 0x50, 0x0e, 0x8c, 0x84, 0xa3, 0xb8, 0x32, 0xe5, 0x28, 0x7e, 0x0b, 0x16, 0x02, - 0xc1, 0x44, 0xd6, 0xc4, 0x95, 0xc9, 0x2b, 0x7c, 0x80, 0xe6, 0x49, 0xc9, 0x6c, 0x20, 0xe2, 0x30, - 0x86, 0xcf, 0x9a, 0xf6, 0xb5, 0x59, 0xd3, 0x9e, 0xbd, 0x1f, 0xc7, 0x99, 0x82, 0x53, 0x67, 0x84, - 0x07, 0x77, 0x9c, 0xe8, 0x21, 0x27, 0xb8, 0x7b, 0xea, 0x8c, 0x4c, 0x15, 0xd4, 0x14, 0x1f, 0xc6, - 0x7f, 0xce, 0x40, 0x43, 0xf0, 0x41, 0x82, 0xcf, 0x7f, 0x03, 0x70, 0x47, 0xbe, 0x24, 0x9b, 0x57, - 0x04, 0xad, 0xe2, 0xf2, 0x0f, 0x01, 0xd9, 0xd6, 0x12, 0xb6, 0x98, 0x64, 0xf2, 0x66, 0x92, 0xc9, - 0x63, 0x41, 0xb6, 0x7d, 0x8d, 0x94, 0x6c, 0x01, 0x49, 0x8b, 0xef, 0xe5, 0x53, 0xe2, 0x7b, 0xda, - 0x56, 0xd8, 0x06, 0x78, 0xca, 0x2f, 0x77, 0xbc, 0x3e, 0x5a, 0x41, 0xb7, 0x00, 0x04, 0x43, 0x1e, - 0xdb, 0x23, 0x47, 0x7a, 0x30, 0x0a, 0x66, 0xf9, 0x19, 0xbf, 0xdc, 0x42, 0x80, 0x58, 0x0d, 0x81, - 0x8e, 0xf7, 0x43, 0xc1, 0x2c, 0x3d, 0xe3, 0x97, 0xb4, 0x19, 0x2c, 0xa8, 0x3d, 0xe5, 0x97, 0x9b, - 0x9c, 0xd4, 0x35, 0xcf, 0x17, 0x9c, 0xe0, 0xdb, 0xe7, 0x42, 0x3f, 0x4b, 0xc4, 0xe6, 0x2a, 0xbe, - 0x7d, 0xfe, 0x94, 0x5f, 0xaa, 0x38, 0x61, 0x51, 0xe0, 0x87, 0x5e, 0x5f, 0x9e, 0x40, 0x2a, 0xcb, - 0x20, 0xee, 0x94, 0x39, 0xf7, 0x0c, 0xff, 0x36, 0xfe, 0x34, 0x03, 0x35, 0xd1, 0x7f, 0x14, 0x70, - 0x62, 0xde, 0x55, 0xb2, 0x4a, 0x26, 0x4e, 0x56, 0x79, 0x2c, 0xe5, 0x03, 0x49, 0xcb, 0xec, 0xd5, - 0xd2, 0x12, 0x27, 0x98, 0x44, 0xe5, 0xbb, 0x50, 0xa6, 0xbd, 0x25, 0x36, 0x6b, 0x2e, 0xb1, 0x4a, - 0x89, 0x01, 0x99, 0x25, 0x24, 0x7b, 0x4a, 0xb1, 0x71, 0xcd, 0x01, 0x45, 0x53, 0x5c, 0xf6, 0x23, - 0xd7, 0x53, 0xca, 0x32, 0x14, 0xd2, 0xc2, 0xac, 0x87, 0x50, 0xd1, 0x78, 0x8a, 0x7d, 0x8f, 0x02, - 0xd4, 0xd4, 0x79, 0x62, 0xc0, 0x24, 0xd3, 0x24, 0x46, 0xbf, 0x7d, 0xcd, 0xac, 0xf5, 0x75, 0xc0, - 0xfa, 0x1c, 0xe4, 0x45, 0x21, 0xe3, 0x13, 0x58, 0xd0, 0xaa, 0x25, 0x8b, 0x2f, 0xad, 0x4f, 0x99, - 0xb4, 0x3e, 0xfd, 0xd3, 0x0c, 0x2c, 0xc9, 0xd2, 0x98, 0xd8, 0xe4, 0x88, 0xe3, 0x7a, 0x37, 0x38, - 0x61, 0xbf, 0x01, 0x35, 0x51, 0xbb, 0xe5, 0xf3, 0x13, 0x27, 0x08, 0xb9, 0xf2, 0xec, 0xa7, 0x6c, - 0x0e, 0x21, 0xb5, 0x05, 0xa9, 0x29, 0x29, 0xd9, 0x27, 0x50, 0xc1, 0xa2, 0x64, 0x93, 0xca, 0x65, - 0x69, 0xce, 0x16, 0xa4, 0xae, 0x6e, 0x5f, 0x33, 0x21, 0x88, 0xbe, 0xd6, 0xcb, 0x50, 0x0c, 0x7d, - 0xe7, 0xe4, 0x84, 0xfb, 0xc6, 0x4a, 0xd4, 0x35, 0xb1, 0xd3, 0x78, 0x37, 0xe4, 0x63, 0xa1, 0x04, - 0x19, 0xff, 0x35, 0x03, 0x15, 0xb9, 0x77, 0xbe, 0xb5, 0x3b, 0x7f, 0x4d, 0xcb, 0xcc, 0x23, 0xf3, - 0x33, 0x4e, 0xc4, 0xbb, 0x0b, 0xf3, 0x23, 0xa1, 0x10, 0x09, 0x85, 0x3d, 0xe1, 0xcb, 0xaf, 0x2b, - 0xb0, 0xd4, 0x47, 0x1e, 0xc0, 0x22, 0xaa, 0x27, 0x81, 0x15, 0x3a, 0x43, 0x4b, 0x21, 0x65, 0x16, - 0xdc, 0x02, 0xa1, 0x7a, 0xce, 0x70, 0x57, 0x22, 0xc4, 0x29, 0x1d, 0x84, 0xf6, 0x09, 0x97, 0xaa, - 0x2f, 0x7d, 0x18, 0x4d, 0x58, 0x99, 0xd2, 0xd5, 0x95, 0x9d, 0xf1, 0xf7, 0x6b, 0xb0, 0x3a, 0x83, - 0x92, 0xf6, 0x46, 0xe4, 0xc3, 0x1e, 0x3a, 0xa3, 0x23, 0x2f, 0x72, 0x37, 0x65, 0x34, 0x1f, 0xf6, - 0x8e, 0xc0, 0x28, 0x77, 0x13, 0x87, 0x65, 0xc5, 0x10, 0xe8, 0x2f, 0x8a, 0xd4, 0xf9, 0x2c, 0x2a, - 0x9b, 0xef, 0x26, 0x05, 0xd5, 0x74, 0x73, 0x0a, 0xae, 0x1f, 0x7f, 0x8b, 0xe3, 0x19, 0x58, 0xc0, - 0x8e, 0xa1, 0x19, 0xf1, 0x9d, 0xd4, 0x8f, 0x34, 0xdb, 0x44, 0xb4, 0xf4, 0xf6, 0x0b, 0x5a, 0x4a, - 0x38, 0x22, 0xcc, 0x15, 0xc5, 0xae, 0x54, 0x59, 0xd4, 0xce, 0x19, 0xbc, 0xa2, 0xda, 0x41, 0x5d, - 0x67, 0xb6, 0xb5, 0xfc, 0x4b, 0x8d, 0x0b, 0x1d, 0x2c, 0xc9, 0x26, 0x6f, 0xc8, 0x8a, 0x23, 0x94, - 0xde, 0xee, 0x29, 0xac, 0x9c, 0xdb, 0x4e, 0xa8, 0xc6, 0xa7, 0x99, 0x45, 0x05, 0x6c, 0xef, 0xf1, - 0x0b, 0xda, 0xfb, 0x9c, 0x0a, 0x27, 0xb4, 0xbf, 0xa5, 0xf3, 0x59, 0x60, 0xb0, 0xf6, 0x1f, 0xb3, - 0x50, 0x4f, 0xd6, 0x22, 0x36, 0xb5, 0x94, 0x43, 0x4a, 0x9f, 0x90, 0xfa, 0xb8, 0x74, 0x83, 0xee, - 0x91, 0x1e, 0x31, 0xeb, 0xa0, 0xcd, 0xa6, 0x38, 0x68, 0x75, 0xbf, 0x68, 0xee, 0x45, 0xb1, 0x9f, - 0xfc, 0x4b, 0xc5, 0x7e, 0x0a, 0x69, 0xb1, 0x9f, 0xab, 0x03, 0x06, 0x73, 0xdf, 0x2a, 0x60, 0x50, - 0xbc, 0x3a, 0x60, 0xb0, 0xf6, 0x7f, 0x32, 0xc0, 0x66, 0x39, 0x95, 0x3d, 0x21, 0x5f, 0xb4, 0xcb, - 0x87, 0x52, 0x8a, 0xbd, 0xf3, 0x72, 0xdc, 0xae, 0x16, 0x48, 0x95, 0x66, 0x0f, 0x61, 0x51, 0xcf, - 0x9b, 0xd5, 0x4d, 0x95, 0x9a, 0xc9, 0x74, 0x54, 0x6c, 0xd0, 0x6a, 0x81, 0xaf, 0xfc, 0x0b, 0x03, - 0x5f, 0x85, 0x17, 0x06, 0xbe, 0xe6, 0x92, 0x81, 0xaf, 0xb5, 0xbf, 0x95, 0x81, 0xc5, 0x14, 0xa6, - 0xfa, 0xd5, 0x8d, 0x59, 0xf0, 0x42, 0x42, 0xc4, 0x64, 0x25, 0x2f, 0x68, 0xd2, 0x65, 0xed, 0x2b, - 0xa8, 0x25, 0x36, 0xd1, 0xaf, 0xae, 0xf9, 0x69, 0x43, 0x8b, 0x58, 0x59, 0x37, 0xb4, 0xd6, 0xfe, - 0x2a, 0x0b, 0x6c, 0x76, 0x1f, 0xff, 0x3a, 0xbb, 0x30, 0x3b, 0x49, 0xb9, 0xd9, 0x49, 0xfa, 0x7f, - 0x77, 0xae, 0xbc, 0x05, 0x0b, 0x32, 0xd7, 0x5f, 0x0b, 0x3c, 0x10, 0xa3, 0x34, 0x22, 0x84, 0xea, - 0xc5, 0x87, 0xd3, 0x31, 0xc7, 0x52, 0x22, 0xbd, 0x59, 0x3b, 0x58, 0x93, 0xa1, 0x47, 0x63, 0x0d, - 0x9a, 0x72, 0x6a, 0x66, 0x5d, 0x75, 0x3f, 0xc9, 0x47, 0x56, 0x32, 0x22, 0xa5, 0x52, 0xfc, 0x5d, - 0xa8, 0xea, 0x87, 0x8d, 0x5c, 0x87, 0xa9, 0x88, 0x93, 0x50, 0x87, 0x3d, 0x6d, 0xb7, 0x6e, 0x00, - 0xc5, 0x11, 0x06, 0x51, 0x31, 0xd2, 0x20, 0x9e, 0xe3, 0x78, 0x46, 0xe5, 0x28, 0xb1, 0xf8, 0xff, - 0x1f, 0xd4, 0x93, 0x7e, 0x2b, 0xa9, 0xea, 0xa5, 0x69, 0x87, 0xa2, 0x74, 0xc2, 0x91, 0xc5, 0x7e, - 0x0b, 0x1a, 0xd3, 0x7e, 0x2f, 0x99, 0x7b, 0x79, 0x45, 0xf9, 0x79, 0x27, 0xe9, 0x0a, 0x63, 0xdb, - 0xb0, 0x94, 0x76, 0xdc, 0xe2, 0xaa, 0x5c, 0x6d, 0x16, 0xb0, 0xd9, 0x23, 0x95, 0x7d, 0x24, 0xdd, - 0x9b, 0x85, 0xb4, 0x40, 0x8c, 0x36, 0xd9, 0x0f, 0xe8, 0x3f, 0xcd, 0xd1, 0x79, 0x06, 0x10, 0xc3, - 0x58, 0x03, 0xaa, 0xfb, 0x07, 0xed, 0x3d, 0x6b, 0x63, 0xbb, 0xb5, 0xb7, 0xd7, 0xde, 0x69, 0x5c, - 0x63, 0x0c, 0xea, 0x18, 0x41, 0xd9, 0x8c, 0x60, 0x19, 0x01, 0x93, 0xbe, 0x5f, 0x05, 0xcb, 0xb2, - 0x25, 0x68, 0x74, 0xf6, 0xa6, 0xa0, 0x39, 0xd6, 0x84, 0xa5, 0x83, 0x36, 0x05, 0x5d, 0x12, 0xf5, - 0xe6, 0x85, 0x0a, 0x27, 0x87, 0x2b, 0x54, 0x38, 0xba, 0x29, 0x22, 0xb9, 0x4f, 0x69, 0x36, 0x3f, - 0xcd, 0xc0, 0xf2, 0x14, 0x22, 0xce, 0xff, 0x25, 0xbd, 0x26, 0xa9, 0xd1, 0x54, 0x11, 0xa8, 0x78, - 0xf8, 0x2d, 0x58, 0x88, 0x4c, 0xbd, 0x29, 0xb9, 0xd4, 0x88, 0x10, 0x8a, 0xf8, 0x21, 0x2c, 0x6a, - 0x16, 0xe3, 0xd4, 0x0e, 0x65, 0x1a, 0x4a, 0x16, 0x30, 0x56, 0xa3, 0x3c, 0xcb, 0xa9, 0x5e, 0x0f, - 0xe8, 0xfa, 0x89, 0x8e, 0x88, 0xbd, 0xbf, 0xc9, 0xfe, 0xaa, 0x4f, 0x61, 0xca, 0x27, 0x18, 0x21, - 0xd9, 0x5b, 0x7d, 0xc1, 0x55, 0xf3, 0x7f, 0x38, 0x07, 0xec, 0xd3, 0x09, 0xf7, 0x2f, 0x31, 0xbf, - 0x37, 0x78, 0x51, 0xc2, 0x8b, 0x32, 0x8b, 0xb2, 0x2f, 0x95, 0xc3, 0x9f, 0x96, 0x43, 0x9f, 0x7f, - 0x71, 0x0e, 0x7d, 0xe1, 0x45, 0x39, 0xf4, 0xaf, 0x41, 0xcd, 0x39, 0x71, 0x3d, 0x21, 0x80, 0x84, - 0x6e, 0x12, 0x34, 0xe7, 0xee, 0xe4, 0xee, 0x55, 0xcd, 0xaa, 0x04, 0x0a, 0xcd, 0x24, 0x60, 0x9f, - 0xc4, 0x44, 0x7c, 0x70, 0x82, 0xf7, 0x3d, 0x74, 0xd1, 0xd3, 0x1e, 0x9c, 0x70, 0x69, 0x05, 0xa2, - 0x5f, 0x44, 0x15, 0x16, 0xf0, 0x80, 0xbd, 0x0e, 0xf5, 0xc0, 0x9b, 0x08, 0x55, 0x4f, 0x4d, 0x03, - 0xf9, 0x87, 0xab, 0x04, 0x3d, 0x50, 0xc1, 0x80, 0xc5, 0x49, 0xc0, 0xad, 0x91, 0x13, 0x04, 0xe2, - 0x80, 0xee, 0x7b, 0x6e, 0xe8, 0x7b, 0x43, 0xe9, 0xf2, 0x5d, 0x98, 0x04, 0x7c, 0x97, 0x30, 0x1b, - 0x84, 0x60, 0xef, 0xc5, 0x5d, 0x1a, 0xdb, 0x8e, 0x1f, 0x34, 0x01, 0xbb, 0xa4, 0x46, 0x8a, 0x1a, - 0x95, 0xed, 0xf8, 0x51, 0x5f, 0xc4, 0x47, 0x30, 0x95, 0xdb, 0x5f, 0x99, 0xce, 0xed, 0xff, 0x51, - 0x7a, 0x6e, 0x7f, 0x0d, 0xab, 0x7e, 0x24, 0xab, 0x9e, 0x5d, 0xe2, 0x6f, 0x94, 0xe2, 0x3f, 0x7b, - 0x65, 0xa1, 0xfe, 0x4d, 0xae, 0x2c, 0xcc, 0xa7, 0x5d, 0x59, 0x78, 0x17, 0x2a, 0x98, 0x4c, 0x6e, - 0x9d, 0x3a, 0x6e, 0xa8, 0x5c, 0xd8, 0x0d, 0x3d, 0xdb, 0x7c, 0x5b, 0x18, 0xd3, 0xe0, 0xab, 0x3f, - 0x83, 0xd9, 0xdb, 0x03, 0x0b, 0xbf, 0xc6, 0xdb, 0x03, 0x32, 0xe9, 0xfd, 0x01, 0x94, 0xd4, 0x3a, - 0x31, 0x06, 0xf9, 0x63, 0xdf, 0x1b, 0x29, 0xd7, 0x9e, 0xf8, 0x9b, 0xd5, 0x21, 0x1b, 0x7a, 0xb2, - 0x70, 0x36, 0xf4, 0x8c, 0xdf, 0x81, 0x8a, 0xc6, 0x6a, 0xec, 0x55, 0x72, 0x22, 0x08, 0x6d, 0x59, - 0x5a, 0xc9, 0x34, 0x8b, 0x65, 0x09, 0xed, 0x0c, 0x84, 0xbc, 0x19, 0x38, 0x3e, 0xc7, 0x7b, 0x3e, - 0x96, 0xcf, 0xcf, 0xb8, 0x1f, 0x28, 0x57, 0x6b, 0x23, 0x42, 0x98, 0x04, 0x37, 0xfe, 0x3a, 0x2c, - 0x26, 0xd6, 0x56, 0x8a, 0x88, 0xd7, 0x61, 0x0e, 0xe7, 0x4d, 0x85, 0xc2, 0x92, 0x59, 0xfc, 0x12, - 0x87, 0x17, 0x38, 0xc9, 0x4b, 0x6c, 0x8d, 0x7d, 0xef, 0x08, 0x1b, 0xc9, 0x98, 0x15, 0x09, 0x3b, - 0xf0, 0xbd, 0x23, 0xe3, 0xe7, 0x39, 0xc8, 0x6d, 0x7b, 0x63, 0x3d, 0xc3, 0x22, 0x33, 0x93, 0x61, - 0x21, 0x4d, 0x00, 0x2b, 0x52, 0xf1, 0xa5, 0xd6, 0x86, 0xfe, 0x51, 0xa5, 0xe6, 0xdf, 0x83, 0xba, - 0x90, 0x13, 0xa1, 0x27, 0x6c, 0xa8, 0x73, 0xdb, 0xa7, 0x9c, 0xfe, 0x1c, 0x6d, 0x3e, 0x7b, 0x14, - 0xf6, 0xbc, 0x2d, 0x82, 0xb3, 0x25, 0xc8, 0x45, 0x0a, 0x2c, 0xa2, 0xc5, 0xa7, 0x30, 0xae, 0x31, - 0xbb, 0xed, 0x52, 0xc6, 0x7a, 0xe4, 0x17, 0x7b, 0x07, 0x16, 0x93, 0xf5, 0x92, 0x28, 0x92, 0x1a, - 0x89, 0x5e, 0x31, 0xca, 0xa4, 0xeb, 0x20, 0xe4, 0x08, 0xd1, 0xc8, 0xb0, 0xec, 0x31, 0xe7, 0x88, - 0xd2, 0x84, 0x5e, 0x29, 0x21, 0xf4, 0x6e, 0x43, 0x25, 0x1c, 0x9e, 0x59, 0x63, 0xfb, 0x72, 0xe8, - 0xd9, 0x03, 0xb9, 0xbf, 0x21, 0x1c, 0x9e, 0x1d, 0x10, 0x84, 0x3d, 0x04, 0x18, 0x8d, 0xc7, 0x72, - 0xef, 0xa1, 0xbb, 0x31, 0x66, 0xe5, 0xdd, 0x83, 0x03, 0x62, 0x39, 0xb3, 0x3c, 0x1a, 0x8f, 0xe9, - 0x4f, 0xb6, 0x09, 0xf5, 0xd4, 0xbb, 0x38, 0xb7, 0x54, 0x32, 0x96, 0x37, 0x7e, 0x90, 0xb2, 0x39, - 0x6b, 0x7d, 0x1d, 0xb6, 0xf6, 0x5b, 0xc0, 0x7e, 0xc9, 0x1b, 0x31, 0x3d, 0x28, 0x47, 0xfd, 0xd3, - 0x2f, 0x94, 0x60, 0x7a, 0x65, 0x25, 0x71, 0xa1, 0xa4, 0x35, 0x18, 0xf8, 0x42, 0x2e, 0xd2, 0x81, - 0x19, 0x89, 0x7c, 0xd0, 0x4e, 0xcc, 0x16, 0xc9, 0x7d, 0xe3, 0x2f, 0x33, 0x50, 0xa0, 0xdb, 0x2d, - 0x6f, 0xc0, 0x3c, 0xd1, 0x47, 0xd9, 0x2a, 0x32, 0x42, 0x44, 0xe7, 0x6e, 0x4f, 0x26, 0xaa, 0x88, - 0x6d, 0xa1, 0xdd, 0xcc, 0xcb, 0x46, 0x2b, 0xaf, 0xdd, 0xce, 0xbb, 0x0d, 0xe5, 0xa8, 0x69, 0x8d, - 0x75, 0x4a, 0xaa, 0x65, 0xf6, 0x0a, 0xe4, 0x4f, 0xbd, 0xb1, 0xb2, 0xc5, 0x21, 0x9e, 0x49, 0x13, - 0xe1, 0x71, 0x5f, 0x44, 0x1b, 0xd4, 0x79, 0x69, 0x43, 0x46, 0x8d, 0x20, 0x1b, 0xcc, 0x8e, 0x71, - 0x2e, 0x65, 0x8c, 0x87, 0x30, 0x2f, 0xe4, 0x80, 0x16, 0xa9, 0xbd, 0xfa, 0xd0, 0x7c, 0x53, 0x68, - 0x78, 0xfd, 0xe1, 0x64, 0xc0, 0x75, 0x4f, 0x08, 0xa6, 0x4e, 0x48, 0xb8, 0x32, 0x0f, 0x8c, 0x3f, - 0xcc, 0x90, 0x7c, 0x11, 0xf5, 0xb2, 0x7b, 0x90, 0x17, 0xe7, 0xdb, 0x94, 0xa7, 0x2e, 0xca, 0x73, - 0x15, 0x74, 0x26, 0x52, 0xe0, 0x75, 0xd6, 0xc9, 0x28, 0x59, 0x7b, 0xcd, 0xac, 0xb8, 0x93, 0x51, - 0xe4, 0x4c, 0xf8, 0x8e, 0x1a, 0xd6, 0x94, 0x21, 0x4e, 0xa3, 0x8f, 0xb6, 0xe9, 0x03, 0x2d, 0x07, - 0x23, 0x9f, 0x38, 0x31, 0x95, 0x16, 0x38, 0x38, 0xe1, 0x5a, 0xee, 0xc5, 0x1f, 0x67, 0xa1, 0x96, - 0xe8, 0x11, 0x26, 0xa1, 0x88, 0x03, 0x80, 0xbc, 0xc0, 0x72, 0xbd, 0x41, 0x80, 0xa4, 0xa2, 0xae, - 0xcd, 0x53, 0x36, 0x31, 0x4f, 0x51, 0x4c, 0x3a, 0xa7, 0xc7, 0xa4, 0x1f, 0x41, 0x39, 0xbe, 0x91, - 0x99, 0xec, 0x92, 0x68, 0x4f, 0x65, 0xfb, 0xc6, 0x44, 0x71, 0x14, 0xbb, 0xa0, 0x47, 0xb1, 0xbf, - 0xa7, 0x05, 0x3d, 0xe7, 0xb0, 0x1a, 0x23, 0x6d, 0x46, 0x7f, 0x3d, 0x49, 0x11, 0x9f, 0x40, 0x45, - 0xeb, 0xbc, 0x1e, 0xdc, 0xcc, 0x24, 0x82, 0x9b, 0x51, 0x5e, 0x7e, 0x36, 0xce, 0xcb, 0x37, 0x7e, - 0x2f, 0x0b, 0x35, 0xb1, 0xbf, 0x1c, 0xf7, 0xe4, 0xc0, 0x1b, 0x3a, 0x7d, 0xf4, 0x0a, 0x47, 0x3b, - 0x4c, 0x2a, 0x5a, 0x6a, 0x9f, 0xc9, 0x2d, 0x46, 0x7a, 0x96, 0x7e, 0xfd, 0x88, 0x84, 0x74, 0x74, - 0xfd, 0xc8, 0x80, 0x9a, 0x10, 0x8c, 0x47, 0x76, 0xc0, 0xb5, 0xfb, 0xa2, 0x66, 0xe5, 0x98, 0xf3, - 0x75, 0x3b, 0x20, 0x09, 0xf9, 0x0e, 0x2c, 0x0a, 0x1a, 0xbc, 0x79, 0x31, 0x72, 0x86, 0x43, 0x87, - 0x28, 0xc9, 0xd5, 0xd0, 0x38, 0xe6, 0xdc, 0xb4, 0x43, 0xbe, 0x2b, 0x10, 0xf2, 0x7a, 0x69, 0x69, - 0xe0, 0x04, 0xf6, 0x51, 0x9c, 0x2a, 0x14, 0x7d, 0x63, 0x2c, 0xc7, 0xbe, 0xd0, 0x62, 0x39, 0x74, - 0x05, 0xab, 0x32, 0xb2, 0x2f, 0xa2, 0x58, 0xce, 0x14, 0x27, 0x15, 0xa7, 0x39, 0xc9, 0xf8, 0x2f, - 0x59, 0xa8, 0x68, 0x6c, 0xf9, 0x32, 0xa7, 0xeb, 0xad, 0x19, 0x2f, 0x7e, 0x59, 0x77, 0xd8, 0xbf, - 0x96, 0x6c, 0x12, 0x43, 0xbe, 0x74, 0x91, 0x55, 0x63, 0xe0, 0x1b, 0x50, 0x16, 0xbb, 0xee, 0x5d, - 0x74, 0x8a, 0xc9, 0x6b, 0xd8, 0x08, 0x38, 0x98, 0x1c, 0x29, 0xe4, 0x63, 0x44, 0x16, 0x62, 0xe4, - 0x63, 0x81, 0x7c, 0x5e, 0x7e, 0xe0, 0x87, 0x50, 0x95, 0xb5, 0xe2, 0x9a, 0xe2, 0x70, 0xe3, 0x5d, - 0x9f, 0x58, 0x6f, 0xb3, 0x42, 0xcd, 0xd1, 0xe2, 0xcb, 0x82, 0x8f, 0x55, 0xc1, 0xd2, 0x8b, 0x0a, - 0x3e, 0xa6, 0x0f, 0x63, 0x2b, 0x4a, 0xb9, 0xc4, 0x74, 0x03, 0x25, 0xc7, 0x1e, 0xc2, 0xa2, 0x12, - 0x57, 0x13, 0xd7, 0x76, 0x5d, 0x6f, 0xe2, 0xf6, 0xb9, 0x4a, 0xd8, 0x67, 0x12, 0x75, 0x18, 0x63, - 0x8c, 0x41, 0x74, 0xa3, 0x8b, 0xd2, 0x16, 0xee, 0x43, 0x81, 0xf4, 0x72, 0x52, 0x3e, 0xd2, 0x05, - 0x17, 0x91, 0xb0, 0x7b, 0x50, 0x20, 0xf5, 0x3c, 0x7b, 0xa5, 0xb0, 0x21, 0x02, 0xe3, 0x01, 0xcc, - 0xa3, 0x8a, 0xa9, 0x49, 0xdc, 0xe7, 0x69, 0x25, 0xc6, 0x12, 0xb0, 0x3d, 0xda, 0x44, 0x7a, 0x3a, - 0xcd, 0x7f, 0xcf, 0x41, 0x45, 0x03, 0x0b, 0xb1, 0x88, 0x09, 0x18, 0xd6, 0xc0, 0xb1, 0x47, 0x5c, - 0xc5, 0x1e, 0x6a, 0x66, 0x0d, 0xa1, 0x9b, 0x12, 0x28, 0x0e, 0x05, 0xfb, 0xec, 0xc4, 0xf2, 0x26, - 0xa1, 0x35, 0xe0, 0x27, 0x3e, 0xe7, 0x52, 0x59, 0xaa, 0xda, 0x67, 0x27, 0xfb, 0x93, 0x70, 0x13, - 0x61, 0x82, 0x4a, 0x30, 0xb5, 0x46, 0x25, 0x73, 0x06, 0x46, 0xf6, 0x45, 0x4c, 0x25, 0x13, 0x57, - 0x68, 0x8a, 0xf2, 0x51, 0xe2, 0x0a, 0x99, 0x2d, 0xd3, 0x92, 0xbc, 0x30, 0x2b, 0xc9, 0xdf, 0x83, - 0x15, 0x92, 0xe4, 0x52, 0x46, 0x58, 0x53, 0x2c, 0xb5, 0x84, 0x58, 0x39, 0x48, 0x4d, 0xff, 0x6a, - 0x88, 0x11, 0xa8, 0xfd, 0x11, 0x38, 0x3f, 0xa6, 0x1d, 0x95, 0x31, 0xc5, 0xc8, 0x64, 0xe5, 0x5d, - 0xe7, 0xc7, 0x5c, 0x50, 0x62, 0x60, 0x54, 0xa7, 0x94, 0x69, 0xa8, 0x23, 0xc7, 0x9d, 0xa6, 0xb4, - 0x2f, 0x92, 0x94, 0x65, 0x49, 0x69, 0x5f, 0xe8, 0x94, 0xef, 0xc3, 0xea, 0x88, 0x0f, 0x1c, 0x3b, - 0x59, 0xad, 0x15, 0x6b, 0x10, 0x4b, 0x84, 0xd6, 0xca, 0x74, 0xc9, 0x82, 0x14, 0xb3, 0xf1, 0x63, - 0x6f, 0x74, 0xe4, 0xd0, 0xe1, 0x49, 0xa1, 0xda, 0xbc, 0x59, 0x77, 0x27, 0xa3, 0x1f, 0x20, 0x58, - 0x14, 0x09, 0x8c, 0x1a, 0x54, 0xba, 0xa1, 0x37, 0x56, 0xcb, 0x5c, 0x87, 0x2a, 0x7d, 0xca, 0xeb, - 0x18, 0x37, 0xe0, 0x3a, 0xf2, 0x66, 0xcf, 0x1b, 0x7b, 0x43, 0xef, 0xe4, 0x32, 0xe1, 0x50, 0xfa, - 0x6f, 0x19, 0x58, 0x4c, 0x60, 0xe5, 0x3e, 0x7f, 0x8f, 0x36, 0x56, 0x94, 0x53, 0x4f, 0xec, 0xbc, - 0xa0, 0x1d, 0x3e, 0x44, 0x48, 0xbb, 0x4a, 0xe5, 0xd9, 0xb7, 0xe2, 0xbb, 0xa0, 0xaa, 0x20, 0xf1, - 0x76, 0x73, 0x96, 0xb7, 0x65, 0x79, 0x75, 0x4b, 0x54, 0x55, 0xf1, 0xff, 0xcb, 0x54, 0xe1, 0x81, - 0x1c, 0x72, 0x2e, 0x99, 0x0c, 0xa9, 0x3b, 0x9f, 0x54, 0x0f, 0x62, 0x8f, 0x54, 0x60, 0xfc, 0xab, - 0x0c, 0x40, 0xdc, 0x3b, 0x4c, 0xc7, 0x8c, 0x0e, 0x50, 0x7a, 0x66, 0x45, 0x3b, 0x2c, 0x5f, 0x85, - 0x6a, 0x94, 0x31, 0x16, 0x1f, 0xc9, 0x15, 0x05, 0x13, 0xe7, 0xf2, 0x5d, 0x98, 0x3f, 0x19, 0x7a, - 0x47, 0xa8, 0x3a, 0xc9, 0x03, 0x94, 0x2e, 0xa5, 0xd4, 0x09, 0xac, 0x8e, 0xc5, 0xf8, 0x00, 0xcf, - 0xa7, 0x26, 0x95, 0xe9, 0xc7, 0xb1, 0xf1, 0xfb, 0xd9, 0x28, 0x75, 0x26, 0x9e, 0x89, 0xe7, 0xdb, - 0x19, 0xdf, 0x26, 0x02, 0xfb, 0xbc, 0xc8, 0xc3, 0x27, 0x50, 0xf7, 0x49, 0x3a, 0x2a, 0xd1, 0x99, - 0x7f, 0x8e, 0xe8, 0xac, 0xf9, 0x89, 0x23, 0xf7, 0x4d, 0x68, 0xd8, 0x83, 0x33, 0xee, 0x87, 0x0e, - 0x3a, 0x6b, 0x51, 0x51, 0x93, 0xc9, 0x2a, 0x1a, 0x1c, 0x35, 0xa2, 0xbb, 0x30, 0x2f, 0xaf, 0x08, - 0x45, 0x94, 0xf2, 0xd1, 0x81, 0x18, 0x2c, 0x08, 0x8d, 0x7f, 0xab, 0x72, 0x75, 0x92, 0xab, 0xfb, - 0xfc, 0x59, 0xd1, 0x47, 0x98, 0x9d, 0x8d, 0xad, 0x48, 0x46, 0x92, 0x3e, 0x60, 0x29, 0x8f, 0x08, - 0x28, 0x3d, 0xc0, 0xc9, 0x69, 0xcd, 0xbf, 0xcc, 0xb4, 0x1a, 0x7f, 0x9a, 0x81, 0xe2, 0xb6, 0x37, - 0x16, 0x76, 0xb9, 0xd0, 0xe7, 0x70, 0x9b, 0x44, 0xd7, 0xf3, 0xe6, 0xc4, 0x67, 0x67, 0xf0, 0xfc, - 0xb4, 0xfc, 0x54, 0x7d, 0xa3, 0x96, 0xd4, 0x37, 0xbe, 0x07, 0x37, 0x30, 0x1a, 0xe1, 0x7b, 0x63, - 0xcf, 0x17, 0x5b, 0xd5, 0x1e, 0x92, 0xde, 0xe1, 0xb9, 0xe1, 0xa9, 0x92, 0x9d, 0xd7, 0x8f, 0x39, - 0x3f, 0xd0, 0x28, 0x76, 0x23, 0x02, 0xbc, 0x6b, 0x32, 0x0c, 0xcf, 0x2c, 0x32, 0x15, 0xa5, 0x62, - 0x44, 0x12, 0x75, 0x5e, 0x20, 0xda, 0x08, 0x47, 0xd5, 0xc8, 0xf8, 0x08, 0xca, 0x91, 0xd7, 0x81, - 0xbd, 0x05, 0xe5, 0x53, 0x6f, 0x2c, 0x5d, 0x13, 0x99, 0xc4, 0xd5, 0x05, 0x39, 0x6a, 0xb3, 0x74, - 0x4a, 0x7f, 0x04, 0xc6, 0xcf, 0x8b, 0x50, 0xec, 0xb8, 0x67, 0x9e, 0xd3, 0xc7, 0x6c, 0x9f, 0x11, - 0x1f, 0x79, 0xea, 0x9e, 0xa2, 0xf8, 0x1b, 0x23, 0xfa, 0xf1, 0xd3, 0x01, 0x39, 0x19, 0xd1, 0x8f, - 0x1e, 0x0d, 0x58, 0x86, 0x39, 0x5f, 0xbf, 0xfb, 0x5f, 0xf0, 0x31, 0xff, 0x30, 0x32, 0xda, 0x0a, - 0xda, 0x3d, 0x4f, 0x51, 0x17, 0xdd, 0x49, 0xc7, 0x29, 0xa3, 0xbb, 0x27, 0x65, 0x84, 0xe0, 0x84, - 0xdd, 0x84, 0xa2, 0xbc, 0x29, 0x40, 0x79, 0xd7, 0x94, 0x30, 0x28, 0x41, 0xc8, 0x0d, 0x3e, 0xa7, - 0x68, 0x52, 0xa4, 0x51, 0x09, 0x3b, 0x5d, 0x02, 0x37, 0x05, 0xaf, 0xdd, 0x86, 0x0a, 0xd1, 0x13, - 0x49, 0x49, 0xe6, 0xe7, 0x20, 0x08, 0x09, 0x52, 0x9e, 0xd0, 0x28, 0xa7, 0x3e, 0xa1, 0x81, 0xe9, - 0x5c, 0x91, 0x94, 0xa5, 0x21, 0x02, 0x3d, 0x9c, 0xa0, 0xc1, 0xd5, 0xfb, 0x31, 0xd2, 0xb8, 0xa7, - 0x6b, 0x54, 0xca, 0xb8, 0x7f, 0x0d, 0x6a, 0xc7, 0xf6, 0x70, 0x78, 0x64, 0xf7, 0x9f, 0x91, 0x4d, - 0x5a, 0x25, 0x37, 0x9c, 0x02, 0xa2, 0x51, 0x7a, 0x1b, 0x2a, 0xda, 0x2a, 0x63, 0xf2, 0x4d, 0xde, - 0x84, 0x78, 0x7d, 0xa7, 0x5d, 0x4d, 0xf5, 0x97, 0x70, 0x35, 0x69, 0x49, 0x48, 0xf3, 0xc9, 0x24, - 0xa4, 0x1b, 0x28, 0x4d, 0x65, 0xa2, 0x4a, 0x83, 0x6e, 0xe9, 0xdb, 0x83, 0x01, 0x26, 0xaa, 0xd0, - 0x93, 0x58, 0x38, 0x79, 0x84, 0x5f, 0x20, 0xa5, 0x96, 0x60, 0x44, 0x72, 0x8b, 0xfc, 0xa5, 0x63, - 0xdb, 0x19, 0x60, 0xd2, 0x27, 0x99, 0xb1, 0x45, 0x7b, 0x14, 0x1e, 0xd8, 0xce, 0x80, 0xdd, 0x81, - 0xaa, 0x42, 0xe3, 0xe9, 0xb8, 0x48, 0xf3, 0x2f, 0xd1, 0xe2, 0x4c, 0x34, 0xa0, 0x16, 0x51, 0x8c, - 0xe2, 0xbb, 0x50, 0x15, 0x49, 0x82, 0x7c, 0xf0, 0x2e, 0x06, 0xff, 0x43, 0x8e, 0x37, 0x9e, 0xea, - 0x8f, 0x6f, 0xc8, 0xb1, 0x4a, 0x2e, 0x55, 0xff, 0x63, 0xa6, 0x83, 0x49, 0x94, 0x42, 0x11, 0xa3, - 0x10, 0xcd, 0x4a, 0x42, 0x11, 0x93, 0xa4, 0x18, 0xa2, 0x21, 0x02, 0xf6, 0x91, 0x66, 0x48, 0x35, - 0x91, 0xf8, 0xe6, 0x54, 0xfd, 0x57, 0x98, 0x50, 0x82, 0x7b, 0x9d, 0x40, 0x9c, 0x32, 0x01, 0x77, - 0x07, 0x78, 0x01, 0xaa, 0x64, 0x96, 0x9d, 0xe0, 0x29, 0x01, 0x7e, 0xb5, 0x16, 0x56, 0x0b, 0xaa, - 0xfa, 0x30, 0x59, 0x09, 0xf2, 0xfb, 0x07, 0xed, 0xbd, 0xc6, 0x35, 0x56, 0x81, 0x62, 0xb7, 0xdd, - 0xeb, 0xed, 0xb4, 0x37, 0x1b, 0x19, 0x56, 0x85, 0x52, 0x74, 0x8d, 0x23, 0x2b, 0xbe, 0x5a, 0x1b, - 0x1b, 0xed, 0x83, 0x5e, 0x7b, 0xb3, 0x91, 0xfb, 0x7e, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0xbf, 0xc8, - 0x41, 0x45, 0x9b, 0x85, 0xe7, 0x0b, 0xe3, 0x5b, 0x00, 0x68, 0xd2, 0xc4, 0x79, 0x4c, 0x79, 0xb3, - 0x2c, 0x20, 0xb4, 0xf8, 0xba, 0xb3, 0x3c, 0x47, 0xcf, 0x3f, 0x28, 0x67, 0xf9, 0x6b, 0x50, 0xa3, - 0x97, 0x14, 0xf4, 0x70, 0x5d, 0xc1, 0xac, 0x12, 0x50, 0x8a, 0x6a, 0xbc, 0x07, 0x86, 0x44, 0x78, - 0x43, 0x40, 0xde, 0xab, 0x26, 0x10, 0xde, 0x11, 0xc0, 0x0b, 0x1e, 0x81, 0x37, 0x3c, 0xe3, 0x44, - 0x41, 0x1a, 0x61, 0x45, 0xc2, 0x7a, 0xf2, 0x22, 0x9a, 0x94, 0x87, 0xda, 0x45, 0xa4, 0x82, 0x59, - 0x25, 0xa0, 0x6c, 0xe8, 0x1d, 0xc5, 0x40, 0x25, 0x64, 0xa0, 0xd5, 0x59, 0x6e, 0x48, 0x30, 0xcf, - 0xce, 0x8c, 0x3f, 0xab, 0x8c, 0x8c, 0xf1, 0x9d, 0xd9, 0x72, 0x2f, 0xf6, 0x6b, 0xb1, 0xb7, 0x80, - 0x8d, 0xc6, 0x63, 0x2b, 0xc5, 0xd3, 0x94, 0x37, 0xe7, 0x47, 0xe3, 0x71, 0x4f, 0x73, 0xc4, 0xfc, - 0x0a, 0x9c, 0x60, 0x5f, 0x02, 0x6b, 0x89, 0x0d, 0x8c, 0x5d, 0x8c, 0x5c, 0xa8, 0xb1, 0x58, 0xce, - 0xe8, 0x62, 0x39, 0x45, 0xfa, 0x65, 0x53, 0xa5, 0xdf, 0xf3, 0xe4, 0x84, 0xb1, 0x05, 0x95, 0x03, - 0xed, 0x9d, 0x96, 0x3b, 0xe2, 0x84, 0x50, 0x2f, 0xb4, 0xd0, 0xd9, 0x41, 0xce, 0x2d, 0x5f, 0x3e, - 0xcc, 0xa2, 0xf5, 0x26, 0xab, 0xf5, 0xc6, 0xf8, 0x97, 0x19, 0xba, 0x03, 0x1f, 0x75, 0x3e, 0x7e, - 0x1a, 0x46, 0xc5, 0x81, 0xe2, 0xfb, 0x82, 0x15, 0x15, 0xff, 0x91, 0x57, 0xfd, 0xb0, 0x6b, 0x96, - 0x77, 0x7c, 0x1c, 0x70, 0x75, 0xf3, 0xa5, 0x82, 0xb0, 0x7d, 0x04, 0x29, 0xe5, 0x5b, 0x68, 0xf8, - 0x0e, 0xd5, 0x1f, 0xc8, 0x1b, 0x30, 0x42, 0xf9, 0xde, 0xb5, 0x2f, 0x64, 0xab, 0x81, 0x50, 0x41, - 0xa4, 0xa3, 0x5a, 0xdd, 0xf7, 0x89, 0xbe, 0x8d, 0x7f, 0x26, 0xaf, 0x34, 0x4e, 0xcf, 0xef, 0x7d, - 0x28, 0x45, 0xb5, 0x26, 0x4f, 0x58, 0x45, 0x19, 0xe1, 0xc5, 0x39, 0x8e, 0x56, 0x79, 0xa2, 0xc7, - 0xb4, 0xb9, 0x30, 0xd8, 0xd0, 0xd1, 0x7a, 0xfd, 0x36, 0xb0, 0x63, 0xc7, 0x9f, 0x26, 0xa6, 0xcd, - 0xd6, 0x40, 0x8c, 0x46, 0x6d, 0x1c, 0xc2, 0xa2, 0x92, 0x12, 0x9a, 0x45, 0x90, 0x5c, 0xbc, 0xcc, - 0x0b, 0x84, 0x7c, 0x76, 0x46, 0xc8, 0x1b, 0x3f, 0xcb, 0x43, 0x51, 0xbd, 0x79, 0x94, 0xf6, 0x4e, - 0x4f, 0x39, 0xf9, 0x4e, 0x4f, 0x33, 0xf1, 0xa6, 0x03, 0x2e, 0xbd, 0x3c, 0xef, 0xef, 0x4e, 0x1f, - 0xd9, 0x9a, 0xd3, 0x3c, 0x71, 0x6c, 0xaf, 0x40, 0x7e, 0x6c, 0x87, 0xa7, 0xe8, 0x20, 0x23, 0xe6, - 0xc1, 0x6f, 0xe5, 0x4c, 0x2f, 0x24, 0x9d, 0xe9, 0x69, 0x6f, 0x1a, 0x91, 0x4a, 0x3a, 0xf3, 0xa6, - 0xd1, 0x0d, 0x20, 0xfd, 0x42, 0xcb, 0x87, 0x29, 0x21, 0x40, 0x9c, 0x45, 0x49, 0x75, 0xa4, 0x34, - 0xad, 0x8e, 0xbc, 0xb4, 0xaa, 0xf0, 0x1e, 0xcc, 0xd1, 0x7d, 0x60, 0x79, 0xaf, 0x49, 0x1d, 0x28, - 0x72, 0x0e, 0xd5, 0xff, 0x94, 0x04, 0x6b, 0x4a, 0x5a, 0xfd, 0x81, 0x90, 0x4a, 0xe2, 0x81, 0x10, - 0xdd, 0xc9, 0x5f, 0x4d, 0x3a, 0xf9, 0xef, 0x41, 0x23, 0x9a, 0x50, 0x74, 0x99, 0xb9, 0x81, 0xbc, - 0xd1, 0x51, 0x57, 0x70, 0x21, 0x25, 0xf7, 0x82, 0xf8, 0x40, 0xac, 0x27, 0x0e, 0x44, 0x21, 0xc3, - 0x5a, 0x61, 0xc8, 0x47, 0xe3, 0x50, 0x1e, 0x88, 0x98, 0xf3, 0xad, 0x77, 0x30, 0x79, 0xe3, 0xaf, - 0x06, 0xe5, 0xce, 0x9e, 0xb5, 0xb5, 0xd3, 0x79, 0xb2, 0xdd, 0x6b, 0x64, 0xc4, 0x67, 0xf7, 0x70, - 0x63, 0xa3, 0xdd, 0xde, 0xc4, 0x13, 0x07, 0x60, 0x6e, 0xab, 0xd5, 0x11, 0xa7, 0x4f, 0xce, 0xf8, - 0x69, 0x16, 0x2a, 0x5a, 0xf5, 0xec, 0xfd, 0x68, 0x56, 0xe8, 0x0d, 0x89, 0x5b, 0xb3, 0x5d, 0x78, - 0xa0, 0x44, 0xb1, 0x36, 0x2d, 0xd1, 0x0b, 0x4e, 0xd9, 0x2b, 0x5f, 0x70, 0x62, 0x6f, 0xc0, 0xbc, - 0x4d, 0x35, 0x44, 0xb3, 0x20, 0xdd, 0xc1, 0x12, 0x2c, 0x27, 0x01, 0xb3, 0xc0, 0xe2, 0xf3, 0x44, - 0xd0, 0xe5, 0x55, 0xe2, 0x55, 0x74, 0xa4, 0xe0, 0x64, 0x15, 0x8f, 0x6d, 0x67, 0x38, 0xf1, 0xb9, - 0x0c, 0xdf, 0x46, 0x27, 0x33, 0x41, 0x4d, 0x85, 0x36, 0x3e, 0x00, 0x88, 0xfb, 0x9c, 0x9c, 0x9c, - 0x6b, 0xc9, 0xc9, 0xc9, 0x68, 0x93, 0x93, 0x35, 0x36, 0x49, 0x8c, 0xc8, 0x89, 0x8e, 0x22, 0xd5, - 0xef, 0x80, 0xf2, 0x48, 0x59, 0x98, 0x87, 0x39, 0x1e, 0xf2, 0x50, 0xdd, 0x8d, 0x5c, 0x90, 0x98, - 0x4e, 0x84, 0x50, 0x57, 0x95, 0xe3, 0x5a, 0x62, 0x69, 0x24, 0x59, 0x72, 0x5a, 0x1a, 0x49, 0x52, - 0x33, 0xc2, 0x1b, 0x6b, 0xd0, 0xdc, 0xe4, 0xa2, 0xb6, 0xd6, 0x70, 0x38, 0xd5, 0x1d, 0xe3, 0x06, - 0x5c, 0x4f, 0xc1, 0x49, 0x27, 0xc4, 0xa7, 0xb0, 0xdc, 0xa2, 0x6b, 0x90, 0xbf, 0xaa, 0xbb, 0x18, - 0x46, 0x13, 0x56, 0xa6, 0xab, 0x94, 0x8d, 0x6d, 0xc1, 0xc2, 0x26, 0x3f, 0x9a, 0x9c, 0xec, 0xf0, - 0xb3, 0xb8, 0x21, 0x06, 0xf9, 0xe0, 0xd4, 0x3b, 0x97, 0xf3, 0x83, 0x7f, 0x8b, 0x3d, 0x3c, 0x14, - 0x34, 0x56, 0x30, 0xe6, 0x7d, 0xe5, 0x11, 0x45, 0x48, 0x77, 0xcc, 0xfb, 0xc6, 0xfb, 0xc0, 0xf4, - 0x7a, 0xe4, 0x7c, 0x09, 0x2b, 0x61, 0x72, 0x64, 0x05, 0x97, 0x41, 0xc8, 0x47, 0xea, 0x89, 0x12, - 0x08, 0x26, 0x47, 0x5d, 0x82, 0x18, 0x77, 0xa1, 0x7a, 0x60, 0x5f, 0x9a, 0xfc, 0x4b, 0x79, 0xcb, - 0x60, 0x15, 0x8a, 0x63, 0xfb, 0x52, 0x88, 0x81, 0x28, 0x38, 0x82, 0x68, 0xe3, 0x8f, 0xf2, 0x30, - 0x47, 0x94, 0xec, 0x0e, 0xbd, 0x22, 0xe8, 0xb8, 0xb8, 0x0d, 0x95, 0xa0, 0xd4, 0x40, 0x33, 0xb2, - 0x34, 0x3b, 0x2b, 0x4b, 0xa5, 0x03, 0x4d, 0xbd, 0x9e, 0xa0, 0xdc, 0xd8, 0xee, 0x64, 0xa4, 0x9e, - 0x4c, 0x60, 0x37, 0xa1, 0x1c, 0x5f, 0xe7, 0xca, 0xc7, 0xaf, 0x44, 0xd2, 0x25, 0xae, 0x64, 0xa0, - 0x31, 0xb6, 0x45, 0xa8, 0x77, 0xea, 0x88, 0x90, 0xe2, 0x52, 0x07, 0xa5, 0x1a, 0x3c, 0x45, 0x75, - 0x7f, 0x25, 0x69, 0xf0, 0xcc, 0x18, 0x36, 0xa5, 0x17, 0x1b, 0x36, 0xe4, 0x59, 0x7b, 0x8e, 0x61, - 0x03, 0x2f, 0x61, 0xd8, 0xbc, 0x44, 0x90, 0xef, 0x3a, 0x94, 0xf0, 0xdc, 0xd7, 0xa4, 0xa7, 0x38, - 0xef, 0x85, 0xf4, 0xfc, 0x50, 0x53, 0xfd, 0x29, 0xc3, 0xe0, 0x46, 0xbc, 0x4d, 0x4c, 0xfe, 0xe5, - 0xaf, 0x27, 0x78, 0xf2, 0x05, 0x14, 0x25, 0x54, 0x30, 0xb4, 0x6b, 0x8f, 0xd4, 0x03, 0x34, 0xf8, - 0xb7, 0x98, 0x36, 0x7c, 0x35, 0xe3, 0xcb, 0x89, 0xe3, 0xf3, 0x81, 0x7a, 0xe6, 0xc0, 0xc1, 0x3d, - 0x2a, 0x20, 0x62, 0x80, 0xc2, 0x0c, 0x71, 0xbd, 0x73, 0x57, 0x5e, 0x72, 0x2e, 0x3a, 0xc1, 0x53, - 0xf1, 0x69, 0x30, 0x68, 0xe0, 0x13, 0x54, 0x63, 0xcf, 0x57, 0x87, 0x93, 0xf1, 0xb3, 0x0c, 0x34, - 0xe4, 0xee, 0x8a, 0x70, 0xba, 0x15, 0x50, 0xb8, 0x2a, 0x20, 0xfe, 0xfc, 0x47, 0x0b, 0x0c, 0xa8, - 0xa1, 0xf3, 0x23, 0x3a, 0xa9, 0xc8, 0x79, 0x53, 0x11, 0xc0, 0x2d, 0x79, 0x5a, 0xbd, 0x02, 0x15, - 0x95, 0x8e, 0x39, 0x72, 0x86, 0xea, 0x41, 0x58, 0xca, 0xc7, 0xdc, 0x75, 0x86, 0xea, 0xa0, 0xf3, - 0x6d, 0x79, 0x9f, 0x2a, 0x83, 0x07, 0x9d, 0x69, 0x87, 0xdc, 0xf8, 0x4f, 0x19, 0x58, 0xd0, 0x86, - 0x22, 0xf7, 0xed, 0xc7, 0x50, 0x8d, 0xde, 0x7e, 0xe3, 0x91, 0xe6, 0xb5, 0x9a, 0x14, 0x34, 0x71, - 0xb1, 0x4a, 0x3f, 0x82, 0x04, 0xa2, 0x33, 0x03, 0xfb, 0x12, 0xfb, 0x1b, 0x4c, 0x46, 0xca, 0xb8, - 0x19, 0xd8, 0x97, 0x5b, 0x9c, 0x77, 0x27, 0x23, 0x61, 0xba, 0x9e, 0x73, 0xfe, 0x2c, 0x22, 0x20, - 0x9d, 0x0b, 0x04, 0x4c, 0x52, 0x18, 0x50, 0x1b, 0x79, 0x6e, 0x78, 0x1a, 0x91, 0x48, 0xad, 0x13, - 0x81, 0x44, 0x63, 0xfc, 0x79, 0x16, 0x16, 0xc9, 0xc5, 0x26, 0x5d, 0x9b, 0x52, 0x74, 0x35, 0x61, - 0x8e, 0xbc, 0x8d, 0x24, 0xbc, 0xb6, 0xaf, 0x99, 0xf2, 0x9b, 0xbd, 0xf7, 0x92, 0x6e, 0x41, 0x75, - 0x65, 0xeb, 0x8a, 0xe9, 0xcf, 0xcd, 0x4e, 0xff, 0xd5, 0xd3, 0x9b, 0x16, 0x71, 0x2b, 0xa4, 0x45, - 0xdc, 0x5e, 0x26, 0xce, 0x35, 0x73, 0xaf, 0xa9, 0x28, 0x69, 0xb4, 0x7b, 0x4d, 0xef, 0xc3, 0x6a, - 0x82, 0x06, 0xa5, 0xb5, 0x73, 0xec, 0x70, 0x75, 0x87, 0x7c, 0x49, 0xa3, 0xee, 0x2a, 0xdc, 0x7a, - 0x11, 0x0a, 0x41, 0xdf, 0x1b, 0x73, 0x63, 0x05, 0x96, 0x92, 0xb3, 0x2a, 0x8f, 0x89, 0x3f, 0xc8, - 0x40, 0x53, 0xe6, 0x47, 0x38, 0xee, 0xc9, 0xb6, 0x13, 0x84, 0x9e, 0x1f, 0xbd, 0x91, 0x76, 0x0b, - 0x20, 0x08, 0x6d, 0x5f, 0x5a, 0x9b, 0xa4, 0x07, 0x97, 0x11, 0x82, 0x96, 0xe4, 0x75, 0x28, 0x71, - 0x77, 0x40, 0x48, 0xe2, 0x86, 0x22, 0x77, 0x07, 0xca, 0x0e, 0x9d, 0xd1, 0xbf, 0x6b, 0x49, 0xf3, - 0x42, 0x5e, 0xb0, 0x14, 0xb3, 0xc3, 0xcf, 0xf0, 0xe0, 0xcd, 0x47, 0x17, 0x2c, 0x77, 0xed, 0x0b, - 0xcc, 0x36, 0x0c, 0x8c, 0x7f, 0x9c, 0x85, 0xf9, 0xb8, 0x7f, 0x74, 0x3b, 0x3b, 0x21, 0xbf, 0x65, - 0xaf, 0x62, 0xf9, 0x7d, 0x47, 0xb2, 0x83, 0x23, 0xf4, 0x77, 0xcd, 0xf1, 0x58, 0xa2, 0xcd, 0xd9, - 0x71, 0x99, 0x01, 0x15, 0x45, 0xe1, 0x4d, 0x42, 0xed, 0xa9, 0xa2, 0x32, 0x91, 0xec, 0x4f, 0x42, - 0x61, 0x70, 0x09, 0xcb, 0xd3, 0x71, 0xa5, 0xc9, 0x53, 0xb0, 0x47, 0x61, 0x07, 0x5f, 0x40, 0x16, - 0x60, 0x51, 0x8c, 0x16, 0x52, 0x50, 0x09, 0xfa, 0x06, 0xe9, 0xd9, 0xb4, 0x72, 0xa8, 0x63, 0xeb, - 0x4a, 0x28, 0x3d, 0x06, 0x19, 0x29, 0xa1, 0xaf, 0x40, 0x85, 0x2a, 0x8f, 0xaf, 0xb1, 0xe5, 0xcd, - 0x32, 0xb6, 0x80, 0x78, 0xe9, 0x04, 0xf2, 0x26, 0x09, 0xd3, 0x17, 0xa8, 0x29, 0x4c, 0x3f, 0xf8, - 0x07, 0x19, 0xb8, 0x9e, 0xb2, 0x6c, 0x72, 0x97, 0x6f, 0xc0, 0xc2, 0x71, 0x84, 0x54, 0xb3, 0x4b, - 0x5b, 0x7d, 0x45, 0x89, 0xd5, 0xe4, 0x9c, 0x9a, 0x8d, 0xe3, 0x24, 0x20, 0x36, 0xba, 0x68, 0x05, - 0x13, 0x37, 0x15, 0xd1, 0xe8, 0xa2, 0x65, 0x24, 0x7b, 0xe7, 0x00, 0xd6, 0xda, 0x17, 0x42, 0x62, - 0x6c, 0xe8, 0x4f, 0x78, 0x2b, 0x36, 0x4a, 0x3a, 0x98, 0x33, 0x2f, 0xe5, 0x60, 0x1e, 0xd0, 0x85, - 0xac, 0xa8, 0xae, 0x6f, 0x53, 0x09, 0x1e, 0xa0, 0xa2, 0x0c, 0x3d, 0x41, 0xae, 0x6e, 0x4b, 0xf6, - 0xa3, 0xa7, 0xc7, 0x8d, 0x00, 0xe6, 0x77, 0x27, 0xc3, 0xd0, 0x89, 0x5f, 0x23, 0x67, 0xef, 0xc9, - 0x32, 0xd8, 0x8e, 0x9a, 0xb5, 0xd4, 0x86, 0x20, 0x6a, 0x08, 0x27, 0x6b, 0x24, 0x2a, 0xb2, 0x66, - 0xdb, 0x9b, 0x1f, 0x25, 0x5b, 0x30, 0xae, 0xc3, 0x6a, 0xfc, 0x45, 0xd3, 0xa6, 0x8e, 0x9a, 0x7f, - 0x91, 0xa1, 0xd4, 0xe6, 0xe4, 0xcb, 0xe8, 0xac, 0x0d, 0x8b, 0x81, 0xe3, 0x9e, 0x0c, 0xb9, 0x5e, - 0x7d, 0x20, 0x27, 0x61, 0x39, 0xd9, 0x37, 0xf9, 0x7a, 0xba, 0xb9, 0x40, 0x25, 0xe2, 0xda, 0x02, - 0xb6, 0x7e, 0x55, 0x27, 0x63, 0xb6, 0x98, 0x9a, 0x8d, 0xd9, 0xce, 0x77, 0xa0, 0x9e, 0x6c, 0x88, - 0x7d, 0x28, 0x2f, 0x23, 0xc6, 0xbd, 0xca, 0x4d, 0xdd, 0x2b, 0x8b, 0x19, 0xa2, 0x12, 0xcf, 0x7d, - 0x60, 0xfc, 0xc3, 0x0c, 0x34, 0x4d, 0x2e, 0x38, 0x57, 0xeb, 0xa5, 0xe2, 0x99, 0x8f, 0x67, 0x6a, - 0xbd, 0x7a, 0xac, 0xea, 0x8e, 0xa3, 0xea, 0xd1, 0xdb, 0x57, 0x2e, 0xc6, 0xf6, 0xb5, 0x99, 0x11, - 0xad, 0x97, 0x60, 0x8e, 0x48, 0x8c, 0x55, 0x58, 0x96, 0xfd, 0x51, 0x7d, 0x89, 0xa3, 0x87, 0x89, - 0x16, 0x13, 0xd1, 0xc3, 0x35, 0x68, 0xd2, 0x53, 0x77, 0xfa, 0x20, 0x64, 0xc1, 0x4d, 0x60, 0xbb, - 0x76, 0xdf, 0xf6, 0x3d, 0xcf, 0x3d, 0xe0, 0xbe, 0x4c, 0x14, 0x45, 0x0d, 0x13, 0x83, 0x6b, 0x4a, - 0x15, 0xa6, 0x2f, 0xf5, 0x40, 0x9b, 0xe7, 0xaa, 0xbc, 0x18, 0xfa, 0x32, 0x4c, 0x58, 0x5c, 0xb7, - 0x9f, 0x71, 0x55, 0x93, 0x9a, 0xa2, 0x4f, 0xa0, 0x32, 0x8e, 0x2a, 0x55, 0xf3, 0xae, 0x6e, 0x2c, - 0xcf, 0x36, 0x6b, 0xea, 0xd4, 0xc6, 0x63, 0x58, 0x4a, 0xd6, 0x29, 0x45, 0xc7, 0x1a, 0x94, 0x46, - 0x12, 0x26, 0x7b, 0x17, 0x7d, 0x1b, 0x3f, 0x29, 0x41, 0x51, 0xda, 0x73, 0xec, 0x01, 0xe4, 0xfb, - 0x2a, 0x37, 0x29, 0x7e, 0x08, 0x43, 0x62, 0xd5, 0xff, 0x1b, 0x98, 0xa1, 0x24, 0xe8, 0xd8, 0x27, - 0x50, 0x4f, 0x46, 0x45, 0xa7, 0xae, 0x43, 0x26, 0xc3, 0x99, 0xb5, 0xfe, 0x54, 0xfc, 0xab, 0x1c, - 0x1f, 0x8e, 0xa4, 0x33, 0x94, 0x4e, 0xb5, 0xd3, 0xd3, 0x73, 0x85, 0xbe, 0x1d, 0x9c, 0xda, 0xd6, - 0xe3, 0xf7, 0x3f, 0x90, 0xf7, 0x21, 0x2b, 0x08, 0xec, 0x9e, 0xda, 0x8f, 0xdf, 0xff, 0x60, 0x5a, - 0x93, 0xa6, 0x2b, 0x71, 0xba, 0x26, 0xbd, 0x04, 0x05, 0x7a, 0x89, 0x8c, 0x92, 0x4c, 0xe8, 0x83, - 0x3d, 0x82, 0x25, 0x69, 0xb6, 0x5a, 0x32, 0x1d, 0x98, 0xa4, 0x60, 0x89, 0xee, 0xe0, 0x48, 0x5c, - 0x17, 0x51, 0xe4, 0x1b, 0x5a, 0x81, 0xb9, 0xd3, 0xf8, 0x59, 0xb9, 0x9a, 0x29, 0xbf, 0x8c, 0x3f, - 0x2f, 0x40, 0x45, 0x9b, 0x14, 0x56, 0x85, 0x92, 0xd9, 0xee, 0xb6, 0xcd, 0xcf, 0xda, 0x9b, 0x8d, - 0x6b, 0xec, 0x1e, 0xbc, 0xde, 0xd9, 0xdb, 0xd8, 0x37, 0xcd, 0xf6, 0x46, 0xcf, 0xda, 0x37, 0x2d, - 0xf5, 0x46, 0xca, 0x41, 0xeb, 0x8b, 0xdd, 0xf6, 0x5e, 0xcf, 0xda, 0x6c, 0xf7, 0x5a, 0x9d, 0x9d, - 0x6e, 0x23, 0xc3, 0x6e, 0x42, 0x33, 0xa6, 0x54, 0xe8, 0xd6, 0xee, 0xfe, 0xe1, 0x5e, 0xaf, 0x91, - 0x65, 0xb7, 0xe1, 0xc6, 0x56, 0x67, 0xaf, 0xb5, 0x63, 0xc5, 0x34, 0x1b, 0x3b, 0xbd, 0xcf, 0xac, - 0xf6, 0x6f, 0x1f, 0x74, 0xcc, 0x2f, 0x1a, 0xb9, 0x34, 0x02, 0x61, 0x8c, 0xab, 0x1a, 0xf2, 0xec, - 0x3a, 0x2c, 0x13, 0x01, 0x15, 0xb1, 0x7a, 0xfb, 0xfb, 0x56, 0x77, 0x7f, 0x7f, 0xaf, 0x51, 0x60, - 0x0b, 0x50, 0xeb, 0xec, 0x7d, 0xd6, 0xda, 0xe9, 0x6c, 0x5a, 0x66, 0xbb, 0xb5, 0xb3, 0xdb, 0x98, - 0x63, 0x8b, 0x30, 0x3f, 0x4d, 0x57, 0x14, 0x55, 0x28, 0xba, 0xfd, 0xbd, 0xce, 0xfe, 0x9e, 0xf5, - 0x59, 0xdb, 0xec, 0x76, 0xf6, 0xf7, 0x1a, 0x25, 0xb6, 0x02, 0x2c, 0x89, 0xda, 0xde, 0x6d, 0x6d, - 0x34, 0xca, 0x6c, 0x19, 0x16, 0x92, 0xf0, 0xa7, 0xed, 0x2f, 0x1a, 0xc0, 0x9a, 0xb0, 0x44, 0x1d, - 0xb3, 0xd6, 0xdb, 0x3b, 0xfb, 0x9f, 0x5b, 0xbb, 0x9d, 0xbd, 0xce, 0xee, 0xe1, 0x6e, 0xa3, 0x82, - 0x8f, 0x30, 0xb5, 0xdb, 0x56, 0x67, 0xaf, 0x7b, 0xb8, 0xb5, 0xd5, 0xd9, 0xe8, 0xb4, 0xf7, 0x7a, - 0x8d, 0x2a, 0xb5, 0x9c, 0x36, 0xf0, 0x9a, 0x28, 0x20, 0xef, 0x0c, 0x58, 0x9b, 0x9d, 0x6e, 0x6b, - 0x7d, 0xa7, 0xbd, 0xd9, 0xa8, 0xb3, 0x5b, 0x70, 0xbd, 0xd7, 0xde, 0x3d, 0xd8, 0x37, 0x5b, 0xe6, - 0x17, 0xea, 0x4e, 0x81, 0xb5, 0xd5, 0xea, 0xec, 0x1c, 0x9a, 0xed, 0xc6, 0x3c, 0x7b, 0x15, 0x6e, - 0x99, 0xed, 0x4f, 0x0f, 0x3b, 0x66, 0x7b, 0xd3, 0xda, 0xdb, 0xdf, 0x6c, 0x5b, 0x5b, 0xed, 0x56, - 0xef, 0xd0, 0x6c, 0x5b, 0xbb, 0x9d, 0x6e, 0xb7, 0xb3, 0xf7, 0xa4, 0xd1, 0x60, 0xaf, 0xc3, 0x9d, - 0x88, 0x24, 0xaa, 0x60, 0x8a, 0x6a, 0x41, 0x8c, 0x4f, 0x2d, 0xe9, 0x5e, 0xfb, 0xb7, 0x7b, 0xd6, - 0x41, 0xbb, 0x6d, 0x36, 0x18, 0x5b, 0x83, 0x95, 0xb8, 0x79, 0x6a, 0x40, 0xb6, 0xbd, 0x28, 0x70, - 0x07, 0x6d, 0x73, 0xb7, 0xb5, 0x27, 0x16, 0x38, 0x81, 0x5b, 0x12, 0xdd, 0x8e, 0x71, 0xd3, 0xdd, - 0x5e, 0x66, 0x0c, 0xea, 0xda, 0xaa, 0x6c, 0xb5, 0xcc, 0xc6, 0x0a, 0x9b, 0x87, 0xca, 0xee, 0xc1, - 0x81, 0xd5, 0xeb, 0xec, 0xb6, 0xf7, 0x0f, 0x7b, 0x8d, 0x55, 0xb6, 0x0c, 0x8d, 0xce, 0x5e, 0xaf, - 0x6d, 0x8a, 0xb5, 0x56, 0x45, 0xff, 0x57, 0x91, 0x2d, 0xc1, 0xbc, 0xea, 0xa9, 0x82, 0xfe, 0xa2, - 0xc8, 0x56, 0x81, 0x1d, 0xee, 0x99, 0xed, 0xd6, 0xa6, 0x98, 0xb8, 0x08, 0xf1, 0xbf, 0x8b, 0x32, - 0x42, 0xf2, 0xb3, 0x5c, 0x74, 0x58, 0xc7, 0x29, 0x07, 0xc9, 0x47, 0x46, 0xab, 0xda, 0xe3, 0xa0, - 0x2f, 0x7a, 0xfe, 0x5b, 0x33, 0xad, 0x72, 0x33, 0xa6, 0xd5, 0x8c, 0xed, 0x5e, 0xd3, 0x75, 0xbf, - 0xd7, 0xa0, 0x36, 0xa2, 0x07, 0x47, 0xe5, 0xc3, 0x82, 0x20, 0xf3, 0x6f, 0x08, 0x48, 0xaf, 0x0a, - 0xce, 0xbc, 0x7f, 0x5d, 0x98, 0x7d, 0xff, 0x3a, 0x4d, 0xbf, 0x9f, 0x4b, 0xd3, 0xef, 0xef, 0xc3, - 0x02, 0x89, 0x26, 0xc7, 0x75, 0x46, 0xca, 0x6a, 0x26, 0x2d, 0x70, 0x1e, 0x45, 0x14, 0xc1, 0x95, - 0x39, 0xa1, 0x4c, 0x0e, 0x29, 0x42, 0x8a, 0xd2, 0xda, 0x48, 0x58, 0x1a, 0x24, 0x39, 0x22, 0x4b, - 0x23, 0x6a, 0xc1, 0xbe, 0x88, 0x5b, 0xa8, 0x68, 0x2d, 0x10, 0x1c, 0x5b, 0xb8, 0x0f, 0x0b, 0xfc, - 0x22, 0xf4, 0x6d, 0xcb, 0x1b, 0xdb, 0x5f, 0x4e, 0x30, 0x84, 0x6b, 0xa3, 0x0d, 0x5f, 0x35, 0xe7, - 0x11, 0xb1, 0x8f, 0xf0, 0x4d, 0x3b, 0xb4, 0xef, 0x7f, 0x0d, 0x15, 0xed, 0x31, 0x5a, 0xb6, 0x0a, - 0x8b, 0x9f, 0x77, 0x7a, 0x7b, 0xed, 0x6e, 0xd7, 0x3a, 0x38, 0x5c, 0x7f, 0xda, 0xfe, 0xc2, 0xda, - 0x6e, 0x75, 0xb7, 0x1b, 0xd7, 0xc4, 0xa6, 0xdd, 0x6b, 0x77, 0x7b, 0xed, 0xcd, 0x04, 0x3c, 0xc3, - 0x5e, 0x81, 0xb5, 0xc3, 0xbd, 0xc3, 0x6e, 0x7b, 0xd3, 0x4a, 0x2b, 0x97, 0x15, 0x5c, 0x2a, 0xf1, - 0x29, 0xc5, 0x73, 0xf7, 0x3f, 0x81, 0xc6, 0x74, 0x34, 0x29, 0x11, 0x7e, 0x7b, 0x5e, 0x9c, 0xee, - 0xfe, 0xbf, 0xc9, 0x01, 0xc4, 0xe9, 0xfe, 0x42, 0x50, 0x6c, 0xb6, 0x7a, 0xad, 0x9d, 0x7d, 0xd1, - 0x09, 0x73, 0xbf, 0x27, 0xf6, 0xbf, 0xd9, 0xfe, 0xb4, 0x71, 0x2d, 0x15, 0xb3, 0x7f, 0xd0, 0x6b, - 0x64, 0xc4, 0x78, 0x3b, 0x7b, 0x9d, 0x5e, 0xa7, 0xb5, 0x63, 0x99, 0xfb, 0x87, 0x9d, 0xbd, 0x27, - 0xf4, 0xdc, 0x14, 0xca, 0xc8, 0xc3, 0x83, 0x2d, 0x73, 0x7f, 0xaf, 0x67, 0x75, 0xb7, 0x0f, 0x7b, - 0x9b, 0xf8, 0x58, 0xd5, 0x86, 0xd9, 0x39, 0xa0, 0x3a, 0xf3, 0xcf, 0x23, 0x10, 0x55, 0x17, 0xc4, - 0x8c, 0x3d, 0xd9, 0xef, 0x76, 0x3b, 0x07, 0xd6, 0xa7, 0x87, 0x6d, 0xb3, 0xd3, 0xee, 0x62, 0xc1, - 0xb9, 0x14, 0xb8, 0xa0, 0x2f, 0x0a, 0xc9, 0xda, 0xdb, 0xf9, 0x4c, 0x8a, 0x3e, 0x41, 0x5a, 0x4a, - 0x82, 0x04, 0x55, 0x59, 0x48, 0x04, 0x21, 0x3b, 0x52, 0x6a, 0x86, 0x2b, 0x70, 0xa2, 0x5c, 0x45, - 0x48, 0xc5, 0x6e, 0xaf, 0xd5, 0xeb, 0x6c, 0x58, 0xf2, 0x85, 0x3b, 0xb1, 0x08, 0xa2, 0x58, 0x35, - 0x1d, 0x25, 0x4a, 0xa1, 0xc0, 0x8c, 0x8e, 0x97, 0xcd, 0x4d, 0x13, 0x0b, 0xd4, 0x67, 0xa0, 0x82, - 0x76, 0x5e, 0x2c, 0x94, 0x10, 0x2e, 0x82, 0xa4, 0xa1, 0x3e, 0x04, 0x66, 0xe1, 0xf1, 0xef, 0xe7, - 0xa0, 0x4e, 0x57, 0xaf, 0xe8, 0x97, 0x7c, 0xb8, 0xcf, 0x76, 0xa1, 0x28, 0x7f, 0x12, 0x8a, 0x2d, - 0x47, 0x8f, 0x0e, 0xe9, 0x3f, 0x42, 0xb5, 0xb6, 0x32, 0x0d, 0x96, 0xca, 0xd4, 0xe2, 0xdf, 0xfc, - 0xb3, 0xbf, 0xfa, 0x47, 0xd9, 0x1a, 0xab, 0x3c, 0x3c, 0x7b, 0xf7, 0xe1, 0x09, 0x77, 0x03, 0x51, - 0xc7, 0x5f, 0x03, 0x88, 0x7f, 0xe8, 0x88, 0x35, 0xa3, 0x10, 0xd2, 0xd4, 0xaf, 0x40, 0xad, 0x5d, - 0x4f, 0xc1, 0xc8, 0x7a, 0xaf, 0x63, 0xbd, 0x8b, 0x46, 0x5d, 0xd4, 0xeb, 0xb8, 0x4e, 0x48, 0x3f, - 0x7a, 0xf4, 0x71, 0xe6, 0x3e, 0x1b, 0x40, 0x55, 0xff, 0x09, 0x22, 0xa6, 0xf4, 0x9c, 0x94, 0x1f, - 0x51, 0x5a, 0xbb, 0x91, 0x8a, 0x53, 0x1a, 0x24, 0xb6, 0xb1, 0x6c, 0x34, 0x44, 0x1b, 0x13, 0xa4, - 0x88, 0x5b, 0x19, 0x92, 0x4e, 0x1d, 0xff, 0xd2, 0x10, 0xbb, 0xa9, 0x69, 0x45, 0x33, 0xbf, 0x73, - 0xb4, 0x76, 0xeb, 0x0a, 0xac, 0x6c, 0xeb, 0x16, 0xb6, 0xb5, 0x6a, 0x30, 0xd1, 0x56, 0x1f, 0x69, - 0xd4, 0xef, 0x1c, 0x7d, 0x9c, 0xb9, 0xff, 0xf8, 0x2f, 0xef, 0x41, 0x39, 0x4a, 0xc5, 0x64, 0xbf, - 0x0b, 0xb5, 0xc4, 0xdd, 0x38, 0xa6, 0x86, 0x91, 0x76, 0x95, 0x6e, 0xed, 0x66, 0x3a, 0x52, 0x36, - 0xfc, 0x0a, 0x36, 0xdc, 0x64, 0x2b, 0xa2, 0x61, 0x79, 0xf7, 0xec, 0x21, 0xde, 0x20, 0xa5, 0x27, - 0x9c, 0x9e, 0x69, 0xb6, 0x03, 0x35, 0x76, 0x73, 0x5a, 0x9f, 0x4f, 0xb4, 0x76, 0xeb, 0x0a, 0xac, - 0x6c, 0xee, 0x26, 0x36, 0xb7, 0xc2, 0x96, 0xf4, 0xe6, 0x54, 0xe2, 0x24, 0xe3, 0xf8, 0x6c, 0x9a, - 0xfe, 0x43, 0x3c, 0xec, 0x56, 0xfc, 0xc8, 0x55, 0xca, 0x0f, 0xf4, 0x44, 0x2c, 0x32, 0xfb, 0x2b, - 0x3d, 0x46, 0x13, 0x9b, 0x62, 0x0c, 0x97, 0x4f, 0xff, 0x1d, 0x1e, 0x76, 0x04, 0x15, 0xed, 0xed, - 0x7a, 0x76, 0xfd, 0xca, 0x77, 0xf6, 0xd7, 0xd6, 0xd2, 0x50, 0x69, 0x43, 0xd1, 0xeb, 0x7f, 0x78, - 0xcc, 0x39, 0xfb, 0x21, 0x94, 0xa3, 0x17, 0xd1, 0xd9, 0xaa, 0xf6, 0x42, 0xbd, 0xfe, 0x82, 0xfb, - 0x5a, 0x73, 0x16, 0x91, 0xc6, 0x7c, 0x7a, 0xed, 0x82, 0xf9, 0x3e, 0x87, 0x8a, 0xf6, 0xea, 0x79, - 0x34, 0x80, 0xd9, 0x97, 0xd5, 0xa3, 0x01, 0xa4, 0x3c, 0x92, 0x6e, 0x2c, 0x60, 0x13, 0x15, 0x56, - 0x46, 0xfe, 0x0e, 0x2f, 0xbc, 0x80, 0xed, 0xc0, 0xb2, 0xb4, 0x93, 0x8e, 0xf8, 0x37, 0x59, 0x86, - 0x94, 0xdf, 0x3e, 0x7a, 0x94, 0x61, 0x9f, 0x40, 0x49, 0x3d, 0x6e, 0xcf, 0x56, 0xd2, 0x1f, 0xe9, - 0x5f, 0x5b, 0x9d, 0x81, 0x4b, 0xa3, 0xe6, 0x0b, 0x80, 0xf8, 0x89, 0xf5, 0x48, 0x48, 0xcc, 0x3c, - 0xd9, 0x1e, 0x71, 0xc0, 0xec, 0x7b, 0xec, 0xc6, 0x0a, 0x0e, 0xb0, 0xc1, 0x50, 0x48, 0xb8, 0xfc, - 0x5c, 0xbd, 0x1f, 0xf9, 0x23, 0xa8, 0x68, 0xaf, 0xac, 0x47, 0xd3, 0x37, 0xfb, 0x42, 0x7b, 0x34, - 0x7d, 0x29, 0x8f, 0xb2, 0x1b, 0x6b, 0x58, 0xfb, 0x92, 0x31, 0x2f, 0x6a, 0x17, 0x8a, 0x92, 0x54, - 0x58, 0xc4, 0x02, 0x9d, 0x42, 0x2d, 0xf1, 0x94, 0x7a, 0xb4, 0x43, 0xd3, 0x1e, 0x6a, 0x8f, 0x76, - 0x68, 0xea, 0xeb, 0xeb, 0x8a, 0xcf, 0x8c, 0x05, 0xd1, 0xce, 0x19, 0x92, 0x68, 0x2d, 0xfd, 0x00, - 0x2a, 0xda, 0xb3, 0xe8, 0xd1, 0x58, 0x66, 0x5f, 0x60, 0x8f, 0xc6, 0x92, 0xf6, 0x8a, 0xfa, 0x12, - 0xb6, 0x51, 0x37, 0x90, 0x15, 0xf0, 0x75, 0x3e, 0x51, 0xf7, 0xef, 0x42, 0x3d, 0xf9, 0x52, 0x7a, - 0xb4, 0xf7, 0x53, 0x9f, 0x5c, 0x8f, 0xf6, 0xfe, 0x15, 0xcf, 0xab, 0x4b, 0x96, 0xbe, 0xbf, 0x18, - 0x35, 0xf2, 0xf0, 0x2b, 0x79, 0xa9, 0xe4, 0x6b, 0xf6, 0xa9, 0x10, 0x70, 0xf2, 0x71, 0x48, 0xb6, - 0xaa, 0x71, 0xad, 0xfe, 0x84, 0x64, 0xb4, 0x5f, 0x66, 0xde, 0x91, 0x4c, 0x32, 0x33, 0x56, 0xce, - 0x9e, 0xc0, 0x62, 0xc4, 0xcc, 0xd1, 0x6b, 0x8f, 0x41, 0x34, 0x86, 0xd4, 0x37, 0x25, 0xd7, 0x1a, - 0xd3, 0xd8, 0x47, 0x19, 0x3a, 0xfe, 0xf0, 0x8d, 0x3d, 0xed, 0xf8, 0xd3, 0x1f, 0x7c, 0xd4, 0x8e, - 0xbf, 0xc4, 0x53, 0x7c, 0xd3, 0xc7, 0x5f, 0xe8, 0x88, 0x3a, 0x5c, 0x98, 0x9f, 0x7e, 0x7b, 0xf1, - 0xd6, 0x55, 0x2f, 0x0f, 0x50, 0xf5, 0xaf, 0x3c, 0xff, 0x61, 0x82, 0xa4, 0x28, 0x52, 0xd2, 0xf4, - 0xa1, 0x4c, 0x1d, 0x61, 0xbf, 0x03, 0x55, 0xfd, 0xa9, 0x67, 0xa6, 0xcb, 0x84, 0xe9, 0x96, 0x6e, - 0xa4, 0xe2, 0x92, 0x5c, 0xc2, 0xaa, 0x7a, 0x33, 0xec, 0x33, 0x58, 0x89, 0xa6, 0x59, 0xbf, 0x75, - 0x1e, 0xb0, 0xdb, 0x29, 0x77, 0xd1, 0x13, 0x93, 0x7d, 0xfd, 0xca, 0xcb, 0xea, 0x8f, 0x32, 0x82, - 0xfb, 0x92, 0x6f, 0xce, 0xc6, 0x27, 0x4f, 0xda, 0x53, 0xbb, 0xf1, 0xc9, 0x93, 0xfa, 0x50, 0xad, - 0xe2, 0x3e, 0xb6, 0x98, 0x98, 0x23, 0x4a, 0xaa, 0x65, 0x3f, 0x80, 0x79, 0xed, 0x4a, 0x7d, 0xf7, - 0xd2, 0xed, 0x47, 0x3b, 0x69, 0xf6, 0x41, 0xb7, 0xb5, 0x34, 0xcf, 0xa2, 0xb1, 0x8a, 0xf5, 0x2f, - 0x18, 0x89, 0xc9, 0x11, 0xbb, 0x68, 0x03, 0x2a, 0xfa, 0x75, 0xfd, 0xe7, 0xd4, 0xbb, 0xaa, 0xa1, - 0xf4, 0xb7, 0xc3, 0x1e, 0x65, 0xd8, 0x0e, 0x34, 0xa6, 0x9f, 0x3a, 0x8a, 0x64, 0x4a, 0xda, 0xf3, - 0x4c, 0x6b, 0x53, 0xc8, 0xc4, 0x03, 0x49, 0xec, 0x80, 0xae, 0x65, 0x44, 0x3f, 0x14, 0xe4, 0xf9, - 0xd3, 0xa7, 0x7a, 0xf2, 0x07, 0x84, 0xa2, 0xda, 0xd2, 0x7e, 0x3a, 0xea, 0x5e, 0xe6, 0x51, 0x86, - 0xfd, 0x34, 0x03, 0xd5, 0xc4, 0xf3, 0x22, 0x89, 0xc4, 0xf7, 0xa9, 0x71, 0x36, 0x75, 0x9c, 0x3e, - 0x50, 0xc3, 0xc4, 0x49, 0xdc, 0xb9, 0xff, 0xfd, 0xc4, 0x22, 0x7d, 0x95, 0x08, 0xcc, 0x3d, 0x98, - 0xfe, 0x25, 0xa1, 0xaf, 0xa7, 0x09, 0xf4, 0x77, 0xfa, 0xbe, 0x7e, 0x94, 0x61, 0xff, 0x2e, 0x03, - 0xf5, 0x64, 0xc4, 0x3d, 0x1a, 0x6e, 0x6a, 0x6c, 0x3f, 0x62, 0xa5, 0x2b, 0xc2, 0xf4, 0x3f, 0xc0, - 0x5e, 0xf6, 0xee, 0x9b, 0x89, 0x5e, 0xca, 0xd7, 0x92, 0x7f, 0xb9, 0xde, 0xb2, 0x8f, 0xe9, 0x87, - 0xfb, 0x54, 0x22, 0x12, 0x9b, 0xfd, 0xa1, 0xb7, 0x88, 0xfd, 0xf4, 0x9f, 0x45, 0xc3, 0x45, 0xf8, - 0x11, 0xfd, 0x62, 0x8e, 0xca, 0x6b, 0x11, 0x5c, 0xfc, 0xb2, 0xe5, 0x8d, 0xd7, 0x71, 0x4c, 0xaf, - 0x18, 0xd7, 0x13, 0x63, 0x9a, 0x56, 0x3c, 0x5a, 0xd4, 0x3b, 0xf9, 0xab, 0x66, 0xf1, 0xc9, 0x39, - 0xf3, 0x4b, 0x67, 0x57, 0x77, 0x72, 0x44, 0x9d, 0x94, 0xe4, 0x89, 0xad, 0xf6, 0x92, 0xd5, 0x18, - 0xf7, 0xb1, 0xaf, 0xaf, 0x1b, 0xb7, 0xaf, 0xec, 0xeb, 0x43, 0x8c, 0x9e, 0x8b, 0x1e, 0x1f, 0x00, - 0xc4, 0x89, 0x82, 0x6c, 0x2a, 0x5d, 0x2d, 0x12, 0x40, 0xb3, 0xb9, 0x84, 0xc9, 0xfd, 0xac, 0xb2, - 0xda, 0x44, 0x8d, 0x3f, 0x24, 0x71, 0x1a, 0x25, 0xd2, 0xe9, 0xda, 0x57, 0x32, 0xa7, 0x2f, 0xa1, - 0x7d, 0x4d, 0xd7, 0x9f, 0x10, 0xa6, 0x51, 0xd6, 0xdc, 0x21, 0xd4, 0x76, 0x3c, 0xef, 0xd9, 0x64, - 0x1c, 0x25, 0xa7, 0x27, 0x53, 0x5a, 0xb6, 0xed, 0xe0, 0x74, 0x6d, 0x6a, 0x14, 0xc6, 0x1d, 0xac, - 0x6a, 0x8d, 0x35, 0xb5, 0xaa, 0x1e, 0x7e, 0x15, 0x67, 0x27, 0x7e, 0xcd, 0x6c, 0x58, 0x88, 0x64, - 0x74, 0x9c, 0x01, 0x98, 0xac, 0x26, 0x21, 0x99, 0xa7, 0x9b, 0x48, 0x98, 0x09, 0xaa, 0xb7, 0x0f, - 0x03, 0x55, 0xe7, 0xa3, 0x0c, 0x3b, 0x80, 0xea, 0x26, 0xef, 0xe3, 0x35, 0x7b, 0x4c, 0x0c, 0x59, - 0x4c, 0x24, 0x19, 0x50, 0x46, 0xc9, 0x5a, 0x2d, 0x01, 0x4c, 0x9e, 0x5b, 0x63, 0xfb, 0xd2, 0xe7, - 0x5f, 0x3e, 0xfc, 0x4a, 0xa6, 0x9c, 0x7c, 0xad, 0xce, 0x2d, 0x95, 0x92, 0x93, 0x38, 0xb7, 0xa6, - 0x72, 0x78, 0x12, 0xe7, 0xd6, 0x4c, 0x0e, 0x4f, 0x62, 0xaa, 0x55, 0x4a, 0x10, 0x1b, 0xc2, 0xc2, - 0x4c, 0xda, 0x4f, 0x74, 0x64, 0x5d, 0x95, 0x2c, 0xb4, 0x76, 0xe7, 0x6a, 0x82, 0x64, 0x6b, 0xf7, - 0x93, 0xad, 0x75, 0xa1, 0x46, 0x4f, 0x07, 0x1e, 0x71, 0xba, 0x70, 0x37, 0xf5, 0x5a, 0x8d, 0x7e, - 0x9b, 0x6f, 0xfa, 0x80, 0x41, 0x5c, 0x52, 0xc3, 0xc1, 0x9b, 0x6e, 0xec, 0x87, 0x50, 0x79, 0xc2, - 0x43, 0x75, 0xc3, 0x2e, 0xd2, 0xb1, 0xa7, 0xae, 0xdc, 0xad, 0xa5, 0x5c, 0xd0, 0x4b, 0xf2, 0x0c, - 0xd6, 0xf6, 0x90, 0x0f, 0x4e, 0x38, 0x09, 0x27, 0xcb, 0x19, 0x7c, 0xcd, 0x7e, 0x1b, 0x2b, 0x8f, - 0x2e, 0x36, 0xaf, 0x68, 0x57, 0xa8, 0xf4, 0xca, 0xe7, 0xa7, 0xe0, 0x69, 0x35, 0xbb, 0xde, 0x80, - 0x6b, 0xba, 0x9e, 0x0b, 0x15, 0xed, 0x01, 0x84, 0x68, 0x03, 0xcd, 0x3e, 0x78, 0x11, 0x6d, 0xa0, - 0x94, 0xf7, 0x12, 0x8c, 0x7b, 0xd8, 0x8e, 0xc1, 0xee, 0xc4, 0xed, 0xd0, 0x1b, 0x09, 0x71, 0x4b, - 0x0f, 0xbf, 0xb2, 0x47, 0xe1, 0xd7, 0xec, 0x73, 0x7c, 0xa0, 0x5b, 0xbf, 0x41, 0x18, 0x1b, 0x0d, - 0xd3, 0x97, 0x0d, 0xa3, 0xc9, 0xd2, 0x50, 0x49, 0x43, 0x82, 0x9a, 0x42, 0x4d, 0xee, 0x7d, 0x80, - 0x6e, 0xe8, 0x8d, 0x37, 0x6d, 0x3e, 0xf2, 0xdc, 0x58, 0xd6, 0xc6, 0x77, 0xda, 0x62, 0xf9, 0xa5, - 0x5d, 0x6c, 0x63, 0x9f, 0x6b, 0x56, 0x56, 0xe2, 0x12, 0xa6, 0x62, 0xae, 0x2b, 0xaf, 0xbd, 0x45, - 0x13, 0x92, 0x72, 0xf5, 0xed, 0x51, 0x86, 0xb5, 0x00, 0xe2, 0xbc, 0xaf, 0xc8, 0x66, 0x9a, 0x49, - 0x29, 0x8b, 0xc4, 0x5e, 0x4a, 0x92, 0xd8, 0x01, 0x94, 0xe3, 0x84, 0x99, 0xd5, 0xf8, 0x3d, 0x97, - 0x44, 0x7a, 0x4d, 0x74, 0x82, 0xcf, 0x24, 0xab, 0x18, 0x0d, 0x9c, 0x2a, 0x60, 0x25, 0x31, 0x55, - 0xc7, 0x9c, 0x07, 0xcc, 0x81, 0x45, 0xea, 0x60, 0xa4, 0x2e, 0xe1, 0x5d, 0xac, 0xe8, 0x1d, 0xf6, - 0xd9, 0xbc, 0x91, 0x68, 0x37, 0xa7, 0x66, 0x3f, 0x24, 0x5c, 0x3f, 0x82, 0x5b, 0xe9, 0x1e, 0x98, - 0x10, 0xcd, 0x23, 0x58, 0x98, 0x09, 0xb0, 0x47, 0x5b, 0xfa, 0xaa, 0x8c, 0x89, 0x68, 0x4b, 0x5f, - 0x19, 0x9b, 0x37, 0x96, 0xb1, 0xc9, 0x79, 0x03, 0xd0, 0xd4, 0x3b, 0x77, 0xc2, 0xfe, 0xa9, 0x68, - 0xee, 0x5f, 0x67, 0x60, 0x31, 0x25, 0x84, 0xce, 0x5e, 0x55, 0x5e, 0x83, 0x2b, 0xc3, 0xeb, 0x6b, - 0xa9, 0xa1, 0x56, 0xa3, 0x8b, 0xed, 0xec, 0xb2, 0xa7, 0x89, 0x83, 0x8d, 0x22, 0x9d, 0x72, 0x67, - 0x3e, 0x57, 0xa9, 0x48, 0xd5, 0x28, 0xbe, 0x84, 0x55, 0xea, 0x48, 0x6b, 0x38, 0x9c, 0x0a, 0x03, - 0xbf, 0x32, 0xf3, 0xc3, 0xde, 0x89, 0xd0, 0xf6, 0xda, 0xd5, 0x3f, 0xfc, 0x7d, 0x85, 0x3a, 0x4d, - 0x5d, 0x65, 0x13, 0x68, 0x4c, 0x87, 0x57, 0xd9, 0xd5, 0x75, 0xad, 0xdd, 0x4e, 0xd8, 0xbf, 0x29, - 0x21, 0xd9, 0xef, 0x60, 0x63, 0xb7, 0x8d, 0xb5, 0xb4, 0x79, 0x21, 0x93, 0x58, 0xac, 0xc7, 0xdf, - 0x88, 0x62, 0xc1, 0x53, 0xe3, 0x54, 0x0d, 0x5c, 0x15, 0xb9, 0x8e, 0x2c, 0xf0, 0xf4, 0x50, 0xf2, - 0x1b, 0xd8, 0xfc, 0x1d, 0xe3, 0x46, 0x5a, 0xf3, 0x3e, 0x15, 0x21, 0x5b, 0x7c, 0x75, 0x7a, 0x5f, - 0xab, 0x1e, 0xdc, 0x49, 0x5b, 0xef, 0x2b, 0x6d, 0xa1, 0xa9, 0xb9, 0xbe, 0x86, 0xba, 0x5d, 0x55, - 0x8f, 0xfd, 0x46, 0xdb, 0x27, 0x25, 0xc8, 0x1c, 0x6d, 0x9f, 0xb4, 0x60, 0x71, 0x52, 0xaf, 0x51, - 0x61, 0xe2, 0x8f, 0x33, 0xf7, 0xd7, 0xef, 0xfe, 0xe0, 0x3b, 0x27, 0x4e, 0x78, 0x3a, 0x39, 0x7a, - 0xd0, 0xf7, 0x46, 0x0f, 0x87, 0xca, 0xdb, 0x28, 0x2f, 0x2c, 0x3f, 0x1c, 0xba, 0x83, 0x87, 0x58, - 0xed, 0xd1, 0xdc, 0xd8, 0xf7, 0x42, 0xef, 0xbb, 0xff, 0x37, 0x00, 0x00, 0xff, 0xff, 0x26, 0x2b, - 0x1e, 0xcb, 0xbb, 0x80, 0x00, 0x00, + // 11167 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x1c, 0x49, + 0x76, 0x18, 0xcc, 0xba, 0x75, 0x55, 0x9d, 0xba, 0x76, 0xf4, 0xad, 0xd8, 0x24, 0x87, 0x9c, 0x9c, + 0xd9, 0x21, 0x97, 0xb3, 0x4b, 0x72, 0xb8, 0x3b, 0xb3, 0xab, 0x99, 0xef, 0x5b, 0x6d, 0x75, 0x77, + 0x35, 0xbb, 0x96, 0x7d, 0x9b, 0xac, 0xea, 0x19, 0xcd, 0xca, 0x72, 0x6e, 0x76, 0x55, 0x74, 0x77, + 0x8a, 0x55, 0x99, 0x35, 0x99, 0x59, 0x7d, 0xd9, 0xc1, 0xf8, 0xc1, 0x17, 0xc1, 0xb0, 0x0d, 0x03, + 0x82, 0x2d, 0x03, 0x96, 0x2d, 0xd8, 0xb0, 0x61, 0x18, 0x86, 0x01, 0x41, 0xc6, 0xca, 0x80, 0x1f, + 0xfc, 0xae, 0x17, 0x1b, 0x7a, 0x90, 0xfc, 0x62, 0x08, 0x02, 0x04, 0xcb, 0xf2, 0xab, 0x7e, 0x82, + 0x11, 0xe7, 0x44, 0x64, 0x46, 0x56, 0x65, 0x93, 0x9c, 0xd9, 0xf5, 0xbe, 0x90, 0x9d, 0x27, 0x4e, + 0xdc, 0x4f, 0x9c, 0x38, 0xd7, 0x28, 0x28, 0xfb, 0x93, 0xc1, 0xa3, 0x89, 0xef, 0x85, 0x1e, 0x2b, + 0x8c, 0x5c, 0x7f, 0x32, 0x58, 0xbf, 0x7d, 0xea, 0x79, 0xa7, 0x23, 0xfe, 0xd8, 0x9e, 0x38, 0x8f, + 0x6d, 0xd7, 0xf5, 0x42, 0x3b, 0x74, 0x3c, 0x37, 0x20, 0x24, 0xe3, 0x27, 0x50, 0x7f, 0xc6, 0xdd, + 0x1e, 0xe7, 0x43, 0x93, 0x7f, 0x3e, 0xe5, 0x41, 0xc8, 0xde, 0x85, 0x45, 0x9b, 0xff, 0x94, 0xf3, + 0xa1, 0x35, 0xb1, 0x83, 0x60, 0x72, 0xe6, 0xdb, 0x01, 0x6f, 0x65, 0xee, 0x65, 0x1e, 0x54, 0xcd, + 0x26, 0x15, 0x1c, 0x46, 0x70, 0xf6, 0x26, 0x54, 0x03, 0x81, 0xca, 0xdd, 0xd0, 0xf7, 0x26, 0x57, + 0xad, 0x2c, 0xe2, 0x55, 0x04, 0xac, 0x43, 0x20, 0x63, 0x04, 0x8d, 0xa8, 0x87, 0x60, 0xe2, 0xb9, + 0x01, 0x67, 0x4f, 0x60, 0x79, 0xe0, 0x4c, 0xce, 0xb8, 0x6f, 0x61, 0xe5, 0xb1, 0xcb, 0xc7, 0x9e, + 0xeb, 0x0c, 0x5a, 0x99, 0x7b, 0xb9, 0x07, 0x65, 0x93, 0x51, 0x99, 0xa8, 0xb1, 0x27, 0x4b, 0xd8, + 0x7d, 0x68, 0x70, 0x97, 0xe0, 0x7c, 0x88, 0xb5, 0x64, 0x57, 0xf5, 0x18, 0x2c, 0x2a, 0x18, 0x7f, + 0x3f, 0x0b, 0x8b, 0x5d, 0xd7, 0x09, 0x3f, 0xb5, 0x47, 0x23, 0x1e, 0xaa, 0x39, 0xdd, 0x87, 0xc6, + 0x05, 0x02, 0x70, 0x4e, 0x17, 0x9e, 0x3f, 0x94, 0x33, 0xaa, 0x13, 0xf8, 0x50, 0x42, 0xaf, 0x1d, + 0x59, 0xf6, 0xda, 0x91, 0xa5, 0x2e, 0x57, 0xee, 0x9a, 0xe5, 0xba, 0x0f, 0x0d, 0x9f, 0x0f, 0xbc, + 0x73, 0xee, 0x5f, 0x59, 0x17, 0x8e, 0x3b, 0xf4, 0x2e, 0x5a, 0xf9, 0x7b, 0x99, 0x07, 0x05, 0xb3, + 0xae, 0xc0, 0x9f, 0x22, 0x94, 0x6d, 0x40, 0x63, 0x70, 0x66, 0xbb, 0x2e, 0x1f, 0x59, 0xc7, 0xf6, + 0xe0, 0xc5, 0x74, 0x12, 0xb4, 0x0a, 0xf7, 0x32, 0x0f, 0x2a, 0x4f, 0x6f, 0x3e, 0xc2, 0x5d, 0x7d, + 0xb4, 0x79, 0x66, 0xbb, 0x1b, 0x58, 0xd2, 0x73, 0xed, 0x49, 0x70, 0xe6, 0x85, 0x66, 0x5d, 0xd6, + 0x20, 0x70, 0x60, 0x2c, 0x03, 0xd3, 0x57, 0x82, 0xd6, 0xde, 0xf8, 0x8f, 0x19, 0x58, 0x3a, 0x72, + 0x47, 0xde, 0xe0, 0xc5, 0xd7, 0x5c, 0xa2, 0x94, 0x39, 0x64, 0x5f, 0x77, 0x0e, 0xb9, 0xaf, 0x3a, + 0x87, 0x55, 0x58, 0x4e, 0x0e, 0x56, 0xce, 0x82, 0xc3, 0x8a, 0xa8, 0x7d, 0xca, 0xd5, 0xb0, 0xd4, + 0x34, 0xbe, 0x09, 0xcd, 0xc1, 0xd4, 0xf7, 0xb9, 0x3b, 0x37, 0x8f, 0x86, 0x84, 0x47, 0x13, 0x79, + 0x13, 0xaa, 0x2e, 0xbf, 0x88, 0xd1, 0x24, 0xed, 0xba, 0xfc, 0x42, 0xa1, 0x18, 0x2d, 0x58, 0x9d, + 0xed, 0x46, 0x0e, 0xe0, 0xaf, 0x32, 0x90, 0x3f, 0x0a, 0x2f, 0x3d, 0xf6, 0x3e, 0x54, 0xed, 0xe1, + 0xd0, 0xe7, 0x41, 0x60, 0x85, 0x57, 0x13, 0x3a, 0x29, 0xf5, 0xa7, 0x4c, 0x4e, 0xb1, 0x4d, 0x45, + 0xfd, 0xab, 0x09, 0x37, 0x2b, 0x76, 0xfc, 0xc1, 0x5a, 0x50, 0x94, 0x9f, 0xd8, 0x6f, 0xd9, 0x54, + 0x9f, 0xec, 0x0e, 0x80, 0x3d, 0xf6, 0xa6, 0x6e, 0x68, 0x05, 0x76, 0x88, 0x2b, 0x96, 0x33, 0xcb, + 0x04, 0xe9, 0xd9, 0x21, 0xbb, 0x05, 0xe5, 0xc9, 0x0b, 0x2b, 0x18, 0xf8, 0xce, 0x24, 0x44, 0xe2, + 0x29, 0x9b, 0xa5, 0xc9, 0x8b, 0x1e, 0x7e, 0xb3, 0x77, 0xa1, 0xe4, 0x4d, 0xc3, 0x89, 0xe7, 0xb8, + 0xa1, 0xa4, 0x97, 0x86, 0x1c, 0xc8, 0xc1, 0x34, 0x3c, 0x14, 0x60, 0x33, 0x42, 0x60, 0x6f, 0x43, + 0x6d, 0xe0, 0xb9, 0x27, 0x8e, 0x3f, 0x26, 0x8e, 0xd0, 0x5a, 0xc0, 0xbe, 0x92, 0x40, 0xe3, 0x0f, + 0xb2, 0x50, 0xe9, 0xfb, 0xb6, 0x1b, 0xd8, 0x03, 0x01, 0x60, 0x6b, 0x50, 0x0c, 0x2f, 0xad, 0x33, + 0x3b, 0x38, 0xc3, 0xa9, 0x96, 0xcd, 0x85, 0xf0, 0x72, 0xc7, 0x0e, 0xce, 0xd8, 0x2a, 0x2c, 0xd0, + 0x28, 0x71, 0x42, 0x39, 0x53, 0x7e, 0x89, 0x03, 0xe2, 0x4e, 0xc7, 0x56, 0xb2, 0xab, 0x1c, 0x52, + 0x4c, 0xd3, 0x9d, 0x8e, 0x37, 0x75, 0xb8, 0x98, 0xfc, 0xb1, 0xd8, 0x6e, 0xea, 0x80, 0xa6, 0x57, + 0x46, 0x08, 0xf6, 0xf1, 0x26, 0x54, 0x65, 0x31, 0x77, 0x4e, 0xcf, 0x68, 0x8e, 0x05, 0xb3, 0x42, + 0x08, 0x08, 0x12, 0x2d, 0x84, 0xce, 0x98, 0x5b, 0x41, 0x68, 0x8f, 0x27, 0x72, 0x4a, 0x65, 0x01, + 0xe9, 0x09, 0x00, 0x16, 0x7b, 0xa1, 0x3d, 0xb2, 0x4e, 0x38, 0x0f, 0x5a, 0x45, 0x59, 0x2c, 0x20, + 0xdb, 0x9c, 0x07, 0xec, 0x1b, 0x50, 0x1f, 0xf2, 0x20, 0xb4, 0xe4, 0x66, 0xf0, 0xa0, 0x55, 0xc2, + 0x93, 0x5f, 0x13, 0xd0, 0xb6, 0x02, 0xb2, 0xdb, 0x00, 0xbe, 0x7d, 0x61, 0x89, 0x85, 0xe0, 0x97, + 0xad, 0x32, 0xed, 0x82, 0x6f, 0x5f, 0xf4, 0x2f, 0x77, 0xf8, 0xa5, 0xa0, 0x9a, 0x67, 0x3c, 0xd4, + 0x16, 0x2d, 0x90, 0xd4, 0x69, 0xec, 0x02, 0xd3, 0xc0, 0x5b, 0x3c, 0xb4, 0x9d, 0x51, 0xc0, 0x3e, + 0x80, 0x6a, 0xa8, 0x21, 0x23, 0x1b, 0xac, 0x44, 0x24, 0xa4, 0x55, 0x30, 0x13, 0x78, 0xc6, 0x19, + 0x94, 0xb6, 0x39, 0xdf, 0x75, 0xc6, 0x4e, 0xc8, 0x56, 0xa1, 0x70, 0xe2, 0x5c, 0x72, 0x22, 0xf6, + 0xdc, 0xce, 0x0d, 0x93, 0x3e, 0xd9, 0x5d, 0x00, 0xfc, 0xc3, 0x1a, 0x47, 0xd4, 0xb4, 0x73, 0xc3, + 0x2c, 0x23, 0x6c, 0x2f, 0xb0, 0x43, 0xb6, 0x0e, 0xc5, 0x09, 0xf7, 0x07, 0x5c, 0xed, 0xdb, 0xce, + 0x0d, 0x53, 0x01, 0x36, 0x8a, 0x50, 0x18, 0x89, 0xd6, 0x8d, 0x3f, 0x2a, 0x40, 0xa5, 0xc7, 0xdd, + 0xe8, 0x94, 0x31, 0xc8, 0x8b, 0x05, 0x91, 0x27, 0x0b, 0xff, 0x66, 0x6f, 0x41, 0x05, 0x97, 0x2e, + 0x08, 0x7d, 0xc7, 0x3d, 0x25, 0xaa, 0xde, 0xc8, 0xb6, 0x32, 0x26, 0x08, 0x70, 0x0f, 0xa1, 0xac, + 0x09, 0x39, 0x7b, 0xac, 0xa8, 0x5a, 0xfc, 0xc9, 0x6e, 0x42, 0xc9, 0x1e, 0x87, 0x34, 0xbc, 0x2a, + 0x82, 0x8b, 0xf6, 0x38, 0xc4, 0xa1, 0xbd, 0x09, 0xd5, 0x89, 0x7d, 0x35, 0x16, 0x67, 0x39, 0x22, + 0x87, 0xaa, 0x59, 0x91, 0x30, 0x24, 0x88, 0xa7, 0xb0, 0xa4, 0xa3, 0xa8, 0xce, 0x0b, 0x51, 0xe7, + 0x8b, 0x1a, 0xb6, 0x1c, 0xc3, 0x7d, 0x68, 0xa8, 0x3a, 0x3e, 0xcd, 0x07, 0xc9, 0xa4, 0x6c, 0xd6, + 0x25, 0x58, 0xcd, 0xf2, 0x01, 0x34, 0x4f, 0x1c, 0xd7, 0x1e, 0x59, 0x83, 0x51, 0x78, 0x6e, 0x0d, + 0xf9, 0x28, 0xb4, 0x91, 0x62, 0x0a, 0x66, 0x1d, 0xe1, 0x9b, 0xa3, 0xf0, 0x7c, 0x4b, 0x40, 0xd9, + 0xb7, 0xa0, 0x7c, 0xc2, 0xb9, 0x85, 0x8b, 0xd5, 0x2a, 0x25, 0x0e, 0x9e, 0xda, 0x21, 0xb3, 0x74, + 0xa2, 0xf6, 0xea, 0x5b, 0xd0, 0xf4, 0xa6, 0xe1, 0xa9, 0xe7, 0xb8, 0xa7, 0x96, 0xe0, 0x77, 0x96, + 0x33, 0x44, 0x1a, 0xca, 0x6f, 0x64, 0x9f, 0x64, 0xcc, 0xba, 0x2a, 0x13, 0x9c, 0xa7, 0x3b, 0x64, + 0xef, 0x40, 0x63, 0x64, 0x07, 0xa1, 0x75, 0xe6, 0x4d, 0xac, 0xc9, 0xf4, 0xf8, 0x05, 0xbf, 0x6a, + 0xd5, 0x70, 0x21, 0x6a, 0x02, 0xbc, 0xe3, 0x4d, 0x0e, 0x11, 0x28, 0x28, 0x1b, 0xc7, 0x49, 0x83, + 0x80, 0x7b, 0x99, 0x07, 0x35, 0xb3, 0x2c, 0x20, 0xd4, 0xe9, 0x67, 0xb0, 0x84, 0xdb, 0x33, 0x98, + 0x06, 0xa1, 0x37, 0xb6, 0x04, 0xaf, 0xf6, 0x87, 0x41, 0xab, 0x82, 0xb4, 0xf6, 0x4d, 0x39, 0x58, + 0x6d, 0x8f, 0x1f, 0x6d, 0xf1, 0x20, 0xdc, 0x44, 0x64, 0x93, 0x70, 0xc5, 0x85, 0x7e, 0x65, 0x2e, + 0x0e, 0x67, 0xe1, 0xec, 0x5b, 0xc0, 0xec, 0xd1, 0xc8, 0xbb, 0xb0, 0x02, 0x3e, 0x3a, 0xb1, 0xe4, + 0x22, 0xb6, 0xea, 0xf7, 0x32, 0x0f, 0x4a, 0x66, 0x13, 0x4b, 0x7a, 0x7c, 0x74, 0x72, 0x48, 0x70, + 0xf6, 0x01, 0xe0, 0x61, 0xb2, 0x4e, 0xb8, 0x1d, 0x4e, 0x7d, 0x1e, 0xb4, 0x1a, 0xf7, 0x72, 0x0f, + 0xea, 0x4f, 0x17, 0xa3, 0xf5, 0x42, 0xf0, 0x86, 0x13, 0x9a, 0x55, 0x81, 0x27, 0xbf, 0x83, 0xf5, + 0x2d, 0x58, 0x4d, 0x1f, 0x92, 0x20, 0x2a, 0xb1, 0x2a, 0x82, 0x18, 0xf3, 0xa6, 0xf8, 0x93, 0x2d, + 0x43, 0xe1, 0xdc, 0x1e, 0x4d, 0xb9, 0xe4, 0xe9, 0xf4, 0xf1, 0x61, 0xf6, 0xfb, 0x19, 0xe3, 0x0f, + 0x33, 0x50, 0xa5, 0x59, 0x4a, 0x59, 0xe4, 0x2d, 0xa8, 0x29, 0x6a, 0xe0, 0xbe, 0xef, 0xf9, 0x92, + 0xab, 0x29, 0xca, 0xeb, 0x08, 0x98, 0xb8, 0x55, 0x14, 0xd2, 0xc4, 0xe7, 0xce, 0xd8, 0x3e, 0x55, + 0x4d, 0x2b, 0x52, 0x3a, 0x94, 0x60, 0xf6, 0x5e, 0xdc, 0x9e, 0xef, 0x4d, 0x43, 0x2e, 0xef, 0xbc, + 0xaa, 0x9c, 0x9e, 0x29, 0x60, 0x51, 0xeb, 0xf8, 0xf5, 0x1a, 0x74, 0x6e, 0xfc, 0x4e, 0x06, 0x98, + 0x18, 0x76, 0xdf, 0xa3, 0x06, 0x24, 0x85, 0xce, 0xd6, 0xcc, 0xbc, 0xf6, 0x09, 0xc9, 0xbe, 0xec, + 0x84, 0x18, 0x50, 0xa0, 0xb1, 0xe7, 0x53, 0xc6, 0x4e, 0x45, 0x3f, 0xca, 0x97, 0x72, 0xcd, 0xbc, + 0xf1, 0x3f, 0x73, 0xb0, 0xbc, 0x49, 0x57, 0x76, 0x7b, 0x30, 0xe0, 0x93, 0xe8, 0xec, 0xdc, 0x85, + 0x8a, 0xeb, 0x0d, 0xb9, 0xa2, 0x58, 0x1a, 0x18, 0x08, 0x90, 0x46, 0xae, 0x67, 0xb6, 0xe3, 0xd2, + 0xc0, 0x69, 0x31, 0xcb, 0x08, 0xc1, 0x61, 0xbf, 0x03, 0x8d, 0x09, 0x77, 0x87, 0xfa, 0x11, 0x21, + 0xa1, 0xaa, 0x26, 0xc1, 0xf2, 0x74, 0xdc, 0x85, 0xca, 0xc9, 0x94, 0xf0, 0x04, 0x63, 0xc9, 0x23, + 0x0d, 0x80, 0x04, 0xb5, 0x89, 0xbf, 0x4c, 0xa6, 0xc1, 0x19, 0x96, 0x16, 0xb0, 0xb4, 0x28, 0xbe, + 0x45, 0xd1, 0x1d, 0x80, 0xe1, 0x34, 0x08, 0xe5, 0x89, 0x59, 0xc0, 0xc2, 0xb2, 0x80, 0xd0, 0x89, + 0xf9, 0x36, 0x2c, 0x8d, 0xed, 0x4b, 0x0b, 0x69, 0xc7, 0x72, 0x5c, 0xeb, 0x64, 0x84, 0x77, 0x4e, + 0x11, 0xf1, 0x9a, 0x63, 0xfb, 0xf2, 0x13, 0x51, 0xd2, 0x75, 0xb7, 0x11, 0x2e, 0xd8, 0x8a, 0x12, + 0x77, 0x7c, 0x1e, 0x70, 0xff, 0x9c, 0x23, 0x27, 0xc8, 0x47, 0x32, 0x8d, 0x49, 0x50, 0x31, 0xa2, + 0xb1, 0x98, 0x77, 0x38, 0x1a, 0xd0, 0xb1, 0x37, 0x8b, 0x63, 0xc7, 0xdd, 0x09, 0x47, 0x03, 0x71, + 0xaf, 0x08, 0x3e, 0x32, 0xe1, 0xbe, 0xf5, 0xe2, 0x02, 0xcf, 0x70, 0x1e, 0xf9, 0xc6, 0x21, 0xf7, + 0x9f, 0x5f, 0x88, 0xab, 0x7f, 0x10, 0x20, 0x23, 0xb2, 0xaf, 0x5a, 0x15, 0x3c, 0xe0, 0xa5, 0x41, + 0x20, 0x58, 0x90, 0x7d, 0x25, 0x0e, 0xa1, 0x18, 0xad, 0x8d, 0xbb, 0xc0, 0x87, 0xd8, 0x7c, 0x80, + 0x1c, 0xb5, 0x86, 0x83, 0x6d, 0xcb, 0x02, 0xd1, 0x4f, 0x20, 0xa8, 0x5e, 0x0d, 0xf6, 0x64, 0x64, + 0x9f, 0x06, 0xc8, 0x52, 0x6a, 0x66, 0x55, 0x02, 0xb7, 0x05, 0xcc, 0xf8, 0x94, 0x84, 0x2c, 0x6d, + 0x6f, 0xe5, 0x99, 0x11, 0x57, 0x3d, 0x42, 0x70, 0x5f, 0x4b, 0xa6, 0xfc, 0x4a, 0xdb, 0xb4, 0x6c, + 0xca, 0xa6, 0x19, 0xbf, 0x97, 0x81, 0xaa, 0x6c, 0x19, 0x85, 0x12, 0xf6, 0x08, 0x98, 0xda, 0xc5, + 0xf0, 0xd2, 0x19, 0x5a, 0xc7, 0x57, 0x21, 0x0f, 0x88, 0x68, 0x76, 0x6e, 0x98, 0x4d, 0x59, 0xd6, + 0xbf, 0x74, 0x86, 0x1b, 0xa2, 0x84, 0x3d, 0x84, 0x66, 0x02, 0x3f, 0x08, 0x7d, 0xa2, 0xe8, 0x9d, + 0x1b, 0x66, 0x5d, 0xc3, 0xee, 0x85, 0xbe, 0x38, 0x23, 0x42, 0xe4, 0x99, 0x86, 0x96, 0xe3, 0x0e, + 0xf9, 0x25, 0x92, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x2b, 0x40, 0x1b, 0x75, 0xa8, 0xea, 0xcd, 0x19, + 0xa7, 0x50, 0x52, 0xf2, 0x12, 0x0a, 0x0c, 0x33, 0x43, 0x32, 0xcb, 0x61, 0x34, 0x92, 0x9b, 0x50, + 0x4a, 0x8e, 0xc0, 0x2c, 0x86, 0xaf, 0xdd, 0xb1, 0xf1, 0x03, 0x68, 0xee, 0x0a, 0xe2, 0x71, 0x05, + 0xb1, 0x4a, 0xf9, 0x6f, 0x15, 0x16, 0xb4, 0x43, 0x53, 0x36, 0xe5, 0x97, 0xb8, 0x73, 0xcf, 0xbc, + 0x20, 0x94, 0xbd, 0xe0, 0xdf, 0xc6, 0x1f, 0x65, 0x80, 0x75, 0x82, 0xd0, 0x19, 0xdb, 0x21, 0xdf, + 0xe6, 0x11, 0x5b, 0x38, 0x80, 0xaa, 0x68, 0xad, 0xef, 0xb5, 0x49, 0x20, 0x23, 0x81, 0xe2, 0x5d, + 0x79, 0x8c, 0xe7, 0x2b, 0x3c, 0xd2, 0xb1, 0x89, 0xcd, 0x27, 0x1a, 0x10, 0xa7, 0x2c, 0xb4, 0xfd, + 0x53, 0x1e, 0xa2, 0x18, 0x27, 0xe5, 0x7d, 0x20, 0x90, 0x10, 0xe0, 0xd6, 0x7f, 0x15, 0x16, 0xe7, + 0xda, 0xd0, 0xf9, 0x72, 0x39, 0x85, 0x2f, 0xe7, 0x74, 0xbe, 0x6c, 0xc1, 0x52, 0x62, 0x5c, 0x92, + 0xd2, 0xd6, 0xa0, 0x28, 0x0e, 0x84, 0x10, 0x0e, 0x32, 0x24, 0x55, 0x9e, 0x70, 0x2e, 0xc4, 0xe0, + 0xc7, 0xb0, 0x7c, 0xc2, 0xb9, 0x6f, 0x87, 0x58, 0x88, 0x27, 0x46, 0xec, 0x90, 0x6c, 0x78, 0x51, + 0x96, 0xf5, 0xec, 0xf0, 0x90, 0xfb, 0x62, 0xa7, 0x8c, 0xff, 0x95, 0x81, 0x86, 0xe0, 0xa0, 0x7b, + 0xb6, 0x7b, 0xa5, 0xd6, 0x69, 0x37, 0x75, 0x9d, 0x1e, 0x68, 0x97, 0xa1, 0x86, 0xfd, 0x55, 0x17, + 0x29, 0x37, 0xbb, 0x48, 0xec, 0x1e, 0x54, 0x13, 0x63, 0x2d, 0xe0, 0x58, 0x21, 0x88, 0x06, 0xf9, + 0xf3, 0x2f, 0xe3, 0x3b, 0xd0, 0x8c, 0x87, 0x2d, 0xd7, 0x90, 0x41, 0x5e, 0x90, 0xa4, 0x6c, 0x00, + 0xff, 0x36, 0xfe, 0x65, 0x86, 0x10, 0x37, 0x3d, 0x27, 0x92, 0x4e, 0x05, 0xa2, 0x90, 0x7b, 0x15, + 0xa2, 0xf8, 0xfb, 0x5a, 0xa9, 0xfe, 0xe7, 0x9f, 0xac, 0x38, 0x3a, 0x01, 0x77, 0x87, 0x96, 0x3d, + 0x1a, 0x21, 0xf3, 0x2d, 0x99, 0x45, 0xf1, 0xdd, 0x1e, 0x8d, 0x8c, 0xfb, 0xb0, 0xa8, 0x8d, 0xee, + 0x25, 0xf3, 0xd8, 0x07, 0xb6, 0xeb, 0x04, 0xe1, 0x91, 0x1b, 0x4c, 0x34, 0xc1, 0xed, 0x16, 0x94, + 0x05, 0x87, 0x15, 0x23, 0xa3, 0x23, 0x5b, 0x30, 0x05, 0xcb, 0x15, 0xe3, 0x0a, 0xb0, 0xd0, 0xbe, + 0x94, 0x85, 0x59, 0x59, 0x68, 0x5f, 0x62, 0xa1, 0xf1, 0x7d, 0x58, 0x4a, 0xb4, 0x27, 0xbb, 0x7e, + 0x13, 0x0a, 0xd3, 0xf0, 0xd2, 0x53, 0xa2, 0x79, 0x45, 0x52, 0x88, 0x50, 0x00, 0x4d, 0x2a, 0x31, + 0x3e, 0x82, 0xc5, 0x7d, 0x7e, 0x21, 0x0f, 0xb1, 0x1a, 0xc8, 0x3b, 0x90, 0x7f, 0x85, 0x52, 0x88, + 0xe5, 0xc6, 0x23, 0x60, 0x7a, 0x65, 0xd9, 0xab, 0xa6, 0x23, 0x66, 0x12, 0x3a, 0xa2, 0xf1, 0x0e, + 0xb0, 0x9e, 0x73, 0xea, 0xee, 0xf1, 0x20, 0xb0, 0x4f, 0xa3, 0x63, 0xdf, 0x84, 0xdc, 0x38, 0x38, + 0x95, 0x3c, 0x4a, 0xfc, 0x69, 0x7c, 0x07, 0x96, 0x12, 0x78, 0xb2, 0xe1, 0xdb, 0x50, 0x0e, 0x9c, + 0x53, 0x17, 0x05, 0x2b, 0xd9, 0x74, 0x0c, 0x30, 0xb6, 0x61, 0xf9, 0x13, 0xee, 0x3b, 0x27, 0x57, + 0xaf, 0x6a, 0x3e, 0xd9, 0x4e, 0x76, 0xb6, 0x9d, 0x0e, 0xac, 0xcc, 0xb4, 0x23, 0xbb, 0x27, 0xf2, + 0x95, 0x3b, 0x59, 0x32, 0xe9, 0x43, 0xe3, 0x7b, 0x59, 0x9d, 0xef, 0x19, 0x47, 0xc0, 0x36, 0x3d, + 0xd7, 0xe5, 0x83, 0xf0, 0x90, 0x73, 0x3f, 0xb6, 0x52, 0xc5, 0xb4, 0x5a, 0x79, 0xba, 0x26, 0x57, + 0x76, 0x96, 0x99, 0x4a, 0x22, 0x66, 0x90, 0x9f, 0x70, 0x7f, 0x8c, 0x0d, 0x97, 0x4c, 0xfc, 0xdb, + 0x58, 0x81, 0xa5, 0x44, 0xb3, 0x52, 0xaf, 0x7f, 0x02, 0x2b, 0x5b, 0x4e, 0x30, 0x98, 0xef, 0x70, + 0x0d, 0x8a, 0x93, 0xe9, 0xb1, 0x95, 0xe4, 0xcb, 0xcf, 0xf9, 0x95, 0xd0, 0xf6, 0x66, 0x6b, 0xc8, + 0xb6, 0xfe, 0x6e, 0x06, 0xf2, 0x3b, 0xfd, 0xdd, 0x4d, 0xb6, 0x0e, 0x25, 0xc7, 0x1d, 0x78, 0x63, + 0x21, 0x78, 0xd1, 0x9c, 0xa3, 0xef, 0x6b, 0x0f, 0xd8, 0x2d, 0x28, 0xa3, 0xbc, 0x26, 0x54, 0x5b, + 0x29, 0xfa, 0x94, 0x04, 0x60, 0xd7, 0x1b, 0xbc, 0x10, 0x3a, 0x35, 0xbf, 0x9c, 0x38, 0x3e, 0x6a, + 0xcd, 0x4a, 0x19, 0xce, 0xd3, 0x5d, 0x1f, 0x17, 0x90, 0x46, 0x6c, 0xfc, 0x75, 0x11, 0x8a, 0xf2, + 0xb6, 0xa5, 0x9b, 0x3b, 0x74, 0xce, 0x79, 0x7c, 0x73, 0x8b, 0x2f, 0x21, 0x0f, 0xf8, 0x7c, 0xec, + 0x85, 0x91, 0xc0, 0x46, 0x7b, 0x50, 0x25, 0xa0, 0x14, 0xd9, 0x34, 0xa1, 0x81, 0x4c, 0x0c, 0x39, + 0x42, 0x1a, 0xe8, 0x57, 0xf9, 0x2d, 0x28, 0xaa, 0xbb, 0x3f, 0x1f, 0xe9, 0x34, 0x0b, 0x03, 0x92, + 0xd6, 0xd6, 0xa1, 0x34, 0xb0, 0x27, 0xf6, 0xc0, 0x09, 0xaf, 0x24, 0x43, 0x88, 0xbe, 0x45, 0xeb, + 0x23, 0x6f, 0x60, 0x8f, 0xac, 0x63, 0x7b, 0x64, 0xbb, 0x03, 0x2e, 0x75, 0xf7, 0x2a, 0x02, 0x37, + 0x08, 0x26, 0xf4, 0x73, 0x39, 0x4e, 0x85, 0x45, 0x2a, 0xbc, 0x1c, 0xbd, 0x42, 0x13, 0xc2, 0xa5, + 0x37, 0x1e, 0x3b, 0x42, 0xcb, 0x20, 0x31, 0x2c, 0x67, 0x96, 0x09, 0xb2, 0xcd, 0x71, 0xb6, 0xb2, + 0xf8, 0x82, 0x96, 0xae, 0x4c, 0x5d, 0x11, 0xf0, 0x53, 0x32, 0x24, 0xcc, 0xcb, 0x62, 0x39, 0x4d, + 0x16, 0x7b, 0x17, 0x16, 0xa7, 0x6e, 0xc0, 0xc3, 0x70, 0xc4, 0x87, 0xd1, 0x58, 0x2a, 0x88, 0xd4, + 0x8c, 0x0a, 0xd4, 0x70, 0x1e, 0xc1, 0x12, 0x19, 0x1d, 0x02, 0x3b, 0xf4, 0x82, 0x33, 0x27, 0xb0, + 0x02, 0xa1, 0x21, 0x91, 0xba, 0xbb, 0x88, 0x45, 0x3d, 0x59, 0xd2, 0x23, 0x15, 0x69, 0x6d, 0x06, + 0xdf, 0xe7, 0x03, 0xee, 0x9c, 0xf3, 0x21, 0xca, 0x69, 0x39, 0x73, 0x25, 0x51, 0xc7, 0x94, 0x85, + 0x28, 0x74, 0x4f, 0xc7, 0xd6, 0x74, 0x32, 0xb4, 0x85, 0xb0, 0x52, 0x27, 0x61, 0xd8, 0x9d, 0x8e, + 0x8f, 0x08, 0xc2, 0x9e, 0x80, 0x92, 0xc4, 0xa4, 0x7c, 0xd8, 0x48, 0xf0, 0x33, 0x41, 0xac, 0x66, + 0x55, 0x62, 0x90, 0xa0, 0x98, 0x90, 0x39, 0x9b, 0x33, 0x32, 0x67, 0x0b, 0x8a, 0x13, 0xdf, 0x39, + 0xb7, 0x43, 0xde, 0x5a, 0x24, 0x06, 0x2e, 0x3f, 0x05, 0x67, 0x70, 0x5c, 0x27, 0x74, 0xec, 0xd0, + 0xf3, 0x5b, 0x0c, 0xcb, 0x62, 0x00, 0x7b, 0x08, 0x8b, 0x48, 0x23, 0x41, 0x68, 0x87, 0xd3, 0x40, + 0x4a, 0xa0, 0x4b, 0x48, 0x4c, 0x28, 0x43, 0xf7, 0x10, 0x8e, 0x42, 0x28, 0xfb, 0x0e, 0xac, 0x12, + 0x59, 0x60, 0x0d, 0x29, 0x59, 0xa3, 0x40, 0xb0, 0x8c, 0x4b, 0xb1, 0x84, 0xa5, 0x82, 0xbe, 0xa5, + 0x7c, 0x2d, 0xa4, 0x83, 0xf7, 0x61, 0x4d, 0x92, 0xc9, 0x5c, 0xad, 0x15, 0xac, 0xb5, 0x4c, 0xc5, + 0x33, 0xd5, 0x1e, 0xc1, 0xa2, 0x18, 0x92, 0x33, 0xb0, 0x64, 0x6d, 0x71, 0x12, 0x56, 0xc5, 0xe8, + 0x51, 0x53, 0x6a, 0x50, 0xa1, 0x89, 0x65, 0xcf, 0xf9, 0x15, 0xfb, 0x01, 0x34, 0x88, 0x64, 0x50, + 0xbd, 0x42, 0x4e, 0xbf, 0x8e, 0x9c, 0x7e, 0x45, 0x59, 0x38, 0xa3, 0x52, 0x64, 0xf6, 0xf5, 0x41, + 0xe2, 0x5b, 0x1c, 0x87, 0x91, 0x73, 0xc2, 0x43, 0x67, 0xcc, 0x5b, 0x6b, 0x44, 0x60, 0xea, 0x5b, + 0x9c, 0xd4, 0xe9, 0x04, 0x4b, 0x5a, 0xc4, 0x17, 0xe8, 0x0b, 0x69, 0x77, 0xe4, 0x05, 0x5c, 0x99, + 0xa8, 0x5a, 0x37, 0xe5, 0x21, 0x14, 0x40, 0xc9, 0xf6, 0x8c, 0x9f, 0x65, 0xe8, 0x1e, 0x93, 0xc7, + 0x3e, 0xd0, 0xb4, 0x32, 0x3a, 0xf0, 0x96, 0xe7, 0x8e, 0xae, 0x24, 0x0f, 0x00, 0x02, 0x1d, 0xb8, + 0x23, 0x3c, 0x84, 0x8e, 0xab, 0xa3, 0x10, 0xcb, 0xac, 0x2a, 0x20, 0x22, 0xdd, 0x85, 0xca, 0x64, + 0x7a, 0x3c, 0x72, 0x06, 0x84, 0x92, 0xa3, 0x56, 0x08, 0x84, 0x08, 0x42, 0x2d, 0x25, 0x42, 0x20, + 0x8c, 0x3c, 0x62, 0x54, 0x24, 0x0c, 0x51, 0x90, 0x25, 0x73, 0x1f, 0xb9, 0x40, 0xd5, 0xc4, 0xbf, + 0x8d, 0x0d, 0x58, 0x4e, 0x0e, 0x5a, 0xde, 0x17, 0x0f, 0xa1, 0x24, 0x59, 0x8c, 0xb2, 0x57, 0xd4, + 0x35, 0x0b, 0xb2, 0xd0, 0xac, 0xa2, 0x72, 0xe3, 0xb7, 0x16, 0x60, 0x49, 0x42, 0x37, 0xc5, 0x8a, + 0xf4, 0xa6, 0xe3, 0xb1, 0xed, 0xa7, 0xf0, 0xae, 0xcc, 0xcb, 0x79, 0x57, 0x76, 0x8e, 0x77, 0x25, + 0x15, 0x56, 0x62, 0x7d, 0x49, 0x85, 0x55, 0x6c, 0x01, 0xe9, 0x10, 0xba, 0xf9, 0xb2, 0x26, 0xc1, + 0x7d, 0x32, 0x93, 0xce, 0x71, 0xda, 0x42, 0x0a, 0xa7, 0xd5, 0xf9, 0xe4, 0xc2, 0x0c, 0x9f, 0x7c, + 0x13, 0x68, 0xaf, 0x15, 0xdb, 0x2f, 0x92, 0x5a, 0x81, 0x30, 0x69, 0x03, 0xbd, 0x0f, 0x8d, 0x59, + 0xd6, 0x44, 0x3c, 0xb0, 0x9e, 0xc2, 0x98, 0x9c, 0x31, 0xc7, 0x4b, 0x46, 0x43, 0x2e, 0x4b, 0xc6, + 0xe4, 0x8c, 0xf9, 0x2e, 0x96, 0x28, 0xfc, 0x0e, 0x00, 0xf5, 0x8d, 0xb4, 0x0e, 0x48, 0xeb, 0xef, + 0x24, 0xf7, 0x42, 0x5f, 0xf5, 0x47, 0xe2, 0x63, 0xea, 0x73, 0x24, 0xfe, 0x32, 0xd6, 0x44, 0xba, + 0x7f, 0x0e, 0x75, 0x6f, 0xc2, 0x5d, 0x2b, 0x66, 0x11, 0x15, 0x6c, 0xea, 0xed, 0x97, 0x34, 0xd5, + 0x55, 0xb8, 0x66, 0x4d, 0xd4, 0x8d, 0x3e, 0xd9, 0x1e, 0x2d, 0x3c, 0xd7, 0x5a, 0xab, 0x7e, 0x85, + 0xd6, 0xea, 0x58, 0x39, 0xfa, 0x36, 0xfe, 0x41, 0x06, 0x2a, 0xda, 0xb0, 0xd9, 0x0a, 0x2c, 0x6e, + 0x1e, 0x1c, 0x1c, 0x76, 0xcc, 0x76, 0xbf, 0xfb, 0x49, 0xc7, 0xda, 0xdc, 0x3d, 0xe8, 0x75, 0x9a, + 0x37, 0x04, 0x78, 0xf7, 0x60, 0xb3, 0xbd, 0x6b, 0x6d, 0x1f, 0x98, 0x9b, 0x0a, 0x9c, 0x61, 0xab, + 0xc0, 0xcc, 0xce, 0xde, 0x41, 0xbf, 0x93, 0x80, 0x67, 0x59, 0x13, 0xaa, 0x1b, 0x66, 0xa7, 0xbd, + 0xb9, 0x23, 0x21, 0x39, 0xb6, 0x0c, 0xcd, 0xed, 0xa3, 0xfd, 0xad, 0xee, 0xfe, 0x33, 0x6b, 0xb3, + 0xbd, 0xbf, 0xd9, 0xd9, 0xed, 0x6c, 0x35, 0xf3, 0xac, 0x06, 0xe5, 0xf6, 0x46, 0x7b, 0x7f, 0xeb, + 0x60, 0xbf, 0xb3, 0xd5, 0x2c, 0x18, 0xbf, 0x02, 0xe5, 0x78, 0xa2, 0x15, 0x28, 0x1e, 0xed, 0x3f, + 0xdf, 0x3f, 0xf8, 0x74, 0xbf, 0x79, 0x83, 0x95, 0xa1, 0x80, 0xfd, 0x37, 0x33, 0x0c, 0x60, 0x81, + 0xfa, 0x6c, 0x66, 0x59, 0x09, 0xf2, 0x1b, 0x07, 0xfd, 0x9d, 0x66, 0xce, 0xf8, 0xf3, 0x0c, 0xac, + 0xe0, 0x94, 0x87, 0xb3, 0x4c, 0xe0, 0x1e, 0x54, 0x06, 0x9e, 0x37, 0x11, 0x0a, 0x52, 0x2c, 0x08, + 0xe8, 0x20, 0x71, 0xc0, 0x89, 0xe7, 0x9e, 0x78, 0xfe, 0x80, 0x4b, 0x1e, 0x00, 0x08, 0xda, 0x16, + 0x10, 0x41, 0x83, 0x92, 0x88, 0x09, 0x83, 0x58, 0x40, 0x85, 0x60, 0x84, 0xb2, 0x0a, 0x0b, 0xc7, + 0x3e, 0xb7, 0x07, 0x67, 0xf2, 0xf4, 0xcb, 0x2f, 0xf6, 0xcd, 0x58, 0x75, 0x1f, 0x08, 0x9a, 0x1a, + 0xf1, 0x21, 0x1e, 0x81, 0x92, 0xd9, 0x90, 0xf0, 0x4d, 0x09, 0x16, 0x97, 0x88, 0x7d, 0x6c, 0xbb, + 0x43, 0xcf, 0xe5, 0x43, 0xa9, 0x21, 0xc4, 0x00, 0xe3, 0x10, 0x56, 0x67, 0xe7, 0x27, 0xf9, 0xc5, + 0x07, 0x1a, 0xbf, 0x20, 0x81, 0x7d, 0xfd, 0x7a, 0x52, 0xd0, 0x78, 0xc7, 0x9f, 0xe5, 0x20, 0x2f, + 0x04, 0xb8, 0x6b, 0x65, 0x3d, 0x5d, 0x22, 0xcf, 0xcd, 0x79, 0x6d, 0xd0, 0x42, 0x40, 0x37, 0x3b, + 0x99, 0xa1, 0xca, 0x08, 0xc1, 0x1b, 0x3d, 0x2a, 0xf6, 0xf9, 0xe0, 0x5c, 0xda, 0xa1, 0xa8, 0xd8, + 0xe4, 0x83, 0x73, 0x54, 0x85, 0xec, 0x90, 0xea, 0xd2, 0x79, 0x2f, 0x06, 0x76, 0x88, 0x35, 0x65, + 0x11, 0xd6, 0x2b, 0x46, 0x45, 0x58, 0xab, 0x05, 0x45, 0xc7, 0x3d, 0xf6, 0xa6, 0xee, 0x10, 0x8f, + 0x77, 0xc9, 0x54, 0x9f, 0xe8, 0x24, 0x42, 0x4e, 0x24, 0xee, 0x0f, 0x3a, 0xcd, 0x25, 0x01, 0xe8, + 0x8b, 0x1b, 0xe4, 0x3d, 0x28, 0x07, 0x57, 0xee, 0x40, 0x3f, 0xc3, 0xcb, 0x72, 0x7d, 0xc4, 0xec, + 0x1f, 0xf5, 0xae, 0xdc, 0x01, 0x9e, 0xd8, 0x52, 0x20, 0xff, 0x62, 0xef, 0x43, 0x29, 0x32, 0xd7, + 0x12, 0x07, 0xbe, 0xa9, 0xd7, 0x50, 0x36, 0x5a, 0xd2, 0x8a, 0x23, 0xd4, 0xf5, 0xe7, 0x50, 0x4b, + 0x14, 0xe9, 0xaa, 0x6c, 0x8d, 0x54, 0xd9, 0xb7, 0x75, 0x55, 0x36, 0x66, 0xec, 0xb2, 0x9a, 0xae, + 0xda, 0xfe, 0x2a, 0x94, 0xd4, 0xc8, 0xc4, 0x71, 0x92, 0x47, 0xc1, 0xea, 0x7d, 0xb6, 0xbf, 0xd9, + 0xbc, 0xc1, 0x1a, 0x50, 0x69, 0x6f, 0xe2, 0x09, 0x45, 0x40, 0x46, 0xa0, 0x1c, 0xb6, 0x7b, 0xbd, + 0x08, 0x92, 0x35, 0x18, 0x34, 0xc5, 0xf5, 0x22, 0x46, 0x1c, 0x39, 0x64, 0x3e, 0x80, 0x45, 0x0d, + 0x16, 0x6b, 0x7b, 0xe2, 0x3e, 0x9a, 0xd5, 0xf6, 0x50, 0xb6, 0xa7, 0x12, 0x63, 0x0d, 0x56, 0xc4, + 0x67, 0xe7, 0x9c, 0xbb, 0x61, 0x6f, 0x7a, 0x4c, 0xee, 0x38, 0xc7, 0x73, 0x85, 0xcc, 0x5f, 0x8e, + 0x4a, 0xae, 0x27, 0xa4, 0x47, 0x52, 0x31, 0xcc, 0xe2, 0xf2, 0xaf, 0x6b, 0x3d, 0x60, 0xc5, 0x47, + 0xf8, 0x6f, 0x42, 0x41, 0x2c, 0x47, 0x20, 0x31, 0xd7, 0xc3, 0x4e, 0xc7, 0xb4, 0x0e, 0xf6, 0x77, + 0xbb, 0xfb, 0x82, 0x19, 0x89, 0xb9, 0x22, 0x60, 0x7b, 0x1b, 0x21, 0x19, 0xa3, 0x09, 0xf5, 0x67, + 0x3c, 0xec, 0xba, 0x27, 0x9e, 0x9a, 0xe9, 0x5f, 0x15, 0xa0, 0x11, 0x81, 0x62, 0x05, 0xf3, 0x9c, + 0xfb, 0x81, 0xe3, 0xb9, 0x28, 0x2b, 0x96, 0x4d, 0xf5, 0x29, 0x6e, 0x10, 0x67, 0xc8, 0xdd, 0xd0, + 0x09, 0xaf, 0xac, 0x84, 0x35, 0xaa, 0xae, 0xc0, 0xf2, 0xa6, 0x5a, 0x86, 0x82, 0x3d, 0x72, 0x6c, + 0xe5, 0xc5, 0xa4, 0x0f, 0x01, 0x1d, 0x78, 0x23, 0xcf, 0x47, 0xb1, 0xb0, 0x6c, 0xd2, 0x07, 0x7b, + 0x02, 0xcb, 0x42, 0x3c, 0xd5, 0x4d, 0x84, 0x78, 0x46, 0xc9, 0x30, 0xc6, 0xdc, 0xe9, 0xf8, 0x30, + 0x36, 0x13, 0x8a, 0x12, 0x71, 0x3f, 0x89, 0x1a, 0x52, 0x20, 0x89, 0x2a, 0x90, 0xa6, 0xb3, 0xe8, + 0x4e, 0xc7, 0x6d, 0x2c, 0x89, 0xf0, 0x9f, 0xc2, 0x8a, 0xc0, 0x8f, 0x44, 0x98, 0xa8, 0x46, 0x03, + 0x6b, 0x88, 0xc6, 0xba, 0xb2, 0x2c, 0xaa, 0x73, 0x0b, 0xca, 0x34, 0x2a, 0xb1, 0xe3, 0x05, 0x92, + 0x70, 0x71, 0x28, 0xdc, 0x0f, 0xe6, 0x1c, 0x8e, 0x0b, 0x74, 0xd9, 0xce, 0x38, 0x1c, 0x35, 0x97, + 0x65, 0x69, 0xd6, 0x65, 0xf9, 0x14, 0x56, 0x8e, 0x79, 0x10, 0x5a, 0x67, 0xdc, 0x1e, 0x72, 0x1f, + 0x4f, 0x24, 0xb9, 0x26, 0x49, 0x92, 0x5f, 0x12, 0x85, 0x3b, 0x58, 0xd6, 0x57, 0x45, 0x42, 0x96, + 0x10, 0x47, 0x8f, 0x0f, 0xad, 0xd0, 0xb3, 0x50, 0xc4, 0xc0, 0x43, 0x5c, 0x32, 0x6b, 0x04, 0xee, + 0x7b, 0x9b, 0x02, 0x98, 0xc4, 0x3b, 0xf5, 0xed, 0xc9, 0x99, 0x94, 0xb5, 0x23, 0xbc, 0x67, 0x02, + 0xc8, 0x6e, 0x43, 0x31, 0xe4, 0x41, 0xe8, 0x72, 0xf2, 0x0b, 0x91, 0x34, 0xab, 0x40, 0xec, 0x6d, + 0x58, 0xc0, 0x3e, 0x82, 0x56, 0x13, 0xe9, 0xbd, 0x1a, 0x33, 0x4b, 0xc7, 0x35, 0x65, 0x99, 0x10, + 0xd8, 0xa6, 0xbe, 0x13, 0xb4, 0xaa, 0xe8, 0x0f, 0xc5, 0xbf, 0xd9, 0x0f, 0x35, 0xb6, 0xb0, 0x84, + 0x75, 0xd5, 0x9d, 0x3b, 0x43, 0x69, 0xbf, 0x14, 0x0e, 0xf1, 0xa3, 0x7c, 0xa9, 0xd2, 0xac, 0x1a, + 0xdf, 0x83, 0x02, 0xad, 0x8e, 0x20, 0x42, 0x5c, 0xbb, 0x8c, 0x24, 0x42, 0x84, 0xb6, 0xa0, 0xe8, + 0xf2, 0xf0, 0xc2, 0xf3, 0x5f, 0x28, 0x7b, 0xad, 0xfc, 0x34, 0x7e, 0x8a, 0x86, 0x86, 0xc8, 0x19, + 0x4d, 0x3a, 0x93, 0x20, 0x0f, 0xda, 0xde, 0xe0, 0xcc, 0x96, 0xb6, 0x8f, 0x12, 0x02, 0x7a, 0x67, + 0xf6, 0x1c, 0x79, 0x64, 0xe7, 0xfd, 0xd1, 0x6f, 0x43, 0x5d, 0xb9, 0xbf, 0x03, 0x6b, 0xc4, 0x4f, + 0x42, 0x49, 0xee, 0x55, 0xe9, 0xfb, 0x0e, 0x76, 0xf9, 0x49, 0x68, 0xec, 0xc1, 0xa2, 0x24, 0xc8, + 0x83, 0x09, 0x57, 0x5d, 0x7f, 0x3f, 0x4d, 0x66, 0xad, 0x3c, 0x5d, 0x4a, 0x5e, 0x66, 0xe4, 0xd6, + 0x4f, 0x08, 0xb2, 0xc6, 0xc7, 0xc0, 0xf4, 0xab, 0x4e, 0xb6, 0x27, 0x25, 0x47, 0x65, 0xe6, 0x56, + 0xde, 0xa2, 0x48, 0x3e, 0x75, 0x86, 0x62, 0x75, 0x82, 0xe9, 0x60, 0xa0, 0xc2, 0x12, 0x4a, 0xa6, + 0xfa, 0x34, 0xfe, 0x24, 0x03, 0x4b, 0xd8, 0x98, 0x92, 0xb9, 0xa5, 0x34, 0xf1, 0xb5, 0x07, 0x29, + 0xf6, 0x47, 0x97, 0x2f, 0xe8, 0xe3, 0xab, 0x1b, 0x16, 0xf3, 0x73, 0x86, 0xc5, 0x6f, 0x42, 0x73, + 0xc8, 0x47, 0x0e, 0x46, 0xa8, 0xa8, 0xeb, 0x9a, 0xa4, 0xec, 0x86, 0x82, 0x2b, 0x45, 0xe9, 0x9f, + 0x65, 0x60, 0x91, 0xa4, 0x01, 0x54, 0x39, 0xe5, 0x42, 0x7d, 0xa4, 0x74, 0x2c, 0xc9, 0xaa, 0xe4, + 0x9c, 0xe2, 0x5b, 0x12, 0xa1, 0x84, 0xbc, 0x73, 0x43, 0xea, 0x5e, 0x12, 0xca, 0x3e, 0x44, 0x3d, + 0xc1, 0xb5, 0x10, 0x98, 0x12, 0xf1, 0x92, 0xdc, 0x94, 0x9d, 0x1b, 0xa8, 0x44, 0xb8, 0x08, 0xda, + 0x28, 0x09, 0xa5, 0x4f, 0x80, 0x8d, 0x6d, 0xa8, 0x25, 0xba, 0x49, 0x58, 0x3f, 0xab, 0x64, 0xfd, + 0x9c, 0xf3, 0x30, 0x64, 0xe7, 0x3d, 0x0c, 0x7f, 0x2f, 0x0f, 0x4c, 0x90, 0xd4, 0xcc, 0xae, 0xcd, + 0xb8, 0xe7, 0xb2, 0x73, 0xee, 0xb9, 0x27, 0xc0, 0x34, 0x04, 0xe5, 0x35, 0xcc, 0x45, 0x5e, 0xc3, + 0x66, 0x8c, 0x2b, 0x9d, 0x86, 0x4f, 0x60, 0x59, 0x0a, 0x8d, 0x91, 0x3f, 0x0e, 0xcd, 0x5a, 0xb4, + 0x3f, 0x8c, 0xa4, 0x47, 0xe5, 0x97, 0x43, 0x13, 0x97, 0x72, 0xcd, 0x09, 0xb5, 0x9c, 0xac, 0x41, + 0xe8, 0x9a, 0x13, 0x9a, 0xf8, 0x0c, 0x15, 0x2c, 0xbc, 0x92, 0x0a, 0x8a, 0x73, 0x54, 0xa0, 0x19, + 0x27, 0x4a, 0x49, 0xe3, 0x84, 0x01, 0x35, 0xe5, 0x80, 0xa3, 0xb8, 0x03, 0x92, 0x90, 0x2a, 0xd2, + 0x0b, 0x87, 0xb1, 0x07, 0x0f, 0xa0, 0xa9, 0x2c, 0x08, 0x91, 0xf9, 0x83, 0x7c, 0xea, 0xd2, 0x00, + 0xb5, 0xa9, 0x8c, 0x20, 0x09, 0x63, 0x73, 0x65, 0xc6, 0xd8, 0xfc, 0x2e, 0x2c, 0x06, 0x82, 0x88, + 0xac, 0xa9, 0x2b, 0x03, 0x60, 0xf8, 0x10, 0xd5, 0x93, 0x92, 0xd9, 0xc4, 0x82, 0xa3, 0x18, 0x3e, + 0xaf, 0xda, 0xd7, 0xe6, 0x55, 0x7b, 0xf6, 0x7e, 0xec, 0xab, 0x0a, 0xce, 0x9c, 0x31, 0x5e, 0xdc, + 0x71, 0xb0, 0x88, 0x5c, 0xe0, 0xde, 0x99, 0x33, 0x36, 0x95, 0x63, 0x54, 0x7c, 0x18, 0xff, 0x25, + 0x03, 0x4d, 0x41, 0x07, 0x09, 0x3a, 0xff, 0x15, 0xc0, 0x13, 0xf9, 0x9a, 0x64, 0x5e, 0x11, 0xb8, + 0x8a, 0xca, 0xbf, 0x07, 0x48, 0xb6, 0x96, 0xd0, 0xc5, 0x24, 0x91, 0xb7, 0x92, 0x44, 0x1e, 0x33, + 0xb2, 0x9d, 0x1b, 0x24, 0x64, 0x0b, 0x48, 0x9a, 0x8f, 0x30, 0x9f, 0xe2, 0x23, 0xd4, 0x8e, 0xc2, + 0x0e, 0xc0, 0x73, 0x7e, 0xb5, 0xeb, 0x0d, 0x50, 0x0b, 0xba, 0x03, 0x20, 0x08, 0xf2, 0xc4, 0x1e, + 0x3b, 0xd2, 0x82, 0x51, 0x30, 0xcb, 0x2f, 0xf8, 0xd5, 0x36, 0x02, 0xc4, 0x6e, 0x88, 0xe2, 0xf8, + 0x3c, 0x14, 0xcc, 0xd2, 0x0b, 0x7e, 0x45, 0x87, 0xc1, 0x82, 0xda, 0x73, 0x7e, 0xb5, 0xc5, 0x49, + 0x5c, 0xf3, 0x7c, 0x41, 0x09, 0xbe, 0x7d, 0x21, 0xe4, 0xb3, 0x84, 0x7f, 0xaf, 0xe2, 0xdb, 0x17, + 0xcf, 0xf9, 0x95, 0xf2, 0x35, 0x16, 0x45, 0xf9, 0xc8, 0x1b, 0xc8, 0x1b, 0x48, 0x45, 0x2a, 0xc4, + 0x83, 0x32, 0x17, 0x5e, 0xe0, 0xdf, 0xc6, 0x1f, 0x67, 0xa0, 0x26, 0xc6, 0x8f, 0x0c, 0x4e, 0xac, + 0xbb, 0x0a, 0x78, 0xc9, 0xc4, 0x01, 0x2f, 0x4f, 0x25, 0x7f, 0x20, 0x6e, 0x99, 0xbd, 0x9e, 0x5b, + 0xe2, 0x02, 0x13, 0xab, 0x7c, 0x0f, 0xca, 0x74, 0xb6, 0xc4, 0x61, 0xcd, 0x25, 0x76, 0x29, 0x31, + 0x21, 0xb3, 0x84, 0x68, 0xcf, 0xc9, 0xbf, 0xae, 0x19, 0xb1, 0x68, 0x89, 0xcb, 0x7e, 0x64, 0xba, + 0x4a, 0xd9, 0x86, 0x42, 0x9a, 0xab, 0xf6, 0x08, 0x2a, 0x1a, 0x4d, 0xa1, 0xc5, 0x2b, 0x1a, 0x3c, + 0x11, 0x60, 0x92, 0x68, 0x12, 0xb3, 0xdf, 0xb9, 0x61, 0xd6, 0x06, 0x3a, 0x60, 0x63, 0x01, 0xf2, + 0xa2, 0x92, 0xf1, 0x11, 0x2c, 0x6a, 0xcd, 0x92, 0xc6, 0x97, 0x36, 0xa6, 0x4c, 0xda, 0x98, 0xfe, + 0x79, 0x06, 0x96, 0x65, 0x6d, 0x0c, 0x8e, 0x72, 0xc4, 0x75, 0xbd, 0x17, 0x9c, 0xb2, 0x5f, 0x81, + 0x9a, 0x68, 0xdd, 0xf2, 0xf9, 0xa9, 0x13, 0x84, 0x5c, 0x79, 0x07, 0x52, 0x0e, 0x87, 0xe0, 0xda, + 0x02, 0xd5, 0x94, 0x98, 0xec, 0x23, 0xa8, 0x60, 0x55, 0xd2, 0x49, 0xe5, 0xb6, 0xb4, 0xe6, 0x2b, + 0xd2, 0x50, 0x77, 0x6e, 0x98, 0x10, 0x44, 0x5f, 0x1b, 0x65, 0x28, 0x86, 0xbe, 0x73, 0x7a, 0xca, + 0x7d, 0x63, 0x35, 0x1a, 0x9a, 0x38, 0x69, 0xbc, 0x17, 0xf2, 0x89, 0x10, 0x82, 0x8c, 0xff, 0x96, + 0x81, 0x8a, 0x3c, 0x3b, 0x5f, 0xdb, 0x25, 0xb0, 0xae, 0x45, 0xf7, 0x91, 0xfa, 0x19, 0x07, 0xf3, + 0xdd, 0x87, 0xc6, 0x58, 0x08, 0x44, 0x42, 0x60, 0x4f, 0xf8, 0x03, 0xea, 0x0a, 0x2c, 0xe5, 0x91, + 0x47, 0xb0, 0x84, 0xe2, 0x49, 0x60, 0x85, 0xce, 0xc8, 0x52, 0x85, 0x32, 0x92, 0x6e, 0x91, 0x8a, + 0xfa, 0xce, 0x68, 0x4f, 0x16, 0x88, 0x5b, 0x3a, 0x08, 0xed, 0x53, 0x2e, 0x45, 0x5f, 0xfa, 0x30, + 0x5a, 0xb0, 0x3a, 0x23, 0xab, 0x2b, 0x3d, 0xe3, 0x1f, 0xd6, 0x60, 0x6d, 0xae, 0x48, 0xea, 0x1b, + 0x91, 0x1d, 0x7c, 0xe4, 0x8c, 0x8f, 0xbd, 0xc8, 0xdc, 0x94, 0xd1, 0xec, 0xe0, 0xbb, 0xa2, 0x44, + 0x99, 0x9b, 0x38, 0xac, 0x28, 0x82, 0x40, 0x7b, 0x51, 0x24, 0xce, 0x67, 0x51, 0xd8, 0x7c, 0x2f, + 0xc9, 0xa8, 0x66, 0xbb, 0x53, 0x70, 0xfd, 0xfa, 0x5b, 0x9a, 0xcc, 0xc1, 0x02, 0x76, 0x02, 0xad, + 0x88, 0xee, 0xa4, 0x7c, 0xa4, 0xe9, 0x26, 0xa2, 0xa7, 0x6f, 0xbd, 0xa2, 0xa7, 0x84, 0x21, 0xc2, + 0x5c, 0x55, 0xe4, 0x4a, 0x8d, 0x45, 0xfd, 0x9c, 0xc3, 0x1b, 0xaa, 0x1f, 0x94, 0x75, 0xe6, 0x7b, + 0xcb, 0xbf, 0xd6, 0xbc, 0xd0, 0xc0, 0x92, 0xec, 0xf2, 0x96, 0x6c, 0x38, 0x2a, 0xd2, 0xfb, 0x3d, + 0x83, 0xd5, 0x0b, 0xdb, 0x09, 0xd5, 0xfc, 0x34, 0xb5, 0xa8, 0x80, 0xfd, 0x3d, 0x7d, 0x45, 0x7f, + 0x9f, 0x52, 0xe5, 0x84, 0xf4, 0xb7, 0x7c, 0x31, 0x0f, 0x0c, 0xd6, 0xff, 0x53, 0x16, 0xea, 0xc9, + 0x56, 0xc4, 0xa1, 0x96, 0x7c, 0x48, 0xc9, 0x13, 0x52, 0x1e, 0x97, 0x66, 0xd0, 0x7d, 0x92, 0x23, + 0xe6, 0x0d, 0xb4, 0xd9, 0x14, 0x03, 0xad, 0x6e, 0x17, 0xcd, 0xbd, 0xca, 0x7f, 0x94, 0x7f, 0x2d, + 0xff, 0x51, 0x21, 0xcd, 0x7f, 0x74, 0xbd, 0xd3, 0x61, 0xe1, 0x6b, 0x39, 0x1d, 0x8a, 0xd7, 0x3b, + 0x1d, 0xd6, 0xff, 0x3a, 0x03, 0x6c, 0x9e, 0x52, 0xd9, 0x33, 0xb2, 0x45, 0xbb, 0x7c, 0x24, 0xb9, + 0xd8, 0xb7, 0x5f, 0x8f, 0xda, 0xd5, 0x06, 0xa9, 0xda, 0xec, 0x31, 0x2c, 0xe9, 0xb1, 0xb7, 0xba, + 0xaa, 0x52, 0x33, 0x99, 0x5e, 0x14, 0x2b, 0xb4, 0x9a, 0xf3, 0x2c, 0xff, 0x4a, 0xe7, 0x59, 0xe1, + 0x95, 0xce, 0xb3, 0x85, 0xa4, 0xf3, 0x6c, 0xfd, 0xef, 0x64, 0x60, 0x29, 0x85, 0xa8, 0x7e, 0x71, + 0x73, 0x16, 0xb4, 0x90, 0x60, 0x31, 0x59, 0x49, 0x0b, 0x1a, 0x77, 0x59, 0xff, 0x02, 0x6a, 0x89, + 0x43, 0xf4, 0x8b, 0xeb, 0x7e, 0x56, 0xd1, 0x22, 0x52, 0xd6, 0x15, 0xad, 0xf5, 0xbf, 0xcc, 0x02, + 0x9b, 0x3f, 0xc7, 0xbf, 0xcc, 0x21, 0xcc, 0x2f, 0x52, 0x6e, 0x7e, 0x91, 0xfe, 0xdf, 0xdd, 0x2b, + 0xef, 0xc2, 0xa2, 0xcc, 0x17, 0xd0, 0x1c, 0x0f, 0x44, 0x28, 0xcd, 0xa8, 0x40, 0x8d, 0xe2, 0x7b, + 0xb3, 0x7e, 0xcb, 0x52, 0x22, 0x44, 0x5a, 0xbb, 0x58, 0x93, 0xee, 0x4b, 0x63, 0x1d, 0x5a, 0x72, + 0x69, 0xe6, 0x4d, 0x75, 0xbf, 0x93, 0x8f, 0xb4, 0x64, 0x2c, 0x94, 0x42, 0xf1, 0x77, 0xa0, 0xaa, + 0x5f, 0x36, 0x72, 0x1f, 0x66, 0x3c, 0x4e, 0x42, 0x1c, 0xf6, 0xb4, 0xd3, 0xba, 0x09, 0xe4, 0x47, + 0x18, 0x46, 0xd5, 0x48, 0x82, 0x78, 0x89, 0xe1, 0x19, 0x85, 0xa3, 0xc4, 0xe6, 0xff, 0x7f, 0x50, + 0x4f, 0xda, 0xad, 0xa4, 0xa8, 0x97, 0x26, 0x1d, 0x8a, 0xda, 0x09, 0x43, 0x16, 0xfb, 0x21, 0x34, + 0x67, 0xed, 0x5e, 0x32, 0x7e, 0xf3, 0x9a, 0xfa, 0x0d, 0x27, 0x69, 0x0a, 0x63, 0x3b, 0xb0, 0x9c, + 0x76, 0xdd, 0xe2, 0xae, 0x5c, 0xaf, 0x16, 0xb0, 0xf9, 0x2b, 0x95, 0x7d, 0x5f, 0x9a, 0x37, 0x0b, + 0x69, 0x8e, 0x18, 0x6d, 0xb1, 0x1f, 0xd1, 0x7f, 0x9a, 0xa1, 0xf3, 0x1c, 0x20, 0x86, 0xb1, 0x26, + 0x54, 0x0f, 0x0e, 0x3b, 0xfb, 0xd6, 0xe6, 0x4e, 0x7b, 0x7f, 0xbf, 0xb3, 0xdb, 0xbc, 0xc1, 0x18, + 0xd4, 0xd1, 0x83, 0xb2, 0x15, 0xc1, 0x32, 0x02, 0x26, 0x6d, 0xbf, 0x0a, 0x96, 0x65, 0xcb, 0xd0, + 0xec, 0xee, 0xcf, 0x40, 0x73, 0xac, 0x05, 0xcb, 0x87, 0x1d, 0x72, 0xba, 0x24, 0xda, 0xcd, 0x0b, + 0x11, 0x4e, 0x4e, 0x57, 0x88, 0x70, 0x94, 0x6d, 0x22, 0xa9, 0x4f, 0x49, 0x36, 0xbf, 0x9b, 0x81, + 0x95, 0x99, 0x82, 0x38, 0x86, 0x98, 0xe4, 0x9a, 0xa4, 0x44, 0x53, 0x45, 0xa0, 0xa2, 0xe1, 0x77, + 0x61, 0x31, 0x52, 0xf5, 0x66, 0xf8, 0x52, 0x33, 0x2a, 0x50, 0xc8, 0x8f, 0x61, 0x49, 0xd3, 0x18, + 0x67, 0x4e, 0x28, 0xd3, 0x8a, 0x64, 0x05, 0x63, 0x2d, 0x8a, 0xd5, 0x9c, 0x19, 0xf5, 0x90, 0x52, + 0x58, 0xf4, 0x82, 0xd8, 0xfa, 0x9b, 0x1c, 0xaf, 0xfa, 0x14, 0xaa, 0x7c, 0x82, 0x10, 0x92, 0xa3, + 0xd5, 0x37, 0x5c, 0x75, 0xff, 0xfb, 0x0b, 0xc0, 0x3e, 0x9e, 0x72, 0xff, 0x0a, 0x63, 0x84, 0x83, + 0x57, 0x05, 0xcd, 0x28, 0xb5, 0x28, 0xfb, 0x5a, 0x79, 0x00, 0x69, 0x71, 0xf8, 0xf9, 0x57, 0xc7, + 0xe1, 0x17, 0x5e, 0x15, 0x87, 0xff, 0x16, 0xd4, 0x9c, 0x53, 0xd7, 0x13, 0x0c, 0x48, 0xc8, 0x26, + 0x41, 0x6b, 0xe1, 0x5e, 0xee, 0x41, 0xd5, 0xac, 0x4a, 0xa0, 0x90, 0x4c, 0x02, 0xf6, 0x51, 0x8c, + 0xc4, 0x87, 0xa7, 0x98, 0x33, 0xa2, 0xb3, 0x9e, 0xce, 0xf0, 0x94, 0x4b, 0x2d, 0x10, 0xed, 0x22, + 0xaa, 0xb2, 0x80, 0x07, 0xec, 0x6d, 0xa8, 0x07, 0xde, 0x54, 0x88, 0x7a, 0x6a, 0x19, 0xc8, 0x3e, + 0x5c, 0x25, 0xe8, 0xa1, 0x72, 0x06, 0x2c, 0x4d, 0x03, 0x6e, 0x8d, 0x9d, 0x20, 0x10, 0x17, 0xf4, + 0xc0, 0x73, 0x43, 0xdf, 0x1b, 0x49, 0x93, 0xef, 0xe2, 0x34, 0xe0, 0x7b, 0x54, 0xb2, 0x49, 0x05, + 0xec, 0xbb, 0xf1, 0x90, 0x26, 0xb6, 0xe3, 0x07, 0x2d, 0xc0, 0x21, 0xa9, 0x99, 0xa2, 0x44, 0x65, + 0x3b, 0x7e, 0x34, 0x16, 0xf1, 0x11, 0xcc, 0xe4, 0x07, 0x54, 0x66, 0xf3, 0x03, 0x7e, 0x92, 0x9e, + 0x1f, 0x50, 0xc3, 0xa6, 0x9f, 0xc8, 0xa6, 0xe7, 0xb7, 0xf8, 0x2b, 0xa5, 0x09, 0xcc, 0xa7, 0x3d, + 0xd4, 0xbf, 0x4a, 0xda, 0x43, 0x23, 0x2d, 0xed, 0xe1, 0x3d, 0xa8, 0x60, 0x40, 0xba, 0x75, 0xe6, + 0xb8, 0xa1, 0x32, 0x61, 0x37, 0xf5, 0x88, 0xf5, 0x1d, 0xa1, 0x4c, 0x83, 0xaf, 0xfe, 0x0c, 0xe6, + 0x33, 0x10, 0x16, 0x7f, 0x89, 0x19, 0x08, 0x32, 0x70, 0xfe, 0x11, 0x94, 0xd4, 0x3e, 0x31, 0x06, + 0xf9, 0x13, 0xdf, 0x1b, 0x2b, 0xd3, 0x9e, 0xf8, 0x9b, 0xd5, 0x21, 0x1b, 0x7a, 0xb2, 0x72, 0x36, + 0xf4, 0x8c, 0xdf, 0x80, 0x8a, 0x46, 0x6a, 0xec, 0x4d, 0x32, 0x22, 0x08, 0x69, 0x59, 0x6a, 0xc9, + 0xb4, 0x8a, 0x65, 0x09, 0xed, 0x0e, 0x05, 0xbf, 0x19, 0x3a, 0x3e, 0xc7, 0x5c, 0x21, 0xcb, 0xe7, + 0xe7, 0xdc, 0x0f, 0x94, 0xa9, 0xb5, 0x19, 0x15, 0x98, 0x04, 0x37, 0xfe, 0x26, 0x2c, 0x25, 0xf6, + 0x56, 0xb2, 0x88, 0xb7, 0x61, 0x01, 0xd7, 0x4d, 0xb9, 0xc2, 0x92, 0x99, 0x00, 0xb2, 0x0c, 0x93, + 0x40, 0xc9, 0x4a, 0x6c, 0x4d, 0x7c, 0xef, 0x18, 0x3b, 0xc9, 0x98, 0x15, 0x09, 0x3b, 0xf4, 0xbd, + 0x63, 0xe3, 0xcf, 0x72, 0x90, 0xdb, 0xf1, 0x26, 0x7a, 0x84, 0x45, 0x66, 0x2e, 0xc2, 0x42, 0xaa, + 0x00, 0x56, 0x24, 0xe2, 0x4b, 0xa9, 0x0d, 0xed, 0xa3, 0x4a, 0xcc, 0x7f, 0x00, 0x75, 0xc1, 0x27, + 0x42, 0x4f, 0xe8, 0x50, 0x17, 0xb6, 0x4f, 0x79, 0x01, 0x39, 0x3a, 0x7c, 0xf6, 0x38, 0xec, 0x7b, + 0xdb, 0x04, 0x67, 0xcb, 0x90, 0x8b, 0x04, 0x58, 0x2c, 0x16, 0x9f, 0x42, 0xb9, 0xc6, 0x08, 0xb9, + 0x2b, 0xe9, 0xeb, 0x91, 0x5f, 0xec, 0xdb, 0xb0, 0x94, 0x6c, 0x97, 0x58, 0x91, 0x94, 0x48, 0xf4, + 0x86, 0x91, 0x27, 0xdd, 0x04, 0xc1, 0x47, 0x08, 0x47, 0xba, 0x65, 0x4f, 0x38, 0xc7, 0x22, 0x8d, + 0xe9, 0x95, 0x12, 0x4c, 0xef, 0x2e, 0x54, 0xc2, 0xd1, 0xb9, 0x35, 0xb1, 0xaf, 0x46, 0x9e, 0x3d, + 0x94, 0xe7, 0x1b, 0xc2, 0xd1, 0xf9, 0x21, 0x41, 0xd8, 0x63, 0x80, 0xf1, 0x64, 0x22, 0xcf, 0x1e, + 0x9a, 0x1b, 0x63, 0x52, 0xde, 0x3b, 0x3c, 0x24, 0x92, 0x33, 0xcb, 0xe3, 0xc9, 0x84, 0xfe, 0x64, + 0x5b, 0x50, 0x4f, 0xcd, 0xe7, 0xb9, 0xa3, 0x02, 0xba, 0xbc, 0xc9, 0xa3, 0x94, 0xc3, 0x59, 0x1b, + 0xe8, 0xb0, 0xf5, 0x1f, 0x02, 0xfb, 0x39, 0xb3, 0x6a, 0xfa, 0x50, 0x8e, 0xc6, 0xa7, 0x27, 0xa5, + 0x60, 0x88, 0x66, 0x25, 0x91, 0x94, 0xd2, 0x1e, 0x0e, 0x7d, 0xc1, 0x17, 0xe9, 0xc2, 0x8c, 0x58, + 0x3e, 0x68, 0x37, 0x66, 0x9b, 0xf8, 0xbe, 0xf1, 0x17, 0x19, 0x28, 0x50, 0x86, 0xcc, 0x3b, 0xd0, + 0x20, 0xfc, 0x28, 0x5a, 0x45, 0x7a, 0x88, 0xe8, 0xde, 0xed, 0xcb, 0x40, 0x15, 0x71, 0x2c, 0xb4, + 0xec, 0xbe, 0x6c, 0xb4, 0xf3, 0x5a, 0x86, 0xdf, 0x5d, 0x28, 0x47, 0x5d, 0x6b, 0xa4, 0x53, 0x52, + 0x3d, 0xb3, 0x37, 0x20, 0x7f, 0xe6, 0x4d, 0x94, 0x2e, 0x0e, 0xf1, 0x4a, 0x9a, 0x08, 0x8f, 0xc7, + 0x22, 0xfa, 0xa0, 0xc1, 0x4b, 0x1d, 0x32, 0xea, 0x04, 0xc9, 0x60, 0x7e, 0x8e, 0x0b, 0x29, 0x73, + 0x3c, 0x82, 0x86, 0xe0, 0x03, 0x9a, 0xa7, 0xf6, 0xfa, 0x4b, 0xf3, 0x9b, 0x42, 0xc2, 0x1b, 0x8c, + 0xa6, 0x43, 0xae, 0x5b, 0x42, 0x30, 0x74, 0x42, 0xc2, 0x95, 0x7a, 0x60, 0xfc, 0x7e, 0x86, 0xf8, + 0x8b, 0x68, 0x97, 0x3d, 0x80, 0xbc, 0xb8, 0xdf, 0x66, 0x2c, 0x75, 0x51, 0xac, 0xac, 0xc0, 0x33, + 0x11, 0x03, 0x53, 0x62, 0xa7, 0xe3, 0x64, 0xeb, 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0x31, 0xe1, + 0x1b, 0x6a, 0x5a, 0x33, 0x8a, 0x38, 0xcd, 0x3e, 0x3a, 0xa6, 0x8f, 0xb4, 0x18, 0x8c, 0x7c, 0xe2, + 0xc6, 0x54, 0x52, 0xe0, 0xf0, 0x94, 0x6b, 0xb1, 0x17, 0x7f, 0x98, 0x85, 0x5a, 0x62, 0x44, 0x18, + 0x84, 0x22, 0x2e, 0x00, 0xb2, 0x02, 0xcb, 0xfd, 0x06, 0x01, 0x92, 0x82, 0xba, 0xb6, 0x4e, 0xd9, + 0xc4, 0x3a, 0x45, 0x3e, 0xe9, 0x9c, 0xee, 0x93, 0x7e, 0x02, 0xe5, 0x38, 0xab, 0x33, 0x39, 0x24, + 0xd1, 0x9f, 0x8a, 0x18, 0x8e, 0x91, 0x62, 0x2f, 0x76, 0x41, 0xf7, 0x62, 0xff, 0x40, 0x73, 0x7a, + 0x2e, 0x60, 0x33, 0x46, 0xda, 0x8a, 0xfe, 0x72, 0x82, 0x22, 0x3e, 0x82, 0x8a, 0x36, 0x78, 0xdd, + 0xb9, 0x99, 0x49, 0x38, 0x37, 0xa3, 0xd8, 0xfe, 0x6c, 0x1c, 0xdb, 0x6f, 0xfc, 0x56, 0x16, 0x6a, + 0xe2, 0x7c, 0x39, 0xee, 0xe9, 0xa1, 0x37, 0x72, 0x06, 0x68, 0x15, 0x8e, 0x4e, 0x98, 0x14, 0xb4, + 0xd4, 0x39, 0x93, 0x47, 0x8c, 0xe4, 0x2c, 0x3d, 0x85, 0x89, 0x98, 0x74, 0x94, 0xc2, 0x64, 0x40, + 0x4d, 0x30, 0xc6, 0x63, 0x3b, 0xe0, 0x5a, 0xce, 0xa9, 0x59, 0x39, 0xe1, 0x7c, 0xc3, 0x0e, 0x88, + 0x43, 0x7e, 0x1b, 0x96, 0x04, 0x0e, 0x66, 0x6f, 0x8c, 0x9d, 0xd1, 0xc8, 0x21, 0x4c, 0x32, 0x35, + 0x34, 0x4f, 0x38, 0x37, 0xed, 0x90, 0xef, 0x89, 0x02, 0x99, 0xa2, 0x5a, 0x1a, 0x3a, 0x81, 0x7d, + 0x1c, 0x87, 0x0a, 0x45, 0xdf, 0xe8, 0xcb, 0xb1, 0x2f, 0x35, 0x5f, 0x0e, 0xa5, 0x71, 0x55, 0xc6, + 0xf6, 0x65, 0xe4, 0xcb, 0x99, 0xa1, 0xa4, 0xe2, 0x2c, 0x25, 0x19, 0xff, 0x35, 0x0b, 0x15, 0x8d, + 0x2c, 0x5f, 0xe7, 0x76, 0xbd, 0x33, 0x67, 0xc5, 0x2f, 0xeb, 0x06, 0xfb, 0xb7, 0x92, 0x5d, 0xa2, + 0xcb, 0x97, 0x92, 0x61, 0x35, 0x02, 0xbe, 0x05, 0x65, 0x71, 0xea, 0xde, 0x43, 0xa3, 0x98, 0x4c, + 0xe5, 0x46, 0xc0, 0xe1, 0xf4, 0x58, 0x15, 0x3e, 0xc5, 0xc2, 0x42, 0x5c, 0xf8, 0x54, 0x14, 0xbe, + 0x2c, 0x3e, 0xf0, 0x7b, 0x50, 0x95, 0xad, 0xe2, 0x9e, 0xe2, 0x74, 0xe3, 0x53, 0x9f, 0xd8, 0x6f, + 0xb3, 0x42, 0xdd, 0xd1, 0xe6, 0xcb, 0x8a, 0x4f, 0x55, 0xc5, 0xd2, 0xab, 0x2a, 0x3e, 0xa5, 0x0f, + 0x63, 0x3b, 0x0a, 0xb9, 0xc4, 0x70, 0x03, 0xc5, 0xc7, 0x1e, 0xc3, 0x92, 0x62, 0x57, 0x53, 0xd7, + 0x76, 0x5d, 0x6f, 0xea, 0x0e, 0xb8, 0x0a, 0xfa, 0x67, 0xb2, 0xe8, 0x28, 0x2e, 0x31, 0x86, 0x51, + 0x56, 0x18, 0x85, 0x2d, 0x3c, 0x84, 0x02, 0xc9, 0xe5, 0x24, 0x7c, 0xa4, 0x33, 0x2e, 0x42, 0x61, + 0x0f, 0xa0, 0x40, 0xe2, 0x79, 0xf6, 0x5a, 0x66, 0x43, 0x08, 0xc6, 0x23, 0x68, 0xa0, 0x88, 0xa9, + 0x71, 0xdc, 0x97, 0x49, 0x25, 0xc6, 0x32, 0xb0, 0x7d, 0x3a, 0x44, 0x7a, 0x38, 0xcd, 0xff, 0xc8, + 0x41, 0x45, 0x03, 0x0b, 0xb6, 0x88, 0x01, 0x18, 0xd6, 0xd0, 0xb1, 0xc7, 0x5c, 0xf9, 0x1e, 0x6a, + 0x66, 0x0d, 0xa1, 0x5b, 0x12, 0x28, 0x2e, 0x05, 0xfb, 0xfc, 0xd4, 0xf2, 0xa6, 0xa1, 0x35, 0xe4, + 0xa7, 0x3e, 0xe7, 0x52, 0x58, 0xaa, 0xda, 0xe7, 0xa7, 0x07, 0xd3, 0x70, 0x0b, 0x61, 0x02, 0x4b, + 0x10, 0xb5, 0x86, 0x25, 0x63, 0x06, 0xc6, 0xf6, 0x65, 0x8c, 0x25, 0x03, 0x57, 0x68, 0x89, 0xf2, + 0x51, 0xe0, 0x0a, 0xa9, 0x2d, 0xb3, 0x9c, 0xbc, 0x30, 0xcf, 0xc9, 0xbf, 0x0b, 0xab, 0xc4, 0xc9, + 0x25, 0x8f, 0xb0, 0x66, 0x48, 0x6a, 0x19, 0x4b, 0xe5, 0x24, 0x35, 0xf9, 0xab, 0x29, 0x66, 0xa0, + 0xce, 0x47, 0xe0, 0xfc, 0x94, 0x4e, 0x54, 0xc6, 0x14, 0x33, 0x93, 0x8d, 0xf7, 0x9c, 0x9f, 0x72, + 0x81, 0x89, 0x8e, 0x51, 0x1d, 0x53, 0x86, 0xa1, 0x8e, 0x1d, 0x77, 0x16, 0xd3, 0xbe, 0x4c, 0x62, + 0x96, 0x25, 0xa6, 0x7d, 0xa9, 0x63, 0xbe, 0x0f, 0x6b, 0x63, 0x3e, 0x74, 0xec, 0x64, 0xb3, 0x56, + 0x2c, 0x41, 0x2c, 0x53, 0xb1, 0x56, 0xa7, 0x47, 0x1a, 0xa4, 0x58, 0x8d, 0x9f, 0x7a, 0xe3, 0x63, + 0x87, 0x2e, 0x4f, 0x72, 0xd5, 0xe6, 0xcd, 0xba, 0x3b, 0x1d, 0xff, 0x18, 0xc1, 0xa2, 0x4a, 0x60, + 0xd4, 0xa0, 0xd2, 0x0b, 0xbd, 0x89, 0xda, 0xe6, 0x3a, 0x54, 0xe9, 0x53, 0xa6, 0x74, 0xdc, 0x82, + 0x9b, 0x48, 0x9b, 0x7d, 0x6f, 0xe2, 0x8d, 0xbc, 0xd3, 0xab, 0x84, 0x41, 0xe9, 0xbf, 0x67, 0x60, + 0x29, 0x51, 0x2a, 0xcf, 0xf9, 0x77, 0xe9, 0x60, 0x45, 0x71, 0xf9, 0x44, 0xce, 0x8b, 0xda, 0xe5, + 0x43, 0x88, 0x74, 0xaa, 0x54, 0xac, 0x7e, 0x3b, 0xce, 0x27, 0x55, 0x15, 0x89, 0xb6, 0x5b, 0xf3, + 0xb4, 0x2d, 0xeb, 0xab, 0x4c, 0x53, 0xd5, 0xc4, 0xff, 0x2f, 0x43, 0x85, 0x87, 0x72, 0xca, 0xb9, + 0x64, 0x30, 0xa4, 0x6e, 0x7c, 0x52, 0x23, 0x88, 0x2d, 0x52, 0x81, 0xf1, 0x6f, 0x32, 0x00, 0xf1, + 0xe8, 0x30, 0x1c, 0x33, 0xba, 0x40, 0xe9, 0xa9, 0x16, 0xed, 0xb2, 0x7c, 0x13, 0xaa, 0x51, 0xc4, + 0x58, 0x7c, 0x25, 0x57, 0x14, 0x4c, 0xdc, 0xcb, 0xf7, 0xa1, 0x71, 0x3a, 0xf2, 0x8e, 0x51, 0x74, + 0x92, 0x17, 0x28, 0x25, 0xb6, 0xd4, 0x09, 0xac, 0xae, 0xc5, 0xf8, 0x02, 0xcf, 0xa7, 0x06, 0x95, + 0xe9, 0xd7, 0xb1, 0xf1, 0xdb, 0xd9, 0x28, 0x74, 0x26, 0x5e, 0x89, 0x97, 0xeb, 0x19, 0x5f, 0xc7, + 0x03, 0xfb, 0x32, 0xcf, 0xc3, 0x47, 0x50, 0xf7, 0x89, 0x3b, 0x2a, 0xd6, 0x99, 0x7f, 0x09, 0xeb, + 0xac, 0xf9, 0x89, 0x2b, 0xf7, 0x9b, 0xd0, 0xb4, 0x87, 0xe7, 0xdc, 0x0f, 0x1d, 0x34, 0xd6, 0xa2, + 0xa0, 0x26, 0x83, 0x55, 0x34, 0x38, 0x4a, 0x44, 0xf7, 0xa1, 0x21, 0xd3, 0x8c, 0x22, 0x4c, 0xf9, + 0x70, 0x41, 0x0c, 0x16, 0x88, 0xc6, 0xbf, 0x57, 0xb1, 0x3a, 0xc9, 0xdd, 0x7d, 0xf9, 0xaa, 0xe8, + 0x33, 0xcc, 0xce, 0xfb, 0x56, 0x24, 0x21, 0x49, 0x1b, 0xb0, 0xe4, 0x47, 0x04, 0x94, 0x16, 0xe0, + 0xe4, 0xb2, 0xe6, 0x5f, 0x67, 0x59, 0x8d, 0x3f, 0xce, 0x40, 0x71, 0xc7, 0x9b, 0x08, 0xbd, 0x5c, + 0xc8, 0x73, 0x78, 0x4c, 0xa2, 0x14, 0xbf, 0x05, 0xf1, 0xd9, 0x1d, 0xbe, 0x3c, 0x2c, 0x3f, 0x55, + 0xde, 0xa8, 0x25, 0xe5, 0x8d, 0x1f, 0xc0, 0x2d, 0xf4, 0x46, 0xf8, 0xde, 0xc4, 0xf3, 0xc5, 0x51, + 0xb5, 0x47, 0x24, 0x77, 0x78, 0x6e, 0x78, 0xa6, 0x78, 0xe7, 0xcd, 0x13, 0xce, 0x0f, 0x35, 0x8c, + 0xbd, 0x08, 0x01, 0xf3, 0x55, 0x46, 0xe1, 0xb9, 0x45, 0xaa, 0xa2, 0x14, 0x8c, 0x88, 0xa3, 0x36, + 0x44, 0x41, 0x07, 0xe1, 0x28, 0x1a, 0x19, 0xdf, 0x87, 0x72, 0x64, 0x75, 0x60, 0xef, 0x42, 0xf9, + 0xcc, 0x9b, 0x48, 0xd3, 0x44, 0x26, 0x91, 0xba, 0x20, 0x67, 0x6d, 0x96, 0xce, 0xe8, 0x8f, 0xc0, + 0xf8, 0xb3, 0x22, 0x14, 0xbb, 0xee, 0xb9, 0xe7, 0x0c, 0x30, 0xda, 0x67, 0xcc, 0xc7, 0x9e, 0xca, + 0x75, 0x14, 0x7f, 0xa3, 0x47, 0x3f, 0x7e, 0x7e, 0x20, 0x27, 0x3d, 0xfa, 0xd1, 0xc3, 0x03, 0x2b, + 0xb0, 0xe0, 0xeb, 0xef, 0x07, 0x14, 0x7c, 0x8c, 0x3f, 0x8c, 0x94, 0xb6, 0x82, 0x96, 0x2b, 0x2a, + 0xda, 0xa2, 0xbc, 0x76, 0x5c, 0x32, 0xca, 0x3d, 0x29, 0x23, 0x04, 0x17, 0xec, 0x36, 0x14, 0x65, + 0xa6, 0x00, 0xc5, 0x5d, 0x53, 0xc0, 0xa0, 0x04, 0x21, 0x35, 0xf8, 0x9c, 0xbc, 0x49, 0x91, 0x44, + 0x25, 0xf4, 0x74, 0x09, 0xdc, 0x12, 0xb4, 0x76, 0x17, 0x2a, 0x84, 0x4f, 0x28, 0x25, 0x19, 0x9f, + 0x83, 0x20, 0x44, 0x48, 0x79, 0x86, 0xa3, 0x9c, 0xfa, 0x0c, 0x07, 0x86, 0x73, 0x45, 0x5c, 0x96, + 0xa6, 0x08, 0xf4, 0xf8, 0x82, 0x06, 0x57, 0x6f, 0xd0, 0x48, 0xe5, 0x9e, 0x52, 0xb1, 0x94, 0x72, + 0xff, 0x16, 0xd4, 0x4e, 0xec, 0xd1, 0xe8, 0xd8, 0x1e, 0xbc, 0x20, 0x9d, 0xb4, 0x4a, 0x66, 0x38, + 0x05, 0x44, 0xa5, 0xf4, 0x2e, 0x54, 0xb4, 0x5d, 0xc6, 0xe0, 0x9b, 0xbc, 0x09, 0xf1, 0xfe, 0xce, + 0x9a, 0x9a, 0xea, 0xaf, 0x61, 0x6a, 0xd2, 0x82, 0x90, 0x1a, 0xc9, 0x20, 0xa4, 0x5b, 0xc8, 0x4d, + 0x65, 0xa0, 0x4a, 0x93, 0x32, 0xfd, 0xed, 0xe1, 0x10, 0x03, 0x55, 0xe8, 0x59, 0x2d, 0x5c, 0x3c, + 0x2a, 0x5f, 0x24, 0xa1, 0x96, 0x60, 0x84, 0x72, 0x87, 0xec, 0xa5, 0x13, 0xdb, 0x19, 0x62, 0xd0, + 0x27, 0xa9, 0xb1, 0x45, 0x7b, 0x1c, 0x1e, 0xda, 0xce, 0x90, 0xdd, 0x83, 0xaa, 0x2a, 0xc6, 0xdb, + 0x71, 0x89, 0xd6, 0x5f, 0x16, 0x8b, 0x3b, 0xd1, 0x80, 0x5a, 0x84, 0x31, 0x8e, 0xf3, 0xa9, 0x2a, + 0x12, 0x05, 0xe9, 0xe0, 0x3d, 0x74, 0xfe, 0x87, 0x1c, 0xb3, 0xa6, 0xea, 0x4f, 0x6f, 0xc9, 0xb9, + 0x4a, 0x2a, 0x55, 0xff, 0x63, 0xa4, 0x83, 0x49, 0x98, 0x42, 0x10, 0x23, 0x17, 0xcd, 0x6a, 0x42, + 0x10, 0x93, 0xa8, 0xe8, 0xa2, 0x21, 0x04, 0xf6, 0x7d, 0x4d, 0x91, 0x6a, 0x21, 0xf2, 0xed, 0x99, + 0xf6, 0xaf, 0x51, 0xa1, 0x04, 0xf5, 0x3a, 0x81, 0xb8, 0x65, 0x02, 0xee, 0x0e, 0x31, 0x01, 0xaa, + 0x64, 0x96, 0x9d, 0xe0, 0x39, 0x01, 0x7e, 0xb1, 0x1a, 0x56, 0x1b, 0xaa, 0xfa, 0x34, 0x59, 0x09, + 0xf2, 0x07, 0x87, 0x9d, 0xfd, 0xe6, 0x0d, 0x56, 0x81, 0x62, 0xaf, 0xd3, 0xef, 0xef, 0x76, 0xb6, + 0x9a, 0x19, 0x56, 0x85, 0x52, 0x94, 0xc6, 0x91, 0x15, 0x5f, 0xed, 0xcd, 0xcd, 0xce, 0x61, 0xbf, + 0xb3, 0xd5, 0xcc, 0xfd, 0x28, 0x5f, 0xca, 0x36, 0x73, 0xc6, 0x9f, 0xe7, 0xa0, 0xa2, 0xad, 0xc2, + 0xcb, 0x99, 0xf1, 0x1d, 0x00, 0x54, 0x69, 0xe2, 0x38, 0xa6, 0xbc, 0x59, 0x16, 0x10, 0xda, 0x7c, + 0xdd, 0x58, 0x9e, 0xa3, 0x27, 0x24, 0x94, 0xb1, 0xfc, 0x2d, 0xa8, 0xd1, 0x6b, 0x0c, 0xba, 0xbb, + 0xae, 0x60, 0x56, 0x09, 0x28, 0x59, 0x35, 0xe6, 0x81, 0x21, 0x12, 0x66, 0x08, 0xc8, 0xdc, 0x6c, + 0x02, 0x61, 0x8e, 0x00, 0x26, 0x78, 0x04, 0xde, 0xe8, 0x9c, 0x13, 0x06, 0x49, 0x84, 0x15, 0x09, + 0xeb, 0xcb, 0x44, 0x34, 0xc9, 0x0f, 0xb5, 0x44, 0xa4, 0x82, 0x59, 0x25, 0xa0, 0xec, 0xe8, 0xdb, + 0x8a, 0x80, 0x4a, 0x48, 0x40, 0x6b, 0xf3, 0xd4, 0x90, 0x20, 0x9e, 0xdd, 0x39, 0x7b, 0x56, 0x19, + 0x09, 0xe3, 0x1b, 0xf3, 0xf5, 0x5e, 0x6d, 0xd7, 0x62, 0xef, 0x02, 0x1b, 0x4f, 0x26, 0x56, 0x8a, + 0xa5, 0x29, 0x6f, 0x36, 0xc6, 0x93, 0x49, 0x5f, 0x33, 0xc4, 0xfc, 0x02, 0x8c, 0x60, 0x9f, 0x03, + 0x6b, 0x8b, 0x03, 0x8c, 0x43, 0x8c, 0x4c, 0xa8, 0x31, 0x5b, 0xce, 0xe8, 0x6c, 0x39, 0x85, 0xfb, + 0x65, 0x53, 0xb9, 0xdf, 0xcb, 0xf8, 0x84, 0xb1, 0x0d, 0x95, 0x43, 0xed, 0xad, 0x97, 0x7b, 0xe2, + 0x86, 0x50, 0xaf, 0xbc, 0xd0, 0xdd, 0x41, 0xc6, 0x2d, 0x5f, 0x3e, 0xee, 0xa2, 0x8d, 0x26, 0xab, + 0x8d, 0xc6, 0xf8, 0xd7, 0x19, 0xca, 0xa3, 0x8f, 0x06, 0x1f, 0x3f, 0x2f, 0xa3, 0xfc, 0x40, 0x71, + 0xbe, 0x60, 0x45, 0xf9, 0x7f, 0x64, 0xaa, 0x1f, 0x0e, 0xcd, 0xf2, 0x4e, 0x4e, 0x02, 0xae, 0x32, + 0x5f, 0x2a, 0x08, 0x3b, 0x40, 0x90, 0x12, 0xbe, 0x85, 0x84, 0xef, 0x50, 0xfb, 0x81, 0xcc, 0x80, + 0x11, 0xc2, 0xf7, 0x9e, 0x7d, 0x29, 0x7b, 0x0d, 0x84, 0x08, 0x22, 0x0d, 0xd5, 0x2a, 0xdf, 0x27, + 0xfa, 0x36, 0xfe, 0x85, 0x4c, 0x69, 0x9c, 0x5d, 0xdf, 0x87, 0x50, 0x8a, 0x5a, 0x4d, 0xde, 0xb0, + 0x0a, 0x33, 0x2a, 0x17, 0xf7, 0x38, 0x6a, 0xe5, 0x89, 0x11, 0xd3, 0xe1, 0x42, 0x67, 0x43, 0x57, + 0x1b, 0xf5, 0xb7, 0x80, 0x9d, 0x38, 0xfe, 0x2c, 0x32, 0x1d, 0xb6, 0x26, 0x96, 0x68, 0xd8, 0xc6, + 0x11, 0x2c, 0x29, 0x2e, 0xa1, 0x69, 0x04, 0xc9, 0xcd, 0xcb, 0xbc, 0x82, 0xc9, 0x67, 0xe7, 0x98, + 0xbc, 0xf1, 0xb3, 0x3c, 0x14, 0xd5, 0xbb, 0x49, 0x69, 0x6f, 0xfd, 0x94, 0x93, 0x6f, 0xfd, 0xb4, + 0x12, 0xef, 0x42, 0xe0, 0xd6, 0xcb, 0xfb, 0xfe, 0xfe, 0xec, 0x95, 0xad, 0x19, 0xcd, 0x13, 0xd7, + 0xf6, 0x2a, 0xe4, 0x27, 0x76, 0x78, 0x86, 0x06, 0x32, 0x22, 0x1e, 0xfc, 0x56, 0xc6, 0xf4, 0x42, + 0xd2, 0x98, 0x9e, 0xf6, 0x2e, 0x12, 0x89, 0xa4, 0x73, 0xef, 0x22, 0xdd, 0x02, 0x92, 0x2f, 0xb4, + 0x78, 0x98, 0x12, 0x02, 0xc4, 0x5d, 0x94, 0x14, 0x47, 0x4a, 0xb3, 0xe2, 0xc8, 0x6b, 0x8b, 0x0a, + 0xdf, 0x85, 0x05, 0xca, 0x29, 0x96, 0x79, 0x4d, 0xea, 0x42, 0x91, 0x6b, 0xa8, 0xfe, 0xa7, 0x20, + 0x58, 0x53, 0xe2, 0xea, 0x8f, 0x8c, 0x54, 0x12, 0x8f, 0x8c, 0xe8, 0x46, 0xfe, 0x6a, 0xd2, 0xc8, + 0xff, 0x00, 0x9a, 0xd1, 0x82, 0xa2, 0xc9, 0xcc, 0x0d, 0x64, 0x46, 0x47, 0x5d, 0xc1, 0x05, 0x97, + 0xdc, 0x0f, 0xe2, 0x0b, 0xb1, 0x9e, 0xb8, 0x10, 0x05, 0x0f, 0x6b, 0x87, 0x21, 0x1f, 0x4f, 0x42, + 0x79, 0x21, 0x62, 0xcc, 0xb7, 0x3e, 0xc0, 0x64, 0xc6, 0x5f, 0x0d, 0xca, 0xdd, 0x7d, 0x6b, 0x7b, + 0xb7, 0xfb, 0x6c, 0xa7, 0xdf, 0xcc, 0x88, 0xcf, 0xde, 0xd1, 0xe6, 0x66, 0xa7, 0xb3, 0x85, 0x37, + 0x0e, 0xc0, 0xc2, 0x76, 0xbb, 0x2b, 0x6e, 0x9f, 0x9c, 0xf1, 0xbb, 0x59, 0xa8, 0x68, 0xcd, 0xb3, + 0xf7, 0xa3, 0x55, 0xa1, 0x77, 0x28, 0xee, 0xcc, 0x0f, 0xe1, 0x91, 0x62, 0xc5, 0xda, 0xb2, 0x44, + 0xaf, 0x40, 0x65, 0xaf, 0x7d, 0x05, 0x8a, 0xbd, 0x03, 0x0d, 0x9b, 0x5a, 0x88, 0x56, 0x41, 0x9a, + 0x83, 0x25, 0x58, 0x2e, 0x02, 0x46, 0x81, 0xc5, 0xf7, 0x89, 0xc0, 0xcb, 0xab, 0xc0, 0xab, 0xe8, + 0x4a, 0xc1, 0xc5, 0x2a, 0x9e, 0xd8, 0xce, 0x68, 0xea, 0x73, 0xe9, 0xbe, 0x8d, 0x6e, 0x66, 0x82, + 0x9a, 0xaa, 0xd8, 0xf8, 0x00, 0x20, 0x1e, 0x73, 0x72, 0x71, 0x6e, 0x24, 0x17, 0x27, 0xa3, 0x2d, + 0x4e, 0xd6, 0xd8, 0x22, 0x36, 0x22, 0x17, 0x3a, 0xf2, 0x54, 0x7f, 0x1b, 0x94, 0x45, 0xca, 0xc2, + 0x38, 0xcc, 0xc9, 0x88, 0x87, 0x2a, 0x37, 0x72, 0x51, 0x96, 0x74, 0xa3, 0x02, 0x95, 0xaa, 0x1c, + 0xb7, 0x12, 0x73, 0x23, 0x49, 0x92, 0xb3, 0xdc, 0x48, 0xa2, 0x9a, 0x51, 0xb9, 0xb1, 0x0e, 0xad, + 0x2d, 0x2e, 0x5a, 0x6b, 0x8f, 0x46, 0x33, 0xc3, 0x31, 0x6e, 0xc1, 0xcd, 0x94, 0x32, 0x69, 0x84, + 0xf8, 0x18, 0x56, 0xda, 0x94, 0x06, 0xf9, 0x8b, 0xca, 0xc5, 0x30, 0x5a, 0xb0, 0x3a, 0xdb, 0xa4, + 0xec, 0x6c, 0x1b, 0x16, 0xb7, 0xf8, 0xf1, 0xf4, 0x74, 0x97, 0x9f, 0xc7, 0x1d, 0x31, 0xc8, 0x07, + 0x67, 0xde, 0x85, 0x5c, 0x1f, 0xfc, 0x5b, 0x9c, 0xe1, 0x91, 0xc0, 0xb1, 0x82, 0x09, 0x1f, 0x28, + 0x8b, 0x28, 0x42, 0x7a, 0x13, 0x3e, 0x30, 0xde, 0x07, 0xa6, 0xb7, 0x23, 0xd7, 0x4b, 0x68, 0x09, + 0xd3, 0x63, 0x2b, 0xb8, 0x0a, 0x42, 0x3e, 0x56, 0xcf, 0x9c, 0x40, 0x30, 0x3d, 0xee, 0x11, 0xc4, + 0xb8, 0x0f, 0xd5, 0x43, 0xfb, 0xca, 0xe4, 0x9f, 0xcb, 0x2c, 0x83, 0x35, 0x28, 0x4e, 0xec, 0x2b, + 0xc1, 0x06, 0x22, 0xe7, 0x08, 0x16, 0x1b, 0x7f, 0x90, 0x87, 0x05, 0xc2, 0x64, 0xf7, 0xe8, 0x25, + 0x42, 0xc7, 0xc5, 0x63, 0xa8, 0x18, 0xa5, 0x06, 0x9a, 0xe3, 0xa5, 0xd9, 0x79, 0x5e, 0x2a, 0x0d, + 0x68, 0xea, 0x05, 0x06, 0x65, 0xc6, 0x76, 0xa7, 0x63, 0xf5, 0xec, 0x02, 0xbb, 0x0d, 0xe5, 0x38, + 0x9d, 0x2b, 0x1f, 0xbf, 0x34, 0x49, 0x49, 0x5c, 0x49, 0x47, 0x63, 0xac, 0x8b, 0xd0, 0xe8, 0xd4, + 0x15, 0x21, 0xd9, 0xa5, 0x0e, 0x4a, 0x55, 0x78, 0x8a, 0x2a, 0x7f, 0x25, 0xa9, 0xf0, 0xcc, 0x29, + 0x36, 0xa5, 0x57, 0x2b, 0x36, 0x64, 0x59, 0x7b, 0x89, 0x62, 0x03, 0xaf, 0xa1, 0xd8, 0xbc, 0x86, + 0x93, 0xef, 0x26, 0x94, 0xf0, 0xde, 0xd7, 0xb8, 0xa7, 0xb8, 0xef, 0x05, 0xf7, 0xfc, 0x9e, 0x26, + 0xfa, 0x53, 0x84, 0xc1, 0xad, 0xf8, 0x98, 0x98, 0xfc, 0xf3, 0x5f, 0x8e, 0xf3, 0xe4, 0x33, 0x28, + 0x4a, 0xa8, 0x20, 0x68, 0xd7, 0x1e, 0xab, 0x47, 0x6c, 0xf0, 0x6f, 0xb1, 0x6c, 0xf8, 0xf2, 0xc6, + 0xe7, 0x53, 0xc7, 0xe7, 0x43, 0xf5, 0xcc, 0x81, 0x83, 0x67, 0x54, 0x40, 0xc4, 0x04, 0x85, 0x1a, + 0xe2, 0x7a, 0x17, 0xae, 0x4c, 0x72, 0x2e, 0x3a, 0xc1, 0x73, 0xf1, 0x69, 0x30, 0x68, 0xe2, 0x33, + 0x56, 0x13, 0xcf, 0x57, 0x97, 0x93, 0xf1, 0xb3, 0x0c, 0x34, 0xe5, 0xe9, 0x8a, 0xca, 0x74, 0x2d, + 0xa0, 0x70, 0x9d, 0x43, 0xfc, 0xe5, 0x8f, 0x16, 0x18, 0x50, 0x43, 0xe3, 0x47, 0x74, 0x53, 0x91, + 0xf1, 0xa6, 0x22, 0x80, 0xdb, 0xf2, 0xb6, 0x7a, 0x03, 0x2a, 0x2a, 0x1c, 0x73, 0xec, 0x8c, 0xd4, + 0xa3, 0xb2, 0x14, 0x8f, 0xb9, 0xe7, 0x8c, 0xd4, 0x45, 0xe7, 0xdb, 0x32, 0x9f, 0x2a, 0x83, 0x17, + 0x9d, 0x69, 0x87, 0xdc, 0xf8, 0xcf, 0x19, 0x58, 0xd4, 0xa6, 0x22, 0xcf, 0xed, 0x87, 0x50, 0x8d, + 0xde, 0x8f, 0xe3, 0x91, 0xe4, 0xb5, 0x96, 0x64, 0x34, 0x71, 0xb5, 0xca, 0x20, 0x82, 0x04, 0x62, + 0x30, 0x43, 0xfb, 0x0a, 0xc7, 0x1b, 0x4c, 0xc7, 0x4a, 0xb9, 0x19, 0xda, 0x57, 0xdb, 0x9c, 0xf7, + 0xa6, 0x63, 0xa1, 0xba, 0x5e, 0x70, 0xfe, 0x22, 0x42, 0x20, 0x99, 0x0b, 0x04, 0x4c, 0x62, 0x18, + 0x50, 0x1b, 0x7b, 0x6e, 0x78, 0x16, 0xa1, 0x48, 0xa9, 0x13, 0x81, 0x84, 0x63, 0xfc, 0x69, 0x16, + 0x96, 0xc8, 0xc4, 0x26, 0x4d, 0x9b, 0x92, 0x75, 0xb5, 0x60, 0x81, 0xac, 0x8d, 0xc4, 0xbc, 0x76, + 0x6e, 0x98, 0xf2, 0x9b, 0x7d, 0xf7, 0x35, 0xcd, 0x82, 0x2a, 0x65, 0xeb, 0x9a, 0xe5, 0xcf, 0xcd, + 0x2f, 0xff, 0xf5, 0xcb, 0x9b, 0xe6, 0x71, 0x2b, 0xa4, 0x79, 0xdc, 0x5e, 0xc7, 0xcf, 0x35, 0x97, + 0xd7, 0x54, 0x94, 0x38, 0x5a, 0x5e, 0xd3, 0xfb, 0xb0, 0x96, 0xc0, 0x41, 0x6e, 0xed, 0x9c, 0x38, + 0x5c, 0xe5, 0x90, 0x2f, 0x6b, 0xd8, 0x3d, 0x55, 0xb6, 0x51, 0x84, 0x42, 0x30, 0xf0, 0x26, 0xdc, + 0x58, 0x85, 0xe5, 0xe4, 0xaa, 0xca, 0x6b, 0xe2, 0xf7, 0x32, 0xd0, 0x92, 0xf1, 0x11, 0x8e, 0x7b, + 0xba, 0xe3, 0x04, 0xa1, 0xe7, 0x47, 0xef, 0xac, 0xdd, 0x01, 0x08, 0x42, 0xdb, 0x97, 0xda, 0x26, + 0xc9, 0xc1, 0x65, 0x84, 0xa0, 0x26, 0x79, 0x13, 0x4a, 0xdc, 0x1d, 0x52, 0x21, 0x51, 0x43, 0x91, + 0xbb, 0x43, 0xa5, 0x87, 0xce, 0xc9, 0xdf, 0xb5, 0xa4, 0x7a, 0x21, 0x13, 0x2c, 0xc5, 0xea, 0xf0, + 0x73, 0xbc, 0x78, 0xf3, 0x51, 0x82, 0xe5, 0x9e, 0x7d, 0x89, 0xd1, 0x86, 0x81, 0xf1, 0x4f, 0xb3, + 0xd0, 0x88, 0xc7, 0x47, 0xd9, 0xd9, 0x09, 0xfe, 0x2d, 0x47, 0x15, 0xf3, 0xef, 0x7b, 0x92, 0x1c, + 0x1c, 0x21, 0xbf, 0x6b, 0x86, 0xc7, 0x12, 0x1d, 0xce, 0xae, 0xcb, 0x0c, 0xa8, 0x28, 0x0c, 0x6f, + 0x1a, 0x6a, 0xcf, 0x1d, 0x95, 0x09, 0xe5, 0x60, 0x1a, 0x0a, 0x85, 0x4b, 0x68, 0x9e, 0x8e, 0x2b, + 0x55, 0x9e, 0x82, 0x3d, 0x0e, 0xbb, 0xf8, 0x8a, 0xb2, 0x00, 0x8b, 0x6a, 0xb4, 0x91, 0x02, 0x4b, + 0xe0, 0x37, 0x49, 0xce, 0xa6, 0x9d, 0x43, 0x19, 0x5b, 0x17, 0x42, 0xe9, 0x41, 0xc9, 0x48, 0x08, + 0x7d, 0x03, 0x2a, 0xd4, 0x78, 0x9c, 0xc6, 0x96, 0x37, 0xcb, 0xd8, 0x03, 0x96, 0x4b, 0x23, 0x90, + 0x37, 0x4d, 0xa8, 0xbe, 0x40, 0x5d, 0x61, 0xf8, 0xc1, 0x3f, 0xca, 0xc0, 0xcd, 0x94, 0x6d, 0x93, + 0xa7, 0x7c, 0x13, 0x16, 0x4f, 0xa2, 0x42, 0xb5, 0xba, 0x74, 0xd4, 0x57, 0x15, 0x5b, 0x4d, 0xae, + 0xa9, 0xd9, 0x3c, 0x49, 0x02, 0x62, 0xa5, 0x8b, 0x76, 0x30, 0x91, 0xa9, 0x88, 0x4a, 0x17, 0x6d, + 0x23, 0xe9, 0x3b, 0x87, 0xb0, 0xde, 0xb9, 0x14, 0x1c, 0x63, 0x53, 0x7f, 0x06, 0x5c, 0x91, 0x51, + 0xd2, 0xc0, 0x9c, 0x79, 0x2d, 0x03, 0xf3, 0x90, 0x12, 0xb2, 0xa2, 0xb6, 0xbe, 0x4e, 0x23, 0x78, + 0x81, 0x8a, 0x3a, 0xf4, 0x8c, 0xb9, 0xca, 0x96, 0x1c, 0x44, 0xcf, 0x97, 0x1b, 0x01, 0x34, 0xf6, + 0xa6, 0xa3, 0xd0, 0x89, 0x5f, 0x34, 0x67, 0xdf, 0x95, 0x75, 0xb0, 0x1f, 0xb5, 0x6a, 0xa9, 0x1d, + 0x41, 0xd4, 0x11, 0x2e, 0xd6, 0x58, 0x34, 0x64, 0xcd, 0xf7, 0xd7, 0x18, 0x27, 0x7b, 0x30, 0x6e, + 0xc2, 0x5a, 0xfc, 0x45, 0xcb, 0xa6, 0xae, 0x9a, 0x7f, 0x95, 0xa1, 0xd0, 0xe6, 0xe4, 0xeb, 0xea, + 0xac, 0x03, 0x4b, 0x81, 0xe3, 0x9e, 0x8e, 0xb8, 0xde, 0x7c, 0x20, 0x17, 0x61, 0x25, 0x39, 0x36, + 0xf9, 0x02, 0xbb, 0xb9, 0x48, 0x35, 0xe2, 0xd6, 0x02, 0xb6, 0x71, 0xdd, 0x20, 0x63, 0xb2, 0x98, + 0x59, 0x8d, 0xf9, 0xc1, 0x77, 0xa1, 0x9e, 0xec, 0x88, 0x7d, 0x4f, 0x26, 0x23, 0xc6, 0xa3, 0xca, + 0xcd, 0xe4, 0x95, 0xc5, 0x04, 0x51, 0x89, 0xd7, 0x3e, 0x30, 0xfe, 0x71, 0x06, 0x5a, 0x26, 0x17, + 0x94, 0xab, 0x8d, 0x52, 0xd1, 0xcc, 0x87, 0x73, 0xad, 0x5e, 0x3f, 0x57, 0x95, 0xe3, 0xa8, 0x46, + 0xf4, 0xad, 0x6b, 0x37, 0x63, 0xe7, 0xc6, 0xdc, 0x8c, 0x36, 0x4a, 0xb0, 0x40, 0x28, 0xc6, 0x1a, + 0xac, 0xc8, 0xf1, 0xa8, 0xb1, 0xc4, 0xde, 0xc3, 0x44, 0x8f, 0x09, 0xef, 0xe1, 0x3a, 0xb4, 0xe8, + 0xb9, 0x3c, 0x7d, 0x12, 0xb2, 0xe2, 0x16, 0xb0, 0x3d, 0x7b, 0x60, 0xfb, 0x9e, 0xe7, 0x1e, 0x72, + 0x5f, 0x06, 0x8a, 0xa2, 0x84, 0x89, 0xce, 0x35, 0x25, 0x0a, 0xd3, 0x97, 0x7a, 0xe4, 0xcd, 0x73, + 0x55, 0x5c, 0x0c, 0x7d, 0x19, 0x26, 0x2c, 0x6d, 0xd8, 0x2f, 0xb8, 0x6a, 0x49, 0x2d, 0xd1, 0x47, + 0x50, 0x99, 0x44, 0x8d, 0xaa, 0x75, 0x57, 0x19, 0xcb, 0xf3, 0xdd, 0x9a, 0x3a, 0xb6, 0xf1, 0x14, + 0x96, 0x93, 0x6d, 0x4a, 0xd6, 0xb1, 0x0e, 0xa5, 0xb1, 0x84, 0xc9, 0xd1, 0x45, 0xdf, 0xc6, 0xef, + 0x94, 0xa0, 0x28, 0xf5, 0x39, 0xf6, 0x08, 0xf2, 0x03, 0x15, 0x9b, 0x14, 0x3f, 0x84, 0x21, 0x4b, + 0xd5, 0xff, 0x9b, 0x18, 0xa1, 0x24, 0xf0, 0xd8, 0x47, 0x50, 0x4f, 0x7a, 0x45, 0x67, 0xd2, 0x21, + 0x93, 0xee, 0xcc, 0xda, 0x60, 0xc6, 0xff, 0x55, 0x8e, 0x2f, 0x47, 0x92, 0x19, 0x4a, 0x67, 0xda, + 0xed, 0xe9, 0xb9, 0x42, 0xde, 0x0e, 0xce, 0x6c, 0xeb, 0xe9, 0xfb, 0x1f, 0xc8, 0x7c, 0xc8, 0x0a, + 0x02, 0x7b, 0x67, 0xf6, 0xd3, 0xf7, 0x3f, 0x98, 0x95, 0xa4, 0x29, 0x25, 0x4e, 0x97, 0xa4, 0x97, + 0xa1, 0x40, 0xaf, 0x99, 0x51, 0x90, 0x09, 0x7d, 0xb0, 0x27, 0xb0, 0x2c, 0xd5, 0x56, 0x4b, 0x86, + 0x03, 0x13, 0x17, 0x2c, 0x51, 0x0e, 0x8e, 0x2c, 0xeb, 0x61, 0x11, 0xd9, 0x86, 0x56, 0x61, 0xe1, + 0x2c, 0x7e, 0x9a, 0xae, 0x66, 0xca, 0x2f, 0xe3, 0x4f, 0x0b, 0x50, 0xd1, 0x16, 0x85, 0x55, 0xa1, + 0x64, 0x76, 0x7a, 0x1d, 0xf3, 0x93, 0xce, 0x56, 0xf3, 0x06, 0x7b, 0x00, 0x6f, 0x77, 0xf7, 0x37, + 0x0f, 0x4c, 0xb3, 0xb3, 0xd9, 0xb7, 0x0e, 0x4c, 0x4b, 0xbd, 0x91, 0x72, 0xd8, 0xfe, 0x6c, 0xaf, + 0xb3, 0xdf, 0xb7, 0xb6, 0x3a, 0xfd, 0x76, 0x77, 0xb7, 0xd7, 0xcc, 0xb0, 0xdb, 0xd0, 0x8a, 0x31, + 0x55, 0x71, 0x7b, 0xef, 0xe0, 0x68, 0xbf, 0xdf, 0xcc, 0xb2, 0xbb, 0x70, 0x6b, 0xbb, 0xbb, 0xdf, + 0xde, 0xb5, 0x62, 0x9c, 0xcd, 0xdd, 0xfe, 0x27, 0x56, 0xe7, 0xd7, 0x0e, 0xbb, 0xe6, 0x67, 0xcd, + 0x5c, 0x1a, 0x82, 0x50, 0xc6, 0x55, 0x0b, 0x79, 0x76, 0x13, 0x56, 0x08, 0x81, 0xaa, 0x58, 0xfd, + 0x83, 0x03, 0xab, 0x77, 0x70, 0xb0, 0xdf, 0x2c, 0xb0, 0x45, 0xa8, 0x75, 0xf7, 0x3f, 0x69, 0xef, + 0x76, 0xb7, 0x2c, 0xb3, 0xd3, 0xde, 0xdd, 0x6b, 0x2e, 0xb0, 0x25, 0x68, 0xcc, 0xe2, 0x15, 0x45, + 0x13, 0x0a, 0xef, 0x60, 0xbf, 0x7b, 0xb0, 0x6f, 0x7d, 0xd2, 0x31, 0x7b, 0xdd, 0x83, 0xfd, 0x66, + 0x89, 0xad, 0x02, 0x4b, 0x16, 0xed, 0xec, 0xb5, 0x37, 0x9b, 0x65, 0xb6, 0x02, 0x8b, 0x49, 0xf8, + 0xf3, 0xce, 0x67, 0x4d, 0x60, 0x2d, 0x58, 0xa6, 0x81, 0x59, 0x1b, 0x9d, 0xdd, 0x83, 0x4f, 0xad, + 0xbd, 0xee, 0x7e, 0x77, 0xef, 0x68, 0xaf, 0x59, 0xc1, 0x47, 0x98, 0x3a, 0x1d, 0xab, 0xbb, 0xdf, + 0x3b, 0xda, 0xde, 0xee, 0x6e, 0x76, 0x3b, 0xfb, 0xfd, 0x66, 0x95, 0x7a, 0x4e, 0x9b, 0x78, 0x4d, + 0x54, 0x90, 0x39, 0x03, 0xd6, 0x56, 0xb7, 0xd7, 0xde, 0xd8, 0xed, 0x6c, 0x35, 0xeb, 0xec, 0x0e, + 0xdc, 0xec, 0x77, 0xf6, 0x0e, 0x0f, 0xcc, 0xb6, 0xf9, 0x99, 0xca, 0x29, 0xb0, 0xb6, 0xdb, 0xdd, + 0xdd, 0x23, 0xb3, 0xd3, 0x6c, 0xb0, 0x37, 0xe1, 0x8e, 0xd9, 0xf9, 0xf8, 0xa8, 0x6b, 0x76, 0xb6, + 0xac, 0xfd, 0x83, 0xad, 0x8e, 0xb5, 0xdd, 0x69, 0xf7, 0x8f, 0xcc, 0x8e, 0xb5, 0xd7, 0xed, 0xf5, + 0xba, 0xfb, 0xcf, 0x9a, 0x4d, 0xf6, 0x36, 0xdc, 0x8b, 0x50, 0xa2, 0x06, 0x66, 0xb0, 0x16, 0xc5, + 0xfc, 0xd4, 0x96, 0xee, 0x77, 0x7e, 0xad, 0x6f, 0x1d, 0x76, 0x3a, 0x66, 0x93, 0xb1, 0x75, 0x58, + 0x8d, 0xbb, 0xa7, 0x0e, 0x64, 0xdf, 0x4b, 0xa2, 0xec, 0xb0, 0x63, 0xee, 0xb5, 0xf7, 0xc5, 0x06, + 0x27, 0xca, 0x96, 0xc5, 0xb0, 0xe3, 0xb2, 0xd9, 0x61, 0xaf, 0x30, 0x06, 0x75, 0x6d, 0x57, 0xb6, + 0xdb, 0x66, 0x73, 0x95, 0x35, 0xa0, 0xb2, 0x77, 0x78, 0x68, 0xf5, 0xbb, 0x7b, 0x9d, 0x83, 0xa3, + 0x7e, 0x73, 0x8d, 0xad, 0x40, 0xb3, 0xbb, 0xdf, 0xef, 0x98, 0x62, 0xaf, 0x55, 0xd5, 0xff, 0x5d, + 0x64, 0xcb, 0xd0, 0x50, 0x23, 0x55, 0xd0, 0xbf, 0x2a, 0xb2, 0x35, 0x60, 0x47, 0xfb, 0x66, 0xa7, + 0xbd, 0x25, 0x16, 0x2e, 0x2a, 0xf8, 0x3f, 0x45, 0xe9, 0x21, 0xf9, 0x59, 0x2e, 0xba, 0xac, 0xe3, + 0x90, 0x83, 0xe4, 0x43, 0xa5, 0x55, 0xed, 0x81, 0xd1, 0x57, 0x3d, 0x21, 0xae, 0xa9, 0x56, 0xb9, + 0x39, 0xd5, 0x6a, 0x4e, 0x77, 0xaf, 0xe9, 0xb2, 0xdf, 0x5b, 0x50, 0x1b, 0xd3, 0xa3, 0xa5, 0xf2, + 0x71, 0x42, 0x90, 0xf1, 0x37, 0x04, 0xa4, 0x97, 0x09, 0xe7, 0xde, 0xd0, 0x2e, 0xcc, 0xbf, 0xa1, + 0x9d, 0x26, 0xdf, 0x2f, 0xa4, 0xc9, 0xf7, 0x0f, 0x61, 0x91, 0x58, 0x93, 0xe3, 0x3a, 0x63, 0xa5, + 0x35, 0x93, 0x14, 0xd8, 0x40, 0x16, 0x45, 0x70, 0xa5, 0x4e, 0x28, 0x95, 0x43, 0xb2, 0x90, 0xa2, + 0xd4, 0x36, 0x12, 0x9a, 0x06, 0x71, 0x8e, 0x48, 0xd3, 0x88, 0x7a, 0xb0, 0x2f, 0xe3, 0x1e, 0x2a, + 0x5a, 0x0f, 0x04, 0xc7, 0x1e, 0x1e, 0xc2, 0x22, 0xbf, 0x0c, 0x7d, 0xdb, 0xf2, 0x26, 0xf6, 0xe7, + 0x53, 0x74, 0xe1, 0xda, 0xa8, 0xc3, 0x57, 0xcd, 0x06, 0x16, 0x1c, 0x20, 0x7c, 0xcb, 0x0e, 0xed, + 0x87, 0x5f, 0x42, 0x45, 0x7b, 0xd0, 0x96, 0xad, 0xc1, 0xd2, 0xa7, 0xdd, 0xfe, 0x7e, 0xa7, 0xd7, + 0xb3, 0x0e, 0x8f, 0x36, 0x9e, 0x77, 0x3e, 0xb3, 0x76, 0xda, 0xbd, 0x9d, 0xe6, 0x0d, 0x71, 0x68, + 0xf7, 0x3b, 0xbd, 0x7e, 0x67, 0x2b, 0x01, 0xcf, 0xb0, 0x37, 0x60, 0xfd, 0x68, 0xff, 0xa8, 0xd7, + 0xd9, 0xb2, 0xd2, 0xea, 0x65, 0x05, 0x95, 0xca, 0xf2, 0x94, 0xea, 0xb9, 0x87, 0x3f, 0x84, 0x7a, + 0xf2, 0x95, 0x45, 0x06, 0xb0, 0xb0, 0xdb, 0x79, 0xd6, 0xde, 0xfc, 0x8c, 0x9e, 0x69, 0xeb, 0xf5, + 0xdb, 0xfd, 0xee, 0xa6, 0x25, 0x9f, 0x65, 0x13, 0x1c, 0x21, 0xc3, 0x2a, 0x50, 0x6c, 0xef, 0x6f, + 0xee, 0x1c, 0x98, 0xbd, 0x66, 0xf6, 0xe1, 0x47, 0xd0, 0x9c, 0xf5, 0x47, 0x25, 0x1c, 0x78, 0x2f, + 0xf3, 0xf4, 0x3d, 0xfc, 0x77, 0x39, 0x80, 0x38, 0x61, 0x40, 0xb0, 0x9a, 0xad, 0x76, 0xbf, 0xbd, + 0x7b, 0x20, 0xa6, 0x61, 0x1e, 0xf4, 0x05, 0x07, 0x31, 0x3b, 0x1f, 0x37, 0x6f, 0xa4, 0x96, 0x1c, + 0x1c, 0xf6, 0x9b, 0x19, 0xb1, 0x62, 0xdd, 0xfd, 0x6e, 0xbf, 0xdb, 0xde, 0xb5, 0xcc, 0x83, 0xa3, + 0xee, 0xfe, 0x33, 0x7a, 0xb0, 0x0a, 0xb9, 0xec, 0xd1, 0xe1, 0xb6, 0x79, 0xb0, 0xdf, 0xb7, 0x7a, + 0x3b, 0x47, 0xfd, 0x2d, 0x7c, 0xee, 0x6a, 0xd3, 0xec, 0x1e, 0x52, 0x9b, 0xf9, 0x97, 0x21, 0x88, + 0xa6, 0x0b, 0x62, 0xcd, 0x9f, 0x1d, 0xf4, 0x7a, 0xdd, 0x43, 0xeb, 0xe3, 0xa3, 0x8e, 0xd9, 0xed, + 0xf4, 0xb0, 0xe2, 0x42, 0x0a, 0x5c, 0xe0, 0x17, 0x05, 0x6f, 0xee, 0xef, 0x7e, 0x22, 0x99, 0xa7, + 0x40, 0x2d, 0x25, 0x41, 0x02, 0xab, 0x2c, 0x78, 0x8a, 0xe0, 0x3e, 0x29, 0x2d, 0xc3, 0x35, 0x65, + 0xa2, 0x5e, 0x45, 0xf0, 0xd5, 0xb9, 0xcd, 0xc0, 0x6a, 0xd5, 0xf4, 0x22, 0x51, 0x0b, 0x59, 0x6e, + 0x74, 0x41, 0x6d, 0x6d, 0x99, 0x58, 0xa1, 0x3e, 0x07, 0x15, 0xb8, 0x0d, 0xb1, 0x51, 0x82, 0x3d, + 0x09, 0x94, 0xa6, 0xfa, 0x10, 0x25, 0x8b, 0x4f, 0x7f, 0x3b, 0x07, 0x75, 0x4a, 0xde, 0xa2, 0xdf, + 0x13, 0xe2, 0x3e, 0xdb, 0x83, 0xa2, 0xfc, 0x61, 0x2a, 0xb6, 0x12, 0x3d, 0x5b, 0xa4, 0xff, 0x14, + 0xd6, 0xfa, 0xea, 0x2c, 0x58, 0x8a, 0x63, 0x4b, 0x7f, 0xfb, 0x4f, 0xfe, 0xf2, 0x9f, 0x64, 0x6b, + 0xac, 0xf2, 0xf8, 0xfc, 0xbd, 0xc7, 0xa7, 0xdc, 0x0d, 0x44, 0x1b, 0x7f, 0x03, 0x20, 0xfe, 0xb9, + 0x25, 0xd6, 0x8a, 0x9c, 0x50, 0x33, 0xbf, 0x45, 0xb5, 0x7e, 0x33, 0xa5, 0x44, 0xb6, 0x7b, 0x13, + 0xdb, 0x5d, 0x32, 0xea, 0xa2, 0x5d, 0xc7, 0x75, 0x42, 0xfa, 0xe9, 0xa5, 0x0f, 0x33, 0x0f, 0xd9, + 0x10, 0xaa, 0xfa, 0x0f, 0x21, 0x31, 0x25, 0x29, 0xa5, 0xfc, 0x94, 0xd3, 0xfa, 0xad, 0xd4, 0x32, + 0x25, 0x83, 0x62, 0x1f, 0x2b, 0x46, 0x53, 0xf4, 0x31, 0x45, 0x8c, 0xb8, 0x97, 0x11, 0x49, 0xe5, + 0xf1, 0xef, 0x1d, 0xb1, 0xdb, 0x9a, 0x5c, 0x35, 0xf7, 0x6b, 0x4b, 0xeb, 0x77, 0xae, 0x29, 0x95, + 0x7d, 0xdd, 0xc1, 0xbe, 0xd6, 0x0c, 0x26, 0xfa, 0x1a, 0x20, 0x8e, 0xfa, 0xb5, 0xa5, 0x0f, 0x33, + 0x0f, 0x9f, 0xfe, 0xc5, 0x03, 0x28, 0x47, 0xc1, 0x9c, 0xec, 0x37, 0xa1, 0x96, 0xc8, 0xae, 0x63, + 0x6a, 0x1a, 0x69, 0xc9, 0x78, 0xeb, 0xb7, 0xd3, 0x0b, 0x65, 0xc7, 0x6f, 0x60, 0xc7, 0x2d, 0xb6, + 0x2a, 0x3a, 0x96, 0xd9, 0x6b, 0x8f, 0x31, 0x07, 0x95, 0x1e, 0x81, 0x7a, 0xa1, 0x69, 0x1f, 0xd4, + 0xd9, 0xed, 0x59, 0x8d, 0x20, 0xd1, 0xdb, 0x9d, 0x6b, 0x4a, 0x65, 0x77, 0xb7, 0xb1, 0xbb, 0x55, + 0xb6, 0xac, 0x77, 0xa7, 0x42, 0x2f, 0x19, 0xc7, 0x87, 0xd7, 0xf4, 0x9f, 0x03, 0x62, 0x77, 0xe2, + 0x67, 0xb2, 0x52, 0x7e, 0x26, 0x28, 0x22, 0x91, 0xf9, 0xdf, 0x0a, 0x32, 0x5a, 0xd8, 0x15, 0x63, + 0xb8, 0x7d, 0xfa, 0xaf, 0x01, 0xb1, 0x63, 0xa8, 0x68, 0x2f, 0xe8, 0xb3, 0x9b, 0xd7, 0xbe, 0xf6, + 0xbf, 0xbe, 0x9e, 0x56, 0x94, 0x36, 0x15, 0xbd, 0xfd, 0xc7, 0x27, 0x9c, 0xb3, 0x5f, 0x87, 0x72, + 0xf4, 0x2e, 0x3b, 0x5b, 0xd3, 0xde, 0xc9, 0xd7, 0xdf, 0x91, 0x5f, 0x6f, 0xcd, 0x17, 0xa4, 0x11, + 0x9f, 0xde, 0xba, 0x20, 0xbe, 0x4f, 0xa1, 0xa2, 0xbd, 0xbd, 0x1e, 0x4d, 0x60, 0xfe, 0x7d, 0xf7, + 0x68, 0x02, 0x29, 0x4f, 0xb5, 0x1b, 0x8b, 0xd8, 0x45, 0x85, 0x95, 0x91, 0xbe, 0xc3, 0x4b, 0x2f, + 0x60, 0xbb, 0xb0, 0x22, 0x35, 0xad, 0x63, 0xfe, 0x55, 0xb6, 0x21, 0xe5, 0x17, 0x98, 0x9e, 0x64, + 0xd8, 0x47, 0x50, 0x52, 0x4f, 0xec, 0xb3, 0xd5, 0xf4, 0x9f, 0x0a, 0x58, 0x5f, 0x9b, 0x83, 0x4b, + 0xb5, 0xe8, 0x33, 0x80, 0xf8, 0xa1, 0xf7, 0x88, 0x49, 0xcc, 0x3d, 0x1c, 0x1f, 0x51, 0xc0, 0xfc, + 0xab, 0xf0, 0xc6, 0x2a, 0x4e, 0xb0, 0xc9, 0x90, 0x49, 0xb8, 0xfc, 0x42, 0xbd, 0x40, 0xf9, 0x13, + 0xa8, 0x68, 0x6f, 0xbd, 0x47, 0xcb, 0x37, 0xff, 0x4e, 0x7c, 0xb4, 0x7c, 0x29, 0x4f, 0xc3, 0x1b, + 0xeb, 0xd8, 0xfa, 0xb2, 0xd1, 0x10, 0xad, 0x0b, 0x51, 0x4b, 0x8a, 0x3c, 0x62, 0x83, 0xce, 0xa0, + 0x96, 0x78, 0xd0, 0x3d, 0x3a, 0xa1, 0x69, 0xcf, 0xc5, 0x47, 0x27, 0x34, 0xf5, 0x0d, 0x78, 0x45, + 0x67, 0xc6, 0xa2, 0xe8, 0xe7, 0x1c, 0x51, 0xb4, 0x9e, 0x7e, 0x0c, 0x15, 0xed, 0x71, 0xf6, 0x68, + 0x2e, 0xf3, 0xef, 0xc0, 0x47, 0x73, 0x49, 0x7b, 0xcb, 0x7d, 0x19, 0xfb, 0xa8, 0x1b, 0x48, 0x0a, + 0xf8, 0xbe, 0x9f, 0x68, 0xfb, 0x37, 0xa1, 0x9e, 0x7c, 0xaf, 0x3d, 0x3a, 0xfb, 0xa9, 0x0f, 0xbf, + 0x47, 0x67, 0xff, 0x9a, 0x47, 0xde, 0x25, 0x49, 0x3f, 0x5c, 0x8a, 0x3a, 0x79, 0xfc, 0x85, 0x4c, + 0x4b, 0xf9, 0x92, 0x7d, 0x2c, 0x18, 0x9c, 0x7c, 0x5e, 0x92, 0xad, 0x69, 0x54, 0xab, 0x3f, 0x42, + 0x19, 0x9d, 0x97, 0xb9, 0x97, 0x28, 0x93, 0xc4, 0x8c, 0x8d, 0xb3, 0x67, 0xb0, 0x14, 0x11, 0x73, + 0xf4, 0x5e, 0x64, 0x10, 0xcd, 0x21, 0xf5, 0x55, 0xca, 0xf5, 0xe6, 0x6c, 0xe9, 0x93, 0x0c, 0x5d, + 0x7f, 0xf8, 0x4a, 0x9f, 0x76, 0xfd, 0xe9, 0x4f, 0x46, 0x6a, 0xd7, 0x5f, 0xe2, 0x31, 0xbf, 0xd9, + 0xeb, 0x2f, 0x74, 0x44, 0x1b, 0x2e, 0x34, 0x66, 0x5f, 0x6f, 0xbc, 0x73, 0xdd, 0xdb, 0x05, 0xd4, + 0xfc, 0x1b, 0x2f, 0x7f, 0xda, 0x20, 0xc9, 0x8a, 0x14, 0x37, 0x7d, 0x2c, 0x83, 0x4f, 0xd8, 0x6f, + 0x40, 0x55, 0x7f, 0x2c, 0x9a, 0xe9, 0x3c, 0x61, 0xb6, 0xa7, 0x5b, 0xa9, 0x65, 0x49, 0x2a, 0x61, + 0x55, 0xbd, 0x1b, 0xf6, 0x09, 0xac, 0x46, 0xcb, 0xac, 0xe7, 0xad, 0x07, 0xec, 0x6e, 0x4a, 0x36, + 0x7b, 0x62, 0xb1, 0x6f, 0x5e, 0x9b, 0xee, 0xfe, 0x24, 0x23, 0xa8, 0x2f, 0xf9, 0x6a, 0x6d, 0x7c, + 0xf3, 0xa4, 0x3d, 0xd6, 0x1b, 0xdf, 0x3c, 0xa9, 0x4f, 0xdd, 0x2a, 0xea, 0x63, 0x4b, 0x89, 0x35, + 0xa2, 0xb0, 0x5c, 0xf6, 0x63, 0x68, 0x68, 0x49, 0xf9, 0xbd, 0x2b, 0x77, 0x10, 0x9d, 0xa4, 0xf9, + 0x27, 0xe1, 0xd6, 0xd3, 0x6c, 0x93, 0xc6, 0x1a, 0xb6, 0xbf, 0x68, 0x24, 0x16, 0x47, 0x9c, 0xa2, + 0x4d, 0xa8, 0xe8, 0x09, 0xff, 0x2f, 0x69, 0x77, 0x4d, 0x2b, 0xd2, 0x5f, 0x1f, 0x7b, 0x92, 0x61, + 0xbb, 0xd0, 0x9c, 0x7d, 0x2c, 0x29, 0xe2, 0x29, 0x69, 0x0f, 0x3c, 0xad, 0xcf, 0x14, 0x26, 0x9e, + 0x58, 0x62, 0x87, 0x94, 0xd8, 0x11, 0xfd, 0x5c, 0x91, 0xe7, 0xcf, 0xde, 0xea, 0xc9, 0x9f, 0x31, + 0x8a, 0x5a, 0x4b, 0xfb, 0x01, 0xab, 0x07, 0x99, 0x27, 0x19, 0xf6, 0xbb, 0x19, 0xa8, 0x26, 0x1e, + 0x28, 0x49, 0x84, 0xce, 0xcf, 0xcc, 0xb3, 0xa5, 0x97, 0xe9, 0x13, 0x35, 0x4c, 0x5c, 0xc4, 0xdd, + 0x87, 0x3f, 0x4a, 0x6c, 0xd2, 0x17, 0x09, 0xd7, 0xde, 0xa3, 0xd9, 0xdf, 0x33, 0xfa, 0x72, 0x16, + 0x41, 0x7f, 0xe9, 0xef, 0xcb, 0x27, 0x19, 0xf6, 0x1f, 0x32, 0x50, 0x4f, 0xfa, 0xec, 0xa3, 0xe9, + 0xa6, 0x46, 0x07, 0x44, 0xa4, 0x74, 0x8d, 0xa3, 0xff, 0xc7, 0x38, 0xca, 0xfe, 0x43, 0x33, 0x31, + 0x4a, 0xf9, 0xde, 0xf2, 0xcf, 0x37, 0x5a, 0xf6, 0x21, 0xfd, 0x7c, 0xa0, 0x0a, 0x65, 0x62, 0xf3, + 0x3f, 0x37, 0x17, 0x91, 0x9f, 0xfe, 0xe3, 0x6c, 0xb8, 0x09, 0x3f, 0xa1, 0xdf, 0xed, 0x51, 0x91, + 0x31, 0x82, 0x8a, 0x5f, 0xb7, 0xbe, 0xf1, 0x36, 0xce, 0xe9, 0x0d, 0xe3, 0x66, 0x62, 0x4e, 0xb3, + 0x82, 0x47, 0x9b, 0x46, 0x27, 0x7f, 0x5b, 0x2d, 0xbe, 0x39, 0xe7, 0x7e, 0x6f, 0xed, 0xfa, 0x41, + 0x8e, 0x69, 0x90, 0x12, 0x3d, 0x71, 0xd4, 0x5e, 0xb3, 0x19, 0xe3, 0x21, 0x8e, 0xf5, 0x6d, 0xe3, + 0xee, 0xb5, 0x63, 0x7d, 0x8c, 0xfe, 0x77, 0x31, 0xe2, 0x43, 0x80, 0x38, 0xd4, 0x90, 0xcd, 0x04, + 0xbc, 0x45, 0x0c, 0x68, 0x3e, 0x1a, 0x31, 0x79, 0x9e, 0x55, 0x5c, 0x9c, 0x68, 0xf1, 0xd7, 0x89, + 0x9d, 0x46, 0xa1, 0x78, 0xba, 0xf4, 0x95, 0x8c, 0x0a, 0x4c, 0x48, 0x5f, 0xb3, 0xed, 0x27, 0x98, + 0x69, 0x14, 0x77, 0x77, 0x04, 0xb5, 0x5d, 0xcf, 0x7b, 0x31, 0x9d, 0x44, 0xe1, 0xed, 0xc9, 0xa0, + 0x98, 0x1d, 0x3b, 0x38, 0x5b, 0x9f, 0x99, 0x85, 0x71, 0x0f, 0x9b, 0x5a, 0x67, 0x2d, 0xad, 0xa9, + 0xc7, 0x5f, 0xc4, 0xf1, 0x8d, 0x5f, 0x32, 0x1b, 0x16, 0x23, 0x1e, 0x1d, 0xc7, 0x10, 0x26, 0x9b, + 0x49, 0x70, 0xe6, 0xd9, 0x2e, 0x12, 0x6a, 0x82, 0x1a, 0xed, 0xe3, 0x40, 0xb5, 0xf9, 0x24, 0xc3, + 0x0e, 0xa1, 0xba, 0xc5, 0x07, 0x98, 0xa8, 0x8f, 0xa1, 0x25, 0x4b, 0x89, 0x30, 0x05, 0x8a, 0x49, + 0x59, 0xaf, 0x25, 0x80, 0xc9, 0x7b, 0x6b, 0x62, 0x5f, 0xf9, 0xfc, 0xf3, 0xc7, 0x5f, 0xc8, 0xa0, + 0x95, 0x2f, 0xd5, 0xbd, 0xa5, 0x82, 0x7a, 0x12, 0xf7, 0xd6, 0x4c, 0x14, 0x50, 0xe2, 0xde, 0x9a, + 0x8b, 0x02, 0x4a, 0x2c, 0xb5, 0x0a, 0x2a, 0x62, 0x23, 0x58, 0x9c, 0x0b, 0x1c, 0x8a, 0xae, 0xac, + 0xeb, 0xc2, 0x8d, 0xd6, 0xef, 0x5d, 0x8f, 0x90, 0xec, 0xed, 0x61, 0xb2, 0xb7, 0x1e, 0xd4, 0xe8, + 0xf1, 0xc1, 0x63, 0x4e, 0x29, 0x7b, 0x33, 0xef, 0xdd, 0xe8, 0xf9, 0x80, 0xb3, 0x17, 0x0c, 0x96, + 0x25, 0x25, 0x1c, 0xcc, 0x95, 0x63, 0xbf, 0x0e, 0x95, 0x67, 0x3c, 0x54, 0x39, 0x7a, 0x91, 0x8c, + 0x3d, 0x93, 0xb4, 0xb7, 0x9e, 0x92, 0xe2, 0x97, 0xa4, 0x19, 0x6c, 0xed, 0x31, 0x1f, 0x9e, 0x72, + 0x62, 0x4e, 0x96, 0x33, 0xfc, 0x92, 0xfd, 0x1a, 0x36, 0x1e, 0xa5, 0x46, 0xaf, 0x6a, 0x49, 0x58, + 0x7a, 0xe3, 0x8d, 0x19, 0x78, 0x5a, 0xcb, 0xae, 0x37, 0xe4, 0x9a, 0xac, 0xe7, 0x42, 0x45, 0x7b, + 0x42, 0x21, 0x3a, 0x40, 0xf3, 0x4f, 0x66, 0x44, 0x07, 0x28, 0xe5, 0xc5, 0x05, 0xe3, 0x01, 0xf6, + 0x63, 0xb0, 0x7b, 0x71, 0x3f, 0xf4, 0xca, 0x42, 0xdc, 0xd3, 0xe3, 0x2f, 0xec, 0x71, 0xf8, 0x25, + 0xfb, 0x14, 0x9f, 0xf8, 0xd6, 0x73, 0x10, 0x63, 0xa5, 0x61, 0x36, 0x5d, 0x31, 0x5a, 0x2c, 0xad, + 0x28, 0xa9, 0x48, 0x50, 0x57, 0x28, 0xc9, 0xbd, 0x0f, 0xd0, 0x0b, 0xbd, 0xc9, 0x96, 0xcd, 0xc7, + 0x9e, 0x1b, 0xf3, 0xda, 0x38, 0x2b, 0x2e, 0xe6, 0x5f, 0x5a, 0x6a, 0x1c, 0xfb, 0x54, 0xd3, 0xb2, + 0x12, 0x69, 0x9c, 0x8a, 0xb8, 0xae, 0x4d, 0x9c, 0x8b, 0x16, 0x24, 0x25, 0x79, 0xee, 0x49, 0x86, + 0xb5, 0x01, 0xe2, 0xc8, 0xb1, 0x48, 0x67, 0x9a, 0x0b, 0x4a, 0x8b, 0xd8, 0x5e, 0x4a, 0x98, 0xd9, + 0x21, 0x94, 0xe3, 0x90, 0x9b, 0xb5, 0xf8, 0x45, 0x98, 0x44, 0x80, 0x4e, 0x74, 0x83, 0xcf, 0x85, + 0xbb, 0x18, 0x4d, 0x5c, 0x2a, 0x60, 0x25, 0xb1, 0x54, 0x27, 0x9c, 0x07, 0xcc, 0x81, 0x25, 0x1a, + 0x60, 0x24, 0x2e, 0x61, 0x36, 0x57, 0xf4, 0x92, 0xfb, 0x7c, 0xe4, 0x49, 0x74, 0x9a, 0x53, 0xe3, + 0x27, 0x12, 0xa6, 0x1f, 0x41, 0xad, 0x94, 0x49, 0x26, 0x58, 0xf3, 0x18, 0x16, 0xe7, 0x5c, 0xf4, + 0xd1, 0x91, 0xbe, 0x2e, 0xe6, 0x22, 0x3a, 0xd2, 0xd7, 0x7a, 0xf7, 0x8d, 0x15, 0xec, 0xb2, 0x61, + 0x00, 0xaa, 0x7a, 0x17, 0x4e, 0x38, 0x38, 0x13, 0xdd, 0xfd, 0xdb, 0x0c, 0x2c, 0xa5, 0x38, 0xe1, + 0xd9, 0x9b, 0xca, 0x6a, 0x70, 0xad, 0x83, 0x7e, 0x3d, 0xd5, 0x59, 0x6b, 0xf4, 0xb0, 0x9f, 0x3d, + 0xf6, 0x3c, 0x71, 0xb1, 0x91, 0xaf, 0x54, 0x9e, 0xcc, 0x97, 0x0a, 0x15, 0xa9, 0x12, 0xc5, 0xe7, + 0xb0, 0x46, 0x03, 0x69, 0x8f, 0x46, 0x33, 0x8e, 0xe4, 0x37, 0xe6, 0x7e, 0x5e, 0x3c, 0xe1, 0x1c, + 0x5f, 0xbf, 0xfe, 0xe7, 0xc7, 0xaf, 0x11, 0xa7, 0x69, 0xa8, 0x6c, 0x0a, 0xcd, 0x59, 0x07, 0x2d, + 0xbb, 0xbe, 0xad, 0xf5, 0xbb, 0x09, 0xfd, 0x37, 0xc5, 0xa9, 0xfb, 0x0d, 0xec, 0xec, 0xae, 0xb1, + 0x9e, 0xb6, 0x2e, 0xa4, 0x12, 0x8b, 0xfd, 0xf8, 0x5b, 0x91, 0x37, 0x79, 0x66, 0x9e, 0xaa, 0x83, + 0xeb, 0x7c, 0xdf, 0x91, 0x06, 0x9e, 0xee, 0x8c, 0x7e, 0x07, 0xbb, 0xbf, 0x67, 0xdc, 0x4a, 0xeb, + 0xde, 0xa7, 0x2a, 0xa4, 0x8b, 0xaf, 0xcd, 0x9e, 0x6b, 0x35, 0x82, 0x7b, 0x69, 0xfb, 0x7d, 0xad, + 0x2e, 0x34, 0xb3, 0xd6, 0x37, 0x50, 0xb6, 0xab, 0xea, 0xde, 0xe3, 0xe8, 0xf8, 0xa4, 0xb8, 0xa9, + 0xa3, 0xe3, 0x93, 0xe6, 0x6e, 0x4e, 0xca, 0x35, 0xca, 0xd1, 0xfc, 0x61, 0xe6, 0xe1, 0xc6, 0xfd, + 0x1f, 0x7f, 0xe3, 0xd4, 0x09, 0xcf, 0xa6, 0xc7, 0x8f, 0x06, 0xde, 0xf8, 0xf1, 0x48, 0x59, 0x1b, + 0x65, 0xca, 0xf3, 0xe3, 0x91, 0x3b, 0x7c, 0x8c, 0xcd, 0x1e, 0x2f, 0x4c, 0x7c, 0x2f, 0xf4, 0xbe, + 0xf3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xac, 0x73, 0xd7, 0x79, 0x41, 0x81, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 913d09c9cd..1c2bf79541 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1283,6 +1283,29 @@ message HTLC { uint32 expiration_height = 4; } +enum CommitmentType { + /** + A channel using the legacy commitment format having tweaked to_remote + keys. + */ + LEGACY = 0; + + /** + A channel that uses the modern commitment format where the key in the + output of the remote party does not change each state. This makes back + up and recovery easier as when the channel is closed, the funds go + directly to that key. + */ + STATIC_REMOTE_KEY = 1; + + /** + A channel that uses a commitment format that has anchor outputs on the + commitments, allowing fee bumping after a force close transaction has + been broadcast. + */ + ANCHORS = 2; +} + message Channel { /// Whether this channel is active or not bool active = 1; @@ -1377,13 +1400,11 @@ message Channel { */ int64 remote_chan_reserve_sat = 21; - /** - If true, then this channel uses the modern commitment format where the key - in the output of the remote party does not change each state. This makes - back up and recovery easier as when the channel is closed, the funds go - directly to that key. - */ - bool static_remote_key = 22; + /// Deprecated. Use commitment_type. + bool static_remote_key = 22 [deprecated = true]; + + /// The commitment type used by this channel. + CommitmentType commitment_type = 26; /** The number of seconds that the channel has been monitored by the channel @@ -3336,4 +3357,4 @@ message ChannelUpdate { network in a forwards compatible manner. */ bytes extra_opaque_data = 12; -} \ No newline at end of file +} diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index fd769955ef..cf2d0e09a8 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1935,7 +1935,11 @@ "static_remote_key": { "type": "boolean", "format": "boolean", - "description": "*\nIf true, then this channel uses the modern commitment format where the key\nin the output of the remote party does not change each state. This makes\nback up and recovery easier as when the channel is closed, the funds go\ndirectly to that key." + "description": "/ Deprecated. Use commitment_type." + }, + "commitment_type": { + "$ref": "#/definitions/lnrpcCommitmentType", + "description": "/ The commitment type used by this channel." }, "lifetime": { "type": "string", @@ -2402,6 +2406,16 @@ } } }, + "lnrpcCommitmentType": { + "type": "string", + "enum": [ + "LEGACY", + "STATIC_REMOTE_KEY", + "ANCHORS" + ], + "default": "LEGACY", + "description": " - LEGACY: *\nA channel using the legacy commitment format having tweaked to_remote\nkeys.\n - STATIC_REMOTE_KEY: *\nA channel that uses the modern commitment format where the key in the\noutput of the remote party does not change each state. This makes back\nup and recovery easier as when the channel is closed, the funds go\ndirectly to that key.\n - ANCHORS: *\nA channel that uses a commitment format that has anchor outputs on the\ncommitments, allowing fee bumping after a force close transaction has\nbeen broadcast." + }, "lnrpcConnectPeerRequest": { "type": "object", "properties": { diff --git a/rpcserver.go b/rpcserver.go index f2ea166b7f..eee93b4916 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3058,6 +3058,16 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, } externalCommitFee := dbChannel.Capacity - sumOutputs + // Extract the commitment type from the channel type flags. We must + // first check whether it has anchors, since in that case it would also + // be tweakless. + commitmentType := lnrpc.CommitmentType_LEGACY + if dbChannel.ChanType.HasAnchors() { + commitmentType = lnrpc.CommitmentType_ANCHORS + } else if dbChannel.ChanType.IsTweakless() { + commitmentType = lnrpc.CommitmentType_STATIC_REMOTE_KEY + } + channel := &lnrpc.Channel{ Active: isActive, Private: !isPublic, @@ -3079,7 +3089,8 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, ChanStatusFlags: dbChannel.ChanStatus().String(), LocalChanReserveSat: int64(dbChannel.LocalChanCfg.ChanReserve), RemoteChanReserveSat: int64(dbChannel.RemoteChanCfg.ChanReserve), - StaticRemoteKey: dbChannel.ChanType.IsTweakless(), + StaticRemoteKey: commitmentType == lnrpc.CommitmentType_STATIC_REMOTE_KEY, + CommitmentType: commitmentType, } for i, htlc := range localCommit.Htlcs { From 823a9cc2c21d437792e8f3ff58558344b689758f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 18:50:35 -0700 Subject: [PATCH 213/562] chanbackup: add SCB support for new anchor commitments --- chanbackup/backup.go | 11 ----------- chanbackup/pubsub.go | 6 ------ chanbackup/single.go | 16 ++++++++++++++-- chanbackup/single_test.go | 10 +++++++++- chanrestore.go | 7 +++++++ 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/chanbackup/backup.go b/chanbackup/backup.go index 406cc1bfe5..b956c6fa90 100644 --- a/chanbackup/backup.go +++ b/chanbackup/backup.go @@ -62,12 +62,6 @@ func FetchBackupForChan(chanPoint wire.OutPoint, return nil, fmt.Errorf("unable to find target channel") } - // TODO(halseth): support chan backups for anchor types. - if targetChan.ChanType.HasAnchors() { - return nil, fmt.Errorf("channel type does not support " + - "backups yet") - } - // Once we have the target channel, we can assemble the backup using // the source to obtain any extra information that we may need. staticChanBackup, err := assembleChanBackup(chanSource, targetChan) @@ -93,11 +87,6 @@ func FetchStaticChanBackups(chanSource LiveChannelSource) ([]Single, error) { // channel. staticChanBackups := make([]Single, 0, len(openChans)) for _, openChan := range openChans { - // TODO(halseth): support chan backups for anchor types. - if openChan.ChanType.HasAnchors() { - continue - } - chanBackup, err := assembleChanBackup(chanSource, openChan) if err != nil { return nil, err diff --git a/chanbackup/pubsub.go b/chanbackup/pubsub.go index 2bc74898ec..b9331820e5 100644 --- a/chanbackup/pubsub.go +++ b/chanbackup/pubsub.go @@ -213,12 +213,6 @@ func (s *SubSwapper) backupUpdater() { // For all new open channels, we'll create a new SCB // given the required information. for _, newChan := range chanUpdate.NewChans { - // TODO(halseth): support chan backups for - // anchor types. - if newChan.ChanType.HasAnchors() { - continue - } - log.Debugf("Adding channel %v to backup state", newChan.FundingOutpoint) diff --git a/chanbackup/single.go b/chanbackup/single.go index c989bda9fd..490657b90d 100644 --- a/chanbackup/single.go +++ b/chanbackup/single.go @@ -31,6 +31,11 @@ const ( // implicitly denotes that this channel uses the new tweakless commit // format. TweaklessCommitVersion = 1 + + // AnchorsCommitVersion is the third SCB version. This version + // implicitly denotes that this channel uses the new anchor commitment + // format. + AnchorsCommitVersion = 2 ) // Single is a static description of an existing channel that can be used for @@ -157,9 +162,14 @@ func NewSingle(channel *channeldb.OpenChannel, }, } - if channel.ChanType.IsTweakless() { + switch { + case channel.ChanType.HasAnchors(): + single.Version = AnchorsCommitVersion + + case channel.ChanType.IsTweakless(): single.Version = TweaklessCommitVersion - } else { + + default: single.Version = DefaultSingleVersion } @@ -174,6 +184,7 @@ func (s *Single) Serialize(w io.Writer) error { switch s.Version { case DefaultSingleVersion: case TweaklessCommitVersion: + case AnchorsCommitVersion: default: return fmt.Errorf("unable to serialize w/ unknown "+ "version: %v", s.Version) @@ -332,6 +343,7 @@ func (s *Single) Deserialize(r io.Reader) error { switch s.Version { case DefaultSingleVersion: case TweaklessCommitVersion: + case AnchorsCommitVersion: default: return fmt.Errorf("unable to de-serialize w/ unknown "+ "version: %v", s.Version) diff --git a/chanbackup/single_test.go b/chanbackup/single_test.go index 88e2f594bb..ee20d892f6 100644 --- a/chanbackup/single_test.go +++ b/chanbackup/single_test.go @@ -229,12 +229,20 @@ func TestSinglePackUnpack(t *testing.T) { valid: true, }, - // The new tweakless version, should pack/unpack with no problem. + // The new tweakless version, should pack/unpack with no + // problem. { version: TweaklessCommitVersion, valid: true, }, + // The new anchor version, should pack/unpack with no + // problem. + { + version: AnchorsCommitVersion, + valid: true, + }, + // A non-default version, atm this should result in a failure. { version: 99, diff --git a/chanrestore.go b/chanrestore.go index ccc1b34ad3..c42f0de37c 100644 --- a/chanrestore.go +++ b/chanrestore.go @@ -106,10 +106,17 @@ func (c *chanDBRestorer) openChannelShell(backup chanbackup.Single) ( case chanbackup.TweaklessCommitVersion: chanType = channeldb.SingleFunderTweaklessBit + case chanbackup.AnchorsCommitVersion: + chanType = channeldb.AnchorOutputsBit + chanType |= channeldb.SingleFunderTweaklessBit + default: return nil, fmt.Errorf("unknown Single version: %v", err) } + ltndLog.Infof("SCB Recovery: created channel shell for ChannelPoint(%v), "+ + "chan_type=%v", backup.FundingOutpoint, chanType) + chanShell := channeldb.ChannelShell{ NodeAddrs: backup.Addresses, Chan: &channeldb.OpenChannel{ From de2fefe52a9072baa60a9c7afae26842f44323f4 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 18:50:45 -0700 Subject: [PATCH 214/562] lnwallet+lncfg: fix typos --- lncfg/protocol_legacy_on.go | 2 +- lnwallet/commitment.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lncfg/protocol_legacy_on.go b/lncfg/protocol_legacy_on.go index 9be0d1d68d..ad8086b2a8 100644 --- a/lncfg/protocol_legacy_on.go +++ b/lncfg/protocol_legacy_on.go @@ -35,7 +35,7 @@ func (l *ProtocolOptions) NoStaticRemoteKey() bool { return l.CommitmentTweak } -// AnchorCommitments returns true if support for the the anchor commitment type +// AnchorCommitments returns true if support for the anchor commitment type // should be signaled. func (l *ProtocolOptions) AnchorCommitments() bool { return l.Anchors diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 077b6da9dc..251f7b2078 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -309,7 +309,7 @@ func CommitScriptAnchors(localChanCfg, return nil, nil, err } - // And the anchor spemdable by the remote node. + // And the anchor spendable by the remote node. remoteAnchor, err := anchorScript(remoteChanCfg.MultiSigKey.PubKey) if err != nil { return nil, nil, err From 43323f98fa96e5378d1c80d192c9c6b36aed76ac Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 18:52:33 -0700 Subject: [PATCH 215/562] lntest/itest: add itest for SCB file restore for anchor commitments In this commit, we extend the current SCB recovery tests to also cover the new anchor commitment type. We only add a single test that covers the most common case to avoid needing to tests all cases for all commitment types which is being done in a follow up PR. --- lncfg/protocol_legacy_on.go | 2 +- lntest/itest/lnd_test.go | 51 ++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/lncfg/protocol_legacy_on.go b/lncfg/protocol_legacy_on.go index ad8086b2a8..ac388f0200 100644 --- a/lncfg/protocol_legacy_on.go +++ b/lncfg/protocol_legacy_on.go @@ -19,7 +19,7 @@ type ProtocolOptions struct { // Anchors should be set if we want to support opening or accepting // channels having the anchor commitment type. - Anchors bool `long:"anchors" description:"EXPERIMENTAL: enable experimental support for anchor commitments. Won't work with watchtowers or static channel backups"` + Anchors bool `long:"anchors" description:"EXPERIMENTAL: enable experimental support for anchor commitments, won't work with watchtowers"` } // LegacyOnion returns true if the old legacy onion format should be used when diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 8ca1ee7cb7..cc344372b7 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -959,11 +959,15 @@ type commitType byte const ( // commitTypeLegacy is the old school commitment type. - commitTypeLegacy = iota + commitTypeLegacy commitType = iota // commiTypeTweakless is the commitment type where the remote key is // static (non-tweaked). commitTypeTweakless + + // commitTypeAnchors is the kind of commitment that has extra outputs + // used for anchoring down to commitment using CPFP. + commitTypeAnchors ) // String returns that name of the commitment type. @@ -973,6 +977,8 @@ func (c commitType) String() string { return "legacy" case commitTypeTweakless: return "tweakless" + case commitTypeAnchors: + return "anchors" default: return "invalid" } @@ -985,6 +991,8 @@ func (c commitType) Args() []string { return []string{"--protocol.committweak"} case commitTypeTweakless: return []string{} + case commitTypeAnchors: + return []string{"--protocol.anchors"} } return nil @@ -8888,6 +8896,7 @@ func testDataLossProtection(net *lntest.NetworkHarness, t *harnessTest) { if err != nil { t.Fatalf("unable to suspend node: %v", err) } + return restart, chanPoint, balResp.ConfirmedBalance, nil } @@ -13986,6 +13995,10 @@ type chanRestoreTestCase struct { // confirmed or not. unconfirmed bool + // anchorCommit is true, then the new anchor commitment type will be + // used for the channels created in the test. + anchorCommit bool + // restoreMethod takes an old node, then returns a function // closure that'll return the same node, but with its state // restored via a custom method. We use this to abstract away @@ -14010,11 +14023,16 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness, ctxb := context.Background() + var nodeArgs []string + if testCase.anchorCommit { + nodeArgs = commitTypeAnchors.Args() + } + // First, we'll create a brand new node we'll use within the test. If // we have a custom backup file specified, then we'll also create that // for use. dave, mnemonic, err := net.NewNodeWithSeed( - "dave", nil, password, + "dave", nodeArgs, password, ) if err != nil { t.Fatalf("unable to create new node: %v", err) @@ -14024,7 +14042,7 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness, defer func() { shutdownAndAssert(net, t, dave) }() - carol, err := net.NewNode("carol", nil) + carol, err := net.NewNode("carol", nodeArgs) if err != nil { t.Fatalf("unable to make new node: %v", err) } @@ -14545,6 +14563,33 @@ func testChannelBackupRestore(net *lntest.NetworkHarness, t *harnessTest) { ) }, }, + + // Restore the backup from the on-disk file, using the RPC + // interface, for anchor commitment channels. + { + name: "restore from backup file anchors", + initiator: true, + private: false, + anchorCommit: true, + restoreMethod: func(oldNode *lntest.HarnessNode, + backupFilePath string, + mnemonic []string) (nodeRestorer, error) { + + // Read the entire Multi backup stored within + // this node's channels.backup file. + multi, err := ioutil.ReadFile(backupFilePath) + if err != nil { + return nil, err + } + + // Now that we have Dave's backup file, we'll + // create a new nodeRestorer that will restore + // using the on-disk channels.backup. + return chanRestoreViaRPC( + net, password, mnemonic, multi, + ) + }, + }, } // TODO(roasbeef): online vs offline close? From a223e4eedb17601c174ca748ab5d16255f1e281d Mon Sep 17 00:00:00 2001 From: carla Date: Tue, 17 Mar 2020 08:22:23 +0200 Subject: [PATCH 216/562] queue: add fixed size circular buffer This commit introduces a fixed size circular buffer which stores elements in a fixed size underlying array, wrapping to overwrite items when the buffer gets full. --- queue/circular_buf.go | 116 ++++++++++++++++++++++ queue/circular_buf_test.go | 198 +++++++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 queue/circular_buf.go create mode 100644 queue/circular_buf_test.go diff --git a/queue/circular_buf.go b/queue/circular_buf.go new file mode 100644 index 0000000000..5e319f004c --- /dev/null +++ b/queue/circular_buf.go @@ -0,0 +1,116 @@ +package queue + +import ( + "errors" +) + +// errInvalidSize is returned when an invalid size for a buffer is provided. +var errInvalidSize = errors.New("buffer size must be > 0") + +// CircularBuffer is a buffer which retains a set of values in memory, and +// overwrites the oldest item in the buffer when a new item needs to be +// written. +type CircularBuffer struct { + // total is the total number of items that have been added to the + // buffer. + total int + + // items is the set of buffered items. + items []interface{} +} + +// NewCircularBuffer returns a new circular buffer with the size provided. It +// will fail if a zero or negative size parameter is provided. +func NewCircularBuffer(size int) (*CircularBuffer, error) { + if size <= 0 { + return nil, errInvalidSize + } + + return &CircularBuffer{ + total: 0, + + // Create a slice with length and capacity equal to the size of + // the buffer so that we do not need to resize the underlying + // array when we add items. + items: make([]interface{}, size), + }, nil +} + +// index returns the index that should be written to next. +func (c *CircularBuffer) index() int { + return c.total % len(c.items) +} + +// Add adds an item to the buffer, overwriting the oldest item if the buffer +// is full. +func (c *CircularBuffer) Add(item interface{}) { + // Set the item in the next free index in the items array. + c.items[c.index()] = item + + // Increment the total number of items that we have stored. + c.total++ +} + +// List returns a copy of the items in the buffer ordered from the oldest to +// newest item. +func (c *CircularBuffer) List() []interface{} { + size := cap(c.items) + index := c.index() + + switch { + // If no items have been stored yet, we can just return a nil list. + case c.total == 0: + return nil + + // If we have added fewer items than the buffer size, we can simply + // return the total number of items from the beginning of the list + // to the index. This special case is added because the oldest item + // is at the beginning of the underlying array, not at the index when + // we have not filled the array yet. + case c.total < size: + resp := make([]interface{}, c.total) + copy(resp, c.items[:c.index()]) + return resp + } + + resp := make([]interface{}, size) + + // Get the items in the underlying array from index to end, the first + // item in this slice will be the oldest item in the list. + firstHalf := c.items[index:] + + // Copy the first set into our response slice from index 0, so that + // the response returned is from oldest to newest. + copy(resp, firstHalf) + + // Get the items in the underlying array from beginning until the write + // index, the last item in this slice will be the newest item in the + // list. + secondHalf := c.items[:index] + + // Copy the second set of items into the response slice offset by the + // length of the first set of items so that we return a response which + // is ordered from oldest to newest entry. + copy(resp[len(firstHalf):], secondHalf) + + return resp +} + +// Total returns the total number of items that have been added to the buffer. +func (c *CircularBuffer) Total() int { + return c.total +} + +// Latest returns the item that was most recently added to the buffer. +func (c *CircularBuffer) Latest() interface{} { + // If no items have been added yet, return nil. + if c.total == 0 { + return nil + } + + // The latest item is one before our total, mod by length. + latest := (c.total - 1) % len(c.items) + + // Return the latest item added. + return c.items[latest] +} diff --git a/queue/circular_buf_test.go b/queue/circular_buf_test.go new file mode 100644 index 0000000000..4f2c029c90 --- /dev/null +++ b/queue/circular_buf_test.go @@ -0,0 +1,198 @@ +package queue + +import ( + "reflect" + "testing" +) + +// TestNewCircularBuffer tests the size parameter check when creating a circular +// buffer. +func TestNewCircularBuffer(t *testing.T) { + tests := []struct { + name string + size int + expectedError error + }{ + { + name: "zero size", + size: 0, + expectedError: errInvalidSize, + }, + { + name: "negative size", + size: -1, + expectedError: errInvalidSize, + }, + { + name: "ok size", + size: 1, + expectedError: nil, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + _, err := NewCircularBuffer(test.size) + if err != test.expectedError { + t.Fatalf("expected: %v, got: %v", + test.expectedError, err) + } + }) + } +} + +// TestCircularBuffer tests the adding and listing of items in a circular +// buffer. +func TestCircularBuffer(t *testing.T) { + tests := []struct { + name string + size int + itemCount int + expectedItems []interface{} + }{ + { + name: "no elements", + size: 5, + itemCount: 0, + expectedItems: nil, + }, + { + name: "single element", + size: 5, + itemCount: 1, + expectedItems: []interface{}{ + 0, + }, + }, + { + name: "no wrap, not full", + size: 5, + itemCount: 4, + expectedItems: []interface{}{ + 0, 1, 2, 3, + }, + }, + { + name: "no wrap, exactly full", + size: 5, + itemCount: 5, + expectedItems: []interface{}{ + 0, 1, 2, 3, 4, + }, + }, + { + // The underlying array should contain {5, 1, 2, 3, 4}. + name: "wrap, one over", + size: 5, + itemCount: 6, + expectedItems: []interface{}{ + 1, 2, 3, 4, 5, + }, + }, + { + // The underlying array should contain {5, 6, 2, 3, 4}. + name: "wrap, two over", + size: 5, + itemCount: 7, + expectedItems: []interface{}{ + 2, 3, 4, 5, 6, + }, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + buffer, err := NewCircularBuffer(test.size) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + for i := 0; i < test.itemCount; i++ { + buffer.Add(i) + } + + // List the items in the buffer and check that the list + // is as expected. + list := buffer.List() + if !reflect.DeepEqual(test.expectedItems, list) { + t.Fatalf("expected %v, got: %v", + test.expectedItems, list) + } + }) + } +} + +// TestLatest tests fetching of the last item added to a circular buffer. +func TestLatest(t *testing.T) { + tests := []struct { + name string + size int + + // items is the number of items to add to the buffer. + items int + + // expectedItem is the value we expect from Latest(). + expectedItem interface{} + }{ + { + name: "no items", + size: 3, + items: 0, + expectedItem: nil, + }, + { + name: "one item", + size: 3, + items: 1, + expectedItem: 0, + }, + { + name: "exactly full", + size: 3, + items: 3, + expectedItem: 2, + }, + { + name: "overflow to index 0", + size: 3, + items: 4, + expectedItem: 3, + }, + { + name: "overflow twice to index 0", + size: 3, + items: 7, + expectedItem: 6, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + //t.Parallel() + + buffer, err := NewCircularBuffer(test.size) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + for i := 0; i < test.items; i++ { + buffer.Add(i) + } + + latest := buffer.Latest() + + if !reflect.DeepEqual(latest, test.expectedItem) { + t.Fatalf("expected: %v, got: %v", + test.expectedItem, latest) + } + }) + } +} From 54089febd60a9349d12d7ddd365f43d242431368 Mon Sep 17 00:00:00 2001 From: carla Date: Tue, 17 Mar 2020 08:22:35 +0200 Subject: [PATCH 217/562] peer+server: store errors for peers with open channels Add an error buffer to the peer struct which will store errors for peers that we have active channels with. We do not store these errors with peers that we do not have channels open with to prevent peers from connecting and costlessly spamming us with error messages. When the peer disconnects, the error buffer is offloaded to the server so that we can track errors across connections. When peers reconnect, they are created with their historic error buffer. --- peer.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++----- server.go | 34 ++++++++++++++++++++++- 2 files changed, 107 insertions(+), 8 deletions(-) diff --git a/peer.go b/peer.go index 5aef5f592a..2236e66c3a 100644 --- a/peer.go +++ b/peer.go @@ -28,6 +28,7 @@ import ( "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/pool" + "github.com/lightningnetwork/lnd/queue" "github.com/lightningnetwork/lnd/ticker" ) @@ -52,6 +53,9 @@ const ( // messages to be sent across the wire, requested by objects outside // this struct. outgoingQueueLen = 50 + + // errorBufferSize is the number of historic peer errors that we store. + errorBufferSize = 10 ) // outgoingMsg packages an lnwire.Message to be sent out on the wire, along with @@ -91,6 +95,13 @@ type channelCloseUpdate struct { Success bool } +// timestampedError is a timestamped error that is used to store the most recent +// errors we have experienced with our peers. +type timestampedError struct { + error error + timestamp time.Time +} + // peer is an active peer on the Lightning Network. This struct is responsible // for managing any channel state related to this peer. To do so, it has // several helper goroutines to handle events such as HTLC timeouts, new @@ -216,6 +227,14 @@ type peer struct { // peer's chansync message with its own over and over again. resentChanSyncMsg map[lnwire.ChannelID]struct{} + // errorBuffer stores a set of errors related to a peer. It contains + // error messages that our peer has recently sent us over the wire and + // records of unknown messages that were sent to us and, so that we can + // track a full record of the communication errors we have had with our + // peer. If we choose to disconnect from a peer, it also stores the + // reason we had for disconnecting. + errorBuffer *queue.CircularBuffer + // writePool is the task pool to that manages reuse of write buffers. // Write tasks are submitted to the pool in order to conserve the total // number of write buffers allocated at any one time, and decouple write @@ -233,12 +252,15 @@ type peer struct { var _ lnpeer.Peer = (*peer)(nil) // newPeer creates a new peer from an establish connection object, and a -// pointer to the main server. +// pointer to the main server. It takes an error buffer which may contain errors +// from a previous connection with the peer if we have been connected to them +// before. func newPeer(conn net.Conn, connReq *connmgr.ConnReq, server *server, addr *lnwire.NetAddress, inbound bool, features, legacyFeatures *lnwire.FeatureVector, chanActiveTimeout time.Duration, - outgoingCltvRejectDelta uint32) ( + outgoingCltvRejectDelta uint32, + errBuffer *queue.CircularBuffer) ( *peer, error) { nodePub := addr.IdentityKey @@ -276,6 +298,8 @@ func newPeer(conn net.Conn, connReq *connmgr.ConnReq, server *server, chanActiveTimeout: chanActiveTimeout, + errorBuffer: errBuffer, + writePool: server.writePool, readPool: server.readPool, @@ -338,6 +362,7 @@ func (p *peer) Start() error { msg := <-msgChan if msg, ok := msg.(*lnwire.Init); ok { if err := p.handleInitMsg(msg); err != nil { + p.storeError(err) return err } } else { @@ -668,7 +693,10 @@ func (p *peer) Disconnect(reason error) { return } - peerLog.Infof("Disconnecting %s, reason: %v", p, reason) + err := fmt.Errorf("disconnecting %s, reason: %v", p, reason) + p.storeError(err) + + peerLog.Infof(err.Error()) // Ensure that the TCP connection is properly closed before continuing. p.conn.Close() @@ -1026,12 +1054,17 @@ out: peerLog.Infof("unable to read message from %v: %v", p, err) - switch err.(type) { + // If we could not read our peer's message due to an + // unknown type or invalid alias, we continue processing + // as normal. We store unknown message and address + // types, as they may provide debugging insight. + switch e := err.(type) { // If this is just a message we don't yet recognize, // we'll continue processing as normal as this allows // us to introduce new messages in a forwards // compatible manner. case *lnwire.UnknownMessage: + p.storeError(e) idleTimer.Reset(idleTimeout) continue @@ -1040,12 +1073,15 @@ out: // simply continue parsing the remainder of their // messages. case *lnwire.ErrUnknownAddrType: + p.storeError(e) idleTimer.Reset(idleTimeout) continue // If the NodeAnnouncement has an invalid alias, then // we'll log that error above and continue so we can - // continue to read messges from the peer. + // continue to read messages from the peer. We do not + // store this error because it is of little debugging + // value. case *lnwire.ErrInvalidNodeAlias: idleTimer.Reset(idleTimeout) continue @@ -1141,8 +1177,13 @@ out: discStream.AddMsg(msg) default: - peerLog.Errorf("unknown message %v received from peer "+ - "%v", uint16(msg.MsgType()), p) + // If the message we received is unknown to us, store + // the type to track the failure. + err := fmt.Errorf("unknown message type %v received", + uint16(msg.MsgType())) + p.storeError(err) + + peerLog.Errorf("peer: %v, %v", p, err) } if isLinkUpdate { @@ -1181,13 +1222,39 @@ func (p *peer) isActiveChannel(chanID lnwire.ChannelID) bool { return ok } +// storeError stores an error in our peer's buffer of recent errors with the +// current timestamp. Errors are only stored if we have at least one active +// channel with the peer to mitigate dos attack vectors where a peer costlessly +// connects to us and spams us with errors. +func (p *peer) storeError(err error) { + p.activeChanMtx.RLock() + channelCount := len(p.activeChannels) + p.activeChanMtx.RUnlock() + + // If we do not have any active channels with the peer, we do not store + // errors as a dos mitigation. + if channelCount == 0 { + peerLog.Tracef("no channels with peer: %v, not storing err", p) + return + } + + p.errorBuffer.Add( + ×tampedError{timestamp: time.Now(), error: err}, + ) +} + // handleError processes an error message read from the remote peer. The boolean // returns indicates whether the message should be delivered to a targeted peer. +// It stores the error we received from the peer in memory if we have a channel +// open with the peer. // // NOTE: This method should only be called from within the readHandler. func (p *peer) handleError(msg *lnwire.Error) bool { key := p.addr.IdentityKey + // Store the error we have received. + p.storeError(msg) + switch { // In the case of an all-zero channel ID we want to forward the error to diff --git a/server.go b/server.go index 0864d99ef5..98f446d7b3 100644 --- a/server.go +++ b/server.go @@ -53,6 +53,7 @@ import ( "github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/peernotifier" "github.com/lightningnetwork/lnd/pool" + "github.com/lightningnetwork/lnd/queue" "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/routing/localchans" "github.com/lightningnetwork/lnd/routing/route" @@ -176,6 +177,12 @@ type server struct { persistentConnReqs map[string][]*connmgr.ConnReq persistentRetryCancels map[string]chan struct{} + // peerErrors keeps a set of peer error buffers for peers that have + // disconnected from us. This allows us to track historic peer errors + // over connections. The string of the peer's compressed pubkey is used + // as a key for this map. + peerErrors map[string]*queue.CircularBuffer + // ignorePeerTermination tracks peers for which the server has initiated // a disconnect. Adding a peer to this map causes the peer termination // watcher to short circuit in the event that peers are purposefully @@ -425,6 +432,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, persistentPeersBackoff: make(map[string]time.Duration), persistentConnReqs: make(map[string][]*connmgr.ConnReq), persistentRetryCancels: make(map[string]chan struct{}), + peerErrors: make(map[string]*queue.CircularBuffer), ignorePeerTermination: make(map[*peer]struct{}), scheduledPeerConnection: make(map[string]func()), @@ -2782,6 +2790,19 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, initFeatures := s.featureMgr.Get(feature.SetInit) legacyFeatures := s.featureMgr.Get(feature.SetLegacyGlobal) + // Lookup past error caches for the peer in the server. If no buffer is + // found, create a fresh buffer. + pkStr := string(peerAddr.IdentityKey.SerializeCompressed()) + errBuffer, ok := s.peerErrors[pkStr] + if !ok { + var err error + errBuffer, err = queue.NewCircularBuffer(errorBufferSize) + if err != nil { + srvrLog.Errorf("unable to create peer %v", err) + return + } + } + // Now that we've established a connection, create a peer, and it to the // set of currently active peers. Configure the peer with the incoming // and outgoing broadcast deltas to prevent htlcs from being accepted or @@ -2791,7 +2812,7 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, p, err := newPeer( conn, connReq, s, peerAddr, inbound, initFeatures, legacyFeatures, cfg.ChanEnableTimeout, - defaultOutgoingCltvRejectDelta, + defaultOutgoingCltvRejectDelta, errBuffer, ) if err != nil { srvrLog.Errorf("unable to create peer %v", err) @@ -2803,6 +2824,11 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, s.addPeer(p) + // Once we have successfully added the peer to the server, we can + // delete the previous error buffer from the server's map of error + // buffers. + delete(s.peerErrors, pkStr) + // Dispatch a goroutine to asynchronously start the peer. This process // includes sending and receiving Init messages, which would be a DOS // vector if we held the server's mutex throughout the procedure. @@ -3097,6 +3123,12 @@ func (s *server) removePeer(p *peer) { delete(s.outboundPeers, pubStr) } + // Copy the peer's error buffer across to the server if it has any items + // in it so that we can restore peer errors across connections. + if p.errorBuffer.Total() > 0 { + s.peerErrors[pubStr] = p.errorBuffer + } + // Inform the peer notifier of a peer offline event so that it can be // reported to clients listening for peer events. var pubKey [33]byte From 4c48d0361d45bb457cf0727d1c8279e223fad9c9 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 13 Mar 2020 09:15:49 +0200 Subject: [PATCH 218/562] lnrpc+lncli: display peer errors in listpeers This change adds a set of errors to the peer struct returned by list peers. A latest error boolean is added to allow for more succinct default lncli responses. --- cmd/lncli/commands.go | 14 +- lnrpc/rpc.pb.go | 1700 +++++++++++++++++++++------------------- lnrpc/rpc.pb.gw.go | 8 + lnrpc/rpc.proto | 23 + lnrpc/rpc.swagger.json | 31 + rpcserver.go | 27 + 6 files changed, 991 insertions(+), 812 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 36ebe97dd8..15a2b04075 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1335,7 +1335,13 @@ var listPeersCommand = cli.Command{ Name: "listpeers", Category: "Peers", Usage: "List all active, currently connected peers.", - Action: actionDecorator(listPeers), + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "list_errors", + Usage: "list a full set of most recent errors for the peer", + }, + }, + Action: actionDecorator(listPeers), } func listPeers(ctx *cli.Context) error { @@ -1343,7 +1349,11 @@ func listPeers(ctx *cli.Context) error { client, cleanUp := getClient(ctx) defer cleanUp() - req := &lnrpc.ListPeersRequest{} + // By default, we display a single error on the cli. If the user + // specifically requests a full error set, then we will provide it. + req := &lnrpc.ListPeersRequest{ + LatestError: !ctx.IsSet("list_errors"), + } resp, err := client.ListPeers(ctxb, req) if err != nil { return err diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 011ccd40bc..e8637661a4 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -321,7 +321,7 @@ func (x PeerEvent_EventType) String() string { } func (PeerEvent_EventType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{50, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{51, 0} } type ChannelEventUpdate_UpdateType int32 @@ -355,7 +355,7 @@ func (x ChannelEventUpdate_UpdateType) String() string { } func (ChannelEventUpdate_UpdateType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{73, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{74, 0} } type Invoice_InvoiceState int32 @@ -386,7 +386,7 @@ func (x Invoice_InvoiceState) String() string { } func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{105, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{106, 0} } type Payment_PaymentStatus int32 @@ -417,7 +417,7 @@ func (x Payment_PaymentStatus) String() string { } func (Payment_PaymentStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{112, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{113, 0} } type HTLCAttempt_HTLCStatus int32 @@ -445,7 +445,7 @@ func (x HTLCAttempt_HTLCStatus) String() string { } func (HTLCAttempt_HTLCStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{113, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{114, 0} } type Failure_FailureCode int32 @@ -556,7 +556,7 @@ func (x Failure_FailureCode) String() string { } func (Failure_FailureCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{146, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{147, 0} } type GenSeedRequest struct { @@ -3664,7 +3664,14 @@ type Peer struct { // The type of sync we are currently performing with this peer. SyncType Peer_SyncType `protobuf:"varint,10,opt,name=sync_type,json=syncType,proto3,enum=lnrpc.Peer_SyncType" json:"sync_type,omitempty"` /// Features advertised by the remote peer in their init message. - Features map[uint32]*Feature `protobuf:"bytes,11,rep,name=features,proto3" json:"features,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Features map[uint32]*Feature `protobuf:"bytes,11,rep,name=features,proto3" json:"features,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // + //The latest errors received from our peer with timestamps, limited to the 10 + //most recent errors. These errors are tracked across peer connections, but + //are not persisted across lnd restarts. Note that these errors are only + //stored for peers that we have channels open with, to prevent peers from + //spamming us with errors at no cost. + Errors []*TimestampedError `protobuf:"bytes,12,rep,name=errors,proto3" json:"errors,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -3765,7 +3772,68 @@ func (m *Peer) GetFeatures() map[uint32]*Feature { return nil } +func (m *Peer) GetErrors() []*TimestampedError { + if m != nil { + return m.Errors + } + return nil +} + +type TimestampedError struct { + // The unix timestamp in seconds when the error occurred. + Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // The string representation of the error sent by our peer. + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TimestampedError) Reset() { *m = TimestampedError{} } +func (m *TimestampedError) String() string { return proto.CompactTextString(m) } +func (*TimestampedError) ProtoMessage() {} +func (*TimestampedError) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{47} +} + +func (m *TimestampedError) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TimestampedError.Unmarshal(m, b) +} +func (m *TimestampedError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TimestampedError.Marshal(b, m, deterministic) +} +func (m *TimestampedError) XXX_Merge(src proto.Message) { + xxx_messageInfo_TimestampedError.Merge(m, src) +} +func (m *TimestampedError) XXX_Size() int { + return xxx_messageInfo_TimestampedError.Size(m) +} +func (m *TimestampedError) XXX_DiscardUnknown() { + xxx_messageInfo_TimestampedError.DiscardUnknown(m) +} + +var xxx_messageInfo_TimestampedError proto.InternalMessageInfo + +func (m *TimestampedError) GetTimestamp() uint64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *TimestampedError) GetError() string { + if m != nil { + return m.Error + } + return "" +} + type ListPeersRequest struct { + // + //If true, only the last error that our peer sent us will be returned with + //the peer's information, rather than the full set of historic errors we have + //stored. + LatestError bool `protobuf:"varint,1,opt,name=latest_error,json=latestError,proto3" json:"latest_error,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -3775,7 +3843,7 @@ func (m *ListPeersRequest) Reset() { *m = ListPeersRequest{} } func (m *ListPeersRequest) String() string { return proto.CompactTextString(m) } func (*ListPeersRequest) ProtoMessage() {} func (*ListPeersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{47} + return fileDescriptor_77a6da22d6a3feb1, []int{48} } func (m *ListPeersRequest) XXX_Unmarshal(b []byte) error { @@ -3796,6 +3864,13 @@ func (m *ListPeersRequest) XXX_DiscardUnknown() { var xxx_messageInfo_ListPeersRequest proto.InternalMessageInfo +func (m *ListPeersRequest) GetLatestError() bool { + if m != nil { + return m.LatestError + } + return false +} + type ListPeersResponse struct { /// The list of currently connected peers Peers []*Peer `protobuf:"bytes,1,rep,name=peers,proto3" json:"peers,omitempty"` @@ -3808,7 +3883,7 @@ func (m *ListPeersResponse) Reset() { *m = ListPeersResponse{} } func (m *ListPeersResponse) String() string { return proto.CompactTextString(m) } func (*ListPeersResponse) ProtoMessage() {} func (*ListPeersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{48} + return fileDescriptor_77a6da22d6a3feb1, []int{49} } func (m *ListPeersResponse) XXX_Unmarshal(b []byte) error { @@ -3846,7 +3921,7 @@ func (m *PeerEventSubscription) Reset() { *m = PeerEventSubscription{} } func (m *PeerEventSubscription) String() string { return proto.CompactTextString(m) } func (*PeerEventSubscription) ProtoMessage() {} func (*PeerEventSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{49} + return fileDescriptor_77a6da22d6a3feb1, []int{50} } func (m *PeerEventSubscription) XXX_Unmarshal(b []byte) error { @@ -3880,7 +3955,7 @@ func (m *PeerEvent) Reset() { *m = PeerEvent{} } func (m *PeerEvent) String() string { return proto.CompactTextString(m) } func (*PeerEvent) ProtoMessage() {} func (*PeerEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{50} + return fileDescriptor_77a6da22d6a3feb1, []int{51} } func (m *PeerEvent) XXX_Unmarshal(b []byte) error { @@ -3925,7 +4000,7 @@ func (m *GetInfoRequest) Reset() { *m = GetInfoRequest{} } func (m *GetInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetInfoRequest) ProtoMessage() {} func (*GetInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{51} + return fileDescriptor_77a6da22d6a3feb1, []int{52} } func (m *GetInfoRequest) XXX_Unmarshal(b []byte) error { @@ -3994,7 +4069,7 @@ func (m *GetInfoResponse) Reset() { *m = GetInfoResponse{} } func (m *GetInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetInfoResponse) ProtoMessage() {} func (*GetInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{52} + return fileDescriptor_77a6da22d6a3feb1, []int{53} } func (m *GetInfoResponse) XXX_Unmarshal(b []byte) error { @@ -4149,7 +4224,7 @@ func (m *Chain) Reset() { *m = Chain{} } func (m *Chain) String() string { return proto.CompactTextString(m) } func (*Chain) ProtoMessage() {} func (*Chain) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{53} + return fileDescriptor_77a6da22d6a3feb1, []int{54} } func (m *Chain) XXX_Unmarshal(b []byte) error { @@ -4197,7 +4272,7 @@ func (m *ConfirmationUpdate) Reset() { *m = ConfirmationUpdate{} } func (m *ConfirmationUpdate) String() string { return proto.CompactTextString(m) } func (*ConfirmationUpdate) ProtoMessage() {} func (*ConfirmationUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{54} + return fileDescriptor_77a6da22d6a3feb1, []int{55} } func (m *ConfirmationUpdate) XXX_Unmarshal(b []byte) error { @@ -4250,7 +4325,7 @@ func (m *ChannelOpenUpdate) Reset() { *m = ChannelOpenUpdate{} } func (m *ChannelOpenUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelOpenUpdate) ProtoMessage() {} func (*ChannelOpenUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{55} + return fileDescriptor_77a6da22d6a3feb1, []int{56} } func (m *ChannelOpenUpdate) XXX_Unmarshal(b []byte) error { @@ -4290,7 +4365,7 @@ func (m *ChannelCloseUpdate) Reset() { *m = ChannelCloseUpdate{} } func (m *ChannelCloseUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelCloseUpdate) ProtoMessage() {} func (*ChannelCloseUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{56} + return fileDescriptor_77a6da22d6a3feb1, []int{57} } func (m *ChannelCloseUpdate) XXX_Unmarshal(b []byte) error { @@ -4355,7 +4430,7 @@ func (m *CloseChannelRequest) Reset() { *m = CloseChannelRequest{} } func (m *CloseChannelRequest) String() string { return proto.CompactTextString(m) } func (*CloseChannelRequest) ProtoMessage() {} func (*CloseChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{57} + return fileDescriptor_77a6da22d6a3feb1, []int{58} } func (m *CloseChannelRequest) XXX_Unmarshal(b []byte) error { @@ -4425,7 +4500,7 @@ func (m *CloseStatusUpdate) Reset() { *m = CloseStatusUpdate{} } func (m *CloseStatusUpdate) String() string { return proto.CompactTextString(m) } func (*CloseStatusUpdate) ProtoMessage() {} func (*CloseStatusUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{58} + return fileDescriptor_77a6da22d6a3feb1, []int{59} } func (m *CloseStatusUpdate) XXX_Unmarshal(b []byte) error { @@ -4503,7 +4578,7 @@ func (m *PendingUpdate) Reset() { *m = PendingUpdate{} } func (m *PendingUpdate) String() string { return proto.CompactTextString(m) } func (*PendingUpdate) ProtoMessage() {} func (*PendingUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{59} + return fileDescriptor_77a6da22d6a3feb1, []int{60} } func (m *PendingUpdate) XXX_Unmarshal(b []byte) error { @@ -4599,7 +4674,7 @@ func (m *OpenChannelRequest) Reset() { *m = OpenChannelRequest{} } func (m *OpenChannelRequest) String() string { return proto.CompactTextString(m) } func (*OpenChannelRequest) ProtoMessage() {} func (*OpenChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{60} + return fileDescriptor_77a6da22d6a3feb1, []int{61} } func (m *OpenChannelRequest) XXX_Unmarshal(b []byte) error { @@ -4730,7 +4805,7 @@ func (m *OpenStatusUpdate) Reset() { *m = OpenStatusUpdate{} } func (m *OpenStatusUpdate) String() string { return proto.CompactTextString(m) } func (*OpenStatusUpdate) ProtoMessage() {} func (*OpenStatusUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{61} + return fileDescriptor_77a6da22d6a3feb1, []int{62} } func (m *OpenStatusUpdate) XXX_Unmarshal(b []byte) error { @@ -4817,7 +4892,7 @@ func (m *KeyLocator) Reset() { *m = KeyLocator{} } func (m *KeyLocator) String() string { return proto.CompactTextString(m) } func (*KeyLocator) ProtoMessage() {} func (*KeyLocator) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{62} + return fileDescriptor_77a6da22d6a3feb1, []int{63} } func (m *KeyLocator) XXX_Unmarshal(b []byte) error { @@ -4868,7 +4943,7 @@ func (m *KeyDescriptor) Reset() { *m = KeyDescriptor{} } func (m *KeyDescriptor) String() string { return proto.CompactTextString(m) } func (*KeyDescriptor) ProtoMessage() {} func (*KeyDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{63} + return fileDescriptor_77a6da22d6a3feb1, []int{64} } func (m *KeyDescriptor) XXX_Unmarshal(b []byte) error { @@ -4929,7 +5004,7 @@ func (m *ChanPointShim) Reset() { *m = ChanPointShim{} } func (m *ChanPointShim) String() string { return proto.CompactTextString(m) } func (*ChanPointShim) ProtoMessage() {} func (*ChanPointShim) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{64} + return fileDescriptor_77a6da22d6a3feb1, []int{65} } func (m *ChanPointShim) XXX_Unmarshal(b []byte) error { @@ -4998,7 +5073,7 @@ func (m *FundingShim) Reset() { *m = FundingShim{} } func (m *FundingShim) String() string { return proto.CompactTextString(m) } func (*FundingShim) ProtoMessage() {} func (*FundingShim) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{65} + return fileDescriptor_77a6da22d6a3feb1, []int{66} } func (m *FundingShim) XXX_Unmarshal(b []byte) error { @@ -5062,7 +5137,7 @@ func (m *FundingShimCancel) Reset() { *m = FundingShimCancel{} } func (m *FundingShimCancel) String() string { return proto.CompactTextString(m) } func (*FundingShimCancel) ProtoMessage() {} func (*FundingShimCancel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{66} + return fileDescriptor_77a6da22d6a3feb1, []int{67} } func (m *FundingShimCancel) XXX_Unmarshal(b []byte) error { @@ -5104,7 +5179,7 @@ func (m *FundingTransitionMsg) Reset() { *m = FundingTransitionMsg{} } func (m *FundingTransitionMsg) String() string { return proto.CompactTextString(m) } func (*FundingTransitionMsg) ProtoMessage() {} func (*FundingTransitionMsg) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{67} + return fileDescriptor_77a6da22d6a3feb1, []int{68} } func (m *FundingTransitionMsg) XXX_Unmarshal(b []byte) error { @@ -5180,7 +5255,7 @@ func (m *FundingStateStepResp) Reset() { *m = FundingStateStepResp{} } func (m *FundingStateStepResp) String() string { return proto.CompactTextString(m) } func (*FundingStateStepResp) ProtoMessage() {} func (*FundingStateStepResp) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{68} + return fileDescriptor_77a6da22d6a3feb1, []int{69} } func (m *FundingStateStepResp) XXX_Unmarshal(b []byte) error { @@ -5226,7 +5301,7 @@ func (m *PendingHTLC) Reset() { *m = PendingHTLC{} } func (m *PendingHTLC) String() string { return proto.CompactTextString(m) } func (*PendingHTLC) ProtoMessage() {} func (*PendingHTLC) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{69} + return fileDescriptor_77a6da22d6a3feb1, []int{70} } func (m *PendingHTLC) XXX_Unmarshal(b []byte) error { @@ -5299,7 +5374,7 @@ func (m *PendingChannelsRequest) Reset() { *m = PendingChannelsRequest{} func (m *PendingChannelsRequest) String() string { return proto.CompactTextString(m) } func (*PendingChannelsRequest) ProtoMessage() {} func (*PendingChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{70} + return fileDescriptor_77a6da22d6a3feb1, []int{71} } func (m *PendingChannelsRequest) XXX_Unmarshal(b []byte) error { @@ -5340,7 +5415,7 @@ func (m *PendingChannelsResponse) Reset() { *m = PendingChannelsResponse func (m *PendingChannelsResponse) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse) ProtoMessage() {} func (*PendingChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{71} + return fileDescriptor_77a6da22d6a3feb1, []int{72} } func (m *PendingChannelsResponse) XXX_Unmarshal(b []byte) error { @@ -5420,7 +5495,7 @@ func (m *PendingChannelsResponse_PendingChannel) Reset() { func (m *PendingChannelsResponse_PendingChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_PendingChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{71, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{72, 0} } func (m *PendingChannelsResponse_PendingChannel) XXX_Unmarshal(b []byte) error { @@ -5522,7 +5597,7 @@ func (m *PendingChannelsResponse_PendingOpenChannel) String() string { } func (*PendingChannelsResponse_PendingOpenChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingOpenChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{71, 1} + return fileDescriptor_77a6da22d6a3feb1, []int{72, 1} } func (m *PendingChannelsResponse_PendingOpenChannel) XXX_Unmarshal(b []byte) error { @@ -5596,7 +5671,7 @@ func (m *PendingChannelsResponse_WaitingCloseChannel) String() string { } func (*PendingChannelsResponse_WaitingCloseChannel) ProtoMessage() {} func (*PendingChannelsResponse_WaitingCloseChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{71, 2} + return fileDescriptor_77a6da22d6a3feb1, []int{72, 2} } func (m *PendingChannelsResponse_WaitingCloseChannel) XXX_Unmarshal(b []byte) error { @@ -5645,7 +5720,7 @@ func (m *PendingChannelsResponse_ClosedChannel) Reset() { *m = PendingCh func (m *PendingChannelsResponse_ClosedChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_ClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{71, 3} + return fileDescriptor_77a6da22d6a3feb1, []int{72, 3} } func (m *PendingChannelsResponse_ClosedChannel) XXX_Unmarshal(b []byte) error { @@ -5710,7 +5785,7 @@ func (m *PendingChannelsResponse_ForceClosedChannel) String() string { } func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ForceClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{71, 4} + return fileDescriptor_77a6da22d6a3feb1, []int{72, 4} } func (m *PendingChannelsResponse_ForceClosedChannel) XXX_Unmarshal(b []byte) error { @@ -5790,7 +5865,7 @@ func (m *ChannelEventSubscription) Reset() { *m = ChannelEventSubscripti func (m *ChannelEventSubscription) String() string { return proto.CompactTextString(m) } func (*ChannelEventSubscription) ProtoMessage() {} func (*ChannelEventSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72} + return fileDescriptor_77a6da22d6a3feb1, []int{73} } func (m *ChannelEventSubscription) XXX_Unmarshal(b []byte) error { @@ -5829,7 +5904,7 @@ func (m *ChannelEventUpdate) Reset() { *m = ChannelEventUpdate{} } func (m *ChannelEventUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelEventUpdate) ProtoMessage() {} func (*ChannelEventUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{73} + return fileDescriptor_77a6da22d6a3feb1, []int{74} } func (m *ChannelEventUpdate) XXX_Unmarshal(b []byte) error { @@ -5954,7 +6029,7 @@ func (m *WalletBalanceRequest) Reset() { *m = WalletBalanceRequest{} } func (m *WalletBalanceRequest) String() string { return proto.CompactTextString(m) } func (*WalletBalanceRequest) ProtoMessage() {} func (*WalletBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{74} + return fileDescriptor_77a6da22d6a3feb1, []int{75} } func (m *WalletBalanceRequest) XXX_Unmarshal(b []byte) error { @@ -5991,7 +6066,7 @@ func (m *WalletBalanceResponse) Reset() { *m = WalletBalanceResponse{} } func (m *WalletBalanceResponse) String() string { return proto.CompactTextString(m) } func (*WalletBalanceResponse) ProtoMessage() {} func (*WalletBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{75} + return fileDescriptor_77a6da22d6a3feb1, []int{76} } func (m *WalletBalanceResponse) XXX_Unmarshal(b []byte) error { @@ -6043,7 +6118,7 @@ func (m *ChannelBalanceRequest) Reset() { *m = ChannelBalanceRequest{} } func (m *ChannelBalanceRequest) String() string { return proto.CompactTextString(m) } func (*ChannelBalanceRequest) ProtoMessage() {} func (*ChannelBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{76} + return fileDescriptor_77a6da22d6a3feb1, []int{77} } func (m *ChannelBalanceRequest) XXX_Unmarshal(b []byte) error { @@ -6078,7 +6153,7 @@ func (m *ChannelBalanceResponse) Reset() { *m = ChannelBalanceResponse{} func (m *ChannelBalanceResponse) String() string { return proto.CompactTextString(m) } func (*ChannelBalanceResponse) ProtoMessage() {} func (*ChannelBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{77} + return fileDescriptor_77a6da22d6a3feb1, []int{78} } func (m *ChannelBalanceResponse) XXX_Unmarshal(b []byte) error { @@ -6196,7 +6271,7 @@ func (m *QueryRoutesRequest) Reset() { *m = QueryRoutesRequest{} } func (m *QueryRoutesRequest) String() string { return proto.CompactTextString(m) } func (*QueryRoutesRequest) ProtoMessage() {} func (*QueryRoutesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{78} + return fileDescriptor_77a6da22d6a3feb1, []int{79} } func (m *QueryRoutesRequest) XXX_Unmarshal(b []byte) error { @@ -6348,7 +6423,7 @@ func (m *NodePair) Reset() { *m = NodePair{} } func (m *NodePair) String() string { return proto.CompactTextString(m) } func (*NodePair) ProtoMessage() {} func (*NodePair) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{79} + return fileDescriptor_77a6da22d6a3feb1, []int{80} } func (m *NodePair) XXX_Unmarshal(b []byte) error { @@ -6401,7 +6476,7 @@ func (m *EdgeLocator) Reset() { *m = EdgeLocator{} } func (m *EdgeLocator) String() string { return proto.CompactTextString(m) } func (*EdgeLocator) ProtoMessage() {} func (*EdgeLocator) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{80} + return fileDescriptor_77a6da22d6a3feb1, []int{81} } func (m *EdgeLocator) XXX_Unmarshal(b []byte) error { @@ -6454,7 +6529,7 @@ func (m *QueryRoutesResponse) Reset() { *m = QueryRoutesResponse{} } func (m *QueryRoutesResponse) String() string { return proto.CompactTextString(m) } func (*QueryRoutesResponse) ProtoMessage() {} func (*QueryRoutesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{81} + return fileDescriptor_77a6da22d6a3feb1, []int{82} } func (m *QueryRoutesResponse) XXX_Unmarshal(b []byte) error { @@ -6530,7 +6605,7 @@ func (m *Hop) Reset() { *m = Hop{} } func (m *Hop) String() string { return proto.CompactTextString(m) } func (*Hop) ProtoMessage() {} func (*Hop) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{82} + return fileDescriptor_77a6da22d6a3feb1, []int{83} } func (m *Hop) XXX_Unmarshal(b []byte) error { @@ -6652,7 +6727,7 @@ func (m *MPPRecord) Reset() { *m = MPPRecord{} } func (m *MPPRecord) String() string { return proto.CompactTextString(m) } func (*MPPRecord) ProtoMessage() {} func (*MPPRecord) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{83} + return fileDescriptor_77a6da22d6a3feb1, []int{84} } func (m *MPPRecord) XXX_Unmarshal(b []byte) error { @@ -6730,7 +6805,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{84} + return fileDescriptor_77a6da22d6a3feb1, []int{85} } func (m *Route) XXX_Unmarshal(b []byte) error { @@ -6809,7 +6884,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{85} + return fileDescriptor_77a6da22d6a3feb1, []int{86} } func (m *NodeInfoRequest) XXX_Unmarshal(b []byte) error { @@ -6866,7 +6941,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{86} + return fileDescriptor_77a6da22d6a3feb1, []int{87} } func (m *NodeInfo) XXX_Unmarshal(b []byte) error { @@ -6936,7 +7011,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{87} + return fileDescriptor_77a6da22d6a3feb1, []int{88} } func (m *LightningNode) XXX_Unmarshal(b []byte) error { @@ -7011,7 +7086,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{88} + return fileDescriptor_77a6da22d6a3feb1, []int{89} } func (m *NodeAddress) XXX_Unmarshal(b []byte) error { @@ -7063,7 +7138,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{89} + return fileDescriptor_77a6da22d6a3feb1, []int{90} } func (m *RoutingPolicy) XXX_Unmarshal(b []byte) error { @@ -7161,7 +7236,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{90} + return fileDescriptor_77a6da22d6a3feb1, []int{91} } func (m *ChannelEdge) XXX_Unmarshal(b []byte) error { @@ -7254,7 +7329,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{91} + return fileDescriptor_77a6da22d6a3feb1, []int{92} } func (m *ChannelGraphRequest) XXX_Unmarshal(b []byte) error { @@ -7297,7 +7372,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{92} + return fileDescriptor_77a6da22d6a3feb1, []int{93} } func (m *ChannelGraph) XXX_Unmarshal(b []byte) error { @@ -7347,7 +7422,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{93} + return fileDescriptor_77a6da22d6a3feb1, []int{94} } func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error { @@ -7385,7 +7460,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{94} + return fileDescriptor_77a6da22d6a3feb1, []int{95} } func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error { @@ -7428,7 +7503,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{95} + return fileDescriptor_77a6da22d6a3feb1, []int{96} } func (m *NetworkInfo) XXX_Unmarshal(b []byte) error { @@ -7536,7 +7611,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{96} + return fileDescriptor_77a6da22d6a3feb1, []int{97} } func (m *StopRequest) XXX_Unmarshal(b []byte) error { @@ -7567,7 +7642,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{97} + return fileDescriptor_77a6da22d6a3feb1, []int{98} } func (m *StopResponse) XXX_Unmarshal(b []byte) error { @@ -7598,7 +7673,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{98} + return fileDescriptor_77a6da22d6a3feb1, []int{99} } func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error { @@ -7632,7 +7707,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{99} + return fileDescriptor_77a6da22d6a3feb1, []int{100} } func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error { @@ -7689,7 +7764,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{100} + return fileDescriptor_77a6da22d6a3feb1, []int{101} } func (m *NodeUpdate) XXX_Unmarshal(b []byte) error { @@ -7765,7 +7840,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{101} + return fileDescriptor_77a6da22d6a3feb1, []int{102} } func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error { @@ -7846,7 +7921,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{102} + return fileDescriptor_77a6da22d6a3feb1, []int{103} } func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error { @@ -7917,7 +7992,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{103} + return fileDescriptor_77a6da22d6a3feb1, []int{104} } func (m *HopHint) XXX_Unmarshal(b []byte) error { @@ -7987,7 +8062,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{104} + return fileDescriptor_77a6da22d6a3feb1, []int{105} } func (m *RouteHint) XXX_Unmarshal(b []byte) error { @@ -8120,7 +8195,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{105} + return fileDescriptor_77a6da22d6a3feb1, []int{106} } func (m *Invoice) XXX_Unmarshal(b []byte) error { @@ -8342,7 +8417,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{106} + return fileDescriptor_77a6da22d6a3feb1, []int{107} } func (m *InvoiceHTLC) XXX_Unmarshal(b []byte) error { @@ -8455,7 +8530,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{107} + return fileDescriptor_77a6da22d6a3feb1, []int{108} } func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error { @@ -8517,7 +8592,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{108} + return fileDescriptor_77a6da22d6a3feb1, []int{109} } func (m *PaymentHash) XXX_Unmarshal(b []byte) error { @@ -8577,7 +8652,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{109} + return fileDescriptor_77a6da22d6a3feb1, []int{110} } func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error { @@ -8648,7 +8723,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{110} + return fileDescriptor_77a6da22d6a3feb1, []int{111} } func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error { @@ -8712,7 +8787,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{111} + return fileDescriptor_77a6da22d6a3feb1, []int{112} } func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error { @@ -8785,7 +8860,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{112} + return fileDescriptor_77a6da22d6a3feb1, []int{113} } func (m *Payment) XXX_Unmarshal(b []byte) error { @@ -8930,7 +9005,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{113} + return fileDescriptor_77a6da22d6a3feb1, []int{114} } func (m *HTLCAttempt) XXX_Unmarshal(b []byte) error { @@ -9001,7 +9076,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{114} + return fileDescriptor_77a6da22d6a3feb1, []int{115} } func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error { @@ -9041,7 +9116,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{115} + return fileDescriptor_77a6da22d6a3feb1, []int{116} } func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error { @@ -9079,7 +9154,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{116} + return fileDescriptor_77a6da22d6a3feb1, []int{117} } func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error { @@ -9110,7 +9185,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{117} + return fileDescriptor_77a6da22d6a3feb1, []int{118} } func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error { @@ -9142,7 +9217,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{118} + return fileDescriptor_77a6da22d6a3feb1, []int{119} } func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error { @@ -9180,7 +9255,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{119} + return fileDescriptor_77a6da22d6a3feb1, []int{120} } func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error { @@ -9213,7 +9288,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{120} + return fileDescriptor_77a6da22d6a3feb1, []int{121} } func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error { @@ -9259,7 +9334,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{121} + return fileDescriptor_77a6da22d6a3feb1, []int{122} } func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error { @@ -9299,7 +9374,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{122} + return fileDescriptor_77a6da22d6a3feb1, []int{123} } func (m *PayReqString) XXX_Unmarshal(b []byte) error { @@ -9350,7 +9425,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{123} + return fileDescriptor_77a6da22d6a3feb1, []int{124} } func (m *PayReq) XXX_Unmarshal(b []byte) error { @@ -9475,7 +9550,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{124} + return fileDescriptor_77a6da22d6a3feb1, []int{125} } func (m *Feature) XXX_Unmarshal(b []byte) error { @@ -9527,7 +9602,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{125} + return fileDescriptor_77a6da22d6a3feb1, []int{126} } func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error { @@ -9570,7 +9645,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{126} + return fileDescriptor_77a6da22d6a3feb1, []int{127} } func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error { @@ -9648,7 +9723,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{127} + return fileDescriptor_77a6da22d6a3feb1, []int{128} } func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error { @@ -9726,7 +9801,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{128} + return fileDescriptor_77a6da22d6a3feb1, []int{129} } func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error { @@ -9844,7 +9919,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{129} + return fileDescriptor_77a6da22d6a3feb1, []int{130} } func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error { @@ -9889,7 +9964,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{130} + return fileDescriptor_77a6da22d6a3feb1, []int{131} } func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error { @@ -9972,7 +10047,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{131} + return fileDescriptor_77a6da22d6a3feb1, []int{132} } func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error { @@ -10072,7 +10147,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{132} + return fileDescriptor_77a6da22d6a3feb1, []int{133} } func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error { @@ -10119,7 +10194,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{133} + return fileDescriptor_77a6da22d6a3feb1, []int{134} } func (m *ExportChannelBackupRequest) XXX_Unmarshal(b []byte) error { @@ -10166,7 +10241,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{134} + return fileDescriptor_77a6da22d6a3feb1, []int{135} } func (m *ChannelBackup) XXX_Unmarshal(b []byte) error { @@ -10220,7 +10295,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{135} + return fileDescriptor_77a6da22d6a3feb1, []int{136} } func (m *MultiChanBackup) XXX_Unmarshal(b []byte) error { @@ -10265,7 +10340,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{136} + return fileDescriptor_77a6da22d6a3feb1, []int{137} } func (m *ChanBackupExportRequest) XXX_Unmarshal(b []byte) error { @@ -10304,7 +10379,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{137} + return fileDescriptor_77a6da22d6a3feb1, []int{138} } func (m *ChanBackupSnapshot) XXX_Unmarshal(b []byte) error { @@ -10352,7 +10427,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{138} + return fileDescriptor_77a6da22d6a3feb1, []int{139} } func (m *ChannelBackups) XXX_Unmarshal(b []byte) error { @@ -10394,7 +10469,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{139} + return fileDescriptor_77a6da22d6a3feb1, []int{140} } func (m *RestoreChanBackupRequest) XXX_Unmarshal(b []byte) error { @@ -10470,7 +10545,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{140} + return fileDescriptor_77a6da22d6a3feb1, []int{141} } func (m *RestoreBackupResponse) XXX_Unmarshal(b []byte) error { @@ -10501,7 +10576,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{141} + return fileDescriptor_77a6da22d6a3feb1, []int{142} } func (m *ChannelBackupSubscription) XXX_Unmarshal(b []byte) error { @@ -10532,7 +10607,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{142} + return fileDescriptor_77a6da22d6a3feb1, []int{143} } func (m *VerifyChanBackupResponse) XXX_Unmarshal(b []byte) error { @@ -10567,7 +10642,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{143} + return fileDescriptor_77a6da22d6a3feb1, []int{144} } func (m *MacaroonPermission) XXX_Unmarshal(b []byte) error { @@ -10614,7 +10689,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{144} + return fileDescriptor_77a6da22d6a3feb1, []int{145} } func (m *BakeMacaroonRequest) XXX_Unmarshal(b []byte) error { @@ -10654,7 +10729,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{145} + return fileDescriptor_77a6da22d6a3feb1, []int{146} } func (m *BakeMacaroonResponse) XXX_Unmarshal(b []byte) error { @@ -10710,7 +10785,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{146} + return fileDescriptor_77a6da22d6a3feb1, []int{147} } func (m *Failure) XXX_Unmarshal(b []byte) error { @@ -10854,7 +10929,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{147} + return fileDescriptor_77a6da22d6a3feb1, []int{148} } func (m *ChannelUpdate) XXX_Unmarshal(b []byte) error { @@ -11024,6 +11099,7 @@ func init() { proto.RegisterType((*ClosedChannelsResponse)(nil), "lnrpc.ClosedChannelsResponse") proto.RegisterType((*Peer)(nil), "lnrpc.Peer") proto.RegisterMapType((map[uint32]*Feature)(nil), "lnrpc.Peer.FeaturesEntry") + proto.RegisterType((*TimestampedError)(nil), "lnrpc.TimestampedError") proto.RegisterType((*ListPeersRequest)(nil), "lnrpc.ListPeersRequest") proto.RegisterType((*ListPeersResponse)(nil), "lnrpc.ListPeersResponse") proto.RegisterType((*PeerEventSubscription)(nil), "lnrpc.PeerEventSubscription") @@ -11142,705 +11218,709 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11167 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x1c, 0x49, - 0x76, 0x18, 0xcc, 0xba, 0x75, 0x55, 0x9d, 0xba, 0x76, 0xf4, 0xad, 0xd8, 0x24, 0x87, 0x9c, 0x9c, - 0xd9, 0x21, 0x97, 0xb3, 0x4b, 0x72, 0xb8, 0x3b, 0xb3, 0xab, 0x99, 0xef, 0x5b, 0x6d, 0x75, 0x77, - 0x35, 0xbb, 0x96, 0x7d, 0x9b, 0xac, 0xea, 0x19, 0xcd, 0xca, 0x72, 0x6e, 0x76, 0x55, 0x74, 0x77, - 0x8a, 0x55, 0x99, 0x35, 0x99, 0x59, 0x7d, 0xd9, 0xc1, 0xf8, 0xc1, 0x17, 0xc1, 0xb0, 0x0d, 0x03, - 0x82, 0x2d, 0x03, 0x96, 0x2d, 0xd8, 0xb0, 0x61, 0x18, 0x86, 0x01, 0x41, 0xc6, 0xca, 0x80, 0x1f, - 0xfc, 0xae, 0x17, 0x1b, 0x7a, 0x90, 0xfc, 0x62, 0x08, 0x02, 0x04, 0xcb, 0xf2, 0xab, 0x7e, 0x82, - 0x11, 0xe7, 0x44, 0x64, 0x46, 0x56, 0x65, 0x93, 0x9c, 0xd9, 0xf5, 0xbe, 0x90, 0x9d, 0x27, 0x4e, - 0xdc, 0x4f, 0x9c, 0x38, 0xd7, 0x28, 0x28, 0xfb, 0x93, 0xc1, 0xa3, 0x89, 0xef, 0x85, 0x1e, 0x2b, - 0x8c, 0x5c, 0x7f, 0x32, 0x58, 0xbf, 0x7d, 0xea, 0x79, 0xa7, 0x23, 0xfe, 0xd8, 0x9e, 0x38, 0x8f, - 0x6d, 0xd7, 0xf5, 0x42, 0x3b, 0x74, 0x3c, 0x37, 0x20, 0x24, 0xe3, 0x27, 0x50, 0x7f, 0xc6, 0xdd, - 0x1e, 0xe7, 0x43, 0x93, 0x7f, 0x3e, 0xe5, 0x41, 0xc8, 0xde, 0x85, 0x45, 0x9b, 0xff, 0x94, 0xf3, - 0xa1, 0x35, 0xb1, 0x83, 0x60, 0x72, 0xe6, 0xdb, 0x01, 0x6f, 0x65, 0xee, 0x65, 0x1e, 0x54, 0xcd, - 0x26, 0x15, 0x1c, 0x46, 0x70, 0xf6, 0x26, 0x54, 0x03, 0x81, 0xca, 0xdd, 0xd0, 0xf7, 0x26, 0x57, - 0xad, 0x2c, 0xe2, 0x55, 0x04, 0xac, 0x43, 0x20, 0x63, 0x04, 0x8d, 0xa8, 0x87, 0x60, 0xe2, 0xb9, - 0x01, 0x67, 0x4f, 0x60, 0x79, 0xe0, 0x4c, 0xce, 0xb8, 0x6f, 0x61, 0xe5, 0xb1, 0xcb, 0xc7, 0x9e, - 0xeb, 0x0c, 0x5a, 0x99, 0x7b, 0xb9, 0x07, 0x65, 0x93, 0x51, 0x99, 0xa8, 0xb1, 0x27, 0x4b, 0xd8, - 0x7d, 0x68, 0x70, 0x97, 0xe0, 0x7c, 0x88, 0xb5, 0x64, 0x57, 0xf5, 0x18, 0x2c, 0x2a, 0x18, 0x7f, - 0x3f, 0x0b, 0x8b, 0x5d, 0xd7, 0x09, 0x3f, 0xb5, 0x47, 0x23, 0x1e, 0xaa, 0x39, 0xdd, 0x87, 0xc6, - 0x05, 0x02, 0x70, 0x4e, 0x17, 0x9e, 0x3f, 0x94, 0x33, 0xaa, 0x13, 0xf8, 0x50, 0x42, 0xaf, 0x1d, - 0x59, 0xf6, 0xda, 0x91, 0xa5, 0x2e, 0x57, 0xee, 0x9a, 0xe5, 0xba, 0x0f, 0x0d, 0x9f, 0x0f, 0xbc, - 0x73, 0xee, 0x5f, 0x59, 0x17, 0x8e, 0x3b, 0xf4, 0x2e, 0x5a, 0xf9, 0x7b, 0x99, 0x07, 0x05, 0xb3, - 0xae, 0xc0, 0x9f, 0x22, 0x94, 0x6d, 0x40, 0x63, 0x70, 0x66, 0xbb, 0x2e, 0x1f, 0x59, 0xc7, 0xf6, - 0xe0, 0xc5, 0x74, 0x12, 0xb4, 0x0a, 0xf7, 0x32, 0x0f, 0x2a, 0x4f, 0x6f, 0x3e, 0xc2, 0x5d, 0x7d, - 0xb4, 0x79, 0x66, 0xbb, 0x1b, 0x58, 0xd2, 0x73, 0xed, 0x49, 0x70, 0xe6, 0x85, 0x66, 0x5d, 0xd6, - 0x20, 0x70, 0x60, 0x2c, 0x03, 0xd3, 0x57, 0x82, 0xd6, 0xde, 0xf8, 0x8f, 0x19, 0x58, 0x3a, 0x72, - 0x47, 0xde, 0xe0, 0xc5, 0xd7, 0x5c, 0xa2, 0x94, 0x39, 0x64, 0x5f, 0x77, 0x0e, 0xb9, 0xaf, 0x3a, - 0x87, 0x55, 0x58, 0x4e, 0x0e, 0x56, 0xce, 0x82, 0xc3, 0x8a, 0xa8, 0x7d, 0xca, 0xd5, 0xb0, 0xd4, - 0x34, 0xbe, 0x09, 0xcd, 0xc1, 0xd4, 0xf7, 0xb9, 0x3b, 0x37, 0x8f, 0x86, 0x84, 0x47, 0x13, 0x79, - 0x13, 0xaa, 0x2e, 0xbf, 0x88, 0xd1, 0x24, 0xed, 0xba, 0xfc, 0x42, 0xa1, 0x18, 0x2d, 0x58, 0x9d, - 0xed, 0x46, 0x0e, 0xe0, 0xaf, 0x32, 0x90, 0x3f, 0x0a, 0x2f, 0x3d, 0xf6, 0x3e, 0x54, 0xed, 0xe1, - 0xd0, 0xe7, 0x41, 0x60, 0x85, 0x57, 0x13, 0x3a, 0x29, 0xf5, 0xa7, 0x4c, 0x4e, 0xb1, 0x4d, 0x45, - 0xfd, 0xab, 0x09, 0x37, 0x2b, 0x76, 0xfc, 0xc1, 0x5a, 0x50, 0x94, 0x9f, 0xd8, 0x6f, 0xd9, 0x54, - 0x9f, 0xec, 0x0e, 0x80, 0x3d, 0xf6, 0xa6, 0x6e, 0x68, 0x05, 0x76, 0x88, 0x2b, 0x96, 0x33, 0xcb, - 0x04, 0xe9, 0xd9, 0x21, 0xbb, 0x05, 0xe5, 0xc9, 0x0b, 0x2b, 0x18, 0xf8, 0xce, 0x24, 0x44, 0xe2, - 0x29, 0x9b, 0xa5, 0xc9, 0x8b, 0x1e, 0x7e, 0xb3, 0x77, 0xa1, 0xe4, 0x4d, 0xc3, 0x89, 0xe7, 0xb8, - 0xa1, 0xa4, 0x97, 0x86, 0x1c, 0xc8, 0xc1, 0x34, 0x3c, 0x14, 0x60, 0x33, 0x42, 0x60, 0x6f, 0x43, - 0x6d, 0xe0, 0xb9, 0x27, 0x8e, 0x3f, 0x26, 0x8e, 0xd0, 0x5a, 0xc0, 0xbe, 0x92, 0x40, 0xe3, 0x0f, - 0xb2, 0x50, 0xe9, 0xfb, 0xb6, 0x1b, 0xd8, 0x03, 0x01, 0x60, 0x6b, 0x50, 0x0c, 0x2f, 0xad, 0x33, - 0x3b, 0x38, 0xc3, 0xa9, 0x96, 0xcd, 0x85, 0xf0, 0x72, 0xc7, 0x0e, 0xce, 0xd8, 0x2a, 0x2c, 0xd0, - 0x28, 0x71, 0x42, 0x39, 0x53, 0x7e, 0x89, 0x03, 0xe2, 0x4e, 0xc7, 0x56, 0xb2, 0xab, 0x1c, 0x52, - 0x4c, 0xd3, 0x9d, 0x8e, 0x37, 0x75, 0xb8, 0x98, 0xfc, 0xb1, 0xd8, 0x6e, 0xea, 0x80, 0xa6, 0x57, - 0x46, 0x08, 0xf6, 0xf1, 0x26, 0x54, 0x65, 0x31, 0x77, 0x4e, 0xcf, 0x68, 0x8e, 0x05, 0xb3, 0x42, - 0x08, 0x08, 0x12, 0x2d, 0x84, 0xce, 0x98, 0x5b, 0x41, 0x68, 0x8f, 0x27, 0x72, 0x4a, 0x65, 0x01, - 0xe9, 0x09, 0x00, 0x16, 0x7b, 0xa1, 0x3d, 0xb2, 0x4e, 0x38, 0x0f, 0x5a, 0x45, 0x59, 0x2c, 0x20, - 0xdb, 0x9c, 0x07, 0xec, 0x1b, 0x50, 0x1f, 0xf2, 0x20, 0xb4, 0xe4, 0x66, 0xf0, 0xa0, 0x55, 0xc2, - 0x93, 0x5f, 0x13, 0xd0, 0xb6, 0x02, 0xb2, 0xdb, 0x00, 0xbe, 0x7d, 0x61, 0x89, 0x85, 0xe0, 0x97, - 0xad, 0x32, 0xed, 0x82, 0x6f, 0x5f, 0xf4, 0x2f, 0x77, 0xf8, 0xa5, 0xa0, 0x9a, 0x67, 0x3c, 0xd4, - 0x16, 0x2d, 0x90, 0xd4, 0x69, 0xec, 0x02, 0xd3, 0xc0, 0x5b, 0x3c, 0xb4, 0x9d, 0x51, 0xc0, 0x3e, - 0x80, 0x6a, 0xa8, 0x21, 0x23, 0x1b, 0xac, 0x44, 0x24, 0xa4, 0x55, 0x30, 0x13, 0x78, 0xc6, 0x19, - 0x94, 0xb6, 0x39, 0xdf, 0x75, 0xc6, 0x4e, 0xc8, 0x56, 0xa1, 0x70, 0xe2, 0x5c, 0x72, 0x22, 0xf6, - 0xdc, 0xce, 0x0d, 0x93, 0x3e, 0xd9, 0x5d, 0x00, 0xfc, 0xc3, 0x1a, 0x47, 0xd4, 0xb4, 0x73, 0xc3, - 0x2c, 0x23, 0x6c, 0x2f, 0xb0, 0x43, 0xb6, 0x0e, 0xc5, 0x09, 0xf7, 0x07, 0x5c, 0xed, 0xdb, 0xce, - 0x0d, 0x53, 0x01, 0x36, 0x8a, 0x50, 0x18, 0x89, 0xd6, 0x8d, 0x3f, 0x2a, 0x40, 0xa5, 0xc7, 0xdd, - 0xe8, 0x94, 0x31, 0xc8, 0x8b, 0x05, 0x91, 0x27, 0x0b, 0xff, 0x66, 0x6f, 0x41, 0x05, 0x97, 0x2e, - 0x08, 0x7d, 0xc7, 0x3d, 0x25, 0xaa, 0xde, 0xc8, 0xb6, 0x32, 0x26, 0x08, 0x70, 0x0f, 0xa1, 0xac, - 0x09, 0x39, 0x7b, 0xac, 0xa8, 0x5a, 0xfc, 0xc9, 0x6e, 0x42, 0xc9, 0x1e, 0x87, 0x34, 0xbc, 0x2a, - 0x82, 0x8b, 0xf6, 0x38, 0xc4, 0xa1, 0xbd, 0x09, 0xd5, 0x89, 0x7d, 0x35, 0x16, 0x67, 0x39, 0x22, - 0x87, 0xaa, 0x59, 0x91, 0x30, 0x24, 0x88, 0xa7, 0xb0, 0xa4, 0xa3, 0xa8, 0xce, 0x0b, 0x51, 0xe7, - 0x8b, 0x1a, 0xb6, 0x1c, 0xc3, 0x7d, 0x68, 0xa8, 0x3a, 0x3e, 0xcd, 0x07, 0xc9, 0xa4, 0x6c, 0xd6, - 0x25, 0x58, 0xcd, 0xf2, 0x01, 0x34, 0x4f, 0x1c, 0xd7, 0x1e, 0x59, 0x83, 0x51, 0x78, 0x6e, 0x0d, - 0xf9, 0x28, 0xb4, 0x91, 0x62, 0x0a, 0x66, 0x1d, 0xe1, 0x9b, 0xa3, 0xf0, 0x7c, 0x4b, 0x40, 0xd9, - 0xb7, 0xa0, 0x7c, 0xc2, 0xb9, 0x85, 0x8b, 0xd5, 0x2a, 0x25, 0x0e, 0x9e, 0xda, 0x21, 0xb3, 0x74, - 0xa2, 0xf6, 0xea, 0x5b, 0xd0, 0xf4, 0xa6, 0xe1, 0xa9, 0xe7, 0xb8, 0xa7, 0x96, 0xe0, 0x77, 0x96, - 0x33, 0x44, 0x1a, 0xca, 0x6f, 0x64, 0x9f, 0x64, 0xcc, 0xba, 0x2a, 0x13, 0x9c, 0xa7, 0x3b, 0x64, - 0xef, 0x40, 0x63, 0x64, 0x07, 0xa1, 0x75, 0xe6, 0x4d, 0xac, 0xc9, 0xf4, 0xf8, 0x05, 0xbf, 0x6a, - 0xd5, 0x70, 0x21, 0x6a, 0x02, 0xbc, 0xe3, 0x4d, 0x0e, 0x11, 0x28, 0x28, 0x1b, 0xc7, 0x49, 0x83, - 0x80, 0x7b, 0x99, 0x07, 0x35, 0xb3, 0x2c, 0x20, 0xd4, 0xe9, 0x67, 0xb0, 0x84, 0xdb, 0x33, 0x98, - 0x06, 0xa1, 0x37, 0xb6, 0x04, 0xaf, 0xf6, 0x87, 0x41, 0xab, 0x82, 0xb4, 0xf6, 0x4d, 0x39, 0x58, - 0x6d, 0x8f, 0x1f, 0x6d, 0xf1, 0x20, 0xdc, 0x44, 0x64, 0x93, 0x70, 0xc5, 0x85, 0x7e, 0x65, 0x2e, - 0x0e, 0x67, 0xe1, 0xec, 0x5b, 0xc0, 0xec, 0xd1, 0xc8, 0xbb, 0xb0, 0x02, 0x3e, 0x3a, 0xb1, 0xe4, - 0x22, 0xb6, 0xea, 0xf7, 0x32, 0x0f, 0x4a, 0x66, 0x13, 0x4b, 0x7a, 0x7c, 0x74, 0x72, 0x48, 0x70, - 0xf6, 0x01, 0xe0, 0x61, 0xb2, 0x4e, 0xb8, 0x1d, 0x4e, 0x7d, 0x1e, 0xb4, 0x1a, 0xf7, 0x72, 0x0f, - 0xea, 0x4f, 0x17, 0xa3, 0xf5, 0x42, 0xf0, 0x86, 0x13, 0x9a, 0x55, 0x81, 0x27, 0xbf, 0x83, 0xf5, - 0x2d, 0x58, 0x4d, 0x1f, 0x92, 0x20, 0x2a, 0xb1, 0x2a, 0x82, 0x18, 0xf3, 0xa6, 0xf8, 0x93, 0x2d, - 0x43, 0xe1, 0xdc, 0x1e, 0x4d, 0xb9, 0xe4, 0xe9, 0xf4, 0xf1, 0x61, 0xf6, 0xfb, 0x19, 0xe3, 0x0f, - 0x33, 0x50, 0xa5, 0x59, 0x4a, 0x59, 0xe4, 0x2d, 0xa8, 0x29, 0x6a, 0xe0, 0xbe, 0xef, 0xf9, 0x92, - 0xab, 0x29, 0xca, 0xeb, 0x08, 0x98, 0xb8, 0x55, 0x14, 0xd2, 0xc4, 0xe7, 0xce, 0xd8, 0x3e, 0x55, - 0x4d, 0x2b, 0x52, 0x3a, 0x94, 0x60, 0xf6, 0x5e, 0xdc, 0x9e, 0xef, 0x4d, 0x43, 0x2e, 0xef, 0xbc, - 0xaa, 0x9c, 0x9e, 0x29, 0x60, 0x51, 0xeb, 0xf8, 0xf5, 0x1a, 0x74, 0x6e, 0xfc, 0x4e, 0x06, 0x98, - 0x18, 0x76, 0xdf, 0xa3, 0x06, 0x24, 0x85, 0xce, 0xd6, 0xcc, 0xbc, 0xf6, 0x09, 0xc9, 0xbe, 0xec, - 0x84, 0x18, 0x50, 0xa0, 0xb1, 0xe7, 0x53, 0xc6, 0x4e, 0x45, 0x3f, 0xca, 0x97, 0x72, 0xcd, 0xbc, - 0xf1, 0x3f, 0x73, 0xb0, 0xbc, 0x49, 0x57, 0x76, 0x7b, 0x30, 0xe0, 0x93, 0xe8, 0xec, 0xdc, 0x85, - 0x8a, 0xeb, 0x0d, 0xb9, 0xa2, 0x58, 0x1a, 0x18, 0x08, 0x90, 0x46, 0xae, 0x67, 0xb6, 0xe3, 0xd2, - 0xc0, 0x69, 0x31, 0xcb, 0x08, 0xc1, 0x61, 0xbf, 0x03, 0x8d, 0x09, 0x77, 0x87, 0xfa, 0x11, 0x21, - 0xa1, 0xaa, 0x26, 0xc1, 0xf2, 0x74, 0xdc, 0x85, 0xca, 0xc9, 0x94, 0xf0, 0x04, 0x63, 0xc9, 0x23, - 0x0d, 0x80, 0x04, 0xb5, 0x89, 0xbf, 0x4c, 0xa6, 0xc1, 0x19, 0x96, 0x16, 0xb0, 0xb4, 0x28, 0xbe, - 0x45, 0xd1, 0x1d, 0x80, 0xe1, 0x34, 0x08, 0xe5, 0x89, 0x59, 0xc0, 0xc2, 0xb2, 0x80, 0xd0, 0x89, - 0xf9, 0x36, 0x2c, 0x8d, 0xed, 0x4b, 0x0b, 0x69, 0xc7, 0x72, 0x5c, 0xeb, 0x64, 0x84, 0x77, 0x4e, - 0x11, 0xf1, 0x9a, 0x63, 0xfb, 0xf2, 0x13, 0x51, 0xd2, 0x75, 0xb7, 0x11, 0x2e, 0xd8, 0x8a, 0x12, - 0x77, 0x7c, 0x1e, 0x70, 0xff, 0x9c, 0x23, 0x27, 0xc8, 0x47, 0x32, 0x8d, 0x49, 0x50, 0x31, 0xa2, - 0xb1, 0x98, 0x77, 0x38, 0x1a, 0xd0, 0xb1, 0x37, 0x8b, 0x63, 0xc7, 0xdd, 0x09, 0x47, 0x03, 0x71, - 0xaf, 0x08, 0x3e, 0x32, 0xe1, 0xbe, 0xf5, 0xe2, 0x02, 0xcf, 0x70, 0x1e, 0xf9, 0xc6, 0x21, 0xf7, - 0x9f, 0x5f, 0x88, 0xab, 0x7f, 0x10, 0x20, 0x23, 0xb2, 0xaf, 0x5a, 0x15, 0x3c, 0xe0, 0xa5, 0x41, - 0x20, 0x58, 0x90, 0x7d, 0x25, 0x0e, 0xa1, 0x18, 0xad, 0x8d, 0xbb, 0xc0, 0x87, 0xd8, 0x7c, 0x80, - 0x1c, 0xb5, 0x86, 0x83, 0x6d, 0xcb, 0x02, 0xd1, 0x4f, 0x20, 0xa8, 0x5e, 0x0d, 0xf6, 0x64, 0x64, - 0x9f, 0x06, 0xc8, 0x52, 0x6a, 0x66, 0x55, 0x02, 0xb7, 0x05, 0xcc, 0xf8, 0x94, 0x84, 0x2c, 0x6d, - 0x6f, 0xe5, 0x99, 0x11, 0x57, 0x3d, 0x42, 0x70, 0x5f, 0x4b, 0xa6, 0xfc, 0x4a, 0xdb, 0xb4, 0x6c, - 0xca, 0xa6, 0x19, 0xbf, 0x97, 0x81, 0xaa, 0x6c, 0x19, 0x85, 0x12, 0xf6, 0x08, 0x98, 0xda, 0xc5, - 0xf0, 0xd2, 0x19, 0x5a, 0xc7, 0x57, 0x21, 0x0f, 0x88, 0x68, 0x76, 0x6e, 0x98, 0x4d, 0x59, 0xd6, - 0xbf, 0x74, 0x86, 0x1b, 0xa2, 0x84, 0x3d, 0x84, 0x66, 0x02, 0x3f, 0x08, 0x7d, 0xa2, 0xe8, 0x9d, - 0x1b, 0x66, 0x5d, 0xc3, 0xee, 0x85, 0xbe, 0x38, 0x23, 0x42, 0xe4, 0x99, 0x86, 0x96, 0xe3, 0x0e, - 0xf9, 0x25, 0x92, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x2b, 0x40, 0x1b, 0x75, 0xa8, 0xea, 0xcd, 0x19, - 0xa7, 0x50, 0x52, 0xf2, 0x12, 0x0a, 0x0c, 0x33, 0x43, 0x32, 0xcb, 0x61, 0x34, 0x92, 0x9b, 0x50, - 0x4a, 0x8e, 0xc0, 0x2c, 0x86, 0xaf, 0xdd, 0xb1, 0xf1, 0x03, 0x68, 0xee, 0x0a, 0xe2, 0x71, 0x05, - 0xb1, 0x4a, 0xf9, 0x6f, 0x15, 0x16, 0xb4, 0x43, 0x53, 0x36, 0xe5, 0x97, 0xb8, 0x73, 0xcf, 0xbc, - 0x20, 0x94, 0xbd, 0xe0, 0xdf, 0xc6, 0x1f, 0x65, 0x80, 0x75, 0x82, 0xd0, 0x19, 0xdb, 0x21, 0xdf, - 0xe6, 0x11, 0x5b, 0x38, 0x80, 0xaa, 0x68, 0xad, 0xef, 0xb5, 0x49, 0x20, 0x23, 0x81, 0xe2, 0x5d, - 0x79, 0x8c, 0xe7, 0x2b, 0x3c, 0xd2, 0xb1, 0x89, 0xcd, 0x27, 0x1a, 0x10, 0xa7, 0x2c, 0xb4, 0xfd, - 0x53, 0x1e, 0xa2, 0x18, 0x27, 0xe5, 0x7d, 0x20, 0x90, 0x10, 0xe0, 0xd6, 0x7f, 0x15, 0x16, 0xe7, - 0xda, 0xd0, 0xf9, 0x72, 0x39, 0x85, 0x2f, 0xe7, 0x74, 0xbe, 0x6c, 0xc1, 0x52, 0x62, 0x5c, 0x92, - 0xd2, 0xd6, 0xa0, 0x28, 0x0e, 0x84, 0x10, 0x0e, 0x32, 0x24, 0x55, 0x9e, 0x70, 0x2e, 0xc4, 0xe0, - 0xc7, 0xb0, 0x7c, 0xc2, 0xb9, 0x6f, 0x87, 0x58, 0x88, 0x27, 0x46, 0xec, 0x90, 0x6c, 0x78, 0x51, - 0x96, 0xf5, 0xec, 0xf0, 0x90, 0xfb, 0x62, 0xa7, 0x8c, 0xff, 0x95, 0x81, 0x86, 0xe0, 0xa0, 0x7b, - 0xb6, 0x7b, 0xa5, 0xd6, 0x69, 0x37, 0x75, 0x9d, 0x1e, 0x68, 0x97, 0xa1, 0x86, 0xfd, 0x55, 0x17, - 0x29, 0x37, 0xbb, 0x48, 0xec, 0x1e, 0x54, 0x13, 0x63, 0x2d, 0xe0, 0x58, 0x21, 0x88, 0x06, 0xf9, - 0xf3, 0x2f, 0xe3, 0x3b, 0xd0, 0x8c, 0x87, 0x2d, 0xd7, 0x90, 0x41, 0x5e, 0x90, 0xa4, 0x6c, 0x00, - 0xff, 0x36, 0xfe, 0x65, 0x86, 0x10, 0x37, 0x3d, 0x27, 0x92, 0x4e, 0x05, 0xa2, 0x90, 0x7b, 0x15, - 0xa2, 0xf8, 0xfb, 0x5a, 0xa9, 0xfe, 0xe7, 0x9f, 0xac, 0x38, 0x3a, 0x01, 0x77, 0x87, 0x96, 0x3d, - 0x1a, 0x21, 0xf3, 0x2d, 0x99, 0x45, 0xf1, 0xdd, 0x1e, 0x8d, 0x8c, 0xfb, 0xb0, 0xa8, 0x8d, 0xee, - 0x25, 0xf3, 0xd8, 0x07, 0xb6, 0xeb, 0x04, 0xe1, 0x91, 0x1b, 0x4c, 0x34, 0xc1, 0xed, 0x16, 0x94, - 0x05, 0x87, 0x15, 0x23, 0xa3, 0x23, 0x5b, 0x30, 0x05, 0xcb, 0x15, 0xe3, 0x0a, 0xb0, 0xd0, 0xbe, - 0x94, 0x85, 0x59, 0x59, 0x68, 0x5f, 0x62, 0xa1, 0xf1, 0x7d, 0x58, 0x4a, 0xb4, 0x27, 0xbb, 0x7e, - 0x13, 0x0a, 0xd3, 0xf0, 0xd2, 0x53, 0xa2, 0x79, 0x45, 0x52, 0x88, 0x50, 0x00, 0x4d, 0x2a, 0x31, - 0x3e, 0x82, 0xc5, 0x7d, 0x7e, 0x21, 0x0f, 0xb1, 0x1a, 0xc8, 0x3b, 0x90, 0x7f, 0x85, 0x52, 0x88, - 0xe5, 0xc6, 0x23, 0x60, 0x7a, 0x65, 0xd9, 0xab, 0xa6, 0x23, 0x66, 0x12, 0x3a, 0xa2, 0xf1, 0x0e, - 0xb0, 0x9e, 0x73, 0xea, 0xee, 0xf1, 0x20, 0xb0, 0x4f, 0xa3, 0x63, 0xdf, 0x84, 0xdc, 0x38, 0x38, - 0x95, 0x3c, 0x4a, 0xfc, 0x69, 0x7c, 0x07, 0x96, 0x12, 0x78, 0xb2, 0xe1, 0xdb, 0x50, 0x0e, 0x9c, - 0x53, 0x17, 0x05, 0x2b, 0xd9, 0x74, 0x0c, 0x30, 0xb6, 0x61, 0xf9, 0x13, 0xee, 0x3b, 0x27, 0x57, - 0xaf, 0x6a, 0x3e, 0xd9, 0x4e, 0x76, 0xb6, 0x9d, 0x0e, 0xac, 0xcc, 0xb4, 0x23, 0xbb, 0x27, 0xf2, - 0x95, 0x3b, 0x59, 0x32, 0xe9, 0x43, 0xe3, 0x7b, 0x59, 0x9d, 0xef, 0x19, 0x47, 0xc0, 0x36, 0x3d, - 0xd7, 0xe5, 0x83, 0xf0, 0x90, 0x73, 0x3f, 0xb6, 0x52, 0xc5, 0xb4, 0x5a, 0x79, 0xba, 0x26, 0x57, - 0x76, 0x96, 0x99, 0x4a, 0x22, 0x66, 0x90, 0x9f, 0x70, 0x7f, 0x8c, 0x0d, 0x97, 0x4c, 0xfc, 0xdb, - 0x58, 0x81, 0xa5, 0x44, 0xb3, 0x52, 0xaf, 0x7f, 0x02, 0x2b, 0x5b, 0x4e, 0x30, 0x98, 0xef, 0x70, - 0x0d, 0x8a, 0x93, 0xe9, 0xb1, 0x95, 0xe4, 0xcb, 0xcf, 0xf9, 0x95, 0xd0, 0xf6, 0x66, 0x6b, 0xc8, - 0xb6, 0xfe, 0x6e, 0x06, 0xf2, 0x3b, 0xfd, 0xdd, 0x4d, 0xb6, 0x0e, 0x25, 0xc7, 0x1d, 0x78, 0x63, - 0x21, 0x78, 0xd1, 0x9c, 0xa3, 0xef, 0x6b, 0x0f, 0xd8, 0x2d, 0x28, 0xa3, 0xbc, 0x26, 0x54, 0x5b, - 0x29, 0xfa, 0x94, 0x04, 0x60, 0xd7, 0x1b, 0xbc, 0x10, 0x3a, 0x35, 0xbf, 0x9c, 0x38, 0x3e, 0x6a, - 0xcd, 0x4a, 0x19, 0xce, 0xd3, 0x5d, 0x1f, 0x17, 0x90, 0x46, 0x6c, 0xfc, 0x75, 0x11, 0x8a, 0xf2, - 0xb6, 0xa5, 0x9b, 0x3b, 0x74, 0xce, 0x79, 0x7c, 0x73, 0x8b, 0x2f, 0x21, 0x0f, 0xf8, 0x7c, 0xec, - 0x85, 0x91, 0xc0, 0x46, 0x7b, 0x50, 0x25, 0xa0, 0x14, 0xd9, 0x34, 0xa1, 0x81, 0x4c, 0x0c, 0x39, - 0x42, 0x1a, 0xe8, 0x57, 0xf9, 0x2d, 0x28, 0xaa, 0xbb, 0x3f, 0x1f, 0xe9, 0x34, 0x0b, 0x03, 0x92, - 0xd6, 0xd6, 0xa1, 0x34, 0xb0, 0x27, 0xf6, 0xc0, 0x09, 0xaf, 0x24, 0x43, 0x88, 0xbe, 0x45, 0xeb, - 0x23, 0x6f, 0x60, 0x8f, 0xac, 0x63, 0x7b, 0x64, 0xbb, 0x03, 0x2e, 0x75, 0xf7, 0x2a, 0x02, 0x37, - 0x08, 0x26, 0xf4, 0x73, 0x39, 0x4e, 0x85, 0x45, 0x2a, 0xbc, 0x1c, 0xbd, 0x42, 0x13, 0xc2, 0xa5, - 0x37, 0x1e, 0x3b, 0x42, 0xcb, 0x20, 0x31, 0x2c, 0x67, 0x96, 0x09, 0xb2, 0xcd, 0x71, 0xb6, 0xb2, - 0xf8, 0x82, 0x96, 0xae, 0x4c, 0x5d, 0x11, 0xf0, 0x53, 0x32, 0x24, 0xcc, 0xcb, 0x62, 0x39, 0x4d, - 0x16, 0x7b, 0x17, 0x16, 0xa7, 0x6e, 0xc0, 0xc3, 0x70, 0xc4, 0x87, 0xd1, 0x58, 0x2a, 0x88, 0xd4, - 0x8c, 0x0a, 0xd4, 0x70, 0x1e, 0xc1, 0x12, 0x19, 0x1d, 0x02, 0x3b, 0xf4, 0x82, 0x33, 0x27, 0xb0, - 0x02, 0xa1, 0x21, 0x91, 0xba, 0xbb, 0x88, 0x45, 0x3d, 0x59, 0xd2, 0x23, 0x15, 0x69, 0x6d, 0x06, - 0xdf, 0xe7, 0x03, 0xee, 0x9c, 0xf3, 0x21, 0xca, 0x69, 0x39, 0x73, 0x25, 0x51, 0xc7, 0x94, 0x85, - 0x28, 0x74, 0x4f, 0xc7, 0xd6, 0x74, 0x32, 0xb4, 0x85, 0xb0, 0x52, 0x27, 0x61, 0xd8, 0x9d, 0x8e, - 0x8f, 0x08, 0xc2, 0x9e, 0x80, 0x92, 0xc4, 0xa4, 0x7c, 0xd8, 0x48, 0xf0, 0x33, 0x41, 0xac, 0x66, - 0x55, 0x62, 0x90, 0xa0, 0x98, 0x90, 0x39, 0x9b, 0x33, 0x32, 0x67, 0x0b, 0x8a, 0x13, 0xdf, 0x39, - 0xb7, 0x43, 0xde, 0x5a, 0x24, 0x06, 0x2e, 0x3f, 0x05, 0x67, 0x70, 0x5c, 0x27, 0x74, 0xec, 0xd0, - 0xf3, 0x5b, 0x0c, 0xcb, 0x62, 0x00, 0x7b, 0x08, 0x8b, 0x48, 0x23, 0x41, 0x68, 0x87, 0xd3, 0x40, - 0x4a, 0xa0, 0x4b, 0x48, 0x4c, 0x28, 0x43, 0xf7, 0x10, 0x8e, 0x42, 0x28, 0xfb, 0x0e, 0xac, 0x12, - 0x59, 0x60, 0x0d, 0x29, 0x59, 0xa3, 0x40, 0xb0, 0x8c, 0x4b, 0xb1, 0x84, 0xa5, 0x82, 0xbe, 0xa5, - 0x7c, 0x2d, 0xa4, 0x83, 0xf7, 0x61, 0x4d, 0x92, 0xc9, 0x5c, 0xad, 0x15, 0xac, 0xb5, 0x4c, 0xc5, - 0x33, 0xd5, 0x1e, 0xc1, 0xa2, 0x18, 0x92, 0x33, 0xb0, 0x64, 0x6d, 0x71, 0x12, 0x56, 0xc5, 0xe8, - 0x51, 0x53, 0x6a, 0x50, 0xa1, 0x89, 0x65, 0xcf, 0xf9, 0x15, 0xfb, 0x01, 0x34, 0x88, 0x64, 0x50, - 0xbd, 0x42, 0x4e, 0xbf, 0x8e, 0x9c, 0x7e, 0x45, 0x59, 0x38, 0xa3, 0x52, 0x64, 0xf6, 0xf5, 0x41, - 0xe2, 0x5b, 0x1c, 0x87, 0x91, 0x73, 0xc2, 0x43, 0x67, 0xcc, 0x5b, 0x6b, 0x44, 0x60, 0xea, 0x5b, - 0x9c, 0xd4, 0xe9, 0x04, 0x4b, 0x5a, 0xc4, 0x17, 0xe8, 0x0b, 0x69, 0x77, 0xe4, 0x05, 0x5c, 0x99, - 0xa8, 0x5a, 0x37, 0xe5, 0x21, 0x14, 0x40, 0xc9, 0xf6, 0x8c, 0x9f, 0x65, 0xe8, 0x1e, 0x93, 0xc7, - 0x3e, 0xd0, 0xb4, 0x32, 0x3a, 0xf0, 0x96, 0xe7, 0x8e, 0xae, 0x24, 0x0f, 0x00, 0x02, 0x1d, 0xb8, - 0x23, 0x3c, 0x84, 0x8e, 0xab, 0xa3, 0x10, 0xcb, 0xac, 0x2a, 0x20, 0x22, 0xdd, 0x85, 0xca, 0x64, - 0x7a, 0x3c, 0x72, 0x06, 0x84, 0x92, 0xa3, 0x56, 0x08, 0x84, 0x08, 0x42, 0x2d, 0x25, 0x42, 0x20, - 0x8c, 0x3c, 0x62, 0x54, 0x24, 0x0c, 0x51, 0x90, 0x25, 0x73, 0x1f, 0xb9, 0x40, 0xd5, 0xc4, 0xbf, - 0x8d, 0x0d, 0x58, 0x4e, 0x0e, 0x5a, 0xde, 0x17, 0x0f, 0xa1, 0x24, 0x59, 0x8c, 0xb2, 0x57, 0xd4, - 0x35, 0x0b, 0xb2, 0xd0, 0xac, 0xa2, 0x72, 0xe3, 0xb7, 0x16, 0x60, 0x49, 0x42, 0x37, 0xc5, 0x8a, - 0xf4, 0xa6, 0xe3, 0xb1, 0xed, 0xa7, 0xf0, 0xae, 0xcc, 0xcb, 0x79, 0x57, 0x76, 0x8e, 0x77, 0x25, - 0x15, 0x56, 0x62, 0x7d, 0x49, 0x85, 0x55, 0x6c, 0x01, 0xe9, 0x10, 0xba, 0xf9, 0xb2, 0x26, 0xc1, - 0x7d, 0x32, 0x93, 0xce, 0x71, 0xda, 0x42, 0x0a, 0xa7, 0xd5, 0xf9, 0xe4, 0xc2, 0x0c, 0x9f, 0x7c, - 0x13, 0x68, 0xaf, 0x15, 0xdb, 0x2f, 0x92, 0x5a, 0x81, 0x30, 0x69, 0x03, 0xbd, 0x0f, 0x8d, 0x59, - 0xd6, 0x44, 0x3c, 0xb0, 0x9e, 0xc2, 0x98, 0x9c, 0x31, 0xc7, 0x4b, 0x46, 0x43, 0x2e, 0x4b, 0xc6, - 0xe4, 0x8c, 0xf9, 0x2e, 0x96, 0x28, 0xfc, 0x0e, 0x00, 0xf5, 0x8d, 0xb4, 0x0e, 0x48, 0xeb, 0xef, - 0x24, 0xf7, 0x42, 0x5f, 0xf5, 0x47, 0xe2, 0x63, 0xea, 0x73, 0x24, 0xfe, 0x32, 0xd6, 0x44, 0xba, - 0x7f, 0x0e, 0x75, 0x6f, 0xc2, 0x5d, 0x2b, 0x66, 0x11, 0x15, 0x6c, 0xea, 0xed, 0x97, 0x34, 0xd5, - 0x55, 0xb8, 0x66, 0x4d, 0xd4, 0x8d, 0x3e, 0xd9, 0x1e, 0x2d, 0x3c, 0xd7, 0x5a, 0xab, 0x7e, 0x85, - 0xd6, 0xea, 0x58, 0x39, 0xfa, 0x36, 0xfe, 0x41, 0x06, 0x2a, 0xda, 0xb0, 0xd9, 0x0a, 0x2c, 0x6e, - 0x1e, 0x1c, 0x1c, 0x76, 0xcc, 0x76, 0xbf, 0xfb, 0x49, 0xc7, 0xda, 0xdc, 0x3d, 0xe8, 0x75, 0x9a, - 0x37, 0x04, 0x78, 0xf7, 0x60, 0xb3, 0xbd, 0x6b, 0x6d, 0x1f, 0x98, 0x9b, 0x0a, 0x9c, 0x61, 0xab, - 0xc0, 0xcc, 0xce, 0xde, 0x41, 0xbf, 0x93, 0x80, 0x67, 0x59, 0x13, 0xaa, 0x1b, 0x66, 0xa7, 0xbd, - 0xb9, 0x23, 0x21, 0x39, 0xb6, 0x0c, 0xcd, 0xed, 0xa3, 0xfd, 0xad, 0xee, 0xfe, 0x33, 0x6b, 0xb3, - 0xbd, 0xbf, 0xd9, 0xd9, 0xed, 0x6c, 0x35, 0xf3, 0xac, 0x06, 0xe5, 0xf6, 0x46, 0x7b, 0x7f, 0xeb, - 0x60, 0xbf, 0xb3, 0xd5, 0x2c, 0x18, 0xbf, 0x02, 0xe5, 0x78, 0xa2, 0x15, 0x28, 0x1e, 0xed, 0x3f, - 0xdf, 0x3f, 0xf8, 0x74, 0xbf, 0x79, 0x83, 0x95, 0xa1, 0x80, 0xfd, 0x37, 0x33, 0x0c, 0x60, 0x81, - 0xfa, 0x6c, 0x66, 0x59, 0x09, 0xf2, 0x1b, 0x07, 0xfd, 0x9d, 0x66, 0xce, 0xf8, 0xf3, 0x0c, 0xac, - 0xe0, 0x94, 0x87, 0xb3, 0x4c, 0xe0, 0x1e, 0x54, 0x06, 0x9e, 0x37, 0x11, 0x0a, 0x52, 0x2c, 0x08, - 0xe8, 0x20, 0x71, 0xc0, 0x89, 0xe7, 0x9e, 0x78, 0xfe, 0x80, 0x4b, 0x1e, 0x00, 0x08, 0xda, 0x16, - 0x10, 0x41, 0x83, 0x92, 0x88, 0x09, 0x83, 0x58, 0x40, 0x85, 0x60, 0x84, 0xb2, 0x0a, 0x0b, 0xc7, - 0x3e, 0xb7, 0x07, 0x67, 0xf2, 0xf4, 0xcb, 0x2f, 0xf6, 0xcd, 0x58, 0x75, 0x1f, 0x08, 0x9a, 0x1a, - 0xf1, 0x21, 0x1e, 0x81, 0x92, 0xd9, 0x90, 0xf0, 0x4d, 0x09, 0x16, 0x97, 0x88, 0x7d, 0x6c, 0xbb, - 0x43, 0xcf, 0xe5, 0x43, 0xa9, 0x21, 0xc4, 0x00, 0xe3, 0x10, 0x56, 0x67, 0xe7, 0x27, 0xf9, 0xc5, - 0x07, 0x1a, 0xbf, 0x20, 0x81, 0x7d, 0xfd, 0x7a, 0x52, 0xd0, 0x78, 0xc7, 0x9f, 0xe5, 0x20, 0x2f, - 0x04, 0xb8, 0x6b, 0x65, 0x3d, 0x5d, 0x22, 0xcf, 0xcd, 0x79, 0x6d, 0xd0, 0x42, 0x40, 0x37, 0x3b, - 0x99, 0xa1, 0xca, 0x08, 0xc1, 0x1b, 0x3d, 0x2a, 0xf6, 0xf9, 0xe0, 0x5c, 0xda, 0xa1, 0xa8, 0xd8, - 0xe4, 0x83, 0x73, 0x54, 0x85, 0xec, 0x90, 0xea, 0xd2, 0x79, 0x2f, 0x06, 0x76, 0x88, 0x35, 0x65, - 0x11, 0xd6, 0x2b, 0x46, 0x45, 0x58, 0xab, 0x05, 0x45, 0xc7, 0x3d, 0xf6, 0xa6, 0xee, 0x10, 0x8f, - 0x77, 0xc9, 0x54, 0x9f, 0xe8, 0x24, 0x42, 0x4e, 0x24, 0xee, 0x0f, 0x3a, 0xcd, 0x25, 0x01, 0xe8, - 0x8b, 0x1b, 0xe4, 0x3d, 0x28, 0x07, 0x57, 0xee, 0x40, 0x3f, 0xc3, 0xcb, 0x72, 0x7d, 0xc4, 0xec, - 0x1f, 0xf5, 0xae, 0xdc, 0x01, 0x9e, 0xd8, 0x52, 0x20, 0xff, 0x62, 0xef, 0x43, 0x29, 0x32, 0xd7, - 0x12, 0x07, 0xbe, 0xa9, 0xd7, 0x50, 0x36, 0x5a, 0xd2, 0x8a, 0x23, 0xd4, 0xf5, 0xe7, 0x50, 0x4b, - 0x14, 0xe9, 0xaa, 0x6c, 0x8d, 0x54, 0xd9, 0xb7, 0x75, 0x55, 0x36, 0x66, 0xec, 0xb2, 0x9a, 0xae, - 0xda, 0xfe, 0x2a, 0x94, 0xd4, 0xc8, 0xc4, 0x71, 0x92, 0x47, 0xc1, 0xea, 0x7d, 0xb6, 0xbf, 0xd9, - 0xbc, 0xc1, 0x1a, 0x50, 0x69, 0x6f, 0xe2, 0x09, 0x45, 0x40, 0x46, 0xa0, 0x1c, 0xb6, 0x7b, 0xbd, - 0x08, 0x92, 0x35, 0x18, 0x34, 0xc5, 0xf5, 0x22, 0x46, 0x1c, 0x39, 0x64, 0x3e, 0x80, 0x45, 0x0d, - 0x16, 0x6b, 0x7b, 0xe2, 0x3e, 0x9a, 0xd5, 0xf6, 0x50, 0xb6, 0xa7, 0x12, 0x63, 0x0d, 0x56, 0xc4, - 0x67, 0xe7, 0x9c, 0xbb, 0x61, 0x6f, 0x7a, 0x4c, 0xee, 0x38, 0xc7, 0x73, 0x85, 0xcc, 0x5f, 0x8e, - 0x4a, 0xae, 0x27, 0xa4, 0x47, 0x52, 0x31, 0xcc, 0xe2, 0xf2, 0xaf, 0x6b, 0x3d, 0x60, 0xc5, 0x47, - 0xf8, 0x6f, 0x42, 0x41, 0x2c, 0x47, 0x20, 0x31, 0xd7, 0xc3, 0x4e, 0xc7, 0xb4, 0x0e, 0xf6, 0x77, - 0xbb, 0xfb, 0x82, 0x19, 0x89, 0xb9, 0x22, 0x60, 0x7b, 0x1b, 0x21, 0x19, 0xa3, 0x09, 0xf5, 0x67, - 0x3c, 0xec, 0xba, 0x27, 0x9e, 0x9a, 0xe9, 0x5f, 0x15, 0xa0, 0x11, 0x81, 0x62, 0x05, 0xf3, 0x9c, - 0xfb, 0x81, 0xe3, 0xb9, 0x28, 0x2b, 0x96, 0x4d, 0xf5, 0x29, 0x6e, 0x10, 0x67, 0xc8, 0xdd, 0xd0, - 0x09, 0xaf, 0xac, 0x84, 0x35, 0xaa, 0xae, 0xc0, 0xf2, 0xa6, 0x5a, 0x86, 0x82, 0x3d, 0x72, 0x6c, - 0xe5, 0xc5, 0xa4, 0x0f, 0x01, 0x1d, 0x78, 0x23, 0xcf, 0x47, 0xb1, 0xb0, 0x6c, 0xd2, 0x07, 0x7b, - 0x02, 0xcb, 0x42, 0x3c, 0xd5, 0x4d, 0x84, 0x78, 0x46, 0xc9, 0x30, 0xc6, 0xdc, 0xe9, 0xf8, 0x30, - 0x36, 0x13, 0x8a, 0x12, 0x71, 0x3f, 0x89, 0x1a, 0x52, 0x20, 0x89, 0x2a, 0x90, 0xa6, 0xb3, 0xe8, - 0x4e, 0xc7, 0x6d, 0x2c, 0x89, 0xf0, 0x9f, 0xc2, 0x8a, 0xc0, 0x8f, 0x44, 0x98, 0xa8, 0x46, 0x03, - 0x6b, 0x88, 0xc6, 0xba, 0xb2, 0x2c, 0xaa, 0x73, 0x0b, 0xca, 0x34, 0x2a, 0xb1, 0xe3, 0x05, 0x92, - 0x70, 0x71, 0x28, 0xdc, 0x0f, 0xe6, 0x1c, 0x8e, 0x0b, 0x74, 0xd9, 0xce, 0x38, 0x1c, 0x35, 0x97, - 0x65, 0x69, 0xd6, 0x65, 0xf9, 0x14, 0x56, 0x8e, 0x79, 0x10, 0x5a, 0x67, 0xdc, 0x1e, 0x72, 0x1f, - 0x4f, 0x24, 0xb9, 0x26, 0x49, 0x92, 0x5f, 0x12, 0x85, 0x3b, 0x58, 0xd6, 0x57, 0x45, 0x42, 0x96, - 0x10, 0x47, 0x8f, 0x0f, 0xad, 0xd0, 0xb3, 0x50, 0xc4, 0xc0, 0x43, 0x5c, 0x32, 0x6b, 0x04, 0xee, - 0x7b, 0x9b, 0x02, 0x98, 0xc4, 0x3b, 0xf5, 0xed, 0xc9, 0x99, 0x94, 0xb5, 0x23, 0xbc, 0x67, 0x02, - 0xc8, 0x6e, 0x43, 0x31, 0xe4, 0x41, 0xe8, 0x72, 0xf2, 0x0b, 0x91, 0x34, 0xab, 0x40, 0xec, 0x6d, - 0x58, 0xc0, 0x3e, 0x82, 0x56, 0x13, 0xe9, 0xbd, 0x1a, 0x33, 0x4b, 0xc7, 0x35, 0x65, 0x99, 0x10, - 0xd8, 0xa6, 0xbe, 0x13, 0xb4, 0xaa, 0xe8, 0x0f, 0xc5, 0xbf, 0xd9, 0x0f, 0x35, 0xb6, 0xb0, 0x84, - 0x75, 0xd5, 0x9d, 0x3b, 0x43, 0x69, 0xbf, 0x14, 0x0e, 0xf1, 0xa3, 0x7c, 0xa9, 0xd2, 0xac, 0x1a, - 0xdf, 0x83, 0x02, 0xad, 0x8e, 0x20, 0x42, 0x5c, 0xbb, 0x8c, 0x24, 0x42, 0x84, 0xb6, 0xa0, 0xe8, - 0xf2, 0xf0, 0xc2, 0xf3, 0x5f, 0x28, 0x7b, 0xad, 0xfc, 0x34, 0x7e, 0x8a, 0x86, 0x86, 0xc8, 0x19, - 0x4d, 0x3a, 0x93, 0x20, 0x0f, 0xda, 0xde, 0xe0, 0xcc, 0x96, 0xb6, 0x8f, 0x12, 0x02, 0x7a, 0x67, - 0xf6, 0x1c, 0x79, 0x64, 0xe7, 0xfd, 0xd1, 0x6f, 0x43, 0x5d, 0xb9, 0xbf, 0x03, 0x6b, 0xc4, 0x4f, - 0x42, 0x49, 0xee, 0x55, 0xe9, 0xfb, 0x0e, 0x76, 0xf9, 0x49, 0x68, 0xec, 0xc1, 0xa2, 0x24, 0xc8, - 0x83, 0x09, 0x57, 0x5d, 0x7f, 0x3f, 0x4d, 0x66, 0xad, 0x3c, 0x5d, 0x4a, 0x5e, 0x66, 0xe4, 0xd6, - 0x4f, 0x08, 0xb2, 0xc6, 0xc7, 0xc0, 0xf4, 0xab, 0x4e, 0xb6, 0x27, 0x25, 0x47, 0x65, 0xe6, 0x56, - 0xde, 0xa2, 0x48, 0x3e, 0x75, 0x86, 0x62, 0x75, 0x82, 0xe9, 0x60, 0xa0, 0xc2, 0x12, 0x4a, 0xa6, - 0xfa, 0x34, 0xfe, 0x24, 0x03, 0x4b, 0xd8, 0x98, 0x92, 0xb9, 0xa5, 0x34, 0xf1, 0xb5, 0x07, 0x29, - 0xf6, 0x47, 0x97, 0x2f, 0xe8, 0xe3, 0xab, 0x1b, 0x16, 0xf3, 0x73, 0x86, 0xc5, 0x6f, 0x42, 0x73, - 0xc8, 0x47, 0x0e, 0x46, 0xa8, 0xa8, 0xeb, 0x9a, 0xa4, 0xec, 0x86, 0x82, 0x2b, 0x45, 0xe9, 0x9f, - 0x65, 0x60, 0x91, 0xa4, 0x01, 0x54, 0x39, 0xe5, 0x42, 0x7d, 0xa4, 0x74, 0x2c, 0xc9, 0xaa, 0xe4, - 0x9c, 0xe2, 0x5b, 0x12, 0xa1, 0x84, 0xbc, 0x73, 0x43, 0xea, 0x5e, 0x12, 0xca, 0x3e, 0x44, 0x3d, - 0xc1, 0xb5, 0x10, 0x98, 0x12, 0xf1, 0x92, 0xdc, 0x94, 0x9d, 0x1b, 0xa8, 0x44, 0xb8, 0x08, 0xda, - 0x28, 0x09, 0xa5, 0x4f, 0x80, 0x8d, 0x6d, 0xa8, 0x25, 0xba, 0x49, 0x58, 0x3f, 0xab, 0x64, 0xfd, - 0x9c, 0xf3, 0x30, 0x64, 0xe7, 0x3d, 0x0c, 0x7f, 0x2f, 0x0f, 0x4c, 0x90, 0xd4, 0xcc, 0xae, 0xcd, - 0xb8, 0xe7, 0xb2, 0x73, 0xee, 0xb9, 0x27, 0xc0, 0x34, 0x04, 0xe5, 0x35, 0xcc, 0x45, 0x5e, 0xc3, - 0x66, 0x8c, 0x2b, 0x9d, 0x86, 0x4f, 0x60, 0x59, 0x0a, 0x8d, 0x91, 0x3f, 0x0e, 0xcd, 0x5a, 0xb4, - 0x3f, 0x8c, 0xa4, 0x47, 0xe5, 0x97, 0x43, 0x13, 0x97, 0x72, 0xcd, 0x09, 0xb5, 0x9c, 0xac, 0x41, - 0xe8, 0x9a, 0x13, 0x9a, 0xf8, 0x0c, 0x15, 0x2c, 0xbc, 0x92, 0x0a, 0x8a, 0x73, 0x54, 0xa0, 0x19, - 0x27, 0x4a, 0x49, 0xe3, 0x84, 0x01, 0x35, 0xe5, 0x80, 0xa3, 0xb8, 0x03, 0x92, 0x90, 0x2a, 0xd2, - 0x0b, 0x87, 0xb1, 0x07, 0x0f, 0xa0, 0xa9, 0x2c, 0x08, 0x91, 0xf9, 0x83, 0x7c, 0xea, 0xd2, 0x00, - 0xb5, 0xa9, 0x8c, 0x20, 0x09, 0x63, 0x73, 0x65, 0xc6, 0xd8, 0xfc, 0x2e, 0x2c, 0x06, 0x82, 0x88, - 0xac, 0xa9, 0x2b, 0x03, 0x60, 0xf8, 0x10, 0xd5, 0x93, 0x92, 0xd9, 0xc4, 0x82, 0xa3, 0x18, 0x3e, - 0xaf, 0xda, 0xd7, 0xe6, 0x55, 0x7b, 0xf6, 0x7e, 0xec, 0xab, 0x0a, 0xce, 0x9c, 0x31, 0x5e, 0xdc, - 0x71, 0xb0, 0x88, 0x5c, 0xe0, 0xde, 0x99, 0x33, 0x36, 0x95, 0x63, 0x54, 0x7c, 0x18, 0xff, 0x25, - 0x03, 0x4d, 0x41, 0x07, 0x09, 0x3a, 0xff, 0x15, 0xc0, 0x13, 0xf9, 0x9a, 0x64, 0x5e, 0x11, 0xb8, - 0x8a, 0xca, 0xbf, 0x07, 0x48, 0xb6, 0x96, 0xd0, 0xc5, 0x24, 0x91, 0xb7, 0x92, 0x44, 0x1e, 0x33, - 0xb2, 0x9d, 0x1b, 0x24, 0x64, 0x0b, 0x48, 0x9a, 0x8f, 0x30, 0x9f, 0xe2, 0x23, 0xd4, 0x8e, 0xc2, - 0x0e, 0xc0, 0x73, 0x7e, 0xb5, 0xeb, 0x0d, 0x50, 0x0b, 0xba, 0x03, 0x20, 0x08, 0xf2, 0xc4, 0x1e, - 0x3b, 0xd2, 0x82, 0x51, 0x30, 0xcb, 0x2f, 0xf8, 0xd5, 0x36, 0x02, 0xc4, 0x6e, 0x88, 0xe2, 0xf8, - 0x3c, 0x14, 0xcc, 0xd2, 0x0b, 0x7e, 0x45, 0x87, 0xc1, 0x82, 0xda, 0x73, 0x7e, 0xb5, 0xc5, 0x49, - 0x5c, 0xf3, 0x7c, 0x41, 0x09, 0xbe, 0x7d, 0x21, 0xe4, 0xb3, 0x84, 0x7f, 0xaf, 0xe2, 0xdb, 0x17, - 0xcf, 0xf9, 0x95, 0xf2, 0x35, 0x16, 0x45, 0xf9, 0xc8, 0x1b, 0xc8, 0x1b, 0x48, 0x45, 0x2a, 0xc4, - 0x83, 0x32, 0x17, 0x5e, 0xe0, 0xdf, 0xc6, 0x1f, 0x67, 0xa0, 0x26, 0xc6, 0x8f, 0x0c, 0x4e, 0xac, - 0xbb, 0x0a, 0x78, 0xc9, 0xc4, 0x01, 0x2f, 0x4f, 0x25, 0x7f, 0x20, 0x6e, 0x99, 0xbd, 0x9e, 0x5b, - 0xe2, 0x02, 0x13, 0xab, 0x7c, 0x0f, 0xca, 0x74, 0xb6, 0xc4, 0x61, 0xcd, 0x25, 0x76, 0x29, 0x31, - 0x21, 0xb3, 0x84, 0x68, 0xcf, 0xc9, 0xbf, 0xae, 0x19, 0xb1, 0x68, 0x89, 0xcb, 0x7e, 0x64, 0xba, - 0x4a, 0xd9, 0x86, 0x42, 0x9a, 0xab, 0xf6, 0x08, 0x2a, 0x1a, 0x4d, 0xa1, 0xc5, 0x2b, 0x1a, 0x3c, - 0x11, 0x60, 0x92, 0x68, 0x12, 0xb3, 0xdf, 0xb9, 0x61, 0xd6, 0x06, 0x3a, 0x60, 0x63, 0x01, 0xf2, - 0xa2, 0x92, 0xf1, 0x11, 0x2c, 0x6a, 0xcd, 0x92, 0xc6, 0x97, 0x36, 0xa6, 0x4c, 0xda, 0x98, 0xfe, - 0x79, 0x06, 0x96, 0x65, 0x6d, 0x0c, 0x8e, 0x72, 0xc4, 0x75, 0xbd, 0x17, 0x9c, 0xb2, 0x5f, 0x81, - 0x9a, 0x68, 0xdd, 0xf2, 0xf9, 0xa9, 0x13, 0x84, 0x5c, 0x79, 0x07, 0x52, 0x0e, 0x87, 0xe0, 0xda, - 0x02, 0xd5, 0x94, 0x98, 0xec, 0x23, 0xa8, 0x60, 0x55, 0xd2, 0x49, 0xe5, 0xb6, 0xb4, 0xe6, 0x2b, - 0xd2, 0x50, 0x77, 0x6e, 0x98, 0x10, 0x44, 0x5f, 0x1b, 0x65, 0x28, 0x86, 0xbe, 0x73, 0x7a, 0xca, - 0x7d, 0x63, 0x35, 0x1a, 0x9a, 0x38, 0x69, 0xbc, 0x17, 0xf2, 0x89, 0x10, 0x82, 0x8c, 0xff, 0x96, - 0x81, 0x8a, 0x3c, 0x3b, 0x5f, 0xdb, 0x25, 0xb0, 0xae, 0x45, 0xf7, 0x91, 0xfa, 0x19, 0x07, 0xf3, - 0xdd, 0x87, 0xc6, 0x58, 0x08, 0x44, 0x42, 0x60, 0x4f, 0xf8, 0x03, 0xea, 0x0a, 0x2c, 0xe5, 0x91, - 0x47, 0xb0, 0x84, 0xe2, 0x49, 0x60, 0x85, 0xce, 0xc8, 0x52, 0x85, 0x32, 0x92, 0x6e, 0x91, 0x8a, - 0xfa, 0xce, 0x68, 0x4f, 0x16, 0x88, 0x5b, 0x3a, 0x08, 0xed, 0x53, 0x2e, 0x45, 0x5f, 0xfa, 0x30, - 0x5a, 0xb0, 0x3a, 0x23, 0xab, 0x2b, 0x3d, 0xe3, 0x1f, 0xd6, 0x60, 0x6d, 0xae, 0x48, 0xea, 0x1b, - 0x91, 0x1d, 0x7c, 0xe4, 0x8c, 0x8f, 0xbd, 0xc8, 0xdc, 0x94, 0xd1, 0xec, 0xe0, 0xbb, 0xa2, 0x44, - 0x99, 0x9b, 0x38, 0xac, 0x28, 0x82, 0x40, 0x7b, 0x51, 0x24, 0xce, 0x67, 0x51, 0xd8, 0x7c, 0x2f, - 0xc9, 0xa8, 0x66, 0xbb, 0x53, 0x70, 0xfd, 0xfa, 0x5b, 0x9a, 0xcc, 0xc1, 0x02, 0x76, 0x02, 0xad, - 0x88, 0xee, 0xa4, 0x7c, 0xa4, 0xe9, 0x26, 0xa2, 0xa7, 0x6f, 0xbd, 0xa2, 0xa7, 0x84, 0x21, 0xc2, - 0x5c, 0x55, 0xe4, 0x4a, 0x8d, 0x45, 0xfd, 0x9c, 0xc3, 0x1b, 0xaa, 0x1f, 0x94, 0x75, 0xe6, 0x7b, - 0xcb, 0xbf, 0xd6, 0xbc, 0xd0, 0xc0, 0x92, 0xec, 0xf2, 0x96, 0x6c, 0x38, 0x2a, 0xd2, 0xfb, 0x3d, - 0x83, 0xd5, 0x0b, 0xdb, 0x09, 0xd5, 0xfc, 0x34, 0xb5, 0xa8, 0x80, 0xfd, 0x3d, 0x7d, 0x45, 0x7f, - 0x9f, 0x52, 0xe5, 0x84, 0xf4, 0xb7, 0x7c, 0x31, 0x0f, 0x0c, 0xd6, 0xff, 0x53, 0x16, 0xea, 0xc9, - 0x56, 0xc4, 0xa1, 0x96, 0x7c, 0x48, 0xc9, 0x13, 0x52, 0x1e, 0x97, 0x66, 0xd0, 0x7d, 0x92, 0x23, - 0xe6, 0x0d, 0xb4, 0xd9, 0x14, 0x03, 0xad, 0x6e, 0x17, 0xcd, 0xbd, 0xca, 0x7f, 0x94, 0x7f, 0x2d, - 0xff, 0x51, 0x21, 0xcd, 0x7f, 0x74, 0xbd, 0xd3, 0x61, 0xe1, 0x6b, 0x39, 0x1d, 0x8a, 0xd7, 0x3b, - 0x1d, 0xd6, 0xff, 0x3a, 0x03, 0x6c, 0x9e, 0x52, 0xd9, 0x33, 0xb2, 0x45, 0xbb, 0x7c, 0x24, 0xb9, - 0xd8, 0xb7, 0x5f, 0x8f, 0xda, 0xd5, 0x06, 0xa9, 0xda, 0xec, 0x31, 0x2c, 0xe9, 0xb1, 0xb7, 0xba, - 0xaa, 0x52, 0x33, 0x99, 0x5e, 0x14, 0x2b, 0xb4, 0x9a, 0xf3, 0x2c, 0xff, 0x4a, 0xe7, 0x59, 0xe1, - 0x95, 0xce, 0xb3, 0x85, 0xa4, 0xf3, 0x6c, 0xfd, 0xef, 0x64, 0x60, 0x29, 0x85, 0xa8, 0x7e, 0x71, - 0x73, 0x16, 0xb4, 0x90, 0x60, 0x31, 0x59, 0x49, 0x0b, 0x1a, 0x77, 0x59, 0xff, 0x02, 0x6a, 0x89, - 0x43, 0xf4, 0x8b, 0xeb, 0x7e, 0x56, 0xd1, 0x22, 0x52, 0xd6, 0x15, 0xad, 0xf5, 0xbf, 0xcc, 0x02, - 0x9b, 0x3f, 0xc7, 0xbf, 0xcc, 0x21, 0xcc, 0x2f, 0x52, 0x6e, 0x7e, 0x91, 0xfe, 0xdf, 0xdd, 0x2b, - 0xef, 0xc2, 0xa2, 0xcc, 0x17, 0xd0, 0x1c, 0x0f, 0x44, 0x28, 0xcd, 0xa8, 0x40, 0x8d, 0xe2, 0x7b, - 0xb3, 0x7e, 0xcb, 0x52, 0x22, 0x44, 0x5a, 0xbb, 0x58, 0x93, 0xee, 0x4b, 0x63, 0x1d, 0x5a, 0x72, - 0x69, 0xe6, 0x4d, 0x75, 0xbf, 0x93, 0x8f, 0xb4, 0x64, 0x2c, 0x94, 0x42, 0xf1, 0x77, 0xa0, 0xaa, - 0x5f, 0x36, 0x72, 0x1f, 0x66, 0x3c, 0x4e, 0x42, 0x1c, 0xf6, 0xb4, 0xd3, 0xba, 0x09, 0xe4, 0x47, - 0x18, 0x46, 0xd5, 0x48, 0x82, 0x78, 0x89, 0xe1, 0x19, 0x85, 0xa3, 0xc4, 0xe6, 0xff, 0x7f, 0x50, - 0x4f, 0xda, 0xad, 0xa4, 0xa8, 0x97, 0x26, 0x1d, 0x8a, 0xda, 0x09, 0x43, 0x16, 0xfb, 0x21, 0x34, - 0x67, 0xed, 0x5e, 0x32, 0x7e, 0xf3, 0x9a, 0xfa, 0x0d, 0x27, 0x69, 0x0a, 0x63, 0x3b, 0xb0, 0x9c, - 0x76, 0xdd, 0xe2, 0xae, 0x5c, 0xaf, 0x16, 0xb0, 0xf9, 0x2b, 0x95, 0x7d, 0x5f, 0x9a, 0x37, 0x0b, - 0x69, 0x8e, 0x18, 0x6d, 0xb1, 0x1f, 0xd1, 0x7f, 0x9a, 0xa1, 0xf3, 0x1c, 0x20, 0x86, 0xb1, 0x26, - 0x54, 0x0f, 0x0e, 0x3b, 0xfb, 0xd6, 0xe6, 0x4e, 0x7b, 0x7f, 0xbf, 0xb3, 0xdb, 0xbc, 0xc1, 0x18, - 0xd4, 0xd1, 0x83, 0xb2, 0x15, 0xc1, 0x32, 0x02, 0x26, 0x6d, 0xbf, 0x0a, 0x96, 0x65, 0xcb, 0xd0, - 0xec, 0xee, 0xcf, 0x40, 0x73, 0xac, 0x05, 0xcb, 0x87, 0x1d, 0x72, 0xba, 0x24, 0xda, 0xcd, 0x0b, - 0x11, 0x4e, 0x4e, 0x57, 0x88, 0x70, 0x94, 0x6d, 0x22, 0xa9, 0x4f, 0x49, 0x36, 0xbf, 0x9b, 0x81, - 0x95, 0x99, 0x82, 0x38, 0x86, 0x98, 0xe4, 0x9a, 0xa4, 0x44, 0x53, 0x45, 0xa0, 0xa2, 0xe1, 0x77, - 0x61, 0x31, 0x52, 0xf5, 0x66, 0xf8, 0x52, 0x33, 0x2a, 0x50, 0xc8, 0x8f, 0x61, 0x49, 0xd3, 0x18, - 0x67, 0x4e, 0x28, 0xd3, 0x8a, 0x64, 0x05, 0x63, 0x2d, 0x8a, 0xd5, 0x9c, 0x19, 0xf5, 0x90, 0x52, - 0x58, 0xf4, 0x82, 0xd8, 0xfa, 0x9b, 0x1c, 0xaf, 0xfa, 0x14, 0xaa, 0x7c, 0x82, 0x10, 0x92, 0xa3, - 0xd5, 0x37, 0x5c, 0x75, 0xff, 0xfb, 0x0b, 0xc0, 0x3e, 0x9e, 0x72, 0xff, 0x0a, 0x63, 0x84, 0x83, - 0x57, 0x05, 0xcd, 0x28, 0xb5, 0x28, 0xfb, 0x5a, 0x79, 0x00, 0x69, 0x71, 0xf8, 0xf9, 0x57, 0xc7, - 0xe1, 0x17, 0x5e, 0x15, 0x87, 0xff, 0x16, 0xd4, 0x9c, 0x53, 0xd7, 0x13, 0x0c, 0x48, 0xc8, 0x26, - 0x41, 0x6b, 0xe1, 0x5e, 0xee, 0x41, 0xd5, 0xac, 0x4a, 0xa0, 0x90, 0x4c, 0x02, 0xf6, 0x51, 0x8c, - 0xc4, 0x87, 0xa7, 0x98, 0x33, 0xa2, 0xb3, 0x9e, 0xce, 0xf0, 0x94, 0x4b, 0x2d, 0x10, 0xed, 0x22, - 0xaa, 0xb2, 0x80, 0x07, 0xec, 0x6d, 0xa8, 0x07, 0xde, 0x54, 0x88, 0x7a, 0x6a, 0x19, 0xc8, 0x3e, - 0x5c, 0x25, 0xe8, 0xa1, 0x72, 0x06, 0x2c, 0x4d, 0x03, 0x6e, 0x8d, 0x9d, 0x20, 0x10, 0x17, 0xf4, - 0xc0, 0x73, 0x43, 0xdf, 0x1b, 0x49, 0x93, 0xef, 0xe2, 0x34, 0xe0, 0x7b, 0x54, 0xb2, 0x49, 0x05, - 0xec, 0xbb, 0xf1, 0x90, 0x26, 0xb6, 0xe3, 0x07, 0x2d, 0xc0, 0x21, 0xa9, 0x99, 0xa2, 0x44, 0x65, - 0x3b, 0x7e, 0x34, 0x16, 0xf1, 0x11, 0xcc, 0xe4, 0x07, 0x54, 0x66, 0xf3, 0x03, 0x7e, 0x92, 0x9e, - 0x1f, 0x50, 0xc3, 0xa6, 0x9f, 0xc8, 0xa6, 0xe7, 0xb7, 0xf8, 0x2b, 0xa5, 0x09, 0xcc, 0xa7, 0x3d, - 0xd4, 0xbf, 0x4a, 0xda, 0x43, 0x23, 0x2d, 0xed, 0xe1, 0x3d, 0xa8, 0x60, 0x40, 0xba, 0x75, 0xe6, - 0xb8, 0xa1, 0x32, 0x61, 0x37, 0xf5, 0x88, 0xf5, 0x1d, 0xa1, 0x4c, 0x83, 0xaf, 0xfe, 0x0c, 0xe6, - 0x33, 0x10, 0x16, 0x7f, 0x89, 0x19, 0x08, 0x32, 0x70, 0xfe, 0x11, 0x94, 0xd4, 0x3e, 0x31, 0x06, - 0xf9, 0x13, 0xdf, 0x1b, 0x2b, 0xd3, 0x9e, 0xf8, 0x9b, 0xd5, 0x21, 0x1b, 0x7a, 0xb2, 0x72, 0x36, - 0xf4, 0x8c, 0xdf, 0x80, 0x8a, 0x46, 0x6a, 0xec, 0x4d, 0x32, 0x22, 0x08, 0x69, 0x59, 0x6a, 0xc9, - 0xb4, 0x8a, 0x65, 0x09, 0xed, 0x0e, 0x05, 0xbf, 0x19, 0x3a, 0x3e, 0xc7, 0x5c, 0x21, 0xcb, 0xe7, - 0xe7, 0xdc, 0x0f, 0x94, 0xa9, 0xb5, 0x19, 0x15, 0x98, 0x04, 0x37, 0xfe, 0x26, 0x2c, 0x25, 0xf6, - 0x56, 0xb2, 0x88, 0xb7, 0x61, 0x01, 0xd7, 0x4d, 0xb9, 0xc2, 0x92, 0x99, 0x00, 0xb2, 0x0c, 0x93, - 0x40, 0xc9, 0x4a, 0x6c, 0x4d, 0x7c, 0xef, 0x18, 0x3b, 0xc9, 0x98, 0x15, 0x09, 0x3b, 0xf4, 0xbd, - 0x63, 0xe3, 0xcf, 0x72, 0x90, 0xdb, 0xf1, 0x26, 0x7a, 0x84, 0x45, 0x66, 0x2e, 0xc2, 0x42, 0xaa, - 0x00, 0x56, 0x24, 0xe2, 0x4b, 0xa9, 0x0d, 0xed, 0xa3, 0x4a, 0xcc, 0x7f, 0x00, 0x75, 0xc1, 0x27, - 0x42, 0x4f, 0xe8, 0x50, 0x17, 0xb6, 0x4f, 0x79, 0x01, 0x39, 0x3a, 0x7c, 0xf6, 0x38, 0xec, 0x7b, - 0xdb, 0x04, 0x67, 0xcb, 0x90, 0x8b, 0x04, 0x58, 0x2c, 0x16, 0x9f, 0x42, 0xb9, 0xc6, 0x08, 0xb9, - 0x2b, 0xe9, 0xeb, 0x91, 0x5f, 0xec, 0xdb, 0xb0, 0x94, 0x6c, 0x97, 0x58, 0x91, 0x94, 0x48, 0xf4, - 0x86, 0x91, 0x27, 0xdd, 0x04, 0xc1, 0x47, 0x08, 0x47, 0xba, 0x65, 0x4f, 0x38, 0xc7, 0x22, 0x8d, - 0xe9, 0x95, 0x12, 0x4c, 0xef, 0x2e, 0x54, 0xc2, 0xd1, 0xb9, 0x35, 0xb1, 0xaf, 0x46, 0x9e, 0x3d, - 0x94, 0xe7, 0x1b, 0xc2, 0xd1, 0xf9, 0x21, 0x41, 0xd8, 0x63, 0x80, 0xf1, 0x64, 0x22, 0xcf, 0x1e, - 0x9a, 0x1b, 0x63, 0x52, 0xde, 0x3b, 0x3c, 0x24, 0x92, 0x33, 0xcb, 0xe3, 0xc9, 0x84, 0xfe, 0x64, - 0x5b, 0x50, 0x4f, 0xcd, 0xe7, 0xb9, 0xa3, 0x02, 0xba, 0xbc, 0xc9, 0xa3, 0x94, 0xc3, 0x59, 0x1b, - 0xe8, 0xb0, 0xf5, 0x1f, 0x02, 0xfb, 0x39, 0xb3, 0x6a, 0xfa, 0x50, 0x8e, 0xc6, 0xa7, 0x27, 0xa5, - 0x60, 0x88, 0x66, 0x25, 0x91, 0x94, 0xd2, 0x1e, 0x0e, 0x7d, 0xc1, 0x17, 0xe9, 0xc2, 0x8c, 0x58, - 0x3e, 0x68, 0x37, 0x66, 0x9b, 0xf8, 0xbe, 0xf1, 0x17, 0x19, 0x28, 0x50, 0x86, 0xcc, 0x3b, 0xd0, - 0x20, 0xfc, 0x28, 0x5a, 0x45, 0x7a, 0x88, 0xe8, 0xde, 0xed, 0xcb, 0x40, 0x15, 0x71, 0x2c, 0xb4, - 0xec, 0xbe, 0x6c, 0xb4, 0xf3, 0x5a, 0x86, 0xdf, 0x5d, 0x28, 0x47, 0x5d, 0x6b, 0xa4, 0x53, 0x52, - 0x3d, 0xb3, 0x37, 0x20, 0x7f, 0xe6, 0x4d, 0x94, 0x2e, 0x0e, 0xf1, 0x4a, 0x9a, 0x08, 0x8f, 0xc7, - 0x22, 0xfa, 0xa0, 0xc1, 0x4b, 0x1d, 0x32, 0xea, 0x04, 0xc9, 0x60, 0x7e, 0x8e, 0x0b, 0x29, 0x73, - 0x3c, 0x82, 0x86, 0xe0, 0x03, 0x9a, 0xa7, 0xf6, 0xfa, 0x4b, 0xf3, 0x9b, 0x42, 0xc2, 0x1b, 0x8c, - 0xa6, 0x43, 0xae, 0x5b, 0x42, 0x30, 0x74, 0x42, 0xc2, 0x95, 0x7a, 0x60, 0xfc, 0x7e, 0x86, 0xf8, - 0x8b, 0x68, 0x97, 0x3d, 0x80, 0xbc, 0xb8, 0xdf, 0x66, 0x2c, 0x75, 0x51, 0xac, 0xac, 0xc0, 0x33, - 0x11, 0x03, 0x53, 0x62, 0xa7, 0xe3, 0x64, 0xeb, 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0x31, 0xe1, - 0x1b, 0x6a, 0x5a, 0x33, 0x8a, 0x38, 0xcd, 0x3e, 0x3a, 0xa6, 0x8f, 0xb4, 0x18, 0x8c, 0x7c, 0xe2, - 0xc6, 0x54, 0x52, 0xe0, 0xf0, 0x94, 0x6b, 0xb1, 0x17, 0x7f, 0x98, 0x85, 0x5a, 0x62, 0x44, 0x18, - 0x84, 0x22, 0x2e, 0x00, 0xb2, 0x02, 0xcb, 0xfd, 0x06, 0x01, 0x92, 0x82, 0xba, 0xb6, 0x4e, 0xd9, - 0xc4, 0x3a, 0x45, 0x3e, 0xe9, 0x9c, 0xee, 0x93, 0x7e, 0x02, 0xe5, 0x38, 0xab, 0x33, 0x39, 0x24, - 0xd1, 0x9f, 0x8a, 0x18, 0x8e, 0x91, 0x62, 0x2f, 0x76, 0x41, 0xf7, 0x62, 0xff, 0x40, 0x73, 0x7a, - 0x2e, 0x60, 0x33, 0x46, 0xda, 0x8a, 0xfe, 0x72, 0x82, 0x22, 0x3e, 0x82, 0x8a, 0x36, 0x78, 0xdd, - 0xb9, 0x99, 0x49, 0x38, 0x37, 0xa3, 0xd8, 0xfe, 0x6c, 0x1c, 0xdb, 0x6f, 0xfc, 0x56, 0x16, 0x6a, - 0xe2, 0x7c, 0x39, 0xee, 0xe9, 0xa1, 0x37, 0x72, 0x06, 0x68, 0x15, 0x8e, 0x4e, 0x98, 0x14, 0xb4, - 0xd4, 0x39, 0x93, 0x47, 0x8c, 0xe4, 0x2c, 0x3d, 0x85, 0x89, 0x98, 0x74, 0x94, 0xc2, 0x64, 0x40, - 0x4d, 0x30, 0xc6, 0x63, 0x3b, 0xe0, 0x5a, 0xce, 0xa9, 0x59, 0x39, 0xe1, 0x7c, 0xc3, 0x0e, 0x88, - 0x43, 0x7e, 0x1b, 0x96, 0x04, 0x0e, 0x66, 0x6f, 0x8c, 0x9d, 0xd1, 0xc8, 0x21, 0x4c, 0x32, 0x35, - 0x34, 0x4f, 0x38, 0x37, 0xed, 0x90, 0xef, 0x89, 0x02, 0x99, 0xa2, 0x5a, 0x1a, 0x3a, 0x81, 0x7d, - 0x1c, 0x87, 0x0a, 0x45, 0xdf, 0xe8, 0xcb, 0xb1, 0x2f, 0x35, 0x5f, 0x0e, 0xa5, 0x71, 0x55, 0xc6, - 0xf6, 0x65, 0xe4, 0xcb, 0x99, 0xa1, 0xa4, 0xe2, 0x2c, 0x25, 0x19, 0xff, 0x35, 0x0b, 0x15, 0x8d, - 0x2c, 0x5f, 0xe7, 0x76, 0xbd, 0x33, 0x67, 0xc5, 0x2f, 0xeb, 0x06, 0xfb, 0xb7, 0x92, 0x5d, 0xa2, - 0xcb, 0x97, 0x92, 0x61, 0x35, 0x02, 0xbe, 0x05, 0x65, 0x71, 0xea, 0xde, 0x43, 0xa3, 0x98, 0x4c, - 0xe5, 0x46, 0xc0, 0xe1, 0xf4, 0x58, 0x15, 0x3e, 0xc5, 0xc2, 0x42, 0x5c, 0xf8, 0x54, 0x14, 0xbe, - 0x2c, 0x3e, 0xf0, 0x7b, 0x50, 0x95, 0xad, 0xe2, 0x9e, 0xe2, 0x74, 0xe3, 0x53, 0x9f, 0xd8, 0x6f, - 0xb3, 0x42, 0xdd, 0xd1, 0xe6, 0xcb, 0x8a, 0x4f, 0x55, 0xc5, 0xd2, 0xab, 0x2a, 0x3e, 0xa5, 0x0f, - 0x63, 0x3b, 0x0a, 0xb9, 0xc4, 0x70, 0x03, 0xc5, 0xc7, 0x1e, 0xc3, 0x92, 0x62, 0x57, 0x53, 0xd7, - 0x76, 0x5d, 0x6f, 0xea, 0x0e, 0xb8, 0x0a, 0xfa, 0x67, 0xb2, 0xe8, 0x28, 0x2e, 0x31, 0x86, 0x51, - 0x56, 0x18, 0x85, 0x2d, 0x3c, 0x84, 0x02, 0xc9, 0xe5, 0x24, 0x7c, 0xa4, 0x33, 0x2e, 0x42, 0x61, - 0x0f, 0xa0, 0x40, 0xe2, 0x79, 0xf6, 0x5a, 0x66, 0x43, 0x08, 0xc6, 0x23, 0x68, 0xa0, 0x88, 0xa9, - 0x71, 0xdc, 0x97, 0x49, 0x25, 0xc6, 0x32, 0xb0, 0x7d, 0x3a, 0x44, 0x7a, 0x38, 0xcd, 0xff, 0xc8, - 0x41, 0x45, 0x03, 0x0b, 0xb6, 0x88, 0x01, 0x18, 0xd6, 0xd0, 0xb1, 0xc7, 0x5c, 0xf9, 0x1e, 0x6a, + // 11219 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x1c, 0x49, + 0x72, 0x18, 0xfb, 0x35, 0xdd, 0x1d, 0xfd, 0x9c, 0x9c, 0x57, 0x73, 0xb8, 0x5c, 0x72, 0x6b, 0xf7, + 0x96, 0x3c, 0xee, 0x1d, 0xc9, 0xe5, 0x1d, 0xf7, 0x4e, 0xbb, 0xf6, 0xe9, 0x7a, 0x66, 0x7a, 0x38, + 0x7d, 0x9c, 0xd7, 0x56, 0xf7, 0xec, 0x6a, 0x4f, 0x96, 0xeb, 0x6a, 0xba, 0x73, 0x66, 0x4a, 0xec, + 0xae, 0xea, 0xad, 0xaa, 0x9e, 0xc7, 0x1d, 0xd6, 0x1f, 0xfc, 0x10, 0x0c, 0xbf, 0x00, 0xc1, 0x96, + 0x01, 0xcb, 0x16, 0x6c, 0xd8, 0x30, 0x0c, 0xc3, 0x80, 0x20, 0xe3, 0x64, 0xc0, 0x1f, 0xfc, 0x5d, + 0x5f, 0x6c, 0xe8, 0x83, 0xe4, 0x2f, 0x86, 0x20, 0x40, 0xb0, 0x7c, 0xfe, 0xaa, 0x9f, 0x60, 0x64, + 0x44, 0x66, 0x55, 0x56, 0x77, 0x0d, 0xc9, 0xbd, 0x5b, 0xdf, 0x17, 0x72, 0x2a, 0x32, 0xf2, 0x1d, + 0x19, 0x19, 0x8f, 0x8c, 0x68, 0x28, 0xfb, 0x93, 0xc1, 0xc3, 0x89, 0xef, 0x85, 0x1e, 0x2b, 0x8c, + 0x5c, 0x7f, 0x32, 0x58, 0x7f, 0xe3, 0xd4, 0xf3, 0x4e, 0x47, 0xfc, 0x91, 0x3d, 0x71, 0x1e, 0xd9, + 0xae, 0xeb, 0x85, 0x76, 0xe8, 0x78, 0x6e, 0x40, 0x48, 0xc6, 0x8f, 0xa0, 0xfe, 0x8c, 0xbb, 0x3d, + 0xce, 0x87, 0x26, 0xff, 0x7c, 0xca, 0x83, 0x90, 0xbd, 0x07, 0x8b, 0x36, 0xff, 0x31, 0xe7, 0x43, + 0x6b, 0x62, 0x07, 0xc1, 0xe4, 0xcc, 0xb7, 0x03, 0xde, 0xca, 0xdc, 0xcd, 0xdc, 0xaf, 0x9a, 0x4d, + 0x2a, 0x38, 0x8c, 0xe0, 0xec, 0x2d, 0xa8, 0x06, 0x02, 0x95, 0xbb, 0xa1, 0xef, 0x4d, 0xae, 0x5a, + 0x59, 0xc4, 0xab, 0x08, 0x58, 0x87, 0x40, 0xc6, 0x08, 0x1a, 0x51, 0x0f, 0xc1, 0xc4, 0x73, 0x03, + 0xce, 0x1e, 0xc3, 0xf2, 0xc0, 0x99, 0x9c, 0x71, 0xdf, 0xc2, 0xca, 0x63, 0x97, 0x8f, 0x3d, 0xd7, + 0x19, 0xb4, 0x32, 0x77, 0x73, 0xf7, 0xcb, 0x26, 0xa3, 0x32, 0x51, 0x63, 0x4f, 0x96, 0xb0, 0x7b, + 0xd0, 0xe0, 0x2e, 0xc1, 0xf9, 0x10, 0x6b, 0xc9, 0xae, 0xea, 0x31, 0x58, 0x54, 0x30, 0xfe, 0x7e, + 0x16, 0x16, 0xbb, 0xae, 0x13, 0x7e, 0x6a, 0x8f, 0x46, 0x3c, 0x54, 0x73, 0xba, 0x07, 0x8d, 0x0b, + 0x04, 0xe0, 0x9c, 0x2e, 0x3c, 0x7f, 0x28, 0x67, 0x54, 0x27, 0xf0, 0xa1, 0x84, 0x5e, 0x3b, 0xb2, + 0xec, 0xb5, 0x23, 0x4b, 0x5d, 0xae, 0xdc, 0x35, 0xcb, 0x75, 0x0f, 0x1a, 0x3e, 0x1f, 0x78, 0xe7, + 0xdc, 0xbf, 0xb2, 0x2e, 0x1c, 0x77, 0xe8, 0x5d, 0xb4, 0xf2, 0x77, 0x33, 0xf7, 0x0b, 0x66, 0x5d, + 0x81, 0x3f, 0x45, 0x28, 0xdb, 0x80, 0xc6, 0xe0, 0xcc, 0x76, 0x5d, 0x3e, 0xb2, 0x8e, 0xed, 0xc1, + 0x8b, 0xe9, 0x24, 0x68, 0x15, 0xee, 0x66, 0xee, 0x57, 0x9e, 0xdc, 0x7c, 0x88, 0xbb, 0xfa, 0x70, + 0xf3, 0xcc, 0x76, 0x37, 0xb0, 0xa4, 0xe7, 0xda, 0x93, 0xe0, 0xcc, 0x0b, 0xcd, 0xba, 0xac, 0x41, + 0xe0, 0xc0, 0x58, 0x06, 0xa6, 0xaf, 0x04, 0xad, 0xbd, 0xf1, 0x9f, 0x32, 0xb0, 0x74, 0xe4, 0x8e, + 0xbc, 0xc1, 0x8b, 0x9f, 0x73, 0x89, 0x52, 0xe6, 0x90, 0x7d, 0xdd, 0x39, 0xe4, 0xbe, 0xec, 0x1c, + 0x56, 0x61, 0x39, 0x39, 0x58, 0x39, 0x0b, 0x0e, 0x2b, 0xa2, 0xf6, 0x29, 0x57, 0xc3, 0x52, 0xd3, + 0xf8, 0x3a, 0x34, 0x07, 0x53, 0xdf, 0xe7, 0xee, 0xdc, 0x3c, 0x1a, 0x12, 0x1e, 0x4d, 0xe4, 0x2d, + 0xa8, 0xba, 0xfc, 0x22, 0x46, 0x93, 0xb4, 0xeb, 0xf2, 0x0b, 0x85, 0x62, 0xb4, 0x60, 0x75, 0xb6, + 0x1b, 0x39, 0x80, 0x9f, 0x65, 0x20, 0x7f, 0x14, 0x5e, 0x7a, 0xec, 0x29, 0x54, 0xed, 0xe1, 0xd0, + 0xe7, 0x41, 0x60, 0x85, 0x57, 0x13, 0x3a, 0x29, 0xf5, 0x27, 0x4c, 0x4e, 0xb1, 0x4d, 0x45, 0xfd, + 0xab, 0x09, 0x37, 0x2b, 0x76, 0xfc, 0xc1, 0x5a, 0x50, 0x94, 0x9f, 0xd8, 0x6f, 0xd9, 0x54, 0x9f, + 0xec, 0x36, 0x80, 0x3d, 0xf6, 0xa6, 0x6e, 0x68, 0x05, 0x76, 0x88, 0x2b, 0x96, 0x33, 0xcb, 0x04, + 0xe9, 0xd9, 0x21, 0xbb, 0x05, 0xe5, 0xc9, 0x0b, 0x2b, 0x18, 0xf8, 0xce, 0x24, 0x44, 0xe2, 0x29, + 0x9b, 0xa5, 0xc9, 0x8b, 0x1e, 0x7e, 0xb3, 0xf7, 0xa0, 0xe4, 0x4d, 0xc3, 0x89, 0xe7, 0xb8, 0xa1, + 0xa4, 0x97, 0x86, 0x1c, 0xc8, 0xc1, 0x34, 0x3c, 0x14, 0x60, 0x33, 0x42, 0x60, 0xef, 0x40, 0x6d, + 0xe0, 0xb9, 0x27, 0x8e, 0x3f, 0x26, 0x8e, 0xd0, 0x5a, 0xc0, 0xbe, 0x92, 0x40, 0xe3, 0x0f, 0xb2, + 0x50, 0xe9, 0xfb, 0xb6, 0x1b, 0xd8, 0x03, 0x01, 0x60, 0x6b, 0x50, 0x0c, 0x2f, 0xad, 0x33, 0x3b, + 0x38, 0xc3, 0xa9, 0x96, 0xcd, 0x85, 0xf0, 0x72, 0xc7, 0x0e, 0xce, 0xd8, 0x2a, 0x2c, 0xd0, 0x28, + 0x71, 0x42, 0x39, 0x53, 0x7e, 0x89, 0x03, 0xe2, 0x4e, 0xc7, 0x56, 0xb2, 0xab, 0x1c, 0x52, 0x4c, + 0xd3, 0x9d, 0x8e, 0x37, 0x75, 0xb8, 0x98, 0xfc, 0xb1, 0xd8, 0x6e, 0xea, 0x80, 0xa6, 0x57, 0x46, + 0x08, 0xf6, 0xf1, 0x16, 0x54, 0x65, 0x31, 0x77, 0x4e, 0xcf, 0x68, 0x8e, 0x05, 0xb3, 0x42, 0x08, + 0x08, 0x12, 0x2d, 0x84, 0xce, 0x98, 0x5b, 0x41, 0x68, 0x8f, 0x27, 0x72, 0x4a, 0x65, 0x01, 0xe9, + 0x09, 0x00, 0x16, 0x7b, 0xa1, 0x3d, 0xb2, 0x4e, 0x38, 0x0f, 0x5a, 0x45, 0x59, 0x2c, 0x20, 0xdb, + 0x9c, 0x07, 0xec, 0x6b, 0x50, 0x1f, 0xf2, 0x20, 0xb4, 0xe4, 0x66, 0xf0, 0xa0, 0x55, 0xc2, 0x93, + 0x5f, 0x13, 0xd0, 0xb6, 0x02, 0xb2, 0x37, 0x00, 0x7c, 0xfb, 0xc2, 0x12, 0x0b, 0xc1, 0x2f, 0x5b, + 0x65, 0xda, 0x05, 0xdf, 0xbe, 0xe8, 0x5f, 0xee, 0xf0, 0x4b, 0x41, 0x35, 0xcf, 0x78, 0xa8, 0x2d, + 0x5a, 0x20, 0xa9, 0xd3, 0xd8, 0x05, 0xa6, 0x81, 0xb7, 0x78, 0x68, 0x3b, 0xa3, 0x80, 0x7d, 0x00, + 0xd5, 0x50, 0x43, 0x46, 0x36, 0x58, 0x89, 0x48, 0x48, 0xab, 0x60, 0x26, 0xf0, 0x8c, 0x33, 0x28, + 0x6d, 0x73, 0xbe, 0xeb, 0x8c, 0x9d, 0x90, 0xad, 0x42, 0xe1, 0xc4, 0xb9, 0xe4, 0x44, 0xec, 0xb9, + 0x9d, 0x1b, 0x26, 0x7d, 0xb2, 0x3b, 0x00, 0xf8, 0x87, 0x35, 0x8e, 0xa8, 0x69, 0xe7, 0x86, 0x59, + 0x46, 0xd8, 0x5e, 0x60, 0x87, 0x6c, 0x1d, 0x8a, 0x13, 0xee, 0x0f, 0xb8, 0xda, 0xb7, 0x9d, 0x1b, + 0xa6, 0x02, 0x6c, 0x14, 0xa1, 0x30, 0x12, 0xad, 0x1b, 0x7f, 0x54, 0x80, 0x4a, 0x8f, 0xbb, 0xd1, + 0x29, 0x63, 0x90, 0x17, 0x0b, 0x22, 0x4f, 0x16, 0xfe, 0xcd, 0xde, 0x86, 0x0a, 0x2e, 0x5d, 0x10, + 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x91, 0x6d, 0x65, 0x4c, 0x10, 0xe0, 0x1e, 0x42, 0x59, 0x13, + 0x72, 0xf6, 0x58, 0x51, 0xb5, 0xf8, 0x93, 0xdd, 0x84, 0x92, 0x3d, 0x0e, 0x69, 0x78, 0x55, 0x04, + 0x17, 0xed, 0x71, 0x88, 0x43, 0x7b, 0x0b, 0xaa, 0x13, 0xfb, 0x6a, 0x2c, 0xce, 0x72, 0x44, 0x0e, + 0x55, 0xb3, 0x22, 0x61, 0x48, 0x10, 0x4f, 0x60, 0x49, 0x47, 0x51, 0x9d, 0x17, 0xa2, 0xce, 0x17, + 0x35, 0x6c, 0x39, 0x86, 0x7b, 0xd0, 0x50, 0x75, 0x7c, 0x9a, 0x0f, 0x92, 0x49, 0xd9, 0xac, 0x4b, + 0xb0, 0x9a, 0xe5, 0x7d, 0x68, 0x9e, 0x38, 0xae, 0x3d, 0xb2, 0x06, 0xa3, 0xf0, 0xdc, 0x1a, 0xf2, + 0x51, 0x68, 0x23, 0xc5, 0x14, 0xcc, 0x3a, 0xc2, 0x37, 0x47, 0xe1, 0xf9, 0x96, 0x80, 0xb2, 0x6f, + 0x40, 0xf9, 0x84, 0x73, 0x0b, 0x17, 0xab, 0x55, 0x4a, 0x1c, 0x3c, 0xb5, 0x43, 0x66, 0xe9, 0x44, + 0xed, 0xd5, 0x37, 0xa0, 0xe9, 0x4d, 0xc3, 0x53, 0xcf, 0x71, 0x4f, 0x2d, 0xc1, 0xef, 0x2c, 0x67, + 0x88, 0x34, 0x94, 0xdf, 0xc8, 0x3e, 0xce, 0x98, 0x75, 0x55, 0x26, 0x38, 0x4f, 0x77, 0xc8, 0xde, + 0x85, 0xc6, 0xc8, 0x0e, 0x42, 0xeb, 0xcc, 0x9b, 0x58, 0x93, 0xe9, 0xf1, 0x0b, 0x7e, 0xd5, 0xaa, + 0xe1, 0x42, 0xd4, 0x04, 0x78, 0xc7, 0x9b, 0x1c, 0x22, 0x50, 0x50, 0x36, 0x8e, 0x93, 0x06, 0x01, + 0x77, 0x33, 0xf7, 0x6b, 0x66, 0x59, 0x40, 0xa8, 0xd3, 0xcf, 0x60, 0x09, 0xb7, 0x67, 0x30, 0x0d, + 0x42, 0x6f, 0x6c, 0x09, 0x5e, 0xed, 0x0f, 0x83, 0x56, 0x05, 0x69, 0xed, 0xeb, 0x72, 0xb0, 0xda, + 0x1e, 0x3f, 0xdc, 0xe2, 0x41, 0xb8, 0x89, 0xc8, 0x26, 0xe1, 0x8a, 0x0b, 0xfd, 0xca, 0x5c, 0x1c, + 0xce, 0xc2, 0xd9, 0x37, 0x80, 0xd9, 0xa3, 0x91, 0x77, 0x61, 0x05, 0x7c, 0x74, 0x62, 0xc9, 0x45, + 0x6c, 0xd5, 0xef, 0x66, 0xee, 0x97, 0xcc, 0x26, 0x96, 0xf4, 0xf8, 0xe8, 0xe4, 0x90, 0xe0, 0xec, + 0x03, 0xc0, 0xc3, 0x64, 0x9d, 0x70, 0x3b, 0x9c, 0xfa, 0x3c, 0x68, 0x35, 0xee, 0xe6, 0xee, 0xd7, + 0x9f, 0x2c, 0x46, 0xeb, 0x85, 0xe0, 0x0d, 0x27, 0x34, 0xab, 0x02, 0x4f, 0x7e, 0x07, 0xeb, 0x5b, + 0xb0, 0x9a, 0x3e, 0x24, 0x41, 0x54, 0x62, 0x55, 0x04, 0x31, 0xe6, 0x4d, 0xf1, 0x27, 0x5b, 0x86, + 0xc2, 0xb9, 0x3d, 0x9a, 0x72, 0xc9, 0xd3, 0xe9, 0xe3, 0xc3, 0xec, 0x77, 0x33, 0xc6, 0x1f, 0x66, + 0xa0, 0x4a, 0xb3, 0x94, 0xb2, 0xc8, 0xdb, 0x50, 0x53, 0xd4, 0xc0, 0x7d, 0xdf, 0xf3, 0x25, 0x57, + 0x53, 0x94, 0xd7, 0x11, 0x30, 0x71, 0xab, 0x28, 0xa4, 0x89, 0xcf, 0x9d, 0xb1, 0x7d, 0xaa, 0x9a, + 0x56, 0xa4, 0x74, 0x28, 0xc1, 0xec, 0xfd, 0xb8, 0x3d, 0xdf, 0x9b, 0x86, 0x5c, 0xde, 0x79, 0x55, + 0x39, 0x3d, 0x53, 0xc0, 0xa2, 0xd6, 0xf1, 0xeb, 0x35, 0xe8, 0xdc, 0xf8, 0x9d, 0x0c, 0x30, 0x31, + 0xec, 0xbe, 0x47, 0x0d, 0x48, 0x0a, 0x9d, 0xad, 0x99, 0x79, 0xed, 0x13, 0x92, 0x7d, 0xd9, 0x09, + 0x31, 0xa0, 0x40, 0x63, 0xcf, 0xa7, 0x8c, 0x9d, 0x8a, 0x7e, 0x90, 0x2f, 0xe5, 0x9a, 0x79, 0xe3, + 0x7f, 0xe5, 0x60, 0x79, 0x93, 0xae, 0xec, 0xf6, 0x60, 0xc0, 0x27, 0xd1, 0xd9, 0xb9, 0x03, 0x15, + 0xd7, 0x1b, 0x72, 0x45, 0xb1, 0x34, 0x30, 0x10, 0x20, 0x8d, 0x5c, 0xcf, 0x6c, 0xc7, 0xa5, 0x81, + 0xd3, 0x62, 0x96, 0x11, 0x82, 0xc3, 0x7e, 0x17, 0x1a, 0x13, 0xee, 0x0e, 0xf5, 0x23, 0x42, 0x42, + 0x55, 0x4d, 0x82, 0xe5, 0xe9, 0xb8, 0x03, 0x95, 0x93, 0x29, 0xe1, 0x09, 0xc6, 0x92, 0x47, 0x1a, + 0x00, 0x09, 0x6a, 0x13, 0x7f, 0x99, 0x4c, 0x83, 0x33, 0x2c, 0x2d, 0x60, 0x69, 0x51, 0x7c, 0x8b, + 0xa2, 0xdb, 0x00, 0xc3, 0x69, 0x10, 0xca, 0x13, 0xb3, 0x80, 0x85, 0x65, 0x01, 0xa1, 0x13, 0xf3, + 0x4d, 0x58, 0x1a, 0xdb, 0x97, 0x16, 0xd2, 0x8e, 0xe5, 0xb8, 0xd6, 0xc9, 0x08, 0xef, 0x9c, 0x22, + 0xe2, 0x35, 0xc7, 0xf6, 0xe5, 0x27, 0xa2, 0xa4, 0xeb, 0x6e, 0x23, 0x5c, 0xb0, 0x15, 0x25, 0xee, + 0xf8, 0x3c, 0xe0, 0xfe, 0x39, 0x47, 0x4e, 0x90, 0x8f, 0x64, 0x1a, 0x93, 0xa0, 0x62, 0x44, 0x63, + 0x31, 0xef, 0x70, 0x34, 0xa0, 0x63, 0x6f, 0x16, 0xc7, 0x8e, 0xbb, 0x13, 0x8e, 0x06, 0xe2, 0x5e, + 0x11, 0x7c, 0x64, 0xc2, 0x7d, 0xeb, 0xc5, 0x05, 0x9e, 0xe1, 0x3c, 0xf2, 0x8d, 0x43, 0xee, 0x3f, + 0xbf, 0x10, 0x57, 0xff, 0x20, 0x40, 0x46, 0x64, 0x5f, 0xb5, 0x2a, 0x78, 0xc0, 0x4b, 0x83, 0x40, + 0xb0, 0x20, 0xfb, 0x4a, 0x1c, 0x42, 0x31, 0x5a, 0x1b, 0x77, 0x81, 0x0f, 0xb1, 0xf9, 0x00, 0x39, + 0x6a, 0x0d, 0x07, 0xdb, 0x96, 0x05, 0xa2, 0x9f, 0x40, 0x50, 0xbd, 0x1a, 0xec, 0xc9, 0xc8, 0x3e, + 0x0d, 0x90, 0xa5, 0xd4, 0xcc, 0xaa, 0x04, 0x6e, 0x0b, 0x98, 0xf1, 0x29, 0x09, 0x59, 0xda, 0xde, + 0xca, 0x33, 0x23, 0xae, 0x7a, 0x84, 0xe0, 0xbe, 0x96, 0x4c, 0xf9, 0x95, 0xb6, 0x69, 0xd9, 0x94, + 0x4d, 0x33, 0x7e, 0x2f, 0x03, 0x55, 0xd9, 0x32, 0x0a, 0x25, 0xec, 0x21, 0x30, 0xb5, 0x8b, 0xe1, + 0xa5, 0x33, 0xb4, 0x8e, 0xaf, 0x42, 0x1e, 0x10, 0xd1, 0xec, 0xdc, 0x30, 0x9b, 0xb2, 0xac, 0x7f, + 0xe9, 0x0c, 0x37, 0x44, 0x09, 0x7b, 0x00, 0xcd, 0x04, 0x7e, 0x10, 0xfa, 0x44, 0xd1, 0x3b, 0x37, + 0xcc, 0xba, 0x86, 0xdd, 0x0b, 0x7d, 0x71, 0x46, 0x84, 0xc8, 0x33, 0x0d, 0x2d, 0xc7, 0x1d, 0xf2, + 0x4b, 0x24, 0xa3, 0x9a, 0x59, 0x21, 0x58, 0x57, 0x80, 0x36, 0xea, 0x50, 0xd5, 0x9b, 0x33, 0x4e, + 0xa1, 0xa4, 0xe4, 0x25, 0x14, 0x18, 0x66, 0x86, 0x64, 0x96, 0xc3, 0x68, 0x24, 0x37, 0xa1, 0x94, + 0x1c, 0x81, 0x59, 0x0c, 0x5f, 0xbb, 0x63, 0xe3, 0x7b, 0xd0, 0xdc, 0x15, 0xc4, 0xe3, 0x0a, 0x62, + 0x95, 0xf2, 0xdf, 0x2a, 0x2c, 0x68, 0x87, 0xa6, 0x6c, 0xca, 0x2f, 0x71, 0xe7, 0x9e, 0x79, 0x41, + 0x28, 0x7b, 0xc1, 0xbf, 0x8d, 0x3f, 0xca, 0x00, 0xeb, 0x04, 0xa1, 0x33, 0xb6, 0x43, 0xbe, 0xcd, + 0x23, 0xb6, 0x70, 0x00, 0x55, 0xd1, 0x5a, 0xdf, 0x6b, 0x93, 0x40, 0x46, 0x02, 0xc5, 0x7b, 0xf2, + 0x18, 0xcf, 0x57, 0x78, 0xa8, 0x63, 0x13, 0x9b, 0x4f, 0x34, 0x20, 0x4e, 0x59, 0x68, 0xfb, 0xa7, + 0x3c, 0x44, 0x31, 0x4e, 0xca, 0xfb, 0x40, 0x20, 0x21, 0xc0, 0xad, 0xff, 0x2a, 0x2c, 0xce, 0xb5, + 0xa1, 0xf3, 0xe5, 0x72, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, 0x82, 0xa5, 0xc4, 0xb8, 0x24, 0xa5, + 0xad, 0x41, 0x51, 0x1c, 0x08, 0x21, 0x1c, 0x64, 0x48, 0xaa, 0x3c, 0xe1, 0x5c, 0x88, 0xc1, 0x8f, + 0x60, 0xf9, 0x84, 0x73, 0xdf, 0x0e, 0xb1, 0x10, 0x4f, 0x8c, 0xd8, 0x21, 0xd9, 0xf0, 0xa2, 0x2c, + 0xeb, 0xd9, 0xe1, 0x21, 0xf7, 0xc5, 0x4e, 0x19, 0xff, 0x3b, 0x03, 0x0d, 0xc1, 0x41, 0xf7, 0x6c, + 0xf7, 0x4a, 0xad, 0xd3, 0x6e, 0xea, 0x3a, 0xdd, 0xd7, 0x2e, 0x43, 0x0d, 0xfb, 0xcb, 0x2e, 0x52, + 0x6e, 0x76, 0x91, 0xd8, 0x5d, 0xa8, 0x26, 0xc6, 0x5a, 0xc0, 0xb1, 0x42, 0x10, 0x0d, 0xf2, 0x17, + 0x5f, 0xc6, 0x77, 0xa1, 0x19, 0x0f, 0x5b, 0xae, 0x21, 0x83, 0xbc, 0x20, 0x49, 0xd9, 0x00, 0xfe, + 0x6d, 0xfc, 0xab, 0x0c, 0x21, 0x6e, 0x7a, 0x4e, 0x24, 0x9d, 0x0a, 0x44, 0x21, 0xf7, 0x2a, 0x44, + 0xf1, 0xf7, 0xb5, 0x52, 0xfd, 0x2f, 0x3e, 0x59, 0x71, 0x74, 0x02, 0xee, 0x0e, 0x2d, 0x7b, 0x34, + 0x42, 0xe6, 0x5b, 0x32, 0x8b, 0xe2, 0xbb, 0x3d, 0x1a, 0x19, 0xf7, 0x60, 0x51, 0x1b, 0xdd, 0x4b, + 0xe6, 0xb1, 0x0f, 0x6c, 0xd7, 0x09, 0xc2, 0x23, 0x37, 0x98, 0x68, 0x82, 0xdb, 0x2d, 0x28, 0x0b, + 0x0e, 0x2b, 0x46, 0x46, 0x47, 0xb6, 0x60, 0x0a, 0x96, 0x2b, 0xc6, 0x15, 0x60, 0xa1, 0x7d, 0x29, + 0x0b, 0xb3, 0xb2, 0xd0, 0xbe, 0xc4, 0x42, 0xe3, 0xbb, 0xb0, 0x94, 0x68, 0x4f, 0x76, 0xfd, 0x16, + 0x14, 0xa6, 0xe1, 0xa5, 0xa7, 0x44, 0xf3, 0x8a, 0xa4, 0x10, 0xa1, 0x00, 0x9a, 0x54, 0x62, 0x7c, + 0x04, 0x8b, 0xfb, 0xfc, 0x42, 0x1e, 0x62, 0x35, 0x90, 0x77, 0x21, 0xff, 0x0a, 0xa5, 0x10, 0xcb, + 0x8d, 0x87, 0xc0, 0xf4, 0xca, 0xb2, 0x57, 0x4d, 0x47, 0xcc, 0x24, 0x74, 0x44, 0xe3, 0x5d, 0x60, + 0x3d, 0xe7, 0xd4, 0xdd, 0xe3, 0x41, 0x60, 0x9f, 0x46, 0xc7, 0xbe, 0x09, 0xb9, 0x71, 0x70, 0x2a, + 0x79, 0x94, 0xf8, 0xd3, 0xf8, 0x16, 0x2c, 0x25, 0xf0, 0x64, 0xc3, 0x6f, 0x40, 0x39, 0x70, 0x4e, + 0x5d, 0x14, 0xac, 0x64, 0xd3, 0x31, 0xc0, 0xd8, 0x86, 0xe5, 0x4f, 0xb8, 0xef, 0x9c, 0x5c, 0xbd, + 0xaa, 0xf9, 0x64, 0x3b, 0xd9, 0xd9, 0x76, 0x3a, 0xb0, 0x32, 0xd3, 0x8e, 0xec, 0x9e, 0xc8, 0x57, + 0xee, 0x64, 0xc9, 0xa4, 0x0f, 0x8d, 0xef, 0x65, 0x75, 0xbe, 0x67, 0x1c, 0x01, 0xdb, 0xf4, 0x5c, + 0x97, 0x0f, 0xc2, 0x43, 0xce, 0xfd, 0xd8, 0x4a, 0x15, 0xd3, 0x6a, 0xe5, 0xc9, 0x9a, 0x5c, 0xd9, + 0x59, 0x66, 0x2a, 0x89, 0x98, 0x41, 0x7e, 0xc2, 0xfd, 0x31, 0x36, 0x5c, 0x32, 0xf1, 0x6f, 0x63, + 0x05, 0x96, 0x12, 0xcd, 0x4a, 0xbd, 0xfe, 0x31, 0xac, 0x6c, 0x39, 0xc1, 0x60, 0xbe, 0xc3, 0x35, + 0x28, 0x4e, 0xa6, 0xc7, 0x56, 0x92, 0x2f, 0x3f, 0xe7, 0x57, 0x42, 0xdb, 0x9b, 0xad, 0x21, 0xdb, + 0xfa, 0xbb, 0x19, 0xc8, 0xef, 0xf4, 0x77, 0x37, 0xd9, 0x3a, 0x94, 0x1c, 0x77, 0xe0, 0x8d, 0x85, + 0xe0, 0x45, 0x73, 0x8e, 0xbe, 0xaf, 0x3d, 0x60, 0xb7, 0xa0, 0x8c, 0xf2, 0x9a, 0x50, 0x6d, 0xa5, + 0xe8, 0x53, 0x12, 0x80, 0x5d, 0x6f, 0xf0, 0x42, 0xe8, 0xd4, 0xfc, 0x72, 0xe2, 0xf8, 0xa8, 0x35, + 0x2b, 0x65, 0x38, 0x4f, 0x77, 0x7d, 0x5c, 0x40, 0x1a, 0xb1, 0xf1, 0x57, 0x45, 0x28, 0xca, 0xdb, + 0x96, 0x6e, 0xee, 0xd0, 0x39, 0xe7, 0xf1, 0xcd, 0x2d, 0xbe, 0x84, 0x3c, 0xe0, 0xf3, 0xb1, 0x17, + 0x46, 0x02, 0x1b, 0xed, 0x41, 0x95, 0x80, 0x52, 0x64, 0xd3, 0x84, 0x06, 0x32, 0x31, 0xe4, 0x08, + 0x69, 0xa0, 0x5f, 0xe5, 0xb7, 0xa0, 0xa8, 0xee, 0xfe, 0x7c, 0xa4, 0xd3, 0x2c, 0x0c, 0x48, 0x5a, + 0x5b, 0x87, 0xd2, 0xc0, 0x9e, 0xd8, 0x03, 0x27, 0xbc, 0x92, 0x0c, 0x21, 0xfa, 0x16, 0xad, 0x8f, + 0xbc, 0x81, 0x3d, 0xb2, 0x8e, 0xed, 0x91, 0xed, 0x0e, 0xb8, 0xd4, 0xdd, 0xab, 0x08, 0xdc, 0x20, + 0x98, 0xd0, 0xcf, 0xe5, 0x38, 0x15, 0x16, 0xa9, 0xf0, 0x72, 0xf4, 0x0a, 0x4d, 0x08, 0x97, 0xde, + 0x78, 0xec, 0x08, 0x2d, 0x83, 0xc4, 0xb0, 0x9c, 0x59, 0x26, 0xc8, 0x36, 0xc7, 0xd9, 0xca, 0xe2, + 0x0b, 0x5a, 0xba, 0x32, 0x75, 0x45, 0xc0, 0x4f, 0xc9, 0x90, 0x30, 0x2f, 0x8b, 0xe5, 0x34, 0x59, + 0xec, 0x3d, 0x58, 0x9c, 0xba, 0x01, 0x0f, 0xc3, 0x11, 0x1f, 0x46, 0x63, 0xa9, 0x20, 0x52, 0x33, + 0x2a, 0x50, 0xc3, 0x79, 0x08, 0x4b, 0x64, 0x74, 0x08, 0xec, 0xd0, 0x0b, 0xce, 0x9c, 0xc0, 0x0a, + 0x84, 0x86, 0x44, 0xea, 0xee, 0x22, 0x16, 0xf5, 0x64, 0x49, 0x8f, 0x54, 0xa4, 0xb5, 0x19, 0x7c, + 0x9f, 0x0f, 0xb8, 0x73, 0xce, 0x87, 0x28, 0xa7, 0xe5, 0xcc, 0x95, 0x44, 0x1d, 0x53, 0x16, 0xa2, + 0xd0, 0x3d, 0x1d, 0x5b, 0xd3, 0xc9, 0xd0, 0x16, 0xc2, 0x4a, 0x9d, 0x84, 0x61, 0x77, 0x3a, 0x3e, + 0x22, 0x08, 0x7b, 0x0c, 0x4a, 0x12, 0x93, 0xf2, 0x61, 0x23, 0xc1, 0xcf, 0x04, 0xb1, 0x9a, 0x55, + 0x89, 0x41, 0x82, 0x62, 0x42, 0xe6, 0x6c, 0xce, 0xc8, 0x9c, 0x2d, 0x28, 0x4e, 0x7c, 0xe7, 0xdc, + 0x0e, 0x79, 0x6b, 0x91, 0x18, 0xb8, 0xfc, 0x14, 0x9c, 0xc1, 0x71, 0x9d, 0xd0, 0xb1, 0x43, 0xcf, + 0x6f, 0x31, 0x2c, 0x8b, 0x01, 0xec, 0x01, 0x2c, 0x22, 0x8d, 0x04, 0xa1, 0x1d, 0x4e, 0x03, 0x29, + 0x81, 0x2e, 0x21, 0x31, 0xa1, 0x0c, 0xdd, 0x43, 0x38, 0x0a, 0xa1, 0xec, 0x5b, 0xb0, 0x4a, 0x64, + 0x81, 0x35, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x32, 0x2e, 0xc5, 0x12, 0x96, 0x0a, 0xfa, 0x96, 0xf2, + 0xb5, 0x90, 0x0e, 0x9e, 0xc2, 0x9a, 0x24, 0x93, 0xb9, 0x5a, 0x2b, 0x58, 0x6b, 0x99, 0x8a, 0x67, + 0xaa, 0x3d, 0x84, 0x45, 0x31, 0x24, 0x67, 0x60, 0xc9, 0xda, 0xe2, 0x24, 0xac, 0x8a, 0xd1, 0xa3, + 0xa6, 0xd4, 0xa0, 0x42, 0x13, 0xcb, 0x9e, 0xf3, 0x2b, 0xf6, 0x3d, 0x68, 0x10, 0xc9, 0xa0, 0x7a, + 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, 0xa5, 0xc8, 0xec, 0xeb, 0x83, 0xc4, + 0xb7, 0x38, 0x0e, 0x23, 0xe7, 0x84, 0x87, 0xce, 0x98, 0xb7, 0xd6, 0x88, 0xc0, 0xd4, 0xb7, 0x38, + 0xa9, 0xd3, 0x09, 0x96, 0xb4, 0x88, 0x2f, 0xd0, 0x17, 0xd2, 0xee, 0xc8, 0x0b, 0xb8, 0x32, 0x51, + 0xb5, 0x6e, 0xca, 0x43, 0x28, 0x80, 0x92, 0xed, 0x19, 0x3f, 0xcd, 0xd0, 0x3d, 0x26, 0x8f, 0x7d, + 0xa0, 0x69, 0x65, 0x74, 0xe0, 0x2d, 0xcf, 0x1d, 0x5d, 0x49, 0x1e, 0x00, 0x04, 0x3a, 0x70, 0x47, + 0x78, 0x08, 0x1d, 0x57, 0x47, 0x21, 0x96, 0x59, 0x55, 0x40, 0x44, 0xba, 0x03, 0x95, 0xc9, 0xf4, + 0x78, 0xe4, 0x0c, 0x08, 0x25, 0x47, 0xad, 0x10, 0x08, 0x11, 0x84, 0x5a, 0x4a, 0x84, 0x40, 0x18, + 0x79, 0xc4, 0xa8, 0x48, 0x18, 0xa2, 0x20, 0x4b, 0xe6, 0x3e, 0x72, 0x81, 0xaa, 0x89, 0x7f, 0x1b, + 0x1b, 0xb0, 0x9c, 0x1c, 0xb4, 0xbc, 0x2f, 0x1e, 0x40, 0x49, 0xb2, 0x18, 0x65, 0xaf, 0xa8, 0x6b, + 0x16, 0x64, 0xa1, 0x59, 0x45, 0xe5, 0xc6, 0x6f, 0x2d, 0xc0, 0x92, 0x84, 0x6e, 0x8a, 0x15, 0xe9, + 0x4d, 0xc7, 0x63, 0xdb, 0x4f, 0xe1, 0x5d, 0x99, 0x97, 0xf3, 0xae, 0xec, 0x1c, 0xef, 0x4a, 0x2a, + 0xac, 0xc4, 0xfa, 0x92, 0x0a, 0xab, 0xd8, 0x02, 0xd2, 0x21, 0x74, 0xf3, 0x65, 0x4d, 0x82, 0xfb, + 0x64, 0x26, 0x9d, 0xe3, 0xb4, 0x85, 0x14, 0x4e, 0xab, 0xf3, 0xc9, 0x85, 0x19, 0x3e, 0xf9, 0x16, + 0xd0, 0x5e, 0x2b, 0xb6, 0x5f, 0x24, 0xb5, 0x02, 0x61, 0xd2, 0x06, 0x7a, 0x0f, 0x1a, 0xb3, 0xac, + 0x89, 0x78, 0x60, 0x3d, 0x85, 0x31, 0x39, 0x63, 0x8e, 0x97, 0x8c, 0x86, 0x5c, 0x96, 0x8c, 0xc9, + 0x19, 0xf3, 0x5d, 0x2c, 0x51, 0xf8, 0x1d, 0x00, 0xea, 0x1b, 0x69, 0x1d, 0x90, 0xd6, 0xdf, 0x4d, + 0xee, 0x85, 0xbe, 0xea, 0x0f, 0xc5, 0xc7, 0xd4, 0xe7, 0x48, 0xfc, 0x65, 0xac, 0x89, 0x74, 0xff, + 0x1c, 0xea, 0xde, 0x84, 0xbb, 0x56, 0xcc, 0x22, 0x2a, 0xd8, 0xd4, 0x3b, 0x2f, 0x69, 0xaa, 0xab, + 0x70, 0xcd, 0x9a, 0xa8, 0x1b, 0x7d, 0xb2, 0x3d, 0x5a, 0x78, 0xae, 0xb5, 0x56, 0xfd, 0x12, 0xad, + 0xd5, 0xb1, 0x72, 0xf4, 0x6d, 0xfc, 0x83, 0x0c, 0x54, 0xb4, 0x61, 0xb3, 0x15, 0x58, 0xdc, 0x3c, + 0x38, 0x38, 0xec, 0x98, 0xed, 0x7e, 0xf7, 0x93, 0x8e, 0xb5, 0xb9, 0x7b, 0xd0, 0xeb, 0x34, 0x6f, + 0x08, 0xf0, 0xee, 0xc1, 0x66, 0x7b, 0xd7, 0xda, 0x3e, 0x30, 0x37, 0x15, 0x38, 0xc3, 0x56, 0x81, + 0x99, 0x9d, 0xbd, 0x83, 0x7e, 0x27, 0x01, 0xcf, 0xb2, 0x26, 0x54, 0x37, 0xcc, 0x4e, 0x7b, 0x73, + 0x47, 0x42, 0x72, 0x6c, 0x19, 0x9a, 0xdb, 0x47, 0xfb, 0x5b, 0xdd, 0xfd, 0x67, 0xd6, 0x66, 0x7b, + 0x7f, 0xb3, 0xb3, 0xdb, 0xd9, 0x6a, 0xe6, 0x59, 0x0d, 0xca, 0xed, 0x8d, 0xf6, 0xfe, 0xd6, 0xc1, + 0x7e, 0x67, 0xab, 0x59, 0x30, 0x7e, 0x05, 0xca, 0xf1, 0x44, 0x2b, 0x50, 0x3c, 0xda, 0x7f, 0xbe, + 0x7f, 0xf0, 0xe9, 0x7e, 0xf3, 0x06, 0x2b, 0x43, 0x01, 0xfb, 0x6f, 0x66, 0x18, 0xc0, 0x02, 0xf5, + 0xd9, 0xcc, 0xb2, 0x12, 0xe4, 0x37, 0x0e, 0xfa, 0x3b, 0xcd, 0x9c, 0xf1, 0xe7, 0x19, 0x58, 0xc1, + 0x29, 0x0f, 0x67, 0x99, 0xc0, 0x5d, 0xa8, 0x0c, 0x3c, 0x6f, 0x22, 0x14, 0xa4, 0x58, 0x10, 0xd0, + 0x41, 0xe2, 0x80, 0x13, 0xcf, 0x3d, 0xf1, 0xfc, 0x01, 0x97, 0x3c, 0x00, 0x10, 0xb4, 0x2d, 0x20, + 0x82, 0x06, 0x25, 0x11, 0x13, 0x06, 0xb1, 0x80, 0x0a, 0xc1, 0x08, 0x65, 0x15, 0x16, 0x8e, 0x7d, + 0x6e, 0x0f, 0xce, 0xe4, 0xe9, 0x97, 0x5f, 0xec, 0xeb, 0xb1, 0xea, 0x3e, 0x10, 0x34, 0x35, 0xe2, + 0x43, 0x3c, 0x02, 0x25, 0xb3, 0x21, 0xe1, 0x9b, 0x12, 0x2c, 0x2e, 0x11, 0xfb, 0xd8, 0x76, 0x87, + 0x9e, 0xcb, 0x87, 0x52, 0x43, 0x88, 0x01, 0xc6, 0x21, 0xac, 0xce, 0xce, 0x4f, 0xf2, 0x8b, 0x0f, + 0x34, 0x7e, 0x41, 0x02, 0xfb, 0xfa, 0xf5, 0xa4, 0xa0, 0xf1, 0x8e, 0x7f, 0x9c, 0x87, 0xbc, 0x10, + 0xe0, 0xae, 0x95, 0xf5, 0x74, 0x89, 0x3c, 0x37, 0xe7, 0xb5, 0x41, 0x0b, 0x01, 0xdd, 0xec, 0x64, + 0x86, 0x2a, 0x23, 0x04, 0x6f, 0xf4, 0xa8, 0xd8, 0xe7, 0x83, 0x73, 0x69, 0x87, 0xa2, 0x62, 0x93, + 0x0f, 0xce, 0x51, 0x15, 0xb2, 0x43, 0xaa, 0x4b, 0xe7, 0xbd, 0x18, 0xd8, 0x21, 0xd6, 0x94, 0x45, + 0x58, 0xaf, 0x18, 0x15, 0x61, 0xad, 0x16, 0x14, 0x1d, 0xf7, 0xd8, 0x9b, 0xba, 0x43, 0x3c, 0xde, + 0x25, 0x53, 0x7d, 0xa2, 0x93, 0x08, 0x39, 0x91, 0xb8, 0x3f, 0xe8, 0x34, 0x97, 0x04, 0xa0, 0x2f, + 0x6e, 0x90, 0xf7, 0xa1, 0x1c, 0x5c, 0xb9, 0x03, 0xfd, 0x0c, 0x2f, 0xcb, 0xf5, 0x11, 0xb3, 0x7f, + 0xd8, 0xbb, 0x72, 0x07, 0x78, 0x62, 0x4b, 0x81, 0xfc, 0x8b, 0x3d, 0x85, 0x52, 0x64, 0xae, 0x25, + 0x0e, 0x7c, 0x53, 0xaf, 0xa1, 0x6c, 0xb4, 0xa4, 0x15, 0x47, 0xa8, 0xec, 0x11, 0x2c, 0xa0, 0x4d, + 0x35, 0x68, 0x55, 0xb1, 0x92, 0x12, 0xd3, 0xc5, 0x30, 0xd0, 0x3f, 0xc3, 0x87, 0x68, 0x5f, 0x35, + 0x25, 0xda, 0xfa, 0x73, 0xa8, 0x25, 0xda, 0xd2, 0x75, 0xdf, 0x1a, 0xe9, 0xbe, 0xef, 0xe8, 0xba, + 0x6f, 0x7c, 0x13, 0xc8, 0x6a, 0xba, 0x2e, 0xfc, 0xab, 0x50, 0x52, 0x53, 0x11, 0xe7, 0x4f, 0x9e, + 0x1d, 0xab, 0xf7, 0xd9, 0xfe, 0x66, 0xf3, 0x06, 0x6b, 0x40, 0xa5, 0xbd, 0x89, 0x47, 0x1a, 0x01, + 0x19, 0x81, 0x72, 0xd8, 0xee, 0xf5, 0x22, 0x48, 0xd6, 0xd8, 0x86, 0xe6, 0xec, 0x48, 0x05, 0x4d, + 0x86, 0x0a, 0x26, 0x2d, 0xce, 0x31, 0x40, 0x68, 0x36, 0x64, 0x44, 0x26, 0xf1, 0x99, 0x3e, 0x8c, + 0xa7, 0xd0, 0x14, 0xf7, 0x9a, 0x58, 0xaa, 0x40, 0xb3, 0xdc, 0x8e, 0x84, 0x48, 0xa6, 0x5b, 0x9d, + 0x4b, 0x66, 0x85, 0x60, 0xd8, 0x95, 0xf1, 0x01, 0x2c, 0x6a, 0xd5, 0x62, 0x4d, 0x54, 0xdc, 0x95, + 0xb3, 0x9a, 0x28, 0xea, 0x1d, 0x54, 0x62, 0xac, 0xc1, 0x8a, 0xf8, 0xec, 0x9c, 0x73, 0x37, 0xec, + 0x4d, 0x8f, 0xc9, 0x55, 0xe8, 0x78, 0xae, 0xd0, 0x47, 0xca, 0x51, 0xc9, 0xf5, 0x44, 0xfe, 0x50, + 0x2a, 0xad, 0x59, 0x24, 0x8d, 0x75, 0xad, 0x07, 0xac, 0xf8, 0x10, 0xff, 0x4d, 0x28, 0xaf, 0xe5, + 0x08, 0x24, 0x96, 0xf5, 0xb0, 0xd3, 0x31, 0xad, 0x83, 0xfd, 0xdd, 0xee, 0xbe, 0x60, 0x94, 0x62, + 0x59, 0x11, 0xb0, 0xbd, 0x8d, 0x90, 0x8c, 0xd1, 0x84, 0xfa, 0x33, 0x1e, 0x76, 0xdd, 0x13, 0x4f, + 0xb9, 0xc5, 0x7e, 0x56, 0x80, 0x46, 0x04, 0x8a, 0x95, 0xdf, 0x73, 0xee, 0x07, 0x8e, 0xe7, 0xa2, + 0x1c, 0x5b, 0x36, 0xd5, 0xa7, 0xb8, 0xdd, 0x9c, 0x21, 0x77, 0x43, 0x27, 0xbc, 0xb2, 0x12, 0x96, + 0xb2, 0xba, 0x02, 0xcb, 0x5b, 0x74, 0x19, 0x0a, 0xf6, 0xc8, 0xb1, 0x95, 0x87, 0x95, 0x3e, 0x04, + 0x74, 0xe0, 0x8d, 0x3c, 0x1f, 0x45, 0xd6, 0xb2, 0x49, 0x1f, 0xec, 0x31, 0x2c, 0x0b, 0xd1, 0x59, + 0x37, 0x5f, 0x22, 0xff, 0x20, 0xa3, 0x1d, 0x73, 0xa7, 0xe3, 0xc3, 0xd8, 0x84, 0x29, 0x4a, 0xc4, + 0xdd, 0x29, 0x6a, 0x48, 0x61, 0x29, 0xaa, 0x40, 0x5a, 0xd8, 0xa2, 0x3b, 0x1d, 0xb7, 0xb1, 0x24, + 0xc2, 0x7f, 0x02, 0x2b, 0x02, 0x3f, 0x12, 0xaf, 0xa2, 0x1a, 0x0d, 0xac, 0x21, 0x1a, 0xeb, 0xca, + 0xb2, 0xa8, 0xce, 0x2d, 0x28, 0xd3, 0xa8, 0xc4, 0x8e, 0x17, 0x48, 0xfa, 0xc6, 0xa1, 0x70, 0x3f, + 0x98, 0x73, 0x86, 0x2e, 0x90, 0x20, 0x30, 0xe3, 0x0c, 0xd5, 0xdc, 0xa9, 0xa5, 0x59, 0x77, 0xea, + 0x13, 0x58, 0x39, 0x16, 0x24, 0x78, 0xc6, 0xed, 0x21, 0xf7, 0xad, 0x98, 0xb0, 0x49, 0xcb, 0x58, + 0x12, 0x85, 0x3b, 0x58, 0x16, 0x9d, 0x03, 0x21, 0xe7, 0x08, 0xb6, 0xc0, 0x87, 0x56, 0xe8, 0x59, + 0x28, 0xfe, 0x20, 0x83, 0x29, 0x99, 0x35, 0x02, 0xf7, 0xbd, 0x4d, 0x01, 0x4c, 0xe2, 0x9d, 0xfa, + 0xf6, 0xe4, 0x4c, 0xea, 0x01, 0x11, 0xde, 0x33, 0x01, 0x64, 0x6f, 0x40, 0x51, 0x90, 0xbc, 0xcb, + 0xc9, 0x67, 0x45, 0x92, 0xb6, 0x02, 0xb1, 0x77, 0x60, 0x01, 0xfb, 0x08, 0x5a, 0x4d, 0xa4, 0xf7, + 0x6a, 0xcc, 0xc8, 0x1d, 0xd7, 0x94, 0x65, 0x42, 0x98, 0x9c, 0xfa, 0x0e, 0x71, 0x99, 0xb2, 0x89, + 0x7f, 0xb3, 0xef, 0x6b, 0x2c, 0x6b, 0x09, 0xeb, 0x2a, 0x79, 0x60, 0x86, 0xd2, 0xae, 0xe3, 0x5e, + 0x5f, 0x29, 0x33, 0xfa, 0x41, 0xbe, 0x54, 0x69, 0x56, 0x8d, 0xef, 0x40, 0x81, 0x56, 0x47, 0x10, + 0x21, 0xae, 0x5d, 0x46, 0x12, 0x21, 0x42, 0x5b, 0x50, 0x74, 0x79, 0x78, 0xe1, 0xf9, 0x2f, 0x94, + 0x2d, 0x59, 0x7e, 0x1a, 0x3f, 0x46, 0x23, 0x48, 0xe4, 0x28, 0x27, 0x7d, 0x4e, 0x90, 0x07, 0x6d, + 0x6f, 0x70, 0x66, 0x4b, 0xbb, 0x4c, 0x09, 0x01, 0xbd, 0x33, 0x7b, 0x8e, 0x3c, 0xb2, 0xf3, 0xbe, + 0xf2, 0x77, 0xa0, 0xae, 0x5c, 0xf3, 0x81, 0x35, 0xe2, 0x27, 0xa1, 0x24, 0xf7, 0xaa, 0xf4, 0xcb, + 0x07, 0xbb, 0xfc, 0x24, 0x34, 0xf6, 0x60, 0x51, 0x12, 0xe4, 0xc1, 0x84, 0xab, 0xae, 0xbf, 0x9b, + 0x26, 0x4f, 0x57, 0x9e, 0x2c, 0x25, 0x2f, 0x5a, 0x7a, 0x72, 0x90, 0x10, 0xb2, 0x8d, 0x8f, 0x81, + 0xe9, 0xd7, 0xb0, 0x6c, 0x4f, 0x4a, 0xb5, 0xca, 0x04, 0xaf, 0x3c, 0x59, 0x91, 0xec, 0xec, 0x0c, + 0xc5, 0xea, 0x04, 0xd3, 0xc1, 0x40, 0x3d, 0x99, 0x28, 0x99, 0xea, 0xd3, 0xf8, 0x93, 0x0c, 0x2c, + 0x61, 0x63, 0x4a, 0x1f, 0x90, 0x4c, 0xf6, 0xe7, 0x1e, 0xa4, 0xd8, 0x1f, 0x5d, 0xf6, 0xa1, 0x8f, + 0x2f, 0x6f, 0xf4, 0xcc, 0xcf, 0x19, 0x3d, 0xbf, 0x0e, 0xcd, 0x21, 0x1f, 0x39, 0xf8, 0x7a, 0x46, + 0x89, 0x12, 0xa4, 0x01, 0x34, 0x14, 0x5c, 0x29, 0x71, 0xff, 0x3c, 0x03, 0x8b, 0x24, 0xa9, 0xa0, + 0x3a, 0x2c, 0x17, 0xea, 0x23, 0xa5, 0xff, 0x49, 0x56, 0x25, 0xe7, 0x14, 0xdf, 0xe0, 0x08, 0x25, + 0xe4, 0x9d, 0x1b, 0x52, 0x2f, 0x94, 0x50, 0xf6, 0x21, 0xea, 0x30, 0xae, 0x85, 0xc0, 0x94, 0xd7, + 0x38, 0xc9, 0x4d, 0xd9, 0xb9, 0x81, 0x0a, 0x8e, 0x8b, 0xa0, 0x8d, 0x92, 0x50, 0x48, 0x05, 0xd8, + 0xd8, 0x86, 0x5a, 0xa2, 0x9b, 0x84, 0x65, 0xb6, 0x4a, 0x96, 0xd9, 0x39, 0xef, 0x47, 0x76, 0xde, + 0xfb, 0xf1, 0xf7, 0xf2, 0xc0, 0x04, 0x49, 0xcd, 0xec, 0xda, 0x8c, 0xeb, 0x30, 0x3b, 0xe7, 0x3a, + 0x7c, 0x0c, 0x4c, 0x43, 0x50, 0x1e, 0xcd, 0x5c, 0xe4, 0xd1, 0x6c, 0xc6, 0xb8, 0xd2, 0xa1, 0xf9, + 0x18, 0x96, 0xa5, 0x40, 0x1b, 0xf9, 0x0a, 0xd1, 0xe4, 0x46, 0xfb, 0xc3, 0x48, 0xb2, 0x55, 0x3e, + 0x43, 0x34, 0xbf, 0x29, 0xb7, 0x61, 0x60, 0x87, 0xd2, 0x52, 0x85, 0x6e, 0xc3, 0x9e, 0x3d, 0x67, + 0xfa, 0x5e, 0x78, 0x25, 0x15, 0x14, 0xe7, 0xa8, 0x40, 0x33, 0x9c, 0x94, 0x92, 0x86, 0x13, 0x03, + 0x6a, 0xca, 0x39, 0x48, 0x6f, 0x22, 0x48, 0x7a, 0xab, 0x48, 0x0f, 0x21, 0xbe, 0x8b, 0xb8, 0x0f, + 0x4d, 0x65, 0xdd, 0x88, 0x4c, 0x33, 0xe4, 0xef, 0x97, 0xc6, 0xb1, 0x4d, 0x65, 0xa0, 0x49, 0x18, + 0xc2, 0x2b, 0x33, 0x86, 0xf0, 0xf7, 0x60, 0x31, 0x10, 0x44, 0x64, 0x4d, 0x5d, 0xf9, 0x38, 0x87, + 0x0f, 0x51, 0x75, 0x2a, 0x99, 0x4d, 0x2c, 0x38, 0x8a, 0xe1, 0xf3, 0x66, 0x87, 0xda, 0xbc, 0xd9, + 0x81, 0x3d, 0x8d, 0xfd, 0x68, 0xc1, 0x99, 0x33, 0xc6, 0x8b, 0x3b, 0x7e, 0xc8, 0x22, 0x17, 0xb8, + 0x77, 0xe6, 0x8c, 0x4d, 0xe5, 0xb4, 0x15, 0x1f, 0xc6, 0x7f, 0xcd, 0x40, 0x53, 0xd0, 0x41, 0x82, + 0xce, 0x7f, 0x05, 0xf0, 0x44, 0xbe, 0x26, 0x99, 0x57, 0x04, 0xae, 0xa2, 0xf2, 0xef, 0x00, 0x92, + 0xad, 0x25, 0xf4, 0x44, 0x49, 0xe4, 0xad, 0x24, 0x91, 0xc7, 0x8c, 0x6c, 0xe7, 0x06, 0x29, 0x00, + 0x02, 0x92, 0xe6, 0xbf, 0xcc, 0xa7, 0xf8, 0x2f, 0xb5, 0xa3, 0xb0, 0x03, 0xf0, 0x9c, 0x5f, 0xed, + 0x7a, 0x03, 0xd4, 0xd0, 0x6e, 0x03, 0x08, 0x82, 0x3c, 0xb1, 0xc7, 0x8e, 0xb4, 0xae, 0x14, 0xcc, + 0xf2, 0x0b, 0x7e, 0xb5, 0x8d, 0x00, 0xb1, 0x1b, 0xa2, 0x38, 0x3e, 0x0f, 0x05, 0xb3, 0xf4, 0x82, + 0x5f, 0xd1, 0x61, 0xb0, 0xa0, 0xf6, 0x9c, 0x5f, 0x6d, 0x71, 0x12, 0xd7, 0x3c, 0x5f, 0x50, 0x82, + 0x6f, 0x5f, 0x08, 0xf9, 0x2c, 0xe1, 0x7b, 0xac, 0xf8, 0xf6, 0xc5, 0x73, 0x7e, 0xa5, 0xfc, 0xa0, + 0x45, 0x51, 0x3e, 0xf2, 0x06, 0xf2, 0x06, 0x52, 0xaf, 0x28, 0xe2, 0x41, 0x99, 0x0b, 0x2f, 0xf0, + 0x6f, 0xe3, 0x8f, 0x33, 0x50, 0x13, 0xe3, 0x47, 0x06, 0x27, 0xd6, 0x5d, 0x3d, 0xc6, 0xc9, 0xc4, + 0x8f, 0x71, 0x9e, 0x48, 0xfe, 0x40, 0xdc, 0x32, 0x7b, 0x3d, 0xb7, 0xc4, 0x05, 0x26, 0x56, 0xf9, + 0x3e, 0x94, 0xe9, 0x6c, 0x89, 0xc3, 0x9a, 0x4b, 0xec, 0x52, 0x62, 0x42, 0x66, 0x09, 0xd1, 0x9e, + 0x93, 0xef, 0x5f, 0x33, 0xb0, 0xd1, 0x12, 0x97, 0xfd, 0xc8, 0xac, 0x96, 0xb2, 0x0d, 0x85, 0x34, + 0x37, 0xf2, 0x11, 0x54, 0x34, 0x9a, 0x42, 0x6b, 0x5c, 0x34, 0x78, 0x22, 0xc0, 0x24, 0xd1, 0x24, + 0x66, 0xbf, 0x73, 0xc3, 0xac, 0x0d, 0x74, 0xc0, 0xc6, 0x02, 0xe4, 0x45, 0x25, 0xe3, 0x23, 0x58, + 0xd4, 0x9a, 0x25, 0x6d, 0x34, 0x6d, 0x4c, 0x99, 0xb4, 0x31, 0xfd, 0x8b, 0x0c, 0x2c, 0xcb, 0xda, + 0xf8, 0x70, 0xcb, 0x11, 0xd7, 0xf5, 0x5e, 0x70, 0xca, 0x7e, 0x05, 0x6a, 0xa2, 0x75, 0xcb, 0xe7, + 0xa7, 0x4e, 0x10, 0x72, 0xe5, 0xb9, 0x48, 0x39, 0x1c, 0x82, 0x6b, 0x0b, 0x54, 0x53, 0x62, 0xb2, + 0x8f, 0xa0, 0x82, 0x55, 0x49, 0x5f, 0x96, 0xdb, 0xd2, 0x9a, 0xaf, 0x48, 0x43, 0xdd, 0xb9, 0x61, + 0x42, 0x10, 0x7d, 0x6d, 0x94, 0xa1, 0x18, 0xfa, 0xce, 0xe9, 0x29, 0xf7, 0x8d, 0xd5, 0x68, 0x68, + 0xe2, 0xa4, 0xf1, 0x5e, 0xc8, 0x27, 0x42, 0x08, 0x32, 0xfe, 0x7b, 0x06, 0x2a, 0xf2, 0xec, 0xfc, + 0xdc, 0xee, 0x8a, 0x75, 0xed, 0xe5, 0x21, 0xa9, 0xc6, 0xf1, 0x43, 0xc3, 0x7b, 0xd0, 0x18, 0x0b, + 0x81, 0x48, 0x08, 0xec, 0x09, 0x5f, 0x45, 0x5d, 0x81, 0xa5, 0x3c, 0xf2, 0x10, 0x96, 0x50, 0x3c, + 0x09, 0xac, 0xd0, 0x19, 0x59, 0xaa, 0x50, 0xbe, 0xf2, 0x5b, 0xa4, 0xa2, 0xbe, 0x33, 0xda, 0x93, + 0x05, 0xe2, 0x96, 0x0e, 0x42, 0xfb, 0x94, 0x4b, 0xd1, 0x97, 0x3e, 0x8c, 0x16, 0xac, 0xce, 0xc8, + 0xea, 0x4a, 0xcf, 0xf8, 0x87, 0x35, 0x58, 0x9b, 0x2b, 0x92, 0xfa, 0x46, 0x64, 0xa3, 0x1f, 0x39, + 0xe3, 0x63, 0x2f, 0x32, 0x85, 0x65, 0x34, 0x1b, 0xfd, 0xae, 0x28, 0x51, 0xa6, 0x30, 0x0e, 0x2b, + 0x8a, 0x20, 0xd0, 0x96, 0x15, 0x89, 0xf3, 0x59, 0x14, 0x36, 0xdf, 0x4f, 0x32, 0xaa, 0xd9, 0xee, + 0x14, 0x5c, 0xbf, 0xfe, 0x96, 0x26, 0x73, 0xb0, 0x80, 0x9d, 0x40, 0x2b, 0xa2, 0x3b, 0x29, 0x1f, + 0x69, 0xba, 0x89, 0xe8, 0xe9, 0x1b, 0xaf, 0xe8, 0x29, 0x61, 0x24, 0x31, 0x57, 0x15, 0xb9, 0x52, + 0x63, 0x51, 0x3f, 0xe7, 0xf0, 0xa6, 0xea, 0x07, 0x65, 0x9d, 0xf9, 0xde, 0xf2, 0xaf, 0x35, 0x2f, + 0x34, 0xfe, 0x24, 0xbb, 0xbc, 0x25, 0x1b, 0x8e, 0x8a, 0xf4, 0x7e, 0xcf, 0x60, 0xf5, 0xc2, 0x76, + 0x42, 0x35, 0x3f, 0x4d, 0x2d, 0x2a, 0x60, 0x7f, 0x4f, 0x5e, 0xd1, 0xdf, 0xa7, 0x54, 0x39, 0x21, + 0xfd, 0x2d, 0x5f, 0xcc, 0x03, 0x83, 0xf5, 0xff, 0x9c, 0x85, 0x7a, 0xb2, 0x15, 0x71, 0xa8, 0x25, + 0x1f, 0x52, 0xf2, 0x84, 0x94, 0xc7, 0xa5, 0x89, 0x76, 0x9f, 0xe4, 0x88, 0x79, 0xe3, 0x71, 0x36, + 0xc5, 0x78, 0xac, 0xdb, 0x6c, 0x73, 0xaf, 0xf2, 0x6d, 0xe5, 0x5f, 0xcb, 0xb7, 0x55, 0x48, 0xf3, + 0x6d, 0x5d, 0xef, 0x10, 0x59, 0xf8, 0xb9, 0x1c, 0x22, 0xc5, 0xeb, 0x1d, 0x22, 0xeb, 0x7f, 0x95, + 0x01, 0x36, 0x4f, 0xa9, 0xec, 0x19, 0xd9, 0xc9, 0x5d, 0x3e, 0x92, 0x5c, 0xec, 0x9b, 0xaf, 0x47, + 0xed, 0x6a, 0x83, 0x54, 0x6d, 0xf6, 0x08, 0x96, 0xf4, 0x77, 0xc1, 0xba, 0xaa, 0x52, 0x33, 0x99, + 0x5e, 0x14, 0x2b, 0xb4, 0x9a, 0x63, 0x2f, 0xff, 0x4a, 0xc7, 0x5e, 0xe1, 0x95, 0x8e, 0xbd, 0x85, + 0xa4, 0x63, 0x6f, 0xfd, 0xef, 0x64, 0x60, 0x29, 0x85, 0xa8, 0xbe, 0xba, 0x39, 0x0b, 0x5a, 0x48, + 0xb0, 0x98, 0xac, 0xa4, 0x05, 0x8d, 0xbb, 0xac, 0xff, 0x04, 0x6a, 0x89, 0x43, 0xf4, 0xd5, 0x75, + 0x3f, 0xab, 0x68, 0x11, 0x29, 0xeb, 0x8a, 0xd6, 0xfa, 0x5f, 0x66, 0x81, 0xcd, 0x9f, 0xe3, 0x5f, + 0xe6, 0x10, 0xe6, 0x17, 0x29, 0x37, 0xbf, 0x48, 0xff, 0xff, 0xee, 0x95, 0xf7, 0x60, 0x51, 0xc6, + 0x32, 0x68, 0x4e, 0x11, 0x22, 0x94, 0x66, 0x54, 0xa0, 0x46, 0xf1, 0x9d, 0x59, 0x9f, 0x6a, 0x29, + 0xf1, 0x7c, 0x5b, 0xbb, 0x58, 0x93, 0xae, 0x55, 0x63, 0x1d, 0x5a, 0x72, 0x69, 0xe6, 0x4d, 0x75, + 0xbf, 0x93, 0x8f, 0xb4, 0x64, 0x2c, 0x94, 0x42, 0xf1, 0xb7, 0xa0, 0xaa, 0x5f, 0x36, 0x72, 0x1f, + 0x66, 0xbc, 0x61, 0x42, 0x1c, 0xf6, 0xb4, 0xd3, 0xba, 0x09, 0xe4, 0xe3, 0x18, 0x46, 0xd5, 0x48, + 0x82, 0x78, 0x89, 0x51, 0x1c, 0x85, 0xa3, 0xc4, 0xe6, 0xff, 0x35, 0xa8, 0x27, 0xed, 0x56, 0x52, + 0xd4, 0x4b, 0x93, 0x0e, 0x45, 0xed, 0x84, 0x21, 0x8b, 0x7d, 0x1f, 0x9a, 0xb3, 0x76, 0x2f, 0xf9, + 0xb6, 0xf4, 0x9a, 0xfa, 0x0d, 0x27, 0x69, 0x0a, 0x63, 0x3b, 0xb0, 0x9c, 0x76, 0xdd, 0xe2, 0xae, + 0x5c, 0xaf, 0x16, 0xb0, 0xf9, 0x2b, 0x95, 0x7d, 0x57, 0x9a, 0x37, 0x0b, 0x69, 0x4e, 0x22, 0x6d, + 0xb1, 0x1f, 0xd2, 0x7f, 0x9a, 0xa1, 0xf3, 0x1c, 0x20, 0x86, 0xb1, 0x26, 0x54, 0x0f, 0x0e, 0x3b, + 0xfb, 0xd6, 0xe6, 0x4e, 0x7b, 0x7f, 0xbf, 0xb3, 0xdb, 0xbc, 0xc1, 0x18, 0xd4, 0xd1, 0xbb, 0xb3, + 0x15, 0xc1, 0x32, 0x02, 0x26, 0xcd, 0xcc, 0x0a, 0x96, 0x65, 0xcb, 0xd0, 0xec, 0xee, 0xcf, 0x40, + 0x73, 0xac, 0x05, 0xcb, 0x87, 0x1d, 0x72, 0x08, 0x25, 0xda, 0xcd, 0x0b, 0x11, 0x4e, 0x4e, 0x57, + 0x88, 0x70, 0x14, 0x09, 0x23, 0xa9, 0x4f, 0x49, 0x36, 0xbf, 0x9b, 0x81, 0x95, 0x99, 0x82, 0xf8, + 0x7d, 0x33, 0xc9, 0x35, 0x49, 0x89, 0xa6, 0x8a, 0x40, 0x45, 0xc3, 0xef, 0xc1, 0x62, 0xa4, 0xea, + 0xcd, 0xf0, 0xa5, 0x66, 0x54, 0xa0, 0x90, 0x1f, 0xc1, 0x92, 0xa6, 0x31, 0xce, 0x9c, 0x50, 0xa6, + 0x15, 0xc9, 0x0a, 0xc6, 0x5a, 0xf4, 0x8e, 0x74, 0x66, 0xd4, 0x43, 0x0a, 0xaf, 0xd1, 0x0b, 0x62, + 0xeb, 0x6f, 0x72, 0xbc, 0xea, 0x53, 0xa8, 0xf2, 0x09, 0x42, 0x48, 0x8e, 0x56, 0xdf, 0x70, 0xd5, + 0xfd, 0xef, 0x2f, 0x00, 0xfb, 0x78, 0xca, 0xfd, 0x2b, 0x7c, 0xbf, 0x1c, 0xbc, 0xea, 0x41, 0x8f, + 0x52, 0x8b, 0xb2, 0xaf, 0x15, 0xa3, 0x90, 0x16, 0x23, 0x90, 0x7f, 0x75, 0x8c, 0x40, 0xe1, 0x55, + 0x31, 0x02, 0x6f, 0x43, 0xcd, 0x39, 0x75, 0x3d, 0xc1, 0x80, 0x84, 0x6c, 0x12, 0xb4, 0x16, 0xee, + 0xe6, 0xee, 0x57, 0xcd, 0xaa, 0x04, 0x0a, 0xc9, 0x24, 0x60, 0x1f, 0xc5, 0x48, 0x7c, 0x78, 0x8a, + 0xf1, 0x2c, 0x3a, 0xeb, 0xe9, 0x0c, 0x4f, 0xb9, 0xd4, 0x02, 0xd1, 0x2e, 0xa2, 0x2a, 0x0b, 0x78, + 0xc0, 0xde, 0x81, 0x7a, 0xe0, 0x4d, 0x85, 0xa8, 0xa7, 0x96, 0x81, 0xec, 0xc3, 0x55, 0x82, 0x1e, + 0x2a, 0x67, 0xc0, 0xd2, 0x34, 0xe0, 0xd6, 0xd8, 0x09, 0x02, 0x71, 0x41, 0x0f, 0x3c, 0x37, 0xf4, + 0xbd, 0x91, 0x34, 0xf9, 0x2e, 0x4e, 0x03, 0xbe, 0x47, 0x25, 0x9b, 0x54, 0xc0, 0xbe, 0x1d, 0x0f, + 0x69, 0x62, 0x3b, 0x7e, 0xd0, 0x02, 0x1c, 0x92, 0x9a, 0x29, 0x4a, 0x54, 0xb6, 0xe3, 0x47, 0x63, + 0x11, 0x1f, 0xc1, 0x4c, 0xec, 0x42, 0x65, 0x36, 0x76, 0xe1, 0x47, 0xe9, 0xb1, 0x0b, 0x35, 0x6c, + 0xfa, 0xb1, 0x6c, 0x7a, 0x7e, 0x8b, 0xbf, 0x54, 0x08, 0xc3, 0x7c, 0x48, 0x46, 0xfd, 0xcb, 0x84, + 0x64, 0x34, 0xd2, 0x42, 0x32, 0xde, 0x87, 0x0a, 0x3e, 0x96, 0xb7, 0xce, 0x1c, 0x37, 0x54, 0x26, + 0xec, 0xa6, 0xfe, 0x9a, 0x7e, 0x47, 0x28, 0xd3, 0xe0, 0xab, 0x3f, 0x83, 0xf9, 0xe8, 0x88, 0xc5, + 0x5f, 0x62, 0x74, 0x84, 0x7c, 0xd4, 0xff, 0x10, 0x4a, 0x6a, 0x9f, 0x18, 0x83, 0xfc, 0x89, 0xef, + 0x8d, 0x95, 0x69, 0x4f, 0xfc, 0xcd, 0xea, 0x90, 0x0d, 0x3d, 0x59, 0x39, 0x1b, 0x7a, 0xc6, 0x6f, + 0x40, 0x45, 0x23, 0x35, 0xf6, 0x16, 0x19, 0x11, 0x84, 0xb4, 0x2c, 0xb5, 0x64, 0x5a, 0xc5, 0xb2, + 0x84, 0x76, 0x87, 0x82, 0xdf, 0x0c, 0x1d, 0x9f, 0x63, 0x1c, 0x93, 0xe5, 0xf3, 0x73, 0xee, 0x07, + 0xca, 0xd4, 0xda, 0x8c, 0x0a, 0x4c, 0x82, 0x1b, 0x7f, 0x13, 0x96, 0x12, 0x7b, 0x2b, 0x59, 0xc4, + 0x3b, 0xb0, 0x80, 0xeb, 0xa6, 0x5c, 0x61, 0xc9, 0x28, 0x05, 0x59, 0x86, 0x01, 0xaa, 0x64, 0x25, + 0xb6, 0x26, 0xbe, 0x77, 0x8c, 0x9d, 0x64, 0xcc, 0x8a, 0x84, 0x1d, 0xfa, 0xde, 0xb1, 0xf1, 0x67, + 0x39, 0xc8, 0xed, 0x78, 0x13, 0xfd, 0xf5, 0x47, 0x66, 0xee, 0xf5, 0x87, 0x54, 0x01, 0xac, 0x48, + 0xc4, 0x97, 0x52, 0x1b, 0xda, 0x47, 0x95, 0x98, 0x7f, 0x1f, 0xea, 0x82, 0x4f, 0x84, 0x9e, 0xd0, + 0xa1, 0x2e, 0x6c, 0x9f, 0x62, 0x16, 0x72, 0x74, 0xf8, 0xec, 0x71, 0xd8, 0xf7, 0xb6, 0x09, 0xce, + 0x96, 0x21, 0x17, 0x09, 0xb0, 0x58, 0x2c, 0x3e, 0x85, 0x72, 0x8d, 0xaf, 0xf7, 0xae, 0xa4, 0xaf, + 0x47, 0x7e, 0xb1, 0x6f, 0xc2, 0x52, 0xb2, 0x5d, 0x62, 0x45, 0x52, 0x22, 0xd1, 0x1b, 0x46, 0x9e, + 0x74, 0x13, 0x04, 0x1f, 0x21, 0x1c, 0xe9, 0x32, 0x3e, 0xe1, 0x1c, 0x8b, 0x34, 0xa6, 0x57, 0x4a, + 0x30, 0xbd, 0x3b, 0x50, 0x09, 0x47, 0xe7, 0xd6, 0xc4, 0xbe, 0x1a, 0x79, 0xf6, 0x50, 0x9e, 0x6f, + 0x08, 0x47, 0xe7, 0x87, 0x04, 0x61, 0x8f, 0x00, 0xc6, 0x93, 0x89, 0x3c, 0x7b, 0x68, 0x6e, 0x8c, + 0x49, 0x79, 0xef, 0xf0, 0x90, 0x48, 0xce, 0x2c, 0x8f, 0x27, 0x13, 0xfa, 0x93, 0x6d, 0x41, 0x3d, + 0x35, 0xd6, 0xe8, 0xb6, 0x7a, 0x6c, 0xe6, 0x4d, 0x1e, 0xa6, 0x1c, 0xce, 0xda, 0x40, 0x87, 0xad, + 0x7f, 0x1f, 0xd8, 0x2f, 0x18, 0xf1, 0xd3, 0x87, 0x72, 0x34, 0x3e, 0x3d, 0x60, 0x06, 0x9f, 0x8f, + 0x56, 0x12, 0x01, 0x33, 0xed, 0xe1, 0xd0, 0x17, 0x7c, 0x91, 0x2e, 0xcc, 0x88, 0xe5, 0x83, 0x76, + 0x63, 0xb6, 0x89, 0xef, 0x1b, 0x7f, 0x91, 0x81, 0x02, 0x45, 0xef, 0xbc, 0x0b, 0x0d, 0xc2, 0x8f, + 0x5e, 0xd2, 0x48, 0x0f, 0x11, 0xdd, 0xbb, 0x7d, 0xf9, 0x88, 0x46, 0x1c, 0x0b, 0x2d, 0xf2, 0x30, + 0x1b, 0xed, 0xbc, 0x16, 0x7d, 0x78, 0x07, 0xca, 0x51, 0xd7, 0x1a, 0xe9, 0x94, 0x54, 0xcf, 0xec, + 0x4d, 0xc8, 0x9f, 0x79, 0x13, 0xa5, 0x8b, 0x43, 0xbc, 0x92, 0x26, 0xc2, 0xe3, 0xb1, 0x88, 0x3e, + 0x68, 0xf0, 0x52, 0x87, 0x8c, 0x3a, 0x41, 0x32, 0x98, 0x9f, 0xe3, 0x42, 0xca, 0x1c, 0x8f, 0xa0, + 0x21, 0xf8, 0x80, 0xe6, 0xa9, 0xbd, 0xfe, 0xd2, 0xfc, 0xba, 0x90, 0xf0, 0x06, 0xa3, 0xe9, 0x90, + 0xeb, 0x96, 0x10, 0x7c, 0xd6, 0x21, 0xe1, 0x4a, 0x3d, 0x30, 0x7e, 0x3f, 0x43, 0xfc, 0x45, 0xb4, + 0xcb, 0xee, 0x43, 0x5e, 0xdc, 0x6f, 0x33, 0x96, 0xba, 0xe8, 0x1d, 0xaf, 0xc0, 0x33, 0x11, 0x03, + 0xc3, 0x75, 0xa7, 0xe3, 0x64, 0xeb, 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0x31, 0xe1, 0x6b, 0x6a, + 0x5a, 0x33, 0x8a, 0x38, 0xcd, 0x3e, 0x3a, 0xa6, 0x0f, 0xb5, 0xf7, 0x21, 0xf9, 0xc4, 0x8d, 0xa9, + 0xa4, 0xc0, 0xe1, 0x29, 0xd7, 0xde, 0x85, 0xfc, 0x61, 0x16, 0x6a, 0x89, 0x11, 0xe1, 0x03, 0x19, + 0x71, 0x01, 0x90, 0x15, 0x58, 0xee, 0x37, 0x08, 0x90, 0x14, 0xd4, 0xb5, 0x75, 0xca, 0x26, 0xd6, + 0x29, 0xf2, 0x49, 0xe7, 0x74, 0x9f, 0xf4, 0x63, 0x28, 0xc7, 0x11, 0xa7, 0xc9, 0x21, 0x89, 0xfe, + 0xd4, 0x6b, 0xe6, 0x18, 0x29, 0xf6, 0x62, 0x17, 0x74, 0x2f, 0xf6, 0xf7, 0x34, 0xa7, 0xe7, 0x02, + 0x36, 0x63, 0xa4, 0xad, 0xe8, 0x2f, 0xc5, 0xe5, 0x69, 0x7c, 0x04, 0x15, 0x6d, 0xf0, 0xba, 0x73, + 0x33, 0x93, 0x70, 0x6e, 0x46, 0x71, 0x07, 0xd9, 0x38, 0xee, 0xc0, 0xf8, 0xad, 0x2c, 0xd4, 0xc4, + 0xf9, 0x72, 0xdc, 0xd3, 0x43, 0x6f, 0xe4, 0x0c, 0xd0, 0x2a, 0x1c, 0x9d, 0x30, 0x29, 0x68, 0xa9, + 0x73, 0x26, 0x8f, 0x18, 0xc9, 0x59, 0x7a, 0x78, 0x15, 0x31, 0xe9, 0x28, 0xbc, 0xca, 0x80, 0x9a, + 0x60, 0x8c, 0xc7, 0x76, 0xc0, 0xb5, 0x78, 0x58, 0xb3, 0x72, 0xc2, 0xf9, 0x86, 0x1d, 0x10, 0x87, + 0xfc, 0x26, 0x2c, 0x09, 0x1c, 0x8c, 0x2c, 0x19, 0x3b, 0xa3, 0x91, 0x43, 0x98, 0x64, 0x6a, 0x68, + 0x9e, 0x70, 0x6e, 0xda, 0x21, 0xdf, 0x13, 0x05, 0x32, 0x7c, 0xb6, 0x34, 0x74, 0x02, 0xfb, 0x38, + 0x7e, 0xc6, 0x14, 0x7d, 0xa3, 0x2f, 0xc7, 0xbe, 0xd4, 0x7c, 0x39, 0x14, 0x62, 0x56, 0x19, 0xdb, + 0x97, 0x91, 0x2f, 0x67, 0x86, 0x92, 0x8a, 0xb3, 0x94, 0x64, 0xfc, 0xb7, 0x2c, 0x54, 0x34, 0xb2, + 0x7c, 0x9d, 0xdb, 0xf5, 0xf6, 0x9c, 0x15, 0xbf, 0xac, 0x1b, 0xec, 0xdf, 0x4e, 0x76, 0x89, 0x2e, + 0x5f, 0x0a, 0xd4, 0xd5, 0x08, 0xf8, 0x16, 0x94, 0xc5, 0xa9, 0x7b, 0x1f, 0x8d, 0x62, 0x32, 0xcc, + 0x1c, 0x01, 0x87, 0xd3, 0x63, 0x55, 0xf8, 0x04, 0x0b, 0x0b, 0x71, 0xe1, 0x13, 0x51, 0xf8, 0xb2, + 0xb7, 0x8b, 0xdf, 0x81, 0xaa, 0x6c, 0x15, 0xf7, 0x14, 0xa7, 0x1b, 0x9f, 0xfa, 0xc4, 0x7e, 0x9b, + 0x15, 0xea, 0x8e, 0x36, 0x5f, 0x56, 0x7c, 0xa2, 0x2a, 0x96, 0x5e, 0x55, 0xf1, 0x09, 0x7d, 0x18, + 0xdb, 0xd1, 0x73, 0x50, 0x7c, 0x6e, 0xa0, 0xf8, 0xd8, 0x23, 0x58, 0x52, 0xec, 0x6a, 0xea, 0xda, + 0xae, 0xeb, 0x4d, 0xdd, 0x01, 0x57, 0x01, 0x09, 0x4c, 0x16, 0x1d, 0xc5, 0x25, 0xc6, 0x30, 0x8a, + 0x58, 0xa3, 0x67, 0x0b, 0x0f, 0xa0, 0x40, 0x72, 0x39, 0x09, 0x1f, 0xe9, 0x8c, 0x8b, 0x50, 0xd8, + 0x7d, 0x28, 0x90, 0x78, 0x9e, 0xbd, 0x96, 0xd9, 0x10, 0x82, 0xf1, 0x10, 0x1a, 0x28, 0x62, 0x6a, + 0x1c, 0xf7, 0x65, 0x52, 0x89, 0xb1, 0x0c, 0x6c, 0x9f, 0x0e, 0x91, 0xfe, 0x9c, 0xe6, 0x7f, 0xe6, + 0xa0, 0xa2, 0x81, 0x05, 0x5b, 0xc4, 0x07, 0x18, 0xd6, 0xd0, 0xb1, 0xc7, 0x5c, 0xf9, 0x1e, 0x6a, 0x66, 0x0d, 0xa1, 0x5b, 0x12, 0x28, 0x2e, 0x05, 0xfb, 0xfc, 0xd4, 0xf2, 0xa6, 0xa1, 0x35, 0xe4, 0xa7, 0x3e, 0xe7, 0x52, 0x58, 0xaa, 0xda, 0xe7, 0xa7, 0x07, 0xd3, 0x70, 0x0b, 0x61, 0x02, 0x4b, - 0x10, 0xb5, 0x86, 0x25, 0x63, 0x06, 0xc6, 0xf6, 0x65, 0x8c, 0x25, 0x03, 0x57, 0x68, 0x89, 0xf2, - 0x51, 0xe0, 0x0a, 0xa9, 0x2d, 0xb3, 0x9c, 0xbc, 0x30, 0xcf, 0xc9, 0xbf, 0x0b, 0xab, 0xc4, 0xc9, - 0x25, 0x8f, 0xb0, 0x66, 0x48, 0x6a, 0x19, 0x4b, 0xe5, 0x24, 0x35, 0xf9, 0xab, 0x29, 0x66, 0xa0, - 0xce, 0x47, 0xe0, 0xfc, 0x94, 0x4e, 0x54, 0xc6, 0x14, 0x33, 0x93, 0x8d, 0xf7, 0x9c, 0x9f, 0x72, - 0x81, 0x89, 0x8e, 0x51, 0x1d, 0x53, 0x86, 0xa1, 0x8e, 0x1d, 0x77, 0x16, 0xd3, 0xbe, 0x4c, 0x62, - 0x96, 0x25, 0xa6, 0x7d, 0xa9, 0x63, 0xbe, 0x0f, 0x6b, 0x63, 0x3e, 0x74, 0xec, 0x64, 0xb3, 0x56, - 0x2c, 0x41, 0x2c, 0x53, 0xb1, 0x56, 0xa7, 0x47, 0x1a, 0xa4, 0x58, 0x8d, 0x9f, 0x7a, 0xe3, 0x63, - 0x87, 0x2e, 0x4f, 0x72, 0xd5, 0xe6, 0xcd, 0xba, 0x3b, 0x1d, 0xff, 0x18, 0xc1, 0xa2, 0x4a, 0x60, - 0xd4, 0xa0, 0xd2, 0x0b, 0xbd, 0x89, 0xda, 0xe6, 0x3a, 0x54, 0xe9, 0x53, 0xa6, 0x74, 0xdc, 0x82, - 0x9b, 0x48, 0x9b, 0x7d, 0x6f, 0xe2, 0x8d, 0xbc, 0xd3, 0xab, 0x84, 0x41, 0xe9, 0xbf, 0x67, 0x60, - 0x29, 0x51, 0x2a, 0xcf, 0xf9, 0x77, 0xe9, 0x60, 0x45, 0x71, 0xf9, 0x44, 0xce, 0x8b, 0xda, 0xe5, - 0x43, 0x88, 0x74, 0xaa, 0x54, 0xac, 0x7e, 0x3b, 0xce, 0x27, 0x55, 0x15, 0x89, 0xb6, 0x5b, 0xf3, - 0xb4, 0x2d, 0xeb, 0xab, 0x4c, 0x53, 0xd5, 0xc4, 0xff, 0x2f, 0x43, 0x85, 0x87, 0x72, 0xca, 0xb9, - 0x64, 0x30, 0xa4, 0x6e, 0x7c, 0x52, 0x23, 0x88, 0x2d, 0x52, 0x81, 0xf1, 0x6f, 0x32, 0x00, 0xf1, - 0xe8, 0x30, 0x1c, 0x33, 0xba, 0x40, 0xe9, 0xa9, 0x16, 0xed, 0xb2, 0x7c, 0x13, 0xaa, 0x51, 0xc4, - 0x58, 0x7c, 0x25, 0x57, 0x14, 0x4c, 0xdc, 0xcb, 0xf7, 0xa1, 0x71, 0x3a, 0xf2, 0x8e, 0x51, 0x74, - 0x92, 0x17, 0x28, 0x25, 0xb6, 0xd4, 0x09, 0xac, 0xae, 0xc5, 0xf8, 0x02, 0xcf, 0xa7, 0x06, 0x95, - 0xe9, 0xd7, 0xb1, 0xf1, 0xdb, 0xd9, 0x28, 0x74, 0x26, 0x5e, 0x89, 0x97, 0xeb, 0x19, 0x5f, 0xc7, - 0x03, 0xfb, 0x32, 0xcf, 0xc3, 0x47, 0x50, 0xf7, 0x89, 0x3b, 0x2a, 0xd6, 0x99, 0x7f, 0x09, 0xeb, - 0xac, 0xf9, 0x89, 0x2b, 0xf7, 0x9b, 0xd0, 0xb4, 0x87, 0xe7, 0xdc, 0x0f, 0x1d, 0x34, 0xd6, 0xa2, - 0xa0, 0x26, 0x83, 0x55, 0x34, 0x38, 0x4a, 0x44, 0xf7, 0xa1, 0x21, 0xd3, 0x8c, 0x22, 0x4c, 0xf9, - 0x70, 0x41, 0x0c, 0x16, 0x88, 0xc6, 0xbf, 0x57, 0xb1, 0x3a, 0xc9, 0xdd, 0x7d, 0xf9, 0xaa, 0xe8, - 0x33, 0xcc, 0xce, 0xfb, 0x56, 0x24, 0x21, 0x49, 0x1b, 0xb0, 0xe4, 0x47, 0x04, 0x94, 0x16, 0xe0, - 0xe4, 0xb2, 0xe6, 0x5f, 0x67, 0x59, 0x8d, 0x3f, 0xce, 0x40, 0x71, 0xc7, 0x9b, 0x08, 0xbd, 0x5c, - 0xc8, 0x73, 0x78, 0x4c, 0xa2, 0x14, 0xbf, 0x05, 0xf1, 0xd9, 0x1d, 0xbe, 0x3c, 0x2c, 0x3f, 0x55, - 0xde, 0xa8, 0x25, 0xe5, 0x8d, 0x1f, 0xc0, 0x2d, 0xf4, 0x46, 0xf8, 0xde, 0xc4, 0xf3, 0xc5, 0x51, - 0xb5, 0x47, 0x24, 0x77, 0x78, 0x6e, 0x78, 0xa6, 0x78, 0xe7, 0xcd, 0x13, 0xce, 0x0f, 0x35, 0x8c, - 0xbd, 0x08, 0x01, 0xf3, 0x55, 0x46, 0xe1, 0xb9, 0x45, 0xaa, 0xa2, 0x14, 0x8c, 0x88, 0xa3, 0x36, - 0x44, 0x41, 0x07, 0xe1, 0x28, 0x1a, 0x19, 0xdf, 0x87, 0x72, 0x64, 0x75, 0x60, 0xef, 0x42, 0xf9, - 0xcc, 0x9b, 0x48, 0xd3, 0x44, 0x26, 0x91, 0xba, 0x20, 0x67, 0x6d, 0x96, 0xce, 0xe8, 0x8f, 0xc0, - 0xf8, 0xb3, 0x22, 0x14, 0xbb, 0xee, 0xb9, 0xe7, 0x0c, 0x30, 0xda, 0x67, 0xcc, 0xc7, 0x9e, 0xca, - 0x75, 0x14, 0x7f, 0xa3, 0x47, 0x3f, 0x7e, 0x7e, 0x20, 0x27, 0x3d, 0xfa, 0xd1, 0xc3, 0x03, 0x2b, - 0xb0, 0xe0, 0xeb, 0xef, 0x07, 0x14, 0x7c, 0x8c, 0x3f, 0x8c, 0x94, 0xb6, 0x82, 0x96, 0x2b, 0x2a, - 0xda, 0xa2, 0xbc, 0x76, 0x5c, 0x32, 0xca, 0x3d, 0x29, 0x23, 0x04, 0x17, 0xec, 0x36, 0x14, 0x65, - 0xa6, 0x00, 0xc5, 0x5d, 0x53, 0xc0, 0xa0, 0x04, 0x21, 0x35, 0xf8, 0x9c, 0xbc, 0x49, 0x91, 0x44, - 0x25, 0xf4, 0x74, 0x09, 0xdc, 0x12, 0xb4, 0x76, 0x17, 0x2a, 0x84, 0x4f, 0x28, 0x25, 0x19, 0x9f, - 0x83, 0x20, 0x44, 0x48, 0x79, 0x86, 0xa3, 0x9c, 0xfa, 0x0c, 0x07, 0x86, 0x73, 0x45, 0x5c, 0x96, - 0xa6, 0x08, 0xf4, 0xf8, 0x82, 0x06, 0x57, 0x6f, 0xd0, 0x48, 0xe5, 0x9e, 0x52, 0xb1, 0x94, 0x72, - 0xff, 0x16, 0xd4, 0x4e, 0xec, 0xd1, 0xe8, 0xd8, 0x1e, 0xbc, 0x20, 0x9d, 0xb4, 0x4a, 0x66, 0x38, - 0x05, 0x44, 0xa5, 0xf4, 0x2e, 0x54, 0xb4, 0x5d, 0xc6, 0xe0, 0x9b, 0xbc, 0x09, 0xf1, 0xfe, 0xce, - 0x9a, 0x9a, 0xea, 0xaf, 0x61, 0x6a, 0xd2, 0x82, 0x90, 0x1a, 0xc9, 0x20, 0xa4, 0x5b, 0xc8, 0x4d, - 0x65, 0xa0, 0x4a, 0x93, 0x32, 0xfd, 0xed, 0xe1, 0x10, 0x03, 0x55, 0xe8, 0x59, 0x2d, 0x5c, 0x3c, - 0x2a, 0x5f, 0x24, 0xa1, 0x96, 0x60, 0x84, 0x72, 0x87, 0xec, 0xa5, 0x13, 0xdb, 0x19, 0x62, 0xd0, - 0x27, 0xa9, 0xb1, 0x45, 0x7b, 0x1c, 0x1e, 0xda, 0xce, 0x90, 0xdd, 0x83, 0xaa, 0x2a, 0xc6, 0xdb, - 0x71, 0x89, 0xd6, 0x5f, 0x16, 0x8b, 0x3b, 0xd1, 0x80, 0x5a, 0x84, 0x31, 0x8e, 0xf3, 0xa9, 0x2a, - 0x12, 0x05, 0xe9, 0xe0, 0x3d, 0x74, 0xfe, 0x87, 0x1c, 0xb3, 0xa6, 0xea, 0x4f, 0x6f, 0xc9, 0xb9, - 0x4a, 0x2a, 0x55, 0xff, 0x63, 0xa4, 0x83, 0x49, 0x98, 0x42, 0x10, 0x23, 0x17, 0xcd, 0x6a, 0x42, - 0x10, 0x93, 0xa8, 0xe8, 0xa2, 0x21, 0x04, 0xf6, 0x7d, 0x4d, 0x91, 0x6a, 0x21, 0xf2, 0xed, 0x99, - 0xf6, 0xaf, 0x51, 0xa1, 0x04, 0xf5, 0x3a, 0x81, 0xb8, 0x65, 0x02, 0xee, 0x0e, 0x31, 0x01, 0xaa, - 0x64, 0x96, 0x9d, 0xe0, 0x39, 0x01, 0x7e, 0xb1, 0x1a, 0x56, 0x1b, 0xaa, 0xfa, 0x34, 0x59, 0x09, - 0xf2, 0x07, 0x87, 0x9d, 0xfd, 0xe6, 0x0d, 0x56, 0x81, 0x62, 0xaf, 0xd3, 0xef, 0xef, 0x76, 0xb6, - 0x9a, 0x19, 0x56, 0x85, 0x52, 0x94, 0xc6, 0x91, 0x15, 0x5f, 0xed, 0xcd, 0xcd, 0xce, 0x61, 0xbf, - 0xb3, 0xd5, 0xcc, 0xfd, 0x28, 0x5f, 0xca, 0x36, 0x73, 0xc6, 0x9f, 0xe7, 0xa0, 0xa2, 0xad, 0xc2, - 0xcb, 0x99, 0xf1, 0x1d, 0x00, 0x54, 0x69, 0xe2, 0x38, 0xa6, 0xbc, 0x59, 0x16, 0x10, 0xda, 0x7c, - 0xdd, 0x58, 0x9e, 0xa3, 0x27, 0x24, 0x94, 0xb1, 0xfc, 0x2d, 0xa8, 0xd1, 0x6b, 0x0c, 0xba, 0xbb, - 0xae, 0x60, 0x56, 0x09, 0x28, 0x59, 0x35, 0xe6, 0x81, 0x21, 0x12, 0x66, 0x08, 0xc8, 0xdc, 0x6c, - 0x02, 0x61, 0x8e, 0x00, 0x26, 0x78, 0x04, 0xde, 0xe8, 0x9c, 0x13, 0x06, 0x49, 0x84, 0x15, 0x09, - 0xeb, 0xcb, 0x44, 0x34, 0xc9, 0x0f, 0xb5, 0x44, 0xa4, 0x82, 0x59, 0x25, 0xa0, 0xec, 0xe8, 0xdb, - 0x8a, 0x80, 0x4a, 0x48, 0x40, 0x6b, 0xf3, 0xd4, 0x90, 0x20, 0x9e, 0xdd, 0x39, 0x7b, 0x56, 0x19, - 0x09, 0xe3, 0x1b, 0xf3, 0xf5, 0x5e, 0x6d, 0xd7, 0x62, 0xef, 0x02, 0x1b, 0x4f, 0x26, 0x56, 0x8a, - 0xa5, 0x29, 0x6f, 0x36, 0xc6, 0x93, 0x49, 0x5f, 0x33, 0xc4, 0xfc, 0x02, 0x8c, 0x60, 0x9f, 0x03, - 0x6b, 0x8b, 0x03, 0x8c, 0x43, 0x8c, 0x4c, 0xa8, 0x31, 0x5b, 0xce, 0xe8, 0x6c, 0x39, 0x85, 0xfb, - 0x65, 0x53, 0xb9, 0xdf, 0xcb, 0xf8, 0x84, 0xb1, 0x0d, 0x95, 0x43, 0xed, 0xad, 0x97, 0x7b, 0xe2, - 0x86, 0x50, 0xaf, 0xbc, 0xd0, 0xdd, 0x41, 0xc6, 0x2d, 0x5f, 0x3e, 0xee, 0xa2, 0x8d, 0x26, 0xab, - 0x8d, 0xc6, 0xf8, 0xd7, 0x19, 0xca, 0xa3, 0x8f, 0x06, 0x1f, 0x3f, 0x2f, 0xa3, 0xfc, 0x40, 0x71, - 0xbe, 0x60, 0x45, 0xf9, 0x7f, 0x64, 0xaa, 0x1f, 0x0e, 0xcd, 0xf2, 0x4e, 0x4e, 0x02, 0xae, 0x32, - 0x5f, 0x2a, 0x08, 0x3b, 0x40, 0x90, 0x12, 0xbe, 0x85, 0x84, 0xef, 0x50, 0xfb, 0x81, 0xcc, 0x80, - 0x11, 0xc2, 0xf7, 0x9e, 0x7d, 0x29, 0x7b, 0x0d, 0x84, 0x08, 0x22, 0x0d, 0xd5, 0x2a, 0xdf, 0x27, - 0xfa, 0x36, 0xfe, 0x85, 0x4c, 0x69, 0x9c, 0x5d, 0xdf, 0x87, 0x50, 0x8a, 0x5a, 0x4d, 0xde, 0xb0, - 0x0a, 0x33, 0x2a, 0x17, 0xf7, 0x38, 0x6a, 0xe5, 0x89, 0x11, 0xd3, 0xe1, 0x42, 0x67, 0x43, 0x57, - 0x1b, 0xf5, 0xb7, 0x80, 0x9d, 0x38, 0xfe, 0x2c, 0x32, 0x1d, 0xb6, 0x26, 0x96, 0x68, 0xd8, 0xc6, - 0x11, 0x2c, 0x29, 0x2e, 0xa1, 0x69, 0x04, 0xc9, 0xcd, 0xcb, 0xbc, 0x82, 0xc9, 0x67, 0xe7, 0x98, - 0xbc, 0xf1, 0xb3, 0x3c, 0x14, 0xd5, 0xbb, 0x49, 0x69, 0x6f, 0xfd, 0x94, 0x93, 0x6f, 0xfd, 0xb4, - 0x12, 0xef, 0x42, 0xe0, 0xd6, 0xcb, 0xfb, 0xfe, 0xfe, 0xec, 0x95, 0xad, 0x19, 0xcd, 0x13, 0xd7, - 0xf6, 0x2a, 0xe4, 0x27, 0x76, 0x78, 0x86, 0x06, 0x32, 0x22, 0x1e, 0xfc, 0x56, 0xc6, 0xf4, 0x42, - 0xd2, 0x98, 0x9e, 0xf6, 0x2e, 0x12, 0x89, 0xa4, 0x73, 0xef, 0x22, 0xdd, 0x02, 0x92, 0x2f, 0xb4, - 0x78, 0x98, 0x12, 0x02, 0xc4, 0x5d, 0x94, 0x14, 0x47, 0x4a, 0xb3, 0xe2, 0xc8, 0x6b, 0x8b, 0x0a, - 0xdf, 0x85, 0x05, 0xca, 0x29, 0x96, 0x79, 0x4d, 0xea, 0x42, 0x91, 0x6b, 0xa8, 0xfe, 0xa7, 0x20, - 0x58, 0x53, 0xe2, 0xea, 0x8f, 0x8c, 0x54, 0x12, 0x8f, 0x8c, 0xe8, 0x46, 0xfe, 0x6a, 0xd2, 0xc8, - 0xff, 0x00, 0x9a, 0xd1, 0x82, 0xa2, 0xc9, 0xcc, 0x0d, 0x64, 0x46, 0x47, 0x5d, 0xc1, 0x05, 0x97, - 0xdc, 0x0f, 0xe2, 0x0b, 0xb1, 0x9e, 0xb8, 0x10, 0x05, 0x0f, 0x6b, 0x87, 0x21, 0x1f, 0x4f, 0x42, - 0x79, 0x21, 0x62, 0xcc, 0xb7, 0x3e, 0xc0, 0x64, 0xc6, 0x5f, 0x0d, 0xca, 0xdd, 0x7d, 0x6b, 0x7b, - 0xb7, 0xfb, 0x6c, 0xa7, 0xdf, 0xcc, 0x88, 0xcf, 0xde, 0xd1, 0xe6, 0x66, 0xa7, 0xb3, 0x85, 0x37, - 0x0e, 0xc0, 0xc2, 0x76, 0xbb, 0x2b, 0x6e, 0x9f, 0x9c, 0xf1, 0xbb, 0x59, 0xa8, 0x68, 0xcd, 0xb3, - 0xf7, 0xa3, 0x55, 0xa1, 0x77, 0x28, 0xee, 0xcc, 0x0f, 0xe1, 0x91, 0x62, 0xc5, 0xda, 0xb2, 0x44, - 0xaf, 0x40, 0x65, 0xaf, 0x7d, 0x05, 0x8a, 0xbd, 0x03, 0x0d, 0x9b, 0x5a, 0x88, 0x56, 0x41, 0x9a, - 0x83, 0x25, 0x58, 0x2e, 0x02, 0x46, 0x81, 0xc5, 0xf7, 0x89, 0xc0, 0xcb, 0xab, 0xc0, 0xab, 0xe8, - 0x4a, 0xc1, 0xc5, 0x2a, 0x9e, 0xd8, 0xce, 0x68, 0xea, 0x73, 0xe9, 0xbe, 0x8d, 0x6e, 0x66, 0x82, - 0x9a, 0xaa, 0xd8, 0xf8, 0x00, 0x20, 0x1e, 0x73, 0x72, 0x71, 0x6e, 0x24, 0x17, 0x27, 0xa3, 0x2d, - 0x4e, 0xd6, 0xd8, 0x22, 0x36, 0x22, 0x17, 0x3a, 0xf2, 0x54, 0x7f, 0x1b, 0x94, 0x45, 0xca, 0xc2, - 0x38, 0xcc, 0xc9, 0x88, 0x87, 0x2a, 0x37, 0x72, 0x51, 0x96, 0x74, 0xa3, 0x02, 0x95, 0xaa, 0x1c, - 0xb7, 0x12, 0x73, 0x23, 0x49, 0x92, 0xb3, 0xdc, 0x48, 0xa2, 0x9a, 0x51, 0xb9, 0xb1, 0x0e, 0xad, - 0x2d, 0x2e, 0x5a, 0x6b, 0x8f, 0x46, 0x33, 0xc3, 0x31, 0x6e, 0xc1, 0xcd, 0x94, 0x32, 0x69, 0x84, - 0xf8, 0x18, 0x56, 0xda, 0x94, 0x06, 0xf9, 0x8b, 0xca, 0xc5, 0x30, 0x5a, 0xb0, 0x3a, 0xdb, 0xa4, - 0xec, 0x6c, 0x1b, 0x16, 0xb7, 0xf8, 0xf1, 0xf4, 0x74, 0x97, 0x9f, 0xc7, 0x1d, 0x31, 0xc8, 0x07, - 0x67, 0xde, 0x85, 0x5c, 0x1f, 0xfc, 0x5b, 0x9c, 0xe1, 0x91, 0xc0, 0xb1, 0x82, 0x09, 0x1f, 0x28, - 0x8b, 0x28, 0x42, 0x7a, 0x13, 0x3e, 0x30, 0xde, 0x07, 0xa6, 0xb7, 0x23, 0xd7, 0x4b, 0x68, 0x09, - 0xd3, 0x63, 0x2b, 0xb8, 0x0a, 0x42, 0x3e, 0x56, 0xcf, 0x9c, 0x40, 0x30, 0x3d, 0xee, 0x11, 0xc4, - 0xb8, 0x0f, 0xd5, 0x43, 0xfb, 0xca, 0xe4, 0x9f, 0xcb, 0x2c, 0x83, 0x35, 0x28, 0x4e, 0xec, 0x2b, - 0xc1, 0x06, 0x22, 0xe7, 0x08, 0x16, 0x1b, 0x7f, 0x90, 0x87, 0x05, 0xc2, 0x64, 0xf7, 0xe8, 0x25, - 0x42, 0xc7, 0xc5, 0x63, 0xa8, 0x18, 0xa5, 0x06, 0x9a, 0xe3, 0xa5, 0xd9, 0x79, 0x5e, 0x2a, 0x0d, - 0x68, 0xea, 0x05, 0x06, 0x65, 0xc6, 0x76, 0xa7, 0x63, 0xf5, 0xec, 0x02, 0xbb, 0x0d, 0xe5, 0x38, - 0x9d, 0x2b, 0x1f, 0xbf, 0x34, 0x49, 0x49, 0x5c, 0x49, 0x47, 0x63, 0xac, 0x8b, 0xd0, 0xe8, 0xd4, - 0x15, 0x21, 0xd9, 0xa5, 0x0e, 0x4a, 0x55, 0x78, 0x8a, 0x2a, 0x7f, 0x25, 0xa9, 0xf0, 0xcc, 0x29, - 0x36, 0xa5, 0x57, 0x2b, 0x36, 0x64, 0x59, 0x7b, 0x89, 0x62, 0x03, 0xaf, 0xa1, 0xd8, 0xbc, 0x86, - 0x93, 0xef, 0x26, 0x94, 0xf0, 0xde, 0xd7, 0xb8, 0xa7, 0xb8, 0xef, 0x05, 0xf7, 0xfc, 0x9e, 0x26, - 0xfa, 0x53, 0x84, 0xc1, 0xad, 0xf8, 0x98, 0x98, 0xfc, 0xf3, 0x5f, 0x8e, 0xf3, 0xe4, 0x33, 0x28, - 0x4a, 0xa8, 0x20, 0x68, 0xd7, 0x1e, 0xab, 0x47, 0x6c, 0xf0, 0x6f, 0xb1, 0x6c, 0xf8, 0xf2, 0xc6, - 0xe7, 0x53, 0xc7, 0xe7, 0x43, 0xf5, 0xcc, 0x81, 0x83, 0x67, 0x54, 0x40, 0xc4, 0x04, 0x85, 0x1a, - 0xe2, 0x7a, 0x17, 0xae, 0x4c, 0x72, 0x2e, 0x3a, 0xc1, 0x73, 0xf1, 0x69, 0x30, 0x68, 0xe2, 0x33, - 0x56, 0x13, 0xcf, 0x57, 0x97, 0x93, 0xf1, 0xb3, 0x0c, 0x34, 0xe5, 0xe9, 0x8a, 0xca, 0x74, 0x2d, - 0xa0, 0x70, 0x9d, 0x43, 0xfc, 0xe5, 0x8f, 0x16, 0x18, 0x50, 0x43, 0xe3, 0x47, 0x74, 0x53, 0x91, - 0xf1, 0xa6, 0x22, 0x80, 0xdb, 0xf2, 0xb6, 0x7a, 0x03, 0x2a, 0x2a, 0x1c, 0x73, 0xec, 0x8c, 0xd4, - 0xa3, 0xb2, 0x14, 0x8f, 0xb9, 0xe7, 0x8c, 0xd4, 0x45, 0xe7, 0xdb, 0x32, 0x9f, 0x2a, 0x83, 0x17, - 0x9d, 0x69, 0x87, 0xdc, 0xf8, 0xcf, 0x19, 0x58, 0xd4, 0xa6, 0x22, 0xcf, 0xed, 0x87, 0x50, 0x8d, - 0xde, 0x8f, 0xe3, 0x91, 0xe4, 0xb5, 0x96, 0x64, 0x34, 0x71, 0xb5, 0xca, 0x20, 0x82, 0x04, 0x62, - 0x30, 0x43, 0xfb, 0x0a, 0xc7, 0x1b, 0x4c, 0xc7, 0x4a, 0xb9, 0x19, 0xda, 0x57, 0xdb, 0x9c, 0xf7, - 0xa6, 0x63, 0xa1, 0xba, 0x5e, 0x70, 0xfe, 0x22, 0x42, 0x20, 0x99, 0x0b, 0x04, 0x4c, 0x62, 0x18, - 0x50, 0x1b, 0x7b, 0x6e, 0x78, 0x16, 0xa1, 0x48, 0xa9, 0x13, 0x81, 0x84, 0x63, 0xfc, 0x69, 0x16, - 0x96, 0xc8, 0xc4, 0x26, 0x4d, 0x9b, 0x92, 0x75, 0xb5, 0x60, 0x81, 0xac, 0x8d, 0xc4, 0xbc, 0x76, - 0x6e, 0x98, 0xf2, 0x9b, 0x7d, 0xf7, 0x35, 0xcd, 0x82, 0x2a, 0x65, 0xeb, 0x9a, 0xe5, 0xcf, 0xcd, - 0x2f, 0xff, 0xf5, 0xcb, 0x9b, 0xe6, 0x71, 0x2b, 0xa4, 0x79, 0xdc, 0x5e, 0xc7, 0xcf, 0x35, 0x97, - 0xd7, 0x54, 0x94, 0x38, 0x5a, 0x5e, 0xd3, 0xfb, 0xb0, 0x96, 0xc0, 0x41, 0x6e, 0xed, 0x9c, 0x38, - 0x5c, 0xe5, 0x90, 0x2f, 0x6b, 0xd8, 0x3d, 0x55, 0xb6, 0x51, 0x84, 0x42, 0x30, 0xf0, 0x26, 0xdc, - 0x58, 0x85, 0xe5, 0xe4, 0xaa, 0xca, 0x6b, 0xe2, 0xf7, 0x32, 0xd0, 0x92, 0xf1, 0x11, 0x8e, 0x7b, - 0xba, 0xe3, 0x04, 0xa1, 0xe7, 0x47, 0xef, 0xac, 0xdd, 0x01, 0x08, 0x42, 0xdb, 0x97, 0xda, 0x26, - 0xc9, 0xc1, 0x65, 0x84, 0xa0, 0x26, 0x79, 0x13, 0x4a, 0xdc, 0x1d, 0x52, 0x21, 0x51, 0x43, 0x91, - 0xbb, 0x43, 0xa5, 0x87, 0xce, 0xc9, 0xdf, 0xb5, 0xa4, 0x7a, 0x21, 0x13, 0x2c, 0xc5, 0xea, 0xf0, - 0x73, 0xbc, 0x78, 0xf3, 0x51, 0x82, 0xe5, 0x9e, 0x7d, 0x89, 0xd1, 0x86, 0x81, 0xf1, 0x4f, 0xb3, - 0xd0, 0x88, 0xc7, 0x47, 0xd9, 0xd9, 0x09, 0xfe, 0x2d, 0x47, 0x15, 0xf3, 0xef, 0x7b, 0x92, 0x1c, - 0x1c, 0x21, 0xbf, 0x6b, 0x86, 0xc7, 0x12, 0x1d, 0xce, 0xae, 0xcb, 0x0c, 0xa8, 0x28, 0x0c, 0x6f, - 0x1a, 0x6a, 0xcf, 0x1d, 0x95, 0x09, 0xe5, 0x60, 0x1a, 0x0a, 0x85, 0x4b, 0x68, 0x9e, 0x8e, 0x2b, - 0x55, 0x9e, 0x82, 0x3d, 0x0e, 0xbb, 0xf8, 0x8a, 0xb2, 0x00, 0x8b, 0x6a, 0xb4, 0x91, 0x02, 0x4b, - 0xe0, 0x37, 0x49, 0xce, 0xa6, 0x9d, 0x43, 0x19, 0x5b, 0x17, 0x42, 0xe9, 0x41, 0xc9, 0x48, 0x08, - 0x7d, 0x03, 0x2a, 0xd4, 0x78, 0x9c, 0xc6, 0x96, 0x37, 0xcb, 0xd8, 0x03, 0x96, 0x4b, 0x23, 0x90, - 0x37, 0x4d, 0xa8, 0xbe, 0x40, 0x5d, 0x61, 0xf8, 0xc1, 0x3f, 0xca, 0xc0, 0xcd, 0x94, 0x6d, 0x93, - 0xa7, 0x7c, 0x13, 0x16, 0x4f, 0xa2, 0x42, 0xb5, 0xba, 0x74, 0xd4, 0x57, 0x15, 0x5b, 0x4d, 0xae, - 0xa9, 0xd9, 0x3c, 0x49, 0x02, 0x62, 0xa5, 0x8b, 0x76, 0x30, 0x91, 0xa9, 0x88, 0x4a, 0x17, 0x6d, - 0x23, 0xe9, 0x3b, 0x87, 0xb0, 0xde, 0xb9, 0x14, 0x1c, 0x63, 0x53, 0x7f, 0x06, 0x5c, 0x91, 0x51, - 0xd2, 0xc0, 0x9c, 0x79, 0x2d, 0x03, 0xf3, 0x90, 0x12, 0xb2, 0xa2, 0xb6, 0xbe, 0x4e, 0x23, 0x78, - 0x81, 0x8a, 0x3a, 0xf4, 0x8c, 0xb9, 0xca, 0x96, 0x1c, 0x44, 0xcf, 0x97, 0x1b, 0x01, 0x34, 0xf6, - 0xa6, 0xa3, 0xd0, 0x89, 0x5f, 0x34, 0x67, 0xdf, 0x95, 0x75, 0xb0, 0x1f, 0xb5, 0x6a, 0xa9, 0x1d, - 0x41, 0xd4, 0x11, 0x2e, 0xd6, 0x58, 0x34, 0x64, 0xcd, 0xf7, 0xd7, 0x18, 0x27, 0x7b, 0x30, 0x6e, - 0xc2, 0x5a, 0xfc, 0x45, 0xcb, 0xa6, 0xae, 0x9a, 0x7f, 0x95, 0xa1, 0xd0, 0xe6, 0xe4, 0xeb, 0xea, - 0xac, 0x03, 0x4b, 0x81, 0xe3, 0x9e, 0x8e, 0xb8, 0xde, 0x7c, 0x20, 0x17, 0x61, 0x25, 0x39, 0x36, - 0xf9, 0x02, 0xbb, 0xb9, 0x48, 0x35, 0xe2, 0xd6, 0x02, 0xb6, 0x71, 0xdd, 0x20, 0x63, 0xb2, 0x98, - 0x59, 0x8d, 0xf9, 0xc1, 0x77, 0xa1, 0x9e, 0xec, 0x88, 0x7d, 0x4f, 0x26, 0x23, 0xc6, 0xa3, 0xca, - 0xcd, 0xe4, 0x95, 0xc5, 0x04, 0x51, 0x89, 0xd7, 0x3e, 0x30, 0xfe, 0x71, 0x06, 0x5a, 0x26, 0x17, - 0x94, 0xab, 0x8d, 0x52, 0xd1, 0xcc, 0x87, 0x73, 0xad, 0x5e, 0x3f, 0x57, 0x95, 0xe3, 0xa8, 0x46, - 0xf4, 0xad, 0x6b, 0x37, 0x63, 0xe7, 0xc6, 0xdc, 0x8c, 0x36, 0x4a, 0xb0, 0x40, 0x28, 0xc6, 0x1a, - 0xac, 0xc8, 0xf1, 0xa8, 0xb1, 0xc4, 0xde, 0xc3, 0x44, 0x8f, 0x09, 0xef, 0xe1, 0x3a, 0xb4, 0xe8, - 0xb9, 0x3c, 0x7d, 0x12, 0xb2, 0xe2, 0x16, 0xb0, 0x3d, 0x7b, 0x60, 0xfb, 0x9e, 0xe7, 0x1e, 0x72, - 0x5f, 0x06, 0x8a, 0xa2, 0x84, 0x89, 0xce, 0x35, 0x25, 0x0a, 0xd3, 0x97, 0x7a, 0xe4, 0xcd, 0x73, - 0x55, 0x5c, 0x0c, 0x7d, 0x19, 0x26, 0x2c, 0x6d, 0xd8, 0x2f, 0xb8, 0x6a, 0x49, 0x2d, 0xd1, 0x47, - 0x50, 0x99, 0x44, 0x8d, 0xaa, 0x75, 0x57, 0x19, 0xcb, 0xf3, 0xdd, 0x9a, 0x3a, 0xb6, 0xf1, 0x14, - 0x96, 0x93, 0x6d, 0x4a, 0xd6, 0xb1, 0x0e, 0xa5, 0xb1, 0x84, 0xc9, 0xd1, 0x45, 0xdf, 0xc6, 0xef, - 0x94, 0xa0, 0x28, 0xf5, 0x39, 0xf6, 0x08, 0xf2, 0x03, 0x15, 0x9b, 0x14, 0x3f, 0x84, 0x21, 0x4b, - 0xd5, 0xff, 0x9b, 0x18, 0xa1, 0x24, 0xf0, 0xd8, 0x47, 0x50, 0x4f, 0x7a, 0x45, 0x67, 0xd2, 0x21, - 0x93, 0xee, 0xcc, 0xda, 0x60, 0xc6, 0xff, 0x55, 0x8e, 0x2f, 0x47, 0x92, 0x19, 0x4a, 0x67, 0xda, - 0xed, 0xe9, 0xb9, 0x42, 0xde, 0x0e, 0xce, 0x6c, 0xeb, 0xe9, 0xfb, 0x1f, 0xc8, 0x7c, 0xc8, 0x0a, - 0x02, 0x7b, 0x67, 0xf6, 0xd3, 0xf7, 0x3f, 0x98, 0x95, 0xa4, 0x29, 0x25, 0x4e, 0x97, 0xa4, 0x97, - 0xa1, 0x40, 0xaf, 0x99, 0x51, 0x90, 0x09, 0x7d, 0xb0, 0x27, 0xb0, 0x2c, 0xd5, 0x56, 0x4b, 0x86, - 0x03, 0x13, 0x17, 0x2c, 0x51, 0x0e, 0x8e, 0x2c, 0xeb, 0x61, 0x11, 0xd9, 0x86, 0x56, 0x61, 0xe1, - 0x2c, 0x7e, 0x9a, 0xae, 0x66, 0xca, 0x2f, 0xe3, 0x4f, 0x0b, 0x50, 0xd1, 0x16, 0x85, 0x55, 0xa1, - 0x64, 0x76, 0x7a, 0x1d, 0xf3, 0x93, 0xce, 0x56, 0xf3, 0x06, 0x7b, 0x00, 0x6f, 0x77, 0xf7, 0x37, - 0x0f, 0x4c, 0xb3, 0xb3, 0xd9, 0xb7, 0x0e, 0x4c, 0x4b, 0xbd, 0x91, 0x72, 0xd8, 0xfe, 0x6c, 0xaf, - 0xb3, 0xdf, 0xb7, 0xb6, 0x3a, 0xfd, 0x76, 0x77, 0xb7, 0xd7, 0xcc, 0xb0, 0xdb, 0xd0, 0x8a, 0x31, - 0x55, 0x71, 0x7b, 0xef, 0xe0, 0x68, 0xbf, 0xdf, 0xcc, 0xb2, 0xbb, 0x70, 0x6b, 0xbb, 0xbb, 0xdf, - 0xde, 0xb5, 0x62, 0x9c, 0xcd, 0xdd, 0xfe, 0x27, 0x56, 0xe7, 0xd7, 0x0e, 0xbb, 0xe6, 0x67, 0xcd, - 0x5c, 0x1a, 0x82, 0x50, 0xc6, 0x55, 0x0b, 0x79, 0x76, 0x13, 0x56, 0x08, 0x81, 0xaa, 0x58, 0xfd, - 0x83, 0x03, 0xab, 0x77, 0x70, 0xb0, 0xdf, 0x2c, 0xb0, 0x45, 0xa8, 0x75, 0xf7, 0x3f, 0x69, 0xef, - 0x76, 0xb7, 0x2c, 0xb3, 0xd3, 0xde, 0xdd, 0x6b, 0x2e, 0xb0, 0x25, 0x68, 0xcc, 0xe2, 0x15, 0x45, - 0x13, 0x0a, 0xef, 0x60, 0xbf, 0x7b, 0xb0, 0x6f, 0x7d, 0xd2, 0x31, 0x7b, 0xdd, 0x83, 0xfd, 0x66, - 0x89, 0xad, 0x02, 0x4b, 0x16, 0xed, 0xec, 0xb5, 0x37, 0x9b, 0x65, 0xb6, 0x02, 0x8b, 0x49, 0xf8, - 0xf3, 0xce, 0x67, 0x4d, 0x60, 0x2d, 0x58, 0xa6, 0x81, 0x59, 0x1b, 0x9d, 0xdd, 0x83, 0x4f, 0xad, - 0xbd, 0xee, 0x7e, 0x77, 0xef, 0x68, 0xaf, 0x59, 0xc1, 0x47, 0x98, 0x3a, 0x1d, 0xab, 0xbb, 0xdf, - 0x3b, 0xda, 0xde, 0xee, 0x6e, 0x76, 0x3b, 0xfb, 0xfd, 0x66, 0x95, 0x7a, 0x4e, 0x9b, 0x78, 0x4d, - 0x54, 0x90, 0x39, 0x03, 0xd6, 0x56, 0xb7, 0xd7, 0xde, 0xd8, 0xed, 0x6c, 0x35, 0xeb, 0xec, 0x0e, - 0xdc, 0xec, 0x77, 0xf6, 0x0e, 0x0f, 0xcc, 0xb6, 0xf9, 0x99, 0xca, 0x29, 0xb0, 0xb6, 0xdb, 0xdd, - 0xdd, 0x23, 0xb3, 0xd3, 0x6c, 0xb0, 0x37, 0xe1, 0x8e, 0xd9, 0xf9, 0xf8, 0xa8, 0x6b, 0x76, 0xb6, - 0xac, 0xfd, 0x83, 0xad, 0x8e, 0xb5, 0xdd, 0x69, 0xf7, 0x8f, 0xcc, 0x8e, 0xb5, 0xd7, 0xed, 0xf5, - 0xba, 0xfb, 0xcf, 0x9a, 0x4d, 0xf6, 0x36, 0xdc, 0x8b, 0x50, 0xa2, 0x06, 0x66, 0xb0, 0x16, 0xc5, - 0xfc, 0xd4, 0x96, 0xee, 0x77, 0x7e, 0xad, 0x6f, 0x1d, 0x76, 0x3a, 0x66, 0x93, 0xb1, 0x75, 0x58, - 0x8d, 0xbb, 0xa7, 0x0e, 0x64, 0xdf, 0x4b, 0xa2, 0xec, 0xb0, 0x63, 0xee, 0xb5, 0xf7, 0xc5, 0x06, - 0x27, 0xca, 0x96, 0xc5, 0xb0, 0xe3, 0xb2, 0xd9, 0x61, 0xaf, 0x30, 0x06, 0x75, 0x6d, 0x57, 0xb6, - 0xdb, 0x66, 0x73, 0x95, 0x35, 0xa0, 0xb2, 0x77, 0x78, 0x68, 0xf5, 0xbb, 0x7b, 0x9d, 0x83, 0xa3, - 0x7e, 0x73, 0x8d, 0xad, 0x40, 0xb3, 0xbb, 0xdf, 0xef, 0x98, 0x62, 0xaf, 0x55, 0xd5, 0xff, 0x5d, - 0x64, 0xcb, 0xd0, 0x50, 0x23, 0x55, 0xd0, 0xbf, 0x2a, 0xb2, 0x35, 0x60, 0x47, 0xfb, 0x66, 0xa7, - 0xbd, 0x25, 0x16, 0x2e, 0x2a, 0xf8, 0x3f, 0x45, 0xe9, 0x21, 0xf9, 0x59, 0x2e, 0xba, 0xac, 0xe3, - 0x90, 0x83, 0xe4, 0x43, 0xa5, 0x55, 0xed, 0x81, 0xd1, 0x57, 0x3d, 0x21, 0xae, 0xa9, 0x56, 0xb9, - 0x39, 0xd5, 0x6a, 0x4e, 0x77, 0xaf, 0xe9, 0xb2, 0xdf, 0x5b, 0x50, 0x1b, 0xd3, 0xa3, 0xa5, 0xf2, - 0x71, 0x42, 0x90, 0xf1, 0x37, 0x04, 0xa4, 0x97, 0x09, 0xe7, 0xde, 0xd0, 0x2e, 0xcc, 0xbf, 0xa1, - 0x9d, 0x26, 0xdf, 0x2f, 0xa4, 0xc9, 0xf7, 0x0f, 0x61, 0x91, 0x58, 0x93, 0xe3, 0x3a, 0x63, 0xa5, - 0x35, 0x93, 0x14, 0xd8, 0x40, 0x16, 0x45, 0x70, 0xa5, 0x4e, 0x28, 0x95, 0x43, 0xb2, 0x90, 0xa2, - 0xd4, 0x36, 0x12, 0x9a, 0x06, 0x71, 0x8e, 0x48, 0xd3, 0x88, 0x7a, 0xb0, 0x2f, 0xe3, 0x1e, 0x2a, - 0x5a, 0x0f, 0x04, 0xc7, 0x1e, 0x1e, 0xc2, 0x22, 0xbf, 0x0c, 0x7d, 0xdb, 0xf2, 0x26, 0xf6, 0xe7, - 0x53, 0x74, 0xe1, 0xda, 0xa8, 0xc3, 0x57, 0xcd, 0x06, 0x16, 0x1c, 0x20, 0x7c, 0xcb, 0x0e, 0xed, - 0x87, 0x5f, 0x42, 0x45, 0x7b, 0xd0, 0x96, 0xad, 0xc1, 0xd2, 0xa7, 0xdd, 0xfe, 0x7e, 0xa7, 0xd7, - 0xb3, 0x0e, 0x8f, 0x36, 0x9e, 0x77, 0x3e, 0xb3, 0x76, 0xda, 0xbd, 0x9d, 0xe6, 0x0d, 0x71, 0x68, - 0xf7, 0x3b, 0xbd, 0x7e, 0x67, 0x2b, 0x01, 0xcf, 0xb0, 0x37, 0x60, 0xfd, 0x68, 0xff, 0xa8, 0xd7, - 0xd9, 0xb2, 0xd2, 0xea, 0x65, 0x05, 0x95, 0xca, 0xf2, 0x94, 0xea, 0xb9, 0x87, 0x3f, 0x84, 0x7a, - 0xf2, 0x95, 0x45, 0x06, 0xb0, 0xb0, 0xdb, 0x79, 0xd6, 0xde, 0xfc, 0x8c, 0x9e, 0x69, 0xeb, 0xf5, - 0xdb, 0xfd, 0xee, 0xa6, 0x25, 0x9f, 0x65, 0x13, 0x1c, 0x21, 0xc3, 0x2a, 0x50, 0x6c, 0xef, 0x6f, - 0xee, 0x1c, 0x98, 0xbd, 0x66, 0xf6, 0xe1, 0x47, 0xd0, 0x9c, 0xf5, 0x47, 0x25, 0x1c, 0x78, 0x2f, - 0xf3, 0xf4, 0x3d, 0xfc, 0x77, 0x39, 0x80, 0x38, 0x61, 0x40, 0xb0, 0x9a, 0xad, 0x76, 0xbf, 0xbd, - 0x7b, 0x20, 0xa6, 0x61, 0x1e, 0xf4, 0x05, 0x07, 0x31, 0x3b, 0x1f, 0x37, 0x6f, 0xa4, 0x96, 0x1c, - 0x1c, 0xf6, 0x9b, 0x19, 0xb1, 0x62, 0xdd, 0xfd, 0x6e, 0xbf, 0xdb, 0xde, 0xb5, 0xcc, 0x83, 0xa3, - 0xee, 0xfe, 0x33, 0x7a, 0xb0, 0x0a, 0xb9, 0xec, 0xd1, 0xe1, 0xb6, 0x79, 0xb0, 0xdf, 0xb7, 0x7a, - 0x3b, 0x47, 0xfd, 0x2d, 0x7c, 0xee, 0x6a, 0xd3, 0xec, 0x1e, 0x52, 0x9b, 0xf9, 0x97, 0x21, 0x88, - 0xa6, 0x0b, 0x62, 0xcd, 0x9f, 0x1d, 0xf4, 0x7a, 0xdd, 0x43, 0xeb, 0xe3, 0xa3, 0x8e, 0xd9, 0xed, - 0xf4, 0xb0, 0xe2, 0x42, 0x0a, 0x5c, 0xe0, 0x17, 0x05, 0x6f, 0xee, 0xef, 0x7e, 0x22, 0x99, 0xa7, - 0x40, 0x2d, 0x25, 0x41, 0x02, 0xab, 0x2c, 0x78, 0x8a, 0xe0, 0x3e, 0x29, 0x2d, 0xc3, 0x35, 0x65, - 0xa2, 0x5e, 0x45, 0xf0, 0xd5, 0xb9, 0xcd, 0xc0, 0x6a, 0xd5, 0xf4, 0x22, 0x51, 0x0b, 0x59, 0x6e, - 0x74, 0x41, 0x6d, 0x6d, 0x99, 0x58, 0xa1, 0x3e, 0x07, 0x15, 0xb8, 0x0d, 0xb1, 0x51, 0x82, 0x3d, - 0x09, 0x94, 0xa6, 0xfa, 0x10, 0x25, 0x8b, 0x4f, 0x7f, 0x3b, 0x07, 0x75, 0x4a, 0xde, 0xa2, 0xdf, - 0x13, 0xe2, 0x3e, 0xdb, 0x83, 0xa2, 0xfc, 0x61, 0x2a, 0xb6, 0x12, 0x3d, 0x5b, 0xa4, 0xff, 0x14, - 0xd6, 0xfa, 0xea, 0x2c, 0x58, 0x8a, 0x63, 0x4b, 0x7f, 0xfb, 0x4f, 0xfe, 0xf2, 0x9f, 0x64, 0x6b, - 0xac, 0xf2, 0xf8, 0xfc, 0xbd, 0xc7, 0xa7, 0xdc, 0x0d, 0x44, 0x1b, 0x7f, 0x03, 0x20, 0xfe, 0xb9, - 0x25, 0xd6, 0x8a, 0x9c, 0x50, 0x33, 0xbf, 0x45, 0xb5, 0x7e, 0x33, 0xa5, 0x44, 0xb6, 0x7b, 0x13, - 0xdb, 0x5d, 0x32, 0xea, 0xa2, 0x5d, 0xc7, 0x75, 0x42, 0xfa, 0xe9, 0xa5, 0x0f, 0x33, 0x0f, 0xd9, - 0x10, 0xaa, 0xfa, 0x0f, 0x21, 0x31, 0x25, 0x29, 0xa5, 0xfc, 0x94, 0xd3, 0xfa, 0xad, 0xd4, 0x32, - 0x25, 0x83, 0x62, 0x1f, 0x2b, 0x46, 0x53, 0xf4, 0x31, 0x45, 0x8c, 0xb8, 0x97, 0x11, 0x49, 0xe5, - 0xf1, 0xef, 0x1d, 0xb1, 0xdb, 0x9a, 0x5c, 0x35, 0xf7, 0x6b, 0x4b, 0xeb, 0x77, 0xae, 0x29, 0x95, - 0x7d, 0xdd, 0xc1, 0xbe, 0xd6, 0x0c, 0x26, 0xfa, 0x1a, 0x20, 0x8e, 0xfa, 0xb5, 0xa5, 0x0f, 0x33, - 0x0f, 0x9f, 0xfe, 0xc5, 0x03, 0x28, 0x47, 0xc1, 0x9c, 0xec, 0x37, 0xa1, 0x96, 0xc8, 0xae, 0x63, - 0x6a, 0x1a, 0x69, 0xc9, 0x78, 0xeb, 0xb7, 0xd3, 0x0b, 0x65, 0xc7, 0x6f, 0x60, 0xc7, 0x2d, 0xb6, - 0x2a, 0x3a, 0x96, 0xd9, 0x6b, 0x8f, 0x31, 0x07, 0x95, 0x1e, 0x81, 0x7a, 0xa1, 0x69, 0x1f, 0xd4, - 0xd9, 0xed, 0x59, 0x8d, 0x20, 0xd1, 0xdb, 0x9d, 0x6b, 0x4a, 0x65, 0x77, 0xb7, 0xb1, 0xbb, 0x55, - 0xb6, 0xac, 0x77, 0xa7, 0x42, 0x2f, 0x19, 0xc7, 0x87, 0xd7, 0xf4, 0x9f, 0x03, 0x62, 0x77, 0xe2, - 0x67, 0xb2, 0x52, 0x7e, 0x26, 0x28, 0x22, 0x91, 0xf9, 0xdf, 0x0a, 0x32, 0x5a, 0xd8, 0x15, 0x63, - 0xb8, 0x7d, 0xfa, 0xaf, 0x01, 0xb1, 0x63, 0xa8, 0x68, 0x2f, 0xe8, 0xb3, 0x9b, 0xd7, 0xbe, 0xf6, - 0xbf, 0xbe, 0x9e, 0x56, 0x94, 0x36, 0x15, 0xbd, 0xfd, 0xc7, 0x27, 0x9c, 0xb3, 0x5f, 0x87, 0x72, - 0xf4, 0x2e, 0x3b, 0x5b, 0xd3, 0xde, 0xc9, 0xd7, 0xdf, 0x91, 0x5f, 0x6f, 0xcd, 0x17, 0xa4, 0x11, - 0x9f, 0xde, 0xba, 0x20, 0xbe, 0x4f, 0xa1, 0xa2, 0xbd, 0xbd, 0x1e, 0x4d, 0x60, 0xfe, 0x7d, 0xf7, - 0x68, 0x02, 0x29, 0x4f, 0xb5, 0x1b, 0x8b, 0xd8, 0x45, 0x85, 0x95, 0x91, 0xbe, 0xc3, 0x4b, 0x2f, - 0x60, 0xbb, 0xb0, 0x22, 0x35, 0xad, 0x63, 0xfe, 0x55, 0xb6, 0x21, 0xe5, 0x17, 0x98, 0x9e, 0x64, - 0xd8, 0x47, 0x50, 0x52, 0x4f, 0xec, 0xb3, 0xd5, 0xf4, 0x9f, 0x0a, 0x58, 0x5f, 0x9b, 0x83, 0x4b, - 0xb5, 0xe8, 0x33, 0x80, 0xf8, 0xa1, 0xf7, 0x88, 0x49, 0xcc, 0x3d, 0x1c, 0x1f, 0x51, 0xc0, 0xfc, - 0xab, 0xf0, 0xc6, 0x2a, 0x4e, 0xb0, 0xc9, 0x90, 0x49, 0xb8, 0xfc, 0x42, 0xbd, 0x40, 0xf9, 0x13, - 0xa8, 0x68, 0x6f, 0xbd, 0x47, 0xcb, 0x37, 0xff, 0x4e, 0x7c, 0xb4, 0x7c, 0x29, 0x4f, 0xc3, 0x1b, - 0xeb, 0xd8, 0xfa, 0xb2, 0xd1, 0x10, 0xad, 0x0b, 0x51, 0x4b, 0x8a, 0x3c, 0x62, 0x83, 0xce, 0xa0, - 0x96, 0x78, 0xd0, 0x3d, 0x3a, 0xa1, 0x69, 0xcf, 0xc5, 0x47, 0x27, 0x34, 0xf5, 0x0d, 0x78, 0x45, - 0x67, 0xc6, 0xa2, 0xe8, 0xe7, 0x1c, 0x51, 0xb4, 0x9e, 0x7e, 0x0c, 0x15, 0xed, 0x71, 0xf6, 0x68, - 0x2e, 0xf3, 0xef, 0xc0, 0x47, 0x73, 0x49, 0x7b, 0xcb, 0x7d, 0x19, 0xfb, 0xa8, 0x1b, 0x48, 0x0a, - 0xf8, 0xbe, 0x9f, 0x68, 0xfb, 0x37, 0xa1, 0x9e, 0x7c, 0xaf, 0x3d, 0x3a, 0xfb, 0xa9, 0x0f, 0xbf, - 0x47, 0x67, 0xff, 0x9a, 0x47, 0xde, 0x25, 0x49, 0x3f, 0x5c, 0x8a, 0x3a, 0x79, 0xfc, 0x85, 0x4c, - 0x4b, 0xf9, 0x92, 0x7d, 0x2c, 0x18, 0x9c, 0x7c, 0x5e, 0x92, 0xad, 0x69, 0x54, 0xab, 0x3f, 0x42, - 0x19, 0x9d, 0x97, 0xb9, 0x97, 0x28, 0x93, 0xc4, 0x8c, 0x8d, 0xb3, 0x67, 0xb0, 0x14, 0x11, 0x73, - 0xf4, 0x5e, 0x64, 0x10, 0xcd, 0x21, 0xf5, 0x55, 0xca, 0xf5, 0xe6, 0x6c, 0xe9, 0x93, 0x0c, 0x5d, - 0x7f, 0xf8, 0x4a, 0x9f, 0x76, 0xfd, 0xe9, 0x4f, 0x46, 0x6a, 0xd7, 0x5f, 0xe2, 0x31, 0xbf, 0xd9, - 0xeb, 0x2f, 0x74, 0x44, 0x1b, 0x2e, 0x34, 0x66, 0x5f, 0x6f, 0xbc, 0x73, 0xdd, 0xdb, 0x05, 0xd4, - 0xfc, 0x1b, 0x2f, 0x7f, 0xda, 0x20, 0xc9, 0x8a, 0x14, 0x37, 0x7d, 0x2c, 0x83, 0x4f, 0xd8, 0x6f, - 0x40, 0x55, 0x7f, 0x2c, 0x9a, 0xe9, 0x3c, 0x61, 0xb6, 0xa7, 0x5b, 0xa9, 0x65, 0x49, 0x2a, 0x61, - 0x55, 0xbd, 0x1b, 0xf6, 0x09, 0xac, 0x46, 0xcb, 0xac, 0xe7, 0xad, 0x07, 0xec, 0x6e, 0x4a, 0x36, - 0x7b, 0x62, 0xb1, 0x6f, 0x5e, 0x9b, 0xee, 0xfe, 0x24, 0x23, 0xa8, 0x2f, 0xf9, 0x6a, 0x6d, 0x7c, - 0xf3, 0xa4, 0x3d, 0xd6, 0x1b, 0xdf, 0x3c, 0xa9, 0x4f, 0xdd, 0x2a, 0xea, 0x63, 0x4b, 0x89, 0x35, - 0xa2, 0xb0, 0x5c, 0xf6, 0x63, 0x68, 0x68, 0x49, 0xf9, 0xbd, 0x2b, 0x77, 0x10, 0x9d, 0xa4, 0xf9, - 0x27, 0xe1, 0xd6, 0xd3, 0x6c, 0x93, 0xc6, 0x1a, 0xb6, 0xbf, 0x68, 0x24, 0x16, 0x47, 0x9c, 0xa2, - 0x4d, 0xa8, 0xe8, 0x09, 0xff, 0x2f, 0x69, 0x77, 0x4d, 0x2b, 0xd2, 0x5f, 0x1f, 0x7b, 0x92, 0x61, - 0xbb, 0xd0, 0x9c, 0x7d, 0x2c, 0x29, 0xe2, 0x29, 0x69, 0x0f, 0x3c, 0xad, 0xcf, 0x14, 0x26, 0x9e, - 0x58, 0x62, 0x87, 0x94, 0xd8, 0x11, 0xfd, 0x5c, 0x91, 0xe7, 0xcf, 0xde, 0xea, 0xc9, 0x9f, 0x31, - 0x8a, 0x5a, 0x4b, 0xfb, 0x01, 0xab, 0x07, 0x99, 0x27, 0x19, 0xf6, 0xbb, 0x19, 0xa8, 0x26, 0x1e, - 0x28, 0x49, 0x84, 0xce, 0xcf, 0xcc, 0xb3, 0xa5, 0x97, 0xe9, 0x13, 0x35, 0x4c, 0x5c, 0xc4, 0xdd, - 0x87, 0x3f, 0x4a, 0x6c, 0xd2, 0x17, 0x09, 0xd7, 0xde, 0xa3, 0xd9, 0xdf, 0x33, 0xfa, 0x72, 0x16, - 0x41, 0x7f, 0xe9, 0xef, 0xcb, 0x27, 0x19, 0xf6, 0x1f, 0x32, 0x50, 0x4f, 0xfa, 0xec, 0xa3, 0xe9, - 0xa6, 0x46, 0x07, 0x44, 0xa4, 0x74, 0x8d, 0xa3, 0xff, 0xc7, 0x38, 0xca, 0xfe, 0x43, 0x33, 0x31, - 0x4a, 0xf9, 0xde, 0xf2, 0xcf, 0x37, 0x5a, 0xf6, 0x21, 0xfd, 0x7c, 0xa0, 0x0a, 0x65, 0x62, 0xf3, - 0x3f, 0x37, 0x17, 0x91, 0x9f, 0xfe, 0xe3, 0x6c, 0xb8, 0x09, 0x3f, 0xa1, 0xdf, 0xed, 0x51, 0x91, - 0x31, 0x82, 0x8a, 0x5f, 0xb7, 0xbe, 0xf1, 0x36, 0xce, 0xe9, 0x0d, 0xe3, 0x66, 0x62, 0x4e, 0xb3, - 0x82, 0x47, 0x9b, 0x46, 0x27, 0x7f, 0x5b, 0x2d, 0xbe, 0x39, 0xe7, 0x7e, 0x6f, 0xed, 0xfa, 0x41, - 0x8e, 0x69, 0x90, 0x12, 0x3d, 0x71, 0xd4, 0x5e, 0xb3, 0x19, 0xe3, 0x21, 0x8e, 0xf5, 0x6d, 0xe3, - 0xee, 0xb5, 0x63, 0x7d, 0x8c, 0xfe, 0x77, 0x31, 0xe2, 0x43, 0x80, 0x38, 0xd4, 0x90, 0xcd, 0x04, - 0xbc, 0x45, 0x0c, 0x68, 0x3e, 0x1a, 0x31, 0x79, 0x9e, 0x55, 0x5c, 0x9c, 0x68, 0xf1, 0xd7, 0x89, - 0x9d, 0x46, 0xa1, 0x78, 0xba, 0xf4, 0x95, 0x8c, 0x0a, 0x4c, 0x48, 0x5f, 0xb3, 0xed, 0x27, 0x98, - 0x69, 0x14, 0x77, 0x77, 0x04, 0xb5, 0x5d, 0xcf, 0x7b, 0x31, 0x9d, 0x44, 0xe1, 0xed, 0xc9, 0xa0, - 0x98, 0x1d, 0x3b, 0x38, 0x5b, 0x9f, 0x99, 0x85, 0x71, 0x0f, 0x9b, 0x5a, 0x67, 0x2d, 0xad, 0xa9, - 0xc7, 0x5f, 0xc4, 0xf1, 0x8d, 0x5f, 0x32, 0x1b, 0x16, 0x23, 0x1e, 0x1d, 0xc7, 0x10, 0x26, 0x9b, - 0x49, 0x70, 0xe6, 0xd9, 0x2e, 0x12, 0x6a, 0x82, 0x1a, 0xed, 0xe3, 0x40, 0xb5, 0xf9, 0x24, 0xc3, - 0x0e, 0xa1, 0xba, 0xc5, 0x07, 0x98, 0xa8, 0x8f, 0xa1, 0x25, 0x4b, 0x89, 0x30, 0x05, 0x8a, 0x49, - 0x59, 0xaf, 0x25, 0x80, 0xc9, 0x7b, 0x6b, 0x62, 0x5f, 0xf9, 0xfc, 0xf3, 0xc7, 0x5f, 0xc8, 0xa0, - 0x95, 0x2f, 0xd5, 0xbd, 0xa5, 0x82, 0x7a, 0x12, 0xf7, 0xd6, 0x4c, 0x14, 0x50, 0xe2, 0xde, 0x9a, - 0x8b, 0x02, 0x4a, 0x2c, 0xb5, 0x0a, 0x2a, 0x62, 0x23, 0x58, 0x9c, 0x0b, 0x1c, 0x8a, 0xae, 0xac, - 0xeb, 0xc2, 0x8d, 0xd6, 0xef, 0x5d, 0x8f, 0x90, 0xec, 0xed, 0x61, 0xb2, 0xb7, 0x1e, 0xd4, 0xe8, - 0xf1, 0xc1, 0x63, 0x4e, 0x29, 0x7b, 0x33, 0xef, 0xdd, 0xe8, 0xf9, 0x80, 0xb3, 0x17, 0x0c, 0x96, - 0x25, 0x25, 0x1c, 0xcc, 0x95, 0x63, 0xbf, 0x0e, 0x95, 0x67, 0x3c, 0x54, 0x39, 0x7a, 0x91, 0x8c, - 0x3d, 0x93, 0xb4, 0xb7, 0x9e, 0x92, 0xe2, 0x97, 0xa4, 0x19, 0x6c, 0xed, 0x31, 0x1f, 0x9e, 0x72, - 0x62, 0x4e, 0x96, 0x33, 0xfc, 0x92, 0xfd, 0x1a, 0x36, 0x1e, 0xa5, 0x46, 0xaf, 0x6a, 0x49, 0x58, - 0x7a, 0xe3, 0x8d, 0x19, 0x78, 0x5a, 0xcb, 0xae, 0x37, 0xe4, 0x9a, 0xac, 0xe7, 0x42, 0x45, 0x7b, - 0x42, 0x21, 0x3a, 0x40, 0xf3, 0x4f, 0x66, 0x44, 0x07, 0x28, 0xe5, 0xc5, 0x05, 0xe3, 0x01, 0xf6, - 0x63, 0xb0, 0x7b, 0x71, 0x3f, 0xf4, 0xca, 0x42, 0xdc, 0xd3, 0xe3, 0x2f, 0xec, 0x71, 0xf8, 0x25, - 0xfb, 0x14, 0x9f, 0xf8, 0xd6, 0x73, 0x10, 0x63, 0xa5, 0x61, 0x36, 0x5d, 0x31, 0x5a, 0x2c, 0xad, - 0x28, 0xa9, 0x48, 0x50, 0x57, 0x28, 0xc9, 0xbd, 0x0f, 0xd0, 0x0b, 0xbd, 0xc9, 0x96, 0xcd, 0xc7, - 0x9e, 0x1b, 0xf3, 0xda, 0x38, 0x2b, 0x2e, 0xe6, 0x5f, 0x5a, 0x6a, 0x1c, 0xfb, 0x54, 0xd3, 0xb2, - 0x12, 0x69, 0x9c, 0x8a, 0xb8, 0xae, 0x4d, 0x9c, 0x8b, 0x16, 0x24, 0x25, 0x79, 0xee, 0x49, 0x86, - 0xb5, 0x01, 0xe2, 0xc8, 0xb1, 0x48, 0x67, 0x9a, 0x0b, 0x4a, 0x8b, 0xd8, 0x5e, 0x4a, 0x98, 0xd9, - 0x21, 0x94, 0xe3, 0x90, 0x9b, 0xb5, 0xf8, 0x45, 0x98, 0x44, 0x80, 0x4e, 0x74, 0x83, 0xcf, 0x85, - 0xbb, 0x18, 0x4d, 0x5c, 0x2a, 0x60, 0x25, 0xb1, 0x54, 0x27, 0x9c, 0x07, 0xcc, 0x81, 0x25, 0x1a, - 0x60, 0x24, 0x2e, 0x61, 0x36, 0x57, 0xf4, 0x92, 0xfb, 0x7c, 0xe4, 0x49, 0x74, 0x9a, 0x53, 0xe3, - 0x27, 0x12, 0xa6, 0x1f, 0x41, 0xad, 0x94, 0x49, 0x26, 0x58, 0xf3, 0x18, 0x16, 0xe7, 0x5c, 0xf4, - 0xd1, 0x91, 0xbe, 0x2e, 0xe6, 0x22, 0x3a, 0xd2, 0xd7, 0x7a, 0xf7, 0x8d, 0x15, 0xec, 0xb2, 0x61, - 0x00, 0xaa, 0x7a, 0x17, 0x4e, 0x38, 0x38, 0x13, 0xdd, 0xfd, 0xdb, 0x0c, 0x2c, 0xa5, 0x38, 0xe1, - 0xd9, 0x9b, 0xca, 0x6a, 0x70, 0xad, 0x83, 0x7e, 0x3d, 0xd5, 0x59, 0x6b, 0xf4, 0xb0, 0x9f, 0x3d, - 0xf6, 0x3c, 0x71, 0xb1, 0x91, 0xaf, 0x54, 0x9e, 0xcc, 0x97, 0x0a, 0x15, 0xa9, 0x12, 0xc5, 0xe7, - 0xb0, 0x46, 0x03, 0x69, 0x8f, 0x46, 0x33, 0x8e, 0xe4, 0x37, 0xe6, 0x7e, 0x5e, 0x3c, 0xe1, 0x1c, - 0x5f, 0xbf, 0xfe, 0xe7, 0xc7, 0xaf, 0x11, 0xa7, 0x69, 0xa8, 0x6c, 0x0a, 0xcd, 0x59, 0x07, 0x2d, - 0xbb, 0xbe, 0xad, 0xf5, 0xbb, 0x09, 0xfd, 0x37, 0xc5, 0xa9, 0xfb, 0x0d, 0xec, 0xec, 0xae, 0xb1, - 0x9e, 0xb6, 0x2e, 0xa4, 0x12, 0x8b, 0xfd, 0xf8, 0x5b, 0x91, 0x37, 0x79, 0x66, 0x9e, 0xaa, 0x83, - 0xeb, 0x7c, 0xdf, 0x91, 0x06, 0x9e, 0xee, 0x8c, 0x7e, 0x07, 0xbb, 0xbf, 0x67, 0xdc, 0x4a, 0xeb, - 0xde, 0xa7, 0x2a, 0xa4, 0x8b, 0xaf, 0xcd, 0x9e, 0x6b, 0x35, 0x82, 0x7b, 0x69, 0xfb, 0x7d, 0xad, - 0x2e, 0x34, 0xb3, 0xd6, 0x37, 0x50, 0xb6, 0xab, 0xea, 0xde, 0xe3, 0xe8, 0xf8, 0xa4, 0xb8, 0xa9, - 0xa3, 0xe3, 0x93, 0xe6, 0x6e, 0x4e, 0xca, 0x35, 0xca, 0xd1, 0xfc, 0x61, 0xe6, 0xe1, 0xc6, 0xfd, - 0x1f, 0x7f, 0xe3, 0xd4, 0x09, 0xcf, 0xa6, 0xc7, 0x8f, 0x06, 0xde, 0xf8, 0xf1, 0x48, 0x59, 0x1b, - 0x65, 0xca, 0xf3, 0xe3, 0x91, 0x3b, 0x7c, 0x8c, 0xcd, 0x1e, 0x2f, 0x4c, 0x7c, 0x2f, 0xf4, 0xbe, - 0xf3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xac, 0x73, 0xd7, 0x79, 0x41, 0x81, 0x00, 0x00, + 0x10, 0xb5, 0x86, 0x25, 0xdf, 0x0c, 0x8c, 0xed, 0xcb, 0x18, 0x4b, 0x3e, 0x5c, 0xa1, 0x25, 0xca, + 0x47, 0x0f, 0x57, 0x48, 0x6d, 0x99, 0xe5, 0xe4, 0x85, 0x79, 0x4e, 0xfe, 0x6d, 0x58, 0x25, 0x4e, + 0x2e, 0x79, 0x84, 0x35, 0x43, 0x52, 0xcb, 0x58, 0x2a, 0x27, 0xa9, 0xc9, 0x5f, 0x4d, 0x31, 0x03, + 0x75, 0x3e, 0x02, 0xe7, 0xc7, 0x74, 0xa2, 0x32, 0xa6, 0x98, 0x99, 0x6c, 0xbc, 0xe7, 0xfc, 0x98, + 0x0b, 0x4c, 0x74, 0x8c, 0xea, 0x98, 0xf2, 0x89, 0xec, 0xd8, 0x71, 0x67, 0x31, 0xed, 0xcb, 0x24, + 0x66, 0x59, 0x62, 0xda, 0x97, 0x3a, 0xe6, 0x53, 0x58, 0x1b, 0xf3, 0xa1, 0x63, 0x27, 0x9b, 0xb5, + 0x62, 0x09, 0x62, 0x99, 0x8a, 0xb5, 0x3a, 0x3d, 0xd2, 0x20, 0xc5, 0x6a, 0xfc, 0xd8, 0x1b, 0x1f, + 0x3b, 0x74, 0x79, 0x92, 0xab, 0x36, 0x6f, 0xd6, 0xdd, 0xe9, 0xf8, 0x87, 0x08, 0x16, 0x55, 0x02, + 0xa3, 0x06, 0x95, 0x5e, 0xe8, 0x4d, 0xd4, 0x36, 0xd7, 0xa1, 0x4a, 0x9f, 0x32, 0xdc, 0xe4, 0x16, + 0xdc, 0x44, 0xda, 0xec, 0x7b, 0x13, 0x6f, 0xe4, 0x9d, 0x5e, 0x25, 0x0c, 0x4a, 0xff, 0x23, 0x03, + 0x4b, 0x89, 0x52, 0x79, 0xce, 0xbf, 0x4d, 0x07, 0x2b, 0x8a, 0x19, 0x20, 0x72, 0x5e, 0xd4, 0x2e, + 0x1f, 0x42, 0xa4, 0x53, 0xa5, 0xe2, 0x08, 0xda, 0x71, 0xac, 0xab, 0xaa, 0x48, 0xb4, 0xdd, 0x9a, + 0xa7, 0x6d, 0x59, 0x5f, 0x45, 0xc1, 0xaa, 0x26, 0xfe, 0xba, 0x7c, 0xc6, 0x3c, 0x94, 0x53, 0xce, + 0x25, 0x1f, 0x6a, 0xea, 0xc6, 0x27, 0x35, 0x82, 0xd8, 0x22, 0x15, 0x18, 0xff, 0x36, 0x03, 0x10, + 0x8f, 0x0e, 0x9f, 0x8a, 0x46, 0x17, 0x28, 0xa5, 0x91, 0xd1, 0x2e, 0xcb, 0xb7, 0xa0, 0x1a, 0xbd, + 0x18, 0x8b, 0xaf, 0xe4, 0x8a, 0x82, 0x89, 0x7b, 0xf9, 0x1e, 0x34, 0x4e, 0x47, 0xde, 0x31, 0x8a, + 0x4e, 0xf2, 0x02, 0xa5, 0xa0, 0x9b, 0x3a, 0x81, 0xd5, 0xb5, 0x18, 0x5f, 0xe0, 0xf9, 0xd4, 0x47, + 0x65, 0xfa, 0x75, 0x6c, 0xfc, 0x76, 0x36, 0x7a, 0x3a, 0x13, 0xaf, 0xc4, 0xcb, 0xf5, 0x8c, 0x9f, + 0xc7, 0x03, 0xfb, 0x32, 0xcf, 0xc3, 0x47, 0x50, 0xf7, 0x89, 0x3b, 0x2a, 0xd6, 0x99, 0x7f, 0x09, + 0xeb, 0xac, 0xf9, 0x89, 0x2b, 0xf7, 0xeb, 0xd0, 0xb4, 0x87, 0xe7, 0xdc, 0x0f, 0x1d, 0x34, 0xd6, + 0xa2, 0xa0, 0x26, 0x1f, 0xab, 0x68, 0x70, 0x94, 0x88, 0xee, 0x41, 0x43, 0x86, 0x40, 0x45, 0x98, + 0x32, 0xa9, 0x42, 0x0c, 0x16, 0x88, 0xc6, 0x7f, 0x50, 0x6f, 0x75, 0x92, 0xbb, 0xfb, 0xf2, 0x55, + 0xd1, 0x67, 0x98, 0x9d, 0xf7, 0xad, 0x48, 0x42, 0x92, 0x36, 0x60, 0xc9, 0x8f, 0x08, 0x28, 0x2d, + 0xc0, 0xc9, 0x65, 0xcd, 0xbf, 0xce, 0xb2, 0x1a, 0x7f, 0x9c, 0x81, 0xe2, 0x8e, 0x37, 0x11, 0x7a, + 0xb9, 0x90, 0xe7, 0xf0, 0x98, 0x44, 0xe1, 0x87, 0x0b, 0xe2, 0xb3, 0x3b, 0x7c, 0x79, 0xc8, 0x40, + 0xaa, 0xbc, 0x51, 0x4b, 0xca, 0x1b, 0xdf, 0x83, 0x5b, 0xe8, 0x8d, 0xf0, 0xbd, 0x89, 0xe7, 0x8b, + 0xa3, 0x6a, 0x8f, 0x48, 0xee, 0xf0, 0xdc, 0xf0, 0x4c, 0xf1, 0xce, 0x9b, 0x27, 0x9c, 0x1f, 0x6a, + 0x18, 0x7b, 0x11, 0x02, 0xc6, 0xd2, 0x8c, 0xc2, 0x73, 0x8b, 0x54, 0x45, 0x29, 0x18, 0x11, 0x47, + 0x6d, 0x88, 0x82, 0x0e, 0xc2, 0x51, 0x34, 0x32, 0xbe, 0x0b, 0xe5, 0xc8, 0xea, 0xc0, 0xde, 0x83, + 0xf2, 0x99, 0x37, 0x91, 0xa6, 0x89, 0x4c, 0x22, 0xac, 0x42, 0xce, 0xda, 0x2c, 0x9d, 0xd1, 0x1f, + 0x81, 0xf1, 0x67, 0x45, 0x28, 0x76, 0xdd, 0x73, 0xcf, 0x19, 0xe0, 0x6b, 0x9f, 0x31, 0x1f, 0x7b, + 0x2a, 0x0e, 0x53, 0xfc, 0x8d, 0x1e, 0xfd, 0x38, 0x35, 0x42, 0x4e, 0x7a, 0xf4, 0xa3, 0xa4, 0x08, + 0x2b, 0xb0, 0xe0, 0xeb, 0xb9, 0x0d, 0x0a, 0x3e, 0xbe, 0x3f, 0x8c, 0x94, 0xb6, 0x82, 0x16, 0xc7, + 0x2a, 0xda, 0xa2, 0x98, 0x7b, 0x5c, 0x32, 0x8a, 0x8b, 0x29, 0x23, 0x04, 0x17, 0xec, 0x0d, 0x28, + 0xca, 0x28, 0x06, 0x7a, 0x13, 0x4e, 0x0f, 0x06, 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0xe4, 0x4d, 0x8a, + 0x24, 0x2a, 0xa1, 0xa7, 0x4b, 0xe0, 0x96, 0xa0, 0xb5, 0x3b, 0x50, 0x21, 0x7c, 0x42, 0x29, 0xc9, + 0xf7, 0x39, 0x08, 0x42, 0x84, 0x94, 0x14, 0x21, 0xe5, 0xd4, 0x14, 0x21, 0xf8, 0x9c, 0x2b, 0xe2, + 0xb2, 0x34, 0x45, 0xa0, 0xc4, 0x10, 0x1a, 0x5c, 0xe5, 0xc7, 0x91, 0xca, 0x3d, 0x85, 0x89, 0x29, + 0xe5, 0xfe, 0x6d, 0xa8, 0x9d, 0xd8, 0xa3, 0xd1, 0xb1, 0x3d, 0x78, 0x41, 0x3a, 0x69, 0x95, 0xcc, + 0x70, 0x0a, 0x88, 0x4a, 0xe9, 0x1d, 0xa8, 0x68, 0xbb, 0x8c, 0x8f, 0x6f, 0xf2, 0x26, 0xc4, 0xfb, + 0x3b, 0x6b, 0x6a, 0xaa, 0xbf, 0x86, 0xa9, 0x49, 0x7b, 0x84, 0xd4, 0x48, 0x3e, 0x42, 0xba, 0x85, + 0xdc, 0x54, 0x3e, 0x54, 0x69, 0x52, 0x16, 0x02, 0x7b, 0x38, 0xc4, 0x87, 0x2a, 0x94, 0xf2, 0x0b, + 0x17, 0x8f, 0xca, 0x17, 0x49, 0xa8, 0x25, 0x18, 0xa1, 0xdc, 0x26, 0x7b, 0xe9, 0xc4, 0x76, 0x86, + 0xf8, 0xe8, 0x93, 0xd4, 0xd8, 0xa2, 0x3d, 0x0e, 0x0f, 0x6d, 0x67, 0xc8, 0xee, 0x42, 0x55, 0x15, + 0xe3, 0xed, 0xb8, 0x44, 0xeb, 0x2f, 0x8b, 0xc5, 0x9d, 0x68, 0x40, 0x2d, 0xc2, 0x18, 0xc7, 0xb1, + 0x5e, 0x15, 0x89, 0x82, 0x74, 0xf0, 0x3e, 0x3a, 0xff, 0x43, 0x8e, 0x11, 0x5d, 0xf5, 0x27, 0xb7, + 0xe4, 0x5c, 0x25, 0x95, 0xaa, 0xff, 0xf1, 0xa5, 0x83, 0x49, 0x98, 0x42, 0x10, 0x23, 0x17, 0xcd, + 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0xa2, 0x21, 0x04, 0xf6, 0x5d, 0x4d, 0x91, 0x6a, 0x21, 0xf2, + 0x1b, 0x33, 0xed, 0x5f, 0xf7, 0xe6, 0xfd, 0x36, 0x80, 0x13, 0x88, 0x5b, 0x26, 0xe0, 0xee, 0x10, + 0x83, 0xb3, 0x4a, 0x66, 0xd9, 0x09, 0x9e, 0x13, 0xe0, 0xab, 0xd5, 0xb0, 0xda, 0x50, 0xd5, 0xa7, + 0xc9, 0x4a, 0x90, 0x3f, 0x38, 0xec, 0xec, 0x37, 0x6f, 0xb0, 0x0a, 0x14, 0x7b, 0x9d, 0x7e, 0x7f, + 0xb7, 0xb3, 0xd5, 0xcc, 0xb0, 0x2a, 0x94, 0xa2, 0x10, 0x93, 0xac, 0xf8, 0x6a, 0x6f, 0x6e, 0x76, + 0x0e, 0xfb, 0x9d, 0xad, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, 0x99, 0x33, 0xfe, 0x3c, 0x07, 0x15, + 0x6d, 0x15, 0x5e, 0xce, 0x8c, 0x6f, 0x03, 0xa0, 0x4a, 0x13, 0xbf, 0x63, 0xca, 0x9b, 0x65, 0x01, + 0xa1, 0xcd, 0xd7, 0x8d, 0xe5, 0x39, 0x4a, 0x6f, 0xa1, 0x8c, 0xe5, 0x6f, 0x43, 0x8d, 0x32, 0x45, + 0xe8, 0xee, 0xba, 0x82, 0x59, 0x25, 0xa0, 0x64, 0xd5, 0x18, 0xa3, 0x86, 0x48, 0x18, 0xbd, 0x20, + 0xe3, 0xc6, 0x09, 0x84, 0xf1, 0x0b, 0x18, 0x7c, 0x12, 0x78, 0xa3, 0x73, 0x4e, 0x18, 0x24, 0x11, + 0x56, 0x24, 0xac, 0x2f, 0x83, 0xe4, 0x24, 0x3f, 0xd4, 0x82, 0xa4, 0x0a, 0x66, 0x95, 0x80, 0xb2, + 0xa3, 0x6f, 0x2a, 0x02, 0x2a, 0x21, 0x01, 0xad, 0xcd, 0x53, 0x43, 0x82, 0x78, 0x76, 0xe7, 0xec, + 0x59, 0x65, 0x24, 0x8c, 0xaf, 0xcd, 0xd7, 0x7b, 0xb5, 0x5d, 0x8b, 0xbd, 0x07, 0x6c, 0x3c, 0x99, + 0x58, 0x29, 0x96, 0xa6, 0xbc, 0xd9, 0x18, 0x4f, 0x26, 0x7d, 0xcd, 0x10, 0xf3, 0x15, 0x18, 0xc1, + 0x3e, 0x07, 0xd6, 0x16, 0x07, 0x18, 0x87, 0x18, 0x99, 0x50, 0x63, 0xb6, 0x9c, 0xd1, 0xd9, 0x72, + 0x0a, 0xf7, 0xcb, 0xa6, 0x72, 0xbf, 0x97, 0xf1, 0x09, 0x63, 0x1b, 0x2a, 0x87, 0x5a, 0x1e, 0x9a, + 0xbb, 0xe2, 0x86, 0x50, 0x19, 0x68, 0xe8, 0xee, 0x20, 0xe3, 0x96, 0x2f, 0x13, 0xcf, 0x68, 0xa3, + 0xc9, 0x6a, 0xa3, 0x31, 0xfe, 0x4d, 0x86, 0x62, 0xfc, 0xa3, 0xc1, 0xc7, 0xa9, 0x6f, 0x94, 0x1f, + 0x28, 0x8e, 0x65, 0xac, 0x28, 0xff, 0x8f, 0x0c, 0x43, 0xc4, 0xa1, 0x59, 0xde, 0xc9, 0x49, 0xc0, + 0x55, 0x54, 0x4e, 0x05, 0x61, 0x07, 0x08, 0x52, 0xc2, 0xb7, 0x90, 0xf0, 0x1d, 0x6a, 0x3f, 0x90, + 0xd1, 0x39, 0x42, 0xf8, 0xde, 0xb3, 0x2f, 0x65, 0xaf, 0x81, 0x10, 0x41, 0xa4, 0xa1, 0x5a, 0xc5, + 0x22, 0x45, 0xdf, 0xc6, 0xbf, 0x94, 0xe1, 0x96, 0xb3, 0xeb, 0xfb, 0x00, 0x4a, 0x51, 0xab, 0xc9, + 0x1b, 0x56, 0x61, 0x46, 0xe5, 0xe2, 0x1e, 0x47, 0xad, 0x3c, 0x31, 0x62, 0x3a, 0x5c, 0xe8, 0x6c, + 0xe8, 0x6a, 0xa3, 0xfe, 0x06, 0xb0, 0x13, 0xc7, 0x9f, 0x45, 0xa6, 0xc3, 0xd6, 0xc4, 0x12, 0x0d, + 0xdb, 0x38, 0x82, 0x25, 0xc5, 0x25, 0x34, 0x8d, 0x20, 0xb9, 0x79, 0x99, 0x57, 0x30, 0xf9, 0xec, + 0x1c, 0x93, 0x37, 0x7e, 0x9a, 0x87, 0xa2, 0xca, 0xe9, 0x94, 0x96, 0x87, 0xa8, 0x9c, 0xcc, 0x43, + 0xd4, 0x4a, 0xe4, 0xac, 0xc0, 0xad, 0x97, 0xf7, 0xfd, 0xbd, 0xd9, 0x2b, 0x5b, 0x33, 0x9a, 0x27, + 0xae, 0xed, 0x55, 0xc8, 0x4f, 0xec, 0xf0, 0x0c, 0x0d, 0x64, 0x44, 0x3c, 0xf8, 0xad, 0x8c, 0xe9, + 0x85, 0xa4, 0x31, 0x3d, 0x2d, 0x67, 0x13, 0x89, 0xa4, 0x73, 0x39, 0x9b, 0x6e, 0x01, 0xc9, 0x17, + 0xda, 0x7b, 0x98, 0x12, 0x02, 0xc4, 0x5d, 0x94, 0x14, 0x47, 0x4a, 0xb3, 0xe2, 0xc8, 0x6b, 0x8b, + 0x0a, 0xdf, 0x86, 0x05, 0x8a, 0x77, 0x96, 0x31, 0x57, 0xea, 0x42, 0x91, 0x6b, 0xa8, 0xfe, 0xa7, + 0x47, 0xb0, 0xa6, 0xc4, 0xd5, 0x13, 0xa0, 0x54, 0x12, 0x09, 0x50, 0x74, 0x23, 0x7f, 0x35, 0x69, + 0xe4, 0xbf, 0x0f, 0xcd, 0x68, 0x41, 0xd1, 0x64, 0xe6, 0x06, 0x32, 0xa2, 0xa3, 0xae, 0xe0, 0x82, + 0x4b, 0xee, 0x07, 0xf1, 0x85, 0x58, 0x4f, 0x5c, 0x88, 0x82, 0x87, 0xb5, 0xc3, 0x90, 0x8f, 0x27, + 0xa1, 0xbc, 0x10, 0xf1, 0xcd, 0xb7, 0x3e, 0xc0, 0x64, 0x34, 0x62, 0x0d, 0xca, 0xdd, 0x7d, 0x6b, + 0x7b, 0xb7, 0xfb, 0x6c, 0xa7, 0xdf, 0xcc, 0x88, 0xcf, 0xde, 0xd1, 0xe6, 0x66, 0xa7, 0xb3, 0x85, + 0x37, 0x0e, 0xc0, 0xc2, 0x76, 0xbb, 0x2b, 0x6e, 0x9f, 0x9c, 0xf1, 0xbb, 0x59, 0xa8, 0x68, 0xcd, + 0xb3, 0xa7, 0xd1, 0xaa, 0x50, 0x8e, 0x8c, 0xdb, 0xf3, 0x43, 0x78, 0xa8, 0x58, 0xb1, 0xb6, 0x2c, + 0x51, 0x86, 0xaa, 0xec, 0xb5, 0x19, 0xaa, 0xd8, 0xbb, 0xd0, 0xb0, 0xa9, 0x85, 0x68, 0x15, 0xa4, + 0x39, 0x58, 0x82, 0xe5, 0x22, 0xe0, 0x2b, 0xb0, 0xf8, 0x3e, 0x11, 0x78, 0x79, 0xf5, 0xf0, 0x2a, + 0xba, 0x52, 0x70, 0xb1, 0x8a, 0x27, 0xb6, 0x33, 0x9a, 0xfa, 0x5c, 0xba, 0x6f, 0xa3, 0x9b, 0x99, + 0xa0, 0xa6, 0x2a, 0x36, 0x3e, 0x00, 0x88, 0xc7, 0x9c, 0x5c, 0x9c, 0x1b, 0xc9, 0xc5, 0xc9, 0x68, + 0x8b, 0x93, 0x35, 0xb6, 0x88, 0x8d, 0xc8, 0x85, 0x8e, 0x3c, 0xd5, 0xdf, 0x04, 0x65, 0x91, 0xb2, + 0xf0, 0x1d, 0xe6, 0x64, 0xc4, 0x43, 0x15, 0xb7, 0xb9, 0x28, 0x4b, 0xba, 0x51, 0x81, 0x0a, 0xa3, + 0x8e, 0x5b, 0x89, 0xb9, 0x91, 0x24, 0xc9, 0x59, 0x6e, 0x24, 0x51, 0xcd, 0xa8, 0xdc, 0x58, 0x87, + 0xd6, 0x16, 0x17, 0xad, 0xb5, 0x47, 0xa3, 0x99, 0xe1, 0x18, 0xb7, 0xe0, 0x66, 0x4a, 0x99, 0x34, + 0x42, 0x7c, 0x0c, 0x2b, 0x6d, 0x0a, 0xd1, 0xfc, 0xaa, 0x62, 0x31, 0x8c, 0x16, 0xac, 0xce, 0x36, + 0x29, 0x3b, 0xdb, 0x86, 0xc5, 0x2d, 0x7e, 0x3c, 0x3d, 0xdd, 0xe5, 0xe7, 0x71, 0x47, 0x0c, 0xf2, + 0xc1, 0x99, 0x77, 0x21, 0xd7, 0x07, 0xff, 0x16, 0x67, 0x78, 0x24, 0x70, 0xac, 0x60, 0xc2, 0x07, + 0xca, 0x22, 0x8a, 0x90, 0xde, 0x84, 0x0f, 0x8c, 0xa7, 0xc0, 0xf4, 0x76, 0xe4, 0x7a, 0x09, 0x2d, + 0x61, 0x7a, 0x6c, 0x05, 0x57, 0x41, 0xc8, 0xc7, 0x2a, 0x05, 0x0b, 0x04, 0xd3, 0xe3, 0x1e, 0x41, + 0x8c, 0x7b, 0x50, 0x3d, 0xb4, 0xaf, 0x4c, 0xfe, 0xb9, 0x8c, 0x32, 0x58, 0x83, 0xe2, 0xc4, 0xbe, + 0x12, 0x6c, 0x20, 0x72, 0x8e, 0x60, 0xb1, 0xf1, 0x07, 0x79, 0x58, 0x20, 0x4c, 0x76, 0x97, 0xb2, + 0x24, 0x3a, 0x2e, 0x1e, 0x43, 0xc5, 0x28, 0x35, 0xd0, 0x1c, 0x2f, 0xcd, 0xce, 0xf3, 0x52, 0x69, + 0x40, 0x53, 0xd9, 0x21, 0x94, 0x19, 0xdb, 0x9d, 0x8e, 0x55, 0x4a, 0x88, 0x64, 0x9c, 0x62, 0x3e, + 0xce, 0x82, 0x49, 0x41, 0x5c, 0x49, 0x47, 0x63, 0xac, 0x8b, 0xd0, 0xe8, 0xd4, 0x15, 0x21, 0xd9, + 0xa5, 0x0e, 0x4a, 0x55, 0x78, 0x8a, 0x2a, 0x7e, 0x25, 0xa9, 0xf0, 0xcc, 0x29, 0x36, 0xa5, 0x57, + 0x2b, 0x36, 0x64, 0x59, 0x7b, 0x89, 0x62, 0x03, 0xaf, 0xa1, 0xd8, 0xbc, 0x86, 0x93, 0xef, 0x26, + 0x94, 0xf0, 0xde, 0xd7, 0xb8, 0xa7, 0xb8, 0xef, 0x05, 0xf7, 0xfc, 0x8e, 0x26, 0xfa, 0xd3, 0x0b, + 0x83, 0x5b, 0xf1, 0x31, 0x31, 0xf9, 0xe7, 0xbf, 0x1c, 0xe7, 0xc9, 0x67, 0x50, 0x94, 0x50, 0x41, + 0xd0, 0xae, 0x3d, 0x56, 0x09, 0x76, 0xf0, 0x6f, 0xb1, 0x6c, 0x98, 0x15, 0xe4, 0xf3, 0xa9, 0xe3, + 0xf3, 0xa1, 0x4a, 0xc1, 0xe0, 0xe0, 0x19, 0x15, 0x10, 0x31, 0x41, 0xa1, 0x86, 0xb8, 0xde, 0x85, + 0x2b, 0x03, 0xb0, 0x8b, 0x4e, 0xf0, 0x5c, 0x7c, 0x1a, 0x0c, 0x9a, 0x98, 0x62, 0x6b, 0xe2, 0xf9, + 0xea, 0x72, 0x32, 0x7e, 0x9a, 0x81, 0xa6, 0x3c, 0x5d, 0x51, 0x99, 0xae, 0x05, 0x14, 0xae, 0x73, + 0x88, 0xbf, 0x3c, 0xa1, 0x82, 0x01, 0x35, 0x34, 0x7e, 0x44, 0x37, 0x15, 0x19, 0x6f, 0x2a, 0x02, + 0xb8, 0x2d, 0x6f, 0xab, 0x37, 0xa1, 0xa2, 0x9e, 0x63, 0x8e, 0x9d, 0x91, 0x4a, 0x78, 0x4b, 0xef, + 0x31, 0xf7, 0x9c, 0x91, 0xba, 0xe8, 0x7c, 0x5b, 0xc6, 0x53, 0x65, 0xf0, 0xa2, 0x33, 0xed, 0x90, + 0x1b, 0xff, 0x25, 0x03, 0x8b, 0xda, 0x54, 0xe4, 0xb9, 0xfd, 0x10, 0xaa, 0x51, 0x6e, 0x3b, 0x1e, + 0x49, 0x5e, 0x6b, 0x49, 0x46, 0x13, 0x57, 0xab, 0x0c, 0x22, 0x48, 0x20, 0x06, 0x33, 0xb4, 0xaf, + 0x70, 0xbc, 0xc1, 0x74, 0xac, 0x94, 0x9b, 0xa1, 0x7d, 0xb5, 0xcd, 0x79, 0x6f, 0x3a, 0x16, 0xaa, + 0xeb, 0x05, 0xe7, 0x2f, 0x22, 0x04, 0x92, 0xb9, 0x40, 0xc0, 0x24, 0x86, 0x01, 0xb5, 0xb1, 0xe7, + 0x86, 0x67, 0x11, 0x8a, 0x94, 0x3a, 0x11, 0x48, 0x38, 0xc6, 0x9f, 0x66, 0x61, 0x89, 0x4c, 0x6c, + 0xd2, 0xb4, 0x29, 0x59, 0x57, 0x0b, 0x16, 0xc8, 0xda, 0x48, 0xcc, 0x6b, 0xe7, 0x86, 0x29, 0xbf, + 0xd9, 0xb7, 0x5f, 0xd3, 0x2c, 0xa8, 0x42, 0xb6, 0xae, 0x59, 0xfe, 0xdc, 0xfc, 0xf2, 0x5f, 0xbf, + 0xbc, 0x69, 0x1e, 0xb7, 0x42, 0x9a, 0xc7, 0xed, 0x75, 0xfc, 0x5c, 0x73, 0x71, 0x4d, 0x45, 0x89, + 0xa3, 0xc5, 0x35, 0x3d, 0x85, 0xb5, 0x04, 0x0e, 0x72, 0x6b, 0xe7, 0xc4, 0xe1, 0x2a, 0xbe, 0x7d, + 0x59, 0xc3, 0xee, 0xa9, 0xb2, 0x8d, 0x22, 0x14, 0x82, 0x81, 0x37, 0xe1, 0xc6, 0x2a, 0x2c, 0x27, + 0x57, 0x55, 0x5e, 0x13, 0xbf, 0x97, 0x81, 0x96, 0x7c, 0x1f, 0xe1, 0xb8, 0xa7, 0x3b, 0x4e, 0x10, + 0x7a, 0x7e, 0x94, 0x03, 0xee, 0x36, 0x40, 0x10, 0xda, 0xbe, 0xd4, 0x36, 0x65, 0x44, 0x37, 0x42, + 0x50, 0x93, 0xbc, 0x09, 0x25, 0xee, 0x0e, 0xa9, 0x90, 0xa8, 0xa1, 0xc8, 0xdd, 0xa1, 0xd2, 0x43, + 0xe7, 0xe4, 0xef, 0x5a, 0x52, 0xbd, 0x90, 0x01, 0x96, 0x62, 0x75, 0xf8, 0x39, 0x5e, 0xbc, 0xf9, + 0x28, 0xc0, 0x72, 0xcf, 0xbe, 0xc4, 0xd7, 0x86, 0x81, 0xf1, 0xcf, 0xb2, 0xd0, 0x88, 0xc7, 0x47, + 0xd1, 0xd9, 0x2f, 0x8f, 0x33, 0xbf, 0x2b, 0xc9, 0xc1, 0x11, 0xf2, 0xbb, 0x66, 0x78, 0x2c, 0xd1, + 0xe1, 0xec, 0xba, 0xcc, 0x80, 0x8a, 0xc2, 0xf0, 0xa6, 0xa1, 0x96, 0x8a, 0xa9, 0x4c, 0x28, 0x07, + 0xd3, 0x50, 0x28, 0x5c, 0x42, 0xf3, 0x74, 0x5c, 0xa9, 0xf2, 0x14, 0xec, 0x71, 0xd8, 0xc5, 0x0c, + 0xcf, 0x02, 0x2c, 0xaa, 0xd1, 0x46, 0x0a, 0x2c, 0x81, 0xdf, 0x24, 0x39, 0x9b, 0x76, 0x0e, 0x65, + 0x6c, 0x5d, 0x08, 0xa5, 0x64, 0x97, 0x91, 0x10, 0xfa, 0x26, 0x54, 0xa8, 0xf1, 0x38, 0x8c, 0x2d, + 0x6f, 0x96, 0xb1, 0x07, 0x2c, 0x97, 0x46, 0x20, 0x6f, 0x9a, 0x50, 0x7d, 0x81, 0xba, 0xc2, 0xe7, + 0x07, 0xff, 0x28, 0x03, 0x37, 0x53, 0xb6, 0x4d, 0x9e, 0xf2, 0x4d, 0x58, 0x3c, 0x89, 0x0a, 0xd5, + 0xea, 0xd2, 0x51, 0x5f, 0x55, 0x6c, 0x35, 0xb9, 0xa6, 0x66, 0xf3, 0x24, 0x09, 0x88, 0x95, 0x2e, + 0xda, 0xc1, 0x44, 0xa4, 0x22, 0x2a, 0x5d, 0xb4, 0x8d, 0xa4, 0xef, 0x1c, 0xc2, 0x7a, 0xe7, 0x52, + 0x70, 0x8c, 0x4d, 0x3d, 0x45, 0xb9, 0x22, 0xa3, 0xa4, 0x81, 0x39, 0xf3, 0x5a, 0x06, 0xe6, 0x21, + 0x05, 0x64, 0x45, 0x6d, 0xfd, 0x3c, 0x8d, 0xe0, 0x05, 0x2a, 0xea, 0x50, 0x8a, 0x75, 0x15, 0x2d, + 0x39, 0x88, 0x52, 0xab, 0x1b, 0x01, 0x34, 0xf6, 0xa6, 0xa3, 0xd0, 0x89, 0xb3, 0xad, 0xb3, 0x6f, + 0xcb, 0x3a, 0xd8, 0x8f, 0x5a, 0xb5, 0xd4, 0x8e, 0x20, 0xea, 0x08, 0x17, 0x6b, 0x2c, 0x1a, 0xb2, + 0xe6, 0xfb, 0x6b, 0x8c, 0x93, 0x3d, 0x18, 0x37, 0x61, 0x2d, 0xfe, 0xa2, 0x65, 0x53, 0x57, 0xcd, + 0xbf, 0xce, 0xd0, 0xd3, 0xe6, 0x64, 0xe6, 0x77, 0xd6, 0x81, 0xa5, 0xc0, 0x71, 0x4f, 0x47, 0x5c, + 0x6f, 0x3e, 0x90, 0x8b, 0xb0, 0x92, 0x1c, 0x9b, 0xcc, 0x0e, 0x6f, 0x2e, 0x52, 0x8d, 0xb8, 0xb5, + 0x80, 0x6d, 0x5c, 0x37, 0xc8, 0x98, 0x2c, 0x66, 0x56, 0x63, 0x7e, 0xf0, 0x5d, 0xa8, 0x27, 0x3b, + 0x62, 0xdf, 0x91, 0xc1, 0x88, 0xf1, 0xa8, 0x72, 0x33, 0x71, 0x65, 0x31, 0x41, 0x54, 0xe2, 0xb5, + 0x0f, 0x8c, 0x7f, 0x92, 0x81, 0x96, 0xc9, 0x05, 0xe5, 0x6a, 0xa3, 0x54, 0x34, 0xf3, 0xe1, 0x5c, + 0xab, 0xd7, 0xcf, 0x55, 0xc5, 0x38, 0xaa, 0x11, 0x7d, 0xe3, 0xda, 0xcd, 0xd8, 0xb9, 0x31, 0x37, + 0xa3, 0x8d, 0x12, 0x2c, 0x10, 0x8a, 0xb1, 0x06, 0x2b, 0x72, 0x3c, 0x6a, 0x2c, 0xb1, 0xf7, 0x30, + 0xd1, 0x63, 0xc2, 0x7b, 0xb8, 0x0e, 0x2d, 0x4a, 0xe5, 0xa7, 0x4f, 0x42, 0x56, 0xdc, 0x02, 0xb6, + 0x67, 0x0f, 0x6c, 0xdf, 0xf3, 0xdc, 0x43, 0xee, 0xcb, 0x87, 0xa2, 0x28, 0x61, 0xa2, 0x73, 0x4d, + 0x89, 0xc2, 0xf4, 0xa5, 0x12, 0xd0, 0x79, 0xae, 0x7a, 0x17, 0x43, 0x5f, 0x86, 0x09, 0x4b, 0x1b, + 0xf6, 0x0b, 0xae, 0x5a, 0x52, 0x4b, 0xf4, 0x11, 0x54, 0x26, 0x51, 0xa3, 0x6a, 0xdd, 0x55, 0xc4, + 0xf2, 0x7c, 0xb7, 0xa6, 0x8e, 0x6d, 0x3c, 0x81, 0xe5, 0x64, 0x9b, 0x92, 0x75, 0xac, 0x43, 0x69, + 0x2c, 0x61, 0x72, 0x74, 0xd1, 0xb7, 0xf1, 0x3b, 0x25, 0x28, 0x4a, 0x7d, 0x8e, 0x3d, 0x84, 0xfc, + 0x40, 0xbd, 0x4d, 0x8a, 0x13, 0x61, 0xc8, 0x52, 0xf5, 0xff, 0x26, 0xbe, 0x50, 0x12, 0x78, 0xec, + 0x23, 0xa8, 0x27, 0xbd, 0xa2, 0x33, 0xe1, 0x90, 0x49, 0x77, 0x66, 0x6d, 0x30, 0xe3, 0xff, 0x2a, + 0xc7, 0x97, 0x23, 0xc9, 0x0c, 0xa5, 0x33, 0xed, 0xf6, 0xf4, 0x5c, 0x21, 0x6f, 0x07, 0x67, 0xb6, + 0xf5, 0xe4, 0xe9, 0x07, 0x32, 0x1e, 0xb2, 0x82, 0xc0, 0xde, 0x99, 0xfd, 0xe4, 0xe9, 0x07, 0xb3, + 0x92, 0x34, 0x85, 0xc4, 0xe9, 0x92, 0xf4, 0x32, 0x14, 0x28, 0xd3, 0x1a, 0x3d, 0x32, 0xa1, 0x0f, + 0xf6, 0x18, 0x96, 0xa5, 0xda, 0x6a, 0xc9, 0xe7, 0xc0, 0xc4, 0x05, 0x4b, 0x14, 0x83, 0x23, 0xcb, + 0x7a, 0x58, 0x44, 0xb6, 0xa1, 0x55, 0x58, 0x38, 0x8b, 0xd3, 0xe6, 0xd5, 0x4c, 0xf9, 0x65, 0xfc, + 0x69, 0x01, 0x2a, 0xda, 0xa2, 0xb0, 0x2a, 0x94, 0xcc, 0x4e, 0xaf, 0x63, 0x7e, 0xd2, 0xd9, 0x6a, + 0xde, 0x60, 0xf7, 0xe1, 0x9d, 0xee, 0xfe, 0xe6, 0x81, 0x69, 0x76, 0x36, 0xfb, 0xd6, 0x81, 0x69, + 0xa9, 0x74, 0x2c, 0x87, 0xed, 0xcf, 0xf6, 0x3a, 0xfb, 0x7d, 0x6b, 0xab, 0xd3, 0x6f, 0x77, 0x77, + 0x7b, 0xcd, 0x0c, 0x7b, 0x03, 0x5a, 0x31, 0xa6, 0x2a, 0x6e, 0xef, 0x1d, 0x1c, 0xed, 0xf7, 0x9b, + 0x59, 0x76, 0x07, 0x6e, 0x6d, 0x77, 0xf7, 0xdb, 0xbb, 0x56, 0x8c, 0xb3, 0xb9, 0xdb, 0xff, 0xc4, + 0xea, 0xfc, 0xda, 0x61, 0xd7, 0xfc, 0xac, 0x99, 0x4b, 0x43, 0x10, 0xca, 0xb8, 0x6a, 0x21, 0xcf, + 0x6e, 0xc2, 0x0a, 0x21, 0x50, 0x15, 0xab, 0x7f, 0x70, 0x60, 0xf5, 0x0e, 0x0e, 0xf6, 0x9b, 0x05, + 0xb6, 0x08, 0xb5, 0xee, 0xfe, 0x27, 0xed, 0xdd, 0xee, 0x96, 0x65, 0x76, 0xda, 0xbb, 0x7b, 0xcd, + 0x05, 0xb6, 0x04, 0x8d, 0x59, 0xbc, 0xa2, 0x68, 0x42, 0xe1, 0x1d, 0xec, 0x77, 0x0f, 0xf6, 0xad, + 0x4f, 0x3a, 0x66, 0xaf, 0x7b, 0xb0, 0xdf, 0x2c, 0xb1, 0x55, 0x60, 0xc9, 0xa2, 0x9d, 0xbd, 0xf6, + 0x66, 0xb3, 0xcc, 0x56, 0x60, 0x31, 0x09, 0x7f, 0xde, 0xf9, 0xac, 0x09, 0xac, 0x05, 0xcb, 0x34, + 0x30, 0x6b, 0xa3, 0xb3, 0x7b, 0xf0, 0xa9, 0xb5, 0xd7, 0xdd, 0xef, 0xee, 0x1d, 0xed, 0x35, 0x2b, + 0x98, 0x20, 0xaa, 0xd3, 0xb1, 0xba, 0xfb, 0xbd, 0xa3, 0xed, 0xed, 0xee, 0x66, 0xb7, 0xb3, 0xdf, + 0x6f, 0x56, 0xa9, 0xe7, 0xb4, 0x89, 0xd7, 0x44, 0x05, 0x19, 0x33, 0x60, 0x6d, 0x75, 0x7b, 0xed, + 0x8d, 0xdd, 0xce, 0x56, 0xb3, 0xce, 0x6e, 0xc3, 0xcd, 0x7e, 0x67, 0xef, 0xf0, 0xc0, 0x6c, 0x9b, + 0x9f, 0xa9, 0x98, 0x02, 0x6b, 0xbb, 0xdd, 0xdd, 0x3d, 0x32, 0x3b, 0xcd, 0x06, 0x7b, 0x0b, 0x6e, + 0x9b, 0x9d, 0x8f, 0x8f, 0xba, 0x66, 0x67, 0xcb, 0xda, 0x3f, 0xd8, 0xea, 0x58, 0xdb, 0x9d, 0x76, + 0xff, 0xc8, 0xec, 0x58, 0x7b, 0xdd, 0x5e, 0xaf, 0xbb, 0xff, 0xac, 0xd9, 0x64, 0xef, 0xc0, 0xdd, + 0x08, 0x25, 0x6a, 0x60, 0x06, 0x6b, 0x51, 0xcc, 0x4f, 0x6d, 0xe9, 0x7e, 0xe7, 0xd7, 0xfa, 0xd6, + 0x61, 0xa7, 0x63, 0x36, 0x19, 0x5b, 0x87, 0xd5, 0xb8, 0x7b, 0xea, 0x40, 0xf6, 0xbd, 0x24, 0xca, + 0x0e, 0x3b, 0xe6, 0x5e, 0x7b, 0x5f, 0x6c, 0x70, 0xa2, 0x6c, 0x59, 0x0c, 0x3b, 0x2e, 0x9b, 0x1d, + 0xf6, 0x0a, 0x63, 0x50, 0xd7, 0x76, 0x65, 0xbb, 0x6d, 0x36, 0x57, 0x59, 0x03, 0x2a, 0x7b, 0x87, + 0x87, 0x56, 0xbf, 0xbb, 0xd7, 0x39, 0x38, 0xea, 0x37, 0xd7, 0xd8, 0x0a, 0x34, 0xbb, 0xfb, 0xfd, + 0x8e, 0x29, 0xf6, 0x5a, 0x55, 0xfd, 0x3f, 0x45, 0xb6, 0x0c, 0x0d, 0x35, 0x52, 0x05, 0xfd, 0x59, + 0x91, 0xad, 0x01, 0x3b, 0xda, 0x37, 0x3b, 0xed, 0x2d, 0xb1, 0x70, 0x51, 0xc1, 0xff, 0x2d, 0x4a, + 0x0f, 0xc9, 0x4f, 0x73, 0xd1, 0x65, 0x1d, 0x3f, 0x39, 0x48, 0x26, 0x51, 0xad, 0x6a, 0xc9, 0x4f, + 0x5f, 0x95, 0xde, 0x5c, 0x53, 0xad, 0x72, 0x73, 0xaa, 0xd5, 0x9c, 0xee, 0x5e, 0xd3, 0x65, 0xbf, + 0xb7, 0xa1, 0x36, 0xa6, 0x84, 0xaa, 0x32, 0x71, 0x22, 0xc8, 0xf7, 0x37, 0x04, 0xa4, 0xac, 0x89, + 0x73, 0xf9, 0xbd, 0x0b, 0xf3, 0xf9, 0xbd, 0xd3, 0xe4, 0xfb, 0x85, 0x34, 0xf9, 0xfe, 0x01, 0x2c, + 0x12, 0x6b, 0x72, 0x5c, 0x67, 0xac, 0xb4, 0x66, 0x92, 0x02, 0x1b, 0xc8, 0xa2, 0x08, 0xae, 0xd4, + 0x09, 0xa5, 0x72, 0x48, 0x16, 0x52, 0x94, 0xda, 0x46, 0x42, 0xd3, 0x20, 0xce, 0x11, 0x69, 0x1a, + 0x51, 0x0f, 0xf6, 0x65, 0xdc, 0x43, 0x45, 0xeb, 0x81, 0xe0, 0xd8, 0xc3, 0x03, 0x58, 0xe4, 0x97, + 0xa1, 0x6f, 0x5b, 0xde, 0xc4, 0xfe, 0x7c, 0x8a, 0x2e, 0x5c, 0x1b, 0x75, 0xf8, 0xaa, 0xd9, 0xc0, + 0x82, 0x03, 0x84, 0x6f, 0xd9, 0xa1, 0xfd, 0xe0, 0x0b, 0xa8, 0x68, 0xc9, 0x76, 0xd9, 0x1a, 0x2c, + 0x7d, 0xda, 0xed, 0xef, 0x77, 0x7a, 0x3d, 0xeb, 0xf0, 0x68, 0xe3, 0x79, 0xe7, 0x33, 0x6b, 0xa7, + 0xdd, 0xdb, 0x69, 0xde, 0x10, 0x87, 0x76, 0xbf, 0xd3, 0xeb, 0x77, 0xb6, 0x12, 0xf0, 0x0c, 0x7b, + 0x13, 0xd6, 0x8f, 0xf6, 0x8f, 0x7a, 0x9d, 0x2d, 0x2b, 0xad, 0x5e, 0x56, 0x50, 0xa9, 0x2c, 0x4f, + 0xa9, 0x9e, 0x7b, 0xf0, 0x7d, 0xa8, 0x27, 0x33, 0x40, 0x32, 0x80, 0x85, 0xdd, 0xce, 0xb3, 0xf6, + 0xe6, 0x67, 0x94, 0x42, 0xae, 0xd7, 0x6f, 0xf7, 0xbb, 0x9b, 0x96, 0x4c, 0x19, 0x27, 0x38, 0x42, + 0x86, 0x55, 0xa0, 0xd8, 0xde, 0xdf, 0xdc, 0x39, 0x30, 0x7b, 0xcd, 0xec, 0x83, 0x8f, 0xa0, 0x39, + 0xeb, 0x8f, 0x4a, 0x38, 0xf0, 0x5e, 0xe6, 0xe9, 0x7b, 0xf0, 0xef, 0x73, 0x00, 0x71, 0xc0, 0x80, + 0x60, 0x35, 0x5b, 0xed, 0x7e, 0x7b, 0xf7, 0x40, 0x4c, 0xc3, 0x3c, 0xe8, 0x0b, 0x0e, 0x62, 0x76, + 0x3e, 0x6e, 0xde, 0x48, 0x2d, 0x39, 0x38, 0xec, 0x37, 0x33, 0x62, 0xc5, 0xba, 0xfb, 0xdd, 0x7e, + 0xb7, 0xbd, 0x6b, 0x99, 0x07, 0x47, 0xdd, 0xfd, 0x67, 0x94, 0x1b, 0x0b, 0xb9, 0xec, 0xd1, 0xe1, + 0xb6, 0x79, 0xb0, 0xdf, 0xb7, 0x7a, 0x3b, 0x47, 0xfd, 0x2d, 0xcc, 0xac, 0xb5, 0x69, 0x76, 0x0f, + 0xa9, 0xcd, 0xfc, 0xcb, 0x10, 0x44, 0xd3, 0x05, 0xb1, 0xe6, 0xcf, 0x0e, 0x7a, 0xbd, 0xee, 0xa1, + 0xf5, 0xf1, 0x51, 0xc7, 0xec, 0x76, 0x7a, 0x58, 0x71, 0x21, 0x05, 0x2e, 0xf0, 0x8b, 0x82, 0x37, + 0xf7, 0x77, 0x3f, 0x91, 0xcc, 0x53, 0xa0, 0x96, 0x92, 0x20, 0x81, 0x55, 0x16, 0x3c, 0x45, 0x70, + 0x9f, 0x94, 0x96, 0xe1, 0x9a, 0x32, 0x51, 0xaf, 0x22, 0xf8, 0xea, 0xdc, 0x66, 0x60, 0xb5, 0x6a, + 0x7a, 0x91, 0xa8, 0x85, 0x2c, 0x37, 0xba, 0xa0, 0xb6, 0xb6, 0x4c, 0xac, 0x50, 0x9f, 0x83, 0x0a, + 0xdc, 0x86, 0xd8, 0x28, 0xc1, 0x9e, 0x04, 0x4a, 0x53, 0x7d, 0x88, 0x92, 0xc5, 0x27, 0xbf, 0x9d, + 0x83, 0x3a, 0x05, 0x6f, 0xd1, 0x6f, 0x1d, 0x71, 0x9f, 0xed, 0x41, 0x51, 0xfe, 0x68, 0x16, 0x5b, + 0x89, 0xd2, 0x16, 0xe9, 0x3f, 0xd3, 0xb5, 0xbe, 0x3a, 0x0b, 0x96, 0xe2, 0xd8, 0xd2, 0xdf, 0xfe, + 0x93, 0xbf, 0xfc, 0xa7, 0xd9, 0x1a, 0xab, 0x3c, 0x3a, 0x7f, 0xff, 0xd1, 0x29, 0x77, 0x03, 0xd1, + 0xc6, 0xdf, 0x00, 0x88, 0x7f, 0x0a, 0x8a, 0xb5, 0x22, 0x27, 0xd4, 0xcc, 0xef, 0x64, 0xad, 0xdf, + 0x4c, 0x29, 0x91, 0xed, 0xde, 0xc4, 0x76, 0x97, 0x8c, 0xba, 0x68, 0xd7, 0x71, 0x9d, 0x90, 0x7e, + 0x16, 0xea, 0xc3, 0xcc, 0x03, 0x36, 0x84, 0xaa, 0xfe, 0x23, 0x4d, 0x4c, 0x49, 0x4a, 0x29, 0x3f, + 0x33, 0xb5, 0x7e, 0x2b, 0xb5, 0x4c, 0xc9, 0xa0, 0xd8, 0xc7, 0x8a, 0xd1, 0x14, 0x7d, 0x4c, 0x11, + 0x23, 0xee, 0x65, 0x44, 0x52, 0x79, 0xfc, 0x5b, 0x4c, 0xec, 0x0d, 0x4d, 0xae, 0x9a, 0xfb, 0x25, + 0xa8, 0xf5, 0xdb, 0xd7, 0x94, 0xca, 0xbe, 0x6e, 0x63, 0x5f, 0x6b, 0x06, 0x13, 0x7d, 0x0d, 0x10, + 0x47, 0xfd, 0x12, 0xd4, 0x87, 0x99, 0x07, 0x4f, 0xfe, 0xe2, 0x3e, 0x94, 0xa3, 0xc7, 0x9c, 0xec, + 0x37, 0xa1, 0x96, 0x88, 0xae, 0x63, 0x6a, 0x1a, 0x69, 0xc1, 0x78, 0xeb, 0x6f, 0xa4, 0x17, 0xca, + 0x8e, 0xdf, 0xc4, 0x8e, 0x5b, 0x6c, 0x55, 0x74, 0x2c, 0xa3, 0xd7, 0x1e, 0x61, 0x0c, 0x2a, 0x25, + 0x81, 0x7a, 0xa1, 0x69, 0x1f, 0xd4, 0xd9, 0x1b, 0xb3, 0x1a, 0x41, 0xa2, 0xb7, 0xdb, 0xd7, 0x94, + 0xca, 0xee, 0xde, 0xc0, 0xee, 0x56, 0xd9, 0xb2, 0xde, 0x9d, 0x7a, 0x7a, 0xc9, 0x38, 0x26, 0x5e, + 0xd3, 0x7f, 0xaa, 0x88, 0xdd, 0x8e, 0xd3, 0x64, 0xa5, 0xfc, 0x84, 0x51, 0x44, 0x22, 0xf3, 0xbf, + 0x63, 0x64, 0xb4, 0xb0, 0x2b, 0xc6, 0x70, 0xfb, 0xf4, 0x5f, 0x2a, 0x62, 0xc7, 0x50, 0xd1, 0xb2, + 0xfb, 0xb3, 0x9b, 0xd7, 0xfe, 0x12, 0xc1, 0xfa, 0x7a, 0x5a, 0x51, 0xda, 0x54, 0xf4, 0xf6, 0x1f, + 0x9d, 0x70, 0xce, 0x7e, 0x1d, 0xca, 0x51, 0xce, 0x78, 0xb6, 0xa6, 0xe5, 0xf0, 0xd7, 0x73, 0xdc, + 0xaf, 0xb7, 0xe6, 0x0b, 0xd2, 0x88, 0x4f, 0x6f, 0x5d, 0x10, 0xdf, 0xa7, 0x50, 0xd1, 0xf2, 0xc2, + 0x47, 0x13, 0x98, 0xcf, 0x3d, 0x1f, 0x4d, 0x20, 0x25, 0x8d, 0xbc, 0xb1, 0x88, 0x5d, 0x54, 0x58, + 0x19, 0xe9, 0x3b, 0xbc, 0xf4, 0x02, 0xb6, 0x0b, 0x2b, 0x52, 0xd3, 0x3a, 0xe6, 0x5f, 0x66, 0x1b, + 0x52, 0x7e, 0x1d, 0xea, 0x71, 0x86, 0x7d, 0x04, 0x25, 0x95, 0xfe, 0x9f, 0xad, 0xa6, 0xff, 0x8c, + 0xc1, 0xfa, 0xda, 0x1c, 0x5c, 0xaa, 0x45, 0x9f, 0x01, 0xc4, 0x49, 0xe8, 0x23, 0x26, 0x31, 0x97, + 0xd4, 0x3e, 0xa2, 0x80, 0xf9, 0x8c, 0xf5, 0xc6, 0x2a, 0x4e, 0xb0, 0xc9, 0x90, 0x49, 0xb8, 0xfc, + 0x42, 0x65, 0xc7, 0xfc, 0x11, 0x54, 0xb4, 0x3c, 0xf4, 0xd1, 0xf2, 0xcd, 0xe7, 0xb0, 0x8f, 0x96, + 0x2f, 0x25, 0x6d, 0xbd, 0xb1, 0x8e, 0xad, 0x2f, 0x1b, 0x0d, 0xd1, 0xba, 0x10, 0xb5, 0xa4, 0xc8, + 0x23, 0x36, 0xe8, 0x0c, 0x6a, 0x89, 0x64, 0xf3, 0xd1, 0x09, 0x4d, 0x4b, 0x65, 0x1f, 0x9d, 0xd0, + 0xd4, 0xfc, 0xf4, 0x8a, 0xce, 0x8c, 0x45, 0xd1, 0xcf, 0x39, 0xa2, 0x68, 0x3d, 0xfd, 0x10, 0x2a, + 0x5a, 0xe2, 0xf8, 0x68, 0x2e, 0xf3, 0x39, 0xea, 0xa3, 0xb9, 0xa4, 0xe5, 0x99, 0x5f, 0xc6, 0x3e, + 0xea, 0x06, 0x92, 0x02, 0xe6, 0xf7, 0x13, 0x6d, 0xff, 0x26, 0xd4, 0x93, 0xb9, 0xe4, 0xa3, 0xb3, + 0x9f, 0x9a, 0x94, 0x3e, 0x3a, 0xfb, 0xd7, 0x24, 0xa0, 0x97, 0x24, 0xfd, 0x60, 0x29, 0xea, 0xe4, + 0xd1, 0x4f, 0x64, 0x58, 0xca, 0x17, 0xec, 0x63, 0xc1, 0xe0, 0x64, 0x7a, 0x49, 0xb6, 0xa6, 0x51, + 0xad, 0x9e, 0xa7, 0x32, 0x3a, 0x2f, 0x73, 0x99, 0x28, 0x93, 0xc4, 0x8c, 0x8d, 0xb3, 0x67, 0xb0, + 0x14, 0x11, 0x73, 0x94, 0x2f, 0x32, 0x88, 0xe6, 0x90, 0x9a, 0x95, 0x72, 0xbd, 0x39, 0x5b, 0xfa, + 0x38, 0x43, 0xd7, 0x1f, 0x66, 0xe9, 0xd3, 0xae, 0x3f, 0x3d, 0x65, 0xa4, 0x76, 0xfd, 0x25, 0x92, + 0xf9, 0xcd, 0x5e, 0x7f, 0xa1, 0x23, 0xda, 0x70, 0xa1, 0x31, 0x9b, 0xbd, 0xf1, 0xf6, 0x75, 0xb9, + 0x0b, 0xa8, 0xf9, 0x37, 0x5f, 0x9e, 0xda, 0x20, 0xc9, 0x8a, 0x14, 0x37, 0x7d, 0x24, 0x1f, 0x9f, + 0xb0, 0xdf, 0x80, 0xaa, 0x9e, 0xc8, 0x9a, 0xe9, 0x3c, 0x61, 0xb6, 0xa7, 0x5b, 0xa9, 0x65, 0x49, + 0x2a, 0x61, 0x55, 0xbd, 0x1b, 0xf6, 0x09, 0xac, 0x46, 0xcb, 0xac, 0xc7, 0xad, 0x07, 0xec, 0x4e, + 0x4a, 0x34, 0x7b, 0x62, 0xb1, 0x6f, 0x5e, 0x1b, 0xee, 0xfe, 0x38, 0x23, 0xa8, 0x2f, 0x99, 0x51, + 0x37, 0xbe, 0x79, 0xd2, 0x12, 0x09, 0xc7, 0x37, 0x4f, 0x6a, 0x1a, 0x5e, 0x45, 0x7d, 0x6c, 0x29, + 0xb1, 0x46, 0xf4, 0x2c, 0x97, 0xfd, 0x10, 0x1a, 0x5a, 0x50, 0x7e, 0xef, 0xca, 0x1d, 0x44, 0x27, + 0x69, 0x3e, 0x25, 0xdc, 0x7a, 0x9a, 0x6d, 0xd2, 0x58, 0xc3, 0xf6, 0x17, 0x8d, 0xc4, 0xe2, 0x88, + 0x53, 0xb4, 0x09, 0x15, 0x3d, 0xe0, 0xff, 0x25, 0xed, 0xae, 0x69, 0x45, 0x7a, 0xf6, 0xb1, 0xc7, + 0x19, 0xb6, 0x0b, 0xcd, 0xd9, 0x64, 0x49, 0x11, 0x4f, 0x49, 0x4b, 0xf0, 0xb4, 0x3e, 0x53, 0x98, + 0x48, 0xb1, 0xc4, 0x0e, 0x29, 0xb0, 0x23, 0xfa, 0x29, 0x25, 0xcf, 0x9f, 0xbd, 0xd5, 0x93, 0x3f, + 0xb1, 0x14, 0xb5, 0x96, 0xf6, 0xe3, 0x5a, 0xf7, 0x33, 0x8f, 0x33, 0xec, 0x77, 0x33, 0x50, 0x4d, + 0x24, 0x28, 0x49, 0x3c, 0x9d, 0x9f, 0x99, 0x67, 0x4b, 0x2f, 0xd3, 0x27, 0x6a, 0x98, 0xb8, 0x88, + 0xbb, 0x0f, 0x7e, 0x90, 0xd8, 0xa4, 0x9f, 0x24, 0x5c, 0x7b, 0x0f, 0x67, 0x7f, 0x6b, 0xe9, 0x8b, + 0x59, 0x04, 0x3d, 0xd3, 0xdf, 0x17, 0x8f, 0x33, 0xec, 0x3f, 0x66, 0xa0, 0x9e, 0xf4, 0xd9, 0x47, + 0xd3, 0x4d, 0x7d, 0x1d, 0x10, 0x91, 0xd2, 0x35, 0x8e, 0xfe, 0x1f, 0xe2, 0x28, 0xfb, 0x0f, 0xcc, + 0xc4, 0x28, 0x65, 0x2e, 0xe8, 0x5f, 0x6c, 0xb4, 0xec, 0x43, 0xfa, 0x69, 0x43, 0xf5, 0x94, 0x89, + 0xcd, 0xff, 0x14, 0x5e, 0x44, 0x7e, 0xfa, 0x0f, 0xc7, 0xe1, 0x26, 0xfc, 0x88, 0x7e, 0x53, 0x48, + 0xbd, 0x8c, 0x11, 0x54, 0xfc, 0xba, 0xf5, 0x8d, 0x77, 0x70, 0x4e, 0x6f, 0x1a, 0x37, 0x13, 0x73, + 0x9a, 0x15, 0x3c, 0xda, 0x34, 0x3a, 0xf9, 0xbb, 0x6f, 0xf1, 0xcd, 0x39, 0xf7, 0x5b, 0x70, 0xd7, + 0x0f, 0x72, 0x4c, 0x83, 0x94, 0xe8, 0x89, 0xa3, 0xf6, 0x9a, 0xcd, 0x18, 0x0f, 0x70, 0xac, 0xef, + 0x18, 0x77, 0xae, 0x1d, 0xeb, 0x23, 0xf4, 0xbf, 0x8b, 0x11, 0x1f, 0x02, 0xc4, 0x4f, 0x0d, 0xd9, + 0xcc, 0x83, 0xb7, 0x88, 0x01, 0xcd, 0xbf, 0x46, 0x4c, 0x9e, 0x67, 0xf5, 0x2e, 0x4e, 0xb4, 0xf8, + 0xeb, 0xc4, 0x4e, 0xa3, 0xa7, 0x78, 0xba, 0xf4, 0x95, 0x7c, 0x15, 0x98, 0x90, 0xbe, 0x66, 0xdb, + 0x4f, 0x30, 0xd3, 0xe8, 0xdd, 0xdd, 0x11, 0xd4, 0x76, 0x3d, 0xef, 0xc5, 0x74, 0x12, 0x3d, 0x6f, + 0x4f, 0x3e, 0x8a, 0xd9, 0xb1, 0x83, 0xb3, 0xf5, 0x99, 0x59, 0x18, 0x77, 0xb1, 0xa9, 0x75, 0xd6, + 0xd2, 0x9a, 0x7a, 0xf4, 0x93, 0xf8, 0x7d, 0xe3, 0x17, 0xcc, 0x86, 0xc5, 0x88, 0x47, 0xc7, 0x6f, + 0x08, 0x93, 0xcd, 0x24, 0x38, 0xf3, 0x6c, 0x17, 0x09, 0x35, 0x41, 0x8d, 0xf6, 0x51, 0xa0, 0xda, + 0x7c, 0x9c, 0x61, 0x87, 0x50, 0xdd, 0xe2, 0x03, 0x0c, 0xd4, 0xc7, 0xa7, 0x25, 0x4b, 0x89, 0x67, + 0x0a, 0xf4, 0x26, 0x65, 0xbd, 0x96, 0x00, 0x26, 0xef, 0xad, 0x89, 0x7d, 0xe5, 0xf3, 0xcf, 0x1f, + 0xfd, 0x44, 0x3e, 0x5a, 0xf9, 0x42, 0xdd, 0x5b, 0xea, 0x51, 0x4f, 0xe2, 0xde, 0x9a, 0x79, 0x05, + 0x94, 0xb8, 0xb7, 0xe6, 0x5e, 0x01, 0x25, 0x96, 0x5a, 0x3d, 0x2a, 0x62, 0x23, 0x58, 0x9c, 0x7b, + 0x38, 0x14, 0x5d, 0x59, 0xd7, 0x3d, 0x37, 0x5a, 0xbf, 0x7b, 0x3d, 0x42, 0xb2, 0xb7, 0x07, 0xc9, + 0xde, 0x7a, 0x50, 0xa3, 0xe4, 0x83, 0xc7, 0x9c, 0x42, 0xf6, 0x66, 0xf2, 0xdd, 0xe8, 0xf1, 0x80, + 0xb3, 0x17, 0x0c, 0x96, 0x25, 0x25, 0x1c, 0x8c, 0x95, 0x63, 0xbf, 0x0e, 0x95, 0x67, 0x3c, 0x54, + 0x31, 0x7a, 0x91, 0x8c, 0x3d, 0x13, 0xb4, 0xb7, 0x9e, 0x12, 0xe2, 0x97, 0xa4, 0x19, 0x6c, 0xed, + 0x11, 0x1f, 0x9e, 0x72, 0x62, 0x4e, 0x96, 0x33, 0xfc, 0x82, 0xfd, 0x1a, 0x36, 0x1e, 0x85, 0x46, + 0xaf, 0x6a, 0x41, 0x58, 0x7a, 0xe3, 0x8d, 0x19, 0x78, 0x5a, 0xcb, 0xae, 0x37, 0xe4, 0x9a, 0xac, + 0xe7, 0x42, 0x45, 0x4b, 0xa1, 0x10, 0x1d, 0xa0, 0xf9, 0x94, 0x19, 0xd1, 0x01, 0x4a, 0xc9, 0xb8, + 0x60, 0xdc, 0xc7, 0x7e, 0x0c, 0x76, 0x37, 0xee, 0x87, 0xb2, 0x2c, 0xc4, 0x3d, 0x3d, 0xfa, 0x89, + 0x3d, 0x0e, 0xbf, 0x60, 0x9f, 0x62, 0x8a, 0x6f, 0x3d, 0x06, 0x31, 0x56, 0x1a, 0x66, 0xc3, 0x15, + 0xa3, 0xc5, 0xd2, 0x8a, 0x92, 0x8a, 0x04, 0x75, 0x85, 0x92, 0xdc, 0x53, 0x80, 0x5e, 0xe8, 0x4d, + 0xb6, 0x6c, 0x3e, 0xf6, 0xdc, 0x98, 0xd7, 0xc6, 0x51, 0x71, 0x31, 0xff, 0xd2, 0x42, 0xe3, 0xd8, + 0xa7, 0x9a, 0x96, 0x95, 0x08, 0xe3, 0x54, 0xc4, 0x75, 0x6d, 0xe0, 0x5c, 0xb4, 0x20, 0x29, 0xc1, + 0x73, 0x8f, 0x33, 0xac, 0x0d, 0x10, 0xbf, 0x1c, 0x8b, 0x74, 0xa6, 0xb9, 0x47, 0x69, 0x11, 0xdb, + 0x4b, 0x79, 0x66, 0x76, 0x08, 0xe5, 0xf8, 0xc9, 0xcd, 0x5a, 0x9c, 0x11, 0x26, 0xf1, 0x40, 0x27, + 0xba, 0xc1, 0xe7, 0x9e, 0xbb, 0x18, 0x4d, 0x5c, 0x2a, 0x60, 0x25, 0xb1, 0x54, 0x27, 0x9c, 0x07, + 0xcc, 0x81, 0x25, 0x1a, 0x60, 0x24, 0x2e, 0x61, 0x34, 0x57, 0x94, 0xc9, 0x7d, 0xfe, 0xe5, 0x49, + 0x74, 0x9a, 0x53, 0xdf, 0x4f, 0x24, 0x4c, 0x3f, 0x82, 0x5a, 0x29, 0x92, 0x4c, 0xb0, 0xe6, 0x31, + 0x2c, 0xce, 0xb9, 0xe8, 0xa3, 0x23, 0x7d, 0xdd, 0x9b, 0x8b, 0xe8, 0x48, 0x5f, 0xeb, 0xdd, 0x37, + 0x56, 0xb0, 0xcb, 0x86, 0x01, 0xa8, 0xea, 0x5d, 0x38, 0xe1, 0xe0, 0x4c, 0x74, 0xf7, 0xef, 0x32, + 0xb0, 0x94, 0xe2, 0x84, 0x67, 0x6f, 0x29, 0xab, 0xc1, 0xb5, 0x0e, 0xfa, 0xf5, 0x54, 0x67, 0xad, + 0xd1, 0xc3, 0x7e, 0xf6, 0xd8, 0xf3, 0xc4, 0xc5, 0x46, 0xbe, 0x52, 0x79, 0x32, 0x5f, 0x2a, 0x54, + 0xa4, 0x4a, 0x14, 0x9f, 0xc3, 0x1a, 0x0d, 0xa4, 0x3d, 0x1a, 0xcd, 0x38, 0x92, 0xdf, 0x9c, 0xfb, + 0xe9, 0xf3, 0x84, 0x73, 0x7c, 0xfd, 0xfa, 0x9f, 0x46, 0xbf, 0x46, 0x9c, 0xa6, 0xa1, 0xb2, 0x29, + 0x34, 0x67, 0x1d, 0xb4, 0xec, 0xfa, 0xb6, 0xd6, 0xef, 0x24, 0xf4, 0xdf, 0x14, 0xa7, 0xee, 0xd7, + 0xb0, 0xb3, 0x3b, 0xc6, 0x7a, 0xda, 0xba, 0x90, 0x4a, 0x2c, 0xf6, 0xe3, 0x6f, 0x45, 0xde, 0xe4, + 0x99, 0x79, 0xaa, 0x0e, 0xae, 0xf3, 0x7d, 0x47, 0x1a, 0x78, 0xba, 0x33, 0xfa, 0x5d, 0xec, 0xfe, + 0xae, 0x71, 0x2b, 0xad, 0x7b, 0x9f, 0xaa, 0x90, 0x2e, 0xbe, 0x36, 0x7b, 0xae, 0xd5, 0x08, 0xee, + 0xa6, 0xed, 0xf7, 0xb5, 0xba, 0xd0, 0xcc, 0x5a, 0xdf, 0x40, 0xd9, 0xae, 0xaa, 0x7b, 0x8f, 0xa3, + 0xe3, 0x93, 0xe2, 0xa6, 0x8e, 0x8e, 0x4f, 0x9a, 0xbb, 0x39, 0x29, 0xd7, 0x28, 0x47, 0xf3, 0x87, + 0x99, 0x07, 0x1b, 0xf7, 0x7e, 0xf8, 0xb5, 0x53, 0x27, 0x3c, 0x9b, 0x1e, 0x3f, 0x1c, 0x78, 0xe3, + 0x47, 0x23, 0x65, 0x6d, 0x94, 0x21, 0xcf, 0x8f, 0x46, 0xee, 0xf0, 0x11, 0x36, 0x7b, 0xbc, 0x30, + 0xf1, 0xbd, 0xd0, 0xfb, 0xd6, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x5f, 0xbc, 0x91, 0xdd, + 0x81, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.pb.gw.go b/lnrpc/rpc.pb.gw.go index 53400f4efc..55ac162c88 100644 --- a/lnrpc/rpc.pb.gw.go +++ b/lnrpc/rpc.pb.gw.go @@ -269,10 +269,18 @@ func request_Lightning_DisconnectPeer_0(ctx context.Context, marshaler runtime.M } +var ( + filter_Lightning_ListPeers_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + func request_Lightning_ListPeers_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ListPeersRequest var metadata runtime.ServerMetadata + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_Lightning_ListPeers_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.ListPeers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 1c2bf79541..64f7a30c53 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1571,9 +1571,32 @@ message Peer { /// Features advertised by the remote peer in their init message. map features = 11; + + /* + The latest errors received from our peer with timestamps, limited to the 10 + most recent errors. These errors are tracked across peer connections, but + are not persisted across lnd restarts. Note that these errors are only + stored for peers that we have channels open with, to prevent peers from + spamming us with errors at no cost. + */ + repeated TimestampedError errors = 12; +} + +message TimestampedError { + // The unix timestamp in seconds when the error occurred. + uint64 timestamp = 1; + + // The string representation of the error sent by our peer. + string error = 2; } message ListPeersRequest { + /* + If true, only the last error that our peer sent us will be returned with + the peer's information, rather than the full set of historic errors we have + stored. + */ + bool latest_error = 1; } message ListPeersResponse { /// The list of currently connected peers diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index cf2d0e09a8..73f192928e 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1186,6 +1186,16 @@ } } }, + "parameters": [ + { + "name": "latest_error", + "description": "If true, only the last error that our peer sent us will be returned with\nthe peer's information, rather than the full set of historic errors we have\nstored.", + "in": "query", + "required": false, + "type": "boolean", + "format": "boolean" + } + ], "tags": [ "Lightning" ] @@ -3819,6 +3829,13 @@ "$ref": "#/definitions/lnrpcFeature" }, "description": "/ Features advertised by the remote peer in their init message." + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/lnrpcTimestampedError" + }, + "description": "The latest errors received from our peer with timestamps, limited to the 10\nmost recent errors. These errors are tracked across peer connections, but\nare not persisted across lnd restarts. Note that these errors are only\nstored for peers that we have channels open with, to prevent peers from\nspamming us with errors at no cost." } } }, @@ -4270,6 +4287,20 @@ "lnrpcStopResponse": { "type": "object" }, + "lnrpcTimestampedError": { + "type": "object", + "properties": { + "timestamp": { + "type": "string", + "format": "uint64", + "description": "The unix timestamp in seconds when the error occurred." + }, + "error": { + "type": "string", + "description": "The string representation of the error sent by our peer." + } + } + }, "lnrpcTransaction": { "type": "object", "properties": { diff --git a/rpcserver.go b/rpcserver.go index eee93b4916..841520a39d 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2459,6 +2459,33 @@ func (r *rpcServer) ListPeers(ctx context.Context, Features: features, } + var peerErrors []interface{} + + // If we only want the most recent error, get the most recent + // error from the buffer and add it to our list of errors if + // it is non-nil. If we want all the stored errors, simply + // add the full list to our set of errors. + if in.LatestError { + latestErr := serverPeer.errorBuffer.Latest() + if latestErr != nil { + peerErrors = []interface{}{latestErr} + } + } else { + peerErrors = serverPeer.errorBuffer.List() + } + + // Add the relevant peer errors to our response. + for _, error := range peerErrors { + tsError := error.(*timestampedError) + + rpcErr := &lnrpc.TimestampedError{ + Timestamp: uint64(tsError.timestamp.Unix()), + Error: tsError.error.Error(), + } + + peer.Errors = append(peer.Errors, rpcErr) + } + resp.Peers = append(resp.Peers, peer) } From 30fc03d84d84232ac9bb72503a153527baa75f8d Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 10 Mar 2020 09:33:38 +0100 Subject: [PATCH 219/562] lnwallet/test: pass in test channel type --- contractcourt/chain_arbitrator_test.go | 8 +- contractcourt/chain_watcher_test.go | 12 +- contractcourt/channel_arbitrator_test.go | 2 +- lnwallet/channel_test.go | 236 +++++++++++++++++------ lnwallet/test_utils.go | 38 ++-- 5 files changed, 208 insertions(+), 88 deletions(-) diff --git a/contractcourt/chain_arbitrator_test.go b/contractcourt/chain_arbitrator_test.go index 0ac7484a50..2692e29753 100644 --- a/contractcourt/chain_arbitrator_test.go +++ b/contractcourt/chain_arbitrator_test.go @@ -35,7 +35,9 @@ func TestChainArbitratorRepublishCloses(t *testing.T) { const numChans = 10 var channels []*channeldb.OpenChannel for i := 0; i < numChans; i++ { - lChannel, _, cleanup, err := lnwallet.CreateTestChannels(true) + lChannel, _, cleanup, err := lnwallet.CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatal(err) } @@ -149,7 +151,9 @@ func TestResolveContract(t *testing.T) { // With the DB created, we'll make a new channel, and mark it as // pending open within the database. - newChannel, _, cleanup, err := lnwallet.CreateTestChannels(true) + newChannel, _, cleanup, err := lnwallet.CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to make new test channel: %v", err) } diff --git a/contractcourt/chain_watcher_test.go b/contractcourt/chain_watcher_test.go index 466662c139..6dc47f530f 100644 --- a/contractcourt/chain_watcher_test.go +++ b/contractcourt/chain_watcher_test.go @@ -63,7 +63,9 @@ func TestChainWatcherRemoteUnilateralClose(t *testing.T) { // First, we'll create two channels which already have established a // commitment contract between themselves. - aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -150,7 +152,9 @@ func TestChainWatcherRemoteUnilateralClosePendingCommit(t *testing.T) { // First, we'll create two channels which already have established a // commitment contract between themselves. - aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -274,7 +278,7 @@ func TestChainWatcherDataLossProtect(t *testing.T) { // First, we'll create two channels which already have // established a commitment contract between themselves. aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels( - false, + channeldb.SingleFunderBit, ) if err != nil { t.Fatalf("unable to create test channels: %v", err) @@ -443,7 +447,7 @@ func TestChainWatcherLocalForceCloseDetect(t *testing.T) { // First, we'll create two channels which already have // established a commitment contract between themselves. aliceChannel, bobChannel, cleanUp, err := lnwallet.CreateTestChannels( - false, + channeldb.SingleFunderBit, ) if err != nil { t.Fatalf("unable to create test channels: %v", err) diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index 0a73cd5e90..b330189286 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -2005,7 +2005,7 @@ func TestRemoteCloseInitiator(t *testing.T) { // First, create alice's channel. alice, _, cleanUp, err := lnwallet.CreateTestChannels( - true, + channeldb.SingleFunderTweaklessBit, ) if err != nil { t.Fatalf("unable to create test channels: %v", diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 511631bb6f..1b1ac942c4 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -60,7 +60,12 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(tweakless) + chanType := channeldb.SingleFunderTweaklessBit + if !tweakless { + chanType = channeldb.SingleFunderBit + } + + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(chanType) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -390,7 +395,9 @@ func TestCheckCommitTxSize(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -449,7 +456,9 @@ func TestCooperativeChannelClosure(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -522,7 +531,9 @@ func TestForceClose(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -808,7 +819,9 @@ func TestForceCloseDustOutput(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -926,7 +939,9 @@ func TestDustHTLCFees(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -970,7 +985,7 @@ func TestDustHTLCFees(t *testing.T) { // The commitment fee paid should be the same, as there have been no // new material outputs added. - defaultFee := calcStaticFee(0) + defaultFee := calcStaticFee(channeldb.SingleFunderTweaklessBit, 0) if aliceChannel.channelState.LocalCommitment.CommitFee != defaultFee { t.Fatalf("dust htlc amounts not subtracted from commitment fee "+ "expected %v, got %v", defaultFee, @@ -1003,7 +1018,9 @@ func TestHTLCDustLimit(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -1046,7 +1063,7 @@ func TestHTLCDustLimit(t *testing.T) { t.Fatalf("incorrect # of outputs: expected %v, got %v", 2, len(bobCommitment.txn.TxOut)) } - defaultFee := calcStaticFee(0) + defaultFee := calcStaticFee(channeldb.SingleFunderTweaklessBit, 0) if bobChannel.channelState.LocalCommitment.CommitFee != defaultFee { t.Fatalf("dust htlc amount was subtracted from commitment fee "+ "expected %v, got %v", defaultFee, @@ -1092,7 +1109,9 @@ func TestHTLCSigNumber(t *testing.T) { // Create a test channel funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. Alice's dustlimit is 200 sat, while // Bob has 1300 sat. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -1266,7 +1285,9 @@ func TestChannelBalanceDustLimit(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -1280,7 +1301,7 @@ func TestChannelBalanceDustLimit(t *testing.T) { // This amount should leave an amount larger than Alice's dust limit // once fees have been subtracted, but smaller than Bob's dust limit. // We account in fees for the HTLC we will be adding. - defaultFee := calcStaticFee(1) + defaultFee := calcStaticFee(channeldb.SingleFunderTweaklessBit, 1) aliceBalance := aliceChannel.channelState.LocalCommitment.LocalBalance.ToSatoshis() htlcSat := aliceBalance - defaultFee htlcSat += HtlcSuccessFee( @@ -1337,7 +1358,9 @@ func TestStateUpdatePersistence(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -1678,7 +1701,9 @@ func TestCancelHTLC(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -1711,7 +1736,7 @@ func TestCancelHTLC(t *testing.T) { // With the HTLC committed, Alice's balance should reflect the clearing // of the new HTLC. aliceExpectedBalance := btcutil.Amount(btcutil.SatoshiPerBitcoin*4) - - calcStaticFee(1) + calcStaticFee(channeldb.SingleFunderTweaklessBit, 1) if aliceChannel.channelState.LocalCommitment.LocalBalance.ToSatoshis() != aliceExpectedBalance { t.Fatalf("Alice's balance is wrong: expected %v, got %v", @@ -1756,12 +1781,13 @@ func TestCancelHTLC(t *testing.T) { } expectedBalance := btcutil.Amount(btcutil.SatoshiPerBitcoin * 5) + staticFee := calcStaticFee(channeldb.SingleFunderTweaklessBit, 0) if aliceChannel.channelState.LocalCommitment.LocalBalance.ToSatoshis() != - expectedBalance-calcStaticFee(0) { + expectedBalance-staticFee { t.Fatalf("balance is wrong: expected %v, got %v", aliceChannel.channelState.LocalCommitment.LocalBalance.ToSatoshis(), - expectedBalance-calcStaticFee(0)) + expectedBalance-staticFee) } if aliceChannel.channelState.LocalCommitment.RemoteBalance.ToSatoshis() != expectedBalance { @@ -1778,11 +1804,11 @@ func TestCancelHTLC(t *testing.T) { expectedBalance) } if bobChannel.channelState.LocalCommitment.RemoteBalance.ToSatoshis() != - expectedBalance-calcStaticFee(0) { + expectedBalance-staticFee { t.Fatalf("balance is wrong: expected %v, got %v", bobChannel.channelState.LocalCommitment.RemoteBalance.ToSatoshis(), - expectedBalance-calcStaticFee(0)) + expectedBalance-staticFee) } } @@ -1792,7 +1818,9 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -1957,7 +1985,9 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { func TestUpdateFeeAdjustments(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2012,7 +2042,9 @@ func TestUpdateFeeAdjustments(t *testing.T) { func TestUpdateFeeFail(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2046,7 +2078,9 @@ func TestUpdateFeeFail(t *testing.T) { func TestUpdateFeeConcurrentSig(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2132,7 +2166,9 @@ func TestUpdateFeeSenderCommits(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2254,7 +2290,9 @@ func TestUpdateFeeReceiverCommits(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2403,7 +2441,9 @@ func TestUpdateFeeReceiverSendsUpdate(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2432,7 +2472,9 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2552,7 +2594,9 @@ func TestAddHTLCNegativeBalance(t *testing.T) { // We'll kick off the test by creating our channels which both are // loaded with 5 BTC each. - aliceChannel, _, cleanUp, err := CreateTestChannels(true) + aliceChannel, _, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2633,7 +2677,9 @@ func TestChanSyncFullySynced(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -2753,7 +2799,9 @@ func TestChanSyncOweCommitment(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -3064,7 +3112,9 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -3187,7 +3237,9 @@ func TestChanSyncOweRevocation(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -3377,7 +3429,9 @@ func TestChanSyncOweRevocationAndCommit(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -3546,7 +3600,9 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -3775,7 +3831,9 @@ func TestChanSyncFailure(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(false) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4028,7 +4086,9 @@ func TestFeeUpdateRejectInsaneFee(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, _, cleanUp, err := CreateTestChannels(true) + aliceChannel, _, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4056,7 +4116,9 @@ func TestChannelRetransmissionFeeUpdate(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4245,7 +4307,9 @@ func TestFeeUpdateOldDiskFormat(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4472,7 +4536,9 @@ func TestChanSyncUnableToSync(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(false) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4509,7 +4575,9 @@ func TestChanSyncInvalidLastSecret(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(false) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4599,7 +4667,9 @@ func TestChanAvailableBandwidth(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4735,7 +4805,9 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4915,7 +4987,9 @@ func TestSignCommitmentFailNotLockedIn(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, _, cleanUp, err := CreateTestChannels(true) + aliceChannel, _, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -4940,7 +5014,9 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) { t.Parallel() // First, we'll make a channel between Alice and Bob. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -5254,7 +5330,9 @@ func TestInvalidCommitSigError(t *testing.T) { t.Parallel() // First, we'll make a channel between Alice and Bob. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -5301,7 +5379,9 @@ func TestChannelUnilateralCloseHtlcResolution(t *testing.T) { // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -5460,7 +5540,7 @@ func TestChannelUnilateralClosePendingCommit(t *testing.T) { // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( - false, + channeldb.SingleFunderBit, ) if err != nil { t.Fatalf("unable to create test channels: %v", err) @@ -5587,7 +5667,9 @@ func TestDesyncHTLCs(t *testing.T) { // We'll kick off the test by creating our channels which both are // loaded with 5 BTC each. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -5654,7 +5736,9 @@ func TestMaxAcceptedHTLCs(t *testing.T) { // We'll kick off the test by creating our channels which both are // loaded with 5 BTC each. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -5786,7 +5870,9 @@ func TestMaxAsynchronousHtlcs(t *testing.T) { // We'll kick off the test by creating our channels which both are // loaded with 5 BTC each. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -5921,7 +6007,9 @@ func TestMaxPendingAmount(t *testing.T) { // We'll kick off the test by creating our channels which both are // loaded with 5 BTC each. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -6005,7 +6093,7 @@ func TestChanReserve(t *testing.T) { // We'll kick off the test by creating our channels which both // are loaded with 5 BTC each. aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( - true, + channeldb.SingleFunderTweaklessBit, ) if err != nil { t.Fatalf("unable to create test channels: %v", err) @@ -6214,7 +6302,7 @@ func TestChanReserveRemoteInitiator(t *testing.T) { // We start out with a channel where both parties have 5 BTC. aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( - true, + channeldb.SingleFunderTweaklessBit, ) if err != nil { t.Fatal(err) @@ -6267,7 +6355,7 @@ func TestChanReserveLocalInitiatorDustHtlc(t *testing.T) { t.Parallel() aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( - true, + channeldb.SingleFunderTweaklessBit, ) if err != nil { t.Fatal(err) @@ -6313,7 +6401,9 @@ func TestMinHTLC(t *testing.T) { // We'll kick off the test by creating our channels which both are // loaded with 5 BTC each. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -6366,7 +6456,9 @@ func TestNewBreachRetributionSkipsDustHtlcs(t *testing.T) { // We'll kick off the test by creating our channels which both are // loaded with 5 BTC each. - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -6538,7 +6630,9 @@ func compareLogs(a, b *updateLog) error { func TestChannelRestoreUpdateLogs(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -6707,7 +6801,9 @@ func restoreAndAssert(t *testing.T, channel *LightningChannel, numAddsLocal, func TestChannelRestoreUpdateLogsFailedHTLC(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -6830,7 +6926,9 @@ func TestChannelRestoreUpdateLogsFailedHTLC(t *testing.T) { func TestDuplicateFailRejection(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -6908,7 +7006,9 @@ func TestDuplicateFailRejection(t *testing.T) { func TestDuplicateSettleRejection(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -6989,7 +7089,9 @@ func TestDuplicateSettleRejection(t *testing.T) { func TestChannelRestoreCommitHeight(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -7176,7 +7278,9 @@ func TestChannelRestoreCommitHeight(t *testing.T) { func TestForceCloseFailLocalDataLoss(t *testing.T) { t.Parallel() - aliceChannel, _, cleanUp, err := CreateTestChannels(false) + aliceChannel, _, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -7207,7 +7311,9 @@ func TestForceCloseFailLocalDataLoss(t *testing.T) { func TestForceCloseBorkedState(t *testing.T) { t.Parallel() - aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(false) + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } @@ -7284,7 +7390,9 @@ func TestForceCloseBorkedState(t *testing.T) { func TestChannelMaxFeeRate(t *testing.T) { t.Parallel() - aliceChannel, _, cleanUp, err := CreateTestChannels(true) + aliceChannel, _, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) if err != nil { t.Fatalf("unable to create test channels: %v", err) } diff --git a/lnwallet/test_utils.go b/lnwallet/test_utils.go index 5253acddae..cbe1b2b3e3 100644 --- a/lnwallet/test_utils.go +++ b/lnwallet/test_utils.go @@ -91,7 +91,7 @@ var ( // the test has been finalized. The clean up function will remote all temporary // files created. If tweaklessCommits is true, then the commits within the // channels will use the new format, otherwise the legacy format. -func CreateTestChannels(tweaklessCommits bool) ( +func CreateTestChannels(chanType channeldb.ChannelType) ( *LightningChannel, *LightningChannel, func(), error) { channelCapacity, err := btcutil.NewAmount(10) @@ -206,11 +206,6 @@ func CreateTestChannels(tweaklessCommits bool) ( } aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:]) - chanType := channeldb.SingleFunderTweaklessBit - if !tweaklessCommits { - chanType = channeldb.SingleFunderBit - } - aliceCommitTx, bobCommitTx, err := CreateCommitmentTxns( channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint, *fundingTxIn, chanType, @@ -244,12 +239,21 @@ func CreateTestChannels(tweaklessCommits bool) ( if err != nil { return nil, nil, nil, err } - commitFee := calcStaticFee(0) + commitFee := calcStaticFee(chanType, 0) + var anchorAmt btcutil.Amount + if chanType.HasAnchors() { + anchorAmt += 2 * anchorSize + } + + aliceBalance := lnwire.NewMSatFromSatoshis( + channelBal - commitFee - anchorAmt, + ) + bobBalance := lnwire.NewMSatFromSatoshis(channelBal) aliceCommit := channeldb.ChannelCommitment{ CommitHeight: 0, - LocalBalance: lnwire.NewMSatFromSatoshis(channelBal - commitFee), - RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal), + LocalBalance: aliceBalance, + RemoteBalance: bobBalance, CommitFee: commitFee, FeePerKw: btcutil.Amount(feePerKw), CommitTx: aliceCommitTx, @@ -257,8 +261,8 @@ func CreateTestChannels(tweaklessCommits bool) ( } bobCommit := channeldb.ChannelCommitment{ CommitHeight: 0, - LocalBalance: lnwire.NewMSatFromSatoshis(channelBal), - RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal - commitFee), + LocalBalance: bobBalance, + RemoteBalance: aliceBalance, CommitFee: commitFee, FeePerKw: btcutil.Amount(feePerKw), CommitTx: bobCommitTx, @@ -449,14 +453,14 @@ func txFromHex(txHex string) (*btcutil.Tx, error) { // calculations into account. // // TODO(bvu): Refactor when dynamic fee estimation is added. -func calcStaticFee(numHTLCs int) btcutil.Amount { +func calcStaticFee(chanType channeldb.ChannelType, numHTLCs int) btcutil.Amount { const ( - commitWeight = btcutil.Amount(724) - htlcWeight = 172 - feePerKw = btcutil.Amount(24/4) * 1000 + htlcWeight = 172 + feePerKw = btcutil.Amount(24/4) * 1000 ) - return feePerKw * (commitWeight + - btcutil.Amount(htlcWeight*numHTLCs)) / 1000 + return feePerKw * + (btcutil.Amount(CommitWeight(chanType) + + htlcWeight*int64(numHTLCs))) / 1000 } // ForceStateTransition executes the necessary interaction between the two From dc6c4637b6f52e58afae6291c4400bbdf34ca7b3 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 13 Dec 2019 11:14:22 +0100 Subject: [PATCH 220/562] lnwallet+channeldb: add anchor resolutions Co-authored-by: Joost Jager --- lnwallet/channel.go | 139 +++++++++++++++++++++++++++++++++++++++ lnwallet/channel_test.go | 63 +++++++++++++++++- 2 files changed, 199 insertions(+), 3 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index aca93b9933..6f64d34d5e 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -5115,6 +5115,11 @@ type UnilateralCloseSummary struct { // RemoteCommit is the exact commitment state that the remote party // broadcast. RemoteCommit channeldb.ChannelCommitment + + // AnchorResolution contains the data required to sweep our anchor + // output. If the channel type doesn't include anchors, the value of + // this field will be nil. + AnchorResolution *AnchorResolution } // NewUnilateralCloseSummary creates a new summary that provides the caller @@ -5229,12 +5234,20 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Si closeSummary.LastChanSyncMsg = chanSync } + anchorResolution, err := NewAnchorResolution( + chanState, commitTxBroadcast, + ) + if err != nil { + return nil, err + } + return &UnilateralCloseSummary{ SpendDetail: commitSpend, ChannelCloseSummary: closeSummary, CommitResolution: commitResolution, HtlcResolutions: htlcResolutions, RemoteCommit: remoteCommit, + AnchorResolution: anchorResolution, }, nil } @@ -5685,6 +5698,16 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool, }, nil } +// AnchorResolution holds the information necessary to spend our commitment tx +// anchor. +type AnchorResolution struct { + // AnchorSignDescriptor is the sign descriptor for our anchor. + AnchorSignDescriptor input.SignDescriptor + + // CommitAnchor is the anchor outpoint on the commit tx. + CommitAnchor wire.OutPoint +} + // LocalForceCloseSummary describes the final commitment state before the // channel is locked-down to initiate a force closure by broadcasting the // latest state on-chain. If we intend to broadcast this this state, the @@ -5717,6 +5740,11 @@ type LocalForceCloseSummary struct { // ChanSnapshot is a snapshot of the final state of the channel at the // time the summary was created. ChanSnapshot channeldb.ChannelSnapshot + + // AnchorResolution contains the data required to sweep the anchor + // output. If the channel type doesn't include anchors, the value of + // this field will be nil. + AnchorResolution *AnchorResolution } // ForceClose executes a unilateral closure of the transaction at the current @@ -5855,12 +5883,20 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer input.Si return nil, err } + anchorResolution, err := NewAnchorResolution( + chanState, commitTx, + ) + if err != nil { + return nil, err + } + return &LocalForceCloseSummary{ ChanPoint: chanState.FundingOutpoint, CloseTx: commitTx, CommitResolution: commitResolution, HtlcResolutions: htlcResolutions, ChanSnapshot: *chanState.Snapshot(), + AnchorResolution: anchorResolution, }, nil } @@ -6019,6 +6055,109 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte, return closeTx, ourBalance, nil } +// NewAnchorResolutions returns the anchor resolutions for all currently valid +// commitment transactions. Because we have no view on the mempool, we can only +// blindly anchor all of these txes down. +func (lc *LightningChannel) NewAnchorResolutions() ([]*AnchorResolution, + error) { + + lc.Lock() + defer lc.Unlock() + + var resolutions []*AnchorResolution + + // Add anchor for local commitment tx, if any. + localRes, err := NewAnchorResolution( + lc.channelState, lc.channelState.LocalCommitment.CommitTx, + ) + if err != nil { + return nil, err + } + if localRes != nil { + resolutions = append(resolutions, localRes) + } + + // Add anchor for remote commitment tx, if any. + remoteRes, err := NewAnchorResolution( + lc.channelState, lc.channelState.RemoteCommitment.CommitTx, + ) + if err != nil { + return nil, err + } + if remoteRes != nil { + resolutions = append(resolutions, remoteRes) + } + + // Add anchor for remote pending commitment tx, if any. + remotePendingCommit, err := lc.channelState.RemoteCommitChainTip() + if err != nil && err != channeldb.ErrNoPendingCommit { + return nil, err + } + + if remotePendingCommit != nil { + remotePendingRes, err := NewAnchorResolution( + lc.channelState, + remotePendingCommit.Commitment.CommitTx, + ) + if err != nil { + return nil, err + } + + if remotePendingRes != nil { + resolutions = append(resolutions, remotePendingRes) + } + } + + return resolutions, nil +} + +// NewAnchorResolution returns the information that is required to sweep the +// local anchor. +func NewAnchorResolution(chanState *channeldb.OpenChannel, + commitTx *wire.MsgTx) (*AnchorResolution, error) { + + // Return nil resolution if the channel has no anchors. + if !chanState.ChanType.HasAnchors() { + return nil, nil + } + + // Derive our local anchor script. + localAnchor, _, err := CommitScriptAnchors( + &chanState.LocalChanCfg, &chanState.RemoteChanCfg, + ) + if err != nil { + return nil, err + } + + // Look up the script on the commitment transaction. It may not be + // present if there is no output paying to us. + found, index := input.FindScriptOutputIndex(commitTx, localAnchor.PkScript) + if !found { + return nil, nil + } + + outPoint := &wire.OutPoint{ + Hash: commitTx.TxHash(), + Index: index, + } + + // Instantiate the sign descriptor that allows sweeping of the anchor. + signDesc := &input.SignDescriptor{ + KeyDesc: chanState.LocalChanCfg.MultiSigKey, + WitnessScript: localAnchor.WitnessScript, + Output: &wire.TxOut{ + PkScript: localAnchor.PkScript, + Value: int64(anchorSize), + }, + HashType: txscript.SigHashAll, + } + + return &AnchorResolution{ + CommitAnchor: *outPoint, + AnchorSignDescriptor: *signDesc, + }, nil +} + // AvailableBalance returns the current balance available for sending within // the channel. By available balance, we mean that if at this very instance a // new commitment were to be created which evals all the log entries, what diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 1b1ac942c4..47355f5706 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -526,13 +526,36 @@ func TestCooperativeChannelClosure(t *testing.T) { // force close generates HTLC resolutions that are capable of sweeping both // incoming and outgoing HTLC's. func TestForceClose(t *testing.T) { + t.Run("tweakless", func(t *testing.T) { + testForceClose(t, &forceCloseTestCase{ + chanType: channeldb.SingleFunderTweaklessBit, + expectedCommitWeight: input.CommitWeight, + }) + }) + t.Run("anchors", func(t *testing.T) { + testForceClose(t, &forceCloseTestCase{ + chanType: channeldb.SingleFunderTweaklessBit | + channeldb.AnchorOutputsBit, + expectedCommitWeight: input.AnchorCommitWeight, + anchorAmt: anchorSize * 2, + }) + }) +} + +type forceCloseTestCase struct { + chanType channeldb.ChannelType + expectedCommitWeight int64 + anchorAmt btcutil.Amount +} + +func testForceClose(t *testing.T, testCase *forceCloseTestCase) { t.Parallel() // Create a test channel which will be used for the duration of this // unittest. The channel will be funded evenly with Alice having 5 BTC, // and Bob having 5 BTC. aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( - channeldb.SingleFunderTweaklessBit, + testCase.chanType, ) if err != nil { t.Fatalf("unable to create test channels: %v", err) @@ -594,6 +617,36 @@ func TestForceClose(t *testing.T) { 1, len(closeSummary.HtlcResolutions.IncomingHTLCs)) } + // Verify the anchor resolutions for the anchor commitment format. + if testCase.chanType.HasAnchors() { + // Check the close summary resolution. + anchorRes := closeSummary.AnchorResolution + if anchorRes == nil { + t.Fatal("expected anchor resolution") + } + if anchorRes.CommitAnchor.Hash != closeSummary.CloseTx.TxHash() { + t.Fatal("commit tx not referenced by anchor res") + } + if anchorRes.AnchorSignDescriptor.Output.Value != + int64(anchorSize) { + + t.Fatal("unexpected anchor size") + } + if anchorRes.AnchorSignDescriptor.WitnessScript == nil { + t.Fatal("expected anchor witness script") + } + + // Check the pre-confirmation resolutions. + resList, err := aliceChannel.NewAnchorResolutions() + if err != nil { + t.Fatalf("pre-confirmation resolution error: %v", err) + } + + if len(resList) != 2 { + t.Fatal("expected two resolutions") + } + } + // The SelfOutputSignDesc should be non-nil since the output to-self is // non-dust. aliceCommitResolution := closeSummary.CommitResolution @@ -612,12 +665,16 @@ func TestForceClose(t *testing.T) { // Factoring in the fee rate, Alice's amount should properly reflect // that we've added two additional HTLC to the commitment transaction. - totalCommitWeight := int64(input.CommitWeight + (input.HTLCWeight * 2)) + totalCommitWeight := testCase.expectedCommitWeight + + (input.HTLCWeight * 2) feePerKw := chainfee.SatPerKWeight( aliceChannel.channelState.LocalCommitment.FeePerKw, ) commitFee := feePerKw.FeeForWeight(totalCommitWeight) - expectedAmount := (aliceChannel.Capacity / 2) - htlcAmount.ToSatoshis() - commitFee + + expectedAmount := (aliceChannel.Capacity / 2) - + htlcAmount.ToSatoshis() - commitFee - testCase.anchorAmt + if aliceCommitResolution.SelfOutputSignDesc.Output.Value != int64(expectedAmount) { t.Fatalf("alice incorrect output value in SelfOutputSignDesc, "+ "expected %v, got %v", int64(expectedAmount), From 1c93e9e03d7bb2fe8d89faea5c4ca01a6069cfcd Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 9 Dec 2019 12:17:58 +0100 Subject: [PATCH 221/562] sweep: isolate min fee rate bucket --- sweep/sweeper.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 5997149348..95c0ff2be4 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -714,7 +714,15 @@ func (s *UtxoSweeper) sweepCluster(cluster inputCluster, func (s *UtxoSweeper) bucketForFeeRate( feeRate chainfee.SatPerKWeight) int { - return int(feeRate-s.relayFeeRate) / s.cfg.FeeRateBucketSize + // Create an isolated bucket for sweeps at the minimum fee rate. This is + // to prevent very small outputs (anchors) from becoming uneconomical if + // their fee rate would be averaged with higher fee rate inputs in a + // regular bucket. + if feeRate == s.relayFeeRate { + return 0 + } + + return 1 + int(feeRate-s.relayFeeRate)/s.cfg.FeeRateBucketSize } // clusterBySweepFeeRate takes the set of pending inputs within the UtxoSweeper From 29e1489179bccb6ac6568111b7341669c583f949 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 11 Mar 2020 18:14:26 +0100 Subject: [PATCH 222/562] sweep: leave exclusive group unchanged on parameter update Exclusive group is a static property that doesn't need to be updated. Requiring the exclusive group to be passed into UpdateParams creates a burden for the caller to make sure they supply the existing group. This change will be beneficial for users that bump anchor sweeps that have exclusive groups set. --- lnrpc/walletrpc/walletkit_server.go | 2 +- sweep/sweeper.go | 26 ++++++++++++++++++++++---- sweep/sweeper_test.go | 6 +++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 42534c653e..1cc5282daf 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -486,7 +486,7 @@ func (w *WalletKit) BumpFee(ctx context.Context, // bump its fee, which will result in a replacement transaction (RBF) // being broadcast. If it is not aware of the input however, // lnwallet.ErrNotMine is returned. - params := sweep.Params{ + params := sweep.ParamsUpdate{ Fee: feePreference, Force: in.Force, } diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 95c0ff2be4..f176f703ba 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -82,6 +82,18 @@ type Params struct { ExclusiveGroup *uint64 } +// ParamsUpdate contains a new set of parameters to update a pending sweep with. +type ParamsUpdate struct { + // Fee is the fee preference of the client who requested the input to be + // swept. If a confirmation target is specified, then we'll map it into + // a fee rate whenever we attempt to cluster inputs for a sweep. + Fee FeePreference + + // Force indicates whether the input should be swept regardless of + // whether it is economical to do so. + Force bool +} + // String returns a human readable interpretation of the sweep parameters. func (p Params) String() string { return fmt.Sprintf("fee=%v, force=%v, exclusive_group=%v", @@ -174,7 +186,7 @@ type PendingInput struct { // intent to update the sweep parameters of a given input. type updateReq struct { input wire.OutPoint - params Params + params ParamsUpdate responseChan chan *updateResp } @@ -1119,7 +1131,7 @@ func (s *UtxoSweeper) handlePendingSweepsReq( // is actually successful. The responsibility of doing so should be handled by // the caller. func (s *UtxoSweeper) UpdateParams(input wire.OutPoint, - params Params) (chan Result, error) { + params ParamsUpdate) (chan Result, error) { // Ensure the client provided a sane fee preference. if _, err := s.feeRateForPreference(params.Fee); err != nil { @@ -1169,10 +1181,16 @@ func (s *UtxoSweeper) handleUpdateReq(req *updateReq, bestHeight int32) ( return nil, lnwallet.ErrNotMine } + // Create the updated parameters struct. Leave the exclusive group + // unchanged. + newParams := pendingInput.params + newParams.Fee = req.params.Fee + newParams.Force = req.params.Force + log.Debugf("Updating sweep parameters for %v from %v to %v", req.input, - pendingInput.params, req.params) + pendingInput.params, newParams) - pendingInput.params = req.params + pendingInput.params = newParams // We'll reset the input's publish height to the current so that a new // transaction can be created that replaces the transaction currently diff --git a/sweep/sweeper_test.go b/sweep/sweeper_test.go index 85908f7e81..5fbfce4c01 100644 --- a/sweep/sweeper_test.go +++ b/sweep/sweeper_test.go @@ -1179,7 +1179,7 @@ func TestBumpFeeRBF(t *testing.T) { // We'll first try to bump the fee of an output currently unknown to the // UtxoSweeper. Doing so should result in a lnwallet.ErrNotMine error. _, err := ctx.sweeper.UpdateParams( - wire.OutPoint{}, Params{Fee: lowFeePref}, + wire.OutPoint{}, ParamsUpdate{Fee: lowFeePref}, ) if err != lnwallet.ErrNotMine { t.Fatalf("expected error lnwallet.ErrNotMine, got \"%v\"", err) @@ -1208,13 +1208,13 @@ func TestBumpFeeRBF(t *testing.T) { ctx.estimator.blocksToFee[highFeePref.ConfTarget] = highFeeRate // We should expect to see an error if a fee preference isn't provided. - _, err = ctx.sweeper.UpdateParams(*input.OutPoint(), Params{}) + _, err = ctx.sweeper.UpdateParams(*input.OutPoint(), ParamsUpdate{}) if err != ErrNoFeePreference { t.Fatalf("expected ErrNoFeePreference, got %v", err) } bumpResult, err := ctx.sweeper.UpdateParams( - *input.OutPoint(), Params{Fee: highFeePref}, + *input.OutPoint(), ParamsUpdate{Fee: highFeePref}, ) if err != nil { t.Fatalf("unable to bump input's fee: %v", err) From c0b1b3be140637b27889ccdb14cf2eaa08331a29 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 12 Mar 2020 14:08:06 +0100 Subject: [PATCH 223/562] cnct: always set trigger height to close height Prior to this change, the trigger height for closed channels was set to the current best block height. As this height is in some cases used as a height hint, the spend may have been missed. --- contractcourt/channel_arbitrator.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 2a58ea523e..1c4ee8e815 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -354,9 +354,6 @@ func (c *ChannelArbitrator) Start() error { return err } - log.Infof("ChannelArbitrator(%v): starting state=%v", c.cfg.ChanPoint, - c.state) - _, bestHeight, err := c.cfg.ChainIO.GetBestBlock() if err != nil { c.cfg.BlockEpochs.Cancel() @@ -391,14 +388,19 @@ func (c *ChannelArbitrator) Start() error { case channeldb.RemoteForceClose: trigger = remoteCloseTrigger } - triggerHeight = c.cfg.ClosingHeight log.Warnf("ChannelArbitrator(%v): detected stalled "+ - "state=%v for closed channel, using "+ - "trigger=%v", c.cfg.ChanPoint, c.state, trigger) + "state=%v for closed channel", + c.cfg.ChanPoint, c.state) } + + triggerHeight = c.cfg.ClosingHeight } + log.Infof("ChannelArbitrator(%v): starting state=%v, trigger=%v, "+ + "triggerHeight=%v", c.cfg.ChanPoint, c.state, trigger, + triggerHeight) + // Next we'll fetch our confirmed commitment set. This will only exist // if the channel has been closed out on chain for modern nodes. For // older nodes, this won't be found at all, and will rely on the From 7f3d4e7d49dd470c627f71cfd4b20447de42896e Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 24 Jan 2020 09:38:24 +0100 Subject: [PATCH 224/562] cnct: create channel interface for arbitrator Allows unit testing of the channel arbitrator with fewer dependencies. This is a preparation for the addition of anchor sweeping. --- contractcourt/chain_arbitrator.go | 99 ++++++++++++++++-------- contractcourt/channel_arbitrator.go | 26 ++++--- contractcourt/channel_arbitrator_test.go | 18 +++-- 3 files changed, 94 insertions(+), 49 deletions(-) diff --git a/contractcourt/chain_arbitrator.go b/contractcourt/chain_arbitrator.go index 7a9cb3095c..4d97b10ba3 100644 --- a/contractcourt/chain_arbitrator.go +++ b/contractcourt/chain_arbitrator.go @@ -220,6 +220,61 @@ func NewChainArbitrator(cfg ChainArbitratorConfig, } } +// arbChannel is a wrapper around an open channel that channel arbitrators +// interact with. +type arbChannel struct { + // channel is the in-memory channel state. + channel *channeldb.OpenChannel + + // c references the chain arbitrator and is used by arbChannel + // internally. + c *ChainArbitrator +} + +// ForceCloseChan should force close the contract that this attendant is +// watching over. We'll use this when we decide that we need to go to chain. It +// should in addition tell the switch to remove the corresponding link, such +// that we won't accept any new updates. The returned summary contains all items +// needed to eventually resolve all outputs on chain. +// +// NOTE: Part of the ArbChannel interface. +func (a *arbChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error) { + // First, we mark the channel as borked, this ensure + // that no new state transitions can happen, and also + // that the link won't be loaded into the switch. + if err := a.channel.MarkBorked(); err != nil { + return nil, err + } + + // With the channel marked as borked, we'll now remove + // the link from the switch if its there. If the link + // is active, then this method will block until it + // exits. + chanPoint := a.channel.FundingOutpoint + + if err := a.c.cfg.MarkLinkInactive(chanPoint); err != nil { + log.Errorf("unable to mark link inactive: %v", err) + } + + // Now that we know the link can't mutate the channel + // state, we'll read the channel from disk the target + // channel according to its channel point. + channel, err := a.c.chanSource.FetchChannel(chanPoint) + if err != nil { + return nil, err + } + + // Finally, we'll force close the channel completing + // the force close workflow. + chanMachine, err := lnwallet.NewLightningChannel( + a.c.cfg.Signer, channel, nil, + ) + if err != nil { + return nil, err + } + return chanMachine.ForceClose() +} + // newActiveChannelArbitrator creates a new instance of an active channel // arbitrator given the state of the target channel. func newActiveChannelArbitrator(channel *channeldb.OpenChannel, @@ -247,42 +302,10 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel, // all interfaces and methods the arbitrator needs to do its job. arbCfg := ChannelArbitratorConfig{ ChanPoint: chanPoint, + Channel: c.getArbChannel(channel), ShortChanID: channel.ShortChanID(), BlockEpochs: blockEpoch, - ForceCloseChan: func() (*lnwallet.LocalForceCloseSummary, error) { - // First, we mark the channel as borked, this ensure - // that no new state transitions can happen, and also - // that the link won't be loaded into the switch. - if err := channel.MarkBorked(); err != nil { - return nil, err - } - - // With the channel marked as borked, we'll now remove - // the link from the switch if its there. If the link - // is active, then this method will block until it - // exits. - if err := c.cfg.MarkLinkInactive(chanPoint); err != nil { - log.Errorf("unable to mark link inactive: %v", err) - } - - // Now that we know the link can't mutate the channel - // state, we'll read the channel from disk the target - // channel according to its channel point. - channel, err := c.chanSource.FetchChannel(chanPoint) - if err != nil { - return nil, err - } - // Finally, we'll force close the channel completing - // the force close workflow. - chanMachine, err := lnwallet.NewLightningChannel( - c.cfg.Signer, channel, nil, - ) - if err != nil { - return nil, err - } - return chanMachine.ForceClose() - }, MarkCommitmentBroadcasted: channel.MarkCommitmentBroadcasted, MarkChannelClosed: func(summary *channeldb.ChannelCloseSummary, statuses ...channeldb.ChannelStatus) error { @@ -339,6 +362,16 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel, ), nil } +// getArbChannel returns an open channel wrapper for use by channel arbitrators. +func (c *ChainArbitrator) getArbChannel( + channel *channeldb.OpenChannel) *arbChannel { + + return &arbChannel{ + channel: channel, + c: c, + } +} + // ResolveContract marks a contract as fully resolved within the database. // This is only to be done once all contracts which were live on the channel // before hitting the chain have been resolved. diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 1c4ee8e815..8c6ba27125 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -64,6 +64,18 @@ type WitnessBeacon interface { AddPreimages(preimages ...lntypes.Preimage) error } +// ArbChannel is an abstraction that allows the channel arbitrator to interact +// with an open channel. +type ArbChannel interface { + // ForceCloseChan should force close the contract that this attendant + // is watching over. We'll use this when we decide that we need to go + // to chain. It should in addition tell the switch to remove the + // corresponding link, such that we won't accept any new updates. The + // returned summary contains all items needed to eventually resolve all + // outputs on chain. + ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error) +} + // ChannelArbitratorConfig contains all the functionality that the // ChannelArbitrator needs in order to properly arbitrate any contract dispute // on chain. @@ -72,6 +84,10 @@ type ChannelArbitratorConfig struct { // channel. ChanPoint wire.OutPoint + // Channel is the full channel data structure. For legacy channels, this + // field may not always be set after a restart. + Channel ArbChannel + // ShortChanID describes the exact location of the channel within the // chain. We'll use this to address any messages that we need to send // to the switch during contract resolution. @@ -88,14 +104,6 @@ type ChannelArbitratorConfig struct { // channel. ChainEvents *ChainEventSubscription - // ForceCloseChan should force close the contract that this attendant - // is watching over. We'll use this when we decide that we need to go - // to chain. It should in addition tell the switch to remove the - // corresponding link, such that we won't accept any new updates. The - // returned summary contains all items needed to eventually resolve all - // outputs on chain. - ForceCloseChan func() (*lnwallet.LocalForceCloseSummary, error) - // MarkCommitmentBroadcasted should mark the channel as the commitment // being broadcast, and we are waiting for the commitment to confirm. MarkCommitmentBroadcasted func(*wire.MsgTx, bool) error @@ -791,7 +799,7 @@ func (c *ChannelArbitrator) stateStep( // We'll tell the switch that it should remove the link for // this channel, in addition to fetching the force close // summary needed to close this channel on chain. - closeSummary, err := c.cfg.ForceCloseChan() + closeSummary, err := c.cfg.Channel.ForceCloseChan() if err != nil { log.Errorf("ChannelArbitrator(%v): unable to "+ "force close: %v", c.cfg.ChanPoint, err) diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index b330189286..46316d0cb9 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -360,13 +360,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog, resolvedChan <- struct{}{} return nil }, - ForceCloseChan: func() (*lnwallet.LocalForceCloseSummary, error) { - summary := &lnwallet.LocalForceCloseSummary{ - CloseTx: &wire.MsgTx{}, - HtlcResolutions: &lnwallet.HtlcResolutions{}, - } - return summary, nil - }, + Channel: &mockChannel{}, MarkCommitmentBroadcasted: func(_ *wire.MsgTx, _ bool) error { return nil }, @@ -2088,3 +2082,13 @@ func TestRemoteCloseInitiator(t *testing.T) { }) } } + +type mockChannel struct{} + +func (m *mockChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error) { + summary := &lnwallet.LocalForceCloseSummary{ + CloseTx: &wire.MsgTx{}, + HtlcResolutions: &lnwallet.HtlcResolutions{}, + } + return summary, nil +} From dd77d9263e1b7f66ca284a02d99797cfaaac08dc Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 24 Jan 2020 12:08:13 +0100 Subject: [PATCH 225/562] cnct: persist anchor resolutions --- contractcourt/briefcase.go | 74 ++++++++++++++++++++++++++++- contractcourt/briefcase_test.go | 13 +++++ contractcourt/channel_arbitrator.go | 2 + 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/contractcourt/briefcase.go b/contractcourt/briefcase.go index 22adcbdc1d..6a3bfa8b8a 100644 --- a/contractcourt/briefcase.go +++ b/contractcourt/briefcase.go @@ -29,6 +29,11 @@ type ContractResolutions struct { // HtlcResolutions contains all data required to fully resolve any // incoming+outgoing HTLC's present within the commitment transaction. HtlcResolutions lnwallet.HtlcResolutions + + // AnchorResolution contains the data required to sweep the anchor + // output. If the channel type doesn't include anchors, the value of + // this field will be nil. + AnchorResolution *lnwallet.AnchorResolution } // IsEmpty returns true if the set of resolutions is "empty". A resolution is @@ -37,7 +42,8 @@ type ContractResolutions struct { func (c *ContractResolutions) IsEmpty() bool { return c.CommitResolution == nil && len(c.HtlcResolutions.IncomingHTLCs) == 0 && - len(c.HtlcResolutions.OutgoingHTLCs) == 0 + len(c.HtlcResolutions.OutgoingHTLCs) == 0 && + c.AnchorResolution == nil } // ArbitratorLog is the primary source of persistent storage for the @@ -263,6 +269,10 @@ var ( // the full set of resolutions for a channel. resolutionsKey = []byte("resolutions") + // anchorResolutionKey is the key under the logScope that we'll use to + // store the anchor resolution, if any. + anchorResolutionKey = []byte("anchor-resolution") + // actionsBucketKey is the key under the logScope that we'll use to // store all chain actions once they're determined. actionsBucketKey = []byte("chain-actions") @@ -630,7 +640,26 @@ func (b *boltArbitratorLog) LogContractResolutions(c *ContractResolutions) error } } - return scopeBucket.Put(resolutionsKey, b.Bytes()) + err = scopeBucket.Put(resolutionsKey, b.Bytes()) + if err != nil { + return err + } + + // Write out the anchor resolution if present. + if c.AnchorResolution != nil { + var b bytes.Buffer + err := encodeAnchorResolution(&b, c.AnchorResolution) + if err != nil { + return err + } + + err = scopeBucket.Put(anchorResolutionKey, b.Bytes()) + if err != nil { + return err + } + } + + return nil }) } @@ -710,6 +739,18 @@ func (b *boltArbitratorLog) FetchContractResolutions() (*ContractResolutions, er } } + anchorResBytes := scopeBucket.Get(anchorResolutionKey) + if anchorResBytes != nil { + c.AnchorResolution = &lnwallet.AnchorResolution{} + resReader := bytes.NewReader(anchorResBytes) + err := decodeAnchorResolution( + resReader, c.AnchorResolution, + ) + if err != nil { + return err + } + } + return nil }) if err != nil { @@ -1045,6 +1086,35 @@ func decodeCommitResolution(r io.Reader, return binary.Read(r, endian, &c.MaturityDelay) } +func encodeAnchorResolution(w io.Writer, + a *lnwallet.AnchorResolution) error { + + if _, err := w.Write(a.CommitAnchor.Hash[:]); err != nil { + return err + } + err := binary.Write(w, endian, a.CommitAnchor.Index) + if err != nil { + return err + } + + return input.WriteSignDescriptor(w, &a.AnchorSignDescriptor) +} + +func decodeAnchorResolution(r io.Reader, + a *lnwallet.AnchorResolution) error { + + _, err := io.ReadFull(r, a.CommitAnchor.Hash[:]) + if err != nil { + return err + } + err = binary.Read(r, endian, &a.CommitAnchor.Index) + if err != nil { + return err + } + + return input.ReadSignDescriptor(r, &a.AnchorSignDescriptor) +} + func encodeHtlcSetKey(w io.Writer, h *HtlcSetKey) error { err := binary.Write(w, endian, h.IsRemote) if err != nil { diff --git a/contractcourt/briefcase_test.go b/contractcourt/briefcase_test.go index 0cccd5a6cb..3408b2c65f 100644 --- a/contractcourt/briefcase_test.go +++ b/contractcourt/briefcase_test.go @@ -46,6 +46,15 @@ var ( Index: 2, } + testChanPoint3 = wire.OutPoint{ + Hash: chainhash.Hash{ + 0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17, + 0x51, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda, + 0x2d, 0xe7, 0x93, 0xe4, + }, + Index: 3, + } + testPreimage = [32]byte{ 0x52, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda, 0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17, @@ -540,6 +549,10 @@ func TestContractResolutionsStorage(t *testing.T) { }, }, }, + AnchorResolution: &lnwallet.AnchorResolution{ + CommitAnchor: testChanPoint3, + AnchorSignDescriptor: testSignDesc, + }, } // First make sure that fetching unlogged contract resolutions will diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 8c6ba27125..6b517daf42 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -2090,6 +2090,7 @@ func (c *ChannelArbitrator) channelAttendant(bestHeight int32) { CommitHash: closeTx.TxHash(), CommitResolution: closeInfo.CommitResolution, HtlcResolutions: *closeInfo.HtlcResolutions, + AnchorResolution: closeInfo.AnchorResolution, } // When processing a unilateral close event, we'll @@ -2156,6 +2157,7 @@ func (c *ChannelArbitrator) channelAttendant(bestHeight int32) { CommitHash: *uniClosure.SpenderTxHash, CommitResolution: uniClosure.CommitResolution, HtlcResolutions: *uniClosure.HtlcResolutions, + AnchorResolution: uniClosure.AnchorResolution, } // When processing a unilateral close event, we'll From c376cdb733103ef04caabd7e1351820ed5361397 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 10 Mar 2020 13:23:17 +0100 Subject: [PATCH 226/562] input: add anchor witness type --- input/size.go | 45 +++++++++ input/size_test.go | 8 ++ input/witnessgen.go | 21 +++++ lnrpc/walletrpc/walletkit.pb.go | 140 +++++++++++++++------------- lnrpc/walletrpc/walletkit.proto | 6 ++ lnrpc/walletrpc/walletkit_server.go | 2 + 6 files changed, 155 insertions(+), 67 deletions(-) diff --git a/input/size.go b/input/size.go index 3db21fbbc3..32a89bcda3 100644 --- a/input/size.go +++ b/input/size.go @@ -1,8 +1,12 @@ package input import ( + "math/big" + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/keychain" ) const ( @@ -406,6 +410,47 @@ const ( OfferedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + OfferedHtlcScriptSize ) +// dummySigner is a fake signer used for size (upper bound) calculations. +type dummySigner struct { + Signer +} + +// SignOutputRaw generates a signature for the passed transaction according to +// the data within the passed SignDescriptor. +func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ( + []byte, error) { + + // Always return worst-case signature length, excluding the one byte + // sighash flag. + return make([]byte, 73-1), nil +} + +var ( + // dummyPubKey is a pubkey used in script size calculation. + dummyPubKey = btcec.PublicKey{ + X: &big.Int{}, + Y: &big.Int{}, + } + + // dummyAnchorScript is a script used for size calculation. + dummyAnchorScript, _ = CommitScriptAnchor(&dummyPubKey) + + // dummyAnchorWitness is a witness used for size calculation. + dummyAnchorWitness, _ = CommitSpendAnchor( + &dummySigner{}, + &SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + PubKey: &dummyPubKey, + }, + WitnessScript: dummyAnchorScript, + }, + nil, + ) + + // AnchorWitnessSize 116 bytes + AnchorWitnessSize = dummyAnchorWitness.SerializeSize() +) + // EstimateCommitTxWeight estimate commitment transaction weight depending on // the precalculated weight of base transaction, witness data, which is needed // for paying for funding tx, and htlc weight multiplied by their count. diff --git a/input/size_test.go b/input/size_test.go index 9164340225..fb57427c3b 100644 --- a/input/size_test.go +++ b/input/size_test.go @@ -280,3 +280,11 @@ func TestTxWeightEstimator(t *testing.T) { } } } + +// TestSizes guards calculated constants to make sure their values remain +// unchanged. +func TestSizes(t *testing.T) { + if input.AnchorWitnessSize != 116 { + t.Fatal("unexpected anchor witness size") + } +} diff --git a/input/witnessgen.go b/input/witnessgen.go index 7fc509cb61..1a1fba6ea9 100644 --- a/input/witnessgen.go +++ b/input/witnessgen.go @@ -125,6 +125,10 @@ const ( // output on the counterparty's commitment transaction after a // confirmation. CommitmentToRemoteConfirmed StandardWitnessType = 13 + + // CommitmentAnchor is a witness that allows us to spend our anchor on + // the commitment transaction. + CommitmentAnchor StandardWitnessType = 14 ) // String returns a human readable version of the target WitnessType. @@ -138,6 +142,9 @@ func (wt StandardWitnessType) String() string { case CommitmentToRemoteConfirmed: return "CommitmentToRemoteConfirmed" + case CommitmentAnchor: + return "CommitmentAnchor" + case CommitmentNoDelay: return "CommitmentNoDelay" @@ -218,6 +225,16 @@ func (wt StandardWitnessType) WitnessGenerator(signer Signer, Witness: witness, }, nil + case CommitmentAnchor: + witness, err := CommitSpendAnchor(signer, desc, tx) + if err != nil { + return nil, err + } + + return &Script{ + Witness: witness, + }, nil + case CommitmentNoDelay: witness, err := CommitSpendNoDelay(signer, desc, tx, false) if err != nil { @@ -348,6 +365,10 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case CommitmentToRemoteConfirmed: return ToRemoteConfirmedWitnessSize, false, nil + // Anchor output on the commitment transaction. + case CommitmentAnchor: + return AnchorWitnessSize, false, nil + // Outgoing second layer HTLC's that have confirmed within the // chain, and the output they produced is now mature enough to // sweep. diff --git a/lnrpc/walletrpc/walletkit.pb.go b/lnrpc/walletrpc/walletkit.pb.go index a8b5623679..ce1e081375 100644 --- a/lnrpc/walletrpc/walletkit.pb.go +++ b/lnrpc/walletrpc/walletkit.pb.go @@ -84,6 +84,10 @@ const ( //A witness type that allows us to sweep an output that sends to a nested P2SH //script that pays to a key solely under our control. WitnessType_NESTED_WITNESS_KEY_HASH WitnessType = 12 + // + //A witness type that allows us to spend our anchor on the commitment + //transaction. + WitnessType_COMMITMENT_ANCHOR WitnessType = 13 ) var WitnessType_name = map[int32]string{ @@ -100,6 +104,7 @@ var WitnessType_name = map[int32]string{ 10: "HTLC_SECOND_LEVEL_REVOKE", 11: "WITNESS_KEY_HASH", 12: "NESTED_WITNESS_KEY_HASH", + 13: "COMMITMENT_ANCHOR", } var WitnessType_value = map[string]int32{ @@ -116,6 +121,7 @@ var WitnessType_value = map[string]int32{ "HTLC_SECOND_LEVEL_REVOKE": 10, "WITNESS_KEY_HASH": 11, "NESTED_WITNESS_KEY_HASH": 12, + "COMMITMENT_ANCHOR": 13, } func (x WitnessType) String() string { @@ -828,73 +834,73 @@ func init() { func init() { proto.RegisterFile("walletrpc/walletkit.proto", fileDescriptor_6cc6942ac78249e5) } var fileDescriptor_6cc6942ac78249e5 = []byte{ - // 1047 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x6b, 0x6f, 0xea, 0x46, - 0x10, 0x2d, 0x21, 0x21, 0x30, 0x40, 0x42, 0x96, 0x3c, 0x7c, 0xb9, 0xb9, 0x0d, 0x75, 0x1f, 0x42, - 0x7d, 0x80, 0x9a, 0xa8, 0x55, 0x1f, 0x52, 0xd5, 0x84, 0x38, 0x22, 0x82, 0x60, 0x6a, 0x3b, 0x37, - 0xba, 0x55, 0xa5, 0x95, 0x03, 0x1b, 0x62, 0x01, 0xb6, 0xef, 0x7a, 0x29, 0xf8, 0x6b, 0x7f, 0x44, - 0xa5, 0xfe, 0x95, 0xfe, 0xba, 0xca, 0xeb, 0x07, 0x6b, 0x68, 0x2a, 0xf5, 0x53, 0xf0, 0x39, 0x67, - 0x8e, 0x67, 0x67, 0xc7, 0x33, 0x81, 0x57, 0x0b, 0x73, 0x3a, 0x25, 0x8c, 0xba, 0xc3, 0x56, 0xf8, - 0x6b, 0x62, 0xb1, 0xa6, 0x4b, 0x1d, 0xe6, 0xa0, 0x42, 0x42, 0xd5, 0x0a, 0xd4, 0x1d, 0x86, 0x68, - 0xed, 0xd0, 0xb3, 0xc6, 0x76, 0x20, 0x0f, 0xfe, 0x12, 0x1a, 0xa2, 0xf2, 0x2f, 0x90, 0xeb, 0x12, - 0x5f, 0x23, 0xef, 0x51, 0x03, 0x2a, 0x13, 0xe2, 0xe3, 0x27, 0xcb, 0x1e, 0x13, 0x8a, 0x5d, 0x6a, - 0xd9, 0x4c, 0xca, 0xd4, 0x33, 0x8d, 0x1d, 0x6d, 0x6f, 0x42, 0xfc, 0x1b, 0x0e, 0x0f, 0x02, 0x14, - 0xbd, 0x01, 0xe0, 0x4a, 0x73, 0x66, 0x4d, 0x7d, 0x69, 0x8b, 0x6b, 0x0a, 0x81, 0x86, 0x03, 0x72, - 0x19, 0x8a, 0x97, 0xa3, 0x11, 0xd5, 0xc8, 0xfb, 0x39, 0xf1, 0x98, 0x2c, 0x43, 0x29, 0x7c, 0xf4, - 0x5c, 0xc7, 0xf6, 0x08, 0x42, 0xb0, 0x6d, 0x8e, 0x46, 0x94, 0x7b, 0x17, 0x34, 0xfe, 0x5b, 0xfe, - 0x04, 0x8a, 0x06, 0x35, 0x6d, 0xcf, 0x1c, 0x32, 0xcb, 0xb1, 0xd1, 0x11, 0xe4, 0xd8, 0x12, 0x3f, - 0x93, 0x25, 0x17, 0x95, 0xb4, 0x1d, 0xb6, 0xec, 0x90, 0xa5, 0xfc, 0x2d, 0xec, 0x0f, 0xe6, 0x8f, - 0x53, 0xcb, 0x7b, 0x4e, 0xcc, 0x3e, 0x86, 0xb2, 0x1b, 0x42, 0x98, 0x50, 0xea, 0xc4, 0xae, 0xa5, - 0x08, 0x54, 0x02, 0x4c, 0xfe, 0x0d, 0x90, 0x4e, 0xec, 0x91, 0x3a, 0x67, 0xee, 0x9c, 0x79, 0x51, - 0x5e, 0xe8, 0x14, 0xc0, 0x33, 0x19, 0x76, 0x09, 0xc5, 0x93, 0x05, 0x8f, 0xcb, 0x6a, 0x79, 0xcf, - 0x64, 0x03, 0x42, 0xbb, 0x0b, 0xd4, 0x80, 0x5d, 0x27, 0xd4, 0x4b, 0x5b, 0xf5, 0x6c, 0xa3, 0x78, - 0xbe, 0xd7, 0x8c, 0xea, 0xd7, 0x34, 0x96, 0xea, 0x9c, 0x69, 0x31, 0x2d, 0x7f, 0x09, 0xd5, 0x94, - 0x7b, 0x94, 0xd9, 0x11, 0xe4, 0xa8, 0xb9, 0xc0, 0x2c, 0x39, 0x03, 0x35, 0x17, 0xc6, 0x52, 0xfe, - 0x06, 0x90, 0xe2, 0x31, 0x6b, 0x66, 0x32, 0x72, 0x43, 0x48, 0x9c, 0xcb, 0x19, 0x14, 0x87, 0x8e, - 0xfd, 0x84, 0x99, 0x49, 0xc7, 0x24, 0x2e, 0x3b, 0x04, 0x90, 0xc1, 0x11, 0xf9, 0x02, 0xaa, 0xa9, - 0xb0, 0xe8, 0x25, 0xff, 0x79, 0x06, 0xf9, 0xaf, 0x2c, 0x94, 0x06, 0xc4, 0x1e, 0x59, 0xf6, 0x58, - 0x5f, 0x10, 0xe2, 0xa2, 0x2f, 0x20, 0x1f, 0x64, 0xed, 0xc4, 0x57, 0x5b, 0x3c, 0xdf, 0x6f, 0x4e, - 0xf9, 0x99, 0xd4, 0x39, 0x1b, 0x04, 0xb0, 0x96, 0x08, 0xd0, 0xf7, 0x50, 0x5a, 0x58, 0xcc, 0x26, - 0x9e, 0x87, 0x99, 0xef, 0x12, 0x7e, 0xcf, 0x7b, 0xe7, 0xc7, 0xcd, 0xa4, 0xb9, 0x9a, 0x0f, 0x21, - 0x6d, 0xf8, 0x2e, 0xd1, 0x8a, 0x8b, 0xd5, 0x43, 0xd0, 0x20, 0xe6, 0xcc, 0x99, 0xdb, 0x0c, 0x7b, - 0x26, 0x93, 0xb2, 0xf5, 0x4c, 0xa3, 0xac, 0x15, 0x42, 0x44, 0x37, 0x19, 0xaa, 0x43, 0x29, 0xce, - 0xfa, 0xd1, 0x67, 0x44, 0xda, 0xe6, 0x02, 0x08, 0xf3, 0xbe, 0xf2, 0x19, 0x41, 0x5f, 0x01, 0x7a, - 0xa4, 0x8e, 0x39, 0x1a, 0x9a, 0x1e, 0xc3, 0x26, 0x63, 0x64, 0xe6, 0x32, 0x4f, 0xda, 0xe1, 0xba, - 0x83, 0x84, 0xb9, 0x8c, 0x08, 0x74, 0x0e, 0x47, 0x36, 0x59, 0x32, 0xbc, 0x8a, 0x79, 0x26, 0xd6, - 0xf8, 0x99, 0x49, 0x39, 0x1e, 0x51, 0x0d, 0xc8, 0xab, 0x98, 0xeb, 0x70, 0x2a, 0x88, 0xa1, 0x61, - 0xf5, 0xc9, 0x08, 0x8b, 0xc5, 0xcf, 0x87, 0x31, 0x09, 0xd9, 0x4e, 0x6e, 0x01, 0x5d, 0xc0, 0xf1, - 0x2a, 0x26, 0x75, 0x84, 0xc2, 0x5a, 0x90, 0xbe, 0x3a, 0xcb, 0x21, 0xec, 0x3c, 0x39, 0x74, 0x48, - 0xa4, 0xdd, 0x7a, 0xa6, 0x91, 0xd7, 0xc2, 0x07, 0xf9, 0x18, 0x0e, 0xc5, 0xab, 0x89, 0xbb, 0x52, - 0x7e, 0x80, 0xa3, 0x35, 0x3c, 0xba, 0xea, 0x9f, 0x60, 0xcf, 0x0d, 0x09, 0xec, 0x71, 0x46, 0xca, - 0xf0, 0xbe, 0x3c, 0x11, 0x2e, 0x44, 0x8c, 0xd4, 0xca, 0xae, 0xe8, 0x23, 0xff, 0x99, 0x81, 0xbd, - 0xab, 0xf9, 0xcc, 0x15, 0xba, 0xee, 0x7f, 0xb5, 0xc3, 0x19, 0x14, 0xc3, 0x02, 0xf1, 0x62, 0xf1, - 0x6e, 0x28, 0x6b, 0x10, 0x42, 0x41, 0x89, 0x36, 0x6e, 0x35, 0xbb, 0x71, 0xab, 0x49, 0x25, 0xb6, - 0xc5, 0x4a, 0x1c, 0xc0, 0x7e, 0x92, 0x57, 0x78, 0xd6, 0xcf, 0xff, 0xc8, 0x42, 0x51, 0x68, 0x2e, - 0x54, 0x85, 0xfd, 0xfb, 0x7e, 0xb7, 0xaf, 0x3e, 0xf4, 0xf1, 0xc3, 0xad, 0xd1, 0x57, 0x74, 0xbd, - 0xf2, 0x01, 0x92, 0xe0, 0xb0, 0xad, 0xde, 0xdd, 0xdd, 0x1a, 0x77, 0x4a, 0xdf, 0xc0, 0xc6, 0xed, - 0x9d, 0x82, 0x7b, 0x6a, 0xbb, 0x5b, 0xc9, 0xa0, 0x13, 0xa8, 0x0a, 0x4c, 0x5f, 0xc5, 0xd7, 0x4a, - 0xef, 0xf2, 0x5d, 0x65, 0x0b, 0x1d, 0xc1, 0x81, 0x40, 0x68, 0xca, 0x5b, 0xb5, 0xab, 0x54, 0xb2, - 0x81, 0xbe, 0x63, 0xf4, 0xda, 0x58, 0xbd, 0xb9, 0x51, 0x34, 0xe5, 0x3a, 0x26, 0xb6, 0x83, 0x57, - 0x70, 0xe2, 0xb2, 0xdd, 0x56, 0x06, 0xc6, 0x8a, 0xd9, 0x41, 0x9f, 0xc2, 0x47, 0xa9, 0x90, 0xe0, - 0xf5, 0xea, 0xbd, 0x81, 0x75, 0xa5, 0xad, 0xf6, 0xaf, 0x71, 0x4f, 0x79, 0xab, 0xf4, 0x2a, 0x39, - 0xf4, 0x19, 0xc8, 0x69, 0x03, 0xfd, 0xbe, 0xdd, 0x56, 0x74, 0x3d, 0xad, 0xdb, 0x45, 0x67, 0xf0, - 0x7a, 0x2d, 0x83, 0x3b, 0xd5, 0x50, 0x62, 0xd7, 0x4a, 0x1e, 0xd5, 0xe1, 0x74, 0x3d, 0x13, 0xae, - 0x88, 0xfc, 0x2a, 0x05, 0x74, 0x0a, 0x12, 0x57, 0x88, 0xce, 0x71, 0xbe, 0x80, 0x0e, 0xa1, 0x12, - 0x55, 0x0e, 0x77, 0x95, 0x77, 0xb8, 0x73, 0xa9, 0x77, 0x2a, 0x45, 0xf4, 0x1a, 0x4e, 0xfa, 0x8a, - 0x1e, 0xd8, 0x6d, 0x90, 0xa5, 0xf3, 0xbf, 0xb7, 0xa1, 0xf0, 0xc0, 0x5b, 0xab, 0x6b, 0x31, 0xf4, - 0x03, 0x94, 0xaf, 0x09, 0xb5, 0x7e, 0x27, 0x7d, 0xb2, 0x64, 0x5d, 0xe2, 0xa3, 0x03, 0xa1, 0xef, - 0xc2, 0x0d, 0x52, 0x3b, 0x4e, 0x46, 0x64, 0x97, 0xf8, 0xd7, 0xc4, 0x1b, 0x52, 0xcb, 0x65, 0x0e, - 0x45, 0xdf, 0x41, 0x21, 0x8c, 0x0d, 0xe2, 0xaa, 0xa2, 0xa8, 0xe7, 0x0c, 0x4d, 0xe6, 0xd0, 0x17, - 0x23, 0x7f, 0x84, 0x7c, 0xf0, 0xbe, 0x60, 0x7f, 0x20, 0x71, 0xf2, 0x08, 0xfb, 0xa5, 0x76, 0xb2, - 0x81, 0x47, 0x5f, 0x4c, 0x07, 0x50, 0xb4, 0x2e, 0xc4, 0xdd, 0x22, 0xda, 0x08, 0x78, 0xad, 0x26, - 0x7e, 0x47, 0x6b, 0x5b, 0xa6, 0x07, 0x45, 0x61, 0xc4, 0xa3, 0x37, 0x82, 0x74, 0x73, 0xb1, 0xd4, - 0x3e, 0x7c, 0x89, 0x5e, 0xb9, 0x09, 0xb3, 0x3c, 0xe5, 0xb6, 0xb9, 0x1a, 0x52, 0x6e, 0xff, 0xb6, - 0x02, 0x34, 0x28, 0xa7, 0x06, 0x06, 0x3a, 0x7b, 0x61, 0x20, 0x24, 0xf9, 0xd5, 0x5f, 0x16, 0x44, - 0x9e, 0x3f, 0xc3, 0x6e, 0xf4, 0x49, 0xa2, 0x57, 0x82, 0x38, 0x3d, 0x3e, 0x52, 0x15, 0x5b, 0xfb, - 0x82, 0xaf, 0xbe, 0xfe, 0xb5, 0x35, 0xb6, 0xd8, 0xf3, 0xfc, 0xb1, 0x39, 0x74, 0x66, 0xad, 0x69, - 0x30, 0x71, 0x6d, 0xcb, 0x1e, 0xdb, 0x84, 0x2d, 0x1c, 0x3a, 0x69, 0x4d, 0xed, 0x51, 0x8b, 0x4f, - 0x9a, 0x56, 0x62, 0xf1, 0x98, 0xe3, 0xff, 0x90, 0x5c, 0xfc, 0x13, 0x00, 0x00, 0xff, 0xff, 0x3b, - 0x08, 0xac, 0xe2, 0xd9, 0x08, 0x00, 0x00, + // 1055 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x6b, 0x6f, 0xe2, 0x46, + 0x14, 0x2d, 0x21, 0x21, 0x70, 0x81, 0xc4, 0x19, 0xf2, 0xf0, 0xb2, 0xd9, 0x86, 0xba, 0x0f, 0xa1, + 0x3e, 0x40, 0x4d, 0xd4, 0xaa, 0x0f, 0xa9, 0x2a, 0x21, 0x8e, 0x88, 0x20, 0x98, 0xda, 0xce, 0x46, + 0x5b, 0x55, 0x1a, 0x39, 0x30, 0x21, 0x56, 0xc0, 0xf6, 0x8e, 0x87, 0x02, 0x7f, 0xa4, 0xd2, 0xfe, + 0x95, 0xfe, 0xba, 0xca, 0xe3, 0x07, 0x63, 0x68, 0x2a, 0xf5, 0x53, 0xf0, 0x39, 0xe7, 0x1e, 0xdf, + 0xb9, 0x73, 0x7d, 0x6f, 0xe0, 0xd5, 0xdc, 0x9a, 0x4c, 0x08, 0xa3, 0xde, 0xb0, 0x19, 0xfe, 0x7a, + 0xb6, 0x59, 0xc3, 0xa3, 0x2e, 0x73, 0x51, 0x21, 0xa1, 0xaa, 0x05, 0xea, 0x0d, 0x43, 0xb4, 0x7a, + 0xe8, 0xdb, 0x63, 0x27, 0x90, 0x07, 0x7f, 0x09, 0x0d, 0x51, 0xe5, 0x37, 0xc8, 0x75, 0xc9, 0x52, + 0x27, 0xef, 0x51, 0x1d, 0xa4, 0x67, 0xb2, 0xc4, 0x8f, 0xb6, 0x33, 0x26, 0x14, 0x7b, 0xd4, 0x76, + 0x98, 0x9c, 0xa9, 0x65, 0xea, 0x3b, 0xfa, 0xde, 0x33, 0x59, 0x5e, 0x73, 0x78, 0x10, 0xa0, 0xe8, + 0x0d, 0x00, 0x57, 0x5a, 0x53, 0x7b, 0xb2, 0x94, 0xb7, 0xb8, 0xa6, 0x10, 0x68, 0x38, 0xa0, 0x94, + 0xa1, 0xd8, 0x1a, 0x8d, 0xa8, 0x4e, 0xde, 0xcf, 0x88, 0xcf, 0x14, 0x05, 0x4a, 0xe1, 0xa3, 0xef, + 0xb9, 0x8e, 0x4f, 0x10, 0x82, 0x6d, 0x6b, 0x34, 0xa2, 0xdc, 0xbb, 0xa0, 0xf3, 0xdf, 0xca, 0x67, + 0x50, 0x34, 0xa9, 0xe5, 0xf8, 0xd6, 0x90, 0xd9, 0xae, 0x83, 0x8e, 0x20, 0xc7, 0x16, 0xf8, 0x89, + 0x2c, 0xb8, 0xa8, 0xa4, 0xef, 0xb0, 0x45, 0x87, 0x2c, 0x94, 0xef, 0x61, 0x7f, 0x30, 0x7b, 0x98, + 0xd8, 0xfe, 0x53, 0x62, 0xf6, 0x29, 0x94, 0xbd, 0x10, 0xc2, 0x84, 0x52, 0x37, 0x76, 0x2d, 0x45, + 0xa0, 0x1a, 0x60, 0xca, 0x1f, 0x80, 0x0c, 0xe2, 0x8c, 0xb4, 0x19, 0xf3, 0x66, 0xcc, 0x8f, 0xf2, + 0x42, 0xa7, 0x00, 0xbe, 0xc5, 0xb0, 0x47, 0x28, 0x7e, 0x9e, 0xf3, 0xb8, 0xac, 0x9e, 0xf7, 0x2d, + 0x36, 0x20, 0xb4, 0x3b, 0x47, 0x75, 0xd8, 0x75, 0x43, 0xbd, 0xbc, 0x55, 0xcb, 0xd6, 0x8b, 0xe7, + 0x7b, 0x8d, 0xa8, 0x7e, 0x0d, 0x73, 0xa1, 0xcd, 0x98, 0x1e, 0xd3, 0xca, 0xd7, 0x50, 0x49, 0xb9, + 0x47, 0x99, 0x1d, 0x41, 0x8e, 0x5a, 0x73, 0xcc, 0x92, 0x33, 0x50, 0x6b, 0x6e, 0x2e, 0x94, 0xef, + 0x00, 0xa9, 0x3e, 0xb3, 0xa7, 0x16, 0x23, 0xd7, 0x84, 0xc4, 0xb9, 0x9c, 0x41, 0x71, 0xe8, 0x3a, + 0x8f, 0x98, 0x59, 0x74, 0x4c, 0xe2, 0xb2, 0x43, 0x00, 0x99, 0x1c, 0x51, 0x2e, 0xa0, 0x92, 0x0a, + 0x8b, 0x5e, 0xf2, 0x9f, 0x67, 0x50, 0x3e, 0x64, 0xa1, 0x34, 0x20, 0xce, 0xc8, 0x76, 0xc6, 0xc6, + 0x9c, 0x10, 0x0f, 0x7d, 0x05, 0xf9, 0x20, 0x6b, 0x37, 0xbe, 0xda, 0xe2, 0xf9, 0x7e, 0x63, 0xc2, + 0xcf, 0xa4, 0xcd, 0xd8, 0x20, 0x80, 0xf5, 0x44, 0x80, 0x7e, 0x84, 0xd2, 0xdc, 0x66, 0x0e, 0xf1, + 0x7d, 0xcc, 0x96, 0x1e, 0xe1, 0xf7, 0xbc, 0x77, 0x7e, 0xdc, 0x48, 0x9a, 0xab, 0x71, 0x1f, 0xd2, + 0xe6, 0xd2, 0x23, 0x7a, 0x71, 0xbe, 0x7a, 0x08, 0x1a, 0xc4, 0x9a, 0xba, 0x33, 0x87, 0x61, 0xdf, + 0x62, 0x72, 0xb6, 0x96, 0xa9, 0x97, 0xf5, 0x42, 0x88, 0x18, 0x16, 0x43, 0x35, 0x28, 0xc5, 0x59, + 0x3f, 0x2c, 0x19, 0x91, 0xb7, 0xb9, 0x00, 0xc2, 0xbc, 0x2f, 0x97, 0x8c, 0xa0, 0x6f, 0x00, 0x3d, + 0x50, 0xd7, 0x1a, 0x0d, 0x2d, 0x9f, 0x61, 0x8b, 0x31, 0x32, 0xf5, 0x98, 0x2f, 0xef, 0x70, 0xdd, + 0x41, 0xc2, 0xb4, 0x22, 0x02, 0x9d, 0xc3, 0x91, 0x43, 0x16, 0x0c, 0xaf, 0x62, 0x9e, 0x88, 0x3d, + 0x7e, 0x62, 0x72, 0x8e, 0x47, 0x54, 0x02, 0xf2, 0x32, 0xe6, 0x3a, 0x9c, 0x0a, 0x62, 0x68, 0x58, + 0x7d, 0x32, 0xc2, 0x62, 0xf1, 0xf3, 0x61, 0x4c, 0x42, 0xb6, 0x93, 0x5b, 0x40, 0x17, 0x70, 0xbc, + 0x8a, 0x49, 0x1d, 0xa1, 0xb0, 0x16, 0x64, 0xac, 0xce, 0x72, 0x08, 0x3b, 0x8f, 0x2e, 0x1d, 0x12, + 0x79, 0xb7, 0x96, 0xa9, 0xe7, 0xf5, 0xf0, 0x41, 0x39, 0x86, 0x43, 0xf1, 0x6a, 0xe2, 0xae, 0x54, + 0xee, 0xe1, 0x68, 0x0d, 0x8f, 0xae, 0xfa, 0x17, 0xd8, 0xf3, 0x42, 0x02, 0xfb, 0x9c, 0x91, 0x33, + 0xbc, 0x2f, 0x4f, 0x84, 0x0b, 0x11, 0x23, 0xf5, 0xb2, 0x27, 0xfa, 0x28, 0x7f, 0x65, 0x60, 0xef, + 0x72, 0x36, 0xf5, 0x84, 0xae, 0xfb, 0x5f, 0xed, 0x70, 0x06, 0xc5, 0xb0, 0x40, 0xbc, 0x58, 0xbc, + 0x1b, 0xca, 0x3a, 0x84, 0x50, 0x50, 0xa2, 0x8d, 0x5b, 0xcd, 0x6e, 0xdc, 0x6a, 0x52, 0x89, 0x6d, + 0xb1, 0x12, 0x07, 0xb0, 0x9f, 0xe4, 0x15, 0x9e, 0xf5, 0xcb, 0x0f, 0x59, 0x28, 0x0a, 0xcd, 0x85, + 0x2a, 0xb0, 0x7f, 0xd7, 0xef, 0xf6, 0xb5, 0xfb, 0x3e, 0xbe, 0xbf, 0x31, 0xfb, 0xaa, 0x61, 0x48, + 0x1f, 0x21, 0x19, 0x0e, 0xdb, 0xda, 0xed, 0xed, 0x8d, 0x79, 0xab, 0xf6, 0x4d, 0x6c, 0xde, 0xdc, + 0xaa, 0xb8, 0xa7, 0xb5, 0xbb, 0x52, 0x06, 0x9d, 0x40, 0x45, 0x60, 0xfa, 0x1a, 0xbe, 0x52, 0x7b, + 0xad, 0x77, 0xd2, 0x16, 0x3a, 0x82, 0x03, 0x81, 0xd0, 0xd5, 0xb7, 0x5a, 0x57, 0x95, 0xb2, 0x81, + 0xbe, 0x63, 0xf6, 0xda, 0x58, 0xbb, 0xbe, 0x56, 0x75, 0xf5, 0x2a, 0x26, 0xb6, 0x83, 0x57, 0x70, + 0xa2, 0xd5, 0x6e, 0xab, 0x03, 0x73, 0xc5, 0xec, 0xa0, 0xcf, 0xe1, 0x93, 0x54, 0x48, 0xf0, 0x7a, + 0xed, 0xce, 0xc4, 0x86, 0xda, 0xd6, 0xfa, 0x57, 0xb8, 0xa7, 0xbe, 0x55, 0x7b, 0x52, 0x0e, 0x7d, + 0x01, 0x4a, 0xda, 0xc0, 0xb8, 0x6b, 0xb7, 0x55, 0xc3, 0x48, 0xeb, 0x76, 0xd1, 0x19, 0xbc, 0x5e, + 0xcb, 0xe0, 0x56, 0x33, 0xd5, 0xd8, 0x55, 0xca, 0xa3, 0x1a, 0x9c, 0xae, 0x67, 0xc2, 0x15, 0x91, + 0x9f, 0x54, 0x40, 0xa7, 0x20, 0x73, 0x85, 0xe8, 0x1c, 0xe7, 0x0b, 0xe8, 0x10, 0xa4, 0xa8, 0x72, + 0xb8, 0xab, 0xbe, 0xc3, 0x9d, 0x96, 0xd1, 0x91, 0x8a, 0xe8, 0x35, 0x9c, 0xf4, 0x55, 0x23, 0xb0, + 0xdb, 0x20, 0x4b, 0x6b, 0xc5, 0x6a, 0xf5, 0xdb, 0x1d, 0x4d, 0x97, 0xca, 0xe7, 0x7f, 0x6f, 0x43, + 0xe1, 0x9e, 0x77, 0x5c, 0xd7, 0x66, 0xe8, 0x27, 0x28, 0x5f, 0x11, 0x6a, 0xff, 0x49, 0xfa, 0x64, + 0xc1, 0xba, 0x64, 0x89, 0x0e, 0x84, 0x76, 0x0c, 0x17, 0x4b, 0xf5, 0x38, 0x99, 0x9c, 0x5d, 0xb2, + 0xbc, 0x22, 0xfe, 0x90, 0xda, 0x1e, 0x73, 0x29, 0xfa, 0x01, 0x0a, 0x61, 0x6c, 0x10, 0x57, 0x11, + 0x45, 0x3d, 0x77, 0x68, 0x31, 0x97, 0xbe, 0x18, 0xf9, 0x33, 0xe4, 0x83, 0xf7, 0x05, 0x6b, 0x05, + 0x89, 0x03, 0x49, 0x58, 0x3b, 0xd5, 0x93, 0x0d, 0x3c, 0xfa, 0x90, 0x3a, 0x80, 0xa2, 0x2d, 0x22, + 0xae, 0x1c, 0xd1, 0x46, 0xc0, 0xab, 0x55, 0xf1, 0xf3, 0x5a, 0x5b, 0x3e, 0x3d, 0x28, 0x0a, 0x93, + 0x1f, 0xbd, 0x11, 0xa4, 0x9b, 0xfb, 0xa6, 0xfa, 0xf1, 0x4b, 0xf4, 0xca, 0x4d, 0x18, 0xf1, 0x29, + 0xb7, 0xcd, 0x8d, 0x91, 0x72, 0xfb, 0xb7, 0xcd, 0xa0, 0x43, 0x39, 0x35, 0x47, 0xd0, 0xd9, 0x0b, + 0x73, 0x22, 0xc9, 0xaf, 0xf6, 0xb2, 0x20, 0xf2, 0xfc, 0x15, 0x76, 0xa3, 0x2f, 0x15, 0xbd, 0x12, + 0xc4, 0xe9, 0xa9, 0x92, 0xaa, 0xd8, 0xda, 0x87, 0x7d, 0xf9, 0xed, 0xef, 0xcd, 0xb1, 0xcd, 0x9e, + 0x66, 0x0f, 0x8d, 0xa1, 0x3b, 0x6d, 0x4e, 0x82, 0x41, 0xec, 0xd8, 0xce, 0xd8, 0x21, 0x6c, 0xee, + 0xd2, 0xe7, 0xe6, 0xc4, 0x19, 0x35, 0xf9, 0x00, 0x6a, 0x26, 0x16, 0x0f, 0x39, 0xfe, 0x7f, 0xca, + 0xc5, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf1, 0x3f, 0xcd, 0xa5, 0xf0, 0x08, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/walletrpc/walletkit.proto b/lnrpc/walletrpc/walletkit.proto index 267af2fdaf..96f2ce0678 100644 --- a/lnrpc/walletrpc/walletkit.proto +++ b/lnrpc/walletrpc/walletkit.proto @@ -164,6 +164,12 @@ enum WitnessType { script that pays to a key solely under our control. */ NESTED_WITNESS_KEY_HASH = 12; + + /* + A witness type that allows us to spend our anchor on the commitment + transaction. + */ + COMMITMENT_ANCHOR = 13; } message PendingSweep { diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 1cc5282daf..edfeb35cc1 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -390,6 +390,8 @@ func (w *WalletKit) PendingSweeps(ctx context.Context, witnessType = WitnessType_WITNESS_KEY_HASH case input.NestedWitnessKeyHash: witnessType = WitnessType_NESTED_WITNESS_KEY_HASH + case input.CommitmentAnchor: + witnessType = WitnessType_COMMITMENT_ANCHOR default: log.Warnf("Unhandled witness type %v for input %v", pendingInput.WitnessType, pendingInput.OutPoint) From 3b517390d8db4ce4dd0f989b1b300bdf4e9f27a1 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 11 Mar 2020 08:52:20 +0100 Subject: [PATCH 227/562] cnct+sweeper: give contract court access to relay fee Relay fee is needed later to sweep anchors at the minimum fee rate. --- contractcourt/commit_sweep_resolver_test.go | 5 +++++ contractcourt/interfaces.go | 5 +++++ sweep/sweeper.go | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/contractcourt/commit_sweep_resolver_test.go b/contractcourt/commit_sweep_resolver_test.go index c142167e17..e5c7df0506 100644 --- a/contractcourt/commit_sweep_resolver_test.go +++ b/contractcourt/commit_sweep_resolver_test.go @@ -10,6 +10,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/sweep" ) @@ -120,6 +121,10 @@ func (s *mockSweeper) CreateSweepTx(inputs []input.Input, feePref sweep.FeePrefe return nil, nil } +func (s *mockSweeper) RelayFeePerKW() chainfee.SatPerKWeight { + return 253 +} + var _ UtxoSweeper = &mockSweeper{} // TestCommitSweepResolverNoDelay tests resolution of a direct commitment output diff --git a/contractcourt/interfaces.go b/contractcourt/interfaces.go index 18dfbc0e86..5497dad8bc 100644 --- a/contractcourt/interfaces.go +++ b/contractcourt/interfaces.go @@ -9,6 +9,7 @@ import ( "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/sweep" ) @@ -51,4 +52,8 @@ type UtxoSweeper interface { // estimate before generating the required witnesses. CreateSweepTx(inputs []input.Input, feePref sweep.FeePreference, currentBlockHeight uint32) (*wire.MsgTx, error) + + // RelayFeePerKW returns the minimum fee rate required for transactions + // to be relayed. + RelayFeePerKW() chainfee.SatPerKWeight } diff --git a/sweep/sweeper.go b/sweep/sweeper.go index f176f703ba..3b9acebe3c 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -384,6 +384,12 @@ func (s *UtxoSweeper) Start() error { return nil } +// RelayFeePerKW returns the minimum fee rate required for transactions to be +// relayed. +func (s *UtxoSweeper) RelayFeePerKW() chainfee.SatPerKWeight { + return s.relayFeeRate +} + // Stop stops sweeper from listening to block epochs and constructing sweep // txes. func (s *UtxoSweeper) Stop() error { From e8e99c65339074f3b311e32e6a2d39cd613dc469 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 12 Mar 2020 17:34:55 +0100 Subject: [PATCH 228/562] cnct: simplify channel arbitrator state logging --- contractcourt/channel_arbitrator.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 6b517daf42..313e8a533f 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -850,28 +850,24 @@ func (c *ChannelArbitrator) stateStep( // We are waiting for a commitment to be confirmed, so any // other trigger will be ignored. case chainTrigger, userTrigger: - log.Infof("ChannelArbitrator(%v): noop trigger %v", - c.cfg.ChanPoint, trigger) nextState = StateCommitmentBroadcasted // If this state advance was triggered by any of the // commitments being confirmed, then we'll jump to the state // where the contract has been closed. case localCloseTrigger, remoteCloseTrigger: - log.Infof("ChannelArbitrator(%v): trigger %v, "+ - " going to StateContractClosed", - c.cfg.ChanPoint, trigger) nextState = StateContractClosed // If a coop close or breach was confirmed, jump straight to // the fully resolved state. case coopCloseTrigger, breachCloseTrigger: - log.Infof("ChannelArbitrator(%v): trigger %v, "+ - " going to StateFullyResolved", - c.cfg.ChanPoint, trigger) nextState = StateFullyResolved } + log.Infof("ChannelArbitrator(%v): trigger %v moving from "+ + "state %v to %v", c.cfg.ChanPoint, trigger, c.state, + nextState) + // If we're in this state, then the contract has been fully closed to // outside sub-systems, so we'll process the prior set of on-chain // contract actions and launch a set of resolvers. From df44d1993614c7373fc13602998d42599e019f23 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 17 Mar 2020 16:23:01 -0700 Subject: [PATCH 229/562] discovery/multi: move SignAnnouncement to netann --- discovery/gossiper.go | 5 ++++- discovery/gossiper_test.go | 13 +++++++------ discovery/utils.go | 31 ------------------------------- netann/sign.go | 36 ++++++++++++++++++++++++++++++++++++ server.go | 4 ++-- 5 files changed, 49 insertions(+), 40 deletions(-) create mode 100644 netann/sign.go diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 8c9ed6e599..5ee79852fb 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/multimutex" + "github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/ticker" @@ -2469,7 +2470,9 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo, // With the update applied, we'll generate a new signature over a // digest of the channel announcement itself. - sig, err := SignAnnouncement(d.cfg.AnnSigner, d.selfKey, chanUpdate) + sig, err := netann.SignAnnouncement( + d.cfg.AnnSigner, d.selfKey, chanUpdate, + ) if err != nil { return nil, nil, err } diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index 4252397c15..f927a9609c 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -26,6 +26,7 @@ import ( "github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/ticker" @@ -550,7 +551,7 @@ func createNodeAnnouncement(priv *btcec.PrivateKey, } signer := mockSigner{priv} - sig, err := SignAnnouncement(&signer, priv.PubKey(), a) + sig, err := netann.SignAnnouncement(&signer, priv.PubKey(), a) if err != nil { return nil, err } @@ -602,7 +603,7 @@ func createUpdateAnnouncement(blockHeight uint32, func signUpdate(nodeKey *btcec.PrivateKey, a *lnwire.ChannelUpdate) error { pub := nodeKey.PubKey() signer := mockSigner{nodeKey} - sig, err := SignAnnouncement(&signer, pub, a) + sig, err := netann.SignAnnouncement(&signer, pub, a) if err != nil { return err } @@ -644,7 +645,7 @@ func createRemoteChannelAnnouncement(blockHeight uint32, pub := nodeKeyPriv1.PubKey() signer := mockSigner{nodeKeyPriv1} - sig, err := SignAnnouncement(&signer, pub, a) + sig, err := netann.SignAnnouncement(&signer, pub, a) if err != nil { return nil, err } @@ -655,7 +656,7 @@ func createRemoteChannelAnnouncement(blockHeight uint32, pub = nodeKeyPriv2.PubKey() signer = mockSigner{nodeKeyPriv2} - sig, err = SignAnnouncement(&signer, pub, a) + sig, err = netann.SignAnnouncement(&signer, pub, a) if err != nil { return nil, err } @@ -666,7 +667,7 @@ func createRemoteChannelAnnouncement(blockHeight uint32, pub = bitcoinKeyPriv1.PubKey() signer = mockSigner{bitcoinKeyPriv1} - sig, err = SignAnnouncement(&signer, pub, a) + sig, err = netann.SignAnnouncement(&signer, pub, a) if err != nil { return nil, err } @@ -677,7 +678,7 @@ func createRemoteChannelAnnouncement(blockHeight uint32, pub = bitcoinKeyPriv2.PubKey() signer = mockSigner{bitcoinKeyPriv2} - sig, err = SignAnnouncement(&signer, pub, a) + sig, err = netann.SignAnnouncement(&signer, pub, a) if err != nil { return nil, err } diff --git a/discovery/utils.go b/discovery/utils.go index ce211493e1..04793a6069 100644 --- a/discovery/utils.go +++ b/discovery/utils.go @@ -1,10 +1,7 @@ package discovery import ( - "github.com/btcsuite/btcd/btcec" - "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" ) @@ -109,34 +106,6 @@ func CreateChanAnnouncement(chanProof *channeldb.ChannelAuthProof, return chanAnn, edge1Ann, edge2Ann, nil } -// SignAnnouncement is a helper function which is used to sign any outgoing -// channel node node announcement messages. -func SignAnnouncement(signer lnwallet.MessageSigner, pubKey *btcec.PublicKey, - msg lnwire.Message) (*btcec.Signature, error) { - - var ( - data []byte - err error - ) - - switch m := msg.(type) { - case *lnwire.ChannelAnnouncement: - data, err = m.DataToSign() - case *lnwire.ChannelUpdate: - data, err = m.DataToSign() - case *lnwire.NodeAnnouncement: - data, err = m.DataToSign() - default: - return nil, errors.New("can't sign message " + - "of this format") - } - if err != nil { - return nil, errors.Errorf("unable to get data to sign: %v", err) - } - - return signer.SignMessage(pubKey, data) -} - // remotePubFromChanInfo returns the public key of the remote peer given a // ChannelEdgeInfo that describe a channel we have with them. func remotePubFromChanInfo(chanInfo *channeldb.ChannelEdgeInfo, diff --git a/netann/sign.go b/netann/sign.go new file mode 100644 index 0000000000..5a66962013 --- /dev/null +++ b/netann/sign.go @@ -0,0 +1,36 @@ +package netann + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/lnwire" +) + +// SignAnnouncement signs any type of gossip message that is announced on the +// network. +func SignAnnouncement(signer lnwallet.MessageSigner, pubKey *btcec.PublicKey, + msg lnwire.Message) (*btcec.Signature, error) { + + var ( + data []byte + err error + ) + + switch m := msg.(type) { + case *lnwire.ChannelAnnouncement: + data, err = m.DataToSign() + case *lnwire.ChannelUpdate: + data, err = m.DataToSign() + case *lnwire.NodeAnnouncement: + data, err = m.DataToSign() + default: + return nil, fmt.Errorf("can't sign %T message", m) + } + if err != nil { + return nil, fmt.Errorf("unable to get data to sign: %v", err) + } + + return signer.SignMessage(pubKey, data) +} diff --git a/server.go b/server.go index 98f446d7b3..32caa33e80 100644 --- a/server.go +++ b/server.go @@ -651,7 +651,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, // With the announcement generated, we'll sign it to properly // authenticate the message on the network. - authSig, err := discovery.SignAnnouncement( + authSig, err := netann.SignAnnouncement( s.nodeSigner, s.identityPriv.PubKey(), nodeAnn, ) if err != nil { @@ -2068,7 +2068,7 @@ func (s *server) genNodeAnnouncement(refresh bool, // Now that the announcement is fully updated, we'll generate a new // signature over the announcement to ensure nodes on the network // accepted the new authenticated announcement. - sig, err := discovery.SignAnnouncement( + sig, err := netann.SignAnnouncement( s.nodeSigner, s.identityPriv.PubKey(), s.currentNodeAnn, ) if err != nil { From 9d92cfd2b446c0d3ec42cfcaba793a86a7cf4e27 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 17 Mar 2020 16:23:19 -0700 Subject: [PATCH 230/562] netann/channel_update: use generic SignAnnouncement --- netann/channel_update.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/netann/channel_update.go b/netann/channel_update.go index c405a0c6a3..b3c53136ac 100644 --- a/netann/channel_update.go +++ b/netann/channel_update.go @@ -55,13 +55,8 @@ func SignChannelUpdate(signer lnwallet.MessageSigner, pubKey *btcec.PublicKey, } update.Timestamp = newTimestamp - chanUpdateMsg, err := update.DataToSign() - if err != nil { - return err - } - // Create the DER-encoded ECDSA signature over the message digest. - sig, err := signer.SignMessage(pubKey, chanUpdateMsg) + sig, err := SignAnnouncement(signer, pubKey, update) if err != nil { return err } From d82aacbdc57ecf19fb57154e92d65d5ac765d243 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 17 Mar 2020 16:23:37 -0700 Subject: [PATCH 231/562] discovery/utils: use netann.ChannelUpdateFromEdge --- discovery/utils.go | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/discovery/utils.go b/discovery/utils.go index 04793a6069..9114e5a3ed 100644 --- a/discovery/utils.go +++ b/discovery/utils.go @@ -3,6 +3,7 @@ package discovery import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/netann" ) // CreateChanAnnouncement is a helper function which creates all channel @@ -65,39 +66,13 @@ func CreateChanAnnouncement(chanProof *channeldb.ChannelAuthProof, // nil. var edge1Ann, edge2Ann *lnwire.ChannelUpdate if e1 != nil { - edge1Ann = &lnwire.ChannelUpdate{ - ChainHash: chanInfo.ChainHash, - ShortChannelID: chanID, - Timestamp: uint32(e1.LastUpdate.Unix()), - MessageFlags: e1.MessageFlags, - ChannelFlags: e1.ChannelFlags, - TimeLockDelta: e1.TimeLockDelta, - HtlcMinimumMsat: e1.MinHTLC, - HtlcMaximumMsat: e1.MaxHTLC, - BaseFee: uint32(e1.FeeBaseMSat), - FeeRate: uint32(e1.FeeProportionalMillionths), - ExtraOpaqueData: e1.ExtraOpaqueData, - } - edge1Ann.Signature, err = lnwire.NewSigFromRawSignature(e1.SigBytes) + edge1Ann, err = netann.ChannelUpdateFromEdge(chanInfo, e1) if err != nil { return nil, nil, nil, err } } if e2 != nil { - edge2Ann = &lnwire.ChannelUpdate{ - ChainHash: chanInfo.ChainHash, - ShortChannelID: chanID, - Timestamp: uint32(e2.LastUpdate.Unix()), - MessageFlags: e2.MessageFlags, - ChannelFlags: e2.ChannelFlags, - TimeLockDelta: e2.TimeLockDelta, - HtlcMinimumMsat: e2.MinHTLC, - HtlcMaximumMsat: e2.MaxHTLC, - BaseFee: uint32(e2.FeeBaseMSat), - FeeRate: uint32(e2.FeeProportionalMillionths), - ExtraOpaqueData: e2.ExtraOpaqueData, - } - edge2Ann.Signature, err = lnwire.NewSigFromRawSignature(e2.SigBytes) + edge2Ann, err = netann.ChannelUpdateFromEdge(chanInfo, e2) if err != nil { return nil, nil, nil, err } From 6a813e3433d05cb08d2eec7df73ced67a1e0443f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 17 Mar 2020 16:23:54 -0700 Subject: [PATCH 232/562] discovery/multi: move CreateChanAnnouncement to netann --- discovery/chan_series.go | 5 ++- discovery/gossiper.go | 6 +-- discovery/utils.go | 76 ------------------------------- netann/channel_announcement.go | 81 ++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 81 deletions(-) create mode 100644 netann/channel_announcement.go diff --git a/discovery/chan_series.go b/discovery/chan_series.go index ddea51041f..7ed101b3f5 100644 --- a/discovery/chan_series.go +++ b/discovery/chan_series.go @@ -6,6 +6,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/routing/route" ) @@ -119,7 +120,7 @@ func (c *ChanSeries) UpdatesInHorizon(chain chainhash.Hash, continue } - chanAnn, edge1, edge2, err := CreateChanAnnouncement( + chanAnn, edge1, edge2, err := netann.CreateChanAnnouncement( channel.Info.AuthProof, channel.Info, channel.Policy1, channel.Policy2, ) @@ -258,7 +259,7 @@ func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash, continue } - chanAnn, edge1, edge2, err := CreateChanAnnouncement( + chanAnn, edge1, edge2, err := netann.CreateChanAnnouncement( channel.Info.AuthProof, channel.Info, channel.Policy1, channel.Policy2, ) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 5ee79852fb..742c260d19 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -1401,7 +1401,7 @@ func (d *AuthenticatedGossiper) processRejectedEdge( // We'll then create then validate the new fully assembled // announcement. - chanAnn, e1Ann, e2Ann, err := CreateChanAnnouncement( + chanAnn, e1Ann, e2Ann, err := netann.CreateChanAnnouncement( proof, chanInfo, e1, e2, ) if err != nil { @@ -2158,7 +2158,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement( msg.ChannelID, peerID) - chanAnn, _, _, err := CreateChanAnnouncement( + chanAnn, _, _, err := netann.CreateChanAnnouncement( chanInfo.AuthProof, chanInfo, e1, e2, ) @@ -2241,7 +2241,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement( dbProof.BitcoinSig1Bytes = oppositeProof.BitcoinSignature.ToSignatureBytes() dbProof.BitcoinSig2Bytes = msg.BitcoinSignature.ToSignatureBytes() } - chanAnn, e1Ann, e2Ann, err := CreateChanAnnouncement( + chanAnn, e1Ann, e2Ann, err := netann.CreateChanAnnouncement( &dbProof, chanInfo, e1, e2, ) if err != nil { diff --git a/discovery/utils.go b/discovery/utils.go index 9114e5a3ed..6a5e2dee94 100644 --- a/discovery/utils.go +++ b/discovery/utils.go @@ -3,84 +3,8 @@ package discovery import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/netann" ) -// CreateChanAnnouncement is a helper function which creates all channel -// announcements given the necessary channel related database items. This -// function is used to transform out database structs into the corresponding wire -// structs for announcing new channels to other peers, or simply syncing up a -// peer's initial routing table upon connect. -func CreateChanAnnouncement(chanProof *channeldb.ChannelAuthProof, - chanInfo *channeldb.ChannelEdgeInfo, - e1, e2 *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, - *lnwire.ChannelUpdate, *lnwire.ChannelUpdate, error) { - - // First, using the parameters of the channel, along with the channel - // authentication chanProof, we'll create re-create the original - // authenticated channel announcement. - chanID := lnwire.NewShortChanIDFromInt(chanInfo.ChannelID) - chanAnn := &lnwire.ChannelAnnouncement{ - ShortChannelID: chanID, - NodeID1: chanInfo.NodeKey1Bytes, - NodeID2: chanInfo.NodeKey2Bytes, - ChainHash: chanInfo.ChainHash, - BitcoinKey1: chanInfo.BitcoinKey1Bytes, - BitcoinKey2: chanInfo.BitcoinKey2Bytes, - Features: lnwire.NewRawFeatureVector(), - ExtraOpaqueData: chanInfo.ExtraOpaqueData, - } - - var err error - chanAnn.BitcoinSig1, err = lnwire.NewSigFromRawSignature( - chanProof.BitcoinSig1Bytes, - ) - if err != nil { - return nil, nil, nil, err - } - chanAnn.BitcoinSig2, err = lnwire.NewSigFromRawSignature( - chanProof.BitcoinSig2Bytes, - ) - if err != nil { - return nil, nil, nil, err - } - chanAnn.NodeSig1, err = lnwire.NewSigFromRawSignature( - chanProof.NodeSig1Bytes, - ) - if err != nil { - return nil, nil, nil, err - } - chanAnn.NodeSig2, err = lnwire.NewSigFromRawSignature( - chanProof.NodeSig2Bytes, - ) - if err != nil { - return nil, nil, nil, err - } - - // We'll unconditionally queue the channel's existence chanProof as it - // will need to be processed before either of the channel update - // networkMsgs. - - // Since it's up to a node's policy as to whether they advertise the - // edge in a direction, we don't create an advertisement if the edge is - // nil. - var edge1Ann, edge2Ann *lnwire.ChannelUpdate - if e1 != nil { - edge1Ann, err = netann.ChannelUpdateFromEdge(chanInfo, e1) - if err != nil { - return nil, nil, nil, err - } - } - if e2 != nil { - edge2Ann, err = netann.ChannelUpdateFromEdge(chanInfo, e2) - if err != nil { - return nil, nil, nil, err - } - } - - return chanAnn, edge1Ann, edge2Ann, nil -} - // remotePubFromChanInfo returns the public key of the remote peer given a // ChannelEdgeInfo that describe a channel we have with them. func remotePubFromChanInfo(chanInfo *channeldb.ChannelEdgeInfo, diff --git a/netann/channel_announcement.go b/netann/channel_announcement.go new file mode 100644 index 0000000000..99f909e260 --- /dev/null +++ b/netann/channel_announcement.go @@ -0,0 +1,81 @@ +package netann + +import ( + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lnwire" +) + +// CreateChanAnnouncement is a helper function which creates all channel +// announcements given the necessary channel related database items. This +// function is used to transform out database structs into the corresponding wire +// structs for announcing new channels to other peers, or simply syncing up a +// peer's initial routing table upon connect. +func CreateChanAnnouncement(chanProof *channeldb.ChannelAuthProof, + chanInfo *channeldb.ChannelEdgeInfo, + e1, e2 *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, + *lnwire.ChannelUpdate, *lnwire.ChannelUpdate, error) { + + // First, using the parameters of the channel, along with the channel + // authentication chanProof, we'll create re-create the original + // authenticated channel announcement. + chanID := lnwire.NewShortChanIDFromInt(chanInfo.ChannelID) + chanAnn := &lnwire.ChannelAnnouncement{ + ShortChannelID: chanID, + NodeID1: chanInfo.NodeKey1Bytes, + NodeID2: chanInfo.NodeKey2Bytes, + ChainHash: chanInfo.ChainHash, + BitcoinKey1: chanInfo.BitcoinKey1Bytes, + BitcoinKey2: chanInfo.BitcoinKey2Bytes, + Features: lnwire.NewRawFeatureVector(), + ExtraOpaqueData: chanInfo.ExtraOpaqueData, + } + + var err error + chanAnn.BitcoinSig1, err = lnwire.NewSigFromRawSignature( + chanProof.BitcoinSig1Bytes, + ) + if err != nil { + return nil, nil, nil, err + } + chanAnn.BitcoinSig2, err = lnwire.NewSigFromRawSignature( + chanProof.BitcoinSig2Bytes, + ) + if err != nil { + return nil, nil, nil, err + } + chanAnn.NodeSig1, err = lnwire.NewSigFromRawSignature( + chanProof.NodeSig1Bytes, + ) + if err != nil { + return nil, nil, nil, err + } + chanAnn.NodeSig2, err = lnwire.NewSigFromRawSignature( + chanProof.NodeSig2Bytes, + ) + if err != nil { + return nil, nil, nil, err + } + + // We'll unconditionally queue the channel's existence chanProof as it + // will need to be processed before either of the channel update + // networkMsgs. + + // Since it's up to a node's policy as to whether they advertise the + // edge in a direction, we don't create an advertisement if the edge is + // nil. + var edge1Ann, edge2Ann *lnwire.ChannelUpdate + if e1 != nil { + edge1Ann, err = ChannelUpdateFromEdge(chanInfo, e1) + if err != nil { + return nil, nil, nil, err + } + } + if e2 != nil { + edge2Ann, err = ChannelUpdateFromEdge(chanInfo, e2) + if err != nil { + return nil, nil, nil, err + } + } + + return chanAnn, edge1Ann, edge2Ann, nil +} From 7b0d564692925bf2970257cfc489ee9d10236fa3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 17 Mar 2020 16:24:10 -0700 Subject: [PATCH 233/562] discovery: move remotePubFromChanInfo to gossiper, remove utils --- discovery/gossiper.go | 16 ++++++++++++++++ discovery/utils.go | 22 ---------------------- 2 files changed, 16 insertions(+), 22 deletions(-) delete mode 100644 discovery/utils.go diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 742c260d19..338558e755 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -1365,6 +1365,22 @@ func (d *AuthenticatedGossiper) processChanPolicyUpdate( return chanUpdates, nil } +// remotePubFromChanInfo returns the public key of the remote peer given a +// ChannelEdgeInfo that describe a channel we have with them. +func remotePubFromChanInfo(chanInfo *channeldb.ChannelEdgeInfo, + chanFlags lnwire.ChanUpdateChanFlags) [33]byte { + + var remotePubKey [33]byte + switch { + case chanFlags&lnwire.ChanUpdateDirection == 0: + remotePubKey = chanInfo.NodeKey2Bytes + case chanFlags&lnwire.ChanUpdateDirection == 1: + remotePubKey = chanInfo.NodeKey1Bytes + } + + return remotePubKey +} + // processRejectedEdge examines a rejected edge to see if we can extract any // new announcements from it. An edge will get rejected if we already added // the same edge without AuthProof to the graph. If the received announcement diff --git a/discovery/utils.go b/discovery/utils.go deleted file mode 100644 index 6a5e2dee94..0000000000 --- a/discovery/utils.go +++ /dev/null @@ -1,22 +0,0 @@ -package discovery - -import ( - "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/lnwire" -) - -// remotePubFromChanInfo returns the public key of the remote peer given a -// ChannelEdgeInfo that describe a channel we have with them. -func remotePubFromChanInfo(chanInfo *channeldb.ChannelEdgeInfo, - chanFlags lnwire.ChanUpdateChanFlags) [33]byte { - - var remotePubKey [33]byte - switch { - case chanFlags&lnwire.ChanUpdateDirection == 0: - remotePubKey = chanInfo.NodeKey2Bytes - case chanFlags&lnwire.ChanUpdateDirection == 1: - remotePubKey = chanInfo.NodeKey1Bytes - } - - return remotePubKey -} From 089ac647d84e0cd7501dbbd0f83557cd15f59922 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 17 Mar 2020 16:24:25 -0700 Subject: [PATCH 234/562] discovery/chan_series: use netann.ChannelUpdateFromEdge helper --- discovery/chan_series.go | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/discovery/chan_series.go b/discovery/chan_series.go index 7ed101b3f5..ffb59b4ef5 100644 --- a/discovery/chan_series.go +++ b/discovery/chan_series.go @@ -324,20 +324,7 @@ func (c *ChanSeries) FetchChanUpdates(chain chainhash.Hash, chanUpdates := make([]*lnwire.ChannelUpdate, 0, 2) if e1 != nil { - chanUpdate := &lnwire.ChannelUpdate{ - ChainHash: chanInfo.ChainHash, - ShortChannelID: shortChanID, - Timestamp: uint32(e1.LastUpdate.Unix()), - MessageFlags: e1.MessageFlags, - ChannelFlags: e1.ChannelFlags, - TimeLockDelta: e1.TimeLockDelta, - HtlcMinimumMsat: e1.MinHTLC, - HtlcMaximumMsat: e1.MaxHTLC, - BaseFee: uint32(e1.FeeBaseMSat), - FeeRate: uint32(e1.FeeProportionalMillionths), - ExtraOpaqueData: e1.ExtraOpaqueData, - } - chanUpdate.Signature, err = lnwire.NewSigFromRawSignature(e1.SigBytes) + chanUpdate, err := netann.ChannelUpdateFromEdge(chanInfo, e1) if err != nil { return nil, err } @@ -345,20 +332,7 @@ func (c *ChanSeries) FetchChanUpdates(chain chainhash.Hash, chanUpdates = append(chanUpdates, chanUpdate) } if e2 != nil { - chanUpdate := &lnwire.ChannelUpdate{ - ChainHash: chanInfo.ChainHash, - ShortChannelID: shortChanID, - Timestamp: uint32(e2.LastUpdate.Unix()), - MessageFlags: e2.MessageFlags, - ChannelFlags: e2.ChannelFlags, - TimeLockDelta: e2.TimeLockDelta, - HtlcMinimumMsat: e2.MinHTLC, - HtlcMaximumMsat: e2.MaxHTLC, - BaseFee: uint32(e2.FeeBaseMSat), - FeeRate: uint32(e2.FeeProportionalMillionths), - ExtraOpaqueData: e2.ExtraOpaqueData, - } - chanUpdate.Signature, err = lnwire.NewSigFromRawSignature(e2.SigBytes) + chanUpdate, err := netann.ChannelUpdateFromEdge(chanInfo, e2) if err != nil { return nil, err } From f6c194c3cdebe4e1d9a5169f0d80cb08ccdf89ec Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 17 Mar 2020 16:25:02 -0700 Subject: [PATCH 235/562] netann/node_announcement: consolidate signing logic --- lnwire/node_announcement.go | 8 ----- netann/node_announcement.go | 60 +++++++++++++++++++++++++++++++++++++ server.go | 33 ++++++-------------- 3 files changed, 69 insertions(+), 32 deletions(-) create mode 100644 netann/node_announcement.go diff --git a/lnwire/node_announcement.go b/lnwire/node_announcement.go index 4ea64fa646..f0d897bc91 100644 --- a/lnwire/node_announcement.go +++ b/lnwire/node_announcement.go @@ -101,14 +101,6 @@ type NodeAnnouncement struct { ExtraOpaqueData []byte } -// UpdateNodeAnnAddrs is a functional option that allows updating the addresses -// of the given node announcement. -func UpdateNodeAnnAddrs(addrs []net.Addr) func(*NodeAnnouncement) { - return func(nodeAnn *NodeAnnouncement) { - nodeAnn.Addresses = addrs - } -} - // A compile time check to ensure NodeAnnouncement implements the // lnwire.Message interface. var _ Message = (*NodeAnnouncement)(nil) diff --git a/netann/node_announcement.go b/netann/node_announcement.go new file mode 100644 index 0000000000..84a261059f --- /dev/null +++ b/netann/node_announcement.go @@ -0,0 +1,60 @@ +package netann + +import ( + "net" + "time" + + "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/lnwire" +) + +// NodeAnnModifier is a closure that makes in-place modifications to an +// lnwire.NodeAnnouncement. +type NodeAnnModifier func(*lnwire.NodeAnnouncement) + +// NodeAnnSetAddrs is a functional option that allows updating the addresses of +// the given node announcement. +func NodeAnnSetAddrs(addrs []net.Addr) func(*lnwire.NodeAnnouncement) { + return func(nodeAnn *lnwire.NodeAnnouncement) { + nodeAnn.Addresses = addrs + } +} + +// NodeAnnSetTimestamp is a functional option that sets the timestamp of the +// announcement to the current time, or increments it if the timestamp is +// already in the future. +func NodeAnnSetTimestamp(nodeAnn *lnwire.NodeAnnouncement) { + newTimestamp := uint32(time.Now().Unix()) + if newTimestamp <= nodeAnn.Timestamp { + // Increment the prior value to ensure the timestamp + // monotonically increases, otherwise the announcement won't + // propagate. + newTimestamp = nodeAnn.Timestamp + 1 + } + nodeAnn.Timestamp = newTimestamp +} + +// SignNodeAnnouncement applies the given modifies to the passed +// lnwire.NodeAnnouncement, then signs the resulting announcement. The provided +// update should be the most recent, valid update, otherwise the timestamp may +// not monotonically increase from the prior. +func SignNodeAnnouncement(signer lnwallet.MessageSigner, + pubKey *btcec.PublicKey, nodeAnn *lnwire.NodeAnnouncement, + mods ...NodeAnnModifier) error { + + // Apply the requested changes to the node announcement. + for _, modifier := range mods { + modifier(nodeAnn) + } + + // Create the DER-encoded ECDSA signature over the message digest. + sig, err := SignAnnouncement(signer, pubKey, nodeAnn) + if err != nil { + return err + } + + // Parse the DER-encoded signature into a fixed-size 64-byte array. + nodeAnn.Signature, err = lnwire.NewSigFromSignature(sig) + return err +} diff --git a/server.go b/server.go index 32caa33e80..db9ba4e9e2 100644 --- a/server.go +++ b/server.go @@ -1657,7 +1657,7 @@ out: // announcement with the updated addresses and broadcast // it to our peers. newNodeAnn, err := s.genNodeAnnouncement( - true, lnwire.UpdateNodeAnnAddrs(newAddrs), + true, netann.NodeAnnSetAddrs(newAddrs), ) if err != nil { srvrLog.Debugf("Unable to generate new node "+ @@ -2039,7 +2039,7 @@ func (s *server) initTorController() error { // announcement. If refresh is true, then the time stamp of the announcement // will be updated in order to ensure it propagates through the network. func (s *server) genNodeAnnouncement(refresh bool, - updates ...func(*lnwire.NodeAnnouncement)) (lnwire.NodeAnnouncement, error) { + modifiers ...netann.NodeAnnModifier) (lnwire.NodeAnnouncement, error) { s.mu.Lock() defer s.mu.Unlock() @@ -2050,34 +2050,19 @@ func (s *server) genNodeAnnouncement(refresh bool, return *s.currentNodeAnn, nil } - // Now that we know we need to update our copy, we'll apply all the - // function updates that'll mutate the current version of our node - // announcement. - for _, update := range updates { - update(s.currentNodeAnn) - } - - // We'll now update the timestamp, ensuring that with each update, the - // timestamp monotonically increases. - newStamp := uint32(time.Now().Unix()) - if newStamp <= s.currentNodeAnn.Timestamp { - newStamp = s.currentNodeAnn.Timestamp + 1 - } - s.currentNodeAnn.Timestamp = newStamp + // Always update the timestamp when refreshing to ensure the update + // propagates. + modifiers = append(modifiers, netann.NodeAnnSetTimestamp) - // Now that the announcement is fully updated, we'll generate a new - // signature over the announcement to ensure nodes on the network - // accepted the new authenticated announcement. - sig, err := netann.SignAnnouncement( + // Otherwise, we'll sign a new update after applying all of the passed + // modifiers. + err := netann.SignNodeAnnouncement( s.nodeSigner, s.identityPriv.PubKey(), s.currentNodeAnn, + modifiers..., ) if err != nil { return lnwire.NodeAnnouncement{}, err } - s.currentNodeAnn.Signature, err = lnwire.NewSigFromSignature(sig) - if err != nil { - return lnwire.NodeAnnouncement{}, err - } return *s.currentNodeAnn, nil } From 5147a6d63d4c55a8b70584d4e7f0c222fdaa1cb5 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 17 Mar 2020 16:25:22 -0700 Subject: [PATCH 236/562] netann/channel_update: set timestamp via modifier --- netann/chan_status_manager.go | 2 +- netann/channel_update.go | 30 +++++++++++++++++------------- netann/channel_update_test.go | 4 +++- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/netann/chan_status_manager.go b/netann/chan_status_manager.go index 146fef47fc..51797c87b3 100644 --- a/netann/chan_status_manager.go +++ b/netann/chan_status_manager.go @@ -527,7 +527,7 @@ func (m *ChanStatusManager) signAndSendNextUpdate(outpoint wire.OutPoint, err = SignChannelUpdate( m.cfg.MessageSigner, m.cfg.OurPubKey, chanUpdate, - ChannelUpdateSetDisable(disabled), + ChanUpdSetDisable(disabled), ChanUpdSetTimestamp, ) if err != nil { return err diff --git a/netann/channel_update.go b/netann/channel_update.go index b3c53136ac..a40abc2519 100644 --- a/netann/channel_update.go +++ b/netann/channel_update.go @@ -15,9 +15,9 @@ import ( // lnwire.ChannelUpdate. type ChannelUpdateModifier func(*lnwire.ChannelUpdate) -// ChannelUpdateSetDisable sets the disabled channel flag if disabled is true, -// and clears the bit otherwise. -func ChannelUpdateSetDisable(disabled bool) ChannelUpdateModifier { +// ChanUpdSetDisable is a functional option that sets the disabled channel flag +// if disabled is true, and clears the bit otherwise. +func ChanUpdSetDisable(disabled bool) ChannelUpdateModifier { return func(update *lnwire.ChannelUpdate) { if disabled { // Set the bit responsible for marking a channel as @@ -31,6 +31,20 @@ func ChannelUpdateSetDisable(disabled bool) ChannelUpdateModifier { } } +// ChanUpdSetTimestamp is a functional option that sets the timestamp of the +// update to the current time, or increments it if the timestamp is already in +// the future. +func ChanUpdSetTimestamp(update *lnwire.ChannelUpdate) { + newTimestamp := uint32(time.Now().Unix()) + if newTimestamp <= update.Timestamp { + // Increment the prior value to ensure the timestamp + // monotonically increases, otherwise the update won't + // propagate. + newTimestamp = update.Timestamp + 1 + } + update.Timestamp = newTimestamp +} + // SignChannelUpdate applies the given modifiers to the passed // lnwire.ChannelUpdate, then signs the resulting update. The provided update // should be the most recent, valid update, otherwise the timestamp may not @@ -45,16 +59,6 @@ func SignChannelUpdate(signer lnwallet.MessageSigner, pubKey *btcec.PublicKey, modifier(update) } - // Update the message's timestamp to the current time. If the update's - // current time is already in the future, we increment the prior value - // to ensure the timestamps monotonically increase, otherwise the - // update won't propagate. - newTimestamp := uint32(time.Now().Unix()) - if newTimestamp <= update.Timestamp { - newTimestamp = update.Timestamp + 1 - } - update.Timestamp = newTimestamp - // Create the DER-encoded ECDSA signature over the message digest. sig, err := SignAnnouncement(signer, pubKey, update) if err != nil { diff --git a/netann/channel_update_test.go b/netann/channel_update_test.go index 4ed019a805..0bc48e5c7a 100644 --- a/netann/channel_update_test.go +++ b/netann/channel_update_test.go @@ -103,6 +103,7 @@ func TestUpdateDisableFlag(t *testing.T) { t.Parallel() for _, tc := range updateDisableTests { + tc := tc t.Run(tc.name, func(t *testing.T) { // Create the initial update, the only fields we are // concerned with in this test are the timestamp and the @@ -127,7 +128,8 @@ func TestUpdateDisableFlag(t *testing.T) { // disabled or enabled as prescribed in the test case. err := netann.SignChannelUpdate( tc.signer, pubKey, newUpdate, - netann.ChannelUpdateSetDisable(tc.disable), + netann.ChanUpdSetDisable(tc.disable), + netann.ChanUpdSetTimestamp, ) var fail bool From f5f0b2107b2d05bb9b3a4bc1bd46f9a61863be15 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 18 Mar 2020 08:54:28 +0100 Subject: [PATCH 237/562] docker: pin down btcd version There was a recent change merged into btcd that isn't backward compatible with older RPC clients. To make sure our docker quick start example still works, we need to pin down btcd to the version that is still compatible with lnd. --- docker/btcd/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docker/btcd/Dockerfile b/docker/btcd/Dockerfile index 6f6ec39d75..5de4a389b8 100644 --- a/docker/btcd/Dockerfile +++ b/docker/btcd/Dockerfile @@ -7,8 +7,12 @@ RUN apk add --no-cache git gcc musl-dev WORKDIR $GOPATH/src/github.com/btcsuite/btcd +# Pin down btcd to a version that we know works with lnd. +ARG BTCD_VERSION=v0.20.1-beta + # Grab and install the latest version of of btcd and all related dependencies. RUN git clone https://github.com/btcsuite/btcd.git . \ + && git checkout $BTCD_VERSION \ && GO111MODULE=on go install -v . ./cmd/... # Start a new image From d2b6472843e70c072e239dcc59b76dd902df2429 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 10 Mar 2020 14:01:39 +0100 Subject: [PATCH 238/562] cnct: pre-confirmation anchor sweep Start anchor sweep attempts immediately after the commitment transaction has been published. This makes the anchor known to the sweeper and allows the user to bump the fee on it to get their commitment transaction confirmed in case the fee committed too is insufficient for timely confirmation. --- contractcourt/chain_arbitrator.go | 27 +++++++ contractcourt/channel_arbitrator.go | 80 +++++++++++++++++++- contractcourt/channel_arbitrator_test.go | 94 +++++++++++++++++++++++- lntest/itest/lnd_test.go | 35 ++++++--- 4 files changed, 221 insertions(+), 15 deletions(-) diff --git a/contractcourt/chain_arbitrator.go b/contractcourt/chain_arbitrator.go index 4d97b10ba3..a9dde5421e 100644 --- a/contractcourt/chain_arbitrator.go +++ b/contractcourt/chain_arbitrator.go @@ -231,6 +231,33 @@ type arbChannel struct { c *ChainArbitrator } +// NewAnchorResolutions returns the anchor resolutions for currently valid +// commitment transactions. +// +// NOTE: Part of the ArbChannel interface. +func (a *arbChannel) NewAnchorResolutions() ([]*lnwallet.AnchorResolution, + error) { + + // Get a fresh copy of the database state to base the anchor resolutions + // on. Unfortunately the channel instance that we have here isn't the + // same instance that is used by the link. + chanPoint := a.channel.FundingOutpoint + + channel, err := a.c.chanSource.FetchChannel(chanPoint) + if err != nil { + return nil, err + } + + chanMachine, err := lnwallet.NewLightningChannel( + a.c.cfg.Signer, channel, nil, + ) + if err != nil { + return nil, err + } + + return chanMachine.NewAnchorResolutions() +} + // ForceCloseChan should force close the contract that this attendant is // watching over. We'll use this when we decide that we need to go to chain. It // should in addition tell the switch to remove the corresponding link, such diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 313e8a533f..f0cc1f31d9 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -13,9 +13,11 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/sweep" ) var ( @@ -74,6 +76,10 @@ type ArbChannel interface { // returned summary contains all items needed to eventually resolve all // outputs on chain. ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error) + + // NewAnchorResolutions returns the anchor resolutions for currently + // valid commitment transactions. + NewAnchorResolutions() ([]*lnwallet.AnchorResolution, error) } // ChannelArbitratorConfig contains all the functionality that the @@ -847,9 +853,31 @@ func (c *ChannelArbitrator) stateStep( // to be confirmed. case StateCommitmentBroadcasted: switch trigger { - // We are waiting for a commitment to be confirmed, so any - // other trigger will be ignored. + + // We are waiting for a commitment to be confirmed. case chainTrigger, userTrigger: + // The commitment transaction has been broadcast, but it + // doesn't necessarily need to be the commitment + // transaction version that is going to be confirmed. To + // be sure that any of those versions can be anchored + // down, we now submit all anchor resolutions to the + // sweeper. The sweeper will keep trying to sweep all of + // them. + // + // Note that the sweeper is idempotent. If we ever + // happen to end up at this point in the code again, no + // harm is done by re-offering the anchors to the + // sweeper. + anchors, err := c.cfg.Channel.NewAnchorResolutions() + if err != nil { + return StateError, closeTx, err + } + + err = c.sweepAnchors(anchors, triggerHeight) + if err != nil { + return StateError, closeTx, err + } + nextState = StateCommitmentBroadcasted // If this state advance was triggered by any of the @@ -979,6 +1007,54 @@ func (c *ChannelArbitrator) stateStep( return nextState, closeTx, nil } +// sweepAnchors offers all given anchor resolutions to the sweeper. It requests +// sweeping at the minimum fee rate. This fee rate can be upped manually by the +// user via the BumpFee rpc. +func (c *ChannelArbitrator) sweepAnchors(anchors []*lnwallet.AnchorResolution, + heightHint uint32) error { + + // Use the chan id as the exclusive group. This prevents any of the + // anchors from being batched together. + exclusiveGroup := c.cfg.ShortChanID.ToUint64() + + // Retrieve the current minimum fee rate from the sweeper. + minFeeRate := c.cfg.Sweeper.RelayFeePerKW() + + for _, anchor := range anchors { + log.Debugf("ChannelArbitrator(%v): pre-confirmation sweep of "+ + "anchor of tx %v", c.cfg.ChanPoint, anchor.CommitAnchor) + + // Prepare anchor output for sweeping. + anchorInput := input.MakeBaseInput( + &anchor.CommitAnchor, + input.CommitmentAnchor, + &anchor.AnchorSignDescriptor, + heightHint, + ) + + // Sweep anchor output with the minimum fee rate. This usually + // (up to a min relay fee of 3 sat/b) means that the anchor + // sweep will be economical. Also signal that this is a force + // sweep. If the user decides to bump the fee on the anchor + // sweep, it will be swept even if it isn't economical. + _, err := c.cfg.Sweeper.SweepInput( + &anchorInput, + sweep.Params{ + Fee: sweep.FeePreference{ + FeeRate: minFeeRate, + }, + Force: true, + ExclusiveGroup: &exclusiveGroup, + }, + ) + if err != nil { + return err + } + } + + return nil +} + // launchResolvers updates the activeResolvers list and starts the resolvers. func (c *ChannelArbitrator) launchResolvers(resolvers []ContractResolver) { c.activeResolversLock.Lock() diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index 46316d0cb9..b78f3c315a 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -197,6 +197,8 @@ type chanArbTestCtx struct { resolutions chan []ResolutionMsg log ArbitratorLog + + sweeper *mockSweeper } func (c *chanArbTestCtx) CleanUp() { @@ -314,6 +316,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog, incubateChan := make(chan struct{}) chainIO := &mockChainIO{} + mockSweeper := newMockSweeper() chainArbCfg := ChainArbitratorConfig{ ChainIO: chainIO, PublishTx: func(*wire.MsgTx) error { @@ -343,7 +346,8 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog, return true }, - Clock: clock.NewDefaultClock(), + Clock: clock.NewDefaultClock(), + Sweeper: mockSweeper, } // We'll use the resolvedChan to synchronize on call to @@ -420,6 +424,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog, blockEpochs: blockEpochs, log: log, incubationRequests: incubateChan, + sweeper: mockSweeper, }, nil } @@ -2083,7 +2088,92 @@ func TestRemoteCloseInitiator(t *testing.T) { } } -type mockChannel struct{} +// TestChannelArbitratorAnchors asserts that the commitment tx anchor is swept. +func TestChannelArbitratorAnchors(t *testing.T) { + log := &mockArbitratorLog{ + state: StateDefault, + newStates: make(chan ArbitratorState, 5), + } + + chanArbCtx, err := createTestChannelArbitrator(t, log) + if err != nil { + t.Fatalf("unable to create ChannelArbitrator: %v", err) + } + chanArb := chanArbCtx.chanArb + chanArb.cfg.PreimageDB = newMockWitnessBeacon() + chanArb.cfg.Registry = &mockRegistry{} + + // Setup two pre-confirmation anchor resolutions on the mock channel. + chanArb.cfg.Channel.(*mockChannel).anchorResolutions = + []*lnwallet.AnchorResolution{ + {}, {}, + } + + if err := chanArb.Start(); err != nil { + t.Fatalf("unable to start ChannelArbitrator: %v", err) + } + defer func() { + if err := chanArb.Stop(); err != nil { + t.Fatal(err) + } + }() + + // Create htlcUpdates channel. + htlcUpdates := make(chan *ContractUpdate) + + signals := &ContractSignals{ + HtlcUpdates: htlcUpdates, + ShortChanID: lnwire.ShortChannelID{}, + } + chanArb.UpdateContractSignals(signals) + + errChan := make(chan error, 1) + respChan := make(chan *wire.MsgTx, 1) + + // With the channel found, and the request crafted, we'll send over a + // force close request to the arbitrator that watches this channel. + chanArb.forceCloseReqs <- &forceCloseReq{ + errResp: errChan, + closeTx: respChan, + } + + // The force close request should trigger broadcast of the commitment + // transaction. + chanArbCtx.AssertStateTransitions( + StateBroadcastCommit, + StateCommitmentBroadcasted, + ) + + // With the commitment tx still unconfirmed, we expect sweep attempts + // for all three versions of the commitment transaction. + <-chanArbCtx.sweeper.sweptInputs + <-chanArbCtx.sweeper.sweptInputs + + select { + case <-respChan: + case <-time.After(5 * time.Second): + t.Fatalf("no response received") + } + + select { + case err := <-errChan: + if err != nil { + t.Fatalf("error force closing channel: %v", err) + } + case <-time.After(5 * time.Second): + t.Fatalf("no response received") + } +} + +type mockChannel struct { + anchorResolutions []*lnwallet.AnchorResolution +} + +func (m *mockChannel) NewAnchorResolutions() ([]*lnwallet.AnchorResolution, + error) { + + return m.anchorResolutions, nil +} func (m *mockChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error) { summary := &lnwallet.LocalForceCloseSummary{ diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index cc344372b7..d84ed1148b 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -8604,13 +8604,19 @@ func assertNumPendingChannels(t *harnessTest, node *lntest.HarnessNode, // on chain as he has no funds in the channel. func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest, carol *lntest.HarnessNode, carolStartingBalance int64, - dave *lntest.HarnessNode, daveStartingBalance int64) { + dave *lntest.HarnessNode, daveStartingBalance int64, + anchors bool) { // Upon reconnection, the nodes should detect that Dave is out of sync. // Carol should force close the channel using her latest commitment. + expectedTxes := 1 + if anchors { + expectedTxes = 2 + } + ctxb := context.Background() - forceClose, err := waitForTxInMempool( - net.Miner.Node, minerMempoolTimeout, + _, err := waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, ) if err != nil { t.Fatalf("unable to find Carol's force close tx in mempool: %v", @@ -8633,12 +8639,13 @@ func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest, } // Generate a single block, which should confirm the closing tx. - block := mineBlocks(t, net, 1, 1)[0] - assertTxInBlock(t, block, forceClose) + block := mineBlocks(t, net, 1, expectedTxes)[0] // Dave should sweep his funds immediately, as they are not timelocked. - daveSweep, err := waitForTxInMempool( - net.Miner.Node, minerMempoolTimeout, + // We also expect Dave to sweep his anchor, if present. + + _, err = waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, ) if err != nil { t.Fatalf("unable to find Dave's sweep tx in mempool: %v", err) @@ -8653,8 +8660,7 @@ func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest, assertNumPendingChannels(t, carol, 0, 1) // Mine the sweep tx. - block = mineBlocks(t, net, 1, 1)[0] - assertTxInBlock(t, block, daveSweep) + block = mineBlocks(t, net, 1, expectedTxes)[0] // Now Dave should consider the channel fully closed. assertNumPendingChannels(t, dave, 0, 0) @@ -8925,6 +8931,7 @@ func testDataLossProtection(net *lntest.NetworkHarness, t *harnessTest) { // on chain, and both of them properly carry out the DLP protocol. assertDLPExecuted( net, t, carol, carolStartingBalance, dave, daveStartingBalance, + false, ) // As a second part of this test, we will test the scenario where a @@ -14048,9 +14055,14 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness, } defer shutdownAndAssert(net, t, carol) - // Now that our new node is created, we'll give him some coins it can - // use to open channels with Carol. + // Now that our new nodes are created, we'll give them some coins for + // channel opening and anchor sweeping. ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, carol) + if err != nil { + t.Fatalf("unable to send coins to dave: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, dave) if err != nil { t.Fatalf("unable to send coins to dave: %v", err) @@ -14216,6 +14228,7 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness, // end of the protocol. assertDLPExecuted( net, t, carol, carolStartingBalance, dave, daveStartingBalance, + testCase.anchorCommit, ) } From 07a39b1ebf49af316239fda2f0d2c918b68ce01b Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 10 Mar 2020 15:07:14 +0100 Subject: [PATCH 239/562] cnct: do not persist stateless resolvers Preparation for the anchor resolver which does not have persistent state. --- contractcourt/briefcase.go | 9 +++++++-- contractcourt/channel_arbitrator_test.go | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/contractcourt/briefcase.go b/contractcourt/briefcase.go index 6a3bfa8b8a..1114f6db50 100644 --- a/contractcourt/briefcase.go +++ b/contractcourt/briefcase.go @@ -372,6 +372,13 @@ func fetchContractWriteBucket(tx *bbolt.Tx, scopeKey []byte) (*bbolt.Bucket, err func (b *boltArbitratorLog) writeResolver(contractBucket *bbolt.Bucket, res ContractResolver) error { + // Only persist resolvers that are stateful. Stateless resolvers don't + // expose a resolver key. + resKey := res.ResolverKey() + if resKey == nil { + return nil + } + // First, we'll write to the buffer the type of this resolver. Using // this byte, we can later properly deserialize the resolver properly. var ( @@ -400,8 +407,6 @@ func (b *boltArbitratorLog) writeResolver(contractBucket *bbolt.Bucket, return err } - resKey := res.ResolverKey() - return contractBucket.Put(resKey, buf.Bytes()) } diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index b78f3c315a..dcf969e93c 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -83,6 +83,11 @@ func (b *mockArbitratorLog) InsertUnresolvedContracts( b.Lock() for _, resolver := range resolvers { + resKey := resolver.ResolverKey() + if resKey == nil { + continue + } + b.resolvers[resolver] = struct{}{} } b.Unlock() From d84b596f55707f71691be049a42de8ce104e30b8 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 10 Mar 2020 15:13:50 +0100 Subject: [PATCH 240/562] cnct: do not ignore resolver reports after resolution Preparation for anchor resolver. The recovered anchor amount should still be included in the pending channel report even after it has been resolved. This also fixes an existing bug that in some cases caused the recovered amount from an htlc resolver not to be included in the total. --- contractcourt/channel_arbitrator.go | 4 ---- rpcserver.go | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index f0cc1f31d9..34ed98d3df 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -575,10 +575,6 @@ func (c *ChannelArbitrator) Report() []*ContractReport { continue } - if r.IsResolved() { - continue - } - report := r.report() if report == nil { continue diff --git a/rpcserver.go b/rpcserver.go index 841520a39d..bed4e79d41 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2817,6 +2817,12 @@ func (r *rpcServer) arbitratorPopulateForceCloseResp(chanPoint *wire.OutPoint, case contractcourt.ReportOutputIncomingHtlc, contractcourt.ReportOutputOutgoingHtlc: + // Don't report details on htlcs that are no longer in + // limbo. + if report.LimboBalance == 0 { + break + } + incoming := report.Type == contractcourt.ReportOutputIncomingHtlc htlc := &lnrpc.PendingHTLC{ Incoming: incoming, From ea397c9d6e6d6ec65f0812785c2ce63ea582eed3 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 25 Nov 2019 13:17:44 +0100 Subject: [PATCH 241/562] cnct: resolve anchors post-confirmation Sweeping anchors and being able to bump the fee was already added in a previous commit. This commit extends anchor sweeping with an anchor resolver object that becomes active after the commitment tx confirms. At that point, the anchors do not serve the purpose of getting the commitment tranaction confirmed anymore. It is however still possible to reclaim some of their value if using a low fee rate. --- contractcourt/anchor_resolver.go | 165 ++++++++++++++++++++ contractcourt/channel_arbitrator.go | 34 +++- contractcourt/channel_arbitrator_test.go | 63 ++++++++ contractcourt/commit_sweep_resolver_test.go | 18 ++- contractcourt/interfaces.go | 8 + 5 files changed, 282 insertions(+), 6 deletions(-) create mode 100644 contractcourt/anchor_resolver.go diff --git a/contractcourt/anchor_resolver.go b/contractcourt/anchor_resolver.go new file mode 100644 index 0000000000..02f44cfcdd --- /dev/null +++ b/contractcourt/anchor_resolver.go @@ -0,0 +1,165 @@ +package contractcourt + +import ( + "errors" + "io" + + "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/sweep" +) + +// anchorResolver is a resolver that will attempt to sweep our anchor output. +type anchorResolver struct { + // anchorSignDescriptor contains the information that is required to + // sweep the anchor. + anchorSignDescriptor input.SignDescriptor + + // anchor is the outpoint on the commitment transaction. + anchor wire.OutPoint + + // resolved reflects if the contract has been fully resolved or not. + resolved bool + + // broadcastHeight is the height that the original contract was + // broadcast to the main-chain at. We'll use this value to bound any + // historical queries to the chain for spends/confirmations. + broadcastHeight uint32 + + // chanPoint is the channel point of the original contract. + chanPoint wire.OutPoint + + contractResolverKit +} + +// newAnchorResolver instantiates a new anchor resolver. +func newAnchorResolver(anchorSignDescriptor input.SignDescriptor, + anchor wire.OutPoint, broadcastHeight uint32, + chanPoint wire.OutPoint, resCfg ResolverConfig) *anchorResolver { + + r := &anchorResolver{ + contractResolverKit: *newContractResolverKit(resCfg), + anchorSignDescriptor: anchorSignDescriptor, + anchor: anchor, + broadcastHeight: broadcastHeight, + chanPoint: chanPoint, + } + + r.initLogger(r) + + return r +} + +// ResolverKey returns an identifier which should be globally unique for this +// particular resolver within the chain the original contract resides within. +func (c *anchorResolver) ResolverKey() []byte { + // The anchor resolver is stateless and doesn't need a database key. + return nil +} + +// Resolve offers the anchor output to the sweeper and waits for it to be swept. +func (c *anchorResolver) Resolve() (ContractResolver, error) { + // Attempt to update the sweep parameters to the post-confirmation + // situation. We don't want to force sweep anymore, because the anchor + // lost its special purpose to get the commitment confirmed. It is just + // an output that we want to sweep only if it is economical to do so. + relayFeeRate := c.Sweeper.RelayFeePerKW() + + resultChan, err := c.Sweeper.UpdateParams( + c.anchor, + sweep.ParamsUpdate{ + Fee: sweep.FeePreference{ + FeeRate: relayFeeRate, + }, + Force: false, + }, + ) + + // After a restart or when the remote force closes, the sweeper is not + // yet aware of the anchor. In that case, offer it as a new input to the + // sweeper. An exclusive group is not necessary anymore, because we know + // that this is the only anchor that can be swept. + if err == lnwallet.ErrNotMine { + anchorInput := input.MakeBaseInput( + &c.anchor, + input.CommitmentAnchor, + &c.anchorSignDescriptor, + c.broadcastHeight, + ) + + resultChan, err = c.Sweeper.SweepInput( + &anchorInput, + sweep.Params{ + Fee: sweep.FeePreference{ + FeeRate: relayFeeRate, + }, + }, + ) + if err != nil { + return nil, err + } + } + + select { + case sweepRes := <-resultChan: + switch sweepRes.Err { + + // Anchor was swept successfully. + case nil: + c.log.Debugf("anchor swept by tx %v", + sweepRes.Tx.TxHash()) + + // Anchor was swept by someone else. This is possible after the + // 16 block csv lock. + case sweep.ErrRemoteSpend: + c.log.Warnf("our anchor spent by someone else") + + // The sweeper gave up on sweeping the anchor. This happens + // after the maximum number of sweep attempts has been reached. + // See sweep.DefaultMaxSweepAttempts. Sweep attempts are + // interspaced with random delays picked from a range that + // increases exponentially. + // + // We consider the anchor as being lost. + case sweep.ErrTooManyAttempts: + c.log.Warnf("anchor sweep abandoned") + + // An unexpected error occurred. + default: + c.log.Errorf("unable to sweep anchor: %v", sweepRes.Err) + + return nil, sweepRes.Err + } + + case <-c.quit: + return nil, errResolverShuttingDown + } + + c.resolved = true + return nil, nil +} + +// Stop signals the resolver to cancel any current resolution processes, and +// suspend. +// +// NOTE: Part of the ContractResolver interface. +func (c *anchorResolver) Stop() { + close(c.quit) +} + +// IsResolved returns true if the stored state in the resolve is fully +// resolved. In this case the target output can be forgotten. +// +// NOTE: Part of the ContractResolver interface. +func (c *anchorResolver) IsResolved() bool { + return c.resolved +} + +func (c *anchorResolver) Encode(w io.Writer) error { + return errors.New("serialization not supported") +} + +// A compile time assertion to ensure anchorResolver meets the +// ContractResolver interface. +var _ ContractResolver = (*anchorResolver)(nil) diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 34ed98d3df..fe2289aba4 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -467,7 +467,7 @@ func (c *ChannelArbitrator) Start() error { // receive a chain event from the chain watcher than the // commitment has been confirmed on chain, and before we // advance our state step, we call InsertConfirmedCommitSet. - if err := c.relaunchResolvers(commitSet); err != nil { + if err := c.relaunchResolvers(commitSet, triggerHeight); err != nil { c.cfg.BlockEpochs.Cancel() return err } @@ -483,7 +483,9 @@ func (c *ChannelArbitrator) Start() error { // starting the ChannelArbitrator. This information should ideally be stored in // the database, so this only serves as a intermediate work-around to prevent a // migration. -func (c *ChannelArbitrator) relaunchResolvers(commitSet *CommitSet) error { +func (c *ChannelArbitrator) relaunchResolvers(commitSet *CommitSet, + heightHint uint32) error { + // We'll now query our log to see if there are any active unresolved // contracts. If this is the case, then we'll relaunch all contract // resolvers. @@ -558,6 +560,19 @@ func (c *ChannelArbitrator) relaunchResolvers(commitSet *CommitSet) error { htlcResolver.Supplement(*htlc) } + // The anchor resolver is stateless and can always be re-instantiated. + if contractResolutions.AnchorResolution != nil { + anchorResolver := newAnchorResolver( + contractResolutions.AnchorResolution.AnchorSignDescriptor, + contractResolutions.AnchorResolution.CommitAnchor, + heightHint, c.cfg.ChanPoint, + ResolverConfig{ + ChannelArbitratorConfig: c.cfg, + }, + ) + unresolvedContracts = append(unresolvedContracts, anchorResolver) + } + c.launchResolvers(unresolvedContracts) return nil @@ -1856,8 +1871,8 @@ func (c *ChannelArbitrator) prepContractResolutions( } } - // Finally, if this is was a unilateral closure, then we'll also create - // a resolver to sweep our commitment output (but only if it wasn't + // If this is was an unilateral closure, then we'll also create a + // resolver to sweep our commitment output (but only if it wasn't // trimmed). if contractResolutions.CommitResolution != nil { resolver := newCommitSweepResolver( @@ -1867,6 +1882,17 @@ func (c *ChannelArbitrator) prepContractResolutions( htlcResolvers = append(htlcResolvers, resolver) } + // We instantiate an anchor resolver if the commitmentment tx has an + // anchor. + if contractResolutions.AnchorResolution != nil { + anchorResolver := newAnchorResolver( + contractResolutions.AnchorResolution.AnchorSignDescriptor, + contractResolutions.AnchorResolution.CommitAnchor, + height, c.cfg.ChanPoint, resolverCfg, + ) + htlcResolvers = append(htlcResolvers, anchorResolver) + } + return htlcResolvers, msgsToSend, nil } diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index dcf969e93c..bbe1c51f52 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -2168,6 +2168,69 @@ func TestChannelArbitratorAnchors(t *testing.T) { case <-time.After(5 * time.Second): t.Fatalf("no response received") } + + // Now notify about the local force close getting confirmed. + closeTx := &wire.MsgTx{ + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{}, + Witness: [][]byte{ + {0x1}, + {0x2}, + }, + }, + }, + } + + chanArb.cfg.ChainEvents.LocalUnilateralClosure <- &LocalUnilateralCloseInfo{ + SpendDetail: &chainntnfs.SpendDetail{}, + LocalForceCloseSummary: &lnwallet.LocalForceCloseSummary{ + CloseTx: closeTx, + HtlcResolutions: &lnwallet.HtlcResolutions{}, + AnchorResolution: &lnwallet.AnchorResolution{ + AnchorSignDescriptor: input.SignDescriptor{ + Output: &wire.TxOut{ + Value: 1, + }, + }, + }, + }, + ChannelCloseSummary: &channeldb.ChannelCloseSummary{}, + CommitSet: CommitSet{ + ConfCommitKey: &LocalHtlcSet, + HtlcSets: map[HtlcSetKey][]channeldb.HTLC{}, + }, + } + + chanArbCtx.AssertStateTransitions( + StateContractClosed, + StateWaitingFullResolution, + ) + + // We expect to only have the anchor resolver active. + if len(chanArb.activeResolvers) != 1 { + t.Fatalf("expected single resolver, instead got: %v", + len(chanArb.activeResolvers)) + } + + resolver := chanArb.activeResolvers[0] + _, ok := resolver.(*anchorResolver) + if !ok { + t.Fatalf("expected anchor resolver, got %T", resolver) + } + + // The anchor resolver is expected to offer the anchor input to the + // sweeper. + <-chanArbCtx.sweeper.updatedInputs + + // The mock sweeper immediately signals success for that input. This + // should transition the channel to the resolved state. + chanArbCtx.AssertStateTransitions(StateFullyResolved) + select { + case <-chanArbCtx.resolvedChan: + case <-time.After(5 * time.Second): + t.Fatalf("contract was not resolved") + } } type mockChannel struct { diff --git a/contractcourt/commit_sweep_resolver_test.go b/contractcourt/commit_sweep_resolver_test.go index e5c7df0506..279cc6e846 100644 --- a/contractcourt/commit_sweep_resolver_test.go +++ b/contractcourt/commit_sweep_resolver_test.go @@ -94,12 +94,14 @@ func (i *commitSweepResolverTestContext) waitForResult() { } type mockSweeper struct { - sweptInputs chan input.Input + sweptInputs chan input.Input + updatedInputs chan wire.OutPoint } func newMockSweeper() *mockSweeper { return &mockSweeper{ - sweptInputs: make(chan input.Input), + sweptInputs: make(chan input.Input), + updatedInputs: make(chan wire.OutPoint), } } @@ -125,6 +127,18 @@ func (s *mockSweeper) RelayFeePerKW() chainfee.SatPerKWeight { return 253 } +func (s *mockSweeper) UpdateParams(input wire.OutPoint, + params sweep.ParamsUpdate) (chan sweep.Result, error) { + + s.updatedInputs <- input + + result := make(chan sweep.Result, 1) + result <- sweep.Result{ + Tx: &wire.MsgTx{}, + } + return result, nil +} + var _ UtxoSweeper = &mockSweeper{} // TestCommitSweepResolverNoDelay tests resolution of a direct commitment output diff --git a/contractcourt/interfaces.go b/contractcourt/interfaces.go index 5497dad8bc..ded07f3276 100644 --- a/contractcourt/interfaces.go +++ b/contractcourt/interfaces.go @@ -56,4 +56,12 @@ type UtxoSweeper interface { // RelayFeePerKW returns the minimum fee rate required for transactions // to be relayed. RelayFeePerKW() chainfee.SatPerKWeight + + // UpdateParams allows updating the sweep parameters of a pending input + // in the UtxoSweeper. This function can be used to provide an updated + // fee preference that will be used for a new sweep transaction of the + // input that will act as a replacement transaction (RBF) of the + // original sweeping transaction, if any. + UpdateParams(input wire.OutPoint, params sweep.ParamsUpdate) ( + chan sweep.Result, error) } From ab451f634e5e708a71e83de330aa09455c0b2330 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 10 Mar 2020 13:39:01 +0100 Subject: [PATCH 242/562] cnct+lnrpc: report anchor resolution --- contractcourt/anchor_resolver.go | 40 + contractcourt/channel_arbitrator.go | 3 + lnrpc/rpc.pb.go | 1454 ++++++++++++++------------- lnrpc/rpc.proto | 8 + lnrpc/rpc.swagger.json | 12 + rpcserver.go | 17 +- 6 files changed, 826 insertions(+), 708 deletions(-) diff --git a/contractcourt/anchor_resolver.go b/contractcourt/anchor_resolver.go index 02f44cfcdd..1cf7a820ad 100644 --- a/contractcourt/anchor_resolver.go +++ b/contractcourt/anchor_resolver.go @@ -3,8 +3,10 @@ package contractcourt import ( "errors" "io" + "sync" "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/sweep" @@ -30,6 +32,13 @@ type anchorResolver struct { // chanPoint is the channel point of the original contract. chanPoint wire.OutPoint + // currentReport stores the current state of the resolver for reporting + // over the rpc interface. + currentReport ContractReport + + // reportLock prevents concurrent access to the resolver report. + reportLock sync.Mutex + contractResolverKit } @@ -38,12 +47,23 @@ func newAnchorResolver(anchorSignDescriptor input.SignDescriptor, anchor wire.OutPoint, broadcastHeight uint32, chanPoint wire.OutPoint, resCfg ResolverConfig) *anchorResolver { + amt := btcutil.Amount(anchorSignDescriptor.Output.Value) + + report := ContractReport{ + Outpoint: anchor, + Type: ReportOutputAnchor, + Amount: amt, + LimboBalance: amt, + RecoveredBalance: 0, + } + r := &anchorResolver{ contractResolverKit: *newContractResolverKit(resCfg), anchorSignDescriptor: anchorSignDescriptor, anchor: anchor, broadcastHeight: broadcastHeight, chanPoint: chanPoint, + currentReport: report, } r.initLogger(r) @@ -101,6 +121,7 @@ func (c *anchorResolver) Resolve() (ContractResolver, error) { } } + var anchorRecovered bool select { case sweepRes := <-resultChan: switch sweepRes.Err { @@ -110,6 +131,8 @@ func (c *anchorResolver) Resolve() (ContractResolver, error) { c.log.Debugf("anchor swept by tx %v", sweepRes.Tx.TxHash()) + anchorRecovered = true + // Anchor was swept by someone else. This is possible after the // 16 block csv lock. case sweep.ErrRemoteSpend: @@ -136,6 +159,14 @@ func (c *anchorResolver) Resolve() (ContractResolver, error) { return nil, errResolverShuttingDown } + // Update report to reflect that funds are no longer in limbo. + c.reportLock.Lock() + if anchorRecovered { + c.currentReport.RecoveredBalance = c.currentReport.LimboBalance + } + c.currentReport.LimboBalance = 0 + c.reportLock.Unlock() + c.resolved = true return nil, nil } @@ -156,6 +187,15 @@ func (c *anchorResolver) IsResolved() bool { return c.resolved } +// report returns a report on the resolution state of the contract. +func (c *anchorResolver) report() *ContractReport { + c.reportLock.Lock() + defer c.reportLock.Unlock() + + reportCopy := c.currentReport + return &reportCopy +} + func (c *anchorResolver) Encode(w io.Writer) error { return errors.New("serialization not supported") } diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index fe2289aba4..46aab0d022 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -162,6 +162,9 @@ const ( // ReportOutputUnencumbered is an uncontested output on the commitment // transaction paying to us directly. ReportOutputUnencumbered + + // ReportOutputAnchor is an anchor output on the commitment tx. + ReportOutputAnchor ) // ContractReport provides a summary of a commitment tx output. diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index e8637661a4..f49fdbebb4 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -324,6 +324,34 @@ func (PeerEvent_EventType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_77a6da22d6a3feb1, []int{51, 0} } +type PendingChannelsResponse_ForceClosedChannel_AnchorState int32 + +const ( + PendingChannelsResponse_ForceClosedChannel_LIMBO PendingChannelsResponse_ForceClosedChannel_AnchorState = 0 + PendingChannelsResponse_ForceClosedChannel_RECOVERED PendingChannelsResponse_ForceClosedChannel_AnchorState = 1 + PendingChannelsResponse_ForceClosedChannel_LOST PendingChannelsResponse_ForceClosedChannel_AnchorState = 2 +) + +var PendingChannelsResponse_ForceClosedChannel_AnchorState_name = map[int32]string{ + 0: "LIMBO", + 1: "RECOVERED", + 2: "LOST", +} + +var PendingChannelsResponse_ForceClosedChannel_AnchorState_value = map[string]int32{ + "LIMBO": 0, + "RECOVERED": 1, + "LOST": 2, +} + +func (x PendingChannelsResponse_ForceClosedChannel_AnchorState) String() string { + return proto.EnumName(PendingChannelsResponse_ForceClosedChannel_AnchorState_name, int32(x)) +} + +func (PendingChannelsResponse_ForceClosedChannel_AnchorState) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{72, 4, 0} +} + type ChannelEventUpdate_UpdateType int32 const ( @@ -5770,11 +5798,12 @@ type PendingChannelsResponse_ForceClosedChannel struct { //mature. BlocksTilMaturity int32 `protobuf:"varint,5,opt,name=blocks_til_maturity,json=blocksTilMaturity,proto3" json:"blocks_til_maturity,omitempty"` /// The total value of funds successfully recovered from this channel - RecoveredBalance int64 `protobuf:"varint,6,opt,name=recovered_balance,json=recoveredBalance,proto3" json:"recovered_balance,omitempty"` - PendingHtlcs []*PendingHTLC `protobuf:"bytes,8,rep,name=pending_htlcs,json=pendingHtlcs,proto3" json:"pending_htlcs,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + RecoveredBalance int64 `protobuf:"varint,6,opt,name=recovered_balance,json=recoveredBalance,proto3" json:"recovered_balance,omitempty"` + PendingHtlcs []*PendingHTLC `protobuf:"bytes,8,rep,name=pending_htlcs,json=pendingHtlcs,proto3" json:"pending_htlcs,omitempty"` + Anchor PendingChannelsResponse_ForceClosedChannel_AnchorState `protobuf:"varint,9,opt,name=anchor,proto3,enum=lnrpc.PendingChannelsResponse_ForceClosedChannel_AnchorState" json:"anchor,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *PendingChannelsResponse_ForceClosedChannel) Reset() { @@ -5855,6 +5884,13 @@ func (m *PendingChannelsResponse_ForceClosedChannel) GetPendingHtlcs() []*Pendin return nil } +func (m *PendingChannelsResponse_ForceClosedChannel) GetAnchor() PendingChannelsResponse_ForceClosedChannel_AnchorState { + if m != nil { + return m.Anchor + } + return PendingChannelsResponse_ForceClosedChannel_LIMBO +} + type ChannelEventSubscription struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -11043,6 +11079,7 @@ func init() { proto.RegisterEnum("lnrpc.ChannelCloseSummary_Initiator", ChannelCloseSummary_Initiator_name, ChannelCloseSummary_Initiator_value) proto.RegisterEnum("lnrpc.Peer_SyncType", Peer_SyncType_name, Peer_SyncType_value) proto.RegisterEnum("lnrpc.PeerEvent_EventType", PeerEvent_EventType_name, PeerEvent_EventType_value) + proto.RegisterEnum("lnrpc.PendingChannelsResponse_ForceClosedChannel_AnchorState", PendingChannelsResponse_ForceClosedChannel_AnchorState_name, PendingChannelsResponse_ForceClosedChannel_AnchorState_value) proto.RegisterEnum("lnrpc.ChannelEventUpdate_UpdateType", ChannelEventUpdate_UpdateType_name, ChannelEventUpdate_UpdateType_value) proto.RegisterEnum("lnrpc.Invoice_InvoiceState", Invoice_InvoiceState_name, Invoice_InvoiceState_value) proto.RegisterEnum("lnrpc.Payment_PaymentStatus", Payment_PaymentStatus_name, Payment_PaymentStatus_value) @@ -11218,709 +11255,712 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11219 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x1c, 0x49, - 0x72, 0x18, 0xfb, 0x35, 0xdd, 0x1d, 0xfd, 0x9c, 0x9c, 0x57, 0x73, 0xb8, 0x5c, 0x72, 0x6b, 0xf7, - 0x96, 0x3c, 0xee, 0x1d, 0xc9, 0xe5, 0x1d, 0xf7, 0x4e, 0xbb, 0xf6, 0xe9, 0x7a, 0x66, 0x7a, 0x38, - 0x7d, 0x9c, 0xd7, 0x56, 0xf7, 0xec, 0x6a, 0x4f, 0x96, 0xeb, 0x6a, 0xba, 0x73, 0x66, 0x4a, 0xec, - 0xae, 0xea, 0xad, 0xaa, 0x9e, 0xc7, 0x1d, 0xd6, 0x1f, 0xfc, 0x10, 0x0c, 0xbf, 0x00, 0xc1, 0x96, - 0x01, 0xcb, 0x16, 0x6c, 0xd8, 0x30, 0x0c, 0xc3, 0x80, 0x20, 0xe3, 0x64, 0xc0, 0x1f, 0xfc, 0x5d, - 0x5f, 0x6c, 0xe8, 0x83, 0xe4, 0x2f, 0x86, 0x20, 0x40, 0xb0, 0x7c, 0xfe, 0xaa, 0x9f, 0x60, 0x64, - 0x44, 0x66, 0x55, 0x56, 0x77, 0x0d, 0xc9, 0xbd, 0x5b, 0xdf, 0x17, 0x72, 0x2a, 0x32, 0xf2, 0x1d, - 0x19, 0x19, 0x8f, 0x8c, 0x68, 0x28, 0xfb, 0x93, 0xc1, 0xc3, 0x89, 0xef, 0x85, 0x1e, 0x2b, 0x8c, - 0x5c, 0x7f, 0x32, 0x58, 0x7f, 0xe3, 0xd4, 0xf3, 0x4e, 0x47, 0xfc, 0x91, 0x3d, 0x71, 0x1e, 0xd9, - 0xae, 0xeb, 0x85, 0x76, 0xe8, 0x78, 0x6e, 0x40, 0x48, 0xc6, 0x8f, 0xa0, 0xfe, 0x8c, 0xbb, 0x3d, - 0xce, 0x87, 0x26, 0xff, 0x7c, 0xca, 0x83, 0x90, 0xbd, 0x07, 0x8b, 0x36, 0xff, 0x31, 0xe7, 0x43, - 0x6b, 0x62, 0x07, 0xc1, 0xe4, 0xcc, 0xb7, 0x03, 0xde, 0xca, 0xdc, 0xcd, 0xdc, 0xaf, 0x9a, 0x4d, - 0x2a, 0x38, 0x8c, 0xe0, 0xec, 0x2d, 0xa8, 0x06, 0x02, 0x95, 0xbb, 0xa1, 0xef, 0x4d, 0xae, 0x5a, - 0x59, 0xc4, 0xab, 0x08, 0x58, 0x87, 0x40, 0xc6, 0x08, 0x1a, 0x51, 0x0f, 0xc1, 0xc4, 0x73, 0x03, - 0xce, 0x1e, 0xc3, 0xf2, 0xc0, 0x99, 0x9c, 0x71, 0xdf, 0xc2, 0xca, 0x63, 0x97, 0x8f, 0x3d, 0xd7, - 0x19, 0xb4, 0x32, 0x77, 0x73, 0xf7, 0xcb, 0x26, 0xa3, 0x32, 0x51, 0x63, 0x4f, 0x96, 0xb0, 0x7b, - 0xd0, 0xe0, 0x2e, 0xc1, 0xf9, 0x10, 0x6b, 0xc9, 0xae, 0xea, 0x31, 0x58, 0x54, 0x30, 0xfe, 0x7e, - 0x16, 0x16, 0xbb, 0xae, 0x13, 0x7e, 0x6a, 0x8f, 0x46, 0x3c, 0x54, 0x73, 0xba, 0x07, 0x8d, 0x0b, - 0x04, 0xe0, 0x9c, 0x2e, 0x3c, 0x7f, 0x28, 0x67, 0x54, 0x27, 0xf0, 0xa1, 0x84, 0x5e, 0x3b, 0xb2, - 0xec, 0xb5, 0x23, 0x4b, 0x5d, 0xae, 0xdc, 0x35, 0xcb, 0x75, 0x0f, 0x1a, 0x3e, 0x1f, 0x78, 0xe7, - 0xdc, 0xbf, 0xb2, 0x2e, 0x1c, 0x77, 0xe8, 0x5d, 0xb4, 0xf2, 0x77, 0x33, 0xf7, 0x0b, 0x66, 0x5d, - 0x81, 0x3f, 0x45, 0x28, 0xdb, 0x80, 0xc6, 0xe0, 0xcc, 0x76, 0x5d, 0x3e, 0xb2, 0x8e, 0xed, 0xc1, - 0x8b, 0xe9, 0x24, 0x68, 0x15, 0xee, 0x66, 0xee, 0x57, 0x9e, 0xdc, 0x7c, 0x88, 0xbb, 0xfa, 0x70, - 0xf3, 0xcc, 0x76, 0x37, 0xb0, 0xa4, 0xe7, 0xda, 0x93, 0xe0, 0xcc, 0x0b, 0xcd, 0xba, 0xac, 0x41, - 0xe0, 0xc0, 0x58, 0x06, 0xa6, 0xaf, 0x04, 0xad, 0xbd, 0xf1, 0x9f, 0x32, 0xb0, 0x74, 0xe4, 0x8e, - 0xbc, 0xc1, 0x8b, 0x9f, 0x73, 0x89, 0x52, 0xe6, 0x90, 0x7d, 0xdd, 0x39, 0xe4, 0xbe, 0xec, 0x1c, - 0x56, 0x61, 0x39, 0x39, 0x58, 0x39, 0x0b, 0x0e, 0x2b, 0xa2, 0xf6, 0x29, 0x57, 0xc3, 0x52, 0xd3, - 0xf8, 0x3a, 0x34, 0x07, 0x53, 0xdf, 0xe7, 0xee, 0xdc, 0x3c, 0x1a, 0x12, 0x1e, 0x4d, 0xe4, 0x2d, - 0xa8, 0xba, 0xfc, 0x22, 0x46, 0x93, 0xb4, 0xeb, 0xf2, 0x0b, 0x85, 0x62, 0xb4, 0x60, 0x75, 0xb6, - 0x1b, 0x39, 0x80, 0x9f, 0x65, 0x20, 0x7f, 0x14, 0x5e, 0x7a, 0xec, 0x29, 0x54, 0xed, 0xe1, 0xd0, - 0xe7, 0x41, 0x60, 0x85, 0x57, 0x13, 0x3a, 0x29, 0xf5, 0x27, 0x4c, 0x4e, 0xb1, 0x4d, 0x45, 0xfd, - 0xab, 0x09, 0x37, 0x2b, 0x76, 0xfc, 0xc1, 0x5a, 0x50, 0x94, 0x9f, 0xd8, 0x6f, 0xd9, 0x54, 0x9f, - 0xec, 0x36, 0x80, 0x3d, 0xf6, 0xa6, 0x6e, 0x68, 0x05, 0x76, 0x88, 0x2b, 0x96, 0x33, 0xcb, 0x04, - 0xe9, 0xd9, 0x21, 0xbb, 0x05, 0xe5, 0xc9, 0x0b, 0x2b, 0x18, 0xf8, 0xce, 0x24, 0x44, 0xe2, 0x29, - 0x9b, 0xa5, 0xc9, 0x8b, 0x1e, 0x7e, 0xb3, 0xf7, 0xa0, 0xe4, 0x4d, 0xc3, 0x89, 0xe7, 0xb8, 0xa1, - 0xa4, 0x97, 0x86, 0x1c, 0xc8, 0xc1, 0x34, 0x3c, 0x14, 0x60, 0x33, 0x42, 0x60, 0xef, 0x40, 0x6d, - 0xe0, 0xb9, 0x27, 0x8e, 0x3f, 0x26, 0x8e, 0xd0, 0x5a, 0xc0, 0xbe, 0x92, 0x40, 0xe3, 0x0f, 0xb2, - 0x50, 0xe9, 0xfb, 0xb6, 0x1b, 0xd8, 0x03, 0x01, 0x60, 0x6b, 0x50, 0x0c, 0x2f, 0xad, 0x33, 0x3b, - 0x38, 0xc3, 0xa9, 0x96, 0xcd, 0x85, 0xf0, 0x72, 0xc7, 0x0e, 0xce, 0xd8, 0x2a, 0x2c, 0xd0, 0x28, - 0x71, 0x42, 0x39, 0x53, 0x7e, 0x89, 0x03, 0xe2, 0x4e, 0xc7, 0x56, 0xb2, 0xab, 0x1c, 0x52, 0x4c, - 0xd3, 0x9d, 0x8e, 0x37, 0x75, 0xb8, 0x98, 0xfc, 0xb1, 0xd8, 0x6e, 0xea, 0x80, 0xa6, 0x57, 0x46, - 0x08, 0xf6, 0xf1, 0x16, 0x54, 0x65, 0x31, 0x77, 0x4e, 0xcf, 0x68, 0x8e, 0x05, 0xb3, 0x42, 0x08, - 0x08, 0x12, 0x2d, 0x84, 0xce, 0x98, 0x5b, 0x41, 0x68, 0x8f, 0x27, 0x72, 0x4a, 0x65, 0x01, 0xe9, - 0x09, 0x00, 0x16, 0x7b, 0xa1, 0x3d, 0xb2, 0x4e, 0x38, 0x0f, 0x5a, 0x45, 0x59, 0x2c, 0x20, 0xdb, - 0x9c, 0x07, 0xec, 0x6b, 0x50, 0x1f, 0xf2, 0x20, 0xb4, 0xe4, 0x66, 0xf0, 0xa0, 0x55, 0xc2, 0x93, - 0x5f, 0x13, 0xd0, 0xb6, 0x02, 0xb2, 0x37, 0x00, 0x7c, 0xfb, 0xc2, 0x12, 0x0b, 0xc1, 0x2f, 0x5b, - 0x65, 0xda, 0x05, 0xdf, 0xbe, 0xe8, 0x5f, 0xee, 0xf0, 0x4b, 0x41, 0x35, 0xcf, 0x78, 0xa8, 0x2d, - 0x5a, 0x20, 0xa9, 0xd3, 0xd8, 0x05, 0xa6, 0x81, 0xb7, 0x78, 0x68, 0x3b, 0xa3, 0x80, 0x7d, 0x00, - 0xd5, 0x50, 0x43, 0x46, 0x36, 0x58, 0x89, 0x48, 0x48, 0xab, 0x60, 0x26, 0xf0, 0x8c, 0x33, 0x28, - 0x6d, 0x73, 0xbe, 0xeb, 0x8c, 0x9d, 0x90, 0xad, 0x42, 0xe1, 0xc4, 0xb9, 0xe4, 0x44, 0xec, 0xb9, - 0x9d, 0x1b, 0x26, 0x7d, 0xb2, 0x3b, 0x00, 0xf8, 0x87, 0x35, 0x8e, 0xa8, 0x69, 0xe7, 0x86, 0x59, - 0x46, 0xd8, 0x5e, 0x60, 0x87, 0x6c, 0x1d, 0x8a, 0x13, 0xee, 0x0f, 0xb8, 0xda, 0xb7, 0x9d, 0x1b, - 0xa6, 0x02, 0x6c, 0x14, 0xa1, 0x30, 0x12, 0xad, 0x1b, 0x7f, 0x54, 0x80, 0x4a, 0x8f, 0xbb, 0xd1, - 0x29, 0x63, 0x90, 0x17, 0x0b, 0x22, 0x4f, 0x16, 0xfe, 0xcd, 0xde, 0x86, 0x0a, 0x2e, 0x5d, 0x10, - 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x91, 0x6d, 0x65, 0x4c, 0x10, 0xe0, 0x1e, 0x42, 0x59, 0x13, - 0x72, 0xf6, 0x58, 0x51, 0xb5, 0xf8, 0x93, 0xdd, 0x84, 0x92, 0x3d, 0x0e, 0x69, 0x78, 0x55, 0x04, - 0x17, 0xed, 0x71, 0x88, 0x43, 0x7b, 0x0b, 0xaa, 0x13, 0xfb, 0x6a, 0x2c, 0xce, 0x72, 0x44, 0x0e, - 0x55, 0xb3, 0x22, 0x61, 0x48, 0x10, 0x4f, 0x60, 0x49, 0x47, 0x51, 0x9d, 0x17, 0xa2, 0xce, 0x17, - 0x35, 0x6c, 0x39, 0x86, 0x7b, 0xd0, 0x50, 0x75, 0x7c, 0x9a, 0x0f, 0x92, 0x49, 0xd9, 0xac, 0x4b, - 0xb0, 0x9a, 0xe5, 0x7d, 0x68, 0x9e, 0x38, 0xae, 0x3d, 0xb2, 0x06, 0xa3, 0xf0, 0xdc, 0x1a, 0xf2, - 0x51, 0x68, 0x23, 0xc5, 0x14, 0xcc, 0x3a, 0xc2, 0x37, 0x47, 0xe1, 0xf9, 0x96, 0x80, 0xb2, 0x6f, - 0x40, 0xf9, 0x84, 0x73, 0x0b, 0x17, 0xab, 0x55, 0x4a, 0x1c, 0x3c, 0xb5, 0x43, 0x66, 0xe9, 0x44, - 0xed, 0xd5, 0x37, 0xa0, 0xe9, 0x4d, 0xc3, 0x53, 0xcf, 0x71, 0x4f, 0x2d, 0xc1, 0xef, 0x2c, 0x67, - 0x88, 0x34, 0x94, 0xdf, 0xc8, 0x3e, 0xce, 0x98, 0x75, 0x55, 0x26, 0x38, 0x4f, 0x77, 0xc8, 0xde, - 0x85, 0xc6, 0xc8, 0x0e, 0x42, 0xeb, 0xcc, 0x9b, 0x58, 0x93, 0xe9, 0xf1, 0x0b, 0x7e, 0xd5, 0xaa, - 0xe1, 0x42, 0xd4, 0x04, 0x78, 0xc7, 0x9b, 0x1c, 0x22, 0x50, 0x50, 0x36, 0x8e, 0x93, 0x06, 0x01, - 0x77, 0x33, 0xf7, 0x6b, 0x66, 0x59, 0x40, 0xa8, 0xd3, 0xcf, 0x60, 0x09, 0xb7, 0x67, 0x30, 0x0d, - 0x42, 0x6f, 0x6c, 0x09, 0x5e, 0xed, 0x0f, 0x83, 0x56, 0x05, 0x69, 0xed, 0xeb, 0x72, 0xb0, 0xda, - 0x1e, 0x3f, 0xdc, 0xe2, 0x41, 0xb8, 0x89, 0xc8, 0x26, 0xe1, 0x8a, 0x0b, 0xfd, 0xca, 0x5c, 0x1c, - 0xce, 0xc2, 0xd9, 0x37, 0x80, 0xd9, 0xa3, 0x91, 0x77, 0x61, 0x05, 0x7c, 0x74, 0x62, 0xc9, 0x45, - 0x6c, 0xd5, 0xef, 0x66, 0xee, 0x97, 0xcc, 0x26, 0x96, 0xf4, 0xf8, 0xe8, 0xe4, 0x90, 0xe0, 0xec, - 0x03, 0xc0, 0xc3, 0x64, 0x9d, 0x70, 0x3b, 0x9c, 0xfa, 0x3c, 0x68, 0x35, 0xee, 0xe6, 0xee, 0xd7, - 0x9f, 0x2c, 0x46, 0xeb, 0x85, 0xe0, 0x0d, 0x27, 0x34, 0xab, 0x02, 0x4f, 0x7e, 0x07, 0xeb, 0x5b, - 0xb0, 0x9a, 0x3e, 0x24, 0x41, 0x54, 0x62, 0x55, 0x04, 0x31, 0xe6, 0x4d, 0xf1, 0x27, 0x5b, 0x86, - 0xc2, 0xb9, 0x3d, 0x9a, 0x72, 0xc9, 0xd3, 0xe9, 0xe3, 0xc3, 0xec, 0x77, 0x33, 0xc6, 0x1f, 0x66, - 0xa0, 0x4a, 0xb3, 0x94, 0xb2, 0xc8, 0xdb, 0x50, 0x53, 0xd4, 0xc0, 0x7d, 0xdf, 0xf3, 0x25, 0x57, - 0x53, 0x94, 0xd7, 0x11, 0x30, 0x71, 0xab, 0x28, 0xa4, 0x89, 0xcf, 0x9d, 0xb1, 0x7d, 0xaa, 0x9a, - 0x56, 0xa4, 0x74, 0x28, 0xc1, 0xec, 0xfd, 0xb8, 0x3d, 0xdf, 0x9b, 0x86, 0x5c, 0xde, 0x79, 0x55, - 0x39, 0x3d, 0x53, 0xc0, 0xa2, 0xd6, 0xf1, 0xeb, 0x35, 0xe8, 0xdc, 0xf8, 0x9d, 0x0c, 0x30, 0x31, - 0xec, 0xbe, 0x47, 0x0d, 0x48, 0x0a, 0x9d, 0xad, 0x99, 0x79, 0xed, 0x13, 0x92, 0x7d, 0xd9, 0x09, - 0x31, 0xa0, 0x40, 0x63, 0xcf, 0xa7, 0x8c, 0x9d, 0x8a, 0x7e, 0x90, 0x2f, 0xe5, 0x9a, 0x79, 0xe3, - 0x7f, 0xe5, 0x60, 0x79, 0x93, 0xae, 0xec, 0xf6, 0x60, 0xc0, 0x27, 0xd1, 0xd9, 0xb9, 0x03, 0x15, - 0xd7, 0x1b, 0x72, 0x45, 0xb1, 0x34, 0x30, 0x10, 0x20, 0x8d, 0x5c, 0xcf, 0x6c, 0xc7, 0xa5, 0x81, - 0xd3, 0x62, 0x96, 0x11, 0x82, 0xc3, 0x7e, 0x17, 0x1a, 0x13, 0xee, 0x0e, 0xf5, 0x23, 0x42, 0x42, - 0x55, 0x4d, 0x82, 0xe5, 0xe9, 0xb8, 0x03, 0x95, 0x93, 0x29, 0xe1, 0x09, 0xc6, 0x92, 0x47, 0x1a, - 0x00, 0x09, 0x6a, 0x13, 0x7f, 0x99, 0x4c, 0x83, 0x33, 0x2c, 0x2d, 0x60, 0x69, 0x51, 0x7c, 0x8b, - 0xa2, 0xdb, 0x00, 0xc3, 0x69, 0x10, 0xca, 0x13, 0xb3, 0x80, 0x85, 0x65, 0x01, 0xa1, 0x13, 0xf3, - 0x4d, 0x58, 0x1a, 0xdb, 0x97, 0x16, 0xd2, 0x8e, 0xe5, 0xb8, 0xd6, 0xc9, 0x08, 0xef, 0x9c, 0x22, - 0xe2, 0x35, 0xc7, 0xf6, 0xe5, 0x27, 0xa2, 0xa4, 0xeb, 0x6e, 0x23, 0x5c, 0xb0, 0x15, 0x25, 0xee, - 0xf8, 0x3c, 0xe0, 0xfe, 0x39, 0x47, 0x4e, 0x90, 0x8f, 0x64, 0x1a, 0x93, 0xa0, 0x62, 0x44, 0x63, - 0x31, 0xef, 0x70, 0x34, 0xa0, 0x63, 0x6f, 0x16, 0xc7, 0x8e, 0xbb, 0x13, 0x8e, 0x06, 0xe2, 0x5e, - 0x11, 0x7c, 0x64, 0xc2, 0x7d, 0xeb, 0xc5, 0x05, 0x9e, 0xe1, 0x3c, 0xf2, 0x8d, 0x43, 0xee, 0x3f, - 0xbf, 0x10, 0x57, 0xff, 0x20, 0x40, 0x46, 0x64, 0x5f, 0xb5, 0x2a, 0x78, 0xc0, 0x4b, 0x83, 0x40, - 0xb0, 0x20, 0xfb, 0x4a, 0x1c, 0x42, 0x31, 0x5a, 0x1b, 0x77, 0x81, 0x0f, 0xb1, 0xf9, 0x00, 0x39, - 0x6a, 0x0d, 0x07, 0xdb, 0x96, 0x05, 0xa2, 0x9f, 0x40, 0x50, 0xbd, 0x1a, 0xec, 0xc9, 0xc8, 0x3e, - 0x0d, 0x90, 0xa5, 0xd4, 0xcc, 0xaa, 0x04, 0x6e, 0x0b, 0x98, 0xf1, 0x29, 0x09, 0x59, 0xda, 0xde, - 0xca, 0x33, 0x23, 0xae, 0x7a, 0x84, 0xe0, 0xbe, 0x96, 0x4c, 0xf9, 0x95, 0xb6, 0x69, 0xd9, 0x94, - 0x4d, 0x33, 0x7e, 0x2f, 0x03, 0x55, 0xd9, 0x32, 0x0a, 0x25, 0xec, 0x21, 0x30, 0xb5, 0x8b, 0xe1, - 0xa5, 0x33, 0xb4, 0x8e, 0xaf, 0x42, 0x1e, 0x10, 0xd1, 0xec, 0xdc, 0x30, 0x9b, 0xb2, 0xac, 0x7f, - 0xe9, 0x0c, 0x37, 0x44, 0x09, 0x7b, 0x00, 0xcd, 0x04, 0x7e, 0x10, 0xfa, 0x44, 0xd1, 0x3b, 0x37, - 0xcc, 0xba, 0x86, 0xdd, 0x0b, 0x7d, 0x71, 0x46, 0x84, 0xc8, 0x33, 0x0d, 0x2d, 0xc7, 0x1d, 0xf2, - 0x4b, 0x24, 0xa3, 0x9a, 0x59, 0x21, 0x58, 0x57, 0x80, 0x36, 0xea, 0x50, 0xd5, 0x9b, 0x33, 0x4e, - 0xa1, 0xa4, 0xe4, 0x25, 0x14, 0x18, 0x66, 0x86, 0x64, 0x96, 0xc3, 0x68, 0x24, 0x37, 0xa1, 0x94, - 0x1c, 0x81, 0x59, 0x0c, 0x5f, 0xbb, 0x63, 0xe3, 0x7b, 0xd0, 0xdc, 0x15, 0xc4, 0xe3, 0x0a, 0x62, - 0x95, 0xf2, 0xdf, 0x2a, 0x2c, 0x68, 0x87, 0xa6, 0x6c, 0xca, 0x2f, 0x71, 0xe7, 0x9e, 0x79, 0x41, - 0x28, 0x7b, 0xc1, 0xbf, 0x8d, 0x3f, 0xca, 0x00, 0xeb, 0x04, 0xa1, 0x33, 0xb6, 0x43, 0xbe, 0xcd, - 0x23, 0xb6, 0x70, 0x00, 0x55, 0xd1, 0x5a, 0xdf, 0x6b, 0x93, 0x40, 0x46, 0x02, 0xc5, 0x7b, 0xf2, - 0x18, 0xcf, 0x57, 0x78, 0xa8, 0x63, 0x13, 0x9b, 0x4f, 0x34, 0x20, 0x4e, 0x59, 0x68, 0xfb, 0xa7, - 0x3c, 0x44, 0x31, 0x4e, 0xca, 0xfb, 0x40, 0x20, 0x21, 0xc0, 0xad, 0xff, 0x2a, 0x2c, 0xce, 0xb5, - 0xa1, 0xf3, 0xe5, 0x72, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, 0x82, 0xa5, 0xc4, 0xb8, 0x24, 0xa5, - 0xad, 0x41, 0x51, 0x1c, 0x08, 0x21, 0x1c, 0x64, 0x48, 0xaa, 0x3c, 0xe1, 0x5c, 0x88, 0xc1, 0x8f, - 0x60, 0xf9, 0x84, 0x73, 0xdf, 0x0e, 0xb1, 0x10, 0x4f, 0x8c, 0xd8, 0x21, 0xd9, 0xf0, 0xa2, 0x2c, - 0xeb, 0xd9, 0xe1, 0x21, 0xf7, 0xc5, 0x4e, 0x19, 0xff, 0x3b, 0x03, 0x0d, 0xc1, 0x41, 0xf7, 0x6c, - 0xf7, 0x4a, 0xad, 0xd3, 0x6e, 0xea, 0x3a, 0xdd, 0xd7, 0x2e, 0x43, 0x0d, 0xfb, 0xcb, 0x2e, 0x52, - 0x6e, 0x76, 0x91, 0xd8, 0x5d, 0xa8, 0x26, 0xc6, 0x5a, 0xc0, 0xb1, 0x42, 0x10, 0x0d, 0xf2, 0x17, - 0x5f, 0xc6, 0x77, 0xa1, 0x19, 0x0f, 0x5b, 0xae, 0x21, 0x83, 0xbc, 0x20, 0x49, 0xd9, 0x00, 0xfe, - 0x6d, 0xfc, 0xab, 0x0c, 0x21, 0x6e, 0x7a, 0x4e, 0x24, 0x9d, 0x0a, 0x44, 0x21, 0xf7, 0x2a, 0x44, - 0xf1, 0xf7, 0xb5, 0x52, 0xfd, 0x2f, 0x3e, 0x59, 0x71, 0x74, 0x02, 0xee, 0x0e, 0x2d, 0x7b, 0x34, - 0x42, 0xe6, 0x5b, 0x32, 0x8b, 0xe2, 0xbb, 0x3d, 0x1a, 0x19, 0xf7, 0x60, 0x51, 0x1b, 0xdd, 0x4b, - 0xe6, 0xb1, 0x0f, 0x6c, 0xd7, 0x09, 0xc2, 0x23, 0x37, 0x98, 0x68, 0x82, 0xdb, 0x2d, 0x28, 0x0b, - 0x0e, 0x2b, 0x46, 0x46, 0x47, 0xb6, 0x60, 0x0a, 0x96, 0x2b, 0xc6, 0x15, 0x60, 0xa1, 0x7d, 0x29, - 0x0b, 0xb3, 0xb2, 0xd0, 0xbe, 0xc4, 0x42, 0xe3, 0xbb, 0xb0, 0x94, 0x68, 0x4f, 0x76, 0xfd, 0x16, - 0x14, 0xa6, 0xe1, 0xa5, 0xa7, 0x44, 0xf3, 0x8a, 0xa4, 0x10, 0xa1, 0x00, 0x9a, 0x54, 0x62, 0x7c, - 0x04, 0x8b, 0xfb, 0xfc, 0x42, 0x1e, 0x62, 0x35, 0x90, 0x77, 0x21, 0xff, 0x0a, 0xa5, 0x10, 0xcb, - 0x8d, 0x87, 0xc0, 0xf4, 0xca, 0xb2, 0x57, 0x4d, 0x47, 0xcc, 0x24, 0x74, 0x44, 0xe3, 0x5d, 0x60, - 0x3d, 0xe7, 0xd4, 0xdd, 0xe3, 0x41, 0x60, 0x9f, 0x46, 0xc7, 0xbe, 0x09, 0xb9, 0x71, 0x70, 0x2a, - 0x79, 0x94, 0xf8, 0xd3, 0xf8, 0x16, 0x2c, 0x25, 0xf0, 0x64, 0xc3, 0x6f, 0x40, 0x39, 0x70, 0x4e, - 0x5d, 0x14, 0xac, 0x64, 0xd3, 0x31, 0xc0, 0xd8, 0x86, 0xe5, 0x4f, 0xb8, 0xef, 0x9c, 0x5c, 0xbd, - 0xaa, 0xf9, 0x64, 0x3b, 0xd9, 0xd9, 0x76, 0x3a, 0xb0, 0x32, 0xd3, 0x8e, 0xec, 0x9e, 0xc8, 0x57, - 0xee, 0x64, 0xc9, 0xa4, 0x0f, 0x8d, 0xef, 0x65, 0x75, 0xbe, 0x67, 0x1c, 0x01, 0xdb, 0xf4, 0x5c, - 0x97, 0x0f, 0xc2, 0x43, 0xce, 0xfd, 0xd8, 0x4a, 0x15, 0xd3, 0x6a, 0xe5, 0xc9, 0x9a, 0x5c, 0xd9, - 0x59, 0x66, 0x2a, 0x89, 0x98, 0x41, 0x7e, 0xc2, 0xfd, 0x31, 0x36, 0x5c, 0x32, 0xf1, 0x6f, 0x63, - 0x05, 0x96, 0x12, 0xcd, 0x4a, 0xbd, 0xfe, 0x31, 0xac, 0x6c, 0x39, 0xc1, 0x60, 0xbe, 0xc3, 0x35, - 0x28, 0x4e, 0xa6, 0xc7, 0x56, 0x92, 0x2f, 0x3f, 0xe7, 0x57, 0x42, 0xdb, 0x9b, 0xad, 0x21, 0xdb, - 0xfa, 0xbb, 0x19, 0xc8, 0xef, 0xf4, 0x77, 0x37, 0xd9, 0x3a, 0x94, 0x1c, 0x77, 0xe0, 0x8d, 0x85, - 0xe0, 0x45, 0x73, 0x8e, 0xbe, 0xaf, 0x3d, 0x60, 0xb7, 0xa0, 0x8c, 0xf2, 0x9a, 0x50, 0x6d, 0xa5, - 0xe8, 0x53, 0x12, 0x80, 0x5d, 0x6f, 0xf0, 0x42, 0xe8, 0xd4, 0xfc, 0x72, 0xe2, 0xf8, 0xa8, 0x35, - 0x2b, 0x65, 0x38, 0x4f, 0x77, 0x7d, 0x5c, 0x40, 0x1a, 0xb1, 0xf1, 0x57, 0x45, 0x28, 0xca, 0xdb, - 0x96, 0x6e, 0xee, 0xd0, 0x39, 0xe7, 0xf1, 0xcd, 0x2d, 0xbe, 0x84, 0x3c, 0xe0, 0xf3, 0xb1, 0x17, - 0x46, 0x02, 0x1b, 0xed, 0x41, 0x95, 0x80, 0x52, 0x64, 0xd3, 0x84, 0x06, 0x32, 0x31, 0xe4, 0x08, - 0x69, 0xa0, 0x5f, 0xe5, 0xb7, 0xa0, 0xa8, 0xee, 0xfe, 0x7c, 0xa4, 0xd3, 0x2c, 0x0c, 0x48, 0x5a, - 0x5b, 0x87, 0xd2, 0xc0, 0x9e, 0xd8, 0x03, 0x27, 0xbc, 0x92, 0x0c, 0x21, 0xfa, 0x16, 0xad, 0x8f, - 0xbc, 0x81, 0x3d, 0xb2, 0x8e, 0xed, 0x91, 0xed, 0x0e, 0xb8, 0xd4, 0xdd, 0xab, 0x08, 0xdc, 0x20, - 0x98, 0xd0, 0xcf, 0xe5, 0x38, 0x15, 0x16, 0xa9, 0xf0, 0x72, 0xf4, 0x0a, 0x4d, 0x08, 0x97, 0xde, - 0x78, 0xec, 0x08, 0x2d, 0x83, 0xc4, 0xb0, 0x9c, 0x59, 0x26, 0xc8, 0x36, 0xc7, 0xd9, 0xca, 0xe2, - 0x0b, 0x5a, 0xba, 0x32, 0x75, 0x45, 0xc0, 0x4f, 0xc9, 0x90, 0x30, 0x2f, 0x8b, 0xe5, 0x34, 0x59, - 0xec, 0x3d, 0x58, 0x9c, 0xba, 0x01, 0x0f, 0xc3, 0x11, 0x1f, 0x46, 0x63, 0xa9, 0x20, 0x52, 0x33, - 0x2a, 0x50, 0xc3, 0x79, 0x08, 0x4b, 0x64, 0x74, 0x08, 0xec, 0xd0, 0x0b, 0xce, 0x9c, 0xc0, 0x0a, - 0x84, 0x86, 0x44, 0xea, 0xee, 0x22, 0x16, 0xf5, 0x64, 0x49, 0x8f, 0x54, 0xa4, 0xb5, 0x19, 0x7c, - 0x9f, 0x0f, 0xb8, 0x73, 0xce, 0x87, 0x28, 0xa7, 0xe5, 0xcc, 0x95, 0x44, 0x1d, 0x53, 0x16, 0xa2, - 0xd0, 0x3d, 0x1d, 0x5b, 0xd3, 0xc9, 0xd0, 0x16, 0xc2, 0x4a, 0x9d, 0x84, 0x61, 0x77, 0x3a, 0x3e, - 0x22, 0x08, 0x7b, 0x0c, 0x4a, 0x12, 0x93, 0xf2, 0x61, 0x23, 0xc1, 0xcf, 0x04, 0xb1, 0x9a, 0x55, - 0x89, 0x41, 0x82, 0x62, 0x42, 0xe6, 0x6c, 0xce, 0xc8, 0x9c, 0x2d, 0x28, 0x4e, 0x7c, 0xe7, 0xdc, - 0x0e, 0x79, 0x6b, 0x91, 0x18, 0xb8, 0xfc, 0x14, 0x9c, 0xc1, 0x71, 0x9d, 0xd0, 0xb1, 0x43, 0xcf, - 0x6f, 0x31, 0x2c, 0x8b, 0x01, 0xec, 0x01, 0x2c, 0x22, 0x8d, 0x04, 0xa1, 0x1d, 0x4e, 0x03, 0x29, - 0x81, 0x2e, 0x21, 0x31, 0xa1, 0x0c, 0xdd, 0x43, 0x38, 0x0a, 0xa1, 0xec, 0x5b, 0xb0, 0x4a, 0x64, - 0x81, 0x35, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x32, 0x2e, 0xc5, 0x12, 0x96, 0x0a, 0xfa, 0x96, 0xf2, - 0xb5, 0x90, 0x0e, 0x9e, 0xc2, 0x9a, 0x24, 0x93, 0xb9, 0x5a, 0x2b, 0x58, 0x6b, 0x99, 0x8a, 0x67, - 0xaa, 0x3d, 0x84, 0x45, 0x31, 0x24, 0x67, 0x60, 0xc9, 0xda, 0xe2, 0x24, 0xac, 0x8a, 0xd1, 0xa3, - 0xa6, 0xd4, 0xa0, 0x42, 0x13, 0xcb, 0x9e, 0xf3, 0x2b, 0xf6, 0x3d, 0x68, 0x10, 0xc9, 0xa0, 0x7a, - 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, 0xa5, 0xc8, 0xec, 0xeb, 0x83, 0xc4, - 0xb7, 0x38, 0x0e, 0x23, 0xe7, 0x84, 0x87, 0xce, 0x98, 0xb7, 0xd6, 0x88, 0xc0, 0xd4, 0xb7, 0x38, - 0xa9, 0xd3, 0x09, 0x96, 0xb4, 0x88, 0x2f, 0xd0, 0x17, 0xd2, 0xee, 0xc8, 0x0b, 0xb8, 0x32, 0x51, - 0xb5, 0x6e, 0xca, 0x43, 0x28, 0x80, 0x92, 0xed, 0x19, 0x3f, 0xcd, 0xd0, 0x3d, 0x26, 0x8f, 0x7d, - 0xa0, 0x69, 0x65, 0x74, 0xe0, 0x2d, 0xcf, 0x1d, 0x5d, 0x49, 0x1e, 0x00, 0x04, 0x3a, 0x70, 0x47, - 0x78, 0x08, 0x1d, 0x57, 0x47, 0x21, 0x96, 0x59, 0x55, 0x40, 0x44, 0xba, 0x03, 0x95, 0xc9, 0xf4, - 0x78, 0xe4, 0x0c, 0x08, 0x25, 0x47, 0xad, 0x10, 0x08, 0x11, 0x84, 0x5a, 0x4a, 0x84, 0x40, 0x18, - 0x79, 0xc4, 0xa8, 0x48, 0x18, 0xa2, 0x20, 0x4b, 0xe6, 0x3e, 0x72, 0x81, 0xaa, 0x89, 0x7f, 0x1b, - 0x1b, 0xb0, 0x9c, 0x1c, 0xb4, 0xbc, 0x2f, 0x1e, 0x40, 0x49, 0xb2, 0x18, 0x65, 0xaf, 0xa8, 0x6b, - 0x16, 0x64, 0xa1, 0x59, 0x45, 0xe5, 0xc6, 0x6f, 0x2d, 0xc0, 0x92, 0x84, 0x6e, 0x8a, 0x15, 0xe9, - 0x4d, 0xc7, 0x63, 0xdb, 0x4f, 0xe1, 0x5d, 0x99, 0x97, 0xf3, 0xae, 0xec, 0x1c, 0xef, 0x4a, 0x2a, - 0xac, 0xc4, 0xfa, 0x92, 0x0a, 0xab, 0xd8, 0x02, 0xd2, 0x21, 0x74, 0xf3, 0x65, 0x4d, 0x82, 0xfb, - 0x64, 0x26, 0x9d, 0xe3, 0xb4, 0x85, 0x14, 0x4e, 0xab, 0xf3, 0xc9, 0x85, 0x19, 0x3e, 0xf9, 0x16, - 0xd0, 0x5e, 0x2b, 0xb6, 0x5f, 0x24, 0xb5, 0x02, 0x61, 0xd2, 0x06, 0x7a, 0x0f, 0x1a, 0xb3, 0xac, - 0x89, 0x78, 0x60, 0x3d, 0x85, 0x31, 0x39, 0x63, 0x8e, 0x97, 0x8c, 0x86, 0x5c, 0x96, 0x8c, 0xc9, - 0x19, 0xf3, 0x5d, 0x2c, 0x51, 0xf8, 0x1d, 0x00, 0xea, 0x1b, 0x69, 0x1d, 0x90, 0xd6, 0xdf, 0x4d, - 0xee, 0x85, 0xbe, 0xea, 0x0f, 0xc5, 0xc7, 0xd4, 0xe7, 0x48, 0xfc, 0x65, 0xac, 0x89, 0x74, 0xff, - 0x1c, 0xea, 0xde, 0x84, 0xbb, 0x56, 0xcc, 0x22, 0x2a, 0xd8, 0xd4, 0x3b, 0x2f, 0x69, 0xaa, 0xab, - 0x70, 0xcd, 0x9a, 0xa8, 0x1b, 0x7d, 0xb2, 0x3d, 0x5a, 0x78, 0xae, 0xb5, 0x56, 0xfd, 0x12, 0xad, - 0xd5, 0xb1, 0x72, 0xf4, 0x6d, 0xfc, 0x83, 0x0c, 0x54, 0xb4, 0x61, 0xb3, 0x15, 0x58, 0xdc, 0x3c, - 0x38, 0x38, 0xec, 0x98, 0xed, 0x7e, 0xf7, 0x93, 0x8e, 0xb5, 0xb9, 0x7b, 0xd0, 0xeb, 0x34, 0x6f, - 0x08, 0xf0, 0xee, 0xc1, 0x66, 0x7b, 0xd7, 0xda, 0x3e, 0x30, 0x37, 0x15, 0x38, 0xc3, 0x56, 0x81, - 0x99, 0x9d, 0xbd, 0x83, 0x7e, 0x27, 0x01, 0xcf, 0xb2, 0x26, 0x54, 0x37, 0xcc, 0x4e, 0x7b, 0x73, - 0x47, 0x42, 0x72, 0x6c, 0x19, 0x9a, 0xdb, 0x47, 0xfb, 0x5b, 0xdd, 0xfd, 0x67, 0xd6, 0x66, 0x7b, - 0x7f, 0xb3, 0xb3, 0xdb, 0xd9, 0x6a, 0xe6, 0x59, 0x0d, 0xca, 0xed, 0x8d, 0xf6, 0xfe, 0xd6, 0xc1, - 0x7e, 0x67, 0xab, 0x59, 0x30, 0x7e, 0x05, 0xca, 0xf1, 0x44, 0x2b, 0x50, 0x3c, 0xda, 0x7f, 0xbe, - 0x7f, 0xf0, 0xe9, 0x7e, 0xf3, 0x06, 0x2b, 0x43, 0x01, 0xfb, 0x6f, 0x66, 0x18, 0xc0, 0x02, 0xf5, - 0xd9, 0xcc, 0xb2, 0x12, 0xe4, 0x37, 0x0e, 0xfa, 0x3b, 0xcd, 0x9c, 0xf1, 0xe7, 0x19, 0x58, 0xc1, - 0x29, 0x0f, 0x67, 0x99, 0xc0, 0x5d, 0xa8, 0x0c, 0x3c, 0x6f, 0x22, 0x14, 0xa4, 0x58, 0x10, 0xd0, - 0x41, 0xe2, 0x80, 0x13, 0xcf, 0x3d, 0xf1, 0xfc, 0x01, 0x97, 0x3c, 0x00, 0x10, 0xb4, 0x2d, 0x20, - 0x82, 0x06, 0x25, 0x11, 0x13, 0x06, 0xb1, 0x80, 0x0a, 0xc1, 0x08, 0x65, 0x15, 0x16, 0x8e, 0x7d, - 0x6e, 0x0f, 0xce, 0xe4, 0xe9, 0x97, 0x5f, 0xec, 0xeb, 0xb1, 0xea, 0x3e, 0x10, 0x34, 0x35, 0xe2, - 0x43, 0x3c, 0x02, 0x25, 0xb3, 0x21, 0xe1, 0x9b, 0x12, 0x2c, 0x2e, 0x11, 0xfb, 0xd8, 0x76, 0x87, - 0x9e, 0xcb, 0x87, 0x52, 0x43, 0x88, 0x01, 0xc6, 0x21, 0xac, 0xce, 0xce, 0x4f, 0xf2, 0x8b, 0x0f, - 0x34, 0x7e, 0x41, 0x02, 0xfb, 0xfa, 0xf5, 0xa4, 0xa0, 0xf1, 0x8e, 0x7f, 0x9c, 0x87, 0xbc, 0x10, - 0xe0, 0xae, 0x95, 0xf5, 0x74, 0x89, 0x3c, 0x37, 0xe7, 0xb5, 0x41, 0x0b, 0x01, 0xdd, 0xec, 0x64, - 0x86, 0x2a, 0x23, 0x04, 0x6f, 0xf4, 0xa8, 0xd8, 0xe7, 0x83, 0x73, 0x69, 0x87, 0xa2, 0x62, 0x93, - 0x0f, 0xce, 0x51, 0x15, 0xb2, 0x43, 0xaa, 0x4b, 0xe7, 0xbd, 0x18, 0xd8, 0x21, 0xd6, 0x94, 0x45, - 0x58, 0xaf, 0x18, 0x15, 0x61, 0xad, 0x16, 0x14, 0x1d, 0xf7, 0xd8, 0x9b, 0xba, 0x43, 0x3c, 0xde, - 0x25, 0x53, 0x7d, 0xa2, 0x93, 0x08, 0x39, 0x91, 0xb8, 0x3f, 0xe8, 0x34, 0x97, 0x04, 0xa0, 0x2f, - 0x6e, 0x90, 0xf7, 0xa1, 0x1c, 0x5c, 0xb9, 0x03, 0xfd, 0x0c, 0x2f, 0xcb, 0xf5, 0x11, 0xb3, 0x7f, - 0xd8, 0xbb, 0x72, 0x07, 0x78, 0x62, 0x4b, 0x81, 0xfc, 0x8b, 0x3d, 0x85, 0x52, 0x64, 0xae, 0x25, - 0x0e, 0x7c, 0x53, 0xaf, 0xa1, 0x6c, 0xb4, 0xa4, 0x15, 0x47, 0xa8, 0xec, 0x11, 0x2c, 0xa0, 0x4d, - 0x35, 0x68, 0x55, 0xb1, 0x92, 0x12, 0xd3, 0xc5, 0x30, 0xd0, 0x3f, 0xc3, 0x87, 0x68, 0x5f, 0x35, - 0x25, 0xda, 0xfa, 0x73, 0xa8, 0x25, 0xda, 0xd2, 0x75, 0xdf, 0x1a, 0xe9, 0xbe, 0xef, 0xe8, 0xba, - 0x6f, 0x7c, 0x13, 0xc8, 0x6a, 0xba, 0x2e, 0xfc, 0xab, 0x50, 0x52, 0x53, 0x11, 0xe7, 0x4f, 0x9e, - 0x1d, 0xab, 0xf7, 0xd9, 0xfe, 0x66, 0xf3, 0x06, 0x6b, 0x40, 0xa5, 0xbd, 0x89, 0x47, 0x1a, 0x01, - 0x19, 0x81, 0x72, 0xd8, 0xee, 0xf5, 0x22, 0x48, 0xd6, 0xd8, 0x86, 0xe6, 0xec, 0x48, 0x05, 0x4d, - 0x86, 0x0a, 0x26, 0x2d, 0xce, 0x31, 0x40, 0x68, 0x36, 0x64, 0x44, 0x26, 0xf1, 0x99, 0x3e, 0x8c, - 0xa7, 0xd0, 0x14, 0xf7, 0x9a, 0x58, 0xaa, 0x40, 0xb3, 0xdc, 0x8e, 0x84, 0x48, 0xa6, 0x5b, 0x9d, - 0x4b, 0x66, 0x85, 0x60, 0xd8, 0x95, 0xf1, 0x01, 0x2c, 0x6a, 0xd5, 0x62, 0x4d, 0x54, 0xdc, 0x95, - 0xb3, 0x9a, 0x28, 0xea, 0x1d, 0x54, 0x62, 0xac, 0xc1, 0x8a, 0xf8, 0xec, 0x9c, 0x73, 0x37, 0xec, - 0x4d, 0x8f, 0xc9, 0x55, 0xe8, 0x78, 0xae, 0xd0, 0x47, 0xca, 0x51, 0xc9, 0xf5, 0x44, 0xfe, 0x50, - 0x2a, 0xad, 0x59, 0x24, 0x8d, 0x75, 0xad, 0x07, 0xac, 0xf8, 0x10, 0xff, 0x4d, 0x28, 0xaf, 0xe5, - 0x08, 0x24, 0x96, 0xf5, 0xb0, 0xd3, 0x31, 0xad, 0x83, 0xfd, 0xdd, 0xee, 0xbe, 0x60, 0x94, 0x62, - 0x59, 0x11, 0xb0, 0xbd, 0x8d, 0x90, 0x8c, 0xd1, 0x84, 0xfa, 0x33, 0x1e, 0x76, 0xdd, 0x13, 0x4f, - 0xb9, 0xc5, 0x7e, 0x56, 0x80, 0x46, 0x04, 0x8a, 0x95, 0xdf, 0x73, 0xee, 0x07, 0x8e, 0xe7, 0xa2, - 0x1c, 0x5b, 0x36, 0xd5, 0xa7, 0xb8, 0xdd, 0x9c, 0x21, 0x77, 0x43, 0x27, 0xbc, 0xb2, 0x12, 0x96, - 0xb2, 0xba, 0x02, 0xcb, 0x5b, 0x74, 0x19, 0x0a, 0xf6, 0xc8, 0xb1, 0x95, 0x87, 0x95, 0x3e, 0x04, - 0x74, 0xe0, 0x8d, 0x3c, 0x1f, 0x45, 0xd6, 0xb2, 0x49, 0x1f, 0xec, 0x31, 0x2c, 0x0b, 0xd1, 0x59, - 0x37, 0x5f, 0x22, 0xff, 0x20, 0xa3, 0x1d, 0x73, 0xa7, 0xe3, 0xc3, 0xd8, 0x84, 0x29, 0x4a, 0xc4, - 0xdd, 0x29, 0x6a, 0x48, 0x61, 0x29, 0xaa, 0x40, 0x5a, 0xd8, 0xa2, 0x3b, 0x1d, 0xb7, 0xb1, 0x24, - 0xc2, 0x7f, 0x02, 0x2b, 0x02, 0x3f, 0x12, 0xaf, 0xa2, 0x1a, 0x0d, 0xac, 0x21, 0x1a, 0xeb, 0xca, - 0xb2, 0xa8, 0xce, 0x2d, 0x28, 0xd3, 0xa8, 0xc4, 0x8e, 0x17, 0x48, 0xfa, 0xc6, 0xa1, 0x70, 0x3f, - 0x98, 0x73, 0x86, 0x2e, 0x90, 0x20, 0x30, 0xe3, 0x0c, 0xd5, 0xdc, 0xa9, 0xa5, 0x59, 0x77, 0xea, - 0x13, 0x58, 0x39, 0x16, 0x24, 0x78, 0xc6, 0xed, 0x21, 0xf7, 0xad, 0x98, 0xb0, 0x49, 0xcb, 0x58, - 0x12, 0x85, 0x3b, 0x58, 0x16, 0x9d, 0x03, 0x21, 0xe7, 0x08, 0xb6, 0xc0, 0x87, 0x56, 0xe8, 0x59, - 0x28, 0xfe, 0x20, 0x83, 0x29, 0x99, 0x35, 0x02, 0xf7, 0xbd, 0x4d, 0x01, 0x4c, 0xe2, 0x9d, 0xfa, - 0xf6, 0xe4, 0x4c, 0xea, 0x01, 0x11, 0xde, 0x33, 0x01, 0x64, 0x6f, 0x40, 0x51, 0x90, 0xbc, 0xcb, - 0xc9, 0x67, 0x45, 0x92, 0xb6, 0x02, 0xb1, 0x77, 0x60, 0x01, 0xfb, 0x08, 0x5a, 0x4d, 0xa4, 0xf7, - 0x6a, 0xcc, 0xc8, 0x1d, 0xd7, 0x94, 0x65, 0x42, 0x98, 0x9c, 0xfa, 0x0e, 0x71, 0x99, 0xb2, 0x89, - 0x7f, 0xb3, 0xef, 0x6b, 0x2c, 0x6b, 0x09, 0xeb, 0x2a, 0x79, 0x60, 0x86, 0xd2, 0xae, 0xe3, 0x5e, - 0x5f, 0x29, 0x33, 0xfa, 0x41, 0xbe, 0x54, 0x69, 0x56, 0x8d, 0xef, 0x40, 0x81, 0x56, 0x47, 0x10, - 0x21, 0xae, 0x5d, 0x46, 0x12, 0x21, 0x42, 0x5b, 0x50, 0x74, 0x79, 0x78, 0xe1, 0xf9, 0x2f, 0x94, - 0x2d, 0x59, 0x7e, 0x1a, 0x3f, 0x46, 0x23, 0x48, 0xe4, 0x28, 0x27, 0x7d, 0x4e, 0x90, 0x07, 0x6d, - 0x6f, 0x70, 0x66, 0x4b, 0xbb, 0x4c, 0x09, 0x01, 0xbd, 0x33, 0x7b, 0x8e, 0x3c, 0xb2, 0xf3, 0xbe, - 0xf2, 0x77, 0xa0, 0xae, 0x5c, 0xf3, 0x81, 0x35, 0xe2, 0x27, 0xa1, 0x24, 0xf7, 0xaa, 0xf4, 0xcb, - 0x07, 0xbb, 0xfc, 0x24, 0x34, 0xf6, 0x60, 0x51, 0x12, 0xe4, 0xc1, 0x84, 0xab, 0xae, 0xbf, 0x9b, - 0x26, 0x4f, 0x57, 0x9e, 0x2c, 0x25, 0x2f, 0x5a, 0x7a, 0x72, 0x90, 0x10, 0xb2, 0x8d, 0x8f, 0x81, + // 11277 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x8f, 0x24, 0xd7, + 0x79, 0xd8, 0xf6, 0x6d, 0xba, 0xfb, 0xeb, 0xeb, 0x9c, 0xb9, 0xf5, 0xce, 0x72, 0xb9, 0xcb, 0x22, + 0x45, 0xae, 0x96, 0xd2, 0xec, 0x72, 0x25, 0x52, 0x32, 0x19, 0xcb, 0xea, 0x99, 0xe9, 0xd9, 0x69, + 0xed, 0xdc, 0x58, 0xdd, 0x43, 0x9a, 0x72, 0x9c, 0x52, 0x4d, 0xf7, 0x99, 0x99, 0xf2, 0x76, 0x57, + 0x35, 0xab, 0xaa, 0xe7, 0x22, 0x81, 0x79, 0xc8, 0xc5, 0x08, 0x82, 0x24, 0x80, 0x91, 0x28, 0x40, + 0x9c, 0x18, 0x09, 0x12, 0x04, 0x41, 0x10, 0xc0, 0x70, 0x20, 0x07, 0xc8, 0x43, 0xde, 0xfd, 0x92, + 0xc0, 0x0f, 0x76, 0x5e, 0x02, 0xc3, 0x80, 0x91, 0xc4, 0x79, 0x0b, 0xfc, 0x13, 0x82, 0xf3, 0x7d, + 0xe7, 0x54, 0x9d, 0xea, 0xae, 0xd9, 0x5d, 0x4a, 0x8c, 0x5e, 0x76, 0xa7, 0xbe, 0xf3, 0x9d, 0xfb, + 0x77, 0xbe, 0xf3, 0x5d, 0x4f, 0x43, 0xd9, 0x9f, 0x0c, 0x36, 0x26, 0xbe, 0x17, 0x7a, 0xac, 0x30, + 0x72, 0xfd, 0xc9, 0x60, 0xfd, 0xb5, 0x33, 0xcf, 0x3b, 0x1b, 0xf1, 0x47, 0xf6, 0xc4, 0x79, 0x64, + 0xbb, 0xae, 0x17, 0xda, 0xa1, 0xe3, 0xb9, 0x01, 0x21, 0x19, 0x3f, 0x82, 0xfa, 0x53, 0xee, 0xf6, + 0x38, 0x1f, 0x9a, 0xfc, 0xf3, 0x29, 0x0f, 0x42, 0xf6, 0x2e, 0x2c, 0xda, 0xfc, 0xc7, 0x9c, 0x0f, + 0xad, 0x89, 0x1d, 0x04, 0x93, 0x73, 0xdf, 0x0e, 0x78, 0x2b, 0x73, 0x3f, 0xf3, 0xa0, 0x6a, 0x36, + 0xa9, 0xe0, 0x28, 0x82, 0xb3, 0x37, 0xa0, 0x1a, 0x08, 0x54, 0xee, 0x86, 0xbe, 0x37, 0xb9, 0x6e, + 0x65, 0x11, 0xaf, 0x22, 0x60, 0x1d, 0x02, 0x19, 0x23, 0x68, 0x44, 0x3d, 0x04, 0x13, 0xcf, 0x0d, + 0x38, 0x7b, 0x0c, 0xcb, 0x03, 0x67, 0x72, 0xce, 0x7d, 0x0b, 0x2b, 0x8f, 0x5d, 0x3e, 0xf6, 0x5c, + 0x67, 0xd0, 0xca, 0xdc, 0xcf, 0x3d, 0x28, 0x9b, 0x8c, 0xca, 0x44, 0x8d, 0x7d, 0x59, 0xc2, 0xde, + 0x81, 0x06, 0x77, 0x09, 0xce, 0x87, 0x58, 0x4b, 0x76, 0x55, 0x8f, 0xc1, 0xa2, 0x82, 0xf1, 0xf7, + 0xb2, 0xb0, 0xd8, 0x75, 0x9d, 0xf0, 0x53, 0x7b, 0x34, 0xe2, 0xa1, 0x9a, 0xd3, 0x3b, 0xd0, 0xb8, + 0x44, 0x00, 0xce, 0xe9, 0xd2, 0xf3, 0x87, 0x72, 0x46, 0x75, 0x02, 0x1f, 0x49, 0xe8, 0x8d, 0x23, + 0xcb, 0xde, 0x38, 0xb2, 0xd4, 0xe5, 0xca, 0xdd, 0xb0, 0x5c, 0xef, 0x40, 0xc3, 0xe7, 0x03, 0xef, + 0x82, 0xfb, 0xd7, 0xd6, 0xa5, 0xe3, 0x0e, 0xbd, 0xcb, 0x56, 0xfe, 0x7e, 0xe6, 0x41, 0xc1, 0xac, + 0x2b, 0xf0, 0xa7, 0x08, 0x65, 0x9b, 0xd0, 0x18, 0x9c, 0xdb, 0xae, 0xcb, 0x47, 0xd6, 0x89, 0x3d, + 0x78, 0x3e, 0x9d, 0x04, 0xad, 0xc2, 0xfd, 0xcc, 0x83, 0xca, 0x93, 0xdb, 0x1b, 0xb8, 0xab, 0x1b, + 0x5b, 0xe7, 0xb6, 0xbb, 0x89, 0x25, 0x3d, 0xd7, 0x9e, 0x04, 0xe7, 0x5e, 0x68, 0xd6, 0x65, 0x0d, + 0x02, 0x07, 0xc6, 0x32, 0x30, 0x7d, 0x25, 0x68, 0xed, 0x8d, 0xff, 0x90, 0x81, 0xa5, 0x63, 0x77, + 0xe4, 0x0d, 0x9e, 0xff, 0x9c, 0x4b, 0x94, 0x32, 0x87, 0xec, 0xab, 0xce, 0x21, 0xf7, 0x65, 0xe7, + 0xb0, 0x0a, 0xcb, 0xc9, 0xc1, 0xca, 0x59, 0x70, 0x58, 0x11, 0xb5, 0xcf, 0xb8, 0x1a, 0x96, 0x9a, + 0xc6, 0xd7, 0xa1, 0x39, 0x98, 0xfa, 0x3e, 0x77, 0xe7, 0xe6, 0xd1, 0x90, 0xf0, 0x68, 0x22, 0x6f, + 0x40, 0xd5, 0xe5, 0x97, 0x31, 0x9a, 0xa4, 0x5d, 0x97, 0x5f, 0x2a, 0x14, 0xa3, 0x05, 0xab, 0xb3, + 0xdd, 0xc8, 0x01, 0xfc, 0x65, 0x06, 0xf2, 0xc7, 0xe1, 0x95, 0xc7, 0xde, 0x87, 0xaa, 0x3d, 0x1c, + 0xfa, 0x3c, 0x08, 0xac, 0xf0, 0x7a, 0x42, 0x27, 0xa5, 0xfe, 0x84, 0xc9, 0x29, 0xb6, 0xa9, 0xa8, + 0x7f, 0x3d, 0xe1, 0x66, 0xc5, 0x8e, 0x3f, 0x58, 0x0b, 0x8a, 0xf2, 0x13, 0xfb, 0x2d, 0x9b, 0xea, + 0x93, 0xdd, 0x05, 0xb0, 0xc7, 0xde, 0xd4, 0x0d, 0xad, 0xc0, 0x0e, 0x71, 0xc5, 0x72, 0x66, 0x99, + 0x20, 0x3d, 0x3b, 0x64, 0x77, 0xa0, 0x3c, 0x79, 0x6e, 0x05, 0x03, 0xdf, 0x99, 0x84, 0x48, 0x3c, + 0x65, 0xb3, 0x34, 0x79, 0xde, 0xc3, 0x6f, 0xf6, 0x2e, 0x94, 0xbc, 0x69, 0x38, 0xf1, 0x1c, 0x37, + 0x94, 0xf4, 0xd2, 0x90, 0x03, 0x39, 0x9c, 0x86, 0x47, 0x02, 0x6c, 0x46, 0x08, 0xec, 0x2d, 0xa8, + 0x0d, 0x3c, 0xf7, 0xd4, 0xf1, 0xc7, 0xc4, 0x11, 0x5a, 0x0b, 0xd8, 0x57, 0x12, 0x68, 0xfc, 0x41, + 0x16, 0x2a, 0x7d, 0xdf, 0x76, 0x03, 0x7b, 0x20, 0x00, 0x6c, 0x0d, 0x8a, 0xe1, 0x95, 0x75, 0x6e, + 0x07, 0xe7, 0x38, 0xd5, 0xb2, 0xb9, 0x10, 0x5e, 0xed, 0xda, 0xc1, 0x39, 0x5b, 0x85, 0x05, 0x1a, + 0x25, 0x4e, 0x28, 0x67, 0xca, 0x2f, 0x71, 0x40, 0xdc, 0xe9, 0xd8, 0x4a, 0x76, 0x95, 0x43, 0x8a, + 0x69, 0xba, 0xd3, 0xf1, 0x96, 0x0e, 0x17, 0x93, 0x3f, 0x11, 0xdb, 0x4d, 0x1d, 0xd0, 0xf4, 0xca, + 0x08, 0xc1, 0x3e, 0xde, 0x80, 0xaa, 0x2c, 0xe6, 0xce, 0xd9, 0x39, 0xcd, 0xb1, 0x60, 0x56, 0x08, + 0x01, 0x41, 0xa2, 0x85, 0xd0, 0x19, 0x73, 0x2b, 0x08, 0xed, 0xf1, 0x44, 0x4e, 0xa9, 0x2c, 0x20, + 0x3d, 0x01, 0xc0, 0x62, 0x2f, 0xb4, 0x47, 0xd6, 0x29, 0xe7, 0x41, 0xab, 0x28, 0x8b, 0x05, 0x64, + 0x87, 0xf3, 0x80, 0x7d, 0x0d, 0xea, 0x43, 0x1e, 0x84, 0x96, 0xdc, 0x0c, 0x1e, 0xb4, 0x4a, 0x78, + 0xf2, 0x6b, 0x02, 0xda, 0x56, 0x40, 0xf6, 0x1a, 0x80, 0x6f, 0x5f, 0x5a, 0x62, 0x21, 0xf8, 0x55, + 0xab, 0x4c, 0xbb, 0xe0, 0xdb, 0x97, 0xfd, 0xab, 0x5d, 0x7e, 0x25, 0xa8, 0xe6, 0x29, 0x0f, 0xb5, + 0x45, 0x0b, 0x24, 0x75, 0x1a, 0x7b, 0xc0, 0x34, 0xf0, 0x36, 0x0f, 0x6d, 0x67, 0x14, 0xb0, 0x0f, + 0xa0, 0x1a, 0x6a, 0xc8, 0xc8, 0x06, 0x2b, 0x11, 0x09, 0x69, 0x15, 0xcc, 0x04, 0x9e, 0x71, 0x0e, + 0xa5, 0x1d, 0xce, 0xf7, 0x9c, 0xb1, 0x13, 0xb2, 0x55, 0x28, 0x9c, 0x3a, 0x57, 0x9c, 0x88, 0x3d, + 0xb7, 0x7b, 0xcb, 0xa4, 0x4f, 0x76, 0x0f, 0x00, 0xff, 0xb0, 0xc6, 0x11, 0x35, 0xed, 0xde, 0x32, + 0xcb, 0x08, 0xdb, 0x0f, 0xec, 0x90, 0xad, 0x43, 0x71, 0xc2, 0xfd, 0x01, 0x57, 0xfb, 0xb6, 0x7b, + 0xcb, 0x54, 0x80, 0xcd, 0x22, 0x14, 0x46, 0xa2, 0x75, 0xe3, 0x8f, 0x0a, 0x50, 0xe9, 0x71, 0x37, + 0x3a, 0x65, 0x0c, 0xf2, 0x62, 0x41, 0xe4, 0xc9, 0xc2, 0xbf, 0xd9, 0x9b, 0x50, 0xc1, 0xa5, 0x0b, + 0x42, 0xdf, 0x71, 0xcf, 0x88, 0xaa, 0x37, 0xb3, 0xad, 0x8c, 0x09, 0x02, 0xdc, 0x43, 0x28, 0x6b, + 0x42, 0xce, 0x1e, 0x2b, 0xaa, 0x16, 0x7f, 0xb2, 0xdb, 0x50, 0xb2, 0xc7, 0x21, 0x0d, 0xaf, 0x8a, + 0xe0, 0xa2, 0x3d, 0x0e, 0x71, 0x68, 0x6f, 0x40, 0x75, 0x62, 0x5f, 0x8f, 0xc5, 0x59, 0x8e, 0xc8, + 0xa1, 0x6a, 0x56, 0x24, 0x0c, 0x09, 0xe2, 0x09, 0x2c, 0xe9, 0x28, 0xaa, 0xf3, 0x42, 0xd4, 0xf9, + 0xa2, 0x86, 0x2d, 0xc7, 0xf0, 0x0e, 0x34, 0x54, 0x1d, 0x9f, 0xe6, 0x83, 0x64, 0x52, 0x36, 0xeb, + 0x12, 0xac, 0x66, 0xf9, 0x00, 0x9a, 0xa7, 0x8e, 0x6b, 0x8f, 0xac, 0xc1, 0x28, 0xbc, 0xb0, 0x86, + 0x7c, 0x14, 0xda, 0x48, 0x31, 0x05, 0xb3, 0x8e, 0xf0, 0xad, 0x51, 0x78, 0xb1, 0x2d, 0xa0, 0xec, + 0x1b, 0x50, 0x3e, 0xe5, 0xdc, 0xc2, 0xc5, 0x6a, 0x95, 0x12, 0x07, 0x4f, 0xed, 0x90, 0x59, 0x3a, + 0x55, 0x7b, 0xf5, 0x0d, 0x68, 0x7a, 0xd3, 0xf0, 0xcc, 0x73, 0xdc, 0x33, 0x4b, 0xf0, 0x3b, 0xcb, + 0x19, 0x22, 0x0d, 0xe5, 0x37, 0xb3, 0x8f, 0x33, 0x66, 0x5d, 0x95, 0x09, 0xce, 0xd3, 0x1d, 0xb2, + 0xb7, 0xa1, 0x31, 0xb2, 0x83, 0xd0, 0x3a, 0xf7, 0x26, 0xd6, 0x64, 0x7a, 0xf2, 0x9c, 0x5f, 0xb7, + 0x6a, 0xb8, 0x10, 0x35, 0x01, 0xde, 0xf5, 0x26, 0x47, 0x08, 0x14, 0x94, 0x8d, 0xe3, 0xa4, 0x41, + 0xc0, 0xfd, 0xcc, 0x83, 0x9a, 0x59, 0x16, 0x10, 0xea, 0xf4, 0x33, 0x58, 0xc2, 0xed, 0x19, 0x4c, + 0x83, 0xd0, 0x1b, 0x5b, 0x82, 0x57, 0xfb, 0xc3, 0xa0, 0x55, 0x41, 0x5a, 0xfb, 0xba, 0x1c, 0xac, + 0xb6, 0xc7, 0x1b, 0xdb, 0x3c, 0x08, 0xb7, 0x10, 0xd9, 0x24, 0x5c, 0x71, 0xa1, 0x5f, 0x9b, 0x8b, + 0xc3, 0x59, 0x38, 0xfb, 0x06, 0x30, 0x7b, 0x34, 0xf2, 0x2e, 0xad, 0x80, 0x8f, 0x4e, 0x2d, 0xb9, + 0x88, 0xad, 0xfa, 0xfd, 0xcc, 0x83, 0x92, 0xd9, 0xc4, 0x92, 0x1e, 0x1f, 0x9d, 0x1e, 0x11, 0x9c, + 0x7d, 0x00, 0x78, 0x98, 0xac, 0x53, 0x6e, 0x87, 0x53, 0x9f, 0x07, 0xad, 0xc6, 0xfd, 0xdc, 0x83, + 0xfa, 0x93, 0xc5, 0x68, 0xbd, 0x10, 0xbc, 0xe9, 0x84, 0x66, 0x55, 0xe0, 0xc9, 0xef, 0x60, 0x7d, + 0x1b, 0x56, 0xd3, 0x87, 0x24, 0x88, 0x4a, 0xac, 0x8a, 0x20, 0xc6, 0xbc, 0x29, 0xfe, 0x64, 0xcb, + 0x50, 0xb8, 0xb0, 0x47, 0x53, 0x2e, 0x79, 0x3a, 0x7d, 0x7c, 0x98, 0xfd, 0x6e, 0xc6, 0xf8, 0xc3, + 0x0c, 0x54, 0x69, 0x96, 0x52, 0x16, 0x79, 0x13, 0x6a, 0x8a, 0x1a, 0xb8, 0xef, 0x7b, 0xbe, 0xe4, + 0x6a, 0x8a, 0xf2, 0x3a, 0x02, 0x26, 0x6e, 0x15, 0x85, 0x34, 0xf1, 0xb9, 0x33, 0xb6, 0xcf, 0x54, + 0xd3, 0x8a, 0x94, 0x8e, 0x24, 0x98, 0xbd, 0x17, 0xb7, 0xe7, 0x7b, 0xd3, 0x90, 0xcb, 0x3b, 0xaf, + 0x2a, 0xa7, 0x67, 0x0a, 0x58, 0xd4, 0x3a, 0x7e, 0xbd, 0x02, 0x9d, 0x1b, 0x3f, 0xcd, 0x00, 0x13, + 0xc3, 0xee, 0x7b, 0xd4, 0x80, 0xa4, 0xd0, 0xd9, 0x9a, 0x99, 0x57, 0x3e, 0x21, 0xd9, 0x17, 0x9d, + 0x10, 0x03, 0x0a, 0x34, 0xf6, 0x7c, 0xca, 0xd8, 0xa9, 0xe8, 0x07, 0xf9, 0x52, 0xae, 0x99, 0x37, + 0xfe, 0x47, 0x0e, 0x96, 0xb7, 0xe8, 0xca, 0x6e, 0x0f, 0x06, 0x7c, 0x12, 0x9d, 0x9d, 0x7b, 0x50, + 0x71, 0xbd, 0x21, 0x57, 0x14, 0x4b, 0x03, 0x03, 0x01, 0xd2, 0xc8, 0xf5, 0xdc, 0x76, 0x5c, 0x1a, + 0x38, 0x2d, 0x66, 0x19, 0x21, 0x38, 0xec, 0xb7, 0xa1, 0x31, 0xe1, 0xee, 0x50, 0x3f, 0x22, 0x24, + 0x54, 0xd5, 0x24, 0x58, 0x9e, 0x8e, 0x7b, 0x50, 0x39, 0x9d, 0x12, 0x9e, 0x60, 0x2c, 0x79, 0xa4, + 0x01, 0x90, 0xa0, 0x36, 0xf1, 0x97, 0xc9, 0x34, 0x38, 0xc7, 0xd2, 0x02, 0x96, 0x16, 0xc5, 0xb7, + 0x28, 0xba, 0x0b, 0x30, 0x9c, 0x06, 0xa1, 0x3c, 0x31, 0x0b, 0x58, 0x58, 0x16, 0x10, 0x3a, 0x31, + 0xdf, 0x84, 0xa5, 0xb1, 0x7d, 0x65, 0x21, 0xed, 0x58, 0x8e, 0x6b, 0x9d, 0x8e, 0xf0, 0xce, 0x29, + 0x22, 0x5e, 0x73, 0x6c, 0x5f, 0x7d, 0x22, 0x4a, 0xba, 0xee, 0x0e, 0xc2, 0x05, 0x5b, 0x51, 0xe2, + 0x8e, 0xcf, 0x03, 0xee, 0x5f, 0x70, 0xe4, 0x04, 0xf9, 0x48, 0xa6, 0x31, 0x09, 0x2a, 0x46, 0x34, + 0x16, 0xf3, 0x0e, 0x47, 0x03, 0x3a, 0xf6, 0x66, 0x71, 0xec, 0xb8, 0xbb, 0xe1, 0x68, 0x20, 0xee, + 0x15, 0xc1, 0x47, 0x26, 0xdc, 0xb7, 0x9e, 0x5f, 0xe2, 0x19, 0xce, 0x23, 0xdf, 0x38, 0xe2, 0xfe, + 0xb3, 0x4b, 0x71, 0xf5, 0x0f, 0x02, 0x64, 0x44, 0xf6, 0x75, 0xab, 0x82, 0x07, 0xbc, 0x34, 0x08, + 0x04, 0x0b, 0xb2, 0xaf, 0xc5, 0x21, 0x14, 0xa3, 0xb5, 0x71, 0x17, 0xf8, 0x10, 0x9b, 0x0f, 0x90, + 0xa3, 0xd6, 0x70, 0xb0, 0x6d, 0x59, 0x20, 0xfa, 0x09, 0x04, 0xd5, 0xab, 0xc1, 0x9e, 0x8e, 0xec, + 0xb3, 0x00, 0x59, 0x4a, 0xcd, 0xac, 0x4a, 0xe0, 0x8e, 0x80, 0x19, 0x9f, 0x92, 0x90, 0xa5, 0xed, + 0xad, 0x3c, 0x33, 0xe2, 0xaa, 0x47, 0x08, 0xee, 0x6b, 0xc9, 0x94, 0x5f, 0x69, 0x9b, 0x96, 0x4d, + 0xd9, 0x34, 0xe3, 0xf7, 0x32, 0x50, 0x95, 0x2d, 0xa3, 0x50, 0xc2, 0x36, 0x80, 0xa9, 0x5d, 0x0c, + 0xaf, 0x9c, 0xa1, 0x75, 0x72, 0x1d, 0xf2, 0x80, 0x88, 0x66, 0xf7, 0x96, 0xd9, 0x94, 0x65, 0xfd, + 0x2b, 0x67, 0xb8, 0x29, 0x4a, 0xd8, 0x43, 0x68, 0x26, 0xf0, 0x83, 0xd0, 0x27, 0x8a, 0xde, 0xbd, + 0x65, 0xd6, 0x35, 0xec, 0x5e, 0xe8, 0x8b, 0x33, 0x22, 0x44, 0x9e, 0x69, 0x68, 0x39, 0xee, 0x90, + 0x5f, 0x21, 0x19, 0xd5, 0xcc, 0x0a, 0xc1, 0xba, 0x02, 0xb4, 0x59, 0x87, 0xaa, 0xde, 0x9c, 0x71, + 0x06, 0x25, 0x25, 0x2f, 0xa1, 0xc0, 0x30, 0x33, 0x24, 0xb3, 0x1c, 0x46, 0x23, 0xb9, 0x0d, 0xa5, + 0xe4, 0x08, 0xcc, 0x62, 0xf8, 0xca, 0x1d, 0x1b, 0xdf, 0x83, 0xe6, 0x9e, 0x20, 0x1e, 0x57, 0x10, + 0xab, 0x94, 0xff, 0x56, 0x61, 0x41, 0x3b, 0x34, 0x65, 0x53, 0x7e, 0x89, 0x3b, 0xf7, 0xdc, 0x0b, + 0x42, 0xd9, 0x0b, 0xfe, 0x6d, 0xfc, 0x51, 0x06, 0x58, 0x27, 0x08, 0x9d, 0xb1, 0x1d, 0xf2, 0x1d, + 0x1e, 0xb1, 0x85, 0x43, 0xa8, 0x8a, 0xd6, 0xfa, 0x5e, 0x9b, 0x04, 0x32, 0x12, 0x28, 0xde, 0x95, + 0xc7, 0x78, 0xbe, 0xc2, 0x86, 0x8e, 0x4d, 0x6c, 0x3e, 0xd1, 0x80, 0x38, 0x65, 0xa1, 0xed, 0x9f, + 0xf1, 0x10, 0xc5, 0x38, 0x29, 0xef, 0x03, 0x81, 0x84, 0x00, 0xb7, 0xfe, 0x6b, 0xb0, 0x38, 0xd7, + 0x86, 0xce, 0x97, 0xcb, 0x29, 0x7c, 0x39, 0xa7, 0xf3, 0x65, 0x0b, 0x96, 0x12, 0xe3, 0x92, 0x94, + 0xb6, 0x06, 0x45, 0x71, 0x20, 0x84, 0x70, 0x90, 0x21, 0xa9, 0xf2, 0x94, 0x73, 0x21, 0x06, 0x3f, + 0x82, 0xe5, 0x53, 0xce, 0x7d, 0x3b, 0xc4, 0x42, 0x3c, 0x31, 0x62, 0x87, 0x64, 0xc3, 0x8b, 0xb2, + 0xac, 0x67, 0x87, 0x47, 0xdc, 0x17, 0x3b, 0x65, 0xfc, 0xcf, 0x0c, 0x34, 0x04, 0x07, 0xdd, 0xb7, + 0xdd, 0x6b, 0xb5, 0x4e, 0x7b, 0xa9, 0xeb, 0xf4, 0x40, 0xbb, 0x0c, 0x35, 0xec, 0x2f, 0xbb, 0x48, + 0xb9, 0xd9, 0x45, 0x62, 0xf7, 0xa1, 0x9a, 0x18, 0x6b, 0x01, 0xc7, 0x0a, 0x41, 0x34, 0xc8, 0x5f, + 0x7c, 0x19, 0xdf, 0x86, 0x66, 0x3c, 0x6c, 0xb9, 0x86, 0x0c, 0xf2, 0x82, 0x24, 0x65, 0x03, 0xf8, + 0xb7, 0xf1, 0x2f, 0x32, 0x84, 0xb8, 0xe5, 0x39, 0x91, 0x74, 0x2a, 0x10, 0x85, 0xdc, 0xab, 0x10, + 0xc5, 0xdf, 0x37, 0x4a, 0xf5, 0xbf, 0xf8, 0x64, 0xc5, 0xd1, 0x09, 0xb8, 0x3b, 0xb4, 0xec, 0xd1, + 0x08, 0x99, 0x6f, 0xc9, 0x2c, 0x8a, 0xef, 0xf6, 0x68, 0x64, 0xbc, 0x03, 0x8b, 0xda, 0xe8, 0x5e, + 0x30, 0x8f, 0x03, 0x60, 0x7b, 0x4e, 0x10, 0x1e, 0xbb, 0xc1, 0x44, 0x13, 0xdc, 0xee, 0x40, 0x59, + 0x70, 0x58, 0x31, 0x32, 0x3a, 0xb2, 0x05, 0x53, 0xb0, 0x5c, 0x31, 0xae, 0x00, 0x0b, 0xed, 0x2b, + 0x59, 0x98, 0x95, 0x85, 0xf6, 0x15, 0x16, 0x1a, 0xdf, 0x85, 0xa5, 0x44, 0x7b, 0xb2, 0xeb, 0x37, + 0xa0, 0x30, 0x0d, 0xaf, 0x3c, 0x25, 0x9a, 0x57, 0x24, 0x85, 0x08, 0x05, 0xd0, 0xa4, 0x12, 0xe3, + 0x23, 0x58, 0x3c, 0xe0, 0x97, 0xf2, 0x10, 0xab, 0x81, 0xbc, 0x0d, 0xf9, 0x97, 0x28, 0x85, 0x58, + 0x6e, 0x6c, 0x00, 0xd3, 0x2b, 0xcb, 0x5e, 0x35, 0x1d, 0x31, 0x93, 0xd0, 0x11, 0x8d, 0xb7, 0x81, + 0xf5, 0x9c, 0x33, 0x77, 0x9f, 0x07, 0x81, 0x7d, 0x16, 0x1d, 0xfb, 0x26, 0xe4, 0xc6, 0xc1, 0x99, + 0xe4, 0x51, 0xe2, 0x4f, 0xe3, 0x5b, 0xb0, 0x94, 0xc0, 0x93, 0x0d, 0xbf, 0x06, 0xe5, 0xc0, 0x39, + 0x73, 0x51, 0xb0, 0x92, 0x4d, 0xc7, 0x00, 0x63, 0x07, 0x96, 0x3f, 0xe1, 0xbe, 0x73, 0x7a, 0xfd, + 0xb2, 0xe6, 0x93, 0xed, 0x64, 0x67, 0xdb, 0xe9, 0xc0, 0xca, 0x4c, 0x3b, 0xb2, 0x7b, 0x22, 0x5f, + 0xb9, 0x93, 0x25, 0x93, 0x3e, 0x34, 0xbe, 0x97, 0xd5, 0xf9, 0x9e, 0x71, 0x0c, 0x6c, 0xcb, 0x73, + 0x5d, 0x3e, 0x08, 0x8f, 0x38, 0xf7, 0x63, 0x2b, 0x55, 0x4c, 0xab, 0x95, 0x27, 0x6b, 0x72, 0x65, + 0x67, 0x99, 0xa9, 0x24, 0x62, 0x06, 0xf9, 0x09, 0xf7, 0xc7, 0xd8, 0x70, 0xc9, 0xc4, 0xbf, 0x8d, + 0x15, 0x58, 0x4a, 0x34, 0x2b, 0xf5, 0xfa, 0xc7, 0xb0, 0xb2, 0xed, 0x04, 0x83, 0xf9, 0x0e, 0xd7, + 0xa0, 0x38, 0x99, 0x9e, 0x58, 0x49, 0xbe, 0xfc, 0x8c, 0x5f, 0x0b, 0x6d, 0x6f, 0xb6, 0x86, 0x6c, + 0xeb, 0xef, 0x64, 0x20, 0xbf, 0xdb, 0xdf, 0xdb, 0x62, 0xeb, 0x50, 0x72, 0xdc, 0x81, 0x37, 0x16, + 0x82, 0x17, 0xcd, 0x39, 0xfa, 0xbe, 0xf1, 0x80, 0xdd, 0x81, 0x32, 0xca, 0x6b, 0x42, 0xb5, 0x95, + 0xa2, 0x4f, 0x49, 0x00, 0xf6, 0xbc, 0xc1, 0x73, 0xa1, 0x53, 0xf3, 0xab, 0x89, 0xe3, 0xa3, 0xd6, + 0xac, 0x94, 0xe1, 0x3c, 0xdd, 0xf5, 0x71, 0x01, 0x69, 0xc4, 0xc6, 0x5f, 0x15, 0xa1, 0x28, 0x6f, + 0x5b, 0xba, 0xb9, 0x43, 0xe7, 0x82, 0xc7, 0x37, 0xb7, 0xf8, 0x12, 0xf2, 0x80, 0xcf, 0xc7, 0x5e, + 0x18, 0x09, 0x6c, 0xb4, 0x07, 0x55, 0x02, 0x4a, 0x91, 0x4d, 0x13, 0x1a, 0xc8, 0xc4, 0x90, 0x23, + 0xa4, 0x81, 0x7e, 0x95, 0xdf, 0x81, 0xa2, 0xba, 0xfb, 0xf3, 0x91, 0x4e, 0xb3, 0x30, 0x20, 0x69, + 0x6d, 0x1d, 0x4a, 0x03, 0x7b, 0x62, 0x0f, 0x9c, 0xf0, 0x5a, 0x32, 0x84, 0xe8, 0x5b, 0xb4, 0x3e, + 0xf2, 0x06, 0xf6, 0xc8, 0x3a, 0xb1, 0x47, 0xb6, 0x3b, 0xe0, 0x52, 0x77, 0xaf, 0x22, 0x70, 0x93, + 0x60, 0x42, 0x3f, 0x97, 0xe3, 0x54, 0x58, 0xa4, 0xc2, 0xcb, 0xd1, 0x2b, 0x34, 0x21, 0x5c, 0x7a, + 0xe3, 0xb1, 0x23, 0xb4, 0x0c, 0x12, 0xc3, 0x72, 0x66, 0x99, 0x20, 0x3b, 0x1c, 0x67, 0x2b, 0x8b, + 0x2f, 0x69, 0xe9, 0xca, 0xd4, 0x15, 0x01, 0x3f, 0x25, 0x43, 0xc2, 0xbc, 0x2c, 0x96, 0xd3, 0x64, + 0xb1, 0x77, 0x61, 0x71, 0xea, 0x06, 0x3c, 0x0c, 0x47, 0x7c, 0x18, 0x8d, 0xa5, 0x82, 0x48, 0xcd, + 0xa8, 0x40, 0x0d, 0x67, 0x03, 0x96, 0xc8, 0xe8, 0x10, 0xd8, 0xa1, 0x17, 0x9c, 0x3b, 0x81, 0x15, + 0x08, 0x0d, 0x89, 0xd4, 0xdd, 0x45, 0x2c, 0xea, 0xc9, 0x92, 0x1e, 0xa9, 0x48, 0x6b, 0x33, 0xf8, + 0x3e, 0x1f, 0x70, 0xe7, 0x82, 0x0f, 0x51, 0x4e, 0xcb, 0x99, 0x2b, 0x89, 0x3a, 0xa6, 0x2c, 0x44, + 0xa1, 0x7b, 0x3a, 0xb6, 0xa6, 0x93, 0xa1, 0x2d, 0x84, 0x95, 0x3a, 0x09, 0xc3, 0xee, 0x74, 0x7c, + 0x4c, 0x10, 0xf6, 0x18, 0x94, 0x24, 0x26, 0xe5, 0xc3, 0x46, 0x82, 0x9f, 0x09, 0x62, 0x35, 0xab, + 0x12, 0x83, 0x04, 0xc5, 0x84, 0xcc, 0xd9, 0x9c, 0x91, 0x39, 0x5b, 0x50, 0x9c, 0xf8, 0xce, 0x85, + 0x1d, 0xf2, 0xd6, 0x22, 0x31, 0x70, 0xf9, 0x29, 0x38, 0x83, 0xe3, 0x3a, 0xa1, 0x63, 0x87, 0x9e, + 0xdf, 0x62, 0x58, 0x16, 0x03, 0xd8, 0x43, 0x58, 0x44, 0x1a, 0x09, 0x42, 0x3b, 0x9c, 0x06, 0x52, + 0x02, 0x5d, 0x42, 0x62, 0x42, 0x19, 0xba, 0x87, 0x70, 0x14, 0x42, 0xd9, 0xb7, 0x60, 0x95, 0xc8, + 0x02, 0x6b, 0x48, 0xc9, 0x1a, 0x05, 0x82, 0x65, 0x5c, 0x8a, 0x25, 0x2c, 0x15, 0xf4, 0x2d, 0xe5, + 0x6b, 0x21, 0x1d, 0xbc, 0x0f, 0x6b, 0x92, 0x4c, 0xe6, 0x6a, 0xad, 0x60, 0xad, 0x65, 0x2a, 0x9e, + 0xa9, 0xb6, 0x01, 0x8b, 0x62, 0x48, 0xce, 0xc0, 0x92, 0xb5, 0xc5, 0x49, 0x58, 0x15, 0xa3, 0x47, + 0x4d, 0xa9, 0x41, 0x85, 0x26, 0x96, 0x3d, 0xe3, 0xd7, 0xec, 0x7b, 0xd0, 0x20, 0x92, 0x41, 0xf5, + 0x0a, 0x39, 0xfd, 0x3a, 0x72, 0xfa, 0x15, 0x65, 0xe1, 0x8c, 0x4a, 0x91, 0xd9, 0xd7, 0x07, 0x89, + 0x6f, 0x71, 0x1c, 0x46, 0xce, 0x29, 0x0f, 0x9d, 0x31, 0x6f, 0xad, 0x11, 0x81, 0xa9, 0x6f, 0x71, + 0x52, 0xa7, 0x13, 0x2c, 0x69, 0x11, 0x5f, 0xa0, 0x2f, 0xa4, 0xdd, 0x91, 0x17, 0x70, 0x65, 0xa2, + 0x6a, 0xdd, 0x96, 0x87, 0x50, 0x00, 0x25, 0xdb, 0x33, 0x7e, 0x96, 0xa1, 0x7b, 0x4c, 0x1e, 0xfb, + 0x40, 0xd3, 0xca, 0xe8, 0xc0, 0x5b, 0x9e, 0x3b, 0xba, 0x96, 0x3c, 0x00, 0x08, 0x74, 0xe8, 0x8e, + 0xf0, 0x10, 0x3a, 0xae, 0x8e, 0x42, 0x2c, 0xb3, 0xaa, 0x80, 0x88, 0x74, 0x0f, 0x2a, 0x93, 0xe9, + 0xc9, 0xc8, 0x19, 0x10, 0x4a, 0x8e, 0x5a, 0x21, 0x10, 0x22, 0x08, 0xb5, 0x94, 0x08, 0x81, 0x30, + 0xf2, 0x88, 0x51, 0x91, 0x30, 0x44, 0x41, 0x96, 0xcc, 0x7d, 0xe4, 0x02, 0x55, 0x13, 0xff, 0x36, + 0x36, 0x61, 0x39, 0x39, 0x68, 0x79, 0x5f, 0x3c, 0x84, 0x92, 0x64, 0x31, 0xca, 0x5e, 0x51, 0xd7, + 0x2c, 0xc8, 0x42, 0xb3, 0x8a, 0xca, 0x8d, 0xdf, 0x5e, 0x80, 0x25, 0x09, 0xdd, 0x12, 0x2b, 0xd2, + 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0xc2, 0xbb, 0x32, 0x2f, 0xe6, 0x5d, 0xd9, 0x39, 0xde, 0x95, 0x54, + 0x58, 0x89, 0xf5, 0x25, 0x15, 0x56, 0xb1, 0x05, 0xa4, 0x43, 0xe8, 0xe6, 0xcb, 0x9a, 0x04, 0xf7, + 0xc9, 0x4c, 0x3a, 0xc7, 0x69, 0x0b, 0x29, 0x9c, 0x56, 0xe7, 0x93, 0x0b, 0x33, 0x7c, 0xf2, 0x0d, + 0xa0, 0xbd, 0x56, 0x6c, 0xbf, 0x48, 0x6a, 0x05, 0xc2, 0xa4, 0x0d, 0xf4, 0x1d, 0x68, 0xcc, 0xb2, + 0x26, 0xe2, 0x81, 0xf5, 0x14, 0xc6, 0xe4, 0x8c, 0x39, 0x5e, 0x32, 0x1a, 0x72, 0x59, 0x32, 0x26, + 0x67, 0xcc, 0xf7, 0xb0, 0x44, 0xe1, 0x77, 0x00, 0xa8, 0x6f, 0xa4, 0x75, 0x40, 0x5a, 0x7f, 0x3b, + 0xb9, 0x17, 0xfa, 0xaa, 0x6f, 0x88, 0x8f, 0xa9, 0xcf, 0x91, 0xf8, 0xcb, 0x58, 0x13, 0xe9, 0xfe, + 0x19, 0xd4, 0xbd, 0x09, 0x77, 0xad, 0x98, 0x45, 0x54, 0xb0, 0xa9, 0xb7, 0x5e, 0xd0, 0x54, 0x57, + 0xe1, 0x9a, 0x35, 0x51, 0x37, 0xfa, 0x64, 0xfb, 0xb4, 0xf0, 0x5c, 0x6b, 0xad, 0xfa, 0x25, 0x5a, + 0xab, 0x63, 0xe5, 0xe8, 0xdb, 0xf8, 0xfb, 0x19, 0xa8, 0x68, 0xc3, 0x66, 0x2b, 0xb0, 0xb8, 0x75, + 0x78, 0x78, 0xd4, 0x31, 0xdb, 0xfd, 0xee, 0x27, 0x1d, 0x6b, 0x6b, 0xef, 0xb0, 0xd7, 0x69, 0xde, + 0x12, 0xe0, 0xbd, 0xc3, 0xad, 0xf6, 0x9e, 0xb5, 0x73, 0x68, 0x6e, 0x29, 0x70, 0x86, 0xad, 0x02, + 0x33, 0x3b, 0xfb, 0x87, 0xfd, 0x4e, 0x02, 0x9e, 0x65, 0x4d, 0xa8, 0x6e, 0x9a, 0x9d, 0xf6, 0xd6, + 0xae, 0x84, 0xe4, 0xd8, 0x32, 0x34, 0x77, 0x8e, 0x0f, 0xb6, 0xbb, 0x07, 0x4f, 0xad, 0xad, 0xf6, + 0xc1, 0x56, 0x67, 0xaf, 0xb3, 0xdd, 0xcc, 0xb3, 0x1a, 0x94, 0xdb, 0x9b, 0xed, 0x83, 0xed, 0xc3, + 0x83, 0xce, 0x76, 0xb3, 0x60, 0xfc, 0x0a, 0x94, 0xe3, 0x89, 0x56, 0xa0, 0x78, 0x7c, 0xf0, 0xec, + 0xe0, 0xf0, 0xd3, 0x83, 0xe6, 0x2d, 0x56, 0x86, 0x02, 0xf6, 0xdf, 0xcc, 0x30, 0x80, 0x05, 0xea, + 0xb3, 0x99, 0x65, 0x25, 0xc8, 0x6f, 0x1e, 0xf6, 0x77, 0x9b, 0x39, 0xe3, 0xcf, 0x33, 0xb0, 0x82, + 0x53, 0x1e, 0xce, 0x32, 0x81, 0xfb, 0x50, 0x19, 0x78, 0xde, 0x44, 0x28, 0x48, 0xb1, 0x20, 0xa0, + 0x83, 0xc4, 0x01, 0x27, 0x9e, 0x7b, 0xea, 0xf9, 0x03, 0x2e, 0x79, 0x00, 0x20, 0x68, 0x47, 0x40, + 0x04, 0x0d, 0x4a, 0x22, 0x26, 0x0c, 0x62, 0x01, 0x15, 0x82, 0x11, 0xca, 0x2a, 0x2c, 0x9c, 0xf8, + 0xdc, 0x1e, 0x9c, 0xcb, 0xd3, 0x2f, 0xbf, 0xd8, 0xd7, 0x63, 0xd5, 0x7d, 0x20, 0x68, 0x6a, 0xc4, + 0x87, 0x78, 0x04, 0x4a, 0x66, 0x43, 0xc2, 0xb7, 0x24, 0x58, 0x5c, 0x22, 0xf6, 0x89, 0xed, 0x0e, + 0x3d, 0x97, 0x0f, 0xa5, 0x86, 0x10, 0x03, 0x8c, 0x23, 0x58, 0x9d, 0x9d, 0x9f, 0xe4, 0x17, 0x1f, + 0x68, 0xfc, 0x82, 0x04, 0xf6, 0xf5, 0x9b, 0x49, 0x41, 0xe3, 0x1d, 0xff, 0x30, 0x0f, 0x79, 0x21, + 0xc0, 0xdd, 0x28, 0xeb, 0xe9, 0x12, 0x79, 0x6e, 0xce, 0x6b, 0x83, 0x16, 0x02, 0xba, 0xd9, 0xc9, + 0x0c, 0x55, 0x46, 0x08, 0xde, 0xe8, 0x51, 0xb1, 0xcf, 0x07, 0x17, 0xd2, 0x0e, 0x45, 0xc5, 0x26, + 0x1f, 0x5c, 0xa0, 0x2a, 0x64, 0x87, 0x54, 0x97, 0xce, 0x7b, 0x31, 0xb0, 0x43, 0xac, 0x29, 0x8b, + 0xb0, 0x5e, 0x31, 0x2a, 0xc2, 0x5a, 0x2d, 0x28, 0x3a, 0xee, 0x89, 0x37, 0x75, 0x87, 0x78, 0xbc, + 0x4b, 0xa6, 0xfa, 0x44, 0x27, 0x11, 0x72, 0x22, 0x71, 0x7f, 0xd0, 0x69, 0x2e, 0x09, 0x40, 0x5f, + 0xdc, 0x20, 0xef, 0x41, 0x39, 0xb8, 0x76, 0x07, 0xfa, 0x19, 0x5e, 0x96, 0xeb, 0x23, 0x66, 0xbf, + 0xd1, 0xbb, 0x76, 0x07, 0x78, 0x62, 0x4b, 0x81, 0xfc, 0x8b, 0xbd, 0x0f, 0xa5, 0xc8, 0x5c, 0x4b, + 0x1c, 0xf8, 0xb6, 0x5e, 0x43, 0xd9, 0x68, 0x49, 0x2b, 0x8e, 0x50, 0xd9, 0x23, 0x58, 0x40, 0x9b, + 0x6a, 0xd0, 0xaa, 0x62, 0x25, 0x25, 0xa6, 0x8b, 0x61, 0xa0, 0x7f, 0x86, 0x0f, 0xd1, 0xbe, 0x6a, + 0x4a, 0xb4, 0xf5, 0x67, 0x50, 0x4b, 0xb4, 0xa5, 0xeb, 0xbe, 0x35, 0xd2, 0x7d, 0xdf, 0xd2, 0x75, + 0xdf, 0xf8, 0x26, 0x90, 0xd5, 0x74, 0x5d, 0xf8, 0xd7, 0xa0, 0xa4, 0xa6, 0x22, 0xce, 0x9f, 0x3c, + 0x3b, 0x56, 0xef, 0xb3, 0x83, 0xad, 0xe6, 0x2d, 0xd6, 0x80, 0x4a, 0x7b, 0x0b, 0x8f, 0x34, 0x02, + 0x32, 0x02, 0xe5, 0xa8, 0xdd, 0xeb, 0x45, 0x90, 0xac, 0xb1, 0x03, 0xcd, 0xd9, 0x91, 0x0a, 0x9a, + 0x0c, 0x15, 0x4c, 0x5a, 0x9c, 0x63, 0x80, 0xd0, 0x6c, 0xc8, 0x88, 0x4c, 0xe2, 0x33, 0x7d, 0x18, + 0xef, 0x43, 0x53, 0xdc, 0x6b, 0x62, 0xa9, 0x02, 0xcd, 0x72, 0x3b, 0x12, 0x22, 0x99, 0x6e, 0x75, + 0x2e, 0x99, 0x15, 0x82, 0x61, 0x57, 0xc6, 0x07, 0xb0, 0xa8, 0x55, 0x8b, 0x35, 0x51, 0x71, 0x57, + 0xce, 0x6a, 0xa2, 0xa8, 0x77, 0x50, 0x89, 0xb1, 0x06, 0x2b, 0xe2, 0xb3, 0x73, 0xc1, 0xdd, 0xb0, + 0x37, 0x3d, 0x21, 0x57, 0xa1, 0xe3, 0xb9, 0x42, 0x1f, 0x29, 0x47, 0x25, 0x37, 0x13, 0xf9, 0x86, + 0x54, 0x5a, 0xb3, 0x48, 0x1a, 0xeb, 0x5a, 0x0f, 0x58, 0x71, 0x03, 0xff, 0x4d, 0x28, 0xaf, 0xe5, + 0x08, 0x24, 0x96, 0xf5, 0xa8, 0xd3, 0x31, 0xad, 0xc3, 0x83, 0xbd, 0xee, 0x81, 0x60, 0x94, 0x62, + 0x59, 0x11, 0xb0, 0xb3, 0x83, 0x90, 0x8c, 0xd1, 0x84, 0xfa, 0x53, 0x1e, 0x76, 0xdd, 0x53, 0x4f, + 0xb9, 0xc5, 0xfe, 0xb2, 0x00, 0x8d, 0x08, 0x14, 0x2b, 0xbf, 0x17, 0xdc, 0x0f, 0x1c, 0xcf, 0x45, + 0x39, 0xb6, 0x6c, 0xaa, 0x4f, 0x71, 0xbb, 0x39, 0x43, 0xee, 0x86, 0x4e, 0x78, 0x6d, 0x25, 0x2c, + 0x65, 0x75, 0x05, 0x96, 0xb7, 0xe8, 0x32, 0x14, 0xec, 0x91, 0x63, 0x2b, 0x0f, 0x2b, 0x7d, 0x08, + 0xe8, 0xc0, 0x1b, 0x79, 0x3e, 0x8a, 0xac, 0x65, 0x93, 0x3e, 0xd8, 0x63, 0x58, 0x16, 0xa2, 0xb3, + 0x6e, 0xbe, 0x44, 0xfe, 0x41, 0x46, 0x3b, 0xe6, 0x4e, 0xc7, 0x47, 0xb1, 0x09, 0x53, 0x94, 0x88, + 0xbb, 0x53, 0xd4, 0x90, 0xc2, 0x52, 0x54, 0x81, 0xb4, 0xb0, 0x45, 0x77, 0x3a, 0x6e, 0x63, 0x49, + 0x84, 0xff, 0x04, 0x56, 0x04, 0x7e, 0x24, 0x5e, 0x45, 0x35, 0x1a, 0x58, 0x43, 0x34, 0xd6, 0x95, + 0x65, 0x51, 0x9d, 0x3b, 0x50, 0xa6, 0x51, 0x89, 0x1d, 0x2f, 0x90, 0xf4, 0x8d, 0x43, 0xe1, 0x7e, + 0x30, 0xe7, 0x0c, 0x5d, 0x20, 0x41, 0x60, 0xc6, 0x19, 0xaa, 0xb9, 0x53, 0x4b, 0xb3, 0xee, 0xd4, + 0x27, 0xb0, 0x72, 0x22, 0x48, 0xf0, 0x9c, 0xdb, 0x43, 0xee, 0x5b, 0x31, 0x61, 0x93, 0x96, 0xb1, + 0x24, 0x0a, 0x77, 0xb1, 0x2c, 0x3a, 0x07, 0x42, 0xce, 0x11, 0x6c, 0x81, 0x0f, 0xad, 0xd0, 0xb3, + 0x50, 0xfc, 0x41, 0x06, 0x53, 0x32, 0x6b, 0x04, 0xee, 0x7b, 0x5b, 0x02, 0x98, 0xc4, 0x3b, 0xf3, + 0xed, 0xc9, 0xb9, 0xd4, 0x03, 0x22, 0xbc, 0xa7, 0x02, 0xc8, 0x5e, 0x83, 0xa2, 0x20, 0x79, 0x97, + 0x93, 0xcf, 0x8a, 0x24, 0x6d, 0x05, 0x62, 0x6f, 0xc1, 0x02, 0xf6, 0x11, 0xb4, 0x9a, 0x48, 0xef, + 0xd5, 0x98, 0x91, 0x3b, 0xae, 0x29, 0xcb, 0x84, 0x30, 0x39, 0xf5, 0x1d, 0xe2, 0x32, 0x65, 0x13, + 0xff, 0x66, 0xdf, 0xd7, 0x58, 0xd6, 0x12, 0xd6, 0x55, 0xf2, 0xc0, 0x0c, 0xa5, 0xdd, 0xc4, 0xbd, + 0xbe, 0x52, 0x66, 0xf4, 0x83, 0x7c, 0xa9, 0xd2, 0xac, 0x1a, 0xdf, 0x81, 0x02, 0xad, 0x8e, 0x20, + 0x42, 0x5c, 0xbb, 0x8c, 0x24, 0x42, 0x84, 0xb6, 0xa0, 0xe8, 0xf2, 0xf0, 0xd2, 0xf3, 0x9f, 0x2b, + 0x5b, 0xb2, 0xfc, 0x34, 0x7e, 0x8c, 0x46, 0x90, 0xc8, 0x51, 0x4e, 0xfa, 0x9c, 0x20, 0x0f, 0xda, + 0xde, 0xe0, 0xdc, 0x96, 0x76, 0x99, 0x12, 0x02, 0x7a, 0xe7, 0xf6, 0x1c, 0x79, 0x64, 0xe7, 0x7d, + 0xe5, 0x6f, 0x41, 0x5d, 0xb9, 0xe6, 0x03, 0x6b, 0xc4, 0x4f, 0x43, 0x49, 0xee, 0x55, 0xe9, 0x97, + 0x0f, 0xf6, 0xf8, 0x69, 0x68, 0xec, 0xc3, 0xa2, 0x24, 0xc8, 0xc3, 0x09, 0x57, 0x5d, 0x7f, 0x37, + 0x4d, 0x9e, 0xae, 0x3c, 0x59, 0x4a, 0x5e, 0xb4, 0x14, 0x72, 0x90, 0x10, 0xb2, 0x8d, 0x8f, 0x81, 0xe9, 0xd7, 0xb0, 0x6c, 0x4f, 0x4a, 0xb5, 0xca, 0x04, 0xaf, 0x3c, 0x59, 0x91, 0xec, 0xec, 0x0c, - 0xc5, 0xea, 0x04, 0xd3, 0xc1, 0x40, 0x3d, 0x99, 0x28, 0x99, 0xea, 0xd3, 0xf8, 0x93, 0x0c, 0x2c, - 0x61, 0x63, 0x4a, 0x1f, 0x90, 0x4c, 0xf6, 0xe7, 0x1e, 0xa4, 0xd8, 0x1f, 0x5d, 0xf6, 0xa1, 0x8f, - 0x2f, 0x6f, 0xf4, 0xcc, 0xcf, 0x19, 0x3d, 0xbf, 0x0e, 0xcd, 0x21, 0x1f, 0x39, 0xf8, 0x7a, 0x46, - 0x89, 0x12, 0xa4, 0x01, 0x34, 0x14, 0x5c, 0x29, 0x71, 0xff, 0x3c, 0x03, 0x8b, 0x24, 0xa9, 0xa0, - 0x3a, 0x2c, 0x17, 0xea, 0x23, 0xa5, 0xff, 0x49, 0x56, 0x25, 0xe7, 0x14, 0xdf, 0xe0, 0x08, 0x25, - 0xe4, 0x9d, 0x1b, 0x52, 0x2f, 0x94, 0x50, 0xf6, 0x21, 0xea, 0x30, 0xae, 0x85, 0xc0, 0x94, 0xd7, - 0x38, 0xc9, 0x4d, 0xd9, 0xb9, 0x81, 0x0a, 0x8e, 0x8b, 0xa0, 0x8d, 0x92, 0x50, 0x48, 0x05, 0xd8, - 0xd8, 0x86, 0x5a, 0xa2, 0x9b, 0x84, 0x65, 0xb6, 0x4a, 0x96, 0xd9, 0x39, 0xef, 0x47, 0x76, 0xde, - 0xfb, 0xf1, 0xf7, 0xf2, 0xc0, 0x04, 0x49, 0xcd, 0xec, 0xda, 0x8c, 0xeb, 0x30, 0x3b, 0xe7, 0x3a, - 0x7c, 0x0c, 0x4c, 0x43, 0x50, 0x1e, 0xcd, 0x5c, 0xe4, 0xd1, 0x6c, 0xc6, 0xb8, 0xd2, 0xa1, 0xf9, - 0x18, 0x96, 0xa5, 0x40, 0x1b, 0xf9, 0x0a, 0xd1, 0xe4, 0x46, 0xfb, 0xc3, 0x48, 0xb2, 0x55, 0x3e, - 0x43, 0x34, 0xbf, 0x29, 0xb7, 0x61, 0x60, 0x87, 0xd2, 0x52, 0x85, 0x6e, 0xc3, 0x9e, 0x3d, 0x67, - 0xfa, 0x5e, 0x78, 0x25, 0x15, 0x14, 0xe7, 0xa8, 0x40, 0x33, 0x9c, 0x94, 0x92, 0x86, 0x13, 0x03, - 0x6a, 0xca, 0x39, 0x48, 0x6f, 0x22, 0x48, 0x7a, 0xab, 0x48, 0x0f, 0x21, 0xbe, 0x8b, 0xb8, 0x0f, - 0x4d, 0x65, 0xdd, 0x88, 0x4c, 0x33, 0xe4, 0xef, 0x97, 0xc6, 0xb1, 0x4d, 0x65, 0xa0, 0x49, 0x18, - 0xc2, 0x2b, 0x33, 0x86, 0xf0, 0xf7, 0x60, 0x31, 0x10, 0x44, 0x64, 0x4d, 0x5d, 0xf9, 0x38, 0x87, - 0x0f, 0x51, 0x75, 0x2a, 0x99, 0x4d, 0x2c, 0x38, 0x8a, 0xe1, 0xf3, 0x66, 0x87, 0xda, 0xbc, 0xd9, - 0x81, 0x3d, 0x8d, 0xfd, 0x68, 0xc1, 0x99, 0x33, 0xc6, 0x8b, 0x3b, 0x7e, 0xc8, 0x22, 0x17, 0xb8, - 0x77, 0xe6, 0x8c, 0x4d, 0xe5, 0xb4, 0x15, 0x1f, 0xc6, 0x7f, 0xcd, 0x40, 0x53, 0xd0, 0x41, 0x82, - 0xce, 0x7f, 0x05, 0xf0, 0x44, 0xbe, 0x26, 0x99, 0x57, 0x04, 0xae, 0xa2, 0xf2, 0xef, 0x00, 0x92, - 0xad, 0x25, 0xf4, 0x44, 0x49, 0xe4, 0xad, 0x24, 0x91, 0xc7, 0x8c, 0x6c, 0xe7, 0x06, 0x29, 0x00, - 0x02, 0x92, 0xe6, 0xbf, 0xcc, 0xa7, 0xf8, 0x2f, 0xb5, 0xa3, 0xb0, 0x03, 0xf0, 0x9c, 0x5f, 0xed, - 0x7a, 0x03, 0xd4, 0xd0, 0x6e, 0x03, 0x08, 0x82, 0x3c, 0xb1, 0xc7, 0x8e, 0xb4, 0xae, 0x14, 0xcc, - 0xf2, 0x0b, 0x7e, 0xb5, 0x8d, 0x00, 0xb1, 0x1b, 0xa2, 0x38, 0x3e, 0x0f, 0x05, 0xb3, 0xf4, 0x82, - 0x5f, 0xd1, 0x61, 0xb0, 0xa0, 0xf6, 0x9c, 0x5f, 0x6d, 0x71, 0x12, 0xd7, 0x3c, 0x5f, 0x50, 0x82, - 0x6f, 0x5f, 0x08, 0xf9, 0x2c, 0xe1, 0x7b, 0xac, 0xf8, 0xf6, 0xc5, 0x73, 0x7e, 0xa5, 0xfc, 0xa0, - 0x45, 0x51, 0x3e, 0xf2, 0x06, 0xf2, 0x06, 0x52, 0xaf, 0x28, 0xe2, 0x41, 0x99, 0x0b, 0x2f, 0xf0, - 0x6f, 0xe3, 0x8f, 0x33, 0x50, 0x13, 0xe3, 0x47, 0x06, 0x27, 0xd6, 0x5d, 0x3d, 0xc6, 0xc9, 0xc4, - 0x8f, 0x71, 0x9e, 0x48, 0xfe, 0x40, 0xdc, 0x32, 0x7b, 0x3d, 0xb7, 0xc4, 0x05, 0x26, 0x56, 0xf9, - 0x3e, 0x94, 0xe9, 0x6c, 0x89, 0xc3, 0x9a, 0x4b, 0xec, 0x52, 0x62, 0x42, 0x66, 0x09, 0xd1, 0x9e, - 0x93, 0xef, 0x5f, 0x33, 0xb0, 0xd1, 0x12, 0x97, 0xfd, 0xc8, 0xac, 0x96, 0xb2, 0x0d, 0x85, 0x34, - 0x37, 0xf2, 0x11, 0x54, 0x34, 0x9a, 0x42, 0x6b, 0x5c, 0x34, 0x78, 0x22, 0xc0, 0x24, 0xd1, 0x24, - 0x66, 0xbf, 0x73, 0xc3, 0xac, 0x0d, 0x74, 0xc0, 0xc6, 0x02, 0xe4, 0x45, 0x25, 0xe3, 0x23, 0x58, - 0xd4, 0x9a, 0x25, 0x6d, 0x34, 0x6d, 0x4c, 0x99, 0xb4, 0x31, 0xfd, 0x8b, 0x0c, 0x2c, 0xcb, 0xda, - 0xf8, 0x70, 0xcb, 0x11, 0xd7, 0xf5, 0x5e, 0x70, 0xca, 0x7e, 0x05, 0x6a, 0xa2, 0x75, 0xcb, 0xe7, - 0xa7, 0x4e, 0x10, 0x72, 0xe5, 0xb9, 0x48, 0x39, 0x1c, 0x82, 0x6b, 0x0b, 0x54, 0x53, 0x62, 0xb2, - 0x8f, 0xa0, 0x82, 0x55, 0x49, 0x5f, 0x96, 0xdb, 0xd2, 0x9a, 0xaf, 0x48, 0x43, 0xdd, 0xb9, 0x61, - 0x42, 0x10, 0x7d, 0x6d, 0x94, 0xa1, 0x18, 0xfa, 0xce, 0xe9, 0x29, 0xf7, 0x8d, 0xd5, 0x68, 0x68, - 0xe2, 0xa4, 0xf1, 0x5e, 0xc8, 0x27, 0x42, 0x08, 0x32, 0xfe, 0x7b, 0x06, 0x2a, 0xf2, 0xec, 0xfc, - 0xdc, 0xee, 0x8a, 0x75, 0xed, 0xe5, 0x21, 0xa9, 0xc6, 0xf1, 0x43, 0xc3, 0x7b, 0xd0, 0x18, 0x0b, - 0x81, 0x48, 0x08, 0xec, 0x09, 0x5f, 0x45, 0x5d, 0x81, 0xa5, 0x3c, 0xf2, 0x10, 0x96, 0x50, 0x3c, - 0x09, 0xac, 0xd0, 0x19, 0x59, 0xaa, 0x50, 0xbe, 0xf2, 0x5b, 0xa4, 0xa2, 0xbe, 0x33, 0xda, 0x93, - 0x05, 0xe2, 0x96, 0x0e, 0x42, 0xfb, 0x94, 0x4b, 0xd1, 0x97, 0x3e, 0x8c, 0x16, 0xac, 0xce, 0xc8, - 0xea, 0x4a, 0xcf, 0xf8, 0x87, 0x35, 0x58, 0x9b, 0x2b, 0x92, 0xfa, 0x46, 0x64, 0xa3, 0x1f, 0x39, - 0xe3, 0x63, 0x2f, 0x32, 0x85, 0x65, 0x34, 0x1b, 0xfd, 0xae, 0x28, 0x51, 0xa6, 0x30, 0x0e, 0x2b, - 0x8a, 0x20, 0xd0, 0x96, 0x15, 0x89, 0xf3, 0x59, 0x14, 0x36, 0xdf, 0x4f, 0x32, 0xaa, 0xd9, 0xee, - 0x14, 0x5c, 0xbf, 0xfe, 0x96, 0x26, 0x73, 0xb0, 0x80, 0x9d, 0x40, 0x2b, 0xa2, 0x3b, 0x29, 0x1f, - 0x69, 0xba, 0x89, 0xe8, 0xe9, 0x1b, 0xaf, 0xe8, 0x29, 0x61, 0x24, 0x31, 0x57, 0x15, 0xb9, 0x52, - 0x63, 0x51, 0x3f, 0xe7, 0xf0, 0xa6, 0xea, 0x07, 0x65, 0x9d, 0xf9, 0xde, 0xf2, 0xaf, 0x35, 0x2f, - 0x34, 0xfe, 0x24, 0xbb, 0xbc, 0x25, 0x1b, 0x8e, 0x8a, 0xf4, 0x7e, 0xcf, 0x60, 0xf5, 0xc2, 0x76, - 0x42, 0x35, 0x3f, 0x4d, 0x2d, 0x2a, 0x60, 0x7f, 0x4f, 0x5e, 0xd1, 0xdf, 0xa7, 0x54, 0x39, 0x21, - 0xfd, 0x2d, 0x5f, 0xcc, 0x03, 0x83, 0xf5, 0xff, 0x9c, 0x85, 0x7a, 0xb2, 0x15, 0x71, 0xa8, 0x25, - 0x1f, 0x52, 0xf2, 0x84, 0x94, 0xc7, 0xa5, 0x89, 0x76, 0x9f, 0xe4, 0x88, 0x79, 0xe3, 0x71, 0x36, - 0xc5, 0x78, 0xac, 0xdb, 0x6c, 0x73, 0xaf, 0xf2, 0x6d, 0xe5, 0x5f, 0xcb, 0xb7, 0x55, 0x48, 0xf3, - 0x6d, 0x5d, 0xef, 0x10, 0x59, 0xf8, 0xb9, 0x1c, 0x22, 0xc5, 0xeb, 0x1d, 0x22, 0xeb, 0x7f, 0x95, - 0x01, 0x36, 0x4f, 0xa9, 0xec, 0x19, 0xd9, 0xc9, 0x5d, 0x3e, 0x92, 0x5c, 0xec, 0x9b, 0xaf, 0x47, - 0xed, 0x6a, 0x83, 0x54, 0x6d, 0xf6, 0x08, 0x96, 0xf4, 0x77, 0xc1, 0xba, 0xaa, 0x52, 0x33, 0x99, - 0x5e, 0x14, 0x2b, 0xb4, 0x9a, 0x63, 0x2f, 0xff, 0x4a, 0xc7, 0x5e, 0xe1, 0x95, 0x8e, 0xbd, 0x85, - 0xa4, 0x63, 0x6f, 0xfd, 0xef, 0x64, 0x60, 0x29, 0x85, 0xa8, 0xbe, 0xba, 0x39, 0x0b, 0x5a, 0x48, - 0xb0, 0x98, 0xac, 0xa4, 0x05, 0x8d, 0xbb, 0xac, 0xff, 0x04, 0x6a, 0x89, 0x43, 0xf4, 0xd5, 0x75, - 0x3f, 0xab, 0x68, 0x11, 0x29, 0xeb, 0x8a, 0xd6, 0xfa, 0x5f, 0x66, 0x81, 0xcd, 0x9f, 0xe3, 0x5f, - 0xe6, 0x10, 0xe6, 0x17, 0x29, 0x37, 0xbf, 0x48, 0xff, 0xff, 0xee, 0x95, 0xf7, 0x60, 0x51, 0xc6, - 0x32, 0x68, 0x4e, 0x11, 0x22, 0x94, 0x66, 0x54, 0xa0, 0x46, 0xf1, 0x9d, 0x59, 0x9f, 0x6a, 0x29, - 0xf1, 0x7c, 0x5b, 0xbb, 0x58, 0x93, 0xae, 0x55, 0x63, 0x1d, 0x5a, 0x72, 0x69, 0xe6, 0x4d, 0x75, - 0xbf, 0x93, 0x8f, 0xb4, 0x64, 0x2c, 0x94, 0x42, 0xf1, 0xb7, 0xa0, 0xaa, 0x5f, 0x36, 0x72, 0x1f, - 0x66, 0xbc, 0x61, 0x42, 0x1c, 0xf6, 0xb4, 0xd3, 0xba, 0x09, 0xe4, 0xe3, 0x18, 0x46, 0xd5, 0x48, - 0x82, 0x78, 0x89, 0x51, 0x1c, 0x85, 0xa3, 0xc4, 0xe6, 0xff, 0x35, 0xa8, 0x27, 0xed, 0x56, 0x52, - 0xd4, 0x4b, 0x93, 0x0e, 0x45, 0xed, 0x84, 0x21, 0x8b, 0x7d, 0x1f, 0x9a, 0xb3, 0x76, 0x2f, 0xf9, - 0xb6, 0xf4, 0x9a, 0xfa, 0x0d, 0x27, 0x69, 0x0a, 0x63, 0x3b, 0xb0, 0x9c, 0x76, 0xdd, 0xe2, 0xae, - 0x5c, 0xaf, 0x16, 0xb0, 0xf9, 0x2b, 0x95, 0x7d, 0x57, 0x9a, 0x37, 0x0b, 0x69, 0x4e, 0x22, 0x6d, - 0xb1, 0x1f, 0xd2, 0x7f, 0x9a, 0xa1, 0xf3, 0x1c, 0x20, 0x86, 0xb1, 0x26, 0x54, 0x0f, 0x0e, 0x3b, - 0xfb, 0xd6, 0xe6, 0x4e, 0x7b, 0x7f, 0xbf, 0xb3, 0xdb, 0xbc, 0xc1, 0x18, 0xd4, 0xd1, 0xbb, 0xb3, - 0x15, 0xc1, 0x32, 0x02, 0x26, 0xcd, 0xcc, 0x0a, 0x96, 0x65, 0xcb, 0xd0, 0xec, 0xee, 0xcf, 0x40, - 0x73, 0xac, 0x05, 0xcb, 0x87, 0x1d, 0x72, 0x08, 0x25, 0xda, 0xcd, 0x0b, 0x11, 0x4e, 0x4e, 0x57, - 0x88, 0x70, 0x14, 0x09, 0x23, 0xa9, 0x4f, 0x49, 0x36, 0xbf, 0x9b, 0x81, 0x95, 0x99, 0x82, 0xf8, - 0x7d, 0x33, 0xc9, 0x35, 0x49, 0x89, 0xa6, 0x8a, 0x40, 0x45, 0xc3, 0xef, 0xc1, 0x62, 0xa4, 0xea, - 0xcd, 0xf0, 0xa5, 0x66, 0x54, 0xa0, 0x90, 0x1f, 0xc1, 0x92, 0xa6, 0x31, 0xce, 0x9c, 0x50, 0xa6, - 0x15, 0xc9, 0x0a, 0xc6, 0x5a, 0xf4, 0x8e, 0x74, 0x66, 0xd4, 0x43, 0x0a, 0xaf, 0xd1, 0x0b, 0x62, - 0xeb, 0x6f, 0x72, 0xbc, 0xea, 0x53, 0xa8, 0xf2, 0x09, 0x42, 0x48, 0x8e, 0x56, 0xdf, 0x70, 0xd5, - 0xfd, 0xef, 0x2f, 0x00, 0xfb, 0x78, 0xca, 0xfd, 0x2b, 0x7c, 0xbf, 0x1c, 0xbc, 0xea, 0x41, 0x8f, - 0x52, 0x8b, 0xb2, 0xaf, 0x15, 0xa3, 0x90, 0x16, 0x23, 0x90, 0x7f, 0x75, 0x8c, 0x40, 0xe1, 0x55, - 0x31, 0x02, 0x6f, 0x43, 0xcd, 0x39, 0x75, 0x3d, 0xc1, 0x80, 0x84, 0x6c, 0x12, 0xb4, 0x16, 0xee, - 0xe6, 0xee, 0x57, 0xcd, 0xaa, 0x04, 0x0a, 0xc9, 0x24, 0x60, 0x1f, 0xc5, 0x48, 0x7c, 0x78, 0x8a, - 0xf1, 0x2c, 0x3a, 0xeb, 0xe9, 0x0c, 0x4f, 0xb9, 0xd4, 0x02, 0xd1, 0x2e, 0xa2, 0x2a, 0x0b, 0x78, - 0xc0, 0xde, 0x81, 0x7a, 0xe0, 0x4d, 0x85, 0xa8, 0xa7, 0x96, 0x81, 0xec, 0xc3, 0x55, 0x82, 0x1e, - 0x2a, 0x67, 0xc0, 0xd2, 0x34, 0xe0, 0xd6, 0xd8, 0x09, 0x02, 0x71, 0x41, 0x0f, 0x3c, 0x37, 0xf4, - 0xbd, 0x91, 0x34, 0xf9, 0x2e, 0x4e, 0x03, 0xbe, 0x47, 0x25, 0x9b, 0x54, 0xc0, 0xbe, 0x1d, 0x0f, - 0x69, 0x62, 0x3b, 0x7e, 0xd0, 0x02, 0x1c, 0x92, 0x9a, 0x29, 0x4a, 0x54, 0xb6, 0xe3, 0x47, 0x63, - 0x11, 0x1f, 0xc1, 0x4c, 0xec, 0x42, 0x65, 0x36, 0x76, 0xe1, 0x47, 0xe9, 0xb1, 0x0b, 0x35, 0x6c, - 0xfa, 0xb1, 0x6c, 0x7a, 0x7e, 0x8b, 0xbf, 0x54, 0x08, 0xc3, 0x7c, 0x48, 0x46, 0xfd, 0xcb, 0x84, - 0x64, 0x34, 0xd2, 0x42, 0x32, 0xde, 0x87, 0x0a, 0x3e, 0x96, 0xb7, 0xce, 0x1c, 0x37, 0x54, 0x26, - 0xec, 0xa6, 0xfe, 0x9a, 0x7e, 0x47, 0x28, 0xd3, 0xe0, 0xab, 0x3f, 0x83, 0xf9, 0xe8, 0x88, 0xc5, - 0x5f, 0x62, 0x74, 0x84, 0x7c, 0xd4, 0xff, 0x10, 0x4a, 0x6a, 0x9f, 0x18, 0x83, 0xfc, 0x89, 0xef, - 0x8d, 0x95, 0x69, 0x4f, 0xfc, 0xcd, 0xea, 0x90, 0x0d, 0x3d, 0x59, 0x39, 0x1b, 0x7a, 0xc6, 0x6f, - 0x40, 0x45, 0x23, 0x35, 0xf6, 0x16, 0x19, 0x11, 0x84, 0xb4, 0x2c, 0xb5, 0x64, 0x5a, 0xc5, 0xb2, - 0x84, 0x76, 0x87, 0x82, 0xdf, 0x0c, 0x1d, 0x9f, 0x63, 0x1c, 0x93, 0xe5, 0xf3, 0x73, 0xee, 0x07, - 0xca, 0xd4, 0xda, 0x8c, 0x0a, 0x4c, 0x82, 0x1b, 0x7f, 0x13, 0x96, 0x12, 0x7b, 0x2b, 0x59, 0xc4, - 0x3b, 0xb0, 0x80, 0xeb, 0xa6, 0x5c, 0x61, 0xc9, 0x28, 0x05, 0x59, 0x86, 0x01, 0xaa, 0x64, 0x25, - 0xb6, 0x26, 0xbe, 0x77, 0x8c, 0x9d, 0x64, 0xcc, 0x8a, 0x84, 0x1d, 0xfa, 0xde, 0xb1, 0xf1, 0x67, - 0x39, 0xc8, 0xed, 0x78, 0x13, 0xfd, 0xf5, 0x47, 0x66, 0xee, 0xf5, 0x87, 0x54, 0x01, 0xac, 0x48, - 0xc4, 0x97, 0x52, 0x1b, 0xda, 0x47, 0x95, 0x98, 0x7f, 0x1f, 0xea, 0x82, 0x4f, 0x84, 0x9e, 0xd0, - 0xa1, 0x2e, 0x6c, 0x9f, 0x62, 0x16, 0x72, 0x74, 0xf8, 0xec, 0x71, 0xd8, 0xf7, 0xb6, 0x09, 0xce, - 0x96, 0x21, 0x17, 0x09, 0xb0, 0x58, 0x2c, 0x3e, 0x85, 0x72, 0x8d, 0xaf, 0xf7, 0xae, 0xa4, 0xaf, - 0x47, 0x7e, 0xb1, 0x6f, 0xc2, 0x52, 0xb2, 0x5d, 0x62, 0x45, 0x52, 0x22, 0xd1, 0x1b, 0x46, 0x9e, - 0x74, 0x13, 0x04, 0x1f, 0x21, 0x1c, 0xe9, 0x32, 0x3e, 0xe1, 0x1c, 0x8b, 0x34, 0xa6, 0x57, 0x4a, - 0x30, 0xbd, 0x3b, 0x50, 0x09, 0x47, 0xe7, 0xd6, 0xc4, 0xbe, 0x1a, 0x79, 0xf6, 0x50, 0x9e, 0x6f, - 0x08, 0x47, 0xe7, 0x87, 0x04, 0x61, 0x8f, 0x00, 0xc6, 0x93, 0x89, 0x3c, 0x7b, 0x68, 0x6e, 0x8c, - 0x49, 0x79, 0xef, 0xf0, 0x90, 0x48, 0xce, 0x2c, 0x8f, 0x27, 0x13, 0xfa, 0x93, 0x6d, 0x41, 0x3d, - 0x35, 0xd6, 0xe8, 0xb6, 0x7a, 0x6c, 0xe6, 0x4d, 0x1e, 0xa6, 0x1c, 0xce, 0xda, 0x40, 0x87, 0xad, - 0x7f, 0x1f, 0xd8, 0x2f, 0x18, 0xf1, 0xd3, 0x87, 0x72, 0x34, 0x3e, 0x3d, 0x60, 0x06, 0x9f, 0x8f, - 0x56, 0x12, 0x01, 0x33, 0xed, 0xe1, 0xd0, 0x17, 0x7c, 0x91, 0x2e, 0xcc, 0x88, 0xe5, 0x83, 0x76, - 0x63, 0xb6, 0x89, 0xef, 0x1b, 0x7f, 0x91, 0x81, 0x02, 0x45, 0xef, 0xbc, 0x0b, 0x0d, 0xc2, 0x8f, - 0x5e, 0xd2, 0x48, 0x0f, 0x11, 0xdd, 0xbb, 0x7d, 0xf9, 0x88, 0x46, 0x1c, 0x0b, 0x2d, 0xf2, 0x30, - 0x1b, 0xed, 0xbc, 0x16, 0x7d, 0x78, 0x07, 0xca, 0x51, 0xd7, 0x1a, 0xe9, 0x94, 0x54, 0xcf, 0xec, - 0x4d, 0xc8, 0x9f, 0x79, 0x13, 0xa5, 0x8b, 0x43, 0xbc, 0x92, 0x26, 0xc2, 0xe3, 0xb1, 0x88, 0x3e, - 0x68, 0xf0, 0x52, 0x87, 0x8c, 0x3a, 0x41, 0x32, 0x98, 0x9f, 0xe3, 0x42, 0xca, 0x1c, 0x8f, 0xa0, - 0x21, 0xf8, 0x80, 0xe6, 0xa9, 0xbd, 0xfe, 0xd2, 0xfc, 0xba, 0x90, 0xf0, 0x06, 0xa3, 0xe9, 0x90, - 0xeb, 0x96, 0x10, 0x7c, 0xd6, 0x21, 0xe1, 0x4a, 0x3d, 0x30, 0x7e, 0x3f, 0x43, 0xfc, 0x45, 0xb4, - 0xcb, 0xee, 0x43, 0x5e, 0xdc, 0x6f, 0x33, 0x96, 0xba, 0xe8, 0x1d, 0xaf, 0xc0, 0x33, 0x11, 0x03, - 0xc3, 0x75, 0xa7, 0xe3, 0x64, 0xeb, 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0x31, 0xe1, 0x6b, 0x6a, - 0x5a, 0x33, 0x8a, 0x38, 0xcd, 0x3e, 0x3a, 0xa6, 0x0f, 0xb5, 0xf7, 0x21, 0xf9, 0xc4, 0x8d, 0xa9, - 0xa4, 0xc0, 0xe1, 0x29, 0xd7, 0xde, 0x85, 0xfc, 0x61, 0x16, 0x6a, 0x89, 0x11, 0xe1, 0x03, 0x19, - 0x71, 0x01, 0x90, 0x15, 0x58, 0xee, 0x37, 0x08, 0x90, 0x14, 0xd4, 0xb5, 0x75, 0xca, 0x26, 0xd6, - 0x29, 0xf2, 0x49, 0xe7, 0x74, 0x9f, 0xf4, 0x63, 0x28, 0xc7, 0x11, 0xa7, 0xc9, 0x21, 0x89, 0xfe, - 0xd4, 0x6b, 0xe6, 0x18, 0x29, 0xf6, 0x62, 0x17, 0x74, 0x2f, 0xf6, 0xf7, 0x34, 0xa7, 0xe7, 0x02, - 0x36, 0x63, 0xa4, 0xad, 0xe8, 0x2f, 0xc5, 0xe5, 0x69, 0x7c, 0x04, 0x15, 0x6d, 0xf0, 0xba, 0x73, - 0x33, 0x93, 0x70, 0x6e, 0x46, 0x71, 0x07, 0xd9, 0x38, 0xee, 0xc0, 0xf8, 0xad, 0x2c, 0xd4, 0xc4, - 0xf9, 0x72, 0xdc, 0xd3, 0x43, 0x6f, 0xe4, 0x0c, 0xd0, 0x2a, 0x1c, 0x9d, 0x30, 0x29, 0x68, 0xa9, - 0x73, 0x26, 0x8f, 0x18, 0xc9, 0x59, 0x7a, 0x78, 0x15, 0x31, 0xe9, 0x28, 0xbc, 0xca, 0x80, 0x9a, - 0x60, 0x8c, 0xc7, 0x76, 0xc0, 0xb5, 0x78, 0x58, 0xb3, 0x72, 0xc2, 0xf9, 0x86, 0x1d, 0x10, 0x87, - 0xfc, 0x26, 0x2c, 0x09, 0x1c, 0x8c, 0x2c, 0x19, 0x3b, 0xa3, 0x91, 0x43, 0x98, 0x64, 0x6a, 0x68, - 0x9e, 0x70, 0x6e, 0xda, 0x21, 0xdf, 0x13, 0x05, 0x32, 0x7c, 0xb6, 0x34, 0x74, 0x02, 0xfb, 0x38, - 0x7e, 0xc6, 0x14, 0x7d, 0xa3, 0x2f, 0xc7, 0xbe, 0xd4, 0x7c, 0x39, 0x14, 0x62, 0x56, 0x19, 0xdb, - 0x97, 0x91, 0x2f, 0x67, 0x86, 0x92, 0x8a, 0xb3, 0x94, 0x64, 0xfc, 0xb7, 0x2c, 0x54, 0x34, 0xb2, - 0x7c, 0x9d, 0xdb, 0xf5, 0xf6, 0x9c, 0x15, 0xbf, 0xac, 0x1b, 0xec, 0xdf, 0x4e, 0x76, 0x89, 0x2e, - 0x5f, 0x0a, 0xd4, 0xd5, 0x08, 0xf8, 0x16, 0x94, 0xc5, 0xa9, 0x7b, 0x1f, 0x8d, 0x62, 0x32, 0xcc, - 0x1c, 0x01, 0x87, 0xd3, 0x63, 0x55, 0xf8, 0x04, 0x0b, 0x0b, 0x71, 0xe1, 0x13, 0x51, 0xf8, 0xb2, - 0xb7, 0x8b, 0xdf, 0x81, 0xaa, 0x6c, 0x15, 0xf7, 0x14, 0xa7, 0x1b, 0x9f, 0xfa, 0xc4, 0x7e, 0x9b, - 0x15, 0xea, 0x8e, 0x36, 0x5f, 0x56, 0x7c, 0xa2, 0x2a, 0x96, 0x5e, 0x55, 0xf1, 0x09, 0x7d, 0x18, - 0xdb, 0xd1, 0x73, 0x50, 0x7c, 0x6e, 0xa0, 0xf8, 0xd8, 0x23, 0x58, 0x52, 0xec, 0x6a, 0xea, 0xda, - 0xae, 0xeb, 0x4d, 0xdd, 0x01, 0x57, 0x01, 0x09, 0x4c, 0x16, 0x1d, 0xc5, 0x25, 0xc6, 0x30, 0x8a, - 0x58, 0xa3, 0x67, 0x0b, 0x0f, 0xa0, 0x40, 0x72, 0x39, 0x09, 0x1f, 0xe9, 0x8c, 0x8b, 0x50, 0xd8, - 0x7d, 0x28, 0x90, 0x78, 0x9e, 0xbd, 0x96, 0xd9, 0x10, 0x82, 0xf1, 0x10, 0x1a, 0x28, 0x62, 0x6a, - 0x1c, 0xf7, 0x65, 0x52, 0x89, 0xb1, 0x0c, 0x6c, 0x9f, 0x0e, 0x91, 0xfe, 0x9c, 0xe6, 0x7f, 0xe6, - 0xa0, 0xa2, 0x81, 0x05, 0x5b, 0xc4, 0x07, 0x18, 0xd6, 0xd0, 0xb1, 0xc7, 0x5c, 0xf9, 0x1e, 0x6a, - 0x66, 0x0d, 0xa1, 0x5b, 0x12, 0x28, 0x2e, 0x05, 0xfb, 0xfc, 0xd4, 0xf2, 0xa6, 0xa1, 0x35, 0xe4, - 0xa7, 0x3e, 0xe7, 0x52, 0x58, 0xaa, 0xda, 0xe7, 0xa7, 0x07, 0xd3, 0x70, 0x0b, 0x61, 0x02, 0x4b, - 0x10, 0xb5, 0x86, 0x25, 0xdf, 0x0c, 0x8c, 0xed, 0xcb, 0x18, 0x4b, 0x3e, 0x5c, 0xa1, 0x25, 0xca, - 0x47, 0x0f, 0x57, 0x48, 0x6d, 0x99, 0xe5, 0xe4, 0x85, 0x79, 0x4e, 0xfe, 0x6d, 0x58, 0x25, 0x4e, - 0x2e, 0x79, 0x84, 0x35, 0x43, 0x52, 0xcb, 0x58, 0x2a, 0x27, 0xa9, 0xc9, 0x5f, 0x4d, 0x31, 0x03, - 0x75, 0x3e, 0x02, 0xe7, 0xc7, 0x74, 0xa2, 0x32, 0xa6, 0x98, 0x99, 0x6c, 0xbc, 0xe7, 0xfc, 0x98, - 0x0b, 0x4c, 0x74, 0x8c, 0xea, 0x98, 0xf2, 0x89, 0xec, 0xd8, 0x71, 0x67, 0x31, 0xed, 0xcb, 0x24, - 0x66, 0x59, 0x62, 0xda, 0x97, 0x3a, 0xe6, 0x53, 0x58, 0x1b, 0xf3, 0xa1, 0x63, 0x27, 0x9b, 0xb5, - 0x62, 0x09, 0x62, 0x99, 0x8a, 0xb5, 0x3a, 0x3d, 0xd2, 0x20, 0xc5, 0x6a, 0xfc, 0xd8, 0x1b, 0x1f, - 0x3b, 0x74, 0x79, 0x92, 0xab, 0x36, 0x6f, 0xd6, 0xdd, 0xe9, 0xf8, 0x87, 0x08, 0x16, 0x55, 0x02, - 0xa3, 0x06, 0x95, 0x5e, 0xe8, 0x4d, 0xd4, 0x36, 0xd7, 0xa1, 0x4a, 0x9f, 0x32, 0xdc, 0xe4, 0x16, - 0xdc, 0x44, 0xda, 0xec, 0x7b, 0x13, 0x6f, 0xe4, 0x9d, 0x5e, 0x25, 0x0c, 0x4a, 0xff, 0x23, 0x03, - 0x4b, 0x89, 0x52, 0x79, 0xce, 0xbf, 0x4d, 0x07, 0x2b, 0x8a, 0x19, 0x20, 0x72, 0x5e, 0xd4, 0x2e, - 0x1f, 0x42, 0xa4, 0x53, 0xa5, 0xe2, 0x08, 0xda, 0x71, 0xac, 0xab, 0xaa, 0x48, 0xb4, 0xdd, 0x9a, - 0xa7, 0x6d, 0x59, 0x5f, 0x45, 0xc1, 0xaa, 0x26, 0xfe, 0xba, 0x7c, 0xc6, 0x3c, 0x94, 0x53, 0xce, - 0x25, 0x1f, 0x6a, 0xea, 0xc6, 0x27, 0x35, 0x82, 0xd8, 0x22, 0x15, 0x18, 0xff, 0x36, 0x03, 0x10, - 0x8f, 0x0e, 0x9f, 0x8a, 0x46, 0x17, 0x28, 0xa5, 0x91, 0xd1, 0x2e, 0xcb, 0xb7, 0xa0, 0x1a, 0xbd, - 0x18, 0x8b, 0xaf, 0xe4, 0x8a, 0x82, 0x89, 0x7b, 0xf9, 0x1e, 0x34, 0x4e, 0x47, 0xde, 0x31, 0x8a, - 0x4e, 0xf2, 0x02, 0xa5, 0xa0, 0x9b, 0x3a, 0x81, 0xd5, 0xb5, 0x18, 0x5f, 0xe0, 0xf9, 0xd4, 0x47, - 0x65, 0xfa, 0x75, 0x6c, 0xfc, 0x76, 0x36, 0x7a, 0x3a, 0x13, 0xaf, 0xc4, 0xcb, 0xf5, 0x8c, 0x9f, - 0xc7, 0x03, 0xfb, 0x32, 0xcf, 0xc3, 0x47, 0x50, 0xf7, 0x89, 0x3b, 0x2a, 0xd6, 0x99, 0x7f, 0x09, - 0xeb, 0xac, 0xf9, 0x89, 0x2b, 0xf7, 0xeb, 0xd0, 0xb4, 0x87, 0xe7, 0xdc, 0x0f, 0x1d, 0x34, 0xd6, - 0xa2, 0xa0, 0x26, 0x1f, 0xab, 0x68, 0x70, 0x94, 0x88, 0xee, 0x41, 0x43, 0x86, 0x40, 0x45, 0x98, - 0x32, 0xa9, 0x42, 0x0c, 0x16, 0x88, 0xc6, 0x7f, 0x50, 0x6f, 0x75, 0x92, 0xbb, 0xfb, 0xf2, 0x55, - 0xd1, 0x67, 0x98, 0x9d, 0xf7, 0xad, 0x48, 0x42, 0x92, 0x36, 0x60, 0xc9, 0x8f, 0x08, 0x28, 0x2d, - 0xc0, 0xc9, 0x65, 0xcd, 0xbf, 0xce, 0xb2, 0x1a, 0x7f, 0x9c, 0x81, 0xe2, 0x8e, 0x37, 0x11, 0x7a, - 0xb9, 0x90, 0xe7, 0xf0, 0x98, 0x44, 0xe1, 0x87, 0x0b, 0xe2, 0xb3, 0x3b, 0x7c, 0x79, 0xc8, 0x40, - 0xaa, 0xbc, 0x51, 0x4b, 0xca, 0x1b, 0xdf, 0x83, 0x5b, 0xe8, 0x8d, 0xf0, 0xbd, 0x89, 0xe7, 0x8b, - 0xa3, 0x6a, 0x8f, 0x48, 0xee, 0xf0, 0xdc, 0xf0, 0x4c, 0xf1, 0xce, 0x9b, 0x27, 0x9c, 0x1f, 0x6a, - 0x18, 0x7b, 0x11, 0x02, 0xc6, 0xd2, 0x8c, 0xc2, 0x73, 0x8b, 0x54, 0x45, 0x29, 0x18, 0x11, 0x47, - 0x6d, 0x88, 0x82, 0x0e, 0xc2, 0x51, 0x34, 0x32, 0xbe, 0x0b, 0xe5, 0xc8, 0xea, 0xc0, 0xde, 0x83, - 0xf2, 0x99, 0x37, 0x91, 0xa6, 0x89, 0x4c, 0x22, 0xac, 0x42, 0xce, 0xda, 0x2c, 0x9d, 0xd1, 0x1f, - 0x81, 0xf1, 0x67, 0x45, 0x28, 0x76, 0xdd, 0x73, 0xcf, 0x19, 0xe0, 0x6b, 0x9f, 0x31, 0x1f, 0x7b, - 0x2a, 0x0e, 0x53, 0xfc, 0x8d, 0x1e, 0xfd, 0x38, 0x35, 0x42, 0x4e, 0x7a, 0xf4, 0xa3, 0xa4, 0x08, - 0x2b, 0xb0, 0xe0, 0xeb, 0xb9, 0x0d, 0x0a, 0x3e, 0xbe, 0x3f, 0x8c, 0x94, 0xb6, 0x82, 0x16, 0xc7, - 0x2a, 0xda, 0xa2, 0x98, 0x7b, 0x5c, 0x32, 0x8a, 0x8b, 0x29, 0x23, 0x04, 0x17, 0xec, 0x0d, 0x28, - 0xca, 0x28, 0x06, 0x7a, 0x13, 0x4e, 0x0f, 0x06, 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0xe4, 0x4d, 0x8a, - 0x24, 0x2a, 0xa1, 0xa7, 0x4b, 0xe0, 0x96, 0xa0, 0xb5, 0x3b, 0x50, 0x21, 0x7c, 0x42, 0x29, 0xc9, - 0xf7, 0x39, 0x08, 0x42, 0x84, 0x94, 0x14, 0x21, 0xe5, 0xd4, 0x14, 0x21, 0xf8, 0x9c, 0x2b, 0xe2, - 0xb2, 0x34, 0x45, 0xa0, 0xc4, 0x10, 0x1a, 0x5c, 0xe5, 0xc7, 0x91, 0xca, 0x3d, 0x85, 0x89, 0x29, - 0xe5, 0xfe, 0x6d, 0xa8, 0x9d, 0xd8, 0xa3, 0xd1, 0xb1, 0x3d, 0x78, 0x41, 0x3a, 0x69, 0x95, 0xcc, - 0x70, 0x0a, 0x88, 0x4a, 0xe9, 0x1d, 0xa8, 0x68, 0xbb, 0x8c, 0x8f, 0x6f, 0xf2, 0x26, 0xc4, 0xfb, - 0x3b, 0x6b, 0x6a, 0xaa, 0xbf, 0x86, 0xa9, 0x49, 0x7b, 0x84, 0xd4, 0x48, 0x3e, 0x42, 0xba, 0x85, - 0xdc, 0x54, 0x3e, 0x54, 0x69, 0x52, 0x16, 0x02, 0x7b, 0x38, 0xc4, 0x87, 0x2a, 0x94, 0xf2, 0x0b, - 0x17, 0x8f, 0xca, 0x17, 0x49, 0xa8, 0x25, 0x18, 0xa1, 0xdc, 0x26, 0x7b, 0xe9, 0xc4, 0x76, 0x86, - 0xf8, 0xe8, 0x93, 0xd4, 0xd8, 0xa2, 0x3d, 0x0e, 0x0f, 0x6d, 0x67, 0xc8, 0xee, 0x42, 0x55, 0x15, - 0xe3, 0xed, 0xb8, 0x44, 0xeb, 0x2f, 0x8b, 0xc5, 0x9d, 0x68, 0x40, 0x2d, 0xc2, 0x18, 0xc7, 0xb1, - 0x5e, 0x15, 0x89, 0x82, 0x74, 0xf0, 0x3e, 0x3a, 0xff, 0x43, 0x8e, 0x11, 0x5d, 0xf5, 0x27, 0xb7, - 0xe4, 0x5c, 0x25, 0x95, 0xaa, 0xff, 0xf1, 0xa5, 0x83, 0x49, 0x98, 0x42, 0x10, 0x23, 0x17, 0xcd, - 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0xa2, 0x21, 0x04, 0xf6, 0x5d, 0x4d, 0x91, 0x6a, 0x21, 0xf2, - 0x1b, 0x33, 0xed, 0x5f, 0xf7, 0xe6, 0xfd, 0x36, 0x80, 0x13, 0x88, 0x5b, 0x26, 0xe0, 0xee, 0x10, - 0x83, 0xb3, 0x4a, 0x66, 0xd9, 0x09, 0x9e, 0x13, 0xe0, 0xab, 0xd5, 0xb0, 0xda, 0x50, 0xd5, 0xa7, - 0xc9, 0x4a, 0x90, 0x3f, 0x38, 0xec, 0xec, 0x37, 0x6f, 0xb0, 0x0a, 0x14, 0x7b, 0x9d, 0x7e, 0x7f, - 0xb7, 0xb3, 0xd5, 0xcc, 0xb0, 0x2a, 0x94, 0xa2, 0x10, 0x93, 0xac, 0xf8, 0x6a, 0x6f, 0x6e, 0x76, - 0x0e, 0xfb, 0x9d, 0xad, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, 0x99, 0x33, 0xfe, 0x3c, 0x07, 0x15, - 0x6d, 0x15, 0x5e, 0xce, 0x8c, 0x6f, 0x03, 0xa0, 0x4a, 0x13, 0xbf, 0x63, 0xca, 0x9b, 0x65, 0x01, - 0xa1, 0xcd, 0xd7, 0x8d, 0xe5, 0x39, 0x4a, 0x6f, 0xa1, 0x8c, 0xe5, 0x6f, 0x43, 0x8d, 0x32, 0x45, - 0xe8, 0xee, 0xba, 0x82, 0x59, 0x25, 0xa0, 0x64, 0xd5, 0x18, 0xa3, 0x86, 0x48, 0x18, 0xbd, 0x20, - 0xe3, 0xc6, 0x09, 0x84, 0xf1, 0x0b, 0x18, 0x7c, 0x12, 0x78, 0xa3, 0x73, 0x4e, 0x18, 0x24, 0x11, - 0x56, 0x24, 0xac, 0x2f, 0x83, 0xe4, 0x24, 0x3f, 0xd4, 0x82, 0xa4, 0x0a, 0x66, 0x95, 0x80, 0xb2, - 0xa3, 0x6f, 0x2a, 0x02, 0x2a, 0x21, 0x01, 0xad, 0xcd, 0x53, 0x43, 0x82, 0x78, 0x76, 0xe7, 0xec, - 0x59, 0x65, 0x24, 0x8c, 0xaf, 0xcd, 0xd7, 0x7b, 0xb5, 0x5d, 0x8b, 0xbd, 0x07, 0x6c, 0x3c, 0x99, - 0x58, 0x29, 0x96, 0xa6, 0xbc, 0xd9, 0x18, 0x4f, 0x26, 0x7d, 0xcd, 0x10, 0xf3, 0x15, 0x18, 0xc1, - 0x3e, 0x07, 0xd6, 0x16, 0x07, 0x18, 0x87, 0x18, 0x99, 0x50, 0x63, 0xb6, 0x9c, 0xd1, 0xd9, 0x72, - 0x0a, 0xf7, 0xcb, 0xa6, 0x72, 0xbf, 0x97, 0xf1, 0x09, 0x63, 0x1b, 0x2a, 0x87, 0x5a, 0x1e, 0x9a, - 0xbb, 0xe2, 0x86, 0x50, 0x19, 0x68, 0xe8, 0xee, 0x20, 0xe3, 0x96, 0x2f, 0x13, 0xcf, 0x68, 0xa3, - 0xc9, 0x6a, 0xa3, 0x31, 0xfe, 0x4d, 0x86, 0x62, 0xfc, 0xa3, 0xc1, 0xc7, 0xa9, 0x6f, 0x94, 0x1f, - 0x28, 0x8e, 0x65, 0xac, 0x28, 0xff, 0x8f, 0x0c, 0x43, 0xc4, 0xa1, 0x59, 0xde, 0xc9, 0x49, 0xc0, - 0x55, 0x54, 0x4e, 0x05, 0x61, 0x07, 0x08, 0x52, 0xc2, 0xb7, 0x90, 0xf0, 0x1d, 0x6a, 0x3f, 0x90, - 0xd1, 0x39, 0x42, 0xf8, 0xde, 0xb3, 0x2f, 0x65, 0xaf, 0x81, 0x10, 0x41, 0xa4, 0xa1, 0x5a, 0xc5, - 0x22, 0x45, 0xdf, 0xc6, 0xbf, 0x94, 0xe1, 0x96, 0xb3, 0xeb, 0xfb, 0x00, 0x4a, 0x51, 0xab, 0xc9, - 0x1b, 0x56, 0x61, 0x46, 0xe5, 0xe2, 0x1e, 0x47, 0xad, 0x3c, 0x31, 0x62, 0x3a, 0x5c, 0xe8, 0x6c, - 0xe8, 0x6a, 0xa3, 0xfe, 0x06, 0xb0, 0x13, 0xc7, 0x9f, 0x45, 0xa6, 0xc3, 0xd6, 0xc4, 0x12, 0x0d, - 0xdb, 0x38, 0x82, 0x25, 0xc5, 0x25, 0x34, 0x8d, 0x20, 0xb9, 0x79, 0x99, 0x57, 0x30, 0xf9, 0xec, - 0x1c, 0x93, 0x37, 0x7e, 0x9a, 0x87, 0xa2, 0xca, 0xe9, 0x94, 0x96, 0x87, 0xa8, 0x9c, 0xcc, 0x43, - 0xd4, 0x4a, 0xe4, 0xac, 0xc0, 0xad, 0x97, 0xf7, 0xfd, 0xbd, 0xd9, 0x2b, 0x5b, 0x33, 0x9a, 0x27, - 0xae, 0xed, 0x55, 0xc8, 0x4f, 0xec, 0xf0, 0x0c, 0x0d, 0x64, 0x44, 0x3c, 0xf8, 0xad, 0x8c, 0xe9, - 0x85, 0xa4, 0x31, 0x3d, 0x2d, 0x67, 0x13, 0x89, 0xa4, 0x73, 0x39, 0x9b, 0x6e, 0x01, 0xc9, 0x17, - 0xda, 0x7b, 0x98, 0x12, 0x02, 0xc4, 0x5d, 0x94, 0x14, 0x47, 0x4a, 0xb3, 0xe2, 0xc8, 0x6b, 0x8b, - 0x0a, 0xdf, 0x86, 0x05, 0x8a, 0x77, 0x96, 0x31, 0x57, 0xea, 0x42, 0x91, 0x6b, 0xa8, 0xfe, 0xa7, - 0x47, 0xb0, 0xa6, 0xc4, 0xd5, 0x13, 0xa0, 0x54, 0x12, 0x09, 0x50, 0x74, 0x23, 0x7f, 0x35, 0x69, - 0xe4, 0xbf, 0x0f, 0xcd, 0x68, 0x41, 0xd1, 0x64, 0xe6, 0x06, 0x32, 0xa2, 0xa3, 0xae, 0xe0, 0x82, - 0x4b, 0xee, 0x07, 0xf1, 0x85, 0x58, 0x4f, 0x5c, 0x88, 0x82, 0x87, 0xb5, 0xc3, 0x90, 0x8f, 0x27, - 0xa1, 0xbc, 0x10, 0xf1, 0xcd, 0xb7, 0x3e, 0xc0, 0x64, 0x34, 0x62, 0x0d, 0xca, 0xdd, 0x7d, 0x6b, - 0x7b, 0xb7, 0xfb, 0x6c, 0xa7, 0xdf, 0xcc, 0x88, 0xcf, 0xde, 0xd1, 0xe6, 0x66, 0xa7, 0xb3, 0x85, - 0x37, 0x0e, 0xc0, 0xc2, 0x76, 0xbb, 0x2b, 0x6e, 0x9f, 0x9c, 0xf1, 0xbb, 0x59, 0xa8, 0x68, 0xcd, - 0xb3, 0xa7, 0xd1, 0xaa, 0x50, 0x8e, 0x8c, 0xdb, 0xf3, 0x43, 0x78, 0xa8, 0x58, 0xb1, 0xb6, 0x2c, - 0x51, 0x86, 0xaa, 0xec, 0xb5, 0x19, 0xaa, 0xd8, 0xbb, 0xd0, 0xb0, 0xa9, 0x85, 0x68, 0x15, 0xa4, - 0x39, 0x58, 0x82, 0xe5, 0x22, 0xe0, 0x2b, 0xb0, 0xf8, 0x3e, 0x11, 0x78, 0x79, 0xf5, 0xf0, 0x2a, - 0xba, 0x52, 0x70, 0xb1, 0x8a, 0x27, 0xb6, 0x33, 0x9a, 0xfa, 0x5c, 0xba, 0x6f, 0xa3, 0x9b, 0x99, - 0xa0, 0xa6, 0x2a, 0x36, 0x3e, 0x00, 0x88, 0xc7, 0x9c, 0x5c, 0x9c, 0x1b, 0xc9, 0xc5, 0xc9, 0x68, - 0x8b, 0x93, 0x35, 0xb6, 0x88, 0x8d, 0xc8, 0x85, 0x8e, 0x3c, 0xd5, 0xdf, 0x04, 0x65, 0x91, 0xb2, - 0xf0, 0x1d, 0xe6, 0x64, 0xc4, 0x43, 0x15, 0xb7, 0xb9, 0x28, 0x4b, 0xba, 0x51, 0x81, 0x0a, 0xa3, - 0x8e, 0x5b, 0x89, 0xb9, 0x91, 0x24, 0xc9, 0x59, 0x6e, 0x24, 0x51, 0xcd, 0xa8, 0xdc, 0x58, 0x87, - 0xd6, 0x16, 0x17, 0xad, 0xb5, 0x47, 0xa3, 0x99, 0xe1, 0x18, 0xb7, 0xe0, 0x66, 0x4a, 0x99, 0x34, - 0x42, 0x7c, 0x0c, 0x2b, 0x6d, 0x0a, 0xd1, 0xfc, 0xaa, 0x62, 0x31, 0x8c, 0x16, 0xac, 0xce, 0x36, - 0x29, 0x3b, 0xdb, 0x86, 0xc5, 0x2d, 0x7e, 0x3c, 0x3d, 0xdd, 0xe5, 0xe7, 0x71, 0x47, 0x0c, 0xf2, - 0xc1, 0x99, 0x77, 0x21, 0xd7, 0x07, 0xff, 0x16, 0x67, 0x78, 0x24, 0x70, 0xac, 0x60, 0xc2, 0x07, - 0xca, 0x22, 0x8a, 0x90, 0xde, 0x84, 0x0f, 0x8c, 0xa7, 0xc0, 0xf4, 0x76, 0xe4, 0x7a, 0x09, 0x2d, - 0x61, 0x7a, 0x6c, 0x05, 0x57, 0x41, 0xc8, 0xc7, 0x2a, 0x05, 0x0b, 0x04, 0xd3, 0xe3, 0x1e, 0x41, - 0x8c, 0x7b, 0x50, 0x3d, 0xb4, 0xaf, 0x4c, 0xfe, 0xb9, 0x8c, 0x32, 0x58, 0x83, 0xe2, 0xc4, 0xbe, - 0x12, 0x6c, 0x20, 0x72, 0x8e, 0x60, 0xb1, 0xf1, 0x07, 0x79, 0x58, 0x20, 0x4c, 0x76, 0x97, 0xb2, - 0x24, 0x3a, 0x2e, 0x1e, 0x43, 0xc5, 0x28, 0x35, 0xd0, 0x1c, 0x2f, 0xcd, 0xce, 0xf3, 0x52, 0x69, - 0x40, 0x53, 0xd9, 0x21, 0x94, 0x19, 0xdb, 0x9d, 0x8e, 0x55, 0x4a, 0x88, 0x64, 0x9c, 0x62, 0x3e, - 0xce, 0x82, 0x49, 0x41, 0x5c, 0x49, 0x47, 0x63, 0xac, 0x8b, 0xd0, 0xe8, 0xd4, 0x15, 0x21, 0xd9, - 0xa5, 0x0e, 0x4a, 0x55, 0x78, 0x8a, 0x2a, 0x7e, 0x25, 0xa9, 0xf0, 0xcc, 0x29, 0x36, 0xa5, 0x57, - 0x2b, 0x36, 0x64, 0x59, 0x7b, 0x89, 0x62, 0x03, 0xaf, 0xa1, 0xd8, 0xbc, 0x86, 0x93, 0xef, 0x26, - 0x94, 0xf0, 0xde, 0xd7, 0xb8, 0xa7, 0xb8, 0xef, 0x05, 0xf7, 0xfc, 0x8e, 0x26, 0xfa, 0xd3, 0x0b, - 0x83, 0x5b, 0xf1, 0x31, 0x31, 0xf9, 0xe7, 0xbf, 0x1c, 0xe7, 0xc9, 0x67, 0x50, 0x94, 0x50, 0x41, - 0xd0, 0xae, 0x3d, 0x56, 0x09, 0x76, 0xf0, 0x6f, 0xb1, 0x6c, 0x98, 0x15, 0xe4, 0xf3, 0xa9, 0xe3, - 0xf3, 0xa1, 0x4a, 0xc1, 0xe0, 0xe0, 0x19, 0x15, 0x10, 0x31, 0x41, 0xa1, 0x86, 0xb8, 0xde, 0x85, - 0x2b, 0x03, 0xb0, 0x8b, 0x4e, 0xf0, 0x5c, 0x7c, 0x1a, 0x0c, 0x9a, 0x98, 0x62, 0x6b, 0xe2, 0xf9, - 0xea, 0x72, 0x32, 0x7e, 0x9a, 0x81, 0xa6, 0x3c, 0x5d, 0x51, 0x99, 0xae, 0x05, 0x14, 0xae, 0x73, - 0x88, 0xbf, 0x3c, 0xa1, 0x82, 0x01, 0x35, 0x34, 0x7e, 0x44, 0x37, 0x15, 0x19, 0x6f, 0x2a, 0x02, - 0xb8, 0x2d, 0x6f, 0xab, 0x37, 0xa1, 0xa2, 0x9e, 0x63, 0x8e, 0x9d, 0x91, 0x4a, 0x78, 0x4b, 0xef, - 0x31, 0xf7, 0x9c, 0x91, 0xba, 0xe8, 0x7c, 0x5b, 0xc6, 0x53, 0x65, 0xf0, 0xa2, 0x33, 0xed, 0x90, - 0x1b, 0xff, 0x25, 0x03, 0x8b, 0xda, 0x54, 0xe4, 0xb9, 0xfd, 0x10, 0xaa, 0x51, 0x6e, 0x3b, 0x1e, - 0x49, 0x5e, 0x6b, 0x49, 0x46, 0x13, 0x57, 0xab, 0x0c, 0x22, 0x48, 0x20, 0x06, 0x33, 0xb4, 0xaf, - 0x70, 0xbc, 0xc1, 0x74, 0xac, 0x94, 0x9b, 0xa1, 0x7d, 0xb5, 0xcd, 0x79, 0x6f, 0x3a, 0x16, 0xaa, - 0xeb, 0x05, 0xe7, 0x2f, 0x22, 0x04, 0x92, 0xb9, 0x40, 0xc0, 0x24, 0x86, 0x01, 0xb5, 0xb1, 0xe7, - 0x86, 0x67, 0x11, 0x8a, 0x94, 0x3a, 0x11, 0x48, 0x38, 0xc6, 0x9f, 0x66, 0x61, 0x89, 0x4c, 0x6c, - 0xd2, 0xb4, 0x29, 0x59, 0x57, 0x0b, 0x16, 0xc8, 0xda, 0x48, 0xcc, 0x6b, 0xe7, 0x86, 0x29, 0xbf, - 0xd9, 0xb7, 0x5f, 0xd3, 0x2c, 0xa8, 0x42, 0xb6, 0xae, 0x59, 0xfe, 0xdc, 0xfc, 0xf2, 0x5f, 0xbf, - 0xbc, 0x69, 0x1e, 0xb7, 0x42, 0x9a, 0xc7, 0xed, 0x75, 0xfc, 0x5c, 0x73, 0x71, 0x4d, 0x45, 0x89, - 0xa3, 0xc5, 0x35, 0x3d, 0x85, 0xb5, 0x04, 0x0e, 0x72, 0x6b, 0xe7, 0xc4, 0xe1, 0x2a, 0xbe, 0x7d, - 0x59, 0xc3, 0xee, 0xa9, 0xb2, 0x8d, 0x22, 0x14, 0x82, 0x81, 0x37, 0xe1, 0xc6, 0x2a, 0x2c, 0x27, - 0x57, 0x55, 0x5e, 0x13, 0xbf, 0x97, 0x81, 0x96, 0x7c, 0x1f, 0xe1, 0xb8, 0xa7, 0x3b, 0x4e, 0x10, - 0x7a, 0x7e, 0x94, 0x03, 0xee, 0x36, 0x40, 0x10, 0xda, 0xbe, 0xd4, 0x36, 0x65, 0x44, 0x37, 0x42, - 0x50, 0x93, 0xbc, 0x09, 0x25, 0xee, 0x0e, 0xa9, 0x90, 0xa8, 0xa1, 0xc8, 0xdd, 0xa1, 0xd2, 0x43, - 0xe7, 0xe4, 0xef, 0x5a, 0x52, 0xbd, 0x90, 0x01, 0x96, 0x62, 0x75, 0xf8, 0x39, 0x5e, 0xbc, 0xf9, - 0x28, 0xc0, 0x72, 0xcf, 0xbe, 0xc4, 0xd7, 0x86, 0x81, 0xf1, 0xcf, 0xb2, 0xd0, 0x88, 0xc7, 0x47, - 0xd1, 0xd9, 0x2f, 0x8f, 0x33, 0xbf, 0x2b, 0xc9, 0xc1, 0x11, 0xf2, 0xbb, 0x66, 0x78, 0x2c, 0xd1, - 0xe1, 0xec, 0xba, 0xcc, 0x80, 0x8a, 0xc2, 0xf0, 0xa6, 0xa1, 0x96, 0x8a, 0xa9, 0x4c, 0x28, 0x07, - 0xd3, 0x50, 0x28, 0x5c, 0x42, 0xf3, 0x74, 0x5c, 0xa9, 0xf2, 0x14, 0xec, 0x71, 0xd8, 0xc5, 0x0c, - 0xcf, 0x02, 0x2c, 0xaa, 0xd1, 0x46, 0x0a, 0x2c, 0x81, 0xdf, 0x24, 0x39, 0x9b, 0x76, 0x0e, 0x65, - 0x6c, 0x5d, 0x08, 0xa5, 0x64, 0x97, 0x91, 0x10, 0xfa, 0x26, 0x54, 0xa8, 0xf1, 0x38, 0x8c, 0x2d, - 0x6f, 0x96, 0xb1, 0x07, 0x2c, 0x97, 0x46, 0x20, 0x6f, 0x9a, 0x50, 0x7d, 0x81, 0xba, 0xc2, 0xe7, - 0x07, 0xff, 0x28, 0x03, 0x37, 0x53, 0xb6, 0x4d, 0x9e, 0xf2, 0x4d, 0x58, 0x3c, 0x89, 0x0a, 0xd5, - 0xea, 0xd2, 0x51, 0x5f, 0x55, 0x6c, 0x35, 0xb9, 0xa6, 0x66, 0xf3, 0x24, 0x09, 0x88, 0x95, 0x2e, - 0xda, 0xc1, 0x44, 0xa4, 0x22, 0x2a, 0x5d, 0xb4, 0x8d, 0xa4, 0xef, 0x1c, 0xc2, 0x7a, 0xe7, 0x52, - 0x70, 0x8c, 0x4d, 0x3d, 0x45, 0xb9, 0x22, 0xa3, 0xa4, 0x81, 0x39, 0xf3, 0x5a, 0x06, 0xe6, 0x21, - 0x05, 0x64, 0x45, 0x6d, 0xfd, 0x3c, 0x8d, 0xe0, 0x05, 0x2a, 0xea, 0x50, 0x8a, 0x75, 0x15, 0x2d, - 0x39, 0x88, 0x52, 0xab, 0x1b, 0x01, 0x34, 0xf6, 0xa6, 0xa3, 0xd0, 0x89, 0xb3, 0xad, 0xb3, 0x6f, - 0xcb, 0x3a, 0xd8, 0x8f, 0x5a, 0xb5, 0xd4, 0x8e, 0x20, 0xea, 0x08, 0x17, 0x6b, 0x2c, 0x1a, 0xb2, - 0xe6, 0xfb, 0x6b, 0x8c, 0x93, 0x3d, 0x18, 0x37, 0x61, 0x2d, 0xfe, 0xa2, 0x65, 0x53, 0x57, 0xcd, - 0xbf, 0xce, 0xd0, 0xd3, 0xe6, 0x64, 0xe6, 0x77, 0xd6, 0x81, 0xa5, 0xc0, 0x71, 0x4f, 0x47, 0x5c, - 0x6f, 0x3e, 0x90, 0x8b, 0xb0, 0x92, 0x1c, 0x9b, 0xcc, 0x0e, 0x6f, 0x2e, 0x52, 0x8d, 0xb8, 0xb5, - 0x80, 0x6d, 0x5c, 0x37, 0xc8, 0x98, 0x2c, 0x66, 0x56, 0x63, 0x7e, 0xf0, 0x5d, 0xa8, 0x27, 0x3b, - 0x62, 0xdf, 0x91, 0xc1, 0x88, 0xf1, 0xa8, 0x72, 0x33, 0x71, 0x65, 0x31, 0x41, 0x54, 0xe2, 0xb5, - 0x0f, 0x8c, 0x7f, 0x92, 0x81, 0x96, 0xc9, 0x05, 0xe5, 0x6a, 0xa3, 0x54, 0x34, 0xf3, 0xe1, 0x5c, - 0xab, 0xd7, 0xcf, 0x55, 0xc5, 0x38, 0xaa, 0x11, 0x7d, 0xe3, 0xda, 0xcd, 0xd8, 0xb9, 0x31, 0x37, - 0xa3, 0x8d, 0x12, 0x2c, 0x10, 0x8a, 0xb1, 0x06, 0x2b, 0x72, 0x3c, 0x6a, 0x2c, 0xb1, 0xf7, 0x30, - 0xd1, 0x63, 0xc2, 0x7b, 0xb8, 0x0e, 0x2d, 0x4a, 0xe5, 0xa7, 0x4f, 0x42, 0x56, 0xdc, 0x02, 0xb6, - 0x67, 0x0f, 0x6c, 0xdf, 0xf3, 0xdc, 0x43, 0xee, 0xcb, 0x87, 0xa2, 0x28, 0x61, 0xa2, 0x73, 0x4d, - 0x89, 0xc2, 0xf4, 0xa5, 0x12, 0xd0, 0x79, 0xae, 0x7a, 0x17, 0x43, 0x5f, 0x86, 0x09, 0x4b, 0x1b, - 0xf6, 0x0b, 0xae, 0x5a, 0x52, 0x4b, 0xf4, 0x11, 0x54, 0x26, 0x51, 0xa3, 0x6a, 0xdd, 0x55, 0xc4, - 0xf2, 0x7c, 0xb7, 0xa6, 0x8e, 0x6d, 0x3c, 0x81, 0xe5, 0x64, 0x9b, 0x92, 0x75, 0xac, 0x43, 0x69, - 0x2c, 0x61, 0x72, 0x74, 0xd1, 0xb7, 0xf1, 0x3b, 0x25, 0x28, 0x4a, 0x7d, 0x8e, 0x3d, 0x84, 0xfc, - 0x40, 0xbd, 0x4d, 0x8a, 0x13, 0x61, 0xc8, 0x52, 0xf5, 0xff, 0x26, 0xbe, 0x50, 0x12, 0x78, 0xec, - 0x23, 0xa8, 0x27, 0xbd, 0xa2, 0x33, 0xe1, 0x90, 0x49, 0x77, 0x66, 0x6d, 0x30, 0xe3, 0xff, 0x2a, - 0xc7, 0x97, 0x23, 0xc9, 0x0c, 0xa5, 0x33, 0xed, 0xf6, 0xf4, 0x5c, 0x21, 0x6f, 0x07, 0x67, 0xb6, - 0xf5, 0xe4, 0xe9, 0x07, 0x32, 0x1e, 0xb2, 0x82, 0xc0, 0xde, 0x99, 0xfd, 0xe4, 0xe9, 0x07, 0xb3, - 0x92, 0x34, 0x85, 0xc4, 0xe9, 0x92, 0xf4, 0x32, 0x14, 0x28, 0xd3, 0x1a, 0x3d, 0x32, 0xa1, 0x0f, - 0xf6, 0x18, 0x96, 0xa5, 0xda, 0x6a, 0xc9, 0xe7, 0xc0, 0xc4, 0x05, 0x4b, 0x14, 0x83, 0x23, 0xcb, - 0x7a, 0x58, 0x44, 0xb6, 0xa1, 0x55, 0x58, 0x38, 0x8b, 0xd3, 0xe6, 0xd5, 0x4c, 0xf9, 0x65, 0xfc, - 0x69, 0x01, 0x2a, 0xda, 0xa2, 0xb0, 0x2a, 0x94, 0xcc, 0x4e, 0xaf, 0x63, 0x7e, 0xd2, 0xd9, 0x6a, - 0xde, 0x60, 0xf7, 0xe1, 0x9d, 0xee, 0xfe, 0xe6, 0x81, 0x69, 0x76, 0x36, 0xfb, 0xd6, 0x81, 0x69, - 0xa9, 0x74, 0x2c, 0x87, 0xed, 0xcf, 0xf6, 0x3a, 0xfb, 0x7d, 0x6b, 0xab, 0xd3, 0x6f, 0x77, 0x77, - 0x7b, 0xcd, 0x0c, 0x7b, 0x03, 0x5a, 0x31, 0xa6, 0x2a, 0x6e, 0xef, 0x1d, 0x1c, 0xed, 0xf7, 0x9b, - 0x59, 0x76, 0x07, 0x6e, 0x6d, 0x77, 0xf7, 0xdb, 0xbb, 0x56, 0x8c, 0xb3, 0xb9, 0xdb, 0xff, 0xc4, - 0xea, 0xfc, 0xda, 0x61, 0xd7, 0xfc, 0xac, 0x99, 0x4b, 0x43, 0x10, 0xca, 0xb8, 0x6a, 0x21, 0xcf, - 0x6e, 0xc2, 0x0a, 0x21, 0x50, 0x15, 0xab, 0x7f, 0x70, 0x60, 0xf5, 0x0e, 0x0e, 0xf6, 0x9b, 0x05, - 0xb6, 0x08, 0xb5, 0xee, 0xfe, 0x27, 0xed, 0xdd, 0xee, 0x96, 0x65, 0x76, 0xda, 0xbb, 0x7b, 0xcd, - 0x05, 0xb6, 0x04, 0x8d, 0x59, 0xbc, 0xa2, 0x68, 0x42, 0xe1, 0x1d, 0xec, 0x77, 0x0f, 0xf6, 0xad, - 0x4f, 0x3a, 0x66, 0xaf, 0x7b, 0xb0, 0xdf, 0x2c, 0xb1, 0x55, 0x60, 0xc9, 0xa2, 0x9d, 0xbd, 0xf6, - 0x66, 0xb3, 0xcc, 0x56, 0x60, 0x31, 0x09, 0x7f, 0xde, 0xf9, 0xac, 0x09, 0xac, 0x05, 0xcb, 0x34, - 0x30, 0x6b, 0xa3, 0xb3, 0x7b, 0xf0, 0xa9, 0xb5, 0xd7, 0xdd, 0xef, 0xee, 0x1d, 0xed, 0x35, 0x2b, - 0x98, 0x20, 0xaa, 0xd3, 0xb1, 0xba, 0xfb, 0xbd, 0xa3, 0xed, 0xed, 0xee, 0x66, 0xb7, 0xb3, 0xdf, - 0x6f, 0x56, 0xa9, 0xe7, 0xb4, 0x89, 0xd7, 0x44, 0x05, 0x19, 0x33, 0x60, 0x6d, 0x75, 0x7b, 0xed, - 0x8d, 0xdd, 0xce, 0x56, 0xb3, 0xce, 0x6e, 0xc3, 0xcd, 0x7e, 0x67, 0xef, 0xf0, 0xc0, 0x6c, 0x9b, - 0x9f, 0xa9, 0x98, 0x02, 0x6b, 0xbb, 0xdd, 0xdd, 0x3d, 0x32, 0x3b, 0xcd, 0x06, 0x7b, 0x0b, 0x6e, - 0x9b, 0x9d, 0x8f, 0x8f, 0xba, 0x66, 0x67, 0xcb, 0xda, 0x3f, 0xd8, 0xea, 0x58, 0xdb, 0x9d, 0x76, - 0xff, 0xc8, 0xec, 0x58, 0x7b, 0xdd, 0x5e, 0xaf, 0xbb, 0xff, 0xac, 0xd9, 0x64, 0xef, 0xc0, 0xdd, - 0x08, 0x25, 0x6a, 0x60, 0x06, 0x6b, 0x51, 0xcc, 0x4f, 0x6d, 0xe9, 0x7e, 0xe7, 0xd7, 0xfa, 0xd6, - 0x61, 0xa7, 0x63, 0x36, 0x19, 0x5b, 0x87, 0xd5, 0xb8, 0x7b, 0xea, 0x40, 0xf6, 0xbd, 0x24, 0xca, - 0x0e, 0x3b, 0xe6, 0x5e, 0x7b, 0x5f, 0x6c, 0x70, 0xa2, 0x6c, 0x59, 0x0c, 0x3b, 0x2e, 0x9b, 0x1d, - 0xf6, 0x0a, 0x63, 0x50, 0xd7, 0x76, 0x65, 0xbb, 0x6d, 0x36, 0x57, 0x59, 0x03, 0x2a, 0x7b, 0x87, - 0x87, 0x56, 0xbf, 0xbb, 0xd7, 0x39, 0x38, 0xea, 0x37, 0xd7, 0xd8, 0x0a, 0x34, 0xbb, 0xfb, 0xfd, - 0x8e, 0x29, 0xf6, 0x5a, 0x55, 0xfd, 0x3f, 0x45, 0xb6, 0x0c, 0x0d, 0x35, 0x52, 0x05, 0xfd, 0x59, - 0x91, 0xad, 0x01, 0x3b, 0xda, 0x37, 0x3b, 0xed, 0x2d, 0xb1, 0x70, 0x51, 0xc1, 0xff, 0x2d, 0x4a, - 0x0f, 0xc9, 0x4f, 0x73, 0xd1, 0x65, 0x1d, 0x3f, 0x39, 0x48, 0x26, 0x51, 0xad, 0x6a, 0xc9, 0x4f, - 0x5f, 0x95, 0xde, 0x5c, 0x53, 0xad, 0x72, 0x73, 0xaa, 0xd5, 0x9c, 0xee, 0x5e, 0xd3, 0x65, 0xbf, - 0xb7, 0xa1, 0x36, 0xa6, 0x84, 0xaa, 0x32, 0x71, 0x22, 0xc8, 0xf7, 0x37, 0x04, 0xa4, 0xac, 0x89, - 0x73, 0xf9, 0xbd, 0x0b, 0xf3, 0xf9, 0xbd, 0xd3, 0xe4, 0xfb, 0x85, 0x34, 0xf9, 0xfe, 0x01, 0x2c, - 0x12, 0x6b, 0x72, 0x5c, 0x67, 0xac, 0xb4, 0x66, 0x92, 0x02, 0x1b, 0xc8, 0xa2, 0x08, 0xae, 0xd4, - 0x09, 0xa5, 0x72, 0x48, 0x16, 0x52, 0x94, 0xda, 0x46, 0x42, 0xd3, 0x20, 0xce, 0x11, 0x69, 0x1a, - 0x51, 0x0f, 0xf6, 0x65, 0xdc, 0x43, 0x45, 0xeb, 0x81, 0xe0, 0xd8, 0xc3, 0x03, 0x58, 0xe4, 0x97, - 0xa1, 0x6f, 0x5b, 0xde, 0xc4, 0xfe, 0x7c, 0x8a, 0x2e, 0x5c, 0x1b, 0x75, 0xf8, 0xaa, 0xd9, 0xc0, - 0x82, 0x03, 0x84, 0x6f, 0xd9, 0xa1, 0xfd, 0xe0, 0x0b, 0xa8, 0x68, 0xc9, 0x76, 0xd9, 0x1a, 0x2c, - 0x7d, 0xda, 0xed, 0xef, 0x77, 0x7a, 0x3d, 0xeb, 0xf0, 0x68, 0xe3, 0x79, 0xe7, 0x33, 0x6b, 0xa7, - 0xdd, 0xdb, 0x69, 0xde, 0x10, 0x87, 0x76, 0xbf, 0xd3, 0xeb, 0x77, 0xb6, 0x12, 0xf0, 0x0c, 0x7b, - 0x13, 0xd6, 0x8f, 0xf6, 0x8f, 0x7a, 0x9d, 0x2d, 0x2b, 0xad, 0x5e, 0x56, 0x50, 0xa9, 0x2c, 0x4f, - 0xa9, 0x9e, 0x7b, 0xf0, 0x7d, 0xa8, 0x27, 0x33, 0x40, 0x32, 0x80, 0x85, 0xdd, 0xce, 0xb3, 0xf6, - 0xe6, 0x67, 0x94, 0x42, 0xae, 0xd7, 0x6f, 0xf7, 0xbb, 0x9b, 0x96, 0x4c, 0x19, 0x27, 0x38, 0x42, - 0x86, 0x55, 0xa0, 0xd8, 0xde, 0xdf, 0xdc, 0x39, 0x30, 0x7b, 0xcd, 0xec, 0x83, 0x8f, 0xa0, 0x39, - 0xeb, 0x8f, 0x4a, 0x38, 0xf0, 0x5e, 0xe6, 0xe9, 0x7b, 0xf0, 0xef, 0x73, 0x00, 0x71, 0xc0, 0x80, - 0x60, 0x35, 0x5b, 0xed, 0x7e, 0x7b, 0xf7, 0x40, 0x4c, 0xc3, 0x3c, 0xe8, 0x0b, 0x0e, 0x62, 0x76, - 0x3e, 0x6e, 0xde, 0x48, 0x2d, 0x39, 0x38, 0xec, 0x37, 0x33, 0x62, 0xc5, 0xba, 0xfb, 0xdd, 0x7e, - 0xb7, 0xbd, 0x6b, 0x99, 0x07, 0x47, 0xdd, 0xfd, 0x67, 0x94, 0x1b, 0x0b, 0xb9, 0xec, 0xd1, 0xe1, - 0xb6, 0x79, 0xb0, 0xdf, 0xb7, 0x7a, 0x3b, 0x47, 0xfd, 0x2d, 0xcc, 0xac, 0xb5, 0x69, 0x76, 0x0f, - 0xa9, 0xcd, 0xfc, 0xcb, 0x10, 0x44, 0xd3, 0x05, 0xb1, 0xe6, 0xcf, 0x0e, 0x7a, 0xbd, 0xee, 0xa1, - 0xf5, 0xf1, 0x51, 0xc7, 0xec, 0x76, 0x7a, 0x58, 0x71, 0x21, 0x05, 0x2e, 0xf0, 0x8b, 0x82, 0x37, - 0xf7, 0x77, 0x3f, 0x91, 0xcc, 0x53, 0xa0, 0x96, 0x92, 0x20, 0x81, 0x55, 0x16, 0x3c, 0x45, 0x70, - 0x9f, 0x94, 0x96, 0xe1, 0x9a, 0x32, 0x51, 0xaf, 0x22, 0xf8, 0xea, 0xdc, 0x66, 0x60, 0xb5, 0x6a, - 0x7a, 0x91, 0xa8, 0x85, 0x2c, 0x37, 0xba, 0xa0, 0xb6, 0xb6, 0x4c, 0xac, 0x50, 0x9f, 0x83, 0x0a, - 0xdc, 0x86, 0xd8, 0x28, 0xc1, 0x9e, 0x04, 0x4a, 0x53, 0x7d, 0x88, 0x92, 0xc5, 0x27, 0xbf, 0x9d, - 0x83, 0x3a, 0x05, 0x6f, 0xd1, 0x6f, 0x1d, 0x71, 0x9f, 0xed, 0x41, 0x51, 0xfe, 0x68, 0x16, 0x5b, - 0x89, 0xd2, 0x16, 0xe9, 0x3f, 0xd3, 0xb5, 0xbe, 0x3a, 0x0b, 0x96, 0xe2, 0xd8, 0xd2, 0xdf, 0xfe, - 0x93, 0xbf, 0xfc, 0xa7, 0xd9, 0x1a, 0xab, 0x3c, 0x3a, 0x7f, 0xff, 0xd1, 0x29, 0x77, 0x03, 0xd1, - 0xc6, 0xdf, 0x00, 0x88, 0x7f, 0x0a, 0x8a, 0xb5, 0x22, 0x27, 0xd4, 0xcc, 0xef, 0x64, 0xad, 0xdf, - 0x4c, 0x29, 0x91, 0xed, 0xde, 0xc4, 0x76, 0x97, 0x8c, 0xba, 0x68, 0xd7, 0x71, 0x9d, 0x90, 0x7e, - 0x16, 0xea, 0xc3, 0xcc, 0x03, 0x36, 0x84, 0xaa, 0xfe, 0x23, 0x4d, 0x4c, 0x49, 0x4a, 0x29, 0x3f, - 0x33, 0xb5, 0x7e, 0x2b, 0xb5, 0x4c, 0xc9, 0xa0, 0xd8, 0xc7, 0x8a, 0xd1, 0x14, 0x7d, 0x4c, 0x11, - 0x23, 0xee, 0x65, 0x44, 0x52, 0x79, 0xfc, 0x5b, 0x4c, 0xec, 0x0d, 0x4d, 0xae, 0x9a, 0xfb, 0x25, - 0xa8, 0xf5, 0xdb, 0xd7, 0x94, 0xca, 0xbe, 0x6e, 0x63, 0x5f, 0x6b, 0x06, 0x13, 0x7d, 0x0d, 0x10, - 0x47, 0xfd, 0x12, 0xd4, 0x87, 0x99, 0x07, 0x4f, 0xfe, 0xe2, 0x3e, 0x94, 0xa3, 0xc7, 0x9c, 0xec, - 0x37, 0xa1, 0x96, 0x88, 0xae, 0x63, 0x6a, 0x1a, 0x69, 0xc1, 0x78, 0xeb, 0x6f, 0xa4, 0x17, 0xca, - 0x8e, 0xdf, 0xc4, 0x8e, 0x5b, 0x6c, 0x55, 0x74, 0x2c, 0xa3, 0xd7, 0x1e, 0x61, 0x0c, 0x2a, 0x25, - 0x81, 0x7a, 0xa1, 0x69, 0x1f, 0xd4, 0xd9, 0x1b, 0xb3, 0x1a, 0x41, 0xa2, 0xb7, 0xdb, 0xd7, 0x94, - 0xca, 0xee, 0xde, 0xc0, 0xee, 0x56, 0xd9, 0xb2, 0xde, 0x9d, 0x7a, 0x7a, 0xc9, 0x38, 0x26, 0x5e, - 0xd3, 0x7f, 0xaa, 0x88, 0xdd, 0x8e, 0xd3, 0x64, 0xa5, 0xfc, 0x84, 0x51, 0x44, 0x22, 0xf3, 0xbf, - 0x63, 0x64, 0xb4, 0xb0, 0x2b, 0xc6, 0x70, 0xfb, 0xf4, 0x5f, 0x2a, 0x62, 0xc7, 0x50, 0xd1, 0xb2, - 0xfb, 0xb3, 0x9b, 0xd7, 0xfe, 0x12, 0xc1, 0xfa, 0x7a, 0x5a, 0x51, 0xda, 0x54, 0xf4, 0xf6, 0x1f, - 0x9d, 0x70, 0xce, 0x7e, 0x1d, 0xca, 0x51, 0xce, 0x78, 0xb6, 0xa6, 0xe5, 0xf0, 0xd7, 0x73, 0xdc, - 0xaf, 0xb7, 0xe6, 0x0b, 0xd2, 0x88, 0x4f, 0x6f, 0x5d, 0x10, 0xdf, 0xa7, 0x50, 0xd1, 0xf2, 0xc2, - 0x47, 0x13, 0x98, 0xcf, 0x3d, 0x1f, 0x4d, 0x20, 0x25, 0x8d, 0xbc, 0xb1, 0x88, 0x5d, 0x54, 0x58, - 0x19, 0xe9, 0x3b, 0xbc, 0xf4, 0x02, 0xb6, 0x0b, 0x2b, 0x52, 0xd3, 0x3a, 0xe6, 0x5f, 0x66, 0x1b, - 0x52, 0x7e, 0x1d, 0xea, 0x71, 0x86, 0x7d, 0x04, 0x25, 0x95, 0xfe, 0x9f, 0xad, 0xa6, 0xff, 0x8c, - 0xc1, 0xfa, 0xda, 0x1c, 0x5c, 0xaa, 0x45, 0x9f, 0x01, 0xc4, 0x49, 0xe8, 0x23, 0x26, 0x31, 0x97, - 0xd4, 0x3e, 0xa2, 0x80, 0xf9, 0x8c, 0xf5, 0xc6, 0x2a, 0x4e, 0xb0, 0xc9, 0x90, 0x49, 0xb8, 0xfc, - 0x42, 0x65, 0xc7, 0xfc, 0x11, 0x54, 0xb4, 0x3c, 0xf4, 0xd1, 0xf2, 0xcd, 0xe7, 0xb0, 0x8f, 0x96, - 0x2f, 0x25, 0x6d, 0xbd, 0xb1, 0x8e, 0xad, 0x2f, 0x1b, 0x0d, 0xd1, 0xba, 0x10, 0xb5, 0xa4, 0xc8, - 0x23, 0x36, 0xe8, 0x0c, 0x6a, 0x89, 0x64, 0xf3, 0xd1, 0x09, 0x4d, 0x4b, 0x65, 0x1f, 0x9d, 0xd0, - 0xd4, 0xfc, 0xf4, 0x8a, 0xce, 0x8c, 0x45, 0xd1, 0xcf, 0x39, 0xa2, 0x68, 0x3d, 0xfd, 0x10, 0x2a, - 0x5a, 0xe2, 0xf8, 0x68, 0x2e, 0xf3, 0x39, 0xea, 0xa3, 0xb9, 0xa4, 0xe5, 0x99, 0x5f, 0xc6, 0x3e, - 0xea, 0x06, 0x92, 0x02, 0xe6, 0xf7, 0x13, 0x6d, 0xff, 0x26, 0xd4, 0x93, 0xb9, 0xe4, 0xa3, 0xb3, - 0x9f, 0x9a, 0x94, 0x3e, 0x3a, 0xfb, 0xd7, 0x24, 0xa0, 0x97, 0x24, 0xfd, 0x60, 0x29, 0xea, 0xe4, - 0xd1, 0x4f, 0x64, 0x58, 0xca, 0x17, 0xec, 0x63, 0xc1, 0xe0, 0x64, 0x7a, 0x49, 0xb6, 0xa6, 0x51, - 0xad, 0x9e, 0xa7, 0x32, 0x3a, 0x2f, 0x73, 0x99, 0x28, 0x93, 0xc4, 0x8c, 0x8d, 0xb3, 0x67, 0xb0, - 0x14, 0x11, 0x73, 0x94, 0x2f, 0x32, 0x88, 0xe6, 0x90, 0x9a, 0x95, 0x72, 0xbd, 0x39, 0x5b, 0xfa, - 0x38, 0x43, 0xd7, 0x1f, 0x66, 0xe9, 0xd3, 0xae, 0x3f, 0x3d, 0x65, 0xa4, 0x76, 0xfd, 0x25, 0x92, - 0xf9, 0xcd, 0x5e, 0x7f, 0xa1, 0x23, 0xda, 0x70, 0xa1, 0x31, 0x9b, 0xbd, 0xf1, 0xf6, 0x75, 0xb9, - 0x0b, 0xa8, 0xf9, 0x37, 0x5f, 0x9e, 0xda, 0x20, 0xc9, 0x8a, 0x14, 0x37, 0x7d, 0x24, 0x1f, 0x9f, - 0xb0, 0xdf, 0x80, 0xaa, 0x9e, 0xc8, 0x9a, 0xe9, 0x3c, 0x61, 0xb6, 0xa7, 0x5b, 0xa9, 0x65, 0x49, - 0x2a, 0x61, 0x55, 0xbd, 0x1b, 0xf6, 0x09, 0xac, 0x46, 0xcb, 0xac, 0xc7, 0xad, 0x07, 0xec, 0x4e, - 0x4a, 0x34, 0x7b, 0x62, 0xb1, 0x6f, 0x5e, 0x1b, 0xee, 0xfe, 0x38, 0x23, 0xa8, 0x2f, 0x99, 0x51, - 0x37, 0xbe, 0x79, 0xd2, 0x12, 0x09, 0xc7, 0x37, 0x4f, 0x6a, 0x1a, 0x5e, 0x45, 0x7d, 0x6c, 0x29, - 0xb1, 0x46, 0xf4, 0x2c, 0x97, 0xfd, 0x10, 0x1a, 0x5a, 0x50, 0x7e, 0xef, 0xca, 0x1d, 0x44, 0x27, - 0x69, 0x3e, 0x25, 0xdc, 0x7a, 0x9a, 0x6d, 0xd2, 0x58, 0xc3, 0xf6, 0x17, 0x8d, 0xc4, 0xe2, 0x88, - 0x53, 0xb4, 0x09, 0x15, 0x3d, 0xe0, 0xff, 0x25, 0xed, 0xae, 0x69, 0x45, 0x7a, 0xf6, 0xb1, 0xc7, - 0x19, 0xb6, 0x0b, 0xcd, 0xd9, 0x64, 0x49, 0x11, 0x4f, 0x49, 0x4b, 0xf0, 0xb4, 0x3e, 0x53, 0x98, - 0x48, 0xb1, 0xc4, 0x0e, 0x29, 0xb0, 0x23, 0xfa, 0x29, 0x25, 0xcf, 0x9f, 0xbd, 0xd5, 0x93, 0x3f, - 0xb1, 0x14, 0xb5, 0x96, 0xf6, 0xe3, 0x5a, 0xf7, 0x33, 0x8f, 0x33, 0xec, 0x77, 0x33, 0x50, 0x4d, - 0x24, 0x28, 0x49, 0x3c, 0x9d, 0x9f, 0x99, 0x67, 0x4b, 0x2f, 0xd3, 0x27, 0x6a, 0x98, 0xb8, 0x88, - 0xbb, 0x0f, 0x7e, 0x90, 0xd8, 0xa4, 0x9f, 0x24, 0x5c, 0x7b, 0x0f, 0x67, 0x7f, 0x6b, 0xe9, 0x8b, - 0x59, 0x04, 0x3d, 0xd3, 0xdf, 0x17, 0x8f, 0x33, 0xec, 0x3f, 0x66, 0xa0, 0x9e, 0xf4, 0xd9, 0x47, - 0xd3, 0x4d, 0x7d, 0x1d, 0x10, 0x91, 0xd2, 0x35, 0x8e, 0xfe, 0x1f, 0xe2, 0x28, 0xfb, 0x0f, 0xcc, - 0xc4, 0x28, 0x65, 0x2e, 0xe8, 0x5f, 0x6c, 0xb4, 0xec, 0x43, 0xfa, 0x69, 0x43, 0xf5, 0x94, 0x89, - 0xcd, 0xff, 0x14, 0x5e, 0x44, 0x7e, 0xfa, 0x0f, 0xc7, 0xe1, 0x26, 0xfc, 0x88, 0x7e, 0x53, 0x48, - 0xbd, 0x8c, 0x11, 0x54, 0xfc, 0xba, 0xf5, 0x8d, 0x77, 0x70, 0x4e, 0x6f, 0x1a, 0x37, 0x13, 0x73, - 0x9a, 0x15, 0x3c, 0xda, 0x34, 0x3a, 0xf9, 0xbb, 0x6f, 0xf1, 0xcd, 0x39, 0xf7, 0x5b, 0x70, 0xd7, - 0x0f, 0x72, 0x4c, 0x83, 0x94, 0xe8, 0x89, 0xa3, 0xf6, 0x9a, 0xcd, 0x18, 0x0f, 0x70, 0xac, 0xef, - 0x18, 0x77, 0xae, 0x1d, 0xeb, 0x23, 0xf4, 0xbf, 0x8b, 0x11, 0x1f, 0x02, 0xc4, 0x4f, 0x0d, 0xd9, - 0xcc, 0x83, 0xb7, 0x88, 0x01, 0xcd, 0xbf, 0x46, 0x4c, 0x9e, 0x67, 0xf5, 0x2e, 0x4e, 0xb4, 0xf8, - 0xeb, 0xc4, 0x4e, 0xa3, 0xa7, 0x78, 0xba, 0xf4, 0x95, 0x7c, 0x15, 0x98, 0x90, 0xbe, 0x66, 0xdb, - 0x4f, 0x30, 0xd3, 0xe8, 0xdd, 0xdd, 0x11, 0xd4, 0x76, 0x3d, 0xef, 0xc5, 0x74, 0x12, 0x3d, 0x6f, - 0x4f, 0x3e, 0x8a, 0xd9, 0xb1, 0x83, 0xb3, 0xf5, 0x99, 0x59, 0x18, 0x77, 0xb1, 0xa9, 0x75, 0xd6, - 0xd2, 0x9a, 0x7a, 0xf4, 0x93, 0xf8, 0x7d, 0xe3, 0x17, 0xcc, 0x86, 0xc5, 0x88, 0x47, 0xc7, 0x6f, - 0x08, 0x93, 0xcd, 0x24, 0x38, 0xf3, 0x6c, 0x17, 0x09, 0x35, 0x41, 0x8d, 0xf6, 0x51, 0xa0, 0xda, - 0x7c, 0x9c, 0x61, 0x87, 0x50, 0xdd, 0xe2, 0x03, 0x0c, 0xd4, 0xc7, 0xa7, 0x25, 0x4b, 0x89, 0x67, - 0x0a, 0xf4, 0x26, 0x65, 0xbd, 0x96, 0x00, 0x26, 0xef, 0xad, 0x89, 0x7d, 0xe5, 0xf3, 0xcf, 0x1f, - 0xfd, 0x44, 0x3e, 0x5a, 0xf9, 0x42, 0xdd, 0x5b, 0xea, 0x51, 0x4f, 0xe2, 0xde, 0x9a, 0x79, 0x05, - 0x94, 0xb8, 0xb7, 0xe6, 0x5e, 0x01, 0x25, 0x96, 0x5a, 0x3d, 0x2a, 0x62, 0x23, 0x58, 0x9c, 0x7b, - 0x38, 0x14, 0x5d, 0x59, 0xd7, 0x3d, 0x37, 0x5a, 0xbf, 0x7b, 0x3d, 0x42, 0xb2, 0xb7, 0x07, 0xc9, - 0xde, 0x7a, 0x50, 0xa3, 0xe4, 0x83, 0xc7, 0x9c, 0x42, 0xf6, 0x66, 0xf2, 0xdd, 0xe8, 0xf1, 0x80, - 0xb3, 0x17, 0x0c, 0x96, 0x25, 0x25, 0x1c, 0x8c, 0x95, 0x63, 0xbf, 0x0e, 0x95, 0x67, 0x3c, 0x54, - 0x31, 0x7a, 0x91, 0x8c, 0x3d, 0x13, 0xb4, 0xb7, 0x9e, 0x12, 0xe2, 0x97, 0xa4, 0x19, 0x6c, 0xed, - 0x11, 0x1f, 0x9e, 0x72, 0x62, 0x4e, 0x96, 0x33, 0xfc, 0x82, 0xfd, 0x1a, 0x36, 0x1e, 0x85, 0x46, - 0xaf, 0x6a, 0x41, 0x58, 0x7a, 0xe3, 0x8d, 0x19, 0x78, 0x5a, 0xcb, 0xae, 0x37, 0xe4, 0x9a, 0xac, - 0xe7, 0x42, 0x45, 0x4b, 0xa1, 0x10, 0x1d, 0xa0, 0xf9, 0x94, 0x19, 0xd1, 0x01, 0x4a, 0xc9, 0xb8, - 0x60, 0xdc, 0xc7, 0x7e, 0x0c, 0x76, 0x37, 0xee, 0x87, 0xb2, 0x2c, 0xc4, 0x3d, 0x3d, 0xfa, 0x89, - 0x3d, 0x0e, 0xbf, 0x60, 0x9f, 0x62, 0x8a, 0x6f, 0x3d, 0x06, 0x31, 0x56, 0x1a, 0x66, 0xc3, 0x15, - 0xa3, 0xc5, 0xd2, 0x8a, 0x92, 0x8a, 0x04, 0x75, 0x85, 0x92, 0xdc, 0x53, 0x80, 0x5e, 0xe8, 0x4d, - 0xb6, 0x6c, 0x3e, 0xf6, 0xdc, 0x98, 0xd7, 0xc6, 0x51, 0x71, 0x31, 0xff, 0xd2, 0x42, 0xe3, 0xd8, - 0xa7, 0x9a, 0x96, 0x95, 0x08, 0xe3, 0x54, 0xc4, 0x75, 0x6d, 0xe0, 0x5c, 0xb4, 0x20, 0x29, 0xc1, - 0x73, 0x8f, 0x33, 0xac, 0x0d, 0x10, 0xbf, 0x1c, 0x8b, 0x74, 0xa6, 0xb9, 0x47, 0x69, 0x11, 0xdb, - 0x4b, 0x79, 0x66, 0x76, 0x08, 0xe5, 0xf8, 0xc9, 0xcd, 0x5a, 0x9c, 0x11, 0x26, 0xf1, 0x40, 0x27, - 0xba, 0xc1, 0xe7, 0x9e, 0xbb, 0x18, 0x4d, 0x5c, 0x2a, 0x60, 0x25, 0xb1, 0x54, 0x27, 0x9c, 0x07, - 0xcc, 0x81, 0x25, 0x1a, 0x60, 0x24, 0x2e, 0x61, 0x34, 0x57, 0x94, 0xc9, 0x7d, 0xfe, 0xe5, 0x49, - 0x74, 0x9a, 0x53, 0xdf, 0x4f, 0x24, 0x4c, 0x3f, 0x82, 0x5a, 0x29, 0x92, 0x4c, 0xb0, 0xe6, 0x31, - 0x2c, 0xce, 0xb9, 0xe8, 0xa3, 0x23, 0x7d, 0xdd, 0x9b, 0x8b, 0xe8, 0x48, 0x5f, 0xeb, 0xdd, 0x37, - 0x56, 0xb0, 0xcb, 0x86, 0x01, 0xa8, 0xea, 0x5d, 0x38, 0xe1, 0xe0, 0x4c, 0x74, 0xf7, 0xef, 0x32, - 0xb0, 0x94, 0xe2, 0x84, 0x67, 0x6f, 0x29, 0xab, 0xc1, 0xb5, 0x0e, 0xfa, 0xf5, 0x54, 0x67, 0xad, - 0xd1, 0xc3, 0x7e, 0xf6, 0xd8, 0xf3, 0xc4, 0xc5, 0x46, 0xbe, 0x52, 0x79, 0x32, 0x5f, 0x2a, 0x54, - 0xa4, 0x4a, 0x14, 0x9f, 0xc3, 0x1a, 0x0d, 0xa4, 0x3d, 0x1a, 0xcd, 0x38, 0x92, 0xdf, 0x9c, 0xfb, - 0xe9, 0xf3, 0x84, 0x73, 0x7c, 0xfd, 0xfa, 0x9f, 0x46, 0xbf, 0x46, 0x9c, 0xa6, 0xa1, 0xb2, 0x29, - 0x34, 0x67, 0x1d, 0xb4, 0xec, 0xfa, 0xb6, 0xd6, 0xef, 0x24, 0xf4, 0xdf, 0x14, 0xa7, 0xee, 0xd7, - 0xb0, 0xb3, 0x3b, 0xc6, 0x7a, 0xda, 0xba, 0x90, 0x4a, 0x2c, 0xf6, 0xe3, 0x6f, 0x45, 0xde, 0xe4, - 0x99, 0x79, 0xaa, 0x0e, 0xae, 0xf3, 0x7d, 0x47, 0x1a, 0x78, 0xba, 0x33, 0xfa, 0x5d, 0xec, 0xfe, - 0xae, 0x71, 0x2b, 0xad, 0x7b, 0x9f, 0xaa, 0x90, 0x2e, 0xbe, 0x36, 0x7b, 0xae, 0xd5, 0x08, 0xee, - 0xa6, 0xed, 0xf7, 0xb5, 0xba, 0xd0, 0xcc, 0x5a, 0xdf, 0x40, 0xd9, 0xae, 0xaa, 0x7b, 0x8f, 0xa3, - 0xe3, 0x93, 0xe2, 0xa6, 0x8e, 0x8e, 0x4f, 0x9a, 0xbb, 0x39, 0x29, 0xd7, 0x28, 0x47, 0xf3, 0x87, - 0x99, 0x07, 0x1b, 0xf7, 0x7e, 0xf8, 0xb5, 0x53, 0x27, 0x3c, 0x9b, 0x1e, 0x3f, 0x1c, 0x78, 0xe3, - 0x47, 0x23, 0x65, 0x6d, 0x94, 0x21, 0xcf, 0x8f, 0x46, 0xee, 0xf0, 0x11, 0x36, 0x7b, 0xbc, 0x30, - 0xf1, 0xbd, 0xd0, 0xfb, 0xd6, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x5f, 0xbc, 0x91, 0xdd, - 0x81, 0x00, 0x00, + 0xc5, 0xea, 0x04, 0xd3, 0xc1, 0x40, 0x85, 0x4c, 0x94, 0x4c, 0xf5, 0x69, 0xfc, 0x49, 0x06, 0x96, + 0xb0, 0x31, 0xa5, 0x0f, 0x48, 0x26, 0xfb, 0x73, 0x0f, 0x52, 0xec, 0x8f, 0x2e, 0xfb, 0xd0, 0xc7, + 0x97, 0x37, 0x7a, 0xe6, 0xe7, 0x8c, 0x9e, 0x5f, 0x87, 0xe6, 0x90, 0x8f, 0x1c, 0x8c, 0x9e, 0x51, + 0xa2, 0x04, 0x69, 0x00, 0x0d, 0x05, 0x57, 0x4a, 0xdc, 0x3f, 0xcd, 0xc0, 0x22, 0x49, 0x2a, 0xa8, + 0x0e, 0xcb, 0x85, 0xfa, 0x48, 0xe9, 0x7f, 0x92, 0x55, 0xc9, 0x39, 0xc5, 0x37, 0x38, 0x42, 0x09, + 0x79, 0xf7, 0x96, 0xd4, 0x0b, 0x25, 0x94, 0x7d, 0x88, 0x3a, 0x8c, 0x6b, 0x21, 0x30, 0x25, 0x1a, + 0x27, 0xb9, 0x29, 0xbb, 0xb7, 0x50, 0xc1, 0x71, 0x11, 0xb4, 0x59, 0x12, 0x0a, 0xa9, 0x00, 0x1b, + 0x3b, 0x50, 0x4b, 0x74, 0x93, 0xb0, 0xcc, 0x56, 0xc9, 0x32, 0x3b, 0xe7, 0xfd, 0xc8, 0xce, 0x7b, + 0x3f, 0xfe, 0x6e, 0x1e, 0x98, 0x20, 0xa9, 0x99, 0x5d, 0x9b, 0x71, 0x1d, 0x66, 0xe7, 0x5c, 0x87, + 0x8f, 0x81, 0x69, 0x08, 0xca, 0xa3, 0x99, 0x8b, 0x3c, 0x9a, 0xcd, 0x18, 0x57, 0x3a, 0x34, 0x1f, + 0xc3, 0xb2, 0x14, 0x68, 0x23, 0x5f, 0x21, 0x9a, 0xdc, 0x68, 0x7f, 0x18, 0x49, 0xb6, 0xca, 0x67, + 0x88, 0xe6, 0x37, 0xe5, 0x36, 0x0c, 0xec, 0x50, 0x5a, 0xaa, 0xd0, 0x6d, 0xd8, 0xb3, 0xe7, 0x4c, + 0xdf, 0x0b, 0x2f, 0xa5, 0x82, 0xe2, 0x1c, 0x15, 0x68, 0x86, 0x93, 0x52, 0xd2, 0x70, 0x62, 0x40, + 0x4d, 0x39, 0x07, 0x29, 0x26, 0x82, 0xa4, 0xb7, 0x8a, 0xf4, 0x10, 0x62, 0x5c, 0xc4, 0x03, 0x68, + 0x2a, 0xeb, 0x46, 0x64, 0x9a, 0x21, 0x7f, 0xbf, 0x34, 0x8e, 0x6d, 0x29, 0x03, 0x4d, 0xc2, 0x10, + 0x5e, 0x99, 0x31, 0x84, 0xbf, 0x0b, 0x8b, 0x81, 0x20, 0x22, 0x6b, 0xea, 0xca, 0xe0, 0x1c, 0x3e, + 0x44, 0xd5, 0xa9, 0x64, 0x36, 0xb1, 0xe0, 0x38, 0x86, 0xcf, 0x9b, 0x1d, 0x6a, 0xf3, 0x66, 0x07, + 0xf6, 0x7e, 0xec, 0x47, 0x0b, 0xce, 0x9d, 0x31, 0x5e, 0xdc, 0x71, 0x20, 0x8b, 0x5c, 0xe0, 0xde, + 0xb9, 0x33, 0x36, 0x95, 0xd3, 0x56, 0x7c, 0x18, 0xff, 0x39, 0x03, 0x4d, 0x41, 0x07, 0x09, 0x3a, + 0xff, 0x15, 0xc0, 0x13, 0xf9, 0x8a, 0x64, 0x5e, 0x11, 0xb8, 0x8a, 0xca, 0xbf, 0x03, 0x48, 0xb6, + 0x96, 0xd0, 0x13, 0x25, 0x91, 0xb7, 0x92, 0x44, 0x1e, 0x33, 0xb2, 0xdd, 0x5b, 0xa4, 0x00, 0x08, + 0x48, 0x9a, 0xff, 0x32, 0x9f, 0xe2, 0xbf, 0xd4, 0x8e, 0xc2, 0x2e, 0xc0, 0x33, 0x7e, 0xbd, 0xe7, + 0x0d, 0x50, 0x43, 0xbb, 0x0b, 0x20, 0x08, 0xf2, 0xd4, 0x1e, 0x3b, 0xd2, 0xba, 0x52, 0x30, 0xcb, + 0xcf, 0xf9, 0xf5, 0x0e, 0x02, 0xc4, 0x6e, 0x88, 0xe2, 0xf8, 0x3c, 0x14, 0xcc, 0xd2, 0x73, 0x7e, + 0x4d, 0x87, 0xc1, 0x82, 0xda, 0x33, 0x7e, 0xbd, 0xcd, 0x49, 0x5c, 0xf3, 0x7c, 0x41, 0x09, 0xbe, + 0x7d, 0x29, 0xe4, 0xb3, 0x84, 0xef, 0xb1, 0xe2, 0xdb, 0x97, 0xcf, 0xf8, 0xb5, 0xf2, 0x83, 0x16, + 0x45, 0xf9, 0xc8, 0x1b, 0xc8, 0x1b, 0x48, 0x45, 0x51, 0xc4, 0x83, 0x32, 0x17, 0x9e, 0xe3, 0xdf, + 0xc6, 0x1f, 0x67, 0xa0, 0x26, 0xc6, 0x8f, 0x0c, 0x4e, 0xac, 0xbb, 0x0a, 0xc6, 0xc9, 0xc4, 0xc1, + 0x38, 0x4f, 0x24, 0x7f, 0x20, 0x6e, 0x99, 0xbd, 0x99, 0x5b, 0xe2, 0x02, 0x13, 0xab, 0x7c, 0x0f, + 0xca, 0x74, 0xb6, 0xc4, 0x61, 0xcd, 0x25, 0x76, 0x29, 0x31, 0x21, 0xb3, 0x84, 0x68, 0xcf, 0xc8, + 0xf7, 0xaf, 0x19, 0xd8, 0x68, 0x89, 0xcb, 0x7e, 0x64, 0x56, 0x4b, 0xd9, 0x86, 0x42, 0x9a, 0x1b, + 0xf9, 0x18, 0x2a, 0x1a, 0x4d, 0xa1, 0x35, 0x2e, 0x1a, 0x3c, 0x11, 0x60, 0x92, 0x68, 0x12, 0xb3, + 0xdf, 0xbd, 0x65, 0xd6, 0x06, 0x3a, 0x60, 0x73, 0x01, 0xf2, 0xa2, 0x92, 0xf1, 0x11, 0x2c, 0x6a, + 0xcd, 0x92, 0x36, 0x9a, 0x36, 0xa6, 0x4c, 0xda, 0x98, 0xfe, 0x59, 0x06, 0x96, 0x65, 0x6d, 0x0c, + 0xdc, 0x72, 0xc4, 0x75, 0xbd, 0x1f, 0x9c, 0xb1, 0x5f, 0x81, 0x9a, 0x68, 0xdd, 0xf2, 0xf9, 0x99, + 0x13, 0x84, 0x5c, 0x79, 0x2e, 0x52, 0x0e, 0x87, 0xe0, 0xda, 0x02, 0xd5, 0x94, 0x98, 0xec, 0x23, + 0xa8, 0x60, 0x55, 0xd2, 0x97, 0xe5, 0xb6, 0xb4, 0xe6, 0x2b, 0xd2, 0x50, 0x77, 0x6f, 0x99, 0x10, + 0x44, 0x5f, 0x9b, 0x65, 0x28, 0x86, 0xbe, 0x73, 0x76, 0xc6, 0x7d, 0x63, 0x35, 0x1a, 0x9a, 0x38, + 0x69, 0xbc, 0x17, 0xf2, 0x89, 0x10, 0x82, 0x8c, 0xff, 0x9a, 0x81, 0x8a, 0x3c, 0x3b, 0x3f, 0xb7, + 0xbb, 0x62, 0x5d, 0x8b, 0x3c, 0x24, 0xd5, 0x38, 0x0e, 0x34, 0x7c, 0x07, 0x1a, 0x63, 0x21, 0x10, + 0x09, 0x81, 0x3d, 0xe1, 0xab, 0xa8, 0x2b, 0xb0, 0x94, 0x47, 0x36, 0x60, 0x09, 0xc5, 0x93, 0xc0, + 0x0a, 0x9d, 0x91, 0xa5, 0x0a, 0x65, 0x94, 0xdf, 0x22, 0x15, 0xf5, 0x9d, 0xd1, 0xbe, 0x2c, 0x10, + 0xb7, 0x74, 0x10, 0xda, 0x67, 0x5c, 0x8a, 0xbe, 0xf4, 0x61, 0xb4, 0x60, 0x75, 0x46, 0x56, 0x57, + 0x7a, 0xc6, 0x4f, 0xeb, 0xb0, 0x36, 0x57, 0x24, 0xf5, 0x8d, 0xc8, 0x46, 0x3f, 0x72, 0xc6, 0x27, + 0x5e, 0x64, 0x0a, 0xcb, 0x68, 0x36, 0xfa, 0x3d, 0x51, 0xa2, 0x4c, 0x61, 0x1c, 0x56, 0x14, 0x41, + 0xa0, 0x2d, 0x2b, 0x12, 0xe7, 0xb3, 0x28, 0x6c, 0xbe, 0x97, 0x64, 0x54, 0xb3, 0xdd, 0x29, 0xb8, + 0x7e, 0xfd, 0x2d, 0x4d, 0xe6, 0x60, 0x01, 0x3b, 0x85, 0x56, 0x44, 0x77, 0x52, 0x3e, 0xd2, 0x74, + 0x13, 0xd1, 0xd3, 0x37, 0x5e, 0xd2, 0x53, 0xc2, 0x48, 0x62, 0xae, 0x2a, 0x72, 0xa5, 0xc6, 0xa2, + 0x7e, 0x2e, 0xe0, 0x75, 0xd5, 0x0f, 0xca, 0x3a, 0xf3, 0xbd, 0xe5, 0x5f, 0x69, 0x5e, 0x68, 0xfc, + 0x49, 0x76, 0x79, 0x47, 0x36, 0x1c, 0x15, 0xe9, 0xfd, 0x9e, 0xc3, 0xea, 0xa5, 0xed, 0x84, 0x6a, + 0x7e, 0x9a, 0x5a, 0x54, 0xc0, 0xfe, 0x9e, 0xbc, 0xa4, 0xbf, 0x4f, 0xa9, 0x72, 0x42, 0xfa, 0x5b, + 0xbe, 0x9c, 0x07, 0x06, 0xeb, 0xff, 0x31, 0x0b, 0xf5, 0x64, 0x2b, 0xe2, 0x50, 0x4b, 0x3e, 0xa4, + 0xe4, 0x09, 0x29, 0x8f, 0x4b, 0x13, 0xed, 0x01, 0xc9, 0x11, 0xf3, 0xc6, 0xe3, 0x6c, 0x8a, 0xf1, + 0x58, 0xb7, 0xd9, 0xe6, 0x5e, 0xe6, 0xdb, 0xca, 0xbf, 0x92, 0x6f, 0xab, 0x90, 0xe6, 0xdb, 0xba, + 0xd9, 0x21, 0xb2, 0xf0, 0x73, 0x39, 0x44, 0x8a, 0x37, 0x3b, 0x44, 0xd6, 0xff, 0x2a, 0x03, 0x6c, + 0x9e, 0x52, 0xd9, 0x53, 0xb2, 0x93, 0xbb, 0x7c, 0x24, 0xb9, 0xd8, 0x37, 0x5f, 0x8d, 0xda, 0xd5, + 0x06, 0xa9, 0xda, 0xec, 0x11, 0x2c, 0xe9, 0x71, 0xc1, 0xba, 0xaa, 0x52, 0x33, 0x99, 0x5e, 0x14, + 0x2b, 0xb4, 0x9a, 0x63, 0x2f, 0xff, 0x52, 0xc7, 0x5e, 0xe1, 0xa5, 0x8e, 0xbd, 0x85, 0xa4, 0x63, + 0x6f, 0xfd, 0x6f, 0x67, 0x60, 0x29, 0x85, 0xa8, 0xbe, 0xba, 0x39, 0x0b, 0x5a, 0x48, 0xb0, 0x98, + 0xac, 0xa4, 0x05, 0x8d, 0xbb, 0xac, 0xff, 0x04, 0x6a, 0x89, 0x43, 0xf4, 0xd5, 0x75, 0x3f, 0xab, + 0x68, 0x11, 0x29, 0xeb, 0x8a, 0xd6, 0xfa, 0xff, 0xcd, 0x01, 0x9b, 0x3f, 0xc7, 0xbf, 0xcc, 0x21, + 0xcc, 0x2f, 0x52, 0x6e, 0x7e, 0x91, 0xfe, 0xff, 0xdd, 0x2b, 0xef, 0xc2, 0xa2, 0xcc, 0x65, 0xd0, + 0x9c, 0x22, 0x44, 0x28, 0xcd, 0xa8, 0x40, 0x8d, 0xe2, 0x3b, 0xb3, 0x3e, 0xd5, 0x52, 0x22, 0x7c, + 0x5b, 0xbb, 0x58, 0x67, 0x5c, 0xab, 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, 0x47, 0x19, 0xbf, + 0xfe, 0xe4, 0x57, 0xbf, 0x34, 0x6b, 0xdd, 0x68, 0x63, 0x7d, 0xbc, 0xcd, 0x4d, 0xd9, 0x98, 0xf1, + 0x1e, 0x54, 0x34, 0x30, 0x3a, 0x0a, 0xba, 0xfb, 0x9b, 0x87, 0xcd, 0x5b, 0xac, 0x06, 0x65, 0xb3, + 0xb3, 0x75, 0xf8, 0x49, 0xc7, 0xec, 0x6c, 0x37, 0x33, 0xac, 0x04, 0xf9, 0xbd, 0xc3, 0x5e, 0xbf, + 0x99, 0x35, 0xd6, 0xa1, 0x25, 0x5b, 0x9c, 0x37, 0x1a, 0xfe, 0x34, 0x1f, 0xe9, 0xeb, 0x58, 0x28, + 0xc5, 0xf3, 0x6f, 0x41, 0x55, 0xbf, 0xf6, 0x24, 0x45, 0xcc, 0xf8, 0xe5, 0x84, 0x60, 0xee, 0x69, + 0x7c, 0x63, 0x0b, 0xc8, 0xdb, 0x32, 0x8c, 0xaa, 0x91, 0x2c, 0xf3, 0x02, 0xf3, 0x3c, 0x8a, 0x69, + 0x09, 0x32, 0xfc, 0x6b, 0x50, 0x4f, 0x5a, 0xd0, 0xa4, 0xd0, 0x99, 0x26, 0xa7, 0x8a, 0xda, 0x09, + 0x93, 0x1a, 0xfb, 0x3e, 0x34, 0x67, 0x2d, 0x70, 0x32, 0xca, 0xf5, 0x86, 0xfa, 0x0d, 0x27, 0x69, + 0x94, 0x63, 0xbb, 0xb0, 0x9c, 0x76, 0xf1, 0x23, 0x7d, 0xdc, 0xac, 0xa0, 0xb0, 0xf9, 0xcb, 0x9d, + 0x7d, 0x57, 0x1a, 0x5a, 0x0b, 0x69, 0xee, 0x2a, 0x6d, 0xb1, 0x37, 0xe8, 0x3f, 0xcd, 0xe4, 0x7a, + 0x01, 0x10, 0xc3, 0x58, 0x13, 0xaa, 0x87, 0x47, 0x9d, 0x03, 0x6b, 0x6b, 0xb7, 0x7d, 0x70, 0xd0, + 0xd9, 0x6b, 0xde, 0x62, 0x0c, 0xea, 0xe8, 0x67, 0xda, 0x8e, 0x60, 0x19, 0x01, 0x93, 0x06, 0x6f, + 0x05, 0xcb, 0xb2, 0x65, 0x68, 0x76, 0x0f, 0x66, 0xa0, 0x39, 0xd6, 0x82, 0xe5, 0xa3, 0x0e, 0xb9, + 0xa6, 0x12, 0xed, 0xe6, 0x85, 0x30, 0x29, 0xa7, 0x2b, 0x84, 0x49, 0xca, 0xc9, 0x91, 0xe7, 0x40, + 0xc9, 0x58, 0xbf, 0x9b, 0x81, 0x95, 0x99, 0x82, 0x38, 0xd2, 0x9a, 0x24, 0xac, 0xa4, 0x6c, 0x55, + 0x45, 0xa0, 0x3a, 0x4d, 0xef, 0xc2, 0x62, 0xa4, 0x74, 0xce, 0x70, 0xc8, 0x66, 0x54, 0xa0, 0x90, + 0x1f, 0xc1, 0x92, 0xa6, 0xbb, 0xce, 0xf0, 0x0a, 0xa6, 0x15, 0xc9, 0x0a, 0xc6, 0x5a, 0x14, 0xd1, + 0x3a, 0x33, 0xea, 0x21, 0x25, 0xfa, 0xe8, 0x05, 0xb1, 0x1d, 0x3a, 0x39, 0x5e, 0xf5, 0xc9, 0x1e, + 0xcf, 0x10, 0x42, 0x72, 0xb4, 0xfa, 0x86, 0xab, 0xee, 0x7f, 0x7f, 0x01, 0xd8, 0xc7, 0x53, 0xee, + 0x5f, 0x63, 0x24, 0x75, 0xf0, 0xb2, 0xd0, 0x22, 0xa5, 0xa0, 0x65, 0x5f, 0x29, 0x5b, 0x22, 0x2d, + 0x5b, 0x21, 0xff, 0xf2, 0x6c, 0x85, 0xc2, 0xcb, 0xb2, 0x15, 0xde, 0x84, 0x9a, 0x73, 0xe6, 0x7a, + 0x82, 0x15, 0x0a, 0x29, 0x29, 0x68, 0x2d, 0xdc, 0xcf, 0x3d, 0xa8, 0x9a, 0x55, 0x09, 0x14, 0x32, + 0x52, 0xc0, 0x3e, 0x8a, 0x91, 0xf8, 0xf0, 0x0c, 0x33, 0x6b, 0x74, 0x26, 0xd8, 0x19, 0x9e, 0x71, + 0xa9, 0x8f, 0xa2, 0x85, 0x46, 0x55, 0x16, 0xf0, 0x80, 0xbd, 0x05, 0xf5, 0xc0, 0x9b, 0x0a, 0xa1, + 0x53, 0x2d, 0x03, 0x59, 0xaa, 0xab, 0x04, 0x3d, 0x52, 0x6e, 0x89, 0xa5, 0x69, 0xc0, 0xad, 0xb1, + 0x13, 0x04, 0x42, 0x54, 0x18, 0x78, 0x6e, 0xe8, 0x7b, 0x23, 0x69, 0x7c, 0x5e, 0x9c, 0x06, 0x7c, + 0x9f, 0x4a, 0xb6, 0xa8, 0x80, 0x7d, 0x3b, 0x1e, 0xd2, 0xc4, 0x76, 0xfc, 0xa0, 0x05, 0x38, 0x24, + 0x35, 0x53, 0x94, 0xed, 0x6c, 0xc7, 0x8f, 0xc6, 0x22, 0x3e, 0x82, 0x99, 0x2c, 0x8a, 0xca, 0x6c, + 0x16, 0xc5, 0x8f, 0xd2, 0xb3, 0x28, 0x6a, 0xd8, 0xf4, 0x63, 0xd9, 0xf4, 0xfc, 0x16, 0x7f, 0xa9, + 0x64, 0x8a, 0xf9, 0xe4, 0x90, 0xfa, 0x97, 0x49, 0x0e, 0x69, 0xa4, 0x25, 0x87, 0xbc, 0x07, 0x15, + 0x0c, 0xdb, 0xb7, 0xce, 0x1d, 0x37, 0x54, 0xc6, 0xf4, 0xa6, 0x1e, 0xd7, 0xbf, 0x2b, 0xd4, 0x7a, + 0xf0, 0xd5, 0x9f, 0xc1, 0x7c, 0x9e, 0xc6, 0xe2, 0x2f, 0x31, 0x4f, 0x43, 0xa6, 0x17, 0x6c, 0x40, + 0x49, 0xed, 0x13, 0x63, 0x90, 0x3f, 0xf5, 0xbd, 0xb1, 0x32, 0x32, 0x8a, 0xbf, 0x59, 0x1d, 0xb2, + 0xa1, 0x27, 0x2b, 0x67, 0x43, 0xcf, 0xf8, 0x4d, 0xa8, 0x68, 0xa4, 0xc6, 0xde, 0x20, 0x73, 0x86, + 0x90, 0xdb, 0xa5, 0xbe, 0x4e, 0xab, 0x58, 0x96, 0xd0, 0xee, 0x50, 0xf0, 0x9b, 0xa1, 0xe3, 0x73, + 0xcc, 0xa8, 0xb2, 0x7c, 0x7e, 0xc1, 0xfd, 0x40, 0x19, 0x7d, 0x9b, 0x51, 0x81, 0x49, 0x70, 0xe3, + 0x6f, 0xc0, 0x52, 0x62, 0x6f, 0x25, 0x8b, 0x78, 0x0b, 0x16, 0x70, 0xdd, 0x94, 0x53, 0x2e, 0x99, + 0x2f, 0x21, 0xcb, 0x30, 0x55, 0x96, 0xec, 0xd5, 0xd6, 0xc4, 0xf7, 0x4e, 0xb0, 0x93, 0x8c, 0x59, + 0x91, 0xb0, 0x23, 0xdf, 0x3b, 0x31, 0xfe, 0x2c, 0x07, 0xb9, 0x5d, 0x6f, 0xa2, 0xc7, 0xa1, 0x64, + 0xe6, 0xe2, 0x50, 0xa4, 0x32, 0x62, 0x45, 0xca, 0x86, 0x94, 0x1f, 0xd1, 0x52, 0xab, 0x14, 0x8e, + 0x07, 0x50, 0x17, 0x7c, 0x22, 0xf4, 0x84, 0x36, 0x77, 0x69, 0xfb, 0x94, 0x3d, 0x91, 0xa3, 0xc3, + 0x67, 0x8f, 0xc3, 0xbe, 0xb7, 0x43, 0x70, 0xb6, 0x0c, 0xb9, 0x48, 0x94, 0xc6, 0x62, 0xf1, 0x29, + 0xd4, 0x7c, 0x8c, 0x23, 0xbc, 0x96, 0x5e, 0x27, 0xf9, 0xc5, 0xbe, 0x09, 0x4b, 0xc9, 0x76, 0x89, + 0x15, 0x49, 0xd9, 0x48, 0x6f, 0x18, 0x79, 0xd2, 0x6d, 0x10, 0x7c, 0x84, 0x70, 0xa4, 0xf3, 0xfa, + 0x94, 0x73, 0x2c, 0xd2, 0x98, 0x5e, 0x29, 0xc1, 0xf4, 0xee, 0x41, 0x25, 0x1c, 0x5d, 0x58, 0x13, + 0xfb, 0x7a, 0xe4, 0xd9, 0x43, 0x79, 0xbe, 0x21, 0x1c, 0x5d, 0x1c, 0x11, 0x84, 0x3d, 0x02, 0x18, + 0x4f, 0x26, 0xf2, 0xec, 0xa1, 0xe1, 0x33, 0x26, 0xe5, 0xfd, 0xa3, 0x23, 0x22, 0x39, 0xb3, 0x3c, + 0x9e, 0x4c, 0xe8, 0x4f, 0xb6, 0x0d, 0xf5, 0xd4, 0xac, 0xa7, 0xbb, 0x2a, 0xec, 0xcd, 0x9b, 0x6c, + 0xa4, 0x1c, 0xce, 0xda, 0x40, 0x87, 0xad, 0x7f, 0x1f, 0xd8, 0x2f, 0x98, 0x7b, 0xd4, 0x87, 0x72, + 0x34, 0x3e, 0x3d, 0x75, 0x07, 0x03, 0x59, 0x2b, 0x89, 0xd4, 0x9d, 0xf6, 0x70, 0xe8, 0x0b, 0xbe, + 0x48, 0x17, 0x66, 0xc4, 0xf2, 0x41, 0xbb, 0x31, 0xdb, 0xc4, 0xf7, 0x8d, 0xbf, 0xc8, 0x40, 0x81, + 0xf2, 0x88, 0xde, 0x86, 0x06, 0xe1, 0x47, 0x31, 0x3d, 0xd2, 0x57, 0x45, 0xf7, 0x6e, 0x5f, 0x86, + 0xf3, 0x88, 0x63, 0xa1, 0xe5, 0x40, 0x66, 0xa3, 0x9d, 0xd7, 0xf2, 0x20, 0xef, 0x41, 0x39, 0xea, + 0x5a, 0x23, 0x9d, 0x92, 0xea, 0x99, 0xbd, 0x0e, 0xf9, 0x73, 0x6f, 0xa2, 0xac, 0x02, 0x10, 0xaf, + 0xa4, 0x89, 0xf0, 0x78, 0x2c, 0xa2, 0x0f, 0x1a, 0xbc, 0xd4, 0x66, 0xa3, 0x4e, 0x90, 0x0c, 0xe6, + 0xe7, 0xb8, 0x90, 0x32, 0xc7, 0x63, 0x68, 0x08, 0x3e, 0xa0, 0xf9, 0x8c, 0x6f, 0xbe, 0x34, 0xbf, + 0x2e, 0x24, 0xbc, 0xc1, 0x68, 0x3a, 0xe4, 0xba, 0x4d, 0x06, 0x03, 0x4c, 0x24, 0x5c, 0x49, 0xd6, + 0xc6, 0xef, 0x67, 0x88, 0xbf, 0x88, 0x76, 0xd9, 0x03, 0xc8, 0x8b, 0xfb, 0x6d, 0xc6, 0x66, 0x18, + 0x45, 0x14, 0x0b, 0x3c, 0x13, 0x31, 0x30, 0x71, 0x78, 0x3a, 0x4e, 0xb6, 0x5e, 0x33, 0x2b, 0xee, + 0x74, 0x1c, 0x99, 0x35, 0xbe, 0xa6, 0xa6, 0x35, 0x63, 0x12, 0xa0, 0xd9, 0x47, 0xc7, 0x74, 0x43, + 0x8b, 0x54, 0xc9, 0x27, 0x6e, 0x4c, 0x25, 0x05, 0x0e, 0xcf, 0xb8, 0x16, 0xa1, 0xf2, 0x87, 0x59, + 0xa8, 0x25, 0x46, 0x84, 0xa1, 0x3a, 0xe2, 0x02, 0x20, 0x7b, 0xb4, 0xdc, 0x6f, 0x10, 0x20, 0x29, + 0xa8, 0x6b, 0xeb, 0x94, 0x4d, 0xac, 0x53, 0xe4, 0x1d, 0xcf, 0xe9, 0xde, 0xf1, 0xc7, 0x50, 0x8e, + 0x73, 0x5f, 0x93, 0x43, 0x12, 0xfd, 0xa9, 0xb8, 0xea, 0x18, 0x29, 0xf6, 0xa7, 0x17, 0x74, 0x7f, + 0xfa, 0xf7, 0x34, 0xf7, 0xeb, 0x02, 0x36, 0x63, 0xa4, 0xad, 0xe8, 0x2f, 0xc5, 0xf9, 0x6a, 0x7c, + 0x04, 0x15, 0x6d, 0xf0, 0xba, 0x9b, 0x35, 0x93, 0x70, 0xb3, 0x46, 0x19, 0x10, 0xd9, 0x38, 0x03, + 0xc2, 0xf8, 0xed, 0x2c, 0xd4, 0xc4, 0xf9, 0x72, 0xdc, 0xb3, 0x23, 0x6f, 0xe4, 0x0c, 0xd0, 0x3e, + 0x1d, 0x9d, 0x30, 0x29, 0x68, 0xa9, 0x73, 0x26, 0x8f, 0x18, 0xc9, 0x59, 0x7a, 0xa2, 0x17, 0x31, + 0xe9, 0x28, 0xd1, 0xcb, 0x80, 0x9a, 0x60, 0x8c, 0x27, 0x76, 0xc0, 0xb5, 0xcc, 0x5c, 0xb3, 0x72, + 0xca, 0xf9, 0xa6, 0x1d, 0x10, 0x87, 0xfc, 0x26, 0x2c, 0x09, 0x1c, 0xcc, 0x71, 0x19, 0x3b, 0xa3, + 0x91, 0x43, 0x98, 0x64, 0xf4, 0x68, 0x9e, 0x72, 0x6e, 0xda, 0x21, 0xdf, 0x17, 0x05, 0x32, 0x91, + 0xb7, 0x34, 0x74, 0x02, 0xfb, 0x24, 0x0e, 0xa8, 0x8a, 0xbe, 0xd1, 0xab, 0x64, 0x5f, 0x69, 0x5e, + 0x25, 0x4a, 0x76, 0xab, 0x8c, 0xed, 0xab, 0xc8, 0xab, 0x34, 0x43, 0x49, 0xc5, 0x59, 0x4a, 0x32, + 0xfe, 0x4b, 0x16, 0x2a, 0x1a, 0x59, 0xbe, 0xca, 0xed, 0x7a, 0x77, 0xce, 0x9f, 0x50, 0xd6, 0x5d, + 0x07, 0x6f, 0x26, 0xbb, 0x44, 0xe7, 0x33, 0xa5, 0x0c, 0x6b, 0x04, 0x7c, 0x07, 0xca, 0xe2, 0xd4, + 0xbd, 0x87, 0xe6, 0x39, 0x99, 0xf0, 0x8e, 0x80, 0xa3, 0xe9, 0x89, 0x2a, 0x7c, 0x82, 0x85, 0x85, + 0xb8, 0xf0, 0x89, 0x28, 0x7c, 0x51, 0x14, 0xe5, 0x77, 0xa0, 0x2a, 0x5b, 0xc5, 0x3d, 0xc5, 0xe9, + 0xc6, 0xa7, 0x3e, 0xb1, 0xdf, 0x66, 0x85, 0xba, 0xa3, 0xcd, 0x97, 0x15, 0x9f, 0xa8, 0x8a, 0xa5, + 0x97, 0x55, 0x7c, 0x42, 0x1f, 0xc6, 0x4e, 0x14, 0x98, 0x8a, 0x81, 0x0f, 0x8a, 0x8f, 0x3d, 0x82, + 0x25, 0xc5, 0xae, 0xa6, 0xae, 0xed, 0xba, 0xde, 0xd4, 0x1d, 0x70, 0x95, 0x1a, 0xc1, 0x64, 0xd1, + 0x71, 0x5c, 0x62, 0x0c, 0xa3, 0xdc, 0x39, 0x0a, 0xa0, 0x78, 0x08, 0x05, 0x92, 0xcb, 0x49, 0xf8, + 0x48, 0x67, 0x5c, 0x84, 0xc2, 0x1e, 0x40, 0x81, 0xc4, 0xf3, 0xec, 0x8d, 0xcc, 0x86, 0x10, 0x8c, + 0x0d, 0x68, 0xa0, 0x88, 0xa9, 0x71, 0xdc, 0x17, 0x49, 0x25, 0xc6, 0x32, 0xb0, 0x03, 0x3a, 0x44, + 0x7a, 0x60, 0xcf, 0x7f, 0xcf, 0x41, 0x45, 0x03, 0x0b, 0xb6, 0x88, 0xa1, 0x20, 0xd6, 0xd0, 0xb1, + 0xc7, 0x5c, 0x79, 0x41, 0x6a, 0x66, 0x0d, 0xa1, 0xdb, 0x12, 0x28, 0x2e, 0x05, 0xfb, 0xe2, 0xcc, + 0xf2, 0xa6, 0xa1, 0x35, 0xe4, 0x67, 0x3e, 0xe7, 0x52, 0x58, 0xaa, 0xda, 0x17, 0x67, 0x87, 0xd3, + 0x70, 0x1b, 0x61, 0x02, 0x4b, 0x10, 0xb5, 0x86, 0x25, 0xa3, 0x17, 0xc6, 0xf6, 0x55, 0x8c, 0x25, + 0x43, 0x68, 0x68, 0x89, 0xf2, 0x51, 0x08, 0x0d, 0xa9, 0x2d, 0xb3, 0x9c, 0xbc, 0x30, 0xcf, 0xc9, + 0xbf, 0x0d, 0xab, 0xc4, 0xc9, 0x25, 0x8f, 0xb0, 0x66, 0x48, 0x6a, 0x19, 0x4b, 0xe5, 0x24, 0x35, + 0xf9, 0xab, 0x29, 0x66, 0xa0, 0xce, 0x47, 0xe0, 0xfc, 0x98, 0x4e, 0x54, 0xc6, 0x14, 0x33, 0x93, + 0x8d, 0xf7, 0x9c, 0x1f, 0x73, 0x81, 0x89, 0x2e, 0x5a, 0x1d, 0x53, 0x06, 0xeb, 0x8e, 0x1d, 0x77, + 0x16, 0xd3, 0xbe, 0x4a, 0x62, 0x96, 0x25, 0xa6, 0x7d, 0xa5, 0x63, 0xbe, 0x0f, 0x6b, 0x63, 0x3e, + 0x74, 0xec, 0x64, 0xb3, 0x56, 0x2c, 0x41, 0x2c, 0x53, 0xb1, 0x56, 0xa7, 0x47, 0x1a, 0xa4, 0x58, + 0x8d, 0x1f, 0x7b, 0xe3, 0x13, 0x87, 0x2e, 0x4f, 0x72, 0x1a, 0xe7, 0xcd, 0xba, 0x3b, 0x1d, 0xff, + 0x10, 0xc1, 0xa2, 0x4a, 0x60, 0xd4, 0xa0, 0xd2, 0x0b, 0xbd, 0x89, 0xda, 0xe6, 0x3a, 0x54, 0xe9, + 0x53, 0x26, 0xbe, 0xdc, 0x81, 0xdb, 0x48, 0x9b, 0x7d, 0x6f, 0xe2, 0x8d, 0xbc, 0xb3, 0xeb, 0x84, + 0x41, 0xe9, 0xbf, 0x65, 0x60, 0x29, 0x51, 0x2a, 0xcf, 0xf9, 0xb7, 0xe9, 0x60, 0x45, 0xd9, 0x0b, + 0x44, 0xce, 0x8b, 0xda, 0xe5, 0x43, 0x88, 0x74, 0xaa, 0x54, 0x46, 0x43, 0x3b, 0xce, 0xba, 0x55, + 0x15, 0x89, 0xb6, 0x5b, 0xf3, 0xb4, 0x2d, 0xeb, 0xab, 0x7c, 0x5c, 0xd5, 0xc4, 0xaf, 0xca, 0x80, + 0xea, 0xa1, 0x9c, 0x72, 0x2e, 0x19, 0x32, 0xaa, 0x1b, 0x9f, 0xd4, 0x08, 0x62, 0x8b, 0x54, 0x60, + 0xfc, 0xeb, 0x0c, 0x40, 0x3c, 0x3a, 0x0c, 0x5a, 0x8d, 0x2e, 0x50, 0x7a, 0xd0, 0x46, 0xbb, 0x2c, + 0xdf, 0x80, 0x6a, 0x14, 0xbb, 0x16, 0x5f, 0xc9, 0x15, 0x05, 0x13, 0xf7, 0xf2, 0x3b, 0xd0, 0x38, + 0x1b, 0x79, 0x27, 0x28, 0x3a, 0xc9, 0x0b, 0x94, 0xd2, 0x7f, 0xea, 0x04, 0x56, 0xd7, 0x62, 0x7c, + 0x81, 0xe7, 0x53, 0xc3, 0xdb, 0xf4, 0xeb, 0xd8, 0xf8, 0x9d, 0x6c, 0x14, 0xc4, 0x13, 0xaf, 0xc4, + 0x8b, 0xf5, 0x8c, 0x9f, 0xc7, 0x17, 0xfc, 0x22, 0x1f, 0xc8, 0x47, 0x50, 0xf7, 0x89, 0x3b, 0x2a, + 0xd6, 0x99, 0x7f, 0x01, 0xeb, 0xac, 0xf9, 0x89, 0x2b, 0xf7, 0xeb, 0xd0, 0xb4, 0x87, 0x17, 0xdc, + 0x0f, 0x1d, 0x34, 0x1b, 0xa3, 0xa0, 0x26, 0xc3, 0x66, 0x34, 0x38, 0x4a, 0x44, 0xef, 0x40, 0x43, + 0x26, 0x63, 0x45, 0x98, 0xf2, 0x79, 0x87, 0x18, 0x2c, 0x10, 0x8d, 0x7f, 0xa7, 0xa2, 0x86, 0x92, + 0xbb, 0xfb, 0xe2, 0x55, 0xd1, 0x67, 0x98, 0x9d, 0xf7, 0xf2, 0x48, 0x42, 0x92, 0xd6, 0x68, 0xc9, + 0x8f, 0x08, 0x28, 0x6d, 0xd1, 0xc9, 0x65, 0xcd, 0xbf, 0xca, 0xb2, 0x1a, 0x7f, 0x9c, 0x81, 0xe2, + 0xae, 0x37, 0x11, 0x7a, 0xb9, 0x90, 0xe7, 0xf0, 0x98, 0x44, 0x89, 0x90, 0x0b, 0xe2, 0xb3, 0x3b, + 0x7c, 0x71, 0xf2, 0x42, 0xaa, 0xbc, 0x51, 0x4b, 0xca, 0x1b, 0xdf, 0x83, 0x3b, 0xe8, 0x17, 0xf1, + 0xbd, 0x89, 0xe7, 0x8b, 0xa3, 0x6a, 0x8f, 0x48, 0xee, 0xf0, 0xdc, 0xf0, 0x5c, 0xf1, 0xce, 0xdb, + 0xa7, 0x9c, 0x1f, 0x69, 0x18, 0xfb, 0x11, 0x02, 0x66, 0xf5, 0x8c, 0xc2, 0x0b, 0x8b, 0x54, 0x45, + 0x29, 0x18, 0x11, 0x47, 0x6d, 0x88, 0x82, 0x0e, 0xc2, 0x51, 0x34, 0x32, 0xbe, 0x0b, 0xe5, 0xc8, + 0xea, 0xc0, 0xde, 0x85, 0xf2, 0xb9, 0x37, 0x91, 0xa6, 0x89, 0x4c, 0x22, 0xc1, 0x43, 0xce, 0xda, + 0x2c, 0x9d, 0xd3, 0x1f, 0x81, 0xf1, 0x67, 0x45, 0x28, 0x76, 0xdd, 0x0b, 0xcf, 0x19, 0x60, 0xdc, + 0xd1, 0x98, 0x8f, 0x3d, 0x95, 0x11, 0x2a, 0xfe, 0xc6, 0xd8, 0x82, 0xf8, 0x91, 0x86, 0x9c, 0x8c, + 0x2d, 0x88, 0x9e, 0x67, 0x58, 0x81, 0x05, 0x5f, 0x7f, 0x65, 0xa1, 0xe0, 0x63, 0x24, 0x64, 0xa4, + 0xb4, 0x15, 0xb4, 0x8c, 0x5a, 0xd1, 0x16, 0x65, 0xff, 0xe3, 0x92, 0x51, 0x86, 0x4e, 0x19, 0x21, + 0xb8, 0x60, 0xaf, 0x41, 0x51, 0xe6, 0x53, 0x50, 0x74, 0x3a, 0x85, 0x2e, 0x4a, 0x10, 0x52, 0x83, + 0xcf, 0xc9, 0xaf, 0x15, 0x49, 0x54, 0x42, 0x4f, 0x97, 0xc0, 0x6d, 0x41, 0x6b, 0xf7, 0xa0, 0x42, + 0xf8, 0x84, 0x52, 0x92, 0x91, 0x42, 0x08, 0x42, 0x84, 0x94, 0xc7, 0x4a, 0xca, 0xa9, 0x8f, 0x95, + 0x60, 0x60, 0x59, 0xc4, 0x65, 0x69, 0x8a, 0x40, 0x4f, 0x54, 0x68, 0x70, 0xf5, 0x52, 0x8f, 0x54, + 0xee, 0x29, 0x61, 0x4d, 0x29, 0xf7, 0x6f, 0x42, 0xed, 0xd4, 0x1e, 0x8d, 0x4e, 0xec, 0xc1, 0x73, + 0xd2, 0x49, 0xab, 0x64, 0x86, 0x53, 0x40, 0x54, 0x4a, 0xef, 0x41, 0x45, 0xdb, 0x65, 0x0c, 0x03, + 0xca, 0x9b, 0x10, 0xef, 0xef, 0xac, 0xa9, 0xa9, 0xfe, 0x0a, 0xa6, 0x26, 0x2d, 0x1c, 0xaa, 0x91, + 0x0c, 0x87, 0xba, 0x83, 0xdc, 0x54, 0x86, 0xcc, 0x34, 0xe9, 0x3d, 0x04, 0x7b, 0x38, 0xc4, 0x90, + 0x19, 0x7a, 0x7c, 0x0c, 0x17, 0x8f, 0xca, 0x17, 0x49, 0xa8, 0x25, 0x18, 0xa1, 0xdc, 0x25, 0x7b, + 0xe9, 0xc4, 0x76, 0x86, 0x18, 0x7e, 0x4a, 0x6a, 0x6c, 0xd1, 0x1e, 0x87, 0x47, 0xb6, 0x33, 0x64, + 0xf7, 0xa1, 0xaa, 0x8a, 0xf1, 0x76, 0x5c, 0xa2, 0xf5, 0x97, 0xc5, 0xe2, 0x4e, 0x34, 0xa0, 0x16, + 0x61, 0x8c, 0xe3, 0xac, 0xb3, 0x8a, 0x44, 0x41, 0x3a, 0x78, 0x0f, 0xc3, 0x10, 0x42, 0x8e, 0xb9, + 0x65, 0xf5, 0x27, 0x77, 0xe4, 0x5c, 0x25, 0x95, 0xaa, 0xff, 0xc9, 0x4b, 0x43, 0x98, 0x42, 0x10, + 0x23, 0x67, 0xd1, 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0x2c, 0x22, 0x04, 0xf6, 0x5d, 0x4d, 0x91, + 0x6a, 0x21, 0xf2, 0x6b, 0x33, 0xed, 0xdf, 0x14, 0x7d, 0x7f, 0x17, 0xc0, 0x09, 0xc4, 0x2d, 0x13, + 0x70, 0x77, 0x88, 0x69, 0x62, 0x25, 0xb3, 0xec, 0x04, 0xcf, 0x08, 0xf0, 0xd5, 0x6a, 0x58, 0x6d, + 0xa8, 0xea, 0xd3, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0x75, 0x0e, 0x9a, 0xb7, 0x58, 0x05, 0x8a, 0xbd, + 0x4e, 0xbf, 0xbf, 0x87, 0x2e, 0xa7, 0x2a, 0x94, 0xa2, 0x64, 0x97, 0xac, 0xf8, 0x6a, 0x6f, 0x6d, + 0x75, 0x8e, 0xfa, 0x9d, 0xed, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, 0x99, 0x33, 0xfe, 0x3c, 0x07, + 0x15, 0x6d, 0x15, 0x5e, 0xcc, 0x8c, 0xef, 0x02, 0xa0, 0x4a, 0x13, 0x47, 0x54, 0xe5, 0xcd, 0xb2, + 0x80, 0xd0, 0xe6, 0xeb, 0xc6, 0xf2, 0x1c, 0x3d, 0xb4, 0xa1, 0x8c, 0xe5, 0x6f, 0x42, 0x8d, 0xde, + 0xac, 0xd0, 0x1d, 0x87, 0x05, 0xb3, 0x4a, 0x40, 0xc9, 0xaa, 0x31, 0x5b, 0x0e, 0x91, 0x30, 0x8f, + 0x42, 0x66, 0xb0, 0x13, 0x08, 0x33, 0x29, 0x30, 0x0d, 0x26, 0xf0, 0x46, 0x17, 0x9c, 0x30, 0x48, + 0x22, 0xac, 0x48, 0x58, 0x5f, 0xa6, 0xeb, 0x49, 0x7e, 0xa8, 0xa5, 0x6b, 0x15, 0xcc, 0x2a, 0x01, + 0x65, 0x47, 0xdf, 0x54, 0x04, 0x54, 0x42, 0x02, 0x5a, 0x9b, 0xa7, 0x86, 0x04, 0xf1, 0xec, 0xcd, + 0xd9, 0xb3, 0xca, 0x48, 0x18, 0x5f, 0x9b, 0xaf, 0xf7, 0x72, 0xbb, 0x16, 0x7b, 0x17, 0xd8, 0x78, + 0x32, 0xb1, 0x52, 0x2c, 0x4d, 0x79, 0xb3, 0x31, 0x9e, 0x4c, 0xfa, 0x9a, 0x21, 0xe6, 0x2b, 0x30, + 0x82, 0x7d, 0x0e, 0xac, 0x2d, 0x0e, 0x30, 0x0e, 0x31, 0x32, 0xa1, 0xc6, 0x6c, 0x39, 0xa3, 0xb3, + 0xe5, 0x14, 0xee, 0x97, 0x4d, 0xe5, 0x7e, 0x2f, 0xe2, 0x13, 0xc6, 0x0e, 0x54, 0x8e, 0xb4, 0x17, + 0x71, 0xee, 0x8b, 0x1b, 0x42, 0xbd, 0x85, 0x43, 0x77, 0x07, 0x19, 0xb7, 0x7c, 0xf9, 0x04, 0x8e, + 0x36, 0x9a, 0xac, 0x36, 0x1a, 0xe3, 0x5f, 0x65, 0xe8, 0xb5, 0x81, 0x68, 0xf0, 0xf1, 0x23, 0x3c, + 0xca, 0x0f, 0x14, 0x67, 0x55, 0x56, 0x94, 0xff, 0x47, 0x26, 0x44, 0xe2, 0xd0, 0x2c, 0xef, 0xf4, + 0x34, 0xe0, 0x2a, 0x3f, 0xa8, 0x82, 0xb0, 0x43, 0x04, 0x29, 0xe1, 0x5b, 0x48, 0xf8, 0x0e, 0xb5, + 0x1f, 0xc8, 0x3c, 0x21, 0x21, 0x7c, 0xef, 0xdb, 0x57, 0xb2, 0xd7, 0x40, 0x88, 0x20, 0xd2, 0x50, + 0xad, 0xb2, 0xa2, 0xa2, 0x6f, 0xe3, 0x9f, 0xcb, 0xc4, 0xcf, 0xd9, 0xf5, 0x7d, 0x08, 0xa5, 0xa8, + 0xd5, 0xe4, 0x0d, 0xab, 0x30, 0xa3, 0x72, 0x71, 0x8f, 0xa3, 0x56, 0x9e, 0x18, 0x31, 0x1d, 0x2e, + 0x74, 0x36, 0x74, 0xb5, 0x51, 0x7f, 0x03, 0xd8, 0xa9, 0xe3, 0xcf, 0x22, 0xd3, 0x61, 0x6b, 0x62, + 0x89, 0x86, 0x6d, 0x1c, 0xc3, 0x92, 0xe2, 0x12, 0x9a, 0x46, 0x90, 0xdc, 0xbc, 0xcc, 0x4b, 0x98, + 0x7c, 0x76, 0x8e, 0xc9, 0x1b, 0x3f, 0xcb, 0x43, 0x51, 0xbd, 0x2e, 0x95, 0xf6, 0x22, 0x52, 0x39, + 0xf9, 0x22, 0x52, 0x2b, 0xf1, 0x7a, 0x06, 0x6e, 0xbd, 0xbc, 0xef, 0xdf, 0x99, 0xbd, 0xb2, 0x35, + 0xa3, 0x79, 0xe2, 0xda, 0x5e, 0x85, 0xfc, 0xc4, 0x0e, 0xcf, 0xd1, 0x40, 0x46, 0xc4, 0x83, 0xdf, + 0xca, 0x98, 0x5e, 0x48, 0x1a, 0xd3, 0xd3, 0x5e, 0x8f, 0x22, 0x91, 0x74, 0xee, 0xf5, 0xa8, 0x3b, + 0x40, 0xf2, 0x85, 0x16, 0x99, 0x53, 0x42, 0x80, 0xb8, 0x8b, 0x92, 0xe2, 0x48, 0x69, 0x56, 0x1c, + 0x79, 0x65, 0x51, 0xe1, 0xdb, 0xb0, 0x40, 0x99, 0xd7, 0x32, 0xfb, 0x4b, 0x5d, 0x28, 0x72, 0x0d, + 0xd5, 0xff, 0x14, 0x8e, 0x6b, 0x4a, 0x5c, 0xfd, 0x29, 0x96, 0x4a, 0xe2, 0x29, 0x16, 0xdd, 0xc8, + 0x5f, 0x4d, 0x1a, 0xf9, 0x1f, 0x40, 0x33, 0x5a, 0x50, 0x34, 0x99, 0xb9, 0x81, 0xcc, 0x2d, 0xa9, + 0x2b, 0xb8, 0xe0, 0x92, 0x07, 0x41, 0x7c, 0x21, 0xd6, 0x13, 0x17, 0xa2, 0xe0, 0x61, 0xed, 0x30, + 0xe4, 0xe3, 0x49, 0x28, 0x2f, 0x44, 0x8c, 0x3e, 0xd7, 0x07, 0x98, 0xcc, 0x8b, 0xac, 0x41, 0xb9, + 0x7b, 0x60, 0xed, 0xec, 0x75, 0x9f, 0xee, 0xf6, 0x9b, 0x19, 0xf1, 0xd9, 0x3b, 0xde, 0xda, 0xea, + 0x74, 0xb6, 0xf1, 0xc6, 0x01, 0x58, 0xd8, 0x69, 0x77, 0xc5, 0xed, 0x93, 0x33, 0x7e, 0x37, 0x0b, + 0x15, 0xad, 0x79, 0xf6, 0x7e, 0xb4, 0x2a, 0xf4, 0x5a, 0xc7, 0xdd, 0xf9, 0x21, 0x6c, 0x28, 0x56, + 0xac, 0x2d, 0x4b, 0xf4, 0x56, 0x56, 0xf6, 0xc6, 0xb7, 0xb2, 0xd8, 0xdb, 0xd0, 0xb0, 0xa9, 0x85, + 0x68, 0x15, 0xa4, 0x39, 0x58, 0x82, 0xe5, 0x22, 0x60, 0x3c, 0x5a, 0x7c, 0x9f, 0x08, 0xbc, 0xbc, + 0x0a, 0x01, 0x8b, 0xae, 0x14, 0x5c, 0xac, 0xe2, 0xa9, 0xed, 0x8c, 0xa6, 0x3e, 0x97, 0xee, 0xdb, + 0xe8, 0x66, 0x26, 0xa8, 0xa9, 0x8a, 0x8d, 0x0f, 0x00, 0xe2, 0x31, 0x27, 0x17, 0xe7, 0x56, 0x72, + 0x71, 0x32, 0xda, 0xe2, 0x64, 0x8d, 0x6d, 0x62, 0x23, 0x72, 0xa1, 0x23, 0x4f, 0xf5, 0x37, 0x41, + 0x59, 0xa4, 0x2c, 0x8c, 0x08, 0x9d, 0x8c, 0x78, 0xa8, 0x32, 0x48, 0x17, 0x65, 0x49, 0x37, 0x2a, + 0x50, 0x09, 0xdd, 0x71, 0x2b, 0x31, 0x37, 0x92, 0x24, 0x39, 0xcb, 0x8d, 0x24, 0xaa, 0x19, 0x95, + 0x1b, 0xeb, 0xd0, 0xda, 0xe6, 0xa2, 0xb5, 0xf6, 0x68, 0x34, 0x33, 0x1c, 0xe3, 0x0e, 0xdc, 0x4e, + 0x29, 0x93, 0x46, 0x88, 0x8f, 0x61, 0xa5, 0x4d, 0xc9, 0xa2, 0x5f, 0x55, 0x56, 0x88, 0xd1, 0x82, + 0xd5, 0xd9, 0x26, 0x65, 0x67, 0x3b, 0xb0, 0xb8, 0xcd, 0x4f, 0xa6, 0x67, 0x7b, 0xfc, 0x22, 0xee, + 0x88, 0x41, 0x3e, 0x38, 0xf7, 0x2e, 0xe5, 0xfa, 0xe0, 0xdf, 0xe2, 0x0c, 0x8f, 0x04, 0x8e, 0x15, + 0x4c, 0xf8, 0x40, 0x59, 0x44, 0x11, 0xd2, 0x9b, 0xf0, 0x81, 0xf1, 0x3e, 0x30, 0xbd, 0x1d, 0xb9, + 0x5e, 0x42, 0x4b, 0x98, 0x9e, 0x58, 0xc1, 0x75, 0x10, 0xf2, 0xb1, 0x7a, 0x0c, 0x06, 0x82, 0xe9, + 0x49, 0x8f, 0x20, 0xc6, 0x3b, 0x50, 0x3d, 0xb2, 0xaf, 0x4d, 0xfe, 0xb9, 0xcc, 0x77, 0x58, 0x83, + 0xe2, 0xc4, 0xbe, 0x16, 0x6c, 0x20, 0x72, 0x8e, 0x60, 0xb1, 0xf1, 0x07, 0x79, 0x58, 0x20, 0x4c, + 0x76, 0x9f, 0xde, 0x6b, 0x74, 0x5c, 0x3c, 0x86, 0x8a, 0x51, 0x6a, 0xa0, 0x39, 0x5e, 0x9a, 0x9d, + 0xe7, 0xa5, 0xd2, 0x80, 0xa6, 0xde, 0xa9, 0x50, 0x66, 0x6c, 0x77, 0x3a, 0x56, 0x8f, 0x53, 0x24, + 0x33, 0x26, 0xf3, 0xf1, 0x7b, 0x9c, 0x94, 0x4e, 0x96, 0x74, 0x34, 0xc6, 0xba, 0x08, 0x8d, 0x4e, + 0x5d, 0x11, 0x92, 0x5d, 0xea, 0xa0, 0x54, 0x85, 0xa7, 0xa8, 0x32, 0x69, 0x92, 0x0a, 0xcf, 0x9c, + 0x62, 0x53, 0x7a, 0xb9, 0x62, 0x43, 0x96, 0xb5, 0x17, 0x28, 0x36, 0xf0, 0x0a, 0x8a, 0xcd, 0x2b, + 0x38, 0xf9, 0x6e, 0x43, 0x09, 0xef, 0x7d, 0x8d, 0x7b, 0x8a, 0xfb, 0x5e, 0x70, 0xcf, 0xef, 0x68, + 0xa2, 0x3f, 0x45, 0x18, 0xdc, 0x89, 0x8f, 0x89, 0xc9, 0x3f, 0xff, 0xe5, 0x38, 0x4f, 0x3e, 0x83, + 0xa2, 0x84, 0x0a, 0x82, 0x76, 0xed, 0xb1, 0x7a, 0xea, 0x07, 0xff, 0x16, 0xcb, 0x86, 0xef, 0x93, + 0x7c, 0x3e, 0x75, 0x7c, 0x3e, 0x54, 0x8f, 0x41, 0x38, 0x78, 0x46, 0x05, 0x44, 0x4c, 0x50, 0xa8, + 0x21, 0xae, 0x77, 0xe9, 0xca, 0x54, 0xf0, 0xa2, 0x13, 0x3c, 0x13, 0x9f, 0x06, 0x83, 0x26, 0x3e, + 0xf6, 0x35, 0xf1, 0x7c, 0x75, 0x39, 0x19, 0x3f, 0xcb, 0x40, 0x53, 0x9e, 0xae, 0xa8, 0x4c, 0xd7, + 0x02, 0x0a, 0x37, 0x39, 0xc4, 0x5f, 0xfc, 0xb4, 0x83, 0x01, 0x35, 0x34, 0x7e, 0x44, 0x37, 0x15, + 0x19, 0x6f, 0x2a, 0x02, 0xb8, 0x23, 0x6f, 0xab, 0xd7, 0xa1, 0xa2, 0x02, 0x43, 0xc7, 0xce, 0x48, + 0x3d, 0xbd, 0x4b, 0x91, 0xa1, 0xfb, 0xce, 0x48, 0x5d, 0x74, 0xbe, 0x2d, 0x33, 0xbb, 0x32, 0x78, + 0xd1, 0x99, 0x76, 0xc8, 0x8d, 0xff, 0x94, 0x81, 0x45, 0x6d, 0x2a, 0xf2, 0xdc, 0x7e, 0x08, 0xd5, + 0xe8, 0x95, 0x3d, 0x1e, 0x49, 0x5e, 0x6b, 0x49, 0x46, 0x13, 0x57, 0xab, 0x0c, 0x22, 0x48, 0x20, + 0x06, 0x33, 0xb4, 0xaf, 0x71, 0xbc, 0xc1, 0x74, 0xac, 0x94, 0x9b, 0xa1, 0x7d, 0xbd, 0xc3, 0x79, + 0x6f, 0x3a, 0x16, 0xaa, 0xeb, 0x25, 0xe7, 0xcf, 0x23, 0x04, 0x92, 0xb9, 0x40, 0xc0, 0x24, 0x86, + 0x01, 0xb5, 0xb1, 0xe7, 0x86, 0xe7, 0x11, 0x8a, 0x94, 0x3a, 0x11, 0x48, 0x38, 0xc6, 0x9f, 0x66, + 0x61, 0x89, 0x4c, 0x6c, 0xd2, 0xb4, 0x29, 0x59, 0x57, 0x0b, 0x16, 0xc8, 0xda, 0x48, 0xcc, 0x6b, + 0xf7, 0x96, 0x29, 0xbf, 0xd9, 0xb7, 0x5f, 0xd1, 0x2c, 0xa8, 0x92, 0xc7, 0x6e, 0x58, 0xfe, 0xdc, + 0xfc, 0xf2, 0xdf, 0xbc, 0xbc, 0x69, 0x1e, 0xb7, 0x42, 0x9a, 0xc7, 0xed, 0x55, 0xfc, 0x5c, 0x73, + 0x19, 0x56, 0x45, 0x89, 0xa3, 0x65, 0x58, 0xbd, 0x0f, 0x6b, 0x09, 0x1c, 0xe4, 0xd6, 0xce, 0xa9, + 0xc3, 0x55, 0xa6, 0xfd, 0xb2, 0x86, 0xdd, 0x53, 0x65, 0x9b, 0x45, 0x28, 0x04, 0x03, 0x6f, 0xc2, + 0x8d, 0x55, 0x58, 0x4e, 0xae, 0xaa, 0xbc, 0x26, 0x7e, 0x2f, 0x03, 0x2d, 0x19, 0x1f, 0xe1, 0xb8, + 0x67, 0xbb, 0x4e, 0x10, 0x7a, 0x7e, 0xf4, 0x1a, 0xdd, 0x5d, 0x80, 0x20, 0xb4, 0x7d, 0xa9, 0x6d, + 0xca, 0xdc, 0x72, 0x84, 0xa0, 0x26, 0x79, 0x1b, 0x4a, 0xdc, 0x1d, 0x52, 0x21, 0x51, 0x43, 0x91, + 0xbb, 0x43, 0xa5, 0x87, 0xce, 0xc9, 0xdf, 0xb5, 0xa4, 0x7a, 0x21, 0x53, 0x3d, 0xc5, 0xea, 0xf0, + 0x0b, 0xbc, 0x78, 0xf3, 0x51, 0xaa, 0xe7, 0xbe, 0x7d, 0x85, 0xd1, 0x86, 0x81, 0xf1, 0x4f, 0xb2, + 0xd0, 0x88, 0xc7, 0x47, 0x79, 0xe2, 0x2f, 0xce, 0x78, 0xbf, 0x2f, 0xc9, 0xc1, 0x11, 0xf2, 0xbb, + 0x66, 0x78, 0x2c, 0xd1, 0xe1, 0xec, 0xba, 0xcc, 0x80, 0x8a, 0xc2, 0xf0, 0xa6, 0xa1, 0xf6, 0x28, + 0x54, 0x99, 0x50, 0x0e, 0xa7, 0xa1, 0x50, 0xb8, 0x84, 0xe6, 0xe9, 0xb8, 0x52, 0xe5, 0x29, 0xd8, + 0xe3, 0xb0, 0x8b, 0x6f, 0x4d, 0x0b, 0xb0, 0xa8, 0x46, 0x1b, 0x29, 0xb0, 0x04, 0x7e, 0x93, 0xe4, + 0x6c, 0xda, 0x39, 0x94, 0xb1, 0x75, 0x21, 0x94, 0x9e, 0xdd, 0x8c, 0x84, 0xd0, 0xd7, 0xa1, 0x42, + 0x8d, 0xc7, 0x09, 0x75, 0x79, 0xb3, 0x8c, 0x3d, 0x60, 0xb9, 0x34, 0x02, 0x79, 0xd3, 0x84, 0xea, + 0x0b, 0xd4, 0x15, 0x86, 0x1f, 0xfc, 0x83, 0x0c, 0xdc, 0x4e, 0xd9, 0x36, 0x79, 0xca, 0xb7, 0x60, + 0xf1, 0x34, 0x2a, 0x54, 0xab, 0x4b, 0x47, 0x7d, 0x55, 0xb1, 0xd5, 0xe4, 0x9a, 0x9a, 0xcd, 0xd3, + 0x24, 0x20, 0x56, 0xba, 0x68, 0x07, 0x13, 0x39, 0x93, 0xa8, 0x74, 0xd1, 0x36, 0x92, 0xbe, 0x73, + 0x04, 0xeb, 0x9d, 0x2b, 0xc1, 0x31, 0xb6, 0xf4, 0xc7, 0xd2, 0x15, 0x19, 0x25, 0x0d, 0xcc, 0x99, + 0x57, 0x32, 0x30, 0x0f, 0x29, 0x35, 0x2c, 0x6a, 0xeb, 0xe7, 0x69, 0x04, 0x2f, 0x50, 0x51, 0x87, + 0x1e, 0x7b, 0x57, 0x79, 0x9b, 0x83, 0xe8, 0x91, 0x77, 0x23, 0x80, 0xc6, 0xfe, 0x74, 0x14, 0x3a, + 0xf1, 0xbb, 0xef, 0xec, 0xdb, 0xb2, 0x0e, 0xf6, 0xa3, 0x56, 0x2d, 0xb5, 0x23, 0x88, 0x3a, 0xc2, + 0xc5, 0x1a, 0x8b, 0x86, 0xac, 0xf9, 0xfe, 0x1a, 0xe3, 0x64, 0x0f, 0xc6, 0x6d, 0x58, 0x8b, 0xbf, + 0x68, 0xd9, 0xd4, 0x55, 0xf3, 0x2f, 0x33, 0x14, 0xda, 0x9c, 0x7c, 0x83, 0x9e, 0x75, 0x60, 0x29, + 0x70, 0xdc, 0xb3, 0x11, 0xd7, 0x9b, 0x0f, 0xe4, 0x22, 0xac, 0x24, 0xc7, 0x26, 0xdf, 0xa9, 0x37, + 0x17, 0xa9, 0x46, 0xdc, 0x5a, 0xc0, 0x36, 0x6f, 0x1a, 0x64, 0x4c, 0x16, 0x33, 0xab, 0x31, 0x3f, + 0xf8, 0x2e, 0xd4, 0x93, 0x1d, 0xb1, 0xef, 0xc8, 0xb4, 0xc8, 0x78, 0x54, 0xb9, 0x99, 0x0c, 0xb7, + 0x98, 0x20, 0x2a, 0xf1, 0xda, 0x07, 0xc6, 0x3f, 0xca, 0x40, 0xcb, 0xe4, 0x82, 0x72, 0xb5, 0x51, + 0x2a, 0x9a, 0xf9, 0x70, 0xae, 0xd5, 0x9b, 0xe7, 0xaa, 0xb2, 0x2d, 0xd5, 0x88, 0xbe, 0x71, 0xe3, + 0x66, 0xec, 0xde, 0x9a, 0x9b, 0xd1, 0x66, 0x09, 0x16, 0x08, 0xc5, 0x58, 0x83, 0x15, 0x39, 0x1e, + 0x35, 0x96, 0xd8, 0x7b, 0x98, 0xe8, 0x31, 0xe1, 0x3d, 0x5c, 0x87, 0x16, 0x3d, 0x2a, 0xa8, 0x4f, + 0x42, 0x56, 0xdc, 0x06, 0xb6, 0x6f, 0x0f, 0x6c, 0xdf, 0xf3, 0xdc, 0x23, 0xee, 0xcb, 0x40, 0x51, + 0x94, 0x30, 0xd1, 0xb9, 0xa6, 0x44, 0x61, 0xfa, 0x52, 0x4f, 0xe1, 0x79, 0xae, 0x8a, 0x8b, 0xa1, + 0x2f, 0xc3, 0x84, 0xa5, 0x4d, 0xfb, 0x39, 0x57, 0x2d, 0xa9, 0x25, 0xfa, 0x08, 0x2a, 0x93, 0xa8, + 0x51, 0xb5, 0xee, 0x2a, 0x77, 0x7a, 0xbe, 0x5b, 0x53, 0xc7, 0x36, 0x9e, 0xc0, 0x72, 0xb2, 0x4d, + 0xc9, 0x3a, 0xd6, 0xa1, 0x34, 0x96, 0x30, 0x39, 0xba, 0xe8, 0xdb, 0xf8, 0x69, 0x09, 0x8a, 0x52, + 0x9f, 0x63, 0x1b, 0x90, 0x1f, 0xa8, 0xd8, 0xa4, 0xf8, 0x49, 0x0e, 0x59, 0xaa, 0xfe, 0xdf, 0xc2, + 0x08, 0x25, 0x81, 0xc7, 0x3e, 0x82, 0x7a, 0xd2, 0x2b, 0x3a, 0x93, 0x98, 0x99, 0x74, 0x67, 0xd6, + 0x06, 0x33, 0xfe, 0xaf, 0x72, 0x7c, 0x39, 0x92, 0xcc, 0x50, 0x3a, 0xd7, 0x6e, 0x4f, 0xcf, 0x15, + 0xf2, 0x76, 0x70, 0x6e, 0x5b, 0x4f, 0xde, 0xff, 0x40, 0x66, 0x66, 0x56, 0x10, 0xd8, 0x3b, 0xb7, + 0x9f, 0xbc, 0xff, 0xc1, 0xac, 0x24, 0x4d, 0xc9, 0x79, 0xba, 0x24, 0xbd, 0x0c, 0x05, 0x7a, 0xf3, + 0x8d, 0x82, 0x4c, 0xe8, 0x83, 0x3d, 0x86, 0x65, 0xa9, 0xb6, 0x5a, 0x32, 0x1c, 0x98, 0xb8, 0x60, + 0x89, 0xb2, 0x81, 0x64, 0x59, 0x0f, 0x8b, 0xc8, 0x36, 0xb4, 0x0a, 0x0b, 0xe7, 0xf1, 0x03, 0x7e, + 0x35, 0x53, 0x7e, 0x19, 0x7f, 0x5a, 0x80, 0x8a, 0xb6, 0x28, 0xac, 0x0a, 0x25, 0xb3, 0xd3, 0xeb, + 0x98, 0x9f, 0x74, 0xb6, 0x9b, 0xb7, 0xd8, 0x03, 0x78, 0xab, 0x7b, 0xb0, 0x75, 0x68, 0x9a, 0x9d, + 0xad, 0xbe, 0x75, 0x68, 0x5a, 0xea, 0x61, 0x98, 0xa3, 0xf6, 0x67, 0xfb, 0x9d, 0x83, 0xbe, 0xb5, + 0xdd, 0xe9, 0xb7, 0xbb, 0x7b, 0xbd, 0x66, 0x86, 0xbd, 0x06, 0xad, 0x18, 0x53, 0x15, 0xb7, 0xf7, + 0x0f, 0x8f, 0x0f, 0xfa, 0xcd, 0x2c, 0xbb, 0x07, 0x77, 0x76, 0xba, 0x07, 0xed, 0x3d, 0x2b, 0xc6, + 0xd9, 0xda, 0xeb, 0x7f, 0x62, 0x75, 0x7e, 0xfd, 0xa8, 0x6b, 0x7e, 0xd6, 0xcc, 0xa5, 0x21, 0x08, + 0x65, 0x5c, 0xb5, 0x90, 0x67, 0xb7, 0x61, 0x85, 0x10, 0xa8, 0x8a, 0xd5, 0x3f, 0x3c, 0xb4, 0x7a, + 0x87, 0x87, 0x07, 0xcd, 0x02, 0x5b, 0x84, 0x5a, 0xf7, 0xe0, 0x93, 0xf6, 0x5e, 0x77, 0xdb, 0x32, + 0x3b, 0xed, 0xbd, 0xfd, 0xe6, 0x02, 0x5b, 0x82, 0xc6, 0x2c, 0x5e, 0x51, 0x34, 0xa1, 0xf0, 0x0e, + 0x0f, 0xba, 0x87, 0x07, 0xd6, 0x27, 0x1d, 0xb3, 0xd7, 0x3d, 0x3c, 0x68, 0x96, 0xd8, 0x2a, 0xb0, + 0x64, 0xd1, 0xee, 0x7e, 0x7b, 0xab, 0x59, 0x66, 0x2b, 0xb0, 0x98, 0x84, 0x3f, 0xeb, 0x7c, 0xd6, + 0x04, 0xd6, 0x82, 0x65, 0x1a, 0x98, 0xb5, 0xd9, 0xd9, 0x3b, 0xfc, 0xd4, 0xda, 0xef, 0x1e, 0x74, + 0xf7, 0x8f, 0xf7, 0x9b, 0x15, 0x7c, 0xaa, 0xaa, 0xd3, 0xb1, 0xba, 0x07, 0xbd, 0xe3, 0x9d, 0x9d, + 0xee, 0x56, 0xb7, 0x73, 0xd0, 0x6f, 0x56, 0xa9, 0xe7, 0xb4, 0x89, 0xd7, 0x44, 0x05, 0x99, 0x33, + 0x60, 0x6d, 0x77, 0x7b, 0xed, 0xcd, 0xbd, 0xce, 0x76, 0xb3, 0xce, 0xee, 0xc2, 0xed, 0x7e, 0x67, + 0xff, 0xe8, 0xd0, 0x6c, 0x9b, 0x9f, 0xa9, 0x9c, 0x02, 0x6b, 0xa7, 0xdd, 0xdd, 0x3b, 0x36, 0x3b, + 0xcd, 0x06, 0x7b, 0x03, 0xee, 0x9a, 0x9d, 0x8f, 0x8f, 0xbb, 0x66, 0x67, 0xdb, 0x3a, 0x38, 0xdc, + 0xee, 0x58, 0x3b, 0x9d, 0x76, 0xff, 0xd8, 0xec, 0x58, 0xfb, 0xdd, 0x5e, 0xaf, 0x7b, 0xf0, 0xb4, + 0xd9, 0x64, 0x6f, 0xc1, 0xfd, 0x08, 0x25, 0x6a, 0x60, 0x06, 0x6b, 0x51, 0xcc, 0x4f, 0x6d, 0xe9, + 0x41, 0xe7, 0xd7, 0xfb, 0xd6, 0x51, 0xa7, 0x63, 0x36, 0x19, 0x5b, 0x87, 0xd5, 0xb8, 0x7b, 0xea, + 0x40, 0xf6, 0xbd, 0x24, 0xca, 0x8e, 0x3a, 0xe6, 0x7e, 0xfb, 0x40, 0x6c, 0x70, 0xa2, 0x6c, 0x59, + 0x0c, 0x3b, 0x2e, 0x9b, 0x1d, 0xf6, 0x0a, 0x63, 0x50, 0xd7, 0x76, 0x65, 0xa7, 0x6d, 0x36, 0x57, + 0x59, 0x03, 0x2a, 0xfb, 0x47, 0x47, 0x56, 0xbf, 0xbb, 0xdf, 0x39, 0x3c, 0xee, 0x37, 0xd7, 0xd8, + 0x0a, 0x34, 0xbb, 0x07, 0xfd, 0x8e, 0x29, 0xf6, 0x5a, 0x55, 0xfd, 0xdf, 0x45, 0xb6, 0x0c, 0x0d, + 0x35, 0x52, 0x05, 0xfd, 0xcb, 0x22, 0x5b, 0x03, 0x76, 0x7c, 0x60, 0x76, 0xda, 0xdb, 0x62, 0xe1, + 0xa2, 0x82, 0xff, 0x53, 0x94, 0x1e, 0x92, 0x9f, 0xe5, 0xa2, 0xcb, 0x3a, 0x0e, 0x39, 0x48, 0x3e, + 0xe7, 0x5a, 0xd5, 0x9e, 0x61, 0x7d, 0xd9, 0x43, 0xeb, 0x9a, 0x6a, 0x95, 0x9b, 0x53, 0xad, 0xe6, + 0x74, 0xf7, 0x9a, 0x2e, 0xfb, 0xbd, 0x09, 0xb5, 0x31, 0x3d, 0xed, 0x2a, 0x9f, 0x70, 0x04, 0x19, + 0x7f, 0x43, 0x40, 0x7a, 0xbf, 0x71, 0xee, 0xa5, 0xf1, 0xc2, 0xfc, 0x4b, 0xe3, 0x69, 0xf2, 0xfd, + 0x42, 0x9a, 0x7c, 0xff, 0x10, 0x16, 0x89, 0x35, 0x39, 0xae, 0x33, 0x56, 0x5a, 0x33, 0x49, 0x81, + 0x0d, 0x64, 0x51, 0x04, 0x57, 0xea, 0x84, 0x52, 0x39, 0x24, 0x0b, 0x29, 0x4a, 0x6d, 0x23, 0xa1, + 0x69, 0x10, 0xe7, 0x88, 0x34, 0x8d, 0xa8, 0x07, 0xfb, 0x2a, 0xee, 0xa1, 0xa2, 0xf5, 0x40, 0x70, + 0xec, 0xe1, 0x21, 0x2c, 0xf2, 0xab, 0xd0, 0xb7, 0x2d, 0x6f, 0x62, 0x7f, 0x3e, 0x45, 0x17, 0xae, + 0x8d, 0x3a, 0x7c, 0xd5, 0x6c, 0x60, 0xc1, 0x21, 0xc2, 0xb7, 0xed, 0xd0, 0x7e, 0xf8, 0x05, 0x54, + 0xb4, 0x67, 0x7f, 0xd9, 0x1a, 0x2c, 0x7d, 0xda, 0xed, 0x1f, 0x74, 0x7a, 0x3d, 0xeb, 0xe8, 0x78, + 0xf3, 0x59, 0xe7, 0x33, 0x6b, 0xb7, 0xdd, 0xdb, 0x6d, 0xde, 0x12, 0x87, 0xf6, 0xa0, 0xd3, 0xeb, + 0x77, 0xb6, 0x13, 0xf0, 0x0c, 0x7b, 0x1d, 0xd6, 0x8f, 0x0f, 0x8e, 0x7b, 0x9d, 0x6d, 0x2b, 0xad, + 0x5e, 0x56, 0x50, 0xa9, 0x2c, 0x4f, 0xa9, 0x9e, 0x7b, 0xf8, 0x7d, 0xa8, 0x27, 0xdf, 0xa2, 0x64, + 0x00, 0x0b, 0x7b, 0x9d, 0xa7, 0xed, 0xad, 0xcf, 0xe8, 0x31, 0xbb, 0x5e, 0xbf, 0xdd, 0xef, 0x6e, + 0x59, 0xf2, 0xf1, 0x3a, 0xc1, 0x11, 0x32, 0xac, 0x02, 0xc5, 0xf6, 0xc1, 0xd6, 0xee, 0xa1, 0xd9, + 0x6b, 0x66, 0x1f, 0x7e, 0x04, 0xcd, 0x59, 0x7f, 0x54, 0xc2, 0x81, 0xf7, 0x22, 0x4f, 0xdf, 0xc3, + 0x7f, 0x9b, 0x03, 0x88, 0x13, 0x06, 0x04, 0xab, 0xd9, 0x6e, 0xf7, 0xdb, 0x7b, 0x87, 0x62, 0x1a, + 0xe6, 0x61, 0x5f, 0x70, 0x10, 0xb3, 0xf3, 0x71, 0xf3, 0x56, 0x6a, 0xc9, 0xe1, 0x51, 0xbf, 0x99, + 0x11, 0x2b, 0xd6, 0x3d, 0xe8, 0xf6, 0xbb, 0xed, 0x3d, 0xcb, 0x3c, 0x3c, 0xee, 0x1e, 0x3c, 0xa5, + 0x57, 0xba, 0x90, 0xcb, 0x1e, 0x1f, 0xed, 0x98, 0x87, 0x07, 0x7d, 0xab, 0xb7, 0x7b, 0xdc, 0xdf, + 0xc6, 0x37, 0xbe, 0xb6, 0xcc, 0xee, 0x11, 0xb5, 0x99, 0x7f, 0x11, 0x82, 0x68, 0xba, 0x20, 0xd6, + 0xfc, 0xe9, 0x61, 0xaf, 0xd7, 0x3d, 0xb2, 0x3e, 0x3e, 0xee, 0x98, 0xdd, 0x4e, 0x0f, 0x2b, 0x2e, + 0xa4, 0xc0, 0x05, 0x7e, 0x51, 0xf0, 0xe6, 0xfe, 0xde, 0x27, 0x92, 0x79, 0x0a, 0xd4, 0x52, 0x12, + 0x24, 0xb0, 0xca, 0x82, 0xa7, 0x08, 0xee, 0x93, 0xd2, 0x32, 0xdc, 0x50, 0x26, 0xea, 0x55, 0x04, + 0x5f, 0x9d, 0xdb, 0x0c, 0xac, 0x56, 0x4d, 0x2f, 0x12, 0xb5, 0x90, 0xe5, 0x46, 0x17, 0xd4, 0xf6, + 0xb6, 0x89, 0x15, 0xea, 0x73, 0x50, 0x81, 0xdb, 0x10, 0x1b, 0x25, 0xd8, 0x93, 0x40, 0x69, 0xaa, + 0x0f, 0x51, 0xb2, 0xf8, 0xe4, 0x77, 0x72, 0x50, 0xa7, 0xe4, 0x2d, 0xfa, 0xd5, 0x25, 0xee, 0xb3, + 0x7d, 0x28, 0xca, 0x9f, 0xef, 0x62, 0x2b, 0xd1, 0x03, 0x4a, 0xfa, 0x0f, 0x86, 0xad, 0xaf, 0xce, + 0x82, 0xa5, 0x38, 0xb6, 0xf4, 0xb7, 0xfe, 0xe4, 0x7f, 0xfd, 0xe3, 0x6c, 0x8d, 0x55, 0x1e, 0x5d, + 0xbc, 0xf7, 0xe8, 0x8c, 0xbb, 0x81, 0x68, 0xe3, 0xaf, 0x03, 0xc4, 0x3f, 0x4a, 0xc5, 0x5a, 0x91, + 0x13, 0x6a, 0xe6, 0x17, 0xbb, 0xd6, 0x6f, 0xa7, 0x94, 0xc8, 0x76, 0x6f, 0x63, 0xbb, 0x4b, 0x46, + 0x5d, 0xb4, 0xeb, 0xb8, 0x4e, 0x48, 0x3f, 0x50, 0xf5, 0x61, 0xe6, 0x21, 0x1b, 0x42, 0x55, 0xff, + 0xb9, 0x28, 0xa6, 0x24, 0xa5, 0x94, 0x1f, 0xbc, 0x5a, 0xbf, 0x93, 0x5a, 0xa6, 0x64, 0x50, 0xec, + 0x63, 0xc5, 0x68, 0x8a, 0x3e, 0xa6, 0x88, 0x11, 0xf7, 0x32, 0x22, 0xa9, 0x3c, 0xfe, 0x55, 0x28, + 0xf6, 0x9a, 0x26, 0x57, 0xcd, 0xfd, 0x26, 0xd5, 0xfa, 0xdd, 0x1b, 0x4a, 0x65, 0x5f, 0x77, 0xb1, + 0xaf, 0x35, 0x83, 0x89, 0xbe, 0x06, 0x88, 0xa3, 0x7e, 0x93, 0xea, 0xc3, 0xcc, 0xc3, 0x27, 0x7f, + 0xf1, 0x00, 0xca, 0x51, 0x30, 0x27, 0xfb, 0x2d, 0xa8, 0x25, 0xb2, 0xeb, 0x98, 0x9a, 0x46, 0x5a, + 0x32, 0xde, 0xfa, 0x6b, 0xe9, 0x85, 0xb2, 0xe3, 0xd7, 0xb1, 0xe3, 0x16, 0x5b, 0x15, 0x1d, 0xcb, + 0xec, 0xb5, 0x47, 0x98, 0x0d, 0x4b, 0xcf, 0x51, 0x3d, 0xd7, 0xb4, 0x0f, 0xea, 0xec, 0xb5, 0x59, + 0x8d, 0x20, 0xd1, 0xdb, 0xdd, 0x1b, 0x4a, 0x65, 0x77, 0xaf, 0x61, 0x77, 0xab, 0x6c, 0x59, 0xef, + 0x4e, 0x85, 0x5e, 0x32, 0x8e, 0x4f, 0xc0, 0xe9, 0x3f, 0x9a, 0xc4, 0xee, 0xc6, 0x0f, 0x76, 0xa5, + 0xfc, 0x98, 0x52, 0x44, 0x22, 0xf3, 0xbf, 0xa8, 0x64, 0xb4, 0xb0, 0x2b, 0xc6, 0x70, 0xfb, 0xf4, + 0xdf, 0x4c, 0x62, 0x27, 0x50, 0xd1, 0x7e, 0x67, 0x80, 0xdd, 0xbe, 0xf1, 0x37, 0x11, 0xd6, 0xd7, + 0xd3, 0x8a, 0xd2, 0xa6, 0xa2, 0xb7, 0xff, 0xe8, 0x94, 0x73, 0xf6, 0x1b, 0x50, 0x8e, 0x5e, 0xaf, + 0x67, 0x6b, 0xda, 0xaf, 0x09, 0xe8, 0xaf, 0xed, 0xaf, 0xb7, 0xe6, 0x0b, 0xd2, 0x88, 0x4f, 0x6f, + 0x5d, 0x10, 0xdf, 0xa7, 0x50, 0xd1, 0x5e, 0xa8, 0x8f, 0x26, 0x30, 0xff, 0x0a, 0x7e, 0x34, 0x81, + 0x94, 0x07, 0xed, 0x8d, 0x45, 0xec, 0xa2, 0xc2, 0xca, 0x48, 0xdf, 0xe1, 0x95, 0x17, 0xb0, 0x3d, + 0x58, 0x91, 0x9a, 0xd6, 0x09, 0xff, 0x32, 0xdb, 0x90, 0xf2, 0x3b, 0x55, 0x8f, 0x33, 0xec, 0x23, + 0x28, 0xa9, 0x1f, 0x22, 0x60, 0xab, 0xe9, 0x3f, 0xa8, 0xb0, 0xbe, 0x36, 0x07, 0x97, 0x6a, 0xd1, + 0x67, 0x00, 0xf1, 0x73, 0xf8, 0x11, 0x93, 0x98, 0x7b, 0x5e, 0x3f, 0xa2, 0x80, 0xf9, 0xb7, 0xf3, + 0x8d, 0x55, 0x9c, 0x60, 0x93, 0x21, 0x93, 0x70, 0xf9, 0xa5, 0x7a, 0xa7, 0xf3, 0x47, 0x50, 0xd1, + 0x5e, 0xc4, 0x8f, 0x96, 0x6f, 0xfe, 0x35, 0xfd, 0x68, 0xf9, 0x52, 0x1e, 0xd0, 0x37, 0xd6, 0xb1, + 0xf5, 0x65, 0xa3, 0x21, 0x5a, 0x17, 0xa2, 0x96, 0x14, 0x79, 0xc4, 0x06, 0x9d, 0x43, 0x2d, 0xf1, + 0xec, 0x7d, 0x74, 0x42, 0xd3, 0x1e, 0xd5, 0x8f, 0x4e, 0x68, 0xea, 0x4b, 0xf9, 0x8a, 0xce, 0x8c, + 0x45, 0xd1, 0xcf, 0x05, 0xa2, 0x68, 0x3d, 0xfd, 0x10, 0x2a, 0xda, 0x13, 0xf6, 0xd1, 0x5c, 0xe6, + 0x5f, 0xcb, 0x8f, 0xe6, 0x92, 0xf6, 0xe2, 0xfd, 0x32, 0xf6, 0x51, 0x37, 0x90, 0x14, 0xf0, 0xa5, + 0x41, 0xd1, 0xf6, 0x6f, 0x41, 0x3d, 0xf9, 0xaa, 0x7d, 0x74, 0xf6, 0x53, 0x9f, 0xc7, 0x8f, 0xce, + 0xfe, 0x0d, 0x4f, 0xe1, 0x4b, 0x92, 0x7e, 0xb8, 0x14, 0x75, 0xf2, 0xe8, 0x27, 0x32, 0x2d, 0xe5, + 0x0b, 0xf6, 0xb1, 0x60, 0x70, 0xf2, 0xa1, 0x4b, 0xb6, 0xa6, 0x51, 0xad, 0xfe, 0x62, 0x66, 0x74, + 0x5e, 0xe6, 0xde, 0xc4, 0x4c, 0x12, 0x33, 0x36, 0xce, 0x9e, 0xc2, 0x52, 0x44, 0xcc, 0xd1, 0xcb, + 0x95, 0x41, 0x34, 0x87, 0xd4, 0xf7, 0x31, 0xd7, 0x9b, 0xb3, 0xa5, 0x8f, 0x33, 0x74, 0xfd, 0xe1, + 0x7b, 0x81, 0xda, 0xf5, 0xa7, 0x3f, 0x5e, 0xa9, 0x5d, 0x7f, 0x89, 0x67, 0x05, 0x67, 0xaf, 0xbf, + 0xd0, 0x11, 0x6d, 0xb8, 0xd0, 0x98, 0x7d, 0x47, 0xf2, 0xee, 0x4d, 0x69, 0xff, 0xd4, 0xfc, 0xeb, + 0x2f, 0x7e, 0x15, 0x20, 0xc9, 0x8a, 0x14, 0x37, 0x7d, 0x24, 0x83, 0x4f, 0xd8, 0x6f, 0x42, 0x55, + 0x7f, 0x52, 0x9b, 0xe9, 0x3c, 0x61, 0xb6, 0xa7, 0x3b, 0xa9, 0x65, 0x49, 0x2a, 0x61, 0x55, 0xbd, + 0x1b, 0xf6, 0x09, 0xac, 0x46, 0xcb, 0xac, 0xe7, 0xad, 0x07, 0xec, 0x5e, 0x4a, 0x36, 0x7b, 0x62, + 0xb1, 0x6f, 0xdf, 0x98, 0xee, 0xfe, 0x38, 0x23, 0xa8, 0x2f, 0xf9, 0xb6, 0x6f, 0x7c, 0xf3, 0xa4, + 0x3d, 0x69, 0x1c, 0xdf, 0x3c, 0xa9, 0x0f, 0x02, 0x2b, 0xea, 0x63, 0x4b, 0x89, 0x35, 0xa2, 0xb0, + 0x5c, 0xf6, 0x43, 0x68, 0x68, 0x49, 0xf9, 0xbd, 0x6b, 0x77, 0x10, 0x9d, 0xa4, 0xf9, 0xc7, 0xe9, + 0xd6, 0xd3, 0x6c, 0x93, 0xc6, 0x1a, 0xb6, 0xbf, 0x68, 0x24, 0x16, 0x47, 0x9c, 0xa2, 0x2d, 0xa8, + 0xe8, 0x09, 0xff, 0x2f, 0x68, 0x77, 0x4d, 0x2b, 0xd2, 0xdf, 0x41, 0x7b, 0x9c, 0x61, 0x7b, 0xd0, + 0x9c, 0x7d, 0xb6, 0x29, 0xe2, 0x29, 0x69, 0x4f, 0x4d, 0xad, 0xcf, 0x14, 0x26, 0x1e, 0x7b, 0x62, + 0x47, 0x94, 0xd8, 0x11, 0xfd, 0xa8, 0x93, 0xe7, 0xcf, 0xde, 0xea, 0xc9, 0x1f, 0x7b, 0x8a, 0x5a, + 0x4b, 0xfb, 0x99, 0xaf, 0x07, 0x99, 0xc7, 0x19, 0xf6, 0xbb, 0x19, 0xa8, 0x26, 0x9e, 0x4a, 0x49, + 0x84, 0xce, 0xcf, 0xcc, 0xb3, 0xa5, 0x97, 0xe9, 0x13, 0x35, 0x4c, 0x5c, 0xc4, 0xbd, 0x87, 0x3f, + 0x48, 0x6c, 0xd2, 0x4f, 0x12, 0xae, 0xbd, 0x8d, 0xd9, 0x5f, 0x7d, 0xfa, 0x62, 0x16, 0x41, 0x7f, + 0x73, 0xf0, 0x8b, 0xc7, 0x19, 0xf6, 0xef, 0x33, 0x50, 0x4f, 0xfa, 0xec, 0xa3, 0xe9, 0xa6, 0x46, + 0x07, 0x44, 0xa4, 0x74, 0x83, 0xa3, 0xff, 0x87, 0x38, 0xca, 0xfe, 0x43, 0x33, 0x31, 0x4a, 0xf9, + 0x2a, 0xf5, 0x2f, 0x36, 0x5a, 0xf6, 0x21, 0xfd, 0xc8, 0xa2, 0x0a, 0x65, 0x62, 0xf3, 0x3f, 0xca, + 0x17, 0x91, 0x9f, 0xfe, 0x13, 0x76, 0xb8, 0x09, 0x3f, 0xa2, 0x5f, 0x37, 0x52, 0x91, 0x31, 0x82, + 0x8a, 0x5f, 0xb5, 0xbe, 0xf1, 0x16, 0xce, 0xe9, 0x75, 0xe3, 0x76, 0x62, 0x4e, 0xb3, 0x82, 0x47, + 0x9b, 0x46, 0x27, 0x7f, 0x81, 0x2e, 0xbe, 0x39, 0xe7, 0x7e, 0x95, 0xee, 0xe6, 0x41, 0x8e, 0x69, + 0x90, 0x12, 0x3d, 0x71, 0xd4, 0x5e, 0xb1, 0x19, 0xe3, 0x21, 0x8e, 0xf5, 0x2d, 0xe3, 0xde, 0x8d, + 0x63, 0x7d, 0x84, 0xfe, 0x77, 0x31, 0xe2, 0x23, 0x80, 0x38, 0xd4, 0x90, 0xcd, 0x04, 0xbc, 0x45, + 0x0c, 0x68, 0x3e, 0x1a, 0x31, 0x79, 0x9e, 0x55, 0x5c, 0x9c, 0x68, 0xf1, 0x37, 0x88, 0x9d, 0x46, + 0xa1, 0x78, 0xba, 0xf4, 0x95, 0x8c, 0x0a, 0x4c, 0x48, 0x5f, 0xb3, 0xed, 0x27, 0x98, 0x69, 0x14, + 0x77, 0x77, 0x0c, 0xb5, 0x3d, 0xcf, 0x7b, 0x3e, 0x9d, 0x44, 0xe1, 0xed, 0xc9, 0xa0, 0x98, 0x5d, + 0x3b, 0x38, 0x5f, 0x9f, 0x99, 0x85, 0x71, 0x1f, 0x9b, 0x5a, 0x67, 0x2d, 0xad, 0xa9, 0x47, 0x3f, + 0x89, 0xe3, 0x1b, 0xbf, 0x60, 0x36, 0x2c, 0x46, 0x3c, 0x3a, 0x8e, 0x21, 0x4c, 0x36, 0x93, 0xe0, + 0xcc, 0xb3, 0x5d, 0x24, 0xd4, 0x04, 0x35, 0xda, 0x47, 0x81, 0x6a, 0xf3, 0x71, 0x86, 0x1d, 0x41, + 0x75, 0x9b, 0x0f, 0x30, 0x51, 0x1f, 0x43, 0x4b, 0x96, 0x12, 0x61, 0x0a, 0x14, 0x93, 0xb2, 0x5e, + 0x4b, 0x00, 0x93, 0xf7, 0xd6, 0xc4, 0xbe, 0xf6, 0xf9, 0xe7, 0x8f, 0x7e, 0x22, 0x83, 0x56, 0xbe, + 0x50, 0xf7, 0x96, 0x0a, 0xea, 0x49, 0xdc, 0x5b, 0x33, 0x51, 0x40, 0x89, 0x7b, 0x6b, 0x2e, 0x0a, + 0x28, 0xb1, 0xd4, 0x2a, 0xa8, 0x88, 0x8d, 0x60, 0x71, 0x2e, 0x70, 0x28, 0xba, 0xb2, 0x6e, 0x0a, + 0x37, 0x5a, 0xbf, 0x7f, 0x33, 0x42, 0xb2, 0xb7, 0x87, 0xc9, 0xde, 0x7a, 0x50, 0xa3, 0x67, 0x10, + 0x4f, 0x38, 0xa5, 0xec, 0xcd, 0xbc, 0x77, 0xa3, 0xe7, 0x03, 0xce, 0x5e, 0x30, 0x58, 0x96, 0x94, + 0x70, 0x30, 0x57, 0x8e, 0xfd, 0x06, 0x54, 0x9e, 0xf2, 0x50, 0xe5, 0xe8, 0x45, 0x32, 0xf6, 0x4c, + 0xd2, 0xde, 0x7a, 0x4a, 0x8a, 0x5f, 0x92, 0x66, 0xb0, 0xb5, 0x47, 0x7c, 0x78, 0xc6, 0x89, 0x39, + 0x59, 0xce, 0xf0, 0x0b, 0xf6, 0xeb, 0xd8, 0x78, 0x94, 0x1a, 0xbd, 0xaa, 0x25, 0x61, 0xe9, 0x8d, + 0x37, 0x66, 0xe0, 0x69, 0x2d, 0xbb, 0xde, 0x90, 0x6b, 0xb2, 0x9e, 0x0b, 0x15, 0xed, 0x09, 0x85, + 0xe8, 0x00, 0xcd, 0x3f, 0x99, 0x11, 0x1d, 0xa0, 0x94, 0x17, 0x17, 0x8c, 0x07, 0xd8, 0x8f, 0xc1, + 0xee, 0xc7, 0xfd, 0xd0, 0x2b, 0x0b, 0x71, 0x4f, 0x8f, 0x7e, 0x62, 0x8f, 0xc3, 0x2f, 0xd8, 0xa7, + 0xf8, 0xd8, 0xb8, 0x9e, 0x83, 0x18, 0x2b, 0x0d, 0xb3, 0xe9, 0x8a, 0xd1, 0x62, 0x69, 0x45, 0x49, + 0x45, 0x82, 0xba, 0x42, 0x49, 0xee, 0x7d, 0x80, 0x5e, 0xe8, 0x4d, 0xb6, 0x6d, 0x3e, 0xf6, 0xdc, + 0x98, 0xd7, 0xc6, 0x59, 0x71, 0x31, 0xff, 0xd2, 0x52, 0xe3, 0xd8, 0xa7, 0x9a, 0x96, 0x95, 0x48, + 0xe3, 0x54, 0xc4, 0x75, 0x63, 0xe2, 0x5c, 0xb4, 0x20, 0x29, 0xc9, 0x73, 0x8f, 0x33, 0xac, 0x0d, + 0x10, 0x47, 0x8e, 0x45, 0x3a, 0xd3, 0x5c, 0x50, 0x5a, 0xc4, 0xf6, 0x52, 0xc2, 0xcc, 0x8e, 0xa0, + 0x1c, 0x87, 0xdc, 0xac, 0xc5, 0x2f, 0xc2, 0x24, 0x02, 0x74, 0xa2, 0x1b, 0x7c, 0x2e, 0xdc, 0xc5, + 0x68, 0xe2, 0x52, 0x01, 0x2b, 0x89, 0xa5, 0x3a, 0xe5, 0x3c, 0x60, 0x0e, 0x2c, 0xd1, 0x00, 0x23, + 0x71, 0x09, 0xb3, 0xb9, 0xa2, 0x37, 0xe5, 0xe7, 0x23, 0x4f, 0xa2, 0xd3, 0x9c, 0x1a, 0x3f, 0x91, + 0x30, 0xfd, 0x08, 0x6a, 0xa5, 0x4c, 0x32, 0xc1, 0x9a, 0xc7, 0xb0, 0x38, 0xe7, 0xa2, 0x8f, 0x8e, + 0xf4, 0x4d, 0x31, 0x17, 0xd1, 0x91, 0xbe, 0xd1, 0xbb, 0x6f, 0xac, 0x60, 0x97, 0x0d, 0x03, 0x50, + 0xd5, 0xbb, 0x74, 0xc2, 0xc1, 0xb9, 0xe8, 0xee, 0xdf, 0x64, 0x60, 0x29, 0xc5, 0x09, 0xcf, 0xde, + 0x50, 0x56, 0x83, 0x1b, 0x1d, 0xf4, 0xeb, 0xa9, 0xce, 0x5a, 0xa3, 0x87, 0xfd, 0xec, 0xb3, 0x67, + 0x89, 0x8b, 0x8d, 0x7c, 0xa5, 0xf2, 0x64, 0xbe, 0x50, 0xa8, 0x48, 0x95, 0x28, 0x3e, 0x87, 0x35, + 0x1a, 0x48, 0x7b, 0x34, 0x9a, 0x71, 0x24, 0xbf, 0x3e, 0xf7, 0x23, 0xec, 0x09, 0xe7, 0xf8, 0xfa, + 0xcd, 0x3f, 0xd2, 0x7e, 0x83, 0x38, 0x4d, 0x43, 0x65, 0x53, 0x68, 0xce, 0x3a, 0x68, 0xd9, 0xcd, + 0x6d, 0xad, 0xdf, 0x4b, 0xe8, 0xbf, 0x29, 0x4e, 0xdd, 0xaf, 0x61, 0x67, 0xf7, 0x8c, 0xf5, 0xb4, + 0x75, 0x21, 0x95, 0x58, 0xec, 0xc7, 0xdf, 0x8c, 0xbc, 0xc9, 0x33, 0xf3, 0x54, 0x1d, 0xdc, 0xe4, + 0xfb, 0x8e, 0x34, 0xf0, 0x74, 0x67, 0xf4, 0xdb, 0xd8, 0xfd, 0x7d, 0xe3, 0x4e, 0x5a, 0xf7, 0x3e, + 0x55, 0x21, 0x5d, 0x7c, 0x6d, 0xf6, 0x5c, 0xab, 0x11, 0xdc, 0x4f, 0xdb, 0xef, 0x1b, 0x75, 0xa1, + 0x99, 0xb5, 0xbe, 0x85, 0xb2, 0x5d, 0x55, 0xf7, 0x1e, 0x47, 0xc7, 0x27, 0xc5, 0x4d, 0x1d, 0x1d, + 0x9f, 0x34, 0x77, 0x73, 0x52, 0xae, 0x51, 0x8e, 0xe6, 0x0f, 0x33, 0x0f, 0x37, 0xdf, 0xf9, 0xe1, + 0xd7, 0xce, 0x9c, 0xf0, 0x7c, 0x7a, 0xb2, 0x31, 0xf0, 0xc6, 0x8f, 0x46, 0xca, 0xda, 0x28, 0x53, + 0x9e, 0x1f, 0x8d, 0xdc, 0xe1, 0x23, 0x6c, 0xf6, 0x64, 0x61, 0xe2, 0x7b, 0xa1, 0xf7, 0xad, 0xff, + 0x17, 0x00, 0x00, 0xff, 0xff, 0x90, 0xab, 0x21, 0xed, 0x67, 0x82, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 64f7a30c53..dc32ab4269 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2016,6 +2016,14 @@ message PendingChannelsResponse { int64 recovered_balance = 6; repeated PendingHTLC pending_htlcs = 8; + + enum AnchorState { + LIMBO = 0; + RECOVERED = 1; + LOST = 2; + } + + AnchorState anchor = 9; } /// The balance in satoshis encumbered in pending channels diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 73f192928e..b8a9f6e8a0 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1534,6 +1534,15 @@ "default": "RESERVED", "description": " - RESERVED: *\nThe numbers assigned in this enumeration match the failure codes as\ndefined in BOLT #4. Because protobuf 3 requires enums to start with 0,\na RESERVED value is added.\n - INTERNAL_FAILURE: *\nAn internal error occurred.\n - UNKNOWN_FAILURE: *\nThe error source is known, but the failure itself couldn't be decoded.\n - UNREADABLE_FAILURE: *\nAn unreadable failure result is returned if the received failure message\ncannot be decrypted. In that case the error source is unknown." }, + "ForceClosedChannelAnchorState": { + "type": "string", + "enum": [ + "LIMBO", + "RECOVERED", + "LOST" + ], + "default": "LIMBO" + }, "HTLCAttemptHTLCStatus": { "type": "string", "enum": [ @@ -1630,6 +1639,9 @@ "items": { "$ref": "#/definitions/lnrpcPendingHTLC" } + }, + "anchor": { + "$ref": "#/definitions/ForceClosedChannelAnchorState" } } }, diff --git a/rpcserver.go b/rpcserver.go index bed4e79d41..2a123e7fe3 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2839,6 +2839,22 @@ func (r *rpcServer) arbitratorPopulateForceCloseResp(chanPoint *wire.OutPoint, forceClose.PendingHtlcs = append(forceClose.PendingHtlcs, htlc) + case contractcourt.ReportOutputAnchor: + // There are three resolution states for the anchor: + // limbo, lost and recovered. Derive the current state + // from the limbo and recovered balances. + switch { + + case report.RecoveredBalance != 0: + forceClose.Anchor = lnrpc.PendingChannelsResponse_ForceClosedChannel_RECOVERED + + case report.LimboBalance != 0: + forceClose.Anchor = lnrpc.PendingChannelsResponse_ForceClosedChannel_LIMBO + + default: + forceClose.Anchor = lnrpc.PendingChannelsResponse_ForceClosedChannel_LOST + } + default: return fmt.Errorf("unknown report output type: %v", report.Type) @@ -2846,7 +2862,6 @@ func (r *rpcServer) arbitratorPopulateForceCloseResp(chanPoint *wire.OutPoint, forceClose.LimboBalance += int64(report.LimboBalance) forceClose.RecoveredBalance += int64(report.RecoveredBalance) - } return nil From d60303b092c01dd9cb357192e0f96c1640475235 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 11 Mar 2020 16:48:45 +0100 Subject: [PATCH 243/562] lnrpc: expose commit hashes for waiting close channels To make it easier to determine which pending sweep to bump in order to get your anchor commitment tx confirmed. --- lnrpc/rpc.pb.go | 1501 +++++++++++++++++++++------------------- lnrpc/rpc.proto | 17 + lnrpc/rpc.swagger.json | 21 + rpcserver.go | 49 +- 4 files changed, 870 insertions(+), 718 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index f49fdbebb4..4034832138 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -349,7 +349,7 @@ func (x PendingChannelsResponse_ForceClosedChannel_AnchorState) String() string } func (PendingChannelsResponse_ForceClosedChannel_AnchorState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 4, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{72, 5, 0} } type ChannelEventUpdate_UpdateType int32 @@ -5685,10 +5685,14 @@ type PendingChannelsResponse_WaitingCloseChannel struct { /// The pending channel waiting for closing tx to confirm Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` /// The balance in satoshis encumbered in this channel - LimboBalance int64 `protobuf:"varint,2,opt,name=limbo_balance,json=limboBalance,proto3" json:"limbo_balance,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + LimboBalance int64 `protobuf:"varint,2,opt,name=limbo_balance,json=limboBalance,proto3" json:"limbo_balance,omitempty"` + //* + //A list of valid commitment transactions. Any of these can confirm at + //this point. + Commitments *PendingChannelsResponse_Commitments `protobuf:"bytes,3,opt,name=commitments,proto3" json:"commitments,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *PendingChannelsResponse_WaitingCloseChannel) Reset() { @@ -5734,6 +5738,71 @@ func (m *PendingChannelsResponse_WaitingCloseChannel) GetLimboBalance() int64 { return 0 } +func (m *PendingChannelsResponse_WaitingCloseChannel) GetCommitments() *PendingChannelsResponse_Commitments { + if m != nil { + return m.Commitments + } + return nil +} + +type PendingChannelsResponse_Commitments struct { + /// Hash of the local version of the commitment tx. + LocalTxid string `protobuf:"bytes,1,opt,name=local_txid,json=localTxid,proto3" json:"local_txid,omitempty"` + /// Hash of the remote version of the commitment tx. + RemoteTxid string `protobuf:"bytes,2,opt,name=remote_txid,json=remoteTxid,proto3" json:"remote_txid,omitempty"` + /// Hash of the remote pending version of the commitment tx. + RemotePendingTxid string `protobuf:"bytes,3,opt,name=remote_pending_txid,json=remotePendingTxid,proto3" json:"remote_pending_txid,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PendingChannelsResponse_Commitments) Reset() { *m = PendingChannelsResponse_Commitments{} } +func (m *PendingChannelsResponse_Commitments) String() string { return proto.CompactTextString(m) } +func (*PendingChannelsResponse_Commitments) ProtoMessage() {} +func (*PendingChannelsResponse_Commitments) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{72, 3} +} + +func (m *PendingChannelsResponse_Commitments) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PendingChannelsResponse_Commitments.Unmarshal(m, b) +} +func (m *PendingChannelsResponse_Commitments) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PendingChannelsResponse_Commitments.Marshal(b, m, deterministic) +} +func (m *PendingChannelsResponse_Commitments) XXX_Merge(src proto.Message) { + xxx_messageInfo_PendingChannelsResponse_Commitments.Merge(m, src) +} +func (m *PendingChannelsResponse_Commitments) XXX_Size() int { + return xxx_messageInfo_PendingChannelsResponse_Commitments.Size(m) +} +func (m *PendingChannelsResponse_Commitments) XXX_DiscardUnknown() { + xxx_messageInfo_PendingChannelsResponse_Commitments.DiscardUnknown(m) +} + +var xxx_messageInfo_PendingChannelsResponse_Commitments proto.InternalMessageInfo + +func (m *PendingChannelsResponse_Commitments) GetLocalTxid() string { + if m != nil { + return m.LocalTxid + } + return "" +} + +func (m *PendingChannelsResponse_Commitments) GetRemoteTxid() string { + if m != nil { + return m.RemoteTxid + } + return "" +} + +func (m *PendingChannelsResponse_Commitments) GetRemotePendingTxid() string { + if m != nil { + return m.RemotePendingTxid + } + return "" +} + type PendingChannelsResponse_ClosedChannel struct { /// The pending channel to be closed Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` @@ -5748,7 +5817,7 @@ func (m *PendingChannelsResponse_ClosedChannel) Reset() { *m = PendingCh func (m *PendingChannelsResponse_ClosedChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_ClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 3} + return fileDescriptor_77a6da22d6a3feb1, []int{72, 4} } func (m *PendingChannelsResponse_ClosedChannel) XXX_Unmarshal(b []byte) error { @@ -5814,7 +5883,7 @@ func (m *PendingChannelsResponse_ForceClosedChannel) String() string { } func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ForceClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 4} + return fileDescriptor_77a6da22d6a3feb1, []int{72, 5} } func (m *PendingChannelsResponse_ForceClosedChannel) XXX_Unmarshal(b []byte) error { @@ -11166,6 +11235,7 @@ func init() { proto.RegisterType((*PendingChannelsResponse_PendingChannel)(nil), "lnrpc.PendingChannelsResponse.PendingChannel") proto.RegisterType((*PendingChannelsResponse_PendingOpenChannel)(nil), "lnrpc.PendingChannelsResponse.PendingOpenChannel") proto.RegisterType((*PendingChannelsResponse_WaitingCloseChannel)(nil), "lnrpc.PendingChannelsResponse.WaitingCloseChannel") + proto.RegisterType((*PendingChannelsResponse_Commitments)(nil), "lnrpc.PendingChannelsResponse.Commitments") proto.RegisterType((*PendingChannelsResponse_ClosedChannel)(nil), "lnrpc.PendingChannelsResponse.ClosedChannel") proto.RegisterType((*PendingChannelsResponse_ForceClosedChannel)(nil), "lnrpc.PendingChannelsResponse.ForceClosedChannel") proto.RegisterType((*ChannelEventSubscription)(nil), "lnrpc.ChannelEventSubscription") @@ -11255,712 +11325,717 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11277 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x8f, 0x24, 0xd7, - 0x79, 0xd8, 0xf6, 0x6d, 0xba, 0xfb, 0xeb, 0xeb, 0x9c, 0xb9, 0xf5, 0xce, 0x72, 0xb9, 0xcb, 0x22, - 0x45, 0xae, 0x96, 0xd2, 0xec, 0x72, 0x25, 0x52, 0x32, 0x19, 0xcb, 0xea, 0x99, 0xe9, 0xd9, 0x69, - 0xed, 0xdc, 0x58, 0xdd, 0x43, 0x9a, 0x72, 0x9c, 0x52, 0x4d, 0xf7, 0x99, 0x99, 0xf2, 0x76, 0x57, - 0x35, 0xab, 0xaa, 0xe7, 0x22, 0x81, 0x79, 0xc8, 0xc5, 0x08, 0x82, 0x24, 0x80, 0x91, 0x28, 0x40, - 0x9c, 0x18, 0x09, 0x12, 0x04, 0x41, 0x10, 0xc0, 0x70, 0x20, 0x07, 0xc8, 0x43, 0xde, 0xfd, 0x92, - 0xc0, 0x0f, 0x76, 0x5e, 0x02, 0xc3, 0x80, 0x91, 0xc4, 0x79, 0x0b, 0xfc, 0x13, 0x82, 0xf3, 0x7d, - 0xe7, 0x54, 0x9d, 0xea, 0xae, 0xd9, 0x5d, 0x4a, 0x8c, 0x5e, 0x76, 0xa7, 0xbe, 0xf3, 0x9d, 0xfb, - 0x77, 0xbe, 0xf3, 0x5d, 0x4f, 0x43, 0xd9, 0x9f, 0x0c, 0x36, 0x26, 0xbe, 0x17, 0x7a, 0xac, 0x30, - 0x72, 0xfd, 0xc9, 0x60, 0xfd, 0xb5, 0x33, 0xcf, 0x3b, 0x1b, 0xf1, 0x47, 0xf6, 0xc4, 0x79, 0x64, - 0xbb, 0xae, 0x17, 0xda, 0xa1, 0xe3, 0xb9, 0x01, 0x21, 0x19, 0x3f, 0x82, 0xfa, 0x53, 0xee, 0xf6, - 0x38, 0x1f, 0x9a, 0xfc, 0xf3, 0x29, 0x0f, 0x42, 0xf6, 0x2e, 0x2c, 0xda, 0xfc, 0xc7, 0x9c, 0x0f, - 0xad, 0x89, 0x1d, 0x04, 0x93, 0x73, 0xdf, 0x0e, 0x78, 0x2b, 0x73, 0x3f, 0xf3, 0xa0, 0x6a, 0x36, - 0xa9, 0xe0, 0x28, 0x82, 0xb3, 0x37, 0xa0, 0x1a, 0x08, 0x54, 0xee, 0x86, 0xbe, 0x37, 0xb9, 0x6e, - 0x65, 0x11, 0xaf, 0x22, 0x60, 0x1d, 0x02, 0x19, 0x23, 0x68, 0x44, 0x3d, 0x04, 0x13, 0xcf, 0x0d, - 0x38, 0x7b, 0x0c, 0xcb, 0x03, 0x67, 0x72, 0xce, 0x7d, 0x0b, 0x2b, 0x8f, 0x5d, 0x3e, 0xf6, 0x5c, - 0x67, 0xd0, 0xca, 0xdc, 0xcf, 0x3d, 0x28, 0x9b, 0x8c, 0xca, 0x44, 0x8d, 0x7d, 0x59, 0xc2, 0xde, - 0x81, 0x06, 0x77, 0x09, 0xce, 0x87, 0x58, 0x4b, 0x76, 0x55, 0x8f, 0xc1, 0xa2, 0x82, 0xf1, 0xf7, - 0xb2, 0xb0, 0xd8, 0x75, 0x9d, 0xf0, 0x53, 0x7b, 0x34, 0xe2, 0xa1, 0x9a, 0xd3, 0x3b, 0xd0, 0xb8, - 0x44, 0x00, 0xce, 0xe9, 0xd2, 0xf3, 0x87, 0x72, 0x46, 0x75, 0x02, 0x1f, 0x49, 0xe8, 0x8d, 0x23, - 0xcb, 0xde, 0x38, 0xb2, 0xd4, 0xe5, 0xca, 0xdd, 0xb0, 0x5c, 0xef, 0x40, 0xc3, 0xe7, 0x03, 0xef, - 0x82, 0xfb, 0xd7, 0xd6, 0xa5, 0xe3, 0x0e, 0xbd, 0xcb, 0x56, 0xfe, 0x7e, 0xe6, 0x41, 0xc1, 0xac, - 0x2b, 0xf0, 0xa7, 0x08, 0x65, 0x9b, 0xd0, 0x18, 0x9c, 0xdb, 0xae, 0xcb, 0x47, 0xd6, 0x89, 0x3d, - 0x78, 0x3e, 0x9d, 0x04, 0xad, 0xc2, 0xfd, 0xcc, 0x83, 0xca, 0x93, 0xdb, 0x1b, 0xb8, 0xab, 0x1b, - 0x5b, 0xe7, 0xb6, 0xbb, 0x89, 0x25, 0x3d, 0xd7, 0x9e, 0x04, 0xe7, 0x5e, 0x68, 0xd6, 0x65, 0x0d, - 0x02, 0x07, 0xc6, 0x32, 0x30, 0x7d, 0x25, 0x68, 0xed, 0x8d, 0xff, 0x90, 0x81, 0xa5, 0x63, 0x77, - 0xe4, 0x0d, 0x9e, 0xff, 0x9c, 0x4b, 0x94, 0x32, 0x87, 0xec, 0xab, 0xce, 0x21, 0xf7, 0x65, 0xe7, - 0xb0, 0x0a, 0xcb, 0xc9, 0xc1, 0xca, 0x59, 0x70, 0x58, 0x11, 0xb5, 0xcf, 0xb8, 0x1a, 0x96, 0x9a, - 0xc6, 0xd7, 0xa1, 0x39, 0x98, 0xfa, 0x3e, 0x77, 0xe7, 0xe6, 0xd1, 0x90, 0xf0, 0x68, 0x22, 0x6f, - 0x40, 0xd5, 0xe5, 0x97, 0x31, 0x9a, 0xa4, 0x5d, 0x97, 0x5f, 0x2a, 0x14, 0xa3, 0x05, 0xab, 0xb3, - 0xdd, 0xc8, 0x01, 0xfc, 0x65, 0x06, 0xf2, 0xc7, 0xe1, 0x95, 0xc7, 0xde, 0x87, 0xaa, 0x3d, 0x1c, - 0xfa, 0x3c, 0x08, 0xac, 0xf0, 0x7a, 0x42, 0x27, 0xa5, 0xfe, 0x84, 0xc9, 0x29, 0xb6, 0xa9, 0xa8, - 0x7f, 0x3d, 0xe1, 0x66, 0xc5, 0x8e, 0x3f, 0x58, 0x0b, 0x8a, 0xf2, 0x13, 0xfb, 0x2d, 0x9b, 0xea, - 0x93, 0xdd, 0x05, 0xb0, 0xc7, 0xde, 0xd4, 0x0d, 0xad, 0xc0, 0x0e, 0x71, 0xc5, 0x72, 0x66, 0x99, - 0x20, 0x3d, 0x3b, 0x64, 0x77, 0xa0, 0x3c, 0x79, 0x6e, 0x05, 0x03, 0xdf, 0x99, 0x84, 0x48, 0x3c, - 0x65, 0xb3, 0x34, 0x79, 0xde, 0xc3, 0x6f, 0xf6, 0x2e, 0x94, 0xbc, 0x69, 0x38, 0xf1, 0x1c, 0x37, - 0x94, 0xf4, 0xd2, 0x90, 0x03, 0x39, 0x9c, 0x86, 0x47, 0x02, 0x6c, 0x46, 0x08, 0xec, 0x2d, 0xa8, - 0x0d, 0x3c, 0xf7, 0xd4, 0xf1, 0xc7, 0xc4, 0x11, 0x5a, 0x0b, 0xd8, 0x57, 0x12, 0x68, 0xfc, 0x41, - 0x16, 0x2a, 0x7d, 0xdf, 0x76, 0x03, 0x7b, 0x20, 0x00, 0x6c, 0x0d, 0x8a, 0xe1, 0x95, 0x75, 0x6e, - 0x07, 0xe7, 0x38, 0xd5, 0xb2, 0xb9, 0x10, 0x5e, 0xed, 0xda, 0xc1, 0x39, 0x5b, 0x85, 0x05, 0x1a, - 0x25, 0x4e, 0x28, 0x67, 0xca, 0x2f, 0x71, 0x40, 0xdc, 0xe9, 0xd8, 0x4a, 0x76, 0x95, 0x43, 0x8a, - 0x69, 0xba, 0xd3, 0xf1, 0x96, 0x0e, 0x17, 0x93, 0x3f, 0x11, 0xdb, 0x4d, 0x1d, 0xd0, 0xf4, 0xca, - 0x08, 0xc1, 0x3e, 0xde, 0x80, 0xaa, 0x2c, 0xe6, 0xce, 0xd9, 0x39, 0xcd, 0xb1, 0x60, 0x56, 0x08, - 0x01, 0x41, 0xa2, 0x85, 0xd0, 0x19, 0x73, 0x2b, 0x08, 0xed, 0xf1, 0x44, 0x4e, 0xa9, 0x2c, 0x20, - 0x3d, 0x01, 0xc0, 0x62, 0x2f, 0xb4, 0x47, 0xd6, 0x29, 0xe7, 0x41, 0xab, 0x28, 0x8b, 0x05, 0x64, - 0x87, 0xf3, 0x80, 0x7d, 0x0d, 0xea, 0x43, 0x1e, 0x84, 0x96, 0xdc, 0x0c, 0x1e, 0xb4, 0x4a, 0x78, - 0xf2, 0x6b, 0x02, 0xda, 0x56, 0x40, 0xf6, 0x1a, 0x80, 0x6f, 0x5f, 0x5a, 0x62, 0x21, 0xf8, 0x55, - 0xab, 0x4c, 0xbb, 0xe0, 0xdb, 0x97, 0xfd, 0xab, 0x5d, 0x7e, 0x25, 0xa8, 0xe6, 0x29, 0x0f, 0xb5, - 0x45, 0x0b, 0x24, 0x75, 0x1a, 0x7b, 0xc0, 0x34, 0xf0, 0x36, 0x0f, 0x6d, 0x67, 0x14, 0xb0, 0x0f, - 0xa0, 0x1a, 0x6a, 0xc8, 0xc8, 0x06, 0x2b, 0x11, 0x09, 0x69, 0x15, 0xcc, 0x04, 0x9e, 0x71, 0x0e, - 0xa5, 0x1d, 0xce, 0xf7, 0x9c, 0xb1, 0x13, 0xb2, 0x55, 0x28, 0x9c, 0x3a, 0x57, 0x9c, 0x88, 0x3d, - 0xb7, 0x7b, 0xcb, 0xa4, 0x4f, 0x76, 0x0f, 0x00, 0xff, 0xb0, 0xc6, 0x11, 0x35, 0xed, 0xde, 0x32, - 0xcb, 0x08, 0xdb, 0x0f, 0xec, 0x90, 0xad, 0x43, 0x71, 0xc2, 0xfd, 0x01, 0x57, 0xfb, 0xb6, 0x7b, - 0xcb, 0x54, 0x80, 0xcd, 0x22, 0x14, 0x46, 0xa2, 0x75, 0xe3, 0x8f, 0x0a, 0x50, 0xe9, 0x71, 0x37, - 0x3a, 0x65, 0x0c, 0xf2, 0x62, 0x41, 0xe4, 0xc9, 0xc2, 0xbf, 0xd9, 0x9b, 0x50, 0xc1, 0xa5, 0x0b, - 0x42, 0xdf, 0x71, 0xcf, 0x88, 0xaa, 0x37, 0xb3, 0xad, 0x8c, 0x09, 0x02, 0xdc, 0x43, 0x28, 0x6b, - 0x42, 0xce, 0x1e, 0x2b, 0xaa, 0x16, 0x7f, 0xb2, 0xdb, 0x50, 0xb2, 0xc7, 0x21, 0x0d, 0xaf, 0x8a, - 0xe0, 0xa2, 0x3d, 0x0e, 0x71, 0x68, 0x6f, 0x40, 0x75, 0x62, 0x5f, 0x8f, 0xc5, 0x59, 0x8e, 0xc8, - 0xa1, 0x6a, 0x56, 0x24, 0x0c, 0x09, 0xe2, 0x09, 0x2c, 0xe9, 0x28, 0xaa, 0xf3, 0x42, 0xd4, 0xf9, - 0xa2, 0x86, 0x2d, 0xc7, 0xf0, 0x0e, 0x34, 0x54, 0x1d, 0x9f, 0xe6, 0x83, 0x64, 0x52, 0x36, 0xeb, - 0x12, 0xac, 0x66, 0xf9, 0x00, 0x9a, 0xa7, 0x8e, 0x6b, 0x8f, 0xac, 0xc1, 0x28, 0xbc, 0xb0, 0x86, - 0x7c, 0x14, 0xda, 0x48, 0x31, 0x05, 0xb3, 0x8e, 0xf0, 0xad, 0x51, 0x78, 0xb1, 0x2d, 0xa0, 0xec, - 0x1b, 0x50, 0x3e, 0xe5, 0xdc, 0xc2, 0xc5, 0x6a, 0x95, 0x12, 0x07, 0x4f, 0xed, 0x90, 0x59, 0x3a, - 0x55, 0x7b, 0xf5, 0x0d, 0x68, 0x7a, 0xd3, 0xf0, 0xcc, 0x73, 0xdc, 0x33, 0x4b, 0xf0, 0x3b, 0xcb, - 0x19, 0x22, 0x0d, 0xe5, 0x37, 0xb3, 0x8f, 0x33, 0x66, 0x5d, 0x95, 0x09, 0xce, 0xd3, 0x1d, 0xb2, - 0xb7, 0xa1, 0x31, 0xb2, 0x83, 0xd0, 0x3a, 0xf7, 0x26, 0xd6, 0x64, 0x7a, 0xf2, 0x9c, 0x5f, 0xb7, - 0x6a, 0xb8, 0x10, 0x35, 0x01, 0xde, 0xf5, 0x26, 0x47, 0x08, 0x14, 0x94, 0x8d, 0xe3, 0xa4, 0x41, - 0xc0, 0xfd, 0xcc, 0x83, 0x9a, 0x59, 0x16, 0x10, 0xea, 0xf4, 0x33, 0x58, 0xc2, 0xed, 0x19, 0x4c, - 0x83, 0xd0, 0x1b, 0x5b, 0x82, 0x57, 0xfb, 0xc3, 0xa0, 0x55, 0x41, 0x5a, 0xfb, 0xba, 0x1c, 0xac, - 0xb6, 0xc7, 0x1b, 0xdb, 0x3c, 0x08, 0xb7, 0x10, 0xd9, 0x24, 0x5c, 0x71, 0xa1, 0x5f, 0x9b, 0x8b, - 0xc3, 0x59, 0x38, 0xfb, 0x06, 0x30, 0x7b, 0x34, 0xf2, 0x2e, 0xad, 0x80, 0x8f, 0x4e, 0x2d, 0xb9, - 0x88, 0xad, 0xfa, 0xfd, 0xcc, 0x83, 0x92, 0xd9, 0xc4, 0x92, 0x1e, 0x1f, 0x9d, 0x1e, 0x11, 0x9c, - 0x7d, 0x00, 0x78, 0x98, 0xac, 0x53, 0x6e, 0x87, 0x53, 0x9f, 0x07, 0xad, 0xc6, 0xfd, 0xdc, 0x83, - 0xfa, 0x93, 0xc5, 0x68, 0xbd, 0x10, 0xbc, 0xe9, 0x84, 0x66, 0x55, 0xe0, 0xc9, 0xef, 0x60, 0x7d, - 0x1b, 0x56, 0xd3, 0x87, 0x24, 0x88, 0x4a, 0xac, 0x8a, 0x20, 0xc6, 0xbc, 0x29, 0xfe, 0x64, 0xcb, - 0x50, 0xb8, 0xb0, 0x47, 0x53, 0x2e, 0x79, 0x3a, 0x7d, 0x7c, 0x98, 0xfd, 0x6e, 0xc6, 0xf8, 0xc3, - 0x0c, 0x54, 0x69, 0x96, 0x52, 0x16, 0x79, 0x13, 0x6a, 0x8a, 0x1a, 0xb8, 0xef, 0x7b, 0xbe, 0xe4, - 0x6a, 0x8a, 0xf2, 0x3a, 0x02, 0x26, 0x6e, 0x15, 0x85, 0x34, 0xf1, 0xb9, 0x33, 0xb6, 0xcf, 0x54, - 0xd3, 0x8a, 0x94, 0x8e, 0x24, 0x98, 0xbd, 0x17, 0xb7, 0xe7, 0x7b, 0xd3, 0x90, 0xcb, 0x3b, 0xaf, - 0x2a, 0xa7, 0x67, 0x0a, 0x58, 0xd4, 0x3a, 0x7e, 0xbd, 0x02, 0x9d, 0x1b, 0x3f, 0xcd, 0x00, 0x13, - 0xc3, 0xee, 0x7b, 0xd4, 0x80, 0xa4, 0xd0, 0xd9, 0x9a, 0x99, 0x57, 0x3e, 0x21, 0xd9, 0x17, 0x9d, - 0x10, 0x03, 0x0a, 0x34, 0xf6, 0x7c, 0xca, 0xd8, 0xa9, 0xe8, 0x07, 0xf9, 0x52, 0xae, 0x99, 0x37, - 0xfe, 0x47, 0x0e, 0x96, 0xb7, 0xe8, 0xca, 0x6e, 0x0f, 0x06, 0x7c, 0x12, 0x9d, 0x9d, 0x7b, 0x50, - 0x71, 0xbd, 0x21, 0x57, 0x14, 0x4b, 0x03, 0x03, 0x01, 0xd2, 0xc8, 0xf5, 0xdc, 0x76, 0x5c, 0x1a, - 0x38, 0x2d, 0x66, 0x19, 0x21, 0x38, 0xec, 0xb7, 0xa1, 0x31, 0xe1, 0xee, 0x50, 0x3f, 0x22, 0x24, - 0x54, 0xd5, 0x24, 0x58, 0x9e, 0x8e, 0x7b, 0x50, 0x39, 0x9d, 0x12, 0x9e, 0x60, 0x2c, 0x79, 0xa4, - 0x01, 0x90, 0xa0, 0x36, 0xf1, 0x97, 0xc9, 0x34, 0x38, 0xc7, 0xd2, 0x02, 0x96, 0x16, 0xc5, 0xb7, - 0x28, 0xba, 0x0b, 0x30, 0x9c, 0x06, 0xa1, 0x3c, 0x31, 0x0b, 0x58, 0x58, 0x16, 0x10, 0x3a, 0x31, - 0xdf, 0x84, 0xa5, 0xb1, 0x7d, 0x65, 0x21, 0xed, 0x58, 0x8e, 0x6b, 0x9d, 0x8e, 0xf0, 0xce, 0x29, - 0x22, 0x5e, 0x73, 0x6c, 0x5f, 0x7d, 0x22, 0x4a, 0xba, 0xee, 0x0e, 0xc2, 0x05, 0x5b, 0x51, 0xe2, - 0x8e, 0xcf, 0x03, 0xee, 0x5f, 0x70, 0xe4, 0x04, 0xf9, 0x48, 0xa6, 0x31, 0x09, 0x2a, 0x46, 0x34, - 0x16, 0xf3, 0x0e, 0x47, 0x03, 0x3a, 0xf6, 0x66, 0x71, 0xec, 0xb8, 0xbb, 0xe1, 0x68, 0x20, 0xee, - 0x15, 0xc1, 0x47, 0x26, 0xdc, 0xb7, 0x9e, 0x5f, 0xe2, 0x19, 0xce, 0x23, 0xdf, 0x38, 0xe2, 0xfe, - 0xb3, 0x4b, 0x71, 0xf5, 0x0f, 0x02, 0x64, 0x44, 0xf6, 0x75, 0xab, 0x82, 0x07, 0xbc, 0x34, 0x08, - 0x04, 0x0b, 0xb2, 0xaf, 0xc5, 0x21, 0x14, 0xa3, 0xb5, 0x71, 0x17, 0xf8, 0x10, 0x9b, 0x0f, 0x90, - 0xa3, 0xd6, 0x70, 0xb0, 0x6d, 0x59, 0x20, 0xfa, 0x09, 0x04, 0xd5, 0xab, 0xc1, 0x9e, 0x8e, 0xec, - 0xb3, 0x00, 0x59, 0x4a, 0xcd, 0xac, 0x4a, 0xe0, 0x8e, 0x80, 0x19, 0x9f, 0x92, 0x90, 0xa5, 0xed, - 0xad, 0x3c, 0x33, 0xe2, 0xaa, 0x47, 0x08, 0xee, 0x6b, 0xc9, 0x94, 0x5f, 0x69, 0x9b, 0x96, 0x4d, - 0xd9, 0x34, 0xe3, 0xf7, 0x32, 0x50, 0x95, 0x2d, 0xa3, 0x50, 0xc2, 0x36, 0x80, 0xa9, 0x5d, 0x0c, - 0xaf, 0x9c, 0xa1, 0x75, 0x72, 0x1d, 0xf2, 0x80, 0x88, 0x66, 0xf7, 0x96, 0xd9, 0x94, 0x65, 0xfd, - 0x2b, 0x67, 0xb8, 0x29, 0x4a, 0xd8, 0x43, 0x68, 0x26, 0xf0, 0x83, 0xd0, 0x27, 0x8a, 0xde, 0xbd, - 0x65, 0xd6, 0x35, 0xec, 0x5e, 0xe8, 0x8b, 0x33, 0x22, 0x44, 0x9e, 0x69, 0x68, 0x39, 0xee, 0x90, - 0x5f, 0x21, 0x19, 0xd5, 0xcc, 0x0a, 0xc1, 0xba, 0x02, 0xb4, 0x59, 0x87, 0xaa, 0xde, 0x9c, 0x71, - 0x06, 0x25, 0x25, 0x2f, 0xa1, 0xc0, 0x30, 0x33, 0x24, 0xb3, 0x1c, 0x46, 0x23, 0xb9, 0x0d, 0xa5, - 0xe4, 0x08, 0xcc, 0x62, 0xf8, 0xca, 0x1d, 0x1b, 0xdf, 0x83, 0xe6, 0x9e, 0x20, 0x1e, 0x57, 0x10, - 0xab, 0x94, 0xff, 0x56, 0x61, 0x41, 0x3b, 0x34, 0x65, 0x53, 0x7e, 0x89, 0x3b, 0xf7, 0xdc, 0x0b, - 0x42, 0xd9, 0x0b, 0xfe, 0x6d, 0xfc, 0x51, 0x06, 0x58, 0x27, 0x08, 0x9d, 0xb1, 0x1d, 0xf2, 0x1d, - 0x1e, 0xb1, 0x85, 0x43, 0xa8, 0x8a, 0xd6, 0xfa, 0x5e, 0x9b, 0x04, 0x32, 0x12, 0x28, 0xde, 0x95, - 0xc7, 0x78, 0xbe, 0xc2, 0x86, 0x8e, 0x4d, 0x6c, 0x3e, 0xd1, 0x80, 0x38, 0x65, 0xa1, 0xed, 0x9f, - 0xf1, 0x10, 0xc5, 0x38, 0x29, 0xef, 0x03, 0x81, 0x84, 0x00, 0xb7, 0xfe, 0x6b, 0xb0, 0x38, 0xd7, - 0x86, 0xce, 0x97, 0xcb, 0x29, 0x7c, 0x39, 0xa7, 0xf3, 0x65, 0x0b, 0x96, 0x12, 0xe3, 0x92, 0x94, - 0xb6, 0x06, 0x45, 0x71, 0x20, 0x84, 0x70, 0x90, 0x21, 0xa9, 0xf2, 0x94, 0x73, 0x21, 0x06, 0x3f, - 0x82, 0xe5, 0x53, 0xce, 0x7d, 0x3b, 0xc4, 0x42, 0x3c, 0x31, 0x62, 0x87, 0x64, 0xc3, 0x8b, 0xb2, - 0xac, 0x67, 0x87, 0x47, 0xdc, 0x17, 0x3b, 0x65, 0xfc, 0xcf, 0x0c, 0x34, 0x04, 0x07, 0xdd, 0xb7, - 0xdd, 0x6b, 0xb5, 0x4e, 0x7b, 0xa9, 0xeb, 0xf4, 0x40, 0xbb, 0x0c, 0x35, 0xec, 0x2f, 0xbb, 0x48, - 0xb9, 0xd9, 0x45, 0x62, 0xf7, 0xa1, 0x9a, 0x18, 0x6b, 0x01, 0xc7, 0x0a, 0x41, 0x34, 0xc8, 0x5f, - 0x7c, 0x19, 0xdf, 0x86, 0x66, 0x3c, 0x6c, 0xb9, 0x86, 0x0c, 0xf2, 0x82, 0x24, 0x65, 0x03, 0xf8, - 0xb7, 0xf1, 0x2f, 0x32, 0x84, 0xb8, 0xe5, 0x39, 0x91, 0x74, 0x2a, 0x10, 0x85, 0xdc, 0xab, 0x10, - 0xc5, 0xdf, 0x37, 0x4a, 0xf5, 0xbf, 0xf8, 0x64, 0xc5, 0xd1, 0x09, 0xb8, 0x3b, 0xb4, 0xec, 0xd1, - 0x08, 0x99, 0x6f, 0xc9, 0x2c, 0x8a, 0xef, 0xf6, 0x68, 0x64, 0xbc, 0x03, 0x8b, 0xda, 0xe8, 0x5e, - 0x30, 0x8f, 0x03, 0x60, 0x7b, 0x4e, 0x10, 0x1e, 0xbb, 0xc1, 0x44, 0x13, 0xdc, 0xee, 0x40, 0x59, - 0x70, 0x58, 0x31, 0x32, 0x3a, 0xb2, 0x05, 0x53, 0xb0, 0x5c, 0x31, 0xae, 0x00, 0x0b, 0xed, 0x2b, - 0x59, 0x98, 0x95, 0x85, 0xf6, 0x15, 0x16, 0x1a, 0xdf, 0x85, 0xa5, 0x44, 0x7b, 0xb2, 0xeb, 0x37, - 0xa0, 0x30, 0x0d, 0xaf, 0x3c, 0x25, 0x9a, 0x57, 0x24, 0x85, 0x08, 0x05, 0xd0, 0xa4, 0x12, 0xe3, - 0x23, 0x58, 0x3c, 0xe0, 0x97, 0xf2, 0x10, 0xab, 0x81, 0xbc, 0x0d, 0xf9, 0x97, 0x28, 0x85, 0x58, - 0x6e, 0x6c, 0x00, 0xd3, 0x2b, 0xcb, 0x5e, 0x35, 0x1d, 0x31, 0x93, 0xd0, 0x11, 0x8d, 0xb7, 0x81, - 0xf5, 0x9c, 0x33, 0x77, 0x9f, 0x07, 0x81, 0x7d, 0x16, 0x1d, 0xfb, 0x26, 0xe4, 0xc6, 0xc1, 0x99, - 0xe4, 0x51, 0xe2, 0x4f, 0xe3, 0x5b, 0xb0, 0x94, 0xc0, 0x93, 0x0d, 0xbf, 0x06, 0xe5, 0xc0, 0x39, - 0x73, 0x51, 0xb0, 0x92, 0x4d, 0xc7, 0x00, 0x63, 0x07, 0x96, 0x3f, 0xe1, 0xbe, 0x73, 0x7a, 0xfd, - 0xb2, 0xe6, 0x93, 0xed, 0x64, 0x67, 0xdb, 0xe9, 0xc0, 0xca, 0x4c, 0x3b, 0xb2, 0x7b, 0x22, 0x5f, - 0xb9, 0x93, 0x25, 0x93, 0x3e, 0x34, 0xbe, 0x97, 0xd5, 0xf9, 0x9e, 0x71, 0x0c, 0x6c, 0xcb, 0x73, - 0x5d, 0x3e, 0x08, 0x8f, 0x38, 0xf7, 0x63, 0x2b, 0x55, 0x4c, 0xab, 0x95, 0x27, 0x6b, 0x72, 0x65, - 0x67, 0x99, 0xa9, 0x24, 0x62, 0x06, 0xf9, 0x09, 0xf7, 0xc7, 0xd8, 0x70, 0xc9, 0xc4, 0xbf, 0x8d, - 0x15, 0x58, 0x4a, 0x34, 0x2b, 0xf5, 0xfa, 0xc7, 0xb0, 0xb2, 0xed, 0x04, 0x83, 0xf9, 0x0e, 0xd7, - 0xa0, 0x38, 0x99, 0x9e, 0x58, 0x49, 0xbe, 0xfc, 0x8c, 0x5f, 0x0b, 0x6d, 0x6f, 0xb6, 0x86, 0x6c, - 0xeb, 0xef, 0x64, 0x20, 0xbf, 0xdb, 0xdf, 0xdb, 0x62, 0xeb, 0x50, 0x72, 0xdc, 0x81, 0x37, 0x16, - 0x82, 0x17, 0xcd, 0x39, 0xfa, 0xbe, 0xf1, 0x80, 0xdd, 0x81, 0x32, 0xca, 0x6b, 0x42, 0xb5, 0x95, - 0xa2, 0x4f, 0x49, 0x00, 0xf6, 0xbc, 0xc1, 0x73, 0xa1, 0x53, 0xf3, 0xab, 0x89, 0xe3, 0xa3, 0xd6, - 0xac, 0x94, 0xe1, 0x3c, 0xdd, 0xf5, 0x71, 0x01, 0x69, 0xc4, 0xc6, 0x5f, 0x15, 0xa1, 0x28, 0x6f, - 0x5b, 0xba, 0xb9, 0x43, 0xe7, 0x82, 0xc7, 0x37, 0xb7, 0xf8, 0x12, 0xf2, 0x80, 0xcf, 0xc7, 0x5e, - 0x18, 0x09, 0x6c, 0xb4, 0x07, 0x55, 0x02, 0x4a, 0x91, 0x4d, 0x13, 0x1a, 0xc8, 0xc4, 0x90, 0x23, - 0xa4, 0x81, 0x7e, 0x95, 0xdf, 0x81, 0xa2, 0xba, 0xfb, 0xf3, 0x91, 0x4e, 0xb3, 0x30, 0x20, 0x69, - 0x6d, 0x1d, 0x4a, 0x03, 0x7b, 0x62, 0x0f, 0x9c, 0xf0, 0x5a, 0x32, 0x84, 0xe8, 0x5b, 0xb4, 0x3e, - 0xf2, 0x06, 0xf6, 0xc8, 0x3a, 0xb1, 0x47, 0xb6, 0x3b, 0xe0, 0x52, 0x77, 0xaf, 0x22, 0x70, 0x93, - 0x60, 0x42, 0x3f, 0x97, 0xe3, 0x54, 0x58, 0xa4, 0xc2, 0xcb, 0xd1, 0x2b, 0x34, 0x21, 0x5c, 0x7a, - 0xe3, 0xb1, 0x23, 0xb4, 0x0c, 0x12, 0xc3, 0x72, 0x66, 0x99, 0x20, 0x3b, 0x1c, 0x67, 0x2b, 0x8b, - 0x2f, 0x69, 0xe9, 0xca, 0xd4, 0x15, 0x01, 0x3f, 0x25, 0x43, 0xc2, 0xbc, 0x2c, 0x96, 0xd3, 0x64, - 0xb1, 0x77, 0x61, 0x71, 0xea, 0x06, 0x3c, 0x0c, 0x47, 0x7c, 0x18, 0x8d, 0xa5, 0x82, 0x48, 0xcd, - 0xa8, 0x40, 0x0d, 0x67, 0x03, 0x96, 0xc8, 0xe8, 0x10, 0xd8, 0xa1, 0x17, 0x9c, 0x3b, 0x81, 0x15, - 0x08, 0x0d, 0x89, 0xd4, 0xdd, 0x45, 0x2c, 0xea, 0xc9, 0x92, 0x1e, 0xa9, 0x48, 0x6b, 0x33, 0xf8, - 0x3e, 0x1f, 0x70, 0xe7, 0x82, 0x0f, 0x51, 0x4e, 0xcb, 0x99, 0x2b, 0x89, 0x3a, 0xa6, 0x2c, 0x44, - 0xa1, 0x7b, 0x3a, 0xb6, 0xa6, 0x93, 0xa1, 0x2d, 0x84, 0x95, 0x3a, 0x09, 0xc3, 0xee, 0x74, 0x7c, - 0x4c, 0x10, 0xf6, 0x18, 0x94, 0x24, 0x26, 0xe5, 0xc3, 0x46, 0x82, 0x9f, 0x09, 0x62, 0x35, 0xab, - 0x12, 0x83, 0x04, 0xc5, 0x84, 0xcc, 0xd9, 0x9c, 0x91, 0x39, 0x5b, 0x50, 0x9c, 0xf8, 0xce, 0x85, - 0x1d, 0xf2, 0xd6, 0x22, 0x31, 0x70, 0xf9, 0x29, 0x38, 0x83, 0xe3, 0x3a, 0xa1, 0x63, 0x87, 0x9e, - 0xdf, 0x62, 0x58, 0x16, 0x03, 0xd8, 0x43, 0x58, 0x44, 0x1a, 0x09, 0x42, 0x3b, 0x9c, 0x06, 0x52, - 0x02, 0x5d, 0x42, 0x62, 0x42, 0x19, 0xba, 0x87, 0x70, 0x14, 0x42, 0xd9, 0xb7, 0x60, 0x95, 0xc8, - 0x02, 0x6b, 0x48, 0xc9, 0x1a, 0x05, 0x82, 0x65, 0x5c, 0x8a, 0x25, 0x2c, 0x15, 0xf4, 0x2d, 0xe5, - 0x6b, 0x21, 0x1d, 0xbc, 0x0f, 0x6b, 0x92, 0x4c, 0xe6, 0x6a, 0xad, 0x60, 0xad, 0x65, 0x2a, 0x9e, - 0xa9, 0xb6, 0x01, 0x8b, 0x62, 0x48, 0xce, 0xc0, 0x92, 0xb5, 0xc5, 0x49, 0x58, 0x15, 0xa3, 0x47, - 0x4d, 0xa9, 0x41, 0x85, 0x26, 0x96, 0x3d, 0xe3, 0xd7, 0xec, 0x7b, 0xd0, 0x20, 0x92, 0x41, 0xf5, - 0x0a, 0x39, 0xfd, 0x3a, 0x72, 0xfa, 0x15, 0x65, 0xe1, 0x8c, 0x4a, 0x91, 0xd9, 0xd7, 0x07, 0x89, - 0x6f, 0x71, 0x1c, 0x46, 0xce, 0x29, 0x0f, 0x9d, 0x31, 0x6f, 0xad, 0x11, 0x81, 0xa9, 0x6f, 0x71, - 0x52, 0xa7, 0x13, 0x2c, 0x69, 0x11, 0x5f, 0xa0, 0x2f, 0xa4, 0xdd, 0x91, 0x17, 0x70, 0x65, 0xa2, - 0x6a, 0xdd, 0x96, 0x87, 0x50, 0x00, 0x25, 0xdb, 0x33, 0x7e, 0x96, 0xa1, 0x7b, 0x4c, 0x1e, 0xfb, - 0x40, 0xd3, 0xca, 0xe8, 0xc0, 0x5b, 0x9e, 0x3b, 0xba, 0x96, 0x3c, 0x00, 0x08, 0x74, 0xe8, 0x8e, - 0xf0, 0x10, 0x3a, 0xae, 0x8e, 0x42, 0x2c, 0xb3, 0xaa, 0x80, 0x88, 0x74, 0x0f, 0x2a, 0x93, 0xe9, - 0xc9, 0xc8, 0x19, 0x10, 0x4a, 0x8e, 0x5a, 0x21, 0x10, 0x22, 0x08, 0xb5, 0x94, 0x08, 0x81, 0x30, - 0xf2, 0x88, 0x51, 0x91, 0x30, 0x44, 0x41, 0x96, 0xcc, 0x7d, 0xe4, 0x02, 0x55, 0x13, 0xff, 0x36, - 0x36, 0x61, 0x39, 0x39, 0x68, 0x79, 0x5f, 0x3c, 0x84, 0x92, 0x64, 0x31, 0xca, 0x5e, 0x51, 0xd7, - 0x2c, 0xc8, 0x42, 0xb3, 0x8a, 0xca, 0x8d, 0xdf, 0x5e, 0x80, 0x25, 0x09, 0xdd, 0x12, 0x2b, 0xd2, - 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0xc2, 0xbb, 0x32, 0x2f, 0xe6, 0x5d, 0xd9, 0x39, 0xde, 0x95, 0x54, - 0x58, 0x89, 0xf5, 0x25, 0x15, 0x56, 0xb1, 0x05, 0xa4, 0x43, 0xe8, 0xe6, 0xcb, 0x9a, 0x04, 0xf7, - 0xc9, 0x4c, 0x3a, 0xc7, 0x69, 0x0b, 0x29, 0x9c, 0x56, 0xe7, 0x93, 0x0b, 0x33, 0x7c, 0xf2, 0x0d, - 0xa0, 0xbd, 0x56, 0x6c, 0xbf, 0x48, 0x6a, 0x05, 0xc2, 0xa4, 0x0d, 0xf4, 0x1d, 0x68, 0xcc, 0xb2, - 0x26, 0xe2, 0x81, 0xf5, 0x14, 0xc6, 0xe4, 0x8c, 0x39, 0x5e, 0x32, 0x1a, 0x72, 0x59, 0x32, 0x26, - 0x67, 0xcc, 0xf7, 0xb0, 0x44, 0xe1, 0x77, 0x00, 0xa8, 0x6f, 0xa4, 0x75, 0x40, 0x5a, 0x7f, 0x3b, - 0xb9, 0x17, 0xfa, 0xaa, 0x6f, 0x88, 0x8f, 0xa9, 0xcf, 0x91, 0xf8, 0xcb, 0x58, 0x13, 0xe9, 0xfe, - 0x19, 0xd4, 0xbd, 0x09, 0x77, 0xad, 0x98, 0x45, 0x54, 0xb0, 0xa9, 0xb7, 0x5e, 0xd0, 0x54, 0x57, - 0xe1, 0x9a, 0x35, 0x51, 0x37, 0xfa, 0x64, 0xfb, 0xb4, 0xf0, 0x5c, 0x6b, 0xad, 0xfa, 0x25, 0x5a, - 0xab, 0x63, 0xe5, 0xe8, 0xdb, 0xf8, 0xfb, 0x19, 0xa8, 0x68, 0xc3, 0x66, 0x2b, 0xb0, 0xb8, 0x75, - 0x78, 0x78, 0xd4, 0x31, 0xdb, 0xfd, 0xee, 0x27, 0x1d, 0x6b, 0x6b, 0xef, 0xb0, 0xd7, 0x69, 0xde, - 0x12, 0xe0, 0xbd, 0xc3, 0xad, 0xf6, 0x9e, 0xb5, 0x73, 0x68, 0x6e, 0x29, 0x70, 0x86, 0xad, 0x02, - 0x33, 0x3b, 0xfb, 0x87, 0xfd, 0x4e, 0x02, 0x9e, 0x65, 0x4d, 0xa8, 0x6e, 0x9a, 0x9d, 0xf6, 0xd6, - 0xae, 0x84, 0xe4, 0xd8, 0x32, 0x34, 0x77, 0x8e, 0x0f, 0xb6, 0xbb, 0x07, 0x4f, 0xad, 0xad, 0xf6, - 0xc1, 0x56, 0x67, 0xaf, 0xb3, 0xdd, 0xcc, 0xb3, 0x1a, 0x94, 0xdb, 0x9b, 0xed, 0x83, 0xed, 0xc3, - 0x83, 0xce, 0x76, 0xb3, 0x60, 0xfc, 0x0a, 0x94, 0xe3, 0x89, 0x56, 0xa0, 0x78, 0x7c, 0xf0, 0xec, - 0xe0, 0xf0, 0xd3, 0x83, 0xe6, 0x2d, 0x56, 0x86, 0x02, 0xf6, 0xdf, 0xcc, 0x30, 0x80, 0x05, 0xea, - 0xb3, 0x99, 0x65, 0x25, 0xc8, 0x6f, 0x1e, 0xf6, 0x77, 0x9b, 0x39, 0xe3, 0xcf, 0x33, 0xb0, 0x82, - 0x53, 0x1e, 0xce, 0x32, 0x81, 0xfb, 0x50, 0x19, 0x78, 0xde, 0x44, 0x28, 0x48, 0xb1, 0x20, 0xa0, - 0x83, 0xc4, 0x01, 0x27, 0x9e, 0x7b, 0xea, 0xf9, 0x03, 0x2e, 0x79, 0x00, 0x20, 0x68, 0x47, 0x40, - 0x04, 0x0d, 0x4a, 0x22, 0x26, 0x0c, 0x62, 0x01, 0x15, 0x82, 0x11, 0xca, 0x2a, 0x2c, 0x9c, 0xf8, - 0xdc, 0x1e, 0x9c, 0xcb, 0xd3, 0x2f, 0xbf, 0xd8, 0xd7, 0x63, 0xd5, 0x7d, 0x20, 0x68, 0x6a, 0xc4, - 0x87, 0x78, 0x04, 0x4a, 0x66, 0x43, 0xc2, 0xb7, 0x24, 0x58, 0x5c, 0x22, 0xf6, 0x89, 0xed, 0x0e, - 0x3d, 0x97, 0x0f, 0xa5, 0x86, 0x10, 0x03, 0x8c, 0x23, 0x58, 0x9d, 0x9d, 0x9f, 0xe4, 0x17, 0x1f, - 0x68, 0xfc, 0x82, 0x04, 0xf6, 0xf5, 0x9b, 0x49, 0x41, 0xe3, 0x1d, 0xff, 0x30, 0x0f, 0x79, 0x21, - 0xc0, 0xdd, 0x28, 0xeb, 0xe9, 0x12, 0x79, 0x6e, 0xce, 0x6b, 0x83, 0x16, 0x02, 0xba, 0xd9, 0xc9, - 0x0c, 0x55, 0x46, 0x08, 0xde, 0xe8, 0x51, 0xb1, 0xcf, 0x07, 0x17, 0xd2, 0x0e, 0x45, 0xc5, 0x26, - 0x1f, 0x5c, 0xa0, 0x2a, 0x64, 0x87, 0x54, 0x97, 0xce, 0x7b, 0x31, 0xb0, 0x43, 0xac, 0x29, 0x8b, - 0xb0, 0x5e, 0x31, 0x2a, 0xc2, 0x5a, 0x2d, 0x28, 0x3a, 0xee, 0x89, 0x37, 0x75, 0x87, 0x78, 0xbc, - 0x4b, 0xa6, 0xfa, 0x44, 0x27, 0x11, 0x72, 0x22, 0x71, 0x7f, 0xd0, 0x69, 0x2e, 0x09, 0x40, 0x5f, - 0xdc, 0x20, 0xef, 0x41, 0x39, 0xb8, 0x76, 0x07, 0xfa, 0x19, 0x5e, 0x96, 0xeb, 0x23, 0x66, 0xbf, - 0xd1, 0xbb, 0x76, 0x07, 0x78, 0x62, 0x4b, 0x81, 0xfc, 0x8b, 0xbd, 0x0f, 0xa5, 0xc8, 0x5c, 0x4b, - 0x1c, 0xf8, 0xb6, 0x5e, 0x43, 0xd9, 0x68, 0x49, 0x2b, 0x8e, 0x50, 0xd9, 0x23, 0x58, 0x40, 0x9b, - 0x6a, 0xd0, 0xaa, 0x62, 0x25, 0x25, 0xa6, 0x8b, 0x61, 0xa0, 0x7f, 0x86, 0x0f, 0xd1, 0xbe, 0x6a, - 0x4a, 0xb4, 0xf5, 0x67, 0x50, 0x4b, 0xb4, 0xa5, 0xeb, 0xbe, 0x35, 0xd2, 0x7d, 0xdf, 0xd2, 0x75, - 0xdf, 0xf8, 0x26, 0x90, 0xd5, 0x74, 0x5d, 0xf8, 0xd7, 0xa0, 0xa4, 0xa6, 0x22, 0xce, 0x9f, 0x3c, - 0x3b, 0x56, 0xef, 0xb3, 0x83, 0xad, 0xe6, 0x2d, 0xd6, 0x80, 0x4a, 0x7b, 0x0b, 0x8f, 0x34, 0x02, - 0x32, 0x02, 0xe5, 0xa8, 0xdd, 0xeb, 0x45, 0x90, 0xac, 0xb1, 0x03, 0xcd, 0xd9, 0x91, 0x0a, 0x9a, - 0x0c, 0x15, 0x4c, 0x5a, 0x9c, 0x63, 0x80, 0xd0, 0x6c, 0xc8, 0x88, 0x4c, 0xe2, 0x33, 0x7d, 0x18, - 0xef, 0x43, 0x53, 0xdc, 0x6b, 0x62, 0xa9, 0x02, 0xcd, 0x72, 0x3b, 0x12, 0x22, 0x99, 0x6e, 0x75, - 0x2e, 0x99, 0x15, 0x82, 0x61, 0x57, 0xc6, 0x07, 0xb0, 0xa8, 0x55, 0x8b, 0x35, 0x51, 0x71, 0x57, - 0xce, 0x6a, 0xa2, 0xa8, 0x77, 0x50, 0x89, 0xb1, 0x06, 0x2b, 0xe2, 0xb3, 0x73, 0xc1, 0xdd, 0xb0, - 0x37, 0x3d, 0x21, 0x57, 0xa1, 0xe3, 0xb9, 0x42, 0x1f, 0x29, 0x47, 0x25, 0x37, 0x13, 0xf9, 0x86, - 0x54, 0x5a, 0xb3, 0x48, 0x1a, 0xeb, 0x5a, 0x0f, 0x58, 0x71, 0x03, 0xff, 0x4d, 0x28, 0xaf, 0xe5, - 0x08, 0x24, 0x96, 0xf5, 0xa8, 0xd3, 0x31, 0xad, 0xc3, 0x83, 0xbd, 0xee, 0x81, 0x60, 0x94, 0x62, - 0x59, 0x11, 0xb0, 0xb3, 0x83, 0x90, 0x8c, 0xd1, 0x84, 0xfa, 0x53, 0x1e, 0x76, 0xdd, 0x53, 0x4f, - 0xb9, 0xc5, 0xfe, 0xb2, 0x00, 0x8d, 0x08, 0x14, 0x2b, 0xbf, 0x17, 0xdc, 0x0f, 0x1c, 0xcf, 0x45, - 0x39, 0xb6, 0x6c, 0xaa, 0x4f, 0x71, 0xbb, 0x39, 0x43, 0xee, 0x86, 0x4e, 0x78, 0x6d, 0x25, 0x2c, - 0x65, 0x75, 0x05, 0x96, 0xb7, 0xe8, 0x32, 0x14, 0xec, 0x91, 0x63, 0x2b, 0x0f, 0x2b, 0x7d, 0x08, - 0xe8, 0xc0, 0x1b, 0x79, 0x3e, 0x8a, 0xac, 0x65, 0x93, 0x3e, 0xd8, 0x63, 0x58, 0x16, 0xa2, 0xb3, - 0x6e, 0xbe, 0x44, 0xfe, 0x41, 0x46, 0x3b, 0xe6, 0x4e, 0xc7, 0x47, 0xb1, 0x09, 0x53, 0x94, 0x88, - 0xbb, 0x53, 0xd4, 0x90, 0xc2, 0x52, 0x54, 0x81, 0xb4, 0xb0, 0x45, 0x77, 0x3a, 0x6e, 0x63, 0x49, - 0x84, 0xff, 0x04, 0x56, 0x04, 0x7e, 0x24, 0x5e, 0x45, 0x35, 0x1a, 0x58, 0x43, 0x34, 0xd6, 0x95, - 0x65, 0x51, 0x9d, 0x3b, 0x50, 0xa6, 0x51, 0x89, 0x1d, 0x2f, 0x90, 0xf4, 0x8d, 0x43, 0xe1, 0x7e, - 0x30, 0xe7, 0x0c, 0x5d, 0x20, 0x41, 0x60, 0xc6, 0x19, 0xaa, 0xb9, 0x53, 0x4b, 0xb3, 0xee, 0xd4, - 0x27, 0xb0, 0x72, 0x22, 0x48, 0xf0, 0x9c, 0xdb, 0x43, 0xee, 0x5b, 0x31, 0x61, 0x93, 0x96, 0xb1, - 0x24, 0x0a, 0x77, 0xb1, 0x2c, 0x3a, 0x07, 0x42, 0xce, 0x11, 0x6c, 0x81, 0x0f, 0xad, 0xd0, 0xb3, - 0x50, 0xfc, 0x41, 0x06, 0x53, 0x32, 0x6b, 0x04, 0xee, 0x7b, 0x5b, 0x02, 0x98, 0xc4, 0x3b, 0xf3, - 0xed, 0xc9, 0xb9, 0xd4, 0x03, 0x22, 0xbc, 0xa7, 0x02, 0xc8, 0x5e, 0x83, 0xa2, 0x20, 0x79, 0x97, - 0x93, 0xcf, 0x8a, 0x24, 0x6d, 0x05, 0x62, 0x6f, 0xc1, 0x02, 0xf6, 0x11, 0xb4, 0x9a, 0x48, 0xef, - 0xd5, 0x98, 0x91, 0x3b, 0xae, 0x29, 0xcb, 0x84, 0x30, 0x39, 0xf5, 0x1d, 0xe2, 0x32, 0x65, 0x13, - 0xff, 0x66, 0xdf, 0xd7, 0x58, 0xd6, 0x12, 0xd6, 0x55, 0xf2, 0xc0, 0x0c, 0xa5, 0xdd, 0xc4, 0xbd, - 0xbe, 0x52, 0x66, 0xf4, 0x83, 0x7c, 0xa9, 0xd2, 0xac, 0x1a, 0xdf, 0x81, 0x02, 0xad, 0x8e, 0x20, - 0x42, 0x5c, 0xbb, 0x8c, 0x24, 0x42, 0x84, 0xb6, 0xa0, 0xe8, 0xf2, 0xf0, 0xd2, 0xf3, 0x9f, 0x2b, - 0x5b, 0xb2, 0xfc, 0x34, 0x7e, 0x8c, 0x46, 0x90, 0xc8, 0x51, 0x4e, 0xfa, 0x9c, 0x20, 0x0f, 0xda, - 0xde, 0xe0, 0xdc, 0x96, 0x76, 0x99, 0x12, 0x02, 0x7a, 0xe7, 0xf6, 0x1c, 0x79, 0x64, 0xe7, 0x7d, - 0xe5, 0x6f, 0x41, 0x5d, 0xb9, 0xe6, 0x03, 0x6b, 0xc4, 0x4f, 0x43, 0x49, 0xee, 0x55, 0xe9, 0x97, - 0x0f, 0xf6, 0xf8, 0x69, 0x68, 0xec, 0xc3, 0xa2, 0x24, 0xc8, 0xc3, 0x09, 0x57, 0x5d, 0x7f, 0x37, - 0x4d, 0x9e, 0xae, 0x3c, 0x59, 0x4a, 0x5e, 0xb4, 0x14, 0x72, 0x90, 0x10, 0xb2, 0x8d, 0x8f, 0x81, - 0xe9, 0xd7, 0xb0, 0x6c, 0x4f, 0x4a, 0xb5, 0xca, 0x04, 0xaf, 0x3c, 0x59, 0x91, 0xec, 0xec, 0x0c, - 0xc5, 0xea, 0x04, 0xd3, 0xc1, 0x40, 0x85, 0x4c, 0x94, 0x4c, 0xf5, 0x69, 0xfc, 0x49, 0x06, 0x96, - 0xb0, 0x31, 0xa5, 0x0f, 0x48, 0x26, 0xfb, 0x73, 0x0f, 0x52, 0xec, 0x8f, 0x2e, 0xfb, 0xd0, 0xc7, - 0x97, 0x37, 0x7a, 0xe6, 0xe7, 0x8c, 0x9e, 0x5f, 0x87, 0xe6, 0x90, 0x8f, 0x1c, 0x8c, 0x9e, 0x51, - 0xa2, 0x04, 0x69, 0x00, 0x0d, 0x05, 0x57, 0x4a, 0xdc, 0x3f, 0xcd, 0xc0, 0x22, 0x49, 0x2a, 0xa8, - 0x0e, 0xcb, 0x85, 0xfa, 0x48, 0xe9, 0x7f, 0x92, 0x55, 0xc9, 0x39, 0xc5, 0x37, 0x38, 0x42, 0x09, - 0x79, 0xf7, 0x96, 0xd4, 0x0b, 0x25, 0x94, 0x7d, 0x88, 0x3a, 0x8c, 0x6b, 0x21, 0x30, 0x25, 0x1a, - 0x27, 0xb9, 0x29, 0xbb, 0xb7, 0x50, 0xc1, 0x71, 0x11, 0xb4, 0x59, 0x12, 0x0a, 0xa9, 0x00, 0x1b, - 0x3b, 0x50, 0x4b, 0x74, 0x93, 0xb0, 0xcc, 0x56, 0xc9, 0x32, 0x3b, 0xe7, 0xfd, 0xc8, 0xce, 0x7b, - 0x3f, 0xfe, 0x6e, 0x1e, 0x98, 0x20, 0xa9, 0x99, 0x5d, 0x9b, 0x71, 0x1d, 0x66, 0xe7, 0x5c, 0x87, - 0x8f, 0x81, 0x69, 0x08, 0xca, 0xa3, 0x99, 0x8b, 0x3c, 0x9a, 0xcd, 0x18, 0x57, 0x3a, 0x34, 0x1f, - 0xc3, 0xb2, 0x14, 0x68, 0x23, 0x5f, 0x21, 0x9a, 0xdc, 0x68, 0x7f, 0x18, 0x49, 0xb6, 0xca, 0x67, - 0x88, 0xe6, 0x37, 0xe5, 0x36, 0x0c, 0xec, 0x50, 0x5a, 0xaa, 0xd0, 0x6d, 0xd8, 0xb3, 0xe7, 0x4c, - 0xdf, 0x0b, 0x2f, 0xa5, 0x82, 0xe2, 0x1c, 0x15, 0x68, 0x86, 0x93, 0x52, 0xd2, 0x70, 0x62, 0x40, - 0x4d, 0x39, 0x07, 0x29, 0x26, 0x82, 0xa4, 0xb7, 0x8a, 0xf4, 0x10, 0x62, 0x5c, 0xc4, 0x03, 0x68, - 0x2a, 0xeb, 0x46, 0x64, 0x9a, 0x21, 0x7f, 0xbf, 0x34, 0x8e, 0x6d, 0x29, 0x03, 0x4d, 0xc2, 0x10, - 0x5e, 0x99, 0x31, 0x84, 0xbf, 0x0b, 0x8b, 0x81, 0x20, 0x22, 0x6b, 0xea, 0xca, 0xe0, 0x1c, 0x3e, - 0x44, 0xd5, 0xa9, 0x64, 0x36, 0xb1, 0xe0, 0x38, 0x86, 0xcf, 0x9b, 0x1d, 0x6a, 0xf3, 0x66, 0x07, - 0xf6, 0x7e, 0xec, 0x47, 0x0b, 0xce, 0x9d, 0x31, 0x5e, 0xdc, 0x71, 0x20, 0x8b, 0x5c, 0xe0, 0xde, - 0xb9, 0x33, 0x36, 0x95, 0xd3, 0x56, 0x7c, 0x18, 0xff, 0x39, 0x03, 0x4d, 0x41, 0x07, 0x09, 0x3a, - 0xff, 0x15, 0xc0, 0x13, 0xf9, 0x8a, 0x64, 0x5e, 0x11, 0xb8, 0x8a, 0xca, 0xbf, 0x03, 0x48, 0xb6, - 0x96, 0xd0, 0x13, 0x25, 0x91, 0xb7, 0x92, 0x44, 0x1e, 0x33, 0xb2, 0xdd, 0x5b, 0xa4, 0x00, 0x08, - 0x48, 0x9a, 0xff, 0x32, 0x9f, 0xe2, 0xbf, 0xd4, 0x8e, 0xc2, 0x2e, 0xc0, 0x33, 0x7e, 0xbd, 0xe7, - 0x0d, 0x50, 0x43, 0xbb, 0x0b, 0x20, 0x08, 0xf2, 0xd4, 0x1e, 0x3b, 0xd2, 0xba, 0x52, 0x30, 0xcb, - 0xcf, 0xf9, 0xf5, 0x0e, 0x02, 0xc4, 0x6e, 0x88, 0xe2, 0xf8, 0x3c, 0x14, 0xcc, 0xd2, 0x73, 0x7e, - 0x4d, 0x87, 0xc1, 0x82, 0xda, 0x33, 0x7e, 0xbd, 0xcd, 0x49, 0x5c, 0xf3, 0x7c, 0x41, 0x09, 0xbe, - 0x7d, 0x29, 0xe4, 0xb3, 0x84, 0xef, 0xb1, 0xe2, 0xdb, 0x97, 0xcf, 0xf8, 0xb5, 0xf2, 0x83, 0x16, - 0x45, 0xf9, 0xc8, 0x1b, 0xc8, 0x1b, 0x48, 0x45, 0x51, 0xc4, 0x83, 0x32, 0x17, 0x9e, 0xe3, 0xdf, - 0xc6, 0x1f, 0x67, 0xa0, 0x26, 0xc6, 0x8f, 0x0c, 0x4e, 0xac, 0xbb, 0x0a, 0xc6, 0xc9, 0xc4, 0xc1, - 0x38, 0x4f, 0x24, 0x7f, 0x20, 0x6e, 0x99, 0xbd, 0x99, 0x5b, 0xe2, 0x02, 0x13, 0xab, 0x7c, 0x0f, - 0xca, 0x74, 0xb6, 0xc4, 0x61, 0xcd, 0x25, 0x76, 0x29, 0x31, 0x21, 0xb3, 0x84, 0x68, 0xcf, 0xc8, - 0xf7, 0xaf, 0x19, 0xd8, 0x68, 0x89, 0xcb, 0x7e, 0x64, 0x56, 0x4b, 0xd9, 0x86, 0x42, 0x9a, 0x1b, - 0xf9, 0x18, 0x2a, 0x1a, 0x4d, 0xa1, 0x35, 0x2e, 0x1a, 0x3c, 0x11, 0x60, 0x92, 0x68, 0x12, 0xb3, - 0xdf, 0xbd, 0x65, 0xd6, 0x06, 0x3a, 0x60, 0x73, 0x01, 0xf2, 0xa2, 0x92, 0xf1, 0x11, 0x2c, 0x6a, - 0xcd, 0x92, 0x36, 0x9a, 0x36, 0xa6, 0x4c, 0xda, 0x98, 0xfe, 0x59, 0x06, 0x96, 0x65, 0x6d, 0x0c, - 0xdc, 0x72, 0xc4, 0x75, 0xbd, 0x1f, 0x9c, 0xb1, 0x5f, 0x81, 0x9a, 0x68, 0xdd, 0xf2, 0xf9, 0x99, - 0x13, 0x84, 0x5c, 0x79, 0x2e, 0x52, 0x0e, 0x87, 0xe0, 0xda, 0x02, 0xd5, 0x94, 0x98, 0xec, 0x23, - 0xa8, 0x60, 0x55, 0xd2, 0x97, 0xe5, 0xb6, 0xb4, 0xe6, 0x2b, 0xd2, 0x50, 0x77, 0x6f, 0x99, 0x10, - 0x44, 0x5f, 0x9b, 0x65, 0x28, 0x86, 0xbe, 0x73, 0x76, 0xc6, 0x7d, 0x63, 0x35, 0x1a, 0x9a, 0x38, - 0x69, 0xbc, 0x17, 0xf2, 0x89, 0x10, 0x82, 0x8c, 0xff, 0x9a, 0x81, 0x8a, 0x3c, 0x3b, 0x3f, 0xb7, - 0xbb, 0x62, 0x5d, 0x8b, 0x3c, 0x24, 0xd5, 0x38, 0x0e, 0x34, 0x7c, 0x07, 0x1a, 0x63, 0x21, 0x10, - 0x09, 0x81, 0x3d, 0xe1, 0xab, 0xa8, 0x2b, 0xb0, 0x94, 0x47, 0x36, 0x60, 0x09, 0xc5, 0x93, 0xc0, - 0x0a, 0x9d, 0x91, 0xa5, 0x0a, 0x65, 0x94, 0xdf, 0x22, 0x15, 0xf5, 0x9d, 0xd1, 0xbe, 0x2c, 0x10, - 0xb7, 0x74, 0x10, 0xda, 0x67, 0x5c, 0x8a, 0xbe, 0xf4, 0x61, 0xb4, 0x60, 0x75, 0x46, 0x56, 0x57, - 0x7a, 0xc6, 0x4f, 0xeb, 0xb0, 0x36, 0x57, 0x24, 0xf5, 0x8d, 0xc8, 0x46, 0x3f, 0x72, 0xc6, 0x27, - 0x5e, 0x64, 0x0a, 0xcb, 0x68, 0x36, 0xfa, 0x3d, 0x51, 0xa2, 0x4c, 0x61, 0x1c, 0x56, 0x14, 0x41, - 0xa0, 0x2d, 0x2b, 0x12, 0xe7, 0xb3, 0x28, 0x6c, 0xbe, 0x97, 0x64, 0x54, 0xb3, 0xdd, 0x29, 0xb8, - 0x7e, 0xfd, 0x2d, 0x4d, 0xe6, 0x60, 0x01, 0x3b, 0x85, 0x56, 0x44, 0x77, 0x52, 0x3e, 0xd2, 0x74, - 0x13, 0xd1, 0xd3, 0x37, 0x5e, 0xd2, 0x53, 0xc2, 0x48, 0x62, 0xae, 0x2a, 0x72, 0xa5, 0xc6, 0xa2, - 0x7e, 0x2e, 0xe0, 0x75, 0xd5, 0x0f, 0xca, 0x3a, 0xf3, 0xbd, 0xe5, 0x5f, 0x69, 0x5e, 0x68, 0xfc, - 0x49, 0x76, 0x79, 0x47, 0x36, 0x1c, 0x15, 0xe9, 0xfd, 0x9e, 0xc3, 0xea, 0xa5, 0xed, 0x84, 0x6a, - 0x7e, 0x9a, 0x5a, 0x54, 0xc0, 0xfe, 0x9e, 0xbc, 0xa4, 0xbf, 0x4f, 0xa9, 0x72, 0x42, 0xfa, 0x5b, - 0xbe, 0x9c, 0x07, 0x06, 0xeb, 0xff, 0x31, 0x0b, 0xf5, 0x64, 0x2b, 0xe2, 0x50, 0x4b, 0x3e, 0xa4, - 0xe4, 0x09, 0x29, 0x8f, 0x4b, 0x13, 0xed, 0x01, 0xc9, 0x11, 0xf3, 0xc6, 0xe3, 0x6c, 0x8a, 0xf1, - 0x58, 0xb7, 0xd9, 0xe6, 0x5e, 0xe6, 0xdb, 0xca, 0xbf, 0x92, 0x6f, 0xab, 0x90, 0xe6, 0xdb, 0xba, - 0xd9, 0x21, 0xb2, 0xf0, 0x73, 0x39, 0x44, 0x8a, 0x37, 0x3b, 0x44, 0xd6, 0xff, 0x2a, 0x03, 0x6c, - 0x9e, 0x52, 0xd9, 0x53, 0xb2, 0x93, 0xbb, 0x7c, 0x24, 0xb9, 0xd8, 0x37, 0x5f, 0x8d, 0xda, 0xd5, - 0x06, 0xa9, 0xda, 0xec, 0x11, 0x2c, 0xe9, 0x71, 0xc1, 0xba, 0xaa, 0x52, 0x33, 0x99, 0x5e, 0x14, - 0x2b, 0xb4, 0x9a, 0x63, 0x2f, 0xff, 0x52, 0xc7, 0x5e, 0xe1, 0xa5, 0x8e, 0xbd, 0x85, 0xa4, 0x63, - 0x6f, 0xfd, 0x6f, 0x67, 0x60, 0x29, 0x85, 0xa8, 0xbe, 0xba, 0x39, 0x0b, 0x5a, 0x48, 0xb0, 0x98, - 0xac, 0xa4, 0x05, 0x8d, 0xbb, 0xac, 0xff, 0x04, 0x6a, 0x89, 0x43, 0xf4, 0xd5, 0x75, 0x3f, 0xab, - 0x68, 0x11, 0x29, 0xeb, 0x8a, 0xd6, 0xfa, 0xff, 0xcd, 0x01, 0x9b, 0x3f, 0xc7, 0xbf, 0xcc, 0x21, - 0xcc, 0x2f, 0x52, 0x6e, 0x7e, 0x91, 0xfe, 0xff, 0xdd, 0x2b, 0xef, 0xc2, 0xa2, 0xcc, 0x65, 0xd0, - 0x9c, 0x22, 0x44, 0x28, 0xcd, 0xa8, 0x40, 0x8d, 0xe2, 0x3b, 0xb3, 0x3e, 0xd5, 0x52, 0x22, 0x7c, - 0x5b, 0xbb, 0x58, 0x67, 0x5c, 0xab, 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, 0x47, 0x19, 0xbf, - 0xfe, 0xe4, 0x57, 0xbf, 0x34, 0x6b, 0xdd, 0x68, 0x63, 0x7d, 0xbc, 0xcd, 0x4d, 0xd9, 0x98, 0xf1, - 0x1e, 0x54, 0x34, 0x30, 0x3a, 0x0a, 0xba, 0xfb, 0x9b, 0x87, 0xcd, 0x5b, 0xac, 0x06, 0x65, 0xb3, - 0xb3, 0x75, 0xf8, 0x49, 0xc7, 0xec, 0x6c, 0x37, 0x33, 0xac, 0x04, 0xf9, 0xbd, 0xc3, 0x5e, 0xbf, - 0x99, 0x35, 0xd6, 0xa1, 0x25, 0x5b, 0x9c, 0x37, 0x1a, 0xfe, 0x34, 0x1f, 0xe9, 0xeb, 0x58, 0x28, - 0xc5, 0xf3, 0x6f, 0x41, 0x55, 0xbf, 0xf6, 0x24, 0x45, 0xcc, 0xf8, 0xe5, 0x84, 0x60, 0xee, 0x69, - 0x7c, 0x63, 0x0b, 0xc8, 0xdb, 0x32, 0x8c, 0xaa, 0x91, 0x2c, 0xf3, 0x02, 0xf3, 0x3c, 0x8a, 0x69, - 0x09, 0x32, 0xfc, 0x6b, 0x50, 0x4f, 0x5a, 0xd0, 0xa4, 0xd0, 0x99, 0x26, 0xa7, 0x8a, 0xda, 0x09, - 0x93, 0x1a, 0xfb, 0x3e, 0x34, 0x67, 0x2d, 0x70, 0x32, 0xca, 0xf5, 0x86, 0xfa, 0x0d, 0x27, 0x69, - 0x94, 0x63, 0xbb, 0xb0, 0x9c, 0x76, 0xf1, 0x23, 0x7d, 0xdc, 0xac, 0xa0, 0xb0, 0xf9, 0xcb, 0x9d, - 0x7d, 0x57, 0x1a, 0x5a, 0x0b, 0x69, 0xee, 0x2a, 0x6d, 0xb1, 0x37, 0xe8, 0x3f, 0xcd, 0xe4, 0x7a, - 0x01, 0x10, 0xc3, 0x58, 0x13, 0xaa, 0x87, 0x47, 0x9d, 0x03, 0x6b, 0x6b, 0xb7, 0x7d, 0x70, 0xd0, - 0xd9, 0x6b, 0xde, 0x62, 0x0c, 0xea, 0xe8, 0x67, 0xda, 0x8e, 0x60, 0x19, 0x01, 0x93, 0x06, 0x6f, - 0x05, 0xcb, 0xb2, 0x65, 0x68, 0x76, 0x0f, 0x66, 0xa0, 0x39, 0xd6, 0x82, 0xe5, 0xa3, 0x0e, 0xb9, - 0xa6, 0x12, 0xed, 0xe6, 0x85, 0x30, 0x29, 0xa7, 0x2b, 0x84, 0x49, 0xca, 0xc9, 0x91, 0xe7, 0x40, - 0xc9, 0x58, 0xbf, 0x9b, 0x81, 0x95, 0x99, 0x82, 0x38, 0xd2, 0x9a, 0x24, 0xac, 0xa4, 0x6c, 0x55, - 0x45, 0xa0, 0x3a, 0x4d, 0xef, 0xc2, 0x62, 0xa4, 0x74, 0xce, 0x70, 0xc8, 0x66, 0x54, 0xa0, 0x90, - 0x1f, 0xc1, 0x92, 0xa6, 0xbb, 0xce, 0xf0, 0x0a, 0xa6, 0x15, 0xc9, 0x0a, 0xc6, 0x5a, 0x14, 0xd1, - 0x3a, 0x33, 0xea, 0x21, 0x25, 0xfa, 0xe8, 0x05, 0xb1, 0x1d, 0x3a, 0x39, 0x5e, 0xf5, 0xc9, 0x1e, - 0xcf, 0x10, 0x42, 0x72, 0xb4, 0xfa, 0x86, 0xab, 0xee, 0x7f, 0x7f, 0x01, 0xd8, 0xc7, 0x53, 0xee, - 0x5f, 0x63, 0x24, 0x75, 0xf0, 0xb2, 0xd0, 0x22, 0xa5, 0xa0, 0x65, 0x5f, 0x29, 0x5b, 0x22, 0x2d, - 0x5b, 0x21, 0xff, 0xf2, 0x6c, 0x85, 0xc2, 0xcb, 0xb2, 0x15, 0xde, 0x84, 0x9a, 0x73, 0xe6, 0x7a, - 0x82, 0x15, 0x0a, 0x29, 0x29, 0x68, 0x2d, 0xdc, 0xcf, 0x3d, 0xa8, 0x9a, 0x55, 0x09, 0x14, 0x32, - 0x52, 0xc0, 0x3e, 0x8a, 0x91, 0xf8, 0xf0, 0x0c, 0x33, 0x6b, 0x74, 0x26, 0xd8, 0x19, 0x9e, 0x71, - 0xa9, 0x8f, 0xa2, 0x85, 0x46, 0x55, 0x16, 0xf0, 0x80, 0xbd, 0x05, 0xf5, 0xc0, 0x9b, 0x0a, 0xa1, - 0x53, 0x2d, 0x03, 0x59, 0xaa, 0xab, 0x04, 0x3d, 0x52, 0x6e, 0x89, 0xa5, 0x69, 0xc0, 0xad, 0xb1, - 0x13, 0x04, 0x42, 0x54, 0x18, 0x78, 0x6e, 0xe8, 0x7b, 0x23, 0x69, 0x7c, 0x5e, 0x9c, 0x06, 0x7c, - 0x9f, 0x4a, 0xb6, 0xa8, 0x80, 0x7d, 0x3b, 0x1e, 0xd2, 0xc4, 0x76, 0xfc, 0xa0, 0x05, 0x38, 0x24, - 0x35, 0x53, 0x94, 0xed, 0x6c, 0xc7, 0x8f, 0xc6, 0x22, 0x3e, 0x82, 0x99, 0x2c, 0x8a, 0xca, 0x6c, - 0x16, 0xc5, 0x8f, 0xd2, 0xb3, 0x28, 0x6a, 0xd8, 0xf4, 0x63, 0xd9, 0xf4, 0xfc, 0x16, 0x7f, 0xa9, - 0x64, 0x8a, 0xf9, 0xe4, 0x90, 0xfa, 0x97, 0x49, 0x0e, 0x69, 0xa4, 0x25, 0x87, 0xbc, 0x07, 0x15, - 0x0c, 0xdb, 0xb7, 0xce, 0x1d, 0x37, 0x54, 0xc6, 0xf4, 0xa6, 0x1e, 0xd7, 0xbf, 0x2b, 0xd4, 0x7a, - 0xf0, 0xd5, 0x9f, 0xc1, 0x7c, 0x9e, 0xc6, 0xe2, 0x2f, 0x31, 0x4f, 0x43, 0xa6, 0x17, 0x6c, 0x40, - 0x49, 0xed, 0x13, 0x63, 0x90, 0x3f, 0xf5, 0xbd, 0xb1, 0x32, 0x32, 0x8a, 0xbf, 0x59, 0x1d, 0xb2, - 0xa1, 0x27, 0x2b, 0x67, 0x43, 0xcf, 0xf8, 0x4d, 0xa8, 0x68, 0xa4, 0xc6, 0xde, 0x20, 0x73, 0x86, - 0x90, 0xdb, 0xa5, 0xbe, 0x4e, 0xab, 0x58, 0x96, 0xd0, 0xee, 0x50, 0xf0, 0x9b, 0xa1, 0xe3, 0x73, - 0xcc, 0xa8, 0xb2, 0x7c, 0x7e, 0xc1, 0xfd, 0x40, 0x19, 0x7d, 0x9b, 0x51, 0x81, 0x49, 0x70, 0xe3, - 0x6f, 0xc0, 0x52, 0x62, 0x6f, 0x25, 0x8b, 0x78, 0x0b, 0x16, 0x70, 0xdd, 0x94, 0x53, 0x2e, 0x99, - 0x2f, 0x21, 0xcb, 0x30, 0x55, 0x96, 0xec, 0xd5, 0xd6, 0xc4, 0xf7, 0x4e, 0xb0, 0x93, 0x8c, 0x59, - 0x91, 0xb0, 0x23, 0xdf, 0x3b, 0x31, 0xfe, 0x2c, 0x07, 0xb9, 0x5d, 0x6f, 0xa2, 0xc7, 0xa1, 0x64, - 0xe6, 0xe2, 0x50, 0xa4, 0x32, 0x62, 0x45, 0xca, 0x86, 0x94, 0x1f, 0xd1, 0x52, 0xab, 0x14, 0x8e, - 0x07, 0x50, 0x17, 0x7c, 0x22, 0xf4, 0x84, 0x36, 0x77, 0x69, 0xfb, 0x94, 0x3d, 0x91, 0xa3, 0xc3, - 0x67, 0x8f, 0xc3, 0xbe, 0xb7, 0x43, 0x70, 0xb6, 0x0c, 0xb9, 0x48, 0x94, 0xc6, 0x62, 0xf1, 0x29, - 0xd4, 0x7c, 0x8c, 0x23, 0xbc, 0x96, 0x5e, 0x27, 0xf9, 0xc5, 0xbe, 0x09, 0x4b, 0xc9, 0x76, 0x89, - 0x15, 0x49, 0xd9, 0x48, 0x6f, 0x18, 0x79, 0xd2, 0x6d, 0x10, 0x7c, 0x84, 0x70, 0xa4, 0xf3, 0xfa, - 0x94, 0x73, 0x2c, 0xd2, 0x98, 0x5e, 0x29, 0xc1, 0xf4, 0xee, 0x41, 0x25, 0x1c, 0x5d, 0x58, 0x13, - 0xfb, 0x7a, 0xe4, 0xd9, 0x43, 0x79, 0xbe, 0x21, 0x1c, 0x5d, 0x1c, 0x11, 0x84, 0x3d, 0x02, 0x18, - 0x4f, 0x26, 0xf2, 0xec, 0xa1, 0xe1, 0x33, 0x26, 0xe5, 0xfd, 0xa3, 0x23, 0x22, 0x39, 0xb3, 0x3c, - 0x9e, 0x4c, 0xe8, 0x4f, 0xb6, 0x0d, 0xf5, 0xd4, 0xac, 0xa7, 0xbb, 0x2a, 0xec, 0xcd, 0x9b, 0x6c, - 0xa4, 0x1c, 0xce, 0xda, 0x40, 0x87, 0xad, 0x7f, 0x1f, 0xd8, 0x2f, 0x98, 0x7b, 0xd4, 0x87, 0x72, - 0x34, 0x3e, 0x3d, 0x75, 0x07, 0x03, 0x59, 0x2b, 0x89, 0xd4, 0x9d, 0xf6, 0x70, 0xe8, 0x0b, 0xbe, - 0x48, 0x17, 0x66, 0xc4, 0xf2, 0x41, 0xbb, 0x31, 0xdb, 0xc4, 0xf7, 0x8d, 0xbf, 0xc8, 0x40, 0x81, - 0xf2, 0x88, 0xde, 0x86, 0x06, 0xe1, 0x47, 0x31, 0x3d, 0xd2, 0x57, 0x45, 0xf7, 0x6e, 0x5f, 0x86, - 0xf3, 0x88, 0x63, 0xa1, 0xe5, 0x40, 0x66, 0xa3, 0x9d, 0xd7, 0xf2, 0x20, 0xef, 0x41, 0x39, 0xea, - 0x5a, 0x23, 0x9d, 0x92, 0xea, 0x99, 0xbd, 0x0e, 0xf9, 0x73, 0x6f, 0xa2, 0xac, 0x02, 0x10, 0xaf, - 0xa4, 0x89, 0xf0, 0x78, 0x2c, 0xa2, 0x0f, 0x1a, 0xbc, 0xd4, 0x66, 0xa3, 0x4e, 0x90, 0x0c, 0xe6, - 0xe7, 0xb8, 0x90, 0x32, 0xc7, 0x63, 0x68, 0x08, 0x3e, 0xa0, 0xf9, 0x8c, 0x6f, 0xbe, 0x34, 0xbf, - 0x2e, 0x24, 0xbc, 0xc1, 0x68, 0x3a, 0xe4, 0xba, 0x4d, 0x06, 0x03, 0x4c, 0x24, 0x5c, 0x49, 0xd6, - 0xc6, 0xef, 0x67, 0x88, 0xbf, 0x88, 0x76, 0xd9, 0x03, 0xc8, 0x8b, 0xfb, 0x6d, 0xc6, 0x66, 0x18, - 0x45, 0x14, 0x0b, 0x3c, 0x13, 0x31, 0x30, 0x71, 0x78, 0x3a, 0x4e, 0xb6, 0x5e, 0x33, 0x2b, 0xee, - 0x74, 0x1c, 0x99, 0x35, 0xbe, 0xa6, 0xa6, 0x35, 0x63, 0x12, 0xa0, 0xd9, 0x47, 0xc7, 0x74, 0x43, - 0x8b, 0x54, 0xc9, 0x27, 0x6e, 0x4c, 0x25, 0x05, 0x0e, 0xcf, 0xb8, 0x16, 0xa1, 0xf2, 0x87, 0x59, - 0xa8, 0x25, 0x46, 0x84, 0xa1, 0x3a, 0xe2, 0x02, 0x20, 0x7b, 0xb4, 0xdc, 0x6f, 0x10, 0x20, 0x29, - 0xa8, 0x6b, 0xeb, 0x94, 0x4d, 0xac, 0x53, 0xe4, 0x1d, 0xcf, 0xe9, 0xde, 0xf1, 0xc7, 0x50, 0x8e, - 0x73, 0x5f, 0x93, 0x43, 0x12, 0xfd, 0xa9, 0xb8, 0xea, 0x18, 0x29, 0xf6, 0xa7, 0x17, 0x74, 0x7f, - 0xfa, 0xf7, 0x34, 0xf7, 0xeb, 0x02, 0x36, 0x63, 0xa4, 0xad, 0xe8, 0x2f, 0xc5, 0xf9, 0x6a, 0x7c, - 0x04, 0x15, 0x6d, 0xf0, 0xba, 0x9b, 0x35, 0x93, 0x70, 0xb3, 0x46, 0x19, 0x10, 0xd9, 0x38, 0x03, - 0xc2, 0xf8, 0xed, 0x2c, 0xd4, 0xc4, 0xf9, 0x72, 0xdc, 0xb3, 0x23, 0x6f, 0xe4, 0x0c, 0xd0, 0x3e, - 0x1d, 0x9d, 0x30, 0x29, 0x68, 0xa9, 0x73, 0x26, 0x8f, 0x18, 0xc9, 0x59, 0x7a, 0xa2, 0x17, 0x31, - 0xe9, 0x28, 0xd1, 0xcb, 0x80, 0x9a, 0x60, 0x8c, 0x27, 0x76, 0xc0, 0xb5, 0xcc, 0x5c, 0xb3, 0x72, - 0xca, 0xf9, 0xa6, 0x1d, 0x10, 0x87, 0xfc, 0x26, 0x2c, 0x09, 0x1c, 0xcc, 0x71, 0x19, 0x3b, 0xa3, - 0x91, 0x43, 0x98, 0x64, 0xf4, 0x68, 0x9e, 0x72, 0x6e, 0xda, 0x21, 0xdf, 0x17, 0x05, 0x32, 0x91, - 0xb7, 0x34, 0x74, 0x02, 0xfb, 0x24, 0x0e, 0xa8, 0x8a, 0xbe, 0xd1, 0xab, 0x64, 0x5f, 0x69, 0x5e, - 0x25, 0x4a, 0x76, 0xab, 0x8c, 0xed, 0xab, 0xc8, 0xab, 0x34, 0x43, 0x49, 0xc5, 0x59, 0x4a, 0x32, - 0xfe, 0x4b, 0x16, 0x2a, 0x1a, 0x59, 0xbe, 0xca, 0xed, 0x7a, 0x77, 0xce, 0x9f, 0x50, 0xd6, 0x5d, - 0x07, 0x6f, 0x26, 0xbb, 0x44, 0xe7, 0x33, 0xa5, 0x0c, 0x6b, 0x04, 0x7c, 0x07, 0xca, 0xe2, 0xd4, - 0xbd, 0x87, 0xe6, 0x39, 0x99, 0xf0, 0x8e, 0x80, 0xa3, 0xe9, 0x89, 0x2a, 0x7c, 0x82, 0x85, 0x85, - 0xb8, 0xf0, 0x89, 0x28, 0x7c, 0x51, 0x14, 0xe5, 0x77, 0xa0, 0x2a, 0x5b, 0xc5, 0x3d, 0xc5, 0xe9, - 0xc6, 0xa7, 0x3e, 0xb1, 0xdf, 0x66, 0x85, 0xba, 0xa3, 0xcd, 0x97, 0x15, 0x9f, 0xa8, 0x8a, 0xa5, - 0x97, 0x55, 0x7c, 0x42, 0x1f, 0xc6, 0x4e, 0x14, 0x98, 0x8a, 0x81, 0x0f, 0x8a, 0x8f, 0x3d, 0x82, - 0x25, 0xc5, 0xae, 0xa6, 0xae, 0xed, 0xba, 0xde, 0xd4, 0x1d, 0x70, 0x95, 0x1a, 0xc1, 0x64, 0xd1, - 0x71, 0x5c, 0x62, 0x0c, 0xa3, 0xdc, 0x39, 0x0a, 0xa0, 0x78, 0x08, 0x05, 0x92, 0xcb, 0x49, 0xf8, - 0x48, 0x67, 0x5c, 0x84, 0xc2, 0x1e, 0x40, 0x81, 0xc4, 0xf3, 0xec, 0x8d, 0xcc, 0x86, 0x10, 0x8c, - 0x0d, 0x68, 0xa0, 0x88, 0xa9, 0x71, 0xdc, 0x17, 0x49, 0x25, 0xc6, 0x32, 0xb0, 0x03, 0x3a, 0x44, - 0x7a, 0x60, 0xcf, 0x7f, 0xcf, 0x41, 0x45, 0x03, 0x0b, 0xb6, 0x88, 0xa1, 0x20, 0xd6, 0xd0, 0xb1, - 0xc7, 0x5c, 0x79, 0x41, 0x6a, 0x66, 0x0d, 0xa1, 0xdb, 0x12, 0x28, 0x2e, 0x05, 0xfb, 0xe2, 0xcc, - 0xf2, 0xa6, 0xa1, 0x35, 0xe4, 0x67, 0x3e, 0xe7, 0x52, 0x58, 0xaa, 0xda, 0x17, 0x67, 0x87, 0xd3, - 0x70, 0x1b, 0x61, 0x02, 0x4b, 0x10, 0xb5, 0x86, 0x25, 0xa3, 0x17, 0xc6, 0xf6, 0x55, 0x8c, 0x25, - 0x43, 0x68, 0x68, 0x89, 0xf2, 0x51, 0x08, 0x0d, 0xa9, 0x2d, 0xb3, 0x9c, 0xbc, 0x30, 0xcf, 0xc9, - 0xbf, 0x0d, 0xab, 0xc4, 0xc9, 0x25, 0x8f, 0xb0, 0x66, 0x48, 0x6a, 0x19, 0x4b, 0xe5, 0x24, 0x35, - 0xf9, 0xab, 0x29, 0x66, 0xa0, 0xce, 0x47, 0xe0, 0xfc, 0x98, 0x4e, 0x54, 0xc6, 0x14, 0x33, 0x93, - 0x8d, 0xf7, 0x9c, 0x1f, 0x73, 0x81, 0x89, 0x2e, 0x5a, 0x1d, 0x53, 0x06, 0xeb, 0x8e, 0x1d, 0x77, - 0x16, 0xd3, 0xbe, 0x4a, 0x62, 0x96, 0x25, 0xa6, 0x7d, 0xa5, 0x63, 0xbe, 0x0f, 0x6b, 0x63, 0x3e, - 0x74, 0xec, 0x64, 0xb3, 0x56, 0x2c, 0x41, 0x2c, 0x53, 0xb1, 0x56, 0xa7, 0x47, 0x1a, 0xa4, 0x58, - 0x8d, 0x1f, 0x7b, 0xe3, 0x13, 0x87, 0x2e, 0x4f, 0x72, 0x1a, 0xe7, 0xcd, 0xba, 0x3b, 0x1d, 0xff, - 0x10, 0xc1, 0xa2, 0x4a, 0x60, 0xd4, 0xa0, 0xd2, 0x0b, 0xbd, 0x89, 0xda, 0xe6, 0x3a, 0x54, 0xe9, - 0x53, 0x26, 0xbe, 0xdc, 0x81, 0xdb, 0x48, 0x9b, 0x7d, 0x6f, 0xe2, 0x8d, 0xbc, 0xb3, 0xeb, 0x84, - 0x41, 0xe9, 0xbf, 0x65, 0x60, 0x29, 0x51, 0x2a, 0xcf, 0xf9, 0xb7, 0xe9, 0x60, 0x45, 0xd9, 0x0b, - 0x44, 0xce, 0x8b, 0xda, 0xe5, 0x43, 0x88, 0x74, 0xaa, 0x54, 0x46, 0x43, 0x3b, 0xce, 0xba, 0x55, - 0x15, 0x89, 0xb6, 0x5b, 0xf3, 0xb4, 0x2d, 0xeb, 0xab, 0x7c, 0x5c, 0xd5, 0xc4, 0xaf, 0xca, 0x80, - 0xea, 0xa1, 0x9c, 0x72, 0x2e, 0x19, 0x32, 0xaa, 0x1b, 0x9f, 0xd4, 0x08, 0x62, 0x8b, 0x54, 0x60, - 0xfc, 0xeb, 0x0c, 0x40, 0x3c, 0x3a, 0x0c, 0x5a, 0x8d, 0x2e, 0x50, 0x7a, 0xd0, 0x46, 0xbb, 0x2c, - 0xdf, 0x80, 0x6a, 0x14, 0xbb, 0x16, 0x5f, 0xc9, 0x15, 0x05, 0x13, 0xf7, 0xf2, 0x3b, 0xd0, 0x38, - 0x1b, 0x79, 0x27, 0x28, 0x3a, 0xc9, 0x0b, 0x94, 0xd2, 0x7f, 0xea, 0x04, 0x56, 0xd7, 0x62, 0x7c, - 0x81, 0xe7, 0x53, 0xc3, 0xdb, 0xf4, 0xeb, 0xd8, 0xf8, 0x9d, 0x6c, 0x14, 0xc4, 0x13, 0xaf, 0xc4, - 0x8b, 0xf5, 0x8c, 0x9f, 0xc7, 0x17, 0xfc, 0x22, 0x1f, 0xc8, 0x47, 0x50, 0xf7, 0x89, 0x3b, 0x2a, - 0xd6, 0x99, 0x7f, 0x01, 0xeb, 0xac, 0xf9, 0x89, 0x2b, 0xf7, 0xeb, 0xd0, 0xb4, 0x87, 0x17, 0xdc, - 0x0f, 0x1d, 0x34, 0x1b, 0xa3, 0xa0, 0x26, 0xc3, 0x66, 0x34, 0x38, 0x4a, 0x44, 0xef, 0x40, 0x43, - 0x26, 0x63, 0x45, 0x98, 0xf2, 0x79, 0x87, 0x18, 0x2c, 0x10, 0x8d, 0x7f, 0xa7, 0xa2, 0x86, 0x92, - 0xbb, 0xfb, 0xe2, 0x55, 0xd1, 0x67, 0x98, 0x9d, 0xf7, 0xf2, 0x48, 0x42, 0x92, 0xd6, 0x68, 0xc9, - 0x8f, 0x08, 0x28, 0x6d, 0xd1, 0xc9, 0x65, 0xcd, 0xbf, 0xca, 0xb2, 0x1a, 0x7f, 0x9c, 0x81, 0xe2, - 0xae, 0x37, 0x11, 0x7a, 0xb9, 0x90, 0xe7, 0xf0, 0x98, 0x44, 0x89, 0x90, 0x0b, 0xe2, 0xb3, 0x3b, - 0x7c, 0x71, 0xf2, 0x42, 0xaa, 0xbc, 0x51, 0x4b, 0xca, 0x1b, 0xdf, 0x83, 0x3b, 0xe8, 0x17, 0xf1, - 0xbd, 0x89, 0xe7, 0x8b, 0xa3, 0x6a, 0x8f, 0x48, 0xee, 0xf0, 0xdc, 0xf0, 0x5c, 0xf1, 0xce, 0xdb, - 0xa7, 0x9c, 0x1f, 0x69, 0x18, 0xfb, 0x11, 0x02, 0x66, 0xf5, 0x8c, 0xc2, 0x0b, 0x8b, 0x54, 0x45, - 0x29, 0x18, 0x11, 0x47, 0x6d, 0x88, 0x82, 0x0e, 0xc2, 0x51, 0x34, 0x32, 0xbe, 0x0b, 0xe5, 0xc8, - 0xea, 0xc0, 0xde, 0x85, 0xf2, 0xb9, 0x37, 0x91, 0xa6, 0x89, 0x4c, 0x22, 0xc1, 0x43, 0xce, 0xda, - 0x2c, 0x9d, 0xd3, 0x1f, 0x81, 0xf1, 0x67, 0x45, 0x28, 0x76, 0xdd, 0x0b, 0xcf, 0x19, 0x60, 0xdc, - 0xd1, 0x98, 0x8f, 0x3d, 0x95, 0x11, 0x2a, 0xfe, 0xc6, 0xd8, 0x82, 0xf8, 0x91, 0x86, 0x9c, 0x8c, - 0x2d, 0x88, 0x9e, 0x67, 0x58, 0x81, 0x05, 0x5f, 0x7f, 0x65, 0xa1, 0xe0, 0x63, 0x24, 0x64, 0xa4, - 0xb4, 0x15, 0xb4, 0x8c, 0x5a, 0xd1, 0x16, 0x65, 0xff, 0xe3, 0x92, 0x51, 0x86, 0x4e, 0x19, 0x21, - 0xb8, 0x60, 0xaf, 0x41, 0x51, 0xe6, 0x53, 0x50, 0x74, 0x3a, 0x85, 0x2e, 0x4a, 0x10, 0x52, 0x83, - 0xcf, 0xc9, 0xaf, 0x15, 0x49, 0x54, 0x42, 0x4f, 0x97, 0xc0, 0x6d, 0x41, 0x6b, 0xf7, 0xa0, 0x42, - 0xf8, 0x84, 0x52, 0x92, 0x91, 0x42, 0x08, 0x42, 0x84, 0x94, 0xc7, 0x4a, 0xca, 0xa9, 0x8f, 0x95, - 0x60, 0x60, 0x59, 0xc4, 0x65, 0x69, 0x8a, 0x40, 0x4f, 0x54, 0x68, 0x70, 0xf5, 0x52, 0x8f, 0x54, - 0xee, 0x29, 0x61, 0x4d, 0x29, 0xf7, 0x6f, 0x42, 0xed, 0xd4, 0x1e, 0x8d, 0x4e, 0xec, 0xc1, 0x73, - 0xd2, 0x49, 0xab, 0x64, 0x86, 0x53, 0x40, 0x54, 0x4a, 0xef, 0x41, 0x45, 0xdb, 0x65, 0x0c, 0x03, - 0xca, 0x9b, 0x10, 0xef, 0xef, 0xac, 0xa9, 0xa9, 0xfe, 0x0a, 0xa6, 0x26, 0x2d, 0x1c, 0xaa, 0x91, - 0x0c, 0x87, 0xba, 0x83, 0xdc, 0x54, 0x86, 0xcc, 0x34, 0xe9, 0x3d, 0x04, 0x7b, 0x38, 0xc4, 0x90, - 0x19, 0x7a, 0x7c, 0x0c, 0x17, 0x8f, 0xca, 0x17, 0x49, 0xa8, 0x25, 0x18, 0xa1, 0xdc, 0x25, 0x7b, - 0xe9, 0xc4, 0x76, 0x86, 0x18, 0x7e, 0x4a, 0x6a, 0x6c, 0xd1, 0x1e, 0x87, 0x47, 0xb6, 0x33, 0x64, - 0xf7, 0xa1, 0xaa, 0x8a, 0xf1, 0x76, 0x5c, 0xa2, 0xf5, 0x97, 0xc5, 0xe2, 0x4e, 0x34, 0xa0, 0x16, - 0x61, 0x8c, 0xe3, 0xac, 0xb3, 0x8a, 0x44, 0x41, 0x3a, 0x78, 0x0f, 0xc3, 0x10, 0x42, 0x8e, 0xb9, - 0x65, 0xf5, 0x27, 0x77, 0xe4, 0x5c, 0x25, 0x95, 0xaa, 0xff, 0xc9, 0x4b, 0x43, 0x98, 0x42, 0x10, - 0x23, 0x67, 0xd1, 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0x2c, 0x22, 0x04, 0xf6, 0x5d, 0x4d, 0x91, - 0x6a, 0x21, 0xf2, 0x6b, 0x33, 0xed, 0xdf, 0x14, 0x7d, 0x7f, 0x17, 0xc0, 0x09, 0xc4, 0x2d, 0x13, - 0x70, 0x77, 0x88, 0x69, 0x62, 0x25, 0xb3, 0xec, 0x04, 0xcf, 0x08, 0xf0, 0xd5, 0x6a, 0x58, 0x6d, - 0xa8, 0xea, 0xd3, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0x75, 0x0e, 0x9a, 0xb7, 0x58, 0x05, 0x8a, 0xbd, - 0x4e, 0xbf, 0xbf, 0x87, 0x2e, 0xa7, 0x2a, 0x94, 0xa2, 0x64, 0x97, 0xac, 0xf8, 0x6a, 0x6f, 0x6d, - 0x75, 0x8e, 0xfa, 0x9d, 0xed, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, 0x99, 0x33, 0xfe, 0x3c, 0x07, - 0x15, 0x6d, 0x15, 0x5e, 0xcc, 0x8c, 0xef, 0x02, 0xa0, 0x4a, 0x13, 0x47, 0x54, 0xe5, 0xcd, 0xb2, - 0x80, 0xd0, 0xe6, 0xeb, 0xc6, 0xf2, 0x1c, 0x3d, 0xb4, 0xa1, 0x8c, 0xe5, 0x6f, 0x42, 0x8d, 0xde, - 0xac, 0xd0, 0x1d, 0x87, 0x05, 0xb3, 0x4a, 0x40, 0xc9, 0xaa, 0x31, 0x5b, 0x0e, 0x91, 0x30, 0x8f, - 0x42, 0x66, 0xb0, 0x13, 0x08, 0x33, 0x29, 0x30, 0x0d, 0x26, 0xf0, 0x46, 0x17, 0x9c, 0x30, 0x48, - 0x22, 0xac, 0x48, 0x58, 0x5f, 0xa6, 0xeb, 0x49, 0x7e, 0xa8, 0xa5, 0x6b, 0x15, 0xcc, 0x2a, 0x01, - 0x65, 0x47, 0xdf, 0x54, 0x04, 0x54, 0x42, 0x02, 0x5a, 0x9b, 0xa7, 0x86, 0x04, 0xf1, 0xec, 0xcd, - 0xd9, 0xb3, 0xca, 0x48, 0x18, 0x5f, 0x9b, 0xaf, 0xf7, 0x72, 0xbb, 0x16, 0x7b, 0x17, 0xd8, 0x78, - 0x32, 0xb1, 0x52, 0x2c, 0x4d, 0x79, 0xb3, 0x31, 0x9e, 0x4c, 0xfa, 0x9a, 0x21, 0xe6, 0x2b, 0x30, - 0x82, 0x7d, 0x0e, 0xac, 0x2d, 0x0e, 0x30, 0x0e, 0x31, 0x32, 0xa1, 0xc6, 0x6c, 0x39, 0xa3, 0xb3, - 0xe5, 0x14, 0xee, 0x97, 0x4d, 0xe5, 0x7e, 0x2f, 0xe2, 0x13, 0xc6, 0x0e, 0x54, 0x8e, 0xb4, 0x17, - 0x71, 0xee, 0x8b, 0x1b, 0x42, 0xbd, 0x85, 0x43, 0x77, 0x07, 0x19, 0xb7, 0x7c, 0xf9, 0x04, 0x8e, - 0x36, 0x9a, 0xac, 0x36, 0x1a, 0xe3, 0x5f, 0x65, 0xe8, 0xb5, 0x81, 0x68, 0xf0, 0xf1, 0x23, 0x3c, - 0xca, 0x0f, 0x14, 0x67, 0x55, 0x56, 0x94, 0xff, 0x47, 0x26, 0x44, 0xe2, 0xd0, 0x2c, 0xef, 0xf4, - 0x34, 0xe0, 0x2a, 0x3f, 0xa8, 0x82, 0xb0, 0x43, 0x04, 0x29, 0xe1, 0x5b, 0x48, 0xf8, 0x0e, 0xb5, - 0x1f, 0xc8, 0x3c, 0x21, 0x21, 0x7c, 0xef, 0xdb, 0x57, 0xb2, 0xd7, 0x40, 0x88, 0x20, 0xd2, 0x50, - 0xad, 0xb2, 0xa2, 0xa2, 0x6f, 0xe3, 0x9f, 0xcb, 0xc4, 0xcf, 0xd9, 0xf5, 0x7d, 0x08, 0xa5, 0xa8, - 0xd5, 0xe4, 0x0d, 0xab, 0x30, 0xa3, 0x72, 0x71, 0x8f, 0xa3, 0x56, 0x9e, 0x18, 0x31, 0x1d, 0x2e, - 0x74, 0x36, 0x74, 0xb5, 0x51, 0x7f, 0x03, 0xd8, 0xa9, 0xe3, 0xcf, 0x22, 0xd3, 0x61, 0x6b, 0x62, - 0x89, 0x86, 0x6d, 0x1c, 0xc3, 0x92, 0xe2, 0x12, 0x9a, 0x46, 0x90, 0xdc, 0xbc, 0xcc, 0x4b, 0x98, - 0x7c, 0x76, 0x8e, 0xc9, 0x1b, 0x3f, 0xcb, 0x43, 0x51, 0xbd, 0x2e, 0x95, 0xf6, 0x22, 0x52, 0x39, - 0xf9, 0x22, 0x52, 0x2b, 0xf1, 0x7a, 0x06, 0x6e, 0xbd, 0xbc, 0xef, 0xdf, 0x99, 0xbd, 0xb2, 0x35, - 0xa3, 0x79, 0xe2, 0xda, 0x5e, 0x85, 0xfc, 0xc4, 0x0e, 0xcf, 0xd1, 0x40, 0x46, 0xc4, 0x83, 0xdf, - 0xca, 0x98, 0x5e, 0x48, 0x1a, 0xd3, 0xd3, 0x5e, 0x8f, 0x22, 0x91, 0x74, 0xee, 0xf5, 0xa8, 0x3b, - 0x40, 0xf2, 0x85, 0x16, 0x99, 0x53, 0x42, 0x80, 0xb8, 0x8b, 0x92, 0xe2, 0x48, 0x69, 0x56, 0x1c, - 0x79, 0x65, 0x51, 0xe1, 0xdb, 0xb0, 0x40, 0x99, 0xd7, 0x32, 0xfb, 0x4b, 0x5d, 0x28, 0x72, 0x0d, - 0xd5, 0xff, 0x14, 0x8e, 0x6b, 0x4a, 0x5c, 0xfd, 0x29, 0x96, 0x4a, 0xe2, 0x29, 0x16, 0xdd, 0xc8, - 0x5f, 0x4d, 0x1a, 0xf9, 0x1f, 0x40, 0x33, 0x5a, 0x50, 0x34, 0x99, 0xb9, 0x81, 0xcc, 0x2d, 0xa9, - 0x2b, 0xb8, 0xe0, 0x92, 0x07, 0x41, 0x7c, 0x21, 0xd6, 0x13, 0x17, 0xa2, 0xe0, 0x61, 0xed, 0x30, - 0xe4, 0xe3, 0x49, 0x28, 0x2f, 0x44, 0x8c, 0x3e, 0xd7, 0x07, 0x98, 0xcc, 0x8b, 0xac, 0x41, 0xb9, - 0x7b, 0x60, 0xed, 0xec, 0x75, 0x9f, 0xee, 0xf6, 0x9b, 0x19, 0xf1, 0xd9, 0x3b, 0xde, 0xda, 0xea, - 0x74, 0xb6, 0xf1, 0xc6, 0x01, 0x58, 0xd8, 0x69, 0x77, 0xc5, 0xed, 0x93, 0x33, 0x7e, 0x37, 0x0b, - 0x15, 0xad, 0x79, 0xf6, 0x7e, 0xb4, 0x2a, 0xf4, 0x5a, 0xc7, 0xdd, 0xf9, 0x21, 0x6c, 0x28, 0x56, - 0xac, 0x2d, 0x4b, 0xf4, 0x56, 0x56, 0xf6, 0xc6, 0xb7, 0xb2, 0xd8, 0xdb, 0xd0, 0xb0, 0xa9, 0x85, - 0x68, 0x15, 0xa4, 0x39, 0x58, 0x82, 0xe5, 0x22, 0x60, 0x3c, 0x5a, 0x7c, 0x9f, 0x08, 0xbc, 0xbc, - 0x0a, 0x01, 0x8b, 0xae, 0x14, 0x5c, 0xac, 0xe2, 0xa9, 0xed, 0x8c, 0xa6, 0x3e, 0x97, 0xee, 0xdb, - 0xe8, 0x66, 0x26, 0xa8, 0xa9, 0x8a, 0x8d, 0x0f, 0x00, 0xe2, 0x31, 0x27, 0x17, 0xe7, 0x56, 0x72, - 0x71, 0x32, 0xda, 0xe2, 0x64, 0x8d, 0x6d, 0x62, 0x23, 0x72, 0xa1, 0x23, 0x4f, 0xf5, 0x37, 0x41, - 0x59, 0xa4, 0x2c, 0x8c, 0x08, 0x9d, 0x8c, 0x78, 0xa8, 0x32, 0x48, 0x17, 0x65, 0x49, 0x37, 0x2a, - 0x50, 0x09, 0xdd, 0x71, 0x2b, 0x31, 0x37, 0x92, 0x24, 0x39, 0xcb, 0x8d, 0x24, 0xaa, 0x19, 0x95, - 0x1b, 0xeb, 0xd0, 0xda, 0xe6, 0xa2, 0xb5, 0xf6, 0x68, 0x34, 0x33, 0x1c, 0xe3, 0x0e, 0xdc, 0x4e, - 0x29, 0x93, 0x46, 0x88, 0x8f, 0x61, 0xa5, 0x4d, 0xc9, 0xa2, 0x5f, 0x55, 0x56, 0x88, 0xd1, 0x82, - 0xd5, 0xd9, 0x26, 0x65, 0x67, 0x3b, 0xb0, 0xb8, 0xcd, 0x4f, 0xa6, 0x67, 0x7b, 0xfc, 0x22, 0xee, - 0x88, 0x41, 0x3e, 0x38, 0xf7, 0x2e, 0xe5, 0xfa, 0xe0, 0xdf, 0xe2, 0x0c, 0x8f, 0x04, 0x8e, 0x15, - 0x4c, 0xf8, 0x40, 0x59, 0x44, 0x11, 0xd2, 0x9b, 0xf0, 0x81, 0xf1, 0x3e, 0x30, 0xbd, 0x1d, 0xb9, - 0x5e, 0x42, 0x4b, 0x98, 0x9e, 0x58, 0xc1, 0x75, 0x10, 0xf2, 0xb1, 0x7a, 0x0c, 0x06, 0x82, 0xe9, - 0x49, 0x8f, 0x20, 0xc6, 0x3b, 0x50, 0x3d, 0xb2, 0xaf, 0x4d, 0xfe, 0xb9, 0xcc, 0x77, 0x58, 0x83, - 0xe2, 0xc4, 0xbe, 0x16, 0x6c, 0x20, 0x72, 0x8e, 0x60, 0xb1, 0xf1, 0x07, 0x79, 0x58, 0x20, 0x4c, - 0x76, 0x9f, 0xde, 0x6b, 0x74, 0x5c, 0x3c, 0x86, 0x8a, 0x51, 0x6a, 0xa0, 0x39, 0x5e, 0x9a, 0x9d, - 0xe7, 0xa5, 0xd2, 0x80, 0xa6, 0xde, 0xa9, 0x50, 0x66, 0x6c, 0x77, 0x3a, 0x56, 0x8f, 0x53, 0x24, - 0x33, 0x26, 0xf3, 0xf1, 0x7b, 0x9c, 0x94, 0x4e, 0x96, 0x74, 0x34, 0xc6, 0xba, 0x08, 0x8d, 0x4e, - 0x5d, 0x11, 0x92, 0x5d, 0xea, 0xa0, 0x54, 0x85, 0xa7, 0xa8, 0x32, 0x69, 0x92, 0x0a, 0xcf, 0x9c, - 0x62, 0x53, 0x7a, 0xb9, 0x62, 0x43, 0x96, 0xb5, 0x17, 0x28, 0x36, 0xf0, 0x0a, 0x8a, 0xcd, 0x2b, - 0x38, 0xf9, 0x6e, 0x43, 0x09, 0xef, 0x7d, 0x8d, 0x7b, 0x8a, 0xfb, 0x5e, 0x70, 0xcf, 0xef, 0x68, - 0xa2, 0x3f, 0x45, 0x18, 0xdc, 0x89, 0x8f, 0x89, 0xc9, 0x3f, 0xff, 0xe5, 0x38, 0x4f, 0x3e, 0x83, - 0xa2, 0x84, 0x0a, 0x82, 0x76, 0xed, 0xb1, 0x7a, 0xea, 0x07, 0xff, 0x16, 0xcb, 0x86, 0xef, 0x93, - 0x7c, 0x3e, 0x75, 0x7c, 0x3e, 0x54, 0x8f, 0x41, 0x38, 0x78, 0x46, 0x05, 0x44, 0x4c, 0x50, 0xa8, - 0x21, 0xae, 0x77, 0xe9, 0xca, 0x54, 0xf0, 0xa2, 0x13, 0x3c, 0x13, 0x9f, 0x06, 0x83, 0x26, 0x3e, - 0xf6, 0x35, 0xf1, 0x7c, 0x75, 0x39, 0x19, 0x3f, 0xcb, 0x40, 0x53, 0x9e, 0xae, 0xa8, 0x4c, 0xd7, - 0x02, 0x0a, 0x37, 0x39, 0xc4, 0x5f, 0xfc, 0xb4, 0x83, 0x01, 0x35, 0x34, 0x7e, 0x44, 0x37, 0x15, - 0x19, 0x6f, 0x2a, 0x02, 0xb8, 0x23, 0x6f, 0xab, 0xd7, 0xa1, 0xa2, 0x02, 0x43, 0xc7, 0xce, 0x48, - 0x3d, 0xbd, 0x4b, 0x91, 0xa1, 0xfb, 0xce, 0x48, 0x5d, 0x74, 0xbe, 0x2d, 0x33, 0xbb, 0x32, 0x78, - 0xd1, 0x99, 0x76, 0xc8, 0x8d, 0xff, 0x94, 0x81, 0x45, 0x6d, 0x2a, 0xf2, 0xdc, 0x7e, 0x08, 0xd5, - 0xe8, 0x95, 0x3d, 0x1e, 0x49, 0x5e, 0x6b, 0x49, 0x46, 0x13, 0x57, 0xab, 0x0c, 0x22, 0x48, 0x20, - 0x06, 0x33, 0xb4, 0xaf, 0x71, 0xbc, 0xc1, 0x74, 0xac, 0x94, 0x9b, 0xa1, 0x7d, 0xbd, 0xc3, 0x79, - 0x6f, 0x3a, 0x16, 0xaa, 0xeb, 0x25, 0xe7, 0xcf, 0x23, 0x04, 0x92, 0xb9, 0x40, 0xc0, 0x24, 0x86, - 0x01, 0xb5, 0xb1, 0xe7, 0x86, 0xe7, 0x11, 0x8a, 0x94, 0x3a, 0x11, 0x48, 0x38, 0xc6, 0x9f, 0x66, - 0x61, 0x89, 0x4c, 0x6c, 0xd2, 0xb4, 0x29, 0x59, 0x57, 0x0b, 0x16, 0xc8, 0xda, 0x48, 0xcc, 0x6b, - 0xf7, 0x96, 0x29, 0xbf, 0xd9, 0xb7, 0x5f, 0xd1, 0x2c, 0xa8, 0x92, 0xc7, 0x6e, 0x58, 0xfe, 0xdc, - 0xfc, 0xf2, 0xdf, 0xbc, 0xbc, 0x69, 0x1e, 0xb7, 0x42, 0x9a, 0xc7, 0xed, 0x55, 0xfc, 0x5c, 0x73, - 0x19, 0x56, 0x45, 0x89, 0xa3, 0x65, 0x58, 0xbd, 0x0f, 0x6b, 0x09, 0x1c, 0xe4, 0xd6, 0xce, 0xa9, - 0xc3, 0x55, 0xa6, 0xfd, 0xb2, 0x86, 0xdd, 0x53, 0x65, 0x9b, 0x45, 0x28, 0x04, 0x03, 0x6f, 0xc2, - 0x8d, 0x55, 0x58, 0x4e, 0xae, 0xaa, 0xbc, 0x26, 0x7e, 0x2f, 0x03, 0x2d, 0x19, 0x1f, 0xe1, 0xb8, - 0x67, 0xbb, 0x4e, 0x10, 0x7a, 0x7e, 0xf4, 0x1a, 0xdd, 0x5d, 0x80, 0x20, 0xb4, 0x7d, 0xa9, 0x6d, - 0xca, 0xdc, 0x72, 0x84, 0xa0, 0x26, 0x79, 0x1b, 0x4a, 0xdc, 0x1d, 0x52, 0x21, 0x51, 0x43, 0x91, - 0xbb, 0x43, 0xa5, 0x87, 0xce, 0xc9, 0xdf, 0xb5, 0xa4, 0x7a, 0x21, 0x53, 0x3d, 0xc5, 0xea, 0xf0, - 0x0b, 0xbc, 0x78, 0xf3, 0x51, 0xaa, 0xe7, 0xbe, 0x7d, 0x85, 0xd1, 0x86, 0x81, 0xf1, 0x4f, 0xb2, - 0xd0, 0x88, 0xc7, 0x47, 0x79, 0xe2, 0x2f, 0xce, 0x78, 0xbf, 0x2f, 0xc9, 0xc1, 0x11, 0xf2, 0xbb, - 0x66, 0x78, 0x2c, 0xd1, 0xe1, 0xec, 0xba, 0xcc, 0x80, 0x8a, 0xc2, 0xf0, 0xa6, 0xa1, 0xf6, 0x28, - 0x54, 0x99, 0x50, 0x0e, 0xa7, 0xa1, 0x50, 0xb8, 0x84, 0xe6, 0xe9, 0xb8, 0x52, 0xe5, 0x29, 0xd8, - 0xe3, 0xb0, 0x8b, 0x6f, 0x4d, 0x0b, 0xb0, 0xa8, 0x46, 0x1b, 0x29, 0xb0, 0x04, 0x7e, 0x93, 0xe4, - 0x6c, 0xda, 0x39, 0x94, 0xb1, 0x75, 0x21, 0x94, 0x9e, 0xdd, 0x8c, 0x84, 0xd0, 0xd7, 0xa1, 0x42, - 0x8d, 0xc7, 0x09, 0x75, 0x79, 0xb3, 0x8c, 0x3d, 0x60, 0xb9, 0x34, 0x02, 0x79, 0xd3, 0x84, 0xea, - 0x0b, 0xd4, 0x15, 0x86, 0x1f, 0xfc, 0x83, 0x0c, 0xdc, 0x4e, 0xd9, 0x36, 0x79, 0xca, 0xb7, 0x60, - 0xf1, 0x34, 0x2a, 0x54, 0xab, 0x4b, 0x47, 0x7d, 0x55, 0xb1, 0xd5, 0xe4, 0x9a, 0x9a, 0xcd, 0xd3, - 0x24, 0x20, 0x56, 0xba, 0x68, 0x07, 0x13, 0x39, 0x93, 0xa8, 0x74, 0xd1, 0x36, 0x92, 0xbe, 0x73, - 0x04, 0xeb, 0x9d, 0x2b, 0xc1, 0x31, 0xb6, 0xf4, 0xc7, 0xd2, 0x15, 0x19, 0x25, 0x0d, 0xcc, 0x99, - 0x57, 0x32, 0x30, 0x0f, 0x29, 0x35, 0x2c, 0x6a, 0xeb, 0xe7, 0x69, 0x04, 0x2f, 0x50, 0x51, 0x87, - 0x1e, 0x7b, 0x57, 0x79, 0x9b, 0x83, 0xe8, 0x91, 0x77, 0x23, 0x80, 0xc6, 0xfe, 0x74, 0x14, 0x3a, - 0xf1, 0xbb, 0xef, 0xec, 0xdb, 0xb2, 0x0e, 0xf6, 0xa3, 0x56, 0x2d, 0xb5, 0x23, 0x88, 0x3a, 0xc2, - 0xc5, 0x1a, 0x8b, 0x86, 0xac, 0xf9, 0xfe, 0x1a, 0xe3, 0x64, 0x0f, 0xc6, 0x6d, 0x58, 0x8b, 0xbf, - 0x68, 0xd9, 0xd4, 0x55, 0xf3, 0x2f, 0x33, 0x14, 0xda, 0x9c, 0x7c, 0x83, 0x9e, 0x75, 0x60, 0x29, - 0x70, 0xdc, 0xb3, 0x11, 0xd7, 0x9b, 0x0f, 0xe4, 0x22, 0xac, 0x24, 0xc7, 0x26, 0xdf, 0xa9, 0x37, - 0x17, 0xa9, 0x46, 0xdc, 0x5a, 0xc0, 0x36, 0x6f, 0x1a, 0x64, 0x4c, 0x16, 0x33, 0xab, 0x31, 0x3f, - 0xf8, 0x2e, 0xd4, 0x93, 0x1d, 0xb1, 0xef, 0xc8, 0xb4, 0xc8, 0x78, 0x54, 0xb9, 0x99, 0x0c, 0xb7, - 0x98, 0x20, 0x2a, 0xf1, 0xda, 0x07, 0xc6, 0x3f, 0xca, 0x40, 0xcb, 0xe4, 0x82, 0x72, 0xb5, 0x51, - 0x2a, 0x9a, 0xf9, 0x70, 0xae, 0xd5, 0x9b, 0xe7, 0xaa, 0xb2, 0x2d, 0xd5, 0x88, 0xbe, 0x71, 0xe3, - 0x66, 0xec, 0xde, 0x9a, 0x9b, 0xd1, 0x66, 0x09, 0x16, 0x08, 0xc5, 0x58, 0x83, 0x15, 0x39, 0x1e, - 0x35, 0x96, 0xd8, 0x7b, 0x98, 0xe8, 0x31, 0xe1, 0x3d, 0x5c, 0x87, 0x16, 0x3d, 0x2a, 0xa8, 0x4f, - 0x42, 0x56, 0xdc, 0x06, 0xb6, 0x6f, 0x0f, 0x6c, 0xdf, 0xf3, 0xdc, 0x23, 0xee, 0xcb, 0x40, 0x51, - 0x94, 0x30, 0xd1, 0xb9, 0xa6, 0x44, 0x61, 0xfa, 0x52, 0x4f, 0xe1, 0x79, 0xae, 0x8a, 0x8b, 0xa1, - 0x2f, 0xc3, 0x84, 0xa5, 0x4d, 0xfb, 0x39, 0x57, 0x2d, 0xa9, 0x25, 0xfa, 0x08, 0x2a, 0x93, 0xa8, - 0x51, 0xb5, 0xee, 0x2a, 0x77, 0x7a, 0xbe, 0x5b, 0x53, 0xc7, 0x36, 0x9e, 0xc0, 0x72, 0xb2, 0x4d, - 0xc9, 0x3a, 0xd6, 0xa1, 0x34, 0x96, 0x30, 0x39, 0xba, 0xe8, 0xdb, 0xf8, 0x69, 0x09, 0x8a, 0x52, - 0x9f, 0x63, 0x1b, 0x90, 0x1f, 0xa8, 0xd8, 0xa4, 0xf8, 0x49, 0x0e, 0x59, 0xaa, 0xfe, 0xdf, 0xc2, - 0x08, 0x25, 0x81, 0xc7, 0x3e, 0x82, 0x7a, 0xd2, 0x2b, 0x3a, 0x93, 0x98, 0x99, 0x74, 0x67, 0xd6, - 0x06, 0x33, 0xfe, 0xaf, 0x72, 0x7c, 0x39, 0x92, 0xcc, 0x50, 0x3a, 0xd7, 0x6e, 0x4f, 0xcf, 0x15, - 0xf2, 0x76, 0x70, 0x6e, 0x5b, 0x4f, 0xde, 0xff, 0x40, 0x66, 0x66, 0x56, 0x10, 0xd8, 0x3b, 0xb7, - 0x9f, 0xbc, 0xff, 0xc1, 0xac, 0x24, 0x4d, 0xc9, 0x79, 0xba, 0x24, 0xbd, 0x0c, 0x05, 0x7a, 0xf3, - 0x8d, 0x82, 0x4c, 0xe8, 0x83, 0x3d, 0x86, 0x65, 0xa9, 0xb6, 0x5a, 0x32, 0x1c, 0x98, 0xb8, 0x60, - 0x89, 0xb2, 0x81, 0x64, 0x59, 0x0f, 0x8b, 0xc8, 0x36, 0xb4, 0x0a, 0x0b, 0xe7, 0xf1, 0x03, 0x7e, - 0x35, 0x53, 0x7e, 0x19, 0x7f, 0x5a, 0x80, 0x8a, 0xb6, 0x28, 0xac, 0x0a, 0x25, 0xb3, 0xd3, 0xeb, - 0x98, 0x9f, 0x74, 0xb6, 0x9b, 0xb7, 0xd8, 0x03, 0x78, 0xab, 0x7b, 0xb0, 0x75, 0x68, 0x9a, 0x9d, - 0xad, 0xbe, 0x75, 0x68, 0x5a, 0xea, 0x61, 0x98, 0xa3, 0xf6, 0x67, 0xfb, 0x9d, 0x83, 0xbe, 0xb5, - 0xdd, 0xe9, 0xb7, 0xbb, 0x7b, 0xbd, 0x66, 0x86, 0xbd, 0x06, 0xad, 0x18, 0x53, 0x15, 0xb7, 0xf7, - 0x0f, 0x8f, 0x0f, 0xfa, 0xcd, 0x2c, 0xbb, 0x07, 0x77, 0x76, 0xba, 0x07, 0xed, 0x3d, 0x2b, 0xc6, - 0xd9, 0xda, 0xeb, 0x7f, 0x62, 0x75, 0x7e, 0xfd, 0xa8, 0x6b, 0x7e, 0xd6, 0xcc, 0xa5, 0x21, 0x08, - 0x65, 0x5c, 0xb5, 0x90, 0x67, 0xb7, 0x61, 0x85, 0x10, 0xa8, 0x8a, 0xd5, 0x3f, 0x3c, 0xb4, 0x7a, - 0x87, 0x87, 0x07, 0xcd, 0x02, 0x5b, 0x84, 0x5a, 0xf7, 0xe0, 0x93, 0xf6, 0x5e, 0x77, 0xdb, 0x32, - 0x3b, 0xed, 0xbd, 0xfd, 0xe6, 0x02, 0x5b, 0x82, 0xc6, 0x2c, 0x5e, 0x51, 0x34, 0xa1, 0xf0, 0x0e, - 0x0f, 0xba, 0x87, 0x07, 0xd6, 0x27, 0x1d, 0xb3, 0xd7, 0x3d, 0x3c, 0x68, 0x96, 0xd8, 0x2a, 0xb0, - 0x64, 0xd1, 0xee, 0x7e, 0x7b, 0xab, 0x59, 0x66, 0x2b, 0xb0, 0x98, 0x84, 0x3f, 0xeb, 0x7c, 0xd6, - 0x04, 0xd6, 0x82, 0x65, 0x1a, 0x98, 0xb5, 0xd9, 0xd9, 0x3b, 0xfc, 0xd4, 0xda, 0xef, 0x1e, 0x74, - 0xf7, 0x8f, 0xf7, 0x9b, 0x15, 0x7c, 0xaa, 0xaa, 0xd3, 0xb1, 0xba, 0x07, 0xbd, 0xe3, 0x9d, 0x9d, - 0xee, 0x56, 0xb7, 0x73, 0xd0, 0x6f, 0x56, 0xa9, 0xe7, 0xb4, 0x89, 0xd7, 0x44, 0x05, 0x99, 0x33, - 0x60, 0x6d, 0x77, 0x7b, 0xed, 0xcd, 0xbd, 0xce, 0x76, 0xb3, 0xce, 0xee, 0xc2, 0xed, 0x7e, 0x67, - 0xff, 0xe8, 0xd0, 0x6c, 0x9b, 0x9f, 0xa9, 0x9c, 0x02, 0x6b, 0xa7, 0xdd, 0xdd, 0x3b, 0x36, 0x3b, - 0xcd, 0x06, 0x7b, 0x03, 0xee, 0x9a, 0x9d, 0x8f, 0x8f, 0xbb, 0x66, 0x67, 0xdb, 0x3a, 0x38, 0xdc, - 0xee, 0x58, 0x3b, 0x9d, 0x76, 0xff, 0xd8, 0xec, 0x58, 0xfb, 0xdd, 0x5e, 0xaf, 0x7b, 0xf0, 0xb4, - 0xd9, 0x64, 0x6f, 0xc1, 0xfd, 0x08, 0x25, 0x6a, 0x60, 0x06, 0x6b, 0x51, 0xcc, 0x4f, 0x6d, 0xe9, - 0x41, 0xe7, 0xd7, 0xfb, 0xd6, 0x51, 0xa7, 0x63, 0x36, 0x19, 0x5b, 0x87, 0xd5, 0xb8, 0x7b, 0xea, - 0x40, 0xf6, 0xbd, 0x24, 0xca, 0x8e, 0x3a, 0xe6, 0x7e, 0xfb, 0x40, 0x6c, 0x70, 0xa2, 0x6c, 0x59, - 0x0c, 0x3b, 0x2e, 0x9b, 0x1d, 0xf6, 0x0a, 0x63, 0x50, 0xd7, 0x76, 0x65, 0xa7, 0x6d, 0x36, 0x57, - 0x59, 0x03, 0x2a, 0xfb, 0x47, 0x47, 0x56, 0xbf, 0xbb, 0xdf, 0x39, 0x3c, 0xee, 0x37, 0xd7, 0xd8, - 0x0a, 0x34, 0xbb, 0x07, 0xfd, 0x8e, 0x29, 0xf6, 0x5a, 0x55, 0xfd, 0xdf, 0x45, 0xb6, 0x0c, 0x0d, - 0x35, 0x52, 0x05, 0xfd, 0xcb, 0x22, 0x5b, 0x03, 0x76, 0x7c, 0x60, 0x76, 0xda, 0xdb, 0x62, 0xe1, - 0xa2, 0x82, 0xff, 0x53, 0x94, 0x1e, 0x92, 0x9f, 0xe5, 0xa2, 0xcb, 0x3a, 0x0e, 0x39, 0x48, 0x3e, - 0xe7, 0x5a, 0xd5, 0x9e, 0x61, 0x7d, 0xd9, 0x43, 0xeb, 0x9a, 0x6a, 0x95, 0x9b, 0x53, 0xad, 0xe6, - 0x74, 0xf7, 0x9a, 0x2e, 0xfb, 0xbd, 0x09, 0xb5, 0x31, 0x3d, 0xed, 0x2a, 0x9f, 0x70, 0x04, 0x19, - 0x7f, 0x43, 0x40, 0x7a, 0xbf, 0x71, 0xee, 0xa5, 0xf1, 0xc2, 0xfc, 0x4b, 0xe3, 0x69, 0xf2, 0xfd, - 0x42, 0x9a, 0x7c, 0xff, 0x10, 0x16, 0x89, 0x35, 0x39, 0xae, 0x33, 0x56, 0x5a, 0x33, 0x49, 0x81, - 0x0d, 0x64, 0x51, 0x04, 0x57, 0xea, 0x84, 0x52, 0x39, 0x24, 0x0b, 0x29, 0x4a, 0x6d, 0x23, 0xa1, - 0x69, 0x10, 0xe7, 0x88, 0x34, 0x8d, 0xa8, 0x07, 0xfb, 0x2a, 0xee, 0xa1, 0xa2, 0xf5, 0x40, 0x70, - 0xec, 0xe1, 0x21, 0x2c, 0xf2, 0xab, 0xd0, 0xb7, 0x2d, 0x6f, 0x62, 0x7f, 0x3e, 0x45, 0x17, 0xae, - 0x8d, 0x3a, 0x7c, 0xd5, 0x6c, 0x60, 0xc1, 0x21, 0xc2, 0xb7, 0xed, 0xd0, 0x7e, 0xf8, 0x05, 0x54, - 0xb4, 0x67, 0x7f, 0xd9, 0x1a, 0x2c, 0x7d, 0xda, 0xed, 0x1f, 0x74, 0x7a, 0x3d, 0xeb, 0xe8, 0x78, - 0xf3, 0x59, 0xe7, 0x33, 0x6b, 0xb7, 0xdd, 0xdb, 0x6d, 0xde, 0x12, 0x87, 0xf6, 0xa0, 0xd3, 0xeb, - 0x77, 0xb6, 0x13, 0xf0, 0x0c, 0x7b, 0x1d, 0xd6, 0x8f, 0x0f, 0x8e, 0x7b, 0x9d, 0x6d, 0x2b, 0xad, - 0x5e, 0x56, 0x50, 0xa9, 0x2c, 0x4f, 0xa9, 0x9e, 0x7b, 0xf8, 0x7d, 0xa8, 0x27, 0xdf, 0xa2, 0x64, - 0x00, 0x0b, 0x7b, 0x9d, 0xa7, 0xed, 0xad, 0xcf, 0xe8, 0x31, 0xbb, 0x5e, 0xbf, 0xdd, 0xef, 0x6e, - 0x59, 0xf2, 0xf1, 0x3a, 0xc1, 0x11, 0x32, 0xac, 0x02, 0xc5, 0xf6, 0xc1, 0xd6, 0xee, 0xa1, 0xd9, - 0x6b, 0x66, 0x1f, 0x7e, 0x04, 0xcd, 0x59, 0x7f, 0x54, 0xc2, 0x81, 0xf7, 0x22, 0x4f, 0xdf, 0xc3, - 0x7f, 0x9b, 0x03, 0x88, 0x13, 0x06, 0x04, 0xab, 0xd9, 0x6e, 0xf7, 0xdb, 0x7b, 0x87, 0x62, 0x1a, - 0xe6, 0x61, 0x5f, 0x70, 0x10, 0xb3, 0xf3, 0x71, 0xf3, 0x56, 0x6a, 0xc9, 0xe1, 0x51, 0xbf, 0x99, - 0x11, 0x2b, 0xd6, 0x3d, 0xe8, 0xf6, 0xbb, 0xed, 0x3d, 0xcb, 0x3c, 0x3c, 0xee, 0x1e, 0x3c, 0xa5, - 0x57, 0xba, 0x90, 0xcb, 0x1e, 0x1f, 0xed, 0x98, 0x87, 0x07, 0x7d, 0xab, 0xb7, 0x7b, 0xdc, 0xdf, - 0xc6, 0x37, 0xbe, 0xb6, 0xcc, 0xee, 0x11, 0xb5, 0x99, 0x7f, 0x11, 0x82, 0x68, 0xba, 0x20, 0xd6, - 0xfc, 0xe9, 0x61, 0xaf, 0xd7, 0x3d, 0xb2, 0x3e, 0x3e, 0xee, 0x98, 0xdd, 0x4e, 0x0f, 0x2b, 0x2e, - 0xa4, 0xc0, 0x05, 0x7e, 0x51, 0xf0, 0xe6, 0xfe, 0xde, 0x27, 0x92, 0x79, 0x0a, 0xd4, 0x52, 0x12, - 0x24, 0xb0, 0xca, 0x82, 0xa7, 0x08, 0xee, 0x93, 0xd2, 0x32, 0xdc, 0x50, 0x26, 0xea, 0x55, 0x04, - 0x5f, 0x9d, 0xdb, 0x0c, 0xac, 0x56, 0x4d, 0x2f, 0x12, 0xb5, 0x90, 0xe5, 0x46, 0x17, 0xd4, 0xf6, - 0xb6, 0x89, 0x15, 0xea, 0x73, 0x50, 0x81, 0xdb, 0x10, 0x1b, 0x25, 0xd8, 0x93, 0x40, 0x69, 0xaa, - 0x0f, 0x51, 0xb2, 0xf8, 0xe4, 0x77, 0x72, 0x50, 0xa7, 0xe4, 0x2d, 0xfa, 0xd5, 0x25, 0xee, 0xb3, - 0x7d, 0x28, 0xca, 0x9f, 0xef, 0x62, 0x2b, 0xd1, 0x03, 0x4a, 0xfa, 0x0f, 0x86, 0xad, 0xaf, 0xce, - 0x82, 0xa5, 0x38, 0xb6, 0xf4, 0xb7, 0xfe, 0xe4, 0x7f, 0xfd, 0xe3, 0x6c, 0x8d, 0x55, 0x1e, 0x5d, - 0xbc, 0xf7, 0xe8, 0x8c, 0xbb, 0x81, 0x68, 0xe3, 0xaf, 0x03, 0xc4, 0x3f, 0x4a, 0xc5, 0x5a, 0x91, - 0x13, 0x6a, 0xe6, 0x17, 0xbb, 0xd6, 0x6f, 0xa7, 0x94, 0xc8, 0x76, 0x6f, 0x63, 0xbb, 0x4b, 0x46, - 0x5d, 0xb4, 0xeb, 0xb8, 0x4e, 0x48, 0x3f, 0x50, 0xf5, 0x61, 0xe6, 0x21, 0x1b, 0x42, 0x55, 0xff, - 0xb9, 0x28, 0xa6, 0x24, 0xa5, 0x94, 0x1f, 0xbc, 0x5a, 0xbf, 0x93, 0x5a, 0xa6, 0x64, 0x50, 0xec, - 0x63, 0xc5, 0x68, 0x8a, 0x3e, 0xa6, 0x88, 0x11, 0xf7, 0x32, 0x22, 0xa9, 0x3c, 0xfe, 0x55, 0x28, - 0xf6, 0x9a, 0x26, 0x57, 0xcd, 0xfd, 0x26, 0xd5, 0xfa, 0xdd, 0x1b, 0x4a, 0x65, 0x5f, 0x77, 0xb1, - 0xaf, 0x35, 0x83, 0x89, 0xbe, 0x06, 0x88, 0xa3, 0x7e, 0x93, 0xea, 0xc3, 0xcc, 0xc3, 0x27, 0x7f, - 0xf1, 0x00, 0xca, 0x51, 0x30, 0x27, 0xfb, 0x2d, 0xa8, 0x25, 0xb2, 0xeb, 0x98, 0x9a, 0x46, 0x5a, - 0x32, 0xde, 0xfa, 0x6b, 0xe9, 0x85, 0xb2, 0xe3, 0xd7, 0xb1, 0xe3, 0x16, 0x5b, 0x15, 0x1d, 0xcb, - 0xec, 0xb5, 0x47, 0x98, 0x0d, 0x4b, 0xcf, 0x51, 0x3d, 0xd7, 0xb4, 0x0f, 0xea, 0xec, 0xb5, 0x59, - 0x8d, 0x20, 0xd1, 0xdb, 0xdd, 0x1b, 0x4a, 0x65, 0x77, 0xaf, 0x61, 0x77, 0xab, 0x6c, 0x59, 0xef, - 0x4e, 0x85, 0x5e, 0x32, 0x8e, 0x4f, 0xc0, 0xe9, 0x3f, 0x9a, 0xc4, 0xee, 0xc6, 0x0f, 0x76, 0xa5, - 0xfc, 0x98, 0x52, 0x44, 0x22, 0xf3, 0xbf, 0xa8, 0x64, 0xb4, 0xb0, 0x2b, 0xc6, 0x70, 0xfb, 0xf4, - 0xdf, 0x4c, 0x62, 0x27, 0x50, 0xd1, 0x7e, 0x67, 0x80, 0xdd, 0xbe, 0xf1, 0x37, 0x11, 0xd6, 0xd7, - 0xd3, 0x8a, 0xd2, 0xa6, 0xa2, 0xb7, 0xff, 0xe8, 0x94, 0x73, 0xf6, 0x1b, 0x50, 0x8e, 0x5e, 0xaf, - 0x67, 0x6b, 0xda, 0xaf, 0x09, 0xe8, 0xaf, 0xed, 0xaf, 0xb7, 0xe6, 0x0b, 0xd2, 0x88, 0x4f, 0x6f, - 0x5d, 0x10, 0xdf, 0xa7, 0x50, 0xd1, 0x5e, 0xa8, 0x8f, 0x26, 0x30, 0xff, 0x0a, 0x7e, 0x34, 0x81, - 0x94, 0x07, 0xed, 0x8d, 0x45, 0xec, 0xa2, 0xc2, 0xca, 0x48, 0xdf, 0xe1, 0x95, 0x17, 0xb0, 0x3d, - 0x58, 0x91, 0x9a, 0xd6, 0x09, 0xff, 0x32, 0xdb, 0x90, 0xf2, 0x3b, 0x55, 0x8f, 0x33, 0xec, 0x23, - 0x28, 0xa9, 0x1f, 0x22, 0x60, 0xab, 0xe9, 0x3f, 0xa8, 0xb0, 0xbe, 0x36, 0x07, 0x97, 0x6a, 0xd1, - 0x67, 0x00, 0xf1, 0x73, 0xf8, 0x11, 0x93, 0x98, 0x7b, 0x5e, 0x3f, 0xa2, 0x80, 0xf9, 0xb7, 0xf3, - 0x8d, 0x55, 0x9c, 0x60, 0x93, 0x21, 0x93, 0x70, 0xf9, 0xa5, 0x7a, 0xa7, 0xf3, 0x47, 0x50, 0xd1, - 0x5e, 0xc4, 0x8f, 0x96, 0x6f, 0xfe, 0x35, 0xfd, 0x68, 0xf9, 0x52, 0x1e, 0xd0, 0x37, 0xd6, 0xb1, - 0xf5, 0x65, 0xa3, 0x21, 0x5a, 0x17, 0xa2, 0x96, 0x14, 0x79, 0xc4, 0x06, 0x9d, 0x43, 0x2d, 0xf1, - 0xec, 0x7d, 0x74, 0x42, 0xd3, 0x1e, 0xd5, 0x8f, 0x4e, 0x68, 0xea, 0x4b, 0xf9, 0x8a, 0xce, 0x8c, - 0x45, 0xd1, 0xcf, 0x05, 0xa2, 0x68, 0x3d, 0xfd, 0x10, 0x2a, 0xda, 0x13, 0xf6, 0xd1, 0x5c, 0xe6, - 0x5f, 0xcb, 0x8f, 0xe6, 0x92, 0xf6, 0xe2, 0xfd, 0x32, 0xf6, 0x51, 0x37, 0x90, 0x14, 0xf0, 0xa5, - 0x41, 0xd1, 0xf6, 0x6f, 0x41, 0x3d, 0xf9, 0xaa, 0x7d, 0x74, 0xf6, 0x53, 0x9f, 0xc7, 0x8f, 0xce, - 0xfe, 0x0d, 0x4f, 0xe1, 0x4b, 0x92, 0x7e, 0xb8, 0x14, 0x75, 0xf2, 0xe8, 0x27, 0x32, 0x2d, 0xe5, - 0x0b, 0xf6, 0xb1, 0x60, 0x70, 0xf2, 0xa1, 0x4b, 0xb6, 0xa6, 0x51, 0xad, 0xfe, 0x62, 0x66, 0x74, - 0x5e, 0xe6, 0xde, 0xc4, 0x4c, 0x12, 0x33, 0x36, 0xce, 0x9e, 0xc2, 0x52, 0x44, 0xcc, 0xd1, 0xcb, - 0x95, 0x41, 0x34, 0x87, 0xd4, 0xf7, 0x31, 0xd7, 0x9b, 0xb3, 0xa5, 0x8f, 0x33, 0x74, 0xfd, 0xe1, - 0x7b, 0x81, 0xda, 0xf5, 0xa7, 0x3f, 0x5e, 0xa9, 0x5d, 0x7f, 0x89, 0x67, 0x05, 0x67, 0xaf, 0xbf, - 0xd0, 0x11, 0x6d, 0xb8, 0xd0, 0x98, 0x7d, 0x47, 0xf2, 0xee, 0x4d, 0x69, 0xff, 0xd4, 0xfc, 0xeb, - 0x2f, 0x7e, 0x15, 0x20, 0xc9, 0x8a, 0x14, 0x37, 0x7d, 0x24, 0x83, 0x4f, 0xd8, 0x6f, 0x42, 0x55, - 0x7f, 0x52, 0x9b, 0xe9, 0x3c, 0x61, 0xb6, 0xa7, 0x3b, 0xa9, 0x65, 0x49, 0x2a, 0x61, 0x55, 0xbd, - 0x1b, 0xf6, 0x09, 0xac, 0x46, 0xcb, 0xac, 0xe7, 0xad, 0x07, 0xec, 0x5e, 0x4a, 0x36, 0x7b, 0x62, - 0xb1, 0x6f, 0xdf, 0x98, 0xee, 0xfe, 0x38, 0x23, 0xa8, 0x2f, 0xf9, 0xb6, 0x6f, 0x7c, 0xf3, 0xa4, - 0x3d, 0x69, 0x1c, 0xdf, 0x3c, 0xa9, 0x0f, 0x02, 0x2b, 0xea, 0x63, 0x4b, 0x89, 0x35, 0xa2, 0xb0, - 0x5c, 0xf6, 0x43, 0x68, 0x68, 0x49, 0xf9, 0xbd, 0x6b, 0x77, 0x10, 0x9d, 0xa4, 0xf9, 0xc7, 0xe9, - 0xd6, 0xd3, 0x6c, 0x93, 0xc6, 0x1a, 0xb6, 0xbf, 0x68, 0x24, 0x16, 0x47, 0x9c, 0xa2, 0x2d, 0xa8, - 0xe8, 0x09, 0xff, 0x2f, 0x68, 0x77, 0x4d, 0x2b, 0xd2, 0xdf, 0x41, 0x7b, 0x9c, 0x61, 0x7b, 0xd0, - 0x9c, 0x7d, 0xb6, 0x29, 0xe2, 0x29, 0x69, 0x4f, 0x4d, 0xad, 0xcf, 0x14, 0x26, 0x1e, 0x7b, 0x62, - 0x47, 0x94, 0xd8, 0x11, 0xfd, 0xa8, 0x93, 0xe7, 0xcf, 0xde, 0xea, 0xc9, 0x1f, 0x7b, 0x8a, 0x5a, - 0x4b, 0xfb, 0x99, 0xaf, 0x07, 0x99, 0xc7, 0x19, 0xf6, 0xbb, 0x19, 0xa8, 0x26, 0x9e, 0x4a, 0x49, - 0x84, 0xce, 0xcf, 0xcc, 0xb3, 0xa5, 0x97, 0xe9, 0x13, 0x35, 0x4c, 0x5c, 0xc4, 0xbd, 0x87, 0x3f, - 0x48, 0x6c, 0xd2, 0x4f, 0x12, 0xae, 0xbd, 0x8d, 0xd9, 0x5f, 0x7d, 0xfa, 0x62, 0x16, 0x41, 0x7f, - 0x73, 0xf0, 0x8b, 0xc7, 0x19, 0xf6, 0xef, 0x33, 0x50, 0x4f, 0xfa, 0xec, 0xa3, 0xe9, 0xa6, 0x46, - 0x07, 0x44, 0xa4, 0x74, 0x83, 0xa3, 0xff, 0x87, 0x38, 0xca, 0xfe, 0x43, 0x33, 0x31, 0x4a, 0xf9, - 0x2a, 0xf5, 0x2f, 0x36, 0x5a, 0xf6, 0x21, 0xfd, 0xc8, 0xa2, 0x0a, 0x65, 0x62, 0xf3, 0x3f, 0xca, - 0x17, 0x91, 0x9f, 0xfe, 0x13, 0x76, 0xb8, 0x09, 0x3f, 0xa2, 0x5f, 0x37, 0x52, 0x91, 0x31, 0x82, - 0x8a, 0x5f, 0xb5, 0xbe, 0xf1, 0x16, 0xce, 0xe9, 0x75, 0xe3, 0x76, 0x62, 0x4e, 0xb3, 0x82, 0x47, - 0x9b, 0x46, 0x27, 0x7f, 0x81, 0x2e, 0xbe, 0x39, 0xe7, 0x7e, 0x95, 0xee, 0xe6, 0x41, 0x8e, 0x69, - 0x90, 0x12, 0x3d, 0x71, 0xd4, 0x5e, 0xb1, 0x19, 0xe3, 0x21, 0x8e, 0xf5, 0x2d, 0xe3, 0xde, 0x8d, - 0x63, 0x7d, 0x84, 0xfe, 0x77, 0x31, 0xe2, 0x23, 0x80, 0x38, 0xd4, 0x90, 0xcd, 0x04, 0xbc, 0x45, - 0x0c, 0x68, 0x3e, 0x1a, 0x31, 0x79, 0x9e, 0x55, 0x5c, 0x9c, 0x68, 0xf1, 0x37, 0x88, 0x9d, 0x46, - 0xa1, 0x78, 0xba, 0xf4, 0x95, 0x8c, 0x0a, 0x4c, 0x48, 0x5f, 0xb3, 0xed, 0x27, 0x98, 0x69, 0x14, - 0x77, 0x77, 0x0c, 0xb5, 0x3d, 0xcf, 0x7b, 0x3e, 0x9d, 0x44, 0xe1, 0xed, 0xc9, 0xa0, 0x98, 0x5d, - 0x3b, 0x38, 0x5f, 0x9f, 0x99, 0x85, 0x71, 0x1f, 0x9b, 0x5a, 0x67, 0x2d, 0xad, 0xa9, 0x47, 0x3f, - 0x89, 0xe3, 0x1b, 0xbf, 0x60, 0x36, 0x2c, 0x46, 0x3c, 0x3a, 0x8e, 0x21, 0x4c, 0x36, 0x93, 0xe0, - 0xcc, 0xb3, 0x5d, 0x24, 0xd4, 0x04, 0x35, 0xda, 0x47, 0x81, 0x6a, 0xf3, 0x71, 0x86, 0x1d, 0x41, - 0x75, 0x9b, 0x0f, 0x30, 0x51, 0x1f, 0x43, 0x4b, 0x96, 0x12, 0x61, 0x0a, 0x14, 0x93, 0xb2, 0x5e, - 0x4b, 0x00, 0x93, 0xf7, 0xd6, 0xc4, 0xbe, 0xf6, 0xf9, 0xe7, 0x8f, 0x7e, 0x22, 0x83, 0x56, 0xbe, - 0x50, 0xf7, 0x96, 0x0a, 0xea, 0x49, 0xdc, 0x5b, 0x33, 0x51, 0x40, 0x89, 0x7b, 0x6b, 0x2e, 0x0a, - 0x28, 0xb1, 0xd4, 0x2a, 0xa8, 0x88, 0x8d, 0x60, 0x71, 0x2e, 0x70, 0x28, 0xba, 0xb2, 0x6e, 0x0a, - 0x37, 0x5a, 0xbf, 0x7f, 0x33, 0x42, 0xb2, 0xb7, 0x87, 0xc9, 0xde, 0x7a, 0x50, 0xa3, 0x67, 0x10, - 0x4f, 0x38, 0xa5, 0xec, 0xcd, 0xbc, 0x77, 0xa3, 0xe7, 0x03, 0xce, 0x5e, 0x30, 0x58, 0x96, 0x94, - 0x70, 0x30, 0x57, 0x8e, 0xfd, 0x06, 0x54, 0x9e, 0xf2, 0x50, 0xe5, 0xe8, 0x45, 0x32, 0xf6, 0x4c, - 0xd2, 0xde, 0x7a, 0x4a, 0x8a, 0x5f, 0x92, 0x66, 0xb0, 0xb5, 0x47, 0x7c, 0x78, 0xc6, 0x89, 0x39, - 0x59, 0xce, 0xf0, 0x0b, 0xf6, 0xeb, 0xd8, 0x78, 0x94, 0x1a, 0xbd, 0xaa, 0x25, 0x61, 0xe9, 0x8d, - 0x37, 0x66, 0xe0, 0x69, 0x2d, 0xbb, 0xde, 0x90, 0x6b, 0xb2, 0x9e, 0x0b, 0x15, 0xed, 0x09, 0x85, - 0xe8, 0x00, 0xcd, 0x3f, 0x99, 0x11, 0x1d, 0xa0, 0x94, 0x17, 0x17, 0x8c, 0x07, 0xd8, 0x8f, 0xc1, - 0xee, 0xc7, 0xfd, 0xd0, 0x2b, 0x0b, 0x71, 0x4f, 0x8f, 0x7e, 0x62, 0x8f, 0xc3, 0x2f, 0xd8, 0xa7, - 0xf8, 0xd8, 0xb8, 0x9e, 0x83, 0x18, 0x2b, 0x0d, 0xb3, 0xe9, 0x8a, 0xd1, 0x62, 0x69, 0x45, 0x49, - 0x45, 0x82, 0xba, 0x42, 0x49, 0xee, 0x7d, 0x80, 0x5e, 0xe8, 0x4d, 0xb6, 0x6d, 0x3e, 0xf6, 0xdc, - 0x98, 0xd7, 0xc6, 0x59, 0x71, 0x31, 0xff, 0xd2, 0x52, 0xe3, 0xd8, 0xa7, 0x9a, 0x96, 0x95, 0x48, - 0xe3, 0x54, 0xc4, 0x75, 0x63, 0xe2, 0x5c, 0xb4, 0x20, 0x29, 0xc9, 0x73, 0x8f, 0x33, 0xac, 0x0d, - 0x10, 0x47, 0x8e, 0x45, 0x3a, 0xd3, 0x5c, 0x50, 0x5a, 0xc4, 0xf6, 0x52, 0xc2, 0xcc, 0x8e, 0xa0, - 0x1c, 0x87, 0xdc, 0xac, 0xc5, 0x2f, 0xc2, 0x24, 0x02, 0x74, 0xa2, 0x1b, 0x7c, 0x2e, 0xdc, 0xc5, - 0x68, 0xe2, 0x52, 0x01, 0x2b, 0x89, 0xa5, 0x3a, 0xe5, 0x3c, 0x60, 0x0e, 0x2c, 0xd1, 0x00, 0x23, - 0x71, 0x09, 0xb3, 0xb9, 0xa2, 0x37, 0xe5, 0xe7, 0x23, 0x4f, 0xa2, 0xd3, 0x9c, 0x1a, 0x3f, 0x91, - 0x30, 0xfd, 0x08, 0x6a, 0xa5, 0x4c, 0x32, 0xc1, 0x9a, 0xc7, 0xb0, 0x38, 0xe7, 0xa2, 0x8f, 0x8e, - 0xf4, 0x4d, 0x31, 0x17, 0xd1, 0x91, 0xbe, 0xd1, 0xbb, 0x6f, 0xac, 0x60, 0x97, 0x0d, 0x03, 0x50, - 0xd5, 0xbb, 0x74, 0xc2, 0xc1, 0xb9, 0xe8, 0xee, 0xdf, 0x64, 0x60, 0x29, 0xc5, 0x09, 0xcf, 0xde, - 0x50, 0x56, 0x83, 0x1b, 0x1d, 0xf4, 0xeb, 0xa9, 0xce, 0x5a, 0xa3, 0x87, 0xfd, 0xec, 0xb3, 0x67, - 0x89, 0x8b, 0x8d, 0x7c, 0xa5, 0xf2, 0x64, 0xbe, 0x50, 0xa8, 0x48, 0x95, 0x28, 0x3e, 0x87, 0x35, - 0x1a, 0x48, 0x7b, 0x34, 0x9a, 0x71, 0x24, 0xbf, 0x3e, 0xf7, 0x23, 0xec, 0x09, 0xe7, 0xf8, 0xfa, - 0xcd, 0x3f, 0xd2, 0x7e, 0x83, 0x38, 0x4d, 0x43, 0x65, 0x53, 0x68, 0xce, 0x3a, 0x68, 0xd9, 0xcd, - 0x6d, 0xad, 0xdf, 0x4b, 0xe8, 0xbf, 0x29, 0x4e, 0xdd, 0xaf, 0x61, 0x67, 0xf7, 0x8c, 0xf5, 0xb4, - 0x75, 0x21, 0x95, 0x58, 0xec, 0xc7, 0xdf, 0x8c, 0xbc, 0xc9, 0x33, 0xf3, 0x54, 0x1d, 0xdc, 0xe4, - 0xfb, 0x8e, 0x34, 0xf0, 0x74, 0x67, 0xf4, 0xdb, 0xd8, 0xfd, 0x7d, 0xe3, 0x4e, 0x5a, 0xf7, 0x3e, - 0x55, 0x21, 0x5d, 0x7c, 0x6d, 0xf6, 0x5c, 0xab, 0x11, 0xdc, 0x4f, 0xdb, 0xef, 0x1b, 0x75, 0xa1, - 0x99, 0xb5, 0xbe, 0x85, 0xb2, 0x5d, 0x55, 0xf7, 0x1e, 0x47, 0xc7, 0x27, 0xc5, 0x4d, 0x1d, 0x1d, - 0x9f, 0x34, 0x77, 0x73, 0x52, 0xae, 0x51, 0x8e, 0xe6, 0x0f, 0x33, 0x0f, 0x37, 0xdf, 0xf9, 0xe1, - 0xd7, 0xce, 0x9c, 0xf0, 0x7c, 0x7a, 0xb2, 0x31, 0xf0, 0xc6, 0x8f, 0x46, 0xca, 0xda, 0x28, 0x53, - 0x9e, 0x1f, 0x8d, 0xdc, 0xe1, 0x23, 0x6c, 0xf6, 0x64, 0x61, 0xe2, 0x7b, 0xa1, 0xf7, 0xad, 0xff, - 0x17, 0x00, 0x00, 0xff, 0xff, 0x90, 0xab, 0x21, 0xed, 0x67, 0x82, 0x00, 0x00, + // 11345 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x24, 0x47, + 0x76, 0x18, 0x3c, 0x75, 0xeb, 0xaa, 0x3a, 0x75, 0xed, 0xe8, 0x5b, 0x4d, 0x0f, 0x87, 0x33, 0x4c, + 0x72, 0xc9, 0xd9, 0xe1, 0x6e, 0xcf, 0x70, 0x76, 0xc9, 0x5d, 0x91, 0x9f, 0x56, 0x5b, 0xdd, 0x5d, + 0x3d, 0x5d, 0x3b, 0x7d, 0x63, 0x56, 0x35, 0x29, 0xae, 0x3e, 0x39, 0x37, 0xbb, 0x2a, 0xba, 0x3b, + 0x35, 0x55, 0x99, 0xc5, 0xcc, 0xac, 0xbe, 0xec, 0x82, 0x7e, 0x30, 0x6c, 0xc1, 0x30, 0x6c, 0x03, + 0x82, 0x2d, 0x03, 0x96, 0x2d, 0xd8, 0xb0, 0x61, 0x18, 0x86, 0x01, 0x41, 0xc6, 0xca, 0x80, 0x1f, + 0xfc, 0xae, 0x17, 0x1b, 0x82, 0x21, 0xf9, 0xc5, 0x10, 0x04, 0xc8, 0x97, 0xf5, 0x9b, 0xa1, 0x9f, + 0x60, 0xc4, 0x39, 0x11, 0x99, 0x91, 0x55, 0xd9, 0x33, 0xc3, 0x5d, 0x7a, 0x5f, 0x66, 0x3a, 0x4f, + 0x9c, 0xb8, 0x9f, 0x38, 0x71, 0xae, 0x51, 0x50, 0xf6, 0x27, 0x83, 0x8d, 0x89, 0xef, 0x85, 0x1e, + 0x2b, 0x8c, 0x5c, 0x7f, 0x32, 0x58, 0x7f, 0xed, 0xcc, 0xf3, 0xce, 0x46, 0xfc, 0x91, 0x3d, 0x71, + 0x1e, 0xd9, 0xae, 0xeb, 0x85, 0x76, 0xe8, 0x78, 0x6e, 0x40, 0x48, 0xc6, 0x8f, 0xa0, 0xfe, 0x94, + 0xbb, 0x3d, 0xce, 0x87, 0x26, 0xff, 0x7c, 0xca, 0x83, 0x90, 0xbd, 0x0b, 0x8b, 0x36, 0xff, 0x31, + 0xe7, 0x43, 0x6b, 0x62, 0x07, 0xc1, 0xe4, 0xdc, 0xb7, 0x03, 0xde, 0xca, 0xdc, 0xcf, 0x3c, 0xa8, + 0x9a, 0x4d, 0x2a, 0x38, 0x8a, 0xe0, 0xec, 0x0d, 0xa8, 0x06, 0x02, 0x95, 0xbb, 0xa1, 0xef, 0x4d, + 0xae, 0x5b, 0x59, 0xc4, 0xab, 0x08, 0x58, 0x87, 0x40, 0xc6, 0x08, 0x1a, 0x51, 0x0f, 0xc1, 0xc4, + 0x73, 0x03, 0xce, 0x1e, 0xc3, 0xf2, 0xc0, 0x99, 0x9c, 0x73, 0xdf, 0xc2, 0xca, 0x63, 0x97, 0x8f, + 0x3d, 0xd7, 0x19, 0xb4, 0x32, 0xf7, 0x73, 0x0f, 0xca, 0x26, 0xa3, 0x32, 0x51, 0x63, 0x5f, 0x96, + 0xb0, 0x77, 0xa0, 0xc1, 0x5d, 0x82, 0xf3, 0x21, 0xd6, 0x92, 0x5d, 0xd5, 0x63, 0xb0, 0xa8, 0x60, + 0xfc, 0xed, 0x2c, 0x2c, 0x76, 0x5d, 0x27, 0xfc, 0xd4, 0x1e, 0x8d, 0x78, 0xa8, 0xe6, 0xf4, 0x0e, + 0x34, 0x2e, 0x11, 0x80, 0x73, 0xba, 0xf4, 0xfc, 0xa1, 0x9c, 0x51, 0x9d, 0xc0, 0x47, 0x12, 0x7a, + 0xe3, 0xc8, 0xb2, 0x37, 0x8e, 0x2c, 0x75, 0xb9, 0x72, 0x37, 0x2c, 0xd7, 0x3b, 0xd0, 0xf0, 0xf9, + 0xc0, 0xbb, 0xe0, 0xfe, 0xb5, 0x75, 0xe9, 0xb8, 0x43, 0xef, 0xb2, 0x95, 0xbf, 0x9f, 0x79, 0x50, + 0x30, 0xeb, 0x0a, 0xfc, 0x29, 0x42, 0xd9, 0x26, 0x34, 0x06, 0xe7, 0xb6, 0xeb, 0xf2, 0x91, 0x75, + 0x62, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xab, 0x70, 0x3f, 0xf3, 0xa0, 0xf2, 0xe4, 0xf6, 0x06, 0xee, + 0xea, 0xc6, 0xd6, 0xb9, 0xed, 0x6e, 0x62, 0x49, 0xcf, 0xb5, 0x27, 0xc1, 0xb9, 0x17, 0x9a, 0x75, + 0x59, 0x83, 0xc0, 0x81, 0xb1, 0x0c, 0x4c, 0x5f, 0x09, 0x5a, 0x7b, 0xe3, 0xdf, 0x66, 0x60, 0xe9, + 0xd8, 0x1d, 0x79, 0x83, 0xe7, 0x3f, 0xe7, 0x12, 0xa5, 0xcc, 0x21, 0xfb, 0xaa, 0x73, 0xc8, 0x7d, + 0xd9, 0x39, 0xac, 0xc2, 0x72, 0x72, 0xb0, 0x72, 0x16, 0x1c, 0x56, 0x44, 0xed, 0x33, 0xae, 0x86, + 0xa5, 0xa6, 0xf1, 0x75, 0x68, 0x0e, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x79, 0x34, 0x24, 0x3c, 0x9a, + 0xc8, 0x1b, 0x50, 0x75, 0xf9, 0x65, 0x8c, 0x26, 0x69, 0xd7, 0xe5, 0x97, 0x0a, 0xc5, 0x68, 0xc1, + 0xea, 0x6c, 0x37, 0x72, 0x00, 0x3f, 0xcb, 0x40, 0xfe, 0x38, 0xbc, 0xf2, 0xd8, 0xfb, 0x50, 0xb5, + 0x87, 0x43, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x4f, 0xe8, 0xa4, 0xd4, 0x9f, 0x30, 0x39, 0xc5, 0x36, + 0x15, 0xf5, 0xaf, 0x27, 0xdc, 0xac, 0xd8, 0xf1, 0x07, 0x6b, 0x41, 0x51, 0x7e, 0x62, 0xbf, 0x65, + 0x53, 0x7d, 0xb2, 0xbb, 0x00, 0xf6, 0xd8, 0x9b, 0xba, 0xa1, 0x15, 0xd8, 0x21, 0xae, 0x58, 0xce, + 0x2c, 0x13, 0xa4, 0x67, 0x87, 0xec, 0x0e, 0x94, 0x27, 0xcf, 0xad, 0x60, 0xe0, 0x3b, 0x93, 0x10, + 0x89, 0xa7, 0x6c, 0x96, 0x26, 0xcf, 0x7b, 0xf8, 0xcd, 0xde, 0x85, 0x92, 0x37, 0x0d, 0x27, 0x9e, + 0xe3, 0x86, 0x92, 0x5e, 0x1a, 0x72, 0x20, 0x87, 0xd3, 0xf0, 0x48, 0x80, 0xcd, 0x08, 0x81, 0xbd, + 0x05, 0xb5, 0x81, 0xe7, 0x9e, 0x3a, 0xfe, 0x98, 0x38, 0x42, 0x6b, 0x01, 0xfb, 0x4a, 0x02, 0x8d, + 0x3f, 0xcc, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, 0x41, 0x31, 0xbc, 0xb2, + 0xce, 0xed, 0xe0, 0x1c, 0xa7, 0x5a, 0x36, 0x17, 0xc2, 0xab, 0x5d, 0x3b, 0x38, 0x67, 0xab, 0xb0, + 0x40, 0xa3, 0xc4, 0x09, 0xe5, 0x4c, 0xf9, 0x25, 0x0e, 0x88, 0x3b, 0x1d, 0x5b, 0xc9, 0xae, 0x72, + 0x48, 0x31, 0x4d, 0x77, 0x3a, 0xde, 0xd2, 0xe1, 0x62, 0xf2, 0x27, 0x62, 0xbb, 0xa9, 0x03, 0x9a, + 0x5e, 0x19, 0x21, 0xd8, 0xc7, 0x1b, 0x50, 0x95, 0xc5, 0xdc, 0x39, 0x3b, 0xa7, 0x39, 0x16, 0xcc, + 0x0a, 0x21, 0x20, 0x48, 0xb4, 0x10, 0x3a, 0x63, 0x6e, 0x05, 0xa1, 0x3d, 0x9e, 0xc8, 0x29, 0x95, + 0x05, 0xa4, 0x27, 0x00, 0x58, 0xec, 0x85, 0xf6, 0xc8, 0x3a, 0xe5, 0x3c, 0x68, 0x15, 0x65, 0xb1, + 0x80, 0xec, 0x70, 0x1e, 0xb0, 0xaf, 0x41, 0x7d, 0xc8, 0x83, 0xd0, 0x92, 0x9b, 0xc1, 0x83, 0x56, + 0x09, 0x4f, 0x7e, 0x4d, 0x40, 0xdb, 0x0a, 0xc8, 0x5e, 0x03, 0xf0, 0xed, 0x4b, 0x4b, 0x2c, 0x04, + 0xbf, 0x6a, 0x95, 0x69, 0x17, 0x7c, 0xfb, 0xb2, 0x7f, 0xb5, 0xcb, 0xaf, 0x04, 0xd5, 0x3c, 0xe5, + 0xa1, 0xb6, 0x68, 0x81, 0xa4, 0x4e, 0x63, 0x0f, 0x98, 0x06, 0xde, 0xe6, 0xa1, 0xed, 0x8c, 0x02, + 0xf6, 0x01, 0x54, 0x43, 0x0d, 0x19, 0xd9, 0x60, 0x25, 0x22, 0x21, 0xad, 0x82, 0x99, 0xc0, 0x33, + 0xce, 0xa1, 0xb4, 0xc3, 0xf9, 0x9e, 0x33, 0x76, 0x42, 0xb6, 0x0a, 0x85, 0x53, 0xe7, 0x8a, 0x13, + 0xb1, 0xe7, 0x76, 0x6f, 0x99, 0xf4, 0xc9, 0xee, 0x01, 0xe0, 0x1f, 0xd6, 0x38, 0xa2, 0xa6, 0xdd, + 0x5b, 0x66, 0x19, 0x61, 0xfb, 0x81, 0x1d, 0xb2, 0x75, 0x28, 0x4e, 0xb8, 0x3f, 0xe0, 0x6a, 0xdf, + 0x76, 0x6f, 0x99, 0x0a, 0xb0, 0x59, 0x84, 0xc2, 0x48, 0xb4, 0x6e, 0xfc, 0x71, 0x01, 0x2a, 0x3d, + 0xee, 0x46, 0xa7, 0x8c, 0x41, 0x5e, 0x2c, 0x88, 0x3c, 0x59, 0xf8, 0x37, 0x7b, 0x13, 0x2a, 0xb8, + 0x74, 0x41, 0xe8, 0x3b, 0xee, 0x19, 0x51, 0xf5, 0x66, 0xb6, 0x95, 0x31, 0x41, 0x80, 0x7b, 0x08, + 0x65, 0x4d, 0xc8, 0xd9, 0x63, 0x45, 0xd5, 0xe2, 0x4f, 0x76, 0x1b, 0x4a, 0xf6, 0x38, 0xa4, 0xe1, + 0x55, 0x11, 0x5c, 0xb4, 0xc7, 0x21, 0x0e, 0xed, 0x0d, 0xa8, 0x4e, 0xec, 0xeb, 0xb1, 0x38, 0xcb, + 0x11, 0x39, 0x54, 0xcd, 0x8a, 0x84, 0x21, 0x41, 0x3c, 0x81, 0x25, 0x1d, 0x45, 0x75, 0x5e, 0x88, + 0x3a, 0x5f, 0xd4, 0xb0, 0xe5, 0x18, 0xde, 0x81, 0x86, 0xaa, 0xe3, 0xd3, 0x7c, 0x90, 0x4c, 0xca, + 0x66, 0x5d, 0x82, 0xd5, 0x2c, 0x1f, 0x40, 0xf3, 0xd4, 0x71, 0xed, 0x91, 0x35, 0x18, 0x85, 0x17, + 0xd6, 0x90, 0x8f, 0x42, 0x1b, 0x29, 0xa6, 0x60, 0xd6, 0x11, 0xbe, 0x35, 0x0a, 0x2f, 0xb6, 0x05, + 0x94, 0x7d, 0x03, 0xca, 0xa7, 0x9c, 0x5b, 0xb8, 0x58, 0xad, 0x52, 0xe2, 0xe0, 0xa9, 0x1d, 0x32, + 0x4b, 0xa7, 0x6a, 0xaf, 0xbe, 0x01, 0x4d, 0x6f, 0x1a, 0x9e, 0x79, 0x8e, 0x7b, 0x66, 0x09, 0x7e, + 0x67, 0x39, 0x43, 0xa4, 0xa1, 0xfc, 0x66, 0xf6, 0x71, 0xc6, 0xac, 0xab, 0x32, 0xc1, 0x79, 0xba, + 0x43, 0xf6, 0x36, 0x34, 0x46, 0x76, 0x10, 0x5a, 0xe7, 0xde, 0xc4, 0x9a, 0x4c, 0x4f, 0x9e, 0xf3, + 0xeb, 0x56, 0x0d, 0x17, 0xa2, 0x26, 0xc0, 0xbb, 0xde, 0xe4, 0x08, 0x81, 0x82, 0xb2, 0x71, 0x9c, + 0x34, 0x08, 0xb8, 0x9f, 0x79, 0x50, 0x33, 0xcb, 0x02, 0x42, 0x9d, 0x7e, 0x06, 0x4b, 0xb8, 0x3d, + 0x83, 0x69, 0x10, 0x7a, 0x63, 0x4b, 0xf0, 0x6a, 0x7f, 0x18, 0xb4, 0x2a, 0x48, 0x6b, 0x5f, 0x97, + 0x83, 0xd5, 0xf6, 0x78, 0x63, 0x9b, 0x07, 0xe1, 0x16, 0x22, 0x9b, 0x84, 0x2b, 0x2e, 0xf4, 0x6b, + 0x73, 0x71, 0x38, 0x0b, 0x67, 0xdf, 0x00, 0x66, 0x8f, 0x46, 0xde, 0xa5, 0x15, 0xf0, 0xd1, 0xa9, + 0x25, 0x17, 0xb1, 0x55, 0xbf, 0x9f, 0x79, 0x50, 0x32, 0x9b, 0x58, 0xd2, 0xe3, 0xa3, 0xd3, 0x23, + 0x82, 0xb3, 0x0f, 0x00, 0x0f, 0x93, 0x75, 0xca, 0xed, 0x70, 0xea, 0xf3, 0xa0, 0xd5, 0xb8, 0x9f, + 0x7b, 0x50, 0x7f, 0xb2, 0x18, 0xad, 0x17, 0x82, 0x37, 0x9d, 0xd0, 0xac, 0x0a, 0x3c, 0xf9, 0x1d, + 0xac, 0x6f, 0xc3, 0x6a, 0xfa, 0x90, 0x04, 0x51, 0x89, 0x55, 0x11, 0xc4, 0x98, 0x37, 0xc5, 0x9f, + 0x6c, 0x19, 0x0a, 0x17, 0xf6, 0x68, 0xca, 0x25, 0x4f, 0xa7, 0x8f, 0x0f, 0xb3, 0xdf, 0xcd, 0x18, + 0x7f, 0x94, 0x81, 0x2a, 0xcd, 0x52, 0xca, 0x22, 0x6f, 0x42, 0x4d, 0x51, 0x03, 0xf7, 0x7d, 0xcf, + 0x97, 0x5c, 0x4d, 0x51, 0x5e, 0x47, 0xc0, 0xc4, 0xad, 0xa2, 0x90, 0x26, 0x3e, 0x77, 0xc6, 0xf6, + 0x99, 0x6a, 0x5a, 0x91, 0xd2, 0x91, 0x04, 0xb3, 0xf7, 0xe2, 0xf6, 0x7c, 0x6f, 0x1a, 0x72, 0x79, + 0xe7, 0x55, 0xe5, 0xf4, 0x4c, 0x01, 0x8b, 0x5a, 0xc7, 0xaf, 0x57, 0xa0, 0x73, 0xe3, 0x77, 0x33, + 0xc0, 0xc4, 0xb0, 0xfb, 0x1e, 0x35, 0x20, 0x29, 0x74, 0xb6, 0x66, 0xe6, 0x95, 0x4f, 0x48, 0xf6, + 0x45, 0x27, 0xc4, 0x80, 0x02, 0x8d, 0x3d, 0x9f, 0x32, 0x76, 0x2a, 0xfa, 0x41, 0xbe, 0x94, 0x6b, + 0xe6, 0x8d, 0xff, 0x96, 0x83, 0xe5, 0x2d, 0xba, 0xb2, 0xdb, 0x83, 0x01, 0x9f, 0x44, 0x67, 0xe7, + 0x1e, 0x54, 0x5c, 0x6f, 0xc8, 0x15, 0xc5, 0xd2, 0xc0, 0x40, 0x80, 0x34, 0x72, 0x3d, 0xb7, 0x1d, + 0x97, 0x06, 0x4e, 0x8b, 0x59, 0x46, 0x08, 0x0e, 0xfb, 0x6d, 0x68, 0x4c, 0xb8, 0x3b, 0xd4, 0x8f, + 0x08, 0x09, 0x55, 0x35, 0x09, 0x96, 0xa7, 0xe3, 0x1e, 0x54, 0x4e, 0xa7, 0x84, 0x27, 0x18, 0x4b, + 0x1e, 0x69, 0x00, 0x24, 0xa8, 0x4d, 0xfc, 0x65, 0x32, 0x0d, 0xce, 0xb1, 0xb4, 0x80, 0xa5, 0x45, + 0xf1, 0x2d, 0x8a, 0xee, 0x02, 0x0c, 0xa7, 0x41, 0x28, 0x4f, 0xcc, 0x02, 0x16, 0x96, 0x05, 0x84, + 0x4e, 0xcc, 0x37, 0x61, 0x69, 0x6c, 0x5f, 0x59, 0x48, 0x3b, 0x96, 0xe3, 0x5a, 0xa7, 0x23, 0xbc, + 0x73, 0x8a, 0x88, 0xd7, 0x1c, 0xdb, 0x57, 0x9f, 0x88, 0x92, 0xae, 0xbb, 0x83, 0x70, 0xc1, 0x56, + 0x94, 0xb8, 0xe3, 0xf3, 0x80, 0xfb, 0x17, 0x1c, 0x39, 0x41, 0x3e, 0x92, 0x69, 0x4c, 0x82, 0x8a, + 0x11, 0x8d, 0xc5, 0xbc, 0xc3, 0xd1, 0x80, 0x8e, 0xbd, 0x59, 0x1c, 0x3b, 0xee, 0x6e, 0x38, 0x1a, + 0x88, 0x7b, 0x45, 0xf0, 0x91, 0x09, 0xf7, 0xad, 0xe7, 0x97, 0x78, 0x86, 0xf3, 0xc8, 0x37, 0x8e, + 0xb8, 0xff, 0xec, 0x52, 0x5c, 0xfd, 0x83, 0x00, 0x19, 0x91, 0x7d, 0xdd, 0xaa, 0xe0, 0x01, 0x2f, + 0x0d, 0x02, 0xc1, 0x82, 0xec, 0x6b, 0x71, 0x08, 0xc5, 0x68, 0x6d, 0xdc, 0x05, 0x3e, 0xc4, 0xe6, + 0x03, 0xe4, 0xa8, 0x35, 0x1c, 0x6c, 0x5b, 0x16, 0x88, 0x7e, 0x02, 0x41, 0xf5, 0x6a, 0xb0, 0xa7, + 0x23, 0xfb, 0x2c, 0x40, 0x96, 0x52, 0x33, 0xab, 0x12, 0xb8, 0x23, 0x60, 0xc6, 0xa7, 0x24, 0x64, + 0x69, 0x7b, 0x2b, 0xcf, 0x8c, 0xb8, 0xea, 0x11, 0x82, 0xfb, 0x5a, 0x32, 0xe5, 0x57, 0xda, 0xa6, + 0x65, 0x53, 0x36, 0xcd, 0xf8, 0xfd, 0x0c, 0x54, 0x65, 0xcb, 0x28, 0x94, 0xb0, 0x0d, 0x60, 0x6a, + 0x17, 0xc3, 0x2b, 0x67, 0x68, 0x9d, 0x5c, 0x87, 0x3c, 0x20, 0xa2, 0xd9, 0xbd, 0x65, 0x36, 0x65, + 0x59, 0xff, 0xca, 0x19, 0x6e, 0x8a, 0x12, 0xf6, 0x10, 0x9a, 0x09, 0xfc, 0x20, 0xf4, 0x89, 0xa2, + 0x77, 0x6f, 0x99, 0x75, 0x0d, 0xbb, 0x17, 0xfa, 0xe2, 0x8c, 0x08, 0x91, 0x67, 0x1a, 0x5a, 0x8e, + 0x3b, 0xe4, 0x57, 0x48, 0x46, 0x35, 0xb3, 0x42, 0xb0, 0xae, 0x00, 0x6d, 0xd6, 0xa1, 0xaa, 0x37, + 0x67, 0x9c, 0x41, 0x49, 0xc9, 0x4b, 0x28, 0x30, 0xcc, 0x0c, 0xc9, 0x2c, 0x87, 0xd1, 0x48, 0x6e, + 0x43, 0x29, 0x39, 0x02, 0xb3, 0x18, 0xbe, 0x72, 0xc7, 0xc6, 0xf7, 0xa0, 0xb9, 0x27, 0x88, 0xc7, + 0x15, 0xc4, 0x2a, 0xe5, 0xbf, 0x55, 0x58, 0xd0, 0x0e, 0x4d, 0xd9, 0x94, 0x5f, 0xe2, 0xce, 0x3d, + 0xf7, 0x82, 0x50, 0xf6, 0x82, 0x7f, 0x1b, 0x7f, 0x9c, 0x01, 0xd6, 0x09, 0x42, 0x67, 0x6c, 0x87, + 0x7c, 0x87, 0x47, 0x6c, 0xe1, 0x10, 0xaa, 0xa2, 0xb5, 0xbe, 0xd7, 0x26, 0x81, 0x8c, 0x04, 0x8a, + 0x77, 0xe5, 0x31, 0x9e, 0xaf, 0xb0, 0xa1, 0x63, 0x13, 0x9b, 0x4f, 0x34, 0x20, 0x4e, 0x59, 0x68, + 0xfb, 0x67, 0x3c, 0x44, 0x31, 0x4e, 0xca, 0xfb, 0x40, 0x20, 0x21, 0xc0, 0xad, 0xff, 0x1a, 0x2c, + 0xce, 0xb5, 0xa1, 0xf3, 0xe5, 0x72, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, 0x82, 0xa5, 0xc4, 0xb8, + 0x24, 0xa5, 0xad, 0x41, 0x51, 0x1c, 0x08, 0x21, 0x1c, 0x64, 0x48, 0xaa, 0x3c, 0xe5, 0x5c, 0x88, + 0xc1, 0x8f, 0x60, 0xf9, 0x94, 0x73, 0xdf, 0x0e, 0xb1, 0x10, 0x4f, 0x8c, 0xd8, 0x21, 0xd9, 0xf0, + 0xa2, 0x2c, 0xeb, 0xd9, 0xe1, 0x11, 0xf7, 0xc5, 0x4e, 0x19, 0xff, 0x23, 0x03, 0x0d, 0xc1, 0x41, + 0xf7, 0x6d, 0xf7, 0x5a, 0xad, 0xd3, 0x5e, 0xea, 0x3a, 0x3d, 0xd0, 0x2e, 0x43, 0x0d, 0xfb, 0xcb, + 0x2e, 0x52, 0x6e, 0x76, 0x91, 0xd8, 0x7d, 0xa8, 0x26, 0xc6, 0x5a, 0xc0, 0xb1, 0x42, 0x10, 0x0d, + 0xf2, 0x17, 0x5f, 0xc6, 0xb7, 0xa1, 0x19, 0x0f, 0x5b, 0xae, 0x21, 0x83, 0xbc, 0x20, 0x49, 0xd9, + 0x00, 0xfe, 0x6d, 0xfc, 0xd3, 0x0c, 0x21, 0x6e, 0x79, 0x4e, 0x24, 0x9d, 0x0a, 0x44, 0x21, 0xf7, + 0x2a, 0x44, 0xf1, 0xf7, 0x8d, 0x52, 0xfd, 0x2f, 0x3e, 0x59, 0x71, 0x74, 0x02, 0xee, 0x0e, 0x2d, + 0x7b, 0x34, 0x42, 0xe6, 0x5b, 0x32, 0x8b, 0xe2, 0xbb, 0x3d, 0x1a, 0x19, 0xef, 0xc0, 0xa2, 0x36, + 0xba, 0x17, 0xcc, 0xe3, 0x00, 0xd8, 0x9e, 0x13, 0x84, 0xc7, 0x6e, 0x30, 0xd1, 0x04, 0xb7, 0x3b, + 0x50, 0x16, 0x1c, 0x56, 0x8c, 0x8c, 0x8e, 0x6c, 0xc1, 0x14, 0x2c, 0x57, 0x8c, 0x2b, 0xc0, 0x42, + 0xfb, 0x4a, 0x16, 0x66, 0x65, 0xa1, 0x7d, 0x85, 0x85, 0xc6, 0x77, 0x61, 0x29, 0xd1, 0x9e, 0xec, + 0xfa, 0x0d, 0x28, 0x4c, 0xc3, 0x2b, 0x4f, 0x89, 0xe6, 0x15, 0x49, 0x21, 0x42, 0x01, 0x34, 0xa9, + 0xc4, 0xf8, 0x08, 0x16, 0x0f, 0xf8, 0xa5, 0x3c, 0xc4, 0x6a, 0x20, 0x6f, 0x43, 0xfe, 0x25, 0x4a, + 0x21, 0x96, 0x1b, 0x1b, 0xc0, 0xf4, 0xca, 0xb2, 0x57, 0x4d, 0x47, 0xcc, 0x24, 0x74, 0x44, 0xe3, + 0x6d, 0x60, 0x3d, 0xe7, 0xcc, 0xdd, 0xe7, 0x41, 0x60, 0x9f, 0x45, 0xc7, 0xbe, 0x09, 0xb9, 0x71, + 0x70, 0x26, 0x79, 0x94, 0xf8, 0xd3, 0xf8, 0x16, 0x2c, 0x25, 0xf0, 0x64, 0xc3, 0xaf, 0x41, 0x39, + 0x70, 0xce, 0x5c, 0x14, 0xac, 0x64, 0xd3, 0x31, 0xc0, 0xd8, 0x81, 0xe5, 0x4f, 0xb8, 0xef, 0x9c, + 0x5e, 0xbf, 0xac, 0xf9, 0x64, 0x3b, 0xd9, 0xd9, 0x76, 0x3a, 0xb0, 0x32, 0xd3, 0x8e, 0xec, 0x9e, + 0xc8, 0x57, 0xee, 0x64, 0xc9, 0xa4, 0x0f, 0x8d, 0xef, 0x65, 0x75, 0xbe, 0x67, 0x1c, 0x03, 0xdb, + 0xf2, 0x5c, 0x97, 0x0f, 0xc2, 0x23, 0xce, 0xfd, 0xd8, 0x4a, 0x15, 0xd3, 0x6a, 0xe5, 0xc9, 0x9a, + 0x5c, 0xd9, 0x59, 0x66, 0x2a, 0x89, 0x98, 0x41, 0x7e, 0xc2, 0xfd, 0x31, 0x36, 0x5c, 0x32, 0xf1, + 0x6f, 0x63, 0x05, 0x96, 0x12, 0xcd, 0x4a, 0xbd, 0xfe, 0x31, 0xac, 0x6c, 0x3b, 0xc1, 0x60, 0xbe, + 0xc3, 0x35, 0x28, 0x4e, 0xa6, 0x27, 0x56, 0x92, 0x2f, 0x3f, 0xe3, 0xd7, 0x42, 0xdb, 0x9b, 0xad, + 0x21, 0xdb, 0xfa, 0x9b, 0x19, 0xc8, 0xef, 0xf6, 0xf7, 0xb6, 0xd8, 0x3a, 0x94, 0x1c, 0x77, 0xe0, + 0x8d, 0x85, 0xe0, 0x45, 0x73, 0x8e, 0xbe, 0x6f, 0x3c, 0x60, 0x77, 0xa0, 0x8c, 0xf2, 0x9a, 0x50, + 0x6d, 0xa5, 0xe8, 0x53, 0x12, 0x80, 0x3d, 0x6f, 0xf0, 0x5c, 0xe8, 0xd4, 0xfc, 0x6a, 0xe2, 0xf8, + 0xa8, 0x35, 0x2b, 0x65, 0x38, 0x4f, 0x77, 0x7d, 0x5c, 0x40, 0x1a, 0xb1, 0xf1, 0x57, 0x45, 0x28, + 0xca, 0xdb, 0x96, 0x6e, 0xee, 0xd0, 0xb9, 0xe0, 0xf1, 0xcd, 0x2d, 0xbe, 0x84, 0x3c, 0xe0, 0xf3, + 0xb1, 0x17, 0x46, 0x02, 0x1b, 0xed, 0x41, 0x95, 0x80, 0x52, 0x64, 0xd3, 0x84, 0x06, 0x32, 0x31, + 0xe4, 0x08, 0x69, 0xa0, 0x5f, 0xe5, 0x77, 0xa0, 0xa8, 0xee, 0xfe, 0x7c, 0xa4, 0xd3, 0x2c, 0x0c, + 0x48, 0x5a, 0x5b, 0x87, 0xd2, 0xc0, 0x9e, 0xd8, 0x03, 0x27, 0xbc, 0x96, 0x0c, 0x21, 0xfa, 0x16, + 0xad, 0x8f, 0xbc, 0x81, 0x3d, 0xb2, 0x4e, 0xec, 0x91, 0xed, 0x0e, 0xb8, 0xd4, 0xdd, 0xab, 0x08, + 0xdc, 0x24, 0x98, 0xd0, 0xcf, 0xe5, 0x38, 0x15, 0x16, 0xa9, 0xf0, 0x72, 0xf4, 0x0a, 0x4d, 0x08, + 0x97, 0xde, 0x78, 0xec, 0x08, 0x2d, 0x83, 0xc4, 0xb0, 0x9c, 0x59, 0x26, 0xc8, 0x0e, 0xc7, 0xd9, + 0xca, 0xe2, 0x4b, 0x5a, 0xba, 0x32, 0x75, 0x45, 0xc0, 0x4f, 0xc9, 0x90, 0x30, 0x2f, 0x8b, 0xe5, + 0x34, 0x59, 0xec, 0x5d, 0x58, 0x9c, 0xba, 0x01, 0x0f, 0xc3, 0x11, 0x1f, 0x46, 0x63, 0xa9, 0x20, + 0x52, 0x33, 0x2a, 0x50, 0xc3, 0xd9, 0x80, 0x25, 0x32, 0x3a, 0x04, 0x76, 0xe8, 0x05, 0xe7, 0x4e, + 0x60, 0x05, 0x42, 0x43, 0x22, 0x75, 0x77, 0x11, 0x8b, 0x7a, 0xb2, 0xa4, 0x47, 0x2a, 0xd2, 0xda, + 0x0c, 0xbe, 0xcf, 0x07, 0xdc, 0xb9, 0xe0, 0x43, 0x94, 0xd3, 0x72, 0xe6, 0x4a, 0xa2, 0x8e, 0x29, + 0x0b, 0x51, 0xe8, 0x9e, 0x8e, 0xad, 0xe9, 0x64, 0x68, 0x0b, 0x61, 0xa5, 0x4e, 0xc2, 0xb0, 0x3b, + 0x1d, 0x1f, 0x13, 0x84, 0x3d, 0x06, 0x25, 0x89, 0x49, 0xf9, 0xb0, 0x91, 0xe0, 0x67, 0x82, 0x58, + 0xcd, 0xaa, 0xc4, 0x20, 0x41, 0x31, 0x21, 0x73, 0x36, 0x67, 0x64, 0xce, 0x16, 0x14, 0x27, 0xbe, + 0x73, 0x61, 0x87, 0xbc, 0xb5, 0x48, 0x0c, 0x5c, 0x7e, 0x0a, 0xce, 0xe0, 0xb8, 0x4e, 0xe8, 0xd8, + 0xa1, 0xe7, 0xb7, 0x18, 0x96, 0xc5, 0x00, 0xf6, 0x10, 0x16, 0x91, 0x46, 0x82, 0xd0, 0x0e, 0xa7, + 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x21, 0x1c, 0x85, 0x50, 0xf6, 0x2d, 0x58, + 0x25, 0xb2, 0xc0, 0x1a, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x97, 0x62, 0x09, 0x4b, 0x05, 0x7d, + 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0xef, 0xc3, 0x9a, 0x24, 0x93, 0xb9, 0x5a, 0x2b, 0x58, 0x6b, 0x99, + 0x8a, 0x67, 0xaa, 0x6d, 0xc0, 0xa2, 0x18, 0x92, 0x33, 0xb0, 0x64, 0x6d, 0x71, 0x12, 0x56, 0xc5, + 0xe8, 0x51, 0x53, 0x6a, 0x50, 0xa1, 0x89, 0x65, 0xcf, 0xf8, 0x35, 0xfb, 0x1e, 0x34, 0x88, 0x64, + 0x50, 0xbd, 0x42, 0x4e, 0xbf, 0x8e, 0x9c, 0x7e, 0x45, 0x59, 0x38, 0xa3, 0x52, 0x64, 0xf6, 0xf5, + 0x41, 0xe2, 0x5b, 0x1c, 0x87, 0x91, 0x73, 0xca, 0x43, 0x67, 0xcc, 0x5b, 0x6b, 0x44, 0x60, 0xea, + 0x5b, 0x9c, 0xd4, 0xe9, 0x04, 0x4b, 0x5a, 0xc4, 0x17, 0xe8, 0x0b, 0x69, 0x77, 0xe4, 0x05, 0x5c, + 0x99, 0xa8, 0x5a, 0xb7, 0xe5, 0x21, 0x14, 0x40, 0xc9, 0xf6, 0x8c, 0x9f, 0x66, 0xe8, 0x1e, 0x93, + 0xc7, 0x3e, 0xd0, 0xb4, 0x32, 0x3a, 0xf0, 0x96, 0xe7, 0x8e, 0xae, 0x25, 0x0f, 0x00, 0x02, 0x1d, + 0xba, 0x23, 0x3c, 0x84, 0x8e, 0xab, 0xa3, 0x10, 0xcb, 0xac, 0x2a, 0x20, 0x22, 0xdd, 0x83, 0xca, + 0x64, 0x7a, 0x32, 0x72, 0x06, 0x84, 0x92, 0xa3, 0x56, 0x08, 0x84, 0x08, 0x42, 0x2d, 0x25, 0x42, + 0x20, 0x8c, 0x3c, 0x62, 0x54, 0x24, 0x0c, 0x51, 0x90, 0x25, 0x73, 0x1f, 0xb9, 0x40, 0xd5, 0xc4, + 0xbf, 0x8d, 0x4d, 0x58, 0x4e, 0x0e, 0x5a, 0xde, 0x17, 0x0f, 0xa1, 0x24, 0x59, 0x8c, 0xb2, 0x57, + 0xd4, 0x35, 0x0b, 0xb2, 0xd0, 0xac, 0xa2, 0x72, 0xe3, 0xb7, 0x17, 0x60, 0x49, 0x42, 0xb7, 0xc4, + 0x8a, 0xf4, 0xa6, 0xe3, 0xb1, 0xed, 0xa7, 0xf0, 0xae, 0xcc, 0x8b, 0x79, 0x57, 0x76, 0x8e, 0x77, + 0x25, 0x15, 0x56, 0x62, 0x7d, 0x49, 0x85, 0x55, 0x6c, 0x01, 0xe9, 0x10, 0xba, 0xf9, 0xb2, 0x26, + 0xc1, 0x7d, 0x32, 0x93, 0xce, 0x71, 0xda, 0x42, 0x0a, 0xa7, 0xd5, 0xf9, 0xe4, 0xc2, 0x0c, 0x9f, + 0x7c, 0x03, 0x68, 0xaf, 0x15, 0xdb, 0x2f, 0x92, 0x5a, 0x81, 0x30, 0x69, 0x03, 0x7d, 0x07, 0x1a, + 0xb3, 0xac, 0x89, 0x78, 0x60, 0x3d, 0x85, 0x31, 0x39, 0x63, 0x8e, 0x97, 0x8c, 0x86, 0x5c, 0x96, + 0x8c, 0xc9, 0x19, 0xf3, 0x3d, 0x2c, 0x51, 0xf8, 0x1d, 0x00, 0xea, 0x1b, 0x69, 0x1d, 0x90, 0xd6, + 0xdf, 0x4e, 0xee, 0x85, 0xbe, 0xea, 0x1b, 0xe2, 0x63, 0xea, 0x73, 0x24, 0xfe, 0x32, 0xd6, 0x44, + 0xba, 0x7f, 0x06, 0x75, 0x6f, 0xc2, 0x5d, 0x2b, 0x66, 0x11, 0x15, 0x6c, 0xea, 0xad, 0x17, 0x34, + 0xd5, 0x55, 0xb8, 0x66, 0x4d, 0xd4, 0x8d, 0x3e, 0xd9, 0x3e, 0x2d, 0x3c, 0xd7, 0x5a, 0xab, 0x7e, + 0x89, 0xd6, 0xea, 0x58, 0x39, 0xfa, 0x36, 0xfe, 0x4e, 0x06, 0x2a, 0xda, 0xb0, 0xd9, 0x0a, 0x2c, + 0x6e, 0x1d, 0x1e, 0x1e, 0x75, 0xcc, 0x76, 0xbf, 0xfb, 0x49, 0xc7, 0xda, 0xda, 0x3b, 0xec, 0x75, + 0x9a, 0xb7, 0x04, 0x78, 0xef, 0x70, 0xab, 0xbd, 0x67, 0xed, 0x1c, 0x9a, 0x5b, 0x0a, 0x9c, 0x61, + 0xab, 0xc0, 0xcc, 0xce, 0xfe, 0x61, 0xbf, 0x93, 0x80, 0x67, 0x59, 0x13, 0xaa, 0x9b, 0x66, 0xa7, + 0xbd, 0xb5, 0x2b, 0x21, 0x39, 0xb6, 0x0c, 0xcd, 0x9d, 0xe3, 0x83, 0xed, 0xee, 0xc1, 0x53, 0x6b, + 0xab, 0x7d, 0xb0, 0xd5, 0xd9, 0xeb, 0x6c, 0x37, 0xf3, 0xac, 0x06, 0xe5, 0xf6, 0x66, 0xfb, 0x60, + 0xfb, 0xf0, 0xa0, 0xb3, 0xdd, 0x2c, 0x18, 0xbf, 0x02, 0xe5, 0x78, 0xa2, 0x15, 0x28, 0x1e, 0x1f, + 0x3c, 0x3b, 0x38, 0xfc, 0xf4, 0xa0, 0x79, 0x8b, 0x95, 0xa1, 0x80, 0xfd, 0x37, 0x33, 0x0c, 0x60, + 0x81, 0xfa, 0x6c, 0x66, 0x59, 0x09, 0xf2, 0x9b, 0x87, 0xfd, 0xdd, 0x66, 0xce, 0xf8, 0x8b, 0x0c, + 0xac, 0xe0, 0x94, 0x87, 0xb3, 0x4c, 0xe0, 0x3e, 0x54, 0x06, 0x9e, 0x37, 0x11, 0x0a, 0x52, 0x2c, + 0x08, 0xe8, 0x20, 0x71, 0xc0, 0x89, 0xe7, 0x9e, 0x7a, 0xfe, 0x80, 0x4b, 0x1e, 0x00, 0x08, 0xda, + 0x11, 0x10, 0x41, 0x83, 0x92, 0x88, 0x09, 0x83, 0x58, 0x40, 0x85, 0x60, 0x84, 0xb2, 0x0a, 0x0b, + 0x27, 0x3e, 0xb7, 0x07, 0xe7, 0xf2, 0xf4, 0xcb, 0x2f, 0xf6, 0xf5, 0x58, 0x75, 0x1f, 0x08, 0x9a, + 0x1a, 0xf1, 0x21, 0x1e, 0x81, 0x92, 0xd9, 0x90, 0xf0, 0x2d, 0x09, 0x16, 0x97, 0x88, 0x7d, 0x62, + 0xbb, 0x43, 0xcf, 0xe5, 0x43, 0xa9, 0x21, 0xc4, 0x00, 0xe3, 0x08, 0x56, 0x67, 0xe7, 0x27, 0xf9, + 0xc5, 0x07, 0x1a, 0xbf, 0x20, 0x81, 0x7d, 0xfd, 0x66, 0x52, 0xd0, 0x78, 0xc7, 0xdf, 0xcb, 0x43, + 0x5e, 0x08, 0x70, 0x37, 0xca, 0x7a, 0xba, 0x44, 0x9e, 0x9b, 0xf3, 0xda, 0xa0, 0x85, 0x80, 0x6e, + 0x76, 0x32, 0x43, 0x95, 0x11, 0x82, 0x37, 0x7a, 0x54, 0xec, 0xf3, 0xc1, 0x85, 0xb4, 0x43, 0x51, + 0xb1, 0xc9, 0x07, 0x17, 0xa8, 0x0a, 0xd9, 0x21, 0xd5, 0xa5, 0xf3, 0x5e, 0x0c, 0xec, 0x10, 0x6b, + 0xca, 0x22, 0xac, 0x57, 0x8c, 0x8a, 0xb0, 0x56, 0x0b, 0x8a, 0x8e, 0x7b, 0xe2, 0x4d, 0xdd, 0x21, + 0x1e, 0xef, 0x92, 0xa9, 0x3e, 0xd1, 0x49, 0x84, 0x9c, 0x48, 0xdc, 0x1f, 0x74, 0x9a, 0x4b, 0x02, + 0xd0, 0x17, 0x37, 0xc8, 0x7b, 0x50, 0x0e, 0xae, 0xdd, 0x81, 0x7e, 0x86, 0x97, 0xe5, 0xfa, 0x88, + 0xd9, 0x6f, 0xf4, 0xae, 0xdd, 0x01, 0x9e, 0xd8, 0x52, 0x20, 0xff, 0x62, 0xef, 0x43, 0x29, 0x32, + 0xd7, 0x12, 0x07, 0xbe, 0xad, 0xd7, 0x50, 0x36, 0x5a, 0xd2, 0x8a, 0x23, 0x54, 0xf6, 0x08, 0x16, + 0xd0, 0xa6, 0x1a, 0xb4, 0xaa, 0x58, 0x49, 0x89, 0xe9, 0x62, 0x18, 0xe8, 0x9f, 0xe1, 0x43, 0xb4, + 0xaf, 0x9a, 0x12, 0x6d, 0xfd, 0x19, 0xd4, 0x12, 0x6d, 0xe9, 0xba, 0x6f, 0x8d, 0x74, 0xdf, 0xb7, + 0x74, 0xdd, 0x37, 0xbe, 0x09, 0x64, 0x35, 0x5d, 0x17, 0xfe, 0x35, 0x28, 0xa9, 0xa9, 0x88, 0xf3, + 0x27, 0xcf, 0x8e, 0xd5, 0xfb, 0xec, 0x60, 0xab, 0x79, 0x8b, 0x35, 0xa0, 0xd2, 0xde, 0xc2, 0x23, + 0x8d, 0x80, 0x8c, 0x40, 0x39, 0x6a, 0xf7, 0x7a, 0x11, 0x24, 0x6b, 0xec, 0x40, 0x73, 0x76, 0xa4, + 0x82, 0x26, 0x43, 0x05, 0x93, 0x16, 0xe7, 0x18, 0x20, 0x34, 0x1b, 0x32, 0x22, 0x93, 0xf8, 0x4c, + 0x1f, 0xc6, 0xfb, 0xd0, 0x14, 0xf7, 0x9a, 0x58, 0xaa, 0x40, 0xb3, 0xdc, 0x8e, 0x84, 0x48, 0xa6, + 0x5b, 0x9d, 0x4b, 0x66, 0x85, 0x60, 0xd8, 0x95, 0xf1, 0x01, 0x2c, 0x6a, 0xd5, 0x62, 0x4d, 0x54, + 0xdc, 0x95, 0xb3, 0x9a, 0x28, 0xea, 0x1d, 0x54, 0x62, 0xac, 0xc1, 0x8a, 0xf8, 0xec, 0x5c, 0x70, + 0x37, 0xec, 0x4d, 0x4f, 0xc8, 0x55, 0xe8, 0x78, 0xae, 0xd0, 0x47, 0xca, 0x51, 0xc9, 0xcd, 0x44, + 0xbe, 0x21, 0x95, 0xd6, 0x2c, 0x92, 0xc6, 0xba, 0xd6, 0x03, 0x56, 0xdc, 0xc0, 0x7f, 0x13, 0xca, + 0x6b, 0x39, 0x02, 0x89, 0x65, 0x3d, 0xea, 0x74, 0x4c, 0xeb, 0xf0, 0x60, 0xaf, 0x7b, 0x20, 0x18, + 0xa5, 0x58, 0x56, 0x04, 0xec, 0xec, 0x20, 0x24, 0x63, 0x34, 0xa1, 0xfe, 0x94, 0x87, 0x5d, 0xf7, + 0xd4, 0x53, 0x6e, 0xb1, 0x9f, 0x15, 0xa0, 0x11, 0x81, 0x62, 0xe5, 0xf7, 0x82, 0xfb, 0x81, 0xe3, + 0xb9, 0x28, 0xc7, 0x96, 0x4d, 0xf5, 0x29, 0x6e, 0x37, 0x67, 0xc8, 0xdd, 0xd0, 0x09, 0xaf, 0xad, + 0x84, 0xa5, 0xac, 0xae, 0xc0, 0xf2, 0x16, 0x5d, 0x86, 0x82, 0x3d, 0x72, 0x6c, 0xe5, 0x61, 0xa5, + 0x0f, 0x01, 0x1d, 0x78, 0x23, 0xcf, 0x47, 0x91, 0xb5, 0x6c, 0xd2, 0x07, 0x7b, 0x0c, 0xcb, 0x42, + 0x74, 0xd6, 0xcd, 0x97, 0xc8, 0x3f, 0xc8, 0x68, 0xc7, 0xdc, 0xe9, 0xf8, 0x28, 0x36, 0x61, 0x8a, + 0x12, 0x71, 0x77, 0x8a, 0x1a, 0x52, 0x58, 0x8a, 0x2a, 0x90, 0x16, 0xb6, 0xe8, 0x4e, 0xc7, 0x6d, + 0x2c, 0x89, 0xf0, 0x9f, 0xc0, 0x8a, 0xc0, 0x8f, 0xc4, 0xab, 0xa8, 0x46, 0x03, 0x6b, 0x88, 0xc6, + 0xba, 0xb2, 0x2c, 0xaa, 0x73, 0x07, 0xca, 0x34, 0x2a, 0xb1, 0xe3, 0x05, 0x92, 0xbe, 0x71, 0x28, + 0xdc, 0x0f, 0xe6, 0x9c, 0xa1, 0x0b, 0x24, 0x08, 0xcc, 0x38, 0x43, 0x35, 0x77, 0x6a, 0x69, 0xd6, + 0x9d, 0xfa, 0x04, 0x56, 0x4e, 0x04, 0x09, 0x9e, 0x73, 0x7b, 0xc8, 0x7d, 0x2b, 0x26, 0x6c, 0xd2, + 0x32, 0x96, 0x44, 0xe1, 0x2e, 0x96, 0x45, 0xe7, 0x40, 0xc8, 0x39, 0x82, 0x2d, 0xf0, 0xa1, 0x15, + 0x7a, 0x16, 0x8a, 0x3f, 0xc8, 0x60, 0x4a, 0x66, 0x8d, 0xc0, 0x7d, 0x6f, 0x4b, 0x00, 0x93, 0x78, + 0x67, 0xbe, 0x3d, 0x39, 0x97, 0x7a, 0x40, 0x84, 0xf7, 0x54, 0x00, 0xd9, 0x6b, 0x50, 0x14, 0x24, + 0xef, 0x72, 0xf2, 0x59, 0x91, 0xa4, 0xad, 0x40, 0xec, 0x2d, 0x58, 0xc0, 0x3e, 0x82, 0x56, 0x13, + 0xe9, 0xbd, 0x1a, 0x33, 0x72, 0xc7, 0x35, 0x65, 0x99, 0x10, 0x26, 0xa7, 0xbe, 0x43, 0x5c, 0xa6, + 0x6c, 0xe2, 0xdf, 0xec, 0xfb, 0x1a, 0xcb, 0x5a, 0xc2, 0xba, 0x4a, 0x1e, 0x98, 0xa1, 0xb4, 0x9b, + 0xb8, 0xd7, 0x57, 0xca, 0x8c, 0x7e, 0x90, 0x2f, 0x55, 0x9a, 0x55, 0xe3, 0x3b, 0x50, 0xa0, 0xd5, + 0x11, 0x44, 0x88, 0x6b, 0x97, 0x91, 0x44, 0x88, 0xd0, 0x16, 0x14, 0x5d, 0x1e, 0x5e, 0x7a, 0xfe, + 0x73, 0x65, 0x4b, 0x96, 0x9f, 0xc6, 0x8f, 0xd1, 0x08, 0x12, 0x39, 0xca, 0x49, 0x9f, 0x13, 0xe4, + 0x41, 0xdb, 0x1b, 0x9c, 0xdb, 0xd2, 0x2e, 0x53, 0x42, 0x40, 0xef, 0xdc, 0x9e, 0x23, 0x8f, 0xec, + 0xbc, 0xaf, 0xfc, 0x2d, 0xa8, 0x2b, 0xd7, 0x7c, 0x60, 0x8d, 0xf8, 0x69, 0x28, 0xc9, 0xbd, 0x2a, + 0xfd, 0xf2, 0xc1, 0x1e, 0x3f, 0x0d, 0x8d, 0x7d, 0x58, 0x94, 0x04, 0x79, 0x38, 0xe1, 0xaa, 0xeb, + 0xef, 0xa6, 0xc9, 0xd3, 0x95, 0x27, 0x4b, 0xc9, 0x8b, 0x96, 0x42, 0x0e, 0x12, 0x42, 0xb6, 0xf1, + 0x31, 0x30, 0xfd, 0x1a, 0x96, 0xed, 0x49, 0xa9, 0x56, 0x99, 0xe0, 0x95, 0x27, 0x2b, 0x92, 0x9d, + 0x9d, 0xa1, 0x58, 0x9d, 0x60, 0x3a, 0x18, 0xa8, 0x90, 0x89, 0x92, 0xa9, 0x3e, 0x8d, 0x3f, 0xcd, + 0xc0, 0x12, 0x36, 0xa6, 0xf4, 0x01, 0xc9, 0x64, 0x7f, 0xee, 0x41, 0x8a, 0xfd, 0xd1, 0x65, 0x1f, + 0xfa, 0xf8, 0xf2, 0x46, 0xcf, 0xfc, 0x9c, 0xd1, 0xf3, 0xeb, 0xd0, 0x1c, 0xf2, 0x91, 0x83, 0xd1, + 0x33, 0x4a, 0x94, 0x20, 0x0d, 0xa0, 0xa1, 0xe0, 0x4a, 0x89, 0xfb, 0x47, 0x19, 0x58, 0x24, 0x49, + 0x05, 0xd5, 0x61, 0xb9, 0x50, 0x1f, 0x29, 0xfd, 0x4f, 0xb2, 0x2a, 0x39, 0xa7, 0xf8, 0x06, 0x47, + 0x28, 0x21, 0xef, 0xde, 0x92, 0x7a, 0xa1, 0x84, 0xb2, 0x0f, 0x51, 0x87, 0x71, 0x2d, 0x04, 0xa6, + 0x44, 0xe3, 0x24, 0x37, 0x65, 0xf7, 0x16, 0x2a, 0x38, 0x2e, 0x82, 0x36, 0x4b, 0x42, 0x21, 0x15, + 0x60, 0x63, 0x07, 0x6a, 0x89, 0x6e, 0x12, 0x96, 0xd9, 0x2a, 0x59, 0x66, 0xe7, 0xbc, 0x1f, 0xd9, + 0x79, 0xef, 0xc7, 0xdf, 0xca, 0x03, 0x13, 0x24, 0x35, 0xb3, 0x6b, 0x33, 0xae, 0xc3, 0xec, 0x9c, + 0xeb, 0xf0, 0x31, 0x30, 0x0d, 0x41, 0x79, 0x34, 0x73, 0x91, 0x47, 0xb3, 0x19, 0xe3, 0x4a, 0x87, + 0xe6, 0x63, 0x58, 0x96, 0x02, 0x6d, 0xe4, 0x2b, 0x44, 0x93, 0x1b, 0xed, 0x0f, 0x23, 0xc9, 0x56, + 0xf9, 0x0c, 0xd1, 0xfc, 0xa6, 0xdc, 0x86, 0x81, 0x1d, 0x4a, 0x4b, 0x15, 0xba, 0x0d, 0x7b, 0xf6, + 0x9c, 0xe9, 0x7b, 0xe1, 0xa5, 0x54, 0x50, 0x9c, 0xa3, 0x02, 0xcd, 0x70, 0x52, 0x4a, 0x1a, 0x4e, + 0x0c, 0xa8, 0x29, 0xe7, 0x20, 0xc5, 0x44, 0x90, 0xf4, 0x56, 0x91, 0x1e, 0x42, 0x8c, 0x8b, 0x78, + 0x00, 0x4d, 0x65, 0xdd, 0x88, 0x4c, 0x33, 0xe4, 0xef, 0x97, 0xc6, 0xb1, 0x2d, 0x65, 0xa0, 0x49, + 0x18, 0xc2, 0x2b, 0x33, 0x86, 0xf0, 0x77, 0x61, 0x31, 0x10, 0x44, 0x64, 0x4d, 0x5d, 0x19, 0x9c, + 0xc3, 0x87, 0xa8, 0x3a, 0x95, 0xcc, 0x26, 0x16, 0x1c, 0xc7, 0xf0, 0x79, 0xb3, 0x43, 0x6d, 0xde, + 0xec, 0xc0, 0xde, 0x8f, 0xfd, 0x68, 0xc1, 0xb9, 0x33, 0xc6, 0x8b, 0x3b, 0x0e, 0x64, 0x91, 0x0b, + 0xdc, 0x3b, 0x77, 0xc6, 0xa6, 0x72, 0xda, 0x8a, 0x0f, 0xe3, 0x3f, 0x64, 0xa0, 0x29, 0xe8, 0x20, + 0x41, 0xe7, 0xbf, 0x02, 0x78, 0x22, 0x5f, 0x91, 0xcc, 0x2b, 0x02, 0x57, 0x51, 0xf9, 0x77, 0x00, + 0xc9, 0xd6, 0x12, 0x7a, 0xa2, 0x24, 0xf2, 0x56, 0x92, 0xc8, 0x63, 0x46, 0xb6, 0x7b, 0x8b, 0x14, + 0x00, 0x01, 0x49, 0xf3, 0x5f, 0xe6, 0x53, 0xfc, 0x97, 0xda, 0x51, 0xd8, 0x05, 0x78, 0xc6, 0xaf, + 0xf7, 0xbc, 0x01, 0x6a, 0x68, 0x77, 0x01, 0x04, 0x41, 0x9e, 0xda, 0x63, 0x47, 0x5a, 0x57, 0x0a, + 0x66, 0xf9, 0x39, 0xbf, 0xde, 0x41, 0x80, 0xd8, 0x0d, 0x51, 0x1c, 0x9f, 0x87, 0x82, 0x59, 0x7a, + 0xce, 0xaf, 0xe9, 0x30, 0x58, 0x50, 0x7b, 0xc6, 0xaf, 0xb7, 0x39, 0x89, 0x6b, 0x9e, 0x2f, 0x28, + 0xc1, 0xb7, 0x2f, 0x85, 0x7c, 0x96, 0xf0, 0x3d, 0x56, 0x7c, 0xfb, 0xf2, 0x19, 0xbf, 0x56, 0x7e, + 0xd0, 0xa2, 0x28, 0x1f, 0x79, 0x03, 0x79, 0x03, 0xa9, 0x28, 0x8a, 0x78, 0x50, 0xe6, 0xc2, 0x73, + 0xfc, 0xdb, 0xf8, 0x93, 0x0c, 0xd4, 0xc4, 0xf8, 0x91, 0xc1, 0x89, 0x75, 0x57, 0xc1, 0x38, 0x99, + 0x38, 0x18, 0xe7, 0x89, 0xe4, 0x0f, 0xc4, 0x2d, 0xb3, 0x37, 0x73, 0x4b, 0x5c, 0x60, 0x62, 0x95, + 0xef, 0x41, 0x99, 0xce, 0x96, 0x38, 0xac, 0xb9, 0xc4, 0x2e, 0x25, 0x26, 0x64, 0x96, 0x10, 0xed, + 0x19, 0xf9, 0xfe, 0x35, 0x03, 0x1b, 0x2d, 0x71, 0xd9, 0x8f, 0xcc, 0x6a, 0x29, 0xdb, 0x50, 0x48, + 0x73, 0x23, 0x1f, 0x43, 0x45, 0xa3, 0x29, 0xb4, 0xc6, 0x45, 0x83, 0x27, 0x02, 0x4c, 0x12, 0x4d, + 0x62, 0xf6, 0xbb, 0xb7, 0xcc, 0xda, 0x40, 0x07, 0x6c, 0x2e, 0x40, 0x5e, 0x54, 0x32, 0x3e, 0x82, + 0x45, 0xad, 0x59, 0xd2, 0x46, 0xd3, 0xc6, 0x94, 0x49, 0x1b, 0xd3, 0x3f, 0xce, 0xc0, 0xb2, 0xac, + 0x8d, 0x81, 0x5b, 0x8e, 0xb8, 0xae, 0xf7, 0x83, 0x33, 0xf6, 0x2b, 0x50, 0x13, 0xad, 0x5b, 0x3e, + 0x3f, 0x73, 0x82, 0x90, 0x2b, 0xcf, 0x45, 0xca, 0xe1, 0x10, 0x5c, 0x5b, 0xa0, 0x9a, 0x12, 0x93, + 0x7d, 0x04, 0x15, 0xac, 0x4a, 0xfa, 0xb2, 0xdc, 0x96, 0xd6, 0x7c, 0x45, 0x1a, 0xea, 0xee, 0x2d, + 0x13, 0x82, 0xe8, 0x6b, 0xb3, 0x0c, 0xc5, 0xd0, 0x77, 0xce, 0xce, 0xb8, 0x6f, 0xac, 0x46, 0x43, + 0x13, 0x27, 0x8d, 0xf7, 0x42, 0x3e, 0x11, 0x42, 0x90, 0xf1, 0x9f, 0x32, 0x50, 0x91, 0x67, 0xe7, + 0xe7, 0x76, 0x57, 0xac, 0x6b, 0x91, 0x87, 0xa4, 0x1a, 0xc7, 0x81, 0x86, 0xef, 0x40, 0x63, 0x2c, + 0x04, 0x22, 0x21, 0xb0, 0x27, 0x7c, 0x15, 0x75, 0x05, 0x96, 0xf2, 0xc8, 0x06, 0x2c, 0xa1, 0x78, + 0x12, 0x58, 0xa1, 0x33, 0xb2, 0x54, 0xa1, 0x8c, 0xf2, 0x5b, 0xa4, 0xa2, 0xbe, 0x33, 0xda, 0x97, + 0x05, 0xe2, 0x96, 0x0e, 0x42, 0xfb, 0x8c, 0x4b, 0xd1, 0x97, 0x3e, 0x8c, 0x16, 0xac, 0xce, 0xc8, + 0xea, 0x4a, 0xcf, 0xf8, 0xef, 0x0d, 0x58, 0x9b, 0x2b, 0x92, 0xfa, 0x46, 0x64, 0xa3, 0x1f, 0x39, + 0xe3, 0x13, 0x2f, 0x32, 0x85, 0x65, 0x34, 0x1b, 0xfd, 0x9e, 0x28, 0x51, 0xa6, 0x30, 0x0e, 0x2b, + 0x8a, 0x20, 0xd0, 0x96, 0x15, 0x89, 0xf3, 0x59, 0x14, 0x36, 0xdf, 0x4b, 0x32, 0xaa, 0xd9, 0xee, + 0x14, 0x5c, 0xbf, 0xfe, 0x96, 0x26, 0x73, 0xb0, 0x80, 0x9d, 0x42, 0x2b, 0xa2, 0x3b, 0x29, 0x1f, + 0x69, 0xba, 0x89, 0xe8, 0xe9, 0x1b, 0x2f, 0xe9, 0x29, 0x61, 0x24, 0x31, 0x57, 0x15, 0xb9, 0x52, + 0x63, 0x51, 0x3f, 0x17, 0xf0, 0xba, 0xea, 0x07, 0x65, 0x9d, 0xf9, 0xde, 0xf2, 0xaf, 0x34, 0x2f, + 0x34, 0xfe, 0x24, 0xbb, 0xbc, 0x23, 0x1b, 0x8e, 0x8a, 0xf4, 0x7e, 0xcf, 0x61, 0xf5, 0xd2, 0x76, + 0x42, 0x35, 0x3f, 0x4d, 0x2d, 0x2a, 0x60, 0x7f, 0x4f, 0x5e, 0xd2, 0xdf, 0xa7, 0x54, 0x39, 0x21, + 0xfd, 0x2d, 0x5f, 0xce, 0x03, 0x83, 0xf5, 0x7f, 0x97, 0x85, 0x7a, 0xb2, 0x15, 0x71, 0xa8, 0x25, + 0x1f, 0x52, 0xf2, 0x84, 0x94, 0xc7, 0xa5, 0x89, 0xf6, 0x80, 0xe4, 0x88, 0x79, 0xe3, 0x71, 0x36, + 0xc5, 0x78, 0xac, 0xdb, 0x6c, 0x73, 0x2f, 0xf3, 0x6d, 0xe5, 0x5f, 0xc9, 0xb7, 0x55, 0x48, 0xf3, + 0x6d, 0xdd, 0xec, 0x10, 0x59, 0xf8, 0xb9, 0x1c, 0x22, 0xc5, 0x9b, 0x1d, 0x22, 0xeb, 0x7f, 0x95, + 0x01, 0x36, 0x4f, 0xa9, 0xec, 0x29, 0xd9, 0xc9, 0x5d, 0x3e, 0x92, 0x5c, 0xec, 0x9b, 0xaf, 0x46, + 0xed, 0x6a, 0x83, 0x54, 0x6d, 0xf6, 0x08, 0x96, 0xf4, 0xb8, 0x60, 0x5d, 0x55, 0xa9, 0x99, 0x4c, + 0x2f, 0x8a, 0x15, 0x5a, 0xcd, 0xb1, 0x97, 0x7f, 0xa9, 0x63, 0xaf, 0xf0, 0x52, 0xc7, 0xde, 0x42, + 0xd2, 0xb1, 0xb7, 0xfe, 0x5f, 0x32, 0xb0, 0x94, 0x42, 0x54, 0x5f, 0xdd, 0x9c, 0x05, 0x2d, 0x24, + 0x58, 0x4c, 0x56, 0xd2, 0x82, 0xce, 0x5d, 0xf6, 0xa0, 0x12, 0xfb, 0x8a, 0x54, 0xdc, 0xfc, 0xc3, + 0x97, 0x9d, 0xf4, 0xb8, 0x86, 0xa9, 0x57, 0x5f, 0xff, 0x02, 0x2a, 0x5a, 0x99, 0x58, 0x44, 0xa2, + 0x20, 0x2d, 0x9c, 0x82, 0xee, 0x70, 0xd4, 0xb3, 0xee, 0x81, 0x34, 0xe4, 0x52, 0x39, 0xd1, 0xba, + 0xbc, 0xb0, 0x11, 0x61, 0x03, 0x96, 0x94, 0x0b, 0x83, 0xc7, 0x51, 0x53, 0x92, 0xed, 0x2f, 0x4a, + 0x47, 0x06, 0x8f, 0x82, 0xb0, 0xd6, 0x7f, 0x02, 0xb5, 0x04, 0x47, 0xf8, 0xea, 0xd6, 0x72, 0x56, + 0x6b, 0xa4, 0xb1, 0xea, 0x5a, 0xe3, 0xfa, 0xff, 0xc9, 0x01, 0x9b, 0x67, 0x4a, 0xbf, 0xcc, 0x21, + 0xcc, 0xef, 0x78, 0x2e, 0x65, 0xc7, 0xff, 0x9f, 0x5d, 0x92, 0xef, 0xc2, 0xa2, 0x4c, 0xcc, 0xd0, + 0x3c, 0x3c, 0x44, 0xf5, 0xcd, 0xa8, 0x40, 0x8d, 0xe2, 0x3b, 0xb3, 0x0e, 0xe2, 0x52, 0x22, 0x16, + 0x5d, 0x93, 0x12, 0x66, 0xfc, 0xc4, 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, 0x47, 0x85, 0xa5, + 0xfe, 0xe4, 0x57, 0xbf, 0xf4, 0x3d, 0xb1, 0xd1, 0xc6, 0xfa, 0x28, 0x9a, 0x98, 0xb2, 0x31, 0xe3, + 0x3d, 0xa8, 0x68, 0x60, 0xf4, 0x7a, 0x74, 0xf7, 0x37, 0x0f, 0x9b, 0xb7, 0x58, 0x0d, 0xca, 0x66, + 0x67, 0xeb, 0xf0, 0x93, 0x8e, 0xd9, 0xd9, 0x6e, 0x66, 0x58, 0x09, 0xf2, 0x7b, 0x87, 0xbd, 0x7e, + 0x33, 0x6b, 0xac, 0x43, 0x4b, 0xb6, 0x38, 0x6f, 0x01, 0xfd, 0xdd, 0x7c, 0x64, 0x7c, 0xc0, 0x42, + 0xa9, 0x6b, 0x7c, 0x0b, 0xaa, 0xfa, 0x1d, 0x2e, 0x29, 0x62, 0xc6, 0xc9, 0x28, 0xb4, 0x0c, 0x4f, + 0x63, 0x82, 0x5b, 0x40, 0xae, 0xa3, 0x61, 0x54, 0x8d, 0x04, 0xb3, 0x17, 0xf8, 0x1a, 0x50, 0xe6, + 0x4c, 0x90, 0xe1, 0xff, 0x07, 0xf5, 0xa4, 0x39, 0x50, 0x1e, 0xf5, 0x34, 0xa1, 0x5b, 0xd4, 0x4e, + 0xd8, 0x07, 0xd9, 0xf7, 0xa1, 0x39, 0x6b, 0x4e, 0x94, 0x21, 0xbb, 0x37, 0xd4, 0x6f, 0x38, 0x49, + 0x0b, 0x23, 0xdb, 0x85, 0xe5, 0x34, 0x29, 0x06, 0xe9, 0xe3, 0x66, 0x6d, 0x8b, 0xcd, 0x4b, 0x2a, + 0xec, 0xbb, 0xd2, 0x6a, 0x5c, 0x48, 0xf3, 0xbd, 0x69, 0x8b, 0xbd, 0x41, 0xff, 0x69, 0xf6, 0xe3, + 0x0b, 0x80, 0x18, 0xc6, 0x9a, 0x50, 0x3d, 0x3c, 0xea, 0x1c, 0x58, 0x5b, 0xbb, 0xed, 0x83, 0x83, + 0xce, 0x5e, 0xf3, 0x16, 0x63, 0x50, 0x47, 0xa7, 0xd9, 0x76, 0x04, 0xcb, 0x08, 0x98, 0xb4, 0xde, + 0x2b, 0x58, 0x96, 0x2d, 0x43, 0xb3, 0x7b, 0x30, 0x03, 0xcd, 0xb1, 0x16, 0x2c, 0x1f, 0x75, 0xc8, + 0xcf, 0x96, 0x68, 0x37, 0x2f, 0x24, 0x63, 0x39, 0x5d, 0x21, 0x19, 0x53, 0x82, 0x91, 0x3c, 0x07, + 0x4a, 0x60, 0xfc, 0xbd, 0x0c, 0xac, 0xcc, 0x14, 0xc4, 0x61, 0xe3, 0x24, 0x2e, 0x26, 0x05, 0xc5, + 0x2a, 0x02, 0xd5, 0x69, 0x7a, 0x17, 0x16, 0x23, 0x0d, 0x7a, 0x86, 0xdd, 0x37, 0xa3, 0x02, 0x85, + 0xfc, 0x08, 0x96, 0x34, 0x45, 0x7c, 0x86, 0x57, 0x30, 0xad, 0x48, 0x56, 0x30, 0xd6, 0xa2, 0xf0, + 0xdc, 0x99, 0x51, 0x0f, 0x29, 0x6b, 0x49, 0x2f, 0x88, 0x8d, 0xea, 0xc9, 0xf1, 0xaa, 0x4f, 0xf6, + 0x78, 0x86, 0x10, 0x92, 0xa3, 0xd5, 0x37, 0x5c, 0x75, 0xff, 0x07, 0x0b, 0xc0, 0x3e, 0x9e, 0x72, + 0xff, 0x1a, 0xc3, 0xc2, 0x83, 0x97, 0xc5, 0x49, 0x29, 0x6d, 0x33, 0xfb, 0x4a, 0xa9, 0x1f, 0x69, + 0xa9, 0x17, 0xf9, 0x97, 0xa7, 0x5e, 0x14, 0x5e, 0x96, 0x7a, 0xf1, 0x26, 0xd4, 0x9c, 0x33, 0xd7, + 0x13, 0xac, 0x50, 0x88, 0x7c, 0x41, 0x6b, 0xe1, 0x7e, 0xee, 0x41, 0xd5, 0xac, 0x4a, 0xa0, 0x10, + 0xf8, 0x02, 0xf6, 0x51, 0x8c, 0xc4, 0x87, 0x67, 0x98, 0x26, 0xa4, 0x33, 0xc1, 0xce, 0xf0, 0x8c, + 0x4b, 0xe5, 0x1a, 0xcd, 0x4d, 0xaa, 0xb2, 0x80, 0x07, 0xec, 0x2d, 0xa8, 0x07, 0xde, 0x54, 0x48, + 0xd0, 0x6a, 0x19, 0xc8, 0xec, 0x5e, 0x25, 0xe8, 0x91, 0xf2, 0xb1, 0x2c, 0x4d, 0x03, 0x6e, 0x8d, + 0x9d, 0x20, 0x10, 0x72, 0xcf, 0xc0, 0x73, 0x43, 0xdf, 0x1b, 0x49, 0x4b, 0xfa, 0xe2, 0x34, 0xe0, + 0xfb, 0x54, 0xb2, 0x45, 0x05, 0xec, 0xdb, 0xf1, 0x90, 0x26, 0xb6, 0xe3, 0x07, 0x2d, 0xc0, 0x21, + 0xa9, 0x99, 0xa2, 0xa0, 0x6a, 0x3b, 0x7e, 0x34, 0x16, 0xf1, 0x11, 0xcc, 0xa4, 0x84, 0x54, 0x66, + 0x53, 0x42, 0x7e, 0x94, 0x9e, 0x12, 0x52, 0xc3, 0xa6, 0x1f, 0xcb, 0xa6, 0xe7, 0xb7, 0xf8, 0x4b, + 0x65, 0x86, 0xcc, 0x67, 0xba, 0xd4, 0xbf, 0x4c, 0xa6, 0x4b, 0x23, 0x2d, 0xd3, 0xe5, 0x3d, 0xa8, + 0x60, 0x0e, 0x82, 0x75, 0xee, 0x08, 0xe1, 0x88, 0x3c, 0x03, 0x4d, 0x3d, 0x49, 0x61, 0xd7, 0x71, + 0x43, 0x13, 0x7c, 0xf5, 0x67, 0x30, 0x9f, 0x74, 0xb2, 0xf8, 0x4b, 0x4c, 0x3a, 0x91, 0xb9, 0x12, + 0x1b, 0x50, 0x52, 0xfb, 0xc4, 0x18, 0xe4, 0x4f, 0x7d, 0x6f, 0xac, 0x2c, 0xa6, 0xe2, 0x6f, 0x56, + 0x87, 0x6c, 0xe8, 0xc9, 0xca, 0xd9, 0xd0, 0x33, 0x7e, 0x13, 0x2a, 0x1a, 0xa9, 0xb1, 0x37, 0xc8, + 0x36, 0x23, 0x94, 0x10, 0x29, 0xb5, 0xd1, 0x2a, 0x96, 0x25, 0xb4, 0x3b, 0x14, 0xfc, 0x66, 0xe8, + 0xf8, 0x1c, 0xd3, 0xc3, 0x2c, 0x9f, 0x5f, 0x70, 0x3f, 0x50, 0x16, 0xec, 0x66, 0x54, 0x60, 0x12, + 0xdc, 0xf8, 0x6b, 0xb0, 0x94, 0xd8, 0x5b, 0xc9, 0x22, 0xde, 0x82, 0x05, 0x5c, 0x37, 0xe5, 0x61, + 0x4c, 0x26, 0x7f, 0xc8, 0x32, 0xcc, 0xfb, 0x25, 0xe3, 0xbb, 0x35, 0xf1, 0xbd, 0x13, 0xec, 0x24, + 0x63, 0x56, 0x24, 0xec, 0xc8, 0xf7, 0x4e, 0x8c, 0x3f, 0xcf, 0x41, 0x6e, 0xd7, 0x9b, 0xe8, 0x41, + 0x35, 0x99, 0xb9, 0xa0, 0x1a, 0xa9, 0x59, 0x59, 0x91, 0xe6, 0x24, 0x85, 0x61, 0x34, 0x3b, 0x2b, + 0xed, 0xe9, 0x01, 0xd4, 0x05, 0x9f, 0x08, 0x3d, 0xa1, 0x9a, 0x5e, 0xda, 0x3e, 0x89, 0x9a, 0x39, + 0x3a, 0x7c, 0xf6, 0x38, 0xec, 0x7b, 0x3b, 0x04, 0x67, 0xcb, 0x90, 0x8b, 0xf4, 0x02, 0x2c, 0x16, + 0x9f, 0x6c, 0x15, 0x16, 0x30, 0x28, 0xf2, 0x5a, 0xba, 0xd0, 0xe4, 0x17, 0xfb, 0x26, 0x2c, 0x25, + 0xdb, 0x25, 0x56, 0x24, 0x65, 0x23, 0xbd, 0x61, 0xe4, 0x49, 0xb7, 0x41, 0xf0, 0x11, 0xc2, 0x91, + 0x9e, 0xf8, 0x53, 0xce, 0xb1, 0x48, 0x63, 0x7a, 0xa5, 0x04, 0xd3, 0xbb, 0x07, 0x95, 0x70, 0x74, + 0x61, 0x4d, 0xec, 0xeb, 0x91, 0x67, 0x0f, 0xe5, 0xf9, 0x86, 0x70, 0x74, 0x71, 0x44, 0x10, 0xf6, + 0x08, 0x60, 0x3c, 0x99, 0xc8, 0xb3, 0x87, 0x56, 0xdc, 0x98, 0x94, 0xf7, 0x8f, 0x8e, 0x88, 0xe4, + 0xcc, 0xf2, 0x78, 0x32, 0xa1, 0x3f, 0xd9, 0x36, 0xd4, 0x53, 0x53, 0xb8, 0xee, 0xaa, 0x18, 0x3e, + 0x6f, 0xb2, 0x91, 0x72, 0x38, 0x6b, 0x03, 0x1d, 0xb6, 0xfe, 0x7d, 0x60, 0xbf, 0x60, 0x22, 0x55, + 0x1f, 0xca, 0xd1, 0xf8, 0xf4, 0x3c, 0x24, 0x8c, 0xca, 0xad, 0x24, 0xf2, 0x90, 0xda, 0xc3, 0xa1, + 0x2f, 0xf8, 0x22, 0x5d, 0x98, 0x11, 0xcb, 0x07, 0xed, 0xc6, 0x6c, 0x13, 0xdf, 0x37, 0xfe, 0x32, + 0x03, 0x05, 0x4a, 0x8a, 0x7a, 0x1b, 0x1a, 0x84, 0x1f, 0x05, 0x28, 0x49, 0xc7, 0x1b, 0xdd, 0xbb, + 0x7d, 0x19, 0x9b, 0x24, 0x8e, 0x85, 0x96, 0xd0, 0x99, 0x8d, 0x76, 0x5e, 0x4b, 0xea, 0xbc, 0x07, + 0xe5, 0xa8, 0x6b, 0x8d, 0x74, 0x4a, 0xaa, 0x67, 0xf6, 0x3a, 0xe4, 0xcf, 0xbd, 0x89, 0x32, 0x71, + 0x40, 0xbc, 0x92, 0x26, 0xc2, 0xe3, 0xb1, 0x88, 0x3e, 0x68, 0xf0, 0x52, 0x35, 0x8f, 0x3a, 0x41, + 0x32, 0x98, 0x9f, 0xe3, 0x42, 0xca, 0x1c, 0x8f, 0xa1, 0x21, 0xf8, 0x80, 0xe6, 0x00, 0xbf, 0xf9, + 0xd2, 0xfc, 0xba, 0x90, 0xf0, 0x06, 0xa3, 0xe9, 0x90, 0xeb, 0x06, 0x26, 0x8c, 0x96, 0x91, 0x70, + 0x25, 0x59, 0x1b, 0x7f, 0x90, 0x21, 0xfe, 0x22, 0xda, 0x65, 0x0f, 0x20, 0x2f, 0xee, 0xb7, 0x19, + 0x03, 0x68, 0x14, 0x1e, 0x2d, 0xf0, 0x4c, 0xc4, 0xc0, 0x2c, 0xe8, 0xe9, 0x38, 0xd9, 0x7a, 0xcd, + 0xac, 0xb8, 0xd3, 0x71, 0x64, 0xa3, 0xf9, 0x9a, 0x9a, 0xd6, 0x8c, 0x7d, 0x83, 0x66, 0x1f, 0x1d, + 0xd3, 0x0d, 0x2d, 0xec, 0x26, 0x9f, 0xb8, 0x31, 0x95, 0x14, 0x38, 0x3c, 0xe3, 0x5a, 0xb8, 0xcd, + 0x1f, 0x65, 0xa1, 0x96, 0x18, 0x11, 0xc6, 0x1d, 0x89, 0x0b, 0x80, 0x8c, 0xeb, 0x72, 0xbf, 0x41, + 0x80, 0xa4, 0xa0, 0xae, 0xad, 0x53, 0x36, 0xb1, 0x4e, 0x91, 0xab, 0x3f, 0xa7, 0xbb, 0xfa, 0x1f, + 0x43, 0x39, 0x4e, 0xe4, 0x4d, 0x0e, 0x49, 0xf4, 0xa7, 0x82, 0xc4, 0x63, 0xa4, 0x38, 0x38, 0xa0, + 0xa0, 0x07, 0x07, 0x7c, 0x4f, 0xf3, 0x25, 0x2f, 0x60, 0x33, 0x46, 0xda, 0x8a, 0xfe, 0x52, 0x3c, + 0xc9, 0xc6, 0x47, 0x50, 0xd1, 0x06, 0xaf, 0xfb, 0x8c, 0x33, 0x09, 0x9f, 0x71, 0x94, 0xce, 0x91, + 0x8d, 0xd3, 0x39, 0x8c, 0xdf, 0xce, 0x42, 0x4d, 0x9c, 0x2f, 0xc7, 0x3d, 0x3b, 0xf2, 0x46, 0xce, + 0x00, 0x8d, 0xed, 0xd1, 0x09, 0x93, 0x82, 0x96, 0x3a, 0x67, 0xf2, 0x88, 0x91, 0x9c, 0xa5, 0x67, + 0xad, 0x11, 0x93, 0x8e, 0xb2, 0xd6, 0x0c, 0xa8, 0x09, 0xc6, 0x78, 0x62, 0x07, 0x5c, 0x4b, 0x33, + 0x36, 0x2b, 0xa7, 0x9c, 0x6f, 0xda, 0x01, 0x71, 0xc8, 0x6f, 0xc2, 0x92, 0xc0, 0xc1, 0x84, 0x9d, + 0xb1, 0x33, 0x1a, 0x39, 0x84, 0x49, 0x16, 0x9c, 0xe6, 0x29, 0xe7, 0xa6, 0x1d, 0xf2, 0x7d, 0x51, + 0x20, 0xb3, 0x92, 0x4b, 0x43, 0x27, 0xb0, 0x4f, 0xe2, 0xe8, 0xb0, 0xe8, 0x1b, 0x5d, 0x64, 0xf6, + 0x95, 0xe6, 0x22, 0xa3, 0xcc, 0xbd, 0xca, 0xd8, 0xbe, 0x8a, 0x5c, 0x64, 0x33, 0x94, 0x54, 0x9c, + 0xa5, 0x24, 0xe3, 0x3f, 0x66, 0xa1, 0xa2, 0x91, 0xe5, 0xab, 0xdc, 0xae, 0x77, 0xe7, 0x9c, 0x23, + 0x65, 0xdd, 0x0f, 0xf2, 0x66, 0xb2, 0x4b, 0xf4, 0xa4, 0x53, 0xfe, 0xb3, 0x46, 0xc0, 0x77, 0xa0, + 0x2c, 0x4e, 0xdd, 0x7b, 0x68, 0x6b, 0x94, 0xd9, 0xfb, 0x08, 0x38, 0x9a, 0x9e, 0xa8, 0xc2, 0x27, + 0x58, 0x58, 0x88, 0x0b, 0x9f, 0x88, 0xc2, 0x17, 0x85, 0x84, 0x7e, 0x07, 0xaa, 0xb2, 0x55, 0xdc, + 0x53, 0x9c, 0x6e, 0x7c, 0xea, 0x13, 0xfb, 0x6d, 0x56, 0xa8, 0x3b, 0xda, 0x7c, 0x59, 0xf1, 0x89, + 0xaa, 0x58, 0x7a, 0x59, 0xc5, 0x27, 0xf4, 0x61, 0xec, 0x44, 0x51, 0xb6, 0x18, 0xc5, 0xa1, 0xf8, + 0xd8, 0x23, 0x58, 0x52, 0xec, 0x6a, 0xea, 0xda, 0xae, 0xeb, 0x4d, 0xdd, 0x01, 0x57, 0x79, 0x1e, + 0x4c, 0x16, 0x1d, 0xc7, 0x25, 0xc6, 0x30, 0x4a, 0x04, 0xa4, 0x68, 0x90, 0x87, 0x50, 0x20, 0xb9, + 0x9c, 0x84, 0x8f, 0x74, 0xc6, 0x45, 0x28, 0xec, 0x01, 0x14, 0x48, 0x3c, 0xcf, 0xde, 0xc8, 0x6c, + 0x08, 0xc1, 0xd8, 0x80, 0x06, 0x8a, 0x98, 0x1a, 0xc7, 0x7d, 0x91, 0x54, 0x62, 0x2c, 0x03, 0x3b, + 0xa0, 0x43, 0xa4, 0x47, 0x29, 0xfd, 0xd7, 0x1c, 0x54, 0x34, 0xb0, 0x60, 0x8b, 0x18, 0xd7, 0x62, + 0x0d, 0x1d, 0x7b, 0xcc, 0x95, 0x4b, 0xa7, 0x66, 0xd6, 0x10, 0xba, 0x2d, 0x81, 0xe2, 0x52, 0xb0, + 0x2f, 0xce, 0x2c, 0x6f, 0x1a, 0x5a, 0x43, 0x7e, 0xe6, 0x73, 0x2e, 0x85, 0xa5, 0xaa, 0x7d, 0x71, + 0x76, 0x38, 0x0d, 0xb7, 0x11, 0x26, 0xb0, 0x04, 0x51, 0x6b, 0x58, 0x32, 0x14, 0x63, 0x6c, 0x5f, + 0xc5, 0x58, 0x32, 0x1e, 0x88, 0x96, 0x28, 0x1f, 0xc5, 0x03, 0x91, 0xda, 0x32, 0xcb, 0xc9, 0x0b, + 0xf3, 0x9c, 0xfc, 0xdb, 0xb0, 0x4a, 0x9c, 0x5c, 0xf2, 0x08, 0x6b, 0x86, 0xa4, 0x96, 0xb1, 0x54, + 0x4e, 0x52, 0x93, 0xbf, 0x9a, 0x62, 0x06, 0xea, 0x7c, 0x04, 0xce, 0x8f, 0xe9, 0x44, 0x65, 0x4c, + 0x31, 0x33, 0xd9, 0x78, 0xcf, 0xf9, 0x31, 0x17, 0x98, 0xe8, 0x6f, 0xd6, 0x31, 0x65, 0xe4, 0xf1, + 0xd8, 0x71, 0x67, 0x31, 0xed, 0xab, 0x24, 0x66, 0x59, 0x62, 0xda, 0x57, 0x3a, 0xe6, 0xfb, 0xb0, + 0x36, 0xe6, 0x43, 0xc7, 0x4e, 0x36, 0x6b, 0xc5, 0x12, 0xc4, 0x32, 0x15, 0x6b, 0x75, 0x7a, 0xa4, + 0x41, 0x8a, 0xd5, 0xf8, 0xb1, 0x37, 0x3e, 0x71, 0xe8, 0xf2, 0x24, 0x0f, 0x78, 0xde, 0xac, 0xbb, + 0xd3, 0xf1, 0x0f, 0x11, 0x2c, 0xaa, 0x04, 0x46, 0x0d, 0x2a, 0xbd, 0xd0, 0x9b, 0xa8, 0x6d, 0xae, + 0x43, 0x95, 0x3e, 0x65, 0x16, 0xcf, 0x1d, 0xb8, 0x8d, 0xb4, 0xd9, 0xf7, 0x26, 0xde, 0xc8, 0x3b, + 0xbb, 0x4e, 0x18, 0x94, 0xfe, 0x73, 0x06, 0x96, 0x12, 0xa5, 0xf2, 0x9c, 0x7f, 0x9b, 0x0e, 0x56, + 0x94, 0x8a, 0x41, 0xe4, 0xbc, 0xa8, 0x5d, 0x3e, 0x84, 0x48, 0xa7, 0x4a, 0xa5, 0x67, 0xb4, 0xe3, + 0x14, 0x62, 0x55, 0x91, 0x68, 0xbb, 0x35, 0x4f, 0xdb, 0xb2, 0xbe, 0x4a, 0x2e, 0x56, 0x4d, 0xfc, + 0xaa, 0x8c, 0x0e, 0x1f, 0xca, 0x29, 0xe7, 0x92, 0xf1, 0xaf, 0xba, 0xf1, 0x49, 0x8d, 0x20, 0xb6, + 0x48, 0x05, 0xc6, 0xbf, 0xc8, 0x00, 0xc4, 0xa3, 0xc3, 0x08, 0xdc, 0xe8, 0x02, 0xa5, 0xd7, 0x79, + 0xb4, 0xcb, 0xf2, 0x0d, 0xa8, 0x46, 0x81, 0x78, 0xf1, 0x95, 0x5c, 0x51, 0x30, 0x71, 0x2f, 0xbf, + 0x03, 0x8d, 0xb3, 0x91, 0x77, 0x82, 0xa2, 0x93, 0xbc, 0x40, 0x29, 0x97, 0xa9, 0x4e, 0x60, 0x75, + 0x2d, 0xc6, 0x17, 0x78, 0x3e, 0x35, 0x56, 0x4f, 0xbf, 0x8e, 0x8d, 0xdf, 0xc9, 0x46, 0x11, 0x49, + 0xf1, 0x4a, 0xbc, 0x58, 0xcf, 0xf8, 0x79, 0x1c, 0xdb, 0x2f, 0x72, 0xe8, 0x7c, 0x04, 0x75, 0x9f, + 0xb8, 0xa3, 0x62, 0x9d, 0xf9, 0x17, 0xb0, 0xce, 0x9a, 0x9f, 0xb8, 0x72, 0xbf, 0x0e, 0x4d, 0x7b, + 0x78, 0xc1, 0xfd, 0xd0, 0x41, 0xb3, 0x31, 0x0a, 0x6a, 0x32, 0x06, 0x48, 0x83, 0xa3, 0x44, 0xf4, + 0x0e, 0x34, 0x64, 0x66, 0x59, 0x84, 0x29, 0xdf, 0xaa, 0x88, 0xc1, 0x02, 0xd1, 0xf8, 0xd7, 0x2a, + 0x04, 0x2a, 0xb9, 0xbb, 0x2f, 0x5e, 0x15, 0x7d, 0x86, 0xd9, 0x79, 0x97, 0x95, 0x24, 0x24, 0x69, + 0x8d, 0x96, 0xfc, 0x88, 0x80, 0xd2, 0x16, 0x9d, 0x5c, 0xd6, 0xfc, 0xab, 0x2c, 0xab, 0xf1, 0x27, + 0x19, 0x28, 0xee, 0x7a, 0x13, 0xa1, 0x97, 0x0b, 0x79, 0x0e, 0x8f, 0x49, 0xe4, 0x86, 0x58, 0x10, + 0x9f, 0xdd, 0xe1, 0x8b, 0x33, 0x31, 0x52, 0xe5, 0x8d, 0x5a, 0x52, 0xde, 0xf8, 0x1e, 0xdc, 0x41, + 0x27, 0x8f, 0xef, 0x4d, 0x3c, 0x5f, 0x1c, 0x55, 0x7b, 0x44, 0x72, 0x87, 0xe7, 0x86, 0xe7, 0x8a, + 0x77, 0xde, 0x3e, 0xe5, 0xfc, 0x48, 0xc3, 0xd8, 0x8f, 0x10, 0x30, 0x45, 0x69, 0x14, 0x5e, 0x58, + 0xa4, 0x2a, 0x4a, 0xc1, 0x88, 0x38, 0x6a, 0x43, 0x14, 0x74, 0x10, 0x8e, 0xa2, 0x91, 0xf1, 0x5d, + 0x28, 0x47, 0x56, 0x07, 0xf6, 0x2e, 0x94, 0xcf, 0xbd, 0x89, 0x34, 0x4d, 0x64, 0x12, 0xd9, 0x2a, + 0x72, 0xd6, 0x66, 0xe9, 0x9c, 0xfe, 0x08, 0x8c, 0x3f, 0x2f, 0x42, 0xb1, 0xeb, 0x5e, 0x78, 0xce, + 0x00, 0x83, 0xa8, 0xc6, 0x7c, 0xec, 0xa9, 0xf4, 0x56, 0xf1, 0x37, 0x06, 0x4a, 0xc4, 0x2f, 0x4e, + 0xe4, 0x64, 0xa0, 0x44, 0xf4, 0xd6, 0xc4, 0x0a, 0x2c, 0xf8, 0xfa, 0x93, 0x11, 0x05, 0x1f, 0xc3, + 0x3a, 0x23, 0xa5, 0xad, 0xa0, 0xa5, 0x07, 0x8b, 0xb6, 0xe8, 0x29, 0x03, 0x5c, 0x32, 0x4a, 0x37, + 0x2a, 0x23, 0x04, 0x17, 0xec, 0x35, 0x28, 0xca, 0xe4, 0x10, 0x0a, 0xb5, 0xa7, 0x38, 0x4c, 0x09, + 0x42, 0x6a, 0xf0, 0x39, 0x39, 0xe9, 0x22, 0x89, 0x4a, 0xe8, 0xe9, 0x12, 0xb8, 0x2d, 0x68, 0xed, + 0x1e, 0x54, 0x08, 0x9f, 0x50, 0x4a, 0x32, 0xec, 0x09, 0x41, 0x88, 0x90, 0xf2, 0xf2, 0x4a, 0x39, + 0xf5, 0xe5, 0x15, 0x8c, 0x92, 0x8b, 0xb8, 0x2c, 0x4d, 0x11, 0xe8, 0xbd, 0x0d, 0x0d, 0xae, 0x9e, + 0x1d, 0x92, 0xca, 0x3d, 0x65, 0xdf, 0x29, 0xe5, 0xfe, 0x4d, 0xa8, 0x9d, 0xda, 0xa3, 0xd1, 0x89, + 0x3d, 0x78, 0x4e, 0x3a, 0x69, 0x95, 0xcc, 0x70, 0x0a, 0x88, 0x4a, 0xe9, 0x3d, 0xa8, 0x68, 0xbb, + 0x8c, 0x31, 0x4d, 0x79, 0x13, 0xe2, 0xfd, 0x9d, 0x35, 0x35, 0xd5, 0x5f, 0xc1, 0xd4, 0xa4, 0xc5, + 0x76, 0x35, 0x92, 0xb1, 0x5d, 0x77, 0x90, 0x9b, 0xca, 0xf8, 0x9f, 0x26, 0x3d, 0xee, 0x60, 0x0f, + 0x87, 0x18, 0xff, 0x43, 0x2f, 0xa9, 0xe1, 0xe2, 0x51, 0xf9, 0x22, 0x09, 0xb5, 0x04, 0x23, 0x94, + 0xbb, 0x64, 0x2f, 0x9d, 0xd8, 0xce, 0x10, 0x63, 0x69, 0x49, 0x8d, 0x2d, 0xda, 0xe3, 0xf0, 0xc8, + 0x76, 0x86, 0xec, 0x3e, 0x54, 0x55, 0x31, 0xde, 0x8e, 0x4b, 0xb4, 0xfe, 0xb2, 0x58, 0xdc, 0x89, + 0x06, 0xd4, 0x22, 0x8c, 0x71, 0x9c, 0x42, 0x57, 0x91, 0x28, 0x48, 0x07, 0xef, 0x61, 0x4c, 0x45, + 0xc8, 0x31, 0x51, 0xae, 0xfe, 0xe4, 0x8e, 0x9c, 0xab, 0xa4, 0x52, 0xf5, 0x3f, 0x79, 0x69, 0x08, + 0x53, 0x08, 0x62, 0xe4, 0x2c, 0x5a, 0x4d, 0x08, 0x62, 0x12, 0x15, 0x9d, 0x45, 0x84, 0xc0, 0xbe, + 0xab, 0x29, 0x52, 0x2d, 0x44, 0x7e, 0x6d, 0xa6, 0xfd, 0x9b, 0x52, 0x09, 0xee, 0x02, 0x38, 0x81, + 0xb8, 0x65, 0x02, 0xee, 0x0e, 0x31, 0xe7, 0xad, 0x64, 0x96, 0x9d, 0xe0, 0x19, 0x01, 0xbe, 0x5a, + 0x0d, 0xab, 0x0d, 0x55, 0x7d, 0x9a, 0xac, 0x04, 0xf9, 0xc3, 0xa3, 0xce, 0x41, 0xf3, 0x16, 0xab, + 0x40, 0xb1, 0xd7, 0xe9, 0xf7, 0xf7, 0xd0, 0xe5, 0x54, 0x85, 0x52, 0x94, 0xb9, 0x93, 0x15, 0x5f, + 0xed, 0xad, 0xad, 0xce, 0x51, 0xbf, 0xb3, 0xdd, 0xcc, 0xfd, 0x20, 0x5f, 0xca, 0x36, 0x73, 0xc6, + 0x5f, 0xe4, 0xa0, 0xa2, 0xad, 0xc2, 0x8b, 0x99, 0xf1, 0x5d, 0x00, 0x54, 0x69, 0xe2, 0xf0, 0xb0, + 0xbc, 0x59, 0x16, 0x10, 0xda, 0x7c, 0xdd, 0x58, 0x9e, 0xa3, 0x57, 0x43, 0x94, 0xb1, 0xfc, 0x4d, + 0xa8, 0xd1, 0x03, 0x1c, 0xba, 0xe3, 0xb0, 0x60, 0x56, 0x09, 0x28, 0x59, 0x35, 0xa6, 0xfe, 0x21, + 0x12, 0x26, 0x85, 0xc8, 0x74, 0x7c, 0x02, 0x61, 0x5a, 0x08, 0xe6, 0xf4, 0x04, 0xde, 0xe8, 0x82, + 0x13, 0x06, 0x49, 0x84, 0x15, 0x09, 0xeb, 0xcb, 0xdc, 0x43, 0xc9, 0x0f, 0xb5, 0xdc, 0xb3, 0x82, + 0x59, 0x25, 0xa0, 0xec, 0xe8, 0x9b, 0x8a, 0x80, 0x4a, 0x48, 0x40, 0x6b, 0xf3, 0xd4, 0x90, 0x20, + 0x9e, 0xbd, 0x39, 0x7b, 0x56, 0x19, 0x09, 0xe3, 0x6b, 0xf3, 0xf5, 0x5e, 0x6e, 0xd7, 0x62, 0xef, + 0x02, 0x1b, 0x4f, 0x26, 0x56, 0x8a, 0xa5, 0x29, 0x6f, 0x36, 0xc6, 0x93, 0x49, 0x5f, 0x33, 0xc4, + 0x7c, 0x05, 0x46, 0xb0, 0xcf, 0x81, 0xb5, 0xc5, 0x01, 0xc6, 0x21, 0x46, 0x26, 0xd4, 0x98, 0x2d, + 0x67, 0x74, 0xb6, 0x9c, 0xc2, 0xfd, 0xb2, 0xa9, 0xdc, 0xef, 0x45, 0x7c, 0xc2, 0xd8, 0x81, 0xca, + 0x91, 0xf6, 0xbc, 0xcf, 0x7d, 0x71, 0x43, 0xa8, 0x87, 0x7d, 0xe8, 0xee, 0x20, 0xe3, 0x96, 0x2f, + 0xdf, 0xf3, 0xd1, 0x46, 0x93, 0xd5, 0x46, 0x63, 0xfc, 0xf3, 0x0c, 0x3d, 0x9d, 0x10, 0x0d, 0x3e, + 0x7e, 0x51, 0x48, 0xf9, 0x81, 0xe2, 0x14, 0xd1, 0x8a, 0xf2, 0xff, 0xc8, 0xec, 0x4e, 0x1c, 0x9a, + 0xe5, 0x9d, 0x9e, 0x06, 0x5c, 0x25, 0x3b, 0x55, 0x10, 0x76, 0x88, 0x20, 0x25, 0x7c, 0x0b, 0x09, + 0xdf, 0xa1, 0xf6, 0x03, 0x99, 0xf4, 0x24, 0x84, 0xef, 0x7d, 0xfb, 0x4a, 0xf6, 0x1a, 0x08, 0x11, + 0x44, 0x1a, 0xaa, 0x55, 0x8a, 0x57, 0xf4, 0x6d, 0xfc, 0x13, 0x99, 0xc5, 0x3a, 0xbb, 0xbe, 0x0f, + 0xa1, 0x14, 0xb5, 0x9a, 0xbc, 0x61, 0x15, 0x66, 0x54, 0x2e, 0xee, 0x71, 0xd4, 0xca, 0x13, 0x23, + 0xa6, 0xc3, 0x85, 0xce, 0x86, 0xae, 0x36, 0xea, 0x6f, 0x00, 0x3b, 0x75, 0xfc, 0x59, 0x64, 0x3a, + 0x6c, 0x4d, 0x2c, 0xd1, 0xb0, 0x8d, 0x63, 0x58, 0x52, 0x5c, 0x42, 0xd3, 0x08, 0x92, 0x9b, 0x97, + 0x79, 0x09, 0x93, 0xcf, 0xce, 0x31, 0x79, 0xe3, 0xa7, 0x79, 0x28, 0xaa, 0xa7, 0xb2, 0xd2, 0x9e, + 0x77, 0x2a, 0x27, 0x9f, 0x77, 0x6a, 0x25, 0x9e, 0x02, 0xc1, 0xad, 0x97, 0xf7, 0xfd, 0x3b, 0xb3, + 0x57, 0xb6, 0x66, 0x34, 0x4f, 0x5c, 0xdb, 0xab, 0x90, 0x9f, 0xd8, 0xe1, 0x39, 0x1a, 0xc8, 0x88, + 0x78, 0xf0, 0x5b, 0x19, 0xd3, 0x0b, 0x49, 0x63, 0x7a, 0xda, 0x53, 0x58, 0x24, 0x92, 0xce, 0x3d, + 0x85, 0x75, 0x07, 0x48, 0xbe, 0xd0, 0xc2, 0x8c, 0x4a, 0x08, 0x10, 0x77, 0x51, 0x52, 0x1c, 0x29, + 0xcd, 0x8a, 0x23, 0xaf, 0x2c, 0x2a, 0x7c, 0x1b, 0x16, 0x28, 0x8d, 0x5c, 0xa6, 0xb2, 0xa9, 0x0b, + 0x45, 0xae, 0xa1, 0xfa, 0x9f, 0x62, 0x8b, 0x4d, 0x89, 0xab, 0xbf, 0x2b, 0x53, 0x49, 0xbc, 0x2b, + 0xa3, 0x1b, 0xf9, 0xab, 0x49, 0x23, 0xff, 0x03, 0x68, 0x46, 0x0b, 0x8a, 0x26, 0x33, 0x37, 0x90, + 0x89, 0x32, 0x75, 0x05, 0x17, 0x5c, 0xf2, 0x20, 0x88, 0x2f, 0xc4, 0x7a, 0xe2, 0x42, 0x14, 0x3c, + 0xac, 0x1d, 0x86, 0x7c, 0x3c, 0x09, 0xe5, 0x85, 0x88, 0xa1, 0xf4, 0xfa, 0x00, 0x93, 0x49, 0x9e, + 0x35, 0x28, 0x77, 0x0f, 0xac, 0x9d, 0xbd, 0xee, 0xd3, 0xdd, 0x7e, 0x33, 0x23, 0x3e, 0x7b, 0xc7, + 0x5b, 0x5b, 0x9d, 0xce, 0x36, 0xde, 0x38, 0x00, 0x0b, 0x3b, 0xed, 0xae, 0xb8, 0x7d, 0x72, 0xc6, + 0xef, 0x65, 0xa1, 0xa2, 0x35, 0xcf, 0xde, 0x8f, 0x56, 0x85, 0x9e, 0x1e, 0xb9, 0x3b, 0x3f, 0x84, + 0x0d, 0xc5, 0x8a, 0xb5, 0x65, 0x89, 0x1e, 0xfe, 0xca, 0xde, 0xf8, 0xf0, 0x17, 0x7b, 0x1b, 0x1a, + 0x36, 0xb5, 0x10, 0xad, 0x82, 0x34, 0x07, 0x4b, 0xb0, 0x5c, 0x04, 0x0c, 0xae, 0x8b, 0xef, 0x13, + 0x81, 0x97, 0x57, 0xf1, 0x6c, 0xd1, 0x95, 0x82, 0x8b, 0x55, 0x3c, 0xb5, 0x9d, 0xd1, 0xd4, 0xe7, + 0xd2, 0x7d, 0x1b, 0xdd, 0xcc, 0x04, 0x35, 0x55, 0xb1, 0xf1, 0x01, 0x40, 0x3c, 0xe6, 0xe4, 0xe2, + 0xdc, 0x4a, 0x2e, 0x4e, 0x46, 0x5b, 0x9c, 0xac, 0xb1, 0x4d, 0x6c, 0x44, 0x2e, 0x74, 0xe4, 0xa9, + 0xfe, 0x26, 0x28, 0x8b, 0x94, 0x85, 0xe1, 0xad, 0x93, 0x11, 0x0f, 0x55, 0x3a, 0xec, 0xa2, 0x2c, + 0xe9, 0x46, 0x05, 0x2a, 0x3b, 0x3d, 0x6e, 0x25, 0xe6, 0x46, 0x92, 0x24, 0x67, 0xb9, 0x91, 0x44, + 0x35, 0xa3, 0x72, 0x63, 0x1d, 0x5a, 0xdb, 0x5c, 0xb4, 0xd6, 0x1e, 0x8d, 0x66, 0x86, 0x63, 0xdc, + 0x81, 0xdb, 0x29, 0x65, 0xd2, 0x08, 0xf1, 0x31, 0xac, 0xb4, 0x29, 0xf3, 0xf5, 0xab, 0x4a, 0x71, + 0x31, 0x5a, 0xb0, 0x3a, 0xdb, 0xa4, 0xec, 0x6c, 0x07, 0x16, 0xb7, 0xf9, 0xc9, 0xf4, 0x6c, 0x8f, + 0x5f, 0xc4, 0x1d, 0x31, 0xc8, 0x07, 0xe7, 0xde, 0xa5, 0x5c, 0x1f, 0xfc, 0x1b, 0x03, 0xc9, 0x04, + 0x8e, 0x15, 0x4c, 0xf8, 0x40, 0x59, 0x44, 0x11, 0xd2, 0x9b, 0xf0, 0x81, 0xf1, 0x3e, 0x30, 0xbd, + 0x1d, 0xb9, 0x5e, 0x42, 0x4b, 0x98, 0x9e, 0x58, 0xc1, 0x75, 0x10, 0xf2, 0xb1, 0x7a, 0xd9, 0x06, + 0x82, 0xe9, 0x49, 0x8f, 0x20, 0xc6, 0x3b, 0x50, 0x3d, 0xb2, 0xaf, 0x4d, 0xfe, 0xb9, 0x4c, 0xde, + 0x58, 0x83, 0xe2, 0xc4, 0xbe, 0x16, 0x6c, 0x20, 0x72, 0x8e, 0x60, 0xb1, 0xf1, 0x87, 0x79, 0x58, + 0x20, 0x4c, 0x76, 0x9f, 0x1e, 0x9f, 0x74, 0x5c, 0x3c, 0x86, 0x8a, 0x51, 0x6a, 0xa0, 0x39, 0x5e, + 0x9a, 0x9d, 0xe7, 0xa5, 0xd2, 0x80, 0xa6, 0x1e, 0xdd, 0x50, 0x66, 0x6c, 0x77, 0x3a, 0x56, 0x2f, + 0x6d, 0x24, 0xd3, 0x3f, 0xf3, 0xf1, 0xe3, 0xa2, 0x94, 0x1b, 0x97, 0x74, 0x34, 0xc6, 0xba, 0x08, + 0x8d, 0x4e, 0x5d, 0x11, 0x92, 0x5d, 0xea, 0xa0, 0x54, 0x85, 0xa7, 0xa8, 0xd2, 0x82, 0x92, 0x0a, + 0xcf, 0x9c, 0x62, 0x53, 0x7a, 0xb9, 0x62, 0x43, 0x96, 0xb5, 0x17, 0x28, 0x36, 0xf0, 0x0a, 0x8a, + 0xcd, 0x2b, 0x38, 0xf9, 0x6e, 0x43, 0x09, 0xef, 0x7d, 0x8d, 0x7b, 0x8a, 0xfb, 0x5e, 0x70, 0xcf, + 0xef, 0x68, 0xa2, 0x3f, 0x45, 0x18, 0xdc, 0x89, 0x8f, 0x89, 0xc9, 0x3f, 0xff, 0xe5, 0x38, 0x4f, + 0x3e, 0x83, 0xa2, 0x84, 0x0a, 0x82, 0x76, 0xed, 0xb1, 0x7a, 0xb7, 0x08, 0xff, 0x16, 0xcb, 0x86, + 0x8f, 0xad, 0x7c, 0x3e, 0x75, 0x7c, 0x3e, 0x54, 0x2f, 0x5b, 0x38, 0x78, 0x46, 0x05, 0x44, 0x4c, + 0x50, 0xa8, 0x21, 0xae, 0x77, 0xe9, 0xca, 0xbc, 0xf6, 0xa2, 0x13, 0x3c, 0x13, 0x9f, 0x06, 0x83, + 0x26, 0xbe, 0x5c, 0x36, 0xf1, 0x7c, 0x75, 0x39, 0x19, 0x3f, 0xcd, 0x40, 0x53, 0x9e, 0xae, 0xa8, + 0x4c, 0xd7, 0x02, 0x0a, 0x37, 0x39, 0xc4, 0x5f, 0xfc, 0x4e, 0x85, 0x01, 0x35, 0x34, 0x7e, 0x44, + 0x37, 0x15, 0x19, 0x6f, 0x2a, 0x02, 0xb8, 0x23, 0x6f, 0xab, 0xd7, 0xa1, 0xa2, 0xa2, 0x5c, 0xc7, + 0xce, 0x48, 0xbd, 0x23, 0x4c, 0x61, 0xae, 0xfb, 0xce, 0x48, 0x5d, 0x74, 0xbe, 0x2d, 0xd3, 0xd4, + 0x32, 0x78, 0xd1, 0x99, 0x76, 0xc8, 0x8d, 0x7f, 0x9f, 0x81, 0x45, 0x6d, 0x2a, 0xf2, 0xdc, 0x7e, + 0x08, 0xd5, 0xe8, 0xc9, 0x40, 0x1e, 0x49, 0x5e, 0x6b, 0x49, 0x46, 0x13, 0x57, 0xab, 0x0c, 0x22, + 0x48, 0x20, 0x06, 0x33, 0xb4, 0xaf, 0x71, 0xbc, 0xc1, 0x74, 0xac, 0x94, 0x9b, 0xa1, 0x7d, 0xbd, + 0xc3, 0x79, 0x6f, 0x3a, 0x16, 0xaa, 0xeb, 0x25, 0xe7, 0xcf, 0x23, 0x04, 0x92, 0xb9, 0x40, 0xc0, + 0x24, 0x86, 0x01, 0xb5, 0xb1, 0xe7, 0x86, 0xe7, 0x11, 0x8a, 0x94, 0x3a, 0x11, 0x48, 0x38, 0xc6, + 0x9f, 0x65, 0x61, 0x89, 0x4c, 0x6c, 0xd2, 0xb4, 0x29, 0x59, 0x57, 0x0b, 0x16, 0xc8, 0xda, 0x48, + 0xcc, 0x6b, 0xf7, 0x96, 0x29, 0xbf, 0xd9, 0xb7, 0x5f, 0xd1, 0x2c, 0xa8, 0x32, 0xe1, 0x6e, 0x58, + 0xfe, 0xdc, 0xfc, 0xf2, 0xdf, 0xbc, 0xbc, 0x69, 0x1e, 0xb7, 0x42, 0x9a, 0xc7, 0xed, 0x55, 0xfc, + 0x5c, 0x73, 0xe9, 0x62, 0x45, 0x89, 0xa3, 0xa5, 0x8b, 0xbd, 0x0f, 0x6b, 0x09, 0x1c, 0xe4, 0xd6, + 0xce, 0xa9, 0xc3, 0xd5, 0xb3, 0x01, 0xcb, 0x1a, 0x76, 0x4f, 0x95, 0x6d, 0x16, 0xa1, 0x10, 0x0c, + 0xbc, 0x09, 0x37, 0x56, 0x61, 0x39, 0xb9, 0xaa, 0xf2, 0x9a, 0xf8, 0xfd, 0x0c, 0xb4, 0x64, 0x7c, + 0x84, 0xe3, 0x9e, 0xed, 0x3a, 0x41, 0xe8, 0xf9, 0xd1, 0xd3, 0x7a, 0x77, 0x01, 0x82, 0xd0, 0xf6, + 0xa5, 0xb6, 0x29, 0x13, 0xe5, 0x11, 0x82, 0x9a, 0xe4, 0x6d, 0x28, 0x71, 0x77, 0x48, 0x85, 0x44, + 0x0d, 0x45, 0xee, 0x0e, 0x95, 0x1e, 0x3a, 0x27, 0x7f, 0xd7, 0x92, 0xea, 0x85, 0xcc, 0x5b, 0x15, + 0xab, 0xc3, 0x2f, 0xf0, 0xe2, 0xcd, 0x47, 0x79, 0xab, 0xfb, 0xf6, 0x15, 0x46, 0x1b, 0x06, 0xc6, + 0x3f, 0xcc, 0x42, 0x23, 0x1e, 0x1f, 0x25, 0xbd, 0xbf, 0x38, 0x7d, 0xff, 0xbe, 0x24, 0x07, 0x47, + 0xc8, 0xef, 0x9a, 0xe1, 0xb1, 0x44, 0x87, 0xb3, 0xeb, 0x32, 0x03, 0x2a, 0x0a, 0xc3, 0x9b, 0x86, + 0xda, 0x0b, 0x57, 0x65, 0x42, 0x39, 0x9c, 0x86, 0x42, 0xe1, 0x12, 0x9a, 0xa7, 0xe3, 0x4a, 0x95, + 0xa7, 0x60, 0x8f, 0xc3, 0x2e, 0x3e, 0x9c, 0x2d, 0xc0, 0xa2, 0x1a, 0x6d, 0xa4, 0xc0, 0x12, 0xf8, + 0x4d, 0x92, 0xb3, 0x69, 0xe7, 0x50, 0xc6, 0xd6, 0x85, 0x50, 0x7a, 0x43, 0x34, 0x12, 0x42, 0x5f, + 0x87, 0x0a, 0x35, 0x1e, 0x67, 0x07, 0xe6, 0xcd, 0x32, 0xf6, 0x80, 0xe5, 0xd2, 0x08, 0xe4, 0x4d, + 0x13, 0xaa, 0x2f, 0x50, 0x57, 0x18, 0x7e, 0xf0, 0x77, 0x33, 0x70, 0x3b, 0x65, 0xdb, 0xe4, 0x29, + 0xdf, 0x82, 0xc5, 0xd3, 0xa8, 0x50, 0xad, 0x2e, 0x1d, 0xf5, 0x55, 0xc5, 0x56, 0x93, 0x6b, 0x6a, + 0x36, 0x4f, 0x93, 0x80, 0x58, 0xe9, 0xa2, 0x1d, 0x4c, 0x24, 0x80, 0xa2, 0xd2, 0x45, 0xdb, 0x48, + 0xfa, 0xce, 0x11, 0xac, 0x77, 0xae, 0x04, 0xc7, 0xd8, 0xd2, 0x5f, 0x7e, 0x57, 0x64, 0x94, 0x34, + 0x30, 0x67, 0x5e, 0xc9, 0xc0, 0x3c, 0xa4, 0x3c, 0xb7, 0xa8, 0xad, 0x9f, 0xa7, 0x11, 0xbc, 0x40, + 0x45, 0x1d, 0x7a, 0xb9, 0x5e, 0x25, 0xa1, 0x0e, 0xa2, 0x17, 0xeb, 0x8d, 0x00, 0x1a, 0xfb, 0xd3, + 0x51, 0xe8, 0xc4, 0x8f, 0xd8, 0xb3, 0x6f, 0xcb, 0x3a, 0xd8, 0x8f, 0x5a, 0xb5, 0xd4, 0x8e, 0x20, + 0xea, 0x08, 0x17, 0x6b, 0x2c, 0x1a, 0xb2, 0xe6, 0xfb, 0x6b, 0x8c, 0x93, 0x3d, 0x18, 0xb7, 0x61, + 0x2d, 0xfe, 0xa2, 0x65, 0x53, 0x57, 0xcd, 0x3f, 0xcb, 0x50, 0x68, 0x73, 0xf2, 0x41, 0x7d, 0xd6, + 0x81, 0xa5, 0xc0, 0x71, 0xcf, 0x46, 0x5c, 0x6f, 0x3e, 0x90, 0x8b, 0xb0, 0x92, 0x1c, 0x9b, 0x7c, + 0x74, 0xdf, 0x5c, 0xa4, 0x1a, 0x71, 0x6b, 0x01, 0xdb, 0xbc, 0x69, 0x90, 0x31, 0x59, 0xcc, 0xac, + 0xc6, 0xfc, 0xe0, 0xbb, 0x50, 0x4f, 0x76, 0xc4, 0xbe, 0x23, 0x73, 0x3c, 0xe3, 0x51, 0xe5, 0x66, + 0xd2, 0xf5, 0x62, 0x82, 0xa8, 0xc4, 0x6b, 0x1f, 0x18, 0x7f, 0x3f, 0x03, 0x2d, 0x93, 0x0b, 0xca, + 0xd5, 0x46, 0xa9, 0x68, 0xe6, 0xc3, 0xb9, 0x56, 0x6f, 0x9e, 0xab, 0x4a, 0x1d, 0x55, 0x23, 0xfa, + 0xc6, 0x8d, 0x9b, 0xb1, 0x7b, 0x6b, 0x6e, 0x46, 0x9b, 0x25, 0x58, 0x20, 0x14, 0x63, 0x0d, 0x56, + 0xe4, 0x78, 0xd4, 0x58, 0x62, 0xef, 0x61, 0xa2, 0xc7, 0x84, 0xf7, 0x70, 0x1d, 0x5a, 0xf4, 0x42, + 0xa2, 0x3e, 0x09, 0x59, 0x71, 0x1b, 0xd8, 0xbe, 0x3d, 0xb0, 0x7d, 0xcf, 0x73, 0x8f, 0xb8, 0x2f, + 0x03, 0x45, 0x51, 0xc2, 0x44, 0xe7, 0x9a, 0x12, 0x85, 0xe9, 0x4b, 0xbd, 0xeb, 0xe7, 0xb9, 0x2a, + 0x2e, 0x86, 0xbe, 0x0c, 0x13, 0x96, 0x36, 0xed, 0xe7, 0x5c, 0xb5, 0xa4, 0x96, 0xe8, 0x23, 0xa8, + 0x4c, 0xa2, 0x46, 0xd5, 0xba, 0xab, 0x44, 0xf0, 0xf9, 0x6e, 0x4d, 0x1d, 0xdb, 0x78, 0x02, 0xcb, + 0xc9, 0x36, 0x25, 0xeb, 0x58, 0x87, 0xd2, 0x58, 0xc2, 0xe4, 0xe8, 0xa2, 0x6f, 0xe3, 0x77, 0x4b, + 0x50, 0x94, 0xfa, 0x1c, 0xdb, 0x80, 0xfc, 0x40, 0xc5, 0x26, 0xc5, 0xef, 0x8b, 0xc8, 0x52, 0xf5, + 0xff, 0x16, 0x46, 0x28, 0x09, 0x3c, 0xf6, 0x11, 0xd4, 0x93, 0x5e, 0xd1, 0x99, 0x2c, 0xd3, 0xa4, + 0x3b, 0xb3, 0x36, 0x98, 0xf1, 0x7f, 0x95, 0xe3, 0xcb, 0x91, 0x64, 0x86, 0xd2, 0xb9, 0x76, 0x7b, + 0x7a, 0xae, 0x90, 0xb7, 0x83, 0x73, 0xdb, 0x7a, 0xf2, 0xfe, 0x07, 0x32, 0xcd, 0xb4, 0x82, 0xc0, + 0xde, 0xb9, 0xfd, 0xe4, 0xfd, 0x0f, 0x66, 0x25, 0x69, 0xca, 0x34, 0xd4, 0x25, 0xe9, 0x65, 0x28, + 0xd0, 0x03, 0x76, 0x14, 0x64, 0x42, 0x1f, 0xec, 0x31, 0x2c, 0x4b, 0xb5, 0xd5, 0x92, 0xe1, 0xc0, + 0xc4, 0x05, 0x4b, 0x94, 0xda, 0x24, 0xcb, 0x7a, 0x58, 0x44, 0xb6, 0xa1, 0x55, 0x58, 0x38, 0x8f, + 0x5f, 0x23, 0xac, 0x99, 0xf2, 0xcb, 0xf8, 0xb3, 0x02, 0x54, 0xb4, 0x45, 0x61, 0x55, 0x28, 0x99, + 0x9d, 0x5e, 0xc7, 0xfc, 0xa4, 0xb3, 0xdd, 0xbc, 0xc5, 0x1e, 0xc0, 0x5b, 0xdd, 0x83, 0xad, 0x43, + 0xd3, 0xec, 0x6c, 0xf5, 0xad, 0x43, 0xd3, 0x52, 0xaf, 0xdc, 0x1c, 0xb5, 0x3f, 0xdb, 0xef, 0x1c, + 0xf4, 0xad, 0xed, 0x4e, 0xbf, 0xdd, 0xdd, 0xeb, 0x35, 0x33, 0xec, 0x35, 0x68, 0xc5, 0x98, 0xaa, + 0xb8, 0xbd, 0x7f, 0x78, 0x7c, 0xd0, 0x6f, 0x66, 0xd9, 0x3d, 0xb8, 0xb3, 0xd3, 0x3d, 0x68, 0xef, + 0x59, 0x31, 0xce, 0xd6, 0x5e, 0xff, 0x13, 0xab, 0xf3, 0xeb, 0x47, 0x5d, 0xf3, 0xb3, 0x66, 0x2e, + 0x0d, 0x41, 0x28, 0xe3, 0xaa, 0x85, 0x3c, 0xbb, 0x0d, 0x2b, 0x84, 0x40, 0x55, 0xac, 0xfe, 0xe1, + 0xa1, 0xd5, 0x3b, 0x3c, 0x3c, 0x68, 0x16, 0xd8, 0x22, 0xd4, 0xba, 0x07, 0x9f, 0xb4, 0xf7, 0xba, + 0xdb, 0x96, 0xd9, 0x69, 0xef, 0xed, 0x37, 0x17, 0xd8, 0x12, 0x34, 0x66, 0xf1, 0x8a, 0xa2, 0x09, + 0x85, 0x77, 0x78, 0xd0, 0x3d, 0x3c, 0xb0, 0x3e, 0xe9, 0x98, 0xbd, 0xee, 0xe1, 0x41, 0xb3, 0xc4, + 0x56, 0x81, 0x25, 0x8b, 0x76, 0xf7, 0xdb, 0x5b, 0xcd, 0x32, 0x5b, 0x81, 0xc5, 0x24, 0xfc, 0x59, + 0xe7, 0xb3, 0x26, 0xb0, 0x16, 0x2c, 0xd3, 0xc0, 0xac, 0xcd, 0xce, 0xde, 0xe1, 0xa7, 0xd6, 0x7e, + 0xf7, 0xa0, 0xbb, 0x7f, 0xbc, 0xdf, 0xac, 0xe0, 0xbb, 0x5b, 0x9d, 0x8e, 0xd5, 0x3d, 0xe8, 0x1d, + 0xef, 0xec, 0x74, 0xb7, 0xba, 0x9d, 0x83, 0x7e, 0xb3, 0x4a, 0x3d, 0xa7, 0x4d, 0xbc, 0x26, 0x2a, + 0xc8, 0x9c, 0x01, 0x6b, 0xbb, 0xdb, 0x6b, 0x6f, 0xee, 0x75, 0xb6, 0x9b, 0x75, 0x76, 0x17, 0x6e, + 0xf7, 0x3b, 0xfb, 0x47, 0x87, 0x66, 0xdb, 0xfc, 0x4c, 0xe5, 0x14, 0x58, 0x3b, 0xed, 0xee, 0xde, + 0xb1, 0xd9, 0x69, 0x36, 0xd8, 0x1b, 0x70, 0xd7, 0xec, 0x7c, 0x7c, 0xdc, 0x35, 0x3b, 0xdb, 0xd6, + 0xc1, 0xe1, 0x76, 0xc7, 0xda, 0xe9, 0xb4, 0xfb, 0xc7, 0x66, 0xc7, 0xda, 0xef, 0xf6, 0x7a, 0xdd, + 0x83, 0xa7, 0xcd, 0x26, 0x7b, 0x0b, 0xee, 0x47, 0x28, 0x51, 0x03, 0x33, 0x58, 0x8b, 0x62, 0x7e, + 0x6a, 0x4b, 0x0f, 0x3a, 0xbf, 0xde, 0xb7, 0x8e, 0x3a, 0x1d, 0xb3, 0xc9, 0xd8, 0x3a, 0xac, 0xc6, + 0xdd, 0x53, 0x07, 0xb2, 0xef, 0x25, 0x51, 0x76, 0xd4, 0x31, 0xf7, 0xdb, 0x07, 0x62, 0x83, 0x13, + 0x65, 0xcb, 0x62, 0xd8, 0x71, 0xd9, 0xec, 0xb0, 0x57, 0x18, 0x83, 0xba, 0xb6, 0x2b, 0x3b, 0x6d, + 0xb3, 0xb9, 0xca, 0x1a, 0x50, 0xd9, 0x3f, 0x3a, 0xb2, 0xfa, 0xdd, 0xfd, 0xce, 0xe1, 0x71, 0xbf, + 0xb9, 0xc6, 0x56, 0xa0, 0xd9, 0x3d, 0xe8, 0x77, 0x4c, 0xb1, 0xd7, 0xaa, 0xea, 0xff, 0x2a, 0xb2, + 0x65, 0x68, 0xa8, 0x91, 0x2a, 0xe8, 0xcf, 0x8a, 0x6c, 0x0d, 0xd8, 0xf1, 0x81, 0xd9, 0x69, 0x6f, + 0x8b, 0x85, 0x8b, 0x0a, 0xfe, 0x77, 0x51, 0x7a, 0x48, 0x7e, 0x9a, 0x8b, 0x2e, 0xeb, 0x38, 0xe4, + 0x20, 0xf9, 0x36, 0x6d, 0x55, 0x7b, 0x53, 0xf6, 0x65, 0xaf, 0xc6, 0x6b, 0xaa, 0x55, 0x6e, 0x4e, + 0xb5, 0x9a, 0xd3, 0xdd, 0x6b, 0xba, 0xec, 0xf7, 0x26, 0xd4, 0xc6, 0xf4, 0x4e, 0xad, 0x7c, 0x8f, + 0x12, 0x64, 0xfc, 0x0d, 0x01, 0xe9, 0x31, 0xca, 0xb9, 0x67, 0xd3, 0x0b, 0xf3, 0xcf, 0xa6, 0xa7, + 0xc9, 0xf7, 0x0b, 0x69, 0xf2, 0xfd, 0x43, 0x58, 0x24, 0xd6, 0xe4, 0xb8, 0xce, 0x58, 0x69, 0xcd, + 0x24, 0x05, 0x36, 0x90, 0x45, 0x11, 0x5c, 0xa9, 0x13, 0x4a, 0xe5, 0x90, 0x2c, 0xa4, 0x28, 0xb5, + 0x8d, 0x84, 0xa6, 0x41, 0x9c, 0x23, 0xd2, 0x34, 0xa2, 0x1e, 0xec, 0xab, 0xb8, 0x87, 0x8a, 0xd6, + 0x03, 0xc1, 0xb1, 0x87, 0x87, 0xb0, 0xc8, 0xaf, 0x42, 0xdf, 0xb6, 0xbc, 0x89, 0xfd, 0xf9, 0x14, + 0x5d, 0xb8, 0x36, 0xea, 0xf0, 0x55, 0xb3, 0x81, 0x05, 0x87, 0x08, 0xdf, 0xb6, 0x43, 0xfb, 0xe1, + 0x17, 0x50, 0xd1, 0xde, 0x30, 0x66, 0x6b, 0xb0, 0xf4, 0x69, 0xb7, 0x7f, 0xd0, 0xe9, 0xf5, 0xac, + 0xa3, 0xe3, 0xcd, 0x67, 0x9d, 0xcf, 0xac, 0xdd, 0x76, 0x6f, 0xb7, 0x79, 0x4b, 0x1c, 0xda, 0x83, + 0x4e, 0xaf, 0xdf, 0xd9, 0x4e, 0xc0, 0x33, 0xec, 0x75, 0x58, 0x3f, 0x3e, 0x38, 0xee, 0x75, 0xb6, + 0xad, 0xb4, 0x7a, 0x59, 0x41, 0xa5, 0xb2, 0x3c, 0xa5, 0x7a, 0xee, 0xe1, 0xf7, 0xa1, 0x9e, 0x7c, + 0x58, 0x93, 0x01, 0x2c, 0xec, 0x75, 0x9e, 0xb6, 0xb7, 0x3e, 0xa3, 0x97, 0xf9, 0x7a, 0xfd, 0x76, + 0xbf, 0xbb, 0x65, 0xc9, 0x97, 0xf8, 0x04, 0x47, 0xc8, 0xb0, 0x0a, 0x14, 0xdb, 0x07, 0x5b, 0xbb, + 0x87, 0x66, 0xaf, 0x99, 0x7d, 0xf8, 0x11, 0x34, 0x67, 0xfd, 0x51, 0x09, 0x07, 0xde, 0x8b, 0x3c, + 0x7d, 0x0f, 0xff, 0x55, 0x0e, 0x20, 0x4e, 0x18, 0x10, 0xac, 0x66, 0xbb, 0xdd, 0x6f, 0xef, 0x1d, + 0x8a, 0x69, 0x98, 0x87, 0x7d, 0xc1, 0x41, 0xcc, 0xce, 0xc7, 0xcd, 0x5b, 0xa9, 0x25, 0x87, 0x47, + 0xfd, 0x66, 0x46, 0xac, 0x58, 0xf7, 0xa0, 0xdb, 0xef, 0xb6, 0xf7, 0x2c, 0xf3, 0xf0, 0xb8, 0x7b, + 0xf0, 0x94, 0x9e, 0x1c, 0x43, 0x2e, 0x7b, 0x7c, 0xb4, 0x63, 0x1e, 0x1e, 0xf4, 0xad, 0xde, 0xee, + 0x71, 0x7f, 0x1b, 0x1f, 0x2c, 0xdb, 0x32, 0xbb, 0x47, 0xd4, 0x66, 0xfe, 0x45, 0x08, 0xa2, 0xe9, + 0x82, 0x58, 0xf3, 0xa7, 0x87, 0xbd, 0x5e, 0xf7, 0xc8, 0xfa, 0xf8, 0xb8, 0x63, 0x76, 0x3b, 0x3d, + 0xac, 0xb8, 0x90, 0x02, 0x17, 0xf8, 0x45, 0xc1, 0x9b, 0xfb, 0x7b, 0x9f, 0x48, 0xe6, 0x29, 0x50, + 0x4b, 0x49, 0x90, 0xc0, 0x2a, 0x0b, 0x9e, 0x22, 0xb8, 0x4f, 0x4a, 0xcb, 0x70, 0x43, 0x99, 0xa8, + 0x57, 0x11, 0x7c, 0x75, 0x6e, 0x33, 0xb0, 0x5a, 0x35, 0xbd, 0x48, 0xd4, 0x42, 0x96, 0x1b, 0x5d, + 0x50, 0xdb, 0xdb, 0x26, 0x56, 0xa8, 0xcf, 0x41, 0x05, 0x6e, 0x43, 0x6c, 0x94, 0x60, 0x4f, 0x02, + 0xa5, 0xa9, 0x3e, 0x44, 0xc9, 0xe2, 0x93, 0xdf, 0xc9, 0x41, 0x9d, 0x92, 0xb7, 0xe8, 0x27, 0xa4, + 0xb8, 0xcf, 0xf6, 0xa1, 0x28, 0x7f, 0x8b, 0x8c, 0xad, 0x44, 0xaf, 0x41, 0xe9, 0xbf, 0x7e, 0xb6, + 0xbe, 0x3a, 0x0b, 0x96, 0xe2, 0xd8, 0xd2, 0xdf, 0xf8, 0xd3, 0xff, 0xf9, 0x0f, 0xb2, 0x35, 0x56, + 0x79, 0x74, 0xf1, 0xde, 0xa3, 0x33, 0xee, 0x06, 0xa2, 0x8d, 0xff, 0x1f, 0x20, 0xfe, 0x85, 0x2d, + 0xd6, 0x8a, 0x9c, 0x50, 0x33, 0x3f, 0x3f, 0xb6, 0x7e, 0x3b, 0xa5, 0x44, 0xb6, 0x7b, 0x1b, 0xdb, + 0x5d, 0x32, 0xea, 0xa2, 0x5d, 0xc7, 0x75, 0x42, 0xfa, 0xb5, 0xad, 0x0f, 0x33, 0x0f, 0xd9, 0x10, + 0xaa, 0xfa, 0x6f, 0x5f, 0x31, 0x25, 0x29, 0xa5, 0xfc, 0x7a, 0xd7, 0xfa, 0x9d, 0xd4, 0x32, 0x25, + 0x83, 0x62, 0x1f, 0x2b, 0x46, 0x53, 0xf4, 0x31, 0x45, 0x8c, 0xb8, 0x97, 0x11, 0x49, 0xe5, 0xf1, + 0x4f, 0x5c, 0xb1, 0xd7, 0x34, 0xb9, 0x6a, 0xee, 0x07, 0xb6, 0xd6, 0xef, 0xde, 0x50, 0x2a, 0xfb, + 0xba, 0x8b, 0x7d, 0xad, 0x19, 0x4c, 0xf4, 0x35, 0x40, 0x1c, 0xf5, 0x03, 0x5b, 0x1f, 0x66, 0x1e, + 0x3e, 0xf9, 0xcb, 0x07, 0x50, 0x8e, 0x82, 0x39, 0xd9, 0x6f, 0x41, 0x2d, 0x91, 0x5d, 0xc7, 0xd4, + 0x34, 0xd2, 0x92, 0xf1, 0xd6, 0x5f, 0x4b, 0x2f, 0x94, 0x1d, 0xbf, 0x8e, 0x1d, 0xb7, 0xd8, 0xaa, + 0xe8, 0x58, 0x66, 0xaf, 0x3d, 0xc2, 0x6c, 0x58, 0x7a, 0x5b, 0xeb, 0xb9, 0xa6, 0x7d, 0x50, 0x67, + 0xaf, 0xcd, 0x6a, 0x04, 0x89, 0xde, 0xee, 0xde, 0x50, 0x2a, 0xbb, 0x7b, 0x0d, 0xbb, 0x5b, 0x65, + 0xcb, 0x7a, 0x77, 0x2a, 0xf4, 0x92, 0x71, 0x7c, 0xcf, 0x4e, 0xff, 0x05, 0x28, 0x76, 0x37, 0x7e, + 0x7d, 0x2c, 0xe5, 0x97, 0xa1, 0x22, 0x12, 0x99, 0xff, 0x79, 0x28, 0xa3, 0x85, 0x5d, 0x31, 0x86, + 0xdb, 0xa7, 0xff, 0x00, 0x14, 0x3b, 0x81, 0x8a, 0xf6, 0xa3, 0x09, 0xec, 0xf6, 0x8d, 0x3f, 0xf0, + 0xb0, 0xbe, 0x9e, 0x56, 0x94, 0x36, 0x15, 0xbd, 0xfd, 0x47, 0xa7, 0x9c, 0xb3, 0xdf, 0x80, 0x72, + 0xf4, 0x14, 0x3f, 0x5b, 0xd3, 0x7e, 0x1a, 0x41, 0xff, 0xe9, 0x80, 0xf5, 0xd6, 0x7c, 0x41, 0x1a, + 0xf1, 0xe9, 0xad, 0x0b, 0xe2, 0xfb, 0x14, 0x2a, 0xda, 0x73, 0xfb, 0xd1, 0x04, 0xe6, 0x9f, 0xf4, + 0x8f, 0x26, 0x90, 0xf2, 0x3a, 0xbf, 0xb1, 0x88, 0x5d, 0x54, 0x58, 0x19, 0xe9, 0x3b, 0xbc, 0xf2, + 0x02, 0xb6, 0x07, 0x2b, 0x52, 0xd3, 0x3a, 0xe1, 0x5f, 0x66, 0x1b, 0x52, 0x7e, 0x74, 0xeb, 0x71, + 0x86, 0x7d, 0x04, 0x25, 0xf5, 0xab, 0x0a, 0x6c, 0x35, 0xfd, 0xd7, 0x21, 0xd6, 0xd7, 0xe6, 0xe0, + 0x52, 0x2d, 0xfa, 0x0c, 0x20, 0x7e, 0xdb, 0x3f, 0x62, 0x12, 0x73, 0xbf, 0x15, 0x10, 0x51, 0xc0, + 0xfc, 0x0f, 0x01, 0x18, 0xab, 0x38, 0xc1, 0x26, 0x43, 0x26, 0xe1, 0xf2, 0x4b, 0xf5, 0xe8, 0xe8, + 0x8f, 0xa0, 0xa2, 0x3d, 0xef, 0x1f, 0x2d, 0xdf, 0xfc, 0x4f, 0x03, 0x44, 0xcb, 0x97, 0xf2, 0x6b, + 0x00, 0xc6, 0x3a, 0xb6, 0xbe, 0x6c, 0x34, 0x44, 0xeb, 0x42, 0xd4, 0x92, 0x22, 0x8f, 0xd8, 0xa0, + 0x73, 0xa8, 0x25, 0xde, 0xf0, 0x8f, 0x4e, 0x68, 0xda, 0x2f, 0x04, 0x44, 0x27, 0x34, 0xf5, 0xd9, + 0x7f, 0x45, 0x67, 0xc6, 0xa2, 0xe8, 0xe7, 0x02, 0x51, 0xb4, 0x9e, 0x7e, 0x08, 0x15, 0xed, 0x3d, + 0xfe, 0x68, 0x2e, 0xf3, 0x4f, 0xff, 0x47, 0x73, 0x49, 0x7b, 0xbe, 0x7f, 0x19, 0xfb, 0xa8, 0x1b, + 0x48, 0x0a, 0xf8, 0x6c, 0xa2, 0x68, 0xfb, 0xb7, 0xa0, 0x9e, 0x7c, 0xa2, 0x3f, 0x3a, 0xfb, 0xa9, + 0x6f, 0xfd, 0x47, 0x67, 0xff, 0x86, 0x77, 0xfd, 0x25, 0x49, 0x3f, 0x5c, 0x8a, 0x3a, 0x79, 0xf4, + 0x13, 0x99, 0x96, 0xf2, 0x05, 0xfb, 0x58, 0x30, 0x38, 0xf9, 0x6a, 0x27, 0x5b, 0xd3, 0xa8, 0x56, + 0x7f, 0xfe, 0x33, 0x3a, 0x2f, 0x73, 0x0f, 0x7c, 0x26, 0x89, 0x19, 0x1b, 0x67, 0x4f, 0x61, 0x29, + 0x22, 0xe6, 0xe8, 0x19, 0xce, 0x20, 0x9a, 0x43, 0xea, 0x63, 0x9f, 0xeb, 0xcd, 0xd9, 0xd2, 0xc7, + 0x19, 0xba, 0xfe, 0xf0, 0xf1, 0x43, 0xed, 0xfa, 0xd3, 0x5f, 0xe2, 0xd4, 0xae, 0xbf, 0xc4, 0x1b, + 0x89, 0xb3, 0xd7, 0x5f, 0xe8, 0x88, 0x36, 0x5c, 0x68, 0xcc, 0x3e, 0x8a, 0x79, 0xf7, 0xa6, 0xb4, + 0x7f, 0x6a, 0xfe, 0xf5, 0x17, 0xbf, 0x0a, 0x90, 0x64, 0x45, 0x8a, 0x9b, 0x3e, 0x92, 0xc1, 0x27, + 0xec, 0x37, 0xa1, 0xaa, 0xbf, 0x0f, 0xce, 0x74, 0x9e, 0x30, 0xdb, 0xd3, 0x9d, 0xd4, 0xb2, 0x24, + 0x95, 0xb0, 0xaa, 0xde, 0x0d, 0xfb, 0x04, 0x56, 0xa3, 0x65, 0xd6, 0xf3, 0xd6, 0x03, 0x76, 0x2f, + 0x25, 0x9b, 0x3d, 0xb1, 0xd8, 0xb7, 0x6f, 0x4c, 0x77, 0x7f, 0x9c, 0x11, 0xd4, 0x97, 0x7c, 0xa8, + 0x38, 0xbe, 0x79, 0xd2, 0xde, 0x67, 0x8e, 0x6f, 0x9e, 0xd4, 0xd7, 0x8d, 0x15, 0xf5, 0xb1, 0xa5, + 0xc4, 0x1a, 0x51, 0x58, 0x2e, 0xfb, 0x21, 0x34, 0xb4, 0xa4, 0xfc, 0xde, 0xb5, 0x3b, 0x88, 0x4e, + 0xd2, 0xfc, 0x4b, 0x7b, 0xeb, 0x69, 0xb6, 0x49, 0x63, 0x0d, 0xdb, 0x5f, 0x34, 0x12, 0x8b, 0x23, + 0x4e, 0xd1, 0x16, 0x54, 0xf4, 0x84, 0xff, 0x17, 0xb4, 0xbb, 0xa6, 0x15, 0xe9, 0x8f, 0xba, 0x3d, + 0xce, 0xb0, 0x3d, 0x68, 0xce, 0xbe, 0x41, 0x15, 0xf1, 0x94, 0xb4, 0x77, 0xb3, 0xd6, 0x67, 0x0a, + 0x13, 0x2f, 0x57, 0xb1, 0x23, 0x4a, 0xec, 0x88, 0x7e, 0xa1, 0xca, 0xf3, 0x67, 0x6f, 0xf5, 0xe4, + 0x2f, 0x57, 0x45, 0xad, 0xa5, 0xfd, 0x66, 0xd9, 0x83, 0xcc, 0xe3, 0x0c, 0xfb, 0xbd, 0x0c, 0x54, + 0x13, 0xef, 0xbe, 0x24, 0x42, 0xe7, 0x67, 0xe6, 0xd9, 0xd2, 0xcb, 0xf4, 0x89, 0x1a, 0x26, 0x2e, + 0xe2, 0xde, 0xc3, 0x1f, 0x24, 0x36, 0xe9, 0x27, 0x09, 0xd7, 0xde, 0xc6, 0xec, 0x4f, 0x58, 0x7d, + 0x31, 0x8b, 0xa0, 0x3f, 0xa0, 0xf8, 0xc5, 0xe3, 0x0c, 0xfb, 0x37, 0x19, 0xa8, 0x27, 0x7d, 0xf6, + 0xd1, 0x74, 0x53, 0xa3, 0x03, 0x22, 0x52, 0xba, 0xc1, 0xd1, 0xff, 0x43, 0x1c, 0x65, 0xff, 0xa1, + 0x99, 0x18, 0xa5, 0x7c, 0x62, 0xfb, 0x17, 0x1b, 0x2d, 0xfb, 0x90, 0x7e, 0x31, 0x52, 0x85, 0x32, + 0xb1, 0xf9, 0x5f, 0x18, 0x8c, 0xc8, 0x4f, 0xff, 0x3d, 0x3e, 0xdc, 0x84, 0x1f, 0xd1, 0x4f, 0x35, + 0xa9, 0xc8, 0x18, 0x41, 0xc5, 0xaf, 0x5a, 0xdf, 0x78, 0x0b, 0xe7, 0xf4, 0xba, 0x71, 0x3b, 0x31, + 0xa7, 0x59, 0xc1, 0xa3, 0x4d, 0xa3, 0x93, 0x3f, 0xa7, 0x17, 0xdf, 0x9c, 0x73, 0x3f, 0xb1, 0x77, + 0xf3, 0x20, 0xc7, 0x34, 0x48, 0x89, 0x9e, 0x38, 0x6a, 0xaf, 0xd8, 0x8c, 0xf1, 0x10, 0xc7, 0xfa, + 0x96, 0x71, 0xef, 0xc6, 0xb1, 0x3e, 0x42, 0xff, 0xbb, 0x18, 0xf1, 0x11, 0x40, 0x1c, 0x6a, 0xc8, + 0x66, 0x02, 0xde, 0x22, 0x06, 0x34, 0x1f, 0x8d, 0x98, 0x3c, 0xcf, 0x2a, 0x2e, 0x4e, 0xb4, 0xf8, + 0x1b, 0xc4, 0x4e, 0xa3, 0x50, 0x3c, 0x5d, 0xfa, 0x4a, 0x46, 0x05, 0x26, 0xa4, 0xaf, 0xd9, 0xf6, + 0x13, 0xcc, 0x34, 0x8a, 0xbb, 0x3b, 0x86, 0xda, 0x9e, 0xe7, 0x3d, 0x9f, 0x4e, 0xa2, 0xf0, 0xf6, + 0x64, 0x50, 0xcc, 0xae, 0x1d, 0x9c, 0xaf, 0xcf, 0xcc, 0xc2, 0xb8, 0x8f, 0x4d, 0xad, 0xb3, 0x96, + 0xd6, 0xd4, 0xa3, 0x9f, 0xc4, 0xf1, 0x8d, 0x5f, 0x30, 0x1b, 0x16, 0x23, 0x1e, 0x1d, 0xc7, 0x10, + 0x26, 0x9b, 0x49, 0x70, 0xe6, 0xd9, 0x2e, 0x12, 0x6a, 0x82, 0x1a, 0xed, 0xa3, 0x40, 0xb5, 0xf9, + 0x38, 0xc3, 0x8e, 0xa0, 0xba, 0xcd, 0x07, 0x98, 0xa8, 0x8f, 0xa1, 0x25, 0x4b, 0x89, 0x30, 0x05, + 0x8a, 0x49, 0x59, 0xaf, 0x25, 0x80, 0xc9, 0x7b, 0x6b, 0x62, 0x5f, 0xfb, 0xfc, 0xf3, 0x47, 0x3f, + 0x91, 0x41, 0x2b, 0x5f, 0xa8, 0x7b, 0x4b, 0x05, 0xf5, 0x24, 0xee, 0xad, 0x99, 0x28, 0xa0, 0xc4, + 0xbd, 0x35, 0x17, 0x05, 0x94, 0x58, 0x6a, 0x15, 0x54, 0xc4, 0x46, 0xb0, 0x38, 0x17, 0x38, 0x14, + 0x5d, 0x59, 0x37, 0x85, 0x1b, 0xad, 0xdf, 0xbf, 0x19, 0x21, 0xd9, 0xdb, 0xc3, 0x64, 0x6f, 0x3d, + 0xa8, 0xd1, 0x9b, 0x8e, 0x27, 0x9c, 0x52, 0xf6, 0x66, 0xde, 0xbb, 0xd1, 0xf3, 0x01, 0x67, 0x2f, + 0x18, 0x2c, 0x4b, 0x4a, 0x38, 0x98, 0x2b, 0xc7, 0x7e, 0x03, 0x2a, 0x4f, 0x79, 0xa8, 0x72, 0xf4, + 0x22, 0x19, 0x7b, 0x26, 0x69, 0x6f, 0x3d, 0x25, 0xc5, 0x2f, 0x49, 0x33, 0xd8, 0xda, 0x23, 0x3e, + 0x3c, 0xe3, 0xc4, 0x9c, 0x2c, 0x67, 0xf8, 0x05, 0xfb, 0x75, 0x6c, 0x3c, 0x4a, 0x8d, 0x5e, 0xd5, + 0x92, 0xb0, 0xf4, 0xc6, 0x1b, 0x33, 0xf0, 0xb4, 0x96, 0x5d, 0x6f, 0xc8, 0x35, 0x59, 0xcf, 0x85, + 0x8a, 0xf6, 0x84, 0x42, 0x74, 0x80, 0xe6, 0x9f, 0xcc, 0x88, 0x0e, 0x50, 0xca, 0x8b, 0x0b, 0xc6, + 0x03, 0xec, 0xc7, 0x60, 0xf7, 0xe3, 0x7e, 0xe8, 0x95, 0x85, 0xb8, 0xa7, 0x47, 0x3f, 0xb1, 0xc7, + 0xe1, 0x17, 0xec, 0x53, 0x7c, 0x39, 0x5d, 0xcf, 0x41, 0x8c, 0x95, 0x86, 0xd9, 0x74, 0xc5, 0x68, + 0xb1, 0xb4, 0xa2, 0xa4, 0x22, 0x41, 0x5d, 0xa1, 0x24, 0xf7, 0x3e, 0x40, 0x2f, 0xf4, 0x26, 0xdb, + 0x36, 0x1f, 0x7b, 0x6e, 0xcc, 0x6b, 0xe3, 0xac, 0xb8, 0x98, 0x7f, 0x69, 0xa9, 0x71, 0xec, 0x53, + 0x4d, 0xcb, 0x4a, 0xa4, 0x71, 0x2a, 0xe2, 0xba, 0x31, 0x71, 0x2e, 0x5a, 0x90, 0x94, 0xe4, 0xb9, + 0xc7, 0x19, 0xd6, 0x06, 0x88, 0x23, 0xc7, 0x22, 0x9d, 0x69, 0x2e, 0x28, 0x2d, 0x62, 0x7b, 0x29, + 0x61, 0x66, 0x47, 0x50, 0x8e, 0x43, 0x6e, 0xd6, 0xe2, 0x17, 0x61, 0x12, 0x01, 0x3a, 0xd1, 0x0d, + 0x3e, 0x17, 0xee, 0x62, 0x34, 0x71, 0xa9, 0x80, 0x95, 0xc4, 0x52, 0x9d, 0x72, 0x1e, 0x30, 0x07, + 0x96, 0x68, 0x80, 0x91, 0xb8, 0x84, 0xd9, 0x5c, 0xd1, 0x03, 0xf9, 0xf3, 0x91, 0x27, 0xd1, 0x69, + 0x4e, 0x8d, 0x9f, 0x48, 0x98, 0x7e, 0x04, 0xb5, 0x52, 0x26, 0x99, 0x60, 0xcd, 0x63, 0x58, 0x9c, + 0x73, 0xd1, 0x47, 0x47, 0xfa, 0xa6, 0x98, 0x8b, 0xe8, 0x48, 0xdf, 0xe8, 0xdd, 0x37, 0x56, 0xb0, + 0xcb, 0x86, 0x01, 0xa8, 0xea, 0x5d, 0x3a, 0xe1, 0xe0, 0x5c, 0x74, 0xf7, 0x2f, 0x33, 0xb0, 0x94, + 0xe2, 0x84, 0x67, 0x6f, 0x28, 0xab, 0xc1, 0x8d, 0x0e, 0xfa, 0xf5, 0x54, 0x67, 0xad, 0xd1, 0xc3, + 0x7e, 0xf6, 0xd9, 0xb3, 0xc4, 0xc5, 0x46, 0xbe, 0x52, 0x79, 0x32, 0x5f, 0x28, 0x54, 0xa4, 0x4a, + 0x14, 0x9f, 0xc3, 0x1a, 0x0d, 0xa4, 0x3d, 0x1a, 0xcd, 0x38, 0x92, 0x5f, 0x9f, 0xfb, 0x45, 0xf9, + 0x84, 0x73, 0x7c, 0xfd, 0xe6, 0x5f, 0x9c, 0xbf, 0x41, 0x9c, 0xa6, 0xa1, 0xb2, 0x29, 0x34, 0x67, + 0x1d, 0xb4, 0xec, 0xe6, 0xb6, 0xd6, 0xef, 0x25, 0xf4, 0xdf, 0x14, 0xa7, 0xee, 0xd7, 0xb0, 0xb3, + 0x7b, 0xc6, 0x7a, 0xda, 0xba, 0x90, 0x4a, 0x2c, 0xf6, 0xe3, 0xaf, 0x47, 0xde, 0xe4, 0x99, 0x79, + 0xaa, 0x0e, 0x6e, 0xf2, 0x7d, 0x47, 0x1a, 0x78, 0xba, 0x33, 0xfa, 0x6d, 0xec, 0xfe, 0xbe, 0x71, + 0x27, 0xad, 0x7b, 0x9f, 0xaa, 0x90, 0x2e, 0xbe, 0x36, 0x7b, 0xae, 0xd5, 0x08, 0xee, 0xa7, 0xed, + 0xf7, 0x8d, 0xba, 0xd0, 0xcc, 0x5a, 0xdf, 0x42, 0xd9, 0xae, 0xaa, 0x7b, 0x8f, 0xa3, 0xe3, 0x93, + 0xe2, 0xa6, 0x8e, 0x8e, 0x4f, 0x9a, 0xbb, 0x39, 0x29, 0xd7, 0x28, 0x47, 0xf3, 0x87, 0x99, 0x87, + 0x9b, 0xef, 0xfc, 0xf0, 0x6b, 0x67, 0x4e, 0x78, 0x3e, 0x3d, 0xd9, 0x18, 0x78, 0xe3, 0x47, 0x23, + 0x65, 0x6d, 0x94, 0x29, 0xcf, 0x8f, 0x46, 0xee, 0xf0, 0x11, 0x36, 0x7b, 0xb2, 0x30, 0xf1, 0xbd, + 0xd0, 0xfb, 0xd6, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x70, 0x9a, 0xaf, 0x28, 0x34, 0x83, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index dc32ab4269..fe5fb29f75 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1982,6 +1982,23 @@ message PendingChannelsResponse { /// The balance in satoshis encumbered in this channel int64 limbo_balance = 2; + + /** + A list of valid commitment transactions. Any of these can confirm at + this point. + */ + Commitments commitments = 3; + } + + message Commitments { + /// Hash of the local version of the commitment tx. + string local_txid = 1; + + /// Hash of the remote version of the commitment tx. + string remote_txid = 2; + + /// Hash of the remote pending version of the commitment tx. + string remote_pending_txid = 3; } message ClosedChannel { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index b8a9f6e8a0..64b693abad 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1603,6 +1603,23 @@ } } }, + "PendingChannelsResponseCommitments": { + "type": "object", + "properties": { + "local_txid": { + "type": "string", + "description": "/ Hash of the local version of the commitment tx." + }, + "remote_txid": { + "type": "string", + "description": "/ Hash of the remote version of the commitment tx." + }, + "remote_pending_txid": { + "type": "string", + "description": "/ Hash of the remote pending version of the commitment tx." + } + } + }, "PendingChannelsResponseForceClosedChannel": { "type": "object", "properties": { @@ -1718,6 +1735,10 @@ "type": "string", "format": "int64", "title": "/ The balance in satoshis encumbered in this channel" + }, + "commitments": { + "$ref": "#/definitions/PendingChannelsResponseCommitments", + "description": "*\nA list of valid commitment transactions. Any of these can confirm at\nthis point." } } }, diff --git a/rpcserver.go b/rpcserver.go index 2a123e7fe3..9613da4fd0 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2756,6 +2756,43 @@ func (r *rpcServer) PendingChannels(ctx context.Context, for _, waitingClose := range waitingCloseChans { pub := waitingClose.IdentityPub.SerializeCompressed() chanPoint := waitingClose.FundingOutpoint + + var commitments lnrpc.PendingChannelsResponse_Commitments + + // Report local commit. May not be present when DLP is active. + if waitingClose.LocalCommitment.CommitTx != nil { + commitments.LocalTxid = + waitingClose.LocalCommitment.CommitTx.TxHash(). + String() + } + + // Report remote commit. May not be present when DLP is active. + if waitingClose.RemoteCommitment.CommitTx != nil { + commitments.RemoteTxid = + waitingClose.RemoteCommitment.CommitTx.TxHash(). + String() + } + + // Report the remote pending commit if any. + remoteCommitDiff, err := waitingClose.RemoteCommitChainTip() + + switch { + + // Don't set hash if there is no pending remote commit. + case err == channeldb.ErrNoPendingCommit: + + // An unexpected error occurred. + case err != nil: + return nil, err + + // There is a pending remote commit. Set its hash in the + // response. + default: + hash := remoteCommitDiff.Commitment.CommitTx.TxHash() + commitments.RemotePendingTxid = hash.String() + + } + channel := &lnrpc.PendingChannelsResponse_PendingChannel{ RemoteNodePub: hex.EncodeToString(pub), ChannelPoint: chanPoint.String(), @@ -2766,14 +2803,16 @@ func (r *rpcServer) PendingChannels(ctx context.Context, RemoteChanReserveSat: int64(waitingClose.RemoteChanCfg.ChanReserve), } + waitingCloseResp := &lnrpc.PendingChannelsResponse_WaitingCloseChannel{ + Channel: channel, + LimboBalance: channel.LocalBalance, + Commitments: &commitments, + } + // A close tx has been broadcasted, all our balance will be in // limbo until it confirms. resp.WaitingCloseChannels = append( - resp.WaitingCloseChannels, - &lnrpc.PendingChannelsResponse_WaitingCloseChannel{ - Channel: channel, - LimboBalance: channel.LocalBalance, - }, + resp.WaitingCloseChannels, waitingCloseResp, ) resp.TotalLimboBalance += channel.LocalBalance From fa115b543df59329d2bf8ce32f2eceaca7e2607e Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 11 Mar 2020 17:43:16 +0100 Subject: [PATCH 244/562] lncli: add bumpchannelclose command This command allows users to easily bump the fee on their unconfirmed closing transactions. --- cmd/lncli/walletrpc_active.go | 132 ++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/cmd/lncli/walletrpc_active.go b/cmd/lncli/walletrpc_active.go index 31b14b764f..c1849e1bb7 100644 --- a/cmd/lncli/walletrpc_active.go +++ b/cmd/lncli/walletrpc_active.go @@ -4,8 +4,12 @@ package main import ( "context" + "errors" + "fmt" "sort" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/urfave/cli" ) @@ -22,6 +26,7 @@ func walletCommands() []cli.Command { Subcommands: []cli.Command{ pendingSweepsCommand, bumpFeeCommand, + bumpCloseFeeCommand, }, }, } @@ -168,3 +173,130 @@ func bumpFee(ctx *cli.Context) error { return nil } + +var bumpCloseFeeCommand = cli.Command{ + Name: "bumpclosefee", + Usage: "Bumps the fee of a channel closing transaction.", + ArgsUsage: "channel_point", + Description: ` + This command allows the fee of a channel closing transaction to be + increased by using the child-pays-for-parent mechanism. It will instruct + the sweeper to sweep the anchor outputs of transactions in the set + of valid commitments for the specified channel at the requested fee + rate or confirmation target. + `, + Flags: []cli.Flag{ + cli.Uint64Flag{ + Name: "conf_target", + Usage: "the number of blocks that the output should " + + "be swept on-chain within", + }, + cli.Uint64Flag{ + Name: "sat_per_byte", + Usage: "a manual fee expressed in sat/byte that " + + "should be used when sweeping the output", + }, + }, + Action: actionDecorator(bumpCloseFee), +} + +func bumpCloseFee(ctx *cli.Context) error { + // Display the command's help message if we do not have the expected + // number of arguments/flags. + if ctx.NArg() != 1 { + return cli.ShowCommandHelp(ctx, "bumpclosefee") + } + + // Validate the channel point. + channelPoint := ctx.Args().Get(0) + _, err := NewProtoOutPoint(channelPoint) + if err != nil { + return err + } + + // Fetch all waiting close channels. + client, cleanUp := getClient(ctx) + defer cleanUp() + + // Fetch waiting close channel commitments. + commitments, err := getWaitingCloseCommitments(client, channelPoint) + if err != nil { + return err + } + + // Retrieve pending sweeps. + walletClient, cleanUp := getWalletClient(ctx) + defer cleanUp() + + ctxb := context.Background() + sweeps, err := walletClient.PendingSweeps( + ctxb, &walletrpc.PendingSweepsRequest{}, + ) + if err != nil { + return err + } + + // Match pending sweeps with commitments of the channel for which a bump + // is requested and bump their fees. + commitSet := map[string]struct{}{ + commitments.LocalTxid: {}, + commitments.RemoteTxid: {}, + } + if commitments.RemotePendingTxid != "" { + commitSet[commitments.RemotePendingTxid] = struct{}{} + } + + for _, sweep := range sweeps.PendingSweeps { + // Only bump anchor sweeps. + if sweep.WitnessType != walletrpc.WitnessType_COMMITMENT_ANCHOR { + continue + } + + // Skip unrelated sweeps. + sweepTxID, err := chainhash.NewHash(sweep.Outpoint.TxidBytes) + if err != nil { + return err + } + if _, match := commitSet[sweepTxID.String()]; !match { + continue + } + + // Bump fee of the anchor sweep. + fmt.Printf("Bumping fee of %v:%v\n", + sweepTxID, sweep.Outpoint.OutputIndex) + + _, err = walletClient.BumpFee(ctxb, &walletrpc.BumpFeeRequest{ + Outpoint: sweep.Outpoint, + TargetConf: uint32(ctx.Uint64("conf_target")), + SatPerByte: uint32(ctx.Uint64("sat_per_byte")), + Force: true, + }) + if err != nil { + return err + } + } + + return nil +} + +func getWaitingCloseCommitments(client lnrpc.LightningClient, + channelPoint string) (*lnrpc.PendingChannelsResponse_Commitments, + error) { + + ctxb := context.Background() + + req := &lnrpc.PendingChannelsRequest{} + resp, err := client.PendingChannels(ctxb, req) + if err != nil { + return nil, err + } + + // Lookup the channel commit tx hashes. + for _, channel := range resp.WaitingCloseChannels { + if channel.Channel.ChannelPoint == channelPoint { + return channel.Commitments, nil + } + } + + return nil, errors.New("channel not found") +} From fc808ac5382b3c323a4a3c056d0074e74a12d5bd Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 12 Dec 2019 16:16:33 -0800 Subject: [PATCH 245/562] channeldb/kvdb: create new package for an abstract kv store In this commit, we create a new package `kvdb`, which is meant to serve as the basis for any future database abstractions within `lnd`. Rather than directly use the `walletdb` package (which we base off of), we instead use a series of type-aliases to re-type the fundamental types/interfaces of the `walletdb` package. This lets us type `kvdb.RwTx` instead of `walletdb.ReadWriteTransaction` everywhere. Additionally, our usage of type-aliases is also intended to create an easy pathway in the future wherein we can gradually re-defined or re-implement these types to wean off of the `walletdb` package. --- channeldb/db.go | 3 +- channeldb/kvdb/bbolt.go | 10 +++++ channeldb/kvdb/interface.go | 90 +++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 channeldb/kvdb/bbolt.go create mode 100644 channeldb/kvdb/interface.go diff --git a/channeldb/db.go b/channeldb/db.go index cd4cd7568d..5fd0bc2022 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/coreos/bbolt" "github.com/go-errors/errors" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/channeldb/migration12" "github.com/lightningnetwork/lnd/channeldb/migration13" "github.com/lightningnetwork/lnd/channeldb/migration_01_to_11" @@ -28,7 +29,7 @@ const ( // migration is a function which takes a prior outdated version of the database // instances and mutates the key/bucket structure to arrive at a more // up-to-date version of the database. -type migration func(tx *bbolt.Tx) error +type migration func(tx kvdb.RwTx) error type version struct { number uint32 diff --git a/channeldb/kvdb/bbolt.go b/channeldb/kvdb/bbolt.go new file mode 100644 index 0000000000..b249e7dbb6 --- /dev/null +++ b/channeldb/kvdb/bbolt.go @@ -0,0 +1,10 @@ +package kvdb + +import ( + _ "github.com/btcsuite/btcwallet/walletdb/bdb" // Import to register backend. +) + +// BoltBackendName is the name of the backend that should be passed into +// kvdb.Create to initialize a new instance of kvdb.Backend backed by a live +// instance of bbolt. +const BoltBackendName = "bdb" diff --git a/channeldb/kvdb/interface.go b/channeldb/kvdb/interface.go new file mode 100644 index 0000000000..ec426410c7 --- /dev/null +++ b/channeldb/kvdb/interface.go @@ -0,0 +1,90 @@ +package kvdb + +import ( + "github.com/btcsuite/btcwallet/walletdb" + _ "github.com/btcsuite/btcwallet/walletdb/bdb" // Import to register backend. +) + +// Update opens a database read/write transaction and executes the function f +// with the transaction passed as a parameter. After f exits, if f did not +// error, the transaction is committed. Otherwise, if f did error, the +// transaction is rolled back. If the rollback fails, the original error +// returned by f is still returned. If the commit fails, the commit error is +// returned. +var Update = walletdb.Update + +// View opens a database read transaction and executes the function f with the +// transaction passed as a parameter. After f exits, the transaction is rolled +// back. If f errors, its error is returned, not a rollback error (if any +// occur). +var View = walletdb.View + +// Batch is identical to the Update call, but it attempts to combine several +// individual Update transactions into a single write database transaction on +// an optimistic basis. This only has benefits if multiple goroutines call +// Batch. +var Batch = walletdb.Batch + +// Create initializes and opens a database for the specified type. The +// arguments are specific to the database type driver. See the documentation +// for the database driver for further details. +// +// ErrDbUnknownType will be returned if the database type is not registered. +var Create = walletdb.Create + +// Backend represents an ACID database. All database access is performed +// through read or read+write transactions. +type Backend = walletdb.DB + +// Open opens an existing database for the specified type. The arguments are +// specific to the database type driver. See the documentation for the database +// driver for further details. +// +// ErrDbUnknownType will be returned if the database type is not registered. +var Open = walletdb.Open + +// Driver defines a structure for backend drivers to use when they registered +// themselves as a backend which implements the Backend interface. +type Driver = walletdb.Driver + +// ReadBucket represents a bucket (a hierarchical structure within the +// database) that is only allowed to perform read operations. +type ReadBucket = walletdb.ReadBucket + +// ReadCursor represents a bucket cursor that can be positioned at the start or +// end of the bucket's key/value pairs and iterate over pairs in the bucket. +// This type is only allowed to perform database read operations. +type ReadCursor = walletdb.ReadCursor + +// ReadTx represents a database transaction that can only be used for reads. If +// a database update must occur, use a RwTx. +type ReadTx = walletdb.ReadTx + +// RwBucket represents a bucket (a hierarchical structure within the database) +// that is allowed to perform both read and write operations. +type RwBucket = walletdb.ReadWriteBucket + +// RwCursor represents a bucket cursor that can be positioned at the start or +// end of the bucket's key/value pairs and iterate over pairs in the bucket. +// This abstraction is allowed to perform both database read and write +// operations. +type RwCursor = walletdb.ReadWriteCursor + +// ReadWriteTx represents a database transaction that can be used for both +// reads and writes. When only reads are necessary, consider using a ReadTx +// instead. +type RwTx = walletdb.ReadWriteTx + +var ( + // ErrBucketNotFound is returned when trying to access a bucket that + // has not been created yet. + ErrBucketNotFound = walletdb.ErrBucketNotFound + + // ErrBucketExists is returned when creating a bucket that already + // exists. + ErrBucketExists = walletdb.ErrBucketExists + + // ErrDatabaseNotOpen is returned when a database instance is accessed + // before it is opened or after it is closed. + ErrDatabaseNotOpen = walletdb.ErrDbNotOpen +) From f0911765af5cb7817253ea588d9b12d4c952726a Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 12 Dec 2019 18:22:19 -0800 Subject: [PATCH 246/562] channeldb: convert to uniformly use new kvdb abstractions In this commit, we migrate all the code in `channeldb` to only reference the new `kvdb` package rather than `bbolt` directly. In many instances, we need to add two version to fetch a bucket as both read and write when needed. As an example, we add a new `fetchChanBucketRw` function. This function is identical to `fetchChanBucket`, but it will be used to fetch the main channel bucket for all _write_ transactions. We need a new method as you can pass a write transaction where a read is accepted, but not the other way around due to the stronger typing of the new `kvdb` package. --- channeldb/channel.go | 172 +++++---- channeldb/db.go | 156 ++++---- channeldb/duplicate_payments.go | 12 +- channeldb/forwarding_log.go | 12 +- channeldb/forwarding_package.go | 84 ++--- channeldb/forwarding_package_test.go | 54 +-- channeldb/graph.go | 336 +++++++++--------- channeldb/graph_test.go | 42 ++- channeldb/invoices.go | 58 +-- channeldb/meta.go | 20 +- channeldb/meta_test.go | 56 +-- channeldb/migration12/migration.go | 6 +- channeldb/migration12/migration_test.go | 22 +- channeldb/migration13/migration.go | 8 +- channeldb/migration13/migration_test.go | 6 +- channeldb/migration_01_to_11/db.go | 43 +-- channeldb/migration_01_to_11/graph.go | 44 +-- channeldb/migration_01_to_11/invoices.go | 6 +- channeldb/migration_01_to_11/meta.go | 10 +- channeldb/migration_01_to_11/meta_test.go | 4 +- .../migration_09_legacy_serialization.go | 28 +- .../migration_10_route_tlv_records.go | 18 +- .../migration_11_invoices.go | 6 +- .../migration_11_invoices_test.go | 6 +- channeldb/migration_01_to_11/migrations.go | 68 ++-- .../migration_01_to_11/migrations_test.go | 34 +- .../migration_01_to_11/payment_control.go | 6 +- channeldb/migration_01_to_11/payments.go | 14 +- channeldb/migtest/migtest.go | 14 +- channeldb/migtest/raw_db.go | 24 +- channeldb/nodes.go | 26 +- channeldb/payment_control.go | 85 +++-- channeldb/payments.go | 31 +- channeldb/waitingproof.go | 18 +- channeldb/witness_cache.go | 22 +- go.mod | 5 +- 36 files changed, 804 insertions(+), 752 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 4b97caa63a..2d44dd1093 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwire" @@ -692,7 +692,7 @@ func (c *OpenChannel) RefreshShortChanID() error { c.Lock() defer c.Unlock() - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -718,27 +718,30 @@ func (c *OpenChannel) RefreshShortChanID() error { // fetchChanBucket is a helper function that returns the bucket where a // channel's data resides in given: the public key for the node, the outpoint, // and the chainhash that the channel resides on. -func fetchChanBucket(tx *bbolt.Tx, nodeKey *btcec.PublicKey, - outPoint *wire.OutPoint, chainHash chainhash.Hash) (*bbolt.Bucket, error) { +func fetchChanBucket(tx kvdb.ReadTx, nodeKey *btcec.PublicKey, + outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.ReadBucket, error) { // First fetch the top level bucket which stores all data related to // current, active channels. - openChanBucket := tx.Bucket(openChannelBucket) + openChanBucket := tx.ReadBucket(openChannelBucket) if openChanBucket == nil { return nil, ErrNoChanDBExists } + // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like + // CreateIfNotExists, will return error + // Within this top level bucket, fetch the bucket dedicated to storing // open channel data specific to the remote node. nodePub := nodeKey.SerializeCompressed() - nodeChanBucket := openChanBucket.Bucket(nodePub) + nodeChanBucket := openChanBucket.NestedReadBucket(nodePub) if nodeChanBucket == nil { return nil, ErrNoActiveChannels } // We'll then recurse down an additional layer in order to fetch the // bucket for this particular chain. - chainBucket := nodeChanBucket.Bucket(chainHash[:]) + chainBucket := nodeChanBucket.NestedReadBucket(chainHash[:]) if chainBucket == nil { return nil, ErrNoActiveChannels } @@ -749,7 +752,7 @@ func fetchChanBucket(tx *bbolt.Tx, nodeKey *btcec.PublicKey, if err := writeOutpoint(&chanPointBuf, outPoint); err != nil { return nil, err } - chanBucket := chainBucket.Bucket(chanPointBuf.Bytes()) + chanBucket := chainBucket.NestedReadBucket(chanPointBuf.Bytes()) if chanBucket == nil { return nil, ErrChannelNotFound } @@ -757,12 +760,27 @@ func fetchChanBucket(tx *bbolt.Tx, nodeKey *btcec.PublicKey, return chanBucket, nil } +// fetchChanBucketRw is a helper function that returns the bucket where a +// channel's data resides in given: the public key for the node, the outpoint, +// and the chainhash that the channel resides on. This differs from +// fetchChanBucket in that it returns a writeable bucket. +func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey, + outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RwBucket, error) { + + readBucket, err := fetchChanBucket(tx, nodeKey, outPoint, chainHash) + if err != nil { + return nil, err + } + + return readBucket.(kvdb.RwBucket), nil +} + // fullSync syncs the contents of an OpenChannel while re-using an existing // database transaction. -func (c *OpenChannel) fullSync(tx *bbolt.Tx) error { +func (c *OpenChannel) fullSync(tx kvdb.RwTx) error { // First fetch the top level bucket which stores all data related to // current, active channels. - openChanBucket, err := tx.CreateBucketIfNotExists(openChannelBucket) + openChanBucket, err := tx.CreateTopLevelBucket(openChannelBucket) if err != nil { return err } @@ -792,7 +810,7 @@ func (c *OpenChannel) fullSync(tx *bbolt.Tx) error { chanPointBuf.Bytes(), ) switch { - case err == bbolt.ErrBucketExists: + case err == kvdb.ErrBucketExists: // If this channel already exists, then in order to avoid // overriding it, we'll return an error back up to the caller. return ErrChanAlreadyExists @@ -809,7 +827,7 @@ func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error { c.Lock() defer c.Unlock() - if err := c.Db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(c.Db, func(tx kvdb.RwTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -825,7 +843,7 @@ func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error { channel.IsPending = false channel.ShortChannelID = openLoc - return putOpenChannel(chanBucket, channel) + return putOpenChannel(chanBucket.(kvdb.RwBucket), channel) }); err != nil { return err } @@ -849,7 +867,7 @@ func (c *OpenChannel) MarkDataLoss(commitPoint *btcec.PublicKey) error { return err } - putCommitPoint := func(chanBucket *bbolt.Bucket) error { + putCommitPoint := func(chanBucket kvdb.RwBucket) error { return chanBucket.Put(dataLossCommitPointKey, b.Bytes()) } @@ -861,7 +879,7 @@ func (c *OpenChannel) MarkDataLoss(commitPoint *btcec.PublicKey) error { func (c *OpenChannel) DataLossCommitPoint() (*btcec.PublicKey, error) { var commitPoint *btcec.PublicKey - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -990,7 +1008,7 @@ func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) { // active. // // NOTE: The primary mutex should already be held before this method is called. -func (c *OpenChannel) isBorked(chanBucket *bbolt.Bucket) (bool, error) { +func (c *OpenChannel) isBorked(chanBucket kvdb.ReadBucket) (bool, error) { channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint) if err != nil { return false, err @@ -1042,14 +1060,14 @@ func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte, // If a closing tx is provided, we'll generate a closure to write the // transaction in the appropriate bucket under the given key. - var putClosingTx func(*bbolt.Bucket) error + var putClosingTx func(kvdb.RwBucket) error if closeTx != nil { var b bytes.Buffer if err := WriteElement(&b, closeTx); err != nil { return err } - putClosingTx = func(chanBucket *bbolt.Bucket) error { + putClosingTx = func(chanBucket kvdb.RwBucket) error { return chanBucket.Put(key, b.Bytes()) } } @@ -1083,7 +1101,7 @@ func (c *OpenChannel) BroadcastedCooperative() (*wire.MsgTx, error) { func (c *OpenChannel) getClosingTx(key []byte) (*wire.MsgTx, error) { var closeTx *wire.MsgTx - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -1113,10 +1131,10 @@ func (c *OpenChannel) getClosingTx(key []byte) (*wire.MsgTx, error) { // list of closures that are given the chanBucket in order to atomically add // extra information together with the new status. func (c *OpenChannel) putChanStatus(status ChannelStatus, - fs ...func(*bbolt.Bucket) error) error { + fs ...func(kvdb.RwBucket) error) error { - if err := c.Db.Update(func(tx *bbolt.Tx) error { - chanBucket, err := fetchChanBucket( + if err := kvdb.Update(c.Db, func(tx kvdb.RwTx) error { + chanBucket, err := fetchChanBucketRw( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) if err != nil { @@ -1159,8 +1177,8 @@ func (c *OpenChannel) putChanStatus(status ChannelStatus, } func (c *OpenChannel) clearChanStatus(status ChannelStatus) error { - if err := c.Db.Update(func(tx *bbolt.Tx) error { - chanBucket, err := fetchChanBucket( + if err := kvdb.Update(c.Db, func(tx kvdb.RwTx) error { + chanBucket, err := fetchChanBucketRw( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) if err != nil { @@ -1189,7 +1207,7 @@ func (c *OpenChannel) clearChanStatus(status ChannelStatus) error { // putChannel serializes, and stores the current state of the channel in its // entirety. -func putOpenChannel(chanBucket *bbolt.Bucket, channel *OpenChannel) error { +func putOpenChannel(chanBucket kvdb.RwBucket, channel *OpenChannel) error { // First, we'll write out all the relatively static fields, that are // decided upon initial channel creation. if err := putChanInfo(chanBucket, channel); err != nil { @@ -1213,7 +1231,7 @@ func putOpenChannel(chanBucket *bbolt.Bucket, channel *OpenChannel) error { // fetchOpenChannel retrieves, and deserializes (including decrypting // sensitive) the complete channel currently active with the passed nodeID. -func fetchOpenChannel(chanBucket *bbolt.Bucket, +func fetchOpenChannel(chanBucket kvdb.ReadBucket, chanPoint *wire.OutPoint) (*OpenChannel, error) { channel := &OpenChannel{ @@ -1260,20 +1278,20 @@ func (c *OpenChannel) SyncPending(addr net.Addr, pendingHeight uint32) error { c.FundingBroadcastHeight = pendingHeight - return c.Db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.Db, func(tx kvdb.RwTx) error { return syncNewChannel(tx, c, []net.Addr{addr}) }) } // syncNewChannel will write the passed channel to disk, and also create a // LinkNode (if needed) for the channel peer. -func syncNewChannel(tx *bbolt.Tx, c *OpenChannel, addrs []net.Addr) error { +func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error { // First, sync all the persistent channel state to disk. if err := c.fullSync(tx); err != nil { return err } - nodeInfoBucket, err := tx.CreateBucketIfNotExists(nodeInfoBucket) + nodeInfoBucket, err := tx.CreateTopLevelBucket(nodeInfoBucket) if err != nil { return err } @@ -1316,8 +1334,8 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment, return ErrNoRestoredChannelMutation } - err := c.Db.Update(func(tx *bbolt.Tx) error { - chanBucket, err := fetchChanBucket( + err := kvdb.Update(c.Db, func(tx kvdb.RwTx) error { + chanBucket, err := fetchChanBucketRw( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) if err != nil { @@ -1786,10 +1804,10 @@ func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error { return ErrNoRestoredChannelMutation } - return c.Db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.Db, func(tx kvdb.RwTx) error { // First, we'll grab the writable bucket where this channel's // data resides. - chanBucket, err := fetchChanBucket( + chanBucket, err := fetchChanBucketRw( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) if err != nil { @@ -1854,7 +1872,7 @@ func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error { // these pointers, causing the tip and the tail to point to the same entry. func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) { var cd *CommitDiff - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -1891,7 +1909,7 @@ func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) { // updates that still need to be signed for. func (c *OpenChannel) UnsignedAckedUpdates() ([]LogUpdate, error) { var updates []LogUpdate - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -1932,8 +1950,8 @@ func (c *OpenChannel) InsertNextRevocation(revKey *btcec.PublicKey) error { c.RemoteNextRevocation = revKey - err := c.Db.Update(func(tx *bbolt.Tx) error { - chanBucket, err := fetchChanBucket( + err := kvdb.Update(c.Db, func(tx kvdb.RwTx) error { + chanBucket, err := fetchChanBucketRw( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) if err != nil { @@ -1969,8 +1987,8 @@ func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg) error { var newRemoteCommit *ChannelCommitment - err := c.Db.Update(func(tx *bbolt.Tx) error { - chanBucket, err := fetchChanBucket( + err := kvdb.Update(c.Db, func(tx kvdb.RwTx) error { + chanBucket, err := fetchChanBucketRw( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) if err != nil { @@ -2089,7 +2107,7 @@ func (c *OpenChannel) LoadFwdPkgs() ([]*FwdPkg, error) { defer c.RUnlock() var fwdPkgs []*FwdPkg - if err := c.Db.View(func(tx *bbolt.Tx) error { + if err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { var err error fwdPkgs, err = c.Packager.LoadFwdPkgs(tx) return err @@ -2107,7 +2125,7 @@ func (c *OpenChannel) AckAddHtlcs(addRefs ...AddRef) error { c.Lock() defer c.Unlock() - return c.Db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.Db, func(tx kvdb.RwTx) error { return c.Packager.AckAddHtlcs(tx, addRefs...) }) } @@ -2120,7 +2138,7 @@ func (c *OpenChannel) AckSettleFails(settleFailRefs ...SettleFailRef) error { c.Lock() defer c.Unlock() - return c.Db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.Db, func(tx kvdb.RwTx) error { return c.Packager.AckSettleFails(tx, settleFailRefs...) }) } @@ -2131,7 +2149,7 @@ func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error { c.Lock() defer c.Unlock() - return c.Db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.Db, func(tx kvdb.RwTx) error { return c.Packager.SetFwdFilter(tx, height, fwdFilter) }) } @@ -2144,7 +2162,7 @@ func (c *OpenChannel) RemoveFwdPkg(height uint64) error { c.Lock() defer c.Unlock() - return c.Db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.Db, func(tx kvdb.RwTx) error { return c.Packager.RemovePkg(tx, height) }) } @@ -2165,7 +2183,7 @@ func (c *OpenChannel) RevocationLogTail() (*ChannelCommitment, error) { } var commit ChannelCommitment - if err := c.Db.View(func(tx *bbolt.Tx) error { + if err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -2173,7 +2191,7 @@ func (c *OpenChannel) RevocationLogTail() (*ChannelCommitment, error) { return err } - logBucket := chanBucket.Bucket(revocationLogBucket) + logBucket := chanBucket.NestedReadBucket(revocationLogBucket) if logBucket == nil { return ErrNoPastDeltas } @@ -2182,7 +2200,7 @@ func (c *OpenChannel) RevocationLogTail() (*ChannelCommitment, error) { // this channel, we'll jump to the _last_ key in bucket. As we // store the update number on disk in a big-endian format, // this will retrieve the latest entry. - cursor := logBucket.Cursor() + cursor := logBucket.ReadCursor() _, tailLogEntry := cursor.Last() logEntryReader := bytes.NewReader(tailLogEntry) @@ -2212,7 +2230,7 @@ func (c *OpenChannel) CommitmentHeight() (uint64, error) { defer c.RUnlock() var height uint64 - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { // Get the bucket dedicated to storing the metadata for open // channels. chanBucket, err := fetchChanBucket( @@ -2247,7 +2265,7 @@ func (c *OpenChannel) FindPreviousState(updateNum uint64) (*ChannelCommitment, e defer c.RUnlock() var commit ChannelCommitment - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -2255,7 +2273,7 @@ func (c *OpenChannel) FindPreviousState(updateNum uint64) (*ChannelCommitment, e return err } - logBucket := chanBucket.Bucket(revocationLogBucket) + logBucket := chanBucket.NestedReadBucket(revocationLogBucket) if logBucket == nil { return ErrNoPastDeltas } @@ -2405,19 +2423,19 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary, c.Lock() defer c.Unlock() - return c.Db.Update(func(tx *bbolt.Tx) error { - openChanBucket := tx.Bucket(openChannelBucket) + return kvdb.Update(c.Db, func(tx kvdb.RwTx) error { + openChanBucket := tx.ReadWriteBucket(openChannelBucket) if openChanBucket == nil { return ErrNoChanDBExists } nodePub := c.IdentityPub.SerializeCompressed() - nodeChanBucket := openChanBucket.Bucket(nodePub) + nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub) if nodeChanBucket == nil { return ErrNoActiveChannels } - chainBucket := nodeChanBucket.Bucket(c.ChainHash[:]) + chainBucket := nodeChanBucket.NestedReadWriteBucket(c.ChainHash[:]) if chainBucket == nil { return ErrNoActiveChannels } @@ -2428,7 +2446,9 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary, return err } chanKey := chanPointBuf.Bytes() - chanBucket := chainBucket.Bucket(chanKey) + chanBucket := chainBucket.NestedReadWriteBucket( + chanKey, + ) if chanBucket == nil { return ErrNoActiveChannels } @@ -2452,21 +2472,21 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary, // With the base channel data deleted, attempt to delete the // information stored within the revocation log. - logBucket := chanBucket.Bucket(revocationLogBucket) + logBucket := chanBucket.NestedReadWriteBucket(revocationLogBucket) if logBucket != nil { - err = chanBucket.DeleteBucket(revocationLogBucket) + err = chanBucket.DeleteNestedBucket(revocationLogBucket) if err != nil { return err } } - err = chainBucket.DeleteBucket(chanPointBuf.Bytes()) + err = chainBucket.DeleteNestedBucket(chanPointBuf.Bytes()) if err != nil { return err } // Add channel state to the historical channel bucket. - historicalBucket, err := tx.CreateBucketIfNotExists( + historicalBucket, err := tx.CreateTopLevelBucket( historicalChannelBucket, ) if err != nil { @@ -2570,7 +2590,7 @@ func (c *OpenChannel) Snapshot() *ChannelSnapshot { // latest fully committed state is returned. The first commitment returned is // the local commitment, and the second returned is the remote commitment. func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitment, error) { - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -2592,7 +2612,7 @@ func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitmen // acting on a possible contract breach to ensure, that the caller has the most // up to date information required to deliver justice. func (c *OpenChannel) RemoteRevocationStore() (shachain.Store, error) { - err := c.Db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.Db, func(tx kvdb.ReadTx) error { chanBucket, err := fetchChanBucket( tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash, ) @@ -2609,10 +2629,10 @@ func (c *OpenChannel) RemoteRevocationStore() (shachain.Store, error) { return c.RevocationStore, nil } -func putChannelCloseSummary(tx *bbolt.Tx, chanID []byte, +func putChannelCloseSummary(tx kvdb.RwTx, chanID []byte, summary *ChannelCloseSummary, lastChanState *OpenChannel) error { - closedChanBucket, err := tx.CreateBucketIfNotExists(closedChannelBucket) + closedChanBucket, err := tx.CreateTopLevelBucket(closedChannelBucket) if err != nil { return err } @@ -2788,7 +2808,7 @@ func fundingTxPresent(channel *OpenChannel) bool { !channel.hasChanStatus(ChanStatusRestored) } -func putChanInfo(chanBucket *bbolt.Bucket, channel *OpenChannel) error { +func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error { var w bytes.Buffer if err := WriteElements(&w, channel.ChanType, channel.ChainHash, channel.FundingOutpoint, @@ -2835,7 +2855,7 @@ func putChanInfo(chanBucket *bbolt.Bucket, channel *OpenChannel) error { // putOptionalUpfrontShutdownScript adds a shutdown script under the key // provided if it has a non-zero length. -func putOptionalUpfrontShutdownScript(chanBucket *bbolt.Bucket, key []byte, +func putOptionalUpfrontShutdownScript(chanBucket kvdb.RwBucket, key []byte, script []byte) error { // If the script is empty, we do not need to add anything. if len(script) == 0 { @@ -2853,7 +2873,7 @@ func putOptionalUpfrontShutdownScript(chanBucket *bbolt.Bucket, key []byte, // getOptionalUpfrontShutdownScript reads the shutdown script stored under the // key provided if it is present. Upfront shutdown scripts are optional, so the // function returns with no error if the key is not present. -func getOptionalUpfrontShutdownScript(chanBucket *bbolt.Bucket, key []byte, +func getOptionalUpfrontShutdownScript(chanBucket kvdb.ReadBucket, key []byte, script *lnwire.DeliveryAddress) error { // Return early if the bucket does not exit, a shutdown script was not set. @@ -2885,7 +2905,7 @@ func serializeChanCommit(w io.Writer, c *ChannelCommitment) error { return SerializeHtlcs(w, c.Htlcs...) } -func putChanCommitment(chanBucket *bbolt.Bucket, c *ChannelCommitment, +func putChanCommitment(chanBucket kvdb.RwBucket, c *ChannelCommitment, local bool) error { var commitKey []byte @@ -2903,7 +2923,7 @@ func putChanCommitment(chanBucket *bbolt.Bucket, c *ChannelCommitment, return chanBucket.Put(commitKey, b.Bytes()) } -func putChanCommitments(chanBucket *bbolt.Bucket, channel *OpenChannel) error { +func putChanCommitments(chanBucket kvdb.RwBucket, channel *OpenChannel) error { // If this is a restored channel, then we don't have any commitments to // write. if channel.hasChanStatus(ChanStatusRestored) { @@ -2922,7 +2942,7 @@ func putChanCommitments(chanBucket *bbolt.Bucket, channel *OpenChannel) error { ) } -func putChanRevocationState(chanBucket *bbolt.Bucket, channel *OpenChannel) error { +func putChanRevocationState(chanBucket kvdb.RwBucket, channel *OpenChannel) error { var b bytes.Buffer err := WriteElements( @@ -2957,7 +2977,7 @@ func readChanConfig(b io.Reader, c *ChannelConfig) error { ) } -func fetchChanInfo(chanBucket *bbolt.Bucket, channel *OpenChannel) error { +func fetchChanInfo(chanBucket kvdb.ReadBucket, channel *OpenChannel) error { infoBytes := chanBucket.Get(chanInfoKey) if infoBytes == nil { return ErrNoChanInfoFound @@ -3024,7 +3044,7 @@ func deserializeChanCommit(r io.Reader) (ChannelCommitment, error) { return c, nil } -func fetchChanCommitment(chanBucket *bbolt.Bucket, local bool) (ChannelCommitment, error) { +func fetchChanCommitment(chanBucket kvdb.ReadBucket, local bool) (ChannelCommitment, error) { var commitKey []byte if local { commitKey = append(chanCommitmentKey, byte(0x00)) @@ -3041,7 +3061,7 @@ func fetchChanCommitment(chanBucket *bbolt.Bucket, local bool) (ChannelCommitmen return deserializeChanCommit(r) } -func fetchChanCommitments(chanBucket *bbolt.Bucket, channel *OpenChannel) error { +func fetchChanCommitments(chanBucket kvdb.ReadBucket, channel *OpenChannel) error { var err error // If this is a restored channel, then we don't have any commitments to @@ -3062,7 +3082,7 @@ func fetchChanCommitments(chanBucket *bbolt.Bucket, channel *OpenChannel) error return nil } -func fetchChanRevocationState(chanBucket *bbolt.Bucket, channel *OpenChannel) error { +func fetchChanRevocationState(chanBucket kvdb.ReadBucket, channel *OpenChannel) error { revBytes := chanBucket.Get(revocationStateKey) if revBytes == nil { return ErrNoRevocationsFound @@ -3088,7 +3108,7 @@ func fetchChanRevocationState(chanBucket *bbolt.Bucket, channel *OpenChannel) er return ReadElements(r, &channel.RemoteNextRevocation) } -func deleteOpenChannel(chanBucket *bbolt.Bucket, chanPointBytes []byte) error { +func deleteOpenChannel(chanBucket kvdb.RwBucket, chanPointBytes []byte) error { if err := chanBucket.Delete(chanInfoKey); err != nil { return err @@ -3122,7 +3142,7 @@ func makeLogKey(updateNum uint64) [8]byte { return key } -func appendChannelLogEntry(log *bbolt.Bucket, +func appendChannelLogEntry(log kvdb.RwBucket, commit *ChannelCommitment) error { var b bytes.Buffer @@ -3134,7 +3154,7 @@ func appendChannelLogEntry(log *bbolt.Bucket, return log.Put(logEntrykey[:], b.Bytes()) } -func fetchChannelLogEntry(log *bbolt.Bucket, +func fetchChannelLogEntry(log kvdb.ReadBucket, updateNum uint64) (ChannelCommitment, error) { logEntrykey := makeLogKey(updateNum) diff --git a/channeldb/db.go b/channeldb/db.go index 5fd0bc2022..c2842b1815 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -11,7 +11,6 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/channeldb/migration12" @@ -142,7 +141,7 @@ var ( // information related to nodes, routing data, open/closed channels, fee // schedules, and reputation data. type DB struct { - *bbolt.DB + kvdb.Backend dbPath string graph *ChannelGraph clock clock.Clock @@ -166,20 +165,15 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) { // Specify bbolt freelist options to reduce heap pressure in case the // freelist grows to be very large. - options := &bbolt.Options{ - NoFreelistSync: opts.NoFreelistSync, - FreelistType: bbolt.FreelistMapType, - } - - bdb, err := bbolt.Open(path, dbFilePermission, options) + bdb, err := kvdb.Open(kvdb.BoltBackendName, path, opts.NoFreelistSync) if err != nil { return nil, err } chanDB := &DB{ - DB: bdb, - dbPath: dbPath, - clock: opts.clock, + Backend: bdb, + dbPath: dbPath, + clock: opts.clock, } chanDB.graph = newChannelGraph( chanDB, opts.RejectCacheSize, opts.ChannelCacheSize, @@ -203,41 +197,41 @@ func (d *DB) Path() string { // database. The deletion is done in a single transaction, therefore this // operation is fully atomic. func (d *DB) Wipe() error { - return d.Update(func(tx *bbolt.Tx) error { - err := tx.DeleteBucket(openChannelBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + return kvdb.Update(d, func(tx kvdb.RwTx) error { + err := tx.DeleteTopLevelBucket(openChannelBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } - err = tx.DeleteBucket(closedChannelBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(closedChannelBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } - err = tx.DeleteBucket(invoiceBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(invoiceBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } - err = tx.DeleteBucket(nodeInfoBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(nodeInfoBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } - err = tx.DeleteBucket(nodeBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(nodeBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } - err = tx.DeleteBucket(edgeBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(edgeBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } - err = tx.DeleteBucket(edgeIndexBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(edgeIndexBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } - err = tx.DeleteBucket(graphMetaBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(graphMetaBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } @@ -257,36 +251,36 @@ func createChannelDB(dbPath string) error { } path := filepath.Join(dbPath, dbName) - bdb, err := bbolt.Open(path, dbFilePermission, nil) + bdb, err := kvdb.Create(kvdb.BoltBackendName, path, true) if err != nil { return err } - err = bdb.Update(func(tx *bbolt.Tx) error { - if _, err := tx.CreateBucket(openChannelBucket); err != nil { + err = kvdb.Update(bdb, func(tx kvdb.RwTx) error { + if _, err := tx.CreateTopLevelBucket(openChannelBucket); err != nil { return err } - if _, err := tx.CreateBucket(closedChannelBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(closedChannelBucket); err != nil { return err } - if _, err := tx.CreateBucket(forwardingLogBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(forwardingLogBucket); err != nil { return err } - if _, err := tx.CreateBucket(fwdPackagesKey); err != nil { + if _, err := tx.CreateTopLevelBucket(fwdPackagesKey); err != nil { return err } - if _, err := tx.CreateBucket(invoiceBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(invoiceBucket); err != nil { return err } - if _, err := tx.CreateBucket(nodeInfoBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(nodeInfoBucket); err != nil { return err } - nodes, err := tx.CreateBucket(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return err } @@ -299,7 +293,7 @@ func createChannelDB(dbPath string) error { return err } - edges, err := tx.CreateBucket(edgeBucket) + edges, err := tx.CreateTopLevelBucket(edgeBucket) if err != nil { return err } @@ -316,7 +310,7 @@ func createChannelDB(dbPath string) error { return err } - graphMeta, err := tx.CreateBucket(graphMetaBucket) + graphMeta, err := tx.CreateTopLevelBucket(graphMetaBucket) if err != nil { return err } @@ -325,7 +319,7 @@ func createChannelDB(dbPath string) error { return err } - if _, err := tx.CreateBucket(metaBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(metaBucket); err != nil { return err } @@ -358,7 +352,7 @@ func fileExists(path string) bool { // zero-length slice is returned. func (d *DB) FetchOpenChannels(nodeID *btcec.PublicKey) ([]*OpenChannel, error) { var channels []*OpenChannel - err := d.View(func(tx *bbolt.Tx) error { + err := kvdb.View(d, func(tx kvdb.ReadTx) error { var err error channels, err = d.fetchOpenChannels(tx, nodeID) return err @@ -371,11 +365,11 @@ func (d *DB) FetchOpenChannels(nodeID *btcec.PublicKey) ([]*OpenChannel, error) // stored currently active/open channels associated with the target nodeID. In // the case that no active channels are known to have been created with this // node, then a zero-length slice is returned. -func (d *DB) fetchOpenChannels(tx *bbolt.Tx, +func (d *DB) fetchOpenChannels(tx kvdb.ReadTx, nodeID *btcec.PublicKey) ([]*OpenChannel, error) { // Get the bucket dedicated to storing the metadata for open channels. - openChanBucket := tx.Bucket(openChannelBucket) + openChanBucket := tx.ReadBucket(openChannelBucket) if openChanBucket == nil { return nil, nil } @@ -383,7 +377,7 @@ func (d *DB) fetchOpenChannels(tx *bbolt.Tx, // Within this top level bucket, fetch the bucket dedicated to storing // open channel data specific to the remote node. pub := nodeID.SerializeCompressed() - nodeChanBucket := openChanBucket.Bucket(pub) + nodeChanBucket := openChanBucket.NestedReadBucket(pub) if nodeChanBucket == nil { return nil, nil } @@ -399,7 +393,7 @@ func (d *DB) fetchOpenChannels(tx *bbolt.Tx, // If we've found a valid chainhash bucket, then we'll retrieve // that so we can extract all the channels. - chainBucket := nodeChanBucket.Bucket(chainHash) + chainBucket := nodeChanBucket.NestedReadBucket(chainHash) if chainBucket == nil { return fmt.Errorf("unable to read bucket for chain=%x", chainHash[:]) @@ -424,7 +418,7 @@ func (d *DB) fetchOpenChannels(tx *bbolt.Tx, // fetchNodeChannels retrieves all active channels from the target chainBucket // which is under a node's dedicated channel bucket. This function is typically // used to fetch all the active channels related to a particular node. -func (d *DB) fetchNodeChannels(chainBucket *bbolt.Bucket) ([]*OpenChannel, error) { +func (d *DB) fetchNodeChannels(chainBucket kvdb.ReadBucket) ([]*OpenChannel, error) { var channels []*OpenChannel @@ -438,7 +432,7 @@ func (d *DB) fetchNodeChannels(chainBucket *bbolt.Bucket) ([]*OpenChannel, error // Once we've found a valid channel bucket, we'll extract it // from the node's chain bucket. - chanBucket := chainBucket.Bucket(chanPoint) + chanBucket := chainBucket.NestedReadBucket(chanPoint) var outPoint wire.OutPoint err := readOutpoint(bytes.NewReader(chanPoint), &outPoint) @@ -483,10 +477,10 @@ func (d *DB) FetchChannel(chanPoint wire.OutPoint) (*OpenChannel, error) { // structure and skipping fully decoding each channel, we save a good // bit of CPU as we don't need to do things like decompress public // keys. - chanScan := func(tx *bbolt.Tx) error { + chanScan := func(tx kvdb.ReadTx) error { // Get the bucket dedicated to storing the metadata for open // channels. - openChanBucket := tx.Bucket(openChannelBucket) + openChanBucket := tx.ReadBucket(openChannelBucket) if openChanBucket == nil { return ErrNoActiveChannels } @@ -501,7 +495,7 @@ func (d *DB) FetchChannel(chanPoint wire.OutPoint) (*OpenChannel, error) { return nil } - nodeChanBucket := openChanBucket.Bucket(nodePub) + nodeChanBucket := openChanBucket.NestedReadBucket(nodePub) if nodeChanBucket == nil { return nil } @@ -515,7 +509,9 @@ func (d *DB) FetchChannel(chanPoint wire.OutPoint) (*OpenChannel, error) { return nil } - chainBucket := nodeChanBucket.Bucket(chainHash) + chainBucket := nodeChanBucket.NestedReadBucket( + chainHash, + ) if chainBucket == nil { return fmt.Errorf("unable to read "+ "bucket for chain=%x", chainHash[:]) @@ -523,7 +519,7 @@ func (d *DB) FetchChannel(chanPoint wire.OutPoint) (*OpenChannel, error) { // Finally we reach the leaf bucket that stores // all the chanPoints for this node. - chanBucket := chainBucket.Bucket( + chanBucket := chainBucket.NestedReadBucket( targetChanPoint.Bytes(), ) if chanBucket == nil { @@ -545,7 +541,7 @@ func (d *DB) FetchChannel(chanPoint wire.OutPoint) (*OpenChannel, error) { }) } - err := d.View(chanScan) + err := kvdb.View(d, chanScan) if err != nil { return nil, err } @@ -637,10 +633,10 @@ func waitingCloseFilter(waitingClose bool) fetchChannelsFilter { func fetchChannels(d *DB, filters ...fetchChannelsFilter) ([]*OpenChannel, error) { var channels []*OpenChannel - err := d.View(func(tx *bbolt.Tx) error { + err := kvdb.View(d, func(tx kvdb.ReadTx) error { // Get the bucket dedicated to storing the metadata for open // channels. - openChanBucket := tx.Bucket(openChannelBucket) + openChanBucket := tx.ReadBucket(openChannelBucket) if openChanBucket == nil { return ErrNoActiveChannels } @@ -648,7 +644,7 @@ func fetchChannels(d *DB, filters ...fetchChannelsFilter) ([]*OpenChannel, error // Next, fetch the bucket dedicated to storing metadata related // to all nodes. All keys within this bucket are the serialized // public keys of all our direct counterparties. - nodeMetaBucket := tx.Bucket(nodeInfoBucket) + nodeMetaBucket := tx.ReadBucket(nodeInfoBucket) if nodeMetaBucket == nil { return fmt.Errorf("node bucket not created") } @@ -656,7 +652,7 @@ func fetchChannels(d *DB, filters ...fetchChannelsFilter) ([]*OpenChannel, error // Finally for each node public key in the bucket, fetch all // the channels related to this particular node. return nodeMetaBucket.ForEach(func(k, v []byte) error { - nodeChanBucket := openChanBucket.Bucket(k) + nodeChanBucket := openChanBucket.NestedReadBucket(k) if nodeChanBucket == nil { return nil } @@ -671,7 +667,9 @@ func fetchChannels(d *DB, filters ...fetchChannelsFilter) ([]*OpenChannel, error // If we've found a valid chainhash bucket, // then we'll retrieve that so we can extract // all the channels. - chainBucket := nodeChanBucket.Bucket(chainHash) + chainBucket := nodeChanBucket.NestedReadBucket( + chainHash, + ) if chainBucket == nil { return fmt.Errorf("unable to read "+ "bucket for chain=%x", chainHash[:]) @@ -727,8 +725,8 @@ func fetchChannels(d *DB, filters ...fetchChannelsFilter) ([]*OpenChannel, error func (d *DB) FetchClosedChannels(pendingOnly bool) ([]*ChannelCloseSummary, error) { var chanSummaries []*ChannelCloseSummary - if err := d.View(func(tx *bbolt.Tx) error { - closeBucket := tx.Bucket(closedChannelBucket) + if err := kvdb.View(d, func(tx kvdb.ReadTx) error { + closeBucket := tx.ReadBucket(closedChannelBucket) if closeBucket == nil { return ErrNoClosedChannels } @@ -765,8 +763,8 @@ var ErrClosedChannelNotFound = errors.New("unable to find closed channel summary // point of the channel in question. func (d *DB) FetchClosedChannel(chanID *wire.OutPoint) (*ChannelCloseSummary, error) { var chanSummary *ChannelCloseSummary - if err := d.View(func(tx *bbolt.Tx) error { - closeBucket := tx.Bucket(closedChannelBucket) + if err := kvdb.View(d, func(tx kvdb.ReadTx) error { + closeBucket := tx.ReadBucket(closedChannelBucket) if closeBucket == nil { return ErrClosedChannelNotFound } @@ -799,15 +797,15 @@ func (d *DB) FetchClosedChannelForID(cid lnwire.ChannelID) ( *ChannelCloseSummary, error) { var chanSummary *ChannelCloseSummary - if err := d.View(func(tx *bbolt.Tx) error { - closeBucket := tx.Bucket(closedChannelBucket) + if err := kvdb.View(d, func(tx kvdb.ReadTx) error { + closeBucket := tx.ReadBucket(closedChannelBucket) if closeBucket == nil { return ErrClosedChannelNotFound } // The first 30 bytes of the channel ID and outpoint will be // equal. - cursor := closeBucket.Cursor() + cursor := closeBucket.ReadCursor() op, c := cursor.Seek(cid[:30]) // We scan over all possible candidates for this channel ID. @@ -847,7 +845,7 @@ func (d *DB) FetchClosedChannelForID(cid lnwire.ChannelID) ( // the pending funds in a channel that has been forcibly closed have been // swept. func (d *DB) MarkChanFullyClosed(chanPoint *wire.OutPoint) error { - return d.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(d, func(tx kvdb.RwTx) error { var b bytes.Buffer if err := writeOutpoint(&b, chanPoint); err != nil { return err @@ -855,7 +853,7 @@ func (d *DB) MarkChanFullyClosed(chanPoint *wire.OutPoint) error { chanID := b.Bytes() - closedChanBucket, err := tx.CreateBucketIfNotExists( + closedChanBucket, err := tx.CreateTopLevelBucket( closedChannelBucket, ) if err != nil { @@ -900,7 +898,7 @@ func (d *DB) MarkChanFullyClosed(chanPoint *wire.OutPoint) error { // pruneLinkNode determines whether we should garbage collect a link node from // the database due to no longer having any open channels with it. If there are // any left, then this acts as a no-op. -func (d *DB) pruneLinkNode(tx *bbolt.Tx, remotePub *btcec.PublicKey) error { +func (d *DB) pruneLinkNode(tx kvdb.RwTx, remotePub *btcec.PublicKey) error { openChannels, err := d.fetchOpenChannels(tx, remotePub) if err != nil { return fmt.Errorf("unable to fetch open channels for peer %x: "+ @@ -920,7 +918,7 @@ func (d *DB) pruneLinkNode(tx *bbolt.Tx, remotePub *btcec.PublicKey) error { // PruneLinkNodes attempts to prune all link nodes found within the databse with // whom we no longer have any open channels with. func (d *DB) PruneLinkNodes() error { - return d.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(d, func(tx kvdb.RwTx) error { linkNodes, err := d.fetchAllLinkNodes(tx) if err != nil { return err @@ -964,7 +962,7 @@ func (d *DB) RestoreChannelShells(channelShells ...*ChannelShell) error { defer chanGraph.cacheMu.Unlock() var chansRestored []uint64 - err := d.Update(func(tx *bbolt.Tx) error { + err := kvdb.Update(d, func(tx kvdb.RwTx) error { for _, channelShell := range channelShells { channel := channelShell.Chan @@ -1001,7 +999,7 @@ func (d *DB) RestoreChannelShells(channelShells ...*ChannelShell) error { Capacity: channel.Capacity, } - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadWriteBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -1075,7 +1073,7 @@ func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error) { graphNode LightningNode ) - dbErr := d.View(func(tx *bbolt.Tx) error { + dbErr := kvdb.View(d, func(tx kvdb.ReadTx) error { var err error linkNode, err = fetchLinkNode(tx, nodePub) @@ -1086,7 +1084,7 @@ func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error) { // We'll also query the graph for this peer to see if they have // any addresses that we don't currently have stored within the // link node database. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -1213,7 +1211,7 @@ func (d *DB) syncVersions(versions []version) error { migrations, migrationVersions := getMigrationsToApply( versions, meta.DbVersionNumber, ) - return d.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(d, func(tx kvdb.RwTx) error { for i, migration := range migrations { if migration == nil { continue @@ -1261,12 +1259,12 @@ func getMigrationsToApply(versions []version, version uint32) ([]migration, []ui // fetchHistoricalChanBucket returns a the channel bucket for a given outpoint // from the historical channel bucket. If the bucket does not exist, // ErrNoHistoricalBucket is returned. -func fetchHistoricalChanBucket(tx *bbolt.Tx, - outPoint *wire.OutPoint) (*bbolt.Bucket, error) { +func fetchHistoricalChanBucket(tx kvdb.ReadTx, + outPoint *wire.OutPoint) (kvdb.ReadBucket, error) { // First fetch the top level bucket which stores all data related to // historically stored channels. - historicalChanBucket := tx.Bucket(historicalChannelBucket) + historicalChanBucket := tx.ReadBucket(historicalChannelBucket) if historicalChanBucket == nil { return nil, ErrNoHistoricalBucket } @@ -1277,7 +1275,7 @@ func fetchHistoricalChanBucket(tx *bbolt.Tx, if err := writeOutpoint(&chanPointBuf, outPoint); err != nil { return nil, err } - chanBucket := historicalChanBucket.Bucket(chanPointBuf.Bytes()) + chanBucket := historicalChanBucket.NestedReadBucket(chanPointBuf.Bytes()) if chanBucket == nil { return nil, ErrChannelNotFound } @@ -1289,7 +1287,7 @@ func fetchHistoricalChanBucket(tx *bbolt.Tx, // bucket. func (d *DB) FetchHistoricalChannel(outPoint *wire.OutPoint) (*OpenChannel, error) { var channel *OpenChannel - err := d.View(func(tx *bbolt.Tx) error { + err := kvdb.View(d, func(tx kvdb.ReadTx) error { chanBucket, err := fetchHistoricalChanBucket(tx, outPoint) if err != nil { return err diff --git a/channeldb/duplicate_payments.go b/channeldb/duplicate_payments.go index da9e969b0f..d5cbd1c2aa 100644 --- a/channeldb/duplicate_payments.go +++ b/channeldb/duplicate_payments.go @@ -8,7 +8,7 @@ import ( "time" "github.com/btcsuite/btcd/btcec" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -61,7 +61,7 @@ type duplicateHTLCAttemptInfo struct { // fetchDuplicatePaymentStatus fetches the payment status of the payment. If the // payment isn't found, it will default to "StatusUnknown". -func fetchDuplicatePaymentStatus(bucket *bbolt.Bucket) PaymentStatus { +func fetchDuplicatePaymentStatus(bucket kvdb.ReadBucket) PaymentStatus { if bucket.Get(duplicatePaymentSettleInfoKey) != nil { return StatusSucceeded } @@ -129,7 +129,7 @@ func deserializeDuplicatePaymentCreationInfo(r io.Reader) ( return c, nil } -func fetchDuplicatePayment(bucket *bbolt.Bucket) (*MPPayment, error) { +func fetchDuplicatePayment(bucket kvdb.ReadBucket) (*MPPayment, error) { seqBytes := bucket.Get(duplicatePaymentSequenceKey) if seqBytes == nil { return nil, fmt.Errorf("sequence number not found") @@ -209,7 +209,7 @@ func fetchDuplicatePayment(bucket *bbolt.Bucket) (*MPPayment, error) { return payment, nil } -func fetchDuplicatePayments(paymentHashBucket *bbolt.Bucket) ([]*MPPayment, +func fetchDuplicatePayments(paymentHashBucket kvdb.ReadBucket) ([]*MPPayment, error) { var payments []*MPPayment @@ -217,13 +217,13 @@ func fetchDuplicatePayments(paymentHashBucket *bbolt.Bucket) ([]*MPPayment, // For older versions of lnd, duplicate payments to a payment has was // possible. These will be found in a sub-bucket indexed by their // sequence number if available. - dup := paymentHashBucket.Bucket(duplicatePaymentsBucket) + dup := paymentHashBucket.NestedReadBucket(duplicatePaymentsBucket) if dup == nil { return nil, nil } err := dup.ForEach(func(k, v []byte) error { - subBucket := dup.Bucket(k) + subBucket := dup.NestedReadBucket(k) if subBucket == nil { // We one bucket for each duplicate to be found. return fmt.Errorf("non bucket element" + diff --git a/channeldb/forwarding_log.go b/channeldb/forwarding_log.go index 04e8719a2f..52596956fc 100644 --- a/channeldb/forwarding_log.go +++ b/channeldb/forwarding_log.go @@ -6,7 +6,7 @@ import ( "sort" "time" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -111,10 +111,10 @@ func (f *ForwardingLog) AddForwardingEvents(events []ForwardingEvent) error { var timestamp [8]byte - return f.db.Batch(func(tx *bbolt.Tx) error { + return kvdb.Batch(f.db.Backend, func(tx kvdb.RwTx) error { // First, we'll fetch the bucket that stores our time series // log. - logBucket, err := tx.CreateBucketIfNotExists( + logBucket, err := tx.CreateTopLevelBucket( forwardingLogBucket, ) if err != nil { @@ -204,10 +204,10 @@ func (f *ForwardingLog) Query(q ForwardingEventQuery) (ForwardingLogTimeSlice, e recordsToSkip := q.IndexOffset recordOffset := q.IndexOffset - err := f.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(f.db, func(tx kvdb.ReadTx) error { // If the bucket wasn't found, then there aren't any events to // be returned. - logBucket := tx.Bucket(forwardingLogBucket) + logBucket := tx.ReadBucket(forwardingLogBucket) if logBucket == nil { return ErrNoForwardingEvents } @@ -223,7 +223,7 @@ func (f *ForwardingLog) Query(q ForwardingEventQuery) (ForwardingLogTimeSlice, e // our seek through the log in order to satisfy the query. // We'll continue until either we reach the end of the range, // or reach our max number of events. - logCursor := logBucket.Cursor() + logCursor := logBucket.ReadCursor() timestamp, events := logCursor.Seek(startTime[:]) for ; timestamp != nil && bytes.Compare(timestamp, endTime[:]) <= 0; timestamp, events = logCursor.Next() { // If our current return payload exceeds the max number diff --git a/channeldb/forwarding_package.go b/channeldb/forwarding_package.go index 4808c55ca0..4ddcf55b3b 100644 --- a/channeldb/forwarding_package.go +++ b/channeldb/forwarding_package.go @@ -7,7 +7,7 @@ import ( "fmt" "io" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -318,7 +318,7 @@ type SettleFailRef struct { type SettleFailAcker interface { // AckSettleFails atomically updates the settle-fail filters in *other* // channels' forwarding packages. - AckSettleFails(tx *bbolt.Tx, settleFailRefs ...SettleFailRef) error + AckSettleFails(tx kvdb.RwTx, settleFailRefs ...SettleFailRef) error } // GlobalFwdPkgReader is an interface used to retrieve the forwarding packages @@ -326,7 +326,7 @@ type SettleFailAcker interface { type GlobalFwdPkgReader interface { // LoadChannelFwdPkgs loads all known forwarding packages for the given // channel. - LoadChannelFwdPkgs(tx *bbolt.Tx, + LoadChannelFwdPkgs(tx kvdb.RwTx, source lnwire.ShortChannelID) ([]*FwdPkg, error) } @@ -357,14 +357,14 @@ func NewSwitchPackager() *SwitchPackager { // AckSettleFails atomically updates the settle-fail filters in *other* // channels' forwarding packages, to mark that the switch has received a settle // or fail residing in the forwarding package of a link. -func (*SwitchPackager) AckSettleFails(tx *bbolt.Tx, +func (*SwitchPackager) AckSettleFails(tx kvdb.RwTx, settleFailRefs ...SettleFailRef) error { return ackSettleFails(tx, settleFailRefs) } // LoadChannelFwdPkgs loads all forwarding packages for a particular channel. -func (*SwitchPackager) LoadChannelFwdPkgs(tx *bbolt.Tx, +func (*SwitchPackager) LoadChannelFwdPkgs(tx kvdb.RwTx, source lnwire.ShortChannelID) ([]*FwdPkg, error) { return loadChannelFwdPkgs(tx, source) @@ -376,19 +376,19 @@ func (*SwitchPackager) LoadChannelFwdPkgs(tx *bbolt.Tx, type FwdPackager interface { // AddFwdPkg serializes and writes a FwdPkg for this channel at the // remote commitment height included in the forwarding package. - AddFwdPkg(tx *bbolt.Tx, fwdPkg *FwdPkg) error + AddFwdPkg(tx kvdb.RwTx, fwdPkg *FwdPkg) error // SetFwdFilter looks up the forwarding package at the remote `height` // and sets the `fwdFilter`, marking the Adds for which: // 1) We are not the exit node // 2) Passed all validation // 3) Should be forwarded to the switch immediately after a failure - SetFwdFilter(tx *bbolt.Tx, height uint64, fwdFilter *PkgFilter) error + SetFwdFilter(tx kvdb.RwTx, height uint64, fwdFilter *PkgFilter) error // AckAddHtlcs atomically updates the add filters in this channel's // forwarding packages to mark the resolution of an Add that was // received from the remote party. - AckAddHtlcs(tx *bbolt.Tx, addRefs ...AddRef) error + AckAddHtlcs(tx kvdb.RwTx, addRefs ...AddRef) error // SettleFailAcker allows a link to acknowledge settle/fail HTLCs // belonging to other channels. @@ -396,11 +396,11 @@ type FwdPackager interface { // LoadFwdPkgs loads all known forwarding packages owned by this // channel. - LoadFwdPkgs(tx *bbolt.Tx) ([]*FwdPkg, error) + LoadFwdPkgs(tx kvdb.ReadTx) ([]*FwdPkg, error) // RemovePkg deletes a forwarding package owned by this channel at // the provided remote `height`. - RemovePkg(tx *bbolt.Tx, height uint64) error + RemovePkg(tx kvdb.RwTx, height uint64) error } // ChannelPackager is used by a channel to manage the lifecycle of its forwarding @@ -420,8 +420,8 @@ func NewChannelPackager(source lnwire.ShortChannelID) *ChannelPackager { } // AddFwdPkg writes a newly locked in forwarding package to disk. -func (*ChannelPackager) AddFwdPkg(tx *bbolt.Tx, fwdPkg *FwdPkg) error { - fwdPkgBkt, err := tx.CreateBucketIfNotExists(fwdPackagesKey) +func (*ChannelPackager) AddFwdPkg(tx kvdb.RwTx, fwdPkg *FwdPkg) error { + fwdPkgBkt, err := tx.CreateTopLevelBucket(fwdPackagesKey) if err != nil { return err } @@ -485,7 +485,7 @@ func (*ChannelPackager) AddFwdPkg(tx *bbolt.Tx, fwdPkg *FwdPkg) error { } // putLogUpdate writes an htlc to the provided `bkt`, using `index` as the key. -func putLogUpdate(bkt *bbolt.Bucket, idx uint16, htlc *LogUpdate) error { +func putLogUpdate(bkt kvdb.RwBucket, idx uint16, htlc *LogUpdate) error { var b bytes.Buffer if err := htlc.Encode(&b); err != nil { return err @@ -497,19 +497,19 @@ func putLogUpdate(bkt *bbolt.Bucket, idx uint16, htlc *LogUpdate) error { // LoadFwdPkgs scans the forwarding log for any packages that haven't been // processed, and returns their deserialized log updates in a map indexed by the // remote commitment height at which the updates were locked in. -func (p *ChannelPackager) LoadFwdPkgs(tx *bbolt.Tx) ([]*FwdPkg, error) { +func (p *ChannelPackager) LoadFwdPkgs(tx kvdb.ReadTx) ([]*FwdPkg, error) { return loadChannelFwdPkgs(tx, p.source) } // loadChannelFwdPkgs loads all forwarding packages owned by `source`. -func loadChannelFwdPkgs(tx *bbolt.Tx, source lnwire.ShortChannelID) ([]*FwdPkg, error) { - fwdPkgBkt := tx.Bucket(fwdPackagesKey) +func loadChannelFwdPkgs(tx kvdb.ReadTx, source lnwire.ShortChannelID) ([]*FwdPkg, error) { + fwdPkgBkt := tx.ReadBucket(fwdPackagesKey) if fwdPkgBkt == nil { return nil, nil } sourceKey := makeLogKey(source.ToUint64()) - sourceBkt := fwdPkgBkt.Bucket(sourceKey[:]) + sourceBkt := fwdPkgBkt.NestedReadBucket(sourceKey[:]) if sourceBkt == nil { return nil, nil } @@ -543,23 +543,23 @@ func loadChannelFwdPkgs(tx *bbolt.Tx, source lnwire.ShortChannelID) ([]*FwdPkg, // loadFwPkg reads the packager's fwd pkg at a given height, and determines the // appropriate FwdState. -func loadFwdPkg(fwdPkgBkt *bbolt.Bucket, source lnwire.ShortChannelID, +func loadFwdPkg(fwdPkgBkt kvdb.ReadBucket, source lnwire.ShortChannelID, height uint64) (*FwdPkg, error) { sourceKey := makeLogKey(source.ToUint64()) - sourceBkt := fwdPkgBkt.Bucket(sourceKey[:]) + sourceBkt := fwdPkgBkt.NestedReadBucket(sourceKey[:]) if sourceBkt == nil { return nil, ErrCorruptedFwdPkg } heightKey := makeLogKey(height) - heightBkt := sourceBkt.Bucket(heightKey[:]) + heightBkt := sourceBkt.NestedReadBucket(heightKey[:]) if heightBkt == nil { return nil, ErrCorruptedFwdPkg } // Load ADDs from disk. - addBkt := heightBkt.Bucket(addBucketKey) + addBkt := heightBkt.NestedReadBucket(addBucketKey) if addBkt == nil { return nil, ErrCorruptedFwdPkg } @@ -582,7 +582,7 @@ func loadFwdPkg(fwdPkgBkt *bbolt.Bucket, source lnwire.ShortChannelID, } // Load SETTLE/FAILs from disk. - failSettleBkt := heightBkt.Bucket(failSettleBucketKey) + failSettleBkt := heightBkt.NestedReadBucket(failSettleBucketKey) if failSettleBkt == nil { return nil, ErrCorruptedFwdPkg } @@ -649,7 +649,7 @@ func loadFwdPkg(fwdPkgBkt *bbolt.Bucket, source lnwire.ShortChannelID, // loadHtlcs retrieves all serialized htlcs in a bucket, returning // them in order of the indexes they were written under. -func loadHtlcs(bkt *bbolt.Bucket) ([]LogUpdate, error) { +func loadHtlcs(bkt kvdb.ReadBucket) ([]LogUpdate, error) { var htlcs []LogUpdate if err := bkt.ForEach(func(_, v []byte) error { var htlc LogUpdate @@ -674,22 +674,22 @@ func loadHtlcs(bkt *bbolt.Bucket) ([]LogUpdate, error) { // leaving this channel. After a restart, we skip validation of these Adds, // since they are assumed to have already been validated, and make the switch or // outgoing link responsible for handling replays. -func (p *ChannelPackager) SetFwdFilter(tx *bbolt.Tx, height uint64, +func (p *ChannelPackager) SetFwdFilter(tx kvdb.RwTx, height uint64, fwdFilter *PkgFilter) error { - fwdPkgBkt := tx.Bucket(fwdPackagesKey) + fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) if fwdPkgBkt == nil { return ErrCorruptedFwdPkg } source := makeLogKey(p.source.ToUint64()) - sourceBkt := fwdPkgBkt.Bucket(source[:]) + sourceBkt := fwdPkgBkt.NestedReadWriteBucket(source[:]) if sourceBkt == nil { return ErrCorruptedFwdPkg } heightKey := makeLogKey(height) - heightBkt := sourceBkt.Bucket(heightKey[:]) + heightBkt := sourceBkt.NestedReadWriteBucket(heightKey[:]) if heightBkt == nil { return ErrCorruptedFwdPkg } @@ -713,18 +713,18 @@ func (p *ChannelPackager) SetFwdFilter(tx *bbolt.Tx, height uint64, // AckAddHtlcs accepts a list of references to add htlcs, and updates the // AckAddFilter of those forwarding packages to indicate that a settle or fail // has been received in response to the add. -func (p *ChannelPackager) AckAddHtlcs(tx *bbolt.Tx, addRefs ...AddRef) error { +func (p *ChannelPackager) AckAddHtlcs(tx kvdb.RwTx, addRefs ...AddRef) error { if len(addRefs) == 0 { return nil } - fwdPkgBkt := tx.Bucket(fwdPackagesKey) + fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) if fwdPkgBkt == nil { return ErrCorruptedFwdPkg } sourceKey := makeLogKey(p.source.ToUint64()) - sourceBkt := fwdPkgBkt.Bucket(sourceKey[:]) + sourceBkt := fwdPkgBkt.NestedReadWriteBucket(sourceKey[:]) if sourceBkt == nil { return ErrCorruptedFwdPkg } @@ -753,11 +753,11 @@ func (p *ChannelPackager) AckAddHtlcs(tx *bbolt.Tx, addRefs ...AddRef) error { // ackAddHtlcsAtHeight updates the AddAckFilter of a single forwarding package // with a list of indexes, writing the resulting filter back in its place. -func ackAddHtlcsAtHeight(sourceBkt *bbolt.Bucket, height uint64, +func ackAddHtlcsAtHeight(sourceBkt kvdb.RwBucket, height uint64, indexes []uint16) error { heightKey := makeLogKey(height) - heightBkt := sourceBkt.Bucket(heightKey[:]) + heightBkt := sourceBkt.NestedReadWriteBucket(heightKey[:]) if heightBkt == nil { // If the height bucket isn't found, this could be because the // forwarding package was already removed. We'll return nil to @@ -796,17 +796,17 @@ func ackAddHtlcsAtHeight(sourceBkt *bbolt.Bucket, height uint64, // package. This should only be called after the source of the Add has locked in // the settle/fail, or it becomes otherwise safe to forgo retransmitting the // settle/fail after a restart. -func (p *ChannelPackager) AckSettleFails(tx *bbolt.Tx, settleFailRefs ...SettleFailRef) error { +func (p *ChannelPackager) AckSettleFails(tx kvdb.RwTx, settleFailRefs ...SettleFailRef) error { return ackSettleFails(tx, settleFailRefs) } // ackSettleFails persistently acknowledges a batch of settle fail references. -func ackSettleFails(tx *bbolt.Tx, settleFailRefs []SettleFailRef) error { +func ackSettleFails(tx kvdb.RwTx, settleFailRefs []SettleFailRef) error { if len(settleFailRefs) == 0 { return nil } - fwdPkgBkt := tx.Bucket(fwdPackagesKey) + fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) if fwdPkgBkt == nil { return ErrCorruptedFwdPkg } @@ -832,7 +832,7 @@ func ackSettleFails(tx *bbolt.Tx, settleFailRefs []SettleFailRef) error { // settle/fail htlcs. for dest, destHeights := range destHeightDiffs { destKey := makeLogKey(dest.ToUint64()) - destBkt := fwdPkgBkt.Bucket(destKey[:]) + destBkt := fwdPkgBkt.NestedReadWriteBucket(destKey[:]) if destBkt == nil { // If the destination bucket is not found, this is // likely the result of the destination channel being @@ -855,11 +855,11 @@ func ackSettleFails(tx *bbolt.Tx, settleFailRefs []SettleFailRef) error { // ackSettleFailsAtHeight given a destination bucket, acks the provided indexes // at particular a height by updating the settle fail filter. -func ackSettleFailsAtHeight(destBkt *bbolt.Bucket, height uint64, +func ackSettleFailsAtHeight(destBkt kvdb.RwBucket, height uint64, indexes []uint16) error { heightKey := makeLogKey(height) - heightBkt := destBkt.Bucket(heightKey[:]) + heightBkt := destBkt.NestedReadWriteBucket(heightKey[:]) if heightBkt == nil { // If the height bucket isn't found, this could be because the // forwarding package was already removed. We'll return nil to @@ -895,21 +895,21 @@ func ackSettleFailsAtHeight(destBkt *bbolt.Bucket, height uint64, // RemovePkg deletes the forwarding package at the given height from the // packager's source bucket. -func (p *ChannelPackager) RemovePkg(tx *bbolt.Tx, height uint64) error { - fwdPkgBkt := tx.Bucket(fwdPackagesKey) +func (p *ChannelPackager) RemovePkg(tx kvdb.RwTx, height uint64) error { + fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) if fwdPkgBkt == nil { return nil } sourceBytes := makeLogKey(p.source.ToUint64()) - sourceBkt := fwdPkgBkt.Bucket(sourceBytes[:]) + sourceBkt := fwdPkgBkt.NestedReadWriteBucket(sourceBytes[:]) if sourceBkt == nil { return ErrCorruptedFwdPkg } heightKey := makeLogKey(height) - return sourceBkt.DeleteBucket(heightKey[:]) + return sourceBkt.DeleteNestedBucket(heightKey[:]) } // uint16Key writes the provided 16-bit unsigned integer to a 2-byte slice. diff --git a/channeldb/forwarding_package_test.go b/channeldb/forwarding_package_test.go index 85fda950bd..52eaa0e05f 100644 --- a/channeldb/forwarding_package_test.go +++ b/channeldb/forwarding_package_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -207,7 +207,7 @@ func TestPackagerEmptyFwdPkg(t *testing.T) { // Next, create and write a new forwarding package with no htlcs. fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, nil, nil) - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AddFwdPkg(tx, fwdPkg) }); err != nil { t.Fatalf("unable to add fwd pkg: %v", err) @@ -226,7 +226,7 @@ func TestPackagerEmptyFwdPkg(t *testing.T) { // Now, write the forwarding decision. In this case, its just an empty // fwd filter. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter) }); err != nil { t.Fatalf("unable to set fwdfiter: %v", err) @@ -244,7 +244,7 @@ func TestPackagerEmptyFwdPkg(t *testing.T) { assertAckFilterIsFull(t, fwdPkgs[0], true) // Lastly, remove the completed forwarding package from disk. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.RemovePkg(tx, fwdPkg.Height) }); err != nil { t.Fatalf("unable to remove fwdpkg: %v", err) @@ -279,7 +279,7 @@ func TestPackagerOnlyAdds(t *testing.T) { nAdds := len(adds) - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AddFwdPkg(tx, fwdPkg) }); err != nil { t.Fatalf("unable to add fwd pkg: %v", err) @@ -300,7 +300,7 @@ func TestPackagerOnlyAdds(t *testing.T) { // added any adds to the fwdfilter, this would indicate that all of the // adds were 1) settled locally by this link (exit hop), or 2) the htlc // was failed locally. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter) }); err != nil { t.Fatalf("unable to set fwdfiter: %v", err) @@ -324,7 +324,7 @@ func TestPackagerOnlyAdds(t *testing.T) { Index: uint16(i), } - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AckAddHtlcs(tx, addRef) }); err != nil { t.Fatalf("unable to ack add htlc: %v", err) @@ -343,7 +343,7 @@ func TestPackagerOnlyAdds(t *testing.T) { assertAckFilterIsFull(t, fwdPkgs[0], true) // Lastly, remove the completed forwarding package from disk. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.RemovePkg(tx, fwdPkg.Height) }); err != nil { t.Fatalf("unable to remove fwdpkg: %v", err) @@ -381,7 +381,7 @@ func TestPackagerOnlySettleFails(t *testing.T) { nSettleFails := len(settleFails) - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AddFwdPkg(tx, fwdPkg) }); err != nil { t.Fatalf("unable to add fwd pkg: %v", err) @@ -402,7 +402,7 @@ func TestPackagerOnlySettleFails(t *testing.T) { // added any adds to the fwdfilter, this would indicate that all of the // adds were 1) settled locally by this link (exit hop), or 2) the htlc // was failed locally. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter) }); err != nil { t.Fatalf("unable to set fwdfiter: %v", err) @@ -428,7 +428,7 @@ func TestPackagerOnlySettleFails(t *testing.T) { Index: uint16(i), } - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AckSettleFails(tx, failSettleRef) }); err != nil { t.Fatalf("unable to ack add htlc: %v", err) @@ -448,7 +448,7 @@ func TestPackagerOnlySettleFails(t *testing.T) { assertAckFilterIsFull(t, fwdPkgs[0], true) // Lastly, remove the completed forwarding package from disk. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.RemovePkg(tx, fwdPkg.Height) }); err != nil { t.Fatalf("unable to remove fwdpkg: %v", err) @@ -486,7 +486,7 @@ func TestPackagerAddsThenSettleFails(t *testing.T) { nAdds := len(adds) nSettleFails := len(settleFails) - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AddFwdPkg(tx, fwdPkg) }); err != nil { t.Fatalf("unable to add fwd pkg: %v", err) @@ -507,7 +507,7 @@ func TestPackagerAddsThenSettleFails(t *testing.T) { // added any adds to the fwdfilter, this would indicate that all of the // adds were 1) settled locally by this link (exit hop), or 2) the htlc // was failed locally. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter) }); err != nil { t.Fatalf("unable to set fwdfiter: %v", err) @@ -532,7 +532,7 @@ func TestPackagerAddsThenSettleFails(t *testing.T) { Index: uint16(i), } - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AckAddHtlcs(tx, addRef) }); err != nil { t.Fatalf("unable to ack add htlc: %v", err) @@ -559,7 +559,7 @@ func TestPackagerAddsThenSettleFails(t *testing.T) { Index: uint16(i), } - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AckSettleFails(tx, failSettleRef) }); err != nil { t.Fatalf("unable to remove settle/fail htlc: %v", err) @@ -579,7 +579,7 @@ func TestPackagerAddsThenSettleFails(t *testing.T) { assertAckFilterIsFull(t, fwdPkgs[0], true) // Lastly, remove the completed forwarding package from disk. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.RemovePkg(tx, fwdPkg.Height) }); err != nil { t.Fatalf("unable to remove fwdpkg: %v", err) @@ -619,7 +619,7 @@ func TestPackagerSettleFailsThenAdds(t *testing.T) { nAdds := len(adds) nSettleFails := len(settleFails) - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AddFwdPkg(tx, fwdPkg) }); err != nil { t.Fatalf("unable to add fwd pkg: %v", err) @@ -640,7 +640,7 @@ func TestPackagerSettleFailsThenAdds(t *testing.T) { // added any adds to the fwdfilter, this would indicate that all of the // adds were 1) settled locally by this link (exit hop), or 2) the htlc // was failed locally. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter) }); err != nil { t.Fatalf("unable to set fwdfiter: %v", err) @@ -669,7 +669,7 @@ func TestPackagerSettleFailsThenAdds(t *testing.T) { Index: uint16(i), } - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AckSettleFails(tx, failSettleRef) }); err != nil { t.Fatalf("unable to remove settle/fail htlc: %v", err) @@ -696,7 +696,7 @@ func TestPackagerSettleFailsThenAdds(t *testing.T) { Index: uint16(i), } - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.AckAddHtlcs(tx, addRef) }); err != nil { t.Fatalf("unable to ack add htlc: %v", err) @@ -716,7 +716,7 @@ func TestPackagerSettleFailsThenAdds(t *testing.T) { assertAckFilterIsFull(t, fwdPkgs[0], true) // Lastly, remove the completed forwarding package from disk. - if err := db.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(db, func(tx kvdb.RwTx) error { return packager.RemovePkg(tx, fwdPkg.Height) }); err != nil { t.Fatalf("unable to remove fwdpkg: %v", err) @@ -778,11 +778,11 @@ func assertSettleFailFilterIsFull(t *testing.T, fwdPkg *channeldb.FwdPkg, expect // loadFwdPkgs is a helper method that reads all forwarding packages for a // particular packager. -func loadFwdPkgs(t *testing.T, db *bbolt.DB, +func loadFwdPkgs(t *testing.T, db kvdb.Backend, packager channeldb.FwdPackager) []*channeldb.FwdPkg { var fwdPkgs []*channeldb.FwdPkg - if err := db.View(func(tx *bbolt.Tx) error { + if err := kvdb.View(db, func(tx kvdb.ReadTx) error { var err error fwdPkgs, err = packager.LoadFwdPkgs(tx) return err @@ -795,7 +795,7 @@ func loadFwdPkgs(t *testing.T, db *bbolt.DB, // makeFwdPkgDB initializes a test database for forwarding packages. If the // provided path is an empty, it will create a temp dir/file to use. -func makeFwdPkgDB(t *testing.T, path string) *bbolt.DB { +func makeFwdPkgDB(t *testing.T, path string) kvdb.Backend { if path == "" { var err error path, err = ioutil.TempDir("", "fwdpkgdb") @@ -806,10 +806,10 @@ func makeFwdPkgDB(t *testing.T, path string) *bbolt.DB { path = filepath.Join(path, "fwdpkg.db") } - db, err := bbolt.Open(path, 0600, nil) + bdb, err := kvdb.Create(kvdb.BoltBackendName, path, true) if err != nil { t.Fatalf("unable to open boltdb: %v", err) } - return db + return bdb } diff --git a/channeldb/graph.go b/channeldb/graph.go index 61ca7a5fe6..efa3dcbb0e 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -18,7 +18,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -206,10 +206,10 @@ func (c *ChannelGraph) Database() *DB { func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error { // TODO(roasbeef): ptr map to reduce # of allocs? no duplicates - return c.db.View(func(tx *bbolt.Tx) error { + return kvdb.View(c.db, func(tx kvdb.ReadTx) error { // First, grab the node bucket. This will be used to populate // the Node pointers in each edge read from disk. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -217,11 +217,11 @@ func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdgeInfo, *ChannelEdgePoli // Next, grab the edge bucket which stores the edges, and also // the index itself so we can group the directed edges together // logically. - edges := tx.Bucket(edgeBucket) + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } @@ -265,8 +265,8 @@ func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdgeInfo, *ChannelEdgePoli // should be passed as the first argument. Otherwise the first argument should // be nil and a fresh transaction will be created to execute the graph // traversal. -func (c *ChannelGraph) ForEachNodeChannel(tx *bbolt.Tx, nodePub []byte, - cb func(*bbolt.Tx, *ChannelEdgeInfo, *ChannelEdgePolicy, +func (c *ChannelGraph) ForEachNodeChannel(tx kvdb.ReadTx, nodePub []byte, + cb func(kvdb.ReadTx, *ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error { db := c.db @@ -281,13 +281,15 @@ func (c *ChannelGraph) DisabledChannelIDs() ([]uint64, error) { var disabledChanIDs []uint64 chanEdgeFound := make(map[uint64]struct{}) - err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - disabledEdgePolicyIndex := edges.Bucket(disabledEdgePolicyBucket) + disabledEdgePolicyIndex := edges.NestedReadBucket( + disabledEdgePolicyBucket, + ) if disabledEdgePolicyIndex == nil { return nil } @@ -326,11 +328,11 @@ func (c *ChannelGraph) DisabledChannelIDs() ([]uint64, error) { // // TODO(roasbeef): add iterator interface to allow for memory efficient graph // traversal when graph gets mega -func (c *ChannelGraph) ForEachNode(tx *bbolt.Tx, cb func(*bbolt.Tx, *LightningNode) error) error { - traversal := func(tx *bbolt.Tx) error { +func (c *ChannelGraph) ForEachNode(tx kvdb.RwTx, cb func(kvdb.ReadTx, *LightningNode) error) error { + traversal := func(tx kvdb.ReadTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -359,7 +361,7 @@ func (c *ChannelGraph) ForEachNode(tx *bbolt.Tx, cb func(*bbolt.Tx, *LightningNo // If no transaction was provided, then we'll create a new transaction // to execute the transaction within. if tx == nil { - return c.db.View(traversal) + return kvdb.View(c.db, traversal) } // Otherwise, we re-use the existing transaction to execute the graph @@ -373,10 +375,10 @@ func (c *ChannelGraph) ForEachNode(tx *bbolt.Tx, cb func(*bbolt.Tx, *LightningNo // node based off the source node. func (c *ChannelGraph) SourceNode() (*LightningNode, error) { var source *LightningNode - err := c.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -400,7 +402,7 @@ func (c *ChannelGraph) SourceNode() (*LightningNode, error) { // of the graph. The source node is treated as the center node within a // star-graph. This method may be used to kick off a path finding algorithm in // order to explore the reachability of another node based off the source node. -func (c *ChannelGraph) sourceNode(nodes *bbolt.Bucket) (*LightningNode, error) { +func (c *ChannelGraph) sourceNode(nodes kvdb.ReadBucket) (*LightningNode, error) { selfPub := nodes.Get(sourceKey) if selfPub == nil { return nil, ErrSourceNodeNotSet @@ -423,10 +425,10 @@ func (c *ChannelGraph) sourceNode(nodes *bbolt.Bucket) (*LightningNode, error) { func (c *ChannelGraph) SetSourceNode(node *LightningNode) error { nodePubBytes := node.PubKeyBytes[:] - return c.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return err } @@ -452,13 +454,13 @@ func (c *ChannelGraph) SetSourceNode(node *LightningNode) error { // // TODO(roasbeef): also need sig of announcement func (c *ChannelGraph) AddLightningNode(node *LightningNode) error { - return c.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { return addLightningNode(tx, node) }) } -func addLightningNode(tx *bbolt.Tx, node *LightningNode) error { - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) +func addLightningNode(tx kvdb.RwTx, node *LightningNode) error { + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return err } @@ -483,13 +485,13 @@ func addLightningNode(tx *bbolt.Tx, node *LightningNode) error { func (c *ChannelGraph) LookupAlias(pub *btcec.PublicKey) (string, error) { var alias string - err := c.db.View(func(tx *bbolt.Tx) error { - nodes := tx.Bucket(nodeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNodesNotFound } - aliases := nodes.Bucket(aliasIndexBucket) + aliases := nodes.NestedReadBucket(aliasIndexBucket) if aliases == nil { return ErrGraphNodesNotFound } @@ -516,8 +518,8 @@ func (c *ChannelGraph) LookupAlias(pub *btcec.PublicKey) (string, error) { // from the database according to the node's public key. func (c *ChannelGraph) DeleteLightningNode(nodePub route.Vertex) error { // TODO(roasbeef): ensure dangling edges are removed... - return c.db.Update(func(tx *bbolt.Tx) error { - nodes := tx.Bucket(nodeBucket) + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { + nodes := tx.ReadWriteBucket(nodeBucket) if nodes == nil { return ErrGraphNodeNotFound } @@ -528,10 +530,10 @@ func (c *ChannelGraph) DeleteLightningNode(nodePub route.Vertex) error { // deleteLightningNode uses an existing database transaction to remove a // vertex/node from the database according to the node's public key. -func (c *ChannelGraph) deleteLightningNode(nodes *bbolt.Bucket, +func (c *ChannelGraph) deleteLightningNode(nodes kvdb.RwBucket, compressedPubKey []byte) error { - aliases := nodes.Bucket(aliasIndexBucket) + aliases := nodes.NestedReadWriteBucket(aliasIndexBucket) if aliases == nil { return ErrGraphNodesNotFound } @@ -556,7 +558,7 @@ func (c *ChannelGraph) deleteLightningNode(nodes *bbolt.Bucket, // Finally, we'll delete the index entry for the node within the // nodeUpdateIndexBucket as this node is no longer active, so we don't // need to track its last update. - nodeUpdateIndex := nodes.Bucket(nodeUpdateIndexBucket) + nodeUpdateIndex := nodes.NestedReadWriteBucket(nodeUpdateIndexBucket) if nodeUpdateIndex == nil { return ErrGraphNodesNotFound } @@ -581,7 +583,7 @@ func (c *ChannelGraph) AddChannelEdge(edge *ChannelEdgeInfo) error { c.cacheMu.Lock() defer c.cacheMu.Unlock() - err := c.db.Update(func(tx *bbolt.Tx) error { + err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { return c.addChannelEdge(tx, edge) }) if err != nil { @@ -596,16 +598,16 @@ func (c *ChannelGraph) AddChannelEdge(edge *ChannelEdgeInfo) error { // addChannelEdge is the private form of AddChannelEdge that allows callers to // utilize an existing db transaction. -func (c *ChannelGraph) addChannelEdge(tx *bbolt.Tx, edge *ChannelEdgeInfo) error { +func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx, edge *ChannelEdgeInfo) error { // Construct the channel's primary key which is the 8-byte channel ID. var chanKey [8]byte binary.BigEndian.PutUint64(chanKey[:], edge.ChannelID) - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return err } - edges, err := tx.CreateBucketIfNotExists(edgeBucket) + edges, err := tx.CreateTopLevelBucket(edgeBucket) if err != nil { return err } @@ -731,12 +733,12 @@ func (c *ChannelGraph) HasChannelEdge( return upd1Time, upd2Time, exists, isZombie, nil } - if err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + if err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } @@ -748,7 +750,7 @@ func (c *ChannelGraph) HasChannelEdge( // index. if edgeIndex.Get(channelID[:]) == nil { exists = false - zombieIndex := edges.Bucket(zombieBucket) + zombieIndex := edges.NestedReadBucket(zombieBucket) if zombieIndex != nil { isZombie, _, _ = isZombieEdge( zombieIndex, chanID, @@ -764,7 +766,7 @@ func (c *ChannelGraph) HasChannelEdge( // If the channel has been found in the graph, then retrieve // the edges itself so we can return the last updated // timestamps. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNodeNotFound } @@ -808,13 +810,13 @@ func (c *ChannelGraph) UpdateChannelEdge(edge *ChannelEdgeInfo) error { var chanKey [8]byte binary.BigEndian.PutUint64(chanKey[:], edge.ChannelID) - return c.db.Update(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { + edges := tx.ReadWriteBucket(edgeBucket) if edge == nil { return ErrEdgeNotFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadWriteBucket(edgeIndexBucket) if edgeIndex == nil { return ErrEdgeNotFound } @@ -851,10 +853,10 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint, var chansClosed []*ChannelEdgeInfo - err := c.db.Update(func(tx *bbolt.Tx) error { + err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { // First grab the edges bucket which houses the information // we'd like to delete - edges, err := tx.CreateBucketIfNotExists(edgeBucket) + edges, err := tx.CreateTopLevelBucket(edgeBucket) if err != nil { return err } @@ -868,7 +870,7 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint, if err != nil { return err } - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadWriteBucket(nodeBucket) if nodes == nil { return ErrSourceNodeNotSet } @@ -919,7 +921,7 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint, chansClosed = append(chansClosed, &edgeInfo) } - metaBucket, err := tx.CreateBucketIfNotExists(graphMetaBucket) + metaBucket, err := tx.CreateTopLevelBucket(graphMetaBucket) if err != nil { return err } @@ -965,16 +967,16 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint, // that we only maintain a graph of reachable nodes. In the event that a pruned // node gains more channels, it will be re-added back to the graph. func (c *ChannelGraph) PruneGraphNodes() error { - return c.db.Update(func(tx *bbolt.Tx) error { - nodes := tx.Bucket(nodeBucket) + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { + nodes := tx.ReadWriteBucket(nodeBucket) if nodes == nil { return ErrGraphNodesNotFound } - edges := tx.Bucket(edgeBucket) + edges := tx.ReadWriteBucket(edgeBucket) if edges == nil { return ErrGraphNotFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadWriteBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } @@ -986,8 +988,8 @@ func (c *ChannelGraph) PruneGraphNodes() error { // pruneGraphNodes attempts to remove any nodes from the graph who have had a // channel closed within the current block. If the node still has existing // channels in the graph, this will act as a no-op. -func (c *ChannelGraph) pruneGraphNodes(nodes *bbolt.Bucket, - edgeIndex *bbolt.Bucket) error { +func (c *ChannelGraph) pruneGraphNodes(nodes kvdb.RwBucket, + edgeIndex kvdb.RwBucket) error { log.Trace("Pruning nodes from graph with no open channels") @@ -1113,8 +1115,8 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf // Keep track of the channels that are removed from the graph. var removedChans []*ChannelEdgeInfo - if err := c.db.Update(func(tx *bbolt.Tx) error { - edges, err := tx.CreateBucketIfNotExists(edgeBucket) + if err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { + edges, err := tx.CreateTopLevelBucket(edgeBucket) if err != nil { return err } @@ -1130,7 +1132,7 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf if err != nil { return err } - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return err } @@ -1140,7 +1142,7 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf // NOTE: we must delete the edges after the cursor loop, since // modifying the bucket while traversing is not safe. var keys [][]byte - cursor := edgeIndex.Cursor() + cursor := edgeIndex.ReadWriteCursor() for k, v := cursor.Seek(chanIDStart[:]); k != nil && bytes.Compare(k, chanIDEnd[:]) <= 0; k, v = cursor.Next() { @@ -1166,7 +1168,7 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf // Delete all the entries in the prune log having a height // greater or equal to the block disconnected. - metaBucket, err := tx.CreateBucketIfNotExists(graphMetaBucket) + metaBucket, err := tx.CreateTopLevelBucket(graphMetaBucket) if err != nil { return err } @@ -1185,7 +1187,7 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf // To avoid modifying the bucket while traversing, we delete // the keys in a second loop. var pruneKeys [][]byte - pruneCursor := pruneBucket.Cursor() + pruneCursor := pruneBucket.ReadWriteCursor() for k, _ := pruneCursor.Seek(pruneKeyStart[:]); k != nil && bytes.Compare(k, pruneKeyEnd[:]) <= 0; k, _ = pruneCursor.Next() { @@ -1221,17 +1223,17 @@ func (c *ChannelGraph) PruneTip() (*chainhash.Hash, uint32, error) { tipHeight uint32 ) - err := c.db.View(func(tx *bbolt.Tx) error { - graphMeta := tx.Bucket(graphMetaBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + graphMeta := tx.ReadBucket(graphMetaBucket) if graphMeta == nil { return ErrGraphNotFound } - pruneBucket := graphMeta.Bucket(pruneLogBucket) + pruneBucket := graphMeta.NestedReadBucket(pruneLogBucket) if pruneBucket == nil { return ErrGraphNeverPruned } - pruneCursor := pruneBucket.Cursor() + pruneCursor := pruneBucket.ReadCursor() // The prune key with the largest block height will be our // prune tip. @@ -1266,20 +1268,20 @@ func (c *ChannelGraph) DeleteChannelEdges(chanIDs ...uint64) error { c.cacheMu.Lock() defer c.cacheMu.Unlock() - err := c.db.Update(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { + edges := tx.ReadWriteBucket(edgeBucket) if edges == nil { return ErrEdgeNotFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadWriteBucket(edgeIndexBucket) if edgeIndex == nil { return ErrEdgeNotFound } - chanIndex := edges.Bucket(channelPointBucket) + chanIndex := edges.NestedReadWriteBucket(channelPointBucket) if chanIndex == nil { return ErrEdgeNotFound } - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadWriteBucket(nodeBucket) if nodes == nil { return ErrGraphNodeNotFound } @@ -1319,7 +1321,7 @@ func (c *ChannelGraph) DeleteChannelEdges(chanIDs ...uint64) error { // the database, then ErrEdgeNotFound is returned. func (c *ChannelGraph) ChannelID(chanPoint *wire.OutPoint) (uint64, error) { var chanID uint64 - if err := c.db.View(func(tx *bbolt.Tx) error { + if err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { var err error chanID, err = getChanID(tx, chanPoint) return err @@ -1331,17 +1333,17 @@ func (c *ChannelGraph) ChannelID(chanPoint *wire.OutPoint) (uint64, error) { } // getChanID returns the assigned channel ID for a given channel point. -func getChanID(tx *bbolt.Tx, chanPoint *wire.OutPoint) (uint64, error) { +func getChanID(tx kvdb.ReadTx, chanPoint *wire.OutPoint) (uint64, error) { var b bytes.Buffer if err := writeOutpoint(&b, chanPoint); err != nil { return 0, err } - edges := tx.Bucket(edgeBucket) + edges := tx.ReadBucket(edgeBucket) if edges == nil { return 0, ErrGraphNoEdgesFound } - chanIndex := edges.Bucket(channelPointBucket) + chanIndex := edges.NestedReadBucket(channelPointBucket) if chanIndex == nil { return 0, ErrGraphNoEdgesFound } @@ -1364,19 +1366,19 @@ func getChanID(tx *bbolt.Tx, chanPoint *wire.OutPoint) (uint64, error) { func (c *ChannelGraph) HighestChanID() (uint64, error) { var cid uint64 - err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } // In order to find the highest chan ID, we'll fetch a cursor // and use that to seek to the "end" of our known rage. - cidCursor := edgeIndex.Cursor() + cidCursor := edgeIndex.ReadCursor() lastChanID, _ := cidCursor.Last() @@ -1428,28 +1430,28 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime, endTime time.Time) ([]Cha defer c.cacheMu.Unlock() var hits int - err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } - edgeUpdateIndex := edges.Bucket(edgeUpdateIndexBucket) + edgeUpdateIndex := edges.NestedReadBucket(edgeUpdateIndexBucket) if edgeUpdateIndex == nil { return ErrGraphNoEdgesFound } - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNodesNotFound } // We'll now obtain a cursor to perform a range query within // the index to find all channels within the horizon. - updateCursor := edgeUpdateIndex.Cursor() + updateCursor := edgeUpdateIndex.ReadCursor() var startTimeBytes, endTimeBytes [8 + 8]byte byteOrder.PutUint64( @@ -1548,20 +1550,20 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime, endTime time.Time) ([]Cha func (c *ChannelGraph) NodeUpdatesInHorizon(startTime, endTime time.Time) ([]LightningNode, error) { var nodesInHorizon []LightningNode - err := c.db.View(func(tx *bbolt.Tx) error { - nodes := tx.Bucket(nodeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNodesNotFound } - nodeUpdateIndex := nodes.Bucket(nodeUpdateIndexBucket) + nodeUpdateIndex := nodes.NestedReadBucket(nodeUpdateIndexBucket) if nodeUpdateIndex == nil { return ErrGraphNodesNotFound } // We'll now obtain a cursor to perform a range query within // the index to find all node announcements within the horizon. - updateCursor := nodeUpdateIndex.Cursor() + updateCursor := nodeUpdateIndex.ReadCursor() var startTimeBytes, endTimeBytes [8 + 33]byte byteOrder.PutUint64( @@ -1610,12 +1612,12 @@ func (c *ChannelGraph) NodeUpdatesInHorizon(startTime, endTime time.Time) ([]Lig func (c *ChannelGraph) FilterKnownChanIDs(chanIDs []uint64) ([]uint64, error) { var newChanIDs []uint64 - err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } @@ -1623,7 +1625,7 @@ func (c *ChannelGraph) FilterKnownChanIDs(chanIDs []uint64) ([]uint64, error) { // Fetch the zombie index, it may not exist if no edges have // ever been marked as zombies. If the index has been // initialized, we will use it later to skip known zombie edges. - zombieIndex := edges.Bucket(zombieBucket) + zombieIndex := edges.NestedReadBucket(zombieBucket) // We'll run through the set of chanIDs and collate only the // set of channel that are unable to be found within our db. @@ -1686,17 +1688,17 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, endHeight uint32) ([]uint byteOrder.PutUint64(chanIDStart[:], startChanID.ToUint64()) byteOrder.PutUint64(chanIDEnd[:], endChanID.ToUint64()) - err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } - cursor := edgeIndex.Cursor() + cursor := edgeIndex.ReadCursor() // We'll now iterate through the database, and find each // channel ID that resides within the specified range. @@ -1739,16 +1741,16 @@ func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) { cidBytes [8]byte ) - err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -1794,12 +1796,12 @@ func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) { return chanEdges, nil } -func delEdgeUpdateIndexEntry(edgesBucket *bbolt.Bucket, chanID uint64, +func delEdgeUpdateIndexEntry(edgesBucket kvdb.RwBucket, chanID uint64, edge1, edge2 *ChannelEdgePolicy) error { // First, we'll fetch the edge update index bucket which currently // stores an entry for the channel we're about to delete. - updateIndex := edgesBucket.Bucket(edgeUpdateIndexBucket) + updateIndex := edgesBucket.NestedReadWriteBucket(edgeUpdateIndexBucket) if updateIndex == nil { // No edges in bucket, return early. return nil @@ -1833,7 +1835,7 @@ func delEdgeUpdateIndexEntry(edgesBucket *bbolt.Bucket, chanID uint64, } func delChannelEdge(edges, edgeIndex, chanIndex, zombieIndex, - nodes *bbolt.Bucket, chanID []byte, isZombie bool) error { + nodes kvdb.RwBucket, chanID []byte, isZombie bool) error { edgeInfo, err := fetchChanEdgeInfo(edgeIndex, chanID) if err != nil { @@ -1919,7 +1921,7 @@ func (c *ChannelGraph) UpdateEdgePolicy(edge *ChannelEdgePolicy) error { defer c.cacheMu.Unlock() var isUpdate1 bool - err := c.db.Update(func(tx *bbolt.Tx) error { + err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { var err error isUpdate1, err = updateEdgePolicy(tx, edge) return err @@ -1961,17 +1963,17 @@ func (c *ChannelGraph) UpdateEdgePolicy(edge *ChannelEdgePolicy) error { // buckets using an existing database transaction. The returned boolean will be // true if the updated policy belongs to node1, and false if the policy belonged // to node2. -func updateEdgePolicy(tx *bbolt.Tx, edge *ChannelEdgePolicy) (bool, error) { - edges := tx.Bucket(edgeBucket) +func updateEdgePolicy(tx kvdb.RwTx, edge *ChannelEdgePolicy) (bool, error) { + edges := tx.ReadWriteBucket(edgeBucket) if edges == nil { return false, ErrEdgeNotFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadWriteBucket(edgeIndexBucket) if edgeIndex == nil { return false, ErrEdgeNotFound } - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return false, err } @@ -2138,14 +2140,14 @@ func (l *LightningNode) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement, // isPublic determines whether the node is seen as public within the graph from // the source node's point of view. An existing database transaction can also be // specified. -func (l *LightningNode) isPublic(tx *bbolt.Tx, sourcePubKey []byte) (bool, error) { +func (l *LightningNode) isPublic(tx kvdb.ReadTx, sourcePubKey []byte) (bool, error) { // In order to determine whether this node is publicly advertised within // the graph, we'll need to look at all of its edges and check whether // they extend to any other node than the source node. errDone will be // used to terminate the check early. nodeIsPublic := false errDone := errors.New("done") - err := l.ForEachChannel(tx, func(_ *bbolt.Tx, info *ChannelEdgeInfo, + err := l.ForEachChannel(tx, func(_ kvdb.ReadTx, info *ChannelEdgeInfo, _, _ *ChannelEdgePolicy) error { // If this edge doesn't extend to the source node, we'll @@ -2184,15 +2186,15 @@ func (l *LightningNode) isPublic(tx *bbolt.Tx, sourcePubKey []byte) (bool, error // should be passed as the first argument. Otherwise the first argument should // be nil and a fresh transaction will be created to execute the graph // traversal. -func (c *ChannelGraph) FetchLightningNode(tx *bbolt.Tx, nodePub route.Vertex) ( +func (c *ChannelGraph) FetchLightningNode(tx kvdb.ReadTx, nodePub route.Vertex) ( *LightningNode, error) { var node *LightningNode - fetchNode := func(tx *bbolt.Tx) error { + fetchNode := func(tx kvdb.ReadTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -2220,7 +2222,7 @@ func (c *ChannelGraph) FetchLightningNode(tx *bbolt.Tx, nodePub route.Vertex) ( var err error if tx == nil { - err = c.db.View(fetchNode) + err = kvdb.View(c.db, fetchNode) } else { err = fetchNode(tx) } @@ -2242,10 +2244,10 @@ func (c *ChannelGraph) HasLightningNode(nodePub [33]byte) (time.Time, bool, erro exists bool ) - err := c.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -2280,19 +2282,19 @@ func (c *ChannelGraph) HasLightningNode(nodePub [33]byte) (time.Time, bool, erro // nodeTraversal is used to traverse all channels of a node given by its // public key and passes channel information into the specified callback. -func nodeTraversal(tx *bbolt.Tx, nodePub []byte, db *DB, - cb func(*bbolt.Tx, *ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error { +func nodeTraversal(tx kvdb.ReadTx, nodePub []byte, db *DB, + cb func(kvdb.ReadTx, *ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error { - traversal := func(tx *bbolt.Tx) error { - nodes := tx.Bucket(nodeBucket) + traversal := func(tx kvdb.ReadTx) error { + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } - edges := tx.Bucket(edgeBucket) + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNotFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } @@ -2312,7 +2314,7 @@ func nodeTraversal(tx *bbolt.Tx, nodePub []byte, db *DB, // bucket until the retrieved key no longer has the public key // as its prefix. This indicates that we've stepped over into // another node's edges, so we can terminate our scan. - edgeCursor := edges.Cursor() + edgeCursor := edges.ReadCursor() for nodeEdge, _ := edgeCursor.Seek(nodeStart[:]); bytes.HasPrefix(nodeEdge, nodePub); nodeEdge, _ = edgeCursor.Next() { // If the prefix still matches, the channel id is // returned in nodeEdge. Channel id is used to lookup @@ -2357,7 +2359,7 @@ func nodeTraversal(tx *bbolt.Tx, nodePub []byte, db *DB, // If no transaction was provided, then we'll create a new transaction // to execute the transaction within. if tx == nil { - return db.View(traversal) + return kvdb.View(db, traversal) } // Otherwise, we re-use the existing transaction to execute the graph @@ -2378,8 +2380,8 @@ func nodeTraversal(tx *bbolt.Tx, nodePub []byte, db *DB, // should be passed as the first argument. Otherwise the first argument should // be nil and a fresh transaction will be created to execute the graph // traversal. -func (l *LightningNode) ForEachChannel(tx *bbolt.Tx, - cb func(*bbolt.Tx, *ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error { +func (l *LightningNode) ForEachChannel(tx kvdb.ReadTx, + cb func(kvdb.ReadTx, *ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error { nodePub := l.PubKeyBytes[:] db := l.db @@ -2570,7 +2572,7 @@ func (c *ChannelEdgeInfo) OtherNodeKeyBytes(thisNodeKey []byte) ( // the target node in the channel. This is useful when one knows the pubkey of // one of the nodes, and wishes to obtain the full LightningNode for the other // end of the channel. -func (c *ChannelEdgeInfo) FetchOtherNode(tx *bbolt.Tx, thisNodeKey []byte) (*LightningNode, error) { +func (c *ChannelEdgeInfo) FetchOtherNode(tx kvdb.ReadTx, thisNodeKey []byte) (*LightningNode, error) { // Ensure that the node passed in is actually a member of the channel. var targetNodeBytes [33]byte @@ -2584,10 +2586,10 @@ func (c *ChannelEdgeInfo) FetchOtherNode(tx *bbolt.Tx, thisNodeKey []byte) (*Lig } var targetNode *LightningNode - fetchNodeFunc := func(tx *bbolt.Tx) error { + fetchNodeFunc := func(tx kvdb.ReadTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -2607,7 +2609,7 @@ func (c *ChannelEdgeInfo) FetchOtherNode(tx *bbolt.Tx, thisNodeKey []byte) (*Lig // otherwise we can use the existing db transaction. var err error if tx == nil { - err = c.db.View(fetchNodeFunc) + err = kvdb.View(c.db, fetchNodeFunc) } else { err = fetchNodeFunc(tx) } @@ -2883,10 +2885,10 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint, policy2 *ChannelEdgePolicy ) - err := c.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { // First, grab the node bucket. This will be used to populate // the Node pointers in each edge read from disk. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -2894,18 +2896,18 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint, // Next, grab the edge bucket which stores the edges, and also // the index itself so we can group the directed edges together // logically. - edges := tx.Bucket(edgeBucket) + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } // If the channel's outpoint doesn't exist within the outpoint // index, then the edge does not exist. - chanIndex := edges.Bucket(channelPointBucket) + chanIndex := edges.NestedReadBucket(channelPointBucket) if chanIndex == nil { return ErrGraphNoEdgesFound } @@ -2967,10 +2969,10 @@ func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64, channelID [8]byte ) - err := c.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { // First, grab the node bucket. This will be used to populate // the Node pointers in each edge read from disk. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -2978,11 +2980,11 @@ func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64, // Next, grab the edge bucket which stores the edges, and also // the index itself so we can group the directed edges together // logically. - edges := tx.Bucket(edgeBucket) + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } @@ -2998,7 +3000,7 @@ func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64, // If the zombie index doesn't exist, or the edge is not // marked as a zombie within it, then we'll return the // original ErrEdgeNotFound error. - zombieIndex := edges.Bucket(zombieBucket) + zombieIndex := edges.NestedReadBucket(zombieBucket) if zombieIndex == nil { return ErrEdgeNotFound } @@ -3057,8 +3059,8 @@ func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64, // source node's point of view. func (c *ChannelGraph) IsPublicNode(pubKey [33]byte) (bool, error) { var nodeIsPublic bool - err := c.db.View(func(tx *bbolt.Tx) error { - nodes := tx.Bucket(nodeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNodesNotFound } @@ -3143,19 +3145,19 @@ func (e *EdgePoint) String() string { // closes on the resident blockchain. func (c *ChannelGraph) ChannelView() ([]EdgePoint, error) { var edgePoints []EdgePoint - if err := c.db.View(func(tx *bbolt.Tx) error { + if err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { // We're going to iterate over the entire channel index, so // we'll need to fetch the edgeBucket to get to the index as // it's a sub-bucket. - edges := tx.Bucket(edgeBucket) + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - chanIndex := edges.Bucket(channelPointBucket) + chanIndex := edges.NestedReadBucket(channelPointBucket) if chanIndex == nil { return ErrGraphNoEdgesFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadBucket(edgeIndexBucket) if edgeIndex == nil { return ErrGraphNoEdgesFound } @@ -3209,7 +3211,7 @@ func (c *ChannelGraph) NewChannelEdgePolicy() *ChannelEdgePolicy { // markEdgeZombie marks an edge as a zombie within our zombie index. The public // keys should represent the node public keys of the two parties involved in the // edge. -func markEdgeZombie(zombieIndex *bbolt.Bucket, chanID uint64, pubKey1, +func markEdgeZombie(zombieIndex kvdb.RwBucket, chanID uint64, pubKey1, pubKey2 [33]byte) error { var k [8]byte @@ -3227,12 +3229,12 @@ func (c *ChannelGraph) MarkEdgeLive(chanID uint64) error { c.cacheMu.Lock() defer c.cacheMu.Unlock() - err := c.db.Update(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { + edges := tx.ReadWriteBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - zombieIndex := edges.Bucket(zombieBucket) + zombieIndex := edges.NestedReadWriteBucket(zombieBucket) if zombieIndex == nil { return nil } @@ -3260,12 +3262,12 @@ func (c *ChannelGraph) IsZombieEdge(chanID uint64) (bool, [33]byte, [33]byte) { pubKey1, pubKey2 [33]byte ) - err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - zombieIndex := edges.Bucket(zombieBucket) + zombieIndex := edges.NestedReadBucket(zombieBucket) if zombieIndex == nil { return nil } @@ -3283,7 +3285,7 @@ func (c *ChannelGraph) IsZombieEdge(chanID uint64) (bool, [33]byte, [33]byte) { // isZombieEdge returns whether an entry exists for the given channel in the // zombie index. If an entry exists, then the two node public keys corresponding // to this edge are also returned. -func isZombieEdge(zombieIndex *bbolt.Bucket, +func isZombieEdge(zombieIndex kvdb.ReadBucket, chanID uint64) (bool, [33]byte, [33]byte) { var k [8]byte @@ -3304,12 +3306,12 @@ func isZombieEdge(zombieIndex *bbolt.Bucket, // NumZombies returns the current number of zombie channels in the graph. func (c *ChannelGraph) NumZombies() (uint64, error) { var numZombies uint64 - err := c.db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return nil } - zombieIndex := edges.Bucket(zombieBucket) + zombieIndex := edges.NestedReadBucket(zombieBucket) if zombieIndex == nil { return nil } @@ -3326,8 +3328,8 @@ func (c *ChannelGraph) NumZombies() (uint64, error) { return numZombies, nil } -func putLightningNode(nodeBucket *bbolt.Bucket, aliasBucket *bbolt.Bucket, - updateIndex *bbolt.Bucket, node *LightningNode) error { +func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, + updateIndex kvdb.RwBucket, node *LightningNode) error { var ( scratch [16]byte @@ -3455,7 +3457,7 @@ func putLightningNode(nodeBucket *bbolt.Bucket, aliasBucket *bbolt.Bucket, return nodeBucket.Put(nodePub, b.Bytes()) } -func fetchLightningNode(nodeBucket *bbolt.Bucket, +func fetchLightningNode(nodeBucket kvdb.ReadBucket, nodePub []byte) (LightningNode, error) { nodeBytes := nodeBucket.Get(nodePub) @@ -3563,7 +3565,7 @@ func deserializeLightningNode(r io.Reader) (LightningNode, error) { return node, nil } -func putChanEdgeInfo(edgeIndex *bbolt.Bucket, edgeInfo *ChannelEdgeInfo, chanID [8]byte) error { +func putChanEdgeInfo(edgeIndex kvdb.RwBucket, edgeInfo *ChannelEdgeInfo, chanID [8]byte) error { var b bytes.Buffer if _, err := b.Write(edgeInfo.NodeKey1Bytes[:]); err != nil { @@ -3629,7 +3631,7 @@ func putChanEdgeInfo(edgeIndex *bbolt.Bucket, edgeInfo *ChannelEdgeInfo, chanID return edgeIndex.Put(chanID[:], b.Bytes()) } -func fetchChanEdgeInfo(edgeIndex *bbolt.Bucket, +func fetchChanEdgeInfo(edgeIndex kvdb.ReadBucket, chanID []byte) (ChannelEdgeInfo, error) { edgeInfoBytes := edgeIndex.Get(chanID) @@ -3718,7 +3720,7 @@ func deserializeChanEdgeInfo(r io.Reader) (ChannelEdgeInfo, error) { return edgeInfo, nil } -func putChanEdgePolicy(edges, nodes *bbolt.Bucket, edge *ChannelEdgePolicy, +func putChanEdgePolicy(edges, nodes kvdb.RwBucket, edge *ChannelEdgePolicy, from, to []byte) error { var edgeKey [33 + 8]byte @@ -3798,7 +3800,7 @@ func putChanEdgePolicy(edges, nodes *bbolt.Bucket, edge *ChannelEdgePolicy, // in this bucket. // Maintaining the bucket this way allows a fast retrieval of disabled // channels, for example when prune is needed. -func updateEdgePolicyDisabledIndex(edges *bbolt.Bucket, chanID uint64, +func updateEdgePolicyDisabledIndex(edges kvdb.RwBucket, chanID uint64, direction bool, disabled bool) error { var disabledEdgeKey [8 + 1]byte @@ -3823,7 +3825,7 @@ func updateEdgePolicyDisabledIndex(edges *bbolt.Bucket, chanID uint64, // putChanEdgePolicyUnknown marks the edge policy as unknown // in the edges bucket. -func putChanEdgePolicyUnknown(edges *bbolt.Bucket, channelID uint64, +func putChanEdgePolicyUnknown(edges kvdb.RwBucket, channelID uint64, from []byte) error { var edgeKey [33 + 8]byte @@ -3838,8 +3840,8 @@ func putChanEdgePolicyUnknown(edges *bbolt.Bucket, channelID uint64, return edges.Put(edgeKey[:], unknownPolicy) } -func fetchChanEdgePolicy(edges *bbolt.Bucket, chanID []byte, - nodePub []byte, nodes *bbolt.Bucket) (*ChannelEdgePolicy, error) { +func fetchChanEdgePolicy(edges kvdb.ReadBucket, chanID []byte, + nodePub []byte, nodes kvdb.ReadBucket) (*ChannelEdgePolicy, error) { var edgeKey [33 + 8]byte copy(edgeKey[:], nodePub) @@ -3871,8 +3873,8 @@ func fetchChanEdgePolicy(edges *bbolt.Bucket, chanID []byte, return ep, nil } -func fetchChanEdgePolicies(edgeIndex *bbolt.Bucket, edges *bbolt.Bucket, - nodes *bbolt.Bucket, chanID []byte, +func fetchChanEdgePolicies(edgeIndex kvdb.ReadBucket, edges kvdb.ReadBucket, + nodes kvdb.ReadBucket, chanID []byte, db *DB) (*ChannelEdgePolicy, *ChannelEdgePolicy, error) { edgeInfo := edgeIndex.Get(chanID) @@ -3980,7 +3982,7 @@ func serializeChanEdgePolicy(w io.Writer, edge *ChannelEdgePolicy, } func deserializeChanEdgePolicy(r io.Reader, - nodes *bbolt.Bucket) (*ChannelEdgePolicy, error) { + nodes kvdb.ReadBucket) (*ChannelEdgePolicy, error) { edge := &ChannelEdgePolicy{} diff --git a/channeldb/graph_test.go b/channeldb/graph_test.go index d79f15dd15..b1355bafc0 100644 --- a/channeldb/graph_test.go +++ b/channeldb/graph_test.go @@ -17,8 +17,8 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -882,7 +882,7 @@ func TestGraphTraversal(t *testing.T) { // Iterate over each node as returned by the graph, if all nodes are // reached, then the map created above should be empty. - err = graph.ForEachNode(nil, func(_ *bbolt.Tx, node *LightningNode) error { + err = graph.ForEachNode(nil, func(_ kvdb.ReadTx, node *LightningNode) error { delete(nodeIndex, node.Alias) return nil }) @@ -978,7 +978,7 @@ func TestGraphTraversal(t *testing.T) { // Finally, we want to test the ability to iterate over all the // outgoing channels for a particular node. numNodeChans := 0 - err = firstNode.ForEachChannel(nil, func(_ *bbolt.Tx, _ *ChannelEdgeInfo, + err = firstNode.ForEachChannel(nil, func(_ kvdb.ReadTx, _ *ChannelEdgeInfo, outEdge, inEdge *ChannelEdgePolicy) error { // All channels between first and second node should have fully @@ -1051,7 +1051,7 @@ func assertNumChans(t *testing.T, graph *ChannelGraph, n int) { func assertNumNodes(t *testing.T, graph *ChannelGraph, n int) { numNodes := 0 - err := graph.ForEachNode(nil, func(_ *bbolt.Tx, _ *LightningNode) error { + err := graph.ForEachNode(nil, func(_ kvdb.ReadTx, _ *LightningNode) error { numNodes++ return nil }) @@ -2097,10 +2097,9 @@ func TestIncompleteChannelPolicies(t *testing.T) { } // Ensure that channel is reported with unknown policies. - checkPolicies := func(node *LightningNode, expectedIn, expectedOut bool) { calls := 0 - node.ForEachChannel(nil, func(_ *bbolt.Tx, _ *ChannelEdgeInfo, + err := node.ForEachChannel(nil, func(_ kvdb.ReadTx, _ *ChannelEdgeInfo, outEdge, inEdge *ChannelEdgePolicy) error { if !expectedOut && outEdge != nil { @@ -2123,6 +2122,9 @@ func TestIncompleteChannelPolicies(t *testing.T) { return nil }) + if err != nil { + t.Fatalf("unable to scan channels: %v", err) + } if calls != 1 { t.Fatalf("Expected only one callback call") @@ -2233,17 +2235,27 @@ func TestChannelEdgePruningUpdateIndexDeletion(t *testing.T) { timestampSet[t] = struct{}{} } - err := db.View(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err := kvdb.View(db, func(tx kvdb.ReadTx) error { + edges := tx.ReadBucket(edgeBucket) if edges == nil { return ErrGraphNoEdgesFound } - edgeUpdateIndex := edges.Bucket(edgeUpdateIndexBucket) + edgeUpdateIndex := edges.NestedReadBucket( + edgeUpdateIndexBucket, + ) if edgeUpdateIndex == nil { return ErrGraphNoEdgesFound } - numEntries := edgeUpdateIndex.Stats().KeyN + var numEntries int + err := edgeUpdateIndex.ForEach(func(k, v []byte) error { + numEntries++ + return nil + }) + if err != nil { + return err + } + expectedEntries := len(timestampSet) if numEntries != expectedEntries { return fmt.Errorf("expected %v entries in the "+ @@ -2832,8 +2844,8 @@ func TestEdgePolicyMissingMaxHtcl(t *testing.T) { // Attempting to deserialize these bytes should return an error. r := bytes.NewReader(stripped) - err = db.View(func(tx *bbolt.Tx) error { - nodes := tx.Bucket(nodeBucket) + err = kvdb.View(db, func(tx kvdb.ReadTx) error { + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -2852,13 +2864,13 @@ func TestEdgePolicyMissingMaxHtcl(t *testing.T) { } // Put the stripped bytes in the DB. - err = db.Update(func(tx *bbolt.Tx) error { - edges := tx.Bucket(edgeBucket) + err = kvdb.Update(db, func(tx kvdb.RwTx) error { + edges := tx.ReadWriteBucket(edgeBucket) if edges == nil { return ErrEdgeNotFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadWriteBucket(edgeIndexBucket) if edgeIndex == nil { return ErrEdgeNotFound } diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 66363fe127..7287910d7a 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -8,7 +8,7 @@ import ( "io" "time" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -401,8 +401,8 @@ func (d *DB) AddInvoice(newInvoice *Invoice, paymentHash lntypes.Hash) ( } var invoiceAddIndex uint64 - err := d.Update(func(tx *bbolt.Tx) error { - invoices, err := tx.CreateBucketIfNotExists(invoiceBucket) + err := kvdb.Update(d, func(tx kvdb.RwTx) error { + invoices, err := tx.CreateTopLevelBucket(invoiceBucket) if err != nil { return err } @@ -479,13 +479,13 @@ func (d *DB) InvoicesAddedSince(sinceAddIndex uint64) ([]Invoice, error) { var startIndex [8]byte byteOrder.PutUint64(startIndex[:], sinceAddIndex) - err := d.DB.View(func(tx *bbolt.Tx) error { - invoices := tx.Bucket(invoiceBucket) + err := kvdb.View(d, func(tx kvdb.ReadTx) error { + invoices := tx.ReadBucket(invoiceBucket) if invoices == nil { return ErrNoInvoicesCreated } - addIndex := invoices.Bucket(addIndexBucket) + addIndex := invoices.NestedReadBucket(addIndexBucket) if addIndex == nil { return ErrNoInvoicesCreated } @@ -493,7 +493,7 @@ func (d *DB) InvoicesAddedSince(sinceAddIndex uint64) ([]Invoice, error) { // We'll now run through each entry in the add index starting // at our starting index. We'll continue until we reach the // very end of the current key space. - invoiceCursor := addIndex.Cursor() + invoiceCursor := addIndex.ReadCursor() // We'll seek to the starting index, then manually advance the // cursor in order to skip the entry with the since add index. @@ -534,12 +534,12 @@ func (d *DB) InvoicesAddedSince(sinceAddIndex uint64) ([]Invoice, error) { // terms of the payment. func (d *DB) LookupInvoice(paymentHash [32]byte) (Invoice, error) { var invoice Invoice - err := d.View(func(tx *bbolt.Tx) error { - invoices := tx.Bucket(invoiceBucket) + err := kvdb.View(d, func(tx kvdb.ReadTx) error { + invoices := tx.ReadBucket(invoiceBucket) if invoices == nil { return ErrNoInvoicesCreated } - invoiceIndex := invoices.Bucket(invoiceIndexBucket) + invoiceIndex := invoices.NestedReadBucket(invoiceIndexBucket) if invoiceIndex == nil { return ErrNoInvoicesCreated } @@ -589,13 +589,13 @@ func (d *DB) FetchAllInvoicesWithPaymentHash(pendingOnly bool) ( var result []InvoiceWithPaymentHash - err := d.View(func(tx *bbolt.Tx) error { - invoices := tx.Bucket(invoiceBucket) + err := kvdb.View(d, func(tx kvdb.ReadTx) error { + invoices := tx.ReadBucket(invoiceBucket) if invoices == nil { return ErrNoInvoicesCreated } - invoiceIndex := invoices.Bucket(invoiceIndexBucket) + invoiceIndex := invoices.NestedReadBucket(invoiceIndexBucket) if invoiceIndex == nil { // Mask the error if there's no invoice // index as that simply means there are no @@ -695,21 +695,21 @@ func (d *DB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error) { InvoiceQuery: q, } - err := d.View(func(tx *bbolt.Tx) error { + err := kvdb.View(d, func(tx kvdb.ReadTx) error { // If the bucket wasn't found, then there aren't any invoices // within the database yet, so we can simply exit. - invoices := tx.Bucket(invoiceBucket) + invoices := tx.ReadBucket(invoiceBucket) if invoices == nil { return ErrNoInvoicesCreated } - invoiceAddIndex := invoices.Bucket(addIndexBucket) + invoiceAddIndex := invoices.NestedReadBucket(addIndexBucket) if invoiceAddIndex == nil { return ErrNoInvoicesCreated } // keyForIndex is a helper closure that retrieves the invoice // key for the given add index of an invoice. - keyForIndex := func(c *bbolt.Cursor, index uint64) []byte { + keyForIndex := func(c kvdb.ReadCursor, index uint64) []byte { var keyIndex [8]byte byteOrder.PutUint64(keyIndex[:], index) _, invoiceKey := c.Seek(keyIndex[:]) @@ -718,7 +718,7 @@ func (d *DB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error) { // nextKey is a helper closure to determine what the next // invoice key is when iterating over the invoice add index. - nextKey := func(c *bbolt.Cursor) ([]byte, []byte) { + nextKey := func(c kvdb.ReadCursor) ([]byte, []byte) { if q.Reversed { return c.Prev() } @@ -728,7 +728,7 @@ func (d *DB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error) { // We'll be using a cursor to seek into the database and return // a slice of invoices. We'll need to determine where to start // our cursor depending on the parameters set within the query. - c := invoiceAddIndex.Cursor() + c := invoiceAddIndex.ReadCursor() invoiceKey := keyForIndex(c, q.IndexOffset+1) // If the query is specifying reverse iteration, then we must @@ -822,8 +822,8 @@ func (d *DB) UpdateInvoice(paymentHash lntypes.Hash, callback InvoiceUpdateCallback) (*Invoice, error) { var updatedInvoice *Invoice - err := d.Update(func(tx *bbolt.Tx) error { - invoices, err := tx.CreateBucketIfNotExists(invoiceBucket) + err := kvdb.Update(d, func(tx kvdb.RwTx) error { + invoices, err := tx.CreateTopLevelBucket(invoiceBucket) if err != nil { return err } @@ -877,13 +877,13 @@ func (d *DB) InvoicesSettledSince(sinceSettleIndex uint64) ([]Invoice, error) { var startIndex [8]byte byteOrder.PutUint64(startIndex[:], sinceSettleIndex) - err := d.DB.View(func(tx *bbolt.Tx) error { - invoices := tx.Bucket(invoiceBucket) + err := kvdb.View(d, func(tx kvdb.ReadTx) error { + invoices := tx.ReadBucket(invoiceBucket) if invoices == nil { return ErrNoInvoicesCreated } - settleIndex := invoices.Bucket(settleIndexBucket) + settleIndex := invoices.NestedReadBucket(settleIndexBucket) if settleIndex == nil { return ErrNoInvoicesCreated } @@ -891,7 +891,7 @@ func (d *DB) InvoicesSettledSince(sinceSettleIndex uint64) ([]Invoice, error) { // We'll now run through each entry in the add index starting // at our starting index. We'll continue until we reach the // very end of the current key space. - invoiceCursor := settleIndex.Cursor() + invoiceCursor := settleIndex.ReadCursor() // We'll seek to the starting index, then manually advance the // cursor in order to skip the entry with the since add index. @@ -919,7 +919,7 @@ func (d *DB) InvoicesSettledSince(sinceSettleIndex uint64) ([]Invoice, error) { return settledInvoices, nil } -func putInvoice(invoices, invoiceIndex, addIndex *bbolt.Bucket, +func putInvoice(invoices, invoiceIndex, addIndex kvdb.RwBucket, i *Invoice, invoiceNum uint32, paymentHash lntypes.Hash) ( uint64, error) { @@ -1112,7 +1112,7 @@ func serializeHtlcs(w io.Writer, htlcs map[CircuitKey]*InvoiceHTLC) error { return nil } -func fetchInvoice(invoiceNum []byte, invoices *bbolt.Bucket) (Invoice, error) { +func fetchInvoice(invoiceNum []byte, invoices kvdb.ReadBucket) (Invoice, error) { invoiceBytes := invoices.Get(invoiceNum) if invoiceBytes == nil { return Invoice{}, ErrInvoiceNotFound @@ -1325,7 +1325,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, settleIndex *bbolt.Bucket, +func (d *DB) updateInvoice(hash lntypes.Hash, invoices, settleIndex kvdb.RwBucket, invoiceNum []byte, callback InvoiceUpdateCallback) (*Invoice, error) { invoice, err := fetchInvoice(invoiceNum, invoices) @@ -1572,7 +1572,7 @@ func updateHtlc(resolveTime time.Time, htlc *InvoiceHTLC, // setSettleMetaFields updates the metadata associated with settlement of an // invoice. -func setSettleMetaFields(settleIndex *bbolt.Bucket, invoiceNum []byte, +func setSettleMetaFields(settleIndex kvdb.RwBucket, invoiceNum []byte, invoice *Invoice, now time.Time) error { // Now that we know the invoice hasn't already been settled, we'll diff --git a/channeldb/meta.go b/channeldb/meta.go index 541559b4a5..a2dd853e38 100644 --- a/channeldb/meta.go +++ b/channeldb/meta.go @@ -1,6 +1,8 @@ package channeldb -import "github.com/coreos/bbolt" +import ( + "github.com/lightningnetwork/lnd/channeldb/kvdb" +) var ( // metaBucket stores all the meta information concerning the state of @@ -20,10 +22,10 @@ type Meta struct { // FetchMeta fetches the meta data from boltdb and returns filled meta // structure. -func (d *DB) FetchMeta(tx *bbolt.Tx) (*Meta, error) { +func (d *DB) FetchMeta(tx kvdb.ReadTx) (*Meta, error) { meta := &Meta{} - err := d.View(func(tx *bbolt.Tx) error { + err := kvdb.View(d, func(tx kvdb.ReadTx) error { return fetchMeta(meta, tx) }) if err != nil { @@ -36,8 +38,8 @@ func (d *DB) FetchMeta(tx *bbolt.Tx) (*Meta, error) { // fetchMeta is an internal helper function used in order to allow callers to // re-use a database transaction. See the publicly exported FetchMeta method // for more information. -func fetchMeta(meta *Meta, tx *bbolt.Tx) error { - metaBucket := tx.Bucket(metaBucket) +func fetchMeta(meta *Meta, tx kvdb.ReadTx) error { + metaBucket := tx.ReadBucket(metaBucket) if metaBucket == nil { return ErrMetaNotFound } @@ -54,7 +56,7 @@ func fetchMeta(meta *Meta, tx *bbolt.Tx) error { // PutMeta writes the passed instance of the database met-data struct to disk. func (d *DB) PutMeta(meta *Meta) error { - return d.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(d, func(tx kvdb.RwTx) error { return putMeta(meta, tx) }) } @@ -62,8 +64,8 @@ func (d *DB) PutMeta(meta *Meta) error { // putMeta is an internal helper function used in order to allow callers to // re-use a database transaction. See the publicly exported PutMeta method for // more information. -func putMeta(meta *Meta, tx *bbolt.Tx) error { - metaBucket, err := tx.CreateBucketIfNotExists(metaBucket) +func putMeta(meta *Meta, tx kvdb.RwTx) error { + metaBucket, err := tx.CreateTopLevelBucket(metaBucket) if err != nil { return err } @@ -71,7 +73,7 @@ func putMeta(meta *Meta, tx *bbolt.Tx) error { return putDbVersion(metaBucket, meta) } -func putDbVersion(metaBucket *bbolt.Bucket, meta *Meta) error { +func putDbVersion(metaBucket kvdb.RwBucket, meta *Meta) error { scratch := make([]byte, 4) byteOrder.PutUint32(scratch, meta.DbVersionNumber) return metaBucket.Put(dbVersionKey, scratch) diff --git a/channeldb/meta_test.go b/channeldb/meta_test.go index 014d5966cb..b72495d532 100644 --- a/channeldb/meta_test.go +++ b/channeldb/meta_test.go @@ -5,8 +5,8 @@ import ( "io/ioutil" "testing" - "github.com/coreos/bbolt" "github.com/go-errors/errors" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) // applyMigration is a helper test function that encapsulates the general steps @@ -121,11 +121,11 @@ func TestOrderOfMigrations(t *testing.T) { versions := []version{ {0, nil}, {1, nil}, - {2, func(tx *bbolt.Tx) error { + {2, func(tx kvdb.RwTx) error { appliedMigration = 2 return nil }}, - {3, func(tx *bbolt.Tx) error { + {3, func(tx kvdb.RwTx) error { appliedMigration = 3 return nil }}, @@ -197,21 +197,23 @@ func TestMigrationWithPanic(t *testing.T) { beforeMigrationFunc := func(d *DB) { // Insert data in database and in order then make sure that the // key isn't changes in case of panic or fail. - d.Update(func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + err := kvdb.Update(d, func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } - bucket.Put(keyPrefix, beforeMigration) - return nil + return bucket.Put(keyPrefix, beforeMigration) }) + if err != nil { + t.Fatalf("unable to insert: %v", err) + } } // Create migration function which changes the initially created data and // throw the panic, in this case we pretending that something goes. - migrationWithPanic := func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + migrationWithPanic := func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } @@ -231,8 +233,8 @@ func TestMigrationWithPanic(t *testing.T) { t.Fatal("migration panicked but version is changed") } - err = d.Update(func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + err = kvdb.Update(d, func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } @@ -268,22 +270,24 @@ func TestMigrationWithFatal(t *testing.T) { afterMigration := []byte("aftermigration") beforeMigrationFunc := func(d *DB) { - d.Update(func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + err := kvdb.Update(d, func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } - bucket.Put(keyPrefix, beforeMigration) - return nil + return bucket.Put(keyPrefix, beforeMigration) }) + if err != nil { + t.Fatalf("unable to insert pre migration key: %v", err) + } } // Create migration function which changes the initially created data and // return the error, in this case we pretending that something goes // wrong. - migrationWithFatal := func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + migrationWithFatal := func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } @@ -303,8 +307,8 @@ func TestMigrationWithFatal(t *testing.T) { t.Fatal("migration failed but version is changed") } - err = d.Update(func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + err = kvdb.Update(d, func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } @@ -341,8 +345,8 @@ func TestMigrationWithoutErrors(t *testing.T) { // Populate database with initial data. beforeMigrationFunc := func(d *DB) { - d.Update(func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + kvdb.Update(d, func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } @@ -353,8 +357,8 @@ func TestMigrationWithoutErrors(t *testing.T) { } // Create migration function which changes the initially created data. - migrationWithoutErrors := func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + migrationWithoutErrors := func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } @@ -375,8 +379,8 @@ func TestMigrationWithoutErrors(t *testing.T) { "successfully applied migration") } - err = d.Update(func(tx *bbolt.Tx) error { - bucket, err := tx.CreateBucketIfNotExists(bucketPrefix) + err = kvdb.Update(d, func(tx kvdb.RwTx) error { + bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } @@ -419,7 +423,7 @@ func TestMigrationReversion(t *testing.T) { // Update the database metadata to point to one more than the highest // known version. - err = cdb.Update(func(tx *bbolt.Tx) error { + err = kvdb.Update(cdb, func(tx kvdb.RwTx) error { newMeta := &Meta{ DbVersionNumber: getLatestDBVersion(dbVersions) + 1, } diff --git a/channeldb/migration12/migration.go b/channeldb/migration12/migration.go index d80497dd0d..66f988deb2 100644 --- a/channeldb/migration12/migration.go +++ b/channeldb/migration12/migration.go @@ -3,7 +3,7 @@ package migration12 import ( "bytes" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -12,11 +12,11 @@ var emptyFeatures = lnwire.NewFeatureVector(nil, nil) // MigrateInvoiceTLV migrates all existing invoice bodies over to be serialized // in a single TLV stream. In the process, we drop the Receipt field and add // PaymentAddr and Features to the invoice Terms. -func MigrateInvoiceTLV(tx *bbolt.Tx) error { +func MigrateInvoiceTLV(tx kvdb.RwTx) error { log.Infof("Migrating invoice bodies to TLV, " + "adding payment addresses and feature vectors.") - invoiceB := tx.Bucket(invoiceBucket) + invoiceB := tx.ReadWriteBucket(invoiceBucket) if invoiceB == nil { return nil } diff --git a/channeldb/migration12/migration_test.go b/channeldb/migration12/migration_test.go index f884d34257..ab420fe6da 100644 --- a/channeldb/migration12/migration_test.go +++ b/channeldb/migration12/migration_test.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/channeldb/migration12" "github.com/lightningnetwork/lnd/channeldb/migtest" "github.com/lightningnetwork/lnd/lntypes" @@ -121,15 +121,15 @@ var ( type migrationTest struct { name string - beforeMigration func(*bbolt.Tx) error - afterMigration func(*bbolt.Tx) error + beforeMigration func(kvdb.RwTx) error + afterMigration func(kvdb.RwTx) error } var migrationTests = []migrationTest{ { name: "no invoices", - beforeMigration: func(*bbolt.Tx) error { return nil }, - afterMigration: func(*bbolt.Tx) error { return nil }, + beforeMigration: func(kvdb.RwTx) error { return nil }, + afterMigration: func(kvdb.RwTx) error { return nil }, }, { name: "zero htlcs", @@ -145,9 +145,9 @@ var migrationTests = []migrationTest{ // genBeforeMigration creates a closure that inserts an invoice serialized under // the old format under the test payment hash. -func genBeforeMigration(beforeBytes []byte) func(*bbolt.Tx) error { - return func(tx *bbolt.Tx) error { - invoices, err := tx.CreateBucketIfNotExists( +func genBeforeMigration(beforeBytes []byte) func(kvdb.RwTx) error { + return func(tx kvdb.RwTx) error { + invoices, err := tx.CreateTopLevelBucket( invoiceBucket, ) if err != nil { @@ -162,9 +162,9 @@ func genBeforeMigration(beforeBytes []byte) func(*bbolt.Tx) error { // succeeded, but comparing the resulting encoding of the invoice to the // expected serialization. In addition, the decoded invoice is compared against // the expected invoice for equality. -func genAfterMigration(afterBytes []byte) func(*bbolt.Tx) error { - return func(tx *bbolt.Tx) error { - invoices := tx.Bucket(invoiceBucket) +func genAfterMigration(afterBytes []byte) func(kvdb.RwTx) error { + return func(tx kvdb.RwTx) error { + invoices := tx.ReadWriteBucket(invoiceBucket) if invoices == nil { return fmt.Errorf("invoice bucket not found") } diff --git a/channeldb/migration13/migration.go b/channeldb/migration13/migration.go index 56fced62de..df737d25a6 100644 --- a/channeldb/migration13/migration.go +++ b/channeldb/migration13/migration.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "fmt" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) var ( @@ -48,13 +48,13 @@ var ( // MigrateMPP migrates the payments to a new structure that accommodates for mpp // payments. -func MigrateMPP(tx *bbolt.Tx) error { +func MigrateMPP(tx kvdb.RwTx) error { log.Infof("Migrating payments to mpp structure") // Iterate over all payments and store their indexing keys. This is // needed, because no modifications are allowed inside a Bucket.ForEach // loop. - paymentsBucket := tx.Bucket(paymentsRootBucket) + paymentsBucket := tx.ReadWriteBucket(paymentsRootBucket) if paymentsBucket == nil { return nil } @@ -70,7 +70,7 @@ func MigrateMPP(tx *bbolt.Tx) error { // With all keys retrieved, start the migration. for _, k := range paymentKeys { - bucket := paymentsBucket.Bucket(k) + bucket := paymentsBucket.NestedReadWriteBucket(k) // We only expect sub-buckets to be found in // this top-level bucket. diff --git a/channeldb/migration13/migration_test.go b/channeldb/migration13/migration_test.go index 4b3e4f2c75..d71302fede 100644 --- a/channeldb/migration13/migration_test.go +++ b/channeldb/migration13/migration_test.go @@ -3,7 +3,7 @@ package migration13 import ( "testing" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/channeldb/migtest" ) @@ -111,10 +111,10 @@ func TestMigrateMpp(t *testing.T) { migtest.ApplyMigration( t, - func(tx *bbolt.Tx) error { + func(tx kvdb.RwTx) error { return migtest.RestoreDB(tx, paymentsRootBucket, pre) }, - func(tx *bbolt.Tx) error { + func(tx kvdb.RwTx) error { return migtest.VerifyDB(tx, paymentsRootBucket, post) }, MigrateMPP, diff --git a/channeldb/migration_01_to_11/db.go b/channeldb/migration_01_to_11/db.go index 116f06a46a..ed1239fd20 100644 --- a/channeldb/migration_01_to_11/db.go +++ b/channeldb/migration_01_to_11/db.go @@ -8,7 +8,7 @@ import ( "path/filepath" "time" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) const ( @@ -19,7 +19,7 @@ const ( // migration is a function which takes a prior outdated version of the database // instances and mutates the key/bucket structure to arrive at a more // up-to-date version of the database. -type migration func(tx *bbolt.Tx) error +type migration func(tx kvdb.RwTx) error var ( // Big endian is the preferred byte order, due to cursor scans over @@ -31,7 +31,7 @@ var ( // information related to nodes, routing data, open/closed channels, fee // schedules, and reputation data. type DB struct { - *bbolt.DB + kvdb.Backend dbPath string graph *ChannelGraph now func() time.Time @@ -55,20 +55,15 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) { // Specify bbolt freelist options to reduce heap pressure in case the // freelist grows to be very large. - options := &bbolt.Options{ - NoFreelistSync: opts.NoFreelistSync, - FreelistType: bbolt.FreelistMapType, - } - - bdb, err := bbolt.Open(path, dbFilePermission, options) + bdb, err := kvdb.Open(kvdb.BoltBackendName, path, opts.NoFreelistSync) if err != nil { return nil, err } chanDB := &DB{ - DB: bdb, - dbPath: dbPath, - now: time.Now, + Backend: bdb, + dbPath: dbPath, + now: time.Now, } chanDB.graph = newChannelGraph( chanDB, opts.RejectCacheSize, opts.ChannelCacheSize, @@ -89,28 +84,28 @@ func createChannelDB(dbPath string) error { } path := filepath.Join(dbPath, dbName) - bdb, err := bbolt.Open(path, dbFilePermission, nil) + bdb, err := kvdb.Create(kvdb.BoltBackendName, path, false) if err != nil { return err } - err = bdb.Update(func(tx *bbolt.Tx) error { - if _, err := tx.CreateBucket(openChannelBucket); err != nil { + err = kvdb.Update(bdb, func(tx kvdb.RwTx) error { + if _, err := tx.CreateTopLevelBucket(openChannelBucket); err != nil { return err } - if _, err := tx.CreateBucket(closedChannelBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(closedChannelBucket); err != nil { return err } - if _, err := tx.CreateBucket(invoiceBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(invoiceBucket); err != nil { return err } - if _, err := tx.CreateBucket(paymentBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(paymentBucket); err != nil { return err } - nodes, err := tx.CreateBucket(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return err } @@ -123,7 +118,7 @@ func createChannelDB(dbPath string) error { return err } - edges, err := tx.CreateBucket(edgeBucket) + edges, err := tx.CreateTopLevelBucket(edgeBucket) if err != nil { return err } @@ -140,7 +135,7 @@ func createChannelDB(dbPath string) error { return err } - graphMeta, err := tx.CreateBucket(graphMetaBucket) + graphMeta, err := tx.CreateTopLevelBucket(graphMetaBucket) if err != nil { return err } @@ -149,7 +144,7 @@ func createChannelDB(dbPath string) error { return err } - if _, err := tx.CreateBucket(metaBucket); err != nil { + if _, err := tx.CreateTopLevelBucket(metaBucket); err != nil { return err } @@ -185,8 +180,8 @@ func fileExists(path string) bool { func (d *DB) FetchClosedChannels(pendingOnly bool) ([]*ChannelCloseSummary, error) { var chanSummaries []*ChannelCloseSummary - if err := d.View(func(tx *bbolt.Tx) error { - closeBucket := tx.Bucket(closedChannelBucket) + if err := kvdb.View(d, func(tx kvdb.ReadTx) error { + closeBucket := tx.ReadBucket(closedChannelBucket) if closeBucket == nil { return ErrNoClosedChannels } diff --git a/channeldb/migration_01_to_11/graph.go b/channeldb/migration_01_to_11/graph.go index a782b9c454..14436f586a 100644 --- a/channeldb/migration_01_to_11/graph.go +++ b/channeldb/migration_01_to_11/graph.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -175,10 +175,10 @@ func newChannelGraph(db *DB, rejectCacheSize, chanCacheSize int) *ChannelGraph { // node based off the source node. func (c *ChannelGraph) SourceNode() (*LightningNode, error) { var source *LightningNode - err := c.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadBucket(nodeBucket) if nodes == nil { return ErrGraphNotFound } @@ -202,7 +202,7 @@ func (c *ChannelGraph) SourceNode() (*LightningNode, error) { // of the graph. The source node is treated as the center node within a // star-graph. This method may be used to kick off a path finding algorithm in // order to explore the reachability of another node based off the source node. -func (c *ChannelGraph) sourceNode(nodes *bbolt.Bucket) (*LightningNode, error) { +func (c *ChannelGraph) sourceNode(nodes kvdb.ReadBucket) (*LightningNode, error) { selfPub := nodes.Get(sourceKey) if selfPub == nil { return nil, ErrSourceNodeNotSet @@ -225,10 +225,10 @@ func (c *ChannelGraph) sourceNode(nodes *bbolt.Bucket) (*LightningNode, error) { func (c *ChannelGraph) SetSourceNode(node *LightningNode) error { nodePubBytes := node.PubKeyBytes[:] - return c.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return err } @@ -245,8 +245,8 @@ func (c *ChannelGraph) SetSourceNode(node *LightningNode) error { }) } -func addLightningNode(tx *bbolt.Tx, node *LightningNode) error { - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) +func addLightningNode(tx kvdb.RwTx, node *LightningNode) error { + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return err } @@ -270,17 +270,17 @@ func addLightningNode(tx *bbolt.Tx, node *LightningNode) error { // buckets using an existing database transaction. The returned boolean will be // true if the updated policy belongs to node1, and false if the policy belonged // to node2. -func updateEdgePolicy(tx *bbolt.Tx, edge *ChannelEdgePolicy) (bool, error) { - edges := tx.Bucket(edgeBucket) - if edges == nil { +func updateEdgePolicy(tx kvdb.RwTx, edge *ChannelEdgePolicy) (bool, error) { + edges, err := tx.CreateTopLevelBucket(edgeBucket) + if err != nil { return false, ErrEdgeNotFound } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadWriteBucket(edgeIndexBucket) if edgeIndex == nil { return false, ErrEdgeNotFound } - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return false, err } @@ -551,8 +551,8 @@ func (c *ChannelEdgePolicy) IsDisabled() bool { lnwire.ChanUpdateDisabled } -func putLightningNode(nodeBucket *bbolt.Bucket, aliasBucket *bbolt.Bucket, - updateIndex *bbolt.Bucket, node *LightningNode) error { +func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, + updateIndex kvdb.RwBucket, node *LightningNode) error { var ( scratch [16]byte @@ -680,7 +680,7 @@ func putLightningNode(nodeBucket *bbolt.Bucket, aliasBucket *bbolt.Bucket, return nodeBucket.Put(nodePub, b.Bytes()) } -func fetchLightningNode(nodeBucket *bbolt.Bucket, +func fetchLightningNode(nodeBucket kvdb.ReadBucket, nodePub []byte) (LightningNode, error) { nodeBytes := nodeBucket.Get(nodePub) @@ -863,7 +863,7 @@ func deserializeChanEdgeInfo(r io.Reader) (ChannelEdgeInfo, error) { return edgeInfo, nil } -func putChanEdgePolicy(edges, nodes *bbolt.Bucket, edge *ChannelEdgePolicy, +func putChanEdgePolicy(edges, nodes kvdb.RwBucket, edge *ChannelEdgePolicy, from, to []byte) error { var edgeKey [33 + 8]byte @@ -943,7 +943,7 @@ func putChanEdgePolicy(edges, nodes *bbolt.Bucket, edge *ChannelEdgePolicy, // in this bucket. // Maintaining the bucket this way allows a fast retrieval of disabled // channels, for example when prune is needed. -func updateEdgePolicyDisabledIndex(edges *bbolt.Bucket, chanID uint64, +func updateEdgePolicyDisabledIndex(edges kvdb.RwBucket, chanID uint64, direction bool, disabled bool) error { var disabledEdgeKey [8 + 1]byte @@ -968,7 +968,7 @@ func updateEdgePolicyDisabledIndex(edges *bbolt.Bucket, chanID uint64, // putChanEdgePolicyUnknown marks the edge policy as unknown // in the edges bucket. -func putChanEdgePolicyUnknown(edges *bbolt.Bucket, channelID uint64, +func putChanEdgePolicyUnknown(edges kvdb.RwBucket, channelID uint64, from []byte) error { var edgeKey [33 + 8]byte @@ -983,8 +983,8 @@ func putChanEdgePolicyUnknown(edges *bbolt.Bucket, channelID uint64, return edges.Put(edgeKey[:], unknownPolicy) } -func fetchChanEdgePolicy(edges *bbolt.Bucket, chanID []byte, - nodePub []byte, nodes *bbolt.Bucket) (*ChannelEdgePolicy, error) { +func fetchChanEdgePolicy(edges kvdb.ReadBucket, chanID []byte, + nodePub []byte, nodes kvdb.ReadBucket) (*ChannelEdgePolicy, error) { var edgeKey [33 + 8]byte copy(edgeKey[:], nodePub) @@ -1084,7 +1084,7 @@ func serializeChanEdgePolicy(w io.Writer, edge *ChannelEdgePolicy, } func deserializeChanEdgePolicy(r io.Reader, - nodes *bbolt.Bucket) (*ChannelEdgePolicy, error) { + nodes kvdb.ReadBucket) (*ChannelEdgePolicy, error) { edge := &ChannelEdgePolicy{} diff --git a/channeldb/migration_01_to_11/invoices.go b/channeldb/migration_01_to_11/invoices.go index f60457ffc9..7e56489b9a 100644 --- a/channeldb/migration_01_to_11/invoices.go +++ b/channeldb/migration_01_to_11/invoices.go @@ -8,7 +8,7 @@ import ( "time" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/tlv" @@ -252,8 +252,8 @@ func validateInvoice(i *Invoice) error { func (d *DB) FetchAllInvoices(pendingOnly bool) ([]Invoice, error) { var invoices []Invoice - err := d.View(func(tx *bbolt.Tx) error { - invoiceB := tx.Bucket(invoiceBucket) + err := kvdb.View(d, func(tx kvdb.ReadTx) error { + invoiceB := tx.ReadBucket(invoiceBucket) if invoiceB == nil { return ErrNoInvoicesCreated } diff --git a/channeldb/migration_01_to_11/meta.go b/channeldb/migration_01_to_11/meta.go index 3abcc0d082..95bce84bff 100644 --- a/channeldb/migration_01_to_11/meta.go +++ b/channeldb/migration_01_to_11/meta.go @@ -1,6 +1,8 @@ package migration_01_to_11 -import "github.com/coreos/bbolt" +import ( + "github.com/lightningnetwork/lnd/channeldb/kvdb" +) var ( // metaBucket stores all the meta information concerning the state of @@ -21,8 +23,8 @@ type Meta struct { // putMeta is an internal helper function used in order to allow callers to // re-use a database transaction. See the publicly exported PutMeta method for // more information. -func putMeta(meta *Meta, tx *bbolt.Tx) error { - metaBucket, err := tx.CreateBucketIfNotExists(metaBucket) +func putMeta(meta *Meta, tx kvdb.RwTx) error { + metaBucket, err := tx.CreateTopLevelBucket(metaBucket) if err != nil { return err } @@ -30,7 +32,7 @@ func putMeta(meta *Meta, tx *bbolt.Tx) error { return putDbVersion(metaBucket, meta) } -func putDbVersion(metaBucket *bbolt.Bucket, meta *Meta) error { +func putDbVersion(metaBucket kvdb.RwBucket, meta *Meta) error { scratch := make([]byte, 4) byteOrder.PutUint32(scratch, meta.DbVersionNumber) return metaBucket.Put(dbVersionKey, scratch) diff --git a/channeldb/migration_01_to_11/meta_test.go b/channeldb/migration_01_to_11/meta_test.go index 587116e197..d3850c155e 100644 --- a/channeldb/migration_01_to_11/meta_test.go +++ b/channeldb/migration_01_to_11/meta_test.go @@ -3,8 +3,8 @@ package migration_01_to_11 import ( "testing" - "github.com/coreos/bbolt" "github.com/go-errors/errors" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) // applyMigration is a helper test function that encapsulates the general steps @@ -49,7 +49,7 @@ func applyMigration(t *testing.T, beforeMigration, afterMigration func(d *DB), }() // Apply migration. - err = cdb.Update(func(tx *bbolt.Tx) error { + err = kvdb.Update(cdb, func(tx kvdb.RwTx) error { return migrationFunc(tx) }) if err != nil { diff --git a/channeldb/migration_01_to_11/migration_09_legacy_serialization.go b/channeldb/migration_01_to_11/migration_09_legacy_serialization.go index cc0568a308..3589662c8c 100644 --- a/channeldb/migration_01_to_11/migration_09_legacy_serialization.go +++ b/channeldb/migration_01_to_11/migration_09_legacy_serialization.go @@ -7,7 +7,7 @@ import ( "io" "sort" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" ) @@ -76,8 +76,8 @@ func (db *DB) addPayment(payment *outgoingPayment) error { } paymentBytes := b.Bytes() - return db.Batch(func(tx *bbolt.Tx) error { - payments, err := tx.CreateBucketIfNotExists(paymentBucket) + return kvdb.Update(db, func(tx kvdb.RwTx) error { + payments, err := tx.CreateTopLevelBucket(paymentBucket) if err != nil { return err } @@ -104,8 +104,8 @@ func (db *DB) addPayment(payment *outgoingPayment) error { func (db *DB) fetchAllPayments() ([]*outgoingPayment, error) { var payments []*outgoingPayment - err := db.View(func(tx *bbolt.Tx) error { - bucket := tx.Bucket(paymentBucket) + err := kvdb.View(db, func(tx kvdb.ReadTx) error { + bucket := tx.ReadBucket(paymentBucket) if bucket == nil { return ErrNoPaymentsCreated } @@ -140,7 +140,7 @@ func (db *DB) fetchAllPayments() ([]*outgoingPayment, error) { // NOTE: Deprecated. Kept around for migration purposes. func (db *DB) fetchPaymentStatus(paymentHash [32]byte) (PaymentStatus, error) { var paymentStatus = StatusUnknown - err := db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(db, func(tx kvdb.ReadTx) error { var err error paymentStatus, err = fetchPaymentStatusTx(tx, paymentHash) return err @@ -158,11 +158,11 @@ func (db *DB) fetchPaymentStatus(paymentHash [32]byte) (PaymentStatus, error) { // can be composed into other atomic operations. // // NOTE: Deprecated. Kept around for migration purposes. -func fetchPaymentStatusTx(tx *bbolt.Tx, paymentHash [32]byte) (PaymentStatus, error) { +func fetchPaymentStatusTx(tx kvdb.ReadTx, paymentHash [32]byte) (PaymentStatus, error) { // The default status for all payments that aren't recorded in database. var paymentStatus = StatusUnknown - bucket := tx.Bucket(paymentStatusBucket) + bucket := tx.ReadBucket(paymentStatusBucket) if bucket == nil { return paymentStatus, nil } @@ -375,14 +375,14 @@ func deserializeHopMigration9(r io.Reader) (*Hop, error) { func (db *DB) fetchPaymentsMigration9() ([]*Payment, error) { var payments []*Payment - err := db.View(func(tx *bbolt.Tx) error { - paymentsBucket := tx.Bucket(paymentsRootBucket) + err := kvdb.View(db, func(tx kvdb.ReadTx) error { + paymentsBucket := tx.ReadBucket(paymentsRootBucket) if paymentsBucket == nil { return nil } return paymentsBucket.ForEach(func(k, v []byte) error { - bucket := paymentsBucket.Bucket(k) + bucket := paymentsBucket.NestedReadBucket(k) if bucket == nil { // We only expect sub-buckets to be found in // this top-level bucket. @@ -401,13 +401,13 @@ func (db *DB) fetchPaymentsMigration9() ([]*Payment, error) { // payment has was possible. These will be found in a // sub-bucket indexed by their sequence number if // available. - dup := bucket.Bucket(paymentDuplicateBucket) + dup := bucket.NestedReadBucket(paymentDuplicateBucket) if dup == nil { return nil } return dup.ForEach(func(k, v []byte) error { - subBucket := dup.Bucket(k) + subBucket := dup.NestedReadBucket(k) if subBucket == nil { // We one bucket for each duplicate to // be found. @@ -437,7 +437,7 @@ func (db *DB) fetchPaymentsMigration9() ([]*Payment, error) { return payments, nil } -func fetchPaymentMigration9(bucket *bbolt.Bucket) (*Payment, error) { +func fetchPaymentMigration9(bucket kvdb.ReadBucket) (*Payment, error) { var ( err error p = &Payment{} diff --git a/channeldb/migration_01_to_11/migration_10_route_tlv_records.go b/channeldb/migration_01_to_11/migration_10_route_tlv_records.go index e404f5751b..21a684f670 100644 --- a/channeldb/migration_01_to_11/migration_10_route_tlv_records.go +++ b/channeldb/migration_01_to_11/migration_10_route_tlv_records.go @@ -4,15 +4,15 @@ import ( "bytes" "io" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) // MigrateRouteSerialization migrates the way we serialize routes across the // entire database. At the time of writing of this migration, this includes our // payment attempts, as well as the payment results in mission control. -func MigrateRouteSerialization(tx *bbolt.Tx) error { +func MigrateRouteSerialization(tx kvdb.RwTx) error { // First, we'll do all the payment attempts. - rootPaymentBucket := tx.Bucket(paymentsRootBucket) + rootPaymentBucket := tx.ReadWriteBucket(paymentsRootBucket) if rootPaymentBucket == nil { return nil } @@ -36,7 +36,7 @@ func MigrateRouteSerialization(tx *bbolt.Tx) error { // Now that we have all the payment hashes, we can carry out the // migration itself. for _, payHash := range payHashes { - payHashBucket := rootPaymentBucket.Bucket(payHash) + payHashBucket := rootPaymentBucket.NestedReadWriteBucket(payHash) // First, we'll migrate the main (non duplicate) payment to // this hash. @@ -47,7 +47,7 @@ func MigrateRouteSerialization(tx *bbolt.Tx) error { // Now that we've migrated the main payment, we'll also check // for any duplicate payments to the same payment hash. - dupBucket := payHashBucket.Bucket(paymentDuplicateBucket) + dupBucket := payHashBucket.NestedReadWriteBucket(paymentDuplicateBucket) // If there's no dup bucket, then we can move on to the next // payment. @@ -69,7 +69,7 @@ func MigrateRouteSerialization(tx *bbolt.Tx) error { // Now in this second pass, we'll re-serialize their duplicate // payment attempts under the new encoding. for _, seqNo := range dupSeqNos { - dupPayHashBucket := dupBucket.Bucket(seqNo) + dupPayHashBucket := dupBucket.NestedReadWriteBucket(seqNo) err := migrateAttemptEncoding(tx, dupPayHashBucket) if err != nil { return err @@ -83,8 +83,8 @@ func MigrateRouteSerialization(tx *bbolt.Tx) error { "existing data") resultsKey := []byte("missioncontrol-results") - err = tx.DeleteBucket(resultsKey) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(resultsKey) + if err != nil && err != kvdb.ErrBucketNotFound { return err } @@ -95,7 +95,7 @@ func MigrateRouteSerialization(tx *bbolt.Tx) error { // migrateAttemptEncoding migrates payment attempts using the legacy format to // the new format. -func migrateAttemptEncoding(tx *bbolt.Tx, payHashBucket *bbolt.Bucket) error { +func migrateAttemptEncoding(tx kvdb.RwTx, payHashBucket kvdb.RwBucket) error { payAttemptBytes := payHashBucket.Get(paymentAttemptInfoKey) if payAttemptBytes == nil { return nil diff --git a/channeldb/migration_01_to_11/migration_11_invoices.go b/channeldb/migration_01_to_11/migration_11_invoices.go index 449e9b5dea..242631d86f 100644 --- a/channeldb/migration_01_to_11/migration_11_invoices.go +++ b/channeldb/migration_01_to_11/migration_11_invoices.go @@ -8,7 +8,7 @@ import ( bitcoinCfg "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/zpay32" litecoinCfg "github.com/ltcsuite/ltcd/chaincfg" @@ -16,10 +16,10 @@ import ( // MigrateInvoices adds invoice htlcs and a separate cltv delta field to the // invoices. -func MigrateInvoices(tx *bbolt.Tx) error { +func MigrateInvoices(tx kvdb.RwTx) error { log.Infof("Migrating invoices to new invoice format") - invoiceB := tx.Bucket(invoiceBucket) + invoiceB := tx.ReadWriteBucket(invoiceBucket) if invoiceB == nil { return nil } diff --git a/channeldb/migration_01_to_11/migration_11_invoices_test.go b/channeldb/migration_01_to_11/migration_11_invoices_test.go index 0776458dee..32899d8e01 100644 --- a/channeldb/migration_01_to_11/migration_11_invoices_test.go +++ b/channeldb/migration_01_to_11/migration_11_invoices_test.go @@ -8,7 +8,7 @@ import ( "github.com/btcsuite/btcd/btcec" bitcoinCfg "github.com/btcsuite/btcd/chaincfg" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/zpay32" litecoinCfg "github.com/ltcsuite/ltcd/chaincfg" ) @@ -26,8 +26,8 @@ var ( // beforeMigrationFuncV11 insert the test invoices in the database. func beforeMigrationFuncV11(t *testing.T, d *DB, invoices []Invoice) { - err := d.Update(func(tx *bbolt.Tx) error { - invoicesBucket, err := tx.CreateBucketIfNotExists( + err := kvdb.Update(d, func(tx kvdb.RwTx) error { + invoicesBucket, err := tx.CreateTopLevelBucket( invoiceBucket, ) if err != nil { diff --git a/channeldb/migration_01_to_11/migrations.go b/channeldb/migration_01_to_11/migrations.go index 511633d88d..35be510e99 100644 --- a/channeldb/migration_01_to_11/migrations.go +++ b/channeldb/migration_01_to_11/migrations.go @@ -7,7 +7,7 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -16,11 +16,11 @@ import ( // (one for nodes and one for edges) to keep track of the last time a node or // edge was updated on the network. These new indexes allow us to implement the // new graph sync protocol added. -func MigrateNodeAndEdgeUpdateIndex(tx *bbolt.Tx) error { +func MigrateNodeAndEdgeUpdateIndex(tx kvdb.RwTx) error { // First, we'll populating the node portion of the new index. Before we // can add new values to the index, we'll first create the new bucket // where these items will be housed. - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return fmt.Errorf("unable to create node bucket: %v", err) } @@ -64,7 +64,7 @@ func MigrateNodeAndEdgeUpdateIndex(tx *bbolt.Tx) error { // With the set of nodes updated, we'll now update all edges to have a // corresponding entry in the edge update index. - edges, err := tx.CreateBucketIfNotExists(edgeBucket) + edges, err := tx.CreateTopLevelBucket(edgeBucket) if err != nil { return fmt.Errorf("unable to create edge bucket: %v", err) } @@ -121,8 +121,8 @@ func MigrateNodeAndEdgeUpdateIndex(tx *bbolt.Tx) error { // invoices an index in the add and/or the settle index. Additionally, all // existing invoices will have their bytes padded out in order to encode the // add+settle index as well as the amount paid. -func MigrateInvoiceTimeSeries(tx *bbolt.Tx) error { - invoices, err := tx.CreateBucketIfNotExists(invoiceBucket) +func MigrateInvoiceTimeSeries(tx kvdb.RwTx) error { + invoices, err := tx.CreateTopLevelBucket(invoiceBucket) if err != nil { return err } @@ -258,8 +258,8 @@ func MigrateInvoiceTimeSeries(tx *bbolt.Tx) error { // migrateInvoiceTimeSeries migration. As at the time of writing, the // OutgoingPayment struct embeddeds an instance of the Invoice struct. As a // result, we also need to migrate the internal invoice to the new format. -func MigrateInvoiceTimeSeriesOutgoingPayments(tx *bbolt.Tx) error { - payBucket := tx.Bucket(paymentBucket) +func MigrateInvoiceTimeSeriesOutgoingPayments(tx kvdb.RwTx) error { + payBucket := tx.ReadWriteBucket(paymentBucket) if payBucket == nil { return nil } @@ -339,18 +339,18 @@ func MigrateInvoiceTimeSeriesOutgoingPayments(tx *bbolt.Tx) error { // bucket. It ensure that edges with unknown policies will also have an entry // in the bucket. After the migration, there will be two edge entries for // every channel, regardless of whether the policies are known. -func MigrateEdgePolicies(tx *bbolt.Tx) error { - nodes := tx.Bucket(nodeBucket) +func MigrateEdgePolicies(tx kvdb.RwTx) error { + nodes := tx.ReadWriteBucket(nodeBucket) if nodes == nil { return nil } - edges := tx.Bucket(edgeBucket) + edges := tx.ReadWriteBucket(edgeBucket) if edges == nil { return nil } - edgeIndex := edges.Bucket(edgeIndexBucket) + edgeIndex := edges.NestedReadWriteBucket(edgeIndexBucket) if edgeIndex == nil { return nil } @@ -411,10 +411,10 @@ func MigrateEdgePolicies(tx *bbolt.Tx) error { // PaymentStatusesMigration is a database migration intended for adding payment // statuses for each existing payment entity in bucket to be able control // transitions of statuses and prevent cases such as double payment -func PaymentStatusesMigration(tx *bbolt.Tx) error { +func PaymentStatusesMigration(tx kvdb.RwTx) error { // Get the bucket dedicated to storing statuses of payments, // where a key is payment hash, value is payment status. - paymentStatuses, err := tx.CreateBucketIfNotExists(paymentStatusBucket) + paymentStatuses, err := tx.CreateTopLevelBucket(paymentStatusBucket) if err != nil { return err } @@ -422,7 +422,7 @@ func PaymentStatusesMigration(tx *bbolt.Tx) error { log.Infof("Migrating database to support payment statuses") circuitAddKey := []byte("circuit-adds") - circuits := tx.Bucket(circuitAddKey) + circuits := tx.ReadWriteBucket(circuitAddKey) if circuits != nil { log.Infof("Marking all known circuits with status InFlight") @@ -455,7 +455,7 @@ func PaymentStatusesMigration(tx *bbolt.Tx) error { log.Infof("Marking all existing payments with status Completed") // Get the bucket dedicated to storing payments - bucket := tx.Bucket(paymentBucket) + bucket := tx.ReadWriteBucket(paymentBucket) if bucket == nil { return nil } @@ -498,14 +498,14 @@ func PaymentStatusesMigration(tx *bbolt.Tx) error { // migration also fixes the case where the public keys within edge policies were // being serialized with an extra byte, causing an even greater error when // attempting to perform the offset calculation described earlier. -func MigratePruneEdgeUpdateIndex(tx *bbolt.Tx) error { +func MigratePruneEdgeUpdateIndex(tx kvdb.RwTx) error { // To begin the migration, we'll retrieve the update index bucket. If it // does not exist, we have nothing left to do so we can simply exit. - edges := tx.Bucket(edgeBucket) + edges := tx.ReadWriteBucket(edgeBucket) if edges == nil { return nil } - edgeUpdateIndex := edges.Bucket(edgeUpdateIndexBucket) + edgeUpdateIndex := edges.NestedReadWriteBucket(edgeUpdateIndexBucket) if edgeUpdateIndex == nil { return nil } @@ -521,7 +521,7 @@ func MigratePruneEdgeUpdateIndex(tx *bbolt.Tx) error { return fmt.Errorf("unable to create/fetch edge index " + "bucket") } - nodes, err := tx.CreateBucketIfNotExists(nodeBucket) + nodes, err := tx.CreateTopLevelBucket(nodeBucket) if err != nil { return fmt.Errorf("unable to make node bucket") } @@ -612,8 +612,8 @@ func MigratePruneEdgeUpdateIndex(tx *bbolt.Tx) error { // MigrateOptionalChannelCloseSummaryFields migrates the serialized format of // ChannelCloseSummary to a format where optional fields' presence is indicated // with boolean markers. -func MigrateOptionalChannelCloseSummaryFields(tx *bbolt.Tx) error { - closedChanBucket := tx.Bucket(closedChannelBucket) +func MigrateOptionalChannelCloseSummaryFields(tx kvdb.RwTx) error { + closedChanBucket := tx.ReadWriteBucket(closedChannelBucket) if closedChanBucket == nil { return nil } @@ -671,11 +671,11 @@ var messageStoreBucket = []byte("message-store") // MigrateGossipMessageStoreKeys migrates the key format for gossip messages // found in the message store to a new one that takes into consideration the of // the message being stored. -func MigrateGossipMessageStoreKeys(tx *bbolt.Tx) error { +func MigrateGossipMessageStoreKeys(tx kvdb.RwTx) error { // We'll start by retrieving the bucket in which these messages are // stored within. If there isn't one, there's nothing left for us to do // so we can avoid the migration. - messageStore := tx.Bucket(messageStoreBucket) + messageStore := tx.ReadWriteBucket(messageStoreBucket) if messageStore == nil { return nil } @@ -747,10 +747,10 @@ func MigrateGossipMessageStoreKeys(tx *bbolt.Tx) error { // InFlight (we have no PaymentAttemptInfo available for pre-migration // payments) we delete those statuses, so only Completed payments remain in the // new bucket structure. -func MigrateOutgoingPayments(tx *bbolt.Tx) error { +func MigrateOutgoingPayments(tx kvdb.RwTx) error { log.Infof("Migrating outgoing payments to new bucket structure") - oldPayments := tx.Bucket(paymentBucket) + oldPayments := tx.ReadWriteBucket(paymentBucket) // Return early if there are no payments to migrate. if oldPayments == nil { @@ -758,7 +758,7 @@ func MigrateOutgoingPayments(tx *bbolt.Tx) error { return nil } - newPayments, err := tx.CreateBucket(paymentsRootBucket) + newPayments, err := tx.CreateTopLevelBucket(paymentsRootBucket) if err != nil { return err } @@ -767,7 +767,7 @@ func MigrateOutgoingPayments(tx *bbolt.Tx) error { // only attempt to fetch it if needed. sourcePub := func() ([33]byte, error) { var pub [33]byte - nodes := tx.Bucket(nodeBucket) + nodes := tx.ReadWriteBucket(nodeBucket) if nodes == nil { return pub, ErrGraphNotFound } @@ -862,8 +862,8 @@ func MigrateOutgoingPayments(tx *bbolt.Tx) error { // from a database containing duplicate payments to a payment // hash. To keep this information, we store such duplicate // payments in a sub-bucket. - if err == bbolt.ErrBucketExists { - pHashBucket := newPayments.Bucket(paymentHash[:]) + if err == kvdb.ErrBucketExists { + pHashBucket := newPayments.NestedReadWriteBucket(paymentHash[:]) // Create a bucket for duplicate payments within this // payment hash's bucket. @@ -922,14 +922,14 @@ func MigrateOutgoingPayments(tx *bbolt.Tx) error { // Now we delete the old buckets. Deleting the payment status buckets // deletes all payment statuses other than Complete. - err = tx.DeleteBucket(paymentStatusBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(paymentStatusBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } // Finally delete the old payment bucket. - err = tx.DeleteBucket(paymentBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = tx.DeleteTopLevelBucket(paymentBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } diff --git a/channeldb/migration_01_to_11/migrations_test.go b/channeldb/migration_01_to_11/migrations_test.go index fd2c25652a..c2531b8fbd 100644 --- a/channeldb/migration_01_to_11/migrations_test.go +++ b/channeldb/migration_01_to_11/migrations_test.go @@ -11,9 +11,9 @@ import ( "time" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" ) @@ -59,8 +59,8 @@ func TestPaymentStatusesMigration(t *testing.T) { // locally-sourced payment should end up with an InFlight // status, while the other should remain unchanged, which // defaults to Grounded. - err = d.Update(func(tx *bbolt.Tx) error { - circuits, err := tx.CreateBucketIfNotExists( + err = kvdb.Update(d, func(tx kvdb.RwTx) error { + circuits, err := tx.CreateTopLevelBucket( []byte("circuit-adds"), ) if err != nil { @@ -377,8 +377,8 @@ func TestMigrateOptionalChannelCloseSummaryFields(t *testing.T) { // Get the old serialization format for this test's // close summary, and it to the closed channel bucket. old := test.oldSerialization(test.closeSummary) - err = d.Update(func(tx *bbolt.Tx) error { - closedChanBucket, err := tx.CreateBucketIfNotExists( + err = kvdb.Update(d, func(tx kvdb.RwTx) error { + closedChanBucket, err := tx.CreateTopLevelBucket( closedChannelBucket, ) if err != nil { @@ -404,8 +404,8 @@ func TestMigrateOptionalChannelCloseSummaryFields(t *testing.T) { newSerialization := b.Bytes() var dbSummary []byte - err = d.View(func(tx *bbolt.Tx) error { - closedChanBucket := tx.Bucket(closedChannelBucket) + err = kvdb.View(d, func(tx kvdb.ReadTx) error { + closedChanBucket := tx.ReadBucket(closedChannelBucket) if closedChanBucket == nil { return errors.New("unable to find bucket") } @@ -482,8 +482,8 @@ func TestMigrateGossipMessageStoreKeys(t *testing.T) { t.Fatalf("unable to serialize message: %v", err) } - err := db.Update(func(tx *bbolt.Tx) error { - messageStore, err := tx.CreateBucketIfNotExists( + err := kvdb.Update(db, func(tx kvdb.RwTx) error { + messageStore, err := tx.CreateTopLevelBucket( messageStoreBucket, ) if err != nil { @@ -503,8 +503,8 @@ func TestMigrateGossipMessageStoreKeys(t *testing.T) { // 3. The message matches the original. afterMigration := func(db *DB) { var rawMsg []byte - err := db.View(func(tx *bbolt.Tx) error { - messageStore := tx.Bucket(messageStoreBucket) + err := kvdb.View(db, func(tx kvdb.ReadTx) error { + messageStore := tx.ReadBucket(messageStoreBucket) if messageStore == nil { return errors.New("message store bucket not " + "found") @@ -666,8 +666,8 @@ func TestOutgoingPaymentsMigration(t *testing.T) { // Finally, check that the payment sequence number is updated // to reflect the migrated payments. - err = d.View(func(tx *bbolt.Tx) error { - payments := tx.Bucket(paymentsRootBucket) + err = kvdb.Update(d, func(tx kvdb.RwTx) error { + payments := tx.ReadWriteBucket(paymentsRootBucket) if payments == nil { return fmt.Errorf("payments bucket not found") } @@ -746,8 +746,8 @@ func TestPaymentRouteSerialization(t *testing.T) { // We'll first add a series of fake payments, using the existing legacy // serialization format. beforeMigrationFunc := func(d *DB) { - err := d.Update(func(tx *bbolt.Tx) error { - paymentsBucket, err := tx.CreateBucket( + err := kvdb.Update(d, func(tx kvdb.RwTx) error { + paymentsBucket, err := tx.CreateTopLevelBucket( paymentsRootBucket, ) if err != nil { @@ -798,7 +798,7 @@ func TestPaymentRouteSerialization(t *testing.T) { // the proper bucket. If this is the duplicate // payment, then we'll grab the dup bucket, // otherwise, we'll use the top level bucket. - var payHashBucket *bbolt.Bucket + var payHashBucket kvdb.RwBucket if i < numPayments-1 { payHashBucket, err = paymentsBucket.CreateBucket( payInfo.PaymentHash[:], @@ -807,7 +807,7 @@ func TestPaymentRouteSerialization(t *testing.T) { t.Fatalf("unable to create payments bucket: %v", err) } } else { - payHashBucket = paymentsBucket.Bucket( + payHashBucket = paymentsBucket.NestedReadWriteBucket( payInfo.PaymentHash[:], ) dupPayBucket, err := payHashBucket.CreateBucket( diff --git a/channeldb/migration_01_to_11/payment_control.go b/channeldb/migration_01_to_11/payment_control.go index 7b069d24e3..80acf9cea8 100644 --- a/channeldb/migration_01_to_11/payment_control.go +++ b/channeldb/migration_01_to_11/payment_control.go @@ -1,12 +1,10 @@ package migration_01_to_11 -import ( - "github.com/coreos/bbolt" -) +import "github.com/lightningnetwork/lnd/channeldb/kvdb" // fetchPaymentStatus fetches the payment status of the payment. If the payment // isn't found, it will default to "StatusUnknown". -func fetchPaymentStatus(bucket *bbolt.Bucket) PaymentStatus { +func fetchPaymentStatus(bucket kvdb.ReadBucket) PaymentStatus { if bucket.Get(paymentSettleInfoKey) != nil { return StatusSucceeded } diff --git a/channeldb/migration_01_to_11/payments.go b/channeldb/migration_01_to_11/payments.go index 16e4a71c4c..e0b185f391 100644 --- a/channeldb/migration_01_to_11/payments.go +++ b/channeldb/migration_01_to_11/payments.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/tlv" @@ -254,14 +254,14 @@ type Payment struct { func (db *DB) FetchPayments() ([]*Payment, error) { var payments []*Payment - err := db.View(func(tx *bbolt.Tx) error { - paymentsBucket := tx.Bucket(paymentsRootBucket) + err := kvdb.View(db, func(tx kvdb.ReadTx) error { + paymentsBucket := tx.ReadBucket(paymentsRootBucket) if paymentsBucket == nil { return nil } return paymentsBucket.ForEach(func(k, v []byte) error { - bucket := paymentsBucket.Bucket(k) + bucket := paymentsBucket.NestedReadBucket(k) if bucket == nil { // We only expect sub-buckets to be found in // this top-level bucket. @@ -280,13 +280,13 @@ func (db *DB) FetchPayments() ([]*Payment, error) { // payment has was possible. These will be found in a // sub-bucket indexed by their sequence number if // available. - dup := bucket.Bucket(paymentDuplicateBucket) + dup := bucket.NestedReadBucket(paymentDuplicateBucket) if dup == nil { return nil } return dup.ForEach(func(k, v []byte) error { - subBucket := dup.Bucket(k) + subBucket := dup.NestedReadBucket(k) if subBucket == nil { // We one bucket for each duplicate to // be found. @@ -316,7 +316,7 @@ func (db *DB) FetchPayments() ([]*Payment, error) { return payments, nil } -func fetchPayment(bucket *bbolt.Bucket) (*Payment, error) { +func fetchPayment(bucket kvdb.ReadBucket) (*Payment, error) { var ( err error p = &Payment{} diff --git a/channeldb/migtest/migtest.go b/channeldb/migtest/migtest.go index b2200ebf71..0b8e14f095 100644 --- a/channeldb/migtest/migtest.go +++ b/channeldb/migtest/migtest.go @@ -6,13 +6,13 @@ import ( "os" "testing" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) // MakeDB creates a new instance of the ChannelDB for testing purposes. A // callback which cleans up the created temporary directories is also returned // and intended to be executed after the test completes. -func MakeDB() (*bbolt.DB, func(), error) { +func MakeDB() (kvdb.Backend, func(), error) { // Create temporary database for mission control. file, err := ioutil.TempFile("", "*.db") if err != nil { @@ -20,7 +20,7 @@ func MakeDB() (*bbolt.DB, func(), error) { } dbPath := file.Name() - db, err := bbolt.Open(dbPath, 0600, nil) + db, err := kvdb.Open(kvdb.BoltBackendName, dbPath, true) if err != nil { return nil, nil, err } @@ -36,7 +36,7 @@ func MakeDB() (*bbolt.DB, func(), error) { // ApplyMigration is a helper test function that encapsulates the general steps // which are needed to properly check the result of applying migration function. func ApplyMigration(t *testing.T, - beforeMigration, afterMigration, migrationFunc func(tx *bbolt.Tx) error, + beforeMigration, afterMigration, migrationFunc func(tx kvdb.RwTx) error, shouldFail bool) { cdb, cleanUp, err := MakeDB() @@ -47,7 +47,7 @@ func ApplyMigration(t *testing.T, // beforeMigration usually used for populating the database // with test data. - err = cdb.Update(beforeMigration) + err = kvdb.Update(cdb, beforeMigration) if err != nil { t.Fatal(err) } @@ -65,14 +65,14 @@ func ApplyMigration(t *testing.T, // afterMigration usually used for checking the database state and // throwing the error if something went wrong. - err = cdb.Update(afterMigration) + err = kvdb.Update(cdb, afterMigration) if err != nil { t.Fatal(err) } }() // Apply migration. - err = cdb.Update(migrationFunc) + err = kvdb.Update(cdb, migrationFunc) if err != nil { t.Fatal(err) } diff --git a/channeldb/migtest/raw_db.go b/channeldb/migtest/raw_db.go index 46dc417a85..8f3f1f2211 100644 --- a/channeldb/migtest/raw_db.go +++ b/channeldb/migtest/raw_db.go @@ -7,7 +7,7 @@ import ( "fmt" "strings" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) // DumpDB dumps go code describing the contents of the database to stdout. This @@ -21,8 +21,8 @@ import ( // hex("1111"): hex("5783492373"), // }, // } -func DumpDB(tx *bbolt.Tx, rootKey []byte) error { - bucket := tx.Bucket(rootKey) +func DumpDB(tx kvdb.ReadTx, rootKey []byte) error { + bucket := tx.ReadBucket(rootKey) if bucket == nil { return fmt.Errorf("bucket %v not found", string(rootKey)) } @@ -30,13 +30,13 @@ func DumpDB(tx *bbolt.Tx, rootKey []byte) error { return dumpBucket(bucket) } -func dumpBucket(bucket *bbolt.Bucket) error { +func dumpBucket(bucket kvdb.ReadBucket) error { fmt.Printf("map[string]interface{} {\n") err := bucket.ForEach(func(k, v []byte) error { key := toString(k) fmt.Printf("%v: ", key) - subBucket := bucket.Bucket(k) + subBucket := bucket.NestedReadBucket(k) if subBucket != nil { err := dumpBucket(subBucket) if err != nil { @@ -58,8 +58,8 @@ func dumpBucket(bucket *bbolt.Bucket) error { } // RestoreDB primes the database with the given data set. -func RestoreDB(tx *bbolt.Tx, rootKey []byte, data map[string]interface{}) error { - bucket, err := tx.CreateBucket(rootKey) +func RestoreDB(tx kvdb.RwTx, rootKey []byte, data map[string]interface{}) error { + bucket, err := tx.CreateTopLevelBucket(rootKey) if err != nil { return err } @@ -67,7 +67,7 @@ func RestoreDB(tx *bbolt.Tx, rootKey []byte, data map[string]interface{}) error return restoreDB(bucket, data) } -func restoreDB(bucket *bbolt.Bucket, data map[string]interface{}) error { +func restoreDB(bucket kvdb.RwBucket, data map[string]interface{}) error { for k, v := range data { key := []byte(k) @@ -100,8 +100,8 @@ func restoreDB(bucket *bbolt.Bucket, data map[string]interface{}) error { } // VerifyDB verifies the database against the given data set. -func VerifyDB(tx *bbolt.Tx, rootKey []byte, data map[string]interface{}) error { - bucket := tx.Bucket(rootKey) +func VerifyDB(tx kvdb.ReadTx, rootKey []byte, data map[string]interface{}) error { + bucket := tx.ReadBucket(rootKey) if bucket == nil { return fmt.Errorf("bucket %v not found", string(rootKey)) } @@ -109,7 +109,7 @@ func VerifyDB(tx *bbolt.Tx, rootKey []byte, data map[string]interface{}) error { return verifyDB(bucket, data) } -func verifyDB(bucket *bbolt.Bucket, data map[string]interface{}) error { +func verifyDB(bucket kvdb.ReadBucket, data map[string]interface{}) error { for k, v := range data { key := []byte(k) @@ -126,7 +126,7 @@ func verifyDB(bucket *bbolt.Bucket, data map[string]interface{}) error { // Key contains a sub-bucket. case map[string]interface{}: - subBucket := bucket.Bucket(key) + subBucket := bucket.NestedReadBucket(key) if subBucket == nil { return fmt.Errorf("bucket %v not found", k) } diff --git a/channeldb/nodes.go b/channeldb/nodes.go index 95f6f7a263..57197fb384 100644 --- a/channeldb/nodes.go +++ b/channeldb/nodes.go @@ -8,7 +8,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) var ( @@ -101,8 +101,8 @@ func (l *LinkNode) Sync() error { // Finally update the database by storing the link node and updating // any relevant indexes. - return l.db.Update(func(tx *bbolt.Tx) error { - nodeMetaBucket := tx.Bucket(nodeInfoBucket) + return kvdb.Update(l.db, func(tx kvdb.RwTx) error { + nodeMetaBucket := tx.ReadWriteBucket(nodeInfoBucket) if nodeMetaBucket == nil { return ErrLinkNodesNotFound } @@ -114,7 +114,7 @@ func (l *LinkNode) Sync() error { // putLinkNode serializes then writes the encoded version of the passed link // node into the nodeMetaBucket. This function is provided in order to allow // the ability to re-use a database transaction across many operations. -func putLinkNode(nodeMetaBucket *bbolt.Bucket, l *LinkNode) error { +func putLinkNode(nodeMetaBucket kvdb.RwBucket, l *LinkNode) error { // First serialize the LinkNode into its raw-bytes encoding. var b bytes.Buffer if err := serializeLinkNode(&b, l); err != nil { @@ -130,13 +130,13 @@ func putLinkNode(nodeMetaBucket *bbolt.Bucket, l *LinkNode) error { // DeleteLinkNode removes the link node with the given identity from the // database. func (db *DB) DeleteLinkNode(identity *btcec.PublicKey) error { - return db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(db, func(tx kvdb.RwTx) error { return db.deleteLinkNode(tx, identity) }) } -func (db *DB) deleteLinkNode(tx *bbolt.Tx, identity *btcec.PublicKey) error { - nodeMetaBucket := tx.Bucket(nodeInfoBucket) +func (db *DB) deleteLinkNode(tx kvdb.RwTx, identity *btcec.PublicKey) error { + nodeMetaBucket := tx.ReadWriteBucket(nodeInfoBucket) if nodeMetaBucket == nil { return ErrLinkNodesNotFound } @@ -150,7 +150,7 @@ func (db *DB) deleteLinkNode(tx *bbolt.Tx, identity *btcec.PublicKey) error { // key cannot be found, then ErrNodeNotFound if returned. func (db *DB) FetchLinkNode(identity *btcec.PublicKey) (*LinkNode, error) { var linkNode *LinkNode - err := db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(db, func(tx kvdb.ReadTx) error { node, err := fetchLinkNode(tx, identity) if err != nil { return err @@ -163,10 +163,10 @@ func (db *DB) FetchLinkNode(identity *btcec.PublicKey) (*LinkNode, error) { return linkNode, err } -func fetchLinkNode(tx *bbolt.Tx, targetPub *btcec.PublicKey) (*LinkNode, error) { +func fetchLinkNode(tx kvdb.ReadTx, targetPub *btcec.PublicKey) (*LinkNode, error) { // First fetch the bucket for storing node metadata, bailing out early // if it hasn't been created yet. - nodeMetaBucket := tx.Bucket(nodeInfoBucket) + nodeMetaBucket := tx.ReadBucket(nodeInfoBucket) if nodeMetaBucket == nil { return nil, ErrLinkNodesNotFound } @@ -191,7 +191,7 @@ func fetchLinkNode(tx *bbolt.Tx, targetPub *btcec.PublicKey) (*LinkNode, error) // whom we have active channels with. func (db *DB) FetchAllLinkNodes() ([]*LinkNode, error) { var linkNodes []*LinkNode - err := db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(db, func(tx kvdb.ReadTx) error { nodes, err := db.fetchAllLinkNodes(tx) if err != nil { return err @@ -209,8 +209,8 @@ func (db *DB) FetchAllLinkNodes() ([]*LinkNode, error) { // fetchAllLinkNodes uses an existing database transaction to fetch all nodes // with whom we have active channels with. -func (db *DB) fetchAllLinkNodes(tx *bbolt.Tx) ([]*LinkNode, error) { - nodeMetaBucket := tx.Bucket(nodeInfoBucket) +func (db *DB) fetchAllLinkNodes(tx kvdb.ReadTx) ([]*LinkNode, error) { + nodeMetaBucket := tx.ReadBucket(nodeInfoBucket) if nodeMetaBucket == nil { return nil, ErrLinkNodesNotFound } diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 1b65f4bf65..64d7a39198 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -6,7 +6,7 @@ import ( "errors" "fmt" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" ) @@ -65,7 +65,7 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, infoBytes := b.Bytes() var updateErr error - err := p.db.Batch(func(tx *bbolt.Tx) error { + err := kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error { // Reset the update error, to avoid carrying over an error // from a previous execution of the batched db transaction. updateErr = nil @@ -130,8 +130,8 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, // We'll delete any lingering HTLCs to start with, in case we // are initializing a payment that was attempted earlier, but // left in a state where we could retry. - err = bucket.DeleteBucket(paymentHtlcsBucket) - if err != nil && err != bbolt.ErrBucketNotFound { + err = bucket.DeleteNestedBucket(paymentHtlcsBucket) + if err != nil && err != kvdb.ErrBucketNotFound { return err } @@ -162,9 +162,8 @@ func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, htlcIDBytes := make([]byte, 8) binary.BigEndian.PutUint64(htlcIDBytes, attempt.AttemptID) - return p.db.Update(func(tx *bbolt.Tx) error { - // Get the payment bucket to register this new attempt in. - bucket, err := fetchPaymentBucket(tx, paymentHash) + return kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error { + bucket, err := fetchPaymentBucketUpdate(tx, paymentHash) if err != nil { return err } @@ -234,10 +233,10 @@ func (p *PaymentControl) updateHtlcKey(paymentHash lntypes.Hash, binary.BigEndian.PutUint64(htlcIDBytes, attemptID) var payment *MPPayment - err := p.db.Batch(func(tx *bbolt.Tx) error { - // Fetch bucket that contains all information for the payment - // with this hash. - bucket, err := fetchPaymentBucket(tx, paymentHash) + err := kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error { + payment = nil + + bucket, err := fetchPaymentBucketUpdate(tx, paymentHash) if err != nil { return err } @@ -247,12 +246,12 @@ func (p *PaymentControl) updateHtlcKey(paymentHash lntypes.Hash, return err } - htlcsBucket := bucket.Bucket(paymentHtlcsBucket) + htlcsBucket := bucket.NestedReadWriteBucket(paymentHtlcsBucket) if htlcsBucket == nil { return fmt.Errorf("htlcs bucket not found") } - htlcBucket := htlcsBucket.Bucket(htlcIDBytes) + htlcBucket := htlcsBucket.NestedReadWriteBucket(htlcIDBytes) if htlcBucket == nil { return fmt.Errorf("HTLC with ID %v not registered", attemptID) @@ -286,13 +285,13 @@ func (p *PaymentControl) Fail(paymentHash lntypes.Hash, updateErr error payment *MPPayment ) - err := p.db.Batch(func(tx *bbolt.Tx) error { + err := kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error { // Reset the update error, to avoid carrying over an error // from a previous execution of the batched db transaction. updateErr = nil payment = nil - bucket, err := fetchPaymentBucket(tx, paymentHash) + bucket, err := fetchPaymentBucketUpdate(tx, paymentHash) if err == ErrPaymentNotInitiated { updateErr = ErrPaymentNotInitiated return nil @@ -341,7 +340,7 @@ func (p *PaymentControl) FetchPayment(paymentHash lntypes.Hash) ( *MPPayment, error) { var payment *MPPayment - err := p.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(p.db, func(tx kvdb.ReadTx) error { bucket, err := fetchPaymentBucket(tx, paymentHash) if err != nil { return err @@ -360,10 +359,10 @@ func (p *PaymentControl) FetchPayment(paymentHash lntypes.Hash) ( // createPaymentBucket creates or fetches the sub-bucket assigned to this // payment hash. -func createPaymentBucket(tx *bbolt.Tx, paymentHash lntypes.Hash) ( - *bbolt.Bucket, error) { +func createPaymentBucket(tx kvdb.RwTx, paymentHash lntypes.Hash) ( + kvdb.RwBucket, error) { - payments, err := tx.CreateBucketIfNotExists(paymentsRootBucket) + payments, err := tx.CreateTopLevelBucket(paymentsRootBucket) if err != nil { return nil, err } @@ -373,15 +372,34 @@ func createPaymentBucket(tx *bbolt.Tx, paymentHash lntypes.Hash) ( // fetchPaymentBucket fetches the sub-bucket assigned to this payment hash. If // the bucket does not exist, it returns ErrPaymentNotInitiated. -func fetchPaymentBucket(tx *bbolt.Tx, paymentHash lntypes.Hash) ( - *bbolt.Bucket, error) { +func fetchPaymentBucket(tx kvdb.ReadTx, paymentHash lntypes.Hash) ( + kvdb.ReadBucket, error) { - payments := tx.Bucket(paymentsRootBucket) + payments := tx.ReadBucket(paymentsRootBucket) if payments == nil { return nil, ErrPaymentNotInitiated } - bucket := payments.Bucket(paymentHash[:]) + bucket := payments.NestedReadBucket(paymentHash[:]) + if bucket == nil { + return nil, ErrPaymentNotInitiated + } + + return bucket, nil + +} + +// fetchPaymentBucketUpdate is identical to fetchPaymentBucket, but it returns a +// bucket that can be written to. +func fetchPaymentBucketUpdate(tx kvdb.RwTx, paymentHash lntypes.Hash) ( + kvdb.RwBucket, error) { + + payments := tx.ReadWriteBucket(paymentsRootBucket) + if payments == nil { + return nil, ErrPaymentNotInitiated + } + + bucket := payments.NestedReadWriteBucket(paymentHash[:]) if bucket == nil { return nil, ErrPaymentNotInitiated } @@ -391,8 +409,8 @@ func fetchPaymentBucket(tx *bbolt.Tx, paymentHash lntypes.Hash) ( // nextPaymentSequence returns the next sequence number to store for a new // payment. -func nextPaymentSequence(tx *bbolt.Tx) ([]byte, error) { - payments, err := tx.CreateBucketIfNotExists(paymentsRootBucket) +func nextPaymentSequence(tx kvdb.RwTx) ([]byte, error) { + payments, err := tx.CreateTopLevelBucket(paymentsRootBucket) if err != nil { return nil, err } @@ -409,8 +427,8 @@ func nextPaymentSequence(tx *bbolt.Tx) ([]byte, error) { // fetchPaymentStatus fetches the payment status of the payment. If the payment // isn't found, it will default to "StatusUnknown". -func fetchPaymentStatus(bucket *bbolt.Bucket) (PaymentStatus, error) { - htlcsBucket := bucket.Bucket(paymentHtlcsBucket) +func fetchPaymentStatus(bucket kvdb.ReadBucket) (PaymentStatus, error) { + htlcsBucket := bucket.NestedReadBucket(paymentHtlcsBucket) if htlcsBucket != nil { htlcs, err := fetchHtlcAttempts(htlcsBucket) if err != nil { @@ -424,7 +442,6 @@ func fetchPaymentStatus(bucket *bbolt.Bucket) (PaymentStatus, error) { return StatusSucceeded, nil } } - } if bucket.Get(paymentFailInfoKey) != nil { @@ -441,7 +458,7 @@ func fetchPaymentStatus(bucket *bbolt.Bucket) (PaymentStatus, error) { // ensureInFlight checks whether the payment found in the given bucket has // status InFlight, and returns an error otherwise. This should be used to // ensure we only mark in-flight payments as succeeded or failed. -func ensureInFlight(bucket *bbolt.Bucket) error { +func ensureInFlight(bucket kvdb.ReadBucket) error { paymentStatus, err := fetchPaymentStatus(bucket) if err != nil { return err @@ -486,14 +503,14 @@ type InFlightPayment struct { // FetchInFlightPayments returns all payments with status InFlight. func (p *PaymentControl) FetchInFlightPayments() ([]*InFlightPayment, error) { var inFlights []*InFlightPayment - err := p.db.View(func(tx *bbolt.Tx) error { - payments := tx.Bucket(paymentsRootBucket) + err := kvdb.View(p.db, func(tx kvdb.ReadTx) error { + payments := tx.ReadBucket(paymentsRootBucket) if payments == nil { return nil } return payments.ForEach(func(k, _ []byte) error { - bucket := payments.Bucket(k) + bucket := payments.NestedReadBucket(k) if bucket == nil { return fmt.Errorf("non bucket element") } @@ -523,7 +540,9 @@ func (p *PaymentControl) FetchInFlightPayments() ([]*InFlightPayment, error) { return err } - htlcsBucket := bucket.Bucket(paymentHtlcsBucket) + htlcsBucket := bucket.NestedReadBucket( + paymentHtlcsBucket, + ) if htlcsBucket == nil { return nil } diff --git a/channeldb/payments.go b/channeldb/payments.go index 96fab0a716..a1ea379b2e 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -9,7 +9,7 @@ import ( "time" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" @@ -200,14 +200,14 @@ type PaymentCreationInfo struct { func (db *DB) FetchPayments() ([]*MPPayment, error) { var payments []*MPPayment - err := db.View(func(tx *bbolt.Tx) error { - paymentsBucket := tx.Bucket(paymentsRootBucket) + err := kvdb.View(db, func(tx kvdb.ReadTx) error { + paymentsBucket := tx.ReadBucket(paymentsRootBucket) if paymentsBucket == nil { return nil } return paymentsBucket.ForEach(func(k, v []byte) error { - bucket := paymentsBucket.Bucket(k) + bucket := paymentsBucket.NestedReadBucket(k) if bucket == nil { // We only expect sub-buckets to be found in // this top-level bucket. @@ -232,7 +232,6 @@ func (db *DB) FetchPayments() ([]*MPPayment, error) { } payments = append(payments, duplicatePayments...) - return nil }) }) @@ -248,7 +247,7 @@ func (db *DB) FetchPayments() ([]*MPPayment, error) { return payments, nil } -func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) { +func fetchPayment(bucket kvdb.ReadBucket) (*MPPayment, error) { seqBytes := bucket.Get(paymentSequenceKey) if seqBytes == nil { return nil, fmt.Errorf("sequence number not found") @@ -276,7 +275,7 @@ func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) { } var htlcs []HTLCAttempt - htlcsBucket := bucket.Bucket(paymentHtlcsBucket) + htlcsBucket := bucket.NestedReadBucket(paymentHtlcsBucket) if htlcsBucket != nil { // Get the payment attempts. This can be empty. htlcs, err = fetchHtlcAttempts(htlcsBucket) @@ -304,12 +303,12 @@ func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) { // fetchHtlcAttempts retrives all htlc attempts made for the payment found in // the given bucket. -func fetchHtlcAttempts(bucket *bbolt.Bucket) ([]HTLCAttempt, error) { +func fetchHtlcAttempts(bucket kvdb.ReadBucket) ([]HTLCAttempt, error) { htlcs := make([]HTLCAttempt, 0) err := bucket.ForEach(func(k, _ []byte) error { aid := byteOrder.Uint64(k) - htlcBucket := bucket.Bucket(k) + htlcBucket := bucket.NestedReadBucket(k) attemptInfo, err := fetchHtlcAttemptInfo( htlcBucket, @@ -347,7 +346,7 @@ func fetchHtlcAttempts(bucket *bbolt.Bucket) ([]HTLCAttempt, error) { // fetchHtlcAttemptInfo fetches the payment attempt info for this htlc from the // bucket. -func fetchHtlcAttemptInfo(bucket *bbolt.Bucket) (*HTLCAttemptInfo, error) { +func fetchHtlcAttemptInfo(bucket kvdb.ReadBucket) (*HTLCAttemptInfo, error) { b := bucket.Get(htlcAttemptInfoKey) if b == nil { return nil, errNoAttemptInfo @@ -359,7 +358,7 @@ func fetchHtlcAttemptInfo(bucket *bbolt.Bucket) (*HTLCAttemptInfo, error) { // fetchHtlcSettleInfo retrieves the settle info for the htlc. If the htlc isn't // settled, nil is returned. -func fetchHtlcSettleInfo(bucket *bbolt.Bucket) (*HTLCSettleInfo, error) { +func fetchHtlcSettleInfo(bucket kvdb.ReadBucket) (*HTLCSettleInfo, error) { b := bucket.Get(htlcSettleInfoKey) if b == nil { // Settle info is optional. @@ -372,7 +371,7 @@ func fetchHtlcSettleInfo(bucket *bbolt.Bucket) (*HTLCSettleInfo, error) { // fetchHtlcFailInfo retrieves the failure info for the htlc. If the htlc hasn't // failed, nil is returned. -func fetchHtlcFailInfo(bucket *bbolt.Bucket) (*HTLCFailInfo, error) { +func fetchHtlcFailInfo(bucket kvdb.ReadBucket) (*HTLCFailInfo, error) { b := bucket.Get(htlcFailInfoKey) if b == nil { // Fail info is optional. @@ -385,15 +384,15 @@ func fetchHtlcFailInfo(bucket *bbolt.Bucket) (*HTLCFailInfo, error) { // DeletePayments deletes all completed and failed payments from the DB. func (db *DB) DeletePayments() error { - return db.Update(func(tx *bbolt.Tx) error { - payments := tx.Bucket(paymentsRootBucket) + return kvdb.Update(db, func(tx kvdb.RwTx) error { + payments := tx.ReadWriteBucket(paymentsRootBucket) if payments == nil { return nil } var deleteBuckets [][]byte err := payments.ForEach(func(k, _ []byte) error { - bucket := payments.Bucket(k) + bucket := payments.NestedReadWriteBucket(k) if bucket == nil { // We only expect sub-buckets to be found in // this top-level bucket. @@ -420,7 +419,7 @@ func (db *DB) DeletePayments() error { } for _, k := range deleteBuckets { - if err := payments.DeleteBucket(k); err != nil { + if err := payments.DeleteNestedBucket(k); err != nil { return err } } diff --git a/channeldb/waitingproof.go b/channeldb/waitingproof.go index 74b80a5159..dbaddaaec4 100644 --- a/channeldb/waitingproof.go +++ b/channeldb/waitingproof.go @@ -8,8 +8,8 @@ import ( "bytes" - "github.com/coreos/bbolt" "github.com/go-errors/errors" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -61,12 +61,12 @@ func (s *WaitingProofStore) Add(proof *WaitingProof) error { s.mu.Lock() defer s.mu.Unlock() - err := s.db.Update(func(tx *bbolt.Tx) error { + err := kvdb.Update(s.db, func(tx kvdb.RwTx) error { var err error var b bytes.Buffer // Get or create the bucket. - bucket, err := tx.CreateBucketIfNotExists(waitingProofsBucketKey) + bucket, err := tx.CreateTopLevelBucket(waitingProofsBucketKey) if err != nil { return err } @@ -100,9 +100,9 @@ func (s *WaitingProofStore) Remove(key WaitingProofKey) error { return ErrWaitingProofNotFound } - err := s.db.Update(func(tx *bbolt.Tx) error { + err := kvdb.Update(s.db, func(tx kvdb.RwTx) error { // Get or create the top bucket. - bucket := tx.Bucket(waitingProofsBucketKey) + bucket := tx.ReadWriteBucket(waitingProofsBucketKey) if bucket == nil { return ErrWaitingProofNotFound } @@ -123,8 +123,8 @@ func (s *WaitingProofStore) Remove(key WaitingProofKey) error { // ForAll iterates thought all waiting proofs and passing the waiting proof // in the given callback. func (s *WaitingProofStore) ForAll(cb func(*WaitingProof) error) error { - return s.db.View(func(tx *bbolt.Tx) error { - bucket := tx.Bucket(waitingProofsBucketKey) + return kvdb.View(s.db, func(tx kvdb.ReadTx) error { + bucket := tx.ReadBucket(waitingProofsBucketKey) if bucket == nil { return ErrWaitingProofNotFound } @@ -158,8 +158,8 @@ func (s *WaitingProofStore) Get(key WaitingProofKey) (*WaitingProof, error) { return nil, ErrWaitingProofNotFound } - err := s.db.View(func(tx *bbolt.Tx) error { - bucket := tx.Bucket(waitingProofsBucketKey) + err := kvdb.View(s.db, func(tx kvdb.ReadTx) error { + bucket := tx.ReadBucket(waitingProofsBucketKey) if bucket == nil { return ErrWaitingProofNotFound } diff --git a/channeldb/witness_cache.go b/channeldb/witness_cache.go index 033662597b..7f52ada52a 100644 --- a/channeldb/witness_cache.go +++ b/channeldb/witness_cache.go @@ -3,7 +3,7 @@ package channeldb import ( "fmt" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" ) @@ -106,8 +106,8 @@ func (w *WitnessCache) addWitnessEntries(wType WitnessType, return nil } - return w.db.Batch(func(tx *bbolt.Tx) error { - witnessBucket, err := tx.CreateBucketIfNotExists(witnessBucketKey) + return kvdb.Batch(w.db.Backend, func(tx kvdb.RwTx) error { + witnessBucket, err := tx.CreateTopLevelBucket(witnessBucketKey) if err != nil { return err } @@ -150,8 +150,8 @@ func (w *WitnessCache) LookupSha256Witness(hash lntypes.Hash) (lntypes.Preimage, // will be returned. func (w *WitnessCache) lookupWitness(wType WitnessType, witnessKey []byte) ([]byte, error) { var witness []byte - err := w.db.View(func(tx *bbolt.Tx) error { - witnessBucket := tx.Bucket(witnessBucketKey) + err := kvdb.View(w.db, func(tx kvdb.ReadTx) error { + witnessBucket := tx.ReadBucket(witnessBucketKey) if witnessBucket == nil { return ErrNoWitnesses } @@ -160,7 +160,7 @@ func (w *WitnessCache) lookupWitness(wType WitnessType, witnessKey []byte) ([]by if err != nil { return err } - witnessTypeBucket := witnessBucket.Bucket(witnessTypeBucketKey) + witnessTypeBucket := witnessBucket.NestedReadBucket(witnessTypeBucketKey) if witnessTypeBucket == nil { return ErrNoWitnesses } @@ -189,8 +189,8 @@ func (w *WitnessCache) DeleteSha256Witness(hash lntypes.Hash) error { // deleteWitness attempts to delete a particular witness from the database. func (w *WitnessCache) deleteWitness(wType WitnessType, witnessKey []byte) error { - return w.db.Batch(func(tx *bbolt.Tx) error { - witnessBucket, err := tx.CreateBucketIfNotExists(witnessBucketKey) + return kvdb.Batch(w.db.Backend, func(tx kvdb.RwTx) error { + witnessBucket, err := tx.CreateTopLevelBucket(witnessBucketKey) if err != nil { return err } @@ -213,8 +213,8 @@ func (w *WitnessCache) deleteWitness(wType WitnessType, witnessKey []byte) error // DeleteWitnessClass attempts to delete an *entire* class of witnesses. After // this function return with a non-nil error, func (w *WitnessCache) DeleteWitnessClass(wType WitnessType) error { - return w.db.Batch(func(tx *bbolt.Tx) error { - witnessBucket, err := tx.CreateBucketIfNotExists(witnessBucketKey) + return kvdb.Batch(w.db.Backend, func(tx kvdb.RwTx) error { + witnessBucket, err := tx.CreateTopLevelBucket(witnessBucketKey) if err != nil { return err } @@ -224,6 +224,6 @@ func (w *WitnessCache) DeleteWitnessClass(wType WitnessType) error { return err } - return witnessBucket.DeleteBucket(witnessTypeBucketKey) + return witnessBucket.DeleteNestedBucket(witnessTypeBucketKey) }) } diff --git a/go.mod b/go.mod index 5b2d56eb31..55e4fea1e1 100644 --- a/go.mod +++ b/go.mod @@ -45,8 +45,9 @@ require ( github.com/rogpeppe/fastuuid v1.2.0 // indirect github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 github.com/urfave/cli v1.18.0 - golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 - golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 + go.etcd.io/bbolt v1.3.3 + golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 + golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 google.golang.org/grpc v1.19.0 From 320101d05461f27245774be74ec417bad8d049e5 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:44:12 -0800 Subject: [PATCH 247/562] contractcourt: convert to use new kvdb abstraction --- contractcourt/briefcase.go | 73 ++++++++++++------------ contractcourt/briefcase_test.go | 6 +- contractcourt/chain_arbitrator.go | 4 +- contractcourt/channel_arbitrator_test.go | 4 +- 4 files changed, 44 insertions(+), 43 deletions(-) diff --git a/contractcourt/briefcase.go b/contractcourt/briefcase.go index 1114f6db50..03a878b7b7 100644 --- a/contractcourt/briefcase.go +++ b/contractcourt/briefcase.go @@ -8,8 +8,8 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" ) @@ -309,7 +309,7 @@ var ( // boltArbitratorLog is an implementation of the ArbitratorLog interface backed // by a bolt DB instance. type boltArbitratorLog struct { - db *bbolt.DB + db kvdb.Backend cfg ChannelArbitratorConfig @@ -318,7 +318,7 @@ type boltArbitratorLog struct { // newBoltArbitratorLog returns a new instance of the boltArbitratorLog given // an arbitrator config, and the items needed to create its log scope. -func newBoltArbitratorLog(db *bbolt.DB, cfg ChannelArbitratorConfig, +func newBoltArbitratorLog(db kvdb.Backend, cfg ChannelArbitratorConfig, chainHash chainhash.Hash, chanPoint wire.OutPoint) (*boltArbitratorLog, error) { scope, err := newLogScope(chainHash, chanPoint) @@ -337,13 +337,13 @@ func newBoltArbitratorLog(db *bbolt.DB, cfg ChannelArbitratorConfig, // interface. var _ ArbitratorLog = (*boltArbitratorLog)(nil) -func fetchContractReadBucket(tx *bbolt.Tx, scopeKey []byte) (*bbolt.Bucket, error) { - scopeBucket := tx.Bucket(scopeKey) +func fetchContractReadBucket(tx kvdb.ReadTx, scopeKey []byte) (kvdb.ReadBucket, error) { + scopeBucket := tx.ReadBucket(scopeKey) if scopeBucket == nil { return nil, errScopeBucketNoExist } - contractBucket := scopeBucket.Bucket(contractsBucketKey) + contractBucket := scopeBucket.NestedReadBucket(contractsBucketKey) if contractBucket == nil { return nil, errNoContracts } @@ -351,8 +351,8 @@ func fetchContractReadBucket(tx *bbolt.Tx, scopeKey []byte) (*bbolt.Bucket, erro return contractBucket, nil } -func fetchContractWriteBucket(tx *bbolt.Tx, scopeKey []byte) (*bbolt.Bucket, error) { - scopeBucket, err := tx.CreateBucketIfNotExists(scopeKey) +func fetchContractWriteBucket(tx kvdb.RwTx, scopeKey []byte) (kvdb.RwBucket, error) { + scopeBucket, err := tx.CreateTopLevelBucket(scopeKey) if err != nil { return nil, err } @@ -369,7 +369,7 @@ func fetchContractWriteBucket(tx *bbolt.Tx, scopeKey []byte) (*bbolt.Bucket, err // writeResolver is a helper method that writes a contract resolver and stores // it it within the passed contractBucket using its unique resolutionsKey key. -func (b *boltArbitratorLog) writeResolver(contractBucket *bbolt.Bucket, +func (b *boltArbitratorLog) writeResolver(contractBucket kvdb.RwBucket, res ContractResolver) error { // Only persist resolvers that are stateful. Stateless resolvers don't @@ -415,8 +415,8 @@ func (b *boltArbitratorLog) writeResolver(contractBucket *bbolt.Bucket, // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) CurrentState() (ArbitratorState, error) { var s ArbitratorState - err := b.db.View(func(tx *bbolt.Tx) error { - scopeBucket := tx.Bucket(b.scopeKey[:]) + err := kvdb.View(b.db, func(tx kvdb.ReadTx) error { + scopeBucket := tx.ReadBucket(b.scopeKey[:]) if scopeBucket == nil { return errScopeBucketNoExist } @@ -440,8 +440,9 @@ func (b *boltArbitratorLog) CurrentState() (ArbitratorState, error) { // // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) CommitState(s ArbitratorState) error { - return b.db.Batch(func(tx *bbolt.Tx) error { - scopeBucket, err := tx.CreateBucketIfNotExists(b.scopeKey[:]) + fmt.Printf("yeee: %T\n", b.db) + return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { + scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:]) if err != nil { return err } @@ -460,7 +461,7 @@ func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, erro Checkpoint: b.checkpointContract, } var contracts []ContractResolver - err := b.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(b.db, func(tx kvdb.ReadTx) error { contractBucket, err := fetchContractReadBucket(tx, b.scopeKey[:]) if err != nil { return err @@ -533,7 +534,7 @@ func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, erro // // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) InsertUnresolvedContracts(resolvers ...ContractResolver) error { - return b.db.Batch(func(tx *bbolt.Tx) error { + return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:]) if err != nil { return err @@ -556,7 +557,7 @@ func (b *boltArbitratorLog) InsertUnresolvedContracts(resolvers ...ContractResol // // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) SwapContract(oldContract, newContract ContractResolver) error { - return b.db.Batch(func(tx *bbolt.Tx) error { + return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:]) if err != nil { return err @@ -576,7 +577,7 @@ func (b *boltArbitratorLog) SwapContract(oldContract, newContract ContractResolv // // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) ResolveContract(res ContractResolver) error { - return b.db.Batch(func(tx *bbolt.Tx) error { + return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:]) if err != nil { return err @@ -594,8 +595,8 @@ func (b *boltArbitratorLog) ResolveContract(res ContractResolver) error { // // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) LogContractResolutions(c *ContractResolutions) error { - return b.db.Batch(func(tx *bbolt.Tx) error { - scopeBucket, err := tx.CreateBucketIfNotExists(b.scopeKey[:]) + return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { + scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:]) if err != nil { return err } @@ -674,8 +675,8 @@ func (b *boltArbitratorLog) LogContractResolutions(c *ContractResolutions) error // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) FetchContractResolutions() (*ContractResolutions, error) { c := &ContractResolutions{} - err := b.db.View(func(tx *bbolt.Tx) error { - scopeBucket := tx.Bucket(b.scopeKey[:]) + err := kvdb.View(b.db, func(tx kvdb.ReadTx) error { + scopeBucket := tx.ReadBucket(b.scopeKey[:]) if scopeBucket == nil { return errScopeBucketNoExist } @@ -773,13 +774,13 @@ func (b *boltArbitratorLog) FetchContractResolutions() (*ContractResolutions, er func (b *boltArbitratorLog) FetchChainActions() (ChainActionMap, error) { actionsMap := make(ChainActionMap) - err := b.db.View(func(tx *bbolt.Tx) error { - scopeBucket := tx.Bucket(b.scopeKey[:]) + err := kvdb.View(b.db, func(tx kvdb.ReadTx) error { + scopeBucket := tx.ReadBucket(b.scopeKey[:]) if scopeBucket == nil { return errScopeBucketNoExist } - actionsBucket := scopeBucket.Bucket(actionsBucketKey) + actionsBucket := scopeBucket.NestedReadBucket(actionsBucketKey) if actionsBucket == nil { return errNoActions } @@ -815,8 +816,8 @@ func (b *boltArbitratorLog) FetchChainActions() (ChainActionMap, error) { // // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) InsertConfirmedCommitSet(c *CommitSet) error { - return b.db.Update(func(tx *bbolt.Tx) error { - scopeBucket, err := tx.CreateBucketIfNotExists(b.scopeKey[:]) + return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { + scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:]) if err != nil { return err } @@ -836,8 +837,8 @@ func (b *boltArbitratorLog) InsertConfirmedCommitSet(c *CommitSet) error { // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) FetchConfirmedCommitSet() (*CommitSet, error) { var c *CommitSet - err := b.db.View(func(tx *bbolt.Tx) error { - scopeBucket := tx.Bucket(b.scopeKey[:]) + err := kvdb.View(b.db, func(tx kvdb.ReadTx) error { + scopeBucket := tx.ReadBucket(b.scopeKey[:]) if scopeBucket == nil { return errScopeBucketNoExist } @@ -868,8 +869,8 @@ func (b *boltArbitratorLog) FetchConfirmedCommitSet() (*CommitSet, error) { // // NOTE: Part of the ContractResolver interface. func (b *boltArbitratorLog) WipeHistory() error { - return b.db.Update(func(tx *bbolt.Tx) error { - scopeBucket, err := tx.CreateBucketIfNotExists(b.scopeKey[:]) + return kvdb.Update(b.db, func(tx kvdb.RwTx) error { + scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:]) if err != nil { return err } @@ -882,8 +883,8 @@ func (b *boltArbitratorLog) WipeHistory() error { // Next, we'll delete any lingering contract state within the // contracts bucket by removing the bucket itself. - err = scopeBucket.DeleteBucket(contractsBucketKey) - if err != nil && err != bbolt.ErrBucketNotFound { + err = scopeBucket.DeleteNestedBucket(contractsBucketKey) + if err != nil && err != kvdb.ErrBucketNotFound { return err } @@ -895,13 +896,13 @@ func (b *boltArbitratorLog) WipeHistory() error { // We'll delete any chain actions that are still stored by // removing the enclosing bucket. - err = scopeBucket.DeleteBucket(actionsBucketKey) - if err != nil && err != bbolt.ErrBucketNotFound { + err = scopeBucket.DeleteNestedBucket(actionsBucketKey) + if err != nil && err != kvdb.ErrBucketNotFound { return err } // Finally, we'll delete the enclosing bucket itself. - return tx.DeleteBucket(b.scopeKey[:]) + return tx.DeleteTopLevelBucket(b.scopeKey[:]) }) } @@ -909,7 +910,7 @@ func (b *boltArbitratorLog) WipeHistory() error { // ContractResolver instances to checkpoint their state once they reach // milestones during contract resolution. func (b *boltArbitratorLog) checkpointContract(c ContractResolver) error { - return b.db.Batch(func(tx *bbolt.Tx) error { + return kvdb.Update(b.db, func(tx kvdb.RwTx) error { contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:]) if err != nil { return err diff --git a/contractcourt/briefcase_test.go b/contractcourt/briefcase_test.go index 3408b2c65f..165016d322 100644 --- a/contractcourt/briefcase_test.go +++ b/contractcourt/briefcase_test.go @@ -14,9 +14,9 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" ) @@ -104,7 +104,7 @@ var ( } ) -func makeTestDB() (*bbolt.DB, func(), error) { +func makeTestDB() (kvdb.Backend, func(), error) { // First, create a temporary directory to be used for the duration of // this test. tempDirName, err := ioutil.TempDir("", "arblog") @@ -112,7 +112,7 @@ func makeTestDB() (*bbolt.DB, func(), error) { return nil, nil, err } - db, err := bbolt.Open(tempDirName+"/test.db", 0600, nil) + db, err := kvdb.Create(kvdb.BoltBackendName, tempDirName+"/test.db", true) if err != nil { return nil, nil, err } diff --git a/contractcourt/chain_arbitrator.go b/contractcourt/chain_arbitrator.go index a9dde5421e..9aa691a9b0 100644 --- a/contractcourt/chain_arbitrator.go +++ b/contractcourt/chain_arbitrator.go @@ -356,7 +356,7 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel, // TODO(roasbeef); abstraction leak... // * rework: adaptor method to set log scope w/ factory func chanLog, err := newBoltArbitratorLog( - c.chanSource.DB, arbCfg, c.cfg.ChainHash, chanPoint, + c.chanSource.Backend, arbCfg, c.cfg.ChainHash, chanPoint, ) if err != nil { blockEpoch.Cancel() @@ -554,7 +554,7 @@ func (c *ChainArbitrator) Start() error { CloseType: closeChanInfo.CloseType, } chanLog, err := newBoltArbitratorLog( - c.chanSource.DB, arbCfg, c.cfg.ChainHash, chanPoint, + c.chanSource.Backend, arbCfg, c.cfg.ChainHash, chanPoint, ) if err != nil { blockEpoch.Cancel() diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index bbe1c51f52..3dedb4200f 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -13,9 +13,9 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" @@ -394,7 +394,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog, return nil, err } dbPath := filepath.Join(dbDir, "testdb") - db, err := bbolt.Open(dbPath, 0600, nil) + db, err := kvdb.Create(kvdb.BoltBackendName, dbPath, true) if err != nil { return nil, err } From 4e68914e9d86d514740db51c43eab9b4f3e7e80a Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:44:27 -0800 Subject: [PATCH 248/562] htlcswitch: convert to use new kvdb abstraction --- htlcswitch/circuit_map.go | 32 +++++++++++++++---------------- htlcswitch/decayedlog.go | 37 +++++++++++++++++++----------------- htlcswitch/link_test.go | 14 +++++++------- htlcswitch/payment_result.go | 14 +++++++------- htlcswitch/sequencer.go | 10 +++++----- htlcswitch/switch.go | 6 +++--- htlcswitch/test_utils.go | 6 +++--- 7 files changed, 61 insertions(+), 58 deletions(-) diff --git a/htlcswitch/circuit_map.go b/htlcswitch/circuit_map.go index fa91bfcd79..7711f2474c 100644 --- a/htlcswitch/circuit_map.go +++ b/htlcswitch/circuit_map.go @@ -5,10 +5,10 @@ import ( "fmt" "sync" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lnwire" ) @@ -213,13 +213,13 @@ func NewCircuitMap(cfg *CircuitMapConfig) (CircuitMap, error) { // initBuckets ensures that the primary buckets used by the circuit are // initialized so that we can assume their existence after startup. func (cm *circuitMap) initBuckets() error { - return cm.cfg.DB.Update(func(tx *bbolt.Tx) error { - _, err := tx.CreateBucketIfNotExists(circuitKeystoneKey) + return kvdb.Update(cm.cfg.DB, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket(circuitKeystoneKey) if err != nil { return err } - _, err = tx.CreateBucketIfNotExists(circuitAddKey) + _, err = tx.CreateTopLevelBucket(circuitAddKey) return err }) } @@ -238,10 +238,10 @@ func (cm *circuitMap) restoreMemState() error { pending = make(map[CircuitKey]*PaymentCircuit) ) - if err := cm.cfg.DB.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(cm.cfg.DB, func(tx kvdb.RwTx) error { // Restore any of the circuits persisted in the circuit bucket // back into memory. - circuitBkt := tx.Bucket(circuitAddKey) + circuitBkt := tx.ReadWriteBucket(circuitAddKey) if circuitBkt == nil { return ErrCorruptedCircuitMap } @@ -262,7 +262,7 @@ func (cm *circuitMap) restoreMemState() error { // Furthermore, load the keystone bucket and resurrect the // keystones used in any open circuits. - keystoneBkt := tx.Bucket(circuitKeystoneKey) + keystoneBkt := tx.ReadWriteBucket(circuitKeystoneKey) if keystoneBkt == nil { return ErrCorruptedCircuitMap } @@ -463,8 +463,8 @@ func (cm *circuitMap) TrimOpenCircuits(chanID lnwire.ShortChannelID, return nil } - return cm.cfg.DB.Update(func(tx *bbolt.Tx) error { - keystoneBkt := tx.Bucket(circuitKeystoneKey) + return kvdb.Update(cm.cfg.DB, func(tx kvdb.RwTx) error { + keystoneBkt := tx.ReadWriteBucket(circuitKeystoneKey) if keystoneBkt == nil { return ErrCorruptedCircuitMap } @@ -616,8 +616,8 @@ func (cm *circuitMap) CommitCircuits(circuits ...*PaymentCircuit) ( // Write the entire batch of circuits to the persistent circuit bucket // using bolt's Batch write. This method must be called from multiple, // distinct goroutines to have any impact on performance. - err := cm.cfg.DB.Batch(func(tx *bbolt.Tx) error { - circuitBkt := tx.Bucket(circuitAddKey) + err := kvdb.Batch(cm.cfg.DB.Backend, func(tx kvdb.RwTx) error { + circuitBkt := tx.ReadWriteBucket(circuitAddKey) if circuitBkt == nil { return ErrCorruptedCircuitMap } @@ -706,10 +706,10 @@ func (cm *circuitMap) OpenCircuits(keystones ...Keystone) error { } cm.mtx.RUnlock() - err := cm.cfg.DB.Update(func(tx *bbolt.Tx) error { + err := kvdb.Update(cm.cfg.DB, func(tx kvdb.RwTx) error { // Now, load the circuit bucket to which we will write the // already serialized circuit. - keystoneBkt := tx.Bucket(circuitKeystoneKey) + keystoneBkt := tx.ReadWriteBucket(circuitKeystoneKey) if keystoneBkt == nil { return ErrCorruptedCircuitMap } @@ -847,13 +847,13 @@ func (cm *circuitMap) DeleteCircuits(inKeys ...CircuitKey) error { } cm.mtx.Unlock() - err := cm.cfg.DB.Batch(func(tx *bbolt.Tx) error { + err := kvdb.Batch(cm.cfg.DB.Backend, func(tx kvdb.RwTx) error { for _, circuit := range removedCircuits { // If this htlc made it to an outgoing link, load the // keystone bucket from which we will remove the // outgoing circuit key. if circuit.HasKeystone() { - keystoneBkt := tx.Bucket(circuitKeystoneKey) + keystoneBkt := tx.ReadWriteBucket(circuitKeystoneKey) if keystoneBkt == nil { return ErrCorruptedCircuitMap } @@ -868,7 +868,7 @@ func (cm *circuitMap) DeleteCircuits(inKeys ...CircuitKey) error { // Remove the circuit itself based on the incoming // circuit key. - circuitBkt := tx.Bucket(circuitAddKey) + circuitBkt := tx.ReadWriteBucket(circuitAddKey) if circuitBkt == nil { return ErrCorruptedCircuitMap } diff --git a/htlcswitch/decayedlog.go b/htlcswitch/decayedlog.go index 6b3c62b56e..3a60e11228 100644 --- a/htlcswitch/decayedlog.go +++ b/htlcswitch/decayedlog.go @@ -8,9 +8,9 @@ import ( "sync" "sync/atomic" - "github.com/coreos/bbolt" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/chainntnfs" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) const ( @@ -56,7 +56,7 @@ type DecayedLog struct { dbPath string - db *bbolt.DB + db kvdb.Backend notifier chainntnfs.ChainNotifier @@ -92,7 +92,10 @@ func (d *DecayedLog) Start() error { // Open the boltdb for use. var err error - if d.db, err = bbolt.Open(d.dbPath, dbPermissions, nil); err != nil { + d.db, err = kvdb.Create( + kvdb.BoltBackendName, d.dbPath, true, + ) + if err != nil { return fmt.Errorf("Could not open boltdb: %v", err) } @@ -119,13 +122,13 @@ func (d *DecayedLog) Start() error { // initBuckets initializes the primary buckets used by the decayed log, namely // the shared hash bucket, and batch replay func (d *DecayedLog) initBuckets() error { - return d.db.Update(func(tx *bbolt.Tx) error { - _, err := tx.CreateBucketIfNotExists(sharedHashBucket) + return kvdb.Update(d.db, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket(sharedHashBucket) if err != nil { return ErrDecayedLogInit } - _, err = tx.CreateBucketIfNotExists(batchReplayBucket) + _, err = tx.CreateTopLevelBucket(batchReplayBucket) if err != nil { return ErrDecayedLogInit } @@ -196,11 +199,11 @@ func (d *DecayedLog) garbageCollector(epochClient *chainntnfs.BlockEpochEvent) { func (d *DecayedLog) gcExpiredHashes(height uint32) (uint32, error) { var numExpiredHashes uint32 - err := d.db.Batch(func(tx *bbolt.Tx) error { + err := kvdb.Batch(d.db, func(tx kvdb.RwTx) error { numExpiredHashes = 0 // Grab the shared hash bucket - sharedHashes := tx.Bucket(sharedHashBucket) + sharedHashes := tx.ReadWriteBucket(sharedHashBucket) if sharedHashes == nil { return fmt.Errorf("sharedHashBucket " + "is nil") @@ -246,8 +249,8 @@ func (d *DecayedLog) gcExpiredHashes(height uint32) (uint32, error) { // Delete removes a key-pair from the // sharedHashBucket. func (d *DecayedLog) Delete(hash *sphinx.HashPrefix) error { - return d.db.Batch(func(tx *bbolt.Tx) error { - sharedHashes := tx.Bucket(sharedHashBucket) + return kvdb.Batch(d.db, func(tx kvdb.RwTx) error { + sharedHashes := tx.ReadWriteBucket(sharedHashBucket) if sharedHashes == nil { return ErrDecayedLogCorrupted } @@ -261,10 +264,10 @@ func (d *DecayedLog) Delete(hash *sphinx.HashPrefix) error { func (d *DecayedLog) Get(hash *sphinx.HashPrefix) (uint32, error) { var value uint32 - err := d.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(d.db, func(tx kvdb.ReadTx) error { // Grab the shared hash bucket which stores the mapping from // truncated sha-256 hashes of shared secrets to CLTV's. - sharedHashes := tx.Bucket(sharedHashBucket) + sharedHashes := tx.ReadBucket(sharedHashBucket) if sharedHashes == nil { return fmt.Errorf("sharedHashes is nil, could " + "not retrieve CLTV value") @@ -294,8 +297,8 @@ func (d *DecayedLog) Put(hash *sphinx.HashPrefix, cltv uint32) error { var scratch [4]byte binary.BigEndian.PutUint32(scratch[:], cltv) - return d.db.Batch(func(tx *bbolt.Tx) error { - sharedHashes := tx.Bucket(sharedHashBucket) + return kvdb.Batch(d.db, func(tx kvdb.RwTx) error { + sharedHashes := tx.ReadWriteBucket(sharedHashBucket) if sharedHashes == nil { return ErrDecayedLogCorrupted } @@ -327,8 +330,8 @@ func (d *DecayedLog) PutBatch(b *sphinx.Batch) (*sphinx.ReplaySet, error) { // to generate the complete replay set. If this batch was previously // processed, the replay set will be deserialized from disk. var replays *sphinx.ReplaySet - if err := d.db.Batch(func(tx *bbolt.Tx) error { - sharedHashes := tx.Bucket(sharedHashBucket) + if err := kvdb.Batch(d.db, func(tx kvdb.RwTx) error { + sharedHashes := tx.ReadWriteBucket(sharedHashBucket) if sharedHashes == nil { return ErrDecayedLogCorrupted } @@ -336,7 +339,7 @@ func (d *DecayedLog) PutBatch(b *sphinx.Batch) (*sphinx.ReplaySet, error) { // Load the batch replay bucket, which will be used to either // retrieve the result of previously processing this batch, or // to write the result of this operation. - batchReplayBkt := tx.Bucket(batchReplayBucket) + batchReplayBkt := tx.ReadWriteBucket(batchReplayBucket) if batchReplayBkt == nil { return ErrDecayedLogCorrupted } diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 0b162cd032..0906141ac1 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -19,12 +19,12 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch/hodl" "github.com/lightningnetwork/lnd/htlcswitch/hop" @@ -5170,32 +5170,32 @@ type mockPackager struct { failLoadFwdPkgs bool } -func (*mockPackager) AddFwdPkg(tx *bbolt.Tx, fwdPkg *channeldb.FwdPkg) error { +func (*mockPackager) AddFwdPkg(tx kvdb.RwTx, fwdPkg *channeldb.FwdPkg) error { return nil } -func (*mockPackager) SetFwdFilter(tx *bbolt.Tx, height uint64, +func (*mockPackager) SetFwdFilter(tx kvdb.RwTx, height uint64, fwdFilter *channeldb.PkgFilter) error { return nil } -func (*mockPackager) AckAddHtlcs(tx *bbolt.Tx, +func (*mockPackager) AckAddHtlcs(tx kvdb.RwTx, addRefs ...channeldb.AddRef) error { return nil } -func (m *mockPackager) LoadFwdPkgs(tx *bbolt.Tx) ([]*channeldb.FwdPkg, error) { +func (m *mockPackager) LoadFwdPkgs(tx kvdb.ReadTx) ([]*channeldb.FwdPkg, error) { if m.failLoadFwdPkgs { return nil, fmt.Errorf("failing LoadFwdPkgs") } return nil, nil } -func (*mockPackager) RemovePkg(tx *bbolt.Tx, height uint64) error { +func (*mockPackager) RemovePkg(tx kvdb.RwTx, height uint64) error { return nil } -func (*mockPackager) AckSettleFails(tx *bbolt.Tx, +func (*mockPackager) AckSettleFails(tx kvdb.RwTx, settleFailRefs ...channeldb.SettleFailRef) error { return nil } diff --git a/htlcswitch/payment_result.go b/htlcswitch/payment_result.go index faf15d84d6..b23dbe0a7e 100644 --- a/htlcswitch/payment_result.go +++ b/htlcswitch/payment_result.go @@ -7,8 +7,8 @@ import ( "io" "sync" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/multimutex" ) @@ -137,8 +137,8 @@ func (store *networkResultStore) storeResult(paymentID uint64, var paymentIDBytes [8]byte binary.BigEndian.PutUint64(paymentIDBytes[:], paymentID) - err := store.db.Batch(func(tx *bbolt.Tx) error { - networkResults, err := tx.CreateBucketIfNotExists( + err := kvdb.Batch(store.db.Backend, func(tx kvdb.RwTx) error { + networkResults, err := tx.CreateTopLevelBucket( networkResultStoreBucketKey, ) if err != nil { @@ -180,7 +180,7 @@ func (store *networkResultStore) subscribeResult(paymentID uint64) ( resultChan = make(chan *networkResult, 1) ) - err := store.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(store.db, func(tx kvdb.ReadTx) error { var err error result, err = fetchResult(tx, paymentID) switch { @@ -226,7 +226,7 @@ func (store *networkResultStore) getResult(pid uint64) ( *networkResult, error) { var result *networkResult - err := store.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(store.db, func(tx kvdb.ReadTx) error { var err error result, err = fetchResult(tx, pid) return err @@ -238,11 +238,11 @@ func (store *networkResultStore) getResult(pid uint64) ( return result, nil } -func fetchResult(tx *bbolt.Tx, pid uint64) (*networkResult, error) { +func fetchResult(tx kvdb.ReadTx, pid uint64) (*networkResult, error) { var paymentIDBytes [8]byte binary.BigEndian.PutUint64(paymentIDBytes[:], pid) - networkResults := tx.Bucket(networkResultStoreBucketKey) + networkResults := tx.ReadBucket(networkResultStoreBucketKey) if networkResults == nil { return nil, ErrPaymentIDNotFound } diff --git a/htlcswitch/sequencer.go b/htlcswitch/sequencer.go index 3a5247db14..5b1526b6bd 100644 --- a/htlcswitch/sequencer.go +++ b/htlcswitch/sequencer.go @@ -3,9 +3,9 @@ package htlcswitch import ( "sync" - "github.com/coreos/bbolt" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) // defaultSequenceBatchSize specifies the window of sequence numbers that are @@ -87,8 +87,8 @@ func (s *persistentSequencer) NextID() (uint64, error) { // allocated will start from the last known tip on disk, which is fine // as we only require uniqueness of the allocated numbers. var nextHorizonID uint64 - if err := s.db.Update(func(tx *bbolt.Tx) error { - nextIDBkt := tx.Bucket(nextPaymentIDKey) + if err := kvdb.Update(s.db, func(tx kvdb.RwTx) error { + nextIDBkt := tx.ReadWriteBucket(nextPaymentIDKey) if nextIDBkt == nil { return ErrSequencerCorrupted } @@ -121,8 +121,8 @@ func (s *persistentSequencer) NextID() (uint64, error) { // initDB populates the bucket used to generate payment sequence numbers. func (s *persistentSequencer) initDB() error { - return s.db.Update(func(tx *bbolt.Tx) error { - _, err := tx.CreateBucketIfNotExists(nextPaymentIDKey) + return kvdb.Update(s.db, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket(nextPaymentIDKey) return err }) } diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 602dc55b0e..9d03b1b7b4 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -10,10 +10,10 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lntypes" @@ -1419,7 +1419,7 @@ func (s *Switch) closeCircuit(pkt *htlcPacket) (*PaymentCircuit, error) { // we're the originator of the payment, so the link stops attempting to // re-broadcast. func (s *Switch) ackSettleFail(settleFailRefs ...channeldb.SettleFailRef) error { - return s.cfg.DB.Batch(func(tx *bbolt.Tx) error { + return kvdb.Batch(s.cfg.DB.Backend, func(tx kvdb.RwTx) error { return s.cfg.SwitchPackager.AckSettleFails(tx, settleFailRefs...) }) } @@ -1865,7 +1865,7 @@ func (s *Switch) reforwardResponses() error { func (s *Switch) loadChannelFwdPkgs(source lnwire.ShortChannelID) ([]*channeldb.FwdPkg, error) { var fwdPkgs []*channeldb.FwdPkg - if err := s.cfg.DB.Update(func(tx *bbolt.Tx) error { + if err := kvdb.Update(s.cfg.DB, func(tx kvdb.RwTx) error { var err error fwdPkgs, err = s.cfg.SwitchPackager.LoadChannelFwdPkgs( tx, source, diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index 26b8dad576..f628f280ba 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -21,10 +21,10 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/fastsha256" - "github.com/coreos/bbolt" "github.com/go-errors/errors" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/input" @@ -420,7 +420,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte, aliceStoredChannels, err := dbAlice.FetchOpenChannels(aliceKeyPub) switch err { case nil: - case bbolt.ErrDatabaseNotOpen: + case kvdb.ErrDatabaseNotOpen: dbAlice, err = channeldb.Open(dbAlice.Path()) if err != nil { return nil, errors.Errorf("unable to reopen alice "+ @@ -464,7 +464,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte, bobStoredChannels, err := dbBob.FetchOpenChannels(bobKeyPub) switch err { case nil: - case bbolt.ErrDatabaseNotOpen: + case kvdb.ErrDatabaseNotOpen: dbBob, err = channeldb.Open(dbBob.Path()) if err != nil { return nil, errors.Errorf("unable to reopen bob "+ From 28bbaa2a94a79b3e3966ce1d7461183c3253d996 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:44:43 -0800 Subject: [PATCH 249/562] routing: convert to use new kvdb abstraction --- routing/graph.go | 8 +++---- routing/integrated_routing_context_test.go | 4 ++-- routing/missioncontrol.go | 4 ++-- routing/missioncontrol_store.go | 28 +++++++++++----------- routing/missioncontrol_store_test.go | 4 ++-- routing/missioncontrol_test.go | 6 ++--- routing/router.go | 8 +++---- routing/router_test.go | 2 +- 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/routing/graph.go b/routing/graph.go index 14eca17861..c1a68bae99 100644 --- a/routing/graph.go +++ b/routing/graph.go @@ -1,8 +1,8 @@ package routing import ( - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -26,7 +26,7 @@ type routingGraph interface { // database. type dbRoutingTx struct { graph *channeldb.ChannelGraph - tx *bbolt.Tx + tx kvdb.ReadTx source route.Vertex } @@ -38,7 +38,7 @@ func newDbRoutingTx(graph *channeldb.ChannelGraph) (*dbRoutingTx, error) { return nil, err } - tx, err := graph.Database().Begin(false) + tx, err := graph.Database().BeginReadTx() if err != nil { return nil, err } @@ -62,7 +62,7 @@ func (g *dbRoutingTx) forEachNodeChannel(nodePub route.Vertex, cb func(*channeldb.ChannelEdgeInfo, *channeldb.ChannelEdgePolicy, *channeldb.ChannelEdgePolicy) error) error { - txCb := func(_ *bbolt.Tx, info *channeldb.ChannelEdgeInfo, + txCb := func(_ kvdb.ReadTx, info *channeldb.ChannelEdgeInfo, p1, p2 *channeldb.ChannelEdgePolicy) error { return cb(info, p1, p2) diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index eb59473e6a..db5c6fe9f3 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -82,7 +82,7 @@ func (c *integratedRoutingContext) testPayment(expectedNofAttempts int) { dbPath := file.Name() defer os.Remove(dbPath) - db, err := bbolt.Open(dbPath, 0600, nil) + db, err := kvdb.Open(kvdb.BoltBackendName, dbPath, true) if err != nil { c.t.Fatal(err) } diff --git a/routing/missioncontrol.go b/routing/missioncontrol.go index f52c6fce9a..a590f20ae3 100644 --- a/routing/missioncontrol.go +++ b/routing/missioncontrol.go @@ -4,8 +4,8 @@ import ( "sync" "time" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -173,7 +173,7 @@ type paymentResult struct { } // NewMissionControl returns a new instance of missionControl. -func NewMissionControl(db *bbolt.DB, cfg *MissionControlConfig) ( +func NewMissionControl(db kvdb.Backend, cfg *MissionControlConfig) ( *MissionControl, error) { log.Debugf("Instantiating mission control with config: "+ diff --git a/routing/missioncontrol_store.go b/routing/missioncontrol_store.go index 329d819f75..9cd99d9545 100644 --- a/routing/missioncontrol_store.go +++ b/routing/missioncontrol_store.go @@ -7,8 +7,8 @@ import ( "time" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -35,20 +35,20 @@ const ( // Also changes to mission control parameters can be applied to historical data. // Finally, it enables importing raw data from an external source. type missionControlStore struct { - db *bbolt.DB + db kvdb.Backend maxRecords int numRecords int } -func newMissionControlStore(db *bbolt.DB, maxRecords int) (*missionControlStore, error) { +func newMissionControlStore(db kvdb.Backend, maxRecords int) (*missionControlStore, error) { store := &missionControlStore{ db: db, maxRecords: maxRecords, } // Create buckets if not yet existing. - err := db.Update(func(tx *bbolt.Tx) error { - resultsBucket, err := tx.CreateBucketIfNotExists(resultsKey) + err := kvdb.Update(db, func(tx kvdb.RwTx) error { + resultsBucket, err := tx.CreateTopLevelBucket(resultsKey) if err != nil { return fmt.Errorf("cannot create results bucket: %v", err) @@ -58,7 +58,7 @@ func newMissionControlStore(db *bbolt.DB, maxRecords int) (*missionControlStore, // memory to avoid calling Stats().KeyN. The reliability of // Stats() is doubtful and seemed to have caused crashes in the // past (see #1874). - c := resultsBucket.Cursor() + c := resultsBucket.ReadCursor() for k, _ := c.First(); k != nil; k, _ = c.Next() { store.numRecords++ } @@ -74,12 +74,12 @@ func newMissionControlStore(db *bbolt.DB, maxRecords int) (*missionControlStore, // clear removes all results from the db. func (b *missionControlStore) clear() error { - return b.db.Update(func(tx *bbolt.Tx) error { - if err := tx.DeleteBucket(resultsKey); err != nil { + return kvdb.Update(b.db, func(tx kvdb.RwTx) error { + if err := tx.DeleteTopLevelBucket(resultsKey); err != nil { return err } - _, err := tx.CreateBucket(resultsKey) + _, err := tx.CreateTopLevelBucket(resultsKey) return err }) } @@ -88,8 +88,8 @@ func (b *missionControlStore) clear() error { func (b *missionControlStore) fetchAll() ([]*paymentResult, error) { var results []*paymentResult - err := b.db.View(func(tx *bbolt.Tx) error { - resultBucket := tx.Bucket(resultsKey) + err := kvdb.View(b.db, func(tx kvdb.ReadTx) error { + resultBucket := tx.ReadBucket(resultsKey) results = make([]*paymentResult, 0) return resultBucket.ForEach(func(k, v []byte) error { @@ -218,13 +218,13 @@ func deserializeResult(k, v []byte) (*paymentResult, error) { // AddResult adds a new result to the db. func (b *missionControlStore) AddResult(rp *paymentResult) error { - return b.db.Update(func(tx *bbolt.Tx) error { - bucket := tx.Bucket(resultsKey) + return kvdb.Update(b.db, func(tx kvdb.RwTx) error { + bucket := tx.ReadWriteBucket(resultsKey) // Prune oldest entries. if b.maxRecords > 0 { for b.numRecords >= b.maxRecords { - cursor := bucket.Cursor() + cursor := bucket.ReadWriteCursor() cursor.First() if err := cursor.Delete(); err != nil { return err diff --git a/routing/missioncontrol_store_test.go b/routing/missioncontrol_store_test.go index e44c591971..497affd52b 100644 --- a/routing/missioncontrol_store_test.go +++ b/routing/missioncontrol_store_test.go @@ -8,9 +8,9 @@ import ( "time" "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/routing/route" ) @@ -31,7 +31,7 @@ func TestMissionControlStore(t *testing.T) { dbPath := file.Name() - db, err := bbolt.Open(dbPath, 0600, nil) + db, err := kvdb.Create(kvdb.BoltBackendName, dbPath, true) if err != nil { t.Fatal(err) } diff --git a/routing/missioncontrol_test.go b/routing/missioncontrol_test.go index 98cf95302f..3a9c93a75b 100644 --- a/routing/missioncontrol_test.go +++ b/routing/missioncontrol_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -44,7 +44,7 @@ type mcTestContext struct { mc *MissionControl now time.Time - db *bbolt.DB + db kvdb.Backend dbPath string pid uint64 @@ -63,7 +63,7 @@ func createMcTestContext(t *testing.T) *mcTestContext { ctx.dbPath = file.Name() - ctx.db, err = bbolt.Open(ctx.dbPath, 0600, nil) + ctx.db, err = kvdb.Open(kvdb.BoltBackendName, ctx.dbPath, true) if err != nil { t.Fatal(err) } diff --git a/routing/router.go b/routing/router.go index 6751bfaea3..ca7a20f806 100644 --- a/routing/router.go +++ b/routing/router.go @@ -11,12 +11,12 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" @@ -2111,7 +2111,7 @@ func (r *ChannelRouter) FetchLightningNode(node route.Vertex) (*channeldb.Lightn // // NOTE: This method is part of the ChannelGraphSource interface. func (r *ChannelRouter) ForEachNode(cb func(*channeldb.LightningNode) error) error { - return r.cfg.Graph.ForEachNode(nil, func(_ *bbolt.Tx, n *channeldb.LightningNode) error { + return r.cfg.Graph.ForEachNode(nil, func(_ kvdb.ReadTx, n *channeldb.LightningNode) error { return cb(n) }) } @@ -2123,7 +2123,7 @@ func (r *ChannelRouter) ForEachNode(cb func(*channeldb.LightningNode) error) err func (r *ChannelRouter) ForAllOutgoingChannels(cb func(*channeldb.ChannelEdgeInfo, *channeldb.ChannelEdgePolicy) error) error { - return r.selfNode.ForEachChannel(nil, func(_ *bbolt.Tx, c *channeldb.ChannelEdgeInfo, + return r.selfNode.ForEachChannel(nil, func(_ kvdb.ReadTx, c *channeldb.ChannelEdgeInfo, e, _ *channeldb.ChannelEdgePolicy) error { if e == nil { @@ -2264,7 +2264,7 @@ func generateBandwidthHints(sourceNode *channeldb.LightningNode, // First, we'll collect the set of outbound edges from the target // source node. var localChans []*channeldb.ChannelEdgeInfo - err := sourceNode.ForEachChannel(nil, func(tx *bbolt.Tx, + err := sourceNode.ForEachChannel(nil, func(tx kvdb.ReadTx, edgeInfo *channeldb.ChannelEdgeInfo, _, _ *channeldb.ChannelEdgePolicy) error { diff --git a/routing/router_test.go b/routing/router_test.go index dd8908c4dd..42020b7ead 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -97,7 +97,7 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr } mc, err := NewMissionControl( - graphInstance.graph.Database().DB, + graphInstance.graph.Database(), mcConfig, ) if err != nil { From 557b930c5fc427ad1d5122bde6f6b459be1c3c90 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:45:04 -0800 Subject: [PATCH 250/562] watchtower: convert to use new kvdb abstraction --- watchtower/wtdb/client_db.go | 114 +++++++++++++++++------------------ watchtower/wtdb/db_common.go | 15 ++--- watchtower/wtdb/tower_db.go | 84 +++++++++++++------------- watchtower/wtdb/version.go | 22 +++---- 4 files changed, 115 insertions(+), 120 deletions(-) diff --git a/watchtower/wtdb/client_db.go b/watchtower/wtdb/client_db.go index 169b904288..22b913e1c5 100644 --- a/watchtower/wtdb/client_db.go +++ b/watchtower/wtdb/client_db.go @@ -8,7 +8,7 @@ import ( "net" "github.com/btcsuite/btcd/btcec" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -113,7 +113,7 @@ var ( // ClientDB is single database providing a persistent storage engine for the // wtclient. type ClientDB struct { - db *bbolt.DB + db kvdb.Backend dbPath string } @@ -146,7 +146,7 @@ func OpenClientDB(dbPath string) (*ClientDB, error) { // initialized. This allows us to assume their presence throughout all // operations. If an known top-level bucket is expected to exist but is // missing, this will trigger a ErrUninitializedDB error. - err = clientDB.db.Update(initClientDBBuckets) + err = kvdb.Update(clientDB.db, initClientDBBuckets) if err != nil { bdb.Close() return nil, err @@ -157,7 +157,7 @@ func OpenClientDB(dbPath string) (*ClientDB, error) { // initClientDBBuckets creates all top-level buckets required to handle database // operations required by the latest version. -func initClientDBBuckets(tx *bbolt.Tx) error { +func initClientDBBuckets(tx kvdb.RwTx) error { buckets := [][]byte{ cSessionKeyIndexBkt, cChanSummaryBkt, @@ -167,7 +167,7 @@ func initClientDBBuckets(tx *bbolt.Tx) error { } for _, bucket := range buckets { - _, err := tx.CreateBucketIfNotExists(bucket) + _, err := tx.CreateTopLevelBucket(bucket) if err != nil { return err } @@ -179,7 +179,7 @@ func initClientDBBuckets(tx *bbolt.Tx) error { // bdb returns the backing bbolt.DB instance. // // NOTE: Part of the versionedDB interface. -func (c *ClientDB) bdb() *bbolt.DB { +func (c *ClientDB) bdb() kvdb.Backend { return c.db } @@ -188,7 +188,7 @@ func (c *ClientDB) bdb() *bbolt.DB { // NOTE: Part of the versionedDB interface. func (c *ClientDB) Version() (uint32, error) { var version uint32 - err := c.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { var err error version, err = getDBVersion(tx) return err @@ -215,13 +215,13 @@ func (c *ClientDB) CreateTower(lnAddr *lnwire.NetAddress) (*Tower, error) { copy(towerPubKey[:], lnAddr.IdentityKey.SerializeCompressed()) var tower *Tower - err := c.db.Update(func(tx *bbolt.Tx) error { - towerIndex := tx.Bucket(cTowerIndexBkt) + err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { + towerIndex := tx.ReadWriteBucket(cTowerIndexBkt) if towerIndex == nil { return ErrUninitializedDB } - towers := tx.Bucket(cTowerBkt) + towers := tx.ReadWriteBucket(cTowerBkt) if towers == nil { return ErrUninitializedDB } @@ -248,7 +248,7 @@ func (c *ClientDB) CreateTower(lnAddr *lnwire.NetAddress) (*Tower, error) { // // TODO(wilmer): with an index of tower -> sessions we // can avoid the linear lookup. - sessions := tx.Bucket(cSessionBkt) + sessions := tx.ReadWriteBucket(cSessionBkt) if sessions == nil { return ErrUninitializedDB } @@ -308,12 +308,12 @@ func (c *ClientDB) CreateTower(lnAddr *lnwire.NetAddress) (*Tower, error) { // // NOTE: An error is not returned if the tower doesn't exist. func (c *ClientDB) RemoveTower(pubKey *btcec.PublicKey, addr net.Addr) error { - return c.db.Update(func(tx *bbolt.Tx) error { - towers := tx.Bucket(cTowerBkt) + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { + towers := tx.ReadWriteBucket(cTowerBkt) if towers == nil { return ErrUninitializedDB } - towerIndex := tx.Bucket(cTowerIndexBkt) + towerIndex := tx.ReadWriteBucket(cTowerIndexBkt) if towerIndex == nil { return ErrUninitializedDB } @@ -342,7 +342,7 @@ func (c *ClientDB) RemoveTower(pubKey *btcec.PublicKey, addr net.Addr) error { // // TODO(wilmer): with an index of tower -> sessions we can avoid // the linear lookup. - sessions := tx.Bucket(cSessionBkt) + sessions := tx.ReadWriteBucket(cSessionBkt) if sessions == nil { return ErrUninitializedDB } @@ -383,8 +383,8 @@ func (c *ClientDB) RemoveTower(pubKey *btcec.PublicKey, addr net.Addr) error { // LoadTowerByID retrieves a tower by its tower ID. func (c *ClientDB) LoadTowerByID(towerID TowerID) (*Tower, error) { var tower *Tower - err := c.db.View(func(tx *bbolt.Tx) error { - towers := tx.Bucket(cTowerBkt) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + towers := tx.ReadBucket(cTowerBkt) if towers == nil { return ErrUninitializedDB } @@ -403,12 +403,12 @@ func (c *ClientDB) LoadTowerByID(towerID TowerID) (*Tower, error) { // LoadTower retrieves a tower by its public key. func (c *ClientDB) LoadTower(pubKey *btcec.PublicKey) (*Tower, error) { var tower *Tower - err := c.db.View(func(tx *bbolt.Tx) error { - towers := tx.Bucket(cTowerBkt) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + towers := tx.ReadBucket(cTowerBkt) if towers == nil { return ErrUninitializedDB } - towerIndex := tx.Bucket(cTowerIndexBkt) + towerIndex := tx.ReadBucket(cTowerIndexBkt) if towerIndex == nil { return ErrUninitializedDB } @@ -432,8 +432,8 @@ func (c *ClientDB) LoadTower(pubKey *btcec.PublicKey) (*Tower, error) { // ListTowers retrieves the list of towers available within the database. func (c *ClientDB) ListTowers() ([]*Tower, error) { var towers []*Tower - err := c.db.View(func(tx *bbolt.Tx) error { - towerBucket := tx.Bucket(cTowerBkt) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + towerBucket := tx.ReadBucket(cTowerBkt) if towerBucket == nil { return ErrUninitializedDB } @@ -461,8 +461,8 @@ func (c *ClientDB) ListTowers() ([]*Tower, error) { // CreateClientSession is invoked should return the same index. func (c *ClientDB) NextSessionKeyIndex(towerID TowerID) (uint32, error) { var index uint32 - err := c.db.Update(func(tx *bbolt.Tx) error { - keyIndex := tx.Bucket(cSessionKeyIndexBkt) + err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { + keyIndex := tx.ReadWriteBucket(cSessionKeyIndexBkt) if keyIndex == nil { return ErrUninitializedDB } @@ -509,20 +509,20 @@ func (c *ClientDB) NextSessionKeyIndex(towerID TowerID) (uint32, error) { // CreateClientSession records a newly negotiated client session in the set of // active sessions. The session can be identified by its SessionID. func (c *ClientDB) CreateClientSession(session *ClientSession) error { - return c.db.Update(func(tx *bbolt.Tx) error { - keyIndexes := tx.Bucket(cSessionKeyIndexBkt) + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { + keyIndexes := tx.ReadWriteBucket(cSessionKeyIndexBkt) if keyIndexes == nil { return ErrUninitializedDB } - sessions := tx.Bucket(cSessionBkt) + sessions := tx.ReadWriteBucket(cSessionBkt) if sessions == nil { return ErrUninitializedDB } // Check that client session with this session id doesn't // already exist. - existingSessionBytes := sessions.Bucket(session.ID[:]) + existingSessionBytes := sessions.NestedReadWriteBucket(session.ID[:]) if existingSessionBytes != nil { return ErrClientSessionAlreadyExists } @@ -558,8 +558,8 @@ func (c *ClientDB) CreateClientSession(session *ClientSession) error { // response that do not correspond to this tower. func (c *ClientDB) ListClientSessions(id *TowerID) (map[SessionID]*ClientSession, error) { var clientSessions map[SessionID]*ClientSession - err := c.db.View(func(tx *bbolt.Tx) error { - sessions := tx.Bucket(cSessionBkt) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + sessions := tx.ReadBucket(cSessionBkt) if sessions == nil { return ErrUninitializedDB } @@ -577,7 +577,7 @@ func (c *ClientDB) ListClientSessions(id *TowerID) (map[SessionID]*ClientSession // listClientSessions returns the set of all client sessions known to the db. An // optional tower ID can be used to filter out any client sessions in the // response that do not correspond to this tower. -func listClientSessions(sessions *bbolt.Bucket, +func listClientSessions(sessions kvdb.ReadBucket, id *TowerID) (map[SessionID]*ClientSession, error) { clientSessions := make(map[SessionID]*ClientSession) @@ -612,8 +612,8 @@ func listClientSessions(sessions *bbolt.Bucket, // channel summaries. func (c *ClientDB) FetchChanSummaries() (ChannelSummaries, error) { summaries := make(map[lnwire.ChannelID]ClientChanSummary) - err := c.db.View(func(tx *bbolt.Tx) error { - chanSummaries := tx.Bucket(cChanSummaryBkt) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + chanSummaries := tx.ReadBucket(cChanSummaryBkt) if chanSummaries == nil { return ErrUninitializedDB } @@ -648,8 +648,8 @@ func (c *ClientDB) FetchChanSummaries() (ChannelSummaries, error) { func (c *ClientDB) RegisterChannel(chanID lnwire.ChannelID, sweepPkScript []byte) error { - return c.db.Update(func(tx *bbolt.Tx) error { - chanSummaries := tx.Bucket(cChanSummaryBkt) + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { + chanSummaries := tx.ReadWriteBucket(cChanSummaryBkt) if chanSummaries == nil { return ErrUninitializedDB } @@ -692,8 +692,8 @@ func (c *ClientDB) CommitUpdate(id *SessionID, update *CommittedUpdate) (uint16, error) { var lastApplied uint16 - err := c.db.Update(func(tx *bbolt.Tx) error { - sessions := tx.Bucket(cSessionBkt) + err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { + sessions := tx.ReadWriteBucket(cSessionBkt) if sessions == nil { return ErrUninitializedDB } @@ -708,7 +708,7 @@ func (c *ClientDB) CommitUpdate(id *SessionID, } // Can't fail if the above didn't fail. - sessionBkt := sessions.Bucket(id[:]) + sessionBkt := sessions.NestedReadWriteBucket(id[:]) // Ensure the session commits sub-bucket is initialized. sessionCommits, err := sessionBkt.CreateBucketIfNotExists( @@ -796,8 +796,8 @@ func (c *ClientDB) CommitUpdate(id *SessionID, func (c *ClientDB) AckUpdate(id *SessionID, seqNum uint16, lastApplied uint16) error { - return c.db.Update(func(tx *bbolt.Tx) error { - sessions := tx.Bucket(cSessionBkt) + return kvdb.Update(c.db, func(tx kvdb.RwTx) error { + sessions := tx.ReadWriteBucket(cSessionBkt) if sessions == nil { return ErrUninitializedDB } @@ -835,11 +835,11 @@ func (c *ClientDB) AckUpdate(id *SessionID, seqNum uint16, } // Can't fail because of getClientSession succeeded. - sessionBkt := sessions.Bucket(id[:]) + sessionBkt := sessions.NestedReadWriteBucket(id[:]) // If the commits sub-bucket doesn't exist, there can't possibly // be a corresponding committed update to remove. - sessionCommits := sessionBkt.Bucket(cSessionCommits) + sessionCommits := sessionBkt.NestedReadWriteBucket(cSessionCommits) if sessionCommits == nil { return ErrCommittedUpdateNotFound } @@ -894,10 +894,10 @@ func (c *ClientDB) AckUpdate(id *SessionID, seqNum uint16, // bucket corresponding to the serialized session id. This does not deserialize // the CommittedUpdates or AckUpdates associated with the session. If the caller // requires this info, use getClientSession. -func getClientSessionBody(sessions *bbolt.Bucket, +func getClientSessionBody(sessions kvdb.ReadBucket, idBytes []byte) (*ClientSession, error) { - sessionBkt := sessions.Bucket(idBytes) + sessionBkt := sessions.NestedReadBucket(idBytes) if sessionBkt == nil { return nil, ErrClientSessionNotFound } @@ -922,7 +922,7 @@ func getClientSessionBody(sessions *bbolt.Bucket, // getClientSession loads the full ClientSession associated with the serialized // session id. This method populates the CommittedUpdates and AckUpdates in // addition to the ClientSession's body. -func getClientSession(sessions *bbolt.Bucket, +func getClientSession(sessions kvdb.ReadBucket, idBytes []byte) (*ClientSession, error) { session, err := getClientSessionBody(sessions, idBytes) @@ -950,17 +950,17 @@ func getClientSession(sessions *bbolt.Bucket, // getClientSessionCommits retrieves all committed updates for the session // identified by the serialized session id. -func getClientSessionCommits(sessions *bbolt.Bucket, +func getClientSessionCommits(sessions kvdb.ReadBucket, idBytes []byte) ([]CommittedUpdate, error) { // Can't fail because client session body has already been read. - sessionBkt := sessions.Bucket(idBytes) + sessionBkt := sessions.NestedReadBucket(idBytes) // Initialize commitedUpdates so that we can return an initialized map // if no committed updates exist. committedUpdates := make([]CommittedUpdate, 0) - sessionCommits := sessionBkt.Bucket(cSessionCommits) + sessionCommits := sessionBkt.NestedReadBucket(cSessionCommits) if sessionCommits == nil { return committedUpdates, nil } @@ -986,17 +986,17 @@ func getClientSessionCommits(sessions *bbolt.Bucket, // getClientSessionAcks retrieves all acked updates for the session identified // by the serialized session id. -func getClientSessionAcks(sessions *bbolt.Bucket, +func getClientSessionAcks(sessions kvdb.ReadBucket, idBytes []byte) (map[uint16]BackupID, error) { // Can't fail because client session body has already been read. - sessionBkt := sessions.Bucket(idBytes) + sessionBkt := sessions.NestedReadBucket(idBytes) // Initialize ackedUpdates so that we can return an initialized map if // no acked updates exist. ackedUpdates := make(map[uint16]BackupID) - sessionAcks := sessionBkt.Bucket(cSessionAcks) + sessionAcks := sessionBkt.NestedReadBucket(cSessionAcks) if sessionAcks == nil { return ackedUpdates, nil } @@ -1023,7 +1023,7 @@ func getClientSessionAcks(sessions *bbolt.Bucket, // putClientSessionBody stores the body of the ClientSession (everything but the // CommittedUpdates and AckedUpdates). -func putClientSessionBody(sessions *bbolt.Bucket, +func putClientSessionBody(sessions kvdb.RwBucket, session *ClientSession) error { sessionBkt, err := sessions.CreateBucketIfNotExists(session.ID[:]) @@ -1042,7 +1042,7 @@ func putClientSessionBody(sessions *bbolt.Bucket, // markSessionStatus updates the persisted state of the session to the new // status. -func markSessionStatus(sessions *bbolt.Bucket, session *ClientSession, +func markSessionStatus(sessions kvdb.RwBucket, session *ClientSession, status CSessionStatus) error { session.Status = status @@ -1050,7 +1050,7 @@ func markSessionStatus(sessions *bbolt.Bucket, session *ClientSession, } // getChanSummary loads a ClientChanSummary for the passed chanID. -func getChanSummary(chanSummaries *bbolt.Bucket, +func getChanSummary(chanSummaries kvdb.ReadBucket, chanID lnwire.ChannelID) (*ClientChanSummary, error) { chanSummaryBytes := chanSummaries.Get(chanID[:]) @@ -1068,7 +1068,7 @@ func getChanSummary(chanSummaries *bbolt.Bucket, } // putChanSummary stores a ClientChanSummary for the passed chanID. -func putChanSummary(chanSummaries *bbolt.Bucket, chanID lnwire.ChannelID, +func putChanSummary(chanSummaries kvdb.RwBucket, chanID lnwire.ChannelID, summary *ClientChanSummary) error { var b bytes.Buffer @@ -1081,7 +1081,7 @@ func putChanSummary(chanSummaries *bbolt.Bucket, chanID lnwire.ChannelID, } // getTower loads a Tower identified by its serialized tower id. -func getTower(towers *bbolt.Bucket, id []byte) (*Tower, error) { +func getTower(towers kvdb.ReadBucket, id []byte) (*Tower, error) { towerBytes := towers.Get(id) if towerBytes == nil { return nil, ErrTowerNotFound @@ -1099,7 +1099,7 @@ func getTower(towers *bbolt.Bucket, id []byte) (*Tower, error) { } // putTower stores a Tower identified by its serialized tower id. -func putTower(towers *bbolt.Bucket, tower *Tower) error { +func putTower(towers kvdb.RwBucket, tower *Tower) error { var b bytes.Buffer err := tower.Encode(&b) if err != nil { diff --git a/watchtower/wtdb/db_common.go b/watchtower/wtdb/db_common.go index ed6f1c6b8f..1592f1e6e8 100644 --- a/watchtower/wtdb/db_common.go +++ b/watchtower/wtdb/db_common.go @@ -6,7 +6,7 @@ import ( "os" "path/filepath" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) const ( @@ -49,7 +49,7 @@ func fileExists(path string) bool { // one doesn't exist. The boolean returned indicates if the database did not // exist before, or if it has been created but no version metadata exists within // it. -func createDBIfNotExist(dbPath, name string) (*bbolt.DB, bool, error) { +func createDBIfNotExist(dbPath, name string) (kvdb.Backend, bool, error) { path := filepath.Join(dbPath, name) // If the database file doesn't exist, this indicates we much initialize @@ -65,12 +65,7 @@ func createDBIfNotExist(dbPath, name string) (*bbolt.DB, bool, error) { // Specify bbolt freelist options to reduce heap pressure in case the // freelist grows to be very large. - options := &bbolt.Options{ - NoFreelistSync: true, - FreelistType: bbolt.FreelistMapType, - } - - bdb, err := bbolt.Open(path, dbFilePermission, options) + bdb, err := kvdb.Create(kvdb.BoltBackendName, path, true) if err != nil { return nil, false, err } @@ -82,8 +77,8 @@ func createDBIfNotExist(dbPath, name string) (*bbolt.DB, bool, error) { // set firstInit to true so that we can treat is initialize the bucket. if !firstInit { var metadataExists bool - err = bdb.View(func(tx *bbolt.Tx) error { - metadataExists = tx.Bucket(metadataBkt) != nil + err = kvdb.View(bdb, func(tx kvdb.ReadTx) error { + metadataExists = tx.ReadBucket(metadataBkt) != nil return nil }) if err != nil { diff --git a/watchtower/wtdb/tower_db.go b/watchtower/wtdb/tower_db.go index 92a9e55abe..39782f1d54 100644 --- a/watchtower/wtdb/tower_db.go +++ b/watchtower/wtdb/tower_db.go @@ -5,8 +5,8 @@ import ( "errors" "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/chainntnfs" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/watchtower/blob" ) @@ -55,7 +55,7 @@ var ( // TowerDB is single database providing a persistent storage engine for the // wtserver and lookout subsystems. type TowerDB struct { - db *bbolt.DB + db kvdb.Backend dbPath string } @@ -88,7 +88,7 @@ func OpenTowerDB(dbPath string) (*TowerDB, error) { // initialized. This allows us to assume their presence throughout all // operations. If an known top-level bucket is expected to exist but is // missing, this will trigger a ErrUninitializedDB error. - err = towerDB.db.Update(initTowerDBBuckets) + err = kvdb.Update(towerDB.db, initTowerDBBuckets) if err != nil { bdb.Close() return nil, err @@ -99,7 +99,7 @@ func OpenTowerDB(dbPath string) (*TowerDB, error) { // initTowerDBBuckets creates all top-level buckets required to handle database // operations required by the latest version. -func initTowerDBBuckets(tx *bbolt.Tx) error { +func initTowerDBBuckets(tx kvdb.RwTx) error { buckets := [][]byte{ sessionsBkt, updateIndexBkt, @@ -108,7 +108,7 @@ func initTowerDBBuckets(tx *bbolt.Tx) error { } for _, bucket := range buckets { - _, err := tx.CreateBucketIfNotExists(bucket) + _, err := tx.CreateTopLevelBucket(bucket) if err != nil { return err } @@ -120,7 +120,7 @@ func initTowerDBBuckets(tx *bbolt.Tx) error { // bdb returns the backing bbolt.DB instance. // // NOTE: Part of the versionedDB interface. -func (t *TowerDB) bdb() *bbolt.DB { +func (t *TowerDB) bdb() kvdb.Backend { return t.db } @@ -129,7 +129,7 @@ func (t *TowerDB) bdb() *bbolt.DB { // NOTE: Part of the versionedDB interface. func (t *TowerDB) Version() (uint32, error) { var version uint32 - err := t.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(t.db, func(tx kvdb.ReadTx) error { var err error version, err = getDBVersion(tx) return err @@ -150,8 +150,8 @@ func (t *TowerDB) Close() error { // returned if the session could not be found. func (t *TowerDB) GetSessionInfo(id *SessionID) (*SessionInfo, error) { var session *SessionInfo - err := t.db.View(func(tx *bbolt.Tx) error { - sessions := tx.Bucket(sessionsBkt) + err := kvdb.View(t.db, func(tx kvdb.ReadTx) error { + sessions := tx.ReadBucket(sessionsBkt) if sessions == nil { return ErrUninitializedDB } @@ -170,13 +170,13 @@ func (t *TowerDB) GetSessionInfo(id *SessionID) (*SessionInfo, error) { // InsertSessionInfo records a negotiated session in the tower database. An // error is returned if the session already exists. func (t *TowerDB) InsertSessionInfo(session *SessionInfo) error { - return t.db.Update(func(tx *bbolt.Tx) error { - sessions := tx.Bucket(sessionsBkt) + return kvdb.Update(t.db, func(tx kvdb.RwTx) error { + sessions := tx.ReadWriteBucket(sessionsBkt) if sessions == nil { return ErrUninitializedDB } - updateIndex := tx.Bucket(updateIndexBkt) + updateIndex := tx.ReadWriteBucket(updateIndexBkt) if updateIndex == nil { return ErrUninitializedDB } @@ -219,18 +219,18 @@ func (t *TowerDB) InsertSessionInfo(session *SessionInfo) error { // properly and the last applied values echoed by the client are sane. func (t *TowerDB) InsertStateUpdate(update *SessionStateUpdate) (uint16, error) { var lastApplied uint16 - err := t.db.Update(func(tx *bbolt.Tx) error { - sessions := tx.Bucket(sessionsBkt) + err := kvdb.Update(t.db, func(tx kvdb.RwTx) error { + sessions := tx.ReadWriteBucket(sessionsBkt) if sessions == nil { return ErrUninitializedDB } - updates := tx.Bucket(updatesBkt) + updates := tx.ReadWriteBucket(updatesBkt) if updates == nil { return ErrUninitializedDB } - updateIndex := tx.Bucket(updateIndexBkt) + updateIndex := tx.ReadWriteBucket(updateIndexBkt) if updateIndex == nil { return ErrUninitializedDB } @@ -303,18 +303,18 @@ func (t *TowerDB) InsertStateUpdate(update *SessionStateUpdate) (uint16, error) // DeleteSession removes all data associated with a particular session id from // the tower's database. func (t *TowerDB) DeleteSession(target SessionID) error { - return t.db.Update(func(tx *bbolt.Tx) error { - sessions := tx.Bucket(sessionsBkt) + return kvdb.Update(t.db, func(tx kvdb.RwTx) error { + sessions := tx.ReadWriteBucket(sessionsBkt) if sessions == nil { return ErrUninitializedDB } - updates := tx.Bucket(updatesBkt) + updates := tx.ReadWriteBucket(updatesBkt) if updates == nil { return ErrUninitializedDB } - updateIndex := tx.Bucket(updateIndexBkt) + updateIndex := tx.ReadWriteBucket(updateIndexBkt) if updateIndex == nil { return ErrUninitializedDB } @@ -341,7 +341,7 @@ func (t *TowerDB) DeleteSession(target SessionID) error { for _, hint := range hints { // Remove the state updates for any blobs stored under // the target session identifier. - updatesForHint := updates.Bucket(hint[:]) + updatesForHint := updates.NestedReadWriteBucket(hint[:]) if updatesForHint == nil { continue } @@ -371,7 +371,7 @@ func (t *TowerDB) DeleteSession(target SessionID) error { // No more updates for this hint, prune hint bucket. default: - err = updates.DeleteBucket(hint[:]) + err = updates.DeleteNestedBucket(hint[:]) if err != nil { return err } @@ -389,13 +389,13 @@ func (t *TowerDB) DeleteSession(target SessionID) error { // they exist in the database. func (t *TowerDB) QueryMatches(breachHints []blob.BreachHint) ([]Match, error) { var matches []Match - err := t.db.View(func(tx *bbolt.Tx) error { - sessions := tx.Bucket(sessionsBkt) + err := kvdb.View(t.db, func(tx kvdb.ReadTx) error { + sessions := tx.ReadBucket(sessionsBkt) if sessions == nil { return ErrUninitializedDB } - updates := tx.Bucket(updatesBkt) + updates := tx.ReadBucket(updatesBkt) if updates == nil { return ErrUninitializedDB } @@ -405,7 +405,7 @@ func (t *TowerDB) QueryMatches(breachHints []blob.BreachHint) ([]Match, error) { for _, hint := range breachHints { // If a bucket does not exist for this hint, no matches // are known. - updatesForHint := updates.Bucket(hint[:]) + updatesForHint := updates.NestedReadBucket(hint[:]) if updatesForHint == nil { continue } @@ -471,8 +471,8 @@ func (t *TowerDB) QueryMatches(breachHints []blob.BreachHint) ([]Match, error) { // SetLookoutTip stores the provided epoch as the latest lookout tip epoch in // the tower database. func (t *TowerDB) SetLookoutTip(epoch *chainntnfs.BlockEpoch) error { - return t.db.Update(func(tx *bbolt.Tx) error { - lookoutTip := tx.Bucket(lookoutTipBkt) + return kvdb.Update(t.db, func(tx kvdb.RwTx) error { + lookoutTip := tx.ReadWriteBucket(lookoutTipBkt) if lookoutTip == nil { return ErrUninitializedDB } @@ -485,8 +485,8 @@ func (t *TowerDB) SetLookoutTip(epoch *chainntnfs.BlockEpoch) error { // database. func (t *TowerDB) GetLookoutTip() (*chainntnfs.BlockEpoch, error) { var epoch *chainntnfs.BlockEpoch - err := t.db.View(func(tx *bbolt.Tx) error { - lookoutTip := tx.Bucket(lookoutTipBkt) + err := kvdb.View(t.db, func(tx kvdb.ReadTx) error { + lookoutTip := tx.ReadBucket(lookoutTipBkt) if lookoutTip == nil { return ErrUninitializedDB } @@ -505,7 +505,7 @@ func (t *TowerDB) GetLookoutTip() (*chainntnfs.BlockEpoch, error) { // getSession retrieves the session info from the sessions bucket identified by // its session id. An error is returned if the session is not found or a // deserialization error occurs. -func getSession(sessions *bbolt.Bucket, id []byte) (*SessionInfo, error) { +func getSession(sessions kvdb.ReadBucket, id []byte) (*SessionInfo, error) { sessionBytes := sessions.Get(id) if sessionBytes == nil { return nil, ErrSessionNotFound @@ -522,7 +522,7 @@ func getSession(sessions *bbolt.Bucket, id []byte) (*SessionInfo, error) { // putSession stores the session info in the sessions bucket identified by its // session id. An error is returned if a serialization error occurs. -func putSession(sessions *bbolt.Bucket, session *SessionInfo) error { +func putSession(sessions kvdb.RwBucket, session *SessionInfo) error { var b bytes.Buffer err := session.Encode(&b) if err != nil { @@ -536,7 +536,7 @@ func putSession(sessions *bbolt.Bucket, session *SessionInfo) error { // session id. This ensures that future calls to getHintsForSession or // putHintForSession can rely on the bucket already being created, and fail if // index has not been initialized as this points to improper usage. -func touchSessionHintBkt(updateIndex *bbolt.Bucket, id *SessionID) error { +func touchSessionHintBkt(updateIndex kvdb.RwBucket, id *SessionID) error { _, err := updateIndex.CreateBucketIfNotExists(id[:]) return err } @@ -544,17 +544,17 @@ func touchSessionHintBkt(updateIndex *bbolt.Bucket, id *SessionID) error { // removeSessionHintBkt prunes the session-hint bucket for the given session id // and all of the hints contained inside. This should be used to clean up the // index upon session deletion. -func removeSessionHintBkt(updateIndex *bbolt.Bucket, id *SessionID) error { - return updateIndex.DeleteBucket(id[:]) +func removeSessionHintBkt(updateIndex kvdb.RwBucket, id *SessionID) error { + return updateIndex.DeleteNestedBucket(id[:]) } // getHintsForSession returns all known hints belonging to the given session id. // If the index for the session has not been initialized, this method returns // ErrNoSessionHintIndex. -func getHintsForSession(updateIndex *bbolt.Bucket, +func getHintsForSession(updateIndex kvdb.ReadBucket, id *SessionID) ([]blob.BreachHint, error) { - sessionHints := updateIndex.Bucket(id[:]) + sessionHints := updateIndex.NestedReadBucket(id[:]) if sessionHints == nil { return nil, ErrNoSessionHintIndex } @@ -582,10 +582,10 @@ func getHintsForSession(updateIndex *bbolt.Bucket, // session id, and used to perform efficient removal of updates. If the index // for the session has not been initialized, this method returns // ErrNoSessionHintIndex. -func putHintForSession(updateIndex *bbolt.Bucket, id *SessionID, +func putHintForSession(updateIndex kvdb.RwBucket, id *SessionID, hint blob.BreachHint) error { - sessionHints := updateIndex.Bucket(id[:]) + sessionHints := updateIndex.NestedReadWriteBucket(id[:]) if sessionHints == nil { return ErrNoSessionHintIndex } @@ -594,7 +594,7 @@ func putHintForSession(updateIndex *bbolt.Bucket, id *SessionID, } // putLookoutEpoch stores the given lookout tip block epoch in provided bucket. -func putLookoutEpoch(bkt *bbolt.Bucket, epoch *chainntnfs.BlockEpoch) error { +func putLookoutEpoch(bkt kvdb.RwBucket, epoch *chainntnfs.BlockEpoch) error { epochBytes := make([]byte, 36) copy(epochBytes, epoch.Hash[:]) byteOrder.PutUint32(epochBytes[32:], uint32(epoch.Height)) @@ -604,7 +604,7 @@ func putLookoutEpoch(bkt *bbolt.Bucket, epoch *chainntnfs.BlockEpoch) error { // getLookoutEpoch retrieves the lookout tip block epoch from the given bucket. // A nil epoch is returned if no update exists. -func getLookoutEpoch(bkt *bbolt.Bucket) *chainntnfs.BlockEpoch { +func getLookoutEpoch(bkt kvdb.ReadBucket) *chainntnfs.BlockEpoch { epochBytes := bkt.Get(lookoutTipKey) if len(epochBytes) != 36 { return nil @@ -625,7 +625,7 @@ func getLookoutEpoch(bkt *bbolt.Bucket) *chainntnfs.BlockEpoch { var errBucketNotEmpty = errors.New("bucket not empty") // isBucketEmpty returns errBucketNotEmpty if the bucket is not empty. -func isBucketEmpty(bkt *bbolt.Bucket) error { +func isBucketEmpty(bkt kvdb.ReadBucket) error { return bkt.ForEach(func(_, _ []byte) error { return errBucketNotEmpty }) diff --git a/watchtower/wtdb/version.go b/watchtower/wtdb/version.go index b8aa2b7e99..597a1f1fb1 100644 --- a/watchtower/wtdb/version.go +++ b/watchtower/wtdb/version.go @@ -1,14 +1,14 @@ package wtdb import ( - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) // migration is a function which takes a prior outdated version of the database // instances and mutates the key/bucket structure to arrive at a more // up-to-date version of the database. -type migration func(tx *bbolt.Tx) error +type migration func(tx kvdb.RwTx) error // version pairs a version number with the migration that would need to be // applied from the prior version to upgrade. @@ -46,8 +46,8 @@ func getMigrations(versions []version, curVersion uint32) []version { // getDBVersion retrieves the current database version from the metadata bucket // using the dbVersionKey. -func getDBVersion(tx *bbolt.Tx) (uint32, error) { - metadata := tx.Bucket(metadataBkt) +func getDBVersion(tx kvdb.ReadTx) (uint32, error) { + metadata := tx.ReadBucket(metadataBkt) if metadata == nil { return 0, ErrUninitializedDB } @@ -62,8 +62,8 @@ func getDBVersion(tx *bbolt.Tx) (uint32, error) { // initDBVersion initializes the top-level metadata bucket and writes the passed // version number as the current version. -func initDBVersion(tx *bbolt.Tx, version uint32) error { - _, err := tx.CreateBucketIfNotExists(metadataBkt) +func initDBVersion(tx kvdb.RwTx, version uint32) error { + _, err := tx.CreateTopLevelBucket(metadataBkt) if err != nil { return err } @@ -73,8 +73,8 @@ func initDBVersion(tx *bbolt.Tx, version uint32) error { // putDBVersion stores the passed database version in the metadata bucket under // the dbVersionKey. -func putDBVersion(tx *bbolt.Tx, version uint32) error { - metadata := tx.Bucket(metadataBkt) +func putDBVersion(tx kvdb.RwTx, version uint32) error { + metadata := tx.ReadWriteBucket(metadataBkt) if metadata == nil { return ErrUninitializedDB } @@ -89,7 +89,7 @@ func putDBVersion(tx *bbolt.Tx, version uint32) error { // on either. type versionedDB interface { // bdb returns the underlying bbolt database. - bdb() *bbolt.DB + bdb() kvdb.Backend // Version returns the current version stored in the database. Version() (uint32, error) @@ -105,7 +105,7 @@ func initOrSyncVersions(db versionedDB, init bool, versions []version) error { // If the database has not yet been created, we'll initialize the // database version with the latest known version. if init { - return db.bdb().Update(func(tx *bbolt.Tx) error { + return kvdb.Update(db.bdb(), func(tx kvdb.RwTx) error { return initDBVersion(tx, getLatestDBVersion(versions)) }) } @@ -141,7 +141,7 @@ func syncVersions(db versionedDB, versions []version) error { // Otherwise, apply any migrations in order to bring the database // version up to the highest known version. updates := getMigrations(versions, curVersion) - return db.bdb().Update(func(tx *bbolt.Tx) error { + return kvdb.Update(db.bdb(), func(tx kvdb.RwTx) error { for i, update := range updates { if update.migration == nil { continue From 852b2380a95ccca46dbb47dcfd71220d6409057f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:45:26 -0800 Subject: [PATCH 251/562] macaroons: convert to use new kvdb abstraction --- macaroons/service.go | 6 +++--- macaroons/service_test.go | 7 ++++--- macaroons/store.go | 26 +++++++++++++------------- macaroons/store_test.go | 14 ++++++++------ 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/macaroons/service.go b/macaroons/service.go index 3dddea6be4..825c643530 100644 --- a/macaroons/service.go +++ b/macaroons/service.go @@ -7,7 +7,7 @@ import ( "os" "path" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "google.golang.org/grpc" "google.golang.org/grpc/metadata" @@ -48,8 +48,8 @@ func NewService(dir string, checks ...Checker) (*Service, error) { // Open the database that we'll use to store the primary macaroon key, // and all generated macaroons+caveats. - macaroonDB, err := bbolt.Open( - path.Join(dir, DBFilename), 0600, bbolt.DefaultOptions, + macaroonDB, err := kvdb.Create( + kvdb.BoltBackendName, path.Join(dir, DBFilename), true, ) if err != nil { return nil, err diff --git a/macaroons/service_test.go b/macaroons/service_test.go index 32ed12f9fc..dd90ad5f8c 100644 --- a/macaroons/service_test.go +++ b/macaroons/service_test.go @@ -8,7 +8,7 @@ import ( "path" "testing" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/macaroons" "google.golang.org/grpc/metadata" "gopkg.in/macaroon-bakery.v2/bakery" @@ -33,8 +33,9 @@ func setupTestRootKeyStorage(t *testing.T) string { if err != nil { t.Fatalf("Error creating temp dir: %v", err) } - db, err := bbolt.Open(path.Join(tempDir, "macaroons.db"), 0600, - bbolt.DefaultOptions) + db, err := kvdb.Create( + kvdb.BoltBackendName, path.Join(tempDir, "macaroons.db"), true, + ) if err != nil { t.Fatalf("Error opening store DB: %v", err) } diff --git a/macaroons/store.go b/macaroons/store.go index 6b80ef5a9b..16ccc9a38a 100644 --- a/macaroons/store.go +++ b/macaroons/store.go @@ -7,7 +7,7 @@ import ( "io" "sync" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/btcsuite/btcwallet/snacl" ) @@ -46,7 +46,7 @@ var ( // RootKeyStorage implements the bakery.RootKeyStorage interface. type RootKeyStorage struct { - *bbolt.DB + kvdb.Backend encKeyMtx sync.RWMutex encKey *snacl.SecretKey @@ -54,10 +54,10 @@ type RootKeyStorage struct { // NewRootKeyStorage creates a RootKeyStorage instance. // TODO(aakselrod): Add support for encryption of data with passphrase. -func NewRootKeyStorage(db *bbolt.DB) (*RootKeyStorage, error) { +func NewRootKeyStorage(db kvdb.Backend) (*RootKeyStorage, error) { // If the store's bucket doesn't exist, create it. - err := db.Update(func(tx *bbolt.Tx) error { - _, err := tx.CreateBucketIfNotExists(rootKeyBucketName) + err := kvdb.Update(db, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket(rootKeyBucketName) return err }) if err != nil { @@ -65,7 +65,7 @@ func NewRootKeyStorage(db *bbolt.DB) (*RootKeyStorage, error) { } // Return the DB wrapped in a RootKeyStorage object. - return &RootKeyStorage{DB: db, encKey: nil}, nil + return &RootKeyStorage{Backend: db, encKey: nil}, nil } // CreateUnlock sets an encryption key if one is not already set, otherwise it @@ -84,8 +84,8 @@ func (r *RootKeyStorage) CreateUnlock(password *[]byte) error { return ErrPasswordRequired } - return r.Update(func(tx *bbolt.Tx) error { - bucket := tx.Bucket(rootKeyBucketName) + return kvdb.Update(r, func(tx kvdb.RwTx) error { + bucket := tx.ReadWriteBucket(rootKeyBucketName) dbKey := bucket.Get(encryptedKeyID) if len(dbKey) > 0 { // We've already stored a key, so try to unlock with @@ -131,8 +131,8 @@ func (r *RootKeyStorage) Get(_ context.Context, id []byte) ([]byte, error) { return nil, ErrStoreLocked } var rootKey []byte - err := r.View(func(tx *bbolt.Tx) error { - dbKey := tx.Bucket(rootKeyBucketName).Get(id) + err := kvdb.View(r, func(tx kvdb.ReadTx) error { + dbKey := tx.ReadBucket(rootKeyBucketName).Get(id) if len(dbKey) == 0 { return fmt.Errorf("root key with id %s doesn't exist", string(id)) @@ -166,8 +166,8 @@ func (r *RootKeyStorage) RootKey(_ context.Context) ([]byte, []byte, error) { } var rootKey []byte id := defaultRootKeyID - err := r.Update(func(tx *bbolt.Tx) error { - ns := tx.Bucket(rootKeyBucketName) + err := kvdb.Update(r, func(tx kvdb.RwTx) error { + ns := tx.ReadWriteBucket(rootKeyBucketName) dbKey := ns.Get(id) // If there's a root key stored in the bucket, decrypt it and @@ -212,5 +212,5 @@ func (r *RootKeyStorage) Close() error { if r.encKey != nil { r.encKey.Zero() } - return r.DB.Close() + return r.Backend.Close() } diff --git a/macaroons/store_test.go b/macaroons/store_test.go index 794b50218e..b6898df6e9 100644 --- a/macaroons/store_test.go +++ b/macaroons/store_test.go @@ -8,8 +8,7 @@ import ( "path" "testing" - "github.com/coreos/bbolt" - + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/macaroons" "github.com/btcsuite/btcwallet/snacl" @@ -22,8 +21,9 @@ func TestStore(t *testing.T) { } defer os.RemoveAll(tempDir) - db, err := bbolt.Open(path.Join(tempDir, "weks.db"), 0600, - bbolt.DefaultOptions) + db, err := kvdb.Create( + kvdb.BoltBackendName, path.Join(tempDir, "weks.db"), true, + ) if err != nil { t.Fatalf("Error opening store DB: %v", err) } @@ -73,11 +73,13 @@ func TestStore(t *testing.T) { } store.Close() + // Between here and the re-opening of the store, it's possible to get // a double-close, but that's not such a big deal since the tests will // fail anyway in that case. - db, err = bbolt.Open(path.Join(tempDir, "weks.db"), 0600, - bbolt.DefaultOptions) + db, err = kvdb.Create( + kvdb.BoltBackendName, path.Join(tempDir, "weks.db"), true, + ) if err != nil { t.Fatalf("Error opening store DB: %v", err) } From ace7a78494b67ddd25474f968bcd6c2ae8507c15 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:45:41 -0800 Subject: [PATCH 252/562] discovery: covert to use new kvdb abstraction --- discovery/message_store.go | 28 ++++++++++++++-------------- discovery/message_store_test.go | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/discovery/message_store.go b/discovery/message_store.go index e0c10a865a..207f857ff8 100644 --- a/discovery/message_store.go +++ b/discovery/message_store.go @@ -6,8 +6,8 @@ import ( "errors" "fmt" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -68,8 +68,8 @@ var _ GossipMessageStore = (*MessageStore)(nil) // NewMessageStore creates a new message store backed by a channeldb instance. func NewMessageStore(db *channeldb.DB) (*MessageStore, error) { - err := db.Update(func(tx *bbolt.Tx) error { - _, err := tx.CreateBucketIfNotExists(messageStoreBucket) + err := kvdb.Batch(db.Backend, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket(messageStoreBucket) return err }) if err != nil { @@ -124,8 +124,8 @@ func (s *MessageStore) AddMessage(msg lnwire.Message, peerPubKey [33]byte) error return err } - return s.db.Batch(func(tx *bbolt.Tx) error { - messageStore := tx.Bucket(messageStoreBucket) + return kvdb.Batch(s.db.Backend, func(tx kvdb.RwTx) error { + messageStore := tx.ReadWriteBucket(messageStoreBucket) if messageStore == nil { return ErrCorruptedMessageStore } @@ -145,8 +145,8 @@ func (s *MessageStore) DeleteMessage(msg lnwire.Message, return err } - return s.db.Batch(func(tx *bbolt.Tx) error { - messageStore := tx.Bucket(messageStoreBucket) + return kvdb.Batch(s.db.Backend, func(tx kvdb.RwTx) error { + messageStore := tx.ReadWriteBucket(messageStoreBucket) if messageStore == nil { return ErrCorruptedMessageStore } @@ -200,8 +200,8 @@ func readMessage(msgBytes []byte) (lnwire.Message, error) { // all peers. func (s *MessageStore) Messages() (map[[33]byte][]lnwire.Message, error) { msgs := make(map[[33]byte][]lnwire.Message) - err := s.db.View(func(tx *bbolt.Tx) error { - messageStore := tx.Bucket(messageStoreBucket) + err := kvdb.View(s.db, func(tx kvdb.ReadTx) error { + messageStore := tx.ReadBucket(messageStoreBucket) if messageStore == nil { return ErrCorruptedMessageStore } @@ -238,13 +238,13 @@ func (s *MessageStore) MessagesForPeer( peerPubKey [33]byte) ([]lnwire.Message, error) { var msgs []lnwire.Message - err := s.db.View(func(tx *bbolt.Tx) error { - messageStore := tx.Bucket(messageStoreBucket) + err := kvdb.View(s.db, func(tx kvdb.ReadTx) error { + messageStore := tx.ReadBucket(messageStoreBucket) if messageStore == nil { return ErrCorruptedMessageStore } - c := messageStore.Cursor() + c := messageStore.ReadCursor() k, v := c.Seek(peerPubKey[:]) for ; bytes.HasPrefix(k, peerPubKey[:]); k, v = c.Next() { // Deserialize the message from its raw bytes and filter @@ -273,8 +273,8 @@ func (s *MessageStore) MessagesForPeer( // Peers returns the public key of all peers with messages within the store. func (s *MessageStore) Peers() (map[[33]byte]struct{}, error) { peers := make(map[[33]byte]struct{}) - err := s.db.View(func(tx *bbolt.Tx) error { - messageStore := tx.Bucket(messageStoreBucket) + err := kvdb.View(s.db, func(tx kvdb.ReadTx) error { + messageStore := tx.ReadBucket(messageStoreBucket) if messageStore == nil { return ErrCorruptedMessageStore } diff --git a/discovery/message_store_test.go b/discovery/message_store_test.go index a106ad2256..fc7ba3360e 100644 --- a/discovery/message_store_test.go +++ b/discovery/message_store_test.go @@ -9,9 +9,9 @@ import ( "testing" "github.com/btcsuite/btcd/btcec" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" ) @@ -236,8 +236,8 @@ func TestMessageStoreUnsupportedMessage(t *testing.T) { if _, err := lnwire.WriteMessage(&rawMsg, unsupportedMsg, 0); err != nil { t.Fatalf("unable to serialize message: %v", err) } - err = msgStore.db.Update(func(tx *bbolt.Tx) error { - messageStore := tx.Bucket(messageStoreBucket) + err = kvdb.Update(msgStore.db, func(tx kvdb.RwTx) error { + messageStore := tx.ReadWriteBucket(messageStoreBucket) return messageStore.Put(msgKey, rawMsg.Bytes()) }) if err != nil { From 46cec2fdc0d0088ab266c4875e797916fab7afaa Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:46:00 -0800 Subject: [PATCH 253/562] sweep: convert to use new kvdb abstraction --- sweep/store.go | 38 ++++++++++++++++++++------------------ sweep/store_test.go | 2 +- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/sweep/store.go b/sweep/store.go index f1ca84759b..287646a7b0 100644 --- a/sweep/store.go +++ b/sweep/store.go @@ -8,7 +8,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) var ( @@ -56,26 +56,28 @@ type SweeperStore interface { } type sweeperStore struct { - db *bbolt.DB + db kvdb.Backend } // NewSweeperStore returns a new store instance. -func NewSweeperStore(db *bbolt.DB, chainHash *chainhash.Hash) ( +func NewSweeperStore(db kvdb.Backend, chainHash *chainhash.Hash) ( SweeperStore, error) { - err := db.Update(func(tx *bbolt.Tx) error { - _, err := tx.CreateBucketIfNotExists( + err := kvdb.Update(db, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket( lastTxBucketKey, ) if err != nil { return err } - if tx.Bucket(txHashesBucketKey) != nil { + if tx.ReadWriteBucket(txHashesBucketKey) != nil { return nil } - txHashesBucket, err := tx.CreateBucket(txHashesBucketKey) + txHashesBucket, err := tx.CreateTopLevelBucket( + txHashesBucketKey, + ) if err != nil { return err } @@ -97,7 +99,7 @@ func NewSweeperStore(db *bbolt.DB, chainHash *chainhash.Hash) ( // migrateTxHashes migrates nursery finalized txes to the tx hashes bucket. This // is not implemented as a database migration, to keep the downgrade path open. -func migrateTxHashes(tx *bbolt.Tx, txHashesBucket *bbolt.Bucket, +func migrateTxHashes(tx kvdb.RwTx, txHashesBucket kvdb.RwBucket, chainHash *chainhash.Hash) error { log.Infof("Migrating UTXO nursery finalized TXIDs") @@ -113,20 +115,20 @@ func migrateTxHashes(tx *bbolt.Tx, txHashesBucket *bbolt.Bucket, } // Get chain bucket if exists. - chainBucket := tx.Bucket(b.Bytes()) + chainBucket := tx.ReadWriteBucket(b.Bytes()) if chainBucket == nil { return nil } // Retrieve the existing height index. - hghtIndex := chainBucket.Bucket(utxnHeightIndexKey) + hghtIndex := chainBucket.NestedReadWriteBucket(utxnHeightIndexKey) if hghtIndex == nil { return nil } // Retrieve all heights. err := hghtIndex.ForEach(func(k, v []byte) error { - heightBucket := hghtIndex.Bucket(k) + heightBucket := hghtIndex.NestedReadWriteBucket(k) if heightBucket == nil { return nil } @@ -163,13 +165,13 @@ func migrateTxHashes(tx *bbolt.Tx, txHashesBucket *bbolt.Bucket, // NotifyPublishTx signals that we are about to publish a tx. func (s *sweeperStore) NotifyPublishTx(sweepTx *wire.MsgTx) error { - return s.db.Update(func(tx *bbolt.Tx) error { - lastTxBucket := tx.Bucket(lastTxBucketKey) + return kvdb.Update(s.db, func(tx kvdb.RwTx) error { + lastTxBucket := tx.ReadWriteBucket(lastTxBucketKey) if lastTxBucket == nil { return errors.New("last tx bucket does not exist") } - txHashesBucket := tx.Bucket(txHashesBucketKey) + txHashesBucket := tx.ReadWriteBucket(txHashesBucketKey) if txHashesBucket == nil { return errors.New("tx hashes bucket does not exist") } @@ -194,8 +196,8 @@ func (s *sweeperStore) NotifyPublishTx(sweepTx *wire.MsgTx) error { func (s *sweeperStore) GetLastPublishedTx() (*wire.MsgTx, error) { var sweepTx *wire.MsgTx - err := s.db.View(func(tx *bbolt.Tx) error { - lastTxBucket := tx.Bucket(lastTxBucketKey) + err := kvdb.View(s.db, func(tx kvdb.ReadTx) error { + lastTxBucket := tx.ReadBucket(lastTxBucketKey) if lastTxBucket == nil { return errors.New("last tx bucket does not exist") } @@ -225,8 +227,8 @@ func (s *sweeperStore) GetLastPublishedTx() (*wire.MsgTx, error) { func (s *sweeperStore) IsOurTx(hash chainhash.Hash) (bool, error) { var ours bool - err := s.db.View(func(tx *bbolt.Tx) error { - txHashesBucket := tx.Bucket(txHashesBucketKey) + err := kvdb.View(s.db, func(tx kvdb.ReadTx) error { + txHashesBucket := tx.ReadBucket(txHashesBucketKey) if txHashesBucket == nil { return errors.New("tx hashes bucket does not exist") } diff --git a/sweep/store_test.go b/sweep/store_test.go index 6853c7bb0e..23714c781b 100644 --- a/sweep/store_test.go +++ b/sweep/store_test.go @@ -53,7 +53,7 @@ func TestStore(t *testing.T) { testStore(t, func() (SweeperStore, error) { var chain chainhash.Hash - return NewSweeperStore(cdb.DB, &chain) + return NewSweeperStore(cdb, &chain) }) }) t.Run("mock", func(t *testing.T) { From 98170e00ef02d07e4dc83d93f5e7d5656cc64711 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:46:17 -0800 Subject: [PATCH 254/562] lnwallet: convert to use new kvdb abstraction --- lnwallet/interface_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index 6ebb7ff9a6..aae62cf317 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -30,12 +30,12 @@ import ( "github.com/btcsuite/btcwallet/chain" "github.com/btcsuite/btcwallet/walletdb" _ "github.com/btcsuite/btcwallet/walletdb/bdb" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/lightninglabs/neutrino" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs/btcdnotify" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet" @@ -3162,7 +3162,7 @@ func runTests(t *testing.T, walletDriver *lnwallet.WalletDriver, // node's chainstate to initial level, cleanly // wipe buckets if err := clearWalletStates(alice, bob); err != - nil && err != bbolt.ErrBucketNotFound { + nil && err != kvdb.ErrBucketNotFound { t.Fatalf("unable to wipe wallet state: %v", err) } } From f1963084a8ab14b4e0534ff24e7ceb9e12731ff7 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:46:38 -0800 Subject: [PATCH 255/562] chainntnfs: convert to use new kvdb abstraction --- chainntnfs/height_hint_cache.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/chainntnfs/height_hint_cache.go b/chainntnfs/height_hint_cache.go index 25a9247925..b80d3ea72d 100644 --- a/chainntnfs/height_hint_cache.go +++ b/chainntnfs/height_hint_cache.go @@ -4,8 +4,8 @@ import ( "bytes" "errors" - bolt "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) var ( @@ -95,13 +95,13 @@ func NewHeightHintCache(db *channeldb.DB) (*HeightHintCache, error) { // initBuckets ensures that the primary buckets used by the circuit are // initialized so that we can assume their existence after startup. func (c *HeightHintCache) initBuckets() error { - return c.db.Update(func(tx *bolt.Tx) error { - _, err := tx.CreateBucketIfNotExists(spendHintBucket) + return kvdb.Batch(c.db.Backend, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket(spendHintBucket) if err != nil { return err } - _, err = tx.CreateBucketIfNotExists(confirmHintBucket) + _, err = tx.CreateTopLevelBucket(confirmHintBucket) return err }) } @@ -117,8 +117,8 @@ func (c *HeightHintCache) CommitSpendHint(height uint32, Log.Tracef("Updating spend hint to height %d for %v", height, spendRequests) - return c.db.Batch(func(tx *bolt.Tx) error { - spendHints := tx.Bucket(spendHintBucket) + return kvdb.Batch(c.db.Backend, func(tx kvdb.RwTx) error { + spendHints := tx.ReadWriteBucket(spendHintBucket) if spendHints == nil { return ErrCorruptedHeightHintCache } @@ -148,8 +148,8 @@ func (c *HeightHintCache) CommitSpendHint(height uint32, // cache for the outpoint. func (c *HeightHintCache) QuerySpendHint(spendRequest SpendRequest) (uint32, error) { var hint uint32 - err := c.db.View(func(tx *bolt.Tx) error { - spendHints := tx.Bucket(spendHintBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + spendHints := tx.ReadBucket(spendHintBucket) if spendHints == nil { return ErrCorruptedHeightHintCache } @@ -180,8 +180,8 @@ func (c *HeightHintCache) PurgeSpendHint(spendRequests ...SpendRequest) error { Log.Tracef("Removing spend hints for %v", spendRequests) - return c.db.Batch(func(tx *bolt.Tx) error { - spendHints := tx.Bucket(spendHintBucket) + return kvdb.Batch(c.db.Backend, func(tx kvdb.RwTx) error { + spendHints := tx.ReadWriteBucket(spendHintBucket) if spendHints == nil { return ErrCorruptedHeightHintCache } @@ -211,8 +211,8 @@ func (c *HeightHintCache) CommitConfirmHint(height uint32, Log.Tracef("Updating confirm hints to height %d for %v", height, confRequests) - return c.db.Batch(func(tx *bolt.Tx) error { - confirmHints := tx.Bucket(confirmHintBucket) + return kvdb.Batch(c.db.Backend, func(tx kvdb.RwTx) error { + confirmHints := tx.ReadWriteBucket(confirmHintBucket) if confirmHints == nil { return ErrCorruptedHeightHintCache } @@ -242,8 +242,8 @@ func (c *HeightHintCache) CommitConfirmHint(height uint32, // the cache for the transaction hash. func (c *HeightHintCache) QueryConfirmHint(confRequest ConfRequest) (uint32, error) { var hint uint32 - err := c.db.View(func(tx *bolt.Tx) error { - confirmHints := tx.Bucket(confirmHintBucket) + err := kvdb.View(c.db, func(tx kvdb.ReadTx) error { + confirmHints := tx.ReadBucket(confirmHintBucket) if confirmHints == nil { return ErrCorruptedHeightHintCache } @@ -275,8 +275,8 @@ func (c *HeightHintCache) PurgeConfirmHint(confRequests ...ConfRequest) error { Log.Tracef("Removing confirm hints for %v", confRequests) - return c.db.Batch(func(tx *bolt.Tx) error { - confirmHints := tx.Bucket(confirmHintBucket) + return kvdb.Batch(c.db.Backend, func(tx kvdb.RwTx) error { + confirmHints := tx.ReadWriteBucket(confirmHintBucket) if confirmHints == nil { return ErrCorruptedHeightHintCache } From 21521ff610ff0e317d6e9842788c806345364b7d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:46:56 -0800 Subject: [PATCH 256/562] autopilot: convert to use new kvdb abstraction --- autopilot/graph.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autopilot/graph.go b/autopilot/graph.go index 7881380f59..5641bb216e 100644 --- a/autopilot/graph.go +++ b/autopilot/graph.go @@ -10,8 +10,8 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -51,7 +51,7 @@ func ChannelGraphFromDatabase(db *channeldb.ChannelGraph) ChannelGraph { // channeldb.LightningNode. The wrapper method implement the autopilot.Node // interface. type dbNode struct { - tx *bbolt.Tx + tx kvdb.ReadTx node *channeldb.LightningNode } @@ -84,7 +84,7 @@ func (d dbNode) Addrs() []net.Addr { // // NOTE: Part of the autopilot.Node interface. func (d dbNode) ForEachChannel(cb func(ChannelEdge) error) error { - return d.node.ForEachChannel(d.tx, func(tx *bbolt.Tx, + return d.node.ForEachChannel(d.tx, func(tx kvdb.ReadTx, ei *channeldb.ChannelEdgeInfo, ep, _ *channeldb.ChannelEdgePolicy) error { // Skip channels for which no outgoing edge policy is available. @@ -121,7 +121,7 @@ func (d dbNode) ForEachChannel(cb func(ChannelEdge) error) error { // // NOTE: Part of the autopilot.ChannelGraph interface. func (d *databaseChannelGraph) ForEachNode(cb func(Node) error) error { - return d.db.ForEachNode(nil, func(tx *bbolt.Tx, n *channeldb.LightningNode) error { + return d.db.ForEachNode(nil, func(tx kvdb.ReadTx, n *channeldb.LightningNode) error { // We'll skip over any node that doesn't have any advertised // addresses. As we won't be able to reach them to actually From 071c7cbe783b03595b8657add5ca85882c79f569 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 Jan 2020 18:47:38 -0800 Subject: [PATCH 257/562] lnd: convert to use new kvdb abstraction --- breacharbiter.go | 28 +++--- fundingmanager.go | 14 +-- nursery_store.go | 232 ++++++++++++++++++++++++++++++++-------------- rpcserver.go | 12 +-- server.go | 8 +- 5 files changed, 193 insertions(+), 101 deletions(-) diff --git a/breacharbiter.go b/breacharbiter.go index eeee4f8ec6..f454aad3be 100644 --- a/breacharbiter.go +++ b/breacharbiter.go @@ -13,11 +13,11 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" @@ -1237,10 +1237,10 @@ func newRetributionStore(db *channeldb.DB) *retributionStore { // Add adds a retribution state to the retributionStore, which is then persisted // to disk. func (rs *retributionStore) Add(ret *retributionInfo) error { - return rs.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(rs.db, func(tx kvdb.RwTx) error { // If this is our first contract breach, the retributionBucket // won't exist, in which case, we just create a new bucket. - retBucket, err := tx.CreateBucketIfNotExists(retributionBucket) + retBucket, err := tx.CreateTopLevelBucket(retributionBucket) if err != nil { return err } @@ -1264,8 +1264,8 @@ func (rs *retributionStore) Add(ret *retributionInfo) error { // startup and re-register for confirmation notifications. func (rs *retributionStore) Finalize(chanPoint *wire.OutPoint, finalTx *wire.MsgTx) error { - return rs.db.Update(func(tx *bbolt.Tx) error { - justiceBkt, err := tx.CreateBucketIfNotExists(justiceTxnBucket) + return kvdb.Update(rs.db, func(tx kvdb.RwTx) error { + justiceBkt, err := tx.CreateTopLevelBucket(justiceTxnBucket) if err != nil { return err } @@ -1291,8 +1291,8 @@ func (rs *retributionStore) GetFinalizedTxn( chanPoint *wire.OutPoint) (*wire.MsgTx, error) { var finalTxBytes []byte - if err := rs.db.View(func(tx *bbolt.Tx) error { - justiceBkt := tx.Bucket(justiceTxnBucket) + if err := kvdb.View(rs.db, func(tx kvdb.ReadTx) error { + justiceBkt := tx.ReadBucket(justiceTxnBucket) if justiceBkt == nil { return nil } @@ -1325,8 +1325,8 @@ func (rs *retributionStore) GetFinalizedTxn( // that has already been breached. func (rs *retributionStore) IsBreached(chanPoint *wire.OutPoint) (bool, error) { var found bool - err := rs.db.View(func(tx *bbolt.Tx) error { - retBucket := tx.Bucket(retributionBucket) + err := kvdb.View(rs.db, func(tx kvdb.ReadTx) error { + retBucket := tx.ReadBucket(retributionBucket) if retBucket == nil { return nil } @@ -1350,8 +1350,8 @@ func (rs *retributionStore) IsBreached(chanPoint *wire.OutPoint) (bool, error) { // Remove removes a retribution state and finalized justice transaction by // channel point from the retribution store. func (rs *retributionStore) Remove(chanPoint *wire.OutPoint) error { - return rs.db.Update(func(tx *bbolt.Tx) error { - retBucket := tx.Bucket(retributionBucket) + return kvdb.Update(rs.db, func(tx kvdb.RwTx) error { + retBucket := tx.ReadWriteBucket(retributionBucket) // We return an error if the bucket is not already created, // since normal operation of the breach arbiter should never try @@ -1377,7 +1377,7 @@ func (rs *retributionStore) Remove(chanPoint *wire.OutPoint) error { // If we have not finalized this channel breach, we can exit // early. - justiceBkt := tx.Bucket(justiceTxnBucket) + justiceBkt := tx.ReadWriteBucket(justiceTxnBucket) if justiceBkt == nil { return nil } @@ -1389,10 +1389,10 @@ func (rs *retributionStore) Remove(chanPoint *wire.OutPoint) error { // ForAll iterates through all stored retributions and executes the passed // callback function on each retribution. func (rs *retributionStore) ForAll(cb func(*retributionInfo) error) error { - return rs.db.View(func(tx *bbolt.Tx) error { + return kvdb.View(rs.db, func(tx kvdb.ReadTx) error { // If the bucket does not exist, then there are no pending // retributions. - retBucket := tx.Bucket(retributionBucket) + retBucket := tx.ReadBucket(retributionBucket) if retBucket == nil { return nil } diff --git a/fundingmanager.go b/fundingmanager.go index a49e0d4def..0bd64430a4 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -12,12 +12,12 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chanacceptor" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/discovery" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" @@ -3287,9 +3287,9 @@ func copyPubKey(pub *btcec.PublicKey) *btcec.PublicKey { // chanPoint to the channelOpeningStateBucket. func (f *fundingManager) saveChannelOpeningState(chanPoint *wire.OutPoint, state channelOpeningState, shortChanID *lnwire.ShortChannelID) error { - return f.cfg.Wallet.Cfg.Database.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(f.cfg.Wallet.Cfg.Database, func(tx kvdb.RwTx) error { - bucket, err := tx.CreateBucketIfNotExists(channelOpeningStateBucket) + bucket, err := tx.CreateTopLevelBucket(channelOpeningStateBucket) if err != nil { return err } @@ -3317,9 +3317,9 @@ func (f *fundingManager) getChannelOpeningState(chanPoint *wire.OutPoint) ( var state channelOpeningState var shortChanID lnwire.ShortChannelID - err := f.cfg.Wallet.Cfg.Database.View(func(tx *bbolt.Tx) error { + err := kvdb.View(f.cfg.Wallet.Cfg.Database, func(tx kvdb.ReadTx) error { - bucket := tx.Bucket(channelOpeningStateBucket) + bucket := tx.ReadBucket(channelOpeningStateBucket) if bucket == nil { // If the bucket does not exist, it means we never added // a channel to the db, so return ErrChannelNotFound. @@ -3349,8 +3349,8 @@ func (f *fundingManager) getChannelOpeningState(chanPoint *wire.OutPoint) ( // deleteChannelOpeningState removes any state for chanPoint from the database. func (f *fundingManager) deleteChannelOpeningState(chanPoint *wire.OutPoint) error { - return f.cfg.Wallet.Cfg.Database.Update(func(tx *bbolt.Tx) error { - bucket := tx.Bucket(channelOpeningStateBucket) + return kvdb.Update(f.cfg.Wallet.Cfg.Database, func(tx kvdb.RwTx) error { + bucket := tx.ReadWriteBucket(channelOpeningStateBucket) if bucket == nil { return fmt.Errorf("Bucket not found") } diff --git a/nursery_store.go b/nursery_store.go index d7f30d0772..2424dbfc9e 100644 --- a/nursery_store.go +++ b/nursery_store.go @@ -7,8 +7,8 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" ) // Overview of Nursery Store Storage Hierarchy @@ -263,7 +263,7 @@ func newNurseryStore(chainHash *chainhash.Hash, // CSV-delayed outputs (commitment and incoming HTLC's), commitment output and // a list of outgoing two-stage htlc outputs. func (ns *nurseryStore) Incubate(kids []kidOutput, babies []babyOutput) error { - return ns.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(ns.db, func(tx kvdb.RwTx) error { // If we have any kid outputs to incubate, then we'll attempt // to add each of them to the nursery store. Any duplicate // outputs will be ignored. @@ -290,7 +290,7 @@ func (ns *nurseryStore) Incubate(kids []kidOutput, babies []babyOutput) error { // kindergarten bucket. The now mature kidOutput contained in the babyOutput // will be stored as it waits out the kidOutput's CSV delay. func (ns *nurseryStore) CribToKinder(bby *babyOutput) error { - return ns.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(ns.db, func(tx kvdb.RwTx) error { // First, retrieve or create the channel bucket corresponding to // the baby output's origin channel point. @@ -374,7 +374,7 @@ func (ns *nurseryStore) CribToKinder(bby *babyOutput) error { func (ns *nurseryStore) PreschoolToKinder(kid *kidOutput, lastGradHeight uint32) error { - return ns.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(ns.db, func(tx kvdb.RwTx) error { // Create or retrieve the channel bucket corresponding to the // kid output's origin channel point. chanPoint := kid.OriginChanPoint() @@ -471,7 +471,7 @@ func (ns *nurseryStore) PreschoolToKinder(kid *kidOutput, // the height and channel indexes. The height bucket will be opportunistically // pruned from the height index as outputs are removed. func (ns *nurseryStore) GraduateKinder(height uint32, kid *kidOutput) error { - return ns.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(ns.db, func(tx kvdb.RwTx) error { hghtBucket := ns.getHeightBucket(tx, height) if hghtBucket == nil { @@ -501,8 +501,7 @@ func (ns *nurseryStore) GraduateKinder(height uint32, kid *kidOutput) error { return err } - chanBucket := ns.getChannelBucket(tx, - chanPoint) + chanBucket := ns.getChannelBucketWrite(tx, chanPoint) if chanBucket == nil { return ErrContractNotFound } @@ -540,7 +539,7 @@ func (ns *nurseryStore) FetchClass( // processed at the provided block height. var kids []kidOutput var babies []babyOutput - if err := ns.db.View(func(tx *bbolt.Tx) error { + if err := kvdb.View(ns.db, func(tx kvdb.ReadTx) error { // Append each crib output to our list of babyOutputs. if err := ns.forEachHeightPrefix(tx, cribPrefix, height, func(buf []byte) error { @@ -594,16 +593,16 @@ func (ns *nurseryStore) FetchClass( // preschool bucket. func (ns *nurseryStore) FetchPreschools() ([]kidOutput, error) { var kids []kidOutput - if err := ns.db.View(func(tx *bbolt.Tx) error { + if err := kvdb.View(ns.db, func(tx kvdb.ReadTx) error { // Retrieve the existing chain bucket for this nursery store. - chainBucket := tx.Bucket(ns.pfxChainKey) + chainBucket := tx.ReadBucket(ns.pfxChainKey) if chainBucket == nil { return nil } // Load the existing channel index from the chain bucket. - chanIndex := chainBucket.Bucket(channelIndexKey) + chanIndex := chainBucket.NestedReadBucket(channelIndexKey) if chanIndex == nil { return nil } @@ -626,7 +625,7 @@ func (ns *nurseryStore) FetchPreschools() ([]kidOutput, error) { for _, chanBytes := range activeChannels { // Retrieve the channel bucket associated with this // channel. - chanBucket := chanIndex.Bucket(chanBytes) + chanBucket := chanIndex.NestedReadBucket(chanBytes) if chanBucket == nil { continue } @@ -635,7 +634,7 @@ func (ns *nurseryStore) FetchPreschools() ([]kidOutput, error) { // "pscl" prefix. So, we will perform a prefix scan of // the channel bucket to efficiently enumerate all the // desired outputs. - c := chanBucket.Cursor() + c := chanBucket.ReadCursor() for k, v := c.Seek(psclPrefix); bytes.HasPrefix( k, psclPrefix); k, v = c.Next() { @@ -667,16 +666,16 @@ func (ns *nurseryStore) FetchPreschools() ([]kidOutput, error) { // index at or below the provided upper bound. func (ns *nurseryStore) HeightsBelowOrEqual(height uint32) ([]uint32, error) { var activeHeights []uint32 - err := ns.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(ns.db, func(tx kvdb.ReadTx) error { // Ensure that the chain bucket for this nursery store exists. - chainBucket := tx.Bucket(ns.pfxChainKey) + chainBucket := tx.ReadBucket(ns.pfxChainKey) if chainBucket == nil { return nil } // Ensure that the height index has been properly initialized for this // chain. - hghtIndex := chainBucket.Bucket(heightIndexKey) + hghtIndex := chainBucket.NestedReadBucket(heightIndexKey) if hghtIndex == nil { return nil } @@ -686,7 +685,7 @@ func (ns *nurseryStore) HeightsBelowOrEqual(height uint32) ([]uint32, error) { var lower, upper [4]byte byteOrder.PutUint32(upper[:], height) - c := hghtIndex.Cursor() + c := hghtIndex.ReadCursor() for k, _ := c.Seek(lower[:]); bytes.Compare(k, upper[:]) <= 0 && len(k) == 4; k, _ = c.Next() { @@ -712,7 +711,7 @@ func (ns *nurseryStore) HeightsBelowOrEqual(height uint32) ([]uint32, error) { func (ns *nurseryStore) ForChanOutputs(chanPoint *wire.OutPoint, callback func([]byte, []byte) error) error { - return ns.db.View(func(tx *bbolt.Tx) error { + return kvdb.View(ns.db, func(tx kvdb.ReadTx) error { return ns.forChanOutputs(tx, chanPoint, callback) }) } @@ -720,15 +719,15 @@ func (ns *nurseryStore) ForChanOutputs(chanPoint *wire.OutPoint, // ListChannels returns all channels the nursery is currently tracking. func (ns *nurseryStore) ListChannels() ([]wire.OutPoint, error) { var activeChannels []wire.OutPoint - if err := ns.db.View(func(tx *bbolt.Tx) error { + if err := kvdb.View(ns.db, func(tx kvdb.ReadTx) error { // Retrieve the existing chain bucket for this nursery store. - chainBucket := tx.Bucket(ns.pfxChainKey) + chainBucket := tx.ReadBucket(ns.pfxChainKey) if chainBucket == nil { return nil } // Retrieve the existing channel index. - chanIndex := chainBucket.Bucket(channelIndexKey) + chanIndex := chainBucket.NestedReadBucket(channelIndexKey) if chanIndex == nil { return nil } @@ -754,7 +753,7 @@ func (ns *nurseryStore) ListChannels() ([]wire.OutPoint, error) { // IsMatureChannel determines the whether or not all of the outputs in a // particular channel bucket have been marked as graduated. func (ns *nurseryStore) IsMatureChannel(chanPoint *wire.OutPoint) (bool, error) { - err := ns.db.View(func(tx *bbolt.Tx) error { + err := kvdb.View(ns.db, func(tx kvdb.ReadTx) error { // Iterate over the contents of the channel bucket, computing // both total number of outputs, and those that have the grad // prefix. @@ -783,15 +782,15 @@ var ErrImmatureChannel = errors.New("cannot remove immature channel, " + // provided channel point. // NOTE: The channel's entries in the height index are assumed to be removed. func (ns *nurseryStore) RemoveChannel(chanPoint *wire.OutPoint) error { - return ns.db.Update(func(tx *bbolt.Tx) error { + return kvdb.Update(ns.db, func(tx kvdb.RwTx) error { // Retrieve the existing chain bucket for this nursery store. - chainBucket := tx.Bucket(ns.pfxChainKey) + chainBucket := tx.ReadWriteBucket(ns.pfxChainKey) if chainBucket == nil { return nil } // Retrieve the channel index stored in the chain bucket. - chanIndex := chainBucket.Bucket(channelIndexKey) + chanIndex := chainBucket.NestedReadWriteBucket(channelIndexKey) if chanIndex == nil { return nil } @@ -824,7 +823,7 @@ func (ns *nurseryStore) RemoveChannel(chanPoint *wire.OutPoint) error { maturityHeight := kid.ConfHeight() + kid.BlocksToMaturity() - hghtBucket := ns.getHeightBucket(tx, maturityHeight) + hghtBucket := ns.getHeightBucketWrite(tx, maturityHeight) if hghtBucket == nil { return nil } @@ -845,7 +844,7 @@ func (ns *nurseryStore) RemoveChannel(chanPoint *wire.OutPoint) error { // its two-stage process of sweeping funds back to the user's wallet. These // outputs are persisted in the nursery store in the crib state, and will be // revisited after the first-stage output's CLTV has expired. -func (ns *nurseryStore) enterCrib(tx *bbolt.Tx, baby *babyOutput) error { +func (ns *nurseryStore) enterCrib(tx kvdb.RwTx, baby *babyOutput) error { // First, retrieve or create the channel bucket corresponding to the // baby output's origin channel point. chanPoint := baby.OriginChanPoint() @@ -902,7 +901,7 @@ func (ns *nurseryStore) enterCrib(tx *bbolt.Tx, baby *babyOutput) error { // through a single stage before sweeping. Outputs are stored in the preschool // bucket until the commitment transaction has been confirmed, at which point // they will be moved to the kindergarten bucket. -func (ns *nurseryStore) enterPreschool(tx *bbolt.Tx, kid *kidOutput) error { +func (ns *nurseryStore) enterPreschool(tx kvdb.RwTx, kid *kidOutput) error { // First, retrieve or create the channel bucket corresponding to the // baby output's origin channel point. chanPoint := kid.OriginChanPoint() @@ -935,11 +934,11 @@ func (ns *nurseryStore) enterPreschool(tx *bbolt.Tx, kid *kidOutput) error { // createChannelBucket creates or retrieves a channel bucket for the provided // channel point. -func (ns *nurseryStore) createChannelBucket(tx *bbolt.Tx, - chanPoint *wire.OutPoint) (*bbolt.Bucket, error) { +func (ns *nurseryStore) createChannelBucket(tx kvdb.RwTx, + chanPoint *wire.OutPoint) (kvdb.RwBucket, error) { // Ensure that the chain bucket for this nursery store exists. - chainBucket, err := tx.CreateBucketIfNotExists(ns.pfxChainKey) + chainBucket, err := tx.CreateTopLevelBucket(ns.pfxChainKey) if err != nil { return nil, err } @@ -966,17 +965,17 @@ func (ns *nurseryStore) createChannelBucket(tx *bbolt.Tx, // getChannelBucket retrieves an existing channel bucket from the nursery store, // using the given channel point. If the bucket does not exist, or any bucket // along its path does not exist, a nil value is returned. -func (ns *nurseryStore) getChannelBucket(tx *bbolt.Tx, - chanPoint *wire.OutPoint) *bbolt.Bucket { +func (ns *nurseryStore) getChannelBucket(tx kvdb.ReadTx, + chanPoint *wire.OutPoint) kvdb.ReadBucket { // Retrieve the existing chain bucket for this nursery store. - chainBucket := tx.Bucket(ns.pfxChainKey) + chainBucket := tx.ReadBucket(ns.pfxChainKey) if chainBucket == nil { return nil } // Retrieve the existing channel index. - chanIndex := chainBucket.Bucket(channelIndexKey) + chanIndex := chainBucket.NestedReadBucket(channelIndexKey) if chanIndex == nil { return nil } @@ -988,16 +987,44 @@ func (ns *nurseryStore) getChannelBucket(tx *bbolt.Tx, return nil } - return chanIndex.Bucket(chanBuffer.Bytes()) + return chanIndex.NestedReadBucket(chanBuffer.Bytes()) +} + +// getChannelBucketWrite retrieves an existing channel bucket from the nursery store, +// using the given channel point. If the bucket does not exist, or any bucket +// along its path does not exist, a nil value is returned. +func (ns *nurseryStore) getChannelBucketWrite(tx kvdb.RwTx, + chanPoint *wire.OutPoint) kvdb.RwBucket { + + // Retrieve the existing chain bucket for this nursery store. + chainBucket := tx.ReadWriteBucket(ns.pfxChainKey) + if chainBucket == nil { + return nil + } + + // Retrieve the existing channel index. + chanIndex := chainBucket.NestedReadWriteBucket(channelIndexKey) + if chanIndex == nil { + return nil + } + + // Serialize the provided channel point and return the bucket matching + // the serialized key. + var chanBuffer bytes.Buffer + if err := writeOutpoint(&chanBuffer, chanPoint); err != nil { + return nil + } + + return chanIndex.NestedReadWriteBucket(chanBuffer.Bytes()) } // createHeightBucket creates or retrieves an existing bucket from the height // index, corresponding to the provided height. -func (ns *nurseryStore) createHeightBucket(tx *bbolt.Tx, - height uint32) (*bbolt.Bucket, error) { +func (ns *nurseryStore) createHeightBucket(tx kvdb.RwTx, + height uint32) (kvdb.RwBucket, error) { // Ensure that the chain bucket for this nursery store exists. - chainBucket, err := tx.CreateBucketIfNotExists(ns.pfxChainKey) + chainBucket, err := tx.CreateTopLevelBucket(ns.pfxChainKey) if err != nil { return nil, err } @@ -1021,17 +1048,17 @@ func (ns *nurseryStore) createHeightBucket(tx *bbolt.Tx, // getHeightBucketPath retrieves an existing height bucket from the nursery // store, using the provided block height. If the bucket does not exist, or any // bucket along its path does not exist, a nil value is returned. -func (ns *nurseryStore) getHeightBucketPath(tx *bbolt.Tx, - height uint32) (*bbolt.Bucket, *bbolt.Bucket, *bbolt.Bucket) { +func (ns *nurseryStore) getHeightBucketPath(tx kvdb.ReadTx, + height uint32) (kvdb.ReadBucket, kvdb.ReadBucket, kvdb.ReadBucket) { // Retrieve the existing chain bucket for this nursery store. - chainBucket := tx.Bucket(ns.pfxChainKey) + chainBucket := tx.ReadBucket(ns.pfxChainKey) if chainBucket == nil { return nil, nil, nil } // Retrieve the existing channel index. - hghtIndex := chainBucket.Bucket(heightIndexKey) + hghtIndex := chainBucket.NestedReadBucket(heightIndexKey) if hghtIndex == nil { return nil, nil, nil } @@ -1041,24 +1068,63 @@ func (ns *nurseryStore) getHeightBucketPath(tx *bbolt.Tx, var heightBytes [4]byte byteOrder.PutUint32(heightBytes[:], height) - return chainBucket, hghtIndex, hghtIndex.Bucket(heightBytes[:]) + return chainBucket, hghtIndex, hghtIndex.NestedReadBucket(heightBytes[:]) +} + +// getHeightBucketPathWrite retrieves an existing height bucket from the nursery +// store, using the provided block height. If the bucket does not exist, or any +// bucket along its path does not exist, a nil value is returned. +func (ns *nurseryStore) getHeightBucketPathWrite(tx kvdb.RwTx, + height uint32) (kvdb.RwBucket, kvdb.RwBucket, kvdb.RwBucket) { + + // Retrieve the existing chain bucket for this nursery store. + chainBucket := tx.ReadWriteBucket(ns.pfxChainKey) + if chainBucket == nil { + return nil, nil, nil + } + + // Retrieve the existing channel index. + hghtIndex := chainBucket.NestedReadWriteBucket(heightIndexKey) + if hghtIndex == nil { + return nil, nil, nil + } + + // Serialize the provided block height and return the bucket matching + // the serialized key. + var heightBytes [4]byte + byteOrder.PutUint32(heightBytes[:], height) + + return chainBucket, hghtIndex, hghtIndex.NestedReadWriteBucket( + heightBytes[:], + ) } // getHeightBucket retrieves an existing height bucket from the nursery store, // using the provided block height. If the bucket does not exist, or any bucket // along its path does not exist, a nil value is returned. -func (ns *nurseryStore) getHeightBucket(tx *bbolt.Tx, - height uint32) *bbolt.Bucket { +func (ns *nurseryStore) getHeightBucket(tx kvdb.ReadTx, + height uint32) kvdb.ReadBucket { _, _, hghtBucket := ns.getHeightBucketPath(tx, height) return hghtBucket } +// getHeightBucketWrite retrieves an existing height bucket from the nursery store, +// using the provided block height. If the bucket does not exist, or any bucket +// along its path does not exist, a nil value is returned. +func (ns *nurseryStore) getHeightBucketWrite(tx kvdb.RwTx, + height uint32) kvdb.RwBucket { + + _, _, hghtBucket := ns.getHeightBucketPathWrite(tx, height) + + return hghtBucket +} + // createHeightChanBucket creates or retrieves an existing height-channel bucket // for the provided block height and channel point. This method will attempt to // instantiate all buckets along the path if required. -func (ns *nurseryStore) createHeightChanBucket(tx *bbolt.Tx, - height uint32, chanPoint *wire.OutPoint) (*bbolt.Bucket, error) { +func (ns *nurseryStore) createHeightChanBucket(tx kvdb.RwTx, + height uint32, chanPoint *wire.OutPoint) (kvdb.RwBucket, error) { // Ensure that the height bucket for this nursery store exists. hghtBucket, err := ns.createHeightBucket(tx, height) @@ -1083,8 +1149,8 @@ func (ns *nurseryStore) createHeightChanBucket(tx *bbolt.Tx, // nursery store, using the provided block height and channel point. if the // bucket does not exist, or any bucket along its path does not exist, a nil // value is returned. -func (ns *nurseryStore) getHeightChanBucket(tx *bbolt.Tx, - height uint32, chanPoint *wire.OutPoint) *bbolt.Bucket { +func (ns *nurseryStore) getHeightChanBucket(tx kvdb.ReadTx, + height uint32, chanPoint *wire.OutPoint) kvdb.ReadBucket { // Retrieve the existing height bucket from this nursery store. hghtBucket := ns.getHeightBucket(tx, height) @@ -1102,7 +1168,33 @@ func (ns *nurseryStore) getHeightChanBucket(tx *bbolt.Tx, // Finally, return the height bucket specified by the serialized channel // point. - return hghtBucket.Bucket(chanBytes) + return hghtBucket.NestedReadBucket(chanBytes) +} + +// getHeightChanBucketWrite retrieves an existing height-channel bucket from the +// nursery store, using the provided block height and channel point. if the +// bucket does not exist, or any bucket along its path does not exist, a nil +// value is returned. +func (ns *nurseryStore) getHeightChanBucketWrite(tx kvdb.RwTx, + height uint32, chanPoint *wire.OutPoint) kvdb.RwBucket { + + // Retrieve the existing height bucket from this nursery store. + hghtBucket := ns.getHeightBucketWrite(tx, height) + if hghtBucket == nil { + return nil + } + + // Serialize the provided channel point, which generates the key for + // looking up the proper height-channel bucket inside the height bucket. + var chanBuffer bytes.Buffer + if err := writeOutpoint(&chanBuffer, chanPoint); err != nil { + return nil + } + chanBytes := chanBuffer.Bytes() + + // Finally, return the height bucket specified by the serialized channel + // point. + return hghtBucket.NestedReadWriteBucket(chanBytes) } // forEachHeightPrefix enumerates all outputs at the given height whose state @@ -1110,7 +1202,7 @@ func (ns *nurseryStore) getHeightChanBucket(tx *bbolt.Tx, // enumerate crib and kindergarten outputs at a particular height. The callback // is invoked with serialized bytes retrieved for each output of interest, // allowing the caller to deserialize them into the appropriate type. -func (ns *nurseryStore) forEachHeightPrefix(tx *bbolt.Tx, prefix []byte, +func (ns *nurseryStore) forEachHeightPrefix(tx kvdb.ReadTx, prefix []byte, height uint32, callback func([]byte) error) error { // Start by retrieving the height bucket corresponding to the provided @@ -1138,7 +1230,7 @@ func (ns *nurseryStore) forEachHeightPrefix(tx *bbolt.Tx, prefix []byte, // Additionally, grab the chain index, which we will facilitate queries // for each of the channel buckets of each of the channels in the list // we assembled above. - chanIndex := chainBucket.Bucket(channelIndexKey) + chanIndex := chainBucket.NestedReadBucket(channelIndexKey) if chanIndex == nil { return errors.New("unable to retrieve channel index") } @@ -1151,7 +1243,7 @@ func (ns *nurseryStore) forEachHeightPrefix(tx *bbolt.Tx, prefix []byte, for _, chanBytes := range channelsAtHeight { // Retrieve the height-channel bucket for this channel, which // holds a sub-bucket for all outputs maturing at this height. - hghtChanBucket := hghtBucket.Bucket(chanBytes) + hghtChanBucket := hghtBucket.NestedReadBucket(chanBytes) if hghtChanBucket == nil { return fmt.Errorf("unable to retrieve height-channel "+ "bucket at height %d for %x", height, chanBytes) @@ -1160,7 +1252,7 @@ func (ns *nurseryStore) forEachHeightPrefix(tx *bbolt.Tx, prefix []byte, // Load the appropriate channel bucket from the channel index, // this will allow us to retrieve the individual serialized // outputs. - chanBucket := chanIndex.Bucket(chanBytes) + chanBucket := chanIndex.NestedReadBucket(chanBytes) if chanBucket == nil { return fmt.Errorf("unable to retrieve channel "+ "bucket: '%x'", chanBytes) @@ -1170,7 +1262,7 @@ func (ns *nurseryStore) forEachHeightPrefix(tx *bbolt.Tx, prefix []byte, // prefix, we will perform a prefix scan of the buckets // contained in the height-channel bucket, efficiently // enumerating the desired outputs. - c := hghtChanBucket.Cursor() + c := hghtChanBucket.ReadCursor() for k, _ := c.Seek(prefix); bytes.HasPrefix( k, prefix); k, _ = c.Next() { @@ -1198,7 +1290,7 @@ func (ns *nurseryStore) forEachHeightPrefix(tx *bbolt.Tx, prefix []byte, // provided callback. The callback accepts a key-value pair of byte slices // corresponding to the prefixed-output key and the serialized output, // respectively. -func (ns *nurseryStore) forChanOutputs(tx *bbolt.Tx, chanPoint *wire.OutPoint, +func (ns *nurseryStore) forChanOutputs(tx kvdb.ReadTx, chanPoint *wire.OutPoint, callback func([]byte, []byte) error) error { chanBucket := ns.getChannelBucket(tx, chanPoint) @@ -1216,11 +1308,11 @@ var errBucketNotEmpty = errors.New("bucket is not empty, cannot be pruned") // removeOutputFromHeight will delete the given output from the specified // height-channel bucket, and attempt to prune the upstream directories if they // are empty. -func (ns *nurseryStore) removeOutputFromHeight(tx *bbolt.Tx, height uint32, +func (ns *nurseryStore) removeOutputFromHeight(tx kvdb.RwTx, height uint32, chanPoint *wire.OutPoint, pfxKey []byte) error { // Retrieve the height-channel bucket and delete the prefixed output. - hghtChanBucket := ns.getHeightChanBucket(tx, height, chanPoint) + hghtChanBucket := ns.getHeightChanBucketWrite(tx, height, chanPoint) if hghtChanBucket == nil { // Height-channel bucket already removed. return nil @@ -1233,7 +1325,7 @@ func (ns *nurseryStore) removeOutputFromHeight(tx *bbolt.Tx, height uint32, } // Retrieve the height bucket that contains the height-channel bucket. - hghtBucket := ns.getHeightBucket(tx, height) + hghtBucket := ns.getHeightBucketWrite(tx, height) if hghtBucket == nil { return errors.New("height bucket not found") } @@ -1268,9 +1360,9 @@ func (ns *nurseryStore) removeOutputFromHeight(tx *bbolt.Tx, height uint32, // all active outputs at this height have been removed from their respective // height-channel buckets. The returned boolean value indicated whether or not // this invocation successfully pruned the height bucket. -func (ns *nurseryStore) pruneHeight(tx *bbolt.Tx, height uint32) (bool, error) { +func (ns *nurseryStore) pruneHeight(tx kvdb.RwTx, height uint32) (bool, error) { // Fetch the existing height index and height bucket. - _, hghtIndex, hghtBucket := ns.getHeightBucketPath(tx, height) + _, hghtIndex, hghtBucket := ns.getHeightBucketPathWrite(tx, height) if hghtBucket == nil { return false, nil } @@ -1287,7 +1379,7 @@ func (ns *nurseryStore) pruneHeight(tx *bbolt.Tx, height uint32) (bool, error) { // Attempt to each height-channel bucket from the height bucket // located above. - hghtChanBucket := hghtBucket.Bucket(chanBytes) + hghtChanBucket := hghtBucket.NestedReadWriteBucket(chanBytes) if hghtChanBucket == nil { return errors.New("unable to find height-channel bucket") } @@ -1315,9 +1407,9 @@ func (ns *nurseryStore) pruneHeight(tx *bbolt.Tx, height uint32) (bool, error) { // removeBucketIfEmpty attempts to delete a bucket specified by name from the // provided parent bucket. -func removeBucketIfEmpty(parent *bbolt.Bucket, bktName []byte) error { +func removeBucketIfEmpty(parent kvdb.RwBucket, bktName []byte) error { // Attempt to fetch the named bucket from its parent. - bkt := parent.Bucket(bktName) + bkt := parent.NestedReadWriteBucket(bktName) if bkt == nil { // No bucket was found, already removed? return nil @@ -1328,25 +1420,25 @@ func removeBucketIfEmpty(parent *bbolt.Bucket, bktName []byte) error { return err } - return parent.DeleteBucket(bktName) + return parent.DeleteNestedBucket(bktName) } // removeBucketIfExists safely deletes the named bucket by first checking // that it exists in the parent bucket. -func removeBucketIfExists(parent *bbolt.Bucket, bktName []byte) error { +func removeBucketIfExists(parent kvdb.RwBucket, bktName []byte) error { // Attempt to fetch the named bucket from its parent. - bkt := parent.Bucket(bktName) + bkt := parent.NestedReadWriteBucket(bktName) if bkt == nil { // No bucket was found, already removed? return nil } - return parent.DeleteBucket(bktName) + return parent.DeleteNestedBucket(bktName) } // isBucketEmpty returns errBucketNotEmpty if the bucket has a non-zero number // of children. -func isBucketEmpty(parent *bbolt.Bucket) error { +func isBucketEmpty(parent kvdb.ReadBucket) error { return parent.ForEach(func(_, _ []byte) error { return errBucketNotEmpty }) diff --git a/rpcserver.go b/rpcserver.go index 700c572ae5..433491002a 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -23,7 +23,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwallet/wallet/txauthor" - "github.com/coreos/bbolt" "github.com/davecgh/go-spew/spew" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" proxy "github.com/grpc-ecosystem/grpc-gateway/runtime" @@ -33,6 +32,7 @@ import ( "github.com/lightningnetwork/lnd/chanbackup" "github.com/lightningnetwork/lnd/chanfitness" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/discovery" @@ -4494,7 +4494,7 @@ func (r *rpcServer) DescribeGraph(ctx context.Context, // First iterate through all the known nodes (connected or unconnected // within the graph), collating their current state into the RPC // response. - err := graph.ForEachNode(nil, func(_ *bbolt.Tx, node *channeldb.LightningNode) error { + err := graph.ForEachNode(nil, func(_ kvdb.ReadTx, node *channeldb.LightningNode) error { nodeAddrs := make([]*lnrpc.NodeAddress, 0) for _, addr := range node.Addresses { nodeAddr := &lnrpc.NodeAddress{ @@ -4652,7 +4652,7 @@ func (r *rpcServer) GetNodeInfo(ctx context.Context, channels []*lnrpc.ChannelEdge ) - if err := node.ForEachChannel(nil, func(_ *bbolt.Tx, + if err := node.ForEachChannel(nil, func(_ kvdb.ReadTx, edge *channeldb.ChannelEdgeInfo, c1, c2 *channeldb.ChannelEdgePolicy) error { @@ -4750,7 +4750,7 @@ func (r *rpcServer) GetNetworkInfo(ctx context.Context, // network, tallying up the total number of nodes, and also gathering // each node so we can measure the graph diameter and degree stats // below. - if err := graph.ForEachNode(nil, func(tx *bbolt.Tx, node *channeldb.LightningNode) error { + if err := graph.ForEachNode(nil, func(tx kvdb.ReadTx, node *channeldb.LightningNode) error { // Increment the total number of nodes with each iteration. numNodes++ @@ -4760,7 +4760,7 @@ func (r *rpcServer) GetNetworkInfo(ctx context.Context, // through the db transaction from the outer view so we can // re-use it within this inner view. var outDegree uint32 - if err := node.ForEachChannel(tx, func(_ *bbolt.Tx, + if err := node.ForEachChannel(tx, func(_ kvdb.ReadTx, edge *channeldb.ChannelEdgeInfo, _, _ *channeldb.ChannelEdgePolicy) error { // Bump up the out degree for this node for each @@ -5225,7 +5225,7 @@ func (r *rpcServer) FeeReport(ctx context.Context, } var feeReports []*lnrpc.ChannelFeeReport - err = selfNode.ForEachChannel(nil, func(_ *bbolt.Tx, chanInfo *channeldb.ChannelEdgeInfo, + err = selfNode.ForEachChannel(nil, func(_ kvdb.ReadTx, chanInfo *channeldb.ChannelEdgeInfo, edgePolicy, _ *channeldb.ChannelEdgePolicy) error { // Self node should always have policies for its channels. diff --git a/server.go b/server.go index 98f446d7b3..6792981c42 100644 --- a/server.go +++ b/server.go @@ -23,7 +23,6 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - "github.com/coreos/bbolt" "github.com/go-errors/errors" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/autopilot" @@ -32,6 +31,7 @@ import ( "github.com/lightningnetwork/lnd/chanbackup" "github.com/lightningnetwork/lnd/chanfitness" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/contractcourt" @@ -708,7 +708,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, routingConfig := routerrpc.GetRoutingConfig(cfg.SubRPCServers.RouterRPC) s.missionControl, err = routing.NewMissionControl( - chanDB.DB, + chanDB, &routing.MissionControlConfig{ AprioriHopProbability: routingConfig.AprioriHopProbability, PenaltyHalfLife: routingConfig.PenaltyHalfLife, @@ -820,7 +820,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, sweep.DefaultBatchWindowDuration) sweeperStore, err := sweep.NewSweeperStore( - chanDB.DB, activeNetParams.GenesisHash, + chanDB, activeNetParams.GenesisHash, ) if err != nil { srvrLog.Errorf("unable to create sweeper store: %v", err) @@ -2126,7 +2126,7 @@ func (s *server) establishPersistentConnections() error { // each of the nodes. selfPub := s.identityPriv.PubKey().SerializeCompressed() err = sourceNode.ForEachChannel(nil, func( - tx *bbolt.Tx, + tx kvdb.ReadTx, chanInfo *channeldb.ChannelEdgeInfo, policy, _ *channeldb.ChannelEdgePolicy) error { From a4e39906b133f90cb18fb33e6c615e52109791ca Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 15 Jan 2020 17:32:59 -0800 Subject: [PATCH 258/562] build: silence new linter errors, tidy modules The explicit `bbolt` dep is gone, as we depend on `kvdb`, which is actually `walletdb`, which has its own module that defines the proper `bbolt` version. --- channeldb/channel.go | 6 +++--- channeldb/forwarding_package_test.go | 2 +- channeldb/graph.go | 4 ++-- channeldb/meta_test.go | 8 +++++--- go.mod | 2 -- go.sum | 7 ------- nursery_store.go | 2 +- 7 files changed, 12 insertions(+), 19 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 2d44dd1093..c784837ed8 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -764,7 +764,7 @@ func fetchChanBucket(tx kvdb.ReadTx, nodeKey *btcec.PublicKey, // channel's data resides in given: the public key for the node, the outpoint, // and the chainhash that the channel resides on. This differs from // fetchChanBucket in that it returns a writeable bucket. -func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey, +func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey, // nolint:interfacer outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RwBucket, error) { readBucket, err := fetchChanBucket(tx, nodeKey, outPoint, chainHash) @@ -2465,7 +2465,7 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary, // Now that the index to this channel has been deleted, purge // the remaining channel metadata from the database. - err = deleteOpenChannel(chanBucket, chanPointBuf.Bytes()) + err = deleteOpenChannel(chanBucket) if err != nil { return err } @@ -3108,7 +3108,7 @@ func fetchChanRevocationState(chanBucket kvdb.ReadBucket, channel *OpenChannel) return ReadElements(r, &channel.RemoteNextRevocation) } -func deleteOpenChannel(chanBucket kvdb.RwBucket, chanPointBytes []byte) error { +func deleteOpenChannel(chanBucket kvdb.RwBucket) error { if err := chanBucket.Delete(chanInfoKey); err != nil { return err diff --git a/channeldb/forwarding_package_test.go b/channeldb/forwarding_package_test.go index 52eaa0e05f..ed18b6bc39 100644 --- a/channeldb/forwarding_package_test.go +++ b/channeldb/forwarding_package_test.go @@ -795,7 +795,7 @@ func loadFwdPkgs(t *testing.T, db kvdb.Backend, // makeFwdPkgDB initializes a test database for forwarding packages. If the // provided path is an empty, it will create a temp dir/file to use. -func makeFwdPkgDB(t *testing.T, path string) kvdb.Backend { +func makeFwdPkgDB(t *testing.T, path string) kvdb.Backend { // nolint:unparam if path == "" { var err error path, err = ioutil.TempDir("", "fwdpkgdb") diff --git a/channeldb/graph.go b/channeldb/graph.go index efa3dcbb0e..e0105043a5 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -328,7 +328,7 @@ func (c *ChannelGraph) DisabledChannelIDs() ([]uint64, error) { // // TODO(roasbeef): add iterator interface to allow for memory efficient graph // traversal when graph gets mega -func (c *ChannelGraph) ForEachNode(tx kvdb.RwTx, cb func(kvdb.ReadTx, *LightningNode) error) error { +func (c *ChannelGraph) ForEachNode(tx kvdb.RwTx, cb func(kvdb.ReadTx, *LightningNode) error) error { // nolint:interfacer traversal := func(tx kvdb.ReadTx) error { // First grab the nodes bucket which stores the mapping from // pubKey to node information. @@ -3328,7 +3328,7 @@ func (c *ChannelGraph) NumZombies() (uint64, error) { return numZombies, nil } -func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, +func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, // nolint:dupl updateIndex kvdb.RwBucket, node *LightningNode) error { var ( diff --git a/channeldb/meta_test.go b/channeldb/meta_test.go index b72495d532..1933c0e161 100644 --- a/channeldb/meta_test.go +++ b/channeldb/meta_test.go @@ -345,15 +345,17 @@ func TestMigrationWithoutErrors(t *testing.T) { // Populate database with initial data. beforeMigrationFunc := func(d *DB) { - kvdb.Update(d, func(tx kvdb.RwTx) error { + err := kvdb.Update(d, func(tx kvdb.RwTx) error { bucket, err := tx.CreateTopLevelBucket(bucketPrefix) if err != nil { return err } - bucket.Put(keyPrefix, beforeMigration) - return nil + return bucket.Put(keyPrefix, beforeMigration) }) + if err != nil { + t.Fatalf("unable to update db pre migration: %v", err) + } } // Create migration function which changes the initially created data. diff --git a/go.mod b/go.mod index 55e4fea1e1..812f824fab 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,6 @@ require ( github.com/btcsuite/btcwallet/walletdb v1.2.0 github.com/btcsuite/btcwallet/wtxmgr v1.0.0 github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 - github.com/coreos/bbolt v1.3.3 github.com/davecgh/go-spew v1.1.1 github.com/go-errors/errors v1.0.1 github.com/golang/protobuf v1.3.1 @@ -45,7 +44,6 @@ require ( github.com/rogpeppe/fastuuid v1.2.0 // indirect github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 github.com/urfave/cli v1.18.0 - go.etcd.io/bbolt v1.3.3 golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 diff --git a/go.sum b/go.sum index c2773b2e59..b8991183ef 100644 --- a/go.sum +++ b/go.sum @@ -185,9 +185,6 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9QSINo2CUPM/cySEvw2w8I0= -golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -199,8 +196,6 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80= golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -213,8 +208,6 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/nursery_store.go b/nursery_store.go index 2424dbfc9e..bc20d1bc2c 100644 --- a/nursery_store.go +++ b/nursery_store.go @@ -1149,7 +1149,7 @@ func (ns *nurseryStore) createHeightChanBucket(tx kvdb.RwTx, // nursery store, using the provided block height and channel point. if the // bucket does not exist, or any bucket along its path does not exist, a nil // value is returned. -func (ns *nurseryStore) getHeightChanBucket(tx kvdb.ReadTx, +func (ns *nurseryStore) getHeightChanBucket(tx kvdb.ReadTx, // nolint:unused height uint32, chanPoint *wire.OutPoint) kvdb.ReadBucket { // Retrieve the existing height bucket from this nursery store. From 4e47181b99ff3075e446f7f3f01e07d86619911e Mon Sep 17 00:00:00 2001 From: ErikEk Date: Thu, 19 Mar 2020 05:43:49 +0100 Subject: [PATCH 259/562] trivial: typo fix --- lnd.go | 2 +- lnwallet/chanfunding/assembler.go | 2 +- lnwallet/wallet.go | 2 +- sweep/interface.go | 2 +- sweep/store_test.go | 2 +- sweep/sweeper.go | 10 +++++----- sweep/sweeper_test.go | 6 +++--- sweep/test_utils.go | 2 +- sweep/walletsweep.go | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lnd.go b/lnd.go index a080f5a7b2..3e6ed885b1 100644 --- a/lnd.go +++ b/lnd.go @@ -118,7 +118,7 @@ func AdminAuthOptions() ([]grpc.DialOption, error) { return opts, nil } -// ListnerWithSignal is a net.Listner that has an additional Ready channel that +// ListenerWithSignal is a net.Listener that has an additional Ready channel that // will be closed when a server starts listening. type ListenerWithSignal struct { net.Listener diff --git a/lnwallet/chanfunding/assembler.go b/lnwallet/chanfunding/assembler.go index e320d9eebc..d06de903dc 100644 --- a/lnwallet/chanfunding/assembler.go +++ b/lnwallet/chanfunding/assembler.go @@ -27,7 +27,7 @@ type CoinSource interface { type CoinSelectionLocker interface { // WithCoinSelectLock will execute the passed function closure in a // synchronized manner preventing any coin selection operations from - // proceeding while the closure if executing. This can be seen as the + // proceeding while the closure is executing. This can be seen as the // ability to execute a function closure under an exclusive coin // selection lock. WithCoinSelectLock(func() error) error diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 73eaf2178a..dbada608b9 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -1435,7 +1435,7 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) { // WithCoinSelectLock will execute the passed function closure in a // synchronized manner preventing any coin selection operations from proceeding -// while the closure if executing. This can be seen as the ability to execute a +// while the closure is executing. This can be seen as the ability to execute a // function closure under an exclusive coin selection lock. func (l *LightningWallet) WithCoinSelectLock(f func() error) error { l.coinSelectMtx.Lock() diff --git a/sweep/interface.go b/sweep/interface.go index 948d8ddfd4..a9ff82cc61 100644 --- a/sweep/interface.go +++ b/sweep/interface.go @@ -20,7 +20,7 @@ type Wallet interface { // WithCoinSelectLock will execute the passed function closure in a // synchronized manner preventing any coin selection operations from - // proceeding while the closure if executing. This can be seen as the + // proceeding while the closure is executing. This can be seen as the // ability to execute a function closure under an exclusive coin // selection lock. WithCoinSelectLock(f func() error) error diff --git a/sweep/store_test.go b/sweep/store_test.go index 6853c7bb0e..29456558d5 100644 --- a/sweep/store_test.go +++ b/sweep/store_test.go @@ -141,7 +141,7 @@ func testStore(t *testing.T, createStore func() (SweeperStore, error)) { t.Fatal("expected tx to be ours") } - // An different hash should be reported on as not being ours. + // An different hash should be reported as not being ours. var unknownHash chainhash.Hash ours, err = store.IsOurTx(unknownHash) if err != nil { diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 5997149348..eb88aef433 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -57,7 +57,7 @@ var ( // ErrSweeperShuttingDown is an error returned when a client attempts to // make a request to the UtxoSweeper, but it is unable to handle it as - // it is/has already been stoppepd. + // it is/has already been stopped. ErrSweeperShuttingDown = errors.New("utxo sweeper shutting down") // DefaultMaxSweepAttempts specifies the default maximum number of times @@ -422,7 +422,7 @@ func (s *UtxoSweeper) SweepInput(input input.Input, resultChan: make(chan Result, 1), } - // Deliver input to main event loop. + // Deliver input to the main event loop. select { case s.newInputs <- sweeperInput: case <-s.quit: @@ -449,7 +449,7 @@ func (s *UtxoSweeper) feeRateForPreference( } if feeRate < s.relayFeeRate { return 0, fmt.Errorf("fee preference resulted in invalid fee "+ - "rate %v, mininum is %v", feeRate, s.relayFeeRate) + "rate %v, minimum is %v", feeRate, s.relayFeeRate) } if feeRate > s.cfg.MaxFeeRate { return 0, fmt.Errorf("fee preference resulted in invalid fee "+ @@ -478,7 +478,7 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch) { select { // A new inputs is offered to the sweeper. We check to see if we // are already trying to sweep this input and if not, set up a - // listener for spend and schedule a sweep. + // listener to spend and schedule a sweep. case input := <-s.newInputs: outpoint := *input.input.OutPoint() pendInput, pending := s.pendingInputs[outpoint] @@ -534,7 +534,7 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch) { s.testSpendChan <- *spend.SpentOutPoint } - // Query store to find out if we every published this + // Query store to find out if we ever published this // tx. spendHash := *spend.SpenderTxHash isOurTx, err := s.cfg.Store.IsOurTx(spendHash) diff --git a/sweep/sweeper_test.go b/sweep/sweeper_test.go index 85908f7e81..dbbb0dc6c1 100644 --- a/sweep/sweeper_test.go +++ b/sweep/sweeper_test.go @@ -760,7 +760,7 @@ func TestRestart(t *testing.T) { // Expect last tx to be republished. ctx.receiveTx() - // Simulate other subsystem (eg contract resolver) re-offering inputs. + // Simulate other subsystem (e.g. contract resolver) re-offering inputs. spendChan1, err := ctx.sweeper.SweepInput(input1, defaultFeePref) if err != nil { t.Fatal(err) @@ -858,7 +858,7 @@ func TestRestartRemoteSpend(t *testing.T) { // Mine remote spending tx. ctx.backend.mine() - // Simulate other subsystem (eg contract resolver) re-offering input 0. + // Simulate other subsystem (e.g. contract resolver) re-offering input 0. spendChan, err := ctx.sweeper.SweepInput(input1, defaultFeePref) if err != nil { t.Fatal(err) @@ -901,7 +901,7 @@ func TestRestartConfirmed(t *testing.T) { // Mine the sweep tx. ctx.backend.mine() - // Simulate other subsystem (eg contract resolver) re-offering input 0. + // Simulate other subsystem (e.g. contract resolver) re-offering input 0. spendChan, err := ctx.sweeper.SweepInput(input, defaultFeePref) if err != nil { t.Fatal(err) diff --git a/sweep/test_utils.go b/sweep/test_utils.go index df44cd1057..6b9b0d7236 100644 --- a/sweep/test_utils.go +++ b/sweep/test_utils.go @@ -216,7 +216,7 @@ func (m *MockNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, m.mutex.Unlock() // If output has been spent already, signal now. Do this outside the - // lock to prevent a dead lock. + // lock to prevent a deadlock. if spent { m.sendSpend(channel, outpoint, spendingTx) } diff --git a/sweep/walletsweep.go b/sweep/walletsweep.go index 38d194887a..fb25ccf3a9 100644 --- a/sweep/walletsweep.go +++ b/sweep/walletsweep.go @@ -112,7 +112,7 @@ type UtxoSource interface { type CoinSelectionLocker interface { // WithCoinSelectLock will execute the passed function closure in a // synchronized manner preventing any coin selection operations from - // proceeding while the closure if executing. This can be seen as the + // proceeding while the closure is executing. This can be seen as the // ability to execute a function closure under an exclusive coin // selection lock. WithCoinSelectLock(func() error) error @@ -120,7 +120,7 @@ type CoinSelectionLocker interface { // OutpointLocker allows a caller to lock/unlock an outpoint. When locked, the // outpoints shouldn't be used for any sort of channel funding of coin -// selection. Locked outpoints are not expect to be persisted between restarts. +// selection. Locked outpoints are not expected to be persisted between restarts. type OutpointLocker interface { // LockOutpoint locks a target outpoint, rendering it unusable for coin // selection. From 3d71a28cce2fd7f0f6ea4295d521258d8236760a Mon Sep 17 00:00:00 2001 From: Roei Erez Date: Mon, 16 Mar 2020 09:44:37 +0200 Subject: [PATCH 260/562] build: update dependencies --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 63b5e7dbc0..de7f0a9db3 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d // indirect github.com/juju/version v0.0.0-20180108022336-b64dbd566305 // indirect github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec - github.com/lightninglabs/neutrino v0.11.0 + github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200 github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d github.com/lightningnetwork/lightning-onion v1.0.1 github.com/lightningnetwork/lnd/cert v1.0.0 diff --git a/go.sum b/go.sum index b8991183ef..3015a6d4b7 100644 --- a/go.sum +++ b/go.sum @@ -130,8 +130,9 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/lightninglabs/neutrino v0.11.0 h1:lPpYFCtsfJX2W5zI4pWycPmbbBdr7zU+BafYdLoD6k0= github.com/lightninglabs/neutrino v0.11.0/go.mod h1:CuhF0iuzg9Sp2HO6ZgXgayviFTn1QHdSTJlMncK80wg= +github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200 h1:j4iZ1XlUAPQmW6oSzMcJGILYsRHNs+4O3Gk+2Ms5Dww= +github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200/go.mod h1:MlZmoKa7CJP3eR1s5yB7Rm5aSyadpKkxqAwLQmog7N0= github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d h1:QWD/5MPnaZfUVP7P8wLa4M8Td2DI7XXHXt2vhVtUgGI= github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d/go.mod h1:KDb67YMzoh4eudnzClmvs2FbiLG9vxISmLApUkCa4uI= github.com/lightningnetwork/lightning-onion v1.0.1 h1:qChGgS5+aPxFeR6JiUsGvanei1bn6WJpYbvosw/1604= From 41355756a143681b4c72ee73057a44c52b9a02b0 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 19 Mar 2020 11:00:53 +0200 Subject: [PATCH 261/562] channeldb: add balance at height lookup Add a balance at height lookup function which can be used to obtain local/remote balance at a given height. The current in memory commits and revocation log are used to source this information. --- channeldb/channel.go | 49 +++++++++- channeldb/channel_test.go | 187 ++++++++++++++++++++++++++++++++++++++ go.mod | 1 + 3 files changed, 236 insertions(+), 1 deletion(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index c784837ed8..65b0f67e44 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -144,6 +144,15 @@ var ( // ErrChanBorked is returned when a caller attempts to mutate a borked // channel. ErrChanBorked = fmt.Errorf("cannot mutate borked channel") + + // errLogEntryNotFound is returned when we cannot find a log entry at + // the height requested in the revocation log. + errLogEntryNotFound = fmt.Errorf("log entry not found") + + // errHeightNotFound is returned when a query for channel balances at + // a height that we have not reached yet is made. + errHeightNotReached = fmt.Errorf("height requested greater than " + + "current commit height") ) // ChannelType is an enum-like type that describes one of several possible @@ -1391,6 +1400,44 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment, return nil } +// BalancesAtHeight returns the local and remote balances on our commitment +// transactions as of a given height. +// +// NOTE: these are our balances *after* subtracting the commitment fee and +// anchor outputs. +func (c *OpenChannel) BalancesAtHeight(height uint64) (lnwire.MilliSatoshi, + lnwire.MilliSatoshi, error) { + + if height > c.LocalCommitment.CommitHeight && + height > c.RemoteCommitment.CommitHeight { + + return 0, 0, errHeightNotReached + } + + // If our current commit is as the desired height, we can return our + // current balances. + if c.LocalCommitment.CommitHeight == height { + return c.LocalCommitment.LocalBalance, + c.LocalCommitment.RemoteBalance, nil + } + + // If our current remote commit is at the desired height, we can return + // the current balances. + if c.RemoteCommitment.CommitHeight == height { + return c.RemoteCommitment.LocalBalance, + c.RemoteCommitment.RemoteBalance, nil + } + + // If we are not currently on the height requested, we need to look up + // the previous height to obtain our balances at the given height. + commit, err := c.FindPreviousState(height) + if err != nil { + return 0, 0, err + } + + return commit.LocalBalance, commit.RemoteBalance, nil +} + // HTLC is the on-disk representation of a hash time-locked contract. HTLCs are // contained within ChannelDeltas which encode the current state of the // commitment between state updates. @@ -3160,7 +3207,7 @@ func fetchChannelLogEntry(log kvdb.ReadBucket, logEntrykey := makeLogKey(updateNum) commitBytes := log.Get(logEntrykey[:]) if commitBytes == nil { - return ChannelCommitment{}, fmt.Errorf("log entry not found") + return ChannelCommitment{}, errLogEntryNotFound } commitReader := bytes.NewReader(commitBytes) diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index bd2ab8b732..2d143437f9 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -10,6 +10,8 @@ import ( "runtime" "testing" + "github.com/lightningnetwork/lnd/channeldb/kvdb" + "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" @@ -131,6 +133,25 @@ type testChannelParams struct { // default channel that is creates for testing. type testChannelOption func(params *testChannelParams) +// channelCommitmentOption is an option which allows overwriting of the default +// commitment height and balances. The local boolean can be used to set these +// balances on the local or remote commit. +func channelCommitmentOption(height uint64, localBalance, + remoteBalance lnwire.MilliSatoshi, local bool) testChannelOption { + + return func(params *testChannelParams) { + if local { + params.channel.LocalCommitment.CommitHeight = height + params.channel.LocalCommitment.LocalBalance = localBalance + params.channel.LocalCommitment.RemoteBalance = remoteBalance + } else { + params.channel.RemoteCommitment.CommitHeight = height + params.channel.RemoteCommitment.LocalBalance = localBalance + params.channel.RemoteCommitment.RemoteBalance = remoteBalance + } + } +} + // pendingHeightOption is an option which can be used to set the height the // channel is marked as pending at. func pendingHeightOption(height uint32) testChannelOption { @@ -1393,3 +1414,169 @@ func TestCloseChannelStatus(t *testing.T) { t.Fatalf("channel should have status") } } + +// TestBalanceAtHeight tests lookup of our local and remote balance at a given +// height. +func TestBalanceAtHeight(t *testing.T) { + const ( + // Values that will be set on our current local commit in + // memory. + localHeight = 2 + localLocalBalance = 1000 + localRemoteBalance = 1500 + + // Values that will be set on our current remote commit in + // memory. + remoteHeight = 3 + remoteLocalBalance = 2000 + remoteRemoteBalance = 2500 + + // Values that will be written to disk in the revocation log. + oldHeight = 0 + oldLocalBalance = 200 + oldRemoteBalance = 300 + + // Heights to test error cases. + unknownHeight = 1 + unreachedHeight = 4 + ) + + // putRevokedState is a helper function used to put commitments is + // the revocation log bucket to test lookup of balances at heights that + // are not our current height. + putRevokedState := func(c *OpenChannel, height uint64, local, + remote lnwire.MilliSatoshi) error { + + err := kvdb.Update(c.Db, func(tx kvdb.RwTx) error { + chanBucket, err := fetchChanBucketRw( + tx, c.IdentityPub, &c.FundingOutpoint, + c.ChainHash, + ) + if err != nil { + return err + } + + logKey := revocationLogBucket + logBucket, err := chanBucket.CreateBucketIfNotExists( + logKey, + ) + if err != nil { + return err + } + + // Make a copy of our current commitment so we do not + // need to re-fill all the required fields and copy in + // our new desired values. + commit := c.LocalCommitment + commit.CommitHeight = height + commit.LocalBalance = local + commit.RemoteBalance = remote + + return appendChannelLogEntry(logBucket, &commit) + }) + + return err + } + + tests := []struct { + name string + targetHeight uint64 + expectedLocalBalance lnwire.MilliSatoshi + expectedRemoteBalance lnwire.MilliSatoshi + expectedError error + }{ + { + name: "target is current local height", + targetHeight: localHeight, + expectedLocalBalance: localLocalBalance, + expectedRemoteBalance: localRemoteBalance, + expectedError: nil, + }, + { + name: "target is current remote height", + targetHeight: remoteHeight, + expectedLocalBalance: remoteLocalBalance, + expectedRemoteBalance: remoteRemoteBalance, + expectedError: nil, + }, + { + name: "need to lookup commit", + targetHeight: oldHeight, + expectedLocalBalance: oldLocalBalance, + expectedRemoteBalance: oldRemoteBalance, + expectedError: nil, + }, + { + name: "height not found", + targetHeight: unknownHeight, + expectedLocalBalance: 0, + expectedRemoteBalance: 0, + expectedError: errLogEntryNotFound, + }, + { + name: "height not reached", + targetHeight: unreachedHeight, + expectedLocalBalance: 0, + expectedRemoteBalance: 0, + expectedError: errHeightNotReached, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + cdb, cleanUp, err := makeTestDB() + if err != nil { + t.Fatalf("unable to make test database: %v", + err) + } + defer cleanUp() + + // Create options to set the heights and balances of + // our local and remote commitments. + localCommitOpt := channelCommitmentOption( + localHeight, localLocalBalance, + localRemoteBalance, true, + ) + + remoteCommitOpt := channelCommitmentOption( + remoteHeight, remoteLocalBalance, + remoteRemoteBalance, false, + ) + + // Create an open channel. + channel := createTestChannel( + t, cdb, openChannelOption(), + localCommitOpt, remoteCommitOpt, + ) + + // Write an older commit to disk. + err = putRevokedState(channel, oldHeight, + oldLocalBalance, oldRemoteBalance) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + local, remote, err := channel.BalancesAtHeight( + test.targetHeight, + ) + if err != test.expectedError { + t.Fatalf("expected: %v, got: %v", + test.expectedError, err) + } + + if local != test.expectedLocalBalance { + t.Fatalf("expected local: %v, got: %v", + test.expectedLocalBalance, local) + } + + if remote != test.expectedRemoteBalance { + t.Fatalf("expected remote: %v, got: %v", + test.expectedRemoteBalance, remote) + } + }) + } +} diff --git a/go.mod b/go.mod index 812f824fab..63b5e7dbc0 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/btcsuite/btcwallet/walletdb v1.2.0 github.com/btcsuite/btcwallet/wtxmgr v1.0.0 github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 + github.com/coreos/bbolt v1.3.3 github.com/davecgh/go-spew v1.1.1 github.com/go-errors/errors v1.0.1 github.com/golang/protobuf v1.3.1 From 72e3b0a5d7fee8e19a96b53f3415831ec45cc52f Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 18 Mar 2020 10:52:43 +0200 Subject: [PATCH 262/562] lnrpc: add push amount to listchannels --- lnrpc/rpc.pb.go | 1179 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 9 + lnrpc/rpc.swagger.json | 5 + rpcserver.go | 17 + 4 files changed, 628 insertions(+), 582 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 4034832138..edf18f53d6 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -3079,7 +3079,14 @@ type Channel struct { //value can be set on channel open by setting close_address in an open channel //request. If this value is not set, you can still choose a payout address by //cooperatively closing with the delivery_address field set. - CloseAddress string `protobuf:"bytes,25,opt,name=close_address,json=closeAddress,proto3" json:"close_address,omitempty"` + CloseAddress string `protobuf:"bytes,25,opt,name=close_address,json=closeAddress,proto3" json:"close_address,omitempty"` + // + //The amount that the initiator of the channel optionally pushed to the remote + //party on channel open. This amount will be zero if the channel initiator did + //not push any funds to the remote peer. If the initiator field is true, we + //pushed this amount to our peer, if it is false, the remote peer pushed this + //amount to us. + PushAmountSat uint64 `protobuf:"varint,27,opt,name=push_amount_sat,json=pushAmountSat,proto3" json:"push_amount_sat,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -3293,6 +3300,13 @@ func (m *Channel) GetCloseAddress() string { return "" } +func (m *Channel) GetPushAmountSat() uint64 { + if m != nil { + return m.PushAmountSat + } + return 0 +} + type ListChannelsRequest struct { ActiveOnly bool `protobuf:"varint,1,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` InactiveOnly bool `protobuf:"varint,2,opt,name=inactive_only,json=inactiveOnly,proto3" json:"inactive_only,omitempty"` @@ -11325,14 +11339,14 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11345 bytes of a gzipped FileDescriptorProto + // 11364 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x24, 0x47, 0x76, 0x18, 0x3c, 0x75, 0xeb, 0xaa, 0x3a, 0x75, 0xed, 0xe8, 0x5b, 0x4d, 0x0f, 0x87, 0x33, 0x4c, 0x72, 0xc9, 0xd9, 0xe1, 0x6e, 0xcf, 0x70, 0x76, 0xc9, 0x5d, 0x91, 0x9f, 0x56, 0x5b, 0xdd, 0x5d, 0x3d, 0x5d, 0x3b, 0x7d, 0x63, 0x56, 0x35, 0x29, 0xae, 0x3e, 0x39, 0x37, 0xbb, 0x2a, 0xba, 0x3b, 0x35, 0x55, 0x99, 0xc5, 0xcc, 0xac, 0xbe, 0xec, 0x82, 0x7e, 0x30, 0x6c, 0xc1, 0x30, 0x6c, 0x03, - 0x82, 0x2d, 0x03, 0x96, 0x2d, 0xd8, 0xb0, 0x61, 0x18, 0x86, 0x01, 0x41, 0xc6, 0xca, 0x80, 0x1f, - 0xfc, 0xae, 0x17, 0x1b, 0x82, 0x21, 0xf9, 0xc5, 0x10, 0x04, 0xc8, 0x97, 0xf5, 0x9b, 0xa1, 0x9f, + 0x82, 0x2d, 0xc3, 0x96, 0x2d, 0xd8, 0xb0, 0x61, 0x18, 0x86, 0x01, 0x41, 0xc6, 0xca, 0x80, 0x1f, + 0xfc, 0xae, 0x17, 0x1b, 0x82, 0x21, 0xf9, 0xc5, 0x10, 0x04, 0xc8, 0x97, 0xf5, 0x9b, 0xe1, 0x9f, 0x60, 0xc4, 0x39, 0x11, 0x99, 0x91, 0x55, 0xd9, 0x33, 0xc3, 0x5d, 0x7a, 0x5f, 0x66, 0x3a, 0x4f, 0x9c, 0xb8, 0x9f, 0x38, 0x71, 0xae, 0x51, 0x50, 0xf6, 0x27, 0x83, 0x8d, 0x89, 0xef, 0x85, 0x1e, 0x2b, 0x8c, 0x5c, 0x7f, 0x32, 0x58, 0x7f, 0xed, 0xcc, 0xf3, 0xce, 0x46, 0xfc, 0x91, 0x3d, 0x71, @@ -11344,14 +11358,14 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0x73, 0x03, 0xce, 0x1e, 0xc3, 0xf2, 0xc0, 0x99, 0x9c, 0x73, 0xdf, 0xc2, 0xca, 0x63, 0x97, 0x8f, 0x3d, 0xd7, 0x19, 0xb4, 0x32, 0xf7, 0x73, 0x0f, 0xca, 0x26, 0xa3, 0x32, 0x51, 0x63, 0x5f, 0x96, 0xb0, 0x77, 0xa0, 0xc1, 0x5d, 0x82, 0xf3, 0x21, 0xd6, 0x92, 0x5d, 0xd5, 0x63, 0xb0, 0xa8, 0x60, - 0xfc, 0xed, 0x2c, 0x2c, 0x76, 0x5d, 0x27, 0xfc, 0xd4, 0x1e, 0x8d, 0x78, 0xa8, 0xe6, 0xf4, 0x0e, + 0xfc, 0xcd, 0x2c, 0x2c, 0x76, 0x5d, 0x27, 0xfc, 0xd4, 0x1e, 0x8d, 0x78, 0xa8, 0xe6, 0xf4, 0x0e, 0x34, 0x2e, 0x11, 0x80, 0x73, 0xba, 0xf4, 0xfc, 0xa1, 0x9c, 0x51, 0x9d, 0xc0, 0x47, 0x12, 0x7a, 0xe3, 0xc8, 0xb2, 0x37, 0x8e, 0x2c, 0x75, 0xb9, 0x72, 0x37, 0x2c, 0xd7, 0x3b, 0xd0, 0xf0, 0xf9, 0xc0, 0xbb, 0xe0, 0xfe, 0xb5, 0x75, 0xe9, 0xb8, 0x43, 0xef, 0xb2, 0x95, 0xbf, 0x9f, 0x79, 0x50, 0x30, 0xeb, 0x0a, 0xfc, 0x29, 0x42, 0xd9, 0x26, 0x34, 0x06, 0xe7, 0xb6, 0xeb, 0xf2, 0x91, 0x75, 0x62, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xab, 0x70, 0x3f, 0xf3, 0xa0, 0xf2, 0xe4, 0xf6, 0x06, 0xee, 0xea, 0xc6, 0xd6, 0xb9, 0xed, 0x6e, 0x62, 0x49, 0xcf, 0xb5, 0x27, 0xc1, 0xb9, 0x17, 0x9a, 0x75, - 0x59, 0x83, 0xc0, 0x81, 0xb1, 0x0c, 0x4c, 0x5f, 0x09, 0x5a, 0x7b, 0xe3, 0xdf, 0x66, 0x60, 0xe9, + 0x59, 0x83, 0xc0, 0x81, 0xb1, 0x0c, 0x4c, 0x5f, 0x09, 0x5a, 0x7b, 0xe3, 0xdf, 0x64, 0x60, 0xe9, 0xd8, 0x1d, 0x79, 0x83, 0xe7, 0x3f, 0xe7, 0x12, 0xa5, 0xcc, 0x21, 0xfb, 0xaa, 0x73, 0xc8, 0x7d, 0xd9, 0x39, 0xac, 0xc2, 0x72, 0x72, 0xb0, 0x72, 0x16, 0x1c, 0x56, 0x44, 0xed, 0x33, 0xae, 0x86, 0xa5, 0xa6, 0xf1, 0x75, 0x68, 0x0e, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x79, 0x34, 0x24, 0x3c, 0x9a, @@ -11408,7 +11422,7 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xe7, 0x55, 0xe5, 0xf4, 0x4c, 0x01, 0x8b, 0x5a, 0xc7, 0xaf, 0x57, 0xa0, 0x73, 0xe3, 0x77, 0x33, 0xc0, 0xc4, 0xb0, 0xfb, 0x1e, 0x35, 0x20, 0x29, 0x74, 0xb6, 0x66, 0xe6, 0x95, 0x4f, 0x48, 0xf6, 0x45, 0x27, 0xc4, 0x80, 0x02, 0x8d, 0x3d, 0x9f, 0x32, 0x76, 0x2a, 0xfa, 0x41, 0xbe, 0x94, 0x6b, - 0xe6, 0x8d, 0xff, 0x96, 0x83, 0xe5, 0x2d, 0xba, 0xb2, 0xdb, 0x83, 0x01, 0x9f, 0x44, 0x67, 0xe7, + 0xe6, 0x8d, 0xff, 0x9a, 0x83, 0xe5, 0x2d, 0xba, 0xb2, 0xdb, 0x83, 0x01, 0x9f, 0x44, 0x67, 0xe7, 0x1e, 0x54, 0x5c, 0x6f, 0xc8, 0x15, 0xc5, 0xd2, 0xc0, 0x40, 0x80, 0x34, 0x72, 0x3d, 0xb7, 0x1d, 0x97, 0x06, 0x4e, 0x8b, 0x59, 0x46, 0x08, 0x0e, 0xfb, 0x6d, 0x68, 0x4c, 0xb8, 0x3b, 0xd4, 0x8f, 0x08, 0x09, 0x55, 0x35, 0x09, 0x96, 0xa7, 0xe3, 0x1e, 0x54, 0x4e, 0xa7, 0x84, 0x27, 0x18, 0x4b, @@ -11439,11 +11453,11 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xce, 0xb5, 0xa1, 0xf3, 0xe5, 0x72, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, 0x82, 0xa5, 0xc4, 0xb8, 0x24, 0xa5, 0xad, 0x41, 0x51, 0x1c, 0x08, 0x21, 0x1c, 0x64, 0x48, 0xaa, 0x3c, 0xe5, 0x5c, 0x88, 0xc1, 0x8f, 0x60, 0xf9, 0x94, 0x73, 0xdf, 0x0e, 0xb1, 0x10, 0x4f, 0x8c, 0xd8, 0x21, 0xd9, 0xf0, - 0xa2, 0x2c, 0xeb, 0xd9, 0xe1, 0x11, 0xf7, 0xc5, 0x4e, 0x19, 0xff, 0x23, 0x03, 0x0d, 0xc1, 0x41, + 0xa2, 0x2c, 0xeb, 0xd9, 0xe1, 0x11, 0xf7, 0xc5, 0x4e, 0x19, 0xff, 0x3d, 0x03, 0x0d, 0xc1, 0x41, 0xf7, 0x6d, 0xf7, 0x5a, 0xad, 0xd3, 0x5e, 0xea, 0x3a, 0x3d, 0xd0, 0x2e, 0x43, 0x0d, 0xfb, 0xcb, 0x2e, 0x52, 0x6e, 0x76, 0x91, 0xd8, 0x7d, 0xa8, 0x26, 0xc6, 0x5a, 0xc0, 0xb1, 0x42, 0x10, 0x0d, 0xf2, 0x17, 0x5f, 0xc6, 0xb7, 0xa1, 0x19, 0x0f, 0x5b, 0xae, 0x21, 0x83, 0xbc, 0x20, 0x49, 0xd9, - 0x00, 0xfe, 0x6d, 0xfc, 0xd3, 0x0c, 0x21, 0x6e, 0x79, 0x4e, 0x24, 0x9d, 0x0a, 0x44, 0x21, 0xf7, + 0x00, 0xfe, 0x6d, 0xfc, 0x93, 0x0c, 0x21, 0x6e, 0x79, 0x4e, 0x24, 0x9d, 0x0a, 0x44, 0x21, 0xf7, 0x2a, 0x44, 0xf1, 0xf7, 0x8d, 0x52, 0xfd, 0x2f, 0x3e, 0x59, 0x71, 0x74, 0x02, 0xee, 0x0e, 0x2d, 0x7b, 0x34, 0x42, 0xe6, 0x5b, 0x32, 0x8b, 0xe2, 0xbb, 0x3d, 0x1a, 0x19, 0xef, 0xc0, 0xa2, 0x36, 0xba, 0x17, 0xcc, 0xe3, 0x00, 0xd8, 0x9e, 0x13, 0x84, 0xc7, 0x6e, 0x30, 0xd1, 0x04, 0xb7, 0x3b, @@ -11461,581 +11475,582 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0x5c, 0xd9, 0x59, 0x66, 0x2a, 0x89, 0x98, 0x41, 0x7e, 0xc2, 0xfd, 0x31, 0x36, 0x5c, 0x32, 0xf1, 0x6f, 0x63, 0x05, 0x96, 0x12, 0xcd, 0x4a, 0xbd, 0xfe, 0x31, 0xac, 0x6c, 0x3b, 0xc1, 0x60, 0xbe, 0xc3, 0x35, 0x28, 0x4e, 0xa6, 0x27, 0x56, 0x92, 0x2f, 0x3f, 0xe3, 0xd7, 0x42, 0xdb, 0x9b, 0xad, - 0x21, 0xdb, 0xfa, 0x9b, 0x19, 0xc8, 0xef, 0xf6, 0xf7, 0xb6, 0xd8, 0x3a, 0x94, 0x1c, 0x77, 0xe0, + 0x21, 0xdb, 0xfa, 0xeb, 0x19, 0xc8, 0xef, 0xf6, 0xf7, 0xb6, 0xd8, 0x3a, 0x94, 0x1c, 0x77, 0xe0, 0x8d, 0x85, 0xe0, 0x45, 0x73, 0x8e, 0xbe, 0x6f, 0x3c, 0x60, 0x77, 0xa0, 0x8c, 0xf2, 0x9a, 0x50, 0x6d, 0xa5, 0xe8, 0x53, 0x12, 0x80, 0x3d, 0x6f, 0xf0, 0x5c, 0xe8, 0xd4, 0xfc, 0x6a, 0xe2, 0xf8, - 0xa8, 0x35, 0x2b, 0x65, 0x38, 0x4f, 0x77, 0x7d, 0x5c, 0x40, 0x1a, 0xb1, 0xf1, 0x57, 0x45, 0x28, - 0xca, 0xdb, 0x96, 0x6e, 0xee, 0xd0, 0xb9, 0xe0, 0xf1, 0xcd, 0x2d, 0xbe, 0x84, 0x3c, 0xe0, 0xf3, - 0xb1, 0x17, 0x46, 0x02, 0x1b, 0xed, 0x41, 0x95, 0x80, 0x52, 0x64, 0xd3, 0x84, 0x06, 0x32, 0x31, - 0xe4, 0x08, 0x69, 0xa0, 0x5f, 0xe5, 0x77, 0xa0, 0xa8, 0xee, 0xfe, 0x7c, 0xa4, 0xd3, 0x2c, 0x0c, - 0x48, 0x5a, 0x5b, 0x87, 0xd2, 0xc0, 0x9e, 0xd8, 0x03, 0x27, 0xbc, 0x96, 0x0c, 0x21, 0xfa, 0x16, - 0xad, 0x8f, 0xbc, 0x81, 0x3d, 0xb2, 0x4e, 0xec, 0x91, 0xed, 0x0e, 0xb8, 0xd4, 0xdd, 0xab, 0x08, - 0xdc, 0x24, 0x98, 0xd0, 0xcf, 0xe5, 0x38, 0x15, 0x16, 0xa9, 0xf0, 0x72, 0xf4, 0x0a, 0x4d, 0x08, - 0x97, 0xde, 0x78, 0xec, 0x08, 0x2d, 0x83, 0xc4, 0xb0, 0x9c, 0x59, 0x26, 0xc8, 0x0e, 0xc7, 0xd9, - 0xca, 0xe2, 0x4b, 0x5a, 0xba, 0x32, 0x75, 0x45, 0xc0, 0x4f, 0xc9, 0x90, 0x30, 0x2f, 0x8b, 0xe5, - 0x34, 0x59, 0xec, 0x5d, 0x58, 0x9c, 0xba, 0x01, 0x0f, 0xc3, 0x11, 0x1f, 0x46, 0x63, 0xa9, 0x20, - 0x52, 0x33, 0x2a, 0x50, 0xc3, 0xd9, 0x80, 0x25, 0x32, 0x3a, 0x04, 0x76, 0xe8, 0x05, 0xe7, 0x4e, - 0x60, 0x05, 0x42, 0x43, 0x22, 0x75, 0x77, 0x11, 0x8b, 0x7a, 0xb2, 0xa4, 0x47, 0x2a, 0xd2, 0xda, - 0x0c, 0xbe, 0xcf, 0x07, 0xdc, 0xb9, 0xe0, 0x43, 0x94, 0xd3, 0x72, 0xe6, 0x4a, 0xa2, 0x8e, 0x29, - 0x0b, 0x51, 0xe8, 0x9e, 0x8e, 0xad, 0xe9, 0x64, 0x68, 0x0b, 0x61, 0xa5, 0x4e, 0xc2, 0xb0, 0x3b, - 0x1d, 0x1f, 0x13, 0x84, 0x3d, 0x06, 0x25, 0x89, 0x49, 0xf9, 0xb0, 0x91, 0xe0, 0x67, 0x82, 0x58, - 0xcd, 0xaa, 0xc4, 0x20, 0x41, 0x31, 0x21, 0x73, 0x36, 0x67, 0x64, 0xce, 0x16, 0x14, 0x27, 0xbe, - 0x73, 0x61, 0x87, 0xbc, 0xb5, 0x48, 0x0c, 0x5c, 0x7e, 0x0a, 0xce, 0xe0, 0xb8, 0x4e, 0xe8, 0xd8, - 0xa1, 0xe7, 0xb7, 0x18, 0x96, 0xc5, 0x00, 0xf6, 0x10, 0x16, 0x91, 0x46, 0x82, 0xd0, 0x0e, 0xa7, - 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x21, 0x1c, 0x85, 0x50, 0xf6, 0x2d, 0x58, - 0x25, 0xb2, 0xc0, 0x1a, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x97, 0x62, 0x09, 0x4b, 0x05, 0x7d, - 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0xef, 0xc3, 0x9a, 0x24, 0x93, 0xb9, 0x5a, 0x2b, 0x58, 0x6b, 0x99, - 0x8a, 0x67, 0xaa, 0x6d, 0xc0, 0xa2, 0x18, 0x92, 0x33, 0xb0, 0x64, 0x6d, 0x71, 0x12, 0x56, 0xc5, - 0xe8, 0x51, 0x53, 0x6a, 0x50, 0xa1, 0x89, 0x65, 0xcf, 0xf8, 0x35, 0xfb, 0x1e, 0x34, 0x88, 0x64, - 0x50, 0xbd, 0x42, 0x4e, 0xbf, 0x8e, 0x9c, 0x7e, 0x45, 0x59, 0x38, 0xa3, 0x52, 0x64, 0xf6, 0xf5, - 0x41, 0xe2, 0x5b, 0x1c, 0x87, 0x91, 0x73, 0xca, 0x43, 0x67, 0xcc, 0x5b, 0x6b, 0x44, 0x60, 0xea, - 0x5b, 0x9c, 0xd4, 0xe9, 0x04, 0x4b, 0x5a, 0xc4, 0x17, 0xe8, 0x0b, 0x69, 0x77, 0xe4, 0x05, 0x5c, - 0x99, 0xa8, 0x5a, 0xb7, 0xe5, 0x21, 0x14, 0x40, 0xc9, 0xf6, 0x8c, 0x9f, 0x66, 0xe8, 0x1e, 0x93, - 0xc7, 0x3e, 0xd0, 0xb4, 0x32, 0x3a, 0xf0, 0x96, 0xe7, 0x8e, 0xae, 0x25, 0x0f, 0x00, 0x02, 0x1d, - 0xba, 0x23, 0x3c, 0x84, 0x8e, 0xab, 0xa3, 0x10, 0xcb, 0xac, 0x2a, 0x20, 0x22, 0xdd, 0x83, 0xca, - 0x64, 0x7a, 0x32, 0x72, 0x06, 0x84, 0x92, 0xa3, 0x56, 0x08, 0x84, 0x08, 0x42, 0x2d, 0x25, 0x42, - 0x20, 0x8c, 0x3c, 0x62, 0x54, 0x24, 0x0c, 0x51, 0x90, 0x25, 0x73, 0x1f, 0xb9, 0x40, 0xd5, 0xc4, - 0xbf, 0x8d, 0x4d, 0x58, 0x4e, 0x0e, 0x5a, 0xde, 0x17, 0x0f, 0xa1, 0x24, 0x59, 0x8c, 0xb2, 0x57, - 0xd4, 0x35, 0x0b, 0xb2, 0xd0, 0xac, 0xa2, 0x72, 0xe3, 0xb7, 0x17, 0x60, 0x49, 0x42, 0xb7, 0xc4, - 0x8a, 0xf4, 0xa6, 0xe3, 0xb1, 0xed, 0xa7, 0xf0, 0xae, 0xcc, 0x8b, 0x79, 0x57, 0x76, 0x8e, 0x77, - 0x25, 0x15, 0x56, 0x62, 0x7d, 0x49, 0x85, 0x55, 0x6c, 0x01, 0xe9, 0x10, 0xba, 0xf9, 0xb2, 0x26, - 0xc1, 0x7d, 0x32, 0x93, 0xce, 0x71, 0xda, 0x42, 0x0a, 0xa7, 0xd5, 0xf9, 0xe4, 0xc2, 0x0c, 0x9f, - 0x7c, 0x03, 0x68, 0xaf, 0x15, 0xdb, 0x2f, 0x92, 0x5a, 0x81, 0x30, 0x69, 0x03, 0x7d, 0x07, 0x1a, - 0xb3, 0xac, 0x89, 0x78, 0x60, 0x3d, 0x85, 0x31, 0x39, 0x63, 0x8e, 0x97, 0x8c, 0x86, 0x5c, 0x96, - 0x8c, 0xc9, 0x19, 0xf3, 0x3d, 0x2c, 0x51, 0xf8, 0x1d, 0x00, 0xea, 0x1b, 0x69, 0x1d, 0x90, 0xd6, - 0xdf, 0x4e, 0xee, 0x85, 0xbe, 0xea, 0x1b, 0xe2, 0x63, 0xea, 0x73, 0x24, 0xfe, 0x32, 0xd6, 0x44, - 0xba, 0x7f, 0x06, 0x75, 0x6f, 0xc2, 0x5d, 0x2b, 0x66, 0x11, 0x15, 0x6c, 0xea, 0xad, 0x17, 0x34, - 0xd5, 0x55, 0xb8, 0x66, 0x4d, 0xd4, 0x8d, 0x3e, 0xd9, 0x3e, 0x2d, 0x3c, 0xd7, 0x5a, 0xab, 0x7e, - 0x89, 0xd6, 0xea, 0x58, 0x39, 0xfa, 0x36, 0xfe, 0x4e, 0x06, 0x2a, 0xda, 0xb0, 0xd9, 0x0a, 0x2c, - 0x6e, 0x1d, 0x1e, 0x1e, 0x75, 0xcc, 0x76, 0xbf, 0xfb, 0x49, 0xc7, 0xda, 0xda, 0x3b, 0xec, 0x75, - 0x9a, 0xb7, 0x04, 0x78, 0xef, 0x70, 0xab, 0xbd, 0x67, 0xed, 0x1c, 0x9a, 0x5b, 0x0a, 0x9c, 0x61, - 0xab, 0xc0, 0xcc, 0xce, 0xfe, 0x61, 0xbf, 0x93, 0x80, 0x67, 0x59, 0x13, 0xaa, 0x9b, 0x66, 0xa7, - 0xbd, 0xb5, 0x2b, 0x21, 0x39, 0xb6, 0x0c, 0xcd, 0x9d, 0xe3, 0x83, 0xed, 0xee, 0xc1, 0x53, 0x6b, - 0xab, 0x7d, 0xb0, 0xd5, 0xd9, 0xeb, 0x6c, 0x37, 0xf3, 0xac, 0x06, 0xe5, 0xf6, 0x66, 0xfb, 0x60, - 0xfb, 0xf0, 0xa0, 0xb3, 0xdd, 0x2c, 0x18, 0xbf, 0x02, 0xe5, 0x78, 0xa2, 0x15, 0x28, 0x1e, 0x1f, - 0x3c, 0x3b, 0x38, 0xfc, 0xf4, 0xa0, 0x79, 0x8b, 0x95, 0xa1, 0x80, 0xfd, 0x37, 0x33, 0x0c, 0x60, - 0x81, 0xfa, 0x6c, 0x66, 0x59, 0x09, 0xf2, 0x9b, 0x87, 0xfd, 0xdd, 0x66, 0xce, 0xf8, 0x8b, 0x0c, - 0xac, 0xe0, 0x94, 0x87, 0xb3, 0x4c, 0xe0, 0x3e, 0x54, 0x06, 0x9e, 0x37, 0x11, 0x0a, 0x52, 0x2c, - 0x08, 0xe8, 0x20, 0x71, 0xc0, 0x89, 0xe7, 0x9e, 0x7a, 0xfe, 0x80, 0x4b, 0x1e, 0x00, 0x08, 0xda, - 0x11, 0x10, 0x41, 0x83, 0x92, 0x88, 0x09, 0x83, 0x58, 0x40, 0x85, 0x60, 0x84, 0xb2, 0x0a, 0x0b, - 0x27, 0x3e, 0xb7, 0x07, 0xe7, 0xf2, 0xf4, 0xcb, 0x2f, 0xf6, 0xf5, 0x58, 0x75, 0x1f, 0x08, 0x9a, - 0x1a, 0xf1, 0x21, 0x1e, 0x81, 0x92, 0xd9, 0x90, 0xf0, 0x2d, 0x09, 0x16, 0x97, 0x88, 0x7d, 0x62, - 0xbb, 0x43, 0xcf, 0xe5, 0x43, 0xa9, 0x21, 0xc4, 0x00, 0xe3, 0x08, 0x56, 0x67, 0xe7, 0x27, 0xf9, - 0xc5, 0x07, 0x1a, 0xbf, 0x20, 0x81, 0x7d, 0xfd, 0x66, 0x52, 0xd0, 0x78, 0xc7, 0xdf, 0xcb, 0x43, - 0x5e, 0x08, 0x70, 0x37, 0xca, 0x7a, 0xba, 0x44, 0x9e, 0x9b, 0xf3, 0xda, 0xa0, 0x85, 0x80, 0x6e, - 0x76, 0x32, 0x43, 0x95, 0x11, 0x82, 0x37, 0x7a, 0x54, 0xec, 0xf3, 0xc1, 0x85, 0xb4, 0x43, 0x51, - 0xb1, 0xc9, 0x07, 0x17, 0xa8, 0x0a, 0xd9, 0x21, 0xd5, 0xa5, 0xf3, 0x5e, 0x0c, 0xec, 0x10, 0x6b, - 0xca, 0x22, 0xac, 0x57, 0x8c, 0x8a, 0xb0, 0x56, 0x0b, 0x8a, 0x8e, 0x7b, 0xe2, 0x4d, 0xdd, 0x21, - 0x1e, 0xef, 0x92, 0xa9, 0x3e, 0xd1, 0x49, 0x84, 0x9c, 0x48, 0xdc, 0x1f, 0x74, 0x9a, 0x4b, 0x02, - 0xd0, 0x17, 0x37, 0xc8, 0x7b, 0x50, 0x0e, 0xae, 0xdd, 0x81, 0x7e, 0x86, 0x97, 0xe5, 0xfa, 0x88, - 0xd9, 0x6f, 0xf4, 0xae, 0xdd, 0x01, 0x9e, 0xd8, 0x52, 0x20, 0xff, 0x62, 0xef, 0x43, 0x29, 0x32, - 0xd7, 0x12, 0x07, 0xbe, 0xad, 0xd7, 0x50, 0x36, 0x5a, 0xd2, 0x8a, 0x23, 0x54, 0xf6, 0x08, 0x16, - 0xd0, 0xa6, 0x1a, 0xb4, 0xaa, 0x58, 0x49, 0x89, 0xe9, 0x62, 0x18, 0xe8, 0x9f, 0xe1, 0x43, 0xb4, - 0xaf, 0x9a, 0x12, 0x6d, 0xfd, 0x19, 0xd4, 0x12, 0x6d, 0xe9, 0xba, 0x6f, 0x8d, 0x74, 0xdf, 0xb7, - 0x74, 0xdd, 0x37, 0xbe, 0x09, 0x64, 0x35, 0x5d, 0x17, 0xfe, 0x35, 0x28, 0xa9, 0xa9, 0x88, 0xf3, - 0x27, 0xcf, 0x8e, 0xd5, 0xfb, 0xec, 0x60, 0xab, 0x79, 0x8b, 0x35, 0xa0, 0xd2, 0xde, 0xc2, 0x23, - 0x8d, 0x80, 0x8c, 0x40, 0x39, 0x6a, 0xf7, 0x7a, 0x11, 0x24, 0x6b, 0xec, 0x40, 0x73, 0x76, 0xa4, - 0x82, 0x26, 0x43, 0x05, 0x93, 0x16, 0xe7, 0x18, 0x20, 0x34, 0x1b, 0x32, 0x22, 0x93, 0xf8, 0x4c, - 0x1f, 0xc6, 0xfb, 0xd0, 0x14, 0xf7, 0x9a, 0x58, 0xaa, 0x40, 0xb3, 0xdc, 0x8e, 0x84, 0x48, 0xa6, - 0x5b, 0x9d, 0x4b, 0x66, 0x85, 0x60, 0xd8, 0x95, 0xf1, 0x01, 0x2c, 0x6a, 0xd5, 0x62, 0x4d, 0x54, - 0xdc, 0x95, 0xb3, 0x9a, 0x28, 0xea, 0x1d, 0x54, 0x62, 0xac, 0xc1, 0x8a, 0xf8, 0xec, 0x5c, 0x70, - 0x37, 0xec, 0x4d, 0x4f, 0xc8, 0x55, 0xe8, 0x78, 0xae, 0xd0, 0x47, 0xca, 0x51, 0xc9, 0xcd, 0x44, - 0xbe, 0x21, 0x95, 0xd6, 0x2c, 0x92, 0xc6, 0xba, 0xd6, 0x03, 0x56, 0xdc, 0xc0, 0x7f, 0x13, 0xca, - 0x6b, 0x39, 0x02, 0x89, 0x65, 0x3d, 0xea, 0x74, 0x4c, 0xeb, 0xf0, 0x60, 0xaf, 0x7b, 0x20, 0x18, - 0xa5, 0x58, 0x56, 0x04, 0xec, 0xec, 0x20, 0x24, 0x63, 0x34, 0xa1, 0xfe, 0x94, 0x87, 0x5d, 0xf7, - 0xd4, 0x53, 0x6e, 0xb1, 0x9f, 0x15, 0xa0, 0x11, 0x81, 0x62, 0xe5, 0xf7, 0x82, 0xfb, 0x81, 0xe3, - 0xb9, 0x28, 0xc7, 0x96, 0x4d, 0xf5, 0x29, 0x6e, 0x37, 0x67, 0xc8, 0xdd, 0xd0, 0x09, 0xaf, 0xad, - 0x84, 0xa5, 0xac, 0xae, 0xc0, 0xf2, 0x16, 0x5d, 0x86, 0x82, 0x3d, 0x72, 0x6c, 0xe5, 0x61, 0xa5, - 0x0f, 0x01, 0x1d, 0x78, 0x23, 0xcf, 0x47, 0x91, 0xb5, 0x6c, 0xd2, 0x07, 0x7b, 0x0c, 0xcb, 0x42, - 0x74, 0xd6, 0xcd, 0x97, 0xc8, 0x3f, 0xc8, 0x68, 0xc7, 0xdc, 0xe9, 0xf8, 0x28, 0x36, 0x61, 0x8a, - 0x12, 0x71, 0x77, 0x8a, 0x1a, 0x52, 0x58, 0x8a, 0x2a, 0x90, 0x16, 0xb6, 0xe8, 0x4e, 0xc7, 0x6d, - 0x2c, 0x89, 0xf0, 0x9f, 0xc0, 0x8a, 0xc0, 0x8f, 0xc4, 0xab, 0xa8, 0x46, 0x03, 0x6b, 0x88, 0xc6, - 0xba, 0xb2, 0x2c, 0xaa, 0x73, 0x07, 0xca, 0x34, 0x2a, 0xb1, 0xe3, 0x05, 0x92, 0xbe, 0x71, 0x28, - 0xdc, 0x0f, 0xe6, 0x9c, 0xa1, 0x0b, 0x24, 0x08, 0xcc, 0x38, 0x43, 0x35, 0x77, 0x6a, 0x69, 0xd6, - 0x9d, 0xfa, 0x04, 0x56, 0x4e, 0x04, 0x09, 0x9e, 0x73, 0x7b, 0xc8, 0x7d, 0x2b, 0x26, 0x6c, 0xd2, - 0x32, 0x96, 0x44, 0xe1, 0x2e, 0x96, 0x45, 0xe7, 0x40, 0xc8, 0x39, 0x82, 0x2d, 0xf0, 0xa1, 0x15, - 0x7a, 0x16, 0x8a, 0x3f, 0xc8, 0x60, 0x4a, 0x66, 0x8d, 0xc0, 0x7d, 0x6f, 0x4b, 0x00, 0x93, 0x78, - 0x67, 0xbe, 0x3d, 0x39, 0x97, 0x7a, 0x40, 0x84, 0xf7, 0x54, 0x00, 0xd9, 0x6b, 0x50, 0x14, 0x24, - 0xef, 0x72, 0xf2, 0x59, 0x91, 0xa4, 0xad, 0x40, 0xec, 0x2d, 0x58, 0xc0, 0x3e, 0x82, 0x56, 0x13, - 0xe9, 0xbd, 0x1a, 0x33, 0x72, 0xc7, 0x35, 0x65, 0x99, 0x10, 0x26, 0xa7, 0xbe, 0x43, 0x5c, 0xa6, - 0x6c, 0xe2, 0xdf, 0xec, 0xfb, 0x1a, 0xcb, 0x5a, 0xc2, 0xba, 0x4a, 0x1e, 0x98, 0xa1, 0xb4, 0x9b, - 0xb8, 0xd7, 0x57, 0xca, 0x8c, 0x7e, 0x90, 0x2f, 0x55, 0x9a, 0x55, 0xe3, 0x3b, 0x50, 0xa0, 0xd5, - 0x11, 0x44, 0x88, 0x6b, 0x97, 0x91, 0x44, 0x88, 0xd0, 0x16, 0x14, 0x5d, 0x1e, 0x5e, 0x7a, 0xfe, - 0x73, 0x65, 0x4b, 0x96, 0x9f, 0xc6, 0x8f, 0xd1, 0x08, 0x12, 0x39, 0xca, 0x49, 0x9f, 0x13, 0xe4, - 0x41, 0xdb, 0x1b, 0x9c, 0xdb, 0xd2, 0x2e, 0x53, 0x42, 0x40, 0xef, 0xdc, 0x9e, 0x23, 0x8f, 0xec, - 0xbc, 0xaf, 0xfc, 0x2d, 0xa8, 0x2b, 0xd7, 0x7c, 0x60, 0x8d, 0xf8, 0x69, 0x28, 0xc9, 0xbd, 0x2a, - 0xfd, 0xf2, 0xc1, 0x1e, 0x3f, 0x0d, 0x8d, 0x7d, 0x58, 0x94, 0x04, 0x79, 0x38, 0xe1, 0xaa, 0xeb, - 0xef, 0xa6, 0xc9, 0xd3, 0x95, 0x27, 0x4b, 0xc9, 0x8b, 0x96, 0x42, 0x0e, 0x12, 0x42, 0xb6, 0xf1, - 0x31, 0x30, 0xfd, 0x1a, 0x96, 0xed, 0x49, 0xa9, 0x56, 0x99, 0xe0, 0x95, 0x27, 0x2b, 0x92, 0x9d, - 0x9d, 0xa1, 0x58, 0x9d, 0x60, 0x3a, 0x18, 0xa8, 0x90, 0x89, 0x92, 0xa9, 0x3e, 0x8d, 0x3f, 0xcd, - 0xc0, 0x12, 0x36, 0xa6, 0xf4, 0x01, 0xc9, 0x64, 0x7f, 0xee, 0x41, 0x8a, 0xfd, 0xd1, 0x65, 0x1f, - 0xfa, 0xf8, 0xf2, 0x46, 0xcf, 0xfc, 0x9c, 0xd1, 0xf3, 0xeb, 0xd0, 0x1c, 0xf2, 0x91, 0x83, 0xd1, - 0x33, 0x4a, 0x94, 0x20, 0x0d, 0xa0, 0xa1, 0xe0, 0x4a, 0x89, 0xfb, 0x47, 0x19, 0x58, 0x24, 0x49, - 0x05, 0xd5, 0x61, 0xb9, 0x50, 0x1f, 0x29, 0xfd, 0x4f, 0xb2, 0x2a, 0x39, 0xa7, 0xf8, 0x06, 0x47, - 0x28, 0x21, 0xef, 0xde, 0x92, 0x7a, 0xa1, 0x84, 0xb2, 0x0f, 0x51, 0x87, 0x71, 0x2d, 0x04, 0xa6, - 0x44, 0xe3, 0x24, 0x37, 0x65, 0xf7, 0x16, 0x2a, 0x38, 0x2e, 0x82, 0x36, 0x4b, 0x42, 0x21, 0x15, - 0x60, 0x63, 0x07, 0x6a, 0x89, 0x6e, 0x12, 0x96, 0xd9, 0x2a, 0x59, 0x66, 0xe7, 0xbc, 0x1f, 0xd9, - 0x79, 0xef, 0xc7, 0xdf, 0xca, 0x03, 0x13, 0x24, 0x35, 0xb3, 0x6b, 0x33, 0xae, 0xc3, 0xec, 0x9c, - 0xeb, 0xf0, 0x31, 0x30, 0x0d, 0x41, 0x79, 0x34, 0x73, 0x91, 0x47, 0xb3, 0x19, 0xe3, 0x4a, 0x87, - 0xe6, 0x63, 0x58, 0x96, 0x02, 0x6d, 0xe4, 0x2b, 0x44, 0x93, 0x1b, 0xed, 0x0f, 0x23, 0xc9, 0x56, - 0xf9, 0x0c, 0xd1, 0xfc, 0xa6, 0xdc, 0x86, 0x81, 0x1d, 0x4a, 0x4b, 0x15, 0xba, 0x0d, 0x7b, 0xf6, - 0x9c, 0xe9, 0x7b, 0xe1, 0xa5, 0x54, 0x50, 0x9c, 0xa3, 0x02, 0xcd, 0x70, 0x52, 0x4a, 0x1a, 0x4e, - 0x0c, 0xa8, 0x29, 0xe7, 0x20, 0xc5, 0x44, 0x90, 0xf4, 0x56, 0x91, 0x1e, 0x42, 0x8c, 0x8b, 0x78, - 0x00, 0x4d, 0x65, 0xdd, 0x88, 0x4c, 0x33, 0xe4, 0xef, 0x97, 0xc6, 0xb1, 0x2d, 0x65, 0xa0, 0x49, - 0x18, 0xc2, 0x2b, 0x33, 0x86, 0xf0, 0x77, 0x61, 0x31, 0x10, 0x44, 0x64, 0x4d, 0x5d, 0x19, 0x9c, - 0xc3, 0x87, 0xa8, 0x3a, 0x95, 0xcc, 0x26, 0x16, 0x1c, 0xc7, 0xf0, 0x79, 0xb3, 0x43, 0x6d, 0xde, - 0xec, 0xc0, 0xde, 0x8f, 0xfd, 0x68, 0xc1, 0xb9, 0x33, 0xc6, 0x8b, 0x3b, 0x0e, 0x64, 0x91, 0x0b, - 0xdc, 0x3b, 0x77, 0xc6, 0xa6, 0x72, 0xda, 0x8a, 0x0f, 0xe3, 0x3f, 0x64, 0xa0, 0x29, 0xe8, 0x20, - 0x41, 0xe7, 0xbf, 0x02, 0x78, 0x22, 0x5f, 0x91, 0xcc, 0x2b, 0x02, 0x57, 0x51, 0xf9, 0x77, 0x00, - 0xc9, 0xd6, 0x12, 0x7a, 0xa2, 0x24, 0xf2, 0x56, 0x92, 0xc8, 0x63, 0x46, 0xb6, 0x7b, 0x8b, 0x14, - 0x00, 0x01, 0x49, 0xf3, 0x5f, 0xe6, 0x53, 0xfc, 0x97, 0xda, 0x51, 0xd8, 0x05, 0x78, 0xc6, 0xaf, - 0xf7, 0xbc, 0x01, 0x6a, 0x68, 0x77, 0x01, 0x04, 0x41, 0x9e, 0xda, 0x63, 0x47, 0x5a, 0x57, 0x0a, - 0x66, 0xf9, 0x39, 0xbf, 0xde, 0x41, 0x80, 0xd8, 0x0d, 0x51, 0x1c, 0x9f, 0x87, 0x82, 0x59, 0x7a, - 0xce, 0xaf, 0xe9, 0x30, 0x58, 0x50, 0x7b, 0xc6, 0xaf, 0xb7, 0x39, 0x89, 0x6b, 0x9e, 0x2f, 0x28, - 0xc1, 0xb7, 0x2f, 0x85, 0x7c, 0x96, 0xf0, 0x3d, 0x56, 0x7c, 0xfb, 0xf2, 0x19, 0xbf, 0x56, 0x7e, - 0xd0, 0xa2, 0x28, 0x1f, 0x79, 0x03, 0x79, 0x03, 0xa9, 0x28, 0x8a, 0x78, 0x50, 0xe6, 0xc2, 0x73, - 0xfc, 0xdb, 0xf8, 0x93, 0x0c, 0xd4, 0xc4, 0xf8, 0x91, 0xc1, 0x89, 0x75, 0x57, 0xc1, 0x38, 0x99, - 0x38, 0x18, 0xe7, 0x89, 0xe4, 0x0f, 0xc4, 0x2d, 0xb3, 0x37, 0x73, 0x4b, 0x5c, 0x60, 0x62, 0x95, - 0xef, 0x41, 0x99, 0xce, 0x96, 0x38, 0xac, 0xb9, 0xc4, 0x2e, 0x25, 0x26, 0x64, 0x96, 0x10, 0xed, - 0x19, 0xf9, 0xfe, 0x35, 0x03, 0x1b, 0x2d, 0x71, 0xd9, 0x8f, 0xcc, 0x6a, 0x29, 0xdb, 0x50, 0x48, - 0x73, 0x23, 0x1f, 0x43, 0x45, 0xa3, 0x29, 0xb4, 0xc6, 0x45, 0x83, 0x27, 0x02, 0x4c, 0x12, 0x4d, - 0x62, 0xf6, 0xbb, 0xb7, 0xcc, 0xda, 0x40, 0x07, 0x6c, 0x2e, 0x40, 0x5e, 0x54, 0x32, 0x3e, 0x82, - 0x45, 0xad, 0x59, 0xd2, 0x46, 0xd3, 0xc6, 0x94, 0x49, 0x1b, 0xd3, 0x3f, 0xce, 0xc0, 0xb2, 0xac, - 0x8d, 0x81, 0x5b, 0x8e, 0xb8, 0xae, 0xf7, 0x83, 0x33, 0xf6, 0x2b, 0x50, 0x13, 0xad, 0x5b, 0x3e, - 0x3f, 0x73, 0x82, 0x90, 0x2b, 0xcf, 0x45, 0xca, 0xe1, 0x10, 0x5c, 0x5b, 0xa0, 0x9a, 0x12, 0x93, - 0x7d, 0x04, 0x15, 0xac, 0x4a, 0xfa, 0xb2, 0xdc, 0x96, 0xd6, 0x7c, 0x45, 0x1a, 0xea, 0xee, 0x2d, - 0x13, 0x82, 0xe8, 0x6b, 0xb3, 0x0c, 0xc5, 0xd0, 0x77, 0xce, 0xce, 0xb8, 0x6f, 0xac, 0x46, 0x43, - 0x13, 0x27, 0x8d, 0xf7, 0x42, 0x3e, 0x11, 0x42, 0x90, 0xf1, 0x9f, 0x32, 0x50, 0x91, 0x67, 0xe7, - 0xe7, 0x76, 0x57, 0xac, 0x6b, 0x91, 0x87, 0xa4, 0x1a, 0xc7, 0x81, 0x86, 0xef, 0x40, 0x63, 0x2c, - 0x04, 0x22, 0x21, 0xb0, 0x27, 0x7c, 0x15, 0x75, 0x05, 0x96, 0xf2, 0xc8, 0x06, 0x2c, 0xa1, 0x78, - 0x12, 0x58, 0xa1, 0x33, 0xb2, 0x54, 0xa1, 0x8c, 0xf2, 0x5b, 0xa4, 0xa2, 0xbe, 0x33, 0xda, 0x97, - 0x05, 0xe2, 0x96, 0x0e, 0x42, 0xfb, 0x8c, 0x4b, 0xd1, 0x97, 0x3e, 0x8c, 0x16, 0xac, 0xce, 0xc8, - 0xea, 0x4a, 0xcf, 0xf8, 0xef, 0x0d, 0x58, 0x9b, 0x2b, 0x92, 0xfa, 0x46, 0x64, 0xa3, 0x1f, 0x39, - 0xe3, 0x13, 0x2f, 0x32, 0x85, 0x65, 0x34, 0x1b, 0xfd, 0x9e, 0x28, 0x51, 0xa6, 0x30, 0x0e, 0x2b, - 0x8a, 0x20, 0xd0, 0x96, 0x15, 0x89, 0xf3, 0x59, 0x14, 0x36, 0xdf, 0x4b, 0x32, 0xaa, 0xd9, 0xee, - 0x14, 0x5c, 0xbf, 0xfe, 0x96, 0x26, 0x73, 0xb0, 0x80, 0x9d, 0x42, 0x2b, 0xa2, 0x3b, 0x29, 0x1f, - 0x69, 0xba, 0x89, 0xe8, 0xe9, 0x1b, 0x2f, 0xe9, 0x29, 0x61, 0x24, 0x31, 0x57, 0x15, 0xb9, 0x52, - 0x63, 0x51, 0x3f, 0x17, 0xf0, 0xba, 0xea, 0x07, 0x65, 0x9d, 0xf9, 0xde, 0xf2, 0xaf, 0x34, 0x2f, - 0x34, 0xfe, 0x24, 0xbb, 0xbc, 0x23, 0x1b, 0x8e, 0x8a, 0xf4, 0x7e, 0xcf, 0x61, 0xf5, 0xd2, 0x76, - 0x42, 0x35, 0x3f, 0x4d, 0x2d, 0x2a, 0x60, 0x7f, 0x4f, 0x5e, 0xd2, 0xdf, 0xa7, 0x54, 0x39, 0x21, - 0xfd, 0x2d, 0x5f, 0xce, 0x03, 0x83, 0xf5, 0x7f, 0x97, 0x85, 0x7a, 0xb2, 0x15, 0x71, 0xa8, 0x25, - 0x1f, 0x52, 0xf2, 0x84, 0x94, 0xc7, 0xa5, 0x89, 0xf6, 0x80, 0xe4, 0x88, 0x79, 0xe3, 0x71, 0x36, - 0xc5, 0x78, 0xac, 0xdb, 0x6c, 0x73, 0x2f, 0xf3, 0x6d, 0xe5, 0x5f, 0xc9, 0xb7, 0x55, 0x48, 0xf3, - 0x6d, 0xdd, 0xec, 0x10, 0x59, 0xf8, 0xb9, 0x1c, 0x22, 0xc5, 0x9b, 0x1d, 0x22, 0xeb, 0x7f, 0x95, - 0x01, 0x36, 0x4f, 0xa9, 0xec, 0x29, 0xd9, 0xc9, 0x5d, 0x3e, 0x92, 0x5c, 0xec, 0x9b, 0xaf, 0x46, - 0xed, 0x6a, 0x83, 0x54, 0x6d, 0xf6, 0x08, 0x96, 0xf4, 0xb8, 0x60, 0x5d, 0x55, 0xa9, 0x99, 0x4c, - 0x2f, 0x8a, 0x15, 0x5a, 0xcd, 0xb1, 0x97, 0x7f, 0xa9, 0x63, 0xaf, 0xf0, 0x52, 0xc7, 0xde, 0x42, - 0xd2, 0xb1, 0xb7, 0xfe, 0x5f, 0x32, 0xb0, 0x94, 0x42, 0x54, 0x5f, 0xdd, 0x9c, 0x05, 0x2d, 0x24, - 0x58, 0x4c, 0x56, 0xd2, 0x82, 0xce, 0x5d, 0xf6, 0xa0, 0x12, 0xfb, 0x8a, 0x54, 0xdc, 0xfc, 0xc3, - 0x97, 0x9d, 0xf4, 0xb8, 0x86, 0xa9, 0x57, 0x5f, 0xff, 0x02, 0x2a, 0x5a, 0x99, 0x58, 0x44, 0xa2, - 0x20, 0x2d, 0x9c, 0x82, 0xee, 0x70, 0xd4, 0xb3, 0xee, 0x81, 0x34, 0xe4, 0x52, 0x39, 0xd1, 0xba, - 0xbc, 0xb0, 0x11, 0x61, 0x03, 0x96, 0x94, 0x0b, 0x83, 0xc7, 0x51, 0x53, 0x92, 0xed, 0x2f, 0x4a, - 0x47, 0x06, 0x8f, 0x82, 0xb0, 0xd6, 0x7f, 0x02, 0xb5, 0x04, 0x47, 0xf8, 0xea, 0xd6, 0x72, 0x56, - 0x6b, 0xa4, 0xb1, 0xea, 0x5a, 0xe3, 0xfa, 0xff, 0xc9, 0x01, 0x9b, 0x67, 0x4a, 0xbf, 0xcc, 0x21, - 0xcc, 0xef, 0x78, 0x2e, 0x65, 0xc7, 0xff, 0x9f, 0x5d, 0x92, 0xef, 0xc2, 0xa2, 0x4c, 0xcc, 0xd0, - 0x3c, 0x3c, 0x44, 0xf5, 0xcd, 0xa8, 0x40, 0x8d, 0xe2, 0x3b, 0xb3, 0x0e, 0xe2, 0x52, 0x22, 0x16, - 0x5d, 0x93, 0x12, 0x66, 0xfc, 0xc4, 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, 0x47, 0x85, 0xa5, - 0xfe, 0xe4, 0x57, 0xbf, 0xf4, 0x3d, 0xb1, 0xd1, 0xc6, 0xfa, 0x28, 0x9a, 0x98, 0xb2, 0x31, 0xe3, - 0x3d, 0xa8, 0x68, 0x60, 0xf4, 0x7a, 0x74, 0xf7, 0x37, 0x0f, 0x9b, 0xb7, 0x58, 0x0d, 0xca, 0x66, - 0x67, 0xeb, 0xf0, 0x93, 0x8e, 0xd9, 0xd9, 0x6e, 0x66, 0x58, 0x09, 0xf2, 0x7b, 0x87, 0xbd, 0x7e, - 0x33, 0x6b, 0xac, 0x43, 0x4b, 0xb6, 0x38, 0x6f, 0x01, 0xfd, 0xdd, 0x7c, 0x64, 0x7c, 0xc0, 0x42, - 0xa9, 0x6b, 0x7c, 0x0b, 0xaa, 0xfa, 0x1d, 0x2e, 0x29, 0x62, 0xc6, 0xc9, 0x28, 0xb4, 0x0c, 0x4f, - 0x63, 0x82, 0x5b, 0x40, 0xae, 0xa3, 0x61, 0x54, 0x8d, 0x04, 0xb3, 0x17, 0xf8, 0x1a, 0x50, 0xe6, - 0x4c, 0x90, 0xe1, 0xff, 0x07, 0xf5, 0xa4, 0x39, 0x50, 0x1e, 0xf5, 0x34, 0xa1, 0x5b, 0xd4, 0x4e, - 0xd8, 0x07, 0xd9, 0xf7, 0xa1, 0x39, 0x6b, 0x4e, 0x94, 0x21, 0xbb, 0x37, 0xd4, 0x6f, 0x38, 0x49, - 0x0b, 0x23, 0xdb, 0x85, 0xe5, 0x34, 0x29, 0x06, 0xe9, 0xe3, 0x66, 0x6d, 0x8b, 0xcd, 0x4b, 0x2a, - 0xec, 0xbb, 0xd2, 0x6a, 0x5c, 0x48, 0xf3, 0xbd, 0x69, 0x8b, 0xbd, 0x41, 0xff, 0x69, 0xf6, 0xe3, - 0x0b, 0x80, 0x18, 0xc6, 0x9a, 0x50, 0x3d, 0x3c, 0xea, 0x1c, 0x58, 0x5b, 0xbb, 0xed, 0x83, 0x83, - 0xce, 0x5e, 0xf3, 0x16, 0x63, 0x50, 0x47, 0xa7, 0xd9, 0x76, 0x04, 0xcb, 0x08, 0x98, 0xb4, 0xde, - 0x2b, 0x58, 0x96, 0x2d, 0x43, 0xb3, 0x7b, 0x30, 0x03, 0xcd, 0xb1, 0x16, 0x2c, 0x1f, 0x75, 0xc8, - 0xcf, 0x96, 0x68, 0x37, 0x2f, 0x24, 0x63, 0x39, 0x5d, 0x21, 0x19, 0x53, 0x82, 0x91, 0x3c, 0x07, - 0x4a, 0x60, 0xfc, 0xbd, 0x0c, 0xac, 0xcc, 0x14, 0xc4, 0x61, 0xe3, 0x24, 0x2e, 0x26, 0x05, 0xc5, - 0x2a, 0x02, 0xd5, 0x69, 0x7a, 0x17, 0x16, 0x23, 0x0d, 0x7a, 0x86, 0xdd, 0x37, 0xa3, 0x02, 0x85, - 0xfc, 0x08, 0x96, 0x34, 0x45, 0x7c, 0x86, 0x57, 0x30, 0xad, 0x48, 0x56, 0x30, 0xd6, 0xa2, 0xf0, - 0xdc, 0x99, 0x51, 0x0f, 0x29, 0x6b, 0x49, 0x2f, 0x88, 0x8d, 0xea, 0xc9, 0xf1, 0xaa, 0x4f, 0xf6, - 0x78, 0x86, 0x10, 0x92, 0xa3, 0xd5, 0x37, 0x5c, 0x75, 0xff, 0x07, 0x0b, 0xc0, 0x3e, 0x9e, 0x72, - 0xff, 0x1a, 0xc3, 0xc2, 0x83, 0x97, 0xc5, 0x49, 0x29, 0x6d, 0x33, 0xfb, 0x4a, 0xa9, 0x1f, 0x69, - 0xa9, 0x17, 0xf9, 0x97, 0xa7, 0x5e, 0x14, 0x5e, 0x96, 0x7a, 0xf1, 0x26, 0xd4, 0x9c, 0x33, 0xd7, - 0x13, 0xac, 0x50, 0x88, 0x7c, 0x41, 0x6b, 0xe1, 0x7e, 0xee, 0x41, 0xd5, 0xac, 0x4a, 0xa0, 0x10, - 0xf8, 0x02, 0xf6, 0x51, 0x8c, 0xc4, 0x87, 0x67, 0x98, 0x26, 0xa4, 0x33, 0xc1, 0xce, 0xf0, 0x8c, - 0x4b, 0xe5, 0x1a, 0xcd, 0x4d, 0xaa, 0xb2, 0x80, 0x07, 0xec, 0x2d, 0xa8, 0x07, 0xde, 0x54, 0x48, - 0xd0, 0x6a, 0x19, 0xc8, 0xec, 0x5e, 0x25, 0xe8, 0x91, 0xf2, 0xb1, 0x2c, 0x4d, 0x03, 0x6e, 0x8d, - 0x9d, 0x20, 0x10, 0x72, 0xcf, 0xc0, 0x73, 0x43, 0xdf, 0x1b, 0x49, 0x4b, 0xfa, 0xe2, 0x34, 0xe0, - 0xfb, 0x54, 0xb2, 0x45, 0x05, 0xec, 0xdb, 0xf1, 0x90, 0x26, 0xb6, 0xe3, 0x07, 0x2d, 0xc0, 0x21, - 0xa9, 0x99, 0xa2, 0xa0, 0x6a, 0x3b, 0x7e, 0x34, 0x16, 0xf1, 0x11, 0xcc, 0xa4, 0x84, 0x54, 0x66, - 0x53, 0x42, 0x7e, 0x94, 0x9e, 0x12, 0x52, 0xc3, 0xa6, 0x1f, 0xcb, 0xa6, 0xe7, 0xb7, 0xf8, 0x4b, - 0x65, 0x86, 0xcc, 0x67, 0xba, 0xd4, 0xbf, 0x4c, 0xa6, 0x4b, 0x23, 0x2d, 0xd3, 0xe5, 0x3d, 0xa8, - 0x60, 0x0e, 0x82, 0x75, 0xee, 0x08, 0xe1, 0x88, 0x3c, 0x03, 0x4d, 0x3d, 0x49, 0x61, 0xd7, 0x71, - 0x43, 0x13, 0x7c, 0xf5, 0x67, 0x30, 0x9f, 0x74, 0xb2, 0xf8, 0x4b, 0x4c, 0x3a, 0x91, 0xb9, 0x12, - 0x1b, 0x50, 0x52, 0xfb, 0xc4, 0x18, 0xe4, 0x4f, 0x7d, 0x6f, 0xac, 0x2c, 0xa6, 0xe2, 0x6f, 0x56, - 0x87, 0x6c, 0xe8, 0xc9, 0xca, 0xd9, 0xd0, 0x33, 0x7e, 0x13, 0x2a, 0x1a, 0xa9, 0xb1, 0x37, 0xc8, - 0x36, 0x23, 0x94, 0x10, 0x29, 0xb5, 0xd1, 0x2a, 0x96, 0x25, 0xb4, 0x3b, 0x14, 0xfc, 0x66, 0xe8, - 0xf8, 0x1c, 0xd3, 0xc3, 0x2c, 0x9f, 0x5f, 0x70, 0x3f, 0x50, 0x16, 0xec, 0x66, 0x54, 0x60, 0x12, - 0xdc, 0xf8, 0x6b, 0xb0, 0x94, 0xd8, 0x5b, 0xc9, 0x22, 0xde, 0x82, 0x05, 0x5c, 0x37, 0xe5, 0x61, - 0x4c, 0x26, 0x7f, 0xc8, 0x32, 0xcc, 0xfb, 0x25, 0xe3, 0xbb, 0x35, 0xf1, 0xbd, 0x13, 0xec, 0x24, - 0x63, 0x56, 0x24, 0xec, 0xc8, 0xf7, 0x4e, 0x8c, 0x3f, 0xcf, 0x41, 0x6e, 0xd7, 0x9b, 0xe8, 0x41, - 0x35, 0x99, 0xb9, 0xa0, 0x1a, 0xa9, 0x59, 0x59, 0x91, 0xe6, 0x24, 0x85, 0x61, 0x34, 0x3b, 0x2b, - 0xed, 0xe9, 0x01, 0xd4, 0x05, 0x9f, 0x08, 0x3d, 0xa1, 0x9a, 0x5e, 0xda, 0x3e, 0x89, 0x9a, 0x39, - 0x3a, 0x7c, 0xf6, 0x38, 0xec, 0x7b, 0x3b, 0x04, 0x67, 0xcb, 0x90, 0x8b, 0xf4, 0x02, 0x2c, 0x16, - 0x9f, 0x6c, 0x15, 0x16, 0x30, 0x28, 0xf2, 0x5a, 0xba, 0xd0, 0xe4, 0x17, 0xfb, 0x26, 0x2c, 0x25, - 0xdb, 0x25, 0x56, 0x24, 0x65, 0x23, 0xbd, 0x61, 0xe4, 0x49, 0xb7, 0x41, 0xf0, 0x11, 0xc2, 0x91, - 0x9e, 0xf8, 0x53, 0xce, 0xb1, 0x48, 0x63, 0x7a, 0xa5, 0x04, 0xd3, 0xbb, 0x07, 0x95, 0x70, 0x74, - 0x61, 0x4d, 0xec, 0xeb, 0x91, 0x67, 0x0f, 0xe5, 0xf9, 0x86, 0x70, 0x74, 0x71, 0x44, 0x10, 0xf6, - 0x08, 0x60, 0x3c, 0x99, 0xc8, 0xb3, 0x87, 0x56, 0xdc, 0x98, 0x94, 0xf7, 0x8f, 0x8e, 0x88, 0xe4, - 0xcc, 0xf2, 0x78, 0x32, 0xa1, 0x3f, 0xd9, 0x36, 0xd4, 0x53, 0x53, 0xb8, 0xee, 0xaa, 0x18, 0x3e, - 0x6f, 0xb2, 0x91, 0x72, 0x38, 0x6b, 0x03, 0x1d, 0xb6, 0xfe, 0x7d, 0x60, 0xbf, 0x60, 0x22, 0x55, - 0x1f, 0xca, 0xd1, 0xf8, 0xf4, 0x3c, 0x24, 0x8c, 0xca, 0xad, 0x24, 0xf2, 0x90, 0xda, 0xc3, 0xa1, - 0x2f, 0xf8, 0x22, 0x5d, 0x98, 0x11, 0xcb, 0x07, 0xed, 0xc6, 0x6c, 0x13, 0xdf, 0x37, 0xfe, 0x32, - 0x03, 0x05, 0x4a, 0x8a, 0x7a, 0x1b, 0x1a, 0x84, 0x1f, 0x05, 0x28, 0x49, 0xc7, 0x1b, 0xdd, 0xbb, - 0x7d, 0x19, 0x9b, 0x24, 0x8e, 0x85, 0x96, 0xd0, 0x99, 0x8d, 0x76, 0x5e, 0x4b, 0xea, 0xbc, 0x07, - 0xe5, 0xa8, 0x6b, 0x8d, 0x74, 0x4a, 0xaa, 0x67, 0xf6, 0x3a, 0xe4, 0xcf, 0xbd, 0x89, 0x32, 0x71, - 0x40, 0xbc, 0x92, 0x26, 0xc2, 0xe3, 0xb1, 0x88, 0x3e, 0x68, 0xf0, 0x52, 0x35, 0x8f, 0x3a, 0x41, - 0x32, 0x98, 0x9f, 0xe3, 0x42, 0xca, 0x1c, 0x8f, 0xa1, 0x21, 0xf8, 0x80, 0xe6, 0x00, 0xbf, 0xf9, - 0xd2, 0xfc, 0xba, 0x90, 0xf0, 0x06, 0xa3, 0xe9, 0x90, 0xeb, 0x06, 0x26, 0x8c, 0x96, 0x91, 0x70, - 0x25, 0x59, 0x1b, 0x7f, 0x90, 0x21, 0xfe, 0x22, 0xda, 0x65, 0x0f, 0x20, 0x2f, 0xee, 0xb7, 0x19, - 0x03, 0x68, 0x14, 0x1e, 0x2d, 0xf0, 0x4c, 0xc4, 0xc0, 0x2c, 0xe8, 0xe9, 0x38, 0xd9, 0x7a, 0xcd, - 0xac, 0xb8, 0xd3, 0x71, 0x64, 0xa3, 0xf9, 0x9a, 0x9a, 0xd6, 0x8c, 0x7d, 0x83, 0x66, 0x1f, 0x1d, - 0xd3, 0x0d, 0x2d, 0xec, 0x26, 0x9f, 0xb8, 0x31, 0x95, 0x14, 0x38, 0x3c, 0xe3, 0x5a, 0xb8, 0xcd, - 0x1f, 0x65, 0xa1, 0x96, 0x18, 0x11, 0xc6, 0x1d, 0x89, 0x0b, 0x80, 0x8c, 0xeb, 0x72, 0xbf, 0x41, - 0x80, 0xa4, 0xa0, 0xae, 0xad, 0x53, 0x36, 0xb1, 0x4e, 0x91, 0xab, 0x3f, 0xa7, 0xbb, 0xfa, 0x1f, - 0x43, 0x39, 0x4e, 0xe4, 0x4d, 0x0e, 0x49, 0xf4, 0xa7, 0x82, 0xc4, 0x63, 0xa4, 0x38, 0x38, 0xa0, - 0xa0, 0x07, 0x07, 0x7c, 0x4f, 0xf3, 0x25, 0x2f, 0x60, 0x33, 0x46, 0xda, 0x8a, 0xfe, 0x52, 0x3c, - 0xc9, 0xc6, 0x47, 0x50, 0xd1, 0x06, 0xaf, 0xfb, 0x8c, 0x33, 0x09, 0x9f, 0x71, 0x94, 0xce, 0x91, - 0x8d, 0xd3, 0x39, 0x8c, 0xdf, 0xce, 0x42, 0x4d, 0x9c, 0x2f, 0xc7, 0x3d, 0x3b, 0xf2, 0x46, 0xce, - 0x00, 0x8d, 0xed, 0xd1, 0x09, 0x93, 0x82, 0x96, 0x3a, 0x67, 0xf2, 0x88, 0x91, 0x9c, 0xa5, 0x67, - 0xad, 0x11, 0x93, 0x8e, 0xb2, 0xd6, 0x0c, 0xa8, 0x09, 0xc6, 0x78, 0x62, 0x07, 0x5c, 0x4b, 0x33, - 0x36, 0x2b, 0xa7, 0x9c, 0x6f, 0xda, 0x01, 0x71, 0xc8, 0x6f, 0xc2, 0x92, 0xc0, 0xc1, 0x84, 0x9d, - 0xb1, 0x33, 0x1a, 0x39, 0x84, 0x49, 0x16, 0x9c, 0xe6, 0x29, 0xe7, 0xa6, 0x1d, 0xf2, 0x7d, 0x51, - 0x20, 0xb3, 0x92, 0x4b, 0x43, 0x27, 0xb0, 0x4f, 0xe2, 0xe8, 0xb0, 0xe8, 0x1b, 0x5d, 0x64, 0xf6, - 0x95, 0xe6, 0x22, 0xa3, 0xcc, 0xbd, 0xca, 0xd8, 0xbe, 0x8a, 0x5c, 0x64, 0x33, 0x94, 0x54, 0x9c, - 0xa5, 0x24, 0xe3, 0x3f, 0x66, 0xa1, 0xa2, 0x91, 0xe5, 0xab, 0xdc, 0xae, 0x77, 0xe7, 0x9c, 0x23, - 0x65, 0xdd, 0x0f, 0xf2, 0x66, 0xb2, 0x4b, 0xf4, 0xa4, 0x53, 0xfe, 0xb3, 0x46, 0xc0, 0x77, 0xa0, - 0x2c, 0x4e, 0xdd, 0x7b, 0x68, 0x6b, 0x94, 0xd9, 0xfb, 0x08, 0x38, 0x9a, 0x9e, 0xa8, 0xc2, 0x27, - 0x58, 0x58, 0x88, 0x0b, 0x9f, 0x88, 0xc2, 0x17, 0x85, 0x84, 0x7e, 0x07, 0xaa, 0xb2, 0x55, 0xdc, - 0x53, 0x9c, 0x6e, 0x7c, 0xea, 0x13, 0xfb, 0x6d, 0x56, 0xa8, 0x3b, 0xda, 0x7c, 0x59, 0xf1, 0x89, - 0xaa, 0x58, 0x7a, 0x59, 0xc5, 0x27, 0xf4, 0x61, 0xec, 0x44, 0x51, 0xb6, 0x18, 0xc5, 0xa1, 0xf8, - 0xd8, 0x23, 0x58, 0x52, 0xec, 0x6a, 0xea, 0xda, 0xae, 0xeb, 0x4d, 0xdd, 0x01, 0x57, 0x79, 0x1e, - 0x4c, 0x16, 0x1d, 0xc7, 0x25, 0xc6, 0x30, 0x4a, 0x04, 0xa4, 0x68, 0x90, 0x87, 0x50, 0x20, 0xb9, - 0x9c, 0x84, 0x8f, 0x74, 0xc6, 0x45, 0x28, 0xec, 0x01, 0x14, 0x48, 0x3c, 0xcf, 0xde, 0xc8, 0x6c, - 0x08, 0xc1, 0xd8, 0x80, 0x06, 0x8a, 0x98, 0x1a, 0xc7, 0x7d, 0x91, 0x54, 0x62, 0x2c, 0x03, 0x3b, - 0xa0, 0x43, 0xa4, 0x47, 0x29, 0xfd, 0xd7, 0x1c, 0x54, 0x34, 0xb0, 0x60, 0x8b, 0x18, 0xd7, 0x62, - 0x0d, 0x1d, 0x7b, 0xcc, 0x95, 0x4b, 0xa7, 0x66, 0xd6, 0x10, 0xba, 0x2d, 0x81, 0xe2, 0x52, 0xb0, - 0x2f, 0xce, 0x2c, 0x6f, 0x1a, 0x5a, 0x43, 0x7e, 0xe6, 0x73, 0x2e, 0x85, 0xa5, 0xaa, 0x7d, 0x71, - 0x76, 0x38, 0x0d, 0xb7, 0x11, 0x26, 0xb0, 0x04, 0x51, 0x6b, 0x58, 0x32, 0x14, 0x63, 0x6c, 0x5f, - 0xc5, 0x58, 0x32, 0x1e, 0x88, 0x96, 0x28, 0x1f, 0xc5, 0x03, 0x91, 0xda, 0x32, 0xcb, 0xc9, 0x0b, - 0xf3, 0x9c, 0xfc, 0xdb, 0xb0, 0x4a, 0x9c, 0x5c, 0xf2, 0x08, 0x6b, 0x86, 0xa4, 0x96, 0xb1, 0x54, - 0x4e, 0x52, 0x93, 0xbf, 0x9a, 0x62, 0x06, 0xea, 0x7c, 0x04, 0xce, 0x8f, 0xe9, 0x44, 0x65, 0x4c, - 0x31, 0x33, 0xd9, 0x78, 0xcf, 0xf9, 0x31, 0x17, 0x98, 0xe8, 0x6f, 0xd6, 0x31, 0x65, 0xe4, 0xf1, - 0xd8, 0x71, 0x67, 0x31, 0xed, 0xab, 0x24, 0x66, 0x59, 0x62, 0xda, 0x57, 0x3a, 0xe6, 0xfb, 0xb0, - 0x36, 0xe6, 0x43, 0xc7, 0x4e, 0x36, 0x6b, 0xc5, 0x12, 0xc4, 0x32, 0x15, 0x6b, 0x75, 0x7a, 0xa4, - 0x41, 0x8a, 0xd5, 0xf8, 0xb1, 0x37, 0x3e, 0x71, 0xe8, 0xf2, 0x24, 0x0f, 0x78, 0xde, 0xac, 0xbb, - 0xd3, 0xf1, 0x0f, 0x11, 0x2c, 0xaa, 0x04, 0x46, 0x0d, 0x2a, 0xbd, 0xd0, 0x9b, 0xa8, 0x6d, 0xae, - 0x43, 0x95, 0x3e, 0x65, 0x16, 0xcf, 0x1d, 0xb8, 0x8d, 0xb4, 0xd9, 0xf7, 0x26, 0xde, 0xc8, 0x3b, - 0xbb, 0x4e, 0x18, 0x94, 0xfe, 0x73, 0x06, 0x96, 0x12, 0xa5, 0xf2, 0x9c, 0x7f, 0x9b, 0x0e, 0x56, - 0x94, 0x8a, 0x41, 0xe4, 0xbc, 0xa8, 0x5d, 0x3e, 0x84, 0x48, 0xa7, 0x4a, 0xa5, 0x67, 0xb4, 0xe3, - 0x14, 0x62, 0x55, 0x91, 0x68, 0xbb, 0x35, 0x4f, 0xdb, 0xb2, 0xbe, 0x4a, 0x2e, 0x56, 0x4d, 0xfc, - 0xaa, 0x8c, 0x0e, 0x1f, 0xca, 0x29, 0xe7, 0x92, 0xf1, 0xaf, 0xba, 0xf1, 0x49, 0x8d, 0x20, 0xb6, - 0x48, 0x05, 0xc6, 0xbf, 0xc8, 0x00, 0xc4, 0xa3, 0xc3, 0x08, 0xdc, 0xe8, 0x02, 0xa5, 0xd7, 0x79, - 0xb4, 0xcb, 0xf2, 0x0d, 0xa8, 0x46, 0x81, 0x78, 0xf1, 0x95, 0x5c, 0x51, 0x30, 0x71, 0x2f, 0xbf, - 0x03, 0x8d, 0xb3, 0x91, 0x77, 0x82, 0xa2, 0x93, 0xbc, 0x40, 0x29, 0x97, 0xa9, 0x4e, 0x60, 0x75, - 0x2d, 0xc6, 0x17, 0x78, 0x3e, 0x35, 0x56, 0x4f, 0xbf, 0x8e, 0x8d, 0xdf, 0xc9, 0x46, 0x11, 0x49, - 0xf1, 0x4a, 0xbc, 0x58, 0xcf, 0xf8, 0x79, 0x1c, 0xdb, 0x2f, 0x72, 0xe8, 0x7c, 0x04, 0x75, 0x9f, - 0xb8, 0xa3, 0x62, 0x9d, 0xf9, 0x17, 0xb0, 0xce, 0x9a, 0x9f, 0xb8, 0x72, 0xbf, 0x0e, 0x4d, 0x7b, - 0x78, 0xc1, 0xfd, 0xd0, 0x41, 0xb3, 0x31, 0x0a, 0x6a, 0x32, 0x06, 0x48, 0x83, 0xa3, 0x44, 0xf4, - 0x0e, 0x34, 0x64, 0x66, 0x59, 0x84, 0x29, 0xdf, 0xaa, 0x88, 0xc1, 0x02, 0xd1, 0xf8, 0xd7, 0x2a, - 0x04, 0x2a, 0xb9, 0xbb, 0x2f, 0x5e, 0x15, 0x7d, 0x86, 0xd9, 0x79, 0x97, 0x95, 0x24, 0x24, 0x69, - 0x8d, 0x96, 0xfc, 0x88, 0x80, 0xd2, 0x16, 0x9d, 0x5c, 0xd6, 0xfc, 0xab, 0x2c, 0xab, 0xf1, 0x27, - 0x19, 0x28, 0xee, 0x7a, 0x13, 0xa1, 0x97, 0x0b, 0x79, 0x0e, 0x8f, 0x49, 0xe4, 0x86, 0x58, 0x10, - 0x9f, 0xdd, 0xe1, 0x8b, 0x33, 0x31, 0x52, 0xe5, 0x8d, 0x5a, 0x52, 0xde, 0xf8, 0x1e, 0xdc, 0x41, - 0x27, 0x8f, 0xef, 0x4d, 0x3c, 0x5f, 0x1c, 0x55, 0x7b, 0x44, 0x72, 0x87, 0xe7, 0x86, 0xe7, 0x8a, - 0x77, 0xde, 0x3e, 0xe5, 0xfc, 0x48, 0xc3, 0xd8, 0x8f, 0x10, 0x30, 0x45, 0x69, 0x14, 0x5e, 0x58, - 0xa4, 0x2a, 0x4a, 0xc1, 0x88, 0x38, 0x6a, 0x43, 0x14, 0x74, 0x10, 0x8e, 0xa2, 0x91, 0xf1, 0x5d, - 0x28, 0x47, 0x56, 0x07, 0xf6, 0x2e, 0x94, 0xcf, 0xbd, 0x89, 0x34, 0x4d, 0x64, 0x12, 0xd9, 0x2a, - 0x72, 0xd6, 0x66, 0xe9, 0x9c, 0xfe, 0x08, 0x8c, 0x3f, 0x2f, 0x42, 0xb1, 0xeb, 0x5e, 0x78, 0xce, - 0x00, 0x83, 0xa8, 0xc6, 0x7c, 0xec, 0xa9, 0xf4, 0x56, 0xf1, 0x37, 0x06, 0x4a, 0xc4, 0x2f, 0x4e, - 0xe4, 0x64, 0xa0, 0x44, 0xf4, 0xd6, 0xc4, 0x0a, 0x2c, 0xf8, 0xfa, 0x93, 0x11, 0x05, 0x1f, 0xc3, - 0x3a, 0x23, 0xa5, 0xad, 0xa0, 0xa5, 0x07, 0x8b, 0xb6, 0xe8, 0x29, 0x03, 0x5c, 0x32, 0x4a, 0x37, - 0x2a, 0x23, 0x04, 0x17, 0xec, 0x35, 0x28, 0xca, 0xe4, 0x10, 0x0a, 0xb5, 0xa7, 0x38, 0x4c, 0x09, - 0x42, 0x6a, 0xf0, 0x39, 0x39, 0xe9, 0x22, 0x89, 0x4a, 0xe8, 0xe9, 0x12, 0xb8, 0x2d, 0x68, 0xed, - 0x1e, 0x54, 0x08, 0x9f, 0x50, 0x4a, 0x32, 0xec, 0x09, 0x41, 0x88, 0x90, 0xf2, 0xf2, 0x4a, 0x39, - 0xf5, 0xe5, 0x15, 0x8c, 0x92, 0x8b, 0xb8, 0x2c, 0x4d, 0x11, 0xe8, 0xbd, 0x0d, 0x0d, 0xae, 0x9e, - 0x1d, 0x92, 0xca, 0x3d, 0x65, 0xdf, 0x29, 0xe5, 0xfe, 0x4d, 0xa8, 0x9d, 0xda, 0xa3, 0xd1, 0x89, - 0x3d, 0x78, 0x4e, 0x3a, 0x69, 0x95, 0xcc, 0x70, 0x0a, 0x88, 0x4a, 0xe9, 0x3d, 0xa8, 0x68, 0xbb, - 0x8c, 0x31, 0x4d, 0x79, 0x13, 0xe2, 0xfd, 0x9d, 0x35, 0x35, 0xd5, 0x5f, 0xc1, 0xd4, 0xa4, 0xc5, - 0x76, 0x35, 0x92, 0xb1, 0x5d, 0x77, 0x90, 0x9b, 0xca, 0xf8, 0x9f, 0x26, 0x3d, 0xee, 0x60, 0x0f, - 0x87, 0x18, 0xff, 0x43, 0x2f, 0xa9, 0xe1, 0xe2, 0x51, 0xf9, 0x22, 0x09, 0xb5, 0x04, 0x23, 0x94, - 0xbb, 0x64, 0x2f, 0x9d, 0xd8, 0xce, 0x10, 0x63, 0x69, 0x49, 0x8d, 0x2d, 0xda, 0xe3, 0xf0, 0xc8, - 0x76, 0x86, 0xec, 0x3e, 0x54, 0x55, 0x31, 0xde, 0x8e, 0x4b, 0xb4, 0xfe, 0xb2, 0x58, 0xdc, 0x89, - 0x06, 0xd4, 0x22, 0x8c, 0x71, 0x9c, 0x42, 0x57, 0x91, 0x28, 0x48, 0x07, 0xef, 0x61, 0x4c, 0x45, - 0xc8, 0x31, 0x51, 0xae, 0xfe, 0xe4, 0x8e, 0x9c, 0xab, 0xa4, 0x52, 0xf5, 0x3f, 0x79, 0x69, 0x08, - 0x53, 0x08, 0x62, 0xe4, 0x2c, 0x5a, 0x4d, 0x08, 0x62, 0x12, 0x15, 0x9d, 0x45, 0x84, 0xc0, 0xbe, - 0xab, 0x29, 0x52, 0x2d, 0x44, 0x7e, 0x6d, 0xa6, 0xfd, 0x9b, 0x52, 0x09, 0xee, 0x02, 0x38, 0x81, - 0xb8, 0x65, 0x02, 0xee, 0x0e, 0x31, 0xe7, 0xad, 0x64, 0x96, 0x9d, 0xe0, 0x19, 0x01, 0xbe, 0x5a, - 0x0d, 0xab, 0x0d, 0x55, 0x7d, 0x9a, 0xac, 0x04, 0xf9, 0xc3, 0xa3, 0xce, 0x41, 0xf3, 0x16, 0xab, - 0x40, 0xb1, 0xd7, 0xe9, 0xf7, 0xf7, 0xd0, 0xe5, 0x54, 0x85, 0x52, 0x94, 0xb9, 0x93, 0x15, 0x5f, - 0xed, 0xad, 0xad, 0xce, 0x51, 0xbf, 0xb3, 0xdd, 0xcc, 0xfd, 0x20, 0x5f, 0xca, 0x36, 0x73, 0xc6, - 0x5f, 0xe4, 0xa0, 0xa2, 0xad, 0xc2, 0x8b, 0x99, 0xf1, 0x5d, 0x00, 0x54, 0x69, 0xe2, 0xf0, 0xb0, - 0xbc, 0x59, 0x16, 0x10, 0xda, 0x7c, 0xdd, 0x58, 0x9e, 0xa3, 0x57, 0x43, 0x94, 0xb1, 0xfc, 0x4d, - 0xa8, 0xd1, 0x03, 0x1c, 0xba, 0xe3, 0xb0, 0x60, 0x56, 0x09, 0x28, 0x59, 0x35, 0xa6, 0xfe, 0x21, - 0x12, 0x26, 0x85, 0xc8, 0x74, 0x7c, 0x02, 0x61, 0x5a, 0x08, 0xe6, 0xf4, 0x04, 0xde, 0xe8, 0x82, - 0x13, 0x06, 0x49, 0x84, 0x15, 0x09, 0xeb, 0xcb, 0xdc, 0x43, 0xc9, 0x0f, 0xb5, 0xdc, 0xb3, 0x82, - 0x59, 0x25, 0xa0, 0xec, 0xe8, 0x9b, 0x8a, 0x80, 0x4a, 0x48, 0x40, 0x6b, 0xf3, 0xd4, 0x90, 0x20, - 0x9e, 0xbd, 0x39, 0x7b, 0x56, 0x19, 0x09, 0xe3, 0x6b, 0xf3, 0xf5, 0x5e, 0x6e, 0xd7, 0x62, 0xef, - 0x02, 0x1b, 0x4f, 0x26, 0x56, 0x8a, 0xa5, 0x29, 0x6f, 0x36, 0xc6, 0x93, 0x49, 0x5f, 0x33, 0xc4, - 0x7c, 0x05, 0x46, 0xb0, 0xcf, 0x81, 0xb5, 0xc5, 0x01, 0xc6, 0x21, 0x46, 0x26, 0xd4, 0x98, 0x2d, - 0x67, 0x74, 0xb6, 0x9c, 0xc2, 0xfd, 0xb2, 0xa9, 0xdc, 0xef, 0x45, 0x7c, 0xc2, 0xd8, 0x81, 0xca, - 0x91, 0xf6, 0xbc, 0xcf, 0x7d, 0x71, 0x43, 0xa8, 0x87, 0x7d, 0xe8, 0xee, 0x20, 0xe3, 0x96, 0x2f, - 0xdf, 0xf3, 0xd1, 0x46, 0x93, 0xd5, 0x46, 0x63, 0xfc, 0xf3, 0x0c, 0x3d, 0x9d, 0x10, 0x0d, 0x3e, - 0x7e, 0x51, 0x48, 0xf9, 0x81, 0xe2, 0x14, 0xd1, 0x8a, 0xf2, 0xff, 0xc8, 0xec, 0x4e, 0x1c, 0x9a, - 0xe5, 0x9d, 0x9e, 0x06, 0x5c, 0x25, 0x3b, 0x55, 0x10, 0x76, 0x88, 0x20, 0x25, 0x7c, 0x0b, 0x09, - 0xdf, 0xa1, 0xf6, 0x03, 0x99, 0xf4, 0x24, 0x84, 0xef, 0x7d, 0xfb, 0x4a, 0xf6, 0x1a, 0x08, 0x11, - 0x44, 0x1a, 0xaa, 0x55, 0x8a, 0x57, 0xf4, 0x6d, 0xfc, 0x13, 0x99, 0xc5, 0x3a, 0xbb, 0xbe, 0x0f, - 0xa1, 0x14, 0xb5, 0x9a, 0xbc, 0x61, 0x15, 0x66, 0x54, 0x2e, 0xee, 0x71, 0xd4, 0xca, 0x13, 0x23, - 0xa6, 0xc3, 0x85, 0xce, 0x86, 0xae, 0x36, 0xea, 0x6f, 0x00, 0x3b, 0x75, 0xfc, 0x59, 0x64, 0x3a, - 0x6c, 0x4d, 0x2c, 0xd1, 0xb0, 0x8d, 0x63, 0x58, 0x52, 0x5c, 0x42, 0xd3, 0x08, 0x92, 0x9b, 0x97, - 0x79, 0x09, 0x93, 0xcf, 0xce, 0x31, 0x79, 0xe3, 0xa7, 0x79, 0x28, 0xaa, 0xa7, 0xb2, 0xd2, 0x9e, - 0x77, 0x2a, 0x27, 0x9f, 0x77, 0x6a, 0x25, 0x9e, 0x02, 0xc1, 0xad, 0x97, 0xf7, 0xfd, 0x3b, 0xb3, - 0x57, 0xb6, 0x66, 0x34, 0x4f, 0x5c, 0xdb, 0xab, 0x90, 0x9f, 0xd8, 0xe1, 0x39, 0x1a, 0xc8, 0x88, - 0x78, 0xf0, 0x5b, 0x19, 0xd3, 0x0b, 0x49, 0x63, 0x7a, 0xda, 0x53, 0x58, 0x24, 0x92, 0xce, 0x3d, - 0x85, 0x75, 0x07, 0x48, 0xbe, 0xd0, 0xc2, 0x8c, 0x4a, 0x08, 0x10, 0x77, 0x51, 0x52, 0x1c, 0x29, - 0xcd, 0x8a, 0x23, 0xaf, 0x2c, 0x2a, 0x7c, 0x1b, 0x16, 0x28, 0x8d, 0x5c, 0xa6, 0xb2, 0xa9, 0x0b, - 0x45, 0xae, 0xa1, 0xfa, 0x9f, 0x62, 0x8b, 0x4d, 0x89, 0xab, 0xbf, 0x2b, 0x53, 0x49, 0xbc, 0x2b, - 0xa3, 0x1b, 0xf9, 0xab, 0x49, 0x23, 0xff, 0x03, 0x68, 0x46, 0x0b, 0x8a, 0x26, 0x33, 0x37, 0x90, - 0x89, 0x32, 0x75, 0x05, 0x17, 0x5c, 0xf2, 0x20, 0x88, 0x2f, 0xc4, 0x7a, 0xe2, 0x42, 0x14, 0x3c, - 0xac, 0x1d, 0x86, 0x7c, 0x3c, 0x09, 0xe5, 0x85, 0x88, 0xa1, 0xf4, 0xfa, 0x00, 0x93, 0x49, 0x9e, - 0x35, 0x28, 0x77, 0x0f, 0xac, 0x9d, 0xbd, 0xee, 0xd3, 0xdd, 0x7e, 0x33, 0x23, 0x3e, 0x7b, 0xc7, - 0x5b, 0x5b, 0x9d, 0xce, 0x36, 0xde, 0x38, 0x00, 0x0b, 0x3b, 0xed, 0xae, 0xb8, 0x7d, 0x72, 0xc6, - 0xef, 0x65, 0xa1, 0xa2, 0x35, 0xcf, 0xde, 0x8f, 0x56, 0x85, 0x9e, 0x1e, 0xb9, 0x3b, 0x3f, 0x84, - 0x0d, 0xc5, 0x8a, 0xb5, 0x65, 0x89, 0x1e, 0xfe, 0xca, 0xde, 0xf8, 0xf0, 0x17, 0x7b, 0x1b, 0x1a, - 0x36, 0xb5, 0x10, 0xad, 0x82, 0x34, 0x07, 0x4b, 0xb0, 0x5c, 0x04, 0x0c, 0xae, 0x8b, 0xef, 0x13, - 0x81, 0x97, 0x57, 0xf1, 0x6c, 0xd1, 0x95, 0x82, 0x8b, 0x55, 0x3c, 0xb5, 0x9d, 0xd1, 0xd4, 0xe7, - 0xd2, 0x7d, 0x1b, 0xdd, 0xcc, 0x04, 0x35, 0x55, 0xb1, 0xf1, 0x01, 0x40, 0x3c, 0xe6, 0xe4, 0xe2, - 0xdc, 0x4a, 0x2e, 0x4e, 0x46, 0x5b, 0x9c, 0xac, 0xb1, 0x4d, 0x6c, 0x44, 0x2e, 0x74, 0xe4, 0xa9, - 0xfe, 0x26, 0x28, 0x8b, 0x94, 0x85, 0xe1, 0xad, 0x93, 0x11, 0x0f, 0x55, 0x3a, 0xec, 0xa2, 0x2c, - 0xe9, 0x46, 0x05, 0x2a, 0x3b, 0x3d, 0x6e, 0x25, 0xe6, 0x46, 0x92, 0x24, 0x67, 0xb9, 0x91, 0x44, - 0x35, 0xa3, 0x72, 0x63, 0x1d, 0x5a, 0xdb, 0x5c, 0xb4, 0xd6, 0x1e, 0x8d, 0x66, 0x86, 0x63, 0xdc, - 0x81, 0xdb, 0x29, 0x65, 0xd2, 0x08, 0xf1, 0x31, 0xac, 0xb4, 0x29, 0xf3, 0xf5, 0xab, 0x4a, 0x71, - 0x31, 0x5a, 0xb0, 0x3a, 0xdb, 0xa4, 0xec, 0x6c, 0x07, 0x16, 0xb7, 0xf9, 0xc9, 0xf4, 0x6c, 0x8f, - 0x5f, 0xc4, 0x1d, 0x31, 0xc8, 0x07, 0xe7, 0xde, 0xa5, 0x5c, 0x1f, 0xfc, 0x1b, 0x03, 0xc9, 0x04, - 0x8e, 0x15, 0x4c, 0xf8, 0x40, 0x59, 0x44, 0x11, 0xd2, 0x9b, 0xf0, 0x81, 0xf1, 0x3e, 0x30, 0xbd, - 0x1d, 0xb9, 0x5e, 0x42, 0x4b, 0x98, 0x9e, 0x58, 0xc1, 0x75, 0x10, 0xf2, 0xb1, 0x7a, 0xd9, 0x06, - 0x82, 0xe9, 0x49, 0x8f, 0x20, 0xc6, 0x3b, 0x50, 0x3d, 0xb2, 0xaf, 0x4d, 0xfe, 0xb9, 0x4c, 0xde, - 0x58, 0x83, 0xe2, 0xc4, 0xbe, 0x16, 0x6c, 0x20, 0x72, 0x8e, 0x60, 0xb1, 0xf1, 0x87, 0x79, 0x58, - 0x20, 0x4c, 0x76, 0x9f, 0x1e, 0x9f, 0x74, 0x5c, 0x3c, 0x86, 0x8a, 0x51, 0x6a, 0xa0, 0x39, 0x5e, - 0x9a, 0x9d, 0xe7, 0xa5, 0xd2, 0x80, 0xa6, 0x1e, 0xdd, 0x50, 0x66, 0x6c, 0x77, 0x3a, 0x56, 0x2f, - 0x6d, 0x24, 0xd3, 0x3f, 0xf3, 0xf1, 0xe3, 0xa2, 0x94, 0x1b, 0x97, 0x74, 0x34, 0xc6, 0xba, 0x08, - 0x8d, 0x4e, 0x5d, 0x11, 0x92, 0x5d, 0xea, 0xa0, 0x54, 0x85, 0xa7, 0xa8, 0xd2, 0x82, 0x92, 0x0a, - 0xcf, 0x9c, 0x62, 0x53, 0x7a, 0xb9, 0x62, 0x43, 0x96, 0xb5, 0x17, 0x28, 0x36, 0xf0, 0x0a, 0x8a, - 0xcd, 0x2b, 0x38, 0xf9, 0x6e, 0x43, 0x09, 0xef, 0x7d, 0x8d, 0x7b, 0x8a, 0xfb, 0x5e, 0x70, 0xcf, - 0xef, 0x68, 0xa2, 0x3f, 0x45, 0x18, 0xdc, 0x89, 0x8f, 0x89, 0xc9, 0x3f, 0xff, 0xe5, 0x38, 0x4f, - 0x3e, 0x83, 0xa2, 0x84, 0x0a, 0x82, 0x76, 0xed, 0xb1, 0x7a, 0xb7, 0x08, 0xff, 0x16, 0xcb, 0x86, - 0x8f, 0xad, 0x7c, 0x3e, 0x75, 0x7c, 0x3e, 0x54, 0x2f, 0x5b, 0x38, 0x78, 0x46, 0x05, 0x44, 0x4c, - 0x50, 0xa8, 0x21, 0xae, 0x77, 0xe9, 0xca, 0xbc, 0xf6, 0xa2, 0x13, 0x3c, 0x13, 0x9f, 0x06, 0x83, - 0x26, 0xbe, 0x5c, 0x36, 0xf1, 0x7c, 0x75, 0x39, 0x19, 0x3f, 0xcd, 0x40, 0x53, 0x9e, 0xae, 0xa8, - 0x4c, 0xd7, 0x02, 0x0a, 0x37, 0x39, 0xc4, 0x5f, 0xfc, 0x4e, 0x85, 0x01, 0x35, 0x34, 0x7e, 0x44, - 0x37, 0x15, 0x19, 0x6f, 0x2a, 0x02, 0xb8, 0x23, 0x6f, 0xab, 0xd7, 0xa1, 0xa2, 0xa2, 0x5c, 0xc7, - 0xce, 0x48, 0xbd, 0x23, 0x4c, 0x61, 0xae, 0xfb, 0xce, 0x48, 0x5d, 0x74, 0xbe, 0x2d, 0xd3, 0xd4, - 0x32, 0x78, 0xd1, 0x99, 0x76, 0xc8, 0x8d, 0x7f, 0x9f, 0x81, 0x45, 0x6d, 0x2a, 0xf2, 0xdc, 0x7e, - 0x08, 0xd5, 0xe8, 0xc9, 0x40, 0x1e, 0x49, 0x5e, 0x6b, 0x49, 0x46, 0x13, 0x57, 0xab, 0x0c, 0x22, - 0x48, 0x20, 0x06, 0x33, 0xb4, 0xaf, 0x71, 0xbc, 0xc1, 0x74, 0xac, 0x94, 0x9b, 0xa1, 0x7d, 0xbd, - 0xc3, 0x79, 0x6f, 0x3a, 0x16, 0xaa, 0xeb, 0x25, 0xe7, 0xcf, 0x23, 0x04, 0x92, 0xb9, 0x40, 0xc0, - 0x24, 0x86, 0x01, 0xb5, 0xb1, 0xe7, 0x86, 0xe7, 0x11, 0x8a, 0x94, 0x3a, 0x11, 0x48, 0x38, 0xc6, - 0x9f, 0x65, 0x61, 0x89, 0x4c, 0x6c, 0xd2, 0xb4, 0x29, 0x59, 0x57, 0x0b, 0x16, 0xc8, 0xda, 0x48, - 0xcc, 0x6b, 0xf7, 0x96, 0x29, 0xbf, 0xd9, 0xb7, 0x5f, 0xd1, 0x2c, 0xa8, 0x32, 0xe1, 0x6e, 0x58, - 0xfe, 0xdc, 0xfc, 0xf2, 0xdf, 0xbc, 0xbc, 0x69, 0x1e, 0xb7, 0x42, 0x9a, 0xc7, 0xed, 0x55, 0xfc, - 0x5c, 0x73, 0xe9, 0x62, 0x45, 0x89, 0xa3, 0xa5, 0x8b, 0xbd, 0x0f, 0x6b, 0x09, 0x1c, 0xe4, 0xd6, - 0xce, 0xa9, 0xc3, 0xd5, 0xb3, 0x01, 0xcb, 0x1a, 0x76, 0x4f, 0x95, 0x6d, 0x16, 0xa1, 0x10, 0x0c, - 0xbc, 0x09, 0x37, 0x56, 0x61, 0x39, 0xb9, 0xaa, 0xf2, 0x9a, 0xf8, 0xfd, 0x0c, 0xb4, 0x64, 0x7c, - 0x84, 0xe3, 0x9e, 0xed, 0x3a, 0x41, 0xe8, 0xf9, 0xd1, 0xd3, 0x7a, 0x77, 0x01, 0x82, 0xd0, 0xf6, - 0xa5, 0xb6, 0x29, 0x13, 0xe5, 0x11, 0x82, 0x9a, 0xe4, 0x6d, 0x28, 0x71, 0x77, 0x48, 0x85, 0x44, - 0x0d, 0x45, 0xee, 0x0e, 0x95, 0x1e, 0x3a, 0x27, 0x7f, 0xd7, 0x92, 0xea, 0x85, 0xcc, 0x5b, 0x15, - 0xab, 0xc3, 0x2f, 0xf0, 0xe2, 0xcd, 0x47, 0x79, 0xab, 0xfb, 0xf6, 0x15, 0x46, 0x1b, 0x06, 0xc6, - 0x3f, 0xcc, 0x42, 0x23, 0x1e, 0x1f, 0x25, 0xbd, 0xbf, 0x38, 0x7d, 0xff, 0xbe, 0x24, 0x07, 0x47, - 0xc8, 0xef, 0x9a, 0xe1, 0xb1, 0x44, 0x87, 0xb3, 0xeb, 0x32, 0x03, 0x2a, 0x0a, 0xc3, 0x9b, 0x86, - 0xda, 0x0b, 0x57, 0x65, 0x42, 0x39, 0x9c, 0x86, 0x42, 0xe1, 0x12, 0x9a, 0xa7, 0xe3, 0x4a, 0x95, - 0xa7, 0x60, 0x8f, 0xc3, 0x2e, 0x3e, 0x9c, 0x2d, 0xc0, 0xa2, 0x1a, 0x6d, 0xa4, 0xc0, 0x12, 0xf8, - 0x4d, 0x92, 0xb3, 0x69, 0xe7, 0x50, 0xc6, 0xd6, 0x85, 0x50, 0x7a, 0x43, 0x34, 0x12, 0x42, 0x5f, - 0x87, 0x0a, 0x35, 0x1e, 0x67, 0x07, 0xe6, 0xcd, 0x32, 0xf6, 0x80, 0xe5, 0xd2, 0x08, 0xe4, 0x4d, - 0x13, 0xaa, 0x2f, 0x50, 0x57, 0x18, 0x7e, 0xf0, 0x77, 0x33, 0x70, 0x3b, 0x65, 0xdb, 0xe4, 0x29, - 0xdf, 0x82, 0xc5, 0xd3, 0xa8, 0x50, 0xad, 0x2e, 0x1d, 0xf5, 0x55, 0xc5, 0x56, 0x93, 0x6b, 0x6a, - 0x36, 0x4f, 0x93, 0x80, 0x58, 0xe9, 0xa2, 0x1d, 0x4c, 0x24, 0x80, 0xa2, 0xd2, 0x45, 0xdb, 0x48, - 0xfa, 0xce, 0x11, 0xac, 0x77, 0xae, 0x04, 0xc7, 0xd8, 0xd2, 0x5f, 0x7e, 0x57, 0x64, 0x94, 0x34, - 0x30, 0x67, 0x5e, 0xc9, 0xc0, 0x3c, 0xa4, 0x3c, 0xb7, 0xa8, 0xad, 0x9f, 0xa7, 0x11, 0xbc, 0x40, - 0x45, 0x1d, 0x7a, 0xb9, 0x5e, 0x25, 0xa1, 0x0e, 0xa2, 0x17, 0xeb, 0x8d, 0x00, 0x1a, 0xfb, 0xd3, - 0x51, 0xe8, 0xc4, 0x8f, 0xd8, 0xb3, 0x6f, 0xcb, 0x3a, 0xd8, 0x8f, 0x5a, 0xb5, 0xd4, 0x8e, 0x20, - 0xea, 0x08, 0x17, 0x6b, 0x2c, 0x1a, 0xb2, 0xe6, 0xfb, 0x6b, 0x8c, 0x93, 0x3d, 0x18, 0xb7, 0x61, - 0x2d, 0xfe, 0xa2, 0x65, 0x53, 0x57, 0xcd, 0x3f, 0xcb, 0x50, 0x68, 0x73, 0xf2, 0x41, 0x7d, 0xd6, - 0x81, 0xa5, 0xc0, 0x71, 0xcf, 0x46, 0x5c, 0x6f, 0x3e, 0x90, 0x8b, 0xb0, 0x92, 0x1c, 0x9b, 0x7c, - 0x74, 0xdf, 0x5c, 0xa4, 0x1a, 0x71, 0x6b, 0x01, 0xdb, 0xbc, 0x69, 0x90, 0x31, 0x59, 0xcc, 0xac, - 0xc6, 0xfc, 0xe0, 0xbb, 0x50, 0x4f, 0x76, 0xc4, 0xbe, 0x23, 0x73, 0x3c, 0xe3, 0x51, 0xe5, 0x66, - 0xd2, 0xf5, 0x62, 0x82, 0xa8, 0xc4, 0x6b, 0x1f, 0x18, 0x7f, 0x3f, 0x03, 0x2d, 0x93, 0x0b, 0xca, - 0xd5, 0x46, 0xa9, 0x68, 0xe6, 0xc3, 0xb9, 0x56, 0x6f, 0x9e, 0xab, 0x4a, 0x1d, 0x55, 0x23, 0xfa, - 0xc6, 0x8d, 0x9b, 0xb1, 0x7b, 0x6b, 0x6e, 0x46, 0x9b, 0x25, 0x58, 0x20, 0x14, 0x63, 0x0d, 0x56, - 0xe4, 0x78, 0xd4, 0x58, 0x62, 0xef, 0x61, 0xa2, 0xc7, 0x84, 0xf7, 0x70, 0x1d, 0x5a, 0xf4, 0x42, - 0xa2, 0x3e, 0x09, 0x59, 0x71, 0x1b, 0xd8, 0xbe, 0x3d, 0xb0, 0x7d, 0xcf, 0x73, 0x8f, 0xb8, 0x2f, - 0x03, 0x45, 0x51, 0xc2, 0x44, 0xe7, 0x9a, 0x12, 0x85, 0xe9, 0x4b, 0xbd, 0xeb, 0xe7, 0xb9, 0x2a, - 0x2e, 0x86, 0xbe, 0x0c, 0x13, 0x96, 0x36, 0xed, 0xe7, 0x5c, 0xb5, 0xa4, 0x96, 0xe8, 0x23, 0xa8, - 0x4c, 0xa2, 0x46, 0xd5, 0xba, 0xab, 0x44, 0xf0, 0xf9, 0x6e, 0x4d, 0x1d, 0xdb, 0x78, 0x02, 0xcb, - 0xc9, 0x36, 0x25, 0xeb, 0x58, 0x87, 0xd2, 0x58, 0xc2, 0xe4, 0xe8, 0xa2, 0x6f, 0xe3, 0x77, 0x4b, - 0x50, 0x94, 0xfa, 0x1c, 0xdb, 0x80, 0xfc, 0x40, 0xc5, 0x26, 0xc5, 0xef, 0x8b, 0xc8, 0x52, 0xf5, - 0xff, 0x16, 0x46, 0x28, 0x09, 0x3c, 0xf6, 0x11, 0xd4, 0x93, 0x5e, 0xd1, 0x99, 0x2c, 0xd3, 0xa4, - 0x3b, 0xb3, 0x36, 0x98, 0xf1, 0x7f, 0x95, 0xe3, 0xcb, 0x91, 0x64, 0x86, 0xd2, 0xb9, 0x76, 0x7b, - 0x7a, 0xae, 0x90, 0xb7, 0x83, 0x73, 0xdb, 0x7a, 0xf2, 0xfe, 0x07, 0x32, 0xcd, 0xb4, 0x82, 0xc0, - 0xde, 0xb9, 0xfd, 0xe4, 0xfd, 0x0f, 0x66, 0x25, 0x69, 0xca, 0x34, 0xd4, 0x25, 0xe9, 0x65, 0x28, - 0xd0, 0x03, 0x76, 0x14, 0x64, 0x42, 0x1f, 0xec, 0x31, 0x2c, 0x4b, 0xb5, 0xd5, 0x92, 0xe1, 0xc0, - 0xc4, 0x05, 0x4b, 0x94, 0xda, 0x24, 0xcb, 0x7a, 0x58, 0x44, 0xb6, 0xa1, 0x55, 0x58, 0x38, 0x8f, - 0x5f, 0x23, 0xac, 0x99, 0xf2, 0xcb, 0xf8, 0xb3, 0x02, 0x54, 0xb4, 0x45, 0x61, 0x55, 0x28, 0x99, - 0x9d, 0x5e, 0xc7, 0xfc, 0xa4, 0xb3, 0xdd, 0xbc, 0xc5, 0x1e, 0xc0, 0x5b, 0xdd, 0x83, 0xad, 0x43, - 0xd3, 0xec, 0x6c, 0xf5, 0xad, 0x43, 0xd3, 0x52, 0xaf, 0xdc, 0x1c, 0xb5, 0x3f, 0xdb, 0xef, 0x1c, - 0xf4, 0xad, 0xed, 0x4e, 0xbf, 0xdd, 0xdd, 0xeb, 0x35, 0x33, 0xec, 0x35, 0x68, 0xc5, 0x98, 0xaa, - 0xb8, 0xbd, 0x7f, 0x78, 0x7c, 0xd0, 0x6f, 0x66, 0xd9, 0x3d, 0xb8, 0xb3, 0xd3, 0x3d, 0x68, 0xef, - 0x59, 0x31, 0xce, 0xd6, 0x5e, 0xff, 0x13, 0xab, 0xf3, 0xeb, 0x47, 0x5d, 0xf3, 0xb3, 0x66, 0x2e, - 0x0d, 0x41, 0x28, 0xe3, 0xaa, 0x85, 0x3c, 0xbb, 0x0d, 0x2b, 0x84, 0x40, 0x55, 0xac, 0xfe, 0xe1, - 0xa1, 0xd5, 0x3b, 0x3c, 0x3c, 0x68, 0x16, 0xd8, 0x22, 0xd4, 0xba, 0x07, 0x9f, 0xb4, 0xf7, 0xba, - 0xdb, 0x96, 0xd9, 0x69, 0xef, 0xed, 0x37, 0x17, 0xd8, 0x12, 0x34, 0x66, 0xf1, 0x8a, 0xa2, 0x09, - 0x85, 0x77, 0x78, 0xd0, 0x3d, 0x3c, 0xb0, 0x3e, 0xe9, 0x98, 0xbd, 0xee, 0xe1, 0x41, 0xb3, 0xc4, - 0x56, 0x81, 0x25, 0x8b, 0x76, 0xf7, 0xdb, 0x5b, 0xcd, 0x32, 0x5b, 0x81, 0xc5, 0x24, 0xfc, 0x59, - 0xe7, 0xb3, 0x26, 0xb0, 0x16, 0x2c, 0xd3, 0xc0, 0xac, 0xcd, 0xce, 0xde, 0xe1, 0xa7, 0xd6, 0x7e, - 0xf7, 0xa0, 0xbb, 0x7f, 0xbc, 0xdf, 0xac, 0xe0, 0xbb, 0x5b, 0x9d, 0x8e, 0xd5, 0x3d, 0xe8, 0x1d, - 0xef, 0xec, 0x74, 0xb7, 0xba, 0x9d, 0x83, 0x7e, 0xb3, 0x4a, 0x3d, 0xa7, 0x4d, 0xbc, 0x26, 0x2a, - 0xc8, 0x9c, 0x01, 0x6b, 0xbb, 0xdb, 0x6b, 0x6f, 0xee, 0x75, 0xb6, 0x9b, 0x75, 0x76, 0x17, 0x6e, - 0xf7, 0x3b, 0xfb, 0x47, 0x87, 0x66, 0xdb, 0xfc, 0x4c, 0xe5, 0x14, 0x58, 0x3b, 0xed, 0xee, 0xde, - 0xb1, 0xd9, 0x69, 0x36, 0xd8, 0x1b, 0x70, 0xd7, 0xec, 0x7c, 0x7c, 0xdc, 0x35, 0x3b, 0xdb, 0xd6, - 0xc1, 0xe1, 0x76, 0xc7, 0xda, 0xe9, 0xb4, 0xfb, 0xc7, 0x66, 0xc7, 0xda, 0xef, 0xf6, 0x7a, 0xdd, - 0x83, 0xa7, 0xcd, 0x26, 0x7b, 0x0b, 0xee, 0x47, 0x28, 0x51, 0x03, 0x33, 0x58, 0x8b, 0x62, 0x7e, - 0x6a, 0x4b, 0x0f, 0x3a, 0xbf, 0xde, 0xb7, 0x8e, 0x3a, 0x1d, 0xb3, 0xc9, 0xd8, 0x3a, 0xac, 0xc6, - 0xdd, 0x53, 0x07, 0xb2, 0xef, 0x25, 0x51, 0x76, 0xd4, 0x31, 0xf7, 0xdb, 0x07, 0x62, 0x83, 0x13, - 0x65, 0xcb, 0x62, 0xd8, 0x71, 0xd9, 0xec, 0xb0, 0x57, 0x18, 0x83, 0xba, 0xb6, 0x2b, 0x3b, 0x6d, - 0xb3, 0xb9, 0xca, 0x1a, 0x50, 0xd9, 0x3f, 0x3a, 0xb2, 0xfa, 0xdd, 0xfd, 0xce, 0xe1, 0x71, 0xbf, - 0xb9, 0xc6, 0x56, 0xa0, 0xd9, 0x3d, 0xe8, 0x77, 0x4c, 0xb1, 0xd7, 0xaa, 0xea, 0xff, 0x2a, 0xb2, - 0x65, 0x68, 0xa8, 0x91, 0x2a, 0xe8, 0xcf, 0x8a, 0x6c, 0x0d, 0xd8, 0xf1, 0x81, 0xd9, 0x69, 0x6f, - 0x8b, 0x85, 0x8b, 0x0a, 0xfe, 0x77, 0x51, 0x7a, 0x48, 0x7e, 0x9a, 0x8b, 0x2e, 0xeb, 0x38, 0xe4, - 0x20, 0xf9, 0x36, 0x6d, 0x55, 0x7b, 0x53, 0xf6, 0x65, 0xaf, 0xc6, 0x6b, 0xaa, 0x55, 0x6e, 0x4e, - 0xb5, 0x9a, 0xd3, 0xdd, 0x6b, 0xba, 0xec, 0xf7, 0x26, 0xd4, 0xc6, 0xf4, 0x4e, 0xad, 0x7c, 0x8f, - 0x12, 0x64, 0xfc, 0x0d, 0x01, 0xe9, 0x31, 0xca, 0xb9, 0x67, 0xd3, 0x0b, 0xf3, 0xcf, 0xa6, 0xa7, - 0xc9, 0xf7, 0x0b, 0x69, 0xf2, 0xfd, 0x43, 0x58, 0x24, 0xd6, 0xe4, 0xb8, 0xce, 0x58, 0x69, 0xcd, - 0x24, 0x05, 0x36, 0x90, 0x45, 0x11, 0x5c, 0xa9, 0x13, 0x4a, 0xe5, 0x90, 0x2c, 0xa4, 0x28, 0xb5, - 0x8d, 0x84, 0xa6, 0x41, 0x9c, 0x23, 0xd2, 0x34, 0xa2, 0x1e, 0xec, 0xab, 0xb8, 0x87, 0x8a, 0xd6, - 0x03, 0xc1, 0xb1, 0x87, 0x87, 0xb0, 0xc8, 0xaf, 0x42, 0xdf, 0xb6, 0xbc, 0x89, 0xfd, 0xf9, 0x14, - 0x5d, 0xb8, 0x36, 0xea, 0xf0, 0x55, 0xb3, 0x81, 0x05, 0x87, 0x08, 0xdf, 0xb6, 0x43, 0xfb, 0xe1, - 0x17, 0x50, 0xd1, 0xde, 0x30, 0x66, 0x6b, 0xb0, 0xf4, 0x69, 0xb7, 0x7f, 0xd0, 0xe9, 0xf5, 0xac, - 0xa3, 0xe3, 0xcd, 0x67, 0x9d, 0xcf, 0xac, 0xdd, 0x76, 0x6f, 0xb7, 0x79, 0x4b, 0x1c, 0xda, 0x83, - 0x4e, 0xaf, 0xdf, 0xd9, 0x4e, 0xc0, 0x33, 0xec, 0x75, 0x58, 0x3f, 0x3e, 0x38, 0xee, 0x75, 0xb6, - 0xad, 0xb4, 0x7a, 0x59, 0x41, 0xa5, 0xb2, 0x3c, 0xa5, 0x7a, 0xee, 0xe1, 0xf7, 0xa1, 0x9e, 0x7c, - 0x58, 0x93, 0x01, 0x2c, 0xec, 0x75, 0x9e, 0xb6, 0xb7, 0x3e, 0xa3, 0x97, 0xf9, 0x7a, 0xfd, 0x76, - 0xbf, 0xbb, 0x65, 0xc9, 0x97, 0xf8, 0x04, 0x47, 0xc8, 0xb0, 0x0a, 0x14, 0xdb, 0x07, 0x5b, 0xbb, - 0x87, 0x66, 0xaf, 0x99, 0x7d, 0xf8, 0x11, 0x34, 0x67, 0xfd, 0x51, 0x09, 0x07, 0xde, 0x8b, 0x3c, - 0x7d, 0x0f, 0xff, 0x55, 0x0e, 0x20, 0x4e, 0x18, 0x10, 0xac, 0x66, 0xbb, 0xdd, 0x6f, 0xef, 0x1d, - 0x8a, 0x69, 0x98, 0x87, 0x7d, 0xc1, 0x41, 0xcc, 0xce, 0xc7, 0xcd, 0x5b, 0xa9, 0x25, 0x87, 0x47, - 0xfd, 0x66, 0x46, 0xac, 0x58, 0xf7, 0xa0, 0xdb, 0xef, 0xb6, 0xf7, 0x2c, 0xf3, 0xf0, 0xb8, 0x7b, - 0xf0, 0x94, 0x9e, 0x1c, 0x43, 0x2e, 0x7b, 0x7c, 0xb4, 0x63, 0x1e, 0x1e, 0xf4, 0xad, 0xde, 0xee, - 0x71, 0x7f, 0x1b, 0x1f, 0x2c, 0xdb, 0x32, 0xbb, 0x47, 0xd4, 0x66, 0xfe, 0x45, 0x08, 0xa2, 0xe9, - 0x82, 0x58, 0xf3, 0xa7, 0x87, 0xbd, 0x5e, 0xf7, 0xc8, 0xfa, 0xf8, 0xb8, 0x63, 0x76, 0x3b, 0x3d, - 0xac, 0xb8, 0x90, 0x02, 0x17, 0xf8, 0x45, 0xc1, 0x9b, 0xfb, 0x7b, 0x9f, 0x48, 0xe6, 0x29, 0x50, - 0x4b, 0x49, 0x90, 0xc0, 0x2a, 0x0b, 0x9e, 0x22, 0xb8, 0x4f, 0x4a, 0xcb, 0x70, 0x43, 0x99, 0xa8, - 0x57, 0x11, 0x7c, 0x75, 0x6e, 0x33, 0xb0, 0x5a, 0x35, 0xbd, 0x48, 0xd4, 0x42, 0x96, 0x1b, 0x5d, - 0x50, 0xdb, 0xdb, 0x26, 0x56, 0xa8, 0xcf, 0x41, 0x05, 0x6e, 0x43, 0x6c, 0x94, 0x60, 0x4f, 0x02, - 0xa5, 0xa9, 0x3e, 0x44, 0xc9, 0xe2, 0x93, 0xdf, 0xc9, 0x41, 0x9d, 0x92, 0xb7, 0xe8, 0x27, 0xa4, - 0xb8, 0xcf, 0xf6, 0xa1, 0x28, 0x7f, 0x8b, 0x8c, 0xad, 0x44, 0xaf, 0x41, 0xe9, 0xbf, 0x7e, 0xb6, - 0xbe, 0x3a, 0x0b, 0x96, 0xe2, 0xd8, 0xd2, 0xdf, 0xf8, 0xd3, 0xff, 0xf9, 0x0f, 0xb2, 0x35, 0x56, - 0x79, 0x74, 0xf1, 0xde, 0xa3, 0x33, 0xee, 0x06, 0xa2, 0x8d, 0xff, 0x1f, 0x20, 0xfe, 0x85, 0x2d, - 0xd6, 0x8a, 0x9c, 0x50, 0x33, 0x3f, 0x3f, 0xb6, 0x7e, 0x3b, 0xa5, 0x44, 0xb6, 0x7b, 0x1b, 0xdb, - 0x5d, 0x32, 0xea, 0xa2, 0x5d, 0xc7, 0x75, 0x42, 0xfa, 0xb5, 0xad, 0x0f, 0x33, 0x0f, 0xd9, 0x10, - 0xaa, 0xfa, 0x6f, 0x5f, 0x31, 0x25, 0x29, 0xa5, 0xfc, 0x7a, 0xd7, 0xfa, 0x9d, 0xd4, 0x32, 0x25, - 0x83, 0x62, 0x1f, 0x2b, 0x46, 0x53, 0xf4, 0x31, 0x45, 0x8c, 0xb8, 0x97, 0x11, 0x49, 0xe5, 0xf1, - 0x4f, 0x5c, 0xb1, 0xd7, 0x34, 0xb9, 0x6a, 0xee, 0x07, 0xb6, 0xd6, 0xef, 0xde, 0x50, 0x2a, 0xfb, - 0xba, 0x8b, 0x7d, 0xad, 0x19, 0x4c, 0xf4, 0x35, 0x40, 0x1c, 0xf5, 0x03, 0x5b, 0x1f, 0x66, 0x1e, - 0x3e, 0xf9, 0xcb, 0x07, 0x50, 0x8e, 0x82, 0x39, 0xd9, 0x6f, 0x41, 0x2d, 0x91, 0x5d, 0xc7, 0xd4, - 0x34, 0xd2, 0x92, 0xf1, 0xd6, 0x5f, 0x4b, 0x2f, 0x94, 0x1d, 0xbf, 0x8e, 0x1d, 0xb7, 0xd8, 0xaa, - 0xe8, 0x58, 0x66, 0xaf, 0x3d, 0xc2, 0x6c, 0x58, 0x7a, 0x5b, 0xeb, 0xb9, 0xa6, 0x7d, 0x50, 0x67, - 0xaf, 0xcd, 0x6a, 0x04, 0x89, 0xde, 0xee, 0xde, 0x50, 0x2a, 0xbb, 0x7b, 0x0d, 0xbb, 0x5b, 0x65, - 0xcb, 0x7a, 0x77, 0x2a, 0xf4, 0x92, 0x71, 0x7c, 0xcf, 0x4e, 0xff, 0x05, 0x28, 0x76, 0x37, 0x7e, - 0x7d, 0x2c, 0xe5, 0x97, 0xa1, 0x22, 0x12, 0x99, 0xff, 0x79, 0x28, 0xa3, 0x85, 0x5d, 0x31, 0x86, - 0xdb, 0xa7, 0xff, 0x00, 0x14, 0x3b, 0x81, 0x8a, 0xf6, 0xa3, 0x09, 0xec, 0xf6, 0x8d, 0x3f, 0xf0, - 0xb0, 0xbe, 0x9e, 0x56, 0x94, 0x36, 0x15, 0xbd, 0xfd, 0x47, 0xa7, 0x9c, 0xb3, 0xdf, 0x80, 0x72, - 0xf4, 0x14, 0x3f, 0x5b, 0xd3, 0x7e, 0x1a, 0x41, 0xff, 0xe9, 0x80, 0xf5, 0xd6, 0x7c, 0x41, 0x1a, - 0xf1, 0xe9, 0xad, 0x0b, 0xe2, 0xfb, 0x14, 0x2a, 0xda, 0x73, 0xfb, 0xd1, 0x04, 0xe6, 0x9f, 0xf4, - 0x8f, 0x26, 0x90, 0xf2, 0x3a, 0xbf, 0xb1, 0x88, 0x5d, 0x54, 0x58, 0x19, 0xe9, 0x3b, 0xbc, 0xf2, - 0x02, 0xb6, 0x07, 0x2b, 0x52, 0xd3, 0x3a, 0xe1, 0x5f, 0x66, 0x1b, 0x52, 0x7e, 0x74, 0xeb, 0x71, - 0x86, 0x7d, 0x04, 0x25, 0xf5, 0xab, 0x0a, 0x6c, 0x35, 0xfd, 0xd7, 0x21, 0xd6, 0xd7, 0xe6, 0xe0, - 0x52, 0x2d, 0xfa, 0x0c, 0x20, 0x7e, 0xdb, 0x3f, 0x62, 0x12, 0x73, 0xbf, 0x15, 0x10, 0x51, 0xc0, - 0xfc, 0x0f, 0x01, 0x18, 0xab, 0x38, 0xc1, 0x26, 0x43, 0x26, 0xe1, 0xf2, 0x4b, 0xf5, 0xe8, 0xe8, - 0x8f, 0xa0, 0xa2, 0x3d, 0xef, 0x1f, 0x2d, 0xdf, 0xfc, 0x4f, 0x03, 0x44, 0xcb, 0x97, 0xf2, 0x6b, - 0x00, 0xc6, 0x3a, 0xb6, 0xbe, 0x6c, 0x34, 0x44, 0xeb, 0x42, 0xd4, 0x92, 0x22, 0x8f, 0xd8, 0xa0, - 0x73, 0xa8, 0x25, 0xde, 0xf0, 0x8f, 0x4e, 0x68, 0xda, 0x2f, 0x04, 0x44, 0x27, 0x34, 0xf5, 0xd9, - 0x7f, 0x45, 0x67, 0xc6, 0xa2, 0xe8, 0xe7, 0x02, 0x51, 0xb4, 0x9e, 0x7e, 0x08, 0x15, 0xed, 0x3d, - 0xfe, 0x68, 0x2e, 0xf3, 0x4f, 0xff, 0x47, 0x73, 0x49, 0x7b, 0xbe, 0x7f, 0x19, 0xfb, 0xa8, 0x1b, - 0x48, 0x0a, 0xf8, 0x6c, 0xa2, 0x68, 0xfb, 0xb7, 0xa0, 0x9e, 0x7c, 0xa2, 0x3f, 0x3a, 0xfb, 0xa9, - 0x6f, 0xfd, 0x47, 0x67, 0xff, 0x86, 0x77, 0xfd, 0x25, 0x49, 0x3f, 0x5c, 0x8a, 0x3a, 0x79, 0xf4, - 0x13, 0x99, 0x96, 0xf2, 0x05, 0xfb, 0x58, 0x30, 0x38, 0xf9, 0x6a, 0x27, 0x5b, 0xd3, 0xa8, 0x56, - 0x7f, 0xfe, 0x33, 0x3a, 0x2f, 0x73, 0x0f, 0x7c, 0x26, 0x89, 0x19, 0x1b, 0x67, 0x4f, 0x61, 0x29, - 0x22, 0xe6, 0xe8, 0x19, 0xce, 0x20, 0x9a, 0x43, 0xea, 0x63, 0x9f, 0xeb, 0xcd, 0xd9, 0xd2, 0xc7, - 0x19, 0xba, 0xfe, 0xf0, 0xf1, 0x43, 0xed, 0xfa, 0xd3, 0x5f, 0xe2, 0xd4, 0xae, 0xbf, 0xc4, 0x1b, - 0x89, 0xb3, 0xd7, 0x5f, 0xe8, 0x88, 0x36, 0x5c, 0x68, 0xcc, 0x3e, 0x8a, 0x79, 0xf7, 0xa6, 0xb4, - 0x7f, 0x6a, 0xfe, 0xf5, 0x17, 0xbf, 0x0a, 0x90, 0x64, 0x45, 0x8a, 0x9b, 0x3e, 0x92, 0xc1, 0x27, - 0xec, 0x37, 0xa1, 0xaa, 0xbf, 0x0f, 0xce, 0x74, 0x9e, 0x30, 0xdb, 0xd3, 0x9d, 0xd4, 0xb2, 0x24, - 0x95, 0xb0, 0xaa, 0xde, 0x0d, 0xfb, 0x04, 0x56, 0xa3, 0x65, 0xd6, 0xf3, 0xd6, 0x03, 0x76, 0x2f, - 0x25, 0x9b, 0x3d, 0xb1, 0xd8, 0xb7, 0x6f, 0x4c, 0x77, 0x7f, 0x9c, 0x11, 0xd4, 0x97, 0x7c, 0xa8, - 0x38, 0xbe, 0x79, 0xd2, 0xde, 0x67, 0x8e, 0x6f, 0x9e, 0xd4, 0xd7, 0x8d, 0x15, 0xf5, 0xb1, 0xa5, - 0xc4, 0x1a, 0x51, 0x58, 0x2e, 0xfb, 0x21, 0x34, 0xb4, 0xa4, 0xfc, 0xde, 0xb5, 0x3b, 0x88, 0x4e, - 0xd2, 0xfc, 0x4b, 0x7b, 0xeb, 0x69, 0xb6, 0x49, 0x63, 0x0d, 0xdb, 0x5f, 0x34, 0x12, 0x8b, 0x23, - 0x4e, 0xd1, 0x16, 0x54, 0xf4, 0x84, 0xff, 0x17, 0xb4, 0xbb, 0xa6, 0x15, 0xe9, 0x8f, 0xba, 0x3d, - 0xce, 0xb0, 0x3d, 0x68, 0xce, 0xbe, 0x41, 0x15, 0xf1, 0x94, 0xb4, 0x77, 0xb3, 0xd6, 0x67, 0x0a, - 0x13, 0x2f, 0x57, 0xb1, 0x23, 0x4a, 0xec, 0x88, 0x7e, 0xa1, 0xca, 0xf3, 0x67, 0x6f, 0xf5, 0xe4, - 0x2f, 0x57, 0x45, 0xad, 0xa5, 0xfd, 0x66, 0xd9, 0x83, 0xcc, 0xe3, 0x0c, 0xfb, 0xbd, 0x0c, 0x54, - 0x13, 0xef, 0xbe, 0x24, 0x42, 0xe7, 0x67, 0xe6, 0xd9, 0xd2, 0xcb, 0xf4, 0x89, 0x1a, 0x26, 0x2e, - 0xe2, 0xde, 0xc3, 0x1f, 0x24, 0x36, 0xe9, 0x27, 0x09, 0xd7, 0xde, 0xc6, 0xec, 0x4f, 0x58, 0x7d, - 0x31, 0x8b, 0xa0, 0x3f, 0xa0, 0xf8, 0xc5, 0xe3, 0x0c, 0xfb, 0x37, 0x19, 0xa8, 0x27, 0x7d, 0xf6, - 0xd1, 0x74, 0x53, 0xa3, 0x03, 0x22, 0x52, 0xba, 0xc1, 0xd1, 0xff, 0x43, 0x1c, 0x65, 0xff, 0xa1, - 0x99, 0x18, 0xa5, 0x7c, 0x62, 0xfb, 0x17, 0x1b, 0x2d, 0xfb, 0x90, 0x7e, 0x31, 0x52, 0x85, 0x32, - 0xb1, 0xf9, 0x5f, 0x18, 0x8c, 0xc8, 0x4f, 0xff, 0x3d, 0x3e, 0xdc, 0x84, 0x1f, 0xd1, 0x4f, 0x35, - 0xa9, 0xc8, 0x18, 0x41, 0xc5, 0xaf, 0x5a, 0xdf, 0x78, 0x0b, 0xe7, 0xf4, 0xba, 0x71, 0x3b, 0x31, - 0xa7, 0x59, 0xc1, 0xa3, 0x4d, 0xa3, 0x93, 0x3f, 0xa7, 0x17, 0xdf, 0x9c, 0x73, 0x3f, 0xb1, 0x77, - 0xf3, 0x20, 0xc7, 0x34, 0x48, 0x89, 0x9e, 0x38, 0x6a, 0xaf, 0xd8, 0x8c, 0xf1, 0x10, 0xc7, 0xfa, - 0x96, 0x71, 0xef, 0xc6, 0xb1, 0x3e, 0x42, 0xff, 0xbb, 0x18, 0xf1, 0x11, 0x40, 0x1c, 0x6a, 0xc8, - 0x66, 0x02, 0xde, 0x22, 0x06, 0x34, 0x1f, 0x8d, 0x98, 0x3c, 0xcf, 0x2a, 0x2e, 0x4e, 0xb4, 0xf8, - 0x1b, 0xc4, 0x4e, 0xa3, 0x50, 0x3c, 0x5d, 0xfa, 0x4a, 0x46, 0x05, 0x26, 0xa4, 0xaf, 0xd9, 0xf6, - 0x13, 0xcc, 0x34, 0x8a, 0xbb, 0x3b, 0x86, 0xda, 0x9e, 0xe7, 0x3d, 0x9f, 0x4e, 0xa2, 0xf0, 0xf6, - 0x64, 0x50, 0xcc, 0xae, 0x1d, 0x9c, 0xaf, 0xcf, 0xcc, 0xc2, 0xb8, 0x8f, 0x4d, 0xad, 0xb3, 0x96, - 0xd6, 0xd4, 0xa3, 0x9f, 0xc4, 0xf1, 0x8d, 0x5f, 0x30, 0x1b, 0x16, 0x23, 0x1e, 0x1d, 0xc7, 0x10, - 0x26, 0x9b, 0x49, 0x70, 0xe6, 0xd9, 0x2e, 0x12, 0x6a, 0x82, 0x1a, 0xed, 0xa3, 0x40, 0xb5, 0xf9, - 0x38, 0xc3, 0x8e, 0xa0, 0xba, 0xcd, 0x07, 0x98, 0xa8, 0x8f, 0xa1, 0x25, 0x4b, 0x89, 0x30, 0x05, - 0x8a, 0x49, 0x59, 0xaf, 0x25, 0x80, 0xc9, 0x7b, 0x6b, 0x62, 0x5f, 0xfb, 0xfc, 0xf3, 0x47, 0x3f, - 0x91, 0x41, 0x2b, 0x5f, 0xa8, 0x7b, 0x4b, 0x05, 0xf5, 0x24, 0xee, 0xad, 0x99, 0x28, 0xa0, 0xc4, - 0xbd, 0x35, 0x17, 0x05, 0x94, 0x58, 0x6a, 0x15, 0x54, 0xc4, 0x46, 0xb0, 0x38, 0x17, 0x38, 0x14, - 0x5d, 0x59, 0x37, 0x85, 0x1b, 0xad, 0xdf, 0xbf, 0x19, 0x21, 0xd9, 0xdb, 0xc3, 0x64, 0x6f, 0x3d, - 0xa8, 0xd1, 0x9b, 0x8e, 0x27, 0x9c, 0x52, 0xf6, 0x66, 0xde, 0xbb, 0xd1, 0xf3, 0x01, 0x67, 0x2f, - 0x18, 0x2c, 0x4b, 0x4a, 0x38, 0x98, 0x2b, 0xc7, 0x7e, 0x03, 0x2a, 0x4f, 0x79, 0xa8, 0x72, 0xf4, - 0x22, 0x19, 0x7b, 0x26, 0x69, 0x6f, 0x3d, 0x25, 0xc5, 0x2f, 0x49, 0x33, 0xd8, 0xda, 0x23, 0x3e, - 0x3c, 0xe3, 0xc4, 0x9c, 0x2c, 0x67, 0xf8, 0x05, 0xfb, 0x75, 0x6c, 0x3c, 0x4a, 0x8d, 0x5e, 0xd5, - 0x92, 0xb0, 0xf4, 0xc6, 0x1b, 0x33, 0xf0, 0xb4, 0x96, 0x5d, 0x6f, 0xc8, 0x35, 0x59, 0xcf, 0x85, - 0x8a, 0xf6, 0x84, 0x42, 0x74, 0x80, 0xe6, 0x9f, 0xcc, 0x88, 0x0e, 0x50, 0xca, 0x8b, 0x0b, 0xc6, - 0x03, 0xec, 0xc7, 0x60, 0xf7, 0xe3, 0x7e, 0xe8, 0x95, 0x85, 0xb8, 0xa7, 0x47, 0x3f, 0xb1, 0xc7, - 0xe1, 0x17, 0xec, 0x53, 0x7c, 0x39, 0x5d, 0xcf, 0x41, 0x8c, 0x95, 0x86, 0xd9, 0x74, 0xc5, 0x68, - 0xb1, 0xb4, 0xa2, 0xa4, 0x22, 0x41, 0x5d, 0xa1, 0x24, 0xf7, 0x3e, 0x40, 0x2f, 0xf4, 0x26, 0xdb, - 0x36, 0x1f, 0x7b, 0x6e, 0xcc, 0x6b, 0xe3, 0xac, 0xb8, 0x98, 0x7f, 0x69, 0xa9, 0x71, 0xec, 0x53, - 0x4d, 0xcb, 0x4a, 0xa4, 0x71, 0x2a, 0xe2, 0xba, 0x31, 0x71, 0x2e, 0x5a, 0x90, 0x94, 0xe4, 0xb9, - 0xc7, 0x19, 0xd6, 0x06, 0x88, 0x23, 0xc7, 0x22, 0x9d, 0x69, 0x2e, 0x28, 0x2d, 0x62, 0x7b, 0x29, - 0x61, 0x66, 0x47, 0x50, 0x8e, 0x43, 0x6e, 0xd6, 0xe2, 0x17, 0x61, 0x12, 0x01, 0x3a, 0xd1, 0x0d, - 0x3e, 0x17, 0xee, 0x62, 0x34, 0x71, 0xa9, 0x80, 0x95, 0xc4, 0x52, 0x9d, 0x72, 0x1e, 0x30, 0x07, - 0x96, 0x68, 0x80, 0x91, 0xb8, 0x84, 0xd9, 0x5c, 0xd1, 0x03, 0xf9, 0xf3, 0x91, 0x27, 0xd1, 0x69, - 0x4e, 0x8d, 0x9f, 0x48, 0x98, 0x7e, 0x04, 0xb5, 0x52, 0x26, 0x99, 0x60, 0xcd, 0x63, 0x58, 0x9c, - 0x73, 0xd1, 0x47, 0x47, 0xfa, 0xa6, 0x98, 0x8b, 0xe8, 0x48, 0xdf, 0xe8, 0xdd, 0x37, 0x56, 0xb0, - 0xcb, 0x86, 0x01, 0xa8, 0xea, 0x5d, 0x3a, 0xe1, 0xe0, 0x5c, 0x74, 0xf7, 0x2f, 0x33, 0xb0, 0x94, - 0xe2, 0x84, 0x67, 0x6f, 0x28, 0xab, 0xc1, 0x8d, 0x0e, 0xfa, 0xf5, 0x54, 0x67, 0xad, 0xd1, 0xc3, - 0x7e, 0xf6, 0xd9, 0xb3, 0xc4, 0xc5, 0x46, 0xbe, 0x52, 0x79, 0x32, 0x5f, 0x28, 0x54, 0xa4, 0x4a, - 0x14, 0x9f, 0xc3, 0x1a, 0x0d, 0xa4, 0x3d, 0x1a, 0xcd, 0x38, 0x92, 0x5f, 0x9f, 0xfb, 0x45, 0xf9, - 0x84, 0x73, 0x7c, 0xfd, 0xe6, 0x5f, 0x9c, 0xbf, 0x41, 0x9c, 0xa6, 0xa1, 0xb2, 0x29, 0x34, 0x67, - 0x1d, 0xb4, 0xec, 0xe6, 0xb6, 0xd6, 0xef, 0x25, 0xf4, 0xdf, 0x14, 0xa7, 0xee, 0xd7, 0xb0, 0xb3, - 0x7b, 0xc6, 0x7a, 0xda, 0xba, 0x90, 0x4a, 0x2c, 0xf6, 0xe3, 0xaf, 0x47, 0xde, 0xe4, 0x99, 0x79, - 0xaa, 0x0e, 0x6e, 0xf2, 0x7d, 0x47, 0x1a, 0x78, 0xba, 0x33, 0xfa, 0x6d, 0xec, 0xfe, 0xbe, 0x71, - 0x27, 0xad, 0x7b, 0x9f, 0xaa, 0x90, 0x2e, 0xbe, 0x36, 0x7b, 0xae, 0xd5, 0x08, 0xee, 0xa7, 0xed, - 0xf7, 0x8d, 0xba, 0xd0, 0xcc, 0x5a, 0xdf, 0x42, 0xd9, 0xae, 0xaa, 0x7b, 0x8f, 0xa3, 0xe3, 0x93, - 0xe2, 0xa6, 0x8e, 0x8e, 0x4f, 0x9a, 0xbb, 0x39, 0x29, 0xd7, 0x28, 0x47, 0xf3, 0x87, 0x99, 0x87, - 0x9b, 0xef, 0xfc, 0xf0, 0x6b, 0x67, 0x4e, 0x78, 0x3e, 0x3d, 0xd9, 0x18, 0x78, 0xe3, 0x47, 0x23, - 0x65, 0x6d, 0x94, 0x29, 0xcf, 0x8f, 0x46, 0xee, 0xf0, 0x11, 0x36, 0x7b, 0xb2, 0x30, 0xf1, 0xbd, - 0xd0, 0xfb, 0xd6, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x70, 0x9a, 0xaf, 0x28, 0x34, 0x83, 0x00, - 0x00, + 0xa8, 0x35, 0x2b, 0x65, 0x38, 0x4f, 0x77, 0x7d, 0x5c, 0x40, 0x1a, 0xb1, 0xf1, 0x0f, 0x4b, 0x50, + 0x94, 0xb7, 0x2d, 0xdd, 0xdc, 0xa1, 0x73, 0xc1, 0xe3, 0x9b, 0x5b, 0x7c, 0x09, 0x79, 0xc0, 0xe7, + 0x63, 0x2f, 0x8c, 0x04, 0x36, 0xda, 0x83, 0x2a, 0x01, 0xa5, 0xc8, 0xa6, 0x09, 0x0d, 0x64, 0x62, + 0xc8, 0x11, 0xd2, 0x40, 0xbf, 0xca, 0xef, 0x40, 0x51, 0xdd, 0xfd, 0xf9, 0x48, 0xa7, 0x59, 0x18, + 0x90, 0xb4, 0xb6, 0x0e, 0xa5, 0x81, 0x3d, 0xb1, 0x07, 0x4e, 0x78, 0x2d, 0x19, 0x42, 0xf4, 0x2d, + 0x5a, 0x1f, 0x79, 0x03, 0x7b, 0x64, 0x9d, 0xd8, 0x23, 0xdb, 0x1d, 0x70, 0xa9, 0xbb, 0x57, 0x11, + 0xb8, 0x49, 0x30, 0xa1, 0x9f, 0xcb, 0x71, 0x2a, 0x2c, 0x52, 0xe1, 0xe5, 0xe8, 0x15, 0x9a, 0x10, + 0x2e, 0xbd, 0xf1, 0xd8, 0x11, 0x5a, 0x06, 0x89, 0x61, 0x39, 0xb3, 0x4c, 0x90, 0x1d, 0x8e, 0xb3, + 0x95, 0xc5, 0x97, 0xb4, 0x74, 0x65, 0xea, 0x8a, 0x80, 0x9f, 0x92, 0x21, 0x61, 0x5e, 0x16, 0xcb, + 0x69, 0xb2, 0xd8, 0xbb, 0xb0, 0x38, 0x75, 0x03, 0x1e, 0x86, 0x23, 0x3e, 0x8c, 0xc6, 0x52, 0x41, + 0xa4, 0x66, 0x54, 0xa0, 0x86, 0xb3, 0x01, 0x4b, 0x64, 0x74, 0x08, 0xec, 0xd0, 0x0b, 0xce, 0x9d, + 0xc0, 0x0a, 0x84, 0x86, 0x44, 0xea, 0xee, 0x22, 0x16, 0xf5, 0x64, 0x49, 0x8f, 0x54, 0xa4, 0xb5, + 0x19, 0x7c, 0x9f, 0x0f, 0xb8, 0x73, 0xc1, 0x87, 0x28, 0xa7, 0xe5, 0xcc, 0x95, 0x44, 0x1d, 0x53, + 0x16, 0xa2, 0xd0, 0x3d, 0x1d, 0x5b, 0xd3, 0xc9, 0xd0, 0x16, 0xc2, 0x4a, 0x9d, 0x84, 0x61, 0x77, + 0x3a, 0x3e, 0x26, 0x08, 0x7b, 0x0c, 0x4a, 0x12, 0x93, 0xf2, 0x61, 0x23, 0xc1, 0xcf, 0x04, 0xb1, + 0x9a, 0x55, 0x89, 0x41, 0x82, 0x62, 0x42, 0xe6, 0x6c, 0xce, 0xc8, 0x9c, 0x2d, 0x28, 0x4e, 0x7c, + 0xe7, 0xc2, 0x0e, 0x79, 0x6b, 0x91, 0x18, 0xb8, 0xfc, 0x14, 0x9c, 0xc1, 0x71, 0x9d, 0xd0, 0xb1, + 0x43, 0xcf, 0x6f, 0x31, 0x2c, 0x8b, 0x01, 0xec, 0x21, 0x2c, 0x22, 0x8d, 0x04, 0xa1, 0x1d, 0x4e, + 0x03, 0x29, 0x81, 0x2e, 0x21, 0x31, 0xa1, 0x0c, 0xdd, 0x43, 0x38, 0x0a, 0xa1, 0xec, 0x5b, 0xb0, + 0x4a, 0x64, 0x81, 0x35, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x32, 0x2e, 0xc5, 0x12, 0x96, 0x0a, 0xfa, + 0x96, 0xf2, 0xb5, 0x90, 0x0e, 0xde, 0x87, 0x35, 0x49, 0x26, 0x73, 0xb5, 0x56, 0xb0, 0xd6, 0x32, + 0x15, 0xcf, 0x54, 0xdb, 0x80, 0x45, 0x31, 0x24, 0x67, 0x60, 0xc9, 0xda, 0xe2, 0x24, 0xac, 0x8a, + 0xd1, 0xa3, 0xa6, 0xd4, 0xa0, 0x42, 0x13, 0xcb, 0x9e, 0xf1, 0x6b, 0xf6, 0x3d, 0x68, 0x10, 0xc9, + 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, 0xa5, 0xc8, 0xec, 0xeb, + 0x83, 0xc4, 0xb7, 0x38, 0x0e, 0x23, 0xe7, 0x94, 0x87, 0xce, 0x98, 0xb7, 0xd6, 0x88, 0xc0, 0xd4, + 0xb7, 0x38, 0xa9, 0xd3, 0x09, 0x96, 0xb4, 0x88, 0x2f, 0xd0, 0x17, 0xd2, 0xee, 0xc8, 0x0b, 0xb8, + 0x32, 0x51, 0xb5, 0x6e, 0xcb, 0x43, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, 0x38, 0x29, 0x3d, 0x91, + 0x21, 0xf1, 0x0e, 0x12, 0x43, 0x8d, 0x74, 0x1f, 0x69, 0x4c, 0x34, 0x7e, 0x9a, 0xa1, 0xfb, 0x4e, + 0xb2, 0x87, 0x40, 0xd3, 0xde, 0x88, 0x31, 0x58, 0x9e, 0x3b, 0xba, 0x96, 0xbc, 0x02, 0x08, 0x74, + 0xe8, 0x8e, 0xf0, 0xb0, 0x3a, 0xae, 0x8e, 0x42, 0xac, 0xb5, 0xaa, 0x80, 0x88, 0x74, 0x0f, 0x2a, + 0x93, 0xe9, 0xc9, 0xc8, 0x19, 0x10, 0x4a, 0x8e, 0x5a, 0x21, 0x10, 0x22, 0x08, 0xf5, 0x95, 0x08, + 0x86, 0x30, 0xf2, 0x88, 0x51, 0x91, 0x30, 0x44, 0x41, 0xd6, 0xcd, 0x7d, 0xe4, 0x16, 0x55, 0x13, + 0xff, 0x36, 0x36, 0x61, 0x39, 0x39, 0x68, 0x79, 0xaf, 0x3c, 0x84, 0x92, 0x64, 0x45, 0xca, 0xae, + 0x51, 0xd7, 0x2c, 0xcd, 0x42, 0x03, 0x8b, 0xca, 0x8d, 0xdf, 0x5e, 0x80, 0x25, 0x09, 0xdd, 0x12, + 0x2b, 0xd7, 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0xc2, 0xe3, 0x32, 0x2f, 0xe6, 0x71, 0xd9, 0x39, 0x1e, + 0x97, 0x54, 0x6c, 0x89, 0x45, 0x26, 0x15, 0x5b, 0xb1, 0x55, 0xa4, 0x6b, 0xe8, 0x66, 0xce, 0x9a, + 0x04, 0xf7, 0xc9, 0x9c, 0x3a, 0xc7, 0x91, 0x0b, 0x29, 0x1c, 0x59, 0xe7, 0xa7, 0x0b, 0x33, 0xfc, + 0xf4, 0x0d, 0x20, 0x9a, 0x50, 0xd7, 0x43, 0x91, 0xd4, 0x0f, 0x84, 0x49, 0x5b, 0xe9, 0x3b, 0xd0, + 0x98, 0x65, 0x61, 0xc4, 0x2b, 0xeb, 0x29, 0x0c, 0xcc, 0x19, 0x73, 0xbc, 0x8c, 0x34, 0xe4, 0xb2, + 0x64, 0x60, 0xce, 0x98, 0xef, 0x61, 0x89, 0xc2, 0xef, 0x00, 0x50, 0xdf, 0x78, 0x26, 0x00, 0xcf, + 0xc4, 0xdb, 0xc9, 0xbd, 0xd0, 0x57, 0x7d, 0x43, 0x7c, 0x4c, 0x7d, 0x8e, 0x87, 0xa4, 0x8c, 0x35, + 0xf1, 0x7c, 0x3c, 0x83, 0xba, 0x37, 0xe1, 0xae, 0x15, 0xb3, 0x92, 0x0a, 0x36, 0xf5, 0xd6, 0x0b, + 0x9a, 0xea, 0x2a, 0x5c, 0xb3, 0x26, 0xea, 0x46, 0x9f, 0x6c, 0x9f, 0x16, 0x9e, 0x6b, 0xad, 0x55, + 0xbf, 0x44, 0x6b, 0x75, 0xac, 0x1c, 0x7d, 0x1b, 0x7f, 0x2b, 0x03, 0x15, 0x6d, 0xd8, 0x6c, 0x05, + 0x16, 0xb7, 0x0e, 0x0f, 0x8f, 0x3a, 0x66, 0xbb, 0xdf, 0xfd, 0xa4, 0x63, 0x6d, 0xed, 0x1d, 0xf6, + 0x3a, 0xcd, 0x5b, 0x02, 0xbc, 0x77, 0xb8, 0xd5, 0xde, 0xb3, 0x76, 0x0e, 0xcd, 0x2d, 0x05, 0xce, + 0xb0, 0x55, 0x60, 0x66, 0x67, 0xff, 0xb0, 0xdf, 0x49, 0xc0, 0xb3, 0xac, 0x09, 0xd5, 0x4d, 0xb3, + 0xd3, 0xde, 0xda, 0x95, 0x90, 0x1c, 0x5b, 0x86, 0xe6, 0xce, 0xf1, 0xc1, 0x76, 0xf7, 0xe0, 0xa9, + 0xb5, 0xd5, 0x3e, 0xd8, 0xea, 0xec, 0x75, 0xb6, 0x9b, 0x79, 0x56, 0x83, 0x72, 0x7b, 0xb3, 0x7d, + 0xb0, 0x7d, 0x78, 0xd0, 0xd9, 0x6e, 0x16, 0x8c, 0x5f, 0x81, 0x72, 0x3c, 0xd1, 0x0a, 0x14, 0x8f, + 0x0f, 0x9e, 0x1d, 0x1c, 0x7e, 0x7a, 0xd0, 0xbc, 0xc5, 0xca, 0x50, 0xc0, 0xfe, 0x9b, 0x19, 0x06, + 0xb0, 0x40, 0x7d, 0x36, 0xb3, 0xac, 0x04, 0xf9, 0xcd, 0xc3, 0xfe, 0x6e, 0x33, 0x67, 0xfc, 0x45, + 0x06, 0x56, 0x70, 0xca, 0xc3, 0x59, 0x26, 0x70, 0x1f, 0x2a, 0x03, 0xcf, 0x9b, 0x08, 0x45, 0x2a, + 0x16, 0x18, 0x74, 0x90, 0x38, 0xe0, 0xc4, 0x9b, 0x4f, 0x3d, 0x7f, 0xc0, 0x25, 0x0f, 0x00, 0x04, + 0xed, 0x08, 0x88, 0xa0, 0x41, 0x49, 0xc4, 0x84, 0x41, 0x2c, 0xa0, 0x42, 0x30, 0x42, 0x59, 0x85, + 0x85, 0x13, 0x9f, 0xdb, 0x83, 0x73, 0x79, 0xfa, 0xe5, 0x17, 0xfb, 0x7a, 0xac, 0xe2, 0x0f, 0x04, + 0x4d, 0x8d, 0xf8, 0x10, 0x8f, 0x40, 0xc9, 0x6c, 0x48, 0xf8, 0x96, 0x04, 0x8b, 0xcb, 0xc6, 0x3e, + 0xb1, 0xdd, 0xa1, 0xe7, 0xf2, 0xa1, 0xd4, 0x24, 0x62, 0x80, 0x71, 0x04, 0xab, 0xb3, 0xf3, 0x93, + 0xfc, 0xe2, 0x03, 0x8d, 0x5f, 0x90, 0x60, 0xbf, 0x7e, 0x33, 0x29, 0x68, 0xbc, 0xe3, 0xef, 0xe4, + 0x21, 0x2f, 0x04, 0xbd, 0x1b, 0x65, 0x42, 0x5d, 0x72, 0xcf, 0xcd, 0x79, 0x77, 0xd0, 0x92, 0x40, + 0x12, 0x00, 0x99, 0xab, 0xca, 0x08, 0xc1, 0x9b, 0x3f, 0x2a, 0xf6, 0xf9, 0xe0, 0x42, 0xda, 0xab, + 0xa8, 0xd8, 0xe4, 0x83, 0x0b, 0x54, 0x99, 0xec, 0x90, 0xea, 0xd2, 0x79, 0x2f, 0x06, 0x76, 0x88, + 0x35, 0x65, 0x11, 0xd6, 0x2b, 0x46, 0x45, 0x58, 0xab, 0x05, 0x45, 0xc7, 0x3d, 0xf1, 0xa6, 0xee, + 0x10, 0x8f, 0x77, 0xc9, 0x54, 0x9f, 0xe8, 0x4c, 0x42, 0x4e, 0x24, 0xee, 0x19, 0x3a, 0xcd, 0x25, + 0x01, 0xe8, 0x8b, 0x9b, 0xe6, 0x3d, 0x28, 0x07, 0xd7, 0xee, 0x40, 0x3f, 0xc3, 0xcb, 0x72, 0x7d, + 0xc4, 0xec, 0x37, 0x7a, 0xd7, 0xee, 0x00, 0x4f, 0x6c, 0x29, 0x90, 0x7f, 0xb1, 0xf7, 0xa1, 0x14, + 0x99, 0x75, 0x89, 0x03, 0xdf, 0xd6, 0x6b, 0x28, 0x5b, 0x2e, 0x69, 0xcf, 0x11, 0x2a, 0x7b, 0x04, + 0x0b, 0x68, 0x7b, 0x0d, 0x5a, 0x55, 0xac, 0xa4, 0xc4, 0x79, 0x31, 0x0c, 0xf4, 0xe3, 0xf0, 0x21, + 0xda, 0x61, 0x4d, 0x89, 0xb6, 0xfe, 0x0c, 0x6a, 0x89, 0xb6, 0x74, 0x1d, 0xb9, 0x46, 0x3a, 0xf2, + 0x5b, 0xba, 0x8e, 0x1c, 0xdf, 0x04, 0xb2, 0x9a, 0xae, 0x33, 0xff, 0x1a, 0x94, 0xd4, 0x54, 0xc4, + 0xf9, 0x93, 0x67, 0xc7, 0xea, 0x7d, 0x76, 0xb0, 0xd5, 0xbc, 0xc5, 0x1a, 0x50, 0x69, 0x6f, 0xe1, + 0x91, 0x46, 0x40, 0x46, 0xa0, 0x1c, 0xb5, 0x7b, 0xbd, 0x08, 0x92, 0x35, 0x76, 0xa0, 0x39, 0x3b, + 0x52, 0x41, 0x93, 0xa1, 0x82, 0x49, 0xcb, 0x74, 0x0c, 0x10, 0x1a, 0x10, 0x19, 0x9b, 0x49, 0xcc, + 0xa6, 0x0f, 0xe3, 0x7d, 0x68, 0x8a, 0x7b, 0x4d, 0x2c, 0x55, 0xa0, 0x59, 0x78, 0x47, 0x42, 0x74, + 0xd3, 0xad, 0xd3, 0x25, 0xb3, 0x42, 0x30, 0xec, 0xca, 0xf8, 0x00, 0x16, 0xb5, 0x6a, 0xb1, 0xc6, + 0x2a, 0xee, 0xca, 0x59, 0x8d, 0x15, 0xf5, 0x13, 0x2a, 0x31, 0xd6, 0x60, 0x45, 0x7c, 0x76, 0x2e, + 0xb8, 0x1b, 0xf6, 0xa6, 0x27, 0xe4, 0x52, 0x74, 0x3c, 0x57, 0xe8, 0x2d, 0xe5, 0xa8, 0xe4, 0x66, + 0x22, 0xdf, 0x90, 0xca, 0x6d, 0x16, 0x49, 0x63, 0x5d, 0xeb, 0x01, 0x2b, 0x6e, 0xe0, 0xbf, 0x09, + 0x25, 0xb7, 0x1c, 0x81, 0xc4, 0xb2, 0x1e, 0x75, 0x3a, 0xa6, 0x75, 0x78, 0xb0, 0xd7, 0x3d, 0x10, + 0x8c, 0x52, 0x2c, 0x2b, 0x02, 0x76, 0x76, 0x10, 0x92, 0x31, 0x9a, 0x50, 0x7f, 0xca, 0xc3, 0xae, + 0x7b, 0xea, 0x29, 0xf7, 0xd9, 0xcf, 0x0a, 0xd0, 0x88, 0x40, 0xb1, 0x92, 0x7c, 0xc1, 0xfd, 0xc0, + 0xf1, 0x5c, 0x94, 0x77, 0xcb, 0xa6, 0xfa, 0x14, 0xb7, 0x9b, 0x33, 0xe4, 0x6e, 0xe8, 0x84, 0xd7, + 0x56, 0xc2, 0xa2, 0x56, 0x57, 0x60, 0x79, 0x8b, 0x2e, 0x43, 0xc1, 0x1e, 0x39, 0xb6, 0xf2, 0xc4, + 0xd2, 0x87, 0x80, 0x0e, 0xbc, 0x91, 0xe7, 0xa3, 0x68, 0x5b, 0x36, 0xe9, 0x83, 0x3d, 0x86, 0x65, + 0x21, 0x62, 0xeb, 0x66, 0x4e, 0xe4, 0x1f, 0x64, 0xdc, 0x63, 0xee, 0x74, 0x7c, 0x14, 0x9b, 0x3a, + 0x45, 0x89, 0xb8, 0x3b, 0x45, 0x0d, 0x29, 0x2c, 0x45, 0x15, 0x48, 0x5b, 0x5b, 0x74, 0xa7, 0xe3, + 0x36, 0x96, 0x44, 0xf8, 0x4f, 0x60, 0x45, 0xe0, 0x47, 0xe2, 0x55, 0x54, 0xa3, 0x81, 0x35, 0x44, + 0x63, 0x5d, 0x59, 0x16, 0xd5, 0xb9, 0x03, 0x65, 0x1a, 0x95, 0xd8, 0xf1, 0x02, 0x49, 0xe9, 0x38, + 0x14, 0xee, 0x07, 0x73, 0x4e, 0xd3, 0x05, 0x12, 0x04, 0x66, 0x9c, 0xa6, 0x9a, 0xdb, 0xb5, 0x34, + 0xeb, 0x76, 0x7d, 0x02, 0x2b, 0x27, 0x82, 0x04, 0xcf, 0xb9, 0x3d, 0xe4, 0xbe, 0x15, 0x13, 0x36, + 0x69, 0x23, 0x4b, 0xa2, 0x70, 0x17, 0xcb, 0xa2, 0x73, 0x20, 0xe4, 0x1c, 0xc1, 0x16, 0xf8, 0xd0, + 0x0a, 0x3d, 0x0b, 0xc5, 0x1f, 0x64, 0x30, 0x25, 0xb3, 0x46, 0xe0, 0xbe, 0xb7, 0x25, 0x80, 0x49, + 0xbc, 0x33, 0xdf, 0x9e, 0x9c, 0x4b, 0x7d, 0x21, 0xc2, 0x7b, 0x2a, 0x80, 0xec, 0x35, 0x28, 0x0a, + 0x92, 0x77, 0x39, 0xf9, 0xb6, 0x48, 0x22, 0x57, 0x20, 0xf6, 0x16, 0x2c, 0x60, 0x1f, 0x41, 0xab, + 0x89, 0xf4, 0x5e, 0x8d, 0x19, 0xb9, 0xe3, 0x9a, 0xb2, 0x4c, 0x08, 0x93, 0x53, 0xdf, 0x21, 0x2e, + 0x53, 0x36, 0xf1, 0x6f, 0xf6, 0x7d, 0x8d, 0x65, 0x2d, 0x61, 0x5d, 0x25, 0x0f, 0xcc, 0x50, 0xda, + 0x4d, 0xdc, 0xeb, 0x2b, 0x65, 0x46, 0x3f, 0xc8, 0x97, 0x2a, 0xcd, 0xaa, 0xf1, 0x1d, 0x28, 0xd0, + 0xea, 0x08, 0x22, 0xc4, 0xb5, 0xcb, 0x48, 0x22, 0x44, 0x68, 0x0b, 0x8a, 0x2e, 0x0f, 0x2f, 0x3d, + 0xff, 0xb9, 0xb2, 0x39, 0xcb, 0x4f, 0xe3, 0xc7, 0x68, 0x2c, 0x89, 0x1c, 0xea, 0xa4, 0xf7, 0x09, + 0xf2, 0xa0, 0xed, 0x0d, 0xce, 0x6d, 0x69, 0xbf, 0x29, 0x21, 0xa0, 0x77, 0x6e, 0xcf, 0x91, 0x47, + 0x76, 0xde, 0xa7, 0xfe, 0x16, 0xd4, 0x95, 0x0b, 0x3f, 0xb0, 0x46, 0xfc, 0x34, 0x94, 0xe4, 0x5e, + 0x95, 0xfe, 0xfb, 0x60, 0x8f, 0x9f, 0x86, 0xc6, 0x3e, 0x2c, 0x4a, 0x82, 0x3c, 0x9c, 0x70, 0xd5, + 0xf5, 0x77, 0xd3, 0xe4, 0xe9, 0xca, 0x93, 0xa5, 0xe4, 0x45, 0x4b, 0xa1, 0x09, 0x09, 0x21, 0xdb, + 0xf8, 0x18, 0x98, 0x7e, 0x0d, 0xcb, 0xf6, 0xa4, 0x54, 0xab, 0x4c, 0xf5, 0xca, 0xe3, 0x15, 0xc9, + 0xce, 0xce, 0x50, 0xac, 0x4e, 0x30, 0x1d, 0x0c, 0x54, 0x68, 0x45, 0xc9, 0x54, 0x9f, 0xc6, 0x9f, + 0x66, 0x60, 0x09, 0x1b, 0x53, 0xfa, 0x80, 0x64, 0xb2, 0x3f, 0xf7, 0x20, 0xc5, 0xfe, 0xe8, 0xb2, + 0x0f, 0x7d, 0x7c, 0x79, 0xe3, 0x68, 0x7e, 0xce, 0x38, 0xfa, 0x75, 0x68, 0x0e, 0xf9, 0xc8, 0xc1, + 0x28, 0x1b, 0x25, 0x4a, 0x90, 0x06, 0xd0, 0x50, 0x70, 0xa9, 0xec, 0x19, 0xff, 0x20, 0x03, 0x8b, + 0x24, 0xa9, 0xa0, 0xda, 0x2c, 0x17, 0xea, 0x23, 0xa5, 0x27, 0x4a, 0x56, 0x25, 0xe7, 0x14, 0xdf, + 0xe0, 0x08, 0x25, 0xe4, 0xdd, 0x5b, 0x52, 0x7f, 0x94, 0x50, 0xf6, 0x21, 0xea, 0x30, 0xae, 0x85, + 0xc0, 0x94, 0xa8, 0x9d, 0xe4, 0xa6, 0xec, 0xde, 0x42, 0x05, 0xc7, 0x45, 0xd0, 0x66, 0x49, 0x28, + 0xae, 0x02, 0x6c, 0xec, 0x40, 0x2d, 0xd1, 0x4d, 0xc2, 0x82, 0x5b, 0x25, 0x0b, 0xee, 0x9c, 0x97, + 0x24, 0x3b, 0xef, 0x25, 0xf9, 0x1b, 0x79, 0x60, 0x82, 0xa4, 0x66, 0x76, 0x6d, 0xc6, 0xc5, 0x98, + 0x9d, 0x73, 0x31, 0x3e, 0x06, 0xa6, 0x21, 0x28, 0xcf, 0x67, 0x2e, 0xf2, 0x7c, 0x36, 0x63, 0x5c, + 0xe9, 0xf8, 0x7c, 0x0c, 0xcb, 0x52, 0xa0, 0x8d, 0x7c, 0x8a, 0x68, 0x9a, 0xa3, 0xfd, 0x61, 0x24, + 0xd9, 0x2a, 0xdf, 0x22, 0x9a, 0xe9, 0x94, 0x7b, 0x51, 0xa8, 0xd8, 0x64, 0xd1, 0x42, 0xf7, 0x62, + 0xcf, 0x9e, 0x33, 0x91, 0x2f, 0xbc, 0x94, 0x0a, 0x8a, 0x73, 0x54, 0xa0, 0x19, 0x58, 0x4a, 0x49, + 0x03, 0x8b, 0x01, 0x35, 0xe5, 0x44, 0xa4, 0xd8, 0x09, 0x92, 0xde, 0x2a, 0xd2, 0x93, 0x88, 0xf1, + 0x13, 0x0f, 0xa0, 0xa9, 0xac, 0x20, 0x91, 0x09, 0x87, 0xe2, 0x02, 0xa4, 0x11, 0x6d, 0x4b, 0x19, + 0x72, 0x12, 0x06, 0xf3, 0xca, 0x8c, 0xc1, 0xfc, 0x5d, 0x58, 0x0c, 0x04, 0x11, 0x59, 0x53, 0x57, + 0x06, 0xf1, 0xf0, 0x21, 0xaa, 0x4e, 0x25, 0xb3, 0x89, 0x05, 0xc7, 0x31, 0x7c, 0xde, 0x3c, 0x51, + 0x4b, 0x31, 0x4f, 0xbc, 0x1f, 0xfb, 0xdb, 0x82, 0x73, 0x67, 0x8c, 0x17, 0x77, 0x1c, 0xf0, 0x22, + 0x17, 0xb8, 0x77, 0xee, 0x8c, 0x4d, 0xe5, 0xdc, 0x15, 0x1f, 0xc6, 0xbf, 0xcf, 0x40, 0x53, 0xd0, + 0x41, 0x82, 0xce, 0x7f, 0x05, 0xf0, 0x44, 0xbe, 0x22, 0x99, 0x57, 0x04, 0xae, 0xa2, 0xf2, 0xef, + 0x00, 0x92, 0xad, 0x25, 0xf4, 0x44, 0x49, 0xe4, 0xad, 0x24, 0x91, 0xc7, 0x8c, 0x6c, 0xf7, 0x16, + 0x29, 0x00, 0x02, 0x92, 0xe6, 0xe7, 0xcc, 0xa7, 0xf8, 0x39, 0xb5, 0xa3, 0xb0, 0x0b, 0xf0, 0x8c, + 0x5f, 0xef, 0x79, 0x03, 0xd4, 0xd0, 0xee, 0x02, 0x08, 0x82, 0x3c, 0xb5, 0xc7, 0x8e, 0xb4, 0xae, + 0x14, 0xcc, 0xf2, 0x73, 0x7e, 0xbd, 0x83, 0x00, 0xb1, 0x1b, 0xa2, 0x38, 0x3e, 0x0f, 0x05, 0xb3, + 0xf4, 0x9c, 0x5f, 0xd3, 0x61, 0xb0, 0xa0, 0xf6, 0x8c, 0x5f, 0x6f, 0x73, 0x12, 0xd7, 0x3c, 0x5f, + 0x50, 0x82, 0x6f, 0x5f, 0x0a, 0xf9, 0x2c, 0xe1, 0xa3, 0xac, 0xf8, 0xf6, 0xe5, 0x33, 0x7e, 0xad, + 0xfc, 0xa5, 0x45, 0x51, 0x3e, 0xf2, 0x06, 0xf2, 0x06, 0x52, 0xd1, 0x16, 0xf1, 0xa0, 0xcc, 0x85, + 0xe7, 0xf8, 0xb7, 0xf1, 0x27, 0x19, 0xa8, 0x89, 0xf1, 0x23, 0x83, 0x13, 0xeb, 0xae, 0x82, 0x76, + 0x32, 0x71, 0xd0, 0xce, 0x13, 0xc9, 0x1f, 0x88, 0x5b, 0x66, 0x6f, 0xe6, 0x96, 0xb8, 0xc0, 0xc4, + 0x2a, 0xdf, 0x83, 0x32, 0x9d, 0x2d, 0x71, 0x58, 0x73, 0x89, 0x5d, 0x4a, 0x4c, 0xc8, 0x2c, 0x21, + 0xda, 0x33, 0x8a, 0x11, 0xd0, 0x0c, 0x71, 0xb4, 0xc4, 0x65, 0x3f, 0x32, 0xbf, 0xa5, 0x6c, 0x43, + 0x21, 0xcd, 0xdd, 0x7c, 0x0c, 0x15, 0x8d, 0xa6, 0xd0, 0x6a, 0x17, 0x0d, 0x9e, 0x08, 0x30, 0x49, + 0x34, 0x89, 0xd9, 0xef, 0xde, 0x32, 0x6b, 0x03, 0x1d, 0xb0, 0xb9, 0x00, 0x79, 0x51, 0xc9, 0xf8, + 0x08, 0x16, 0xb5, 0x66, 0x49, 0x1b, 0x4d, 0x1b, 0x53, 0x26, 0x6d, 0x4c, 0xff, 0x28, 0x03, 0xcb, + 0xb2, 0x36, 0x06, 0x78, 0x39, 0xe2, 0xba, 0xde, 0x0f, 0xce, 0xd8, 0xaf, 0x40, 0x4d, 0xb4, 0x6e, + 0xf9, 0xfc, 0xcc, 0x09, 0x42, 0xae, 0x3c, 0x1c, 0x29, 0x87, 0x43, 0x70, 0x6d, 0x81, 0x6a, 0x4a, + 0x4c, 0xf6, 0x11, 0x54, 0xb0, 0x2a, 0xe9, 0xcb, 0x72, 0x5b, 0x5a, 0xf3, 0x15, 0x69, 0xa8, 0xbb, + 0xb7, 0x4c, 0x08, 0xa2, 0xaf, 0xcd, 0x32, 0x14, 0x43, 0xdf, 0x39, 0x3b, 0xe3, 0xbe, 0xb1, 0x1a, + 0x0d, 0x4d, 0x9c, 0x34, 0xde, 0x0b, 0xf9, 0x44, 0x08, 0x41, 0xc6, 0x7f, 0xcc, 0x40, 0x45, 0x9e, + 0x9d, 0x9f, 0xdb, 0xad, 0xb1, 0xae, 0x45, 0x28, 0x92, 0x6a, 0x1c, 0x07, 0x24, 0xbe, 0x03, 0x8d, + 0xb1, 0x10, 0x88, 0x84, 0xc0, 0x9e, 0xf0, 0x69, 0xd4, 0x15, 0x58, 0xca, 0x23, 0x1b, 0xb0, 0x84, + 0xe2, 0x49, 0x60, 0x85, 0xce, 0xc8, 0x52, 0x85, 0x32, 0x1a, 0x70, 0x91, 0x8a, 0xfa, 0xce, 0x68, + 0x5f, 0x16, 0x88, 0x5b, 0x3a, 0x08, 0xed, 0x33, 0x2e, 0x45, 0x5f, 0xfa, 0x30, 0x5a, 0xb0, 0x3a, + 0x23, 0xab, 0x2b, 0x3d, 0xe3, 0xbf, 0x35, 0x60, 0x6d, 0xae, 0x48, 0xea, 0x1b, 0x91, 0x2d, 0x7f, + 0xe4, 0x8c, 0x4f, 0xbc, 0xc8, 0x14, 0x96, 0xd1, 0x6c, 0xf9, 0x7b, 0xa2, 0x44, 0x99, 0xc2, 0x38, + 0xac, 0x28, 0x82, 0x40, 0x5b, 0x56, 0x24, 0xce, 0x67, 0x51, 0xd8, 0x7c, 0x2f, 0xc9, 0xa8, 0x66, + 0xbb, 0x53, 0x70, 0xfd, 0xfa, 0x5b, 0x9a, 0xcc, 0xc1, 0x02, 0x76, 0x0a, 0xad, 0x88, 0xee, 0xa4, + 0x7c, 0xa4, 0xe9, 0x26, 0xa2, 0xa7, 0x6f, 0xbc, 0xa4, 0xa7, 0x84, 0x91, 0xc4, 0x5c, 0x55, 0xe4, + 0x4a, 0x8d, 0x45, 0xfd, 0x5c, 0xc0, 0xeb, 0xaa, 0x1f, 0x94, 0x75, 0xe6, 0x7b, 0xcb, 0xbf, 0xd2, + 0xbc, 0xd0, 0xf8, 0x93, 0xec, 0xf2, 0x8e, 0x6c, 0x38, 0x2a, 0xd2, 0xfb, 0x3d, 0x87, 0xd5, 0x4b, + 0xdb, 0x09, 0xd5, 0xfc, 0x34, 0xb5, 0xa8, 0x80, 0xfd, 0x3d, 0x79, 0x49, 0x7f, 0x9f, 0x52, 0xe5, + 0x84, 0xf4, 0xb7, 0x7c, 0x39, 0x0f, 0x0c, 0xd6, 0xff, 0x6d, 0x16, 0xea, 0xc9, 0x56, 0xc4, 0xa1, + 0x96, 0x7c, 0x48, 0xc9, 0x13, 0x52, 0x1e, 0x97, 0x26, 0xda, 0x03, 0x92, 0x23, 0xe6, 0x8d, 0xc7, + 0xd9, 0x14, 0xe3, 0xb1, 0x6e, 0xb3, 0xcd, 0xbd, 0xcc, 0x07, 0x96, 0x7f, 0x25, 0x1f, 0x58, 0x21, + 0xcd, 0x07, 0x76, 0xb3, 0xe3, 0x64, 0xe1, 0xe7, 0x72, 0x9c, 0x14, 0x6f, 0x76, 0x9c, 0xac, 0xff, + 0x9f, 0x0c, 0xb0, 0x79, 0x4a, 0x65, 0x4f, 0xc9, 0x4e, 0xee, 0xf2, 0x91, 0xe4, 0x62, 0xdf, 0x7c, + 0x35, 0x6a, 0x57, 0x1b, 0xa4, 0x6a, 0xb3, 0x47, 0xb0, 0xa4, 0xc7, 0x0f, 0xeb, 0xaa, 0x4a, 0xcd, + 0x64, 0x7a, 0x51, 0xac, 0xd0, 0x6a, 0x0e, 0xc0, 0xfc, 0x4b, 0x1d, 0x80, 0x85, 0x97, 0x3a, 0x00, + 0x17, 0x92, 0x0e, 0xc0, 0xf5, 0xff, 0x9c, 0x81, 0xa5, 0x14, 0xa2, 0xfa, 0xea, 0xe6, 0x2c, 0x68, + 0x21, 0xc1, 0x62, 0xb2, 0x92, 0x16, 0x74, 0xee, 0xb2, 0x07, 0x95, 0xd8, 0xa7, 0xa4, 0xe2, 0xeb, + 0x1f, 0xbe, 0xec, 0xa4, 0xc7, 0x35, 0x4c, 0xbd, 0xfa, 0xfa, 0x17, 0x50, 0xd1, 0xca, 0xc4, 0x22, + 0x12, 0x05, 0x69, 0x61, 0x17, 0x74, 0x87, 0xa3, 0x9e, 0x75, 0x0f, 0xa4, 0x21, 0x97, 0xca, 0x89, + 0xd6, 0xe5, 0x85, 0x8d, 0x08, 0x1b, 0xb0, 0xa4, 0x5c, 0x18, 0x3c, 0x8e, 0xae, 0x92, 0x6c, 0x7f, + 0x51, 0x3a, 0x32, 0x78, 0x14, 0xac, 0xb5, 0xfe, 0x13, 0xa8, 0x25, 0x38, 0xc2, 0x57, 0xb7, 0x96, + 0xb3, 0x5a, 0x23, 0x8d, 0x55, 0xd7, 0x1a, 0xd7, 0xff, 0x77, 0x0e, 0xd8, 0x3c, 0x53, 0xfa, 0x65, + 0x0e, 0x61, 0x7e, 0xc7, 0x73, 0x29, 0x3b, 0xfe, 0xff, 0xec, 0x92, 0x7c, 0x17, 0x16, 0x65, 0x02, + 0x87, 0xe6, 0xe1, 0x21, 0xaa, 0x6f, 0x46, 0x05, 0x6a, 0x14, 0xdf, 0x99, 0x75, 0x24, 0x97, 0x12, + 0x31, 0xeb, 0x9a, 0x94, 0x30, 0xe3, 0x4f, 0x3e, 0x86, 0x05, 0xdb, 0x1d, 0x9c, 0x7b, 0x3e, 0x2a, + 0x2c, 0xf5, 0x27, 0xbf, 0xfa, 0xa5, 0xef, 0x89, 0x8d, 0x36, 0xd6, 0x47, 0xd1, 0xc4, 0x94, 0x8d, + 0x19, 0xef, 0x41, 0x45, 0x03, 0xa3, 0xd7, 0xa3, 0xbb, 0xbf, 0x79, 0xd8, 0xbc, 0xc5, 0x6a, 0x50, + 0x36, 0x3b, 0x5b, 0x87, 0x9f, 0x74, 0xcc, 0xce, 0x76, 0x33, 0xc3, 0x4a, 0x90, 0xdf, 0x3b, 0xec, + 0xf5, 0x9b, 0x59, 0x63, 0x1d, 0x5a, 0xb2, 0xc5, 0x79, 0x0b, 0xe8, 0xef, 0xe6, 0x23, 0xe3, 0x03, + 0x16, 0x4a, 0x5d, 0xe3, 0x5b, 0x50, 0xd5, 0xef, 0x70, 0x49, 0x11, 0x33, 0x4e, 0x46, 0xa1, 0x65, + 0x78, 0x1a, 0x13, 0xdc, 0x02, 0x72, 0x1d, 0x0d, 0xa3, 0x6a, 0x24, 0x98, 0xbd, 0xc0, 0xd7, 0x80, + 0x32, 0x67, 0x82, 0x0c, 0xff, 0x3f, 0xa8, 0x27, 0xcd, 0x81, 0xf2, 0xa8, 0xa7, 0x09, 0xdd, 0xa2, + 0x76, 0xc2, 0x3e, 0xc8, 0xbe, 0x0f, 0xcd, 0x59, 0x73, 0xa2, 0x0c, 0xed, 0xbd, 0xa1, 0x7e, 0xc3, + 0x49, 0x5a, 0x18, 0xd9, 0x2e, 0x2c, 0xa7, 0x49, 0x31, 0x48, 0x1f, 0x37, 0x6b, 0x5b, 0x6c, 0x5e, + 0x52, 0x61, 0xdf, 0x95, 0x56, 0xe3, 0x42, 0x9a, 0xef, 0x4d, 0x5b, 0xec, 0x0d, 0xfa, 0x4f, 0xb3, + 0x1f, 0x5f, 0x00, 0xc4, 0x30, 0xd6, 0x84, 0xea, 0xe1, 0x51, 0xe7, 0xc0, 0xda, 0xda, 0x6d, 0x1f, + 0x1c, 0x74, 0xf6, 0x9a, 0xb7, 0x18, 0x83, 0x3a, 0x3a, 0xcd, 0xb6, 0x23, 0x58, 0x46, 0xc0, 0xa4, + 0xf5, 0x5e, 0xc1, 0xb2, 0x6c, 0x19, 0x9a, 0xdd, 0x83, 0x19, 0x68, 0x8e, 0xb5, 0x60, 0xf9, 0xa8, + 0x43, 0x7e, 0xb6, 0x44, 0xbb, 0x79, 0x21, 0x19, 0xcb, 0xe9, 0x0a, 0xc9, 0x98, 0x12, 0x91, 0xe4, + 0x39, 0x50, 0x02, 0xe3, 0xef, 0x65, 0x60, 0x65, 0xa6, 0x20, 0x0e, 0x2f, 0x27, 0x71, 0x31, 0x29, + 0x28, 0x56, 0x11, 0xa8, 0x4e, 0xd3, 0xbb, 0xb0, 0x18, 0x69, 0xd0, 0x33, 0xec, 0xbe, 0x19, 0x15, + 0x28, 0xe4, 0x47, 0xb0, 0xa4, 0x29, 0xe2, 0x33, 0xbc, 0x82, 0x69, 0x45, 0xb2, 0x82, 0xb1, 0x16, + 0x85, 0xf1, 0xce, 0x8c, 0x7a, 0x48, 0xd9, 0x4d, 0x7a, 0x41, 0x6c, 0x54, 0x4f, 0x8e, 0x57, 0x7d, + 0xb2, 0xc7, 0x33, 0x84, 0x90, 0x1c, 0xad, 0xbe, 0xe1, 0xaa, 0xfb, 0x3f, 0x58, 0x00, 0xf6, 0xf1, + 0x94, 0xfb, 0xd7, 0x18, 0x3e, 0x1e, 0xbc, 0x2c, 0x9e, 0x4a, 0x69, 0x9b, 0xd9, 0x57, 0x4a, 0x11, + 0x49, 0x4b, 0xd1, 0xc8, 0xbf, 0x3c, 0x45, 0xa3, 0xf0, 0xb2, 0x14, 0x8d, 0x37, 0xa1, 0xe6, 0x9c, + 0xb9, 0x9e, 0x60, 0x85, 0x42, 0xe4, 0x0b, 0x5a, 0x0b, 0xf7, 0x73, 0x0f, 0xaa, 0x66, 0x55, 0x02, + 0x85, 0xc0, 0x17, 0xb0, 0x8f, 0x62, 0x24, 0x3e, 0x3c, 0xc3, 0x74, 0x22, 0x9d, 0x09, 0x76, 0x86, + 0x67, 0x5c, 0x2a, 0xd7, 0x68, 0x6e, 0x52, 0x95, 0x05, 0x3c, 0x60, 0x6f, 0x41, 0x3d, 0xf0, 0xa6, + 0x42, 0x82, 0x56, 0xcb, 0x40, 0x66, 0xf7, 0x2a, 0x41, 0x8f, 0x94, 0x8f, 0x65, 0x69, 0x1a, 0x70, + 0x6b, 0xec, 0x04, 0x81, 0x90, 0x7b, 0x06, 0x9e, 0x1b, 0xfa, 0xde, 0x48, 0x5a, 0xd2, 0x17, 0xa7, + 0x01, 0xdf, 0xa7, 0x92, 0x2d, 0x2a, 0x60, 0xdf, 0x8e, 0x87, 0x34, 0xb1, 0x1d, 0x3f, 0x68, 0x01, + 0x0e, 0x49, 0xcd, 0x14, 0x05, 0x55, 0xdb, 0xf1, 0xa3, 0xb1, 0x88, 0x8f, 0x60, 0x26, 0x75, 0xa4, + 0x32, 0x9b, 0x3a, 0xf2, 0xa3, 0xf4, 0xd4, 0x91, 0x1a, 0x36, 0xfd, 0x58, 0x36, 0x3d, 0xbf, 0xc5, + 0x5f, 0x2a, 0x83, 0x64, 0x3e, 0x23, 0xa6, 0xfe, 0x65, 0x32, 0x62, 0x1a, 0x69, 0x19, 0x31, 0xef, + 0x41, 0x05, 0x73, 0x15, 0xac, 0x73, 0x47, 0x08, 0x47, 0xe4, 0x19, 0x68, 0xea, 0xc9, 0x0c, 0xbb, + 0x8e, 0x1b, 0x9a, 0xe0, 0xab, 0x3f, 0x83, 0xf9, 0xe4, 0x94, 0xc5, 0x5f, 0x62, 0x72, 0x8a, 0xcc, + 0xa9, 0xd8, 0x80, 0x92, 0xda, 0x27, 0xc6, 0x20, 0x7f, 0xea, 0x7b, 0x63, 0x65, 0x31, 0x15, 0x7f, + 0xb3, 0x3a, 0x64, 0x43, 0x4f, 0x56, 0xce, 0x86, 0x9e, 0xf1, 0x9b, 0x50, 0xd1, 0x48, 0x8d, 0xbd, + 0x41, 0xb6, 0x19, 0xa1, 0x84, 0x48, 0xa9, 0x8d, 0x56, 0xb1, 0x2c, 0xa1, 0xdd, 0xa1, 0xe0, 0x37, + 0x43, 0xc7, 0xe7, 0x98, 0x46, 0x66, 0xf9, 0xfc, 0x82, 0xfb, 0x81, 0xb2, 0x60, 0x37, 0xa3, 0x02, + 0x93, 0xe0, 0xc6, 0x5f, 0x81, 0xa5, 0xc4, 0xde, 0x4a, 0x16, 0xf1, 0x16, 0x2c, 0xe0, 0xba, 0x29, + 0x0f, 0x63, 0x32, 0x49, 0x44, 0x96, 0x61, 0x7e, 0x30, 0x19, 0xdf, 0xad, 0x89, 0xef, 0x9d, 0x60, + 0x27, 0x19, 0xb3, 0x22, 0x61, 0x47, 0xbe, 0x77, 0x62, 0xfc, 0x79, 0x0e, 0x72, 0xbb, 0xde, 0x44, + 0x0f, 0xaa, 0xc9, 0xcc, 0x05, 0xd5, 0x48, 0xcd, 0xca, 0x8a, 0x34, 0x27, 0x29, 0x0c, 0xa3, 0xd9, + 0x59, 0x69, 0x4f, 0x0f, 0xa0, 0x2e, 0xf8, 0x44, 0xe8, 0x09, 0xd5, 0xf4, 0xd2, 0xf6, 0x49, 0xd4, + 0xcc, 0xd1, 0xe1, 0xb3, 0xc7, 0x61, 0xdf, 0xdb, 0x21, 0x38, 0x5b, 0x86, 0x5c, 0xa4, 0x17, 0x60, + 0xb1, 0xf8, 0x64, 0xab, 0xb0, 0x80, 0xc1, 0x93, 0xd7, 0xd2, 0x85, 0x26, 0xbf, 0xd8, 0x37, 0x61, + 0x29, 0xd9, 0x2e, 0xb1, 0x22, 0x29, 0x1b, 0xe9, 0x0d, 0x23, 0x4f, 0xba, 0x0d, 0x82, 0x8f, 0x10, + 0x8e, 0xf4, 0xc4, 0x9f, 0x72, 0x8e, 0x45, 0x1a, 0xd3, 0x2b, 0x25, 0x98, 0xde, 0x3d, 0xa8, 0x84, + 0xa3, 0x0b, 0x6b, 0x62, 0x5f, 0x8f, 0x3c, 0x7b, 0x28, 0xcf, 0x37, 0x84, 0xa3, 0x8b, 0x23, 0x82, + 0xb0, 0x47, 0x00, 0xe3, 0xc9, 0x44, 0x9e, 0x3d, 0xb4, 0xe2, 0xc6, 0xa4, 0xbc, 0x7f, 0x74, 0x44, + 0x24, 0x67, 0x96, 0xc7, 0x93, 0x09, 0xfd, 0xc9, 0xb6, 0xa1, 0x9e, 0x9a, 0xea, 0x75, 0x57, 0xc5, + 0xfa, 0x79, 0x93, 0x8d, 0x94, 0xc3, 0x59, 0x1b, 0xe8, 0xb0, 0xf5, 0xef, 0x03, 0xfb, 0x05, 0x13, + 0xae, 0xfa, 0x50, 0x8e, 0xc6, 0xa7, 0xe7, 0x2b, 0x61, 0xf4, 0x6e, 0x25, 0x91, 0xaf, 0xd4, 0x1e, + 0x0e, 0x7d, 0xc1, 0x17, 0xe9, 0xc2, 0x8c, 0x58, 0x3e, 0x68, 0x37, 0x66, 0x9b, 0xf8, 0xbe, 0xf1, + 0x97, 0x19, 0x28, 0x50, 0xf2, 0xd4, 0xdb, 0xd0, 0x20, 0xfc, 0x28, 0x40, 0x49, 0x3a, 0xde, 0xe8, + 0xde, 0xed, 0xcb, 0xd8, 0x24, 0x71, 0x2c, 0xb4, 0xc4, 0xcf, 0x6c, 0xb4, 0xf3, 0x5a, 0xf2, 0xe7, + 0x3d, 0x28, 0x47, 0x5d, 0x6b, 0xa4, 0x53, 0x52, 0x3d, 0xb3, 0xd7, 0x21, 0x7f, 0xee, 0x4d, 0x94, + 0x89, 0x03, 0xe2, 0x95, 0x34, 0x11, 0x1e, 0x8f, 0x45, 0xf4, 0x41, 0x83, 0x97, 0xaa, 0x79, 0xd4, + 0x09, 0x92, 0xc1, 0xfc, 0x1c, 0x17, 0x52, 0xe6, 0x78, 0x0c, 0x0d, 0xc1, 0x07, 0x34, 0x07, 0xf8, + 0xcd, 0x97, 0xe6, 0xd7, 0x85, 0x84, 0x37, 0x18, 0x4d, 0x87, 0x5c, 0x37, 0x30, 0x61, 0xb4, 0x8c, + 0x84, 0x2b, 0xc9, 0xda, 0xf8, 0x83, 0x0c, 0xf1, 0x17, 0xd1, 0x2e, 0x7b, 0x00, 0x79, 0x71, 0xbf, + 0xcd, 0x18, 0x40, 0xa3, 0x30, 0x6a, 0x81, 0x67, 0x22, 0x06, 0x66, 0x4b, 0x4f, 0xc7, 0xc9, 0xd6, + 0x6b, 0x66, 0xc5, 0x9d, 0x8e, 0x23, 0x1b, 0xcd, 0xd7, 0xd4, 0xb4, 0x66, 0xec, 0x1b, 0x34, 0xfb, + 0xe8, 0x98, 0x6e, 0x68, 0x61, 0x37, 0xf9, 0xc4, 0x8d, 0xa9, 0xa4, 0xc0, 0xe1, 0x19, 0xd7, 0xc2, + 0x6d, 0xfe, 0x28, 0x0b, 0xb5, 0xc4, 0x88, 0x30, 0xee, 0x48, 0x5c, 0x00, 0x64, 0x5c, 0x97, 0xfb, + 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9d, 0xb2, 0x89, 0x75, 0x8a, 0x5c, 0xfd, 0x39, 0xdd, 0xd5, + 0xff, 0x18, 0xca, 0x71, 0xc2, 0x6f, 0x72, 0x48, 0xa2, 0x3f, 0x15, 0x4c, 0x1e, 0x23, 0xc5, 0xc1, + 0x01, 0x05, 0x3d, 0x38, 0xe0, 0x7b, 0x9a, 0x2f, 0x79, 0x01, 0x9b, 0x31, 0xd2, 0x56, 0xf4, 0x97, + 0xe2, 0x49, 0x36, 0x3e, 0x82, 0x8a, 0x36, 0x78, 0xdd, 0x67, 0x9c, 0x49, 0xf8, 0x8c, 0xa3, 0xb4, + 0x8f, 0x6c, 0x9c, 0xf6, 0x61, 0xfc, 0x76, 0x16, 0x6a, 0xe2, 0x7c, 0x39, 0xee, 0xd9, 0x91, 0x37, + 0x72, 0x06, 0x68, 0x6c, 0x8f, 0x4e, 0x98, 0x14, 0xb4, 0xd4, 0x39, 0x93, 0x47, 0x8c, 0xe4, 0x2c, + 0x3d, 0xbb, 0x8d, 0x98, 0x74, 0x94, 0xdd, 0x66, 0x40, 0x4d, 0x30, 0xc6, 0x13, 0x3b, 0xe0, 0x5a, + 0x3a, 0xb2, 0x59, 0x39, 0xe5, 0x7c, 0xd3, 0x0e, 0x88, 0x43, 0x7e, 0x13, 0x96, 0x04, 0x0e, 0x26, + 0xf6, 0x8c, 0x9d, 0xd1, 0xc8, 0x21, 0x4c, 0xb2, 0xe0, 0x34, 0x4f, 0x39, 0x37, 0xed, 0x90, 0xef, + 0x8b, 0x02, 0x99, 0xbd, 0x5c, 0x1a, 0x3a, 0x81, 0x7d, 0x12, 0x47, 0x87, 0x45, 0xdf, 0xe8, 0x22, + 0xb3, 0xaf, 0x34, 0x17, 0x19, 0x65, 0xf8, 0x55, 0xc6, 0xf6, 0x55, 0xe4, 0x22, 0x9b, 0xa1, 0xa4, + 0xe2, 0x2c, 0x25, 0x19, 0xff, 0x21, 0x0b, 0x15, 0x8d, 0x2c, 0x5f, 0xe5, 0x76, 0xbd, 0x3b, 0xe7, + 0x1c, 0x29, 0xeb, 0x7e, 0x90, 0x37, 0x93, 0x5d, 0xa2, 0x27, 0x9d, 0xf2, 0xa4, 0x35, 0x02, 0xbe, + 0x03, 0x65, 0x71, 0xea, 0xde, 0x43, 0x5b, 0xa3, 0xcc, 0xf2, 0x47, 0xc0, 0xd1, 0xf4, 0x44, 0x15, + 0x3e, 0xc1, 0xc2, 0x42, 0x5c, 0xf8, 0x44, 0x14, 0xbe, 0x28, 0x24, 0xf4, 0x3b, 0x50, 0x95, 0xad, + 0xe2, 0x9e, 0xe2, 0x74, 0xe3, 0x53, 0x9f, 0xd8, 0x6f, 0xb3, 0x42, 0xdd, 0xd1, 0xe6, 0xcb, 0x8a, + 0x4f, 0x54, 0xc5, 0xd2, 0xcb, 0x2a, 0x3e, 0xa1, 0x0f, 0x63, 0x27, 0x8a, 0xb2, 0xc5, 0x28, 0x0e, + 0xc5, 0xc7, 0x1e, 0xc1, 0x92, 0x62, 0x57, 0x53, 0xd7, 0x76, 0x5d, 0x6f, 0xea, 0x0e, 0xb8, 0xca, + 0x07, 0x61, 0xb2, 0xe8, 0x38, 0x2e, 0x31, 0x86, 0x51, 0xc2, 0x20, 0x45, 0x83, 0x3c, 0x84, 0x02, + 0xc9, 0xe5, 0x24, 0x7c, 0xa4, 0x33, 0x2e, 0x42, 0x61, 0x0f, 0xa0, 0x40, 0xe2, 0x79, 0xf6, 0x46, + 0x66, 0x43, 0x08, 0xc6, 0x06, 0x34, 0x50, 0xc4, 0xd4, 0x38, 0xee, 0x8b, 0xa4, 0x12, 0x63, 0x19, + 0xd8, 0x01, 0x1d, 0x22, 0x3d, 0x4a, 0xe9, 0xbf, 0xe4, 0xa0, 0xa2, 0x81, 0x05, 0x5b, 0xc4, 0xb8, + 0x16, 0x6b, 0xe8, 0xd8, 0x63, 0xae, 0x5c, 0x3a, 0x35, 0xb3, 0x86, 0xd0, 0x6d, 0x09, 0x14, 0x97, + 0x82, 0x7d, 0x71, 0x66, 0x79, 0xd3, 0xd0, 0x1a, 0xf2, 0x33, 0x9f, 0x73, 0x29, 0x2c, 0x55, 0xed, + 0x8b, 0xb3, 0xc3, 0x69, 0xb8, 0x8d, 0x30, 0x81, 0x25, 0x88, 0x5a, 0xc3, 0x92, 0xa1, 0x18, 0x63, + 0xfb, 0x2a, 0xc6, 0x92, 0xf1, 0x40, 0xb4, 0x44, 0xf9, 0x28, 0x1e, 0x88, 0xd4, 0x96, 0x59, 0x4e, + 0x5e, 0x98, 0xe7, 0xe4, 0xdf, 0x86, 0x55, 0xe2, 0xe4, 0x92, 0x47, 0x58, 0x33, 0x24, 0xb5, 0x8c, + 0xa5, 0x72, 0x92, 0x9a, 0xfc, 0xd5, 0x14, 0x33, 0x50, 0xe7, 0x23, 0x70, 0x7e, 0x4c, 0x27, 0x2a, + 0x63, 0x8a, 0x99, 0xc9, 0xc6, 0x7b, 0xce, 0x8f, 0xb9, 0xc0, 0x44, 0x7f, 0xb3, 0x8e, 0x29, 0x23, + 0x8f, 0xc7, 0x8e, 0x3b, 0x8b, 0x69, 0x5f, 0x25, 0x31, 0xcb, 0x12, 0xd3, 0xbe, 0xd2, 0x31, 0xdf, + 0x87, 0xb5, 0x31, 0x1f, 0x3a, 0x76, 0xb2, 0x59, 0x2b, 0x96, 0x20, 0x96, 0xa9, 0x58, 0xab, 0xd3, + 0x23, 0x0d, 0x52, 0xac, 0xc6, 0x8f, 0xbd, 0xf1, 0x89, 0x43, 0x97, 0x27, 0x79, 0xc0, 0xf3, 0x66, + 0xdd, 0x9d, 0x8e, 0x7f, 0x88, 0x60, 0x51, 0x25, 0x30, 0x6a, 0x50, 0xe9, 0x85, 0xde, 0x44, 0x6d, + 0x73, 0x1d, 0xaa, 0xf4, 0x29, 0xb3, 0x7d, 0xee, 0xc0, 0x6d, 0xa4, 0xcd, 0xbe, 0x37, 0xf1, 0x46, + 0xde, 0xd9, 0x75, 0xc2, 0xa0, 0xf4, 0x9f, 0x32, 0xb0, 0x94, 0x28, 0x95, 0xe7, 0xfc, 0xdb, 0x74, + 0xb0, 0xa2, 0x94, 0x0d, 0x22, 0xe7, 0x45, 0xed, 0xf2, 0x21, 0x44, 0x3a, 0x55, 0x2a, 0x8d, 0xa3, + 0x1d, 0xa7, 0x1a, 0xab, 0x8a, 0x44, 0xdb, 0xad, 0x79, 0xda, 0x96, 0xf5, 0x55, 0x12, 0xb2, 0x6a, + 0xe2, 0x57, 0x65, 0x74, 0xf8, 0x50, 0x4e, 0x39, 0x97, 0x8c, 0x7f, 0xd5, 0x8d, 0x4f, 0x6a, 0x04, + 0xb1, 0x45, 0x2a, 0x30, 0xfe, 0x79, 0x06, 0x20, 0x1e, 0x1d, 0x46, 0xe0, 0x46, 0x17, 0x28, 0xbd, + 0xe2, 0xa3, 0x5d, 0x96, 0x6f, 0x40, 0x35, 0x0a, 0xc4, 0x8b, 0xaf, 0xe4, 0x8a, 0x82, 0x89, 0x7b, + 0xf9, 0x1d, 0x68, 0x9c, 0x8d, 0xbc, 0x13, 0x14, 0x9d, 0xe4, 0x05, 0x4a, 0x39, 0x4f, 0x75, 0x02, + 0xab, 0x6b, 0x31, 0xbe, 0xc0, 0xf3, 0xa9, 0xb1, 0x7a, 0xfa, 0x75, 0x6c, 0xfc, 0x4e, 0x36, 0x8a, + 0x48, 0x8a, 0x57, 0xe2, 0xc5, 0x7a, 0xc6, 0xcf, 0xe3, 0xd8, 0x7e, 0x91, 0x43, 0xe7, 0x23, 0xa8, + 0xfb, 0xc4, 0x1d, 0x15, 0xeb, 0xcc, 0xbf, 0x80, 0x75, 0xd6, 0xfc, 0xc4, 0x95, 0xfb, 0x75, 0x68, + 0xda, 0xc3, 0x0b, 0xee, 0x87, 0x0e, 0x9a, 0x8d, 0x51, 0x50, 0x93, 0x31, 0x40, 0x1a, 0x1c, 0x25, + 0xa2, 0x77, 0xa0, 0x21, 0x33, 0xd0, 0x22, 0x4c, 0xf9, 0xa6, 0x45, 0x0c, 0x16, 0x88, 0xc6, 0xbf, + 0x52, 0x21, 0x50, 0xc9, 0xdd, 0x7d, 0xf1, 0xaa, 0xe8, 0x33, 0xcc, 0xce, 0xbb, 0xac, 0x24, 0x21, + 0x49, 0x6b, 0xb4, 0xe4, 0x47, 0x04, 0x94, 0xb6, 0xe8, 0xe4, 0xb2, 0xe6, 0x5f, 0x65, 0x59, 0x8d, + 0x3f, 0xc9, 0x40, 0x71, 0xd7, 0x9b, 0x08, 0xbd, 0x5c, 0xc8, 0x73, 0x78, 0x4c, 0x22, 0x37, 0xc4, + 0x82, 0xf8, 0xec, 0x0e, 0x5f, 0x9c, 0x89, 0x91, 0x2a, 0x6f, 0xd4, 0x92, 0xf2, 0xc6, 0xf7, 0xe0, + 0x0e, 0x3a, 0x79, 0x7c, 0x6f, 0xe2, 0xf9, 0xe2, 0xa8, 0xda, 0x23, 0x92, 0x3b, 0x3c, 0x37, 0x3c, + 0x57, 0xbc, 0xf3, 0xf6, 0x29, 0xe7, 0x47, 0x1a, 0xc6, 0x7e, 0x84, 0x80, 0xa9, 0x4c, 0xa3, 0xf0, + 0xc2, 0x22, 0x55, 0x51, 0x0a, 0x46, 0xc4, 0x51, 0x1b, 0xa2, 0xa0, 0x83, 0x70, 0x14, 0x8d, 0x8c, + 0xef, 0x42, 0x39, 0xb2, 0x3a, 0xb0, 0x77, 0xa1, 0x7c, 0xee, 0x4d, 0xa4, 0x69, 0x22, 0x93, 0xc8, + 0x56, 0x91, 0xb3, 0x36, 0x4b, 0xe7, 0xf4, 0x47, 0x60, 0xfc, 0x79, 0x11, 0x8a, 0x5d, 0xf7, 0xc2, + 0x73, 0x06, 0x18, 0x44, 0x35, 0xe6, 0x63, 0x4f, 0xa5, 0xc1, 0x8a, 0xbf, 0x31, 0x50, 0x22, 0x7e, + 0x99, 0x22, 0x27, 0x03, 0x25, 0xa2, 0x37, 0x29, 0x56, 0x60, 0xc1, 0xd7, 0x9f, 0x96, 0x28, 0xf8, + 0x18, 0xd6, 0x19, 0x29, 0x6d, 0x05, 0x2d, 0x8d, 0x58, 0xb4, 0x45, 0x4f, 0x1e, 0xe0, 0x92, 0x51, + 0x5a, 0x52, 0x19, 0x21, 0xb8, 0x60, 0xaf, 0x41, 0x51, 0x26, 0x87, 0x50, 0xa8, 0x3d, 0xc5, 0x61, + 0x4a, 0x10, 0x52, 0x83, 0xcf, 0xc9, 0x49, 0x17, 0x49, 0x54, 0x42, 0x4f, 0x97, 0xc0, 0x6d, 0x41, + 0x6b, 0xf7, 0xa0, 0x42, 0xf8, 0x84, 0x52, 0x92, 0x61, 0x4f, 0x08, 0x42, 0x84, 0x94, 0x17, 0x5a, + 0xca, 0xa9, 0x2f, 0xb4, 0x60, 0x94, 0x5c, 0xc4, 0x65, 0x69, 0x8a, 0x40, 0xef, 0x72, 0x68, 0x70, + 0xf5, 0x3c, 0x91, 0x54, 0xee, 0x29, 0x4b, 0x4f, 0x29, 0xf7, 0x6f, 0x42, 0xed, 0xd4, 0x1e, 0x8d, + 0x4e, 0xec, 0xc1, 0x73, 0xd2, 0x49, 0xab, 0x64, 0x86, 0x53, 0x40, 0x54, 0x4a, 0xef, 0x41, 0x45, + 0xdb, 0x65, 0x8c, 0x69, 0xca, 0x9b, 0x10, 0xef, 0xef, 0xac, 0xa9, 0xa9, 0xfe, 0x0a, 0xa6, 0x26, + 0x2d, 0xb6, 0xab, 0x91, 0x8c, 0xed, 0xba, 0x83, 0xdc, 0x54, 0xc6, 0xff, 0x34, 0xe9, 0x11, 0x08, + 0x7b, 0x38, 0xc4, 0xf8, 0x1f, 0x7a, 0x71, 0x0d, 0x17, 0x8f, 0xca, 0x17, 0x49, 0xa8, 0x25, 0x18, + 0xa1, 0xdc, 0x25, 0x7b, 0xe9, 0xc4, 0x76, 0x86, 0x18, 0x4b, 0x4b, 0x6a, 0x6c, 0xd1, 0x1e, 0x87, + 0x47, 0xb6, 0x33, 0x64, 0xf7, 0xa1, 0xaa, 0x8a, 0xf1, 0x76, 0x5c, 0xa2, 0xf5, 0x97, 0xc5, 0xe2, + 0x4e, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe3, 0x54, 0xbb, 0x8a, 0x44, 0x41, 0x3a, 0x78, 0x0f, 0x63, + 0x2a, 0x42, 0x8e, 0x09, 0x75, 0xf5, 0x27, 0x77, 0xe4, 0x5c, 0x25, 0x95, 0xaa, 0xff, 0xc9, 0x4b, + 0x43, 0x98, 0x42, 0x10, 0x23, 0x67, 0xd1, 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0x2c, 0x22, 0x04, + 0xf6, 0x5d, 0x4d, 0x91, 0x6a, 0x21, 0xf2, 0x6b, 0x33, 0xed, 0xdf, 0x94, 0x4a, 0x70, 0x17, 0xc0, + 0x09, 0xc4, 0x2d, 0x13, 0x70, 0x77, 0x88, 0xb9, 0x71, 0x25, 0xb3, 0xec, 0x04, 0xcf, 0x08, 0xf0, + 0xd5, 0x6a, 0x58, 0x6d, 0xa8, 0xea, 0xd3, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0x75, 0x0e, 0x9a, 0xb7, + 0x58, 0x05, 0x8a, 0xbd, 0x4e, 0xbf, 0xbf, 0x87, 0x2e, 0xa7, 0x2a, 0x94, 0xa2, 0xcc, 0x9d, 0xac, + 0xf8, 0x6a, 0x6f, 0x6d, 0x75, 0x8e, 0xfa, 0x9d, 0xed, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, 0x99, + 0x33, 0xfe, 0x22, 0x07, 0x15, 0x6d, 0x15, 0x5e, 0xcc, 0x8c, 0xef, 0x02, 0xa0, 0x4a, 0x13, 0x87, + 0x87, 0xe5, 0xcd, 0xb2, 0x80, 0xd0, 0xe6, 0xeb, 0xc6, 0xf2, 0x1c, 0xbd, 0x2e, 0xa2, 0x8c, 0xe5, + 0x6f, 0x42, 0x8d, 0x1e, 0xea, 0xd0, 0x1d, 0x87, 0x05, 0xb3, 0x4a, 0x40, 0xc9, 0xaa, 0x31, 0xf5, + 0x0f, 0x91, 0x30, 0x29, 0x44, 0xa6, 0xed, 0x13, 0x08, 0xd3, 0x42, 0x30, 0xa7, 0x27, 0xf0, 0x46, + 0x17, 0x9c, 0x30, 0x48, 0x22, 0xac, 0x48, 0x58, 0x5f, 0xe6, 0x28, 0x4a, 0x7e, 0xa8, 0xe5, 0x9e, + 0x15, 0xcc, 0x2a, 0x01, 0x65, 0x47, 0xdf, 0x54, 0x04, 0x54, 0x42, 0x02, 0x5a, 0x9b, 0xa7, 0x86, + 0x04, 0xf1, 0xec, 0xcd, 0xd9, 0xb3, 0xca, 0x48, 0x18, 0x5f, 0x9b, 0xaf, 0xf7, 0x72, 0xbb, 0x16, + 0x7b, 0x17, 0xd8, 0x78, 0x32, 0xb1, 0x52, 0x2c, 0x4d, 0x79, 0xb3, 0x31, 0x9e, 0x4c, 0xfa, 0x9a, + 0x21, 0xe6, 0x2b, 0x30, 0x82, 0x7d, 0x0e, 0xac, 0x2d, 0x0e, 0x30, 0x0e, 0x31, 0x32, 0xa1, 0xc6, + 0x6c, 0x39, 0xa3, 0xb3, 0xe5, 0x14, 0xee, 0x97, 0x4d, 0xe5, 0x7e, 0x2f, 0xe2, 0x13, 0xc6, 0x0e, + 0x54, 0x8e, 0xb4, 0x67, 0x80, 0xee, 0x8b, 0x1b, 0x42, 0x3d, 0x00, 0x44, 0x77, 0x07, 0x19, 0xb7, + 0x7c, 0xf9, 0xee, 0x8f, 0x36, 0x9a, 0xac, 0x36, 0x1a, 0xe3, 0x9f, 0x65, 0xe8, 0x89, 0x85, 0x68, + 0xf0, 0xf1, 0xcb, 0x43, 0xca, 0x0f, 0x14, 0xa7, 0x88, 0x56, 0x94, 0xff, 0x47, 0x66, 0x77, 0xe2, + 0xd0, 0x2c, 0xef, 0xf4, 0x34, 0xe0, 0x2a, 0xd9, 0xa9, 0x82, 0xb0, 0x43, 0x04, 0x29, 0xe1, 0x5b, + 0x48, 0xf8, 0x0e, 0xb5, 0x1f, 0xc8, 0xa4, 0x27, 0x21, 0x7c, 0xef, 0xdb, 0x57, 0xb2, 0xd7, 0x40, + 0x88, 0x20, 0xd2, 0x50, 0xad, 0x52, 0xbc, 0xa2, 0x6f, 0xe3, 0x1f, 0xcb, 0x2c, 0xd6, 0xd9, 0xf5, + 0x7d, 0x08, 0xa5, 0xa8, 0xd5, 0xe4, 0x0d, 0xab, 0x30, 0xa3, 0x72, 0x71, 0x8f, 0xa3, 0x56, 0x9e, + 0x18, 0x31, 0x1d, 0x2e, 0x74, 0x36, 0x74, 0xb5, 0x51, 0x7f, 0x03, 0xd8, 0xa9, 0xe3, 0xcf, 0x22, + 0xd3, 0x61, 0x6b, 0x62, 0x89, 0x86, 0x6d, 0x1c, 0xc3, 0x92, 0xe2, 0x12, 0x9a, 0x46, 0x90, 0xdc, + 0xbc, 0xcc, 0x4b, 0x98, 0x7c, 0x76, 0x8e, 0xc9, 0x1b, 0x3f, 0xcd, 0x43, 0x51, 0x3d, 0xa9, 0x95, + 0xf6, 0x0c, 0x54, 0x39, 0xf9, 0x0c, 0x54, 0x2b, 0xf1, 0x64, 0x08, 0x6e, 0xbd, 0xbc, 0xef, 0xdf, + 0x99, 0xbd, 0xb2, 0x35, 0xa3, 0x79, 0xe2, 0xda, 0x5e, 0x85, 0xfc, 0xc4, 0x0e, 0xcf, 0xd1, 0x40, + 0x46, 0xc4, 0x83, 0xdf, 0xca, 0x98, 0x5e, 0x48, 0x1a, 0xd3, 0xd3, 0x9e, 0xcc, 0x22, 0x91, 0x74, + 0xee, 0xc9, 0xac, 0x3b, 0x40, 0xf2, 0x85, 0x16, 0x66, 0x54, 0x42, 0x80, 0xb8, 0x8b, 0x92, 0xe2, + 0x48, 0x69, 0x56, 0x1c, 0x79, 0x65, 0x51, 0xe1, 0xdb, 0xb0, 0x40, 0xe9, 0xe6, 0x32, 0x95, 0x4d, + 0x5d, 0x28, 0x72, 0x0d, 0xd5, 0xff, 0x14, 0x5b, 0x6c, 0x4a, 0x5c, 0xfd, 0xfd, 0x99, 0x4a, 0xe2, + 0xfd, 0x19, 0xdd, 0xc8, 0x5f, 0x4d, 0x1a, 0xf9, 0x1f, 0x40, 0x33, 0x5a, 0x50, 0x34, 0x99, 0xb9, + 0x81, 0x4c, 0x94, 0xa9, 0x2b, 0xb8, 0xe0, 0x92, 0x07, 0x41, 0x7c, 0x21, 0xd6, 0x13, 0x17, 0xa2, + 0xe0, 0x61, 0xed, 0x30, 0xe4, 0xe3, 0x49, 0x28, 0x2f, 0x44, 0x0c, 0xa5, 0xd7, 0x07, 0x98, 0x4c, + 0xf2, 0xac, 0x41, 0xb9, 0x7b, 0x60, 0xed, 0xec, 0x75, 0x9f, 0xee, 0xf6, 0x9b, 0x19, 0xf1, 0xd9, + 0x3b, 0xde, 0xda, 0xea, 0x74, 0xb6, 0xf1, 0xc6, 0x01, 0x58, 0xd8, 0x69, 0x77, 0xc5, 0xed, 0x93, + 0x33, 0x7e, 0x2f, 0x0b, 0x15, 0xad, 0x79, 0xf6, 0x7e, 0xb4, 0x2a, 0xf4, 0x44, 0xc9, 0xdd, 0xf9, + 0x21, 0x6c, 0x28, 0x56, 0xac, 0x2d, 0x4b, 0xf4, 0x40, 0x58, 0xf6, 0xc6, 0x07, 0xc2, 0xd8, 0xdb, + 0xd0, 0xb0, 0xa9, 0x85, 0x68, 0x15, 0xa4, 0x39, 0x58, 0x82, 0xe5, 0x22, 0x60, 0x70, 0x5d, 0x7c, + 0x9f, 0x08, 0xbc, 0xbc, 0x8a, 0x67, 0x8b, 0xae, 0x14, 0x5c, 0xac, 0xe2, 0xa9, 0xed, 0x8c, 0xa6, + 0x3e, 0x97, 0xee, 0xdb, 0xe8, 0x66, 0x26, 0xa8, 0xa9, 0x8a, 0x8d, 0x0f, 0x00, 0xe2, 0x31, 0x27, + 0x17, 0xe7, 0x56, 0x72, 0x71, 0x32, 0xda, 0xe2, 0x64, 0x8d, 0x6d, 0x62, 0x23, 0x72, 0xa1, 0x23, + 0x4f, 0xf5, 0x37, 0x41, 0x59, 0xa4, 0x2c, 0x0c, 0x6f, 0x9d, 0x8c, 0x78, 0xa8, 0xd2, 0x61, 0x17, + 0x65, 0x49, 0x37, 0x2a, 0x50, 0xd9, 0xe9, 0x71, 0x2b, 0x31, 0x37, 0x92, 0x24, 0x39, 0xcb, 0x8d, + 0x24, 0xaa, 0x19, 0x95, 0x1b, 0xeb, 0xd0, 0xda, 0xe6, 0xa2, 0xb5, 0xf6, 0x68, 0x34, 0x33, 0x1c, + 0xe3, 0x0e, 0xdc, 0x4e, 0x29, 0x93, 0x46, 0x88, 0x8f, 0x61, 0xa5, 0x4d, 0x99, 0xaf, 0x5f, 0x55, + 0x8a, 0x8b, 0xd1, 0x82, 0xd5, 0xd9, 0x26, 0x65, 0x67, 0x3b, 0xb0, 0xb8, 0xcd, 0x4f, 0xa6, 0x67, + 0x7b, 0xfc, 0x22, 0xee, 0x88, 0x41, 0x3e, 0x38, 0xf7, 0x2e, 0xe5, 0xfa, 0xe0, 0xdf, 0x18, 0x48, + 0x26, 0x70, 0xac, 0x60, 0xc2, 0x07, 0xca, 0x22, 0x8a, 0x90, 0xde, 0x84, 0x0f, 0x8c, 0xf7, 0x81, + 0xe9, 0xed, 0xc8, 0xf5, 0x12, 0x5a, 0xc2, 0xf4, 0xc4, 0x0a, 0xae, 0x83, 0x90, 0x8f, 0xd5, 0x0b, + 0x38, 0x10, 0x4c, 0x4f, 0x7a, 0x04, 0x31, 0xde, 0x81, 0xea, 0x91, 0x7d, 0x6d, 0xf2, 0xcf, 0x65, + 0xf2, 0xc6, 0x1a, 0x14, 0x27, 0xf6, 0xb5, 0x60, 0x03, 0x91, 0x73, 0x04, 0x8b, 0x8d, 0x3f, 0xcc, + 0xc3, 0x02, 0x61, 0xb2, 0xfb, 0xf4, 0x48, 0xa5, 0xe3, 0xe2, 0x31, 0x54, 0x8c, 0x52, 0x03, 0xcd, + 0xf1, 0xd2, 0xec, 0x3c, 0x2f, 0x95, 0x06, 0x34, 0xf5, 0x38, 0x87, 0x32, 0x63, 0xbb, 0xd3, 0xb1, + 0x7a, 0x91, 0x23, 0x99, 0xfe, 0x99, 0x8f, 0x1f, 0x21, 0xa5, 0xdc, 0xb8, 0xa4, 0xa3, 0x31, 0xd6, + 0x45, 0x68, 0x74, 0xea, 0x8a, 0x90, 0xec, 0x52, 0x07, 0xa5, 0x2a, 0x3c, 0x45, 0x95, 0x16, 0x94, + 0x54, 0x78, 0xe6, 0x14, 0x9b, 0xd2, 0xcb, 0x15, 0x1b, 0xb2, 0xac, 0xbd, 0x40, 0xb1, 0x81, 0x57, + 0x50, 0x6c, 0x5e, 0xc1, 0xc9, 0x77, 0x1b, 0x4a, 0x78, 0xef, 0x6b, 0xdc, 0x53, 0xdc, 0xf7, 0x82, + 0x7b, 0x7e, 0x47, 0x13, 0xfd, 0x29, 0xc2, 0xe0, 0x4e, 0x7c, 0x4c, 0x4c, 0xfe, 0xf9, 0x2f, 0xc7, + 0x79, 0xf2, 0x19, 0x14, 0x25, 0x54, 0x10, 0xb4, 0x6b, 0x8f, 0xd5, 0xfb, 0x46, 0xf8, 0xb7, 0x58, + 0x36, 0x7c, 0x94, 0xe5, 0xf3, 0xa9, 0xe3, 0xf3, 0xa1, 0x7a, 0xd9, 0xc2, 0xc1, 0x33, 0x2a, 0x20, + 0x62, 0x82, 0x42, 0x0d, 0x71, 0xbd, 0x4b, 0x57, 0xe6, 0xb5, 0x17, 0x9d, 0xe0, 0x99, 0xf8, 0x34, + 0x18, 0x34, 0xf1, 0x85, 0xb3, 0x89, 0xe7, 0xab, 0xcb, 0xc9, 0xf8, 0x69, 0x06, 0x9a, 0xf2, 0x74, + 0x45, 0x65, 0xba, 0x16, 0x50, 0xb8, 0xc9, 0x21, 0xfe, 0xe2, 0x77, 0x2a, 0x0c, 0xa8, 0xa1, 0xf1, + 0x23, 0xba, 0xa9, 0xc8, 0x78, 0x53, 0x11, 0xc0, 0x1d, 0x79, 0x5b, 0xbd, 0x0e, 0x15, 0x15, 0xe5, + 0x3a, 0x76, 0x46, 0xea, 0xbd, 0x61, 0x0a, 0x73, 0xdd, 0x77, 0x46, 0xea, 0xa2, 0xf3, 0x6d, 0x99, + 0xa6, 0x96, 0xc1, 0x8b, 0xce, 0xb4, 0x43, 0x6e, 0xfc, 0xbb, 0x0c, 0x2c, 0x6a, 0x53, 0x91, 0xe7, + 0xf6, 0x43, 0xa8, 0x46, 0x4f, 0x0b, 0xf2, 0x48, 0xf2, 0x5a, 0x4b, 0x32, 0x9a, 0xb8, 0x5a, 0x65, + 0x10, 0x41, 0x02, 0x31, 0x98, 0xa1, 0x7d, 0x8d, 0xe3, 0x0d, 0xa6, 0x63, 0xa5, 0xdc, 0x0c, 0xed, + 0xeb, 0x1d, 0xce, 0x7b, 0xd3, 0xb1, 0x50, 0x5d, 0x2f, 0x39, 0x7f, 0x1e, 0x21, 0x90, 0xcc, 0x05, + 0x02, 0x26, 0x31, 0x0c, 0xa8, 0x8d, 0x3d, 0x37, 0x3c, 0x8f, 0x50, 0xa4, 0xd4, 0x89, 0x40, 0xc2, + 0x31, 0xfe, 0x2c, 0x0b, 0x4b, 0x64, 0x62, 0x93, 0xa6, 0x4d, 0xc9, 0xba, 0x5a, 0xb0, 0x40, 0xd6, + 0x46, 0x62, 0x5e, 0xbb, 0xb7, 0x4c, 0xf9, 0xcd, 0xbe, 0xfd, 0x8a, 0x66, 0x41, 0x95, 0x09, 0x77, + 0xc3, 0xf2, 0xe7, 0xe6, 0x97, 0xff, 0xe6, 0xe5, 0x4d, 0xf3, 0xb8, 0x15, 0xd2, 0x3c, 0x6e, 0xaf, + 0xe2, 0xe7, 0x9a, 0x4b, 0x17, 0x2b, 0x4a, 0x1c, 0x2d, 0x5d, 0xec, 0x7d, 0x58, 0x4b, 0xe0, 0x20, + 0xb7, 0x76, 0x4e, 0x1d, 0xae, 0x9e, 0x0d, 0x58, 0xd6, 0xb0, 0x7b, 0xaa, 0x6c, 0xb3, 0x08, 0x85, + 0x60, 0xe0, 0x4d, 0xb8, 0xb1, 0x0a, 0xcb, 0xc9, 0x55, 0x95, 0xd7, 0xc4, 0xef, 0x67, 0xa0, 0x25, + 0xe3, 0x23, 0x1c, 0xf7, 0x6c, 0xd7, 0x09, 0x42, 0xcf, 0x8f, 0x9e, 0xe0, 0xbb, 0x0b, 0x10, 0x84, + 0xb6, 0x2f, 0xb5, 0x4d, 0x99, 0x28, 0x8f, 0x10, 0xd4, 0x24, 0x6f, 0x43, 0x89, 0xbb, 0x43, 0x2a, + 0x24, 0x6a, 0x28, 0x72, 0x77, 0xa8, 0xf4, 0xd0, 0x39, 0xf9, 0xbb, 0x96, 0x54, 0x2f, 0x64, 0xde, + 0xaa, 0x58, 0x1d, 0x7e, 0x81, 0x17, 0x6f, 0x3e, 0xca, 0x5b, 0xdd, 0xb7, 0xaf, 0x30, 0xda, 0x30, + 0x30, 0xfe, 0x7e, 0x16, 0x1a, 0xf1, 0xf8, 0x28, 0xe9, 0xfd, 0xc5, 0xe9, 0xfb, 0xf7, 0x25, 0x39, + 0x38, 0x42, 0x7e, 0xd7, 0x0c, 0x8f, 0x25, 0x3a, 0x9c, 0x5d, 0x97, 0x19, 0x50, 0x51, 0x18, 0xde, + 0x34, 0xd4, 0x5e, 0xc2, 0x2a, 0x13, 0xca, 0xe1, 0x34, 0x14, 0x0a, 0x97, 0xd0, 0x3c, 0x1d, 0x57, + 0xaa, 0x3c, 0x05, 0x7b, 0x1c, 0x76, 0xf1, 0x81, 0x6d, 0x01, 0x16, 0xd5, 0x68, 0x23, 0x05, 0x96, + 0xc0, 0x6f, 0x92, 0x9c, 0x4d, 0x3b, 0x87, 0x32, 0xb6, 0x2e, 0x84, 0xd2, 0x5b, 0xa3, 0x91, 0x10, + 0xfa, 0x3a, 0x54, 0xa8, 0xf1, 0x38, 0x3b, 0x30, 0x6f, 0x96, 0xb1, 0x07, 0x2c, 0x97, 0x46, 0x20, + 0x6f, 0x9a, 0x50, 0x7d, 0x81, 0xba, 0xc2, 0xf0, 0x83, 0xbf, 0x9d, 0x81, 0xdb, 0x29, 0xdb, 0x26, + 0x4f, 0xf9, 0x16, 0x2c, 0x9e, 0x46, 0x85, 0x6a, 0x75, 0xe9, 0xa8, 0xaf, 0x2a, 0xb6, 0x9a, 0x5c, + 0x53, 0xb3, 0x79, 0x9a, 0x04, 0xc4, 0x4a, 0x17, 0xed, 0x60, 0x22, 0x01, 0x14, 0x95, 0x2e, 0xda, + 0x46, 0xd2, 0x77, 0x8e, 0x60, 0xbd, 0x73, 0x25, 0x38, 0xc6, 0x96, 0xfe, 0x42, 0xbc, 0x22, 0xa3, + 0xa4, 0x81, 0x39, 0xf3, 0x4a, 0x06, 0xe6, 0x21, 0xe5, 0xb9, 0x45, 0x6d, 0xfd, 0x3c, 0x8d, 0xe0, + 0x05, 0x2a, 0xea, 0xd0, 0x0b, 0xf7, 0x2a, 0x09, 0x75, 0x10, 0xbd, 0x6c, 0x6f, 0x04, 0xd0, 0xd8, + 0x9f, 0x8e, 0x42, 0x27, 0x7e, 0xec, 0x9e, 0x7d, 0x5b, 0xd6, 0xc1, 0x7e, 0xd4, 0xaa, 0xa5, 0x76, + 0x04, 0x51, 0x47, 0xb8, 0x58, 0x63, 0xd1, 0x90, 0x35, 0xdf, 0x5f, 0x63, 0x9c, 0xec, 0xc1, 0xb8, + 0x0d, 0x6b, 0xf1, 0x17, 0x2d, 0x9b, 0xba, 0x6a, 0xfe, 0x69, 0x86, 0x42, 0x9b, 0x93, 0x0f, 0xef, + 0xb3, 0x0e, 0x2c, 0x05, 0x8e, 0x7b, 0x36, 0xe2, 0x7a, 0xf3, 0x81, 0x5c, 0x84, 0x95, 0xe4, 0xd8, + 0xe4, 0xe3, 0xfc, 0xe6, 0x22, 0xd5, 0x88, 0x5b, 0x0b, 0xd8, 0xe6, 0x4d, 0x83, 0x8c, 0xc9, 0x62, + 0x66, 0x35, 0xe6, 0x07, 0xdf, 0x85, 0x7a, 0xb2, 0x23, 0xf6, 0x1d, 0x99, 0xe3, 0x19, 0x8f, 0x2a, + 0x37, 0x93, 0xae, 0x17, 0x13, 0x44, 0x25, 0x5e, 0xfb, 0xc0, 0xf8, 0xbb, 0x19, 0x68, 0x99, 0x5c, + 0x50, 0xae, 0x36, 0x4a, 0x45, 0x33, 0x1f, 0xce, 0xb5, 0x7a, 0xf3, 0x5c, 0x55, 0xea, 0xa8, 0x1a, + 0xd1, 0x37, 0x6e, 0xdc, 0x8c, 0xdd, 0x5b, 0x73, 0x33, 0xda, 0x2c, 0xc1, 0x02, 0xa1, 0x18, 0x6b, + 0xb0, 0x22, 0xc7, 0xa3, 0xc6, 0x12, 0x7b, 0x0f, 0x13, 0x3d, 0x26, 0xbc, 0x87, 0xeb, 0xd0, 0xa2, + 0x97, 0x14, 0xf5, 0x49, 0xc8, 0x8a, 0xdb, 0xc0, 0xf6, 0xed, 0x81, 0xed, 0x7b, 0x9e, 0x7b, 0xc4, + 0x7d, 0x19, 0x28, 0x8a, 0x12, 0x26, 0x3a, 0xd7, 0x94, 0x28, 0x4c, 0x5f, 0xea, 0xfd, 0x3f, 0xcf, + 0x55, 0x71, 0x31, 0xf4, 0x65, 0x98, 0xb0, 0xb4, 0x69, 0x3f, 0xe7, 0xaa, 0x25, 0xb5, 0x44, 0x1f, + 0x41, 0x65, 0x12, 0x35, 0xaa, 0xd6, 0x5d, 0x25, 0x82, 0xcf, 0x77, 0x6b, 0xea, 0xd8, 0xc6, 0x13, + 0x58, 0x4e, 0xb6, 0x29, 0x59, 0xc7, 0x3a, 0x94, 0xc6, 0x12, 0x26, 0x47, 0x17, 0x7d, 0x1b, 0xbf, + 0x5b, 0x82, 0xa2, 0xd4, 0xe7, 0xd8, 0x06, 0xe4, 0x07, 0x2a, 0x36, 0x29, 0x7e, 0x5f, 0x44, 0x96, + 0xaa, 0xff, 0xb7, 0x30, 0x42, 0x49, 0xe0, 0xb1, 0x8f, 0xa0, 0x9e, 0xf4, 0x8a, 0xce, 0x64, 0x99, + 0x26, 0xdd, 0x99, 0xb5, 0xc1, 0x8c, 0xff, 0xab, 0x1c, 0x5f, 0x8e, 0x24, 0x33, 0x94, 0xce, 0xb5, + 0xdb, 0xd3, 0x73, 0x85, 0xbc, 0x1d, 0x9c, 0xdb, 0xd6, 0x93, 0xf7, 0x3f, 0x90, 0x69, 0xa6, 0x15, + 0x04, 0xf6, 0xce, 0xed, 0x27, 0xef, 0x7f, 0x30, 0x2b, 0x49, 0x53, 0xa6, 0xa1, 0x2e, 0x49, 0x2f, + 0x43, 0x81, 0x1e, 0xba, 0xa3, 0x20, 0x13, 0xfa, 0x60, 0x8f, 0x61, 0x59, 0xaa, 0xad, 0x96, 0x0c, + 0x07, 0x26, 0x2e, 0x58, 0xa2, 0xd4, 0x26, 0x59, 0xd6, 0xc3, 0x22, 0xb2, 0x0d, 0xad, 0xc2, 0xc2, + 0x79, 0xfc, 0x6a, 0x61, 0xcd, 0x94, 0x5f, 0xc6, 0x9f, 0x15, 0xa0, 0xa2, 0x2d, 0x0a, 0xab, 0x42, + 0xc9, 0xec, 0xf4, 0x3a, 0xe6, 0x27, 0x9d, 0xed, 0xe6, 0x2d, 0xf6, 0x00, 0xde, 0xea, 0x1e, 0x6c, + 0x1d, 0x9a, 0x66, 0x67, 0xab, 0x6f, 0x1d, 0x9a, 0x96, 0x7a, 0xe5, 0xe6, 0xa8, 0xfd, 0xd9, 0x7e, + 0xe7, 0xa0, 0x6f, 0x6d, 0x77, 0xfa, 0xed, 0xee, 0x5e, 0xaf, 0x99, 0x61, 0xaf, 0x41, 0x2b, 0xc6, + 0x54, 0xc5, 0xed, 0xfd, 0xc3, 0xe3, 0x83, 0x7e, 0x33, 0xcb, 0xee, 0xc1, 0x9d, 0x9d, 0xee, 0x41, + 0x7b, 0xcf, 0x8a, 0x71, 0xb6, 0xf6, 0xfa, 0x9f, 0x58, 0x9d, 0x5f, 0x3f, 0xea, 0x9a, 0x9f, 0x35, + 0x73, 0x69, 0x08, 0x42, 0x19, 0x57, 0x2d, 0xe4, 0xd9, 0x6d, 0x58, 0x21, 0x04, 0xaa, 0x62, 0xf5, + 0x0f, 0x0f, 0xad, 0xde, 0xe1, 0xe1, 0x41, 0xb3, 0xc0, 0x16, 0xa1, 0xd6, 0x3d, 0xf8, 0xa4, 0xbd, + 0xd7, 0xdd, 0xb6, 0xcc, 0x4e, 0x7b, 0x6f, 0xbf, 0xb9, 0xc0, 0x96, 0xa0, 0x31, 0x8b, 0x57, 0x14, + 0x4d, 0x28, 0xbc, 0xc3, 0x83, 0xee, 0xe1, 0x81, 0xf5, 0x49, 0xc7, 0xec, 0x75, 0x0f, 0x0f, 0x9a, + 0x25, 0xb6, 0x0a, 0x2c, 0x59, 0xb4, 0xbb, 0xdf, 0xde, 0x6a, 0x96, 0xd9, 0x0a, 0x2c, 0x26, 0xe1, + 0xcf, 0x3a, 0x9f, 0x35, 0x81, 0xb5, 0x60, 0x99, 0x06, 0x66, 0x6d, 0x76, 0xf6, 0x0e, 0x3f, 0xb5, + 0xf6, 0xbb, 0x07, 0xdd, 0xfd, 0xe3, 0xfd, 0x66, 0x05, 0xdf, 0xdd, 0xea, 0x74, 0xac, 0xee, 0x41, + 0xef, 0x78, 0x67, 0xa7, 0xbb, 0xd5, 0xed, 0x1c, 0xf4, 0x9b, 0x55, 0xea, 0x39, 0x6d, 0xe2, 0x35, + 0x51, 0x41, 0xe6, 0x0c, 0x58, 0xdb, 0xdd, 0x5e, 0x7b, 0x73, 0xaf, 0xb3, 0xdd, 0xac, 0xb3, 0xbb, + 0x70, 0xbb, 0xdf, 0xd9, 0x3f, 0x3a, 0x34, 0xdb, 0xe6, 0x67, 0x2a, 0xa7, 0xc0, 0xda, 0x69, 0x77, + 0xf7, 0x8e, 0xcd, 0x4e, 0xb3, 0xc1, 0xde, 0x80, 0xbb, 0x66, 0xe7, 0xe3, 0xe3, 0xae, 0xd9, 0xd9, + 0xb6, 0x0e, 0x0e, 0xb7, 0x3b, 0xd6, 0x4e, 0xa7, 0xdd, 0x3f, 0x36, 0x3b, 0xd6, 0x7e, 0xb7, 0xd7, + 0xeb, 0x1e, 0x3c, 0x6d, 0x36, 0xd9, 0x5b, 0x70, 0x3f, 0x42, 0x89, 0x1a, 0x98, 0xc1, 0x5a, 0x14, + 0xf3, 0x53, 0x5b, 0x7a, 0xd0, 0xf9, 0xf5, 0xbe, 0x75, 0xd4, 0xe9, 0x98, 0x4d, 0xc6, 0xd6, 0x61, + 0x35, 0xee, 0x9e, 0x3a, 0x90, 0x7d, 0x2f, 0x89, 0xb2, 0xa3, 0x8e, 0xb9, 0xdf, 0x3e, 0x10, 0x1b, + 0x9c, 0x28, 0x5b, 0x16, 0xc3, 0x8e, 0xcb, 0x66, 0x87, 0xbd, 0xc2, 0x18, 0xd4, 0xb5, 0x5d, 0xd9, + 0x69, 0x9b, 0xcd, 0x55, 0xd6, 0x80, 0xca, 0xfe, 0xd1, 0x91, 0xd5, 0xef, 0xee, 0x77, 0x0e, 0x8f, + 0xfb, 0xcd, 0x35, 0xb6, 0x02, 0xcd, 0xee, 0x41, 0xbf, 0x63, 0x8a, 0xbd, 0x56, 0x55, 0xff, 0x67, + 0x91, 0x2d, 0x43, 0x43, 0x8d, 0x54, 0x41, 0x7f, 0x56, 0x64, 0x6b, 0xc0, 0x8e, 0x0f, 0xcc, 0x4e, + 0x7b, 0x5b, 0x2c, 0x5c, 0x54, 0xf0, 0xbf, 0x8a, 0xd2, 0x43, 0xf2, 0xd3, 0x5c, 0x74, 0x59, 0xc7, + 0x21, 0x07, 0xc9, 0x37, 0x6c, 0xab, 0xda, 0xdb, 0xb3, 0x2f, 0x7b, 0x5d, 0x5e, 0x53, 0xad, 0x72, + 0x73, 0xaa, 0xd5, 0x9c, 0xee, 0x5e, 0xd3, 0x65, 0xbf, 0x37, 0xa1, 0x36, 0xa6, 0xf7, 0x6c, 0xe5, + 0xbb, 0x95, 0x20, 0xe3, 0x6f, 0x08, 0x48, 0x8f, 0x56, 0xce, 0x3d, 0xaf, 0x5e, 0x98, 0x7f, 0x5e, + 0x3d, 0x4d, 0xbe, 0x5f, 0x48, 0x93, 0xef, 0x1f, 0xc2, 0x22, 0xb1, 0x26, 0xc7, 0x75, 0xc6, 0x4a, + 0x6b, 0x26, 0x29, 0xb0, 0x81, 0x2c, 0x8a, 0xe0, 0x4a, 0x9d, 0x50, 0x2a, 0x87, 0x64, 0x21, 0x45, + 0xa9, 0x6d, 0x24, 0x34, 0x0d, 0xe2, 0x1c, 0x91, 0xa6, 0x11, 0xf5, 0x60, 0x5f, 0xc5, 0x3d, 0x54, + 0xb4, 0x1e, 0x08, 0x8e, 0x3d, 0x3c, 0x84, 0x45, 0x7e, 0x15, 0xfa, 0xb6, 0xe5, 0x4d, 0xec, 0xcf, + 0xa7, 0xe8, 0xc2, 0xb5, 0x51, 0x87, 0xaf, 0x9a, 0x0d, 0x2c, 0x38, 0x44, 0xf8, 0xb6, 0x1d, 0xda, + 0x0f, 0xbf, 0x80, 0x8a, 0xf6, 0xd6, 0x31, 0x5b, 0x83, 0xa5, 0x4f, 0xbb, 0xfd, 0x83, 0x4e, 0xaf, + 0x67, 0x1d, 0x1d, 0x6f, 0x3e, 0xeb, 0x7c, 0x66, 0xed, 0xb6, 0x7b, 0xbb, 0xcd, 0x5b, 0xe2, 0xd0, + 0x1e, 0x74, 0x7a, 0xfd, 0xce, 0x76, 0x02, 0x9e, 0x61, 0xaf, 0xc3, 0xfa, 0xf1, 0xc1, 0x71, 0xaf, + 0xb3, 0x6d, 0xa5, 0xd5, 0xcb, 0x0a, 0x2a, 0x95, 0xe5, 0x29, 0xd5, 0x73, 0x0f, 0xbf, 0x0f, 0xf5, + 0xe4, 0x03, 0x9c, 0x0c, 0x60, 0x61, 0xaf, 0xf3, 0xb4, 0xbd, 0xf5, 0x19, 0xbd, 0xcc, 0xd7, 0xeb, + 0xb7, 0xfb, 0xdd, 0x2d, 0x4b, 0xbe, 0xc4, 0x27, 0x38, 0x42, 0x86, 0x55, 0xa0, 0xd8, 0x3e, 0xd8, + 0xda, 0x3d, 0x34, 0x7b, 0xcd, 0xec, 0xc3, 0x8f, 0xa0, 0x39, 0xeb, 0x8f, 0x4a, 0x38, 0xf0, 0x5e, + 0xe4, 0xe9, 0x7b, 0xf8, 0x2f, 0x73, 0x00, 0x71, 0xc2, 0x80, 0x60, 0x35, 0xdb, 0xed, 0x7e, 0x7b, + 0xef, 0x50, 0x4c, 0xc3, 0x3c, 0xec, 0x0b, 0x0e, 0x62, 0x76, 0x3e, 0x6e, 0xde, 0x4a, 0x2d, 0x39, + 0x3c, 0xea, 0x37, 0x33, 0x62, 0xc5, 0xba, 0x07, 0xdd, 0x7e, 0xb7, 0xbd, 0x67, 0x99, 0x87, 0xc7, + 0xdd, 0x83, 0xa7, 0xf4, 0xe4, 0x18, 0x72, 0xd9, 0xe3, 0xa3, 0x1d, 0xf3, 0xf0, 0xa0, 0x6f, 0xf5, + 0x76, 0x8f, 0xfb, 0xdb, 0xf8, 0x60, 0xd9, 0x96, 0xd9, 0x3d, 0xa2, 0x36, 0xf3, 0x2f, 0x42, 0x10, + 0x4d, 0x17, 0xc4, 0x9a, 0x3f, 0x3d, 0xec, 0xf5, 0xba, 0x47, 0xd6, 0xc7, 0xc7, 0x1d, 0xb3, 0xdb, + 0xe9, 0x61, 0xc5, 0x85, 0x14, 0xb8, 0xc0, 0x2f, 0x0a, 0xde, 0xdc, 0xdf, 0xfb, 0x44, 0x32, 0x4f, + 0x81, 0x5a, 0x4a, 0x82, 0x04, 0x56, 0x59, 0xf0, 0x14, 0xc1, 0x7d, 0x52, 0x5a, 0x86, 0x1b, 0xca, + 0x44, 0xbd, 0x8a, 0xe0, 0xab, 0x73, 0x9b, 0x81, 0xd5, 0xaa, 0xe9, 0x45, 0xa2, 0x16, 0xb2, 0xdc, + 0xe8, 0x82, 0xda, 0xde, 0x36, 0xb1, 0x42, 0x7d, 0x0e, 0x2a, 0x70, 0x1b, 0x62, 0xa3, 0x04, 0x7b, + 0x12, 0x28, 0x4d, 0xf5, 0x21, 0x4a, 0x16, 0x9f, 0xfc, 0x4e, 0x0e, 0xea, 0x94, 0xbc, 0x45, 0x3f, + 0x35, 0xc5, 0x7d, 0xb6, 0x0f, 0x45, 0xf9, 0x9b, 0x65, 0x6c, 0x25, 0x7a, 0x0d, 0x4a, 0xff, 0x95, + 0xb4, 0xf5, 0xd5, 0x59, 0xb0, 0x14, 0xc7, 0x96, 0xfe, 0xda, 0x9f, 0xfe, 0x8f, 0xbf, 0x97, 0xad, + 0xb1, 0xca, 0xa3, 0x8b, 0xf7, 0x1e, 0x9d, 0x71, 0x37, 0x10, 0x6d, 0xfc, 0xff, 0x00, 0xf1, 0x2f, + 0x71, 0xb1, 0x56, 0xe4, 0x84, 0x9a, 0xf9, 0x99, 0xb2, 0xf5, 0xdb, 0x29, 0x25, 0xb2, 0xdd, 0xdb, + 0xd8, 0xee, 0x92, 0x51, 0x17, 0xed, 0x3a, 0xae, 0x13, 0xd2, 0xaf, 0x72, 0x7d, 0x98, 0x79, 0xc8, + 0x86, 0x50, 0xd5, 0x7f, 0x23, 0x8b, 0x29, 0x49, 0x29, 0xe5, 0x57, 0xbe, 0xd6, 0xef, 0xa4, 0x96, + 0x29, 0x19, 0x14, 0xfb, 0x58, 0x31, 0x9a, 0xa2, 0x8f, 0x29, 0x62, 0xc4, 0xbd, 0x8c, 0x48, 0x2a, + 0x8f, 0x7f, 0x0a, 0x8b, 0xbd, 0xa6, 0xc9, 0x55, 0x73, 0x3f, 0xc4, 0xb5, 0x7e, 0xf7, 0x86, 0x52, + 0xd9, 0xd7, 0x5d, 0xec, 0x6b, 0xcd, 0x60, 0xa2, 0xaf, 0x01, 0xe2, 0xa8, 0x1f, 0xe2, 0xfa, 0x30, + 0xf3, 0xf0, 0xc9, 0x5f, 0x3e, 0x80, 0x72, 0x14, 0xcc, 0xc9, 0x7e, 0x0b, 0x6a, 0x89, 0xec, 0x3a, + 0xa6, 0xa6, 0x91, 0x96, 0x8c, 0xb7, 0xfe, 0x5a, 0x7a, 0xa1, 0xec, 0xf8, 0x75, 0xec, 0xb8, 0xc5, + 0x56, 0x45, 0xc7, 0x32, 0x7b, 0xed, 0x11, 0x66, 0xc3, 0xd2, 0xdb, 0x5a, 0xcf, 0x35, 0xed, 0x83, + 0x3a, 0x7b, 0x6d, 0x56, 0x23, 0x48, 0xf4, 0x76, 0xf7, 0x86, 0x52, 0xd9, 0xdd, 0x6b, 0xd8, 0xdd, + 0x2a, 0x5b, 0xd6, 0xbb, 0x53, 0xa1, 0x97, 0x8c, 0xe3, 0x7b, 0x76, 0xfa, 0x2f, 0x45, 0xb1, 0xbb, + 0xf1, 0xeb, 0x63, 0x29, 0xbf, 0x20, 0x15, 0x91, 0xc8, 0xfc, 0xcf, 0x48, 0x19, 0x2d, 0xec, 0x8a, + 0x31, 0xdc, 0x3e, 0xfd, 0x87, 0xa2, 0xd8, 0x09, 0x54, 0xb4, 0x1f, 0x57, 0x60, 0xb7, 0x6f, 0xfc, + 0x21, 0x88, 0xf5, 0xf5, 0xb4, 0xa2, 0xb4, 0xa9, 0xe8, 0xed, 0x3f, 0x3a, 0xe5, 0x9c, 0xfd, 0x06, + 0x94, 0xa3, 0x27, 0xfb, 0xd9, 0x9a, 0xf6, 0x13, 0x0a, 0xfa, 0x4f, 0x0c, 0xac, 0xb7, 0xe6, 0x0b, + 0xd2, 0x88, 0x4f, 0x6f, 0x5d, 0x10, 0xdf, 0xa7, 0x50, 0xd1, 0x9e, 0xe5, 0x8f, 0x26, 0x30, 0xff, + 0xf4, 0x7f, 0x34, 0x81, 0x94, 0x57, 0xfc, 0x8d, 0x45, 0xec, 0xa2, 0xc2, 0xca, 0x48, 0xdf, 0xe1, + 0x95, 0x17, 0xb0, 0x3d, 0x58, 0x91, 0x9a, 0xd6, 0x09, 0xff, 0x32, 0xdb, 0x90, 0xf2, 0xe3, 0x5c, + 0x8f, 0x33, 0xec, 0x23, 0x28, 0xa9, 0x5f, 0x5f, 0x60, 0xab, 0xe9, 0xbf, 0x22, 0xb1, 0xbe, 0x36, + 0x07, 0x97, 0x6a, 0xd1, 0x67, 0x00, 0xf1, 0x6f, 0x00, 0x44, 0x4c, 0x62, 0xee, 0x37, 0x05, 0x22, + 0x0a, 0x98, 0xff, 0xc1, 0x00, 0x63, 0x15, 0x27, 0xd8, 0x64, 0xc8, 0x24, 0x5c, 0x7e, 0xa9, 0x1e, + 0x1d, 0xfd, 0x11, 0x54, 0xb4, 0x9f, 0x01, 0x88, 0x96, 0x6f, 0xfe, 0x27, 0x04, 0xa2, 0xe5, 0x4b, + 0xf9, 0xd5, 0x00, 0x63, 0x1d, 0x5b, 0x5f, 0x36, 0x1a, 0xa2, 0x75, 0x21, 0x6a, 0x49, 0x91, 0x47, + 0x6c, 0xd0, 0x39, 0xd4, 0x12, 0x6f, 0xfd, 0x47, 0x27, 0x34, 0xed, 0x97, 0x04, 0xa2, 0x13, 0x9a, + 0xfa, 0xf3, 0x00, 0x8a, 0xce, 0x8c, 0x45, 0xd1, 0xcf, 0x05, 0xa2, 0x68, 0x3d, 0xfd, 0x10, 0x2a, + 0xda, 0xbb, 0xfd, 0xd1, 0x5c, 0xe6, 0x7f, 0x22, 0x20, 0x9a, 0x4b, 0xda, 0x33, 0xff, 0xcb, 0xd8, + 0x47, 0xdd, 0x40, 0x52, 0xc0, 0x67, 0x13, 0x45, 0xdb, 0xbf, 0x05, 0xf5, 0xe4, 0x53, 0xfe, 0xd1, + 0xd9, 0x4f, 0xfd, 0x4d, 0x80, 0xe8, 0xec, 0xdf, 0xf0, 0xfe, 0xbf, 0x24, 0xe9, 0x87, 0x4b, 0x51, + 0x27, 0x8f, 0x7e, 0x22, 0xd3, 0x52, 0xbe, 0x60, 0x1f, 0x0b, 0x06, 0x27, 0x5f, 0xed, 0x64, 0x6b, + 0x1a, 0xd5, 0xea, 0xcf, 0x7f, 0x46, 0xe7, 0x65, 0xee, 0x81, 0xcf, 0x24, 0x31, 0x63, 0xe3, 0xec, + 0x29, 0x2c, 0x45, 0xc4, 0x1c, 0x3d, 0xc3, 0x19, 0x44, 0x73, 0x48, 0x7d, 0xec, 0x73, 0xbd, 0x39, + 0x5b, 0xfa, 0x38, 0x43, 0xd7, 0x1f, 0x3e, 0x7e, 0xa8, 0x5d, 0x7f, 0xfa, 0x4b, 0x9c, 0xda, 0xf5, + 0x97, 0x78, 0x23, 0x71, 0xf6, 0xfa, 0x0b, 0x1d, 0xd1, 0x86, 0x0b, 0x8d, 0xd9, 0x47, 0x31, 0xef, + 0xde, 0x94, 0xf6, 0x4f, 0xcd, 0xbf, 0xfe, 0xe2, 0x57, 0x01, 0x92, 0xac, 0x48, 0x71, 0xd3, 0x47, + 0x32, 0xf8, 0x84, 0xfd, 0x26, 0x54, 0xf5, 0xf7, 0xc1, 0x99, 0xce, 0x13, 0x66, 0x7b, 0xba, 0x93, + 0x5a, 0x96, 0xa4, 0x12, 0x56, 0xd5, 0xbb, 0x61, 0x9f, 0xc0, 0x6a, 0xb4, 0xcc, 0x7a, 0xde, 0x7a, + 0xc0, 0xee, 0xa5, 0x64, 0xb3, 0x27, 0x16, 0xfb, 0xf6, 0x8d, 0xe9, 0xee, 0x8f, 0x33, 0x82, 0xfa, + 0x92, 0x0f, 0x15, 0xc7, 0x37, 0x4f, 0xda, 0xfb, 0xcc, 0xf1, 0xcd, 0x93, 0xfa, 0xba, 0xb1, 0xa2, + 0x3e, 0xb6, 0x94, 0x58, 0x23, 0x0a, 0xcb, 0x65, 0x3f, 0x84, 0x86, 0x96, 0x94, 0xdf, 0xbb, 0x76, + 0x07, 0xd1, 0x49, 0x9a, 0x7f, 0x69, 0x6f, 0x3d, 0xcd, 0x36, 0x69, 0xac, 0x61, 0xfb, 0x8b, 0x46, + 0x62, 0x71, 0xc4, 0x29, 0xda, 0x82, 0x8a, 0x9e, 0xf0, 0xff, 0x82, 0x76, 0xd7, 0xb4, 0x22, 0xfd, + 0x51, 0xb7, 0xc7, 0x19, 0xb6, 0x07, 0xcd, 0xd9, 0x37, 0xa8, 0x22, 0x9e, 0x92, 0xf6, 0x6e, 0xd6, + 0xfa, 0x4c, 0x61, 0xe2, 0xe5, 0x2a, 0x76, 0x44, 0x89, 0x1d, 0xd1, 0x2f, 0x59, 0x79, 0xfe, 0xec, + 0xad, 0x9e, 0xfc, 0x85, 0xab, 0xa8, 0xb5, 0xb4, 0xdf, 0x36, 0x7b, 0x90, 0x79, 0x9c, 0x61, 0xbf, + 0x97, 0x81, 0x6a, 0xe2, 0xdd, 0x97, 0x44, 0xe8, 0xfc, 0xcc, 0x3c, 0x5b, 0x7a, 0x99, 0x3e, 0x51, + 0xc3, 0xc4, 0x45, 0xdc, 0x7b, 0xf8, 0x83, 0xc4, 0x26, 0xfd, 0x24, 0xe1, 0xda, 0xdb, 0x98, 0xfd, + 0xa9, 0xab, 0x2f, 0x66, 0x11, 0xf4, 0x07, 0x14, 0xbf, 0x78, 0x9c, 0x61, 0xff, 0x3a, 0x03, 0xf5, + 0xa4, 0xcf, 0x3e, 0x9a, 0x6e, 0x6a, 0x74, 0x40, 0x44, 0x4a, 0x37, 0x38, 0xfa, 0x7f, 0x88, 0xa3, + 0xec, 0x3f, 0x34, 0x13, 0xa3, 0x94, 0x4f, 0x6c, 0xff, 0x62, 0xa3, 0x65, 0x1f, 0xd2, 0x2f, 0x4b, + 0xaa, 0x50, 0x26, 0x36, 0xff, 0x4b, 0x84, 0x11, 0xf9, 0xe9, 0xbf, 0xdb, 0x87, 0x9b, 0xf0, 0x23, + 0xfa, 0x49, 0x27, 0x15, 0x19, 0x23, 0xa8, 0xf8, 0x55, 0xeb, 0x1b, 0x6f, 0xe1, 0x9c, 0x5e, 0x37, + 0x6e, 0x27, 0xe6, 0x34, 0x2b, 0x78, 0xb4, 0x69, 0x74, 0xf2, 0x67, 0xf7, 0xe2, 0x9b, 0x73, 0xee, + 0xa7, 0xf8, 0x6e, 0x1e, 0xe4, 0x98, 0x06, 0x29, 0xd1, 0x13, 0x47, 0xed, 0x15, 0x9b, 0x31, 0x1e, + 0xe2, 0x58, 0xdf, 0x32, 0xee, 0xdd, 0x38, 0xd6, 0x47, 0xe8, 0x7f, 0x17, 0x23, 0x3e, 0x02, 0x88, + 0x43, 0x0d, 0xd9, 0x4c, 0xc0, 0x5b, 0xc4, 0x80, 0xe6, 0xa3, 0x11, 0x93, 0xe7, 0x59, 0xc5, 0xc5, + 0x89, 0x16, 0x7f, 0x83, 0xd8, 0x69, 0x14, 0x8a, 0xa7, 0x4b, 0x5f, 0xc9, 0xa8, 0xc0, 0x84, 0xf4, + 0x35, 0xdb, 0x7e, 0x82, 0x99, 0x46, 0x71, 0x77, 0xc7, 0x50, 0xdb, 0xf3, 0xbc, 0xe7, 0xd3, 0x49, + 0x14, 0xde, 0x9e, 0x0c, 0x8a, 0xd9, 0xb5, 0x83, 0xf3, 0xf5, 0x99, 0x59, 0x18, 0xf7, 0xb1, 0xa9, + 0x75, 0xd6, 0xd2, 0x9a, 0x7a, 0xf4, 0x93, 0x38, 0xbe, 0xf1, 0x0b, 0x66, 0xc3, 0x62, 0xc4, 0xa3, + 0xe3, 0x18, 0xc2, 0x64, 0x33, 0x09, 0xce, 0x3c, 0xdb, 0x45, 0x42, 0x4d, 0x50, 0xa3, 0x7d, 0x14, + 0xa8, 0x36, 0x1f, 0x67, 0xd8, 0x11, 0x54, 0xb7, 0xf9, 0x00, 0x13, 0xf5, 0x31, 0xb4, 0x64, 0x29, + 0x11, 0xa6, 0x40, 0x31, 0x29, 0xeb, 0xb5, 0x04, 0x30, 0x79, 0x6f, 0x4d, 0xec, 0x6b, 0x9f, 0x7f, + 0xfe, 0xe8, 0x27, 0x32, 0x68, 0xe5, 0x0b, 0x75, 0x6f, 0xa9, 0xa0, 0x9e, 0xc4, 0xbd, 0x35, 0x13, + 0x05, 0x94, 0xb8, 0xb7, 0xe6, 0xa2, 0x80, 0x12, 0x4b, 0xad, 0x82, 0x8a, 0xd8, 0x08, 0x16, 0xe7, + 0x02, 0x87, 0xa2, 0x2b, 0xeb, 0xa6, 0x70, 0xa3, 0xf5, 0xfb, 0x37, 0x23, 0x24, 0x7b, 0x7b, 0x98, + 0xec, 0xad, 0x07, 0x35, 0x7a, 0xd3, 0xf1, 0x84, 0x53, 0xca, 0xde, 0xcc, 0x7b, 0x37, 0x7a, 0x3e, + 0xe0, 0xec, 0x05, 0x83, 0x65, 0x49, 0x09, 0x07, 0x73, 0xe5, 0xd8, 0x6f, 0x40, 0xe5, 0x29, 0x0f, + 0x55, 0x8e, 0x5e, 0x24, 0x63, 0xcf, 0x24, 0xed, 0xad, 0xa7, 0xa4, 0xf8, 0x25, 0x69, 0x06, 0x5b, + 0x7b, 0xc4, 0x87, 0x67, 0x9c, 0x98, 0x93, 0xe5, 0x0c, 0xbf, 0x60, 0xbf, 0x8e, 0x8d, 0x47, 0xa9, + 0xd1, 0xab, 0x5a, 0x12, 0x96, 0xde, 0x78, 0x63, 0x06, 0x9e, 0xd6, 0xb2, 0xeb, 0x0d, 0xb9, 0x26, + 0xeb, 0xb9, 0x50, 0xd1, 0x9e, 0x50, 0x88, 0x0e, 0xd0, 0xfc, 0x93, 0x19, 0xd1, 0x01, 0x4a, 0x79, + 0x71, 0xc1, 0x78, 0x80, 0xfd, 0x18, 0xec, 0x7e, 0xdc, 0x0f, 0xbd, 0xb2, 0x10, 0xf7, 0xf4, 0xe8, + 0x27, 0xf6, 0x38, 0xfc, 0x82, 0x7d, 0x8a, 0x2f, 0xa7, 0xeb, 0x39, 0x88, 0xb1, 0xd2, 0x30, 0x9b, + 0xae, 0x18, 0x2d, 0x96, 0x56, 0x94, 0x54, 0x24, 0xa8, 0x2b, 0x94, 0xe4, 0xde, 0x07, 0xe8, 0x85, + 0xde, 0x64, 0xdb, 0xe6, 0x63, 0xcf, 0x8d, 0x79, 0x6d, 0x9c, 0x15, 0x17, 0xf3, 0x2f, 0x2d, 0x35, + 0x8e, 0x7d, 0xaa, 0x69, 0x59, 0x89, 0x34, 0x4e, 0x45, 0x5c, 0x37, 0x26, 0xce, 0x45, 0x0b, 0x92, + 0x92, 0x3c, 0xf7, 0x38, 0xc3, 0xda, 0x00, 0x71, 0xe4, 0x58, 0xa4, 0x33, 0xcd, 0x05, 0xa5, 0x45, + 0x6c, 0x2f, 0x25, 0xcc, 0xec, 0x08, 0xca, 0x71, 0xc8, 0xcd, 0x5a, 0xfc, 0x22, 0x4c, 0x22, 0x40, + 0x27, 0xba, 0xc1, 0xe7, 0xc2, 0x5d, 0x8c, 0x26, 0x2e, 0x15, 0xb0, 0x92, 0x58, 0xaa, 0x53, 0xce, + 0x03, 0xe6, 0xc0, 0x12, 0x0d, 0x30, 0x12, 0x97, 0x30, 0x9b, 0x2b, 0x7a, 0x20, 0x7f, 0x3e, 0xf2, + 0x24, 0x3a, 0xcd, 0xa9, 0xf1, 0x13, 0x09, 0xd3, 0x8f, 0xa0, 0x56, 0xca, 0x24, 0x13, 0xac, 0x79, + 0x0c, 0x8b, 0x73, 0x2e, 0xfa, 0xe8, 0x48, 0xdf, 0x14, 0x73, 0x11, 0x1d, 0xe9, 0x1b, 0xbd, 0xfb, + 0xc6, 0x0a, 0x76, 0xd9, 0x30, 0x00, 0x55, 0xbd, 0x4b, 0x27, 0x1c, 0x9c, 0x8b, 0xee, 0xfe, 0x45, + 0x06, 0x96, 0x52, 0x9c, 0xf0, 0xec, 0x0d, 0x65, 0x35, 0xb8, 0xd1, 0x41, 0xbf, 0x9e, 0xea, 0xac, + 0x35, 0x7a, 0xd8, 0xcf, 0x3e, 0x7b, 0x96, 0xb8, 0xd8, 0xc8, 0x57, 0x2a, 0x4f, 0xe6, 0x0b, 0x85, + 0x8a, 0x54, 0x89, 0xe2, 0x73, 0x58, 0xa3, 0x81, 0xb4, 0x47, 0xa3, 0x19, 0x47, 0xf2, 0xeb, 0x73, + 0xbf, 0x3c, 0x9f, 0x70, 0x8e, 0xaf, 0xdf, 0xfc, 0xcb, 0xf4, 0x37, 0x88, 0xd3, 0x34, 0x54, 0x36, + 0x85, 0xe6, 0xac, 0x83, 0x96, 0xdd, 0xdc, 0xd6, 0xfa, 0xbd, 0x84, 0xfe, 0x9b, 0xe2, 0xd4, 0xfd, + 0x1a, 0x76, 0x76, 0xcf, 0x58, 0x4f, 0x5b, 0x17, 0x52, 0x89, 0xc5, 0x7e, 0xfc, 0xd5, 0xc8, 0x9b, + 0x3c, 0x33, 0x4f, 0xd5, 0xc1, 0x4d, 0xbe, 0xef, 0x48, 0x03, 0x4f, 0x77, 0x46, 0xbf, 0x8d, 0xdd, + 0xdf, 0x37, 0xee, 0xa4, 0x75, 0xef, 0x53, 0x15, 0xd2, 0xc5, 0xd7, 0x66, 0xcf, 0xb5, 0x1a, 0xc1, + 0xfd, 0xb4, 0xfd, 0xbe, 0x51, 0x17, 0x9a, 0x59, 0xeb, 0x5b, 0x28, 0xdb, 0x55, 0x75, 0xef, 0x71, + 0x74, 0x7c, 0x52, 0xdc, 0xd4, 0xd1, 0xf1, 0x49, 0x73, 0x37, 0x27, 0xe5, 0x1a, 0xe5, 0x68, 0xfe, + 0x30, 0xf3, 0x70, 0xf3, 0x9d, 0x1f, 0x7e, 0xed, 0xcc, 0x09, 0xcf, 0xa7, 0x27, 0x1b, 0x03, 0x6f, + 0xfc, 0x68, 0xa4, 0xac, 0x8d, 0x32, 0xe5, 0xf9, 0xd1, 0xc8, 0x1d, 0x3e, 0xc2, 0x66, 0x4f, 0x16, + 0x26, 0xbe, 0x17, 0x7a, 0xdf, 0xfa, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc3, 0xc3, 0x75, 0xd6, + 0x5c, 0x83, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index fe5fb29f75..4d660a82b9 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1428,6 +1428,15 @@ message Channel { cooperatively closing with the delivery_address field set. */ string close_address = 25; + + /* + The amount that the initiator of the channel optionally pushed to the remote + party on channel open. This amount will be zero if the channel initiator did + not push any funds to the remote peer. If the initiator field is true, we + pushed this amount to our peer, if it is false, the remote peer pushed this + amount to us. + */ + uint64 push_amount_sat = 27; } message ListChannelsRequest { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 64b693abad..6d96ac69bd 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1997,6 +1997,11 @@ "close_address": { "type": "string", "description": "*\nClose address is the address that we will enforce payout to on cooperative\nclose if the channel was opened utilizing option upfront shutdown. This\nvalue can be set on channel open by setting close_address in an open channel\nrequest. If this value is not set, you can still choose a payout address by\ncooperatively closing with the delivery_address field set." + }, + "push_amount_sat": { + "type": "string", + "format": "uint64", + "description": "The amount that the initiator of the channel optionally pushed to the remote\nparty on channel open. This amount will be zero if the channel initiator did\nnot push any funds to the remote peer. If the initiator field is true, we\npushed this amount to our peer, if it is false, the remote peer pushed this\namount to us." } } }, diff --git a/rpcserver.go b/rpcserver.go index 433491002a..baf7c05720 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3195,6 +3195,23 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, channel.UnsettledBalance += channel.PendingHtlcs[i].Amount } + // Lookup our balances at height 0, because they will reflect any + // push amounts that may have been present when this channel was + // created. + localBalance, remoteBalance, err := dbChannel.BalancesAtHeight(0) + if err != nil { + return nil, err + } + + // If we initiated opening the channel, the zero height remote balance + // is the push amount. Otherwise, our starting balance is the push + // amount. If there is no push amount, these values will simply be zero. + if dbChannel.IsInitiator { + channel.PushAmountSat = uint64(remoteBalance.ToSatoshis()) + } else { + channel.PushAmountSat = uint64(localBalance.ToSatoshis()) + } + outpoint := dbChannel.FundingOutpoint // Get the lifespan observed by the channel event store. If the channel is From 5c2fc4a2d6ba61ab79ac46930f3dd2c71b7962de Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 19 Mar 2020 13:43:39 -0700 Subject: [PATCH 263/562] discovery/gossiper: use netann pkg for signing channel updates --- discovery/gossiper.go | 37 ++++++++----------------------------- netann/channel_update.go | 18 +++++++++++++----- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 338558e755..bbc1ebd1bc 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -2462,32 +2462,14 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo, edge *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, *lnwire.ChannelUpdate, error) { - // Make sure timestamp is always increased, such that our update gets - // propagated. - timestamp := time.Now().Unix() - if timestamp <= edge.LastUpdate.Unix() { - timestamp = edge.LastUpdate.Unix() + 1 - } - edge.LastUpdate = time.Unix(timestamp, 0) - - chanUpdate := &lnwire.ChannelUpdate{ - ChainHash: info.ChainHash, - ShortChannelID: lnwire.NewShortChanIDFromInt(edge.ChannelID), - Timestamp: uint32(timestamp), - MessageFlags: edge.MessageFlags, - ChannelFlags: edge.ChannelFlags, - TimeLockDelta: edge.TimeLockDelta, - HtlcMinimumMsat: edge.MinHTLC, - HtlcMaximumMsat: edge.MaxHTLC, - BaseFee: uint32(edge.FeeBaseMSat), - FeeRate: uint32(edge.FeeProportionalMillionths), - ExtraOpaqueData: edge.ExtraOpaqueData, - } + // Parse the unsigned edge into a channel update. + chanUpdate := netann.UnsignedChannelUpdateFromEdge(info, edge) - // With the update applied, we'll generate a new signature over a - // digest of the channel announcement itself. - sig, err := netann.SignAnnouncement( + // We'll generate a new signature over a digest of the channel + // announcement itself and update the timestamp to ensure it propagate. + err := netann.SignChannelUpdate( d.cfg.AnnSigner, d.selfKey, chanUpdate, + netann.ChanUpdSetTimestamp, ) if err != nil { return nil, nil, err @@ -2495,11 +2477,8 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo, // Next, we'll set the new signature in place, and update the reference // in the backing slice. - edge.SetSigBytes(sig.Serialize()) - chanUpdate.Signature, err = lnwire.NewSigFromSignature(sig) - if err != nil { - return nil, nil, err - } + edge.LastUpdate = time.Unix(int64(chanUpdate.Timestamp), 0) + edge.SigBytes = chanUpdate.Signature.ToSignatureBytes() // To ensure that our signature is valid, we'll verify it ourself // before committing it to the slice returned. diff --git a/netann/channel_update.go b/netann/channel_update.go index a40abc2519..4423f4ec2a 100644 --- a/netann/channel_update.go +++ b/netann/channel_update.go @@ -111,12 +111,12 @@ func ExtractChannelUpdate(ownerPubKey []byte, info.ChannelPoint) } -// ChannelUpdateFromEdge reconstructs a signed ChannelUpdate from the given edge -// info and policy. -func ChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, - policy *channeldb.ChannelEdgePolicy) (*lnwire.ChannelUpdate, error) { +// UnsignedChannelUpdateFromEdge reconstructs an unsigned ChannelUpdate from the +// given edge info and policy. +func UnsignedChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, + policy *channeldb.ChannelEdgePolicy) *lnwire.ChannelUpdate { - update := &lnwire.ChannelUpdate{ + return &lnwire.ChannelUpdate{ ChainHash: info.ChainHash, ShortChannelID: lnwire.NewShortChanIDFromInt(policy.ChannelID), Timestamp: uint32(policy.LastUpdate.Unix()), @@ -129,6 +129,14 @@ func ChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, FeeRate: uint32(policy.FeeProportionalMillionths), ExtraOpaqueData: policy.ExtraOpaqueData, } +} + +// ChannelUpdateFromEdge reconstructs a signed ChannelUpdate from the given edge +// info and policy. +func ChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, + policy *channeldb.ChannelEdgePolicy) (*lnwire.ChannelUpdate, error) { + + update := UnsignedChannelUpdateFromEdge(info, policy) var err error update.Signature, err = lnwire.NewSigFromRawSignature(policy.SigBytes) From 92456d063d83ddef549d9cd8d35a74ebe23eed65 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 19 Mar 2020 13:43:57 -0700 Subject: [PATCH 264/562] discovery: remove unused updateChanPolicies struct --- discovery/gossiper.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index bbc1ebd1bc..031394123f 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -351,15 +351,6 @@ func New(cfg Config, selfKey *btcec.PublicKey) *AuthenticatedGossiper { return gossiper } -// updatedChanPolicies is a set of channel policies that have been successfully -// updated and written to disk, or an error if the policy update failed. This -// struct's map field is intended to be used for updating channel policies on -// the link layer. -type updatedChanPolicies struct { - chanPolicies map[wire.OutPoint]*channeldb.ChannelEdgePolicy - err error -} - // EdgeWithInfo contains the information that is required to update an edge. type EdgeWithInfo struct { // Info describes the channel. From 090d56b3a24d0bae76eb4edd3998a6c81ce06a14 Mon Sep 17 00:00:00 2001 From: chokoboko <44872722+chokoboko@users.noreply.github.com> Date: Fri, 20 Mar 2020 01:07:47 +0200 Subject: [PATCH 265/562] config: remove default values from flag descriptions --- config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index 99011dca23..8b9d3e0bea 100644 --- a/config.go +++ b/config.go @@ -305,9 +305,9 @@ type config struct { PaymentsExpirationGracePeriod time.Duration `long:"payments-expiration-grace-period" description:"A period to wait before force closing channels with outgoing htlcs that have timed-out and are a result of this node initiated payments."` TrickleDelay int `long:"trickledelay" description:"Time in milliseconds between each release of announcements to the network"` - ChanEnableTimeout time.Duration `long:"chan-enable-timeout" description:"The duration that a peer connection must be stable before attempting to send a channel update to reenable or cancel a pending disables of the peer's channels on the network (default: 19m)."` - ChanDisableTimeout time.Duration `long:"chan-disable-timeout" description:"The duration that must elapse after first detecting that an already active channel is actually inactive and sending channel update disabling it to the network. The pending disable can be canceled if the peer reconnects and becomes stable for chan-enable-timeout before the disable update is sent. (default: 20m)"` - ChanStatusSampleInterval time.Duration `long:"chan-status-sample-interval" description:"The polling interval between attempts to detect if an active channel has become inactive due to its peer going offline. (default: 1m)"` + ChanEnableTimeout time.Duration `long:"chan-enable-timeout" description:"The duration that a peer connection must be stable before attempting to send a channel update to reenable or cancel a pending disables of the peer's channels on the network."` + ChanDisableTimeout time.Duration `long:"chan-disable-timeout" description:"The duration that must elapse after first detecting that an already active channel is actually inactive and sending channel update disabling it to the network. The pending disable can be canceled if the peer reconnects and becomes stable for chan-enable-timeout before the disable update is sent."` + ChanStatusSampleInterval time.Duration `long:"chan-status-sample-interval" description:"The polling interval between attempts to detect if an active channel has become inactive due to its peer going offline."` Alias string `long:"alias" description:"The node alias. Used as a moniker by peers and intelligence services"` Color string `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"` From 5516a53728fb5693108d2dad3212a0a4b76a5c3a Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 20 Mar 2020 11:11:45 +0200 Subject: [PATCH 266/562] routerrpc: run rpc-format on routerrpc --- lnrpc/routerrpc/router.proto | 25 ++++++++++++++----------- lnrpc/rpc.proto | 2 +- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 027b6c5187..7a63f86aea 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -333,8 +333,8 @@ message BuildRouteResponse { lnrpc.Route route = 1; } - -message SubscribeHtlcEventsRequest{} +message SubscribeHtlcEventsRequest { +} /** HtlcEvent contains the htlc event that was processed. These are served on a @@ -344,7 +344,7 @@ some events may be replayed upon restart. Events consumed from this package should be de-duplicated by the htlc's unique combination of incoming and outgoing channel id and htlc id. [EXPERIMENTAL] */ -message HtlcEvent{ +message HtlcEvent { /** The short channel id that the incoming htlc arrived at our node on. This value is zero for sends. @@ -374,7 +374,7 @@ message HtlcEvent{ */ uint64 timestamp_ns = 5; - enum EventType{ + enum EventType { UNKNOWN = 0; SEND = 1; RECEIVE = 2; @@ -395,7 +395,7 @@ message HtlcEvent{ } } -message HtlcInfo{ +message HtlcInfo { // The timelock on the incoming htlc. uint32 incoming_timelock = 1; @@ -409,16 +409,18 @@ message HtlcInfo{ uint64 outgoing_amt_msat = 4; } -message ForwardEvent{ +message ForwardEvent { // Info contains details about the htlc that was forwarded. HtlcInfo info = 1; } -message ForwardFailEvent{} +message ForwardFailEvent { +} -message SettleEvent{} +message SettleEvent { +} -message LinkFailEvent{ +message LinkFailEvent { // Info contains details about the htlc that we failed. HtlcInfo info = 1; @@ -443,7 +445,7 @@ enum FailureDetail { LINK_NOT_ELIGIBLE = 3; ON_CHAIN_TIMEOUT = 4; HTLC_EXCEEDS_MAX = 5; - INSUFFICIENT_BALANCE =6; + INSUFFICIENT_BALANCE = 6; INCOMPLETE_FORWARD = 7; HTLC_ADD_FAILED = 8; FORWARDS_DISABLED = 9; @@ -521,5 +523,6 @@ service Router { SubscribeHtlcEvents creates a uni-directional stream from the server to the client which delivers a stream of htlc events. */ - rpc SubscribeHtlcEvents (SubscribeHtlcEventsRequest) returns (stream HtlcEvent); + rpc SubscribeHtlcEvents (SubscribeHtlcEventsRequest) + returns (stream HtlcEvent); } diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index fe5fb29f75..2b0c1e764f 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1996,7 +1996,7 @@ message PendingChannelsResponse { /// Hash of the remote version of the commitment tx. string remote_txid = 2; - + /// Hash of the remote pending version of the commitment tx. string remote_pending_txid = 3; } From ceb454aa16752a387c775459f208f0dd41d5e387 Mon Sep 17 00:00:00 2001 From: Roei Erez Date: Mon, 23 Mar 2020 09:49:51 +0200 Subject: [PATCH 267/562] neutrinonotify: use batch for historical confirmations. This commit introduces an optimization for the chain scanning used in historical confirmations notifications. It now uses batch request instead of requesting filters one by one. --- chainntnfs/neutrinonotify/neutrino.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/chainntnfs/neutrinonotify/neutrino.go b/chainntnfs/neutrinonotify/neutrino.go index dfe6fca3aa..771c4b8627 100644 --- a/chainntnfs/neutrinonotify/neutrino.go +++ b/chainntnfs/neutrinonotify/neutrino.go @@ -523,11 +523,18 @@ func (n *NeutrinoNotifier) historicalConfDetails(confRequest chainntnfs.ConfRequ scanHeight, err) } - // With the hash computed, we can now fetch the basic filter - // for this height. + // With the hash computed, we can now fetch the basic filter for this + // height. Since the range of required items is known we avoid + // roundtrips by requesting a batched response and save bandwidth by + // limiting the max number of items per batch. Since neutrino populates + // its underline filters cache with the batch response, the next call + // will execute a network query only once per batch and not on every + // iteration. regFilter, err := n.p2pNode.GetCFilter( *blockHash, wire.GCSFilterRegular, neutrino.NumRetries(5), + neutrino.OptimisticReverseBatch(), + neutrino.MaxBatchSize(int64(scanHeight-startHeight+1)), ) if err != nil { return nil, fmt.Errorf("unable to retrieve regular filter for "+ From 538f3baac8102b238ff5799a4a0ae8d7e61dbfad Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:27 +0100 Subject: [PATCH 268/562] itest: print wrong balance in correct format --- lntest/itest/lnd_test.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index d84ed1148b..a46ef329fa 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -1053,14 +1053,19 @@ func basicChannelFundingTest(t *harnessTest, net *lntest.NetworkHarness, return nil, nil, nil, fmt.Errorf("unable to get bobs's "+ "balance: %v", err) } - if aliceBal.Balance != int64(chanAmt-pushAmt-calcStaticFee(0)) { + + expBalanceAlice := chanAmt - pushAmt - calcStaticFee(0) + aliceBalance := btcutil.Amount(aliceBal.Balance) + if aliceBalance != expBalanceAlice { return nil, nil, nil, fmt.Errorf("alice's balance is "+ "incorrect: expected %v got %v", - chanAmt-pushAmt-calcStaticFee(0), aliceBal) + expBalanceAlice, aliceBalance) } - if bobBal.Balance != int64(pushAmt) { + + bobBalance := btcutil.Amount(bobBal.Balance) + if bobBalance != pushAmt { return nil, nil, nil, fmt.Errorf("bob's balance is incorrect: "+ - "expected %v got %v", pushAmt, bobBal.Balance) + "expected %v got %v", pushAmt, bobBalance) } req := &lnrpc.ListChannelsRequest{} From 651bb09c251d8aa2b0ca353954e8527b0799bc0c Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:27 +0100 Subject: [PATCH 269/562] itest: extract channel force closure test into subtest To make it possible to run the for close test for multiple commit types, we extract it into a subtest, where the two nodes get passed in. --- lntest/itest/lnd_test.go | 75 +++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index a46ef329fa..193dc71666 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -2983,6 +2983,25 @@ func padCLTV(cltv uint32) uint32 { // // TODO(roasbeef): also add an unsettled HTLC before force closing. func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { + t.t.Run("channelForceClosure", func(t *testing.T) { + ht := newHarnessTest(t, net) + + // Since we'd like to test failure scenarios with outstanding + // htlcs, we'll introduce another node into our test network: + // Carol. + carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"}) + if err != nil { + t.Fatalf("unable to create new nodes: %v", err) + } + defer shutdownAndAssert(net, ht, carol) + + channelForceClosureTest(net, ht, net.Alice, carol) + }) +} + +func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, + alice, carol *lntest.HarnessNode) { + ctxb := context.Background() const ( @@ -2996,18 +3015,10 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // instead, or make delay a param defaultCLTV := uint32(lnd.DefaultBitcoinTimeLockDelta) - // Since we'd like to test failure scenarios with outstanding htlcs, - // we'll introduce another node into our test network: Carol. - carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"}) - if err != nil { - t.Fatalf("unable to create new nodes: %v", err) - } - defer shutdownAndAssert(net, t, carol) - // We must let Alice have an open channel before she can send a node // announcement, so we open a channel with Carol, ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, net.Alice, carol); err != nil { + if err := net.ConnectNodes(ctxt, alice, carol); err != nil { t.Fatalf("unable to connect alice to carol: %v", err) } @@ -3025,7 +3036,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) chanPoint := openChannelAndAssert( - ctxt, t, net, net.Alice, carol, + ctxt, t, net, alice, carol, lntest.OpenChannelParams{ Amt: chanAmt, PushAmt: pushAmt, @@ -3035,7 +3046,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // Wait for Alice and Carol to receive the channel edge from the // funding manager. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.Alice.WaitForNetworkChannelOpen(ctxt, chanPoint) + err = alice.WaitForNetworkChannelOpen(ctxt, chanPoint) if err != nil { t.Fatalf("alice didn't see the alice->carol channel before "+ "timeout: %v", err) @@ -3052,7 +3063,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { ctx, cancel := context.WithCancel(ctxb) defer cancel() - alicePayStream, err := net.Alice.SendPayment(ctx) + alicePayStream, err := alice.SendPayment(ctx) if err != nil { t.Fatalf("unable to create payment stream for alice: %v", err) } @@ -3072,7 +3083,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // Once the HTLC has cleared, all the nodes n our mini network should // show that the HTLC has been locked in. - nodes := []*lntest.HarnessNode{net.Alice, carol} + nodes := []*lntest.HarnessNode{alice, carol} var predErr error err = wait.Predicate(func() bool { predErr = assertNumActiveHtlcs(nodes, numInvoices) @@ -3102,7 +3113,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { ) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - aliceChan, err := getChanInfo(ctxt, net.Alice) + aliceChan, err := getChanInfo(ctxt, alice) if err != nil { t.Fatalf("unable to get alice's channel info: %v", err) } @@ -3115,7 +3126,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // the commitment transaction was immediately broadcast in order to // fulfill the force closure request. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - _, closingTxID, err := net.CloseChannel(ctxt, net.Alice, chanPoint, true) + _, closingTxID, err := net.CloseChannel(ctxt, alice, chanPoint, true) if err != nil { t.Fatalf("unable to execute force channel closure: %v", err) } @@ -3124,7 +3135,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // PendingChannels RPC under the waiting close section. pendingChansRequest := &lnrpc.PendingChannelsRequest{} ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Alice.PendingChannels(ctxt, pendingChansRequest) + pendingChanResp, err := alice.PendingChannels(ctxt, pendingChansRequest) if err != nil { t.Fatalf("unable to query for pending channels: %v", err) } @@ -3160,7 +3171,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // when the system comes back on line. This restart tests state // persistence at the beginning of the process, when the commitment // transaction has been broadcast but not yet confirmed in a block. - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3179,7 +3190,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // marked as force closed. err = wait.Predicate(func() bool { ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Alice.PendingChannels( + pendingChanResp, err := alice.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -3232,7 +3243,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // force close commitment transaction have been persisted once the // transaction has been confirmed, but before the outputs are spendable // (the "kindergarten" bucket.) - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3255,7 +3266,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // The following restart checks to ensure that outputs in the // kindergarten bucket are persisted while waiting for the required // number of confirmations to be reported. - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3263,7 +3274,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // channels with her funds still in limbo. err = wait.NoError(func() error { ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Alice.PendingChannels( + pendingChanResp, err := alice.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -3341,7 +3352,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // Restart Alice to ensure that she resumes watching the finalized // commitment sweep txid. - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3369,7 +3380,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // Now that the commit output has been fully swept, check to see // that the channel remains open for the pending htlc outputs. ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Alice.PendingChannels( + pendingChanResp, err := alice.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -3432,7 +3443,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // We now restart Alice, to ensure that she will broadcast the presigned // htlc timeout txns after the delay expires after experiencing a while // waiting for the htlc outputs to incubate. - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3440,7 +3451,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // channels with one pending HTLC. err = wait.NoError(func() error { ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Alice.PendingChannels( + pendingChanResp, err := alice.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -3533,7 +3544,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // With the htlc timeout txns still in the mempool, we restart Alice to // verify that she can resume watching the htlc txns she broadcasted // before crashing. - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3547,7 +3558,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // Alice is restarted here to ensure that she promptly moved the crib // outputs to the kindergarten bucket after the htlc timeout txns were // confirmed. - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3559,7 +3570,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // Restart Alice to ensure that she can recover from a failure before // having graduated the htlc outputs in the kindergarten bucket. - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3568,7 +3579,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // as pending force closed. err = wait.Predicate(func() bool { ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err = net.Alice.PendingChannels( + pendingChanResp, err = alice.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -3660,7 +3671,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // The following restart checks to ensure that the nursery store is // storing the txid of the previously broadcast htlc sweep txn, and that // it begins watching that txid after restarting. - if err := net.RestartNode(net.Alice, nil); err != nil { + if err := net.RestartNode(alice, nil); err != nil { t.Fatalf("Node restart failed: %v", err) } @@ -3669,7 +3680,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // as pending force closed. err = wait.Predicate(func() bool { ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Alice.PendingChannels( + pendingChanResp, err := alice.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -3718,7 +3729,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // up within the pending channels RPC. err = wait.Predicate(func() bool { ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Alice.PendingChannels( + pendingChanResp, err := alice.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { From d81c8bbda76f4902eb8a4ef3f696348497459b2b Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:27 +0100 Subject: [PATCH 270/562] itest: run force closure test for all commit types Now that the force closure test has been extracted, spin up new nodes for each commit type, and ensure the test succeed for all types. --- lntest/itest/lnd_test.go | 59 ++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 193dc71666..a25475fa5f 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -2983,20 +2983,55 @@ func padCLTV(cltv uint32) uint32 { // // TODO(roasbeef): also add an unsettled HTLC before force closing. func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { - t.t.Run("channelForceClosure", func(t *testing.T) { - ht := newHarnessTest(t, net) + // We'll test the scenario for some of the commitment types, to ensure + // outputs can be swept. + commitTypes := []commitType{ + commitTypeLegacy, + } - // Since we'd like to test failure scenarios with outstanding - // htlcs, we'll introduce another node into our test network: - // Carol. - carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"}) - if err != nil { - t.Fatalf("unable to create new nodes: %v", err) - } - defer shutdownAndAssert(net, ht, carol) + for _, channelType := range commitTypes { + testName := fmt.Sprintf("committype=%v", channelType) - channelForceClosureTest(net, ht, net.Alice, carol) - }) + success := t.t.Run(testName, func(t *testing.T) { + ht := newHarnessTest(t, net) + + args := channelType.Args() + alice, err := net.NewNode("Alice", args) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + defer shutdownAndAssert(net, ht, alice) + + // Since we'd like to test failure scenarios with + // outstanding htlcs, we'll introduce another node into + // our test network: Carol. + carolArgs := []string{"--hodl.exit-settle"} + carolArgs = append(carolArgs, args...) + carol, err := net.NewNode("Carol", carolArgs) + if err != nil { + t.Fatalf("unable to create new nodes: %v", err) + } + defer shutdownAndAssert(net, ht, carol) + + // Each time, we'll send Alice new set of coins in + // order to fund the channel. + ctxt, _ := context.WithTimeout( + context.Background(), defaultTimeout, + ) + err = net.SendCoins( + ctxt, btcutil.SatoshiPerBitcoin, alice, + ) + if err != nil { + t.Fatalf("unable to send coins to Alice: %v", + err) + } + + channelForceClosureTest(net, ht, alice, carol) + }) + if !success { + return + } + } } func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, From 4b5d91d24d661164237a4085915db20b3dd77bff Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:27 +0100 Subject: [PATCH 271/562] itest: move multi hop tests to own files PURE CODE MOVE. --- ...d_multi-hop_htlc_local_chain_claim_test.go | 73 ++ .../lnd_multi-hop_htlc_local_timeout_test.go | 250 ++++++ ..._force_close_on_chain_htlc_timeout_test.go | 278 ++++++ ..._force_close_on_chain_htlc_timeout_test.go | 236 ++++++ lntest/itest/lnd_test.go | 790 ------------------ 5 files changed, 837 insertions(+), 790 deletions(-) create mode 100644 lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go create mode 100644 lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go create mode 100644 lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 123359dc49..dd84105c76 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -498,3 +498,76 @@ func checkPaymentStatus(ctxt context.Context, node *lntest.HarnessNode, return nil } + +func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, + carolHodl bool) (*lnrpc.ChannelPoint, *lnrpc.ChannelPoint, + *lntest.HarnessNode) { + + ctxb := context.Background() + + // We'll start the test by creating a channel between Alice and Bob, + // which will act as the first leg for out multi-hop HTLC. + const chanAmt = 1000000 + ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) + aliceChanPoint := openChannelAndAssert( + ctxt, t, net, net.Alice, net.Bob, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err := net.Alice.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) + if err != nil { + t.Fatalf("alice didn't report channel: %v", err) + } + + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = net.Bob.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) + if err != nil { + t.Fatalf("bob didn't report channel: %v", err) + } + + // Next, we'll create a new node "carol" and have Bob connect to her. If + // the carolHodl flag is set, we'll make carol always hold onto the + // HTLC, this way it'll force Bob to go to chain to resolve the HTLC. + carolFlags := []string{} + if carolHodl { + carolFlags = append(carolFlags, "--hodl.exit-settle") + } + carol, err := net.NewNode("Carol", carolFlags) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + if err := net.ConnectNodes(ctxt, net.Bob, carol); err != nil { + t.Fatalf("unable to connect bob to carol: %v", err) + } + + // We'll then create a channel from Bob to Carol. After this channel is + // open, our topology looks like: A -> B -> C. + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) + bobChanPoint := openChannelAndAssert( + ctxt, t, net, net.Bob, carol, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = net.Bob.WaitForNetworkChannelOpen(ctxt, bobChanPoint) + if err != nil { + t.Fatalf("alice didn't report channel: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = carol.WaitForNetworkChannelOpen(ctxt, bobChanPoint) + if err != nil { + t.Fatalf("bob didn't report channel: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = net.Alice.WaitForNetworkChannelOpen(ctxt, bobChanPoint) + if err != nil { + t.Fatalf("bob didn't report channel: %v", err) + } + + return aliceChanPoint, bobChanPoint, carol +} diff --git a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go new file mode 100644 index 0000000000..cb32a0f9d5 --- /dev/null +++ b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go @@ -0,0 +1,250 @@ +// +build rpctest + +package itest + +import ( + "context" + "fmt" + "time" + + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lntest" + "github.com/lightningnetwork/lnd/lntest/wait" +) + +// testMultiHopHtlcLocalTimeout tests that in a multi-hop HTLC scenario, if the +// outgoing HTLC is about to time out, then we'll go to chain in order to claim +// it. Any dust HTLC's should be immediately canceled backwards. Once the +// timeout has been reached, then we should sweep it on-chain, and cancel the +// HTLC backwards. +func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() + + // First, we'll create a three hop network: Alice -> Bob -> Carol, with + // Carol refusing to actually settle or directly cancel any HTLC's + // self. + aliceChanPoint, bobChanPoint, carol := + createThreeHopNetwork(t, net, true) + + // Clean up carol's node when the test finishes. + defer shutdownAndAssert(net, t, carol) + + time.Sleep(time.Second * 1) + + // Now that our channels are set up, we'll send two HTLC's from Alice + // to Carol. The first HTLC will be universally considered "dust", + // while the second will be a proper fully valued HTLC. + const ( + dustHtlcAmt = btcutil.Amount(100) + htlcAmt = btcutil.Amount(30000) + finalCltvDelta = 40 + ) + + ctx, cancel := context.WithCancel(ctxb) + defer cancel() + + alicePayStream, err := net.Alice.SendPayment(ctx) + if err != nil { + t.Fatalf("unable to create payment stream for alice: %v", err) + } + + // We'll create two random payment hashes unknown to carol, then send + // each of them by manually specifying the HTLC details. + carolPubKey := carol.PubKey[:] + dustPayHash := makeFakePayHash(t) + payHash := makeFakePayHash(t) + err = alicePayStream.Send(&lnrpc.SendRequest{ + Dest: carolPubKey, + Amt: int64(dustHtlcAmt), + PaymentHash: dustPayHash, + FinalCltvDelta: finalCltvDelta, + }) + if err != nil { + t.Fatalf("unable to send alice htlc: %v", err) + } + err = alicePayStream.Send(&lnrpc.SendRequest{ + Dest: carolPubKey, + Amt: int64(htlcAmt), + PaymentHash: payHash, + FinalCltvDelta: finalCltvDelta, + }) + if err != nil { + t.Fatalf("unable to send alice htlc: %v", err) + } + + // Verify that all nodes in the path now have two HTLC's with the + // proper parameters. + var predErr error + nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + err = wait.Predicate(func() bool { + predErr = assertActiveHtlcs(nodes, dustPayHash, payHash) + if predErr != nil { + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf("htlc mismatch: %v", predErr) + } + + // We'll now mine enough blocks to trigger Bob's broadcast of his + // commitment transaction due to the fact that the HTLC is about to + // timeout. With the default outgoing broadcast delta of zero, this will + // be the same height as the htlc expiry height. + numBlocks := padCLTV( + uint32(finalCltvDelta - lnd.DefaultOutgoingBroadcastDelta), + ) + if _, err := net.Miner.Node.Generate(numBlocks); err != nil { + t.Fatalf("unable to generate blocks: %v", err) + } + + // Bob's force close transaction should now be found in the mempool. + bobFundingTxid, err := lnd.GetChanPointFundingTxid(bobChanPoint) + if err != nil { + t.Fatalf("unable to get txid: %v", err) + } + closeTxid, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + t.Fatalf("unable to find closing txid: %v", err) + } + assertSpendingTxInMempool( + t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{ + Hash: *bobFundingTxid, + Index: bobChanPoint.OutputIndex, + }, + ) + + // Mine a block to confirm the closing transaction. + mineBlocks(t, net, 1, 1) + + // At this point, Bob should have canceled backwards the dust HTLC + // that we sent earlier. This means Alice should now only have a single + // HTLC on her channel. + nodes = []*lntest.HarnessNode{net.Alice} + err = wait.Predicate(func() bool { + predErr = assertActiveHtlcs(nodes, payHash) + if predErr != nil { + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf("htlc mismatch: %v", predErr) + } + + // With the closing transaction confirmed, we should expect Bob's HTLC + // timeout transaction to be broadcast due to the expiry being reached. + htlcTimeout, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + t.Fatalf("unable to find bob's htlc timeout tx: %v", err) + } + + // We'll mine the remaining blocks in order to generate the sweep + // transaction of Bob's commitment output. + mineBlocks(t, net, defaultCSV, 1) + assertSpendingTxInMempool( + t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{ + Hash: *closeTxid, + Index: 1, + }, + ) + + // Bob's pending channel report should show that he has a commitment + // output awaiting sweeping, and also that there's an outgoing HTLC + // output pending. + pendingChansRequest := &lnrpc.PendingChannelsRequest{} + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err := net.Bob.PendingChannels(ctxt, pendingChansRequest) + if err != nil { + t.Fatalf("unable to query for pending channels: %v", err) + } + + if len(pendingChanResp.PendingForceClosingChannels) == 0 { + t.Fatalf("bob should have pending for close chan but doesn't") + } + forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] + if forceCloseChan.LimboBalance == 0 { + t.Fatalf("bob should have nonzero limbo balance instead "+ + "has: %v", forceCloseChan.LimboBalance) + } + if len(forceCloseChan.PendingHtlcs) == 0 { + t.Fatalf("bob should have pending htlc but doesn't") + } + + // Now we'll mine an additional block, which should confirm Bob's commit + // sweep. This block should also prompt Bob to broadcast their second + // layer sweep due to the CSV on the HTLC timeout output. + mineBlocks(t, net, 1, 1) + assertSpendingTxInMempool( + t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{ + Hash: *htlcTimeout, + Index: 0, + }, + ) + + // The block should have confirmed Bob's HTLC timeout transaction. + // Therefore, at this point, there should be no active HTLC's on the + // commitment transaction from Alice -> Bob. + nodes = []*lntest.HarnessNode{net.Alice} + err = wait.Predicate(func() bool { + predErr = assertNumActiveHtlcs(nodes, 0) + if predErr != nil { + return false + } + return true + }, time.Second*15) + if err != nil { + t.Fatalf("alice's channel still has active htlc's: %v", predErr) + } + + // At this point, Bob should show that the pending HTLC has advanced to + // the second stage and is to be swept. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err = net.Bob.PendingChannels(ctxt, pendingChansRequest) + if err != nil { + t.Fatalf("unable to query for pending channels: %v", err) + } + forceCloseChan = pendingChanResp.PendingForceClosingChannels[0] + if forceCloseChan.PendingHtlcs[0].Stage != 2 { + t.Fatalf("bob's htlc should have advanced to the second stage: %v", err) + } + + // Next, we'll mine a final block that should confirm the second-layer + // sweeping transaction. + if _, err := net.Miner.Node.Generate(1); err != nil { + t.Fatalf("unable to generate blocks: %v", err) + } + + // Once this transaction has been confirmed, Bob should detect that he + // no longer has any pending channels. + err = wait.Predicate(func() bool { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err = net.Bob.PendingChannels(ctxt, pendingChansRequest) + if err != nil { + predErr = fmt.Errorf("unable to query for pending "+ + "channels: %v", err) + return false + } + if len(pendingChanResp.PendingForceClosingChannels) != 0 { + predErr = fmt.Errorf("bob still has pending "+ + "channels but shouldn't: %v", + spew.Sdump(pendingChanResp)) + return false + } + + return true + + }, time.Second*15) + if err != nil { + t.Fatalf(predErr.Error()) + } + + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) +} diff --git a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go new file mode 100644 index 0000000000..ea5bf3d785 --- /dev/null +++ b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go @@ -0,0 +1,278 @@ +// +build rpctest + +package itest + +import ( + "context" + "fmt" + "time" + + "github.com/btcsuite/btcutil" + "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lntest" + "github.com/lightningnetwork/lnd/lntest/wait" +) + +// testMultiHopLocalForceCloseOnChainHtlcTimeout tests that in a multi-hop HTLC +// scenario, if the node that extended the HTLC to the final node closes their +// commitment on-chain early, then it eventually recognizes this HTLC as one +// that's timed out. At this point, the node should timeout the HTLC, then +// cancel it backwards as normal. +func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, + t *harnessTest) { + ctxb := context.Background() + + // First, we'll create a three hop network: Alice -> Bob -> Carol, with + // Carol refusing to actually settle or directly cancel any HTLC's + // self. + aliceChanPoint, bobChanPoint, carol := + createThreeHopNetwork(t, net, true) + + // Clean up carol's node when the test finishes. + defer shutdownAndAssert(net, t, carol) + + // With our channels set up, we'll then send a single HTLC from Alice + // to Carol. As Carol is in hodl mode, she won't settle this HTLC which + // opens up the base for out tests. + const ( + finalCltvDelta = 40 + htlcAmt = btcutil.Amount(30000) + ) + ctx, cancel := context.WithCancel(ctxb) + defer cancel() + + alicePayStream, err := net.Alice.SendPayment(ctx) + if err != nil { + t.Fatalf("unable to create payment stream for alice: %v", err) + } + + // We'll now send a single HTLC across our multi-hop network. + carolPubKey := carol.PubKey[:] + payHash := makeFakePayHash(t) + err = alicePayStream.Send(&lnrpc.SendRequest{ + Dest: carolPubKey, + Amt: int64(htlcAmt), + PaymentHash: payHash, + FinalCltvDelta: finalCltvDelta, + }) + if err != nil { + t.Fatalf("unable to send alice htlc: %v", err) + } + + // Once the HTLC has cleared, all channels in our mini network should + // have the it locked in. + var predErr error + nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + err = wait.Predicate(func() bool { + predErr = assertActiveHtlcs(nodes, payHash) + if predErr != nil { + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf("htlc mismatch: %v", err) + } + + // Now that all parties have the HTLC locked in, we'll immediately + // force close the Bob -> Carol channel. This should trigger contract + // resolution mode for both of them. + ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, net.Bob, bobChanPoint, true) + + // At this point, Bob should have a pending force close channel as he + // just went to chain. + pendingChansRequest := &lnrpc.PendingChannelsRequest{} + err = wait.Predicate(func() bool { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err := net.Bob.PendingChannels(ctxt, + pendingChansRequest) + if err != nil { + predErr = fmt.Errorf("unable to query for pending "+ + "channels: %v", err) + return false + } + if len(pendingChanResp.PendingForceClosingChannels) == 0 { + predErr = fmt.Errorf("bob should have pending for " + + "close chan but doesn't") + return false + } + + forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] + if forceCloseChan.LimboBalance == 0 { + predErr = fmt.Errorf("bob should have nonzero limbo "+ + "balance instead has: %v", + forceCloseChan.LimboBalance) + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf(predErr.Error()) + } + + // We'll mine defaultCSV blocks in order to generate the sweep transaction + // of Bob's funding output. + if _, err := net.Miner.Node.Generate(defaultCSV); err != nil { + t.Fatalf("unable to generate blocks: %v", err) + } + + _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + t.Fatalf("unable to find bob's funding output sweep tx: %v", err) + } + + // We'll now mine enough blocks for the HTLC to expire. After this, Bob + // should hand off the now expired HTLC output to the utxo nursery. + numBlocks := padCLTV(uint32(finalCltvDelta - defaultCSV - 1)) + if _, err := net.Miner.Node.Generate(numBlocks); err != nil { + t.Fatalf("unable to generate blocks: %v", err) + } + + // Bob's pending channel report should show that he has a single HTLC + // that's now in stage one. + err = wait.Predicate(func() bool { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err := net.Bob.PendingChannels( + ctxt, pendingChansRequest, + ) + if err != nil { + predErr = fmt.Errorf("unable to query for pending "+ + "channels: %v", err) + return false + } + + if len(pendingChanResp.PendingForceClosingChannels) == 0 { + predErr = fmt.Errorf("bob should have pending force " + + "close chan but doesn't") + return false + } + + forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] + if len(forceCloseChan.PendingHtlcs) != 1 { + predErr = fmt.Errorf("bob should have pending htlc " + + "but doesn't") + return false + } + if forceCloseChan.PendingHtlcs[0].Stage != 1 { + predErr = fmt.Errorf("bob's htlc should have "+ + "advanced to the first stage: %v", err) + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf("bob didn't hand off time-locked HTLC: %v", predErr) + } + + // We should also now find a transaction in the mempool, as Bob should + // have broadcast his second layer timeout transaction. + timeoutTx, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + t.Fatalf("unable to find bob's htlc timeout tx: %v", err) + } + + // Next, we'll mine an additional block. This should serve to confirm + // the second layer timeout transaction. + block := mineBlocks(t, net, 1, 1)[0] + assertTxInBlock(t, block, timeoutTx) + + // With the second layer timeout transaction confirmed, Bob should have + // canceled backwards the HTLC that carol sent. + nodes = []*lntest.HarnessNode{net.Alice} + err = wait.Predicate(func() bool { + predErr = assertNumActiveHtlcs(nodes, 0) + if predErr != nil { + return false + } + return true + }, time.Second*15) + if err != nil { + t.Fatalf("alice's channel still has active htlc's: %v", predErr) + } + + // Additionally, Bob should now show that HTLC as being advanced to the + // second stage. + err = wait.Predicate(func() bool { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err := net.Bob.PendingChannels( + ctxt, pendingChansRequest, + ) + if err != nil { + predErr = fmt.Errorf("unable to query for pending "+ + "channels: %v", err) + return false + } + + if len(pendingChanResp.PendingForceClosingChannels) == 0 { + predErr = fmt.Errorf("bob should have pending for " + + "close chan but doesn't") + return false + } + + forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] + if len(forceCloseChan.PendingHtlcs) != 1 { + predErr = fmt.Errorf("bob should have pending htlc " + + "but doesn't") + return false + } + if forceCloseChan.PendingHtlcs[0].Stage != 2 { + predErr = fmt.Errorf("bob's htlc should have "+ + "advanced to the second stage: %v", err) + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf("bob didn't hand off time-locked HTLC: %v", predErr) + } + + // We'll now mine 4 additional blocks. This should be enough for Bob's + // CSV timelock to expire and the sweeping transaction of the HTLC to be + // broadcast. + if _, err := net.Miner.Node.Generate(defaultCSV); err != nil { + t.Fatalf("unable to mine blocks: %v", err) + } + + sweepTx, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + t.Fatalf("unable to find bob's htlc sweep tx: %v", err) + } + + // We'll then mine a final block which should confirm this second layer + // sweep transaction. + block = mineBlocks(t, net, 1, 1)[0] + assertTxInBlock(t, block, sweepTx) + + // At this point, Bob should no longer show any channels as pending + // close. + err = wait.Predicate(func() bool { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err := net.Bob.PendingChannels( + ctxt, pendingChansRequest, + ) + if err != nil { + predErr = fmt.Errorf("unable to query for pending "+ + "channels: %v", err) + return false + } + if len(pendingChanResp.PendingForceClosingChannels) != 0 { + predErr = fmt.Errorf("bob still has pending channels "+ + "but shouldn't: %v", spew.Sdump(pendingChanResp)) + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf(predErr.Error()) + } + + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) +} diff --git a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go new file mode 100644 index 0000000000..eea8e1f63c --- /dev/null +++ b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go @@ -0,0 +1,236 @@ +// +build rpctest + +package itest + +import ( + "context" + "fmt" + "time" + + "github.com/btcsuite/btcutil" + "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lntest" + "github.com/lightningnetwork/lnd/lntest/wait" +) + +// testMultiHopRemoteForceCloseOnChainHtlcTimeout tests that if we extend a +// multi-hop HTLC, and the final destination of the HTLC force closes the +// channel, then we properly timeout the HTLC on *their* commitment transaction +// once the timeout has expired. Once we sweep the transaction, we should also +// cancel back the initial HTLC. +func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, + t *harnessTest) { + ctxb := context.Background() + + // First, we'll create a three hop network: Alice -> Bob -> Carol, with + // Carol refusing to actually settle or directly cancel any HTLC's + // self. + aliceChanPoint, bobChanPoint, carol := + createThreeHopNetwork(t, net, true) + + // Clean up carol's node when the test finishes. + defer shutdownAndAssert(net, t, carol) + + // With our channels set up, we'll then send a single HTLC from Alice + // to Carol. As Carol is in hodl mode, she won't settle this HTLC which + // opens up the base for out tests. + const ( + finalCltvDelta = 40 + htlcAmt = btcutil.Amount(30000) + ) + + ctx, cancel := context.WithCancel(ctxb) + defer cancel() + + alicePayStream, err := net.Alice.SendPayment(ctx) + if err != nil { + t.Fatalf("unable to create payment stream for alice: %v", err) + } + + // We'll now send a single HTLC across our multi-hop network. + carolPubKey := carol.PubKey[:] + payHash := makeFakePayHash(t) + err = alicePayStream.Send(&lnrpc.SendRequest{ + Dest: carolPubKey, + Amt: int64(htlcAmt), + PaymentHash: payHash, + FinalCltvDelta: finalCltvDelta, + }) + if err != nil { + t.Fatalf("unable to send alice htlc: %v", err) + } + + // Once the HTLC has cleared, all the nodes in our mini network should + // show that the HTLC has been locked in. + var predErr error + nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + err = wait.Predicate(func() bool { + predErr = assertActiveHtlcs(nodes, payHash) + if predErr != nil { + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf("htlc mismatch: %v", predErr) + } + + // At this point, we'll now instruct Carol to force close the + // transaction. This will let us exercise that Bob is able to sweep the + // expired HTLC on Carol's version of the commitment transaction. + ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, carol, bobChanPoint, true) + + // At this point, Bob should have a pending force close channel as + // Carol has gone directly to chain. + pendingChansRequest := &lnrpc.PendingChannelsRequest{} + err = wait.Predicate(func() bool { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err := net.Bob.PendingChannels( + ctxt, pendingChansRequest, + ) + if err != nil { + predErr = fmt.Errorf("unable to query for "+ + "pending channels: %v", err) + return false + } + if len(pendingChanResp.PendingForceClosingChannels) == 0 { + predErr = fmt.Errorf("bob should have pending " + + "force close channels but doesn't") + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf(predErr.Error()) + } + + // Bob can sweep his output immediately. + _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + t.Fatalf("unable to find bob's funding output sweep tx: %v", + err) + } + + // Next, we'll mine enough blocks for the HTLC to expire. At this + // point, Bob should hand off the output to his internal utxo nursery, + // which will broadcast a sweep transaction. + numBlocks := padCLTV(finalCltvDelta - 1) + if _, err := net.Miner.Node.Generate(numBlocks); err != nil { + t.Fatalf("unable to generate blocks: %v", err) + } + + // If we check Bob's pending channel report, it should show that he has + // a single HTLC that's now in the second stage, as skip the initial + // first stage since this is a direct HTLC. + err = wait.Predicate(func() bool { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err := net.Bob.PendingChannels( + ctxt, pendingChansRequest, + ) + if err != nil { + predErr = fmt.Errorf("unable to query for pending "+ + "channels: %v", err) + return false + } + + if len(pendingChanResp.PendingForceClosingChannels) == 0 { + predErr = fmt.Errorf("bob should have pending for " + + "close chan but doesn't") + return false + } + + forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] + if len(forceCloseChan.PendingHtlcs) != 1 { + predErr = fmt.Errorf("bob should have pending htlc " + + "but doesn't") + return false + } + if forceCloseChan.PendingHtlcs[0].Stage != 2 { + predErr = fmt.Errorf("bob's htlc should have "+ + "advanced to the second stage: %v", err) + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf("bob didn't hand off time-locked HTLC: %v", predErr) + } + + // Bob's sweeping transaction should now be found in the mempool at + // this point. + sweepTx, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + // If Bob's transaction isn't yet in the mempool, then due to + // internal message passing and the low period between blocks + // being mined, it may have been detected as a late + // registration. As a result, we'll mine another block and + // repeat the check. If it doesn't go through this time, then + // we'll fail. + // TODO(halseth): can we use waitForChannelPendingForceClose to + // avoid this hack? + if _, err := net.Miner.Node.Generate(1); err != nil { + t.Fatalf("unable to generate block: %v", err) + } + sweepTx, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + t.Fatalf("unable to find bob's sweeping transaction: "+ + "%v", err) + } + } + + // If we mine an additional block, then this should confirm Bob's + // transaction which sweeps the direct HTLC output. + block := mineBlocks(t, net, 1, 1)[0] + assertTxInBlock(t, block, sweepTx) + + // Now that the sweeping transaction has been confirmed, Bob should + // cancel back that HTLC. As a result, Alice should not know of any + // active HTLC's. + nodes = []*lntest.HarnessNode{net.Alice} + err = wait.Predicate(func() bool { + predErr = assertNumActiveHtlcs(nodes, 0) + if predErr != nil { + return false + } + return true + }, time.Second*15) + if err != nil { + t.Fatalf("alice's channel still has active htlc's: %v", predErr) + } + + // Now we'll check Bob's pending channel report. Since this was Carol's + // commitment, he doesn't have to wait for any CSV delays. As a result, + // he should show no additional pending transactions. + err = wait.Predicate(func() bool { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + pendingChanResp, err := net.Bob.PendingChannels( + ctxt, pendingChansRequest, + ) + if err != nil { + predErr = fmt.Errorf("unable to query for pending "+ + "channels: %v", err) + return false + } + if len(pendingChanResp.PendingForceClosingChannels) != 0 { + predErr = fmt.Errorf("bob still has pending channels "+ + "but shouldn't: %v", spew.Sdump(pendingChanResp)) + return false + } + + return true + }, time.Second*15) + if err != nil { + t.Fatalf(predErr.Error()) + } + + // We'll close out the test by closing the channel from Alice to Bob, + // and then shutting down the new node we created as its no longer + // needed. + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) +} diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index a25475fa5f..19a631f355 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -10593,796 +10593,6 @@ func assertSpendingTxInMempool(t *harnessTest, miner *rpcclient.Client, } } -func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, - carolHodl bool) (*lnrpc.ChannelPoint, *lnrpc.ChannelPoint, - *lntest.HarnessNode) { - - ctxb := context.Background() - - // We'll start the test by creating a channel between Alice and Bob, - // which will act as the first leg for out multi-hop HTLC. - const chanAmt = 1000000 - ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) - aliceChanPoint := openChannelAndAssert( - ctxt, t, net, net.Alice, net.Bob, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err := net.Alice.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) - if err != nil { - t.Fatalf("alice didn't report channel: %v", err) - } - - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.Bob.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) - if err != nil { - t.Fatalf("bob didn't report channel: %v", err) - } - - // Next, we'll create a new node "carol" and have Bob connect to her. If - // the carolHodl flag is set, we'll make carol always hold onto the - // HTLC, this way it'll force Bob to go to chain to resolve the HTLC. - carolFlags := []string{} - if carolHodl { - carolFlags = append(carolFlags, "--hodl.exit-settle") - } - carol, err := net.NewNode("Carol", carolFlags) - if err != nil { - t.Fatalf("unable to create new node: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, net.Bob, carol); err != nil { - t.Fatalf("unable to connect bob to carol: %v", err) - } - - // We'll then create a channel from Bob to Carol. After this channel is - // open, our topology looks like: A -> B -> C. - ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - bobChanPoint := openChannelAndAssert( - ctxt, t, net, net.Bob, carol, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.Bob.WaitForNetworkChannelOpen(ctxt, bobChanPoint) - if err != nil { - t.Fatalf("alice didn't report channel: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = carol.WaitForNetworkChannelOpen(ctxt, bobChanPoint) - if err != nil { - t.Fatalf("bob didn't report channel: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.Alice.WaitForNetworkChannelOpen(ctxt, bobChanPoint) - if err != nil { - t.Fatalf("bob didn't report channel: %v", err) - } - - return aliceChanPoint, bobChanPoint, carol -} - -// testMultiHopHtlcLocalTimeout tests that in a multi-hop HTLC scenario, if the -// outgoing HTLC is about to time out, then we'll go to chain in order to claim -// it. Any dust HTLC's should be immediately canceled backwards. Once the -// timeout has been reached, then we should sweep it on-chain, and cancel the -// HTLC backwards. -func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { - ctxb := context.Background() - - // First, we'll create a three hop network: Alice -> Bob -> Carol, with - // Carol refusing to actually settle or directly cancel any HTLC's - // self. - aliceChanPoint, bobChanPoint, carol := - createThreeHopNetwork(t, net, true) - - // Clean up carol's node when the test finishes. - defer shutdownAndAssert(net, t, carol) - - time.Sleep(time.Second * 1) - - // Now that our channels are set up, we'll send two HTLC's from Alice - // to Carol. The first HTLC will be universally considered "dust", - // while the second will be a proper fully valued HTLC. - const ( - dustHtlcAmt = btcutil.Amount(100) - htlcAmt = btcutil.Amount(30000) - finalCltvDelta = 40 - ) - - ctx, cancel := context.WithCancel(ctxb) - defer cancel() - - alicePayStream, err := net.Alice.SendPayment(ctx) - if err != nil { - t.Fatalf("unable to create payment stream for alice: %v", err) - } - - // We'll create two random payment hashes unknown to carol, then send - // each of them by manually specifying the HTLC details. - carolPubKey := carol.PubKey[:] - dustPayHash := makeFakePayHash(t) - payHash := makeFakePayHash(t) - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(dustHtlcAmt), - PaymentHash: dustPayHash, - FinalCltvDelta: finalCltvDelta, - }) - if err != nil { - t.Fatalf("unable to send alice htlc: %v", err) - } - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(htlcAmt), - PaymentHash: payHash, - FinalCltvDelta: finalCltvDelta, - }) - if err != nil { - t.Fatalf("unable to send alice htlc: %v", err) - } - - // Verify that all nodes in the path now have two HTLC's with the - // proper parameters. - var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} - err = wait.Predicate(func() bool { - predErr = assertActiveHtlcs(nodes, dustPayHash, payHash) - if predErr != nil { - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf("htlc mismatch: %v", predErr) - } - - // We'll now mine enough blocks to trigger Bob's broadcast of his - // commitment transaction due to the fact that the HTLC is about to - // timeout. With the default outgoing broadcast delta of zero, this will - // be the same height as the htlc expiry height. - numBlocks := padCLTV( - uint32(finalCltvDelta - lnd.DefaultOutgoingBroadcastDelta), - ) - if _, err := net.Miner.Node.Generate(numBlocks); err != nil { - t.Fatalf("unable to generate blocks: %v", err) - } - - // Bob's force close transaction should now be found in the mempool. - bobFundingTxid, err := lnd.GetChanPointFundingTxid(bobChanPoint) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - closeTxid, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) - if err != nil { - t.Fatalf("unable to find closing txid: %v", err) - } - assertSpendingTxInMempool( - t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{ - Hash: *bobFundingTxid, - Index: bobChanPoint.OutputIndex, - }, - ) - - // Mine a block to confirm the closing transaction. - mineBlocks(t, net, 1, 1) - - // At this point, Bob should have canceled backwards the dust HTLC - // that we sent earlier. This means Alice should now only have a single - // HTLC on her channel. - nodes = []*lntest.HarnessNode{net.Alice} - err = wait.Predicate(func() bool { - predErr = assertActiveHtlcs(nodes, payHash) - if predErr != nil { - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf("htlc mismatch: %v", predErr) - } - - // With the closing transaction confirmed, we should expect Bob's HTLC - // timeout transaction to be broadcast due to the expiry being reached. - htlcTimeout, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) - if err != nil { - t.Fatalf("unable to find bob's htlc timeout tx: %v", err) - } - - // We'll mine the remaining blocks in order to generate the sweep - // transaction of Bob's commitment output. - mineBlocks(t, net, defaultCSV, 1) - assertSpendingTxInMempool( - t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{ - Hash: *closeTxid, - Index: 1, - }, - ) - - // Bob's pending channel report should show that he has a commitment - // output awaiting sweeping, and also that there's an outgoing HTLC - // output pending. - pendingChansRequest := &lnrpc.PendingChannelsRequest{} - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels(ctxt, pendingChansRequest) - if err != nil { - t.Fatalf("unable to query for pending channels: %v", err) - } - - if len(pendingChanResp.PendingForceClosingChannels) == 0 { - t.Fatalf("bob should have pending for close chan but doesn't") - } - forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] - if forceCloseChan.LimboBalance == 0 { - t.Fatalf("bob should have nonzero limbo balance instead "+ - "has: %v", forceCloseChan.LimboBalance) - } - if len(forceCloseChan.PendingHtlcs) == 0 { - t.Fatalf("bob should have pending htlc but doesn't") - } - - // Now we'll mine an additional block, which should confirm Bob's commit - // sweep. This block should also prompt Bob to broadcast their second - // layer sweep due to the CSV on the HTLC timeout output. - mineBlocks(t, net, 1, 1) - assertSpendingTxInMempool( - t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{ - Hash: *htlcTimeout, - Index: 0, - }, - ) - - // The block should have confirmed Bob's HTLC timeout transaction. - // Therefore, at this point, there should be no active HTLC's on the - // commitment transaction from Alice -> Bob. - nodes = []*lntest.HarnessNode{net.Alice} - err = wait.Predicate(func() bool { - predErr = assertNumActiveHtlcs(nodes, 0) - if predErr != nil { - return false - } - return true - }, time.Second*15) - if err != nil { - t.Fatalf("alice's channel still has active htlc's: %v", predErr) - } - - // At this point, Bob should show that the pending HTLC has advanced to - // the second stage and is to be swept. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err = net.Bob.PendingChannels(ctxt, pendingChansRequest) - if err != nil { - t.Fatalf("unable to query for pending channels: %v", err) - } - forceCloseChan = pendingChanResp.PendingForceClosingChannels[0] - if forceCloseChan.PendingHtlcs[0].Stage != 2 { - t.Fatalf("bob's htlc should have advanced to the second stage: %v", err) - } - - // Next, we'll mine a final block that should confirm the second-layer - // sweeping transaction. - if _, err := net.Miner.Node.Generate(1); err != nil { - t.Fatalf("unable to generate blocks: %v", err) - } - - // Once this transaction has been confirmed, Bob should detect that he - // no longer has any pending channels. - err = wait.Predicate(func() bool { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err = net.Bob.PendingChannels(ctxt, pendingChansRequest) - if err != nil { - predErr = fmt.Errorf("unable to query for pending "+ - "channels: %v", err) - return false - } - if len(pendingChanResp.PendingForceClosingChannels) != 0 { - predErr = fmt.Errorf("bob still has pending "+ - "channels but shouldn't: %v", - spew.Sdump(pendingChanResp)) - return false - } - - return true - - }, time.Second*15) - if err != nil { - t.Fatalf(predErr.Error()) - } - - ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) -} - -// testMultiHopLocalForceCloseOnChainHtlcTimeout tests that in a multi-hop HTLC -// scenario, if the node that extended the HTLC to the final node closes their -// commitment on-chain early, then it eventually recognizes this HTLC as one -// that's timed out. At this point, the node should timeout the HTLC, then -// cancel it backwards as normal. -func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, - t *harnessTest) { - ctxb := context.Background() - - // First, we'll create a three hop network: Alice -> Bob -> Carol, with - // Carol refusing to actually settle or directly cancel any HTLC's - // self. - aliceChanPoint, bobChanPoint, carol := - createThreeHopNetwork(t, net, true) - - // Clean up carol's node when the test finishes. - defer shutdownAndAssert(net, t, carol) - - // With our channels set up, we'll then send a single HTLC from Alice - // to Carol. As Carol is in hodl mode, she won't settle this HTLC which - // opens up the base for out tests. - const ( - finalCltvDelta = 40 - htlcAmt = btcutil.Amount(30000) - ) - ctx, cancel := context.WithCancel(ctxb) - defer cancel() - - alicePayStream, err := net.Alice.SendPayment(ctx) - if err != nil { - t.Fatalf("unable to create payment stream for alice: %v", err) - } - - // We'll now send a single HTLC across our multi-hop network. - carolPubKey := carol.PubKey[:] - payHash := makeFakePayHash(t) - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(htlcAmt), - PaymentHash: payHash, - FinalCltvDelta: finalCltvDelta, - }) - if err != nil { - t.Fatalf("unable to send alice htlc: %v", err) - } - - // Once the HTLC has cleared, all channels in our mini network should - // have the it locked in. - var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} - err = wait.Predicate(func() bool { - predErr = assertActiveHtlcs(nodes, payHash) - if predErr != nil { - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf("htlc mismatch: %v", err) - } - - // Now that all parties have the HTLC locked in, we'll immediately - // force close the Bob -> Carol channel. This should trigger contract - // resolution mode for both of them. - ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Bob, bobChanPoint, true) - - // At this point, Bob should have a pending force close channel as he - // just went to chain. - pendingChansRequest := &lnrpc.PendingChannelsRequest{} - err = wait.Predicate(func() bool { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels(ctxt, - pendingChansRequest) - if err != nil { - predErr = fmt.Errorf("unable to query for pending "+ - "channels: %v", err) - return false - } - if len(pendingChanResp.PendingForceClosingChannels) == 0 { - predErr = fmt.Errorf("bob should have pending for " + - "close chan but doesn't") - return false - } - - forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] - if forceCloseChan.LimboBalance == 0 { - predErr = fmt.Errorf("bob should have nonzero limbo "+ - "balance instead has: %v", - forceCloseChan.LimboBalance) - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf(predErr.Error()) - } - - // We'll mine defaultCSV blocks in order to generate the sweep transaction - // of Bob's funding output. - if _, err := net.Miner.Node.Generate(defaultCSV); err != nil { - t.Fatalf("unable to generate blocks: %v", err) - } - - _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) - if err != nil { - t.Fatalf("unable to find bob's funding output sweep tx: %v", err) - } - - // We'll now mine enough blocks for the HTLC to expire. After this, Bob - // should hand off the now expired HTLC output to the utxo nursery. - numBlocks := padCLTV(uint32(finalCltvDelta - defaultCSV - 1)) - if _, err := net.Miner.Node.Generate(numBlocks); err != nil { - t.Fatalf("unable to generate blocks: %v", err) - } - - // Bob's pending channel report should show that he has a single HTLC - // that's now in stage one. - err = wait.Predicate(func() bool { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( - ctxt, pendingChansRequest, - ) - if err != nil { - predErr = fmt.Errorf("unable to query for pending "+ - "channels: %v", err) - return false - } - - if len(pendingChanResp.PendingForceClosingChannels) == 0 { - predErr = fmt.Errorf("bob should have pending force " + - "close chan but doesn't") - return false - } - - forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] - if len(forceCloseChan.PendingHtlcs) != 1 { - predErr = fmt.Errorf("bob should have pending htlc " + - "but doesn't") - return false - } - if forceCloseChan.PendingHtlcs[0].Stage != 1 { - predErr = fmt.Errorf("bob's htlc should have "+ - "advanced to the first stage: %v", err) - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf("bob didn't hand off time-locked HTLC: %v", predErr) - } - - // We should also now find a transaction in the mempool, as Bob should - // have broadcast his second layer timeout transaction. - timeoutTx, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) - if err != nil { - t.Fatalf("unable to find bob's htlc timeout tx: %v", err) - } - - // Next, we'll mine an additional block. This should serve to confirm - // the second layer timeout transaction. - block := mineBlocks(t, net, 1, 1)[0] - assertTxInBlock(t, block, timeoutTx) - - // With the second layer timeout transaction confirmed, Bob should have - // canceled backwards the HTLC that carol sent. - nodes = []*lntest.HarnessNode{net.Alice} - err = wait.Predicate(func() bool { - predErr = assertNumActiveHtlcs(nodes, 0) - if predErr != nil { - return false - } - return true - }, time.Second*15) - if err != nil { - t.Fatalf("alice's channel still has active htlc's: %v", predErr) - } - - // Additionally, Bob should now show that HTLC as being advanced to the - // second stage. - err = wait.Predicate(func() bool { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( - ctxt, pendingChansRequest, - ) - if err != nil { - predErr = fmt.Errorf("unable to query for pending "+ - "channels: %v", err) - return false - } - - if len(pendingChanResp.PendingForceClosingChannels) == 0 { - predErr = fmt.Errorf("bob should have pending for " + - "close chan but doesn't") - return false - } - - forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] - if len(forceCloseChan.PendingHtlcs) != 1 { - predErr = fmt.Errorf("bob should have pending htlc " + - "but doesn't") - return false - } - if forceCloseChan.PendingHtlcs[0].Stage != 2 { - predErr = fmt.Errorf("bob's htlc should have "+ - "advanced to the second stage: %v", err) - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf("bob didn't hand off time-locked HTLC: %v", predErr) - } - - // We'll now mine 4 additional blocks. This should be enough for Bob's - // CSV timelock to expire and the sweeping transaction of the HTLC to be - // broadcast. - if _, err := net.Miner.Node.Generate(defaultCSV); err != nil { - t.Fatalf("unable to mine blocks: %v", err) - } - - sweepTx, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) - if err != nil { - t.Fatalf("unable to find bob's htlc sweep tx: %v", err) - } - - // We'll then mine a final block which should confirm this second layer - // sweep transaction. - block = mineBlocks(t, net, 1, 1)[0] - assertTxInBlock(t, block, sweepTx) - - // At this point, Bob should no longer show any channels as pending - // close. - err = wait.Predicate(func() bool { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( - ctxt, pendingChansRequest, - ) - if err != nil { - predErr = fmt.Errorf("unable to query for pending "+ - "channels: %v", err) - return false - } - if len(pendingChanResp.PendingForceClosingChannels) != 0 { - predErr = fmt.Errorf("bob still has pending channels "+ - "but shouldn't: %v", spew.Sdump(pendingChanResp)) - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf(predErr.Error()) - } - - ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) -} - -// testMultiHopRemoteForceCloseOnChainHtlcTimeout tests that if we extend a -// multi-hop HTLC, and the final destination of the HTLC force closes the -// channel, then we properly timeout the HTLC on *their* commitment transaction -// once the timeout has expired. Once we sweep the transaction, we should also -// cancel back the initial HTLC. -func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, - t *harnessTest) { - ctxb := context.Background() - - // First, we'll create a three hop network: Alice -> Bob -> Carol, with - // Carol refusing to actually settle or directly cancel any HTLC's - // self. - aliceChanPoint, bobChanPoint, carol := - createThreeHopNetwork(t, net, true) - - // Clean up carol's node when the test finishes. - defer shutdownAndAssert(net, t, carol) - - // With our channels set up, we'll then send a single HTLC from Alice - // to Carol. As Carol is in hodl mode, she won't settle this HTLC which - // opens up the base for out tests. - const ( - finalCltvDelta = 40 - htlcAmt = btcutil.Amount(30000) - ) - - ctx, cancel := context.WithCancel(ctxb) - defer cancel() - - alicePayStream, err := net.Alice.SendPayment(ctx) - if err != nil { - t.Fatalf("unable to create payment stream for alice: %v", err) - } - - // We'll now send a single HTLC across our multi-hop network. - carolPubKey := carol.PubKey[:] - payHash := makeFakePayHash(t) - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(htlcAmt), - PaymentHash: payHash, - FinalCltvDelta: finalCltvDelta, - }) - if err != nil { - t.Fatalf("unable to send alice htlc: %v", err) - } - - // Once the HTLC has cleared, all the nodes in our mini network should - // show that the HTLC has been locked in. - var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} - err = wait.Predicate(func() bool { - predErr = assertActiveHtlcs(nodes, payHash) - if predErr != nil { - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf("htlc mismatch: %v", predErr) - } - - // At this point, we'll now instruct Carol to force close the - // transaction. This will let us exercise that Bob is able to sweep the - // expired HTLC on Carol's version of the commitment transaction. - ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, carol, bobChanPoint, true) - - // At this point, Bob should have a pending force close channel as - // Carol has gone directly to chain. - pendingChansRequest := &lnrpc.PendingChannelsRequest{} - err = wait.Predicate(func() bool { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( - ctxt, pendingChansRequest, - ) - if err != nil { - predErr = fmt.Errorf("unable to query for "+ - "pending channels: %v", err) - return false - } - if len(pendingChanResp.PendingForceClosingChannels) == 0 { - predErr = fmt.Errorf("bob should have pending " + - "force close channels but doesn't") - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf(predErr.Error()) - } - - // Bob can sweep his output immediately. - _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) - if err != nil { - t.Fatalf("unable to find bob's funding output sweep tx: %v", - err) - } - - // Next, we'll mine enough blocks for the HTLC to expire. At this - // point, Bob should hand off the output to his internal utxo nursery, - // which will broadcast a sweep transaction. - numBlocks := padCLTV(finalCltvDelta - 1) - if _, err := net.Miner.Node.Generate(numBlocks); err != nil { - t.Fatalf("unable to generate blocks: %v", err) - } - - // If we check Bob's pending channel report, it should show that he has - // a single HTLC that's now in the second stage, as skip the initial - // first stage since this is a direct HTLC. - err = wait.Predicate(func() bool { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( - ctxt, pendingChansRequest, - ) - if err != nil { - predErr = fmt.Errorf("unable to query for pending "+ - "channels: %v", err) - return false - } - - if len(pendingChanResp.PendingForceClosingChannels) == 0 { - predErr = fmt.Errorf("bob should have pending for " + - "close chan but doesn't") - return false - } - - forceCloseChan := pendingChanResp.PendingForceClosingChannels[0] - if len(forceCloseChan.PendingHtlcs) != 1 { - predErr = fmt.Errorf("bob should have pending htlc " + - "but doesn't") - return false - } - if forceCloseChan.PendingHtlcs[0].Stage != 2 { - predErr = fmt.Errorf("bob's htlc should have "+ - "advanced to the second stage: %v", err) - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf("bob didn't hand off time-locked HTLC: %v", predErr) - } - - // Bob's sweeping transaction should now be found in the mempool at - // this point. - sweepTx, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) - if err != nil { - // If Bob's transaction isn't yet in the mempool, then due to - // internal message passing and the low period between blocks - // being mined, it may have been detected as a late - // registration. As a result, we'll mine another block and - // repeat the check. If it doesn't go through this time, then - // we'll fail. - // TODO(halseth): can we use waitForChannelPendingForceClose to - // avoid this hack? - if _, err := net.Miner.Node.Generate(1); err != nil { - t.Fatalf("unable to generate block: %v", err) - } - sweepTx, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) - if err != nil { - t.Fatalf("unable to find bob's sweeping transaction: "+ - "%v", err) - } - } - - // If we mine an additional block, then this should confirm Bob's - // transaction which sweeps the direct HTLC output. - block := mineBlocks(t, net, 1, 1)[0] - assertTxInBlock(t, block, sweepTx) - - // Now that the sweeping transaction has been confirmed, Bob should - // cancel back that HTLC. As a result, Alice should not know of any - // active HTLC's. - nodes = []*lntest.HarnessNode{net.Alice} - err = wait.Predicate(func() bool { - predErr = assertNumActiveHtlcs(nodes, 0) - if predErr != nil { - return false - } - return true - }, time.Second*15) - if err != nil { - t.Fatalf("alice's channel still has active htlc's: %v", predErr) - } - - // Now we'll check Bob's pending channel report. Since this was Carol's - // commitment, he doesn't have to wait for any CSV delays. As a result, - // he should show no additional pending transactions. - err = wait.Predicate(func() bool { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( - ctxt, pendingChansRequest, - ) - if err != nil { - predErr = fmt.Errorf("unable to query for pending "+ - "channels: %v", err) - return false - } - if len(pendingChanResp.PendingForceClosingChannels) != 0 { - predErr = fmt.Errorf("bob still has pending channels "+ - "but shouldn't: %v", spew.Sdump(pendingChanResp)) - return false - } - - return true - }, time.Second*15) - if err != nil { - t.Fatalf(predErr.Error()) - } - - // We'll close out the test by closing the channel from Alice to Bob, - // and then shutting down the new node we created as its no longer - // needed. - ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) -} - // testSwitchCircuitPersistence creates a multihop network to ensure the sender // and intermediaries are persisting their open payment circuits. After // forwarding a packet via an outgoing link, all are restarted, and expected to From 5a0f2d004a244e4baaa8634b0361b6557c81dfa1 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:28 +0100 Subject: [PATCH 272/562] itest: update multi hop test case docs To make clear whcih sweep scenarios are actually being tested --- lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go | 6 +++--- lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go | 6 +++--- .../itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go | 7 ++++--- lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go | 3 ++- ...lti-hop_local_force_close_on_chain_htlc_timeout_test.go | 4 ++-- ...ti-hop_remote_force_close_on_chain_htlc_timeout_test.go | 6 +++--- lntest/itest/lnd_test.go | 2 +- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index dd84105c76..1ae63b1433 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -18,9 +18,9 @@ import ( ) // testMultiHopHtlcLocalChainClaim tests that in a multi-hop HTLC scenario, if -// we're forced to go to chain with an incoming HTLC, then when we find out the -// preimage via the witness beacon, we properly settle the HTLC on-chain in -// order to ensure we don't lose any funds. +// we force close a channel with an incoming HTLC, and later find out the +// preimage via the witness beacon, we properly settle the HTLC on-chain using +// the HTLC success transaction in order to ensure we don't lose any funds. func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() diff --git a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go index cb32a0f9d5..71c6671667 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go @@ -18,9 +18,9 @@ import ( // testMultiHopHtlcLocalTimeout tests that in a multi-hop HTLC scenario, if the // outgoing HTLC is about to time out, then we'll go to chain in order to claim -// it. Any dust HTLC's should be immediately canceled backwards. Once the -// timeout has been reached, then we should sweep it on-chain, and cancel the -// HTLC backwards. +// it using the HTLC timeout transaction. Any dust HTLC's should be immediately +// canceled backwards. Once the timeout has been reached, then we should sweep +// it on-chain, and cancel the HTLC backwards. func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() diff --git a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go index 8a01763393..0df3925046 100644 --- a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go @@ -20,9 +20,10 @@ import ( // testMultiHopReceiverChainClaim tests that in the multi-hop setting, if the // receiver of an HTLC knows the preimage, but wasn't able to settle the HTLC -// off-chain, then it goes on chain to claim the HTLC. In this scenario, the -// node that sent the outgoing HTLC should extract the preimage from the sweep -// transaction, and finish settling the HTLC backwards into the route. +// off-chain, then it goes on chain to claim the HTLC uing the HTLC success +// transaction. In this scenario, the node that sent the outgoing HTLC should +// extract the preimage from the sweep transaction, and finish settling the +// HTLC backwards into the route. func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() diff --git a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go index b96bc17f8e..8c3a1f285f 100644 --- a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go @@ -20,7 +20,8 @@ import ( // testMultiHopHtlcRemoteChainClaim tests that in the multi-hop HTLC scenario, // if the remote party goes to chain while we have an incoming HTLC, then when // we found out the preimage via the witness beacon, we properly settle the -// HTLC on-chain in order to ensure that we don't lose any funds. +// HTLC directly on-chain using the preimage in order to ensure that we don't +// lose any funds. func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() diff --git a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go index ea5bf3d785..960ff17d4d 100644 --- a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go @@ -17,8 +17,8 @@ import ( // testMultiHopLocalForceCloseOnChainHtlcTimeout tests that in a multi-hop HTLC // scenario, if the node that extended the HTLC to the final node closes their // commitment on-chain early, then it eventually recognizes this HTLC as one -// that's timed out. At this point, the node should timeout the HTLC, then -// cancel it backwards as normal. +// that's timed out. At this point, the node should timeout the HTLC using the +// HTLC timeout transaction, then cancel it backwards as normal. func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() diff --git a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go index eea8e1f63c..6c6d6eab65 100644 --- a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go @@ -16,9 +16,9 @@ import ( // testMultiHopRemoteForceCloseOnChainHtlcTimeout tests that if we extend a // multi-hop HTLC, and the final destination of the HTLC force closes the -// channel, then we properly timeout the HTLC on *their* commitment transaction -// once the timeout has expired. Once we sweep the transaction, we should also -// cancel back the initial HTLC. +// channel, then we properly timeout the HTLC directly on *their* commitment +// transaction once the timeout has expired. Once we sweep the transaction, we +// should also cancel back the initial HTLC. func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 19a631f355..fb93746b5e 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -2976,7 +2976,7 @@ func padCLTV(cltv uint32) uint32 { // total of 3 + n transactions will be broadcast, representing the commitment // transaction, a transaction sweeping the local CSV delayed output, a // transaction sweeping the CSV delayed 2nd-layer htlcs outputs, and n -// htlc success transactions, where n is the number of payments Alice attempted +// htlc timeout transactions, where n is the number of payments Alice attempted // to send to Carol. This test includes several restarts to ensure that the // transaction output states are persisted throughout the forced closure // process. From 1ce4abc0a9879e47887dcb4524c9a32d55f0320a Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:28 +0100 Subject: [PATCH 273/562] itest: extract multi-hop tests into sub tests --- ...d_multi-hop_htlc_local_chain_claim_test.go | 63 +++++++++++++++++++ lntest/itest/lnd_test.go | 38 +---------- 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 1ae63b1433..868e8974b3 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -5,6 +5,7 @@ package itest import ( "context" "fmt" + "testing" "time" "github.com/btcsuite/btcd/wire" @@ -17,6 +18,68 @@ import ( "github.com/lightningnetwork/lnd/lntypes" ) +func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { + + type testCase struct { + name string + test func(net *lntest.NetworkHarness, t *harnessTest) + } + + subTests := []testCase{ + { + // bob: outgoing our commit timeout + // carol: incoming their commit watch and see timeout + name: "local force close immediate expiry", + test: testMultiHopHtlcLocalTimeout, + }, + { + // bob: outgoing watch and see, they sweep on chain + // carol: incoming our commit, know preimage + name: "receiver chain claim", + test: testMultiHopReceiverChainClaim, + }, + { + // bob: outgoing our commit watch and see timeout + // carol: incoming their commit watch and see timeout + name: "local force close on-chain htlc timeout", + test: testMultiHopLocalForceCloseOnChainHtlcTimeout, + }, + { + // bob: outgoing their commit watch and see timeout + // carol: incoming our commit watch and see timeout + name: "remote force close on-chain htlc timeout", + test: testMultiHopRemoteForceCloseOnChainHtlcTimeout, + }, + { + // bob: outgoing our commit watch and see, they sweep on chain + // bob: incoming our commit watch and learn preimage + // carol: incoming their commit know preimage + name: "local chain claim", + test: testMultiHopHtlcLocalChainClaim, + }, + { + // bob: outgoing their commit watch and see, they sweep on chain + // bob: incoming their commit watch and learn preimage + // carol: incoming our commit know preimage + name: "remote chain claim", + test: testMultiHopHtlcRemoteChainClaim, + }, + } + + for _, subTest := range subTests { + subTest := subTest + + success := t.t.Run(subTest.name, func(t *testing.T) { + ht := newHarnessTest(t, net) + + subTest.test(net, ht) + }) + if !success { + return + } + } +} + // testMultiHopHtlcLocalChainClaim tests that in a multi-hop HTLC scenario, if // we force close a channel with an incoming HTLC, and later find out the // preimage via the witness beacon, we properly settle the HTLC on-chain using diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index fb93746b5e..5e7ea5f58a 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -14551,42 +14551,8 @@ var testsCases = []*testCase{ test: testBidirectionalAsyncPayments, }, { - // bob: outgoing our commit timeout - // carol: incoming their commit watch and see timeout - name: "test multi-hop htlc local force close immediate expiry", - test: testMultiHopHtlcLocalTimeout, - }, - { - // bob: outgoing watch and see, they sweep on chain - // carol: incoming our commit, know preimage - name: "test multi-hop htlc receiver chain claim", - test: testMultiHopReceiverChainClaim, - }, - { - // bob: outgoing our commit watch and see timeout - // carol: incoming their commit watch and see timeout - name: "test multi-hop local force close on-chain htlc timeout", - test: testMultiHopLocalForceCloseOnChainHtlcTimeout, - }, - { - // bob: outgoing their commit watch and see timeout - // carol: incoming our commit watch and see timeout - name: "test multi-hop remote force close on-chain htlc timeout", - test: testMultiHopRemoteForceCloseOnChainHtlcTimeout, - }, - { - // bob: outgoing our commit watch and see, they sweep on chain - // bob: incoming our commit watch and learn preimage - // carol: incoming their commit know preimage - name: "test multi-hop htlc local chain claim", - test: testMultiHopHtlcLocalChainClaim, - }, - { - // bob: outgoing their commit watch and see, they sweep on chain - // bob: incoming their commit watch and learn preimage - // carol: incoming our commit know preimage - name: "test multi-hop htlc remote chain claim", - test: testMultiHopHtlcRemoteChainClaim, + name: "test multi-hop htlc", + test: testMultiHopHtlcClaims, }, { name: "switch circuit persistence", From 6ed0c83d115899326a51ce1494eb8ab0be69759f Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:28 +0100 Subject: [PATCH 274/562] itest: spin up new nodes for multi-hop tests This will let us set their commitment type for the subtest. --- ...d_multi-hop_htlc_local_chain_claim_test.go | 86 ++++++++++++++----- .../lnd_multi-hop_htlc_local_timeout_test.go | 25 +++--- ...ulti-hop_htlc_receiver_chain_claim_test.go | 18 ++-- ..._multi-hop_htlc_remote_chain_claim_test.go | 20 +++-- ..._force_close_on_chain_htlc_timeout_test.go | 26 +++--- ..._force_close_on_chain_htlc_timeout_test.go | 22 ++--- 6 files changed, 124 insertions(+), 73 deletions(-) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 868e8974b3..d5eade40f8 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -22,7 +22,8 @@ func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { type testCase struct { name string - test func(net *lntest.NetworkHarness, t *harnessTest) + test func(net *lntest.NetworkHarness, t *harnessTest, alice, + bob *lntest.HarnessNode) } subTests := []testCase{ @@ -66,13 +67,32 @@ func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { }, } + args := []string{} + alice, err := net.NewNode("Alice", args) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + defer shutdownAndAssert(net, t, alice) + + bob, err := net.NewNode("Bob", args) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + defer shutdownAndAssert(net, t, bob) + + ctxb := context.Background() + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + if err := net.ConnectNodes(ctxt, alice, bob); err != nil { + t.Fatalf("unable to connect alice to bob: %v", err) + } + for _, subTest := range subTests { subTest := subTest success := t.t.Run(subTest.name, func(t *testing.T) { ht := newHarnessTest(t, net) - subTest.test(net, ht) + subTest.test(net, ht, alice, bob) }) if !success { return @@ -84,14 +104,16 @@ func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { // we force close a channel with an incoming HTLC, and later find out the // preimage via the witness beacon, we properly settle the HTLC on-chain using // the HTLC success transaction in order to ensure we don't lose any funds. -func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) { +func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, + alice, bob *lntest.HarnessNode) { + ctxb := context.Background() // First, we'll create a three hop network: Alice -> Bob -> Carol, with // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, false, + t, net, alice, bob, false, ) // Clean up carol's node when the test finishes. @@ -122,7 +144,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) ctx, cancel := context.WithCancel(ctxb) defer cancel() - alicePayStream, err := net.Alice.SendPayment(ctx) + alicePayStream, err := alice.SendPayment(ctx) if err != nil { t.Fatalf("unable to create payment stream for alice: %v", err) } @@ -136,7 +158,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) // At this point, all 3 nodes should now have an active channel with // the created HTLC pending on all of them. var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + nodes := []*lntest.HarnessNode{alice, bob, carol} err = wait.Predicate(func() bool { predErr = assertActiveHtlcs(nodes, payHash[:]) if predErr != nil { @@ -157,7 +179,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) // At this point, Bob decides that he wants to exit the channel // immediately, so he force closes his commitment transaction. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - bobForceClose := closeChannelAndAssert(ctxt, t, net, net.Bob, + bobForceClose := closeChannelAndAssert(ctxt, t, net, bob, aliceChanPoint, true) // Alice will sweep her output immediately. @@ -168,7 +190,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) } // Suspend Bob to force Carol to go to chain. - restartBob, err := net.SuspendNode(net.Bob) + restartBob, err := net.SuspendNode(bob) if err != nil { t.Fatalf("unable to suspend bob: %v", err) } @@ -260,7 +282,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) // At this point we suspend Alice to make sure she'll handle the // on-chain settle after a restart. - restartAlice, err := net.SuspendNode(net.Alice) + restartAlice, err := net.SuspendNode(alice) if err != nil { t.Fatalf("unable to suspend alice: %v", err) } @@ -302,7 +324,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) pendingChansRequest := &lnrpc.PendingChannelsRequest{} err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -400,7 +422,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -415,7 +437,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) } req := &lnrpc.ListChannelsRequest{} ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - chanInfo, err := net.Bob.ListChannels(ctxt, req) + chanInfo, err := bob.ListChannels(ctxt, req) if err != nil { predErr = fmt.Errorf("unable to query for open "+ "channels: %v", err) @@ -474,7 +496,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) // succeeded. ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) err = checkPaymentStatus( - ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ctxt, alice, preimage, lnrpc.Payment_SUCCEEDED, ) if err != nil { t.Fatalf(err.Error()) @@ -563,30 +585,48 @@ func checkPaymentStatus(ctxt context.Context, node *lntest.HarnessNode, } func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, - carolHodl bool) (*lnrpc.ChannelPoint, *lnrpc.ChannelPoint, - *lntest.HarnessNode) { + alice, bob *lntest.HarnessNode, carolHodl bool) (*lnrpc.ChannelPoint, + *lnrpc.ChannelPoint, *lntest.HarnessNode) { ctxb := context.Background() + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + err := net.EnsureConnected(ctxt, alice, bob) + if err != nil { + t.Fatalf("unable to connect peers: %v", err) + } + + ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, alice) + if err != nil { + t.Fatalf("unable to send coins to Alice: %v", err) + } + + ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, bob) + if err != nil { + t.Fatalf("unable to send coins to Bob: %v", err) + } + // We'll start the test by creating a channel between Alice and Bob, // which will act as the first leg for out multi-hop HTLC. const chanAmt = 1000000 - ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) aliceChanPoint := openChannelAndAssert( - ctxt, t, net, net.Alice, net.Bob, + ctxt, t, net, alice, bob, lntest.OpenChannelParams{ Amt: chanAmt, }, ) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err := net.Alice.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) + err = alice.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) if err != nil { t.Fatalf("alice didn't report channel: %v", err) } ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.Bob.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) + err = bob.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) if err != nil { t.Fatalf("bob didn't report channel: %v", err) } @@ -603,7 +643,7 @@ func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, t.Fatalf("unable to create new node: %v", err) } ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, net.Bob, carol); err != nil { + if err := net.ConnectNodes(ctxt, bob, carol); err != nil { t.Fatalf("unable to connect bob to carol: %v", err) } @@ -611,13 +651,13 @@ func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, // open, our topology looks like: A -> B -> C. ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) bobChanPoint := openChannelAndAssert( - ctxt, t, net, net.Bob, carol, + ctxt, t, net, bob, carol, lntest.OpenChannelParams{ Amt: chanAmt, }, ) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.Bob.WaitForNetworkChannelOpen(ctxt, bobChanPoint) + err = bob.WaitForNetworkChannelOpen(ctxt, bobChanPoint) if err != nil { t.Fatalf("alice didn't report channel: %v", err) } @@ -627,7 +667,7 @@ func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, t.Fatalf("bob didn't report channel: %v", err) } ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.Alice.WaitForNetworkChannelOpen(ctxt, bobChanPoint) + err = alice.WaitForNetworkChannelOpen(ctxt, bobChanPoint) if err != nil { t.Fatalf("bob didn't report channel: %v", err) } diff --git a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go index 71c6671667..8d6e8fa79c 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go @@ -21,14 +21,17 @@ import ( // it using the HTLC timeout transaction. Any dust HTLC's should be immediately // canceled backwards. Once the timeout has been reached, then we should sweep // it on-chain, and cancel the HTLC backwards. -func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { +func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest, + alice, bob *lntest.HarnessNode) { + ctxb := context.Background() // First, we'll create a three hop network: Alice -> Bob -> Carol, with // Carol refusing to actually settle or directly cancel any HTLC's // self. - aliceChanPoint, bobChanPoint, carol := - createThreeHopNetwork(t, net, true) + aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( + t, net, alice, bob, true, + ) // Clean up carol's node when the test finishes. defer shutdownAndAssert(net, t, carol) @@ -47,7 +50,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { ctx, cancel := context.WithCancel(ctxb) defer cancel() - alicePayStream, err := net.Alice.SendPayment(ctx) + alicePayStream, err := alice.SendPayment(ctx) if err != nil { t.Fatalf("unable to create payment stream for alice: %v", err) } @@ -79,7 +82,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { // Verify that all nodes in the path now have two HTLC's with the // proper parameters. var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + nodes := []*lntest.HarnessNode{alice, bob, carol} err = wait.Predicate(func() bool { predErr = assertActiveHtlcs(nodes, dustPayHash, payHash) if predErr != nil { @@ -125,7 +128,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { // At this point, Bob should have canceled backwards the dust HTLC // that we sent earlier. This means Alice should now only have a single // HTLC on her channel. - nodes = []*lntest.HarnessNode{net.Alice} + nodes = []*lntest.HarnessNode{alice} err = wait.Predicate(func() bool { predErr = assertActiveHtlcs(nodes, payHash) if predErr != nil { @@ -160,7 +163,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { // output pending. pendingChansRequest := &lnrpc.PendingChannelsRequest{} ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels(ctxt, pendingChansRequest) + pendingChanResp, err := bob.PendingChannels(ctxt, pendingChansRequest) if err != nil { t.Fatalf("unable to query for pending channels: %v", err) } @@ -191,7 +194,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { // The block should have confirmed Bob's HTLC timeout transaction. // Therefore, at this point, there should be no active HTLC's on the // commitment transaction from Alice -> Bob. - nodes = []*lntest.HarnessNode{net.Alice} + nodes = []*lntest.HarnessNode{alice} err = wait.Predicate(func() bool { predErr = assertNumActiveHtlcs(nodes, 0) if predErr != nil { @@ -206,7 +209,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { // At this point, Bob should show that the pending HTLC has advanced to // the second stage and is to be swept. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err = net.Bob.PendingChannels(ctxt, pendingChansRequest) + pendingChanResp, err = bob.PendingChannels(ctxt, pendingChansRequest) if err != nil { t.Fatalf("unable to query for pending channels: %v", err) } @@ -225,7 +228,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { // no longer has any pending channels. err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err = net.Bob.PendingChannels(ctxt, pendingChansRequest) + pendingChanResp, err = bob.PendingChannels(ctxt, pendingChansRequest) if err != nil { predErr = fmt.Errorf("unable to query for pending "+ "channels: %v", err) @@ -246,5 +249,5 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) { } ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) + closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, false) } diff --git a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go index 0df3925046..845d799875 100644 --- a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go @@ -24,14 +24,16 @@ import ( // transaction. In this scenario, the node that sent the outgoing HTLC should // extract the preimage from the sweep transaction, and finish settling the // HTLC backwards into the route. -func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) { +func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest, + alice, bob *lntest.HarnessNode) { + ctxb := context.Background() // First, we'll create a three hop network: Alice -> Bob -> Carol, with // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, false, + t, net, alice, bob, false, ) // Clean up carol's node when the test finishes. @@ -62,7 +64,7 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) ctx, cancel := context.WithCancel(ctxb) defer cancel() - alicePayStream, err := net.Alice.SendPayment(ctx) + alicePayStream, err := alice.SendPayment(ctx) if err != nil { t.Fatalf("unable to create payment stream for alice: %v", err) } @@ -76,7 +78,7 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) // At this point, all 3 nodes should now have an active channel with // the created HTLC pending on all of them. var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + nodes := []*lntest.HarnessNode{alice, bob, carol} err = wait.Predicate(func() bool { predErr = assertActiveHtlcs(nodes, payHash[:]) if predErr != nil { @@ -94,7 +96,7 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) // hop logic. waitForInvoiceAccepted(t, carol, payHash) - restartBob, err := net.SuspendNode(net.Bob) + restartBob, err := net.SuspendNode(bob) if err != nil { t.Fatalf("unable to suspend bob: %v", err) } @@ -231,7 +233,7 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) // Once the second-level transaction confirmed, Bob should have // extracted the preimage from the chain, and sent it back to Alice, // clearing the HTLC off-chain. - nodes = []*lntest.HarnessNode{net.Alice} + nodes = []*lntest.HarnessNode{alice} err = wait.Predicate(func() bool { predErr = assertNumActiveHtlcs(nodes, 0) if predErr != nil { @@ -303,7 +305,7 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) // succeeded. ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) err = checkPaymentStatus( - ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ctxt, alice, preimage, lnrpc.Payment_SUCCEEDED, ) if err != nil { t.Fatalf(err.Error()) @@ -312,5 +314,5 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) // We'll close out the channel between Alice and Bob, then shutdown // carol to conclude the test. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) + closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, false) } diff --git a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go index 8c3a1f285f..1a5db70b78 100644 --- a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go @@ -22,14 +22,16 @@ import ( // we found out the preimage via the witness beacon, we properly settle the // HTLC directly on-chain using the preimage in order to ensure that we don't // lose any funds. -func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest) { +func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest, + alice, bob *lntest.HarnessNode) { + ctxb := context.Background() // First, we'll create a three hop network: Alice -> Bob -> Carol, with // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, false, + t, net, alice, bob, false, ) // Clean up carol's node when the test finishes. @@ -59,7 +61,7 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest ctx, cancel := context.WithCancel(ctxb) defer cancel() - alicePayStream, err := net.Alice.SendPayment(ctx) + alicePayStream, err := alice.SendPayment(ctx) if err != nil { t.Fatalf("unable to create payment stream for alice: %v", err) } @@ -73,7 +75,7 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest // At this point, all 3 nodes should now have an active channel with // the created HTLC pending on all of them. var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + nodes := []*lntest.HarnessNode{alice, bob, carol} err = wait.Predicate(func() bool { predErr = assertActiveHtlcs(nodes, payHash[:]) if predErr != nil { @@ -95,12 +97,12 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest // immediately force close the channel by broadcast her commitment // transaction. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - aliceForceClose := closeChannelAndAssert(ctxt, t, net, net.Alice, + aliceForceClose := closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, true) // Wait for the channel to be marked pending force close. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = waitForChannelPendingForceClose(ctxt, net.Alice, aliceChanPoint) + err = waitForChannelPendingForceClose(ctxt, alice, aliceChanPoint) if err != nil { t.Fatalf("channel not pending force close: %v", err) } @@ -119,7 +121,7 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest } // Suspend bob, so Carol is forced to go on chain. - restartBob, err := net.SuspendNode(net.Bob) + restartBob, err := net.SuspendNode(bob) if err != nil { t.Fatalf("unable to suspend bob: %v", err) } @@ -256,7 +258,7 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest pendingChansRequest := &lnrpc.PendingChannelsRequest{} err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -338,7 +340,7 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest // succeeded. ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) err = checkPaymentStatus( - ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ctxt, alice, preimage, lnrpc.Payment_SUCCEEDED, ) if err != nil { t.Fatalf(err.Error()) diff --git a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go index 960ff17d4d..b6a8bcd976 100644 --- a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go @@ -20,14 +20,16 @@ import ( // that's timed out. At this point, the node should timeout the HTLC using the // HTLC timeout transaction, then cancel it backwards as normal. func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, - t *harnessTest) { + t *harnessTest, alice, bob *lntest.HarnessNode) { + ctxb := context.Background() // First, we'll create a three hop network: Alice -> Bob -> Carol, with // Carol refusing to actually settle or directly cancel any HTLC's // self. - aliceChanPoint, bobChanPoint, carol := - createThreeHopNetwork(t, net, true) + aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( + t, net, alice, bob, true, + ) // Clean up carol's node when the test finishes. defer shutdownAndAssert(net, t, carol) @@ -42,7 +44,7 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, ctx, cancel := context.WithCancel(ctxb) defer cancel() - alicePayStream, err := net.Alice.SendPayment(ctx) + alicePayStream, err := alice.SendPayment(ctx) if err != nil { t.Fatalf("unable to create payment stream for alice: %v", err) } @@ -63,7 +65,7 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // Once the HTLC has cleared, all channels in our mini network should // have the it locked in. var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + nodes := []*lntest.HarnessNode{alice, bob, carol} err = wait.Predicate(func() bool { predErr = assertActiveHtlcs(nodes, payHash) if predErr != nil { @@ -80,14 +82,14 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // force close the Bob -> Carol channel. This should trigger contract // resolution mode for both of them. ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Bob, bobChanPoint, true) + closeChannelAndAssert(ctxt, t, net, bob, bobChanPoint, true) // At this point, Bob should have a pending force close channel as he // just went to chain. pendingChansRequest := &lnrpc.PendingChannelsRequest{} err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels(ctxt, + pendingChanResp, err := bob.PendingChannels(ctxt, pendingChansRequest) if err != nil { predErr = fmt.Errorf("unable to query for pending "+ @@ -136,7 +138,7 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // that's now in stage one. err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -183,7 +185,7 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // With the second layer timeout transaction confirmed, Bob should have // canceled backwards the HTLC that carol sent. - nodes = []*lntest.HarnessNode{net.Alice} + nodes = []*lntest.HarnessNode{alice} err = wait.Predicate(func() bool { predErr = assertNumActiveHtlcs(nodes, 0) if predErr != nil { @@ -199,7 +201,7 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // second stage. err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -253,7 +255,7 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // close. err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -274,5 +276,5 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, } ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) + closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, false) } diff --git a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go index 6c6d6eab65..7d9cfa56bf 100644 --- a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go @@ -20,14 +20,16 @@ import ( // transaction once the timeout has expired. Once we sweep the transaction, we // should also cancel back the initial HTLC. func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, - t *harnessTest) { + t *harnessTest, alice, bob *lntest.HarnessNode) { + ctxb := context.Background() // First, we'll create a three hop network: Alice -> Bob -> Carol, with // Carol refusing to actually settle or directly cancel any HTLC's // self. - aliceChanPoint, bobChanPoint, carol := - createThreeHopNetwork(t, net, true) + aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( + t, net, alice, bob, true, + ) // Clean up carol's node when the test finishes. defer shutdownAndAssert(net, t, carol) @@ -43,7 +45,7 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, ctx, cancel := context.WithCancel(ctxb) defer cancel() - alicePayStream, err := net.Alice.SendPayment(ctx) + alicePayStream, err := alice.SendPayment(ctx) if err != nil { t.Fatalf("unable to create payment stream for alice: %v", err) } @@ -64,7 +66,7 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // Once the HTLC has cleared, all the nodes in our mini network should // show that the HTLC has been locked in. var predErr error - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol} + nodes := []*lntest.HarnessNode{alice, bob, carol} err = wait.Predicate(func() bool { predErr = assertActiveHtlcs(nodes, payHash) if predErr != nil { @@ -88,7 +90,7 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, pendingChansRequest := &lnrpc.PendingChannelsRequest{} err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -128,7 +130,7 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // first stage since this is a direct HTLC. err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -191,7 +193,7 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // Now that the sweeping transaction has been confirmed, Bob should // cancel back that HTLC. As a result, Alice should not know of any // active HTLC's. - nodes = []*lntest.HarnessNode{net.Alice} + nodes = []*lntest.HarnessNode{alice} err = wait.Predicate(func() bool { predErr = assertNumActiveHtlcs(nodes, 0) if predErr != nil { @@ -208,7 +210,7 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // he should show no additional pending transactions. err = wait.Predicate(func() bool { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - pendingChanResp, err := net.Bob.PendingChannels( + pendingChanResp, err := bob.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { @@ -232,5 +234,5 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // and then shutting down the new node we created as its no longer // needed. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, aliceChanPoint, false) + closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, false) } From 1ade912361bb422c834984416ac024b0861cf39e Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:28 +0100 Subject: [PATCH 275/562] itest: run multi-hop claim tests for all commit types --- ...d_multi-hop_htlc_local_chain_claim_test.go | 68 ++++++++++++------- .../lnd_multi-hop_htlc_local_timeout_test.go | 4 +- ...ulti-hop_htlc_receiver_chain_claim_test.go | 4 +- ..._multi-hop_htlc_remote_chain_claim_test.go | 4 +- ..._force_close_on_chain_htlc_timeout_test.go | 4 +- ..._force_close_on_chain_htlc_timeout_test.go | 4 +- 6 files changed, 52 insertions(+), 36 deletions(-) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index d5eade40f8..4ebd83e7c2 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd" "github.com/lightningnetwork/lnd/lnrpc" @@ -23,7 +24,7 @@ func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { type testCase struct { name string test func(net *lntest.NetworkHarness, t *harnessTest, alice, - bob *lntest.HarnessNode) + bob *lntest.HarnessNode, c commitType) } subTests := []testCase{ @@ -67,32 +68,47 @@ func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { }, } - args := []string{} - alice, err := net.NewNode("Alice", args) - if err != nil { - t.Fatalf("unable to create new node: %v", err) + commitTypes := []commitType{ + commitTypeLegacy, } - defer shutdownAndAssert(net, t, alice) - bob, err := net.NewNode("Bob", args) - if err != nil { - t.Fatalf("unable to create new node: %v", err) - } - defer shutdownAndAssert(net, t, bob) + for _, commitType := range commitTypes { + testName := fmt.Sprintf("committype=%v", commitType.String()) - ctxb := context.Background() - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, alice, bob); err != nil { - t.Fatalf("unable to connect alice to bob: %v", err) - } + success := t.t.Run(testName, func(t *testing.T) { + ht := newHarnessTest(t, net) - for _, subTest := range subTests { - subTest := subTest + args := commitType.Args() + alice, err := net.NewNode("Alice", args) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + defer shutdownAndAssert(net, ht, alice) - success := t.t.Run(subTest.name, func(t *testing.T) { - ht := newHarnessTest(t, net) + bob, err := net.NewNode("Bob", args) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + defer shutdownAndAssert(net, ht, bob) + + ctxb := context.Background() + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + if err := net.ConnectNodes(ctxt, alice, bob); err != nil { + t.Fatalf("unable to connect alice to bob: %v", err) + } + + for _, subTest := range subTests { + subTest := subTest - subTest.test(net, ht, alice, bob) + success := ht.t.Run(subTest.name, func(t *testing.T) { + ht := newHarnessTest(t, net) + + subTest.test(net, ht, alice, bob, commitType) + }) + if !success { + return + } + } }) if !success { return @@ -105,7 +121,7 @@ func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { // preimage via the witness beacon, we properly settle the HTLC on-chain using // the HTLC success transaction in order to ensure we don't lose any funds. func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, - alice, bob *lntest.HarnessNode) { + alice, bob *lntest.HarnessNode, c commitType) { ctxb := context.Background() @@ -113,7 +129,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, alice, bob, false, + t, net, alice, bob, false, c, ) // Clean up carol's node when the test finishes. @@ -585,8 +601,8 @@ func checkPaymentStatus(ctxt context.Context, node *lntest.HarnessNode, } func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, - alice, bob *lntest.HarnessNode, carolHodl bool) (*lnrpc.ChannelPoint, - *lnrpc.ChannelPoint, *lntest.HarnessNode) { + alice, bob *lntest.HarnessNode, carolHodl bool, c commitType) ( + *lnrpc.ChannelPoint, *lnrpc.ChannelPoint, *lntest.HarnessNode) { ctxb := context.Background() @@ -634,7 +650,7 @@ func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, // Next, we'll create a new node "carol" and have Bob connect to her. If // the carolHodl flag is set, we'll make carol always hold onto the // HTLC, this way it'll force Bob to go to chain to resolve the HTLC. - carolFlags := []string{} + carolFlags := c.Args() if carolHodl { carolFlags = append(carolFlags, "--hodl.exit-settle") } diff --git a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go index 8d6e8fa79c..98b66bda0a 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go @@ -22,7 +22,7 @@ import ( // canceled backwards. Once the timeout has been reached, then we should sweep // it on-chain, and cancel the HTLC backwards. func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest, - alice, bob *lntest.HarnessNode) { + alice, bob *lntest.HarnessNode, c commitType) { ctxb := context.Background() @@ -30,7 +30,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest, // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, alice, bob, true, + t, net, alice, bob, true, c, ) // Clean up carol's node when the test finishes. diff --git a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go index 845d799875..e11b2ed7fa 100644 --- a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go @@ -25,7 +25,7 @@ import ( // extract the preimage from the sweep transaction, and finish settling the // HTLC backwards into the route. func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest, - alice, bob *lntest.HarnessNode) { + alice, bob *lntest.HarnessNode, c commitType) { ctxb := context.Background() @@ -33,7 +33,7 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest, // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, alice, bob, false, + t, net, alice, bob, false, c, ) // Clean up carol's node when the test finishes. diff --git a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go index 1a5db70b78..257b7b9703 100644 --- a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go @@ -23,7 +23,7 @@ import ( // HTLC directly on-chain using the preimage in order to ensure that we don't // lose any funds. func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest, - alice, bob *lntest.HarnessNode) { + alice, bob *lntest.HarnessNode, c commitType) { ctxb := context.Background() @@ -31,7 +31,7 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, alice, bob, false, + t, net, alice, bob, false, c, ) // Clean up carol's node when the test finishes. diff --git a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go index b6a8bcd976..b60cfda4be 100644 --- a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go @@ -20,7 +20,7 @@ import ( // that's timed out. At this point, the node should timeout the HTLC using the // HTLC timeout transaction, then cancel it backwards as normal. func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, - t *harnessTest, alice, bob *lntest.HarnessNode) { + t *harnessTest, alice, bob *lntest.HarnessNode, c commitType) { ctxb := context.Background() @@ -28,7 +28,7 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, alice, bob, true, + t, net, alice, bob, true, c, ) // Clean up carol's node when the test finishes. diff --git a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go index 7d9cfa56bf..2f70fe3cf4 100644 --- a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go @@ -20,7 +20,7 @@ import ( // transaction once the timeout has expired. Once we sweep the transaction, we // should also cancel back the initial HTLC. func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, - t *harnessTest, alice, bob *lntest.HarnessNode) { + t *harnessTest, alice, bob *lntest.HarnessNode, c commitType) { ctxb := context.Background() @@ -28,7 +28,7 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // Carol refusing to actually settle or directly cancel any HTLC's // self. aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork( - t, net, alice, bob, true, + t, net, alice, bob, true, c, ) // Clean up carol's node when the test finishes. From b4ea34037aa873a74ddde56103e8469a883c7c36 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 23 Mar 2020 11:19:18 +0100 Subject: [PATCH 276/562] lntest: move multi-hop root test case and common utils to own file --- ...d_multi-hop_htlc_local_chain_claim_test.go | 271 ----------------- lntest/itest/lnd_multi-hop_test.go | 284 ++++++++++++++++++ 2 files changed, 284 insertions(+), 271 deletions(-) create mode 100644 lntest/itest/lnd_multi-hop_test.go diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 4ebd83e7c2..37634a28b1 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -5,11 +5,9 @@ package itest import ( "context" "fmt" - "testing" "time" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd" "github.com/lightningnetwork/lnd/lnrpc" @@ -19,103 +17,6 @@ import ( "github.com/lightningnetwork/lnd/lntypes" ) -func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { - - type testCase struct { - name string - test func(net *lntest.NetworkHarness, t *harnessTest, alice, - bob *lntest.HarnessNode, c commitType) - } - - subTests := []testCase{ - { - // bob: outgoing our commit timeout - // carol: incoming their commit watch and see timeout - name: "local force close immediate expiry", - test: testMultiHopHtlcLocalTimeout, - }, - { - // bob: outgoing watch and see, they sweep on chain - // carol: incoming our commit, know preimage - name: "receiver chain claim", - test: testMultiHopReceiverChainClaim, - }, - { - // bob: outgoing our commit watch and see timeout - // carol: incoming their commit watch and see timeout - name: "local force close on-chain htlc timeout", - test: testMultiHopLocalForceCloseOnChainHtlcTimeout, - }, - { - // bob: outgoing their commit watch and see timeout - // carol: incoming our commit watch and see timeout - name: "remote force close on-chain htlc timeout", - test: testMultiHopRemoteForceCloseOnChainHtlcTimeout, - }, - { - // bob: outgoing our commit watch and see, they sweep on chain - // bob: incoming our commit watch and learn preimage - // carol: incoming their commit know preimage - name: "local chain claim", - test: testMultiHopHtlcLocalChainClaim, - }, - { - // bob: outgoing their commit watch and see, they sweep on chain - // bob: incoming their commit watch and learn preimage - // carol: incoming our commit know preimage - name: "remote chain claim", - test: testMultiHopHtlcRemoteChainClaim, - }, - } - - commitTypes := []commitType{ - commitTypeLegacy, - } - - for _, commitType := range commitTypes { - testName := fmt.Sprintf("committype=%v", commitType.String()) - - success := t.t.Run(testName, func(t *testing.T) { - ht := newHarnessTest(t, net) - - args := commitType.Args() - alice, err := net.NewNode("Alice", args) - if err != nil { - t.Fatalf("unable to create new node: %v", err) - } - defer shutdownAndAssert(net, ht, alice) - - bob, err := net.NewNode("Bob", args) - if err != nil { - t.Fatalf("unable to create new node: %v", err) - } - defer shutdownAndAssert(net, ht, bob) - - ctxb := context.Background() - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, alice, bob); err != nil { - t.Fatalf("unable to connect alice to bob: %v", err) - } - - for _, subTest := range subTests { - subTest := subTest - - success := ht.t.Run(subTest.name, func(t *testing.T) { - ht := newHarnessTest(t, net) - - subTest.test(net, ht, alice, bob, commitType) - }) - if !success { - return - } - } - }) - if !success { - return - } - } -} - // testMultiHopHtlcLocalChainClaim tests that in a multi-hop HTLC scenario, if // we force close a channel with an incoming HTLC, and later find out the // preimage via the witness beacon, we properly settle the HTLC on-chain using @@ -518,175 +419,3 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, t.Fatalf(err.Error()) } } - -// waitForInvoiceAccepted waits until the specified invoice moved to the -// accepted state by the node. -func waitForInvoiceAccepted(t *harnessTest, node *lntest.HarnessNode, - payHash lntypes.Hash) { - - ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) - defer cancel() - invoiceUpdates, err := node.SubscribeSingleInvoice(ctx, - &invoicesrpc.SubscribeSingleInvoiceRequest{ - RHash: payHash[:], - }, - ) - if err != nil { - t.Fatalf("subscribe single invoice: %v", err) - } - - for { - update, err := invoiceUpdates.Recv() - if err != nil { - t.Fatalf("invoice update err: %v", err) - } - if update.State == lnrpc.Invoice_ACCEPTED { - break - } - } -} - -// checkPaymentStatus asserts that the given node list a payment with the given -// preimage has the expected status. -func checkPaymentStatus(ctxt context.Context, node *lntest.HarnessNode, - preimage lntypes.Preimage, status lnrpc.Payment_PaymentStatus) error { - - req := &lnrpc.ListPaymentsRequest{ - IncludeIncomplete: true, - } - paymentsResp, err := node.ListPayments(ctxt, req) - if err != nil { - return fmt.Errorf("error when obtaining Alice payments: %v", - err) - } - - payHash := preimage.Hash() - var found bool - for _, p := range paymentsResp.Payments { - if p.PaymentHash != payHash.String() { - continue - } - - found = true - if p.Status != status { - return fmt.Errorf("expected payment status "+ - "%v, got %v", status, p.Status) - } - - switch status { - - // If this expected status is SUCCEEDED, we expect the final preimage. - case lnrpc.Payment_SUCCEEDED: - if p.PaymentPreimage != preimage.String() { - return fmt.Errorf("preimage doesn't match: %v vs %v", - p.PaymentPreimage, preimage.String()) - } - - // Otherwise we expect an all-zero preimage. - default: - if p.PaymentPreimage != (lntypes.Preimage{}).String() { - return fmt.Errorf("expected zero preimage, got %v", - p.PaymentPreimage) - } - } - - } - - if !found { - return fmt.Errorf("payment with payment hash %v not found "+ - "in response", payHash) - } - - return nil -} - -func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, - alice, bob *lntest.HarnessNode, carolHodl bool, c commitType) ( - *lnrpc.ChannelPoint, *lnrpc.ChannelPoint, *lntest.HarnessNode) { - - ctxb := context.Background() - - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - err := net.EnsureConnected(ctxt, alice, bob) - if err != nil { - t.Fatalf("unable to connect peers: %v", err) - } - - ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) - err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, alice) - if err != nil { - t.Fatalf("unable to send coins to Alice: %v", err) - } - - ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) - err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, bob) - if err != nil { - t.Fatalf("unable to send coins to Bob: %v", err) - } - - // We'll start the test by creating a channel between Alice and Bob, - // which will act as the first leg for out multi-hop HTLC. - const chanAmt = 1000000 - ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - aliceChanPoint := openChannelAndAssert( - ctxt, t, net, alice, bob, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = alice.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) - if err != nil { - t.Fatalf("alice didn't report channel: %v", err) - } - - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = bob.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) - if err != nil { - t.Fatalf("bob didn't report channel: %v", err) - } - - // Next, we'll create a new node "carol" and have Bob connect to her. If - // the carolHodl flag is set, we'll make carol always hold onto the - // HTLC, this way it'll force Bob to go to chain to resolve the HTLC. - carolFlags := c.Args() - if carolHodl { - carolFlags = append(carolFlags, "--hodl.exit-settle") - } - carol, err := net.NewNode("Carol", carolFlags) - if err != nil { - t.Fatalf("unable to create new node: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, bob, carol); err != nil { - t.Fatalf("unable to connect bob to carol: %v", err) - } - - // We'll then create a channel from Bob to Carol. After this channel is - // open, our topology looks like: A -> B -> C. - ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - bobChanPoint := openChannelAndAssert( - ctxt, t, net, bob, carol, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = bob.WaitForNetworkChannelOpen(ctxt, bobChanPoint) - if err != nil { - t.Fatalf("alice didn't report channel: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = carol.WaitForNetworkChannelOpen(ctxt, bobChanPoint) - if err != nil { - t.Fatalf("bob didn't report channel: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = alice.WaitForNetworkChannelOpen(ctxt, bobChanPoint) - if err != nil { - t.Fatalf("bob didn't report channel: %v", err) - } - - return aliceChanPoint, bobChanPoint, carol -} diff --git a/lntest/itest/lnd_multi-hop_test.go b/lntest/itest/lnd_multi-hop_test.go new file mode 100644 index 0000000000..2d4a9e5f04 --- /dev/null +++ b/lntest/itest/lnd_multi-hop_test.go @@ -0,0 +1,284 @@ +// +build rpctest + +package itest + +import ( + "context" + "fmt" + "testing" + + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" + "github.com/lightningnetwork/lnd/lntest" + "github.com/lightningnetwork/lnd/lntypes" +) + +func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { + + type testCase struct { + name string + test func(net *lntest.NetworkHarness, t *harnessTest, alice, + bob *lntest.HarnessNode, c commitType) + } + + subTests := []testCase{ + { + // bob: outgoing our commit timeout + // carol: incoming their commit watch and see timeout + name: "local force close immediate expiry", + test: testMultiHopHtlcLocalTimeout, + }, + { + // bob: outgoing watch and see, they sweep on chain + // carol: incoming our commit, know preimage + name: "receiver chain claim", + test: testMultiHopReceiverChainClaim, + }, + { + // bob: outgoing our commit watch and see timeout + // carol: incoming their commit watch and see timeout + name: "local force close on-chain htlc timeout", + test: testMultiHopLocalForceCloseOnChainHtlcTimeout, + }, + { + // bob: outgoing their commit watch and see timeout + // carol: incoming our commit watch and see timeout + name: "remote force close on-chain htlc timeout", + test: testMultiHopRemoteForceCloseOnChainHtlcTimeout, + }, + { + // bob: outgoing our commit watch and see, they sweep on chain + // bob: incoming our commit watch and learn preimage + // carol: incoming their commit know preimage + name: "local chain claim", + test: testMultiHopHtlcLocalChainClaim, + }, + { + // bob: outgoing their commit watch and see, they sweep on chain + // bob: incoming their commit watch and learn preimage + // carol: incoming our commit know preimage + name: "remote chain claim", + test: testMultiHopHtlcRemoteChainClaim, + }, + } + + commitTypes := []commitType{ + commitTypeLegacy, + } + + for _, commitType := range commitTypes { + testName := fmt.Sprintf("committype=%v", commitType.String()) + + success := t.t.Run(testName, func(t *testing.T) { + ht := newHarnessTest(t, net) + + args := commitType.Args() + alice, err := net.NewNode("Alice", args) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + defer shutdownAndAssert(net, ht, alice) + + bob, err := net.NewNode("Bob", args) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + defer shutdownAndAssert(net, ht, bob) + + ctxb := context.Background() + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + if err := net.ConnectNodes(ctxt, alice, bob); err != nil { + t.Fatalf("unable to connect alice to bob: %v", err) + } + + for _, subTest := range subTests { + subTest := subTest + + success := ht.t.Run(subTest.name, func(t *testing.T) { + ht := newHarnessTest(t, net) + + subTest.test(net, ht, alice, bob, commitType) + }) + if !success { + return + } + } + }) + if !success { + return + } + } +} + +// waitForInvoiceAccepted waits until the specified invoice moved to the +// accepted state by the node. +func waitForInvoiceAccepted(t *harnessTest, node *lntest.HarnessNode, + payHash lntypes.Hash) { + + ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) + defer cancel() + invoiceUpdates, err := node.SubscribeSingleInvoice(ctx, + &invoicesrpc.SubscribeSingleInvoiceRequest{ + RHash: payHash[:], + }, + ) + if err != nil { + t.Fatalf("subscribe single invoice: %v", err) + } + + for { + update, err := invoiceUpdates.Recv() + if err != nil { + t.Fatalf("invoice update err: %v", err) + } + if update.State == lnrpc.Invoice_ACCEPTED { + break + } + } +} + +// checkPaymentStatus asserts that the given node list a payment with the given +// preimage has the expected status. +func checkPaymentStatus(ctxt context.Context, node *lntest.HarnessNode, + preimage lntypes.Preimage, status lnrpc.Payment_PaymentStatus) error { + + req := &lnrpc.ListPaymentsRequest{ + IncludeIncomplete: true, + } + paymentsResp, err := node.ListPayments(ctxt, req) + if err != nil { + return fmt.Errorf("error when obtaining Alice payments: %v", + err) + } + + payHash := preimage.Hash() + var found bool + for _, p := range paymentsResp.Payments { + if p.PaymentHash != payHash.String() { + continue + } + + found = true + if p.Status != status { + return fmt.Errorf("expected payment status "+ + "%v, got %v", status, p.Status) + } + + switch status { + + // If this expected status is SUCCEEDED, we expect the final preimage. + case lnrpc.Payment_SUCCEEDED: + if p.PaymentPreimage != preimage.String() { + return fmt.Errorf("preimage doesn't match: %v vs %v", + p.PaymentPreimage, preimage.String()) + } + + // Otherwise we expect an all-zero preimage. + default: + if p.PaymentPreimage != (lntypes.Preimage{}).String() { + return fmt.Errorf("expected zero preimage, got %v", + p.PaymentPreimage) + } + } + + } + + if !found { + return fmt.Errorf("payment with payment hash %v not found "+ + "in response", payHash) + } + + return nil +} + +func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, + alice, bob *lntest.HarnessNode, carolHodl bool, c commitType) ( + *lnrpc.ChannelPoint, *lnrpc.ChannelPoint, *lntest.HarnessNode) { + + ctxb := context.Background() + + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + err := net.EnsureConnected(ctxt, alice, bob) + if err != nil { + t.Fatalf("unable to connect peers: %v", err) + } + + ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, alice) + if err != nil { + t.Fatalf("unable to send coins to Alice: %v", err) + } + + ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, bob) + if err != nil { + t.Fatalf("unable to send coins to Bob: %v", err) + } + + // We'll start the test by creating a channel between Alice and Bob, + // which will act as the first leg for out multi-hop HTLC. + const chanAmt = 1000000 + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) + aliceChanPoint := openChannelAndAssert( + ctxt, t, net, alice, bob, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = alice.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) + if err != nil { + t.Fatalf("alice didn't report channel: %v", err) + } + + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = bob.WaitForNetworkChannelOpen(ctxt, aliceChanPoint) + if err != nil { + t.Fatalf("bob didn't report channel: %v", err) + } + + // Next, we'll create a new node "carol" and have Bob connect to her. If + // the carolHodl flag is set, we'll make carol always hold onto the + // HTLC, this way it'll force Bob to go to chain to resolve the HTLC. + carolFlags := c.Args() + if carolHodl { + carolFlags = append(carolFlags, "--hodl.exit-settle") + } + carol, err := net.NewNode("Carol", carolFlags) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + if err := net.ConnectNodes(ctxt, bob, carol); err != nil { + t.Fatalf("unable to connect bob to carol: %v", err) + } + + // We'll then create a channel from Bob to Carol. After this channel is + // open, our topology looks like: A -> B -> C. + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) + bobChanPoint := openChannelAndAssert( + ctxt, t, net, bob, carol, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = bob.WaitForNetworkChannelOpen(ctxt, bobChanPoint) + if err != nil { + t.Fatalf("alice didn't report channel: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = carol.WaitForNetworkChannelOpen(ctxt, bobChanPoint) + if err != nil { + t.Fatalf("bob didn't report channel: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = alice.WaitForNetworkChannelOpen(ctxt, bobChanPoint) + if err != nil { + t.Fatalf("bob didn't report channel: %v", err) + } + + return aliceChanPoint, bobChanPoint, carol +} From 6e4bbc75a06af600c6eddb0f14b71deb29b37359 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Mon, 23 Mar 2020 12:28:28 -0400 Subject: [PATCH 277/562] [Docs] fix defaultBitcoinMinHTLCInMSat comment Comment says default value is 0, when it is in fact 1. --- chainregistry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainregistry.go b/chainregistry.go index 52e87c8a68..97a0e52453 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -38,7 +38,7 @@ import ( const ( // defaultBitcoinMinHTLCMSat is the default smallest value htlc this // node will accept. This value is proposed in the channel open sequence - // and cannot be changed during the life of the channel. It is zero by + // and cannot be changed during the life of the channel. It is 1 msat by // default to allow maximum flexibility in deciding what size payments // to forward. // From 421d73b72e449218d112559340805008aa22ee7b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 16:49:12 -0700 Subject: [PATCH 278/562] channeldb: add new frozen channel type bit and thaw height In this commit, we add a new channel type bit: a frozen channel. A frozen channel is one that can only be cooperatively closed by the responder, but not the initiator. This channel type is useful for certain classes of channel factory like protocols. We then add a new key on the channel bucket level to store the height after which this restriction no longer applies. --- channeldb/channel.go | 80 +++++++++++++++++++++++++++++++++++++++ channeldb/channel_test.go | 3 +- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 65b0f67e44..27f8887c69 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -102,6 +102,11 @@ var ( // channel closure. This key should be accessed from within the // sub-bucket of a target channel, identified by its channel point. revocationLogBucket = []byte("revocation-log-key") + + // frozenChanKey is the key where we store the information for any + // active "frozen" channels. This key is present only in the leaf + // bucket for a given channel. + frozenChanKey = []byte("frozen-chans") ) var ( @@ -191,6 +196,11 @@ const ( // channel type also uses a delayed to_remote output script. If bit is // set, we'll find the size of the anchor outputs in the database. AnchorOutputsBit ChannelType = 1 << 3 + + // FrozenBit indicates that the channel is a frozen channel, meaning + // that only the responder can decide to cooperatively close the + // channel. + FrozenBit ChannelType = 1 << 4 ) // IsSingleFunder returns true if the channel type if one of the known single @@ -222,6 +232,13 @@ func (c ChannelType) HasAnchors() bool { return c&AnchorOutputsBit == AnchorOutputsBit } +// IsFrozen returns true if the channel is considered to be "frozen". A frozen +// channel means that only the responder can initiate a cooperative channel +// closure. +func (c ChannelType) IsFrozen() bool { + return c&FrozenBit == FrozenBit +} + // ChannelConstraints represents a set of constraints meant to allow a node to // limit their exposure, enact flow control and ensure that all HTLCs are // economically relevant. This struct will be mirrored for both sides of the @@ -635,6 +652,11 @@ type OpenChannel struct { // was not set, the field is empty. RemoteShutdownScript lnwire.DeliveryAddress + // ThawHeight is the height when a frozen channel once again becomes a + // normal channel. If this is zero, then there're no restrictions on + // this channel. + ThawHeight uint32 + // TODO(roasbeef): eww Db *DB @@ -1229,6 +1251,17 @@ func putOpenChannel(chanBucket kvdb.RwBucket, channel *OpenChannel) error { return fmt.Errorf("unable to store chan commitments: %v", err) } + // Next, if this is a frozen channel, we'll add in the axillary + // information we need to store. + if channel.ChanType.IsFrozen() { + err := storeThawHeight( + chanBucket, channel.ThawHeight, + ) + if err != nil { + return fmt.Errorf("unable to store thaw height: %v", err) + } + } + // Finally, we'll write out the revocation state for both parties // within a distinct key space. if err := putChanRevocationState(chanBucket, channel); err != nil { @@ -1259,6 +1292,18 @@ func fetchOpenChannel(chanBucket kvdb.ReadBucket, return nil, fmt.Errorf("unable to fetch chan commitments: %v", err) } + // Next, if this is a frozen channel, we'll add in the axillary + // information we need to store. + if channel.ChanType.IsFrozen() { + thawHeight, err := fetchThawHeight(chanBucket) + if err != nil { + return nil, fmt.Errorf("unable to store thaw "+ + "height: %v", err) + } + + channel.ThawHeight = thawHeight + } + // Finally, we'll retrieve the current revocation state so we can // properly if err := fetchChanRevocationState(chanBucket, channel); err != nil { @@ -2517,6 +2562,15 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary, return err } + // We'll also remove the channel from the frozen channel bucket + // if we need to. + if c.ChanType.IsFrozen() { + err := deleteThawHeight(chanBucket) + if err != nil { + return err + } + } + // With the base channel data deleted, attempt to delete the // information stored within the revocation log. logBucket := chanBucket.NestedReadWriteBucket(revocationLogBucket) @@ -3213,3 +3267,29 @@ func fetchChannelLogEntry(log kvdb.ReadBucket, commitReader := bytes.NewReader(commitBytes) return deserializeChanCommit(commitReader) } + +func fetchThawHeight(chanBucket kvdb.ReadBucket) (uint32, error) { + var height uint32 + + heightBytes := chanBucket.Get(frozenChanKey) + heightReader := bytes.NewReader(heightBytes) + + if err := ReadElements(heightReader, &height); err != nil { + return 0, err + } + + return height, nil +} + +func storeThawHeight(chanBucket kvdb.RwBucket, height uint32) error { + var heightBuf bytes.Buffer + if err := WriteElements(&heightBuf, height); err != nil { + return err + } + + return chanBucket.Put(frozenChanKey, heightBuf.Bytes()) +} + +func deleteThawHeight(chanBucket kvdb.RwBucket) error { + return chanBucket.Delete(frozenChanKey) +} diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index 2d143437f9..eb068485e5 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -349,7 +349,7 @@ func createTestChannelState(t *testing.T, cdb *DB) *OpenChannel { chanID := lnwire.NewShortChanIDFromInt(uint64(rand.Int63())) return &OpenChannel{ - ChanType: SingleFunderBit, + ChanType: SingleFunderBit | FrozenBit, ChainHash: key, FundingOutpoint: wire.OutPoint{Hash: key, Index: rand.Uint32()}, ShortChannelID: chanID, @@ -387,6 +387,7 @@ func createTestChannelState(t *testing.T, cdb *DB) *OpenChannel { Db: cdb, Packager: NewChannelPackager(chanID), FundingTxn: testTx, + ThawHeight: uint32(defaultPendingHeight), } } From dbc485f72477f6e84e1945d093fb52386db5d5f3 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 16:49:40 -0700 Subject: [PATCH 279/562] lnrpc: add thaw_height to Channel and ChanPointShim --- lnrpc/rpc.pb.go | 1448 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 17 + lnrpc/rpc.swagger.json | 10 + 3 files changed, 765 insertions(+), 710 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index edf18f53d6..fcc66a4d41 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -3086,7 +3086,14 @@ type Channel struct { //not push any funds to the remote peer. If the initiator field is true, we //pushed this amount to our peer, if it is false, the remote peer pushed this //amount to us. - PushAmountSat uint64 `protobuf:"varint,27,opt,name=push_amount_sat,json=pushAmountSat,proto3" json:"push_amount_sat,omitempty"` + PushAmountSat uint64 `protobuf:"varint,27,opt,name=push_amount_sat,json=pushAmountSat,proto3" json:"push_amount_sat,omitempty"` + //* + //This uint32 indicates if this channel is to be considered 'frozen'. A + //frozen channel doest not allow a cooperative channel close by the + //initiator. The thaw_height is the height that this restriction stops + //applying to the channel. This field is optional, not setting it or using a + //value of zero will mean the channel has no additional restrictions. + ThawHeight uint32 `protobuf:"varint,28,opt,name=thaw_height,json=thawHeight,proto3" json:"thaw_height,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -3307,6 +3314,13 @@ func (m *Channel) GetPushAmountSat() uint64 { return 0 } +func (m *Channel) GetThawHeight() uint32 { + if m != nil { + return m.ThawHeight + } + return 0 +} + type ListChannelsRequest struct { ActiveOnly bool `protobuf:"varint,1,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` InactiveOnly bool `protobuf:"varint,2,opt,name=inactive_only,json=inactiveOnly,proto3" json:"inactive_only,omitempty"` @@ -5036,7 +5050,13 @@ type ChanPointShim struct { //protocol to initate the funding request. This is an optional field, and //should only be set if the responder is already expecting a specific pending //channel ID. - PendingChanId []byte `protobuf:"bytes,5,opt,name=pending_chan_id,json=pendingChanId,proto3" json:"pending_chan_id,omitempty"` + PendingChanId []byte `protobuf:"bytes,5,opt,name=pending_chan_id,json=pendingChanId,proto3" json:"pending_chan_id,omitempty"` + //* + //This uint32 indicates if this channel is to be considered 'frozen'. A + //frozen channel does not allow a cooperative channel close by the + //initiator. The thaw_height is the height that this restriction stops + //applying to the channel. + ThawHeight uint32 `protobuf:"varint,6,opt,name=thaw_height,json=thawHeight,proto3" json:"thaw_height,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5102,6 +5122,13 @@ func (m *ChanPointShim) GetPendingChanId() []byte { return nil } +func (m *ChanPointShim) GetThawHeight() uint32 { + if m != nil { + return m.ThawHeight + } + return 0 +} + type FundingShim struct { // Types that are valid to be assigned to Shim: // *FundingShim_ChanPointShim @@ -11339,718 +11366,719 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11364 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x8f, 0x24, 0x47, - 0x76, 0x18, 0x3c, 0x75, 0xeb, 0xaa, 0x3a, 0x75, 0xed, 0xe8, 0x5b, 0x4d, 0x0f, 0x87, 0x33, 0x4c, - 0x72, 0xc9, 0xd9, 0xe1, 0x6e, 0xcf, 0x70, 0x76, 0xc9, 0x5d, 0x91, 0x9f, 0x56, 0x5b, 0xdd, 0x5d, - 0x3d, 0x5d, 0x3b, 0x7d, 0x63, 0x56, 0x35, 0x29, 0xae, 0x3e, 0x39, 0x37, 0xbb, 0x2a, 0xba, 0x3b, - 0x35, 0x55, 0x99, 0xc5, 0xcc, 0xac, 0xbe, 0xec, 0x82, 0x7e, 0x30, 0x6c, 0xc1, 0x30, 0x6c, 0x03, - 0x82, 0x2d, 0xc3, 0x96, 0x2d, 0xd8, 0xb0, 0x61, 0x18, 0x86, 0x01, 0x41, 0xc6, 0xca, 0x80, 0x1f, - 0xfc, 0xae, 0x17, 0x1b, 0x82, 0x21, 0xf9, 0xc5, 0x10, 0x04, 0xc8, 0x97, 0xf5, 0x9b, 0xe1, 0x9f, - 0x60, 0xc4, 0x39, 0x11, 0x99, 0x91, 0x55, 0xd9, 0x33, 0xc3, 0x5d, 0x7a, 0x5f, 0x66, 0x3a, 0x4f, - 0x9c, 0xb8, 0x9f, 0x38, 0x71, 0xae, 0x51, 0x50, 0xf6, 0x27, 0x83, 0x8d, 0x89, 0xef, 0x85, 0x1e, - 0x2b, 0x8c, 0x5c, 0x7f, 0x32, 0x58, 0x7f, 0xed, 0xcc, 0xf3, 0xce, 0x46, 0xfc, 0x91, 0x3d, 0x71, - 0x1e, 0xd9, 0xae, 0xeb, 0x85, 0x76, 0xe8, 0x78, 0x6e, 0x40, 0x48, 0xc6, 0x8f, 0xa0, 0xfe, 0x94, - 0xbb, 0x3d, 0xce, 0x87, 0x26, 0xff, 0x7c, 0xca, 0x83, 0x90, 0xbd, 0x0b, 0x8b, 0x36, 0xff, 0x31, - 0xe7, 0x43, 0x6b, 0x62, 0x07, 0xc1, 0xe4, 0xdc, 0xb7, 0x03, 0xde, 0xca, 0xdc, 0xcf, 0x3c, 0xa8, - 0x9a, 0x4d, 0x2a, 0x38, 0x8a, 0xe0, 0xec, 0x0d, 0xa8, 0x06, 0x02, 0x95, 0xbb, 0xa1, 0xef, 0x4d, - 0xae, 0x5b, 0x59, 0xc4, 0xab, 0x08, 0x58, 0x87, 0x40, 0xc6, 0x08, 0x1a, 0x51, 0x0f, 0xc1, 0xc4, - 0x73, 0x03, 0xce, 0x1e, 0xc3, 0xf2, 0xc0, 0x99, 0x9c, 0x73, 0xdf, 0xc2, 0xca, 0x63, 0x97, 0x8f, - 0x3d, 0xd7, 0x19, 0xb4, 0x32, 0xf7, 0x73, 0x0f, 0xca, 0x26, 0xa3, 0x32, 0x51, 0x63, 0x5f, 0x96, - 0xb0, 0x77, 0xa0, 0xc1, 0x5d, 0x82, 0xf3, 0x21, 0xd6, 0x92, 0x5d, 0xd5, 0x63, 0xb0, 0xa8, 0x60, - 0xfc, 0xcd, 0x2c, 0x2c, 0x76, 0x5d, 0x27, 0xfc, 0xd4, 0x1e, 0x8d, 0x78, 0xa8, 0xe6, 0xf4, 0x0e, - 0x34, 0x2e, 0x11, 0x80, 0x73, 0xba, 0xf4, 0xfc, 0xa1, 0x9c, 0x51, 0x9d, 0xc0, 0x47, 0x12, 0x7a, - 0xe3, 0xc8, 0xb2, 0x37, 0x8e, 0x2c, 0x75, 0xb9, 0x72, 0x37, 0x2c, 0xd7, 0x3b, 0xd0, 0xf0, 0xf9, - 0xc0, 0xbb, 0xe0, 0xfe, 0xb5, 0x75, 0xe9, 0xb8, 0x43, 0xef, 0xb2, 0x95, 0xbf, 0x9f, 0x79, 0x50, - 0x30, 0xeb, 0x0a, 0xfc, 0x29, 0x42, 0xd9, 0x26, 0x34, 0x06, 0xe7, 0xb6, 0xeb, 0xf2, 0x91, 0x75, - 0x62, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xab, 0x70, 0x3f, 0xf3, 0xa0, 0xf2, 0xe4, 0xf6, 0x06, 0xee, - 0xea, 0xc6, 0xd6, 0xb9, 0xed, 0x6e, 0x62, 0x49, 0xcf, 0xb5, 0x27, 0xc1, 0xb9, 0x17, 0x9a, 0x75, - 0x59, 0x83, 0xc0, 0x81, 0xb1, 0x0c, 0x4c, 0x5f, 0x09, 0x5a, 0x7b, 0xe3, 0xdf, 0x64, 0x60, 0xe9, - 0xd8, 0x1d, 0x79, 0x83, 0xe7, 0x3f, 0xe7, 0x12, 0xa5, 0xcc, 0x21, 0xfb, 0xaa, 0x73, 0xc8, 0x7d, - 0xd9, 0x39, 0xac, 0xc2, 0x72, 0x72, 0xb0, 0x72, 0x16, 0x1c, 0x56, 0x44, 0xed, 0x33, 0xae, 0x86, - 0xa5, 0xa6, 0xf1, 0x75, 0x68, 0x0e, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x79, 0x34, 0x24, 0x3c, 0x9a, - 0xc8, 0x1b, 0x50, 0x75, 0xf9, 0x65, 0x8c, 0x26, 0x69, 0xd7, 0xe5, 0x97, 0x0a, 0xc5, 0x68, 0xc1, - 0xea, 0x6c, 0x37, 0x72, 0x00, 0x3f, 0xcb, 0x40, 0xfe, 0x38, 0xbc, 0xf2, 0xd8, 0xfb, 0x50, 0xb5, - 0x87, 0x43, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x4f, 0xe8, 0xa4, 0xd4, 0x9f, 0x30, 0x39, 0xc5, 0x36, - 0x15, 0xf5, 0xaf, 0x27, 0xdc, 0xac, 0xd8, 0xf1, 0x07, 0x6b, 0x41, 0x51, 0x7e, 0x62, 0xbf, 0x65, - 0x53, 0x7d, 0xb2, 0xbb, 0x00, 0xf6, 0xd8, 0x9b, 0xba, 0xa1, 0x15, 0xd8, 0x21, 0xae, 0x58, 0xce, - 0x2c, 0x13, 0xa4, 0x67, 0x87, 0xec, 0x0e, 0x94, 0x27, 0xcf, 0xad, 0x60, 0xe0, 0x3b, 0x93, 0x10, - 0x89, 0xa7, 0x6c, 0x96, 0x26, 0xcf, 0x7b, 0xf8, 0xcd, 0xde, 0x85, 0x92, 0x37, 0x0d, 0x27, 0x9e, - 0xe3, 0x86, 0x92, 0x5e, 0x1a, 0x72, 0x20, 0x87, 0xd3, 0xf0, 0x48, 0x80, 0xcd, 0x08, 0x81, 0xbd, - 0x05, 0xb5, 0x81, 0xe7, 0x9e, 0x3a, 0xfe, 0x98, 0x38, 0x42, 0x6b, 0x01, 0xfb, 0x4a, 0x02, 0x8d, - 0x3f, 0xcc, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, 0x41, 0x31, 0xbc, 0xb2, - 0xce, 0xed, 0xe0, 0x1c, 0xa7, 0x5a, 0x36, 0x17, 0xc2, 0xab, 0x5d, 0x3b, 0x38, 0x67, 0xab, 0xb0, - 0x40, 0xa3, 0xc4, 0x09, 0xe5, 0x4c, 0xf9, 0x25, 0x0e, 0x88, 0x3b, 0x1d, 0x5b, 0xc9, 0xae, 0x72, - 0x48, 0x31, 0x4d, 0x77, 0x3a, 0xde, 0xd2, 0xe1, 0x62, 0xf2, 0x27, 0x62, 0xbb, 0xa9, 0x03, 0x9a, - 0x5e, 0x19, 0x21, 0xd8, 0xc7, 0x1b, 0x50, 0x95, 0xc5, 0xdc, 0x39, 0x3b, 0xa7, 0x39, 0x16, 0xcc, - 0x0a, 0x21, 0x20, 0x48, 0xb4, 0x10, 0x3a, 0x63, 0x6e, 0x05, 0xa1, 0x3d, 0x9e, 0xc8, 0x29, 0x95, - 0x05, 0xa4, 0x27, 0x00, 0x58, 0xec, 0x85, 0xf6, 0xc8, 0x3a, 0xe5, 0x3c, 0x68, 0x15, 0x65, 0xb1, - 0x80, 0xec, 0x70, 0x1e, 0xb0, 0xaf, 0x41, 0x7d, 0xc8, 0x83, 0xd0, 0x92, 0x9b, 0xc1, 0x83, 0x56, - 0x09, 0x4f, 0x7e, 0x4d, 0x40, 0xdb, 0x0a, 0xc8, 0x5e, 0x03, 0xf0, 0xed, 0x4b, 0x4b, 0x2c, 0x04, - 0xbf, 0x6a, 0x95, 0x69, 0x17, 0x7c, 0xfb, 0xb2, 0x7f, 0xb5, 0xcb, 0xaf, 0x04, 0xd5, 0x3c, 0xe5, - 0xa1, 0xb6, 0x68, 0x81, 0xa4, 0x4e, 0x63, 0x0f, 0x98, 0x06, 0xde, 0xe6, 0xa1, 0xed, 0x8c, 0x02, - 0xf6, 0x01, 0x54, 0x43, 0x0d, 0x19, 0xd9, 0x60, 0x25, 0x22, 0x21, 0xad, 0x82, 0x99, 0xc0, 0x33, - 0xce, 0xa1, 0xb4, 0xc3, 0xf9, 0x9e, 0x33, 0x76, 0x42, 0xb6, 0x0a, 0x85, 0x53, 0xe7, 0x8a, 0x13, - 0xb1, 0xe7, 0x76, 0x6f, 0x99, 0xf4, 0xc9, 0xee, 0x01, 0xe0, 0x1f, 0xd6, 0x38, 0xa2, 0xa6, 0xdd, - 0x5b, 0x66, 0x19, 0x61, 0xfb, 0x81, 0x1d, 0xb2, 0x75, 0x28, 0x4e, 0xb8, 0x3f, 0xe0, 0x6a, 0xdf, - 0x76, 0x6f, 0x99, 0x0a, 0xb0, 0x59, 0x84, 0xc2, 0x48, 0xb4, 0x6e, 0xfc, 0x71, 0x01, 0x2a, 0x3d, - 0xee, 0x46, 0xa7, 0x8c, 0x41, 0x5e, 0x2c, 0x88, 0x3c, 0x59, 0xf8, 0x37, 0x7b, 0x13, 0x2a, 0xb8, - 0x74, 0x41, 0xe8, 0x3b, 0xee, 0x19, 0x51, 0xf5, 0x66, 0xb6, 0x95, 0x31, 0x41, 0x80, 0x7b, 0x08, - 0x65, 0x4d, 0xc8, 0xd9, 0x63, 0x45, 0xd5, 0xe2, 0x4f, 0x76, 0x1b, 0x4a, 0xf6, 0x38, 0xa4, 0xe1, - 0x55, 0x11, 0x5c, 0xb4, 0xc7, 0x21, 0x0e, 0xed, 0x0d, 0xa8, 0x4e, 0xec, 0xeb, 0xb1, 0x38, 0xcb, - 0x11, 0x39, 0x54, 0xcd, 0x8a, 0x84, 0x21, 0x41, 0x3c, 0x81, 0x25, 0x1d, 0x45, 0x75, 0x5e, 0x88, - 0x3a, 0x5f, 0xd4, 0xb0, 0xe5, 0x18, 0xde, 0x81, 0x86, 0xaa, 0xe3, 0xd3, 0x7c, 0x90, 0x4c, 0xca, - 0x66, 0x5d, 0x82, 0xd5, 0x2c, 0x1f, 0x40, 0xf3, 0xd4, 0x71, 0xed, 0x91, 0x35, 0x18, 0x85, 0x17, - 0xd6, 0x90, 0x8f, 0x42, 0x1b, 0x29, 0xa6, 0x60, 0xd6, 0x11, 0xbe, 0x35, 0x0a, 0x2f, 0xb6, 0x05, - 0x94, 0x7d, 0x03, 0xca, 0xa7, 0x9c, 0x5b, 0xb8, 0x58, 0xad, 0x52, 0xe2, 0xe0, 0xa9, 0x1d, 0x32, - 0x4b, 0xa7, 0x6a, 0xaf, 0xbe, 0x01, 0x4d, 0x6f, 0x1a, 0x9e, 0x79, 0x8e, 0x7b, 0x66, 0x09, 0x7e, - 0x67, 0x39, 0x43, 0xa4, 0xa1, 0xfc, 0x66, 0xf6, 0x71, 0xc6, 0xac, 0xab, 0x32, 0xc1, 0x79, 0xba, - 0x43, 0xf6, 0x36, 0x34, 0x46, 0x76, 0x10, 0x5a, 0xe7, 0xde, 0xc4, 0x9a, 0x4c, 0x4f, 0x9e, 0xf3, - 0xeb, 0x56, 0x0d, 0x17, 0xa2, 0x26, 0xc0, 0xbb, 0xde, 0xe4, 0x08, 0x81, 0x82, 0xb2, 0x71, 0x9c, - 0x34, 0x08, 0xb8, 0x9f, 0x79, 0x50, 0x33, 0xcb, 0x02, 0x42, 0x9d, 0x7e, 0x06, 0x4b, 0xb8, 0x3d, - 0x83, 0x69, 0x10, 0x7a, 0x63, 0x4b, 0xf0, 0x6a, 0x7f, 0x18, 0xb4, 0x2a, 0x48, 0x6b, 0x5f, 0x97, - 0x83, 0xd5, 0xf6, 0x78, 0x63, 0x9b, 0x07, 0xe1, 0x16, 0x22, 0x9b, 0x84, 0x2b, 0x2e, 0xf4, 0x6b, - 0x73, 0x71, 0x38, 0x0b, 0x67, 0xdf, 0x00, 0x66, 0x8f, 0x46, 0xde, 0xa5, 0x15, 0xf0, 0xd1, 0xa9, - 0x25, 0x17, 0xb1, 0x55, 0xbf, 0x9f, 0x79, 0x50, 0x32, 0x9b, 0x58, 0xd2, 0xe3, 0xa3, 0xd3, 0x23, - 0x82, 0xb3, 0x0f, 0x00, 0x0f, 0x93, 0x75, 0xca, 0xed, 0x70, 0xea, 0xf3, 0xa0, 0xd5, 0xb8, 0x9f, - 0x7b, 0x50, 0x7f, 0xb2, 0x18, 0xad, 0x17, 0x82, 0x37, 0x9d, 0xd0, 0xac, 0x0a, 0x3c, 0xf9, 0x1d, - 0xac, 0x6f, 0xc3, 0x6a, 0xfa, 0x90, 0x04, 0x51, 0x89, 0x55, 0x11, 0xc4, 0x98, 0x37, 0xc5, 0x9f, - 0x6c, 0x19, 0x0a, 0x17, 0xf6, 0x68, 0xca, 0x25, 0x4f, 0xa7, 0x8f, 0x0f, 0xb3, 0xdf, 0xcd, 0x18, - 0x7f, 0x94, 0x81, 0x2a, 0xcd, 0x52, 0xca, 0x22, 0x6f, 0x42, 0x4d, 0x51, 0x03, 0xf7, 0x7d, 0xcf, - 0x97, 0x5c, 0x4d, 0x51, 0x5e, 0x47, 0xc0, 0xc4, 0xad, 0xa2, 0x90, 0x26, 0x3e, 0x77, 0xc6, 0xf6, - 0x99, 0x6a, 0x5a, 0x91, 0xd2, 0x91, 0x04, 0xb3, 0xf7, 0xe2, 0xf6, 0x7c, 0x6f, 0x1a, 0x72, 0x79, - 0xe7, 0x55, 0xe5, 0xf4, 0x4c, 0x01, 0x8b, 0x5a, 0xc7, 0xaf, 0x57, 0xa0, 0x73, 0xe3, 0x77, 0x33, - 0xc0, 0xc4, 0xb0, 0xfb, 0x1e, 0x35, 0x20, 0x29, 0x74, 0xb6, 0x66, 0xe6, 0x95, 0x4f, 0x48, 0xf6, - 0x45, 0x27, 0xc4, 0x80, 0x02, 0x8d, 0x3d, 0x9f, 0x32, 0x76, 0x2a, 0xfa, 0x41, 0xbe, 0x94, 0x6b, - 0xe6, 0x8d, 0xff, 0x9a, 0x83, 0xe5, 0x2d, 0xba, 0xb2, 0xdb, 0x83, 0x01, 0x9f, 0x44, 0x67, 0xe7, - 0x1e, 0x54, 0x5c, 0x6f, 0xc8, 0x15, 0xc5, 0xd2, 0xc0, 0x40, 0x80, 0x34, 0x72, 0x3d, 0xb7, 0x1d, - 0x97, 0x06, 0x4e, 0x8b, 0x59, 0x46, 0x08, 0x0e, 0xfb, 0x6d, 0x68, 0x4c, 0xb8, 0x3b, 0xd4, 0x8f, - 0x08, 0x09, 0x55, 0x35, 0x09, 0x96, 0xa7, 0xe3, 0x1e, 0x54, 0x4e, 0xa7, 0x84, 0x27, 0x18, 0x4b, - 0x1e, 0x69, 0x00, 0x24, 0xa8, 0x4d, 0xfc, 0x65, 0x32, 0x0d, 0xce, 0xb1, 0xb4, 0x80, 0xa5, 0x45, - 0xf1, 0x2d, 0x8a, 0xee, 0x02, 0x0c, 0xa7, 0x41, 0x28, 0x4f, 0xcc, 0x02, 0x16, 0x96, 0x05, 0x84, - 0x4e, 0xcc, 0x37, 0x61, 0x69, 0x6c, 0x5f, 0x59, 0x48, 0x3b, 0x96, 0xe3, 0x5a, 0xa7, 0x23, 0xbc, - 0x73, 0x8a, 0x88, 0xd7, 0x1c, 0xdb, 0x57, 0x9f, 0x88, 0x92, 0xae, 0xbb, 0x83, 0x70, 0xc1, 0x56, - 0x94, 0xb8, 0xe3, 0xf3, 0x80, 0xfb, 0x17, 0x1c, 0x39, 0x41, 0x3e, 0x92, 0x69, 0x4c, 0x82, 0x8a, - 0x11, 0x8d, 0xc5, 0xbc, 0xc3, 0xd1, 0x80, 0x8e, 0xbd, 0x59, 0x1c, 0x3b, 0xee, 0x6e, 0x38, 0x1a, - 0x88, 0x7b, 0x45, 0xf0, 0x91, 0x09, 0xf7, 0xad, 0xe7, 0x97, 0x78, 0x86, 0xf3, 0xc8, 0x37, 0x8e, - 0xb8, 0xff, 0xec, 0x52, 0x5c, 0xfd, 0x83, 0x00, 0x19, 0x91, 0x7d, 0xdd, 0xaa, 0xe0, 0x01, 0x2f, - 0x0d, 0x02, 0xc1, 0x82, 0xec, 0x6b, 0x71, 0x08, 0xc5, 0x68, 0x6d, 0xdc, 0x05, 0x3e, 0xc4, 0xe6, - 0x03, 0xe4, 0xa8, 0x35, 0x1c, 0x6c, 0x5b, 0x16, 0x88, 0x7e, 0x02, 0x41, 0xf5, 0x6a, 0xb0, 0xa7, - 0x23, 0xfb, 0x2c, 0x40, 0x96, 0x52, 0x33, 0xab, 0x12, 0xb8, 0x23, 0x60, 0xc6, 0xa7, 0x24, 0x64, - 0x69, 0x7b, 0x2b, 0xcf, 0x8c, 0xb8, 0xea, 0x11, 0x82, 0xfb, 0x5a, 0x32, 0xe5, 0x57, 0xda, 0xa6, - 0x65, 0x53, 0x36, 0xcd, 0xf8, 0xfd, 0x0c, 0x54, 0x65, 0xcb, 0x28, 0x94, 0xb0, 0x0d, 0x60, 0x6a, - 0x17, 0xc3, 0x2b, 0x67, 0x68, 0x9d, 0x5c, 0x87, 0x3c, 0x20, 0xa2, 0xd9, 0xbd, 0x65, 0x36, 0x65, - 0x59, 0xff, 0xca, 0x19, 0x6e, 0x8a, 0x12, 0xf6, 0x10, 0x9a, 0x09, 0xfc, 0x20, 0xf4, 0x89, 0xa2, - 0x77, 0x6f, 0x99, 0x75, 0x0d, 0xbb, 0x17, 0xfa, 0xe2, 0x8c, 0x08, 0x91, 0x67, 0x1a, 0x5a, 0x8e, - 0x3b, 0xe4, 0x57, 0x48, 0x46, 0x35, 0xb3, 0x42, 0xb0, 0xae, 0x00, 0x6d, 0xd6, 0xa1, 0xaa, 0x37, - 0x67, 0x9c, 0x41, 0x49, 0xc9, 0x4b, 0x28, 0x30, 0xcc, 0x0c, 0xc9, 0x2c, 0x87, 0xd1, 0x48, 0x6e, - 0x43, 0x29, 0x39, 0x02, 0xb3, 0x18, 0xbe, 0x72, 0xc7, 0xc6, 0xf7, 0xa0, 0xb9, 0x27, 0x88, 0xc7, - 0x15, 0xc4, 0x2a, 0xe5, 0xbf, 0x55, 0x58, 0xd0, 0x0e, 0x4d, 0xd9, 0x94, 0x5f, 0xe2, 0xce, 0x3d, - 0xf7, 0x82, 0x50, 0xf6, 0x82, 0x7f, 0x1b, 0x7f, 0x9c, 0x01, 0xd6, 0x09, 0x42, 0x67, 0x6c, 0x87, - 0x7c, 0x87, 0x47, 0x6c, 0xe1, 0x10, 0xaa, 0xa2, 0xb5, 0xbe, 0xd7, 0x26, 0x81, 0x8c, 0x04, 0x8a, - 0x77, 0xe5, 0x31, 0x9e, 0xaf, 0xb0, 0xa1, 0x63, 0x13, 0x9b, 0x4f, 0x34, 0x20, 0x4e, 0x59, 0x68, - 0xfb, 0x67, 0x3c, 0x44, 0x31, 0x4e, 0xca, 0xfb, 0x40, 0x20, 0x21, 0xc0, 0xad, 0xff, 0x1a, 0x2c, - 0xce, 0xb5, 0xa1, 0xf3, 0xe5, 0x72, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, 0x82, 0xa5, 0xc4, 0xb8, - 0x24, 0xa5, 0xad, 0x41, 0x51, 0x1c, 0x08, 0x21, 0x1c, 0x64, 0x48, 0xaa, 0x3c, 0xe5, 0x5c, 0x88, - 0xc1, 0x8f, 0x60, 0xf9, 0x94, 0x73, 0xdf, 0x0e, 0xb1, 0x10, 0x4f, 0x8c, 0xd8, 0x21, 0xd9, 0xf0, - 0xa2, 0x2c, 0xeb, 0xd9, 0xe1, 0x11, 0xf7, 0xc5, 0x4e, 0x19, 0xff, 0x3d, 0x03, 0x0d, 0xc1, 0x41, - 0xf7, 0x6d, 0xf7, 0x5a, 0xad, 0xd3, 0x5e, 0xea, 0x3a, 0x3d, 0xd0, 0x2e, 0x43, 0x0d, 0xfb, 0xcb, - 0x2e, 0x52, 0x6e, 0x76, 0x91, 0xd8, 0x7d, 0xa8, 0x26, 0xc6, 0x5a, 0xc0, 0xb1, 0x42, 0x10, 0x0d, - 0xf2, 0x17, 0x5f, 0xc6, 0xb7, 0xa1, 0x19, 0x0f, 0x5b, 0xae, 0x21, 0x83, 0xbc, 0x20, 0x49, 0xd9, - 0x00, 0xfe, 0x6d, 0xfc, 0x93, 0x0c, 0x21, 0x6e, 0x79, 0x4e, 0x24, 0x9d, 0x0a, 0x44, 0x21, 0xf7, - 0x2a, 0x44, 0xf1, 0xf7, 0x8d, 0x52, 0xfd, 0x2f, 0x3e, 0x59, 0x71, 0x74, 0x02, 0xee, 0x0e, 0x2d, - 0x7b, 0x34, 0x42, 0xe6, 0x5b, 0x32, 0x8b, 0xe2, 0xbb, 0x3d, 0x1a, 0x19, 0xef, 0xc0, 0xa2, 0x36, - 0xba, 0x17, 0xcc, 0xe3, 0x00, 0xd8, 0x9e, 0x13, 0x84, 0xc7, 0x6e, 0x30, 0xd1, 0x04, 0xb7, 0x3b, - 0x50, 0x16, 0x1c, 0x56, 0x8c, 0x8c, 0x8e, 0x6c, 0xc1, 0x14, 0x2c, 0x57, 0x8c, 0x2b, 0xc0, 0x42, - 0xfb, 0x4a, 0x16, 0x66, 0x65, 0xa1, 0x7d, 0x85, 0x85, 0xc6, 0x77, 0x61, 0x29, 0xd1, 0x9e, 0xec, - 0xfa, 0x0d, 0x28, 0x4c, 0xc3, 0x2b, 0x4f, 0x89, 0xe6, 0x15, 0x49, 0x21, 0x42, 0x01, 0x34, 0xa9, - 0xc4, 0xf8, 0x08, 0x16, 0x0f, 0xf8, 0xa5, 0x3c, 0xc4, 0x6a, 0x20, 0x6f, 0x43, 0xfe, 0x25, 0x4a, - 0x21, 0x96, 0x1b, 0x1b, 0xc0, 0xf4, 0xca, 0xb2, 0x57, 0x4d, 0x47, 0xcc, 0x24, 0x74, 0x44, 0xe3, - 0x6d, 0x60, 0x3d, 0xe7, 0xcc, 0xdd, 0xe7, 0x41, 0x60, 0x9f, 0x45, 0xc7, 0xbe, 0x09, 0xb9, 0x71, - 0x70, 0x26, 0x79, 0x94, 0xf8, 0xd3, 0xf8, 0x16, 0x2c, 0x25, 0xf0, 0x64, 0xc3, 0xaf, 0x41, 0x39, - 0x70, 0xce, 0x5c, 0x14, 0xac, 0x64, 0xd3, 0x31, 0xc0, 0xd8, 0x81, 0xe5, 0x4f, 0xb8, 0xef, 0x9c, - 0x5e, 0xbf, 0xac, 0xf9, 0x64, 0x3b, 0xd9, 0xd9, 0x76, 0x3a, 0xb0, 0x32, 0xd3, 0x8e, 0xec, 0x9e, - 0xc8, 0x57, 0xee, 0x64, 0xc9, 0xa4, 0x0f, 0x8d, 0xef, 0x65, 0x75, 0xbe, 0x67, 0x1c, 0x03, 0xdb, - 0xf2, 0x5c, 0x97, 0x0f, 0xc2, 0x23, 0xce, 0xfd, 0xd8, 0x4a, 0x15, 0xd3, 0x6a, 0xe5, 0xc9, 0x9a, - 0x5c, 0xd9, 0x59, 0x66, 0x2a, 0x89, 0x98, 0x41, 0x7e, 0xc2, 0xfd, 0x31, 0x36, 0x5c, 0x32, 0xf1, - 0x6f, 0x63, 0x05, 0x96, 0x12, 0xcd, 0x4a, 0xbd, 0xfe, 0x31, 0xac, 0x6c, 0x3b, 0xc1, 0x60, 0xbe, - 0xc3, 0x35, 0x28, 0x4e, 0xa6, 0x27, 0x56, 0x92, 0x2f, 0x3f, 0xe3, 0xd7, 0x42, 0xdb, 0x9b, 0xad, - 0x21, 0xdb, 0xfa, 0xeb, 0x19, 0xc8, 0xef, 0xf6, 0xf7, 0xb6, 0xd8, 0x3a, 0x94, 0x1c, 0x77, 0xe0, - 0x8d, 0x85, 0xe0, 0x45, 0x73, 0x8e, 0xbe, 0x6f, 0x3c, 0x60, 0x77, 0xa0, 0x8c, 0xf2, 0x9a, 0x50, - 0x6d, 0xa5, 0xe8, 0x53, 0x12, 0x80, 0x3d, 0x6f, 0xf0, 0x5c, 0xe8, 0xd4, 0xfc, 0x6a, 0xe2, 0xf8, - 0xa8, 0x35, 0x2b, 0x65, 0x38, 0x4f, 0x77, 0x7d, 0x5c, 0x40, 0x1a, 0xb1, 0xf1, 0x0f, 0x4b, 0x50, - 0x94, 0xb7, 0x2d, 0xdd, 0xdc, 0xa1, 0x73, 0xc1, 0xe3, 0x9b, 0x5b, 0x7c, 0x09, 0x79, 0xc0, 0xe7, - 0x63, 0x2f, 0x8c, 0x04, 0x36, 0xda, 0x83, 0x2a, 0x01, 0xa5, 0xc8, 0xa6, 0x09, 0x0d, 0x64, 0x62, - 0xc8, 0x11, 0xd2, 0x40, 0xbf, 0xca, 0xef, 0x40, 0x51, 0xdd, 0xfd, 0xf9, 0x48, 0xa7, 0x59, 0x18, - 0x90, 0xb4, 0xb6, 0x0e, 0xa5, 0x81, 0x3d, 0xb1, 0x07, 0x4e, 0x78, 0x2d, 0x19, 0x42, 0xf4, 0x2d, - 0x5a, 0x1f, 0x79, 0x03, 0x7b, 0x64, 0x9d, 0xd8, 0x23, 0xdb, 0x1d, 0x70, 0xa9, 0xbb, 0x57, 0x11, - 0xb8, 0x49, 0x30, 0xa1, 0x9f, 0xcb, 0x71, 0x2a, 0x2c, 0x52, 0xe1, 0xe5, 0xe8, 0x15, 0x9a, 0x10, - 0x2e, 0xbd, 0xf1, 0xd8, 0x11, 0x5a, 0x06, 0x89, 0x61, 0x39, 0xb3, 0x4c, 0x90, 0x1d, 0x8e, 0xb3, - 0x95, 0xc5, 0x97, 0xb4, 0x74, 0x65, 0xea, 0x8a, 0x80, 0x9f, 0x92, 0x21, 0x61, 0x5e, 0x16, 0xcb, - 0x69, 0xb2, 0xd8, 0xbb, 0xb0, 0x38, 0x75, 0x03, 0x1e, 0x86, 0x23, 0x3e, 0x8c, 0xc6, 0x52, 0x41, - 0xa4, 0x66, 0x54, 0xa0, 0x86, 0xb3, 0x01, 0x4b, 0x64, 0x74, 0x08, 0xec, 0xd0, 0x0b, 0xce, 0x9d, - 0xc0, 0x0a, 0x84, 0x86, 0x44, 0xea, 0xee, 0x22, 0x16, 0xf5, 0x64, 0x49, 0x8f, 0x54, 0xa4, 0xb5, - 0x19, 0x7c, 0x9f, 0x0f, 0xb8, 0x73, 0xc1, 0x87, 0x28, 0xa7, 0xe5, 0xcc, 0x95, 0x44, 0x1d, 0x53, - 0x16, 0xa2, 0xd0, 0x3d, 0x1d, 0x5b, 0xd3, 0xc9, 0xd0, 0x16, 0xc2, 0x4a, 0x9d, 0x84, 0x61, 0x77, - 0x3a, 0x3e, 0x26, 0x08, 0x7b, 0x0c, 0x4a, 0x12, 0x93, 0xf2, 0x61, 0x23, 0xc1, 0xcf, 0x04, 0xb1, - 0x9a, 0x55, 0x89, 0x41, 0x82, 0x62, 0x42, 0xe6, 0x6c, 0xce, 0xc8, 0x9c, 0x2d, 0x28, 0x4e, 0x7c, - 0xe7, 0xc2, 0x0e, 0x79, 0x6b, 0x91, 0x18, 0xb8, 0xfc, 0x14, 0x9c, 0xc1, 0x71, 0x9d, 0xd0, 0xb1, - 0x43, 0xcf, 0x6f, 0x31, 0x2c, 0x8b, 0x01, 0xec, 0x21, 0x2c, 0x22, 0x8d, 0x04, 0xa1, 0x1d, 0x4e, - 0x03, 0x29, 0x81, 0x2e, 0x21, 0x31, 0xa1, 0x0c, 0xdd, 0x43, 0x38, 0x0a, 0xa1, 0xec, 0x5b, 0xb0, - 0x4a, 0x64, 0x81, 0x35, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x32, 0x2e, 0xc5, 0x12, 0x96, 0x0a, 0xfa, - 0x96, 0xf2, 0xb5, 0x90, 0x0e, 0xde, 0x87, 0x35, 0x49, 0x26, 0x73, 0xb5, 0x56, 0xb0, 0xd6, 0x32, - 0x15, 0xcf, 0x54, 0xdb, 0x80, 0x45, 0x31, 0x24, 0x67, 0x60, 0xc9, 0xda, 0xe2, 0x24, 0xac, 0x8a, - 0xd1, 0xa3, 0xa6, 0xd4, 0xa0, 0x42, 0x13, 0xcb, 0x9e, 0xf1, 0x6b, 0xf6, 0x3d, 0x68, 0x10, 0xc9, - 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, 0xa5, 0xc8, 0xec, 0xeb, - 0x83, 0xc4, 0xb7, 0x38, 0x0e, 0x23, 0xe7, 0x94, 0x87, 0xce, 0x98, 0xb7, 0xd6, 0x88, 0xc0, 0xd4, - 0xb7, 0x38, 0xa9, 0xd3, 0x09, 0x96, 0xb4, 0x88, 0x2f, 0xd0, 0x17, 0xd2, 0xee, 0xc8, 0x0b, 0xb8, - 0x32, 0x51, 0xb5, 0x6e, 0xcb, 0x43, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, 0x38, 0x29, 0x3d, 0x91, - 0x21, 0xf1, 0x0e, 0x12, 0x43, 0x8d, 0x74, 0x1f, 0x69, 0x4c, 0x34, 0x7e, 0x9a, 0xa1, 0xfb, 0x4e, - 0xb2, 0x87, 0x40, 0xd3, 0xde, 0x88, 0x31, 0x58, 0x9e, 0x3b, 0xba, 0x96, 0xbc, 0x02, 0x08, 0x74, - 0xe8, 0x8e, 0xf0, 0xb0, 0x3a, 0xae, 0x8e, 0x42, 0xac, 0xb5, 0xaa, 0x80, 0x88, 0x74, 0x0f, 0x2a, - 0x93, 0xe9, 0xc9, 0xc8, 0x19, 0x10, 0x4a, 0x8e, 0x5a, 0x21, 0x10, 0x22, 0x08, 0xf5, 0x95, 0x08, - 0x86, 0x30, 0xf2, 0x88, 0x51, 0x91, 0x30, 0x44, 0x41, 0xd6, 0xcd, 0x7d, 0xe4, 0x16, 0x55, 0x13, - 0xff, 0x36, 0x36, 0x61, 0x39, 0x39, 0x68, 0x79, 0xaf, 0x3c, 0x84, 0x92, 0x64, 0x45, 0xca, 0xae, - 0x51, 0xd7, 0x2c, 0xcd, 0x42, 0x03, 0x8b, 0xca, 0x8d, 0xdf, 0x5e, 0x80, 0x25, 0x09, 0xdd, 0x12, - 0x2b, 0xd7, 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0xc2, 0xe3, 0x32, 0x2f, 0xe6, 0x71, 0xd9, 0x39, 0x1e, - 0x97, 0x54, 0x6c, 0x89, 0x45, 0x26, 0x15, 0x5b, 0xb1, 0x55, 0xa4, 0x6b, 0xe8, 0x66, 0xce, 0x9a, - 0x04, 0xf7, 0xc9, 0x9c, 0x3a, 0xc7, 0x91, 0x0b, 0x29, 0x1c, 0x59, 0xe7, 0xa7, 0x0b, 0x33, 0xfc, - 0xf4, 0x0d, 0x20, 0x9a, 0x50, 0xd7, 0x43, 0x91, 0xd4, 0x0f, 0x84, 0x49, 0x5b, 0xe9, 0x3b, 0xd0, - 0x98, 0x65, 0x61, 0xc4, 0x2b, 0xeb, 0x29, 0x0c, 0xcc, 0x19, 0x73, 0xbc, 0x8c, 0x34, 0xe4, 0xb2, - 0x64, 0x60, 0xce, 0x98, 0xef, 0x61, 0x89, 0xc2, 0xef, 0x00, 0x50, 0xdf, 0x78, 0x26, 0x00, 0xcf, - 0xc4, 0xdb, 0xc9, 0xbd, 0xd0, 0x57, 0x7d, 0x43, 0x7c, 0x4c, 0x7d, 0x8e, 0x87, 0xa4, 0x8c, 0x35, - 0xf1, 0x7c, 0x3c, 0x83, 0xba, 0x37, 0xe1, 0xae, 0x15, 0xb3, 0x92, 0x0a, 0x36, 0xf5, 0xd6, 0x0b, - 0x9a, 0xea, 0x2a, 0x5c, 0xb3, 0x26, 0xea, 0x46, 0x9f, 0x6c, 0x9f, 0x16, 0x9e, 0x6b, 0xad, 0x55, - 0xbf, 0x44, 0x6b, 0x75, 0xac, 0x1c, 0x7d, 0x1b, 0x7f, 0x2b, 0x03, 0x15, 0x6d, 0xd8, 0x6c, 0x05, - 0x16, 0xb7, 0x0e, 0x0f, 0x8f, 0x3a, 0x66, 0xbb, 0xdf, 0xfd, 0xa4, 0x63, 0x6d, 0xed, 0x1d, 0xf6, - 0x3a, 0xcd, 0x5b, 0x02, 0xbc, 0x77, 0xb8, 0xd5, 0xde, 0xb3, 0x76, 0x0e, 0xcd, 0x2d, 0x05, 0xce, - 0xb0, 0x55, 0x60, 0x66, 0x67, 0xff, 0xb0, 0xdf, 0x49, 0xc0, 0xb3, 0xac, 0x09, 0xd5, 0x4d, 0xb3, - 0xd3, 0xde, 0xda, 0x95, 0x90, 0x1c, 0x5b, 0x86, 0xe6, 0xce, 0xf1, 0xc1, 0x76, 0xf7, 0xe0, 0xa9, - 0xb5, 0xd5, 0x3e, 0xd8, 0xea, 0xec, 0x75, 0xb6, 0x9b, 0x79, 0x56, 0x83, 0x72, 0x7b, 0xb3, 0x7d, - 0xb0, 0x7d, 0x78, 0xd0, 0xd9, 0x6e, 0x16, 0x8c, 0x5f, 0x81, 0x72, 0x3c, 0xd1, 0x0a, 0x14, 0x8f, - 0x0f, 0x9e, 0x1d, 0x1c, 0x7e, 0x7a, 0xd0, 0xbc, 0xc5, 0xca, 0x50, 0xc0, 0xfe, 0x9b, 0x19, 0x06, - 0xb0, 0x40, 0x7d, 0x36, 0xb3, 0xac, 0x04, 0xf9, 0xcd, 0xc3, 0xfe, 0x6e, 0x33, 0x67, 0xfc, 0x45, - 0x06, 0x56, 0x70, 0xca, 0xc3, 0x59, 0x26, 0x70, 0x1f, 0x2a, 0x03, 0xcf, 0x9b, 0x08, 0x45, 0x2a, - 0x16, 0x18, 0x74, 0x90, 0x38, 0xe0, 0xc4, 0x9b, 0x4f, 0x3d, 0x7f, 0xc0, 0x25, 0x0f, 0x00, 0x04, - 0xed, 0x08, 0x88, 0xa0, 0x41, 0x49, 0xc4, 0x84, 0x41, 0x2c, 0xa0, 0x42, 0x30, 0x42, 0x59, 0x85, - 0x85, 0x13, 0x9f, 0xdb, 0x83, 0x73, 0x79, 0xfa, 0xe5, 0x17, 0xfb, 0x7a, 0xac, 0xe2, 0x0f, 0x04, - 0x4d, 0x8d, 0xf8, 0x10, 0x8f, 0x40, 0xc9, 0x6c, 0x48, 0xf8, 0x96, 0x04, 0x8b, 0xcb, 0xc6, 0x3e, - 0xb1, 0xdd, 0xa1, 0xe7, 0xf2, 0xa1, 0xd4, 0x24, 0x62, 0x80, 0x71, 0x04, 0xab, 0xb3, 0xf3, 0x93, - 0xfc, 0xe2, 0x03, 0x8d, 0x5f, 0x90, 0x60, 0xbf, 0x7e, 0x33, 0x29, 0x68, 0xbc, 0xe3, 0xef, 0xe4, - 0x21, 0x2f, 0x04, 0xbd, 0x1b, 0x65, 0x42, 0x5d, 0x72, 0xcf, 0xcd, 0x79, 0x77, 0xd0, 0x92, 0x40, - 0x12, 0x00, 0x99, 0xab, 0xca, 0x08, 0xc1, 0x9b, 0x3f, 0x2a, 0xf6, 0xf9, 0xe0, 0x42, 0xda, 0xab, - 0xa8, 0xd8, 0xe4, 0x83, 0x0b, 0x54, 0x99, 0xec, 0x90, 0xea, 0xd2, 0x79, 0x2f, 0x06, 0x76, 0x88, - 0x35, 0x65, 0x11, 0xd6, 0x2b, 0x46, 0x45, 0x58, 0xab, 0x05, 0x45, 0xc7, 0x3d, 0xf1, 0xa6, 0xee, - 0x10, 0x8f, 0x77, 0xc9, 0x54, 0x9f, 0xe8, 0x4c, 0x42, 0x4e, 0x24, 0xee, 0x19, 0x3a, 0xcd, 0x25, - 0x01, 0xe8, 0x8b, 0x9b, 0xe6, 0x3d, 0x28, 0x07, 0xd7, 0xee, 0x40, 0x3f, 0xc3, 0xcb, 0x72, 0x7d, - 0xc4, 0xec, 0x37, 0x7a, 0xd7, 0xee, 0x00, 0x4f, 0x6c, 0x29, 0x90, 0x7f, 0xb1, 0xf7, 0xa1, 0x14, - 0x99, 0x75, 0x89, 0x03, 0xdf, 0xd6, 0x6b, 0x28, 0x5b, 0x2e, 0x69, 0xcf, 0x11, 0x2a, 0x7b, 0x04, - 0x0b, 0x68, 0x7b, 0x0d, 0x5a, 0x55, 0xac, 0xa4, 0xc4, 0x79, 0x31, 0x0c, 0xf4, 0xe3, 0xf0, 0x21, - 0xda, 0x61, 0x4d, 0x89, 0xb6, 0xfe, 0x0c, 0x6a, 0x89, 0xb6, 0x74, 0x1d, 0xb9, 0x46, 0x3a, 0xf2, - 0x5b, 0xba, 0x8e, 0x1c, 0xdf, 0x04, 0xb2, 0x9a, 0xae, 0x33, 0xff, 0x1a, 0x94, 0xd4, 0x54, 0xc4, - 0xf9, 0x93, 0x67, 0xc7, 0xea, 0x7d, 0x76, 0xb0, 0xd5, 0xbc, 0xc5, 0x1a, 0x50, 0x69, 0x6f, 0xe1, - 0x91, 0x46, 0x40, 0x46, 0xa0, 0x1c, 0xb5, 0x7b, 0xbd, 0x08, 0x92, 0x35, 0x76, 0xa0, 0x39, 0x3b, - 0x52, 0x41, 0x93, 0xa1, 0x82, 0x49, 0xcb, 0x74, 0x0c, 0x10, 0x1a, 0x10, 0x19, 0x9b, 0x49, 0xcc, - 0xa6, 0x0f, 0xe3, 0x7d, 0x68, 0x8a, 0x7b, 0x4d, 0x2c, 0x55, 0xa0, 0x59, 0x78, 0x47, 0x42, 0x74, - 0xd3, 0xad, 0xd3, 0x25, 0xb3, 0x42, 0x30, 0xec, 0xca, 0xf8, 0x00, 0x16, 0xb5, 0x6a, 0xb1, 0xc6, - 0x2a, 0xee, 0xca, 0x59, 0x8d, 0x15, 0xf5, 0x13, 0x2a, 0x31, 0xd6, 0x60, 0x45, 0x7c, 0x76, 0x2e, - 0xb8, 0x1b, 0xf6, 0xa6, 0x27, 0xe4, 0x52, 0x74, 0x3c, 0x57, 0xe8, 0x2d, 0xe5, 0xa8, 0xe4, 0x66, - 0x22, 0xdf, 0x90, 0xca, 0x6d, 0x16, 0x49, 0x63, 0x5d, 0xeb, 0x01, 0x2b, 0x6e, 0xe0, 0xbf, 0x09, - 0x25, 0xb7, 0x1c, 0x81, 0xc4, 0xb2, 0x1e, 0x75, 0x3a, 0xa6, 0x75, 0x78, 0xb0, 0xd7, 0x3d, 0x10, + // 11387 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x8f, 0x24, 0xd7, + 0x75, 0x18, 0xbe, 0xfd, 0x9a, 0xee, 0x3e, 0xfd, 0x9c, 0x3b, 0xaf, 0xde, 0x59, 0x2e, 0x77, 0x59, + 0xa4, 0xc8, 0xd5, 0x52, 0x9a, 0x5d, 0xae, 0x44, 0x4a, 0x26, 0x7f, 0x96, 0xd5, 0x33, 0xd3, 0xb3, + 0xd3, 0xda, 0x79, 0xb1, 0xba, 0x87, 0x34, 0xe5, 0x9f, 0x53, 0xaa, 0xe9, 0xbe, 0x33, 0x53, 0xde, + 0xee, 0xaa, 0x66, 0x55, 0xf5, 0x3c, 0x24, 0x30, 0x1f, 0x82, 0xc4, 0x08, 0x82, 0x24, 0x80, 0x91, + 0x38, 0x40, 0x9c, 0x18, 0x09, 0x12, 0x04, 0x41, 0x10, 0xc0, 0x70, 0x20, 0x07, 0x48, 0x80, 0x7c, + 0xf7, 0x97, 0x04, 0x41, 0x60, 0xe7, 0x4b, 0x60, 0x18, 0x70, 0x1e, 0xca, 0xb7, 0xc0, 0x7f, 0x42, + 0x70, 0xcf, 0xb9, 0xb7, 0xea, 0x56, 0x77, 0xcd, 0xee, 0x52, 0x62, 0xf4, 0x65, 0xa6, 0xeb, 0xdc, + 0x73, 0x9f, 0x75, 0xee, 0xb9, 0xe7, 0x79, 0x0b, 0xca, 0xfe, 0x64, 0xb0, 0x31, 0xf1, 0xbd, 0xd0, + 0x63, 0x85, 0x91, 0xeb, 0x4f, 0x06, 0xeb, 0xaf, 0x9d, 0x79, 0xde, 0xd9, 0x88, 0x3f, 0xb2, 0x27, + 0xce, 0x23, 0xdb, 0x75, 0xbd, 0xd0, 0x0e, 0x1d, 0xcf, 0x0d, 0x08, 0xc9, 0xf8, 0x11, 0xd4, 0x9f, + 0x72, 0xb7, 0xc7, 0xf9, 0xd0, 0xe4, 0x9f, 0x4f, 0x79, 0x10, 0xb2, 0x77, 0x61, 0xd1, 0xe6, 0x3f, + 0xe6, 0x7c, 0x68, 0x4d, 0xec, 0x20, 0x98, 0x9c, 0xfb, 0x76, 0xc0, 0x5b, 0x99, 0xfb, 0x99, 0x07, + 0x55, 0xb3, 0x49, 0x05, 0x47, 0x11, 0x9c, 0xbd, 0x01, 0xd5, 0x40, 0xa0, 0x72, 0x37, 0xf4, 0xbd, + 0xc9, 0x75, 0x2b, 0x8b, 0x78, 0x15, 0x01, 0xeb, 0x10, 0xc8, 0x18, 0x41, 0x23, 0xea, 0x21, 0x98, + 0x78, 0x6e, 0xc0, 0xd9, 0x63, 0x58, 0x1e, 0x38, 0x93, 0x73, 0xee, 0x5b, 0x58, 0x79, 0xec, 0xf2, + 0xb1, 0xe7, 0x3a, 0x83, 0x56, 0xe6, 0x7e, 0xee, 0x41, 0xd9, 0x64, 0x54, 0x26, 0x6a, 0xec, 0xcb, + 0x12, 0xf6, 0x0e, 0x34, 0xb8, 0x4b, 0x70, 0x3e, 0xc4, 0x5a, 0xb2, 0xab, 0x7a, 0x0c, 0x16, 0x15, + 0x8c, 0xbf, 0x99, 0x85, 0xc5, 0xae, 0xeb, 0x84, 0x9f, 0xda, 0xa3, 0x11, 0x0f, 0xd5, 0x9c, 0xde, + 0x81, 0xc6, 0x25, 0x02, 0x70, 0x4e, 0x97, 0x9e, 0x3f, 0x94, 0x33, 0xaa, 0x13, 0xf8, 0x48, 0x42, + 0x6f, 0x1c, 0x59, 0xf6, 0xc6, 0x91, 0xa5, 0x2e, 0x57, 0xee, 0x86, 0xe5, 0x7a, 0x07, 0x1a, 0x3e, + 0x1f, 0x78, 0x17, 0xdc, 0xbf, 0xb6, 0x2e, 0x1d, 0x77, 0xe8, 0x5d, 0xb6, 0xf2, 0xf7, 0x33, 0x0f, + 0x0a, 0x66, 0x5d, 0x81, 0x3f, 0x45, 0x28, 0xdb, 0x84, 0xc6, 0xe0, 0xdc, 0x76, 0x5d, 0x3e, 0xb2, + 0x4e, 0xec, 0xc1, 0xf3, 0xe9, 0x24, 0x68, 0x15, 0xee, 0x67, 0x1e, 0x54, 0x9e, 0xdc, 0xde, 0xc0, + 0xb7, 0xba, 0xb1, 0x75, 0x6e, 0xbb, 0x9b, 0x58, 0xd2, 0x73, 0xed, 0x49, 0x70, 0xee, 0x85, 0x66, + 0x5d, 0xd6, 0x20, 0x70, 0x60, 0x2c, 0x03, 0xd3, 0x57, 0x82, 0xd6, 0xde, 0xf8, 0xd7, 0x19, 0x58, + 0x3a, 0x76, 0x47, 0xde, 0xe0, 0xf9, 0xcf, 0xb9, 0x44, 0x29, 0x73, 0xc8, 0xbe, 0xea, 0x1c, 0x72, + 0x5f, 0x76, 0x0e, 0xab, 0xb0, 0x9c, 0x1c, 0xac, 0x9c, 0x05, 0x87, 0x15, 0x51, 0xfb, 0x8c, 0xab, + 0x61, 0xa9, 0x69, 0x7c, 0x1d, 0x9a, 0x83, 0xa9, 0xef, 0x73, 0x77, 0x6e, 0x1e, 0x0d, 0x09, 0x8f, + 0x26, 0xf2, 0x06, 0x54, 0x5d, 0x7e, 0x19, 0xa3, 0x49, 0xda, 0x75, 0xf9, 0xa5, 0x42, 0x31, 0x5a, + 0xb0, 0x3a, 0xdb, 0x8d, 0x1c, 0xc0, 0xcf, 0x32, 0x90, 0x3f, 0x0e, 0xaf, 0x3c, 0xf6, 0x3e, 0x54, + 0xed, 0xe1, 0xd0, 0xe7, 0x41, 0x60, 0x85, 0xd7, 0x13, 0xda, 0x29, 0xf5, 0x27, 0x4c, 0x4e, 0xb1, + 0x4d, 0x45, 0xfd, 0xeb, 0x09, 0x37, 0x2b, 0x76, 0xfc, 0xc0, 0x5a, 0x50, 0x94, 0x8f, 0xd8, 0x6f, + 0xd9, 0x54, 0x8f, 0xec, 0x2e, 0x80, 0x3d, 0xf6, 0xa6, 0x6e, 0x68, 0x05, 0x76, 0x88, 0x2b, 0x96, + 0x33, 0xcb, 0x04, 0xe9, 0xd9, 0x21, 0xbb, 0x03, 0xe5, 0xc9, 0x73, 0x2b, 0x18, 0xf8, 0xce, 0x24, + 0x44, 0xe2, 0x29, 0x9b, 0xa5, 0xc9, 0xf3, 0x1e, 0x3e, 0xb3, 0x77, 0xa1, 0xe4, 0x4d, 0xc3, 0x89, + 0xe7, 0xb8, 0xa1, 0xa4, 0x97, 0x86, 0x1c, 0xc8, 0xe1, 0x34, 0x3c, 0x12, 0x60, 0x33, 0x42, 0x60, + 0x6f, 0x41, 0x6d, 0xe0, 0xb9, 0xa7, 0x8e, 0x3f, 0x26, 0x8e, 0xd0, 0x5a, 0xc0, 0xbe, 0x92, 0x40, + 0xe3, 0x0f, 0xb3, 0x50, 0xe9, 0xfb, 0xb6, 0x1b, 0xd8, 0x03, 0x01, 0x60, 0x6b, 0x50, 0x0c, 0xaf, + 0xac, 0x73, 0x3b, 0x38, 0xc7, 0xa9, 0x96, 0xcd, 0x85, 0xf0, 0x6a, 0xd7, 0x0e, 0xce, 0xd9, 0x2a, + 0x2c, 0xd0, 0x28, 0x71, 0x42, 0x39, 0x53, 0x3e, 0x89, 0x0d, 0xe2, 0x4e, 0xc7, 0x56, 0xb2, 0xab, + 0x1c, 0x52, 0x4c, 0xd3, 0x9d, 0x8e, 0xb7, 0x74, 0xb8, 0x98, 0xfc, 0x89, 0x78, 0xdd, 0xd4, 0x01, + 0x4d, 0xaf, 0x8c, 0x10, 0xec, 0xe3, 0x0d, 0xa8, 0xca, 0x62, 0xee, 0x9c, 0x9d, 0xd3, 0x1c, 0x0b, + 0x66, 0x85, 0x10, 0x10, 0x24, 0x5a, 0x08, 0x9d, 0x31, 0xb7, 0x82, 0xd0, 0x1e, 0x4f, 0xe4, 0x94, + 0xca, 0x02, 0xd2, 0x13, 0x00, 0x2c, 0xf6, 0x42, 0x7b, 0x64, 0x9d, 0x72, 0x1e, 0xb4, 0x8a, 0xb2, + 0x58, 0x40, 0x76, 0x38, 0x0f, 0xd8, 0xd7, 0xa0, 0x3e, 0xe4, 0x41, 0x68, 0xc9, 0x97, 0xc1, 0x83, + 0x56, 0x09, 0x77, 0x7e, 0x4d, 0x40, 0xdb, 0x0a, 0xc8, 0x5e, 0x03, 0xf0, 0xed, 0x4b, 0x4b, 0x2c, + 0x04, 0xbf, 0x6a, 0x95, 0xe9, 0x2d, 0xf8, 0xf6, 0x65, 0xff, 0x6a, 0x97, 0x5f, 0x09, 0xaa, 0x79, + 0xca, 0x43, 0x6d, 0xd1, 0x02, 0x49, 0x9d, 0xc6, 0x1e, 0x30, 0x0d, 0xbc, 0xcd, 0x43, 0xdb, 0x19, + 0x05, 0xec, 0x03, 0xa8, 0x86, 0x1a, 0x32, 0xb2, 0xc1, 0x4a, 0x44, 0x42, 0x5a, 0x05, 0x33, 0x81, + 0x67, 0x9c, 0x43, 0x69, 0x87, 0xf3, 0x3d, 0x67, 0xec, 0x84, 0x6c, 0x15, 0x0a, 0xa7, 0xce, 0x15, + 0x27, 0x62, 0xcf, 0xed, 0xde, 0x32, 0xe9, 0x91, 0xdd, 0x03, 0xc0, 0x1f, 0xd6, 0x38, 0xa2, 0xa6, + 0xdd, 0x5b, 0x66, 0x19, 0x61, 0xfb, 0x81, 0x1d, 0xb2, 0x75, 0x28, 0x4e, 0xb8, 0x3f, 0xe0, 0xea, + 0xbd, 0xed, 0xde, 0x32, 0x15, 0x60, 0xb3, 0x08, 0x85, 0x91, 0x68, 0xdd, 0xf8, 0xe3, 0x02, 0x54, + 0x7a, 0xdc, 0x8d, 0x76, 0x19, 0x83, 0xbc, 0x58, 0x10, 0xb9, 0xb3, 0xf0, 0x37, 0x7b, 0x13, 0x2a, + 0xb8, 0x74, 0x41, 0xe8, 0x3b, 0xee, 0x19, 0x51, 0xf5, 0x66, 0xb6, 0x95, 0x31, 0x41, 0x80, 0x7b, + 0x08, 0x65, 0x4d, 0xc8, 0xd9, 0x63, 0x45, 0xd5, 0xe2, 0x27, 0xbb, 0x0d, 0x25, 0x7b, 0x1c, 0xd2, + 0xf0, 0xaa, 0x08, 0x2e, 0xda, 0xe3, 0x10, 0x87, 0xf6, 0x06, 0x54, 0x27, 0xf6, 0xf5, 0x58, 0xec, + 0xe5, 0x88, 0x1c, 0xaa, 0x66, 0x45, 0xc2, 0x90, 0x20, 0x9e, 0xc0, 0x92, 0x8e, 0xa2, 0x3a, 0x2f, + 0x44, 0x9d, 0x2f, 0x6a, 0xd8, 0x72, 0x0c, 0xef, 0x40, 0x43, 0xd5, 0xf1, 0x69, 0x3e, 0x48, 0x26, + 0x65, 0xb3, 0x2e, 0xc1, 0x6a, 0x96, 0x0f, 0xa0, 0x79, 0xea, 0xb8, 0xf6, 0xc8, 0x1a, 0x8c, 0xc2, + 0x0b, 0x6b, 0xc8, 0x47, 0xa1, 0x8d, 0x14, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1a, 0x85, 0x17, 0xdb, + 0x02, 0xca, 0xbe, 0x01, 0xe5, 0x53, 0xce, 0x2d, 0x5c, 0xac, 0x56, 0x29, 0xb1, 0xf1, 0xd4, 0x1b, + 0x32, 0x4b, 0xa7, 0xea, 0x5d, 0x7d, 0x03, 0x9a, 0xde, 0x34, 0x3c, 0xf3, 0x1c, 0xf7, 0xcc, 0x12, + 0xfc, 0xce, 0x72, 0x86, 0x48, 0x43, 0xf9, 0xcd, 0xec, 0xe3, 0x8c, 0x59, 0x57, 0x65, 0x82, 0xf3, + 0x74, 0x87, 0xec, 0x6d, 0x68, 0x8c, 0xec, 0x20, 0xb4, 0xce, 0xbd, 0x89, 0x35, 0x99, 0x9e, 0x3c, + 0xe7, 0xd7, 0xad, 0x1a, 0x2e, 0x44, 0x4d, 0x80, 0x77, 0xbd, 0xc9, 0x11, 0x02, 0x05, 0x65, 0xe3, + 0x38, 0x69, 0x10, 0x70, 0x3f, 0xf3, 0xa0, 0x66, 0x96, 0x05, 0x84, 0x3a, 0xfd, 0x0c, 0x96, 0xf0, + 0xf5, 0x0c, 0xa6, 0x41, 0xe8, 0x8d, 0x2d, 0xc1, 0xab, 0xfd, 0x61, 0xd0, 0xaa, 0x20, 0xad, 0x7d, + 0x5d, 0x0e, 0x56, 0x7b, 0xc7, 0x1b, 0xdb, 0x3c, 0x08, 0xb7, 0x10, 0xd9, 0x24, 0x5c, 0x71, 0xa0, + 0x5f, 0x9b, 0x8b, 0xc3, 0x59, 0x38, 0xfb, 0x06, 0x30, 0x7b, 0x34, 0xf2, 0x2e, 0xad, 0x80, 0x8f, + 0x4e, 0x2d, 0xb9, 0x88, 0xad, 0xfa, 0xfd, 0xcc, 0x83, 0x92, 0xd9, 0xc4, 0x92, 0x1e, 0x1f, 0x9d, + 0x1e, 0x11, 0x9c, 0x7d, 0x00, 0xb8, 0x99, 0xac, 0x53, 0x6e, 0x87, 0x53, 0x9f, 0x07, 0xad, 0xc6, + 0xfd, 0xdc, 0x83, 0xfa, 0x93, 0xc5, 0x68, 0xbd, 0x10, 0xbc, 0xe9, 0x84, 0x66, 0x55, 0xe0, 0xc9, + 0xe7, 0x60, 0x7d, 0x1b, 0x56, 0xd3, 0x87, 0x24, 0x88, 0x4a, 0xac, 0x8a, 0x20, 0xc6, 0xbc, 0x29, + 0x7e, 0xb2, 0x65, 0x28, 0x5c, 0xd8, 0xa3, 0x29, 0x97, 0x3c, 0x9d, 0x1e, 0x3e, 0xcc, 0x7e, 0x37, + 0x63, 0xfc, 0x51, 0x06, 0xaa, 0x34, 0x4b, 0x29, 0x8b, 0xbc, 0x09, 0x35, 0x45, 0x0d, 0xdc, 0xf7, + 0x3d, 0x5f, 0x72, 0x35, 0x45, 0x79, 0x1d, 0x01, 0x13, 0xa7, 0x8a, 0x42, 0x9a, 0xf8, 0xdc, 0x19, + 0xdb, 0x67, 0xaa, 0x69, 0x45, 0x4a, 0x47, 0x12, 0xcc, 0xde, 0x8b, 0xdb, 0xf3, 0xbd, 0x69, 0xc8, + 0xe5, 0x99, 0x57, 0x95, 0xd3, 0x33, 0x05, 0x2c, 0x6a, 0x1d, 0x9f, 0x5e, 0x81, 0xce, 0x8d, 0xdf, + 0xcd, 0x00, 0x13, 0xc3, 0xee, 0x7b, 0xd4, 0x80, 0xa4, 0xd0, 0xd9, 0x9a, 0x99, 0x57, 0xde, 0x21, + 0xd9, 0x17, 0xed, 0x10, 0x03, 0x0a, 0x34, 0xf6, 0x7c, 0xca, 0xd8, 0xa9, 0xe8, 0x07, 0xf9, 0x52, + 0xae, 0x99, 0x37, 0xfe, 0x5b, 0x0e, 0x96, 0xb7, 0xe8, 0xc8, 0x6e, 0x0f, 0x06, 0x7c, 0x12, 0xed, + 0x9d, 0x7b, 0x50, 0x71, 0xbd, 0x21, 0x57, 0x14, 0x4b, 0x03, 0x03, 0x01, 0xd2, 0xc8, 0xf5, 0xdc, + 0x76, 0x5c, 0x1a, 0x38, 0x2d, 0x66, 0x19, 0x21, 0x38, 0xec, 0xb7, 0xa1, 0x31, 0xe1, 0xee, 0x50, + 0xdf, 0x22, 0x24, 0x54, 0xd5, 0x24, 0x58, 0xee, 0x8e, 0x7b, 0x50, 0x39, 0x9d, 0x12, 0x9e, 0x60, + 0x2c, 0x79, 0xa4, 0x01, 0x90, 0xa0, 0x36, 0xf1, 0x97, 0xc9, 0x34, 0x38, 0xc7, 0xd2, 0x02, 0x96, + 0x16, 0xc5, 0xb3, 0x28, 0xba, 0x0b, 0x30, 0x9c, 0x06, 0xa1, 0xdc, 0x31, 0x0b, 0x58, 0x58, 0x16, + 0x10, 0xda, 0x31, 0xdf, 0x84, 0xa5, 0xb1, 0x7d, 0x65, 0x21, 0xed, 0x58, 0x8e, 0x6b, 0x9d, 0x8e, + 0xf0, 0xcc, 0x29, 0x22, 0x5e, 0x73, 0x6c, 0x5f, 0x7d, 0x22, 0x4a, 0xba, 0xee, 0x0e, 0xc2, 0x05, + 0x5b, 0x51, 0xe2, 0x8e, 0xcf, 0x03, 0xee, 0x5f, 0x70, 0xe4, 0x04, 0xf9, 0x48, 0xa6, 0x31, 0x09, + 0x2a, 0x46, 0x34, 0x16, 0xf3, 0x0e, 0x47, 0x03, 0xda, 0xf6, 0x66, 0x71, 0xec, 0xb8, 0xbb, 0xe1, + 0x68, 0x20, 0xce, 0x15, 0xc1, 0x47, 0x26, 0xdc, 0xb7, 0x9e, 0x5f, 0xe2, 0x1e, 0xce, 0x23, 0xdf, + 0x38, 0xe2, 0xfe, 0xb3, 0x4b, 0x71, 0xf4, 0x0f, 0x02, 0x64, 0x44, 0xf6, 0x75, 0xab, 0x82, 0x1b, + 0xbc, 0x34, 0x08, 0x04, 0x0b, 0xb2, 0xaf, 0xc5, 0x26, 0x14, 0xa3, 0xb5, 0xf1, 0x2d, 0xf0, 0x21, + 0x36, 0x1f, 0x20, 0x47, 0xad, 0xe1, 0x60, 0xdb, 0xb2, 0x40, 0xf4, 0x13, 0x08, 0xaa, 0x57, 0x83, + 0x3d, 0x1d, 0xd9, 0x67, 0x01, 0xb2, 0x94, 0x9a, 0x59, 0x95, 0xc0, 0x1d, 0x01, 0x33, 0x3e, 0x25, + 0x21, 0x4b, 0x7b, 0xb7, 0x72, 0xcf, 0x88, 0xa3, 0x1e, 0x21, 0xf8, 0x5e, 0x4b, 0xa6, 0x7c, 0x4a, + 0x7b, 0x69, 0xd9, 0x94, 0x97, 0x66, 0xfc, 0x7e, 0x06, 0xaa, 0xb2, 0x65, 0x14, 0x4a, 0xd8, 0x06, + 0x30, 0xf5, 0x16, 0xc3, 0x2b, 0x67, 0x68, 0x9d, 0x5c, 0x87, 0x3c, 0x20, 0xa2, 0xd9, 0xbd, 0x65, + 0x36, 0x65, 0x59, 0xff, 0xca, 0x19, 0x6e, 0x8a, 0x12, 0xf6, 0x10, 0x9a, 0x09, 0xfc, 0x20, 0xf4, + 0x89, 0xa2, 0x77, 0x6f, 0x99, 0x75, 0x0d, 0xbb, 0x17, 0xfa, 0x62, 0x8f, 0x08, 0x91, 0x67, 0x1a, + 0x5a, 0x8e, 0x3b, 0xe4, 0x57, 0x48, 0x46, 0x35, 0xb3, 0x42, 0xb0, 0xae, 0x00, 0x6d, 0xd6, 0xa1, + 0xaa, 0x37, 0x67, 0x9c, 0x41, 0x49, 0xc9, 0x4b, 0x28, 0x30, 0xcc, 0x0c, 0xc9, 0x2c, 0x87, 0xd1, + 0x48, 0x6e, 0x43, 0x29, 0x39, 0x02, 0xb3, 0x18, 0xbe, 0x72, 0xc7, 0xc6, 0xf7, 0xa0, 0xb9, 0x27, + 0x88, 0xc7, 0x15, 0xc4, 0x2a, 0xe5, 0xbf, 0x55, 0x58, 0xd0, 0x36, 0x4d, 0xd9, 0x94, 0x4f, 0xe2, + 0xcc, 0x3d, 0xf7, 0x82, 0x50, 0xf6, 0x82, 0xbf, 0x8d, 0x3f, 0xce, 0x00, 0xeb, 0x04, 0xa1, 0x33, + 0xb6, 0x43, 0xbe, 0xc3, 0x23, 0xb6, 0x70, 0x08, 0x55, 0xd1, 0x5a, 0xdf, 0x6b, 0x93, 0x40, 0x46, + 0x02, 0xc5, 0xbb, 0x72, 0x1b, 0xcf, 0x57, 0xd8, 0xd0, 0xb1, 0x89, 0xcd, 0x27, 0x1a, 0x10, 0xbb, + 0x2c, 0xb4, 0xfd, 0x33, 0x1e, 0xa2, 0x18, 0x27, 0xe5, 0x7d, 0x20, 0x90, 0x10, 0xe0, 0xd6, 0x7f, + 0x0d, 0x16, 0xe7, 0xda, 0xd0, 0xf9, 0x72, 0x39, 0x85, 0x2f, 0xe7, 0x74, 0xbe, 0x6c, 0xc1, 0x52, + 0x62, 0x5c, 0x92, 0xd2, 0xd6, 0xa0, 0x28, 0x36, 0x84, 0x10, 0x0e, 0x32, 0x24, 0x55, 0x9e, 0x72, + 0x2e, 0xc4, 0xe0, 0x47, 0xb0, 0x7c, 0xca, 0xb9, 0x6f, 0x87, 0x58, 0x88, 0x3b, 0x46, 0xbc, 0x21, + 0xd9, 0xf0, 0xa2, 0x2c, 0xeb, 0xd9, 0xe1, 0x11, 0xf7, 0xc5, 0x9b, 0x32, 0xfe, 0x47, 0x06, 0x1a, + 0x82, 0x83, 0xee, 0xdb, 0xee, 0xb5, 0x5a, 0xa7, 0xbd, 0xd4, 0x75, 0x7a, 0xa0, 0x1d, 0x86, 0x1a, + 0xf6, 0x97, 0x5d, 0xa4, 0xdc, 0xec, 0x22, 0xb1, 0xfb, 0x50, 0x4d, 0x8c, 0xb5, 0x80, 0x63, 0x85, + 0x20, 0x1a, 0xe4, 0x2f, 0xbe, 0x8c, 0x6f, 0x43, 0x33, 0x1e, 0xb6, 0x5c, 0x43, 0x06, 0x79, 0x41, + 0x92, 0xb2, 0x01, 0xfc, 0x6d, 0xfc, 0xe3, 0x0c, 0x21, 0x6e, 0x79, 0x4e, 0x24, 0x9d, 0x0a, 0x44, + 0x21, 0xf7, 0x2a, 0x44, 0xf1, 0xfb, 0x46, 0xa9, 0xfe, 0x17, 0x9f, 0xac, 0xd8, 0x3a, 0x01, 0x77, + 0x87, 0x96, 0x3d, 0x1a, 0x21, 0xf3, 0x2d, 0x99, 0x45, 0xf1, 0xdc, 0x1e, 0x8d, 0x8c, 0x77, 0x60, + 0x51, 0x1b, 0xdd, 0x0b, 0xe6, 0x71, 0x00, 0x6c, 0xcf, 0x09, 0xc2, 0x63, 0x37, 0x98, 0x68, 0x82, + 0xdb, 0x1d, 0x28, 0x0b, 0x0e, 0x2b, 0x46, 0x46, 0x5b, 0xb6, 0x60, 0x0a, 0x96, 0x2b, 0xc6, 0x15, + 0x60, 0xa1, 0x7d, 0x25, 0x0b, 0xb3, 0xb2, 0xd0, 0xbe, 0xc2, 0x42, 0xe3, 0xbb, 0xb0, 0x94, 0x68, + 0x4f, 0x76, 0xfd, 0x06, 0x14, 0xa6, 0xe1, 0x95, 0xa7, 0x44, 0xf3, 0x8a, 0xa4, 0x10, 0xa1, 0x00, + 0x9a, 0x54, 0x62, 0x7c, 0x04, 0x8b, 0x07, 0xfc, 0x52, 0x6e, 0x62, 0x35, 0x90, 0xb7, 0x21, 0xff, + 0x12, 0xa5, 0x10, 0xcb, 0x8d, 0x0d, 0x60, 0x7a, 0x65, 0xd9, 0xab, 0xa6, 0x23, 0x66, 0x12, 0x3a, + 0xa2, 0xf1, 0x36, 0xb0, 0x9e, 0x73, 0xe6, 0xee, 0xf3, 0x20, 0xb0, 0xcf, 0xa2, 0x6d, 0xdf, 0x84, + 0xdc, 0x38, 0x38, 0x93, 0x3c, 0x4a, 0xfc, 0x34, 0xbe, 0x05, 0x4b, 0x09, 0x3c, 0xd9, 0xf0, 0x6b, + 0x50, 0x0e, 0x9c, 0x33, 0x17, 0x05, 0x2b, 0xd9, 0x74, 0x0c, 0x30, 0x76, 0x60, 0xf9, 0x13, 0xee, + 0x3b, 0xa7, 0xd7, 0x2f, 0x6b, 0x3e, 0xd9, 0x4e, 0x76, 0xb6, 0x9d, 0x0e, 0xac, 0xcc, 0xb4, 0x23, + 0xbb, 0x27, 0xf2, 0x95, 0x6f, 0xb2, 0x64, 0xd2, 0x83, 0xc6, 0xf7, 0xb2, 0x3a, 0xdf, 0x33, 0x8e, + 0x81, 0x6d, 0x79, 0xae, 0xcb, 0x07, 0xe1, 0x11, 0xe7, 0x7e, 0x6c, 0xa5, 0x8a, 0x69, 0xb5, 0xf2, + 0x64, 0x4d, 0xae, 0xec, 0x2c, 0x33, 0x95, 0x44, 0xcc, 0x20, 0x3f, 0xe1, 0xfe, 0x18, 0x1b, 0x2e, + 0x99, 0xf8, 0xdb, 0x58, 0x81, 0xa5, 0x44, 0xb3, 0x52, 0xaf, 0x7f, 0x0c, 0x2b, 0xdb, 0x4e, 0x30, + 0x98, 0xef, 0x70, 0x0d, 0x8a, 0x93, 0xe9, 0x89, 0x95, 0xe4, 0xcb, 0xcf, 0xf8, 0xb5, 0xd0, 0xf6, + 0x66, 0x6b, 0xc8, 0xb6, 0xfe, 0x7a, 0x06, 0xf2, 0xbb, 0xfd, 0xbd, 0x2d, 0xb6, 0x0e, 0x25, 0xc7, + 0x1d, 0x78, 0x63, 0x21, 0x78, 0xd1, 0x9c, 0xa3, 0xe7, 0x1b, 0x37, 0xd8, 0x1d, 0x28, 0xa3, 0xbc, + 0x26, 0x54, 0x5b, 0x29, 0xfa, 0x94, 0x04, 0x60, 0xcf, 0x1b, 0x3c, 0x17, 0x3a, 0x35, 0xbf, 0x9a, + 0x38, 0x3e, 0x6a, 0xcd, 0x4a, 0x19, 0xce, 0xd3, 0x59, 0x1f, 0x17, 0x90, 0x46, 0x6c, 0xfc, 0xfb, + 0x12, 0x14, 0xe5, 0x69, 0x4b, 0x27, 0x77, 0xe8, 0x5c, 0xf0, 0xf8, 0xe4, 0x16, 0x4f, 0x42, 0x1e, + 0xf0, 0xf9, 0xd8, 0x0b, 0x23, 0x81, 0x8d, 0xde, 0x41, 0x95, 0x80, 0x52, 0x64, 0xd3, 0x84, 0x06, + 0x32, 0x31, 0xe4, 0x08, 0x69, 0xa0, 0x1f, 0xe5, 0x77, 0xa0, 0xa8, 0xce, 0xfe, 0x7c, 0xa4, 0xd3, + 0x2c, 0x0c, 0x48, 0x5a, 0x5b, 0x87, 0xd2, 0xc0, 0x9e, 0xd8, 0x03, 0x27, 0xbc, 0x96, 0x0c, 0x21, + 0x7a, 0x16, 0xad, 0x8f, 0xbc, 0x81, 0x3d, 0xb2, 0x4e, 0xec, 0x91, 0xed, 0x0e, 0xb8, 0xd4, 0xdd, + 0xab, 0x08, 0xdc, 0x24, 0x98, 0xd0, 0xcf, 0xe5, 0x38, 0x15, 0x16, 0xa9, 0xf0, 0x72, 0xf4, 0x0a, + 0x4d, 0x08, 0x97, 0xde, 0x78, 0xec, 0x08, 0x2d, 0x83, 0xc4, 0xb0, 0x9c, 0x59, 0x26, 0xc8, 0x0e, + 0xc7, 0xd9, 0xca, 0xe2, 0x4b, 0x5a, 0xba, 0x32, 0x75, 0x45, 0xc0, 0x4f, 0xc9, 0x90, 0x30, 0x2f, + 0x8b, 0xe5, 0x34, 0x59, 0xec, 0x5d, 0x58, 0x9c, 0xba, 0x01, 0x0f, 0xc3, 0x11, 0x1f, 0x46, 0x63, + 0xa9, 0x20, 0x52, 0x33, 0x2a, 0x50, 0xc3, 0xd9, 0x80, 0x25, 0x32, 0x3a, 0x04, 0x76, 0xe8, 0x05, + 0xe7, 0x4e, 0x60, 0x05, 0x42, 0x43, 0x22, 0x75, 0x77, 0x11, 0x8b, 0x7a, 0xb2, 0xa4, 0x47, 0x2a, + 0xd2, 0xda, 0x0c, 0xbe, 0xcf, 0x07, 0xdc, 0xb9, 0xe0, 0x43, 0x94, 0xd3, 0x72, 0xe6, 0x4a, 0xa2, + 0x8e, 0x29, 0x0b, 0x51, 0xe8, 0x9e, 0x8e, 0xad, 0xe9, 0x64, 0x68, 0x0b, 0x61, 0xa5, 0x4e, 0xc2, + 0xb0, 0x3b, 0x1d, 0x1f, 0x13, 0x84, 0x3d, 0x06, 0x25, 0x89, 0x49, 0xf9, 0xb0, 0x91, 0xe0, 0x67, + 0x82, 0x58, 0xcd, 0xaa, 0xc4, 0x20, 0x41, 0x31, 0x21, 0x73, 0x36, 0x67, 0x64, 0xce, 0x16, 0x14, + 0x27, 0xbe, 0x73, 0x61, 0x87, 0xbc, 0xb5, 0x48, 0x0c, 0x5c, 0x3e, 0x0a, 0xce, 0xe0, 0xb8, 0x4e, + 0xe8, 0xd8, 0xa1, 0xe7, 0xb7, 0x18, 0x96, 0xc5, 0x00, 0xf6, 0x10, 0x16, 0x91, 0x46, 0x82, 0xd0, + 0x0e, 0xa7, 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x21, 0x1c, 0x85, 0x50, 0xf6, + 0x2d, 0x58, 0x25, 0xb2, 0xc0, 0x1a, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x97, 0x62, 0x09, 0x4b, + 0x05, 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0xef, 0xc3, 0x9a, 0x24, 0x93, 0xb9, 0x5a, 0x2b, 0x58, + 0x6b, 0x99, 0x8a, 0x67, 0xaa, 0x6d, 0xc0, 0xa2, 0x18, 0x92, 0x33, 0xb0, 0x64, 0x6d, 0xb1, 0x13, + 0x56, 0xc5, 0xe8, 0x51, 0x53, 0x6a, 0x50, 0xa1, 0x89, 0x65, 0xcf, 0xf8, 0x35, 0xfb, 0x1e, 0x34, + 0x88, 0x64, 0x50, 0xbd, 0x42, 0x4e, 0xbf, 0x8e, 0x9c, 0x7e, 0x45, 0x59, 0x38, 0xa3, 0x52, 0x64, + 0xf6, 0xf5, 0x41, 0xe2, 0x59, 0x6c, 0x87, 0x91, 0x73, 0xca, 0x43, 0x67, 0xcc, 0x5b, 0x6b, 0x44, + 0x60, 0xea, 0x59, 0xec, 0xd4, 0xe9, 0x04, 0x4b, 0x5a, 0xc4, 0x17, 0xe8, 0x09, 0x69, 0x77, 0xe4, + 0x05, 0x5c, 0x99, 0xa8, 0x5a, 0xb7, 0xe5, 0x26, 0x14, 0x40, 0x25, 0x43, 0x0a, 0x41, 0x9c, 0x94, + 0x9e, 0xc8, 0x90, 0x78, 0x07, 0x89, 0xa1, 0x46, 0xba, 0x8f, 0x32, 0x26, 0x8a, 0x53, 0xfc, 0xdc, + 0xbe, 0x54, 0x1c, 0xe4, 0x35, 0x7c, 0xbf, 0x20, 0x40, 0x92, 0x77, 0xfc, 0x34, 0x43, 0x07, 0xa2, + 0xe4, 0x1f, 0x81, 0xa6, 0xde, 0x11, 0xe7, 0xb0, 0x3c, 0x77, 0x74, 0x2d, 0x99, 0x09, 0x10, 0xe8, + 0xd0, 0x1d, 0xe1, 0x6e, 0x76, 0x5c, 0x1d, 0x85, 0x78, 0x6f, 0x55, 0x01, 0x11, 0xe9, 0x1e, 0x54, + 0x26, 0xd3, 0x93, 0x91, 0x33, 0x20, 0x94, 0x1c, 0xb5, 0x42, 0x20, 0x44, 0x10, 0xfa, 0x2d, 0x51, + 0x14, 0x61, 0xe4, 0x11, 0xa3, 0x22, 0x61, 0x88, 0x82, 0xbc, 0x9d, 0xfb, 0xc8, 0x4e, 0xaa, 0x26, + 0xfe, 0x36, 0x36, 0x61, 0x39, 0x39, 0x68, 0x79, 0xf0, 0x3c, 0x84, 0x92, 0xe4, 0x55, 0xca, 0xf0, + 0x51, 0xd7, 0x4c, 0xd1, 0x42, 0x45, 0x8b, 0xca, 0x8d, 0xdf, 0x5e, 0x80, 0x25, 0x09, 0xdd, 0x12, + 0x4b, 0xdb, 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0xc2, 0x04, 0x33, 0x2f, 0x66, 0x82, 0xd9, 0x39, 0x26, + 0x98, 0xd4, 0x7c, 0x89, 0x87, 0x26, 0x35, 0x5f, 0xf1, 0x2e, 0x49, 0x19, 0xd1, 0xed, 0xa0, 0x35, + 0x09, 0xee, 0x93, 0xbd, 0x75, 0x8e, 0x65, 0x17, 0x52, 0x58, 0xb6, 0xce, 0x70, 0x17, 0x66, 0x18, + 0xee, 0x1b, 0x40, 0x44, 0xa3, 0xde, 0x7e, 0x91, 0xf4, 0x13, 0x84, 0x49, 0x63, 0xea, 0x3b, 0xd0, + 0x98, 0xe5, 0x71, 0xc4, 0x4c, 0xeb, 0x29, 0x1c, 0xce, 0x19, 0x73, 0x3c, 0xad, 0x34, 0xe4, 0xb2, + 0xe4, 0x70, 0xce, 0x98, 0xef, 0x61, 0x89, 0xc2, 0xef, 0x00, 0x50, 0xdf, 0xb8, 0x69, 0x00, 0x37, + 0xcd, 0xdb, 0xc9, 0x77, 0xa1, 0xaf, 0xfa, 0x86, 0x78, 0x98, 0xfa, 0x1c, 0x77, 0x51, 0x19, 0x6b, + 0xe2, 0x06, 0x7a, 0x06, 0x75, 0x6f, 0xc2, 0x5d, 0x2b, 0xe6, 0x35, 0x15, 0x6c, 0xea, 0xad, 0x17, + 0x34, 0xd5, 0x55, 0xb8, 0x66, 0x4d, 0xd4, 0x8d, 0x1e, 0xd9, 0x3e, 0x2d, 0x3c, 0xd7, 0x5a, 0xab, + 0x7e, 0x89, 0xd6, 0xea, 0x58, 0x39, 0x7a, 0x36, 0xfe, 0x56, 0x06, 0x2a, 0xda, 0xb0, 0xd9, 0x0a, + 0x2c, 0x6e, 0x1d, 0x1e, 0x1e, 0x75, 0xcc, 0x76, 0xbf, 0xfb, 0x49, 0xc7, 0xda, 0xda, 0x3b, 0xec, + 0x75, 0x9a, 0xb7, 0x04, 0x78, 0xef, 0x70, 0xab, 0xbd, 0x67, 0xed, 0x1c, 0x9a, 0x5b, 0x0a, 0x9c, + 0x61, 0xab, 0xc0, 0xcc, 0xce, 0xfe, 0x61, 0xbf, 0x93, 0x80, 0x67, 0x59, 0x13, 0xaa, 0x9b, 0x66, + 0xa7, 0xbd, 0xb5, 0x2b, 0x21, 0x39, 0xb6, 0x0c, 0xcd, 0x9d, 0xe3, 0x83, 0xed, 0xee, 0xc1, 0x53, + 0x6b, 0xab, 0x7d, 0xb0, 0xd5, 0xd9, 0xeb, 0x6c, 0x37, 0xf3, 0xac, 0x06, 0xe5, 0xf6, 0x66, 0xfb, + 0x60, 0xfb, 0xf0, 0xa0, 0xb3, 0xdd, 0x2c, 0x18, 0xbf, 0x02, 0xe5, 0x78, 0xa2, 0x15, 0x28, 0x1e, + 0x1f, 0x3c, 0x3b, 0x38, 0xfc, 0xf4, 0xa0, 0x79, 0x8b, 0x95, 0xa1, 0x80, 0xfd, 0x37, 0x33, 0x0c, + 0x60, 0x81, 0xfa, 0x6c, 0x66, 0x59, 0x09, 0xf2, 0x9b, 0x87, 0xfd, 0xdd, 0x66, 0xce, 0xf8, 0xf3, + 0x0c, 0xac, 0xe0, 0x94, 0x87, 0xb3, 0x4c, 0xe0, 0x3e, 0x54, 0x06, 0x9e, 0x37, 0x11, 0x9a, 0x56, + 0x2c, 0x51, 0xe8, 0x20, 0xb1, 0xc1, 0x89, 0x79, 0x9f, 0x7a, 0xfe, 0x80, 0x4b, 0x1e, 0x00, 0x08, + 0xda, 0x11, 0x10, 0x41, 0x83, 0x92, 0x88, 0x09, 0x83, 0x58, 0x40, 0x85, 0x60, 0x84, 0xb2, 0x0a, + 0x0b, 0x27, 0x3e, 0xb7, 0x07, 0xe7, 0x72, 0xf7, 0xcb, 0x27, 0xf6, 0xf5, 0xd8, 0x06, 0x30, 0x10, + 0x34, 0x35, 0xe2, 0x43, 0xdc, 0x02, 0x25, 0xb3, 0x21, 0xe1, 0x5b, 0x12, 0x2c, 0x4e, 0x23, 0xfb, + 0xc4, 0x76, 0x87, 0x9e, 0xcb, 0x87, 0x52, 0xd5, 0x88, 0x01, 0xc6, 0x11, 0xac, 0xce, 0xce, 0x4f, + 0xf2, 0x8b, 0x0f, 0x34, 0x7e, 0x41, 0x92, 0xff, 0xfa, 0xcd, 0xa4, 0xa0, 0xf1, 0x8e, 0xbf, 0x93, + 0x87, 0xbc, 0x90, 0x04, 0x6f, 0x14, 0x1a, 0x75, 0xd1, 0x3e, 0x37, 0xe7, 0xfe, 0x41, 0x53, 0x03, + 0x89, 0x08, 0x64, 0xcf, 0x2a, 0x23, 0x04, 0x45, 0x83, 0xa8, 0xd8, 0xe7, 0x83, 0x0b, 0x69, 0xd0, + 0xa2, 0x62, 0x93, 0x0f, 0x2e, 0x50, 0xa7, 0xb2, 0x43, 0xaa, 0x4b, 0xfb, 0xbd, 0x18, 0xd8, 0x21, + 0xd6, 0x94, 0x45, 0x58, 0xaf, 0x18, 0x15, 0x61, 0xad, 0x16, 0x14, 0x1d, 0xf7, 0xc4, 0x9b, 0xba, + 0x43, 0xdc, 0xde, 0x25, 0x53, 0x3d, 0xa2, 0xb7, 0x09, 0x39, 0x91, 0x38, 0x88, 0x68, 0x37, 0x97, + 0x04, 0xa0, 0x2f, 0x8e, 0xa2, 0xf7, 0xa0, 0x1c, 0x5c, 0xbb, 0x03, 0x7d, 0x0f, 0x2f, 0xcb, 0xf5, + 0x11, 0xb3, 0xdf, 0xe8, 0x5d, 0xbb, 0x03, 0xdc, 0xb1, 0xa5, 0x40, 0xfe, 0x62, 0xef, 0x43, 0x29, + 0xb2, 0xfb, 0x12, 0x07, 0xbe, 0xad, 0xd7, 0x50, 0xc6, 0x5e, 0x52, 0xaf, 0x23, 0x54, 0xf6, 0x08, + 0x16, 0xd0, 0x38, 0x1b, 0xb4, 0xaa, 0x58, 0x49, 0xc9, 0xfb, 0x62, 0x18, 0xe8, 0xe8, 0xe1, 0x43, + 0x34, 0xd4, 0x9a, 0x12, 0x6d, 0xfd, 0x19, 0xd4, 0x12, 0x6d, 0xe9, 0x4a, 0x74, 0x8d, 0x94, 0xe8, + 0xb7, 0x74, 0x25, 0x3a, 0x3e, 0x09, 0x64, 0x35, 0x5d, 0xa9, 0xfe, 0x35, 0x28, 0xa9, 0xa9, 0x88, + 0xfd, 0x27, 0xf7, 0x8e, 0xd5, 0xfb, 0xec, 0x60, 0xab, 0x79, 0x8b, 0x35, 0xa0, 0xd2, 0xde, 0xc2, + 0x2d, 0x8d, 0x80, 0x8c, 0x40, 0x39, 0x6a, 0xf7, 0x7a, 0x11, 0x24, 0x6b, 0xec, 0x40, 0x73, 0x76, + 0xa4, 0x82, 0x26, 0x43, 0x05, 0x93, 0xa6, 0xeb, 0x18, 0x20, 0x54, 0x24, 0xb2, 0x46, 0x93, 0x1c, + 0x4e, 0x0f, 0xc6, 0xfb, 0xd0, 0x14, 0xe7, 0x9a, 0x58, 0xaa, 0x40, 0x33, 0x01, 0x8f, 0x84, 0x6c, + 0xa7, 0x9b, 0xaf, 0x4b, 0x66, 0x85, 0x60, 0xd8, 0x95, 0xf1, 0x01, 0x2c, 0x6a, 0xd5, 0x62, 0x95, + 0x56, 0x9c, 0x95, 0xb3, 0x2a, 0x2d, 0x2a, 0x30, 0x54, 0x62, 0xac, 0xc1, 0x8a, 0x78, 0xec, 0x5c, + 0x70, 0x37, 0xec, 0x4d, 0x4f, 0xc8, 0xe7, 0xe8, 0x78, 0xae, 0x50, 0x6c, 0xca, 0x51, 0xc9, 0xcd, + 0x44, 0xbe, 0x21, 0xb5, 0xdf, 0x2c, 0x92, 0xc6, 0xba, 0xd6, 0x03, 0x56, 0xdc, 0xc0, 0xbf, 0x09, + 0x2d, 0xb8, 0x1c, 0x81, 0xc4, 0xb2, 0x1e, 0x75, 0x3a, 0xa6, 0x75, 0x78, 0xb0, 0xd7, 0x3d, 0x10, 0x8c, 0x52, 0x2c, 0x2b, 0x02, 0x76, 0x76, 0x10, 0x92, 0x31, 0x9a, 0x50, 0x7f, 0xca, 0xc3, 0xae, - 0x7b, 0xea, 0x29, 0xf7, 0xd9, 0xcf, 0x0a, 0xd0, 0x88, 0x40, 0xb1, 0x92, 0x7c, 0xc1, 0xfd, 0xc0, - 0xf1, 0x5c, 0x94, 0x77, 0xcb, 0xa6, 0xfa, 0x14, 0xb7, 0x9b, 0x33, 0xe4, 0x6e, 0xe8, 0x84, 0xd7, - 0x56, 0xc2, 0xa2, 0x56, 0x57, 0x60, 0x79, 0x8b, 0x2e, 0x43, 0xc1, 0x1e, 0x39, 0xb6, 0xf2, 0xc4, - 0xd2, 0x87, 0x80, 0x0e, 0xbc, 0x91, 0xe7, 0xa3, 0x68, 0x5b, 0x36, 0xe9, 0x83, 0x3d, 0x86, 0x65, - 0x21, 0x62, 0xeb, 0x66, 0x4e, 0xe4, 0x1f, 0x64, 0xdc, 0x63, 0xee, 0x74, 0x7c, 0x14, 0x9b, 0x3a, - 0x45, 0x89, 0xb8, 0x3b, 0x45, 0x0d, 0x29, 0x2c, 0x45, 0x15, 0x48, 0x5b, 0x5b, 0x74, 0xa7, 0xe3, + 0x7b, 0xea, 0x29, 0xff, 0xda, 0xcf, 0x0a, 0xd0, 0x88, 0x40, 0xb1, 0x16, 0x7d, 0xc1, 0xfd, 0xc0, + 0xf1, 0x5c, 0x14, 0x88, 0xcb, 0xa6, 0x7a, 0x14, 0xa7, 0x9b, 0x33, 0xe4, 0x6e, 0xe8, 0x84, 0xd7, + 0x56, 0xc2, 0xe4, 0x56, 0x57, 0x60, 0x79, 0x8a, 0x2e, 0x43, 0xc1, 0x1e, 0x39, 0xb6, 0x72, 0xd5, + 0xd2, 0x83, 0x80, 0x0e, 0xbc, 0x91, 0xe7, 0xa3, 0xec, 0x5b, 0x36, 0xe9, 0x81, 0x3d, 0x86, 0x65, + 0x21, 0x83, 0xeb, 0x76, 0x50, 0xe4, 0x1f, 0x64, 0xfd, 0x63, 0xee, 0x74, 0x7c, 0x14, 0xdb, 0x42, + 0x45, 0x89, 0x38, 0x3b, 0x45, 0x0d, 0x29, 0x2c, 0x45, 0x15, 0x48, 0x9d, 0x5b, 0x74, 0xa7, 0xe3, 0x36, 0x96, 0x44, 0xf8, 0x4f, 0x60, 0x45, 0xe0, 0x47, 0xe2, 0x55, 0x54, 0xa3, 0x81, 0x35, 0x44, - 0x63, 0x5d, 0x59, 0x16, 0xd5, 0xb9, 0x03, 0x65, 0x1a, 0x95, 0xd8, 0xf1, 0x02, 0x49, 0xe9, 0x38, - 0x14, 0xee, 0x07, 0x73, 0x4e, 0xd3, 0x05, 0x12, 0x04, 0x66, 0x9c, 0xa6, 0x9a, 0xdb, 0xb5, 0x34, - 0xeb, 0x76, 0x7d, 0x02, 0x2b, 0x27, 0x82, 0x04, 0xcf, 0xb9, 0x3d, 0xe4, 0xbe, 0x15, 0x13, 0x36, - 0x69, 0x23, 0x4b, 0xa2, 0x70, 0x17, 0xcb, 0xa2, 0x73, 0x20, 0xe4, 0x1c, 0xc1, 0x16, 0xf8, 0xd0, - 0x0a, 0x3d, 0x0b, 0xc5, 0x1f, 0x64, 0x30, 0x25, 0xb3, 0x46, 0xe0, 0xbe, 0xb7, 0x25, 0x80, 0x49, - 0xbc, 0x33, 0xdf, 0x9e, 0x9c, 0x4b, 0x7d, 0x21, 0xc2, 0x7b, 0x2a, 0x80, 0xec, 0x35, 0x28, 0x0a, - 0x92, 0x77, 0x39, 0xf9, 0xb6, 0x48, 0x22, 0x57, 0x20, 0xf6, 0x16, 0x2c, 0x60, 0x1f, 0x41, 0xab, - 0x89, 0xf4, 0x5e, 0x8d, 0x19, 0xb9, 0xe3, 0x9a, 0xb2, 0x4c, 0x08, 0x93, 0x53, 0xdf, 0x21, 0x2e, - 0x53, 0x36, 0xf1, 0x6f, 0xf6, 0x7d, 0x8d, 0x65, 0x2d, 0x61, 0x5d, 0x25, 0x0f, 0xcc, 0x50, 0xda, + 0x63, 0x5d, 0x59, 0x16, 0xd5, 0xb9, 0x03, 0x65, 0x1a, 0x95, 0x78, 0xe3, 0x05, 0x12, 0xe3, 0x71, + 0x28, 0xdc, 0x0f, 0xe6, 0xbc, 0xaa, 0x0b, 0x24, 0x08, 0xcc, 0x78, 0x55, 0x35, 0xbf, 0x6c, 0x69, + 0xd6, 0x2f, 0xfb, 0x04, 0x56, 0x4e, 0x04, 0x09, 0x9e, 0x73, 0x7b, 0xc8, 0x7d, 0x2b, 0x26, 0x6c, + 0x52, 0x57, 0x96, 0x44, 0xe1, 0x2e, 0x96, 0x45, 0xfb, 0x40, 0xc8, 0x39, 0x82, 0x2d, 0xf0, 0xa1, + 0x15, 0x7a, 0x16, 0x8a, 0x3f, 0xc8, 0x60, 0x4a, 0x66, 0x8d, 0xc0, 0x7d, 0x6f, 0x4b, 0x00, 0x93, + 0x78, 0x67, 0xbe, 0x3d, 0x39, 0x97, 0x0a, 0x45, 0x84, 0xf7, 0x54, 0x00, 0xd9, 0x6b, 0x50, 0x14, + 0x24, 0xef, 0x72, 0x72, 0x7e, 0x91, 0xc8, 0xae, 0x40, 0xec, 0x2d, 0x58, 0xc0, 0x3e, 0x82, 0x56, + 0x13, 0xe9, 0xbd, 0x1a, 0x33, 0x72, 0xc7, 0x35, 0x65, 0x99, 0x10, 0x26, 0xa7, 0xbe, 0x43, 0x5c, + 0xa6, 0x6c, 0xe2, 0x6f, 0xf6, 0x7d, 0x8d, 0x65, 0x2d, 0x61, 0x5d, 0x25, 0x0f, 0xcc, 0x50, 0xda, 0x4d, 0xdc, 0xeb, 0x2b, 0x65, 0x46, 0x3f, 0xc8, 0x97, 0x2a, 0xcd, 0xaa, 0xf1, 0x1d, 0x28, 0xd0, 0xea, 0x08, 0x22, 0xc4, 0xb5, 0xcb, 0x48, 0x22, 0x44, 0x68, 0x0b, 0x8a, 0x2e, 0x0f, 0x2f, 0x3d, - 0xff, 0xb9, 0xb2, 0x39, 0xcb, 0x4f, 0xe3, 0xc7, 0x68, 0x2c, 0x89, 0x1c, 0xea, 0xa4, 0xf7, 0x09, - 0xf2, 0xa0, 0xed, 0x0d, 0xce, 0x6d, 0x69, 0xbf, 0x29, 0x21, 0xa0, 0x77, 0x6e, 0xcf, 0x91, 0x47, - 0x76, 0xde, 0xa7, 0xfe, 0x16, 0xd4, 0x95, 0x0b, 0x3f, 0xb0, 0x46, 0xfc, 0x34, 0x94, 0xe4, 0x5e, - 0x95, 0xfe, 0xfb, 0x60, 0x8f, 0x9f, 0x86, 0xc6, 0x3e, 0x2c, 0x4a, 0x82, 0x3c, 0x9c, 0x70, 0xd5, - 0xf5, 0x77, 0xd3, 0xe4, 0xe9, 0xca, 0x93, 0xa5, 0xe4, 0x45, 0x4b, 0xa1, 0x09, 0x09, 0x21, 0xdb, - 0xf8, 0x18, 0x98, 0x7e, 0x0d, 0xcb, 0xf6, 0xa4, 0x54, 0xab, 0x4c, 0xf5, 0xca, 0xe3, 0x15, 0xc9, - 0xce, 0xce, 0x50, 0xac, 0x4e, 0x30, 0x1d, 0x0c, 0x54, 0x68, 0x45, 0xc9, 0x54, 0x9f, 0xc6, 0x9f, - 0x66, 0x60, 0x09, 0x1b, 0x53, 0xfa, 0x80, 0x64, 0xb2, 0x3f, 0xf7, 0x20, 0xc5, 0xfe, 0xe8, 0xb2, - 0x0f, 0x7d, 0x7c, 0x79, 0xe3, 0x68, 0x7e, 0xce, 0x38, 0xfa, 0x75, 0x68, 0x0e, 0xf9, 0xc8, 0xc1, - 0x28, 0x1b, 0x25, 0x4a, 0x90, 0x06, 0xd0, 0x50, 0x70, 0xa9, 0xec, 0x19, 0xff, 0x20, 0x03, 0x8b, - 0x24, 0xa9, 0xa0, 0xda, 0x2c, 0x17, 0xea, 0x23, 0xa5, 0x27, 0x4a, 0x56, 0x25, 0xe7, 0x14, 0xdf, - 0xe0, 0x08, 0x25, 0xe4, 0xdd, 0x5b, 0x52, 0x7f, 0x94, 0x50, 0xf6, 0x21, 0xea, 0x30, 0xae, 0x85, - 0xc0, 0x94, 0xa8, 0x9d, 0xe4, 0xa6, 0xec, 0xde, 0x42, 0x05, 0xc7, 0x45, 0xd0, 0x66, 0x49, 0x28, - 0xae, 0x02, 0x6c, 0xec, 0x40, 0x2d, 0xd1, 0x4d, 0xc2, 0x82, 0x5b, 0x25, 0x0b, 0xee, 0x9c, 0x97, - 0x24, 0x3b, 0xef, 0x25, 0xf9, 0x1b, 0x79, 0x60, 0x82, 0xa4, 0x66, 0x76, 0x6d, 0xc6, 0xc5, 0x98, - 0x9d, 0x73, 0x31, 0x3e, 0x06, 0xa6, 0x21, 0x28, 0xcf, 0x67, 0x2e, 0xf2, 0x7c, 0x36, 0x63, 0x5c, - 0xe9, 0xf8, 0x7c, 0x0c, 0xcb, 0x52, 0xa0, 0x8d, 0x7c, 0x8a, 0x68, 0x9a, 0xa3, 0xfd, 0x61, 0x24, - 0xd9, 0x2a, 0xdf, 0x22, 0x9a, 0xe9, 0x94, 0x7b, 0x51, 0xa8, 0xd8, 0x64, 0xd1, 0x42, 0xf7, 0x62, - 0xcf, 0x9e, 0x33, 0x91, 0x2f, 0xbc, 0x94, 0x0a, 0x8a, 0x73, 0x54, 0xa0, 0x19, 0x58, 0x4a, 0x49, - 0x03, 0x8b, 0x01, 0x35, 0xe5, 0x44, 0xa4, 0xd8, 0x09, 0x92, 0xde, 0x2a, 0xd2, 0x93, 0x88, 0xf1, - 0x13, 0x0f, 0xa0, 0xa9, 0xac, 0x20, 0x91, 0x09, 0x87, 0xe2, 0x02, 0xa4, 0x11, 0x6d, 0x4b, 0x19, - 0x72, 0x12, 0x06, 0xf3, 0xca, 0x8c, 0xc1, 0xfc, 0x5d, 0x58, 0x0c, 0x04, 0x11, 0x59, 0x53, 0x57, - 0x06, 0xf1, 0xf0, 0x21, 0xaa, 0x4e, 0x25, 0xb3, 0x89, 0x05, 0xc7, 0x31, 0x7c, 0xde, 0x3c, 0x51, - 0x4b, 0x31, 0x4f, 0xbc, 0x1f, 0xfb, 0xdb, 0x82, 0x73, 0x67, 0x8c, 0x17, 0x77, 0x1c, 0xf0, 0x22, - 0x17, 0xb8, 0x77, 0xee, 0x8c, 0x4d, 0xe5, 0xdc, 0x15, 0x1f, 0xc6, 0xbf, 0xcf, 0x40, 0x53, 0xd0, - 0x41, 0x82, 0xce, 0x7f, 0x05, 0xf0, 0x44, 0xbe, 0x22, 0x99, 0x57, 0x04, 0xae, 0xa2, 0xf2, 0xef, - 0x00, 0x92, 0xad, 0x25, 0xf4, 0x44, 0x49, 0xe4, 0xad, 0x24, 0x91, 0xc7, 0x8c, 0x6c, 0xf7, 0x16, - 0x29, 0x00, 0x02, 0x92, 0xe6, 0xe7, 0xcc, 0xa7, 0xf8, 0x39, 0xb5, 0xa3, 0xb0, 0x0b, 0xf0, 0x8c, - 0x5f, 0xef, 0x79, 0x03, 0xd4, 0xd0, 0xee, 0x02, 0x08, 0x82, 0x3c, 0xb5, 0xc7, 0x8e, 0xb4, 0xae, - 0x14, 0xcc, 0xf2, 0x73, 0x7e, 0xbd, 0x83, 0x00, 0xb1, 0x1b, 0xa2, 0x38, 0x3e, 0x0f, 0x05, 0xb3, - 0xf4, 0x9c, 0x5f, 0xd3, 0x61, 0xb0, 0xa0, 0xf6, 0x8c, 0x5f, 0x6f, 0x73, 0x12, 0xd7, 0x3c, 0x5f, - 0x50, 0x82, 0x6f, 0x5f, 0x0a, 0xf9, 0x2c, 0xe1, 0xa3, 0xac, 0xf8, 0xf6, 0xe5, 0x33, 0x7e, 0xad, - 0xfc, 0xa5, 0x45, 0x51, 0x3e, 0xf2, 0x06, 0xf2, 0x06, 0x52, 0xd1, 0x16, 0xf1, 0xa0, 0xcc, 0x85, - 0xe7, 0xf8, 0xb7, 0xf1, 0x27, 0x19, 0xa8, 0x89, 0xf1, 0x23, 0x83, 0x13, 0xeb, 0xae, 0x82, 0x76, - 0x32, 0x71, 0xd0, 0xce, 0x13, 0xc9, 0x1f, 0x88, 0x5b, 0x66, 0x6f, 0xe6, 0x96, 0xb8, 0xc0, 0xc4, - 0x2a, 0xdf, 0x83, 0x32, 0x9d, 0x2d, 0x71, 0x58, 0x73, 0x89, 0x5d, 0x4a, 0x4c, 0xc8, 0x2c, 0x21, - 0xda, 0x33, 0x8a, 0x11, 0xd0, 0x0c, 0x71, 0xb4, 0xc4, 0x65, 0x3f, 0x32, 0xbf, 0xa5, 0x6c, 0x43, - 0x21, 0xcd, 0xdd, 0x7c, 0x0c, 0x15, 0x8d, 0xa6, 0xd0, 0x6a, 0x17, 0x0d, 0x9e, 0x08, 0x30, 0x49, - 0x34, 0x89, 0xd9, 0xef, 0xde, 0x32, 0x6b, 0x03, 0x1d, 0xb0, 0xb9, 0x00, 0x79, 0x51, 0xc9, 0xf8, - 0x08, 0x16, 0xb5, 0x66, 0x49, 0x1b, 0x4d, 0x1b, 0x53, 0x26, 0x6d, 0x4c, 0xff, 0x28, 0x03, 0xcb, - 0xb2, 0x36, 0x06, 0x78, 0x39, 0xe2, 0xba, 0xde, 0x0f, 0xce, 0xd8, 0xaf, 0x40, 0x4d, 0xb4, 0x6e, - 0xf9, 0xfc, 0xcc, 0x09, 0x42, 0xae, 0x3c, 0x1c, 0x29, 0x87, 0x43, 0x70, 0x6d, 0x81, 0x6a, 0x4a, - 0x4c, 0xf6, 0x11, 0x54, 0xb0, 0x2a, 0xe9, 0xcb, 0x72, 0x5b, 0x5a, 0xf3, 0x15, 0x69, 0xa8, 0xbb, - 0xb7, 0x4c, 0x08, 0xa2, 0xaf, 0xcd, 0x32, 0x14, 0x43, 0xdf, 0x39, 0x3b, 0xe3, 0xbe, 0xb1, 0x1a, - 0x0d, 0x4d, 0x9c, 0x34, 0xde, 0x0b, 0xf9, 0x44, 0x08, 0x41, 0xc6, 0x7f, 0xcc, 0x40, 0x45, 0x9e, - 0x9d, 0x9f, 0xdb, 0xad, 0xb1, 0xae, 0x45, 0x28, 0x92, 0x6a, 0x1c, 0x07, 0x24, 0xbe, 0x03, 0x8d, - 0xb1, 0x10, 0x88, 0x84, 0xc0, 0x9e, 0xf0, 0x69, 0xd4, 0x15, 0x58, 0xca, 0x23, 0x1b, 0xb0, 0x84, - 0xe2, 0x49, 0x60, 0x85, 0xce, 0xc8, 0x52, 0x85, 0x32, 0x1a, 0x70, 0x91, 0x8a, 0xfa, 0xce, 0x68, - 0x5f, 0x16, 0x88, 0x5b, 0x3a, 0x08, 0xed, 0x33, 0x2e, 0x45, 0x5f, 0xfa, 0x30, 0x5a, 0xb0, 0x3a, - 0x23, 0xab, 0x2b, 0x3d, 0xe3, 0xbf, 0x35, 0x60, 0x6d, 0xae, 0x48, 0xea, 0x1b, 0x91, 0x2d, 0x7f, - 0xe4, 0x8c, 0x4f, 0xbc, 0xc8, 0x14, 0x96, 0xd1, 0x6c, 0xf9, 0x7b, 0xa2, 0x44, 0x99, 0xc2, 0x38, - 0xac, 0x28, 0x82, 0x40, 0x5b, 0x56, 0x24, 0xce, 0x67, 0x51, 0xd8, 0x7c, 0x2f, 0xc9, 0xa8, 0x66, - 0xbb, 0x53, 0x70, 0xfd, 0xfa, 0x5b, 0x9a, 0xcc, 0xc1, 0x02, 0x76, 0x0a, 0xad, 0x88, 0xee, 0xa4, - 0x7c, 0xa4, 0xe9, 0x26, 0xa2, 0xa7, 0x6f, 0xbc, 0xa4, 0xa7, 0x84, 0x91, 0xc4, 0x5c, 0x55, 0xe4, - 0x4a, 0x8d, 0x45, 0xfd, 0x5c, 0xc0, 0xeb, 0xaa, 0x1f, 0x94, 0x75, 0xe6, 0x7b, 0xcb, 0xbf, 0xd2, - 0xbc, 0xd0, 0xf8, 0x93, 0xec, 0xf2, 0x8e, 0x6c, 0x38, 0x2a, 0xd2, 0xfb, 0x3d, 0x87, 0xd5, 0x4b, - 0xdb, 0x09, 0xd5, 0xfc, 0x34, 0xb5, 0xa8, 0x80, 0xfd, 0x3d, 0x79, 0x49, 0x7f, 0x9f, 0x52, 0xe5, - 0x84, 0xf4, 0xb7, 0x7c, 0x39, 0x0f, 0x0c, 0xd6, 0xff, 0x6d, 0x16, 0xea, 0xc9, 0x56, 0xc4, 0xa1, - 0x96, 0x7c, 0x48, 0xc9, 0x13, 0x52, 0x1e, 0x97, 0x26, 0xda, 0x03, 0x92, 0x23, 0xe6, 0x8d, 0xc7, - 0xd9, 0x14, 0xe3, 0xb1, 0x6e, 0xb3, 0xcd, 0xbd, 0xcc, 0x07, 0x96, 0x7f, 0x25, 0x1f, 0x58, 0x21, - 0xcd, 0x07, 0x76, 0xb3, 0xe3, 0x64, 0xe1, 0xe7, 0x72, 0x9c, 0x14, 0x6f, 0x76, 0x9c, 0xac, 0xff, - 0x9f, 0x0c, 0xb0, 0x79, 0x4a, 0x65, 0x4f, 0xc9, 0x4e, 0xee, 0xf2, 0x91, 0xe4, 0x62, 0xdf, 0x7c, - 0x35, 0x6a, 0x57, 0x1b, 0xa4, 0x6a, 0xb3, 0x47, 0xb0, 0xa4, 0xc7, 0x0f, 0xeb, 0xaa, 0x4a, 0xcd, - 0x64, 0x7a, 0x51, 0xac, 0xd0, 0x6a, 0x0e, 0xc0, 0xfc, 0x4b, 0x1d, 0x80, 0x85, 0x97, 0x3a, 0x00, - 0x17, 0x92, 0x0e, 0xc0, 0xf5, 0xff, 0x9c, 0x81, 0xa5, 0x14, 0xa2, 0xfa, 0xea, 0xe6, 0x2c, 0x68, - 0x21, 0xc1, 0x62, 0xb2, 0x92, 0x16, 0x74, 0xee, 0xb2, 0x07, 0x95, 0xd8, 0xa7, 0xa4, 0xe2, 0xeb, - 0x1f, 0xbe, 0xec, 0xa4, 0xc7, 0x35, 0x4c, 0xbd, 0xfa, 0xfa, 0x17, 0x50, 0xd1, 0xca, 0xc4, 0x22, - 0x12, 0x05, 0x69, 0x61, 0x17, 0x74, 0x87, 0xa3, 0x9e, 0x75, 0x0f, 0xa4, 0x21, 0x97, 0xca, 0x89, - 0xd6, 0xe5, 0x85, 0x8d, 0x08, 0x1b, 0xb0, 0xa4, 0x5c, 0x18, 0x3c, 0x8e, 0xae, 0x92, 0x6c, 0x7f, - 0x51, 0x3a, 0x32, 0x78, 0x14, 0xac, 0xb5, 0xfe, 0x13, 0xa8, 0x25, 0x38, 0xc2, 0x57, 0xb7, 0x96, - 0xb3, 0x5a, 0x23, 0x8d, 0x55, 0xd7, 0x1a, 0xd7, 0xff, 0x77, 0x0e, 0xd8, 0x3c, 0x53, 0xfa, 0x65, - 0x0e, 0x61, 0x7e, 0xc7, 0x73, 0x29, 0x3b, 0xfe, 0xff, 0xec, 0x92, 0x7c, 0x17, 0x16, 0x65, 0x02, - 0x87, 0xe6, 0xe1, 0x21, 0xaa, 0x6f, 0x46, 0x05, 0x6a, 0x14, 0xdf, 0x99, 0x75, 0x24, 0x97, 0x12, - 0x31, 0xeb, 0x9a, 0x94, 0x30, 0xe3, 0x4f, 0x3e, 0x86, 0x05, 0xdb, 0x1d, 0x9c, 0x7b, 0x3e, 0x2a, - 0x2c, 0xf5, 0x27, 0xbf, 0xfa, 0xa5, 0xef, 0x89, 0x8d, 0x36, 0xd6, 0x47, 0xd1, 0xc4, 0x94, 0x8d, - 0x19, 0xef, 0x41, 0x45, 0x03, 0xa3, 0xd7, 0xa3, 0xbb, 0xbf, 0x79, 0xd8, 0xbc, 0xc5, 0x6a, 0x50, - 0x36, 0x3b, 0x5b, 0x87, 0x9f, 0x74, 0xcc, 0xce, 0x76, 0x33, 0xc3, 0x4a, 0x90, 0xdf, 0x3b, 0xec, - 0xf5, 0x9b, 0x59, 0x63, 0x1d, 0x5a, 0xb2, 0xc5, 0x79, 0x0b, 0xe8, 0xef, 0xe6, 0x23, 0xe3, 0x03, - 0x16, 0x4a, 0x5d, 0xe3, 0x5b, 0x50, 0xd5, 0xef, 0x70, 0x49, 0x11, 0x33, 0x4e, 0x46, 0xa1, 0x65, - 0x78, 0x1a, 0x13, 0xdc, 0x02, 0x72, 0x1d, 0x0d, 0xa3, 0x6a, 0x24, 0x98, 0xbd, 0xc0, 0xd7, 0x80, - 0x32, 0x67, 0x82, 0x0c, 0xff, 0x3f, 0xa8, 0x27, 0xcd, 0x81, 0xf2, 0xa8, 0xa7, 0x09, 0xdd, 0xa2, - 0x76, 0xc2, 0x3e, 0xc8, 0xbe, 0x0f, 0xcd, 0x59, 0x73, 0xa2, 0x0c, 0xed, 0xbd, 0xa1, 0x7e, 0xc3, - 0x49, 0x5a, 0x18, 0xd9, 0x2e, 0x2c, 0xa7, 0x49, 0x31, 0x48, 0x1f, 0x37, 0x6b, 0x5b, 0x6c, 0x5e, - 0x52, 0x61, 0xdf, 0x95, 0x56, 0xe3, 0x42, 0x9a, 0xef, 0x4d, 0x5b, 0xec, 0x0d, 0xfa, 0x4f, 0xb3, - 0x1f, 0x5f, 0x00, 0xc4, 0x30, 0xd6, 0x84, 0xea, 0xe1, 0x51, 0xe7, 0xc0, 0xda, 0xda, 0x6d, 0x1f, - 0x1c, 0x74, 0xf6, 0x9a, 0xb7, 0x18, 0x83, 0x3a, 0x3a, 0xcd, 0xb6, 0x23, 0x58, 0x46, 0xc0, 0xa4, - 0xf5, 0x5e, 0xc1, 0xb2, 0x6c, 0x19, 0x9a, 0xdd, 0x83, 0x19, 0x68, 0x8e, 0xb5, 0x60, 0xf9, 0xa8, - 0x43, 0x7e, 0xb6, 0x44, 0xbb, 0x79, 0x21, 0x19, 0xcb, 0xe9, 0x0a, 0xc9, 0x98, 0x12, 0x91, 0xe4, - 0x39, 0x50, 0x02, 0xe3, 0xef, 0x65, 0x60, 0x65, 0xa6, 0x20, 0x0e, 0x2f, 0x27, 0x71, 0x31, 0x29, - 0x28, 0x56, 0x11, 0xa8, 0x4e, 0xd3, 0xbb, 0xb0, 0x18, 0x69, 0xd0, 0x33, 0xec, 0xbe, 0x19, 0x15, - 0x28, 0xe4, 0x47, 0xb0, 0xa4, 0x29, 0xe2, 0x33, 0xbc, 0x82, 0x69, 0x45, 0xb2, 0x82, 0xb1, 0x16, - 0x85, 0xf1, 0xce, 0x8c, 0x7a, 0x48, 0xd9, 0x4d, 0x7a, 0x41, 0x6c, 0x54, 0x4f, 0x8e, 0x57, 0x7d, - 0xb2, 0xc7, 0x33, 0x84, 0x90, 0x1c, 0xad, 0xbe, 0xe1, 0xaa, 0xfb, 0x3f, 0x58, 0x00, 0xf6, 0xf1, - 0x94, 0xfb, 0xd7, 0x18, 0x3e, 0x1e, 0xbc, 0x2c, 0x9e, 0x4a, 0x69, 0x9b, 0xd9, 0x57, 0x4a, 0x11, - 0x49, 0x4b, 0xd1, 0xc8, 0xbf, 0x3c, 0x45, 0xa3, 0xf0, 0xb2, 0x14, 0x8d, 0x37, 0xa1, 0xe6, 0x9c, - 0xb9, 0x9e, 0x60, 0x85, 0x42, 0xe4, 0x0b, 0x5a, 0x0b, 0xf7, 0x73, 0x0f, 0xaa, 0x66, 0x55, 0x02, - 0x85, 0xc0, 0x17, 0xb0, 0x8f, 0x62, 0x24, 0x3e, 0x3c, 0xc3, 0x74, 0x22, 0x9d, 0x09, 0x76, 0x86, - 0x67, 0x5c, 0x2a, 0xd7, 0x68, 0x6e, 0x52, 0x95, 0x05, 0x3c, 0x60, 0x6f, 0x41, 0x3d, 0xf0, 0xa6, - 0x42, 0x82, 0x56, 0xcb, 0x40, 0x66, 0xf7, 0x2a, 0x41, 0x8f, 0x94, 0x8f, 0x65, 0x69, 0x1a, 0x70, - 0x6b, 0xec, 0x04, 0x81, 0x90, 0x7b, 0x06, 0x9e, 0x1b, 0xfa, 0xde, 0x48, 0x5a, 0xd2, 0x17, 0xa7, - 0x01, 0xdf, 0xa7, 0x92, 0x2d, 0x2a, 0x60, 0xdf, 0x8e, 0x87, 0x34, 0xb1, 0x1d, 0x3f, 0x68, 0x01, - 0x0e, 0x49, 0xcd, 0x14, 0x05, 0x55, 0xdb, 0xf1, 0xa3, 0xb1, 0x88, 0x8f, 0x60, 0x26, 0x75, 0xa4, - 0x32, 0x9b, 0x3a, 0xf2, 0xa3, 0xf4, 0xd4, 0x91, 0x1a, 0x36, 0xfd, 0x58, 0x36, 0x3d, 0xbf, 0xc5, - 0x5f, 0x2a, 0x83, 0x64, 0x3e, 0x23, 0xa6, 0xfe, 0x65, 0x32, 0x62, 0x1a, 0x69, 0x19, 0x31, 0xef, - 0x41, 0x05, 0x73, 0x15, 0xac, 0x73, 0x47, 0x08, 0x47, 0xe4, 0x19, 0x68, 0xea, 0xc9, 0x0c, 0xbb, - 0x8e, 0x1b, 0x9a, 0xe0, 0xab, 0x3f, 0x83, 0xf9, 0xe4, 0x94, 0xc5, 0x5f, 0x62, 0x72, 0x8a, 0xcc, - 0xa9, 0xd8, 0x80, 0x92, 0xda, 0x27, 0xc6, 0x20, 0x7f, 0xea, 0x7b, 0x63, 0x65, 0x31, 0x15, 0x7f, - 0xb3, 0x3a, 0x64, 0x43, 0x4f, 0x56, 0xce, 0x86, 0x9e, 0xf1, 0x9b, 0x50, 0xd1, 0x48, 0x8d, 0xbd, - 0x41, 0xb6, 0x19, 0xa1, 0x84, 0x48, 0xa9, 0x8d, 0x56, 0xb1, 0x2c, 0xa1, 0xdd, 0xa1, 0xe0, 0x37, - 0x43, 0xc7, 0xe7, 0x98, 0x46, 0x66, 0xf9, 0xfc, 0x82, 0xfb, 0x81, 0xb2, 0x60, 0x37, 0xa3, 0x02, - 0x93, 0xe0, 0xc6, 0x5f, 0x81, 0xa5, 0xc4, 0xde, 0x4a, 0x16, 0xf1, 0x16, 0x2c, 0xe0, 0xba, 0x29, - 0x0f, 0x63, 0x32, 0x49, 0x44, 0x96, 0x61, 0x7e, 0x30, 0x19, 0xdf, 0xad, 0x89, 0xef, 0x9d, 0x60, - 0x27, 0x19, 0xb3, 0x22, 0x61, 0x47, 0xbe, 0x77, 0x62, 0xfc, 0x79, 0x0e, 0x72, 0xbb, 0xde, 0x44, - 0x0f, 0xaa, 0xc9, 0xcc, 0x05, 0xd5, 0x48, 0xcd, 0xca, 0x8a, 0x34, 0x27, 0x29, 0x0c, 0xa3, 0xd9, - 0x59, 0x69, 0x4f, 0x0f, 0xa0, 0x2e, 0xf8, 0x44, 0xe8, 0x09, 0xd5, 0xf4, 0xd2, 0xf6, 0x49, 0xd4, - 0xcc, 0xd1, 0xe1, 0xb3, 0xc7, 0x61, 0xdf, 0xdb, 0x21, 0x38, 0x5b, 0x86, 0x5c, 0xa4, 0x17, 0x60, - 0xb1, 0xf8, 0x64, 0xab, 0xb0, 0x80, 0xc1, 0x93, 0xd7, 0xd2, 0x85, 0x26, 0xbf, 0xd8, 0x37, 0x61, - 0x29, 0xd9, 0x2e, 0xb1, 0x22, 0x29, 0x1b, 0xe9, 0x0d, 0x23, 0x4f, 0xba, 0x0d, 0x82, 0x8f, 0x10, - 0x8e, 0xf4, 0xc4, 0x9f, 0x72, 0x8e, 0x45, 0x1a, 0xd3, 0x2b, 0x25, 0x98, 0xde, 0x3d, 0xa8, 0x84, - 0xa3, 0x0b, 0x6b, 0x62, 0x5f, 0x8f, 0x3c, 0x7b, 0x28, 0xcf, 0x37, 0x84, 0xa3, 0x8b, 0x23, 0x82, - 0xb0, 0x47, 0x00, 0xe3, 0xc9, 0x44, 0x9e, 0x3d, 0xb4, 0xe2, 0xc6, 0xa4, 0xbc, 0x7f, 0x74, 0x44, - 0x24, 0x67, 0x96, 0xc7, 0x93, 0x09, 0xfd, 0xc9, 0xb6, 0xa1, 0x9e, 0x9a, 0xea, 0x75, 0x57, 0xc5, - 0xfa, 0x79, 0x93, 0x8d, 0x94, 0xc3, 0x59, 0x1b, 0xe8, 0xb0, 0xf5, 0xef, 0x03, 0xfb, 0x05, 0x13, - 0xae, 0xfa, 0x50, 0x8e, 0xc6, 0xa7, 0xe7, 0x2b, 0x61, 0xf4, 0x6e, 0x25, 0x91, 0xaf, 0xd4, 0x1e, - 0x0e, 0x7d, 0xc1, 0x17, 0xe9, 0xc2, 0x8c, 0x58, 0x3e, 0x68, 0x37, 0x66, 0x9b, 0xf8, 0xbe, 0xf1, - 0x97, 0x19, 0x28, 0x50, 0xf2, 0xd4, 0xdb, 0xd0, 0x20, 0xfc, 0x28, 0x40, 0x49, 0x3a, 0xde, 0xe8, - 0xde, 0xed, 0xcb, 0xd8, 0x24, 0x71, 0x2c, 0xb4, 0xc4, 0xcf, 0x6c, 0xb4, 0xf3, 0x5a, 0xf2, 0xe7, - 0x3d, 0x28, 0x47, 0x5d, 0x6b, 0xa4, 0x53, 0x52, 0x3d, 0xb3, 0xd7, 0x21, 0x7f, 0xee, 0x4d, 0x94, - 0x89, 0x03, 0xe2, 0x95, 0x34, 0x11, 0x1e, 0x8f, 0x45, 0xf4, 0x41, 0x83, 0x97, 0xaa, 0x79, 0xd4, - 0x09, 0x92, 0xc1, 0xfc, 0x1c, 0x17, 0x52, 0xe6, 0x78, 0x0c, 0x0d, 0xc1, 0x07, 0x34, 0x07, 0xf8, - 0xcd, 0x97, 0xe6, 0xd7, 0x85, 0x84, 0x37, 0x18, 0x4d, 0x87, 0x5c, 0x37, 0x30, 0x61, 0xb4, 0x8c, - 0x84, 0x2b, 0xc9, 0xda, 0xf8, 0x83, 0x0c, 0xf1, 0x17, 0xd1, 0x2e, 0x7b, 0x00, 0x79, 0x71, 0xbf, - 0xcd, 0x18, 0x40, 0xa3, 0x30, 0x6a, 0x81, 0x67, 0x22, 0x06, 0x66, 0x4b, 0x4f, 0xc7, 0xc9, 0xd6, - 0x6b, 0x66, 0xc5, 0x9d, 0x8e, 0x23, 0x1b, 0xcd, 0xd7, 0xd4, 0xb4, 0x66, 0xec, 0x1b, 0x34, 0xfb, - 0xe8, 0x98, 0x6e, 0x68, 0x61, 0x37, 0xf9, 0xc4, 0x8d, 0xa9, 0xa4, 0xc0, 0xe1, 0x19, 0xd7, 0xc2, - 0x6d, 0xfe, 0x28, 0x0b, 0xb5, 0xc4, 0x88, 0x30, 0xee, 0x48, 0x5c, 0x00, 0x64, 0x5c, 0x97, 0xfb, - 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9d, 0xb2, 0x89, 0x75, 0x8a, 0x5c, 0xfd, 0x39, 0xdd, 0xd5, - 0xff, 0x18, 0xca, 0x71, 0xc2, 0x6f, 0x72, 0x48, 0xa2, 0x3f, 0x15, 0x4c, 0x1e, 0x23, 0xc5, 0xc1, - 0x01, 0x05, 0x3d, 0x38, 0xe0, 0x7b, 0x9a, 0x2f, 0x79, 0x01, 0x9b, 0x31, 0xd2, 0x56, 0xf4, 0x97, - 0xe2, 0x49, 0x36, 0x3e, 0x82, 0x8a, 0x36, 0x78, 0xdd, 0x67, 0x9c, 0x49, 0xf8, 0x8c, 0xa3, 0xb4, - 0x8f, 0x6c, 0x9c, 0xf6, 0x61, 0xfc, 0x76, 0x16, 0x6a, 0xe2, 0x7c, 0x39, 0xee, 0xd9, 0x91, 0x37, - 0x72, 0x06, 0x68, 0x6c, 0x8f, 0x4e, 0x98, 0x14, 0xb4, 0xd4, 0x39, 0x93, 0x47, 0x8c, 0xe4, 0x2c, - 0x3d, 0xbb, 0x8d, 0x98, 0x74, 0x94, 0xdd, 0x66, 0x40, 0x4d, 0x30, 0xc6, 0x13, 0x3b, 0xe0, 0x5a, - 0x3a, 0xb2, 0x59, 0x39, 0xe5, 0x7c, 0xd3, 0x0e, 0x88, 0x43, 0x7e, 0x13, 0x96, 0x04, 0x0e, 0x26, - 0xf6, 0x8c, 0x9d, 0xd1, 0xc8, 0x21, 0x4c, 0xb2, 0xe0, 0x34, 0x4f, 0x39, 0x37, 0xed, 0x90, 0xef, - 0x8b, 0x02, 0x99, 0xbd, 0x5c, 0x1a, 0x3a, 0x81, 0x7d, 0x12, 0x47, 0x87, 0x45, 0xdf, 0xe8, 0x22, - 0xb3, 0xaf, 0x34, 0x17, 0x19, 0x65, 0xf8, 0x55, 0xc6, 0xf6, 0x55, 0xe4, 0x22, 0x9b, 0xa1, 0xa4, - 0xe2, 0x2c, 0x25, 0x19, 0xff, 0x21, 0x0b, 0x15, 0x8d, 0x2c, 0x5f, 0xe5, 0x76, 0xbd, 0x3b, 0xe7, - 0x1c, 0x29, 0xeb, 0x7e, 0x90, 0x37, 0x93, 0x5d, 0xa2, 0x27, 0x9d, 0xf2, 0xa4, 0x35, 0x02, 0xbe, - 0x03, 0x65, 0x71, 0xea, 0xde, 0x43, 0x5b, 0xa3, 0xcc, 0xf2, 0x47, 0xc0, 0xd1, 0xf4, 0x44, 0x15, - 0x3e, 0xc1, 0xc2, 0x42, 0x5c, 0xf8, 0x44, 0x14, 0xbe, 0x28, 0x24, 0xf4, 0x3b, 0x50, 0x95, 0xad, - 0xe2, 0x9e, 0xe2, 0x74, 0xe3, 0x53, 0x9f, 0xd8, 0x6f, 0xb3, 0x42, 0xdd, 0xd1, 0xe6, 0xcb, 0x8a, - 0x4f, 0x54, 0xc5, 0xd2, 0xcb, 0x2a, 0x3e, 0xa1, 0x0f, 0x63, 0x27, 0x8a, 0xb2, 0xc5, 0x28, 0x0e, - 0xc5, 0xc7, 0x1e, 0xc1, 0x92, 0x62, 0x57, 0x53, 0xd7, 0x76, 0x5d, 0x6f, 0xea, 0x0e, 0xb8, 0xca, - 0x07, 0x61, 0xb2, 0xe8, 0x38, 0x2e, 0x31, 0x86, 0x51, 0xc2, 0x20, 0x45, 0x83, 0x3c, 0x84, 0x02, - 0xc9, 0xe5, 0x24, 0x7c, 0xa4, 0x33, 0x2e, 0x42, 0x61, 0x0f, 0xa0, 0x40, 0xe2, 0x79, 0xf6, 0x46, - 0x66, 0x43, 0x08, 0xc6, 0x06, 0x34, 0x50, 0xc4, 0xd4, 0x38, 0xee, 0x8b, 0xa4, 0x12, 0x63, 0x19, - 0xd8, 0x01, 0x1d, 0x22, 0x3d, 0x4a, 0xe9, 0xbf, 0xe4, 0xa0, 0xa2, 0x81, 0x05, 0x5b, 0xc4, 0xb8, - 0x16, 0x6b, 0xe8, 0xd8, 0x63, 0xae, 0x5c, 0x3a, 0x35, 0xb3, 0x86, 0xd0, 0x6d, 0x09, 0x14, 0x97, - 0x82, 0x7d, 0x71, 0x66, 0x79, 0xd3, 0xd0, 0x1a, 0xf2, 0x33, 0x9f, 0x73, 0x29, 0x2c, 0x55, 0xed, - 0x8b, 0xb3, 0xc3, 0x69, 0xb8, 0x8d, 0x30, 0x81, 0x25, 0x88, 0x5a, 0xc3, 0x92, 0xa1, 0x18, 0x63, - 0xfb, 0x2a, 0xc6, 0x92, 0xf1, 0x40, 0xb4, 0x44, 0xf9, 0x28, 0x1e, 0x88, 0xd4, 0x96, 0x59, 0x4e, - 0x5e, 0x98, 0xe7, 0xe4, 0xdf, 0x86, 0x55, 0xe2, 0xe4, 0x92, 0x47, 0x58, 0x33, 0x24, 0xb5, 0x8c, - 0xa5, 0x72, 0x92, 0x9a, 0xfc, 0xd5, 0x14, 0x33, 0x50, 0xe7, 0x23, 0x70, 0x7e, 0x4c, 0x27, 0x2a, - 0x63, 0x8a, 0x99, 0xc9, 0xc6, 0x7b, 0xce, 0x8f, 0xb9, 0xc0, 0x44, 0x7f, 0xb3, 0x8e, 0x29, 0x23, - 0x8f, 0xc7, 0x8e, 0x3b, 0x8b, 0x69, 0x5f, 0x25, 0x31, 0xcb, 0x12, 0xd3, 0xbe, 0xd2, 0x31, 0xdf, - 0x87, 0xb5, 0x31, 0x1f, 0x3a, 0x76, 0xb2, 0x59, 0x2b, 0x96, 0x20, 0x96, 0xa9, 0x58, 0xab, 0xd3, - 0x23, 0x0d, 0x52, 0xac, 0xc6, 0x8f, 0xbd, 0xf1, 0x89, 0x43, 0x97, 0x27, 0x79, 0xc0, 0xf3, 0x66, - 0xdd, 0x9d, 0x8e, 0x7f, 0x88, 0x60, 0x51, 0x25, 0x30, 0x6a, 0x50, 0xe9, 0x85, 0xde, 0x44, 0x6d, - 0x73, 0x1d, 0xaa, 0xf4, 0x29, 0xb3, 0x7d, 0xee, 0xc0, 0x6d, 0xa4, 0xcd, 0xbe, 0x37, 0xf1, 0x46, - 0xde, 0xd9, 0x75, 0xc2, 0xa0, 0xf4, 0x9f, 0x32, 0xb0, 0x94, 0x28, 0x95, 0xe7, 0xfc, 0xdb, 0x74, - 0xb0, 0xa2, 0x94, 0x0d, 0x22, 0xe7, 0x45, 0xed, 0xf2, 0x21, 0x44, 0x3a, 0x55, 0x2a, 0x8d, 0xa3, - 0x1d, 0xa7, 0x1a, 0xab, 0x8a, 0x44, 0xdb, 0xad, 0x79, 0xda, 0x96, 0xf5, 0x55, 0x12, 0xb2, 0x6a, - 0xe2, 0x57, 0x65, 0x74, 0xf8, 0x50, 0x4e, 0x39, 0x97, 0x8c, 0x7f, 0xd5, 0x8d, 0x4f, 0x6a, 0x04, - 0xb1, 0x45, 0x2a, 0x30, 0xfe, 0x79, 0x06, 0x20, 0x1e, 0x1d, 0x46, 0xe0, 0x46, 0x17, 0x28, 0xbd, - 0xe2, 0xa3, 0x5d, 0x96, 0x6f, 0x40, 0x35, 0x0a, 0xc4, 0x8b, 0xaf, 0xe4, 0x8a, 0x82, 0x89, 0x7b, - 0xf9, 0x1d, 0x68, 0x9c, 0x8d, 0xbc, 0x13, 0x14, 0x9d, 0xe4, 0x05, 0x4a, 0x39, 0x4f, 0x75, 0x02, - 0xab, 0x6b, 0x31, 0xbe, 0xc0, 0xf3, 0xa9, 0xb1, 0x7a, 0xfa, 0x75, 0x6c, 0xfc, 0x4e, 0x36, 0x8a, - 0x48, 0x8a, 0x57, 0xe2, 0xc5, 0x7a, 0xc6, 0xcf, 0xe3, 0xd8, 0x7e, 0x91, 0x43, 0xe7, 0x23, 0xa8, - 0xfb, 0xc4, 0x1d, 0x15, 0xeb, 0xcc, 0xbf, 0x80, 0x75, 0xd6, 0xfc, 0xc4, 0x95, 0xfb, 0x75, 0x68, - 0xda, 0xc3, 0x0b, 0xee, 0x87, 0x0e, 0x9a, 0x8d, 0x51, 0x50, 0x93, 0x31, 0x40, 0x1a, 0x1c, 0x25, - 0xa2, 0x77, 0xa0, 0x21, 0x33, 0xd0, 0x22, 0x4c, 0xf9, 0xa6, 0x45, 0x0c, 0x16, 0x88, 0xc6, 0xbf, - 0x52, 0x21, 0x50, 0xc9, 0xdd, 0x7d, 0xf1, 0xaa, 0xe8, 0x33, 0xcc, 0xce, 0xbb, 0xac, 0x24, 0x21, - 0x49, 0x6b, 0xb4, 0xe4, 0x47, 0x04, 0x94, 0xb6, 0xe8, 0xe4, 0xb2, 0xe6, 0x5f, 0x65, 0x59, 0x8d, - 0x3f, 0xc9, 0x40, 0x71, 0xd7, 0x9b, 0x08, 0xbd, 0x5c, 0xc8, 0x73, 0x78, 0x4c, 0x22, 0x37, 0xc4, - 0x82, 0xf8, 0xec, 0x0e, 0x5f, 0x9c, 0x89, 0x91, 0x2a, 0x6f, 0xd4, 0x92, 0xf2, 0xc6, 0xf7, 0xe0, - 0x0e, 0x3a, 0x79, 0x7c, 0x6f, 0xe2, 0xf9, 0xe2, 0xa8, 0xda, 0x23, 0x92, 0x3b, 0x3c, 0x37, 0x3c, - 0x57, 0xbc, 0xf3, 0xf6, 0x29, 0xe7, 0x47, 0x1a, 0xc6, 0x7e, 0x84, 0x80, 0xa9, 0x4c, 0xa3, 0xf0, - 0xc2, 0x22, 0x55, 0x51, 0x0a, 0x46, 0xc4, 0x51, 0x1b, 0xa2, 0xa0, 0x83, 0x70, 0x14, 0x8d, 0x8c, - 0xef, 0x42, 0x39, 0xb2, 0x3a, 0xb0, 0x77, 0xa1, 0x7c, 0xee, 0x4d, 0xa4, 0x69, 0x22, 0x93, 0xc8, - 0x56, 0x91, 0xb3, 0x36, 0x4b, 0xe7, 0xf4, 0x47, 0x60, 0xfc, 0x79, 0x11, 0x8a, 0x5d, 0xf7, 0xc2, - 0x73, 0x06, 0x18, 0x44, 0x35, 0xe6, 0x63, 0x4f, 0xa5, 0xc1, 0x8a, 0xbf, 0x31, 0x50, 0x22, 0x7e, - 0x99, 0x22, 0x27, 0x03, 0x25, 0xa2, 0x37, 0x29, 0x56, 0x60, 0xc1, 0xd7, 0x9f, 0x96, 0x28, 0xf8, - 0x18, 0xd6, 0x19, 0x29, 0x6d, 0x05, 0x2d, 0x8d, 0x58, 0xb4, 0x45, 0x4f, 0x1e, 0xe0, 0x92, 0x51, - 0x5a, 0x52, 0x19, 0x21, 0xb8, 0x60, 0xaf, 0x41, 0x51, 0x26, 0x87, 0x50, 0xa8, 0x3d, 0xc5, 0x61, - 0x4a, 0x10, 0x52, 0x83, 0xcf, 0xc9, 0x49, 0x17, 0x49, 0x54, 0x42, 0x4f, 0x97, 0xc0, 0x6d, 0x41, - 0x6b, 0xf7, 0xa0, 0x42, 0xf8, 0x84, 0x52, 0x92, 0x61, 0x4f, 0x08, 0x42, 0x84, 0x94, 0x17, 0x5a, - 0xca, 0xa9, 0x2f, 0xb4, 0x60, 0x94, 0x5c, 0xc4, 0x65, 0x69, 0x8a, 0x40, 0xef, 0x72, 0x68, 0x70, - 0xf5, 0x3c, 0x91, 0x54, 0xee, 0x29, 0x4b, 0x4f, 0x29, 0xf7, 0x6f, 0x42, 0xed, 0xd4, 0x1e, 0x8d, - 0x4e, 0xec, 0xc1, 0x73, 0xd2, 0x49, 0xab, 0x64, 0x86, 0x53, 0x40, 0x54, 0x4a, 0xef, 0x41, 0x45, - 0xdb, 0x65, 0x8c, 0x69, 0xca, 0x9b, 0x10, 0xef, 0xef, 0xac, 0xa9, 0xa9, 0xfe, 0x0a, 0xa6, 0x26, - 0x2d, 0xb6, 0xab, 0x91, 0x8c, 0xed, 0xba, 0x83, 0xdc, 0x54, 0xc6, 0xff, 0x34, 0xe9, 0x11, 0x08, - 0x7b, 0x38, 0xc4, 0xf8, 0x1f, 0x7a, 0x71, 0x0d, 0x17, 0x8f, 0xca, 0x17, 0x49, 0xa8, 0x25, 0x18, - 0xa1, 0xdc, 0x25, 0x7b, 0xe9, 0xc4, 0x76, 0x86, 0x18, 0x4b, 0x4b, 0x6a, 0x6c, 0xd1, 0x1e, 0x87, - 0x47, 0xb6, 0x33, 0x64, 0xf7, 0xa1, 0xaa, 0x8a, 0xf1, 0x76, 0x5c, 0xa2, 0xf5, 0x97, 0xc5, 0xe2, - 0x4e, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe3, 0x54, 0xbb, 0x8a, 0x44, 0x41, 0x3a, 0x78, 0x0f, 0x63, - 0x2a, 0x42, 0x8e, 0x09, 0x75, 0xf5, 0x27, 0x77, 0xe4, 0x5c, 0x25, 0x95, 0xaa, 0xff, 0xc9, 0x4b, - 0x43, 0x98, 0x42, 0x10, 0x23, 0x67, 0xd1, 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0x2c, 0x22, 0x04, - 0xf6, 0x5d, 0x4d, 0x91, 0x6a, 0x21, 0xf2, 0x6b, 0x33, 0xed, 0xdf, 0x94, 0x4a, 0x70, 0x17, 0xc0, - 0x09, 0xc4, 0x2d, 0x13, 0x70, 0x77, 0x88, 0xb9, 0x71, 0x25, 0xb3, 0xec, 0x04, 0xcf, 0x08, 0xf0, - 0xd5, 0x6a, 0x58, 0x6d, 0xa8, 0xea, 0xd3, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0x75, 0x0e, 0x9a, 0xb7, - 0x58, 0x05, 0x8a, 0xbd, 0x4e, 0xbf, 0xbf, 0x87, 0x2e, 0xa7, 0x2a, 0x94, 0xa2, 0xcc, 0x9d, 0xac, - 0xf8, 0x6a, 0x6f, 0x6d, 0x75, 0x8e, 0xfa, 0x9d, 0xed, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, 0x99, - 0x33, 0xfe, 0x22, 0x07, 0x15, 0x6d, 0x15, 0x5e, 0xcc, 0x8c, 0xef, 0x02, 0xa0, 0x4a, 0x13, 0x87, - 0x87, 0xe5, 0xcd, 0xb2, 0x80, 0xd0, 0xe6, 0xeb, 0xc6, 0xf2, 0x1c, 0xbd, 0x2e, 0xa2, 0x8c, 0xe5, - 0x6f, 0x42, 0x8d, 0x1e, 0xea, 0xd0, 0x1d, 0x87, 0x05, 0xb3, 0x4a, 0x40, 0xc9, 0xaa, 0x31, 0xf5, - 0x0f, 0x91, 0x30, 0x29, 0x44, 0xa6, 0xed, 0x13, 0x08, 0xd3, 0x42, 0x30, 0xa7, 0x27, 0xf0, 0x46, - 0x17, 0x9c, 0x30, 0x48, 0x22, 0xac, 0x48, 0x58, 0x5f, 0xe6, 0x28, 0x4a, 0x7e, 0xa8, 0xe5, 0x9e, - 0x15, 0xcc, 0x2a, 0x01, 0x65, 0x47, 0xdf, 0x54, 0x04, 0x54, 0x42, 0x02, 0x5a, 0x9b, 0xa7, 0x86, - 0x04, 0xf1, 0xec, 0xcd, 0xd9, 0xb3, 0xca, 0x48, 0x18, 0x5f, 0x9b, 0xaf, 0xf7, 0x72, 0xbb, 0x16, - 0x7b, 0x17, 0xd8, 0x78, 0x32, 0xb1, 0x52, 0x2c, 0x4d, 0x79, 0xb3, 0x31, 0x9e, 0x4c, 0xfa, 0x9a, - 0x21, 0xe6, 0x2b, 0x30, 0x82, 0x7d, 0x0e, 0xac, 0x2d, 0x0e, 0x30, 0x0e, 0x31, 0x32, 0xa1, 0xc6, - 0x6c, 0x39, 0xa3, 0xb3, 0xe5, 0x14, 0xee, 0x97, 0x4d, 0xe5, 0x7e, 0x2f, 0xe2, 0x13, 0xc6, 0x0e, - 0x54, 0x8e, 0xb4, 0x67, 0x80, 0xee, 0x8b, 0x1b, 0x42, 0x3d, 0x00, 0x44, 0x77, 0x07, 0x19, 0xb7, - 0x7c, 0xf9, 0xee, 0x8f, 0x36, 0x9a, 0xac, 0x36, 0x1a, 0xe3, 0x9f, 0x65, 0xe8, 0x89, 0x85, 0x68, - 0xf0, 0xf1, 0xcb, 0x43, 0xca, 0x0f, 0x14, 0xa7, 0x88, 0x56, 0x94, 0xff, 0x47, 0x66, 0x77, 0xe2, - 0xd0, 0x2c, 0xef, 0xf4, 0x34, 0xe0, 0x2a, 0xd9, 0xa9, 0x82, 0xb0, 0x43, 0x04, 0x29, 0xe1, 0x5b, - 0x48, 0xf8, 0x0e, 0xb5, 0x1f, 0xc8, 0xa4, 0x27, 0x21, 0x7c, 0xef, 0xdb, 0x57, 0xb2, 0xd7, 0x40, - 0x88, 0x20, 0xd2, 0x50, 0xad, 0x52, 0xbc, 0xa2, 0x6f, 0xe3, 0x1f, 0xcb, 0x2c, 0xd6, 0xd9, 0xf5, - 0x7d, 0x08, 0xa5, 0xa8, 0xd5, 0xe4, 0x0d, 0xab, 0x30, 0xa3, 0x72, 0x71, 0x8f, 0xa3, 0x56, 0x9e, - 0x18, 0x31, 0x1d, 0x2e, 0x74, 0x36, 0x74, 0xb5, 0x51, 0x7f, 0x03, 0xd8, 0xa9, 0xe3, 0xcf, 0x22, - 0xd3, 0x61, 0x6b, 0x62, 0x89, 0x86, 0x6d, 0x1c, 0xc3, 0x92, 0xe2, 0x12, 0x9a, 0x46, 0x90, 0xdc, - 0xbc, 0xcc, 0x4b, 0x98, 0x7c, 0x76, 0x8e, 0xc9, 0x1b, 0x3f, 0xcd, 0x43, 0x51, 0x3d, 0xa9, 0x95, - 0xf6, 0x0c, 0x54, 0x39, 0xf9, 0x0c, 0x54, 0x2b, 0xf1, 0x64, 0x08, 0x6e, 0xbd, 0xbc, 0xef, 0xdf, - 0x99, 0xbd, 0xb2, 0x35, 0xa3, 0x79, 0xe2, 0xda, 0x5e, 0x85, 0xfc, 0xc4, 0x0e, 0xcf, 0xd1, 0x40, - 0x46, 0xc4, 0x83, 0xdf, 0xca, 0x98, 0x5e, 0x48, 0x1a, 0xd3, 0xd3, 0x9e, 0xcc, 0x22, 0x91, 0x74, - 0xee, 0xc9, 0xac, 0x3b, 0x40, 0xf2, 0x85, 0x16, 0x66, 0x54, 0x42, 0x80, 0xb8, 0x8b, 0x92, 0xe2, - 0x48, 0x69, 0x56, 0x1c, 0x79, 0x65, 0x51, 0xe1, 0xdb, 0xb0, 0x40, 0xe9, 0xe6, 0x32, 0x95, 0x4d, - 0x5d, 0x28, 0x72, 0x0d, 0xd5, 0xff, 0x14, 0x5b, 0x6c, 0x4a, 0x5c, 0xfd, 0xfd, 0x99, 0x4a, 0xe2, - 0xfd, 0x19, 0xdd, 0xc8, 0x5f, 0x4d, 0x1a, 0xf9, 0x1f, 0x40, 0x33, 0x5a, 0x50, 0x34, 0x99, 0xb9, - 0x81, 0x4c, 0x94, 0xa9, 0x2b, 0xb8, 0xe0, 0x92, 0x07, 0x41, 0x7c, 0x21, 0xd6, 0x13, 0x17, 0xa2, - 0xe0, 0x61, 0xed, 0x30, 0xe4, 0xe3, 0x49, 0x28, 0x2f, 0x44, 0x0c, 0xa5, 0xd7, 0x07, 0x98, 0x4c, - 0xf2, 0xac, 0x41, 0xb9, 0x7b, 0x60, 0xed, 0xec, 0x75, 0x9f, 0xee, 0xf6, 0x9b, 0x19, 0xf1, 0xd9, - 0x3b, 0xde, 0xda, 0xea, 0x74, 0xb6, 0xf1, 0xc6, 0x01, 0x58, 0xd8, 0x69, 0x77, 0xc5, 0xed, 0x93, - 0x33, 0x7e, 0x2f, 0x0b, 0x15, 0xad, 0x79, 0xf6, 0x7e, 0xb4, 0x2a, 0xf4, 0x44, 0xc9, 0xdd, 0xf9, - 0x21, 0x6c, 0x28, 0x56, 0xac, 0x2d, 0x4b, 0xf4, 0x40, 0x58, 0xf6, 0xc6, 0x07, 0xc2, 0xd8, 0xdb, - 0xd0, 0xb0, 0xa9, 0x85, 0x68, 0x15, 0xa4, 0x39, 0x58, 0x82, 0xe5, 0x22, 0x60, 0x70, 0x5d, 0x7c, - 0x9f, 0x08, 0xbc, 0xbc, 0x8a, 0x67, 0x8b, 0xae, 0x14, 0x5c, 0xac, 0xe2, 0xa9, 0xed, 0x8c, 0xa6, - 0x3e, 0x97, 0xee, 0xdb, 0xe8, 0x66, 0x26, 0xa8, 0xa9, 0x8a, 0x8d, 0x0f, 0x00, 0xe2, 0x31, 0x27, - 0x17, 0xe7, 0x56, 0x72, 0x71, 0x32, 0xda, 0xe2, 0x64, 0x8d, 0x6d, 0x62, 0x23, 0x72, 0xa1, 0x23, - 0x4f, 0xf5, 0x37, 0x41, 0x59, 0xa4, 0x2c, 0x0c, 0x6f, 0x9d, 0x8c, 0x78, 0xa8, 0xd2, 0x61, 0x17, - 0x65, 0x49, 0x37, 0x2a, 0x50, 0xd9, 0xe9, 0x71, 0x2b, 0x31, 0x37, 0x92, 0x24, 0x39, 0xcb, 0x8d, - 0x24, 0xaa, 0x19, 0x95, 0x1b, 0xeb, 0xd0, 0xda, 0xe6, 0xa2, 0xb5, 0xf6, 0x68, 0x34, 0x33, 0x1c, - 0xe3, 0x0e, 0xdc, 0x4e, 0x29, 0x93, 0x46, 0x88, 0x8f, 0x61, 0xa5, 0x4d, 0x99, 0xaf, 0x5f, 0x55, - 0x8a, 0x8b, 0xd1, 0x82, 0xd5, 0xd9, 0x26, 0x65, 0x67, 0x3b, 0xb0, 0xb8, 0xcd, 0x4f, 0xa6, 0x67, - 0x7b, 0xfc, 0x22, 0xee, 0x88, 0x41, 0x3e, 0x38, 0xf7, 0x2e, 0xe5, 0xfa, 0xe0, 0xdf, 0x18, 0x48, - 0x26, 0x70, 0xac, 0x60, 0xc2, 0x07, 0xca, 0x22, 0x8a, 0x90, 0xde, 0x84, 0x0f, 0x8c, 0xf7, 0x81, - 0xe9, 0xed, 0xc8, 0xf5, 0x12, 0x5a, 0xc2, 0xf4, 0xc4, 0x0a, 0xae, 0x83, 0x90, 0x8f, 0xd5, 0x0b, - 0x38, 0x10, 0x4c, 0x4f, 0x7a, 0x04, 0x31, 0xde, 0x81, 0xea, 0x91, 0x7d, 0x6d, 0xf2, 0xcf, 0x65, - 0xf2, 0xc6, 0x1a, 0x14, 0x27, 0xf6, 0xb5, 0x60, 0x03, 0x91, 0x73, 0x04, 0x8b, 0x8d, 0x3f, 0xcc, - 0xc3, 0x02, 0x61, 0xb2, 0xfb, 0xf4, 0x48, 0xa5, 0xe3, 0xe2, 0x31, 0x54, 0x8c, 0x52, 0x03, 0xcd, - 0xf1, 0xd2, 0xec, 0x3c, 0x2f, 0x95, 0x06, 0x34, 0xf5, 0x38, 0x87, 0x32, 0x63, 0xbb, 0xd3, 0xb1, - 0x7a, 0x91, 0x23, 0x99, 0xfe, 0x99, 0x8f, 0x1f, 0x21, 0xa5, 0xdc, 0xb8, 0xa4, 0xa3, 0x31, 0xd6, - 0x45, 0x68, 0x74, 0xea, 0x8a, 0x90, 0xec, 0x52, 0x07, 0xa5, 0x2a, 0x3c, 0x45, 0x95, 0x16, 0x94, - 0x54, 0x78, 0xe6, 0x14, 0x9b, 0xd2, 0xcb, 0x15, 0x1b, 0xb2, 0xac, 0xbd, 0x40, 0xb1, 0x81, 0x57, - 0x50, 0x6c, 0x5e, 0xc1, 0xc9, 0x77, 0x1b, 0x4a, 0x78, 0xef, 0x6b, 0xdc, 0x53, 0xdc, 0xf7, 0x82, - 0x7b, 0x7e, 0x47, 0x13, 0xfd, 0x29, 0xc2, 0xe0, 0x4e, 0x7c, 0x4c, 0x4c, 0xfe, 0xf9, 0x2f, 0xc7, - 0x79, 0xf2, 0x19, 0x14, 0x25, 0x54, 0x10, 0xb4, 0x6b, 0x8f, 0xd5, 0xfb, 0x46, 0xf8, 0xb7, 0x58, - 0x36, 0x7c, 0x94, 0xe5, 0xf3, 0xa9, 0xe3, 0xf3, 0xa1, 0x7a, 0xd9, 0xc2, 0xc1, 0x33, 0x2a, 0x20, - 0x62, 0x82, 0x42, 0x0d, 0x71, 0xbd, 0x4b, 0x57, 0xe6, 0xb5, 0x17, 0x9d, 0xe0, 0x99, 0xf8, 0x34, - 0x18, 0x34, 0xf1, 0x85, 0xb3, 0x89, 0xe7, 0xab, 0xcb, 0xc9, 0xf8, 0x69, 0x06, 0x9a, 0xf2, 0x74, - 0x45, 0x65, 0xba, 0x16, 0x50, 0xb8, 0xc9, 0x21, 0xfe, 0xe2, 0x77, 0x2a, 0x0c, 0xa8, 0xa1, 0xf1, - 0x23, 0xba, 0xa9, 0xc8, 0x78, 0x53, 0x11, 0xc0, 0x1d, 0x79, 0x5b, 0xbd, 0x0e, 0x15, 0x15, 0xe5, - 0x3a, 0x76, 0x46, 0xea, 0xbd, 0x61, 0x0a, 0x73, 0xdd, 0x77, 0x46, 0xea, 0xa2, 0xf3, 0x6d, 0x99, - 0xa6, 0x96, 0xc1, 0x8b, 0xce, 0xb4, 0x43, 0x6e, 0xfc, 0xbb, 0x0c, 0x2c, 0x6a, 0x53, 0x91, 0xe7, - 0xf6, 0x43, 0xa8, 0x46, 0x4f, 0x0b, 0xf2, 0x48, 0xf2, 0x5a, 0x4b, 0x32, 0x9a, 0xb8, 0x5a, 0x65, - 0x10, 0x41, 0x02, 0x31, 0x98, 0xa1, 0x7d, 0x8d, 0xe3, 0x0d, 0xa6, 0x63, 0xa5, 0xdc, 0x0c, 0xed, - 0xeb, 0x1d, 0xce, 0x7b, 0xd3, 0xb1, 0x50, 0x5d, 0x2f, 0x39, 0x7f, 0x1e, 0x21, 0x90, 0xcc, 0x05, - 0x02, 0x26, 0x31, 0x0c, 0xa8, 0x8d, 0x3d, 0x37, 0x3c, 0x8f, 0x50, 0xa4, 0xd4, 0x89, 0x40, 0xc2, - 0x31, 0xfe, 0x2c, 0x0b, 0x4b, 0x64, 0x62, 0x93, 0xa6, 0x4d, 0xc9, 0xba, 0x5a, 0xb0, 0x40, 0xd6, - 0x46, 0x62, 0x5e, 0xbb, 0xb7, 0x4c, 0xf9, 0xcd, 0xbe, 0xfd, 0x8a, 0x66, 0x41, 0x95, 0x09, 0x77, - 0xc3, 0xf2, 0xe7, 0xe6, 0x97, 0xff, 0xe6, 0xe5, 0x4d, 0xf3, 0xb8, 0x15, 0xd2, 0x3c, 0x6e, 0xaf, - 0xe2, 0xe7, 0x9a, 0x4b, 0x17, 0x2b, 0x4a, 0x1c, 0x2d, 0x5d, 0xec, 0x7d, 0x58, 0x4b, 0xe0, 0x20, - 0xb7, 0x76, 0x4e, 0x1d, 0xae, 0x9e, 0x0d, 0x58, 0xd6, 0xb0, 0x7b, 0xaa, 0x6c, 0xb3, 0x08, 0x85, - 0x60, 0xe0, 0x4d, 0xb8, 0xb1, 0x0a, 0xcb, 0xc9, 0x55, 0x95, 0xd7, 0xc4, 0xef, 0x67, 0xa0, 0x25, - 0xe3, 0x23, 0x1c, 0xf7, 0x6c, 0xd7, 0x09, 0x42, 0xcf, 0x8f, 0x9e, 0xe0, 0xbb, 0x0b, 0x10, 0x84, - 0xb6, 0x2f, 0xb5, 0x4d, 0x99, 0x28, 0x8f, 0x10, 0xd4, 0x24, 0x6f, 0x43, 0x89, 0xbb, 0x43, 0x2a, - 0x24, 0x6a, 0x28, 0x72, 0x77, 0xa8, 0xf4, 0xd0, 0x39, 0xf9, 0xbb, 0x96, 0x54, 0x2f, 0x64, 0xde, - 0xaa, 0x58, 0x1d, 0x7e, 0x81, 0x17, 0x6f, 0x3e, 0xca, 0x5b, 0xdd, 0xb7, 0xaf, 0x30, 0xda, 0x30, - 0x30, 0xfe, 0x7e, 0x16, 0x1a, 0xf1, 0xf8, 0x28, 0xe9, 0xfd, 0xc5, 0xe9, 0xfb, 0xf7, 0x25, 0x39, - 0x38, 0x42, 0x7e, 0xd7, 0x0c, 0x8f, 0x25, 0x3a, 0x9c, 0x5d, 0x97, 0x19, 0x50, 0x51, 0x18, 0xde, - 0x34, 0xd4, 0x5e, 0xc2, 0x2a, 0x13, 0xca, 0xe1, 0x34, 0x14, 0x0a, 0x97, 0xd0, 0x3c, 0x1d, 0x57, - 0xaa, 0x3c, 0x05, 0x7b, 0x1c, 0x76, 0xf1, 0x81, 0x6d, 0x01, 0x16, 0xd5, 0x68, 0x23, 0x05, 0x96, - 0xc0, 0x6f, 0x92, 0x9c, 0x4d, 0x3b, 0x87, 0x32, 0xb6, 0x2e, 0x84, 0xd2, 0x5b, 0xa3, 0x91, 0x10, - 0xfa, 0x3a, 0x54, 0xa8, 0xf1, 0x38, 0x3b, 0x30, 0x6f, 0x96, 0xb1, 0x07, 0x2c, 0x97, 0x46, 0x20, - 0x6f, 0x9a, 0x50, 0x7d, 0x81, 0xba, 0xc2, 0xf0, 0x83, 0xbf, 0x9d, 0x81, 0xdb, 0x29, 0xdb, 0x26, - 0x4f, 0xf9, 0x16, 0x2c, 0x9e, 0x46, 0x85, 0x6a, 0x75, 0xe9, 0xa8, 0xaf, 0x2a, 0xb6, 0x9a, 0x5c, - 0x53, 0xb3, 0x79, 0x9a, 0x04, 0xc4, 0x4a, 0x17, 0xed, 0x60, 0x22, 0x01, 0x14, 0x95, 0x2e, 0xda, - 0x46, 0xd2, 0x77, 0x8e, 0x60, 0xbd, 0x73, 0x25, 0x38, 0xc6, 0x96, 0xfe, 0x42, 0xbc, 0x22, 0xa3, - 0xa4, 0x81, 0x39, 0xf3, 0x4a, 0x06, 0xe6, 0x21, 0xe5, 0xb9, 0x45, 0x6d, 0xfd, 0x3c, 0x8d, 0xe0, - 0x05, 0x2a, 0xea, 0xd0, 0x0b, 0xf7, 0x2a, 0x09, 0x75, 0x10, 0xbd, 0x6c, 0x6f, 0x04, 0xd0, 0xd8, - 0x9f, 0x8e, 0x42, 0x27, 0x7e, 0xec, 0x9e, 0x7d, 0x5b, 0xd6, 0xc1, 0x7e, 0xd4, 0xaa, 0xa5, 0x76, - 0x04, 0x51, 0x47, 0xb8, 0x58, 0x63, 0xd1, 0x90, 0x35, 0xdf, 0x5f, 0x63, 0x9c, 0xec, 0xc1, 0xb8, - 0x0d, 0x6b, 0xf1, 0x17, 0x2d, 0x9b, 0xba, 0x6a, 0xfe, 0x69, 0x86, 0x42, 0x9b, 0x93, 0x0f, 0xef, - 0xb3, 0x0e, 0x2c, 0x05, 0x8e, 0x7b, 0x36, 0xe2, 0x7a, 0xf3, 0x81, 0x5c, 0x84, 0x95, 0xe4, 0xd8, - 0xe4, 0xe3, 0xfc, 0xe6, 0x22, 0xd5, 0x88, 0x5b, 0x0b, 0xd8, 0xe6, 0x4d, 0x83, 0x8c, 0xc9, 0x62, - 0x66, 0x35, 0xe6, 0x07, 0xdf, 0x85, 0x7a, 0xb2, 0x23, 0xf6, 0x1d, 0x99, 0xe3, 0x19, 0x8f, 0x2a, - 0x37, 0x93, 0xae, 0x17, 0x13, 0x44, 0x25, 0x5e, 0xfb, 0xc0, 0xf8, 0xbb, 0x19, 0x68, 0x99, 0x5c, - 0x50, 0xae, 0x36, 0x4a, 0x45, 0x33, 0x1f, 0xce, 0xb5, 0x7a, 0xf3, 0x5c, 0x55, 0xea, 0xa8, 0x1a, - 0xd1, 0x37, 0x6e, 0xdc, 0x8c, 0xdd, 0x5b, 0x73, 0x33, 0xda, 0x2c, 0xc1, 0x02, 0xa1, 0x18, 0x6b, - 0xb0, 0x22, 0xc7, 0xa3, 0xc6, 0x12, 0x7b, 0x0f, 0x13, 0x3d, 0x26, 0xbc, 0x87, 0xeb, 0xd0, 0xa2, - 0x97, 0x14, 0xf5, 0x49, 0xc8, 0x8a, 0xdb, 0xc0, 0xf6, 0xed, 0x81, 0xed, 0x7b, 0x9e, 0x7b, 0xc4, - 0x7d, 0x19, 0x28, 0x8a, 0x12, 0x26, 0x3a, 0xd7, 0x94, 0x28, 0x4c, 0x5f, 0xea, 0xfd, 0x3f, 0xcf, - 0x55, 0x71, 0x31, 0xf4, 0x65, 0x98, 0xb0, 0xb4, 0x69, 0x3f, 0xe7, 0xaa, 0x25, 0xb5, 0x44, 0x1f, - 0x41, 0x65, 0x12, 0x35, 0xaa, 0xd6, 0x5d, 0x25, 0x82, 0xcf, 0x77, 0x6b, 0xea, 0xd8, 0xc6, 0x13, - 0x58, 0x4e, 0xb6, 0x29, 0x59, 0xc7, 0x3a, 0x94, 0xc6, 0x12, 0x26, 0x47, 0x17, 0x7d, 0x1b, 0xbf, - 0x5b, 0x82, 0xa2, 0xd4, 0xe7, 0xd8, 0x06, 0xe4, 0x07, 0x2a, 0x36, 0x29, 0x7e, 0x5f, 0x44, 0x96, - 0xaa, 0xff, 0xb7, 0x30, 0x42, 0x49, 0xe0, 0xb1, 0x8f, 0xa0, 0x9e, 0xf4, 0x8a, 0xce, 0x64, 0x99, - 0x26, 0xdd, 0x99, 0xb5, 0xc1, 0x8c, 0xff, 0xab, 0x1c, 0x5f, 0x8e, 0x24, 0x33, 0x94, 0xce, 0xb5, - 0xdb, 0xd3, 0x73, 0x85, 0xbc, 0x1d, 0x9c, 0xdb, 0xd6, 0x93, 0xf7, 0x3f, 0x90, 0x69, 0xa6, 0x15, - 0x04, 0xf6, 0xce, 0xed, 0x27, 0xef, 0x7f, 0x30, 0x2b, 0x49, 0x53, 0xa6, 0xa1, 0x2e, 0x49, 0x2f, - 0x43, 0x81, 0x1e, 0xba, 0xa3, 0x20, 0x13, 0xfa, 0x60, 0x8f, 0x61, 0x59, 0xaa, 0xad, 0x96, 0x0c, - 0x07, 0x26, 0x2e, 0x58, 0xa2, 0xd4, 0x26, 0x59, 0xd6, 0xc3, 0x22, 0xb2, 0x0d, 0xad, 0xc2, 0xc2, - 0x79, 0xfc, 0x6a, 0x61, 0xcd, 0x94, 0x5f, 0xc6, 0x9f, 0x15, 0xa0, 0xa2, 0x2d, 0x0a, 0xab, 0x42, - 0xc9, 0xec, 0xf4, 0x3a, 0xe6, 0x27, 0x9d, 0xed, 0xe6, 0x2d, 0xf6, 0x00, 0xde, 0xea, 0x1e, 0x6c, - 0x1d, 0x9a, 0x66, 0x67, 0xab, 0x6f, 0x1d, 0x9a, 0x96, 0x7a, 0xe5, 0xe6, 0xa8, 0xfd, 0xd9, 0x7e, - 0xe7, 0xa0, 0x6f, 0x6d, 0x77, 0xfa, 0xed, 0xee, 0x5e, 0xaf, 0x99, 0x61, 0xaf, 0x41, 0x2b, 0xc6, - 0x54, 0xc5, 0xed, 0xfd, 0xc3, 0xe3, 0x83, 0x7e, 0x33, 0xcb, 0xee, 0xc1, 0x9d, 0x9d, 0xee, 0x41, - 0x7b, 0xcf, 0x8a, 0x71, 0xb6, 0xf6, 0xfa, 0x9f, 0x58, 0x9d, 0x5f, 0x3f, 0xea, 0x9a, 0x9f, 0x35, - 0x73, 0x69, 0x08, 0x42, 0x19, 0x57, 0x2d, 0xe4, 0xd9, 0x6d, 0x58, 0x21, 0x04, 0xaa, 0x62, 0xf5, - 0x0f, 0x0f, 0xad, 0xde, 0xe1, 0xe1, 0x41, 0xb3, 0xc0, 0x16, 0xa1, 0xd6, 0x3d, 0xf8, 0xa4, 0xbd, - 0xd7, 0xdd, 0xb6, 0xcc, 0x4e, 0x7b, 0x6f, 0xbf, 0xb9, 0xc0, 0x96, 0xa0, 0x31, 0x8b, 0x57, 0x14, - 0x4d, 0x28, 0xbc, 0xc3, 0x83, 0xee, 0xe1, 0x81, 0xf5, 0x49, 0xc7, 0xec, 0x75, 0x0f, 0x0f, 0x9a, - 0x25, 0xb6, 0x0a, 0x2c, 0x59, 0xb4, 0xbb, 0xdf, 0xde, 0x6a, 0x96, 0xd9, 0x0a, 0x2c, 0x26, 0xe1, - 0xcf, 0x3a, 0x9f, 0x35, 0x81, 0xb5, 0x60, 0x99, 0x06, 0x66, 0x6d, 0x76, 0xf6, 0x0e, 0x3f, 0xb5, - 0xf6, 0xbb, 0x07, 0xdd, 0xfd, 0xe3, 0xfd, 0x66, 0x05, 0xdf, 0xdd, 0xea, 0x74, 0xac, 0xee, 0x41, - 0xef, 0x78, 0x67, 0xa7, 0xbb, 0xd5, 0xed, 0x1c, 0xf4, 0x9b, 0x55, 0xea, 0x39, 0x6d, 0xe2, 0x35, - 0x51, 0x41, 0xe6, 0x0c, 0x58, 0xdb, 0xdd, 0x5e, 0x7b, 0x73, 0xaf, 0xb3, 0xdd, 0xac, 0xb3, 0xbb, - 0x70, 0xbb, 0xdf, 0xd9, 0x3f, 0x3a, 0x34, 0xdb, 0xe6, 0x67, 0x2a, 0xa7, 0xc0, 0xda, 0x69, 0x77, - 0xf7, 0x8e, 0xcd, 0x4e, 0xb3, 0xc1, 0xde, 0x80, 0xbb, 0x66, 0xe7, 0xe3, 0xe3, 0xae, 0xd9, 0xd9, - 0xb6, 0x0e, 0x0e, 0xb7, 0x3b, 0xd6, 0x4e, 0xa7, 0xdd, 0x3f, 0x36, 0x3b, 0xd6, 0x7e, 0xb7, 0xd7, - 0xeb, 0x1e, 0x3c, 0x6d, 0x36, 0xd9, 0x5b, 0x70, 0x3f, 0x42, 0x89, 0x1a, 0x98, 0xc1, 0x5a, 0x14, - 0xf3, 0x53, 0x5b, 0x7a, 0xd0, 0xf9, 0xf5, 0xbe, 0x75, 0xd4, 0xe9, 0x98, 0x4d, 0xc6, 0xd6, 0x61, - 0x35, 0xee, 0x9e, 0x3a, 0x90, 0x7d, 0x2f, 0x89, 0xb2, 0xa3, 0x8e, 0xb9, 0xdf, 0x3e, 0x10, 0x1b, - 0x9c, 0x28, 0x5b, 0x16, 0xc3, 0x8e, 0xcb, 0x66, 0x87, 0xbd, 0xc2, 0x18, 0xd4, 0xb5, 0x5d, 0xd9, - 0x69, 0x9b, 0xcd, 0x55, 0xd6, 0x80, 0xca, 0xfe, 0xd1, 0x91, 0xd5, 0xef, 0xee, 0x77, 0x0e, 0x8f, - 0xfb, 0xcd, 0x35, 0xb6, 0x02, 0xcd, 0xee, 0x41, 0xbf, 0x63, 0x8a, 0xbd, 0x56, 0x55, 0xff, 0x67, - 0x91, 0x2d, 0x43, 0x43, 0x8d, 0x54, 0x41, 0x7f, 0x56, 0x64, 0x6b, 0xc0, 0x8e, 0x0f, 0xcc, 0x4e, - 0x7b, 0x5b, 0x2c, 0x5c, 0x54, 0xf0, 0xbf, 0x8a, 0xd2, 0x43, 0xf2, 0xd3, 0x5c, 0x74, 0x59, 0xc7, - 0x21, 0x07, 0xc9, 0x37, 0x6c, 0xab, 0xda, 0xdb, 0xb3, 0x2f, 0x7b, 0x5d, 0x5e, 0x53, 0xad, 0x72, - 0x73, 0xaa, 0xd5, 0x9c, 0xee, 0x5e, 0xd3, 0x65, 0xbf, 0x37, 0xa1, 0x36, 0xa6, 0xf7, 0x6c, 0xe5, - 0xbb, 0x95, 0x20, 0xe3, 0x6f, 0x08, 0x48, 0x8f, 0x56, 0xce, 0x3d, 0xaf, 0x5e, 0x98, 0x7f, 0x5e, - 0x3d, 0x4d, 0xbe, 0x5f, 0x48, 0x93, 0xef, 0x1f, 0xc2, 0x22, 0xb1, 0x26, 0xc7, 0x75, 0xc6, 0x4a, - 0x6b, 0x26, 0x29, 0xb0, 0x81, 0x2c, 0x8a, 0xe0, 0x4a, 0x9d, 0x50, 0x2a, 0x87, 0x64, 0x21, 0x45, - 0xa9, 0x6d, 0x24, 0x34, 0x0d, 0xe2, 0x1c, 0x91, 0xa6, 0x11, 0xf5, 0x60, 0x5f, 0xc5, 0x3d, 0x54, - 0xb4, 0x1e, 0x08, 0x8e, 0x3d, 0x3c, 0x84, 0x45, 0x7e, 0x15, 0xfa, 0xb6, 0xe5, 0x4d, 0xec, 0xcf, - 0xa7, 0xe8, 0xc2, 0xb5, 0x51, 0x87, 0xaf, 0x9a, 0x0d, 0x2c, 0x38, 0x44, 0xf8, 0xb6, 0x1d, 0xda, - 0x0f, 0xbf, 0x80, 0x8a, 0xf6, 0xd6, 0x31, 0x5b, 0x83, 0xa5, 0x4f, 0xbb, 0xfd, 0x83, 0x4e, 0xaf, - 0x67, 0x1d, 0x1d, 0x6f, 0x3e, 0xeb, 0x7c, 0x66, 0xed, 0xb6, 0x7b, 0xbb, 0xcd, 0x5b, 0xe2, 0xd0, - 0x1e, 0x74, 0x7a, 0xfd, 0xce, 0x76, 0x02, 0x9e, 0x61, 0xaf, 0xc3, 0xfa, 0xf1, 0xc1, 0x71, 0xaf, - 0xb3, 0x6d, 0xa5, 0xd5, 0xcb, 0x0a, 0x2a, 0x95, 0xe5, 0x29, 0xd5, 0x73, 0x0f, 0xbf, 0x0f, 0xf5, - 0xe4, 0x03, 0x9c, 0x0c, 0x60, 0x61, 0xaf, 0xf3, 0xb4, 0xbd, 0xf5, 0x19, 0xbd, 0xcc, 0xd7, 0xeb, - 0xb7, 0xfb, 0xdd, 0x2d, 0x4b, 0xbe, 0xc4, 0x27, 0x38, 0x42, 0x86, 0x55, 0xa0, 0xd8, 0x3e, 0xd8, - 0xda, 0x3d, 0x34, 0x7b, 0xcd, 0xec, 0xc3, 0x8f, 0xa0, 0x39, 0xeb, 0x8f, 0x4a, 0x38, 0xf0, 0x5e, - 0xe4, 0xe9, 0x7b, 0xf8, 0x2f, 0x73, 0x00, 0x71, 0xc2, 0x80, 0x60, 0x35, 0xdb, 0xed, 0x7e, 0x7b, - 0xef, 0x50, 0x4c, 0xc3, 0x3c, 0xec, 0x0b, 0x0e, 0x62, 0x76, 0x3e, 0x6e, 0xde, 0x4a, 0x2d, 0x39, - 0x3c, 0xea, 0x37, 0x33, 0x62, 0xc5, 0xba, 0x07, 0xdd, 0x7e, 0xb7, 0xbd, 0x67, 0x99, 0x87, 0xc7, - 0xdd, 0x83, 0xa7, 0xf4, 0xe4, 0x18, 0x72, 0xd9, 0xe3, 0xa3, 0x1d, 0xf3, 0xf0, 0xa0, 0x6f, 0xf5, - 0x76, 0x8f, 0xfb, 0xdb, 0xf8, 0x60, 0xd9, 0x96, 0xd9, 0x3d, 0xa2, 0x36, 0xf3, 0x2f, 0x42, 0x10, - 0x4d, 0x17, 0xc4, 0x9a, 0x3f, 0x3d, 0xec, 0xf5, 0xba, 0x47, 0xd6, 0xc7, 0xc7, 0x1d, 0xb3, 0xdb, - 0xe9, 0x61, 0xc5, 0x85, 0x14, 0xb8, 0xc0, 0x2f, 0x0a, 0xde, 0xdc, 0xdf, 0xfb, 0x44, 0x32, 0x4f, - 0x81, 0x5a, 0x4a, 0x82, 0x04, 0x56, 0x59, 0xf0, 0x14, 0xc1, 0x7d, 0x52, 0x5a, 0x86, 0x1b, 0xca, - 0x44, 0xbd, 0x8a, 0xe0, 0xab, 0x73, 0x9b, 0x81, 0xd5, 0xaa, 0xe9, 0x45, 0xa2, 0x16, 0xb2, 0xdc, - 0xe8, 0x82, 0xda, 0xde, 0x36, 0xb1, 0x42, 0x7d, 0x0e, 0x2a, 0x70, 0x1b, 0x62, 0xa3, 0x04, 0x7b, - 0x12, 0x28, 0x4d, 0xf5, 0x21, 0x4a, 0x16, 0x9f, 0xfc, 0x4e, 0x0e, 0xea, 0x94, 0xbc, 0x45, 0x3f, - 0x35, 0xc5, 0x7d, 0xb6, 0x0f, 0x45, 0xf9, 0x9b, 0x65, 0x6c, 0x25, 0x7a, 0x0d, 0x4a, 0xff, 0x95, - 0xb4, 0xf5, 0xd5, 0x59, 0xb0, 0x14, 0xc7, 0x96, 0xfe, 0xda, 0x9f, 0xfe, 0x8f, 0xbf, 0x97, 0xad, - 0xb1, 0xca, 0xa3, 0x8b, 0xf7, 0x1e, 0x9d, 0x71, 0x37, 0x10, 0x6d, 0xfc, 0xff, 0x00, 0xf1, 0x2f, - 0x71, 0xb1, 0x56, 0xe4, 0x84, 0x9a, 0xf9, 0x99, 0xb2, 0xf5, 0xdb, 0x29, 0x25, 0xb2, 0xdd, 0xdb, - 0xd8, 0xee, 0x92, 0x51, 0x17, 0xed, 0x3a, 0xae, 0x13, 0xd2, 0xaf, 0x72, 0x7d, 0x98, 0x79, 0xc8, - 0x86, 0x50, 0xd5, 0x7f, 0x23, 0x8b, 0x29, 0x49, 0x29, 0xe5, 0x57, 0xbe, 0xd6, 0xef, 0xa4, 0x96, - 0x29, 0x19, 0x14, 0xfb, 0x58, 0x31, 0x9a, 0xa2, 0x8f, 0x29, 0x62, 0xc4, 0xbd, 0x8c, 0x48, 0x2a, - 0x8f, 0x7f, 0x0a, 0x8b, 0xbd, 0xa6, 0xc9, 0x55, 0x73, 0x3f, 0xc4, 0xb5, 0x7e, 0xf7, 0x86, 0x52, - 0xd9, 0xd7, 0x5d, 0xec, 0x6b, 0xcd, 0x60, 0xa2, 0xaf, 0x01, 0xe2, 0xa8, 0x1f, 0xe2, 0xfa, 0x30, - 0xf3, 0xf0, 0xc9, 0x5f, 0x3e, 0x80, 0x72, 0x14, 0xcc, 0xc9, 0x7e, 0x0b, 0x6a, 0x89, 0xec, 0x3a, - 0xa6, 0xa6, 0x91, 0x96, 0x8c, 0xb7, 0xfe, 0x5a, 0x7a, 0xa1, 0xec, 0xf8, 0x75, 0xec, 0xb8, 0xc5, - 0x56, 0x45, 0xc7, 0x32, 0x7b, 0xed, 0x11, 0x66, 0xc3, 0xd2, 0xdb, 0x5a, 0xcf, 0x35, 0xed, 0x83, - 0x3a, 0x7b, 0x6d, 0x56, 0x23, 0x48, 0xf4, 0x76, 0xf7, 0x86, 0x52, 0xd9, 0xdd, 0x6b, 0xd8, 0xdd, - 0x2a, 0x5b, 0xd6, 0xbb, 0x53, 0xa1, 0x97, 0x8c, 0xe3, 0x7b, 0x76, 0xfa, 0x2f, 0x45, 0xb1, 0xbb, - 0xf1, 0xeb, 0x63, 0x29, 0xbf, 0x20, 0x15, 0x91, 0xc8, 0xfc, 0xcf, 0x48, 0x19, 0x2d, 0xec, 0x8a, - 0x31, 0xdc, 0x3e, 0xfd, 0x87, 0xa2, 0xd8, 0x09, 0x54, 0xb4, 0x1f, 0x57, 0x60, 0xb7, 0x6f, 0xfc, - 0x21, 0x88, 0xf5, 0xf5, 0xb4, 0xa2, 0xb4, 0xa9, 0xe8, 0xed, 0x3f, 0x3a, 0xe5, 0x9c, 0xfd, 0x06, - 0x94, 0xa3, 0x27, 0xfb, 0xd9, 0x9a, 0xf6, 0x13, 0x0a, 0xfa, 0x4f, 0x0c, 0xac, 0xb7, 0xe6, 0x0b, - 0xd2, 0x88, 0x4f, 0x6f, 0x5d, 0x10, 0xdf, 0xa7, 0x50, 0xd1, 0x9e, 0xe5, 0x8f, 0x26, 0x30, 0xff, - 0xf4, 0x7f, 0x34, 0x81, 0x94, 0x57, 0xfc, 0x8d, 0x45, 0xec, 0xa2, 0xc2, 0xca, 0x48, 0xdf, 0xe1, - 0x95, 0x17, 0xb0, 0x3d, 0x58, 0x91, 0x9a, 0xd6, 0x09, 0xff, 0x32, 0xdb, 0x90, 0xf2, 0xe3, 0x5c, - 0x8f, 0x33, 0xec, 0x23, 0x28, 0xa9, 0x5f, 0x5f, 0x60, 0xab, 0xe9, 0xbf, 0x22, 0xb1, 0xbe, 0x36, - 0x07, 0x97, 0x6a, 0xd1, 0x67, 0x00, 0xf1, 0x6f, 0x00, 0x44, 0x4c, 0x62, 0xee, 0x37, 0x05, 0x22, - 0x0a, 0x98, 0xff, 0xc1, 0x00, 0x63, 0x15, 0x27, 0xd8, 0x64, 0xc8, 0x24, 0x5c, 0x7e, 0xa9, 0x1e, - 0x1d, 0xfd, 0x11, 0x54, 0xb4, 0x9f, 0x01, 0x88, 0x96, 0x6f, 0xfe, 0x27, 0x04, 0xa2, 0xe5, 0x4b, - 0xf9, 0xd5, 0x00, 0x63, 0x1d, 0x5b, 0x5f, 0x36, 0x1a, 0xa2, 0x75, 0x21, 0x6a, 0x49, 0x91, 0x47, - 0x6c, 0xd0, 0x39, 0xd4, 0x12, 0x6f, 0xfd, 0x47, 0x27, 0x34, 0xed, 0x97, 0x04, 0xa2, 0x13, 0x9a, - 0xfa, 0xf3, 0x00, 0x8a, 0xce, 0x8c, 0x45, 0xd1, 0xcf, 0x05, 0xa2, 0x68, 0x3d, 0xfd, 0x10, 0x2a, - 0xda, 0xbb, 0xfd, 0xd1, 0x5c, 0xe6, 0x7f, 0x22, 0x20, 0x9a, 0x4b, 0xda, 0x33, 0xff, 0xcb, 0xd8, - 0x47, 0xdd, 0x40, 0x52, 0xc0, 0x67, 0x13, 0x45, 0xdb, 0xbf, 0x05, 0xf5, 0xe4, 0x53, 0xfe, 0xd1, - 0xd9, 0x4f, 0xfd, 0x4d, 0x80, 0xe8, 0xec, 0xdf, 0xf0, 0xfe, 0xbf, 0x24, 0xe9, 0x87, 0x4b, 0x51, - 0x27, 0x8f, 0x7e, 0x22, 0xd3, 0x52, 0xbe, 0x60, 0x1f, 0x0b, 0x06, 0x27, 0x5f, 0xed, 0x64, 0x6b, - 0x1a, 0xd5, 0xea, 0xcf, 0x7f, 0x46, 0xe7, 0x65, 0xee, 0x81, 0xcf, 0x24, 0x31, 0x63, 0xe3, 0xec, - 0x29, 0x2c, 0x45, 0xc4, 0x1c, 0x3d, 0xc3, 0x19, 0x44, 0x73, 0x48, 0x7d, 0xec, 0x73, 0xbd, 0x39, - 0x5b, 0xfa, 0x38, 0x43, 0xd7, 0x1f, 0x3e, 0x7e, 0xa8, 0x5d, 0x7f, 0xfa, 0x4b, 0x9c, 0xda, 0xf5, - 0x97, 0x78, 0x23, 0x71, 0xf6, 0xfa, 0x0b, 0x1d, 0xd1, 0x86, 0x0b, 0x8d, 0xd9, 0x47, 0x31, 0xef, - 0xde, 0x94, 0xf6, 0x4f, 0xcd, 0xbf, 0xfe, 0xe2, 0x57, 0x01, 0x92, 0xac, 0x48, 0x71, 0xd3, 0x47, - 0x32, 0xf8, 0x84, 0xfd, 0x26, 0x54, 0xf5, 0xf7, 0xc1, 0x99, 0xce, 0x13, 0x66, 0x7b, 0xba, 0x93, - 0x5a, 0x96, 0xa4, 0x12, 0x56, 0xd5, 0xbb, 0x61, 0x9f, 0xc0, 0x6a, 0xb4, 0xcc, 0x7a, 0xde, 0x7a, - 0xc0, 0xee, 0xa5, 0x64, 0xb3, 0x27, 0x16, 0xfb, 0xf6, 0x8d, 0xe9, 0xee, 0x8f, 0x33, 0x82, 0xfa, - 0x92, 0x0f, 0x15, 0xc7, 0x37, 0x4f, 0xda, 0xfb, 0xcc, 0xf1, 0xcd, 0x93, 0xfa, 0xba, 0xb1, 0xa2, - 0x3e, 0xb6, 0x94, 0x58, 0x23, 0x0a, 0xcb, 0x65, 0x3f, 0x84, 0x86, 0x96, 0x94, 0xdf, 0xbb, 0x76, - 0x07, 0xd1, 0x49, 0x9a, 0x7f, 0x69, 0x6f, 0x3d, 0xcd, 0x36, 0x69, 0xac, 0x61, 0xfb, 0x8b, 0x46, - 0x62, 0x71, 0xc4, 0x29, 0xda, 0x82, 0x8a, 0x9e, 0xf0, 0xff, 0x82, 0x76, 0xd7, 0xb4, 0x22, 0xfd, - 0x51, 0xb7, 0xc7, 0x19, 0xb6, 0x07, 0xcd, 0xd9, 0x37, 0xa8, 0x22, 0x9e, 0x92, 0xf6, 0x6e, 0xd6, - 0xfa, 0x4c, 0x61, 0xe2, 0xe5, 0x2a, 0x76, 0x44, 0x89, 0x1d, 0xd1, 0x2f, 0x59, 0x79, 0xfe, 0xec, - 0xad, 0x9e, 0xfc, 0x85, 0xab, 0xa8, 0xb5, 0xb4, 0xdf, 0x36, 0x7b, 0x90, 0x79, 0x9c, 0x61, 0xbf, - 0x97, 0x81, 0x6a, 0xe2, 0xdd, 0x97, 0x44, 0xe8, 0xfc, 0xcc, 0x3c, 0x5b, 0x7a, 0x99, 0x3e, 0x51, - 0xc3, 0xc4, 0x45, 0xdc, 0x7b, 0xf8, 0x83, 0xc4, 0x26, 0xfd, 0x24, 0xe1, 0xda, 0xdb, 0x98, 0xfd, - 0xa9, 0xab, 0x2f, 0x66, 0x11, 0xf4, 0x07, 0x14, 0xbf, 0x78, 0x9c, 0x61, 0xff, 0x3a, 0x03, 0xf5, - 0xa4, 0xcf, 0x3e, 0x9a, 0x6e, 0x6a, 0x74, 0x40, 0x44, 0x4a, 0x37, 0x38, 0xfa, 0x7f, 0x88, 0xa3, - 0xec, 0x3f, 0x34, 0x13, 0xa3, 0x94, 0x4f, 0x6c, 0xff, 0x62, 0xa3, 0x65, 0x1f, 0xd2, 0x2f, 0x4b, - 0xaa, 0x50, 0x26, 0x36, 0xff, 0x4b, 0x84, 0x11, 0xf9, 0xe9, 0xbf, 0xdb, 0x87, 0x9b, 0xf0, 0x23, - 0xfa, 0x49, 0x27, 0x15, 0x19, 0x23, 0xa8, 0xf8, 0x55, 0xeb, 0x1b, 0x6f, 0xe1, 0x9c, 0x5e, 0x37, - 0x6e, 0x27, 0xe6, 0x34, 0x2b, 0x78, 0xb4, 0x69, 0x74, 0xf2, 0x67, 0xf7, 0xe2, 0x9b, 0x73, 0xee, - 0xa7, 0xf8, 0x6e, 0x1e, 0xe4, 0x98, 0x06, 0x29, 0xd1, 0x13, 0x47, 0xed, 0x15, 0x9b, 0x31, 0x1e, - 0xe2, 0x58, 0xdf, 0x32, 0xee, 0xdd, 0x38, 0xd6, 0x47, 0xe8, 0x7f, 0x17, 0x23, 0x3e, 0x02, 0x88, - 0x43, 0x0d, 0xd9, 0x4c, 0xc0, 0x5b, 0xc4, 0x80, 0xe6, 0xa3, 0x11, 0x93, 0xe7, 0x59, 0xc5, 0xc5, - 0x89, 0x16, 0x7f, 0x83, 0xd8, 0x69, 0x14, 0x8a, 0xa7, 0x4b, 0x5f, 0xc9, 0xa8, 0xc0, 0x84, 0xf4, - 0x35, 0xdb, 0x7e, 0x82, 0x99, 0x46, 0x71, 0x77, 0xc7, 0x50, 0xdb, 0xf3, 0xbc, 0xe7, 0xd3, 0x49, - 0x14, 0xde, 0x9e, 0x0c, 0x8a, 0xd9, 0xb5, 0x83, 0xf3, 0xf5, 0x99, 0x59, 0x18, 0xf7, 0xb1, 0xa9, - 0x75, 0xd6, 0xd2, 0x9a, 0x7a, 0xf4, 0x93, 0x38, 0xbe, 0xf1, 0x0b, 0x66, 0xc3, 0x62, 0xc4, 0xa3, - 0xe3, 0x18, 0xc2, 0x64, 0x33, 0x09, 0xce, 0x3c, 0xdb, 0x45, 0x42, 0x4d, 0x50, 0xa3, 0x7d, 0x14, - 0xa8, 0x36, 0x1f, 0x67, 0xd8, 0x11, 0x54, 0xb7, 0xf9, 0x00, 0x13, 0xf5, 0x31, 0xb4, 0x64, 0x29, - 0x11, 0xa6, 0x40, 0x31, 0x29, 0xeb, 0xb5, 0x04, 0x30, 0x79, 0x6f, 0x4d, 0xec, 0x6b, 0x9f, 0x7f, - 0xfe, 0xe8, 0x27, 0x32, 0x68, 0xe5, 0x0b, 0x75, 0x6f, 0xa9, 0xa0, 0x9e, 0xc4, 0xbd, 0x35, 0x13, - 0x05, 0x94, 0xb8, 0xb7, 0xe6, 0xa2, 0x80, 0x12, 0x4b, 0xad, 0x82, 0x8a, 0xd8, 0x08, 0x16, 0xe7, - 0x02, 0x87, 0xa2, 0x2b, 0xeb, 0xa6, 0x70, 0xa3, 0xf5, 0xfb, 0x37, 0x23, 0x24, 0x7b, 0x7b, 0x98, - 0xec, 0xad, 0x07, 0x35, 0x7a, 0xd3, 0xf1, 0x84, 0x53, 0xca, 0xde, 0xcc, 0x7b, 0x37, 0x7a, 0x3e, - 0xe0, 0xec, 0x05, 0x83, 0x65, 0x49, 0x09, 0x07, 0x73, 0xe5, 0xd8, 0x6f, 0x40, 0xe5, 0x29, 0x0f, - 0x55, 0x8e, 0x5e, 0x24, 0x63, 0xcf, 0x24, 0xed, 0xad, 0xa7, 0xa4, 0xf8, 0x25, 0x69, 0x06, 0x5b, - 0x7b, 0xc4, 0x87, 0x67, 0x9c, 0x98, 0x93, 0xe5, 0x0c, 0xbf, 0x60, 0xbf, 0x8e, 0x8d, 0x47, 0xa9, - 0xd1, 0xab, 0x5a, 0x12, 0x96, 0xde, 0x78, 0x63, 0x06, 0x9e, 0xd6, 0xb2, 0xeb, 0x0d, 0xb9, 0x26, - 0xeb, 0xb9, 0x50, 0xd1, 0x9e, 0x50, 0x88, 0x0e, 0xd0, 0xfc, 0x93, 0x19, 0xd1, 0x01, 0x4a, 0x79, - 0x71, 0xc1, 0x78, 0x80, 0xfd, 0x18, 0xec, 0x7e, 0xdc, 0x0f, 0xbd, 0xb2, 0x10, 0xf7, 0xf4, 0xe8, - 0x27, 0xf6, 0x38, 0xfc, 0x82, 0x7d, 0x8a, 0x2f, 0xa7, 0xeb, 0x39, 0x88, 0xb1, 0xd2, 0x30, 0x9b, - 0xae, 0x18, 0x2d, 0x96, 0x56, 0x94, 0x54, 0x24, 0xa8, 0x2b, 0x94, 0xe4, 0xde, 0x07, 0xe8, 0x85, - 0xde, 0x64, 0xdb, 0xe6, 0x63, 0xcf, 0x8d, 0x79, 0x6d, 0x9c, 0x15, 0x17, 0xf3, 0x2f, 0x2d, 0x35, - 0x8e, 0x7d, 0xaa, 0x69, 0x59, 0x89, 0x34, 0x4e, 0x45, 0x5c, 0x37, 0x26, 0xce, 0x45, 0x0b, 0x92, - 0x92, 0x3c, 0xf7, 0x38, 0xc3, 0xda, 0x00, 0x71, 0xe4, 0x58, 0xa4, 0x33, 0xcd, 0x05, 0xa5, 0x45, - 0x6c, 0x2f, 0x25, 0xcc, 0xec, 0x08, 0xca, 0x71, 0xc8, 0xcd, 0x5a, 0xfc, 0x22, 0x4c, 0x22, 0x40, - 0x27, 0xba, 0xc1, 0xe7, 0xc2, 0x5d, 0x8c, 0x26, 0x2e, 0x15, 0xb0, 0x92, 0x58, 0xaa, 0x53, 0xce, - 0x03, 0xe6, 0xc0, 0x12, 0x0d, 0x30, 0x12, 0x97, 0x30, 0x9b, 0x2b, 0x7a, 0x20, 0x7f, 0x3e, 0xf2, - 0x24, 0x3a, 0xcd, 0xa9, 0xf1, 0x13, 0x09, 0xd3, 0x8f, 0xa0, 0x56, 0xca, 0x24, 0x13, 0xac, 0x79, - 0x0c, 0x8b, 0x73, 0x2e, 0xfa, 0xe8, 0x48, 0xdf, 0x14, 0x73, 0x11, 0x1d, 0xe9, 0x1b, 0xbd, 0xfb, - 0xc6, 0x0a, 0x76, 0xd9, 0x30, 0x00, 0x55, 0xbd, 0x4b, 0x27, 0x1c, 0x9c, 0x8b, 0xee, 0xfe, 0x45, - 0x06, 0x96, 0x52, 0x9c, 0xf0, 0xec, 0x0d, 0x65, 0x35, 0xb8, 0xd1, 0x41, 0xbf, 0x9e, 0xea, 0xac, - 0x35, 0x7a, 0xd8, 0xcf, 0x3e, 0x7b, 0x96, 0xb8, 0xd8, 0xc8, 0x57, 0x2a, 0x4f, 0xe6, 0x0b, 0x85, - 0x8a, 0x54, 0x89, 0xe2, 0x73, 0x58, 0xa3, 0x81, 0xb4, 0x47, 0xa3, 0x19, 0x47, 0xf2, 0xeb, 0x73, - 0xbf, 0x3c, 0x9f, 0x70, 0x8e, 0xaf, 0xdf, 0xfc, 0xcb, 0xf4, 0x37, 0x88, 0xd3, 0x34, 0x54, 0x36, - 0x85, 0xe6, 0xac, 0x83, 0x96, 0xdd, 0xdc, 0xd6, 0xfa, 0xbd, 0x84, 0xfe, 0x9b, 0xe2, 0xd4, 0xfd, - 0x1a, 0x76, 0x76, 0xcf, 0x58, 0x4f, 0x5b, 0x17, 0x52, 0x89, 0xc5, 0x7e, 0xfc, 0xd5, 0xc8, 0x9b, - 0x3c, 0x33, 0x4f, 0xd5, 0xc1, 0x4d, 0xbe, 0xef, 0x48, 0x03, 0x4f, 0x77, 0x46, 0xbf, 0x8d, 0xdd, - 0xdf, 0x37, 0xee, 0xa4, 0x75, 0xef, 0x53, 0x15, 0xd2, 0xc5, 0xd7, 0x66, 0xcf, 0xb5, 0x1a, 0xc1, - 0xfd, 0xb4, 0xfd, 0xbe, 0x51, 0x17, 0x9a, 0x59, 0xeb, 0x5b, 0x28, 0xdb, 0x55, 0x75, 0xef, 0x71, - 0x74, 0x7c, 0x52, 0xdc, 0xd4, 0xd1, 0xf1, 0x49, 0x73, 0x37, 0x27, 0xe5, 0x1a, 0xe5, 0x68, 0xfe, - 0x30, 0xf3, 0x70, 0xf3, 0x9d, 0x1f, 0x7e, 0xed, 0xcc, 0x09, 0xcf, 0xa7, 0x27, 0x1b, 0x03, 0x6f, - 0xfc, 0x68, 0xa4, 0xac, 0x8d, 0x32, 0xe5, 0xf9, 0xd1, 0xc8, 0x1d, 0x3e, 0xc2, 0x66, 0x4f, 0x16, - 0x26, 0xbe, 0x17, 0x7a, 0xdf, 0xfa, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc3, 0xc3, 0x75, 0xd6, - 0x5c, 0x83, 0x00, 0x00, + 0xff, 0xb9, 0x32, 0x4a, 0xcb, 0x47, 0xe3, 0xc7, 0x68, 0x4d, 0x89, 0x3c, 0xee, 0xa4, 0x18, 0x0a, + 0xf2, 0xa0, 0xd7, 0x1b, 0x9c, 0xdb, 0xd2, 0xc0, 0x53, 0x42, 0x40, 0xef, 0xdc, 0x9e, 0x23, 0x8f, + 0xec, 0xbc, 0xd3, 0xfd, 0x2d, 0xa8, 0x2b, 0x1f, 0x7f, 0x60, 0x8d, 0xf8, 0x69, 0x28, 0xc9, 0xbd, + 0x2a, 0x1d, 0xfc, 0xc1, 0x1e, 0x3f, 0x0d, 0x8d, 0x7d, 0x58, 0x94, 0x04, 0x79, 0x38, 0xe1, 0xaa, + 0xeb, 0xef, 0xa6, 0xc9, 0xd3, 0x95, 0x27, 0x4b, 0xc9, 0x83, 0x96, 0x62, 0x17, 0x12, 0x42, 0xb6, + 0xf1, 0x31, 0x30, 0xfd, 0x18, 0x96, 0xed, 0x49, 0xa9, 0x56, 0xd9, 0xf2, 0x95, 0x4b, 0x2c, 0x92, + 0x9d, 0x9d, 0xa1, 0x58, 0x9d, 0x60, 0x3a, 0x18, 0xa8, 0xd8, 0x8b, 0x92, 0xa9, 0x1e, 0x8d, 0x3f, + 0xc9, 0xc0, 0x12, 0x36, 0xa6, 0xf4, 0x01, 0xc9, 0x64, 0x7f, 0xee, 0x41, 0x8a, 0xf7, 0xa3, 0xcb, + 0x3e, 0xf4, 0xf0, 0xe5, 0xad, 0xa7, 0xf9, 0x39, 0xeb, 0xe9, 0xd7, 0xa1, 0x39, 0xe4, 0x23, 0x07, + 0xc3, 0x70, 0x94, 0x28, 0x41, 0x1a, 0x40, 0x43, 0xc1, 0xa5, 0x36, 0x68, 0xfc, 0x83, 0x0c, 0x2c, + 0x92, 0xa4, 0x82, 0x7a, 0xb5, 0x5c, 0xa8, 0x8f, 0x94, 0x22, 0x29, 0x59, 0x95, 0x9c, 0x53, 0x7c, + 0x82, 0x23, 0x94, 0x90, 0x77, 0x6f, 0x49, 0x05, 0x53, 0x42, 0xd9, 0x87, 0xa8, 0xc3, 0xb8, 0x16, + 0x02, 0x53, 0xc2, 0x7a, 0x92, 0x2f, 0x65, 0xf7, 0x16, 0x2a, 0x38, 0x2e, 0x82, 0x36, 0x4b, 0x42, + 0xb3, 0x15, 0x60, 0x63, 0x07, 0x6a, 0x89, 0x6e, 0x12, 0x26, 0xde, 0x2a, 0x99, 0x78, 0xe7, 0xdc, + 0x28, 0xd9, 0x79, 0x37, 0xca, 0xdf, 0xc8, 0x03, 0x13, 0x24, 0x35, 0xf3, 0xd6, 0x66, 0x7c, 0x90, + 0xd9, 0x39, 0x1f, 0xe4, 0x63, 0x60, 0x1a, 0x82, 0x72, 0x8d, 0xe6, 0x22, 0xd7, 0x68, 0x33, 0xc6, + 0x95, 0x9e, 0xd1, 0xc7, 0xb0, 0x2c, 0x05, 0xda, 0xc8, 0xe9, 0x88, 0xb6, 0x3b, 0x7a, 0x3f, 0x8c, + 0x24, 0x5b, 0xe5, 0x7c, 0x44, 0x3b, 0x9e, 0xf2, 0x3f, 0x0a, 0x1d, 0x9c, 0x4c, 0x5e, 0xe8, 0x7f, + 0x54, 0xda, 0xb7, 0x46, 0x05, 0x0b, 0x2f, 0xa5, 0x82, 0xe2, 0x1c, 0x15, 0x68, 0x16, 0x98, 0x52, + 0xd2, 0x02, 0x63, 0x40, 0x4d, 0x79, 0x19, 0x29, 0xb8, 0x82, 0xa4, 0xb7, 0x8a, 0x74, 0x35, 0x62, + 0x80, 0xc5, 0x03, 0x68, 0x2a, 0x33, 0x49, 0x64, 0xe3, 0xa1, 0xc0, 0x01, 0x69, 0x65, 0xdb, 0x52, + 0x96, 0x9e, 0x84, 0x45, 0xbd, 0x32, 0x63, 0x51, 0x7f, 0x17, 0x16, 0x03, 0x41, 0x44, 0xd6, 0xd4, + 0x95, 0x51, 0x3e, 0x7c, 0x88, 0xaa, 0x53, 0xc9, 0x6c, 0x62, 0xc1, 0x71, 0x0c, 0x9f, 0xb7, 0x5f, + 0xd4, 0x52, 0xec, 0x17, 0xef, 0xc7, 0x0e, 0xb9, 0xe0, 0xdc, 0x19, 0xe3, 0xc1, 0x1d, 0x47, 0xc4, + 0xc8, 0x05, 0xee, 0x9d, 0x3b, 0x63, 0x53, 0x79, 0x7f, 0xc5, 0x83, 0xf1, 0xef, 0x32, 0xd0, 0x14, + 0x74, 0x90, 0xa0, 0xf3, 0x5f, 0x01, 0xdc, 0x91, 0xaf, 0x48, 0xe6, 0x15, 0x81, 0xab, 0xa8, 0xfc, + 0x3b, 0x80, 0x64, 0x6b, 0x09, 0x3d, 0x51, 0x12, 0x79, 0x2b, 0x49, 0xe4, 0x31, 0x23, 0xdb, 0xbd, + 0x45, 0x0a, 0x80, 0x80, 0xa4, 0x39, 0x42, 0xf3, 0x29, 0x8e, 0x50, 0x6d, 0x2b, 0xec, 0x02, 0x3c, + 0xe3, 0xd7, 0x7b, 0xde, 0x00, 0x35, 0xb4, 0xbb, 0x00, 0x82, 0x20, 0x4f, 0xed, 0xb1, 0x23, 0xad, + 0x2b, 0x05, 0xb3, 0xfc, 0x9c, 0x5f, 0xef, 0x20, 0x40, 0xbc, 0x0d, 0x51, 0x1c, 0xef, 0x87, 0x82, + 0x59, 0x7a, 0xce, 0xaf, 0x69, 0x33, 0x58, 0x50, 0x7b, 0xc6, 0xaf, 0xb7, 0x39, 0x89, 0x6b, 0x9e, + 0x2f, 0x28, 0xc1, 0xb7, 0x2f, 0x85, 0x7c, 0x96, 0x70, 0x62, 0x56, 0x7c, 0xfb, 0xf2, 0x19, 0xbf, + 0x56, 0x0e, 0xd5, 0xa2, 0x28, 0x1f, 0x79, 0x03, 0x79, 0x02, 0xa9, 0x70, 0x8c, 0x78, 0x50, 0xe6, + 0xc2, 0x73, 0xfc, 0x6d, 0xfc, 0x65, 0x06, 0x6a, 0x62, 0xfc, 0xc8, 0xe0, 0xc4, 0xba, 0xab, 0xa8, + 0x9e, 0x4c, 0x1c, 0xd5, 0xf3, 0x44, 0xf2, 0x07, 0xe2, 0x96, 0xd9, 0x9b, 0xb9, 0x25, 0x2e, 0x30, + 0xb1, 0xca, 0xf7, 0xa0, 0x4c, 0x7b, 0x4b, 0x6c, 0xd6, 0x5c, 0xe2, 0x2d, 0x25, 0x26, 0x64, 0x96, + 0x10, 0xed, 0x19, 0x05, 0x11, 0x68, 0x96, 0x3a, 0x5a, 0xe2, 0xb2, 0x1f, 0xd9, 0xe7, 0x52, 0x5e, + 0x43, 0xe1, 0x86, 0x20, 0x02, 0xdd, 0x0c, 0xb6, 0x30, 0x67, 0x06, 0x3b, 0x86, 0x8a, 0x46, 0x74, + 0x68, 0xf7, 0x8b, 0x66, 0x47, 0x14, 0x9a, 0xa4, 0xaa, 0xc4, 0xf2, 0xec, 0xde, 0x32, 0x6b, 0x03, + 0x1d, 0xb0, 0xb9, 0x00, 0x79, 0x51, 0xc9, 0xf8, 0x08, 0x16, 0xb5, 0x66, 0x49, 0x5d, 0x4d, 0x1b, + 0x74, 0x26, 0xcd, 0x89, 0xfe, 0x0f, 0x33, 0xb0, 0x2c, 0x6b, 0x63, 0x88, 0x98, 0x23, 0xce, 0xf3, + 0xfd, 0xe0, 0x8c, 0xfd, 0x0a, 0xd4, 0x44, 0xeb, 0x96, 0xcf, 0xcf, 0x9c, 0x20, 0xe4, 0xca, 0x47, + 0x92, 0xb2, 0x7b, 0x04, 0x5b, 0x17, 0xa8, 0xa6, 0xc4, 0x64, 0x1f, 0x41, 0x05, 0xab, 0x92, 0x42, + 0x2d, 0xdf, 0x5b, 0x6b, 0xbe, 0x22, 0x0d, 0x75, 0xf7, 0x96, 0x09, 0x41, 0xf4, 0xb4, 0x59, 0x86, + 0x62, 0xe8, 0x3b, 0x67, 0x67, 0xdc, 0x37, 0x56, 0xa3, 0xa1, 0x89, 0xad, 0xc8, 0x7b, 0x21, 0x9f, + 0x08, 0x29, 0xc9, 0xf8, 0x8f, 0x19, 0xa8, 0xc8, 0xcd, 0xf5, 0x73, 0x3b, 0x46, 0xd6, 0xb5, 0x18, + 0x47, 0xd2, 0x9d, 0xe3, 0x90, 0xc6, 0x77, 0xa0, 0x31, 0x16, 0x12, 0x93, 0x90, 0xe8, 0x13, 0x5e, + 0x91, 0xba, 0x02, 0x4b, 0x81, 0x65, 0x03, 0x96, 0x50, 0x7e, 0x09, 0xac, 0xd0, 0x19, 0x59, 0xaa, + 0x50, 0xc6, 0x13, 0x2e, 0x52, 0x51, 0xdf, 0x19, 0xed, 0xcb, 0x02, 0x71, 0x8c, 0x07, 0xa1, 0x7d, + 0xc6, 0x25, 0x6d, 0xd0, 0x83, 0xd1, 0x82, 0xd5, 0x19, 0x61, 0x5e, 0x29, 0x22, 0xff, 0xbd, 0x01, + 0x6b, 0x73, 0x45, 0x52, 0x21, 0x89, 0xbc, 0x01, 0x23, 0x67, 0x7c, 0xe2, 0x45, 0xb6, 0xb2, 0x8c, + 0xe6, 0x0d, 0xd8, 0x13, 0x25, 0xca, 0x56, 0xc6, 0x61, 0x45, 0x11, 0x04, 0x1a, 0xbb, 0x22, 0x79, + 0x3f, 0x8b, 0xd2, 0xe8, 0x7b, 0x49, 0x4e, 0x36, 0xdb, 0x9d, 0x82, 0xeb, 0xe7, 0xe3, 0xd2, 0x64, + 0x0e, 0x16, 0xb0, 0x53, 0x68, 0x45, 0x74, 0x27, 0x05, 0x28, 0x4d, 0x79, 0x11, 0x3d, 0x7d, 0xe3, + 0x25, 0x3d, 0x25, 0xac, 0x28, 0xe6, 0xaa, 0x22, 0x57, 0x6a, 0x2c, 0xea, 0xe7, 0x02, 0x5e, 0x57, + 0xfd, 0xa0, 0x30, 0x34, 0xdf, 0x5b, 0xfe, 0x95, 0xe6, 0x85, 0xd6, 0xa1, 0x64, 0x97, 0x77, 0x64, + 0xc3, 0x51, 0x91, 0xde, 0xef, 0x39, 0xac, 0x5e, 0xda, 0x4e, 0xa8, 0xe6, 0xa7, 0xe9, 0x4d, 0x05, + 0xec, 0xef, 0xc9, 0x4b, 0xfa, 0xfb, 0x94, 0x2a, 0x27, 0xc4, 0xc3, 0xe5, 0xcb, 0x79, 0x60, 0xb0, + 0xfe, 0x6f, 0xb2, 0x50, 0x4f, 0xb6, 0x22, 0x36, 0xb5, 0x64, 0x54, 0x4a, 0xe0, 0x90, 0x02, 0xbb, + 0xb4, 0xe1, 0x1e, 0x90, 0xa0, 0x31, 0x6f, 0x5d, 0xce, 0xa6, 0x58, 0x97, 0x75, 0xa3, 0x6e, 0xee, + 0x65, 0x5e, 0xb4, 0xfc, 0x2b, 0x79, 0xd1, 0x0a, 0x69, 0x5e, 0xb4, 0x9b, 0x5d, 0x2f, 0x0b, 0x3f, + 0x97, 0xeb, 0xa5, 0x78, 0xb3, 0xeb, 0x65, 0xfd, 0x2f, 0x33, 0xc0, 0xe6, 0x29, 0x95, 0x3d, 0x25, + 0x43, 0xba, 0xcb, 0x47, 0x92, 0x8b, 0x7d, 0xf3, 0xd5, 0xa8, 0x5d, 0xbd, 0x20, 0x55, 0x9b, 0x3d, + 0x82, 0x25, 0x3d, 0x02, 0x59, 0xd7, 0x65, 0x6a, 0x26, 0xd3, 0x8b, 0x62, 0x8d, 0x57, 0x73, 0x21, + 0xe6, 0x5f, 0xea, 0x42, 0x2c, 0xbc, 0xd4, 0x85, 0xb8, 0x90, 0x74, 0x21, 0xae, 0xff, 0x97, 0x0c, + 0x2c, 0xa5, 0x10, 0xd5, 0x57, 0x37, 0x67, 0x41, 0x0b, 0x09, 0x16, 0x93, 0x95, 0xb4, 0xa0, 0x73, + 0x97, 0x3d, 0xa8, 0xc4, 0x5e, 0x29, 0x15, 0xa1, 0xff, 0xf0, 0x65, 0x3b, 0x3d, 0xae, 0x61, 0xea, + 0xd5, 0xd7, 0xbf, 0x80, 0x8a, 0x56, 0x26, 0x16, 0x91, 0x28, 0x48, 0x0b, 0xdc, 0xa0, 0x43, 0x1e, + 0x15, 0xb1, 0x7b, 0x20, 0x2d, 0xbd, 0x54, 0x4e, 0xb4, 0x2e, 0x4f, 0x74, 0x44, 0xd8, 0x80, 0x25, + 0xe5, 0xe3, 0xe0, 0x71, 0x7c, 0x96, 0x64, 0xfb, 0x8b, 0xd2, 0xd3, 0xc1, 0xa3, 0x70, 0xaf, 0xf5, + 0x9f, 0x40, 0x2d, 0xc1, 0x11, 0xbe, 0xba, 0xb5, 0x9c, 0x55, 0x2b, 0x69, 0xac, 0xba, 0x5a, 0xb9, + 0xfe, 0x7f, 0x72, 0xc0, 0xe6, 0x99, 0xd2, 0x2f, 0x73, 0x08, 0xf3, 0x6f, 0x3c, 0x97, 0xf2, 0xc6, + 0xff, 0x9f, 0x1d, 0x92, 0xef, 0xc2, 0xa2, 0x4c, 0x01, 0xd1, 0x5c, 0x40, 0x44, 0xf5, 0xcd, 0xa8, + 0x40, 0x8d, 0xe2, 0x3b, 0xb3, 0xae, 0xe8, 0x52, 0x22, 0xea, 0x5d, 0x93, 0x12, 0x66, 0x3c, 0xd2, + 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, 0x47, 0x8d, 0xa6, 0xfe, 0xe4, 0x57, 0xbf, 0xf4, 0x39, + 0xb1, 0xd1, 0xc6, 0xfa, 0x28, 0x9a, 0x98, 0xb2, 0x31, 0xe3, 0x3d, 0xa8, 0x68, 0x60, 0x74, 0x8b, + 0x74, 0xf7, 0x37, 0x0f, 0x9b, 0xb7, 0x58, 0x0d, 0xca, 0x66, 0x67, 0xeb, 0xf0, 0x93, 0x8e, 0xd9, + 0xd9, 0x6e, 0x66, 0x58, 0x09, 0xf2, 0x7b, 0x87, 0xbd, 0x7e, 0x33, 0x6b, 0xac, 0x43, 0x4b, 0xb6, + 0x38, 0x6f, 0x22, 0xfd, 0xdd, 0x7c, 0x64, 0x9d, 0xc0, 0x42, 0xa9, 0x8c, 0x7c, 0x0b, 0xaa, 0xfa, + 0x19, 0x2e, 0x29, 0x62, 0xc6, 0x0b, 0x29, 0xd4, 0x10, 0x4f, 0x63, 0x82, 0x5b, 0x40, 0xbe, 0xa5, + 0x61, 0x54, 0x8d, 0x04, 0xb3, 0x17, 0x38, 0x23, 0x50, 0xe6, 0x4c, 0x90, 0xe1, 0xff, 0x07, 0xf5, + 0xa4, 0xbd, 0x50, 0x6e, 0xf5, 0x34, 0xa9, 0x5c, 0xd4, 0x4e, 0x18, 0x10, 0xd9, 0xf7, 0xa1, 0x39, + 0x6b, 0x6f, 0x94, 0xc1, 0xc1, 0x37, 0xd4, 0x6f, 0x38, 0x49, 0x13, 0x24, 0xdb, 0x85, 0xe5, 0x34, + 0x29, 0x06, 0xe9, 0xe3, 0x66, 0x75, 0x8c, 0xcd, 0x4b, 0x2a, 0xec, 0xbb, 0xd2, 0xac, 0x5c, 0x48, + 0x73, 0xce, 0x69, 0x8b, 0xbd, 0x41, 0xff, 0x34, 0x03, 0xf3, 0x05, 0x40, 0x0c, 0x63, 0x4d, 0xa8, + 0x1e, 0x1e, 0x75, 0x0e, 0xac, 0xad, 0xdd, 0xf6, 0xc1, 0x41, 0x67, 0xaf, 0x79, 0x8b, 0x31, 0xa8, + 0xa3, 0x57, 0x6d, 0x3b, 0x82, 0x65, 0x04, 0x4c, 0x9a, 0xf7, 0x15, 0x2c, 0xcb, 0x96, 0xa1, 0xd9, + 0x3d, 0x98, 0x81, 0xe6, 0x58, 0x0b, 0x96, 0x8f, 0x3a, 0xe4, 0x88, 0x4b, 0xb4, 0x9b, 0x17, 0x92, + 0xb1, 0x9c, 0xae, 0x90, 0x8c, 0x29, 0x95, 0x49, 0xee, 0x03, 0x25, 0x30, 0xfe, 0x5e, 0x06, 0x56, + 0x66, 0x0a, 0xe2, 0x00, 0x75, 0x12, 0x17, 0x93, 0x82, 0x62, 0x15, 0x81, 0x6a, 0x37, 0xbd, 0x0b, + 0x8b, 0x91, 0x8a, 0x3d, 0xc3, 0xee, 0x9b, 0x51, 0x81, 0x42, 0x7e, 0x04, 0x4b, 0x9a, 0xa6, 0x3e, + 0xc3, 0x2b, 0x98, 0x56, 0x24, 0x2b, 0x18, 0x6b, 0x51, 0x20, 0xf0, 0xcc, 0xa8, 0x87, 0x94, 0x1f, + 0xa5, 0x17, 0xc4, 0x56, 0xf7, 0xe4, 0x78, 0xd5, 0x23, 0x7b, 0x3c, 0x43, 0x08, 0xc9, 0xd1, 0xea, + 0x2f, 0x5c, 0x75, 0xff, 0x07, 0x0b, 0xc0, 0x3e, 0x9e, 0x72, 0xff, 0x1a, 0x03, 0xd0, 0x83, 0x97, + 0x45, 0x64, 0x29, 0x75, 0x34, 0xfb, 0x4a, 0x49, 0x26, 0x69, 0x49, 0x1e, 0xf9, 0x97, 0x27, 0x79, + 0x14, 0x5e, 0x96, 0xe4, 0xf1, 0x26, 0xd4, 0x9c, 0x33, 0xd7, 0x13, 0xac, 0x50, 0x88, 0x7c, 0x41, + 0x6b, 0xe1, 0x7e, 0xee, 0x41, 0xd5, 0xac, 0x4a, 0xa0, 0x10, 0xf8, 0x02, 0xf6, 0x51, 0x8c, 0xc4, + 0x87, 0x67, 0x98, 0x90, 0xa4, 0x33, 0xc1, 0xce, 0xf0, 0x8c, 0x4b, 0xed, 0x1b, 0xed, 0x51, 0xaa, + 0xb2, 0x80, 0x07, 0xec, 0x2d, 0xa8, 0x07, 0xde, 0x54, 0x48, 0xd0, 0x6a, 0x19, 0xc8, 0x2e, 0x5f, + 0x25, 0xe8, 0x91, 0x72, 0xc2, 0x2c, 0x4d, 0x03, 0x6e, 0x8d, 0x9d, 0x20, 0x10, 0x72, 0xcf, 0xc0, + 0x73, 0x43, 0xdf, 0x1b, 0x49, 0x53, 0xfb, 0xe2, 0x34, 0xe0, 0xfb, 0x54, 0xb2, 0x45, 0x05, 0xec, + 0xdb, 0xf1, 0x90, 0x26, 0xb6, 0xe3, 0x07, 0x2d, 0xc0, 0x21, 0xa9, 0x99, 0xa2, 0xa0, 0x6a, 0x3b, + 0x7e, 0x34, 0x16, 0xf1, 0x10, 0xcc, 0x24, 0x9f, 0x54, 0x66, 0x93, 0x4f, 0x7e, 0x94, 0x9e, 0x7c, + 0x52, 0xc3, 0xa6, 0x1f, 0xcb, 0xa6, 0xe7, 0x5f, 0xf1, 0x97, 0xca, 0x41, 0x99, 0xcf, 0xa9, 0xa9, + 0x7f, 0x99, 0x9c, 0x9a, 0x46, 0x5a, 0x4e, 0xcd, 0x7b, 0x50, 0xc1, 0x6c, 0x07, 0xeb, 0xdc, 0x11, + 0xc2, 0x11, 0xb9, 0x0e, 0x9a, 0x7a, 0x3a, 0xc4, 0xae, 0xe3, 0x86, 0x26, 0xf8, 0xea, 0x67, 0x30, + 0x9f, 0xde, 0xb2, 0xf8, 0x4b, 0x4c, 0x6f, 0x91, 0x59, 0x19, 0x1b, 0x50, 0x52, 0xef, 0x89, 0x31, + 0xc8, 0x9f, 0xfa, 0xde, 0x58, 0x99, 0x54, 0xc5, 0x6f, 0x56, 0x87, 0x6c, 0xe8, 0xc9, 0xca, 0xd9, + 0xd0, 0x33, 0x7e, 0x13, 0x2a, 0x1a, 0xa9, 0xb1, 0x37, 0xc8, 0x78, 0x23, 0x94, 0x10, 0x29, 0xb5, + 0xd1, 0x2a, 0x96, 0x25, 0xb4, 0x3b, 0x14, 0xfc, 0x66, 0xe8, 0xf8, 0x1c, 0x13, 0xd1, 0x2c, 0x9f, + 0x5f, 0x70, 0x3f, 0x50, 0x26, 0xee, 0x66, 0x54, 0x60, 0x12, 0xdc, 0xf8, 0x2b, 0xb0, 0x94, 0x78, + 0xb7, 0x92, 0x45, 0xbc, 0x05, 0x0b, 0xb8, 0x6e, 0xca, 0x05, 0x99, 0x4c, 0x33, 0x91, 0x65, 0x98, + 0x61, 0x4c, 0xd6, 0x79, 0x6b, 0xe2, 0x7b, 0x27, 0xd8, 0x49, 0xc6, 0xac, 0x48, 0xd8, 0x91, 0xef, + 0x9d, 0x18, 0x7f, 0x96, 0x83, 0xdc, 0xae, 0x37, 0xd1, 0xa3, 0x6e, 0x32, 0x73, 0x51, 0x37, 0x52, + 0xb3, 0xb2, 0x22, 0xcd, 0x49, 0x0a, 0xc3, 0x68, 0x97, 0x56, 0xda, 0xd3, 0x03, 0xa8, 0x0b, 0x3e, + 0x11, 0x7a, 0x42, 0x35, 0xbd, 0xb4, 0x7d, 0x12, 0x35, 0x73, 0xb4, 0xf9, 0xec, 0x71, 0xd8, 0xf7, + 0x76, 0x08, 0xce, 0x96, 0x21, 0x17, 0xe9, 0x05, 0x58, 0x2c, 0x1e, 0xd9, 0x2a, 0x2c, 0x60, 0xf8, + 0xe5, 0xb5, 0xf4, 0xb1, 0xc9, 0x27, 0xf6, 0x4d, 0x58, 0x4a, 0xb6, 0x4b, 0xac, 0x48, 0xca, 0x46, + 0x7a, 0xc3, 0xc8, 0x93, 0x6e, 0x83, 0xe0, 0x23, 0x84, 0x23, 0x5d, 0xf5, 0xa7, 0x9c, 0x63, 0x91, + 0xc6, 0xf4, 0x4a, 0x09, 0xa6, 0x77, 0x0f, 0x2a, 0xe1, 0xe8, 0xc2, 0x9a, 0xd8, 0xd7, 0x23, 0xcf, + 0x1e, 0xca, 0xfd, 0x0d, 0xe1, 0xe8, 0xe2, 0x88, 0x20, 0xec, 0x11, 0xc0, 0x78, 0x32, 0x91, 0x7b, + 0x0f, 0xcd, 0xbc, 0x31, 0x29, 0xef, 0x1f, 0x1d, 0x11, 0xc9, 0x99, 0xe5, 0xf1, 0x64, 0x42, 0x3f, + 0xd9, 0x36, 0xd4, 0x53, 0x93, 0xc5, 0xee, 0xaa, 0x68, 0x41, 0x6f, 0xb2, 0x91, 0xb2, 0x39, 0x6b, + 0x03, 0x1d, 0xb6, 0xfe, 0x7d, 0x60, 0xbf, 0x60, 0xca, 0x56, 0x1f, 0xca, 0xd1, 0xf8, 0xf4, 0x8c, + 0x27, 0x8c, 0xff, 0xad, 0x24, 0x32, 0x9e, 0xda, 0xc3, 0xa1, 0x2f, 0xf8, 0x22, 0x1d, 0x98, 0x11, + 0xcb, 0x07, 0xed, 0xc4, 0x6c, 0x13, 0xdf, 0x37, 0xfe, 0x22, 0x03, 0x05, 0x4a, 0xbf, 0x7a, 0x1b, + 0x1a, 0x84, 0x1f, 0x45, 0x30, 0x49, 0xcf, 0x1c, 0x9d, 0xbb, 0x7d, 0x19, 0xbc, 0x24, 0xb6, 0x85, + 0x96, 0x3a, 0x9a, 0x8d, 0xde, 0xbc, 0x96, 0x3e, 0x7a, 0x0f, 0xca, 0x51, 0xd7, 0x1a, 0xe9, 0x94, + 0x54, 0xcf, 0xec, 0x75, 0xc8, 0x9f, 0x7b, 0x13, 0x65, 0xe2, 0x80, 0x78, 0x25, 0x4d, 0x84, 0xc7, + 0x63, 0x11, 0x7d, 0xd0, 0xe0, 0xa5, 0x6a, 0x1e, 0x75, 0x82, 0x64, 0x30, 0x3f, 0xc7, 0x85, 0x94, + 0x39, 0x1e, 0x43, 0x43, 0xf0, 0x01, 0xcd, 0x43, 0x7e, 0xf3, 0xa1, 0xf9, 0x75, 0x21, 0xe1, 0x0d, + 0x46, 0xd3, 0x21, 0xd7, 0x0d, 0x4c, 0x18, 0x4e, 0x23, 0xe1, 0x4a, 0xb2, 0x36, 0xfe, 0x20, 0x43, + 0xfc, 0x45, 0xb4, 0xcb, 0x1e, 0x40, 0x5e, 0x9c, 0x6f, 0x33, 0x06, 0xd0, 0x28, 0x10, 0x5b, 0xe0, + 0x99, 0x88, 0x81, 0xf9, 0xd6, 0xd3, 0x71, 0xb2, 0xf5, 0x9a, 0x59, 0x71, 0xa7, 0xe3, 0xc8, 0x46, + 0xf3, 0x35, 0x35, 0xad, 0x19, 0xfb, 0x06, 0xcd, 0x3e, 0xda, 0xa6, 0x1b, 0x5a, 0x5c, 0x4e, 0x3e, + 0x71, 0x62, 0x2a, 0x29, 0x70, 0x78, 0xc6, 0xb5, 0x78, 0x9c, 0x3f, 0xca, 0x42, 0x2d, 0x31, 0x22, + 0x0c, 0x4c, 0x12, 0x07, 0x00, 0x59, 0xdf, 0xe5, 0xfb, 0x06, 0x01, 0x92, 0x82, 0xba, 0xb6, 0x4e, + 0xd9, 0xc4, 0x3a, 0x45, 0xb1, 0x00, 0x39, 0x3d, 0x16, 0xe0, 0x31, 0x94, 0xe3, 0x94, 0xe1, 0xe4, + 0x90, 0x44, 0x7f, 0x2a, 0x1c, 0x3d, 0x46, 0x8a, 0xa3, 0x07, 0x0a, 0x7a, 0xf4, 0xc0, 0xf7, 0x34, + 0x67, 0xf3, 0x02, 0x36, 0x63, 0xa4, 0xad, 0xe8, 0x2f, 0xc5, 0xd5, 0x6c, 0x7c, 0x04, 0x15, 0x6d, + 0xf0, 0xba, 0x53, 0x39, 0x93, 0x70, 0x2a, 0x47, 0x89, 0x23, 0xd9, 0x38, 0x71, 0xc4, 0xf8, 0xed, + 0x2c, 0xd4, 0xc4, 0xfe, 0x72, 0xdc, 0xb3, 0x23, 0x6f, 0xe4, 0x0c, 0xd0, 0x1a, 0x1f, 0xed, 0x30, + 0x29, 0x68, 0xa9, 0x7d, 0x26, 0xb7, 0x18, 0xc9, 0x59, 0x7a, 0x7e, 0x1c, 0x31, 0xe9, 0x28, 0x3f, + 0xce, 0x80, 0x9a, 0x60, 0x8c, 0x27, 0x76, 0xc0, 0xb5, 0x84, 0x66, 0xb3, 0x72, 0xca, 0xf9, 0xa6, + 0x1d, 0x10, 0x87, 0xfc, 0x26, 0x2c, 0x09, 0x1c, 0x4c, 0x0d, 0x1a, 0x3b, 0xa3, 0x91, 0x43, 0x98, + 0x64, 0xc1, 0x69, 0x9e, 0x72, 0x6e, 0xda, 0x21, 0xdf, 0x17, 0x05, 0x32, 0xff, 0xb9, 0x34, 0x74, + 0x02, 0xfb, 0x24, 0x0e, 0x1f, 0x8b, 0x9e, 0xd1, 0x87, 0x66, 0x5f, 0x69, 0x3e, 0x34, 0xca, 0x11, + 0xac, 0x8c, 0xed, 0xab, 0xc8, 0x87, 0x36, 0x43, 0x49, 0xc5, 0x59, 0x4a, 0x32, 0xfe, 0x43, 0x16, + 0x2a, 0x1a, 0x59, 0xbe, 0xca, 0xe9, 0x7a, 0x77, 0xce, 0x7b, 0x52, 0xd6, 0x1d, 0x25, 0x6f, 0x26, + 0xbb, 0x44, 0x57, 0x3b, 0x65, 0x5a, 0x6b, 0x04, 0x7c, 0x07, 0xca, 0x62, 0xd7, 0xbd, 0x87, 0xb6, + 0x46, 0x79, 0x4f, 0x00, 0x02, 0x8e, 0xa6, 0x27, 0xaa, 0xf0, 0x09, 0x16, 0x16, 0xe2, 0xc2, 0x27, + 0xa2, 0xf0, 0x45, 0x31, 0xa3, 0xdf, 0x81, 0xaa, 0x6c, 0x15, 0xdf, 0x29, 0x4e, 0x37, 0xde, 0xf5, + 0x89, 0xf7, 0x6d, 0x56, 0xa8, 0x3b, 0x7a, 0xf9, 0xb2, 0xe2, 0x13, 0x55, 0xb1, 0xf4, 0xb2, 0x8a, + 0x4f, 0xe8, 0xc1, 0xd8, 0x89, 0xc2, 0x70, 0x31, 0xcc, 0x43, 0xf1, 0xb1, 0x47, 0xb0, 0xa4, 0xd8, + 0xd5, 0xd4, 0xb5, 0x5d, 0xd7, 0x9b, 0xba, 0x03, 0xae, 0x32, 0x4a, 0x98, 0x2c, 0x3a, 0x8e, 0x4b, + 0x8c, 0x61, 0x94, 0x72, 0x48, 0xe1, 0x22, 0x0f, 0xa1, 0x40, 0x72, 0x39, 0x09, 0x1f, 0xe9, 0x8c, + 0x8b, 0x50, 0xd8, 0x03, 0x28, 0x90, 0x78, 0x9e, 0xbd, 0x91, 0xd9, 0x10, 0x82, 0xb1, 0x01, 0x0d, + 0x14, 0x31, 0x35, 0x8e, 0xfb, 0x22, 0xa9, 0xc4, 0x58, 0x06, 0x76, 0x40, 0x9b, 0x48, 0x0f, 0x63, + 0xfa, 0xaf, 0x39, 0xa8, 0x68, 0x60, 0xc1, 0x16, 0x31, 0xf0, 0xc5, 0x1a, 0x3a, 0xf6, 0x98, 0x2b, + 0x97, 0x4e, 0xcd, 0xac, 0x21, 0x74, 0x5b, 0x02, 0xc5, 0xa1, 0x60, 0x5f, 0x9c, 0x59, 0xde, 0x34, + 0xb4, 0x86, 0xfc, 0xcc, 0xe7, 0x5c, 0x0a, 0x4b, 0x55, 0xfb, 0xe2, 0xec, 0x70, 0x1a, 0x6e, 0x23, + 0x4c, 0x60, 0x09, 0xa2, 0xd6, 0xb0, 0x64, 0xac, 0xc6, 0xd8, 0xbe, 0x8a, 0xb1, 0x64, 0xc0, 0x10, + 0x2d, 0x51, 0x3e, 0x0a, 0x18, 0x22, 0xb5, 0x65, 0x96, 0x93, 0x17, 0xe6, 0x39, 0xf9, 0xb7, 0x61, + 0x95, 0x38, 0xb9, 0xe4, 0x11, 0xd6, 0x0c, 0x49, 0x2d, 0x63, 0xa9, 0x9c, 0xa4, 0x26, 0x7f, 0x35, + 0xc5, 0x0c, 0xd4, 0xfe, 0x08, 0x9c, 0x1f, 0xd3, 0x8e, 0xca, 0x98, 0x62, 0x66, 0xb2, 0xf1, 0x9e, + 0xf3, 0x63, 0x2e, 0x30, 0xd1, 0x21, 0xad, 0x63, 0xca, 0xd0, 0xe4, 0xb1, 0xe3, 0xce, 0x62, 0xda, + 0x57, 0x49, 0xcc, 0xb2, 0xc4, 0xb4, 0xaf, 0x74, 0xcc, 0xf7, 0x61, 0x6d, 0xcc, 0x87, 0x8e, 0x9d, + 0x6c, 0xd6, 0x8a, 0x25, 0x88, 0x65, 0x2a, 0xd6, 0xea, 0xf4, 0x48, 0x83, 0x14, 0xab, 0xf1, 0x63, + 0x6f, 0x7c, 0xe2, 0xd0, 0xe1, 0x49, 0x2e, 0xf2, 0xbc, 0x59, 0x77, 0xa7, 0xe3, 0x1f, 0x22, 0x58, + 0x54, 0x09, 0x8c, 0x1a, 0x54, 0x7a, 0xa1, 0x37, 0x51, 0xaf, 0xb9, 0x0e, 0x55, 0x7a, 0x94, 0xf9, + 0x42, 0x77, 0xe0, 0x36, 0xd2, 0x66, 0xdf, 0x9b, 0x78, 0x23, 0xef, 0xec, 0x3a, 0x61, 0x50, 0xfa, + 0x4f, 0x19, 0x58, 0x4a, 0x94, 0xca, 0x7d, 0xfe, 0x6d, 0xda, 0x58, 0x51, 0xd2, 0x07, 0x91, 0xf3, + 0xa2, 0x76, 0xf8, 0x10, 0x22, 0xed, 0x2a, 0x95, 0x08, 0xd2, 0x8e, 0x93, 0x95, 0x55, 0x45, 0xa2, + 0xed, 0xd6, 0x3c, 0x6d, 0xcb, 0xfa, 0x2a, 0x8d, 0x59, 0x35, 0xf1, 0xab, 0x32, 0x7c, 0x7c, 0x28, + 0xa7, 0x9c, 0x4b, 0x06, 0xc8, 0xea, 0xc6, 0x27, 0x35, 0x82, 0xd8, 0x22, 0x15, 0x18, 0xff, 0x2c, + 0x03, 0x10, 0x8f, 0x0e, 0x43, 0x74, 0xa3, 0x03, 0x94, 0xee, 0x01, 0xd2, 0x0e, 0xcb, 0x37, 0xa0, + 0x1a, 0x45, 0xea, 0xc5, 0x47, 0x72, 0x45, 0xc1, 0xc4, 0xb9, 0xfc, 0x0e, 0x34, 0xce, 0x46, 0xde, + 0x09, 0x8a, 0x4e, 0xf2, 0x00, 0xa5, 0xac, 0xa9, 0x3a, 0x81, 0xd5, 0xb1, 0x18, 0x1f, 0xe0, 0xf9, + 0xd4, 0x60, 0x3e, 0xfd, 0x38, 0x36, 0x7e, 0x27, 0x1b, 0x85, 0x2c, 0xc5, 0x2b, 0xf1, 0x62, 0x3d, + 0xe3, 0xe7, 0xf1, 0x7c, 0xbf, 0xc8, 0xa1, 0xf3, 0x11, 0xd4, 0x7d, 0xe2, 0x8e, 0x8a, 0x75, 0xe6, + 0x5f, 0xc0, 0x3a, 0x6b, 0x7e, 0xe2, 0xc8, 0xfd, 0x3a, 0x34, 0xed, 0xe1, 0x05, 0xf7, 0x43, 0x07, + 0xcd, 0xc6, 0x28, 0xa8, 0xc9, 0x20, 0x21, 0x0d, 0x8e, 0x12, 0xd1, 0x3b, 0xd0, 0x90, 0x39, 0x6c, + 0x11, 0xa6, 0xbc, 0x15, 0x23, 0x06, 0x0b, 0x44, 0xe3, 0x5f, 0xaa, 0x18, 0xa9, 0xe4, 0xdb, 0x7d, + 0xf1, 0xaa, 0xe8, 0x33, 0xcc, 0xce, 0xbb, 0xac, 0x24, 0x21, 0x49, 0x6b, 0xb4, 0xe4, 0x47, 0x04, + 0x94, 0xb6, 0xe8, 0xe4, 0xb2, 0xe6, 0x5f, 0x65, 0x59, 0x8d, 0xff, 0x9c, 0x81, 0xe2, 0xae, 0x37, + 0x11, 0x7a, 0xb9, 0x90, 0xe7, 0x70, 0x9b, 0x44, 0x6e, 0x88, 0x05, 0xf1, 0xd8, 0x1d, 0xbe, 0x38, + 0x55, 0x23, 0x55, 0xde, 0xa8, 0x25, 0xe5, 0x8d, 0xef, 0xc1, 0x1d, 0x74, 0xf2, 0xf8, 0xde, 0xc4, + 0xf3, 0xc5, 0x56, 0xb5, 0x47, 0x24, 0x77, 0x78, 0x6e, 0x78, 0xae, 0x78, 0xe7, 0xed, 0x53, 0xce, + 0x8f, 0x34, 0x8c, 0xfd, 0x08, 0x01, 0x93, 0xa1, 0x46, 0xe1, 0x85, 0x45, 0xaa, 0xa2, 0x14, 0x8c, + 0x88, 0xa3, 0x36, 0x44, 0x41, 0x07, 0xe1, 0x28, 0x1a, 0x19, 0xdf, 0x85, 0x72, 0x64, 0x75, 0x60, + 0xef, 0x42, 0xf9, 0xdc, 0x9b, 0x48, 0xd3, 0x44, 0x26, 0x91, 0xce, 0x22, 0x67, 0x6d, 0x96, 0xce, + 0xe9, 0x47, 0x60, 0xfc, 0x59, 0x11, 0x8a, 0x5d, 0xf7, 0xc2, 0x73, 0x06, 0x18, 0x65, 0x35, 0xe6, + 0x63, 0x4f, 0x25, 0xd2, 0x8a, 0xdf, 0x18, 0x49, 0x11, 0xdf, 0x6d, 0x91, 0x93, 0x91, 0x14, 0xd1, + 0xad, 0x16, 0x2b, 0xb0, 0xe0, 0xeb, 0x97, 0x53, 0x14, 0x7c, 0x8c, 0xfb, 0x8c, 0x94, 0xb6, 0x82, + 0x96, 0x88, 0x2c, 0xda, 0xa2, 0x4b, 0x13, 0x70, 0xc9, 0x28, 0xb1, 0xa9, 0x8c, 0x10, 0x5c, 0xb0, + 0xd7, 0xa0, 0x28, 0xb3, 0x47, 0x28, 0x16, 0x9f, 0x02, 0x35, 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0xe4, + 0xa4, 0x8b, 0x24, 0x2a, 0xa1, 0xa7, 0x4b, 0xe0, 0xb6, 0xa0, 0xb5, 0x7b, 0x50, 0x21, 0x7c, 0x42, + 0x29, 0xc9, 0xb8, 0x28, 0x04, 0x21, 0x42, 0xca, 0x1d, 0x2f, 0xe5, 0xd4, 0x3b, 0x5e, 0x30, 0x8c, + 0x2e, 0xe2, 0xb2, 0x34, 0x45, 0xa0, 0x9b, 0x3d, 0x34, 0xb8, 0xba, 0xe0, 0x48, 0x2a, 0xf7, 0x94, + 0xe7, 0xa7, 0x94, 0xfb, 0x37, 0xa1, 0x76, 0x6a, 0x8f, 0x46, 0x27, 0xf6, 0xe0, 0x39, 0xe9, 0xa4, + 0x55, 0x32, 0xc3, 0x29, 0x20, 0x2a, 0xa5, 0xf7, 0xa0, 0xa2, 0xbd, 0x65, 0x0c, 0x7a, 0xca, 0x9b, + 0x10, 0xbf, 0xdf, 0x59, 0x53, 0x53, 0xfd, 0x15, 0x4c, 0x4d, 0x5a, 0xf0, 0x57, 0x23, 0x19, 0xfc, + 0x75, 0x07, 0xb9, 0xa9, 0x0c, 0x10, 0x6a, 0xd2, 0x35, 0x12, 0xf6, 0x70, 0x88, 0x01, 0x42, 0x74, + 0x67, 0x1b, 0x2e, 0x1e, 0x95, 0x2f, 0x92, 0x50, 0x4b, 0x30, 0x42, 0xb9, 0x4b, 0xf6, 0xd2, 0x89, + 0xed, 0x0c, 0x31, 0xd8, 0x96, 0xd4, 0xd8, 0xa2, 0x3d, 0x0e, 0x8f, 0x6c, 0x67, 0xc8, 0xee, 0x43, + 0x55, 0x15, 0xe3, 0xe9, 0xb8, 0x44, 0xeb, 0x2f, 0x8b, 0xc5, 0x99, 0x68, 0x40, 0x2d, 0xc2, 0x18, + 0xc7, 0xc9, 0x7a, 0x15, 0x89, 0x82, 0x74, 0xf0, 0x1e, 0xc6, 0x54, 0x84, 0x1c, 0x53, 0xf2, 0xea, + 0x4f, 0xee, 0xc8, 0xb9, 0x4a, 0x2a, 0x55, 0xff, 0xc9, 0x4b, 0x43, 0x98, 0x42, 0x10, 0x23, 0x67, + 0xd1, 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0x2c, 0x22, 0x04, 0xf6, 0x5d, 0x4d, 0x91, 0x6a, 0x21, + 0xf2, 0x6b, 0x33, 0xed, 0xdf, 0x94, 0x6b, 0x70, 0x17, 0xc0, 0x09, 0xc4, 0x29, 0x13, 0x70, 0x77, + 0x88, 0xd9, 0x75, 0x25, 0xb3, 0xec, 0x04, 0xcf, 0x08, 0xf0, 0xd5, 0x6a, 0x58, 0x6d, 0xa8, 0xea, + 0xd3, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0x75, 0x0e, 0x9a, 0xb7, 0x58, 0x05, 0x8a, 0xbd, 0x4e, 0xbf, + 0xbf, 0x87, 0x2e, 0xa7, 0x2a, 0x94, 0xa2, 0xd4, 0x9e, 0xac, 0x78, 0x6a, 0x6f, 0x6d, 0x75, 0x8e, + 0xfa, 0x9d, 0xed, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, 0x99, 0x33, 0xfe, 0x3c, 0x07, 0x15, 0x6d, + 0x15, 0x5e, 0xcc, 0x8c, 0xef, 0x02, 0xa0, 0x4a, 0x13, 0xc7, 0x8f, 0xe5, 0xcd, 0xb2, 0x80, 0xd0, + 0xcb, 0xd7, 0x8d, 0xe5, 0x39, 0xba, 0x9f, 0x44, 0x19, 0xcb, 0xdf, 0x84, 0x1a, 0x5d, 0xf5, 0xa1, + 0x3b, 0x0e, 0x0b, 0x66, 0x95, 0x80, 0x92, 0x55, 0x63, 0x6e, 0x20, 0x22, 0x61, 0xd6, 0x88, 0x4c, + 0xfc, 0x27, 0x10, 0xe6, 0x8d, 0x60, 0xd2, 0x4f, 0xe0, 0x8d, 0x2e, 0x38, 0x61, 0x90, 0x44, 0x58, + 0x91, 0xb0, 0xbe, 0xcc, 0x72, 0x94, 0xfc, 0x50, 0x4b, 0x4e, 0x2b, 0x98, 0x55, 0x02, 0xca, 0x8e, + 0xbe, 0xa9, 0x08, 0xa8, 0x84, 0x04, 0xb4, 0x36, 0x4f, 0x0d, 0x09, 0xe2, 0xd9, 0x9b, 0xb3, 0x67, + 0x95, 0x91, 0x30, 0xbe, 0x36, 0x5f, 0xef, 0xe5, 0x76, 0x2d, 0xf6, 0x2e, 0xb0, 0xf1, 0x64, 0x62, + 0xa5, 0x58, 0x9a, 0xf2, 0x66, 0x63, 0x3c, 0x99, 0xf4, 0x35, 0x43, 0xcc, 0x57, 0x60, 0x04, 0xfb, + 0x1c, 0x58, 0x5b, 0x6c, 0x60, 0x1c, 0x62, 0x64, 0x42, 0x8d, 0xd9, 0x72, 0x46, 0x67, 0xcb, 0x29, + 0xdc, 0x2f, 0x9b, 0xca, 0xfd, 0x5e, 0xc4, 0x27, 0x8c, 0x1d, 0xa8, 0x1c, 0x69, 0x17, 0x09, 0xdd, + 0x17, 0x27, 0x84, 0xba, 0x42, 0x88, 0xce, 0x0e, 0x32, 0x6e, 0xf9, 0xf2, 0xe6, 0x20, 0x6d, 0x34, + 0x59, 0x6d, 0x34, 0xc6, 0x3f, 0xcd, 0xd0, 0x25, 0x0d, 0xd1, 0xe0, 0xe3, 0xbb, 0x8b, 0x94, 0x1f, + 0x28, 0xce, 0x21, 0xad, 0x28, 0xff, 0x8f, 0x4c, 0xff, 0xc4, 0xa1, 0x59, 0xde, 0xe9, 0x69, 0xc0, + 0x55, 0x36, 0x54, 0x05, 0x61, 0x87, 0x08, 0x52, 0xc2, 0xb7, 0x90, 0xf0, 0x1d, 0x6a, 0x3f, 0x90, + 0x59, 0x51, 0x42, 0xf8, 0xde, 0xb7, 0xaf, 0x64, 0xaf, 0x81, 0x10, 0x41, 0xa4, 0xa1, 0x5a, 0xe5, + 0x80, 0x45, 0xcf, 0xc6, 0x3f, 0x92, 0x69, 0xae, 0xb3, 0xeb, 0xfb, 0x10, 0x4a, 0x51, 0xab, 0xc9, + 0x13, 0x56, 0x61, 0x46, 0xe5, 0xe2, 0x1c, 0x47, 0xad, 0x3c, 0x31, 0x62, 0xda, 0x5c, 0xe8, 0x6c, + 0xe8, 0x6a, 0xa3, 0xfe, 0x06, 0xb0, 0x53, 0xc7, 0x9f, 0x45, 0xa6, 0xcd, 0xd6, 0xc4, 0x12, 0x0d, + 0xdb, 0x38, 0x86, 0x25, 0xc5, 0x25, 0x34, 0x8d, 0x20, 0xf9, 0xf2, 0x32, 0x2f, 0x61, 0xf2, 0xd9, + 0x39, 0x26, 0x6f, 0xfc, 0x34, 0x0f, 0x45, 0x75, 0x29, 0x57, 0xda, 0x45, 0x52, 0xe5, 0xe4, 0x45, + 0x52, 0xad, 0xc4, 0xa5, 0x23, 0xf8, 0xea, 0xe5, 0x79, 0xff, 0xce, 0xec, 0x91, 0xad, 0x19, 0xcd, + 0x13, 0xc7, 0xf6, 0x2a, 0xe4, 0x27, 0x76, 0x78, 0x8e, 0x06, 0x32, 0x22, 0x1e, 0x7c, 0x56, 0xc6, + 0xf4, 0x42, 0xd2, 0x98, 0x9e, 0x76, 0xe9, 0x16, 0x89, 0xa4, 0x73, 0x97, 0x6e, 0xdd, 0x01, 0x92, + 0x2f, 0xb4, 0x30, 0xa3, 0x12, 0x02, 0xc4, 0x59, 0x94, 0x14, 0x47, 0x4a, 0xb3, 0xe2, 0xc8, 0x2b, + 0x8b, 0x0a, 0xdf, 0x86, 0x05, 0x4a, 0x58, 0x97, 0xb9, 0x6e, 0xea, 0x40, 0x91, 0x6b, 0xa8, 0xfe, + 0x53, 0xf0, 0xb1, 0x29, 0x71, 0xf5, 0x1b, 0x6c, 0x2a, 0x89, 0x1b, 0x6c, 0x74, 0x23, 0x7f, 0x35, + 0x69, 0xe4, 0x7f, 0x00, 0xcd, 0x68, 0x41, 0xd1, 0x64, 0xe6, 0x06, 0x32, 0x93, 0xa6, 0xae, 0xe0, + 0x82, 0x4b, 0x1e, 0x04, 0xf1, 0x81, 0x58, 0x4f, 0x1c, 0x88, 0x82, 0x87, 0xb5, 0xc3, 0x90, 0x8f, + 0x27, 0xa1, 0x3c, 0x10, 0x31, 0xd6, 0x5e, 0x1f, 0x60, 0x32, 0x0b, 0xb4, 0x06, 0xe5, 0xee, 0x81, + 0xb5, 0xb3, 0xd7, 0x7d, 0xba, 0xdb, 0x6f, 0x66, 0xc4, 0x63, 0xef, 0x78, 0x6b, 0xab, 0xd3, 0xd9, + 0xc6, 0x13, 0x07, 0x60, 0x61, 0xa7, 0xdd, 0x15, 0xa7, 0x4f, 0xce, 0xf8, 0xbd, 0x2c, 0x54, 0xb4, + 0xe6, 0xd9, 0xfb, 0xd1, 0xaa, 0xd0, 0x25, 0x27, 0x77, 0xe7, 0x87, 0xb0, 0xa1, 0x58, 0xb1, 0xb6, + 0x2c, 0xd1, 0x15, 0x63, 0xd9, 0x1b, 0xaf, 0x18, 0x63, 0x6f, 0x43, 0xc3, 0xa6, 0x16, 0xa2, 0x55, + 0x90, 0xe6, 0x60, 0x09, 0x96, 0x8b, 0x80, 0xc1, 0x75, 0xf1, 0x79, 0x22, 0xf0, 0xf2, 0x2a, 0x9e, + 0x2d, 0x3a, 0x52, 0x70, 0xb1, 0x8a, 0xa7, 0xb6, 0x33, 0x9a, 0xfa, 0x5c, 0xba, 0x6f, 0xa3, 0x93, + 0x99, 0xa0, 0xa6, 0x2a, 0x36, 0x3e, 0x00, 0x88, 0xc7, 0x9c, 0x5c, 0x9c, 0x5b, 0xc9, 0xc5, 0xc9, + 0x68, 0x8b, 0x93, 0x35, 0xb6, 0x89, 0x8d, 0xc8, 0x85, 0x8e, 0x3c, 0xd5, 0xdf, 0x04, 0x65, 0x91, + 0xb2, 0x30, 0xbc, 0x75, 0x32, 0xe2, 0xa1, 0xca, 0x97, 0x5d, 0x94, 0x25, 0xdd, 0xa8, 0x40, 0xa5, + 0xaf, 0xc7, 0xad, 0xc4, 0xdc, 0x48, 0x92, 0xe4, 0x2c, 0x37, 0x92, 0xa8, 0x66, 0x54, 0x6e, 0xac, + 0x43, 0x6b, 0x9b, 0x8b, 0xd6, 0xda, 0xa3, 0xd1, 0xcc, 0x70, 0x8c, 0x3b, 0x70, 0x3b, 0xa5, 0x4c, + 0x1a, 0x21, 0x3e, 0x86, 0x95, 0x36, 0xa5, 0xc6, 0x7e, 0x55, 0x39, 0x30, 0x46, 0x0b, 0x56, 0x67, + 0x9b, 0x94, 0x9d, 0xed, 0xc0, 0xe2, 0x36, 0x3f, 0x99, 0x9e, 0xed, 0xf1, 0x8b, 0xb8, 0x23, 0x06, + 0xf9, 0xe0, 0xdc, 0xbb, 0x94, 0xeb, 0x83, 0xbf, 0x31, 0x90, 0x4c, 0xe0, 0x58, 0xc1, 0x84, 0x0f, + 0x94, 0x45, 0x14, 0x21, 0xbd, 0x09, 0x1f, 0x18, 0xef, 0x03, 0xd3, 0xdb, 0x91, 0xeb, 0x25, 0xb4, + 0x84, 0xe9, 0x89, 0x15, 0x5c, 0x07, 0x21, 0x1f, 0xab, 0x3b, 0x74, 0x20, 0x98, 0x9e, 0xf4, 0x08, + 0x62, 0xbc, 0x03, 0xd5, 0x23, 0xfb, 0xda, 0xe4, 0x9f, 0xcb, 0xec, 0x8e, 0x35, 0x28, 0x4e, 0xec, + 0x6b, 0xc1, 0x06, 0x22, 0xe7, 0x08, 0x16, 0x1b, 0x7f, 0x98, 0x87, 0x05, 0xc2, 0x64, 0xf7, 0xe9, + 0x9a, 0x4b, 0xc7, 0xc5, 0x6d, 0xa8, 0x18, 0xa5, 0x06, 0x9a, 0xe3, 0xa5, 0xd9, 0x79, 0x5e, 0x2a, + 0x0d, 0x68, 0xea, 0x7a, 0x0f, 0x65, 0xc6, 0x76, 0xa7, 0x63, 0x75, 0xa7, 0x47, 0x32, 0x3f, 0x34, + 0x1f, 0x5f, 0x63, 0x4a, 0xc9, 0x73, 0x49, 0x47, 0x63, 0xac, 0x8b, 0xd0, 0xe8, 0xd4, 0x11, 0x21, + 0xd9, 0xa5, 0x0e, 0x4a, 0x55, 0x78, 0x8a, 0x2a, 0x6f, 0x28, 0xa9, 0xf0, 0xcc, 0x29, 0x36, 0xa5, + 0x97, 0x2b, 0x36, 0x64, 0x59, 0x7b, 0x81, 0x62, 0x03, 0xaf, 0xa0, 0xd8, 0xbc, 0x82, 0x93, 0xef, + 0x36, 0x94, 0xf0, 0xdc, 0xd7, 0xb8, 0xa7, 0x38, 0xef, 0x05, 0xf7, 0xfc, 0x8e, 0x26, 0xfa, 0x53, + 0x84, 0xc1, 0x9d, 0x78, 0x9b, 0x98, 0xfc, 0xf3, 0x5f, 0x8e, 0xf3, 0xe4, 0x33, 0x28, 0x4a, 0xa8, + 0x20, 0x68, 0xd7, 0x1e, 0xab, 0x1b, 0x92, 0xf0, 0xb7, 0x58, 0x36, 0xbc, 0xd6, 0xe5, 0xf3, 0xa9, + 0xe3, 0xf3, 0xa1, 0xba, 0xfa, 0xc2, 0xc1, 0x3d, 0x2a, 0x20, 0x62, 0x82, 0x42, 0x0d, 0x71, 0xbd, + 0x4b, 0x57, 0x26, 0xbe, 0x17, 0x9d, 0xe0, 0x99, 0x78, 0x34, 0x18, 0x34, 0xf1, 0x8e, 0xb4, 0x89, + 0xe7, 0xab, 0xc3, 0xc9, 0xf8, 0x69, 0x06, 0x9a, 0x72, 0x77, 0x45, 0x65, 0xba, 0x16, 0x50, 0xb8, + 0xc9, 0x21, 0xfe, 0xe2, 0x8b, 0x2c, 0x0c, 0xa8, 0xa1, 0xf1, 0x23, 0x3a, 0xa9, 0xc8, 0x78, 0x53, + 0x11, 0xc0, 0x1d, 0x79, 0x5a, 0xbd, 0x0e, 0x15, 0x15, 0xe5, 0x3a, 0x76, 0x46, 0xea, 0xc6, 0x62, + 0x0a, 0x73, 0xdd, 0x77, 0x46, 0xea, 0xa0, 0xf3, 0x6d, 0x99, 0xc7, 0x96, 0xc1, 0x83, 0xce, 0xb4, + 0x43, 0x6e, 0xfc, 0xdb, 0x0c, 0x2c, 0x6a, 0x53, 0x91, 0xfb, 0xf6, 0x43, 0xa8, 0x46, 0x97, 0x13, + 0xf2, 0x48, 0xf2, 0x5a, 0x4b, 0x32, 0x9a, 0xb8, 0x5a, 0x65, 0x10, 0x41, 0x02, 0x31, 0x98, 0xa1, + 0x7d, 0x8d, 0xe3, 0x0d, 0xa6, 0x63, 0xa5, 0xdc, 0x0c, 0xed, 0xeb, 0x1d, 0xce, 0x7b, 0xd3, 0xb1, + 0x50, 0x5d, 0x2f, 0x39, 0x7f, 0x1e, 0x21, 0x90, 0xcc, 0x05, 0x02, 0x26, 0x31, 0x0c, 0xa8, 0x8d, + 0x3d, 0x37, 0x3c, 0x8f, 0x50, 0xa4, 0xd4, 0x89, 0x40, 0xc2, 0x31, 0xfe, 0x34, 0x0b, 0x4b, 0x64, + 0x62, 0x93, 0xa6, 0x4d, 0xc9, 0xba, 0x5a, 0xb0, 0x40, 0xd6, 0x46, 0x62, 0x5e, 0xbb, 0xb7, 0x4c, + 0xf9, 0xcc, 0xbe, 0xfd, 0x8a, 0x66, 0x41, 0x95, 0x2a, 0x77, 0xc3, 0xf2, 0xe7, 0xe6, 0x97, 0xff, + 0xe6, 0xe5, 0x4d, 0xf3, 0xb8, 0x15, 0xd2, 0x3c, 0x6e, 0xaf, 0xe2, 0xe7, 0x9a, 0xcb, 0x27, 0x2b, + 0x4a, 0x1c, 0x2d, 0x9f, 0xec, 0x7d, 0x58, 0x4b, 0xe0, 0x20, 0xb7, 0x76, 0x4e, 0x1d, 0xae, 0xee, + 0x15, 0x58, 0xd6, 0xb0, 0x7b, 0xaa, 0x6c, 0xb3, 0x08, 0x85, 0x60, 0xe0, 0x4d, 0xb8, 0xb1, 0x0a, + 0xcb, 0xc9, 0x55, 0x95, 0xc7, 0xc4, 0xef, 0x67, 0xa0, 0x25, 0xe3, 0x23, 0x1c, 0xf7, 0x6c, 0xd7, + 0x09, 0x42, 0xcf, 0x8f, 0x2e, 0xf1, 0xbb, 0x0b, 0x10, 0x84, 0xb6, 0x2f, 0xb5, 0x4d, 0x99, 0x49, + 0x8f, 0x10, 0xd4, 0x24, 0x6f, 0x43, 0x89, 0xbb, 0x43, 0x2a, 0x24, 0x6a, 0x28, 0x72, 0x77, 0xa8, + 0xf4, 0xd0, 0x39, 0xf9, 0xbb, 0x96, 0x54, 0x2f, 0x64, 0x62, 0xab, 0x58, 0x1d, 0x7e, 0x81, 0x07, + 0x6f, 0x3e, 0x4a, 0x6c, 0xdd, 0xb7, 0xaf, 0x30, 0xda, 0x30, 0x30, 0xfe, 0x7e, 0x16, 0x1a, 0xf1, + 0xf8, 0x28, 0x2b, 0xfe, 0xc5, 0xf9, 0xfd, 0xf7, 0x25, 0x39, 0x38, 0x42, 0x7e, 0xd7, 0x0c, 0x8f, + 0x25, 0xda, 0x9c, 0x5d, 0x97, 0x19, 0x50, 0x51, 0x18, 0xde, 0x34, 0xd4, 0xee, 0xd2, 0x2a, 0x13, + 0xca, 0xe1, 0x34, 0x14, 0x0a, 0x97, 0xd0, 0x3c, 0x1d, 0x57, 0xaa, 0x3c, 0x05, 0x7b, 0x1c, 0x76, + 0xf1, 0x8a, 0x6e, 0x01, 0x16, 0xd5, 0xe8, 0x45, 0x0a, 0x2c, 0x81, 0xdf, 0x24, 0x39, 0x9b, 0xde, + 0x1c, 0xca, 0xd8, 0xba, 0x10, 0x4a, 0xb7, 0x95, 0x46, 0x42, 0xe8, 0xeb, 0x50, 0xa1, 0xc6, 0xe3, + 0xf4, 0xc1, 0xbc, 0x59, 0xc6, 0x1e, 0xb0, 0x5c, 0x1a, 0x81, 0xbc, 0x69, 0x42, 0xf5, 0x05, 0xea, + 0x0a, 0xc3, 0x0f, 0xfe, 0x76, 0x06, 0x6e, 0xa7, 0xbc, 0x36, 0xb9, 0xcb, 0xb7, 0x60, 0xf1, 0x34, + 0x2a, 0x54, 0xab, 0x4b, 0x5b, 0x7d, 0x55, 0xb1, 0xd5, 0xe4, 0x9a, 0x9a, 0xcd, 0xd3, 0x24, 0x20, + 0x56, 0xba, 0xe8, 0x0d, 0x26, 0x32, 0x44, 0x51, 0xe9, 0xa2, 0xd7, 0x48, 0xfa, 0xce, 0x11, 0xac, + 0x77, 0xae, 0x04, 0xc7, 0xd8, 0xd2, 0xef, 0x98, 0x57, 0x64, 0x94, 0x34, 0x30, 0x67, 0x5e, 0xc9, + 0xc0, 0x3c, 0xa4, 0x44, 0xb8, 0xa8, 0xad, 0x9f, 0xa7, 0x11, 0x3c, 0x40, 0x45, 0x1d, 0xba, 0x23, + 0x5f, 0x65, 0xa9, 0x0e, 0xa2, 0xbb, 0xf1, 0x8d, 0x00, 0x1a, 0xfb, 0xd3, 0x51, 0xe8, 0xc4, 0xd7, + 0xe5, 0xb3, 0x6f, 0xcb, 0x3a, 0xd8, 0x8f, 0x5a, 0xb5, 0xd4, 0x8e, 0x20, 0xea, 0x08, 0x17, 0x6b, + 0x2c, 0x1a, 0xb2, 0xe6, 0xfb, 0x6b, 0x8c, 0x93, 0x3d, 0x18, 0xb7, 0x61, 0x2d, 0x7e, 0xa2, 0x65, + 0x53, 0x47, 0xcd, 0x3f, 0xc9, 0x50, 0x68, 0x73, 0xf2, 0xea, 0x7e, 0xd6, 0x81, 0xa5, 0xc0, 0x71, + 0xcf, 0x46, 0x5c, 0x6f, 0x3e, 0x90, 0x8b, 0xb0, 0x92, 0x1c, 0x9b, 0xbc, 0xde, 0xdf, 0x5c, 0xa4, + 0x1a, 0x71, 0x6b, 0x01, 0xdb, 0xbc, 0x69, 0x90, 0x31, 0x59, 0xcc, 0xac, 0xc6, 0xfc, 0xe0, 0xbb, + 0x50, 0x4f, 0x76, 0xc4, 0xbe, 0x23, 0x93, 0x40, 0xe3, 0x51, 0xe5, 0x66, 0xd2, 0xf5, 0x62, 0x82, + 0xa8, 0xc4, 0x6b, 0x1f, 0x18, 0x7f, 0x37, 0x03, 0x2d, 0x93, 0x0b, 0xca, 0xd5, 0x46, 0xa9, 0x68, + 0xe6, 0xc3, 0xb9, 0x56, 0x6f, 0x9e, 0xab, 0xca, 0x2d, 0x55, 0x23, 0xfa, 0xc6, 0x8d, 0x2f, 0x63, + 0xf7, 0xd6, 0xdc, 0x8c, 0x36, 0x4b, 0xb0, 0x40, 0x28, 0xc6, 0x1a, 0xac, 0xc8, 0xf1, 0xa8, 0xb1, + 0xc4, 0xde, 0xc3, 0x44, 0x8f, 0x09, 0xef, 0xe1, 0x3a, 0xb4, 0xe8, 0x2e, 0x46, 0x7d, 0x12, 0xb2, + 0xe2, 0x36, 0xb0, 0x7d, 0x7b, 0x60, 0xfb, 0x9e, 0xe7, 0x1e, 0x71, 0x5f, 0x06, 0x8a, 0xa2, 0x84, + 0x89, 0xce, 0x35, 0x25, 0x0a, 0xd3, 0x93, 0xba, 0x41, 0xd0, 0x73, 0x55, 0x5c, 0x0c, 0x3d, 0x19, + 0x26, 0x2c, 0x6d, 0xda, 0xcf, 0xb9, 0x6a, 0x49, 0x2d, 0xd1, 0x47, 0x50, 0x99, 0x44, 0x8d, 0xaa, + 0x75, 0x57, 0x99, 0xe2, 0xf3, 0xdd, 0x9a, 0x3a, 0xb6, 0xf1, 0x04, 0x96, 0x93, 0x6d, 0x4a, 0xd6, + 0xb1, 0x0e, 0xa5, 0xb1, 0x84, 0xc9, 0xd1, 0x45, 0xcf, 0xc6, 0xef, 0x96, 0xa0, 0x28, 0xf5, 0x39, + 0xb6, 0x01, 0xf9, 0x81, 0x8a, 0x4d, 0x8a, 0x2f, 0x20, 0x91, 0xa5, 0xea, 0xff, 0x16, 0x46, 0x28, + 0x09, 0x3c, 0xf6, 0x11, 0xd4, 0x93, 0x5e, 0xd1, 0x99, 0x34, 0xd4, 0xa4, 0x3b, 0xb3, 0x36, 0x98, + 0xf1, 0x7f, 0x95, 0xe3, 0xc3, 0x91, 0x64, 0x86, 0xd2, 0xb9, 0x76, 0x7a, 0x7a, 0xae, 0x90, 0xb7, + 0x83, 0x73, 0xdb, 0x7a, 0xf2, 0xfe, 0x07, 0x32, 0x0f, 0xb5, 0x82, 0xc0, 0xde, 0xb9, 0xfd, 0xe4, + 0xfd, 0x0f, 0x66, 0x25, 0x69, 0x99, 0x85, 0xaa, 0x49, 0xd2, 0xcb, 0x50, 0xa0, 0xab, 0xf2, 0x28, + 0xc8, 0x84, 0x1e, 0xd8, 0x63, 0x58, 0x96, 0x6a, 0xab, 0x25, 0xc3, 0x81, 0x89, 0x0b, 0x96, 0x28, + 0xb5, 0x49, 0x96, 0xf5, 0xb0, 0x88, 0x6c, 0x43, 0xab, 0xb0, 0x70, 0x1e, 0xdf, 0x7b, 0x58, 0x33, + 0xe5, 0x93, 0xf1, 0xa7, 0x05, 0xa8, 0x68, 0x8b, 0xc2, 0xaa, 0x50, 0x32, 0x3b, 0xbd, 0x8e, 0xf9, + 0x49, 0x67, 0xbb, 0x79, 0x8b, 0x3d, 0x80, 0xb7, 0xba, 0x07, 0x5b, 0x87, 0xa6, 0xd9, 0xd9, 0xea, + 0x5b, 0x87, 0xa6, 0xa5, 0xae, 0xc1, 0x39, 0x6a, 0x7f, 0xb6, 0xdf, 0x39, 0xe8, 0x5b, 0xdb, 0x9d, + 0x7e, 0xbb, 0xbb, 0xd7, 0x6b, 0x66, 0xd8, 0x6b, 0xd0, 0x8a, 0x31, 0x55, 0x71, 0x7b, 0xff, 0xf0, + 0xf8, 0xa0, 0xdf, 0xcc, 0xb2, 0x7b, 0x70, 0x67, 0xa7, 0x7b, 0xd0, 0xde, 0xb3, 0x62, 0x9c, 0xad, + 0xbd, 0xfe, 0x27, 0x56, 0xe7, 0xd7, 0x8f, 0xba, 0xe6, 0x67, 0xcd, 0x5c, 0x1a, 0x82, 0x50, 0xc6, + 0x55, 0x0b, 0x79, 0x76, 0x1b, 0x56, 0x08, 0x81, 0xaa, 0x58, 0xfd, 0xc3, 0x43, 0xab, 0x77, 0x78, + 0x78, 0xd0, 0x2c, 0xb0, 0x45, 0xa8, 0x75, 0x0f, 0x3e, 0x69, 0xef, 0x75, 0xb7, 0x2d, 0xb3, 0xd3, + 0xde, 0xdb, 0x6f, 0x2e, 0xb0, 0x25, 0x68, 0xcc, 0xe2, 0x15, 0x45, 0x13, 0x0a, 0xef, 0xf0, 0xa0, + 0x7b, 0x78, 0x60, 0x7d, 0xd2, 0x31, 0x7b, 0xdd, 0xc3, 0x83, 0x66, 0x89, 0xad, 0x02, 0x4b, 0x16, + 0xed, 0xee, 0xb7, 0xb7, 0x9a, 0x65, 0xb6, 0x02, 0x8b, 0x49, 0xf8, 0xb3, 0xce, 0x67, 0x4d, 0x60, + 0x2d, 0x58, 0xa6, 0x81, 0x59, 0x9b, 0x9d, 0xbd, 0xc3, 0x4f, 0xad, 0xfd, 0xee, 0x41, 0x77, 0xff, + 0x78, 0xbf, 0x59, 0xc1, 0x8b, 0xb9, 0x3a, 0x1d, 0xab, 0x7b, 0xd0, 0x3b, 0xde, 0xd9, 0xe9, 0x6e, + 0x75, 0x3b, 0x07, 0xfd, 0x66, 0x95, 0x7a, 0x4e, 0x9b, 0x78, 0x4d, 0x54, 0x90, 0x39, 0x03, 0xd6, + 0x76, 0xb7, 0xd7, 0xde, 0xdc, 0xeb, 0x6c, 0x37, 0xeb, 0xec, 0x2e, 0xdc, 0xee, 0x77, 0xf6, 0x8f, + 0x0e, 0xcd, 0xb6, 0xf9, 0x99, 0xca, 0x29, 0xb0, 0x76, 0xda, 0xdd, 0xbd, 0x63, 0xb3, 0xd3, 0x6c, + 0xb0, 0x37, 0xe0, 0xae, 0xd9, 0xf9, 0xf8, 0xb8, 0x6b, 0x76, 0xb6, 0xad, 0x83, 0xc3, 0xed, 0x8e, + 0xb5, 0xd3, 0x69, 0xf7, 0x8f, 0xcd, 0x8e, 0xb5, 0xdf, 0xed, 0xf5, 0xba, 0x07, 0x4f, 0x9b, 0x4d, + 0xf6, 0x16, 0xdc, 0x8f, 0x50, 0xa2, 0x06, 0x66, 0xb0, 0x16, 0xc5, 0xfc, 0xd4, 0x2b, 0x3d, 0xe8, + 0xfc, 0x7a, 0xdf, 0x3a, 0xea, 0x74, 0xcc, 0x26, 0x63, 0xeb, 0xb0, 0x1a, 0x77, 0x4f, 0x1d, 0xc8, + 0xbe, 0x97, 0x44, 0xd9, 0x51, 0xc7, 0xdc, 0x6f, 0x1f, 0x88, 0x17, 0x9c, 0x28, 0x5b, 0x16, 0xc3, + 0x8e, 0xcb, 0x66, 0x87, 0xbd, 0xc2, 0x18, 0xd4, 0xb5, 0xb7, 0xb2, 0xd3, 0x36, 0x9b, 0xab, 0xac, + 0x01, 0x95, 0xfd, 0xa3, 0x23, 0xab, 0xdf, 0xdd, 0xef, 0x1c, 0x1e, 0xf7, 0x9b, 0x6b, 0x6c, 0x05, + 0x9a, 0xdd, 0x83, 0x7e, 0xc7, 0x14, 0xef, 0x5a, 0x55, 0xfd, 0x5f, 0x45, 0xb6, 0x0c, 0x0d, 0x35, + 0x52, 0x05, 0xfd, 0x59, 0x91, 0xad, 0x01, 0x3b, 0x3e, 0x30, 0x3b, 0xed, 0x6d, 0xb1, 0x70, 0x51, + 0xc1, 0xff, 0x2e, 0x4a, 0x0f, 0xc9, 0x4f, 0x73, 0xd1, 0x61, 0x1d, 0x87, 0x1c, 0x24, 0x6f, 0xc1, + 0xad, 0x6a, 0xb7, 0xd7, 0xbe, 0xec, 0x7e, 0x7a, 0x4d, 0xb5, 0xca, 0xcd, 0xa9, 0x56, 0x73, 0xba, + 0x7b, 0x4d, 0x97, 0xfd, 0xde, 0x84, 0xda, 0x98, 0x6e, 0xc4, 0x95, 0x37, 0x5f, 0x82, 0x8c, 0xbf, + 0x21, 0x20, 0x5d, 0x7b, 0x39, 0x77, 0x41, 0x7b, 0x61, 0xfe, 0x82, 0xf6, 0x34, 0xf9, 0x7e, 0x21, + 0x4d, 0xbe, 0x7f, 0x08, 0x8b, 0xc4, 0x9a, 0x1c, 0xd7, 0x19, 0x2b, 0xad, 0x99, 0xa4, 0xc0, 0x06, + 0xb2, 0x28, 0x82, 0x2b, 0x75, 0x42, 0xa9, 0x1c, 0x92, 0x85, 0x14, 0xa5, 0xb6, 0x91, 0xd0, 0x34, + 0x88, 0x73, 0x44, 0x9a, 0x46, 0xd4, 0x83, 0x7d, 0x15, 0xf7, 0x50, 0xd1, 0x7a, 0x20, 0x38, 0xf6, + 0xf0, 0x10, 0x16, 0xf9, 0x55, 0xe8, 0xdb, 0x96, 0x37, 0xb1, 0x3f, 0x9f, 0xa2, 0x0b, 0xd7, 0x46, + 0x1d, 0xbe, 0x6a, 0x36, 0xb0, 0xe0, 0x10, 0xe1, 0xdb, 0x76, 0x68, 0x3f, 0xfc, 0x02, 0x2a, 0xda, + 0x6d, 0xc9, 0x6c, 0x0d, 0x96, 0x3e, 0xed, 0xf6, 0x0f, 0x3a, 0xbd, 0x9e, 0x75, 0x74, 0xbc, 0xf9, + 0xac, 0xf3, 0x99, 0xb5, 0xdb, 0xee, 0xed, 0x36, 0x6f, 0x89, 0x4d, 0x7b, 0xd0, 0xe9, 0xf5, 0x3b, + 0xdb, 0x09, 0x78, 0x86, 0xbd, 0x0e, 0xeb, 0xc7, 0x07, 0xc7, 0xbd, 0xce, 0xb6, 0x95, 0x56, 0x2f, + 0x2b, 0xa8, 0x54, 0x96, 0xa7, 0x54, 0xcf, 0x3d, 0xfc, 0x3e, 0xd4, 0x93, 0x57, 0x78, 0x32, 0x80, + 0x85, 0xbd, 0xce, 0xd3, 0xf6, 0xd6, 0x67, 0x74, 0x75, 0x5f, 0xaf, 0xdf, 0xee, 0x77, 0xb7, 0x2c, + 0x79, 0x55, 0x9f, 0xe0, 0x08, 0x19, 0x56, 0x81, 0x62, 0xfb, 0x60, 0x6b, 0xf7, 0xd0, 0xec, 0x35, + 0xb3, 0x0f, 0x3f, 0x82, 0xe6, 0xac, 0x3f, 0x2a, 0xe1, 0xc0, 0x7b, 0x91, 0xa7, 0xef, 0xe1, 0xbf, + 0xc8, 0x01, 0xc4, 0x09, 0x03, 0x82, 0xd5, 0x6c, 0xb7, 0xfb, 0xed, 0xbd, 0x43, 0x31, 0x0d, 0xf3, + 0xb0, 0x2f, 0x38, 0x88, 0xd9, 0xf9, 0xb8, 0x79, 0x2b, 0xb5, 0xe4, 0xf0, 0xa8, 0xdf, 0xcc, 0x88, + 0x15, 0xeb, 0x1e, 0x74, 0xfb, 0xdd, 0xf6, 0x9e, 0x65, 0x1e, 0x1e, 0x77, 0x0f, 0x9e, 0xd2, 0x9d, + 0x64, 0xc8, 0x65, 0x8f, 0x8f, 0x76, 0xcc, 0xc3, 0x83, 0xbe, 0xd5, 0xdb, 0x3d, 0xee, 0x6f, 0xe3, + 0x8d, 0x66, 0x5b, 0x66, 0xf7, 0x88, 0xda, 0xcc, 0xbf, 0x08, 0x41, 0x34, 0x5d, 0x10, 0x6b, 0xfe, + 0xf4, 0xb0, 0xd7, 0xeb, 0x1e, 0x59, 0x1f, 0x1f, 0x77, 0xcc, 0x6e, 0xa7, 0x87, 0x15, 0x17, 0x52, + 0xe0, 0x02, 0xbf, 0x28, 0x78, 0x73, 0x7f, 0xef, 0x13, 0xc9, 0x3c, 0x05, 0x6a, 0x29, 0x09, 0x12, + 0x58, 0x65, 0xc1, 0x53, 0x04, 0xf7, 0x49, 0x69, 0x19, 0x6e, 0x28, 0x13, 0xf5, 0x2a, 0x82, 0xaf, + 0xce, 0xbd, 0x0c, 0xac, 0x56, 0x4d, 0x2f, 0x12, 0xb5, 0x90, 0xe5, 0x46, 0x07, 0xd4, 0xf6, 0xb6, + 0x89, 0x15, 0xea, 0x73, 0x50, 0x81, 0xdb, 0x10, 0x2f, 0x4a, 0xb0, 0x27, 0x81, 0xd2, 0x54, 0x0f, + 0xa2, 0x64, 0xf1, 0xc9, 0xef, 0xe4, 0xa0, 0x4e, 0xc9, 0x5b, 0xf4, 0xb1, 0x2a, 0xee, 0xb3, 0x7d, + 0x28, 0xca, 0xaf, 0x9e, 0xb1, 0x95, 0xe8, 0xba, 0x28, 0xfd, 0x3b, 0x6b, 0xeb, 0xab, 0xb3, 0x60, + 0x29, 0x8e, 0x2d, 0xfd, 0xb5, 0x3f, 0xf9, 0x9f, 0x7f, 0x2f, 0x5b, 0x63, 0x95, 0x47, 0x17, 0xef, + 0x3d, 0x3a, 0xe3, 0x6e, 0x20, 0xda, 0xf8, 0xff, 0x01, 0xe2, 0x6f, 0x79, 0xb1, 0x56, 0xe4, 0x84, + 0x9a, 0xf9, 0xd0, 0xd9, 0xfa, 0xed, 0x94, 0x12, 0xd9, 0xee, 0x6d, 0x6c, 0x77, 0xc9, 0xa8, 0x8b, + 0x76, 0x1d, 0xd7, 0x09, 0xe9, 0xbb, 0x5e, 0x1f, 0x66, 0x1e, 0xb2, 0x21, 0x54, 0xf5, 0xaf, 0x6c, + 0x31, 0x25, 0x29, 0xa5, 0x7c, 0x27, 0x6c, 0xfd, 0x4e, 0x6a, 0x99, 0x92, 0x41, 0xb1, 0x8f, 0x15, + 0xa3, 0x29, 0xfa, 0x98, 0x22, 0x46, 0xdc, 0xcb, 0x88, 0xa4, 0xf2, 0xf8, 0x63, 0x5a, 0xec, 0x35, + 0x4d, 0xae, 0x9a, 0xfb, 0x94, 0xd7, 0xfa, 0xdd, 0x1b, 0x4a, 0x65, 0x5f, 0x77, 0xb1, 0xaf, 0x35, + 0x83, 0x89, 0xbe, 0x06, 0x88, 0xa3, 0x3e, 0xe5, 0xf5, 0x61, 0xe6, 0xe1, 0x93, 0xbf, 0x78, 0x00, + 0xe5, 0x28, 0x98, 0x93, 0xfd, 0x16, 0xd4, 0x12, 0xd9, 0x75, 0x4c, 0x4d, 0x23, 0x2d, 0x19, 0x6f, + 0xfd, 0xb5, 0xf4, 0x42, 0xd9, 0xf1, 0xeb, 0xd8, 0x71, 0x8b, 0xad, 0x8a, 0x8e, 0x65, 0xf6, 0xda, + 0x23, 0xcc, 0x86, 0xa5, 0xcb, 0xb7, 0x9e, 0x6b, 0xda, 0x07, 0x75, 0xf6, 0xda, 0xac, 0x46, 0x90, + 0xe8, 0xed, 0xee, 0x0d, 0xa5, 0xb2, 0xbb, 0xd7, 0xb0, 0xbb, 0x55, 0xb6, 0xac, 0x77, 0xa7, 0x42, + 0x2f, 0x19, 0xc7, 0x0b, 0xef, 0xf4, 0x6f, 0x4d, 0xb1, 0xbb, 0xf1, 0xf5, 0x64, 0x29, 0xdf, 0xa0, + 0x8a, 0x48, 0x64, 0xfe, 0x43, 0x54, 0x46, 0x0b, 0xbb, 0x62, 0x0c, 0x5f, 0x9f, 0xfe, 0xa9, 0x29, + 0x76, 0x02, 0x15, 0xed, 0xf3, 0x0c, 0xec, 0xf6, 0x8d, 0x9f, 0x92, 0x58, 0x5f, 0x4f, 0x2b, 0x4a, + 0x9b, 0x8a, 0xde, 0xfe, 0xa3, 0x53, 0xce, 0xd9, 0x6f, 0x40, 0x39, 0xba, 0xf4, 0x9f, 0xad, 0x69, + 0x1f, 0x61, 0xd0, 0x3f, 0x52, 0xb0, 0xde, 0x9a, 0x2f, 0x48, 0x23, 0x3e, 0xbd, 0x75, 0x41, 0x7c, + 0x9f, 0x42, 0x45, 0xbb, 0xd8, 0x3f, 0x9a, 0xc0, 0xfc, 0xc7, 0x03, 0xa2, 0x09, 0xa4, 0x7c, 0x07, + 0xc0, 0x58, 0xc4, 0x2e, 0x2a, 0xac, 0x8c, 0xf4, 0x1d, 0x5e, 0x79, 0x01, 0xdb, 0x83, 0x15, 0xa9, + 0x69, 0x9d, 0xf0, 0x2f, 0xf3, 0x1a, 0x52, 0x3e, 0xef, 0xf5, 0x38, 0xc3, 0x3e, 0x82, 0x92, 0xfa, + 0x7e, 0x03, 0x5b, 0x4d, 0xff, 0x0e, 0xc5, 0xfa, 0xda, 0x1c, 0x5c, 0xaa, 0x45, 0x9f, 0x01, 0xc4, + 0x5f, 0x11, 0x88, 0x98, 0xc4, 0xdc, 0x57, 0x09, 0x22, 0x0a, 0x98, 0xff, 0xe4, 0x80, 0xb1, 0x8a, + 0x13, 0x6c, 0x32, 0x64, 0x12, 0x2e, 0xbf, 0x54, 0xb7, 0x92, 0xfe, 0x08, 0x2a, 0xda, 0x87, 0x04, + 0xa2, 0xe5, 0x9b, 0xff, 0x08, 0x41, 0xb4, 0x7c, 0x29, 0xdf, 0x1d, 0x30, 0xd6, 0xb1, 0xf5, 0x65, + 0xa3, 0x21, 0x5a, 0x17, 0xa2, 0x96, 0x14, 0x79, 0xc4, 0x0b, 0x3a, 0x87, 0x5a, 0xe2, 0x6b, 0x01, + 0xd1, 0x0e, 0x4d, 0xfb, 0x16, 0x41, 0xb4, 0x43, 0x53, 0x3f, 0x30, 0xa0, 0xe8, 0xcc, 0x58, 0x14, + 0xfd, 0x5c, 0x20, 0x8a, 0xd6, 0xd3, 0x0f, 0xa1, 0xa2, 0xdd, 0xfc, 0x1f, 0xcd, 0x65, 0xfe, 0x23, + 0x03, 0xd1, 0x5c, 0xd2, 0x3e, 0x14, 0xb0, 0x8c, 0x7d, 0xd4, 0x0d, 0x24, 0x05, 0xbc, 0x57, 0x51, + 0xb4, 0xfd, 0x5b, 0x50, 0x4f, 0x7e, 0x0c, 0x20, 0xda, 0xfb, 0xa9, 0x5f, 0x15, 0x88, 0xf6, 0xfe, + 0x0d, 0x5f, 0x10, 0x90, 0x24, 0xfd, 0x70, 0x29, 0xea, 0xe4, 0xd1, 0x4f, 0x64, 0x5a, 0xca, 0x17, + 0xec, 0x63, 0xc1, 0xe0, 0xe4, 0xb5, 0x9e, 0x6c, 0x4d, 0xa3, 0x5a, 0xfd, 0x7e, 0xd0, 0x68, 0xbf, + 0xcc, 0xdd, 0x00, 0x9a, 0x24, 0x66, 0x6c, 0x9c, 0x3d, 0x85, 0xa5, 0x88, 0x98, 0xa3, 0x7b, 0x3a, + 0x83, 0x68, 0x0e, 0xa9, 0xb7, 0x81, 0xae, 0x37, 0x67, 0x4b, 0x1f, 0x67, 0xe8, 0xf8, 0xc3, 0xdb, + 0x11, 0xb5, 0xe3, 0x4f, 0xbf, 0xaa, 0x53, 0x3b, 0xfe, 0x12, 0x97, 0x28, 0xce, 0x1e, 0x7f, 0xa1, + 0x23, 0xda, 0x70, 0xa1, 0x31, 0x7b, 0x6b, 0xe6, 0xdd, 0x9b, 0xd2, 0xfe, 0xa9, 0xf9, 0xd7, 0x5f, + 0x7c, 0x2b, 0x40, 0x92, 0x15, 0x29, 0x6e, 0xfa, 0x48, 0x06, 0x9f, 0xb0, 0xdf, 0x84, 0xaa, 0x7e, + 0x81, 0x38, 0xd3, 0x79, 0xc2, 0x6c, 0x4f, 0x77, 0x52, 0xcb, 0x92, 0x54, 0xc2, 0xaa, 0x7a, 0x37, + 0xec, 0x13, 0x58, 0x8d, 0x96, 0x59, 0xcf, 0x5b, 0x0f, 0xd8, 0xbd, 0x94, 0x6c, 0xf6, 0xc4, 0x62, + 0xdf, 0xbe, 0x31, 0xdd, 0xfd, 0x71, 0x46, 0x50, 0x5f, 0xf2, 0x26, 0xe3, 0xf8, 0xe4, 0x49, 0xbb, + 0xc0, 0x39, 0x3e, 0x79, 0x52, 0xaf, 0x3f, 0x56, 0xd4, 0xc7, 0x96, 0x12, 0x6b, 0x44, 0x61, 0xb9, + 0xec, 0x87, 0xd0, 0xd0, 0x92, 0xf2, 0x7b, 0xd7, 0xee, 0x20, 0xda, 0x49, 0xf3, 0x57, 0xf1, 0xad, + 0xa7, 0xd9, 0x26, 0x8d, 0x35, 0x6c, 0x7f, 0xd1, 0x48, 0x2c, 0x8e, 0xd8, 0x45, 0x5b, 0x50, 0xd1, + 0x13, 0xfe, 0x5f, 0xd0, 0xee, 0x9a, 0x56, 0xa4, 0xdf, 0xfa, 0xf6, 0x38, 0xc3, 0xf6, 0xa0, 0x39, + 0x7b, 0x07, 0x55, 0xc4, 0x53, 0xd2, 0xee, 0xcd, 0x5a, 0x9f, 0x29, 0x4c, 0xdc, 0x5c, 0xc5, 0x8e, + 0x28, 0xb1, 0x23, 0xfa, 0x16, 0x96, 0xe7, 0xcf, 0x9e, 0xea, 0xc9, 0x6f, 0x64, 0x45, 0xad, 0xa5, + 0x7d, 0x1d, 0xed, 0x41, 0xe6, 0x71, 0x86, 0xfd, 0x5e, 0x06, 0xaa, 0x89, 0x7b, 0x5f, 0x12, 0xa1, + 0xf3, 0x33, 0xf3, 0x6c, 0xe9, 0x65, 0xfa, 0x44, 0x0d, 0x13, 0x17, 0x71, 0xef, 0xe1, 0x0f, 0x12, + 0x2f, 0xe9, 0x27, 0x09, 0xd7, 0xde, 0xc6, 0xec, 0xc7, 0xb2, 0xbe, 0x98, 0x45, 0xd0, 0x6f, 0x58, + 0xfc, 0xe2, 0x71, 0x86, 0xfd, 0xab, 0x0c, 0xd4, 0x93, 0x3e, 0xfb, 0x68, 0xba, 0xa9, 0xd1, 0x01, + 0x11, 0x29, 0xdd, 0xe0, 0xe8, 0xff, 0x21, 0x8e, 0xb2, 0xff, 0xd0, 0x4c, 0x8c, 0x52, 0xde, 0xc1, + 0xfd, 0x8b, 0x8d, 0x96, 0x7d, 0x48, 0xdf, 0xa6, 0x54, 0xa1, 0x4c, 0x6c, 0xfe, 0x5b, 0x86, 0x11, + 0xf9, 0xe9, 0x5f, 0xfe, 0xc3, 0x97, 0xf0, 0x23, 0xfa, 0x28, 0x94, 0x8a, 0x8c, 0x11, 0x54, 0xfc, + 0xaa, 0xf5, 0x8d, 0xb7, 0x70, 0x4e, 0xaf, 0x1b, 0xb7, 0x13, 0x73, 0x9a, 0x15, 0x3c, 0xda, 0x34, + 0x3a, 0xf9, 0xe1, 0xbe, 0xf8, 0xe4, 0x9c, 0xfb, 0x98, 0xdf, 0xcd, 0x83, 0x1c, 0xd3, 0x20, 0x25, + 0x7a, 0x62, 0xab, 0xbd, 0x62, 0x33, 0xc6, 0x43, 0x1c, 0xeb, 0x5b, 0xc6, 0xbd, 0x1b, 0xc7, 0xfa, + 0x08, 0xfd, 0xef, 0x62, 0xc4, 0x47, 0x00, 0x71, 0xa8, 0x21, 0x9b, 0x09, 0x78, 0x8b, 0x18, 0xd0, + 0x7c, 0x34, 0x62, 0x72, 0x3f, 0xab, 0xb8, 0x38, 0xd1, 0xe2, 0x6f, 0x10, 0x3b, 0x8d, 0x42, 0xf1, + 0x74, 0xe9, 0x2b, 0x19, 0x15, 0x98, 0x90, 0xbe, 0x66, 0xdb, 0x4f, 0x30, 0xd3, 0x28, 0xee, 0xee, + 0x18, 0x6a, 0x7b, 0x9e, 0xf7, 0x7c, 0x3a, 0x89, 0xc2, 0xdb, 0x93, 0x41, 0x31, 0xbb, 0x76, 0x70, + 0xbe, 0x3e, 0x33, 0x0b, 0xe3, 0x3e, 0x36, 0xb5, 0xce, 0x5a, 0x5a, 0x53, 0x8f, 0x7e, 0x12, 0xc7, + 0x37, 0x7e, 0xc1, 0x6c, 0x58, 0x8c, 0x78, 0x74, 0x1c, 0x43, 0x98, 0x6c, 0x26, 0xc1, 0x99, 0x67, + 0xbb, 0x48, 0xa8, 0x09, 0x6a, 0xb4, 0x8f, 0x02, 0xd5, 0xe6, 0xe3, 0x0c, 0x3b, 0x82, 0xea, 0x36, + 0x1f, 0x60, 0xa2, 0x3e, 0x86, 0x96, 0x2c, 0x25, 0xc2, 0x14, 0x28, 0x26, 0x65, 0xbd, 0x96, 0x00, + 0x26, 0xcf, 0xad, 0x89, 0x7d, 0xed, 0xf3, 0xcf, 0x1f, 0xfd, 0x44, 0x06, 0xad, 0x7c, 0xa1, 0xce, + 0x2d, 0x15, 0xd4, 0x93, 0x38, 0xb7, 0x66, 0xa2, 0x80, 0x12, 0xe7, 0xd6, 0x5c, 0x14, 0x50, 0x62, + 0xa9, 0x55, 0x50, 0x11, 0x1b, 0xc1, 0xe2, 0x5c, 0xe0, 0x50, 0x74, 0x64, 0xdd, 0x14, 0x6e, 0xb4, + 0x7e, 0xff, 0x66, 0x84, 0x64, 0x6f, 0x0f, 0x93, 0xbd, 0xf5, 0xa0, 0x46, 0x97, 0x3e, 0x9e, 0x70, + 0x4a, 0xd9, 0x9b, 0xb9, 0xef, 0x46, 0xcf, 0x07, 0x9c, 0x3d, 0x60, 0xb0, 0x2c, 0x29, 0xe1, 0x60, + 0xae, 0x1c, 0xfb, 0x0d, 0xa8, 0x3c, 0xe5, 0xa1, 0xca, 0xd1, 0x8b, 0x64, 0xec, 0x99, 0xa4, 0xbd, + 0xf5, 0x94, 0x14, 0xbf, 0x24, 0xcd, 0x60, 0x6b, 0x8f, 0xf8, 0xf0, 0x8c, 0x13, 0x73, 0xb2, 0x9c, + 0xe1, 0x17, 0xec, 0xd7, 0xb1, 0xf1, 0x28, 0x35, 0x7a, 0x55, 0x4b, 0xc2, 0xd2, 0x1b, 0x6f, 0xcc, + 0xc0, 0xd3, 0x5a, 0x76, 0xbd, 0x21, 0xd7, 0x64, 0x3d, 0x17, 0x2a, 0xda, 0x15, 0x0a, 0xd1, 0x06, + 0x9a, 0xbf, 0x32, 0x23, 0xda, 0x40, 0x29, 0x37, 0x2e, 0x18, 0x0f, 0xb0, 0x1f, 0x83, 0xdd, 0x8f, + 0xfb, 0xa1, 0x5b, 0x16, 0xe2, 0x9e, 0x1e, 0xfd, 0xc4, 0x1e, 0x87, 0x5f, 0xb0, 0x4f, 0xf1, 0x6a, + 0x75, 0x3d, 0x07, 0x31, 0x56, 0x1a, 0x66, 0xd3, 0x15, 0xa3, 0xc5, 0xd2, 0x8a, 0x92, 0x8a, 0x04, + 0x75, 0x85, 0x92, 0xdc, 0xfb, 0x00, 0xbd, 0xd0, 0x9b, 0x6c, 0xdb, 0x7c, 0xec, 0xb9, 0x31, 0xaf, + 0x8d, 0xb3, 0xe2, 0x62, 0xfe, 0xa5, 0xa5, 0xc6, 0xb1, 0x4f, 0x35, 0x2d, 0x2b, 0x91, 0xc6, 0xa9, + 0x88, 0xeb, 0xc6, 0xc4, 0xb9, 0x68, 0x41, 0x52, 0x92, 0xe7, 0x1e, 0x67, 0x58, 0x1b, 0x20, 0x8e, + 0x1c, 0x8b, 0x74, 0xa6, 0xb9, 0xa0, 0xb4, 0x88, 0xed, 0xa5, 0x84, 0x99, 0x1d, 0x41, 0x39, 0x0e, + 0xb9, 0x59, 0x8b, 0x6f, 0x84, 0x49, 0x04, 0xe8, 0x44, 0x27, 0xf8, 0x5c, 0xb8, 0x8b, 0xd1, 0xc4, + 0xa5, 0x02, 0x56, 0x12, 0x4b, 0x75, 0xca, 0x79, 0xc0, 0x1c, 0x58, 0xa2, 0x01, 0x46, 0xe2, 0x12, + 0x66, 0x73, 0x45, 0x37, 0xe8, 0xcf, 0x47, 0x9e, 0x44, 0xbb, 0x39, 0x35, 0x7e, 0x22, 0x61, 0xfa, + 0x11, 0xd4, 0x4a, 0x99, 0x64, 0x82, 0x35, 0x8f, 0x61, 0x71, 0xce, 0x45, 0x1f, 0x6d, 0xe9, 0x9b, + 0x62, 0x2e, 0xa2, 0x2d, 0x7d, 0xa3, 0x77, 0xdf, 0x58, 0xc1, 0x2e, 0x1b, 0x06, 0xa0, 0xaa, 0x77, + 0xe9, 0x84, 0x83, 0x73, 0xd1, 0xdd, 0x3f, 0xcf, 0xc0, 0x52, 0x8a, 0x13, 0x9e, 0xbd, 0xa1, 0xac, + 0x06, 0x37, 0x3a, 0xe8, 0xd7, 0x53, 0x9d, 0xb5, 0x46, 0x0f, 0xfb, 0xd9, 0x67, 0xcf, 0x12, 0x07, + 0x1b, 0xf9, 0x4a, 0xe5, 0xce, 0x7c, 0xa1, 0x50, 0x91, 0x2a, 0x51, 0x7c, 0x0e, 0x6b, 0x34, 0x90, + 0xf6, 0x68, 0x34, 0xe3, 0x48, 0x7e, 0x7d, 0xee, 0xdb, 0xf5, 0x09, 0xe7, 0xf8, 0xfa, 0xcd, 0xdf, + 0xb6, 0xbf, 0x41, 0x9c, 0xa6, 0xa1, 0xb2, 0x29, 0x34, 0x67, 0x1d, 0xb4, 0xec, 0xe6, 0xb6, 0xd6, + 0xef, 0x25, 0xf4, 0xdf, 0x14, 0xa7, 0xee, 0xd7, 0xb0, 0xb3, 0x7b, 0xc6, 0x7a, 0xda, 0xba, 0x90, + 0x4a, 0x2c, 0xde, 0xc7, 0x5f, 0x8d, 0xbc, 0xc9, 0x33, 0xf3, 0x54, 0x1d, 0xdc, 0xe4, 0xfb, 0x8e, + 0x34, 0xf0, 0x74, 0x67, 0xf4, 0xdb, 0xd8, 0xfd, 0x7d, 0xe3, 0x4e, 0x5a, 0xf7, 0x3e, 0x55, 0x21, + 0x5d, 0x7c, 0x6d, 0x76, 0x5f, 0xab, 0x11, 0xdc, 0x4f, 0x7b, 0xdf, 0x37, 0xea, 0x42, 0x33, 0x6b, + 0x7d, 0x0b, 0x65, 0xbb, 0xaa, 0xee, 0x3d, 0x8e, 0xb6, 0x4f, 0x8a, 0x9b, 0x3a, 0xda, 0x3e, 0x69, + 0xee, 0xe6, 0xa4, 0x5c, 0xa3, 0x1c, 0xcd, 0x1f, 0x66, 0x1e, 0x6e, 0xbe, 0xf3, 0xc3, 0xaf, 0x9d, + 0x39, 0xe1, 0xf9, 0xf4, 0x64, 0x63, 0xe0, 0x8d, 0x1f, 0x8d, 0x94, 0xb5, 0x51, 0xa6, 0x3c, 0x3f, + 0x1a, 0xb9, 0xc3, 0x47, 0xd8, 0xec, 0xc9, 0xc2, 0xc4, 0xf7, 0x42, 0xef, 0x5b, 0xff, 0x37, 0x00, + 0x00, 0xff, 0xff, 0x1f, 0xcc, 0xbd, 0x51, 0x9e, 0x83, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index f15cbfa42c..5a34ab6252 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1437,6 +1437,15 @@ message Channel { amount to us. */ uint64 push_amount_sat = 27; + + /** + This uint32 indicates if this channel is to be considered 'frozen'. A + frozen channel doest not allow a cooperative channel close by the + initiator. The thaw_height is the height that this restriction stops + applying to the channel. This field is optional, not setting it or using a + value of zero will mean the channel has no additional restrictions. + */ + uint32 thaw_height = 28; } message ListChannelsRequest { @@ -1881,6 +1890,14 @@ message ChanPointShim { channel ID. */ bytes pending_chan_id = 5; + + /** + This uint32 indicates if this channel is to be considered 'frozen'. A + frozen channel does not allow a cooperative channel close by the + initiator. The thaw_height is the height that this restriction stops + applying to the channel. + */ + uint32 thaw_height = 6; } message FundingShim { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 6d96ac69bd..feab931a53 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1847,6 +1847,11 @@ "type": "string", "format": "byte", "description": "*\nIf non-zero, then this will be used as the pending channel ID on the wire\nprotocol to initate the funding request. This is an optional field, and\nshould only be set if the responder is already expecting a specific pending\nchannel ID." + }, + "thaw_height": { + "type": "integer", + "format": "int64", + "description": "*\nThis uint32 indicates if this channel is to be considered 'frozen'. A\nfrozen channel does not allow a cooperative channel close by the\ninitiator. The thaw_height is the height that this restriction stops\napplying to the channel." } } }, @@ -2002,6 +2007,11 @@ "type": "string", "format": "uint64", "description": "The amount that the initiator of the channel optionally pushed to the remote\nparty on channel open. This amount will be zero if the channel initiator did\nnot push any funds to the remote peer. If the initiator field is true, we\npushed this amount to our peer, if it is false, the remote peer pushed this\namount to us." + }, + "thaw_height": { + "type": "integer", + "format": "int64", + "description": "*\nThis uint32 indicates if this channel is to be considered 'frozen'. A\nfrozen channel doest not allow a cooperative channel close by the\ninitiator. The thaw_height is the height that this restriction stops\napplying to the channel. This field is optional, not setting it or using a\nvalue of zero will mean the channel has no additional restrictions." } } }, From 8bce48d3ccd84dc2eb46c44dd2337a0c2b52dacd Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 16:51:32 -0700 Subject: [PATCH 280/562] lnwallet/chanfunding: add new ThawHeight() method to ShimIntent+CannedAssembler As frozen channels can only be created via the non-default channel assembler, we extend both the ShimIntent and CannedAssembler to also accept and expose this new channel status along with the thaw height. --- lnwallet/chanfunding/canned_assembler.go | 28 +++++++++++++++++++----- rpcserver.go | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lnwallet/chanfunding/canned_assembler.go b/lnwallet/chanfunding/canned_assembler.go index 36ebba15f1..b512a7223a 100644 --- a/lnwallet/chanfunding/canned_assembler.go +++ b/lnwallet/chanfunding/canned_assembler.go @@ -30,6 +30,11 @@ type ShimIntent struct { // chanPoint is the final channel point for the to be created channel. chanPoint *wire.OutPoint + + // thawHeight, if non-zero is the height where this channel will become + // a normal channel. Until this height, it's considered frozen, so it + // can only be cooperatively closed by the responding party. + thawHeight uint32 } // FundingOutput returns the witness script, and the output that creates the @@ -87,6 +92,12 @@ func (s *ShimIntent) ChanPoint() (*wire.OutPoint, error) { return s.chanPoint, nil } +// ThawHeight returns the height where this channel goes back to being a normal +// channel. +func (s *ShimIntent) ThawHeight() uint32 { + return s.thawHeight +} + // FundingKeys couples our multi-sig key along with the remote party's key. type FundingKeys struct { // LocalKey is our multi-sig key. @@ -131,12 +142,17 @@ type CannedAssembler struct { // initiator indicates if we're the initiator or the channel or not. initiator bool + + // thawHeight, if non-zero is the height where this channel will become + // a normal channel. Until this height, it's considered frozen, so it + // can only be cooperatively closed by the responding party. + thawHeight uint32 } // NewCannedAssembler creates a new CannedAssembler from the material required // to construct a funding output and channel point. -func NewCannedAssembler(chanPoint wire.OutPoint, fundingAmt btcutil.Amount, - localKey *keychain.KeyDescriptor, +func NewCannedAssembler(thawHeight uint32, chanPoint wire.OutPoint, + fundingAmt btcutil.Amount, localKey *keychain.KeyDescriptor, remoteKey *btcec.PublicKey, initiator bool) *CannedAssembler { return &CannedAssembler{ @@ -145,6 +161,7 @@ func NewCannedAssembler(chanPoint wire.OutPoint, fundingAmt btcutil.Amount, remoteKey: remoteKey, fundingAmt: fundingAmt, chanPoint: chanPoint, + thawHeight: thawHeight, } } @@ -162,9 +179,10 @@ func (c *CannedAssembler) ProvisionChannel(req *Request) (Intent, error) { } intent := &ShimIntent{ - localKey: c.localKey, - remoteKey: c.remoteKey, - chanPoint: &c.chanPoint, + localKey: c.localKey, + remoteKey: c.remoteKey, + chanPoint: &c.chanPoint, + thawHeight: c.thawHeight, } if c.initiator { diff --git a/rpcserver.go b/rpcserver.go index baf7c05720..a9aaa09f2c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1545,7 +1545,7 @@ func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, // With all the parts assembled, we can now make the canned assembler // to pass into the wallet. return chanfunding.NewCannedAssembler( - *chanPoint, btcutil.Amount(chanPointShim.Amt), + 0, *chanPoint, btcutil.Amount(chanPointShim.Amt), &localKeyDesc, remoteKey, initiator, ), nil } From c85f6bb364bd32ea965c082aba0957a524b48e86 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 16:57:48 -0700 Subject: [PATCH 281/562] lnwallet: mark channel as frozen based on ShimIntent In this commit, we make the internal channel funding flow aware of frozen channels. We also update the testSingleFunderReservationWorkflow method to ensure that the created channels have the proper type bit set. --- lnwallet/interface_test.go | 39 ++++++++++++++++++++++++++++---------- lnwallet/reservation.go | 11 +++++++++-- lnwallet/wallet.go | 34 ++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index aae62cf317..faadaca22d 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -701,7 +701,7 @@ func testCancelNonExistentReservation(miner *rpctest.Harness, res, err := lnwallet.NewChannelReservation( 10000, 10000, feePerKw, alice, 22, 10, &testHdSeed, lnwire.FFAnnounceChannel, lnwallet.CommitmentTypeTweakless, - nil, [32]byte{}, + nil, [32]byte{}, 0, ) if err != nil { t.Fatalf("unable to create res: %v", err) @@ -796,8 +796,8 @@ func assertContributionInitPopulated(t *testing.T, c *lnwallet.ChannelContributi func testSingleFunderReservationWorkflow(miner *rpctest.Harness, alice, bob *lnwallet.LightningWallet, t *testing.T, commitType lnwallet.CommitmentType, - aliceChanFunder chanfunding.Assembler, - fetchFundingTx func() *wire.MsgTx, pendingChanID [32]byte) { + aliceChanFunder chanfunding.Assembler, fetchFundingTx func() *wire.MsgTx, + pendingChanID [32]byte, thawHeight uint32) { // For this scenario, Alice will be the channel initiator while bob // will act as the responder to the workflow. @@ -1045,6 +1045,24 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, t.Fatalf("incorrect transaction was mined") } + // If a frozen channel was requested, then we expect that both channel + // types show as being a frozen channel type. + aliceChanFrozen := aliceChannels[0].ChanType.IsFrozen() + bobChanFrozen := bobChannels[0].ChanType.IsFrozen() + if thawHeight != 0 && (!aliceChanFrozen || !bobChanFrozen) { + t.Fatalf("expected both alice and bob to have frozen chans: "+ + "alice_frozen=%v, bob_frozen=%v", aliceChanFrozen, + bobChanFrozen) + } + if thawHeight != bobChannels[0].ThawHeight { + t.Fatalf("wrong thaw height: expected %v got %v", thawHeight, + bobChannels[0].ThawHeight) + } + if thawHeight != aliceChannels[0].ThawHeight { + t.Fatalf("wrong thaw height: expected %v got %v", thawHeight, + aliceChannels[0].ThawHeight) + } + assertReservationDeleted(aliceChanReservation, t) assertReservationDeleted(bobChanReservation, t) } @@ -2546,8 +2564,8 @@ var walletTests = []walletTestCase{ testSingleFunderReservationWorkflow( miner, alice, bob, t, - lnwallet.CommitmentTypeLegacy, nil, nil, - [32]byte{}, + lnwallet.CommitmentTypeLegacy, nil, + nil, [32]byte{}, 0, ) }, }, @@ -2558,8 +2576,8 @@ var walletTests = []walletTestCase{ testSingleFunderReservationWorkflow( miner, alice, bob, t, - lnwallet.CommitmentTypeTweakless, nil, nil, - [32]byte{}, + lnwallet.CommitmentTypeTweakless, nil, + nil, [32]byte{}, 0, ) }, }, @@ -2777,12 +2795,13 @@ func testSingleFunderExternalFundingTx(miner *rpctest.Harness, // Now that we have the fully constructed funding transaction, we'll // create a new shim external funder out of it for Alice, and prep a // shim intent for Bob. + thawHeight := uint32(200) aliceExternalFunder := chanfunding.NewCannedAssembler( - *chanPoint, btcutil.Amount(chanAmt), &aliceFundingKey, + thawHeight, *chanPoint, btcutil.Amount(chanAmt), &aliceFundingKey, bobFundingKey.PubKey, true, ) bobShimIntent, err := chanfunding.NewCannedAssembler( - *chanPoint, btcutil.Amount(chanAmt), &bobFundingKey, + thawHeight, *chanPoint, btcutil.Amount(chanAmt), &bobFundingKey, aliceFundingKey.PubKey, false, ).ProvisionChannel(&chanfunding.Request{ LocalAmt: btcutil.Amount(chanAmt), @@ -2816,7 +2835,7 @@ func testSingleFunderExternalFundingTx(miner *rpctest.Harness, miner, alice, bob, t, lnwallet.CommitmentTypeTweakless, aliceExternalFunder, func() *wire.MsgTx { return fundingTx - }, pendingChanID, + }, pendingChanID, thawHeight, ) } diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 823aec4ae3..3c9188a655 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -171,7 +171,7 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, id uint64, pushMSat lnwire.MilliSatoshi, chainHash *chainhash.Hash, flags lnwire.FundingFlag, commitType CommitmentType, fundingAssembler chanfunding.Assembler, - pendingChanID [32]byte) (*ChannelReservation, error) { + pendingChanID [32]byte, thawHeight uint32) (*ChannelReservation, error) { var ( ourBalance lnwire.MilliSatoshi @@ -306,6 +306,12 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, chanType |= channeldb.AnchorOutputsBit } + // If the channel is meant to be frozen, then we'll set the frozen bit + // now so once the channel is open, it can be interpreted properly. + if thawHeight != 0 { + chanType |= channeldb.FrozenBit + } + return &ChannelReservation{ ourContribution: &ChannelContribution{ FundingAmount: ourBalance.ToSatoshis(), @@ -334,7 +340,8 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, FeePerKw: btcutil.Amount(commitFeePerKw), CommitFee: commitFee, }, - Db: wallet.Cfg.Database, + ThawHeight: thawHeight, + Db: wallet.Cfg.Database, }, pushMSat: pushMSat, pendingChanID: pendingChanID, diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index dbada608b9..06fb9bb7e8 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -560,6 +560,26 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg remoteFundingAmt = fundingIntent.RemoteFundingAmt() } + // If this is a shim intent, then it may be attempting to use an + // existing set of keys for the funding workflow. In this case, we'll + // make a simple wrapper keychain.KeyRing that will proxy certain + // derivation calls to future callers. + var ( + keyRing keychain.KeyRing = l.SecretKeyRing + thawHeight uint32 + ) + if shimIntent, ok := fundingIntent.(*chanfunding.ShimIntent); ok { + keyRing = &shimKeyRing{ + KeyRing: keyRing, + ShimIntent: shimIntent, + } + + // As this was a registered shim intent, we'll obtain the thaw + // height of the intent, if present at all. If this is + // non-zero, then we'll mark this as the proper channel type. + thawHeight = shimIntent.ThawHeight() + } + // The total channel capacity will be the size of the funding output we // created plus the remote contribution. capacity := localFundingAmt + remoteFundingAmt @@ -569,6 +589,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg capacity, localFundingAmt, req.CommitFeePerKw, l, id, req.PushMSat, l.Cfg.NetParams.GenesisHash, req.Flags, req.CommitType, req.ChanFunder, req.PendingChanID, + thawHeight, ) if err != nil { if fundingIntent != nil { @@ -580,19 +601,6 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg return } - var keyRing keychain.KeyRing = l.SecretKeyRing - - // If this is a shim intent, then it may be attempting to use an - // existing set of keys for the funding workflow. In this case, we'll - // make a simple wrapper keychain.KeyRing that will proxy certain - // derivation calls to future callers. - if shimIntent, ok := fundingIntent.(*chanfunding.ShimIntent); ok { - keyRing = &shimKeyRing{ - KeyRing: keyRing, - ShimIntent: shimIntent, - } - } - err = l.initOurContribution( reservation, fundingIntent, req.NodeAddr, req.NodeID, keyRing, ) From 1ac7550e3fdcac5be575bfffe50c5c9e2bfe1656 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 16:58:05 -0700 Subject: [PATCH 282/562] chancloser: deny co-op close initiated by the chan initiator for frozen chans --- chancloser.go | 17 ++++++++++++++++- rpcserver.go | 28 ++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/chancloser.go b/chancloser.go index bcd0ec8bde..4dc28d40ef 100644 --- a/chancloser.go +++ b/chancloser.go @@ -347,6 +347,21 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b "instead have %v", spew.Sdump(msg)) } + // As we're the responder to this shutdown (the other party + // wants to close), we'll check if this is a frozen channel or + // not. If the channel is frozen as we were also the initiator + // of the channel opening, then we'll deny their close attempt. + chanInitiator := c.cfg.channel.IsInitiator() + if !chanInitiator && c.cfg.channel.State().ChanType.IsFrozen() && + c.negotiationHeight < c.cfg.channel.State().ThawHeight { + + return nil, false, fmt.Errorf("initiator attempting "+ + "to co-op close frozen ChannelPoint(%v) "+ + "(current_height=%v, thaw_height=%v)", + c.chanPoint, c.negotiationHeight, + c.cfg.channel.State().ThawHeight) + } + // If the remote node opened the channel with option upfront shutdown // script, check that the script they provided matches. if err := maybeMatchScript( @@ -382,7 +397,7 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b // We'll also craft our initial close proposal in order to keep // the negotiation moving, but only if we're the negotiator. - if c.cfg.channel.IsInitiator() { + if chanInitiator { closeSigned, err := c.proposeCloseSigned(c.idealFeeSat) if err != nil { return nil, false, err diff --git a/rpcserver.go b/rpcserver.go index a9aaa09f2c..1cf9935d78 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1470,8 +1470,8 @@ func extractOpenChannelMinConfs(in *lnrpc.OpenChannelRequest) (int32, error) { // newFundingShimAssembler returns a new fully populated // chanfunding.CannedAssembler using a FundingShim obtained from an RPC caller. -func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, - initiator bool, keyRing keychain.KeyRing) (chanfunding.Assembler, error) { +func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, initiator bool, + keyRing keychain.KeyRing) (chanfunding.Assembler, error) { // Perform some basic sanity checks to ensure that all the expected // fields are populated. @@ -1545,8 +1545,9 @@ func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, // With all the parts assembled, we can now make the canned assembler // to pass into the wallet. return chanfunding.NewCannedAssembler( - 0, *chanPoint, btcutil.Amount(chanPointShim.Amt), - &localKeyDesc, remoteKey, initiator, + chanPointShim.ThawHeight, *chanPoint, + btcutil.Amount(chanPointShim.Amt), &localKeyDesc, + remoteKey, initiator, ), nil } @@ -1956,15 +1957,25 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, return err } + // If this is a frozen channel, then we only allow the close to proceed + // if we were the responder to this channel. + _, bestHeight, err := r.server.cc.chainIO.GetBestBlock() + if err != nil { + return err + } + if channel.State().ChanType.IsFrozen() && channel.IsInitiator() && + uint32(bestHeight) < channel.State().ThawHeight { + + return fmt.Errorf("cannot co-op close frozen channel as "+ + "initiator until height=%v, (current_height=%v)", + channel.State().ThawHeight, bestHeight) + } + // If a force closure was requested, then we'll handle all the details // around the creation and broadcast of the unilateral closure // transaction here rather than going to the switch as we don't require // interaction from the peer. if force { - _, bestHeight, err := r.server.cc.chainIO.GetBestBlock() - if err != nil { - return err - } // As we're force closing this channel, as a precaution, we'll // ensure that the switch doesn't continue to see this channel @@ -3179,6 +3190,7 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, RemoteChanReserveSat: int64(dbChannel.RemoteChanCfg.ChanReserve), StaticRemoteKey: commitmentType == lnrpc.CommitmentType_STATIC_REMOTE_KEY, CommitmentType: commitmentType, + ThawHeight: dbChannel.ThawHeight, } for i, htlc := range localCommit.Htlcs { From 625d62e0077da7b5a47162f89dbbf4fec450c197 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Mar 2020 17:14:30 -0700 Subject: [PATCH 283/562] lntest/itest: update external funding test to exercise frozen chans --- lntest/itest/lnd_test.go | 53 ++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index d84ed1148b..c097bdabf2 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -15060,16 +15060,23 @@ func testExternalFundingChanPoint(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("unable to gen pending chan ID: %v", err) } + _, currentHeight, err := net.Miner.Node.GetBestBlock() + if err != nil { + t.Fatalf("unable to get current blockheight %v", err) + } + // Now that we have the pending channel ID, Dave (our responder) will // register the intent to receive a new channel funding workflow using // the pending channel ID. - chanPointShim := &lnrpc.ChanPointShim{ - Amt: int64(chanSize), - ChanPoint: &lnrpc.ChannelPoint{ - FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ - FundingTxidBytes: txid[:], - }, + chanPoint := &lnrpc.ChannelPoint{ + FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ + FundingTxidBytes: txid[:], }, + } + thawHeight := uint32(currentHeight + 10) + chanPointShim := &lnrpc.ChanPointShim{ + Amt: int64(chanSize), + ChanPoint: chanPoint, LocalKey: &lnrpc.KeyDescriptor{ RawKeyBytes: daveFundingKey.RawKeyBytes, KeyLoc: &lnrpc.KeyLocator{ @@ -15079,6 +15086,7 @@ func testExternalFundingChanPoint(net *lntest.NetworkHarness, t *harnessTest) { }, RemoteKey: carolFundingKey.RawKeyBytes, PendingChanId: pendingChanID[:], + ThawHeight: thawHeight, } fundingShim := &lnrpc.FundingShim{ Shim: &lnrpc.FundingShim_ChanPointShim{ @@ -15121,13 +15129,24 @@ func testExternalFundingChanPoint(net *lntest.NetworkHarness, t *harnessTest) { // At this point, we'll now carry out the normal basic channel funding // test as everything should now proceed as normal (a regular channel // funding flow). - _, _, closeChans, err := basicChannelFundingTest( + carolChan, daveChan, _, err := basicChannelFundingTest( t, net, carol, dave, fundingShim, ) if err != nil { t.Fatalf("unable to open channels: %v", err) } + // Both channels should be marked as frozen with the proper thaw + // height. + if carolChan.ThawHeight != thawHeight { + t.Fatalf("expected thaw height of %v, got %v", + carolChan.ThawHeight, thawHeight) + } + if daveChan.ThawHeight != thawHeight { + t.Fatalf("expected thaw height of %v, got %v", + daveChan.ThawHeight, thawHeight) + } + // Next, to make sure the channel functions as normal, we'll make some // payments within the channel. payAmt := btcutil.Amount(100000) @@ -15148,10 +15167,24 @@ func testExternalFundingChanPoint(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("unable to make payments between Carol and Dave") } - // To conclude, we'll close the newly created channel between Carol and - // Dave. - closeChans() + // Now that the channels are open, and we've confirmed that they're + // operational, we'll now ensure that the channels are frozen as + // intended (if requested). + // + // First, we'll try to close the channel as Carol, the initiator. This + // should fail as a frozen channel only allows the responder to + // initiate a channel close. + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + _, _, err = net.CloseChannel(ctxt, carol, chanPoint, false) + if err == nil { + t.Fatalf("carol wasn't denied a co-op close attempt for a " + + "frozen channel") + } + // Next we'll try but this time with Dave (the responder) as the + // initiator. This time the channel should be closed as normal. + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, dave, chanPoint, false) } type testCase struct { From 466294ed4c87c0e121799d36b7d02021dabda803 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 24 Jan 2020 11:03:02 +0100 Subject: [PATCH 284/562] aezeed: use fast scrypt options in itest --- aezeed/cipherseed_rpctest.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 aezeed/cipherseed_rpctest.go diff --git a/aezeed/cipherseed_rpctest.go b/aezeed/cipherseed_rpctest.go new file mode 100644 index 0000000000..82f782cd2d --- /dev/null +++ b/aezeed/cipherseed_rpctest.go @@ -0,0 +1,13 @@ +// +build rpctest + +package aezeed + +import "github.com/btcsuite/btcwallet/waddrmgr" + +func init() { + // For the purposes of our itest, we'll crank down the scrypt params a + // bit. + scryptN = waddrmgr.FastScryptOptions.N + scryptR = waddrmgr.FastScryptOptions.R + scryptP = waddrmgr.FastScryptOptions.P +} From 847d27f8a688a3136de45e9560063d237c4e2bff Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 17 Jan 2020 14:23:42 +0100 Subject: [PATCH 285/562] macaroons: use fast scrypt options in itest and unit tests --- macaroons/security.go | 13 +++++++++++++ macaroons/security_rpctest.go | 14 ++++++++++++++ macaroons/security_test.go | 12 ++++++++++++ macaroons/store.go | 5 +++-- 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 macaroons/security.go create mode 100644 macaroons/security_rpctest.go create mode 100644 macaroons/security_test.go diff --git a/macaroons/security.go b/macaroons/security.go new file mode 100644 index 0000000000..814b0d256f --- /dev/null +++ b/macaroons/security.go @@ -0,0 +1,13 @@ +// +build !rpctest + +package macaroons + +import "github.com/btcsuite/btcwallet/snacl" + +var ( + // Below are the default scrypt parameters that are used when creating + // the encryption key for the macaroon database with snacl.NewSecretKey. + scryptN = snacl.DefaultN + scryptR = snacl.DefaultR + scryptP = snacl.DefaultP +) diff --git a/macaroons/security_rpctest.go b/macaroons/security_rpctest.go new file mode 100644 index 0000000000..d49819e0f2 --- /dev/null +++ b/macaroons/security_rpctest.go @@ -0,0 +1,14 @@ +// +build rpctest + +package macaroons + +import "github.com/btcsuite/btcwallet/waddrmgr" + +var ( + // Below are the reduced scrypt parameters that are used when creating + // the encryption key for the macaroon database with snacl.NewSecretKey. + // We use very low values for our itest/rpctest to speed things up. + scryptN = waddrmgr.FastScryptOptions.N + scryptR = waddrmgr.FastScryptOptions.R + scryptP = waddrmgr.FastScryptOptions.P +) diff --git a/macaroons/security_test.go b/macaroons/security_test.go new file mode 100644 index 0000000000..48c18e313a --- /dev/null +++ b/macaroons/security_test.go @@ -0,0 +1,12 @@ +package macaroons + +import "github.com/btcsuite/btcwallet/waddrmgr" + +func init() { + // Below are the reduced scrypt parameters that are used when creating + // the encryption key for the macaroon database with snacl.NewSecretKey. + // We use very low values for our itest/rpctest to speed things up. + scryptN = waddrmgr.FastScryptOptions.N + scryptR = waddrmgr.FastScryptOptions.R + scryptP = waddrmgr.FastScryptOptions.P +} diff --git a/macaroons/store.go b/macaroons/store.go index 16ccc9a38a..affb0c5067 100644 --- a/macaroons/store.go +++ b/macaroons/store.go @@ -106,8 +106,9 @@ func (r *RootKeyStorage) CreateUnlock(password *[]byte) error { } // We haven't yet stored a key, so create a new one. - encKey, err := snacl.NewSecretKey(password, snacl.DefaultN, - snacl.DefaultR, snacl.DefaultP) + encKey, err := snacl.NewSecretKey( + password, scryptN, scryptR, scryptP, + ) if err != nil { return err } From 95a67967783178579c595ced89236925e3d24850 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 17 Jan 2020 23:19:27 +0100 Subject: [PATCH 286/562] lnwallet/btcwallet: use fast scrypt options in itest --- lnwallet/btcwallet/btcwallet_rpctest.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 lnwallet/btcwallet/btcwallet_rpctest.go diff --git a/lnwallet/btcwallet/btcwallet_rpctest.go b/lnwallet/btcwallet/btcwallet_rpctest.go new file mode 100644 index 0000000000..7139e4cc17 --- /dev/null +++ b/lnwallet/btcwallet/btcwallet_rpctest.go @@ -0,0 +1,23 @@ +// +build rpctest + +package btcwallet + +import ( + "github.com/btcsuite/btcwallet/snacl" + "github.com/btcsuite/btcwallet/waddrmgr" +) + +func init() { + // Instruct waddrmgr to use the cranked down scrypt parameters when + // creating new wallet encryption keys. This will speed up the itests + // considerably. + fastScrypt := waddrmgr.FastScryptOptions + keyGen := func(passphrase *[]byte, config *waddrmgr.ScryptOptions) ( + *snacl.SecretKey, error) { + + return snacl.NewSecretKey( + passphrase, fastScrypt.N, fastScrypt.R, fastScrypt.P, + ) + } + waddrmgr.SetSecretKeyGen(keyGen) +} From a101c8eeedb33a2a2cd450ae8b5e961f35610385 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 17 Jan 2020 23:19:56 +0100 Subject: [PATCH 287/562] lntest: fix timing issue with auto reconnect --- lntest/itest/lnd_test.go | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 0e8237d02d..f2d53cc9ef 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -7328,10 +7328,12 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) { // Carol will be the breached party. We set --nolisten to ensure Bob // won't be able to connect to her and trigger the channel data - // protection logic automatically. + // protection logic automatically. We also can't have Carol + // automatically re-connect too early, otherwise DLP would be initiated + // instead of the breach we want to provoke. carol, err := net.NewNode( "Carol", - []string{"--hodl.exit-settle", "--nolisten"}, + []string{"--hodl.exit-settle", "--nolisten", "--minbackoff=1h"}, ) if err != nil { t.Fatalf("unable to create new carol node: %v", err) @@ -7591,10 +7593,12 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness // Dave will be the breached party. We set --nolisten to ensure Carol // won't be able to connect to him and trigger the channel data - // protection logic automatically. + // protection logic automatically. We also can't have Dave automatically + // re-connect too early, otherwise DLP would be initiated instead of the + // breach we want to provoke. dave, err := net.NewNode( "Dave", - []string{"--hodl.exit-settle", "--nolisten"}, + []string{"--hodl.exit-settle", "--nolisten", "--minbackoff=1h"}, ) if err != nil { t.Fatalf("unable to create new node: %v", err) @@ -8658,15 +8662,23 @@ func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest, dave *lntest.HarnessNode, daveStartingBalance int64, anchors bool) { + // We disabled auto-reconnect for some tests to avoid timing issues. + // To make sure the nodes are initiating DLP now, we have to manually + // re-connect them. + ctxb := context.Background() + err := net.ConnectNodes(ctxb, carol, dave) + if err != nil && !strings.Contains(err.Error(), "already connected") { + t.Fatalf("unable to connect Carol to Dave to initiate DLP: %v", + err) + } + // Upon reconnection, the nodes should detect that Dave is out of sync. // Carol should force close the channel using her latest commitment. expectedTxes := 1 if anchors { expectedTxes = 2 } - - ctxb := context.Background() - _, err := waitForNTxsInMempool( + _, err = waitForNTxsInMempool( net.Miner.Node, expectedTxes, minerMempoolTimeout, ) if err != nil { @@ -8777,8 +8789,12 @@ func testDataLossProtection(net *lntest.NetworkHarness, t *harnessTest) { // Carol will be the up-to-date party. We set --nolisten to ensure Dave // won't be able to connect to her and trigger the channel data - // protection logic automatically. - carol, err := net.NewNode("Carol", []string{"--nolisten"}) + // protection logic automatically. We also can't have Carol + // automatically re-connect too early, otherwise DLP would be initiated + // at the wrong moment. + carol, err := net.NewNode( + "Carol", []string{"--nolisten", "--minbackoff=1h"}, + ) if err != nil { t.Fatalf("unable to create new carol node: %v", err) } From eb531d0449cb3b95a3d3ff9a03a0ad0e15e91651 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 5 Mar 2020 15:57:28 +0100 Subject: [PATCH 288/562] htlcswitch: add causing error to log and err msg --- htlcswitch/link.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 7c834827d7..9b8323cd5e 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -627,7 +627,7 @@ func (l *channelLink) syncChanStates() error { if err := l.cfg.Peer.SendMessage(true, localChanSyncMsg); err != nil { return fmt.Errorf("Unable to send chan sync message for "+ - "ChannelPoint(%v)", l.channel.ChannelPoint()) + "ChannelPoint(%v): %v", l.channel.ChannelPoint(), err) } var msgsToReSend []lnwire.Message @@ -3121,7 +3121,7 @@ func (l *channelLink) fail(linkErr LinkFailureError, return } - l.log.Errorf("failing link: %s", reason) + l.log.Errorf("failing link: %s with error: %v", reason, linkErr) // Set failed, such that we won't process any more updates, and notify // the peer about the failure. From 770c80635ca14852f5097948298e892cf2e7a5fd Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 5 Mar 2020 15:59:01 +0100 Subject: [PATCH 289/562] lntest: give async payments enough time to complete --- lntest/timeouts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lntest/timeouts.go b/lntest/timeouts.go index 0521384605..d099d06b1d 100644 --- a/lntest/timeouts.go +++ b/lntest/timeouts.go @@ -23,5 +23,5 @@ const ( // AsyncBenchmarkTimeout is the timeout used when running the async // payments benchmark. - AsyncBenchmarkTimeout = time.Minute + AsyncBenchmarkTimeout = 2 * time.Minute ) From 81730e644450d6f9caf2528a3cb7633ff249856e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 24 Mar 2020 10:00:53 +0100 Subject: [PATCH 290/562] mod: update btcwallet dependency to fix neutrino flake --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index de7f0a9db3..987ffb5a0c 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d - github.com/btcsuite/btcwallet v0.11.1-0.20200219004649-ae9416ad7623 + github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7 github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 github.com/btcsuite/btcwallet/walletdb v1.2.0 diff --git a/go.sum b/go.sum index 3015a6d4b7..7fff12d554 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.11.1-0.20200219004649-ae9416ad7623 h1:ZuJRjucNsTmlrbZncsqzD0z3EaXrOobCx2I4lc12R4g= -github.com/btcsuite/btcwallet v0.11.1-0.20200219004649-ae9416ad7623/go.mod h1:1O1uRHMPXHdwA4/od8nqYqrgclVKp+wtfXUAqHmeRvE= +github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7 h1:ubYJYIi13atgwPCX7FZQZV2mytkaRHWPycDFdF28U0o= +github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7/go.mod h1:1O1uRHMPXHdwA4/od8nqYqrgclVKp+wtfXUAqHmeRvE= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= From 8dc5a3c14457faeb05087c562a8e91e7718355ce Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 24 Mar 2020 12:18:42 +0100 Subject: [PATCH 291/562] itest: wait for file writing in wait predicate --- lntest/itest/lnd_test.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 0e8237d02d..482d2a7fc4 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -12717,12 +12717,16 @@ func testAbandonChannel(net *lntest.NetworkHarness, t *harnessTest) { } // Make sure the channel is no longer in the channel backup list. - bkupAfter, err := ioutil.ReadFile(net.Alice.ChanBackupPath()) + err = wait.Predicate(func() bool { + bkupAfter, err := ioutil.ReadFile(net.Alice.ChanBackupPath()) + if err != nil { + t.Fatalf("could not get channel backup before "+ + "abandoning channel: %v", err) + } + + return len(bkupAfter) < len(bkupBefore) + }, defaultTimeout) if err != nil { - t.Fatalf("could not get channel backup before abandoning "+ - "channel: %v", err) - } - if len(bkupAfter) >= len(bkupBefore) { t.Fatalf("channel wasn't removed from channel backup file") } From 45a59345e7b5b441a5c0fe9ed85579f2c3497b6d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 24 Mar 2020 14:51:04 +0100 Subject: [PATCH 292/562] mod: bump version of queue package To fix external projects depending on lnd, we need to bump the queue package to a new version for the changes to be picked up. --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index de7f0a9db3..e642a81185 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d github.com/lightningnetwork/lightning-onion v1.0.1 github.com/lightningnetwork/lnd/cert v1.0.0 - github.com/lightningnetwork/lnd/queue v1.0.2 + github.com/lightningnetwork/lnd/queue v1.0.3 github.com/lightningnetwork/lnd/ticker v1.0.0 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 From ce7970ec4a1563d9ca4dcbad0efbdf3671c4ef3e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 24 Mar 2020 14:57:07 +0100 Subject: [PATCH 293/562] mod: bump version of cert package To fix external projects depending on lind, we need to bump the cert package to a new version for the changes to be picked up. --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index e642a81185..bcce60d792 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200 github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d github.com/lightningnetwork/lightning-onion v1.0.1 - github.com/lightningnetwork/lnd/cert v1.0.0 + github.com/lightningnetwork/lnd/cert v1.0.1 github.com/lightningnetwork/lnd/queue v1.0.3 github.com/lightningnetwork/lnd/ticker v1.0.0 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 From 6a36ed44f856ebd5a3b0731f0eea10f793a43c7f Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 24 Mar 2020 16:26:48 +0100 Subject: [PATCH 294/562] routing: extract mission control state Preparation for unit testing just the state logic. --- routing/missioncontrol.go | 173 +++-------------------------- routing/missioncontrol_state.go | 187 ++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+), 157 deletions(-) create mode 100644 routing/missioncontrol_state.go diff --git a/routing/missioncontrol.go b/routing/missioncontrol.go index a590f20ae3..963ea886b0 100644 --- a/routing/missioncontrol.go +++ b/routing/missioncontrol.go @@ -65,15 +65,9 @@ type NodeResults map[route.Vertex]TimedPairResult // since the last failure is used to estimate a success probability that is fed // into the path finding process for subsequent payment attempts. type MissionControl struct { - // lastPairResult tracks the last payment result (on a pair basis) for - // each transited node. This is a multi-layer map that allows us to look - // up the failure history of all connected channels (node pairs) for a - // particular node. - lastPairResult map[route.Vertex]NodeResults - - // lastSecondChance tracks the last time a second chance was granted for - // a directed node pair. - lastSecondChance map[DirectedNodePair]time.Time + // state is the internal mission control state that is input for + // probability estimation. + state *missionControlState // now is expected to return the current time. It is supplied as an // external function to enable deterministic unit tests. @@ -194,12 +188,11 @@ func NewMissionControl(db kvdb.Backend, cfg *MissionControlConfig) ( } mc := &MissionControl{ - lastPairResult: make(map[route.Vertex]NodeResults), - lastSecondChance: make(map[DirectedNodePair]time.Time), - now: time.Now, - cfg: cfg, - store: store, - estimator: estimator, + state: newMissionControlState(), + now: time.Now, + cfg: cfg, + store: store, + estimator: estimator, } if err := mc.init(); err != nil { @@ -240,8 +233,7 @@ func (m *MissionControl) ResetHistory() error { return err } - m.lastPairResult = make(map[route.Vertex]NodeResults) - m.lastSecondChance = make(map[DirectedNodePair]time.Time) + m.state.resetHistory() log.Debugf("Mission control history cleared") @@ -257,7 +249,7 @@ func (m *MissionControl) GetProbability(fromNode, toNode route.Vertex, defer m.Unlock() now := m.now() - results := m.lastPairResult[fromNode] + results, _ := m.state.getLastPairResult(fromNode) // Use a distinct probability estimation function for local channels. if fromNode == m.cfg.SelfNode { @@ -267,148 +259,15 @@ func (m *MissionControl) GetProbability(fromNode, toNode route.Vertex, return m.estimator.getPairProbability(now, results, toNode, amt) } -// setLastPairResult stores a result for a node pair. -func (m *MissionControl) setLastPairResult(fromNode, toNode route.Vertex, - timestamp time.Time, result *pairResult) { - - nodePairs, ok := m.lastPairResult[fromNode] - if !ok { - nodePairs = make(NodeResults) - m.lastPairResult[fromNode] = nodePairs - } - - current := nodePairs[toNode] - - // Apply the new result to the existing data for this pair. If there is - // no existing data, apply it to the default values for TimedPairResult. - if result.success { - successAmt := result.amt - current.SuccessTime = timestamp - - // Only update the success amount if this amount is higher. This - // prevents the success range from shrinking when there is no - // reason to do so. For example: small amount probes shouldn't - // affect a previous success for a much larger amount. - if successAmt > current.SuccessAmt { - current.SuccessAmt = successAmt - } - - // If the success amount goes into the failure range, move the - // failure range up. Future attempts up to the success amount - // are likely to succeed. We don't want to clear the failure - // completely, because we haven't learnt much for amounts above - // the current success amount. - if !current.FailTime.IsZero() && successAmt >= current.FailAmt { - current.FailAmt = successAmt + 1 - } - } else { - // For failures we always want to update both the amount and the - // time. Those need to relate to the same result, because the - // time is used to gradually diminish the penality for that - // specific result. Updating the timestamp but not the amount - // could cause a failure for a lower amount (a more severe - // condition) to be revived as if it just happened. - failAmt := result.amt - current.FailTime = timestamp - current.FailAmt = failAmt - - switch { - // The failure amount is set to zero when the failure is - // amount-independent, meaning that the attempt would have - // failed regardless of the amount. This should also reset the - // success amount to zero. - case failAmt == 0: - current.SuccessAmt = 0 - - // If the failure range goes into the success range, move the - // success range down. - case failAmt <= current.SuccessAmt: - current.SuccessAmt = failAmt - 1 - } - } - - log.Debugf("Setting %v->%v range to [%v-%v]", - fromNode, toNode, current.SuccessAmt, current.FailAmt) - - nodePairs[toNode] = current -} - -// setAllFail stores a fail result for all known connections to and from the -// given node. -func (m *MissionControl) setAllFail(node route.Vertex, - timestamp time.Time) { - - for fromNode, nodePairs := range m.lastPairResult { - for toNode := range nodePairs { - if fromNode == node || toNode == node { - nodePairs[toNode] = TimedPairResult{ - FailTime: timestamp, - } - } - } - } -} - -// requestSecondChance checks whether the node fromNode can have a second chance -// at providing a channel update for its channel with toNode. -func (m *MissionControl) requestSecondChance(timestamp time.Time, - fromNode, toNode route.Vertex) bool { - - // Look up previous second chance time. - pair := DirectedNodePair{ - From: fromNode, - To: toNode, - } - lastSecondChance, ok := m.lastSecondChance[pair] - - // If the channel hasn't already be given a second chance or its last - // second chance was long ago, we give it another chance. - if !ok || timestamp.Sub(lastSecondChance) > minSecondChanceInterval { - m.lastSecondChance[pair] = timestamp - - log.Debugf("Second chance granted for %v->%v", fromNode, toNode) - - return true - } - - // Otherwise penalize the channel, because we don't allow channel - // updates that are that frequent. This is to prevent nodes from keeping - // us busy by continuously sending new channel updates. - log.Debugf("Second chance denied for %v->%v, remaining interval: %v", - fromNode, toNode, timestamp.Sub(lastSecondChance)) - - return false -} - // GetHistorySnapshot takes a snapshot from the current mission control state // and actual probability estimates. func (m *MissionControl) GetHistorySnapshot() *MissionControlSnapshot { m.Lock() defer m.Unlock() - log.Debugf("Requesting history snapshot from mission control: "+ - "pair_result_count=%v", len(m.lastPairResult)) - - pairs := make([]MissionControlPairSnapshot, 0, len(m.lastPairResult)) - - for fromNode, fromPairs := range m.lastPairResult { - for toNode, result := range fromPairs { - pair := NewDirectedNodePair(fromNode, toNode) - - pairSnapshot := MissionControlPairSnapshot{ - Pair: pair, - TimedPairResult: result, - } - - pairs = append(pairs, pairSnapshot) - } - } - - snapshot := MissionControlSnapshot{ - Pairs: pairs, - } + log.Debugf("Requesting history snapshot from mission control") - return &snapshot + return m.state.getSnapshot() } // GetPairHistorySnapshot returns the stored history for a given node pair. @@ -418,7 +277,7 @@ func (m *MissionControl) GetPairHistorySnapshot( m.Lock() defer m.Unlock() - results, ok := m.lastPairResult[fromNode] + results, ok := m.state.getLastPairResult(fromNode) if !ok { return TimedPairResult{} } @@ -507,7 +366,7 @@ func (m *MissionControl) applyPaymentResult( defer m.Unlock() if i.policyFailure != nil { - if m.requestSecondChance( + if m.state.requestSecondChance( result.timeReply, i.policyFailure.From, i.policyFailure.To, ) { @@ -536,7 +395,7 @@ func (m *MissionControl) applyPaymentResult( log.Debugf("Reporting node failure to Mission Control: "+ "node=%v", *i.nodeFailure) - m.setAllFail(*i.nodeFailure, result.timeReply) + m.state.setAllFail(*i.nodeFailure, result.timeReply) } for pair, pairResult := range i.pairResults { @@ -551,7 +410,7 @@ func (m *MissionControl) applyPaymentResult( pair, pairResult.amt) } - m.setLastPairResult( + m.state.setLastPairResult( pair.From, pair.To, result.timeReply, &pairResult, ) } diff --git a/routing/missioncontrol_state.go b/routing/missioncontrol_state.go new file mode 100644 index 0000000000..9b342f6d2a --- /dev/null +++ b/routing/missioncontrol_state.go @@ -0,0 +1,187 @@ +package routing + +import ( + "time" + + "github.com/lightningnetwork/lnd/routing/route" +) + +// missionControlState is an object that manages the internal mission control +// state. Note that it isn't thread safe and synchronization needs to be +// enforced externally. +type missionControlState struct { + // lastPairResult tracks the last payment result (on a pair basis) for + // each transited node. This is a multi-layer map that allows us to look + // up the failure history of all connected channels (node pairs) for a + // particular node. + lastPairResult map[route.Vertex]NodeResults + + // lastSecondChance tracks the last time a second chance was granted for + // a directed node pair. + lastSecondChance map[DirectedNodePair]time.Time +} + +// newMissionControlState instantiates a new mission control state object. +func newMissionControlState() *missionControlState { + return &missionControlState{ + lastPairResult: make(map[route.Vertex]NodeResults), + lastSecondChance: make(map[DirectedNodePair]time.Time), + } +} + +// getLastPairResult returns the current state for connections to the given node. +func (m *missionControlState) getLastPairResult(node route.Vertex) (NodeResults, + bool) { + + result, ok := m.lastPairResult[node] + return result, ok +} + +// ResetHistory resets the history of MissionControl returning it to a state as +// if no payment attempts have been made. +func (m *missionControlState) resetHistory() { + m.lastPairResult = make(map[route.Vertex]NodeResults) + m.lastSecondChance = make(map[DirectedNodePair]time.Time) +} + +// setLastPairResult stores a result for a node pair. +func (m *missionControlState) setLastPairResult(fromNode, toNode route.Vertex, + timestamp time.Time, result *pairResult) { + + nodePairs, ok := m.lastPairResult[fromNode] + if !ok { + nodePairs = make(NodeResults) + m.lastPairResult[fromNode] = nodePairs + } + + current := nodePairs[toNode] + + // Apply the new result to the existing data for this pair. If there is + // no existing data, apply it to the default values for TimedPairResult. + if result.success { + successAmt := result.amt + current.SuccessTime = timestamp + + // Only update the success amount if this amount is higher. This + // prevents the success range from shrinking when there is no + // reason to do so. For example: small amount probes shouldn't + // affect a previous success for a much larger amount. + if successAmt > current.SuccessAmt { + current.SuccessAmt = successAmt + } + + // If the success amount goes into the failure range, move the + // failure range up. Future attempts up to the success amount + // are likely to succeed. We don't want to clear the failure + // completely, because we haven't learnt much for amounts above + // the current success amount. + if !current.FailTime.IsZero() && successAmt >= current.FailAmt { + current.FailAmt = successAmt + 1 + } + } else { + // For failures we always want to update both the amount and the + // time. Those need to relate to the same result, because the + // time is used to gradually diminish the penality for that + // specific result. Updating the timestamp but not the amount + // could cause a failure for a lower amount (a more severe + // condition) to be revived as if it just happened. + failAmt := result.amt + + current.FailTime = timestamp + current.FailAmt = failAmt + + switch { + // The failure amount is set to zero when the failure is + // amount-independent, meaning that the attempt would have + // failed regardless of the amount. This should also reset the + // success amount to zero. + case failAmt == 0: + current.SuccessAmt = 0 + + // If the failure range goes into the success range, move the + // success range down. + case failAmt <= current.SuccessAmt: + current.SuccessAmt = failAmt - 1 + } + } + + log.Debugf("Setting %v->%v range to [%v-%v]", + fromNode, toNode, current.SuccessAmt, current.FailAmt) + + nodePairs[toNode] = current +} + +// setAllFail stores a fail result for all known connections to and from the +// given node. +func (m *missionControlState) setAllFail(node route.Vertex, + timestamp time.Time) { + + for fromNode, nodePairs := range m.lastPairResult { + for toNode := range nodePairs { + if fromNode == node || toNode == node { + nodePairs[toNode] = TimedPairResult{ + FailTime: timestamp, + } + } + } + } +} + +// requestSecondChance checks whether the node fromNode can have a second chance +// at providing a channel update for its channel with toNode. +func (m *missionControlState) requestSecondChance(timestamp time.Time, + fromNode, toNode route.Vertex) bool { + + // Look up previous second chance time. + pair := DirectedNodePair{ + From: fromNode, + To: toNode, + } + lastSecondChance, ok := m.lastSecondChance[pair] + + // If the channel hasn't already be given a second chance or its last + // second chance was long ago, we give it another chance. + if !ok || timestamp.Sub(lastSecondChance) > minSecondChanceInterval { + m.lastSecondChance[pair] = timestamp + + log.Debugf("Second chance granted for %v->%v", fromNode, toNode) + + return true + } + + // Otherwise penalize the channel, because we don't allow channel + // updates that are that frequent. This is to prevent nodes from keeping + // us busy by continuously sending new channel updates. + log.Debugf("Second chance denied for %v->%v, remaining interval: %v", + fromNode, toNode, timestamp.Sub(lastSecondChance)) + + return false +} + +// GetHistorySnapshot takes a snapshot from the current mission control state +// and actual probability estimates. +func (m *missionControlState) getSnapshot() *MissionControlSnapshot { + log.Debugf("Requesting history snapshot from mission control: "+ + "pair_result_count=%v", len(m.lastPairResult)) + + pairs := make([]MissionControlPairSnapshot, 0, len(m.lastPairResult)) + + for fromNode, fromPairs := range m.lastPairResult { + for toNode, result := range fromPairs { + pair := NewDirectedNodePair(fromNode, toNode) + + pairSnapshot := MissionControlPairSnapshot{ + Pair: pair, + TimedPairResult: result, + } + + pairs = append(pairs, pairSnapshot) + } + } + + snapshot := MissionControlSnapshot{ + Pairs: pairs, + } + + return &snapshot +} From 2d0775626369f211517e46fe3c72317cc92aba84 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 17 Mar 2020 13:22:32 +0100 Subject: [PATCH 295/562] routing: log amount for probability --- routing/pathfind.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/routing/pathfind.go b/routing/pathfind.go index d9125cc4c8..549d341667 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -584,7 +584,8 @@ func findPathInternal( log.Trace(newLogClosure(func() string { return fmt.Sprintf("path finding probability: fromnode=%v,"+ - " tonode=%v, probability=%v", fromVertex, toNodeDist.node, + " tonode=%v, amt=%v, probability=%v", + fromVertex, toNodeDist.node, amountToSend, edgeProbability) })) From 36e1b92e0c5bcb84937ec0b09558e267d02a611a Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 18 Mar 2020 13:06:05 +0100 Subject: [PATCH 296/562] routing: log reported success amount --- routing/missioncontrol.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/routing/missioncontrol.go b/routing/missioncontrol.go index a590f20ae3..f140634f5b 100644 --- a/routing/missioncontrol.go +++ b/routing/missioncontrol.go @@ -544,7 +544,8 @@ func (m *MissionControl) applyPaymentResult( if pairResult.success { log.Debugf("Reporting pair success to Mission "+ - "Control: pair=%v", pair) + "Control: pair=%v, amt=%v", + pair, pairResult.amt) } else { log.Debugf("Reporting pair failure to Mission "+ "Control: pair=%v, amt=%v", From fd6b397496caef105367b8f3740a3623894bce20 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 25 Mar 2020 08:40:44 +0200 Subject: [PATCH 297/562] lnrpc: add initiator bool to PendingChannel message --- lnrpc/rpc.pb.go | 1438 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 3 + lnrpc/rpc.swagger.json | 5 + rpcserver.go | 25 + 4 files changed, 757 insertions(+), 714 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index fcc66a4d41..af20fab4d1 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -5552,7 +5552,9 @@ type PendingChannelsResponse_PendingChannel struct { //* //The minimum satoshis the other node is required to reserve in its //balance. - RemoteChanReserveSat int64 `protobuf:"varint,7,opt,name=remote_chan_reserve_sat,json=remoteChanReserveSat,proto3" json:"remote_chan_reserve_sat,omitempty"` + RemoteChanReserveSat int64 `protobuf:"varint,7,opt,name=remote_chan_reserve_sat,json=remoteChanReserveSat,proto3" json:"remote_chan_reserve_sat,omitempty"` + // True if we initiated opening the channel. + Initiator bool `protobuf:"varint,8,opt,name=initiator,proto3" json:"initiator,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5634,6 +5636,13 @@ func (m *PendingChannelsResponse_PendingChannel) GetRemoteChanReserveSat() int64 return 0 } +func (m *PendingChannelsResponse_PendingChannel) GetInitiator() bool { + if m != nil { + return m.Initiator + } + return false +} + type PendingChannelsResponse_PendingOpenChannel struct { /// The pending channel Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` @@ -11366,719 +11375,720 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11387 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x8f, 0x24, 0xd7, - 0x75, 0x18, 0xbe, 0xfd, 0x9a, 0xee, 0x3e, 0xfd, 0x9c, 0x3b, 0xaf, 0xde, 0x59, 0x2e, 0x77, 0x59, - 0xa4, 0xc8, 0xd5, 0x52, 0x9a, 0x5d, 0xae, 0x44, 0x4a, 0x26, 0x7f, 0x96, 0xd5, 0x33, 0xd3, 0xb3, - 0xd3, 0xda, 0x79, 0xb1, 0xba, 0x87, 0x34, 0xe5, 0x9f, 0x53, 0xaa, 0xe9, 0xbe, 0x33, 0x53, 0xde, - 0xee, 0xaa, 0x66, 0x55, 0xf5, 0x3c, 0x24, 0x30, 0x1f, 0x82, 0xc4, 0x08, 0x82, 0x24, 0x80, 0x91, - 0x38, 0x40, 0x9c, 0x18, 0x09, 0x12, 0x04, 0x41, 0x10, 0xc0, 0x70, 0x20, 0x07, 0x48, 0x80, 0x7c, - 0xf7, 0x97, 0x04, 0x41, 0x60, 0xe7, 0x4b, 0x60, 0x18, 0x70, 0x1e, 0xca, 0xb7, 0xc0, 0x7f, 0x42, - 0x70, 0xcf, 0xb9, 0xb7, 0xea, 0x56, 0x77, 0xcd, 0xee, 0x52, 0x62, 0xf4, 0x65, 0xa6, 0xeb, 0xdc, - 0x73, 0x9f, 0x75, 0xee, 0xb9, 0xe7, 0x79, 0x0b, 0xca, 0xfe, 0x64, 0xb0, 0x31, 0xf1, 0xbd, 0xd0, - 0x63, 0x85, 0x91, 0xeb, 0x4f, 0x06, 0xeb, 0xaf, 0x9d, 0x79, 0xde, 0xd9, 0x88, 0x3f, 0xb2, 0x27, - 0xce, 0x23, 0xdb, 0x75, 0xbd, 0xd0, 0x0e, 0x1d, 0xcf, 0x0d, 0x08, 0xc9, 0xf8, 0x11, 0xd4, 0x9f, - 0x72, 0xb7, 0xc7, 0xf9, 0xd0, 0xe4, 0x9f, 0x4f, 0x79, 0x10, 0xb2, 0x77, 0x61, 0xd1, 0xe6, 0x3f, - 0xe6, 0x7c, 0x68, 0x4d, 0xec, 0x20, 0x98, 0x9c, 0xfb, 0x76, 0xc0, 0x5b, 0x99, 0xfb, 0x99, 0x07, - 0x55, 0xb3, 0x49, 0x05, 0x47, 0x11, 0x9c, 0xbd, 0x01, 0xd5, 0x40, 0xa0, 0x72, 0x37, 0xf4, 0xbd, - 0xc9, 0x75, 0x2b, 0x8b, 0x78, 0x15, 0x01, 0xeb, 0x10, 0xc8, 0x18, 0x41, 0x23, 0xea, 0x21, 0x98, - 0x78, 0x6e, 0xc0, 0xd9, 0x63, 0x58, 0x1e, 0x38, 0x93, 0x73, 0xee, 0x5b, 0x58, 0x79, 0xec, 0xf2, - 0xb1, 0xe7, 0x3a, 0x83, 0x56, 0xe6, 0x7e, 0xee, 0x41, 0xd9, 0x64, 0x54, 0x26, 0x6a, 0xec, 0xcb, - 0x12, 0xf6, 0x0e, 0x34, 0xb8, 0x4b, 0x70, 0x3e, 0xc4, 0x5a, 0xb2, 0xab, 0x7a, 0x0c, 0x16, 0x15, - 0x8c, 0xbf, 0x99, 0x85, 0xc5, 0xae, 0xeb, 0x84, 0x9f, 0xda, 0xa3, 0x11, 0x0f, 0xd5, 0x9c, 0xde, - 0x81, 0xc6, 0x25, 0x02, 0x70, 0x4e, 0x97, 0x9e, 0x3f, 0x94, 0x33, 0xaa, 0x13, 0xf8, 0x48, 0x42, - 0x6f, 0x1c, 0x59, 0xf6, 0xc6, 0x91, 0xa5, 0x2e, 0x57, 0xee, 0x86, 0xe5, 0x7a, 0x07, 0x1a, 0x3e, - 0x1f, 0x78, 0x17, 0xdc, 0xbf, 0xb6, 0x2e, 0x1d, 0x77, 0xe8, 0x5d, 0xb6, 0xf2, 0xf7, 0x33, 0x0f, - 0x0a, 0x66, 0x5d, 0x81, 0x3f, 0x45, 0x28, 0xdb, 0x84, 0xc6, 0xe0, 0xdc, 0x76, 0x5d, 0x3e, 0xb2, - 0x4e, 0xec, 0xc1, 0xf3, 0xe9, 0x24, 0x68, 0x15, 0xee, 0x67, 0x1e, 0x54, 0x9e, 0xdc, 0xde, 0xc0, - 0xb7, 0xba, 0xb1, 0x75, 0x6e, 0xbb, 0x9b, 0x58, 0xd2, 0x73, 0xed, 0x49, 0x70, 0xee, 0x85, 0x66, - 0x5d, 0xd6, 0x20, 0x70, 0x60, 0x2c, 0x03, 0xd3, 0x57, 0x82, 0xd6, 0xde, 0xf8, 0xd7, 0x19, 0x58, - 0x3a, 0x76, 0x47, 0xde, 0xe0, 0xf9, 0xcf, 0xb9, 0x44, 0x29, 0x73, 0xc8, 0xbe, 0xea, 0x1c, 0x72, - 0x5f, 0x76, 0x0e, 0xab, 0xb0, 0x9c, 0x1c, 0xac, 0x9c, 0x05, 0x87, 0x15, 0x51, 0xfb, 0x8c, 0xab, - 0x61, 0xa9, 0x69, 0x7c, 0x1d, 0x9a, 0x83, 0xa9, 0xef, 0x73, 0x77, 0x6e, 0x1e, 0x0d, 0x09, 0x8f, - 0x26, 0xf2, 0x06, 0x54, 0x5d, 0x7e, 0x19, 0xa3, 0x49, 0xda, 0x75, 0xf9, 0xa5, 0x42, 0x31, 0x5a, - 0xb0, 0x3a, 0xdb, 0x8d, 0x1c, 0xc0, 0xcf, 0x32, 0x90, 0x3f, 0x0e, 0xaf, 0x3c, 0xf6, 0x3e, 0x54, - 0xed, 0xe1, 0xd0, 0xe7, 0x41, 0x60, 0x85, 0xd7, 0x13, 0xda, 0x29, 0xf5, 0x27, 0x4c, 0x4e, 0xb1, - 0x4d, 0x45, 0xfd, 0xeb, 0x09, 0x37, 0x2b, 0x76, 0xfc, 0xc0, 0x5a, 0x50, 0x94, 0x8f, 0xd8, 0x6f, - 0xd9, 0x54, 0x8f, 0xec, 0x2e, 0x80, 0x3d, 0xf6, 0xa6, 0x6e, 0x68, 0x05, 0x76, 0x88, 0x2b, 0x96, - 0x33, 0xcb, 0x04, 0xe9, 0xd9, 0x21, 0xbb, 0x03, 0xe5, 0xc9, 0x73, 0x2b, 0x18, 0xf8, 0xce, 0x24, - 0x44, 0xe2, 0x29, 0x9b, 0xa5, 0xc9, 0xf3, 0x1e, 0x3e, 0xb3, 0x77, 0xa1, 0xe4, 0x4d, 0xc3, 0x89, - 0xe7, 0xb8, 0xa1, 0xa4, 0x97, 0x86, 0x1c, 0xc8, 0xe1, 0x34, 0x3c, 0x12, 0x60, 0x33, 0x42, 0x60, - 0x6f, 0x41, 0x6d, 0xe0, 0xb9, 0xa7, 0x8e, 0x3f, 0x26, 0x8e, 0xd0, 0x5a, 0xc0, 0xbe, 0x92, 0x40, - 0xe3, 0x0f, 0xb3, 0x50, 0xe9, 0xfb, 0xb6, 0x1b, 0xd8, 0x03, 0x01, 0x60, 0x6b, 0x50, 0x0c, 0xaf, - 0xac, 0x73, 0x3b, 0x38, 0xc7, 0xa9, 0x96, 0xcd, 0x85, 0xf0, 0x6a, 0xd7, 0x0e, 0xce, 0xd9, 0x2a, - 0x2c, 0xd0, 0x28, 0x71, 0x42, 0x39, 0x53, 0x3e, 0x89, 0x0d, 0xe2, 0x4e, 0xc7, 0x56, 0xb2, 0xab, - 0x1c, 0x52, 0x4c, 0xd3, 0x9d, 0x8e, 0xb7, 0x74, 0xb8, 0x98, 0xfc, 0x89, 0x78, 0xdd, 0xd4, 0x01, - 0x4d, 0xaf, 0x8c, 0x10, 0xec, 0xe3, 0x0d, 0xa8, 0xca, 0x62, 0xee, 0x9c, 0x9d, 0xd3, 0x1c, 0x0b, - 0x66, 0x85, 0x10, 0x10, 0x24, 0x5a, 0x08, 0x9d, 0x31, 0xb7, 0x82, 0xd0, 0x1e, 0x4f, 0xe4, 0x94, - 0xca, 0x02, 0xd2, 0x13, 0x00, 0x2c, 0xf6, 0x42, 0x7b, 0x64, 0x9d, 0x72, 0x1e, 0xb4, 0x8a, 0xb2, - 0x58, 0x40, 0x76, 0x38, 0x0f, 0xd8, 0xd7, 0xa0, 0x3e, 0xe4, 0x41, 0x68, 0xc9, 0x97, 0xc1, 0x83, - 0x56, 0x09, 0x77, 0x7e, 0x4d, 0x40, 0xdb, 0x0a, 0xc8, 0x5e, 0x03, 0xf0, 0xed, 0x4b, 0x4b, 0x2c, - 0x04, 0xbf, 0x6a, 0x95, 0xe9, 0x2d, 0xf8, 0xf6, 0x65, 0xff, 0x6a, 0x97, 0x5f, 0x09, 0xaa, 0x79, - 0xca, 0x43, 0x6d, 0xd1, 0x02, 0x49, 0x9d, 0xc6, 0x1e, 0x30, 0x0d, 0xbc, 0xcd, 0x43, 0xdb, 0x19, - 0x05, 0xec, 0x03, 0xa8, 0x86, 0x1a, 0x32, 0xb2, 0xc1, 0x4a, 0x44, 0x42, 0x5a, 0x05, 0x33, 0x81, - 0x67, 0x9c, 0x43, 0x69, 0x87, 0xf3, 0x3d, 0x67, 0xec, 0x84, 0x6c, 0x15, 0x0a, 0xa7, 0xce, 0x15, - 0x27, 0x62, 0xcf, 0xed, 0xde, 0x32, 0xe9, 0x91, 0xdd, 0x03, 0xc0, 0x1f, 0xd6, 0x38, 0xa2, 0xa6, - 0xdd, 0x5b, 0x66, 0x19, 0x61, 0xfb, 0x81, 0x1d, 0xb2, 0x75, 0x28, 0x4e, 0xb8, 0x3f, 0xe0, 0xea, - 0xbd, 0xed, 0xde, 0x32, 0x15, 0x60, 0xb3, 0x08, 0x85, 0x91, 0x68, 0xdd, 0xf8, 0xe3, 0x02, 0x54, - 0x7a, 0xdc, 0x8d, 0x76, 0x19, 0x83, 0xbc, 0x58, 0x10, 0xb9, 0xb3, 0xf0, 0x37, 0x7b, 0x13, 0x2a, - 0xb8, 0x74, 0x41, 0xe8, 0x3b, 0xee, 0x19, 0x51, 0xf5, 0x66, 0xb6, 0x95, 0x31, 0x41, 0x80, 0x7b, - 0x08, 0x65, 0x4d, 0xc8, 0xd9, 0x63, 0x45, 0xd5, 0xe2, 0x27, 0xbb, 0x0d, 0x25, 0x7b, 0x1c, 0xd2, - 0xf0, 0xaa, 0x08, 0x2e, 0xda, 0xe3, 0x10, 0x87, 0xf6, 0x06, 0x54, 0x27, 0xf6, 0xf5, 0x58, 0xec, - 0xe5, 0x88, 0x1c, 0xaa, 0x66, 0x45, 0xc2, 0x90, 0x20, 0x9e, 0xc0, 0x92, 0x8e, 0xa2, 0x3a, 0x2f, - 0x44, 0x9d, 0x2f, 0x6a, 0xd8, 0x72, 0x0c, 0xef, 0x40, 0x43, 0xd5, 0xf1, 0x69, 0x3e, 0x48, 0x26, - 0x65, 0xb3, 0x2e, 0xc1, 0x6a, 0x96, 0x0f, 0xa0, 0x79, 0xea, 0xb8, 0xf6, 0xc8, 0x1a, 0x8c, 0xc2, - 0x0b, 0x6b, 0xc8, 0x47, 0xa1, 0x8d, 0x14, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1a, 0x85, 0x17, 0xdb, - 0x02, 0xca, 0xbe, 0x01, 0xe5, 0x53, 0xce, 0x2d, 0x5c, 0xac, 0x56, 0x29, 0xb1, 0xf1, 0xd4, 0x1b, - 0x32, 0x4b, 0xa7, 0xea, 0x5d, 0x7d, 0x03, 0x9a, 0xde, 0x34, 0x3c, 0xf3, 0x1c, 0xf7, 0xcc, 0x12, - 0xfc, 0xce, 0x72, 0x86, 0x48, 0x43, 0xf9, 0xcd, 0xec, 0xe3, 0x8c, 0x59, 0x57, 0x65, 0x82, 0xf3, - 0x74, 0x87, 0xec, 0x6d, 0x68, 0x8c, 0xec, 0x20, 0xb4, 0xce, 0xbd, 0x89, 0x35, 0x99, 0x9e, 0x3c, - 0xe7, 0xd7, 0xad, 0x1a, 0x2e, 0x44, 0x4d, 0x80, 0x77, 0xbd, 0xc9, 0x11, 0x02, 0x05, 0x65, 0xe3, - 0x38, 0x69, 0x10, 0x70, 0x3f, 0xf3, 0xa0, 0x66, 0x96, 0x05, 0x84, 0x3a, 0xfd, 0x0c, 0x96, 0xf0, - 0xf5, 0x0c, 0xa6, 0x41, 0xe8, 0x8d, 0x2d, 0xc1, 0xab, 0xfd, 0x61, 0xd0, 0xaa, 0x20, 0xad, 0x7d, - 0x5d, 0x0e, 0x56, 0x7b, 0xc7, 0x1b, 0xdb, 0x3c, 0x08, 0xb7, 0x10, 0xd9, 0x24, 0x5c, 0x71, 0xa0, - 0x5f, 0x9b, 0x8b, 0xc3, 0x59, 0x38, 0xfb, 0x06, 0x30, 0x7b, 0x34, 0xf2, 0x2e, 0xad, 0x80, 0x8f, - 0x4e, 0x2d, 0xb9, 0x88, 0xad, 0xfa, 0xfd, 0xcc, 0x83, 0x92, 0xd9, 0xc4, 0x92, 0x1e, 0x1f, 0x9d, - 0x1e, 0x11, 0x9c, 0x7d, 0x00, 0xb8, 0x99, 0xac, 0x53, 0x6e, 0x87, 0x53, 0x9f, 0x07, 0xad, 0xc6, - 0xfd, 0xdc, 0x83, 0xfa, 0x93, 0xc5, 0x68, 0xbd, 0x10, 0xbc, 0xe9, 0x84, 0x66, 0x55, 0xe0, 0xc9, - 0xe7, 0x60, 0x7d, 0x1b, 0x56, 0xd3, 0x87, 0x24, 0x88, 0x4a, 0xac, 0x8a, 0x20, 0xc6, 0xbc, 0x29, - 0x7e, 0xb2, 0x65, 0x28, 0x5c, 0xd8, 0xa3, 0x29, 0x97, 0x3c, 0x9d, 0x1e, 0x3e, 0xcc, 0x7e, 0x37, - 0x63, 0xfc, 0x51, 0x06, 0xaa, 0x34, 0x4b, 0x29, 0x8b, 0xbc, 0x09, 0x35, 0x45, 0x0d, 0xdc, 0xf7, - 0x3d, 0x5f, 0x72, 0x35, 0x45, 0x79, 0x1d, 0x01, 0x13, 0xa7, 0x8a, 0x42, 0x9a, 0xf8, 0xdc, 0x19, - 0xdb, 0x67, 0xaa, 0x69, 0x45, 0x4a, 0x47, 0x12, 0xcc, 0xde, 0x8b, 0xdb, 0xf3, 0xbd, 0x69, 0xc8, - 0xe5, 0x99, 0x57, 0x95, 0xd3, 0x33, 0x05, 0x2c, 0x6a, 0x1d, 0x9f, 0x5e, 0x81, 0xce, 0x8d, 0xdf, - 0xcd, 0x00, 0x13, 0xc3, 0xee, 0x7b, 0xd4, 0x80, 0xa4, 0xd0, 0xd9, 0x9a, 0x99, 0x57, 0xde, 0x21, - 0xd9, 0x17, 0xed, 0x10, 0x03, 0x0a, 0x34, 0xf6, 0x7c, 0xca, 0xd8, 0xa9, 0xe8, 0x07, 0xf9, 0x52, - 0xae, 0x99, 0x37, 0xfe, 0x5b, 0x0e, 0x96, 0xb7, 0xe8, 0xc8, 0x6e, 0x0f, 0x06, 0x7c, 0x12, 0xed, - 0x9d, 0x7b, 0x50, 0x71, 0xbd, 0x21, 0x57, 0x14, 0x4b, 0x03, 0x03, 0x01, 0xd2, 0xc8, 0xf5, 0xdc, - 0x76, 0x5c, 0x1a, 0x38, 0x2d, 0x66, 0x19, 0x21, 0x38, 0xec, 0xb7, 0xa1, 0x31, 0xe1, 0xee, 0x50, - 0xdf, 0x22, 0x24, 0x54, 0xd5, 0x24, 0x58, 0xee, 0x8e, 0x7b, 0x50, 0x39, 0x9d, 0x12, 0x9e, 0x60, - 0x2c, 0x79, 0xa4, 0x01, 0x90, 0xa0, 0x36, 0xf1, 0x97, 0xc9, 0x34, 0x38, 0xc7, 0xd2, 0x02, 0x96, - 0x16, 0xc5, 0xb3, 0x28, 0xba, 0x0b, 0x30, 0x9c, 0x06, 0xa1, 0xdc, 0x31, 0x0b, 0x58, 0x58, 0x16, - 0x10, 0xda, 0x31, 0xdf, 0x84, 0xa5, 0xb1, 0x7d, 0x65, 0x21, 0xed, 0x58, 0x8e, 0x6b, 0x9d, 0x8e, - 0xf0, 0xcc, 0x29, 0x22, 0x5e, 0x73, 0x6c, 0x5f, 0x7d, 0x22, 0x4a, 0xba, 0xee, 0x0e, 0xc2, 0x05, - 0x5b, 0x51, 0xe2, 0x8e, 0xcf, 0x03, 0xee, 0x5f, 0x70, 0xe4, 0x04, 0xf9, 0x48, 0xa6, 0x31, 0x09, - 0x2a, 0x46, 0x34, 0x16, 0xf3, 0x0e, 0x47, 0x03, 0xda, 0xf6, 0x66, 0x71, 0xec, 0xb8, 0xbb, 0xe1, - 0x68, 0x20, 0xce, 0x15, 0xc1, 0x47, 0x26, 0xdc, 0xb7, 0x9e, 0x5f, 0xe2, 0x1e, 0xce, 0x23, 0xdf, - 0x38, 0xe2, 0xfe, 0xb3, 0x4b, 0x71, 0xf4, 0x0f, 0x02, 0x64, 0x44, 0xf6, 0x75, 0xab, 0x82, 0x1b, - 0xbc, 0x34, 0x08, 0x04, 0x0b, 0xb2, 0xaf, 0xc5, 0x26, 0x14, 0xa3, 0xb5, 0xf1, 0x2d, 0xf0, 0x21, - 0x36, 0x1f, 0x20, 0x47, 0xad, 0xe1, 0x60, 0xdb, 0xb2, 0x40, 0xf4, 0x13, 0x08, 0xaa, 0x57, 0x83, - 0x3d, 0x1d, 0xd9, 0x67, 0x01, 0xb2, 0x94, 0x9a, 0x59, 0x95, 0xc0, 0x1d, 0x01, 0x33, 0x3e, 0x25, - 0x21, 0x4b, 0x7b, 0xb7, 0x72, 0xcf, 0x88, 0xa3, 0x1e, 0x21, 0xf8, 0x5e, 0x4b, 0xa6, 0x7c, 0x4a, - 0x7b, 0x69, 0xd9, 0x94, 0x97, 0x66, 0xfc, 0x7e, 0x06, 0xaa, 0xb2, 0x65, 0x14, 0x4a, 0xd8, 0x06, - 0x30, 0xf5, 0x16, 0xc3, 0x2b, 0x67, 0x68, 0x9d, 0x5c, 0x87, 0x3c, 0x20, 0xa2, 0xd9, 0xbd, 0x65, - 0x36, 0x65, 0x59, 0xff, 0xca, 0x19, 0x6e, 0x8a, 0x12, 0xf6, 0x10, 0x9a, 0x09, 0xfc, 0x20, 0xf4, - 0x89, 0xa2, 0x77, 0x6f, 0x99, 0x75, 0x0d, 0xbb, 0x17, 0xfa, 0x62, 0x8f, 0x08, 0x91, 0x67, 0x1a, - 0x5a, 0x8e, 0x3b, 0xe4, 0x57, 0x48, 0x46, 0x35, 0xb3, 0x42, 0xb0, 0xae, 0x00, 0x6d, 0xd6, 0xa1, - 0xaa, 0x37, 0x67, 0x9c, 0x41, 0x49, 0xc9, 0x4b, 0x28, 0x30, 0xcc, 0x0c, 0xc9, 0x2c, 0x87, 0xd1, - 0x48, 0x6e, 0x43, 0x29, 0x39, 0x02, 0xb3, 0x18, 0xbe, 0x72, 0xc7, 0xc6, 0xf7, 0xa0, 0xb9, 0x27, - 0x88, 0xc7, 0x15, 0xc4, 0x2a, 0xe5, 0xbf, 0x55, 0x58, 0xd0, 0x36, 0x4d, 0xd9, 0x94, 0x4f, 0xe2, - 0xcc, 0x3d, 0xf7, 0x82, 0x50, 0xf6, 0x82, 0xbf, 0x8d, 0x3f, 0xce, 0x00, 0xeb, 0x04, 0xa1, 0x33, - 0xb6, 0x43, 0xbe, 0xc3, 0x23, 0xb6, 0x70, 0x08, 0x55, 0xd1, 0x5a, 0xdf, 0x6b, 0x93, 0x40, 0x46, - 0x02, 0xc5, 0xbb, 0x72, 0x1b, 0xcf, 0x57, 0xd8, 0xd0, 0xb1, 0x89, 0xcd, 0x27, 0x1a, 0x10, 0xbb, - 0x2c, 0xb4, 0xfd, 0x33, 0x1e, 0xa2, 0x18, 0x27, 0xe5, 0x7d, 0x20, 0x90, 0x10, 0xe0, 0xd6, 0x7f, - 0x0d, 0x16, 0xe7, 0xda, 0xd0, 0xf9, 0x72, 0x39, 0x85, 0x2f, 0xe7, 0x74, 0xbe, 0x6c, 0xc1, 0x52, - 0x62, 0x5c, 0x92, 0xd2, 0xd6, 0xa0, 0x28, 0x36, 0x84, 0x10, 0x0e, 0x32, 0x24, 0x55, 0x9e, 0x72, - 0x2e, 0xc4, 0xe0, 0x47, 0xb0, 0x7c, 0xca, 0xb9, 0x6f, 0x87, 0x58, 0x88, 0x3b, 0x46, 0xbc, 0x21, - 0xd9, 0xf0, 0xa2, 0x2c, 0xeb, 0xd9, 0xe1, 0x11, 0xf7, 0xc5, 0x9b, 0x32, 0xfe, 0x47, 0x06, 0x1a, - 0x82, 0x83, 0xee, 0xdb, 0xee, 0xb5, 0x5a, 0xa7, 0xbd, 0xd4, 0x75, 0x7a, 0xa0, 0x1d, 0x86, 0x1a, - 0xf6, 0x97, 0x5d, 0xa4, 0xdc, 0xec, 0x22, 0xb1, 0xfb, 0x50, 0x4d, 0x8c, 0xb5, 0x80, 0x63, 0x85, - 0x20, 0x1a, 0xe4, 0x2f, 0xbe, 0x8c, 0x6f, 0x43, 0x33, 0x1e, 0xb6, 0x5c, 0x43, 0x06, 0x79, 0x41, - 0x92, 0xb2, 0x01, 0xfc, 0x6d, 0xfc, 0xe3, 0x0c, 0x21, 0x6e, 0x79, 0x4e, 0x24, 0x9d, 0x0a, 0x44, - 0x21, 0xf7, 0x2a, 0x44, 0xf1, 0xfb, 0x46, 0xa9, 0xfe, 0x17, 0x9f, 0xac, 0xd8, 0x3a, 0x01, 0x77, - 0x87, 0x96, 0x3d, 0x1a, 0x21, 0xf3, 0x2d, 0x99, 0x45, 0xf1, 0xdc, 0x1e, 0x8d, 0x8c, 0x77, 0x60, - 0x51, 0x1b, 0xdd, 0x0b, 0xe6, 0x71, 0x00, 0x6c, 0xcf, 0x09, 0xc2, 0x63, 0x37, 0x98, 0x68, 0x82, - 0xdb, 0x1d, 0x28, 0x0b, 0x0e, 0x2b, 0x46, 0x46, 0x5b, 0xb6, 0x60, 0x0a, 0x96, 0x2b, 0xc6, 0x15, - 0x60, 0xa1, 0x7d, 0x25, 0x0b, 0xb3, 0xb2, 0xd0, 0xbe, 0xc2, 0x42, 0xe3, 0xbb, 0xb0, 0x94, 0x68, - 0x4f, 0x76, 0xfd, 0x06, 0x14, 0xa6, 0xe1, 0x95, 0xa7, 0x44, 0xf3, 0x8a, 0xa4, 0x10, 0xa1, 0x00, - 0x9a, 0x54, 0x62, 0x7c, 0x04, 0x8b, 0x07, 0xfc, 0x52, 0x6e, 0x62, 0x35, 0x90, 0xb7, 0x21, 0xff, - 0x12, 0xa5, 0x10, 0xcb, 0x8d, 0x0d, 0x60, 0x7a, 0x65, 0xd9, 0xab, 0xa6, 0x23, 0x66, 0x12, 0x3a, - 0xa2, 0xf1, 0x36, 0xb0, 0x9e, 0x73, 0xe6, 0xee, 0xf3, 0x20, 0xb0, 0xcf, 0xa2, 0x6d, 0xdf, 0x84, - 0xdc, 0x38, 0x38, 0x93, 0x3c, 0x4a, 0xfc, 0x34, 0xbe, 0x05, 0x4b, 0x09, 0x3c, 0xd9, 0xf0, 0x6b, - 0x50, 0x0e, 0x9c, 0x33, 0x17, 0x05, 0x2b, 0xd9, 0x74, 0x0c, 0x30, 0x76, 0x60, 0xf9, 0x13, 0xee, - 0x3b, 0xa7, 0xd7, 0x2f, 0x6b, 0x3e, 0xd9, 0x4e, 0x76, 0xb6, 0x9d, 0x0e, 0xac, 0xcc, 0xb4, 0x23, - 0xbb, 0x27, 0xf2, 0x95, 0x6f, 0xb2, 0x64, 0xd2, 0x83, 0xc6, 0xf7, 0xb2, 0x3a, 0xdf, 0x33, 0x8e, - 0x81, 0x6d, 0x79, 0xae, 0xcb, 0x07, 0xe1, 0x11, 0xe7, 0x7e, 0x6c, 0xa5, 0x8a, 0x69, 0xb5, 0xf2, - 0x64, 0x4d, 0xae, 0xec, 0x2c, 0x33, 0x95, 0x44, 0xcc, 0x20, 0x3f, 0xe1, 0xfe, 0x18, 0x1b, 0x2e, - 0x99, 0xf8, 0xdb, 0x58, 0x81, 0xa5, 0x44, 0xb3, 0x52, 0xaf, 0x7f, 0x0c, 0x2b, 0xdb, 0x4e, 0x30, - 0x98, 0xef, 0x70, 0x0d, 0x8a, 0x93, 0xe9, 0x89, 0x95, 0xe4, 0xcb, 0xcf, 0xf8, 0xb5, 0xd0, 0xf6, - 0x66, 0x6b, 0xc8, 0xb6, 0xfe, 0x7a, 0x06, 0xf2, 0xbb, 0xfd, 0xbd, 0x2d, 0xb6, 0x0e, 0x25, 0xc7, - 0x1d, 0x78, 0x63, 0x21, 0x78, 0xd1, 0x9c, 0xa3, 0xe7, 0x1b, 0x37, 0xd8, 0x1d, 0x28, 0xa3, 0xbc, - 0x26, 0x54, 0x5b, 0x29, 0xfa, 0x94, 0x04, 0x60, 0xcf, 0x1b, 0x3c, 0x17, 0x3a, 0x35, 0xbf, 0x9a, - 0x38, 0x3e, 0x6a, 0xcd, 0x4a, 0x19, 0xce, 0xd3, 0x59, 0x1f, 0x17, 0x90, 0x46, 0x6c, 0xfc, 0xfb, - 0x12, 0x14, 0xe5, 0x69, 0x4b, 0x27, 0x77, 0xe8, 0x5c, 0xf0, 0xf8, 0xe4, 0x16, 0x4f, 0x42, 0x1e, - 0xf0, 0xf9, 0xd8, 0x0b, 0x23, 0x81, 0x8d, 0xde, 0x41, 0x95, 0x80, 0x52, 0x64, 0xd3, 0x84, 0x06, - 0x32, 0x31, 0xe4, 0x08, 0x69, 0xa0, 0x1f, 0xe5, 0x77, 0xa0, 0xa8, 0xce, 0xfe, 0x7c, 0xa4, 0xd3, - 0x2c, 0x0c, 0x48, 0x5a, 0x5b, 0x87, 0xd2, 0xc0, 0x9e, 0xd8, 0x03, 0x27, 0xbc, 0x96, 0x0c, 0x21, - 0x7a, 0x16, 0xad, 0x8f, 0xbc, 0x81, 0x3d, 0xb2, 0x4e, 0xec, 0x91, 0xed, 0x0e, 0xb8, 0xd4, 0xdd, - 0xab, 0x08, 0xdc, 0x24, 0x98, 0xd0, 0xcf, 0xe5, 0x38, 0x15, 0x16, 0xa9, 0xf0, 0x72, 0xf4, 0x0a, - 0x4d, 0x08, 0x97, 0xde, 0x78, 0xec, 0x08, 0x2d, 0x83, 0xc4, 0xb0, 0x9c, 0x59, 0x26, 0xc8, 0x0e, - 0xc7, 0xd9, 0xca, 0xe2, 0x4b, 0x5a, 0xba, 0x32, 0x75, 0x45, 0xc0, 0x4f, 0xc9, 0x90, 0x30, 0x2f, - 0x8b, 0xe5, 0x34, 0x59, 0xec, 0x5d, 0x58, 0x9c, 0xba, 0x01, 0x0f, 0xc3, 0x11, 0x1f, 0x46, 0x63, - 0xa9, 0x20, 0x52, 0x33, 0x2a, 0x50, 0xc3, 0xd9, 0x80, 0x25, 0x32, 0x3a, 0x04, 0x76, 0xe8, 0x05, - 0xe7, 0x4e, 0x60, 0x05, 0x42, 0x43, 0x22, 0x75, 0x77, 0x11, 0x8b, 0x7a, 0xb2, 0xa4, 0x47, 0x2a, - 0xd2, 0xda, 0x0c, 0xbe, 0xcf, 0x07, 0xdc, 0xb9, 0xe0, 0x43, 0x94, 0xd3, 0x72, 0xe6, 0x4a, 0xa2, - 0x8e, 0x29, 0x0b, 0x51, 0xe8, 0x9e, 0x8e, 0xad, 0xe9, 0x64, 0x68, 0x0b, 0x61, 0xa5, 0x4e, 0xc2, - 0xb0, 0x3b, 0x1d, 0x1f, 0x13, 0x84, 0x3d, 0x06, 0x25, 0x89, 0x49, 0xf9, 0xb0, 0x91, 0xe0, 0x67, - 0x82, 0x58, 0xcd, 0xaa, 0xc4, 0x20, 0x41, 0x31, 0x21, 0x73, 0x36, 0x67, 0x64, 0xce, 0x16, 0x14, - 0x27, 0xbe, 0x73, 0x61, 0x87, 0xbc, 0xb5, 0x48, 0x0c, 0x5c, 0x3e, 0x0a, 0xce, 0xe0, 0xb8, 0x4e, - 0xe8, 0xd8, 0xa1, 0xe7, 0xb7, 0x18, 0x96, 0xc5, 0x00, 0xf6, 0x10, 0x16, 0x91, 0x46, 0x82, 0xd0, - 0x0e, 0xa7, 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x21, 0x1c, 0x85, 0x50, 0xf6, - 0x2d, 0x58, 0x25, 0xb2, 0xc0, 0x1a, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x97, 0x62, 0x09, 0x4b, - 0x05, 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0xef, 0xc3, 0x9a, 0x24, 0x93, 0xb9, 0x5a, 0x2b, 0x58, - 0x6b, 0x99, 0x8a, 0x67, 0xaa, 0x6d, 0xc0, 0xa2, 0x18, 0x92, 0x33, 0xb0, 0x64, 0x6d, 0xb1, 0x13, - 0x56, 0xc5, 0xe8, 0x51, 0x53, 0x6a, 0x50, 0xa1, 0x89, 0x65, 0xcf, 0xf8, 0x35, 0xfb, 0x1e, 0x34, - 0x88, 0x64, 0x50, 0xbd, 0x42, 0x4e, 0xbf, 0x8e, 0x9c, 0x7e, 0x45, 0x59, 0x38, 0xa3, 0x52, 0x64, - 0xf6, 0xf5, 0x41, 0xe2, 0x59, 0x6c, 0x87, 0x91, 0x73, 0xca, 0x43, 0x67, 0xcc, 0x5b, 0x6b, 0x44, - 0x60, 0xea, 0x59, 0xec, 0xd4, 0xe9, 0x04, 0x4b, 0x5a, 0xc4, 0x17, 0xe8, 0x09, 0x69, 0x77, 0xe4, - 0x05, 0x5c, 0x99, 0xa8, 0x5a, 0xb7, 0xe5, 0x26, 0x14, 0x40, 0x25, 0x43, 0x0a, 0x41, 0x9c, 0x94, - 0x9e, 0xc8, 0x90, 0x78, 0x07, 0x89, 0xa1, 0x46, 0xba, 0x8f, 0x32, 0x26, 0x8a, 0x53, 0xfc, 0xdc, - 0xbe, 0x54, 0x1c, 0xe4, 0x35, 0x7c, 0xbf, 0x20, 0x40, 0x92, 0x77, 0xfc, 0x34, 0x43, 0x07, 0xa2, - 0xe4, 0x1f, 0x81, 0xa6, 0xde, 0x11, 0xe7, 0xb0, 0x3c, 0x77, 0x74, 0x2d, 0x99, 0x09, 0x10, 0xe8, - 0xd0, 0x1d, 0xe1, 0x6e, 0x76, 0x5c, 0x1d, 0x85, 0x78, 0x6f, 0x55, 0x01, 0x11, 0xe9, 0x1e, 0x54, - 0x26, 0xd3, 0x93, 0x91, 0x33, 0x20, 0x94, 0x1c, 0xb5, 0x42, 0x20, 0x44, 0x10, 0xfa, 0x2d, 0x51, - 0x14, 0x61, 0xe4, 0x11, 0xa3, 0x22, 0x61, 0x88, 0x82, 0xbc, 0x9d, 0xfb, 0xc8, 0x4e, 0xaa, 0x26, - 0xfe, 0x36, 0x36, 0x61, 0x39, 0x39, 0x68, 0x79, 0xf0, 0x3c, 0x84, 0x92, 0xe4, 0x55, 0xca, 0xf0, - 0x51, 0xd7, 0x4c, 0xd1, 0x42, 0x45, 0x8b, 0xca, 0x8d, 0xdf, 0x5e, 0x80, 0x25, 0x09, 0xdd, 0x12, - 0x4b, 0xdb, 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0xc2, 0x04, 0x33, 0x2f, 0x66, 0x82, 0xd9, 0x39, 0x26, - 0x98, 0xd4, 0x7c, 0x89, 0x87, 0x26, 0x35, 0x5f, 0xf1, 0x2e, 0x49, 0x19, 0xd1, 0xed, 0xa0, 0x35, - 0x09, 0xee, 0x93, 0xbd, 0x75, 0x8e, 0x65, 0x17, 0x52, 0x58, 0xb6, 0xce, 0x70, 0x17, 0x66, 0x18, - 0xee, 0x1b, 0x40, 0x44, 0xa3, 0xde, 0x7e, 0x91, 0xf4, 0x13, 0x84, 0x49, 0x63, 0xea, 0x3b, 0xd0, - 0x98, 0xe5, 0x71, 0xc4, 0x4c, 0xeb, 0x29, 0x1c, 0xce, 0x19, 0x73, 0x3c, 0xad, 0x34, 0xe4, 0xb2, - 0xe4, 0x70, 0xce, 0x98, 0xef, 0x61, 0x89, 0xc2, 0xef, 0x00, 0x50, 0xdf, 0xb8, 0x69, 0x00, 0x37, - 0xcd, 0xdb, 0xc9, 0x77, 0xa1, 0xaf, 0xfa, 0x86, 0x78, 0x98, 0xfa, 0x1c, 0x77, 0x51, 0x19, 0x6b, - 0xe2, 0x06, 0x7a, 0x06, 0x75, 0x6f, 0xc2, 0x5d, 0x2b, 0xe6, 0x35, 0x15, 0x6c, 0xea, 0xad, 0x17, - 0x34, 0xd5, 0x55, 0xb8, 0x66, 0x4d, 0xd4, 0x8d, 0x1e, 0xd9, 0x3e, 0x2d, 0x3c, 0xd7, 0x5a, 0xab, - 0x7e, 0x89, 0xd6, 0xea, 0x58, 0x39, 0x7a, 0x36, 0xfe, 0x56, 0x06, 0x2a, 0xda, 0xb0, 0xd9, 0x0a, - 0x2c, 0x6e, 0x1d, 0x1e, 0x1e, 0x75, 0xcc, 0x76, 0xbf, 0xfb, 0x49, 0xc7, 0xda, 0xda, 0x3b, 0xec, - 0x75, 0x9a, 0xb7, 0x04, 0x78, 0xef, 0x70, 0xab, 0xbd, 0x67, 0xed, 0x1c, 0x9a, 0x5b, 0x0a, 0x9c, - 0x61, 0xab, 0xc0, 0xcc, 0xce, 0xfe, 0x61, 0xbf, 0x93, 0x80, 0x67, 0x59, 0x13, 0xaa, 0x9b, 0x66, - 0xa7, 0xbd, 0xb5, 0x2b, 0x21, 0x39, 0xb6, 0x0c, 0xcd, 0x9d, 0xe3, 0x83, 0xed, 0xee, 0xc1, 0x53, - 0x6b, 0xab, 0x7d, 0xb0, 0xd5, 0xd9, 0xeb, 0x6c, 0x37, 0xf3, 0xac, 0x06, 0xe5, 0xf6, 0x66, 0xfb, - 0x60, 0xfb, 0xf0, 0xa0, 0xb3, 0xdd, 0x2c, 0x18, 0xbf, 0x02, 0xe5, 0x78, 0xa2, 0x15, 0x28, 0x1e, - 0x1f, 0x3c, 0x3b, 0x38, 0xfc, 0xf4, 0xa0, 0x79, 0x8b, 0x95, 0xa1, 0x80, 0xfd, 0x37, 0x33, 0x0c, - 0x60, 0x81, 0xfa, 0x6c, 0x66, 0x59, 0x09, 0xf2, 0x9b, 0x87, 0xfd, 0xdd, 0x66, 0xce, 0xf8, 0xf3, - 0x0c, 0xac, 0xe0, 0x94, 0x87, 0xb3, 0x4c, 0xe0, 0x3e, 0x54, 0x06, 0x9e, 0x37, 0x11, 0x9a, 0x56, - 0x2c, 0x51, 0xe8, 0x20, 0xb1, 0xc1, 0x89, 0x79, 0x9f, 0x7a, 0xfe, 0x80, 0x4b, 0x1e, 0x00, 0x08, - 0xda, 0x11, 0x10, 0x41, 0x83, 0x92, 0x88, 0x09, 0x83, 0x58, 0x40, 0x85, 0x60, 0x84, 0xb2, 0x0a, - 0x0b, 0x27, 0x3e, 0xb7, 0x07, 0xe7, 0x72, 0xf7, 0xcb, 0x27, 0xf6, 0xf5, 0xd8, 0x06, 0x30, 0x10, - 0x34, 0x35, 0xe2, 0x43, 0xdc, 0x02, 0x25, 0xb3, 0x21, 0xe1, 0x5b, 0x12, 0x2c, 0x4e, 0x23, 0xfb, - 0xc4, 0x76, 0x87, 0x9e, 0xcb, 0x87, 0x52, 0xd5, 0x88, 0x01, 0xc6, 0x11, 0xac, 0xce, 0xce, 0x4f, - 0xf2, 0x8b, 0x0f, 0x34, 0x7e, 0x41, 0x92, 0xff, 0xfa, 0xcd, 0xa4, 0xa0, 0xf1, 0x8e, 0xbf, 0x93, - 0x87, 0xbc, 0x90, 0x04, 0x6f, 0x14, 0x1a, 0x75, 0xd1, 0x3e, 0x37, 0xe7, 0xfe, 0x41, 0x53, 0x03, - 0x89, 0x08, 0x64, 0xcf, 0x2a, 0x23, 0x04, 0x45, 0x83, 0xa8, 0xd8, 0xe7, 0x83, 0x0b, 0x69, 0xd0, - 0xa2, 0x62, 0x93, 0x0f, 0x2e, 0x50, 0xa7, 0xb2, 0x43, 0xaa, 0x4b, 0xfb, 0xbd, 0x18, 0xd8, 0x21, - 0xd6, 0x94, 0x45, 0x58, 0xaf, 0x18, 0x15, 0x61, 0xad, 0x16, 0x14, 0x1d, 0xf7, 0xc4, 0x9b, 0xba, - 0x43, 0xdc, 0xde, 0x25, 0x53, 0x3d, 0xa2, 0xb7, 0x09, 0x39, 0x91, 0x38, 0x88, 0x68, 0x37, 0x97, - 0x04, 0xa0, 0x2f, 0x8e, 0xa2, 0xf7, 0xa0, 0x1c, 0x5c, 0xbb, 0x03, 0x7d, 0x0f, 0x2f, 0xcb, 0xf5, - 0x11, 0xb3, 0xdf, 0xe8, 0x5d, 0xbb, 0x03, 0xdc, 0xb1, 0xa5, 0x40, 0xfe, 0x62, 0xef, 0x43, 0x29, - 0xb2, 0xfb, 0x12, 0x07, 0xbe, 0xad, 0xd7, 0x50, 0xc6, 0x5e, 0x52, 0xaf, 0x23, 0x54, 0xf6, 0x08, - 0x16, 0xd0, 0x38, 0x1b, 0xb4, 0xaa, 0x58, 0x49, 0xc9, 0xfb, 0x62, 0x18, 0xe8, 0xe8, 0xe1, 0x43, - 0x34, 0xd4, 0x9a, 0x12, 0x6d, 0xfd, 0x19, 0xd4, 0x12, 0x6d, 0xe9, 0x4a, 0x74, 0x8d, 0x94, 0xe8, - 0xb7, 0x74, 0x25, 0x3a, 0x3e, 0x09, 0x64, 0x35, 0x5d, 0xa9, 0xfe, 0x35, 0x28, 0xa9, 0xa9, 0x88, - 0xfd, 0x27, 0xf7, 0x8e, 0xd5, 0xfb, 0xec, 0x60, 0xab, 0x79, 0x8b, 0x35, 0xa0, 0xd2, 0xde, 0xc2, - 0x2d, 0x8d, 0x80, 0x8c, 0x40, 0x39, 0x6a, 0xf7, 0x7a, 0x11, 0x24, 0x6b, 0xec, 0x40, 0x73, 0x76, - 0xa4, 0x82, 0x26, 0x43, 0x05, 0x93, 0xa6, 0xeb, 0x18, 0x20, 0x54, 0x24, 0xb2, 0x46, 0x93, 0x1c, - 0x4e, 0x0f, 0xc6, 0xfb, 0xd0, 0x14, 0xe7, 0x9a, 0x58, 0xaa, 0x40, 0x33, 0x01, 0x8f, 0x84, 0x6c, - 0xa7, 0x9b, 0xaf, 0x4b, 0x66, 0x85, 0x60, 0xd8, 0x95, 0xf1, 0x01, 0x2c, 0x6a, 0xd5, 0x62, 0x95, - 0x56, 0x9c, 0x95, 0xb3, 0x2a, 0x2d, 0x2a, 0x30, 0x54, 0x62, 0xac, 0xc1, 0x8a, 0x78, 0xec, 0x5c, - 0x70, 0x37, 0xec, 0x4d, 0x4f, 0xc8, 0xe7, 0xe8, 0x78, 0xae, 0x50, 0x6c, 0xca, 0x51, 0xc9, 0xcd, - 0x44, 0xbe, 0x21, 0xb5, 0xdf, 0x2c, 0x92, 0xc6, 0xba, 0xd6, 0x03, 0x56, 0xdc, 0xc0, 0xbf, 0x09, - 0x2d, 0xb8, 0x1c, 0x81, 0xc4, 0xb2, 0x1e, 0x75, 0x3a, 0xa6, 0x75, 0x78, 0xb0, 0xd7, 0x3d, 0x10, - 0x8c, 0x52, 0x2c, 0x2b, 0x02, 0x76, 0x76, 0x10, 0x92, 0x31, 0x9a, 0x50, 0x7f, 0xca, 0xc3, 0xae, - 0x7b, 0xea, 0x29, 0xff, 0xda, 0xcf, 0x0a, 0xd0, 0x88, 0x40, 0xb1, 0x16, 0x7d, 0xc1, 0xfd, 0xc0, - 0xf1, 0x5c, 0x14, 0x88, 0xcb, 0xa6, 0x7a, 0x14, 0xa7, 0x9b, 0x33, 0xe4, 0x6e, 0xe8, 0x84, 0xd7, - 0x56, 0xc2, 0xe4, 0x56, 0x57, 0x60, 0x79, 0x8a, 0x2e, 0x43, 0xc1, 0x1e, 0x39, 0xb6, 0x72, 0xd5, - 0xd2, 0x83, 0x80, 0x0e, 0xbc, 0x91, 0xe7, 0xa3, 0xec, 0x5b, 0x36, 0xe9, 0x81, 0x3d, 0x86, 0x65, - 0x21, 0x83, 0xeb, 0x76, 0x50, 0xe4, 0x1f, 0x64, 0xfd, 0x63, 0xee, 0x74, 0x7c, 0x14, 0xdb, 0x42, - 0x45, 0x89, 0x38, 0x3b, 0x45, 0x0d, 0x29, 0x2c, 0x45, 0x15, 0x48, 0x9d, 0x5b, 0x74, 0xa7, 0xe3, - 0x36, 0x96, 0x44, 0xf8, 0x4f, 0x60, 0x45, 0xe0, 0x47, 0xe2, 0x55, 0x54, 0xa3, 0x81, 0x35, 0x44, - 0x63, 0x5d, 0x59, 0x16, 0xd5, 0xb9, 0x03, 0x65, 0x1a, 0x95, 0x78, 0xe3, 0x05, 0x12, 0xe3, 0x71, - 0x28, 0xdc, 0x0f, 0xe6, 0xbc, 0xaa, 0x0b, 0x24, 0x08, 0xcc, 0x78, 0x55, 0x35, 0xbf, 0x6c, 0x69, - 0xd6, 0x2f, 0xfb, 0x04, 0x56, 0x4e, 0x04, 0x09, 0x9e, 0x73, 0x7b, 0xc8, 0x7d, 0x2b, 0x26, 0x6c, - 0x52, 0x57, 0x96, 0x44, 0xe1, 0x2e, 0x96, 0x45, 0xfb, 0x40, 0xc8, 0x39, 0x82, 0x2d, 0xf0, 0xa1, - 0x15, 0x7a, 0x16, 0x8a, 0x3f, 0xc8, 0x60, 0x4a, 0x66, 0x8d, 0xc0, 0x7d, 0x6f, 0x4b, 0x00, 0x93, - 0x78, 0x67, 0xbe, 0x3d, 0x39, 0x97, 0x0a, 0x45, 0x84, 0xf7, 0x54, 0x00, 0xd9, 0x6b, 0x50, 0x14, - 0x24, 0xef, 0x72, 0x72, 0x7e, 0x91, 0xc8, 0xae, 0x40, 0xec, 0x2d, 0x58, 0xc0, 0x3e, 0x82, 0x56, - 0x13, 0xe9, 0xbd, 0x1a, 0x33, 0x72, 0xc7, 0x35, 0x65, 0x99, 0x10, 0x26, 0xa7, 0xbe, 0x43, 0x5c, - 0xa6, 0x6c, 0xe2, 0x6f, 0xf6, 0x7d, 0x8d, 0x65, 0x2d, 0x61, 0x5d, 0x25, 0x0f, 0xcc, 0x50, 0xda, - 0x4d, 0xdc, 0xeb, 0x2b, 0x65, 0x46, 0x3f, 0xc8, 0x97, 0x2a, 0xcd, 0xaa, 0xf1, 0x1d, 0x28, 0xd0, - 0xea, 0x08, 0x22, 0xc4, 0xb5, 0xcb, 0x48, 0x22, 0x44, 0x68, 0x0b, 0x8a, 0x2e, 0x0f, 0x2f, 0x3d, - 0xff, 0xb9, 0x32, 0x4a, 0xcb, 0x47, 0xe3, 0xc7, 0x68, 0x4d, 0x89, 0x3c, 0xee, 0xa4, 0x18, 0x0a, - 0xf2, 0xa0, 0xd7, 0x1b, 0x9c, 0xdb, 0xd2, 0xc0, 0x53, 0x42, 0x40, 0xef, 0xdc, 0x9e, 0x23, 0x8f, - 0xec, 0xbc, 0xd3, 0xfd, 0x2d, 0xa8, 0x2b, 0x1f, 0x7f, 0x60, 0x8d, 0xf8, 0x69, 0x28, 0xc9, 0xbd, - 0x2a, 0x1d, 0xfc, 0xc1, 0x1e, 0x3f, 0x0d, 0x8d, 0x7d, 0x58, 0x94, 0x04, 0x79, 0x38, 0xe1, 0xaa, - 0xeb, 0xef, 0xa6, 0xc9, 0xd3, 0x95, 0x27, 0x4b, 0xc9, 0x83, 0x96, 0x62, 0x17, 0x12, 0x42, 0xb6, - 0xf1, 0x31, 0x30, 0xfd, 0x18, 0x96, 0xed, 0x49, 0xa9, 0x56, 0xd9, 0xf2, 0x95, 0x4b, 0x2c, 0x92, - 0x9d, 0x9d, 0xa1, 0x58, 0x9d, 0x60, 0x3a, 0x18, 0xa8, 0xd8, 0x8b, 0x92, 0xa9, 0x1e, 0x8d, 0x3f, - 0xc9, 0xc0, 0x12, 0x36, 0xa6, 0xf4, 0x01, 0xc9, 0x64, 0x7f, 0xee, 0x41, 0x8a, 0xf7, 0xa3, 0xcb, - 0x3e, 0xf4, 0xf0, 0xe5, 0xad, 0xa7, 0xf9, 0x39, 0xeb, 0xe9, 0xd7, 0xa1, 0x39, 0xe4, 0x23, 0x07, - 0xc3, 0x70, 0x94, 0x28, 0x41, 0x1a, 0x40, 0x43, 0xc1, 0xa5, 0x36, 0x68, 0xfc, 0x83, 0x0c, 0x2c, - 0x92, 0xa4, 0x82, 0x7a, 0xb5, 0x5c, 0xa8, 0x8f, 0x94, 0x22, 0x29, 0x59, 0x95, 0x9c, 0x53, 0x7c, - 0x82, 0x23, 0x94, 0x90, 0x77, 0x6f, 0x49, 0x05, 0x53, 0x42, 0xd9, 0x87, 0xa8, 0xc3, 0xb8, 0x16, - 0x02, 0x53, 0xc2, 0x7a, 0x92, 0x2f, 0x65, 0xf7, 0x16, 0x2a, 0x38, 0x2e, 0x82, 0x36, 0x4b, 0x42, - 0xb3, 0x15, 0x60, 0x63, 0x07, 0x6a, 0x89, 0x6e, 0x12, 0x26, 0xde, 0x2a, 0x99, 0x78, 0xe7, 0xdc, - 0x28, 0xd9, 0x79, 0x37, 0xca, 0xdf, 0xc8, 0x03, 0x13, 0x24, 0x35, 0xf3, 0xd6, 0x66, 0x7c, 0x90, - 0xd9, 0x39, 0x1f, 0xe4, 0x63, 0x60, 0x1a, 0x82, 0x72, 0x8d, 0xe6, 0x22, 0xd7, 0x68, 0x33, 0xc6, - 0x95, 0x9e, 0xd1, 0xc7, 0xb0, 0x2c, 0x05, 0xda, 0xc8, 0xe9, 0x88, 0xb6, 0x3b, 0x7a, 0x3f, 0x8c, - 0x24, 0x5b, 0xe5, 0x7c, 0x44, 0x3b, 0x9e, 0xf2, 0x3f, 0x0a, 0x1d, 0x9c, 0x4c, 0x5e, 0xe8, 0x7f, - 0x54, 0xda, 0xb7, 0x46, 0x05, 0x0b, 0x2f, 0xa5, 0x82, 0xe2, 0x1c, 0x15, 0x68, 0x16, 0x98, 0x52, - 0xd2, 0x02, 0x63, 0x40, 0x4d, 0x79, 0x19, 0x29, 0xb8, 0x82, 0xa4, 0xb7, 0x8a, 0x74, 0x35, 0x62, - 0x80, 0xc5, 0x03, 0x68, 0x2a, 0x33, 0x49, 0x64, 0xe3, 0xa1, 0xc0, 0x01, 0x69, 0x65, 0xdb, 0x52, - 0x96, 0x9e, 0x84, 0x45, 0xbd, 0x32, 0x63, 0x51, 0x7f, 0x17, 0x16, 0x03, 0x41, 0x44, 0xd6, 0xd4, - 0x95, 0x51, 0x3e, 0x7c, 0x88, 0xaa, 0x53, 0xc9, 0x6c, 0x62, 0xc1, 0x71, 0x0c, 0x9f, 0xb7, 0x5f, - 0xd4, 0x52, 0xec, 0x17, 0xef, 0xc7, 0x0e, 0xb9, 0xe0, 0xdc, 0x19, 0xe3, 0xc1, 0x1d, 0x47, 0xc4, - 0xc8, 0x05, 0xee, 0x9d, 0x3b, 0x63, 0x53, 0x79, 0x7f, 0xc5, 0x83, 0xf1, 0xef, 0x32, 0xd0, 0x14, - 0x74, 0x90, 0xa0, 0xf3, 0x5f, 0x01, 0xdc, 0x91, 0xaf, 0x48, 0xe6, 0x15, 0x81, 0xab, 0xa8, 0xfc, - 0x3b, 0x80, 0x64, 0x6b, 0x09, 0x3d, 0x51, 0x12, 0x79, 0x2b, 0x49, 0xe4, 0x31, 0x23, 0xdb, 0xbd, - 0x45, 0x0a, 0x80, 0x80, 0xa4, 0x39, 0x42, 0xf3, 0x29, 0x8e, 0x50, 0x6d, 0x2b, 0xec, 0x02, 0x3c, - 0xe3, 0xd7, 0x7b, 0xde, 0x00, 0x35, 0xb4, 0xbb, 0x00, 0x82, 0x20, 0x4f, 0xed, 0xb1, 0x23, 0xad, - 0x2b, 0x05, 0xb3, 0xfc, 0x9c, 0x5f, 0xef, 0x20, 0x40, 0xbc, 0x0d, 0x51, 0x1c, 0xef, 0x87, 0x82, - 0x59, 0x7a, 0xce, 0xaf, 0x69, 0x33, 0x58, 0x50, 0x7b, 0xc6, 0xaf, 0xb7, 0x39, 0x89, 0x6b, 0x9e, - 0x2f, 0x28, 0xc1, 0xb7, 0x2f, 0x85, 0x7c, 0x96, 0x70, 0x62, 0x56, 0x7c, 0xfb, 0xf2, 0x19, 0xbf, - 0x56, 0x0e, 0xd5, 0xa2, 0x28, 0x1f, 0x79, 0x03, 0x79, 0x02, 0xa9, 0x70, 0x8c, 0x78, 0x50, 0xe6, - 0xc2, 0x73, 0xfc, 0x6d, 0xfc, 0x65, 0x06, 0x6a, 0x62, 0xfc, 0xc8, 0xe0, 0xc4, 0xba, 0xab, 0xa8, - 0x9e, 0x4c, 0x1c, 0xd5, 0xf3, 0x44, 0xf2, 0x07, 0xe2, 0x96, 0xd9, 0x9b, 0xb9, 0x25, 0x2e, 0x30, - 0xb1, 0xca, 0xf7, 0xa0, 0x4c, 0x7b, 0x4b, 0x6c, 0xd6, 0x5c, 0xe2, 0x2d, 0x25, 0x26, 0x64, 0x96, - 0x10, 0xed, 0x19, 0x05, 0x11, 0x68, 0x96, 0x3a, 0x5a, 0xe2, 0xb2, 0x1f, 0xd9, 0xe7, 0x52, 0x5e, - 0x43, 0xe1, 0x86, 0x20, 0x02, 0xdd, 0x0c, 0xb6, 0x30, 0x67, 0x06, 0x3b, 0x86, 0x8a, 0x46, 0x74, - 0x68, 0xf7, 0x8b, 0x66, 0x47, 0x14, 0x9a, 0xa4, 0xaa, 0xc4, 0xf2, 0xec, 0xde, 0x32, 0x6b, 0x03, - 0x1d, 0xb0, 0xb9, 0x00, 0x79, 0x51, 0xc9, 0xf8, 0x08, 0x16, 0xb5, 0x66, 0x49, 0x5d, 0x4d, 0x1b, - 0x74, 0x26, 0xcd, 0x89, 0xfe, 0x0f, 0x33, 0xb0, 0x2c, 0x6b, 0x63, 0x88, 0x98, 0x23, 0xce, 0xf3, - 0xfd, 0xe0, 0x8c, 0xfd, 0x0a, 0xd4, 0x44, 0xeb, 0x96, 0xcf, 0xcf, 0x9c, 0x20, 0xe4, 0xca, 0x47, - 0x92, 0xb2, 0x7b, 0x04, 0x5b, 0x17, 0xa8, 0xa6, 0xc4, 0x64, 0x1f, 0x41, 0x05, 0xab, 0x92, 0x42, - 0x2d, 0xdf, 0x5b, 0x6b, 0xbe, 0x22, 0x0d, 0x75, 0xf7, 0x96, 0x09, 0x41, 0xf4, 0xb4, 0x59, 0x86, - 0x62, 0xe8, 0x3b, 0x67, 0x67, 0xdc, 0x37, 0x56, 0xa3, 0xa1, 0x89, 0xad, 0xc8, 0x7b, 0x21, 0x9f, - 0x08, 0x29, 0xc9, 0xf8, 0x8f, 0x19, 0xa8, 0xc8, 0xcd, 0xf5, 0x73, 0x3b, 0x46, 0xd6, 0xb5, 0x18, - 0x47, 0xd2, 0x9d, 0xe3, 0x90, 0xc6, 0x77, 0xa0, 0x31, 0x16, 0x12, 0x93, 0x90, 0xe8, 0x13, 0x5e, - 0x91, 0xba, 0x02, 0x4b, 0x81, 0x65, 0x03, 0x96, 0x50, 0x7e, 0x09, 0xac, 0xd0, 0x19, 0x59, 0xaa, - 0x50, 0xc6, 0x13, 0x2e, 0x52, 0x51, 0xdf, 0x19, 0xed, 0xcb, 0x02, 0x71, 0x8c, 0x07, 0xa1, 0x7d, - 0xc6, 0x25, 0x6d, 0xd0, 0x83, 0xd1, 0x82, 0xd5, 0x19, 0x61, 0x5e, 0x29, 0x22, 0xff, 0xbd, 0x01, - 0x6b, 0x73, 0x45, 0x52, 0x21, 0x89, 0xbc, 0x01, 0x23, 0x67, 0x7c, 0xe2, 0x45, 0xb6, 0xb2, 0x8c, - 0xe6, 0x0d, 0xd8, 0x13, 0x25, 0xca, 0x56, 0xc6, 0x61, 0x45, 0x11, 0x04, 0x1a, 0xbb, 0x22, 0x79, - 0x3f, 0x8b, 0xd2, 0xe8, 0x7b, 0x49, 0x4e, 0x36, 0xdb, 0x9d, 0x82, 0xeb, 0xe7, 0xe3, 0xd2, 0x64, - 0x0e, 0x16, 0xb0, 0x53, 0x68, 0x45, 0x74, 0x27, 0x05, 0x28, 0x4d, 0x79, 0x11, 0x3d, 0x7d, 0xe3, - 0x25, 0x3d, 0x25, 0xac, 0x28, 0xe6, 0xaa, 0x22, 0x57, 0x6a, 0x2c, 0xea, 0xe7, 0x02, 0x5e, 0x57, - 0xfd, 0xa0, 0x30, 0x34, 0xdf, 0x5b, 0xfe, 0x95, 0xe6, 0x85, 0xd6, 0xa1, 0x64, 0x97, 0x77, 0x64, - 0xc3, 0x51, 0x91, 0xde, 0xef, 0x39, 0xac, 0x5e, 0xda, 0x4e, 0xa8, 0xe6, 0xa7, 0xe9, 0x4d, 0x05, - 0xec, 0xef, 0xc9, 0x4b, 0xfa, 0xfb, 0x94, 0x2a, 0x27, 0xc4, 0xc3, 0xe5, 0xcb, 0x79, 0x60, 0xb0, - 0xfe, 0x6f, 0xb2, 0x50, 0x4f, 0xb6, 0x22, 0x36, 0xb5, 0x64, 0x54, 0x4a, 0xe0, 0x90, 0x02, 0xbb, - 0xb4, 0xe1, 0x1e, 0x90, 0xa0, 0x31, 0x6f, 0x5d, 0xce, 0xa6, 0x58, 0x97, 0x75, 0xa3, 0x6e, 0xee, - 0x65, 0x5e, 0xb4, 0xfc, 0x2b, 0x79, 0xd1, 0x0a, 0x69, 0x5e, 0xb4, 0x9b, 0x5d, 0x2f, 0x0b, 0x3f, - 0x97, 0xeb, 0xa5, 0x78, 0xb3, 0xeb, 0x65, 0xfd, 0x2f, 0x33, 0xc0, 0xe6, 0x29, 0x95, 0x3d, 0x25, - 0x43, 0xba, 0xcb, 0x47, 0x92, 0x8b, 0x7d, 0xf3, 0xd5, 0xa8, 0x5d, 0xbd, 0x20, 0x55, 0x9b, 0x3d, - 0x82, 0x25, 0x3d, 0x02, 0x59, 0xd7, 0x65, 0x6a, 0x26, 0xd3, 0x8b, 0x62, 0x8d, 0x57, 0x73, 0x21, - 0xe6, 0x5f, 0xea, 0x42, 0x2c, 0xbc, 0xd4, 0x85, 0xb8, 0x90, 0x74, 0x21, 0xae, 0xff, 0x97, 0x0c, - 0x2c, 0xa5, 0x10, 0xd5, 0x57, 0x37, 0x67, 0x41, 0x0b, 0x09, 0x16, 0x93, 0x95, 0xb4, 0xa0, 0x73, - 0x97, 0x3d, 0xa8, 0xc4, 0x5e, 0x29, 0x15, 0xa1, 0xff, 0xf0, 0x65, 0x3b, 0x3d, 0xae, 0x61, 0xea, - 0xd5, 0xd7, 0xbf, 0x80, 0x8a, 0x56, 0x26, 0x16, 0x91, 0x28, 0x48, 0x0b, 0xdc, 0xa0, 0x43, 0x1e, - 0x15, 0xb1, 0x7b, 0x20, 0x2d, 0xbd, 0x54, 0x4e, 0xb4, 0x2e, 0x4f, 0x74, 0x44, 0xd8, 0x80, 0x25, - 0xe5, 0xe3, 0xe0, 0x71, 0x7c, 0x96, 0x64, 0xfb, 0x8b, 0xd2, 0xd3, 0xc1, 0xa3, 0x70, 0xaf, 0xf5, - 0x9f, 0x40, 0x2d, 0xc1, 0x11, 0xbe, 0xba, 0xb5, 0x9c, 0x55, 0x2b, 0x69, 0xac, 0xba, 0x5a, 0xb9, - 0xfe, 0x7f, 0x72, 0xc0, 0xe6, 0x99, 0xd2, 0x2f, 0x73, 0x08, 0xf3, 0x6f, 0x3c, 0x97, 0xf2, 0xc6, - 0xff, 0x9f, 0x1d, 0x92, 0xef, 0xc2, 0xa2, 0x4c, 0x01, 0xd1, 0x5c, 0x40, 0x44, 0xf5, 0xcd, 0xa8, - 0x40, 0x8d, 0xe2, 0x3b, 0xb3, 0xae, 0xe8, 0x52, 0x22, 0xea, 0x5d, 0x93, 0x12, 0x66, 0x3c, 0xd2, - 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, 0x47, 0x8d, 0xa6, 0xfe, 0xe4, 0x57, 0xbf, 0xf4, 0x39, - 0xb1, 0xd1, 0xc6, 0xfa, 0x28, 0x9a, 0x98, 0xb2, 0x31, 0xe3, 0x3d, 0xa8, 0x68, 0x60, 0x74, 0x8b, - 0x74, 0xf7, 0x37, 0x0f, 0x9b, 0xb7, 0x58, 0x0d, 0xca, 0x66, 0x67, 0xeb, 0xf0, 0x93, 0x8e, 0xd9, - 0xd9, 0x6e, 0x66, 0x58, 0x09, 0xf2, 0x7b, 0x87, 0xbd, 0x7e, 0x33, 0x6b, 0xac, 0x43, 0x4b, 0xb6, - 0x38, 0x6f, 0x22, 0xfd, 0xdd, 0x7c, 0x64, 0x9d, 0xc0, 0x42, 0xa9, 0x8c, 0x7c, 0x0b, 0xaa, 0xfa, - 0x19, 0x2e, 0x29, 0x62, 0xc6, 0x0b, 0x29, 0xd4, 0x10, 0x4f, 0x63, 0x82, 0x5b, 0x40, 0xbe, 0xa5, - 0x61, 0x54, 0x8d, 0x04, 0xb3, 0x17, 0x38, 0x23, 0x50, 0xe6, 0x4c, 0x90, 0xe1, 0xff, 0x07, 0xf5, - 0xa4, 0xbd, 0x50, 0x6e, 0xf5, 0x34, 0xa9, 0x5c, 0xd4, 0x4e, 0x18, 0x10, 0xd9, 0xf7, 0xa1, 0x39, - 0x6b, 0x6f, 0x94, 0xc1, 0xc1, 0x37, 0xd4, 0x6f, 0x38, 0x49, 0x13, 0x24, 0xdb, 0x85, 0xe5, 0x34, - 0x29, 0x06, 0xe9, 0xe3, 0x66, 0x75, 0x8c, 0xcd, 0x4b, 0x2a, 0xec, 0xbb, 0xd2, 0xac, 0x5c, 0x48, - 0x73, 0xce, 0x69, 0x8b, 0xbd, 0x41, 0xff, 0x34, 0x03, 0xf3, 0x05, 0x40, 0x0c, 0x63, 0x4d, 0xa8, - 0x1e, 0x1e, 0x75, 0x0e, 0xac, 0xad, 0xdd, 0xf6, 0xc1, 0x41, 0x67, 0xaf, 0x79, 0x8b, 0x31, 0xa8, - 0xa3, 0x57, 0x6d, 0x3b, 0x82, 0x65, 0x04, 0x4c, 0x9a, 0xf7, 0x15, 0x2c, 0xcb, 0x96, 0xa1, 0xd9, - 0x3d, 0x98, 0x81, 0xe6, 0x58, 0x0b, 0x96, 0x8f, 0x3a, 0xe4, 0x88, 0x4b, 0xb4, 0x9b, 0x17, 0x92, - 0xb1, 0x9c, 0xae, 0x90, 0x8c, 0x29, 0x95, 0x49, 0xee, 0x03, 0x25, 0x30, 0xfe, 0x5e, 0x06, 0x56, - 0x66, 0x0a, 0xe2, 0x00, 0x75, 0x12, 0x17, 0x93, 0x82, 0x62, 0x15, 0x81, 0x6a, 0x37, 0xbd, 0x0b, - 0x8b, 0x91, 0x8a, 0x3d, 0xc3, 0xee, 0x9b, 0x51, 0x81, 0x42, 0x7e, 0x04, 0x4b, 0x9a, 0xa6, 0x3e, - 0xc3, 0x2b, 0x98, 0x56, 0x24, 0x2b, 0x18, 0x6b, 0x51, 0x20, 0xf0, 0xcc, 0xa8, 0x87, 0x94, 0x1f, - 0xa5, 0x17, 0xc4, 0x56, 0xf7, 0xe4, 0x78, 0xd5, 0x23, 0x7b, 0x3c, 0x43, 0x08, 0xc9, 0xd1, 0xea, - 0x2f, 0x5c, 0x75, 0xff, 0x07, 0x0b, 0xc0, 0x3e, 0x9e, 0x72, 0xff, 0x1a, 0x03, 0xd0, 0x83, 0x97, - 0x45, 0x64, 0x29, 0x75, 0x34, 0xfb, 0x4a, 0x49, 0x26, 0x69, 0x49, 0x1e, 0xf9, 0x97, 0x27, 0x79, - 0x14, 0x5e, 0x96, 0xe4, 0xf1, 0x26, 0xd4, 0x9c, 0x33, 0xd7, 0x13, 0xac, 0x50, 0x88, 0x7c, 0x41, - 0x6b, 0xe1, 0x7e, 0xee, 0x41, 0xd5, 0xac, 0x4a, 0xa0, 0x10, 0xf8, 0x02, 0xf6, 0x51, 0x8c, 0xc4, - 0x87, 0x67, 0x98, 0x90, 0xa4, 0x33, 0xc1, 0xce, 0xf0, 0x8c, 0x4b, 0xed, 0x1b, 0xed, 0x51, 0xaa, - 0xb2, 0x80, 0x07, 0xec, 0x2d, 0xa8, 0x07, 0xde, 0x54, 0x48, 0xd0, 0x6a, 0x19, 0xc8, 0x2e, 0x5f, - 0x25, 0xe8, 0x91, 0x72, 0xc2, 0x2c, 0x4d, 0x03, 0x6e, 0x8d, 0x9d, 0x20, 0x10, 0x72, 0xcf, 0xc0, - 0x73, 0x43, 0xdf, 0x1b, 0x49, 0x53, 0xfb, 0xe2, 0x34, 0xe0, 0xfb, 0x54, 0xb2, 0x45, 0x05, 0xec, - 0xdb, 0xf1, 0x90, 0x26, 0xb6, 0xe3, 0x07, 0x2d, 0xc0, 0x21, 0xa9, 0x99, 0xa2, 0xa0, 0x6a, 0x3b, - 0x7e, 0x34, 0x16, 0xf1, 0x10, 0xcc, 0x24, 0x9f, 0x54, 0x66, 0x93, 0x4f, 0x7e, 0x94, 0x9e, 0x7c, - 0x52, 0xc3, 0xa6, 0x1f, 0xcb, 0xa6, 0xe7, 0x5f, 0xf1, 0x97, 0xca, 0x41, 0x99, 0xcf, 0xa9, 0xa9, - 0x7f, 0x99, 0x9c, 0x9a, 0x46, 0x5a, 0x4e, 0xcd, 0x7b, 0x50, 0xc1, 0x6c, 0x07, 0xeb, 0xdc, 0x11, - 0xc2, 0x11, 0xb9, 0x0e, 0x9a, 0x7a, 0x3a, 0xc4, 0xae, 0xe3, 0x86, 0x26, 0xf8, 0xea, 0x67, 0x30, - 0x9f, 0xde, 0xb2, 0xf8, 0x4b, 0x4c, 0x6f, 0x91, 0x59, 0x19, 0x1b, 0x50, 0x52, 0xef, 0x89, 0x31, - 0xc8, 0x9f, 0xfa, 0xde, 0x58, 0x99, 0x54, 0xc5, 0x6f, 0x56, 0x87, 0x6c, 0xe8, 0xc9, 0xca, 0xd9, - 0xd0, 0x33, 0x7e, 0x13, 0x2a, 0x1a, 0xa9, 0xb1, 0x37, 0xc8, 0x78, 0x23, 0x94, 0x10, 0x29, 0xb5, - 0xd1, 0x2a, 0x96, 0x25, 0xb4, 0x3b, 0x14, 0xfc, 0x66, 0xe8, 0xf8, 0x1c, 0x13, 0xd1, 0x2c, 0x9f, - 0x5f, 0x70, 0x3f, 0x50, 0x26, 0xee, 0x66, 0x54, 0x60, 0x12, 0xdc, 0xf8, 0x2b, 0xb0, 0x94, 0x78, - 0xb7, 0x92, 0x45, 0xbc, 0x05, 0x0b, 0xb8, 0x6e, 0xca, 0x05, 0x99, 0x4c, 0x33, 0x91, 0x65, 0x98, - 0x61, 0x4c, 0xd6, 0x79, 0x6b, 0xe2, 0x7b, 0x27, 0xd8, 0x49, 0xc6, 0xac, 0x48, 0xd8, 0x91, 0xef, - 0x9d, 0x18, 0x7f, 0x96, 0x83, 0xdc, 0xae, 0x37, 0xd1, 0xa3, 0x6e, 0x32, 0x73, 0x51, 0x37, 0x52, - 0xb3, 0xb2, 0x22, 0xcd, 0x49, 0x0a, 0xc3, 0x68, 0x97, 0x56, 0xda, 0xd3, 0x03, 0xa8, 0x0b, 0x3e, - 0x11, 0x7a, 0x42, 0x35, 0xbd, 0xb4, 0x7d, 0x12, 0x35, 0x73, 0xb4, 0xf9, 0xec, 0x71, 0xd8, 0xf7, - 0x76, 0x08, 0xce, 0x96, 0x21, 0x17, 0xe9, 0x05, 0x58, 0x2c, 0x1e, 0xd9, 0x2a, 0x2c, 0x60, 0xf8, - 0xe5, 0xb5, 0xf4, 0xb1, 0xc9, 0x27, 0xf6, 0x4d, 0x58, 0x4a, 0xb6, 0x4b, 0xac, 0x48, 0xca, 0x46, - 0x7a, 0xc3, 0xc8, 0x93, 0x6e, 0x83, 0xe0, 0x23, 0x84, 0x23, 0x5d, 0xf5, 0xa7, 0x9c, 0x63, 0x91, - 0xc6, 0xf4, 0x4a, 0x09, 0xa6, 0x77, 0x0f, 0x2a, 0xe1, 0xe8, 0xc2, 0x9a, 0xd8, 0xd7, 0x23, 0xcf, - 0x1e, 0xca, 0xfd, 0x0d, 0xe1, 0xe8, 0xe2, 0x88, 0x20, 0xec, 0x11, 0xc0, 0x78, 0x32, 0x91, 0x7b, - 0x0f, 0xcd, 0xbc, 0x31, 0x29, 0xef, 0x1f, 0x1d, 0x11, 0xc9, 0x99, 0xe5, 0xf1, 0x64, 0x42, 0x3f, - 0xd9, 0x36, 0xd4, 0x53, 0x93, 0xc5, 0xee, 0xaa, 0x68, 0x41, 0x6f, 0xb2, 0x91, 0xb2, 0x39, 0x6b, - 0x03, 0x1d, 0xb6, 0xfe, 0x7d, 0x60, 0xbf, 0x60, 0xca, 0x56, 0x1f, 0xca, 0xd1, 0xf8, 0xf4, 0x8c, - 0x27, 0x8c, 0xff, 0xad, 0x24, 0x32, 0x9e, 0xda, 0xc3, 0xa1, 0x2f, 0xf8, 0x22, 0x1d, 0x98, 0x11, - 0xcb, 0x07, 0xed, 0xc4, 0x6c, 0x13, 0xdf, 0x37, 0xfe, 0x22, 0x03, 0x05, 0x4a, 0xbf, 0x7a, 0x1b, - 0x1a, 0x84, 0x1f, 0x45, 0x30, 0x49, 0xcf, 0x1c, 0x9d, 0xbb, 0x7d, 0x19, 0xbc, 0x24, 0xb6, 0x85, - 0x96, 0x3a, 0x9a, 0x8d, 0xde, 0xbc, 0x96, 0x3e, 0x7a, 0x0f, 0xca, 0x51, 0xd7, 0x1a, 0xe9, 0x94, - 0x54, 0xcf, 0xec, 0x75, 0xc8, 0x9f, 0x7b, 0x13, 0x65, 0xe2, 0x80, 0x78, 0x25, 0x4d, 0x84, 0xc7, - 0x63, 0x11, 0x7d, 0xd0, 0xe0, 0xa5, 0x6a, 0x1e, 0x75, 0x82, 0x64, 0x30, 0x3f, 0xc7, 0x85, 0x94, - 0x39, 0x1e, 0x43, 0x43, 0xf0, 0x01, 0xcd, 0x43, 0x7e, 0xf3, 0xa1, 0xf9, 0x75, 0x21, 0xe1, 0x0d, - 0x46, 0xd3, 0x21, 0xd7, 0x0d, 0x4c, 0x18, 0x4e, 0x23, 0xe1, 0x4a, 0xb2, 0x36, 0xfe, 0x20, 0x43, - 0xfc, 0x45, 0xb4, 0xcb, 0x1e, 0x40, 0x5e, 0x9c, 0x6f, 0x33, 0x06, 0xd0, 0x28, 0x10, 0x5b, 0xe0, - 0x99, 0x88, 0x81, 0xf9, 0xd6, 0xd3, 0x71, 0xb2, 0xf5, 0x9a, 0x59, 0x71, 0xa7, 0xe3, 0xc8, 0x46, - 0xf3, 0x35, 0x35, 0xad, 0x19, 0xfb, 0x06, 0xcd, 0x3e, 0xda, 0xa6, 0x1b, 0x5a, 0x5c, 0x4e, 0x3e, - 0x71, 0x62, 0x2a, 0x29, 0x70, 0x78, 0xc6, 0xb5, 0x78, 0x9c, 0x3f, 0xca, 0x42, 0x2d, 0x31, 0x22, - 0x0c, 0x4c, 0x12, 0x07, 0x00, 0x59, 0xdf, 0xe5, 0xfb, 0x06, 0x01, 0x92, 0x82, 0xba, 0xb6, 0x4e, - 0xd9, 0xc4, 0x3a, 0x45, 0xb1, 0x00, 0x39, 0x3d, 0x16, 0xe0, 0x31, 0x94, 0xe3, 0x94, 0xe1, 0xe4, - 0x90, 0x44, 0x7f, 0x2a, 0x1c, 0x3d, 0x46, 0x8a, 0xa3, 0x07, 0x0a, 0x7a, 0xf4, 0xc0, 0xf7, 0x34, - 0x67, 0xf3, 0x02, 0x36, 0x63, 0xa4, 0xad, 0xe8, 0x2f, 0xc5, 0xd5, 0x6c, 0x7c, 0x04, 0x15, 0x6d, - 0xf0, 0xba, 0x53, 0x39, 0x93, 0x70, 0x2a, 0x47, 0x89, 0x23, 0xd9, 0x38, 0x71, 0xc4, 0xf8, 0xed, - 0x2c, 0xd4, 0xc4, 0xfe, 0x72, 0xdc, 0xb3, 0x23, 0x6f, 0xe4, 0x0c, 0xd0, 0x1a, 0x1f, 0xed, 0x30, - 0x29, 0x68, 0xa9, 0x7d, 0x26, 0xb7, 0x18, 0xc9, 0x59, 0x7a, 0x7e, 0x1c, 0x31, 0xe9, 0x28, 0x3f, - 0xce, 0x80, 0x9a, 0x60, 0x8c, 0x27, 0x76, 0xc0, 0xb5, 0x84, 0x66, 0xb3, 0x72, 0xca, 0xf9, 0xa6, - 0x1d, 0x10, 0x87, 0xfc, 0x26, 0x2c, 0x09, 0x1c, 0x4c, 0x0d, 0x1a, 0x3b, 0xa3, 0x91, 0x43, 0x98, - 0x64, 0xc1, 0x69, 0x9e, 0x72, 0x6e, 0xda, 0x21, 0xdf, 0x17, 0x05, 0x32, 0xff, 0xb9, 0x34, 0x74, - 0x02, 0xfb, 0x24, 0x0e, 0x1f, 0x8b, 0x9e, 0xd1, 0x87, 0x66, 0x5f, 0x69, 0x3e, 0x34, 0xca, 0x11, - 0xac, 0x8c, 0xed, 0xab, 0xc8, 0x87, 0x36, 0x43, 0x49, 0xc5, 0x59, 0x4a, 0x32, 0xfe, 0x43, 0x16, - 0x2a, 0x1a, 0x59, 0xbe, 0xca, 0xe9, 0x7a, 0x77, 0xce, 0x7b, 0x52, 0xd6, 0x1d, 0x25, 0x6f, 0x26, - 0xbb, 0x44, 0x57, 0x3b, 0x65, 0x5a, 0x6b, 0x04, 0x7c, 0x07, 0xca, 0x62, 0xd7, 0xbd, 0x87, 0xb6, - 0x46, 0x79, 0x4f, 0x00, 0x02, 0x8e, 0xa6, 0x27, 0xaa, 0xf0, 0x09, 0x16, 0x16, 0xe2, 0xc2, 0x27, - 0xa2, 0xf0, 0x45, 0x31, 0xa3, 0xdf, 0x81, 0xaa, 0x6c, 0x15, 0xdf, 0x29, 0x4e, 0x37, 0xde, 0xf5, - 0x89, 0xf7, 0x6d, 0x56, 0xa8, 0x3b, 0x7a, 0xf9, 0xb2, 0xe2, 0x13, 0x55, 0xb1, 0xf4, 0xb2, 0x8a, - 0x4f, 0xe8, 0xc1, 0xd8, 0x89, 0xc2, 0x70, 0x31, 0xcc, 0x43, 0xf1, 0xb1, 0x47, 0xb0, 0xa4, 0xd8, - 0xd5, 0xd4, 0xb5, 0x5d, 0xd7, 0x9b, 0xba, 0x03, 0xae, 0x32, 0x4a, 0x98, 0x2c, 0x3a, 0x8e, 0x4b, - 0x8c, 0x61, 0x94, 0x72, 0x48, 0xe1, 0x22, 0x0f, 0xa1, 0x40, 0x72, 0x39, 0x09, 0x1f, 0xe9, 0x8c, - 0x8b, 0x50, 0xd8, 0x03, 0x28, 0x90, 0x78, 0x9e, 0xbd, 0x91, 0xd9, 0x10, 0x82, 0xb1, 0x01, 0x0d, - 0x14, 0x31, 0x35, 0x8e, 0xfb, 0x22, 0xa9, 0xc4, 0x58, 0x06, 0x76, 0x40, 0x9b, 0x48, 0x0f, 0x63, - 0xfa, 0xaf, 0x39, 0xa8, 0x68, 0x60, 0xc1, 0x16, 0x31, 0xf0, 0xc5, 0x1a, 0x3a, 0xf6, 0x98, 0x2b, - 0x97, 0x4e, 0xcd, 0xac, 0x21, 0x74, 0x5b, 0x02, 0xc5, 0xa1, 0x60, 0x5f, 0x9c, 0x59, 0xde, 0x34, - 0xb4, 0x86, 0xfc, 0xcc, 0xe7, 0x5c, 0x0a, 0x4b, 0x55, 0xfb, 0xe2, 0xec, 0x70, 0x1a, 0x6e, 0x23, - 0x4c, 0x60, 0x09, 0xa2, 0xd6, 0xb0, 0x64, 0xac, 0xc6, 0xd8, 0xbe, 0x8a, 0xb1, 0x64, 0xc0, 0x10, - 0x2d, 0x51, 0x3e, 0x0a, 0x18, 0x22, 0xb5, 0x65, 0x96, 0x93, 0x17, 0xe6, 0x39, 0xf9, 0xb7, 0x61, - 0x95, 0x38, 0xb9, 0xe4, 0x11, 0xd6, 0x0c, 0x49, 0x2d, 0x63, 0xa9, 0x9c, 0xa4, 0x26, 0x7f, 0x35, - 0xc5, 0x0c, 0xd4, 0xfe, 0x08, 0x9c, 0x1f, 0xd3, 0x8e, 0xca, 0x98, 0x62, 0x66, 0xb2, 0xf1, 0x9e, - 0xf3, 0x63, 0x2e, 0x30, 0xd1, 0x21, 0xad, 0x63, 0xca, 0xd0, 0xe4, 0xb1, 0xe3, 0xce, 0x62, 0xda, - 0x57, 0x49, 0xcc, 0xb2, 0xc4, 0xb4, 0xaf, 0x74, 0xcc, 0xf7, 0x61, 0x6d, 0xcc, 0x87, 0x8e, 0x9d, - 0x6c, 0xd6, 0x8a, 0x25, 0x88, 0x65, 0x2a, 0xd6, 0xea, 0xf4, 0x48, 0x83, 0x14, 0xab, 0xf1, 0x63, - 0x6f, 0x7c, 0xe2, 0xd0, 0xe1, 0x49, 0x2e, 0xf2, 0xbc, 0x59, 0x77, 0xa7, 0xe3, 0x1f, 0x22, 0x58, - 0x54, 0x09, 0x8c, 0x1a, 0x54, 0x7a, 0xa1, 0x37, 0x51, 0xaf, 0xb9, 0x0e, 0x55, 0x7a, 0x94, 0xf9, - 0x42, 0x77, 0xe0, 0x36, 0xd2, 0x66, 0xdf, 0x9b, 0x78, 0x23, 0xef, 0xec, 0x3a, 0x61, 0x50, 0xfa, - 0x4f, 0x19, 0x58, 0x4a, 0x94, 0xca, 0x7d, 0xfe, 0x6d, 0xda, 0x58, 0x51, 0xd2, 0x07, 0x91, 0xf3, - 0xa2, 0x76, 0xf8, 0x10, 0x22, 0xed, 0x2a, 0x95, 0x08, 0xd2, 0x8e, 0x93, 0x95, 0x55, 0x45, 0xa2, - 0xed, 0xd6, 0x3c, 0x6d, 0xcb, 0xfa, 0x2a, 0x8d, 0x59, 0x35, 0xf1, 0xab, 0x32, 0x7c, 0x7c, 0x28, - 0xa7, 0x9c, 0x4b, 0x06, 0xc8, 0xea, 0xc6, 0x27, 0x35, 0x82, 0xd8, 0x22, 0x15, 0x18, 0xff, 0x2c, - 0x03, 0x10, 0x8f, 0x0e, 0x43, 0x74, 0xa3, 0x03, 0x94, 0xee, 0x01, 0xd2, 0x0e, 0xcb, 0x37, 0xa0, - 0x1a, 0x45, 0xea, 0xc5, 0x47, 0x72, 0x45, 0xc1, 0xc4, 0xb9, 0xfc, 0x0e, 0x34, 0xce, 0x46, 0xde, - 0x09, 0x8a, 0x4e, 0xf2, 0x00, 0xa5, 0xac, 0xa9, 0x3a, 0x81, 0xd5, 0xb1, 0x18, 0x1f, 0xe0, 0xf9, - 0xd4, 0x60, 0x3e, 0xfd, 0x38, 0x36, 0x7e, 0x27, 0x1b, 0x85, 0x2c, 0xc5, 0x2b, 0xf1, 0x62, 0x3d, - 0xe3, 0xe7, 0xf1, 0x7c, 0xbf, 0xc8, 0xa1, 0xf3, 0x11, 0xd4, 0x7d, 0xe2, 0x8e, 0x8a, 0x75, 0xe6, - 0x5f, 0xc0, 0x3a, 0x6b, 0x7e, 0xe2, 0xc8, 0xfd, 0x3a, 0x34, 0xed, 0xe1, 0x05, 0xf7, 0x43, 0x07, - 0xcd, 0xc6, 0x28, 0xa8, 0xc9, 0x20, 0x21, 0x0d, 0x8e, 0x12, 0xd1, 0x3b, 0xd0, 0x90, 0x39, 0x6c, - 0x11, 0xa6, 0xbc, 0x15, 0x23, 0x06, 0x0b, 0x44, 0xe3, 0x5f, 0xaa, 0x18, 0xa9, 0xe4, 0xdb, 0x7d, - 0xf1, 0xaa, 0xe8, 0x33, 0xcc, 0xce, 0xbb, 0xac, 0x24, 0x21, 0x49, 0x6b, 0xb4, 0xe4, 0x47, 0x04, - 0x94, 0xb6, 0xe8, 0xe4, 0xb2, 0xe6, 0x5f, 0x65, 0x59, 0x8d, 0xff, 0x9c, 0x81, 0xe2, 0xae, 0x37, - 0x11, 0x7a, 0xb9, 0x90, 0xe7, 0x70, 0x9b, 0x44, 0x6e, 0x88, 0x05, 0xf1, 0xd8, 0x1d, 0xbe, 0x38, - 0x55, 0x23, 0x55, 0xde, 0xa8, 0x25, 0xe5, 0x8d, 0xef, 0xc1, 0x1d, 0x74, 0xf2, 0xf8, 0xde, 0xc4, - 0xf3, 0xc5, 0x56, 0xb5, 0x47, 0x24, 0x77, 0x78, 0x6e, 0x78, 0xae, 0x78, 0xe7, 0xed, 0x53, 0xce, - 0x8f, 0x34, 0x8c, 0xfd, 0x08, 0x01, 0x93, 0xa1, 0x46, 0xe1, 0x85, 0x45, 0xaa, 0xa2, 0x14, 0x8c, - 0x88, 0xa3, 0x36, 0x44, 0x41, 0x07, 0xe1, 0x28, 0x1a, 0x19, 0xdf, 0x85, 0x72, 0x64, 0x75, 0x60, - 0xef, 0x42, 0xf9, 0xdc, 0x9b, 0x48, 0xd3, 0x44, 0x26, 0x91, 0xce, 0x22, 0x67, 0x6d, 0x96, 0xce, - 0xe9, 0x47, 0x60, 0xfc, 0x59, 0x11, 0x8a, 0x5d, 0xf7, 0xc2, 0x73, 0x06, 0x18, 0x65, 0x35, 0xe6, - 0x63, 0x4f, 0x25, 0xd2, 0x8a, 0xdf, 0x18, 0x49, 0x11, 0xdf, 0x6d, 0x91, 0x93, 0x91, 0x14, 0xd1, - 0xad, 0x16, 0x2b, 0xb0, 0xe0, 0xeb, 0x97, 0x53, 0x14, 0x7c, 0x8c, 0xfb, 0x8c, 0x94, 0xb6, 0x82, - 0x96, 0x88, 0x2c, 0xda, 0xa2, 0x4b, 0x13, 0x70, 0xc9, 0x28, 0xb1, 0xa9, 0x8c, 0x10, 0x5c, 0xb0, - 0xd7, 0xa0, 0x28, 0xb3, 0x47, 0x28, 0x16, 0x9f, 0x02, 0x35, 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0xe4, - 0xa4, 0x8b, 0x24, 0x2a, 0xa1, 0xa7, 0x4b, 0xe0, 0xb6, 0xa0, 0xb5, 0x7b, 0x50, 0x21, 0x7c, 0x42, - 0x29, 0xc9, 0xb8, 0x28, 0x04, 0x21, 0x42, 0xca, 0x1d, 0x2f, 0xe5, 0xd4, 0x3b, 0x5e, 0x30, 0x8c, - 0x2e, 0xe2, 0xb2, 0x34, 0x45, 0xa0, 0x9b, 0x3d, 0x34, 0xb8, 0xba, 0xe0, 0x48, 0x2a, 0xf7, 0x94, - 0xe7, 0xa7, 0x94, 0xfb, 0x37, 0xa1, 0x76, 0x6a, 0x8f, 0x46, 0x27, 0xf6, 0xe0, 0x39, 0xe9, 0xa4, - 0x55, 0x32, 0xc3, 0x29, 0x20, 0x2a, 0xa5, 0xf7, 0xa0, 0xa2, 0xbd, 0x65, 0x0c, 0x7a, 0xca, 0x9b, - 0x10, 0xbf, 0xdf, 0x59, 0x53, 0x53, 0xfd, 0x15, 0x4c, 0x4d, 0x5a, 0xf0, 0x57, 0x23, 0x19, 0xfc, - 0x75, 0x07, 0xb9, 0xa9, 0x0c, 0x10, 0x6a, 0xd2, 0x35, 0x12, 0xf6, 0x70, 0x88, 0x01, 0x42, 0x74, - 0x67, 0x1b, 0x2e, 0x1e, 0x95, 0x2f, 0x92, 0x50, 0x4b, 0x30, 0x42, 0xb9, 0x4b, 0xf6, 0xd2, 0x89, - 0xed, 0x0c, 0x31, 0xd8, 0x96, 0xd4, 0xd8, 0xa2, 0x3d, 0x0e, 0x8f, 0x6c, 0x67, 0xc8, 0xee, 0x43, - 0x55, 0x15, 0xe3, 0xe9, 0xb8, 0x44, 0xeb, 0x2f, 0x8b, 0xc5, 0x99, 0x68, 0x40, 0x2d, 0xc2, 0x18, - 0xc7, 0xc9, 0x7a, 0x15, 0x89, 0x82, 0x74, 0xf0, 0x1e, 0xc6, 0x54, 0x84, 0x1c, 0x53, 0xf2, 0xea, - 0x4f, 0xee, 0xc8, 0xb9, 0x4a, 0x2a, 0x55, 0xff, 0xc9, 0x4b, 0x43, 0x98, 0x42, 0x10, 0x23, 0x67, - 0xd1, 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0x2c, 0x22, 0x04, 0xf6, 0x5d, 0x4d, 0x91, 0x6a, 0x21, - 0xf2, 0x6b, 0x33, 0xed, 0xdf, 0x94, 0x6b, 0x70, 0x17, 0xc0, 0x09, 0xc4, 0x29, 0x13, 0x70, 0x77, - 0x88, 0xd9, 0x75, 0x25, 0xb3, 0xec, 0x04, 0xcf, 0x08, 0xf0, 0xd5, 0x6a, 0x58, 0x6d, 0xa8, 0xea, - 0xd3, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0x75, 0x0e, 0x9a, 0xb7, 0x58, 0x05, 0x8a, 0xbd, 0x4e, 0xbf, - 0xbf, 0x87, 0x2e, 0xa7, 0x2a, 0x94, 0xa2, 0xd4, 0x9e, 0xac, 0x78, 0x6a, 0x6f, 0x6d, 0x75, 0x8e, - 0xfa, 0x9d, 0xed, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, 0x99, 0x33, 0xfe, 0x3c, 0x07, 0x15, 0x6d, - 0x15, 0x5e, 0xcc, 0x8c, 0xef, 0x02, 0xa0, 0x4a, 0x13, 0xc7, 0x8f, 0xe5, 0xcd, 0xb2, 0x80, 0xd0, - 0xcb, 0xd7, 0x8d, 0xe5, 0x39, 0xba, 0x9f, 0x44, 0x19, 0xcb, 0xdf, 0x84, 0x1a, 0x5d, 0xf5, 0xa1, - 0x3b, 0x0e, 0x0b, 0x66, 0x95, 0x80, 0x92, 0x55, 0x63, 0x6e, 0x20, 0x22, 0x61, 0xd6, 0x88, 0x4c, - 0xfc, 0x27, 0x10, 0xe6, 0x8d, 0x60, 0xd2, 0x4f, 0xe0, 0x8d, 0x2e, 0x38, 0x61, 0x90, 0x44, 0x58, - 0x91, 0xb0, 0xbe, 0xcc, 0x72, 0x94, 0xfc, 0x50, 0x4b, 0x4e, 0x2b, 0x98, 0x55, 0x02, 0xca, 0x8e, - 0xbe, 0xa9, 0x08, 0xa8, 0x84, 0x04, 0xb4, 0x36, 0x4f, 0x0d, 0x09, 0xe2, 0xd9, 0x9b, 0xb3, 0x67, - 0x95, 0x91, 0x30, 0xbe, 0x36, 0x5f, 0xef, 0xe5, 0x76, 0x2d, 0xf6, 0x2e, 0xb0, 0xf1, 0x64, 0x62, - 0xa5, 0x58, 0x9a, 0xf2, 0x66, 0x63, 0x3c, 0x99, 0xf4, 0x35, 0x43, 0xcc, 0x57, 0x60, 0x04, 0xfb, - 0x1c, 0x58, 0x5b, 0x6c, 0x60, 0x1c, 0x62, 0x64, 0x42, 0x8d, 0xd9, 0x72, 0x46, 0x67, 0xcb, 0x29, - 0xdc, 0x2f, 0x9b, 0xca, 0xfd, 0x5e, 0xc4, 0x27, 0x8c, 0x1d, 0xa8, 0x1c, 0x69, 0x17, 0x09, 0xdd, - 0x17, 0x27, 0x84, 0xba, 0x42, 0x88, 0xce, 0x0e, 0x32, 0x6e, 0xf9, 0xf2, 0xe6, 0x20, 0x6d, 0x34, - 0x59, 0x6d, 0x34, 0xc6, 0x3f, 0xcd, 0xd0, 0x25, 0x0d, 0xd1, 0xe0, 0xe3, 0xbb, 0x8b, 0x94, 0x1f, - 0x28, 0xce, 0x21, 0xad, 0x28, 0xff, 0x8f, 0x4c, 0xff, 0xc4, 0xa1, 0x59, 0xde, 0xe9, 0x69, 0xc0, - 0x55, 0x36, 0x54, 0x05, 0x61, 0x87, 0x08, 0x52, 0xc2, 0xb7, 0x90, 0xf0, 0x1d, 0x6a, 0x3f, 0x90, - 0x59, 0x51, 0x42, 0xf8, 0xde, 0xb7, 0xaf, 0x64, 0xaf, 0x81, 0x10, 0x41, 0xa4, 0xa1, 0x5a, 0xe5, - 0x80, 0x45, 0xcf, 0xc6, 0x3f, 0x92, 0x69, 0xae, 0xb3, 0xeb, 0xfb, 0x10, 0x4a, 0x51, 0xab, 0xc9, - 0x13, 0x56, 0x61, 0x46, 0xe5, 0xe2, 0x1c, 0x47, 0xad, 0x3c, 0x31, 0x62, 0xda, 0x5c, 0xe8, 0x6c, - 0xe8, 0x6a, 0xa3, 0xfe, 0x06, 0xb0, 0x53, 0xc7, 0x9f, 0x45, 0xa6, 0xcd, 0xd6, 0xc4, 0x12, 0x0d, - 0xdb, 0x38, 0x86, 0x25, 0xc5, 0x25, 0x34, 0x8d, 0x20, 0xf9, 0xf2, 0x32, 0x2f, 0x61, 0xf2, 0xd9, - 0x39, 0x26, 0x6f, 0xfc, 0x34, 0x0f, 0x45, 0x75, 0x29, 0x57, 0xda, 0x45, 0x52, 0xe5, 0xe4, 0x45, - 0x52, 0xad, 0xc4, 0xa5, 0x23, 0xf8, 0xea, 0xe5, 0x79, 0xff, 0xce, 0xec, 0x91, 0xad, 0x19, 0xcd, - 0x13, 0xc7, 0xf6, 0x2a, 0xe4, 0x27, 0x76, 0x78, 0x8e, 0x06, 0x32, 0x22, 0x1e, 0x7c, 0x56, 0xc6, - 0xf4, 0x42, 0xd2, 0x98, 0x9e, 0x76, 0xe9, 0x16, 0x89, 0xa4, 0x73, 0x97, 0x6e, 0xdd, 0x01, 0x92, - 0x2f, 0xb4, 0x30, 0xa3, 0x12, 0x02, 0xc4, 0x59, 0x94, 0x14, 0x47, 0x4a, 0xb3, 0xe2, 0xc8, 0x2b, - 0x8b, 0x0a, 0xdf, 0x86, 0x05, 0x4a, 0x58, 0x97, 0xb9, 0x6e, 0xea, 0x40, 0x91, 0x6b, 0xa8, 0xfe, - 0x53, 0xf0, 0xb1, 0x29, 0x71, 0xf5, 0x1b, 0x6c, 0x2a, 0x89, 0x1b, 0x6c, 0x74, 0x23, 0x7f, 0x35, - 0x69, 0xe4, 0x7f, 0x00, 0xcd, 0x68, 0x41, 0xd1, 0x64, 0xe6, 0x06, 0x32, 0x93, 0xa6, 0xae, 0xe0, - 0x82, 0x4b, 0x1e, 0x04, 0xf1, 0x81, 0x58, 0x4f, 0x1c, 0x88, 0x82, 0x87, 0xb5, 0xc3, 0x90, 0x8f, - 0x27, 0xa1, 0x3c, 0x10, 0x31, 0xd6, 0x5e, 0x1f, 0x60, 0x32, 0x0b, 0xb4, 0x06, 0xe5, 0xee, 0x81, - 0xb5, 0xb3, 0xd7, 0x7d, 0xba, 0xdb, 0x6f, 0x66, 0xc4, 0x63, 0xef, 0x78, 0x6b, 0xab, 0xd3, 0xd9, - 0xc6, 0x13, 0x07, 0x60, 0x61, 0xa7, 0xdd, 0x15, 0xa7, 0x4f, 0xce, 0xf8, 0xbd, 0x2c, 0x54, 0xb4, - 0xe6, 0xd9, 0xfb, 0xd1, 0xaa, 0xd0, 0x25, 0x27, 0x77, 0xe7, 0x87, 0xb0, 0xa1, 0x58, 0xb1, 0xb6, - 0x2c, 0xd1, 0x15, 0x63, 0xd9, 0x1b, 0xaf, 0x18, 0x63, 0x6f, 0x43, 0xc3, 0xa6, 0x16, 0xa2, 0x55, - 0x90, 0xe6, 0x60, 0x09, 0x96, 0x8b, 0x80, 0xc1, 0x75, 0xf1, 0x79, 0x22, 0xf0, 0xf2, 0x2a, 0x9e, - 0x2d, 0x3a, 0x52, 0x70, 0xb1, 0x8a, 0xa7, 0xb6, 0x33, 0x9a, 0xfa, 0x5c, 0xba, 0x6f, 0xa3, 0x93, - 0x99, 0xa0, 0xa6, 0x2a, 0x36, 0x3e, 0x00, 0x88, 0xc7, 0x9c, 0x5c, 0x9c, 0x5b, 0xc9, 0xc5, 0xc9, - 0x68, 0x8b, 0x93, 0x35, 0xb6, 0x89, 0x8d, 0xc8, 0x85, 0x8e, 0x3c, 0xd5, 0xdf, 0x04, 0x65, 0x91, - 0xb2, 0x30, 0xbc, 0x75, 0x32, 0xe2, 0xa1, 0xca, 0x97, 0x5d, 0x94, 0x25, 0xdd, 0xa8, 0x40, 0xa5, - 0xaf, 0xc7, 0xad, 0xc4, 0xdc, 0x48, 0x92, 0xe4, 0x2c, 0x37, 0x92, 0xa8, 0x66, 0x54, 0x6e, 0xac, - 0x43, 0x6b, 0x9b, 0x8b, 0xd6, 0xda, 0xa3, 0xd1, 0xcc, 0x70, 0x8c, 0x3b, 0x70, 0x3b, 0xa5, 0x4c, - 0x1a, 0x21, 0x3e, 0x86, 0x95, 0x36, 0xa5, 0xc6, 0x7e, 0x55, 0x39, 0x30, 0x46, 0x0b, 0x56, 0x67, - 0x9b, 0x94, 0x9d, 0xed, 0xc0, 0xe2, 0x36, 0x3f, 0x99, 0x9e, 0xed, 0xf1, 0x8b, 0xb8, 0x23, 0x06, - 0xf9, 0xe0, 0xdc, 0xbb, 0x94, 0xeb, 0x83, 0xbf, 0x31, 0x90, 0x4c, 0xe0, 0x58, 0xc1, 0x84, 0x0f, - 0x94, 0x45, 0x14, 0x21, 0xbd, 0x09, 0x1f, 0x18, 0xef, 0x03, 0xd3, 0xdb, 0x91, 0xeb, 0x25, 0xb4, - 0x84, 0xe9, 0x89, 0x15, 0x5c, 0x07, 0x21, 0x1f, 0xab, 0x3b, 0x74, 0x20, 0x98, 0x9e, 0xf4, 0x08, - 0x62, 0xbc, 0x03, 0xd5, 0x23, 0xfb, 0xda, 0xe4, 0x9f, 0xcb, 0xec, 0x8e, 0x35, 0x28, 0x4e, 0xec, - 0x6b, 0xc1, 0x06, 0x22, 0xe7, 0x08, 0x16, 0x1b, 0x7f, 0x98, 0x87, 0x05, 0xc2, 0x64, 0xf7, 0xe9, - 0x9a, 0x4b, 0xc7, 0xc5, 0x6d, 0xa8, 0x18, 0xa5, 0x06, 0x9a, 0xe3, 0xa5, 0xd9, 0x79, 0x5e, 0x2a, - 0x0d, 0x68, 0xea, 0x7a, 0x0f, 0x65, 0xc6, 0x76, 0xa7, 0x63, 0x75, 0xa7, 0x47, 0x32, 0x3f, 0x34, - 0x1f, 0x5f, 0x63, 0x4a, 0xc9, 0x73, 0x49, 0x47, 0x63, 0xac, 0x8b, 0xd0, 0xe8, 0xd4, 0x11, 0x21, - 0xd9, 0xa5, 0x0e, 0x4a, 0x55, 0x78, 0x8a, 0x2a, 0x6f, 0x28, 0xa9, 0xf0, 0xcc, 0x29, 0x36, 0xa5, - 0x97, 0x2b, 0x36, 0x64, 0x59, 0x7b, 0x81, 0x62, 0x03, 0xaf, 0xa0, 0xd8, 0xbc, 0x82, 0x93, 0xef, - 0x36, 0x94, 0xf0, 0xdc, 0xd7, 0xb8, 0xa7, 0x38, 0xef, 0x05, 0xf7, 0xfc, 0x8e, 0x26, 0xfa, 0x53, - 0x84, 0xc1, 0x9d, 0x78, 0x9b, 0x98, 0xfc, 0xf3, 0x5f, 0x8e, 0xf3, 0xe4, 0x33, 0x28, 0x4a, 0xa8, - 0x20, 0x68, 0xd7, 0x1e, 0xab, 0x1b, 0x92, 0xf0, 0xb7, 0x58, 0x36, 0xbc, 0xd6, 0xe5, 0xf3, 0xa9, - 0xe3, 0xf3, 0xa1, 0xba, 0xfa, 0xc2, 0xc1, 0x3d, 0x2a, 0x20, 0x62, 0x82, 0x42, 0x0d, 0x71, 0xbd, - 0x4b, 0x57, 0x26, 0xbe, 0x17, 0x9d, 0xe0, 0x99, 0x78, 0x34, 0x18, 0x34, 0xf1, 0x8e, 0xb4, 0x89, - 0xe7, 0xab, 0xc3, 0xc9, 0xf8, 0x69, 0x06, 0x9a, 0x72, 0x77, 0x45, 0x65, 0xba, 0x16, 0x50, 0xb8, - 0xc9, 0x21, 0xfe, 0xe2, 0x8b, 0x2c, 0x0c, 0xa8, 0xa1, 0xf1, 0x23, 0x3a, 0xa9, 0xc8, 0x78, 0x53, - 0x11, 0xc0, 0x1d, 0x79, 0x5a, 0xbd, 0x0e, 0x15, 0x15, 0xe5, 0x3a, 0x76, 0x46, 0xea, 0xc6, 0x62, - 0x0a, 0x73, 0xdd, 0x77, 0x46, 0xea, 0xa0, 0xf3, 0x6d, 0x99, 0xc7, 0x96, 0xc1, 0x83, 0xce, 0xb4, - 0x43, 0x6e, 0xfc, 0xdb, 0x0c, 0x2c, 0x6a, 0x53, 0x91, 0xfb, 0xf6, 0x43, 0xa8, 0x46, 0x97, 0x13, - 0xf2, 0x48, 0xf2, 0x5a, 0x4b, 0x32, 0x9a, 0xb8, 0x5a, 0x65, 0x10, 0x41, 0x02, 0x31, 0x98, 0xa1, - 0x7d, 0x8d, 0xe3, 0x0d, 0xa6, 0x63, 0xa5, 0xdc, 0x0c, 0xed, 0xeb, 0x1d, 0xce, 0x7b, 0xd3, 0xb1, - 0x50, 0x5d, 0x2f, 0x39, 0x7f, 0x1e, 0x21, 0x90, 0xcc, 0x05, 0x02, 0x26, 0x31, 0x0c, 0xa8, 0x8d, - 0x3d, 0x37, 0x3c, 0x8f, 0x50, 0xa4, 0xd4, 0x89, 0x40, 0xc2, 0x31, 0xfe, 0x34, 0x0b, 0x4b, 0x64, - 0x62, 0x93, 0xa6, 0x4d, 0xc9, 0xba, 0x5a, 0xb0, 0x40, 0xd6, 0x46, 0x62, 0x5e, 0xbb, 0xb7, 0x4c, - 0xf9, 0xcc, 0xbe, 0xfd, 0x8a, 0x66, 0x41, 0x95, 0x2a, 0x77, 0xc3, 0xf2, 0xe7, 0xe6, 0x97, 0xff, - 0xe6, 0xe5, 0x4d, 0xf3, 0xb8, 0x15, 0xd2, 0x3c, 0x6e, 0xaf, 0xe2, 0xe7, 0x9a, 0xcb, 0x27, 0x2b, - 0x4a, 0x1c, 0x2d, 0x9f, 0xec, 0x7d, 0x58, 0x4b, 0xe0, 0x20, 0xb7, 0x76, 0x4e, 0x1d, 0xae, 0xee, - 0x15, 0x58, 0xd6, 0xb0, 0x7b, 0xaa, 0x6c, 0xb3, 0x08, 0x85, 0x60, 0xe0, 0x4d, 0xb8, 0xb1, 0x0a, - 0xcb, 0xc9, 0x55, 0x95, 0xc7, 0xc4, 0xef, 0x67, 0xa0, 0x25, 0xe3, 0x23, 0x1c, 0xf7, 0x6c, 0xd7, - 0x09, 0x42, 0xcf, 0x8f, 0x2e, 0xf1, 0xbb, 0x0b, 0x10, 0x84, 0xb6, 0x2f, 0xb5, 0x4d, 0x99, 0x49, - 0x8f, 0x10, 0xd4, 0x24, 0x6f, 0x43, 0x89, 0xbb, 0x43, 0x2a, 0x24, 0x6a, 0x28, 0x72, 0x77, 0xa8, - 0xf4, 0xd0, 0x39, 0xf9, 0xbb, 0x96, 0x54, 0x2f, 0x64, 0x62, 0xab, 0x58, 0x1d, 0x7e, 0x81, 0x07, - 0x6f, 0x3e, 0x4a, 0x6c, 0xdd, 0xb7, 0xaf, 0x30, 0xda, 0x30, 0x30, 0xfe, 0x7e, 0x16, 0x1a, 0xf1, - 0xf8, 0x28, 0x2b, 0xfe, 0xc5, 0xf9, 0xfd, 0xf7, 0x25, 0x39, 0x38, 0x42, 0x7e, 0xd7, 0x0c, 0x8f, - 0x25, 0xda, 0x9c, 0x5d, 0x97, 0x19, 0x50, 0x51, 0x18, 0xde, 0x34, 0xd4, 0xee, 0xd2, 0x2a, 0x13, - 0xca, 0xe1, 0x34, 0x14, 0x0a, 0x97, 0xd0, 0x3c, 0x1d, 0x57, 0xaa, 0x3c, 0x05, 0x7b, 0x1c, 0x76, - 0xf1, 0x8a, 0x6e, 0x01, 0x16, 0xd5, 0xe8, 0x45, 0x0a, 0x2c, 0x81, 0xdf, 0x24, 0x39, 0x9b, 0xde, - 0x1c, 0xca, 0xd8, 0xba, 0x10, 0x4a, 0xb7, 0x95, 0x46, 0x42, 0xe8, 0xeb, 0x50, 0xa1, 0xc6, 0xe3, - 0xf4, 0xc1, 0xbc, 0x59, 0xc6, 0x1e, 0xb0, 0x5c, 0x1a, 0x81, 0xbc, 0x69, 0x42, 0xf5, 0x05, 0xea, - 0x0a, 0xc3, 0x0f, 0xfe, 0x76, 0x06, 0x6e, 0xa7, 0xbc, 0x36, 0xb9, 0xcb, 0xb7, 0x60, 0xf1, 0x34, - 0x2a, 0x54, 0xab, 0x4b, 0x5b, 0x7d, 0x55, 0xb1, 0xd5, 0xe4, 0x9a, 0x9a, 0xcd, 0xd3, 0x24, 0x20, - 0x56, 0xba, 0xe8, 0x0d, 0x26, 0x32, 0x44, 0x51, 0xe9, 0xa2, 0xd7, 0x48, 0xfa, 0xce, 0x11, 0xac, - 0x77, 0xae, 0x04, 0xc7, 0xd8, 0xd2, 0xef, 0x98, 0x57, 0x64, 0x94, 0x34, 0x30, 0x67, 0x5e, 0xc9, - 0xc0, 0x3c, 0xa4, 0x44, 0xb8, 0xa8, 0xad, 0x9f, 0xa7, 0x11, 0x3c, 0x40, 0x45, 0x1d, 0xba, 0x23, - 0x5f, 0x65, 0xa9, 0x0e, 0xa2, 0xbb, 0xf1, 0x8d, 0x00, 0x1a, 0xfb, 0xd3, 0x51, 0xe8, 0xc4, 0xd7, - 0xe5, 0xb3, 0x6f, 0xcb, 0x3a, 0xd8, 0x8f, 0x5a, 0xb5, 0xd4, 0x8e, 0x20, 0xea, 0x08, 0x17, 0x6b, - 0x2c, 0x1a, 0xb2, 0xe6, 0xfb, 0x6b, 0x8c, 0x93, 0x3d, 0x18, 0xb7, 0x61, 0x2d, 0x7e, 0xa2, 0x65, - 0x53, 0x47, 0xcd, 0x3f, 0xc9, 0x50, 0x68, 0x73, 0xf2, 0xea, 0x7e, 0xd6, 0x81, 0xa5, 0xc0, 0x71, - 0xcf, 0x46, 0x5c, 0x6f, 0x3e, 0x90, 0x8b, 0xb0, 0x92, 0x1c, 0x9b, 0xbc, 0xde, 0xdf, 0x5c, 0xa4, - 0x1a, 0x71, 0x6b, 0x01, 0xdb, 0xbc, 0x69, 0x90, 0x31, 0x59, 0xcc, 0xac, 0xc6, 0xfc, 0xe0, 0xbb, - 0x50, 0x4f, 0x76, 0xc4, 0xbe, 0x23, 0x93, 0x40, 0xe3, 0x51, 0xe5, 0x66, 0xd2, 0xf5, 0x62, 0x82, - 0xa8, 0xc4, 0x6b, 0x1f, 0x18, 0x7f, 0x37, 0x03, 0x2d, 0x93, 0x0b, 0xca, 0xd5, 0x46, 0xa9, 0x68, - 0xe6, 0xc3, 0xb9, 0x56, 0x6f, 0x9e, 0xab, 0xca, 0x2d, 0x55, 0x23, 0xfa, 0xc6, 0x8d, 0x2f, 0x63, - 0xf7, 0xd6, 0xdc, 0x8c, 0x36, 0x4b, 0xb0, 0x40, 0x28, 0xc6, 0x1a, 0xac, 0xc8, 0xf1, 0xa8, 0xb1, - 0xc4, 0xde, 0xc3, 0x44, 0x8f, 0x09, 0xef, 0xe1, 0x3a, 0xb4, 0xe8, 0x2e, 0x46, 0x7d, 0x12, 0xb2, - 0xe2, 0x36, 0xb0, 0x7d, 0x7b, 0x60, 0xfb, 0x9e, 0xe7, 0x1e, 0x71, 0x5f, 0x06, 0x8a, 0xa2, 0x84, - 0x89, 0xce, 0x35, 0x25, 0x0a, 0xd3, 0x93, 0xba, 0x41, 0xd0, 0x73, 0x55, 0x5c, 0x0c, 0x3d, 0x19, - 0x26, 0x2c, 0x6d, 0xda, 0xcf, 0xb9, 0x6a, 0x49, 0x2d, 0xd1, 0x47, 0x50, 0x99, 0x44, 0x8d, 0xaa, - 0x75, 0x57, 0x99, 0xe2, 0xf3, 0xdd, 0x9a, 0x3a, 0xb6, 0xf1, 0x04, 0x96, 0x93, 0x6d, 0x4a, 0xd6, - 0xb1, 0x0e, 0xa5, 0xb1, 0x84, 0xc9, 0xd1, 0x45, 0xcf, 0xc6, 0xef, 0x96, 0xa0, 0x28, 0xf5, 0x39, - 0xb6, 0x01, 0xf9, 0x81, 0x8a, 0x4d, 0x8a, 0x2f, 0x20, 0x91, 0xa5, 0xea, 0xff, 0x16, 0x46, 0x28, - 0x09, 0x3c, 0xf6, 0x11, 0xd4, 0x93, 0x5e, 0xd1, 0x99, 0x34, 0xd4, 0xa4, 0x3b, 0xb3, 0x36, 0x98, - 0xf1, 0x7f, 0x95, 0xe3, 0xc3, 0x91, 0x64, 0x86, 0xd2, 0xb9, 0x76, 0x7a, 0x7a, 0xae, 0x90, 0xb7, - 0x83, 0x73, 0xdb, 0x7a, 0xf2, 0xfe, 0x07, 0x32, 0x0f, 0xb5, 0x82, 0xc0, 0xde, 0xb9, 0xfd, 0xe4, - 0xfd, 0x0f, 0x66, 0x25, 0x69, 0x99, 0x85, 0xaa, 0x49, 0xd2, 0xcb, 0x50, 0xa0, 0xab, 0xf2, 0x28, - 0xc8, 0x84, 0x1e, 0xd8, 0x63, 0x58, 0x96, 0x6a, 0xab, 0x25, 0xc3, 0x81, 0x89, 0x0b, 0x96, 0x28, - 0xb5, 0x49, 0x96, 0xf5, 0xb0, 0x88, 0x6c, 0x43, 0xab, 0xb0, 0x70, 0x1e, 0xdf, 0x7b, 0x58, 0x33, - 0xe5, 0x93, 0xf1, 0xa7, 0x05, 0xa8, 0x68, 0x8b, 0xc2, 0xaa, 0x50, 0x32, 0x3b, 0xbd, 0x8e, 0xf9, - 0x49, 0x67, 0xbb, 0x79, 0x8b, 0x3d, 0x80, 0xb7, 0xba, 0x07, 0x5b, 0x87, 0xa6, 0xd9, 0xd9, 0xea, - 0x5b, 0x87, 0xa6, 0xa5, 0xae, 0xc1, 0x39, 0x6a, 0x7f, 0xb6, 0xdf, 0x39, 0xe8, 0x5b, 0xdb, 0x9d, - 0x7e, 0xbb, 0xbb, 0xd7, 0x6b, 0x66, 0xd8, 0x6b, 0xd0, 0x8a, 0x31, 0x55, 0x71, 0x7b, 0xff, 0xf0, - 0xf8, 0xa0, 0xdf, 0xcc, 0xb2, 0x7b, 0x70, 0x67, 0xa7, 0x7b, 0xd0, 0xde, 0xb3, 0x62, 0x9c, 0xad, - 0xbd, 0xfe, 0x27, 0x56, 0xe7, 0xd7, 0x8f, 0xba, 0xe6, 0x67, 0xcd, 0x5c, 0x1a, 0x82, 0x50, 0xc6, - 0x55, 0x0b, 0x79, 0x76, 0x1b, 0x56, 0x08, 0x81, 0xaa, 0x58, 0xfd, 0xc3, 0x43, 0xab, 0x77, 0x78, - 0x78, 0xd0, 0x2c, 0xb0, 0x45, 0xa8, 0x75, 0x0f, 0x3e, 0x69, 0xef, 0x75, 0xb7, 0x2d, 0xb3, 0xd3, - 0xde, 0xdb, 0x6f, 0x2e, 0xb0, 0x25, 0x68, 0xcc, 0xe2, 0x15, 0x45, 0x13, 0x0a, 0xef, 0xf0, 0xa0, - 0x7b, 0x78, 0x60, 0x7d, 0xd2, 0x31, 0x7b, 0xdd, 0xc3, 0x83, 0x66, 0x89, 0xad, 0x02, 0x4b, 0x16, - 0xed, 0xee, 0xb7, 0xb7, 0x9a, 0x65, 0xb6, 0x02, 0x8b, 0x49, 0xf8, 0xb3, 0xce, 0x67, 0x4d, 0x60, - 0x2d, 0x58, 0xa6, 0x81, 0x59, 0x9b, 0x9d, 0xbd, 0xc3, 0x4f, 0xad, 0xfd, 0xee, 0x41, 0x77, 0xff, - 0x78, 0xbf, 0x59, 0xc1, 0x8b, 0xb9, 0x3a, 0x1d, 0xab, 0x7b, 0xd0, 0x3b, 0xde, 0xd9, 0xe9, 0x6e, - 0x75, 0x3b, 0x07, 0xfd, 0x66, 0x95, 0x7a, 0x4e, 0x9b, 0x78, 0x4d, 0x54, 0x90, 0x39, 0x03, 0xd6, - 0x76, 0xb7, 0xd7, 0xde, 0xdc, 0xeb, 0x6c, 0x37, 0xeb, 0xec, 0x2e, 0xdc, 0xee, 0x77, 0xf6, 0x8f, - 0x0e, 0xcd, 0xb6, 0xf9, 0x99, 0xca, 0x29, 0xb0, 0x76, 0xda, 0xdd, 0xbd, 0x63, 0xb3, 0xd3, 0x6c, - 0xb0, 0x37, 0xe0, 0xae, 0xd9, 0xf9, 0xf8, 0xb8, 0x6b, 0x76, 0xb6, 0xad, 0x83, 0xc3, 0xed, 0x8e, - 0xb5, 0xd3, 0x69, 0xf7, 0x8f, 0xcd, 0x8e, 0xb5, 0xdf, 0xed, 0xf5, 0xba, 0x07, 0x4f, 0x9b, 0x4d, - 0xf6, 0x16, 0xdc, 0x8f, 0x50, 0xa2, 0x06, 0x66, 0xb0, 0x16, 0xc5, 0xfc, 0xd4, 0x2b, 0x3d, 0xe8, - 0xfc, 0x7a, 0xdf, 0x3a, 0xea, 0x74, 0xcc, 0x26, 0x63, 0xeb, 0xb0, 0x1a, 0x77, 0x4f, 0x1d, 0xc8, - 0xbe, 0x97, 0x44, 0xd9, 0x51, 0xc7, 0xdc, 0x6f, 0x1f, 0x88, 0x17, 0x9c, 0x28, 0x5b, 0x16, 0xc3, - 0x8e, 0xcb, 0x66, 0x87, 0xbd, 0xc2, 0x18, 0xd4, 0xb5, 0xb7, 0xb2, 0xd3, 0x36, 0x9b, 0xab, 0xac, - 0x01, 0x95, 0xfd, 0xa3, 0x23, 0xab, 0xdf, 0xdd, 0xef, 0x1c, 0x1e, 0xf7, 0x9b, 0x6b, 0x6c, 0x05, - 0x9a, 0xdd, 0x83, 0x7e, 0xc7, 0x14, 0xef, 0x5a, 0x55, 0xfd, 0x5f, 0x45, 0xb6, 0x0c, 0x0d, 0x35, - 0x52, 0x05, 0xfd, 0x59, 0x91, 0xad, 0x01, 0x3b, 0x3e, 0x30, 0x3b, 0xed, 0x6d, 0xb1, 0x70, 0x51, - 0xc1, 0xff, 0x2e, 0x4a, 0x0f, 0xc9, 0x4f, 0x73, 0xd1, 0x61, 0x1d, 0x87, 0x1c, 0x24, 0x6f, 0xc1, - 0xad, 0x6a, 0xb7, 0xd7, 0xbe, 0xec, 0x7e, 0x7a, 0x4d, 0xb5, 0xca, 0xcd, 0xa9, 0x56, 0x73, 0xba, - 0x7b, 0x4d, 0x97, 0xfd, 0xde, 0x84, 0xda, 0x98, 0x6e, 0xc4, 0x95, 0x37, 0x5f, 0x82, 0x8c, 0xbf, - 0x21, 0x20, 0x5d, 0x7b, 0x39, 0x77, 0x41, 0x7b, 0x61, 0xfe, 0x82, 0xf6, 0x34, 0xf9, 0x7e, 0x21, - 0x4d, 0xbe, 0x7f, 0x08, 0x8b, 0xc4, 0x9a, 0x1c, 0xd7, 0x19, 0x2b, 0xad, 0x99, 0xa4, 0xc0, 0x06, - 0xb2, 0x28, 0x82, 0x2b, 0x75, 0x42, 0xa9, 0x1c, 0x92, 0x85, 0x14, 0xa5, 0xb6, 0x91, 0xd0, 0x34, - 0x88, 0x73, 0x44, 0x9a, 0x46, 0xd4, 0x83, 0x7d, 0x15, 0xf7, 0x50, 0xd1, 0x7a, 0x20, 0x38, 0xf6, - 0xf0, 0x10, 0x16, 0xf9, 0x55, 0xe8, 0xdb, 0x96, 0x37, 0xb1, 0x3f, 0x9f, 0xa2, 0x0b, 0xd7, 0x46, - 0x1d, 0xbe, 0x6a, 0x36, 0xb0, 0xe0, 0x10, 0xe1, 0xdb, 0x76, 0x68, 0x3f, 0xfc, 0x02, 0x2a, 0xda, - 0x6d, 0xc9, 0x6c, 0x0d, 0x96, 0x3e, 0xed, 0xf6, 0x0f, 0x3a, 0xbd, 0x9e, 0x75, 0x74, 0xbc, 0xf9, - 0xac, 0xf3, 0x99, 0xb5, 0xdb, 0xee, 0xed, 0x36, 0x6f, 0x89, 0x4d, 0x7b, 0xd0, 0xe9, 0xf5, 0x3b, - 0xdb, 0x09, 0x78, 0x86, 0xbd, 0x0e, 0xeb, 0xc7, 0x07, 0xc7, 0xbd, 0xce, 0xb6, 0x95, 0x56, 0x2f, - 0x2b, 0xa8, 0x54, 0x96, 0xa7, 0x54, 0xcf, 0x3d, 0xfc, 0x3e, 0xd4, 0x93, 0x57, 0x78, 0x32, 0x80, - 0x85, 0xbd, 0xce, 0xd3, 0xf6, 0xd6, 0x67, 0x74, 0x75, 0x5f, 0xaf, 0xdf, 0xee, 0x77, 0xb7, 0x2c, - 0x79, 0x55, 0x9f, 0xe0, 0x08, 0x19, 0x56, 0x81, 0x62, 0xfb, 0x60, 0x6b, 0xf7, 0xd0, 0xec, 0x35, - 0xb3, 0x0f, 0x3f, 0x82, 0xe6, 0xac, 0x3f, 0x2a, 0xe1, 0xc0, 0x7b, 0x91, 0xa7, 0xef, 0xe1, 0xbf, - 0xc8, 0x01, 0xc4, 0x09, 0x03, 0x82, 0xd5, 0x6c, 0xb7, 0xfb, 0xed, 0xbd, 0x43, 0x31, 0x0d, 0xf3, - 0xb0, 0x2f, 0x38, 0x88, 0xd9, 0xf9, 0xb8, 0x79, 0x2b, 0xb5, 0xe4, 0xf0, 0xa8, 0xdf, 0xcc, 0x88, - 0x15, 0xeb, 0x1e, 0x74, 0xfb, 0xdd, 0xf6, 0x9e, 0x65, 0x1e, 0x1e, 0x77, 0x0f, 0x9e, 0xd2, 0x9d, - 0x64, 0xc8, 0x65, 0x8f, 0x8f, 0x76, 0xcc, 0xc3, 0x83, 0xbe, 0xd5, 0xdb, 0x3d, 0xee, 0x6f, 0xe3, - 0x8d, 0x66, 0x5b, 0x66, 0xf7, 0x88, 0xda, 0xcc, 0xbf, 0x08, 0x41, 0x34, 0x5d, 0x10, 0x6b, 0xfe, - 0xf4, 0xb0, 0xd7, 0xeb, 0x1e, 0x59, 0x1f, 0x1f, 0x77, 0xcc, 0x6e, 0xa7, 0x87, 0x15, 0x17, 0x52, - 0xe0, 0x02, 0xbf, 0x28, 0x78, 0x73, 0x7f, 0xef, 0x13, 0xc9, 0x3c, 0x05, 0x6a, 0x29, 0x09, 0x12, - 0x58, 0x65, 0xc1, 0x53, 0x04, 0xf7, 0x49, 0x69, 0x19, 0x6e, 0x28, 0x13, 0xf5, 0x2a, 0x82, 0xaf, - 0xce, 0xbd, 0x0c, 0xac, 0x56, 0x4d, 0x2f, 0x12, 0xb5, 0x90, 0xe5, 0x46, 0x07, 0xd4, 0xf6, 0xb6, - 0x89, 0x15, 0xea, 0x73, 0x50, 0x81, 0xdb, 0x10, 0x2f, 0x4a, 0xb0, 0x27, 0x81, 0xd2, 0x54, 0x0f, - 0xa2, 0x64, 0xf1, 0xc9, 0xef, 0xe4, 0xa0, 0x4e, 0xc9, 0x5b, 0xf4, 0xb1, 0x2a, 0xee, 0xb3, 0x7d, - 0x28, 0xca, 0xaf, 0x9e, 0xb1, 0x95, 0xe8, 0xba, 0x28, 0xfd, 0x3b, 0x6b, 0xeb, 0xab, 0xb3, 0x60, - 0x29, 0x8e, 0x2d, 0xfd, 0xb5, 0x3f, 0xf9, 0x9f, 0x7f, 0x2f, 0x5b, 0x63, 0x95, 0x47, 0x17, 0xef, - 0x3d, 0x3a, 0xe3, 0x6e, 0x20, 0xda, 0xf8, 0xff, 0x01, 0xe2, 0x6f, 0x79, 0xb1, 0x56, 0xe4, 0x84, - 0x9a, 0xf9, 0xd0, 0xd9, 0xfa, 0xed, 0x94, 0x12, 0xd9, 0xee, 0x6d, 0x6c, 0x77, 0xc9, 0xa8, 0x8b, - 0x76, 0x1d, 0xd7, 0x09, 0xe9, 0xbb, 0x5e, 0x1f, 0x66, 0x1e, 0xb2, 0x21, 0x54, 0xf5, 0xaf, 0x6c, - 0x31, 0x25, 0x29, 0xa5, 0x7c, 0x27, 0x6c, 0xfd, 0x4e, 0x6a, 0x99, 0x92, 0x41, 0xb1, 0x8f, 0x15, - 0xa3, 0x29, 0xfa, 0x98, 0x22, 0x46, 0xdc, 0xcb, 0x88, 0xa4, 0xf2, 0xf8, 0x63, 0x5a, 0xec, 0x35, - 0x4d, 0xae, 0x9a, 0xfb, 0x94, 0xd7, 0xfa, 0xdd, 0x1b, 0x4a, 0x65, 0x5f, 0x77, 0xb1, 0xaf, 0x35, - 0x83, 0x89, 0xbe, 0x06, 0x88, 0xa3, 0x3e, 0xe5, 0xf5, 0x61, 0xe6, 0xe1, 0x93, 0xbf, 0x78, 0x00, - 0xe5, 0x28, 0x98, 0x93, 0xfd, 0x16, 0xd4, 0x12, 0xd9, 0x75, 0x4c, 0x4d, 0x23, 0x2d, 0x19, 0x6f, - 0xfd, 0xb5, 0xf4, 0x42, 0xd9, 0xf1, 0xeb, 0xd8, 0x71, 0x8b, 0xad, 0x8a, 0x8e, 0x65, 0xf6, 0xda, - 0x23, 0xcc, 0x86, 0xa5, 0xcb, 0xb7, 0x9e, 0x6b, 0xda, 0x07, 0x75, 0xf6, 0xda, 0xac, 0x46, 0x90, - 0xe8, 0xed, 0xee, 0x0d, 0xa5, 0xb2, 0xbb, 0xd7, 0xb0, 0xbb, 0x55, 0xb6, 0xac, 0x77, 0xa7, 0x42, - 0x2f, 0x19, 0xc7, 0x0b, 0xef, 0xf4, 0x6f, 0x4d, 0xb1, 0xbb, 0xf1, 0xf5, 0x64, 0x29, 0xdf, 0xa0, - 0x8a, 0x48, 0x64, 0xfe, 0x43, 0x54, 0x46, 0x0b, 0xbb, 0x62, 0x0c, 0x5f, 0x9f, 0xfe, 0xa9, 0x29, - 0x76, 0x02, 0x15, 0xed, 0xf3, 0x0c, 0xec, 0xf6, 0x8d, 0x9f, 0x92, 0x58, 0x5f, 0x4f, 0x2b, 0x4a, - 0x9b, 0x8a, 0xde, 0xfe, 0xa3, 0x53, 0xce, 0xd9, 0x6f, 0x40, 0x39, 0xba, 0xf4, 0x9f, 0xad, 0x69, - 0x1f, 0x61, 0xd0, 0x3f, 0x52, 0xb0, 0xde, 0x9a, 0x2f, 0x48, 0x23, 0x3e, 0xbd, 0x75, 0x41, 0x7c, - 0x9f, 0x42, 0x45, 0xbb, 0xd8, 0x3f, 0x9a, 0xc0, 0xfc, 0xc7, 0x03, 0xa2, 0x09, 0xa4, 0x7c, 0x07, - 0xc0, 0x58, 0xc4, 0x2e, 0x2a, 0xac, 0x8c, 0xf4, 0x1d, 0x5e, 0x79, 0x01, 0xdb, 0x83, 0x15, 0xa9, - 0x69, 0x9d, 0xf0, 0x2f, 0xf3, 0x1a, 0x52, 0x3e, 0xef, 0xf5, 0x38, 0xc3, 0x3e, 0x82, 0x92, 0xfa, - 0x7e, 0x03, 0x5b, 0x4d, 0xff, 0x0e, 0xc5, 0xfa, 0xda, 0x1c, 0x5c, 0xaa, 0x45, 0x9f, 0x01, 0xc4, - 0x5f, 0x11, 0x88, 0x98, 0xc4, 0xdc, 0x57, 0x09, 0x22, 0x0a, 0x98, 0xff, 0xe4, 0x80, 0xb1, 0x8a, - 0x13, 0x6c, 0x32, 0x64, 0x12, 0x2e, 0xbf, 0x54, 0xb7, 0x92, 0xfe, 0x08, 0x2a, 0xda, 0x87, 0x04, - 0xa2, 0xe5, 0x9b, 0xff, 0x08, 0x41, 0xb4, 0x7c, 0x29, 0xdf, 0x1d, 0x30, 0xd6, 0xb1, 0xf5, 0x65, - 0xa3, 0x21, 0x5a, 0x17, 0xa2, 0x96, 0x14, 0x79, 0xc4, 0x0b, 0x3a, 0x87, 0x5a, 0xe2, 0x6b, 0x01, - 0xd1, 0x0e, 0x4d, 0xfb, 0x16, 0x41, 0xb4, 0x43, 0x53, 0x3f, 0x30, 0xa0, 0xe8, 0xcc, 0x58, 0x14, - 0xfd, 0x5c, 0x20, 0x8a, 0xd6, 0xd3, 0x0f, 0xa1, 0xa2, 0xdd, 0xfc, 0x1f, 0xcd, 0x65, 0xfe, 0x23, - 0x03, 0xd1, 0x5c, 0xd2, 0x3e, 0x14, 0xb0, 0x8c, 0x7d, 0xd4, 0x0d, 0x24, 0x05, 0xbc, 0x57, 0x51, - 0xb4, 0xfd, 0x5b, 0x50, 0x4f, 0x7e, 0x0c, 0x20, 0xda, 0xfb, 0xa9, 0x5f, 0x15, 0x88, 0xf6, 0xfe, - 0x0d, 0x5f, 0x10, 0x90, 0x24, 0xfd, 0x70, 0x29, 0xea, 0xe4, 0xd1, 0x4f, 0x64, 0x5a, 0xca, 0x17, - 0xec, 0x63, 0xc1, 0xe0, 0xe4, 0xb5, 0x9e, 0x6c, 0x4d, 0xa3, 0x5a, 0xfd, 0x7e, 0xd0, 0x68, 0xbf, - 0xcc, 0xdd, 0x00, 0x9a, 0x24, 0x66, 0x6c, 0x9c, 0x3d, 0x85, 0xa5, 0x88, 0x98, 0xa3, 0x7b, 0x3a, - 0x83, 0x68, 0x0e, 0xa9, 0xb7, 0x81, 0xae, 0x37, 0x67, 0x4b, 0x1f, 0x67, 0xe8, 0xf8, 0xc3, 0xdb, - 0x11, 0xb5, 0xe3, 0x4f, 0xbf, 0xaa, 0x53, 0x3b, 0xfe, 0x12, 0x97, 0x28, 0xce, 0x1e, 0x7f, 0xa1, - 0x23, 0xda, 0x70, 0xa1, 0x31, 0x7b, 0x6b, 0xe6, 0xdd, 0x9b, 0xd2, 0xfe, 0xa9, 0xf9, 0xd7, 0x5f, - 0x7c, 0x2b, 0x40, 0x92, 0x15, 0x29, 0x6e, 0xfa, 0x48, 0x06, 0x9f, 0xb0, 0xdf, 0x84, 0xaa, 0x7e, - 0x81, 0x38, 0xd3, 0x79, 0xc2, 0x6c, 0x4f, 0x77, 0x52, 0xcb, 0x92, 0x54, 0xc2, 0xaa, 0x7a, 0x37, - 0xec, 0x13, 0x58, 0x8d, 0x96, 0x59, 0xcf, 0x5b, 0x0f, 0xd8, 0xbd, 0x94, 0x6c, 0xf6, 0xc4, 0x62, - 0xdf, 0xbe, 0x31, 0xdd, 0xfd, 0x71, 0x46, 0x50, 0x5f, 0xf2, 0x26, 0xe3, 0xf8, 0xe4, 0x49, 0xbb, - 0xc0, 0x39, 0x3e, 0x79, 0x52, 0xaf, 0x3f, 0x56, 0xd4, 0xc7, 0x96, 0x12, 0x6b, 0x44, 0x61, 0xb9, - 0xec, 0x87, 0xd0, 0xd0, 0x92, 0xf2, 0x7b, 0xd7, 0xee, 0x20, 0xda, 0x49, 0xf3, 0x57, 0xf1, 0xad, - 0xa7, 0xd9, 0x26, 0x8d, 0x35, 0x6c, 0x7f, 0xd1, 0x48, 0x2c, 0x8e, 0xd8, 0x45, 0x5b, 0x50, 0xd1, - 0x13, 0xfe, 0x5f, 0xd0, 0xee, 0x9a, 0x56, 0xa4, 0xdf, 0xfa, 0xf6, 0x38, 0xc3, 0xf6, 0xa0, 0x39, - 0x7b, 0x07, 0x55, 0xc4, 0x53, 0xd2, 0xee, 0xcd, 0x5a, 0x9f, 0x29, 0x4c, 0xdc, 0x5c, 0xc5, 0x8e, - 0x28, 0xb1, 0x23, 0xfa, 0x16, 0x96, 0xe7, 0xcf, 0x9e, 0xea, 0xc9, 0x6f, 0x64, 0x45, 0xad, 0xa5, - 0x7d, 0x1d, 0xed, 0x41, 0xe6, 0x71, 0x86, 0xfd, 0x5e, 0x06, 0xaa, 0x89, 0x7b, 0x5f, 0x12, 0xa1, - 0xf3, 0x33, 0xf3, 0x6c, 0xe9, 0x65, 0xfa, 0x44, 0x0d, 0x13, 0x17, 0x71, 0xef, 0xe1, 0x0f, 0x12, - 0x2f, 0xe9, 0x27, 0x09, 0xd7, 0xde, 0xc6, 0xec, 0xc7, 0xb2, 0xbe, 0x98, 0x45, 0xd0, 0x6f, 0x58, - 0xfc, 0xe2, 0x71, 0x86, 0xfd, 0xab, 0x0c, 0xd4, 0x93, 0x3e, 0xfb, 0x68, 0xba, 0xa9, 0xd1, 0x01, - 0x11, 0x29, 0xdd, 0xe0, 0xe8, 0xff, 0x21, 0x8e, 0xb2, 0xff, 0xd0, 0x4c, 0x8c, 0x52, 0xde, 0xc1, - 0xfd, 0x8b, 0x8d, 0x96, 0x7d, 0x48, 0xdf, 0xa6, 0x54, 0xa1, 0x4c, 0x6c, 0xfe, 0x5b, 0x86, 0x11, - 0xf9, 0xe9, 0x5f, 0xfe, 0xc3, 0x97, 0xf0, 0x23, 0xfa, 0x28, 0x94, 0x8a, 0x8c, 0x11, 0x54, 0xfc, - 0xaa, 0xf5, 0x8d, 0xb7, 0x70, 0x4e, 0xaf, 0x1b, 0xb7, 0x13, 0x73, 0x9a, 0x15, 0x3c, 0xda, 0x34, - 0x3a, 0xf9, 0xe1, 0xbe, 0xf8, 0xe4, 0x9c, 0xfb, 0x98, 0xdf, 0xcd, 0x83, 0x1c, 0xd3, 0x20, 0x25, - 0x7a, 0x62, 0xab, 0xbd, 0x62, 0x33, 0xc6, 0x43, 0x1c, 0xeb, 0x5b, 0xc6, 0xbd, 0x1b, 0xc7, 0xfa, - 0x08, 0xfd, 0xef, 0x62, 0xc4, 0x47, 0x00, 0x71, 0xa8, 0x21, 0x9b, 0x09, 0x78, 0x8b, 0x18, 0xd0, - 0x7c, 0x34, 0x62, 0x72, 0x3f, 0xab, 0xb8, 0x38, 0xd1, 0xe2, 0x6f, 0x10, 0x3b, 0x8d, 0x42, 0xf1, - 0x74, 0xe9, 0x2b, 0x19, 0x15, 0x98, 0x90, 0xbe, 0x66, 0xdb, 0x4f, 0x30, 0xd3, 0x28, 0xee, 0xee, - 0x18, 0x6a, 0x7b, 0x9e, 0xf7, 0x7c, 0x3a, 0x89, 0xc2, 0xdb, 0x93, 0x41, 0x31, 0xbb, 0x76, 0x70, - 0xbe, 0x3e, 0x33, 0x0b, 0xe3, 0x3e, 0x36, 0xb5, 0xce, 0x5a, 0x5a, 0x53, 0x8f, 0x7e, 0x12, 0xc7, - 0x37, 0x7e, 0xc1, 0x6c, 0x58, 0x8c, 0x78, 0x74, 0x1c, 0x43, 0x98, 0x6c, 0x26, 0xc1, 0x99, 0x67, - 0xbb, 0x48, 0xa8, 0x09, 0x6a, 0xb4, 0x8f, 0x02, 0xd5, 0xe6, 0xe3, 0x0c, 0x3b, 0x82, 0xea, 0x36, - 0x1f, 0x60, 0xa2, 0x3e, 0x86, 0x96, 0x2c, 0x25, 0xc2, 0x14, 0x28, 0x26, 0x65, 0xbd, 0x96, 0x00, - 0x26, 0xcf, 0xad, 0x89, 0x7d, 0xed, 0xf3, 0xcf, 0x1f, 0xfd, 0x44, 0x06, 0xad, 0x7c, 0xa1, 0xce, - 0x2d, 0x15, 0xd4, 0x93, 0x38, 0xb7, 0x66, 0xa2, 0x80, 0x12, 0xe7, 0xd6, 0x5c, 0x14, 0x50, 0x62, - 0xa9, 0x55, 0x50, 0x11, 0x1b, 0xc1, 0xe2, 0x5c, 0xe0, 0x50, 0x74, 0x64, 0xdd, 0x14, 0x6e, 0xb4, - 0x7e, 0xff, 0x66, 0x84, 0x64, 0x6f, 0x0f, 0x93, 0xbd, 0xf5, 0xa0, 0x46, 0x97, 0x3e, 0x9e, 0x70, - 0x4a, 0xd9, 0x9b, 0xb9, 0xef, 0x46, 0xcf, 0x07, 0x9c, 0x3d, 0x60, 0xb0, 0x2c, 0x29, 0xe1, 0x60, - 0xae, 0x1c, 0xfb, 0x0d, 0xa8, 0x3c, 0xe5, 0xa1, 0xca, 0xd1, 0x8b, 0x64, 0xec, 0x99, 0xa4, 0xbd, - 0xf5, 0x94, 0x14, 0xbf, 0x24, 0xcd, 0x60, 0x6b, 0x8f, 0xf8, 0xf0, 0x8c, 0x13, 0x73, 0xb2, 0x9c, - 0xe1, 0x17, 0xec, 0xd7, 0xb1, 0xf1, 0x28, 0x35, 0x7a, 0x55, 0x4b, 0xc2, 0xd2, 0x1b, 0x6f, 0xcc, - 0xc0, 0xd3, 0x5a, 0x76, 0xbd, 0x21, 0xd7, 0x64, 0x3d, 0x17, 0x2a, 0xda, 0x15, 0x0a, 0xd1, 0x06, - 0x9a, 0xbf, 0x32, 0x23, 0xda, 0x40, 0x29, 0x37, 0x2e, 0x18, 0x0f, 0xb0, 0x1f, 0x83, 0xdd, 0x8f, - 0xfb, 0xa1, 0x5b, 0x16, 0xe2, 0x9e, 0x1e, 0xfd, 0xc4, 0x1e, 0x87, 0x5f, 0xb0, 0x4f, 0xf1, 0x6a, - 0x75, 0x3d, 0x07, 0x31, 0x56, 0x1a, 0x66, 0xd3, 0x15, 0xa3, 0xc5, 0xd2, 0x8a, 0x92, 0x8a, 0x04, - 0x75, 0x85, 0x92, 0xdc, 0xfb, 0x00, 0xbd, 0xd0, 0x9b, 0x6c, 0xdb, 0x7c, 0xec, 0xb9, 0x31, 0xaf, - 0x8d, 0xb3, 0xe2, 0x62, 0xfe, 0xa5, 0xa5, 0xc6, 0xb1, 0x4f, 0x35, 0x2d, 0x2b, 0x91, 0xc6, 0xa9, - 0x88, 0xeb, 0xc6, 0xc4, 0xb9, 0x68, 0x41, 0x52, 0x92, 0xe7, 0x1e, 0x67, 0x58, 0x1b, 0x20, 0x8e, - 0x1c, 0x8b, 0x74, 0xa6, 0xb9, 0xa0, 0xb4, 0x88, 0xed, 0xa5, 0x84, 0x99, 0x1d, 0x41, 0x39, 0x0e, - 0xb9, 0x59, 0x8b, 0x6f, 0x84, 0x49, 0x04, 0xe8, 0x44, 0x27, 0xf8, 0x5c, 0xb8, 0x8b, 0xd1, 0xc4, - 0xa5, 0x02, 0x56, 0x12, 0x4b, 0x75, 0xca, 0x79, 0xc0, 0x1c, 0x58, 0xa2, 0x01, 0x46, 0xe2, 0x12, - 0x66, 0x73, 0x45, 0x37, 0xe8, 0xcf, 0x47, 0x9e, 0x44, 0xbb, 0x39, 0x35, 0x7e, 0x22, 0x61, 0xfa, - 0x11, 0xd4, 0x4a, 0x99, 0x64, 0x82, 0x35, 0x8f, 0x61, 0x71, 0xce, 0x45, 0x1f, 0x6d, 0xe9, 0x9b, - 0x62, 0x2e, 0xa2, 0x2d, 0x7d, 0xa3, 0x77, 0xdf, 0x58, 0xc1, 0x2e, 0x1b, 0x06, 0xa0, 0xaa, 0x77, - 0xe9, 0x84, 0x83, 0x73, 0xd1, 0xdd, 0x3f, 0xcf, 0xc0, 0x52, 0x8a, 0x13, 0x9e, 0xbd, 0xa1, 0xac, - 0x06, 0x37, 0x3a, 0xe8, 0xd7, 0x53, 0x9d, 0xb5, 0x46, 0x0f, 0xfb, 0xd9, 0x67, 0xcf, 0x12, 0x07, - 0x1b, 0xf9, 0x4a, 0xe5, 0xce, 0x7c, 0xa1, 0x50, 0x91, 0x2a, 0x51, 0x7c, 0x0e, 0x6b, 0x34, 0x90, - 0xf6, 0x68, 0x34, 0xe3, 0x48, 0x7e, 0x7d, 0xee, 0xdb, 0xf5, 0x09, 0xe7, 0xf8, 0xfa, 0xcd, 0xdf, - 0xb6, 0xbf, 0x41, 0x9c, 0xa6, 0xa1, 0xb2, 0x29, 0x34, 0x67, 0x1d, 0xb4, 0xec, 0xe6, 0xb6, 0xd6, - 0xef, 0x25, 0xf4, 0xdf, 0x14, 0xa7, 0xee, 0xd7, 0xb0, 0xb3, 0x7b, 0xc6, 0x7a, 0xda, 0xba, 0x90, - 0x4a, 0x2c, 0xde, 0xc7, 0x5f, 0x8d, 0xbc, 0xc9, 0x33, 0xf3, 0x54, 0x1d, 0xdc, 0xe4, 0xfb, 0x8e, - 0x34, 0xf0, 0x74, 0x67, 0xf4, 0xdb, 0xd8, 0xfd, 0x7d, 0xe3, 0x4e, 0x5a, 0xf7, 0x3e, 0x55, 0x21, - 0x5d, 0x7c, 0x6d, 0x76, 0x5f, 0xab, 0x11, 0xdc, 0x4f, 0x7b, 0xdf, 0x37, 0xea, 0x42, 0x33, 0x6b, - 0x7d, 0x0b, 0x65, 0xbb, 0xaa, 0xee, 0x3d, 0x8e, 0xb6, 0x4f, 0x8a, 0x9b, 0x3a, 0xda, 0x3e, 0x69, - 0xee, 0xe6, 0xa4, 0x5c, 0xa3, 0x1c, 0xcd, 0x1f, 0x66, 0x1e, 0x6e, 0xbe, 0xf3, 0xc3, 0xaf, 0x9d, - 0x39, 0xe1, 0xf9, 0xf4, 0x64, 0x63, 0xe0, 0x8d, 0x1f, 0x8d, 0x94, 0xb5, 0x51, 0xa6, 0x3c, 0x3f, - 0x1a, 0xb9, 0xc3, 0x47, 0xd8, 0xec, 0xc9, 0xc2, 0xc4, 0xf7, 0x42, 0xef, 0x5b, 0xff, 0x37, 0x00, - 0x00, 0xff, 0xff, 0x1f, 0xcc, 0xbd, 0x51, 0x9e, 0x83, 0x00, 0x00, + // 11395 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x8f, 0x24, 0x59, + 0x76, 0x10, 0xde, 0xf9, 0xaa, 0xcc, 0x3c, 0xf9, 0xac, 0x5b, 0xaf, 0xec, 0xea, 0xe9, 0xe9, 0x9e, + 0x98, 0xd9, 0x99, 0xde, 0x9e, 0xdd, 0xea, 0x9e, 0xde, 0x9d, 0xd9, 0xf5, 0xcc, 0xcf, 0xeb, 0xcd, + 0xaa, 0xca, 0xea, 0xca, 0xed, 0x7a, 0x4d, 0x64, 0xd6, 0x8c, 0x67, 0xfd, 0x33, 0xb1, 0x51, 0x99, + 0xb7, 0xaa, 0xc2, 0x9d, 0x19, 0x91, 0x13, 0x11, 0x59, 0x8f, 0x5d, 0x0d, 0x42, 0x08, 0x2c, 0x84, + 0x00, 0xc9, 0x02, 0x23, 0x61, 0xb0, 0x40, 0x20, 0x84, 0x10, 0x92, 0x65, 0x69, 0x8d, 0x04, 0x12, + 0xdf, 0xfd, 0x05, 0x64, 0x21, 0x9b, 0x2f, 0xc8, 0xb2, 0x64, 0x01, 0xcb, 0x37, 0xe4, 0x3f, 0x01, + 0xdd, 0x73, 0xee, 0x8d, 0xb8, 0x91, 0x19, 0xd5, 0xdd, 0xb3, 0x3b, 0xec, 0x97, 0xaa, 0x8c, 0x73, + 0xcf, 0x7d, 0xc6, 0xb9, 0xe7, 0x9e, 0xe7, 0x0d, 0x28, 0xfb, 0x93, 0xc1, 0xc6, 0xc4, 0xf7, 0x42, + 0x8f, 0x15, 0x46, 0xae, 0x3f, 0x19, 0xac, 0xbf, 0x76, 0xe6, 0x79, 0x67, 0x23, 0xfe, 0xc8, 0x9e, + 0x38, 0x8f, 0x6c, 0xd7, 0xf5, 0x42, 0x3b, 0x74, 0x3c, 0x37, 0x20, 0x24, 0xe3, 0x47, 0x50, 0x7f, + 0xca, 0xdd, 0x1e, 0xe7, 0x43, 0x93, 0x7f, 0x3e, 0xe5, 0x41, 0xc8, 0xde, 0x85, 0x45, 0x9b, 0xff, + 0x98, 0xf3, 0xa1, 0x35, 0xb1, 0x83, 0x60, 0x72, 0xee, 0xdb, 0x01, 0x6f, 0x65, 0xee, 0x67, 0x1e, + 0x54, 0xcd, 0x26, 0x15, 0x1c, 0x45, 0x70, 0xf6, 0x06, 0x54, 0x03, 0x81, 0xca, 0xdd, 0xd0, 0xf7, + 0x26, 0xd7, 0xad, 0x2c, 0xe2, 0x55, 0x04, 0xac, 0x43, 0x20, 0x63, 0x04, 0x8d, 0xa8, 0x87, 0x60, + 0xe2, 0xb9, 0x01, 0x67, 0x8f, 0x61, 0x79, 0xe0, 0x4c, 0xce, 0xb9, 0x6f, 0x61, 0xe5, 0xb1, 0xcb, + 0xc7, 0x9e, 0xeb, 0x0c, 0x5a, 0x99, 0xfb, 0xb9, 0x07, 0x65, 0x93, 0x51, 0x99, 0xa8, 0xb1, 0x2f, + 0x4b, 0xd8, 0x3b, 0xd0, 0xe0, 0x2e, 0xc1, 0xf9, 0x10, 0x6b, 0xc9, 0xae, 0xea, 0x31, 0x58, 0x54, + 0x30, 0xfe, 0x4e, 0x16, 0x16, 0xbb, 0xae, 0x13, 0x7e, 0x6a, 0x8f, 0x46, 0x3c, 0x54, 0x73, 0x7a, + 0x07, 0x1a, 0x97, 0x08, 0xc0, 0x39, 0x5d, 0x7a, 0xfe, 0x50, 0xce, 0xa8, 0x4e, 0xe0, 0x23, 0x09, + 0xbd, 0x71, 0x64, 0xd9, 0x1b, 0x47, 0x96, 0xba, 0x5c, 0xb9, 0x1b, 0x96, 0xeb, 0x1d, 0x68, 0xf8, + 0x7c, 0xe0, 0x5d, 0x70, 0xff, 0xda, 0xba, 0x74, 0xdc, 0xa1, 0x77, 0xd9, 0xca, 0xdf, 0xcf, 0x3c, + 0x28, 0x98, 0x75, 0x05, 0xfe, 0x14, 0xa1, 0x6c, 0x13, 0x1a, 0x83, 0x73, 0xdb, 0x75, 0xf9, 0xc8, + 0x3a, 0xb1, 0x07, 0xcf, 0xa7, 0x93, 0xa0, 0x55, 0xb8, 0x9f, 0x79, 0x50, 0x79, 0x72, 0x7b, 0x03, + 0xdf, 0xea, 0xc6, 0xd6, 0xb9, 0xed, 0x6e, 0x62, 0x49, 0xcf, 0xb5, 0x27, 0xc1, 0xb9, 0x17, 0x9a, + 0x75, 0x59, 0x83, 0xc0, 0x81, 0xb1, 0x0c, 0x4c, 0x5f, 0x09, 0x5a, 0x7b, 0xe3, 0xdf, 0x65, 0x60, + 0xe9, 0xd8, 0x1d, 0x79, 0x83, 0xe7, 0x3f, 0xe7, 0x12, 0xa5, 0xcc, 0x21, 0xfb, 0xaa, 0x73, 0xc8, + 0x7d, 0xd9, 0x39, 0xac, 0xc2, 0x72, 0x72, 0xb0, 0x72, 0x16, 0x1c, 0x56, 0x44, 0xed, 0x33, 0xae, + 0x86, 0xa5, 0xa6, 0xf1, 0x75, 0x68, 0x0e, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x79, 0x34, 0x24, 0x3c, + 0x9a, 0xc8, 0x1b, 0x50, 0x75, 0xf9, 0x65, 0x8c, 0x26, 0x69, 0xd7, 0xe5, 0x97, 0x0a, 0xc5, 0x68, + 0xc1, 0xea, 0x6c, 0x37, 0x72, 0x00, 0x3f, 0xcb, 0x40, 0xfe, 0x38, 0xbc, 0xf2, 0xd8, 0xfb, 0x50, + 0xb5, 0x87, 0x43, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x4f, 0x68, 0xa7, 0xd4, 0x9f, 0x30, 0x39, 0xc5, + 0x36, 0x15, 0xf5, 0xaf, 0x27, 0xdc, 0xac, 0xd8, 0xf1, 0x03, 0x6b, 0x41, 0x51, 0x3e, 0x62, 0xbf, + 0x65, 0x53, 0x3d, 0xb2, 0xbb, 0x00, 0xf6, 0xd8, 0x9b, 0xba, 0xa1, 0x15, 0xd8, 0x21, 0xae, 0x58, + 0xce, 0x2c, 0x13, 0xa4, 0x67, 0x87, 0xec, 0x0e, 0x94, 0x27, 0xcf, 0xad, 0x60, 0xe0, 0x3b, 0x93, + 0x10, 0x89, 0xa7, 0x6c, 0x96, 0x26, 0xcf, 0x7b, 0xf8, 0xcc, 0xde, 0x85, 0x92, 0x37, 0x0d, 0x27, + 0x9e, 0xe3, 0x86, 0x92, 0x5e, 0x1a, 0x72, 0x20, 0x87, 0xd3, 0xf0, 0x48, 0x80, 0xcd, 0x08, 0x81, + 0xbd, 0x05, 0xb5, 0x81, 0xe7, 0x9e, 0x3a, 0xfe, 0x98, 0x38, 0x42, 0x6b, 0x01, 0xfb, 0x4a, 0x02, + 0x8d, 0x3f, 0xcc, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, 0x41, 0x31, 0xbc, + 0xb2, 0xce, 0xed, 0xe0, 0x1c, 0xa7, 0x5a, 0x36, 0x17, 0xc2, 0xab, 0x5d, 0x3b, 0x38, 0x67, 0xab, + 0xb0, 0x40, 0xa3, 0xc4, 0x09, 0xe5, 0x4c, 0xf9, 0x24, 0x36, 0x88, 0x3b, 0x1d, 0x5b, 0xc9, 0xae, + 0x72, 0x48, 0x31, 0x4d, 0x77, 0x3a, 0xde, 0xd2, 0xe1, 0x62, 0xf2, 0x27, 0xe2, 0x75, 0x53, 0x07, + 0x34, 0xbd, 0x32, 0x42, 0xb0, 0x8f, 0x37, 0xa0, 0x2a, 0x8b, 0xb9, 0x73, 0x76, 0x4e, 0x73, 0x2c, + 0x98, 0x15, 0x42, 0x40, 0x90, 0x68, 0x21, 0x74, 0xc6, 0xdc, 0x0a, 0x42, 0x7b, 0x3c, 0x91, 0x53, + 0x2a, 0x0b, 0x48, 0x4f, 0x00, 0xb0, 0xd8, 0x0b, 0xed, 0x91, 0x75, 0xca, 0x79, 0xd0, 0x2a, 0xca, + 0x62, 0x01, 0xd9, 0xe1, 0x3c, 0x60, 0x5f, 0x83, 0xfa, 0x90, 0x07, 0xa1, 0x25, 0x5f, 0x06, 0x0f, + 0x5a, 0x25, 0xdc, 0xf9, 0x35, 0x01, 0x6d, 0x2b, 0x20, 0x7b, 0x0d, 0xc0, 0xb7, 0x2f, 0x2d, 0xb1, + 0x10, 0xfc, 0xaa, 0x55, 0xa6, 0xb7, 0xe0, 0xdb, 0x97, 0xfd, 0xab, 0x5d, 0x7e, 0x25, 0xa8, 0xe6, + 0x29, 0x0f, 0xb5, 0x45, 0x0b, 0x24, 0x75, 0x1a, 0x7b, 0xc0, 0x34, 0xf0, 0x36, 0x0f, 0x6d, 0x67, + 0x14, 0xb0, 0x0f, 0xa0, 0x1a, 0x6a, 0xc8, 0xc8, 0x06, 0x2b, 0x11, 0x09, 0x69, 0x15, 0xcc, 0x04, + 0x9e, 0x71, 0x0e, 0xa5, 0x1d, 0xce, 0xf7, 0x9c, 0xb1, 0x13, 0xb2, 0x55, 0x28, 0x9c, 0x3a, 0x57, + 0x9c, 0x88, 0x3d, 0xb7, 0x7b, 0xcb, 0xa4, 0x47, 0x76, 0x0f, 0x00, 0x7f, 0x58, 0xe3, 0x88, 0x9a, + 0x76, 0x6f, 0x99, 0x65, 0x84, 0xed, 0x07, 0x76, 0xc8, 0xd6, 0xa1, 0x38, 0xe1, 0xfe, 0x80, 0xab, + 0xf7, 0xb6, 0x7b, 0xcb, 0x54, 0x80, 0xcd, 0x22, 0x14, 0x46, 0xa2, 0x75, 0xe3, 0x8f, 0x0b, 0x50, + 0xe9, 0x71, 0x37, 0xda, 0x65, 0x0c, 0xf2, 0x62, 0x41, 0xe4, 0xce, 0xc2, 0xdf, 0xec, 0x4d, 0xa8, + 0xe0, 0xd2, 0x05, 0xa1, 0xef, 0xb8, 0x67, 0x44, 0xd5, 0x9b, 0xd9, 0x56, 0xc6, 0x04, 0x01, 0xee, + 0x21, 0x94, 0x35, 0x21, 0x67, 0x8f, 0x15, 0x55, 0x8b, 0x9f, 0xec, 0x36, 0x94, 0xec, 0x71, 0x48, + 0xc3, 0xab, 0x22, 0xb8, 0x68, 0x8f, 0x43, 0x1c, 0xda, 0x1b, 0x50, 0x9d, 0xd8, 0xd7, 0x63, 0xb1, + 0x97, 0x23, 0x72, 0xa8, 0x9a, 0x15, 0x09, 0x43, 0x82, 0x78, 0x02, 0x4b, 0x3a, 0x8a, 0xea, 0xbc, + 0x10, 0x75, 0xbe, 0xa8, 0x61, 0xcb, 0x31, 0xbc, 0x03, 0x0d, 0x55, 0xc7, 0xa7, 0xf9, 0x20, 0x99, + 0x94, 0xcd, 0xba, 0x04, 0xab, 0x59, 0x3e, 0x80, 0xe6, 0xa9, 0xe3, 0xda, 0x23, 0x6b, 0x30, 0x0a, + 0x2f, 0xac, 0x21, 0x1f, 0x85, 0x36, 0x52, 0x4c, 0xc1, 0xac, 0x23, 0x7c, 0x6b, 0x14, 0x5e, 0x6c, + 0x0b, 0x28, 0xfb, 0x06, 0x94, 0x4f, 0x39, 0xb7, 0x70, 0xb1, 0x5a, 0xa5, 0xc4, 0xc6, 0x53, 0x6f, + 0xc8, 0x2c, 0x9d, 0xaa, 0x77, 0xf5, 0x0d, 0x68, 0x7a, 0xd3, 0xf0, 0xcc, 0x73, 0xdc, 0x33, 0x4b, + 0xf0, 0x3b, 0xcb, 0x19, 0x22, 0x0d, 0xe5, 0x37, 0xb3, 0x8f, 0x33, 0x66, 0x5d, 0x95, 0x09, 0xce, + 0xd3, 0x1d, 0xb2, 0xb7, 0xa1, 0x31, 0xb2, 0x83, 0xd0, 0x3a, 0xf7, 0x26, 0xd6, 0x64, 0x7a, 0xf2, + 0x9c, 0x5f, 0xb7, 0x6a, 0xb8, 0x10, 0x35, 0x01, 0xde, 0xf5, 0x26, 0x47, 0x08, 0x14, 0x94, 0x8d, + 0xe3, 0xa4, 0x41, 0xc0, 0xfd, 0xcc, 0x83, 0x9a, 0x59, 0x16, 0x10, 0xea, 0xf4, 0x33, 0x58, 0xc2, + 0xd7, 0x33, 0x98, 0x06, 0xa1, 0x37, 0xb6, 0x04, 0xaf, 0xf6, 0x87, 0x41, 0xab, 0x82, 0xb4, 0xf6, + 0x75, 0x39, 0x58, 0xed, 0x1d, 0x6f, 0x6c, 0xf3, 0x20, 0xdc, 0x42, 0x64, 0x93, 0x70, 0xc5, 0x81, + 0x7e, 0x6d, 0x2e, 0x0e, 0x67, 0xe1, 0xec, 0x1b, 0xc0, 0xec, 0xd1, 0xc8, 0xbb, 0xb4, 0x02, 0x3e, + 0x3a, 0xb5, 0xe4, 0x22, 0xb6, 0xea, 0xf7, 0x33, 0x0f, 0x4a, 0x66, 0x13, 0x4b, 0x7a, 0x7c, 0x74, + 0x7a, 0x44, 0x70, 0xf6, 0x01, 0xe0, 0x66, 0xb2, 0x4e, 0xb9, 0x1d, 0x4e, 0x7d, 0x1e, 0xb4, 0x1a, + 0xf7, 0x73, 0x0f, 0xea, 0x4f, 0x16, 0xa3, 0xf5, 0x42, 0xf0, 0xa6, 0x13, 0x9a, 0x55, 0x81, 0x27, + 0x9f, 0x83, 0xf5, 0x6d, 0x58, 0x4d, 0x1f, 0x92, 0x20, 0x2a, 0xb1, 0x2a, 0x82, 0x18, 0xf3, 0xa6, + 0xf8, 0xc9, 0x96, 0xa1, 0x70, 0x61, 0x8f, 0xa6, 0x5c, 0xf2, 0x74, 0x7a, 0xf8, 0x30, 0xfb, 0xdd, + 0x8c, 0xf1, 0x47, 0x19, 0xa8, 0xd2, 0x2c, 0xa5, 0x2c, 0xf2, 0x26, 0xd4, 0x14, 0x35, 0x70, 0xdf, + 0xf7, 0x7c, 0xc9, 0xd5, 0x14, 0xe5, 0x75, 0x04, 0x4c, 0x9c, 0x2a, 0x0a, 0x69, 0xe2, 0x73, 0x67, + 0x6c, 0x9f, 0xa9, 0xa6, 0x15, 0x29, 0x1d, 0x49, 0x30, 0x7b, 0x2f, 0x6e, 0xcf, 0xf7, 0xa6, 0x21, + 0x97, 0x67, 0x5e, 0x55, 0x4e, 0xcf, 0x14, 0xb0, 0xa8, 0x75, 0x7c, 0x7a, 0x05, 0x3a, 0x37, 0x7e, + 0x37, 0x03, 0x4c, 0x0c, 0xbb, 0xef, 0x51, 0x03, 0x92, 0x42, 0x67, 0x6b, 0x66, 0x5e, 0x79, 0x87, + 0x64, 0x5f, 0xb4, 0x43, 0x0c, 0x28, 0xd0, 0xd8, 0xf3, 0x29, 0x63, 0xa7, 0xa2, 0x1f, 0xe4, 0x4b, + 0xb9, 0x66, 0xde, 0xf8, 0xef, 0x39, 0x58, 0xde, 0xa2, 0x23, 0xbb, 0x3d, 0x18, 0xf0, 0x49, 0xb4, + 0x77, 0xee, 0x41, 0xc5, 0xf5, 0x86, 0x5c, 0x51, 0x2c, 0x0d, 0x0c, 0x04, 0x48, 0x23, 0xd7, 0x73, + 0xdb, 0x71, 0x69, 0xe0, 0xb4, 0x98, 0x65, 0x84, 0xe0, 0xb0, 0xdf, 0x86, 0xc6, 0x84, 0xbb, 0x43, + 0x7d, 0x8b, 0x90, 0x50, 0x55, 0x93, 0x60, 0xb9, 0x3b, 0xee, 0x41, 0xe5, 0x74, 0x4a, 0x78, 0x82, + 0xb1, 0xe4, 0x91, 0x06, 0x40, 0x82, 0xda, 0xc4, 0x5f, 0x26, 0xd3, 0xe0, 0x1c, 0x4b, 0x0b, 0x58, + 0x5a, 0x14, 0xcf, 0xa2, 0xe8, 0x2e, 0xc0, 0x70, 0x1a, 0x84, 0x72, 0xc7, 0x2c, 0x60, 0x61, 0x59, + 0x40, 0x68, 0xc7, 0x7c, 0x13, 0x96, 0xc6, 0xf6, 0x95, 0x85, 0xb4, 0x63, 0x39, 0xae, 0x75, 0x3a, + 0xc2, 0x33, 0xa7, 0x88, 0x78, 0xcd, 0xb1, 0x7d, 0xf5, 0x89, 0x28, 0xe9, 0xba, 0x3b, 0x08, 0x17, + 0x6c, 0x45, 0x89, 0x3b, 0x3e, 0x0f, 0xb8, 0x7f, 0xc1, 0x91, 0x13, 0xe4, 0x23, 0x99, 0xc6, 0x24, + 0xa8, 0x18, 0xd1, 0x58, 0xcc, 0x3b, 0x1c, 0x0d, 0x68, 0xdb, 0x9b, 0xc5, 0xb1, 0xe3, 0xee, 0x86, + 0xa3, 0x81, 0x38, 0x57, 0x04, 0x1f, 0x99, 0x70, 0xdf, 0x7a, 0x7e, 0x89, 0x7b, 0x38, 0x8f, 0x7c, + 0xe3, 0x88, 0xfb, 0xcf, 0x2e, 0xc5, 0xd1, 0x3f, 0x08, 0x90, 0x11, 0xd9, 0xd7, 0xad, 0x0a, 0x6e, + 0xf0, 0xd2, 0x20, 0x10, 0x2c, 0xc8, 0xbe, 0x16, 0x9b, 0x50, 0x8c, 0xd6, 0xc6, 0xb7, 0xc0, 0x87, + 0xd8, 0x7c, 0x80, 0x1c, 0xb5, 0x86, 0x83, 0x6d, 0xcb, 0x02, 0xd1, 0x4f, 0x20, 0xa8, 0x5e, 0x0d, + 0xf6, 0x74, 0x64, 0x9f, 0x05, 0xc8, 0x52, 0x6a, 0x66, 0x55, 0x02, 0x77, 0x04, 0xcc, 0xf8, 0x94, + 0x84, 0x2c, 0xed, 0xdd, 0xca, 0x3d, 0x23, 0x8e, 0x7a, 0x84, 0xe0, 0x7b, 0x2d, 0x99, 0xf2, 0x29, + 0xed, 0xa5, 0x65, 0x53, 0x5e, 0x9a, 0xf1, 0xfb, 0x19, 0xa8, 0xca, 0x96, 0x51, 0x28, 0x61, 0x1b, + 0xc0, 0xd4, 0x5b, 0x0c, 0xaf, 0x9c, 0xa1, 0x75, 0x72, 0x1d, 0xf2, 0x80, 0x88, 0x66, 0xf7, 0x96, + 0xd9, 0x94, 0x65, 0xfd, 0x2b, 0x67, 0xb8, 0x29, 0x4a, 0xd8, 0x43, 0x68, 0x26, 0xf0, 0x83, 0xd0, + 0x27, 0x8a, 0xde, 0xbd, 0x65, 0xd6, 0x35, 0xec, 0x5e, 0xe8, 0x8b, 0x3d, 0x22, 0x44, 0x9e, 0x69, + 0x68, 0x39, 0xee, 0x90, 0x5f, 0x21, 0x19, 0xd5, 0xcc, 0x0a, 0xc1, 0xba, 0x02, 0xb4, 0x59, 0x87, + 0xaa, 0xde, 0x9c, 0x71, 0x06, 0x25, 0x25, 0x2f, 0xa1, 0xc0, 0x30, 0x33, 0x24, 0xb3, 0x1c, 0x46, + 0x23, 0xb9, 0x0d, 0xa5, 0xe4, 0x08, 0xcc, 0x62, 0xf8, 0xca, 0x1d, 0x1b, 0xdf, 0x83, 0xe6, 0x9e, + 0x20, 0x1e, 0x57, 0x10, 0xab, 0x94, 0xff, 0x56, 0x61, 0x41, 0xdb, 0x34, 0x65, 0x53, 0x3e, 0x89, + 0x33, 0xf7, 0xdc, 0x0b, 0x42, 0xd9, 0x0b, 0xfe, 0x36, 0xfe, 0x38, 0x03, 0xac, 0x13, 0x84, 0xce, + 0xd8, 0x0e, 0xf9, 0x0e, 0x8f, 0xd8, 0xc2, 0x21, 0x54, 0x45, 0x6b, 0x7d, 0xaf, 0x4d, 0x02, 0x19, + 0x09, 0x14, 0xef, 0xca, 0x6d, 0x3c, 0x5f, 0x61, 0x43, 0xc7, 0x26, 0x36, 0x9f, 0x68, 0x40, 0xec, + 0xb2, 0xd0, 0xf6, 0xcf, 0x78, 0x88, 0x62, 0x9c, 0x94, 0xf7, 0x81, 0x40, 0x42, 0x80, 0x5b, 0xff, + 0x35, 0x58, 0x9c, 0x6b, 0x43, 0xe7, 0xcb, 0xe5, 0x14, 0xbe, 0x9c, 0xd3, 0xf9, 0xb2, 0x05, 0x4b, + 0x89, 0x71, 0x49, 0x4a, 0x5b, 0x83, 0xa2, 0xd8, 0x10, 0x42, 0x38, 0xc8, 0x90, 0x54, 0x79, 0xca, + 0xb9, 0x10, 0x83, 0x1f, 0xc1, 0xf2, 0x29, 0xe7, 0xbe, 0x1d, 0x62, 0x21, 0xee, 0x18, 0xf1, 0x86, + 0x64, 0xc3, 0x8b, 0xb2, 0xac, 0x67, 0x87, 0x47, 0xdc, 0x17, 0x6f, 0xca, 0xf8, 0x1f, 0x19, 0x68, + 0x08, 0x0e, 0xba, 0x6f, 0xbb, 0xd7, 0x6a, 0x9d, 0xf6, 0x52, 0xd7, 0xe9, 0x81, 0x76, 0x18, 0x6a, + 0xd8, 0x5f, 0x76, 0x91, 0x72, 0xb3, 0x8b, 0xc4, 0xee, 0x43, 0x35, 0x31, 0xd6, 0x02, 0x8e, 0x15, + 0x82, 0x68, 0x90, 0xbf, 0xf8, 0x32, 0xbe, 0x0d, 0xcd, 0x78, 0xd8, 0x72, 0x0d, 0x19, 0xe4, 0x05, + 0x49, 0xca, 0x06, 0xf0, 0xb7, 0xf1, 0xcf, 0x32, 0x84, 0xb8, 0xe5, 0x39, 0x91, 0x74, 0x2a, 0x10, + 0x85, 0xdc, 0xab, 0x10, 0xc5, 0xef, 0x1b, 0xa5, 0xfa, 0x5f, 0x7c, 0xb2, 0x62, 0xeb, 0x04, 0xdc, + 0x1d, 0x5a, 0xf6, 0x68, 0x84, 0xcc, 0xb7, 0x64, 0x16, 0xc5, 0x73, 0x7b, 0x34, 0x32, 0xde, 0x81, + 0x45, 0x6d, 0x74, 0x2f, 0x98, 0xc7, 0x01, 0xb0, 0x3d, 0x27, 0x08, 0x8f, 0xdd, 0x60, 0xa2, 0x09, + 0x6e, 0x77, 0xa0, 0x2c, 0x38, 0xac, 0x18, 0x19, 0x6d, 0xd9, 0x82, 0x29, 0x58, 0xae, 0x18, 0x57, + 0x80, 0x85, 0xf6, 0x95, 0x2c, 0xcc, 0xca, 0x42, 0xfb, 0x0a, 0x0b, 0x8d, 0xef, 0xc2, 0x52, 0xa2, + 0x3d, 0xd9, 0xf5, 0x1b, 0x50, 0x98, 0x86, 0x57, 0x9e, 0x12, 0xcd, 0x2b, 0x92, 0x42, 0x84, 0x02, + 0x68, 0x52, 0x89, 0xf1, 0x11, 0x2c, 0x1e, 0xf0, 0x4b, 0xb9, 0x89, 0xd5, 0x40, 0xde, 0x86, 0xfc, + 0x4b, 0x94, 0x42, 0x2c, 0x37, 0x36, 0x80, 0xe9, 0x95, 0x65, 0xaf, 0x9a, 0x8e, 0x98, 0x49, 0xe8, + 0x88, 0xc6, 0xdb, 0xc0, 0x7a, 0xce, 0x99, 0xbb, 0xcf, 0x83, 0xc0, 0x3e, 0x8b, 0xb6, 0x7d, 0x13, + 0x72, 0xe3, 0xe0, 0x4c, 0xf2, 0x28, 0xf1, 0xd3, 0xf8, 0x16, 0x2c, 0x25, 0xf0, 0x64, 0xc3, 0xaf, + 0x41, 0x39, 0x70, 0xce, 0x5c, 0x14, 0xac, 0x64, 0xd3, 0x31, 0xc0, 0xd8, 0x81, 0xe5, 0x4f, 0xb8, + 0xef, 0x9c, 0x5e, 0xbf, 0xac, 0xf9, 0x64, 0x3b, 0xd9, 0xd9, 0x76, 0x3a, 0xb0, 0x32, 0xd3, 0x8e, + 0xec, 0x9e, 0xc8, 0x57, 0xbe, 0xc9, 0x92, 0x49, 0x0f, 0x1a, 0xdf, 0xcb, 0xea, 0x7c, 0xcf, 0x38, + 0x06, 0xb6, 0xe5, 0xb9, 0x2e, 0x1f, 0x84, 0x47, 0x9c, 0xfb, 0xb1, 0x95, 0x2a, 0xa6, 0xd5, 0xca, + 0x93, 0x35, 0xb9, 0xb2, 0xb3, 0xcc, 0x54, 0x12, 0x31, 0x83, 0xfc, 0x84, 0xfb, 0x63, 0x6c, 0xb8, + 0x64, 0xe2, 0x6f, 0x63, 0x05, 0x96, 0x12, 0xcd, 0x4a, 0xbd, 0xfe, 0x31, 0xac, 0x6c, 0x3b, 0xc1, + 0x60, 0xbe, 0xc3, 0x35, 0x28, 0x4e, 0xa6, 0x27, 0x56, 0x92, 0x2f, 0x3f, 0xe3, 0xd7, 0x42, 0xdb, + 0x9b, 0xad, 0x21, 0xdb, 0xfa, 0x5b, 0x19, 0xc8, 0xef, 0xf6, 0xf7, 0xb6, 0xd8, 0x3a, 0x94, 0x1c, + 0x77, 0xe0, 0x8d, 0x85, 0xe0, 0x45, 0x73, 0x8e, 0x9e, 0x6f, 0xdc, 0x60, 0x77, 0xa0, 0x8c, 0xf2, + 0x9a, 0x50, 0x6d, 0xa5, 0xe8, 0x53, 0x12, 0x80, 0x3d, 0x6f, 0xf0, 0x5c, 0xe8, 0xd4, 0xfc, 0x6a, + 0xe2, 0xf8, 0xa8, 0x35, 0x2b, 0x65, 0x38, 0x4f, 0x67, 0x7d, 0x5c, 0x40, 0x1a, 0xb1, 0xf1, 0x1f, + 0x4b, 0x50, 0x94, 0xa7, 0x2d, 0x9d, 0xdc, 0xa1, 0x73, 0xc1, 0xe3, 0x93, 0x5b, 0x3c, 0x09, 0x79, + 0xc0, 0xe7, 0x63, 0x2f, 0x8c, 0x04, 0x36, 0x7a, 0x07, 0x55, 0x02, 0x4a, 0x91, 0x4d, 0x13, 0x1a, + 0xc8, 0xc4, 0x90, 0x23, 0xa4, 0x81, 0x7e, 0x94, 0xdf, 0x81, 0xa2, 0x3a, 0xfb, 0xf3, 0x91, 0x4e, + 0xb3, 0x30, 0x20, 0x69, 0x6d, 0x1d, 0x4a, 0x03, 0x7b, 0x62, 0x0f, 0x9c, 0xf0, 0x5a, 0x32, 0x84, + 0xe8, 0x59, 0xb4, 0x3e, 0xf2, 0x06, 0xf6, 0xc8, 0x3a, 0xb1, 0x47, 0xb6, 0x3b, 0xe0, 0x52, 0x77, + 0xaf, 0x22, 0x70, 0x93, 0x60, 0x42, 0x3f, 0x97, 0xe3, 0x54, 0x58, 0xa4, 0xc2, 0xcb, 0xd1, 0x2b, + 0x34, 0x21, 0x5c, 0x7a, 0xe3, 0xb1, 0x23, 0xb4, 0x0c, 0x12, 0xc3, 0x72, 0x66, 0x99, 0x20, 0x3b, + 0x1c, 0x67, 0x2b, 0x8b, 0x2f, 0x69, 0xe9, 0xca, 0xd4, 0x15, 0x01, 0x3f, 0x25, 0x43, 0xc2, 0xbc, + 0x2c, 0x96, 0xd3, 0x64, 0xb1, 0x77, 0x61, 0x71, 0xea, 0x06, 0x3c, 0x0c, 0x47, 0x7c, 0x18, 0x8d, + 0xa5, 0x82, 0x48, 0xcd, 0xa8, 0x40, 0x0d, 0x67, 0x03, 0x96, 0xc8, 0xe8, 0x10, 0xd8, 0xa1, 0x17, + 0x9c, 0x3b, 0x81, 0x15, 0x08, 0x0d, 0x89, 0xd4, 0xdd, 0x45, 0x2c, 0xea, 0xc9, 0x92, 0x1e, 0xa9, + 0x48, 0x6b, 0x33, 0xf8, 0x3e, 0x1f, 0x70, 0xe7, 0x82, 0x0f, 0x51, 0x4e, 0xcb, 0x99, 0x2b, 0x89, + 0x3a, 0xa6, 0x2c, 0x44, 0xa1, 0x7b, 0x3a, 0xb6, 0xa6, 0x93, 0xa1, 0x2d, 0x84, 0x95, 0x3a, 0x09, + 0xc3, 0xee, 0x74, 0x7c, 0x4c, 0x10, 0xf6, 0x18, 0x94, 0x24, 0x26, 0xe5, 0xc3, 0x46, 0x82, 0x9f, + 0x09, 0x62, 0x35, 0xab, 0x12, 0x83, 0x04, 0xc5, 0x84, 0xcc, 0xd9, 0x9c, 0x91, 0x39, 0x5b, 0x50, + 0x9c, 0xf8, 0xce, 0x85, 0x1d, 0xf2, 0xd6, 0x22, 0x31, 0x70, 0xf9, 0x28, 0x38, 0x83, 0xe3, 0x3a, + 0xa1, 0x63, 0x87, 0x9e, 0xdf, 0x62, 0x58, 0x16, 0x03, 0xd8, 0x43, 0x58, 0x44, 0x1a, 0x09, 0x42, + 0x3b, 0x9c, 0x06, 0x52, 0x02, 0x5d, 0x42, 0x62, 0x42, 0x19, 0xba, 0x87, 0x70, 0x14, 0x42, 0xd9, + 0xb7, 0x60, 0x95, 0xc8, 0x02, 0x6b, 0x48, 0xc9, 0x1a, 0x05, 0x82, 0x65, 0x5c, 0x8a, 0x25, 0x2c, + 0x15, 0xf4, 0x2d, 0xe5, 0x6b, 0x21, 0x1d, 0xbc, 0x0f, 0x6b, 0x92, 0x4c, 0xe6, 0x6a, 0xad, 0x60, + 0xad, 0x65, 0x2a, 0x9e, 0xa9, 0xb6, 0x01, 0x8b, 0x62, 0x48, 0xce, 0xc0, 0x92, 0xb5, 0xc5, 0x4e, + 0x58, 0x15, 0xa3, 0x47, 0x4d, 0xa9, 0x41, 0x85, 0x26, 0x96, 0x3d, 0xe3, 0xd7, 0xec, 0x7b, 0xd0, + 0x20, 0x92, 0x41, 0xf5, 0x0a, 0x39, 0xfd, 0x3a, 0x72, 0xfa, 0x15, 0x65, 0xe1, 0x8c, 0x4a, 0x91, + 0xd9, 0xd7, 0x07, 0x89, 0x67, 0xb1, 0x1d, 0x46, 0xce, 0x29, 0x0f, 0x9d, 0x31, 0x6f, 0xad, 0x11, + 0x81, 0xa9, 0x67, 0xb1, 0x53, 0xa7, 0x13, 0x2c, 0x69, 0x11, 0x5f, 0xa0, 0x27, 0xa4, 0xdd, 0x91, + 0x17, 0x70, 0x65, 0xa2, 0x6a, 0xdd, 0x96, 0x9b, 0x50, 0x00, 0x95, 0x0c, 0x29, 0x04, 0x71, 0x52, + 0x7a, 0x22, 0x43, 0xe2, 0x1d, 0x24, 0x86, 0x1a, 0xe9, 0x3e, 0xca, 0x98, 0x28, 0x4e, 0xf1, 0x73, + 0xfb, 0x52, 0x71, 0x90, 0xd7, 0xf0, 0xfd, 0x82, 0x00, 0x49, 0xde, 0xf1, 0xd3, 0x0c, 0x1d, 0x88, + 0x92, 0x7f, 0x04, 0x9a, 0x7a, 0x47, 0x9c, 0xc3, 0xf2, 0xdc, 0xd1, 0xb5, 0x64, 0x26, 0x40, 0xa0, + 0x43, 0x77, 0x84, 0xbb, 0xd9, 0x71, 0x75, 0x14, 0xe2, 0xbd, 0x55, 0x05, 0x44, 0xa4, 0x7b, 0x50, + 0x99, 0x4c, 0x4f, 0x46, 0xce, 0x80, 0x50, 0x72, 0xd4, 0x0a, 0x81, 0x10, 0x41, 0xe8, 0xb7, 0x44, + 0x51, 0x84, 0x91, 0x47, 0x8c, 0x8a, 0x84, 0x21, 0x0a, 0xf2, 0x76, 0xee, 0x23, 0x3b, 0xa9, 0x9a, + 0xf8, 0xdb, 0xd8, 0x84, 0xe5, 0xe4, 0xa0, 0xe5, 0xc1, 0xf3, 0x10, 0x4a, 0x92, 0x57, 0x29, 0xc3, + 0x47, 0x5d, 0x33, 0x45, 0x0b, 0x15, 0x2d, 0x2a, 0x37, 0x7e, 0x7b, 0x01, 0x96, 0x24, 0x74, 0x4b, + 0x2c, 0x6d, 0x6f, 0x3a, 0x1e, 0xdb, 0x7e, 0x0a, 0x13, 0xcc, 0xbc, 0x98, 0x09, 0x66, 0xe7, 0x98, + 0x60, 0x52, 0xf3, 0x25, 0x1e, 0x9a, 0xd4, 0x7c, 0xc5, 0xbb, 0x24, 0x65, 0x44, 0xb7, 0x83, 0xd6, + 0x24, 0xb8, 0x4f, 0xf6, 0xd6, 0x39, 0x96, 0x5d, 0x48, 0x61, 0xd9, 0x3a, 0xc3, 0x5d, 0x98, 0x61, + 0xb8, 0x6f, 0x00, 0x11, 0x8d, 0x7a, 0xfb, 0x45, 0xd2, 0x4f, 0x10, 0x26, 0x8d, 0xa9, 0xef, 0x40, + 0x63, 0x96, 0xc7, 0x11, 0x33, 0xad, 0xa7, 0x70, 0x38, 0x67, 0xcc, 0xf1, 0xb4, 0xd2, 0x90, 0xcb, + 0x92, 0xc3, 0x39, 0x63, 0xbe, 0x87, 0x25, 0x0a, 0xbf, 0x03, 0x40, 0x7d, 0xe3, 0xa6, 0x01, 0xdc, + 0x34, 0x6f, 0x27, 0xdf, 0x85, 0xbe, 0xea, 0x1b, 0xe2, 0x61, 0xea, 0x73, 0xdc, 0x45, 0x65, 0xac, + 0x89, 0x1b, 0xe8, 0x19, 0xd4, 0xbd, 0x09, 0x77, 0xad, 0x98, 0xd7, 0x54, 0xb0, 0xa9, 0xb7, 0x5e, + 0xd0, 0x54, 0x57, 0xe1, 0x9a, 0x35, 0x51, 0x37, 0x7a, 0x64, 0xfb, 0xb4, 0xf0, 0x5c, 0x6b, 0xad, + 0xfa, 0x25, 0x5a, 0xab, 0x63, 0xe5, 0xe8, 0xd9, 0xf8, 0xbb, 0x19, 0xa8, 0x68, 0xc3, 0x66, 0x2b, + 0xb0, 0xb8, 0x75, 0x78, 0x78, 0xd4, 0x31, 0xdb, 0xfd, 0xee, 0x27, 0x1d, 0x6b, 0x6b, 0xef, 0xb0, + 0xd7, 0x69, 0xde, 0x12, 0xe0, 0xbd, 0xc3, 0xad, 0xf6, 0x9e, 0xb5, 0x73, 0x68, 0x6e, 0x29, 0x70, + 0x86, 0xad, 0x02, 0x33, 0x3b, 0xfb, 0x87, 0xfd, 0x4e, 0x02, 0x9e, 0x65, 0x4d, 0xa8, 0x6e, 0x9a, + 0x9d, 0xf6, 0xd6, 0xae, 0x84, 0xe4, 0xd8, 0x32, 0x34, 0x77, 0x8e, 0x0f, 0xb6, 0xbb, 0x07, 0x4f, + 0xad, 0xad, 0xf6, 0xc1, 0x56, 0x67, 0xaf, 0xb3, 0xdd, 0xcc, 0xb3, 0x1a, 0x94, 0xdb, 0x9b, 0xed, + 0x83, 0xed, 0xc3, 0x83, 0xce, 0x76, 0xb3, 0x60, 0xfc, 0x0a, 0x94, 0xe3, 0x89, 0x56, 0xa0, 0x78, + 0x7c, 0xf0, 0xec, 0xe0, 0xf0, 0xd3, 0x83, 0xe6, 0x2d, 0x56, 0x86, 0x02, 0xf6, 0xdf, 0xcc, 0x30, + 0x80, 0x05, 0xea, 0xb3, 0x99, 0x65, 0x25, 0xc8, 0x6f, 0x1e, 0xf6, 0x77, 0x9b, 0x39, 0xe3, 0x2f, + 0x32, 0xb0, 0x82, 0x53, 0x1e, 0xce, 0x32, 0x81, 0xfb, 0x50, 0x19, 0x78, 0xde, 0x44, 0x68, 0x5a, + 0xb1, 0x44, 0xa1, 0x83, 0xc4, 0x06, 0x27, 0xe6, 0x7d, 0xea, 0xf9, 0x03, 0x2e, 0x79, 0x00, 0x20, + 0x68, 0x47, 0x40, 0x04, 0x0d, 0x4a, 0x22, 0x26, 0x0c, 0x62, 0x01, 0x15, 0x82, 0x11, 0xca, 0x2a, + 0x2c, 0x9c, 0xf8, 0xdc, 0x1e, 0x9c, 0xcb, 0xdd, 0x2f, 0x9f, 0xd8, 0xd7, 0x63, 0x1b, 0xc0, 0x40, + 0xd0, 0xd4, 0x88, 0x0f, 0x71, 0x0b, 0x94, 0xcc, 0x86, 0x84, 0x6f, 0x49, 0xb0, 0x38, 0x8d, 0xec, + 0x13, 0xdb, 0x1d, 0x7a, 0x2e, 0x1f, 0x4a, 0x55, 0x23, 0x06, 0x18, 0x47, 0xb0, 0x3a, 0x3b, 0x3f, + 0xc9, 0x2f, 0x3e, 0xd0, 0xf8, 0x05, 0x49, 0xfe, 0xeb, 0x37, 0x93, 0x82, 0xc6, 0x3b, 0xfe, 0x7e, + 0x1e, 0xf2, 0x42, 0x12, 0xbc, 0x51, 0x68, 0xd4, 0x45, 0xfb, 0xdc, 0x9c, 0xfb, 0x07, 0x4d, 0x0d, + 0x24, 0x22, 0x90, 0x3d, 0xab, 0x8c, 0x10, 0x14, 0x0d, 0xa2, 0x62, 0x9f, 0x0f, 0x2e, 0xa4, 0x41, + 0x8b, 0x8a, 0x4d, 0x3e, 0xb8, 0x40, 0x9d, 0xca, 0x0e, 0xa9, 0x2e, 0xed, 0xf7, 0x62, 0x60, 0x87, + 0x58, 0x53, 0x16, 0x61, 0xbd, 0x62, 0x54, 0x84, 0xb5, 0x5a, 0x50, 0x74, 0xdc, 0x13, 0x6f, 0xea, + 0x0e, 0x71, 0x7b, 0x97, 0x4c, 0xf5, 0x88, 0xde, 0x26, 0xe4, 0x44, 0xe2, 0x20, 0xa2, 0xdd, 0x5c, + 0x12, 0x80, 0xbe, 0x38, 0x8a, 0xde, 0x83, 0x72, 0x70, 0xed, 0x0e, 0xf4, 0x3d, 0xbc, 0x2c, 0xd7, + 0x47, 0xcc, 0x7e, 0xa3, 0x77, 0xed, 0x0e, 0x70, 0xc7, 0x96, 0x02, 0xf9, 0x8b, 0xbd, 0x0f, 0xa5, + 0xc8, 0xee, 0x4b, 0x1c, 0xf8, 0xb6, 0x5e, 0x43, 0x19, 0x7b, 0x49, 0xbd, 0x8e, 0x50, 0xd9, 0x23, + 0x58, 0x40, 0xe3, 0x6c, 0xd0, 0xaa, 0x62, 0x25, 0x25, 0xef, 0x8b, 0x61, 0xa0, 0xa3, 0x87, 0x0f, + 0xd1, 0x50, 0x6b, 0x4a, 0xb4, 0xf5, 0x67, 0x50, 0x4b, 0xb4, 0xa5, 0x2b, 0xd1, 0x35, 0x52, 0xa2, + 0xdf, 0xd2, 0x95, 0xe8, 0xf8, 0x24, 0x90, 0xd5, 0x74, 0xa5, 0xfa, 0xd7, 0xa0, 0xa4, 0xa6, 0x22, + 0xf6, 0x9f, 0xdc, 0x3b, 0x56, 0xef, 0xb3, 0x83, 0xad, 0xe6, 0x2d, 0xd6, 0x80, 0x4a, 0x7b, 0x0b, + 0xb7, 0x34, 0x02, 0x32, 0x02, 0xe5, 0xa8, 0xdd, 0xeb, 0x45, 0x90, 0xac, 0xb1, 0x03, 0xcd, 0xd9, + 0x91, 0x0a, 0x9a, 0x0c, 0x15, 0x4c, 0x9a, 0xae, 0x63, 0x80, 0x50, 0x91, 0xc8, 0x1a, 0x4d, 0x72, + 0x38, 0x3d, 0x18, 0xef, 0x43, 0x53, 0x9c, 0x6b, 0x62, 0xa9, 0x02, 0xcd, 0x04, 0x3c, 0x12, 0xb2, + 0x9d, 0x6e, 0xbe, 0x2e, 0x99, 0x15, 0x82, 0x61, 0x57, 0xc6, 0x07, 0xb0, 0xa8, 0x55, 0x8b, 0x55, + 0x5a, 0x71, 0x56, 0xce, 0xaa, 0xb4, 0xa8, 0xc0, 0x50, 0x89, 0xb1, 0x06, 0x2b, 0xe2, 0xb1, 0x73, + 0xc1, 0xdd, 0xb0, 0x37, 0x3d, 0x21, 0x9f, 0xa3, 0xe3, 0xb9, 0x42, 0xb1, 0x29, 0x47, 0x25, 0x37, + 0x13, 0xf9, 0x86, 0xd4, 0x7e, 0xb3, 0x48, 0x1a, 0xeb, 0x5a, 0x0f, 0x58, 0x71, 0x03, 0xff, 0x26, + 0xb4, 0xe0, 0x72, 0x04, 0x12, 0xcb, 0x7a, 0xd4, 0xe9, 0x98, 0xd6, 0xe1, 0xc1, 0x5e, 0xf7, 0x40, + 0x30, 0x4a, 0xb1, 0xac, 0x08, 0xd8, 0xd9, 0x41, 0x48, 0xc6, 0x68, 0x42, 0xfd, 0x29, 0x0f, 0xbb, + 0xee, 0xa9, 0xa7, 0xfc, 0x6b, 0x3f, 0x2b, 0x40, 0x23, 0x02, 0xc5, 0x5a, 0xf4, 0x05, 0xf7, 0x03, + 0xc7, 0x73, 0x51, 0x20, 0x2e, 0x9b, 0xea, 0x51, 0x9c, 0x6e, 0xce, 0x90, 0xbb, 0xa1, 0x13, 0x5e, + 0x5b, 0x09, 0x93, 0x5b, 0x5d, 0x81, 0xe5, 0x29, 0xba, 0x0c, 0x05, 0x7b, 0xe4, 0xd8, 0xca, 0x55, + 0x4b, 0x0f, 0x02, 0x3a, 0xf0, 0x46, 0x9e, 0x8f, 0xb2, 0x6f, 0xd9, 0xa4, 0x07, 0xf6, 0x18, 0x96, + 0x85, 0x0c, 0xae, 0xdb, 0x41, 0x91, 0x7f, 0x90, 0xf5, 0x8f, 0xb9, 0xd3, 0xf1, 0x51, 0x6c, 0x0b, + 0x15, 0x25, 0xe2, 0xec, 0x14, 0x35, 0xa4, 0xb0, 0x14, 0x55, 0x20, 0x75, 0x6e, 0xd1, 0x9d, 0x8e, + 0xdb, 0x58, 0x12, 0xe1, 0x3f, 0x81, 0x15, 0x81, 0x1f, 0x89, 0x57, 0x51, 0x8d, 0x06, 0xd6, 0x10, + 0x8d, 0x75, 0x65, 0x59, 0x54, 0xe7, 0x0e, 0x94, 0x69, 0x54, 0xe2, 0x8d, 0x17, 0x48, 0x8c, 0xc7, + 0xa1, 0x70, 0x3f, 0x98, 0xf3, 0xaa, 0x2e, 0x90, 0x20, 0x30, 0xe3, 0x55, 0xd5, 0xfc, 0xb2, 0xa5, + 0x59, 0xbf, 0xec, 0x13, 0x58, 0x39, 0x11, 0x24, 0x78, 0xce, 0xed, 0x21, 0xf7, 0xad, 0x98, 0xb0, + 0x49, 0x5d, 0x59, 0x12, 0x85, 0xbb, 0x58, 0x16, 0xed, 0x03, 0x21, 0xe7, 0x08, 0xb6, 0xc0, 0x87, + 0x56, 0xe8, 0x59, 0x28, 0xfe, 0x20, 0x83, 0x29, 0x99, 0x35, 0x02, 0xf7, 0xbd, 0x2d, 0x01, 0x4c, + 0xe2, 0x9d, 0xf9, 0xf6, 0xe4, 0x5c, 0x2a, 0x14, 0x11, 0xde, 0x53, 0x01, 0x64, 0xaf, 0x41, 0x51, + 0x90, 0xbc, 0xcb, 0xc9, 0xf9, 0x45, 0x22, 0xbb, 0x02, 0xb1, 0xb7, 0x60, 0x01, 0xfb, 0x08, 0x5a, + 0x4d, 0xa4, 0xf7, 0x6a, 0xcc, 0xc8, 0x1d, 0xd7, 0x94, 0x65, 0x42, 0x98, 0x9c, 0xfa, 0x0e, 0x71, + 0x99, 0xb2, 0x89, 0xbf, 0xd9, 0xf7, 0x35, 0x96, 0xb5, 0x84, 0x75, 0x95, 0x3c, 0x30, 0x43, 0x69, + 0x37, 0x71, 0xaf, 0xaf, 0x94, 0x19, 0xfd, 0x20, 0x5f, 0xaa, 0x34, 0xab, 0xc6, 0x77, 0xa0, 0x40, + 0xab, 0x23, 0x88, 0x10, 0xd7, 0x2e, 0x23, 0x89, 0x10, 0xa1, 0x2d, 0x28, 0xba, 0x3c, 0xbc, 0xf4, + 0xfc, 0xe7, 0xca, 0x28, 0x2d, 0x1f, 0x8d, 0x1f, 0xa3, 0x35, 0x25, 0xf2, 0xb8, 0x93, 0x62, 0x28, + 0xc8, 0x83, 0x5e, 0x6f, 0x70, 0x6e, 0x4b, 0x03, 0x4f, 0x09, 0x01, 0xbd, 0x73, 0x7b, 0x8e, 0x3c, + 0xb2, 0xf3, 0x4e, 0xf7, 0xb7, 0xa0, 0xae, 0x7c, 0xfc, 0x81, 0x35, 0xe2, 0xa7, 0xa1, 0x24, 0xf7, + 0xaa, 0x74, 0xf0, 0x07, 0x7b, 0xfc, 0x34, 0x34, 0xf6, 0x61, 0x51, 0x12, 0xe4, 0xe1, 0x84, 0xab, + 0xae, 0xbf, 0x9b, 0x26, 0x4f, 0x57, 0x9e, 0x2c, 0x25, 0x0f, 0x5a, 0x8a, 0x5d, 0x48, 0x08, 0xd9, + 0xc6, 0xc7, 0xc0, 0xf4, 0x63, 0x58, 0xb6, 0x27, 0xa5, 0x5a, 0x65, 0xcb, 0x57, 0x2e, 0xb1, 0x48, + 0x76, 0x76, 0x86, 0x62, 0x75, 0x82, 0xe9, 0x60, 0xa0, 0x62, 0x2f, 0x4a, 0xa6, 0x7a, 0x34, 0xfe, + 0x34, 0x03, 0x4b, 0xd8, 0x98, 0xd2, 0x07, 0x24, 0x93, 0xfd, 0xb9, 0x07, 0x29, 0xde, 0x8f, 0x2e, + 0xfb, 0xd0, 0xc3, 0x97, 0xb7, 0x9e, 0xe6, 0xe7, 0xac, 0xa7, 0x5f, 0x87, 0xe6, 0x90, 0x8f, 0x1c, + 0x0c, 0xc3, 0x51, 0xa2, 0x04, 0x69, 0x00, 0x0d, 0x05, 0x97, 0xda, 0xa0, 0xf1, 0x8f, 0x33, 0xb0, + 0x48, 0x92, 0x0a, 0xea, 0xd5, 0x72, 0xa1, 0x3e, 0x52, 0x8a, 0xa4, 0x64, 0x55, 0x72, 0x4e, 0xf1, + 0x09, 0x8e, 0x50, 0x42, 0xde, 0xbd, 0x25, 0x15, 0x4c, 0x09, 0x65, 0x1f, 0xa2, 0x0e, 0xe3, 0x5a, + 0x08, 0x4c, 0x09, 0xeb, 0x49, 0xbe, 0x94, 0xdd, 0x5b, 0xa8, 0xe0, 0xb8, 0x08, 0xda, 0x2c, 0x09, + 0xcd, 0x56, 0x80, 0x8d, 0x1d, 0xa8, 0x25, 0xba, 0x49, 0x98, 0x78, 0xab, 0x64, 0xe2, 0x9d, 0x73, + 0xa3, 0x64, 0xe7, 0xdd, 0x28, 0x7f, 0x3b, 0x0f, 0x4c, 0x90, 0xd4, 0xcc, 0x5b, 0x9b, 0xf1, 0x41, + 0x66, 0xe7, 0x7c, 0x90, 0x8f, 0x81, 0x69, 0x08, 0xca, 0x35, 0x9a, 0x8b, 0x5c, 0xa3, 0xcd, 0x18, + 0x57, 0x7a, 0x46, 0x1f, 0xc3, 0xb2, 0x14, 0x68, 0x23, 0xa7, 0x23, 0xda, 0xee, 0xe8, 0xfd, 0x30, + 0x92, 0x6c, 0x95, 0xf3, 0x11, 0xed, 0x78, 0xca, 0xff, 0x28, 0x74, 0x70, 0x32, 0x79, 0xa1, 0xff, + 0x51, 0x69, 0xdf, 0x1a, 0x15, 0x2c, 0xbc, 0x94, 0x0a, 0x8a, 0x73, 0x54, 0xa0, 0x59, 0x60, 0x4a, + 0x49, 0x0b, 0x8c, 0x01, 0x35, 0xe5, 0x65, 0xa4, 0xe0, 0x0a, 0x92, 0xde, 0x2a, 0xd2, 0xd5, 0x88, + 0x01, 0x16, 0x0f, 0xa0, 0xa9, 0xcc, 0x24, 0x91, 0x8d, 0x87, 0x02, 0x07, 0xa4, 0x95, 0x6d, 0x4b, + 0x59, 0x7a, 0x12, 0x16, 0xf5, 0xca, 0x8c, 0x45, 0xfd, 0x5d, 0x58, 0x0c, 0x04, 0x11, 0x59, 0x53, + 0x57, 0x46, 0xf9, 0xf0, 0x21, 0xaa, 0x4e, 0x25, 0xb3, 0x89, 0x05, 0xc7, 0x31, 0x7c, 0xde, 0x7e, + 0x51, 0x4b, 0xb1, 0x5f, 0xbc, 0x1f, 0x3b, 0xe4, 0x82, 0x73, 0x67, 0x8c, 0x07, 0x77, 0x1c, 0x11, + 0x23, 0x17, 0xb8, 0x77, 0xee, 0x8c, 0x4d, 0xe5, 0xfd, 0x15, 0x0f, 0xc6, 0x7f, 0xc8, 0x40, 0x53, + 0xd0, 0x41, 0x82, 0xce, 0x7f, 0x05, 0x70, 0x47, 0xbe, 0x22, 0x99, 0x57, 0x04, 0xae, 0xa2, 0xf2, + 0xef, 0x00, 0x92, 0xad, 0x25, 0xf4, 0x44, 0x49, 0xe4, 0xad, 0x24, 0x91, 0xc7, 0x8c, 0x6c, 0xf7, + 0x16, 0x29, 0x00, 0x02, 0x92, 0xe6, 0x08, 0xcd, 0xa7, 0x38, 0x42, 0xb5, 0xad, 0xb0, 0x0b, 0xf0, + 0x8c, 0x5f, 0xef, 0x79, 0x03, 0xd4, 0xd0, 0xee, 0x02, 0x08, 0x82, 0x3c, 0xb5, 0xc7, 0x8e, 0xb4, + 0xae, 0x14, 0xcc, 0xf2, 0x73, 0x7e, 0xbd, 0x83, 0x00, 0xf1, 0x36, 0x44, 0x71, 0xbc, 0x1f, 0x0a, + 0x66, 0xe9, 0x39, 0xbf, 0xa6, 0xcd, 0x60, 0x41, 0xed, 0x19, 0xbf, 0xde, 0xe6, 0x24, 0xae, 0x79, + 0xbe, 0xa0, 0x04, 0xdf, 0xbe, 0x14, 0xf2, 0x59, 0xc2, 0x89, 0x59, 0xf1, 0xed, 0xcb, 0x67, 0xfc, + 0x5a, 0x39, 0x54, 0x8b, 0xa2, 0x7c, 0xe4, 0x0d, 0xe4, 0x09, 0xa4, 0xc2, 0x31, 0xe2, 0x41, 0x99, + 0x0b, 0xcf, 0xf1, 0xb7, 0xf1, 0x57, 0x19, 0xa8, 0x89, 0xf1, 0x23, 0x83, 0x13, 0xeb, 0xae, 0xa2, + 0x7a, 0x32, 0x71, 0x54, 0xcf, 0x13, 0xc9, 0x1f, 0x88, 0x5b, 0x66, 0x6f, 0xe6, 0x96, 0xb8, 0xc0, + 0xc4, 0x2a, 0xdf, 0x83, 0x32, 0xed, 0x2d, 0xb1, 0x59, 0x73, 0x89, 0xb7, 0x94, 0x98, 0x90, 0x59, + 0x42, 0xb4, 0x67, 0x14, 0x44, 0xa0, 0x59, 0xea, 0x68, 0x89, 0xcb, 0x7e, 0x64, 0x9f, 0x4b, 0x79, + 0x0d, 0x85, 0x1b, 0x82, 0x08, 0x74, 0x33, 0xd8, 0xc2, 0x9c, 0x19, 0xec, 0x18, 0x2a, 0x1a, 0xd1, + 0xa1, 0xdd, 0x2f, 0x9a, 0x1d, 0x51, 0x68, 0x92, 0xaa, 0x12, 0xcb, 0xb3, 0x7b, 0xcb, 0xac, 0x0d, + 0x74, 0xc0, 0xe6, 0x02, 0xe4, 0x45, 0x25, 0xe3, 0x23, 0x58, 0xd4, 0x9a, 0x25, 0x75, 0x35, 0x6d, + 0xd0, 0x99, 0x34, 0x27, 0xfa, 0x3f, 0xc9, 0xc0, 0xb2, 0xac, 0x8d, 0x21, 0x62, 0x8e, 0x38, 0xcf, + 0xf7, 0x83, 0x33, 0xf6, 0x2b, 0x50, 0x13, 0xad, 0x5b, 0x3e, 0x3f, 0x73, 0x82, 0x90, 0x2b, 0x1f, + 0x49, 0xca, 0xee, 0x11, 0x6c, 0x5d, 0xa0, 0x9a, 0x12, 0x93, 0x7d, 0x04, 0x15, 0xac, 0x4a, 0x0a, + 0xb5, 0x7c, 0x6f, 0xad, 0xf9, 0x8a, 0x34, 0xd4, 0xdd, 0x5b, 0x26, 0x04, 0xd1, 0xd3, 0x66, 0x19, + 0x8a, 0xa1, 0xef, 0x9c, 0x9d, 0x71, 0xdf, 0x58, 0x8d, 0x86, 0x26, 0xb6, 0x22, 0xef, 0x85, 0x7c, + 0x22, 0xa4, 0x24, 0xe3, 0x3f, 0x67, 0xa0, 0x22, 0x37, 0xd7, 0xcf, 0xed, 0x18, 0x59, 0xd7, 0x62, + 0x1c, 0x49, 0x77, 0x8e, 0x43, 0x1a, 0xdf, 0x81, 0xc6, 0x58, 0x48, 0x4c, 0x42, 0xa2, 0x4f, 0x78, + 0x45, 0xea, 0x0a, 0x2c, 0x05, 0x96, 0x0d, 0x58, 0x42, 0xf9, 0x25, 0xb0, 0x42, 0x67, 0x64, 0xa9, + 0x42, 0x19, 0x4f, 0xb8, 0x48, 0x45, 0x7d, 0x67, 0xb4, 0x2f, 0x0b, 0xc4, 0x31, 0x1e, 0x84, 0xf6, + 0x19, 0x97, 0xb4, 0x41, 0x0f, 0x46, 0x0b, 0x56, 0x67, 0x84, 0x79, 0xa5, 0x88, 0xfc, 0x8d, 0x26, + 0xac, 0xcd, 0x15, 0x49, 0x85, 0x24, 0xf2, 0x06, 0x8c, 0x9c, 0xf1, 0x89, 0x17, 0xd9, 0xca, 0x32, + 0x9a, 0x37, 0x60, 0x4f, 0x94, 0x28, 0x5b, 0x19, 0x87, 0x15, 0x45, 0x10, 0x68, 0xec, 0x8a, 0xe4, + 0xfd, 0x2c, 0x4a, 0xa3, 0xef, 0x25, 0x39, 0xd9, 0x6c, 0x77, 0x0a, 0xae, 0x9f, 0x8f, 0x4b, 0x93, + 0x39, 0x58, 0xc0, 0x4e, 0xa1, 0x15, 0xd1, 0x9d, 0x14, 0xa0, 0x34, 0xe5, 0x45, 0xf4, 0xf4, 0x8d, + 0x97, 0xf4, 0x94, 0xb0, 0xa2, 0x98, 0xab, 0x8a, 0x5c, 0xa9, 0xb1, 0xa8, 0x9f, 0x0b, 0x78, 0x5d, + 0xf5, 0x83, 0xc2, 0xd0, 0x7c, 0x6f, 0xf9, 0x57, 0x9a, 0x17, 0x5a, 0x87, 0x92, 0x5d, 0xde, 0x91, + 0x0d, 0x47, 0x45, 0x7a, 0xbf, 0xe7, 0xb0, 0x7a, 0x69, 0x3b, 0xa1, 0x9a, 0x9f, 0xa6, 0x37, 0x15, + 0xb0, 0xbf, 0x27, 0x2f, 0xe9, 0xef, 0x53, 0xaa, 0x9c, 0x10, 0x0f, 0x97, 0x2f, 0xe7, 0x81, 0xc1, + 0xfa, 0x9f, 0x64, 0xa1, 0x9e, 0x6c, 0x45, 0x6c, 0x6a, 0xc9, 0xa8, 0x94, 0xc0, 0x21, 0x05, 0x76, + 0x69, 0xc3, 0x3d, 0x20, 0x41, 0x63, 0xde, 0xba, 0x9c, 0x4d, 0xb1, 0x2e, 0xeb, 0x46, 0xdd, 0xdc, + 0xcb, 0xbc, 0x68, 0xf9, 0x57, 0xf2, 0xa2, 0x15, 0xd2, 0xbc, 0x68, 0x37, 0xbb, 0x5e, 0x16, 0x7e, + 0x2e, 0xd7, 0x4b, 0xf1, 0x05, 0xae, 0x97, 0x84, 0xc3, 0xa8, 0x34, 0xe3, 0x30, 0x5a, 0xff, 0xab, + 0x0c, 0xb0, 0x79, 0x3a, 0x66, 0x4f, 0xc9, 0xcc, 0xee, 0xf2, 0x91, 0xe4, 0x71, 0xdf, 0x7c, 0xb5, + 0xbd, 0xa0, 0x5e, 0x9f, 0xaa, 0xcd, 0x1e, 0xc1, 0x92, 0x1e, 0x9f, 0xac, 0x6b, 0x3a, 0x35, 0x93, + 0xe9, 0x45, 0xb1, 0x3e, 0xac, 0x39, 0x18, 0xf3, 0x2f, 0x75, 0x30, 0x16, 0x5e, 0xea, 0x60, 0x5c, + 0x48, 0x3a, 0x18, 0xd7, 0xff, 0x6b, 0x06, 0x96, 0x52, 0x48, 0xee, 0xab, 0x9b, 0xb3, 0xa0, 0x94, + 0x04, 0x03, 0xca, 0x4a, 0x4a, 0xd1, 0x79, 0xcf, 0x1e, 0x54, 0x62, 0x9f, 0x95, 0x8a, 0xdf, 0x7f, + 0xf8, 0x32, 0x3e, 0x10, 0xd7, 0x30, 0xf5, 0xea, 0xeb, 0x5f, 0x40, 0x45, 0x2b, 0x13, 0x8b, 0x48, + 0xf4, 0xa5, 0x85, 0x75, 0x90, 0x08, 0x80, 0x6a, 0xda, 0x3d, 0x90, 0x76, 0x60, 0x2a, 0xa7, 0x9d, + 0x20, 0xcf, 0x7b, 0x44, 0xd8, 0x80, 0x25, 0xe5, 0x01, 0xe1, 0x71, 0xf4, 0x96, 0x3c, 0x14, 0x16, + 0xa5, 0x1f, 0x84, 0x47, 0xc1, 0x60, 0xeb, 0x3f, 0x81, 0x5a, 0x82, 0x5f, 0x7c, 0x75, 0x6b, 0x39, + 0xab, 0x74, 0xd2, 0x58, 0x75, 0xa5, 0x73, 0xfd, 0xff, 0xe4, 0x80, 0xcd, 0xb3, 0xac, 0x5f, 0xe6, + 0x10, 0xe6, 0xdf, 0x78, 0x2e, 0xe5, 0x8d, 0xff, 0x3f, 0x3b, 0x42, 0xdf, 0x85, 0x45, 0x99, 0x20, + 0xa2, 0x39, 0x88, 0x88, 0xea, 0x9b, 0x51, 0x81, 0x1a, 0xc5, 0x77, 0x66, 0x1d, 0xd5, 0xa5, 0x44, + 0x4c, 0xbc, 0x26, 0x43, 0xcc, 0xf8, 0xab, 0x8f, 0x61, 0xc1, 0x76, 0x07, 0xe7, 0x9e, 0x8f, 0xfa, + 0x4e, 0xfd, 0xc9, 0xaf, 0x7e, 0xe9, 0x53, 0x64, 0xa3, 0x8d, 0xf5, 0x51, 0x70, 0x31, 0x65, 0x63, + 0xc6, 0x7b, 0x50, 0xd1, 0xc0, 0xe8, 0x34, 0xe9, 0xee, 0x6f, 0x1e, 0x36, 0x6f, 0xb1, 0x1a, 0x94, + 0xcd, 0xce, 0xd6, 0xe1, 0x27, 0x1d, 0xb3, 0xb3, 0xdd, 0xcc, 0xb0, 0x12, 0xe4, 0xf7, 0x0e, 0x7b, + 0xfd, 0x66, 0xd6, 0x58, 0x87, 0x96, 0x6c, 0x71, 0xde, 0x80, 0xfa, 0xbb, 0xf9, 0xc8, 0x76, 0x81, + 0x85, 0x52, 0x55, 0xf9, 0x16, 0x54, 0xf5, 0x13, 0x5e, 0x52, 0xc4, 0x8c, 0x8f, 0x52, 0x28, 0x29, + 0x9e, 0xc6, 0x04, 0xb7, 0x80, 0x3c, 0x4f, 0xc3, 0xa8, 0x1a, 0x89, 0x6d, 0x2f, 0x70, 0x55, 0xa0, + 0x44, 0x9a, 0x20, 0xc3, 0xff, 0x0f, 0xea, 0x49, 0x6b, 0xa2, 0xdc, 0xea, 0x69, 0x32, 0xbb, 0xa8, + 0x9d, 0x30, 0x2f, 0xb2, 0xef, 0x43, 0x73, 0xd6, 0x1a, 0x29, 0x43, 0x87, 0x6f, 0xa8, 0xdf, 0x70, + 0x92, 0x06, 0x4a, 0xb6, 0x0b, 0xcb, 0x69, 0x32, 0x0e, 0xd2, 0xc7, 0xcd, 0xca, 0x1a, 0x9b, 0x97, + 0x63, 0xd8, 0x77, 0xa5, 0xd1, 0xb9, 0x90, 0xe6, 0xba, 0xd3, 0x16, 0x7b, 0x83, 0xfe, 0x69, 0xe6, + 0xe7, 0x0b, 0x80, 0x18, 0xc6, 0x9a, 0x50, 0x3d, 0x3c, 0xea, 0x1c, 0x58, 0x5b, 0xbb, 0xed, 0x83, + 0x83, 0xce, 0x5e, 0xf3, 0x16, 0x63, 0x50, 0x47, 0x9f, 0xdb, 0x76, 0x04, 0xcb, 0x08, 0x98, 0x34, + 0xfe, 0x2b, 0x58, 0x96, 0x2d, 0x43, 0xb3, 0x7b, 0x30, 0x03, 0xcd, 0xb1, 0x16, 0x2c, 0x1f, 0x75, + 0xc8, 0x4d, 0x97, 0x68, 0x37, 0x2f, 0xe4, 0x66, 0x39, 0x5d, 0x21, 0x37, 0x53, 0xa2, 0x93, 0xdc, + 0x07, 0x4a, 0x9c, 0xfc, 0xbd, 0x0c, 0xac, 0xcc, 0x14, 0xc4, 0xe1, 0xeb, 0x24, 0x4c, 0x26, 0xc5, + 0xc8, 0x2a, 0x02, 0xd5, 0x6e, 0x7a, 0x17, 0x16, 0x23, 0x05, 0x7c, 0x86, 0xdd, 0x37, 0xa3, 0x02, + 0x85, 0xfc, 0x08, 0x96, 0x34, 0x3d, 0x7e, 0x86, 0x57, 0x30, 0xad, 0x48, 0x56, 0x30, 0xd6, 0xa2, + 0x30, 0xe1, 0x99, 0x51, 0x0f, 0x29, 0x7b, 0x4a, 0x2f, 0x88, 0x6d, 0xf2, 0xc9, 0xf1, 0xaa, 0x47, + 0xf6, 0x78, 0x86, 0x10, 0x92, 0xa3, 0xd5, 0x5f, 0xb8, 0xea, 0xfe, 0x0f, 0x16, 0x80, 0x7d, 0x3c, + 0xe5, 0xfe, 0x35, 0x86, 0xa7, 0x07, 0x2f, 0x8b, 0xd7, 0x52, 0xca, 0x6a, 0xf6, 0x95, 0x52, 0x50, + 0xd2, 0x52, 0x40, 0xf2, 0x2f, 0x4f, 0x01, 0x29, 0xbc, 0x2c, 0x05, 0xe4, 0x4d, 0xa8, 0x39, 0x67, + 0xae, 0x27, 0x58, 0xa1, 0x10, 0x08, 0x83, 0xd6, 0xc2, 0xfd, 0xdc, 0x83, 0xaa, 0x59, 0x95, 0x40, + 0x21, 0x0e, 0x06, 0xec, 0xa3, 0x18, 0x89, 0x0f, 0xcf, 0x30, 0x5d, 0x49, 0x67, 0x82, 0x9d, 0xe1, + 0x19, 0x97, 0xba, 0x39, 0x5a, 0xab, 0x54, 0x65, 0x01, 0x0f, 0xd8, 0x5b, 0x50, 0x0f, 0xbc, 0xa9, + 0x90, 0xaf, 0xd5, 0x32, 0x90, 0xd5, 0xbe, 0x4a, 0xd0, 0x23, 0xe5, 0xa2, 0x59, 0x9a, 0x06, 0xdc, + 0x1a, 0x3b, 0x41, 0x20, 0xe4, 0x9e, 0x81, 0xe7, 0x86, 0xbe, 0x37, 0x92, 0x86, 0xf8, 0xc5, 0x69, + 0xc0, 0xf7, 0xa9, 0x64, 0x8b, 0x0a, 0xd8, 0xb7, 0xe3, 0x21, 0x4d, 0x6c, 0xc7, 0x0f, 0x5a, 0x80, + 0x43, 0x52, 0x33, 0x45, 0x31, 0xd6, 0x76, 0xfc, 0x68, 0x2c, 0xe2, 0x21, 0x98, 0x49, 0x4d, 0xa9, + 0xcc, 0xa6, 0xa6, 0xfc, 0x28, 0x3d, 0x35, 0xa5, 0x86, 0x4d, 0x3f, 0x96, 0x4d, 0xcf, 0xbf, 0xe2, + 0x2f, 0x95, 0xa1, 0x32, 0x9f, 0x71, 0x53, 0xff, 0x32, 0x19, 0x37, 0x8d, 0xb4, 0x8c, 0x9b, 0xf7, + 0xa0, 0x82, 0xb9, 0x10, 0xd6, 0xb9, 0x23, 0x84, 0x23, 0x72, 0x2c, 0x34, 0xf5, 0x64, 0x89, 0x5d, + 0xc7, 0x0d, 0x4d, 0xf0, 0xd5, 0xcf, 0x60, 0x3e, 0xf9, 0x65, 0xf1, 0x97, 0x98, 0xfc, 0x22, 0x73, + 0x36, 0x36, 0xa0, 0xa4, 0xde, 0x13, 0x63, 0x90, 0x3f, 0xf5, 0xbd, 0xb1, 0x32, 0xb8, 0x8a, 0xdf, + 0xac, 0x0e, 0xd9, 0xd0, 0x93, 0x95, 0xb3, 0xa1, 0x67, 0xfc, 0x26, 0x54, 0x34, 0x52, 0x63, 0x6f, + 0x90, 0x69, 0x47, 0xa8, 0x28, 0x52, 0x6a, 0xa3, 0x55, 0x2c, 0x4b, 0x68, 0x77, 0x28, 0xf8, 0xcd, + 0xd0, 0xf1, 0x39, 0xa6, 0xa9, 0x59, 0x3e, 0xbf, 0xe0, 0x7e, 0xa0, 0x0c, 0xe0, 0xcd, 0xa8, 0xc0, + 0x24, 0xb8, 0xf1, 0xd7, 0x60, 0x29, 0xf1, 0x6e, 0x25, 0x8b, 0x78, 0x0b, 0x16, 0x70, 0xdd, 0x94, + 0x83, 0x32, 0x99, 0x84, 0x22, 0xcb, 0x30, 0xff, 0x98, 0x6c, 0xf7, 0xd6, 0xc4, 0xf7, 0x4e, 0xb0, + 0x93, 0x8c, 0x59, 0x91, 0xb0, 0x23, 0xdf, 0x3b, 0x31, 0xfe, 0x3c, 0x07, 0xb9, 0x5d, 0x6f, 0xa2, + 0xc7, 0xe4, 0x64, 0xe6, 0x62, 0x72, 0xa4, 0xde, 0x65, 0x45, 0x7a, 0x95, 0x14, 0x86, 0xd1, 0x6a, + 0xad, 0x74, 0xab, 0x07, 0x50, 0x17, 0x7c, 0x22, 0xf4, 0x84, 0xe2, 0x7a, 0x69, 0xfb, 0x24, 0x6a, + 0xe6, 0x68, 0xf3, 0xd9, 0xe3, 0xb0, 0xef, 0xed, 0x10, 0x9c, 0x2d, 0x43, 0x2e, 0xd2, 0x0b, 0xb0, + 0x58, 0x3c, 0xb2, 0x55, 0x58, 0xc0, 0xe0, 0xcc, 0x6b, 0xe9, 0x81, 0x93, 0x4f, 0xec, 0x9b, 0xb0, + 0x94, 0x6c, 0x97, 0x58, 0x91, 0x94, 0x8d, 0xf4, 0x86, 0x91, 0x27, 0xdd, 0x06, 0xc1, 0x47, 0x08, + 0x47, 0x3a, 0xf2, 0x4f, 0x39, 0xc7, 0x22, 0x8d, 0xe9, 0x95, 0x12, 0x4c, 0xef, 0x1e, 0x54, 0xc2, + 0xd1, 0x85, 0x35, 0xb1, 0xaf, 0x47, 0x9e, 0x3d, 0x94, 0xfb, 0x1b, 0xc2, 0xd1, 0xc5, 0x11, 0x41, + 0xd8, 0x23, 0x80, 0xf1, 0x64, 0x22, 0xf7, 0x1e, 0x1a, 0x81, 0x63, 0x52, 0xde, 0x3f, 0x3a, 0x22, + 0x92, 0x33, 0xcb, 0xe3, 0xc9, 0x84, 0x7e, 0xb2, 0x6d, 0xa8, 0xa7, 0xa6, 0x92, 0xdd, 0x55, 0xb1, + 0x84, 0xde, 0x64, 0x23, 0x65, 0x73, 0xd6, 0x06, 0x3a, 0x6c, 0xfd, 0xfb, 0xc0, 0x7e, 0xc1, 0x84, + 0xae, 0x3e, 0x94, 0xa3, 0xf1, 0xe9, 0xf9, 0x50, 0x18, 0x1d, 0x5c, 0x49, 0xe4, 0x43, 0xb5, 0x87, + 0x43, 0x5f, 0xf0, 0x45, 0x3a, 0x30, 0x23, 0x96, 0x0f, 0xda, 0x89, 0xd9, 0x26, 0xbe, 0x6f, 0xfc, + 0x65, 0x06, 0x0a, 0x94, 0x9c, 0xf5, 0x36, 0x34, 0x08, 0x3f, 0x8a, 0x6f, 0x92, 0x7e, 0x3b, 0x3a, + 0x77, 0xfb, 0x32, 0xb4, 0x49, 0x6c, 0x0b, 0x2d, 0xb1, 0x34, 0x1b, 0xbd, 0x79, 0x2d, 0xb9, 0xf4, + 0x1e, 0x94, 0xa3, 0xae, 0x35, 0xd2, 0x29, 0xa9, 0x9e, 0xd9, 0xeb, 0x90, 0x3f, 0xf7, 0x26, 0xca, + 0x00, 0x02, 0xf1, 0x4a, 0x9a, 0x08, 0x8f, 0xc7, 0x22, 0xfa, 0xa0, 0xc1, 0x4b, 0xc5, 0x3d, 0xea, + 0x04, 0xc9, 0x60, 0x7e, 0x8e, 0x0b, 0x29, 0x73, 0x3c, 0x86, 0x86, 0xe0, 0x03, 0x9a, 0xff, 0xfc, + 0xe6, 0x43, 0xf3, 0xeb, 0x42, 0xc2, 0x1b, 0x8c, 0xa6, 0x43, 0xae, 0x9b, 0x9f, 0x30, 0xd8, 0x46, + 0xc2, 0x95, 0x64, 0x6d, 0xfc, 0x41, 0x86, 0xf8, 0x8b, 0x68, 0x97, 0x3d, 0x80, 0xbc, 0x38, 0xdf, + 0x66, 0xcc, 0xa3, 0x51, 0x98, 0xb6, 0xc0, 0x33, 0x11, 0x03, 0xb3, 0xb1, 0xa7, 0xe3, 0x64, 0xeb, + 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0x05, 0xe7, 0x6b, 0x6a, 0x5a, 0x33, 0xd6, 0x0f, 0x9a, 0x7d, + 0xb4, 0x4d, 0x37, 0xb4, 0xa8, 0x9d, 0x7c, 0xe2, 0xc4, 0x54, 0x52, 0xe0, 0xf0, 0x8c, 0x6b, 0xd1, + 0x3a, 0x7f, 0x94, 0x85, 0x5a, 0x62, 0x44, 0x18, 0xb6, 0x24, 0x0e, 0x00, 0xb2, 0xcd, 0xcb, 0xf7, + 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9d, 0xb2, 0x89, 0x75, 0x8a, 0x22, 0x05, 0x72, 0x7a, 0xa4, + 0xc0, 0x63, 0x28, 0xc7, 0x09, 0xc5, 0xc9, 0x21, 0x89, 0xfe, 0x54, 0xb0, 0x7a, 0x8c, 0x14, 0xc7, + 0x16, 0x14, 0xf4, 0xd8, 0x82, 0xef, 0x69, 0xae, 0xe8, 0x05, 0x6c, 0xc6, 0x48, 0x5b, 0xd1, 0x5f, + 0x8a, 0x23, 0xda, 0xf8, 0x08, 0x2a, 0xda, 0xe0, 0x75, 0x97, 0x73, 0x26, 0xe1, 0x72, 0x8e, 0xd2, + 0x4a, 0xb2, 0x71, 0x5a, 0x89, 0xf1, 0xdb, 0x59, 0xa8, 0x89, 0xfd, 0xe5, 0xb8, 0x67, 0x47, 0xde, + 0xc8, 0x19, 0xa0, 0xad, 0x3e, 0xda, 0x61, 0x52, 0xd0, 0x52, 0xfb, 0x4c, 0x6e, 0x31, 0x92, 0xb3, + 0xf4, 0xec, 0x39, 0x62, 0xd2, 0x51, 0xf6, 0x9c, 0x01, 0x35, 0xc1, 0x18, 0x4f, 0xec, 0x80, 0x6b, + 0xe9, 0xce, 0x66, 0xe5, 0x94, 0xf3, 0x4d, 0x3b, 0x20, 0x0e, 0xf9, 0x4d, 0x58, 0x12, 0x38, 0x98, + 0x38, 0x34, 0x76, 0x46, 0x23, 0x87, 0x30, 0xc9, 0x82, 0xd3, 0x3c, 0xe5, 0xdc, 0xb4, 0x43, 0xbe, + 0x2f, 0x0a, 0x64, 0x76, 0x74, 0x69, 0xe8, 0x04, 0xf6, 0x49, 0x1c, 0x5c, 0x16, 0x3d, 0xa3, 0x87, + 0xcd, 0xbe, 0xd2, 0x3c, 0x6c, 0x94, 0x41, 0x58, 0x19, 0xdb, 0x57, 0x91, 0x87, 0x6d, 0x86, 0x92, + 0x8a, 0xb3, 0x94, 0x64, 0xfc, 0xa7, 0x2c, 0x54, 0x34, 0xb2, 0x7c, 0x95, 0xd3, 0xf5, 0xee, 0x9c, + 0x6f, 0xa5, 0xac, 0xbb, 0x51, 0xde, 0x4c, 0x76, 0x89, 0x8e, 0x78, 0xca, 0xc3, 0xd6, 0x08, 0xf8, + 0x0e, 0x94, 0xc5, 0xae, 0x7b, 0x0f, 0x2d, 0x91, 0xf2, 0x16, 0x01, 0x04, 0x1c, 0x4d, 0x4f, 0x54, + 0xe1, 0x13, 0x2c, 0x2c, 0xc4, 0x85, 0x4f, 0x44, 0xe1, 0x8b, 0x22, 0x4a, 0xbf, 0x03, 0x55, 0xd9, + 0x2a, 0xbe, 0x53, 0x9c, 0x6e, 0xbc, 0xeb, 0x13, 0xef, 0xdb, 0xac, 0x50, 0x77, 0xf4, 0xf2, 0x65, + 0xc5, 0x27, 0xaa, 0x62, 0xe9, 0x65, 0x15, 0x9f, 0xd0, 0x83, 0xb1, 0x13, 0x05, 0xe9, 0x62, 0x10, + 0x88, 0xe2, 0x63, 0x8f, 0x60, 0x49, 0xb1, 0xab, 0xa9, 0x6b, 0xbb, 0xae, 0x37, 0x75, 0x07, 0x5c, + 0xe5, 0x9b, 0x30, 0x59, 0x74, 0x1c, 0x97, 0x18, 0xc3, 0x28, 0x21, 0x91, 0x82, 0x49, 0x1e, 0x42, + 0x81, 0xe4, 0x72, 0x12, 0x3e, 0xd2, 0x19, 0x17, 0xa1, 0xb0, 0x07, 0x50, 0x20, 0xf1, 0x3c, 0x7b, + 0x23, 0xb3, 0x21, 0x04, 0x63, 0x03, 0x1a, 0x28, 0x62, 0x6a, 0x1c, 0xf7, 0x45, 0x52, 0x89, 0xb1, + 0x0c, 0xec, 0x80, 0x36, 0x91, 0x1e, 0xe4, 0xf4, 0xdf, 0x72, 0x50, 0xd1, 0xc0, 0x82, 0x2d, 0x62, + 0x58, 0x8c, 0x35, 0x74, 0xec, 0x31, 0x57, 0x0e, 0x9f, 0x9a, 0x59, 0x43, 0xe8, 0xb6, 0x04, 0x8a, + 0x43, 0xc1, 0xbe, 0x38, 0xb3, 0xbc, 0x69, 0x68, 0x0d, 0xf9, 0x99, 0xcf, 0xb9, 0x14, 0x96, 0xaa, + 0xf6, 0xc5, 0xd9, 0xe1, 0x34, 0xdc, 0x46, 0x98, 0xc0, 0x12, 0x44, 0xad, 0x61, 0xc9, 0x48, 0x8e, + 0xb1, 0x7d, 0x15, 0x63, 0xc9, 0x70, 0x22, 0x5a, 0xa2, 0x7c, 0x14, 0x4e, 0x44, 0x6a, 0xcb, 0x2c, + 0x27, 0x2f, 0xcc, 0x73, 0xf2, 0x6f, 0xc3, 0x2a, 0x71, 0x72, 0xc9, 0x23, 0xac, 0x19, 0x92, 0x5a, + 0xc6, 0x52, 0x39, 0x49, 0x4d, 0xfe, 0x6a, 0x8a, 0x19, 0xa8, 0xfd, 0x11, 0x38, 0x3f, 0xa6, 0x1d, + 0x95, 0x31, 0xc5, 0xcc, 0x64, 0xe3, 0x3d, 0xe7, 0xc7, 0x5c, 0x60, 0xa2, 0xbb, 0x5a, 0xc7, 0x94, + 0x81, 0xcb, 0x63, 0xc7, 0x9d, 0xc5, 0xb4, 0xaf, 0x92, 0x98, 0x65, 0x89, 0x69, 0x5f, 0xe9, 0x98, + 0xef, 0xc3, 0xda, 0x98, 0x0f, 0x1d, 0x3b, 0xd9, 0xac, 0x15, 0x4b, 0x10, 0xcb, 0x54, 0xac, 0xd5, + 0xe9, 0x91, 0x06, 0x29, 0x56, 0xe3, 0xc7, 0xde, 0xf8, 0xc4, 0xa1, 0xc3, 0x93, 0x1c, 0xe8, 0x79, + 0xb3, 0xee, 0x4e, 0xc7, 0x3f, 0x44, 0xb0, 0xa8, 0x12, 0x18, 0x35, 0xa8, 0xf4, 0x42, 0x6f, 0xa2, + 0x5e, 0x73, 0x1d, 0xaa, 0xf4, 0x28, 0xb3, 0x89, 0xee, 0xc0, 0x6d, 0xa4, 0xcd, 0xbe, 0x37, 0xf1, + 0x46, 0xde, 0xd9, 0x75, 0xc2, 0xa0, 0xf4, 0x5f, 0x32, 0xb0, 0x94, 0x28, 0x95, 0xfb, 0xfc, 0xdb, + 0xb4, 0xb1, 0xa2, 0x94, 0x10, 0x22, 0xe7, 0x45, 0xed, 0xf0, 0x21, 0x44, 0xda, 0x55, 0x2a, 0x4d, + 0xa4, 0x1d, 0xa7, 0x32, 0xab, 0x8a, 0x44, 0xdb, 0xad, 0x79, 0xda, 0x96, 0xf5, 0x55, 0x92, 0xb3, + 0x6a, 0xe2, 0x57, 0x65, 0x70, 0xf9, 0x50, 0x4e, 0x39, 0x97, 0x0c, 0x9f, 0xd5, 0x8d, 0x4f, 0x6a, + 0x04, 0xb1, 0x45, 0x2a, 0x30, 0xfe, 0x65, 0x06, 0x20, 0x1e, 0x1d, 0x06, 0xf0, 0x46, 0x07, 0x28, + 0xdd, 0x12, 0xa4, 0x1d, 0x96, 0x6f, 0x40, 0x35, 0x8a, 0xe3, 0x8b, 0x8f, 0xe4, 0x8a, 0x82, 0x89, + 0x73, 0xf9, 0x1d, 0x68, 0x9c, 0x8d, 0xbc, 0x13, 0x14, 0x9d, 0xe4, 0x01, 0x4a, 0x39, 0x55, 0x75, + 0x02, 0xab, 0x63, 0x31, 0x3e, 0xc0, 0xf3, 0xa9, 0xa1, 0x7e, 0xfa, 0x71, 0x6c, 0xfc, 0x4e, 0x36, + 0x0a, 0x68, 0x8a, 0x57, 0xe2, 0xc5, 0x7a, 0xc6, 0xcf, 0xe3, 0x17, 0x7f, 0x91, 0xbb, 0xe7, 0x23, + 0xa8, 0xfb, 0xc4, 0x1d, 0x15, 0xeb, 0xcc, 0xbf, 0x80, 0x75, 0xd6, 0xfc, 0xc4, 0x91, 0xfb, 0x75, + 0x68, 0xda, 0xc3, 0x0b, 0xee, 0x87, 0x0e, 0x9a, 0x8d, 0x51, 0x50, 0x93, 0x21, 0x44, 0x1a, 0x1c, + 0x25, 0xa2, 0x77, 0xa0, 0x21, 0x33, 0xdc, 0x22, 0x4c, 0x79, 0x67, 0x46, 0x0c, 0x16, 0x88, 0xc6, + 0xbf, 0x51, 0x11, 0x54, 0xc9, 0xb7, 0xfb, 0xe2, 0x55, 0xd1, 0x67, 0x98, 0x9d, 0x77, 0x68, 0x49, + 0x42, 0x92, 0xd6, 0x68, 0xc9, 0x8f, 0x08, 0x28, 0x6d, 0xd1, 0xc9, 0x65, 0xcd, 0xbf, 0xca, 0xb2, + 0x1a, 0x7f, 0x92, 0x81, 0xe2, 0xae, 0x37, 0x11, 0x7a, 0xb9, 0x90, 0xe7, 0x70, 0x9b, 0x44, 0x6e, + 0x88, 0x05, 0xf1, 0xd8, 0x1d, 0xbe, 0x38, 0x91, 0x23, 0x55, 0xde, 0xa8, 0x25, 0xe5, 0x8d, 0xef, + 0xc1, 0x1d, 0x74, 0xf2, 0xf8, 0xde, 0xc4, 0xf3, 0xc5, 0x56, 0xb5, 0x47, 0x24, 0x77, 0x78, 0x6e, + 0x78, 0xae, 0x78, 0xe7, 0xed, 0x53, 0xce, 0x8f, 0x34, 0x8c, 0xfd, 0x08, 0x01, 0x53, 0xa5, 0x46, + 0xe1, 0x85, 0x45, 0xaa, 0xa2, 0x14, 0x8c, 0x88, 0xa3, 0x36, 0x44, 0x41, 0x07, 0xe1, 0x28, 0x1a, + 0x19, 0xdf, 0x85, 0x72, 0x64, 0x75, 0x60, 0xef, 0x42, 0xf9, 0xdc, 0x9b, 0x48, 0xd3, 0x44, 0x26, + 0x91, 0xec, 0x22, 0x67, 0x6d, 0x96, 0xce, 0xe9, 0x47, 0x60, 0xfc, 0x79, 0x11, 0x8a, 0x5d, 0xf7, + 0xc2, 0x73, 0x06, 0x18, 0x83, 0x35, 0xe6, 0x63, 0x4f, 0xa5, 0xd9, 0x8a, 0xdf, 0x18, 0x67, 0x11, + 0xdf, 0x7c, 0x91, 0x93, 0x71, 0x16, 0xd1, 0x9d, 0x17, 0x2b, 0xb0, 0xe0, 0xeb, 0x57, 0x57, 0x14, + 0x7c, 0x8c, 0x0a, 0x8d, 0x94, 0xb6, 0x82, 0x96, 0xa6, 0x2c, 0xda, 0xa2, 0x2b, 0x15, 0x70, 0xc9, + 0x28, 0xed, 0xa9, 0x8c, 0x10, 0x5c, 0xb0, 0xd7, 0xa0, 0x28, 0x73, 0x4b, 0x28, 0x52, 0x9f, 0xc2, + 0x38, 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0xe4, 0xa4, 0x8b, 0x24, 0x2a, 0xa1, 0xa7, 0x4b, 0xe0, 0xb6, + 0xa0, 0xb5, 0x7b, 0x50, 0x21, 0x7c, 0x42, 0x29, 0xc9, 0xa8, 0x29, 0x04, 0x21, 0x42, 0xca, 0x0d, + 0x30, 0xe5, 0xd4, 0x1b, 0x60, 0x30, 0xc8, 0x2e, 0xe2, 0xb2, 0x34, 0x45, 0xa0, 0x7b, 0x3f, 0x34, + 0xb8, 0xba, 0xfe, 0x48, 0x2a, 0xf7, 0x94, 0x05, 0xa8, 0x94, 0xfb, 0x37, 0xa1, 0x76, 0x6a, 0x8f, + 0x46, 0x27, 0xf6, 0xe0, 0x39, 0xe9, 0xa4, 0x55, 0x32, 0xc3, 0x29, 0x20, 0x2a, 0xa5, 0xf7, 0xa0, + 0xa2, 0xbd, 0x65, 0x0c, 0x89, 0xca, 0x9b, 0x10, 0xbf, 0xdf, 0x59, 0x53, 0x53, 0xfd, 0x15, 0x4c, + 0x4d, 0x5a, 0x68, 0x58, 0x23, 0x19, 0x1a, 0x76, 0x07, 0xb9, 0xa9, 0x0c, 0x1f, 0x6a, 0xd2, 0x25, + 0x13, 0xf6, 0x70, 0x88, 0xe1, 0x43, 0x74, 0xa3, 0x1b, 0x2e, 0x1e, 0x95, 0x2f, 0x92, 0x50, 0x4b, + 0x30, 0x42, 0xb9, 0x4b, 0xf6, 0xd2, 0x89, 0xed, 0x0c, 0x31, 0x14, 0x97, 0xd4, 0xd8, 0xa2, 0x3d, + 0x0e, 0x8f, 0x6c, 0x67, 0xc8, 0xee, 0x43, 0x55, 0x15, 0xe3, 0xe9, 0xb8, 0x44, 0xeb, 0x2f, 0x8b, + 0xc5, 0x99, 0x68, 0x40, 0x2d, 0xc2, 0x18, 0xc7, 0xa9, 0x7c, 0x15, 0x89, 0x82, 0x74, 0xf0, 0x1e, + 0x46, 0x5c, 0x84, 0x1c, 0x13, 0xf6, 0xea, 0x4f, 0xee, 0xc8, 0xb9, 0x4a, 0x2a, 0x55, 0xff, 0xc9, + 0x4b, 0x43, 0x98, 0x42, 0x10, 0x23, 0x67, 0xd1, 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0x2c, 0x22, + 0x04, 0xf6, 0x5d, 0x4d, 0x91, 0x6a, 0x21, 0xf2, 0x6b, 0x33, 0xed, 0xdf, 0x94, 0x89, 0x70, 0x17, + 0xc0, 0x09, 0xc4, 0x29, 0x13, 0x70, 0x77, 0x88, 0xb9, 0x77, 0x25, 0xb3, 0xec, 0x04, 0xcf, 0x08, + 0xf0, 0xd5, 0x6a, 0x58, 0x6d, 0xa8, 0xea, 0xd3, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0x75, 0x0e, 0x9a, + 0xb7, 0x58, 0x05, 0x8a, 0xbd, 0x4e, 0xbf, 0xbf, 0x87, 0x2e, 0xa7, 0x2a, 0x94, 0xa2, 0xc4, 0x9f, + 0xac, 0x78, 0x6a, 0x6f, 0x6d, 0x75, 0x8e, 0xfa, 0x9d, 0xed, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, + 0x99, 0x33, 0xfe, 0x22, 0x07, 0x15, 0x6d, 0x15, 0x5e, 0xcc, 0x8c, 0xef, 0x02, 0xa0, 0x4a, 0x13, + 0x47, 0x97, 0xe5, 0xcd, 0xb2, 0x80, 0xd0, 0xcb, 0xd7, 0x8d, 0xe5, 0x39, 0xba, 0xbd, 0x44, 0x19, + 0xcb, 0xdf, 0x84, 0x1a, 0x5d, 0x04, 0xa2, 0x3b, 0x0e, 0x0b, 0x66, 0x95, 0x80, 0x92, 0x55, 0x63, + 0xe6, 0x20, 0x22, 0x61, 0x4e, 0x89, 0xbc, 0x16, 0x80, 0x40, 0x98, 0x55, 0x82, 0x29, 0x41, 0x81, + 0x37, 0xba, 0xe0, 0x84, 0x41, 0x12, 0x61, 0x45, 0xc2, 0xfa, 0x32, 0x07, 0x52, 0xf2, 0x43, 0x2d, + 0x75, 0xad, 0x60, 0x56, 0x09, 0x28, 0x3b, 0xfa, 0xa6, 0x22, 0xa0, 0x12, 0x12, 0xd0, 0xda, 0x3c, + 0x35, 0x24, 0x88, 0x67, 0x6f, 0xce, 0x9e, 0x55, 0x46, 0xc2, 0xf8, 0xda, 0x7c, 0xbd, 0x97, 0xdb, + 0xb5, 0xd8, 0xbb, 0xc0, 0xc6, 0x93, 0x89, 0x95, 0x62, 0x69, 0xca, 0x9b, 0x8d, 0xf1, 0x64, 0xd2, + 0xd7, 0x0c, 0x31, 0x5f, 0x81, 0x11, 0xec, 0x73, 0x60, 0x6d, 0xb1, 0x81, 0x71, 0x88, 0x91, 0x09, + 0x35, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, 0x70, 0xbf, 0x6c, 0x2a, 0xf7, 0x7b, 0x11, 0x9f, 0x30, + 0x76, 0xa0, 0x72, 0xa4, 0x5d, 0x33, 0x74, 0x5f, 0x9c, 0x10, 0xea, 0x82, 0x21, 0x3a, 0x3b, 0xc8, + 0xb8, 0xe5, 0xcb, 0x7b, 0x85, 0xb4, 0xd1, 0x64, 0xb5, 0xd1, 0x18, 0xff, 0x22, 0x43, 0x57, 0x38, + 0x44, 0x83, 0x8f, 0x6f, 0x36, 0x52, 0x7e, 0xa0, 0x38, 0xc3, 0xb4, 0xa2, 0xfc, 0x3f, 0x32, 0x39, + 0x14, 0x87, 0x66, 0x79, 0xa7, 0xa7, 0x01, 0x57, 0xb9, 0x52, 0x15, 0x84, 0x1d, 0x22, 0x48, 0x09, + 0xdf, 0x42, 0xc2, 0x77, 0xa8, 0xfd, 0x40, 0xe6, 0x4c, 0x09, 0xe1, 0x7b, 0xdf, 0xbe, 0x92, 0xbd, + 0x06, 0x42, 0x04, 0x91, 0x86, 0x6a, 0x95, 0x21, 0x16, 0x3d, 0x1b, 0xff, 0x54, 0x26, 0xc1, 0xce, + 0xae, 0xef, 0x43, 0x28, 0x45, 0xad, 0x26, 0x4f, 0x58, 0x85, 0x19, 0x95, 0x8b, 0x73, 0x1c, 0xb5, + 0xf2, 0xc4, 0x88, 0x69, 0x73, 0xa1, 0xb3, 0xa1, 0xab, 0x8d, 0xfa, 0x1b, 0xc0, 0x4e, 0x1d, 0x7f, + 0x16, 0x99, 0x36, 0x5b, 0x13, 0x4b, 0x34, 0x6c, 0xe3, 0x18, 0x96, 0x14, 0x97, 0xd0, 0x34, 0x82, + 0xe4, 0xcb, 0xcb, 0xbc, 0x84, 0xc9, 0x67, 0xe7, 0x98, 0xbc, 0xf1, 0xd3, 0x3c, 0x14, 0xd5, 0x95, + 0x5d, 0x69, 0xd7, 0x4c, 0x95, 0x93, 0xd7, 0x4c, 0xb5, 0x12, 0x57, 0x92, 0xe0, 0xab, 0x97, 0xe7, + 0xfd, 0x3b, 0xb3, 0x47, 0xb6, 0x66, 0x34, 0x4f, 0x1c, 0xdb, 0xab, 0x90, 0x9f, 0xd8, 0xe1, 0x39, + 0x1a, 0xc8, 0x88, 0x78, 0xf0, 0x59, 0x19, 0xd3, 0x0b, 0x49, 0x63, 0x7a, 0xda, 0x95, 0x5c, 0x24, + 0x92, 0xce, 0x5d, 0xc9, 0x75, 0x07, 0x48, 0xbe, 0xd0, 0x82, 0x90, 0x4a, 0x08, 0x10, 0x67, 0x51, + 0x52, 0x1c, 0x29, 0xcd, 0x8a, 0x23, 0xaf, 0x2c, 0x2a, 0x7c, 0x1b, 0x16, 0x28, 0x9d, 0x5d, 0x66, + 0xc2, 0xa9, 0x03, 0x45, 0xae, 0xa1, 0xfa, 0x4f, 0xa1, 0xc9, 0xa6, 0xc4, 0xd5, 0xef, 0xb7, 0xa9, + 0x24, 0xee, 0xb7, 0xd1, 0x8d, 0xfc, 0xd5, 0xa4, 0x91, 0xff, 0x01, 0x34, 0xa3, 0x05, 0x45, 0x93, + 0x99, 0x1b, 0xc8, 0x3c, 0x9b, 0xba, 0x82, 0x0b, 0x2e, 0x79, 0x10, 0xc4, 0x07, 0x62, 0x3d, 0x71, + 0x20, 0x0a, 0x1e, 0xd6, 0x0e, 0x43, 0x3e, 0x9e, 0x84, 0xf2, 0x40, 0xc4, 0x48, 0x7c, 0x7d, 0x80, + 0xc9, 0x1c, 0xd1, 0x1a, 0x94, 0xbb, 0x07, 0xd6, 0xce, 0x5e, 0xf7, 0xe9, 0x6e, 0xbf, 0x99, 0x11, + 0x8f, 0xbd, 0xe3, 0xad, 0xad, 0x4e, 0x67, 0x1b, 0x4f, 0x1c, 0x80, 0x85, 0x9d, 0x76, 0x57, 0x9c, + 0x3e, 0x39, 0xe3, 0xf7, 0xb2, 0x50, 0xd1, 0x9a, 0x67, 0xef, 0x47, 0xab, 0x42, 0x57, 0xa0, 0xdc, + 0x9d, 0x1f, 0xc2, 0x86, 0x62, 0xc5, 0xda, 0xb2, 0x44, 0x17, 0x90, 0x65, 0x6f, 0xbc, 0x80, 0x8c, + 0xbd, 0x0d, 0x0d, 0x9b, 0x5a, 0x88, 0x56, 0x41, 0x9a, 0x83, 0x25, 0x58, 0x2e, 0x02, 0x86, 0xde, + 0xc5, 0xe7, 0x89, 0xc0, 0xcb, 0xab, 0x68, 0xb7, 0xe8, 0x48, 0xc1, 0xc5, 0x2a, 0x9e, 0xda, 0xce, + 0x68, 0xea, 0x73, 0xe9, 0xbe, 0x8d, 0x4e, 0x66, 0x82, 0x9a, 0xaa, 0xd8, 0xf8, 0x00, 0x20, 0x1e, + 0x73, 0x72, 0x71, 0x6e, 0x25, 0x17, 0x27, 0xa3, 0x2d, 0x4e, 0xd6, 0xd8, 0x26, 0x36, 0x22, 0x17, + 0x3a, 0xf2, 0x54, 0x7f, 0x13, 0x94, 0x45, 0xca, 0xc2, 0xe0, 0xd7, 0xc9, 0x88, 0x87, 0x2a, 0x9b, + 0x76, 0x51, 0x96, 0x74, 0xa3, 0x02, 0x95, 0xdc, 0x1e, 0xb7, 0x12, 0x73, 0x23, 0x49, 0x92, 0xb3, + 0xdc, 0x48, 0xa2, 0x9a, 0x51, 0xb9, 0xb1, 0x0e, 0xad, 0x6d, 0x2e, 0x5a, 0x6b, 0x8f, 0x46, 0x33, + 0xc3, 0x31, 0xee, 0xc0, 0xed, 0x94, 0x32, 0x69, 0x84, 0xf8, 0x18, 0x56, 0xda, 0x94, 0x38, 0xfb, + 0x55, 0x65, 0xc8, 0x18, 0x2d, 0x58, 0x9d, 0x6d, 0x52, 0x76, 0xb6, 0x03, 0x8b, 0xdb, 0xfc, 0x64, + 0x7a, 0xb6, 0xc7, 0x2f, 0xe2, 0x8e, 0x18, 0xe4, 0x83, 0x73, 0xef, 0x52, 0xae, 0x0f, 0xfe, 0xc6, + 0x40, 0x32, 0x81, 0x63, 0x05, 0x13, 0x3e, 0x50, 0x16, 0x51, 0x84, 0xf4, 0x26, 0x7c, 0x60, 0xbc, + 0x0f, 0x4c, 0x6f, 0x47, 0xae, 0x97, 0xd0, 0x12, 0xa6, 0x27, 0x56, 0x70, 0x1d, 0x84, 0x7c, 0xac, + 0x6e, 0xd8, 0x81, 0x60, 0x7a, 0xd2, 0x23, 0x88, 0xf1, 0x0e, 0x54, 0x8f, 0xec, 0x6b, 0x93, 0x7f, + 0x2e, 0x73, 0x3f, 0xd6, 0xa0, 0x38, 0xb1, 0xaf, 0x05, 0x1b, 0x88, 0x9c, 0x23, 0x58, 0x6c, 0xfc, + 0x61, 0x1e, 0x16, 0x08, 0x93, 0xdd, 0xa7, 0x4b, 0x30, 0x1d, 0x17, 0xb7, 0xa1, 0x62, 0x94, 0x1a, + 0x68, 0x8e, 0x97, 0x66, 0xe7, 0x79, 0xa9, 0x34, 0xa0, 0xa9, 0xcb, 0x3f, 0x94, 0x19, 0xdb, 0x9d, + 0x8e, 0xd5, 0x8d, 0x1f, 0xc9, 0xec, 0xd1, 0x7c, 0x7c, 0xc9, 0x29, 0xa5, 0xd6, 0x25, 0x1d, 0x8d, + 0xb1, 0x2e, 0x42, 0xa3, 0x53, 0x47, 0x84, 0x64, 0x97, 0x3a, 0x28, 0x55, 0xe1, 0x29, 0xaa, 0xac, + 0xa2, 0xa4, 0xc2, 0x33, 0xa7, 0xd8, 0x94, 0x5e, 0xae, 0xd8, 0x90, 0x65, 0xed, 0x05, 0x8a, 0x0d, + 0xbc, 0x82, 0x62, 0xf3, 0x0a, 0x4e, 0xbe, 0xdb, 0x50, 0xc2, 0x73, 0x5f, 0xe3, 0x9e, 0xe2, 0xbc, + 0x17, 0xdc, 0xf3, 0x3b, 0x9a, 0xe8, 0x4f, 0x11, 0x06, 0x77, 0xe2, 0x6d, 0x62, 0xf2, 0xcf, 0x7f, + 0x39, 0xce, 0x93, 0xcf, 0xa0, 0x28, 0xa1, 0x82, 0xa0, 0x5d, 0x7b, 0xac, 0xee, 0x4f, 0xc2, 0xdf, + 0x62, 0xd9, 0xf0, 0xd2, 0x97, 0xcf, 0xa7, 0x8e, 0xcf, 0x87, 0xea, 0x62, 0x0c, 0x07, 0xf7, 0xa8, + 0x80, 0x88, 0x09, 0x0a, 0x35, 0xc4, 0xf5, 0x2e, 0x5d, 0x99, 0x16, 0x5f, 0x74, 0x82, 0x67, 0xe2, + 0xd1, 0x60, 0xd0, 0xc4, 0x1b, 0xd4, 0x26, 0x9e, 0xaf, 0x0e, 0x27, 0xe3, 0xa7, 0x19, 0x68, 0xca, + 0xdd, 0x15, 0x95, 0xe9, 0x5a, 0x40, 0xe1, 0x26, 0x87, 0xf8, 0x8b, 0xaf, 0xb9, 0x30, 0xa0, 0x86, + 0xc6, 0x8f, 0xe8, 0xa4, 0x22, 0xe3, 0x4d, 0x45, 0x00, 0x77, 0xe4, 0x69, 0xf5, 0x3a, 0x54, 0x54, + 0x94, 0xeb, 0xd8, 0x19, 0xa9, 0xfb, 0x8c, 0x29, 0xcc, 0x75, 0xdf, 0x19, 0xa9, 0x83, 0xce, 0xb7, + 0x65, 0x96, 0x5b, 0x06, 0x0f, 0x3a, 0xd3, 0x0e, 0xb9, 0xf1, 0xef, 0x33, 0xb0, 0xa8, 0x4d, 0x45, + 0xee, 0xdb, 0x0f, 0xa1, 0x1a, 0x5d, 0x5d, 0xc8, 0x23, 0xc9, 0x6b, 0x2d, 0xc9, 0x68, 0xe2, 0x6a, + 0x95, 0x41, 0x04, 0x09, 0xc4, 0x60, 0x86, 0xf6, 0x35, 0x8e, 0x37, 0x98, 0x8e, 0x95, 0x72, 0x33, + 0xb4, 0xaf, 0x77, 0x38, 0xef, 0x4d, 0xc7, 0x42, 0x75, 0xbd, 0xe4, 0xfc, 0x79, 0x84, 0x40, 0x32, + 0x17, 0x08, 0x98, 0xc4, 0x30, 0xa0, 0x36, 0xf6, 0xdc, 0xf0, 0x3c, 0x42, 0x91, 0x52, 0x27, 0x02, + 0x09, 0xc7, 0xf8, 0xb3, 0x2c, 0x2c, 0x91, 0x89, 0x4d, 0x9a, 0x36, 0x25, 0xeb, 0x6a, 0xc1, 0x02, + 0x59, 0x1b, 0x89, 0x79, 0xed, 0xde, 0x32, 0xe5, 0x33, 0xfb, 0xf6, 0x2b, 0x9a, 0x05, 0x55, 0x22, + 0xdd, 0x0d, 0xcb, 0x9f, 0x9b, 0x5f, 0xfe, 0x9b, 0x97, 0x37, 0xcd, 0xe3, 0x56, 0x48, 0xf3, 0xb8, + 0xbd, 0x8a, 0x9f, 0x6b, 0x2e, 0xdb, 0xac, 0x28, 0x71, 0xb4, 0x6c, 0xb3, 0xf7, 0x61, 0x2d, 0x81, + 0x83, 0xdc, 0xda, 0x39, 0x75, 0xb8, 0xba, 0x75, 0x60, 0x59, 0xc3, 0xee, 0xa9, 0xb2, 0xcd, 0x22, + 0x14, 0x82, 0x81, 0x37, 0xe1, 0xc6, 0x2a, 0x2c, 0x27, 0x57, 0x55, 0x1e, 0x13, 0xbf, 0x9f, 0x81, + 0x96, 0x8c, 0x8f, 0x70, 0xdc, 0xb3, 0x5d, 0x27, 0x08, 0x3d, 0x3f, 0xba, 0xe2, 0xef, 0x2e, 0x40, + 0x10, 0xda, 0xbe, 0xd4, 0x36, 0x65, 0x9e, 0x3d, 0x42, 0x50, 0x93, 0xbc, 0x0d, 0x25, 0xee, 0x0e, + 0xa9, 0x90, 0xa8, 0xa1, 0xc8, 0xdd, 0xa1, 0xd2, 0x43, 0xe7, 0xe4, 0xef, 0x5a, 0x52, 0xbd, 0x90, + 0x69, 0xaf, 0x62, 0x75, 0xf8, 0x05, 0x1e, 0xbc, 0xf9, 0x28, 0xed, 0x75, 0xdf, 0xbe, 0xc2, 0x68, + 0xc3, 0xc0, 0xf8, 0x47, 0x59, 0x68, 0xc4, 0xe3, 0xa3, 0x9c, 0xf9, 0x17, 0x67, 0xff, 0xdf, 0x97, + 0xe4, 0xe0, 0x08, 0xf9, 0x5d, 0x33, 0x3c, 0x96, 0x68, 0x73, 0x76, 0x5d, 0x66, 0x40, 0x45, 0x61, + 0x78, 0xd3, 0x50, 0xbb, 0x69, 0xab, 0x4c, 0x28, 0x87, 0xd3, 0x50, 0x28, 0x5c, 0x42, 0xf3, 0x74, + 0x5c, 0xa9, 0xf2, 0x14, 0xec, 0x71, 0xd8, 0xc5, 0x0b, 0xbc, 0x05, 0x58, 0x54, 0xa3, 0x17, 0x29, + 0xb0, 0x04, 0x7e, 0x93, 0xe4, 0x6c, 0x7a, 0x73, 0x28, 0x63, 0xeb, 0x42, 0x28, 0xdd, 0x65, 0x1a, + 0x09, 0xa1, 0xaf, 0x43, 0x85, 0x1a, 0x8f, 0x93, 0x0b, 0xf3, 0x66, 0x19, 0x7b, 0xc0, 0x72, 0x69, + 0x04, 0xf2, 0xa6, 0x09, 0xd5, 0x17, 0xa8, 0x2b, 0x0c, 0x3f, 0xf8, 0x7b, 0x19, 0xb8, 0x9d, 0xf2, + 0xda, 0xe4, 0x2e, 0xdf, 0x82, 0xc5, 0xd3, 0xa8, 0x50, 0xad, 0x2e, 0x6d, 0xf5, 0x55, 0xc5, 0x56, + 0x93, 0x6b, 0x6a, 0x36, 0x4f, 0x93, 0x80, 0x58, 0xe9, 0xa2, 0x37, 0x98, 0xc8, 0x1f, 0x45, 0xa5, + 0x8b, 0x5e, 0x23, 0xe9, 0x3b, 0x47, 0xb0, 0xde, 0xb9, 0x12, 0x1c, 0x63, 0x4b, 0xbf, 0x81, 0x5e, + 0x91, 0x51, 0xd2, 0xc0, 0x9c, 0x79, 0x25, 0x03, 0xf3, 0x90, 0xd2, 0xe4, 0xa2, 0xb6, 0x7e, 0x9e, + 0x46, 0xf0, 0x00, 0x15, 0x75, 0xe8, 0x06, 0x7d, 0x95, 0xc3, 0x3a, 0x88, 0x6e, 0xce, 0x37, 0x02, + 0x68, 0xec, 0x4f, 0x47, 0xa1, 0x13, 0x5f, 0xa6, 0xcf, 0xbe, 0x2d, 0xeb, 0x60, 0x3f, 0x6a, 0xd5, + 0x52, 0x3b, 0x82, 0xa8, 0x23, 0x5c, 0xac, 0xb1, 0x68, 0xc8, 0x9a, 0xef, 0xaf, 0x31, 0x4e, 0xf6, + 0x60, 0xdc, 0x86, 0xb5, 0xf8, 0x89, 0x96, 0x4d, 0x1d, 0x35, 0xff, 0x3c, 0x43, 0xa1, 0xcd, 0xc9, + 0x8b, 0xfd, 0x59, 0x07, 0x96, 0x02, 0xc7, 0x3d, 0x1b, 0x71, 0xbd, 0xf9, 0x40, 0x2e, 0xc2, 0x4a, + 0x72, 0x6c, 0xf2, 0xf2, 0x7f, 0x73, 0x91, 0x6a, 0xc4, 0xad, 0x05, 0x6c, 0xf3, 0xa6, 0x41, 0xc6, + 0x64, 0x31, 0xb3, 0x1a, 0xf3, 0x83, 0xef, 0x42, 0x3d, 0xd9, 0x11, 0xfb, 0x8e, 0x4c, 0x11, 0x8d, + 0x47, 0x95, 0x9b, 0x49, 0xe6, 0x8b, 0x09, 0xa2, 0x12, 0xaf, 0x7d, 0x60, 0xfc, 0x83, 0x0c, 0xb4, + 0x4c, 0x2e, 0x28, 0x57, 0x1b, 0xa5, 0xa2, 0x99, 0x0f, 0xe7, 0x5a, 0xbd, 0x79, 0xae, 0x2a, 0xf3, + 0x54, 0x8d, 0xe8, 0x1b, 0x37, 0xbe, 0x8c, 0xdd, 0x5b, 0x73, 0x33, 0xda, 0x2c, 0xc1, 0x02, 0xa1, + 0x18, 0x6b, 0xb0, 0x22, 0xc7, 0xa3, 0xc6, 0x12, 0x7b, 0x0f, 0x13, 0x3d, 0x26, 0xbc, 0x87, 0xeb, + 0xd0, 0xa2, 0x9b, 0x1a, 0xf5, 0x49, 0xc8, 0x8a, 0xdb, 0xc0, 0xf6, 0xed, 0x81, 0xed, 0x7b, 0x9e, + 0x7b, 0xc4, 0x7d, 0x19, 0x28, 0x8a, 0x12, 0x26, 0x3a, 0xd7, 0x94, 0x28, 0x4c, 0x4f, 0xea, 0x7e, + 0x41, 0xcf, 0x55, 0x71, 0x31, 0xf4, 0x64, 0x98, 0xb0, 0xb4, 0x69, 0x3f, 0xe7, 0xaa, 0x25, 0xb5, + 0x44, 0x1f, 0x41, 0x65, 0x12, 0x35, 0xaa, 0xd6, 0x5d, 0xe5, 0x91, 0xcf, 0x77, 0x6b, 0xea, 0xd8, + 0xc6, 0x13, 0x58, 0x4e, 0xb6, 0x29, 0x59, 0xc7, 0x3a, 0x94, 0xc6, 0x12, 0x26, 0x47, 0x17, 0x3d, + 0x1b, 0xbf, 0x5b, 0x82, 0xa2, 0xd4, 0xe7, 0xd8, 0x06, 0xe4, 0x07, 0x2a, 0x36, 0x29, 0xbe, 0x9e, + 0x44, 0x96, 0xaa, 0xff, 0x5b, 0x18, 0xa1, 0x24, 0xf0, 0xd8, 0x47, 0x50, 0x4f, 0x7a, 0x45, 0x67, + 0x92, 0x54, 0x93, 0xee, 0xcc, 0xda, 0x60, 0xc6, 0xff, 0x55, 0x8e, 0x0f, 0x47, 0x92, 0x19, 0x4a, + 0xe7, 0xda, 0xe9, 0xe9, 0xb9, 0x42, 0xde, 0x0e, 0xce, 0x6d, 0xeb, 0xc9, 0xfb, 0x1f, 0xc8, 0x2c, + 0xd5, 0x0a, 0x02, 0x7b, 0xe7, 0xf6, 0x93, 0xf7, 0x3f, 0x98, 0x95, 0xa4, 0x65, 0x8e, 0xaa, 0x26, + 0x49, 0x2f, 0x43, 0x81, 0x2e, 0xd2, 0xa3, 0x20, 0x13, 0x7a, 0x60, 0x8f, 0x61, 0x59, 0xaa, 0xad, + 0x96, 0x0c, 0x07, 0x26, 0x2e, 0x58, 0xa2, 0xd4, 0x26, 0x59, 0xd6, 0xc3, 0x22, 0xb2, 0x0d, 0xad, + 0xc2, 0xc2, 0x79, 0x7c, 0x2b, 0x62, 0xcd, 0x94, 0x4f, 0xc6, 0x9f, 0x15, 0xa0, 0xa2, 0x2d, 0x0a, + 0xab, 0x42, 0xc9, 0xec, 0xf4, 0x3a, 0xe6, 0x27, 0x9d, 0xed, 0xe6, 0x2d, 0xf6, 0x00, 0xde, 0xea, + 0x1e, 0x6c, 0x1d, 0x9a, 0x66, 0x67, 0xab, 0x6f, 0x1d, 0x9a, 0x96, 0xba, 0x24, 0xe7, 0xa8, 0xfd, + 0xd9, 0x7e, 0xe7, 0xa0, 0x6f, 0x6d, 0x77, 0xfa, 0xed, 0xee, 0x5e, 0xaf, 0x99, 0x61, 0xaf, 0x41, + 0x2b, 0xc6, 0x54, 0xc5, 0xed, 0xfd, 0xc3, 0xe3, 0x83, 0x7e, 0x33, 0xcb, 0xee, 0xc1, 0x9d, 0x9d, + 0xee, 0x41, 0x7b, 0xcf, 0x8a, 0x71, 0xb6, 0xf6, 0xfa, 0x9f, 0x58, 0x9d, 0x5f, 0x3f, 0xea, 0x9a, + 0x9f, 0x35, 0x73, 0x69, 0x08, 0x42, 0x19, 0x57, 0x2d, 0xe4, 0xd9, 0x6d, 0x58, 0x21, 0x04, 0xaa, + 0x62, 0xf5, 0x0f, 0x0f, 0xad, 0xde, 0xe1, 0xe1, 0x41, 0xb3, 0xc0, 0x16, 0xa1, 0xd6, 0x3d, 0xf8, + 0xa4, 0xbd, 0xd7, 0xdd, 0xb6, 0xcc, 0x4e, 0x7b, 0x6f, 0xbf, 0xb9, 0xc0, 0x96, 0xa0, 0x31, 0x8b, + 0x57, 0x14, 0x4d, 0x28, 0xbc, 0xc3, 0x83, 0xee, 0xe1, 0x81, 0xf5, 0x49, 0xc7, 0xec, 0x75, 0x0f, + 0x0f, 0x9a, 0x25, 0xb6, 0x0a, 0x2c, 0x59, 0xb4, 0xbb, 0xdf, 0xde, 0x6a, 0x96, 0xd9, 0x0a, 0x2c, + 0x26, 0xe1, 0xcf, 0x3a, 0x9f, 0x35, 0x81, 0xb5, 0x60, 0x99, 0x06, 0x66, 0x6d, 0x76, 0xf6, 0x0e, + 0x3f, 0xb5, 0xf6, 0xbb, 0x07, 0xdd, 0xfd, 0xe3, 0xfd, 0x66, 0x05, 0xaf, 0xed, 0xea, 0x74, 0xac, + 0xee, 0x41, 0xef, 0x78, 0x67, 0xa7, 0xbb, 0xd5, 0xed, 0x1c, 0xf4, 0x9b, 0x55, 0xea, 0x39, 0x6d, + 0xe2, 0x35, 0x51, 0x41, 0xe6, 0x0c, 0x58, 0xdb, 0xdd, 0x5e, 0x7b, 0x73, 0xaf, 0xb3, 0xdd, 0xac, + 0xb3, 0xbb, 0x70, 0xbb, 0xdf, 0xd9, 0x3f, 0x3a, 0x34, 0xdb, 0xe6, 0x67, 0x2a, 0xa7, 0xc0, 0xda, + 0x69, 0x77, 0xf7, 0x8e, 0xcd, 0x4e, 0xb3, 0xc1, 0xde, 0x80, 0xbb, 0x66, 0xe7, 0xe3, 0xe3, 0xae, + 0xd9, 0xd9, 0xb6, 0x0e, 0x0e, 0xb7, 0x3b, 0xd6, 0x4e, 0xa7, 0xdd, 0x3f, 0x36, 0x3b, 0xd6, 0x7e, + 0xb7, 0xd7, 0xeb, 0x1e, 0x3c, 0x6d, 0x36, 0xd9, 0x5b, 0x70, 0x3f, 0x42, 0x89, 0x1a, 0x98, 0xc1, + 0x5a, 0x14, 0xf3, 0x53, 0xaf, 0xf4, 0xa0, 0xf3, 0xeb, 0x7d, 0xeb, 0xa8, 0xd3, 0x31, 0x9b, 0x8c, + 0xad, 0xc3, 0x6a, 0xdc, 0x3d, 0x75, 0x20, 0xfb, 0x5e, 0x12, 0x65, 0x47, 0x1d, 0x73, 0xbf, 0x7d, + 0x20, 0x5e, 0x70, 0xa2, 0x6c, 0x59, 0x0c, 0x3b, 0x2e, 0x9b, 0x1d, 0xf6, 0x0a, 0x63, 0x50, 0xd7, + 0xde, 0xca, 0x4e, 0xdb, 0x6c, 0xae, 0xb2, 0x06, 0x54, 0xf6, 0x8f, 0x8e, 0xac, 0x7e, 0x77, 0xbf, + 0x73, 0x78, 0xdc, 0x6f, 0xae, 0xb1, 0x15, 0x68, 0x76, 0x0f, 0xfa, 0x1d, 0x53, 0xbc, 0x6b, 0x55, + 0xf5, 0x7f, 0x15, 0xd9, 0x32, 0x34, 0xd4, 0x48, 0x15, 0xf4, 0x67, 0x45, 0xb6, 0x06, 0xec, 0xf8, + 0xc0, 0xec, 0xb4, 0xb7, 0xc5, 0xc2, 0x45, 0x05, 0xff, 0xbb, 0x28, 0x3d, 0x24, 0x3f, 0xcd, 0x45, + 0x87, 0x75, 0x1c, 0x72, 0x90, 0xbc, 0x23, 0xb7, 0xaa, 0xdd, 0x6d, 0xfb, 0xb2, 0xdb, 0xeb, 0x35, + 0xd5, 0x2a, 0x37, 0xa7, 0x5a, 0xcd, 0xe9, 0xee, 0x35, 0x5d, 0xf6, 0x7b, 0x13, 0x6a, 0x63, 0xba, + 0x2f, 0x57, 0xde, 0x8b, 0x09, 0x32, 0xfe, 0x86, 0x80, 0x74, 0x29, 0xe6, 0xdc, 0xf5, 0xed, 0x85, + 0xf9, 0xeb, 0xdb, 0xd3, 0xe4, 0xfb, 0x85, 0x34, 0xf9, 0xfe, 0x21, 0x2c, 0x12, 0x6b, 0x72, 0x5c, + 0x67, 0xac, 0xb4, 0x66, 0x92, 0x02, 0x1b, 0xc8, 0xa2, 0x08, 0xae, 0xd4, 0x09, 0xa5, 0x72, 0x48, + 0x16, 0x52, 0x94, 0xda, 0x46, 0x42, 0xd3, 0x20, 0xce, 0x11, 0x69, 0x1a, 0x51, 0x0f, 0xf6, 0x55, + 0xdc, 0x43, 0x45, 0xeb, 0x81, 0xe0, 0xd8, 0xc3, 0x43, 0x58, 0xe4, 0x57, 0xa1, 0x6f, 0x5b, 0xde, + 0xc4, 0xfe, 0x7c, 0x8a, 0x2e, 0x5c, 0x1b, 0x75, 0xf8, 0xaa, 0xd9, 0xc0, 0x82, 0x43, 0x84, 0x6f, + 0xdb, 0xa1, 0xfd, 0xf0, 0x0b, 0xa8, 0x68, 0x77, 0x29, 0xb3, 0x35, 0x58, 0xfa, 0xb4, 0xdb, 0x3f, + 0xe8, 0xf4, 0x7a, 0xd6, 0xd1, 0xf1, 0xe6, 0xb3, 0xce, 0x67, 0xd6, 0x6e, 0xbb, 0xb7, 0xdb, 0xbc, + 0x25, 0x36, 0xed, 0x41, 0xa7, 0xd7, 0xef, 0x6c, 0x27, 0xe0, 0x19, 0xf6, 0x3a, 0xac, 0x1f, 0x1f, + 0x1c, 0xf7, 0x3a, 0xdb, 0x56, 0x5a, 0xbd, 0xac, 0xa0, 0x52, 0x59, 0x9e, 0x52, 0x3d, 0xf7, 0xf0, + 0xfb, 0x50, 0x4f, 0x5e, 0xf0, 0xc9, 0x00, 0x16, 0xf6, 0x3a, 0x4f, 0xdb, 0x5b, 0x9f, 0xd1, 0xc5, + 0x7e, 0xbd, 0x7e, 0xbb, 0xdf, 0xdd, 0xb2, 0xe4, 0x45, 0x7e, 0x82, 0x23, 0x64, 0x58, 0x05, 0x8a, + 0xed, 0x83, 0xad, 0xdd, 0x43, 0xb3, 0xd7, 0xcc, 0x3e, 0xfc, 0x08, 0x9a, 0xb3, 0xfe, 0xa8, 0x84, + 0x03, 0xef, 0x45, 0x9e, 0xbe, 0x87, 0xff, 0x3a, 0x07, 0x10, 0x27, 0x0c, 0x08, 0x56, 0xb3, 0xdd, + 0xee, 0xb7, 0xf7, 0x0e, 0xc5, 0x34, 0xcc, 0xc3, 0xbe, 0xe0, 0x20, 0x66, 0xe7, 0xe3, 0xe6, 0xad, + 0xd4, 0x92, 0xc3, 0xa3, 0x7e, 0x33, 0x23, 0x56, 0xac, 0x7b, 0xd0, 0xed, 0x77, 0xdb, 0x7b, 0x96, + 0x79, 0x78, 0xdc, 0x3d, 0x78, 0x4a, 0x37, 0x96, 0x21, 0x97, 0x3d, 0x3e, 0xda, 0x31, 0x0f, 0x0f, + 0xfa, 0x56, 0x6f, 0xf7, 0xb8, 0xbf, 0x8d, 0xf7, 0x9d, 0x6d, 0x99, 0xdd, 0x23, 0x6a, 0x33, 0xff, + 0x22, 0x04, 0xd1, 0x74, 0x41, 0xac, 0xf9, 0xd3, 0xc3, 0x5e, 0xaf, 0x7b, 0x64, 0x7d, 0x7c, 0xdc, + 0x31, 0xbb, 0x9d, 0x1e, 0x56, 0x5c, 0x48, 0x81, 0x0b, 0xfc, 0xa2, 0xe0, 0xcd, 0xfd, 0xbd, 0x4f, + 0x24, 0xf3, 0x14, 0xa8, 0xa5, 0x24, 0x48, 0x60, 0x95, 0x05, 0x4f, 0x11, 0xdc, 0x27, 0xa5, 0x65, + 0xb8, 0xa1, 0x4c, 0xd4, 0xab, 0x08, 0xbe, 0x3a, 0xf7, 0x32, 0xb0, 0x5a, 0x35, 0xbd, 0x48, 0xd4, + 0x42, 0x96, 0x1b, 0x1d, 0x50, 0xdb, 0xdb, 0x26, 0x56, 0xa8, 0xcf, 0x41, 0x05, 0x6e, 0x43, 0xbc, + 0x28, 0xc1, 0x9e, 0x04, 0x4a, 0x53, 0x3d, 0x88, 0x92, 0xc5, 0x27, 0xbf, 0x93, 0x83, 0x3a, 0x25, + 0x6f, 0xd1, 0xa7, 0xac, 0xb8, 0xcf, 0xf6, 0xa1, 0x28, 0xbf, 0x89, 0xc6, 0x56, 0xa2, 0xcb, 0xa4, + 0xf4, 0xaf, 0xb0, 0xad, 0xaf, 0xce, 0x82, 0xa5, 0x38, 0xb6, 0xf4, 0x37, 0xff, 0xf4, 0x7f, 0xfe, + 0xc3, 0x6c, 0x8d, 0x55, 0x1e, 0x5d, 0xbc, 0xf7, 0xe8, 0x8c, 0xbb, 0x81, 0x68, 0xe3, 0xff, 0x07, + 0x88, 0xbf, 0xf4, 0xc5, 0x5a, 0x91, 0x13, 0x6a, 0xe6, 0x33, 0x68, 0xeb, 0xb7, 0x53, 0x4a, 0x64, + 0xbb, 0xb7, 0xb1, 0xdd, 0x25, 0xa3, 0x2e, 0xda, 0x75, 0x5c, 0x27, 0xa4, 0xaf, 0x7e, 0x7d, 0x98, + 0x79, 0xc8, 0x86, 0x50, 0xd5, 0xbf, 0xc1, 0xc5, 0x94, 0xa4, 0x94, 0xf2, 0x15, 0xb1, 0xf5, 0x3b, + 0xa9, 0x65, 0x4a, 0x06, 0xc5, 0x3e, 0x56, 0x8c, 0xa6, 0xe8, 0x63, 0x8a, 0x18, 0x71, 0x2f, 0x23, + 0x92, 0xca, 0xe3, 0x4f, 0x6d, 0xb1, 0xd7, 0x34, 0xb9, 0x6a, 0xee, 0x43, 0x5f, 0xeb, 0x77, 0x6f, + 0x28, 0x95, 0x7d, 0xdd, 0xc5, 0xbe, 0xd6, 0x0c, 0x26, 0xfa, 0x1a, 0x20, 0x8e, 0xfa, 0xd0, 0xd7, + 0x87, 0x99, 0x87, 0x4f, 0xfe, 0xf2, 0x01, 0x94, 0xa3, 0x60, 0x4e, 0xf6, 0x5b, 0x50, 0x4b, 0x64, + 0xd7, 0x31, 0x35, 0x8d, 0xb4, 0x64, 0xbc, 0xf5, 0xd7, 0xd2, 0x0b, 0x65, 0xc7, 0xaf, 0x63, 0xc7, + 0x2d, 0xb6, 0x2a, 0x3a, 0x96, 0xd9, 0x6b, 0x8f, 0x30, 0x1b, 0x96, 0xae, 0xe6, 0x7a, 0xae, 0x69, + 0x1f, 0xd4, 0xd9, 0x6b, 0xb3, 0x1a, 0x41, 0xa2, 0xb7, 0xbb, 0x37, 0x94, 0xca, 0xee, 0x5e, 0xc3, + 0xee, 0x56, 0xd9, 0xb2, 0xde, 0x9d, 0x0a, 0xbd, 0x64, 0x1c, 0xaf, 0xc3, 0xd3, 0xbf, 0x44, 0xc5, + 0xee, 0xc6, 0x97, 0x97, 0xa5, 0x7c, 0xa1, 0x2a, 0x22, 0x91, 0xf9, 0xcf, 0x54, 0x19, 0x2d, 0xec, + 0x8a, 0x31, 0x7c, 0x7d, 0xfa, 0x87, 0xa8, 0xd8, 0x09, 0x54, 0xb4, 0x8f, 0x37, 0xb0, 0xdb, 0x37, + 0x7e, 0x68, 0x62, 0x7d, 0x3d, 0xad, 0x28, 0x6d, 0x2a, 0x7a, 0xfb, 0x8f, 0x4e, 0x39, 0x67, 0xbf, + 0x01, 0xe5, 0xe8, 0x93, 0x00, 0x6c, 0x4d, 0xfb, 0x44, 0x83, 0xfe, 0x09, 0x83, 0xf5, 0xd6, 0x7c, + 0x41, 0x1a, 0xf1, 0xe9, 0xad, 0x0b, 0xe2, 0xfb, 0x14, 0x2a, 0xda, 0xb5, 0xff, 0xd1, 0x04, 0xe6, + 0x3f, 0x2d, 0x10, 0x4d, 0x20, 0xe5, 0x2b, 0x01, 0xc6, 0x22, 0x76, 0x51, 0x61, 0x65, 0xa4, 0xef, + 0xf0, 0xca, 0x0b, 0xd8, 0x1e, 0xac, 0x48, 0x4d, 0xeb, 0x84, 0x7f, 0x99, 0xd7, 0x90, 0xf2, 0xf1, + 0xaf, 0xc7, 0x19, 0xf6, 0x11, 0x94, 0xd4, 0xd7, 0x1d, 0xd8, 0x6a, 0xfa, 0x57, 0x2a, 0xd6, 0xd7, + 0xe6, 0xe0, 0x52, 0x2d, 0xfa, 0x0c, 0x20, 0xfe, 0xc6, 0x40, 0xc4, 0x24, 0xe6, 0xbe, 0x59, 0x10, + 0x51, 0xc0, 0xfc, 0x07, 0x09, 0x8c, 0x55, 0x9c, 0x60, 0x93, 0x21, 0x93, 0x70, 0xf9, 0xa5, 0xba, + 0xb3, 0xf4, 0x47, 0x50, 0xd1, 0x3e, 0x33, 0x10, 0x2d, 0xdf, 0xfc, 0x27, 0x0a, 0xa2, 0xe5, 0x4b, + 0xf9, 0x2a, 0x81, 0xb1, 0x8e, 0xad, 0x2f, 0x1b, 0x0d, 0xd1, 0xba, 0x10, 0xb5, 0xa4, 0xc8, 0x23, + 0x5e, 0xd0, 0x39, 0xd4, 0x12, 0xdf, 0x12, 0x88, 0x76, 0x68, 0xda, 0x97, 0x0a, 0xa2, 0x1d, 0x9a, + 0xfa, 0xf9, 0x01, 0x45, 0x67, 0xc6, 0xa2, 0xe8, 0xe7, 0x02, 0x51, 0xb4, 0x9e, 0x7e, 0x08, 0x15, + 0xed, 0xbb, 0x00, 0xd1, 0x5c, 0xe6, 0x3f, 0x41, 0x10, 0xcd, 0x25, 0xed, 0x33, 0x02, 0xcb, 0xd8, + 0x47, 0xdd, 0x40, 0x52, 0xc0, 0x5b, 0x17, 0x45, 0xdb, 0xbf, 0x05, 0xf5, 0xe4, 0xa7, 0x02, 0xa2, + 0xbd, 0x9f, 0xfa, 0xcd, 0x81, 0x68, 0xef, 0xdf, 0xf0, 0x7d, 0x01, 0x49, 0xd2, 0x0f, 0x97, 0xa2, + 0x4e, 0x1e, 0xfd, 0x44, 0xa6, 0xa5, 0x7c, 0xc1, 0x3e, 0x16, 0x0c, 0x4e, 0x5e, 0xfa, 0xc9, 0xd6, + 0x34, 0xaa, 0xd5, 0x6f, 0x0f, 0x8d, 0xf6, 0xcb, 0xdc, 0xfd, 0xa0, 0x49, 0x62, 0xc6, 0xc6, 0xd9, + 0x53, 0x58, 0x8a, 0x88, 0x39, 0xba, 0xc5, 0x33, 0x88, 0xe6, 0x90, 0x7a, 0x57, 0xe8, 0x7a, 0x73, + 0xb6, 0xf4, 0x71, 0x86, 0x8e, 0x3f, 0xbc, 0x3b, 0x51, 0x3b, 0xfe, 0xf4, 0x8b, 0x3c, 0xb5, 0xe3, + 0x2f, 0x71, 0xc5, 0xe2, 0xec, 0xf1, 0x17, 0x3a, 0xa2, 0x0d, 0x17, 0x1a, 0xb3, 0x77, 0x6a, 0xde, + 0xbd, 0x29, 0xed, 0x9f, 0x9a, 0x7f, 0xfd, 0xc5, 0xb7, 0x02, 0x24, 0x59, 0x91, 0xe2, 0xa6, 0x8f, + 0x64, 0xf0, 0x09, 0xfb, 0x4d, 0xa8, 0xea, 0xd7, 0x8b, 0x33, 0x9d, 0x27, 0xcc, 0xf6, 0x74, 0x27, + 0xb5, 0x2c, 0x49, 0x25, 0xac, 0xaa, 0x77, 0xc3, 0x3e, 0x81, 0xd5, 0x68, 0x99, 0xf5, 0xbc, 0xf5, + 0x80, 0xdd, 0x4b, 0xc9, 0x66, 0x4f, 0x2c, 0xf6, 0xed, 0x1b, 0xd3, 0xdd, 0x1f, 0x67, 0x04, 0xf5, + 0x25, 0xef, 0x39, 0x8e, 0x4f, 0x9e, 0xb4, 0xeb, 0x9d, 0xe3, 0x93, 0x27, 0xf5, 0x72, 0x64, 0x45, + 0x7d, 0x6c, 0x29, 0xb1, 0x46, 0x14, 0x96, 0xcb, 0x7e, 0x08, 0x0d, 0x2d, 0x29, 0xbf, 0x77, 0xed, + 0x0e, 0xa2, 0x9d, 0x34, 0x7f, 0x51, 0xdf, 0x7a, 0x9a, 0x6d, 0xd2, 0x58, 0xc3, 0xf6, 0x17, 0x8d, + 0xc4, 0xe2, 0x88, 0x5d, 0xb4, 0x05, 0x15, 0x3d, 0xe1, 0xff, 0x05, 0xed, 0xae, 0x69, 0x45, 0xfa, + 0x9d, 0x70, 0x8f, 0x33, 0x6c, 0x0f, 0x9a, 0xb3, 0x37, 0x54, 0x45, 0x3c, 0x25, 0xed, 0x56, 0xad, + 0xf5, 0x99, 0xc2, 0xc4, 0xbd, 0x56, 0xec, 0x88, 0x12, 0x3b, 0xa2, 0x2f, 0x65, 0x79, 0xfe, 0xec, + 0xa9, 0x9e, 0xfc, 0x82, 0x56, 0xd4, 0x5a, 0xda, 0xb7, 0xd3, 0x1e, 0x64, 0x1e, 0x67, 0xd8, 0xef, + 0x65, 0xa0, 0x9a, 0xb8, 0xf7, 0x25, 0x11, 0x3a, 0x3f, 0x33, 0xcf, 0x96, 0x5e, 0xa6, 0x4f, 0xd4, + 0x30, 0x71, 0x11, 0xf7, 0x1e, 0xfe, 0x20, 0xf1, 0x92, 0x7e, 0x92, 0x70, 0xed, 0x6d, 0xcc, 0x7e, + 0x4a, 0xeb, 0x8b, 0x59, 0x04, 0xfd, 0xfe, 0xc5, 0x2f, 0x1e, 0x67, 0xd8, 0xbf, 0xcd, 0x40, 0x3d, + 0xe9, 0xb3, 0x8f, 0xa6, 0x9b, 0x1a, 0x1d, 0x10, 0x91, 0xd2, 0x0d, 0x8e, 0xfe, 0x1f, 0xe2, 0x28, + 0xfb, 0x0f, 0xcd, 0xc4, 0x28, 0xe5, 0x0d, 0xdd, 0xbf, 0xd8, 0x68, 0xd9, 0x87, 0xf4, 0xe5, 0x4a, + 0x15, 0xca, 0xc4, 0xe6, 0xbf, 0x74, 0x18, 0x91, 0x9f, 0xfe, 0x5d, 0x40, 0x7c, 0x09, 0x3f, 0xa2, + 0x4f, 0x46, 0xa9, 0xc8, 0x18, 0x41, 0xc5, 0xaf, 0x5a, 0xdf, 0x78, 0x0b, 0xe7, 0xf4, 0xba, 0x71, + 0x3b, 0x31, 0xa7, 0x59, 0xc1, 0xa3, 0x4d, 0xa3, 0x93, 0x9f, 0xf5, 0x8b, 0x4f, 0xce, 0xb9, 0x4f, + 0xfd, 0xdd, 0x3c, 0xc8, 0x31, 0x0d, 0x52, 0xa2, 0x27, 0xb6, 0xda, 0x2b, 0x36, 0x63, 0x3c, 0xc4, + 0xb1, 0xbe, 0x65, 0xdc, 0xbb, 0x71, 0xac, 0x8f, 0xd0, 0xff, 0x2e, 0x46, 0x7c, 0x04, 0x10, 0x87, + 0x1a, 0xb2, 0x99, 0x80, 0xb7, 0x88, 0x01, 0xcd, 0x47, 0x23, 0x26, 0xf7, 0xb3, 0x8a, 0x8b, 0x13, + 0x2d, 0xfe, 0x06, 0xb1, 0xd3, 0x28, 0x14, 0x4f, 0x97, 0xbe, 0x92, 0x51, 0x81, 0x09, 0xe9, 0x6b, + 0xb6, 0xfd, 0x04, 0x33, 0x8d, 0xe2, 0xee, 0x8e, 0xa1, 0xb6, 0xe7, 0x79, 0xcf, 0xa7, 0x93, 0x28, + 0xbc, 0x3d, 0x19, 0x14, 0xb3, 0x6b, 0x07, 0xe7, 0xeb, 0x33, 0xb3, 0x30, 0xee, 0x63, 0x53, 0xeb, + 0xac, 0xa5, 0x35, 0xf5, 0xe8, 0x27, 0x71, 0x7c, 0xe3, 0x17, 0xcc, 0x86, 0xc5, 0x88, 0x47, 0xc7, + 0x31, 0x84, 0xc9, 0x66, 0x12, 0x9c, 0x79, 0xb6, 0x8b, 0x84, 0x9a, 0xa0, 0x46, 0xfb, 0x28, 0x50, + 0x6d, 0x3e, 0xce, 0xb0, 0x23, 0xa8, 0x6e, 0xf3, 0x01, 0x26, 0xea, 0x63, 0x68, 0xc9, 0x52, 0x22, + 0x4c, 0x81, 0x62, 0x52, 0xd6, 0x6b, 0x09, 0x60, 0xf2, 0xdc, 0x9a, 0xd8, 0xd7, 0x3e, 0xff, 0xfc, + 0xd1, 0x4f, 0x64, 0xd0, 0xca, 0x17, 0xea, 0xdc, 0x52, 0x41, 0x3d, 0x89, 0x73, 0x6b, 0x26, 0x0a, + 0x28, 0x71, 0x6e, 0xcd, 0x45, 0x01, 0x25, 0x96, 0x5a, 0x05, 0x15, 0xb1, 0x11, 0x2c, 0xce, 0x05, + 0x0e, 0x45, 0x47, 0xd6, 0x4d, 0xe1, 0x46, 0xeb, 0xf7, 0x6f, 0x46, 0x48, 0xf6, 0xf6, 0x30, 0xd9, + 0x5b, 0x0f, 0x6a, 0x74, 0x25, 0xe4, 0x09, 0xa7, 0x94, 0xbd, 0x99, 0xfb, 0x6e, 0xf4, 0x7c, 0xc0, + 0xd9, 0x03, 0x06, 0xcb, 0x92, 0x12, 0x0e, 0xe6, 0xca, 0xb1, 0xdf, 0x80, 0xca, 0x53, 0x1e, 0xaa, + 0x1c, 0xbd, 0x48, 0xc6, 0x9e, 0x49, 0xda, 0x5b, 0x4f, 0x49, 0xf1, 0x4b, 0xd2, 0x0c, 0xb6, 0xf6, + 0x88, 0x0f, 0xcf, 0x38, 0x31, 0x27, 0xcb, 0x19, 0x7e, 0xc1, 0x7e, 0x1d, 0x1b, 0x8f, 0x52, 0xa3, + 0x57, 0xb5, 0x24, 0x2c, 0xbd, 0xf1, 0xc6, 0x0c, 0x3c, 0xad, 0x65, 0xd7, 0x1b, 0x72, 0x4d, 0xd6, + 0x73, 0xa1, 0xa2, 0x5d, 0xa1, 0x10, 0x6d, 0xa0, 0xf9, 0x2b, 0x33, 0xa2, 0x0d, 0x94, 0x72, 0xe3, + 0x82, 0xf1, 0x00, 0xfb, 0x31, 0xd8, 0xfd, 0xb8, 0x1f, 0xba, 0x65, 0x21, 0xee, 0xe9, 0xd1, 0x4f, + 0xec, 0x71, 0xf8, 0x05, 0xfb, 0x14, 0x2f, 0x5e, 0xd7, 0x73, 0x10, 0x63, 0xa5, 0x61, 0x36, 0x5d, + 0x31, 0x5a, 0x2c, 0xad, 0x28, 0xa9, 0x48, 0x50, 0x57, 0x28, 0xc9, 0xbd, 0x0f, 0xd0, 0x0b, 0xbd, + 0xc9, 0xb6, 0xcd, 0xc7, 0x9e, 0x1b, 0xf3, 0xda, 0x38, 0x2b, 0x2e, 0xe6, 0x5f, 0x5a, 0x6a, 0x1c, + 0xfb, 0x54, 0xd3, 0xb2, 0x12, 0x69, 0x9c, 0x8a, 0xb8, 0x6e, 0x4c, 0x9c, 0x8b, 0x16, 0x24, 0x25, + 0x79, 0xee, 0x71, 0x86, 0xb5, 0x01, 0xe2, 0xc8, 0xb1, 0x48, 0x67, 0x9a, 0x0b, 0x4a, 0x8b, 0xd8, + 0x5e, 0x4a, 0x98, 0xd9, 0x11, 0x94, 0xe3, 0x90, 0x9b, 0xb5, 0xf8, 0x46, 0x98, 0x44, 0x80, 0x4e, + 0x74, 0x82, 0xcf, 0x85, 0xbb, 0x18, 0x4d, 0x5c, 0x2a, 0x60, 0x25, 0xb1, 0x54, 0xa7, 0x9c, 0x07, + 0xcc, 0x81, 0x25, 0x1a, 0x60, 0x24, 0x2e, 0x61, 0x36, 0x57, 0x74, 0xbf, 0xfe, 0x7c, 0xe4, 0x49, + 0xb4, 0x9b, 0x53, 0xe3, 0x27, 0x12, 0xa6, 0x1f, 0x41, 0xad, 0x94, 0x49, 0x26, 0x58, 0xf3, 0x18, + 0x16, 0xe7, 0x5c, 0xf4, 0xd1, 0x96, 0xbe, 0x29, 0xe6, 0x22, 0xda, 0xd2, 0x37, 0x7a, 0xf7, 0x8d, + 0x15, 0xec, 0xb2, 0x61, 0x00, 0xaa, 0x7a, 0x97, 0x4e, 0x38, 0x38, 0x17, 0xdd, 0xfd, 0xab, 0x0c, + 0x2c, 0xa5, 0x38, 0xe1, 0xd9, 0x1b, 0xca, 0x6a, 0x70, 0xa3, 0x83, 0x7e, 0x3d, 0xd5, 0x59, 0x6b, + 0xf4, 0xb0, 0x9f, 0x7d, 0xf6, 0x2c, 0x71, 0xb0, 0x91, 0xaf, 0x54, 0xee, 0xcc, 0x17, 0x0a, 0x15, + 0xa9, 0x12, 0xc5, 0xe7, 0xb0, 0x46, 0x03, 0x69, 0x8f, 0x46, 0x33, 0x8e, 0xe4, 0xd7, 0xe7, 0xbe, + 0x6c, 0x9f, 0x70, 0x8e, 0xaf, 0xdf, 0xfc, 0xe5, 0xfb, 0x1b, 0xc4, 0x69, 0x1a, 0x2a, 0x9b, 0x42, + 0x73, 0xd6, 0x41, 0xcb, 0x6e, 0x6e, 0x6b, 0xfd, 0x5e, 0x42, 0xff, 0x4d, 0x71, 0xea, 0x7e, 0x0d, + 0x3b, 0xbb, 0x67, 0xac, 0xa7, 0xad, 0x0b, 0xa9, 0xc4, 0xe2, 0x7d, 0xfc, 0xf5, 0xc8, 0x9b, 0x3c, + 0x33, 0x4f, 0xd5, 0xc1, 0x4d, 0xbe, 0xef, 0x48, 0x03, 0x4f, 0x77, 0x46, 0xbf, 0x8d, 0xdd, 0xdf, + 0x37, 0xee, 0xa4, 0x75, 0xef, 0x53, 0x15, 0xd2, 0xc5, 0xd7, 0x66, 0xf7, 0xb5, 0x1a, 0xc1, 0xfd, + 0xb4, 0xf7, 0x7d, 0xa3, 0x2e, 0x34, 0xb3, 0xd6, 0xb7, 0x50, 0xb6, 0xab, 0xea, 0xde, 0xe3, 0x68, + 0xfb, 0xa4, 0xb8, 0xa9, 0xa3, 0xed, 0x93, 0xe6, 0x6e, 0x4e, 0xca, 0x35, 0xca, 0xd1, 0xfc, 0x61, + 0xe6, 0xe1, 0xe6, 0x3b, 0x3f, 0xfc, 0xda, 0x99, 0x13, 0x9e, 0x4f, 0x4f, 0x36, 0x06, 0xde, 0xf8, + 0xd1, 0x48, 0x59, 0x1b, 0x65, 0xca, 0xf3, 0xa3, 0x91, 0x3b, 0x7c, 0x84, 0xcd, 0x9e, 0x2c, 0x4c, + 0x7c, 0x2f, 0xf4, 0xbe, 0xf5, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xc2, 0x01, 0xa8, 0x32, 0xbc, + 0x83, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 5a34ab6252..b508dad65c 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1973,6 +1973,9 @@ message PendingChannelsResponse { balance. */ int64 remote_chan_reserve_sat = 7; + + // True if we initiated opening the channel. + bool initiator = 8; } message PendingOpenChannel { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index feab931a53..e534685ce8 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1692,6 +1692,11 @@ "type": "string", "format": "int64", "description": "*\nThe minimum satoshis the other node is required to reserve in its\nbalance." + }, + "initiator": { + "type": "boolean", + "format": "boolean", + "description": "True if we initiated opening the channel." } } }, diff --git a/rpcserver.go b/rpcserver.go index 1cf9935d78..5cf7b0c86c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2665,6 +2665,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context, RemoteBalance: int64(localCommitment.RemoteBalance.ToSatoshis()), LocalChanReserveSat: int64(pendingChan.LocalChanCfg.ChanReserve), RemoteChanReserveSat: int64(pendingChan.RemoteChanCfg.ChanReserve), + Initiator: pendingChan.IsInitiator, }, CommitWeight: commitWeight, CommitFee: int64(localCommitment.CommitFee), @@ -2697,6 +2698,29 @@ func (r *rpcServer) PendingChannels(ctx context.Context, LocalBalance: int64(pendingClose.SettledBalance), } + // Lookup the channel in the historical channel bucket to obtain + // initiator information. If the historical channel bucket was + // not found, or the channel itself, this channel was closed + // in a version before we started persisting historical + // channels, so we silence the error. + historical, err := r.server.chanDB.FetchHistoricalChannel( + &pendingClose.ChanPoint, + ) + switch err { + // If the channel was closed in a version that did not record + // historical channels, ignore the error. + case channeldb.ErrNoHistoricalBucket: + case channeldb.ErrChannelNotFound: + + case nil: + channel.Initiator = historical.IsInitiator + + // If the error is non-nil, and not due to older versions of lnd + // not persisting historical channels, return it. + default: + return nil, err + } + closeTXID := pendingClose.ClosingTXID.String() switch pendingClose.CloseType { @@ -2813,6 +2837,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context, RemoteBalance: int64(waitingClose.LocalCommitment.RemoteBalance.ToSatoshis()), LocalChanReserveSat: int64(waitingClose.LocalChanCfg.ChanReserve), RemoteChanReserveSat: int64(waitingClose.RemoteChanCfg.ChanReserve), + Initiator: waitingClose.IsInitiator, } waitingCloseResp := &lnrpc.PendingChannelsResponse_WaitingCloseChannel{ From 8b83c1f7f999c23971de125f3761a2becf05bb51 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 25 Mar 2020 08:41:00 +0200 Subject: [PATCH 298/562] lnrpc: add commit fees to WaitingPendingClose --- lnrpc/rpc.pb.go | 1460 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 18 + lnrpc/rpc.swagger.json | 15 + rpcserver.go | 12 +- 4 files changed, 792 insertions(+), 713 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index af20fab4d1..0a5fa13110 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -5801,10 +5801,22 @@ type PendingChannelsResponse_Commitments struct { /// Hash of the remote version of the commitment tx. RemoteTxid string `protobuf:"bytes,2,opt,name=remote_txid,json=remoteTxid,proto3" json:"remote_txid,omitempty"` /// Hash of the remote pending version of the commitment tx. - RemotePendingTxid string `protobuf:"bytes,3,opt,name=remote_pending_txid,json=remotePendingTxid,proto3" json:"remote_pending_txid,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + RemotePendingTxid string `protobuf:"bytes,3,opt,name=remote_pending_txid,json=remotePendingTxid,proto3" json:"remote_pending_txid,omitempty"` + // + //The amount in satoshis calculated to be paid in fees for the local + //commitment. + LocalCommitFeeSat uint64 `protobuf:"varint,4,opt,name=local_commit_fee_sat,json=localCommitFeeSat,proto3" json:"local_commit_fee_sat,omitempty"` + // + //The amount in satoshis calculated to be paid in fees for the remote + //commitment. + RemoteCommitFeeSat uint64 `protobuf:"varint,5,opt,name=remote_commit_fee_sat,json=remoteCommitFeeSat,proto3" json:"remote_commit_fee_sat,omitempty"` + // + //The amount in satoshis calculated to be paid in fees for the remote + //pending commitment. + RemotePendingCommitFeeSat uint64 `protobuf:"varint,6,opt,name=remote_pending_commit_fee_sat,json=remotePendingCommitFeeSat,proto3" json:"remote_pending_commit_fee_sat,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *PendingChannelsResponse_Commitments) Reset() { *m = PendingChannelsResponse_Commitments{} } @@ -5853,6 +5865,27 @@ func (m *PendingChannelsResponse_Commitments) GetRemotePendingTxid() string { return "" } +func (m *PendingChannelsResponse_Commitments) GetLocalCommitFeeSat() uint64 { + if m != nil { + return m.LocalCommitFeeSat + } + return 0 +} + +func (m *PendingChannelsResponse_Commitments) GetRemoteCommitFeeSat() uint64 { + if m != nil { + return m.RemoteCommitFeeSat + } + return 0 +} + +func (m *PendingChannelsResponse_Commitments) GetRemotePendingCommitFeeSat() uint64 { + if m != nil { + return m.RemotePendingCommitFeeSat + } + return 0 +} + type PendingChannelsResponse_ClosedChannel struct { /// The pending channel to be closed Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` @@ -11375,720 +11408,723 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11395 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x8f, 0x24, 0x59, - 0x76, 0x10, 0xde, 0xf9, 0xaa, 0xcc, 0x3c, 0xf9, 0xac, 0x5b, 0xaf, 0xec, 0xea, 0xe9, 0xe9, 0x9e, - 0x98, 0xd9, 0x99, 0xde, 0x9e, 0xdd, 0xea, 0x9e, 0xde, 0x9d, 0xd9, 0xf5, 0xcc, 0xcf, 0xeb, 0xcd, - 0xaa, 0xca, 0xea, 0xca, 0xed, 0x7a, 0x4d, 0x64, 0xd6, 0x8c, 0x67, 0xfd, 0x33, 0xb1, 0x51, 0x99, - 0xb7, 0xaa, 0xc2, 0x9d, 0x19, 0x91, 0x13, 0x11, 0x59, 0x8f, 0x5d, 0x0d, 0x42, 0x08, 0x2c, 0x84, - 0x00, 0xc9, 0x02, 0x23, 0x61, 0xb0, 0x40, 0x20, 0x84, 0x10, 0x92, 0x65, 0x69, 0x8d, 0x04, 0x12, - 0xdf, 0xfd, 0x05, 0x64, 0x21, 0x9b, 0x2f, 0xc8, 0xb2, 0x64, 0x01, 0xcb, 0x37, 0xe4, 0x3f, 0x01, - 0xdd, 0x73, 0xee, 0x8d, 0xb8, 0x91, 0x19, 0xd5, 0xdd, 0xb3, 0x3b, 0xec, 0x97, 0xaa, 0x8c, 0x73, - 0xcf, 0x7d, 0xc6, 0xb9, 0xe7, 0x9e, 0xe7, 0x0d, 0x28, 0xfb, 0x93, 0xc1, 0xc6, 0xc4, 0xf7, 0x42, - 0x8f, 0x15, 0x46, 0xae, 0x3f, 0x19, 0xac, 0xbf, 0x76, 0xe6, 0x79, 0x67, 0x23, 0xfe, 0xc8, 0x9e, - 0x38, 0x8f, 0x6c, 0xd7, 0xf5, 0x42, 0x3b, 0x74, 0x3c, 0x37, 0x20, 0x24, 0xe3, 0x47, 0x50, 0x7f, - 0xca, 0xdd, 0x1e, 0xe7, 0x43, 0x93, 0x7f, 0x3e, 0xe5, 0x41, 0xc8, 0xde, 0x85, 0x45, 0x9b, 0xff, - 0x98, 0xf3, 0xa1, 0x35, 0xb1, 0x83, 0x60, 0x72, 0xee, 0xdb, 0x01, 0x6f, 0x65, 0xee, 0x67, 0x1e, - 0x54, 0xcd, 0x26, 0x15, 0x1c, 0x45, 0x70, 0xf6, 0x06, 0x54, 0x03, 0x81, 0xca, 0xdd, 0xd0, 0xf7, - 0x26, 0xd7, 0xad, 0x2c, 0xe2, 0x55, 0x04, 0xac, 0x43, 0x20, 0x63, 0x04, 0x8d, 0xa8, 0x87, 0x60, - 0xe2, 0xb9, 0x01, 0x67, 0x8f, 0x61, 0x79, 0xe0, 0x4c, 0xce, 0xb9, 0x6f, 0x61, 0xe5, 0xb1, 0xcb, - 0xc7, 0x9e, 0xeb, 0x0c, 0x5a, 0x99, 0xfb, 0xb9, 0x07, 0x65, 0x93, 0x51, 0x99, 0xa8, 0xb1, 0x2f, - 0x4b, 0xd8, 0x3b, 0xd0, 0xe0, 0x2e, 0xc1, 0xf9, 0x10, 0x6b, 0xc9, 0xae, 0xea, 0x31, 0x58, 0x54, - 0x30, 0xfe, 0x4e, 0x16, 0x16, 0xbb, 0xae, 0x13, 0x7e, 0x6a, 0x8f, 0x46, 0x3c, 0x54, 0x73, 0x7a, - 0x07, 0x1a, 0x97, 0x08, 0xc0, 0x39, 0x5d, 0x7a, 0xfe, 0x50, 0xce, 0xa8, 0x4e, 0xe0, 0x23, 0x09, - 0xbd, 0x71, 0x64, 0xd9, 0x1b, 0x47, 0x96, 0xba, 0x5c, 0xb9, 0x1b, 0x96, 0xeb, 0x1d, 0x68, 0xf8, - 0x7c, 0xe0, 0x5d, 0x70, 0xff, 0xda, 0xba, 0x74, 0xdc, 0xa1, 0x77, 0xd9, 0xca, 0xdf, 0xcf, 0x3c, - 0x28, 0x98, 0x75, 0x05, 0xfe, 0x14, 0xa1, 0x6c, 0x13, 0x1a, 0x83, 0x73, 0xdb, 0x75, 0xf9, 0xc8, - 0x3a, 0xb1, 0x07, 0xcf, 0xa7, 0x93, 0xa0, 0x55, 0xb8, 0x9f, 0x79, 0x50, 0x79, 0x72, 0x7b, 0x03, - 0xdf, 0xea, 0xc6, 0xd6, 0xb9, 0xed, 0x6e, 0x62, 0x49, 0xcf, 0xb5, 0x27, 0xc1, 0xb9, 0x17, 0x9a, - 0x75, 0x59, 0x83, 0xc0, 0x81, 0xb1, 0x0c, 0x4c, 0x5f, 0x09, 0x5a, 0x7b, 0xe3, 0xdf, 0x65, 0x60, - 0xe9, 0xd8, 0x1d, 0x79, 0x83, 0xe7, 0x3f, 0xe7, 0x12, 0xa5, 0xcc, 0x21, 0xfb, 0xaa, 0x73, 0xc8, - 0x7d, 0xd9, 0x39, 0xac, 0xc2, 0x72, 0x72, 0xb0, 0x72, 0x16, 0x1c, 0x56, 0x44, 0xed, 0x33, 0xae, - 0x86, 0xa5, 0xa6, 0xf1, 0x75, 0x68, 0x0e, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x79, 0x34, 0x24, 0x3c, - 0x9a, 0xc8, 0x1b, 0x50, 0x75, 0xf9, 0x65, 0x8c, 0x26, 0x69, 0xd7, 0xe5, 0x97, 0x0a, 0xc5, 0x68, - 0xc1, 0xea, 0x6c, 0x37, 0x72, 0x00, 0x3f, 0xcb, 0x40, 0xfe, 0x38, 0xbc, 0xf2, 0xd8, 0xfb, 0x50, - 0xb5, 0x87, 0x43, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x4f, 0x68, 0xa7, 0xd4, 0x9f, 0x30, 0x39, 0xc5, - 0x36, 0x15, 0xf5, 0xaf, 0x27, 0xdc, 0xac, 0xd8, 0xf1, 0x03, 0x6b, 0x41, 0x51, 0x3e, 0x62, 0xbf, - 0x65, 0x53, 0x3d, 0xb2, 0xbb, 0x00, 0xf6, 0xd8, 0x9b, 0xba, 0xa1, 0x15, 0xd8, 0x21, 0xae, 0x58, - 0xce, 0x2c, 0x13, 0xa4, 0x67, 0x87, 0xec, 0x0e, 0x94, 0x27, 0xcf, 0xad, 0x60, 0xe0, 0x3b, 0x93, - 0x10, 0x89, 0xa7, 0x6c, 0x96, 0x26, 0xcf, 0x7b, 0xf8, 0xcc, 0xde, 0x85, 0x92, 0x37, 0x0d, 0x27, - 0x9e, 0xe3, 0x86, 0x92, 0x5e, 0x1a, 0x72, 0x20, 0x87, 0xd3, 0xf0, 0x48, 0x80, 0xcd, 0x08, 0x81, - 0xbd, 0x05, 0xb5, 0x81, 0xe7, 0x9e, 0x3a, 0xfe, 0x98, 0x38, 0x42, 0x6b, 0x01, 0xfb, 0x4a, 0x02, - 0x8d, 0x3f, 0xcc, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, 0x41, 0x31, 0xbc, - 0xb2, 0xce, 0xed, 0xe0, 0x1c, 0xa7, 0x5a, 0x36, 0x17, 0xc2, 0xab, 0x5d, 0x3b, 0x38, 0x67, 0xab, - 0xb0, 0x40, 0xa3, 0xc4, 0x09, 0xe5, 0x4c, 0xf9, 0x24, 0x36, 0x88, 0x3b, 0x1d, 0x5b, 0xc9, 0xae, - 0x72, 0x48, 0x31, 0x4d, 0x77, 0x3a, 0xde, 0xd2, 0xe1, 0x62, 0xf2, 0x27, 0xe2, 0x75, 0x53, 0x07, - 0x34, 0xbd, 0x32, 0x42, 0xb0, 0x8f, 0x37, 0xa0, 0x2a, 0x8b, 0xb9, 0x73, 0x76, 0x4e, 0x73, 0x2c, - 0x98, 0x15, 0x42, 0x40, 0x90, 0x68, 0x21, 0x74, 0xc6, 0xdc, 0x0a, 0x42, 0x7b, 0x3c, 0x91, 0x53, - 0x2a, 0x0b, 0x48, 0x4f, 0x00, 0xb0, 0xd8, 0x0b, 0xed, 0x91, 0x75, 0xca, 0x79, 0xd0, 0x2a, 0xca, - 0x62, 0x01, 0xd9, 0xe1, 0x3c, 0x60, 0x5f, 0x83, 0xfa, 0x90, 0x07, 0xa1, 0x25, 0x5f, 0x06, 0x0f, - 0x5a, 0x25, 0xdc, 0xf9, 0x35, 0x01, 0x6d, 0x2b, 0x20, 0x7b, 0x0d, 0xc0, 0xb7, 0x2f, 0x2d, 0xb1, - 0x10, 0xfc, 0xaa, 0x55, 0xa6, 0xb7, 0xe0, 0xdb, 0x97, 0xfd, 0xab, 0x5d, 0x7e, 0x25, 0xa8, 0xe6, - 0x29, 0x0f, 0xb5, 0x45, 0x0b, 0x24, 0x75, 0x1a, 0x7b, 0xc0, 0x34, 0xf0, 0x36, 0x0f, 0x6d, 0x67, - 0x14, 0xb0, 0x0f, 0xa0, 0x1a, 0x6a, 0xc8, 0xc8, 0x06, 0x2b, 0x11, 0x09, 0x69, 0x15, 0xcc, 0x04, - 0x9e, 0x71, 0x0e, 0xa5, 0x1d, 0xce, 0xf7, 0x9c, 0xb1, 0x13, 0xb2, 0x55, 0x28, 0x9c, 0x3a, 0x57, - 0x9c, 0x88, 0x3d, 0xb7, 0x7b, 0xcb, 0xa4, 0x47, 0x76, 0x0f, 0x00, 0x7f, 0x58, 0xe3, 0x88, 0x9a, - 0x76, 0x6f, 0x99, 0x65, 0x84, 0xed, 0x07, 0x76, 0xc8, 0xd6, 0xa1, 0x38, 0xe1, 0xfe, 0x80, 0xab, - 0xf7, 0xb6, 0x7b, 0xcb, 0x54, 0x80, 0xcd, 0x22, 0x14, 0x46, 0xa2, 0x75, 0xe3, 0x8f, 0x0b, 0x50, - 0xe9, 0x71, 0x37, 0xda, 0x65, 0x0c, 0xf2, 0x62, 0x41, 0xe4, 0xce, 0xc2, 0xdf, 0xec, 0x4d, 0xa8, - 0xe0, 0xd2, 0x05, 0xa1, 0xef, 0xb8, 0x67, 0x44, 0xd5, 0x9b, 0xd9, 0x56, 0xc6, 0x04, 0x01, 0xee, - 0x21, 0x94, 0x35, 0x21, 0x67, 0x8f, 0x15, 0x55, 0x8b, 0x9f, 0xec, 0x36, 0x94, 0xec, 0x71, 0x48, - 0xc3, 0xab, 0x22, 0xb8, 0x68, 0x8f, 0x43, 0x1c, 0xda, 0x1b, 0x50, 0x9d, 0xd8, 0xd7, 0x63, 0xb1, - 0x97, 0x23, 0x72, 0xa8, 0x9a, 0x15, 0x09, 0x43, 0x82, 0x78, 0x02, 0x4b, 0x3a, 0x8a, 0xea, 0xbc, - 0x10, 0x75, 0xbe, 0xa8, 0x61, 0xcb, 0x31, 0xbc, 0x03, 0x0d, 0x55, 0xc7, 0xa7, 0xf9, 0x20, 0x99, - 0x94, 0xcd, 0xba, 0x04, 0xab, 0x59, 0x3e, 0x80, 0xe6, 0xa9, 0xe3, 0xda, 0x23, 0x6b, 0x30, 0x0a, - 0x2f, 0xac, 0x21, 0x1f, 0x85, 0x36, 0x52, 0x4c, 0xc1, 0xac, 0x23, 0x7c, 0x6b, 0x14, 0x5e, 0x6c, - 0x0b, 0x28, 0xfb, 0x06, 0x94, 0x4f, 0x39, 0xb7, 0x70, 0xb1, 0x5a, 0xa5, 0xc4, 0xc6, 0x53, 0x6f, - 0xc8, 0x2c, 0x9d, 0xaa, 0x77, 0xf5, 0x0d, 0x68, 0x7a, 0xd3, 0xf0, 0xcc, 0x73, 0xdc, 0x33, 0x4b, - 0xf0, 0x3b, 0xcb, 0x19, 0x22, 0x0d, 0xe5, 0x37, 0xb3, 0x8f, 0x33, 0x66, 0x5d, 0x95, 0x09, 0xce, - 0xd3, 0x1d, 0xb2, 0xb7, 0xa1, 0x31, 0xb2, 0x83, 0xd0, 0x3a, 0xf7, 0x26, 0xd6, 0x64, 0x7a, 0xf2, - 0x9c, 0x5f, 0xb7, 0x6a, 0xb8, 0x10, 0x35, 0x01, 0xde, 0xf5, 0x26, 0x47, 0x08, 0x14, 0x94, 0x8d, - 0xe3, 0xa4, 0x41, 0xc0, 0xfd, 0xcc, 0x83, 0x9a, 0x59, 0x16, 0x10, 0xea, 0xf4, 0x33, 0x58, 0xc2, - 0xd7, 0x33, 0x98, 0x06, 0xa1, 0x37, 0xb6, 0x04, 0xaf, 0xf6, 0x87, 0x41, 0xab, 0x82, 0xb4, 0xf6, - 0x75, 0x39, 0x58, 0xed, 0x1d, 0x6f, 0x6c, 0xf3, 0x20, 0xdc, 0x42, 0x64, 0x93, 0x70, 0xc5, 0x81, - 0x7e, 0x6d, 0x2e, 0x0e, 0x67, 0xe1, 0xec, 0x1b, 0xc0, 0xec, 0xd1, 0xc8, 0xbb, 0xb4, 0x02, 0x3e, - 0x3a, 0xb5, 0xe4, 0x22, 0xb6, 0xea, 0xf7, 0x33, 0x0f, 0x4a, 0x66, 0x13, 0x4b, 0x7a, 0x7c, 0x74, - 0x7a, 0x44, 0x70, 0xf6, 0x01, 0xe0, 0x66, 0xb2, 0x4e, 0xb9, 0x1d, 0x4e, 0x7d, 0x1e, 0xb4, 0x1a, - 0xf7, 0x73, 0x0f, 0xea, 0x4f, 0x16, 0xa3, 0xf5, 0x42, 0xf0, 0xa6, 0x13, 0x9a, 0x55, 0x81, 0x27, - 0x9f, 0x83, 0xf5, 0x6d, 0x58, 0x4d, 0x1f, 0x92, 0x20, 0x2a, 0xb1, 0x2a, 0x82, 0x18, 0xf3, 0xa6, - 0xf8, 0xc9, 0x96, 0xa1, 0x70, 0x61, 0x8f, 0xa6, 0x5c, 0xf2, 0x74, 0x7a, 0xf8, 0x30, 0xfb, 0xdd, - 0x8c, 0xf1, 0x47, 0x19, 0xa8, 0xd2, 0x2c, 0xa5, 0x2c, 0xf2, 0x26, 0xd4, 0x14, 0x35, 0x70, 0xdf, - 0xf7, 0x7c, 0xc9, 0xd5, 0x14, 0xe5, 0x75, 0x04, 0x4c, 0x9c, 0x2a, 0x0a, 0x69, 0xe2, 0x73, 0x67, - 0x6c, 0x9f, 0xa9, 0xa6, 0x15, 0x29, 0x1d, 0x49, 0x30, 0x7b, 0x2f, 0x6e, 0xcf, 0xf7, 0xa6, 0x21, - 0x97, 0x67, 0x5e, 0x55, 0x4e, 0xcf, 0x14, 0xb0, 0xa8, 0x75, 0x7c, 0x7a, 0x05, 0x3a, 0x37, 0x7e, - 0x37, 0x03, 0x4c, 0x0c, 0xbb, 0xef, 0x51, 0x03, 0x92, 0x42, 0x67, 0x6b, 0x66, 0x5e, 0x79, 0x87, - 0x64, 0x5f, 0xb4, 0x43, 0x0c, 0x28, 0xd0, 0xd8, 0xf3, 0x29, 0x63, 0xa7, 0xa2, 0x1f, 0xe4, 0x4b, - 0xb9, 0x66, 0xde, 0xf8, 0xef, 0x39, 0x58, 0xde, 0xa2, 0x23, 0xbb, 0x3d, 0x18, 0xf0, 0x49, 0xb4, - 0x77, 0xee, 0x41, 0xc5, 0xf5, 0x86, 0x5c, 0x51, 0x2c, 0x0d, 0x0c, 0x04, 0x48, 0x23, 0xd7, 0x73, - 0xdb, 0x71, 0x69, 0xe0, 0xb4, 0x98, 0x65, 0x84, 0xe0, 0xb0, 0xdf, 0x86, 0xc6, 0x84, 0xbb, 0x43, - 0x7d, 0x8b, 0x90, 0x50, 0x55, 0x93, 0x60, 0xb9, 0x3b, 0xee, 0x41, 0xe5, 0x74, 0x4a, 0x78, 0x82, - 0xb1, 0xe4, 0x91, 0x06, 0x40, 0x82, 0xda, 0xc4, 0x5f, 0x26, 0xd3, 0xe0, 0x1c, 0x4b, 0x0b, 0x58, - 0x5a, 0x14, 0xcf, 0xa2, 0xe8, 0x2e, 0xc0, 0x70, 0x1a, 0x84, 0x72, 0xc7, 0x2c, 0x60, 0x61, 0x59, - 0x40, 0x68, 0xc7, 0x7c, 0x13, 0x96, 0xc6, 0xf6, 0x95, 0x85, 0xb4, 0x63, 0x39, 0xae, 0x75, 0x3a, - 0xc2, 0x33, 0xa7, 0x88, 0x78, 0xcd, 0xb1, 0x7d, 0xf5, 0x89, 0x28, 0xe9, 0xba, 0x3b, 0x08, 0x17, - 0x6c, 0x45, 0x89, 0x3b, 0x3e, 0x0f, 0xb8, 0x7f, 0xc1, 0x91, 0x13, 0xe4, 0x23, 0x99, 0xc6, 0x24, - 0xa8, 0x18, 0xd1, 0x58, 0xcc, 0x3b, 0x1c, 0x0d, 0x68, 0xdb, 0x9b, 0xc5, 0xb1, 0xe3, 0xee, 0x86, - 0xa3, 0x81, 0x38, 0x57, 0x04, 0x1f, 0x99, 0x70, 0xdf, 0x7a, 0x7e, 0x89, 0x7b, 0x38, 0x8f, 0x7c, - 0xe3, 0x88, 0xfb, 0xcf, 0x2e, 0xc5, 0xd1, 0x3f, 0x08, 0x90, 0x11, 0xd9, 0xd7, 0xad, 0x0a, 0x6e, - 0xf0, 0xd2, 0x20, 0x10, 0x2c, 0xc8, 0xbe, 0x16, 0x9b, 0x50, 0x8c, 0xd6, 0xc6, 0xb7, 0xc0, 0x87, - 0xd8, 0x7c, 0x80, 0x1c, 0xb5, 0x86, 0x83, 0x6d, 0xcb, 0x02, 0xd1, 0x4f, 0x20, 0xa8, 0x5e, 0x0d, - 0xf6, 0x74, 0x64, 0x9f, 0x05, 0xc8, 0x52, 0x6a, 0x66, 0x55, 0x02, 0x77, 0x04, 0xcc, 0xf8, 0x94, - 0x84, 0x2c, 0xed, 0xdd, 0xca, 0x3d, 0x23, 0x8e, 0x7a, 0x84, 0xe0, 0x7b, 0x2d, 0x99, 0xf2, 0x29, - 0xed, 0xa5, 0x65, 0x53, 0x5e, 0x9a, 0xf1, 0xfb, 0x19, 0xa8, 0xca, 0x96, 0x51, 0x28, 0x61, 0x1b, - 0xc0, 0xd4, 0x5b, 0x0c, 0xaf, 0x9c, 0xa1, 0x75, 0x72, 0x1d, 0xf2, 0x80, 0x88, 0x66, 0xf7, 0x96, - 0xd9, 0x94, 0x65, 0xfd, 0x2b, 0x67, 0xb8, 0x29, 0x4a, 0xd8, 0x43, 0x68, 0x26, 0xf0, 0x83, 0xd0, - 0x27, 0x8a, 0xde, 0xbd, 0x65, 0xd6, 0x35, 0xec, 0x5e, 0xe8, 0x8b, 0x3d, 0x22, 0x44, 0x9e, 0x69, - 0x68, 0x39, 0xee, 0x90, 0x5f, 0x21, 0x19, 0xd5, 0xcc, 0x0a, 0xc1, 0xba, 0x02, 0xb4, 0x59, 0x87, - 0xaa, 0xde, 0x9c, 0x71, 0x06, 0x25, 0x25, 0x2f, 0xa1, 0xc0, 0x30, 0x33, 0x24, 0xb3, 0x1c, 0x46, - 0x23, 0xb9, 0x0d, 0xa5, 0xe4, 0x08, 0xcc, 0x62, 0xf8, 0xca, 0x1d, 0x1b, 0xdf, 0x83, 0xe6, 0x9e, - 0x20, 0x1e, 0x57, 0x10, 0xab, 0x94, 0xff, 0x56, 0x61, 0x41, 0xdb, 0x34, 0x65, 0x53, 0x3e, 0x89, - 0x33, 0xf7, 0xdc, 0x0b, 0x42, 0xd9, 0x0b, 0xfe, 0x36, 0xfe, 0x38, 0x03, 0xac, 0x13, 0x84, 0xce, - 0xd8, 0x0e, 0xf9, 0x0e, 0x8f, 0xd8, 0xc2, 0x21, 0x54, 0x45, 0x6b, 0x7d, 0xaf, 0x4d, 0x02, 0x19, - 0x09, 0x14, 0xef, 0xca, 0x6d, 0x3c, 0x5f, 0x61, 0x43, 0xc7, 0x26, 0x36, 0x9f, 0x68, 0x40, 0xec, - 0xb2, 0xd0, 0xf6, 0xcf, 0x78, 0x88, 0x62, 0x9c, 0x94, 0xf7, 0x81, 0x40, 0x42, 0x80, 0x5b, 0xff, - 0x35, 0x58, 0x9c, 0x6b, 0x43, 0xe7, 0xcb, 0xe5, 0x14, 0xbe, 0x9c, 0xd3, 0xf9, 0xb2, 0x05, 0x4b, - 0x89, 0x71, 0x49, 0x4a, 0x5b, 0x83, 0xa2, 0xd8, 0x10, 0x42, 0x38, 0xc8, 0x90, 0x54, 0x79, 0xca, - 0xb9, 0x10, 0x83, 0x1f, 0xc1, 0xf2, 0x29, 0xe7, 0xbe, 0x1d, 0x62, 0x21, 0xee, 0x18, 0xf1, 0x86, - 0x64, 0xc3, 0x8b, 0xb2, 0xac, 0x67, 0x87, 0x47, 0xdc, 0x17, 0x6f, 0xca, 0xf8, 0x1f, 0x19, 0x68, - 0x08, 0x0e, 0xba, 0x6f, 0xbb, 0xd7, 0x6a, 0x9d, 0xf6, 0x52, 0xd7, 0xe9, 0x81, 0x76, 0x18, 0x6a, - 0xd8, 0x5f, 0x76, 0x91, 0x72, 0xb3, 0x8b, 0xc4, 0xee, 0x43, 0x35, 0x31, 0xd6, 0x02, 0x8e, 0x15, - 0x82, 0x68, 0x90, 0xbf, 0xf8, 0x32, 0xbe, 0x0d, 0xcd, 0x78, 0xd8, 0x72, 0x0d, 0x19, 0xe4, 0x05, - 0x49, 0xca, 0x06, 0xf0, 0xb7, 0xf1, 0xcf, 0x32, 0x84, 0xb8, 0xe5, 0x39, 0x91, 0x74, 0x2a, 0x10, - 0x85, 0xdc, 0xab, 0x10, 0xc5, 0xef, 0x1b, 0xa5, 0xfa, 0x5f, 0x7c, 0xb2, 0x62, 0xeb, 0x04, 0xdc, - 0x1d, 0x5a, 0xf6, 0x68, 0x84, 0xcc, 0xb7, 0x64, 0x16, 0xc5, 0x73, 0x7b, 0x34, 0x32, 0xde, 0x81, - 0x45, 0x6d, 0x74, 0x2f, 0x98, 0xc7, 0x01, 0xb0, 0x3d, 0x27, 0x08, 0x8f, 0xdd, 0x60, 0xa2, 0x09, - 0x6e, 0x77, 0xa0, 0x2c, 0x38, 0xac, 0x18, 0x19, 0x6d, 0xd9, 0x82, 0x29, 0x58, 0xae, 0x18, 0x57, - 0x80, 0x85, 0xf6, 0x95, 0x2c, 0xcc, 0xca, 0x42, 0xfb, 0x0a, 0x0b, 0x8d, 0xef, 0xc2, 0x52, 0xa2, - 0x3d, 0xd9, 0xf5, 0x1b, 0x50, 0x98, 0x86, 0x57, 0x9e, 0x12, 0xcd, 0x2b, 0x92, 0x42, 0x84, 0x02, - 0x68, 0x52, 0x89, 0xf1, 0x11, 0x2c, 0x1e, 0xf0, 0x4b, 0xb9, 0x89, 0xd5, 0x40, 0xde, 0x86, 0xfc, - 0x4b, 0x94, 0x42, 0x2c, 0x37, 0x36, 0x80, 0xe9, 0x95, 0x65, 0xaf, 0x9a, 0x8e, 0x98, 0x49, 0xe8, - 0x88, 0xc6, 0xdb, 0xc0, 0x7a, 0xce, 0x99, 0xbb, 0xcf, 0x83, 0xc0, 0x3e, 0x8b, 0xb6, 0x7d, 0x13, - 0x72, 0xe3, 0xe0, 0x4c, 0xf2, 0x28, 0xf1, 0xd3, 0xf8, 0x16, 0x2c, 0x25, 0xf0, 0x64, 0xc3, 0xaf, - 0x41, 0x39, 0x70, 0xce, 0x5c, 0x14, 0xac, 0x64, 0xd3, 0x31, 0xc0, 0xd8, 0x81, 0xe5, 0x4f, 0xb8, - 0xef, 0x9c, 0x5e, 0xbf, 0xac, 0xf9, 0x64, 0x3b, 0xd9, 0xd9, 0x76, 0x3a, 0xb0, 0x32, 0xd3, 0x8e, - 0xec, 0x9e, 0xc8, 0x57, 0xbe, 0xc9, 0x92, 0x49, 0x0f, 0x1a, 0xdf, 0xcb, 0xea, 0x7c, 0xcf, 0x38, - 0x06, 0xb6, 0xe5, 0xb9, 0x2e, 0x1f, 0x84, 0x47, 0x9c, 0xfb, 0xb1, 0x95, 0x2a, 0xa6, 0xd5, 0xca, - 0x93, 0x35, 0xb9, 0xb2, 0xb3, 0xcc, 0x54, 0x12, 0x31, 0x83, 0xfc, 0x84, 0xfb, 0x63, 0x6c, 0xb8, - 0x64, 0xe2, 0x6f, 0x63, 0x05, 0x96, 0x12, 0xcd, 0x4a, 0xbd, 0xfe, 0x31, 0xac, 0x6c, 0x3b, 0xc1, - 0x60, 0xbe, 0xc3, 0x35, 0x28, 0x4e, 0xa6, 0x27, 0x56, 0x92, 0x2f, 0x3f, 0xe3, 0xd7, 0x42, 0xdb, - 0x9b, 0xad, 0x21, 0xdb, 0xfa, 0x5b, 0x19, 0xc8, 0xef, 0xf6, 0xf7, 0xb6, 0xd8, 0x3a, 0x94, 0x1c, - 0x77, 0xe0, 0x8d, 0x85, 0xe0, 0x45, 0x73, 0x8e, 0x9e, 0x6f, 0xdc, 0x60, 0x77, 0xa0, 0x8c, 0xf2, - 0x9a, 0x50, 0x6d, 0xa5, 0xe8, 0x53, 0x12, 0x80, 0x3d, 0x6f, 0xf0, 0x5c, 0xe8, 0xd4, 0xfc, 0x6a, - 0xe2, 0xf8, 0xa8, 0x35, 0x2b, 0x65, 0x38, 0x4f, 0x67, 0x7d, 0x5c, 0x40, 0x1a, 0xb1, 0xf1, 0x1f, - 0x4b, 0x50, 0x94, 0xa7, 0x2d, 0x9d, 0xdc, 0xa1, 0x73, 0xc1, 0xe3, 0x93, 0x5b, 0x3c, 0x09, 0x79, - 0xc0, 0xe7, 0x63, 0x2f, 0x8c, 0x04, 0x36, 0x7a, 0x07, 0x55, 0x02, 0x4a, 0x91, 0x4d, 0x13, 0x1a, - 0xc8, 0xc4, 0x90, 0x23, 0xa4, 0x81, 0x7e, 0x94, 0xdf, 0x81, 0xa2, 0x3a, 0xfb, 0xf3, 0x91, 0x4e, - 0xb3, 0x30, 0x20, 0x69, 0x6d, 0x1d, 0x4a, 0x03, 0x7b, 0x62, 0x0f, 0x9c, 0xf0, 0x5a, 0x32, 0x84, - 0xe8, 0x59, 0xb4, 0x3e, 0xf2, 0x06, 0xf6, 0xc8, 0x3a, 0xb1, 0x47, 0xb6, 0x3b, 0xe0, 0x52, 0x77, - 0xaf, 0x22, 0x70, 0x93, 0x60, 0x42, 0x3f, 0x97, 0xe3, 0x54, 0x58, 0xa4, 0xc2, 0xcb, 0xd1, 0x2b, - 0x34, 0x21, 0x5c, 0x7a, 0xe3, 0xb1, 0x23, 0xb4, 0x0c, 0x12, 0xc3, 0x72, 0x66, 0x99, 0x20, 0x3b, - 0x1c, 0x67, 0x2b, 0x8b, 0x2f, 0x69, 0xe9, 0xca, 0xd4, 0x15, 0x01, 0x3f, 0x25, 0x43, 0xc2, 0xbc, - 0x2c, 0x96, 0xd3, 0x64, 0xb1, 0x77, 0x61, 0x71, 0xea, 0x06, 0x3c, 0x0c, 0x47, 0x7c, 0x18, 0x8d, - 0xa5, 0x82, 0x48, 0xcd, 0xa8, 0x40, 0x0d, 0x67, 0x03, 0x96, 0xc8, 0xe8, 0x10, 0xd8, 0xa1, 0x17, - 0x9c, 0x3b, 0x81, 0x15, 0x08, 0x0d, 0x89, 0xd4, 0xdd, 0x45, 0x2c, 0xea, 0xc9, 0x92, 0x1e, 0xa9, - 0x48, 0x6b, 0x33, 0xf8, 0x3e, 0x1f, 0x70, 0xe7, 0x82, 0x0f, 0x51, 0x4e, 0xcb, 0x99, 0x2b, 0x89, - 0x3a, 0xa6, 0x2c, 0x44, 0xa1, 0x7b, 0x3a, 0xb6, 0xa6, 0x93, 0xa1, 0x2d, 0x84, 0x95, 0x3a, 0x09, - 0xc3, 0xee, 0x74, 0x7c, 0x4c, 0x10, 0xf6, 0x18, 0x94, 0x24, 0x26, 0xe5, 0xc3, 0x46, 0x82, 0x9f, - 0x09, 0x62, 0x35, 0xab, 0x12, 0x83, 0x04, 0xc5, 0x84, 0xcc, 0xd9, 0x9c, 0x91, 0x39, 0x5b, 0x50, - 0x9c, 0xf8, 0xce, 0x85, 0x1d, 0xf2, 0xd6, 0x22, 0x31, 0x70, 0xf9, 0x28, 0x38, 0x83, 0xe3, 0x3a, - 0xa1, 0x63, 0x87, 0x9e, 0xdf, 0x62, 0x58, 0x16, 0x03, 0xd8, 0x43, 0x58, 0x44, 0x1a, 0x09, 0x42, - 0x3b, 0x9c, 0x06, 0x52, 0x02, 0x5d, 0x42, 0x62, 0x42, 0x19, 0xba, 0x87, 0x70, 0x14, 0x42, 0xd9, - 0xb7, 0x60, 0x95, 0xc8, 0x02, 0x6b, 0x48, 0xc9, 0x1a, 0x05, 0x82, 0x65, 0x5c, 0x8a, 0x25, 0x2c, - 0x15, 0xf4, 0x2d, 0xe5, 0x6b, 0x21, 0x1d, 0xbc, 0x0f, 0x6b, 0x92, 0x4c, 0xe6, 0x6a, 0xad, 0x60, - 0xad, 0x65, 0x2a, 0x9e, 0xa9, 0xb6, 0x01, 0x8b, 0x62, 0x48, 0xce, 0xc0, 0x92, 0xb5, 0xc5, 0x4e, - 0x58, 0x15, 0xa3, 0x47, 0x4d, 0xa9, 0x41, 0x85, 0x26, 0x96, 0x3d, 0xe3, 0xd7, 0xec, 0x7b, 0xd0, - 0x20, 0x92, 0x41, 0xf5, 0x0a, 0x39, 0xfd, 0x3a, 0x72, 0xfa, 0x15, 0x65, 0xe1, 0x8c, 0x4a, 0x91, - 0xd9, 0xd7, 0x07, 0x89, 0x67, 0xb1, 0x1d, 0x46, 0xce, 0x29, 0x0f, 0x9d, 0x31, 0x6f, 0xad, 0x11, - 0x81, 0xa9, 0x67, 0xb1, 0x53, 0xa7, 0x13, 0x2c, 0x69, 0x11, 0x5f, 0xa0, 0x27, 0xa4, 0xdd, 0x91, - 0x17, 0x70, 0x65, 0xa2, 0x6a, 0xdd, 0x96, 0x9b, 0x50, 0x00, 0x95, 0x0c, 0x29, 0x04, 0x71, 0x52, - 0x7a, 0x22, 0x43, 0xe2, 0x1d, 0x24, 0x86, 0x1a, 0xe9, 0x3e, 0xca, 0x98, 0x28, 0x4e, 0xf1, 0x73, - 0xfb, 0x52, 0x71, 0x90, 0xd7, 0xf0, 0xfd, 0x82, 0x00, 0x49, 0xde, 0xf1, 0xd3, 0x0c, 0x1d, 0x88, - 0x92, 0x7f, 0x04, 0x9a, 0x7a, 0x47, 0x9c, 0xc3, 0xf2, 0xdc, 0xd1, 0xb5, 0x64, 0x26, 0x40, 0xa0, - 0x43, 0x77, 0x84, 0xbb, 0xd9, 0x71, 0x75, 0x14, 0xe2, 0xbd, 0x55, 0x05, 0x44, 0xa4, 0x7b, 0x50, - 0x99, 0x4c, 0x4f, 0x46, 0xce, 0x80, 0x50, 0x72, 0xd4, 0x0a, 0x81, 0x10, 0x41, 0xe8, 0xb7, 0x44, - 0x51, 0x84, 0x91, 0x47, 0x8c, 0x8a, 0x84, 0x21, 0x0a, 0xf2, 0x76, 0xee, 0x23, 0x3b, 0xa9, 0x9a, - 0xf8, 0xdb, 0xd8, 0x84, 0xe5, 0xe4, 0xa0, 0xe5, 0xc1, 0xf3, 0x10, 0x4a, 0x92, 0x57, 0x29, 0xc3, - 0x47, 0x5d, 0x33, 0x45, 0x0b, 0x15, 0x2d, 0x2a, 0x37, 0x7e, 0x7b, 0x01, 0x96, 0x24, 0x74, 0x4b, - 0x2c, 0x6d, 0x6f, 0x3a, 0x1e, 0xdb, 0x7e, 0x0a, 0x13, 0xcc, 0xbc, 0x98, 0x09, 0x66, 0xe7, 0x98, - 0x60, 0x52, 0xf3, 0x25, 0x1e, 0x9a, 0xd4, 0x7c, 0xc5, 0xbb, 0x24, 0x65, 0x44, 0xb7, 0x83, 0xd6, - 0x24, 0xb8, 0x4f, 0xf6, 0xd6, 0x39, 0x96, 0x5d, 0x48, 0x61, 0xd9, 0x3a, 0xc3, 0x5d, 0x98, 0x61, - 0xb8, 0x6f, 0x00, 0x11, 0x8d, 0x7a, 0xfb, 0x45, 0xd2, 0x4f, 0x10, 0x26, 0x8d, 0xa9, 0xef, 0x40, - 0x63, 0x96, 0xc7, 0x11, 0x33, 0xad, 0xa7, 0x70, 0x38, 0x67, 0xcc, 0xf1, 0xb4, 0xd2, 0x90, 0xcb, - 0x92, 0xc3, 0x39, 0x63, 0xbe, 0x87, 0x25, 0x0a, 0xbf, 0x03, 0x40, 0x7d, 0xe3, 0xa6, 0x01, 0xdc, - 0x34, 0x6f, 0x27, 0xdf, 0x85, 0xbe, 0xea, 0x1b, 0xe2, 0x61, 0xea, 0x73, 0xdc, 0x45, 0x65, 0xac, - 0x89, 0x1b, 0xe8, 0x19, 0xd4, 0xbd, 0x09, 0x77, 0xad, 0x98, 0xd7, 0x54, 0xb0, 0xa9, 0xb7, 0x5e, - 0xd0, 0x54, 0x57, 0xe1, 0x9a, 0x35, 0x51, 0x37, 0x7a, 0x64, 0xfb, 0xb4, 0xf0, 0x5c, 0x6b, 0xad, - 0xfa, 0x25, 0x5a, 0xab, 0x63, 0xe5, 0xe8, 0xd9, 0xf8, 0xbb, 0x19, 0xa8, 0x68, 0xc3, 0x66, 0x2b, - 0xb0, 0xb8, 0x75, 0x78, 0x78, 0xd4, 0x31, 0xdb, 0xfd, 0xee, 0x27, 0x1d, 0x6b, 0x6b, 0xef, 0xb0, - 0xd7, 0x69, 0xde, 0x12, 0xe0, 0xbd, 0xc3, 0xad, 0xf6, 0x9e, 0xb5, 0x73, 0x68, 0x6e, 0x29, 0x70, - 0x86, 0xad, 0x02, 0x33, 0x3b, 0xfb, 0x87, 0xfd, 0x4e, 0x02, 0x9e, 0x65, 0x4d, 0xa8, 0x6e, 0x9a, - 0x9d, 0xf6, 0xd6, 0xae, 0x84, 0xe4, 0xd8, 0x32, 0x34, 0x77, 0x8e, 0x0f, 0xb6, 0xbb, 0x07, 0x4f, - 0xad, 0xad, 0xf6, 0xc1, 0x56, 0x67, 0xaf, 0xb3, 0xdd, 0xcc, 0xb3, 0x1a, 0x94, 0xdb, 0x9b, 0xed, - 0x83, 0xed, 0xc3, 0x83, 0xce, 0x76, 0xb3, 0x60, 0xfc, 0x0a, 0x94, 0xe3, 0x89, 0x56, 0xa0, 0x78, - 0x7c, 0xf0, 0xec, 0xe0, 0xf0, 0xd3, 0x83, 0xe6, 0x2d, 0x56, 0x86, 0x02, 0xf6, 0xdf, 0xcc, 0x30, - 0x80, 0x05, 0xea, 0xb3, 0x99, 0x65, 0x25, 0xc8, 0x6f, 0x1e, 0xf6, 0x77, 0x9b, 0x39, 0xe3, 0x2f, - 0x32, 0xb0, 0x82, 0x53, 0x1e, 0xce, 0x32, 0x81, 0xfb, 0x50, 0x19, 0x78, 0xde, 0x44, 0x68, 0x5a, - 0xb1, 0x44, 0xa1, 0x83, 0xc4, 0x06, 0x27, 0xe6, 0x7d, 0xea, 0xf9, 0x03, 0x2e, 0x79, 0x00, 0x20, - 0x68, 0x47, 0x40, 0x04, 0x0d, 0x4a, 0x22, 0x26, 0x0c, 0x62, 0x01, 0x15, 0x82, 0x11, 0xca, 0x2a, - 0x2c, 0x9c, 0xf8, 0xdc, 0x1e, 0x9c, 0xcb, 0xdd, 0x2f, 0x9f, 0xd8, 0xd7, 0x63, 0x1b, 0xc0, 0x40, - 0xd0, 0xd4, 0x88, 0x0f, 0x71, 0x0b, 0x94, 0xcc, 0x86, 0x84, 0x6f, 0x49, 0xb0, 0x38, 0x8d, 0xec, - 0x13, 0xdb, 0x1d, 0x7a, 0x2e, 0x1f, 0x4a, 0x55, 0x23, 0x06, 0x18, 0x47, 0xb0, 0x3a, 0x3b, 0x3f, - 0xc9, 0x2f, 0x3e, 0xd0, 0xf8, 0x05, 0x49, 0xfe, 0xeb, 0x37, 0x93, 0x82, 0xc6, 0x3b, 0xfe, 0x7e, - 0x1e, 0xf2, 0x42, 0x12, 0xbc, 0x51, 0x68, 0xd4, 0x45, 0xfb, 0xdc, 0x9c, 0xfb, 0x07, 0x4d, 0x0d, - 0x24, 0x22, 0x90, 0x3d, 0xab, 0x8c, 0x10, 0x14, 0x0d, 0xa2, 0x62, 0x9f, 0x0f, 0x2e, 0xa4, 0x41, - 0x8b, 0x8a, 0x4d, 0x3e, 0xb8, 0x40, 0x9d, 0xca, 0x0e, 0xa9, 0x2e, 0xed, 0xf7, 0x62, 0x60, 0x87, - 0x58, 0x53, 0x16, 0x61, 0xbd, 0x62, 0x54, 0x84, 0xb5, 0x5a, 0x50, 0x74, 0xdc, 0x13, 0x6f, 0xea, - 0x0e, 0x71, 0x7b, 0x97, 0x4c, 0xf5, 0x88, 0xde, 0x26, 0xe4, 0x44, 0xe2, 0x20, 0xa2, 0xdd, 0x5c, - 0x12, 0x80, 0xbe, 0x38, 0x8a, 0xde, 0x83, 0x72, 0x70, 0xed, 0x0e, 0xf4, 0x3d, 0xbc, 0x2c, 0xd7, - 0x47, 0xcc, 0x7e, 0xa3, 0x77, 0xed, 0x0e, 0x70, 0xc7, 0x96, 0x02, 0xf9, 0x8b, 0xbd, 0x0f, 0xa5, - 0xc8, 0xee, 0x4b, 0x1c, 0xf8, 0xb6, 0x5e, 0x43, 0x19, 0x7b, 0x49, 0xbd, 0x8e, 0x50, 0xd9, 0x23, - 0x58, 0x40, 0xe3, 0x6c, 0xd0, 0xaa, 0x62, 0x25, 0x25, 0xef, 0x8b, 0x61, 0xa0, 0xa3, 0x87, 0x0f, - 0xd1, 0x50, 0x6b, 0x4a, 0xb4, 0xf5, 0x67, 0x50, 0x4b, 0xb4, 0xa5, 0x2b, 0xd1, 0x35, 0x52, 0xa2, - 0xdf, 0xd2, 0x95, 0xe8, 0xf8, 0x24, 0x90, 0xd5, 0x74, 0xa5, 0xfa, 0xd7, 0xa0, 0xa4, 0xa6, 0x22, - 0xf6, 0x9f, 0xdc, 0x3b, 0x56, 0xef, 0xb3, 0x83, 0xad, 0xe6, 0x2d, 0xd6, 0x80, 0x4a, 0x7b, 0x0b, - 0xb7, 0x34, 0x02, 0x32, 0x02, 0xe5, 0xa8, 0xdd, 0xeb, 0x45, 0x90, 0xac, 0xb1, 0x03, 0xcd, 0xd9, - 0x91, 0x0a, 0x9a, 0x0c, 0x15, 0x4c, 0x9a, 0xae, 0x63, 0x80, 0x50, 0x91, 0xc8, 0x1a, 0x4d, 0x72, - 0x38, 0x3d, 0x18, 0xef, 0x43, 0x53, 0x9c, 0x6b, 0x62, 0xa9, 0x02, 0xcd, 0x04, 0x3c, 0x12, 0xb2, - 0x9d, 0x6e, 0xbe, 0x2e, 0x99, 0x15, 0x82, 0x61, 0x57, 0xc6, 0x07, 0xb0, 0xa8, 0x55, 0x8b, 0x55, - 0x5a, 0x71, 0x56, 0xce, 0xaa, 0xb4, 0xa8, 0xc0, 0x50, 0x89, 0xb1, 0x06, 0x2b, 0xe2, 0xb1, 0x73, - 0xc1, 0xdd, 0xb0, 0x37, 0x3d, 0x21, 0x9f, 0xa3, 0xe3, 0xb9, 0x42, 0xb1, 0x29, 0x47, 0x25, 0x37, - 0x13, 0xf9, 0x86, 0xd4, 0x7e, 0xb3, 0x48, 0x1a, 0xeb, 0x5a, 0x0f, 0x58, 0x71, 0x03, 0xff, 0x26, - 0xb4, 0xe0, 0x72, 0x04, 0x12, 0xcb, 0x7a, 0xd4, 0xe9, 0x98, 0xd6, 0xe1, 0xc1, 0x5e, 0xf7, 0x40, - 0x30, 0x4a, 0xb1, 0xac, 0x08, 0xd8, 0xd9, 0x41, 0x48, 0xc6, 0x68, 0x42, 0xfd, 0x29, 0x0f, 0xbb, - 0xee, 0xa9, 0xa7, 0xfc, 0x6b, 0x3f, 0x2b, 0x40, 0x23, 0x02, 0xc5, 0x5a, 0xf4, 0x05, 0xf7, 0x03, - 0xc7, 0x73, 0x51, 0x20, 0x2e, 0x9b, 0xea, 0x51, 0x9c, 0x6e, 0xce, 0x90, 0xbb, 0xa1, 0x13, 0x5e, - 0x5b, 0x09, 0x93, 0x5b, 0x5d, 0x81, 0xe5, 0x29, 0xba, 0x0c, 0x05, 0x7b, 0xe4, 0xd8, 0xca, 0x55, - 0x4b, 0x0f, 0x02, 0x3a, 0xf0, 0x46, 0x9e, 0x8f, 0xb2, 0x6f, 0xd9, 0xa4, 0x07, 0xf6, 0x18, 0x96, - 0x85, 0x0c, 0xae, 0xdb, 0x41, 0x91, 0x7f, 0x90, 0xf5, 0x8f, 0xb9, 0xd3, 0xf1, 0x51, 0x6c, 0x0b, - 0x15, 0x25, 0xe2, 0xec, 0x14, 0x35, 0xa4, 0xb0, 0x14, 0x55, 0x20, 0x75, 0x6e, 0xd1, 0x9d, 0x8e, - 0xdb, 0x58, 0x12, 0xe1, 0x3f, 0x81, 0x15, 0x81, 0x1f, 0x89, 0x57, 0x51, 0x8d, 0x06, 0xd6, 0x10, - 0x8d, 0x75, 0x65, 0x59, 0x54, 0xe7, 0x0e, 0x94, 0x69, 0x54, 0xe2, 0x8d, 0x17, 0x48, 0x8c, 0xc7, - 0xa1, 0x70, 0x3f, 0x98, 0xf3, 0xaa, 0x2e, 0x90, 0x20, 0x30, 0xe3, 0x55, 0xd5, 0xfc, 0xb2, 0xa5, - 0x59, 0xbf, 0xec, 0x13, 0x58, 0x39, 0x11, 0x24, 0x78, 0xce, 0xed, 0x21, 0xf7, 0xad, 0x98, 0xb0, - 0x49, 0x5d, 0x59, 0x12, 0x85, 0xbb, 0x58, 0x16, 0xed, 0x03, 0x21, 0xe7, 0x08, 0xb6, 0xc0, 0x87, - 0x56, 0xe8, 0x59, 0x28, 0xfe, 0x20, 0x83, 0x29, 0x99, 0x35, 0x02, 0xf7, 0xbd, 0x2d, 0x01, 0x4c, - 0xe2, 0x9d, 0xf9, 0xf6, 0xe4, 0x5c, 0x2a, 0x14, 0x11, 0xde, 0x53, 0x01, 0x64, 0xaf, 0x41, 0x51, - 0x90, 0xbc, 0xcb, 0xc9, 0xf9, 0x45, 0x22, 0xbb, 0x02, 0xb1, 0xb7, 0x60, 0x01, 0xfb, 0x08, 0x5a, - 0x4d, 0xa4, 0xf7, 0x6a, 0xcc, 0xc8, 0x1d, 0xd7, 0x94, 0x65, 0x42, 0x98, 0x9c, 0xfa, 0x0e, 0x71, - 0x99, 0xb2, 0x89, 0xbf, 0xd9, 0xf7, 0x35, 0x96, 0xb5, 0x84, 0x75, 0x95, 0x3c, 0x30, 0x43, 0x69, - 0x37, 0x71, 0xaf, 0xaf, 0x94, 0x19, 0xfd, 0x20, 0x5f, 0xaa, 0x34, 0xab, 0xc6, 0x77, 0xa0, 0x40, - 0xab, 0x23, 0x88, 0x10, 0xd7, 0x2e, 0x23, 0x89, 0x10, 0xa1, 0x2d, 0x28, 0xba, 0x3c, 0xbc, 0xf4, - 0xfc, 0xe7, 0xca, 0x28, 0x2d, 0x1f, 0x8d, 0x1f, 0xa3, 0x35, 0x25, 0xf2, 0xb8, 0x93, 0x62, 0x28, - 0xc8, 0x83, 0x5e, 0x6f, 0x70, 0x6e, 0x4b, 0x03, 0x4f, 0x09, 0x01, 0xbd, 0x73, 0x7b, 0x8e, 0x3c, - 0xb2, 0xf3, 0x4e, 0xf7, 0xb7, 0xa0, 0xae, 0x7c, 0xfc, 0x81, 0x35, 0xe2, 0xa7, 0xa1, 0x24, 0xf7, - 0xaa, 0x74, 0xf0, 0x07, 0x7b, 0xfc, 0x34, 0x34, 0xf6, 0x61, 0x51, 0x12, 0xe4, 0xe1, 0x84, 0xab, - 0xae, 0xbf, 0x9b, 0x26, 0x4f, 0x57, 0x9e, 0x2c, 0x25, 0x0f, 0x5a, 0x8a, 0x5d, 0x48, 0x08, 0xd9, - 0xc6, 0xc7, 0xc0, 0xf4, 0x63, 0x58, 0xb6, 0x27, 0xa5, 0x5a, 0x65, 0xcb, 0x57, 0x2e, 0xb1, 0x48, - 0x76, 0x76, 0x86, 0x62, 0x75, 0x82, 0xe9, 0x60, 0xa0, 0x62, 0x2f, 0x4a, 0xa6, 0x7a, 0x34, 0xfe, - 0x34, 0x03, 0x4b, 0xd8, 0x98, 0xd2, 0x07, 0x24, 0x93, 0xfd, 0xb9, 0x07, 0x29, 0xde, 0x8f, 0x2e, - 0xfb, 0xd0, 0xc3, 0x97, 0xb7, 0x9e, 0xe6, 0xe7, 0xac, 0xa7, 0x5f, 0x87, 0xe6, 0x90, 0x8f, 0x1c, - 0x0c, 0xc3, 0x51, 0xa2, 0x04, 0x69, 0x00, 0x0d, 0x05, 0x97, 0xda, 0xa0, 0xf1, 0x8f, 0x33, 0xb0, - 0x48, 0x92, 0x0a, 0xea, 0xd5, 0x72, 0xa1, 0x3e, 0x52, 0x8a, 0xa4, 0x64, 0x55, 0x72, 0x4e, 0xf1, - 0x09, 0x8e, 0x50, 0x42, 0xde, 0xbd, 0x25, 0x15, 0x4c, 0x09, 0x65, 0x1f, 0xa2, 0x0e, 0xe3, 0x5a, - 0x08, 0x4c, 0x09, 0xeb, 0x49, 0xbe, 0x94, 0xdd, 0x5b, 0xa8, 0xe0, 0xb8, 0x08, 0xda, 0x2c, 0x09, - 0xcd, 0x56, 0x80, 0x8d, 0x1d, 0xa8, 0x25, 0xba, 0x49, 0x98, 0x78, 0xab, 0x64, 0xe2, 0x9d, 0x73, - 0xa3, 0x64, 0xe7, 0xdd, 0x28, 0x7f, 0x3b, 0x0f, 0x4c, 0x90, 0xd4, 0xcc, 0x5b, 0x9b, 0xf1, 0x41, - 0x66, 0xe7, 0x7c, 0x90, 0x8f, 0x81, 0x69, 0x08, 0xca, 0x35, 0x9a, 0x8b, 0x5c, 0xa3, 0xcd, 0x18, - 0x57, 0x7a, 0x46, 0x1f, 0xc3, 0xb2, 0x14, 0x68, 0x23, 0xa7, 0x23, 0xda, 0xee, 0xe8, 0xfd, 0x30, - 0x92, 0x6c, 0x95, 0xf3, 0x11, 0xed, 0x78, 0xca, 0xff, 0x28, 0x74, 0x70, 0x32, 0x79, 0xa1, 0xff, - 0x51, 0x69, 0xdf, 0x1a, 0x15, 0x2c, 0xbc, 0x94, 0x0a, 0x8a, 0x73, 0x54, 0xa0, 0x59, 0x60, 0x4a, - 0x49, 0x0b, 0x8c, 0x01, 0x35, 0xe5, 0x65, 0xa4, 0xe0, 0x0a, 0x92, 0xde, 0x2a, 0xd2, 0xd5, 0x88, - 0x01, 0x16, 0x0f, 0xa0, 0xa9, 0xcc, 0x24, 0x91, 0x8d, 0x87, 0x02, 0x07, 0xa4, 0x95, 0x6d, 0x4b, - 0x59, 0x7a, 0x12, 0x16, 0xf5, 0xca, 0x8c, 0x45, 0xfd, 0x5d, 0x58, 0x0c, 0x04, 0x11, 0x59, 0x53, - 0x57, 0x46, 0xf9, 0xf0, 0x21, 0xaa, 0x4e, 0x25, 0xb3, 0x89, 0x05, 0xc7, 0x31, 0x7c, 0xde, 0x7e, - 0x51, 0x4b, 0xb1, 0x5f, 0xbc, 0x1f, 0x3b, 0xe4, 0x82, 0x73, 0x67, 0x8c, 0x07, 0x77, 0x1c, 0x11, - 0x23, 0x17, 0xb8, 0x77, 0xee, 0x8c, 0x4d, 0xe5, 0xfd, 0x15, 0x0f, 0xc6, 0x7f, 0xc8, 0x40, 0x53, - 0xd0, 0x41, 0x82, 0xce, 0x7f, 0x05, 0x70, 0x47, 0xbe, 0x22, 0x99, 0x57, 0x04, 0xae, 0xa2, 0xf2, - 0xef, 0x00, 0x92, 0xad, 0x25, 0xf4, 0x44, 0x49, 0xe4, 0xad, 0x24, 0x91, 0xc7, 0x8c, 0x6c, 0xf7, - 0x16, 0x29, 0x00, 0x02, 0x92, 0xe6, 0x08, 0xcd, 0xa7, 0x38, 0x42, 0xb5, 0xad, 0xb0, 0x0b, 0xf0, - 0x8c, 0x5f, 0xef, 0x79, 0x03, 0xd4, 0xd0, 0xee, 0x02, 0x08, 0x82, 0x3c, 0xb5, 0xc7, 0x8e, 0xb4, - 0xae, 0x14, 0xcc, 0xf2, 0x73, 0x7e, 0xbd, 0x83, 0x00, 0xf1, 0x36, 0x44, 0x71, 0xbc, 0x1f, 0x0a, - 0x66, 0xe9, 0x39, 0xbf, 0xa6, 0xcd, 0x60, 0x41, 0xed, 0x19, 0xbf, 0xde, 0xe6, 0x24, 0xae, 0x79, - 0xbe, 0xa0, 0x04, 0xdf, 0xbe, 0x14, 0xf2, 0x59, 0xc2, 0x89, 0x59, 0xf1, 0xed, 0xcb, 0x67, 0xfc, - 0x5a, 0x39, 0x54, 0x8b, 0xa2, 0x7c, 0xe4, 0x0d, 0xe4, 0x09, 0xa4, 0xc2, 0x31, 0xe2, 0x41, 0x99, - 0x0b, 0xcf, 0xf1, 0xb7, 0xf1, 0x57, 0x19, 0xa8, 0x89, 0xf1, 0x23, 0x83, 0x13, 0xeb, 0xae, 0xa2, - 0x7a, 0x32, 0x71, 0x54, 0xcf, 0x13, 0xc9, 0x1f, 0x88, 0x5b, 0x66, 0x6f, 0xe6, 0x96, 0xb8, 0xc0, - 0xc4, 0x2a, 0xdf, 0x83, 0x32, 0xed, 0x2d, 0xb1, 0x59, 0x73, 0x89, 0xb7, 0x94, 0x98, 0x90, 0x59, - 0x42, 0xb4, 0x67, 0x14, 0x44, 0xa0, 0x59, 0xea, 0x68, 0x89, 0xcb, 0x7e, 0x64, 0x9f, 0x4b, 0x79, - 0x0d, 0x85, 0x1b, 0x82, 0x08, 0x74, 0x33, 0xd8, 0xc2, 0x9c, 0x19, 0xec, 0x18, 0x2a, 0x1a, 0xd1, - 0xa1, 0xdd, 0x2f, 0x9a, 0x1d, 0x51, 0x68, 0x92, 0xaa, 0x12, 0xcb, 0xb3, 0x7b, 0xcb, 0xac, 0x0d, - 0x74, 0xc0, 0xe6, 0x02, 0xe4, 0x45, 0x25, 0xe3, 0x23, 0x58, 0xd4, 0x9a, 0x25, 0x75, 0x35, 0x6d, - 0xd0, 0x99, 0x34, 0x27, 0xfa, 0x3f, 0xc9, 0xc0, 0xb2, 0xac, 0x8d, 0x21, 0x62, 0x8e, 0x38, 0xcf, - 0xf7, 0x83, 0x33, 0xf6, 0x2b, 0x50, 0x13, 0xad, 0x5b, 0x3e, 0x3f, 0x73, 0x82, 0x90, 0x2b, 0x1f, - 0x49, 0xca, 0xee, 0x11, 0x6c, 0x5d, 0xa0, 0x9a, 0x12, 0x93, 0x7d, 0x04, 0x15, 0xac, 0x4a, 0x0a, - 0xb5, 0x7c, 0x6f, 0xad, 0xf9, 0x8a, 0x34, 0xd4, 0xdd, 0x5b, 0x26, 0x04, 0xd1, 0xd3, 0x66, 0x19, - 0x8a, 0xa1, 0xef, 0x9c, 0x9d, 0x71, 0xdf, 0x58, 0x8d, 0x86, 0x26, 0xb6, 0x22, 0xef, 0x85, 0x7c, - 0x22, 0xa4, 0x24, 0xe3, 0x3f, 0x67, 0xa0, 0x22, 0x37, 0xd7, 0xcf, 0xed, 0x18, 0x59, 0xd7, 0x62, - 0x1c, 0x49, 0x77, 0x8e, 0x43, 0x1a, 0xdf, 0x81, 0xc6, 0x58, 0x48, 0x4c, 0x42, 0xa2, 0x4f, 0x78, - 0x45, 0xea, 0x0a, 0x2c, 0x05, 0x96, 0x0d, 0x58, 0x42, 0xf9, 0x25, 0xb0, 0x42, 0x67, 0x64, 0xa9, - 0x42, 0x19, 0x4f, 0xb8, 0x48, 0x45, 0x7d, 0x67, 0xb4, 0x2f, 0x0b, 0xc4, 0x31, 0x1e, 0x84, 0xf6, - 0x19, 0x97, 0xb4, 0x41, 0x0f, 0x46, 0x0b, 0x56, 0x67, 0x84, 0x79, 0xa5, 0x88, 0xfc, 0x8d, 0x26, - 0xac, 0xcd, 0x15, 0x49, 0x85, 0x24, 0xf2, 0x06, 0x8c, 0x9c, 0xf1, 0x89, 0x17, 0xd9, 0xca, 0x32, - 0x9a, 0x37, 0x60, 0x4f, 0x94, 0x28, 0x5b, 0x19, 0x87, 0x15, 0x45, 0x10, 0x68, 0xec, 0x8a, 0xe4, - 0xfd, 0x2c, 0x4a, 0xa3, 0xef, 0x25, 0x39, 0xd9, 0x6c, 0x77, 0x0a, 0xae, 0x9f, 0x8f, 0x4b, 0x93, - 0x39, 0x58, 0xc0, 0x4e, 0xa1, 0x15, 0xd1, 0x9d, 0x14, 0xa0, 0x34, 0xe5, 0x45, 0xf4, 0xf4, 0x8d, - 0x97, 0xf4, 0x94, 0xb0, 0xa2, 0x98, 0xab, 0x8a, 0x5c, 0xa9, 0xb1, 0xa8, 0x9f, 0x0b, 0x78, 0x5d, - 0xf5, 0x83, 0xc2, 0xd0, 0x7c, 0x6f, 0xf9, 0x57, 0x9a, 0x17, 0x5a, 0x87, 0x92, 0x5d, 0xde, 0x91, - 0x0d, 0x47, 0x45, 0x7a, 0xbf, 0xe7, 0xb0, 0x7a, 0x69, 0x3b, 0xa1, 0x9a, 0x9f, 0xa6, 0x37, 0x15, - 0xb0, 0xbf, 0x27, 0x2f, 0xe9, 0xef, 0x53, 0xaa, 0x9c, 0x10, 0x0f, 0x97, 0x2f, 0xe7, 0x81, 0xc1, - 0xfa, 0x9f, 0x64, 0xa1, 0x9e, 0x6c, 0x45, 0x6c, 0x6a, 0xc9, 0xa8, 0x94, 0xc0, 0x21, 0x05, 0x76, - 0x69, 0xc3, 0x3d, 0x20, 0x41, 0x63, 0xde, 0xba, 0x9c, 0x4d, 0xb1, 0x2e, 0xeb, 0x46, 0xdd, 0xdc, - 0xcb, 0xbc, 0x68, 0xf9, 0x57, 0xf2, 0xa2, 0x15, 0xd2, 0xbc, 0x68, 0x37, 0xbb, 0x5e, 0x16, 0x7e, - 0x2e, 0xd7, 0x4b, 0xf1, 0x05, 0xae, 0x97, 0x84, 0xc3, 0xa8, 0x34, 0xe3, 0x30, 0x5a, 0xff, 0xab, - 0x0c, 0xb0, 0x79, 0x3a, 0x66, 0x4f, 0xc9, 0xcc, 0xee, 0xf2, 0x91, 0xe4, 0x71, 0xdf, 0x7c, 0xb5, - 0xbd, 0xa0, 0x5e, 0x9f, 0xaa, 0xcd, 0x1e, 0xc1, 0x92, 0x1e, 0x9f, 0xac, 0x6b, 0x3a, 0x35, 0x93, - 0xe9, 0x45, 0xb1, 0x3e, 0xac, 0x39, 0x18, 0xf3, 0x2f, 0x75, 0x30, 0x16, 0x5e, 0xea, 0x60, 0x5c, - 0x48, 0x3a, 0x18, 0xd7, 0xff, 0x6b, 0x06, 0x96, 0x52, 0x48, 0xee, 0xab, 0x9b, 0xb3, 0xa0, 0x94, - 0x04, 0x03, 0xca, 0x4a, 0x4a, 0xd1, 0x79, 0xcf, 0x1e, 0x54, 0x62, 0x9f, 0x95, 0x8a, 0xdf, 0x7f, - 0xf8, 0x32, 0x3e, 0x10, 0xd7, 0x30, 0xf5, 0xea, 0xeb, 0x5f, 0x40, 0x45, 0x2b, 0x13, 0x8b, 0x48, - 0xf4, 0xa5, 0x85, 0x75, 0x90, 0x08, 0x80, 0x6a, 0xda, 0x3d, 0x90, 0x76, 0x60, 0x2a, 0xa7, 0x9d, - 0x20, 0xcf, 0x7b, 0x44, 0xd8, 0x80, 0x25, 0xe5, 0x01, 0xe1, 0x71, 0xf4, 0x96, 0x3c, 0x14, 0x16, - 0xa5, 0x1f, 0x84, 0x47, 0xc1, 0x60, 0xeb, 0x3f, 0x81, 0x5a, 0x82, 0x5f, 0x7c, 0x75, 0x6b, 0x39, - 0xab, 0x74, 0xd2, 0x58, 0x75, 0xa5, 0x73, 0xfd, 0xff, 0xe4, 0x80, 0xcd, 0xb3, 0xac, 0x5f, 0xe6, - 0x10, 0xe6, 0xdf, 0x78, 0x2e, 0xe5, 0x8d, 0xff, 0x3f, 0x3b, 0x42, 0xdf, 0x85, 0x45, 0x99, 0x20, - 0xa2, 0x39, 0x88, 0x88, 0xea, 0x9b, 0x51, 0x81, 0x1a, 0xc5, 0x77, 0x66, 0x1d, 0xd5, 0xa5, 0x44, - 0x4c, 0xbc, 0x26, 0x43, 0xcc, 0xf8, 0xab, 0x8f, 0x61, 0xc1, 0x76, 0x07, 0xe7, 0x9e, 0x8f, 0xfa, - 0x4e, 0xfd, 0xc9, 0xaf, 0x7e, 0xe9, 0x53, 0x64, 0xa3, 0x8d, 0xf5, 0x51, 0x70, 0x31, 0x65, 0x63, - 0xc6, 0x7b, 0x50, 0xd1, 0xc0, 0xe8, 0x34, 0xe9, 0xee, 0x6f, 0x1e, 0x36, 0x6f, 0xb1, 0x1a, 0x94, - 0xcd, 0xce, 0xd6, 0xe1, 0x27, 0x1d, 0xb3, 0xb3, 0xdd, 0xcc, 0xb0, 0x12, 0xe4, 0xf7, 0x0e, 0x7b, - 0xfd, 0x66, 0xd6, 0x58, 0x87, 0x96, 0x6c, 0x71, 0xde, 0x80, 0xfa, 0xbb, 0xf9, 0xc8, 0x76, 0x81, - 0x85, 0x52, 0x55, 0xf9, 0x16, 0x54, 0xf5, 0x13, 0x5e, 0x52, 0xc4, 0x8c, 0x8f, 0x52, 0x28, 0x29, - 0x9e, 0xc6, 0x04, 0xb7, 0x80, 0x3c, 0x4f, 0xc3, 0xa8, 0x1a, 0x89, 0x6d, 0x2f, 0x70, 0x55, 0xa0, - 0x44, 0x9a, 0x20, 0xc3, 0xff, 0x0f, 0xea, 0x49, 0x6b, 0xa2, 0xdc, 0xea, 0x69, 0x32, 0xbb, 0xa8, - 0x9d, 0x30, 0x2f, 0xb2, 0xef, 0x43, 0x73, 0xd6, 0x1a, 0x29, 0x43, 0x87, 0x6f, 0xa8, 0xdf, 0x70, - 0x92, 0x06, 0x4a, 0xb6, 0x0b, 0xcb, 0x69, 0x32, 0x0e, 0xd2, 0xc7, 0xcd, 0xca, 0x1a, 0x9b, 0x97, - 0x63, 0xd8, 0x77, 0xa5, 0xd1, 0xb9, 0x90, 0xe6, 0xba, 0xd3, 0x16, 0x7b, 0x83, 0xfe, 0x69, 0xe6, - 0xe7, 0x0b, 0x80, 0x18, 0xc6, 0x9a, 0x50, 0x3d, 0x3c, 0xea, 0x1c, 0x58, 0x5b, 0xbb, 0xed, 0x83, - 0x83, 0xce, 0x5e, 0xf3, 0x16, 0x63, 0x50, 0x47, 0x9f, 0xdb, 0x76, 0x04, 0xcb, 0x08, 0x98, 0x34, - 0xfe, 0x2b, 0x58, 0x96, 0x2d, 0x43, 0xb3, 0x7b, 0x30, 0x03, 0xcd, 0xb1, 0x16, 0x2c, 0x1f, 0x75, - 0xc8, 0x4d, 0x97, 0x68, 0x37, 0x2f, 0xe4, 0x66, 0x39, 0x5d, 0x21, 0x37, 0x53, 0xa2, 0x93, 0xdc, - 0x07, 0x4a, 0x9c, 0xfc, 0xbd, 0x0c, 0xac, 0xcc, 0x14, 0xc4, 0xe1, 0xeb, 0x24, 0x4c, 0x26, 0xc5, - 0xc8, 0x2a, 0x02, 0xd5, 0x6e, 0x7a, 0x17, 0x16, 0x23, 0x05, 0x7c, 0x86, 0xdd, 0x37, 0xa3, 0x02, - 0x85, 0xfc, 0x08, 0x96, 0x34, 0x3d, 0x7e, 0x86, 0x57, 0x30, 0xad, 0x48, 0x56, 0x30, 0xd6, 0xa2, - 0x30, 0xe1, 0x99, 0x51, 0x0f, 0x29, 0x7b, 0x4a, 0x2f, 0x88, 0x6d, 0xf2, 0xc9, 0xf1, 0xaa, 0x47, - 0xf6, 0x78, 0x86, 0x10, 0x92, 0xa3, 0xd5, 0x5f, 0xb8, 0xea, 0xfe, 0x0f, 0x16, 0x80, 0x7d, 0x3c, - 0xe5, 0xfe, 0x35, 0x86, 0xa7, 0x07, 0x2f, 0x8b, 0xd7, 0x52, 0xca, 0x6a, 0xf6, 0x95, 0x52, 0x50, - 0xd2, 0x52, 0x40, 0xf2, 0x2f, 0x4f, 0x01, 0x29, 0xbc, 0x2c, 0x05, 0xe4, 0x4d, 0xa8, 0x39, 0x67, - 0xae, 0x27, 0x58, 0xa1, 0x10, 0x08, 0x83, 0xd6, 0xc2, 0xfd, 0xdc, 0x83, 0xaa, 0x59, 0x95, 0x40, - 0x21, 0x0e, 0x06, 0xec, 0xa3, 0x18, 0x89, 0x0f, 0xcf, 0x30, 0x5d, 0x49, 0x67, 0x82, 0x9d, 0xe1, - 0x19, 0x97, 0xba, 0x39, 0x5a, 0xab, 0x54, 0x65, 0x01, 0x0f, 0xd8, 0x5b, 0x50, 0x0f, 0xbc, 0xa9, - 0x90, 0xaf, 0xd5, 0x32, 0x90, 0xd5, 0xbe, 0x4a, 0xd0, 0x23, 0xe5, 0xa2, 0x59, 0x9a, 0x06, 0xdc, - 0x1a, 0x3b, 0x41, 0x20, 0xe4, 0x9e, 0x81, 0xe7, 0x86, 0xbe, 0x37, 0x92, 0x86, 0xf8, 0xc5, 0x69, - 0xc0, 0xf7, 0xa9, 0x64, 0x8b, 0x0a, 0xd8, 0xb7, 0xe3, 0x21, 0x4d, 0x6c, 0xc7, 0x0f, 0x5a, 0x80, - 0x43, 0x52, 0x33, 0x45, 0x31, 0xd6, 0x76, 0xfc, 0x68, 0x2c, 0xe2, 0x21, 0x98, 0x49, 0x4d, 0xa9, - 0xcc, 0xa6, 0xa6, 0xfc, 0x28, 0x3d, 0x35, 0xa5, 0x86, 0x4d, 0x3f, 0x96, 0x4d, 0xcf, 0xbf, 0xe2, - 0x2f, 0x95, 0xa1, 0x32, 0x9f, 0x71, 0x53, 0xff, 0x32, 0x19, 0x37, 0x8d, 0xb4, 0x8c, 0x9b, 0xf7, - 0xa0, 0x82, 0xb9, 0x10, 0xd6, 0xb9, 0x23, 0x84, 0x23, 0x72, 0x2c, 0x34, 0xf5, 0x64, 0x89, 0x5d, - 0xc7, 0x0d, 0x4d, 0xf0, 0xd5, 0xcf, 0x60, 0x3e, 0xf9, 0x65, 0xf1, 0x97, 0x98, 0xfc, 0x22, 0x73, - 0x36, 0x36, 0xa0, 0xa4, 0xde, 0x13, 0x63, 0x90, 0x3f, 0xf5, 0xbd, 0xb1, 0x32, 0xb8, 0x8a, 0xdf, - 0xac, 0x0e, 0xd9, 0xd0, 0x93, 0x95, 0xb3, 0xa1, 0x67, 0xfc, 0x26, 0x54, 0x34, 0x52, 0x63, 0x6f, - 0x90, 0x69, 0x47, 0xa8, 0x28, 0x52, 0x6a, 0xa3, 0x55, 0x2c, 0x4b, 0x68, 0x77, 0x28, 0xf8, 0xcd, - 0xd0, 0xf1, 0x39, 0xa6, 0xa9, 0x59, 0x3e, 0xbf, 0xe0, 0x7e, 0xa0, 0x0c, 0xe0, 0xcd, 0xa8, 0xc0, - 0x24, 0xb8, 0xf1, 0xd7, 0x60, 0x29, 0xf1, 0x6e, 0x25, 0x8b, 0x78, 0x0b, 0x16, 0x70, 0xdd, 0x94, - 0x83, 0x32, 0x99, 0x84, 0x22, 0xcb, 0x30, 0xff, 0x98, 0x6c, 0xf7, 0xd6, 0xc4, 0xf7, 0x4e, 0xb0, - 0x93, 0x8c, 0x59, 0x91, 0xb0, 0x23, 0xdf, 0x3b, 0x31, 0xfe, 0x3c, 0x07, 0xb9, 0x5d, 0x6f, 0xa2, - 0xc7, 0xe4, 0x64, 0xe6, 0x62, 0x72, 0xa4, 0xde, 0x65, 0x45, 0x7a, 0x95, 0x14, 0x86, 0xd1, 0x6a, - 0xad, 0x74, 0xab, 0x07, 0x50, 0x17, 0x7c, 0x22, 0xf4, 0x84, 0xe2, 0x7a, 0x69, 0xfb, 0x24, 0x6a, - 0xe6, 0x68, 0xf3, 0xd9, 0xe3, 0xb0, 0xef, 0xed, 0x10, 0x9c, 0x2d, 0x43, 0x2e, 0xd2, 0x0b, 0xb0, - 0x58, 0x3c, 0xb2, 0x55, 0x58, 0xc0, 0xe0, 0xcc, 0x6b, 0xe9, 0x81, 0x93, 0x4f, 0xec, 0x9b, 0xb0, - 0x94, 0x6c, 0x97, 0x58, 0x91, 0x94, 0x8d, 0xf4, 0x86, 0x91, 0x27, 0xdd, 0x06, 0xc1, 0x47, 0x08, - 0x47, 0x3a, 0xf2, 0x4f, 0x39, 0xc7, 0x22, 0x8d, 0xe9, 0x95, 0x12, 0x4c, 0xef, 0x1e, 0x54, 0xc2, - 0xd1, 0x85, 0x35, 0xb1, 0xaf, 0x47, 0x9e, 0x3d, 0x94, 0xfb, 0x1b, 0xc2, 0xd1, 0xc5, 0x11, 0x41, - 0xd8, 0x23, 0x80, 0xf1, 0x64, 0x22, 0xf7, 0x1e, 0x1a, 0x81, 0x63, 0x52, 0xde, 0x3f, 0x3a, 0x22, - 0x92, 0x33, 0xcb, 0xe3, 0xc9, 0x84, 0x7e, 0xb2, 0x6d, 0xa8, 0xa7, 0xa6, 0x92, 0xdd, 0x55, 0xb1, - 0x84, 0xde, 0x64, 0x23, 0x65, 0x73, 0xd6, 0x06, 0x3a, 0x6c, 0xfd, 0xfb, 0xc0, 0x7e, 0xc1, 0x84, - 0xae, 0x3e, 0x94, 0xa3, 0xf1, 0xe9, 0xf9, 0x50, 0x18, 0x1d, 0x5c, 0x49, 0xe4, 0x43, 0xb5, 0x87, - 0x43, 0x5f, 0xf0, 0x45, 0x3a, 0x30, 0x23, 0x96, 0x0f, 0xda, 0x89, 0xd9, 0x26, 0xbe, 0x6f, 0xfc, - 0x65, 0x06, 0x0a, 0x94, 0x9c, 0xf5, 0x36, 0x34, 0x08, 0x3f, 0x8a, 0x6f, 0x92, 0x7e, 0x3b, 0x3a, - 0x77, 0xfb, 0x32, 0xb4, 0x49, 0x6c, 0x0b, 0x2d, 0xb1, 0x34, 0x1b, 0xbd, 0x79, 0x2d, 0xb9, 0xf4, - 0x1e, 0x94, 0xa3, 0xae, 0x35, 0xd2, 0x29, 0xa9, 0x9e, 0xd9, 0xeb, 0x90, 0x3f, 0xf7, 0x26, 0xca, - 0x00, 0x02, 0xf1, 0x4a, 0x9a, 0x08, 0x8f, 0xc7, 0x22, 0xfa, 0xa0, 0xc1, 0x4b, 0xc5, 0x3d, 0xea, - 0x04, 0xc9, 0x60, 0x7e, 0x8e, 0x0b, 0x29, 0x73, 0x3c, 0x86, 0x86, 0xe0, 0x03, 0x9a, 0xff, 0xfc, - 0xe6, 0x43, 0xf3, 0xeb, 0x42, 0xc2, 0x1b, 0x8c, 0xa6, 0x43, 0xae, 0x9b, 0x9f, 0x30, 0xd8, 0x46, + // 11444 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x23, 0x57, + 0x76, 0xd8, 0xf0, 0xd5, 0x24, 0x0f, 0x1f, 0x4d, 0xde, 0x7e, 0x71, 0x7a, 0x34, 0x9a, 0x51, 0x49, + 0x2b, 0xcd, 0x8e, 0x76, 0x7b, 0x46, 0xb3, 0x2b, 0xed, 0x5a, 0x8a, 0xd7, 0xcb, 0xee, 0x66, 0x4f, + 0x73, 0xa7, 0x5f, 0x2a, 0xb2, 0x25, 0x6b, 0x1d, 0xa7, 0xb6, 0x9a, 0xbc, 0xdd, 0x5d, 0x1e, 0xb2, + 0x8a, 0xaa, 0x2a, 0xf6, 0x63, 0x17, 0xca, 0x87, 0x20, 0x31, 0x82, 0x20, 0x09, 0x60, 0x24, 0x0e, + 0x10, 0x27, 0x46, 0x82, 0x18, 0x81, 0x11, 0x04, 0x30, 0x0c, 0xac, 0x03, 0x24, 0x40, 0xbe, 0xfb, + 0x4b, 0x02, 0x23, 0xb0, 0xf3, 0x25, 0x30, 0x0c, 0x18, 0x49, 0x9c, 0x6f, 0x81, 0x7f, 0x42, 0x70, + 0xcf, 0xb9, 0xb7, 0xea, 0x16, 0x59, 0x3d, 0x33, 0xda, 0x55, 0xf6, 0x4b, 0x37, 0xeb, 0xdc, 0x73, + 0x9f, 0x75, 0xee, 0xb9, 0xe7, 0x79, 0x0b, 0xca, 0xfe, 0x64, 0xb0, 0x31, 0xf1, 0xbd, 0xd0, 0x63, + 0x85, 0x91, 0xeb, 0x4f, 0x06, 0xeb, 0xaf, 0x9d, 0x79, 0xde, 0xd9, 0x88, 0x3f, 0xb2, 0x27, 0xce, + 0x23, 0xdb, 0x75, 0xbd, 0xd0, 0x0e, 0x1d, 0xcf, 0x0d, 0x08, 0xc9, 0xf8, 0x11, 0xd4, 0x9f, 0x72, + 0xb7, 0xc7, 0xf9, 0xd0, 0xe4, 0x9f, 0x4f, 0x79, 0x10, 0xb2, 0x77, 0xa1, 0x69, 0xf3, 0x1f, 0x73, + 0x3e, 0xb4, 0x26, 0x76, 0x10, 0x4c, 0xce, 0x7d, 0x3b, 0xe0, 0xad, 0xcc, 0xfd, 0xcc, 0x83, 0xaa, + 0xd9, 0xa0, 0x82, 0xa3, 0x08, 0xce, 0xde, 0x80, 0x6a, 0x20, 0x50, 0xb9, 0x1b, 0xfa, 0xde, 0xe4, + 0xba, 0x95, 0x45, 0xbc, 0x8a, 0x80, 0x75, 0x08, 0x64, 0x8c, 0x60, 0x31, 0xea, 0x21, 0x98, 0x78, + 0x6e, 0xc0, 0xd9, 0x63, 0x58, 0x1e, 0x38, 0x93, 0x73, 0xee, 0x5b, 0x58, 0x79, 0xec, 0xf2, 0xb1, + 0xe7, 0x3a, 0x83, 0x56, 0xe6, 0x7e, 0xee, 0x41, 0xd9, 0x64, 0x54, 0x26, 0x6a, 0xec, 0xcb, 0x12, + 0xf6, 0x0e, 0x2c, 0x72, 0x97, 0xe0, 0x7c, 0x88, 0xb5, 0x64, 0x57, 0xf5, 0x18, 0x2c, 0x2a, 0x18, + 0x7f, 0x3f, 0x0b, 0xcd, 0xae, 0xeb, 0x84, 0x9f, 0xda, 0xa3, 0x11, 0x0f, 0xd5, 0x9c, 0xde, 0x81, + 0xc5, 0x4b, 0x04, 0xe0, 0x9c, 0x2e, 0x3d, 0x7f, 0x28, 0x67, 0x54, 0x27, 0xf0, 0x91, 0x84, 0xde, + 0x38, 0xb2, 0xec, 0x8d, 0x23, 0x4b, 0x5d, 0xae, 0xdc, 0x0d, 0xcb, 0xf5, 0x0e, 0x2c, 0xfa, 0x7c, + 0xe0, 0x5d, 0x70, 0xff, 0xda, 0xba, 0x74, 0xdc, 0xa1, 0x77, 0xd9, 0xca, 0xdf, 0xcf, 0x3c, 0x28, + 0x98, 0x75, 0x05, 0xfe, 0x14, 0xa1, 0x6c, 0x13, 0x16, 0x07, 0xe7, 0xb6, 0xeb, 0xf2, 0x91, 0x75, + 0x62, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xab, 0x70, 0x3f, 0xf3, 0xa0, 0xf2, 0xe4, 0xf6, 0x06, 0xbe, + 0xd5, 0x8d, 0xad, 0x73, 0xdb, 0xdd, 0xc4, 0x92, 0x9e, 0x6b, 0x4f, 0x82, 0x73, 0x2f, 0x34, 0xeb, + 0xb2, 0x06, 0x81, 0x03, 0x63, 0x19, 0x98, 0xbe, 0x12, 0xb4, 0xf6, 0xc6, 0xbf, 0xcf, 0xc0, 0xd2, + 0xb1, 0x3b, 0xf2, 0x06, 0xcf, 0x7f, 0xc6, 0x25, 0x4a, 0x99, 0x43, 0xf6, 0x55, 0xe7, 0x90, 0xfb, + 0xb2, 0x73, 0x58, 0x85, 0xe5, 0xe4, 0x60, 0xe5, 0x2c, 0x38, 0xac, 0x88, 0xda, 0x67, 0x5c, 0x0d, + 0x4b, 0x4d, 0xe3, 0xeb, 0xd0, 0x18, 0x4c, 0x7d, 0x9f, 0xbb, 0x73, 0xf3, 0x58, 0x94, 0xf0, 0x68, + 0x22, 0x6f, 0x40, 0xd5, 0xe5, 0x97, 0x31, 0x9a, 0xa4, 0x5d, 0x97, 0x5f, 0x2a, 0x14, 0xa3, 0x05, + 0xab, 0xb3, 0xdd, 0xc8, 0x01, 0xfc, 0x55, 0x06, 0xf2, 0xc7, 0xe1, 0x95, 0xc7, 0xde, 0x87, 0xaa, + 0x3d, 0x1c, 0xfa, 0x3c, 0x08, 0xac, 0xf0, 0x7a, 0x42, 0x3b, 0xa5, 0xfe, 0x84, 0xc9, 0x29, 0xb6, + 0xa9, 0xa8, 0x7f, 0x3d, 0xe1, 0x66, 0xc5, 0x8e, 0x1f, 0x58, 0x0b, 0x8a, 0xf2, 0x11, 0xfb, 0x2d, + 0x9b, 0xea, 0x91, 0xdd, 0x05, 0xb0, 0xc7, 0xde, 0xd4, 0x0d, 0xad, 0xc0, 0x0e, 0x71, 0xc5, 0x72, + 0x66, 0x99, 0x20, 0x3d, 0x3b, 0x64, 0x77, 0xa0, 0x3c, 0x79, 0x6e, 0x05, 0x03, 0xdf, 0x99, 0x84, + 0x48, 0x3c, 0x65, 0xb3, 0x34, 0x79, 0xde, 0xc3, 0x67, 0xf6, 0x2e, 0x94, 0xbc, 0x69, 0x38, 0xf1, + 0x1c, 0x37, 0x94, 0xf4, 0xb2, 0x28, 0x07, 0x72, 0x38, 0x0d, 0x8f, 0x04, 0xd8, 0x8c, 0x10, 0xd8, + 0x5b, 0x50, 0x1b, 0x78, 0xee, 0xa9, 0xe3, 0x8f, 0x89, 0x23, 0xb4, 0x16, 0xb0, 0xaf, 0x24, 0xd0, + 0xf8, 0xc3, 0x2c, 0x54, 0xfa, 0xbe, 0xed, 0x06, 0xf6, 0x40, 0x00, 0xd8, 0x1a, 0x14, 0xc3, 0x2b, + 0xeb, 0xdc, 0x0e, 0xce, 0x71, 0xaa, 0x65, 0x73, 0x21, 0xbc, 0xda, 0xb5, 0x83, 0x73, 0xb6, 0x0a, + 0x0b, 0x34, 0x4a, 0x9c, 0x50, 0xce, 0x94, 0x4f, 0x62, 0x83, 0xb8, 0xd3, 0xb1, 0x95, 0xec, 0x2a, + 0x87, 0x14, 0xd3, 0x70, 0xa7, 0xe3, 0x2d, 0x1d, 0x2e, 0x26, 0x7f, 0x22, 0x5e, 0x37, 0x75, 0x40, + 0xd3, 0x2b, 0x23, 0x04, 0xfb, 0x78, 0x03, 0xaa, 0xb2, 0x98, 0x3b, 0x67, 0xe7, 0x34, 0xc7, 0x82, + 0x59, 0x21, 0x04, 0x04, 0x89, 0x16, 0x42, 0x67, 0xcc, 0xad, 0x20, 0xb4, 0xc7, 0x13, 0x39, 0xa5, + 0xb2, 0x80, 0xf4, 0x04, 0x00, 0x8b, 0xbd, 0xd0, 0x1e, 0x59, 0xa7, 0x9c, 0x07, 0xad, 0xa2, 0x2c, + 0x16, 0x90, 0x1d, 0xce, 0x03, 0xf6, 0x35, 0xa8, 0x0f, 0x79, 0x10, 0x5a, 0xf2, 0x65, 0xf0, 0xa0, + 0x55, 0xc2, 0x9d, 0x5f, 0x13, 0xd0, 0xb6, 0x02, 0xb2, 0xd7, 0x00, 0x7c, 0xfb, 0xd2, 0x12, 0x0b, + 0xc1, 0xaf, 0x5a, 0x65, 0x7a, 0x0b, 0xbe, 0x7d, 0xd9, 0xbf, 0xda, 0xe5, 0x57, 0x82, 0x6a, 0x9e, + 0xf2, 0x50, 0x5b, 0xb4, 0x40, 0x52, 0xa7, 0xb1, 0x07, 0x4c, 0x03, 0x6f, 0xf3, 0xd0, 0x76, 0x46, + 0x01, 0xfb, 0x00, 0xaa, 0xa1, 0x86, 0x8c, 0x6c, 0xb0, 0x12, 0x91, 0x90, 0x56, 0xc1, 0x4c, 0xe0, + 0x19, 0xe7, 0x50, 0xda, 0xe1, 0x7c, 0xcf, 0x19, 0x3b, 0x21, 0x5b, 0x85, 0xc2, 0xa9, 0x73, 0xc5, + 0x89, 0xd8, 0x73, 0xbb, 0xb7, 0x4c, 0x7a, 0x64, 0xf7, 0x00, 0xf0, 0x87, 0x35, 0x8e, 0xa8, 0x69, + 0xf7, 0x96, 0x59, 0x46, 0xd8, 0x7e, 0x60, 0x87, 0x6c, 0x1d, 0x8a, 0x13, 0xee, 0x0f, 0xb8, 0x7a, + 0x6f, 0xbb, 0xb7, 0x4c, 0x05, 0xd8, 0x2c, 0x42, 0x61, 0x24, 0x5a, 0x37, 0xfe, 0xb8, 0x00, 0x95, + 0x1e, 0x77, 0xa3, 0x5d, 0xc6, 0x20, 0x2f, 0x16, 0x44, 0xee, 0x2c, 0xfc, 0xcd, 0xde, 0x84, 0x0a, + 0x2e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x46, 0x54, 0xbd, 0x99, 0x6d, 0x65, 0x4c, 0x10, 0xe0, 0x1e, + 0x42, 0x59, 0x03, 0x72, 0xf6, 0x58, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x43, 0xc9, 0x1e, 0x87, 0x34, + 0xbc, 0x2a, 0x82, 0x8b, 0xf6, 0x38, 0xc4, 0xa1, 0xbd, 0x01, 0xd5, 0x89, 0x7d, 0x3d, 0x16, 0x7b, + 0x39, 0x22, 0x87, 0xaa, 0x59, 0x91, 0x30, 0x24, 0x88, 0x27, 0xb0, 0xa4, 0xa3, 0xa8, 0xce, 0x0b, + 0x51, 0xe7, 0x4d, 0x0d, 0x5b, 0x8e, 0xe1, 0x1d, 0x58, 0x54, 0x75, 0x7c, 0x9a, 0x0f, 0x92, 0x49, + 0xd9, 0xac, 0x4b, 0xb0, 0x9a, 0xe5, 0x03, 0x68, 0x9c, 0x3a, 0xae, 0x3d, 0xb2, 0x06, 0xa3, 0xf0, + 0xc2, 0x1a, 0xf2, 0x51, 0x68, 0x23, 0xc5, 0x14, 0xcc, 0x3a, 0xc2, 0xb7, 0x46, 0xe1, 0xc5, 0xb6, + 0x80, 0xb2, 0x6f, 0x40, 0xf9, 0x94, 0x73, 0x0b, 0x17, 0xab, 0x55, 0x4a, 0x6c, 0x3c, 0xf5, 0x86, + 0xcc, 0xd2, 0xa9, 0x7a, 0x57, 0xdf, 0x80, 0x86, 0x37, 0x0d, 0xcf, 0x3c, 0xc7, 0x3d, 0xb3, 0x04, + 0xbf, 0xb3, 0x9c, 0x21, 0xd2, 0x50, 0x7e, 0x33, 0xfb, 0x38, 0x63, 0xd6, 0x55, 0x99, 0xe0, 0x3c, + 0xdd, 0x21, 0x7b, 0x1b, 0x16, 0x47, 0x76, 0x10, 0x5a, 0xe7, 0xde, 0xc4, 0x9a, 0x4c, 0x4f, 0x9e, + 0xf3, 0xeb, 0x56, 0x0d, 0x17, 0xa2, 0x26, 0xc0, 0xbb, 0xde, 0xe4, 0x08, 0x81, 0x82, 0xb2, 0x71, + 0x9c, 0x34, 0x08, 0xb8, 0x9f, 0x79, 0x50, 0x33, 0xcb, 0x02, 0x42, 0x9d, 0x7e, 0x06, 0x4b, 0xf8, + 0x7a, 0x06, 0xd3, 0x20, 0xf4, 0xc6, 0x96, 0xe0, 0xd5, 0xfe, 0x30, 0x68, 0x55, 0x90, 0xd6, 0xbe, + 0x2e, 0x07, 0xab, 0xbd, 0xe3, 0x8d, 0x6d, 0x1e, 0x84, 0x5b, 0x88, 0x6c, 0x12, 0xae, 0x38, 0xd0, + 0xaf, 0xcd, 0xe6, 0x70, 0x16, 0xce, 0xbe, 0x01, 0xcc, 0x1e, 0x8d, 0xbc, 0x4b, 0x2b, 0xe0, 0xa3, + 0x53, 0x4b, 0x2e, 0x62, 0xab, 0x7e, 0x3f, 0xf3, 0xa0, 0x64, 0x36, 0xb0, 0xa4, 0xc7, 0x47, 0xa7, + 0x47, 0x04, 0x67, 0x1f, 0x00, 0x6e, 0x26, 0xeb, 0x94, 0xdb, 0xe1, 0xd4, 0xe7, 0x41, 0x6b, 0xf1, + 0x7e, 0xee, 0x41, 0xfd, 0x49, 0x33, 0x5a, 0x2f, 0x04, 0x6f, 0x3a, 0xa1, 0x59, 0x15, 0x78, 0xf2, + 0x39, 0x58, 0xdf, 0x86, 0xd5, 0xf4, 0x21, 0x09, 0xa2, 0x12, 0xab, 0x22, 0x88, 0x31, 0x6f, 0x8a, + 0x9f, 0x6c, 0x19, 0x0a, 0x17, 0xf6, 0x68, 0xca, 0x25, 0x4f, 0xa7, 0x87, 0x0f, 0xb3, 0xdf, 0xcd, + 0x18, 0x7f, 0x94, 0x81, 0x2a, 0xcd, 0x52, 0xca, 0x22, 0x6f, 0x42, 0x4d, 0x51, 0x03, 0xf7, 0x7d, + 0xcf, 0x97, 0x5c, 0x4d, 0x51, 0x5e, 0x47, 0xc0, 0xc4, 0xa9, 0xa2, 0x90, 0x26, 0x3e, 0x77, 0xc6, + 0xf6, 0x99, 0x6a, 0x5a, 0x91, 0xd2, 0x91, 0x04, 0xb3, 0xf7, 0xe2, 0xf6, 0x7c, 0x6f, 0x1a, 0x72, + 0x79, 0xe6, 0x55, 0xe5, 0xf4, 0x4c, 0x01, 0x8b, 0x5a, 0xc7, 0xa7, 0x57, 0xa0, 0x73, 0xe3, 0xb7, + 0x33, 0xc0, 0xc4, 0xb0, 0xfb, 0x1e, 0x35, 0x20, 0x29, 0x74, 0xb6, 0x66, 0xe6, 0x95, 0x77, 0x48, + 0xf6, 0x45, 0x3b, 0xc4, 0x80, 0x02, 0x8d, 0x3d, 0x9f, 0x32, 0x76, 0x2a, 0xfa, 0x41, 0xbe, 0x94, + 0x6b, 0xe4, 0x8d, 0xff, 0x91, 0x83, 0xe5, 0x2d, 0x3a, 0xb2, 0xdb, 0x83, 0x01, 0x9f, 0x44, 0x7b, + 0xe7, 0x1e, 0x54, 0x5c, 0x6f, 0xc8, 0x15, 0xc5, 0xd2, 0xc0, 0x40, 0x80, 0x34, 0x72, 0x3d, 0xb7, + 0x1d, 0x97, 0x06, 0x4e, 0x8b, 0x59, 0x46, 0x08, 0x0e, 0xfb, 0x6d, 0x58, 0x9c, 0x70, 0x77, 0xa8, + 0x6f, 0x11, 0x12, 0xaa, 0x6a, 0x12, 0x2c, 0x77, 0xc7, 0x3d, 0xa8, 0x9c, 0x4e, 0x09, 0x4f, 0x30, + 0x96, 0x3c, 0xd2, 0x00, 0x48, 0x50, 0x9b, 0xf8, 0xcb, 0x64, 0x1a, 0x9c, 0x63, 0x69, 0x01, 0x4b, + 0x8b, 0xe2, 0x59, 0x14, 0xdd, 0x05, 0x18, 0x4e, 0x83, 0x50, 0xee, 0x98, 0x05, 0x2c, 0x2c, 0x0b, + 0x08, 0xed, 0x98, 0x6f, 0xc2, 0xd2, 0xd8, 0xbe, 0xb2, 0x90, 0x76, 0x2c, 0xc7, 0xb5, 0x4e, 0x47, + 0x78, 0xe6, 0x14, 0x11, 0xaf, 0x31, 0xb6, 0xaf, 0x3e, 0x11, 0x25, 0x5d, 0x77, 0x07, 0xe1, 0x82, + 0xad, 0x28, 0x71, 0xc7, 0xe7, 0x01, 0xf7, 0x2f, 0x38, 0x72, 0x82, 0x7c, 0x24, 0xd3, 0x98, 0x04, + 0x15, 0x23, 0x1a, 0x8b, 0x79, 0x87, 0xa3, 0x01, 0x6d, 0x7b, 0xb3, 0x38, 0x76, 0xdc, 0xdd, 0x70, + 0x34, 0x10, 0xe7, 0x8a, 0xe0, 0x23, 0x13, 0xee, 0x5b, 0xcf, 0x2f, 0x71, 0x0f, 0xe7, 0x91, 0x6f, + 0x1c, 0x71, 0xff, 0xd9, 0xa5, 0x38, 0xfa, 0x07, 0x01, 0x32, 0x22, 0xfb, 0xba, 0x55, 0xc1, 0x0d, + 0x5e, 0x1a, 0x04, 0x82, 0x05, 0xd9, 0xd7, 0x62, 0x13, 0x8a, 0xd1, 0xda, 0xf8, 0x16, 0xf8, 0x10, + 0x9b, 0x0f, 0x90, 0xa3, 0xd6, 0x70, 0xb0, 0x6d, 0x59, 0x20, 0xfa, 0x09, 0x04, 0xd5, 0xab, 0xc1, + 0x9e, 0x8e, 0xec, 0xb3, 0x00, 0x59, 0x4a, 0xcd, 0xac, 0x4a, 0xe0, 0x8e, 0x80, 0x19, 0x9f, 0x92, + 0x90, 0xa5, 0xbd, 0x5b, 0xb9, 0x67, 0xc4, 0x51, 0x8f, 0x10, 0x7c, 0xaf, 0x25, 0x53, 0x3e, 0xa5, + 0xbd, 0xb4, 0x6c, 0xca, 0x4b, 0x33, 0x7e, 0x37, 0x03, 0x55, 0xd9, 0x32, 0x0a, 0x25, 0x6c, 0x03, + 0x98, 0x7a, 0x8b, 0xe1, 0x95, 0x33, 0xb4, 0x4e, 0xae, 0x43, 0x1e, 0x10, 0xd1, 0xec, 0xde, 0x32, + 0x1b, 0xb2, 0xac, 0x7f, 0xe5, 0x0c, 0x37, 0x45, 0x09, 0x7b, 0x08, 0x8d, 0x04, 0x7e, 0x10, 0xfa, + 0x44, 0xd1, 0xbb, 0xb7, 0xcc, 0xba, 0x86, 0xdd, 0x0b, 0x7d, 0xb1, 0x47, 0x84, 0xc8, 0x33, 0x0d, + 0x2d, 0xc7, 0x1d, 0xf2, 0x2b, 0x24, 0xa3, 0x9a, 0x59, 0x21, 0x58, 0x57, 0x80, 0x36, 0xeb, 0x50, + 0xd5, 0x9b, 0x33, 0xce, 0xa0, 0xa4, 0xe4, 0x25, 0x14, 0x18, 0x66, 0x86, 0x64, 0x96, 0xc3, 0x68, + 0x24, 0xb7, 0xa1, 0x94, 0x1c, 0x81, 0x59, 0x0c, 0x5f, 0xb9, 0x63, 0xe3, 0x7b, 0xd0, 0xd8, 0x13, + 0xc4, 0xe3, 0x0a, 0x62, 0x95, 0xf2, 0xdf, 0x2a, 0x2c, 0x68, 0x9b, 0xa6, 0x6c, 0xca, 0x27, 0x71, + 0xe6, 0x9e, 0x7b, 0x41, 0x28, 0x7b, 0xc1, 0xdf, 0xc6, 0x1f, 0x67, 0x80, 0x75, 0x82, 0xd0, 0x19, + 0xdb, 0x21, 0xdf, 0xe1, 0x11, 0x5b, 0x38, 0x84, 0xaa, 0x68, 0xad, 0xef, 0xb5, 0x49, 0x20, 0x23, + 0x81, 0xe2, 0x5d, 0xb9, 0x8d, 0xe7, 0x2b, 0x6c, 0xe8, 0xd8, 0xc4, 0xe6, 0x13, 0x0d, 0x88, 0x5d, + 0x16, 0xda, 0xfe, 0x19, 0x0f, 0x51, 0x8c, 0x93, 0xf2, 0x3e, 0x10, 0x48, 0x08, 0x70, 0xeb, 0xbf, + 0x02, 0xcd, 0xb9, 0x36, 0x74, 0xbe, 0x5c, 0x4e, 0xe1, 0xcb, 0x39, 0x9d, 0x2f, 0x5b, 0xb0, 0x94, + 0x18, 0x97, 0xa4, 0xb4, 0x35, 0x28, 0x8a, 0x0d, 0x21, 0x84, 0x83, 0x0c, 0x49, 0x95, 0xa7, 0x9c, + 0x0b, 0x31, 0xf8, 0x11, 0x2c, 0x9f, 0x72, 0xee, 0xdb, 0x21, 0x16, 0xe2, 0x8e, 0x11, 0x6f, 0x48, + 0x36, 0xdc, 0x94, 0x65, 0x3d, 0x3b, 0x3c, 0xe2, 0xbe, 0x78, 0x53, 0xc6, 0xff, 0xcc, 0xc0, 0xa2, + 0xe0, 0xa0, 0xfb, 0xb6, 0x7b, 0xad, 0xd6, 0x69, 0x2f, 0x75, 0x9d, 0x1e, 0x68, 0x87, 0xa1, 0x86, + 0xfd, 0x65, 0x17, 0x29, 0x37, 0xbb, 0x48, 0xec, 0x3e, 0x54, 0x13, 0x63, 0x2d, 0xe0, 0x58, 0x21, + 0x88, 0x06, 0xf9, 0xf3, 0x2f, 0xe3, 0xdb, 0xd0, 0x88, 0x87, 0x2d, 0xd7, 0x90, 0x41, 0x5e, 0x90, + 0xa4, 0x6c, 0x00, 0x7f, 0x1b, 0xff, 0x32, 0x43, 0x88, 0x5b, 0x9e, 0x13, 0x49, 0xa7, 0x02, 0x51, + 0xc8, 0xbd, 0x0a, 0x51, 0xfc, 0xbe, 0x51, 0xaa, 0xff, 0xf9, 0x27, 0x2b, 0xb6, 0x4e, 0xc0, 0xdd, + 0xa1, 0x65, 0x8f, 0x46, 0xc8, 0x7c, 0x4b, 0x66, 0x51, 0x3c, 0xb7, 0x47, 0x23, 0xe3, 0x1d, 0x68, + 0x6a, 0xa3, 0x7b, 0xc1, 0x3c, 0x0e, 0x80, 0xed, 0x39, 0x41, 0x78, 0xec, 0x06, 0x13, 0x4d, 0x70, + 0xbb, 0x03, 0x65, 0xc1, 0x61, 0xc5, 0xc8, 0x68, 0xcb, 0x16, 0x4c, 0xc1, 0x72, 0xc5, 0xb8, 0x02, + 0x2c, 0xb4, 0xaf, 0x64, 0x61, 0x56, 0x16, 0xda, 0x57, 0x58, 0x68, 0x7c, 0x17, 0x96, 0x12, 0xed, + 0xc9, 0xae, 0xdf, 0x80, 0xc2, 0x34, 0xbc, 0xf2, 0x94, 0x68, 0x5e, 0x91, 0x14, 0x22, 0x14, 0x40, + 0x93, 0x4a, 0x8c, 0x8f, 0xa0, 0x79, 0xc0, 0x2f, 0xe5, 0x26, 0x56, 0x03, 0x79, 0x1b, 0xf2, 0x2f, + 0x51, 0x0a, 0xb1, 0xdc, 0xd8, 0x00, 0xa6, 0x57, 0x96, 0xbd, 0x6a, 0x3a, 0x62, 0x26, 0xa1, 0x23, + 0x1a, 0x6f, 0x03, 0xeb, 0x39, 0x67, 0xee, 0x3e, 0x0f, 0x02, 0xfb, 0x2c, 0xda, 0xf6, 0x0d, 0xc8, + 0x8d, 0x83, 0x33, 0xc9, 0xa3, 0xc4, 0x4f, 0xe3, 0x5b, 0xb0, 0x94, 0xc0, 0x93, 0x0d, 0xbf, 0x06, + 0xe5, 0xc0, 0x39, 0x73, 0x51, 0xb0, 0x92, 0x4d, 0xc7, 0x00, 0x63, 0x07, 0x96, 0x3f, 0xe1, 0xbe, + 0x73, 0x7a, 0xfd, 0xb2, 0xe6, 0x93, 0xed, 0x64, 0x67, 0xdb, 0xe9, 0xc0, 0xca, 0x4c, 0x3b, 0xb2, + 0x7b, 0x22, 0x5f, 0xf9, 0x26, 0x4b, 0x26, 0x3d, 0x68, 0x7c, 0x2f, 0xab, 0xf3, 0x3d, 0xe3, 0x18, + 0xd8, 0x96, 0xe7, 0xba, 0x7c, 0x10, 0x1e, 0x71, 0xee, 0xc7, 0x56, 0xaa, 0x98, 0x56, 0x2b, 0x4f, + 0xd6, 0xe4, 0xca, 0xce, 0x32, 0x53, 0x49, 0xc4, 0x0c, 0xf2, 0x13, 0xee, 0x8f, 0xb1, 0xe1, 0x92, + 0x89, 0xbf, 0x8d, 0x15, 0x58, 0x4a, 0x34, 0x2b, 0xf5, 0xfa, 0xc7, 0xb0, 0xb2, 0xed, 0x04, 0x83, + 0xf9, 0x0e, 0xd7, 0xa0, 0x38, 0x99, 0x9e, 0x58, 0x49, 0xbe, 0xfc, 0x8c, 0x5f, 0x0b, 0x6d, 0x6f, + 0xb6, 0x86, 0x6c, 0xeb, 0xef, 0x66, 0x20, 0xbf, 0xdb, 0xdf, 0xdb, 0x62, 0xeb, 0x50, 0x72, 0xdc, + 0x81, 0x37, 0x16, 0x82, 0x17, 0xcd, 0x39, 0x7a, 0xbe, 0x71, 0x83, 0xdd, 0x81, 0x32, 0xca, 0x6b, + 0x42, 0xb5, 0x95, 0xa2, 0x4f, 0x49, 0x00, 0xf6, 0xbc, 0xc1, 0x73, 0xa1, 0x53, 0xf3, 0xab, 0x89, + 0xe3, 0xa3, 0xd6, 0xac, 0x94, 0xe1, 0x3c, 0x9d, 0xf5, 0x71, 0x01, 0x69, 0xc4, 0xc6, 0x7f, 0x2a, + 0x41, 0x51, 0x9e, 0xb6, 0x74, 0x72, 0x87, 0xce, 0x05, 0x8f, 0x4f, 0x6e, 0xf1, 0x24, 0xe4, 0x01, + 0x9f, 0x8f, 0xbd, 0x30, 0x12, 0xd8, 0xe8, 0x1d, 0x54, 0x09, 0x28, 0x45, 0x36, 0x4d, 0x68, 0x20, + 0x13, 0x43, 0x8e, 0x90, 0x06, 0xfa, 0x51, 0x7e, 0x07, 0x8a, 0xea, 0xec, 0xcf, 0x47, 0x3a, 0xcd, + 0xc2, 0x80, 0xa4, 0xb5, 0x75, 0x28, 0x0d, 0xec, 0x89, 0x3d, 0x70, 0xc2, 0x6b, 0xc9, 0x10, 0xa2, + 0x67, 0xd1, 0xfa, 0xc8, 0x1b, 0xd8, 0x23, 0xeb, 0xc4, 0x1e, 0xd9, 0xee, 0x80, 0x4b, 0xdd, 0xbd, + 0x8a, 0xc0, 0x4d, 0x82, 0x09, 0xfd, 0x5c, 0x8e, 0x53, 0x61, 0x91, 0x0a, 0x2f, 0x47, 0xaf, 0xd0, + 0x84, 0x70, 0xe9, 0x8d, 0xc7, 0x8e, 0xd0, 0x32, 0x48, 0x0c, 0xcb, 0x99, 0x65, 0x82, 0xec, 0x70, + 0x9c, 0xad, 0x2c, 0xbe, 0xa4, 0xa5, 0x2b, 0x53, 0x57, 0x04, 0xfc, 0x94, 0x0c, 0x09, 0xf3, 0xb2, + 0x58, 0x4e, 0x93, 0xc5, 0xde, 0x85, 0xe6, 0xd4, 0x0d, 0x78, 0x18, 0x8e, 0xf8, 0x30, 0x1a, 0x4b, + 0x05, 0x91, 0x1a, 0x51, 0x81, 0x1a, 0xce, 0x06, 0x2c, 0x91, 0xd1, 0x21, 0xb0, 0x43, 0x2f, 0x38, + 0x77, 0x02, 0x2b, 0x10, 0x1a, 0x12, 0xa9, 0xbb, 0x4d, 0x2c, 0xea, 0xc9, 0x92, 0x1e, 0xa9, 0x48, + 0x6b, 0x33, 0xf8, 0x3e, 0x1f, 0x70, 0xe7, 0x82, 0x0f, 0x51, 0x4e, 0xcb, 0x99, 0x2b, 0x89, 0x3a, + 0xa6, 0x2c, 0x44, 0xa1, 0x7b, 0x3a, 0xb6, 0xa6, 0x93, 0xa1, 0x2d, 0x84, 0x95, 0x3a, 0x09, 0xc3, + 0xee, 0x74, 0x7c, 0x4c, 0x10, 0xf6, 0x18, 0x94, 0x24, 0x26, 0xe5, 0xc3, 0xc5, 0x04, 0x3f, 0x13, + 0xc4, 0x6a, 0x56, 0x25, 0x06, 0x09, 0x8a, 0x09, 0x99, 0xb3, 0x31, 0x23, 0x73, 0xb6, 0xa0, 0x38, + 0xf1, 0x9d, 0x0b, 0x3b, 0xe4, 0xad, 0x26, 0x31, 0x70, 0xf9, 0x28, 0x38, 0x83, 0xe3, 0x3a, 0xa1, + 0x63, 0x87, 0x9e, 0xdf, 0x62, 0x58, 0x16, 0x03, 0xd8, 0x43, 0x68, 0x22, 0x8d, 0x04, 0xa1, 0x1d, + 0x4e, 0x03, 0x29, 0x81, 0x2e, 0x21, 0x31, 0xa1, 0x0c, 0xdd, 0x43, 0x38, 0x0a, 0xa1, 0xec, 0x5b, + 0xb0, 0x4a, 0x64, 0x81, 0x35, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x32, 0x2e, 0xc5, 0x12, 0x96, 0x0a, + 0xfa, 0x96, 0xf2, 0xb5, 0x90, 0x0e, 0xde, 0x87, 0x35, 0x49, 0x26, 0x73, 0xb5, 0x56, 0xb0, 0xd6, + 0x32, 0x15, 0xcf, 0x54, 0xdb, 0x80, 0xa6, 0x18, 0x92, 0x33, 0xb0, 0x64, 0x6d, 0xb1, 0x13, 0x56, + 0xc5, 0xe8, 0x51, 0x53, 0x5a, 0xa4, 0x42, 0x13, 0xcb, 0x9e, 0xf1, 0x6b, 0xf6, 0x3d, 0x58, 0x24, + 0x92, 0x41, 0xf5, 0x0a, 0x39, 0xfd, 0x3a, 0x72, 0xfa, 0x15, 0x65, 0xe1, 0x8c, 0x4a, 0x91, 0xd9, + 0xd7, 0x07, 0x89, 0x67, 0xb1, 0x1d, 0x46, 0xce, 0x29, 0x0f, 0x9d, 0x31, 0x6f, 0xad, 0x11, 0x81, + 0xa9, 0x67, 0xb1, 0x53, 0xa7, 0x13, 0x2c, 0x69, 0x11, 0x5f, 0xa0, 0x27, 0xa4, 0xdd, 0x91, 0x17, + 0x70, 0x65, 0xa2, 0x6a, 0xdd, 0x96, 0x9b, 0x50, 0x00, 0x95, 0x0c, 0x29, 0x04, 0x71, 0x52, 0x7a, + 0x22, 0x43, 0xe2, 0x1d, 0x24, 0x86, 0x1a, 0xe9, 0x3e, 0xca, 0x98, 0x28, 0x4e, 0xf1, 0x73, 0xfb, + 0x52, 0x71, 0x90, 0xd7, 0xf0, 0xfd, 0x82, 0x00, 0x49, 0xde, 0xf1, 0xd3, 0x0c, 0x1d, 0x88, 0x92, + 0x7f, 0x04, 0x9a, 0x7a, 0x47, 0x9c, 0xc3, 0xf2, 0xdc, 0xd1, 0xb5, 0x64, 0x26, 0x40, 0xa0, 0x43, + 0x77, 0x84, 0xbb, 0xd9, 0x71, 0x75, 0x14, 0xe2, 0xbd, 0x55, 0x05, 0x44, 0xa4, 0x7b, 0x50, 0x99, + 0x4c, 0x4f, 0x46, 0xce, 0x80, 0x50, 0x72, 0xd4, 0x0a, 0x81, 0x10, 0x41, 0xe8, 0xb7, 0x44, 0x51, + 0x84, 0x91, 0x47, 0x8c, 0x8a, 0x84, 0x21, 0x0a, 0xf2, 0x76, 0xee, 0x23, 0x3b, 0xa9, 0x9a, 0xf8, + 0xdb, 0xd8, 0x84, 0xe5, 0xe4, 0xa0, 0xe5, 0xc1, 0xf3, 0x10, 0x4a, 0x92, 0x57, 0x29, 0xc3, 0x47, + 0x5d, 0x33, 0x45, 0x0b, 0x15, 0x2d, 0x2a, 0x37, 0x7e, 0x73, 0x01, 0x96, 0x24, 0x74, 0x4b, 0x2c, + 0x6d, 0x6f, 0x3a, 0x1e, 0xdb, 0x7e, 0x0a, 0x13, 0xcc, 0xbc, 0x98, 0x09, 0x66, 0xe7, 0x98, 0x60, + 0x52, 0xf3, 0x25, 0x1e, 0x9a, 0xd4, 0x7c, 0xc5, 0xbb, 0x24, 0x65, 0x44, 0xb7, 0x83, 0xd6, 0x24, + 0xb8, 0x4f, 0xf6, 0xd6, 0x39, 0x96, 0x5d, 0x48, 0x61, 0xd9, 0x3a, 0xc3, 0x5d, 0x98, 0x61, 0xb8, + 0x6f, 0x00, 0x11, 0x8d, 0x7a, 0xfb, 0x45, 0xd2, 0x4f, 0x10, 0x26, 0x8d, 0xa9, 0xef, 0xc0, 0xe2, + 0x2c, 0x8f, 0x23, 0x66, 0x5a, 0x4f, 0xe1, 0x70, 0xce, 0x98, 0xe3, 0x69, 0xa5, 0x21, 0x97, 0x25, + 0x87, 0x73, 0xc6, 0x7c, 0x0f, 0x4b, 0x14, 0x7e, 0x07, 0x80, 0xfa, 0xc6, 0x4d, 0x03, 0xb8, 0x69, + 0xde, 0x4e, 0xbe, 0x0b, 0x7d, 0xd5, 0x37, 0xc4, 0xc3, 0xd4, 0xe7, 0xb8, 0x8b, 0xca, 0x58, 0x13, + 0x37, 0xd0, 0x33, 0xa8, 0x7b, 0x13, 0xee, 0x5a, 0x31, 0xaf, 0xa9, 0x60, 0x53, 0x6f, 0xbd, 0xa0, + 0xa9, 0xae, 0xc2, 0x35, 0x6b, 0xa2, 0x6e, 0xf4, 0xc8, 0xf6, 0x69, 0xe1, 0xb9, 0xd6, 0x5a, 0xf5, + 0x4b, 0xb4, 0x56, 0xc7, 0xca, 0xd1, 0xb3, 0xf1, 0x0f, 0x32, 0x50, 0xd1, 0x86, 0xcd, 0x56, 0xa0, + 0xb9, 0x75, 0x78, 0x78, 0xd4, 0x31, 0xdb, 0xfd, 0xee, 0x27, 0x1d, 0x6b, 0x6b, 0xef, 0xb0, 0xd7, + 0x69, 0xdc, 0x12, 0xe0, 0xbd, 0xc3, 0xad, 0xf6, 0x9e, 0xb5, 0x73, 0x68, 0x6e, 0x29, 0x70, 0x86, + 0xad, 0x02, 0x33, 0x3b, 0xfb, 0x87, 0xfd, 0x4e, 0x02, 0x9e, 0x65, 0x0d, 0xa8, 0x6e, 0x9a, 0x9d, + 0xf6, 0xd6, 0xae, 0x84, 0xe4, 0xd8, 0x32, 0x34, 0x76, 0x8e, 0x0f, 0xb6, 0xbb, 0x07, 0x4f, 0xad, + 0xad, 0xf6, 0xc1, 0x56, 0x67, 0xaf, 0xb3, 0xdd, 0xc8, 0xb3, 0x1a, 0x94, 0xdb, 0x9b, 0xed, 0x83, + 0xed, 0xc3, 0x83, 0xce, 0x76, 0xa3, 0x60, 0xfc, 0x12, 0x94, 0xe3, 0x89, 0x56, 0xa0, 0x78, 0x7c, + 0xf0, 0xec, 0xe0, 0xf0, 0xd3, 0x83, 0xc6, 0x2d, 0x56, 0x86, 0x02, 0xf6, 0xdf, 0xc8, 0x30, 0x80, + 0x05, 0xea, 0xb3, 0x91, 0x65, 0x25, 0xc8, 0x6f, 0x1e, 0xf6, 0x77, 0x1b, 0x39, 0xe3, 0x2f, 0x32, + 0xb0, 0x82, 0x53, 0x1e, 0xce, 0x32, 0x81, 0xfb, 0x50, 0x19, 0x78, 0xde, 0x44, 0x68, 0x5a, 0xb1, + 0x44, 0xa1, 0x83, 0xc4, 0x06, 0x27, 0xe6, 0x7d, 0xea, 0xf9, 0x03, 0x2e, 0x79, 0x00, 0x20, 0x68, + 0x47, 0x40, 0x04, 0x0d, 0x4a, 0x22, 0x26, 0x0c, 0x62, 0x01, 0x15, 0x82, 0x11, 0xca, 0x2a, 0x2c, + 0x9c, 0xf8, 0xdc, 0x1e, 0x9c, 0xcb, 0xdd, 0x2f, 0x9f, 0xd8, 0xd7, 0x63, 0x1b, 0xc0, 0x40, 0xd0, + 0xd4, 0x88, 0x0f, 0x71, 0x0b, 0x94, 0xcc, 0x45, 0x09, 0xdf, 0x92, 0x60, 0x71, 0x1a, 0xd9, 0x27, + 0xb6, 0x3b, 0xf4, 0x5c, 0x3e, 0x94, 0xaa, 0x46, 0x0c, 0x30, 0x8e, 0x60, 0x75, 0x76, 0x7e, 0x92, + 0x5f, 0x7c, 0xa0, 0xf1, 0x0b, 0x92, 0xfc, 0xd7, 0x6f, 0x26, 0x05, 0x8d, 0x77, 0xfc, 0xa3, 0x3c, + 0xe4, 0x85, 0x24, 0x78, 0xa3, 0xd0, 0xa8, 0x8b, 0xf6, 0xb9, 0x39, 0xf7, 0x0f, 0x9a, 0x1a, 0x48, + 0x44, 0x20, 0x7b, 0x56, 0x19, 0x21, 0x28, 0x1a, 0x44, 0xc5, 0x3e, 0x1f, 0x5c, 0x48, 0x83, 0x16, + 0x15, 0x9b, 0x7c, 0x70, 0x81, 0x3a, 0x95, 0x1d, 0x52, 0x5d, 0xda, 0xef, 0xc5, 0xc0, 0x0e, 0xb1, + 0xa6, 0x2c, 0xc2, 0x7a, 0xc5, 0xa8, 0x08, 0x6b, 0xb5, 0xa0, 0xe8, 0xb8, 0x27, 0xde, 0xd4, 0x1d, + 0xe2, 0xf6, 0x2e, 0x99, 0xea, 0x11, 0xbd, 0x4d, 0xc8, 0x89, 0xc4, 0x41, 0x44, 0xbb, 0xb9, 0x24, + 0x00, 0x7d, 0x71, 0x14, 0xbd, 0x07, 0xe5, 0xe0, 0xda, 0x1d, 0xe8, 0x7b, 0x78, 0x59, 0xae, 0x8f, + 0x98, 0xfd, 0x46, 0xef, 0xda, 0x1d, 0xe0, 0x8e, 0x2d, 0x05, 0xf2, 0x17, 0x7b, 0x1f, 0x4a, 0x91, + 0xdd, 0x97, 0x38, 0xf0, 0x6d, 0xbd, 0x86, 0x32, 0xf6, 0x92, 0x7a, 0x1d, 0xa1, 0xb2, 0x47, 0xb0, + 0x80, 0xc6, 0xd9, 0xa0, 0x55, 0xc5, 0x4a, 0x4a, 0xde, 0x17, 0xc3, 0x40, 0x47, 0x0f, 0x1f, 0xa2, + 0xa1, 0xd6, 0x94, 0x68, 0xeb, 0xcf, 0xa0, 0x96, 0x68, 0x4b, 0x57, 0xa2, 0x6b, 0xa4, 0x44, 0xbf, + 0xa5, 0x2b, 0xd1, 0xf1, 0x49, 0x20, 0xab, 0xe9, 0x4a, 0xf5, 0xaf, 0x40, 0x49, 0x4d, 0x45, 0xec, + 0x3f, 0xb9, 0x77, 0xac, 0xde, 0x67, 0x07, 0x5b, 0x8d, 0x5b, 0x6c, 0x11, 0x2a, 0xed, 0x2d, 0xdc, + 0xd2, 0x08, 0xc8, 0x08, 0x94, 0xa3, 0x76, 0xaf, 0x17, 0x41, 0xb2, 0xc6, 0x0e, 0x34, 0x66, 0x47, + 0x2a, 0x68, 0x32, 0x54, 0x30, 0x69, 0xba, 0x8e, 0x01, 0x42, 0x45, 0x22, 0x6b, 0x34, 0xc9, 0xe1, + 0xf4, 0x60, 0xbc, 0x0f, 0x0d, 0x71, 0xae, 0x89, 0xa5, 0x0a, 0x34, 0x13, 0xf0, 0x48, 0xc8, 0x76, + 0xba, 0xf9, 0xba, 0x64, 0x56, 0x08, 0x86, 0x5d, 0x19, 0x1f, 0x40, 0x53, 0xab, 0x16, 0xab, 0xb4, + 0xe2, 0xac, 0x9c, 0x55, 0x69, 0x51, 0x81, 0xa1, 0x12, 0x63, 0x0d, 0x56, 0xc4, 0x63, 0xe7, 0x82, + 0xbb, 0x61, 0x6f, 0x7a, 0x42, 0x3e, 0x47, 0xc7, 0x73, 0x85, 0x62, 0x53, 0x8e, 0x4a, 0x6e, 0x26, + 0xf2, 0x0d, 0xa9, 0xfd, 0x66, 0x91, 0x34, 0xd6, 0xb5, 0x1e, 0xb0, 0xe2, 0x06, 0xfe, 0x4d, 0x68, + 0xc1, 0xe5, 0x08, 0x24, 0x96, 0xf5, 0xa8, 0xd3, 0x31, 0xad, 0xc3, 0x83, 0xbd, 0xee, 0x81, 0x60, + 0x94, 0x62, 0x59, 0x11, 0xb0, 0xb3, 0x83, 0x90, 0x8c, 0xd1, 0x80, 0xfa, 0x53, 0x1e, 0x76, 0xdd, + 0x53, 0x4f, 0xf9, 0xd7, 0xfe, 0xaa, 0x00, 0x8b, 0x11, 0x28, 0xd6, 0xa2, 0x2f, 0xb8, 0x1f, 0x38, + 0x9e, 0x8b, 0x02, 0x71, 0xd9, 0x54, 0x8f, 0xe2, 0x74, 0x73, 0x86, 0xdc, 0x0d, 0x9d, 0xf0, 0xda, + 0x4a, 0x98, 0xdc, 0xea, 0x0a, 0x2c, 0x4f, 0xd1, 0x65, 0x28, 0xd8, 0x23, 0xc7, 0x56, 0xae, 0x5a, + 0x7a, 0x10, 0xd0, 0x81, 0x37, 0xf2, 0x7c, 0x94, 0x7d, 0xcb, 0x26, 0x3d, 0xb0, 0xc7, 0xb0, 0x2c, + 0x64, 0x70, 0xdd, 0x0e, 0x8a, 0xfc, 0x83, 0xac, 0x7f, 0xcc, 0x9d, 0x8e, 0x8f, 0x62, 0x5b, 0xa8, + 0x28, 0x11, 0x67, 0xa7, 0xa8, 0x21, 0x85, 0xa5, 0xa8, 0x02, 0xa9, 0x73, 0x4d, 0x77, 0x3a, 0x6e, + 0x63, 0x49, 0x84, 0xff, 0x04, 0x56, 0x04, 0x7e, 0x24, 0x5e, 0x45, 0x35, 0x16, 0xb1, 0x86, 0x68, + 0xac, 0x2b, 0xcb, 0xa2, 0x3a, 0x77, 0xa0, 0x4c, 0xa3, 0x12, 0x6f, 0xbc, 0x40, 0x62, 0x3c, 0x0e, + 0x85, 0xfb, 0xc1, 0x9c, 0x57, 0x75, 0x81, 0x04, 0x81, 0x19, 0xaf, 0xaa, 0xe6, 0x97, 0x2d, 0xcd, + 0xfa, 0x65, 0x9f, 0xc0, 0xca, 0x89, 0x20, 0xc1, 0x73, 0x6e, 0x0f, 0xb9, 0x6f, 0xc5, 0x84, 0x4d, + 0xea, 0xca, 0x92, 0x28, 0xdc, 0xc5, 0xb2, 0x68, 0x1f, 0x08, 0x39, 0x47, 0xb0, 0x05, 0x3e, 0xb4, + 0x42, 0xcf, 0x42, 0xf1, 0x07, 0x19, 0x4c, 0xc9, 0xac, 0x11, 0xb8, 0xef, 0x6d, 0x09, 0x60, 0x12, + 0xef, 0xcc, 0xb7, 0x27, 0xe7, 0x52, 0xa1, 0x88, 0xf0, 0x9e, 0x0a, 0x20, 0x7b, 0x0d, 0x8a, 0x82, + 0xe4, 0x5d, 0x4e, 0xce, 0x2f, 0x12, 0xd9, 0x15, 0x88, 0xbd, 0x05, 0x0b, 0xd8, 0x47, 0xd0, 0x6a, + 0x20, 0xbd, 0x57, 0x63, 0x46, 0xee, 0xb8, 0xa6, 0x2c, 0x13, 0xc2, 0xe4, 0xd4, 0x77, 0x88, 0xcb, + 0x94, 0x4d, 0xfc, 0xcd, 0xbe, 0xaf, 0xb1, 0xac, 0x25, 0xac, 0xab, 0xe4, 0x81, 0x19, 0x4a, 0xbb, + 0x89, 0x7b, 0x7d, 0xa5, 0xcc, 0xe8, 0x07, 0xf9, 0x52, 0xa5, 0x51, 0x35, 0xbe, 0x03, 0x05, 0x5a, + 0x1d, 0x41, 0x84, 0xb8, 0x76, 0x19, 0x49, 0x84, 0x08, 0x6d, 0x41, 0xd1, 0xe5, 0xe1, 0xa5, 0xe7, + 0x3f, 0x57, 0x46, 0x69, 0xf9, 0x68, 0xfc, 0x18, 0xad, 0x29, 0x91, 0xc7, 0x9d, 0x14, 0x43, 0x41, + 0x1e, 0xf4, 0x7a, 0x83, 0x73, 0x5b, 0x1a, 0x78, 0x4a, 0x08, 0xe8, 0x9d, 0xdb, 0x73, 0xe4, 0x91, + 0x9d, 0x77, 0xba, 0xbf, 0x05, 0x75, 0xe5, 0xe3, 0x0f, 0xac, 0x11, 0x3f, 0x0d, 0x25, 0xb9, 0x57, + 0xa5, 0x83, 0x3f, 0xd8, 0xe3, 0xa7, 0xa1, 0xb1, 0x0f, 0x4d, 0x49, 0x90, 0x87, 0x13, 0xae, 0xba, + 0xfe, 0x6e, 0x9a, 0x3c, 0x5d, 0x79, 0xb2, 0x94, 0x3c, 0x68, 0x29, 0x76, 0x21, 0x21, 0x64, 0x1b, + 0x1f, 0x03, 0xd3, 0x8f, 0x61, 0xd9, 0x9e, 0x94, 0x6a, 0x95, 0x2d, 0x5f, 0xb9, 0xc4, 0x22, 0xd9, + 0xd9, 0x19, 0x8a, 0xd5, 0x09, 0xa6, 0x83, 0x81, 0x8a, 0xbd, 0x28, 0x99, 0xea, 0xd1, 0xf8, 0xd3, + 0x0c, 0x2c, 0x61, 0x63, 0x4a, 0x1f, 0x90, 0x4c, 0xf6, 0x67, 0x1e, 0xa4, 0x78, 0x3f, 0xba, 0xec, + 0x43, 0x0f, 0x5f, 0xde, 0x7a, 0x9a, 0x9f, 0xb3, 0x9e, 0x7e, 0x1d, 0x1a, 0x43, 0x3e, 0x72, 0x30, + 0x0c, 0x47, 0x89, 0x12, 0xa4, 0x01, 0x2c, 0x2a, 0xb8, 0xd4, 0x06, 0x8d, 0x7f, 0x96, 0x81, 0x26, + 0x49, 0x2a, 0xa8, 0x57, 0xcb, 0x85, 0xfa, 0x48, 0x29, 0x92, 0x92, 0x55, 0xc9, 0x39, 0xc5, 0x27, + 0x38, 0x42, 0x09, 0x79, 0xf7, 0x96, 0x54, 0x30, 0x25, 0x94, 0x7d, 0x88, 0x3a, 0x8c, 0x6b, 0x21, + 0x30, 0x25, 0xac, 0x27, 0xf9, 0x52, 0x76, 0x6f, 0xa1, 0x82, 0xe3, 0x22, 0x68, 0xb3, 0x24, 0x34, + 0x5b, 0x01, 0x36, 0x76, 0xa0, 0x96, 0xe8, 0x26, 0x61, 0xe2, 0xad, 0x92, 0x89, 0x77, 0xce, 0x8d, + 0x92, 0x9d, 0x77, 0xa3, 0xfc, 0xbd, 0x3c, 0x30, 0x41, 0x52, 0x33, 0x6f, 0x6d, 0xc6, 0x07, 0x99, + 0x9d, 0xf3, 0x41, 0x3e, 0x06, 0xa6, 0x21, 0x28, 0xd7, 0x68, 0x2e, 0x72, 0x8d, 0x36, 0x62, 0x5c, + 0xe9, 0x19, 0x7d, 0x0c, 0xcb, 0x52, 0xa0, 0x8d, 0x9c, 0x8e, 0x68, 0xbb, 0xa3, 0xf7, 0xc3, 0x48, + 0xb2, 0x55, 0xce, 0x47, 0xb4, 0xe3, 0x29, 0xff, 0xa3, 0xd0, 0xc1, 0xc9, 0xe4, 0x85, 0xfe, 0x47, + 0xa5, 0x7d, 0x6b, 0x54, 0xb0, 0xf0, 0x52, 0x2a, 0x28, 0xce, 0x51, 0x81, 0x66, 0x81, 0x29, 0x25, + 0x2d, 0x30, 0x06, 0xd4, 0x94, 0x97, 0x91, 0x82, 0x2b, 0x48, 0x7a, 0xab, 0x48, 0x57, 0x23, 0x06, + 0x58, 0x3c, 0x80, 0x86, 0x32, 0x93, 0x44, 0x36, 0x1e, 0x0a, 0x1c, 0x90, 0x56, 0xb6, 0x2d, 0x65, + 0xe9, 0x49, 0x58, 0xd4, 0x2b, 0x33, 0x16, 0xf5, 0x77, 0xa1, 0x19, 0x08, 0x22, 0xb2, 0xa6, 0xae, + 0x8c, 0xf2, 0xe1, 0x43, 0x54, 0x9d, 0x4a, 0x66, 0x03, 0x0b, 0x8e, 0x63, 0xf8, 0xbc, 0xfd, 0xa2, + 0x96, 0x62, 0xbf, 0x78, 0x3f, 0x76, 0xc8, 0x05, 0xe7, 0xce, 0x18, 0x0f, 0xee, 0x38, 0x22, 0x46, + 0x2e, 0x70, 0xef, 0xdc, 0x19, 0x9b, 0xca, 0xfb, 0x2b, 0x1e, 0x8c, 0xff, 0x98, 0x81, 0x86, 0xa0, + 0x83, 0x04, 0x9d, 0xff, 0x12, 0xe0, 0x8e, 0x7c, 0x45, 0x32, 0xaf, 0x08, 0x5c, 0x45, 0xe5, 0xdf, + 0x01, 0x24, 0x5b, 0x4b, 0xe8, 0x89, 0x92, 0xc8, 0x5b, 0x49, 0x22, 0x8f, 0x19, 0xd9, 0xee, 0x2d, + 0x52, 0x00, 0x04, 0x24, 0xcd, 0x11, 0x9a, 0x4f, 0x71, 0x84, 0x6a, 0x5b, 0x61, 0x17, 0xe0, 0x19, + 0xbf, 0xde, 0xf3, 0x06, 0xa8, 0xa1, 0xdd, 0x05, 0x10, 0x04, 0x79, 0x6a, 0x8f, 0x1d, 0x69, 0x5d, + 0x29, 0x98, 0xe5, 0xe7, 0xfc, 0x7a, 0x07, 0x01, 0xe2, 0x6d, 0x88, 0xe2, 0x78, 0x3f, 0x14, 0xcc, + 0xd2, 0x73, 0x7e, 0x4d, 0x9b, 0xc1, 0x82, 0xda, 0x33, 0x7e, 0xbd, 0xcd, 0x49, 0x5c, 0xf3, 0x7c, + 0x41, 0x09, 0xbe, 0x7d, 0x29, 0xe4, 0xb3, 0x84, 0x13, 0xb3, 0xe2, 0xdb, 0x97, 0xcf, 0xf8, 0xb5, + 0x72, 0xa8, 0x16, 0x45, 0xf9, 0xc8, 0x1b, 0xc8, 0x13, 0x48, 0x85, 0x63, 0xc4, 0x83, 0x32, 0x17, + 0x9e, 0xe3, 0x6f, 0xe3, 0xaf, 0x33, 0x50, 0x13, 0xe3, 0x47, 0x06, 0x27, 0xd6, 0x5d, 0x45, 0xf5, + 0x64, 0xe2, 0xa8, 0x9e, 0x27, 0x92, 0x3f, 0x10, 0xb7, 0xcc, 0xde, 0xcc, 0x2d, 0x71, 0x81, 0x89, + 0x55, 0xbe, 0x07, 0x65, 0xda, 0x5b, 0x62, 0xb3, 0xe6, 0x12, 0x6f, 0x29, 0x31, 0x21, 0xb3, 0x84, + 0x68, 0xcf, 0x28, 0x88, 0x40, 0xb3, 0xd4, 0xd1, 0x12, 0x97, 0xfd, 0xc8, 0x3e, 0x97, 0xf2, 0x1a, + 0x0a, 0x37, 0x04, 0x11, 0xe8, 0x66, 0xb0, 0x85, 0x39, 0x33, 0xd8, 0x31, 0x54, 0x34, 0xa2, 0x43, + 0xbb, 0x5f, 0x34, 0x3b, 0xa2, 0xd0, 0x24, 0x55, 0x25, 0x96, 0x67, 0xf7, 0x96, 0x59, 0x1b, 0xe8, + 0x80, 0xcd, 0x05, 0xc8, 0x8b, 0x4a, 0xc6, 0x47, 0xd0, 0xd4, 0x9a, 0x25, 0x75, 0x35, 0x6d, 0xd0, + 0x99, 0x34, 0x27, 0xfa, 0x3f, 0xcf, 0xc0, 0xb2, 0xac, 0x8d, 0x21, 0x62, 0x8e, 0x38, 0xcf, 0xf7, + 0x83, 0x33, 0xf6, 0x4b, 0x50, 0x13, 0xad, 0x5b, 0x3e, 0x3f, 0x73, 0x82, 0x90, 0x2b, 0x1f, 0x49, + 0xca, 0xee, 0x11, 0x6c, 0x5d, 0xa0, 0x9a, 0x12, 0x93, 0x7d, 0x04, 0x15, 0xac, 0x4a, 0x0a, 0xb5, + 0x7c, 0x6f, 0xad, 0xf9, 0x8a, 0x34, 0xd4, 0xdd, 0x5b, 0x26, 0x04, 0xd1, 0xd3, 0x66, 0x19, 0x8a, + 0xa1, 0xef, 0x9c, 0x9d, 0x71, 0xdf, 0x58, 0x8d, 0x86, 0x26, 0xb6, 0x22, 0xef, 0x85, 0x7c, 0x22, + 0xa4, 0x24, 0xe3, 0xbf, 0x64, 0xa0, 0x22, 0x37, 0xd7, 0xcf, 0xec, 0x18, 0x59, 0xd7, 0x62, 0x1c, + 0x49, 0x77, 0x8e, 0x43, 0x1a, 0xdf, 0x81, 0xc5, 0xb1, 0x90, 0x98, 0x84, 0x44, 0x9f, 0xf0, 0x8a, + 0xd4, 0x15, 0x58, 0x0a, 0x2c, 0x1b, 0xb0, 0x84, 0xf2, 0x4b, 0x60, 0x85, 0xce, 0xc8, 0x52, 0x85, + 0x32, 0x9e, 0xb0, 0x49, 0x45, 0x7d, 0x67, 0xb4, 0x2f, 0x0b, 0xc4, 0x31, 0x1e, 0x84, 0xf6, 0x19, + 0x97, 0xb4, 0x41, 0x0f, 0x46, 0x0b, 0x56, 0x67, 0x84, 0x79, 0xa5, 0x88, 0xfc, 0x7e, 0x13, 0xd6, + 0xe6, 0x8a, 0xa4, 0x42, 0x12, 0x79, 0x03, 0x46, 0xce, 0xf8, 0xc4, 0x8b, 0x6c, 0x65, 0x19, 0xcd, + 0x1b, 0xb0, 0x27, 0x4a, 0x94, 0xad, 0x8c, 0xc3, 0x8a, 0x22, 0x08, 0x34, 0x76, 0x45, 0xf2, 0x7e, + 0x16, 0xa5, 0xd1, 0xf7, 0x92, 0x9c, 0x6c, 0xb6, 0x3b, 0x05, 0xd7, 0xcf, 0xc7, 0xa5, 0xc9, 0x1c, + 0x2c, 0x60, 0xa7, 0xd0, 0x8a, 0xe8, 0x4e, 0x0a, 0x50, 0x9a, 0xf2, 0x22, 0x7a, 0xfa, 0xc6, 0x4b, + 0x7a, 0x4a, 0x58, 0x51, 0xcc, 0x55, 0x45, 0xae, 0xd4, 0x58, 0xd4, 0xcf, 0x05, 0xbc, 0xae, 0xfa, + 0x41, 0x61, 0x68, 0xbe, 0xb7, 0xfc, 0x2b, 0xcd, 0x0b, 0xad, 0x43, 0xc9, 0x2e, 0xef, 0xc8, 0x86, + 0xa3, 0x22, 0xbd, 0xdf, 0x73, 0x58, 0xbd, 0xb4, 0x9d, 0x50, 0xcd, 0x4f, 0xd3, 0x9b, 0x0a, 0xd8, + 0xdf, 0x93, 0x97, 0xf4, 0xf7, 0x29, 0x55, 0x4e, 0x88, 0x87, 0xcb, 0x97, 0xf3, 0xc0, 0x60, 0xfd, + 0x4f, 0xb2, 0x50, 0x4f, 0xb6, 0x22, 0x36, 0xb5, 0x64, 0x54, 0x4a, 0xe0, 0x90, 0x02, 0xbb, 0xb4, + 0xe1, 0x1e, 0x90, 0xa0, 0x31, 0x6f, 0x5d, 0xce, 0xa6, 0x58, 0x97, 0x75, 0xa3, 0x6e, 0xee, 0x65, + 0x5e, 0xb4, 0xfc, 0x2b, 0x79, 0xd1, 0x0a, 0x69, 0x5e, 0xb4, 0x9b, 0x5d, 0x2f, 0x0b, 0x3f, 0x93, + 0xeb, 0xa5, 0xf8, 0x02, 0xd7, 0x4b, 0xc2, 0x61, 0x54, 0x9a, 0x71, 0x18, 0xad, 0xff, 0x75, 0x06, + 0xd8, 0x3c, 0x1d, 0xb3, 0xa7, 0x64, 0x66, 0x77, 0xf9, 0x48, 0xf2, 0xb8, 0x6f, 0xbe, 0xda, 0x5e, + 0x50, 0xaf, 0x4f, 0xd5, 0x66, 0x8f, 0x60, 0x49, 0x8f, 0x4f, 0xd6, 0x35, 0x9d, 0x9a, 0xc9, 0xf4, + 0xa2, 0x58, 0x1f, 0xd6, 0x1c, 0x8c, 0xf9, 0x97, 0x3a, 0x18, 0x0b, 0x2f, 0x75, 0x30, 0x2e, 0x24, + 0x1d, 0x8c, 0xeb, 0xff, 0x2d, 0x03, 0x4b, 0x29, 0x24, 0xf7, 0xd5, 0xcd, 0x59, 0x50, 0x4a, 0x82, + 0x01, 0x65, 0x25, 0xa5, 0xe8, 0xbc, 0x67, 0x0f, 0x2a, 0xb1, 0xcf, 0x4a, 0xc5, 0xef, 0x3f, 0x7c, + 0x19, 0x1f, 0x88, 0x6b, 0x98, 0x7a, 0xf5, 0xf5, 0xdf, 0xcb, 0x42, 0x45, 0x2b, 0x14, 0xab, 0x48, + 0x04, 0xa6, 0xc5, 0x75, 0x90, 0x0c, 0x80, 0x7a, 0xda, 0x3d, 0x90, 0x86, 0x60, 0x2a, 0xa7, 0xad, + 0x20, 0x0f, 0x7c, 0x44, 0xd8, 0x80, 0x25, 0xe5, 0x02, 0xe1, 0x71, 0xf8, 0x96, 0x3c, 0x15, 0x9a, + 0xd2, 0x11, 0xc2, 0xa3, 0x68, 0x30, 0xf6, 0x48, 0x49, 0xef, 0xf1, 0xbb, 0x43, 0xc2, 0x24, 0x2b, + 0x6b, 0x93, 0xc8, 0x59, 0xbd, 0x44, 0x41, 0x95, 0xef, 0xc1, 0x8a, 0x22, 0xe6, 0x64, 0x0d, 0x32, + 0xbc, 0x32, 0x49, 0xca, 0x7a, 0x95, 0xef, 0xc3, 0xdd, 0x99, 0x31, 0xcd, 0x54, 0xa5, 0x38, 0xc3, + 0xdb, 0x89, 0xd1, 0xe9, 0x2d, 0xac, 0xff, 0x04, 0x6a, 0x09, 0xb6, 0xf6, 0xd5, 0xbd, 0xf2, 0x59, + 0xdd, 0x98, 0x56, 0x54, 0xd7, 0x8d, 0xd7, 0xff, 0x6f, 0x0e, 0xd8, 0x3c, 0x67, 0xfd, 0x45, 0x0e, + 0x61, 0x9e, 0x30, 0x73, 0x29, 0x84, 0xf9, 0xff, 0xed, 0xa4, 0x7f, 0x17, 0x9a, 0x32, 0x8f, 0x45, + 0xf3, 0x63, 0xd1, 0xe6, 0x6c, 0x44, 0x05, 0x6a, 0x14, 0xdf, 0x99, 0xf5, 0xa7, 0x97, 0x12, 0xa1, + 0xfb, 0x9a, 0xa8, 0x33, 0xe3, 0x56, 0x3f, 0x86, 0x05, 0xdb, 0x1d, 0x9c, 0x7b, 0x3e, 0xaa, 0x65, + 0xf5, 0x27, 0xbf, 0xfc, 0xa5, 0x0f, 0xbb, 0x8d, 0x36, 0xd6, 0x47, 0xf9, 0xca, 0x94, 0x8d, 0x19, + 0xef, 0x41, 0x45, 0x03, 0xa3, 0x6f, 0xa7, 0xbb, 0xbf, 0x79, 0xd8, 0xb8, 0xc5, 0x6a, 0x50, 0x36, + 0x3b, 0x5b, 0x87, 0x9f, 0x74, 0xcc, 0xce, 0x76, 0x23, 0xc3, 0x4a, 0x90, 0xdf, 0x3b, 0xec, 0xf5, + 0x1b, 0x59, 0x63, 0x1d, 0x5a, 0xb2, 0xc5, 0x79, 0x3b, 0xef, 0x6f, 0xe7, 0x23, 0x13, 0x0b, 0x16, + 0x4a, 0x8d, 0xea, 0x5b, 0x50, 0xd5, 0x05, 0x11, 0x49, 0x11, 0x33, 0xae, 0x54, 0xa1, 0x4b, 0x79, + 0x1a, 0xaf, 0xde, 0x02, 0x72, 0x90, 0x0d, 0xa3, 0x6a, 0x24, 0x5d, 0xbe, 0xc0, 0xa3, 0x82, 0x82, + 0x73, 0x82, 0x0c, 0xff, 0x06, 0xd4, 0x93, 0x46, 0x4f, 0xc9, 0x91, 0xd2, 0x54, 0x0b, 0x51, 0x3b, + 0x61, 0x05, 0x65, 0xdf, 0x87, 0xc6, 0xac, 0xd1, 0x54, 0x46, 0x38, 0xdf, 0x50, 0x7f, 0xd1, 0x49, + 0xda, 0x51, 0xd9, 0x2e, 0x2c, 0xa7, 0x89, 0x62, 0x48, 0x1f, 0x37, 0xeb, 0x94, 0x6c, 0x5e, 0xdc, + 0x62, 0xdf, 0x95, 0xb6, 0xf1, 0x42, 0x9a, 0x87, 0x51, 0x5b, 0xec, 0x0d, 0xfa, 0xa7, 0x59, 0xc9, + 0x2f, 0x00, 0x62, 0x18, 0x6b, 0x40, 0xf5, 0xf0, 0xa8, 0x73, 0x60, 0x6d, 0xed, 0xb6, 0x0f, 0x0e, + 0x3a, 0x7b, 0x8d, 0x5b, 0x8c, 0x41, 0x1d, 0x5d, 0x83, 0xdb, 0x11, 0x2c, 0x23, 0x60, 0xd2, 0x47, + 0xa1, 0x60, 0x59, 0xb6, 0x0c, 0x8d, 0xee, 0xc1, 0x0c, 0x34, 0xc7, 0x5a, 0xb0, 0x7c, 0xd4, 0x21, + 0x6f, 0x62, 0xa2, 0xdd, 0xbc, 0x10, 0xef, 0xe5, 0x74, 0x85, 0x78, 0x4f, 0xf9, 0x58, 0x72, 0x1f, + 0x28, 0xa9, 0xf7, 0x77, 0x32, 0xb0, 0x32, 0x53, 0x10, 0x47, 0xd9, 0x93, 0xcc, 0x9b, 0x94, 0x76, + 0xab, 0x08, 0x54, 0xbb, 0xe9, 0x5d, 0x68, 0x46, 0x76, 0x82, 0x99, 0x53, 0xa9, 0x11, 0x15, 0x28, + 0xe4, 0x47, 0xb0, 0xa4, 0x99, 0x1b, 0x66, 0x78, 0x05, 0xd3, 0x8a, 0x64, 0x05, 0x63, 0x2d, 0x8a, + 0x66, 0x9e, 0x19, 0xf5, 0x90, 0x92, 0xbc, 0xf4, 0x82, 0xd8, 0x75, 0x90, 0x1c, 0xaf, 0x7a, 0x64, + 0x8f, 0x67, 0x08, 0x21, 0x39, 0x5a, 0xfd, 0x85, 0xab, 0xee, 0xff, 0x60, 0x01, 0xd8, 0xc7, 0x53, + 0xee, 0x5f, 0x63, 0x14, 0x7d, 0xf0, 0xb2, 0xb0, 0x32, 0xa5, 0x53, 0x67, 0x5f, 0x29, 0x53, 0x26, + 0x2d, 0x53, 0x25, 0xff, 0xf2, 0x4c, 0x95, 0xc2, 0xcb, 0x32, 0x55, 0xde, 0x84, 0x9a, 0x73, 0xe6, + 0x7a, 0x82, 0x15, 0x0a, 0xb9, 0x35, 0x68, 0x2d, 0xdc, 0xcf, 0x3d, 0xa8, 0x9a, 0x55, 0x09, 0x14, + 0x52, 0x6b, 0xc0, 0x3e, 0x8a, 0x91, 0xf8, 0xf0, 0x0c, 0xb3, 0xaa, 0x74, 0x26, 0xd8, 0x19, 0x9e, + 0x71, 0x69, 0x42, 0x40, 0xa3, 0x9a, 0xaa, 0x2c, 0xe0, 0x01, 0x7b, 0x0b, 0xea, 0x81, 0x37, 0x15, + 0x6a, 0x80, 0x5a, 0x06, 0x72, 0x2e, 0x54, 0x09, 0x7a, 0xa4, 0x3c, 0x49, 0x4b, 0xd3, 0x80, 0x5b, + 0x63, 0x27, 0x08, 0x84, 0x78, 0x36, 0xf0, 0xdc, 0xd0, 0xf7, 0x46, 0xd2, 0x5f, 0xd0, 0x9c, 0x06, + 0x7c, 0x9f, 0x4a, 0xb6, 0xa8, 0x80, 0x7d, 0x3b, 0x1e, 0xd2, 0xc4, 0x76, 0xfc, 0xa0, 0x05, 0x38, + 0x24, 0x35, 0x53, 0x94, 0xb6, 0x6d, 0xc7, 0x8f, 0xc6, 0x22, 0x1e, 0x82, 0x99, 0x0c, 0x9a, 0xca, + 0x6c, 0x06, 0xcd, 0x8f, 0xd2, 0x33, 0x68, 0x6a, 0xd8, 0xf4, 0x63, 0xd9, 0xf4, 0xfc, 0x2b, 0xfe, + 0x52, 0x89, 0x34, 0xf3, 0x89, 0x41, 0xf5, 0x2f, 0x93, 0x18, 0xb4, 0x98, 0x96, 0x18, 0xf4, 0x1e, + 0x54, 0x30, 0x65, 0xc3, 0x3a, 0x77, 0x84, 0x0c, 0x47, 0xfe, 0x8f, 0x86, 0x9e, 0xd3, 0xb1, 0xeb, + 0xb8, 0xa1, 0x09, 0xbe, 0xfa, 0x19, 0xcc, 0xe7, 0xe8, 0x34, 0x7f, 0x81, 0x39, 0x3a, 0x32, 0xb5, + 0x64, 0x03, 0x4a, 0xea, 0x3d, 0x31, 0x06, 0xf9, 0x53, 0xdf, 0x1b, 0x2b, 0xbb, 0xb0, 0xf8, 0xcd, + 0xea, 0x90, 0x0d, 0x3d, 0x59, 0x39, 0x1b, 0x7a, 0xc6, 0xaf, 0x43, 0x45, 0x23, 0x35, 0xf6, 0x06, + 0x59, 0xa0, 0x84, 0x26, 0x25, 0x65, 0x4b, 0x5a, 0xc5, 0xb2, 0x84, 0x76, 0x87, 0x82, 0xdf, 0x0c, + 0x1d, 0x9f, 0x63, 0x36, 0x9d, 0xe5, 0xf3, 0x0b, 0xee, 0x07, 0xca, 0x4e, 0xdf, 0x88, 0x0a, 0x4c, + 0x82, 0x1b, 0x7f, 0x0b, 0x96, 0x12, 0xef, 0x56, 0xb2, 0x88, 0xb7, 0x60, 0x01, 0xd7, 0x4d, 0xf9, + 0x51, 0x93, 0xb9, 0x32, 0xb2, 0x0c, 0xd3, 0xa4, 0xc9, 0xc5, 0x60, 0x4d, 0x7c, 0xef, 0x04, 0x3b, + 0xc9, 0x98, 0x15, 0x09, 0x3b, 0xf2, 0xbd, 0x13, 0xe3, 0xcf, 0x73, 0x90, 0xdb, 0xf5, 0x26, 0x7a, + 0xe8, 0x50, 0x66, 0x2e, 0x74, 0x48, 0xaa, 0x87, 0x56, 0xa4, 0xfe, 0x49, 0x99, 0x1d, 0x8d, 0xeb, + 0x4a, 0x05, 0x7c, 0x00, 0x75, 0xc1, 0x27, 0x42, 0x4f, 0xe8, 0xd7, 0x97, 0xb6, 0x4f, 0x02, 0x71, + 0x8e, 0x36, 0x9f, 0x3d, 0x0e, 0xfb, 0xde, 0x0e, 0xc1, 0xd9, 0x32, 0xe4, 0x22, 0xf5, 0x05, 0x8b, + 0xc5, 0x23, 0x5b, 0x85, 0x05, 0x8c, 0x21, 0xbd, 0x96, 0x8e, 0x42, 0xf9, 0xc4, 0xbe, 0x09, 0x4b, + 0xc9, 0x76, 0x89, 0x15, 0x49, 0xd9, 0x48, 0x6f, 0x18, 0x79, 0xd2, 0x6d, 0x10, 0x7c, 0x84, 0x70, + 0x64, 0xbc, 0xc1, 0x29, 0xe7, 0x58, 0xa4, 0x31, 0xbd, 0x52, 0x82, 0xe9, 0xdd, 0x83, 0x4a, 0x38, + 0xba, 0xb0, 0x26, 0xf6, 0xf5, 0xc8, 0xb3, 0x87, 0x72, 0x7f, 0x43, 0x38, 0xba, 0x38, 0x22, 0x08, + 0x7b, 0x04, 0x30, 0x9e, 0x4c, 0xe4, 0xde, 0x43, 0x5b, 0x75, 0x4c, 0xca, 0xfb, 0x47, 0x47, 0x44, + 0x72, 0x66, 0x79, 0x3c, 0x99, 0xd0, 0x4f, 0xb6, 0x0d, 0xf5, 0xd4, 0x8c, 0xb7, 0xbb, 0x2a, 0xe4, + 0xd1, 0x9b, 0x6c, 0xa4, 0x6c, 0xce, 0xda, 0x40, 0x87, 0xad, 0x7f, 0x1f, 0xd8, 0xcf, 0x99, 0x77, + 0xd6, 0x87, 0x72, 0x34, 0x3e, 0x3d, 0x6d, 0x0b, 0x83, 0x98, 0x2b, 0x89, 0xb4, 0xad, 0xf6, 0x70, + 0xe8, 0x0b, 0xbe, 0x48, 0x07, 0x66, 0xc4, 0xf2, 0x41, 0x3b, 0x31, 0xdb, 0xc4, 0xf7, 0x8d, 0xbf, + 0xcc, 0x40, 0x81, 0x72, 0xc8, 0xde, 0x86, 0x45, 0xc2, 0x8f, 0xc2, 0xb0, 0xa4, 0x7b, 0x91, 0xce, + 0xdd, 0xbe, 0x8c, 0xc0, 0x12, 0xdb, 0x42, 0xcb, 0x7f, 0xcd, 0x46, 0x6f, 0x5e, 0xcb, 0x81, 0xbd, + 0x07, 0xe5, 0xa8, 0x6b, 0x8d, 0x74, 0x4a, 0xaa, 0x67, 0xf6, 0x3a, 0xe4, 0xcf, 0xbd, 0x89, 0xb2, + 0xd3, 0x40, 0xbc, 0x92, 0x26, 0xc2, 0xe3, 0xb1, 0x88, 0x3e, 0x68, 0xf0, 0xd2, 0xbe, 0x10, 0x75, + 0x82, 0x64, 0x30, 0x3f, 0xc7, 0x85, 0x94, 0x39, 0x1e, 0xc3, 0xa2, 0xe0, 0x03, 0x9a, 0x9b, 0xff, + 0xe6, 0x43, 0xf3, 0xeb, 0x42, 0xc2, 0x1b, 0x8c, 0xa6, 0x43, 0xae, 0x5b, 0xc9, 0x30, 0x26, 0x48, 0xc2, 0x95, 0x64, 0x6d, 0xfc, 0x41, 0x86, 0xf8, 0x8b, 0x68, 0x97, 0x3d, 0x80, 0xbc, 0x38, 0xdf, - 0x66, 0xcc, 0xa3, 0x51, 0x98, 0xb6, 0xc0, 0x33, 0x11, 0x03, 0xb3, 0xb1, 0xa7, 0xe3, 0x64, 0xeb, - 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0x05, 0xe7, 0x6b, 0x6a, 0x5a, 0x33, 0xd6, 0x0f, 0x9a, 0x7d, - 0xb4, 0x4d, 0x37, 0xb4, 0xa8, 0x9d, 0x7c, 0xe2, 0xc4, 0x54, 0x52, 0xe0, 0xf0, 0x8c, 0x6b, 0xd1, - 0x3a, 0x7f, 0x94, 0x85, 0x5a, 0x62, 0x44, 0x18, 0xb6, 0x24, 0x0e, 0x00, 0xb2, 0xcd, 0xcb, 0xf7, - 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9d, 0xb2, 0x89, 0x75, 0x8a, 0x22, 0x05, 0x72, 0x7a, 0xa4, - 0xc0, 0x63, 0x28, 0xc7, 0x09, 0xc5, 0xc9, 0x21, 0x89, 0xfe, 0x54, 0xb0, 0x7a, 0x8c, 0x14, 0xc7, - 0x16, 0x14, 0xf4, 0xd8, 0x82, 0xef, 0x69, 0xae, 0xe8, 0x05, 0x6c, 0xc6, 0x48, 0x5b, 0xd1, 0x5f, - 0x8a, 0x23, 0xda, 0xf8, 0x08, 0x2a, 0xda, 0xe0, 0x75, 0x97, 0x73, 0x26, 0xe1, 0x72, 0x8e, 0xd2, - 0x4a, 0xb2, 0x71, 0x5a, 0x89, 0xf1, 0xdb, 0x59, 0xa8, 0x89, 0xfd, 0xe5, 0xb8, 0x67, 0x47, 0xde, - 0xc8, 0x19, 0xa0, 0xad, 0x3e, 0xda, 0x61, 0x52, 0xd0, 0x52, 0xfb, 0x4c, 0x6e, 0x31, 0x92, 0xb3, - 0xf4, 0xec, 0x39, 0x62, 0xd2, 0x51, 0xf6, 0x9c, 0x01, 0x35, 0xc1, 0x18, 0x4f, 0xec, 0x80, 0x6b, - 0xe9, 0xce, 0x66, 0xe5, 0x94, 0xf3, 0x4d, 0x3b, 0x20, 0x0e, 0xf9, 0x4d, 0x58, 0x12, 0x38, 0x98, - 0x38, 0x34, 0x76, 0x46, 0x23, 0x87, 0x30, 0xc9, 0x82, 0xd3, 0x3c, 0xe5, 0xdc, 0xb4, 0x43, 0xbe, - 0x2f, 0x0a, 0x64, 0x76, 0x74, 0x69, 0xe8, 0x04, 0xf6, 0x49, 0x1c, 0x5c, 0x16, 0x3d, 0xa3, 0x87, - 0xcd, 0xbe, 0xd2, 0x3c, 0x6c, 0x94, 0x41, 0x58, 0x19, 0xdb, 0x57, 0x91, 0x87, 0x6d, 0x86, 0x92, - 0x8a, 0xb3, 0x94, 0x64, 0xfc, 0xa7, 0x2c, 0x54, 0x34, 0xb2, 0x7c, 0x95, 0xd3, 0xf5, 0xee, 0x9c, - 0x6f, 0xa5, 0xac, 0xbb, 0x51, 0xde, 0x4c, 0x76, 0x89, 0x8e, 0x78, 0xca, 0xc3, 0xd6, 0x08, 0xf8, - 0x0e, 0x94, 0xc5, 0xae, 0x7b, 0x0f, 0x2d, 0x91, 0xf2, 0x16, 0x01, 0x04, 0x1c, 0x4d, 0x4f, 0x54, - 0xe1, 0x13, 0x2c, 0x2c, 0xc4, 0x85, 0x4f, 0x44, 0xe1, 0x8b, 0x22, 0x4a, 0xbf, 0x03, 0x55, 0xd9, + 0x66, 0xac, 0xb8, 0x51, 0x34, 0xb9, 0xc0, 0x33, 0x11, 0x03, 0x93, 0xc6, 0xa7, 0xe3, 0x64, 0xeb, + 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0xa1, 0xe9, 0x6b, 0x6a, 0x5a, 0x33, 0x46, 0x1a, 0x9a, 0x7d, + 0xb4, 0x4d, 0x37, 0xb4, 0xe0, 0xa2, 0x7c, 0xe2, 0xc4, 0x54, 0x52, 0xe0, 0xf0, 0x8c, 0x6b, 0x41, + 0x45, 0x7f, 0x94, 0x85, 0x5a, 0x62, 0x44, 0x18, 0x5d, 0x25, 0x0e, 0x00, 0x72, 0x21, 0xc8, 0xf7, + 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9d, 0xb2, 0x89, 0x75, 0x8a, 0x02, 0x1a, 0x72, 0x7a, 0x40, + 0xc3, 0x63, 0x28, 0xc7, 0x79, 0xcf, 0xc9, 0x21, 0x89, 0xfe, 0x54, 0x4c, 0x7d, 0x8c, 0x14, 0x87, + 0x40, 0x14, 0xf4, 0x10, 0x88, 0xef, 0x69, 0x1e, 0xf3, 0x05, 0x6c, 0xc6, 0x48, 0x5b, 0xd1, 0x5f, + 0x88, 0xbf, 0xdc, 0xf8, 0x08, 0x2a, 0xda, 0xe0, 0x75, 0xcf, 0x78, 0x26, 0xe1, 0x19, 0x8f, 0xb2, + 0x5f, 0xb2, 0x71, 0xf6, 0x8b, 0xf1, 0x9b, 0x59, 0xa8, 0x89, 0xfd, 0xe5, 0xb8, 0x67, 0x47, 0xde, + 0xc8, 0x19, 0xa0, 0x4b, 0x21, 0xda, 0x61, 0x52, 0xd0, 0x52, 0xfb, 0x4c, 0x6e, 0x31, 0x92, 0xb3, + 0xf4, 0x24, 0x3f, 0x62, 0xd2, 0x51, 0x92, 0x9f, 0x01, 0x35, 0xc1, 0x18, 0x4f, 0xec, 0x80, 0x6b, + 0x59, 0xd9, 0x66, 0xe5, 0x94, 0xf3, 0x4d, 0x3b, 0x20, 0x0e, 0xf9, 0x4d, 0x58, 0x12, 0x38, 0x98, + 0xdf, 0x34, 0x76, 0x46, 0x23, 0x87, 0x30, 0xc9, 0xd0, 0xd4, 0x38, 0xe5, 0xdc, 0xb4, 0x43, 0xbe, + 0x2f, 0x0a, 0x64, 0x12, 0x77, 0x69, 0xe8, 0x04, 0xf6, 0x49, 0x1c, 0x03, 0x17, 0x3d, 0xa3, 0x23, + 0xd0, 0xbe, 0xd2, 0x1c, 0x81, 0x64, 0x80, 0xa8, 0x8c, 0xed, 0xab, 0xc8, 0x11, 0x38, 0x43, 0x49, + 0xc5, 0x59, 0x4a, 0x32, 0xfe, 0x73, 0x16, 0x2a, 0x1a, 0x59, 0xbe, 0xca, 0xe9, 0x7a, 0x77, 0xce, + 0x05, 0x54, 0xd6, 0xbd, 0x3d, 0x6f, 0x26, 0xbb, 0xc4, 0x78, 0x01, 0x4a, 0x17, 0xd7, 0x08, 0xf8, + 0x0e, 0x94, 0xc5, 0xae, 0x7b, 0x0f, 0x0d, 0xa6, 0xf2, 0xb2, 0x03, 0x04, 0x1c, 0x4d, 0x4f, 0x54, + 0xe1, 0x13, 0x2c, 0x2c, 0xc4, 0x85, 0x4f, 0x44, 0xe1, 0x8b, 0x02, 0x5f, 0xbf, 0x03, 0x55, 0xd9, 0x2a, 0xbe, 0x53, 0x9c, 0x6e, 0xbc, 0xeb, 0x13, 0xef, 0xdb, 0xac, 0x50, 0x77, 0xf4, 0xf2, 0x65, - 0xc5, 0x27, 0xaa, 0x62, 0xe9, 0x65, 0x15, 0x9f, 0xd0, 0x83, 0xb1, 0x13, 0x05, 0xe9, 0x62, 0x10, - 0x88, 0xe2, 0x63, 0x8f, 0x60, 0x49, 0xb1, 0xab, 0xa9, 0x6b, 0xbb, 0xae, 0x37, 0x75, 0x07, 0x5c, - 0xe5, 0x9b, 0x30, 0x59, 0x74, 0x1c, 0x97, 0x18, 0xc3, 0x28, 0x21, 0x91, 0x82, 0x49, 0x1e, 0x42, + 0xc5, 0x27, 0xaa, 0x62, 0xe9, 0x65, 0x15, 0x9f, 0xd0, 0x83, 0xb1, 0x13, 0xc5, 0x12, 0x63, 0xac, + 0x8a, 0xe2, 0x63, 0x8f, 0x60, 0x49, 0xb1, 0xab, 0xa9, 0x6b, 0xbb, 0xae, 0x37, 0x75, 0x07, 0x5c, + 0xa5, 0xc5, 0x30, 0x59, 0x74, 0x1c, 0x97, 0x18, 0xc3, 0x28, 0x6f, 0x92, 0x62, 0x5e, 0x1e, 0x42, 0x81, 0xe4, 0x72, 0x12, 0x3e, 0xd2, 0x19, 0x17, 0xa1, 0xb0, 0x07, 0x50, 0x20, 0xf1, 0x3c, 0x7b, - 0x23, 0xb3, 0x21, 0x04, 0x63, 0x03, 0x1a, 0x28, 0x62, 0x6a, 0x1c, 0xf7, 0x45, 0x52, 0x89, 0xb1, - 0x0c, 0xec, 0x80, 0x36, 0x91, 0x1e, 0xe4, 0xf4, 0xdf, 0x72, 0x50, 0xd1, 0xc0, 0x82, 0x2d, 0x62, - 0x58, 0x8c, 0x35, 0x74, 0xec, 0x31, 0x57, 0x0e, 0x9f, 0x9a, 0x59, 0x43, 0xe8, 0xb6, 0x04, 0x8a, - 0x43, 0xc1, 0xbe, 0x38, 0xb3, 0xbc, 0x69, 0x68, 0x0d, 0xf9, 0x99, 0xcf, 0xb9, 0x14, 0x96, 0xaa, - 0xf6, 0xc5, 0xd9, 0xe1, 0x34, 0xdc, 0x46, 0x98, 0xc0, 0x12, 0x44, 0xad, 0x61, 0xc9, 0x48, 0x8e, - 0xb1, 0x7d, 0x15, 0x63, 0xc9, 0x70, 0x22, 0x5a, 0xa2, 0x7c, 0x14, 0x4e, 0x44, 0x6a, 0xcb, 0x2c, - 0x27, 0x2f, 0xcc, 0x73, 0xf2, 0x6f, 0xc3, 0x2a, 0x71, 0x72, 0xc9, 0x23, 0xac, 0x19, 0x92, 0x5a, - 0xc6, 0x52, 0x39, 0x49, 0x4d, 0xfe, 0x6a, 0x8a, 0x19, 0xa8, 0xfd, 0x11, 0x38, 0x3f, 0xa6, 0x1d, - 0x95, 0x31, 0xc5, 0xcc, 0x64, 0xe3, 0x3d, 0xe7, 0xc7, 0x5c, 0x60, 0xa2, 0xbb, 0x5a, 0xc7, 0x94, - 0x81, 0xcb, 0x63, 0xc7, 0x9d, 0xc5, 0xb4, 0xaf, 0x92, 0x98, 0x65, 0x89, 0x69, 0x5f, 0xe9, 0x98, - 0xef, 0xc3, 0xda, 0x98, 0x0f, 0x1d, 0x3b, 0xd9, 0xac, 0x15, 0x4b, 0x10, 0xcb, 0x54, 0xac, 0xd5, - 0xe9, 0x91, 0x06, 0x29, 0x56, 0xe3, 0xc7, 0xde, 0xf8, 0xc4, 0xa1, 0xc3, 0x93, 0x1c, 0xe8, 0x79, - 0xb3, 0xee, 0x4e, 0xc7, 0x3f, 0x44, 0xb0, 0xa8, 0x12, 0x18, 0x35, 0xa8, 0xf4, 0x42, 0x6f, 0xa2, - 0x5e, 0x73, 0x1d, 0xaa, 0xf4, 0x28, 0xb3, 0x89, 0xee, 0xc0, 0x6d, 0xa4, 0xcd, 0xbe, 0x37, 0xf1, - 0x46, 0xde, 0xd9, 0x75, 0xc2, 0xa0, 0xf4, 0x5f, 0x32, 0xb0, 0x94, 0x28, 0x95, 0xfb, 0xfc, 0xdb, - 0xb4, 0xb1, 0xa2, 0x94, 0x10, 0x22, 0xe7, 0x45, 0xed, 0xf0, 0x21, 0x44, 0xda, 0x55, 0x2a, 0x4d, - 0xa4, 0x1d, 0xa7, 0x32, 0xab, 0x8a, 0x44, 0xdb, 0xad, 0x79, 0xda, 0x96, 0xf5, 0x55, 0x92, 0xb3, - 0x6a, 0xe2, 0x57, 0x65, 0x70, 0xf9, 0x50, 0x4e, 0x39, 0x97, 0x0c, 0x9f, 0xd5, 0x8d, 0x4f, 0x6a, - 0x04, 0xb1, 0x45, 0x2a, 0x30, 0xfe, 0x65, 0x06, 0x20, 0x1e, 0x1d, 0x06, 0xf0, 0x46, 0x07, 0x28, - 0xdd, 0x12, 0xa4, 0x1d, 0x96, 0x6f, 0x40, 0x35, 0x8a, 0xe3, 0x8b, 0x8f, 0xe4, 0x8a, 0x82, 0x89, - 0x73, 0xf9, 0x1d, 0x68, 0x9c, 0x8d, 0xbc, 0x13, 0x14, 0x9d, 0xe4, 0x01, 0x4a, 0x39, 0x55, 0x75, - 0x02, 0xab, 0x63, 0x31, 0x3e, 0xc0, 0xf3, 0xa9, 0xa1, 0x7e, 0xfa, 0x71, 0x6c, 0xfc, 0x4e, 0x36, - 0x0a, 0x68, 0x8a, 0x57, 0xe2, 0xc5, 0x7a, 0xc6, 0xcf, 0xe3, 0x17, 0x7f, 0x91, 0xbb, 0xe7, 0x23, - 0xa8, 0xfb, 0xc4, 0x1d, 0x15, 0xeb, 0xcc, 0xbf, 0x80, 0x75, 0xd6, 0xfc, 0xc4, 0x91, 0xfb, 0x75, - 0x68, 0xda, 0xc3, 0x0b, 0xee, 0x87, 0x0e, 0x9a, 0x8d, 0x51, 0x50, 0x93, 0x21, 0x44, 0x1a, 0x1c, - 0x25, 0xa2, 0x77, 0xa0, 0x21, 0x33, 0xdc, 0x22, 0x4c, 0x79, 0x67, 0x46, 0x0c, 0x16, 0x88, 0xc6, - 0xbf, 0x51, 0x11, 0x54, 0xc9, 0xb7, 0xfb, 0xe2, 0x55, 0xd1, 0x67, 0x98, 0x9d, 0x77, 0x68, 0x49, - 0x42, 0x92, 0xd6, 0x68, 0xc9, 0x8f, 0x08, 0x28, 0x6d, 0xd1, 0xc9, 0x65, 0xcd, 0xbf, 0xca, 0xb2, - 0x1a, 0x7f, 0x92, 0x81, 0xe2, 0xae, 0x37, 0x11, 0x7a, 0xb9, 0x90, 0xe7, 0x70, 0x9b, 0x44, 0x6e, - 0x88, 0x05, 0xf1, 0xd8, 0x1d, 0xbe, 0x38, 0x91, 0x23, 0x55, 0xde, 0xa8, 0x25, 0xe5, 0x8d, 0xef, - 0xc1, 0x1d, 0x74, 0xf2, 0xf8, 0xde, 0xc4, 0xf3, 0xc5, 0x56, 0xb5, 0x47, 0x24, 0x77, 0x78, 0x6e, - 0x78, 0xae, 0x78, 0xe7, 0xed, 0x53, 0xce, 0x8f, 0x34, 0x8c, 0xfd, 0x08, 0x01, 0x53, 0xa5, 0x46, - 0xe1, 0x85, 0x45, 0xaa, 0xa2, 0x14, 0x8c, 0x88, 0xa3, 0x36, 0x44, 0x41, 0x07, 0xe1, 0x28, 0x1a, - 0x19, 0xdf, 0x85, 0x72, 0x64, 0x75, 0x60, 0xef, 0x42, 0xf9, 0xdc, 0x9b, 0x48, 0xd3, 0x44, 0x26, - 0x91, 0xec, 0x22, 0x67, 0x6d, 0x96, 0xce, 0xe9, 0x47, 0x60, 0xfc, 0x79, 0x11, 0x8a, 0x5d, 0xf7, - 0xc2, 0x73, 0x06, 0x18, 0x83, 0x35, 0xe6, 0x63, 0x4f, 0xa5, 0xd9, 0x8a, 0xdf, 0x18, 0x67, 0x11, - 0xdf, 0x7c, 0x91, 0x93, 0x71, 0x16, 0xd1, 0x9d, 0x17, 0x2b, 0xb0, 0xe0, 0xeb, 0x57, 0x57, 0x14, - 0x7c, 0x8c, 0x0a, 0x8d, 0x94, 0xb6, 0x82, 0x96, 0xa6, 0x2c, 0xda, 0xa2, 0x2b, 0x15, 0x70, 0xc9, - 0x28, 0xed, 0xa9, 0x8c, 0x10, 0x5c, 0xb0, 0xd7, 0xa0, 0x28, 0x73, 0x4b, 0x28, 0x52, 0x9f, 0xc2, - 0x38, 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0xe4, 0xa4, 0x8b, 0x24, 0x2a, 0xa1, 0xa7, 0x4b, 0xe0, 0xb6, - 0xa0, 0xb5, 0x7b, 0x50, 0x21, 0x7c, 0x42, 0x29, 0xc9, 0xa8, 0x29, 0x04, 0x21, 0x42, 0xca, 0x0d, - 0x30, 0xe5, 0xd4, 0x1b, 0x60, 0x30, 0xc8, 0x2e, 0xe2, 0xb2, 0x34, 0x45, 0xa0, 0x7b, 0x3f, 0x34, - 0xb8, 0xba, 0xfe, 0x48, 0x2a, 0xf7, 0x94, 0x05, 0xa8, 0x94, 0xfb, 0x37, 0xa1, 0x76, 0x6a, 0x8f, - 0x46, 0x27, 0xf6, 0xe0, 0x39, 0xe9, 0xa4, 0x55, 0x32, 0xc3, 0x29, 0x20, 0x2a, 0xa5, 0xf7, 0xa0, - 0xa2, 0xbd, 0x65, 0x0c, 0x89, 0xca, 0x9b, 0x10, 0xbf, 0xdf, 0x59, 0x53, 0x53, 0xfd, 0x15, 0x4c, - 0x4d, 0x5a, 0x68, 0x58, 0x23, 0x19, 0x1a, 0x76, 0x07, 0xb9, 0xa9, 0x0c, 0x1f, 0x6a, 0xd2, 0x25, - 0x13, 0xf6, 0x70, 0x88, 0xe1, 0x43, 0x74, 0xa3, 0x1b, 0x2e, 0x1e, 0x95, 0x2f, 0x92, 0x50, 0x4b, - 0x30, 0x42, 0xb9, 0x4b, 0xf6, 0xd2, 0x89, 0xed, 0x0c, 0x31, 0x14, 0x97, 0xd4, 0xd8, 0xa2, 0x3d, - 0x0e, 0x8f, 0x6c, 0x67, 0xc8, 0xee, 0x43, 0x55, 0x15, 0xe3, 0xe9, 0xb8, 0x44, 0xeb, 0x2f, 0x8b, - 0xc5, 0x99, 0x68, 0x40, 0x2d, 0xc2, 0x18, 0xc7, 0xa9, 0x7c, 0x15, 0x89, 0x82, 0x74, 0xf0, 0x1e, - 0x46, 0x5c, 0x84, 0x1c, 0x13, 0xf6, 0xea, 0x4f, 0xee, 0xc8, 0xb9, 0x4a, 0x2a, 0x55, 0xff, 0xc9, - 0x4b, 0x43, 0x98, 0x42, 0x10, 0x23, 0x67, 0xd1, 0x6a, 0x42, 0x10, 0x93, 0xa8, 0xe8, 0x2c, 0x22, - 0x04, 0xf6, 0x5d, 0x4d, 0x91, 0x6a, 0x21, 0xf2, 0x6b, 0x33, 0xed, 0xdf, 0x94, 0x89, 0x70, 0x17, - 0xc0, 0x09, 0xc4, 0x29, 0x13, 0x70, 0x77, 0x88, 0xb9, 0x77, 0x25, 0xb3, 0xec, 0x04, 0xcf, 0x08, - 0xf0, 0xd5, 0x6a, 0x58, 0x6d, 0xa8, 0xea, 0xd3, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0x75, 0x0e, 0x9a, - 0xb7, 0x58, 0x05, 0x8a, 0xbd, 0x4e, 0xbf, 0xbf, 0x87, 0x2e, 0xa7, 0x2a, 0x94, 0xa2, 0xc4, 0x9f, - 0xac, 0x78, 0x6a, 0x6f, 0x6d, 0x75, 0x8e, 0xfa, 0x9d, 0xed, 0x66, 0xee, 0x07, 0xf9, 0x52, 0xb6, - 0x99, 0x33, 0xfe, 0x22, 0x07, 0x15, 0x6d, 0x15, 0x5e, 0xcc, 0x8c, 0xef, 0x02, 0xa0, 0x4a, 0x13, - 0x47, 0x97, 0xe5, 0xcd, 0xb2, 0x80, 0xd0, 0xcb, 0xd7, 0x8d, 0xe5, 0x39, 0xba, 0xbd, 0x44, 0x19, - 0xcb, 0xdf, 0x84, 0x1a, 0x5d, 0x04, 0xa2, 0x3b, 0x0e, 0x0b, 0x66, 0x95, 0x80, 0x92, 0x55, 0x63, - 0xe6, 0x20, 0x22, 0x61, 0x4e, 0x89, 0xbc, 0x16, 0x80, 0x40, 0x98, 0x55, 0x82, 0x29, 0x41, 0x81, - 0x37, 0xba, 0xe0, 0x84, 0x41, 0x12, 0x61, 0x45, 0xc2, 0xfa, 0x32, 0x07, 0x52, 0xf2, 0x43, 0x2d, - 0x75, 0xad, 0x60, 0x56, 0x09, 0x28, 0x3b, 0xfa, 0xa6, 0x22, 0xa0, 0x12, 0x12, 0xd0, 0xda, 0x3c, - 0x35, 0x24, 0x88, 0x67, 0x6f, 0xce, 0x9e, 0x55, 0x46, 0xc2, 0xf8, 0xda, 0x7c, 0xbd, 0x97, 0xdb, - 0xb5, 0xd8, 0xbb, 0xc0, 0xc6, 0x93, 0x89, 0x95, 0x62, 0x69, 0xca, 0x9b, 0x8d, 0xf1, 0x64, 0xd2, - 0xd7, 0x0c, 0x31, 0x5f, 0x81, 0x11, 0xec, 0x73, 0x60, 0x6d, 0xb1, 0x81, 0x71, 0x88, 0x91, 0x09, - 0x35, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, 0x70, 0xbf, 0x6c, 0x2a, 0xf7, 0x7b, 0x11, 0x9f, 0x30, - 0x76, 0xa0, 0x72, 0xa4, 0x5d, 0x33, 0x74, 0x5f, 0x9c, 0x10, 0xea, 0x82, 0x21, 0x3a, 0x3b, 0xc8, - 0xb8, 0xe5, 0xcb, 0x7b, 0x85, 0xb4, 0xd1, 0x64, 0xb5, 0xd1, 0x18, 0xff, 0x22, 0x43, 0x57, 0x38, - 0x44, 0x83, 0x8f, 0x6f, 0x36, 0x52, 0x7e, 0xa0, 0x38, 0xc3, 0xb4, 0xa2, 0xfc, 0x3f, 0x32, 0x39, - 0x14, 0x87, 0x66, 0x79, 0xa7, 0xa7, 0x01, 0x57, 0xb9, 0x52, 0x15, 0x84, 0x1d, 0x22, 0x48, 0x09, - 0xdf, 0x42, 0xc2, 0x77, 0xa8, 0xfd, 0x40, 0xe6, 0x4c, 0x09, 0xe1, 0x7b, 0xdf, 0xbe, 0x92, 0xbd, - 0x06, 0x42, 0x04, 0x91, 0x86, 0x6a, 0x95, 0x21, 0x16, 0x3d, 0x1b, 0xff, 0x54, 0x26, 0xc1, 0xce, - 0xae, 0xef, 0x43, 0x28, 0x45, 0xad, 0x26, 0x4f, 0x58, 0x85, 0x19, 0x95, 0x8b, 0x73, 0x1c, 0xb5, - 0xf2, 0xc4, 0x88, 0x69, 0x73, 0xa1, 0xb3, 0xa1, 0xab, 0x8d, 0xfa, 0x1b, 0xc0, 0x4e, 0x1d, 0x7f, - 0x16, 0x99, 0x36, 0x5b, 0x13, 0x4b, 0x34, 0x6c, 0xe3, 0x18, 0x96, 0x14, 0x97, 0xd0, 0x34, 0x82, - 0xe4, 0xcb, 0xcb, 0xbc, 0x84, 0xc9, 0x67, 0xe7, 0x98, 0xbc, 0xf1, 0xd3, 0x3c, 0x14, 0xd5, 0x95, - 0x5d, 0x69, 0xd7, 0x4c, 0x95, 0x93, 0xd7, 0x4c, 0xb5, 0x12, 0x57, 0x92, 0xe0, 0xab, 0x97, 0xe7, - 0xfd, 0x3b, 0xb3, 0x47, 0xb6, 0x66, 0x34, 0x4f, 0x1c, 0xdb, 0xab, 0x90, 0x9f, 0xd8, 0xe1, 0x39, - 0x1a, 0xc8, 0x88, 0x78, 0xf0, 0x59, 0x19, 0xd3, 0x0b, 0x49, 0x63, 0x7a, 0xda, 0x95, 0x5c, 0x24, - 0x92, 0xce, 0x5d, 0xc9, 0x75, 0x07, 0x48, 0xbe, 0xd0, 0x82, 0x90, 0x4a, 0x08, 0x10, 0x67, 0x51, - 0x52, 0x1c, 0x29, 0xcd, 0x8a, 0x23, 0xaf, 0x2c, 0x2a, 0x7c, 0x1b, 0x16, 0x28, 0x9d, 0x5d, 0x66, - 0xc2, 0xa9, 0x03, 0x45, 0xae, 0xa1, 0xfa, 0x4f, 0xa1, 0xc9, 0xa6, 0xc4, 0xd5, 0xef, 0xb7, 0xa9, - 0x24, 0xee, 0xb7, 0xd1, 0x8d, 0xfc, 0xd5, 0xa4, 0x91, 0xff, 0x01, 0x34, 0xa3, 0x05, 0x45, 0x93, - 0x99, 0x1b, 0xc8, 0x3c, 0x9b, 0xba, 0x82, 0x0b, 0x2e, 0x79, 0x10, 0xc4, 0x07, 0x62, 0x3d, 0x71, - 0x20, 0x0a, 0x1e, 0xd6, 0x0e, 0x43, 0x3e, 0x9e, 0x84, 0xf2, 0x40, 0xc4, 0x48, 0x7c, 0x7d, 0x80, - 0xc9, 0x1c, 0xd1, 0x1a, 0x94, 0xbb, 0x07, 0xd6, 0xce, 0x5e, 0xf7, 0xe9, 0x6e, 0xbf, 0x99, 0x11, - 0x8f, 0xbd, 0xe3, 0xad, 0xad, 0x4e, 0x67, 0x1b, 0x4f, 0x1c, 0x80, 0x85, 0x9d, 0x76, 0x57, 0x9c, - 0x3e, 0x39, 0xe3, 0xf7, 0xb2, 0x50, 0xd1, 0x9a, 0x67, 0xef, 0x47, 0xab, 0x42, 0x57, 0xa0, 0xdc, - 0x9d, 0x1f, 0xc2, 0x86, 0x62, 0xc5, 0xda, 0xb2, 0x44, 0x17, 0x90, 0x65, 0x6f, 0xbc, 0x80, 0x8c, - 0xbd, 0x0d, 0x0d, 0x9b, 0x5a, 0x88, 0x56, 0x41, 0x9a, 0x83, 0x25, 0x58, 0x2e, 0x02, 0x86, 0xde, - 0xc5, 0xe7, 0x89, 0xc0, 0xcb, 0xab, 0x68, 0xb7, 0xe8, 0x48, 0xc1, 0xc5, 0x2a, 0x9e, 0xda, 0xce, - 0x68, 0xea, 0x73, 0xe9, 0xbe, 0x8d, 0x4e, 0x66, 0x82, 0x9a, 0xaa, 0xd8, 0xf8, 0x00, 0x20, 0x1e, - 0x73, 0x72, 0x71, 0x6e, 0x25, 0x17, 0x27, 0xa3, 0x2d, 0x4e, 0xd6, 0xd8, 0x26, 0x36, 0x22, 0x17, - 0x3a, 0xf2, 0x54, 0x7f, 0x13, 0x94, 0x45, 0xca, 0xc2, 0xe0, 0xd7, 0xc9, 0x88, 0x87, 0x2a, 0x9b, - 0x76, 0x51, 0x96, 0x74, 0xa3, 0x02, 0x95, 0xdc, 0x1e, 0xb7, 0x12, 0x73, 0x23, 0x49, 0x92, 0xb3, - 0xdc, 0x48, 0xa2, 0x9a, 0x51, 0xb9, 0xb1, 0x0e, 0xad, 0x6d, 0x2e, 0x5a, 0x6b, 0x8f, 0x46, 0x33, - 0xc3, 0x31, 0xee, 0xc0, 0xed, 0x94, 0x32, 0x69, 0x84, 0xf8, 0x18, 0x56, 0xda, 0x94, 0x38, 0xfb, - 0x55, 0x65, 0xc8, 0x18, 0x2d, 0x58, 0x9d, 0x6d, 0x52, 0x76, 0xb6, 0x03, 0x8b, 0xdb, 0xfc, 0x64, - 0x7a, 0xb6, 0xc7, 0x2f, 0xe2, 0x8e, 0x18, 0xe4, 0x83, 0x73, 0xef, 0x52, 0xae, 0x0f, 0xfe, 0xc6, - 0x40, 0x32, 0x81, 0x63, 0x05, 0x13, 0x3e, 0x50, 0x16, 0x51, 0x84, 0xf4, 0x26, 0x7c, 0x60, 0xbc, - 0x0f, 0x4c, 0x6f, 0x47, 0xae, 0x97, 0xd0, 0x12, 0xa6, 0x27, 0x56, 0x70, 0x1d, 0x84, 0x7c, 0xac, - 0x6e, 0xd8, 0x81, 0x60, 0x7a, 0xd2, 0x23, 0x88, 0xf1, 0x0e, 0x54, 0x8f, 0xec, 0x6b, 0x93, 0x7f, - 0x2e, 0x73, 0x3f, 0xd6, 0xa0, 0x38, 0xb1, 0xaf, 0x05, 0x1b, 0x88, 0x9c, 0x23, 0x58, 0x6c, 0xfc, - 0x61, 0x1e, 0x16, 0x08, 0x93, 0xdd, 0xa7, 0x4b, 0x30, 0x1d, 0x17, 0xb7, 0xa1, 0x62, 0x94, 0x1a, - 0x68, 0x8e, 0x97, 0x66, 0xe7, 0x79, 0xa9, 0x34, 0xa0, 0xa9, 0xcb, 0x3f, 0x94, 0x19, 0xdb, 0x9d, - 0x8e, 0xd5, 0x8d, 0x1f, 0xc9, 0xec, 0xd1, 0x7c, 0x7c, 0xc9, 0x29, 0xa5, 0xd6, 0x25, 0x1d, 0x8d, - 0xb1, 0x2e, 0x42, 0xa3, 0x53, 0x47, 0x84, 0x64, 0x97, 0x3a, 0x28, 0x55, 0xe1, 0x29, 0xaa, 0xac, - 0xa2, 0xa4, 0xc2, 0x33, 0xa7, 0xd8, 0x94, 0x5e, 0xae, 0xd8, 0x90, 0x65, 0xed, 0x05, 0x8a, 0x0d, - 0xbc, 0x82, 0x62, 0xf3, 0x0a, 0x4e, 0xbe, 0xdb, 0x50, 0xc2, 0x73, 0x5f, 0xe3, 0x9e, 0xe2, 0xbc, - 0x17, 0xdc, 0xf3, 0x3b, 0x9a, 0xe8, 0x4f, 0x11, 0x06, 0x77, 0xe2, 0x6d, 0x62, 0xf2, 0xcf, 0x7f, - 0x39, 0xce, 0x93, 0xcf, 0xa0, 0x28, 0xa1, 0x82, 0xa0, 0x5d, 0x7b, 0xac, 0xee, 0x4f, 0xc2, 0xdf, - 0x62, 0xd9, 0xf0, 0xd2, 0x97, 0xcf, 0xa7, 0x8e, 0xcf, 0x87, 0xea, 0x62, 0x0c, 0x07, 0xf7, 0xa8, - 0x80, 0x88, 0x09, 0x0a, 0x35, 0xc4, 0xf5, 0x2e, 0x5d, 0x99, 0x16, 0x5f, 0x74, 0x82, 0x67, 0xe2, - 0xd1, 0x60, 0xd0, 0xc4, 0x1b, 0xd4, 0x26, 0x9e, 0xaf, 0x0e, 0x27, 0xe3, 0xa7, 0x19, 0x68, 0xca, - 0xdd, 0x15, 0x95, 0xe9, 0x5a, 0x40, 0xe1, 0x26, 0x87, 0xf8, 0x8b, 0xaf, 0xb9, 0x30, 0xa0, 0x86, - 0xc6, 0x8f, 0xe8, 0xa4, 0x22, 0xe3, 0x4d, 0x45, 0x00, 0x77, 0xe4, 0x69, 0xf5, 0x3a, 0x54, 0x54, - 0x94, 0xeb, 0xd8, 0x19, 0xa9, 0xfb, 0x8c, 0x29, 0xcc, 0x75, 0xdf, 0x19, 0xa9, 0x83, 0xce, 0xb7, - 0x65, 0x96, 0x5b, 0x06, 0x0f, 0x3a, 0xd3, 0x0e, 0xb9, 0xf1, 0xef, 0x33, 0xb0, 0xa8, 0x4d, 0x45, - 0xee, 0xdb, 0x0f, 0xa1, 0x1a, 0x5d, 0x5d, 0xc8, 0x23, 0xc9, 0x6b, 0x2d, 0xc9, 0x68, 0xe2, 0x6a, - 0x95, 0x41, 0x04, 0x09, 0xc4, 0x60, 0x86, 0xf6, 0x35, 0x8e, 0x37, 0x98, 0x8e, 0x95, 0x72, 0x33, + 0x23, 0xb3, 0x21, 0x04, 0x63, 0x03, 0x16, 0x51, 0xc4, 0xd4, 0x38, 0xee, 0x8b, 0xa4, 0x12, 0x63, + 0x19, 0xd8, 0x01, 0x6d, 0x22, 0x3d, 0x16, 0xeb, 0xbf, 0xe7, 0xa0, 0xa2, 0x81, 0x05, 0x5b, 0xc4, + 0xe8, 0x1d, 0x6b, 0xe8, 0xd8, 0x63, 0xae, 0xfc, 0x52, 0x35, 0xb3, 0x86, 0xd0, 0x6d, 0x09, 0x14, + 0x87, 0x82, 0x7d, 0x71, 0x66, 0x79, 0xd3, 0xd0, 0x1a, 0xf2, 0x33, 0x9f, 0x73, 0x29, 0x2c, 0x55, + 0xed, 0x8b, 0xb3, 0xc3, 0x69, 0xb8, 0x8d, 0x30, 0x81, 0x25, 0x88, 0x5a, 0xc3, 0x92, 0x01, 0x27, + 0x63, 0xfb, 0x2a, 0xc6, 0x92, 0x51, 0x4f, 0xb4, 0x44, 0xf9, 0x28, 0xea, 0x89, 0xd4, 0x96, 0x59, + 0x4e, 0x5e, 0x98, 0xe7, 0xe4, 0xdf, 0x86, 0x55, 0xe2, 0xe4, 0x92, 0x47, 0x58, 0x33, 0x24, 0xb5, + 0x8c, 0xa5, 0x72, 0x92, 0x9a, 0xfc, 0xd5, 0x10, 0x33, 0x50, 0xfb, 0x23, 0x70, 0x7e, 0x4c, 0x3b, + 0x2a, 0x63, 0x8a, 0x99, 0xc9, 0xc6, 0x7b, 0xce, 0x8f, 0xb9, 0xc0, 0x44, 0xaf, 0xba, 0x8e, 0x29, + 0xe3, 0xab, 0xc7, 0x8e, 0x3b, 0x8b, 0x69, 0x5f, 0x25, 0x31, 0xcb, 0x12, 0xd3, 0xbe, 0xd2, 0x31, + 0xdf, 0x87, 0xb5, 0x31, 0x1f, 0x3a, 0x76, 0xb2, 0x59, 0x2b, 0x96, 0x20, 0x96, 0xa9, 0x58, 0xab, + 0xd3, 0x23, 0x0d, 0x52, 0xac, 0xc6, 0x8f, 0xbd, 0xf1, 0x89, 0x43, 0x87, 0x27, 0xf9, 0xf9, 0xf3, + 0x66, 0xdd, 0x9d, 0x8e, 0x7f, 0x88, 0x60, 0x51, 0x25, 0x30, 0x6a, 0x50, 0xe9, 0x85, 0xde, 0x44, + 0xbd, 0xe6, 0x3a, 0x54, 0xe9, 0x51, 0x26, 0x3d, 0xdd, 0x81, 0xdb, 0x48, 0x9b, 0x7d, 0x6f, 0xe2, + 0x8d, 0xbc, 0xb3, 0xeb, 0x84, 0x41, 0xe9, 0xbf, 0x66, 0x60, 0x29, 0x51, 0x2a, 0xf7, 0xf9, 0xb7, + 0x69, 0x63, 0x45, 0x99, 0x2b, 0x44, 0xce, 0x4d, 0xed, 0xf0, 0x21, 0x44, 0xda, 0x55, 0x2a, 0x9b, + 0xa5, 0x1d, 0x67, 0x5c, 0xab, 0x8a, 0x44, 0xdb, 0xad, 0x79, 0xda, 0x96, 0xf5, 0x55, 0x2e, 0xb6, + 0x6a, 0xe2, 0x97, 0x65, 0x0c, 0xfc, 0x50, 0x4e, 0x39, 0x97, 0x8c, 0xf2, 0xd5, 0x8d, 0x4f, 0x6a, + 0x04, 0xb1, 0x45, 0x2a, 0x30, 0xfe, 0x4d, 0x06, 0x20, 0x1e, 0x1d, 0xc6, 0x19, 0x47, 0x07, 0x28, + 0x5d, 0x66, 0xa4, 0x1d, 0x96, 0x6f, 0x40, 0x35, 0x0a, 0x37, 0x8c, 0x8f, 0xe4, 0x8a, 0x82, 0x89, + 0x73, 0xf9, 0x1d, 0x58, 0x3c, 0x1b, 0x79, 0x27, 0x28, 0x3a, 0xc9, 0x03, 0x94, 0x52, 0xbf, 0xea, + 0x04, 0x56, 0xc7, 0x62, 0x7c, 0x80, 0xe7, 0x53, 0x23, 0x12, 0xf5, 0xe3, 0xd8, 0xf8, 0xad, 0x6c, + 0x14, 0x77, 0x15, 0xaf, 0xc4, 0x8b, 0xf5, 0x8c, 0x9f, 0xc5, 0x7d, 0xff, 0x22, 0xaf, 0xd4, 0x47, + 0x50, 0xf7, 0x89, 0x3b, 0x2a, 0xd6, 0x99, 0x7f, 0x01, 0xeb, 0xac, 0xf9, 0x89, 0x23, 0xf7, 0xeb, + 0xd0, 0xb0, 0x87, 0x17, 0xdc, 0x0f, 0x1d, 0x34, 0x1b, 0xa3, 0xa0, 0x26, 0x23, 0x9d, 0x34, 0x38, + 0x4a, 0x44, 0xef, 0xc0, 0xa2, 0x4c, 0xc4, 0x8b, 0x30, 0xe5, 0xd5, 0x1e, 0x31, 0x58, 0x20, 0x1a, + 0xbf, 0xaf, 0x02, 0xbd, 0x92, 0x6f, 0xf7, 0xc5, 0xab, 0xa2, 0xcf, 0x30, 0x3b, 0xef, 0x77, 0x93, + 0x84, 0x24, 0xad, 0xd1, 0x92, 0x1f, 0x11, 0x50, 0xda, 0xa2, 0x93, 0xcb, 0x9a, 0x7f, 0x95, 0x65, + 0x35, 0xfe, 0x24, 0x03, 0xc5, 0x5d, 0x6f, 0x22, 0xf4, 0x72, 0x21, 0xcf, 0xe1, 0x36, 0x89, 0x9c, + 0x25, 0x0b, 0xe2, 0xb1, 0x3b, 0x7c, 0x71, 0xbe, 0x49, 0xaa, 0xbc, 0x51, 0x4b, 0xca, 0x1b, 0xdf, + 0x83, 0x3b, 0xe8, 0x8b, 0xf2, 0xbd, 0x89, 0xe7, 0x8b, 0xad, 0x6a, 0x8f, 0x48, 0xee, 0xf0, 0xdc, + 0xf0, 0x5c, 0xf1, 0xce, 0xdb, 0xa7, 0x9c, 0x1f, 0x69, 0x18, 0xfb, 0x11, 0x02, 0x66, 0x74, 0x8d, + 0xc2, 0x0b, 0x8b, 0x54, 0x45, 0x29, 0x18, 0x11, 0x47, 0x5d, 0x14, 0x05, 0x1d, 0x84, 0xa3, 0x68, + 0x64, 0x7c, 0x17, 0xca, 0x91, 0xd5, 0x81, 0xbd, 0x0b, 0xe5, 0x73, 0x6f, 0x22, 0x4d, 0x13, 0x99, + 0x44, 0x4e, 0x8e, 0x9c, 0xb5, 0x59, 0x3a, 0xa7, 0x1f, 0x81, 0xf1, 0xe7, 0x45, 0x28, 0x76, 0xdd, + 0x0b, 0xcf, 0x19, 0x60, 0xa8, 0xd8, 0x98, 0x8f, 0x3d, 0x95, 0x0d, 0x2c, 0x7e, 0x63, 0x38, 0x48, + 0x7c, 0x41, 0x47, 0x4e, 0x86, 0x83, 0x44, 0x57, 0x73, 0xac, 0xc0, 0x82, 0xaf, 0xdf, 0xb0, 0x51, + 0xf0, 0x31, 0x78, 0x35, 0x52, 0xda, 0x0a, 0x5a, 0x36, 0xb5, 0x68, 0x8b, 0x6e, 0x7e, 0xc0, 0x25, + 0xa3, 0xec, 0xac, 0x32, 0x42, 0x70, 0xc1, 0x5e, 0x83, 0xa2, 0x4c, 0x81, 0xa1, 0x84, 0x02, 0x8a, + 0x36, 0x95, 0x20, 0xa4, 0x06, 0x9f, 0x93, 0x2f, 0x31, 0x92, 0xa8, 0x84, 0x9e, 0x2e, 0x81, 0xdb, + 0x82, 0xd6, 0xee, 0x41, 0x85, 0xf0, 0x09, 0xa5, 0x24, 0x83, 0xbb, 0x10, 0x84, 0x08, 0x29, 0x17, + 0xd5, 0x94, 0x53, 0x2f, 0xaa, 0xc1, 0x58, 0xc0, 0x88, 0xcb, 0xd2, 0x14, 0x81, 0xae, 0x27, 0xd1, + 0xe0, 0xea, 0x96, 0x26, 0xa9, 0xdc, 0x53, 0xb2, 0xa2, 0x52, 0xee, 0xdf, 0x84, 0xda, 0xa9, 0x3d, + 0x1a, 0x9d, 0xd8, 0x83, 0xe7, 0xa4, 0x93, 0x56, 0xc9, 0x0c, 0xa7, 0x80, 0xa8, 0x94, 0xde, 0x83, + 0x8a, 0xf6, 0x96, 0x31, 0x72, 0x2b, 0x6f, 0x42, 0xfc, 0x7e, 0x67, 0x4d, 0x4d, 0xf5, 0x57, 0x30, + 0x35, 0x69, 0x11, 0x6c, 0x8b, 0xc9, 0x08, 0xb6, 0x3b, 0xc8, 0x4d, 0x65, 0x94, 0x53, 0x83, 0xee, + 0xc2, 0xb0, 0x87, 0x43, 0x8c, 0x72, 0xa2, 0x8b, 0xe7, 0x70, 0xf1, 0xa8, 0xbc, 0x49, 0x42, 0x2d, + 0xc1, 0x08, 0xe5, 0x2e, 0xd9, 0x4b, 0x27, 0xb6, 0x33, 0xc4, 0x88, 0x61, 0x52, 0x63, 0x8b, 0xf6, + 0x38, 0x3c, 0xb2, 0x9d, 0x21, 0xbb, 0x0f, 0x55, 0x55, 0x8c, 0xa7, 0xe3, 0x12, 0xad, 0xbf, 0x2c, + 0x16, 0x67, 0xa2, 0x01, 0xb5, 0x08, 0x63, 0x1c, 0x67, 0x1c, 0x56, 0x24, 0x0a, 0xd2, 0xc1, 0x7b, + 0x18, 0x18, 0x12, 0x72, 0xcc, 0x2b, 0xac, 0x3f, 0xb9, 0x23, 0xe7, 0x2a, 0xa9, 0x54, 0xfd, 0x27, + 0x2f, 0x0d, 0x61, 0x0a, 0x41, 0x8c, 0x9c, 0x45, 0xab, 0x09, 0x41, 0x4c, 0xa2, 0xa2, 0xb3, 0x88, + 0x10, 0xd8, 0x77, 0x35, 0x45, 0xaa, 0x85, 0xc8, 0xaf, 0xcd, 0xb4, 0x7f, 0x53, 0xc2, 0xc4, 0x5d, + 0x00, 0x27, 0x10, 0xa7, 0x4c, 0xc0, 0xdd, 0x21, 0xa6, 0x08, 0x96, 0xcc, 0xb2, 0x13, 0x3c, 0x23, + 0xc0, 0x57, 0xab, 0x61, 0xb5, 0xa1, 0xaa, 0x4f, 0x93, 0x95, 0x20, 0x7f, 0x78, 0xd4, 0x39, 0x68, + 0xdc, 0x62, 0x15, 0x28, 0xf6, 0x3a, 0xfd, 0xfe, 0x1e, 0xba, 0x9c, 0xaa, 0x50, 0x8a, 0xf2, 0x93, + 0xb2, 0xe2, 0xa9, 0xbd, 0xb5, 0xd5, 0x39, 0xea, 0x77, 0xb6, 0x1b, 0xb9, 0x1f, 0xe4, 0x4b, 0xd9, + 0x46, 0xce, 0xf8, 0x8b, 0x1c, 0x54, 0xb4, 0x55, 0x78, 0x31, 0x33, 0xbe, 0x0b, 0x80, 0x2a, 0x4d, + 0x1c, 0x04, 0x97, 0x37, 0xcb, 0x02, 0x42, 0x2f, 0x5f, 0x37, 0x96, 0xe7, 0xe8, 0x92, 0x15, 0x65, + 0x2c, 0x7f, 0x13, 0x6a, 0x74, 0x5f, 0x89, 0xee, 0x38, 0x2c, 0x98, 0x55, 0x02, 0x4a, 0x56, 0x8d, + 0x09, 0x8e, 0x88, 0x84, 0xa9, 0x2f, 0xf2, 0xf6, 0x02, 0x02, 0x61, 0xf2, 0x0b, 0x66, 0x2e, 0x05, + 0xde, 0xe8, 0x82, 0x13, 0x06, 0x49, 0x84, 0x15, 0x09, 0xeb, 0xcb, 0x54, 0x4d, 0xc9, 0x0f, 0xb5, + 0x0c, 0xbb, 0x82, 0x59, 0x25, 0xa0, 0xec, 0xe8, 0x9b, 0x8a, 0x80, 0x4a, 0x48, 0x40, 0x6b, 0xf3, + 0xd4, 0x90, 0x20, 0x9e, 0xbd, 0x39, 0x7b, 0x56, 0x19, 0x09, 0xe3, 0x6b, 0xf3, 0xf5, 0x5e, 0x6e, + 0xd7, 0x62, 0xef, 0x02, 0x1b, 0x4f, 0x26, 0x56, 0x8a, 0xa5, 0x29, 0x6f, 0x2e, 0x8e, 0x27, 0x93, + 0xbe, 0x66, 0x88, 0xf9, 0x0a, 0x8c, 0x60, 0x9f, 0x03, 0x6b, 0x8b, 0x0d, 0x8c, 0x43, 0x8c, 0x4c, + 0xa8, 0x31, 0x5b, 0xce, 0xe8, 0x6c, 0x39, 0x85, 0xfb, 0x65, 0x53, 0xb9, 0xdf, 0x8b, 0xf8, 0x84, + 0xb1, 0x03, 0x95, 0x23, 0xed, 0x36, 0xa4, 0xfb, 0xe2, 0x84, 0x50, 0xf7, 0x20, 0xd1, 0xd9, 0x41, + 0xc6, 0x2d, 0x5f, 0x5e, 0x7f, 0xa4, 0x8d, 0x26, 0xab, 0x8d, 0xc6, 0xf8, 0xd7, 0x19, 0xba, 0x69, + 0x22, 0x1a, 0x7c, 0x7c, 0x01, 0x93, 0xf2, 0x03, 0xc5, 0x89, 0xb0, 0x15, 0xe5, 0xff, 0x91, 0x39, + 0xac, 0x38, 0x34, 0xcb, 0x3b, 0x3d, 0x0d, 0xb8, 0x0a, 0x36, 0xa8, 0x20, 0xec, 0x10, 0x41, 0x4a, + 0xf8, 0x16, 0x12, 0xbe, 0x43, 0xed, 0x07, 0x32, 0xc2, 0x40, 0x08, 0xdf, 0xfb, 0xf6, 0x95, 0xec, + 0x35, 0x10, 0x22, 0x88, 0x34, 0x54, 0xab, 0x44, 0xb6, 0xe8, 0xd9, 0xf8, 0x17, 0x32, 0x57, 0x77, + 0x76, 0x7d, 0x1f, 0x42, 0x29, 0x6a, 0x35, 0x79, 0xc2, 0x2a, 0xcc, 0xa8, 0x5c, 0x9c, 0xe3, 0xa8, + 0x95, 0x27, 0x46, 0x4c, 0x9b, 0x0b, 0x9d, 0x0d, 0x5d, 0x6d, 0xd4, 0xdf, 0x00, 0x76, 0xea, 0xf8, + 0xb3, 0xc8, 0xb4, 0xd9, 0x1a, 0x58, 0xa2, 0x61, 0x1b, 0xc7, 0xb0, 0xa4, 0xb8, 0x84, 0xa6, 0x11, + 0x24, 0x5f, 0x5e, 0xe6, 0x25, 0x4c, 0x3e, 0x3b, 0xc7, 0xe4, 0x8d, 0x9f, 0xe6, 0xa1, 0xa8, 0x6e, + 0x16, 0x4b, 0xbb, 0x0d, 0xab, 0x9c, 0xbc, 0x0d, 0xab, 0x95, 0xb8, 0x39, 0x05, 0x5f, 0xbd, 0x3c, + 0xef, 0xdf, 0x99, 0x3d, 0xb2, 0x35, 0xa3, 0x79, 0xe2, 0xd8, 0x5e, 0x85, 0xfc, 0xc4, 0x0e, 0xcf, + 0xd1, 0x40, 0x46, 0xc4, 0x83, 0xcf, 0xca, 0x98, 0x5e, 0x48, 0x1a, 0xd3, 0xd3, 0x6e, 0x0e, 0x23, + 0x91, 0x74, 0xee, 0xe6, 0xb0, 0x3b, 0x40, 0xf2, 0x85, 0x16, 0x2b, 0x55, 0x42, 0x80, 0x38, 0x8b, + 0x92, 0xe2, 0x48, 0x69, 0x56, 0x1c, 0x79, 0x65, 0x51, 0xe1, 0xdb, 0xb0, 0x40, 0x59, 0xf7, 0x32, + 0x61, 0x4f, 0x1d, 0x28, 0x72, 0x0d, 0xd5, 0x7f, 0x8a, 0xa0, 0x36, 0x25, 0xae, 0x7e, 0x0d, 0x4f, + 0x25, 0x71, 0x0d, 0x8f, 0x6e, 0xe4, 0xaf, 0x26, 0x8d, 0xfc, 0x0f, 0xa0, 0x11, 0x2d, 0x28, 0x9a, + 0xcc, 0xdc, 0x40, 0xa6, 0x03, 0xd5, 0x15, 0x5c, 0x70, 0xc9, 0x83, 0x20, 0x3e, 0x10, 0xeb, 0x89, + 0x03, 0x51, 0xf0, 0xb0, 0x76, 0x18, 0xf2, 0xf1, 0x24, 0x94, 0x07, 0x22, 0x26, 0x0c, 0xe8, 0x03, + 0x4c, 0xa6, 0xb2, 0xd6, 0xa0, 0xdc, 0x3d, 0xb0, 0x76, 0xf6, 0xba, 0x4f, 0x77, 0xfb, 0x8d, 0x8c, + 0x78, 0xec, 0x1d, 0x6f, 0x6d, 0x75, 0x3a, 0xdb, 0x78, 0xe2, 0x00, 0x2c, 0xec, 0xb4, 0xbb, 0xe2, + 0xf4, 0xc9, 0x19, 0xbf, 0x93, 0x85, 0x8a, 0xd6, 0x3c, 0x7b, 0x3f, 0x5a, 0x15, 0xba, 0xa9, 0xe5, + 0xee, 0xfc, 0x10, 0x36, 0x14, 0x2b, 0xd6, 0x96, 0x25, 0xba, 0x27, 0x2d, 0x7b, 0xe3, 0x3d, 0x69, + 0xec, 0x6d, 0x58, 0xb4, 0xa9, 0x85, 0x68, 0x15, 0xa4, 0x39, 0x58, 0x82, 0xe5, 0x22, 0x60, 0x84, + 0x60, 0x7c, 0x9e, 0x08, 0xbc, 0xbc, 0x0a, 0xca, 0x8b, 0x8e, 0x14, 0x5c, 0xac, 0xe2, 0xa9, 0xed, + 0x8c, 0xa6, 0x3e, 0x97, 0xee, 0xdb, 0xe8, 0x64, 0x26, 0xa8, 0xa9, 0x8a, 0x8d, 0x0f, 0x00, 0xe2, + 0x31, 0x27, 0x17, 0xe7, 0x56, 0x72, 0x71, 0x32, 0xda, 0xe2, 0x64, 0x8d, 0x6d, 0x62, 0x23, 0x72, + 0xa1, 0x23, 0x4f, 0xf5, 0x37, 0x41, 0x59, 0xa4, 0x2c, 0x8c, 0xd1, 0x9d, 0x8c, 0x78, 0xa8, 0x92, + 0x7e, 0x9b, 0xb2, 0xa4, 0x1b, 0x15, 0xa8, 0x1c, 0xfc, 0xb8, 0x95, 0x98, 0x1b, 0x49, 0x92, 0x9c, + 0xe5, 0x46, 0x12, 0xd5, 0x8c, 0xca, 0x8d, 0x75, 0x68, 0x6d, 0x73, 0xd1, 0x5a, 0x7b, 0x34, 0x9a, + 0x19, 0x8e, 0x71, 0x07, 0x6e, 0xa7, 0x94, 0x49, 0x23, 0xc4, 0xc7, 0xb0, 0xd2, 0xa6, 0xfc, 0xde, + 0xaf, 0x2a, 0x91, 0xc7, 0x68, 0xc1, 0xea, 0x6c, 0x93, 0xb2, 0xb3, 0x1d, 0x68, 0x6e, 0xf3, 0x93, + 0xe9, 0xd9, 0x1e, 0xbf, 0x88, 0x3b, 0x62, 0x90, 0x0f, 0xce, 0xbd, 0x4b, 0xb9, 0x3e, 0xf8, 0x1b, + 0xc3, 0xdd, 0x04, 0x8e, 0x15, 0x4c, 0xf8, 0x40, 0x59, 0x44, 0x11, 0xd2, 0x9b, 0xf0, 0x81, 0xf1, + 0x3e, 0x30, 0xbd, 0x1d, 0xb9, 0x5e, 0x42, 0x4b, 0x98, 0x9e, 0x58, 0xc1, 0x75, 0x10, 0xf2, 0xb1, + 0xba, 0x08, 0x08, 0x82, 0xe9, 0x49, 0x8f, 0x20, 0xc6, 0x3b, 0x50, 0x3d, 0xb2, 0xaf, 0x4d, 0xfe, + 0xb9, 0x4c, 0x51, 0x59, 0x83, 0xe2, 0xc4, 0xbe, 0x16, 0x6c, 0x20, 0x72, 0x8e, 0x60, 0xb1, 0xf1, + 0x87, 0x79, 0x58, 0x20, 0x4c, 0x76, 0x9f, 0xee, 0xea, 0x74, 0x5c, 0xdc, 0x86, 0x8a, 0x51, 0x6a, + 0xa0, 0x39, 0x5e, 0x9a, 0x9d, 0xe7, 0xa5, 0xd2, 0x80, 0xa6, 0xee, 0x28, 0x51, 0x66, 0x6c, 0x77, + 0x3a, 0x56, 0x17, 0x93, 0x24, 0x93, 0x5c, 0xf3, 0xf1, 0x5d, 0xac, 0x94, 0x01, 0x98, 0x74, 0x34, + 0xc6, 0xba, 0x08, 0x8d, 0x4e, 0x1d, 0x11, 0x92, 0x5d, 0xea, 0xa0, 0x54, 0x85, 0xa7, 0xa8, 0x92, + 0x9f, 0x92, 0x0a, 0xcf, 0x9c, 0x62, 0x53, 0x7a, 0xb9, 0x62, 0x43, 0x96, 0xb5, 0x17, 0x28, 0x36, + 0xf0, 0x0a, 0x8a, 0xcd, 0x2b, 0x38, 0xf9, 0x6e, 0x43, 0x09, 0xcf, 0x7d, 0x8d, 0x7b, 0x8a, 0xf3, + 0x5e, 0x70, 0xcf, 0xef, 0x68, 0xa2, 0x3f, 0x45, 0x18, 0xdc, 0x89, 0xb7, 0x89, 0xc9, 0x3f, 0xff, + 0xc5, 0x38, 0x4f, 0x3e, 0x83, 0xa2, 0x84, 0x0a, 0x82, 0x76, 0xed, 0xb1, 0xba, 0xe6, 0x09, 0x7f, + 0x8b, 0x65, 0xc3, 0xbb, 0x69, 0x3e, 0x9f, 0x3a, 0x3e, 0x1f, 0xaa, 0xfb, 0x3b, 0x1c, 0xdc, 0xa3, + 0x02, 0x22, 0x26, 0x28, 0xd4, 0x10, 0xd7, 0xbb, 0x74, 0x65, 0xf6, 0x7e, 0xd1, 0x09, 0x9e, 0x89, + 0x47, 0x83, 0x41, 0x03, 0x2f, 0x7a, 0x9b, 0x78, 0xbe, 0x3a, 0x9c, 0x8c, 0x9f, 0x66, 0xa0, 0x21, + 0x77, 0x57, 0x54, 0xa6, 0x6b, 0x01, 0x85, 0x9b, 0x1c, 0xe2, 0x2f, 0xbe, 0x8d, 0xc3, 0x80, 0x1a, + 0x1a, 0x3f, 0xa2, 0x93, 0x8a, 0x8c, 0x37, 0x15, 0x01, 0xdc, 0x91, 0xa7, 0xd5, 0xeb, 0x50, 0x51, + 0xc1, 0xb8, 0x63, 0x67, 0xa4, 0xae, 0x5d, 0xa6, 0x68, 0xdc, 0x7d, 0x67, 0xa4, 0x0e, 0x3a, 0xdf, + 0x96, 0xc9, 0x78, 0x19, 0x3c, 0xe8, 0x4c, 0x3b, 0xe4, 0xc6, 0x7f, 0xc8, 0x40, 0x53, 0x9b, 0x8a, + 0xdc, 0xb7, 0x1f, 0x42, 0x35, 0xba, 0x61, 0x91, 0x47, 0x92, 0xd7, 0x5a, 0x92, 0xd1, 0xc4, 0xd5, + 0x2a, 0x83, 0x08, 0x12, 0x88, 0xc1, 0x0c, 0xed, 0x6b, 0x8a, 0x18, 0x9d, 0x8e, 0x95, 0x72, 0x33, 0xb4, 0xaf, 0x77, 0x38, 0xef, 0x4d, 0xc7, 0x42, 0x75, 0xbd, 0xe4, 0xfc, 0x79, 0x84, 0x40, 0x32, 0x17, 0x08, 0x98, 0xc4, 0x30, 0xa0, 0x36, 0xf6, 0xdc, 0xf0, 0x3c, 0x42, 0x91, 0x52, 0x27, 0x02, 0x09, 0xc7, 0xf8, 0xb3, 0x2c, 0x2c, 0x91, 0x89, 0x4d, 0x9a, 0x36, 0x25, 0xeb, 0x6a, 0xc1, 0x02, - 0x59, 0x1b, 0x89, 0x79, 0xed, 0xde, 0x32, 0xe5, 0x33, 0xfb, 0xf6, 0x2b, 0x9a, 0x05, 0x55, 0x22, - 0xdd, 0x0d, 0xcb, 0x9f, 0x9b, 0x5f, 0xfe, 0x9b, 0x97, 0x37, 0xcd, 0xe3, 0x56, 0x48, 0xf3, 0xb8, - 0xbd, 0x8a, 0x9f, 0x6b, 0x2e, 0xdb, 0xac, 0x28, 0x71, 0xb4, 0x6c, 0xb3, 0xf7, 0x61, 0x2d, 0x81, - 0x83, 0xdc, 0xda, 0x39, 0x75, 0xb8, 0xba, 0x75, 0x60, 0x59, 0xc3, 0xee, 0xa9, 0xb2, 0xcd, 0x22, - 0x14, 0x82, 0x81, 0x37, 0xe1, 0xc6, 0x2a, 0x2c, 0x27, 0x57, 0x55, 0x1e, 0x13, 0xbf, 0x9f, 0x81, - 0x96, 0x8c, 0x8f, 0x70, 0xdc, 0xb3, 0x5d, 0x27, 0x08, 0x3d, 0x3f, 0xba, 0xe2, 0xef, 0x2e, 0x40, - 0x10, 0xda, 0xbe, 0xd4, 0x36, 0x65, 0x9e, 0x3d, 0x42, 0x50, 0x93, 0xbc, 0x0d, 0x25, 0xee, 0x0e, - 0xa9, 0x90, 0xa8, 0xa1, 0xc8, 0xdd, 0xa1, 0xd2, 0x43, 0xe7, 0xe4, 0xef, 0x5a, 0x52, 0xbd, 0x90, - 0x69, 0xaf, 0x62, 0x75, 0xf8, 0x05, 0x1e, 0xbc, 0xf9, 0x28, 0xed, 0x75, 0xdf, 0xbe, 0xc2, 0x68, - 0xc3, 0xc0, 0xf8, 0x47, 0x59, 0x68, 0xc4, 0xe3, 0xa3, 0x9c, 0xf9, 0x17, 0x67, 0xff, 0xdf, 0x97, - 0xe4, 0xe0, 0x08, 0xf9, 0x5d, 0x33, 0x3c, 0x96, 0x68, 0x73, 0x76, 0x5d, 0x66, 0x40, 0x45, 0x61, - 0x78, 0xd3, 0x50, 0xbb, 0x69, 0xab, 0x4c, 0x28, 0x87, 0xd3, 0x50, 0x28, 0x5c, 0x42, 0xf3, 0x74, - 0x5c, 0xa9, 0xf2, 0x14, 0xec, 0x71, 0xd8, 0xc5, 0x0b, 0xbc, 0x05, 0x58, 0x54, 0xa3, 0x17, 0x29, - 0xb0, 0x04, 0x7e, 0x93, 0xe4, 0x6c, 0x7a, 0x73, 0x28, 0x63, 0xeb, 0x42, 0x28, 0xdd, 0x65, 0x1a, - 0x09, 0xa1, 0xaf, 0x43, 0x85, 0x1a, 0x8f, 0x93, 0x0b, 0xf3, 0x66, 0x19, 0x7b, 0xc0, 0x72, 0x69, - 0x04, 0xf2, 0xa6, 0x09, 0xd5, 0x17, 0xa8, 0x2b, 0x0c, 0x3f, 0xf8, 0x7b, 0x19, 0xb8, 0x9d, 0xf2, - 0xda, 0xe4, 0x2e, 0xdf, 0x82, 0xc5, 0xd3, 0xa8, 0x50, 0xad, 0x2e, 0x6d, 0xf5, 0x55, 0xc5, 0x56, - 0x93, 0x6b, 0x6a, 0x36, 0x4f, 0x93, 0x80, 0x58, 0xe9, 0xa2, 0x37, 0x98, 0xc8, 0x1f, 0x45, 0xa5, - 0x8b, 0x5e, 0x23, 0xe9, 0x3b, 0x47, 0xb0, 0xde, 0xb9, 0x12, 0x1c, 0x63, 0x4b, 0xbf, 0x81, 0x5e, - 0x91, 0x51, 0xd2, 0xc0, 0x9c, 0x79, 0x25, 0x03, 0xf3, 0x90, 0xd2, 0xe4, 0xa2, 0xb6, 0x7e, 0x9e, - 0x46, 0xf0, 0x00, 0x15, 0x75, 0xe8, 0x06, 0x7d, 0x95, 0xc3, 0x3a, 0x88, 0x6e, 0xce, 0x37, 0x02, - 0x68, 0xec, 0x4f, 0x47, 0xa1, 0x13, 0x5f, 0xa6, 0xcf, 0xbe, 0x2d, 0xeb, 0x60, 0x3f, 0x6a, 0xd5, - 0x52, 0x3b, 0x82, 0xa8, 0x23, 0x5c, 0xac, 0xb1, 0x68, 0xc8, 0x9a, 0xef, 0xaf, 0x31, 0x4e, 0xf6, - 0x60, 0xdc, 0x86, 0xb5, 0xf8, 0x89, 0x96, 0x4d, 0x1d, 0x35, 0xff, 0x3c, 0x43, 0xa1, 0xcd, 0xc9, - 0x8b, 0xfd, 0x59, 0x07, 0x96, 0x02, 0xc7, 0x3d, 0x1b, 0x71, 0xbd, 0xf9, 0x40, 0x2e, 0xc2, 0x4a, - 0x72, 0x6c, 0xf2, 0xf2, 0x7f, 0x73, 0x91, 0x6a, 0xc4, 0xad, 0x05, 0x6c, 0xf3, 0xa6, 0x41, 0xc6, - 0x64, 0x31, 0xb3, 0x1a, 0xf3, 0x83, 0xef, 0x42, 0x3d, 0xd9, 0x11, 0xfb, 0x8e, 0x4c, 0x11, 0x8d, - 0x47, 0x95, 0x9b, 0x49, 0xe6, 0x8b, 0x09, 0xa2, 0x12, 0xaf, 0x7d, 0x60, 0xfc, 0x83, 0x0c, 0xb4, - 0x4c, 0x2e, 0x28, 0x57, 0x1b, 0xa5, 0xa2, 0x99, 0x0f, 0xe7, 0x5a, 0xbd, 0x79, 0xae, 0x2a, 0xf3, - 0x54, 0x8d, 0xe8, 0x1b, 0x37, 0xbe, 0x8c, 0xdd, 0x5b, 0x73, 0x33, 0xda, 0x2c, 0xc1, 0x02, 0xa1, - 0x18, 0x6b, 0xb0, 0x22, 0xc7, 0xa3, 0xc6, 0x12, 0x7b, 0x0f, 0x13, 0x3d, 0x26, 0xbc, 0x87, 0xeb, - 0xd0, 0xa2, 0x9b, 0x1a, 0xf5, 0x49, 0xc8, 0x8a, 0xdb, 0xc0, 0xf6, 0xed, 0x81, 0xed, 0x7b, 0x9e, - 0x7b, 0xc4, 0x7d, 0x19, 0x28, 0x8a, 0x12, 0x26, 0x3a, 0xd7, 0x94, 0x28, 0x4c, 0x4f, 0xea, 0x7e, - 0x41, 0xcf, 0x55, 0x71, 0x31, 0xf4, 0x64, 0x98, 0xb0, 0xb4, 0x69, 0x3f, 0xe7, 0xaa, 0x25, 0xb5, - 0x44, 0x1f, 0x41, 0x65, 0x12, 0x35, 0xaa, 0xd6, 0x5d, 0xe5, 0x91, 0xcf, 0x77, 0x6b, 0xea, 0xd8, - 0xc6, 0x13, 0x58, 0x4e, 0xb6, 0x29, 0x59, 0xc7, 0x3a, 0x94, 0xc6, 0x12, 0x26, 0x47, 0x17, 0x3d, - 0x1b, 0xbf, 0x5b, 0x82, 0xa2, 0xd4, 0xe7, 0xd8, 0x06, 0xe4, 0x07, 0x2a, 0x36, 0x29, 0xbe, 0x9e, - 0x44, 0x96, 0xaa, 0xff, 0x5b, 0x18, 0xa1, 0x24, 0xf0, 0xd8, 0x47, 0x50, 0x4f, 0x7a, 0x45, 0x67, - 0x92, 0x54, 0x93, 0xee, 0xcc, 0xda, 0x60, 0xc6, 0xff, 0x55, 0x8e, 0x0f, 0x47, 0x92, 0x19, 0x4a, - 0xe7, 0xda, 0xe9, 0xe9, 0xb9, 0x42, 0xde, 0x0e, 0xce, 0x6d, 0xeb, 0xc9, 0xfb, 0x1f, 0xc8, 0x2c, - 0xd5, 0x0a, 0x02, 0x7b, 0xe7, 0xf6, 0x93, 0xf7, 0x3f, 0x98, 0x95, 0xa4, 0x65, 0x8e, 0xaa, 0x26, - 0x49, 0x2f, 0x43, 0x81, 0x2e, 0xd2, 0xa3, 0x20, 0x13, 0x7a, 0x60, 0x8f, 0x61, 0x59, 0xaa, 0xad, - 0x96, 0x0c, 0x07, 0x26, 0x2e, 0x58, 0xa2, 0xd4, 0x26, 0x59, 0xd6, 0xc3, 0x22, 0xb2, 0x0d, 0xad, - 0xc2, 0xc2, 0x79, 0x7c, 0x2b, 0x62, 0xcd, 0x94, 0x4f, 0xc6, 0x9f, 0x15, 0xa0, 0xa2, 0x2d, 0x0a, - 0xab, 0x42, 0xc9, 0xec, 0xf4, 0x3a, 0xe6, 0x27, 0x9d, 0xed, 0xe6, 0x2d, 0xf6, 0x00, 0xde, 0xea, - 0x1e, 0x6c, 0x1d, 0x9a, 0x66, 0x67, 0xab, 0x6f, 0x1d, 0x9a, 0x96, 0xba, 0x24, 0xe7, 0xa8, 0xfd, - 0xd9, 0x7e, 0xe7, 0xa0, 0x6f, 0x6d, 0x77, 0xfa, 0xed, 0xee, 0x5e, 0xaf, 0x99, 0x61, 0xaf, 0x41, - 0x2b, 0xc6, 0x54, 0xc5, 0xed, 0xfd, 0xc3, 0xe3, 0x83, 0x7e, 0x33, 0xcb, 0xee, 0xc1, 0x9d, 0x9d, - 0xee, 0x41, 0x7b, 0xcf, 0x8a, 0x71, 0xb6, 0xf6, 0xfa, 0x9f, 0x58, 0x9d, 0x5f, 0x3f, 0xea, 0x9a, - 0x9f, 0x35, 0x73, 0x69, 0x08, 0x42, 0x19, 0x57, 0x2d, 0xe4, 0xd9, 0x6d, 0x58, 0x21, 0x04, 0xaa, - 0x62, 0xf5, 0x0f, 0x0f, 0xad, 0xde, 0xe1, 0xe1, 0x41, 0xb3, 0xc0, 0x16, 0xa1, 0xd6, 0x3d, 0xf8, - 0xa4, 0xbd, 0xd7, 0xdd, 0xb6, 0xcc, 0x4e, 0x7b, 0x6f, 0xbf, 0xb9, 0xc0, 0x96, 0xa0, 0x31, 0x8b, - 0x57, 0x14, 0x4d, 0x28, 0xbc, 0xc3, 0x83, 0xee, 0xe1, 0x81, 0xf5, 0x49, 0xc7, 0xec, 0x75, 0x0f, - 0x0f, 0x9a, 0x25, 0xb6, 0x0a, 0x2c, 0x59, 0xb4, 0xbb, 0xdf, 0xde, 0x6a, 0x96, 0xd9, 0x0a, 0x2c, - 0x26, 0xe1, 0xcf, 0x3a, 0x9f, 0x35, 0x81, 0xb5, 0x60, 0x99, 0x06, 0x66, 0x6d, 0x76, 0xf6, 0x0e, - 0x3f, 0xb5, 0xf6, 0xbb, 0x07, 0xdd, 0xfd, 0xe3, 0xfd, 0x66, 0x05, 0xaf, 0xed, 0xea, 0x74, 0xac, - 0xee, 0x41, 0xef, 0x78, 0x67, 0xa7, 0xbb, 0xd5, 0xed, 0x1c, 0xf4, 0x9b, 0x55, 0xea, 0x39, 0x6d, - 0xe2, 0x35, 0x51, 0x41, 0xe6, 0x0c, 0x58, 0xdb, 0xdd, 0x5e, 0x7b, 0x73, 0xaf, 0xb3, 0xdd, 0xac, - 0xb3, 0xbb, 0x70, 0xbb, 0xdf, 0xd9, 0x3f, 0x3a, 0x34, 0xdb, 0xe6, 0x67, 0x2a, 0xa7, 0xc0, 0xda, - 0x69, 0x77, 0xf7, 0x8e, 0xcd, 0x4e, 0xb3, 0xc1, 0xde, 0x80, 0xbb, 0x66, 0xe7, 0xe3, 0xe3, 0xae, - 0xd9, 0xd9, 0xb6, 0x0e, 0x0e, 0xb7, 0x3b, 0xd6, 0x4e, 0xa7, 0xdd, 0x3f, 0x36, 0x3b, 0xd6, 0x7e, - 0xb7, 0xd7, 0xeb, 0x1e, 0x3c, 0x6d, 0x36, 0xd9, 0x5b, 0x70, 0x3f, 0x42, 0x89, 0x1a, 0x98, 0xc1, - 0x5a, 0x14, 0xf3, 0x53, 0xaf, 0xf4, 0xa0, 0xf3, 0xeb, 0x7d, 0xeb, 0xa8, 0xd3, 0x31, 0x9b, 0x8c, - 0xad, 0xc3, 0x6a, 0xdc, 0x3d, 0x75, 0x20, 0xfb, 0x5e, 0x12, 0x65, 0x47, 0x1d, 0x73, 0xbf, 0x7d, - 0x20, 0x5e, 0x70, 0xa2, 0x6c, 0x59, 0x0c, 0x3b, 0x2e, 0x9b, 0x1d, 0xf6, 0x0a, 0x63, 0x50, 0xd7, - 0xde, 0xca, 0x4e, 0xdb, 0x6c, 0xae, 0xb2, 0x06, 0x54, 0xf6, 0x8f, 0x8e, 0xac, 0x7e, 0x77, 0xbf, - 0x73, 0x78, 0xdc, 0x6f, 0xae, 0xb1, 0x15, 0x68, 0x76, 0x0f, 0xfa, 0x1d, 0x53, 0xbc, 0x6b, 0x55, - 0xf5, 0x7f, 0x15, 0xd9, 0x32, 0x34, 0xd4, 0x48, 0x15, 0xf4, 0x67, 0x45, 0xb6, 0x06, 0xec, 0xf8, - 0xc0, 0xec, 0xb4, 0xb7, 0xc5, 0xc2, 0x45, 0x05, 0xff, 0xbb, 0x28, 0x3d, 0x24, 0x3f, 0xcd, 0x45, - 0x87, 0x75, 0x1c, 0x72, 0x90, 0xbc, 0x23, 0xb7, 0xaa, 0xdd, 0x6d, 0xfb, 0xb2, 0xdb, 0xeb, 0x35, - 0xd5, 0x2a, 0x37, 0xa7, 0x5a, 0xcd, 0xe9, 0xee, 0x35, 0x5d, 0xf6, 0x7b, 0x13, 0x6a, 0x63, 0xba, - 0x2f, 0x57, 0xde, 0x8b, 0x09, 0x32, 0xfe, 0x86, 0x80, 0x74, 0x29, 0xe6, 0xdc, 0xf5, 0xed, 0x85, - 0xf9, 0xeb, 0xdb, 0xd3, 0xe4, 0xfb, 0x85, 0x34, 0xf9, 0xfe, 0x21, 0x2c, 0x12, 0x6b, 0x72, 0x5c, - 0x67, 0xac, 0xb4, 0x66, 0x92, 0x02, 0x1b, 0xc8, 0xa2, 0x08, 0xae, 0xd4, 0x09, 0xa5, 0x72, 0x48, - 0x16, 0x52, 0x94, 0xda, 0x46, 0x42, 0xd3, 0x20, 0xce, 0x11, 0x69, 0x1a, 0x51, 0x0f, 0xf6, 0x55, - 0xdc, 0x43, 0x45, 0xeb, 0x81, 0xe0, 0xd8, 0xc3, 0x43, 0x58, 0xe4, 0x57, 0xa1, 0x6f, 0x5b, 0xde, - 0xc4, 0xfe, 0x7c, 0x8a, 0x2e, 0x5c, 0x1b, 0x75, 0xf8, 0xaa, 0xd9, 0xc0, 0x82, 0x43, 0x84, 0x6f, - 0xdb, 0xa1, 0xfd, 0xf0, 0x0b, 0xa8, 0x68, 0x77, 0x29, 0xb3, 0x35, 0x58, 0xfa, 0xb4, 0xdb, 0x3f, - 0xe8, 0xf4, 0x7a, 0xd6, 0xd1, 0xf1, 0xe6, 0xb3, 0xce, 0x67, 0xd6, 0x6e, 0xbb, 0xb7, 0xdb, 0xbc, - 0x25, 0x36, 0xed, 0x41, 0xa7, 0xd7, 0xef, 0x6c, 0x27, 0xe0, 0x19, 0xf6, 0x3a, 0xac, 0x1f, 0x1f, - 0x1c, 0xf7, 0x3a, 0xdb, 0x56, 0x5a, 0xbd, 0xac, 0xa0, 0x52, 0x59, 0x9e, 0x52, 0x3d, 0xf7, 0xf0, - 0xfb, 0x50, 0x4f, 0x5e, 0xf0, 0xc9, 0x00, 0x16, 0xf6, 0x3a, 0x4f, 0xdb, 0x5b, 0x9f, 0xd1, 0xc5, - 0x7e, 0xbd, 0x7e, 0xbb, 0xdf, 0xdd, 0xb2, 0xe4, 0x45, 0x7e, 0x82, 0x23, 0x64, 0x58, 0x05, 0x8a, - 0xed, 0x83, 0xad, 0xdd, 0x43, 0xb3, 0xd7, 0xcc, 0x3e, 0xfc, 0x08, 0x9a, 0xb3, 0xfe, 0xa8, 0x84, - 0x03, 0xef, 0x45, 0x9e, 0xbe, 0x87, 0xff, 0x3a, 0x07, 0x10, 0x27, 0x0c, 0x08, 0x56, 0xb3, 0xdd, - 0xee, 0xb7, 0xf7, 0x0e, 0xc5, 0x34, 0xcc, 0xc3, 0xbe, 0xe0, 0x20, 0x66, 0xe7, 0xe3, 0xe6, 0xad, - 0xd4, 0x92, 0xc3, 0xa3, 0x7e, 0x33, 0x23, 0x56, 0xac, 0x7b, 0xd0, 0xed, 0x77, 0xdb, 0x7b, 0x96, - 0x79, 0x78, 0xdc, 0x3d, 0x78, 0x4a, 0x37, 0x96, 0x21, 0x97, 0x3d, 0x3e, 0xda, 0x31, 0x0f, 0x0f, - 0xfa, 0x56, 0x6f, 0xf7, 0xb8, 0xbf, 0x8d, 0xf7, 0x9d, 0x6d, 0x99, 0xdd, 0x23, 0x6a, 0x33, 0xff, - 0x22, 0x04, 0xd1, 0x74, 0x41, 0xac, 0xf9, 0xd3, 0xc3, 0x5e, 0xaf, 0x7b, 0x64, 0x7d, 0x7c, 0xdc, - 0x31, 0xbb, 0x9d, 0x1e, 0x56, 0x5c, 0x48, 0x81, 0x0b, 0xfc, 0xa2, 0xe0, 0xcd, 0xfd, 0xbd, 0x4f, - 0x24, 0xf3, 0x14, 0xa8, 0xa5, 0x24, 0x48, 0x60, 0x95, 0x05, 0x4f, 0x11, 0xdc, 0x27, 0xa5, 0x65, - 0xb8, 0xa1, 0x4c, 0xd4, 0xab, 0x08, 0xbe, 0x3a, 0xf7, 0x32, 0xb0, 0x5a, 0x35, 0xbd, 0x48, 0xd4, - 0x42, 0x96, 0x1b, 0x1d, 0x50, 0xdb, 0xdb, 0x26, 0x56, 0xa8, 0xcf, 0x41, 0x05, 0x6e, 0x43, 0xbc, - 0x28, 0xc1, 0x9e, 0x04, 0x4a, 0x53, 0x3d, 0x88, 0x92, 0xc5, 0x27, 0xbf, 0x93, 0x83, 0x3a, 0x25, - 0x6f, 0xd1, 0xa7, 0xac, 0xb8, 0xcf, 0xf6, 0xa1, 0x28, 0xbf, 0x89, 0xc6, 0x56, 0xa2, 0xcb, 0xa4, - 0xf4, 0xaf, 0xb0, 0xad, 0xaf, 0xce, 0x82, 0xa5, 0x38, 0xb6, 0xf4, 0x37, 0xff, 0xf4, 0x7f, 0xfe, - 0xc3, 0x6c, 0x8d, 0x55, 0x1e, 0x5d, 0xbc, 0xf7, 0xe8, 0x8c, 0xbb, 0x81, 0x68, 0xe3, 0xff, 0x07, - 0x88, 0xbf, 0xf4, 0xc5, 0x5a, 0x91, 0x13, 0x6a, 0xe6, 0x33, 0x68, 0xeb, 0xb7, 0x53, 0x4a, 0x64, - 0xbb, 0xb7, 0xb1, 0xdd, 0x25, 0xa3, 0x2e, 0xda, 0x75, 0x5c, 0x27, 0xa4, 0xaf, 0x7e, 0x7d, 0x98, - 0x79, 0xc8, 0x86, 0x50, 0xd5, 0xbf, 0xc1, 0xc5, 0x94, 0xa4, 0x94, 0xf2, 0x15, 0xb1, 0xf5, 0x3b, - 0xa9, 0x65, 0x4a, 0x06, 0xc5, 0x3e, 0x56, 0x8c, 0xa6, 0xe8, 0x63, 0x8a, 0x18, 0x71, 0x2f, 0x23, - 0x92, 0xca, 0xe3, 0x4f, 0x6d, 0xb1, 0xd7, 0x34, 0xb9, 0x6a, 0xee, 0x43, 0x5f, 0xeb, 0x77, 0x6f, - 0x28, 0x95, 0x7d, 0xdd, 0xc5, 0xbe, 0xd6, 0x0c, 0x26, 0xfa, 0x1a, 0x20, 0x8e, 0xfa, 0xd0, 0xd7, - 0x87, 0x99, 0x87, 0x4f, 0xfe, 0xf2, 0x01, 0x94, 0xa3, 0x60, 0x4e, 0xf6, 0x5b, 0x50, 0x4b, 0x64, - 0xd7, 0x31, 0x35, 0x8d, 0xb4, 0x64, 0xbc, 0xf5, 0xd7, 0xd2, 0x0b, 0x65, 0xc7, 0xaf, 0x63, 0xc7, - 0x2d, 0xb6, 0x2a, 0x3a, 0x96, 0xd9, 0x6b, 0x8f, 0x30, 0x1b, 0x96, 0xae, 0xe6, 0x7a, 0xae, 0x69, - 0x1f, 0xd4, 0xd9, 0x6b, 0xb3, 0x1a, 0x41, 0xa2, 0xb7, 0xbb, 0x37, 0x94, 0xca, 0xee, 0x5e, 0xc3, - 0xee, 0x56, 0xd9, 0xb2, 0xde, 0x9d, 0x0a, 0xbd, 0x64, 0x1c, 0xaf, 0xc3, 0xd3, 0xbf, 0x44, 0xc5, - 0xee, 0xc6, 0x97, 0x97, 0xa5, 0x7c, 0xa1, 0x2a, 0x22, 0x91, 0xf9, 0xcf, 0x54, 0x19, 0x2d, 0xec, - 0x8a, 0x31, 0x7c, 0x7d, 0xfa, 0x87, 0xa8, 0xd8, 0x09, 0x54, 0xb4, 0x8f, 0x37, 0xb0, 0xdb, 0x37, - 0x7e, 0x68, 0x62, 0x7d, 0x3d, 0xad, 0x28, 0x6d, 0x2a, 0x7a, 0xfb, 0x8f, 0x4e, 0x39, 0x67, 0xbf, - 0x01, 0xe5, 0xe8, 0x93, 0x00, 0x6c, 0x4d, 0xfb, 0x44, 0x83, 0xfe, 0x09, 0x83, 0xf5, 0xd6, 0x7c, - 0x41, 0x1a, 0xf1, 0xe9, 0xad, 0x0b, 0xe2, 0xfb, 0x14, 0x2a, 0xda, 0xb5, 0xff, 0xd1, 0x04, 0xe6, - 0x3f, 0x2d, 0x10, 0x4d, 0x20, 0xe5, 0x2b, 0x01, 0xc6, 0x22, 0x76, 0x51, 0x61, 0x65, 0xa4, 0xef, - 0xf0, 0xca, 0x0b, 0xd8, 0x1e, 0xac, 0x48, 0x4d, 0xeb, 0x84, 0x7f, 0x99, 0xd7, 0x90, 0xf2, 0xf1, - 0xaf, 0xc7, 0x19, 0xf6, 0x11, 0x94, 0xd4, 0xd7, 0x1d, 0xd8, 0x6a, 0xfa, 0x57, 0x2a, 0xd6, 0xd7, - 0xe6, 0xe0, 0x52, 0x2d, 0xfa, 0x0c, 0x20, 0xfe, 0xc6, 0x40, 0xc4, 0x24, 0xe6, 0xbe, 0x59, 0x10, - 0x51, 0xc0, 0xfc, 0x07, 0x09, 0x8c, 0x55, 0x9c, 0x60, 0x93, 0x21, 0x93, 0x70, 0xf9, 0xa5, 0xba, - 0xb3, 0xf4, 0x47, 0x50, 0xd1, 0x3e, 0x33, 0x10, 0x2d, 0xdf, 0xfc, 0x27, 0x0a, 0xa2, 0xe5, 0x4b, - 0xf9, 0x2a, 0x81, 0xb1, 0x8e, 0xad, 0x2f, 0x1b, 0x0d, 0xd1, 0xba, 0x10, 0xb5, 0xa4, 0xc8, 0x23, - 0x5e, 0xd0, 0x39, 0xd4, 0x12, 0xdf, 0x12, 0x88, 0x76, 0x68, 0xda, 0x97, 0x0a, 0xa2, 0x1d, 0x9a, - 0xfa, 0xf9, 0x01, 0x45, 0x67, 0xc6, 0xa2, 0xe8, 0xe7, 0x02, 0x51, 0xb4, 0x9e, 0x7e, 0x08, 0x15, - 0xed, 0xbb, 0x00, 0xd1, 0x5c, 0xe6, 0x3f, 0x41, 0x10, 0xcd, 0x25, 0xed, 0x33, 0x02, 0xcb, 0xd8, - 0x47, 0xdd, 0x40, 0x52, 0xc0, 0x5b, 0x17, 0x45, 0xdb, 0xbf, 0x05, 0xf5, 0xe4, 0xa7, 0x02, 0xa2, - 0xbd, 0x9f, 0xfa, 0xcd, 0x81, 0x68, 0xef, 0xdf, 0xf0, 0x7d, 0x01, 0x49, 0xd2, 0x0f, 0x97, 0xa2, - 0x4e, 0x1e, 0xfd, 0x44, 0xa6, 0xa5, 0x7c, 0xc1, 0x3e, 0x16, 0x0c, 0x4e, 0x5e, 0xfa, 0xc9, 0xd6, - 0x34, 0xaa, 0xd5, 0x6f, 0x0f, 0x8d, 0xf6, 0xcb, 0xdc, 0xfd, 0xa0, 0x49, 0x62, 0xc6, 0xc6, 0xd9, - 0x53, 0x58, 0x8a, 0x88, 0x39, 0xba, 0xc5, 0x33, 0x88, 0xe6, 0x90, 0x7a, 0x57, 0xe8, 0x7a, 0x73, - 0xb6, 0xf4, 0x71, 0x86, 0x8e, 0x3f, 0xbc, 0x3b, 0x51, 0x3b, 0xfe, 0xf4, 0x8b, 0x3c, 0xb5, 0xe3, - 0x2f, 0x71, 0xc5, 0xe2, 0xec, 0xf1, 0x17, 0x3a, 0xa2, 0x0d, 0x17, 0x1a, 0xb3, 0x77, 0x6a, 0xde, - 0xbd, 0x29, 0xed, 0x9f, 0x9a, 0x7f, 0xfd, 0xc5, 0xb7, 0x02, 0x24, 0x59, 0x91, 0xe2, 0xa6, 0x8f, - 0x64, 0xf0, 0x09, 0xfb, 0x4d, 0xa8, 0xea, 0xd7, 0x8b, 0x33, 0x9d, 0x27, 0xcc, 0xf6, 0x74, 0x27, - 0xb5, 0x2c, 0x49, 0x25, 0xac, 0xaa, 0x77, 0xc3, 0x3e, 0x81, 0xd5, 0x68, 0x99, 0xf5, 0xbc, 0xf5, - 0x80, 0xdd, 0x4b, 0xc9, 0x66, 0x4f, 0x2c, 0xf6, 0xed, 0x1b, 0xd3, 0xdd, 0x1f, 0x67, 0x04, 0xf5, - 0x25, 0xef, 0x39, 0x8e, 0x4f, 0x9e, 0xb4, 0xeb, 0x9d, 0xe3, 0x93, 0x27, 0xf5, 0x72, 0x64, 0x45, - 0x7d, 0x6c, 0x29, 0xb1, 0x46, 0x14, 0x96, 0xcb, 0x7e, 0x08, 0x0d, 0x2d, 0x29, 0xbf, 0x77, 0xed, - 0x0e, 0xa2, 0x9d, 0x34, 0x7f, 0x51, 0xdf, 0x7a, 0x9a, 0x6d, 0xd2, 0x58, 0xc3, 0xf6, 0x17, 0x8d, - 0xc4, 0xe2, 0x88, 0x5d, 0xb4, 0x05, 0x15, 0x3d, 0xe1, 0xff, 0x05, 0xed, 0xae, 0x69, 0x45, 0xfa, - 0x9d, 0x70, 0x8f, 0x33, 0x6c, 0x0f, 0x9a, 0xb3, 0x37, 0x54, 0x45, 0x3c, 0x25, 0xed, 0x56, 0xad, - 0xf5, 0x99, 0xc2, 0xc4, 0xbd, 0x56, 0xec, 0x88, 0x12, 0x3b, 0xa2, 0x2f, 0x65, 0x79, 0xfe, 0xec, - 0xa9, 0x9e, 0xfc, 0x82, 0x56, 0xd4, 0x5a, 0xda, 0xb7, 0xd3, 0x1e, 0x64, 0x1e, 0x67, 0xd8, 0xef, - 0x65, 0xa0, 0x9a, 0xb8, 0xf7, 0x25, 0x11, 0x3a, 0x3f, 0x33, 0xcf, 0x96, 0x5e, 0xa6, 0x4f, 0xd4, - 0x30, 0x71, 0x11, 0xf7, 0x1e, 0xfe, 0x20, 0xf1, 0x92, 0x7e, 0x92, 0x70, 0xed, 0x6d, 0xcc, 0x7e, - 0x4a, 0xeb, 0x8b, 0x59, 0x04, 0xfd, 0xfe, 0xc5, 0x2f, 0x1e, 0x67, 0xd8, 0xbf, 0xcd, 0x40, 0x3d, - 0xe9, 0xb3, 0x8f, 0xa6, 0x9b, 0x1a, 0x1d, 0x10, 0x91, 0xd2, 0x0d, 0x8e, 0xfe, 0x1f, 0xe2, 0x28, - 0xfb, 0x0f, 0xcd, 0xc4, 0x28, 0xe5, 0x0d, 0xdd, 0xbf, 0xd8, 0x68, 0xd9, 0x87, 0xf4, 0xe5, 0x4a, - 0x15, 0xca, 0xc4, 0xe6, 0xbf, 0x74, 0x18, 0x91, 0x9f, 0xfe, 0x5d, 0x40, 0x7c, 0x09, 0x3f, 0xa2, - 0x4f, 0x46, 0xa9, 0xc8, 0x18, 0x41, 0xc5, 0xaf, 0x5a, 0xdf, 0x78, 0x0b, 0xe7, 0xf4, 0xba, 0x71, - 0x3b, 0x31, 0xa7, 0x59, 0xc1, 0xa3, 0x4d, 0xa3, 0x93, 0x9f, 0xf5, 0x8b, 0x4f, 0xce, 0xb9, 0x4f, - 0xfd, 0xdd, 0x3c, 0xc8, 0x31, 0x0d, 0x52, 0xa2, 0x27, 0xb6, 0xda, 0x2b, 0x36, 0x63, 0x3c, 0xc4, - 0xb1, 0xbe, 0x65, 0xdc, 0xbb, 0x71, 0xac, 0x8f, 0xd0, 0xff, 0x2e, 0x46, 0x7c, 0x04, 0x10, 0x87, - 0x1a, 0xb2, 0x99, 0x80, 0xb7, 0x88, 0x01, 0xcd, 0x47, 0x23, 0x26, 0xf7, 0xb3, 0x8a, 0x8b, 0x13, - 0x2d, 0xfe, 0x06, 0xb1, 0xd3, 0x28, 0x14, 0x4f, 0x97, 0xbe, 0x92, 0x51, 0x81, 0x09, 0xe9, 0x6b, - 0xb6, 0xfd, 0x04, 0x33, 0x8d, 0xe2, 0xee, 0x8e, 0xa1, 0xb6, 0xe7, 0x79, 0xcf, 0xa7, 0x93, 0x28, - 0xbc, 0x3d, 0x19, 0x14, 0xb3, 0x6b, 0x07, 0xe7, 0xeb, 0x33, 0xb3, 0x30, 0xee, 0x63, 0x53, 0xeb, - 0xac, 0xa5, 0x35, 0xf5, 0xe8, 0x27, 0x71, 0x7c, 0xe3, 0x17, 0xcc, 0x86, 0xc5, 0x88, 0x47, 0xc7, - 0x31, 0x84, 0xc9, 0x66, 0x12, 0x9c, 0x79, 0xb6, 0x8b, 0x84, 0x9a, 0xa0, 0x46, 0xfb, 0x28, 0x50, - 0x6d, 0x3e, 0xce, 0xb0, 0x23, 0xa8, 0x6e, 0xf3, 0x01, 0x26, 0xea, 0x63, 0x68, 0xc9, 0x52, 0x22, - 0x4c, 0x81, 0x62, 0x52, 0xd6, 0x6b, 0x09, 0x60, 0xf2, 0xdc, 0x9a, 0xd8, 0xd7, 0x3e, 0xff, 0xfc, - 0xd1, 0x4f, 0x64, 0xd0, 0xca, 0x17, 0xea, 0xdc, 0x52, 0x41, 0x3d, 0x89, 0x73, 0x6b, 0x26, 0x0a, - 0x28, 0x71, 0x6e, 0xcd, 0x45, 0x01, 0x25, 0x96, 0x5a, 0x05, 0x15, 0xb1, 0x11, 0x2c, 0xce, 0x05, - 0x0e, 0x45, 0x47, 0xd6, 0x4d, 0xe1, 0x46, 0xeb, 0xf7, 0x6f, 0x46, 0x48, 0xf6, 0xf6, 0x30, 0xd9, - 0x5b, 0x0f, 0x6a, 0x74, 0x25, 0xe4, 0x09, 0xa7, 0x94, 0xbd, 0x99, 0xfb, 0x6e, 0xf4, 0x7c, 0xc0, - 0xd9, 0x03, 0x06, 0xcb, 0x92, 0x12, 0x0e, 0xe6, 0xca, 0xb1, 0xdf, 0x80, 0xca, 0x53, 0x1e, 0xaa, - 0x1c, 0xbd, 0x48, 0xc6, 0x9e, 0x49, 0xda, 0x5b, 0x4f, 0x49, 0xf1, 0x4b, 0xd2, 0x0c, 0xb6, 0xf6, - 0x88, 0x0f, 0xcf, 0x38, 0x31, 0x27, 0xcb, 0x19, 0x7e, 0xc1, 0x7e, 0x1d, 0x1b, 0x8f, 0x52, 0xa3, - 0x57, 0xb5, 0x24, 0x2c, 0xbd, 0xf1, 0xc6, 0x0c, 0x3c, 0xad, 0x65, 0xd7, 0x1b, 0x72, 0x4d, 0xd6, - 0x73, 0xa1, 0xa2, 0x5d, 0xa1, 0x10, 0x6d, 0xa0, 0xf9, 0x2b, 0x33, 0xa2, 0x0d, 0x94, 0x72, 0xe3, - 0x82, 0xf1, 0x00, 0xfb, 0x31, 0xd8, 0xfd, 0xb8, 0x1f, 0xba, 0x65, 0x21, 0xee, 0xe9, 0xd1, 0x4f, - 0xec, 0x71, 0xf8, 0x05, 0xfb, 0x14, 0x2f, 0x5e, 0xd7, 0x73, 0x10, 0x63, 0xa5, 0x61, 0x36, 0x5d, - 0x31, 0x5a, 0x2c, 0xad, 0x28, 0xa9, 0x48, 0x50, 0x57, 0x28, 0xc9, 0xbd, 0x0f, 0xd0, 0x0b, 0xbd, - 0xc9, 0xb6, 0xcd, 0xc7, 0x9e, 0x1b, 0xf3, 0xda, 0x38, 0x2b, 0x2e, 0xe6, 0x5f, 0x5a, 0x6a, 0x1c, - 0xfb, 0x54, 0xd3, 0xb2, 0x12, 0x69, 0x9c, 0x8a, 0xb8, 0x6e, 0x4c, 0x9c, 0x8b, 0x16, 0x24, 0x25, - 0x79, 0xee, 0x71, 0x86, 0xb5, 0x01, 0xe2, 0xc8, 0xb1, 0x48, 0x67, 0x9a, 0x0b, 0x4a, 0x8b, 0xd8, - 0x5e, 0x4a, 0x98, 0xd9, 0x11, 0x94, 0xe3, 0x90, 0x9b, 0xb5, 0xf8, 0x46, 0x98, 0x44, 0x80, 0x4e, - 0x74, 0x82, 0xcf, 0x85, 0xbb, 0x18, 0x4d, 0x5c, 0x2a, 0x60, 0x25, 0xb1, 0x54, 0xa7, 0x9c, 0x07, - 0xcc, 0x81, 0x25, 0x1a, 0x60, 0x24, 0x2e, 0x61, 0x36, 0x57, 0x74, 0xbf, 0xfe, 0x7c, 0xe4, 0x49, - 0xb4, 0x9b, 0x53, 0xe3, 0x27, 0x12, 0xa6, 0x1f, 0x41, 0xad, 0x94, 0x49, 0x26, 0x58, 0xf3, 0x18, - 0x16, 0xe7, 0x5c, 0xf4, 0xd1, 0x96, 0xbe, 0x29, 0xe6, 0x22, 0xda, 0xd2, 0x37, 0x7a, 0xf7, 0x8d, - 0x15, 0xec, 0xb2, 0x61, 0x00, 0xaa, 0x7a, 0x97, 0x4e, 0x38, 0x38, 0x17, 0xdd, 0xfd, 0xab, 0x0c, - 0x2c, 0xa5, 0x38, 0xe1, 0xd9, 0x1b, 0xca, 0x6a, 0x70, 0xa3, 0x83, 0x7e, 0x3d, 0xd5, 0x59, 0x6b, - 0xf4, 0xb0, 0x9f, 0x7d, 0xf6, 0x2c, 0x71, 0xb0, 0x91, 0xaf, 0x54, 0xee, 0xcc, 0x17, 0x0a, 0x15, - 0xa9, 0x12, 0xc5, 0xe7, 0xb0, 0x46, 0x03, 0x69, 0x8f, 0x46, 0x33, 0x8e, 0xe4, 0xd7, 0xe7, 0xbe, - 0x6c, 0x9f, 0x70, 0x8e, 0xaf, 0xdf, 0xfc, 0xe5, 0xfb, 0x1b, 0xc4, 0x69, 0x1a, 0x2a, 0x9b, 0x42, - 0x73, 0xd6, 0x41, 0xcb, 0x6e, 0x6e, 0x6b, 0xfd, 0x5e, 0x42, 0xff, 0x4d, 0x71, 0xea, 0x7e, 0x0d, - 0x3b, 0xbb, 0x67, 0xac, 0xa7, 0xad, 0x0b, 0xa9, 0xc4, 0xe2, 0x7d, 0xfc, 0xf5, 0xc8, 0x9b, 0x3c, - 0x33, 0x4f, 0xd5, 0xc1, 0x4d, 0xbe, 0xef, 0x48, 0x03, 0x4f, 0x77, 0x46, 0xbf, 0x8d, 0xdd, 0xdf, - 0x37, 0xee, 0xa4, 0x75, 0xef, 0x53, 0x15, 0xd2, 0xc5, 0xd7, 0x66, 0xf7, 0xb5, 0x1a, 0xc1, 0xfd, - 0xb4, 0xf7, 0x7d, 0xa3, 0x2e, 0x34, 0xb3, 0xd6, 0xb7, 0x50, 0xb6, 0xab, 0xea, 0xde, 0xe3, 0x68, - 0xfb, 0xa4, 0xb8, 0xa9, 0xa3, 0xed, 0x93, 0xe6, 0x6e, 0x4e, 0xca, 0x35, 0xca, 0xd1, 0xfc, 0x61, - 0xe6, 0xe1, 0xe6, 0x3b, 0x3f, 0xfc, 0xda, 0x99, 0x13, 0x9e, 0x4f, 0x4f, 0x36, 0x06, 0xde, 0xf8, - 0xd1, 0x48, 0x59, 0x1b, 0x65, 0xca, 0xf3, 0xa3, 0x91, 0x3b, 0x7c, 0x84, 0xcd, 0x9e, 0x2c, 0x4c, - 0x7c, 0x2f, 0xf4, 0xbe, 0xf5, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xc2, 0x01, 0xa8, 0x32, 0xbc, - 0x83, 0x00, 0x00, + 0x59, 0x1b, 0x89, 0x79, 0xed, 0xde, 0x32, 0xe5, 0x33, 0xfb, 0xf6, 0x2b, 0x9a, 0x05, 0x55, 0xbe, + 0xdf, 0x0d, 0xcb, 0x9f, 0x9b, 0x5f, 0xfe, 0x9b, 0x97, 0x37, 0xcd, 0xe3, 0x56, 0x48, 0xf3, 0xb8, + 0xbd, 0x8a, 0x9f, 0x6b, 0x2e, 0x29, 0xae, 0x28, 0x71, 0xb4, 0xa4, 0xb8, 0xf7, 0x61, 0x2d, 0x81, + 0x83, 0xdc, 0xda, 0x39, 0x75, 0xb8, 0xba, 0x1c, 0x61, 0x59, 0xc3, 0xee, 0xa9, 0xb2, 0xcd, 0x22, + 0x14, 0x82, 0x81, 0x37, 0xe1, 0xc6, 0x2a, 0x2c, 0x27, 0x57, 0x55, 0x1e, 0x13, 0xbf, 0x9b, 0x81, + 0x96, 0x8c, 0x8f, 0x70, 0xdc, 0xb3, 0x5d, 0x27, 0x08, 0x3d, 0x3f, 0xba, 0x89, 0xf0, 0x2e, 0x40, + 0x10, 0xda, 0xbe, 0xd4, 0x36, 0xe5, 0x75, 0x00, 0x08, 0x41, 0x4d, 0xf2, 0x36, 0x94, 0xb8, 0x3b, + 0xa4, 0x42, 0xa2, 0x86, 0x22, 0x77, 0x87, 0x4a, 0x0f, 0x9d, 0x93, 0xbf, 0x6b, 0x49, 0xf5, 0x42, + 0x66, 0xe7, 0x8a, 0xd5, 0xe1, 0x17, 0x78, 0xf0, 0xe6, 0xa3, 0xec, 0xdc, 0x7d, 0xfb, 0x0a, 0xa3, + 0x0d, 0x03, 0xe3, 0x9f, 0x66, 0x61, 0x31, 0x1e, 0x1f, 0xa5, 0xf6, 0xbf, 0xf8, 0x92, 0x82, 0xfb, + 0x92, 0x1c, 0x1c, 0x21, 0xbf, 0x6b, 0x86, 0xc7, 0x12, 0x6d, 0xce, 0xae, 0xcb, 0x0c, 0xa8, 0x28, + 0x0c, 0x6f, 0x1a, 0x6a, 0x17, 0x82, 0x95, 0x09, 0xe5, 0x70, 0x1a, 0x0a, 0x85, 0x4b, 0x68, 0x9e, + 0x8e, 0x2b, 0x55, 0x9e, 0x82, 0x3d, 0x0e, 0xbb, 0x78, 0xcf, 0xb8, 0x00, 0x8b, 0x6a, 0xf4, 0x22, + 0x05, 0x96, 0xc0, 0x6f, 0x90, 0x9c, 0x4d, 0x6f, 0x0e, 0x65, 0x6c, 0x5d, 0x08, 0xa5, 0x2b, 0x57, + 0x23, 0x21, 0xf4, 0x75, 0xa8, 0x50, 0xe3, 0x71, 0x0e, 0x64, 0xde, 0x2c, 0x63, 0x0f, 0x58, 0x2e, + 0x8d, 0x40, 0xde, 0x34, 0xa1, 0xfa, 0x02, 0x75, 0x85, 0xe1, 0x07, 0xff, 0x30, 0x03, 0xb7, 0x53, + 0x5e, 0x9b, 0xdc, 0xe5, 0x5b, 0xd0, 0x3c, 0x8d, 0x0a, 0xd5, 0xea, 0xd2, 0x56, 0x5f, 0x55, 0x6c, + 0x35, 0xb9, 0xa6, 0x66, 0xe3, 0x34, 0x09, 0x88, 0x95, 0x2e, 0x7a, 0x83, 0x89, 0x34, 0x57, 0x54, + 0xba, 0xe8, 0x35, 0x92, 0xbe, 0x73, 0x04, 0xeb, 0x9d, 0x2b, 0xc1, 0x31, 0xb6, 0xf4, 0x8b, 0xf2, + 0x15, 0x19, 0x25, 0x0d, 0xcc, 0x99, 0x57, 0x32, 0x30, 0x0f, 0x29, 0x9b, 0x2f, 0x6a, 0xeb, 0x67, + 0x69, 0x04, 0x0f, 0x50, 0x51, 0x87, 0x2e, 0xfa, 0x57, 0xa9, 0xb6, 0x83, 0xe8, 0x82, 0x7f, 0x23, + 0x80, 0xc5, 0xfd, 0xe9, 0x28, 0x74, 0xe2, 0x3b, 0xff, 0xd9, 0xb7, 0x65, 0x1d, 0xec, 0x47, 0xad, + 0x5a, 0x6a, 0x47, 0x10, 0x75, 0x84, 0x8b, 0x35, 0x16, 0x0d, 0x59, 0xf3, 0xfd, 0x2d, 0x8e, 0x93, + 0x3d, 0x18, 0xb7, 0x61, 0x2d, 0x7e, 0xa2, 0x65, 0x53, 0x47, 0xcd, 0xbf, 0xca, 0x50, 0x68, 0x73, + 0xf2, 0xfb, 0x03, 0xac, 0x03, 0x4b, 0x81, 0xe3, 0x9e, 0x8d, 0xb8, 0xde, 0x7c, 0x20, 0x17, 0x61, + 0x25, 0x39, 0x36, 0xf9, 0x8d, 0x02, 0xb3, 0x49, 0x35, 0xe2, 0xd6, 0x02, 0xb6, 0x79, 0xd3, 0x20, + 0x63, 0xb2, 0x98, 0x59, 0x8d, 0xf9, 0xc1, 0x77, 0xa1, 0x9e, 0xec, 0x88, 0x7d, 0x47, 0x66, 0xb2, + 0xc6, 0xa3, 0xca, 0xcd, 0xe4, 0x1c, 0xc6, 0x04, 0x51, 0x89, 0xd7, 0x3e, 0x30, 0xfe, 0x71, 0x06, + 0x5a, 0x26, 0x17, 0x94, 0xab, 0x8d, 0x52, 0xd1, 0xcc, 0x87, 0x73, 0xad, 0xde, 0x3c, 0x57, 0x95, + 0x20, 0xab, 0x46, 0xf4, 0x8d, 0x1b, 0x5f, 0xc6, 0xee, 0xad, 0xb9, 0x19, 0x6d, 0x96, 0x60, 0x81, + 0x50, 0x8c, 0x35, 0x58, 0x91, 0xe3, 0x51, 0x63, 0x89, 0xbd, 0x87, 0x89, 0x1e, 0x13, 0xde, 0xc3, + 0x75, 0x68, 0xd1, 0x85, 0x92, 0xfa, 0x24, 0x64, 0xc5, 0x6d, 0x60, 0xfb, 0xf6, 0xc0, 0xf6, 0x3d, + 0xcf, 0x3d, 0xe2, 0xbe, 0x0c, 0x14, 0x45, 0x09, 0x13, 0x9d, 0x6b, 0x4a, 0x14, 0xa6, 0x27, 0x75, + 0x0d, 0xa2, 0xe7, 0xaa, 0xb8, 0x18, 0x7a, 0x32, 0x4c, 0x58, 0xda, 0xb4, 0x9f, 0x73, 0xd5, 0x92, + 0x5a, 0xa2, 0x8f, 0xa0, 0x32, 0x89, 0x1a, 0x55, 0xeb, 0xae, 0xd2, 0xdd, 0xe7, 0xbb, 0x35, 0x75, + 0x6c, 0xe3, 0x09, 0x2c, 0x27, 0xdb, 0x94, 0xac, 0x63, 0x1d, 0x4a, 0x63, 0x09, 0x93, 0xa3, 0x8b, + 0x9e, 0x8d, 0xdf, 0x2e, 0x41, 0x51, 0xea, 0x73, 0x6c, 0x03, 0xf2, 0x03, 0x15, 0x9b, 0x14, 0xdf, + 0xa2, 0x22, 0x4b, 0xd5, 0xff, 0x2d, 0x8c, 0x50, 0x12, 0x78, 0xec, 0x23, 0xa8, 0x27, 0xbd, 0xa2, + 0x33, 0xb9, 0xb4, 0x49, 0x77, 0x66, 0x6d, 0x30, 0xe3, 0xff, 0x2a, 0xc7, 0x87, 0x23, 0xc9, 0x0c, + 0xa5, 0x73, 0xed, 0xf4, 0xf4, 0x5c, 0x21, 0x6f, 0x07, 0xe7, 0xb6, 0xf5, 0xe4, 0xfd, 0x0f, 0x64, + 0x32, 0x6d, 0x05, 0x81, 0xbd, 0x73, 0xfb, 0xc9, 0xfb, 0x1f, 0xcc, 0x4a, 0xd2, 0x32, 0x95, 0x56, + 0x93, 0xa4, 0x97, 0xa1, 0x40, 0xf7, 0xfd, 0x51, 0x90, 0x09, 0x3d, 0xb0, 0xc7, 0xb0, 0x2c, 0xd5, + 0x56, 0x4b, 0x86, 0x03, 0x13, 0x17, 0x2c, 0x51, 0x06, 0x96, 0x2c, 0xeb, 0x61, 0x11, 0xd9, 0x86, + 0x56, 0x61, 0xe1, 0x3c, 0xbe, 0xbc, 0xb1, 0x66, 0xca, 0x27, 0xe3, 0xcf, 0x0a, 0x50, 0xd1, 0x16, + 0x85, 0x55, 0xa1, 0x64, 0x76, 0x7a, 0x1d, 0xf3, 0x93, 0xce, 0x76, 0xe3, 0x16, 0x7b, 0x00, 0x6f, + 0x75, 0x0f, 0xb6, 0x0e, 0x4d, 0xb3, 0xb3, 0xd5, 0xb7, 0x0e, 0x4d, 0x4b, 0xdd, 0xe5, 0x73, 0xd4, + 0xfe, 0x6c, 0xbf, 0x73, 0xd0, 0xb7, 0xb6, 0x3b, 0xfd, 0x76, 0x77, 0xaf, 0xd7, 0xc8, 0xb0, 0xd7, + 0xa0, 0x15, 0x63, 0xaa, 0xe2, 0xf6, 0xfe, 0xe1, 0xf1, 0x41, 0xbf, 0x91, 0x65, 0xf7, 0xe0, 0xce, + 0x4e, 0xf7, 0xa0, 0xbd, 0x67, 0xc5, 0x38, 0x5b, 0x7b, 0xfd, 0x4f, 0xac, 0xce, 0xaf, 0x1e, 0x75, + 0xcd, 0xcf, 0x1a, 0xb9, 0x34, 0x04, 0xa1, 0x8c, 0xab, 0x16, 0xf2, 0xec, 0x36, 0xac, 0x10, 0x02, + 0x55, 0xb1, 0xfa, 0x87, 0x87, 0x56, 0xef, 0xf0, 0xf0, 0xa0, 0x51, 0x60, 0x4d, 0xa8, 0x75, 0x0f, + 0x3e, 0x69, 0xef, 0x75, 0xb7, 0x2d, 0xb3, 0xd3, 0xde, 0xdb, 0x6f, 0x2c, 0xb0, 0x25, 0x58, 0x9c, + 0xc5, 0x2b, 0x8a, 0x26, 0x14, 0xde, 0xe1, 0x41, 0xf7, 0xf0, 0xc0, 0xfa, 0xa4, 0x63, 0xf6, 0xba, + 0x87, 0x07, 0x8d, 0x12, 0x5b, 0x05, 0x96, 0x2c, 0xda, 0xdd, 0x6f, 0x6f, 0x35, 0xca, 0x6c, 0x05, + 0x9a, 0x49, 0xf8, 0xb3, 0xce, 0x67, 0x0d, 0x60, 0x2d, 0x58, 0xa6, 0x81, 0x59, 0x9b, 0x9d, 0xbd, + 0xc3, 0x4f, 0xad, 0xfd, 0xee, 0x41, 0x77, 0xff, 0x78, 0xbf, 0x51, 0xc1, 0xdb, 0xc5, 0x3a, 0x1d, + 0xab, 0x7b, 0xd0, 0x3b, 0xde, 0xd9, 0xe9, 0x6e, 0x75, 0x3b, 0x07, 0xfd, 0x46, 0x95, 0x7a, 0x4e, + 0x9b, 0x78, 0x4d, 0x54, 0x90, 0x39, 0x03, 0xd6, 0x76, 0xb7, 0xd7, 0xde, 0xdc, 0xeb, 0x6c, 0x37, + 0xea, 0xec, 0x2e, 0xdc, 0xee, 0x77, 0xf6, 0x8f, 0x0e, 0xcd, 0xb6, 0xf9, 0x99, 0xca, 0x29, 0xb0, + 0x76, 0xda, 0xdd, 0xbd, 0x63, 0xb3, 0xd3, 0x58, 0x64, 0x6f, 0xc0, 0x5d, 0xb3, 0xf3, 0xf1, 0x71, + 0xd7, 0xec, 0x6c, 0x5b, 0x07, 0x87, 0xdb, 0x1d, 0x6b, 0xa7, 0xd3, 0xee, 0x1f, 0x9b, 0x1d, 0x6b, + 0xbf, 0xdb, 0xeb, 0x75, 0x0f, 0x9e, 0x36, 0x1a, 0xec, 0x2d, 0xb8, 0x1f, 0xa1, 0x44, 0x0d, 0xcc, + 0x60, 0x35, 0xc5, 0xfc, 0xd4, 0x2b, 0x3d, 0xe8, 0xfc, 0x6a, 0xdf, 0x3a, 0xea, 0x74, 0xcc, 0x06, + 0x63, 0xeb, 0xb0, 0x1a, 0x77, 0x4f, 0x1d, 0xc8, 0xbe, 0x97, 0x44, 0xd9, 0x51, 0xc7, 0xdc, 0x6f, + 0x1f, 0x88, 0x17, 0x9c, 0x28, 0x5b, 0x16, 0xc3, 0x8e, 0xcb, 0x66, 0x87, 0xbd, 0xc2, 0x18, 0xd4, + 0xb5, 0xb7, 0xb2, 0xd3, 0x36, 0x1b, 0xab, 0x6c, 0x11, 0x2a, 0xfb, 0x47, 0x47, 0x56, 0xbf, 0xbb, + 0xdf, 0x39, 0x3c, 0xee, 0x37, 0xd6, 0xd8, 0x0a, 0x34, 0xba, 0x07, 0xfd, 0x8e, 0x29, 0xde, 0xb5, + 0xaa, 0xfa, 0xbf, 0x8b, 0x6c, 0x19, 0x16, 0xd5, 0x48, 0x15, 0xf4, 0xaf, 0x8a, 0x6c, 0x0d, 0xd8, + 0xf1, 0x81, 0xd9, 0x69, 0x6f, 0x8b, 0x85, 0x8b, 0x0a, 0xfe, 0x4f, 0x51, 0x7a, 0x48, 0x7e, 0x9a, + 0x8b, 0x0e, 0xeb, 0x38, 0xe4, 0x20, 0x79, 0x95, 0x6f, 0x55, 0xbb, 0x82, 0xf7, 0x65, 0x97, 0xec, + 0x6b, 0xaa, 0x55, 0x6e, 0x4e, 0xb5, 0x9a, 0xd3, 0xdd, 0x6b, 0xba, 0xec, 0xf7, 0x26, 0xd4, 0xc6, + 0x74, 0xad, 0xaf, 0xbc, 0xbe, 0x13, 0x64, 0xfc, 0x0d, 0x01, 0xe9, 0xee, 0xce, 0xb9, 0x5b, 0xe6, + 0x0b, 0xf3, 0xb7, 0xcc, 0xa7, 0xc9, 0xf7, 0x0b, 0x69, 0xf2, 0xfd, 0x43, 0x68, 0x12, 0x6b, 0x72, + 0x5c, 0x67, 0xac, 0xb4, 0x66, 0x92, 0x02, 0x17, 0x91, 0x45, 0x11, 0x5c, 0xa9, 0x13, 0x4a, 0xe5, + 0x90, 0x2c, 0xa4, 0x28, 0xb5, 0x8d, 0x84, 0xa6, 0x41, 0x9c, 0x23, 0xd2, 0x34, 0xa2, 0x1e, 0xec, + 0xab, 0xb8, 0x87, 0x8a, 0xd6, 0x03, 0xc1, 0xb1, 0x87, 0x87, 0xd0, 0xe4, 0x57, 0xa1, 0x6f, 0x5b, + 0xde, 0xc4, 0xfe, 0x7c, 0x8a, 0x2e, 0x5c, 0x1b, 0x75, 0xf8, 0xaa, 0xb9, 0x88, 0x05, 0x87, 0x08, + 0xdf, 0xb6, 0x43, 0xfb, 0xe1, 0x17, 0x50, 0xd1, 0xae, 0x7c, 0x66, 0x6b, 0xb0, 0xf4, 0x69, 0xb7, + 0x7f, 0xd0, 0xe9, 0xf5, 0xac, 0xa3, 0xe3, 0xcd, 0x67, 0x9d, 0xcf, 0xac, 0xdd, 0x76, 0x6f, 0xb7, + 0x71, 0x4b, 0x6c, 0xda, 0x83, 0x4e, 0xaf, 0xdf, 0xd9, 0x4e, 0xc0, 0x33, 0xec, 0x75, 0x58, 0x3f, + 0x3e, 0x38, 0xee, 0x75, 0xb6, 0xad, 0xb4, 0x7a, 0x59, 0x41, 0xa5, 0xb2, 0x3c, 0xa5, 0x7a, 0xee, + 0xe1, 0xf7, 0xa1, 0x9e, 0xbc, 0x87, 0x94, 0x01, 0x2c, 0xec, 0x75, 0x9e, 0xb6, 0xb7, 0x3e, 0xa3, + 0xfb, 0x07, 0x7b, 0xfd, 0x76, 0xbf, 0xbb, 0x65, 0xc9, 0xfb, 0x06, 0x05, 0x47, 0xc8, 0xb0, 0x0a, + 0x14, 0xdb, 0x07, 0x5b, 0xbb, 0x87, 0x66, 0xaf, 0x91, 0x7d, 0xf8, 0x11, 0x34, 0x66, 0xfd, 0x51, + 0x09, 0x07, 0xde, 0x8b, 0x3c, 0x7d, 0x0f, 0xff, 0x6d, 0x0e, 0x20, 0x4e, 0x18, 0x10, 0xac, 0x66, + 0xbb, 0xdd, 0x6f, 0xef, 0x1d, 0x8a, 0x69, 0x98, 0x87, 0x7d, 0xc1, 0x41, 0xcc, 0xce, 0xc7, 0x8d, + 0x5b, 0xa9, 0x25, 0x87, 0x47, 0xfd, 0x46, 0x46, 0xac, 0x58, 0xf7, 0xa0, 0xdb, 0xef, 0xb6, 0xf7, + 0x2c, 0xf3, 0xf0, 0xb8, 0x7b, 0xf0, 0x94, 0x2e, 0x56, 0x43, 0x2e, 0x7b, 0x7c, 0xb4, 0x63, 0x1e, + 0x1e, 0xf4, 0xad, 0xde, 0xee, 0x71, 0x7f, 0x1b, 0xaf, 0x65, 0xdb, 0x32, 0xbb, 0x47, 0xd4, 0x66, + 0xfe, 0x45, 0x08, 0xa2, 0xe9, 0x82, 0x58, 0xf3, 0xa7, 0x87, 0xbd, 0x5e, 0xf7, 0xc8, 0xfa, 0xf8, + 0xb8, 0x63, 0x76, 0x3b, 0x3d, 0xac, 0xb8, 0x90, 0x02, 0x17, 0xf8, 0x45, 0xc1, 0x9b, 0xfb, 0x7b, + 0x9f, 0x48, 0xe6, 0x29, 0x50, 0x4b, 0x49, 0x90, 0xc0, 0x2a, 0x0b, 0x9e, 0x22, 0xb8, 0x4f, 0x4a, + 0xcb, 0x70, 0x43, 0x99, 0xa8, 0x57, 0x11, 0x7c, 0x75, 0xee, 0x65, 0x60, 0xb5, 0x6a, 0x7a, 0x91, + 0xa8, 0x85, 0x2c, 0x37, 0x3a, 0xa0, 0xb6, 0xb7, 0x4d, 0xac, 0x50, 0x9f, 0x83, 0x0a, 0xdc, 0x45, + 0xf1, 0xa2, 0x04, 0x7b, 0x12, 0x28, 0x0d, 0xf5, 0x20, 0x4a, 0x9a, 0x4f, 0x7e, 0x2b, 0x07, 0x75, + 0x4a, 0xde, 0xa2, 0x2f, 0x6e, 0x71, 0x9f, 0xed, 0x43, 0x51, 0x7e, 0xba, 0x8d, 0xad, 0x44, 0x77, + 0x5e, 0xe9, 0x1f, 0x8b, 0x5b, 0x5f, 0x9d, 0x05, 0x4b, 0x71, 0x6c, 0xe9, 0xef, 0xfc, 0xe9, 0xff, + 0xfa, 0x27, 0xd9, 0x1a, 0xab, 0x3c, 0xba, 0x78, 0xef, 0xd1, 0x19, 0x77, 0x03, 0xd1, 0xc6, 0xdf, + 0x04, 0x88, 0x3f, 0x48, 0xc6, 0x5a, 0x91, 0x13, 0x6a, 0xe6, 0x6b, 0x6d, 0xeb, 0xb7, 0x53, 0x4a, + 0x64, 0xbb, 0xb7, 0xb1, 0xdd, 0x25, 0xa3, 0x2e, 0xda, 0x75, 0x5c, 0x27, 0xa4, 0x8f, 0x93, 0x7d, + 0x98, 0x79, 0xc8, 0x86, 0x50, 0xd5, 0x3f, 0x15, 0xc6, 0x94, 0xa4, 0x94, 0xf2, 0xb1, 0xb3, 0xf5, + 0x3b, 0xa9, 0x65, 0x4a, 0x06, 0xc5, 0x3e, 0x56, 0x8c, 0x86, 0xe8, 0x63, 0x8a, 0x18, 0x71, 0x2f, + 0x23, 0x92, 0xca, 0xe3, 0x2f, 0x82, 0xb1, 0xd7, 0x34, 0xb9, 0x6a, 0xee, 0x7b, 0x64, 0xeb, 0x77, + 0x6f, 0x28, 0x95, 0x7d, 0xdd, 0xc5, 0xbe, 0xd6, 0x0c, 0x26, 0xfa, 0x1a, 0x20, 0x8e, 0xfa, 0x1e, + 0xd9, 0x87, 0x99, 0x87, 0x4f, 0xfe, 0xf2, 0x01, 0x94, 0xa3, 0x60, 0x4e, 0xf6, 0x1b, 0x50, 0x4b, + 0x64, 0xd7, 0x31, 0x35, 0x8d, 0xb4, 0x64, 0xbc, 0xf5, 0xd7, 0xd2, 0x0b, 0x65, 0xc7, 0xaf, 0x63, + 0xc7, 0x2d, 0xb6, 0x2a, 0x3a, 0x96, 0xd9, 0x6b, 0x8f, 0x30, 0x1b, 0x96, 0x6e, 0x10, 0x7b, 0xae, + 0x69, 0x1f, 0xd4, 0xd9, 0x6b, 0xb3, 0x1a, 0x41, 0xa2, 0xb7, 0xbb, 0x37, 0x94, 0xca, 0xee, 0x5e, + 0xc3, 0xee, 0x56, 0xd9, 0xb2, 0xde, 0x9d, 0x0a, 0xbd, 0x64, 0x1c, 0x6f, 0xed, 0xd3, 0x3f, 0x98, + 0xc5, 0xee, 0xc6, 0x77, 0xac, 0xa5, 0x7c, 0x48, 0x2b, 0x22, 0x91, 0xf9, 0xaf, 0x69, 0x19, 0x2d, + 0xec, 0x8a, 0x31, 0x7c, 0x7d, 0xfa, 0xf7, 0xb2, 0xd8, 0x09, 0x54, 0xb4, 0x6f, 0x4c, 0xb0, 0xdb, + 0x37, 0x7e, 0x0f, 0x63, 0x7d, 0x3d, 0xad, 0x28, 0x6d, 0x2a, 0x7a, 0xfb, 0x8f, 0x4e, 0x39, 0x67, + 0xbf, 0x06, 0xe5, 0xe8, 0xcb, 0x05, 0x6c, 0x4d, 0xfb, 0x92, 0x84, 0xfe, 0xa5, 0x85, 0xf5, 0xd6, + 0x7c, 0x41, 0x1a, 0xf1, 0xe9, 0xad, 0x0b, 0xe2, 0xfb, 0x14, 0x2a, 0xda, 0xd7, 0x09, 0xa2, 0x09, + 0xcc, 0x7f, 0x01, 0x21, 0x9a, 0x40, 0xca, 0xc7, 0x0c, 0x8c, 0x26, 0x76, 0x51, 0x61, 0x65, 0xa4, + 0xef, 0xf0, 0xca, 0x0b, 0xd8, 0x1e, 0xac, 0x48, 0x4d, 0xeb, 0x84, 0x7f, 0x99, 0xd7, 0x90, 0xf2, + 0x8d, 0xb2, 0xc7, 0x19, 0xf6, 0x11, 0x94, 0xd4, 0x47, 0x28, 0xd8, 0x6a, 0xfa, 0xc7, 0x34, 0xd6, + 0xd7, 0xe6, 0xe0, 0x52, 0x2d, 0xfa, 0x0c, 0x20, 0xfe, 0x14, 0x42, 0xc4, 0x24, 0xe6, 0x3e, 0xad, + 0x10, 0x51, 0xc0, 0xfc, 0x77, 0x13, 0x8c, 0x55, 0x9c, 0x60, 0x83, 0x21, 0x93, 0x70, 0xf9, 0xa5, + 0xba, 0x5a, 0xf5, 0x47, 0x50, 0xd1, 0xbe, 0x86, 0x10, 0x2d, 0xdf, 0xfc, 0x97, 0x14, 0xa2, 0xe5, + 0x4b, 0xf9, 0x78, 0x82, 0xb1, 0x8e, 0xad, 0x2f, 0x1b, 0x8b, 0xa2, 0x75, 0x21, 0x6a, 0x49, 0x91, + 0x47, 0xbc, 0xa0, 0x73, 0xa8, 0x25, 0x3e, 0x79, 0x10, 0xed, 0xd0, 0xb4, 0x0f, 0x2a, 0x44, 0x3b, + 0x34, 0xf5, 0x2b, 0x09, 0x8a, 0xce, 0x8c, 0xa6, 0xe8, 0xe7, 0x02, 0x51, 0xb4, 0x9e, 0x7e, 0x08, + 0x15, 0xed, 0xf3, 0x05, 0xd1, 0x5c, 0xe6, 0xbf, 0x94, 0x10, 0xcd, 0x25, 0xed, 0x6b, 0x07, 0xcb, + 0xd8, 0x47, 0xdd, 0x40, 0x52, 0xc0, 0xcb, 0x21, 0x45, 0xdb, 0xbf, 0x01, 0xf5, 0xe4, 0x17, 0x0d, + 0xa2, 0xbd, 0x9f, 0xfa, 0x69, 0x84, 0x68, 0xef, 0xdf, 0xf0, 0x19, 0x04, 0x49, 0xd2, 0x0f, 0x97, + 0xa2, 0x4e, 0x1e, 0xfd, 0x44, 0xa6, 0xa5, 0x7c, 0xc1, 0x3e, 0x16, 0x0c, 0x4e, 0xde, 0x4d, 0xca, + 0xd6, 0x34, 0xaa, 0xd5, 0x2f, 0x39, 0x8d, 0xf6, 0xcb, 0xdc, 0x35, 0xa6, 0x49, 0x62, 0xc6, 0xc6, + 0xd9, 0x53, 0x58, 0x8a, 0x88, 0x39, 0xba, 0x6c, 0x34, 0x88, 0xe6, 0x90, 0x7a, 0xa5, 0xe9, 0x7a, + 0x63, 0xb6, 0xf4, 0x71, 0x86, 0x8e, 0x3f, 0xbc, 0xe2, 0x51, 0x3b, 0xfe, 0xf4, 0xfb, 0x46, 0xb5, + 0xe3, 0x2f, 0x71, 0x13, 0xe4, 0xec, 0xf1, 0x17, 0x3a, 0xa2, 0x0d, 0x17, 0x16, 0x67, 0xaf, 0xfe, + 0xbc, 0x7b, 0x53, 0xda, 0x3f, 0x35, 0xff, 0xfa, 0x8b, 0x6f, 0x05, 0x48, 0xb2, 0x22, 0xc5, 0x4d, + 0x1f, 0xc9, 0xe0, 0x13, 0xf6, 0xeb, 0x50, 0xd5, 0x6f, 0x41, 0x67, 0x3a, 0x4f, 0x98, 0xed, 0xe9, + 0x4e, 0x6a, 0x59, 0x92, 0x4a, 0x58, 0x55, 0xef, 0x86, 0x7d, 0x02, 0xab, 0xd1, 0x32, 0xeb, 0x79, + 0xeb, 0x01, 0xbb, 0x97, 0x92, 0xcd, 0x9e, 0x58, 0xec, 0xdb, 0x37, 0xa6, 0xbb, 0x3f, 0xce, 0x08, + 0xea, 0x4b, 0x5e, 0xc7, 0x1c, 0x9f, 0x3c, 0x69, 0xb7, 0x50, 0xc7, 0x27, 0x4f, 0xea, 0x1d, 0xce, + 0x8a, 0xfa, 0xd8, 0x52, 0x62, 0x8d, 0x28, 0x2c, 0x97, 0xfd, 0x10, 0x16, 0xb5, 0xa4, 0xfc, 0xde, + 0xb5, 0x3b, 0x88, 0x76, 0xd2, 0xfc, 0x7d, 0x82, 0xeb, 0x69, 0xb6, 0x49, 0x63, 0x0d, 0xdb, 0x6f, + 0x1a, 0x89, 0xc5, 0x11, 0xbb, 0x68, 0x0b, 0x2a, 0x7a, 0xc2, 0xff, 0x0b, 0xda, 0x5d, 0xd3, 0x8a, + 0xf4, 0xab, 0xeb, 0x1e, 0x67, 0xd8, 0x1e, 0x34, 0x66, 0x2f, 0xd2, 0x8a, 0x78, 0x4a, 0xda, 0xe5, + 0x5f, 0xeb, 0x33, 0x85, 0x89, 0xeb, 0xb7, 0xd8, 0x11, 0x25, 0x76, 0x44, 0x1f, 0xf4, 0xf2, 0xfc, + 0xd9, 0x53, 0x3d, 0xf9, 0xa1, 0xaf, 0xa8, 0xb5, 0xb4, 0x4f, 0xbc, 0x3d, 0xc8, 0x3c, 0xce, 0xb0, + 0xdf, 0xc9, 0x40, 0x35, 0x71, 0x3d, 0x4d, 0x22, 0x74, 0x7e, 0x66, 0x9e, 0x2d, 0xbd, 0x4c, 0x9f, + 0xa8, 0x61, 0xe2, 0x22, 0xee, 0x3d, 0xfc, 0x41, 0xe2, 0x25, 0xfd, 0x24, 0xe1, 0xda, 0xdb, 0x98, + 0xfd, 0xe2, 0xd7, 0x17, 0xb3, 0x08, 0xfa, 0x35, 0x91, 0x5f, 0x3c, 0xce, 0xb0, 0x7f, 0x97, 0x81, + 0x7a, 0xd2, 0x67, 0x1f, 0x4d, 0x37, 0x35, 0x3a, 0x20, 0x22, 0xa5, 0x1b, 0x1c, 0xfd, 0x3f, 0xc4, + 0x51, 0xf6, 0x1f, 0x9a, 0x89, 0x51, 0xca, 0x8b, 0xc4, 0x7f, 0xbe, 0xd1, 0xb2, 0x0f, 0xe9, 0x03, + 0x9b, 0x2a, 0x94, 0x89, 0xcd, 0x7f, 0x90, 0x31, 0x22, 0x3f, 0xfd, 0xf3, 0x85, 0xf8, 0x12, 0x7e, + 0x44, 0x5f, 0xb6, 0x52, 0x91, 0x31, 0x82, 0x8a, 0x5f, 0xb5, 0xbe, 0xf1, 0x16, 0xce, 0xe9, 0x75, + 0xe3, 0x76, 0x62, 0x4e, 0xb3, 0x82, 0x47, 0x9b, 0x46, 0x27, 0xbf, 0x3e, 0x18, 0x9f, 0x9c, 0x73, + 0x5f, 0x24, 0xbc, 0x79, 0x90, 0x63, 0x1a, 0xa4, 0x44, 0x4f, 0x6c, 0xb5, 0x57, 0x6c, 0xc6, 0x78, + 0x88, 0x63, 0x7d, 0xcb, 0xb8, 0x77, 0xe3, 0x58, 0x1f, 0xa1, 0xff, 0x5d, 0x8c, 0xf8, 0x08, 0x20, + 0x0e, 0x35, 0x64, 0x33, 0x01, 0x6f, 0x11, 0x03, 0x9a, 0x8f, 0x46, 0x4c, 0xee, 0x67, 0x15, 0x17, + 0x27, 0x5a, 0xfc, 0x35, 0x62, 0xa7, 0x51, 0x28, 0x9e, 0x2e, 0x7d, 0x25, 0xa3, 0x02, 0x13, 0xd2, + 0xd7, 0x6c, 0xfb, 0x09, 0x66, 0x1a, 0xc5, 0xdd, 0x1d, 0x43, 0x6d, 0xcf, 0xf3, 0x9e, 0x4f, 0x27, + 0x51, 0x78, 0x7b, 0x32, 0x28, 0x66, 0xd7, 0x0e, 0xce, 0xd7, 0x67, 0x66, 0x61, 0xdc, 0xc7, 0xa6, + 0xd6, 0x59, 0x4b, 0x6b, 0xea, 0xd1, 0x4f, 0xe2, 0xf8, 0xc6, 0x2f, 0x98, 0x0d, 0xcd, 0x88, 0x47, + 0xc7, 0x31, 0x84, 0xc9, 0x66, 0x12, 0x9c, 0x79, 0xb6, 0x8b, 0x84, 0x9a, 0xa0, 0x46, 0xfb, 0x28, + 0x50, 0x6d, 0x3e, 0xce, 0xb0, 0x23, 0xa8, 0x6e, 0xf3, 0x01, 0x26, 0xea, 0x63, 0x68, 0xc9, 0x52, + 0x22, 0x4c, 0x81, 0x62, 0x52, 0xd6, 0x6b, 0x09, 0x60, 0xf2, 0xdc, 0x9a, 0xd8, 0xd7, 0x3e, 0xff, + 0xfc, 0xd1, 0x4f, 0x64, 0xd0, 0xca, 0x17, 0xea, 0xdc, 0x52, 0x41, 0x3d, 0x89, 0x73, 0x6b, 0x26, + 0x0a, 0x28, 0x71, 0x6e, 0xcd, 0x45, 0x01, 0x25, 0x96, 0x5a, 0x05, 0x15, 0xb1, 0x11, 0x34, 0xe7, + 0x02, 0x87, 0xa2, 0x23, 0xeb, 0xa6, 0x70, 0xa3, 0xf5, 0xfb, 0x37, 0x23, 0x24, 0x7b, 0x7b, 0x98, + 0xec, 0xad, 0x07, 0x35, 0xba, 0xb9, 0xf2, 0x84, 0x53, 0xca, 0xde, 0xcc, 0x7d, 0x37, 0x7a, 0x3e, + 0xe0, 0xec, 0x01, 0x83, 0x65, 0x49, 0x09, 0x07, 0x73, 0xe5, 0xd8, 0xaf, 0x41, 0xe5, 0x29, 0x0f, + 0x55, 0x8e, 0x5e, 0x24, 0x63, 0xcf, 0x24, 0xed, 0xad, 0xa7, 0xa4, 0xf8, 0x25, 0x69, 0x06, 0x5b, + 0x7b, 0xc4, 0x87, 0x67, 0x9c, 0x98, 0x93, 0xe5, 0x0c, 0xbf, 0x60, 0xbf, 0x8a, 0x8d, 0x47, 0xa9, + 0xd1, 0xab, 0x5a, 0x12, 0x96, 0xde, 0xf8, 0xe2, 0x0c, 0x3c, 0xad, 0x65, 0xd7, 0x1b, 0x72, 0x4d, + 0xd6, 0x73, 0xa1, 0xa2, 0x5d, 0xa1, 0x10, 0x6d, 0xa0, 0xf9, 0x2b, 0x33, 0xa2, 0x0d, 0x94, 0x72, + 0xe3, 0x82, 0xf1, 0x00, 0xfb, 0x31, 0xd8, 0xfd, 0xb8, 0x1f, 0xba, 0x65, 0x21, 0xee, 0xe9, 0xd1, + 0x4f, 0xec, 0x71, 0xf8, 0x05, 0xfb, 0x14, 0xef, 0x87, 0xd7, 0x73, 0x10, 0x63, 0xa5, 0x61, 0x36, + 0x5d, 0x31, 0x5a, 0x2c, 0xad, 0x28, 0xa9, 0x48, 0x50, 0x57, 0x28, 0xc9, 0xbd, 0x0f, 0xd0, 0x0b, + 0xbd, 0xc9, 0xb6, 0xcd, 0xc7, 0x9e, 0x1b, 0xf3, 0xda, 0x38, 0x2b, 0x2e, 0xe6, 0x5f, 0x5a, 0x6a, + 0x1c, 0xfb, 0x54, 0xd3, 0xb2, 0x12, 0x69, 0x9c, 0x8a, 0xb8, 0x6e, 0x4c, 0x9c, 0x8b, 0x16, 0x24, + 0x25, 0x79, 0xee, 0x71, 0x86, 0xb5, 0x01, 0xe2, 0xc8, 0xb1, 0x48, 0x67, 0x9a, 0x0b, 0x4a, 0x8b, + 0xd8, 0x5e, 0x4a, 0x98, 0xd9, 0x11, 0x94, 0xe3, 0x90, 0x9b, 0xb5, 0xf8, 0x46, 0x98, 0x44, 0x80, + 0x4e, 0x74, 0x82, 0xcf, 0x85, 0xbb, 0x18, 0x0d, 0x5c, 0x2a, 0x60, 0x25, 0xb1, 0x54, 0xa7, 0x9c, + 0x07, 0xcc, 0x81, 0x25, 0x1a, 0x60, 0x24, 0x2e, 0x61, 0x36, 0x57, 0xf4, 0x19, 0x80, 0xf9, 0xc8, + 0x93, 0x68, 0x37, 0xa7, 0xc6, 0x4f, 0x24, 0x4c, 0x3f, 0x82, 0x5a, 0x29, 0x93, 0x4c, 0xb0, 0xe6, + 0x31, 0x34, 0xe7, 0x5c, 0xf4, 0xd1, 0x96, 0xbe, 0x29, 0xe6, 0x22, 0xda, 0xd2, 0x37, 0x7a, 0xf7, + 0x8d, 0x15, 0xec, 0x72, 0xd1, 0x00, 0x54, 0xf5, 0x2e, 0x9d, 0x70, 0x70, 0x2e, 0xba, 0xfb, 0xbd, + 0x0c, 0x2c, 0xa5, 0x38, 0xe1, 0xd9, 0x1b, 0xca, 0x6a, 0x70, 0xa3, 0x83, 0x7e, 0x3d, 0xd5, 0x59, + 0x6b, 0xf4, 0xb0, 0x9f, 0x7d, 0xf6, 0x2c, 0x71, 0xb0, 0x91, 0xaf, 0x54, 0xee, 0xcc, 0x17, 0x0a, + 0x15, 0xa9, 0x12, 0xc5, 0xe7, 0xb0, 0x46, 0x03, 0x69, 0x8f, 0x46, 0x33, 0x8e, 0xe4, 0xd7, 0xe7, + 0x3e, 0xc0, 0x9f, 0x70, 0x8e, 0xaf, 0xdf, 0xfc, 0x81, 0xfe, 0x1b, 0xc4, 0x69, 0x1a, 0x2a, 0x9b, + 0x42, 0x63, 0xd6, 0x41, 0xcb, 0x6e, 0x6e, 0x6b, 0xfd, 0x5e, 0x42, 0xff, 0x4d, 0x71, 0xea, 0x7e, + 0x0d, 0x3b, 0xbb, 0x67, 0xac, 0xa7, 0xad, 0x0b, 0xa9, 0xc4, 0xe2, 0x7d, 0xfc, 0xed, 0xc8, 0x9b, + 0x3c, 0x33, 0x4f, 0xd5, 0xc1, 0x4d, 0xbe, 0xef, 0x48, 0x03, 0x4f, 0x77, 0x46, 0xbf, 0x8d, 0xdd, + 0xdf, 0x37, 0xee, 0xa4, 0x75, 0xef, 0x53, 0x15, 0xd2, 0xc5, 0xd7, 0x66, 0xf7, 0xb5, 0x1a, 0xc1, + 0xfd, 0xb4, 0xf7, 0x7d, 0xa3, 0x2e, 0x34, 0xb3, 0xd6, 0xb7, 0x50, 0xb6, 0xab, 0xea, 0xde, 0xe3, + 0x68, 0xfb, 0xa4, 0xb8, 0xa9, 0xa3, 0xed, 0x93, 0xe6, 0x6e, 0x4e, 0xca, 0x35, 0xca, 0xd1, 0xfc, + 0x61, 0xe6, 0xe1, 0xe6, 0x3b, 0x3f, 0xfc, 0xda, 0x99, 0x13, 0x9e, 0x4f, 0x4f, 0x36, 0x06, 0xde, + 0xf8, 0xd1, 0x48, 0x59, 0x1b, 0x65, 0xca, 0xf3, 0xa3, 0x91, 0x3b, 0x7c, 0x84, 0xcd, 0x9e, 0x2c, + 0x4c, 0x7c, 0x2f, 0xf4, 0xbe, 0xf5, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x10, 0x0b, 0x84, 0xf3, + 0x63, 0x84, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index b508dad65c..59522ccce7 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2028,6 +2028,24 @@ message PendingChannelsResponse { /// Hash of the remote pending version of the commitment tx. string remote_pending_txid = 3; + + /* + The amount in satoshis calculated to be paid in fees for the local + commitment. + */ + uint64 local_commit_fee_sat = 4; + + /* + The amount in satoshis calculated to be paid in fees for the remote + commitment. + */ + uint64 remote_commit_fee_sat = 5; + + /* + The amount in satoshis calculated to be paid in fees for the remote + pending commitment. + */ + uint64 remote_pending_commit_fee_sat = 6; } message ClosedChannel { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index e534685ce8..65eb685abd 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1617,6 +1617,21 @@ "remote_pending_txid": { "type": "string", "description": "/ Hash of the remote pending version of the commitment tx." + }, + "local_commit_fee_sat": { + "type": "string", + "format": "uint64", + "description": "The amount in satoshis calculated to be paid in fees for the local\ncommitment." + }, + "remote_commit_fee_sat": { + "type": "string", + "format": "uint64", + "description": "The amount in satoshis calculated to be paid in fees for the remote\ncommitment." + }, + "remote_pending_commit_fee_sat": { + "type": "string", + "format": "uint64", + "description": "The amount in satoshis calculated to be paid in fees for the remote\npending commitment." } } }, diff --git a/rpcserver.go b/rpcserver.go index 5cf7b0c86c..1f039a7515 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2800,6 +2800,10 @@ func (r *rpcServer) PendingChannels(ctx context.Context, commitments.LocalTxid = waitingClose.LocalCommitment.CommitTx.TxHash(). String() + + commitments.LocalCommitFeeSat = uint64( + waitingClose.LocalCommitment.CommitFee, + ) } // Report remote commit. May not be present when DLP is active. @@ -2807,6 +2811,10 @@ func (r *rpcServer) PendingChannels(ctx context.Context, commitments.RemoteTxid = waitingClose.RemoteCommitment.CommitTx.TxHash(). String() + + commitments.RemoteCommitFeeSat = uint64( + waitingClose.RemoteCommitment.CommitFee, + ) } // Report the remote pending commit if any. @@ -2826,7 +2834,9 @@ func (r *rpcServer) PendingChannels(ctx context.Context, default: hash := remoteCommitDiff.Commitment.CommitTx.TxHash() commitments.RemotePendingTxid = hash.String() - + commitments.RemoteCommitFeeSat = uint64( + remoteCommitDiff.Commitment.CommitFee, + ) } channel := &lnrpc.PendingChannelsResponse_PendingChannel{ From 9e1cdb78e7db60558ae016465652f30e33af2097 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 25 Mar 2020 08:41:00 +0200 Subject: [PATCH 299/562] lnrpc: deprecate unused pending closing channels field The pending closing channels field was present to cover an edge case where coperatively closed channels were closed before upgrade and confirmed after the upgrade. This commit deprecates the field and adds a warning log to cover these edge cases. --- lnrpc/rpc.pb.go | 1394 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 8 +- lnrpc/rpc.swagger.json | 2 +- rpcserver.go | 23 +- 4 files changed, 714 insertions(+), 713 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 0a5fa13110..4203c5fb12 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -5469,8 +5469,11 @@ type PendingChannelsResponse struct { TotalLimboBalance int64 `protobuf:"varint,1,opt,name=total_limbo_balance,json=totalLimboBalance,proto3" json:"total_limbo_balance,omitempty"` /// Channels pending opening PendingOpenChannels []*PendingChannelsResponse_PendingOpenChannel `protobuf:"bytes,2,rep,name=pending_open_channels,json=pendingOpenChannels,proto3" json:"pending_open_channels,omitempty"` - /// Channels pending closing - PendingClosingChannels []*PendingChannelsResponse_ClosedChannel `protobuf:"bytes,3,rep,name=pending_closing_channels,json=pendingClosingChannels,proto3" json:"pending_closing_channels,omitempty"` + // + //Deprecated: Channels pending closing previously contained cooperatively + //closed channels with a single confirmation. These channels are now + //considered closed from the time we see them on chain. + PendingClosingChannels []*PendingChannelsResponse_ClosedChannel `protobuf:"bytes,3,rep,name=pending_closing_channels,json=pendingClosingChannels,proto3" json:"pending_closing_channels,omitempty"` // Deprecated: Do not use. /// Channels pending force closing PendingForceClosingChannels []*PendingChannelsResponse_ForceClosedChannel `protobuf:"bytes,4,rep,name=pending_force_closing_channels,json=pendingForceClosingChannels,proto3" json:"pending_force_closing_channels,omitempty"` /// Channels waiting for closing tx to confirm @@ -5519,6 +5522,7 @@ func (m *PendingChannelsResponse) GetPendingOpenChannels() []*PendingChannelsRes return nil } +// Deprecated: Do not use. func (m *PendingChannelsResponse) GetPendingClosingChannels() []*PendingChannelsResponse_ClosedChannel { if m != nil { return m.PendingClosingChannels @@ -11408,13 +11412,13 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11444 bytes of a gzipped FileDescriptorProto + // 11447 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x23, 0x57, 0x76, 0xd8, 0xf0, 0xd5, 0x24, 0x0f, 0x1f, 0x4d, 0xde, 0x7e, 0x71, 0x7a, 0x34, 0x9a, 0x51, 0x49, 0x2b, 0xcd, 0x8e, 0x76, 0x7b, 0x46, 0xb3, 0x2b, 0xed, 0x5a, 0x8a, 0xd7, 0xcb, 0xee, 0x66, 0x4f, 0x73, 0xa7, 0x5f, 0x2a, 0xb2, 0x25, 0x6b, 0x1d, 0xa7, 0xb6, 0x9a, 0xbc, 0xdd, 0x5d, 0x1e, 0xb2, 0x8a, 0xaa, 0x2a, 0xf6, 0x63, 0x17, 0xca, 0x87, 0x20, 0x31, 0x82, 0x20, 0x09, 0x60, 0x24, 0x0e, - 0x10, 0x27, 0x46, 0x82, 0x18, 0x81, 0x11, 0x04, 0x30, 0x0c, 0xac, 0x03, 0x24, 0x40, 0xbe, 0xfb, + 0x10, 0x27, 0x46, 0x82, 0x18, 0x41, 0x10, 0x18, 0x30, 0x0c, 0xac, 0x03, 0x24, 0x40, 0xbe, 0xfb, 0x4b, 0x02, 0x23, 0xb0, 0xf3, 0x25, 0x30, 0x0c, 0x18, 0x49, 0x9c, 0x6f, 0x81, 0x7f, 0x42, 0x70, 0xcf, 0xb9, 0xb7, 0xea, 0x16, 0x59, 0x3d, 0x33, 0xda, 0x55, 0xf6, 0x4b, 0x37, 0xeb, 0xdc, 0x73, 0x9f, 0x75, 0xee, 0xb9, 0xe7, 0x79, 0x0b, 0xca, 0xfe, 0x64, 0xb0, 0x31, 0xf1, 0xbd, 0xd0, 0x63, @@ -11434,697 +11438,697 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0x98, 0x75, 0x05, 0xfe, 0x14, 0xa1, 0x6c, 0x13, 0x16, 0x07, 0xe7, 0xb6, 0xeb, 0xf2, 0x91, 0x75, 0x62, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xab, 0x70, 0x3f, 0xf3, 0xa0, 0xf2, 0xe4, 0xf6, 0x06, 0xbe, 0xd5, 0x8d, 0xad, 0x73, 0xdb, 0xdd, 0xc4, 0x92, 0x9e, 0x6b, 0x4f, 0x82, 0x73, 0x2f, 0x34, 0xeb, - 0xb2, 0x06, 0x81, 0x03, 0x63, 0x19, 0x98, 0xbe, 0x12, 0xb4, 0xf6, 0xc6, 0xbf, 0xcf, 0xc0, 0xd2, - 0xb1, 0x3b, 0xf2, 0x06, 0xcf, 0x7f, 0xc6, 0x25, 0x4a, 0x99, 0x43, 0xf6, 0x55, 0xe7, 0x90, 0xfb, - 0xb2, 0x73, 0x58, 0x85, 0xe5, 0xe4, 0x60, 0xe5, 0x2c, 0x38, 0xac, 0x88, 0xda, 0x67, 0x5c, 0x0d, - 0x4b, 0x4d, 0xe3, 0xeb, 0xd0, 0x18, 0x4c, 0x7d, 0x9f, 0xbb, 0x73, 0xf3, 0x58, 0x94, 0xf0, 0x68, - 0x22, 0x6f, 0x40, 0xd5, 0xe5, 0x97, 0x31, 0x9a, 0xa4, 0x5d, 0x97, 0x5f, 0x2a, 0x14, 0xa3, 0x05, - 0xab, 0xb3, 0xdd, 0xc8, 0x01, 0xfc, 0x55, 0x06, 0xf2, 0xc7, 0xe1, 0x95, 0xc7, 0xde, 0x87, 0xaa, - 0x3d, 0x1c, 0xfa, 0x3c, 0x08, 0xac, 0xf0, 0x7a, 0x42, 0x3b, 0xa5, 0xfe, 0x84, 0xc9, 0x29, 0xb6, - 0xa9, 0xa8, 0x7f, 0x3d, 0xe1, 0x66, 0xc5, 0x8e, 0x1f, 0x58, 0x0b, 0x8a, 0xf2, 0x11, 0xfb, 0x2d, - 0x9b, 0xea, 0x91, 0xdd, 0x05, 0xb0, 0xc7, 0xde, 0xd4, 0x0d, 0xad, 0xc0, 0x0e, 0x71, 0xc5, 0x72, - 0x66, 0x99, 0x20, 0x3d, 0x3b, 0x64, 0x77, 0xa0, 0x3c, 0x79, 0x6e, 0x05, 0x03, 0xdf, 0x99, 0x84, - 0x48, 0x3c, 0x65, 0xb3, 0x34, 0x79, 0xde, 0xc3, 0x67, 0xf6, 0x2e, 0x94, 0xbc, 0x69, 0x38, 0xf1, - 0x1c, 0x37, 0x94, 0xf4, 0xb2, 0x28, 0x07, 0x72, 0x38, 0x0d, 0x8f, 0x04, 0xd8, 0x8c, 0x10, 0xd8, - 0x5b, 0x50, 0x1b, 0x78, 0xee, 0xa9, 0xe3, 0x8f, 0x89, 0x23, 0xb4, 0x16, 0xb0, 0xaf, 0x24, 0xd0, - 0xf8, 0xc3, 0x2c, 0x54, 0xfa, 0xbe, 0xed, 0x06, 0xf6, 0x40, 0x00, 0xd8, 0x1a, 0x14, 0xc3, 0x2b, - 0xeb, 0xdc, 0x0e, 0xce, 0x71, 0xaa, 0x65, 0x73, 0x21, 0xbc, 0xda, 0xb5, 0x83, 0x73, 0xb6, 0x0a, - 0x0b, 0x34, 0x4a, 0x9c, 0x50, 0xce, 0x94, 0x4f, 0x62, 0x83, 0xb8, 0xd3, 0xb1, 0x95, 0xec, 0x2a, - 0x87, 0x14, 0xd3, 0x70, 0xa7, 0xe3, 0x2d, 0x1d, 0x2e, 0x26, 0x7f, 0x22, 0x5e, 0x37, 0x75, 0x40, - 0xd3, 0x2b, 0x23, 0x04, 0xfb, 0x78, 0x03, 0xaa, 0xb2, 0x98, 0x3b, 0x67, 0xe7, 0x34, 0xc7, 0x82, - 0x59, 0x21, 0x04, 0x04, 0x89, 0x16, 0x42, 0x67, 0xcc, 0xad, 0x20, 0xb4, 0xc7, 0x13, 0x39, 0xa5, - 0xb2, 0x80, 0xf4, 0x04, 0x00, 0x8b, 0xbd, 0xd0, 0x1e, 0x59, 0xa7, 0x9c, 0x07, 0xad, 0xa2, 0x2c, - 0x16, 0x90, 0x1d, 0xce, 0x03, 0xf6, 0x35, 0xa8, 0x0f, 0x79, 0x10, 0x5a, 0xf2, 0x65, 0xf0, 0xa0, - 0x55, 0xc2, 0x9d, 0x5f, 0x13, 0xd0, 0xb6, 0x02, 0xb2, 0xd7, 0x00, 0x7c, 0xfb, 0xd2, 0x12, 0x0b, - 0xc1, 0xaf, 0x5a, 0x65, 0x7a, 0x0b, 0xbe, 0x7d, 0xd9, 0xbf, 0xda, 0xe5, 0x57, 0x82, 0x6a, 0x9e, - 0xf2, 0x50, 0x5b, 0xb4, 0x40, 0x52, 0xa7, 0xb1, 0x07, 0x4c, 0x03, 0x6f, 0xf3, 0xd0, 0x76, 0x46, - 0x01, 0xfb, 0x00, 0xaa, 0xa1, 0x86, 0x8c, 0x6c, 0xb0, 0x12, 0x91, 0x90, 0x56, 0xc1, 0x4c, 0xe0, - 0x19, 0xe7, 0x50, 0xda, 0xe1, 0x7c, 0xcf, 0x19, 0x3b, 0x21, 0x5b, 0x85, 0xc2, 0xa9, 0x73, 0xc5, - 0x89, 0xd8, 0x73, 0xbb, 0xb7, 0x4c, 0x7a, 0x64, 0xf7, 0x00, 0xf0, 0x87, 0x35, 0x8e, 0xa8, 0x69, - 0xf7, 0x96, 0x59, 0x46, 0xd8, 0x7e, 0x60, 0x87, 0x6c, 0x1d, 0x8a, 0x13, 0xee, 0x0f, 0xb8, 0x7a, - 0x6f, 0xbb, 0xb7, 0x4c, 0x05, 0xd8, 0x2c, 0x42, 0x61, 0x24, 0x5a, 0x37, 0xfe, 0xb8, 0x00, 0x95, - 0x1e, 0x77, 0xa3, 0x5d, 0xc6, 0x20, 0x2f, 0x16, 0x44, 0xee, 0x2c, 0xfc, 0xcd, 0xde, 0x84, 0x0a, - 0x2e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x46, 0x54, 0xbd, 0x99, 0x6d, 0x65, 0x4c, 0x10, 0xe0, 0x1e, - 0x42, 0x59, 0x03, 0x72, 0xf6, 0x58, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x43, 0xc9, 0x1e, 0x87, 0x34, - 0xbc, 0x2a, 0x82, 0x8b, 0xf6, 0x38, 0xc4, 0xa1, 0xbd, 0x01, 0xd5, 0x89, 0x7d, 0x3d, 0x16, 0x7b, - 0x39, 0x22, 0x87, 0xaa, 0x59, 0x91, 0x30, 0x24, 0x88, 0x27, 0xb0, 0xa4, 0xa3, 0xa8, 0xce, 0x0b, - 0x51, 0xe7, 0x4d, 0x0d, 0x5b, 0x8e, 0xe1, 0x1d, 0x58, 0x54, 0x75, 0x7c, 0x9a, 0x0f, 0x92, 0x49, - 0xd9, 0xac, 0x4b, 0xb0, 0x9a, 0xe5, 0x03, 0x68, 0x9c, 0x3a, 0xae, 0x3d, 0xb2, 0x06, 0xa3, 0xf0, - 0xc2, 0x1a, 0xf2, 0x51, 0x68, 0x23, 0xc5, 0x14, 0xcc, 0x3a, 0xc2, 0xb7, 0x46, 0xe1, 0xc5, 0xb6, - 0x80, 0xb2, 0x6f, 0x40, 0xf9, 0x94, 0x73, 0x0b, 0x17, 0xab, 0x55, 0x4a, 0x6c, 0x3c, 0xf5, 0x86, - 0xcc, 0xd2, 0xa9, 0x7a, 0x57, 0xdf, 0x80, 0x86, 0x37, 0x0d, 0xcf, 0x3c, 0xc7, 0x3d, 0xb3, 0x04, - 0xbf, 0xb3, 0x9c, 0x21, 0xd2, 0x50, 0x7e, 0x33, 0xfb, 0x38, 0x63, 0xd6, 0x55, 0x99, 0xe0, 0x3c, - 0xdd, 0x21, 0x7b, 0x1b, 0x16, 0x47, 0x76, 0x10, 0x5a, 0xe7, 0xde, 0xc4, 0x9a, 0x4c, 0x4f, 0x9e, - 0xf3, 0xeb, 0x56, 0x0d, 0x17, 0xa2, 0x26, 0xc0, 0xbb, 0xde, 0xe4, 0x08, 0x81, 0x82, 0xb2, 0x71, - 0x9c, 0x34, 0x08, 0xb8, 0x9f, 0x79, 0x50, 0x33, 0xcb, 0x02, 0x42, 0x9d, 0x7e, 0x06, 0x4b, 0xf8, - 0x7a, 0x06, 0xd3, 0x20, 0xf4, 0xc6, 0x96, 0xe0, 0xd5, 0xfe, 0x30, 0x68, 0x55, 0x90, 0xd6, 0xbe, - 0x2e, 0x07, 0xab, 0xbd, 0xe3, 0x8d, 0x6d, 0x1e, 0x84, 0x5b, 0x88, 0x6c, 0x12, 0xae, 0x38, 0xd0, - 0xaf, 0xcd, 0xe6, 0x70, 0x16, 0xce, 0xbe, 0x01, 0xcc, 0x1e, 0x8d, 0xbc, 0x4b, 0x2b, 0xe0, 0xa3, - 0x53, 0x4b, 0x2e, 0x62, 0xab, 0x7e, 0x3f, 0xf3, 0xa0, 0x64, 0x36, 0xb0, 0xa4, 0xc7, 0x47, 0xa7, - 0x47, 0x04, 0x67, 0x1f, 0x00, 0x6e, 0x26, 0xeb, 0x94, 0xdb, 0xe1, 0xd4, 0xe7, 0x41, 0x6b, 0xf1, - 0x7e, 0xee, 0x41, 0xfd, 0x49, 0x33, 0x5a, 0x2f, 0x04, 0x6f, 0x3a, 0xa1, 0x59, 0x15, 0x78, 0xf2, - 0x39, 0x58, 0xdf, 0x86, 0xd5, 0xf4, 0x21, 0x09, 0xa2, 0x12, 0xab, 0x22, 0x88, 0x31, 0x6f, 0x8a, - 0x9f, 0x6c, 0x19, 0x0a, 0x17, 0xf6, 0x68, 0xca, 0x25, 0x4f, 0xa7, 0x87, 0x0f, 0xb3, 0xdf, 0xcd, - 0x18, 0x7f, 0x94, 0x81, 0x2a, 0xcd, 0x52, 0xca, 0x22, 0x6f, 0x42, 0x4d, 0x51, 0x03, 0xf7, 0x7d, - 0xcf, 0x97, 0x5c, 0x4d, 0x51, 0x5e, 0x47, 0xc0, 0xc4, 0xa9, 0xa2, 0x90, 0x26, 0x3e, 0x77, 0xc6, - 0xf6, 0x99, 0x6a, 0x5a, 0x91, 0xd2, 0x91, 0x04, 0xb3, 0xf7, 0xe2, 0xf6, 0x7c, 0x6f, 0x1a, 0x72, - 0x79, 0xe6, 0x55, 0xe5, 0xf4, 0x4c, 0x01, 0x8b, 0x5a, 0xc7, 0xa7, 0x57, 0xa0, 0x73, 0xe3, 0xb7, - 0x33, 0xc0, 0xc4, 0xb0, 0xfb, 0x1e, 0x35, 0x20, 0x29, 0x74, 0xb6, 0x66, 0xe6, 0x95, 0x77, 0x48, - 0xf6, 0x45, 0x3b, 0xc4, 0x80, 0x02, 0x8d, 0x3d, 0x9f, 0x32, 0x76, 0x2a, 0xfa, 0x41, 0xbe, 0x94, - 0x6b, 0xe4, 0x8d, 0xff, 0x91, 0x83, 0xe5, 0x2d, 0x3a, 0xb2, 0xdb, 0x83, 0x01, 0x9f, 0x44, 0x7b, - 0xe7, 0x1e, 0x54, 0x5c, 0x6f, 0xc8, 0x15, 0xc5, 0xd2, 0xc0, 0x40, 0x80, 0x34, 0x72, 0x3d, 0xb7, - 0x1d, 0x97, 0x06, 0x4e, 0x8b, 0x59, 0x46, 0x08, 0x0e, 0xfb, 0x6d, 0x58, 0x9c, 0x70, 0x77, 0xa8, - 0x6f, 0x11, 0x12, 0xaa, 0x6a, 0x12, 0x2c, 0x77, 0xc7, 0x3d, 0xa8, 0x9c, 0x4e, 0x09, 0x4f, 0x30, - 0x96, 0x3c, 0xd2, 0x00, 0x48, 0x50, 0x9b, 0xf8, 0xcb, 0x64, 0x1a, 0x9c, 0x63, 0x69, 0x01, 0x4b, - 0x8b, 0xe2, 0x59, 0x14, 0xdd, 0x05, 0x18, 0x4e, 0x83, 0x50, 0xee, 0x98, 0x05, 0x2c, 0x2c, 0x0b, - 0x08, 0xed, 0x98, 0x6f, 0xc2, 0xd2, 0xd8, 0xbe, 0xb2, 0x90, 0x76, 0x2c, 0xc7, 0xb5, 0x4e, 0x47, - 0x78, 0xe6, 0x14, 0x11, 0xaf, 0x31, 0xb6, 0xaf, 0x3e, 0x11, 0x25, 0x5d, 0x77, 0x07, 0xe1, 0x82, - 0xad, 0x28, 0x71, 0xc7, 0xe7, 0x01, 0xf7, 0x2f, 0x38, 0x72, 0x82, 0x7c, 0x24, 0xd3, 0x98, 0x04, - 0x15, 0x23, 0x1a, 0x8b, 0x79, 0x87, 0xa3, 0x01, 0x6d, 0x7b, 0xb3, 0x38, 0x76, 0xdc, 0xdd, 0x70, - 0x34, 0x10, 0xe7, 0x8a, 0xe0, 0x23, 0x13, 0xee, 0x5b, 0xcf, 0x2f, 0x71, 0x0f, 0xe7, 0x91, 0x6f, - 0x1c, 0x71, 0xff, 0xd9, 0xa5, 0x38, 0xfa, 0x07, 0x01, 0x32, 0x22, 0xfb, 0xba, 0x55, 0xc1, 0x0d, - 0x5e, 0x1a, 0x04, 0x82, 0x05, 0xd9, 0xd7, 0x62, 0x13, 0x8a, 0xd1, 0xda, 0xf8, 0x16, 0xf8, 0x10, - 0x9b, 0x0f, 0x90, 0xa3, 0xd6, 0x70, 0xb0, 0x6d, 0x59, 0x20, 0xfa, 0x09, 0x04, 0xd5, 0xab, 0xc1, - 0x9e, 0x8e, 0xec, 0xb3, 0x00, 0x59, 0x4a, 0xcd, 0xac, 0x4a, 0xe0, 0x8e, 0x80, 0x19, 0x9f, 0x92, - 0x90, 0xa5, 0xbd, 0x5b, 0xb9, 0x67, 0xc4, 0x51, 0x8f, 0x10, 0x7c, 0xaf, 0x25, 0x53, 0x3e, 0xa5, - 0xbd, 0xb4, 0x6c, 0xca, 0x4b, 0x33, 0x7e, 0x37, 0x03, 0x55, 0xd9, 0x32, 0x0a, 0x25, 0x6c, 0x03, - 0x98, 0x7a, 0x8b, 0xe1, 0x95, 0x33, 0xb4, 0x4e, 0xae, 0x43, 0x1e, 0x10, 0xd1, 0xec, 0xde, 0x32, - 0x1b, 0xb2, 0xac, 0x7f, 0xe5, 0x0c, 0x37, 0x45, 0x09, 0x7b, 0x08, 0x8d, 0x04, 0x7e, 0x10, 0xfa, - 0x44, 0xd1, 0xbb, 0xb7, 0xcc, 0xba, 0x86, 0xdd, 0x0b, 0x7d, 0xb1, 0x47, 0x84, 0xc8, 0x33, 0x0d, - 0x2d, 0xc7, 0x1d, 0xf2, 0x2b, 0x24, 0xa3, 0x9a, 0x59, 0x21, 0x58, 0x57, 0x80, 0x36, 0xeb, 0x50, - 0xd5, 0x9b, 0x33, 0xce, 0xa0, 0xa4, 0xe4, 0x25, 0x14, 0x18, 0x66, 0x86, 0x64, 0x96, 0xc3, 0x68, - 0x24, 0xb7, 0xa1, 0x94, 0x1c, 0x81, 0x59, 0x0c, 0x5f, 0xb9, 0x63, 0xe3, 0x7b, 0xd0, 0xd8, 0x13, - 0xc4, 0xe3, 0x0a, 0x62, 0x95, 0xf2, 0xdf, 0x2a, 0x2c, 0x68, 0x9b, 0xa6, 0x6c, 0xca, 0x27, 0x71, - 0xe6, 0x9e, 0x7b, 0x41, 0x28, 0x7b, 0xc1, 0xdf, 0xc6, 0x1f, 0x67, 0x80, 0x75, 0x82, 0xd0, 0x19, - 0xdb, 0x21, 0xdf, 0xe1, 0x11, 0x5b, 0x38, 0x84, 0xaa, 0x68, 0xad, 0xef, 0xb5, 0x49, 0x20, 0x23, - 0x81, 0xe2, 0x5d, 0xb9, 0x8d, 0xe7, 0x2b, 0x6c, 0xe8, 0xd8, 0xc4, 0xe6, 0x13, 0x0d, 0x88, 0x5d, - 0x16, 0xda, 0xfe, 0x19, 0x0f, 0x51, 0x8c, 0x93, 0xf2, 0x3e, 0x10, 0x48, 0x08, 0x70, 0xeb, 0xbf, - 0x02, 0xcd, 0xb9, 0x36, 0x74, 0xbe, 0x5c, 0x4e, 0xe1, 0xcb, 0x39, 0x9d, 0x2f, 0x5b, 0xb0, 0x94, - 0x18, 0x97, 0xa4, 0xb4, 0x35, 0x28, 0x8a, 0x0d, 0x21, 0x84, 0x83, 0x0c, 0x49, 0x95, 0xa7, 0x9c, - 0x0b, 0x31, 0xf8, 0x11, 0x2c, 0x9f, 0x72, 0xee, 0xdb, 0x21, 0x16, 0xe2, 0x8e, 0x11, 0x6f, 0x48, - 0x36, 0xdc, 0x94, 0x65, 0x3d, 0x3b, 0x3c, 0xe2, 0xbe, 0x78, 0x53, 0xc6, 0xff, 0xcc, 0xc0, 0xa2, - 0xe0, 0xa0, 0xfb, 0xb6, 0x7b, 0xad, 0xd6, 0x69, 0x2f, 0x75, 0x9d, 0x1e, 0x68, 0x87, 0xa1, 0x86, - 0xfd, 0x65, 0x17, 0x29, 0x37, 0xbb, 0x48, 0xec, 0x3e, 0x54, 0x13, 0x63, 0x2d, 0xe0, 0x58, 0x21, - 0x88, 0x06, 0xf9, 0xf3, 0x2f, 0xe3, 0xdb, 0xd0, 0x88, 0x87, 0x2d, 0xd7, 0x90, 0x41, 0x5e, 0x90, - 0xa4, 0x6c, 0x00, 0x7f, 0x1b, 0xff, 0x32, 0x43, 0x88, 0x5b, 0x9e, 0x13, 0x49, 0xa7, 0x02, 0x51, - 0xc8, 0xbd, 0x0a, 0x51, 0xfc, 0xbe, 0x51, 0xaa, 0xff, 0xf9, 0x27, 0x2b, 0xb6, 0x4e, 0xc0, 0xdd, - 0xa1, 0x65, 0x8f, 0x46, 0xc8, 0x7c, 0x4b, 0x66, 0x51, 0x3c, 0xb7, 0x47, 0x23, 0xe3, 0x1d, 0x68, - 0x6a, 0xa3, 0x7b, 0xc1, 0x3c, 0x0e, 0x80, 0xed, 0x39, 0x41, 0x78, 0xec, 0x06, 0x13, 0x4d, 0x70, - 0xbb, 0x03, 0x65, 0xc1, 0x61, 0xc5, 0xc8, 0x68, 0xcb, 0x16, 0x4c, 0xc1, 0x72, 0xc5, 0xb8, 0x02, - 0x2c, 0xb4, 0xaf, 0x64, 0x61, 0x56, 0x16, 0xda, 0x57, 0x58, 0x68, 0x7c, 0x17, 0x96, 0x12, 0xed, - 0xc9, 0xae, 0xdf, 0x80, 0xc2, 0x34, 0xbc, 0xf2, 0x94, 0x68, 0x5e, 0x91, 0x14, 0x22, 0x14, 0x40, - 0x93, 0x4a, 0x8c, 0x8f, 0xa0, 0x79, 0xc0, 0x2f, 0xe5, 0x26, 0x56, 0x03, 0x79, 0x1b, 0xf2, 0x2f, - 0x51, 0x0a, 0xb1, 0xdc, 0xd8, 0x00, 0xa6, 0x57, 0x96, 0xbd, 0x6a, 0x3a, 0x62, 0x26, 0xa1, 0x23, - 0x1a, 0x6f, 0x03, 0xeb, 0x39, 0x67, 0xee, 0x3e, 0x0f, 0x02, 0xfb, 0x2c, 0xda, 0xf6, 0x0d, 0xc8, - 0x8d, 0x83, 0x33, 0xc9, 0xa3, 0xc4, 0x4f, 0xe3, 0x5b, 0xb0, 0x94, 0xc0, 0x93, 0x0d, 0xbf, 0x06, - 0xe5, 0xc0, 0x39, 0x73, 0x51, 0xb0, 0x92, 0x4d, 0xc7, 0x00, 0x63, 0x07, 0x96, 0x3f, 0xe1, 0xbe, - 0x73, 0x7a, 0xfd, 0xb2, 0xe6, 0x93, 0xed, 0x64, 0x67, 0xdb, 0xe9, 0xc0, 0xca, 0x4c, 0x3b, 0xb2, - 0x7b, 0x22, 0x5f, 0xf9, 0x26, 0x4b, 0x26, 0x3d, 0x68, 0x7c, 0x2f, 0xab, 0xf3, 0x3d, 0xe3, 0x18, - 0xd8, 0x96, 0xe7, 0xba, 0x7c, 0x10, 0x1e, 0x71, 0xee, 0xc7, 0x56, 0xaa, 0x98, 0x56, 0x2b, 0x4f, - 0xd6, 0xe4, 0xca, 0xce, 0x32, 0x53, 0x49, 0xc4, 0x0c, 0xf2, 0x13, 0xee, 0x8f, 0xb1, 0xe1, 0x92, - 0x89, 0xbf, 0x8d, 0x15, 0x58, 0x4a, 0x34, 0x2b, 0xf5, 0xfa, 0xc7, 0xb0, 0xb2, 0xed, 0x04, 0x83, - 0xf9, 0x0e, 0xd7, 0xa0, 0x38, 0x99, 0x9e, 0x58, 0x49, 0xbe, 0xfc, 0x8c, 0x5f, 0x0b, 0x6d, 0x6f, - 0xb6, 0x86, 0x6c, 0xeb, 0xef, 0x66, 0x20, 0xbf, 0xdb, 0xdf, 0xdb, 0x62, 0xeb, 0x50, 0x72, 0xdc, - 0x81, 0x37, 0x16, 0x82, 0x17, 0xcd, 0x39, 0x7a, 0xbe, 0x71, 0x83, 0xdd, 0x81, 0x32, 0xca, 0x6b, - 0x42, 0xb5, 0x95, 0xa2, 0x4f, 0x49, 0x00, 0xf6, 0xbc, 0xc1, 0x73, 0xa1, 0x53, 0xf3, 0xab, 0x89, - 0xe3, 0xa3, 0xd6, 0xac, 0x94, 0xe1, 0x3c, 0x9d, 0xf5, 0x71, 0x01, 0x69, 0xc4, 0xc6, 0x7f, 0x2a, - 0x41, 0x51, 0x9e, 0xb6, 0x74, 0x72, 0x87, 0xce, 0x05, 0x8f, 0x4f, 0x6e, 0xf1, 0x24, 0xe4, 0x01, - 0x9f, 0x8f, 0xbd, 0x30, 0x12, 0xd8, 0xe8, 0x1d, 0x54, 0x09, 0x28, 0x45, 0x36, 0x4d, 0x68, 0x20, - 0x13, 0x43, 0x8e, 0x90, 0x06, 0xfa, 0x51, 0x7e, 0x07, 0x8a, 0xea, 0xec, 0xcf, 0x47, 0x3a, 0xcd, - 0xc2, 0x80, 0xa4, 0xb5, 0x75, 0x28, 0x0d, 0xec, 0x89, 0x3d, 0x70, 0xc2, 0x6b, 0xc9, 0x10, 0xa2, - 0x67, 0xd1, 0xfa, 0xc8, 0x1b, 0xd8, 0x23, 0xeb, 0xc4, 0x1e, 0xd9, 0xee, 0x80, 0x4b, 0xdd, 0xbd, - 0x8a, 0xc0, 0x4d, 0x82, 0x09, 0xfd, 0x5c, 0x8e, 0x53, 0x61, 0x91, 0x0a, 0x2f, 0x47, 0xaf, 0xd0, - 0x84, 0x70, 0xe9, 0x8d, 0xc7, 0x8e, 0xd0, 0x32, 0x48, 0x0c, 0xcb, 0x99, 0x65, 0x82, 0xec, 0x70, - 0x9c, 0xad, 0x2c, 0xbe, 0xa4, 0xa5, 0x2b, 0x53, 0x57, 0x04, 0xfc, 0x94, 0x0c, 0x09, 0xf3, 0xb2, - 0x58, 0x4e, 0x93, 0xc5, 0xde, 0x85, 0xe6, 0xd4, 0x0d, 0x78, 0x18, 0x8e, 0xf8, 0x30, 0x1a, 0x4b, - 0x05, 0x91, 0x1a, 0x51, 0x81, 0x1a, 0xce, 0x06, 0x2c, 0x91, 0xd1, 0x21, 0xb0, 0x43, 0x2f, 0x38, - 0x77, 0x02, 0x2b, 0x10, 0x1a, 0x12, 0xa9, 0xbb, 0x4d, 0x2c, 0xea, 0xc9, 0x92, 0x1e, 0xa9, 0x48, - 0x6b, 0x33, 0xf8, 0x3e, 0x1f, 0x70, 0xe7, 0x82, 0x0f, 0x51, 0x4e, 0xcb, 0x99, 0x2b, 0x89, 0x3a, - 0xa6, 0x2c, 0x44, 0xa1, 0x7b, 0x3a, 0xb6, 0xa6, 0x93, 0xa1, 0x2d, 0x84, 0x95, 0x3a, 0x09, 0xc3, - 0xee, 0x74, 0x7c, 0x4c, 0x10, 0xf6, 0x18, 0x94, 0x24, 0x26, 0xe5, 0xc3, 0xc5, 0x04, 0x3f, 0x13, - 0xc4, 0x6a, 0x56, 0x25, 0x06, 0x09, 0x8a, 0x09, 0x99, 0xb3, 0x31, 0x23, 0x73, 0xb6, 0xa0, 0x38, - 0xf1, 0x9d, 0x0b, 0x3b, 0xe4, 0xad, 0x26, 0x31, 0x70, 0xf9, 0x28, 0x38, 0x83, 0xe3, 0x3a, 0xa1, - 0x63, 0x87, 0x9e, 0xdf, 0x62, 0x58, 0x16, 0x03, 0xd8, 0x43, 0x68, 0x22, 0x8d, 0x04, 0xa1, 0x1d, - 0x4e, 0x03, 0x29, 0x81, 0x2e, 0x21, 0x31, 0xa1, 0x0c, 0xdd, 0x43, 0x38, 0x0a, 0xa1, 0xec, 0x5b, - 0xb0, 0x4a, 0x64, 0x81, 0x35, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x32, 0x2e, 0xc5, 0x12, 0x96, 0x0a, - 0xfa, 0x96, 0xf2, 0xb5, 0x90, 0x0e, 0xde, 0x87, 0x35, 0x49, 0x26, 0x73, 0xb5, 0x56, 0xb0, 0xd6, - 0x32, 0x15, 0xcf, 0x54, 0xdb, 0x80, 0xa6, 0x18, 0x92, 0x33, 0xb0, 0x64, 0x6d, 0xb1, 0x13, 0x56, - 0xc5, 0xe8, 0x51, 0x53, 0x5a, 0xa4, 0x42, 0x13, 0xcb, 0x9e, 0xf1, 0x6b, 0xf6, 0x3d, 0x58, 0x24, - 0x92, 0x41, 0xf5, 0x0a, 0x39, 0xfd, 0x3a, 0x72, 0xfa, 0x15, 0x65, 0xe1, 0x8c, 0x4a, 0x91, 0xd9, - 0xd7, 0x07, 0x89, 0x67, 0xb1, 0x1d, 0x46, 0xce, 0x29, 0x0f, 0x9d, 0x31, 0x6f, 0xad, 0x11, 0x81, - 0xa9, 0x67, 0xb1, 0x53, 0xa7, 0x13, 0x2c, 0x69, 0x11, 0x5f, 0xa0, 0x27, 0xa4, 0xdd, 0x91, 0x17, - 0x70, 0x65, 0xa2, 0x6a, 0xdd, 0x96, 0x9b, 0x50, 0x00, 0x95, 0x0c, 0x29, 0x04, 0x71, 0x52, 0x7a, - 0x22, 0x43, 0xe2, 0x1d, 0x24, 0x86, 0x1a, 0xe9, 0x3e, 0xca, 0x98, 0x28, 0x4e, 0xf1, 0x73, 0xfb, - 0x52, 0x71, 0x90, 0xd7, 0xf0, 0xfd, 0x82, 0x00, 0x49, 0xde, 0xf1, 0xd3, 0x0c, 0x1d, 0x88, 0x92, - 0x7f, 0x04, 0x9a, 0x7a, 0x47, 0x9c, 0xc3, 0xf2, 0xdc, 0xd1, 0xb5, 0x64, 0x26, 0x40, 0xa0, 0x43, - 0x77, 0x84, 0xbb, 0xd9, 0x71, 0x75, 0x14, 0xe2, 0xbd, 0x55, 0x05, 0x44, 0xa4, 0x7b, 0x50, 0x99, - 0x4c, 0x4f, 0x46, 0xce, 0x80, 0x50, 0x72, 0xd4, 0x0a, 0x81, 0x10, 0x41, 0xe8, 0xb7, 0x44, 0x51, - 0x84, 0x91, 0x47, 0x8c, 0x8a, 0x84, 0x21, 0x0a, 0xf2, 0x76, 0xee, 0x23, 0x3b, 0xa9, 0x9a, 0xf8, - 0xdb, 0xd8, 0x84, 0xe5, 0xe4, 0xa0, 0xe5, 0xc1, 0xf3, 0x10, 0x4a, 0x92, 0x57, 0x29, 0xc3, 0x47, - 0x5d, 0x33, 0x45, 0x0b, 0x15, 0x2d, 0x2a, 0x37, 0x7e, 0x73, 0x01, 0x96, 0x24, 0x74, 0x4b, 0x2c, - 0x6d, 0x6f, 0x3a, 0x1e, 0xdb, 0x7e, 0x0a, 0x13, 0xcc, 0xbc, 0x98, 0x09, 0x66, 0xe7, 0x98, 0x60, - 0x52, 0xf3, 0x25, 0x1e, 0x9a, 0xd4, 0x7c, 0xc5, 0xbb, 0x24, 0x65, 0x44, 0xb7, 0x83, 0xd6, 0x24, - 0xb8, 0x4f, 0xf6, 0xd6, 0x39, 0x96, 0x5d, 0x48, 0x61, 0xd9, 0x3a, 0xc3, 0x5d, 0x98, 0x61, 0xb8, - 0x6f, 0x00, 0x11, 0x8d, 0x7a, 0xfb, 0x45, 0xd2, 0x4f, 0x10, 0x26, 0x8d, 0xa9, 0xef, 0xc0, 0xe2, - 0x2c, 0x8f, 0x23, 0x66, 0x5a, 0x4f, 0xe1, 0x70, 0xce, 0x98, 0xe3, 0x69, 0xa5, 0x21, 0x97, 0x25, - 0x87, 0x73, 0xc6, 0x7c, 0x0f, 0x4b, 0x14, 0x7e, 0x07, 0x80, 0xfa, 0xc6, 0x4d, 0x03, 0xb8, 0x69, - 0xde, 0x4e, 0xbe, 0x0b, 0x7d, 0xd5, 0x37, 0xc4, 0xc3, 0xd4, 0xe7, 0xb8, 0x8b, 0xca, 0x58, 0x13, - 0x37, 0xd0, 0x33, 0xa8, 0x7b, 0x13, 0xee, 0x5a, 0x31, 0xaf, 0xa9, 0x60, 0x53, 0x6f, 0xbd, 0xa0, - 0xa9, 0xae, 0xc2, 0x35, 0x6b, 0xa2, 0x6e, 0xf4, 0xc8, 0xf6, 0x69, 0xe1, 0xb9, 0xd6, 0x5a, 0xf5, - 0x4b, 0xb4, 0x56, 0xc7, 0xca, 0xd1, 0xb3, 0xf1, 0x0f, 0x32, 0x50, 0xd1, 0x86, 0xcd, 0x56, 0xa0, - 0xb9, 0x75, 0x78, 0x78, 0xd4, 0x31, 0xdb, 0xfd, 0xee, 0x27, 0x1d, 0x6b, 0x6b, 0xef, 0xb0, 0xd7, - 0x69, 0xdc, 0x12, 0xe0, 0xbd, 0xc3, 0xad, 0xf6, 0x9e, 0xb5, 0x73, 0x68, 0x6e, 0x29, 0x70, 0x86, - 0xad, 0x02, 0x33, 0x3b, 0xfb, 0x87, 0xfd, 0x4e, 0x02, 0x9e, 0x65, 0x0d, 0xa8, 0x6e, 0x9a, 0x9d, - 0xf6, 0xd6, 0xae, 0x84, 0xe4, 0xd8, 0x32, 0x34, 0x76, 0x8e, 0x0f, 0xb6, 0xbb, 0x07, 0x4f, 0xad, - 0xad, 0xf6, 0xc1, 0x56, 0x67, 0xaf, 0xb3, 0xdd, 0xc8, 0xb3, 0x1a, 0x94, 0xdb, 0x9b, 0xed, 0x83, - 0xed, 0xc3, 0x83, 0xce, 0x76, 0xa3, 0x60, 0xfc, 0x12, 0x94, 0xe3, 0x89, 0x56, 0xa0, 0x78, 0x7c, - 0xf0, 0xec, 0xe0, 0xf0, 0xd3, 0x83, 0xc6, 0x2d, 0x56, 0x86, 0x02, 0xf6, 0xdf, 0xc8, 0x30, 0x80, - 0x05, 0xea, 0xb3, 0x91, 0x65, 0x25, 0xc8, 0x6f, 0x1e, 0xf6, 0x77, 0x1b, 0x39, 0xe3, 0x2f, 0x32, - 0xb0, 0x82, 0x53, 0x1e, 0xce, 0x32, 0x81, 0xfb, 0x50, 0x19, 0x78, 0xde, 0x44, 0x68, 0x5a, 0xb1, - 0x44, 0xa1, 0x83, 0xc4, 0x06, 0x27, 0xe6, 0x7d, 0xea, 0xf9, 0x03, 0x2e, 0x79, 0x00, 0x20, 0x68, - 0x47, 0x40, 0x04, 0x0d, 0x4a, 0x22, 0x26, 0x0c, 0x62, 0x01, 0x15, 0x82, 0x11, 0xca, 0x2a, 0x2c, - 0x9c, 0xf8, 0xdc, 0x1e, 0x9c, 0xcb, 0xdd, 0x2f, 0x9f, 0xd8, 0xd7, 0x63, 0x1b, 0xc0, 0x40, 0xd0, - 0xd4, 0x88, 0x0f, 0x71, 0x0b, 0x94, 0xcc, 0x45, 0x09, 0xdf, 0x92, 0x60, 0x71, 0x1a, 0xd9, 0x27, - 0xb6, 0x3b, 0xf4, 0x5c, 0x3e, 0x94, 0xaa, 0x46, 0x0c, 0x30, 0x8e, 0x60, 0x75, 0x76, 0x7e, 0x92, - 0x5f, 0x7c, 0xa0, 0xf1, 0x0b, 0x92, 0xfc, 0xd7, 0x6f, 0x26, 0x05, 0x8d, 0x77, 0xfc, 0xa3, 0x3c, - 0xe4, 0x85, 0x24, 0x78, 0xa3, 0xd0, 0xa8, 0x8b, 0xf6, 0xb9, 0x39, 0xf7, 0x0f, 0x9a, 0x1a, 0x48, - 0x44, 0x20, 0x7b, 0x56, 0x19, 0x21, 0x28, 0x1a, 0x44, 0xc5, 0x3e, 0x1f, 0x5c, 0x48, 0x83, 0x16, - 0x15, 0x9b, 0x7c, 0x70, 0x81, 0x3a, 0x95, 0x1d, 0x52, 0x5d, 0xda, 0xef, 0xc5, 0xc0, 0x0e, 0xb1, - 0xa6, 0x2c, 0xc2, 0x7a, 0xc5, 0xa8, 0x08, 0x6b, 0xb5, 0xa0, 0xe8, 0xb8, 0x27, 0xde, 0xd4, 0x1d, - 0xe2, 0xf6, 0x2e, 0x99, 0xea, 0x11, 0xbd, 0x4d, 0xc8, 0x89, 0xc4, 0x41, 0x44, 0xbb, 0xb9, 0x24, - 0x00, 0x7d, 0x71, 0x14, 0xbd, 0x07, 0xe5, 0xe0, 0xda, 0x1d, 0xe8, 0x7b, 0x78, 0x59, 0xae, 0x8f, - 0x98, 0xfd, 0x46, 0xef, 0xda, 0x1d, 0xe0, 0x8e, 0x2d, 0x05, 0xf2, 0x17, 0x7b, 0x1f, 0x4a, 0x91, - 0xdd, 0x97, 0x38, 0xf0, 0x6d, 0xbd, 0x86, 0x32, 0xf6, 0x92, 0x7a, 0x1d, 0xa1, 0xb2, 0x47, 0xb0, - 0x80, 0xc6, 0xd9, 0xa0, 0x55, 0xc5, 0x4a, 0x4a, 0xde, 0x17, 0xc3, 0x40, 0x47, 0x0f, 0x1f, 0xa2, - 0xa1, 0xd6, 0x94, 0x68, 0xeb, 0xcf, 0xa0, 0x96, 0x68, 0x4b, 0x57, 0xa2, 0x6b, 0xa4, 0x44, 0xbf, - 0xa5, 0x2b, 0xd1, 0xf1, 0x49, 0x20, 0xab, 0xe9, 0x4a, 0xf5, 0xaf, 0x40, 0x49, 0x4d, 0x45, 0xec, - 0x3f, 0xb9, 0x77, 0xac, 0xde, 0x67, 0x07, 0x5b, 0x8d, 0x5b, 0x6c, 0x11, 0x2a, 0xed, 0x2d, 0xdc, - 0xd2, 0x08, 0xc8, 0x08, 0x94, 0xa3, 0x76, 0xaf, 0x17, 0x41, 0xb2, 0xc6, 0x0e, 0x34, 0x66, 0x47, - 0x2a, 0x68, 0x32, 0x54, 0x30, 0x69, 0xba, 0x8e, 0x01, 0x42, 0x45, 0x22, 0x6b, 0x34, 0xc9, 0xe1, - 0xf4, 0x60, 0xbc, 0x0f, 0x0d, 0x71, 0xae, 0x89, 0xa5, 0x0a, 0x34, 0x13, 0xf0, 0x48, 0xc8, 0x76, - 0xba, 0xf9, 0xba, 0x64, 0x56, 0x08, 0x86, 0x5d, 0x19, 0x1f, 0x40, 0x53, 0xab, 0x16, 0xab, 0xb4, - 0xe2, 0xac, 0x9c, 0x55, 0x69, 0x51, 0x81, 0xa1, 0x12, 0x63, 0x0d, 0x56, 0xc4, 0x63, 0xe7, 0x82, - 0xbb, 0x61, 0x6f, 0x7a, 0x42, 0x3e, 0x47, 0xc7, 0x73, 0x85, 0x62, 0x53, 0x8e, 0x4a, 0x6e, 0x26, - 0xf2, 0x0d, 0xa9, 0xfd, 0x66, 0x91, 0x34, 0xd6, 0xb5, 0x1e, 0xb0, 0xe2, 0x06, 0xfe, 0x4d, 0x68, - 0xc1, 0xe5, 0x08, 0x24, 0x96, 0xf5, 0xa8, 0xd3, 0x31, 0xad, 0xc3, 0x83, 0xbd, 0xee, 0x81, 0x60, - 0x94, 0x62, 0x59, 0x11, 0xb0, 0xb3, 0x83, 0x90, 0x8c, 0xd1, 0x80, 0xfa, 0x53, 0x1e, 0x76, 0xdd, - 0x53, 0x4f, 0xf9, 0xd7, 0xfe, 0xaa, 0x00, 0x8b, 0x11, 0x28, 0xd6, 0xa2, 0x2f, 0xb8, 0x1f, 0x38, - 0x9e, 0x8b, 0x02, 0x71, 0xd9, 0x54, 0x8f, 0xe2, 0x74, 0x73, 0x86, 0xdc, 0x0d, 0x9d, 0xf0, 0xda, - 0x4a, 0x98, 0xdc, 0xea, 0x0a, 0x2c, 0x4f, 0xd1, 0x65, 0x28, 0xd8, 0x23, 0xc7, 0x56, 0xae, 0x5a, - 0x7a, 0x10, 0xd0, 0x81, 0x37, 0xf2, 0x7c, 0x94, 0x7d, 0xcb, 0x26, 0x3d, 0xb0, 0xc7, 0xb0, 0x2c, - 0x64, 0x70, 0xdd, 0x0e, 0x8a, 0xfc, 0x83, 0xac, 0x7f, 0xcc, 0x9d, 0x8e, 0x8f, 0x62, 0x5b, 0xa8, - 0x28, 0x11, 0x67, 0xa7, 0xa8, 0x21, 0x85, 0xa5, 0xa8, 0x02, 0xa9, 0x73, 0x4d, 0x77, 0x3a, 0x6e, - 0x63, 0x49, 0x84, 0xff, 0x04, 0x56, 0x04, 0x7e, 0x24, 0x5e, 0x45, 0x35, 0x16, 0xb1, 0x86, 0x68, - 0xac, 0x2b, 0xcb, 0xa2, 0x3a, 0x77, 0xa0, 0x4c, 0xa3, 0x12, 0x6f, 0xbc, 0x40, 0x62, 0x3c, 0x0e, - 0x85, 0xfb, 0xc1, 0x9c, 0x57, 0x75, 0x81, 0x04, 0x81, 0x19, 0xaf, 0xaa, 0xe6, 0x97, 0x2d, 0xcd, - 0xfa, 0x65, 0x9f, 0xc0, 0xca, 0x89, 0x20, 0xc1, 0x73, 0x6e, 0x0f, 0xb9, 0x6f, 0xc5, 0x84, 0x4d, - 0xea, 0xca, 0x92, 0x28, 0xdc, 0xc5, 0xb2, 0x68, 0x1f, 0x08, 0x39, 0x47, 0xb0, 0x05, 0x3e, 0xb4, - 0x42, 0xcf, 0x42, 0xf1, 0x07, 0x19, 0x4c, 0xc9, 0xac, 0x11, 0xb8, 0xef, 0x6d, 0x09, 0x60, 0x12, - 0xef, 0xcc, 0xb7, 0x27, 0xe7, 0x52, 0xa1, 0x88, 0xf0, 0x9e, 0x0a, 0x20, 0x7b, 0x0d, 0x8a, 0x82, - 0xe4, 0x5d, 0x4e, 0xce, 0x2f, 0x12, 0xd9, 0x15, 0x88, 0xbd, 0x05, 0x0b, 0xd8, 0x47, 0xd0, 0x6a, - 0x20, 0xbd, 0x57, 0x63, 0x46, 0xee, 0xb8, 0xa6, 0x2c, 0x13, 0xc2, 0xe4, 0xd4, 0x77, 0x88, 0xcb, - 0x94, 0x4d, 0xfc, 0xcd, 0xbe, 0xaf, 0xb1, 0xac, 0x25, 0xac, 0xab, 0xe4, 0x81, 0x19, 0x4a, 0xbb, - 0x89, 0x7b, 0x7d, 0xa5, 0xcc, 0xe8, 0x07, 0xf9, 0x52, 0xa5, 0x51, 0x35, 0xbe, 0x03, 0x05, 0x5a, - 0x1d, 0x41, 0x84, 0xb8, 0x76, 0x19, 0x49, 0x84, 0x08, 0x6d, 0x41, 0xd1, 0xe5, 0xe1, 0xa5, 0xe7, - 0x3f, 0x57, 0x46, 0x69, 0xf9, 0x68, 0xfc, 0x18, 0xad, 0x29, 0x91, 0xc7, 0x9d, 0x14, 0x43, 0x41, - 0x1e, 0xf4, 0x7a, 0x83, 0x73, 0x5b, 0x1a, 0x78, 0x4a, 0x08, 0xe8, 0x9d, 0xdb, 0x73, 0xe4, 0x91, - 0x9d, 0x77, 0xba, 0xbf, 0x05, 0x75, 0xe5, 0xe3, 0x0f, 0xac, 0x11, 0x3f, 0x0d, 0x25, 0xb9, 0x57, - 0xa5, 0x83, 0x3f, 0xd8, 0xe3, 0xa7, 0xa1, 0xb1, 0x0f, 0x4d, 0x49, 0x90, 0x87, 0x13, 0xae, 0xba, - 0xfe, 0x6e, 0x9a, 0x3c, 0x5d, 0x79, 0xb2, 0x94, 0x3c, 0x68, 0x29, 0x76, 0x21, 0x21, 0x64, 0x1b, - 0x1f, 0x03, 0xd3, 0x8f, 0x61, 0xd9, 0x9e, 0x94, 0x6a, 0x95, 0x2d, 0x5f, 0xb9, 0xc4, 0x22, 0xd9, - 0xd9, 0x19, 0x8a, 0xd5, 0x09, 0xa6, 0x83, 0x81, 0x8a, 0xbd, 0x28, 0x99, 0xea, 0xd1, 0xf8, 0xd3, - 0x0c, 0x2c, 0x61, 0x63, 0x4a, 0x1f, 0x90, 0x4c, 0xf6, 0x67, 0x1e, 0xa4, 0x78, 0x3f, 0xba, 0xec, - 0x43, 0x0f, 0x5f, 0xde, 0x7a, 0x9a, 0x9f, 0xb3, 0x9e, 0x7e, 0x1d, 0x1a, 0x43, 0x3e, 0x72, 0x30, - 0x0c, 0x47, 0x89, 0x12, 0xa4, 0x01, 0x2c, 0x2a, 0xb8, 0xd4, 0x06, 0x8d, 0x7f, 0x96, 0x81, 0x26, - 0x49, 0x2a, 0xa8, 0x57, 0xcb, 0x85, 0xfa, 0x48, 0x29, 0x92, 0x92, 0x55, 0xc9, 0x39, 0xc5, 0x27, - 0x38, 0x42, 0x09, 0x79, 0xf7, 0x96, 0x54, 0x30, 0x25, 0x94, 0x7d, 0x88, 0x3a, 0x8c, 0x6b, 0x21, - 0x30, 0x25, 0xac, 0x27, 0xf9, 0x52, 0x76, 0x6f, 0xa1, 0x82, 0xe3, 0x22, 0x68, 0xb3, 0x24, 0x34, - 0x5b, 0x01, 0x36, 0x76, 0xa0, 0x96, 0xe8, 0x26, 0x61, 0xe2, 0xad, 0x92, 0x89, 0x77, 0xce, 0x8d, - 0x92, 0x9d, 0x77, 0xa3, 0xfc, 0xbd, 0x3c, 0x30, 0x41, 0x52, 0x33, 0x6f, 0x6d, 0xc6, 0x07, 0x99, - 0x9d, 0xf3, 0x41, 0x3e, 0x06, 0xa6, 0x21, 0x28, 0xd7, 0x68, 0x2e, 0x72, 0x8d, 0x36, 0x62, 0x5c, - 0xe9, 0x19, 0x7d, 0x0c, 0xcb, 0x52, 0xa0, 0x8d, 0x9c, 0x8e, 0x68, 0xbb, 0xa3, 0xf7, 0xc3, 0x48, - 0xb2, 0x55, 0xce, 0x47, 0xb4, 0xe3, 0x29, 0xff, 0xa3, 0xd0, 0xc1, 0xc9, 0xe4, 0x85, 0xfe, 0x47, - 0xa5, 0x7d, 0x6b, 0x54, 0xb0, 0xf0, 0x52, 0x2a, 0x28, 0xce, 0x51, 0x81, 0x66, 0x81, 0x29, 0x25, - 0x2d, 0x30, 0x06, 0xd4, 0x94, 0x97, 0x91, 0x82, 0x2b, 0x48, 0x7a, 0xab, 0x48, 0x57, 0x23, 0x06, - 0x58, 0x3c, 0x80, 0x86, 0x32, 0x93, 0x44, 0x36, 0x1e, 0x0a, 0x1c, 0x90, 0x56, 0xb6, 0x2d, 0x65, - 0xe9, 0x49, 0x58, 0xd4, 0x2b, 0x33, 0x16, 0xf5, 0x77, 0xa1, 0x19, 0x08, 0x22, 0xb2, 0xa6, 0xae, - 0x8c, 0xf2, 0xe1, 0x43, 0x54, 0x9d, 0x4a, 0x66, 0x03, 0x0b, 0x8e, 0x63, 0xf8, 0xbc, 0xfd, 0xa2, - 0x96, 0x62, 0xbf, 0x78, 0x3f, 0x76, 0xc8, 0x05, 0xe7, 0xce, 0x18, 0x0f, 0xee, 0x38, 0x22, 0x46, - 0x2e, 0x70, 0xef, 0xdc, 0x19, 0x9b, 0xca, 0xfb, 0x2b, 0x1e, 0x8c, 0xff, 0x98, 0x81, 0x86, 0xa0, - 0x83, 0x04, 0x9d, 0xff, 0x12, 0xe0, 0x8e, 0x7c, 0x45, 0x32, 0xaf, 0x08, 0x5c, 0x45, 0xe5, 0xdf, - 0x01, 0x24, 0x5b, 0x4b, 0xe8, 0x89, 0x92, 0xc8, 0x5b, 0x49, 0x22, 0x8f, 0x19, 0xd9, 0xee, 0x2d, - 0x52, 0x00, 0x04, 0x24, 0xcd, 0x11, 0x9a, 0x4f, 0x71, 0x84, 0x6a, 0x5b, 0x61, 0x17, 0xe0, 0x19, - 0xbf, 0xde, 0xf3, 0x06, 0xa8, 0xa1, 0xdd, 0x05, 0x10, 0x04, 0x79, 0x6a, 0x8f, 0x1d, 0x69, 0x5d, - 0x29, 0x98, 0xe5, 0xe7, 0xfc, 0x7a, 0x07, 0x01, 0xe2, 0x6d, 0x88, 0xe2, 0x78, 0x3f, 0x14, 0xcc, - 0xd2, 0x73, 0x7e, 0x4d, 0x9b, 0xc1, 0x82, 0xda, 0x33, 0x7e, 0xbd, 0xcd, 0x49, 0x5c, 0xf3, 0x7c, - 0x41, 0x09, 0xbe, 0x7d, 0x29, 0xe4, 0xb3, 0x84, 0x13, 0xb3, 0xe2, 0xdb, 0x97, 0xcf, 0xf8, 0xb5, - 0x72, 0xa8, 0x16, 0x45, 0xf9, 0xc8, 0x1b, 0xc8, 0x13, 0x48, 0x85, 0x63, 0xc4, 0x83, 0x32, 0x17, - 0x9e, 0xe3, 0x6f, 0xe3, 0xaf, 0x33, 0x50, 0x13, 0xe3, 0x47, 0x06, 0x27, 0xd6, 0x5d, 0x45, 0xf5, - 0x64, 0xe2, 0xa8, 0x9e, 0x27, 0x92, 0x3f, 0x10, 0xb7, 0xcc, 0xde, 0xcc, 0x2d, 0x71, 0x81, 0x89, - 0x55, 0xbe, 0x07, 0x65, 0xda, 0x5b, 0x62, 0xb3, 0xe6, 0x12, 0x6f, 0x29, 0x31, 0x21, 0xb3, 0x84, - 0x68, 0xcf, 0x28, 0x88, 0x40, 0xb3, 0xd4, 0xd1, 0x12, 0x97, 0xfd, 0xc8, 0x3e, 0x97, 0xf2, 0x1a, - 0x0a, 0x37, 0x04, 0x11, 0xe8, 0x66, 0xb0, 0x85, 0x39, 0x33, 0xd8, 0x31, 0x54, 0x34, 0xa2, 0x43, - 0xbb, 0x5f, 0x34, 0x3b, 0xa2, 0xd0, 0x24, 0x55, 0x25, 0x96, 0x67, 0xf7, 0x96, 0x59, 0x1b, 0xe8, - 0x80, 0xcd, 0x05, 0xc8, 0x8b, 0x4a, 0xc6, 0x47, 0xd0, 0xd4, 0x9a, 0x25, 0x75, 0x35, 0x6d, 0xd0, - 0x99, 0x34, 0x27, 0xfa, 0x3f, 0xcf, 0xc0, 0xb2, 0xac, 0x8d, 0x21, 0x62, 0x8e, 0x38, 0xcf, 0xf7, - 0x83, 0x33, 0xf6, 0x4b, 0x50, 0x13, 0xad, 0x5b, 0x3e, 0x3f, 0x73, 0x82, 0x90, 0x2b, 0x1f, 0x49, - 0xca, 0xee, 0x11, 0x6c, 0x5d, 0xa0, 0x9a, 0x12, 0x93, 0x7d, 0x04, 0x15, 0xac, 0x4a, 0x0a, 0xb5, - 0x7c, 0x6f, 0xad, 0xf9, 0x8a, 0x34, 0xd4, 0xdd, 0x5b, 0x26, 0x04, 0xd1, 0xd3, 0x66, 0x19, 0x8a, - 0xa1, 0xef, 0x9c, 0x9d, 0x71, 0xdf, 0x58, 0x8d, 0x86, 0x26, 0xb6, 0x22, 0xef, 0x85, 0x7c, 0x22, - 0xa4, 0x24, 0xe3, 0xbf, 0x64, 0xa0, 0x22, 0x37, 0xd7, 0xcf, 0xec, 0x18, 0x59, 0xd7, 0x62, 0x1c, - 0x49, 0x77, 0x8e, 0x43, 0x1a, 0xdf, 0x81, 0xc5, 0xb1, 0x90, 0x98, 0x84, 0x44, 0x9f, 0xf0, 0x8a, - 0xd4, 0x15, 0x58, 0x0a, 0x2c, 0x1b, 0xb0, 0x84, 0xf2, 0x4b, 0x60, 0x85, 0xce, 0xc8, 0x52, 0x85, - 0x32, 0x9e, 0xb0, 0x49, 0x45, 0x7d, 0x67, 0xb4, 0x2f, 0x0b, 0xc4, 0x31, 0x1e, 0x84, 0xf6, 0x19, - 0x97, 0xb4, 0x41, 0x0f, 0x46, 0x0b, 0x56, 0x67, 0x84, 0x79, 0xa5, 0x88, 0xfc, 0x7e, 0x13, 0xd6, - 0xe6, 0x8a, 0xa4, 0x42, 0x12, 0x79, 0x03, 0x46, 0xce, 0xf8, 0xc4, 0x8b, 0x6c, 0x65, 0x19, 0xcd, - 0x1b, 0xb0, 0x27, 0x4a, 0x94, 0xad, 0x8c, 0xc3, 0x8a, 0x22, 0x08, 0x34, 0x76, 0x45, 0xf2, 0x7e, - 0x16, 0xa5, 0xd1, 0xf7, 0x92, 0x9c, 0x6c, 0xb6, 0x3b, 0x05, 0xd7, 0xcf, 0xc7, 0xa5, 0xc9, 0x1c, - 0x2c, 0x60, 0xa7, 0xd0, 0x8a, 0xe8, 0x4e, 0x0a, 0x50, 0x9a, 0xf2, 0x22, 0x7a, 0xfa, 0xc6, 0x4b, - 0x7a, 0x4a, 0x58, 0x51, 0xcc, 0x55, 0x45, 0xae, 0xd4, 0x58, 0xd4, 0xcf, 0x05, 0xbc, 0xae, 0xfa, - 0x41, 0x61, 0x68, 0xbe, 0xb7, 0xfc, 0x2b, 0xcd, 0x0b, 0xad, 0x43, 0xc9, 0x2e, 0xef, 0xc8, 0x86, - 0xa3, 0x22, 0xbd, 0xdf, 0x73, 0x58, 0xbd, 0xb4, 0x9d, 0x50, 0xcd, 0x4f, 0xd3, 0x9b, 0x0a, 0xd8, - 0xdf, 0x93, 0x97, 0xf4, 0xf7, 0x29, 0x55, 0x4e, 0x88, 0x87, 0xcb, 0x97, 0xf3, 0xc0, 0x60, 0xfd, - 0x4f, 0xb2, 0x50, 0x4f, 0xb6, 0x22, 0x36, 0xb5, 0x64, 0x54, 0x4a, 0xe0, 0x90, 0x02, 0xbb, 0xb4, - 0xe1, 0x1e, 0x90, 0xa0, 0x31, 0x6f, 0x5d, 0xce, 0xa6, 0x58, 0x97, 0x75, 0xa3, 0x6e, 0xee, 0x65, - 0x5e, 0xb4, 0xfc, 0x2b, 0x79, 0xd1, 0x0a, 0x69, 0x5e, 0xb4, 0x9b, 0x5d, 0x2f, 0x0b, 0x3f, 0x93, - 0xeb, 0xa5, 0xf8, 0x02, 0xd7, 0x4b, 0xc2, 0x61, 0x54, 0x9a, 0x71, 0x18, 0xad, 0xff, 0x75, 0x06, - 0xd8, 0x3c, 0x1d, 0xb3, 0xa7, 0x64, 0x66, 0x77, 0xf9, 0x48, 0xf2, 0xb8, 0x6f, 0xbe, 0xda, 0x5e, - 0x50, 0xaf, 0x4f, 0xd5, 0x66, 0x8f, 0x60, 0x49, 0x8f, 0x4f, 0xd6, 0x35, 0x9d, 0x9a, 0xc9, 0xf4, - 0xa2, 0x58, 0x1f, 0xd6, 0x1c, 0x8c, 0xf9, 0x97, 0x3a, 0x18, 0x0b, 0x2f, 0x75, 0x30, 0x2e, 0x24, - 0x1d, 0x8c, 0xeb, 0xff, 0x2d, 0x03, 0x4b, 0x29, 0x24, 0xf7, 0xd5, 0xcd, 0x59, 0x50, 0x4a, 0x82, - 0x01, 0x65, 0x25, 0xa5, 0xe8, 0xbc, 0x67, 0x0f, 0x2a, 0xb1, 0xcf, 0x4a, 0xc5, 0xef, 0x3f, 0x7c, - 0x19, 0x1f, 0x88, 0x6b, 0x98, 0x7a, 0xf5, 0xf5, 0xdf, 0xcb, 0x42, 0x45, 0x2b, 0x14, 0xab, 0x48, - 0x04, 0xa6, 0xc5, 0x75, 0x90, 0x0c, 0x80, 0x7a, 0xda, 0x3d, 0x90, 0x86, 0x60, 0x2a, 0xa7, 0xad, - 0x20, 0x0f, 0x7c, 0x44, 0xd8, 0x80, 0x25, 0xe5, 0x02, 0xe1, 0x71, 0xf8, 0x96, 0x3c, 0x15, 0x9a, - 0xd2, 0x11, 0xc2, 0xa3, 0x68, 0x30, 0xf6, 0x48, 0x49, 0xef, 0xf1, 0xbb, 0x43, 0xc2, 0x24, 0x2b, - 0x6b, 0x93, 0xc8, 0x59, 0xbd, 0x44, 0x41, 0x95, 0xef, 0xc1, 0x8a, 0x22, 0xe6, 0x64, 0x0d, 0x32, - 0xbc, 0x32, 0x49, 0xca, 0x7a, 0x95, 0xef, 0xc3, 0xdd, 0x99, 0x31, 0xcd, 0x54, 0xa5, 0x38, 0xc3, - 0xdb, 0x89, 0xd1, 0xe9, 0x2d, 0xac, 0xff, 0x04, 0x6a, 0x09, 0xb6, 0xf6, 0xd5, 0xbd, 0xf2, 0x59, - 0xdd, 0x98, 0x56, 0x54, 0xd7, 0x8d, 0xd7, 0xff, 0x6f, 0x0e, 0xd8, 0x3c, 0x67, 0xfd, 0x45, 0x0e, - 0x61, 0x9e, 0x30, 0x73, 0x29, 0x84, 0xf9, 0xff, 0xed, 0xa4, 0x7f, 0x17, 0x9a, 0x32, 0x8f, 0x45, - 0xf3, 0x63, 0xd1, 0xe6, 0x6c, 0x44, 0x05, 0x6a, 0x14, 0xdf, 0x99, 0xf5, 0xa7, 0x97, 0x12, 0xa1, - 0xfb, 0x9a, 0xa8, 0x33, 0xe3, 0x56, 0x3f, 0x86, 0x05, 0xdb, 0x1d, 0x9c, 0x7b, 0x3e, 0xaa, 0x65, - 0xf5, 0x27, 0xbf, 0xfc, 0xa5, 0x0f, 0xbb, 0x8d, 0x36, 0xd6, 0x47, 0xf9, 0xca, 0x94, 0x8d, 0x19, - 0xef, 0x41, 0x45, 0x03, 0xa3, 0x6f, 0xa7, 0xbb, 0xbf, 0x79, 0xd8, 0xb8, 0xc5, 0x6a, 0x50, 0x36, - 0x3b, 0x5b, 0x87, 0x9f, 0x74, 0xcc, 0xce, 0x76, 0x23, 0xc3, 0x4a, 0x90, 0xdf, 0x3b, 0xec, 0xf5, - 0x1b, 0x59, 0x63, 0x1d, 0x5a, 0xb2, 0xc5, 0x79, 0x3b, 0xef, 0x6f, 0xe7, 0x23, 0x13, 0x0b, 0x16, - 0x4a, 0x8d, 0xea, 0x5b, 0x50, 0xd5, 0x05, 0x11, 0x49, 0x11, 0x33, 0xae, 0x54, 0xa1, 0x4b, 0x79, - 0x1a, 0xaf, 0xde, 0x02, 0x72, 0x90, 0x0d, 0xa3, 0x6a, 0x24, 0x5d, 0xbe, 0xc0, 0xa3, 0x82, 0x82, - 0x73, 0x82, 0x0c, 0xff, 0x06, 0xd4, 0x93, 0x46, 0x4f, 0xc9, 0x91, 0xd2, 0x54, 0x0b, 0x51, 0x3b, - 0x61, 0x05, 0x65, 0xdf, 0x87, 0xc6, 0xac, 0xd1, 0x54, 0x46, 0x38, 0xdf, 0x50, 0x7f, 0xd1, 0x49, - 0xda, 0x51, 0xd9, 0x2e, 0x2c, 0xa7, 0x89, 0x62, 0x48, 0x1f, 0x37, 0xeb, 0x94, 0x6c, 0x5e, 0xdc, - 0x62, 0xdf, 0x95, 0xb6, 0xf1, 0x42, 0x9a, 0x87, 0x51, 0x5b, 0xec, 0x0d, 0xfa, 0xa7, 0x59, 0xc9, - 0x2f, 0x00, 0x62, 0x18, 0x6b, 0x40, 0xf5, 0xf0, 0xa8, 0x73, 0x60, 0x6d, 0xed, 0xb6, 0x0f, 0x0e, - 0x3a, 0x7b, 0x8d, 0x5b, 0x8c, 0x41, 0x1d, 0x5d, 0x83, 0xdb, 0x11, 0x2c, 0x23, 0x60, 0xd2, 0x47, - 0xa1, 0x60, 0x59, 0xb6, 0x0c, 0x8d, 0xee, 0xc1, 0x0c, 0x34, 0xc7, 0x5a, 0xb0, 0x7c, 0xd4, 0x21, - 0x6f, 0x62, 0xa2, 0xdd, 0xbc, 0x10, 0xef, 0xe5, 0x74, 0x85, 0x78, 0x4f, 0xf9, 0x58, 0x72, 0x1f, - 0x28, 0xa9, 0xf7, 0x77, 0x32, 0xb0, 0x32, 0x53, 0x10, 0x47, 0xd9, 0x93, 0xcc, 0x9b, 0x94, 0x76, - 0xab, 0x08, 0x54, 0xbb, 0xe9, 0x5d, 0x68, 0x46, 0x76, 0x82, 0x99, 0x53, 0xa9, 0x11, 0x15, 0x28, - 0xe4, 0x47, 0xb0, 0xa4, 0x99, 0x1b, 0x66, 0x78, 0x05, 0xd3, 0x8a, 0x64, 0x05, 0x63, 0x2d, 0x8a, - 0x66, 0x9e, 0x19, 0xf5, 0x90, 0x92, 0xbc, 0xf4, 0x82, 0xd8, 0x75, 0x90, 0x1c, 0xaf, 0x7a, 0x64, - 0x8f, 0x67, 0x08, 0x21, 0x39, 0x5a, 0xfd, 0x85, 0xab, 0xee, 0xff, 0x60, 0x01, 0xd8, 0xc7, 0x53, - 0xee, 0x5f, 0x63, 0x14, 0x7d, 0xf0, 0xb2, 0xb0, 0x32, 0xa5, 0x53, 0x67, 0x5f, 0x29, 0x53, 0x26, - 0x2d, 0x53, 0x25, 0xff, 0xf2, 0x4c, 0x95, 0xc2, 0xcb, 0x32, 0x55, 0xde, 0x84, 0x9a, 0x73, 0xe6, - 0x7a, 0x82, 0x15, 0x0a, 0xb9, 0x35, 0x68, 0x2d, 0xdc, 0xcf, 0x3d, 0xa8, 0x9a, 0x55, 0x09, 0x14, - 0x52, 0x6b, 0xc0, 0x3e, 0x8a, 0x91, 0xf8, 0xf0, 0x0c, 0xb3, 0xaa, 0x74, 0x26, 0xd8, 0x19, 0x9e, - 0x71, 0x69, 0x42, 0x40, 0xa3, 0x9a, 0xaa, 0x2c, 0xe0, 0x01, 0x7b, 0x0b, 0xea, 0x81, 0x37, 0x15, - 0x6a, 0x80, 0x5a, 0x06, 0x72, 0x2e, 0x54, 0x09, 0x7a, 0xa4, 0x3c, 0x49, 0x4b, 0xd3, 0x80, 0x5b, - 0x63, 0x27, 0x08, 0x84, 0x78, 0x36, 0xf0, 0xdc, 0xd0, 0xf7, 0x46, 0xd2, 0x5f, 0xd0, 0x9c, 0x06, - 0x7c, 0x9f, 0x4a, 0xb6, 0xa8, 0x80, 0x7d, 0x3b, 0x1e, 0xd2, 0xc4, 0x76, 0xfc, 0xa0, 0x05, 0x38, - 0x24, 0x35, 0x53, 0x94, 0xb6, 0x6d, 0xc7, 0x8f, 0xc6, 0x22, 0x1e, 0x82, 0x99, 0x0c, 0x9a, 0xca, - 0x6c, 0x06, 0xcd, 0x8f, 0xd2, 0x33, 0x68, 0x6a, 0xd8, 0xf4, 0x63, 0xd9, 0xf4, 0xfc, 0x2b, 0xfe, - 0x52, 0x89, 0x34, 0xf3, 0x89, 0x41, 0xf5, 0x2f, 0x93, 0x18, 0xb4, 0x98, 0x96, 0x18, 0xf4, 0x1e, - 0x54, 0x30, 0x65, 0xc3, 0x3a, 0x77, 0x84, 0x0c, 0x47, 0xfe, 0x8f, 0x86, 0x9e, 0xd3, 0xb1, 0xeb, - 0xb8, 0xa1, 0x09, 0xbe, 0xfa, 0x19, 0xcc, 0xe7, 0xe8, 0x34, 0x7f, 0x81, 0x39, 0x3a, 0x32, 0xb5, - 0x64, 0x03, 0x4a, 0xea, 0x3d, 0x31, 0x06, 0xf9, 0x53, 0xdf, 0x1b, 0x2b, 0xbb, 0xb0, 0xf8, 0xcd, - 0xea, 0x90, 0x0d, 0x3d, 0x59, 0x39, 0x1b, 0x7a, 0xc6, 0xaf, 0x43, 0x45, 0x23, 0x35, 0xf6, 0x06, - 0x59, 0xa0, 0x84, 0x26, 0x25, 0x65, 0x4b, 0x5a, 0xc5, 0xb2, 0x84, 0x76, 0x87, 0x82, 0xdf, 0x0c, - 0x1d, 0x9f, 0x63, 0x36, 0x9d, 0xe5, 0xf3, 0x0b, 0xee, 0x07, 0xca, 0x4e, 0xdf, 0x88, 0x0a, 0x4c, - 0x82, 0x1b, 0x7f, 0x0b, 0x96, 0x12, 0xef, 0x56, 0xb2, 0x88, 0xb7, 0x60, 0x01, 0xd7, 0x4d, 0xf9, - 0x51, 0x93, 0xb9, 0x32, 0xb2, 0x0c, 0xd3, 0xa4, 0xc9, 0xc5, 0x60, 0x4d, 0x7c, 0xef, 0x04, 0x3b, - 0xc9, 0x98, 0x15, 0x09, 0x3b, 0xf2, 0xbd, 0x13, 0xe3, 0xcf, 0x73, 0x90, 0xdb, 0xf5, 0x26, 0x7a, - 0xe8, 0x50, 0x66, 0x2e, 0x74, 0x48, 0xaa, 0x87, 0x56, 0xa4, 0xfe, 0x49, 0x99, 0x1d, 0x8d, 0xeb, - 0x4a, 0x05, 0x7c, 0x00, 0x75, 0xc1, 0x27, 0x42, 0x4f, 0xe8, 0xd7, 0x97, 0xb6, 0x4f, 0x02, 0x71, - 0x8e, 0x36, 0x9f, 0x3d, 0x0e, 0xfb, 0xde, 0x0e, 0xc1, 0xd9, 0x32, 0xe4, 0x22, 0xf5, 0x05, 0x8b, - 0xc5, 0x23, 0x5b, 0x85, 0x05, 0x8c, 0x21, 0xbd, 0x96, 0x8e, 0x42, 0xf9, 0xc4, 0xbe, 0x09, 0x4b, - 0xc9, 0x76, 0x89, 0x15, 0x49, 0xd9, 0x48, 0x6f, 0x18, 0x79, 0xd2, 0x6d, 0x10, 0x7c, 0x84, 0x70, - 0x64, 0xbc, 0xc1, 0x29, 0xe7, 0x58, 0xa4, 0x31, 0xbd, 0x52, 0x82, 0xe9, 0xdd, 0x83, 0x4a, 0x38, - 0xba, 0xb0, 0x26, 0xf6, 0xf5, 0xc8, 0xb3, 0x87, 0x72, 0x7f, 0x43, 0x38, 0xba, 0x38, 0x22, 0x08, - 0x7b, 0x04, 0x30, 0x9e, 0x4c, 0xe4, 0xde, 0x43, 0x5b, 0x75, 0x4c, 0xca, 0xfb, 0x47, 0x47, 0x44, - 0x72, 0x66, 0x79, 0x3c, 0x99, 0xd0, 0x4f, 0xb6, 0x0d, 0xf5, 0xd4, 0x8c, 0xb7, 0xbb, 0x2a, 0xe4, - 0xd1, 0x9b, 0x6c, 0xa4, 0x6c, 0xce, 0xda, 0x40, 0x87, 0xad, 0x7f, 0x1f, 0xd8, 0xcf, 0x99, 0x77, - 0xd6, 0x87, 0x72, 0x34, 0x3e, 0x3d, 0x6d, 0x0b, 0x83, 0x98, 0x2b, 0x89, 0xb4, 0xad, 0xf6, 0x70, - 0xe8, 0x0b, 0xbe, 0x48, 0x07, 0x66, 0xc4, 0xf2, 0x41, 0x3b, 0x31, 0xdb, 0xc4, 0xf7, 0x8d, 0xbf, - 0xcc, 0x40, 0x81, 0x72, 0xc8, 0xde, 0x86, 0x45, 0xc2, 0x8f, 0xc2, 0xb0, 0xa4, 0x7b, 0x91, 0xce, - 0xdd, 0xbe, 0x8c, 0xc0, 0x12, 0xdb, 0x42, 0xcb, 0x7f, 0xcd, 0x46, 0x6f, 0x5e, 0xcb, 0x81, 0xbd, - 0x07, 0xe5, 0xa8, 0x6b, 0x8d, 0x74, 0x4a, 0xaa, 0x67, 0xf6, 0x3a, 0xe4, 0xcf, 0xbd, 0x89, 0xb2, - 0xd3, 0x40, 0xbc, 0x92, 0x26, 0xc2, 0xe3, 0xb1, 0x88, 0x3e, 0x68, 0xf0, 0xd2, 0xbe, 0x10, 0x75, - 0x82, 0x64, 0x30, 0x3f, 0xc7, 0x85, 0x94, 0x39, 0x1e, 0xc3, 0xa2, 0xe0, 0x03, 0x9a, 0x9b, 0xff, - 0xe6, 0x43, 0xf3, 0xeb, 0x42, 0xc2, 0x1b, 0x8c, 0xa6, 0x43, 0xae, 0x5b, 0xc9, 0x30, 0x26, 0x48, - 0xc2, 0x95, 0x64, 0x6d, 0xfc, 0x41, 0x86, 0xf8, 0x8b, 0x68, 0x97, 0x3d, 0x80, 0xbc, 0x38, 0xdf, - 0x66, 0xac, 0xb8, 0x51, 0x34, 0xb9, 0xc0, 0x33, 0x11, 0x03, 0x93, 0xc6, 0xa7, 0xe3, 0x64, 0xeb, - 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0xa1, 0xe9, 0x6b, 0x6a, 0x5a, 0x33, 0x46, 0x1a, 0x9a, 0x7d, - 0xb4, 0x4d, 0x37, 0xb4, 0xe0, 0xa2, 0x7c, 0xe2, 0xc4, 0x54, 0x52, 0xe0, 0xf0, 0x8c, 0x6b, 0x41, - 0x45, 0x7f, 0x94, 0x85, 0x5a, 0x62, 0x44, 0x18, 0x5d, 0x25, 0x0e, 0x00, 0x72, 0x21, 0xc8, 0xf7, - 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9d, 0xb2, 0x89, 0x75, 0x8a, 0x02, 0x1a, 0x72, 0x7a, 0x40, - 0xc3, 0x63, 0x28, 0xc7, 0x79, 0xcf, 0xc9, 0x21, 0x89, 0xfe, 0x54, 0x4c, 0x7d, 0x8c, 0x14, 0x87, - 0x40, 0x14, 0xf4, 0x10, 0x88, 0xef, 0x69, 0x1e, 0xf3, 0x05, 0x6c, 0xc6, 0x48, 0x5b, 0xd1, 0x5f, - 0x88, 0xbf, 0xdc, 0xf8, 0x08, 0x2a, 0xda, 0xe0, 0x75, 0xcf, 0x78, 0x26, 0xe1, 0x19, 0x8f, 0xb2, - 0x5f, 0xb2, 0x71, 0xf6, 0x8b, 0xf1, 0x9b, 0x59, 0xa8, 0x89, 0xfd, 0xe5, 0xb8, 0x67, 0x47, 0xde, - 0xc8, 0x19, 0xa0, 0x4b, 0x21, 0xda, 0x61, 0x52, 0xd0, 0x52, 0xfb, 0x4c, 0x6e, 0x31, 0x92, 0xb3, - 0xf4, 0x24, 0x3f, 0x62, 0xd2, 0x51, 0x92, 0x9f, 0x01, 0x35, 0xc1, 0x18, 0x4f, 0xec, 0x80, 0x6b, - 0x59, 0xd9, 0x66, 0xe5, 0x94, 0xf3, 0x4d, 0x3b, 0x20, 0x0e, 0xf9, 0x4d, 0x58, 0x12, 0x38, 0x98, - 0xdf, 0x34, 0x76, 0x46, 0x23, 0x87, 0x30, 0xc9, 0xd0, 0xd4, 0x38, 0xe5, 0xdc, 0xb4, 0x43, 0xbe, - 0x2f, 0x0a, 0x64, 0x12, 0x77, 0x69, 0xe8, 0x04, 0xf6, 0x49, 0x1c, 0x03, 0x17, 0x3d, 0xa3, 0x23, - 0xd0, 0xbe, 0xd2, 0x1c, 0x81, 0x64, 0x80, 0xa8, 0x8c, 0xed, 0xab, 0xc8, 0x11, 0x38, 0x43, 0x49, - 0xc5, 0x59, 0x4a, 0x32, 0xfe, 0x73, 0x16, 0x2a, 0x1a, 0x59, 0xbe, 0xca, 0xe9, 0x7a, 0x77, 0xce, - 0x05, 0x54, 0xd6, 0xbd, 0x3d, 0x6f, 0x26, 0xbb, 0xc4, 0x78, 0x01, 0x4a, 0x17, 0xd7, 0x08, 0xf8, - 0x0e, 0x94, 0xc5, 0xae, 0x7b, 0x0f, 0x0d, 0xa6, 0xf2, 0xb2, 0x03, 0x04, 0x1c, 0x4d, 0x4f, 0x54, - 0xe1, 0x13, 0x2c, 0x2c, 0xc4, 0x85, 0x4f, 0x44, 0xe1, 0x8b, 0x02, 0x5f, 0xbf, 0x03, 0x55, 0xd9, - 0x2a, 0xbe, 0x53, 0x9c, 0x6e, 0xbc, 0xeb, 0x13, 0xef, 0xdb, 0xac, 0x50, 0x77, 0xf4, 0xf2, 0x65, - 0xc5, 0x27, 0xaa, 0x62, 0xe9, 0x65, 0x15, 0x9f, 0xd0, 0x83, 0xb1, 0x13, 0xc5, 0x12, 0x63, 0xac, - 0x8a, 0xe2, 0x63, 0x8f, 0x60, 0x49, 0xb1, 0xab, 0xa9, 0x6b, 0xbb, 0xae, 0x37, 0x75, 0x07, 0x5c, - 0xa5, 0xc5, 0x30, 0x59, 0x74, 0x1c, 0x97, 0x18, 0xc3, 0x28, 0x6f, 0x92, 0x62, 0x5e, 0x1e, 0x42, - 0x81, 0xe4, 0x72, 0x12, 0x3e, 0xd2, 0x19, 0x17, 0xa1, 0xb0, 0x07, 0x50, 0x20, 0xf1, 0x3c, 0x7b, - 0x23, 0xb3, 0x21, 0x04, 0x63, 0x03, 0x16, 0x51, 0xc4, 0xd4, 0x38, 0xee, 0x8b, 0xa4, 0x12, 0x63, - 0x19, 0xd8, 0x01, 0x6d, 0x22, 0x3d, 0x16, 0xeb, 0xbf, 0xe7, 0xa0, 0xa2, 0x81, 0x05, 0x5b, 0xc4, - 0xe8, 0x1d, 0x6b, 0xe8, 0xd8, 0x63, 0xae, 0xfc, 0x52, 0x35, 0xb3, 0x86, 0xd0, 0x6d, 0x09, 0x14, - 0x87, 0x82, 0x7d, 0x71, 0x66, 0x79, 0xd3, 0xd0, 0x1a, 0xf2, 0x33, 0x9f, 0x73, 0x29, 0x2c, 0x55, - 0xed, 0x8b, 0xb3, 0xc3, 0x69, 0xb8, 0x8d, 0x30, 0x81, 0x25, 0x88, 0x5a, 0xc3, 0x92, 0x01, 0x27, - 0x63, 0xfb, 0x2a, 0xc6, 0x92, 0x51, 0x4f, 0xb4, 0x44, 0xf9, 0x28, 0xea, 0x89, 0xd4, 0x96, 0x59, - 0x4e, 0x5e, 0x98, 0xe7, 0xe4, 0xdf, 0x86, 0x55, 0xe2, 0xe4, 0x92, 0x47, 0x58, 0x33, 0x24, 0xb5, - 0x8c, 0xa5, 0x72, 0x92, 0x9a, 0xfc, 0xd5, 0x10, 0x33, 0x50, 0xfb, 0x23, 0x70, 0x7e, 0x4c, 0x3b, - 0x2a, 0x63, 0x8a, 0x99, 0xc9, 0xc6, 0x7b, 0xce, 0x8f, 0xb9, 0xc0, 0x44, 0xaf, 0xba, 0x8e, 0x29, - 0xe3, 0xab, 0xc7, 0x8e, 0x3b, 0x8b, 0x69, 0x5f, 0x25, 0x31, 0xcb, 0x12, 0xd3, 0xbe, 0xd2, 0x31, - 0xdf, 0x87, 0xb5, 0x31, 0x1f, 0x3a, 0x76, 0xb2, 0x59, 0x2b, 0x96, 0x20, 0x96, 0xa9, 0x58, 0xab, - 0xd3, 0x23, 0x0d, 0x52, 0xac, 0xc6, 0x8f, 0xbd, 0xf1, 0x89, 0x43, 0x87, 0x27, 0xf9, 0xf9, 0xf3, - 0x66, 0xdd, 0x9d, 0x8e, 0x7f, 0x88, 0x60, 0x51, 0x25, 0x30, 0x6a, 0x50, 0xe9, 0x85, 0xde, 0x44, - 0xbd, 0xe6, 0x3a, 0x54, 0xe9, 0x51, 0x26, 0x3d, 0xdd, 0x81, 0xdb, 0x48, 0x9b, 0x7d, 0x6f, 0xe2, - 0x8d, 0xbc, 0xb3, 0xeb, 0x84, 0x41, 0xe9, 0xbf, 0x66, 0x60, 0x29, 0x51, 0x2a, 0xf7, 0xf9, 0xb7, - 0x69, 0x63, 0x45, 0x99, 0x2b, 0x44, 0xce, 0x4d, 0xed, 0xf0, 0x21, 0x44, 0xda, 0x55, 0x2a, 0x9b, - 0xa5, 0x1d, 0x67, 0x5c, 0xab, 0x8a, 0x44, 0xdb, 0xad, 0x79, 0xda, 0x96, 0xf5, 0x55, 0x2e, 0xb6, - 0x6a, 0xe2, 0x97, 0x65, 0x0c, 0xfc, 0x50, 0x4e, 0x39, 0x97, 0x8c, 0xf2, 0xd5, 0x8d, 0x4f, 0x6a, - 0x04, 0xb1, 0x45, 0x2a, 0x30, 0xfe, 0x4d, 0x06, 0x20, 0x1e, 0x1d, 0xc6, 0x19, 0x47, 0x07, 0x28, - 0x5d, 0x66, 0xa4, 0x1d, 0x96, 0x6f, 0x40, 0x35, 0x0a, 0x37, 0x8c, 0x8f, 0xe4, 0x8a, 0x82, 0x89, - 0x73, 0xf9, 0x1d, 0x58, 0x3c, 0x1b, 0x79, 0x27, 0x28, 0x3a, 0xc9, 0x03, 0x94, 0x52, 0xbf, 0xea, - 0x04, 0x56, 0xc7, 0x62, 0x7c, 0x80, 0xe7, 0x53, 0x23, 0x12, 0xf5, 0xe3, 0xd8, 0xf8, 0xad, 0x6c, - 0x14, 0x77, 0x15, 0xaf, 0xc4, 0x8b, 0xf5, 0x8c, 0x9f, 0xc5, 0x7d, 0xff, 0x22, 0xaf, 0xd4, 0x47, - 0x50, 0xf7, 0x89, 0x3b, 0x2a, 0xd6, 0x99, 0x7f, 0x01, 0xeb, 0xac, 0xf9, 0x89, 0x23, 0xf7, 0xeb, - 0xd0, 0xb0, 0x87, 0x17, 0xdc, 0x0f, 0x1d, 0x34, 0x1b, 0xa3, 0xa0, 0x26, 0x23, 0x9d, 0x34, 0x38, - 0x4a, 0x44, 0xef, 0xc0, 0xa2, 0x4c, 0xc4, 0x8b, 0x30, 0xe5, 0xd5, 0x1e, 0x31, 0x58, 0x20, 0x1a, - 0xbf, 0xaf, 0x02, 0xbd, 0x92, 0x6f, 0xf7, 0xc5, 0xab, 0xa2, 0xcf, 0x30, 0x3b, 0xef, 0x77, 0x93, - 0x84, 0x24, 0xad, 0xd1, 0x92, 0x1f, 0x11, 0x50, 0xda, 0xa2, 0x93, 0xcb, 0x9a, 0x7f, 0x95, 0x65, - 0x35, 0xfe, 0x24, 0x03, 0xc5, 0x5d, 0x6f, 0x22, 0xf4, 0x72, 0x21, 0xcf, 0xe1, 0x36, 0x89, 0x9c, - 0x25, 0x0b, 0xe2, 0xb1, 0x3b, 0x7c, 0x71, 0xbe, 0x49, 0xaa, 0xbc, 0x51, 0x4b, 0xca, 0x1b, 0xdf, - 0x83, 0x3b, 0xe8, 0x8b, 0xf2, 0xbd, 0x89, 0xe7, 0x8b, 0xad, 0x6a, 0x8f, 0x48, 0xee, 0xf0, 0xdc, - 0xf0, 0x5c, 0xf1, 0xce, 0xdb, 0xa7, 0x9c, 0x1f, 0x69, 0x18, 0xfb, 0x11, 0x02, 0x66, 0x74, 0x8d, - 0xc2, 0x0b, 0x8b, 0x54, 0x45, 0x29, 0x18, 0x11, 0x47, 0x5d, 0x14, 0x05, 0x1d, 0x84, 0xa3, 0x68, - 0x64, 0x7c, 0x17, 0xca, 0x91, 0xd5, 0x81, 0xbd, 0x0b, 0xe5, 0x73, 0x6f, 0x22, 0x4d, 0x13, 0x99, - 0x44, 0x4e, 0x8e, 0x9c, 0xb5, 0x59, 0x3a, 0xa7, 0x1f, 0x81, 0xf1, 0xe7, 0x45, 0x28, 0x76, 0xdd, - 0x0b, 0xcf, 0x19, 0x60, 0xa8, 0xd8, 0x98, 0x8f, 0x3d, 0x95, 0x0d, 0x2c, 0x7e, 0x63, 0x38, 0x48, - 0x7c, 0x41, 0x47, 0x4e, 0x86, 0x83, 0x44, 0x57, 0x73, 0xac, 0xc0, 0x82, 0xaf, 0xdf, 0xb0, 0x51, - 0xf0, 0x31, 0x78, 0x35, 0x52, 0xda, 0x0a, 0x5a, 0x36, 0xb5, 0x68, 0x8b, 0x6e, 0x7e, 0xc0, 0x25, - 0xa3, 0xec, 0xac, 0x32, 0x42, 0x70, 0xc1, 0x5e, 0x83, 0xa2, 0x4c, 0x81, 0xa1, 0x84, 0x02, 0x8a, - 0x36, 0x95, 0x20, 0xa4, 0x06, 0x9f, 0x93, 0x2f, 0x31, 0x92, 0xa8, 0x84, 0x9e, 0x2e, 0x81, 0xdb, - 0x82, 0xd6, 0xee, 0x41, 0x85, 0xf0, 0x09, 0xa5, 0x24, 0x83, 0xbb, 0x10, 0x84, 0x08, 0x29, 0x17, - 0xd5, 0x94, 0x53, 0x2f, 0xaa, 0xc1, 0x58, 0xc0, 0x88, 0xcb, 0xd2, 0x14, 0x81, 0xae, 0x27, 0xd1, - 0xe0, 0xea, 0x96, 0x26, 0xa9, 0xdc, 0x53, 0xb2, 0xa2, 0x52, 0xee, 0xdf, 0x84, 0xda, 0xa9, 0x3d, - 0x1a, 0x9d, 0xd8, 0x83, 0xe7, 0xa4, 0x93, 0x56, 0xc9, 0x0c, 0xa7, 0x80, 0xa8, 0x94, 0xde, 0x83, - 0x8a, 0xf6, 0x96, 0x31, 0x72, 0x2b, 0x6f, 0x42, 0xfc, 0x7e, 0x67, 0x4d, 0x4d, 0xf5, 0x57, 0x30, - 0x35, 0x69, 0x11, 0x6c, 0x8b, 0xc9, 0x08, 0xb6, 0x3b, 0xc8, 0x4d, 0x65, 0x94, 0x53, 0x83, 0xee, - 0xc2, 0xb0, 0x87, 0x43, 0x8c, 0x72, 0xa2, 0x8b, 0xe7, 0x70, 0xf1, 0xa8, 0xbc, 0x49, 0x42, 0x2d, - 0xc1, 0x08, 0xe5, 0x2e, 0xd9, 0x4b, 0x27, 0xb6, 0x33, 0xc4, 0x88, 0x61, 0x52, 0x63, 0x8b, 0xf6, - 0x38, 0x3c, 0xb2, 0x9d, 0x21, 0xbb, 0x0f, 0x55, 0x55, 0x8c, 0xa7, 0xe3, 0x12, 0xad, 0xbf, 0x2c, - 0x16, 0x67, 0xa2, 0x01, 0xb5, 0x08, 0x63, 0x1c, 0x67, 0x1c, 0x56, 0x24, 0x0a, 0xd2, 0xc1, 0x7b, - 0x18, 0x18, 0x12, 0x72, 0xcc, 0x2b, 0xac, 0x3f, 0xb9, 0x23, 0xe7, 0x2a, 0xa9, 0x54, 0xfd, 0x27, - 0x2f, 0x0d, 0x61, 0x0a, 0x41, 0x8c, 0x9c, 0x45, 0xab, 0x09, 0x41, 0x4c, 0xa2, 0xa2, 0xb3, 0x88, - 0x10, 0xd8, 0x77, 0x35, 0x45, 0xaa, 0x85, 0xc8, 0xaf, 0xcd, 0xb4, 0x7f, 0x53, 0xc2, 0xc4, 0x5d, - 0x00, 0x27, 0x10, 0xa7, 0x4c, 0xc0, 0xdd, 0x21, 0xa6, 0x08, 0x96, 0xcc, 0xb2, 0x13, 0x3c, 0x23, - 0xc0, 0x57, 0xab, 0x61, 0xb5, 0xa1, 0xaa, 0x4f, 0x93, 0x95, 0x20, 0x7f, 0x78, 0xd4, 0x39, 0x68, - 0xdc, 0x62, 0x15, 0x28, 0xf6, 0x3a, 0xfd, 0xfe, 0x1e, 0xba, 0x9c, 0xaa, 0x50, 0x8a, 0xf2, 0x93, - 0xb2, 0xe2, 0xa9, 0xbd, 0xb5, 0xd5, 0x39, 0xea, 0x77, 0xb6, 0x1b, 0xb9, 0x1f, 0xe4, 0x4b, 0xd9, - 0x46, 0xce, 0xf8, 0x8b, 0x1c, 0x54, 0xb4, 0x55, 0x78, 0x31, 0x33, 0xbe, 0x0b, 0x80, 0x2a, 0x4d, - 0x1c, 0x04, 0x97, 0x37, 0xcb, 0x02, 0x42, 0x2f, 0x5f, 0x37, 0x96, 0xe7, 0xe8, 0x92, 0x15, 0x65, - 0x2c, 0x7f, 0x13, 0x6a, 0x74, 0x5f, 0x89, 0xee, 0x38, 0x2c, 0x98, 0x55, 0x02, 0x4a, 0x56, 0x8d, - 0x09, 0x8e, 0x88, 0x84, 0xa9, 0x2f, 0xf2, 0xf6, 0x02, 0x02, 0x61, 0xf2, 0x0b, 0x66, 0x2e, 0x05, - 0xde, 0xe8, 0x82, 0x13, 0x06, 0x49, 0x84, 0x15, 0x09, 0xeb, 0xcb, 0x54, 0x4d, 0xc9, 0x0f, 0xb5, - 0x0c, 0xbb, 0x82, 0x59, 0x25, 0xa0, 0xec, 0xe8, 0x9b, 0x8a, 0x80, 0x4a, 0x48, 0x40, 0x6b, 0xf3, - 0xd4, 0x90, 0x20, 0x9e, 0xbd, 0x39, 0x7b, 0x56, 0x19, 0x09, 0xe3, 0x6b, 0xf3, 0xf5, 0x5e, 0x6e, - 0xd7, 0x62, 0xef, 0x02, 0x1b, 0x4f, 0x26, 0x56, 0x8a, 0xa5, 0x29, 0x6f, 0x2e, 0x8e, 0x27, 0x93, - 0xbe, 0x66, 0x88, 0xf9, 0x0a, 0x8c, 0x60, 0x9f, 0x03, 0x6b, 0x8b, 0x0d, 0x8c, 0x43, 0x8c, 0x4c, - 0xa8, 0x31, 0x5b, 0xce, 0xe8, 0x6c, 0x39, 0x85, 0xfb, 0x65, 0x53, 0xb9, 0xdf, 0x8b, 0xf8, 0x84, - 0xb1, 0x03, 0x95, 0x23, 0xed, 0x36, 0xa4, 0xfb, 0xe2, 0x84, 0x50, 0xf7, 0x20, 0xd1, 0xd9, 0x41, - 0xc6, 0x2d, 0x5f, 0x5e, 0x7f, 0xa4, 0x8d, 0x26, 0xab, 0x8d, 0xc6, 0xf8, 0xd7, 0x19, 0xba, 0x69, - 0x22, 0x1a, 0x7c, 0x7c, 0x01, 0x93, 0xf2, 0x03, 0xc5, 0x89, 0xb0, 0x15, 0xe5, 0xff, 0x91, 0x39, - 0xac, 0x38, 0x34, 0xcb, 0x3b, 0x3d, 0x0d, 0xb8, 0x0a, 0x36, 0xa8, 0x20, 0xec, 0x10, 0x41, 0x4a, - 0xf8, 0x16, 0x12, 0xbe, 0x43, 0xed, 0x07, 0x32, 0xc2, 0x40, 0x08, 0xdf, 0xfb, 0xf6, 0x95, 0xec, - 0x35, 0x10, 0x22, 0x88, 0x34, 0x54, 0xab, 0x44, 0xb6, 0xe8, 0xd9, 0xf8, 0x17, 0x32, 0x57, 0x77, - 0x76, 0x7d, 0x1f, 0x42, 0x29, 0x6a, 0x35, 0x79, 0xc2, 0x2a, 0xcc, 0xa8, 0x5c, 0x9c, 0xe3, 0xa8, - 0x95, 0x27, 0x46, 0x4c, 0x9b, 0x0b, 0x9d, 0x0d, 0x5d, 0x6d, 0xd4, 0xdf, 0x00, 0x76, 0xea, 0xf8, - 0xb3, 0xc8, 0xb4, 0xd9, 0x1a, 0x58, 0xa2, 0x61, 0x1b, 0xc7, 0xb0, 0xa4, 0xb8, 0x84, 0xa6, 0x11, - 0x24, 0x5f, 0x5e, 0xe6, 0x25, 0x4c, 0x3e, 0x3b, 0xc7, 0xe4, 0x8d, 0x9f, 0xe6, 0xa1, 0xa8, 0x6e, - 0x16, 0x4b, 0xbb, 0x0d, 0xab, 0x9c, 0xbc, 0x0d, 0xab, 0x95, 0xb8, 0x39, 0x05, 0x5f, 0xbd, 0x3c, - 0xef, 0xdf, 0x99, 0x3d, 0xb2, 0x35, 0xa3, 0x79, 0xe2, 0xd8, 0x5e, 0x85, 0xfc, 0xc4, 0x0e, 0xcf, - 0xd1, 0x40, 0x46, 0xc4, 0x83, 0xcf, 0xca, 0x98, 0x5e, 0x48, 0x1a, 0xd3, 0xd3, 0x6e, 0x0e, 0x23, - 0x91, 0x74, 0xee, 0xe6, 0xb0, 0x3b, 0x40, 0xf2, 0x85, 0x16, 0x2b, 0x55, 0x42, 0x80, 0x38, 0x8b, - 0x92, 0xe2, 0x48, 0x69, 0x56, 0x1c, 0x79, 0x65, 0x51, 0xe1, 0xdb, 0xb0, 0x40, 0x59, 0xf7, 0x32, - 0x61, 0x4f, 0x1d, 0x28, 0x72, 0x0d, 0xd5, 0x7f, 0x8a, 0xa0, 0x36, 0x25, 0xae, 0x7e, 0x0d, 0x4f, - 0x25, 0x71, 0x0d, 0x8f, 0x6e, 0xe4, 0xaf, 0x26, 0x8d, 0xfc, 0x0f, 0xa0, 0x11, 0x2d, 0x28, 0x9a, - 0xcc, 0xdc, 0x40, 0xa6, 0x03, 0xd5, 0x15, 0x5c, 0x70, 0xc9, 0x83, 0x20, 0x3e, 0x10, 0xeb, 0x89, - 0x03, 0x51, 0xf0, 0xb0, 0x76, 0x18, 0xf2, 0xf1, 0x24, 0x94, 0x07, 0x22, 0x26, 0x0c, 0xe8, 0x03, - 0x4c, 0xa6, 0xb2, 0xd6, 0xa0, 0xdc, 0x3d, 0xb0, 0x76, 0xf6, 0xba, 0x4f, 0x77, 0xfb, 0x8d, 0x8c, - 0x78, 0xec, 0x1d, 0x6f, 0x6d, 0x75, 0x3a, 0xdb, 0x78, 0xe2, 0x00, 0x2c, 0xec, 0xb4, 0xbb, 0xe2, - 0xf4, 0xc9, 0x19, 0xbf, 0x93, 0x85, 0x8a, 0xd6, 0x3c, 0x7b, 0x3f, 0x5a, 0x15, 0xba, 0xa9, 0xe5, - 0xee, 0xfc, 0x10, 0x36, 0x14, 0x2b, 0xd6, 0x96, 0x25, 0xba, 0x27, 0x2d, 0x7b, 0xe3, 0x3d, 0x69, - 0xec, 0x6d, 0x58, 0xb4, 0xa9, 0x85, 0x68, 0x15, 0xa4, 0x39, 0x58, 0x82, 0xe5, 0x22, 0x60, 0x84, - 0x60, 0x7c, 0x9e, 0x08, 0xbc, 0xbc, 0x0a, 0xca, 0x8b, 0x8e, 0x14, 0x5c, 0xac, 0xe2, 0xa9, 0xed, - 0x8c, 0xa6, 0x3e, 0x97, 0xee, 0xdb, 0xe8, 0x64, 0x26, 0xa8, 0xa9, 0x8a, 0x8d, 0x0f, 0x00, 0xe2, - 0x31, 0x27, 0x17, 0xe7, 0x56, 0x72, 0x71, 0x32, 0xda, 0xe2, 0x64, 0x8d, 0x6d, 0x62, 0x23, 0x72, - 0xa1, 0x23, 0x4f, 0xf5, 0x37, 0x41, 0x59, 0xa4, 0x2c, 0x8c, 0xd1, 0x9d, 0x8c, 0x78, 0xa8, 0x92, - 0x7e, 0x9b, 0xb2, 0xa4, 0x1b, 0x15, 0xa8, 0x1c, 0xfc, 0xb8, 0x95, 0x98, 0x1b, 0x49, 0x92, 0x9c, - 0xe5, 0x46, 0x12, 0xd5, 0x8c, 0xca, 0x8d, 0x75, 0x68, 0x6d, 0x73, 0xd1, 0x5a, 0x7b, 0x34, 0x9a, - 0x19, 0x8e, 0x71, 0x07, 0x6e, 0xa7, 0x94, 0x49, 0x23, 0xc4, 0xc7, 0xb0, 0xd2, 0xa6, 0xfc, 0xde, - 0xaf, 0x2a, 0x91, 0xc7, 0x68, 0xc1, 0xea, 0x6c, 0x93, 0xb2, 0xb3, 0x1d, 0x68, 0x6e, 0xf3, 0x93, - 0xe9, 0xd9, 0x1e, 0xbf, 0x88, 0x3b, 0x62, 0x90, 0x0f, 0xce, 0xbd, 0x4b, 0xb9, 0x3e, 0xf8, 0x1b, - 0xc3, 0xdd, 0x04, 0x8e, 0x15, 0x4c, 0xf8, 0x40, 0x59, 0x44, 0x11, 0xd2, 0x9b, 0xf0, 0x81, 0xf1, - 0x3e, 0x30, 0xbd, 0x1d, 0xb9, 0x5e, 0x42, 0x4b, 0x98, 0x9e, 0x58, 0xc1, 0x75, 0x10, 0xf2, 0xb1, - 0xba, 0x08, 0x08, 0x82, 0xe9, 0x49, 0x8f, 0x20, 0xc6, 0x3b, 0x50, 0x3d, 0xb2, 0xaf, 0x4d, 0xfe, - 0xb9, 0x4c, 0x51, 0x59, 0x83, 0xe2, 0xc4, 0xbe, 0x16, 0x6c, 0x20, 0x72, 0x8e, 0x60, 0xb1, 0xf1, - 0x87, 0x79, 0x58, 0x20, 0x4c, 0x76, 0x9f, 0xee, 0xea, 0x74, 0x5c, 0xdc, 0x86, 0x8a, 0x51, 0x6a, - 0xa0, 0x39, 0x5e, 0x9a, 0x9d, 0xe7, 0xa5, 0xd2, 0x80, 0xa6, 0xee, 0x28, 0x51, 0x66, 0x6c, 0x77, - 0x3a, 0x56, 0x17, 0x93, 0x24, 0x93, 0x5c, 0xf3, 0xf1, 0x5d, 0xac, 0x94, 0x01, 0x98, 0x74, 0x34, - 0xc6, 0xba, 0x08, 0x8d, 0x4e, 0x1d, 0x11, 0x92, 0x5d, 0xea, 0xa0, 0x54, 0x85, 0xa7, 0xa8, 0x92, - 0x9f, 0x92, 0x0a, 0xcf, 0x9c, 0x62, 0x53, 0x7a, 0xb9, 0x62, 0x43, 0x96, 0xb5, 0x17, 0x28, 0x36, - 0xf0, 0x0a, 0x8a, 0xcd, 0x2b, 0x38, 0xf9, 0x6e, 0x43, 0x09, 0xcf, 0x7d, 0x8d, 0x7b, 0x8a, 0xf3, - 0x5e, 0x70, 0xcf, 0xef, 0x68, 0xa2, 0x3f, 0x45, 0x18, 0xdc, 0x89, 0xb7, 0x89, 0xc9, 0x3f, 0xff, - 0xc5, 0x38, 0x4f, 0x3e, 0x83, 0xa2, 0x84, 0x0a, 0x82, 0x76, 0xed, 0xb1, 0xba, 0xe6, 0x09, 0x7f, - 0x8b, 0x65, 0xc3, 0xbb, 0x69, 0x3e, 0x9f, 0x3a, 0x3e, 0x1f, 0xaa, 0xfb, 0x3b, 0x1c, 0xdc, 0xa3, - 0x02, 0x22, 0x26, 0x28, 0xd4, 0x10, 0xd7, 0xbb, 0x74, 0x65, 0xf6, 0x7e, 0xd1, 0x09, 0x9e, 0x89, - 0x47, 0x83, 0x41, 0x03, 0x2f, 0x7a, 0x9b, 0x78, 0xbe, 0x3a, 0x9c, 0x8c, 0x9f, 0x66, 0xa0, 0x21, - 0x77, 0x57, 0x54, 0xa6, 0x6b, 0x01, 0x85, 0x9b, 0x1c, 0xe2, 0x2f, 0xbe, 0x8d, 0xc3, 0x80, 0x1a, - 0x1a, 0x3f, 0xa2, 0x93, 0x8a, 0x8c, 0x37, 0x15, 0x01, 0xdc, 0x91, 0xa7, 0xd5, 0xeb, 0x50, 0x51, - 0xc1, 0xb8, 0x63, 0x67, 0xa4, 0xae, 0x5d, 0xa6, 0x68, 0xdc, 0x7d, 0x67, 0xa4, 0x0e, 0x3a, 0xdf, - 0x96, 0xc9, 0x78, 0x19, 0x3c, 0xe8, 0x4c, 0x3b, 0xe4, 0xc6, 0x7f, 0xc8, 0x40, 0x53, 0x9b, 0x8a, - 0xdc, 0xb7, 0x1f, 0x42, 0x35, 0xba, 0x61, 0x91, 0x47, 0x92, 0xd7, 0x5a, 0x92, 0xd1, 0xc4, 0xd5, - 0x2a, 0x83, 0x08, 0x12, 0x88, 0xc1, 0x0c, 0xed, 0x6b, 0x8a, 0x18, 0x9d, 0x8e, 0x95, 0x72, 0x33, - 0xb4, 0xaf, 0x77, 0x38, 0xef, 0x4d, 0xc7, 0x42, 0x75, 0xbd, 0xe4, 0xfc, 0x79, 0x84, 0x40, 0x32, - 0x17, 0x08, 0x98, 0xc4, 0x30, 0xa0, 0x36, 0xf6, 0xdc, 0xf0, 0x3c, 0x42, 0x91, 0x52, 0x27, 0x02, - 0x09, 0xc7, 0xf8, 0xb3, 0x2c, 0x2c, 0x91, 0x89, 0x4d, 0x9a, 0x36, 0x25, 0xeb, 0x6a, 0xc1, 0x02, - 0x59, 0x1b, 0x89, 0x79, 0xed, 0xde, 0x32, 0xe5, 0x33, 0xfb, 0xf6, 0x2b, 0x9a, 0x05, 0x55, 0xbe, - 0xdf, 0x0d, 0xcb, 0x9f, 0x9b, 0x5f, 0xfe, 0x9b, 0x97, 0x37, 0xcd, 0xe3, 0x56, 0x48, 0xf3, 0xb8, - 0xbd, 0x8a, 0x9f, 0x6b, 0x2e, 0x29, 0xae, 0x28, 0x71, 0xb4, 0xa4, 0xb8, 0xf7, 0x61, 0x2d, 0x81, - 0x83, 0xdc, 0xda, 0x39, 0x75, 0xb8, 0xba, 0x1c, 0x61, 0x59, 0xc3, 0xee, 0xa9, 0xb2, 0xcd, 0x22, - 0x14, 0x82, 0x81, 0x37, 0xe1, 0xc6, 0x2a, 0x2c, 0x27, 0x57, 0x55, 0x1e, 0x13, 0xbf, 0x9b, 0x81, - 0x96, 0x8c, 0x8f, 0x70, 0xdc, 0xb3, 0x5d, 0x27, 0x08, 0x3d, 0x3f, 0xba, 0x89, 0xf0, 0x2e, 0x40, - 0x10, 0xda, 0xbe, 0xd4, 0x36, 0xe5, 0x75, 0x00, 0x08, 0x41, 0x4d, 0xf2, 0x36, 0x94, 0xb8, 0x3b, - 0xa4, 0x42, 0xa2, 0x86, 0x22, 0x77, 0x87, 0x4a, 0x0f, 0x9d, 0x93, 0xbf, 0x6b, 0x49, 0xf5, 0x42, - 0x66, 0xe7, 0x8a, 0xd5, 0xe1, 0x17, 0x78, 0xf0, 0xe6, 0xa3, 0xec, 0xdc, 0x7d, 0xfb, 0x0a, 0xa3, - 0x0d, 0x03, 0xe3, 0x9f, 0x66, 0x61, 0x31, 0x1e, 0x1f, 0xa5, 0xf6, 0xbf, 0xf8, 0x92, 0x82, 0xfb, - 0x92, 0x1c, 0x1c, 0x21, 0xbf, 0x6b, 0x86, 0xc7, 0x12, 0x6d, 0xce, 0xae, 0xcb, 0x0c, 0xa8, 0x28, - 0x0c, 0x6f, 0x1a, 0x6a, 0x17, 0x82, 0x95, 0x09, 0xe5, 0x70, 0x1a, 0x0a, 0x85, 0x4b, 0x68, 0x9e, - 0x8e, 0x2b, 0x55, 0x9e, 0x82, 0x3d, 0x0e, 0xbb, 0x78, 0xcf, 0xb8, 0x00, 0x8b, 0x6a, 0xf4, 0x22, - 0x05, 0x96, 0xc0, 0x6f, 0x90, 0x9c, 0x4d, 0x6f, 0x0e, 0x65, 0x6c, 0x5d, 0x08, 0xa5, 0x2b, 0x57, - 0x23, 0x21, 0xf4, 0x75, 0xa8, 0x50, 0xe3, 0x71, 0x0e, 0x64, 0xde, 0x2c, 0x63, 0x0f, 0x58, 0x2e, - 0x8d, 0x40, 0xde, 0x34, 0xa1, 0xfa, 0x02, 0x75, 0x85, 0xe1, 0x07, 0xff, 0x30, 0x03, 0xb7, 0x53, - 0x5e, 0x9b, 0xdc, 0xe5, 0x5b, 0xd0, 0x3c, 0x8d, 0x0a, 0xd5, 0xea, 0xd2, 0x56, 0x5f, 0x55, 0x6c, - 0x35, 0xb9, 0xa6, 0x66, 0xe3, 0x34, 0x09, 0x88, 0x95, 0x2e, 0x7a, 0x83, 0x89, 0x34, 0x57, 0x54, - 0xba, 0xe8, 0x35, 0x92, 0xbe, 0x73, 0x04, 0xeb, 0x9d, 0x2b, 0xc1, 0x31, 0xb6, 0xf4, 0x8b, 0xf2, - 0x15, 0x19, 0x25, 0x0d, 0xcc, 0x99, 0x57, 0x32, 0x30, 0x0f, 0x29, 0x9b, 0x2f, 0x6a, 0xeb, 0x67, - 0x69, 0x04, 0x0f, 0x50, 0x51, 0x87, 0x2e, 0xfa, 0x57, 0xa9, 0xb6, 0x83, 0xe8, 0x82, 0x7f, 0x23, - 0x80, 0xc5, 0xfd, 0xe9, 0x28, 0x74, 0xe2, 0x3b, 0xff, 0xd9, 0xb7, 0x65, 0x1d, 0xec, 0x47, 0xad, - 0x5a, 0x6a, 0x47, 0x10, 0x75, 0x84, 0x8b, 0x35, 0x16, 0x0d, 0x59, 0xf3, 0xfd, 0x2d, 0x8e, 0x93, - 0x3d, 0x18, 0xb7, 0x61, 0x2d, 0x7e, 0xa2, 0x65, 0x53, 0x47, 0xcd, 0xbf, 0xca, 0x50, 0x68, 0x73, - 0xf2, 0xfb, 0x03, 0xac, 0x03, 0x4b, 0x81, 0xe3, 0x9e, 0x8d, 0xb8, 0xde, 0x7c, 0x20, 0x17, 0x61, - 0x25, 0x39, 0x36, 0xf9, 0x8d, 0x02, 0xb3, 0x49, 0x35, 0xe2, 0xd6, 0x02, 0xb6, 0x79, 0xd3, 0x20, - 0x63, 0xb2, 0x98, 0x59, 0x8d, 0xf9, 0xc1, 0x77, 0xa1, 0x9e, 0xec, 0x88, 0x7d, 0x47, 0x66, 0xb2, - 0xc6, 0xa3, 0xca, 0xcd, 0xe4, 0x1c, 0xc6, 0x04, 0x51, 0x89, 0xd7, 0x3e, 0x30, 0xfe, 0x71, 0x06, - 0x5a, 0x26, 0x17, 0x94, 0xab, 0x8d, 0x52, 0xd1, 0xcc, 0x87, 0x73, 0xad, 0xde, 0x3c, 0x57, 0x95, - 0x20, 0xab, 0x46, 0xf4, 0x8d, 0x1b, 0x5f, 0xc6, 0xee, 0xad, 0xb9, 0x19, 0x6d, 0x96, 0x60, 0x81, - 0x50, 0x8c, 0x35, 0x58, 0x91, 0xe3, 0x51, 0x63, 0x89, 0xbd, 0x87, 0x89, 0x1e, 0x13, 0xde, 0xc3, - 0x75, 0x68, 0xd1, 0x85, 0x92, 0xfa, 0x24, 0x64, 0xc5, 0x6d, 0x60, 0xfb, 0xf6, 0xc0, 0xf6, 0x3d, - 0xcf, 0x3d, 0xe2, 0xbe, 0x0c, 0x14, 0x45, 0x09, 0x13, 0x9d, 0x6b, 0x4a, 0x14, 0xa6, 0x27, 0x75, - 0x0d, 0xa2, 0xe7, 0xaa, 0xb8, 0x18, 0x7a, 0x32, 0x4c, 0x58, 0xda, 0xb4, 0x9f, 0x73, 0xd5, 0x92, - 0x5a, 0xa2, 0x8f, 0xa0, 0x32, 0x89, 0x1a, 0x55, 0xeb, 0xae, 0xd2, 0xdd, 0xe7, 0xbb, 0x35, 0x75, - 0x6c, 0xe3, 0x09, 0x2c, 0x27, 0xdb, 0x94, 0xac, 0x63, 0x1d, 0x4a, 0x63, 0x09, 0x93, 0xa3, 0x8b, - 0x9e, 0x8d, 0xdf, 0x2e, 0x41, 0x51, 0xea, 0x73, 0x6c, 0x03, 0xf2, 0x03, 0x15, 0x9b, 0x14, 0xdf, - 0xa2, 0x22, 0x4b, 0xd5, 0xff, 0x2d, 0x8c, 0x50, 0x12, 0x78, 0xec, 0x23, 0xa8, 0x27, 0xbd, 0xa2, - 0x33, 0xb9, 0xb4, 0x49, 0x77, 0x66, 0x6d, 0x30, 0xe3, 0xff, 0x2a, 0xc7, 0x87, 0x23, 0xc9, 0x0c, - 0xa5, 0x73, 0xed, 0xf4, 0xf4, 0x5c, 0x21, 0x6f, 0x07, 0xe7, 0xb6, 0xf5, 0xe4, 0xfd, 0x0f, 0x64, - 0x32, 0x6d, 0x05, 0x81, 0xbd, 0x73, 0xfb, 0xc9, 0xfb, 0x1f, 0xcc, 0x4a, 0xd2, 0x32, 0x95, 0x56, - 0x93, 0xa4, 0x97, 0xa1, 0x40, 0xf7, 0xfd, 0x51, 0x90, 0x09, 0x3d, 0xb0, 0xc7, 0xb0, 0x2c, 0xd5, - 0x56, 0x4b, 0x86, 0x03, 0x13, 0x17, 0x2c, 0x51, 0x06, 0x96, 0x2c, 0xeb, 0x61, 0x11, 0xd9, 0x86, - 0x56, 0x61, 0xe1, 0x3c, 0xbe, 0xbc, 0xb1, 0x66, 0xca, 0x27, 0xe3, 0xcf, 0x0a, 0x50, 0xd1, 0x16, - 0x85, 0x55, 0xa1, 0x64, 0x76, 0x7a, 0x1d, 0xf3, 0x93, 0xce, 0x76, 0xe3, 0x16, 0x7b, 0x00, 0x6f, - 0x75, 0x0f, 0xb6, 0x0e, 0x4d, 0xb3, 0xb3, 0xd5, 0xb7, 0x0e, 0x4d, 0x4b, 0xdd, 0xe5, 0x73, 0xd4, - 0xfe, 0x6c, 0xbf, 0x73, 0xd0, 0xb7, 0xb6, 0x3b, 0xfd, 0x76, 0x77, 0xaf, 0xd7, 0xc8, 0xb0, 0xd7, - 0xa0, 0x15, 0x63, 0xaa, 0xe2, 0xf6, 0xfe, 0xe1, 0xf1, 0x41, 0xbf, 0x91, 0x65, 0xf7, 0xe0, 0xce, - 0x4e, 0xf7, 0xa0, 0xbd, 0x67, 0xc5, 0x38, 0x5b, 0x7b, 0xfd, 0x4f, 0xac, 0xce, 0xaf, 0x1e, 0x75, - 0xcd, 0xcf, 0x1a, 0xb9, 0x34, 0x04, 0xa1, 0x8c, 0xab, 0x16, 0xf2, 0xec, 0x36, 0xac, 0x10, 0x02, - 0x55, 0xb1, 0xfa, 0x87, 0x87, 0x56, 0xef, 0xf0, 0xf0, 0xa0, 0x51, 0x60, 0x4d, 0xa8, 0x75, 0x0f, - 0x3e, 0x69, 0xef, 0x75, 0xb7, 0x2d, 0xb3, 0xd3, 0xde, 0xdb, 0x6f, 0x2c, 0xb0, 0x25, 0x58, 0x9c, - 0xc5, 0x2b, 0x8a, 0x26, 0x14, 0xde, 0xe1, 0x41, 0xf7, 0xf0, 0xc0, 0xfa, 0xa4, 0x63, 0xf6, 0xba, - 0x87, 0x07, 0x8d, 0x12, 0x5b, 0x05, 0x96, 0x2c, 0xda, 0xdd, 0x6f, 0x6f, 0x35, 0xca, 0x6c, 0x05, - 0x9a, 0x49, 0xf8, 0xb3, 0xce, 0x67, 0x0d, 0x60, 0x2d, 0x58, 0xa6, 0x81, 0x59, 0x9b, 0x9d, 0xbd, - 0xc3, 0x4f, 0xad, 0xfd, 0xee, 0x41, 0x77, 0xff, 0x78, 0xbf, 0x51, 0xc1, 0xdb, 0xc5, 0x3a, 0x1d, - 0xab, 0x7b, 0xd0, 0x3b, 0xde, 0xd9, 0xe9, 0x6e, 0x75, 0x3b, 0x07, 0xfd, 0x46, 0x95, 0x7a, 0x4e, - 0x9b, 0x78, 0x4d, 0x54, 0x90, 0x39, 0x03, 0xd6, 0x76, 0xb7, 0xd7, 0xde, 0xdc, 0xeb, 0x6c, 0x37, - 0xea, 0xec, 0x2e, 0xdc, 0xee, 0x77, 0xf6, 0x8f, 0x0e, 0xcd, 0xb6, 0xf9, 0x99, 0xca, 0x29, 0xb0, - 0x76, 0xda, 0xdd, 0xbd, 0x63, 0xb3, 0xd3, 0x58, 0x64, 0x6f, 0xc0, 0x5d, 0xb3, 0xf3, 0xf1, 0x71, - 0xd7, 0xec, 0x6c, 0x5b, 0x07, 0x87, 0xdb, 0x1d, 0x6b, 0xa7, 0xd3, 0xee, 0x1f, 0x9b, 0x1d, 0x6b, - 0xbf, 0xdb, 0xeb, 0x75, 0x0f, 0x9e, 0x36, 0x1a, 0xec, 0x2d, 0xb8, 0x1f, 0xa1, 0x44, 0x0d, 0xcc, - 0x60, 0x35, 0xc5, 0xfc, 0xd4, 0x2b, 0x3d, 0xe8, 0xfc, 0x6a, 0xdf, 0x3a, 0xea, 0x74, 0xcc, 0x06, - 0x63, 0xeb, 0xb0, 0x1a, 0x77, 0x4f, 0x1d, 0xc8, 0xbe, 0x97, 0x44, 0xd9, 0x51, 0xc7, 0xdc, 0x6f, - 0x1f, 0x88, 0x17, 0x9c, 0x28, 0x5b, 0x16, 0xc3, 0x8e, 0xcb, 0x66, 0x87, 0xbd, 0xc2, 0x18, 0xd4, - 0xb5, 0xb7, 0xb2, 0xd3, 0x36, 0x1b, 0xab, 0x6c, 0x11, 0x2a, 0xfb, 0x47, 0x47, 0x56, 0xbf, 0xbb, - 0xdf, 0x39, 0x3c, 0xee, 0x37, 0xd6, 0xd8, 0x0a, 0x34, 0xba, 0x07, 0xfd, 0x8e, 0x29, 0xde, 0xb5, - 0xaa, 0xfa, 0xbf, 0x8b, 0x6c, 0x19, 0x16, 0xd5, 0x48, 0x15, 0xf4, 0xaf, 0x8a, 0x6c, 0x0d, 0xd8, - 0xf1, 0x81, 0xd9, 0x69, 0x6f, 0x8b, 0x85, 0x8b, 0x0a, 0xfe, 0x4f, 0x51, 0x7a, 0x48, 0x7e, 0x9a, - 0x8b, 0x0e, 0xeb, 0x38, 0xe4, 0x20, 0x79, 0x95, 0x6f, 0x55, 0xbb, 0x82, 0xf7, 0x65, 0x97, 0xec, - 0x6b, 0xaa, 0x55, 0x6e, 0x4e, 0xb5, 0x9a, 0xd3, 0xdd, 0x6b, 0xba, 0xec, 0xf7, 0x26, 0xd4, 0xc6, - 0x74, 0xad, 0xaf, 0xbc, 0xbe, 0x13, 0x64, 0xfc, 0x0d, 0x01, 0xe9, 0xee, 0xce, 0xb9, 0x5b, 0xe6, - 0x0b, 0xf3, 0xb7, 0xcc, 0xa7, 0xc9, 0xf7, 0x0b, 0x69, 0xf2, 0xfd, 0x43, 0x68, 0x12, 0x6b, 0x72, - 0x5c, 0x67, 0xac, 0xb4, 0x66, 0x92, 0x02, 0x17, 0x91, 0x45, 0x11, 0x5c, 0xa9, 0x13, 0x4a, 0xe5, - 0x90, 0x2c, 0xa4, 0x28, 0xb5, 0x8d, 0x84, 0xa6, 0x41, 0x9c, 0x23, 0xd2, 0x34, 0xa2, 0x1e, 0xec, - 0xab, 0xb8, 0x87, 0x8a, 0xd6, 0x03, 0xc1, 0xb1, 0x87, 0x87, 0xd0, 0xe4, 0x57, 0xa1, 0x6f, 0x5b, - 0xde, 0xc4, 0xfe, 0x7c, 0x8a, 0x2e, 0x5c, 0x1b, 0x75, 0xf8, 0xaa, 0xb9, 0x88, 0x05, 0x87, 0x08, - 0xdf, 0xb6, 0x43, 0xfb, 0xe1, 0x17, 0x50, 0xd1, 0xae, 0x7c, 0x66, 0x6b, 0xb0, 0xf4, 0x69, 0xb7, - 0x7f, 0xd0, 0xe9, 0xf5, 0xac, 0xa3, 0xe3, 0xcd, 0x67, 0x9d, 0xcf, 0xac, 0xdd, 0x76, 0x6f, 0xb7, - 0x71, 0x4b, 0x6c, 0xda, 0x83, 0x4e, 0xaf, 0xdf, 0xd9, 0x4e, 0xc0, 0x33, 0xec, 0x75, 0x58, 0x3f, - 0x3e, 0x38, 0xee, 0x75, 0xb6, 0xad, 0xb4, 0x7a, 0x59, 0x41, 0xa5, 0xb2, 0x3c, 0xa5, 0x7a, 0xee, - 0xe1, 0xf7, 0xa1, 0x9e, 0xbc, 0x87, 0x94, 0x01, 0x2c, 0xec, 0x75, 0x9e, 0xb6, 0xb7, 0x3e, 0xa3, - 0xfb, 0x07, 0x7b, 0xfd, 0x76, 0xbf, 0xbb, 0x65, 0xc9, 0xfb, 0x06, 0x05, 0x47, 0xc8, 0xb0, 0x0a, - 0x14, 0xdb, 0x07, 0x5b, 0xbb, 0x87, 0x66, 0xaf, 0x91, 0x7d, 0xf8, 0x11, 0x34, 0x66, 0xfd, 0x51, - 0x09, 0x07, 0xde, 0x8b, 0x3c, 0x7d, 0x0f, 0xff, 0x6d, 0x0e, 0x20, 0x4e, 0x18, 0x10, 0xac, 0x66, - 0xbb, 0xdd, 0x6f, 0xef, 0x1d, 0x8a, 0x69, 0x98, 0x87, 0x7d, 0xc1, 0x41, 0xcc, 0xce, 0xc7, 0x8d, - 0x5b, 0xa9, 0x25, 0x87, 0x47, 0xfd, 0x46, 0x46, 0xac, 0x58, 0xf7, 0xa0, 0xdb, 0xef, 0xb6, 0xf7, - 0x2c, 0xf3, 0xf0, 0xb8, 0x7b, 0xf0, 0x94, 0x2e, 0x56, 0x43, 0x2e, 0x7b, 0x7c, 0xb4, 0x63, 0x1e, - 0x1e, 0xf4, 0xad, 0xde, 0xee, 0x71, 0x7f, 0x1b, 0xaf, 0x65, 0xdb, 0x32, 0xbb, 0x47, 0xd4, 0x66, - 0xfe, 0x45, 0x08, 0xa2, 0xe9, 0x82, 0x58, 0xf3, 0xa7, 0x87, 0xbd, 0x5e, 0xf7, 0xc8, 0xfa, 0xf8, - 0xb8, 0x63, 0x76, 0x3b, 0x3d, 0xac, 0xb8, 0x90, 0x02, 0x17, 0xf8, 0x45, 0xc1, 0x9b, 0xfb, 0x7b, - 0x9f, 0x48, 0xe6, 0x29, 0x50, 0x4b, 0x49, 0x90, 0xc0, 0x2a, 0x0b, 0x9e, 0x22, 0xb8, 0x4f, 0x4a, - 0xcb, 0x70, 0x43, 0x99, 0xa8, 0x57, 0x11, 0x7c, 0x75, 0xee, 0x65, 0x60, 0xb5, 0x6a, 0x7a, 0x91, - 0xa8, 0x85, 0x2c, 0x37, 0x3a, 0xa0, 0xb6, 0xb7, 0x4d, 0xac, 0x50, 0x9f, 0x83, 0x0a, 0xdc, 0x45, - 0xf1, 0xa2, 0x04, 0x7b, 0x12, 0x28, 0x0d, 0xf5, 0x20, 0x4a, 0x9a, 0x4f, 0x7e, 0x2b, 0x07, 0x75, - 0x4a, 0xde, 0xa2, 0x2f, 0x6e, 0x71, 0x9f, 0xed, 0x43, 0x51, 0x7e, 0xba, 0x8d, 0xad, 0x44, 0x77, - 0x5e, 0xe9, 0x1f, 0x8b, 0x5b, 0x5f, 0x9d, 0x05, 0x4b, 0x71, 0x6c, 0xe9, 0xef, 0xfc, 0xe9, 0xff, - 0xfa, 0x27, 0xd9, 0x1a, 0xab, 0x3c, 0xba, 0x78, 0xef, 0xd1, 0x19, 0x77, 0x03, 0xd1, 0xc6, 0xdf, - 0x04, 0x88, 0x3f, 0x48, 0xc6, 0x5a, 0x91, 0x13, 0x6a, 0xe6, 0x6b, 0x6d, 0xeb, 0xb7, 0x53, 0x4a, - 0x64, 0xbb, 0xb7, 0xb1, 0xdd, 0x25, 0xa3, 0x2e, 0xda, 0x75, 0x5c, 0x27, 0xa4, 0x8f, 0x93, 0x7d, - 0x98, 0x79, 0xc8, 0x86, 0x50, 0xd5, 0x3f, 0x15, 0xc6, 0x94, 0xa4, 0x94, 0xf2, 0xb1, 0xb3, 0xf5, - 0x3b, 0xa9, 0x65, 0x4a, 0x06, 0xc5, 0x3e, 0x56, 0x8c, 0x86, 0xe8, 0x63, 0x8a, 0x18, 0x71, 0x2f, - 0x23, 0x92, 0xca, 0xe3, 0x2f, 0x82, 0xb1, 0xd7, 0x34, 0xb9, 0x6a, 0xee, 0x7b, 0x64, 0xeb, 0x77, - 0x6f, 0x28, 0x95, 0x7d, 0xdd, 0xc5, 0xbe, 0xd6, 0x0c, 0x26, 0xfa, 0x1a, 0x20, 0x8e, 0xfa, 0x1e, - 0xd9, 0x87, 0x99, 0x87, 0x4f, 0xfe, 0xf2, 0x01, 0x94, 0xa3, 0x60, 0x4e, 0xf6, 0x1b, 0x50, 0x4b, - 0x64, 0xd7, 0x31, 0x35, 0x8d, 0xb4, 0x64, 0xbc, 0xf5, 0xd7, 0xd2, 0x0b, 0x65, 0xc7, 0xaf, 0x63, - 0xc7, 0x2d, 0xb6, 0x2a, 0x3a, 0x96, 0xd9, 0x6b, 0x8f, 0x30, 0x1b, 0x96, 0x6e, 0x10, 0x7b, 0xae, - 0x69, 0x1f, 0xd4, 0xd9, 0x6b, 0xb3, 0x1a, 0x41, 0xa2, 0xb7, 0xbb, 0x37, 0x94, 0xca, 0xee, 0x5e, - 0xc3, 0xee, 0x56, 0xd9, 0xb2, 0xde, 0x9d, 0x0a, 0xbd, 0x64, 0x1c, 0x6f, 0xed, 0xd3, 0x3f, 0x98, - 0xc5, 0xee, 0xc6, 0x77, 0xac, 0xa5, 0x7c, 0x48, 0x2b, 0x22, 0x91, 0xf9, 0xaf, 0x69, 0x19, 0x2d, - 0xec, 0x8a, 0x31, 0x7c, 0x7d, 0xfa, 0xf7, 0xb2, 0xd8, 0x09, 0x54, 0xb4, 0x6f, 0x4c, 0xb0, 0xdb, - 0x37, 0x7e, 0x0f, 0x63, 0x7d, 0x3d, 0xad, 0x28, 0x6d, 0x2a, 0x7a, 0xfb, 0x8f, 0x4e, 0x39, 0x67, - 0xbf, 0x06, 0xe5, 0xe8, 0xcb, 0x05, 0x6c, 0x4d, 0xfb, 0x92, 0x84, 0xfe, 0xa5, 0x85, 0xf5, 0xd6, - 0x7c, 0x41, 0x1a, 0xf1, 0xe9, 0xad, 0x0b, 0xe2, 0xfb, 0x14, 0x2a, 0xda, 0xd7, 0x09, 0xa2, 0x09, - 0xcc, 0x7f, 0x01, 0x21, 0x9a, 0x40, 0xca, 0xc7, 0x0c, 0x8c, 0x26, 0x76, 0x51, 0x61, 0x65, 0xa4, - 0xef, 0xf0, 0xca, 0x0b, 0xd8, 0x1e, 0xac, 0x48, 0x4d, 0xeb, 0x84, 0x7f, 0x99, 0xd7, 0x90, 0xf2, - 0x8d, 0xb2, 0xc7, 0x19, 0xf6, 0x11, 0x94, 0xd4, 0x47, 0x28, 0xd8, 0x6a, 0xfa, 0xc7, 0x34, 0xd6, - 0xd7, 0xe6, 0xe0, 0x52, 0x2d, 0xfa, 0x0c, 0x20, 0xfe, 0x14, 0x42, 0xc4, 0x24, 0xe6, 0x3e, 0xad, - 0x10, 0x51, 0xc0, 0xfc, 0x77, 0x13, 0x8c, 0x55, 0x9c, 0x60, 0x83, 0x21, 0x93, 0x70, 0xf9, 0xa5, - 0xba, 0x5a, 0xf5, 0x47, 0x50, 0xd1, 0xbe, 0x86, 0x10, 0x2d, 0xdf, 0xfc, 0x97, 0x14, 0xa2, 0xe5, - 0x4b, 0xf9, 0x78, 0x82, 0xb1, 0x8e, 0xad, 0x2f, 0x1b, 0x8b, 0xa2, 0x75, 0x21, 0x6a, 0x49, 0x91, - 0x47, 0xbc, 0xa0, 0x73, 0xa8, 0x25, 0x3e, 0x79, 0x10, 0xed, 0xd0, 0xb4, 0x0f, 0x2a, 0x44, 0x3b, - 0x34, 0xf5, 0x2b, 0x09, 0x8a, 0xce, 0x8c, 0xa6, 0xe8, 0xe7, 0x02, 0x51, 0xb4, 0x9e, 0x7e, 0x08, - 0x15, 0xed, 0xf3, 0x05, 0xd1, 0x5c, 0xe6, 0xbf, 0x94, 0x10, 0xcd, 0x25, 0xed, 0x6b, 0x07, 0xcb, - 0xd8, 0x47, 0xdd, 0x40, 0x52, 0xc0, 0xcb, 0x21, 0x45, 0xdb, 0xbf, 0x01, 0xf5, 0xe4, 0x17, 0x0d, - 0xa2, 0xbd, 0x9f, 0xfa, 0x69, 0x84, 0x68, 0xef, 0xdf, 0xf0, 0x19, 0x04, 0x49, 0xd2, 0x0f, 0x97, - 0xa2, 0x4e, 0x1e, 0xfd, 0x44, 0xa6, 0xa5, 0x7c, 0xc1, 0x3e, 0x16, 0x0c, 0x4e, 0xde, 0x4d, 0xca, - 0xd6, 0x34, 0xaa, 0xd5, 0x2f, 0x39, 0x8d, 0xf6, 0xcb, 0xdc, 0x35, 0xa6, 0x49, 0x62, 0xc6, 0xc6, - 0xd9, 0x53, 0x58, 0x8a, 0x88, 0x39, 0xba, 0x6c, 0x34, 0x88, 0xe6, 0x90, 0x7a, 0xa5, 0xe9, 0x7a, - 0x63, 0xb6, 0xf4, 0x71, 0x86, 0x8e, 0x3f, 0xbc, 0xe2, 0x51, 0x3b, 0xfe, 0xf4, 0xfb, 0x46, 0xb5, - 0xe3, 0x2f, 0x71, 0x13, 0xe4, 0xec, 0xf1, 0x17, 0x3a, 0xa2, 0x0d, 0x17, 0x16, 0x67, 0xaf, 0xfe, - 0xbc, 0x7b, 0x53, 0xda, 0x3f, 0x35, 0xff, 0xfa, 0x8b, 0x6f, 0x05, 0x48, 0xb2, 0x22, 0xc5, 0x4d, - 0x1f, 0xc9, 0xe0, 0x13, 0xf6, 0xeb, 0x50, 0xd5, 0x6f, 0x41, 0x67, 0x3a, 0x4f, 0x98, 0xed, 0xe9, - 0x4e, 0x6a, 0x59, 0x92, 0x4a, 0x58, 0x55, 0xef, 0x86, 0x7d, 0x02, 0xab, 0xd1, 0x32, 0xeb, 0x79, - 0xeb, 0x01, 0xbb, 0x97, 0x92, 0xcd, 0x9e, 0x58, 0xec, 0xdb, 0x37, 0xa6, 0xbb, 0x3f, 0xce, 0x08, - 0xea, 0x4b, 0x5e, 0xc7, 0x1c, 0x9f, 0x3c, 0x69, 0xb7, 0x50, 0xc7, 0x27, 0x4f, 0xea, 0x1d, 0xce, - 0x8a, 0xfa, 0xd8, 0x52, 0x62, 0x8d, 0x28, 0x2c, 0x97, 0xfd, 0x10, 0x16, 0xb5, 0xa4, 0xfc, 0xde, - 0xb5, 0x3b, 0x88, 0x76, 0xd2, 0xfc, 0x7d, 0x82, 0xeb, 0x69, 0xb6, 0x49, 0x63, 0x0d, 0xdb, 0x6f, - 0x1a, 0x89, 0xc5, 0x11, 0xbb, 0x68, 0x0b, 0x2a, 0x7a, 0xc2, 0xff, 0x0b, 0xda, 0x5d, 0xd3, 0x8a, - 0xf4, 0xab, 0xeb, 0x1e, 0x67, 0xd8, 0x1e, 0x34, 0x66, 0x2f, 0xd2, 0x8a, 0x78, 0x4a, 0xda, 0xe5, - 0x5f, 0xeb, 0x33, 0x85, 0x89, 0xeb, 0xb7, 0xd8, 0x11, 0x25, 0x76, 0x44, 0x1f, 0xf4, 0xf2, 0xfc, - 0xd9, 0x53, 0x3d, 0xf9, 0xa1, 0xaf, 0xa8, 0xb5, 0xb4, 0x4f, 0xbc, 0x3d, 0xc8, 0x3c, 0xce, 0xb0, - 0xdf, 0xc9, 0x40, 0x35, 0x71, 0x3d, 0x4d, 0x22, 0x74, 0x7e, 0x66, 0x9e, 0x2d, 0xbd, 0x4c, 0x9f, - 0xa8, 0x61, 0xe2, 0x22, 0xee, 0x3d, 0xfc, 0x41, 0xe2, 0x25, 0xfd, 0x24, 0xe1, 0xda, 0xdb, 0x98, - 0xfd, 0xe2, 0xd7, 0x17, 0xb3, 0x08, 0xfa, 0x35, 0x91, 0x5f, 0x3c, 0xce, 0xb0, 0x7f, 0x97, 0x81, - 0x7a, 0xd2, 0x67, 0x1f, 0x4d, 0x37, 0x35, 0x3a, 0x20, 0x22, 0xa5, 0x1b, 0x1c, 0xfd, 0x3f, 0xc4, - 0x51, 0xf6, 0x1f, 0x9a, 0x89, 0x51, 0xca, 0x8b, 0xc4, 0x7f, 0xbe, 0xd1, 0xb2, 0x0f, 0xe9, 0x03, - 0x9b, 0x2a, 0x94, 0x89, 0xcd, 0x7f, 0x90, 0x31, 0x22, 0x3f, 0xfd, 0xf3, 0x85, 0xf8, 0x12, 0x7e, - 0x44, 0x5f, 0xb6, 0x52, 0x91, 0x31, 0x82, 0x8a, 0x5f, 0xb5, 0xbe, 0xf1, 0x16, 0xce, 0xe9, 0x75, - 0xe3, 0x76, 0x62, 0x4e, 0xb3, 0x82, 0x47, 0x9b, 0x46, 0x27, 0xbf, 0x3e, 0x18, 0x9f, 0x9c, 0x73, - 0x5f, 0x24, 0xbc, 0x79, 0x90, 0x63, 0x1a, 0xa4, 0x44, 0x4f, 0x6c, 0xb5, 0x57, 0x6c, 0xc6, 0x78, - 0x88, 0x63, 0x7d, 0xcb, 0xb8, 0x77, 0xe3, 0x58, 0x1f, 0xa1, 0xff, 0x5d, 0x8c, 0xf8, 0x08, 0x20, - 0x0e, 0x35, 0x64, 0x33, 0x01, 0x6f, 0x11, 0x03, 0x9a, 0x8f, 0x46, 0x4c, 0xee, 0x67, 0x15, 0x17, - 0x27, 0x5a, 0xfc, 0x35, 0x62, 0xa7, 0x51, 0x28, 0x9e, 0x2e, 0x7d, 0x25, 0xa3, 0x02, 0x13, 0xd2, - 0xd7, 0x6c, 0xfb, 0x09, 0x66, 0x1a, 0xc5, 0xdd, 0x1d, 0x43, 0x6d, 0xcf, 0xf3, 0x9e, 0x4f, 0x27, - 0x51, 0x78, 0x7b, 0x32, 0x28, 0x66, 0xd7, 0x0e, 0xce, 0xd7, 0x67, 0x66, 0x61, 0xdc, 0xc7, 0xa6, - 0xd6, 0x59, 0x4b, 0x6b, 0xea, 0xd1, 0x4f, 0xe2, 0xf8, 0xc6, 0x2f, 0x98, 0x0d, 0xcd, 0x88, 0x47, - 0xc7, 0x31, 0x84, 0xc9, 0x66, 0x12, 0x9c, 0x79, 0xb6, 0x8b, 0x84, 0x9a, 0xa0, 0x46, 0xfb, 0x28, - 0x50, 0x6d, 0x3e, 0xce, 0xb0, 0x23, 0xa8, 0x6e, 0xf3, 0x01, 0x26, 0xea, 0x63, 0x68, 0xc9, 0x52, - 0x22, 0x4c, 0x81, 0x62, 0x52, 0xd6, 0x6b, 0x09, 0x60, 0xf2, 0xdc, 0x9a, 0xd8, 0xd7, 0x3e, 0xff, - 0xfc, 0xd1, 0x4f, 0x64, 0xd0, 0xca, 0x17, 0xea, 0xdc, 0x52, 0x41, 0x3d, 0x89, 0x73, 0x6b, 0x26, - 0x0a, 0x28, 0x71, 0x6e, 0xcd, 0x45, 0x01, 0x25, 0x96, 0x5a, 0x05, 0x15, 0xb1, 0x11, 0x34, 0xe7, - 0x02, 0x87, 0xa2, 0x23, 0xeb, 0xa6, 0x70, 0xa3, 0xf5, 0xfb, 0x37, 0x23, 0x24, 0x7b, 0x7b, 0x98, - 0xec, 0xad, 0x07, 0x35, 0xba, 0xb9, 0xf2, 0x84, 0x53, 0xca, 0xde, 0xcc, 0x7d, 0x37, 0x7a, 0x3e, - 0xe0, 0xec, 0x01, 0x83, 0x65, 0x49, 0x09, 0x07, 0x73, 0xe5, 0xd8, 0xaf, 0x41, 0xe5, 0x29, 0x0f, - 0x55, 0x8e, 0x5e, 0x24, 0x63, 0xcf, 0x24, 0xed, 0xad, 0xa7, 0xa4, 0xf8, 0x25, 0x69, 0x06, 0x5b, - 0x7b, 0xc4, 0x87, 0x67, 0x9c, 0x98, 0x93, 0xe5, 0x0c, 0xbf, 0x60, 0xbf, 0x8a, 0x8d, 0x47, 0xa9, - 0xd1, 0xab, 0x5a, 0x12, 0x96, 0xde, 0xf8, 0xe2, 0x0c, 0x3c, 0xad, 0x65, 0xd7, 0x1b, 0x72, 0x4d, - 0xd6, 0x73, 0xa1, 0xa2, 0x5d, 0xa1, 0x10, 0x6d, 0xa0, 0xf9, 0x2b, 0x33, 0xa2, 0x0d, 0x94, 0x72, - 0xe3, 0x82, 0xf1, 0x00, 0xfb, 0x31, 0xd8, 0xfd, 0xb8, 0x1f, 0xba, 0x65, 0x21, 0xee, 0xe9, 0xd1, - 0x4f, 0xec, 0x71, 0xf8, 0x05, 0xfb, 0x14, 0xef, 0x87, 0xd7, 0x73, 0x10, 0x63, 0xa5, 0x61, 0x36, - 0x5d, 0x31, 0x5a, 0x2c, 0xad, 0x28, 0xa9, 0x48, 0x50, 0x57, 0x28, 0xc9, 0xbd, 0x0f, 0xd0, 0x0b, - 0xbd, 0xc9, 0xb6, 0xcd, 0xc7, 0x9e, 0x1b, 0xf3, 0xda, 0x38, 0x2b, 0x2e, 0xe6, 0x5f, 0x5a, 0x6a, - 0x1c, 0xfb, 0x54, 0xd3, 0xb2, 0x12, 0x69, 0x9c, 0x8a, 0xb8, 0x6e, 0x4c, 0x9c, 0x8b, 0x16, 0x24, - 0x25, 0x79, 0xee, 0x71, 0x86, 0xb5, 0x01, 0xe2, 0xc8, 0xb1, 0x48, 0x67, 0x9a, 0x0b, 0x4a, 0x8b, - 0xd8, 0x5e, 0x4a, 0x98, 0xd9, 0x11, 0x94, 0xe3, 0x90, 0x9b, 0xb5, 0xf8, 0x46, 0x98, 0x44, 0x80, - 0x4e, 0x74, 0x82, 0xcf, 0x85, 0xbb, 0x18, 0x0d, 0x5c, 0x2a, 0x60, 0x25, 0xb1, 0x54, 0xa7, 0x9c, - 0x07, 0xcc, 0x81, 0x25, 0x1a, 0x60, 0x24, 0x2e, 0x61, 0x36, 0x57, 0xf4, 0x19, 0x80, 0xf9, 0xc8, - 0x93, 0x68, 0x37, 0xa7, 0xc6, 0x4f, 0x24, 0x4c, 0x3f, 0x82, 0x5a, 0x29, 0x93, 0x4c, 0xb0, 0xe6, - 0x31, 0x34, 0xe7, 0x5c, 0xf4, 0xd1, 0x96, 0xbe, 0x29, 0xe6, 0x22, 0xda, 0xd2, 0x37, 0x7a, 0xf7, - 0x8d, 0x15, 0xec, 0x72, 0xd1, 0x00, 0x54, 0xf5, 0x2e, 0x9d, 0x70, 0x70, 0x2e, 0xba, 0xfb, 0xbd, - 0x0c, 0x2c, 0xa5, 0x38, 0xe1, 0xd9, 0x1b, 0xca, 0x6a, 0x70, 0xa3, 0x83, 0x7e, 0x3d, 0xd5, 0x59, - 0x6b, 0xf4, 0xb0, 0x9f, 0x7d, 0xf6, 0x2c, 0x71, 0xb0, 0x91, 0xaf, 0x54, 0xee, 0xcc, 0x17, 0x0a, - 0x15, 0xa9, 0x12, 0xc5, 0xe7, 0xb0, 0x46, 0x03, 0x69, 0x8f, 0x46, 0x33, 0x8e, 0xe4, 0xd7, 0xe7, - 0x3e, 0xc0, 0x9f, 0x70, 0x8e, 0xaf, 0xdf, 0xfc, 0x81, 0xfe, 0x1b, 0xc4, 0x69, 0x1a, 0x2a, 0x9b, - 0x42, 0x63, 0xd6, 0x41, 0xcb, 0x6e, 0x6e, 0x6b, 0xfd, 0x5e, 0x42, 0xff, 0x4d, 0x71, 0xea, 0x7e, - 0x0d, 0x3b, 0xbb, 0x67, 0xac, 0xa7, 0xad, 0x0b, 0xa9, 0xc4, 0xe2, 0x7d, 0xfc, 0xed, 0xc8, 0x9b, - 0x3c, 0x33, 0x4f, 0xd5, 0xc1, 0x4d, 0xbe, 0xef, 0x48, 0x03, 0x4f, 0x77, 0x46, 0xbf, 0x8d, 0xdd, - 0xdf, 0x37, 0xee, 0xa4, 0x75, 0xef, 0x53, 0x15, 0xd2, 0xc5, 0xd7, 0x66, 0xf7, 0xb5, 0x1a, 0xc1, - 0xfd, 0xb4, 0xf7, 0x7d, 0xa3, 0x2e, 0x34, 0xb3, 0xd6, 0xb7, 0x50, 0xb6, 0xab, 0xea, 0xde, 0xe3, - 0x68, 0xfb, 0xa4, 0xb8, 0xa9, 0xa3, 0xed, 0x93, 0xe6, 0x6e, 0x4e, 0xca, 0x35, 0xca, 0xd1, 0xfc, - 0x61, 0xe6, 0xe1, 0xe6, 0x3b, 0x3f, 0xfc, 0xda, 0x99, 0x13, 0x9e, 0x4f, 0x4f, 0x36, 0x06, 0xde, - 0xf8, 0xd1, 0x48, 0x59, 0x1b, 0x65, 0xca, 0xf3, 0xa3, 0x91, 0x3b, 0x7c, 0x84, 0xcd, 0x9e, 0x2c, - 0x4c, 0x7c, 0x2f, 0xf4, 0xbe, 0xf5, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x10, 0x0b, 0x84, 0xf3, - 0x63, 0x84, 0x00, 0x00, + 0xb2, 0x06, 0x81, 0x03, 0x63, 0x19, 0x98, 0xbe, 0x12, 0xb4, 0xf6, 0xc6, 0xef, 0x67, 0x60, 0xe9, + 0xd8, 0x1d, 0x79, 0x83, 0xe7, 0x3f, 0xe3, 0x12, 0xa5, 0xcc, 0x21, 0xfb, 0xaa, 0x73, 0xc8, 0x7d, + 0xd9, 0x39, 0xac, 0xc2, 0x72, 0x72, 0xb0, 0x72, 0x16, 0x1c, 0x56, 0x44, 0xed, 0x33, 0xae, 0x86, + 0xa5, 0xa6, 0xf1, 0x75, 0x68, 0x0c, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x79, 0x2c, 0x4a, 0x78, 0x34, + 0x91, 0x37, 0xa0, 0xea, 0xf2, 0xcb, 0x18, 0x4d, 0xd2, 0xae, 0xcb, 0x2f, 0x15, 0x8a, 0xd1, 0x82, + 0xd5, 0xd9, 0x6e, 0xe4, 0x00, 0xfe, 0x2a, 0x03, 0xf9, 0xe3, 0xf0, 0xca, 0x63, 0xef, 0x43, 0xd5, + 0x1e, 0x0e, 0x7d, 0x1e, 0x04, 0x56, 0x78, 0x3d, 0xa1, 0x9d, 0x52, 0x7f, 0xc2, 0xe4, 0x14, 0xdb, + 0x54, 0xd4, 0xbf, 0x9e, 0x70, 0xb3, 0x62, 0xc7, 0x0f, 0xac, 0x05, 0x45, 0xf9, 0x88, 0xfd, 0x96, + 0x4d, 0xf5, 0xc8, 0xee, 0x02, 0xd8, 0x63, 0x6f, 0xea, 0x86, 0x56, 0x60, 0x87, 0xb8, 0x62, 0x39, + 0xb3, 0x4c, 0x90, 0x9e, 0x1d, 0xb2, 0x3b, 0x50, 0x9e, 0x3c, 0xb7, 0x82, 0x81, 0xef, 0x4c, 0x42, + 0x24, 0x9e, 0xb2, 0x59, 0x9a, 0x3c, 0xef, 0xe1, 0x33, 0x7b, 0x17, 0x4a, 0xde, 0x34, 0x9c, 0x78, + 0x8e, 0x1b, 0x4a, 0x7a, 0x59, 0x94, 0x03, 0x39, 0x9c, 0x86, 0x47, 0x02, 0x6c, 0x46, 0x08, 0xec, + 0x2d, 0xa8, 0x0d, 0x3c, 0xf7, 0xd4, 0xf1, 0xc7, 0xc4, 0x11, 0x5a, 0x0b, 0xd8, 0x57, 0x12, 0x68, + 0xfc, 0x61, 0x16, 0x2a, 0x7d, 0xdf, 0x76, 0x03, 0x7b, 0x20, 0x00, 0x6c, 0x0d, 0x8a, 0xe1, 0x95, + 0x75, 0x6e, 0x07, 0xe7, 0x38, 0xd5, 0xb2, 0xb9, 0x10, 0x5e, 0xed, 0xda, 0xc1, 0x39, 0x5b, 0x85, + 0x05, 0x1a, 0x25, 0x4e, 0x28, 0x67, 0xca, 0x27, 0xb1, 0x41, 0xdc, 0xe9, 0xd8, 0x4a, 0x76, 0x95, + 0x43, 0x8a, 0x69, 0xb8, 0xd3, 0xf1, 0x96, 0x0e, 0x17, 0x93, 0x3f, 0x11, 0xaf, 0x9b, 0x3a, 0xa0, + 0xe9, 0x95, 0x11, 0x82, 0x7d, 0xbc, 0x01, 0x55, 0x59, 0xcc, 0x9d, 0xb3, 0x73, 0x9a, 0x63, 0xc1, + 0xac, 0x10, 0x02, 0x82, 0x44, 0x0b, 0xa1, 0x33, 0xe6, 0x56, 0x10, 0xda, 0xe3, 0x89, 0x9c, 0x52, + 0x59, 0x40, 0x7a, 0x02, 0x80, 0xc5, 0x5e, 0x68, 0x8f, 0xac, 0x53, 0xce, 0x83, 0x56, 0x51, 0x16, + 0x0b, 0xc8, 0x0e, 0xe7, 0x01, 0xfb, 0x1a, 0xd4, 0x87, 0x3c, 0x08, 0x2d, 0xf9, 0x32, 0x78, 0xd0, + 0x2a, 0xe1, 0xce, 0xaf, 0x09, 0x68, 0x5b, 0x01, 0xd9, 0x6b, 0x00, 0xbe, 0x7d, 0x69, 0x89, 0x85, + 0xe0, 0x57, 0xad, 0x32, 0xbd, 0x05, 0xdf, 0xbe, 0xec, 0x5f, 0xed, 0xf2, 0x2b, 0x41, 0x35, 0x4f, + 0x79, 0xa8, 0x2d, 0x5a, 0x20, 0xa9, 0xd3, 0xd8, 0x03, 0xa6, 0x81, 0xb7, 0x79, 0x68, 0x3b, 0xa3, + 0x80, 0x7d, 0x00, 0xd5, 0x50, 0x43, 0x46, 0x36, 0x58, 0x89, 0x48, 0x48, 0xab, 0x60, 0x26, 0xf0, + 0x8c, 0x73, 0x28, 0xed, 0x70, 0xbe, 0xe7, 0x8c, 0x9d, 0x90, 0xad, 0x42, 0xe1, 0xd4, 0xb9, 0xe2, + 0x44, 0xec, 0xb9, 0xdd, 0x5b, 0x26, 0x3d, 0xb2, 0x7b, 0x00, 0xf8, 0xc3, 0x1a, 0x47, 0xd4, 0xb4, + 0x7b, 0xcb, 0x2c, 0x23, 0x6c, 0x3f, 0xb0, 0x43, 0xb6, 0x0e, 0xc5, 0x09, 0xf7, 0x07, 0x5c, 0xbd, + 0xb7, 0xdd, 0x5b, 0xa6, 0x02, 0x6c, 0x16, 0xa1, 0x30, 0x12, 0xad, 0x1b, 0x7f, 0x5c, 0x80, 0x4a, + 0x8f, 0xbb, 0xd1, 0x2e, 0x63, 0x90, 0x17, 0x0b, 0x22, 0x77, 0x16, 0xfe, 0x66, 0x6f, 0x42, 0x05, + 0x97, 0x2e, 0x08, 0x7d, 0xc7, 0x3d, 0x23, 0xaa, 0xde, 0xcc, 0xb6, 0x32, 0x26, 0x08, 0x70, 0x0f, + 0xa1, 0xac, 0x01, 0x39, 0x7b, 0xac, 0xa8, 0x5a, 0xfc, 0x64, 0xb7, 0xa1, 0x64, 0x8f, 0x43, 0x1a, + 0x5e, 0x15, 0xc1, 0x45, 0x7b, 0x1c, 0xe2, 0xd0, 0xde, 0x80, 0xea, 0xc4, 0xbe, 0x1e, 0x8b, 0xbd, + 0x1c, 0x91, 0x43, 0xd5, 0xac, 0x48, 0x18, 0x12, 0xc4, 0x13, 0x58, 0xd2, 0x51, 0x54, 0xe7, 0x85, + 0xa8, 0xf3, 0xa6, 0x86, 0x2d, 0xc7, 0xf0, 0x0e, 0x2c, 0xaa, 0x3a, 0x3e, 0xcd, 0x07, 0xc9, 0xa4, + 0x6c, 0xd6, 0x25, 0x58, 0xcd, 0xf2, 0x01, 0x34, 0x4e, 0x1d, 0xd7, 0x1e, 0x59, 0x83, 0x51, 0x78, + 0x61, 0x0d, 0xf9, 0x28, 0xb4, 0x91, 0x62, 0x0a, 0x66, 0x1d, 0xe1, 0x5b, 0xa3, 0xf0, 0x62, 0x5b, + 0x40, 0xd9, 0x37, 0xa0, 0x7c, 0xca, 0xb9, 0x85, 0x8b, 0xd5, 0x2a, 0x25, 0x36, 0x9e, 0x7a, 0x43, + 0x66, 0xe9, 0x54, 0xbd, 0xab, 0x6f, 0x40, 0xc3, 0x9b, 0x86, 0x67, 0x9e, 0xe3, 0x9e, 0x59, 0x82, + 0xdf, 0x59, 0xce, 0x10, 0x69, 0x28, 0xbf, 0x99, 0x7d, 0x9c, 0x31, 0xeb, 0xaa, 0x4c, 0x70, 0x9e, + 0xee, 0x90, 0xbd, 0x0d, 0x8b, 0x23, 0x3b, 0x08, 0xad, 0x73, 0x6f, 0x62, 0x4d, 0xa6, 0x27, 0xcf, + 0xf9, 0x75, 0xab, 0x86, 0x0b, 0x51, 0x13, 0xe0, 0x5d, 0x6f, 0x72, 0x84, 0x40, 0x41, 0xd9, 0x38, + 0x4e, 0x1a, 0x04, 0xdc, 0xcf, 0x3c, 0xa8, 0x99, 0x65, 0x01, 0xa1, 0x4e, 0x3f, 0x83, 0x25, 0x7c, + 0x3d, 0x83, 0x69, 0x10, 0x7a, 0x63, 0x4b, 0xf0, 0x6a, 0x7f, 0x18, 0xb4, 0x2a, 0x48, 0x6b, 0x5f, + 0x97, 0x83, 0xd5, 0xde, 0xf1, 0xc6, 0x36, 0x0f, 0xc2, 0x2d, 0x44, 0x36, 0x09, 0x57, 0x1c, 0xe8, + 0xd7, 0x66, 0x73, 0x38, 0x0b, 0x67, 0xdf, 0x00, 0x66, 0x8f, 0x46, 0xde, 0xa5, 0x15, 0xf0, 0xd1, + 0xa9, 0x25, 0x17, 0xb1, 0x55, 0xbf, 0x9f, 0x79, 0x50, 0x32, 0x1b, 0x58, 0xd2, 0xe3, 0xa3, 0xd3, + 0x23, 0x82, 0xb3, 0x0f, 0x00, 0x37, 0x93, 0x75, 0xca, 0xed, 0x70, 0xea, 0xf3, 0xa0, 0xb5, 0x78, + 0x3f, 0xf7, 0xa0, 0xfe, 0xa4, 0x19, 0xad, 0x17, 0x82, 0x37, 0x9d, 0xd0, 0xac, 0x0a, 0x3c, 0xf9, + 0x1c, 0xac, 0x6f, 0xc3, 0x6a, 0xfa, 0x90, 0x04, 0x51, 0x89, 0x55, 0x11, 0xc4, 0x98, 0x37, 0xc5, + 0x4f, 0xb6, 0x0c, 0x85, 0x0b, 0x7b, 0x34, 0xe5, 0x92, 0xa7, 0xd3, 0xc3, 0x87, 0xd9, 0xef, 0x66, + 0x8c, 0x3f, 0xca, 0x40, 0x95, 0x66, 0x29, 0x65, 0x91, 0x37, 0xa1, 0xa6, 0xa8, 0x81, 0xfb, 0xbe, + 0xe7, 0x4b, 0xae, 0xa6, 0x28, 0xaf, 0x23, 0x60, 0xe2, 0x54, 0x51, 0x48, 0x13, 0x9f, 0x3b, 0x63, + 0xfb, 0x4c, 0x35, 0xad, 0x48, 0xe9, 0x48, 0x82, 0xd9, 0x7b, 0x71, 0x7b, 0xbe, 0x37, 0x0d, 0xb9, + 0x3c, 0xf3, 0xaa, 0x72, 0x7a, 0xa6, 0x80, 0x45, 0xad, 0xe3, 0xd3, 0x2b, 0xd0, 0xb9, 0xf1, 0xdb, + 0x19, 0x60, 0x62, 0xd8, 0x7d, 0x8f, 0x1a, 0x90, 0x14, 0x3a, 0x5b, 0x33, 0xf3, 0xca, 0x3b, 0x24, + 0xfb, 0xa2, 0x1d, 0x62, 0x40, 0x81, 0xc6, 0x9e, 0x4f, 0x19, 0x3b, 0x15, 0xfd, 0x20, 0x5f, 0xca, + 0x35, 0xf2, 0xc6, 0xff, 0xc8, 0xc1, 0xf2, 0x16, 0x1d, 0xd9, 0xed, 0xc1, 0x80, 0x4f, 0xa2, 0xbd, + 0x73, 0x0f, 0x2a, 0xae, 0x37, 0xe4, 0x8a, 0x62, 0x69, 0x60, 0x20, 0x40, 0x1a, 0xb9, 0x9e, 0xdb, + 0x8e, 0x4b, 0x03, 0xa7, 0xc5, 0x2c, 0x23, 0x04, 0x87, 0xfd, 0x36, 0x2c, 0x4e, 0xb8, 0x3b, 0xd4, + 0xb7, 0x08, 0x09, 0x55, 0x35, 0x09, 0x96, 0xbb, 0xe3, 0x1e, 0x54, 0x4e, 0xa7, 0x84, 0x27, 0x18, + 0x4b, 0x1e, 0x69, 0x00, 0x24, 0xa8, 0x4d, 0xfc, 0x65, 0x32, 0x0d, 0xce, 0xb1, 0xb4, 0x80, 0xa5, + 0x45, 0xf1, 0x2c, 0x8a, 0xee, 0x02, 0x0c, 0xa7, 0x41, 0x28, 0x77, 0xcc, 0x02, 0x16, 0x96, 0x05, + 0x84, 0x76, 0xcc, 0x37, 0x61, 0x69, 0x6c, 0x5f, 0x59, 0x48, 0x3b, 0x96, 0xe3, 0x5a, 0xa7, 0x23, + 0x3c, 0x73, 0x8a, 0x88, 0xd7, 0x18, 0xdb, 0x57, 0x9f, 0x88, 0x92, 0xae, 0xbb, 0x83, 0x70, 0xc1, + 0x56, 0x94, 0xb8, 0xe3, 0xf3, 0x80, 0xfb, 0x17, 0x1c, 0x39, 0x41, 0x3e, 0x92, 0x69, 0x4c, 0x82, + 0x8a, 0x11, 0x8d, 0xc5, 0xbc, 0xc3, 0xd1, 0x80, 0xb6, 0xbd, 0x59, 0x1c, 0x3b, 0xee, 0x6e, 0x38, + 0x1a, 0x88, 0x73, 0x45, 0xf0, 0x91, 0x09, 0xf7, 0xad, 0xe7, 0x97, 0xb8, 0x87, 0xf3, 0xc8, 0x37, + 0x8e, 0xb8, 0xff, 0xec, 0x52, 0x1c, 0xfd, 0x83, 0x00, 0x19, 0x91, 0x7d, 0xdd, 0xaa, 0xe0, 0x06, + 0x2f, 0x0d, 0x02, 0xc1, 0x82, 0xec, 0x6b, 0xb1, 0x09, 0xc5, 0x68, 0x6d, 0x7c, 0x0b, 0x7c, 0x88, + 0xcd, 0x07, 0xc8, 0x51, 0x6b, 0x38, 0xd8, 0xb6, 0x2c, 0x10, 0xfd, 0x04, 0x82, 0xea, 0xd5, 0x60, + 0x4f, 0x47, 0xf6, 0x59, 0x80, 0x2c, 0xa5, 0x66, 0x56, 0x25, 0x70, 0x47, 0xc0, 0x8c, 0x4f, 0x49, + 0xc8, 0xd2, 0xde, 0xad, 0xdc, 0x33, 0xe2, 0xa8, 0x47, 0x08, 0xbe, 0xd7, 0x92, 0x29, 0x9f, 0xd2, + 0x5e, 0x5a, 0x36, 0xe5, 0xa5, 0x19, 0xbf, 0x9b, 0x81, 0xaa, 0x6c, 0x19, 0x85, 0x12, 0xb6, 0x01, + 0x4c, 0xbd, 0xc5, 0xf0, 0xca, 0x19, 0x5a, 0x27, 0xd7, 0x21, 0x0f, 0x88, 0x68, 0x76, 0x6f, 0x99, + 0x0d, 0x59, 0xd6, 0xbf, 0x72, 0x86, 0x9b, 0xa2, 0x84, 0x3d, 0x84, 0x46, 0x02, 0x3f, 0x08, 0x7d, + 0xa2, 0xe8, 0xdd, 0x5b, 0x66, 0x5d, 0xc3, 0xee, 0x85, 0xbe, 0xd8, 0x23, 0x42, 0xe4, 0x99, 0x86, + 0x96, 0xe3, 0x0e, 0xf9, 0x15, 0x92, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x2b, 0x40, 0x9b, 0x75, 0xa8, + 0xea, 0xcd, 0x19, 0x67, 0x50, 0x52, 0xf2, 0x12, 0x0a, 0x0c, 0x33, 0x43, 0x32, 0xcb, 0x61, 0x34, + 0x92, 0xdb, 0x50, 0x4a, 0x8e, 0xc0, 0x2c, 0x86, 0xaf, 0xdc, 0xb1, 0xf1, 0x3d, 0x68, 0xec, 0x09, + 0xe2, 0x71, 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x15, 0x16, 0xb4, 0x4d, 0x53, 0x36, 0xe5, 0x93, 0x38, + 0x73, 0xcf, 0xbd, 0x20, 0x94, 0xbd, 0xe0, 0x6f, 0xe3, 0x8f, 0x33, 0xc0, 0x3a, 0x41, 0xe8, 0x8c, + 0xed, 0x90, 0xef, 0xf0, 0x88, 0x2d, 0x1c, 0x42, 0x55, 0xb4, 0xd6, 0xf7, 0xda, 0x24, 0x90, 0x91, + 0x40, 0xf1, 0xae, 0xdc, 0xc6, 0xf3, 0x15, 0x36, 0x74, 0x6c, 0x62, 0xf3, 0x89, 0x06, 0xc4, 0x2e, + 0x0b, 0x6d, 0xff, 0x8c, 0x87, 0x28, 0xc6, 0x49, 0x79, 0x1f, 0x08, 0x24, 0x04, 0xb8, 0xf5, 0x5f, + 0x81, 0xe6, 0x5c, 0x1b, 0x3a, 0x5f, 0x2e, 0xa7, 0xf0, 0xe5, 0x9c, 0xce, 0x97, 0x2d, 0x58, 0x4a, + 0x8c, 0x4b, 0x52, 0xda, 0x1a, 0x14, 0xc5, 0x86, 0x10, 0xc2, 0x41, 0x86, 0xa4, 0xca, 0x53, 0xce, + 0x85, 0x18, 0xfc, 0x08, 0x96, 0x4f, 0x39, 0xf7, 0xed, 0x10, 0x0b, 0x71, 0xc7, 0x88, 0x37, 0x24, + 0x1b, 0x6e, 0xca, 0xb2, 0x9e, 0x1d, 0x1e, 0x71, 0x5f, 0xbc, 0x29, 0xe3, 0x7f, 0x66, 0x60, 0x51, + 0x70, 0xd0, 0x7d, 0xdb, 0xbd, 0x56, 0xeb, 0xb4, 0x97, 0xba, 0x4e, 0x0f, 0xb4, 0xc3, 0x50, 0xc3, + 0xfe, 0xb2, 0x8b, 0x94, 0x9b, 0x5d, 0x24, 0x76, 0x1f, 0xaa, 0x89, 0xb1, 0x16, 0x70, 0xac, 0x10, + 0x44, 0x83, 0xfc, 0xf9, 0x97, 0xf1, 0x6d, 0x68, 0xc4, 0xc3, 0x96, 0x6b, 0xc8, 0x20, 0x2f, 0x48, + 0x52, 0x36, 0x80, 0xbf, 0x8d, 0x7f, 0x99, 0x21, 0xc4, 0x2d, 0xcf, 0x89, 0xa4, 0x53, 0x81, 0x28, + 0xe4, 0x5e, 0x85, 0x28, 0x7e, 0xdf, 0x28, 0xd5, 0xff, 0xfc, 0x93, 0x15, 0x5b, 0x27, 0xe0, 0xee, + 0xd0, 0xb2, 0x47, 0x23, 0x64, 0xbe, 0x25, 0xb3, 0x28, 0x9e, 0xdb, 0xa3, 0x91, 0xf1, 0x0e, 0x34, + 0xb5, 0xd1, 0xbd, 0x60, 0x1e, 0x07, 0xc0, 0xf6, 0x9c, 0x20, 0x3c, 0x76, 0x83, 0x89, 0x26, 0xb8, + 0xdd, 0x81, 0xb2, 0xe0, 0xb0, 0x62, 0x64, 0xb4, 0x65, 0x0b, 0xa6, 0x60, 0xb9, 0x62, 0x5c, 0x01, + 0x16, 0xda, 0x57, 0xb2, 0x30, 0x2b, 0x0b, 0xed, 0x2b, 0x2c, 0x34, 0xbe, 0x0b, 0x4b, 0x89, 0xf6, + 0x64, 0xd7, 0x6f, 0x40, 0x61, 0x1a, 0x5e, 0x79, 0x4a, 0x34, 0xaf, 0x48, 0x0a, 0x11, 0x0a, 0xa0, + 0x49, 0x25, 0xc6, 0x47, 0xd0, 0x3c, 0xe0, 0x97, 0x72, 0x13, 0xab, 0x81, 0xbc, 0x0d, 0xf9, 0x97, + 0x28, 0x85, 0x58, 0x6e, 0x6c, 0x00, 0xd3, 0x2b, 0xcb, 0x5e, 0x35, 0x1d, 0x31, 0x93, 0xd0, 0x11, + 0x8d, 0xb7, 0x81, 0xf5, 0x9c, 0x33, 0x77, 0x9f, 0x07, 0x81, 0x7d, 0x16, 0x6d, 0xfb, 0x06, 0xe4, + 0xc6, 0xc1, 0x99, 0xe4, 0x51, 0xe2, 0xa7, 0xf1, 0x2d, 0x58, 0x4a, 0xe0, 0xc9, 0x86, 0x5f, 0x83, + 0x72, 0xe0, 0x9c, 0xb9, 0x28, 0x58, 0xc9, 0xa6, 0x63, 0x80, 0xb1, 0x03, 0xcb, 0x9f, 0x70, 0xdf, + 0x39, 0xbd, 0x7e, 0x59, 0xf3, 0xc9, 0x76, 0xb2, 0xb3, 0xed, 0x74, 0x60, 0x65, 0xa6, 0x1d, 0xd9, + 0x3d, 0x91, 0xaf, 0x7c, 0x93, 0x25, 0x93, 0x1e, 0x34, 0xbe, 0x97, 0xd5, 0xf9, 0x9e, 0x71, 0x0c, + 0x6c, 0xcb, 0x73, 0x5d, 0x3e, 0x08, 0x8f, 0x38, 0xf7, 0x63, 0x2b, 0x55, 0x4c, 0xab, 0x95, 0x27, + 0x6b, 0x72, 0x65, 0x67, 0x99, 0xa9, 0x24, 0x62, 0x06, 0xf9, 0x09, 0xf7, 0xc7, 0xd8, 0x70, 0xc9, + 0xc4, 0xdf, 0xc6, 0x0a, 0x2c, 0x25, 0x9a, 0x95, 0x7a, 0xfd, 0x63, 0x58, 0xd9, 0x76, 0x82, 0xc1, + 0x7c, 0x87, 0x6b, 0x50, 0x9c, 0x4c, 0x4f, 0xac, 0x24, 0x5f, 0x7e, 0xc6, 0xaf, 0x85, 0xb6, 0x37, + 0x5b, 0x43, 0xb6, 0xf5, 0x77, 0x33, 0x90, 0xdf, 0xed, 0xef, 0x6d, 0xb1, 0x75, 0x28, 0x39, 0xee, + 0xc0, 0x1b, 0x0b, 0xc1, 0x8b, 0xe6, 0x1c, 0x3d, 0xdf, 0xb8, 0xc1, 0xee, 0x40, 0x19, 0xe5, 0x35, + 0xa1, 0xda, 0x4a, 0xd1, 0xa7, 0x24, 0x00, 0x7b, 0xde, 0xe0, 0xb9, 0xd0, 0xa9, 0xf9, 0xd5, 0xc4, + 0xf1, 0x51, 0x6b, 0x56, 0xca, 0x70, 0x9e, 0xce, 0xfa, 0xb8, 0x80, 0x34, 0x62, 0xe3, 0x3f, 0x95, + 0xa0, 0x28, 0x4f, 0x5b, 0x3a, 0xb9, 0x43, 0xe7, 0x82, 0xc7, 0x27, 0xb7, 0x78, 0x12, 0xf2, 0x80, + 0xcf, 0xc7, 0x5e, 0x18, 0x09, 0x6c, 0xf4, 0x0e, 0xaa, 0x04, 0x94, 0x22, 0x9b, 0x26, 0x34, 0x90, + 0x89, 0x21, 0x47, 0x48, 0x03, 0xfd, 0x28, 0xbf, 0x03, 0x45, 0x75, 0xf6, 0xe7, 0x23, 0x9d, 0x66, + 0x61, 0x40, 0xd2, 0xda, 0x3a, 0x94, 0x06, 0xf6, 0xc4, 0x1e, 0x38, 0xe1, 0xb5, 0x64, 0x08, 0xd1, + 0xb3, 0x68, 0x7d, 0xe4, 0x0d, 0xec, 0x91, 0x75, 0x62, 0x8f, 0x6c, 0x77, 0xc0, 0xa5, 0xee, 0x5e, + 0x45, 0xe0, 0x26, 0xc1, 0x84, 0x7e, 0x2e, 0xc7, 0xa9, 0xb0, 0x48, 0x85, 0x97, 0xa3, 0x57, 0x68, + 0x42, 0xb8, 0xf4, 0xc6, 0x63, 0x47, 0x68, 0x19, 0x24, 0x86, 0xe5, 0xcc, 0x32, 0x41, 0x76, 0x38, + 0xce, 0x56, 0x16, 0x5f, 0xd2, 0xd2, 0x95, 0xa9, 0x2b, 0x02, 0x7e, 0x4a, 0x86, 0x84, 0x79, 0x59, + 0x2c, 0xa7, 0xc9, 0x62, 0xef, 0x42, 0x73, 0xea, 0x06, 0x3c, 0x0c, 0x47, 0x7c, 0x18, 0x8d, 0xa5, + 0x82, 0x48, 0x8d, 0xa8, 0x40, 0x0d, 0x67, 0x03, 0x96, 0xc8, 0xe8, 0x10, 0xd8, 0xa1, 0x17, 0x9c, + 0x3b, 0x81, 0x15, 0x08, 0x0d, 0x89, 0xd4, 0xdd, 0x26, 0x16, 0xf5, 0x64, 0x49, 0x8f, 0x54, 0xa4, + 0xb5, 0x19, 0x7c, 0x9f, 0x0f, 0xb8, 0x73, 0xc1, 0x87, 0x28, 0xa7, 0xe5, 0xcc, 0x95, 0x44, 0x1d, + 0x53, 0x16, 0xa2, 0xd0, 0x3d, 0x1d, 0x5b, 0xd3, 0xc9, 0xd0, 0x16, 0xc2, 0x4a, 0x9d, 0x84, 0x61, + 0x77, 0x3a, 0x3e, 0x26, 0x08, 0x7b, 0x0c, 0x4a, 0x12, 0x93, 0xf2, 0xe1, 0x62, 0x82, 0x9f, 0x09, + 0x62, 0x35, 0xab, 0x12, 0x83, 0x04, 0xc5, 0x84, 0xcc, 0xd9, 0x98, 0x91, 0x39, 0x5b, 0x50, 0x9c, + 0xf8, 0xce, 0x85, 0x1d, 0xf2, 0x56, 0x93, 0x18, 0xb8, 0x7c, 0x14, 0x9c, 0xc1, 0x71, 0x9d, 0xd0, + 0xb1, 0x43, 0xcf, 0x6f, 0x31, 0x2c, 0x8b, 0x01, 0xec, 0x21, 0x34, 0x91, 0x46, 0x82, 0xd0, 0x0e, + 0xa7, 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x21, 0x1c, 0x85, 0x50, 0xf6, 0x2d, + 0x58, 0x25, 0xb2, 0xc0, 0x1a, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x97, 0x62, 0x09, 0x4b, 0x05, + 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0xef, 0xc3, 0x9a, 0x24, 0x93, 0xb9, 0x5a, 0x2b, 0x58, 0x6b, + 0x99, 0x8a, 0x67, 0xaa, 0x6d, 0x40, 0x53, 0x0c, 0xc9, 0x19, 0x58, 0xb2, 0xb6, 0xd8, 0x09, 0xab, + 0x62, 0xf4, 0xa8, 0x29, 0x2d, 0x52, 0xa1, 0x89, 0x65, 0xcf, 0xf8, 0x35, 0xfb, 0x1e, 0x2c, 0x12, + 0xc9, 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, 0xa5, 0xc8, 0xec, + 0xeb, 0x83, 0xc4, 0xb3, 0xd8, 0x0e, 0x23, 0xe7, 0x94, 0x87, 0xce, 0x98, 0xb7, 0xd6, 0x88, 0xc0, + 0xd4, 0xb3, 0xd8, 0xa9, 0xd3, 0x09, 0x96, 0xb4, 0x88, 0x2f, 0xd0, 0x13, 0xd2, 0xee, 0xc8, 0x0b, + 0xb8, 0x32, 0x51, 0xb5, 0x6e, 0xcb, 0x4d, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, 0x38, 0x29, 0x3d, + 0x91, 0x21, 0xf1, 0x0e, 0x12, 0x43, 0x8d, 0x74, 0x1f, 0x65, 0x4c, 0x14, 0xa7, 0xf8, 0xb9, 0x7d, + 0xa9, 0x38, 0xc8, 0x6b, 0xf8, 0x7e, 0x41, 0x80, 0x24, 0xef, 0xf8, 0x69, 0x86, 0x0e, 0x44, 0xc9, + 0x3f, 0x02, 0x4d, 0xbd, 0x23, 0xce, 0x61, 0x79, 0xee, 0xe8, 0x5a, 0x32, 0x13, 0x20, 0xd0, 0xa1, + 0x3b, 0xc2, 0xdd, 0xec, 0xb8, 0x3a, 0x0a, 0xf1, 0xde, 0xaa, 0x02, 0x22, 0xd2, 0x3d, 0xa8, 0x4c, + 0xa6, 0x27, 0x23, 0x67, 0x40, 0x28, 0x39, 0x6a, 0x85, 0x40, 0x88, 0x20, 0xf4, 0x5b, 0xa2, 0x28, + 0xc2, 0xc8, 0x23, 0x46, 0x45, 0xc2, 0x10, 0x05, 0x79, 0x3b, 0xf7, 0x91, 0x9d, 0x54, 0x4d, 0xfc, + 0x6d, 0x6c, 0xc2, 0x72, 0x72, 0xd0, 0xf2, 0xe0, 0x79, 0x08, 0x25, 0xc9, 0xab, 0x94, 0xe1, 0xa3, + 0xae, 0x99, 0xa2, 0x85, 0x8a, 0x16, 0x95, 0x1b, 0xbf, 0xb9, 0x00, 0x4b, 0x12, 0xba, 0x25, 0x96, + 0xb6, 0x37, 0x1d, 0x8f, 0x6d, 0x3f, 0x85, 0x09, 0x66, 0x5e, 0xcc, 0x04, 0xb3, 0x73, 0x4c, 0x30, + 0xa9, 0xf9, 0x12, 0x0f, 0x4d, 0x6a, 0xbe, 0xe2, 0x5d, 0x92, 0x32, 0xa2, 0xdb, 0x41, 0x6b, 0x12, + 0xdc, 0x27, 0x7b, 0xeb, 0x1c, 0xcb, 0x2e, 0xa4, 0xb0, 0x6c, 0x9d, 0xe1, 0x2e, 0xcc, 0x30, 0xdc, + 0x37, 0x80, 0x88, 0x46, 0xbd, 0xfd, 0x22, 0xe9, 0x27, 0x08, 0x93, 0xc6, 0xd4, 0x77, 0x60, 0x71, + 0x96, 0xc7, 0x11, 0x33, 0xad, 0xa7, 0x70, 0x38, 0x67, 0xcc, 0xf1, 0xb4, 0xd2, 0x90, 0xcb, 0x92, + 0xc3, 0x39, 0x63, 0xbe, 0x87, 0x25, 0x0a, 0xbf, 0x03, 0x40, 0x7d, 0xe3, 0xa6, 0x01, 0xdc, 0x34, + 0x6f, 0x27, 0xdf, 0x85, 0xbe, 0xea, 0x1b, 0xe2, 0x61, 0xea, 0x73, 0xdc, 0x45, 0x65, 0xac, 0x89, + 0x1b, 0xe8, 0x19, 0xd4, 0xbd, 0x09, 0x77, 0xad, 0x98, 0xd7, 0x54, 0xb0, 0xa9, 0xb7, 0x5e, 0xd0, + 0x54, 0x57, 0xe1, 0x9a, 0x35, 0x51, 0x37, 0x7a, 0x64, 0xfb, 0xb4, 0xf0, 0x5c, 0x6b, 0xad, 0xfa, + 0x25, 0x5a, 0xab, 0x63, 0xe5, 0xe8, 0xd9, 0xf8, 0x07, 0x19, 0xa8, 0x68, 0xc3, 0x66, 0x2b, 0xd0, + 0xdc, 0x3a, 0x3c, 0x3c, 0xea, 0x98, 0xed, 0x7e, 0xf7, 0x93, 0x8e, 0xb5, 0xb5, 0x77, 0xd8, 0xeb, + 0x34, 0x6e, 0x09, 0xf0, 0xde, 0xe1, 0x56, 0x7b, 0xcf, 0xda, 0x39, 0x34, 0xb7, 0x14, 0x38, 0xc3, + 0x56, 0x81, 0x99, 0x9d, 0xfd, 0xc3, 0x7e, 0x27, 0x01, 0xcf, 0xb2, 0x06, 0x54, 0x37, 0xcd, 0x4e, + 0x7b, 0x6b, 0x57, 0x42, 0x72, 0x6c, 0x19, 0x1a, 0x3b, 0xc7, 0x07, 0xdb, 0xdd, 0x83, 0xa7, 0xd6, + 0x56, 0xfb, 0x60, 0xab, 0xb3, 0xd7, 0xd9, 0x6e, 0xe4, 0x59, 0x0d, 0xca, 0xed, 0xcd, 0xf6, 0xc1, + 0xf6, 0xe1, 0x41, 0x67, 0xbb, 0x51, 0x30, 0x7e, 0x09, 0xca, 0xf1, 0x44, 0x2b, 0x50, 0x3c, 0x3e, + 0x78, 0x76, 0x70, 0xf8, 0xe9, 0x41, 0xe3, 0x16, 0x2b, 0x43, 0x01, 0xfb, 0x6f, 0x64, 0x18, 0xc0, + 0x02, 0xf5, 0xd9, 0xc8, 0xb2, 0x12, 0xe4, 0x37, 0x0f, 0xfb, 0xbb, 0x8d, 0x9c, 0xf1, 0x17, 0x19, + 0x58, 0xc1, 0x29, 0x0f, 0x67, 0x99, 0xc0, 0x7d, 0xa8, 0x0c, 0x3c, 0x6f, 0x22, 0x34, 0xad, 0x58, + 0xa2, 0xd0, 0x41, 0x62, 0x83, 0x13, 0xf3, 0x3e, 0xf5, 0xfc, 0x01, 0x97, 0x3c, 0x00, 0x10, 0xb4, + 0x23, 0x20, 0x82, 0x06, 0x25, 0x11, 0x13, 0x06, 0xb1, 0x80, 0x0a, 0xc1, 0x08, 0x65, 0x15, 0x16, + 0x4e, 0x7c, 0x6e, 0x0f, 0xce, 0xe5, 0xee, 0x97, 0x4f, 0xec, 0xeb, 0xb1, 0x0d, 0x60, 0x20, 0x68, + 0x6a, 0xc4, 0x87, 0xb8, 0x05, 0x4a, 0xe6, 0xa2, 0x84, 0x6f, 0x49, 0xb0, 0x38, 0x8d, 0xec, 0x13, + 0xdb, 0x1d, 0x7a, 0x2e, 0x1f, 0x4a, 0x55, 0x23, 0x06, 0x18, 0x47, 0xb0, 0x3a, 0x3b, 0x3f, 0xc9, + 0x2f, 0x3e, 0xd0, 0xf8, 0x05, 0x49, 0xfe, 0xeb, 0x37, 0x93, 0x82, 0xc6, 0x3b, 0xfe, 0x51, 0x1e, + 0xf2, 0x42, 0x12, 0xbc, 0x51, 0x68, 0xd4, 0x45, 0xfb, 0xdc, 0x9c, 0xfb, 0x07, 0x4d, 0x0d, 0x24, + 0x22, 0x90, 0x3d, 0xab, 0x8c, 0x10, 0x14, 0x0d, 0xa2, 0x62, 0x9f, 0x0f, 0x2e, 0xa4, 0x41, 0x8b, + 0x8a, 0x4d, 0x3e, 0xb8, 0x40, 0x9d, 0xca, 0x0e, 0xa9, 0x2e, 0xed, 0xf7, 0x62, 0x60, 0x87, 0x58, + 0x53, 0x16, 0x61, 0xbd, 0x62, 0x54, 0x84, 0xb5, 0x5a, 0x50, 0x74, 0xdc, 0x13, 0x6f, 0xea, 0x0e, + 0x71, 0x7b, 0x97, 0x4c, 0xf5, 0x88, 0xde, 0x26, 0xe4, 0x44, 0xe2, 0x20, 0xa2, 0xdd, 0x5c, 0x12, + 0x80, 0xbe, 0x38, 0x8a, 0xde, 0x83, 0x72, 0x70, 0xed, 0x0e, 0xf4, 0x3d, 0xbc, 0x2c, 0xd7, 0x47, + 0xcc, 0x7e, 0xa3, 0x77, 0xed, 0x0e, 0x70, 0xc7, 0x96, 0x02, 0xf9, 0x8b, 0xbd, 0x0f, 0xa5, 0xc8, + 0xee, 0x4b, 0x1c, 0xf8, 0xb6, 0x5e, 0x43, 0x19, 0x7b, 0x49, 0xbd, 0x8e, 0x50, 0xd9, 0x23, 0x58, + 0x40, 0xe3, 0x6c, 0xd0, 0xaa, 0x62, 0x25, 0x25, 0xef, 0x8b, 0x61, 0xa0, 0xa3, 0x87, 0x0f, 0xd1, + 0x50, 0x6b, 0x4a, 0xb4, 0xf5, 0x67, 0x50, 0x4b, 0xb4, 0xa5, 0x2b, 0xd1, 0x35, 0x52, 0xa2, 0xdf, + 0xd2, 0x95, 0xe8, 0xf8, 0x24, 0x90, 0xd5, 0x74, 0xa5, 0xfa, 0x57, 0xa0, 0xa4, 0xa6, 0x22, 0xf6, + 0x9f, 0xdc, 0x3b, 0x56, 0xef, 0xb3, 0x83, 0xad, 0xc6, 0x2d, 0xb6, 0x08, 0x95, 0xf6, 0x16, 0x6e, + 0x69, 0x04, 0x64, 0x04, 0xca, 0x51, 0xbb, 0xd7, 0x8b, 0x20, 0x59, 0x63, 0x07, 0x1a, 0xb3, 0x23, + 0x15, 0x34, 0x19, 0x2a, 0x98, 0x34, 0x5d, 0xc7, 0x00, 0xa1, 0x22, 0x91, 0x35, 0x9a, 0xe4, 0x70, + 0x7a, 0x30, 0xde, 0x87, 0x86, 0x38, 0xd7, 0xc4, 0x52, 0x05, 0x9a, 0x09, 0x78, 0x24, 0x64, 0x3b, + 0xdd, 0x7c, 0x5d, 0x32, 0x2b, 0x04, 0xc3, 0xae, 0x8c, 0x0f, 0xa0, 0xa9, 0x55, 0x8b, 0x55, 0x5a, + 0x71, 0x56, 0xce, 0xaa, 0xb4, 0xa8, 0xc0, 0x50, 0x89, 0xb1, 0x06, 0x2b, 0xe2, 0xb1, 0x73, 0xc1, + 0xdd, 0xb0, 0x37, 0x3d, 0x21, 0x9f, 0xa3, 0xe3, 0xb9, 0x42, 0xb1, 0x29, 0x47, 0x25, 0x37, 0x13, + 0xf9, 0x86, 0xd4, 0x7e, 0xb3, 0x48, 0x1a, 0xeb, 0x5a, 0x0f, 0x58, 0x71, 0x03, 0xff, 0x26, 0xb4, + 0xe0, 0x72, 0x04, 0x12, 0xcb, 0x7a, 0xd4, 0xe9, 0x98, 0xd6, 0xe1, 0xc1, 0x5e, 0xf7, 0x40, 0x30, + 0x4a, 0xb1, 0xac, 0x08, 0xd8, 0xd9, 0x41, 0x48, 0xc6, 0x68, 0x40, 0xfd, 0x29, 0x0f, 0xbb, 0xee, + 0xa9, 0xa7, 0xfc, 0x6b, 0x7f, 0x55, 0x80, 0xc5, 0x08, 0x14, 0x6b, 0xd1, 0x17, 0xdc, 0x0f, 0x1c, + 0xcf, 0x45, 0x81, 0xb8, 0x6c, 0xaa, 0x47, 0x71, 0xba, 0x39, 0x43, 0xee, 0x86, 0x4e, 0x78, 0x6d, + 0x25, 0x4c, 0x6e, 0x75, 0x05, 0x96, 0xa7, 0xe8, 0x32, 0x14, 0xec, 0x91, 0x63, 0x2b, 0x57, 0x2d, + 0x3d, 0x08, 0xe8, 0xc0, 0x1b, 0x79, 0x3e, 0xca, 0xbe, 0x65, 0x93, 0x1e, 0xd8, 0x63, 0x58, 0x16, + 0x32, 0xb8, 0x6e, 0x07, 0x45, 0xfe, 0x41, 0xd6, 0x3f, 0xe6, 0x4e, 0xc7, 0x47, 0xb1, 0x2d, 0x54, + 0x94, 0x88, 0xb3, 0x53, 0xd4, 0x90, 0xc2, 0x52, 0x54, 0x81, 0xd4, 0xb9, 0xa6, 0x3b, 0x1d, 0xb7, + 0xb1, 0x24, 0xc2, 0x7f, 0x02, 0x2b, 0x02, 0x3f, 0x12, 0xaf, 0xa2, 0x1a, 0x8b, 0x58, 0x43, 0x34, + 0xd6, 0x95, 0x65, 0x51, 0x9d, 0x3b, 0x50, 0xa6, 0x51, 0x89, 0x37, 0x5e, 0x20, 0x31, 0x1e, 0x87, + 0xc2, 0xfd, 0x60, 0xce, 0xab, 0xba, 0x40, 0x82, 0xc0, 0x8c, 0x57, 0x55, 0xf3, 0xcb, 0x96, 0x66, + 0xfd, 0xb2, 0x4f, 0x60, 0xe5, 0x44, 0x90, 0xe0, 0x39, 0xb7, 0x87, 0xdc, 0xb7, 0x62, 0xc2, 0x26, + 0x75, 0x65, 0x49, 0x14, 0xee, 0x62, 0x59, 0xb4, 0x0f, 0x84, 0x9c, 0x23, 0xd8, 0x02, 0x1f, 0x5a, + 0xa1, 0x67, 0xa1, 0xf8, 0x83, 0x0c, 0xa6, 0x64, 0xd6, 0x08, 0xdc, 0xf7, 0xb6, 0x04, 0x30, 0x89, + 0x77, 0xe6, 0xdb, 0x93, 0x73, 0xa9, 0x50, 0x44, 0x78, 0x4f, 0x05, 0x90, 0xbd, 0x06, 0x45, 0x41, + 0xf2, 0x2e, 0x27, 0xe7, 0x17, 0x89, 0xec, 0x0a, 0xc4, 0xde, 0x82, 0x05, 0xec, 0x23, 0x68, 0x35, + 0x90, 0xde, 0xab, 0x31, 0x23, 0x77, 0x5c, 0x53, 0x96, 0x09, 0x61, 0x72, 0xea, 0x3b, 0xc4, 0x65, + 0xca, 0x26, 0xfe, 0x66, 0xdf, 0xd7, 0x58, 0xd6, 0x12, 0xd6, 0x55, 0xf2, 0xc0, 0x0c, 0xa5, 0xdd, + 0xc4, 0xbd, 0xbe, 0x52, 0x66, 0xf4, 0x83, 0x7c, 0xa9, 0xd2, 0xa8, 0x1a, 0xdf, 0x81, 0x02, 0xad, + 0x8e, 0x20, 0x42, 0x5c, 0xbb, 0x8c, 0x24, 0x42, 0x84, 0xb6, 0xa0, 0xe8, 0xf2, 0xf0, 0xd2, 0xf3, + 0x9f, 0x2b, 0xa3, 0xb4, 0x7c, 0x34, 0x7e, 0x8c, 0xd6, 0x94, 0xc8, 0xe3, 0x4e, 0x8a, 0xa1, 0x20, + 0x0f, 0x7a, 0xbd, 0xc1, 0xb9, 0x2d, 0x0d, 0x3c, 0x25, 0x04, 0xf4, 0xce, 0xed, 0x39, 0xf2, 0xc8, + 0xce, 0x3b, 0xdd, 0xdf, 0x82, 0xba, 0xf2, 0xf1, 0x07, 0xd6, 0x88, 0x9f, 0x86, 0x92, 0xdc, 0xab, + 0xd2, 0xc1, 0x1f, 0xec, 0xf1, 0xd3, 0xd0, 0xd8, 0x87, 0xa6, 0x24, 0xc8, 0xc3, 0x09, 0x57, 0x5d, + 0x7f, 0x37, 0x4d, 0x9e, 0xae, 0x3c, 0x59, 0x4a, 0x1e, 0xb4, 0x14, 0xbb, 0x90, 0x10, 0xb2, 0x8d, + 0x8f, 0x81, 0xe9, 0xc7, 0xb0, 0x6c, 0x4f, 0x4a, 0xb5, 0xca, 0x96, 0xaf, 0x5c, 0x62, 0x91, 0xec, + 0xec, 0x0c, 0xc5, 0xea, 0x04, 0xd3, 0xc1, 0x40, 0xc5, 0x5e, 0x94, 0x4c, 0xf5, 0x68, 0xfc, 0x69, + 0x06, 0x96, 0xb0, 0x31, 0xa5, 0x0f, 0x48, 0x26, 0xfb, 0x33, 0x0f, 0x52, 0xbc, 0x1f, 0x5d, 0xf6, + 0xa1, 0x87, 0x2f, 0x6f, 0x3d, 0xcd, 0xcf, 0x59, 0x4f, 0xbf, 0x0e, 0x8d, 0x21, 0x1f, 0x39, 0x18, + 0x86, 0xa3, 0x44, 0x09, 0xd2, 0x00, 0x16, 0x15, 0x5c, 0x6a, 0x83, 0xc6, 0x3f, 0xcb, 0x40, 0x93, + 0x24, 0x15, 0xd4, 0xab, 0xe5, 0x42, 0x7d, 0xa4, 0x14, 0x49, 0xc9, 0xaa, 0xe4, 0x9c, 0xe2, 0x13, + 0x1c, 0xa1, 0x84, 0xbc, 0x7b, 0x4b, 0x2a, 0x98, 0x12, 0xca, 0x3e, 0x44, 0x1d, 0xc6, 0xb5, 0x10, + 0x98, 0x12, 0xd6, 0x93, 0x7c, 0x29, 0xbb, 0xb7, 0x50, 0xc1, 0x71, 0x11, 0xb4, 0x59, 0x12, 0x9a, + 0xad, 0x00, 0x1b, 0x3b, 0x50, 0x4b, 0x74, 0x93, 0x30, 0xf1, 0x56, 0xc9, 0xc4, 0x3b, 0xe7, 0x46, + 0xc9, 0xce, 0xbb, 0x51, 0xfe, 0x5e, 0x1e, 0x98, 0x20, 0xa9, 0x99, 0xb7, 0x36, 0xe3, 0x83, 0xcc, + 0xce, 0xf9, 0x20, 0x1f, 0x03, 0xd3, 0x10, 0x94, 0x6b, 0x34, 0x17, 0xb9, 0x46, 0x1b, 0x31, 0xae, + 0xf4, 0x8c, 0x3e, 0x86, 0x65, 0x29, 0xd0, 0x46, 0x4e, 0x47, 0xb4, 0xdd, 0xd1, 0xfb, 0x61, 0x24, + 0xd9, 0x2a, 0xe7, 0x23, 0xda, 0xf1, 0x94, 0xff, 0x51, 0xe8, 0xe0, 0x64, 0xf2, 0x42, 0xff, 0xa3, + 0xd2, 0xbe, 0x35, 0x2a, 0x58, 0x78, 0x29, 0x15, 0x14, 0xe7, 0xa8, 0x40, 0xb3, 0xc0, 0x94, 0x92, + 0x16, 0x18, 0x03, 0x6a, 0xca, 0xcb, 0x48, 0xc1, 0x15, 0x24, 0xbd, 0x55, 0xa4, 0xab, 0x11, 0x03, + 0x2c, 0x1e, 0x40, 0x43, 0x99, 0x49, 0x22, 0x1b, 0x0f, 0x05, 0x0e, 0x48, 0x2b, 0xdb, 0x96, 0xb2, + 0xf4, 0x24, 0x2c, 0xea, 0x95, 0x19, 0x8b, 0xfa, 0xbb, 0xd0, 0x0c, 0x04, 0x11, 0x59, 0x53, 0x57, + 0x46, 0xf9, 0xf0, 0x21, 0xaa, 0x4e, 0x25, 0xb3, 0x81, 0x05, 0xc7, 0x31, 0x7c, 0xde, 0x7e, 0x51, + 0x4b, 0xb1, 0x5f, 0xbc, 0x1f, 0x3b, 0xe4, 0x82, 0x73, 0x67, 0x8c, 0x07, 0x77, 0x1c, 0x11, 0x23, + 0x17, 0xb8, 0x77, 0xee, 0x8c, 0x4d, 0xe5, 0xfd, 0x15, 0x0f, 0xc6, 0x7f, 0xcc, 0x40, 0x43, 0xd0, + 0x41, 0x82, 0xce, 0x7f, 0x09, 0x70, 0x47, 0xbe, 0x22, 0x99, 0x57, 0x04, 0xae, 0xa2, 0xf2, 0xef, + 0x00, 0x92, 0xad, 0x25, 0xf4, 0x44, 0x49, 0xe4, 0xad, 0x24, 0x91, 0xc7, 0x8c, 0x6c, 0xf7, 0x16, + 0x29, 0x00, 0x02, 0x92, 0xe6, 0x08, 0xcd, 0xa7, 0x38, 0x42, 0xb5, 0xad, 0xb0, 0x0b, 0xf0, 0x8c, + 0x5f, 0xef, 0x79, 0x03, 0xd4, 0xd0, 0xee, 0x02, 0x08, 0x82, 0x3c, 0xb5, 0xc7, 0x8e, 0xb4, 0xae, + 0x14, 0xcc, 0xf2, 0x73, 0x7e, 0xbd, 0x83, 0x00, 0xf1, 0x36, 0x44, 0x71, 0xbc, 0x1f, 0x0a, 0x66, + 0xe9, 0x39, 0xbf, 0xa6, 0xcd, 0x60, 0x41, 0xed, 0x19, 0xbf, 0xde, 0xe6, 0x24, 0xae, 0x79, 0xbe, + 0xa0, 0x04, 0xdf, 0xbe, 0x14, 0xf2, 0x59, 0xc2, 0x89, 0x59, 0xf1, 0xed, 0xcb, 0x67, 0xfc, 0x5a, + 0x39, 0x54, 0x8b, 0xa2, 0x7c, 0xe4, 0x0d, 0xe4, 0x09, 0xa4, 0xc2, 0x31, 0xe2, 0x41, 0x99, 0x0b, + 0xcf, 0xf1, 0xb7, 0xf1, 0xd7, 0x19, 0xa8, 0x89, 0xf1, 0x23, 0x83, 0x13, 0xeb, 0xae, 0xa2, 0x7a, + 0x32, 0x71, 0x54, 0xcf, 0x13, 0xc9, 0x1f, 0x88, 0x5b, 0x66, 0x6f, 0xe6, 0x96, 0xb8, 0xc0, 0xc4, + 0x2a, 0xdf, 0x83, 0x32, 0xed, 0x2d, 0xb1, 0x59, 0x73, 0x89, 0xb7, 0x94, 0x98, 0x90, 0x59, 0x42, + 0xb4, 0x67, 0x14, 0x44, 0xa0, 0x59, 0xea, 0x68, 0x89, 0xcb, 0x7e, 0x64, 0x9f, 0x4b, 0x79, 0x0d, + 0x85, 0x1b, 0x82, 0x08, 0x74, 0x33, 0xd8, 0xc2, 0x9c, 0x19, 0xec, 0x18, 0x2a, 0x1a, 0xd1, 0xa1, + 0xdd, 0x2f, 0x9a, 0x1d, 0x51, 0x68, 0x92, 0xaa, 0x12, 0xcb, 0xb3, 0x7b, 0xcb, 0xac, 0x0d, 0x74, + 0xc0, 0xe6, 0x02, 0xe4, 0x45, 0x25, 0xe3, 0x23, 0x68, 0x6a, 0xcd, 0x92, 0xba, 0x9a, 0x36, 0xe8, + 0x4c, 0x9a, 0x13, 0xfd, 0x9f, 0x67, 0x60, 0x59, 0xd6, 0xc6, 0x10, 0x31, 0x47, 0x9c, 0xe7, 0xfb, + 0xc1, 0x19, 0xfb, 0x25, 0xa8, 0x89, 0xd6, 0x2d, 0x9f, 0x9f, 0x39, 0x41, 0xc8, 0x95, 0x8f, 0x24, + 0x65, 0xf7, 0x08, 0xb6, 0x2e, 0x50, 0x4d, 0x89, 0xc9, 0x3e, 0x82, 0x0a, 0x56, 0x25, 0x85, 0x5a, + 0xbe, 0xb7, 0xd6, 0x7c, 0x45, 0x1a, 0xea, 0xee, 0x2d, 0x13, 0x82, 0xe8, 0x69, 0xb3, 0x0c, 0xc5, + 0xd0, 0x77, 0xce, 0xce, 0xb8, 0x6f, 0xac, 0x46, 0x43, 0x13, 0x5b, 0x91, 0xf7, 0x42, 0x3e, 0x11, + 0x52, 0x92, 0xf1, 0x5f, 0x32, 0x50, 0x91, 0x9b, 0xeb, 0x67, 0x76, 0x8c, 0xac, 0x6b, 0x31, 0x8e, + 0xa4, 0x3b, 0xc7, 0x21, 0x8d, 0xef, 0xc0, 0xe2, 0x58, 0x48, 0x4c, 0x42, 0xa2, 0x4f, 0x78, 0x45, + 0xea, 0x0a, 0x2c, 0x05, 0x96, 0x0d, 0x58, 0x42, 0xf9, 0x25, 0xb0, 0x42, 0x67, 0x64, 0xa9, 0x42, + 0x19, 0x4f, 0xd8, 0xa4, 0xa2, 0xbe, 0x33, 0xda, 0x97, 0x05, 0xe2, 0x18, 0x0f, 0x42, 0xfb, 0x8c, + 0x4b, 0xda, 0xa0, 0x07, 0xa3, 0x05, 0xab, 0x33, 0xc2, 0xbc, 0x52, 0x44, 0x7e, 0xbf, 0x09, 0x6b, + 0x73, 0x45, 0x52, 0x21, 0x89, 0xbc, 0x01, 0x23, 0x67, 0x7c, 0xe2, 0x45, 0xb6, 0xb2, 0x8c, 0xe6, + 0x0d, 0xd8, 0x13, 0x25, 0xca, 0x56, 0xc6, 0x61, 0x45, 0x11, 0x04, 0x1a, 0xbb, 0x22, 0x79, 0x3f, + 0x8b, 0xd2, 0xe8, 0x7b, 0x49, 0x4e, 0x36, 0xdb, 0x9d, 0x82, 0xeb, 0xe7, 0xe3, 0xd2, 0x64, 0x0e, + 0x16, 0xb0, 0xdf, 0x80, 0x56, 0x44, 0x77, 0x52, 0x80, 0xd2, 0x94, 0x17, 0xd1, 0xd3, 0x37, 0x5e, + 0xd2, 0x53, 0xc2, 0x8a, 0x82, 0x07, 0xe8, 0xaa, 0x22, 0x59, 0x6a, 0x30, 0xea, 0xeb, 0x02, 0x5e, + 0x57, 0x7d, 0xa1, 0x40, 0x34, 0xdf, 0x63, 0xfe, 0x95, 0xe6, 0x86, 0x16, 0xa2, 0x44, 0xb7, 0xe6, + 0x1d, 0xd9, 0x70, 0x54, 0xa4, 0xf7, 0x7b, 0x0e, 0xab, 0x97, 0xb6, 0x13, 0xaa, 0x39, 0x6a, 0xba, + 0x53, 0x01, 0xfb, 0x7b, 0xf2, 0x92, 0xfe, 0x3e, 0xa5, 0xca, 0x09, 0x11, 0x71, 0xf9, 0x72, 0x1e, + 0x18, 0xac, 0xff, 0x49, 0x16, 0xea, 0xc9, 0x56, 0xc4, 0xc6, 0x96, 0xcc, 0x4a, 0x09, 0x1d, 0x52, + 0x68, 0x97, 0x76, 0xdc, 0x03, 0x12, 0x36, 0xe6, 0x2d, 0xcc, 0xd9, 0x14, 0x0b, 0xb3, 0x6e, 0xd8, + 0xcd, 0xbd, 0xcc, 0x93, 0x96, 0x7f, 0x25, 0x4f, 0x5a, 0x21, 0xcd, 0x93, 0x76, 0xb3, 0xfb, 0x65, + 0xe1, 0x67, 0x72, 0xbf, 0x14, 0x5f, 0xe0, 0x7e, 0x49, 0x38, 0x8d, 0x4a, 0x33, 0x4e, 0xa3, 0xf5, + 0xbf, 0xce, 0x00, 0x9b, 0xa7, 0x65, 0xf6, 0x94, 0x4c, 0xed, 0x2e, 0x1f, 0x49, 0x3e, 0xf7, 0xcd, + 0x57, 0xdb, 0x0f, 0xea, 0xf5, 0xa9, 0xda, 0xec, 0x11, 0x2c, 0xe9, 0x31, 0xca, 0xba, 0xb6, 0x53, + 0x33, 0x99, 0x5e, 0x14, 0xeb, 0xc4, 0x9a, 0x93, 0x31, 0xff, 0x52, 0x27, 0x63, 0xe1, 0xa5, 0x4e, + 0xc6, 0x85, 0xa4, 0x93, 0x71, 0xfd, 0xbf, 0x65, 0x60, 0x29, 0x85, 0xe4, 0xbe, 0xba, 0x39, 0x0b, + 0x4a, 0x49, 0x30, 0xa1, 0xac, 0xa4, 0x14, 0x9d, 0xff, 0xec, 0x41, 0x25, 0xf6, 0x5b, 0xa9, 0x18, + 0xfe, 0x87, 0x2f, 0xe3, 0x05, 0x71, 0x0d, 0x53, 0xaf, 0xbe, 0xfe, 0x7b, 0x59, 0xa8, 0x68, 0x85, + 0x62, 0x15, 0x89, 0xc0, 0xb4, 0xd8, 0x0e, 0x92, 0x03, 0x50, 0x57, 0xbb, 0x07, 0xd2, 0x18, 0x4c, + 0xe5, 0xb4, 0x15, 0xe4, 0xa1, 0x8f, 0x08, 0x1b, 0xb0, 0xa4, 0xdc, 0x20, 0x3c, 0x0e, 0xe1, 0x92, + 0x27, 0x43, 0x53, 0x3a, 0x43, 0x78, 0x14, 0x11, 0xc6, 0x1e, 0x29, 0x09, 0x3e, 0x7e, 0x77, 0x48, + 0x98, 0x64, 0x69, 0x6d, 0x12, 0x39, 0xab, 0x97, 0x28, 0xa8, 0xf2, 0x3d, 0x58, 0x51, 0xc4, 0x9c, + 0xac, 0x41, 0xc6, 0x57, 0x26, 0x49, 0x59, 0xaf, 0xf2, 0x7d, 0xb8, 0x3b, 0x33, 0xa6, 0x99, 0xaa, + 0x14, 0x6b, 0x78, 0x3b, 0x31, 0x3a, 0xbd, 0x85, 0xf5, 0x9f, 0x40, 0x2d, 0xc1, 0xd6, 0xbe, 0xba, + 0x57, 0x3e, 0xab, 0x1f, 0xd3, 0x8a, 0xea, 0xfa, 0xf1, 0xfa, 0xff, 0xcd, 0x01, 0x9b, 0xe7, 0xac, + 0xbf, 0xc8, 0x21, 0xcc, 0x13, 0x66, 0x2e, 0x85, 0x30, 0xff, 0xbf, 0x9d, 0xf6, 0xef, 0x42, 0x53, + 0xe6, 0xb2, 0x68, 0xbe, 0x2c, 0xda, 0x9c, 0x8d, 0xa8, 0x40, 0x8d, 0xe2, 0x3b, 0xb3, 0x3e, 0xf5, + 0x52, 0x22, 0x7c, 0x5f, 0x13, 0x77, 0x66, 0x5c, 0xeb, 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, + 0x47, 0xd5, 0xac, 0xfe, 0xe4, 0x97, 0xbf, 0xf4, 0x61, 0xb7, 0xd1, 0xc6, 0xfa, 0x28, 0x63, 0x99, + 0xb2, 0x31, 0xe3, 0x3d, 0xa8, 0x68, 0x60, 0xf4, 0xef, 0x74, 0xf7, 0x37, 0x0f, 0x1b, 0xb7, 0x58, + 0x0d, 0xca, 0x66, 0x67, 0xeb, 0xf0, 0x93, 0x8e, 0xd9, 0xd9, 0x6e, 0x64, 0x58, 0x09, 0xf2, 0x7b, + 0x87, 0xbd, 0x7e, 0x23, 0x6b, 0xac, 0x43, 0x4b, 0xb6, 0x38, 0x6f, 0xeb, 0xfd, 0xed, 0x7c, 0x64, + 0x66, 0xc1, 0x42, 0xa9, 0x55, 0x7d, 0x0b, 0xaa, 0xba, 0x30, 0x22, 0x29, 0x62, 0xc6, 0x9d, 0x2a, + 0xf4, 0x29, 0x4f, 0xe3, 0xd5, 0x5b, 0x40, 0x4e, 0xb2, 0x61, 0x54, 0x8d, 0x24, 0xcc, 0x17, 0x78, + 0x55, 0x50, 0x78, 0x4e, 0x90, 0xe1, 0xdf, 0x80, 0x7a, 0xd2, 0xf0, 0x29, 0x39, 0x52, 0x9a, 0x7a, + 0x21, 0x6a, 0x27, 0x2c, 0xa1, 0xec, 0xfb, 0xd0, 0x98, 0x35, 0x9c, 0xca, 0x28, 0xe7, 0x1b, 0xea, + 0x2f, 0x3a, 0x49, 0x5b, 0x2a, 0xdb, 0x85, 0xe5, 0x34, 0x71, 0x0c, 0xe9, 0xe3, 0x66, 0xbd, 0x92, + 0xcd, 0x8b, 0x5c, 0xec, 0xbb, 0xd2, 0x3e, 0x5e, 0x48, 0xf3, 0x32, 0x6a, 0x8b, 0xbd, 0x41, 0xff, + 0x34, 0x4b, 0xf9, 0x05, 0x40, 0x0c, 0x63, 0x0d, 0xa8, 0x1e, 0x1e, 0x75, 0x0e, 0xac, 0xad, 0xdd, + 0xf6, 0xc1, 0x41, 0x67, 0xaf, 0x71, 0x8b, 0x31, 0xa8, 0xa3, 0x7b, 0x70, 0x3b, 0x82, 0x65, 0x04, + 0x4c, 0xfa, 0x29, 0x14, 0x2c, 0xcb, 0x96, 0xa1, 0xd1, 0x3d, 0x98, 0x81, 0xe6, 0x58, 0x0b, 0x96, + 0x8f, 0x3a, 0xe4, 0x51, 0x4c, 0xb4, 0x9b, 0x17, 0x22, 0xbe, 0x9c, 0xae, 0x10, 0xf1, 0x29, 0x27, + 0x4b, 0xee, 0x03, 0x25, 0xf9, 0xfe, 0x4e, 0x06, 0x56, 0x66, 0x0a, 0xe2, 0x48, 0x7b, 0x92, 0x7b, + 0x93, 0x12, 0x6f, 0x15, 0x81, 0x6a, 0x37, 0xbd, 0x0b, 0xcd, 0xc8, 0x56, 0x30, 0x73, 0x2a, 0x35, + 0xa2, 0x02, 0x85, 0xfc, 0x08, 0x96, 0x34, 0x93, 0xc3, 0x0c, 0xaf, 0x60, 0x5a, 0x91, 0xac, 0x60, + 0xac, 0x45, 0x11, 0xcd, 0x33, 0xa3, 0x1e, 0x52, 0xa2, 0x97, 0x5e, 0x10, 0xbb, 0x0f, 0x92, 0xe3, + 0x55, 0x8f, 0xec, 0xf1, 0x0c, 0x21, 0x24, 0x47, 0xab, 0xbf, 0x70, 0xd5, 0xfd, 0x1f, 0x2c, 0x00, + 0xfb, 0x78, 0xca, 0xfd, 0x6b, 0x8c, 0xa4, 0x0f, 0x5e, 0x16, 0x5a, 0xa6, 0xf4, 0xea, 0xec, 0x2b, + 0x65, 0xcb, 0xa4, 0x65, 0xab, 0xe4, 0x5f, 0x9e, 0xad, 0x52, 0x78, 0x59, 0xb6, 0xca, 0x9b, 0x50, + 0x73, 0xce, 0x5c, 0x4f, 0xb0, 0x42, 0x21, 0xb7, 0x06, 0xad, 0x85, 0xfb, 0xb9, 0x07, 0x55, 0xb3, + 0x2a, 0x81, 0x42, 0x6a, 0x0d, 0xd8, 0x47, 0x31, 0x12, 0x1f, 0x9e, 0x61, 0x66, 0x95, 0xce, 0x04, + 0x3b, 0xc3, 0x33, 0x2e, 0xcd, 0x08, 0xa8, 0x17, 0xa8, 0xca, 0x02, 0x1e, 0xb0, 0xb7, 0xa0, 0x1e, + 0x78, 0x53, 0xa1, 0x06, 0xa8, 0x65, 0x20, 0x07, 0x43, 0x95, 0xa0, 0x47, 0xca, 0x9b, 0xb4, 0x34, + 0x0d, 0xb8, 0x35, 0x76, 0x82, 0x40, 0x88, 0x67, 0x03, 0xcf, 0x0d, 0x7d, 0x6f, 0x24, 0x7d, 0x06, + 0xcd, 0x69, 0xc0, 0xf7, 0xa9, 0x64, 0x8b, 0x0a, 0xd8, 0xb7, 0xe3, 0x21, 0x4d, 0x6c, 0xc7, 0x0f, + 0x5a, 0x80, 0x43, 0x52, 0x33, 0x45, 0x69, 0xdb, 0x76, 0xfc, 0x68, 0x2c, 0xe2, 0x21, 0x98, 0xc9, + 0xa2, 0xa9, 0xcc, 0x66, 0xd1, 0xfc, 0x28, 0x3d, 0x8b, 0xa6, 0x86, 0x4d, 0x3f, 0x96, 0x4d, 0xcf, + 0xbf, 0xe2, 0x2f, 0x95, 0x4c, 0x33, 0x9f, 0x1c, 0x54, 0xff, 0x32, 0xc9, 0x41, 0x8b, 0x69, 0xc9, + 0x41, 0xef, 0x41, 0x05, 0xd3, 0x36, 0xac, 0x73, 0x47, 0xc8, 0x70, 0xe4, 0x03, 0x69, 0xe8, 0x79, + 0x1d, 0xbb, 0x8e, 0x1b, 0x9a, 0xe0, 0xab, 0x9f, 0xc1, 0x7c, 0x9e, 0x4e, 0xf3, 0x17, 0x98, 0xa7, + 0x23, 0xd3, 0x4b, 0x36, 0xa0, 0xa4, 0xde, 0x13, 0x63, 0x90, 0x3f, 0xf5, 0xbd, 0xb1, 0xb2, 0x0d, + 0x8b, 0xdf, 0xac, 0x0e, 0xd9, 0xd0, 0x93, 0x95, 0xb3, 0xa1, 0x67, 0xfc, 0x3a, 0x54, 0x34, 0x52, + 0x63, 0x6f, 0x90, 0x15, 0x4a, 0x68, 0x52, 0x52, 0xb6, 0xa4, 0x55, 0x2c, 0x4b, 0x68, 0x77, 0x28, + 0xf8, 0xcd, 0xd0, 0xf1, 0x39, 0x66, 0xd4, 0x59, 0x3e, 0xbf, 0xe0, 0x7e, 0xa0, 0x6c, 0xf5, 0x8d, + 0xa8, 0xc0, 0x24, 0xb8, 0xf1, 0xb7, 0x60, 0x29, 0xf1, 0x6e, 0x25, 0x8b, 0x78, 0x0b, 0x16, 0x70, + 0xdd, 0x94, 0x2f, 0x35, 0x99, 0x2f, 0x23, 0xcb, 0x30, 0x55, 0x9a, 0xdc, 0x0c, 0xd6, 0xc4, 0xf7, + 0x4e, 0xb0, 0x93, 0x8c, 0x59, 0x91, 0xb0, 0x23, 0xdf, 0x3b, 0x31, 0xfe, 0x3c, 0x07, 0xb9, 0x5d, + 0x6f, 0xa2, 0x87, 0x0f, 0x65, 0xe6, 0xc2, 0x87, 0xa4, 0x7a, 0x68, 0x45, 0xea, 0x9f, 0x94, 0xd9, + 0xd1, 0xc0, 0xae, 0x54, 0xc0, 0x07, 0x50, 0x17, 0x7c, 0x22, 0xf4, 0x84, 0x7e, 0x7d, 0x69, 0xfb, + 0x24, 0x10, 0xe7, 0x68, 0xf3, 0xd9, 0xe3, 0xb0, 0xef, 0xed, 0x10, 0x9c, 0x2d, 0x43, 0x2e, 0x52, + 0x5f, 0xb0, 0x58, 0x3c, 0xb2, 0x55, 0x58, 0xc0, 0x38, 0xd2, 0x6b, 0xe9, 0x2c, 0x94, 0x4f, 0xec, + 0x9b, 0xb0, 0x94, 0x6c, 0x97, 0x58, 0x91, 0x94, 0x8d, 0xf4, 0x86, 0x91, 0x27, 0xdd, 0x06, 0xc1, + 0x47, 0x08, 0x47, 0xc6, 0x1c, 0x9c, 0x72, 0x8e, 0x45, 0x1a, 0xd3, 0x2b, 0x25, 0x98, 0xde, 0x3d, + 0xa8, 0x84, 0xa3, 0x0b, 0x6b, 0x62, 0x5f, 0x8f, 0x3c, 0x7b, 0x28, 0xf7, 0x37, 0x84, 0xa3, 0x8b, + 0x23, 0x82, 0xb0, 0x47, 0x00, 0xe3, 0xc9, 0x44, 0xee, 0x3d, 0xb4, 0x57, 0xc7, 0xa4, 0xbc, 0x7f, + 0x74, 0x44, 0x24, 0x67, 0x96, 0xc7, 0x93, 0x09, 0xfd, 0x64, 0xdb, 0x50, 0x4f, 0xcd, 0x7a, 0xbb, + 0xab, 0xc2, 0x1e, 0xbd, 0xc9, 0x46, 0xca, 0xe6, 0xac, 0x0d, 0x74, 0xd8, 0xfa, 0xf7, 0x81, 0xfd, + 0x9c, 0xb9, 0x67, 0x7d, 0x28, 0x47, 0xe3, 0xd3, 0x53, 0xb7, 0x30, 0x90, 0xb9, 0x92, 0x48, 0xdd, + 0x6a, 0x0f, 0x87, 0xbe, 0xe0, 0x8b, 0x74, 0x60, 0x46, 0x2c, 0x1f, 0xb4, 0x13, 0xb3, 0x4d, 0x7c, + 0xdf, 0xf8, 0xcb, 0x0c, 0x14, 0x28, 0x8f, 0xec, 0x6d, 0x58, 0x24, 0xfc, 0x28, 0x14, 0x4b, 0xba, + 0x18, 0xe9, 0xdc, 0xed, 0xcb, 0x28, 0x2c, 0xb1, 0x2d, 0xb4, 0x1c, 0xd8, 0x6c, 0xf4, 0xe6, 0xb5, + 0x3c, 0xd8, 0x7b, 0x50, 0x8e, 0xba, 0xd6, 0x48, 0xa7, 0xa4, 0x7a, 0x66, 0xaf, 0x43, 0xfe, 0xdc, + 0x9b, 0x28, 0x3b, 0x0d, 0xc4, 0x2b, 0x69, 0x22, 0x3c, 0x1e, 0x8b, 0xe8, 0x83, 0x06, 0x2f, 0xed, + 0x0b, 0x51, 0x27, 0x48, 0x06, 0xf3, 0x73, 0x5c, 0x48, 0x99, 0xe3, 0x31, 0x2c, 0x0a, 0x3e, 0xa0, + 0xb9, 0xfa, 0x6f, 0x3e, 0x34, 0xbf, 0x2e, 0x24, 0xbc, 0xc1, 0x68, 0x3a, 0xe4, 0xba, 0xa5, 0x0c, + 0xe3, 0x82, 0x24, 0x5c, 0x49, 0xd6, 0xc6, 0x1f, 0x64, 0x88, 0xbf, 0x88, 0x76, 0xd9, 0x03, 0xc8, + 0x8b, 0xf3, 0x6d, 0xc6, 0x92, 0x1b, 0x45, 0x94, 0x0b, 0x3c, 0x13, 0x31, 0x30, 0x71, 0x7c, 0x3a, + 0x4e, 0xb6, 0x5e, 0x33, 0x2b, 0xee, 0x74, 0x1c, 0x19, 0x9a, 0xbe, 0xa6, 0xa6, 0x35, 0x63, 0xa4, + 0xa1, 0xd9, 0x47, 0xdb, 0x74, 0x43, 0x0b, 0x30, 0xca, 0x27, 0x4e, 0x4c, 0x25, 0x05, 0x0e, 0xcf, + 0xb8, 0x16, 0x58, 0xf4, 0x47, 0x59, 0xa8, 0x25, 0x46, 0x84, 0x11, 0x56, 0xe2, 0x00, 0x20, 0x37, + 0x82, 0x7c, 0xdf, 0x20, 0x40, 0x52, 0x50, 0xd7, 0xd6, 0x29, 0x9b, 0x58, 0xa7, 0x28, 0xa8, 0x21, + 0xa7, 0x07, 0x35, 0x3c, 0x86, 0x72, 0x9c, 0xfb, 0x9c, 0x1c, 0x92, 0xe8, 0x4f, 0xc5, 0xd5, 0xc7, + 0x48, 0x71, 0x18, 0x44, 0x41, 0x0f, 0x83, 0xf8, 0x9e, 0xe6, 0x35, 0x5f, 0xc0, 0x66, 0x8c, 0xb4, + 0x15, 0xfd, 0x85, 0xf8, 0xcc, 0x8d, 0x8f, 0xa0, 0xa2, 0x0d, 0x5e, 0xf7, 0x8e, 0x67, 0x12, 0xde, + 0xf1, 0x28, 0x03, 0x26, 0x1b, 0x67, 0xc0, 0x18, 0xbf, 0x99, 0x85, 0x9a, 0xd8, 0x5f, 0x8e, 0x7b, + 0x76, 0xe4, 0x8d, 0x9c, 0x01, 0xba, 0x15, 0xa2, 0x1d, 0x26, 0x05, 0x2d, 0xb5, 0xcf, 0xe4, 0x16, + 0x23, 0x39, 0x4b, 0x4f, 0xf4, 0x23, 0x26, 0x1d, 0x25, 0xfa, 0x19, 0x50, 0x13, 0x8c, 0xf1, 0xc4, + 0x0e, 0xb8, 0x96, 0x99, 0x6d, 0x56, 0x4e, 0x39, 0xdf, 0xb4, 0x03, 0xe2, 0x90, 0xdf, 0x84, 0x25, + 0x81, 0x83, 0x39, 0x4e, 0x63, 0x67, 0x34, 0x72, 0x08, 0x93, 0x0c, 0x4d, 0x8d, 0x53, 0xce, 0x4d, + 0x3b, 0xe4, 0xfb, 0xa2, 0x40, 0x26, 0x72, 0x97, 0x86, 0x4e, 0x60, 0x9f, 0xc4, 0x71, 0x70, 0xd1, + 0x33, 0x3a, 0x03, 0xed, 0x2b, 0xcd, 0x19, 0x48, 0x06, 0x88, 0xca, 0xd8, 0xbe, 0x8a, 0x9c, 0x81, + 0x33, 0x94, 0x54, 0x9c, 0xa5, 0x24, 0xe3, 0x3f, 0x67, 0xa1, 0xa2, 0x91, 0xe5, 0xab, 0x9c, 0xae, + 0x77, 0xe7, 0xdc, 0x40, 0x65, 0xdd, 0xe3, 0xf3, 0x66, 0xb2, 0x4b, 0x8c, 0x19, 0xa0, 0x94, 0x71, + 0x8d, 0x80, 0xef, 0x40, 0x59, 0xec, 0xba, 0xf7, 0xd0, 0x60, 0x2a, 0x2f, 0x3c, 0x40, 0xc0, 0xd1, + 0xf4, 0x44, 0x15, 0x3e, 0xc1, 0xc2, 0x42, 0x5c, 0xf8, 0x44, 0x14, 0xbe, 0x28, 0xf8, 0xf5, 0x3b, + 0x50, 0x95, 0xad, 0xe2, 0x3b, 0xc5, 0xe9, 0xc6, 0xbb, 0x3e, 0xf1, 0xbe, 0xcd, 0x0a, 0x75, 0x47, + 0x2f, 0x5f, 0x56, 0x7c, 0xa2, 0x2a, 0x96, 0x5e, 0x56, 0xf1, 0x09, 0x3d, 0x18, 0x3b, 0x51, 0x3c, + 0x31, 0xc6, 0xab, 0x28, 0x3e, 0xf6, 0x08, 0x96, 0x14, 0xbb, 0x9a, 0xba, 0xb6, 0xeb, 0x7a, 0x53, + 0x77, 0xc0, 0x55, 0x6a, 0x0c, 0x93, 0x45, 0xc7, 0x71, 0x89, 0x31, 0x8c, 0x72, 0x27, 0x29, 0xee, + 0xe5, 0x21, 0x14, 0x48, 0x2e, 0x27, 0xe1, 0x23, 0x9d, 0x71, 0x11, 0x0a, 0x7b, 0x00, 0x05, 0x12, + 0xcf, 0xb3, 0x37, 0x32, 0x1b, 0x42, 0x30, 0x36, 0x60, 0x11, 0x45, 0x4c, 0x8d, 0xe3, 0xbe, 0x48, + 0x2a, 0x31, 0x96, 0x81, 0x1d, 0xd0, 0x26, 0xd2, 0xe3, 0xb1, 0xfe, 0x7b, 0x0e, 0x2a, 0x1a, 0x58, + 0xb0, 0x45, 0x8c, 0xe0, 0xb1, 0x86, 0x8e, 0x3d, 0xe6, 0xca, 0x37, 0x55, 0x33, 0x6b, 0x08, 0xdd, + 0x96, 0x40, 0x71, 0x28, 0xd8, 0x17, 0x67, 0x96, 0x37, 0x0d, 0xad, 0x21, 0x3f, 0xf3, 0x39, 0x97, + 0xc2, 0x52, 0xd5, 0xbe, 0x38, 0x3b, 0x9c, 0x86, 0xdb, 0x08, 0x13, 0x58, 0x82, 0xa8, 0x35, 0x2c, + 0x19, 0x74, 0x32, 0xb6, 0xaf, 0x62, 0x2c, 0x19, 0xf9, 0x44, 0x4b, 0x94, 0x8f, 0x22, 0x9f, 0x48, + 0x6d, 0x99, 0xe5, 0xe4, 0x85, 0x79, 0x4e, 0xfe, 0x6d, 0x58, 0x25, 0x4e, 0x2e, 0x79, 0x84, 0x35, + 0x43, 0x52, 0xcb, 0x58, 0x2a, 0x27, 0xa9, 0xc9, 0x5f, 0x0d, 0x31, 0x03, 0xb5, 0x3f, 0x02, 0xe7, + 0xc7, 0xb4, 0xa3, 0x32, 0xa6, 0x98, 0x99, 0x6c, 0xbc, 0xe7, 0xfc, 0x98, 0x0b, 0x4c, 0xf4, 0xac, + 0xeb, 0x98, 0x32, 0xc6, 0x7a, 0xec, 0xb8, 0xb3, 0x98, 0xf6, 0x55, 0x12, 0xb3, 0x2c, 0x31, 0xed, + 0x2b, 0x1d, 0xf3, 0x7d, 0x58, 0x1b, 0xf3, 0xa1, 0x63, 0x27, 0x9b, 0xb5, 0x62, 0x09, 0x62, 0x99, + 0x8a, 0xb5, 0x3a, 0x3d, 0xd2, 0x20, 0xc5, 0x6a, 0xfc, 0xd8, 0x1b, 0x9f, 0x38, 0x74, 0x78, 0x92, + 0xaf, 0x3f, 0x6f, 0xd6, 0xdd, 0xe9, 0xf8, 0x87, 0x08, 0x16, 0x55, 0x02, 0xa3, 0x06, 0x95, 0x5e, + 0xe8, 0x4d, 0xd4, 0x6b, 0xae, 0x43, 0x95, 0x1e, 0x65, 0xe2, 0xd3, 0x1d, 0xb8, 0x8d, 0xb4, 0xd9, + 0xf7, 0x26, 0xde, 0xc8, 0x3b, 0xbb, 0x4e, 0x18, 0x94, 0xfe, 0x6b, 0x06, 0x96, 0x12, 0xa5, 0x72, + 0x9f, 0x7f, 0x9b, 0x36, 0x56, 0x94, 0xbd, 0x42, 0xe4, 0xdc, 0xd4, 0x0e, 0x1f, 0x42, 0xa4, 0x5d, + 0xa5, 0x32, 0x5a, 0xda, 0x71, 0xd6, 0xb5, 0xaa, 0x48, 0xb4, 0xdd, 0x9a, 0xa7, 0x6d, 0x59, 0x5f, + 0xe5, 0x63, 0xab, 0x26, 0x7e, 0x59, 0xc6, 0xc1, 0x0f, 0xe5, 0x94, 0x73, 0xc9, 0x48, 0x5f, 0xdd, + 0xf8, 0xa4, 0x46, 0x10, 0x5b, 0xa4, 0x02, 0xe3, 0xdf, 0x64, 0x00, 0xe2, 0xd1, 0x61, 0xac, 0x71, + 0x74, 0x80, 0xd2, 0x85, 0x46, 0xda, 0x61, 0xf9, 0x06, 0x54, 0xa3, 0x90, 0xc3, 0xf8, 0x48, 0xae, + 0x28, 0x98, 0x38, 0x97, 0xdf, 0x81, 0xc5, 0xb3, 0x91, 0x77, 0x82, 0xa2, 0x93, 0x3c, 0x40, 0x29, + 0xfd, 0xab, 0x4e, 0x60, 0x75, 0x2c, 0xc6, 0x07, 0x78, 0x3e, 0x35, 0x2a, 0x51, 0x3f, 0x8e, 0x8d, + 0xdf, 0xca, 0x46, 0xb1, 0x57, 0xf1, 0x4a, 0xbc, 0x58, 0xcf, 0xf8, 0x59, 0x5c, 0xf8, 0x2f, 0xf2, + 0x4a, 0x7d, 0x04, 0x75, 0x9f, 0xb8, 0xa3, 0x62, 0x9d, 0xf9, 0x17, 0xb0, 0xce, 0x9a, 0x9f, 0x38, + 0x72, 0xbf, 0x0e, 0x0d, 0x7b, 0x78, 0xc1, 0xfd, 0xd0, 0x41, 0xb3, 0x31, 0x0a, 0x6a, 0x32, 0xda, + 0x49, 0x83, 0xa3, 0x44, 0xf4, 0x0e, 0x2c, 0xca, 0x64, 0xbc, 0x08, 0x53, 0x5e, 0xef, 0x11, 0x83, + 0x05, 0xa2, 0xf1, 0xef, 0x54, 0xb0, 0x57, 0xf2, 0xed, 0xbe, 0x78, 0x55, 0xf4, 0x19, 0x66, 0xe7, + 0xfd, 0x6e, 0x92, 0x90, 0xa4, 0x35, 0x5a, 0xf2, 0x23, 0x02, 0x4a, 0x5b, 0x74, 0x72, 0x59, 0xf3, + 0xaf, 0xb2, 0xac, 0xc6, 0x9f, 0x64, 0xa0, 0xb8, 0xeb, 0x4d, 0x84, 0x5e, 0x2e, 0xe4, 0x39, 0xdc, + 0x26, 0x91, 0xb3, 0x64, 0x41, 0x3c, 0x76, 0x87, 0x2f, 0xce, 0x39, 0x49, 0x95, 0x37, 0x6a, 0x49, + 0x79, 0xe3, 0x7b, 0x70, 0x07, 0x7d, 0x51, 0xbe, 0x37, 0xf1, 0x7c, 0xb1, 0x55, 0xed, 0x11, 0xc9, + 0x1d, 0x9e, 0x1b, 0x9e, 0x2b, 0xde, 0x79, 0xfb, 0x94, 0xf3, 0x23, 0x0d, 0x63, 0x3f, 0x42, 0xc0, + 0xac, 0xae, 0x51, 0x78, 0x61, 0x91, 0xaa, 0x28, 0x05, 0x23, 0xe2, 0xa8, 0x8b, 0xa2, 0xa0, 0x83, + 0x70, 0x14, 0x8d, 0x8c, 0xef, 0x42, 0x39, 0xb2, 0x3a, 0xb0, 0x77, 0xa1, 0x7c, 0xee, 0x4d, 0xa4, + 0x69, 0x22, 0x93, 0xc8, 0xcb, 0x91, 0xb3, 0x36, 0x4b, 0xe7, 0xf4, 0x23, 0x30, 0xfe, 0xbc, 0x08, + 0xc5, 0xae, 0x7b, 0xe1, 0x39, 0x03, 0x0c, 0x17, 0x1b, 0xf3, 0xb1, 0xa7, 0x32, 0x82, 0xc5, 0x6f, + 0x0c, 0x09, 0x89, 0x2f, 0xe9, 0xc8, 0xc9, 0x90, 0x90, 0xe8, 0x7a, 0x8e, 0x15, 0x58, 0xf0, 0xf5, + 0x5b, 0x36, 0x0a, 0x3e, 0x06, 0xb0, 0x46, 0x4a, 0x5b, 0x41, 0xcb, 0xa8, 0x16, 0x6d, 0xd1, 0xed, + 0x0f, 0xb8, 0x64, 0x94, 0xa1, 0x55, 0x46, 0x08, 0x2e, 0xd8, 0x6b, 0x50, 0x94, 0x69, 0x30, 0x94, + 0x54, 0x40, 0x11, 0xa7, 0x12, 0x84, 0xd4, 0xe0, 0x73, 0xf2, 0x25, 0x46, 0x12, 0x95, 0xd0, 0xd3, + 0x25, 0x70, 0x5b, 0xd0, 0xda, 0x3d, 0xa8, 0x10, 0x3e, 0xa1, 0x94, 0x64, 0x80, 0x17, 0x82, 0x10, + 0x21, 0xe5, 0xb2, 0x9a, 0x72, 0xea, 0x65, 0x35, 0x18, 0x0f, 0x18, 0x71, 0x59, 0x9a, 0x22, 0xd0, + 0x15, 0x25, 0x1a, 0x5c, 0xdd, 0xd4, 0x24, 0x95, 0x7b, 0x4a, 0x58, 0x54, 0xca, 0xfd, 0x9b, 0x50, + 0x3b, 0xb5, 0x47, 0xa3, 0x13, 0x7b, 0xf0, 0x9c, 0x74, 0xd2, 0x2a, 0x99, 0xe1, 0x14, 0x10, 0x95, + 0xd2, 0x7b, 0x50, 0xd1, 0xde, 0x32, 0x46, 0x6f, 0xe5, 0x4d, 0x88, 0xdf, 0xef, 0xac, 0xa9, 0xa9, + 0xfe, 0x0a, 0xa6, 0x26, 0x2d, 0x8a, 0x6d, 0x31, 0x19, 0xc5, 0x76, 0x07, 0xb9, 0xa9, 0x8c, 0x74, + 0x6a, 0xd0, 0x7d, 0x18, 0xf6, 0x70, 0x88, 0x91, 0x4e, 0x74, 0xf9, 0x1c, 0x2e, 0x1e, 0x95, 0x37, + 0x49, 0xa8, 0x25, 0x18, 0xa1, 0xdc, 0x25, 0x7b, 0xe9, 0xc4, 0x76, 0x86, 0x18, 0x35, 0x4c, 0x6a, + 0x6c, 0xd1, 0x1e, 0x87, 0x47, 0xb6, 0x33, 0x64, 0xf7, 0xa1, 0xaa, 0x8a, 0xf1, 0x74, 0x5c, 0xa2, + 0xf5, 0x97, 0xc5, 0xe2, 0x4c, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe3, 0xac, 0xc3, 0x8a, 0x44, 0x41, + 0x3a, 0x78, 0x0f, 0x83, 0x43, 0x42, 0x8e, 0xb9, 0x85, 0xf5, 0x27, 0x77, 0xe4, 0x5c, 0x25, 0x95, + 0xaa, 0xff, 0xe4, 0xa5, 0x21, 0x4c, 0x21, 0x88, 0x91, 0xb3, 0x68, 0x35, 0x21, 0x88, 0x49, 0x54, + 0x74, 0x16, 0x11, 0x02, 0xfb, 0xae, 0xa6, 0x48, 0xb5, 0x10, 0xf9, 0xb5, 0x99, 0xf6, 0x6f, 0x4a, + 0x9a, 0xb8, 0x0b, 0xe0, 0x04, 0xe2, 0x94, 0x09, 0xb8, 0x3b, 0xc4, 0x34, 0xc1, 0x92, 0x59, 0x76, + 0x82, 0x67, 0x04, 0xf8, 0x6a, 0x35, 0xac, 0x36, 0x54, 0xf5, 0x69, 0xb2, 0x12, 0xe4, 0x0f, 0x8f, + 0x3a, 0x07, 0x8d, 0x5b, 0xac, 0x02, 0xc5, 0x5e, 0xa7, 0xdf, 0xdf, 0x43, 0x97, 0x53, 0x15, 0x4a, + 0x51, 0x8e, 0x52, 0x56, 0x3c, 0xb5, 0xb7, 0xb6, 0x3a, 0x47, 0xfd, 0xce, 0x76, 0x23, 0xf7, 0x83, + 0x7c, 0x29, 0xdb, 0xc8, 0x19, 0x7f, 0x91, 0x83, 0x8a, 0xb6, 0x0a, 0x2f, 0x66, 0xc6, 0x77, 0x01, + 0x50, 0xa5, 0x89, 0x03, 0xe1, 0xf2, 0x66, 0x59, 0x40, 0xe8, 0xe5, 0xeb, 0xc6, 0xf2, 0x1c, 0x5d, + 0xb4, 0xa2, 0x8c, 0xe5, 0x6f, 0x42, 0x8d, 0xee, 0x2c, 0xd1, 0x1d, 0x87, 0x05, 0xb3, 0x4a, 0x40, + 0xc9, 0xaa, 0x31, 0xc9, 0x11, 0x91, 0x30, 0xfd, 0x45, 0xde, 0x60, 0x40, 0x20, 0x4c, 0x80, 0xc1, + 0xec, 0xa5, 0xc0, 0x1b, 0x5d, 0x70, 0xc2, 0x20, 0x89, 0xb0, 0x22, 0x61, 0x7d, 0x99, 0xae, 0x29, + 0xf9, 0xa1, 0x96, 0x65, 0x57, 0x30, 0xab, 0x04, 0x94, 0x1d, 0x7d, 0x53, 0x11, 0x50, 0x09, 0x09, + 0x68, 0x6d, 0x9e, 0x1a, 0x12, 0xc4, 0xb3, 0x37, 0x67, 0xcf, 0x2a, 0x23, 0x61, 0x7c, 0x6d, 0xbe, + 0xde, 0xcb, 0xed, 0x5a, 0xec, 0x5d, 0x60, 0xe3, 0xc9, 0xc4, 0x4a, 0xb1, 0x34, 0xe5, 0xcd, 0xc5, + 0xf1, 0x64, 0xd2, 0xd7, 0x0c, 0x31, 0x5f, 0x81, 0x11, 0xec, 0x73, 0x60, 0x6d, 0xb1, 0x81, 0x71, + 0x88, 0x91, 0x09, 0x35, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, 0x70, 0xbf, 0x6c, 0x2a, 0xf7, 0x7b, + 0x11, 0x9f, 0x30, 0x76, 0xa0, 0x72, 0xa4, 0xdd, 0x88, 0x74, 0x5f, 0x9c, 0x10, 0xea, 0x2e, 0x24, + 0x3a, 0x3b, 0xc8, 0xb8, 0xe5, 0xcb, 0x2b, 0x90, 0xb4, 0xd1, 0x64, 0xb5, 0xd1, 0x18, 0xff, 0x3a, + 0x43, 0xb7, 0x4d, 0x44, 0x83, 0x8f, 0x2f, 0x61, 0x52, 0x7e, 0xa0, 0x38, 0x19, 0xb6, 0xa2, 0xfc, + 0x3f, 0x32, 0x8f, 0x15, 0x87, 0x66, 0x79, 0xa7, 0xa7, 0x01, 0x57, 0xc1, 0x06, 0x15, 0x84, 0x1d, + 0x22, 0x48, 0x09, 0xdf, 0x42, 0xc2, 0x77, 0xa8, 0xfd, 0x40, 0x46, 0x18, 0x08, 0xe1, 0x7b, 0xdf, + 0xbe, 0x92, 0xbd, 0x06, 0x42, 0x04, 0x91, 0x86, 0x6a, 0x95, 0xcc, 0x16, 0x3d, 0x1b, 0xff, 0x42, + 0xe6, 0xeb, 0xce, 0xae, 0xef, 0x43, 0x28, 0x45, 0xad, 0x26, 0x4f, 0x58, 0x85, 0x19, 0x95, 0x8b, + 0x73, 0x1c, 0xb5, 0xf2, 0xc4, 0x88, 0x69, 0x73, 0xa1, 0xb3, 0xa1, 0xab, 0x8d, 0xfa, 0x1b, 0xc0, + 0x4e, 0x1d, 0x7f, 0x16, 0x99, 0x36, 0x5b, 0x03, 0x4b, 0x34, 0x6c, 0xe3, 0x18, 0x96, 0x14, 0x97, + 0xd0, 0x34, 0x82, 0xe4, 0xcb, 0xcb, 0xbc, 0x84, 0xc9, 0x67, 0xe7, 0x98, 0xbc, 0xf1, 0xd3, 0x3c, + 0x14, 0xd5, 0xed, 0x62, 0x69, 0x37, 0x62, 0x95, 0x93, 0x37, 0x62, 0xb5, 0x12, 0xb7, 0xa7, 0xe0, + 0xab, 0x97, 0xe7, 0xfd, 0x3b, 0xb3, 0x47, 0xb6, 0x66, 0x34, 0x4f, 0x1c, 0xdb, 0xab, 0x90, 0x9f, + 0xd8, 0xe1, 0x39, 0x1a, 0xc8, 0x88, 0x78, 0xf0, 0x59, 0x19, 0xd3, 0x0b, 0x49, 0x63, 0x7a, 0xda, + 0xed, 0x61, 0x24, 0x92, 0xce, 0xdd, 0x1e, 0x76, 0x07, 0x48, 0xbe, 0xd0, 0x62, 0xa5, 0x4a, 0x08, + 0x10, 0x67, 0x51, 0x52, 0x1c, 0x29, 0xcd, 0x8a, 0x23, 0xaf, 0x2c, 0x2a, 0x7c, 0x1b, 0x16, 0x28, + 0xf3, 0x5e, 0x26, 0xed, 0xa9, 0x03, 0x45, 0xae, 0xa1, 0xfa, 0x4f, 0x51, 0xd4, 0xa6, 0xc4, 0xd5, + 0xaf, 0xe2, 0xa9, 0x24, 0xae, 0xe2, 0xd1, 0x8d, 0xfc, 0xd5, 0xa4, 0x91, 0xff, 0x01, 0x34, 0xa2, + 0x05, 0x45, 0x93, 0x99, 0x1b, 0xc8, 0x94, 0xa0, 0xba, 0x82, 0x0b, 0x2e, 0x79, 0x10, 0xc4, 0x07, + 0x62, 0x3d, 0x71, 0x20, 0x0a, 0x1e, 0xd6, 0x0e, 0x43, 0x3e, 0x9e, 0x84, 0xf2, 0x40, 0xc4, 0xa4, + 0x01, 0x7d, 0x80, 0xc9, 0x74, 0xd6, 0x1a, 0x94, 0xbb, 0x07, 0xd6, 0xce, 0x5e, 0xf7, 0xe9, 0x6e, + 0xbf, 0x91, 0x11, 0x8f, 0xbd, 0xe3, 0xad, 0xad, 0x4e, 0x67, 0x1b, 0x4f, 0x1c, 0x80, 0x85, 0x9d, + 0x76, 0x57, 0x9c, 0x3e, 0x39, 0xe3, 0x77, 0xb2, 0x50, 0xd1, 0x9a, 0x67, 0xef, 0x47, 0xab, 0x42, + 0xb7, 0xb5, 0xdc, 0x9d, 0x1f, 0xc2, 0x86, 0x62, 0xc5, 0xda, 0xb2, 0x44, 0x77, 0xa5, 0x65, 0x6f, + 0xbc, 0x2b, 0x8d, 0xbd, 0x0d, 0x8b, 0x36, 0xb5, 0x10, 0xad, 0x82, 0x34, 0x07, 0x4b, 0xb0, 0x5c, + 0x04, 0x8c, 0x10, 0x8c, 0xcf, 0x13, 0x81, 0x97, 0x57, 0x41, 0x79, 0xd1, 0x91, 0x82, 0x8b, 0x55, + 0x3c, 0xb5, 0x9d, 0xd1, 0xd4, 0xe7, 0xd2, 0x7d, 0x1b, 0x9d, 0xcc, 0x04, 0x35, 0x55, 0xb1, 0xf1, + 0x01, 0x40, 0x3c, 0xe6, 0xe4, 0xe2, 0xdc, 0x4a, 0x2e, 0x4e, 0x46, 0x5b, 0x9c, 0xac, 0xb1, 0x4d, + 0x6c, 0x44, 0x2e, 0x74, 0xe4, 0xa9, 0xfe, 0x26, 0x28, 0x8b, 0x94, 0x85, 0x71, 0xba, 0x93, 0x11, + 0x0f, 0x55, 0xe2, 0x6f, 0x53, 0x96, 0x74, 0xa3, 0x02, 0x95, 0x87, 0x1f, 0xb7, 0x12, 0x73, 0x23, + 0x49, 0x92, 0xb3, 0xdc, 0x48, 0xa2, 0x9a, 0x51, 0xb9, 0xb1, 0x0e, 0xad, 0x6d, 0x2e, 0x5a, 0x6b, + 0x8f, 0x46, 0x33, 0xc3, 0x31, 0xee, 0xc0, 0xed, 0x94, 0x32, 0x69, 0x84, 0xf8, 0x18, 0x56, 0xda, + 0x94, 0xe3, 0xfb, 0x55, 0x25, 0xf3, 0x18, 0x2d, 0x58, 0x9d, 0x6d, 0x52, 0x76, 0xb6, 0x03, 0xcd, + 0x6d, 0x7e, 0x32, 0x3d, 0xdb, 0xe3, 0x17, 0x71, 0x47, 0x0c, 0xf2, 0xc1, 0xb9, 0x77, 0x29, 0xd7, + 0x07, 0x7f, 0x63, 0xb8, 0x9b, 0xc0, 0xb1, 0x82, 0x09, 0x1f, 0x28, 0x8b, 0x28, 0x42, 0x7a, 0x13, + 0x3e, 0x30, 0xde, 0x07, 0xa6, 0xb7, 0x23, 0xd7, 0x4b, 0x68, 0x09, 0xd3, 0x13, 0x2b, 0xb8, 0x0e, + 0x42, 0x3e, 0x56, 0x97, 0x01, 0x41, 0x30, 0x3d, 0xe9, 0x11, 0xc4, 0x78, 0x07, 0xaa, 0x47, 0xf6, + 0xb5, 0xc9, 0x3f, 0x97, 0x69, 0x2a, 0x6b, 0x50, 0x9c, 0xd8, 0xd7, 0x82, 0x0d, 0x44, 0xce, 0x11, + 0x2c, 0x36, 0xfe, 0x30, 0x0f, 0x0b, 0x84, 0xc9, 0xee, 0xd3, 0x7d, 0x9d, 0x8e, 0x8b, 0xdb, 0x50, + 0x31, 0x4a, 0x0d, 0x34, 0xc7, 0x4b, 0xb3, 0xf3, 0xbc, 0x54, 0x1a, 0xd0, 0xd4, 0x3d, 0x25, 0xca, + 0x8c, 0xed, 0x4e, 0xc7, 0xea, 0x72, 0x92, 0x64, 0xa2, 0x6b, 0x3e, 0xbe, 0x8f, 0x95, 0xb2, 0x00, + 0x93, 0x8e, 0xc6, 0x58, 0x17, 0xa1, 0xd1, 0xa9, 0x23, 0x42, 0xb2, 0x4b, 0x1d, 0x94, 0xaa, 0xf0, + 0x14, 0x55, 0x02, 0x54, 0x52, 0xe1, 0x99, 0x53, 0x6c, 0x4a, 0x2f, 0x57, 0x6c, 0xc8, 0xb2, 0xf6, + 0x02, 0xc5, 0x06, 0x5e, 0x41, 0xb1, 0x79, 0x05, 0x27, 0xdf, 0x6d, 0x28, 0xe1, 0xb9, 0xaf, 0x71, + 0x4f, 0x71, 0xde, 0x0b, 0xee, 0xf9, 0x1d, 0x4d, 0xf4, 0xa7, 0x08, 0x83, 0x3b, 0xf1, 0x36, 0x31, + 0xf9, 0xe7, 0xbf, 0x18, 0xe7, 0xc9, 0x67, 0x50, 0x94, 0x50, 0x41, 0xd0, 0xae, 0x3d, 0x56, 0x57, + 0x3d, 0xe1, 0x6f, 0xb1, 0x6c, 0x78, 0x3f, 0xcd, 0xe7, 0x53, 0xc7, 0xe7, 0x43, 0x75, 0x87, 0x87, + 0x83, 0x7b, 0x54, 0x40, 0xc4, 0x04, 0x85, 0x1a, 0xe2, 0x7a, 0x97, 0xae, 0xcc, 0xe0, 0x2f, 0x3a, + 0xc1, 0x33, 0xf1, 0x68, 0x30, 0x68, 0xe0, 0x65, 0x6f, 0x13, 0xcf, 0x57, 0x87, 0x93, 0xf1, 0xd3, + 0x0c, 0x34, 0xe4, 0xee, 0x8a, 0xca, 0x74, 0x2d, 0xa0, 0x70, 0x93, 0x43, 0xfc, 0xc5, 0x37, 0x72, + 0x18, 0x50, 0x43, 0xe3, 0x47, 0x74, 0x52, 0x91, 0xf1, 0xa6, 0x22, 0x80, 0x3b, 0xf2, 0xb4, 0x7a, + 0x1d, 0x2a, 0x2a, 0x18, 0x77, 0xec, 0x8c, 0xd4, 0xd5, 0xcb, 0x14, 0x8d, 0xbb, 0xef, 0x8c, 0xd4, + 0x41, 0xe7, 0xdb, 0x32, 0x21, 0x2f, 0x83, 0x07, 0x9d, 0x69, 0x87, 0xdc, 0xf8, 0x0f, 0x19, 0x68, + 0x6a, 0x53, 0x91, 0xfb, 0xf6, 0x43, 0xa8, 0x46, 0xb7, 0x2c, 0xf2, 0x48, 0xf2, 0x5a, 0x4b, 0x32, + 0x9a, 0xb8, 0x5a, 0x65, 0x10, 0x41, 0x02, 0x31, 0x98, 0xa1, 0x7d, 0x4d, 0x11, 0xa3, 0xd3, 0xb1, + 0x52, 0x6e, 0x86, 0xf6, 0xf5, 0x0e, 0xe7, 0xbd, 0xe9, 0x58, 0xa8, 0xae, 0x97, 0x9c, 0x3f, 0x8f, + 0x10, 0x48, 0xe6, 0x02, 0x01, 0x93, 0x18, 0x06, 0xd4, 0xc6, 0x9e, 0x1b, 0x9e, 0x47, 0x28, 0x52, + 0xea, 0x44, 0x20, 0xe1, 0x18, 0x7f, 0x96, 0x85, 0x25, 0x32, 0xb1, 0x49, 0xd3, 0xa6, 0x64, 0x5d, + 0x2d, 0x58, 0x20, 0x6b, 0x23, 0x31, 0xaf, 0xdd, 0x5b, 0xa6, 0x7c, 0x66, 0xdf, 0x7e, 0x45, 0xb3, + 0xa0, 0xca, 0xf9, 0xbb, 0x61, 0xf9, 0x73, 0xf3, 0xcb, 0x7f, 0xf3, 0xf2, 0xa6, 0x79, 0xdc, 0x0a, + 0x69, 0x1e, 0xb7, 0x57, 0xf1, 0x73, 0xcd, 0x25, 0xc6, 0x15, 0x25, 0x8e, 0x96, 0x18, 0xf7, 0x3e, + 0xac, 0x25, 0x70, 0x90, 0x5b, 0x3b, 0xa7, 0x0e, 0x57, 0x17, 0x24, 0x2c, 0x6b, 0xd8, 0x3d, 0x55, + 0xb6, 0x59, 0x84, 0x42, 0x30, 0xf0, 0x26, 0xdc, 0x58, 0x85, 0xe5, 0xe4, 0xaa, 0xca, 0x63, 0xe2, + 0x77, 0x33, 0xd0, 0x92, 0xf1, 0x11, 0x8e, 0x7b, 0xb6, 0xeb, 0x04, 0xa1, 0xe7, 0x47, 0xb7, 0x11, + 0xde, 0x05, 0x08, 0x42, 0xdb, 0x97, 0xda, 0xa6, 0xbc, 0x12, 0x00, 0x21, 0xa8, 0x49, 0xde, 0x86, + 0x12, 0x77, 0x87, 0x54, 0x48, 0xd4, 0x50, 0xe4, 0xee, 0x50, 0xe9, 0xa1, 0x73, 0xf2, 0x77, 0x2d, + 0xa9, 0x5e, 0xc8, 0x0c, 0x5d, 0xb1, 0x3a, 0xfc, 0x02, 0x0f, 0xde, 0x7c, 0x94, 0xa1, 0xbb, 0x6f, + 0x5f, 0x61, 0xb4, 0x61, 0x60, 0xfc, 0xd3, 0x2c, 0x2c, 0xc6, 0xe3, 0xa3, 0xf4, 0xfe, 0x17, 0x5f, + 0x54, 0x70, 0x5f, 0x92, 0x83, 0x23, 0xe4, 0x77, 0xcd, 0xf0, 0x58, 0xa2, 0xcd, 0xd9, 0x75, 0x99, + 0x01, 0x15, 0x85, 0xe1, 0x4d, 0x43, 0xed, 0x52, 0xb0, 0x32, 0xa1, 0x1c, 0x4e, 0x43, 0xa1, 0x70, + 0x09, 0xcd, 0xd3, 0x71, 0xa5, 0xca, 0x53, 0xb0, 0xc7, 0x61, 0x17, 0xef, 0x1a, 0x17, 0x60, 0x51, + 0x8d, 0x5e, 0xa4, 0xc0, 0x12, 0xf8, 0x0d, 0x92, 0xb3, 0xe9, 0xcd, 0xa1, 0x8c, 0xad, 0x0b, 0xa1, + 0x74, 0xed, 0x6a, 0x24, 0x84, 0xbe, 0x0e, 0x15, 0x6a, 0x3c, 0xce, 0x83, 0xcc, 0x9b, 0x65, 0xec, + 0x01, 0xcb, 0xa5, 0x11, 0xc8, 0x9b, 0x26, 0x54, 0x5f, 0xa0, 0xae, 0x30, 0xfc, 0xe0, 0x1f, 0x66, + 0xe0, 0x76, 0xca, 0x6b, 0x93, 0xbb, 0x7c, 0x0b, 0x9a, 0xa7, 0x51, 0xa1, 0x5a, 0x5d, 0xda, 0xea, + 0xab, 0x8a, 0xad, 0x26, 0xd7, 0xd4, 0x6c, 0x9c, 0x26, 0x01, 0xb1, 0xd2, 0x45, 0x6f, 0x30, 0x91, + 0xea, 0x8a, 0x4a, 0x17, 0xbd, 0x46, 0xd2, 0x77, 0x8e, 0x60, 0xbd, 0x73, 0x25, 0x38, 0xc6, 0x96, + 0x7e, 0x59, 0xbe, 0x22, 0xa3, 0xa4, 0x81, 0x39, 0xf3, 0x4a, 0x06, 0xe6, 0x21, 0x65, 0xf4, 0x45, + 0x6d, 0xfd, 0x2c, 0x8d, 0xe0, 0x01, 0x2a, 0xea, 0xd0, 0x65, 0xff, 0x2a, 0xdd, 0x76, 0x10, 0x5d, + 0xf2, 0x6f, 0x04, 0xb0, 0xb8, 0x3f, 0x1d, 0x85, 0x4e, 0x7c, 0xef, 0x3f, 0xfb, 0xb6, 0xac, 0x83, + 0xfd, 0xa8, 0x55, 0x4b, 0xed, 0x08, 0xa2, 0x8e, 0x70, 0xb1, 0xc6, 0xa2, 0x21, 0x6b, 0xbe, 0xbf, + 0xc5, 0x71, 0xb2, 0x07, 0xe3, 0x36, 0xac, 0xc5, 0x4f, 0xb4, 0x6c, 0xea, 0xa8, 0xf9, 0x57, 0x19, + 0x0a, 0x6d, 0x4e, 0x7e, 0x83, 0x80, 0x75, 0x60, 0x29, 0x70, 0xdc, 0xb3, 0x11, 0xd7, 0x9b, 0x0f, + 0xe4, 0x22, 0xac, 0x24, 0xc7, 0x26, 0xbf, 0x53, 0x60, 0x36, 0xa9, 0x46, 0xdc, 0x5a, 0xc0, 0x36, + 0x6f, 0x1a, 0x64, 0x4c, 0x16, 0x33, 0xab, 0x31, 0x3f, 0xf8, 0x2e, 0xd4, 0x93, 0x1d, 0xb1, 0xef, + 0xc8, 0x6c, 0xd6, 0x78, 0x54, 0xb9, 0x99, 0xbc, 0xc3, 0x98, 0x20, 0x2a, 0xf1, 0xda, 0x07, 0xc6, + 0x3f, 0xce, 0x40, 0xcb, 0xe4, 0x82, 0x72, 0xb5, 0x51, 0x2a, 0x9a, 0xf9, 0x70, 0xae, 0xd5, 0x9b, + 0xe7, 0xaa, 0x92, 0x64, 0xd5, 0x88, 0xbe, 0x71, 0xe3, 0xcb, 0xd8, 0xbd, 0x35, 0x37, 0xa3, 0xcd, + 0x12, 0x2c, 0x10, 0x8a, 0xb1, 0x06, 0x2b, 0x72, 0x3c, 0x6a, 0x2c, 0xb1, 0xf7, 0x30, 0xd1, 0x63, + 0xc2, 0x7b, 0xb8, 0x0e, 0x2d, 0xba, 0x54, 0x52, 0x9f, 0x84, 0xac, 0xb8, 0x0d, 0x6c, 0xdf, 0x1e, + 0xd8, 0xbe, 0xe7, 0xb9, 0x47, 0xdc, 0x97, 0x81, 0xa2, 0x28, 0x61, 0xa2, 0x73, 0x4d, 0x89, 0xc2, + 0xf4, 0xa4, 0xae, 0x42, 0xf4, 0x5c, 0x15, 0x17, 0x43, 0x4f, 0x86, 0x09, 0x4b, 0x9b, 0xf6, 0x73, + 0xae, 0x5a, 0x52, 0x4b, 0xf4, 0x11, 0x54, 0x26, 0x51, 0xa3, 0x6a, 0xdd, 0x55, 0xca, 0xfb, 0x7c, + 0xb7, 0xa6, 0x8e, 0x6d, 0x3c, 0x81, 0xe5, 0x64, 0x9b, 0x92, 0x75, 0xac, 0x43, 0x69, 0x2c, 0x61, + 0x72, 0x74, 0xd1, 0xb3, 0xf1, 0xdb, 0x25, 0x28, 0x4a, 0x7d, 0x8e, 0x6d, 0x40, 0x7e, 0xa0, 0x62, + 0x93, 0xe2, 0x9b, 0x54, 0x64, 0xa9, 0xfa, 0xbf, 0x85, 0x11, 0x4a, 0x02, 0x8f, 0x7d, 0x04, 0xf5, + 0xa4, 0x57, 0x74, 0x26, 0x9f, 0x36, 0xe9, 0xce, 0xac, 0x0d, 0x66, 0xfc, 0x5f, 0xe5, 0xf8, 0x70, + 0x24, 0x99, 0xa1, 0x74, 0xae, 0x9d, 0x9e, 0x9e, 0x2b, 0xe4, 0xed, 0xe0, 0xdc, 0xb6, 0x9e, 0xbc, + 0xff, 0x81, 0x4c, 0xa8, 0xad, 0x20, 0xb0, 0x77, 0x6e, 0x3f, 0x79, 0xff, 0x83, 0x59, 0x49, 0x5a, + 0xa6, 0xd3, 0x6a, 0x92, 0xf4, 0x32, 0x14, 0xe8, 0xce, 0x3f, 0x0a, 0x32, 0xa1, 0x07, 0xf6, 0x18, + 0x96, 0xa5, 0xda, 0x6a, 0xc9, 0x70, 0x60, 0xe2, 0x82, 0x25, 0xca, 0xc0, 0x92, 0x65, 0x3d, 0x2c, + 0x22, 0xdb, 0xd0, 0x2a, 0x2c, 0x9c, 0xc7, 0x17, 0x38, 0xd6, 0x4c, 0xf9, 0x64, 0xfc, 0x59, 0x01, + 0x2a, 0xda, 0xa2, 0xb0, 0x2a, 0x94, 0xcc, 0x4e, 0xaf, 0x63, 0x7e, 0xd2, 0xd9, 0x6e, 0xdc, 0x62, + 0x0f, 0xe0, 0xad, 0xee, 0xc1, 0xd6, 0xa1, 0x69, 0x76, 0xb6, 0xfa, 0xd6, 0xa1, 0x69, 0xa9, 0xfb, + 0x7c, 0x8e, 0xda, 0x9f, 0xed, 0x77, 0x0e, 0xfa, 0xd6, 0x76, 0xa7, 0xdf, 0xee, 0xee, 0xf5, 0x1a, + 0x19, 0xf6, 0x1a, 0xb4, 0x62, 0x4c, 0x55, 0xdc, 0xde, 0x3f, 0x3c, 0x3e, 0xe8, 0x37, 0xb2, 0xec, + 0x1e, 0xdc, 0xd9, 0xe9, 0x1e, 0xb4, 0xf7, 0xac, 0x18, 0x67, 0x6b, 0xaf, 0xff, 0x89, 0xd5, 0xf9, + 0xd5, 0xa3, 0xae, 0xf9, 0x59, 0x23, 0x97, 0x86, 0x20, 0x94, 0x71, 0xd5, 0x42, 0x9e, 0xdd, 0x86, + 0x15, 0x42, 0xa0, 0x2a, 0x56, 0xff, 0xf0, 0xd0, 0xea, 0x1d, 0x1e, 0x1e, 0x34, 0x0a, 0xac, 0x09, + 0xb5, 0xee, 0xc1, 0x27, 0xed, 0xbd, 0xee, 0xb6, 0x65, 0x76, 0xda, 0x7b, 0xfb, 0x8d, 0x05, 0xb6, + 0x04, 0x8b, 0xb3, 0x78, 0x45, 0xd1, 0x84, 0xc2, 0x3b, 0x3c, 0xe8, 0x1e, 0x1e, 0x58, 0x9f, 0x74, + 0xcc, 0x5e, 0xf7, 0xf0, 0xa0, 0x51, 0x62, 0xab, 0xc0, 0x92, 0x45, 0xbb, 0xfb, 0xed, 0xad, 0x46, + 0x99, 0xad, 0x40, 0x33, 0x09, 0x7f, 0xd6, 0xf9, 0xac, 0x01, 0xac, 0x05, 0xcb, 0x34, 0x30, 0x6b, + 0xb3, 0xb3, 0x77, 0xf8, 0xa9, 0xb5, 0xdf, 0x3d, 0xe8, 0xee, 0x1f, 0xef, 0x37, 0x2a, 0x78, 0xc3, + 0x58, 0xa7, 0x63, 0x75, 0x0f, 0x7a, 0xc7, 0x3b, 0x3b, 0xdd, 0xad, 0x6e, 0xe7, 0xa0, 0xdf, 0xa8, + 0x52, 0xcf, 0x69, 0x13, 0xaf, 0x89, 0x0a, 0x32, 0x67, 0xc0, 0xda, 0xee, 0xf6, 0xda, 0x9b, 0x7b, + 0x9d, 0xed, 0x46, 0x9d, 0xdd, 0x85, 0xdb, 0xfd, 0xce, 0xfe, 0xd1, 0xa1, 0xd9, 0x36, 0x3f, 0x53, + 0x39, 0x05, 0xd6, 0x4e, 0xbb, 0xbb, 0x77, 0x6c, 0x76, 0x1a, 0x8b, 0xec, 0x0d, 0xb8, 0x6b, 0x76, + 0x3e, 0x3e, 0xee, 0x9a, 0x9d, 0x6d, 0xeb, 0xe0, 0x70, 0xbb, 0x63, 0xed, 0x74, 0xda, 0xfd, 0x63, + 0xb3, 0x63, 0xed, 0x77, 0x7b, 0xbd, 0xee, 0xc1, 0xd3, 0x46, 0x83, 0xbd, 0x05, 0xf7, 0x23, 0x94, + 0xa8, 0x81, 0x19, 0xac, 0xa6, 0x98, 0x9f, 0x7a, 0xa5, 0x07, 0x9d, 0x5f, 0xed, 0x5b, 0x47, 0x9d, + 0x8e, 0xd9, 0x60, 0x6c, 0x1d, 0x56, 0xe3, 0xee, 0xa9, 0x03, 0xd9, 0xf7, 0x92, 0x28, 0x3b, 0xea, + 0x98, 0xfb, 0xed, 0x03, 0xf1, 0x82, 0x13, 0x65, 0xcb, 0x62, 0xd8, 0x71, 0xd9, 0xec, 0xb0, 0x57, + 0x18, 0x83, 0xba, 0xf6, 0x56, 0x76, 0xda, 0x66, 0x63, 0x95, 0x2d, 0x42, 0x65, 0xff, 0xe8, 0xc8, + 0xea, 0x77, 0xf7, 0x3b, 0x87, 0xc7, 0xfd, 0xc6, 0x1a, 0x5b, 0x81, 0x46, 0xf7, 0xa0, 0xdf, 0x31, + 0xc5, 0xbb, 0x56, 0x55, 0xff, 0x77, 0x91, 0x2d, 0xc3, 0xa2, 0x1a, 0xa9, 0x82, 0xfe, 0x55, 0x91, + 0xad, 0x01, 0x3b, 0x3e, 0x30, 0x3b, 0xed, 0x6d, 0xb1, 0x70, 0x51, 0xc1, 0xff, 0x29, 0x4a, 0x0f, + 0xc9, 0x4f, 0x73, 0xd1, 0x61, 0x1d, 0x87, 0x1c, 0x24, 0xaf, 0xf3, 0xad, 0x6a, 0xd7, 0xf0, 0xbe, + 0xec, 0xa2, 0x7d, 0x4d, 0xb5, 0xca, 0xcd, 0xa9, 0x56, 0x73, 0xba, 0x7b, 0x4d, 0x97, 0xfd, 0xde, + 0x84, 0xda, 0x98, 0xae, 0xf6, 0x95, 0x57, 0x78, 0x82, 0x8c, 0xbf, 0x21, 0x20, 0xdd, 0xdf, 0x39, + 0x77, 0xd3, 0x7c, 0x61, 0xfe, 0xa6, 0xf9, 0x34, 0xf9, 0x7e, 0x21, 0x4d, 0xbe, 0x7f, 0x08, 0x4d, + 0x62, 0x4d, 0x8e, 0xeb, 0x8c, 0x95, 0xd6, 0x4c, 0x52, 0xe0, 0x22, 0xb2, 0x28, 0x82, 0x2b, 0x75, + 0x42, 0xa9, 0x1c, 0x92, 0x85, 0x14, 0xa5, 0xb6, 0x91, 0xd0, 0x34, 0x88, 0x73, 0x44, 0x9a, 0x46, + 0xd4, 0x83, 0x7d, 0x15, 0xf7, 0x50, 0xd1, 0x7a, 0x20, 0x38, 0xf6, 0xf0, 0x10, 0x9a, 0xfc, 0x2a, + 0xf4, 0x6d, 0xcb, 0x9b, 0xd8, 0x9f, 0x4f, 0xd1, 0x85, 0x6b, 0xa3, 0x0e, 0x5f, 0x35, 0x17, 0xb1, + 0xe0, 0x10, 0xe1, 0xdb, 0x76, 0x68, 0x3f, 0xfc, 0x02, 0x2a, 0xda, 0xb5, 0xcf, 0x6c, 0x0d, 0x96, + 0x3e, 0xed, 0xf6, 0x0f, 0x3a, 0xbd, 0x9e, 0x75, 0x74, 0xbc, 0xf9, 0xac, 0xf3, 0x99, 0xb5, 0xdb, + 0xee, 0xed, 0x36, 0x6e, 0x89, 0x4d, 0x7b, 0xd0, 0xe9, 0xf5, 0x3b, 0xdb, 0x09, 0x78, 0x86, 0xbd, + 0x0e, 0xeb, 0xc7, 0x07, 0xc7, 0xbd, 0xce, 0xb6, 0x95, 0x56, 0x2f, 0x2b, 0xa8, 0x54, 0x96, 0xa7, + 0x54, 0xcf, 0x3d, 0xfc, 0x3e, 0xd4, 0x93, 0x77, 0x91, 0x32, 0x80, 0x85, 0xbd, 0xce, 0xd3, 0xf6, + 0xd6, 0x67, 0x74, 0x07, 0x61, 0xaf, 0xdf, 0xee, 0x77, 0xb7, 0x2c, 0x79, 0xe7, 0xa0, 0xe0, 0x08, + 0x19, 0x56, 0x81, 0x62, 0xfb, 0x60, 0x6b, 0xf7, 0xd0, 0xec, 0x35, 0xb2, 0x0f, 0x3f, 0x82, 0xc6, + 0xac, 0x3f, 0x2a, 0xe1, 0xc0, 0x7b, 0x91, 0xa7, 0xef, 0xe1, 0xbf, 0xcd, 0x01, 0xc4, 0x09, 0x03, + 0x82, 0xd5, 0x6c, 0xb7, 0xfb, 0xed, 0xbd, 0x43, 0x31, 0x0d, 0xf3, 0xb0, 0x2f, 0x38, 0x88, 0xd9, + 0xf9, 0xb8, 0x71, 0x2b, 0xb5, 0xe4, 0xf0, 0xa8, 0xdf, 0xc8, 0x88, 0x15, 0xeb, 0x1e, 0x74, 0xfb, + 0xdd, 0xf6, 0x9e, 0x65, 0x1e, 0x1e, 0x77, 0x0f, 0x9e, 0xd2, 0xe5, 0x6a, 0xc8, 0x65, 0x8f, 0x8f, + 0x76, 0xcc, 0xc3, 0x83, 0xbe, 0xd5, 0xdb, 0x3d, 0xee, 0x6f, 0xe3, 0xd5, 0x6c, 0x5b, 0x66, 0xf7, + 0x88, 0xda, 0xcc, 0xbf, 0x08, 0x41, 0x34, 0x5d, 0x10, 0x6b, 0xfe, 0xf4, 0xb0, 0xd7, 0xeb, 0x1e, + 0x59, 0x1f, 0x1f, 0x77, 0xcc, 0x6e, 0xa7, 0x87, 0x15, 0x17, 0x52, 0xe0, 0x02, 0xbf, 0x28, 0x78, + 0x73, 0x7f, 0xef, 0x13, 0xc9, 0x3c, 0x05, 0x6a, 0x29, 0x09, 0x12, 0x58, 0x65, 0xc1, 0x53, 0x04, + 0xf7, 0x49, 0x69, 0x19, 0x6e, 0x28, 0x13, 0xf5, 0x2a, 0x82, 0xaf, 0xce, 0xbd, 0x0c, 0xac, 0x56, + 0x4d, 0x2f, 0x12, 0xb5, 0x90, 0xe5, 0x46, 0x07, 0xd4, 0xf6, 0xb6, 0x89, 0x15, 0xea, 0x73, 0x50, + 0x81, 0xbb, 0x28, 0x5e, 0x94, 0x60, 0x4f, 0x02, 0xa5, 0xa1, 0x1e, 0x44, 0x49, 0xf3, 0xc9, 0x6f, + 0xe5, 0xa0, 0x4e, 0xc9, 0x5b, 0xf4, 0xd5, 0x2d, 0xee, 0xb3, 0x7d, 0x28, 0xca, 0xcf, 0xb7, 0xb1, + 0x95, 0xe8, 0xde, 0x2b, 0xfd, 0x83, 0x71, 0xeb, 0xab, 0xb3, 0x60, 0x29, 0x8e, 0x2d, 0xfd, 0x9d, + 0x3f, 0xfd, 0x5f, 0xff, 0x24, 0x5b, 0x63, 0x95, 0x47, 0x17, 0xef, 0x3d, 0x3a, 0xe3, 0x6e, 0x20, + 0xda, 0xf8, 0x9b, 0x00, 0xf1, 0x47, 0xc9, 0x58, 0x2b, 0x72, 0x42, 0xcd, 0x7c, 0xb1, 0x6d, 0xfd, + 0x76, 0x4a, 0x89, 0x6c, 0xf7, 0x36, 0xb6, 0xbb, 0x64, 0xd4, 0x45, 0xbb, 0x8e, 0xeb, 0x84, 0xf4, + 0x81, 0xb2, 0x0f, 0x33, 0x0f, 0xd9, 0x10, 0xaa, 0xfa, 0xe7, 0xc2, 0x98, 0x92, 0x94, 0x52, 0x3e, + 0x78, 0xb6, 0x7e, 0x27, 0xb5, 0x4c, 0xc9, 0xa0, 0xd8, 0xc7, 0x8a, 0xd1, 0x10, 0x7d, 0x4c, 0x11, + 0x23, 0xee, 0x65, 0x44, 0x52, 0x79, 0xfc, 0x55, 0x30, 0xf6, 0x9a, 0x26, 0x57, 0xcd, 0x7d, 0x93, + 0x6c, 0xfd, 0xee, 0x0d, 0xa5, 0xb2, 0xaf, 0xbb, 0xd8, 0xd7, 0x9a, 0xc1, 0x44, 0x5f, 0x03, 0xc4, + 0x51, 0xdf, 0x24, 0xfb, 0x30, 0xf3, 0xf0, 0xc9, 0x5f, 0x3e, 0x80, 0x72, 0x14, 0xcc, 0xc9, 0x7e, + 0x03, 0x6a, 0x89, 0xec, 0x3a, 0xa6, 0xa6, 0x91, 0x96, 0x8c, 0xb7, 0xfe, 0x5a, 0x7a, 0xa1, 0xec, + 0xf8, 0x75, 0xec, 0xb8, 0xc5, 0x56, 0x45, 0xc7, 0x32, 0x7b, 0xed, 0x11, 0x66, 0xc3, 0xd2, 0x2d, + 0x62, 0xcf, 0x35, 0xed, 0x83, 0x3a, 0x7b, 0x6d, 0x56, 0x23, 0x48, 0xf4, 0x76, 0xf7, 0x86, 0x52, + 0xd9, 0xdd, 0x6b, 0xd8, 0xdd, 0x2a, 0x5b, 0xd6, 0xbb, 0x53, 0xa1, 0x97, 0x8c, 0xe3, 0xcd, 0x7d, + 0xfa, 0x47, 0xb3, 0xd8, 0xdd, 0xf8, 0x9e, 0xb5, 0x94, 0x8f, 0x69, 0x45, 0x24, 0x32, 0xff, 0x45, + 0x2d, 0xa3, 0x85, 0x5d, 0x31, 0x86, 0xaf, 0x4f, 0xff, 0x66, 0x16, 0x3b, 0x81, 0x8a, 0xf6, 0x9d, + 0x09, 0x76, 0xfb, 0xc6, 0x6f, 0x62, 0xac, 0xaf, 0xa7, 0x15, 0xa5, 0x4d, 0x45, 0x6f, 0xff, 0xd1, + 0x29, 0xe7, 0xec, 0xd7, 0xa0, 0x1c, 0x7d, 0xbd, 0x80, 0xad, 0x69, 0x5f, 0x93, 0xd0, 0xbf, 0xb6, + 0xb0, 0xde, 0x9a, 0x2f, 0x48, 0x23, 0x3e, 0xbd, 0x75, 0x41, 0x7c, 0x9f, 0x42, 0x45, 0xfb, 0x42, + 0x41, 0x34, 0x81, 0xf9, 0xaf, 0x20, 0x44, 0x13, 0x48, 0xf9, 0xa0, 0x81, 0xd1, 0xc4, 0x2e, 0x2a, + 0xac, 0x8c, 0xf4, 0x1d, 0x5e, 0x79, 0x01, 0xdb, 0x83, 0x15, 0xa9, 0x69, 0x9d, 0xf0, 0x2f, 0xf3, + 0x1a, 0x52, 0xbe, 0x53, 0xf6, 0x38, 0xc3, 0x3e, 0x82, 0x92, 0xfa, 0x10, 0x05, 0x5b, 0x4d, 0xff, + 0xa0, 0xc6, 0xfa, 0xda, 0x1c, 0x5c, 0xaa, 0x45, 0x9f, 0x01, 0xc4, 0x9f, 0x43, 0x88, 0x98, 0xc4, + 0xdc, 0xe7, 0x15, 0x22, 0x0a, 0x98, 0xff, 0x76, 0x82, 0xb1, 0x8a, 0x13, 0x6c, 0x30, 0x64, 0x12, + 0x2e, 0xbf, 0x54, 0xd7, 0xab, 0xfe, 0x08, 0x2a, 0xda, 0x17, 0x11, 0xa2, 0xe5, 0x9b, 0xff, 0x9a, + 0x42, 0xb4, 0x7c, 0x29, 0x1f, 0x50, 0x30, 0xd6, 0xb1, 0xf5, 0x65, 0x63, 0x51, 0xb4, 0x2e, 0x44, + 0x2d, 0x29, 0xf2, 0x88, 0x17, 0x74, 0x0e, 0xb5, 0xc4, 0x67, 0x0f, 0xa2, 0x1d, 0x9a, 0xf6, 0x51, + 0x85, 0x68, 0x87, 0xa6, 0x7e, 0x29, 0x41, 0xd1, 0x99, 0xd1, 0x14, 0xfd, 0x5c, 0x20, 0x8a, 0xd6, + 0xd3, 0x0f, 0xa1, 0xa2, 0x7d, 0xc2, 0x20, 0x9a, 0xcb, 0xfc, 0xd7, 0x12, 0xa2, 0xb9, 0xa4, 0x7d, + 0xf1, 0x60, 0x19, 0xfb, 0xa8, 0x1b, 0x48, 0x0a, 0x78, 0x41, 0xa4, 0x68, 0xfb, 0x37, 0xa0, 0x9e, + 0xfc, 0xaa, 0x41, 0xb4, 0xf7, 0x53, 0x3f, 0x8f, 0x10, 0xed, 0xfd, 0x1b, 0x3e, 0x85, 0x20, 0x49, + 0xfa, 0xe1, 0x52, 0xd4, 0xc9, 0xa3, 0x9f, 0xc8, 0xb4, 0x94, 0x2f, 0xd8, 0xc7, 0x82, 0xc1, 0xc9, + 0xfb, 0x49, 0xd9, 0x9a, 0x46, 0xb5, 0xfa, 0x45, 0xa7, 0xd1, 0x7e, 0x99, 0xbb, 0xca, 0x34, 0x49, + 0xcc, 0xd8, 0x38, 0x7b, 0x0a, 0x4b, 0x11, 0x31, 0x47, 0x17, 0x8e, 0x06, 0xd1, 0x1c, 0x52, 0xaf, + 0x35, 0x5d, 0x6f, 0xcc, 0x96, 0x3e, 0xce, 0xd0, 0xf1, 0x87, 0xd7, 0x3c, 0x6a, 0xc7, 0x9f, 0x7e, + 0xe7, 0xa8, 0x76, 0xfc, 0x25, 0x6e, 0x83, 0x9c, 0x3d, 0xfe, 0x42, 0x47, 0xb4, 0xe1, 0xc2, 0xe2, + 0xec, 0xf5, 0x9f, 0x77, 0x6f, 0x4a, 0xfb, 0xa7, 0xe6, 0x5f, 0x7f, 0xf1, 0xad, 0x00, 0x49, 0x56, + 0xa4, 0xb8, 0xe9, 0x23, 0x19, 0x7c, 0xc2, 0x7e, 0x1d, 0xaa, 0xfa, 0x4d, 0xe8, 0x4c, 0xe7, 0x09, + 0xb3, 0x3d, 0xdd, 0x49, 0x2d, 0x4b, 0x52, 0x09, 0xab, 0xea, 0xdd, 0xb0, 0x4f, 0x60, 0x35, 0x5a, + 0x66, 0x3d, 0x6f, 0x3d, 0x60, 0xf7, 0x52, 0xb2, 0xd9, 0x13, 0x8b, 0x7d, 0xfb, 0xc6, 0x74, 0xf7, + 0xc7, 0x19, 0x41, 0x7d, 0xc9, 0x2b, 0x99, 0xe3, 0x93, 0x27, 0xed, 0x26, 0xea, 0xf8, 0xe4, 0x49, + 0xbd, 0xc7, 0x59, 0x51, 0x1f, 0x5b, 0x4a, 0xac, 0x11, 0x85, 0xe5, 0xb2, 0x1f, 0xc2, 0xa2, 0x96, + 0x94, 0xdf, 0xbb, 0x76, 0x07, 0xd1, 0x4e, 0x9a, 0xbf, 0x53, 0x70, 0x3d, 0xcd, 0x36, 0x69, 0xac, + 0x61, 0xfb, 0x4d, 0x23, 0xb1, 0x38, 0x62, 0x17, 0x6d, 0x41, 0x45, 0x4f, 0xf8, 0x7f, 0x41, 0xbb, + 0x6b, 0x5a, 0x91, 0x7e, 0x7d, 0xdd, 0xe3, 0x0c, 0xdb, 0x83, 0xc6, 0xec, 0x65, 0x5a, 0x11, 0x4f, + 0x49, 0xbb, 0x00, 0x6c, 0x7d, 0xa6, 0x30, 0x71, 0x05, 0x17, 0x3b, 0xa2, 0xc4, 0x8e, 0xe8, 0xa3, + 0x5e, 0x9e, 0x3f, 0x7b, 0xaa, 0x27, 0x3f, 0xf6, 0x15, 0xb5, 0x96, 0xf6, 0x99, 0xb7, 0x07, 0x99, + 0xc7, 0x19, 0xf6, 0x3b, 0x19, 0xa8, 0x26, 0xae, 0xa7, 0x49, 0x84, 0xce, 0xcf, 0xcc, 0xb3, 0xa5, + 0x97, 0xe9, 0x13, 0x35, 0x4c, 0x5c, 0xc4, 0xbd, 0x87, 0x3f, 0x48, 0xbc, 0xa4, 0x9f, 0x24, 0x5c, + 0x7b, 0x1b, 0xb3, 0x5f, 0xfd, 0xfa, 0x62, 0x16, 0x41, 0xbf, 0x2a, 0xf2, 0x8b, 0xc7, 0x19, 0xf6, + 0xef, 0x33, 0x50, 0x4f, 0xfa, 0xec, 0xa3, 0xe9, 0xa6, 0x46, 0x07, 0x44, 0xa4, 0x74, 0x83, 0xa3, + 0xff, 0x87, 0x38, 0xca, 0xfe, 0x43, 0x33, 0x31, 0x4a, 0x79, 0x99, 0xf8, 0xcf, 0x37, 0x5a, 0xf6, + 0x21, 0x7d, 0x64, 0x53, 0x85, 0x32, 0xb1, 0xf9, 0x8f, 0x32, 0x46, 0xe4, 0xa7, 0x7f, 0xc2, 0x10, + 0x5f, 0xc2, 0x8f, 0xe8, 0xeb, 0x56, 0x2a, 0x32, 0x46, 0x50, 0xf1, 0xab, 0xd6, 0x37, 0xde, 0xc2, + 0x39, 0xbd, 0x6e, 0xdc, 0x4e, 0xcc, 0x69, 0x56, 0xf0, 0x68, 0xd3, 0xe8, 0xe4, 0x17, 0x08, 0xe3, + 0x93, 0x73, 0xee, 0xab, 0x84, 0x37, 0x0f, 0x72, 0x4c, 0x83, 0x94, 0xe8, 0x89, 0xad, 0xf6, 0x8a, + 0xcd, 0x18, 0x0f, 0x71, 0xac, 0x6f, 0x19, 0xf7, 0x6e, 0x1c, 0xeb, 0x23, 0xf4, 0xbf, 0x8b, 0x11, + 0x1f, 0x01, 0xc4, 0xa1, 0x86, 0x6c, 0x26, 0xe0, 0x2d, 0x62, 0x40, 0xf3, 0xd1, 0x88, 0xc9, 0xfd, + 0xac, 0xe2, 0xe2, 0x44, 0x8b, 0xbf, 0x46, 0xec, 0x34, 0x0a, 0xc5, 0xd3, 0xa5, 0xaf, 0x64, 0x54, + 0x60, 0x42, 0xfa, 0x9a, 0x6d, 0x3f, 0xc1, 0x4c, 0xa3, 0xb8, 0xbb, 0x63, 0xa8, 0xed, 0x79, 0xde, + 0xf3, 0xe9, 0x24, 0x0a, 0x6f, 0x4f, 0x06, 0xc5, 0xec, 0xda, 0xc1, 0xf9, 0xfa, 0xcc, 0x2c, 0x8c, + 0xfb, 0xd8, 0xd4, 0x3a, 0x6b, 0x69, 0x4d, 0x3d, 0xfa, 0x49, 0x1c, 0xdf, 0xf8, 0x05, 0xb3, 0xa1, + 0x19, 0xf1, 0xe8, 0x38, 0x86, 0x30, 0xd9, 0x4c, 0x82, 0x33, 0xcf, 0x76, 0x91, 0x50, 0x13, 0xd4, + 0x68, 0x1f, 0x05, 0xaa, 0xcd, 0xc7, 0x19, 0x76, 0x04, 0xd5, 0x6d, 0x3e, 0xc0, 0x44, 0x7d, 0x0c, + 0x2d, 0x59, 0x4a, 0x84, 0x29, 0x50, 0x4c, 0xca, 0x7a, 0x2d, 0x01, 0x4c, 0x9e, 0x5b, 0x13, 0xfb, + 0xda, 0xe7, 0x9f, 0x3f, 0xfa, 0x89, 0x0c, 0x5a, 0xf9, 0x42, 0x9d, 0x5b, 0x2a, 0xa8, 0x27, 0x71, + 0x6e, 0xcd, 0x44, 0x01, 0x25, 0xce, 0xad, 0xb9, 0x28, 0xa0, 0xc4, 0x52, 0xab, 0xa0, 0x22, 0x36, + 0x82, 0xe6, 0x5c, 0xe0, 0x50, 0x74, 0x64, 0xdd, 0x14, 0x6e, 0xb4, 0x7e, 0xff, 0x66, 0x84, 0x64, + 0x6f, 0x0f, 0x93, 0xbd, 0xf5, 0xa0, 0x46, 0xb7, 0x57, 0x9e, 0x70, 0x4a, 0xd9, 0x9b, 0xb9, 0xef, + 0x46, 0xcf, 0x07, 0x9c, 0x3d, 0x60, 0xb0, 0x2c, 0x29, 0xe1, 0x60, 0xae, 0x1c, 0xfb, 0x35, 0xa8, + 0x3c, 0xe5, 0xa1, 0xca, 0xd1, 0x8b, 0x64, 0xec, 0x99, 0xa4, 0xbd, 0xf5, 0x94, 0x14, 0xbf, 0x24, + 0xcd, 0x60, 0x6b, 0x8f, 0xf8, 0xf0, 0x8c, 0x13, 0x73, 0xb2, 0x9c, 0xe1, 0x17, 0xec, 0x57, 0xb1, + 0xf1, 0x28, 0x35, 0x7a, 0x55, 0x4b, 0xc2, 0xd2, 0x1b, 0x5f, 0x9c, 0x81, 0xa7, 0xb5, 0xec, 0x7a, + 0x43, 0xae, 0xc9, 0x7a, 0x2e, 0x54, 0xb4, 0x2b, 0x14, 0xa2, 0x0d, 0x34, 0x7f, 0x65, 0x46, 0xb4, + 0x81, 0x52, 0x6e, 0x5c, 0x30, 0x1e, 0x60, 0x3f, 0x06, 0xbb, 0x1f, 0xf7, 0x43, 0xb7, 0x2c, 0xc4, + 0x3d, 0x3d, 0xfa, 0x89, 0x3d, 0x0e, 0xbf, 0x60, 0x9f, 0xe2, 0x1d, 0xf1, 0x7a, 0x0e, 0x62, 0xac, + 0x34, 0xcc, 0xa6, 0x2b, 0x46, 0x8b, 0xa5, 0x15, 0x25, 0x15, 0x09, 0xea, 0x0a, 0x25, 0xb9, 0xf7, + 0x01, 0x7a, 0xa1, 0x37, 0xd9, 0xb6, 0xf9, 0xd8, 0x73, 0x63, 0x5e, 0x1b, 0x67, 0xc5, 0xc5, 0xfc, + 0x4b, 0x4b, 0x8d, 0x63, 0x9f, 0x6a, 0x5a, 0x56, 0x22, 0x8d, 0x53, 0x11, 0xd7, 0x8d, 0x89, 0x73, + 0xd1, 0x82, 0xa4, 0x24, 0xcf, 0x3d, 0xce, 0xb0, 0x36, 0x40, 0x1c, 0x39, 0x16, 0xe9, 0x4c, 0x73, + 0x41, 0x69, 0x11, 0xdb, 0x4b, 0x09, 0x33, 0x3b, 0x82, 0x72, 0x1c, 0x72, 0xb3, 0x16, 0xdf, 0x08, + 0x93, 0x08, 0xd0, 0x89, 0x4e, 0xf0, 0xb9, 0x70, 0x17, 0xa3, 0x81, 0x4b, 0x05, 0xac, 0x24, 0x96, + 0xea, 0x94, 0xf3, 0x80, 0x39, 0xb0, 0x44, 0x03, 0x8c, 0xc4, 0x25, 0xcc, 0xe6, 0x8a, 0x3e, 0x05, + 0x30, 0x1f, 0x79, 0x12, 0xed, 0xe6, 0xd4, 0xf8, 0x89, 0x84, 0xe9, 0x47, 0x50, 0x2b, 0x65, 0x92, + 0x09, 0xd6, 0x3c, 0x86, 0xe6, 0x9c, 0x8b, 0x3e, 0xda, 0xd2, 0x37, 0xc5, 0x5c, 0x44, 0x5b, 0xfa, + 0x46, 0xef, 0xbe, 0xb1, 0x82, 0x5d, 0x2e, 0x1a, 0x80, 0xaa, 0xde, 0xa5, 0x13, 0x0e, 0xce, 0x45, + 0x77, 0xbf, 0x97, 0x81, 0xa5, 0x14, 0x27, 0x3c, 0x7b, 0x43, 0x59, 0x0d, 0x6e, 0x74, 0xd0, 0xaf, + 0xa7, 0x3a, 0x6b, 0x8d, 0x1e, 0xf6, 0xb3, 0xcf, 0x9e, 0x25, 0x0e, 0x36, 0xf2, 0x95, 0xca, 0x9d, + 0xf9, 0x42, 0xa1, 0x22, 0x55, 0xa2, 0xf8, 0x1c, 0xd6, 0x68, 0x20, 0xed, 0xd1, 0x68, 0xc6, 0x91, + 0xfc, 0xfa, 0xdc, 0x47, 0xf8, 0x13, 0xce, 0xf1, 0xf5, 0x9b, 0x3f, 0xd2, 0x7f, 0x83, 0x38, 0x4d, + 0x43, 0x65, 0x53, 0x68, 0xcc, 0x3a, 0x68, 0xd9, 0xcd, 0x6d, 0xad, 0xdf, 0x4b, 0xe8, 0xbf, 0x29, + 0x4e, 0xdd, 0xaf, 0x61, 0x67, 0xf7, 0x8c, 0xf5, 0xb4, 0x75, 0x21, 0x95, 0x58, 0xbc, 0x8f, 0xbf, + 0x1d, 0x79, 0x93, 0x67, 0xe6, 0xa9, 0x3a, 0xb8, 0xc9, 0xf7, 0x1d, 0x69, 0xe0, 0xe9, 0xce, 0xe8, + 0xb7, 0xb1, 0xfb, 0xfb, 0xc6, 0x9d, 0xb4, 0xee, 0x7d, 0xaa, 0x42, 0xba, 0xf8, 0xda, 0xec, 0xbe, + 0x56, 0x23, 0xb8, 0x9f, 0xf6, 0xbe, 0x6f, 0xd4, 0x85, 0x66, 0xd6, 0xfa, 0x16, 0xca, 0x76, 0x55, + 0xdd, 0x7b, 0x1c, 0x6d, 0x9f, 0x14, 0x37, 0x75, 0xb4, 0x7d, 0xd2, 0xdc, 0xcd, 0x49, 0xb9, 0x46, + 0x39, 0x9a, 0x3f, 0xcc, 0x3c, 0xdc, 0x7c, 0xe7, 0x87, 0x5f, 0x3b, 0x73, 0xc2, 0xf3, 0xe9, 0xc9, + 0xc6, 0xc0, 0x1b, 0x3f, 0x1a, 0x29, 0x6b, 0xa3, 0x4c, 0x79, 0x7e, 0x34, 0x72, 0x87, 0x8f, 0xb0, + 0xd9, 0x93, 0x85, 0x89, 0xef, 0x85, 0xde, 0xb7, 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x38, + 0x4e, 0xcb, 0x28, 0x67, 0x84, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 59522ccce7..536eb46a2d 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2096,8 +2096,12 @@ message PendingChannelsResponse { /// Channels pending opening repeated PendingOpenChannel pending_open_channels = 2; - /// Channels pending closing - repeated ClosedChannel pending_closing_channels = 3; + /* + Deprecated: Channels pending closing previously contained cooperatively + closed channels with a single confirmation. These channels are now + considered closed from the time we see them on chain. + */ + repeated ClosedChannel pending_closing_channels = 3 [deprecated = true]; /// Channels pending force closing repeated ForceClosedChannel pending_force_closing_channels = 4; diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 65eb685abd..b6c9f5bb49 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -3939,7 +3939,7 @@ "items": { "$ref": "#/definitions/PendingChannelsResponseClosedChannel" }, - "title": "/ Channels pending closing" + "description": "Deprecated: Channels pending closing previously contained cooperatively\nclosed channels with a single confirmation. These channels are now\nconsidered closed from the time we see them on chain." }, "pending_force_closing_channels": { "type": "array", diff --git a/rpcserver.go b/rpcserver.go index 1f039a7515..721b4fad4f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2725,22 +2725,15 @@ func (r *rpcServer) PendingChannels(ctx context.Context, switch pendingClose.CloseType { - // If the channel was closed cooperatively, then we'll only - // need to tack on the closing txid. - // TODO(halseth): remove. After recent changes, a coop closed - // channel should never be in the "pending close" state. - // Keeping for now to let someone that upgraded in the middle - // of a close let their closing tx confirm. + // A coop closed channel should never be in the "pending close" + // state. If a node upgraded from an older lnd version in the + // middle of a their channel confirming, it will be in this + // state. We log a warning that the channel will not be included + // in the now deprecated pending close channels field. case channeldb.CooperativeClose: - resp.PendingClosingChannels = append( - resp.PendingClosingChannels, - &lnrpc.PendingChannelsResponse_ClosedChannel{ - Channel: channel, - ClosingTxid: closeTXID, - }, - ) - - resp.TotalLimboBalance += channel.LocalBalance + rpcsLog.Warn("channel %v cooperatively closed and "+ + "in pending close state", + pendingClose.ChanPoint) // If the channel was force closed, then we'll need to query // the utxoNursery for additional information. From 97da7b344498d3f5ec8b4760018d2d2eaf3f634b Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 13 Mar 2020 16:41:08 +0800 Subject: [PATCH 300/562] multi: support config bitcoind fee estimate mode --- chainregistry.go | 12 +++++++---- config.go | 37 ++++++++++++++++++++++++++++++---- docs/INSTALL.md | 4 ++++ lnwallet/chainfee/estimator.go | 18 ++++++++++++++--- sample-lnd.conf | 6 ++++++ 5 files changed, 66 insertions(+), 11 deletions(-) diff --git a/chainregistry.go b/chainregistry.go index 97a0e52453..b5df1cf1d2 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -343,7 +343,8 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, HTTPPostMode: true, } if cfg.Bitcoin.Active && !cfg.Bitcoin.RegTest { - ltndLog.Infof("Initializing bitcoind backed fee estimator") + ltndLog.Infof("Initializing bitcoind backed fee estimator in "+ + "%s mode", bitcoindMode.EstimateMode) // Finally, we'll re-initialize the fee estimator, as // if we're using bitcoind as a backend, then we can @@ -351,7 +352,8 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, // coded value. fallBackFeeRate := chainfee.SatPerKVByte(25 * 1000) cc.feeEstimator, err = chainfee.NewBitcoindEstimator( - *rpcConfig, fallBackFeeRate.FeePerKWeight(), + *rpcConfig, bitcoindMode.EstimateMode, + fallBackFeeRate.FeePerKWeight(), ) if err != nil { return nil, err @@ -360,7 +362,8 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, return nil, err } } else if cfg.Litecoin.Active && !cfg.Litecoin.RegTest { - ltndLog.Infof("Initializing litecoind backed fee estimator") + ltndLog.Infof("Initializing litecoind backed fee estimator in "+ + "%s mode", bitcoindMode.EstimateMode) // Finally, we'll re-initialize the fee estimator, as // if we're using litecoind as a backend, then we can @@ -368,7 +371,8 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, // coded value. fallBackFeeRate := chainfee.SatPerKVByte(25 * 1000) cc.feeEstimator, err = chainfee.NewBitcoindEstimator( - *rpcConfig, fallBackFeeRate.FeePerKWeight(), + *rpcConfig, bitcoindMode.EstimateMode, + fallBackFeeRate.FeePerKWeight(), ) if err != nil { return nil, err diff --git a/config.go b/config.go index 8b9d3e0bea..040f68e29a 100644 --- a/config.go +++ b/config.go @@ -152,6 +152,11 @@ var ( defaultTorSOCKS = net.JoinHostPort("localhost", strconv.Itoa(defaultTorSOCKSPort)) defaultTorDNS = net.JoinHostPort(defaultTorDNSHost, strconv.Itoa(defaultTorDNSPort)) defaultTorControl = net.JoinHostPort("localhost", strconv.Itoa(defaultTorControlPort)) + + // bitcoindEsimateModes defines all the legal values for bitcoind's + // estimatesmartfee RPC call. + defaultBitcoindEstimateMode = "CONSERVATIVE" + bitcoindEstimateModes = [2]string{"ECONOMICAL", defaultBitcoindEstimateMode} ) type chainConfig struct { @@ -200,6 +205,7 @@ type bitcoindConfig struct { RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"` ZMQPubRawBlock string `long:"zmqpubrawblock" description:"The address listening for ZMQ connections to deliver raw block notifications"` ZMQPubRawTx string `long:"zmqpubrawtx" description:"The address listening for ZMQ connections to deliver raw transaction notifications"` + EstimateMode string `long:"estimatemode" description:"The fee estimate mode. Must be either ECONOMICAL or CONSERVATIVE."` } type autoPilotConfig struct { @@ -384,8 +390,9 @@ func loadConfig() (*config, error) { RPCCert: defaultBtcdRPCCertFile, }, BitcoindMode: &bitcoindConfig{ - Dir: defaultBitcoindDir, - RPCHost: defaultRPCHost, + Dir: defaultBitcoindDir, + RPCHost: defaultRPCHost, + EstimateMode: defaultBitcoindEstimateMode, }, Litecoin: &chainConfig{ MinHTLCIn: defaultLitecoinMinHTLCInMSat, @@ -401,8 +408,9 @@ func loadConfig() (*config, error) { RPCCert: defaultLtcdRPCCertFile, }, LitecoindMode: &bitcoindConfig{ - Dir: defaultLitecoindDir, - RPCHost: defaultRPCHost, + Dir: defaultLitecoindDir, + RPCHost: defaultRPCHost, + EstimateMode: defaultBitcoindEstimateMode, }, UnsafeDisconnect: true, MaxPendingChannels: DefaultMaxPendingChannels, @@ -1211,6 +1219,15 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode, } } + // Ensure that if the estimate mode is set, that it is a legal + // value. + if conf.EstimateMode != "" { + err := checkEstimateMode(conf.EstimateMode) + if err != nil { + return err + } + } + // If all of RPCUser, RPCPass, ZMQBlockHost, and ZMQTxHost are // set, we assume those parameters are good to use. if conf.RPCUser != "" && conf.RPCPass != "" && @@ -1448,6 +1465,18 @@ func checkZMQOptions(zmqBlockHost, zmqTxHost string) error { return nil } +// checkEstimateMode ensures that the provided estimate mode is legal. +func checkEstimateMode(estimateMode string) error { + for _, mode := range bitcoindEstimateModes { + if estimateMode == mode { + return nil + } + } + + return fmt.Errorf("estimatemode must be one of the following: %v", + bitcoindEstimateModes[:]) +} + // normalizeNetwork returns the common name of a network type used to create // file paths. This allows differently versioned networks to use the same path. func normalizeNetwork(network string) string { diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 066fafe779..2a24926cde 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -208,6 +208,7 @@ bitcoind: --bitcoind.rpcpass= Password for RPC connections --bitcoind.zmqpubrawblock= The address listening for ZMQ connections to deliver raw block notifications --bitcoind.zmqpubrawtx= The address listening for ZMQ connections to deliver raw transaction notifications + --bitcoind.estimatemode= The fee estimate mode. Must be either "ECONOMICAL" or "CONSERVATIVE". (default: CONSERVATIVE) ``` ## Using btcd @@ -367,6 +368,9 @@ lnd --bitcoin.active --bitcoin.testnet --debuglevel=debug --bitcoin.node=bitcoin the default `bitcoind` settings, having more than one instance of `lnd`, or `lnd` plus any application that consumes the RPC could cause `lnd` to miss crucial updates from the backend. +- The default fee estimate mode in `bitcoind` is CONSERVATIVE. You can set + `bitcoind.estimatemode=ECONOMICAL` to change it into ECONOMICAL. Futhermore, + if you start `bitcoind` in `regtest`, this configuration won't take any effect. # Creating a wallet diff --git a/lnwallet/chainfee/estimator.go b/lnwallet/chainfee/estimator.go index 5f89f12245..98c74f6130 100644 --- a/lnwallet/chainfee/estimator.go +++ b/lnwallet/chainfee/estimator.go @@ -286,6 +286,11 @@ type BitcoindEstimator struct { // through the network. minFeePerKW SatPerKWeight + // feeMode is the estimate_mode to use when calling "estimatesmartfee". + // It can be either "ECONOMICAL" or "CONSERVATIVE", and it's default + // to "CONSERVATIVE". + feeMode string + bitcoindConn *rpcclient.Client } @@ -294,7 +299,7 @@ type BitcoindEstimator struct { // bitcoind node, and also a fall back fee rate. The fallback fee rate is used // in the occasion that the estimator has insufficient data, or returns zero // for a fee estimate. -func NewBitcoindEstimator(rpcConfig rpcclient.ConnConfig, +func NewBitcoindEstimator(rpcConfig rpcclient.ConnConfig, feeMode string, fallBackFeeRate SatPerKWeight) (*BitcoindEstimator, error) { rpcConfig.DisableConnectOnNew = true @@ -309,6 +314,7 @@ func NewBitcoindEstimator(rpcConfig rpcclient.ConnConfig, return &BitcoindEstimator{ fallbackFeePerKW: fallBackFeeRate, bitcoindConn: chainConn, + feeMode: feeMode, }, nil } @@ -403,9 +409,15 @@ func (b *BitcoindEstimator) fetchEstimate(confTarget uint32) (SatPerKWeight, err if err != nil { return 0, err } - // TODO: Allow selection of economical/conservative modifiers. + + // The mode must be either ECONOMICAL or CONSERVATIVE. + mode, err := json.Marshal(b.feeMode) + if err != nil { + return 0, err + } + resp, err := b.bitcoindConn.RawRequest( - "estimatesmartfee", []json.RawMessage{target}, + "estimatesmartfee", []json.RawMessage{target, mode}, ) if err != nil { return 0, err diff --git a/sample-lnd.conf b/sample-lnd.conf index ee3ce7cf0f..422def451f 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -230,6 +230,9 @@ bitcoin.node=btcd ; bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332 ; bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333 +; Fee estimate mode for bitcoind. It must be either "ECONOMICAL" or "CONSERVATIVE". +; If unset, the default value is "CONSERVATIVE". +; bitcoind.estimatemode=CONSERVATIVE [neutrino] @@ -311,6 +314,9 @@ litecoin.node=ltcd ; litecoind.zmqpubrawblock=tcp://127.0.0.1:28332 ; litecoind.zmqpubrawtx=tcp://127.0.0.1:28333 +; Fee estimate mode for litecoind. It must be either "ECONOMICAL" or "CONSERVATIVE". +; If unset, the default value is "CONSERVATIVE". +; litecoind.estimatemode=CONSERVATIVE [autopilot] From f757bf48bdbfd4c115aa896d85210cf83351bb2e Mon Sep 17 00:00:00 2001 From: nsa Date: Mon, 9 Mar 2020 13:36:06 -0400 Subject: [PATCH 301/562] channeldb: use RemoteCommitment in NextLocalHtlcIndex This commit changes the fallback in NextLocalHtlcIndex to RemoteCommitment since the LocalHtlcIndex field lags behind on the LocalCommitment. Without this bug fix, open circuits would get prematurely trimmed, resulting in more erroneous logs. A test case is included to check that the fix works. --- channeldb/channel.go | 6 +- htlcswitch/link_test.go | 155 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+), 3 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 27f8887c69..7189e56af7 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -2171,7 +2171,7 @@ func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg) error { // NextLocalHtlcIndex returns the next unallocated local htlc index. To ensure // this always returns the next index that has been not been allocated, this // will first try to examine any pending commitments, before falling back to the -// last locked-in local commitment. +// last locked-in remote commitment. func (c *OpenChannel) NextLocalHtlcIndex() (uint64, error) { // First, load the most recent commit diff that we initiated for the // remote party. If no pending commit is found, this is not treated as @@ -2187,8 +2187,8 @@ func (c *OpenChannel) NextLocalHtlcIndex() (uint64, error) { return pendingRemoteCommit.Commitment.LocalHtlcIndex, nil } - // Otherwise, fallback to using the local htlc index of our commitment. - return c.LocalCommitment.LocalHtlcIndex, nil + // Otherwise, fallback to using the local htlc index of their commitment. + return c.RemoteCommitment.LocalHtlcIndex, nil } // LoadFwdPkgs scans the forwarding log for any packages that haven't been diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 0906141ac1..d7f95df162 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -3158,6 +3158,161 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { assertLinkBandwidth(t, alice.link, aliceStartingBandwidth) } +// TestChannelLinkTrimCircuitsRemoteCommit checks that the switch and link +// don't trim circuits if the ADD is locked in on the remote commitment but +// not on our local commitment. +func TestChannelLinkTrimCircuitsRemoteCommit(t *testing.T) { + t.Parallel() + + const ( + chanAmt = btcutil.SatoshiPerBitcoin * 5 + numHtlcs = 2 + ) + + // We'll start by creating a new link with our chanAmt (5 BTC). + aliceLink, bobChan, batchTicker, start, cleanUp, restore, err := + newSingleLinkTestHarness(chanAmt, 0) + if err != nil { + t.Fatalf("unable to create link: %v", err) + } + + if err := start(); err != nil { + t.Fatalf("unable to start test harness: %v", err) + } + defer cleanUp() + + alice := newPersistentLinkHarness( + t, aliceLink, batchTicker, restore, + ) + + // Compute the static fees that will be used to determine the + // correctness of Alice's bandwidth when forwarding HTLCs. + estimator := chainfee.NewStaticEstimator(6000, 0) + feePerKw, err := estimator.EstimateFeePerKW(1) + if err != nil { + t.Fatalf("unable to query fee estimator: %v", err) + } + + defaultCommitFee := alice.channel.StateSnapshot().CommitFee + htlcFee := lnwire.NewMSatFromSatoshis( + feePerKw.FeeForWeight(input.HTLCWeight), + ) + + // The starting bandwidth of the channel should be exactly the amount + // that we created the channel between her and Bob, minus the commitment + // fee and fee of adding an HTLC. + expectedBandwidth := lnwire.NewMSatFromSatoshis( + chanAmt-defaultCommitFee, + ) - htlcFee + assertLinkBandwidth(t, alice.link, expectedBandwidth) + + // Capture Alice's starting bandwidth to perform later, relative + // bandwidth assertions. + aliceStartingBandwidth := alice.link.Bandwidth() + + // Next, we'll create an HTLC worth 1 BTC that will be used as a dummy + // message for the test. + var mockBlob [lnwire.OnionPacketSize]byte + htlcAmt := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin) + _, htlc, _, err := generatePayment(htlcAmt, htlcAmt, 5, mockBlob) + if err != nil { + t.Fatalf("unable to create payment: %v", err) + } + + // Create `numHtlc` htlcPackets and payment circuits that will be used + // to drive the test. All of the packets will use the same dummy HTLC. + addPkts, circuits := genAddsAndCircuits(numHtlcs, htlc) + + // To begin the test, start by committing the circuits for our first two + // HTLCs. + fwdActions := alice.commitCircuits(circuits) + + // Both of these circuits should have successfully added, as this is the + // first attempt to send them. + if len(fwdActions.Adds) != numHtlcs { + t.Fatalf("expected %d circuits to be added", numHtlcs) + } + alice.assertNumPendingNumOpenCircuits(2, 0) + + // Since both were committed successfully, we will now deliver them to + // Alice's link. + for _, addPkt := range addPkts { + if err := alice.link.HandleSwitchPacket(addPkt); err != nil { + t.Fatalf("unable to handle switch packet: %v", err) + } + } + + // Wait until Alice's link has sent both HTLCs via the peer. + alice.checkSent(addPkts) + + // Pass both of the htlcs to Bob. + for i, addPkt := range addPkts { + pkt, ok := addPkt.htlc.(*lnwire.UpdateAddHTLC) + if !ok { + t.Fatalf("unable to add packet") + } + + pkt.ID = uint64(i) + + _, err := bobChan.ReceiveHTLC(pkt) + if err != nil { + t.Fatalf("unable to receive htlc: %v", err) + } + } + + // The resulting bandwidth should reflect that Alice is paying both + // htlc amounts, in addition to both htlc fees. + assertLinkBandwidth(t, alice.link, + aliceStartingBandwidth-numHtlcs*(htlcAmt+htlcFee), + ) + + // Now, initiate a state transition by Alice so that the pending HTLCs + // are locked in. + alice.trySignNextCommitment() + alice.assertNumPendingNumOpenCircuits(2, 2) + + select { + case aliceMsg := <-alice.msgs: + // Pass the commitment signature to Bob. + sig, ok := aliceMsg.(*lnwire.CommitSig) + if !ok { + t.Fatalf("alice did not send commitment signature") + } + + err := bobChan.ReceiveNewCommitment(sig.CommitSig, sig.HtlcSigs) + if err != nil { + t.Fatalf("unable to receive new commitment: %v", err) + } + case <-time.After(time.Second): + } + + // Next, revoke Bob's current commitment and send it to Alice so that we + // can test that Alice's circuits aren't trimmed. + rev, _, err := bobChan.RevokeCurrentCommitment() + if err != nil { + t.Fatalf("unable to revoke current commitment: %v", err) + } + + _, _, _, _, err = alice.channel.ReceiveRevocation(rev) + if err != nil { + t.Fatalf("unable to receive revocation: %v", err) + } + + // Restart Alice's link, which simulates a disconnection with the remote + // peer. + cleanUp = alice.restart(false) + defer cleanUp() + + alice.assertNumPendingNumOpenCircuits(2, 2) + + // Restart the link + switch and check that the number of open circuits + // doesn't change. + cleanUp = alice.restart(true) + defer cleanUp() + + alice.assertNumPendingNumOpenCircuits(2, 2) +} + // TestChannelLinkBandwidthChanReserve checks that the bandwidth available // on the channel link reflects the channel reserve that must be kept // at all times. From 4fe174ba4e0ea200f826c3e5ae6ccfedb7a49b72 Mon Sep 17 00:00:00 2001 From: nsa Date: Mon, 9 Mar 2020 13:36:33 -0400 Subject: [PATCH 302/562] htlcswitch: switch ackDownStreamPackets order with contract update call This commit modifies updateCommitTx to error with ErrLinkShuttingDown when we try to send a ContractUpdate on the htlcUpdates chan and the link has closed the quit chan. It also changes the order of the call to ackDownStreamPackets and contract update call for consistency since the packets should be acknowledged before the link goes down. --- htlcswitch/link.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 7c834827d7..cac199b695 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -2060,6 +2060,10 @@ func (l *channelLink) updateCommitTx() error { return err } + if err := l.ackDownStreamPackets(); err != nil { + return err + } + // The remote party now has a new pending commitment, so we'll update // the contract court to be aware of this new set (the prior old remote // pending). @@ -2069,11 +2073,7 @@ func (l *channelLink) updateCommitTx() error { Htlcs: pendingHTLCs, }: case <-l.quit: - return nil - } - - if err := l.ackDownStreamPackets(); err != nil { - return err + return ErrLinkShuttingDown } commitSig := &lnwire.CommitSig{ From 8c0c53eac3bb2f640407dfebe6d86743f4f9dcd2 Mon Sep 17 00:00:00 2001 From: nsa Date: Mon, 9 Mar 2020 13:37:08 -0400 Subject: [PATCH 303/562] htlcswitch: only error in closeCircuit if the htlc was failed This commit changes the switch to only log an error if update_fail_htlc comes in and closeCircuit returns ErrUnknownCircuit. Rationale being that only settles should hit this code path, anything else is a result of a link flap and should be treated as an error. --- htlcswitch/switch.go | 29 ++++++++++++++++++++++------- htlcswitch/switch_test.go | 4 ++-- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 9d03b1b7b4..52d05be8b4 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -1164,6 +1164,12 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { return err } + // closeCircuit returns a nil circuit when a settle packet returns an + // ErrUnknownCircuit error upon the inner call to CloseCircuit. + if circuit == nil { + return nil + } + fail, isFail := htlc.(*lnwire.UpdateFailHTLC) if isFail && !packet.hasSource { switch { @@ -1394,19 +1400,28 @@ func (s *Switch) closeCircuit(pkt *htlcPacket) (*PaymentCircuit, error) { // Failed to close circuit because it does not exist. This is likely // because the circuit was already successfully closed. case ErrUnknownCircuit: - err := fmt.Errorf("Unable to find target channel "+ - "for HTLC settle/fail: channel ID = %s, "+ - "HTLC ID = %d", pkt.outgoingChanID, - pkt.outgoingHTLCID) - log.Error(err) - if pkt.destRef != nil { // Add this SettleFailRef to the set of pending settle/fail entries // awaiting acknowledgement. s.pendingSettleFails = append(s.pendingSettleFails, *pkt.destRef) } - return nil, err + // If this is a settle, we will not log an error message as settles + // are expected to hit the ErrUnknownCircuit case. The only way fails + // can hit this case if the link restarts after having just sent a fail + // to the switch. + _, isSettle := pkt.htlc.(*lnwire.UpdateFulfillHTLC) + if !isSettle { + err := fmt.Errorf("unable to find target channel "+ + "for HTLC fail: channel ID = %s, "+ + "HTLC ID = %d", pkt.outgoingChanID, + pkt.outgoingHTLCID) + log.Error(err) + + return nil, err + } + + return nil, nil // Unexpected error. default: diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index 9cfed11774..bcd98dcf87 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -761,8 +761,8 @@ func TestSwitchForwardSettleAfterFullAdd(t *testing.T) { } // Send the settle packet again, which should fail. - if err := s2.forward(settle); err == nil { - t.Fatalf("expected failure when sending duplicate settle " + + if err := s2.forward(settle); err != nil { + t.Fatalf("expected success when sending duplicate settle " + "with no pending circuit") } } From 9bf117a0f2af90d3bf9829c5a87a4bb44be4b13c Mon Sep 17 00:00:00 2001 From: Craig Hammell Date: Thu, 26 Mar 2020 02:09:09 -0700 Subject: [PATCH 304/562] docker: fix wrong text in README --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 78e0319a58..b2b736d89c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -23,7 +23,7 @@ environment for testing as one doesn't need to wait tens of minutes for blocks to arrive in order to test channel related functionality. Additionally, it's possible to spin up an arbitrary number of `lnd` instances within containers to create a mini development cluster. All state is saved between instances using a -shared value. +shared volume. Current workflow is big because we recreate the whole network by ourselves, next versions will use the started `btcd` bitcoin node in `testnet` and From 863966bac939e483f2f00015add97ea777ccdc3b Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 12 Mar 2020 10:11:08 +0100 Subject: [PATCH 305/562] lntest/itest: fix scope bug Fixes a subtle bug where the outer scope predErr was hidden when the return value of findForceClosedChannel was stored in a newly defined variable with the same name. --- lntest/itest/lnd_test.go | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index c13bfa475d..b0e8b0f743 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -3223,52 +3223,47 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, // Now that the commitment has been confirmed, the channel should be // marked as force closed. - err = wait.Predicate(func() bool { + err = wait.NoError(func() error { ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) pendingChanResp, err := alice.PendingChannels( ctxt, pendingChansRequest, ) if err != nil { - predErr = fmt.Errorf("unable to query for pending "+ + return fmt.Errorf("unable to query for pending "+ "channels: %v", err) - return false } - predErr = checkNumForceClosedChannels(pendingChanResp, 1) - if predErr != nil { - return false + err = checkNumForceClosedChannels(pendingChanResp, 1) + if err != nil { + return err } - forceClose, predErr := findForceClosedChannel( - pendingChanResp, &op, - ) - if predErr != nil { - return false + forceClose, err := findForceClosedChannel(pendingChanResp, &op) + if err != nil { + return err } // Now that the channel has been force closed, it should now // have the height and number of blocks to confirm populated. - predErr = checkCommitmentMaturity( + err = checkCommitmentMaturity( forceClose, commCsvMaturityHeight, int32(defaultCSV), ) - if predErr != nil { - return false + if err != nil { + return err } // None of our outputs have been swept, so they should all be in // limbo. if forceClose.LimboBalance == 0 { - predErr = errors.New("all funds should still be in " + + return errors.New("all funds should still be in " + "limbo") - return false } if forceClose.RecoveredBalance != 0 { - predErr = errors.New("no funds should yet be shown " + + return errors.New("no funds should yet be shown " + "as recovered") - return false } - return true + return nil }, 15*time.Second) if err != nil { t.Fatalf(predErr.Error()) From 8b7bde7200a42cbed58bcb604ff787498c38476a Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 16 Mar 2020 12:28:39 +0100 Subject: [PATCH 306/562] cnct: log txid for force close --- contractcourt/channel_arbitrator.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 46aab0d022..f4e0d96a32 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -842,8 +842,9 @@ func (c *ChannelArbitrator) stateStep( // With the close transaction in hand, broadcast the // transaction to the network, thereby entering the post // channel resolution state. - log.Infof("Broadcasting force close transaction, "+ - "ChannelPoint(%v): %v", c.cfg.ChanPoint, + log.Infof("Broadcasting force close transaction %v, "+ + "ChannelPoint(%v): %v", closeTx.TxHash(), + c.cfg.ChanPoint, newLogClosure(func() string { return spew.Sdump(closeTx) })) From b3afa0c9ed990b3b687e8abd93eabb7eea153b80 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 19 Mar 2020 16:51:32 +0100 Subject: [PATCH 307/562] sweep: log sweep tx id and full list of inputs To facilitate debugging. --- sweep/txgenerator.go | 38 +++++++++++++++----------------------- sweep/txgenerator_test.go | 15 ++++++++++----- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/sweep/txgenerator.go b/sweep/txgenerator.go index 229ecf3eb4..1e47dad217 100644 --- a/sweep/txgenerator.go +++ b/sweep/txgenerator.go @@ -138,10 +138,6 @@ func createSweepTx(inputs []input.Input, outputPkScript []byte, txFee := feePerKw.FeeForWeight(txWeight) - log.Infof("Creating sweep transaction for %v inputs (%s) "+ - "using %v sat/kw, tx_fee=%v", len(inputs), - inputTypeSummary(inputs), int64(feePerKw), txFee) - // Sum up the total value contained in the inputs. var totalSum btcutil.Amount for _, o := range inputs { @@ -211,6 +207,10 @@ func createSweepTx(inputs []input.Input, outputPkScript []byte, } } + log.Infof("Creating sweep transaction %v for %v inputs (%s) "+ + "using %v sat/kw, tx_fee=%v", sweepTx.TxHash(), len(inputs), + inputTypeSummary(inputs), int64(feePerKw), txFee) + return sweepTx, nil } @@ -254,27 +254,19 @@ func getWeightEstimate(inputs []input.Input) ([]input.Input, int64) { // inputSummary returns a string containing a human readable summary about the // witness types of a list of inputs. func inputTypeSummary(inputs []input.Input) string { - // Count each input by the string representation of its witness type. - // We also keep track of the keys so we can later sort by them to get - // a stable output. - counts := make(map[string]uint32) - keys := make([]string, 0, len(inputs)) - for _, i := range inputs { - key := i.WitnessType().String() - _, ok := counts[key] - if !ok { - counts[key] = 0 - keys = append(keys, key) - } - counts[key]++ - } - sort.Strings(keys) + // Sort inputs by witness type. + sortedInputs := make([]input.Input, len(inputs)) + copy(sortedInputs, inputs) + sort.Slice(sortedInputs, func(i, j int) bool { + return sortedInputs[i].WitnessType().String() < + sortedInputs[j].WitnessType().String() + }) - // Return a nice string representation of the counts by comma joining a - // slice. var parts []string - for _, witnessType := range keys { - part := fmt.Sprintf("%d %s", counts[witnessType], witnessType) + for _, i := range sortedInputs { + part := fmt.Sprintf("%v (%v)", + *i.OutPoint(), i.WitnessType()) + parts = append(parts, part) } return strings.Join(parts, ", ") diff --git a/sweep/txgenerator_test.go b/sweep/txgenerator_test.go index 726347ec84..91641e5e59 100644 --- a/sweep/txgenerator_test.go +++ b/sweep/txgenerator_test.go @@ -3,6 +3,7 @@ package sweep import ( "testing" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" ) @@ -15,9 +16,10 @@ var ( input.WitnessKeyHash, } expectedWeight = int64(1462) - expectedSummary = "1 CommitmentTimeLock, 1 " + - "HtlcAcceptedSuccessSecondLevel, 1 HtlcOfferedRemoteTimeout, " + - "1 WitnessKeyHash" + expectedSummary = "0000000000000000000000000000000000000000000000000000000000000000:10 (CommitmentTimeLock), " + + "0000000000000000000000000000000000000000000000000000000000000001:11 (HtlcAcceptedSuccessSecondLevel), " + + "0000000000000000000000000000000000000000000000000000000000000002:12 (HtlcOfferedRemoteTimeout), " + + "0000000000000000000000000000000000000000000000000000000000000003:13 (WitnessKeyHash)" ) // TestWeightEstimate tests that the estimated weight and number of CSVs/CLTVs @@ -27,9 +29,12 @@ func TestWeightEstimate(t *testing.T) { t.Parallel() var inputs []input.Input - for _, witnessType := range witnessTypes { + for i, witnessType := range witnessTypes { inputs = append(inputs, input.NewBaseInput( - &wire.OutPoint{}, witnessType, + &wire.OutPoint{ + Hash: chainhash.Hash{byte(i)}, + Index: uint32(i) + 10, + }, witnessType, &input.SignDescriptor{}, 0, )) } From 0e8eb406258d67a8b686e48c1409329a3b05885a Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 19 Mar 2020 11:01:42 +0100 Subject: [PATCH 308/562] lntest/itest: add mempool tx utility functions --- lntest/itest/lnd_test.go | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index b0e8b0f743..2700cda1b7 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -6850,6 +6850,27 @@ func waitForNTxsInMempool(miner *rpcclient.Client, n int, } } +// getNTxsFromMempool polls until finding the desired number of transactions in +// the provided miner's mempool and returns the full transactions to the caller. +func getNTxsFromMempool(miner *rpcclient.Client, n int, + timeout time.Duration) ([]*wire.MsgTx, error) { + + txids, err := waitForNTxsInMempool(miner, n, timeout) + if err != nil { + return nil, err + } + + var txes []*wire.MsgTx + for _, txid := range txids { + tx, err := miner.GetRawTransaction(txid) + if err != nil { + return nil, err + } + txes = append(txes, tx.MsgTx()) + } + return txes, nil +} + // testFailingChannel tests that we will fail the channel by force closing ii // in the case where a counterparty tries to settle an HTLC with the wrong // preimage. @@ -10568,7 +10589,16 @@ func assertNumActiveHtlcs(nodes []*lntest.HarnessNode, numHtlcs int) error { } func assertSpendingTxInMempool(t *harnessTest, miner *rpcclient.Client, - timeout time.Duration, chanPoint wire.OutPoint) { + timeout time.Duration, chanPoint wire.OutPoint) chainhash.Hash { + + tx := getSpendingTxInMempool(t, miner, timeout, chanPoint) + return tx.TxHash() +} + +// getSpendingTxInMempool waits for a transaction spending the given outpoint to +// appear in the mempool and returns that tx in full. +func getSpendingTxInMempool(t *harnessTest, miner *rpcclient.Client, + timeout time.Duration, chanPoint wire.OutPoint) *wire.MsgTx { breakTimeout := time.After(timeout) ticker := time.NewTicker(50 * time.Millisecond) @@ -10594,9 +10624,10 @@ func assertSpendingTxInMempool(t *harnessTest, miner *rpcclient.Client, t.Fatalf("unable to fetch tx: %v", err) } - for _, txIn := range tx.MsgTx().TxIn { + msgTx := tx.MsgTx() + for _, txIn := range msgTx.TxIn { if txIn.PreviousOutPoint == chanPoint { - return + return msgTx } } } From 7dbb936791e67651d7469030af9bf1073a9b1b34 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 27 Mar 2020 07:55:13 +0100 Subject: [PATCH 309/562] lntest/itest: use helper functions in calcStaticFee --- lntest/itest/lnd_test.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 2700cda1b7..f271fb13dc 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -43,6 +43,7 @@ import ( "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing" ) @@ -607,13 +608,13 @@ func shutdownAndAssert(net *lntest.NetworkHarness, t *harnessTest, // TODO(bvu): Refactor when dynamic fee estimation is added. // TODO(conner) remove code duplication func calcStaticFee(numHTLCs int) btcutil.Amount { - const ( - commitWeight = btcutil.Amount(724) - htlcWeight = 172 - feePerKw = btcutil.Amount(50 * 1000 / 4) + const htlcWeight = input.HTLCWeight + var ( + feePerKw = chainfee.SatPerKVByte(50000).FeePerKWeight() + commitWeight = input.CommitWeight ) - return feePerKw * (commitWeight + - btcutil.Amount(htlcWeight*numHTLCs)) / 1000 + + return feePerKw.FeeForWeight(int64(commitWeight + htlcWeight*numHTLCs)) } // completePaymentRequests sends payments from a lightning node to complete all From e269e3f91ba30afb80f76eaf786cc09ea479375b Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 4 Mar 2020 13:21:28 +0100 Subject: [PATCH 310/562] itest: calcStaticFee based on commit type --- lntest/itest/lnd_test.go | 108 +++++++++++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 21 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index f271fb13dc..17ac4bceac 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -60,6 +60,7 @@ const ( channelOpenTimeout = lntest.ChannelOpenTimeout channelCloseTimeout = lntest.ChannelCloseTimeout itestLndBinary = "../../lnd-itest" + anchorSize = 330 ) // harnessTest wraps a regular testing.T providing enhanced error detection @@ -601,22 +602,6 @@ func shutdownAndAssert(net *lntest.NetworkHarness, t *harnessTest, } } -// calcStaticFee calculates appropriate fees for commitment transactions. This -// function provides a simple way to allow test balance assertions to take fee -// calculations into account. -// -// TODO(bvu): Refactor when dynamic fee estimation is added. -// TODO(conner) remove code duplication -func calcStaticFee(numHTLCs int) btcutil.Amount { - const htlcWeight = input.HTLCWeight - var ( - feePerKw = chainfee.SatPerKVByte(50000).FeePerKWeight() - commitWeight = input.CommitWeight - ) - - return feePerKw.FeeForWeight(int64(commitWeight + htlcWeight*numHTLCs)) -} - // completePaymentRequests sends payments from a lightning node to complete all // payment requests. If the awaitResponse parameter is true, this function // does not return until all payments successfully complete without errors. @@ -999,6 +984,66 @@ func (c commitType) Args() []string { return nil } +// calcStaticFee calculates appropriate fees for commitment transactions. This +// function provides a simple way to allow test balance assertions to take fee +// calculations into account. +func (c commitType) calcStaticFee(numHTLCs int) btcutil.Amount { + const htlcWeight = input.HTLCWeight + var ( + feePerKw = chainfee.SatPerKVByte(50000).FeePerKWeight() + commitWeight = input.CommitWeight + anchors = btcutil.Amount(0) + ) + + // The anchor commitment type is slightly heavier, and we must also add + // the value of the two anchors to the resulting fee the initiator + // pays. + if c == commitTypeAnchors { + commitWeight = input.AnchorCommitWeight + anchors = 2 * anchorSize + } + + return feePerKw.FeeForWeight(int64(commitWeight+htlcWeight*numHTLCs)) + + anchors +} + +// channelCommitType retrieves the active channel commitment type for the given +// chan point. +func channelCommitType(node *lntest.HarnessNode, + chanPoint *lnrpc.ChannelPoint) (commitType, error) { + + ctxb := context.Background() + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + + req := &lnrpc.ListChannelsRequest{} + channels, err := node.ListChannels(ctxt, req) + if err != nil { + return 0, fmt.Errorf("listchannels failed: %v", err) + } + + for _, c := range channels.Channels { + if c.ChannelPoint == txStr(chanPoint) { + switch c.CommitmentType { + + // If the anchor output size is non-zero, we are + // dealing with the anchor type. + case lnrpc.CommitmentType_ANCHORS: + return commitTypeAnchors, nil + + // StaticRemoteKey means it is tweakless, + case lnrpc.CommitmentType_STATIC_REMOTE_KEY: + return commitTypeTweakless, nil + + // Otherwise legacy. + default: + return commitTypeLegacy, nil + } + } + } + + return 0, fmt.Errorf("channel point %v not found", chanPoint) +} + // basicChannelFundingTest is a sub-test of the main testBasicChannelFunding // test. Given two nodes: Alice and Bob, it'll assert proper channel creation, // then return a function closure that should be called to assert proper @@ -1039,6 +1084,12 @@ func basicChannelFundingTest(t *harnessTest, net *lntest.NetworkHarness, "channel: %v", err) } + cType, err := channelCommitType(alice, chanPoint) + if err != nil { + return nil, nil, nil, fmt.Errorf("unable to get channel "+ + "type: %v", err) + } + // With the channel open, ensure that the amount specified above has // properly been pushed to Bob. balReq := &lnrpc.ChannelBalanceRequest{} @@ -1055,7 +1106,7 @@ func basicChannelFundingTest(t *harnessTest, net *lntest.NetworkHarness, "balance: %v", err) } - expBalanceAlice := chanAmt - pushAmt - calcStaticFee(0) + expBalanceAlice := chanAmt - pushAmt - cType.calcStaticFee(0) aliceBalance := btcutil.Amount(aliceBal.Balance) if aliceBalance != expBalanceAlice { return nil, nil, nil, fmt.Errorf("alice's balance is "+ @@ -1276,6 +1327,11 @@ func testUnconfirmedChannelFunding(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("error while waiting for channel open: %v", err) } + cType, err := channelCommitType(net.Alice, chanPoint) + if err != nil { + t.Fatalf("unable to get channel type: %v", err) + } + // With the channel open, we'll check the balances on each side of the // channel as a sanity check to ensure things worked out as intended. balReq := &lnrpc.ChannelBalanceRequest{} @@ -1289,9 +1345,9 @@ func testUnconfirmedChannelFunding(net *lntest.NetworkHarness, t *harnessTest) { if err != nil { t.Fatalf("unable to get alice's balance: %v", err) } - if carolBal.Balance != int64(chanAmt-pushAmt-calcStaticFee(0)) { + if carolBal.Balance != int64(chanAmt-pushAmt-cType.calcStaticFee(0)) { t.Fatalf("carol's balance is incorrect: expected %v got %v", - chanAmt-pushAmt-calcStaticFee(0), carolBal) + chanAmt-pushAmt-cType.calcStaticFee(0), carolBal) } if aliceBal.Balance != int64(pushAmt) { t.Fatalf("alice's balance is incorrect: expected %v got %v", @@ -2709,9 +2765,14 @@ func testChannelBalance(net *lntest.NetworkHarness, t *harnessTest) { "timeout: %v", err) } + cType, err := channelCommitType(net.Alice, chanPoint) + if err != nil { + t.Fatalf("unable to get channel type: %v", err) + } + // As this is a single funder channel, Alice's balance should be // exactly 0.5 BTC since now state transitions have taken place yet. - checkChannelBalance(net.Alice, amount-calcStaticFee(0)) + checkChannelBalance(net.Alice, amount-cType.calcStaticFee(0)) // Ensure Bob currently has no available balance within the channel. checkChannelBalance(net.Bob, 0) @@ -9173,7 +9234,12 @@ func testHtlcErrorPropagation(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("channel not seen by alice before timeout: %v", err) } - commitFee := calcStaticFee(0) + cType, err := channelCommitType(net.Alice, chanPointAlice) + if err != nil { + t.Fatalf("unable to get channel type: %v", err) + } + + commitFee := cType.calcStaticFee(0) assertBaseBalance := func() { balReq := &lnrpc.ChannelBalanceRequest{} ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) From 714166eeb0a71a597b914db1bccca3c9fccd4bd3 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 24 Mar 2020 10:18:30 +0100 Subject: [PATCH 311/562] itest: enable anchor type for basic funding flow Co-authored-by: Johan T. Halseth --- lntest/itest/lnd_test.go | 68 +++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 17ac4bceac..790eff5f56 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -1156,6 +1156,7 @@ func testBasicChannelFunding(net *lntest.NetworkHarness, t *harnessTest) { allTypes := []commitType{ commitTypeLegacy, commitTypeTweakless, + commitTypeAnchors, } test: @@ -1208,27 +1209,58 @@ test: t.Fatalf("failed funding flow: %v", err) } - carolTweakless := carolCommitType == commitTypeTweakless + // Both nodes should report the same commitment + // type. + chansCommitType := carolChannel.CommitmentType + if daveChannel.CommitmentType != chansCommitType { + t.Fatalf("commit types don't match, "+ + "carol got %v, dave got %v", + carolChannel.CommitmentType, + daveChannel.CommitmentType, + ) + } + + // Now check that the commitment type reported + // by both nodes is what we expect. It will be + // the minimum of the two nodes' preference, in + // the order Legacy, Tweakless, Anchors. + expType := carolCommitType + + switch daveCommitType { + + // Dave supports anchors, type will be what + // Carol supports. + case commitTypeAnchors: + + // Dave only supports tweakless, channel will + // be downgraded to this type if Carol supports + // anchors. + case commitTypeTweakless: + if expType == commitTypeAnchors { + expType = commitTypeTweakless + } + + // Dave only supoprts legacy type, channel will + // be downgraded to this type. + case commitTypeLegacy: + expType = commitTypeLegacy - daveTweakless := daveCommitType == commitTypeTweakless + default: + t.Fatalf("invalid commit type %v", + daveCommitType) + } - tweaklessSignalled := carolTweakless && daveTweakless - tweaklessChans := (carolChannel.StaticRemoteKey && - daveChannel.StaticRemoteKey) + // Check that the signalled type matches what we + // expect. switch { - // If both sides signalled a tweakless channel, and the - // resulting channel doesn't reflect this, then this - // is a failed case. - case tweaklessSignalled && !tweaklessChans: - t.Fatalf("expected tweakless channnel, got " + - "non-tweaked channel") - - // If both sides didn't signal a tweakless - // channel, and the resulting channel is - // tweakless, and this is also a failed case. - case !tweaklessSignalled && tweaklessChans: - t.Fatalf("expected non-tweaked channel, got " + - "tweakless channel") + case expType == commitTypeAnchors && chansCommitType == lnrpc.CommitmentType_ANCHORS: + case expType == commitTypeTweakless && chansCommitType == lnrpc.CommitmentType_STATIC_REMOTE_KEY: + case expType == commitTypeLegacy && chansCommitType == lnrpc.CommitmentType_LEGACY: + + default: + t.Fatalf("expected nodes to signal "+ + "commit type %v, instead got "+ + "%v", expType, chansCommitType) } // As we've concluded this sub-test case we'll From 23c81949cc261335b4ee85a2aba183d4386cccf0 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 4 Mar 2020 13:21:29 +0100 Subject: [PATCH 312/562] itest: enable anchor type for force close test Co-authored-by: Johan T. Halseth --- lntest/itest/lnd_test.go | 51 +++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 790eff5f56..c36e8a1395 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -3081,6 +3081,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { // outputs can be swept. commitTypes := []commitType{ commitTypeLegacy, + commitTypeAnchors, } for _, channelType := range commitTypes { @@ -3120,7 +3121,19 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { err) } - channelForceClosureTest(net, ht, alice, carol) + // Also give Carol some coins to allow her to sweep her + // anchor. + err = net.SendCoins( + ctxt, btcutil.SatoshiPerBitcoin, carol, + ) + if err != nil { + t.Fatalf("unable to send coins to Alice: %v", + err) + } + + channelForceClosureTest( + net, ht, alice, carol, channelType, + ) }) if !success { return @@ -3129,7 +3142,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) { } func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, - alice, carol *lntest.HarnessNode) { + alice, carol *lntest.HarnessNode, channelType commitType) { ctxb := context.Background() @@ -3305,8 +3318,16 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, } // Mine a block which should confirm the commitment transaction - // broadcast as a result of the force closure. - _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + // broadcast as a result of the force closure. If there are anchors, we + // also expect the anchor sweep tx to be in the mempool. + expectedTxes := 1 + if channelType == commitTypeAnchors { + expectedTxes = 2 + } + + _, err = waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { t.Fatalf("failed to find commitment in miner mempool: %v", err) } @@ -3347,12 +3368,17 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, } // None of our outputs have been swept, so they should all be in - // limbo. + // limbo. For anchors, we expect the anchor amount to be + // recovered. if forceClose.LimboBalance == 0 { return errors.New("all funds should still be in " + "limbo") } - if forceClose.RecoveredBalance != 0 { + expectedRecoveredBalance := int64(0) + if channelType == commitTypeAnchors { + expectedRecoveredBalance = anchorSize + } + if forceClose.RecoveredBalance != expectedRecoveredBalance { return errors.New("no funds should yet be shown " + "as recovered") } @@ -3372,8 +3398,11 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, } // Carol's sweep tx should be in the mempool already, as her output is - // not timelocked. - _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + // not timelocked. If there are anchors, we also expect Carol's anchor + // sweep now. + _, err = waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { t.Fatalf("failed to find Carol's sweep in miner mempool: %v", err) @@ -3435,7 +3464,11 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, return errors.New("all funds should still be in " + "limbo") } - if forceClose.RecoveredBalance != 0 { + expectedRecoveredBalance := int64(0) + if channelType == commitTypeAnchors { + expectedRecoveredBalance = anchorSize + } + if forceClose.RecoveredBalance != expectedRecoveredBalance { return errors.New("no funds should yet be shown " + "as recovered") } From 8628a989a67e714ba2e427b2776296df89f7b0f0 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 4 Mar 2020 13:21:29 +0100 Subject: [PATCH 313/562] itest: enable anchor commitment for multi-hop test These tests exercise the different ways of sweeping a commitment, so we'll cover the modified scripts used for anchor commitments and spending the anchor itself by both parties. Co-authored-by: Johan T. Halseth --- ...d_multi-hop_htlc_local_chain_claim_test.go | 89 ++++++++++--------- .../lnd_multi-hop_htlc_local_timeout_test.go | 62 ++++++++++--- ...ulti-hop_htlc_receiver_chain_claim_test.go | 65 ++++++-------- ..._multi-hop_htlc_remote_chain_claim_test.go | 88 +++++++++--------- ..._force_close_on_chain_htlc_timeout_test.go | 21 ++++- ..._force_close_on_chain_htlc_timeout_test.go | 30 +++++-- lntest/itest/lnd_multi-hop_test.go | 49 ++++++++-- lntest/itest/lnd_test.go | 26 ++++-- 8 files changed, 265 insertions(+), 165 deletions(-) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 37634a28b1..16ac398763 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -96,11 +96,18 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, // At this point, Bob decides that he wants to exit the channel // immediately, so he force closes his commitment transaction. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - bobForceClose := closeChannelAndAssert(ctxt, t, net, bob, - aliceChanPoint, true) + bobForceClose := closeChannelAndAssertType(ctxt, t, net, bob, + aliceChanPoint, c == commitTypeAnchors, true) - // Alice will sweep her output immediately. - _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + // Alice will sweep her commitment output immediately. If there are + // anchors, Alice will also sweep hers. + expectedTxes := 1 + if c == commitTypeAnchors { + expectedTxes = 2 + } + _, err = waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { t.Fatalf("unable to find alice's sweep tx in miner mempool: %v", err) @@ -135,8 +142,11 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, t.Fatalf("unable to generate blocks") } - // Carol's commitment transaction should now be in the mempool. - txids, err := waitForNTxsInMempool(net.Miner.Node, 1, minerMempoolTimeout) + // Carol's commitment transaction should now be in the mempool. If there + // is an anchor, Carol will sweep that too. + _, err = waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { t.Fatalf("transactions not found in mempool: %v", err) } @@ -149,53 +159,47 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, Index: bobChanPoint.OutputIndex, } - // The tx should be spending from the funding transaction, - commitHash := txids[0] - tx1, err := net.Miner.Node.GetRawTransaction(commitHash) - if err != nil { - t.Fatalf("unable to get txn: %v", err) - } - if tx1.MsgTx().TxIn[0].PreviousOutPoint != carolFundingPoint { - t.Fatalf("commit transaction not spending fundingtx: %v", - spew.Sdump(tx1)) - } + // Look up the closing transaction. It should be spending from the + // funding transaction, + closingTx := getSpendingTxInMempool( + t, net.Miner.Node, minerMempoolTimeout, carolFundingPoint, + ) + closingTxid := closingTx.TxHash() - // Mine a block that should confirm the commit tx. - block := mineBlocks(t, net, 1, 1)[0] - if len(block.Transactions) != 2 { - t.Fatalf("expected 2 transactions in block, got %v", - len(block.Transactions)) + // Mine a block that should confirm the commit tx, the anchor if present + // and the coinbase. + block := mineBlocks(t, net, 1, expectedTxes)[0] + if len(block.Transactions) != expectedTxes+1 { + t.Fatalf("expected %v transactions in block, got %v", + expectedTxes+1, len(block.Transactions)) } - assertTxInBlock(t, block, commitHash) + assertTxInBlock(t, block, &closingTxid) // Restart bob again. if err := restartBob(); err != nil { t.Fatalf("unable to restart bob: %v", err) } - // After the force close transacion is mined, Carol should broadcast - // her second level HTLC transacion. Bob will broadcast a sweep tx to - // sweep his output in the channel with Carol. He can do this - // immediately, as the output is not timelocked since Carol was the one - // force closing. - commitSpends, err := waitForNTxsInMempool(net.Miner.Node, 2, - minerMempoolTimeout) + // After the force close transacion is mined, Carol should broadcast her + // second level HTLC transacion. Bob will broadcast a sweep tx to sweep + // his output in the channel with Carol. He can do this immediately, as + // the output is not timelocked since Carol was the one force closing. + // If there are anchors on the commitment, Bob will also sweep his + // anchor. + expectedTxes = 2 + if c == commitTypeAnchors { + expectedTxes = 3 + } + txes, err := getNTxsFromMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { t.Fatalf("transactions not found in mempool: %v", err) } // Both Carol's second level transaction and Bob's sweep should be // spending from the commitment transaction. - for _, txid := range commitSpends { - tx, err := net.Miner.Node.GetRawTransaction(txid) - if err != nil { - t.Fatalf("unable to get txn: %v", err) - } - - if tx.MsgTx().TxIn[0].PreviousOutPoint.Hash != *commitHash { - t.Fatalf("tx did not spend from commitment tx") - } - } + assertAllTxesSpendFrom(t, txes, closingTxid) // At this point we suspend Alice to make sure she'll handle the // on-chain settle after a restart. @@ -205,14 +209,11 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, } // Mine a block to confirm the two transactions (+ the coinbase). - block = mineBlocks(t, net, 1, 2)[0] - if len(block.Transactions) != 3 { + block = mineBlocks(t, net, 1, expectedTxes)[0] + if len(block.Transactions) != expectedTxes+1 { t.Fatalf("expected 3 transactions in block, got %v", len(block.Transactions)) } - for _, txid := range commitSpends { - assertTxInBlock(t, block, txid) - } // Keep track of the second level tx maturity. carolSecondLevelCSV := uint32(defaultCSV) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go index 98b66bda0a..1a7feed46d 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go @@ -7,6 +7,7 @@ import ( "fmt" "time" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" @@ -106,24 +107,33 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest, t.Fatalf("unable to generate blocks: %v", err) } - // Bob's force close transaction should now be found in the mempool. + // Bob's force close transaction should now be found in the mempool. If + // there are anchors, we also expect Bob's anchor sweep. + expectedTxes := 1 + if c == commitTypeAnchors { + expectedTxes = 2 + } + bobFundingTxid, err := lnd.GetChanPointFundingTxid(bobChanPoint) if err != nil { t.Fatalf("unable to get txid: %v", err) } - closeTxid, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + _, err = waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { t.Fatalf("unable to find closing txid: %v", err) } - assertSpendingTxInMempool( + closeTx := getSpendingTxInMempool( t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{ Hash: *bobFundingTxid, Index: bobChanPoint.OutputIndex, }, ) + closeTxid := closeTx.TxHash() // Mine a block to confirm the closing transaction. - mineBlocks(t, net, 1, 1) + mineBlocks(t, net, 1, expectedTxes) // At this point, Bob should have canceled backwards the dust HTLC // that we sent earlier. This means Alice should now only have a single @@ -143,20 +153,42 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest, // With the closing transaction confirmed, we should expect Bob's HTLC // timeout transaction to be broadcast due to the expiry being reached. - htlcTimeout, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + // If there are anchors, we also expect Carol's anchor sweep now. + txes, err := getNTxsFromMempool(net.Miner.Node, expectedTxes, minerMempoolTimeout) if err != nil { t.Fatalf("unable to find bob's htlc timeout tx: %v", err) } + // Lookup the timeout transaction that is expected to spend from the + // closing tx. We distinguish it from a possibly anchor sweep by value. + var htlcTimeout *chainhash.Hash + for _, tx := range txes { + prevOp := tx.TxIn[0].PreviousOutPoint + if prevOp.Hash != closeTxid { + t.Fatalf("tx not spending from closing tx") + } + + // Assume that the timeout tx doesn't spend an output of exactly + // the size of the anchor. + if closeTx.TxOut[prevOp.Index].Value != anchorSize { + hash := tx.TxHash() + htlcTimeout = &hash + } + } + if htlcTimeout == nil { + t.Fatalf("htlc timeout tx not found in mempool") + } + // We'll mine the remaining blocks in order to generate the sweep // transaction of Bob's commitment output. - mineBlocks(t, net, defaultCSV, 1) - assertSpendingTxInMempool( - t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{ - Hash: *closeTxid, - Index: 1, - }, - ) + mineBlocks(t, net, defaultCSV, expectedTxes) + + // Check that the sweep spends from the mined commitment. + txes, err = getNTxsFromMempool(net.Miner.Node, 1, minerMempoolTimeout) + if err != nil { + t.Fatalf("sweep not found: %v", err) + } + assertAllTxesSpendFrom(t, txes, closeTxid) // Bob's pending channel report should show that he has a commitment // output awaiting sweeping, and also that there's an outgoing HTLC @@ -248,6 +280,10 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest, t.Fatalf(predErr.Error()) } + // Coop close channel, expect no anchors. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, false) + closeChannelAndAssertType( + ctxt, t, net, alice, aliceChanPoint, false, + false, + ) } diff --git a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go index e11b2ed7fa..d7335311e1 100644 --- a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go @@ -7,7 +7,6 @@ import ( "fmt" "time" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd" @@ -126,8 +125,15 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest, } // At this point, Carol should broadcast her active commitment - // transaction in order to go to the chain and sweep her HTLC. - txids, err := waitForNTxsInMempool(net.Miner.Node, 1, minerMempoolTimeout) + // transaction in order to go to the chain and sweep her HTLC. If there + // are anchors, Carol also sweeps hers. + expectedTxes := 1 + if c == commitTypeAnchors { + expectedTxes = 2 + } + txes, err := getNTxsFromMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { t.Fatalf("expected transaction not found in mempool: %v", err) } @@ -144,20 +150,13 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest, // The commitment transaction should be spending from the funding // transaction. - commitHash := txids[0] - tx, err := net.Miner.Node.GetRawTransaction(commitHash) - if err != nil { - t.Fatalf("unable to get txn: %v", err) - } - commitTx := tx.MsgTx() - - if commitTx.TxIn[0].PreviousOutPoint != carolFundingPoint { - t.Fatalf("commit transaction not spending from expected "+ - "outpoint: %v", spew.Sdump(commitTx)) - } + closingTx := getSpendingTxInMempool( + t, net.Miner.Node, minerMempoolTimeout, carolFundingPoint, + ) + closingTxid := closingTx.TxHash() // Confirm the commitment. - mineBlocks(t, net, 1, 1) + mineBlocks(t, net, 1, expectedTxes) // Restart bob again. if err := restartBob(); err != nil { @@ -167,30 +166,21 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest, // After the force close transaction is mined, Carol should broadcast // her second level HTLC transaction. Bob will broadcast a sweep tx to // sweep his output in the channel with Carol. When Bob notices Carol's - // second level transaction in the mempool, he will extract the - // preimage and settle the HTLC back off-chain. - secondLevelHashes, err := waitForNTxsInMempool(net.Miner.Node, 2, - minerMempoolTimeout) + // second level transaction in the mempool, he will extract the preimage + // and settle the HTLC back off-chain. Bob will also sweep his anchor, + // if present. + expectedTxes = 2 + if c == commitTypeAnchors { + expectedTxes = 3 + } + txes, err = getNTxsFromMempool(net.Miner.Node, + expectedTxes, minerMempoolTimeout) if err != nil { t.Fatalf("transactions not found in mempool: %v", err) } - // Carol's second level transaction should be spending from - // the commitment transaction. - var secondLevelHash *chainhash.Hash - for _, txid := range secondLevelHashes { - tx, err := net.Miner.Node.GetRawTransaction(txid) - if err != nil { - t.Fatalf("unable to get txn: %v", err) - } - - if tx.MsgTx().TxIn[0].PreviousOutPoint.Hash == *commitHash { - secondLevelHash = txid - } - } - if secondLevelHash == nil { - t.Fatalf("Carol's second level tx not found") - } + // All transactions should be spending from the commitment transaction. + assertAllTxesSpendFrom(t, txes, closingTxid) // We'll now mine an additional block which should confirm both the // second layer transactions. @@ -314,5 +304,8 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest, // We'll close out the channel between Alice and Bob, then shutdown // carol to conclude the test. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, false) + closeChannelAndAssertType( + ctxt, t, net, alice, aliceChanPoint, + false, false, + ) } diff --git a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go index 257b7b9703..c73a066bf3 100644 --- a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go @@ -97,8 +97,8 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest // immediately force close the channel by broadcast her commitment // transaction. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - aliceForceClose := closeChannelAndAssert(ctxt, t, net, alice, - aliceChanPoint, true) + aliceForceClose := closeChannelAndAssertType(ctxt, t, net, alice, + aliceChanPoint, c == commitTypeAnchors, true) // Wait for the channel to be marked pending force close. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) @@ -114,8 +114,13 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest t.Fatalf("unable to generate blocks: %v", err) } - // Alice should now sweep her funds. - _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + // Alice should now sweep her funds. If there are anchors, Alice should + // also sweep hers. + expectedTxes := 1 + if c == commitTypeAnchors { + expectedTxes = 2 + } + _, err = waitForNTxsInMempool(net.Miner.Node, expectedTxes, minerMempoolTimeout) if err != nil { t.Fatalf("unable to find sweeping tx in mempool: %v", err) } @@ -149,10 +154,13 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest t.Fatalf("unable to generate blocks") } - // Carol's commitment transaction should now be in the mempool. - txids, err := waitForNTxsInMempool(net.Miner.Node, 1, minerMempoolTimeout) + // Carol's commitment transaction should now be in the mempool. If there + // are anchors, Carol also sweeps her anchor. + _, err = waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { - t.Fatalf("transactions not found in mempool: %v", err) + t.Fatalf("unable to find carol's txes: %v", err) } bobFundingTxid, err := lnd.GetChanPointFundingTxid(bobChanPoint) if err != nil { @@ -163,63 +171,51 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest Index: bobChanPoint.OutputIndex, } - // The transaction should be spending from the funding transaction - commitHash := txids[0] - tx1, err := net.Miner.Node.GetRawTransaction(commitHash) - if err != nil { - t.Fatalf("unable to get txn: %v", err) - } - if tx1.MsgTx().TxIn[0].PreviousOutPoint != carolFundingPoint { - t.Fatalf("commit transaction not spending fundingtx: %v", - spew.Sdump(tx1)) - } + // The closing transaction should be spending from the funding + // transaction. + closingTx := getSpendingTxInMempool( + t, net.Miner.Node, minerMempoolTimeout, carolFundingPoint, + ) + closingTxid := closingTx.TxHash() - // Mine a block, which should contain the commitment. - block := mineBlocks(t, net, 1, 1)[0] - if len(block.Transactions) != 2 { - t.Fatalf("expected 2 transactions in block, got %v", - len(block.Transactions)) + // Mine a block, which should contain: the commitment, possibly an + // anchor sweep and the coinbase tx. + block := mineBlocks(t, net, 1, expectedTxes)[0] + if len(block.Transactions) != expectedTxes+1 { + t.Fatalf("expected %v transactions in block, got %v", + expectedTxes, len(block.Transactions)) } - assertTxInBlock(t, block, commitHash) + assertTxInBlock(t, block, &closingTxid) // Restart bob again. if err := restartBob(); err != nil { t.Fatalf("unable to restart bob: %v", err) } - // After the force close transacion is mined, Carol should broadcast - // her second level HTLC transacion. Bob will broadcast a sweep tx to - // sweep his output in the channel with Carol. He can do this - // immediately, as the output is not timelocked since Carol was the one - // force closing. - commitSpends, err := waitForNTxsInMempool(net.Miner.Node, 2, + // After the force close transacion is mined, Carol should broadcast her + // second level HTLC transacion. Bob will broadcast a sweep tx to sweep + // his output in the channel with Carol. He can do this immediately, as + // the output is not timelocked since Carol was the one force closing. + // If there are anchors, Bob should also sweep his. + expectedTxes = 2 + if c == commitTypeAnchors { + expectedTxes = 3 + } + txes, err := getNTxsFromMempool(net.Miner.Node, expectedTxes, minerMempoolTimeout) if err != nil { t.Fatalf("transactions not found in mempool: %v", err) } - // Both Carol's second level transaction and Bob's sweep should be - // spending from the commitment transaction. - for _, txid := range commitSpends { - tx, err := net.Miner.Node.GetRawTransaction(txid) - if err != nil { - t.Fatalf("unable to get txn: %v", err) - } - - if tx.MsgTx().TxIn[0].PreviousOutPoint.Hash != *commitHash { - t.Fatalf("tx did not spend from commitment tx") - } - } + // All transactions should be pending from the commitment transaction. + assertAllTxesSpendFrom(t, txes, closingTxid) // Mine a block to confirm the two transactions (+ coinbase). - block = mineBlocks(t, net, 1, 2)[0] - if len(block.Transactions) != 3 { + block = mineBlocks(t, net, 1, expectedTxes)[0] + if len(block.Transactions) != expectedTxes+1 { t.Fatalf("expected 3 transactions in block, got %v", len(block.Transactions)) } - for _, txid := range commitSpends { - assertTxInBlock(t, block, txid) - } // Keep track of the second level tx maturity. carolSecondLevelCSV := uint32(defaultCSV) diff --git a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go index b60cfda4be..d51d2c3d2c 100644 --- a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go @@ -82,7 +82,9 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // force close the Bob -> Carol channel. This should trigger contract // resolution mode for both of them. ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, bob, bobChanPoint, true) + closeChannelAndAssertType( + ctxt, t, net, bob, bobChanPoint, c == commitTypeAnchors, true, + ) // At this point, Bob should have a pending force close channel as he // just went to chain. @@ -116,8 +118,16 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, t.Fatalf(predErr.Error()) } - // We'll mine defaultCSV blocks in order to generate the sweep transaction - // of Bob's funding output. + // We'll mine defaultCSV blocks in order to generate the sweep + // transaction of Bob's funding output. If there are anchors, mine + // Carol's anchor sweep too. + if c == commitTypeAnchors { + _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + if err != nil { + t.Fatalf("unable to find carol's anchor sweep tx: %v", err) + } + } + if _, err := net.Miner.Node.Generate(defaultCSV); err != nil { t.Fatalf("unable to generate blocks: %v", err) } @@ -275,6 +285,9 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, t.Fatalf(predErr.Error()) } + // Coop close, no anchors. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, false) + closeChannelAndAssertType( + ctxt, t, net, alice, aliceChanPoint, false, false, + ) } diff --git a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go index 2f70fe3cf4..ebff918781 100644 --- a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go @@ -81,9 +81,13 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // At this point, we'll now instruct Carol to force close the // transaction. This will let us exercise that Bob is able to sweep the - // expired HTLC on Carol's version of the commitment transaction. + // expired HTLC on Carol's version of the commitment transaction. If + // Carol has an anchor, it will be swept too. ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, carol, bobChanPoint, true) + closeChannelAndAssertType( + ctxt, t, net, carol, bobChanPoint, c == commitTypeAnchors, + true, + ) // At this point, Bob should have a pending force close channel as // Carol has gone directly to chain. @@ -110,11 +114,18 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, t.Fatalf(predErr.Error()) } - // Bob can sweep his output immediately. - _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) + // Bob can sweep his output immediately. If there is an anchor, Bob will + // sweep that as well. + expectedTxes := 1 + if c == commitTypeAnchors { + expectedTxes = 2 + } + + _, err = waitForNTxsInMempool( + net.Miner.Node, expectedTxes, minerMempoolTimeout, + ) if err != nil { - t.Fatalf("unable to find bob's funding output sweep tx: %v", - err) + t.Fatalf("failed to find txes in miner mempool: %v", err) } // Next, we'll mine enough blocks for the HTLC to expire. At this @@ -232,7 +243,10 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, // We'll close out the test by closing the channel from Alice to Bob, // and then shutting down the new node we created as its no longer - // needed. + // needed. Coop close, no anchors. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, alice, aliceChanPoint, false) + closeChannelAndAssertType( + ctxt, t, net, alice, aliceChanPoint, false, + false, + ) } diff --git a/lntest/itest/lnd_multi-hop_test.go b/lntest/itest/lnd_multi-hop_test.go index 2d4a9e5f04..ec73e18770 100644 --- a/lntest/itest/lnd_multi-hop_test.go +++ b/lntest/itest/lnd_multi-hop_test.go @@ -7,6 +7,8 @@ import ( "fmt" "testing" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" @@ -65,6 +67,7 @@ func testMultiHopHtlcClaims(net *lntest.NetworkHarness, t *harnessTest) { commitTypes := []commitType{ commitTypeLegacy, + commitTypeAnchors, } for _, commitType := range commitTypes { @@ -204,16 +207,19 @@ func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, t.Fatalf("unable to connect peers: %v", err) } - ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) - err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, alice) - if err != nil { - t.Fatalf("unable to send coins to Alice: %v", err) - } + // Make sure there are enough utxos for anchoring. + for i := 0; i < 2; i++ { + ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, alice) + if err != nil { + t.Fatalf("unable to send coins to Alice: %v", err) + } - ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) - err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, bob) - if err != nil { - t.Fatalf("unable to send coins to Bob: %v", err) + ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, bob) + if err != nil { + t.Fatalf("unable to send coins to Bob: %v", err) + } } // We'll start the test by creating a channel between Alice and Bob, @@ -255,6 +261,18 @@ func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, t.Fatalf("unable to connect bob to carol: %v", err) } + // Make sure Carol has enough utxos for anchoring. Because the anchor by + // itself often doesn't meet the dust limit, a utxo from the wallet + // needs to be attached as an additional input. This can still lead to a + // positively-yielding transaction. + for i := 0; i < 2; i++ { + ctxt, _ = context.WithTimeout(context.Background(), defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, carol) + if err != nil { + t.Fatalf("unable to send coins to Alice: %v", err) + } + } + // We'll then create a channel from Bob to Carol. After this channel is // open, our topology looks like: A -> B -> C. ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) @@ -282,3 +300,16 @@ func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness, return aliceChanPoint, bobChanPoint, carol } + +// assertAllTxesSpendFrom asserts that all txes in the list spend from the given +// tx. +func assertAllTxesSpendFrom(t *harnessTest, txes []*wire.MsgTx, + prevTxid chainhash.Hash) { + + for _, tx := range txes { + if tx.TxIn[0].PreviousOutPoint.Hash != prevTxid { + t.Fatalf("tx %v did not spend from %v", + tx.TxHash(), prevTxid) + } + } +} diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index c36e8a1395..be87a3f809 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -268,6 +268,13 @@ func closeChannelAndAssert(ctx context.Context, t *harnessTest, net *lntest.NetworkHarness, node *lntest.HarnessNode, fundingChanPoint *lnrpc.ChannelPoint, force bool) *chainhash.Hash { + return closeChannelAndAssertType(ctx, t, net, node, fundingChanPoint, false, force) +} + +func closeChannelAndAssertType(ctx context.Context, t *harnessTest, + net *lntest.NetworkHarness, node *lntest.HarnessNode, + fundingChanPoint *lnrpc.ChannelPoint, anchors, force bool) *chainhash.Hash { + // Fetch the current channel policy. If the channel is currently // enabled, we will register for graph notifications before closing to // assert that the node sends out a disabling update as a result of the @@ -301,7 +308,9 @@ func closeChannelAndAssert(ctx context.Context, t *harnessTest, ) } - return assertChannelClosed(ctx, t, net, node, fundingChanPoint, closeUpdates) + return assertChannelClosed( + ctx, t, net, node, fundingChanPoint, anchors, closeUpdates, + ) } // closeReorgedChannelAndAssert attempts to close a channel identified by the @@ -322,14 +331,16 @@ func closeReorgedChannelAndAssert(ctx context.Context, t *harnessTest, t.Fatalf("unable to close channel: %v", err) } - return assertChannelClosed(ctx, t, net, node, fundingChanPoint, closeUpdates) + return assertChannelClosed( + ctx, t, net, node, fundingChanPoint, false, closeUpdates, + ) } // assertChannelClosed asserts that the channel is properly cleaned up after // initiating a cooperative or local close. func assertChannelClosed(ctx context.Context, t *harnessTest, net *lntest.NetworkHarness, node *lntest.HarnessNode, - fundingChanPoint *lnrpc.ChannelPoint, + fundingChanPoint *lnrpc.ChannelPoint, anchors bool, closeUpdates lnrpc.Lightning_CloseChannelClient) *chainhash.Hash { txid, err := lnd.GetChanPointFundingTxid(fundingChanPoint) @@ -381,8 +392,13 @@ func assertChannelClosed(ctx context.Context, t *harnessTest, // We'll now, generate a single block, wait for the final close status // update, then ensure that the closing transaction was included in the - // block. - block := mineBlocks(t, net, 1, 1)[0] + // block. If there are anchors, we also expect an anchor sweep. + expectedTxes := 1 + if anchors { + expectedTxes = 2 + } + + block := mineBlocks(t, net, 1, expectedTxes)[0] closingTxid, err := net.WaitForChannelClose(ctx, closeUpdates) if err != nil { From 55241b8e166163fd972a18d25e0a67d10b338819 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 27 Mar 2020 16:58:41 +0800 Subject: [PATCH 314/562] gitignore: add coverage.txt --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 48efdd2abd..ed8d0a8d8b 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,6 @@ profile.tmp .DS_Store .vscode + +# Coverage test +coverage.txt \ No newline at end of file From 4be1a4d0ec7d3e7ccd3ac51bf152840d87021809 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 27 Mar 2020 16:59:18 +0800 Subject: [PATCH 315/562] multi: fix typos --- brontide/noise.go | 13 ++++++------- lntest/itest/lnd_test.go | 2 +- lntest/node.go | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/brontide/noise.go b/brontide/noise.go index 16263e5fa0..f7a6685589 100644 --- a/brontide/noise.go +++ b/brontide/noise.go @@ -47,7 +47,7 @@ const ( ) var ( - // ErrMaxMessageLengthExceeded is returned a message to be written to + // ErrMaxMessageLengthExceeded is returned when a message to be written to // the cipher session exceeds the maximum allowed message payload. ErrMaxMessageLengthExceeded = errors.New("the generated payload exceeds " + "the max allowed message length of (2^16)-1") @@ -209,7 +209,7 @@ type symmetricState struct { handshakeDigest [32]byte } -// mixKey is implements a basic HKDF-based key ratchet. This method is called +// mixKey implements a basic HKDF-based key ratchet. This method is called // with the result of each DH output generated during the handshake process. // The first 32 bytes extract from the HKDF reader is the next chaining key, // then latter 32 bytes become the temp secret key using within any future AEAD @@ -315,7 +315,7 @@ func newHandshakeState(initiator bool, prologue []byte, h.InitializeSymmetric([]byte(protocolName)) h.mixHash(prologue) - // In Noise_XK, then initiator should know the responder's static + // In Noise_XK, the initiator should know the responder's static // public key, therefore we include the responder's static key in the // handshake digest. If the initiator gets this value wrong, then the // handshake will fail. @@ -330,7 +330,7 @@ func newHandshakeState(initiator bool, prologue []byte, // EphemeralGenerator is a functional option that allows callers to substitute // a custom function for use when generating ephemeral keys for ActOne or -// ActTwo. The function closure return by this function can be passed into +// ActTwo. The function closure returned by this function can be passed into // NewBrontideMachine as a function option parameter. func EphemeralGenerator(gen func() (*btcec.PrivateKey, error)) func(*Machine) { return func(m *Machine) { @@ -437,8 +437,7 @@ const ( // ActThreeSize is the size of the packet sent from initiator to // responder in ActThree. The packet consists of a handshake version, // the initiators static key encrypted with strong forward secrecy and - // a 16-byte poly1035 - // tag. + // a 16-byte poly1035 tag. // // 1 + 33 + 16 + 16 ActThreeSize = 66 @@ -519,7 +518,7 @@ func (b *Machine) RecvActOne(actOne [ActOneSize]byte) error { } // GenActTwo generates the second packet (act two) to be sent from the -// responder to the initiator. The packet for act two is identify to that of +// responder to the initiator. The packet for act two is identical to that of // act one, but then results in a different ECDH operation between the // initiator's and responder's ephemeral keys. // diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index c13bfa475d..cefc0acaef 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -1359,7 +1359,7 @@ func testPaymentFollowingChannelOpen(net *lntest.NetworkHarness, t *harnessTest) t.Fatalf("unable to create pay reqs: %v", err) } - // Send payment to Bob so there a chanel update to disk will be + // Send payment to Bob so that a channel update to disk will be // executed. ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) defer cancel() diff --git a/lntest/node.go b/lntest/node.go index 55358e29b5..b08e993517 100644 --- a/lntest/node.go +++ b/lntest/node.go @@ -123,7 +123,7 @@ type BackendConfig interface { // ConnectMiner is called to establish a connection to the test miner. ConnectMiner() error - // DisconnectMiner is called to bitconneeeect the miner. + // DisconnectMiner is called to disconnect the miner. DisconnectMiner() error // Name returns the name of the backend type. From be83d504f89f0bc5ad4406c01d9dad736dd70429 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Fri, 20 Dec 2019 12:52:08 +0100 Subject: [PATCH 316/562] autopilot: introduce NodeMetric interface for arbitrary graph metrics This commit adds the NodeMetric interface which will be used for all graph metrics not directly part of the autopilot but are useful in composite heuristics to drive autopilot decisions and improve node scores. --- autopilot/interface.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/autopilot/interface.go b/autopilot/interface.go index b63661e312..7efeba7657 100644 --- a/autopilot/interface.go +++ b/autopilot/interface.go @@ -147,6 +147,23 @@ type AttachmentHeuristic interface { map[NodeID]*NodeScore, error) } +// NodeMetric is a common interface for all graph metrics that are not +// directly used as autopilot node scores but may be used in compositional +// heuristics or statistical information exposed to users. +type NodeMetric interface { + // Name returns the unique name of this metric. + Name() string + + // Refresh refreshes the metric values based on the current graph. + Refresh(graph ChannelGraph) error + + // GetMetric returns the latest value of this metric. Values in the + // map are per node and can be in arbitrary domain. If normalize is + // set to true, then the returned values are normalized to either + // [0, 1] or [-1, 1] depending on the metric. + GetMetric(normalize bool) map[NodeID]float64 +} + // ScoreSettable is an interface that indicates that the scores returned by the // heuristic can be mutated by an external caller. The ExternalScoreAttachment // currently implements this interface, and so should any heuristic that is From 3fe9c707220935323c03fa943b7b11e275588d77 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Fri, 20 Dec 2019 12:54:59 +0100 Subject: [PATCH 317/562] autopilot: betweenness centrality using Brandes algo on simplifed graph This commit adds betweenness centrality to the available node metrics. Betweenness centrality is a per node centrality measure which for an arbitrary node v equals to the sum of shortest paths going trough v divided by the number of all shortest paths for for each vertex pair k, s where k != s != v. --- autopilot/betweenness_centrality.go | 212 +++++++++++++++++++++++ autopilot/betweenness_centrality_test.go | 156 +++++++++++++++++ autopilot/simple_graph.go | 66 +++++++ 3 files changed, 434 insertions(+) create mode 100644 autopilot/betweenness_centrality.go create mode 100644 autopilot/betweenness_centrality_test.go create mode 100644 autopilot/simple_graph.go diff --git a/autopilot/betweenness_centrality.go b/autopilot/betweenness_centrality.go new file mode 100644 index 0000000000..bfc15e368a --- /dev/null +++ b/autopilot/betweenness_centrality.go @@ -0,0 +1,212 @@ +package autopilot + +// stack is a simple int stack to help with readability of Brandes' +// betweenness centrality implementation below. +type stack struct { + stack []int +} + +func (s *stack) push(v int) { + s.stack = append(s.stack, v) +} + +func (s *stack) top() int { + return s.stack[len(s.stack)-1] +} + +func (s *stack) pop() { + s.stack = s.stack[:len(s.stack)-1] +} + +func (s *stack) empty() bool { + return len(s.stack) == 0 +} + +// queue is a simple int queue to help with readability of Brandes' +// betweenness centrality implementation below. +type queue struct { + queue []int +} + +func (q *queue) push(v int) { + q.queue = append(q.queue, v) +} + +func (q *queue) front() int { + return q.queue[0] +} + +func (q *queue) pop() { + q.queue = q.queue[1:] +} + +func (q *queue) empty() bool { + return len(q.queue) == 0 +} + +// BetweennessCentrality is a NodeMetric that calculates node betweenness +// centrality using Brandes' algorithm. Betweenness centrality for each node +// is the number of shortest paths passing trough that node, not counting +// shortest paths starting or ending at that node. This is a useful metric +// to measure control of individual nodes over the whole network. +type BetweennessCentrality struct { + // centrality stores original (not normalized) centrality values for + // each node in the graph. + centrality map[NodeID]float64 + + // min is the minimum centrality in the graph. + min float64 + + // max is the maximum centrality in the graph. + max float64 +} + +// NewBetweennessCentralityMetric creates a new BetweennessCentrality instance. +func NewBetweennessCentralityMetric() *BetweennessCentrality { + return &BetweennessCentrality{} +} + +// Name returns the name of the metric. +func (bc *BetweennessCentrality) Name() string { + return "betweeness_centrality" +} + +// betweennessCentrality is the core of Brandes' algorithm. +// We first calculate the shortest paths from the start node s to all other +// nodes with BFS, then update the betweenness centrality values by using +// Brandes' dependency trick. +// For detailed explanation please read: +// https://www.cl.cam.ac.uk/teaching/1617/MLRD/handbook/brandes.html +func betweennessCentrality(g *SimpleGraph, s int, centrality []float64) { + // pred[w] is the list of nodes that immediately precede w on a + // shortest path from s to t for each node t. + pred := make([][]int, len(g.Nodes)) + + // sigma[t] is the number of shortest paths between nodes s and t for + // each node t. + sigma := make([]int, len(g.Nodes)) + sigma[s] = 1 + + // dist[t] holds the distance between s and t for each node t. We initialize + // this to -1 (meaning infinity) for each t != s. + dist := make([]int, len(g.Nodes)) + for i := range dist { + dist[i] = -1 + } + + dist[s] = 0 + + var ( + st stack + q queue + ) + q.push(s) + + // BFS to calculate the shortest paths (sigma and pred) + // from s to t for each node t. + for !q.empty() { + v := q.front() + q.pop() + st.push(v) + + for _, w := range g.Adj[v] { + // If distance from s to w is infinity (-1) + // then set it and enqueue w. + if dist[w] < 0 { + dist[w] = dist[v] + 1 + q.push(w) + } + + // If w is on a shortest path the update + // sigma and add v to w's predecessor list. + if dist[w] == dist[v]+1 { + sigma[w] += sigma[v] + pred[w] = append(pred[w], v) + } + } + } + + // delta[v] is the ratio of the shortest paths between s and t that go + // through v and the total number of shortest paths between s and t. + // If we have delta then the betweenness centrality is simply the sum + // of delta[w] for each w != s. + delta := make([]float64, len(g.Nodes)) + + for !st.empty() { + w := st.top() + st.pop() + + // pred[w] is the list of nodes that immediately precede w on a + // shortest path from s. + for _, v := range pred[w] { + // Update delta using Brandes' equation. + delta[v] += (float64(sigma[v]) / float64(sigma[w])) * (1.0 + delta[w]) + } + + if w != s { + // As noted above centrality is simply the sum + // of delta[w] for each w != s. + centrality[w] += delta[w] + } + } +} + +// Refresh recaculates and stores centrality values. +func (bc *BetweennessCentrality) Refresh(graph ChannelGraph) error { + cache, err := NewSimpleGraph(graph) + if err != nil { + return err + } + + // TODO: parallelize updates to centrality. + centrality := make([]float64, len(cache.Nodes)) + for node := range cache.Nodes { + betweennessCentrality(cache, node, centrality) + } + + // Get min/max to be able to normalize + // centrality values between 0 and 1. + bc.min = 0 + bc.max = 0 + if len(centrality) > 0 { + for i := 1; i < len(centrality); i++ { + if centrality[i] < bc.min { + bc.min = centrality[i] + } else if centrality[i] > bc.max { + bc.max = centrality[i] + } + } + } + + // Divide by two as this is an undirected graph. + bc.min /= 2.0 + bc.max /= 2.0 + + bc.centrality = make(map[NodeID]float64) + for u, value := range centrality { + // Divide by two as this is an undirected graph. + bc.centrality[cache.Nodes[u]] = value / 2.0 + } + + return nil +} + +// GetMetric returns the current centrality values for each node indexed +// by node id. +func (bc *BetweennessCentrality) GetMetric(normalize bool) map[NodeID]float64 { + // Normalization factor. + var z float64 + if (bc.max - bc.min) > 0 { + z = 1.0 / (bc.max - bc.min) + } + + centrality := make(map[NodeID]float64) + for k, v := range bc.centrality { + if normalize { + v = (v - bc.min) * z + } + centrality[k] = v + } + + return centrality +} diff --git a/autopilot/betweenness_centrality_test.go b/autopilot/betweenness_centrality_test.go new file mode 100644 index 0000000000..09fd7fc3d0 --- /dev/null +++ b/autopilot/betweenness_centrality_test.go @@ -0,0 +1,156 @@ +package autopilot + +import ( + "testing" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcutil" +) + +// Tests that empty graph results in empty centrality result. +func TestBetweennessCentralityEmptyGraph(t *testing.T) { + centralityMetric := NewBetweennessCentralityMetric() + + for _, chanGraph := range chanGraphs { + graph, cleanup, err := chanGraph.genFunc() + success := t.Run(chanGraph.name, func(t1 *testing.T) { + if err != nil { + t1.Fatalf("unable to create graph: %v", err) + } + if cleanup != nil { + defer cleanup() + } + + if err := centralityMetric.Refresh(graph); err != nil { + t.Fatalf("unexpected failure during metric refresh: %v", err) + } + + centrality := centralityMetric.GetMetric(false) + if len(centrality) > 0 { + t.Fatalf("expected empty metric, got: %v", len(centrality)) + } + + centrality = centralityMetric.GetMetric(true) + if len(centrality) > 0 { + t.Fatalf("expected empty metric, got: %v", len(centrality)) + } + + }) + if !success { + break + } + } +} + +// testGraphDesc is a helper type to describe a test graph. +type testGraphDesc struct { + nodes int + edges map[int][]int +} + +// buildTestGraph builds a test graph from a passed graph desriptor. +func buildTestGraph(t *testing.T, + graph testGraph, desc testGraphDesc) map[int]*btcec.PublicKey { + + nodes := make(map[int]*btcec.PublicKey) + + for i := 0; i < desc.nodes; i++ { + key, err := graph.addRandNode() + if err != nil { + t.Fatalf("cannot create random node") + } + + nodes[i] = key + } + + const chanCapacity = btcutil.SatoshiPerBitcoin + for u, neighbors := range desc.edges { + for _, v := range neighbors { + _, _, err := graph.addRandChannel(nodes[u], nodes[v], chanCapacity) + if err != nil { + t.Fatalf("unexpected error while adding random channel: %v", err) + } + } + } + + return nodes +} + +// Test betweenness centrality calculating using an example graph. +func TestBetweennessCentralityWithNonEmptyGraph(t *testing.T) { + graphDesc := testGraphDesc{ + nodes: 9, + edges: map[int][]int{ + 0: {1, 2, 3}, + 1: {2}, + 2: {3}, + 3: {4, 5}, + 4: {5, 6, 7}, + 5: {6, 7}, + 6: {7, 8}, + }, + } + + tests := []struct { + name string + normalize bool + centrality []float64 + }{ + { + normalize: true, + centrality: []float64{ + 0.2, 0.0, 0.2, 1.0, 0.4, 0.4, 7.0 / 15.0, 0.0, 0.0, + }, + }, + { + normalize: false, + centrality: []float64{ + 3.0, 0.0, 3.0, 15.0, 6.0, 6.0, 7.0, 0.0, 0.0, + }, + }, + } + + for _, chanGraph := range chanGraphs { + graph, cleanup, err := chanGraph.genFunc() + if err != nil { + t.Fatalf("unable to create graph: %v", err) + } + if cleanup != nil { + defer cleanup() + } + + success := t.Run(chanGraph.name, func(t1 *testing.T) { + centralityMetric := NewBetweennessCentralityMetric() + graphNodes := buildTestGraph(t1, graph, graphDesc) + + if err := centralityMetric.Refresh(graph); err != nil { + t1.Fatalf("error while calculating betweeness centrality") + } + for _, test := range tests { + test := test + centrality := centralityMetric.GetMetric(test.normalize) + + if len(centrality) != graphDesc.nodes { + t.Fatalf("expected %v values, got: %v", + graphDesc.nodes, len(centrality)) + } + + for node, nodeCentrality := range test.centrality { + nodeID := NewNodeID(graphNodes[node]) + calculatedCentrality, ok := centrality[nodeID] + if !ok { + t1.Fatalf("no result for node: %x (%v)", nodeID, node) + } + + if nodeCentrality != calculatedCentrality { + t1.Errorf("centrality for node: %v should be %v, got: %v", + node, test.centrality[node], calculatedCentrality) + } + } + } + }) + if !success { + break + } + } +} diff --git a/autopilot/simple_graph.go b/autopilot/simple_graph.go new file mode 100644 index 0000000000..208a784e9f --- /dev/null +++ b/autopilot/simple_graph.go @@ -0,0 +1,66 @@ +package autopilot + +// SimpleGraph stores a simplifed adj graph of a channel graph to speed +// up graph processing by eliminating all unnecessary hashing and map access. +type SimpleGraph struct { + // Nodes is a map from node index to NodeID. + Nodes []NodeID + + // Adj stores nodes and neighbors in an adjacency list. + Adj [][]int +} + +// NewSimpleGraph creates a simplified graph from the current channel graph. +// Returns an error if the channel graph iteration fails due to underlying +// failure. +func NewSimpleGraph(g ChannelGraph) (*SimpleGraph, error) { + nodes := make(map[NodeID]int) + adj := make(map[int][]int) + nextIndex := 0 + + // getNodeIndex returns the integer index of the passed node. + // The returned index is then used to create a simplifed adjacency list + // where each node is identified by its index instead of its pubkey, and + // also to create a mapping from node index to node pubkey. + getNodeIndex := func(node Node) int { + key := NodeID(node.PubKey()) + nodeIndex, ok := nodes[key] + + if !ok { + nodes[key] = nextIndex + nodeIndex = nextIndex + nextIndex++ + } + + return nodeIndex + } + + // Iterate over each node and each channel and update the adj and the node + // index. + err := g.ForEachNode(func(node Node) error { + u := getNodeIndex(node) + + return node.ForEachChannel(func(edge ChannelEdge) error { + v := getNodeIndex(edge.Peer) + + adj[u] = append(adj[u], v) + return nil + }) + }) + if err != nil { + return nil, err + } + + graph := &SimpleGraph{ + Nodes: make([]NodeID, len(nodes)), + Adj: make([][]int, len(nodes)), + } + + // Fill the adj and the node index to node pubkey mapping. + for nodeID, nodeIndex := range nodes { + graph.Adj[nodeIndex] = adj[nodeIndex] + graph.Nodes[nodeIndex] = nodeID + } + + return graph, nil +} From f5237589ea6c214c81b30d0846b47a6b7c7caeed Mon Sep 17 00:00:00 2001 From: nsa Date: Fri, 6 Mar 2020 22:38:39 -0500 Subject: [PATCH 318/562] channelnotifier: new ActiveLinkEvent for link startup notification --- channelnotifier/channelnotifier.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/channelnotifier/channelnotifier.go b/channelnotifier/channelnotifier.go index e6a1fada7d..5d67fd51c0 100644 --- a/channelnotifier/channelnotifier.go +++ b/channelnotifier/channelnotifier.go @@ -40,6 +40,13 @@ type OpenChannelEvent struct { Channel *channeldb.OpenChannel } +// ActiveLinkEvent represents a new event where the link becomes active in the +// switch. This happens before the ActiveChannelEvent. +type ActiveLinkEvent struct { + // ChannelPoint is the channel point for the newly active channel. + ChannelPoint *wire.OutPoint +} + // ActiveChannelEvent represents a new event where a channel becomes active. type ActiveChannelEvent struct { // ChannelPoint is the channelpoint for the newly active channel. @@ -146,6 +153,15 @@ func (c *ChannelNotifier) NotifyClosedChannelEvent(chanPoint wire.OutPoint) { } } +// NotifyActiveLinkEvent notifies the channelEventNotifier goroutine that a +// link has been added to the switch. +func (c *ChannelNotifier) NotifyActiveLinkEvent(chanPoint wire.OutPoint) { + event := ActiveLinkEvent{ChannelPoint: &chanPoint} + if err := c.ntfnServer.SendUpdate(event); err != nil { + log.Warnf("Unable to send active link update: %v", err) + } +} + // NotifyActiveChannelEvent notifies the channelEventNotifier goroutine that a // channel is active. func (c *ChannelNotifier) NotifyActiveChannelEvent(chanPoint wire.OutPoint) { From 966cd2112cfe9481714133be49afe6b5e4c67f98 Mon Sep 17 00:00:00 2001 From: nsa Date: Fri, 6 Mar 2020 22:42:58 -0500 Subject: [PATCH 319/562] multi: link notifies subscribers of ActiveLinkEvent, rpc ignores --- htlcswitch/link.go | 8 ++++++++ htlcswitch/link_test.go | 2 ++ htlcswitch/test_utils.go | 1 + peer.go | 2 ++ rpcserver.go | 7 +++++++ 5 files changed, 20 insertions(+) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index ff631a59db..d91bc85685 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -265,6 +265,10 @@ type ChannelLinkConfig struct { // initiator of the channel. MaxFeeAllocation float64 + // NotifyActiveLink allows the link to tell the ChannelNotifier when a + // link is first started. + NotifyActiveLink func(wire.OutPoint) + // NotifyActiveChannel allows the link to tell the ChannelNotifier when // channels becomes active. NotifyActiveChannel func(wire.OutPoint) @@ -870,6 +874,10 @@ func (l *channelLink) htlcManager() { l.log.Infof("HTLC manager started, bandwidth=%v", l.Bandwidth()) + // Notify any clients that the link is now in the switch via an + // ActiveLinkEvent. + l.cfg.NotifyActiveLink(*l.ChannelPoint()) + // TODO(roasbeef): need to call wipe chan whenever D/C? // If this isn't the first time that this channel link has been diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index d7f95df162..d150ddc55c 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -1748,6 +1748,7 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) ( MaxFeeUpdateTimeout: 40 * time.Minute, MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, MaxFeeAllocation: DefaultMaxLinkFeeAllocation, + NotifyActiveLink: func(wire.OutPoint) {}, NotifyActiveChannel: func(wire.OutPoint) {}, NotifyInactiveChannel: func(wire.OutPoint) {}, HtlcNotifier: aliceSwitch.cfg.HtlcNotifier, @@ -4474,6 +4475,7 @@ func (h *persistentLinkHarness) restartLink( HodlMask: hodl.MaskFromFlags(hodlFlags...), MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, MaxFeeAllocation: DefaultMaxLinkFeeAllocation, + NotifyActiveLink: func(wire.OutPoint) {}, NotifyActiveChannel: func(wire.OutPoint) {}, NotifyInactiveChannel: func(wire.OutPoint) {}, HtlcNotifier: aliceSwitch.cfg.HtlcNotifier, diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index f628f280ba..f302ff01c2 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1173,6 +1173,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer, OutgoingCltvRejectDelta: 3, MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, MaxFeeAllocation: DefaultMaxLinkFeeAllocation, + NotifyActiveLink: func(wire.OutPoint) {}, NotifyActiveChannel: func(wire.OutPoint) {}, NotifyInactiveChannel: func(wire.OutPoint) {}, HtlcNotifier: server.htlcSwitch.cfg.HtlcNotifier, diff --git a/peer.go b/peer.go index 2236e66c3a..4368f71b4a 100644 --- a/peer.go +++ b/peer.go @@ -21,6 +21,7 @@ import ( "github.com/lightningnetwork/lnd/buffer" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/feature" "github.com/lightningnetwork/lnd/htlcswitch" @@ -649,6 +650,7 @@ func (p *peer) addLink(chanPoint *wire.OutPoint, TowerClient: p.server.towerClient, MaxOutgoingCltvExpiry: cfg.MaxOutgoingCltvExpiry, MaxFeeAllocation: cfg.MaxChannelFeeAllocation, + NotifyActiveLink: p.server.channelNotifier.NotifyActiveLinkEvent, NotifyActiveChannel: p.server.channelNotifier.NotifyActiveChannelEvent, NotifyInactiveChannel: p.server.channelNotifier.NotifyInactiveChannelEvent, HtlcNotifier: p.server.htlcNotifier, diff --git a/rpcserver.go b/rpcserver.go index 721b4fad4f..947d462c05 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3522,6 +3522,11 @@ func (r *rpcServer) SubscribeChannelEvents(req *lnrpc.ChannelEventSubscription, }, } + // Completely ignore ActiveLinkEvent as this is explicitly not + // exposed to the RPC. + case channelnotifier.ActiveLinkEvent: + continue + default: return fmt.Errorf("unexpected channel event update: %v", event) } @@ -5896,6 +5901,8 @@ func (r *rpcServer) SubscribeChannelBackups(req *lnrpc.ChannelBackupSubscription continue case channelnotifier.InactiveChannelEvent: continue + case channelnotifier.ActiveLinkEvent: + continue } // Now that we know the channel state has changed, From f00159f64cb4377dd9128b9024f91db333548a2b Mon Sep 17 00:00:00 2001 From: nsa Date: Fri, 6 Mar 2020 22:43:51 -0500 Subject: [PATCH 320/562] peer: no pending channels in switch, buffer msgs until link active --- peer.go | 196 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 143 insertions(+), 53 deletions(-) diff --git a/peer.go b/peer.go index 4368f71b4a..df77c4fd6f 100644 --- a/peer.go +++ b/peer.go @@ -160,6 +160,13 @@ type peer struct { // activeChannels is a map which stores the state machines of all // active channels. Channels are indexed into the map by the txid of // the funding transaction which opened the channel. + // + // NOTE: On startup, pending channels are stored as nil in this map. + // Confirmed channels have channel data populated in the map. This means + // that accesses to this map should nil-check the LightningChannel to + // see if this is a pending channel or not. The tradeoff here is either + // having two maps everywhere (one for pending, one for confirmed chans) + // or having an extra nil-check per access. activeChannels map[lnwire.ChannelID]*lnwallet.LightningChannel // addedChannels tracks any new channels opened during this peer's @@ -564,9 +571,21 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) ( peerLog.Tracef("Using link policy of: %v", spew.Sdump(forwardingPolicy)) - // Register this new channel link with the HTLC Switch. This is - // necessary to properly route multi-hop payments, and forward - // new payments triggered by RPC clients. + // If the channel is pending, set the value to nil in the + // activeChannels map. This is done to signify that the channel is + // pending. We don't add the link to the switch here - it's the funding + // manager's responsibility to spin up pending channels. Adding them + // here would just be extra work as we'll tear them down when creating + // + adding the final link. + if lnChan.IsPending() { + p.activeChanMtx.Lock() + p.activeChannels[chanID] = nil + p.activeChanMtx.Unlock() + + continue + } + + // Subscribe to the set of on-chain events for this channel. chainEvents, err := p.server.chainArb.SubscribeChannelEvents( *chanPoint, ) @@ -574,7 +593,6 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) ( return nil, err } - // Create the link and add it to the switch. err = p.addLink( chanPoint, lnChan, forwardingPolicy, chainEvents, currentHeight, true, @@ -927,6 +945,69 @@ func (ms *msgStream) AddMsg(msg lnwire.Message) { ms.msgCond.Signal() } +// waitUntilLinkActive waits until the target link is active and returns a +// ChannelLink to pass messages to. It accomplishes this by subscribing to +// an ActiveLinkEvent which is emitted by the link when it first starts up. +func waitUntilLinkActive(p *peer, cid lnwire.ChannelID) htlcswitch.ChannelLink { + // Subscribe to receive channel events. + // + // NOTE: If the link is already active by SubscribeChannelEvents, then + // GetLink will retrieve the link and we can send messages. If the link + // becomes active between SubscribeChannelEvents and GetLink, then GetLink + // will retrieve the link. If the link becomes active after GetLink, then + // we will get an ActiveLinkEvent notification and retrieve the link. If + // the call to GetLink is before SubscribeChannelEvents, however, there + // will be a race condition. + sub, err := p.server.channelNotifier.SubscribeChannelEvents() + if err != nil { + // If we have a non-nil error, then the server is shutting down and we + // can exit here and return nil. This means no message will be delivered + // to the link. + return nil + } + defer sub.Cancel() + + // The link may already be active by this point, and we may have missed the + // ActiveLinkEvent. Check if the link exists. + link, _ := p.server.htlcSwitch.GetLink(cid) + if link != nil { + return link + } + + // If the link is nil, we must wait for it to be active. + for { + select { + // A new event has been sent by the ChannelNotifier. We first check + // whether the event is an ActiveLinkEvent. If it is, we'll check + // that the event is for this channel. Otherwise, we discard the + // message. + case e := <-sub.Updates(): + event, ok := e.(channelnotifier.ActiveLinkEvent) + if !ok { + // Ignore this notification. + continue + } + + chanPoint := event.ChannelPoint + + // Check whether the retrieved chanPoint matches the target + // channel id. + if !cid.IsChanPoint(chanPoint) { + continue + } + + // The link shouldn't be nil as we received an + // ActiveLinkEvent. If it is nil, we return nil and the + // calling function should catch it. + link, _ = p.server.htlcSwitch.GetLink(cid) + return link + + case <-p.quit: + return nil + } + } +} + // newChanMsgStream is used to create a msgStream between the peer and // particular channel link in the htlcswitch. We utilize additional // synchronization with the fundingManager to ensure we don't attempt to @@ -942,51 +1023,17 @@ func newChanMsgStream(p *peer, cid lnwire.ChannelID) *msgStream { fmt.Sprintf("Update stream for ChannelID(%x) exiting", cid[:]), 1000, func(msg lnwire.Message) { - _, isChanSyncMsg := msg.(*lnwire.ChannelReestablish) - - // If this is the chanSync message, then we'll deliver - // it immediately to the active link. - if !isChanSyncMsg { - // We'll send a message to the funding manager - // and wait iff an active funding process for - // this channel hasn't yet completed. We do - // this in order to account for the following - // scenario: we send the funding locked message - // to the other side, they immediately send a - // channel update message, but we haven't yet - // sent the channel to the channelManager. - err := p.server.fundingMgr.waitUntilChannelOpen( - cid, p.quit, - ) - if err != nil { - // If we have a non-nil error, then the - // funding manager is shutting down, s - // we can exit here without attempting - // to deliver the message. - return - } - } - - // In order to avoid unnecessarily delivering message - // as the peer is exiting, we'll check quickly to see - // if we need to exit. - select { - case <-p.quit: - return - default: - } - - // Dispatch the commitment update message to the proper - // active goroutine dedicated to this channel. + // This check is fine because if the link no longer exists, it will + // be removed from the activeChannels map and subsequent messages + // shouldn't reach the chan msg stream. if chanLink == nil { - link, err := p.server.htlcSwitch.GetLink(cid) - if err != nil { - peerLog.Errorf("recv'd update for "+ - "unknown channel %v from %v: "+ - "%v", cid, p, err) + chanLink = waitUntilLinkActive(p, cid) + + // If the link is still not active and the calling function + // errored out, just return. + if chanLink == nil { return } - chanLink = link } // In order to avoid unnecessarily delivering message @@ -1229,13 +1276,23 @@ func (p *peer) isActiveChannel(chanID lnwire.ChannelID) bool { // channel with the peer to mitigate dos attack vectors where a peer costlessly // connects to us and spams us with errors. func (p *peer) storeError(err error) { + var haveChannels bool + p.activeChanMtx.RLock() - channelCount := len(p.activeChannels) + for _, channel := range p.activeChannels { + // Pending channels will be nil in the activeChannels map. + if channel == nil { + continue + } + + haveChannels = true + break + } p.activeChanMtx.RUnlock() // If we do not have any active channels with the peer, we do not store // errors as a dos mitigation. - if channelCount == 0 { + if !haveChannels { peerLog.Tracef("no channels with peer: %v, not storing err", p) return } @@ -1777,6 +1834,11 @@ func (p *peer) ChannelSnapshots() []*channeldb.ChannelSnapshot { snapshots := make([]*channeldb.ChannelSnapshot, 0, len(p.activeChannels)) for _, activeChan := range p.activeChannels { + // If the activeChan is nil, then we skip it as the channel is pending. + if activeChan == nil { + continue + } + // We'll only return a snapshot for channels that are // *immedately* available for routing payments over. if activeChan.RemoteNextRevocation() == nil { @@ -1829,9 +1891,12 @@ out: chanPoint := &newChan.FundingOutpoint chanID := lnwire.NewChanIDFromOutPoint(chanPoint) - // Make sure this channel is not already active. + // Only update RemoteNextRevocation if the channel is in the + // activeChannels map and if we added the link to the switch. + // Only active channels will be added to the switch. p.activeChanMtx.Lock() - if currentChan, ok := p.activeChannels[chanID]; ok { + currentChan, ok := p.activeChannels[chanID] + if ok && currentChan != nil { peerLog.Infof("Already have ChannelPoint(%v), "+ "ignoring.", chanPoint) @@ -1877,6 +1942,8 @@ out: continue } + // This refreshes the activeChannels entry if the link was not in + // the switch, also populates for new entries. p.activeChannels[chanID] = lnChan p.addedChannels[chanID] = struct{}{} p.activeChanMtx.Unlock() @@ -1925,10 +1992,17 @@ out: TimeLockDelta: defaultPolicy.TimeLockDelta, } + // If we've reached this point, there are two possible scenarios. + // If the channel was in the active channels map as nil, then it + // was loaded from disk and we need to send reestablish. Else, + // it was not loaded from disk and we don't need to send + // reestablish as this is a fresh channel. + shouldReestablish := ok + // Create the link and add it to the switch. err = p.addLink( chanPoint, lnChan, forwardingPolicy, - chainEvents, currentHeight, false, + chainEvents, currentHeight, shouldReestablish, ) if err != nil { err := fmt.Errorf("can't register new channel "+ @@ -2047,6 +2121,11 @@ out: // our active channel back to their default state. p.activeChanMtx.Lock() for _, channel := range p.activeChannels { + // If the channel is nil, continue as it's a pending channel. + if channel == nil { + continue + } + channel.ResetState() } p.activeChanMtx.Unlock() @@ -2066,6 +2145,11 @@ func (p *peer) reenableActiveChannels() { var activePublicChans []wire.OutPoint p.activeChanMtx.RLock() for chanID, lnChan := range p.activeChannels { + // If the lnChan is nil, continue as this is a pending channel. + if lnChan == nil { + continue + } + dbChan := lnChan.State() isPublic := dbChan.ChannelFlags&lnwire.FFAnnounceChannel != 0 if !isPublic || dbChan.IsPending { @@ -2109,7 +2193,10 @@ func (p *peer) fetchActiveChanCloser(chanID lnwire.ChannelID) (*channelCloser, e p.activeChanMtx.RLock() channel, ok := p.activeChannels[chanID] p.activeChanMtx.RUnlock() - if !ok { + + // If the channel isn't in the map or the channel is nil, return + // ErrChannelNotFound as the channel is pending. + if !ok || channel == nil { return nil, ErrChannelNotFound } @@ -2218,7 +2305,10 @@ func (p *peer) handleLocalCloseReq(req *htlcswitch.ChanClose) { p.activeChanMtx.RLock() channel, ok := p.activeChannels[chanID] p.activeChanMtx.RUnlock() - if !ok { + + // Though this function can't be called for pending channels, we still + // check whether channel is nil for safety. + if !ok || channel == nil { err := fmt.Errorf("unable to close channel, ChannelID(%v) is "+ "unknown", chanID) peerLog.Errorf(err.Error()) From 7e50997bb4d83e129c6560fe81ffc20c62d33fb9 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Thu, 19 Mar 2020 11:14:28 +0100 Subject: [PATCH 321/562] lnrpc: add betweenness centrality to GetNodeMetrics (new RPC call) This commit extends the RPC interface with GetNodeMetrics will contain all graph node metrics in the future. Currently only holds betweennes centrality per node. --- cmd/lncli/commands.go | 25 + cmd/lncli/main.go | 1 + lnrpc/rpc.pb.go | 1768 ++++++++++++++++++++++------------------ lnrpc/rpc.pb.gw.go | 41 + lnrpc/rpc.proto | 39 + lnrpc/rpc.swagger.json | 67 ++ rpcserver.go | 61 +- 7 files changed, 1222 insertions(+), 780 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 15a2b04075..b9fc4089d5 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -2974,6 +2974,31 @@ func describeGraph(ctx *cli.Context) error { return nil } +var getNodeMetricsCommand = cli.Command{ + Name: "getnodemetrics", + Category: "Graph", + Description: "Prints out node metrics calculated from the current graph", + Usage: "Get node metrics.", + Action: actionDecorator(getNodeMetrics), +} + +func getNodeMetrics(ctx *cli.Context) error { + client, cleanUp := getClient(ctx) + defer cleanUp() + + req := &lnrpc.NodeMetricsRequest{ + Types: []lnrpc.NodeMetricType{lnrpc.NodeMetricType_BETWEENNESS_CENTRALITY}, + } + + nodeMetrics, err := client.GetNodeMetrics(context.Background(), req) + if err != nil { + return err + } + + printRespJSON(nodeMetrics) + return nil +} + var listPaymentsCommand = cli.Command{ Name: "listpayments", Category: "Payments", diff --git a/cmd/lncli/main.go b/cmd/lncli/main.go index 30aa2485df..e8170c5939 100644 --- a/cmd/lncli/main.go +++ b/cmd/lncli/main.go @@ -282,6 +282,7 @@ func main() { closedChannelsCommand, listPaymentsCommand, describeGraphCommand, + getNodeMetricsCommand, getChanInfoCommand, getNodeInfoCommand, queryRoutesCommand, diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 4203c5fb12..04be015618 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -99,6 +99,28 @@ func (CommitmentType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_77a6da22d6a3feb1, []int{1} } +type NodeMetricType int32 + +const ( + NodeMetricType_BETWEENNESS_CENTRALITY NodeMetricType = 0 +) + +var NodeMetricType_name = map[int32]string{ + 0: "BETWEENNESS_CENTRALITY", +} + +var NodeMetricType_value = map[string]int32{ + "BETWEENNESS_CENTRALITY": 0, +} + +func (x NodeMetricType) String() string { + return proto.EnumName(NodeMetricType_name, int32(x)) +} + +func (NodeMetricType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{2} +} + type InvoiceHTLCState int32 const ( @@ -124,7 +146,7 @@ func (x InvoiceHTLCState) String() string { } func (InvoiceHTLCState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{2} + return fileDescriptor_77a6da22d6a3feb1, []int{3} } type FeatureBit int32 @@ -194,7 +216,7 @@ func (x FeatureBit) String() string { } func (FeatureBit) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{3} + return fileDescriptor_77a6da22d6a3feb1, []int{4} } type ChannelCloseSummary_ClosureType int32 @@ -414,7 +436,7 @@ func (x Invoice_InvoiceState) String() string { } func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{106, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{109, 0} } type Payment_PaymentStatus int32 @@ -445,7 +467,7 @@ func (x Payment_PaymentStatus) String() string { } func (Payment_PaymentStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{113, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{116, 0} } type HTLCAttempt_HTLCStatus int32 @@ -473,7 +495,7 @@ func (x HTLCAttempt_HTLCStatus) String() string { } func (HTLCAttempt_HTLCStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{114, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{117, 0} } type Failure_FailureCode int32 @@ -584,7 +606,7 @@ func (x Failure_FailureCode) String() string { } func (Failure_FailureCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{147, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{150, 0} } type GenSeedRequest struct { @@ -7599,6 +7621,140 @@ func (m *ChannelGraph) GetEdges() []*ChannelEdge { return nil } +type NodeMetricsRequest struct { + /// The requesteded node metrics. + Types []NodeMetricType `protobuf:"varint,1,rep,packed,name=types,proto3,enum=lnrpc.NodeMetricType" json:"types,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +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{94} +} + +func (m *NodeMetricsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeMetricsRequest.Unmarshal(m, b) +} +func (m *NodeMetricsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeMetricsRequest.Marshal(b, m, deterministic) +} +func (m *NodeMetricsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeMetricsRequest.Merge(m, src) +} +func (m *NodeMetricsRequest) XXX_Size() int { + return xxx_messageInfo_NodeMetricsRequest.Size(m) +} +func (m *NodeMetricsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodeMetricsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeMetricsRequest proto.InternalMessageInfo + +func (m *NodeMetricsRequest) GetTypes() []NodeMetricType { + if m != nil { + return m.Types + } + return nil +} + +type NodeMetricsResponse struct { + //* + //Betweenness centrality is the sum of the ratio of shortest paths that pass + //through the node for each pair of nodes in the graph (not counting paths + //starting or ending at this node). + //Map of node pubkey to betweenness centrality of the node. Normalized + //values are in the [0,1] closed interval. + BetweennessCentrality map[string]*FloatValue `protobuf:"bytes,1,rep,name=betweenness_centrality,json=betweennessCentrality,proto3" json:"betweenness_centrality,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +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{95} +} + +func (m *NodeMetricsResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NodeMetricsResponse.Unmarshal(m, b) +} +func (m *NodeMetricsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NodeMetricsResponse.Marshal(b, m, deterministic) +} +func (m *NodeMetricsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeMetricsResponse.Merge(m, src) +} +func (m *NodeMetricsResponse) XXX_Size() int { + return xxx_messageInfo_NodeMetricsResponse.Size(m) +} +func (m *NodeMetricsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodeMetricsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeMetricsResponse proto.InternalMessageInfo + +func (m *NodeMetricsResponse) GetBetweennessCentrality() map[string]*FloatValue { + if m != nil { + return m.BetweennessCentrality + } + return nil +} + +type FloatValue struct { + /// Arbitrary float value. + Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` + /// The value normalized to [0,1] or [-1,1]. + NormalizedValue float64 `protobuf:"fixed64,2,opt,name=normalized_value,json=normalizedValue,proto3" json:"normalized_value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FloatValue) Reset() { *m = FloatValue{} } +func (m *FloatValue) String() string { return proto.CompactTextString(m) } +func (*FloatValue) ProtoMessage() {} +func (*FloatValue) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{96} +} + +func (m *FloatValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FloatValue.Unmarshal(m, b) +} +func (m *FloatValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FloatValue.Marshal(b, m, deterministic) +} +func (m *FloatValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_FloatValue.Merge(m, src) +} +func (m *FloatValue) XXX_Size() int { + return xxx_messageInfo_FloatValue.Size(m) +} +func (m *FloatValue) XXX_DiscardUnknown() { + xxx_messageInfo_FloatValue.DiscardUnknown(m) +} + +var xxx_messageInfo_FloatValue proto.InternalMessageInfo + +func (m *FloatValue) GetValue() float64 { + if m != nil { + return m.Value + } + return 0 +} + +func (m *FloatValue) GetNormalizedValue() float64 { + if m != nil { + return m.NormalizedValue + } + return 0 +} + type ChanInfoRequest struct { //* //The unique channel ID for the channel. The first 3 bytes are the block @@ -7614,7 +7770,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{94} + return fileDescriptor_77a6da22d6a3feb1, []int{97} } func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error { @@ -7652,7 +7808,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{95} + return fileDescriptor_77a6da22d6a3feb1, []int{98} } func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error { @@ -7695,7 +7851,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{96} + return fileDescriptor_77a6da22d6a3feb1, []int{99} } func (m *NetworkInfo) XXX_Unmarshal(b []byte) error { @@ -7803,7 +7959,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{97} + return fileDescriptor_77a6da22d6a3feb1, []int{100} } func (m *StopRequest) XXX_Unmarshal(b []byte) error { @@ -7834,7 +7990,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{98} + return fileDescriptor_77a6da22d6a3feb1, []int{101} } func (m *StopResponse) XXX_Unmarshal(b []byte) error { @@ -7865,7 +8021,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{99} + return fileDescriptor_77a6da22d6a3feb1, []int{102} } func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error { @@ -7899,7 +8055,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{100} + return fileDescriptor_77a6da22d6a3feb1, []int{103} } func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error { @@ -7956,7 +8112,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{101} + return fileDescriptor_77a6da22d6a3feb1, []int{104} } func (m *NodeUpdate) XXX_Unmarshal(b []byte) error { @@ -8032,7 +8188,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{102} + return fileDescriptor_77a6da22d6a3feb1, []int{105} } func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error { @@ -8113,7 +8269,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{103} + return fileDescriptor_77a6da22d6a3feb1, []int{106} } func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error { @@ -8184,7 +8340,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{104} + return fileDescriptor_77a6da22d6a3feb1, []int{107} } func (m *HopHint) XXX_Unmarshal(b []byte) error { @@ -8254,7 +8410,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{105} + return fileDescriptor_77a6da22d6a3feb1, []int{108} } func (m *RouteHint) XXX_Unmarshal(b []byte) error { @@ -8387,7 +8543,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{106} + return fileDescriptor_77a6da22d6a3feb1, []int{109} } func (m *Invoice) XXX_Unmarshal(b []byte) error { @@ -8609,7 +8765,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{107} + return fileDescriptor_77a6da22d6a3feb1, []int{110} } func (m *InvoiceHTLC) XXX_Unmarshal(b []byte) error { @@ -8722,7 +8878,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{108} + return fileDescriptor_77a6da22d6a3feb1, []int{111} } func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error { @@ -8784,7 +8940,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{109} + return fileDescriptor_77a6da22d6a3feb1, []int{112} } func (m *PaymentHash) XXX_Unmarshal(b []byte) error { @@ -8844,7 +9000,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{110} + return fileDescriptor_77a6da22d6a3feb1, []int{113} } func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error { @@ -8915,7 +9071,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{111} + return fileDescriptor_77a6da22d6a3feb1, []int{114} } func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error { @@ -8979,7 +9135,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{112} + return fileDescriptor_77a6da22d6a3feb1, []int{115} } func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error { @@ -9052,7 +9208,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{113} + return fileDescriptor_77a6da22d6a3feb1, []int{116} } func (m *Payment) XXX_Unmarshal(b []byte) error { @@ -9197,7 +9353,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{114} + return fileDescriptor_77a6da22d6a3feb1, []int{117} } func (m *HTLCAttempt) XXX_Unmarshal(b []byte) error { @@ -9268,7 +9424,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{115} + return fileDescriptor_77a6da22d6a3feb1, []int{118} } func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error { @@ -9308,7 +9464,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{116} + return fileDescriptor_77a6da22d6a3feb1, []int{119} } func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error { @@ -9346,7 +9502,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{117} + return fileDescriptor_77a6da22d6a3feb1, []int{120} } func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error { @@ -9377,7 +9533,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{118} + return fileDescriptor_77a6da22d6a3feb1, []int{121} } func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error { @@ -9409,7 +9565,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{119} + return fileDescriptor_77a6da22d6a3feb1, []int{122} } func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error { @@ -9447,7 +9603,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{120} + return fileDescriptor_77a6da22d6a3feb1, []int{123} } func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error { @@ -9480,7 +9636,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{121} + return fileDescriptor_77a6da22d6a3feb1, []int{124} } func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error { @@ -9526,7 +9682,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{122} + return fileDescriptor_77a6da22d6a3feb1, []int{125} } func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error { @@ -9566,7 +9722,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{123} + return fileDescriptor_77a6da22d6a3feb1, []int{126} } func (m *PayReqString) XXX_Unmarshal(b []byte) error { @@ -9617,7 +9773,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{124} + return fileDescriptor_77a6da22d6a3feb1, []int{127} } func (m *PayReq) XXX_Unmarshal(b []byte) error { @@ -9742,7 +9898,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{125} + return fileDescriptor_77a6da22d6a3feb1, []int{128} } func (m *Feature) XXX_Unmarshal(b []byte) error { @@ -9794,7 +9950,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{126} + return fileDescriptor_77a6da22d6a3feb1, []int{129} } func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error { @@ -9837,7 +9993,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{127} + return fileDescriptor_77a6da22d6a3feb1, []int{130} } func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error { @@ -9915,7 +10071,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{128} + return fileDescriptor_77a6da22d6a3feb1, []int{131} } func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error { @@ -9993,7 +10149,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{129} + return fileDescriptor_77a6da22d6a3feb1, []int{132} } func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error { @@ -10111,7 +10267,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{130} + return fileDescriptor_77a6da22d6a3feb1, []int{133} } func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error { @@ -10156,7 +10312,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{131} + return fileDescriptor_77a6da22d6a3feb1, []int{134} } func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error { @@ -10239,7 +10395,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{132} + return fileDescriptor_77a6da22d6a3feb1, []int{135} } func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error { @@ -10339,7 +10495,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{133} + return fileDescriptor_77a6da22d6a3feb1, []int{136} } func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error { @@ -10386,7 +10542,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{134} + return fileDescriptor_77a6da22d6a3feb1, []int{137} } func (m *ExportChannelBackupRequest) XXX_Unmarshal(b []byte) error { @@ -10433,7 +10589,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{135} + return fileDescriptor_77a6da22d6a3feb1, []int{138} } func (m *ChannelBackup) XXX_Unmarshal(b []byte) error { @@ -10487,7 +10643,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{136} + return fileDescriptor_77a6da22d6a3feb1, []int{139} } func (m *MultiChanBackup) XXX_Unmarshal(b []byte) error { @@ -10532,7 +10688,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{137} + return fileDescriptor_77a6da22d6a3feb1, []int{140} } func (m *ChanBackupExportRequest) XXX_Unmarshal(b []byte) error { @@ -10571,7 +10727,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{138} + return fileDescriptor_77a6da22d6a3feb1, []int{141} } func (m *ChanBackupSnapshot) XXX_Unmarshal(b []byte) error { @@ -10619,7 +10775,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{139} + return fileDescriptor_77a6da22d6a3feb1, []int{142} } func (m *ChannelBackups) XXX_Unmarshal(b []byte) error { @@ -10661,7 +10817,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{140} + return fileDescriptor_77a6da22d6a3feb1, []int{143} } func (m *RestoreChanBackupRequest) XXX_Unmarshal(b []byte) error { @@ -10737,7 +10893,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{141} + return fileDescriptor_77a6da22d6a3feb1, []int{144} } func (m *RestoreBackupResponse) XXX_Unmarshal(b []byte) error { @@ -10768,7 +10924,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{142} + return fileDescriptor_77a6da22d6a3feb1, []int{145} } func (m *ChannelBackupSubscription) XXX_Unmarshal(b []byte) error { @@ -10799,7 +10955,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{143} + return fileDescriptor_77a6da22d6a3feb1, []int{146} } func (m *VerifyChanBackupResponse) XXX_Unmarshal(b []byte) error { @@ -10834,7 +10990,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{144} + return fileDescriptor_77a6da22d6a3feb1, []int{147} } func (m *MacaroonPermission) XXX_Unmarshal(b []byte) error { @@ -10881,7 +11037,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{145} + return fileDescriptor_77a6da22d6a3feb1, []int{148} } func (m *BakeMacaroonRequest) XXX_Unmarshal(b []byte) error { @@ -10921,7 +11077,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{146} + return fileDescriptor_77a6da22d6a3feb1, []int{149} } func (m *BakeMacaroonResponse) XXX_Unmarshal(b []byte) error { @@ -10977,7 +11133,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{147} + return fileDescriptor_77a6da22d6a3feb1, []int{150} } func (m *Failure) XXX_Unmarshal(b []byte) error { @@ -11121,7 +11277,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{148} + return fileDescriptor_77a6da22d6a3feb1, []int{151} } func (m *ChannelUpdate) XXX_Unmarshal(b []byte) error { @@ -11229,6 +11385,7 @@ func (m *ChannelUpdate) GetExtraOpaqueData() []byte { func init() { proto.RegisterEnum("lnrpc.AddressType", AddressType_name, AddressType_value) proto.RegisterEnum("lnrpc.CommitmentType", CommitmentType_name, CommitmentType_value) + proto.RegisterEnum("lnrpc.NodeMetricType", NodeMetricType_name, NodeMetricType_value) proto.RegisterEnum("lnrpc.InvoiceHTLCState", InvoiceHTLCState_name, InvoiceHTLCState_value) proto.RegisterEnum("lnrpc.FeatureBit", FeatureBit_name, FeatureBit_value) proto.RegisterEnum("lnrpc.ChannelCloseSummary_ClosureType", ChannelCloseSummary_ClosureType_name, ChannelCloseSummary_ClosureType_value) @@ -11349,6 +11506,10 @@ func init() { proto.RegisterType((*ChannelEdge)(nil), "lnrpc.ChannelEdge") proto.RegisterType((*ChannelGraphRequest)(nil), "lnrpc.ChannelGraphRequest") proto.RegisterType((*ChannelGraph)(nil), "lnrpc.ChannelGraph") + proto.RegisterType((*NodeMetricsRequest)(nil), "lnrpc.NodeMetricsRequest") + proto.RegisterType((*NodeMetricsResponse)(nil), "lnrpc.NodeMetricsResponse") + proto.RegisterMapType((map[string]*FloatValue)(nil), "lnrpc.NodeMetricsResponse.BetweennessCentralityEntry") + proto.RegisterType((*FloatValue)(nil), "lnrpc.FloatValue") proto.RegisterType((*ChanInfoRequest)(nil), "lnrpc.ChanInfoRequest") proto.RegisterType((*NetworkInfoRequest)(nil), "lnrpc.NetworkInfoRequest") proto.RegisterType((*NetworkInfo)(nil), "lnrpc.NetworkInfo") @@ -11412,723 +11573,735 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11447 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x8f, 0x23, 0x57, - 0x76, 0xd8, 0xf0, 0xd5, 0x24, 0x0f, 0x1f, 0x4d, 0xde, 0x7e, 0x71, 0x7a, 0x34, 0x9a, 0x51, 0x49, - 0x2b, 0xcd, 0x8e, 0x76, 0x7b, 0x46, 0xb3, 0x2b, 0xed, 0x5a, 0x8a, 0xd7, 0xcb, 0xee, 0x66, 0x4f, - 0x73, 0xa7, 0x5f, 0x2a, 0xb2, 0x25, 0x6b, 0x1d, 0xa7, 0xb6, 0x9a, 0xbc, 0xdd, 0x5d, 0x1e, 0xb2, - 0x8a, 0xaa, 0x2a, 0xf6, 0x63, 0x17, 0xca, 0x87, 0x20, 0x31, 0x82, 0x20, 0x09, 0x60, 0x24, 0x0e, - 0x10, 0x27, 0x46, 0x82, 0x18, 0x41, 0x10, 0x18, 0x30, 0x0c, 0xac, 0x03, 0x24, 0x40, 0xbe, 0xfb, - 0x4b, 0x02, 0x23, 0xb0, 0xf3, 0x25, 0x30, 0x0c, 0x18, 0x49, 0x9c, 0x6f, 0x81, 0x7f, 0x42, 0x70, - 0xcf, 0xb9, 0xb7, 0xea, 0x16, 0x59, 0x3d, 0x33, 0xda, 0x55, 0xf6, 0x4b, 0x37, 0xeb, 0xdc, 0x73, - 0x9f, 0x75, 0xee, 0xb9, 0xe7, 0x79, 0x0b, 0xca, 0xfe, 0x64, 0xb0, 0x31, 0xf1, 0xbd, 0xd0, 0x63, - 0x85, 0x91, 0xeb, 0x4f, 0x06, 0xeb, 0xaf, 0x9d, 0x79, 0xde, 0xd9, 0x88, 0x3f, 0xb2, 0x27, 0xce, - 0x23, 0xdb, 0x75, 0xbd, 0xd0, 0x0e, 0x1d, 0xcf, 0x0d, 0x08, 0xc9, 0xf8, 0x11, 0xd4, 0x9f, 0x72, - 0xb7, 0xc7, 0xf9, 0xd0, 0xe4, 0x9f, 0x4f, 0x79, 0x10, 0xb2, 0x77, 0xa1, 0x69, 0xf3, 0x1f, 0x73, - 0x3e, 0xb4, 0x26, 0x76, 0x10, 0x4c, 0xce, 0x7d, 0x3b, 0xe0, 0xad, 0xcc, 0xfd, 0xcc, 0x83, 0xaa, - 0xd9, 0xa0, 0x82, 0xa3, 0x08, 0xce, 0xde, 0x80, 0x6a, 0x20, 0x50, 0xb9, 0x1b, 0xfa, 0xde, 0xe4, - 0xba, 0x95, 0x45, 0xbc, 0x8a, 0x80, 0x75, 0x08, 0x64, 0x8c, 0x60, 0x31, 0xea, 0x21, 0x98, 0x78, - 0x6e, 0xc0, 0xd9, 0x63, 0x58, 0x1e, 0x38, 0x93, 0x73, 0xee, 0x5b, 0x58, 0x79, 0xec, 0xf2, 0xb1, - 0xe7, 0x3a, 0x83, 0x56, 0xe6, 0x7e, 0xee, 0x41, 0xd9, 0x64, 0x54, 0x26, 0x6a, 0xec, 0xcb, 0x12, - 0xf6, 0x0e, 0x2c, 0x72, 0x97, 0xe0, 0x7c, 0x88, 0xb5, 0x64, 0x57, 0xf5, 0x18, 0x2c, 0x2a, 0x18, - 0x7f, 0x3f, 0x0b, 0xcd, 0xae, 0xeb, 0x84, 0x9f, 0xda, 0xa3, 0x11, 0x0f, 0xd5, 0x9c, 0xde, 0x81, - 0xc5, 0x4b, 0x04, 0xe0, 0x9c, 0x2e, 0x3d, 0x7f, 0x28, 0x67, 0x54, 0x27, 0xf0, 0x91, 0x84, 0xde, - 0x38, 0xb2, 0xec, 0x8d, 0x23, 0x4b, 0x5d, 0xae, 0xdc, 0x0d, 0xcb, 0xf5, 0x0e, 0x2c, 0xfa, 0x7c, - 0xe0, 0x5d, 0x70, 0xff, 0xda, 0xba, 0x74, 0xdc, 0xa1, 0x77, 0xd9, 0xca, 0xdf, 0xcf, 0x3c, 0x28, - 0x98, 0x75, 0x05, 0xfe, 0x14, 0xa1, 0x6c, 0x13, 0x16, 0x07, 0xe7, 0xb6, 0xeb, 0xf2, 0x91, 0x75, - 0x62, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xab, 0x70, 0x3f, 0xf3, 0xa0, 0xf2, 0xe4, 0xf6, 0x06, 0xbe, - 0xd5, 0x8d, 0xad, 0x73, 0xdb, 0xdd, 0xc4, 0x92, 0x9e, 0x6b, 0x4f, 0x82, 0x73, 0x2f, 0x34, 0xeb, - 0xb2, 0x06, 0x81, 0x03, 0x63, 0x19, 0x98, 0xbe, 0x12, 0xb4, 0xf6, 0xc6, 0xef, 0x67, 0x60, 0xe9, - 0xd8, 0x1d, 0x79, 0x83, 0xe7, 0x3f, 0xe3, 0x12, 0xa5, 0xcc, 0x21, 0xfb, 0xaa, 0x73, 0xc8, 0x7d, - 0xd9, 0x39, 0xac, 0xc2, 0x72, 0x72, 0xb0, 0x72, 0x16, 0x1c, 0x56, 0x44, 0xed, 0x33, 0xae, 0x86, - 0xa5, 0xa6, 0xf1, 0x75, 0x68, 0x0c, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x79, 0x2c, 0x4a, 0x78, 0x34, - 0x91, 0x37, 0xa0, 0xea, 0xf2, 0xcb, 0x18, 0x4d, 0xd2, 0xae, 0xcb, 0x2f, 0x15, 0x8a, 0xd1, 0x82, - 0xd5, 0xd9, 0x6e, 0xe4, 0x00, 0xfe, 0x2a, 0x03, 0xf9, 0xe3, 0xf0, 0xca, 0x63, 0xef, 0x43, 0xd5, - 0x1e, 0x0e, 0x7d, 0x1e, 0x04, 0x56, 0x78, 0x3d, 0xa1, 0x9d, 0x52, 0x7f, 0xc2, 0xe4, 0x14, 0xdb, - 0x54, 0xd4, 0xbf, 0x9e, 0x70, 0xb3, 0x62, 0xc7, 0x0f, 0xac, 0x05, 0x45, 0xf9, 0x88, 0xfd, 0x96, - 0x4d, 0xf5, 0xc8, 0xee, 0x02, 0xd8, 0x63, 0x6f, 0xea, 0x86, 0x56, 0x60, 0x87, 0xb8, 0x62, 0x39, - 0xb3, 0x4c, 0x90, 0x9e, 0x1d, 0xb2, 0x3b, 0x50, 0x9e, 0x3c, 0xb7, 0x82, 0x81, 0xef, 0x4c, 0x42, - 0x24, 0x9e, 0xb2, 0x59, 0x9a, 0x3c, 0xef, 0xe1, 0x33, 0x7b, 0x17, 0x4a, 0xde, 0x34, 0x9c, 0x78, - 0x8e, 0x1b, 0x4a, 0x7a, 0x59, 0x94, 0x03, 0x39, 0x9c, 0x86, 0x47, 0x02, 0x6c, 0x46, 0x08, 0xec, - 0x2d, 0xa8, 0x0d, 0x3c, 0xf7, 0xd4, 0xf1, 0xc7, 0xc4, 0x11, 0x5a, 0x0b, 0xd8, 0x57, 0x12, 0x68, - 0xfc, 0x61, 0x16, 0x2a, 0x7d, 0xdf, 0x76, 0x03, 0x7b, 0x20, 0x00, 0x6c, 0x0d, 0x8a, 0xe1, 0x95, - 0x75, 0x6e, 0x07, 0xe7, 0x38, 0xd5, 0xb2, 0xb9, 0x10, 0x5e, 0xed, 0xda, 0xc1, 0x39, 0x5b, 0x85, - 0x05, 0x1a, 0x25, 0x4e, 0x28, 0x67, 0xca, 0x27, 0xb1, 0x41, 0xdc, 0xe9, 0xd8, 0x4a, 0x76, 0x95, - 0x43, 0x8a, 0x69, 0xb8, 0xd3, 0xf1, 0x96, 0x0e, 0x17, 0x93, 0x3f, 0x11, 0xaf, 0x9b, 0x3a, 0xa0, - 0xe9, 0x95, 0x11, 0x82, 0x7d, 0xbc, 0x01, 0x55, 0x59, 0xcc, 0x9d, 0xb3, 0x73, 0x9a, 0x63, 0xc1, - 0xac, 0x10, 0x02, 0x82, 0x44, 0x0b, 0xa1, 0x33, 0xe6, 0x56, 0x10, 0xda, 0xe3, 0x89, 0x9c, 0x52, - 0x59, 0x40, 0x7a, 0x02, 0x80, 0xc5, 0x5e, 0x68, 0x8f, 0xac, 0x53, 0xce, 0x83, 0x56, 0x51, 0x16, - 0x0b, 0xc8, 0x0e, 0xe7, 0x01, 0xfb, 0x1a, 0xd4, 0x87, 0x3c, 0x08, 0x2d, 0xf9, 0x32, 0x78, 0xd0, - 0x2a, 0xe1, 0xce, 0xaf, 0x09, 0x68, 0x5b, 0x01, 0xd9, 0x6b, 0x00, 0xbe, 0x7d, 0x69, 0x89, 0x85, - 0xe0, 0x57, 0xad, 0x32, 0xbd, 0x05, 0xdf, 0xbe, 0xec, 0x5f, 0xed, 0xf2, 0x2b, 0x41, 0x35, 0x4f, - 0x79, 0xa8, 0x2d, 0x5a, 0x20, 0xa9, 0xd3, 0xd8, 0x03, 0xa6, 0x81, 0xb7, 0x79, 0x68, 0x3b, 0xa3, - 0x80, 0x7d, 0x00, 0xd5, 0x50, 0x43, 0x46, 0x36, 0x58, 0x89, 0x48, 0x48, 0xab, 0x60, 0x26, 0xf0, - 0x8c, 0x73, 0x28, 0xed, 0x70, 0xbe, 0xe7, 0x8c, 0x9d, 0x90, 0xad, 0x42, 0xe1, 0xd4, 0xb9, 0xe2, - 0x44, 0xec, 0xb9, 0xdd, 0x5b, 0x26, 0x3d, 0xb2, 0x7b, 0x00, 0xf8, 0xc3, 0x1a, 0x47, 0xd4, 0xb4, - 0x7b, 0xcb, 0x2c, 0x23, 0x6c, 0x3f, 0xb0, 0x43, 0xb6, 0x0e, 0xc5, 0x09, 0xf7, 0x07, 0x5c, 0xbd, - 0xb7, 0xdd, 0x5b, 0xa6, 0x02, 0x6c, 0x16, 0xa1, 0x30, 0x12, 0xad, 0x1b, 0x7f, 0x5c, 0x80, 0x4a, - 0x8f, 0xbb, 0xd1, 0x2e, 0x63, 0x90, 0x17, 0x0b, 0x22, 0x77, 0x16, 0xfe, 0x66, 0x6f, 0x42, 0x05, - 0x97, 0x2e, 0x08, 0x7d, 0xc7, 0x3d, 0x23, 0xaa, 0xde, 0xcc, 0xb6, 0x32, 0x26, 0x08, 0x70, 0x0f, - 0xa1, 0xac, 0x01, 0x39, 0x7b, 0xac, 0xa8, 0x5a, 0xfc, 0x64, 0xb7, 0xa1, 0x64, 0x8f, 0x43, 0x1a, - 0x5e, 0x15, 0xc1, 0x45, 0x7b, 0x1c, 0xe2, 0xd0, 0xde, 0x80, 0xea, 0xc4, 0xbe, 0x1e, 0x8b, 0xbd, - 0x1c, 0x91, 0x43, 0xd5, 0xac, 0x48, 0x18, 0x12, 0xc4, 0x13, 0x58, 0xd2, 0x51, 0x54, 0xe7, 0x85, - 0xa8, 0xf3, 0xa6, 0x86, 0x2d, 0xc7, 0xf0, 0x0e, 0x2c, 0xaa, 0x3a, 0x3e, 0xcd, 0x07, 0xc9, 0xa4, - 0x6c, 0xd6, 0x25, 0x58, 0xcd, 0xf2, 0x01, 0x34, 0x4e, 0x1d, 0xd7, 0x1e, 0x59, 0x83, 0x51, 0x78, - 0x61, 0x0d, 0xf9, 0x28, 0xb4, 0x91, 0x62, 0x0a, 0x66, 0x1d, 0xe1, 0x5b, 0xa3, 0xf0, 0x62, 0x5b, - 0x40, 0xd9, 0x37, 0xa0, 0x7c, 0xca, 0xb9, 0x85, 0x8b, 0xd5, 0x2a, 0x25, 0x36, 0x9e, 0x7a, 0x43, - 0x66, 0xe9, 0x54, 0xbd, 0xab, 0x6f, 0x40, 0xc3, 0x9b, 0x86, 0x67, 0x9e, 0xe3, 0x9e, 0x59, 0x82, - 0xdf, 0x59, 0xce, 0x10, 0x69, 0x28, 0xbf, 0x99, 0x7d, 0x9c, 0x31, 0xeb, 0xaa, 0x4c, 0x70, 0x9e, - 0xee, 0x90, 0xbd, 0x0d, 0x8b, 0x23, 0x3b, 0x08, 0xad, 0x73, 0x6f, 0x62, 0x4d, 0xa6, 0x27, 0xcf, - 0xf9, 0x75, 0xab, 0x86, 0x0b, 0x51, 0x13, 0xe0, 0x5d, 0x6f, 0x72, 0x84, 0x40, 0x41, 0xd9, 0x38, - 0x4e, 0x1a, 0x04, 0xdc, 0xcf, 0x3c, 0xa8, 0x99, 0x65, 0x01, 0xa1, 0x4e, 0x3f, 0x83, 0x25, 0x7c, - 0x3d, 0x83, 0x69, 0x10, 0x7a, 0x63, 0x4b, 0xf0, 0x6a, 0x7f, 0x18, 0xb4, 0x2a, 0x48, 0x6b, 0x5f, - 0x97, 0x83, 0xd5, 0xde, 0xf1, 0xc6, 0x36, 0x0f, 0xc2, 0x2d, 0x44, 0x36, 0x09, 0x57, 0x1c, 0xe8, - 0xd7, 0x66, 0x73, 0x38, 0x0b, 0x67, 0xdf, 0x00, 0x66, 0x8f, 0x46, 0xde, 0xa5, 0x15, 0xf0, 0xd1, - 0xa9, 0x25, 0x17, 0xb1, 0x55, 0xbf, 0x9f, 0x79, 0x50, 0x32, 0x1b, 0x58, 0xd2, 0xe3, 0xa3, 0xd3, - 0x23, 0x82, 0xb3, 0x0f, 0x00, 0x37, 0x93, 0x75, 0xca, 0xed, 0x70, 0xea, 0xf3, 0xa0, 0xb5, 0x78, - 0x3f, 0xf7, 0xa0, 0xfe, 0xa4, 0x19, 0xad, 0x17, 0x82, 0x37, 0x9d, 0xd0, 0xac, 0x0a, 0x3c, 0xf9, - 0x1c, 0xac, 0x6f, 0xc3, 0x6a, 0xfa, 0x90, 0x04, 0x51, 0x89, 0x55, 0x11, 0xc4, 0x98, 0x37, 0xc5, - 0x4f, 0xb6, 0x0c, 0x85, 0x0b, 0x7b, 0x34, 0xe5, 0x92, 0xa7, 0xd3, 0xc3, 0x87, 0xd9, 0xef, 0x66, - 0x8c, 0x3f, 0xca, 0x40, 0x95, 0x66, 0x29, 0x65, 0x91, 0x37, 0xa1, 0xa6, 0xa8, 0x81, 0xfb, 0xbe, - 0xe7, 0x4b, 0xae, 0xa6, 0x28, 0xaf, 0x23, 0x60, 0xe2, 0x54, 0x51, 0x48, 0x13, 0x9f, 0x3b, 0x63, - 0xfb, 0x4c, 0x35, 0xad, 0x48, 0xe9, 0x48, 0x82, 0xd9, 0x7b, 0x71, 0x7b, 0xbe, 0x37, 0x0d, 0xb9, - 0x3c, 0xf3, 0xaa, 0x72, 0x7a, 0xa6, 0x80, 0x45, 0xad, 0xe3, 0xd3, 0x2b, 0xd0, 0xb9, 0xf1, 0xdb, - 0x19, 0x60, 0x62, 0xd8, 0x7d, 0x8f, 0x1a, 0x90, 0x14, 0x3a, 0x5b, 0x33, 0xf3, 0xca, 0x3b, 0x24, - 0xfb, 0xa2, 0x1d, 0x62, 0x40, 0x81, 0xc6, 0x9e, 0x4f, 0x19, 0x3b, 0x15, 0xfd, 0x20, 0x5f, 0xca, - 0x35, 0xf2, 0xc6, 0xff, 0xc8, 0xc1, 0xf2, 0x16, 0x1d, 0xd9, 0xed, 0xc1, 0x80, 0x4f, 0xa2, 0xbd, - 0x73, 0x0f, 0x2a, 0xae, 0x37, 0xe4, 0x8a, 0x62, 0x69, 0x60, 0x20, 0x40, 0x1a, 0xb9, 0x9e, 0xdb, - 0x8e, 0x4b, 0x03, 0xa7, 0xc5, 0x2c, 0x23, 0x04, 0x87, 0xfd, 0x36, 0x2c, 0x4e, 0xb8, 0x3b, 0xd4, - 0xb7, 0x08, 0x09, 0x55, 0x35, 0x09, 0x96, 0xbb, 0xe3, 0x1e, 0x54, 0x4e, 0xa7, 0x84, 0x27, 0x18, - 0x4b, 0x1e, 0x69, 0x00, 0x24, 0xa8, 0x4d, 0xfc, 0x65, 0x32, 0x0d, 0xce, 0xb1, 0xb4, 0x80, 0xa5, - 0x45, 0xf1, 0x2c, 0x8a, 0xee, 0x02, 0x0c, 0xa7, 0x41, 0x28, 0x77, 0xcc, 0x02, 0x16, 0x96, 0x05, - 0x84, 0x76, 0xcc, 0x37, 0x61, 0x69, 0x6c, 0x5f, 0x59, 0x48, 0x3b, 0x96, 0xe3, 0x5a, 0xa7, 0x23, - 0x3c, 0x73, 0x8a, 0x88, 0xd7, 0x18, 0xdb, 0x57, 0x9f, 0x88, 0x92, 0xae, 0xbb, 0x83, 0x70, 0xc1, - 0x56, 0x94, 0xb8, 0xe3, 0xf3, 0x80, 0xfb, 0x17, 0x1c, 0x39, 0x41, 0x3e, 0x92, 0x69, 0x4c, 0x82, - 0x8a, 0x11, 0x8d, 0xc5, 0xbc, 0xc3, 0xd1, 0x80, 0xb6, 0xbd, 0x59, 0x1c, 0x3b, 0xee, 0x6e, 0x38, - 0x1a, 0x88, 0x73, 0x45, 0xf0, 0x91, 0x09, 0xf7, 0xad, 0xe7, 0x97, 0xb8, 0x87, 0xf3, 0xc8, 0x37, - 0x8e, 0xb8, 0xff, 0xec, 0x52, 0x1c, 0xfd, 0x83, 0x00, 0x19, 0x91, 0x7d, 0xdd, 0xaa, 0xe0, 0x06, - 0x2f, 0x0d, 0x02, 0xc1, 0x82, 0xec, 0x6b, 0xb1, 0x09, 0xc5, 0x68, 0x6d, 0x7c, 0x0b, 0x7c, 0x88, - 0xcd, 0x07, 0xc8, 0x51, 0x6b, 0x38, 0xd8, 0xb6, 0x2c, 0x10, 0xfd, 0x04, 0x82, 0xea, 0xd5, 0x60, - 0x4f, 0x47, 0xf6, 0x59, 0x80, 0x2c, 0xa5, 0x66, 0x56, 0x25, 0x70, 0x47, 0xc0, 0x8c, 0x4f, 0x49, - 0xc8, 0xd2, 0xde, 0xad, 0xdc, 0x33, 0xe2, 0xa8, 0x47, 0x08, 0xbe, 0xd7, 0x92, 0x29, 0x9f, 0xd2, - 0x5e, 0x5a, 0x36, 0xe5, 0xa5, 0x19, 0xbf, 0x9b, 0x81, 0xaa, 0x6c, 0x19, 0x85, 0x12, 0xb6, 0x01, - 0x4c, 0xbd, 0xc5, 0xf0, 0xca, 0x19, 0x5a, 0x27, 0xd7, 0x21, 0x0f, 0x88, 0x68, 0x76, 0x6f, 0x99, - 0x0d, 0x59, 0xd6, 0xbf, 0x72, 0x86, 0x9b, 0xa2, 0x84, 0x3d, 0x84, 0x46, 0x02, 0x3f, 0x08, 0x7d, - 0xa2, 0xe8, 0xdd, 0x5b, 0x66, 0x5d, 0xc3, 0xee, 0x85, 0xbe, 0xd8, 0x23, 0x42, 0xe4, 0x99, 0x86, - 0x96, 0xe3, 0x0e, 0xf9, 0x15, 0x92, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x2b, 0x40, 0x9b, 0x75, 0xa8, - 0xea, 0xcd, 0x19, 0x67, 0x50, 0x52, 0xf2, 0x12, 0x0a, 0x0c, 0x33, 0x43, 0x32, 0xcb, 0x61, 0x34, - 0x92, 0xdb, 0x50, 0x4a, 0x8e, 0xc0, 0x2c, 0x86, 0xaf, 0xdc, 0xb1, 0xf1, 0x3d, 0x68, 0xec, 0x09, - 0xe2, 0x71, 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x15, 0x16, 0xb4, 0x4d, 0x53, 0x36, 0xe5, 0x93, 0x38, - 0x73, 0xcf, 0xbd, 0x20, 0x94, 0xbd, 0xe0, 0x6f, 0xe3, 0x8f, 0x33, 0xc0, 0x3a, 0x41, 0xe8, 0x8c, - 0xed, 0x90, 0xef, 0xf0, 0x88, 0x2d, 0x1c, 0x42, 0x55, 0xb4, 0xd6, 0xf7, 0xda, 0x24, 0x90, 0x91, - 0x40, 0xf1, 0xae, 0xdc, 0xc6, 0xf3, 0x15, 0x36, 0x74, 0x6c, 0x62, 0xf3, 0x89, 0x06, 0xc4, 0x2e, - 0x0b, 0x6d, 0xff, 0x8c, 0x87, 0x28, 0xc6, 0x49, 0x79, 0x1f, 0x08, 0x24, 0x04, 0xb8, 0xf5, 0x5f, - 0x81, 0xe6, 0x5c, 0x1b, 0x3a, 0x5f, 0x2e, 0xa7, 0xf0, 0xe5, 0x9c, 0xce, 0x97, 0x2d, 0x58, 0x4a, - 0x8c, 0x4b, 0x52, 0xda, 0x1a, 0x14, 0xc5, 0x86, 0x10, 0xc2, 0x41, 0x86, 0xa4, 0xca, 0x53, 0xce, - 0x85, 0x18, 0xfc, 0x08, 0x96, 0x4f, 0x39, 0xf7, 0xed, 0x10, 0x0b, 0x71, 0xc7, 0x88, 0x37, 0x24, - 0x1b, 0x6e, 0xca, 0xb2, 0x9e, 0x1d, 0x1e, 0x71, 0x5f, 0xbc, 0x29, 0xe3, 0x7f, 0x66, 0x60, 0x51, - 0x70, 0xd0, 0x7d, 0xdb, 0xbd, 0x56, 0xeb, 0xb4, 0x97, 0xba, 0x4e, 0x0f, 0xb4, 0xc3, 0x50, 0xc3, - 0xfe, 0xb2, 0x8b, 0x94, 0x9b, 0x5d, 0x24, 0x76, 0x1f, 0xaa, 0x89, 0xb1, 0x16, 0x70, 0xac, 0x10, - 0x44, 0x83, 0xfc, 0xf9, 0x97, 0xf1, 0x6d, 0x68, 0xc4, 0xc3, 0x96, 0x6b, 0xc8, 0x20, 0x2f, 0x48, - 0x52, 0x36, 0x80, 0xbf, 0x8d, 0x7f, 0x99, 0x21, 0xc4, 0x2d, 0xcf, 0x89, 0xa4, 0x53, 0x81, 0x28, - 0xe4, 0x5e, 0x85, 0x28, 0x7e, 0xdf, 0x28, 0xd5, 0xff, 0xfc, 0x93, 0x15, 0x5b, 0x27, 0xe0, 0xee, - 0xd0, 0xb2, 0x47, 0x23, 0x64, 0xbe, 0x25, 0xb3, 0x28, 0x9e, 0xdb, 0xa3, 0x91, 0xf1, 0x0e, 0x34, - 0xb5, 0xd1, 0xbd, 0x60, 0x1e, 0x07, 0xc0, 0xf6, 0x9c, 0x20, 0x3c, 0x76, 0x83, 0x89, 0x26, 0xb8, - 0xdd, 0x81, 0xb2, 0xe0, 0xb0, 0x62, 0x64, 0xb4, 0x65, 0x0b, 0xa6, 0x60, 0xb9, 0x62, 0x5c, 0x01, - 0x16, 0xda, 0x57, 0xb2, 0x30, 0x2b, 0x0b, 0xed, 0x2b, 0x2c, 0x34, 0xbe, 0x0b, 0x4b, 0x89, 0xf6, - 0x64, 0xd7, 0x6f, 0x40, 0x61, 0x1a, 0x5e, 0x79, 0x4a, 0x34, 0xaf, 0x48, 0x0a, 0x11, 0x0a, 0xa0, - 0x49, 0x25, 0xc6, 0x47, 0xd0, 0x3c, 0xe0, 0x97, 0x72, 0x13, 0xab, 0x81, 0xbc, 0x0d, 0xf9, 0x97, - 0x28, 0x85, 0x58, 0x6e, 0x6c, 0x00, 0xd3, 0x2b, 0xcb, 0x5e, 0x35, 0x1d, 0x31, 0x93, 0xd0, 0x11, - 0x8d, 0xb7, 0x81, 0xf5, 0x9c, 0x33, 0x77, 0x9f, 0x07, 0x81, 0x7d, 0x16, 0x6d, 0xfb, 0x06, 0xe4, - 0xc6, 0xc1, 0x99, 0xe4, 0x51, 0xe2, 0xa7, 0xf1, 0x2d, 0x58, 0x4a, 0xe0, 0xc9, 0x86, 0x5f, 0x83, - 0x72, 0xe0, 0x9c, 0xb9, 0x28, 0x58, 0xc9, 0xa6, 0x63, 0x80, 0xb1, 0x03, 0xcb, 0x9f, 0x70, 0xdf, - 0x39, 0xbd, 0x7e, 0x59, 0xf3, 0xc9, 0x76, 0xb2, 0xb3, 0xed, 0x74, 0x60, 0x65, 0xa6, 0x1d, 0xd9, - 0x3d, 0x91, 0xaf, 0x7c, 0x93, 0x25, 0x93, 0x1e, 0x34, 0xbe, 0x97, 0xd5, 0xf9, 0x9e, 0x71, 0x0c, - 0x6c, 0xcb, 0x73, 0x5d, 0x3e, 0x08, 0x8f, 0x38, 0xf7, 0x63, 0x2b, 0x55, 0x4c, 0xab, 0x95, 0x27, - 0x6b, 0x72, 0x65, 0x67, 0x99, 0xa9, 0x24, 0x62, 0x06, 0xf9, 0x09, 0xf7, 0xc7, 0xd8, 0x70, 0xc9, - 0xc4, 0xdf, 0xc6, 0x0a, 0x2c, 0x25, 0x9a, 0x95, 0x7a, 0xfd, 0x63, 0x58, 0xd9, 0x76, 0x82, 0xc1, - 0x7c, 0x87, 0x6b, 0x50, 0x9c, 0x4c, 0x4f, 0xac, 0x24, 0x5f, 0x7e, 0xc6, 0xaf, 0x85, 0xb6, 0x37, - 0x5b, 0x43, 0xb6, 0xf5, 0x77, 0x33, 0x90, 0xdf, 0xed, 0xef, 0x6d, 0xb1, 0x75, 0x28, 0x39, 0xee, - 0xc0, 0x1b, 0x0b, 0xc1, 0x8b, 0xe6, 0x1c, 0x3d, 0xdf, 0xb8, 0xc1, 0xee, 0x40, 0x19, 0xe5, 0x35, - 0xa1, 0xda, 0x4a, 0xd1, 0xa7, 0x24, 0x00, 0x7b, 0xde, 0xe0, 0xb9, 0xd0, 0xa9, 0xf9, 0xd5, 0xc4, - 0xf1, 0x51, 0x6b, 0x56, 0xca, 0x70, 0x9e, 0xce, 0xfa, 0xb8, 0x80, 0x34, 0x62, 0xe3, 0x3f, 0x95, - 0xa0, 0x28, 0x4f, 0x5b, 0x3a, 0xb9, 0x43, 0xe7, 0x82, 0xc7, 0x27, 0xb7, 0x78, 0x12, 0xf2, 0x80, - 0xcf, 0xc7, 0x5e, 0x18, 0x09, 0x6c, 0xf4, 0x0e, 0xaa, 0x04, 0x94, 0x22, 0x9b, 0x26, 0x34, 0x90, - 0x89, 0x21, 0x47, 0x48, 0x03, 0xfd, 0x28, 0xbf, 0x03, 0x45, 0x75, 0xf6, 0xe7, 0x23, 0x9d, 0x66, - 0x61, 0x40, 0xd2, 0xda, 0x3a, 0x94, 0x06, 0xf6, 0xc4, 0x1e, 0x38, 0xe1, 0xb5, 0x64, 0x08, 0xd1, - 0xb3, 0x68, 0x7d, 0xe4, 0x0d, 0xec, 0x91, 0x75, 0x62, 0x8f, 0x6c, 0x77, 0xc0, 0xa5, 0xee, 0x5e, - 0x45, 0xe0, 0x26, 0xc1, 0x84, 0x7e, 0x2e, 0xc7, 0xa9, 0xb0, 0x48, 0x85, 0x97, 0xa3, 0x57, 0x68, - 0x42, 0xb8, 0xf4, 0xc6, 0x63, 0x47, 0x68, 0x19, 0x24, 0x86, 0xe5, 0xcc, 0x32, 0x41, 0x76, 0x38, - 0xce, 0x56, 0x16, 0x5f, 0xd2, 0xd2, 0x95, 0xa9, 0x2b, 0x02, 0x7e, 0x4a, 0x86, 0x84, 0x79, 0x59, - 0x2c, 0xa7, 0xc9, 0x62, 0xef, 0x42, 0x73, 0xea, 0x06, 0x3c, 0x0c, 0x47, 0x7c, 0x18, 0x8d, 0xa5, - 0x82, 0x48, 0x8d, 0xa8, 0x40, 0x0d, 0x67, 0x03, 0x96, 0xc8, 0xe8, 0x10, 0xd8, 0xa1, 0x17, 0x9c, - 0x3b, 0x81, 0x15, 0x08, 0x0d, 0x89, 0xd4, 0xdd, 0x26, 0x16, 0xf5, 0x64, 0x49, 0x8f, 0x54, 0xa4, - 0xb5, 0x19, 0x7c, 0x9f, 0x0f, 0xb8, 0x73, 0xc1, 0x87, 0x28, 0xa7, 0xe5, 0xcc, 0x95, 0x44, 0x1d, - 0x53, 0x16, 0xa2, 0xd0, 0x3d, 0x1d, 0x5b, 0xd3, 0xc9, 0xd0, 0x16, 0xc2, 0x4a, 0x9d, 0x84, 0x61, - 0x77, 0x3a, 0x3e, 0x26, 0x08, 0x7b, 0x0c, 0x4a, 0x12, 0x93, 0xf2, 0xe1, 0x62, 0x82, 0x9f, 0x09, - 0x62, 0x35, 0xab, 0x12, 0x83, 0x04, 0xc5, 0x84, 0xcc, 0xd9, 0x98, 0x91, 0x39, 0x5b, 0x50, 0x9c, - 0xf8, 0xce, 0x85, 0x1d, 0xf2, 0x56, 0x93, 0x18, 0xb8, 0x7c, 0x14, 0x9c, 0xc1, 0x71, 0x9d, 0xd0, - 0xb1, 0x43, 0xcf, 0x6f, 0x31, 0x2c, 0x8b, 0x01, 0xec, 0x21, 0x34, 0x91, 0x46, 0x82, 0xd0, 0x0e, - 0xa7, 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x21, 0x1c, 0x85, 0x50, 0xf6, 0x2d, - 0x58, 0x25, 0xb2, 0xc0, 0x1a, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x97, 0x62, 0x09, 0x4b, 0x05, - 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0xef, 0xc3, 0x9a, 0x24, 0x93, 0xb9, 0x5a, 0x2b, 0x58, 0x6b, - 0x99, 0x8a, 0x67, 0xaa, 0x6d, 0x40, 0x53, 0x0c, 0xc9, 0x19, 0x58, 0xb2, 0xb6, 0xd8, 0x09, 0xab, - 0x62, 0xf4, 0xa8, 0x29, 0x2d, 0x52, 0xa1, 0x89, 0x65, 0xcf, 0xf8, 0x35, 0xfb, 0x1e, 0x2c, 0x12, - 0xc9, 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, 0xa5, 0xc8, 0xec, - 0xeb, 0x83, 0xc4, 0xb3, 0xd8, 0x0e, 0x23, 0xe7, 0x94, 0x87, 0xce, 0x98, 0xb7, 0xd6, 0x88, 0xc0, - 0xd4, 0xb3, 0xd8, 0xa9, 0xd3, 0x09, 0x96, 0xb4, 0x88, 0x2f, 0xd0, 0x13, 0xd2, 0xee, 0xc8, 0x0b, - 0xb8, 0x32, 0x51, 0xb5, 0x6e, 0xcb, 0x4d, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, 0x38, 0x29, 0x3d, - 0x91, 0x21, 0xf1, 0x0e, 0x12, 0x43, 0x8d, 0x74, 0x1f, 0x65, 0x4c, 0x14, 0xa7, 0xf8, 0xb9, 0x7d, - 0xa9, 0x38, 0xc8, 0x6b, 0xf8, 0x7e, 0x41, 0x80, 0x24, 0xef, 0xf8, 0x69, 0x86, 0x0e, 0x44, 0xc9, - 0x3f, 0x02, 0x4d, 0xbd, 0x23, 0xce, 0x61, 0x79, 0xee, 0xe8, 0x5a, 0x32, 0x13, 0x20, 0xd0, 0xa1, - 0x3b, 0xc2, 0xdd, 0xec, 0xb8, 0x3a, 0x0a, 0xf1, 0xde, 0xaa, 0x02, 0x22, 0xd2, 0x3d, 0xa8, 0x4c, - 0xa6, 0x27, 0x23, 0x67, 0x40, 0x28, 0x39, 0x6a, 0x85, 0x40, 0x88, 0x20, 0xf4, 0x5b, 0xa2, 0x28, - 0xc2, 0xc8, 0x23, 0x46, 0x45, 0xc2, 0x10, 0x05, 0x79, 0x3b, 0xf7, 0x91, 0x9d, 0x54, 0x4d, 0xfc, - 0x6d, 0x6c, 0xc2, 0x72, 0x72, 0xd0, 0xf2, 0xe0, 0x79, 0x08, 0x25, 0xc9, 0xab, 0x94, 0xe1, 0xa3, - 0xae, 0x99, 0xa2, 0x85, 0x8a, 0x16, 0x95, 0x1b, 0xbf, 0xb9, 0x00, 0x4b, 0x12, 0xba, 0x25, 0x96, - 0xb6, 0x37, 0x1d, 0x8f, 0x6d, 0x3f, 0x85, 0x09, 0x66, 0x5e, 0xcc, 0x04, 0xb3, 0x73, 0x4c, 0x30, - 0xa9, 0xf9, 0x12, 0x0f, 0x4d, 0x6a, 0xbe, 0xe2, 0x5d, 0x92, 0x32, 0xa2, 0xdb, 0x41, 0x6b, 0x12, - 0xdc, 0x27, 0x7b, 0xeb, 0x1c, 0xcb, 0x2e, 0xa4, 0xb0, 0x6c, 0x9d, 0xe1, 0x2e, 0xcc, 0x30, 0xdc, - 0x37, 0x80, 0x88, 0x46, 0xbd, 0xfd, 0x22, 0xe9, 0x27, 0x08, 0x93, 0xc6, 0xd4, 0x77, 0x60, 0x71, - 0x96, 0xc7, 0x11, 0x33, 0xad, 0xa7, 0x70, 0x38, 0x67, 0xcc, 0xf1, 0xb4, 0xd2, 0x90, 0xcb, 0x92, - 0xc3, 0x39, 0x63, 0xbe, 0x87, 0x25, 0x0a, 0xbf, 0x03, 0x40, 0x7d, 0xe3, 0xa6, 0x01, 0xdc, 0x34, - 0x6f, 0x27, 0xdf, 0x85, 0xbe, 0xea, 0x1b, 0xe2, 0x61, 0xea, 0x73, 0xdc, 0x45, 0x65, 0xac, 0x89, - 0x1b, 0xe8, 0x19, 0xd4, 0xbd, 0x09, 0x77, 0xad, 0x98, 0xd7, 0x54, 0xb0, 0xa9, 0xb7, 0x5e, 0xd0, - 0x54, 0x57, 0xe1, 0x9a, 0x35, 0x51, 0x37, 0x7a, 0x64, 0xfb, 0xb4, 0xf0, 0x5c, 0x6b, 0xad, 0xfa, - 0x25, 0x5a, 0xab, 0x63, 0xe5, 0xe8, 0xd9, 0xf8, 0x07, 0x19, 0xa8, 0x68, 0xc3, 0x66, 0x2b, 0xd0, - 0xdc, 0x3a, 0x3c, 0x3c, 0xea, 0x98, 0xed, 0x7e, 0xf7, 0x93, 0x8e, 0xb5, 0xb5, 0x77, 0xd8, 0xeb, - 0x34, 0x6e, 0x09, 0xf0, 0xde, 0xe1, 0x56, 0x7b, 0xcf, 0xda, 0x39, 0x34, 0xb7, 0x14, 0x38, 0xc3, - 0x56, 0x81, 0x99, 0x9d, 0xfd, 0xc3, 0x7e, 0x27, 0x01, 0xcf, 0xb2, 0x06, 0x54, 0x37, 0xcd, 0x4e, - 0x7b, 0x6b, 0x57, 0x42, 0x72, 0x6c, 0x19, 0x1a, 0x3b, 0xc7, 0x07, 0xdb, 0xdd, 0x83, 0xa7, 0xd6, - 0x56, 0xfb, 0x60, 0xab, 0xb3, 0xd7, 0xd9, 0x6e, 0xe4, 0x59, 0x0d, 0xca, 0xed, 0xcd, 0xf6, 0xc1, - 0xf6, 0xe1, 0x41, 0x67, 0xbb, 0x51, 0x30, 0x7e, 0x09, 0xca, 0xf1, 0x44, 0x2b, 0x50, 0x3c, 0x3e, - 0x78, 0x76, 0x70, 0xf8, 0xe9, 0x41, 0xe3, 0x16, 0x2b, 0x43, 0x01, 0xfb, 0x6f, 0x64, 0x18, 0xc0, - 0x02, 0xf5, 0xd9, 0xc8, 0xb2, 0x12, 0xe4, 0x37, 0x0f, 0xfb, 0xbb, 0x8d, 0x9c, 0xf1, 0x17, 0x19, - 0x58, 0xc1, 0x29, 0x0f, 0x67, 0x99, 0xc0, 0x7d, 0xa8, 0x0c, 0x3c, 0x6f, 0x22, 0x34, 0xad, 0x58, - 0xa2, 0xd0, 0x41, 0x62, 0x83, 0x13, 0xf3, 0x3e, 0xf5, 0xfc, 0x01, 0x97, 0x3c, 0x00, 0x10, 0xb4, - 0x23, 0x20, 0x82, 0x06, 0x25, 0x11, 0x13, 0x06, 0xb1, 0x80, 0x0a, 0xc1, 0x08, 0x65, 0x15, 0x16, - 0x4e, 0x7c, 0x6e, 0x0f, 0xce, 0xe5, 0xee, 0x97, 0x4f, 0xec, 0xeb, 0xb1, 0x0d, 0x60, 0x20, 0x68, - 0x6a, 0xc4, 0x87, 0xb8, 0x05, 0x4a, 0xe6, 0xa2, 0x84, 0x6f, 0x49, 0xb0, 0x38, 0x8d, 0xec, 0x13, - 0xdb, 0x1d, 0x7a, 0x2e, 0x1f, 0x4a, 0x55, 0x23, 0x06, 0x18, 0x47, 0xb0, 0x3a, 0x3b, 0x3f, 0xc9, - 0x2f, 0x3e, 0xd0, 0xf8, 0x05, 0x49, 0xfe, 0xeb, 0x37, 0x93, 0x82, 0xc6, 0x3b, 0xfe, 0x51, 0x1e, - 0xf2, 0x42, 0x12, 0xbc, 0x51, 0x68, 0xd4, 0x45, 0xfb, 0xdc, 0x9c, 0xfb, 0x07, 0x4d, 0x0d, 0x24, - 0x22, 0x90, 0x3d, 0xab, 0x8c, 0x10, 0x14, 0x0d, 0xa2, 0x62, 0x9f, 0x0f, 0x2e, 0xa4, 0x41, 0x8b, - 0x8a, 0x4d, 0x3e, 0xb8, 0x40, 0x9d, 0xca, 0x0e, 0xa9, 0x2e, 0xed, 0xf7, 0x62, 0x60, 0x87, 0x58, - 0x53, 0x16, 0x61, 0xbd, 0x62, 0x54, 0x84, 0xb5, 0x5a, 0x50, 0x74, 0xdc, 0x13, 0x6f, 0xea, 0x0e, - 0x71, 0x7b, 0x97, 0x4c, 0xf5, 0x88, 0xde, 0x26, 0xe4, 0x44, 0xe2, 0x20, 0xa2, 0xdd, 0x5c, 0x12, - 0x80, 0xbe, 0x38, 0x8a, 0xde, 0x83, 0x72, 0x70, 0xed, 0x0e, 0xf4, 0x3d, 0xbc, 0x2c, 0xd7, 0x47, - 0xcc, 0x7e, 0xa3, 0x77, 0xed, 0x0e, 0x70, 0xc7, 0x96, 0x02, 0xf9, 0x8b, 0xbd, 0x0f, 0xa5, 0xc8, - 0xee, 0x4b, 0x1c, 0xf8, 0xb6, 0x5e, 0x43, 0x19, 0x7b, 0x49, 0xbd, 0x8e, 0x50, 0xd9, 0x23, 0x58, - 0x40, 0xe3, 0x6c, 0xd0, 0xaa, 0x62, 0x25, 0x25, 0xef, 0x8b, 0x61, 0xa0, 0xa3, 0x87, 0x0f, 0xd1, - 0x50, 0x6b, 0x4a, 0xb4, 0xf5, 0x67, 0x50, 0x4b, 0xb4, 0xa5, 0x2b, 0xd1, 0x35, 0x52, 0xa2, 0xdf, - 0xd2, 0x95, 0xe8, 0xf8, 0x24, 0x90, 0xd5, 0x74, 0xa5, 0xfa, 0x57, 0xa0, 0xa4, 0xa6, 0x22, 0xf6, - 0x9f, 0xdc, 0x3b, 0x56, 0xef, 0xb3, 0x83, 0xad, 0xc6, 0x2d, 0xb6, 0x08, 0x95, 0xf6, 0x16, 0x6e, - 0x69, 0x04, 0x64, 0x04, 0xca, 0x51, 0xbb, 0xd7, 0x8b, 0x20, 0x59, 0x63, 0x07, 0x1a, 0xb3, 0x23, - 0x15, 0x34, 0x19, 0x2a, 0x98, 0x34, 0x5d, 0xc7, 0x00, 0xa1, 0x22, 0x91, 0x35, 0x9a, 0xe4, 0x70, - 0x7a, 0x30, 0xde, 0x87, 0x86, 0x38, 0xd7, 0xc4, 0x52, 0x05, 0x9a, 0x09, 0x78, 0x24, 0x64, 0x3b, - 0xdd, 0x7c, 0x5d, 0x32, 0x2b, 0x04, 0xc3, 0xae, 0x8c, 0x0f, 0xa0, 0xa9, 0x55, 0x8b, 0x55, 0x5a, - 0x71, 0x56, 0xce, 0xaa, 0xb4, 0xa8, 0xc0, 0x50, 0x89, 0xb1, 0x06, 0x2b, 0xe2, 0xb1, 0x73, 0xc1, - 0xdd, 0xb0, 0x37, 0x3d, 0x21, 0x9f, 0xa3, 0xe3, 0xb9, 0x42, 0xb1, 0x29, 0x47, 0x25, 0x37, 0x13, - 0xf9, 0x86, 0xd4, 0x7e, 0xb3, 0x48, 0x1a, 0xeb, 0x5a, 0x0f, 0x58, 0x71, 0x03, 0xff, 0x26, 0xb4, - 0xe0, 0x72, 0x04, 0x12, 0xcb, 0x7a, 0xd4, 0xe9, 0x98, 0xd6, 0xe1, 0xc1, 0x5e, 0xf7, 0x40, 0x30, - 0x4a, 0xb1, 0xac, 0x08, 0xd8, 0xd9, 0x41, 0x48, 0xc6, 0x68, 0x40, 0xfd, 0x29, 0x0f, 0xbb, 0xee, - 0xa9, 0xa7, 0xfc, 0x6b, 0x7f, 0x55, 0x80, 0xc5, 0x08, 0x14, 0x6b, 0xd1, 0x17, 0xdc, 0x0f, 0x1c, - 0xcf, 0x45, 0x81, 0xb8, 0x6c, 0xaa, 0x47, 0x71, 0xba, 0x39, 0x43, 0xee, 0x86, 0x4e, 0x78, 0x6d, - 0x25, 0x4c, 0x6e, 0x75, 0x05, 0x96, 0xa7, 0xe8, 0x32, 0x14, 0xec, 0x91, 0x63, 0x2b, 0x57, 0x2d, - 0x3d, 0x08, 0xe8, 0xc0, 0x1b, 0x79, 0x3e, 0xca, 0xbe, 0x65, 0x93, 0x1e, 0xd8, 0x63, 0x58, 0x16, - 0x32, 0xb8, 0x6e, 0x07, 0x45, 0xfe, 0x41, 0xd6, 0x3f, 0xe6, 0x4e, 0xc7, 0x47, 0xb1, 0x2d, 0x54, - 0x94, 0x88, 0xb3, 0x53, 0xd4, 0x90, 0xc2, 0x52, 0x54, 0x81, 0xd4, 0xb9, 0xa6, 0x3b, 0x1d, 0xb7, - 0xb1, 0x24, 0xc2, 0x7f, 0x02, 0x2b, 0x02, 0x3f, 0x12, 0xaf, 0xa2, 0x1a, 0x8b, 0x58, 0x43, 0x34, - 0xd6, 0x95, 0x65, 0x51, 0x9d, 0x3b, 0x50, 0xa6, 0x51, 0x89, 0x37, 0x5e, 0x20, 0x31, 0x1e, 0x87, - 0xc2, 0xfd, 0x60, 0xce, 0xab, 0xba, 0x40, 0x82, 0xc0, 0x8c, 0x57, 0x55, 0xf3, 0xcb, 0x96, 0x66, - 0xfd, 0xb2, 0x4f, 0x60, 0xe5, 0x44, 0x90, 0xe0, 0x39, 0xb7, 0x87, 0xdc, 0xb7, 0x62, 0xc2, 0x26, - 0x75, 0x65, 0x49, 0x14, 0xee, 0x62, 0x59, 0xb4, 0x0f, 0x84, 0x9c, 0x23, 0xd8, 0x02, 0x1f, 0x5a, - 0xa1, 0x67, 0xa1, 0xf8, 0x83, 0x0c, 0xa6, 0x64, 0xd6, 0x08, 0xdc, 0xf7, 0xb6, 0x04, 0x30, 0x89, - 0x77, 0xe6, 0xdb, 0x93, 0x73, 0xa9, 0x50, 0x44, 0x78, 0x4f, 0x05, 0x90, 0xbd, 0x06, 0x45, 0x41, - 0xf2, 0x2e, 0x27, 0xe7, 0x17, 0x89, 0xec, 0x0a, 0xc4, 0xde, 0x82, 0x05, 0xec, 0x23, 0x68, 0x35, - 0x90, 0xde, 0xab, 0x31, 0x23, 0x77, 0x5c, 0x53, 0x96, 0x09, 0x61, 0x72, 0xea, 0x3b, 0xc4, 0x65, - 0xca, 0x26, 0xfe, 0x66, 0xdf, 0xd7, 0x58, 0xd6, 0x12, 0xd6, 0x55, 0xf2, 0xc0, 0x0c, 0xa5, 0xdd, - 0xc4, 0xbd, 0xbe, 0x52, 0x66, 0xf4, 0x83, 0x7c, 0xa9, 0xd2, 0xa8, 0x1a, 0xdf, 0x81, 0x02, 0xad, - 0x8e, 0x20, 0x42, 0x5c, 0xbb, 0x8c, 0x24, 0x42, 0x84, 0xb6, 0xa0, 0xe8, 0xf2, 0xf0, 0xd2, 0xf3, - 0x9f, 0x2b, 0xa3, 0xb4, 0x7c, 0x34, 0x7e, 0x8c, 0xd6, 0x94, 0xc8, 0xe3, 0x4e, 0x8a, 0xa1, 0x20, - 0x0f, 0x7a, 0xbd, 0xc1, 0xb9, 0x2d, 0x0d, 0x3c, 0x25, 0x04, 0xf4, 0xce, 0xed, 0x39, 0xf2, 0xc8, - 0xce, 0x3b, 0xdd, 0xdf, 0x82, 0xba, 0xf2, 0xf1, 0x07, 0xd6, 0x88, 0x9f, 0x86, 0x92, 0xdc, 0xab, - 0xd2, 0xc1, 0x1f, 0xec, 0xf1, 0xd3, 0xd0, 0xd8, 0x87, 0xa6, 0x24, 0xc8, 0xc3, 0x09, 0x57, 0x5d, - 0x7f, 0x37, 0x4d, 0x9e, 0xae, 0x3c, 0x59, 0x4a, 0x1e, 0xb4, 0x14, 0xbb, 0x90, 0x10, 0xb2, 0x8d, - 0x8f, 0x81, 0xe9, 0xc7, 0xb0, 0x6c, 0x4f, 0x4a, 0xb5, 0xca, 0x96, 0xaf, 0x5c, 0x62, 0x91, 0xec, - 0xec, 0x0c, 0xc5, 0xea, 0x04, 0xd3, 0xc1, 0x40, 0xc5, 0x5e, 0x94, 0x4c, 0xf5, 0x68, 0xfc, 0x69, - 0x06, 0x96, 0xb0, 0x31, 0xa5, 0x0f, 0x48, 0x26, 0xfb, 0x33, 0x0f, 0x52, 0xbc, 0x1f, 0x5d, 0xf6, - 0xa1, 0x87, 0x2f, 0x6f, 0x3d, 0xcd, 0xcf, 0x59, 0x4f, 0xbf, 0x0e, 0x8d, 0x21, 0x1f, 0x39, 0x18, - 0x86, 0xa3, 0x44, 0x09, 0xd2, 0x00, 0x16, 0x15, 0x5c, 0x6a, 0x83, 0xc6, 0x3f, 0xcb, 0x40, 0x93, - 0x24, 0x15, 0xd4, 0xab, 0xe5, 0x42, 0x7d, 0xa4, 0x14, 0x49, 0xc9, 0xaa, 0xe4, 0x9c, 0xe2, 0x13, - 0x1c, 0xa1, 0x84, 0xbc, 0x7b, 0x4b, 0x2a, 0x98, 0x12, 0xca, 0x3e, 0x44, 0x1d, 0xc6, 0xb5, 0x10, - 0x98, 0x12, 0xd6, 0x93, 0x7c, 0x29, 0xbb, 0xb7, 0x50, 0xc1, 0x71, 0x11, 0xb4, 0x59, 0x12, 0x9a, - 0xad, 0x00, 0x1b, 0x3b, 0x50, 0x4b, 0x74, 0x93, 0x30, 0xf1, 0x56, 0xc9, 0xc4, 0x3b, 0xe7, 0x46, - 0xc9, 0xce, 0xbb, 0x51, 0xfe, 0x5e, 0x1e, 0x98, 0x20, 0xa9, 0x99, 0xb7, 0x36, 0xe3, 0x83, 0xcc, - 0xce, 0xf9, 0x20, 0x1f, 0x03, 0xd3, 0x10, 0x94, 0x6b, 0x34, 0x17, 0xb9, 0x46, 0x1b, 0x31, 0xae, - 0xf4, 0x8c, 0x3e, 0x86, 0x65, 0x29, 0xd0, 0x46, 0x4e, 0x47, 0xb4, 0xdd, 0xd1, 0xfb, 0x61, 0x24, - 0xd9, 0x2a, 0xe7, 0x23, 0xda, 0xf1, 0x94, 0xff, 0x51, 0xe8, 0xe0, 0x64, 0xf2, 0x42, 0xff, 0xa3, - 0xd2, 0xbe, 0x35, 0x2a, 0x58, 0x78, 0x29, 0x15, 0x14, 0xe7, 0xa8, 0x40, 0xb3, 0xc0, 0x94, 0x92, - 0x16, 0x18, 0x03, 0x6a, 0xca, 0xcb, 0x48, 0xc1, 0x15, 0x24, 0xbd, 0x55, 0xa4, 0xab, 0x11, 0x03, - 0x2c, 0x1e, 0x40, 0x43, 0x99, 0x49, 0x22, 0x1b, 0x0f, 0x05, 0x0e, 0x48, 0x2b, 0xdb, 0x96, 0xb2, - 0xf4, 0x24, 0x2c, 0xea, 0x95, 0x19, 0x8b, 0xfa, 0xbb, 0xd0, 0x0c, 0x04, 0x11, 0x59, 0x53, 0x57, - 0x46, 0xf9, 0xf0, 0x21, 0xaa, 0x4e, 0x25, 0xb3, 0x81, 0x05, 0xc7, 0x31, 0x7c, 0xde, 0x7e, 0x51, - 0x4b, 0xb1, 0x5f, 0xbc, 0x1f, 0x3b, 0xe4, 0x82, 0x73, 0x67, 0x8c, 0x07, 0x77, 0x1c, 0x11, 0x23, - 0x17, 0xb8, 0x77, 0xee, 0x8c, 0x4d, 0xe5, 0xfd, 0x15, 0x0f, 0xc6, 0x7f, 0xcc, 0x40, 0x43, 0xd0, - 0x41, 0x82, 0xce, 0x7f, 0x09, 0x70, 0x47, 0xbe, 0x22, 0x99, 0x57, 0x04, 0xae, 0xa2, 0xf2, 0xef, - 0x00, 0x92, 0xad, 0x25, 0xf4, 0x44, 0x49, 0xe4, 0xad, 0x24, 0x91, 0xc7, 0x8c, 0x6c, 0xf7, 0x16, - 0x29, 0x00, 0x02, 0x92, 0xe6, 0x08, 0xcd, 0xa7, 0x38, 0x42, 0xb5, 0xad, 0xb0, 0x0b, 0xf0, 0x8c, - 0x5f, 0xef, 0x79, 0x03, 0xd4, 0xd0, 0xee, 0x02, 0x08, 0x82, 0x3c, 0xb5, 0xc7, 0x8e, 0xb4, 0xae, - 0x14, 0xcc, 0xf2, 0x73, 0x7e, 0xbd, 0x83, 0x00, 0xf1, 0x36, 0x44, 0x71, 0xbc, 0x1f, 0x0a, 0x66, - 0xe9, 0x39, 0xbf, 0xa6, 0xcd, 0x60, 0x41, 0xed, 0x19, 0xbf, 0xde, 0xe6, 0x24, 0xae, 0x79, 0xbe, - 0xa0, 0x04, 0xdf, 0xbe, 0x14, 0xf2, 0x59, 0xc2, 0x89, 0x59, 0xf1, 0xed, 0xcb, 0x67, 0xfc, 0x5a, - 0x39, 0x54, 0x8b, 0xa2, 0x7c, 0xe4, 0x0d, 0xe4, 0x09, 0xa4, 0xc2, 0x31, 0xe2, 0x41, 0x99, 0x0b, - 0xcf, 0xf1, 0xb7, 0xf1, 0xd7, 0x19, 0xa8, 0x89, 0xf1, 0x23, 0x83, 0x13, 0xeb, 0xae, 0xa2, 0x7a, - 0x32, 0x71, 0x54, 0xcf, 0x13, 0xc9, 0x1f, 0x88, 0x5b, 0x66, 0x6f, 0xe6, 0x96, 0xb8, 0xc0, 0xc4, - 0x2a, 0xdf, 0x83, 0x32, 0xed, 0x2d, 0xb1, 0x59, 0x73, 0x89, 0xb7, 0x94, 0x98, 0x90, 0x59, 0x42, - 0xb4, 0x67, 0x14, 0x44, 0xa0, 0x59, 0xea, 0x68, 0x89, 0xcb, 0x7e, 0x64, 0x9f, 0x4b, 0x79, 0x0d, - 0x85, 0x1b, 0x82, 0x08, 0x74, 0x33, 0xd8, 0xc2, 0x9c, 0x19, 0xec, 0x18, 0x2a, 0x1a, 0xd1, 0xa1, - 0xdd, 0x2f, 0x9a, 0x1d, 0x51, 0x68, 0x92, 0xaa, 0x12, 0xcb, 0xb3, 0x7b, 0xcb, 0xac, 0x0d, 0x74, - 0xc0, 0xe6, 0x02, 0xe4, 0x45, 0x25, 0xe3, 0x23, 0x68, 0x6a, 0xcd, 0x92, 0xba, 0x9a, 0x36, 0xe8, - 0x4c, 0x9a, 0x13, 0xfd, 0x9f, 0x67, 0x60, 0x59, 0xd6, 0xc6, 0x10, 0x31, 0x47, 0x9c, 0xe7, 0xfb, - 0xc1, 0x19, 0xfb, 0x25, 0xa8, 0x89, 0xd6, 0x2d, 0x9f, 0x9f, 0x39, 0x41, 0xc8, 0x95, 0x8f, 0x24, - 0x65, 0xf7, 0x08, 0xb6, 0x2e, 0x50, 0x4d, 0x89, 0xc9, 0x3e, 0x82, 0x0a, 0x56, 0x25, 0x85, 0x5a, - 0xbe, 0xb7, 0xd6, 0x7c, 0x45, 0x1a, 0xea, 0xee, 0x2d, 0x13, 0x82, 0xe8, 0x69, 0xb3, 0x0c, 0xc5, - 0xd0, 0x77, 0xce, 0xce, 0xb8, 0x6f, 0xac, 0x46, 0x43, 0x13, 0x5b, 0x91, 0xf7, 0x42, 0x3e, 0x11, - 0x52, 0x92, 0xf1, 0x5f, 0x32, 0x50, 0x91, 0x9b, 0xeb, 0x67, 0x76, 0x8c, 0xac, 0x6b, 0x31, 0x8e, - 0xa4, 0x3b, 0xc7, 0x21, 0x8d, 0xef, 0xc0, 0xe2, 0x58, 0x48, 0x4c, 0x42, 0xa2, 0x4f, 0x78, 0x45, - 0xea, 0x0a, 0x2c, 0x05, 0x96, 0x0d, 0x58, 0x42, 0xf9, 0x25, 0xb0, 0x42, 0x67, 0x64, 0xa9, 0x42, - 0x19, 0x4f, 0xd8, 0xa4, 0xa2, 0xbe, 0x33, 0xda, 0x97, 0x05, 0xe2, 0x18, 0x0f, 0x42, 0xfb, 0x8c, - 0x4b, 0xda, 0xa0, 0x07, 0xa3, 0x05, 0xab, 0x33, 0xc2, 0xbc, 0x52, 0x44, 0x7e, 0xbf, 0x09, 0x6b, - 0x73, 0x45, 0x52, 0x21, 0x89, 0xbc, 0x01, 0x23, 0x67, 0x7c, 0xe2, 0x45, 0xb6, 0xb2, 0x8c, 0xe6, - 0x0d, 0xd8, 0x13, 0x25, 0xca, 0x56, 0xc6, 0x61, 0x45, 0x11, 0x04, 0x1a, 0xbb, 0x22, 0x79, 0x3f, - 0x8b, 0xd2, 0xe8, 0x7b, 0x49, 0x4e, 0x36, 0xdb, 0x9d, 0x82, 0xeb, 0xe7, 0xe3, 0xd2, 0x64, 0x0e, - 0x16, 0xb0, 0xdf, 0x80, 0x56, 0x44, 0x77, 0x52, 0x80, 0xd2, 0x94, 0x17, 0xd1, 0xd3, 0x37, 0x5e, - 0xd2, 0x53, 0xc2, 0x8a, 0x82, 0x07, 0xe8, 0xaa, 0x22, 0x59, 0x6a, 0x30, 0xea, 0xeb, 0x02, 0x5e, - 0x57, 0x7d, 0xa1, 0x40, 0x34, 0xdf, 0x63, 0xfe, 0x95, 0xe6, 0x86, 0x16, 0xa2, 0x44, 0xb7, 0xe6, - 0x1d, 0xd9, 0x70, 0x54, 0xa4, 0xf7, 0x7b, 0x0e, 0xab, 0x97, 0xb6, 0x13, 0xaa, 0x39, 0x6a, 0xba, - 0x53, 0x01, 0xfb, 0x7b, 0xf2, 0x92, 0xfe, 0x3e, 0xa5, 0xca, 0x09, 0x11, 0x71, 0xf9, 0x72, 0x1e, - 0x18, 0xac, 0xff, 0x49, 0x16, 0xea, 0xc9, 0x56, 0xc4, 0xc6, 0x96, 0xcc, 0x4a, 0x09, 0x1d, 0x52, - 0x68, 0x97, 0x76, 0xdc, 0x03, 0x12, 0x36, 0xe6, 0x2d, 0xcc, 0xd9, 0x14, 0x0b, 0xb3, 0x6e, 0xd8, - 0xcd, 0xbd, 0xcc, 0x93, 0x96, 0x7f, 0x25, 0x4f, 0x5a, 0x21, 0xcd, 0x93, 0x76, 0xb3, 0xfb, 0x65, - 0xe1, 0x67, 0x72, 0xbf, 0x14, 0x5f, 0xe0, 0x7e, 0x49, 0x38, 0x8d, 0x4a, 0x33, 0x4e, 0xa3, 0xf5, - 0xbf, 0xce, 0x00, 0x9b, 0xa7, 0x65, 0xf6, 0x94, 0x4c, 0xed, 0x2e, 0x1f, 0x49, 0x3e, 0xf7, 0xcd, - 0x57, 0xdb, 0x0f, 0xea, 0xf5, 0xa9, 0xda, 0xec, 0x11, 0x2c, 0xe9, 0x31, 0xca, 0xba, 0xb6, 0x53, - 0x33, 0x99, 0x5e, 0x14, 0xeb, 0xc4, 0x9a, 0x93, 0x31, 0xff, 0x52, 0x27, 0x63, 0xe1, 0xa5, 0x4e, - 0xc6, 0x85, 0xa4, 0x93, 0x71, 0xfd, 0xbf, 0x65, 0x60, 0x29, 0x85, 0xe4, 0xbe, 0xba, 0x39, 0x0b, - 0x4a, 0x49, 0x30, 0xa1, 0xac, 0xa4, 0x14, 0x9d, 0xff, 0xec, 0x41, 0x25, 0xf6, 0x5b, 0xa9, 0x18, - 0xfe, 0x87, 0x2f, 0xe3, 0x05, 0x71, 0x0d, 0x53, 0xaf, 0xbe, 0xfe, 0x7b, 0x59, 0xa8, 0x68, 0x85, - 0x62, 0x15, 0x89, 0xc0, 0xb4, 0xd8, 0x0e, 0x92, 0x03, 0x50, 0x57, 0xbb, 0x07, 0xd2, 0x18, 0x4c, - 0xe5, 0xb4, 0x15, 0xe4, 0xa1, 0x8f, 0x08, 0x1b, 0xb0, 0xa4, 0xdc, 0x20, 0x3c, 0x0e, 0xe1, 0x92, - 0x27, 0x43, 0x53, 0x3a, 0x43, 0x78, 0x14, 0x11, 0xc6, 0x1e, 0x29, 0x09, 0x3e, 0x7e, 0x77, 0x48, - 0x98, 0x64, 0x69, 0x6d, 0x12, 0x39, 0xab, 0x97, 0x28, 0xa8, 0xf2, 0x3d, 0x58, 0x51, 0xc4, 0x9c, - 0xac, 0x41, 0xc6, 0x57, 0x26, 0x49, 0x59, 0xaf, 0xf2, 0x7d, 0xb8, 0x3b, 0x33, 0xa6, 0x99, 0xaa, - 0x14, 0x6b, 0x78, 0x3b, 0x31, 0x3a, 0xbd, 0x85, 0xf5, 0x9f, 0x40, 0x2d, 0xc1, 0xd6, 0xbe, 0xba, - 0x57, 0x3e, 0xab, 0x1f, 0xd3, 0x8a, 0xea, 0xfa, 0xf1, 0xfa, 0xff, 0xcd, 0x01, 0x9b, 0xe7, 0xac, - 0xbf, 0xc8, 0x21, 0xcc, 0x13, 0x66, 0x2e, 0x85, 0x30, 0xff, 0xbf, 0x9d, 0xf6, 0xef, 0x42, 0x53, - 0xe6, 0xb2, 0x68, 0xbe, 0x2c, 0xda, 0x9c, 0x8d, 0xa8, 0x40, 0x8d, 0xe2, 0x3b, 0xb3, 0x3e, 0xf5, - 0x52, 0x22, 0x7c, 0x5f, 0x13, 0x77, 0x66, 0x5c, 0xeb, 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, - 0x47, 0xd5, 0xac, 0xfe, 0xe4, 0x97, 0xbf, 0xf4, 0x61, 0xb7, 0xd1, 0xc6, 0xfa, 0x28, 0x63, 0x99, - 0xb2, 0x31, 0xe3, 0x3d, 0xa8, 0x68, 0x60, 0xf4, 0xef, 0x74, 0xf7, 0x37, 0x0f, 0x1b, 0xb7, 0x58, - 0x0d, 0xca, 0x66, 0x67, 0xeb, 0xf0, 0x93, 0x8e, 0xd9, 0xd9, 0x6e, 0x64, 0x58, 0x09, 0xf2, 0x7b, - 0x87, 0xbd, 0x7e, 0x23, 0x6b, 0xac, 0x43, 0x4b, 0xb6, 0x38, 0x6f, 0xeb, 0xfd, 0xed, 0x7c, 0x64, - 0x66, 0xc1, 0x42, 0xa9, 0x55, 0x7d, 0x0b, 0xaa, 0xba, 0x30, 0x22, 0x29, 0x62, 0xc6, 0x9d, 0x2a, - 0xf4, 0x29, 0x4f, 0xe3, 0xd5, 0x5b, 0x40, 0x4e, 0xb2, 0x61, 0x54, 0x8d, 0x24, 0xcc, 0x17, 0x78, - 0x55, 0x50, 0x78, 0x4e, 0x90, 0xe1, 0xdf, 0x80, 0x7a, 0xd2, 0xf0, 0x29, 0x39, 0x52, 0x9a, 0x7a, - 0x21, 0x6a, 0x27, 0x2c, 0xa1, 0xec, 0xfb, 0xd0, 0x98, 0x35, 0x9c, 0xca, 0x28, 0xe7, 0x1b, 0xea, - 0x2f, 0x3a, 0x49, 0x5b, 0x2a, 0xdb, 0x85, 0xe5, 0x34, 0x71, 0x0c, 0xe9, 0xe3, 0x66, 0xbd, 0x92, - 0xcd, 0x8b, 0x5c, 0xec, 0xbb, 0xd2, 0x3e, 0x5e, 0x48, 0xf3, 0x32, 0x6a, 0x8b, 0xbd, 0x41, 0xff, - 0x34, 0x4b, 0xf9, 0x05, 0x40, 0x0c, 0x63, 0x0d, 0xa8, 0x1e, 0x1e, 0x75, 0x0e, 0xac, 0xad, 0xdd, - 0xf6, 0xc1, 0x41, 0x67, 0xaf, 0x71, 0x8b, 0x31, 0xa8, 0xa3, 0x7b, 0x70, 0x3b, 0x82, 0x65, 0x04, - 0x4c, 0xfa, 0x29, 0x14, 0x2c, 0xcb, 0x96, 0xa1, 0xd1, 0x3d, 0x98, 0x81, 0xe6, 0x58, 0x0b, 0x96, - 0x8f, 0x3a, 0xe4, 0x51, 0x4c, 0xb4, 0x9b, 0x17, 0x22, 0xbe, 0x9c, 0xae, 0x10, 0xf1, 0x29, 0x27, - 0x4b, 0xee, 0x03, 0x25, 0xf9, 0xfe, 0x4e, 0x06, 0x56, 0x66, 0x0a, 0xe2, 0x48, 0x7b, 0x92, 0x7b, - 0x93, 0x12, 0x6f, 0x15, 0x81, 0x6a, 0x37, 0xbd, 0x0b, 0xcd, 0xc8, 0x56, 0x30, 0x73, 0x2a, 0x35, - 0xa2, 0x02, 0x85, 0xfc, 0x08, 0x96, 0x34, 0x93, 0xc3, 0x0c, 0xaf, 0x60, 0x5a, 0x91, 0xac, 0x60, - 0xac, 0x45, 0x11, 0xcd, 0x33, 0xa3, 0x1e, 0x52, 0xa2, 0x97, 0x5e, 0x10, 0xbb, 0x0f, 0x92, 0xe3, - 0x55, 0x8f, 0xec, 0xf1, 0x0c, 0x21, 0x24, 0x47, 0xab, 0xbf, 0x70, 0xd5, 0xfd, 0x1f, 0x2c, 0x00, - 0xfb, 0x78, 0xca, 0xfd, 0x6b, 0x8c, 0xa4, 0x0f, 0x5e, 0x16, 0x5a, 0xa6, 0xf4, 0xea, 0xec, 0x2b, - 0x65, 0xcb, 0xa4, 0x65, 0xab, 0xe4, 0x5f, 0x9e, 0xad, 0x52, 0x78, 0x59, 0xb6, 0xca, 0x9b, 0x50, - 0x73, 0xce, 0x5c, 0x4f, 0xb0, 0x42, 0x21, 0xb7, 0x06, 0xad, 0x85, 0xfb, 0xb9, 0x07, 0x55, 0xb3, - 0x2a, 0x81, 0x42, 0x6a, 0x0d, 0xd8, 0x47, 0x31, 0x12, 0x1f, 0x9e, 0x61, 0x66, 0x95, 0xce, 0x04, - 0x3b, 0xc3, 0x33, 0x2e, 0xcd, 0x08, 0xa8, 0x17, 0xa8, 0xca, 0x02, 0x1e, 0xb0, 0xb7, 0xa0, 0x1e, - 0x78, 0x53, 0xa1, 0x06, 0xa8, 0x65, 0x20, 0x07, 0x43, 0x95, 0xa0, 0x47, 0xca, 0x9b, 0xb4, 0x34, - 0x0d, 0xb8, 0x35, 0x76, 0x82, 0x40, 0x88, 0x67, 0x03, 0xcf, 0x0d, 0x7d, 0x6f, 0x24, 0x7d, 0x06, - 0xcd, 0x69, 0xc0, 0xf7, 0xa9, 0x64, 0x8b, 0x0a, 0xd8, 0xb7, 0xe3, 0x21, 0x4d, 0x6c, 0xc7, 0x0f, - 0x5a, 0x80, 0x43, 0x52, 0x33, 0x45, 0x69, 0xdb, 0x76, 0xfc, 0x68, 0x2c, 0xe2, 0x21, 0x98, 0xc9, - 0xa2, 0xa9, 0xcc, 0x66, 0xd1, 0xfc, 0x28, 0x3d, 0x8b, 0xa6, 0x86, 0x4d, 0x3f, 0x96, 0x4d, 0xcf, - 0xbf, 0xe2, 0x2f, 0x95, 0x4c, 0x33, 0x9f, 0x1c, 0x54, 0xff, 0x32, 0xc9, 0x41, 0x8b, 0x69, 0xc9, - 0x41, 0xef, 0x41, 0x05, 0xd3, 0x36, 0xac, 0x73, 0x47, 0xc8, 0x70, 0xe4, 0x03, 0x69, 0xe8, 0x79, - 0x1d, 0xbb, 0x8e, 0x1b, 0x9a, 0xe0, 0xab, 0x9f, 0xc1, 0x7c, 0x9e, 0x4e, 0xf3, 0x17, 0x98, 0xa7, - 0x23, 0xd3, 0x4b, 0x36, 0xa0, 0xa4, 0xde, 0x13, 0x63, 0x90, 0x3f, 0xf5, 0xbd, 0xb1, 0xb2, 0x0d, - 0x8b, 0xdf, 0xac, 0x0e, 0xd9, 0xd0, 0x93, 0x95, 0xb3, 0xa1, 0x67, 0xfc, 0x3a, 0x54, 0x34, 0x52, - 0x63, 0x6f, 0x90, 0x15, 0x4a, 0x68, 0x52, 0x52, 0xb6, 0xa4, 0x55, 0x2c, 0x4b, 0x68, 0x77, 0x28, - 0xf8, 0xcd, 0xd0, 0xf1, 0x39, 0x66, 0xd4, 0x59, 0x3e, 0xbf, 0xe0, 0x7e, 0xa0, 0x6c, 0xf5, 0x8d, - 0xa8, 0xc0, 0x24, 0xb8, 0xf1, 0xb7, 0x60, 0x29, 0xf1, 0x6e, 0x25, 0x8b, 0x78, 0x0b, 0x16, 0x70, - 0xdd, 0x94, 0x2f, 0x35, 0x99, 0x2f, 0x23, 0xcb, 0x30, 0x55, 0x9a, 0xdc, 0x0c, 0xd6, 0xc4, 0xf7, - 0x4e, 0xb0, 0x93, 0x8c, 0x59, 0x91, 0xb0, 0x23, 0xdf, 0x3b, 0x31, 0xfe, 0x3c, 0x07, 0xb9, 0x5d, - 0x6f, 0xa2, 0x87, 0x0f, 0x65, 0xe6, 0xc2, 0x87, 0xa4, 0x7a, 0x68, 0x45, 0xea, 0x9f, 0x94, 0xd9, - 0xd1, 0xc0, 0xae, 0x54, 0xc0, 0x07, 0x50, 0x17, 0x7c, 0x22, 0xf4, 0x84, 0x7e, 0x7d, 0x69, 0xfb, - 0x24, 0x10, 0xe7, 0x68, 0xf3, 0xd9, 0xe3, 0xb0, 0xef, 0xed, 0x10, 0x9c, 0x2d, 0x43, 0x2e, 0x52, - 0x5f, 0xb0, 0x58, 0x3c, 0xb2, 0x55, 0x58, 0xc0, 0x38, 0xd2, 0x6b, 0xe9, 0x2c, 0x94, 0x4f, 0xec, - 0x9b, 0xb0, 0x94, 0x6c, 0x97, 0x58, 0x91, 0x94, 0x8d, 0xf4, 0x86, 0x91, 0x27, 0xdd, 0x06, 0xc1, - 0x47, 0x08, 0x47, 0xc6, 0x1c, 0x9c, 0x72, 0x8e, 0x45, 0x1a, 0xd3, 0x2b, 0x25, 0x98, 0xde, 0x3d, - 0xa8, 0x84, 0xa3, 0x0b, 0x6b, 0x62, 0x5f, 0x8f, 0x3c, 0x7b, 0x28, 0xf7, 0x37, 0x84, 0xa3, 0x8b, - 0x23, 0x82, 0xb0, 0x47, 0x00, 0xe3, 0xc9, 0x44, 0xee, 0x3d, 0xb4, 0x57, 0xc7, 0xa4, 0xbc, 0x7f, - 0x74, 0x44, 0x24, 0x67, 0x96, 0xc7, 0x93, 0x09, 0xfd, 0x64, 0xdb, 0x50, 0x4f, 0xcd, 0x7a, 0xbb, - 0xab, 0xc2, 0x1e, 0xbd, 0xc9, 0x46, 0xca, 0xe6, 0xac, 0x0d, 0x74, 0xd8, 0xfa, 0xf7, 0x81, 0xfd, - 0x9c, 0xb9, 0x67, 0x7d, 0x28, 0x47, 0xe3, 0xd3, 0x53, 0xb7, 0x30, 0x90, 0xb9, 0x92, 0x48, 0xdd, - 0x6a, 0x0f, 0x87, 0xbe, 0xe0, 0x8b, 0x74, 0x60, 0x46, 0x2c, 0x1f, 0xb4, 0x13, 0xb3, 0x4d, 0x7c, - 0xdf, 0xf8, 0xcb, 0x0c, 0x14, 0x28, 0x8f, 0xec, 0x6d, 0x58, 0x24, 0xfc, 0x28, 0x14, 0x4b, 0xba, - 0x18, 0xe9, 0xdc, 0xed, 0xcb, 0x28, 0x2c, 0xb1, 0x2d, 0xb4, 0x1c, 0xd8, 0x6c, 0xf4, 0xe6, 0xb5, - 0x3c, 0xd8, 0x7b, 0x50, 0x8e, 0xba, 0xd6, 0x48, 0xa7, 0xa4, 0x7a, 0x66, 0xaf, 0x43, 0xfe, 0xdc, - 0x9b, 0x28, 0x3b, 0x0d, 0xc4, 0x2b, 0x69, 0x22, 0x3c, 0x1e, 0x8b, 0xe8, 0x83, 0x06, 0x2f, 0xed, - 0x0b, 0x51, 0x27, 0x48, 0x06, 0xf3, 0x73, 0x5c, 0x48, 0x99, 0xe3, 0x31, 0x2c, 0x0a, 0x3e, 0xa0, - 0xb9, 0xfa, 0x6f, 0x3e, 0x34, 0xbf, 0x2e, 0x24, 0xbc, 0xc1, 0x68, 0x3a, 0xe4, 0xba, 0xa5, 0x0c, - 0xe3, 0x82, 0x24, 0x5c, 0x49, 0xd6, 0xc6, 0x1f, 0x64, 0x88, 0xbf, 0x88, 0x76, 0xd9, 0x03, 0xc8, - 0x8b, 0xf3, 0x6d, 0xc6, 0x92, 0x1b, 0x45, 0x94, 0x0b, 0x3c, 0x13, 0x31, 0x30, 0x71, 0x7c, 0x3a, - 0x4e, 0xb6, 0x5e, 0x33, 0x2b, 0xee, 0x74, 0x1c, 0x19, 0x9a, 0xbe, 0xa6, 0xa6, 0x35, 0x63, 0xa4, - 0xa1, 0xd9, 0x47, 0xdb, 0x74, 0x43, 0x0b, 0x30, 0xca, 0x27, 0x4e, 0x4c, 0x25, 0x05, 0x0e, 0xcf, - 0xb8, 0x16, 0x58, 0xf4, 0x47, 0x59, 0xa8, 0x25, 0x46, 0x84, 0x11, 0x56, 0xe2, 0x00, 0x20, 0x37, - 0x82, 0x7c, 0xdf, 0x20, 0x40, 0x52, 0x50, 0xd7, 0xd6, 0x29, 0x9b, 0x58, 0xa7, 0x28, 0xa8, 0x21, - 0xa7, 0x07, 0x35, 0x3c, 0x86, 0x72, 0x9c, 0xfb, 0x9c, 0x1c, 0x92, 0xe8, 0x4f, 0xc5, 0xd5, 0xc7, - 0x48, 0x71, 0x18, 0x44, 0x41, 0x0f, 0x83, 0xf8, 0x9e, 0xe6, 0x35, 0x5f, 0xc0, 0x66, 0x8c, 0xb4, - 0x15, 0xfd, 0x85, 0xf8, 0xcc, 0x8d, 0x8f, 0xa0, 0xa2, 0x0d, 0x5e, 0xf7, 0x8e, 0x67, 0x12, 0xde, - 0xf1, 0x28, 0x03, 0x26, 0x1b, 0x67, 0xc0, 0x18, 0xbf, 0x99, 0x85, 0x9a, 0xd8, 0x5f, 0x8e, 0x7b, - 0x76, 0xe4, 0x8d, 0x9c, 0x01, 0xba, 0x15, 0xa2, 0x1d, 0x26, 0x05, 0x2d, 0xb5, 0xcf, 0xe4, 0x16, - 0x23, 0x39, 0x4b, 0x4f, 0xf4, 0x23, 0x26, 0x1d, 0x25, 0xfa, 0x19, 0x50, 0x13, 0x8c, 0xf1, 0xc4, - 0x0e, 0xb8, 0x96, 0x99, 0x6d, 0x56, 0x4e, 0x39, 0xdf, 0xb4, 0x03, 0xe2, 0x90, 0xdf, 0x84, 0x25, - 0x81, 0x83, 0x39, 0x4e, 0x63, 0x67, 0x34, 0x72, 0x08, 0x93, 0x0c, 0x4d, 0x8d, 0x53, 0xce, 0x4d, - 0x3b, 0xe4, 0xfb, 0xa2, 0x40, 0x26, 0x72, 0x97, 0x86, 0x4e, 0x60, 0x9f, 0xc4, 0x71, 0x70, 0xd1, - 0x33, 0x3a, 0x03, 0xed, 0x2b, 0xcd, 0x19, 0x48, 0x06, 0x88, 0xca, 0xd8, 0xbe, 0x8a, 0x9c, 0x81, - 0x33, 0x94, 0x54, 0x9c, 0xa5, 0x24, 0xe3, 0x3f, 0x67, 0xa1, 0xa2, 0x91, 0xe5, 0xab, 0x9c, 0xae, - 0x77, 0xe7, 0xdc, 0x40, 0x65, 0xdd, 0xe3, 0xf3, 0x66, 0xb2, 0x4b, 0x8c, 0x19, 0xa0, 0x94, 0x71, - 0x8d, 0x80, 0xef, 0x40, 0x59, 0xec, 0xba, 0xf7, 0xd0, 0x60, 0x2a, 0x2f, 0x3c, 0x40, 0xc0, 0xd1, - 0xf4, 0x44, 0x15, 0x3e, 0xc1, 0xc2, 0x42, 0x5c, 0xf8, 0x44, 0x14, 0xbe, 0x28, 0xf8, 0xf5, 0x3b, - 0x50, 0x95, 0xad, 0xe2, 0x3b, 0xc5, 0xe9, 0xc6, 0xbb, 0x3e, 0xf1, 0xbe, 0xcd, 0x0a, 0x75, 0x47, - 0x2f, 0x5f, 0x56, 0x7c, 0xa2, 0x2a, 0x96, 0x5e, 0x56, 0xf1, 0x09, 0x3d, 0x18, 0x3b, 0x51, 0x3c, - 0x31, 0xc6, 0xab, 0x28, 0x3e, 0xf6, 0x08, 0x96, 0x14, 0xbb, 0x9a, 0xba, 0xb6, 0xeb, 0x7a, 0x53, - 0x77, 0xc0, 0x55, 0x6a, 0x0c, 0x93, 0x45, 0xc7, 0x71, 0x89, 0x31, 0x8c, 0x72, 0x27, 0x29, 0xee, - 0xe5, 0x21, 0x14, 0x48, 0x2e, 0x27, 0xe1, 0x23, 0x9d, 0x71, 0x11, 0x0a, 0x7b, 0x00, 0x05, 0x12, - 0xcf, 0xb3, 0x37, 0x32, 0x1b, 0x42, 0x30, 0x36, 0x60, 0x11, 0x45, 0x4c, 0x8d, 0xe3, 0xbe, 0x48, - 0x2a, 0x31, 0x96, 0x81, 0x1d, 0xd0, 0x26, 0xd2, 0xe3, 0xb1, 0xfe, 0x7b, 0x0e, 0x2a, 0x1a, 0x58, - 0xb0, 0x45, 0x8c, 0xe0, 0xb1, 0x86, 0x8e, 0x3d, 0xe6, 0xca, 0x37, 0x55, 0x33, 0x6b, 0x08, 0xdd, - 0x96, 0x40, 0x71, 0x28, 0xd8, 0x17, 0x67, 0x96, 0x37, 0x0d, 0xad, 0x21, 0x3f, 0xf3, 0x39, 0x97, - 0xc2, 0x52, 0xd5, 0xbe, 0x38, 0x3b, 0x9c, 0x86, 0xdb, 0x08, 0x13, 0x58, 0x82, 0xa8, 0x35, 0x2c, - 0x19, 0x74, 0x32, 0xb6, 0xaf, 0x62, 0x2c, 0x19, 0xf9, 0x44, 0x4b, 0x94, 0x8f, 0x22, 0x9f, 0x48, - 0x6d, 0x99, 0xe5, 0xe4, 0x85, 0x79, 0x4e, 0xfe, 0x6d, 0x58, 0x25, 0x4e, 0x2e, 0x79, 0x84, 0x35, - 0x43, 0x52, 0xcb, 0x58, 0x2a, 0x27, 0xa9, 0xc9, 0x5f, 0x0d, 0x31, 0x03, 0xb5, 0x3f, 0x02, 0xe7, - 0xc7, 0xb4, 0xa3, 0x32, 0xa6, 0x98, 0x99, 0x6c, 0xbc, 0xe7, 0xfc, 0x98, 0x0b, 0x4c, 0xf4, 0xac, - 0xeb, 0x98, 0x32, 0xc6, 0x7a, 0xec, 0xb8, 0xb3, 0x98, 0xf6, 0x55, 0x12, 0xb3, 0x2c, 0x31, 0xed, - 0x2b, 0x1d, 0xf3, 0x7d, 0x58, 0x1b, 0xf3, 0xa1, 0x63, 0x27, 0x9b, 0xb5, 0x62, 0x09, 0x62, 0x99, - 0x8a, 0xb5, 0x3a, 0x3d, 0xd2, 0x20, 0xc5, 0x6a, 0xfc, 0xd8, 0x1b, 0x9f, 0x38, 0x74, 0x78, 0x92, - 0xaf, 0x3f, 0x6f, 0xd6, 0xdd, 0xe9, 0xf8, 0x87, 0x08, 0x16, 0x55, 0x02, 0xa3, 0x06, 0x95, 0x5e, - 0xe8, 0x4d, 0xd4, 0x6b, 0xae, 0x43, 0x95, 0x1e, 0x65, 0xe2, 0xd3, 0x1d, 0xb8, 0x8d, 0xb4, 0xd9, - 0xf7, 0x26, 0xde, 0xc8, 0x3b, 0xbb, 0x4e, 0x18, 0x94, 0xfe, 0x6b, 0x06, 0x96, 0x12, 0xa5, 0x72, - 0x9f, 0x7f, 0x9b, 0x36, 0x56, 0x94, 0xbd, 0x42, 0xe4, 0xdc, 0xd4, 0x0e, 0x1f, 0x42, 0xa4, 0x5d, - 0xa5, 0x32, 0x5a, 0xda, 0x71, 0xd6, 0xb5, 0xaa, 0x48, 0xb4, 0xdd, 0x9a, 0xa7, 0x6d, 0x59, 0x5f, - 0xe5, 0x63, 0xab, 0x26, 0x7e, 0x59, 0xc6, 0xc1, 0x0f, 0xe5, 0x94, 0x73, 0xc9, 0x48, 0x5f, 0xdd, - 0xf8, 0xa4, 0x46, 0x10, 0x5b, 0xa4, 0x02, 0xe3, 0xdf, 0x64, 0x00, 0xe2, 0xd1, 0x61, 0xac, 0x71, - 0x74, 0x80, 0xd2, 0x85, 0x46, 0xda, 0x61, 0xf9, 0x06, 0x54, 0xa3, 0x90, 0xc3, 0xf8, 0x48, 0xae, - 0x28, 0x98, 0x38, 0x97, 0xdf, 0x81, 0xc5, 0xb3, 0x91, 0x77, 0x82, 0xa2, 0x93, 0x3c, 0x40, 0x29, - 0xfd, 0xab, 0x4e, 0x60, 0x75, 0x2c, 0xc6, 0x07, 0x78, 0x3e, 0x35, 0x2a, 0x51, 0x3f, 0x8e, 0x8d, - 0xdf, 0xca, 0x46, 0xb1, 0x57, 0xf1, 0x4a, 0xbc, 0x58, 0xcf, 0xf8, 0x59, 0x5c, 0xf8, 0x2f, 0xf2, - 0x4a, 0x7d, 0x04, 0x75, 0x9f, 0xb8, 0xa3, 0x62, 0x9d, 0xf9, 0x17, 0xb0, 0xce, 0x9a, 0x9f, 0x38, - 0x72, 0xbf, 0x0e, 0x0d, 0x7b, 0x78, 0xc1, 0xfd, 0xd0, 0x41, 0xb3, 0x31, 0x0a, 0x6a, 0x32, 0xda, - 0x49, 0x83, 0xa3, 0x44, 0xf4, 0x0e, 0x2c, 0xca, 0x64, 0xbc, 0x08, 0x53, 0x5e, 0xef, 0x11, 0x83, - 0x05, 0xa2, 0xf1, 0xef, 0x54, 0xb0, 0x57, 0xf2, 0xed, 0xbe, 0x78, 0x55, 0xf4, 0x19, 0x66, 0xe7, - 0xfd, 0x6e, 0x92, 0x90, 0xa4, 0x35, 0x5a, 0xf2, 0x23, 0x02, 0x4a, 0x5b, 0x74, 0x72, 0x59, 0xf3, - 0xaf, 0xb2, 0xac, 0xc6, 0x9f, 0x64, 0xa0, 0xb8, 0xeb, 0x4d, 0x84, 0x5e, 0x2e, 0xe4, 0x39, 0xdc, - 0x26, 0x91, 0xb3, 0x64, 0x41, 0x3c, 0x76, 0x87, 0x2f, 0xce, 0x39, 0x49, 0x95, 0x37, 0x6a, 0x49, - 0x79, 0xe3, 0x7b, 0x70, 0x07, 0x7d, 0x51, 0xbe, 0x37, 0xf1, 0x7c, 0xb1, 0x55, 0xed, 0x11, 0xc9, - 0x1d, 0x9e, 0x1b, 0x9e, 0x2b, 0xde, 0x79, 0xfb, 0x94, 0xf3, 0x23, 0x0d, 0x63, 0x3f, 0x42, 0xc0, - 0xac, 0xae, 0x51, 0x78, 0x61, 0x91, 0xaa, 0x28, 0x05, 0x23, 0xe2, 0xa8, 0x8b, 0xa2, 0xa0, 0x83, - 0x70, 0x14, 0x8d, 0x8c, 0xef, 0x42, 0x39, 0xb2, 0x3a, 0xb0, 0x77, 0xa1, 0x7c, 0xee, 0x4d, 0xa4, - 0x69, 0x22, 0x93, 0xc8, 0xcb, 0x91, 0xb3, 0x36, 0x4b, 0xe7, 0xf4, 0x23, 0x30, 0xfe, 0xbc, 0x08, - 0xc5, 0xae, 0x7b, 0xe1, 0x39, 0x03, 0x0c, 0x17, 0x1b, 0xf3, 0xb1, 0xa7, 0x32, 0x82, 0xc5, 0x6f, - 0x0c, 0x09, 0x89, 0x2f, 0xe9, 0xc8, 0xc9, 0x90, 0x90, 0xe8, 0x7a, 0x8e, 0x15, 0x58, 0xf0, 0xf5, - 0x5b, 0x36, 0x0a, 0x3e, 0x06, 0xb0, 0x46, 0x4a, 0x5b, 0x41, 0xcb, 0xa8, 0x16, 0x6d, 0xd1, 0xed, - 0x0f, 0xb8, 0x64, 0x94, 0xa1, 0x55, 0x46, 0x08, 0x2e, 0xd8, 0x6b, 0x50, 0x94, 0x69, 0x30, 0x94, - 0x54, 0x40, 0x11, 0xa7, 0x12, 0x84, 0xd4, 0xe0, 0x73, 0xf2, 0x25, 0x46, 0x12, 0x95, 0xd0, 0xd3, - 0x25, 0x70, 0x5b, 0xd0, 0xda, 0x3d, 0xa8, 0x10, 0x3e, 0xa1, 0x94, 0x64, 0x80, 0x17, 0x82, 0x10, - 0x21, 0xe5, 0xb2, 0x9a, 0x72, 0xea, 0x65, 0x35, 0x18, 0x0f, 0x18, 0x71, 0x59, 0x9a, 0x22, 0xd0, - 0x15, 0x25, 0x1a, 0x5c, 0xdd, 0xd4, 0x24, 0x95, 0x7b, 0x4a, 0x58, 0x54, 0xca, 0xfd, 0x9b, 0x50, - 0x3b, 0xb5, 0x47, 0xa3, 0x13, 0x7b, 0xf0, 0x9c, 0x74, 0xd2, 0x2a, 0x99, 0xe1, 0x14, 0x10, 0x95, - 0xd2, 0x7b, 0x50, 0xd1, 0xde, 0x32, 0x46, 0x6f, 0xe5, 0x4d, 0x88, 0xdf, 0xef, 0xac, 0xa9, 0xa9, - 0xfe, 0x0a, 0xa6, 0x26, 0x2d, 0x8a, 0x6d, 0x31, 0x19, 0xc5, 0x76, 0x07, 0xb9, 0xa9, 0x8c, 0x74, - 0x6a, 0xd0, 0x7d, 0x18, 0xf6, 0x70, 0x88, 0x91, 0x4e, 0x74, 0xf9, 0x1c, 0x2e, 0x1e, 0x95, 0x37, - 0x49, 0xa8, 0x25, 0x18, 0xa1, 0xdc, 0x25, 0x7b, 0xe9, 0xc4, 0x76, 0x86, 0x18, 0x35, 0x4c, 0x6a, - 0x6c, 0xd1, 0x1e, 0x87, 0x47, 0xb6, 0x33, 0x64, 0xf7, 0xa1, 0xaa, 0x8a, 0xf1, 0x74, 0x5c, 0xa2, - 0xf5, 0x97, 0xc5, 0xe2, 0x4c, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe3, 0xac, 0xc3, 0x8a, 0x44, 0x41, - 0x3a, 0x78, 0x0f, 0x83, 0x43, 0x42, 0x8e, 0xb9, 0x85, 0xf5, 0x27, 0x77, 0xe4, 0x5c, 0x25, 0x95, - 0xaa, 0xff, 0xe4, 0xa5, 0x21, 0x4c, 0x21, 0x88, 0x91, 0xb3, 0x68, 0x35, 0x21, 0x88, 0x49, 0x54, - 0x74, 0x16, 0x11, 0x02, 0xfb, 0xae, 0xa6, 0x48, 0xb5, 0x10, 0xf9, 0xb5, 0x99, 0xf6, 0x6f, 0x4a, - 0x9a, 0xb8, 0x0b, 0xe0, 0x04, 0xe2, 0x94, 0x09, 0xb8, 0x3b, 0xc4, 0x34, 0xc1, 0x92, 0x59, 0x76, - 0x82, 0x67, 0x04, 0xf8, 0x6a, 0x35, 0xac, 0x36, 0x54, 0xf5, 0x69, 0xb2, 0x12, 0xe4, 0x0f, 0x8f, - 0x3a, 0x07, 0x8d, 0x5b, 0xac, 0x02, 0xc5, 0x5e, 0xa7, 0xdf, 0xdf, 0x43, 0x97, 0x53, 0x15, 0x4a, - 0x51, 0x8e, 0x52, 0x56, 0x3c, 0xb5, 0xb7, 0xb6, 0x3a, 0x47, 0xfd, 0xce, 0x76, 0x23, 0xf7, 0x83, - 0x7c, 0x29, 0xdb, 0xc8, 0x19, 0x7f, 0x91, 0x83, 0x8a, 0xb6, 0x0a, 0x2f, 0x66, 0xc6, 0x77, 0x01, - 0x50, 0xa5, 0x89, 0x03, 0xe1, 0xf2, 0x66, 0x59, 0x40, 0xe8, 0xe5, 0xeb, 0xc6, 0xf2, 0x1c, 0x5d, - 0xb4, 0xa2, 0x8c, 0xe5, 0x6f, 0x42, 0x8d, 0xee, 0x2c, 0xd1, 0x1d, 0x87, 0x05, 0xb3, 0x4a, 0x40, - 0xc9, 0xaa, 0x31, 0xc9, 0x11, 0x91, 0x30, 0xfd, 0x45, 0xde, 0x60, 0x40, 0x20, 0x4c, 0x80, 0xc1, - 0xec, 0xa5, 0xc0, 0x1b, 0x5d, 0x70, 0xc2, 0x20, 0x89, 0xb0, 0x22, 0x61, 0x7d, 0x99, 0xae, 0x29, - 0xf9, 0xa1, 0x96, 0x65, 0x57, 0x30, 0xab, 0x04, 0x94, 0x1d, 0x7d, 0x53, 0x11, 0x50, 0x09, 0x09, - 0x68, 0x6d, 0x9e, 0x1a, 0x12, 0xc4, 0xb3, 0x37, 0x67, 0xcf, 0x2a, 0x23, 0x61, 0x7c, 0x6d, 0xbe, - 0xde, 0xcb, 0xed, 0x5a, 0xec, 0x5d, 0x60, 0xe3, 0xc9, 0xc4, 0x4a, 0xb1, 0x34, 0xe5, 0xcd, 0xc5, - 0xf1, 0x64, 0xd2, 0xd7, 0x0c, 0x31, 0x5f, 0x81, 0x11, 0xec, 0x73, 0x60, 0x6d, 0xb1, 0x81, 0x71, - 0x88, 0x91, 0x09, 0x35, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, 0x70, 0xbf, 0x6c, 0x2a, 0xf7, 0x7b, - 0x11, 0x9f, 0x30, 0x76, 0xa0, 0x72, 0xa4, 0xdd, 0x88, 0x74, 0x5f, 0x9c, 0x10, 0xea, 0x2e, 0x24, - 0x3a, 0x3b, 0xc8, 0xb8, 0xe5, 0xcb, 0x2b, 0x90, 0xb4, 0xd1, 0x64, 0xb5, 0xd1, 0x18, 0xff, 0x3a, - 0x43, 0xb7, 0x4d, 0x44, 0x83, 0x8f, 0x2f, 0x61, 0x52, 0x7e, 0xa0, 0x38, 0x19, 0xb6, 0xa2, 0xfc, - 0x3f, 0x32, 0x8f, 0x15, 0x87, 0x66, 0x79, 0xa7, 0xa7, 0x01, 0x57, 0xc1, 0x06, 0x15, 0x84, 0x1d, - 0x22, 0x48, 0x09, 0xdf, 0x42, 0xc2, 0x77, 0xa8, 0xfd, 0x40, 0x46, 0x18, 0x08, 0xe1, 0x7b, 0xdf, - 0xbe, 0x92, 0xbd, 0x06, 0x42, 0x04, 0x91, 0x86, 0x6a, 0x95, 0xcc, 0x16, 0x3d, 0x1b, 0xff, 0x42, - 0xe6, 0xeb, 0xce, 0xae, 0xef, 0x43, 0x28, 0x45, 0xad, 0x26, 0x4f, 0x58, 0x85, 0x19, 0x95, 0x8b, - 0x73, 0x1c, 0xb5, 0xf2, 0xc4, 0x88, 0x69, 0x73, 0xa1, 0xb3, 0xa1, 0xab, 0x8d, 0xfa, 0x1b, 0xc0, - 0x4e, 0x1d, 0x7f, 0x16, 0x99, 0x36, 0x5b, 0x03, 0x4b, 0x34, 0x6c, 0xe3, 0x18, 0x96, 0x14, 0x97, - 0xd0, 0x34, 0x82, 0xe4, 0xcb, 0xcb, 0xbc, 0x84, 0xc9, 0x67, 0xe7, 0x98, 0xbc, 0xf1, 0xd3, 0x3c, - 0x14, 0xd5, 0xed, 0x62, 0x69, 0x37, 0x62, 0x95, 0x93, 0x37, 0x62, 0xb5, 0x12, 0xb7, 0xa7, 0xe0, - 0xab, 0x97, 0xe7, 0xfd, 0x3b, 0xb3, 0x47, 0xb6, 0x66, 0x34, 0x4f, 0x1c, 0xdb, 0xab, 0x90, 0x9f, - 0xd8, 0xe1, 0x39, 0x1a, 0xc8, 0x88, 0x78, 0xf0, 0x59, 0x19, 0xd3, 0x0b, 0x49, 0x63, 0x7a, 0xda, - 0xed, 0x61, 0x24, 0x92, 0xce, 0xdd, 0x1e, 0x76, 0x07, 0x48, 0xbe, 0xd0, 0x62, 0xa5, 0x4a, 0x08, - 0x10, 0x67, 0x51, 0x52, 0x1c, 0x29, 0xcd, 0x8a, 0x23, 0xaf, 0x2c, 0x2a, 0x7c, 0x1b, 0x16, 0x28, - 0xf3, 0x5e, 0x26, 0xed, 0xa9, 0x03, 0x45, 0xae, 0xa1, 0xfa, 0x4f, 0x51, 0xd4, 0xa6, 0xc4, 0xd5, - 0xaf, 0xe2, 0xa9, 0x24, 0xae, 0xe2, 0xd1, 0x8d, 0xfc, 0xd5, 0xa4, 0x91, 0xff, 0x01, 0x34, 0xa2, - 0x05, 0x45, 0x93, 0x99, 0x1b, 0xc8, 0x94, 0xa0, 0xba, 0x82, 0x0b, 0x2e, 0x79, 0x10, 0xc4, 0x07, - 0x62, 0x3d, 0x71, 0x20, 0x0a, 0x1e, 0xd6, 0x0e, 0x43, 0x3e, 0x9e, 0x84, 0xf2, 0x40, 0xc4, 0xa4, - 0x01, 0x7d, 0x80, 0xc9, 0x74, 0xd6, 0x1a, 0x94, 0xbb, 0x07, 0xd6, 0xce, 0x5e, 0xf7, 0xe9, 0x6e, - 0xbf, 0x91, 0x11, 0x8f, 0xbd, 0xe3, 0xad, 0xad, 0x4e, 0x67, 0x1b, 0x4f, 0x1c, 0x80, 0x85, 0x9d, - 0x76, 0x57, 0x9c, 0x3e, 0x39, 0xe3, 0x77, 0xb2, 0x50, 0xd1, 0x9a, 0x67, 0xef, 0x47, 0xab, 0x42, - 0xb7, 0xb5, 0xdc, 0x9d, 0x1f, 0xc2, 0x86, 0x62, 0xc5, 0xda, 0xb2, 0x44, 0x77, 0xa5, 0x65, 0x6f, - 0xbc, 0x2b, 0x8d, 0xbd, 0x0d, 0x8b, 0x36, 0xb5, 0x10, 0xad, 0x82, 0x34, 0x07, 0x4b, 0xb0, 0x5c, - 0x04, 0x8c, 0x10, 0x8c, 0xcf, 0x13, 0x81, 0x97, 0x57, 0x41, 0x79, 0xd1, 0x91, 0x82, 0x8b, 0x55, - 0x3c, 0xb5, 0x9d, 0xd1, 0xd4, 0xe7, 0xd2, 0x7d, 0x1b, 0x9d, 0xcc, 0x04, 0x35, 0x55, 0xb1, 0xf1, - 0x01, 0x40, 0x3c, 0xe6, 0xe4, 0xe2, 0xdc, 0x4a, 0x2e, 0x4e, 0x46, 0x5b, 0x9c, 0xac, 0xb1, 0x4d, - 0x6c, 0x44, 0x2e, 0x74, 0xe4, 0xa9, 0xfe, 0x26, 0x28, 0x8b, 0x94, 0x85, 0x71, 0xba, 0x93, 0x11, - 0x0f, 0x55, 0xe2, 0x6f, 0x53, 0x96, 0x74, 0xa3, 0x02, 0x95, 0x87, 0x1f, 0xb7, 0x12, 0x73, 0x23, - 0x49, 0x92, 0xb3, 0xdc, 0x48, 0xa2, 0x9a, 0x51, 0xb9, 0xb1, 0x0e, 0xad, 0x6d, 0x2e, 0x5a, 0x6b, - 0x8f, 0x46, 0x33, 0xc3, 0x31, 0xee, 0xc0, 0xed, 0x94, 0x32, 0x69, 0x84, 0xf8, 0x18, 0x56, 0xda, - 0x94, 0xe3, 0xfb, 0x55, 0x25, 0xf3, 0x18, 0x2d, 0x58, 0x9d, 0x6d, 0x52, 0x76, 0xb6, 0x03, 0xcd, - 0x6d, 0x7e, 0x32, 0x3d, 0xdb, 0xe3, 0x17, 0x71, 0x47, 0x0c, 0xf2, 0xc1, 0xb9, 0x77, 0x29, 0xd7, - 0x07, 0x7f, 0x63, 0xb8, 0x9b, 0xc0, 0xb1, 0x82, 0x09, 0x1f, 0x28, 0x8b, 0x28, 0x42, 0x7a, 0x13, - 0x3e, 0x30, 0xde, 0x07, 0xa6, 0xb7, 0x23, 0xd7, 0x4b, 0x68, 0x09, 0xd3, 0x13, 0x2b, 0xb8, 0x0e, - 0x42, 0x3e, 0x56, 0x97, 0x01, 0x41, 0x30, 0x3d, 0xe9, 0x11, 0xc4, 0x78, 0x07, 0xaa, 0x47, 0xf6, - 0xb5, 0xc9, 0x3f, 0x97, 0x69, 0x2a, 0x6b, 0x50, 0x9c, 0xd8, 0xd7, 0x82, 0x0d, 0x44, 0xce, 0x11, - 0x2c, 0x36, 0xfe, 0x30, 0x0f, 0x0b, 0x84, 0xc9, 0xee, 0xd3, 0x7d, 0x9d, 0x8e, 0x8b, 0xdb, 0x50, - 0x31, 0x4a, 0x0d, 0x34, 0xc7, 0x4b, 0xb3, 0xf3, 0xbc, 0x54, 0x1a, 0xd0, 0xd4, 0x3d, 0x25, 0xca, - 0x8c, 0xed, 0x4e, 0xc7, 0xea, 0x72, 0x92, 0x64, 0xa2, 0x6b, 0x3e, 0xbe, 0x8f, 0x95, 0xb2, 0x00, - 0x93, 0x8e, 0xc6, 0x58, 0x17, 0xa1, 0xd1, 0xa9, 0x23, 0x42, 0xb2, 0x4b, 0x1d, 0x94, 0xaa, 0xf0, - 0x14, 0x55, 0x02, 0x54, 0x52, 0xe1, 0x99, 0x53, 0x6c, 0x4a, 0x2f, 0x57, 0x6c, 0xc8, 0xb2, 0xf6, - 0x02, 0xc5, 0x06, 0x5e, 0x41, 0xb1, 0x79, 0x05, 0x27, 0xdf, 0x6d, 0x28, 0xe1, 0xb9, 0xaf, 0x71, - 0x4f, 0x71, 0xde, 0x0b, 0xee, 0xf9, 0x1d, 0x4d, 0xf4, 0xa7, 0x08, 0x83, 0x3b, 0xf1, 0x36, 0x31, - 0xf9, 0xe7, 0xbf, 0x18, 0xe7, 0xc9, 0x67, 0x50, 0x94, 0x50, 0x41, 0xd0, 0xae, 0x3d, 0x56, 0x57, - 0x3d, 0xe1, 0x6f, 0xb1, 0x6c, 0x78, 0x3f, 0xcd, 0xe7, 0x53, 0xc7, 0xe7, 0x43, 0x75, 0x87, 0x87, - 0x83, 0x7b, 0x54, 0x40, 0xc4, 0x04, 0x85, 0x1a, 0xe2, 0x7a, 0x97, 0xae, 0xcc, 0xe0, 0x2f, 0x3a, - 0xc1, 0x33, 0xf1, 0x68, 0x30, 0x68, 0xe0, 0x65, 0x6f, 0x13, 0xcf, 0x57, 0x87, 0x93, 0xf1, 0xd3, - 0x0c, 0x34, 0xe4, 0xee, 0x8a, 0xca, 0x74, 0x2d, 0xa0, 0x70, 0x93, 0x43, 0xfc, 0xc5, 0x37, 0x72, - 0x18, 0x50, 0x43, 0xe3, 0x47, 0x74, 0x52, 0x91, 0xf1, 0xa6, 0x22, 0x80, 0x3b, 0xf2, 0xb4, 0x7a, - 0x1d, 0x2a, 0x2a, 0x18, 0x77, 0xec, 0x8c, 0xd4, 0xd5, 0xcb, 0x14, 0x8d, 0xbb, 0xef, 0x8c, 0xd4, - 0x41, 0xe7, 0xdb, 0x32, 0x21, 0x2f, 0x83, 0x07, 0x9d, 0x69, 0x87, 0xdc, 0xf8, 0x0f, 0x19, 0x68, - 0x6a, 0x53, 0x91, 0xfb, 0xf6, 0x43, 0xa8, 0x46, 0xb7, 0x2c, 0xf2, 0x48, 0xf2, 0x5a, 0x4b, 0x32, - 0x9a, 0xb8, 0x5a, 0x65, 0x10, 0x41, 0x02, 0x31, 0x98, 0xa1, 0x7d, 0x4d, 0x11, 0xa3, 0xd3, 0xb1, - 0x52, 0x6e, 0x86, 0xf6, 0xf5, 0x0e, 0xe7, 0xbd, 0xe9, 0x58, 0xa8, 0xae, 0x97, 0x9c, 0x3f, 0x8f, - 0x10, 0x48, 0xe6, 0x02, 0x01, 0x93, 0x18, 0x06, 0xd4, 0xc6, 0x9e, 0x1b, 0x9e, 0x47, 0x28, 0x52, - 0xea, 0x44, 0x20, 0xe1, 0x18, 0x7f, 0x96, 0x85, 0x25, 0x32, 0xb1, 0x49, 0xd3, 0xa6, 0x64, 0x5d, - 0x2d, 0x58, 0x20, 0x6b, 0x23, 0x31, 0xaf, 0xdd, 0x5b, 0xa6, 0x7c, 0x66, 0xdf, 0x7e, 0x45, 0xb3, - 0xa0, 0xca, 0xf9, 0xbb, 0x61, 0xf9, 0x73, 0xf3, 0xcb, 0x7f, 0xf3, 0xf2, 0xa6, 0x79, 0xdc, 0x0a, - 0x69, 0x1e, 0xb7, 0x57, 0xf1, 0x73, 0xcd, 0x25, 0xc6, 0x15, 0x25, 0x8e, 0x96, 0x18, 0xf7, 0x3e, - 0xac, 0x25, 0x70, 0x90, 0x5b, 0x3b, 0xa7, 0x0e, 0x57, 0x17, 0x24, 0x2c, 0x6b, 0xd8, 0x3d, 0x55, - 0xb6, 0x59, 0x84, 0x42, 0x30, 0xf0, 0x26, 0xdc, 0x58, 0x85, 0xe5, 0xe4, 0xaa, 0xca, 0x63, 0xe2, - 0x77, 0x33, 0xd0, 0x92, 0xf1, 0x11, 0x8e, 0x7b, 0xb6, 0xeb, 0x04, 0xa1, 0xe7, 0x47, 0xb7, 0x11, - 0xde, 0x05, 0x08, 0x42, 0xdb, 0x97, 0xda, 0xa6, 0xbc, 0x12, 0x00, 0x21, 0xa8, 0x49, 0xde, 0x86, - 0x12, 0x77, 0x87, 0x54, 0x48, 0xd4, 0x50, 0xe4, 0xee, 0x50, 0xe9, 0xa1, 0x73, 0xf2, 0x77, 0x2d, - 0xa9, 0x5e, 0xc8, 0x0c, 0x5d, 0xb1, 0x3a, 0xfc, 0x02, 0x0f, 0xde, 0x7c, 0x94, 0xa1, 0xbb, 0x6f, - 0x5f, 0x61, 0xb4, 0x61, 0x60, 0xfc, 0xd3, 0x2c, 0x2c, 0xc6, 0xe3, 0xa3, 0xf4, 0xfe, 0x17, 0x5f, - 0x54, 0x70, 0x5f, 0x92, 0x83, 0x23, 0xe4, 0x77, 0xcd, 0xf0, 0x58, 0xa2, 0xcd, 0xd9, 0x75, 0x99, - 0x01, 0x15, 0x85, 0xe1, 0x4d, 0x43, 0xed, 0x52, 0xb0, 0x32, 0xa1, 0x1c, 0x4e, 0x43, 0xa1, 0x70, - 0x09, 0xcd, 0xd3, 0x71, 0xa5, 0xca, 0x53, 0xb0, 0xc7, 0x61, 0x17, 0xef, 0x1a, 0x17, 0x60, 0x51, - 0x8d, 0x5e, 0xa4, 0xc0, 0x12, 0xf8, 0x0d, 0x92, 0xb3, 0xe9, 0xcd, 0xa1, 0x8c, 0xad, 0x0b, 0xa1, - 0x74, 0xed, 0x6a, 0x24, 0x84, 0xbe, 0x0e, 0x15, 0x6a, 0x3c, 0xce, 0x83, 0xcc, 0x9b, 0x65, 0xec, - 0x01, 0xcb, 0xa5, 0x11, 0xc8, 0x9b, 0x26, 0x54, 0x5f, 0xa0, 0xae, 0x30, 0xfc, 0xe0, 0x1f, 0x66, - 0xe0, 0x76, 0xca, 0x6b, 0x93, 0xbb, 0x7c, 0x0b, 0x9a, 0xa7, 0x51, 0xa1, 0x5a, 0x5d, 0xda, 0xea, - 0xab, 0x8a, 0xad, 0x26, 0xd7, 0xd4, 0x6c, 0x9c, 0x26, 0x01, 0xb1, 0xd2, 0x45, 0x6f, 0x30, 0x91, - 0xea, 0x8a, 0x4a, 0x17, 0xbd, 0x46, 0xd2, 0x77, 0x8e, 0x60, 0xbd, 0x73, 0x25, 0x38, 0xc6, 0x96, - 0x7e, 0x59, 0xbe, 0x22, 0xa3, 0xa4, 0x81, 0x39, 0xf3, 0x4a, 0x06, 0xe6, 0x21, 0x65, 0xf4, 0x45, - 0x6d, 0xfd, 0x2c, 0x8d, 0xe0, 0x01, 0x2a, 0xea, 0xd0, 0x65, 0xff, 0x2a, 0xdd, 0x76, 0x10, 0x5d, - 0xf2, 0x6f, 0x04, 0xb0, 0xb8, 0x3f, 0x1d, 0x85, 0x4e, 0x7c, 0xef, 0x3f, 0xfb, 0xb6, 0xac, 0x83, - 0xfd, 0xa8, 0x55, 0x4b, 0xed, 0x08, 0xa2, 0x8e, 0x70, 0xb1, 0xc6, 0xa2, 0x21, 0x6b, 0xbe, 0xbf, - 0xc5, 0x71, 0xb2, 0x07, 0xe3, 0x36, 0xac, 0xc5, 0x4f, 0xb4, 0x6c, 0xea, 0xa8, 0xf9, 0x57, 0x19, - 0x0a, 0x6d, 0x4e, 0x7e, 0x83, 0x80, 0x75, 0x60, 0x29, 0x70, 0xdc, 0xb3, 0x11, 0xd7, 0x9b, 0x0f, - 0xe4, 0x22, 0xac, 0x24, 0xc7, 0x26, 0xbf, 0x53, 0x60, 0x36, 0xa9, 0x46, 0xdc, 0x5a, 0xc0, 0x36, - 0x6f, 0x1a, 0x64, 0x4c, 0x16, 0x33, 0xab, 0x31, 0x3f, 0xf8, 0x2e, 0xd4, 0x93, 0x1d, 0xb1, 0xef, - 0xc8, 0x6c, 0xd6, 0x78, 0x54, 0xb9, 0x99, 0xbc, 0xc3, 0x98, 0x20, 0x2a, 0xf1, 0xda, 0x07, 0xc6, - 0x3f, 0xce, 0x40, 0xcb, 0xe4, 0x82, 0x72, 0xb5, 0x51, 0x2a, 0x9a, 0xf9, 0x70, 0xae, 0xd5, 0x9b, - 0xe7, 0xaa, 0x92, 0x64, 0xd5, 0x88, 0xbe, 0x71, 0xe3, 0xcb, 0xd8, 0xbd, 0x35, 0x37, 0xa3, 0xcd, - 0x12, 0x2c, 0x10, 0x8a, 0xb1, 0x06, 0x2b, 0x72, 0x3c, 0x6a, 0x2c, 0xb1, 0xf7, 0x30, 0xd1, 0x63, - 0xc2, 0x7b, 0xb8, 0x0e, 0x2d, 0xba, 0x54, 0x52, 0x9f, 0x84, 0xac, 0xb8, 0x0d, 0x6c, 0xdf, 0x1e, - 0xd8, 0xbe, 0xe7, 0xb9, 0x47, 0xdc, 0x97, 0x81, 0xa2, 0x28, 0x61, 0xa2, 0x73, 0x4d, 0x89, 0xc2, - 0xf4, 0xa4, 0xae, 0x42, 0xf4, 0x5c, 0x15, 0x17, 0x43, 0x4f, 0x86, 0x09, 0x4b, 0x9b, 0xf6, 0x73, - 0xae, 0x5a, 0x52, 0x4b, 0xf4, 0x11, 0x54, 0x26, 0x51, 0xa3, 0x6a, 0xdd, 0x55, 0xca, 0xfb, 0x7c, - 0xb7, 0xa6, 0x8e, 0x6d, 0x3c, 0x81, 0xe5, 0x64, 0x9b, 0x92, 0x75, 0xac, 0x43, 0x69, 0x2c, 0x61, - 0x72, 0x74, 0xd1, 0xb3, 0xf1, 0xdb, 0x25, 0x28, 0x4a, 0x7d, 0x8e, 0x6d, 0x40, 0x7e, 0xa0, 0x62, - 0x93, 0xe2, 0x9b, 0x54, 0x64, 0xa9, 0xfa, 0xbf, 0x85, 0x11, 0x4a, 0x02, 0x8f, 0x7d, 0x04, 0xf5, - 0xa4, 0x57, 0x74, 0x26, 0x9f, 0x36, 0xe9, 0xce, 0xac, 0x0d, 0x66, 0xfc, 0x5f, 0xe5, 0xf8, 0x70, - 0x24, 0x99, 0xa1, 0x74, 0xae, 0x9d, 0x9e, 0x9e, 0x2b, 0xe4, 0xed, 0xe0, 0xdc, 0xb6, 0x9e, 0xbc, - 0xff, 0x81, 0x4c, 0xa8, 0xad, 0x20, 0xb0, 0x77, 0x6e, 0x3f, 0x79, 0xff, 0x83, 0x59, 0x49, 0x5a, - 0xa6, 0xd3, 0x6a, 0x92, 0xf4, 0x32, 0x14, 0xe8, 0xce, 0x3f, 0x0a, 0x32, 0xa1, 0x07, 0xf6, 0x18, - 0x96, 0xa5, 0xda, 0x6a, 0xc9, 0x70, 0x60, 0xe2, 0x82, 0x25, 0xca, 0xc0, 0x92, 0x65, 0x3d, 0x2c, - 0x22, 0xdb, 0xd0, 0x2a, 0x2c, 0x9c, 0xc7, 0x17, 0x38, 0xd6, 0x4c, 0xf9, 0x64, 0xfc, 0x59, 0x01, - 0x2a, 0xda, 0xa2, 0xb0, 0x2a, 0x94, 0xcc, 0x4e, 0xaf, 0x63, 0x7e, 0xd2, 0xd9, 0x6e, 0xdc, 0x62, - 0x0f, 0xe0, 0xad, 0xee, 0xc1, 0xd6, 0xa1, 0x69, 0x76, 0xb6, 0xfa, 0xd6, 0xa1, 0x69, 0xa9, 0xfb, - 0x7c, 0x8e, 0xda, 0x9f, 0xed, 0x77, 0x0e, 0xfa, 0xd6, 0x76, 0xa7, 0xdf, 0xee, 0xee, 0xf5, 0x1a, - 0x19, 0xf6, 0x1a, 0xb4, 0x62, 0x4c, 0x55, 0xdc, 0xde, 0x3f, 0x3c, 0x3e, 0xe8, 0x37, 0xb2, 0xec, - 0x1e, 0xdc, 0xd9, 0xe9, 0x1e, 0xb4, 0xf7, 0xac, 0x18, 0x67, 0x6b, 0xaf, 0xff, 0x89, 0xd5, 0xf9, - 0xd5, 0xa3, 0xae, 0xf9, 0x59, 0x23, 0x97, 0x86, 0x20, 0x94, 0x71, 0xd5, 0x42, 0x9e, 0xdd, 0x86, - 0x15, 0x42, 0xa0, 0x2a, 0x56, 0xff, 0xf0, 0xd0, 0xea, 0x1d, 0x1e, 0x1e, 0x34, 0x0a, 0xac, 0x09, - 0xb5, 0xee, 0xc1, 0x27, 0xed, 0xbd, 0xee, 0xb6, 0x65, 0x76, 0xda, 0x7b, 0xfb, 0x8d, 0x05, 0xb6, - 0x04, 0x8b, 0xb3, 0x78, 0x45, 0xd1, 0x84, 0xc2, 0x3b, 0x3c, 0xe8, 0x1e, 0x1e, 0x58, 0x9f, 0x74, - 0xcc, 0x5e, 0xf7, 0xf0, 0xa0, 0x51, 0x62, 0xab, 0xc0, 0x92, 0x45, 0xbb, 0xfb, 0xed, 0xad, 0x46, - 0x99, 0xad, 0x40, 0x33, 0x09, 0x7f, 0xd6, 0xf9, 0xac, 0x01, 0xac, 0x05, 0xcb, 0x34, 0x30, 0x6b, - 0xb3, 0xb3, 0x77, 0xf8, 0xa9, 0xb5, 0xdf, 0x3d, 0xe8, 0xee, 0x1f, 0xef, 0x37, 0x2a, 0x78, 0xc3, - 0x58, 0xa7, 0x63, 0x75, 0x0f, 0x7a, 0xc7, 0x3b, 0x3b, 0xdd, 0xad, 0x6e, 0xe7, 0xa0, 0xdf, 0xa8, - 0x52, 0xcf, 0x69, 0x13, 0xaf, 0x89, 0x0a, 0x32, 0x67, 0xc0, 0xda, 0xee, 0xf6, 0xda, 0x9b, 0x7b, - 0x9d, 0xed, 0x46, 0x9d, 0xdd, 0x85, 0xdb, 0xfd, 0xce, 0xfe, 0xd1, 0xa1, 0xd9, 0x36, 0x3f, 0x53, - 0x39, 0x05, 0xd6, 0x4e, 0xbb, 0xbb, 0x77, 0x6c, 0x76, 0x1a, 0x8b, 0xec, 0x0d, 0xb8, 0x6b, 0x76, - 0x3e, 0x3e, 0xee, 0x9a, 0x9d, 0x6d, 0xeb, 0xe0, 0x70, 0xbb, 0x63, 0xed, 0x74, 0xda, 0xfd, 0x63, - 0xb3, 0x63, 0xed, 0x77, 0x7b, 0xbd, 0xee, 0xc1, 0xd3, 0x46, 0x83, 0xbd, 0x05, 0xf7, 0x23, 0x94, - 0xa8, 0x81, 0x19, 0xac, 0xa6, 0x98, 0x9f, 0x7a, 0xa5, 0x07, 0x9d, 0x5f, 0xed, 0x5b, 0x47, 0x9d, - 0x8e, 0xd9, 0x60, 0x6c, 0x1d, 0x56, 0xe3, 0xee, 0xa9, 0x03, 0xd9, 0xf7, 0x92, 0x28, 0x3b, 0xea, - 0x98, 0xfb, 0xed, 0x03, 0xf1, 0x82, 0x13, 0x65, 0xcb, 0x62, 0xd8, 0x71, 0xd9, 0xec, 0xb0, 0x57, - 0x18, 0x83, 0xba, 0xf6, 0x56, 0x76, 0xda, 0x66, 0x63, 0x95, 0x2d, 0x42, 0x65, 0xff, 0xe8, 0xc8, - 0xea, 0x77, 0xf7, 0x3b, 0x87, 0xc7, 0xfd, 0xc6, 0x1a, 0x5b, 0x81, 0x46, 0xf7, 0xa0, 0xdf, 0x31, - 0xc5, 0xbb, 0x56, 0x55, 0xff, 0x77, 0x91, 0x2d, 0xc3, 0xa2, 0x1a, 0xa9, 0x82, 0xfe, 0x55, 0x91, - 0xad, 0x01, 0x3b, 0x3e, 0x30, 0x3b, 0xed, 0x6d, 0xb1, 0x70, 0x51, 0xc1, 0xff, 0x29, 0x4a, 0x0f, - 0xc9, 0x4f, 0x73, 0xd1, 0x61, 0x1d, 0x87, 0x1c, 0x24, 0xaf, 0xf3, 0xad, 0x6a, 0xd7, 0xf0, 0xbe, - 0xec, 0xa2, 0x7d, 0x4d, 0xb5, 0xca, 0xcd, 0xa9, 0x56, 0x73, 0xba, 0x7b, 0x4d, 0x97, 0xfd, 0xde, - 0x84, 0xda, 0x98, 0xae, 0xf6, 0x95, 0x57, 0x78, 0x82, 0x8c, 0xbf, 0x21, 0x20, 0xdd, 0xdf, 0x39, - 0x77, 0xd3, 0x7c, 0x61, 0xfe, 0xa6, 0xf9, 0x34, 0xf9, 0x7e, 0x21, 0x4d, 0xbe, 0x7f, 0x08, 0x4d, - 0x62, 0x4d, 0x8e, 0xeb, 0x8c, 0x95, 0xd6, 0x4c, 0x52, 0xe0, 0x22, 0xb2, 0x28, 0x82, 0x2b, 0x75, - 0x42, 0xa9, 0x1c, 0x92, 0x85, 0x14, 0xa5, 0xb6, 0x91, 0xd0, 0x34, 0x88, 0x73, 0x44, 0x9a, 0x46, - 0xd4, 0x83, 0x7d, 0x15, 0xf7, 0x50, 0xd1, 0x7a, 0x20, 0x38, 0xf6, 0xf0, 0x10, 0x9a, 0xfc, 0x2a, - 0xf4, 0x6d, 0xcb, 0x9b, 0xd8, 0x9f, 0x4f, 0xd1, 0x85, 0x6b, 0xa3, 0x0e, 0x5f, 0x35, 0x17, 0xb1, - 0xe0, 0x10, 0xe1, 0xdb, 0x76, 0x68, 0x3f, 0xfc, 0x02, 0x2a, 0xda, 0xb5, 0xcf, 0x6c, 0x0d, 0x96, - 0x3e, 0xed, 0xf6, 0x0f, 0x3a, 0xbd, 0x9e, 0x75, 0x74, 0xbc, 0xf9, 0xac, 0xf3, 0x99, 0xb5, 0xdb, - 0xee, 0xed, 0x36, 0x6e, 0x89, 0x4d, 0x7b, 0xd0, 0xe9, 0xf5, 0x3b, 0xdb, 0x09, 0x78, 0x86, 0xbd, - 0x0e, 0xeb, 0xc7, 0x07, 0xc7, 0xbd, 0xce, 0xb6, 0x95, 0x56, 0x2f, 0x2b, 0xa8, 0x54, 0x96, 0xa7, - 0x54, 0xcf, 0x3d, 0xfc, 0x3e, 0xd4, 0x93, 0x77, 0x91, 0x32, 0x80, 0x85, 0xbd, 0xce, 0xd3, 0xf6, - 0xd6, 0x67, 0x74, 0x07, 0x61, 0xaf, 0xdf, 0xee, 0x77, 0xb7, 0x2c, 0x79, 0xe7, 0xa0, 0xe0, 0x08, - 0x19, 0x56, 0x81, 0x62, 0xfb, 0x60, 0x6b, 0xf7, 0xd0, 0xec, 0x35, 0xb2, 0x0f, 0x3f, 0x82, 0xc6, - 0xac, 0x3f, 0x2a, 0xe1, 0xc0, 0x7b, 0x91, 0xa7, 0xef, 0xe1, 0xbf, 0xcd, 0x01, 0xc4, 0x09, 0x03, - 0x82, 0xd5, 0x6c, 0xb7, 0xfb, 0xed, 0xbd, 0x43, 0x31, 0x0d, 0xf3, 0xb0, 0x2f, 0x38, 0x88, 0xd9, - 0xf9, 0xb8, 0x71, 0x2b, 0xb5, 0xe4, 0xf0, 0xa8, 0xdf, 0xc8, 0x88, 0x15, 0xeb, 0x1e, 0x74, 0xfb, - 0xdd, 0xf6, 0x9e, 0x65, 0x1e, 0x1e, 0x77, 0x0f, 0x9e, 0xd2, 0xe5, 0x6a, 0xc8, 0x65, 0x8f, 0x8f, - 0x76, 0xcc, 0xc3, 0x83, 0xbe, 0xd5, 0xdb, 0x3d, 0xee, 0x6f, 0xe3, 0xd5, 0x6c, 0x5b, 0x66, 0xf7, - 0x88, 0xda, 0xcc, 0xbf, 0x08, 0x41, 0x34, 0x5d, 0x10, 0x6b, 0xfe, 0xf4, 0xb0, 0xd7, 0xeb, 0x1e, - 0x59, 0x1f, 0x1f, 0x77, 0xcc, 0x6e, 0xa7, 0x87, 0x15, 0x17, 0x52, 0xe0, 0x02, 0xbf, 0x28, 0x78, - 0x73, 0x7f, 0xef, 0x13, 0xc9, 0x3c, 0x05, 0x6a, 0x29, 0x09, 0x12, 0x58, 0x65, 0xc1, 0x53, 0x04, - 0xf7, 0x49, 0x69, 0x19, 0x6e, 0x28, 0x13, 0xf5, 0x2a, 0x82, 0xaf, 0xce, 0xbd, 0x0c, 0xac, 0x56, - 0x4d, 0x2f, 0x12, 0xb5, 0x90, 0xe5, 0x46, 0x07, 0xd4, 0xf6, 0xb6, 0x89, 0x15, 0xea, 0x73, 0x50, - 0x81, 0xbb, 0x28, 0x5e, 0x94, 0x60, 0x4f, 0x02, 0xa5, 0xa1, 0x1e, 0x44, 0x49, 0xf3, 0xc9, 0x6f, - 0xe5, 0xa0, 0x4e, 0xc9, 0x5b, 0xf4, 0xd5, 0x2d, 0xee, 0xb3, 0x7d, 0x28, 0xca, 0xcf, 0xb7, 0xb1, - 0x95, 0xe8, 0xde, 0x2b, 0xfd, 0x83, 0x71, 0xeb, 0xab, 0xb3, 0x60, 0x29, 0x8e, 0x2d, 0xfd, 0x9d, - 0x3f, 0xfd, 0x5f, 0xff, 0x24, 0x5b, 0x63, 0x95, 0x47, 0x17, 0xef, 0x3d, 0x3a, 0xe3, 0x6e, 0x20, - 0xda, 0xf8, 0x9b, 0x00, 0xf1, 0x47, 0xc9, 0x58, 0x2b, 0x72, 0x42, 0xcd, 0x7c, 0xb1, 0x6d, 0xfd, - 0x76, 0x4a, 0x89, 0x6c, 0xf7, 0x36, 0xb6, 0xbb, 0x64, 0xd4, 0x45, 0xbb, 0x8e, 0xeb, 0x84, 0xf4, - 0x81, 0xb2, 0x0f, 0x33, 0x0f, 0xd9, 0x10, 0xaa, 0xfa, 0xe7, 0xc2, 0x98, 0x92, 0x94, 0x52, 0x3e, - 0x78, 0xb6, 0x7e, 0x27, 0xb5, 0x4c, 0xc9, 0xa0, 0xd8, 0xc7, 0x8a, 0xd1, 0x10, 0x7d, 0x4c, 0x11, - 0x23, 0xee, 0x65, 0x44, 0x52, 0x79, 0xfc, 0x55, 0x30, 0xf6, 0x9a, 0x26, 0x57, 0xcd, 0x7d, 0x93, - 0x6c, 0xfd, 0xee, 0x0d, 0xa5, 0xb2, 0xaf, 0xbb, 0xd8, 0xd7, 0x9a, 0xc1, 0x44, 0x5f, 0x03, 0xc4, - 0x51, 0xdf, 0x24, 0xfb, 0x30, 0xf3, 0xf0, 0xc9, 0x5f, 0x3e, 0x80, 0x72, 0x14, 0xcc, 0xc9, 0x7e, - 0x03, 0x6a, 0x89, 0xec, 0x3a, 0xa6, 0xa6, 0x91, 0x96, 0x8c, 0xb7, 0xfe, 0x5a, 0x7a, 0xa1, 0xec, - 0xf8, 0x75, 0xec, 0xb8, 0xc5, 0x56, 0x45, 0xc7, 0x32, 0x7b, 0xed, 0x11, 0x66, 0xc3, 0xd2, 0x2d, - 0x62, 0xcf, 0x35, 0xed, 0x83, 0x3a, 0x7b, 0x6d, 0x56, 0x23, 0x48, 0xf4, 0x76, 0xf7, 0x86, 0x52, - 0xd9, 0xdd, 0x6b, 0xd8, 0xdd, 0x2a, 0x5b, 0xd6, 0xbb, 0x53, 0xa1, 0x97, 0x8c, 0xe3, 0xcd, 0x7d, - 0xfa, 0x47, 0xb3, 0xd8, 0xdd, 0xf8, 0x9e, 0xb5, 0x94, 0x8f, 0x69, 0x45, 0x24, 0x32, 0xff, 0x45, - 0x2d, 0xa3, 0x85, 0x5d, 0x31, 0x86, 0xaf, 0x4f, 0xff, 0x66, 0x16, 0x3b, 0x81, 0x8a, 0xf6, 0x9d, - 0x09, 0x76, 0xfb, 0xc6, 0x6f, 0x62, 0xac, 0xaf, 0xa7, 0x15, 0xa5, 0x4d, 0x45, 0x6f, 0xff, 0xd1, - 0x29, 0xe7, 0xec, 0xd7, 0xa0, 0x1c, 0x7d, 0xbd, 0x80, 0xad, 0x69, 0x5f, 0x93, 0xd0, 0xbf, 0xb6, - 0xb0, 0xde, 0x9a, 0x2f, 0x48, 0x23, 0x3e, 0xbd, 0x75, 0x41, 0x7c, 0x9f, 0x42, 0x45, 0xfb, 0x42, - 0x41, 0x34, 0x81, 0xf9, 0xaf, 0x20, 0x44, 0x13, 0x48, 0xf9, 0xa0, 0x81, 0xd1, 0xc4, 0x2e, 0x2a, - 0xac, 0x8c, 0xf4, 0x1d, 0x5e, 0x79, 0x01, 0xdb, 0x83, 0x15, 0xa9, 0x69, 0x9d, 0xf0, 0x2f, 0xf3, - 0x1a, 0x52, 0xbe, 0x53, 0xf6, 0x38, 0xc3, 0x3e, 0x82, 0x92, 0xfa, 0x10, 0x05, 0x5b, 0x4d, 0xff, - 0xa0, 0xc6, 0xfa, 0xda, 0x1c, 0x5c, 0xaa, 0x45, 0x9f, 0x01, 0xc4, 0x9f, 0x43, 0x88, 0x98, 0xc4, - 0xdc, 0xe7, 0x15, 0x22, 0x0a, 0x98, 0xff, 0x76, 0x82, 0xb1, 0x8a, 0x13, 0x6c, 0x30, 0x64, 0x12, - 0x2e, 0xbf, 0x54, 0xd7, 0xab, 0xfe, 0x08, 0x2a, 0xda, 0x17, 0x11, 0xa2, 0xe5, 0x9b, 0xff, 0x9a, - 0x42, 0xb4, 0x7c, 0x29, 0x1f, 0x50, 0x30, 0xd6, 0xb1, 0xf5, 0x65, 0x63, 0x51, 0xb4, 0x2e, 0x44, - 0x2d, 0x29, 0xf2, 0x88, 0x17, 0x74, 0x0e, 0xb5, 0xc4, 0x67, 0x0f, 0xa2, 0x1d, 0x9a, 0xf6, 0x51, - 0x85, 0x68, 0x87, 0xa6, 0x7e, 0x29, 0x41, 0xd1, 0x99, 0xd1, 0x14, 0xfd, 0x5c, 0x20, 0x8a, 0xd6, - 0xd3, 0x0f, 0xa1, 0xa2, 0x7d, 0xc2, 0x20, 0x9a, 0xcb, 0xfc, 0xd7, 0x12, 0xa2, 0xb9, 0xa4, 0x7d, - 0xf1, 0x60, 0x19, 0xfb, 0xa8, 0x1b, 0x48, 0x0a, 0x78, 0x41, 0xa4, 0x68, 0xfb, 0x37, 0xa0, 0x9e, - 0xfc, 0xaa, 0x41, 0xb4, 0xf7, 0x53, 0x3f, 0x8f, 0x10, 0xed, 0xfd, 0x1b, 0x3e, 0x85, 0x20, 0x49, - 0xfa, 0xe1, 0x52, 0xd4, 0xc9, 0xa3, 0x9f, 0xc8, 0xb4, 0x94, 0x2f, 0xd8, 0xc7, 0x82, 0xc1, 0xc9, - 0xfb, 0x49, 0xd9, 0x9a, 0x46, 0xb5, 0xfa, 0x45, 0xa7, 0xd1, 0x7e, 0x99, 0xbb, 0xca, 0x34, 0x49, - 0xcc, 0xd8, 0x38, 0x7b, 0x0a, 0x4b, 0x11, 0x31, 0x47, 0x17, 0x8e, 0x06, 0xd1, 0x1c, 0x52, 0xaf, - 0x35, 0x5d, 0x6f, 0xcc, 0x96, 0x3e, 0xce, 0xd0, 0xf1, 0x87, 0xd7, 0x3c, 0x6a, 0xc7, 0x9f, 0x7e, - 0xe7, 0xa8, 0x76, 0xfc, 0x25, 0x6e, 0x83, 0x9c, 0x3d, 0xfe, 0x42, 0x47, 0xb4, 0xe1, 0xc2, 0xe2, - 0xec, 0xf5, 0x9f, 0x77, 0x6f, 0x4a, 0xfb, 0xa7, 0xe6, 0x5f, 0x7f, 0xf1, 0xad, 0x00, 0x49, 0x56, - 0xa4, 0xb8, 0xe9, 0x23, 0x19, 0x7c, 0xc2, 0x7e, 0x1d, 0xaa, 0xfa, 0x4d, 0xe8, 0x4c, 0xe7, 0x09, - 0xb3, 0x3d, 0xdd, 0x49, 0x2d, 0x4b, 0x52, 0x09, 0xab, 0xea, 0xdd, 0xb0, 0x4f, 0x60, 0x35, 0x5a, - 0x66, 0x3d, 0x6f, 0x3d, 0x60, 0xf7, 0x52, 0xb2, 0xd9, 0x13, 0x8b, 0x7d, 0xfb, 0xc6, 0x74, 0xf7, - 0xc7, 0x19, 0x41, 0x7d, 0xc9, 0x2b, 0x99, 0xe3, 0x93, 0x27, 0xed, 0x26, 0xea, 0xf8, 0xe4, 0x49, - 0xbd, 0xc7, 0x59, 0x51, 0x1f, 0x5b, 0x4a, 0xac, 0x11, 0x85, 0xe5, 0xb2, 0x1f, 0xc2, 0xa2, 0x96, - 0x94, 0xdf, 0xbb, 0x76, 0x07, 0xd1, 0x4e, 0x9a, 0xbf, 0x53, 0x70, 0x3d, 0xcd, 0x36, 0x69, 0xac, - 0x61, 0xfb, 0x4d, 0x23, 0xb1, 0x38, 0x62, 0x17, 0x6d, 0x41, 0x45, 0x4f, 0xf8, 0x7f, 0x41, 0xbb, - 0x6b, 0x5a, 0x91, 0x7e, 0x7d, 0xdd, 0xe3, 0x0c, 0xdb, 0x83, 0xc6, 0xec, 0x65, 0x5a, 0x11, 0x4f, - 0x49, 0xbb, 0x00, 0x6c, 0x7d, 0xa6, 0x30, 0x71, 0x05, 0x17, 0x3b, 0xa2, 0xc4, 0x8e, 0xe8, 0xa3, - 0x5e, 0x9e, 0x3f, 0x7b, 0xaa, 0x27, 0x3f, 0xf6, 0x15, 0xb5, 0x96, 0xf6, 0x99, 0xb7, 0x07, 0x99, - 0xc7, 0x19, 0xf6, 0x3b, 0x19, 0xa8, 0x26, 0xae, 0xa7, 0x49, 0x84, 0xce, 0xcf, 0xcc, 0xb3, 0xa5, - 0x97, 0xe9, 0x13, 0x35, 0x4c, 0x5c, 0xc4, 0xbd, 0x87, 0x3f, 0x48, 0xbc, 0xa4, 0x9f, 0x24, 0x5c, - 0x7b, 0x1b, 0xb3, 0x5f, 0xfd, 0xfa, 0x62, 0x16, 0x41, 0xbf, 0x2a, 0xf2, 0x8b, 0xc7, 0x19, 0xf6, - 0xef, 0x33, 0x50, 0x4f, 0xfa, 0xec, 0xa3, 0xe9, 0xa6, 0x46, 0x07, 0x44, 0xa4, 0x74, 0x83, 0xa3, - 0xff, 0x87, 0x38, 0xca, 0xfe, 0x43, 0x33, 0x31, 0x4a, 0x79, 0x99, 0xf8, 0xcf, 0x37, 0x5a, 0xf6, - 0x21, 0x7d, 0x64, 0x53, 0x85, 0x32, 0xb1, 0xf9, 0x8f, 0x32, 0x46, 0xe4, 0xa7, 0x7f, 0xc2, 0x10, - 0x5f, 0xc2, 0x8f, 0xe8, 0xeb, 0x56, 0x2a, 0x32, 0x46, 0x50, 0xf1, 0xab, 0xd6, 0x37, 0xde, 0xc2, - 0x39, 0xbd, 0x6e, 0xdc, 0x4e, 0xcc, 0x69, 0x56, 0xf0, 0x68, 0xd3, 0xe8, 0xe4, 0x17, 0x08, 0xe3, - 0x93, 0x73, 0xee, 0xab, 0x84, 0x37, 0x0f, 0x72, 0x4c, 0x83, 0x94, 0xe8, 0x89, 0xad, 0xf6, 0x8a, - 0xcd, 0x18, 0x0f, 0x71, 0xac, 0x6f, 0x19, 0xf7, 0x6e, 0x1c, 0xeb, 0x23, 0xf4, 0xbf, 0x8b, 0x11, - 0x1f, 0x01, 0xc4, 0xa1, 0x86, 0x6c, 0x26, 0xe0, 0x2d, 0x62, 0x40, 0xf3, 0xd1, 0x88, 0xc9, 0xfd, - 0xac, 0xe2, 0xe2, 0x44, 0x8b, 0xbf, 0x46, 0xec, 0x34, 0x0a, 0xc5, 0xd3, 0xa5, 0xaf, 0x64, 0x54, - 0x60, 0x42, 0xfa, 0x9a, 0x6d, 0x3f, 0xc1, 0x4c, 0xa3, 0xb8, 0xbb, 0x63, 0xa8, 0xed, 0x79, 0xde, - 0xf3, 0xe9, 0x24, 0x0a, 0x6f, 0x4f, 0x06, 0xc5, 0xec, 0xda, 0xc1, 0xf9, 0xfa, 0xcc, 0x2c, 0x8c, - 0xfb, 0xd8, 0xd4, 0x3a, 0x6b, 0x69, 0x4d, 0x3d, 0xfa, 0x49, 0x1c, 0xdf, 0xf8, 0x05, 0xb3, 0xa1, - 0x19, 0xf1, 0xe8, 0x38, 0x86, 0x30, 0xd9, 0x4c, 0x82, 0x33, 0xcf, 0x76, 0x91, 0x50, 0x13, 0xd4, - 0x68, 0x1f, 0x05, 0xaa, 0xcd, 0xc7, 0x19, 0x76, 0x04, 0xd5, 0x6d, 0x3e, 0xc0, 0x44, 0x7d, 0x0c, - 0x2d, 0x59, 0x4a, 0x84, 0x29, 0x50, 0x4c, 0xca, 0x7a, 0x2d, 0x01, 0x4c, 0x9e, 0x5b, 0x13, 0xfb, - 0xda, 0xe7, 0x9f, 0x3f, 0xfa, 0x89, 0x0c, 0x5a, 0xf9, 0x42, 0x9d, 0x5b, 0x2a, 0xa8, 0x27, 0x71, - 0x6e, 0xcd, 0x44, 0x01, 0x25, 0xce, 0xad, 0xb9, 0x28, 0xa0, 0xc4, 0x52, 0xab, 0xa0, 0x22, 0x36, - 0x82, 0xe6, 0x5c, 0xe0, 0x50, 0x74, 0x64, 0xdd, 0x14, 0x6e, 0xb4, 0x7e, 0xff, 0x66, 0x84, 0x64, - 0x6f, 0x0f, 0x93, 0xbd, 0xf5, 0xa0, 0x46, 0xb7, 0x57, 0x9e, 0x70, 0x4a, 0xd9, 0x9b, 0xb9, 0xef, - 0x46, 0xcf, 0x07, 0x9c, 0x3d, 0x60, 0xb0, 0x2c, 0x29, 0xe1, 0x60, 0xae, 0x1c, 0xfb, 0x35, 0xa8, - 0x3c, 0xe5, 0xa1, 0xca, 0xd1, 0x8b, 0x64, 0xec, 0x99, 0xa4, 0xbd, 0xf5, 0x94, 0x14, 0xbf, 0x24, - 0xcd, 0x60, 0x6b, 0x8f, 0xf8, 0xf0, 0x8c, 0x13, 0x73, 0xb2, 0x9c, 0xe1, 0x17, 0xec, 0x57, 0xb1, - 0xf1, 0x28, 0x35, 0x7a, 0x55, 0x4b, 0xc2, 0xd2, 0x1b, 0x5f, 0x9c, 0x81, 0xa7, 0xb5, 0xec, 0x7a, - 0x43, 0xae, 0xc9, 0x7a, 0x2e, 0x54, 0xb4, 0x2b, 0x14, 0xa2, 0x0d, 0x34, 0x7f, 0x65, 0x46, 0xb4, - 0x81, 0x52, 0x6e, 0x5c, 0x30, 0x1e, 0x60, 0x3f, 0x06, 0xbb, 0x1f, 0xf7, 0x43, 0xb7, 0x2c, 0xc4, - 0x3d, 0x3d, 0xfa, 0x89, 0x3d, 0x0e, 0xbf, 0x60, 0x9f, 0xe2, 0x1d, 0xf1, 0x7a, 0x0e, 0x62, 0xac, - 0x34, 0xcc, 0xa6, 0x2b, 0x46, 0x8b, 0xa5, 0x15, 0x25, 0x15, 0x09, 0xea, 0x0a, 0x25, 0xb9, 0xf7, - 0x01, 0x7a, 0xa1, 0x37, 0xd9, 0xb6, 0xf9, 0xd8, 0x73, 0x63, 0x5e, 0x1b, 0x67, 0xc5, 0xc5, 0xfc, - 0x4b, 0x4b, 0x8d, 0x63, 0x9f, 0x6a, 0x5a, 0x56, 0x22, 0x8d, 0x53, 0x11, 0xd7, 0x8d, 0x89, 0x73, - 0xd1, 0x82, 0xa4, 0x24, 0xcf, 0x3d, 0xce, 0xb0, 0x36, 0x40, 0x1c, 0x39, 0x16, 0xe9, 0x4c, 0x73, - 0x41, 0x69, 0x11, 0xdb, 0x4b, 0x09, 0x33, 0x3b, 0x82, 0x72, 0x1c, 0x72, 0xb3, 0x16, 0xdf, 0x08, - 0x93, 0x08, 0xd0, 0x89, 0x4e, 0xf0, 0xb9, 0x70, 0x17, 0xa3, 0x81, 0x4b, 0x05, 0xac, 0x24, 0x96, - 0xea, 0x94, 0xf3, 0x80, 0x39, 0xb0, 0x44, 0x03, 0x8c, 0xc4, 0x25, 0xcc, 0xe6, 0x8a, 0x3e, 0x05, - 0x30, 0x1f, 0x79, 0x12, 0xed, 0xe6, 0xd4, 0xf8, 0x89, 0x84, 0xe9, 0x47, 0x50, 0x2b, 0x65, 0x92, - 0x09, 0xd6, 0x3c, 0x86, 0xe6, 0x9c, 0x8b, 0x3e, 0xda, 0xd2, 0x37, 0xc5, 0x5c, 0x44, 0x5b, 0xfa, - 0x46, 0xef, 0xbe, 0xb1, 0x82, 0x5d, 0x2e, 0x1a, 0x80, 0xaa, 0xde, 0xa5, 0x13, 0x0e, 0xce, 0x45, - 0x77, 0xbf, 0x97, 0x81, 0xa5, 0x14, 0x27, 0x3c, 0x7b, 0x43, 0x59, 0x0d, 0x6e, 0x74, 0xd0, 0xaf, - 0xa7, 0x3a, 0x6b, 0x8d, 0x1e, 0xf6, 0xb3, 0xcf, 0x9e, 0x25, 0x0e, 0x36, 0xf2, 0x95, 0xca, 0x9d, - 0xf9, 0x42, 0xa1, 0x22, 0x55, 0xa2, 0xf8, 0x1c, 0xd6, 0x68, 0x20, 0xed, 0xd1, 0x68, 0xc6, 0x91, - 0xfc, 0xfa, 0xdc, 0x47, 0xf8, 0x13, 0xce, 0xf1, 0xf5, 0x9b, 0x3f, 0xd2, 0x7f, 0x83, 0x38, 0x4d, - 0x43, 0x65, 0x53, 0x68, 0xcc, 0x3a, 0x68, 0xd9, 0xcd, 0x6d, 0xad, 0xdf, 0x4b, 0xe8, 0xbf, 0x29, - 0x4e, 0xdd, 0xaf, 0x61, 0x67, 0xf7, 0x8c, 0xf5, 0xb4, 0x75, 0x21, 0x95, 0x58, 0xbc, 0x8f, 0xbf, - 0x1d, 0x79, 0x93, 0x67, 0xe6, 0xa9, 0x3a, 0xb8, 0xc9, 0xf7, 0x1d, 0x69, 0xe0, 0xe9, 0xce, 0xe8, - 0xb7, 0xb1, 0xfb, 0xfb, 0xc6, 0x9d, 0xb4, 0xee, 0x7d, 0xaa, 0x42, 0xba, 0xf8, 0xda, 0xec, 0xbe, - 0x56, 0x23, 0xb8, 0x9f, 0xf6, 0xbe, 0x6f, 0xd4, 0x85, 0x66, 0xd6, 0xfa, 0x16, 0xca, 0x76, 0x55, - 0xdd, 0x7b, 0x1c, 0x6d, 0x9f, 0x14, 0x37, 0x75, 0xb4, 0x7d, 0xd2, 0xdc, 0xcd, 0x49, 0xb9, 0x46, - 0x39, 0x9a, 0x3f, 0xcc, 0x3c, 0xdc, 0x7c, 0xe7, 0x87, 0x5f, 0x3b, 0x73, 0xc2, 0xf3, 0xe9, 0xc9, - 0xc6, 0xc0, 0x1b, 0x3f, 0x1a, 0x29, 0x6b, 0xa3, 0x4c, 0x79, 0x7e, 0x34, 0x72, 0x87, 0x8f, 0xb0, - 0xd9, 0x93, 0x85, 0x89, 0xef, 0x85, 0xde, 0xb7, 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x38, - 0x4e, 0xcb, 0x28, 0x67, 0x84, 0x00, 0x00, + // 11638 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x6f, 0x23, 0x59, + 0x76, 0x18, 0xde, 0x7c, 0x89, 0xe4, 0xe1, 0x43, 0xd4, 0xd5, 0x8b, 0xad, 0x9e, 0x9e, 0xee, 0xa9, + 0x99, 0x9d, 0xe9, 0xe9, 0x99, 0xed, 0xee, 0xe9, 0xdd, 0x9e, 0x5d, 0xcf, 0xfc, 0xbc, 0x5e, 0x4a, + 0xa2, 0x5a, 0xdc, 0x96, 0x28, 0x4d, 0x91, 0x9a, 0xf1, 0xec, 0xfe, 0x9c, 0xda, 0x12, 0x79, 0x25, + 0x95, 0x9b, 0xac, 0xe2, 0x54, 0x15, 0xf5, 0xd8, 0xc5, 0xe4, 0x43, 0x90, 0x18, 0x41, 0x90, 0x04, + 0x30, 0x12, 0x07, 0x88, 0x13, 0x23, 0x41, 0x8c, 0x20, 0x08, 0x0c, 0x18, 0x06, 0xd6, 0x01, 0x12, + 0x20, 0xdf, 0x8d, 0x00, 0x09, 0x8c, 0xc0, 0xce, 0x97, 0xc0, 0x30, 0x12, 0x24, 0xd9, 0x7c, 0x0b, + 0xfc, 0x27, 0x04, 0xf7, 0x9c, 0x7b, 0xab, 0x6e, 0x91, 0xa5, 0xee, 0x9e, 0xdd, 0xcd, 0x7e, 0x91, + 0x58, 0xe7, 0x9c, 0xfb, 0xac, 0x73, 0xcf, 0x3d, 0xaf, 0x7b, 0x0b, 0xca, 0xfe, 0x64, 0xf0, 0x60, + 0xe2, 0x7b, 0xa1, 0xc7, 0x0a, 0x23, 0xd7, 0x9f, 0x0c, 0x36, 0x5e, 0x3b, 0xf5, 0xbc, 0xd3, 0x11, + 0x7f, 0x68, 0x4f, 0x9c, 0x87, 0xb6, 0xeb, 0x7a, 0xa1, 0x1d, 0x3a, 0x9e, 0x1b, 0x10, 0x91, 0xf1, + 0x43, 0xa8, 0x3f, 0xe5, 0x6e, 0x8f, 0xf3, 0xa1, 0xc9, 0xbf, 0x98, 0xf2, 0x20, 0x64, 0xef, 0xc1, + 0x92, 0xcd, 0x7f, 0xc4, 0xf9, 0xd0, 0x9a, 0xd8, 0x41, 0x30, 0x39, 0xf3, 0xed, 0x80, 0x37, 0x33, + 0x77, 0x33, 0xf7, 0xaa, 0x66, 0x83, 0x10, 0x87, 0x11, 0x9c, 0xbd, 0x01, 0xd5, 0x40, 0x90, 0x72, + 0x37, 0xf4, 0xbd, 0xc9, 0x55, 0x33, 0x8b, 0x74, 0x15, 0x01, 0x6b, 0x13, 0xc8, 0x18, 0xc1, 0x62, + 0xd4, 0x42, 0x30, 0xf1, 0xdc, 0x80, 0xb3, 0x47, 0xb0, 0x32, 0x70, 0x26, 0x67, 0xdc, 0xb7, 0xb0, + 0xf0, 0xd8, 0xe5, 0x63, 0xcf, 0x75, 0x06, 0xcd, 0xcc, 0xdd, 0xdc, 0xbd, 0xb2, 0xc9, 0x08, 0x27, + 0x4a, 0xec, 0x4b, 0x0c, 0x7b, 0x07, 0x16, 0xb9, 0x4b, 0x70, 0x3e, 0xc4, 0x52, 0xb2, 0xa9, 0x7a, + 0x0c, 0x16, 0x05, 0x8c, 0xbf, 0x9d, 0x85, 0xa5, 0x8e, 0xeb, 0x84, 0x9f, 0xd9, 0xa3, 0x11, 0x0f, + 0xd5, 0x98, 0xde, 0x81, 0xc5, 0x0b, 0x04, 0xe0, 0x98, 0x2e, 0x3c, 0x7f, 0x28, 0x47, 0x54, 0x27, + 0xf0, 0xa1, 0x84, 0x5e, 0xdb, 0xb3, 0xec, 0xb5, 0x3d, 0x4b, 0x9d, 0xae, 0xdc, 0x35, 0xd3, 0xf5, + 0x0e, 0x2c, 0xfa, 0x7c, 0xe0, 0x9d, 0x73, 0xff, 0xca, 0xba, 0x70, 0xdc, 0xa1, 0x77, 0xd1, 0xcc, + 0xdf, 0xcd, 0xdc, 0x2b, 0x98, 0x75, 0x05, 0xfe, 0x0c, 0xa1, 0x6c, 0x13, 0x16, 0x07, 0x67, 0xb6, + 0xeb, 0xf2, 0x91, 0x75, 0x6c, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xb3, 0x70, 0x37, 0x73, 0xaf, 0xf2, + 0xf8, 0xe6, 0x03, 0x7c, 0xab, 0x0f, 0xb6, 0xce, 0x6c, 0x77, 0x13, 0x31, 0x3d, 0xd7, 0x9e, 0x04, + 0x67, 0x5e, 0x68, 0xd6, 0x65, 0x09, 0x02, 0x07, 0xc6, 0x0a, 0x30, 0x7d, 0x26, 0x68, 0xee, 0x8d, + 0x3f, 0xc8, 0xc0, 0xf2, 0x91, 0x3b, 0xf2, 0x06, 0xcf, 0x7f, 0xc6, 0x29, 0x4a, 0x19, 0x43, 0xf6, + 0x55, 0xc7, 0x90, 0xfb, 0xaa, 0x63, 0x58, 0x83, 0x95, 0x64, 0x67, 0xe5, 0x28, 0x38, 0xac, 0x8a, + 0xd2, 0xa7, 0x5c, 0x75, 0x4b, 0x0d, 0xe3, 0x5d, 0x68, 0x0c, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x71, + 0x2c, 0x4a, 0x78, 0x34, 0x90, 0x37, 0xa0, 0xea, 0xf2, 0x8b, 0x98, 0x4c, 0xf2, 0xae, 0xcb, 0x2f, + 0x14, 0x89, 0xd1, 0x84, 0xb5, 0xd9, 0x66, 0x64, 0x07, 0x7e, 0x9a, 0x81, 0xfc, 0x51, 0x78, 0xe9, + 0xb1, 0x27, 0x50, 0xb5, 0x87, 0x43, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x4d, 0x68, 0xa5, 0xd4, 0x1f, + 0x33, 0x39, 0xc4, 0x16, 0xa1, 0xfa, 0x57, 0x13, 0x6e, 0x56, 0xec, 0xf8, 0x81, 0x35, 0xa1, 0x28, + 0x1f, 0xb1, 0xdd, 0xb2, 0xa9, 0x1e, 0xd9, 0x6d, 0x00, 0x7b, 0xec, 0x4d, 0xdd, 0xd0, 0x0a, 0xec, + 0x10, 0x67, 0x2c, 0x67, 0x96, 0x09, 0xd2, 0xb3, 0x43, 0x76, 0x0b, 0xca, 0x93, 0xe7, 0x56, 0x30, + 0xf0, 0x9d, 0x49, 0x88, 0xcc, 0x53, 0x36, 0x4b, 0x93, 0xe7, 0x3d, 0x7c, 0x66, 0xef, 0x41, 0xc9, + 0x9b, 0x86, 0x13, 0xcf, 0x71, 0x43, 0xc9, 0x2f, 0x8b, 0xb2, 0x23, 0x07, 0xd3, 0xf0, 0x50, 0x80, + 0xcd, 0x88, 0x80, 0xbd, 0x05, 0xb5, 0x81, 0xe7, 0x9e, 0x38, 0xfe, 0x98, 0x24, 0x42, 0x73, 0x01, + 0xdb, 0x4a, 0x02, 0x8d, 0x3f, 0xca, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, + 0x43, 0x31, 0xbc, 0xb4, 0xce, 0xec, 0xe0, 0x0c, 0x87, 0x5a, 0x36, 0x17, 0xc2, 0xcb, 0x5d, 0x3b, + 0x38, 0x63, 0x6b, 0xb0, 0x40, 0xbd, 0xc4, 0x01, 0xe5, 0x4c, 0xf9, 0x24, 0x16, 0x88, 0x3b, 0x1d, + 0x5b, 0xc9, 0xa6, 0x72, 0xc8, 0x31, 0x0d, 0x77, 0x3a, 0xde, 0xd2, 0xe1, 0x62, 0xf0, 0xc7, 0xe2, + 0x75, 0x53, 0x03, 0x34, 0xbc, 0x32, 0x42, 0xb0, 0x8d, 0x37, 0xa0, 0x2a, 0xd1, 0xdc, 0x39, 0x3d, + 0xa3, 0x31, 0x16, 0xcc, 0x0a, 0x11, 0x20, 0x48, 0xd4, 0x10, 0x3a, 0x63, 0x6e, 0x05, 0xa1, 0x3d, + 0x9e, 0xc8, 0x21, 0x95, 0x05, 0xa4, 0x27, 0x00, 0x88, 0xf6, 0x42, 0x7b, 0x64, 0x9d, 0x70, 0x1e, + 0x34, 0x8b, 0x12, 0x2d, 0x20, 0x3b, 0x9c, 0x07, 0xec, 0x6b, 0x50, 0x1f, 0xf2, 0x20, 0xb4, 0xe4, + 0xcb, 0xe0, 0x41, 0xb3, 0x84, 0x2b, 0xbf, 0x26, 0xa0, 0x2d, 0x05, 0x64, 0xaf, 0x01, 0xf8, 0xf6, + 0x85, 0x25, 0x26, 0x82, 0x5f, 0x36, 0xcb, 0xf4, 0x16, 0x7c, 0xfb, 0xa2, 0x7f, 0xb9, 0xcb, 0x2f, + 0x05, 0xd7, 0x3c, 0xe5, 0xa1, 0x36, 0x69, 0x81, 0xe4, 0x4e, 0x63, 0x0f, 0x98, 0x06, 0xde, 0xe6, + 0xa1, 0xed, 0x8c, 0x02, 0xf6, 0x21, 0x54, 0x43, 0x8d, 0x18, 0xc5, 0x60, 0x25, 0x62, 0x21, 0xad, + 0x80, 0x99, 0xa0, 0x33, 0xce, 0xa0, 0xb4, 0xc3, 0xf9, 0x9e, 0x33, 0x76, 0x42, 0xb6, 0x06, 0x85, + 0x13, 0xe7, 0x92, 0x13, 0xb3, 0xe7, 0x76, 0x6f, 0x98, 0xf4, 0xc8, 0xee, 0x00, 0xe0, 0x0f, 0x6b, + 0x1c, 0x71, 0xd3, 0xee, 0x0d, 0xb3, 0x8c, 0xb0, 0xfd, 0xc0, 0x0e, 0xd9, 0x06, 0x14, 0x27, 0xdc, + 0x1f, 0x70, 0xf5, 0xde, 0x76, 0x6f, 0x98, 0x0a, 0xb0, 0x59, 0x84, 0xc2, 0x48, 0xd4, 0x6e, 0xfc, + 0x49, 0x01, 0x2a, 0x3d, 0xee, 0x46, 0xab, 0x8c, 0x41, 0x5e, 0x4c, 0x88, 0x5c, 0x59, 0xf8, 0x9b, + 0xbd, 0x09, 0x15, 0x9c, 0xba, 0x20, 0xf4, 0x1d, 0xf7, 0x94, 0xb8, 0x7a, 0x33, 0xdb, 0xcc, 0x98, + 0x20, 0xc0, 0x3d, 0x84, 0xb2, 0x06, 0xe4, 0xec, 0xb1, 0xe2, 0x6a, 0xf1, 0x93, 0xdd, 0x84, 0x92, + 0x3d, 0x0e, 0xa9, 0x7b, 0x55, 0x04, 0x17, 0xed, 0x71, 0x88, 0x5d, 0x7b, 0x03, 0xaa, 0x13, 0xfb, + 0x6a, 0x2c, 0xd6, 0x72, 0xc4, 0x0e, 0x55, 0xb3, 0x22, 0x61, 0xc8, 0x10, 0x8f, 0x61, 0x59, 0x27, + 0x51, 0x8d, 0x17, 0xa2, 0xc6, 0x97, 0x34, 0x6a, 0xd9, 0x87, 0x77, 0x60, 0x51, 0x95, 0xf1, 0x69, + 0x3c, 0xc8, 0x26, 0x65, 0xb3, 0x2e, 0xc1, 0x6a, 0x94, 0xf7, 0xa0, 0x71, 0xe2, 0xb8, 0xf6, 0xc8, + 0x1a, 0x8c, 0xc2, 0x73, 0x6b, 0xc8, 0x47, 0xa1, 0x8d, 0x1c, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1a, + 0x85, 0xe7, 0xdb, 0x02, 0xca, 0xde, 0x87, 0xf2, 0x09, 0xe7, 0x16, 0x4e, 0x56, 0xb3, 0x94, 0x58, + 0x78, 0xea, 0x0d, 0x99, 0xa5, 0x13, 0xf5, 0xae, 0xde, 0x87, 0x86, 0x37, 0x0d, 0x4f, 0x3d, 0xc7, + 0x3d, 0xb5, 0x84, 0xbc, 0xb3, 0x9c, 0x21, 0xf2, 0x50, 0x7e, 0x33, 0xfb, 0x28, 0x63, 0xd6, 0x15, + 0x4e, 0x48, 0x9e, 0xce, 0x90, 0xbd, 0x0d, 0x8b, 0x23, 0x3b, 0x08, 0xad, 0x33, 0x6f, 0x62, 0x4d, + 0xa6, 0xc7, 0xcf, 0xf9, 0x55, 0xb3, 0x86, 0x13, 0x51, 0x13, 0xe0, 0x5d, 0x6f, 0x72, 0x88, 0x40, + 0xc1, 0xd9, 0xd8, 0x4f, 0xea, 0x04, 0xdc, 0xcd, 0xdc, 0xab, 0x99, 0x65, 0x01, 0xa1, 0x46, 0x3f, + 0x87, 0x65, 0x7c, 0x3d, 0x83, 0x69, 0x10, 0x7a, 0x63, 0x4b, 0xc8, 0x6a, 0x7f, 0x18, 0x34, 0x2b, + 0xc8, 0x6b, 0xef, 0xca, 0xce, 0x6a, 0xef, 0xf8, 0xc1, 0x36, 0x0f, 0xc2, 0x2d, 0x24, 0x36, 0x89, + 0x56, 0x6c, 0xe8, 0x57, 0xe6, 0xd2, 0x70, 0x16, 0xce, 0xde, 0x07, 0x66, 0x8f, 0x46, 0xde, 0x85, + 0x15, 0xf0, 0xd1, 0x89, 0x25, 0x27, 0xb1, 0x59, 0xbf, 0x9b, 0xb9, 0x57, 0x32, 0x1b, 0x88, 0xe9, + 0xf1, 0xd1, 0xc9, 0x21, 0xc1, 0xd9, 0x87, 0x80, 0x8b, 0xc9, 0x3a, 0xe1, 0x76, 0x38, 0xf5, 0x79, + 0xd0, 0x5c, 0xbc, 0x9b, 0xbb, 0x57, 0x7f, 0xbc, 0x14, 0xcd, 0x17, 0x82, 0x37, 0x9d, 0xd0, 0xac, + 0x0a, 0x3a, 0xf9, 0x1c, 0x6c, 0x6c, 0xc3, 0x5a, 0x7a, 0x97, 0x04, 0x53, 0x89, 0x59, 0x11, 0xcc, + 0x98, 0x37, 0xc5, 0x4f, 0xb6, 0x02, 0x85, 0x73, 0x7b, 0x34, 0xe5, 0x52, 0xa6, 0xd3, 0xc3, 0x47, + 0xd9, 0x6f, 0x67, 0x8c, 0x3f, 0xce, 0x40, 0x95, 0x46, 0x29, 0x75, 0x91, 0x37, 0xa1, 0xa6, 0xb8, + 0x81, 0xfb, 0xbe, 0xe7, 0x4b, 0xa9, 0xa6, 0x38, 0xaf, 0x2d, 0x60, 0x62, 0x57, 0x51, 0x44, 0x13, + 0x9f, 0x3b, 0x63, 0xfb, 0x54, 0x55, 0xad, 0x58, 0xe9, 0x50, 0x82, 0xd9, 0x07, 0x71, 0x7d, 0xbe, + 0x37, 0x0d, 0xb9, 0xdc, 0xf3, 0xaa, 0x72, 0x78, 0xa6, 0x80, 0x45, 0xb5, 0xe3, 0xd3, 0x2b, 0xf0, + 0xb9, 0xf1, 0x3b, 0x19, 0x60, 0xa2, 0xdb, 0x7d, 0x8f, 0x2a, 0x90, 0x1c, 0x3a, 0x5b, 0x32, 0xf3, + 0xca, 0x2b, 0x24, 0xfb, 0xa2, 0x15, 0x62, 0x40, 0x81, 0xfa, 0x9e, 0x4f, 0xe9, 0x3b, 0xa1, 0xbe, + 0x97, 0x2f, 0xe5, 0x1a, 0x79, 0xe3, 0xbf, 0xe6, 0x60, 0x65, 0x8b, 0xb6, 0xec, 0xd6, 0x60, 0xc0, + 0x27, 0xd1, 0xda, 0xb9, 0x03, 0x15, 0xd7, 0x1b, 0x72, 0xc5, 0xb1, 0xd4, 0x31, 0x10, 0x20, 0x8d, + 0x5d, 0xcf, 0x6c, 0xc7, 0xa5, 0x8e, 0xd3, 0x64, 0x96, 0x11, 0x82, 0xdd, 0x7e, 0x1b, 0x16, 0x27, + 0xdc, 0x1d, 0xea, 0x4b, 0x84, 0x94, 0xaa, 0x9a, 0x04, 0xcb, 0xd5, 0x71, 0x07, 0x2a, 0x27, 0x53, + 0xa2, 0x13, 0x82, 0x25, 0x8f, 0x3c, 0x00, 0x12, 0xd4, 0x22, 0xf9, 0x32, 0x99, 0x06, 0x67, 0x88, + 0x2d, 0x20, 0xb6, 0x28, 0x9e, 0x05, 0xea, 0x36, 0xc0, 0x70, 0x1a, 0x84, 0x72, 0xc5, 0x2c, 0x20, + 0xb2, 0x2c, 0x20, 0xb4, 0x62, 0xbe, 0x0e, 0xcb, 0x63, 0xfb, 0xd2, 0x42, 0xde, 0xb1, 0x1c, 0xd7, + 0x3a, 0x19, 0xe1, 0x9e, 0x53, 0x44, 0xba, 0xc6, 0xd8, 0xbe, 0xfc, 0x54, 0x60, 0x3a, 0xee, 0x0e, + 0xc2, 0x85, 0x58, 0x51, 0xea, 0x8e, 0xcf, 0x03, 0xee, 0x9f, 0x73, 0x94, 0x04, 0xf9, 0x48, 0xa7, + 0x31, 0x09, 0x2a, 0x7a, 0x34, 0x16, 0xe3, 0x0e, 0x47, 0x03, 0x5a, 0xf6, 0x66, 0x71, 0xec, 0xb8, + 0xbb, 0xe1, 0x68, 0x20, 0xf6, 0x15, 0x21, 0x47, 0x26, 0xdc, 0xb7, 0x9e, 0x5f, 0xe0, 0x1a, 0xce, + 0xa3, 0xdc, 0x38, 0xe4, 0xfe, 0xb3, 0x0b, 0xb1, 0xf5, 0x0f, 0x02, 0x14, 0x44, 0xf6, 0x55, 0xb3, + 0x82, 0x0b, 0xbc, 0x34, 0x08, 0x84, 0x08, 0xb2, 0xaf, 0xc4, 0x22, 0x14, 0xbd, 0xb5, 0xf1, 0x2d, + 0xf0, 0x21, 0x56, 0x1f, 0xa0, 0x44, 0xad, 0x61, 0x67, 0x5b, 0x12, 0x21, 0xda, 0x09, 0x04, 0xd7, + 0xab, 0xce, 0x9e, 0x8c, 0xec, 0xd3, 0x00, 0x45, 0x4a, 0xcd, 0xac, 0x4a, 0xe0, 0x8e, 0x80, 0x19, + 0x9f, 0x91, 0x92, 0xa5, 0xbd, 0x5b, 0xb9, 0x66, 0xc4, 0x56, 0x8f, 0x10, 0x7c, 0xaf, 0x25, 0x53, + 0x3e, 0xa5, 0xbd, 0xb4, 0x6c, 0xca, 0x4b, 0x33, 0x7e, 0x2f, 0x03, 0x55, 0x59, 0x33, 0x2a, 0x25, + 0xec, 0x01, 0x30, 0xf5, 0x16, 0xc3, 0x4b, 0x67, 0x68, 0x1d, 0x5f, 0x85, 0x3c, 0x20, 0xa6, 0xd9, + 0xbd, 0x61, 0x36, 0x24, 0xae, 0x7f, 0xe9, 0x0c, 0x37, 0x05, 0x86, 0xdd, 0x87, 0x46, 0x82, 0x3e, + 0x08, 0x7d, 0xe2, 0xe8, 0xdd, 0x1b, 0x66, 0x5d, 0xa3, 0xee, 0x85, 0xbe, 0x58, 0x23, 0x42, 0xe5, + 0x99, 0x86, 0x96, 0xe3, 0x0e, 0xf9, 0x25, 0xb2, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x23, 0x40, 0x9b, + 0x75, 0xa8, 0xea, 0xd5, 0x19, 0xa7, 0x50, 0x52, 0xfa, 0x12, 0x2a, 0x0c, 0x33, 0x5d, 0x32, 0xcb, + 0x61, 0xd4, 0x93, 0x9b, 0x50, 0x4a, 0xf6, 0xc0, 0x2c, 0x86, 0xaf, 0xdc, 0xb0, 0xf1, 0x1d, 0x68, + 0xec, 0x09, 0xe6, 0x71, 0x05, 0xb3, 0x4a, 0xfd, 0x6f, 0x0d, 0x16, 0xb4, 0x45, 0x53, 0x36, 0xe5, + 0x93, 0xd8, 0x73, 0xcf, 0xbc, 0x20, 0x94, 0xad, 0xe0, 0x6f, 0xe3, 0x4f, 0x32, 0xc0, 0xda, 0x41, + 0xe8, 0x8c, 0xed, 0x90, 0xef, 0xf0, 0x48, 0x2c, 0x1c, 0x40, 0x55, 0xd4, 0xd6, 0xf7, 0x5a, 0xa4, + 0x90, 0x91, 0x42, 0xf1, 0x9e, 0x5c, 0xc6, 0xf3, 0x05, 0x1e, 0xe8, 0xd4, 0x24, 0xe6, 0x13, 0x15, + 0x88, 0x55, 0x16, 0xda, 0xfe, 0x29, 0x0f, 0x51, 0x8d, 0x93, 0xfa, 0x3e, 0x10, 0x48, 0x28, 0x70, + 0x1b, 0xbf, 0x06, 0x4b, 0x73, 0x75, 0xe8, 0x72, 0xb9, 0x9c, 0x22, 0x97, 0x73, 0xba, 0x5c, 0xb6, + 0x60, 0x39, 0xd1, 0x2f, 0xc9, 0x69, 0xeb, 0x50, 0x14, 0x0b, 0x42, 0x28, 0x07, 0x19, 0xd2, 0x2a, + 0x4f, 0x38, 0x17, 0x6a, 0xf0, 0x43, 0x58, 0x39, 0xe1, 0xdc, 0xb7, 0x43, 0x44, 0xe2, 0x8a, 0x11, + 0x6f, 0x48, 0x56, 0xbc, 0x24, 0x71, 0x3d, 0x3b, 0x3c, 0xe4, 0xbe, 0x78, 0x53, 0xc6, 0xff, 0xc8, + 0xc0, 0xa2, 0x90, 0xa0, 0xfb, 0xb6, 0x7b, 0xa5, 0xe6, 0x69, 0x2f, 0x75, 0x9e, 0xee, 0x69, 0x9b, + 0xa1, 0x46, 0xfd, 0x55, 0x27, 0x29, 0x37, 0x3b, 0x49, 0xec, 0x2e, 0x54, 0x13, 0x7d, 0x2d, 0x60, + 0x5f, 0x21, 0x88, 0x3a, 0xf9, 0xf3, 0x4f, 0xe3, 0xdb, 0xd0, 0x88, 0xbb, 0x2d, 0xe7, 0x90, 0x41, + 0x5e, 0xb0, 0xa4, 0xac, 0x00, 0x7f, 0x1b, 0xff, 0x34, 0x43, 0x84, 0x5b, 0x9e, 0x13, 0x69, 0xa7, + 0x82, 0x50, 0xe8, 0xbd, 0x8a, 0x50, 0xfc, 0xbe, 0x56, 0xab, 0xff, 0xf9, 0x07, 0x2b, 0x96, 0x4e, + 0xc0, 0xdd, 0xa1, 0x65, 0x8f, 0x46, 0x28, 0x7c, 0x4b, 0x66, 0x51, 0x3c, 0xb7, 0x46, 0x23, 0xe3, + 0x1d, 0x58, 0xd2, 0x7a, 0xf7, 0x82, 0x71, 0x74, 0x81, 0xed, 0x39, 0x41, 0x78, 0xe4, 0x06, 0x13, + 0x4d, 0x71, 0xbb, 0x05, 0x65, 0x21, 0x61, 0x45, 0xcf, 0x68, 0xc9, 0x16, 0x4c, 0x21, 0x72, 0x45, + 0xbf, 0x02, 0x44, 0xda, 0x97, 0x12, 0x99, 0x95, 0x48, 0xfb, 0x12, 0x91, 0xc6, 0xb7, 0x61, 0x39, + 0x51, 0x9f, 0x6c, 0xfa, 0x0d, 0x28, 0x4c, 0xc3, 0x4b, 0x4f, 0xa9, 0xe6, 0x15, 0xc9, 0x21, 0xc2, + 0x00, 0x34, 0x09, 0x63, 0x7c, 0x0c, 0x4b, 0x5d, 0x7e, 0x21, 0x17, 0xb1, 0xea, 0xc8, 0xdb, 0x90, + 0x7f, 0x89, 0x51, 0x88, 0x78, 0xe3, 0x01, 0x30, 0xbd, 0xb0, 0x6c, 0x55, 0xb3, 0x11, 0x33, 0x09, + 0x1b, 0xd1, 0x78, 0x1b, 0x58, 0xcf, 0x39, 0x75, 0xf7, 0x79, 0x10, 0xd8, 0xa7, 0xd1, 0xb2, 0x6f, + 0x40, 0x6e, 0x1c, 0x9c, 0x4a, 0x19, 0x25, 0x7e, 0x1a, 0xdf, 0x80, 0xe5, 0x04, 0x9d, 0xac, 0xf8, + 0x35, 0x28, 0x07, 0xce, 0xa9, 0x8b, 0x8a, 0x95, 0xac, 0x3a, 0x06, 0x18, 0x3b, 0xb0, 0xf2, 0x29, + 0xf7, 0x9d, 0x93, 0xab, 0x97, 0x55, 0x9f, 0xac, 0x27, 0x3b, 0x5b, 0x4f, 0x1b, 0x56, 0x67, 0xea, + 0x91, 0xcd, 0x13, 0xfb, 0xca, 0x37, 0x59, 0x32, 0xe9, 0x41, 0x93, 0x7b, 0x59, 0x5d, 0xee, 0x19, + 0x47, 0xc0, 0xb6, 0x3c, 0xd7, 0xe5, 0x83, 0xf0, 0x90, 0x73, 0x3f, 0xf6, 0x52, 0xc5, 0xbc, 0x5a, + 0x79, 0xbc, 0x2e, 0x67, 0x76, 0x56, 0x98, 0x4a, 0x26, 0x66, 0x90, 0x9f, 0x70, 0x7f, 0x8c, 0x15, + 0x97, 0x4c, 0xfc, 0x6d, 0xac, 0xc2, 0x72, 0xa2, 0x5a, 0x69, 0xd7, 0x3f, 0x82, 0xd5, 0x6d, 0x27, + 0x18, 0xcc, 0x37, 0xb8, 0x0e, 0xc5, 0xc9, 0xf4, 0xd8, 0x4a, 0xca, 0xe5, 0x67, 0xfc, 0x4a, 0x58, + 0x7b, 0xb3, 0x25, 0x64, 0x5d, 0x7f, 0x33, 0x03, 0xf9, 0xdd, 0xfe, 0xde, 0x16, 0xdb, 0x80, 0x92, + 0xe3, 0x0e, 0xbc, 0xb1, 0x50, 0xbc, 0x68, 0xcc, 0xd1, 0xf3, 0xb5, 0x0b, 0xec, 0x16, 0x94, 0x51, + 0x5f, 0x13, 0xa6, 0xad, 0x54, 0x7d, 0x4a, 0x02, 0xb0, 0xe7, 0x0d, 0x9e, 0x0b, 0x9b, 0x9a, 0x5f, + 0x4e, 0x1c, 0x1f, 0xad, 0x66, 0x65, 0x0c, 0xe7, 0x69, 0xaf, 0x8f, 0x11, 0x64, 0x11, 0x1b, 0xff, + 0xae, 0x04, 0x45, 0xb9, 0xdb, 0xd2, 0xce, 0x1d, 0x3a, 0xe7, 0x3c, 0xde, 0xb9, 0xc5, 0x93, 0xd0, + 0x07, 0x7c, 0x3e, 0xf6, 0xc2, 0x48, 0x61, 0xa3, 0x77, 0x50, 0x25, 0xa0, 0x54, 0xd9, 0x34, 0xa5, + 0x81, 0x5c, 0x0c, 0x39, 0x22, 0x1a, 0xe8, 0x5b, 0xf9, 0x2d, 0x28, 0xaa, 0xbd, 0x3f, 0x1f, 0xd9, + 0x34, 0x0b, 0x03, 0xd2, 0xd6, 0x36, 0xa0, 0x34, 0xb0, 0x27, 0xf6, 0xc0, 0x09, 0xaf, 0xa4, 0x40, + 0x88, 0x9e, 0x45, 0xed, 0x23, 0x6f, 0x60, 0x8f, 0xac, 0x63, 0x7b, 0x64, 0xbb, 0x03, 0x2e, 0x6d, + 0xf7, 0x2a, 0x02, 0x37, 0x09, 0x26, 0xec, 0x73, 0xd9, 0x4f, 0x45, 0x45, 0x26, 0xbc, 0xec, 0xbd, + 0x22, 0x13, 0xca, 0xa5, 0x37, 0x1e, 0x3b, 0xc2, 0xca, 0x20, 0x35, 0x2c, 0x67, 0x96, 0x09, 0xb2, + 0xc3, 0x71, 0xb4, 0x12, 0x7d, 0x41, 0x53, 0x57, 0xa6, 0xa6, 0x08, 0xf8, 0x19, 0x39, 0x12, 0xe6, + 0x75, 0xb1, 0x9c, 0xa6, 0x8b, 0xbd, 0x07, 0x4b, 0x53, 0x37, 0xe0, 0x61, 0x38, 0xe2, 0xc3, 0xa8, + 0x2f, 0x15, 0x24, 0x6a, 0x44, 0x08, 0xd5, 0x9d, 0x07, 0xb0, 0x4c, 0x4e, 0x87, 0xc0, 0x0e, 0xbd, + 0xe0, 0xcc, 0x09, 0xac, 0x40, 0x58, 0x48, 0x64, 0xee, 0x2e, 0x21, 0xaa, 0x27, 0x31, 0x3d, 0x32, + 0x91, 0xd6, 0x67, 0xe8, 0x7d, 0x3e, 0xe0, 0xce, 0x39, 0x1f, 0xa2, 0x9e, 0x96, 0x33, 0x57, 0x13, + 0x65, 0x4c, 0x89, 0x44, 0xa5, 0x7b, 0x3a, 0xb6, 0xa6, 0x93, 0xa1, 0x2d, 0x94, 0x95, 0x3a, 0x29, + 0xc3, 0xee, 0x74, 0x7c, 0x44, 0x10, 0xf6, 0x08, 0x94, 0x26, 0x26, 0xf5, 0xc3, 0xc5, 0x84, 0x3c, + 0x13, 0xcc, 0x6a, 0x56, 0x25, 0x05, 0x29, 0x8a, 0x09, 0x9d, 0xb3, 0x31, 0xa3, 0x73, 0x36, 0xa1, + 0x38, 0xf1, 0x9d, 0x73, 0x3b, 0xe4, 0xcd, 0x25, 0x12, 0xe0, 0xf2, 0x51, 0x48, 0x06, 0xc7, 0x75, + 0x42, 0xc7, 0x0e, 0x3d, 0xbf, 0xc9, 0x10, 0x17, 0x03, 0xd8, 0x7d, 0x58, 0x42, 0x1e, 0x09, 0x42, + 0x3b, 0x9c, 0x06, 0x52, 0x03, 0x5d, 0x46, 0x66, 0x42, 0x1d, 0xba, 0x87, 0x70, 0x54, 0x42, 0xd9, + 0x37, 0x60, 0x8d, 0xd8, 0x02, 0x4b, 0x48, 0xcd, 0x1a, 0x15, 0x82, 0x15, 0x9c, 0x8a, 0x65, 0xc4, + 0x0a, 0xfe, 0x96, 0xfa, 0xb5, 0xd0, 0x0e, 0x9e, 0xc0, 0xba, 0x64, 0x93, 0xb9, 0x52, 0xab, 0x58, + 0x6a, 0x85, 0xd0, 0x33, 0xc5, 0x1e, 0xc0, 0x92, 0xe8, 0x92, 0x33, 0xb0, 0x64, 0x69, 0xb1, 0x12, + 0xd6, 0x44, 0xef, 0xd1, 0x52, 0x5a, 0x24, 0xa4, 0x89, 0xb8, 0x67, 0xfc, 0x8a, 0x7d, 0x07, 0x16, + 0x89, 0x65, 0xd0, 0xbc, 0x42, 0x49, 0xbf, 0x81, 0x92, 0x7e, 0x55, 0x79, 0x38, 0x23, 0x2c, 0x0a, + 0xfb, 0xfa, 0x20, 0xf1, 0x2c, 0x96, 0xc3, 0xc8, 0x39, 0xe1, 0xa1, 0x33, 0xe6, 0xcd, 0x75, 0x62, + 0x30, 0xf5, 0x2c, 0x56, 0xea, 0x74, 0x82, 0x98, 0x26, 0xc9, 0x05, 0x7a, 0x42, 0xde, 0x1d, 0x79, + 0x01, 0x57, 0x2e, 0xaa, 0xe6, 0x4d, 0xb9, 0x08, 0x05, 0x50, 0xe9, 0x90, 0x42, 0x11, 0x27, 0xa3, + 0x27, 0x72, 0x24, 0xde, 0x42, 0x66, 0xa8, 0x91, 0xed, 0xa3, 0x9c, 0x89, 0x62, 0x17, 0x3f, 0xb3, + 0x2f, 0x94, 0x04, 0x79, 0x0d, 0xdf, 0x2f, 0x08, 0x90, 0x94, 0x1d, 0x3f, 0xc9, 0xd0, 0x86, 0x28, + 0xe5, 0x47, 0xa0, 0x99, 0x77, 0x24, 0x39, 0x2c, 0xcf, 0x1d, 0x5d, 0x49, 0x61, 0x02, 0x04, 0x3a, + 0x70, 0x47, 0xb8, 0x9a, 0x1d, 0x57, 0x27, 0x21, 0xd9, 0x5b, 0x55, 0x40, 0x24, 0xba, 0x03, 0x95, + 0xc9, 0xf4, 0x78, 0xe4, 0x0c, 0x88, 0x24, 0x47, 0xb5, 0x10, 0x08, 0x09, 0x84, 0x7d, 0x4b, 0x1c, + 0x45, 0x14, 0x79, 0xa4, 0xa8, 0x48, 0x18, 0x92, 0xa0, 0x6c, 0xe7, 0x3e, 0x8a, 0x93, 0xaa, 0x89, + 0xbf, 0x8d, 0x4d, 0x58, 0x49, 0x76, 0x5a, 0x6e, 0x3c, 0xf7, 0xa1, 0x24, 0x65, 0x95, 0x72, 0x7c, + 0xd4, 0x35, 0x57, 0xb4, 0x30, 0xd1, 0x22, 0xbc, 0xf1, 0x5b, 0x0b, 0xb0, 0x2c, 0xa1, 0x5b, 0x62, + 0x6a, 0x7b, 0xd3, 0xf1, 0xd8, 0xf6, 0x53, 0x84, 0x60, 0xe6, 0xc5, 0x42, 0x30, 0x3b, 0x27, 0x04, + 0x93, 0x96, 0x2f, 0xc9, 0xd0, 0xa4, 0xe5, 0x2b, 0xde, 0x25, 0x19, 0x23, 0xba, 0x1f, 0xb4, 0x26, + 0xc1, 0x7d, 0xf2, 0xb7, 0xce, 0x89, 0xec, 0x42, 0x8a, 0xc8, 0xd6, 0x05, 0xee, 0xc2, 0x8c, 0xc0, + 0x7d, 0x03, 0x88, 0x69, 0xd4, 0xdb, 0x2f, 0x92, 0x7d, 0x82, 0x30, 0xe9, 0x4c, 0x7d, 0x07, 0x16, + 0x67, 0x65, 0x1c, 0x09, 0xd3, 0x7a, 0x8a, 0x84, 0x73, 0xc6, 0x1c, 0x77, 0x2b, 0x8d, 0xb8, 0x2c, + 0x25, 0x9c, 0x33, 0xe6, 0x7b, 0x88, 0x51, 0xf4, 0x6d, 0x00, 0x6a, 0x1b, 0x17, 0x0d, 0xe0, 0xa2, + 0x79, 0x3b, 0xf9, 0x2e, 0xf4, 0x59, 0x7f, 0x20, 0x1e, 0xa6, 0x3e, 0xc7, 0x55, 0x54, 0xc6, 0x92, + 0xb8, 0x80, 0x9e, 0x41, 0xdd, 0x9b, 0x70, 0xd7, 0x8a, 0x65, 0x4d, 0x05, 0xab, 0x7a, 0xeb, 0x05, + 0x55, 0x75, 0x14, 0xad, 0x59, 0x13, 0x65, 0xa3, 0x47, 0xb6, 0x4f, 0x13, 0xcf, 0xb5, 0xda, 0xaa, + 0x5f, 0xa1, 0xb6, 0x3a, 0x16, 0x8e, 0x9e, 0x8d, 0xbf, 0x93, 0x81, 0x8a, 0xd6, 0x6d, 0xb6, 0x0a, + 0x4b, 0x5b, 0x07, 0x07, 0x87, 0x6d, 0xb3, 0xd5, 0xef, 0x7c, 0xda, 0xb6, 0xb6, 0xf6, 0x0e, 0x7a, + 0xed, 0xc6, 0x0d, 0x01, 0xde, 0x3b, 0xd8, 0x6a, 0xed, 0x59, 0x3b, 0x07, 0xe6, 0x96, 0x02, 0x67, + 0xd8, 0x1a, 0x30, 0xb3, 0xbd, 0x7f, 0xd0, 0x6f, 0x27, 0xe0, 0x59, 0xd6, 0x80, 0xea, 0xa6, 0xd9, + 0x6e, 0x6d, 0xed, 0x4a, 0x48, 0x8e, 0xad, 0x40, 0x63, 0xe7, 0xa8, 0xbb, 0xdd, 0xe9, 0x3e, 0xb5, + 0xb6, 0x5a, 0xdd, 0xad, 0xf6, 0x5e, 0x7b, 0xbb, 0x91, 0x67, 0x35, 0x28, 0xb7, 0x36, 0x5b, 0xdd, + 0xed, 0x83, 0x6e, 0x7b, 0xbb, 0x51, 0x30, 0x7e, 0x05, 0xca, 0xf1, 0x40, 0x2b, 0x50, 0x3c, 0xea, + 0x3e, 0xeb, 0x1e, 0x7c, 0xd6, 0x6d, 0xdc, 0x60, 0x65, 0x28, 0x60, 0xfb, 0x8d, 0x0c, 0x03, 0x58, + 0xa0, 0x36, 0x1b, 0x59, 0x56, 0x82, 0xfc, 0xe6, 0x41, 0x7f, 0xb7, 0x91, 0x33, 0xfe, 0x32, 0x03, + 0xab, 0x38, 0xe4, 0xe1, 0xac, 0x10, 0xb8, 0x0b, 0x95, 0x81, 0xe7, 0x4d, 0x84, 0xa5, 0x15, 0x6b, + 0x14, 0x3a, 0x48, 0x2c, 0x70, 0x12, 0xde, 0x27, 0x9e, 0x3f, 0xe0, 0x52, 0x06, 0x00, 0x82, 0x76, + 0x04, 0x44, 0xf0, 0xa0, 0x64, 0x62, 0xa2, 0x20, 0x11, 0x50, 0x21, 0x18, 0x91, 0xac, 0xc1, 0xc2, + 0xb1, 0xcf, 0xed, 0xc1, 0x99, 0x5c, 0xfd, 0xf2, 0x89, 0xbd, 0x1b, 0xfb, 0x00, 0x06, 0x82, 0xa7, + 0x46, 0x7c, 0x88, 0x4b, 0xa0, 0x64, 0x2e, 0x4a, 0xf8, 0x96, 0x04, 0x8b, 0xdd, 0xc8, 0x3e, 0xb6, + 0xdd, 0xa1, 0xe7, 0xf2, 0xa1, 0x34, 0x35, 0x62, 0x80, 0x71, 0x08, 0x6b, 0xb3, 0xe3, 0x93, 0xf2, + 0xe2, 0x43, 0x4d, 0x5e, 0x90, 0xe6, 0xbf, 0x71, 0x3d, 0x2b, 0x68, 0xb2, 0xe3, 0xef, 0xe5, 0x21, + 0x2f, 0x34, 0xc1, 0x6b, 0x95, 0x46, 0x5d, 0xb5, 0xcf, 0xcd, 0x85, 0x7f, 0xd0, 0xd5, 0x40, 0x2a, + 0x02, 0xf9, 0xb3, 0xca, 0x08, 0x41, 0xd5, 0x20, 0x42, 0xfb, 0x7c, 0x70, 0x2e, 0x1d, 0x5a, 0x84, + 0x36, 0xf9, 0xe0, 0x1c, 0x6d, 0x2a, 0x3b, 0xa4, 0xb2, 0xb4, 0xde, 0x8b, 0x81, 0x1d, 0x62, 0x49, + 0x89, 0xc2, 0x72, 0xc5, 0x08, 0x85, 0xa5, 0x9a, 0x50, 0x74, 0xdc, 0x63, 0x6f, 0xea, 0x0e, 0x71, + 0x79, 0x97, 0x4c, 0xf5, 0x88, 0xd1, 0x26, 0x94, 0x44, 0x62, 0x23, 0xa2, 0xd5, 0x5c, 0x12, 0x80, + 0xbe, 0xd8, 0x8a, 0x3e, 0x80, 0x72, 0x70, 0xe5, 0x0e, 0xf4, 0x35, 0xbc, 0x22, 0xe7, 0x47, 0x8c, + 0xfe, 0x41, 0xef, 0xca, 0x1d, 0xe0, 0x8a, 0x2d, 0x05, 0xf2, 0x17, 0x7b, 0x02, 0xa5, 0xc8, 0xef, + 0x4b, 0x12, 0xf8, 0xa6, 0x5e, 0x42, 0x39, 0x7b, 0xc9, 0xbc, 0x8e, 0x48, 0xd9, 0x43, 0x58, 0x40, + 0xe7, 0x6c, 0xd0, 0xac, 0x62, 0x21, 0xa5, 0xef, 0x8b, 0x6e, 0x60, 0xa0, 0x87, 0x0f, 0xd1, 0x51, + 0x6b, 0x4a, 0xb2, 0x8d, 0x67, 0x50, 0x4b, 0xd4, 0xa5, 0x1b, 0xd1, 0x35, 0x32, 0xa2, 0xdf, 0xd2, + 0x8d, 0xe8, 0x78, 0x27, 0x90, 0xc5, 0x74, 0xa3, 0xfa, 0xd7, 0xa0, 0xa4, 0x86, 0x22, 0xd6, 0x9f, + 0x5c, 0x3b, 0x56, 0xef, 0xf3, 0xee, 0x56, 0xe3, 0x06, 0x5b, 0x84, 0x4a, 0x6b, 0x0b, 0x97, 0x34, + 0x02, 0x32, 0x82, 0xe4, 0xb0, 0xd5, 0xeb, 0x45, 0x90, 0xac, 0xb1, 0x03, 0x8d, 0xd9, 0x9e, 0x0a, + 0x9e, 0x0c, 0x15, 0x4c, 0xba, 0xae, 0x63, 0x80, 0x30, 0x91, 0xc8, 0x1b, 0x4d, 0x7a, 0x38, 0x3d, + 0x18, 0x4f, 0xa0, 0x21, 0xf6, 0x35, 0x31, 0x55, 0x81, 0xe6, 0x02, 0x1e, 0x09, 0xdd, 0x4e, 0x77, + 0x5f, 0x97, 0xcc, 0x0a, 0xc1, 0xb0, 0x29, 0xe3, 0x43, 0x58, 0xd2, 0x8a, 0xc5, 0x26, 0xad, 0xd8, + 0x2b, 0x67, 0x4d, 0x5a, 0x34, 0x60, 0x08, 0x63, 0xac, 0xc3, 0xaa, 0x78, 0x6c, 0x9f, 0x73, 0x37, + 0xec, 0x4d, 0x8f, 0x29, 0xe6, 0xe8, 0x78, 0xae, 0x30, 0x6c, 0xca, 0x11, 0xe6, 0x7a, 0x26, 0x7f, + 0x20, 0xad, 0xdf, 0x2c, 0xb2, 0xc6, 0x86, 0xd6, 0x02, 0x16, 0x7c, 0x80, 0x7f, 0x13, 0x56, 0x70, + 0x39, 0x02, 0x89, 0x69, 0x3d, 0x6c, 0xb7, 0x4d, 0xeb, 0xa0, 0xbb, 0xd7, 0xe9, 0x0a, 0x41, 0x29, + 0xa6, 0x15, 0x01, 0x3b, 0x3b, 0x08, 0xc9, 0x18, 0x0d, 0xa8, 0x3f, 0xe5, 0x61, 0xc7, 0x3d, 0xf1, + 0x54, 0x7c, 0xed, 0xa7, 0x05, 0x58, 0x8c, 0x40, 0xb1, 0x15, 0x7d, 0xce, 0xfd, 0xc0, 0xf1, 0x5c, + 0x54, 0x88, 0xcb, 0xa6, 0x7a, 0x14, 0xbb, 0x9b, 0x33, 0xe4, 0x6e, 0xe8, 0x84, 0x57, 0x56, 0xc2, + 0xe5, 0x56, 0x57, 0x60, 0xb9, 0x8b, 0xae, 0x40, 0xc1, 0x1e, 0x39, 0xb6, 0x0a, 0xd5, 0xd2, 0x83, + 0x80, 0x0e, 0xbc, 0x91, 0xe7, 0xa3, 0xee, 0x5b, 0x36, 0xe9, 0x81, 0x3d, 0x82, 0x15, 0xa1, 0x83, + 0xeb, 0x7e, 0x50, 0x94, 0x1f, 0xe4, 0xfd, 0x63, 0xee, 0x74, 0x7c, 0x18, 0xfb, 0x42, 0x05, 0x46, + 0xec, 0x9d, 0xa2, 0x84, 0x54, 0x96, 0xa2, 0x02, 0x64, 0xce, 0x2d, 0xb9, 0xd3, 0x71, 0x0b, 0x31, + 0x11, 0xfd, 0x63, 0x58, 0x15, 0xf4, 0x91, 0x7a, 0x15, 0x95, 0x58, 0xc4, 0x12, 0xa2, 0xb2, 0x8e, + 0xc4, 0x45, 0x65, 0x6e, 0x41, 0x99, 0x7a, 0x25, 0xde, 0x78, 0x81, 0xd4, 0x78, 0xec, 0x0a, 0xf7, + 0x83, 0xb9, 0xa8, 0xea, 0x02, 0x29, 0x02, 0x33, 0x51, 0x55, 0x2d, 0x2e, 0x5b, 0x9a, 0x8d, 0xcb, + 0x3e, 0x86, 0xd5, 0x63, 0xc1, 0x82, 0x67, 0xdc, 0x1e, 0x72, 0xdf, 0x8a, 0x19, 0x9b, 0xcc, 0x95, + 0x65, 0x81, 0xdc, 0x45, 0x5c, 0xb4, 0x0e, 0x84, 0x9e, 0x23, 0xc4, 0x02, 0x1f, 0x5a, 0xa1, 0x67, + 0xa1, 0xfa, 0x83, 0x02, 0xa6, 0x64, 0xd6, 0x08, 0xdc, 0xf7, 0xb6, 0x04, 0x30, 0x49, 0x77, 0xea, + 0xdb, 0x93, 0x33, 0x69, 0x50, 0x44, 0x74, 0x4f, 0x05, 0x90, 0xbd, 0x06, 0x45, 0xc1, 0xf2, 0x2e, + 0xa7, 0xe0, 0x17, 0xa9, 0xec, 0x0a, 0xc4, 0xde, 0x82, 0x05, 0x6c, 0x23, 0x68, 0x36, 0x90, 0xdf, + 0xab, 0xb1, 0x20, 0x77, 0x5c, 0x53, 0xe2, 0x84, 0x32, 0x39, 0xf5, 0x1d, 0x92, 0x32, 0x65, 0x13, + 0x7f, 0xb3, 0xef, 0x6a, 0x22, 0x6b, 0x19, 0xcb, 0x2a, 0x7d, 0x60, 0x86, 0xd3, 0xae, 0x93, 0x5e, + 0xbf, 0x50, 0x61, 0xf4, 0xbd, 0x7c, 0xa9, 0xd2, 0xa8, 0x1a, 0xdf, 0x82, 0x02, 0xcd, 0x8e, 0x60, + 0x42, 0x9c, 0xbb, 0x8c, 0x64, 0x42, 0x84, 0x36, 0xa1, 0xe8, 0xf2, 0xf0, 0xc2, 0xf3, 0x9f, 0x2b, + 0xa7, 0xb4, 0x7c, 0x34, 0x7e, 0x84, 0xde, 0x94, 0x28, 0xe2, 0x4e, 0x86, 0xa1, 0x60, 0x0f, 0x7a, + 0xbd, 0xc1, 0x99, 0x2d, 0x1d, 0x3c, 0x25, 0x04, 0xf4, 0xce, 0xec, 0x39, 0xf6, 0xc8, 0xce, 0x07, + 0xdd, 0xdf, 0x82, 0xba, 0x8a, 0xf1, 0x07, 0xd6, 0x88, 0x9f, 0x84, 0x92, 0xdd, 0xab, 0x32, 0xc0, + 0x1f, 0xec, 0xf1, 0x93, 0xd0, 0xd8, 0x87, 0x25, 0xc9, 0x90, 0x07, 0x13, 0xae, 0x9a, 0xfe, 0x76, + 0x9a, 0x3e, 0x5d, 0x79, 0xbc, 0x9c, 0xdc, 0x68, 0x29, 0x77, 0x21, 0xa1, 0x64, 0x1b, 0x9f, 0x00, + 0xd3, 0xb7, 0x61, 0x59, 0x9f, 0xd4, 0x6a, 0x95, 0x2f, 0x5f, 0x85, 0xc4, 0x22, 0xdd, 0xd9, 0x19, + 0x8a, 0xd9, 0x09, 0xa6, 0x83, 0x81, 0xca, 0xbd, 0x28, 0x99, 0xea, 0xd1, 0xf8, 0xb3, 0x0c, 0x2c, + 0x63, 0x65, 0xca, 0x1e, 0x90, 0x42, 0xf6, 0x67, 0xee, 0xa4, 0x78, 0x3f, 0xba, 0xee, 0x43, 0x0f, + 0x5f, 0xdd, 0x7b, 0x9a, 0x9f, 0xf3, 0x9e, 0xbe, 0x0b, 0x8d, 0x21, 0x1f, 0x39, 0x98, 0x86, 0xa3, + 0x54, 0x09, 0xb2, 0x00, 0x16, 0x15, 0x5c, 0x5a, 0x83, 0xc6, 0x3f, 0xca, 0xc0, 0x12, 0x69, 0x2a, + 0x68, 0x57, 0xcb, 0x89, 0xfa, 0x58, 0x19, 0x92, 0x52, 0x54, 0xc9, 0x31, 0xc5, 0x3b, 0x38, 0x42, + 0x89, 0x78, 0xf7, 0x86, 0x34, 0x30, 0x25, 0x94, 0x7d, 0x84, 0x36, 0x8c, 0x6b, 0x21, 0x30, 0x25, + 0xad, 0x27, 0xf9, 0x52, 0x76, 0x6f, 0xa0, 0x81, 0xe3, 0x22, 0x68, 0xb3, 0x24, 0x2c, 0x5b, 0x01, + 0x36, 0x76, 0xa0, 0x96, 0x68, 0x26, 0xe1, 0xe2, 0xad, 0x92, 0x8b, 0x77, 0x2e, 0x8c, 0x92, 0x9d, + 0x0f, 0xa3, 0xfc, 0xad, 0x3c, 0x30, 0xc1, 0x52, 0x33, 0x6f, 0x6d, 0x26, 0x06, 0x99, 0x9d, 0x8b, + 0x41, 0x3e, 0x02, 0xa6, 0x11, 0xa8, 0xd0, 0x68, 0x2e, 0x0a, 0x8d, 0x36, 0x62, 0x5a, 0x19, 0x19, + 0x7d, 0x04, 0x2b, 0x52, 0xa1, 0x8d, 0x82, 0x8e, 0xe8, 0xbb, 0xa3, 0xf7, 0xc3, 0x48, 0xb3, 0x55, + 0xc1, 0x47, 0xf4, 0xe3, 0xa9, 0xf8, 0xa3, 0xb0, 0xc1, 0xc9, 0xe5, 0x85, 0xf1, 0x47, 0x65, 0x7d, + 0x6b, 0x5c, 0xb0, 0xf0, 0x52, 0x2e, 0x28, 0xce, 0x71, 0x81, 0xe6, 0x81, 0x29, 0x25, 0x3d, 0x30, + 0x06, 0xd4, 0x54, 0x94, 0x91, 0x92, 0x2b, 0x48, 0x7b, 0xab, 0xc8, 0x50, 0x23, 0x26, 0x58, 0xdc, + 0x83, 0x86, 0x72, 0x93, 0x44, 0x3e, 0x1e, 0x4a, 0x1c, 0x90, 0x5e, 0xb6, 0x2d, 0xe5, 0xe9, 0x49, + 0x78, 0xd4, 0x2b, 0x33, 0x1e, 0xf5, 0xf7, 0x60, 0x29, 0x10, 0x4c, 0x64, 0x4d, 0x5d, 0x99, 0xe5, + 0xc3, 0x87, 0x68, 0x3a, 0x95, 0xcc, 0x06, 0x22, 0x8e, 0x62, 0xf8, 0xbc, 0xff, 0xa2, 0x96, 0xe2, + 0xbf, 0x78, 0x12, 0x07, 0xe4, 0x82, 0x33, 0x67, 0x8c, 0x1b, 0x77, 0x9c, 0x11, 0x23, 0x27, 0xb8, + 0x77, 0xe6, 0x8c, 0x4d, 0x15, 0xfd, 0x15, 0x0f, 0xc6, 0xbf, 0xcd, 0x40, 0x43, 0xf0, 0x41, 0x82, + 0xcf, 0x7f, 0x05, 0x70, 0x45, 0xbe, 0x22, 0x9b, 0x57, 0x04, 0xad, 0xe2, 0xf2, 0x6f, 0x01, 0xb2, + 0xad, 0x25, 0xec, 0x44, 0xc9, 0xe4, 0xcd, 0x24, 0x93, 0xc7, 0x82, 0x6c, 0xf7, 0x06, 0x19, 0x00, + 0x02, 0x92, 0x16, 0x08, 0xcd, 0xa7, 0x04, 0x42, 0xb5, 0xa5, 0xb0, 0x0b, 0xf0, 0x8c, 0x5f, 0xed, + 0x79, 0x03, 0xb4, 0xd0, 0x6e, 0x03, 0x08, 0x86, 0x3c, 0xb1, 0xc7, 0x8e, 0xf4, 0xae, 0x14, 0xcc, + 0xf2, 0x73, 0x7e, 0xb5, 0x83, 0x00, 0xf1, 0x36, 0x04, 0x3a, 0x5e, 0x0f, 0x05, 0xb3, 0xf4, 0x9c, + 0x5f, 0xd1, 0x62, 0xb0, 0xa0, 0xf6, 0x8c, 0x5f, 0x6d, 0x73, 0x52, 0xd7, 0x3c, 0x5f, 0x70, 0x82, + 0x6f, 0x5f, 0x08, 0xfd, 0x2c, 0x11, 0xc4, 0xac, 0xf8, 0xf6, 0xc5, 0x33, 0x7e, 0xa5, 0x02, 0xaa, + 0x45, 0x81, 0x1f, 0x79, 0x03, 0xb9, 0x03, 0xa9, 0x74, 0x8c, 0xb8, 0x53, 0xe6, 0xc2, 0x73, 0xfc, + 0x6d, 0xfc, 0x55, 0x06, 0x6a, 0xa2, 0xff, 0x28, 0xe0, 0xc4, 0xbc, 0xab, 0xac, 0x9e, 0x4c, 0x9c, + 0xd5, 0xf3, 0x58, 0xca, 0x07, 0x92, 0x96, 0xd9, 0xeb, 0xa5, 0x25, 0x4e, 0x30, 0x89, 0xca, 0x0f, + 0xa0, 0x4c, 0x6b, 0x4b, 0x2c, 0xd6, 0x5c, 0xe2, 0x2d, 0x25, 0x06, 0x64, 0x96, 0x90, 0xec, 0x19, + 0x25, 0x11, 0x68, 0x9e, 0x3a, 0x9a, 0xe2, 0xb2, 0x1f, 0xf9, 0xe7, 0x52, 0x5e, 0x43, 0xe1, 0x9a, + 0x24, 0x02, 0xdd, 0x0d, 0xb6, 0x30, 0xe7, 0x06, 0x3b, 0x82, 0x8a, 0xc6, 0x74, 0xe8, 0xf7, 0x8b, + 0x46, 0x47, 0x1c, 0x9a, 0xe4, 0xaa, 0xc4, 0xf4, 0xec, 0xde, 0x30, 0x6b, 0x03, 0x1d, 0xb0, 0xb9, + 0x00, 0x79, 0x51, 0xc8, 0xf8, 0x18, 0x96, 0xb4, 0x6a, 0xc9, 0x5c, 0x4d, 0xeb, 0x74, 0x26, 0x2d, + 0x88, 0xfe, 0x8f, 0x33, 0xb0, 0x22, 0x4b, 0x63, 0x8a, 0x98, 0x23, 0xf6, 0xf3, 0xfd, 0xe0, 0x94, + 0xfd, 0x0a, 0xd4, 0x44, 0xed, 0x96, 0xcf, 0x4f, 0x9d, 0x20, 0xe4, 0x2a, 0x46, 0x92, 0xb2, 0x7a, + 0x84, 0x58, 0x17, 0xa4, 0xa6, 0xa4, 0x64, 0x1f, 0x43, 0x05, 0x8b, 0x92, 0x41, 0x2d, 0xdf, 0x5b, + 0x73, 0xbe, 0x20, 0x75, 0x75, 0xf7, 0x86, 0x09, 0x41, 0xf4, 0xb4, 0x59, 0x86, 0x62, 0xe8, 0x3b, + 0xa7, 0xa7, 0xdc, 0x37, 0xd6, 0xa2, 0xae, 0x89, 0xa5, 0xc8, 0x7b, 0x21, 0x9f, 0x08, 0x2d, 0xc9, + 0xf8, 0x8f, 0x19, 0xa8, 0xc8, 0xc5, 0xf5, 0x33, 0x07, 0x46, 0x36, 0xb4, 0x1c, 0x47, 0xb2, 0x9d, + 0xe3, 0x94, 0xc6, 0x77, 0x60, 0x71, 0x2c, 0x34, 0x26, 0xa1, 0xd1, 0x27, 0xa2, 0x22, 0x75, 0x05, + 0x96, 0x0a, 0xcb, 0x03, 0x58, 0x46, 0xfd, 0x25, 0xb0, 0x42, 0x67, 0x64, 0x29, 0xa4, 0xcc, 0x27, + 0x5c, 0x22, 0x54, 0xdf, 0x19, 0xed, 0x4b, 0x84, 0xd8, 0xc6, 0x83, 0xd0, 0x3e, 0xe5, 0x92, 0x37, + 0xe8, 0xc1, 0x68, 0xc2, 0xda, 0x8c, 0x32, 0xaf, 0x0c, 0x91, 0x3f, 0x58, 0x82, 0xf5, 0x39, 0x94, + 0x34, 0x48, 0xa2, 0x68, 0xc0, 0xc8, 0x19, 0x1f, 0x7b, 0x91, 0xaf, 0x2c, 0xa3, 0x45, 0x03, 0xf6, + 0x04, 0x46, 0xf9, 0xca, 0x38, 0xac, 0x2a, 0x86, 0x40, 0x67, 0x57, 0xa4, 0xef, 0x67, 0x51, 0x1b, + 0xfd, 0x20, 0x29, 0xc9, 0x66, 0x9b, 0x53, 0x70, 0x7d, 0x7f, 0x5c, 0x9e, 0xcc, 0xc1, 0x02, 0xf6, + 0x9b, 0xd0, 0x8c, 0xf8, 0x4e, 0x2a, 0x50, 0x9a, 0xf1, 0x22, 0x5a, 0x7a, 0xff, 0x25, 0x2d, 0x25, + 0xbc, 0x28, 0xb8, 0x81, 0xae, 0x29, 0x96, 0xa5, 0x0a, 0xa3, 0xb6, 0xce, 0xe1, 0x75, 0xd5, 0x16, + 0x2a, 0x44, 0xf3, 0x2d, 0xe6, 0x5f, 0x69, 0x6c, 0xe8, 0x21, 0x4a, 0x34, 0x6b, 0xde, 0x92, 0x15, + 0x47, 0x28, 0xbd, 0xdd, 0x33, 0x58, 0xbb, 0xb0, 0x9d, 0x50, 0x8d, 0x51, 0xb3, 0x9d, 0x0a, 0xd8, + 0xde, 0xe3, 0x97, 0xb4, 0xf7, 0x19, 0x15, 0x4e, 0xa8, 0x88, 0x2b, 0x17, 0xf3, 0xc0, 0x60, 0xe3, + 0x4f, 0xb3, 0x50, 0x4f, 0xd6, 0x22, 0x16, 0xb6, 0x14, 0x56, 0x4a, 0xe9, 0x90, 0x4a, 0xbb, 0xf4, + 0xe3, 0x76, 0x49, 0xd9, 0x98, 0xf7, 0x30, 0x67, 0x53, 0x3c, 0xcc, 0xba, 0x63, 0x37, 0xf7, 0xb2, + 0x48, 0x5a, 0xfe, 0x95, 0x22, 0x69, 0x85, 0xb4, 0x48, 0xda, 0xf5, 0xe1, 0x97, 0x85, 0x9f, 0x29, + 0xfc, 0x52, 0x7c, 0x41, 0xf8, 0x25, 0x11, 0x34, 0x2a, 0xcd, 0x04, 0x8d, 0x36, 0xfe, 0x2a, 0x03, + 0x6c, 0x9e, 0x97, 0xd9, 0x53, 0x72, 0xb5, 0xbb, 0x7c, 0x24, 0xe5, 0xdc, 0xd7, 0x5f, 0x6d, 0x3d, + 0xa8, 0xd7, 0xa7, 0x4a, 0xb3, 0x87, 0xb0, 0xac, 0xe7, 0x28, 0xeb, 0xd6, 0x4e, 0xcd, 0x64, 0x3a, + 0x2a, 0xb6, 0x89, 0xb5, 0x20, 0x63, 0xfe, 0xa5, 0x41, 0xc6, 0xc2, 0x4b, 0x83, 0x8c, 0x0b, 0xc9, + 0x20, 0xe3, 0xc6, 0x7f, 0xce, 0xc0, 0x72, 0x0a, 0xcb, 0xfd, 0xe2, 0xc6, 0x2c, 0x38, 0x25, 0x21, + 0x84, 0xb2, 0x92, 0x53, 0x74, 0xf9, 0xb3, 0x07, 0x95, 0x38, 0x6e, 0xa5, 0x72, 0xf8, 0xef, 0xbf, + 0x4c, 0x16, 0xc4, 0x25, 0x4c, 0xbd, 0xf8, 0xc6, 0xef, 0x67, 0xa1, 0xa2, 0x21, 0xc5, 0x2c, 0x12, + 0x83, 0x69, 0xb9, 0x1d, 0xa4, 0x07, 0xa0, 0xad, 0x76, 0x07, 0xa4, 0x33, 0x98, 0xf0, 0xb4, 0x14, + 0xe4, 0xa6, 0x8f, 0x04, 0x0f, 0x60, 0x59, 0x85, 0x41, 0x78, 0x9c, 0xc2, 0x25, 0x77, 0x86, 0x25, + 0x19, 0x0c, 0xe1, 0x51, 0x46, 0x18, 0x7b, 0xa8, 0x34, 0xf8, 0xf8, 0xdd, 0x21, 0x63, 0x92, 0xa7, + 0x75, 0x89, 0xd8, 0x59, 0xbd, 0x44, 0xc1, 0x95, 0x1f, 0xc0, 0xaa, 0x62, 0xe6, 0x64, 0x09, 0x72, + 0xbe, 0x32, 0xc9, 0xca, 0x7a, 0x91, 0xef, 0xc2, 0xed, 0x99, 0x3e, 0xcd, 0x14, 0xa5, 0x5c, 0xc3, + 0x9b, 0x89, 0xde, 0xe9, 0x35, 0x6c, 0xfc, 0x18, 0x6a, 0x09, 0xb1, 0xf6, 0x8b, 0x7b, 0xe5, 0xb3, + 0xf6, 0x31, 0xcd, 0xa8, 0x6e, 0x1f, 0x6f, 0xfc, 0x9f, 0x1c, 0xb0, 0x79, 0xc9, 0xfa, 0xcb, 0xec, + 0xc2, 0x3c, 0x63, 0xe6, 0x52, 0x18, 0xf3, 0xff, 0xd9, 0x6e, 0xff, 0x1e, 0x2c, 0xc9, 0xb3, 0x2c, + 0x5a, 0x2c, 0x8b, 0x16, 0x67, 0x23, 0x42, 0xa8, 0x5e, 0x7c, 0x6b, 0x36, 0xa6, 0x5e, 0x4a, 0xa4, + 0xef, 0x6b, 0xea, 0xce, 0x4c, 0x68, 0xfd, 0x08, 0x16, 0x6c, 0x77, 0x70, 0xe6, 0xf9, 0x68, 0x9a, + 0xd5, 0x1f, 0xff, 0xea, 0x57, 0xde, 0xec, 0x1e, 0xb4, 0xb0, 0x3c, 0xea, 0x58, 0xa6, 0xac, 0xcc, + 0xf8, 0x00, 0x2a, 0x1a, 0x18, 0xe3, 0x3b, 0x9d, 0xfd, 0xcd, 0x83, 0xc6, 0x0d, 0x56, 0x83, 0xb2, + 0xd9, 0xde, 0x3a, 0xf8, 0xb4, 0x6d, 0xb6, 0xb7, 0x1b, 0x19, 0x56, 0x82, 0xfc, 0xde, 0x41, 0xaf, + 0xdf, 0xc8, 0x1a, 0x1b, 0xd0, 0x94, 0x35, 0xce, 0xfb, 0x7a, 0x7f, 0x27, 0x1f, 0xb9, 0x59, 0x10, + 0x29, 0xad, 0xaa, 0x6f, 0x40, 0x55, 0x57, 0x46, 0x24, 0x47, 0xcc, 0x84, 0x53, 0x85, 0x3d, 0xe5, + 0x69, 0xb2, 0x7a, 0x0b, 0x28, 0x48, 0x36, 0x8c, 0x8a, 0x91, 0x86, 0xf9, 0x82, 0xa8, 0x0a, 0x2a, + 0xcf, 0x09, 0x36, 0xfc, 0xff, 0xa0, 0x9e, 0x74, 0x7c, 0x4a, 0x89, 0x94, 0x66, 0x5e, 0x88, 0xd2, + 0x09, 0x4f, 0x28, 0xfb, 0x2e, 0x34, 0x66, 0x1d, 0xa7, 0x32, 0xcb, 0xf9, 0x9a, 0xf2, 0x8b, 0x4e, + 0xd2, 0x97, 0xca, 0x76, 0x61, 0x25, 0x4d, 0x1d, 0x43, 0xfe, 0xb8, 0xde, 0xae, 0x64, 0xf3, 0x2a, + 0x17, 0xfb, 0xb6, 0xf4, 0x8f, 0x17, 0xd2, 0xa2, 0x8c, 0xda, 0x64, 0x3f, 0xa0, 0x7f, 0x9a, 0xa7, + 0xfc, 0x1c, 0x20, 0x86, 0xb1, 0x06, 0x54, 0x0f, 0x0e, 0xdb, 0x5d, 0x6b, 0x6b, 0xb7, 0xd5, 0xed, + 0xb6, 0xf7, 0x1a, 0x37, 0x18, 0x83, 0x3a, 0x86, 0x07, 0xb7, 0x23, 0x58, 0x46, 0xc0, 0x64, 0x9c, + 0x42, 0xc1, 0xb2, 0x6c, 0x05, 0x1a, 0x9d, 0xee, 0x0c, 0x34, 0xc7, 0x9a, 0xb0, 0x72, 0xd8, 0xa6, + 0x88, 0x62, 0xa2, 0xde, 0xbc, 0x50, 0xf1, 0xe5, 0x70, 0x85, 0x8a, 0x4f, 0x67, 0xb2, 0xe4, 0x3a, + 0x50, 0x9a, 0xef, 0xef, 0x66, 0x60, 0x75, 0x06, 0x11, 0x67, 0xda, 0x93, 0xde, 0x9b, 0xd4, 0x78, + 0xab, 0x08, 0x54, 0xab, 0xe9, 0x3d, 0x58, 0x8a, 0x7c, 0x05, 0x33, 0xbb, 0x52, 0x23, 0x42, 0x28, + 0xe2, 0x87, 0xb0, 0xac, 0xb9, 0x1c, 0x66, 0x64, 0x05, 0xd3, 0x50, 0xb2, 0x80, 0xb1, 0x1e, 0x65, + 0x34, 0xcf, 0xf4, 0x7a, 0x48, 0x07, 0xbd, 0x74, 0x44, 0x1c, 0x3e, 0x48, 0xf6, 0x57, 0x3d, 0xb2, + 0x47, 0x33, 0x8c, 0x90, 0xec, 0xad, 0xfe, 0xc2, 0x55, 0xf3, 0x7f, 0xb8, 0x00, 0xec, 0x93, 0x29, + 0xf7, 0xaf, 0x30, 0x93, 0x3e, 0x78, 0x59, 0x6a, 0x99, 0xb2, 0xab, 0xb3, 0xaf, 0x74, 0x5a, 0x26, + 0xed, 0xb4, 0x4a, 0xfe, 0xe5, 0xa7, 0x55, 0x0a, 0x2f, 0x3b, 0xad, 0xf2, 0x26, 0xd4, 0x9c, 0x53, + 0xd7, 0x13, 0xa2, 0x50, 0xe8, 0xad, 0x41, 0x73, 0xe1, 0x6e, 0xee, 0x5e, 0xd5, 0xac, 0x4a, 0xa0, + 0xd0, 0x5a, 0x03, 0xf6, 0x71, 0x4c, 0xc4, 0x87, 0xa7, 0x78, 0xb2, 0x4a, 0x17, 0x82, 0xed, 0xe1, + 0x29, 0x97, 0x6e, 0x04, 0xb4, 0x0b, 0x54, 0x61, 0x01, 0x0f, 0xd8, 0x5b, 0x50, 0x0f, 0xbc, 0xa9, + 0x30, 0x03, 0xd4, 0x34, 0x50, 0x80, 0xa1, 0x4a, 0xd0, 0x43, 0x15, 0x4d, 0x5a, 0x9e, 0x06, 0xdc, + 0x1a, 0x3b, 0x41, 0x20, 0xd4, 0xb3, 0x81, 0xe7, 0x86, 0xbe, 0x37, 0x92, 0x31, 0x83, 0xa5, 0x69, + 0xc0, 0xf7, 0x09, 0xb3, 0x45, 0x08, 0xf6, 0xcd, 0xb8, 0x4b, 0x13, 0xdb, 0xf1, 0x83, 0x26, 0x60, + 0x97, 0xd4, 0x48, 0x51, 0xdb, 0xb6, 0x1d, 0x3f, 0xea, 0x8b, 0x78, 0x08, 0x66, 0x4e, 0xd1, 0x54, + 0x66, 0x4f, 0xd1, 0xfc, 0x30, 0xfd, 0x14, 0x4d, 0x0d, 0xab, 0x7e, 0x24, 0xab, 0x9e, 0x7f, 0xc5, + 0x5f, 0xe9, 0x30, 0xcd, 0xfc, 0xe1, 0xa0, 0xfa, 0x57, 0x39, 0x1c, 0xb4, 0x98, 0x76, 0x38, 0xe8, + 0x03, 0xa8, 0xe0, 0xb1, 0x0d, 0xeb, 0xcc, 0x11, 0x3a, 0x1c, 0xc5, 0x40, 0x1a, 0xfa, 0xb9, 0x8e, + 0x5d, 0xc7, 0x0d, 0x4d, 0xf0, 0xd5, 0xcf, 0x60, 0xfe, 0x9c, 0xce, 0xd2, 0x2f, 0xf1, 0x9c, 0x8e, + 0x3c, 0x5e, 0xf2, 0x00, 0x4a, 0xea, 0x3d, 0x31, 0x06, 0xf9, 0x13, 0xdf, 0x1b, 0x2b, 0xdf, 0xb0, + 0xf8, 0xcd, 0xea, 0x90, 0x0d, 0x3d, 0x59, 0x38, 0x1b, 0x7a, 0xc6, 0x6f, 0x40, 0x45, 0x63, 0x35, + 0xf6, 0x06, 0x79, 0xa1, 0x84, 0x25, 0x25, 0x75, 0x4b, 0x9a, 0xc5, 0xb2, 0x84, 0x76, 0x86, 0x42, + 0xde, 0x0c, 0x1d, 0x9f, 0xe3, 0x89, 0x3a, 0xcb, 0xe7, 0xe7, 0xdc, 0x0f, 0x94, 0xaf, 0xbe, 0x11, + 0x21, 0x4c, 0x82, 0x1b, 0x7f, 0x0d, 0x96, 0x13, 0xef, 0x56, 0x8a, 0x88, 0xb7, 0x60, 0x01, 0xe7, + 0x4d, 0xc5, 0x52, 0x93, 0xe7, 0x65, 0x24, 0x0e, 0x8f, 0x4a, 0x53, 0x98, 0xc1, 0x9a, 0xf8, 0xde, + 0x31, 0x36, 0x92, 0x31, 0x2b, 0x12, 0x76, 0xe8, 0x7b, 0xc7, 0xc6, 0x5f, 0xe4, 0x20, 0xb7, 0xeb, + 0x4d, 0xf4, 0xf4, 0xa1, 0xcc, 0x5c, 0xfa, 0x90, 0x34, 0x0f, 0xad, 0xc8, 0xfc, 0x93, 0x3a, 0x3b, + 0x3a, 0xd8, 0x95, 0x09, 0x78, 0x0f, 0xea, 0x42, 0x4e, 0x84, 0x9e, 0xb0, 0xaf, 0x2f, 0x6c, 0x9f, + 0x14, 0xe2, 0x1c, 0x2d, 0x3e, 0x7b, 0x1c, 0xf6, 0xbd, 0x1d, 0x82, 0xb3, 0x15, 0xc8, 0x45, 0xe6, + 0x0b, 0xa2, 0xc5, 0x23, 0x5b, 0x83, 0x05, 0xcc, 0x23, 0xbd, 0x92, 0xc1, 0x42, 0xf9, 0xc4, 0xbe, + 0x0e, 0xcb, 0xc9, 0x7a, 0x49, 0x14, 0x49, 0xdd, 0x48, 0xaf, 0x18, 0x65, 0xd2, 0x4d, 0x10, 0x72, + 0x84, 0x68, 0x64, 0xce, 0xc1, 0x09, 0xe7, 0x88, 0xd2, 0x84, 0x5e, 0x29, 0x21, 0xf4, 0xee, 0x40, + 0x25, 0x1c, 0x9d, 0x5b, 0x13, 0xfb, 0x6a, 0xe4, 0xd9, 0x43, 0xb9, 0xbe, 0x21, 0x1c, 0x9d, 0x1f, + 0x12, 0x84, 0x3d, 0x04, 0x18, 0x4f, 0x26, 0x72, 0xed, 0xa1, 0xbf, 0x3a, 0x66, 0xe5, 0xfd, 0xc3, + 0x43, 0x62, 0x39, 0xb3, 0x3c, 0x9e, 0x4c, 0xe8, 0x27, 0xdb, 0x86, 0x7a, 0xea, 0xa9, 0xb7, 0xdb, + 0x2a, 0xed, 0xd1, 0x9b, 0x3c, 0x48, 0x59, 0x9c, 0xb5, 0x81, 0x0e, 0xdb, 0xf8, 0x2e, 0xb0, 0x9f, + 0xf3, 0xec, 0x59, 0x1f, 0xca, 0x51, 0xff, 0xf4, 0xa3, 0x5b, 0x98, 0xc8, 0x5c, 0x49, 0x1c, 0xdd, + 0x6a, 0x0d, 0x87, 0xbe, 0x90, 0x8b, 0xb4, 0x61, 0x46, 0x22, 0x1f, 0xb4, 0x1d, 0xb3, 0x45, 0x72, + 0xdf, 0xf8, 0xef, 0x19, 0x28, 0xd0, 0x39, 0xb2, 0xb7, 0x61, 0x91, 0xe8, 0xa3, 0x54, 0x2c, 0x19, + 0x62, 0xa4, 0x7d, 0xb7, 0x2f, 0xb3, 0xb0, 0xc4, 0xb2, 0xd0, 0xce, 0xc0, 0x66, 0xa3, 0x37, 0xaf, + 0x9d, 0x83, 0xbd, 0x03, 0xe5, 0xa8, 0x69, 0x8d, 0x75, 0x4a, 0xaa, 0x65, 0xf6, 0x3a, 0xe4, 0xcf, + 0xbc, 0x89, 0xf2, 0xd3, 0x40, 0x3c, 0x93, 0x26, 0xc2, 0xe3, 0xbe, 0x88, 0x36, 0xa8, 0xf3, 0xd2, + 0xbf, 0x10, 0x35, 0x82, 0x6c, 0x30, 0x3f, 0xc6, 0x85, 0x94, 0x31, 0x1e, 0xc1, 0xa2, 0x90, 0x03, + 0x5a, 0xa8, 0xff, 0xfa, 0x4d, 0xf3, 0x5d, 0xa1, 0xe1, 0x0d, 0x46, 0xd3, 0x21, 0xd7, 0x3d, 0x65, + 0x98, 0x17, 0x24, 0xe1, 0x4a, 0xb3, 0x36, 0xfe, 0x30, 0x43, 0xf2, 0x45, 0xd4, 0xcb, 0xee, 0x41, + 0x5e, 0xec, 0x6f, 0x33, 0x9e, 0xdc, 0x28, 0xa3, 0x5c, 0xd0, 0x99, 0x48, 0x81, 0x07, 0xc7, 0xa7, + 0xe3, 0x64, 0xed, 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0xa3, 0xe9, 0x6b, 0x6a, 0x58, 0x33, 0x4e, + 0x1a, 0x1a, 0x7d, 0xb4, 0x4c, 0x1f, 0x68, 0x09, 0x46, 0xf9, 0xc4, 0x8e, 0xa9, 0xb4, 0xc0, 0xe1, + 0x29, 0xd7, 0x12, 0x8b, 0xfe, 0x38, 0x0b, 0xb5, 0x44, 0x8f, 0x30, 0xc3, 0x4a, 0x6c, 0x00, 0x14, + 0x46, 0x90, 0xef, 0x1b, 0x04, 0x48, 0x2a, 0xea, 0xda, 0x3c, 0x65, 0x13, 0xf3, 0x14, 0x25, 0x35, + 0xe4, 0xf4, 0xa4, 0x86, 0x47, 0x50, 0x8e, 0xcf, 0x3e, 0x27, 0xbb, 0x24, 0xda, 0x53, 0x79, 0xf5, + 0x31, 0x51, 0x9c, 0x06, 0x51, 0xd0, 0xd3, 0x20, 0xbe, 0xa3, 0x45, 0xcd, 0x17, 0xb0, 0x1a, 0x23, + 0x6d, 0x46, 0x7f, 0x29, 0x31, 0x73, 0xe3, 0x63, 0xa8, 0x68, 0x9d, 0xd7, 0xa3, 0xe3, 0x99, 0x44, + 0x74, 0x3c, 0x3a, 0x01, 0x93, 0x8d, 0x4f, 0xc0, 0x18, 0xbf, 0x95, 0x85, 0x9a, 0x58, 0x5f, 0x8e, + 0x7b, 0x7a, 0xe8, 0x8d, 0x9c, 0x01, 0x86, 0x15, 0xa2, 0x15, 0x26, 0x15, 0x2d, 0xb5, 0xce, 0xe4, + 0x12, 0x23, 0x3d, 0x4b, 0x3f, 0xe8, 0x47, 0x42, 0x3a, 0x3a, 0xe8, 0x67, 0x40, 0x4d, 0x08, 0xc6, + 0x63, 0x3b, 0xe0, 0xda, 0xc9, 0x6c, 0xb3, 0x72, 0xc2, 0xf9, 0xa6, 0x1d, 0x90, 0x84, 0xfc, 0x3a, + 0x2c, 0x0b, 0x1a, 0x3c, 0xe3, 0x34, 0x76, 0x46, 0x23, 0x87, 0x28, 0xc9, 0xd1, 0xd4, 0x38, 0xe1, + 0xdc, 0xb4, 0x43, 0xbe, 0x2f, 0x10, 0xf2, 0x20, 0x77, 0x69, 0xe8, 0x04, 0xf6, 0x71, 0x9c, 0x07, + 0x17, 0x3d, 0x63, 0x30, 0xd0, 0xbe, 0xd4, 0x82, 0x81, 0xe4, 0x80, 0xa8, 0x8c, 0xed, 0xcb, 0x28, + 0x18, 0x38, 0xc3, 0x49, 0xc5, 0x59, 0x4e, 0x32, 0xfe, 0x7d, 0x16, 0x2a, 0x1a, 0x5b, 0xbe, 0xca, + 0xee, 0x7a, 0x7b, 0x2e, 0x0c, 0x54, 0xd6, 0x23, 0x3e, 0x6f, 0x26, 0x9b, 0xc4, 0x9c, 0x01, 0x3a, + 0x32, 0xae, 0x31, 0xf0, 0x2d, 0x28, 0x8b, 0x55, 0xf7, 0x01, 0x3a, 0x4c, 0xe5, 0x85, 0x07, 0x08, + 0x38, 0x9c, 0x1e, 0x2b, 0xe4, 0x63, 0x44, 0x16, 0x62, 0xe4, 0x63, 0x81, 0x7c, 0x51, 0xf2, 0xeb, + 0xb7, 0xa0, 0x2a, 0x6b, 0xc5, 0x77, 0x8a, 0xc3, 0x8d, 0x57, 0x7d, 0xe2, 0x7d, 0x9b, 0x15, 0x6a, + 0x8e, 0x5e, 0xbe, 0x2c, 0xf8, 0x58, 0x15, 0x2c, 0xbd, 0xac, 0xe0, 0x63, 0x7a, 0x30, 0x76, 0xa2, + 0x7c, 0x62, 0xcc, 0x57, 0x51, 0x72, 0xec, 0x21, 0x2c, 0x2b, 0x71, 0x35, 0x75, 0x6d, 0xd7, 0xf5, + 0xa6, 0xee, 0x80, 0xab, 0xa3, 0x31, 0x4c, 0xa2, 0x8e, 0x62, 0x8c, 0x31, 0x8c, 0xce, 0x4e, 0x52, + 0xde, 0xcb, 0x7d, 0x28, 0x90, 0x5e, 0x4e, 0xca, 0x47, 0xba, 0xe0, 0x22, 0x12, 0x76, 0x0f, 0x0a, + 0xa4, 0x9e, 0x67, 0xaf, 0x15, 0x36, 0x44, 0x60, 0xb4, 0x80, 0x89, 0x82, 0xfb, 0x3c, 0xf4, 0x9d, + 0x41, 0x10, 0x9f, 0xba, 0x29, 0x08, 0xfb, 0x93, 0xda, 0x8a, 0xd3, 0xdc, 0x63, 0x4a, 0xb4, 0x51, + 0x89, 0xc6, 0xf8, 0x6f, 0x19, 0x58, 0x4e, 0xd4, 0x21, 0xd5, 0xa5, 0x11, 0xac, 0x1d, 0xf3, 0xf0, + 0x82, 0x73, 0xd7, 0x15, 0xca, 0xd0, 0x80, 0xbb, 0xa1, 0x6f, 0x8f, 0xc4, 0x4b, 0xa2, 0x11, 0x3c, + 0x99, 0xab, 0x35, 0xf6, 0x81, 0x6c, 0xc6, 0x05, 0xb7, 0xa2, 0x72, 0x24, 0x3b, 0x56, 0x8f, 0xd3, + 0x70, 0x1b, 0x3f, 0x80, 0x8d, 0xeb, 0x0b, 0xa5, 0x9c, 0xad, 0x7b, 0x27, 0x29, 0x55, 0x22, 0x75, + 0x77, 0xe4, 0xd9, 0x21, 0x1e, 0xf8, 0xd5, 0x05, 0xcb, 0x3e, 0x40, 0x8c, 0x88, 0x77, 0xfe, 0x0c, + 0xaa, 0x76, 0xf4, 0x20, 0xf6, 0x23, 0xd7, 0xf3, 0xc7, 0xf6, 0xc8, 0xf9, 0x11, 0x1f, 0x5a, 0x71, + 0xdd, 0x19, 0x73, 0x31, 0x86, 0x63, 0x05, 0xc6, 0x03, 0x58, 0x44, 0xbd, 0x5e, 0xdb, 0xe6, 0x5e, + 0xa4, 0x0a, 0x1a, 0x2b, 0xc0, 0xba, 0x24, 0xb9, 0xf4, 0x24, 0xb8, 0xff, 0x92, 0x83, 0x8a, 0x06, + 0x16, 0x7b, 0x11, 0xa6, 0x4d, 0x59, 0x43, 0xc7, 0x1e, 0x73, 0x15, 0x10, 0xac, 0x99, 0x35, 0x84, + 0x6e, 0x4b, 0xa0, 0xd8, 0x89, 0xed, 0xf3, 0x53, 0xcb, 0x9b, 0x86, 0xd6, 0x90, 0x9f, 0xfa, 0x5c, + 0xf5, 0xb2, 0x6a, 0x9f, 0x9f, 0x1e, 0x4c, 0xc3, 0x6d, 0x84, 0x09, 0x2a, 0x21, 0x49, 0x34, 0x2a, + 0x99, 0xe9, 0x33, 0xb6, 0x2f, 0x63, 0x2a, 0x99, 0x6e, 0x46, 0x7c, 0x99, 0x8f, 0xd2, 0xcd, 0xc8, + 0x56, 0x9c, 0xdd, 0x3e, 0x0b, 0xf3, 0xdb, 0xe7, 0x37, 0x61, 0x8d, 0xb6, 0x4f, 0x29, 0x98, 0xad, + 0x99, 0x75, 0xbc, 0x82, 0x58, 0x39, 0x48, 0x4d, 0xe9, 0x6d, 0x88, 0x11, 0x28, 0xa1, 0x14, 0x38, + 0x3f, 0x22, 0x31, 0x96, 0x31, 0xc5, 0xc8, 0x64, 0xe5, 0x3d, 0xe7, 0x47, 0x5c, 0x50, 0x62, 0x3a, + 0x83, 0x4e, 0x29, 0x13, 0xdb, 0xc7, 0x8e, 0x3b, 0x4b, 0x69, 0x5f, 0x26, 0x29, 0xcb, 0x92, 0xd2, + 0xbe, 0xd4, 0x29, 0x9f, 0xc0, 0xfa, 0x98, 0x0f, 0x1d, 0x3b, 0x59, 0xad, 0x15, 0xab, 0x6d, 0x2b, + 0x84, 0xd6, 0xca, 0xf4, 0xc8, 0x6c, 0x17, 0xb3, 0xf1, 0x23, 0x6f, 0x7c, 0xec, 0x90, 0xc6, 0x42, + 0x09, 0x16, 0x79, 0xb3, 0xee, 0x4e, 0xc7, 0xdf, 0x47, 0xb0, 0x28, 0x12, 0x18, 0x35, 0xa8, 0xf4, + 0x42, 0x6f, 0xa2, 0x5e, 0x73, 0x1d, 0xaa, 0xf4, 0x28, 0x4f, 0x9b, 0xdd, 0x82, 0x9b, 0x28, 0x10, + 0xfa, 0xde, 0xc4, 0x1b, 0x79, 0xa7, 0x57, 0x09, 0x2f, 0xde, 0x7f, 0xca, 0xc0, 0x72, 0x02, 0x2b, + 0x85, 0xeb, 0x37, 0x49, 0x9a, 0x45, 0x47, 0x86, 0x68, 0x05, 0x2e, 0x69, 0x2b, 0x90, 0x08, 0x49, + 0x94, 0xa9, 0x63, 0x44, 0xad, 0xf8, 0xa8, 0xbb, 0x2a, 0x48, 0x02, 0xa5, 0x39, 0x2f, 0x50, 0x64, + 0x79, 0x75, 0x08, 0x5e, 0x55, 0xf1, 0xab, 0xf2, 0xf0, 0xc1, 0x50, 0x0e, 0x39, 0x97, 0x4c, 0xaf, + 0xd6, 0x3d, 0x7e, 0xaa, 0x07, 0xb1, 0x1b, 0x30, 0x30, 0xfe, 0x45, 0x06, 0x20, 0xee, 0x1d, 0x26, + 0x78, 0x47, 0x5a, 0x0b, 0xdd, 0x22, 0xa5, 0x69, 0x28, 0x6f, 0x40, 0x35, 0xca, 0xf3, 0x8c, 0xf5, + 0xa0, 0x8a, 0x82, 0x3d, 0xc3, 0x55, 0xbf, 0x78, 0x3a, 0xf2, 0x8e, 0x51, 0x5f, 0x95, 0x5a, 0x0b, + 0x9d, 0xb9, 0xab, 0x13, 0x58, 0xe9, 0x22, 0xb1, 0xd6, 0x94, 0x4f, 0x4d, 0x05, 0xd5, 0x75, 0x20, + 0xe3, 0xb7, 0xb3, 0x51, 0xc2, 0x5b, 0x3c, 0x13, 0x2f, 0x36, 0xee, 0x7e, 0x96, 0xbc, 0x89, 0x17, + 0x85, 0x02, 0x3f, 0x86, 0xba, 0x4f, 0x5b, 0x92, 0xda, 0xaf, 0xf2, 0x2f, 0xd8, 0xaf, 0x6a, 0x7e, + 0x42, 0xcf, 0x79, 0x17, 0x1a, 0xf6, 0xf0, 0x9c, 0xfb, 0xa1, 0x83, 0xbe, 0x7a, 0xd4, 0x8e, 0x65, + 0x8a, 0x99, 0x06, 0x47, 0x35, 0xf4, 0x1d, 0x58, 0x94, 0x27, 0x20, 0x23, 0x4a, 0x79, 0xa7, 0x4a, + 0x0c, 0x16, 0x84, 0xc6, 0xbf, 0x52, 0x19, 0x76, 0xc9, 0xb7, 0xfb, 0xe2, 0x59, 0xd1, 0x47, 0x98, + 0x9d, 0x0f, 0x76, 0x4a, 0x46, 0x92, 0x21, 0x00, 0x29, 0x8f, 0x08, 0x28, 0x03, 0x00, 0xc9, 0x69, + 0xcd, 0xbf, 0xca, 0xb4, 0x1a, 0x7f, 0x9a, 0x81, 0xe2, 0xae, 0x37, 0xd9, 0x75, 0x28, 0xc5, 0x19, + 0x97, 0x49, 0x14, 0xa1, 0x5a, 0x10, 0x8f, 0x9d, 0xe1, 0x8b, 0x0f, 0xfa, 0xa4, 0x2a, 0x79, 0xb5, + 0xa4, 0x92, 0xf7, 0x1d, 0xb8, 0x85, 0x01, 0x40, 0xdf, 0x9b, 0x78, 0xbe, 0x58, 0xaa, 0xf6, 0x88, + 0x94, 0x3d, 0xcf, 0x0d, 0xcf, 0x94, 0xec, 0xbc, 0x79, 0xc2, 0xf9, 0xa1, 0x46, 0xb1, 0x1f, 0x11, + 0xe0, 0x51, 0xba, 0x51, 0x78, 0x6e, 0x91, 0x7d, 0x2e, 0xb5, 0x51, 0x92, 0xa8, 0x8b, 0x02, 0xd1, + 0x46, 0x38, 0xea, 0xa3, 0xc6, 0xb7, 0xa1, 0x1c, 0xb9, 0x7a, 0xd8, 0x7b, 0x50, 0x3e, 0xf3, 0x26, + 0xd2, 0x1f, 0x94, 0x49, 0x1c, 0x86, 0x92, 0xa3, 0x36, 0x4b, 0x67, 0xf4, 0x23, 0x30, 0xfe, 0xa2, + 0x08, 0xc5, 0x8e, 0x7b, 0xee, 0x39, 0x03, 0xcc, 0xd1, 0x1b, 0xf3, 0xb1, 0xa7, 0x8e, 0x61, 0x8b, + 0xdf, 0x98, 0x87, 0x13, 0xdf, 0x8c, 0x92, 0x93, 0x79, 0x38, 0xd1, 0x9d, 0x28, 0xab, 0xb0, 0xe0, + 0xeb, 0x57, 0x9b, 0x14, 0x7c, 0xcc, 0x1a, 0x8e, 0xf6, 0xcb, 0x82, 0x76, 0x8c, 0x5d, 0xd4, 0x45, + 0x57, 0x6e, 0xe0, 0x94, 0xd1, 0xb1, 0xb8, 0x32, 0x42, 0x70, 0xc2, 0x5e, 0x83, 0xa2, 0x3c, 0x7b, + 0x44, 0x27, 0x39, 0x28, 0xcd, 0x57, 0x82, 0x90, 0x1b, 0x7c, 0x4e, 0x01, 0xdc, 0x48, 0x8d, 0xcd, + 0x99, 0x55, 0x05, 0xdc, 0x16, 0xbc, 0x76, 0x07, 0x2a, 0x44, 0x4f, 0x24, 0x25, 0x99, 0x55, 0x87, + 0x20, 0x24, 0x48, 0xb9, 0x21, 0xa8, 0x9c, 0x7a, 0x43, 0x10, 0x26, 0x61, 0x46, 0x52, 0x96, 0x86, + 0x08, 0x74, 0x2f, 0x8c, 0x06, 0x57, 0xd7, 0x63, 0x49, 0x8f, 0x0a, 0x9d, 0x12, 0x55, 0x1e, 0x95, + 0x37, 0xa1, 0x76, 0x62, 0x8f, 0x46, 0xc7, 0xf6, 0xe0, 0x39, 0x39, 0x02, 0xaa, 0xe4, 0xfb, 0x54, + 0x40, 0xf4, 0x04, 0xdc, 0x81, 0x8a, 0xf6, 0x96, 0x31, 0x65, 0x2e, 0x6f, 0x42, 0xfc, 0x7e, 0x67, + 0xfd, 0x7b, 0xf5, 0x57, 0xf0, 0xef, 0x69, 0xa9, 0x83, 0x8b, 0xc9, 0xd4, 0xc1, 0x5b, 0x28, 0x4d, + 0x65, 0x7a, 0x59, 0x83, 0x2e, 0x21, 0xb1, 0x87, 0x43, 0x4c, 0x2f, 0xa3, 0x1b, 0xff, 0x70, 0xf2, + 0x08, 0xbf, 0x44, 0x96, 0x04, 0xc1, 0x88, 0xe4, 0x36, 0x39, 0xa9, 0x27, 0xb6, 0x33, 0xc4, 0x54, + 0x6d, 0xf2, 0x1d, 0x14, 0xed, 0x71, 0x78, 0x68, 0x3b, 0x43, 0x76, 0x17, 0xaa, 0x0a, 0x8d, 0xbb, + 0xe3, 0x32, 0xcd, 0xbf, 0x44, 0x8b, 0x3d, 0xd1, 0x80, 0x5a, 0x44, 0x31, 0x8e, 0x8f, 0x7a, 0x56, + 0x24, 0x09, 0xf2, 0xc1, 0x07, 0x98, 0x91, 0x13, 0x72, 0x3c, 0xd0, 0x59, 0x7f, 0x7c, 0x4b, 0x8e, + 0x55, 0x72, 0xa9, 0xfa, 0x4f, 0xa1, 0x31, 0xa2, 0x14, 0xda, 0x2f, 0x45, 0xe8, 0xd6, 0x12, 0xda, + 0xaf, 0x24, 0xc5, 0x08, 0x1d, 0x11, 0xb0, 0x6f, 0x6b, 0xd6, 0x6b, 0x13, 0x89, 0x5f, 0x9b, 0xa9, + 0xff, 0xba, 0x93, 0x2a, 0xb7, 0x01, 0x9c, 0x40, 0xec, 0x32, 0x01, 0x77, 0x87, 0x78, 0x36, 0xb3, + 0x64, 0x96, 0x9d, 0xe0, 0x19, 0x01, 0x7e, 0xb1, 0x66, 0x6d, 0x0b, 0xaa, 0xfa, 0x30, 0x59, 0x09, + 0xf2, 0x07, 0x87, 0xed, 0x6e, 0xe3, 0x06, 0xab, 0x40, 0xb1, 0xd7, 0xee, 0xf7, 0xf7, 0x30, 0xce, + 0x57, 0x85, 0x52, 0x74, 0x30, 0x2c, 0x2b, 0x9e, 0x5a, 0x5b, 0x5b, 0xed, 0xc3, 0x7e, 0x7b, 0xbb, + 0x91, 0xfb, 0x5e, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0xbf, 0xcc, 0x41, 0x45, 0x9b, 0x85, 0x17, 0x0b, + 0xe3, 0xdb, 0x00, 0x68, 0x47, 0xc6, 0xd9, 0x87, 0x79, 0xb3, 0x2c, 0x20, 0xf4, 0xf2, 0xf5, 0x08, + 0x45, 0x8e, 0x6e, 0xb7, 0x51, 0x11, 0x8a, 0x37, 0xa1, 0x46, 0x17, 0xc5, 0xe8, 0xd1, 0xda, 0x82, + 0x59, 0x25, 0xa0, 0x14, 0xd5, 0x78, 0xb2, 0x14, 0x89, 0xf0, 0xcc, 0x91, 0xbc, 0x36, 0x82, 0x40, + 0x78, 0xea, 0x08, 0x8f, 0x8c, 0x05, 0xde, 0xe8, 0x9c, 0x13, 0x05, 0x69, 0x84, 0x15, 0x09, 0xeb, + 0xcb, 0x33, 0xb2, 0x52, 0x1e, 0x6a, 0x47, 0x1b, 0x0b, 0x66, 0x95, 0x80, 0xb2, 0xa1, 0xaf, 0x2b, + 0x06, 0x2a, 0x21, 0x03, 0xad, 0xcf, 0x73, 0x43, 0x82, 0x79, 0xf6, 0xe6, 0x9c, 0x88, 0x65, 0x64, + 0x8c, 0xaf, 0xcd, 0x97, 0x7b, 0xb9, 0x33, 0x91, 0xbd, 0x07, 0x6c, 0x3c, 0x99, 0x58, 0x29, 0xee, + 0xbd, 0xbc, 0xb9, 0x38, 0x9e, 0x4c, 0xfa, 0x9a, 0xf7, 0xeb, 0x17, 0xe0, 0x79, 0xfc, 0x02, 0x58, + 0x4b, 0x2c, 0x60, 0xec, 0x62, 0x64, 0x88, 0xc5, 0x62, 0x39, 0xa3, 0x8b, 0xe5, 0x14, 0xe9, 0x97, + 0x4d, 0x95, 0x7e, 0x2f, 0x92, 0x13, 0xc6, 0x0e, 0x54, 0x0e, 0xb5, 0x6b, 0xa8, 0xee, 0x8a, 0x1d, + 0x42, 0x5d, 0x40, 0x45, 0x7b, 0x07, 0x79, 0x14, 0x7d, 0x79, 0xef, 0x94, 0xd6, 0x9b, 0xac, 0xd6, + 0x1b, 0xe3, 0x9f, 0x67, 0xe8, 0x8a, 0x8f, 0xa8, 0xf3, 0xf1, 0xcd, 0x57, 0x2a, 0xf8, 0x16, 0x9f, + 0x40, 0xae, 0xa8, 0xa0, 0x9b, 0x3c, 0x3c, 0x8c, 0x5d, 0xb3, 0xbc, 0x93, 0x93, 0x80, 0xab, 0x0c, + 0x8f, 0x0a, 0xc2, 0x0e, 0x10, 0xa4, 0x94, 0x6f, 0xa1, 0xe1, 0x3b, 0x54, 0x7f, 0x20, 0xd3, 0x3a, + 0x84, 0xf2, 0xbd, 0x6f, 0x5f, 0xca, 0x56, 0x03, 0xa1, 0x82, 0xc8, 0xe8, 0x80, 0x3a, 0x41, 0x18, + 0x3d, 0x1b, 0xff, 0x44, 0x1e, 0x92, 0x9e, 0x9d, 0xdf, 0xfb, 0x50, 0x8a, 0x6a, 0x4d, 0xee, 0xb0, + 0x8a, 0x32, 0xc2, 0x8b, 0x7d, 0x1c, 0x5d, 0x21, 0x89, 0x1e, 0xd3, 0xe2, 0xc2, 0x08, 0x4f, 0x47, + 0xeb, 0xf5, 0xfb, 0xc0, 0x4e, 0x1c, 0x7f, 0x96, 0x98, 0x16, 0x5b, 0x03, 0x31, 0x1a, 0xb5, 0x71, + 0x04, 0xcb, 0x4a, 0x4a, 0x68, 0x16, 0x41, 0xf2, 0xe5, 0x65, 0x5e, 0x22, 0xe4, 0xb3, 0x73, 0x42, + 0xde, 0xf8, 0x49, 0x1e, 0x8a, 0xea, 0x4a, 0xb7, 0xb4, 0x6b, 0xc8, 0xca, 0xc9, 0x6b, 0xc8, 0x9a, + 0x89, 0x2b, 0x6b, 0xf0, 0xd5, 0xcb, 0xfd, 0xfe, 0x9d, 0xd9, 0x2d, 0x5b, 0x8b, 0x54, 0x24, 0xb6, + 0xed, 0x35, 0xc8, 0x4f, 0xec, 0xf0, 0x0c, 0xbd, 0x92, 0xc4, 0x3c, 0xf8, 0xac, 0x22, 0x18, 0x85, + 0x64, 0x04, 0x23, 0xed, 0xca, 0x36, 0x52, 0x49, 0xe7, 0xae, 0x6c, 0xbb, 0x05, 0xa4, 0x5f, 0x68, + 0x09, 0x6a, 0x25, 0x04, 0x88, 0xbd, 0x28, 0xa9, 0x8e, 0x94, 0x66, 0xd5, 0x91, 0x57, 0x56, 0x15, + 0xbe, 0x09, 0x0b, 0x74, 0xdd, 0x81, 0x3c, 0x29, 0xa9, 0x36, 0x14, 0x39, 0x87, 0xea, 0x3f, 0xa5, + 0xae, 0x9b, 0x92, 0x56, 0xbf, 0xff, 0xa8, 0x92, 0xb8, 0xff, 0x48, 0x8f, 0xac, 0x54, 0x93, 0x91, + 0x95, 0x7b, 0xd0, 0x88, 0x26, 0x14, 0xfd, 0x94, 0x6e, 0x20, 0xcf, 0x61, 0xd5, 0x15, 0x5c, 0x48, + 0xc9, 0x6e, 0x10, 0x6f, 0x88, 0xf5, 0xc4, 0x86, 0x28, 0x64, 0x58, 0x2b, 0x0c, 0xf9, 0x78, 0x12, + 0xca, 0x0d, 0x11, 0x4f, 0x6a, 0xe8, 0x1d, 0x4c, 0x9e, 0x21, 0xae, 0x41, 0xb9, 0xd3, 0xb5, 0x76, + 0xf6, 0x3a, 0x4f, 0x77, 0xfb, 0x8d, 0x8c, 0x78, 0xec, 0x1d, 0x6d, 0x6d, 0xb5, 0xdb, 0xdb, 0xb8, + 0xe3, 0x00, 0x2c, 0xec, 0xb4, 0x3a, 0x62, 0xf7, 0xc9, 0x19, 0xbf, 0x9b, 0x85, 0x8a, 0x56, 0x3d, + 0x7b, 0x12, 0xcd, 0x0a, 0x5d, 0x91, 0x73, 0x7b, 0xbe, 0x0b, 0x0f, 0x94, 0x28, 0xd6, 0xa6, 0x25, + 0xba, 0xa0, 0x2e, 0x7b, 0xed, 0x05, 0x75, 0xec, 0x6d, 0x58, 0xb4, 0xa9, 0x86, 0x68, 0x16, 0xa4, + 0x0f, 0x5e, 0x82, 0xe5, 0x24, 0x60, 0x5a, 0x66, 0xbc, 0x9f, 0x08, 0xba, 0xbc, 0xca, 0x84, 0x8c, + 0xb6, 0x14, 0x9c, 0xac, 0xe2, 0x89, 0xed, 0x8c, 0xa6, 0x3e, 0x97, 0x31, 0xf3, 0x68, 0x67, 0x26, + 0xa8, 0xa9, 0xd0, 0xc6, 0x87, 0x00, 0x71, 0x9f, 0x93, 0x93, 0x73, 0x23, 0x39, 0x39, 0x19, 0x6d, + 0x72, 0xb2, 0xc6, 0x36, 0x89, 0x11, 0x39, 0xd1, 0x91, 0xd3, 0xed, 0xeb, 0xa0, 0xdc, 0x80, 0x16, + 0x26, 0x47, 0x4f, 0x46, 0x3c, 0x54, 0xa7, 0xad, 0x97, 0x24, 0xa6, 0x13, 0x21, 0xd4, 0xe5, 0x07, + 0x71, 0x2d, 0xb1, 0x34, 0x92, 0x2c, 0x39, 0x2b, 0x8d, 0x24, 0xa9, 0x19, 0xe1, 0x8d, 0x0d, 0x68, + 0x6e, 0x73, 0x51, 0x5b, 0x6b, 0x34, 0x9a, 0xe9, 0x8e, 0x71, 0x0b, 0x6e, 0xa6, 0xe0, 0xa4, 0x13, + 0xe2, 0x13, 0x58, 0x6d, 0xd1, 0xc1, 0xea, 0x5f, 0xd4, 0x09, 0x2a, 0xa3, 0x09, 0x6b, 0xb3, 0x55, + 0xca, 0xc6, 0x76, 0x60, 0x69, 0x9b, 0x1f, 0x4f, 0x4f, 0xf7, 0xf8, 0x79, 0xdc, 0x10, 0x83, 0x7c, + 0x70, 0xe6, 0x5d, 0xc8, 0xf9, 0xc1, 0xdf, 0x98, 0x63, 0x28, 0x68, 0xac, 0x60, 0xc2, 0x07, 0xca, + 0x0d, 0x8d, 0x90, 0xde, 0x84, 0x0f, 0x8c, 0x27, 0xc0, 0xf4, 0x7a, 0xe4, 0x7c, 0x09, 0x2b, 0x61, + 0x7a, 0x6c, 0x05, 0x57, 0x41, 0xc8, 0xc7, 0xea, 0x06, 0x26, 0x08, 0xa6, 0xc7, 0x3d, 0x82, 0x18, + 0xef, 0x40, 0xf5, 0xd0, 0xbe, 0x32, 0xf9, 0x17, 0xf2, 0x6c, 0xd0, 0x3a, 0x14, 0x27, 0xf6, 0x95, + 0x10, 0x03, 0x51, 0x44, 0x0a, 0xd1, 0xc6, 0x1f, 0xe5, 0x61, 0x81, 0x28, 0xd9, 0x5d, 0xba, 0x24, + 0xd5, 0x71, 0x71, 0x19, 0x2a, 0x41, 0xa9, 0x81, 0xe6, 0x64, 0x69, 0x76, 0x5e, 0x96, 0x4a, 0x07, + 0x9a, 0xba, 0x1c, 0x46, 0xc5, 0x0e, 0xdc, 0xe9, 0x58, 0xdd, 0x08, 0x93, 0x3c, 0x5d, 0x9c, 0x8f, + 0x2f, 0xc1, 0xa5, 0xa3, 0x97, 0xc9, 0xe8, 0x6e, 0x6c, 0x8b, 0x50, 0xef, 0xd4, 0x16, 0x21, 0xc5, + 0xa5, 0x0e, 0x4a, 0x35, 0x78, 0x8a, 0xea, 0xd4, 0x59, 0xd2, 0xe0, 0x99, 0x33, 0x6c, 0x4a, 0x2f, + 0x37, 0x6c, 0xc8, 0xb3, 0xf6, 0x02, 0xc3, 0x06, 0x5e, 0xc1, 0xb0, 0x79, 0x85, 0xc8, 0xea, 0x4d, + 0x28, 0xe1, 0xbe, 0xaf, 0x49, 0x4f, 0xb1, 0xdf, 0x0b, 0xe9, 0xf9, 0x2d, 0x4d, 0xf5, 0xa7, 0xb4, + 0x8e, 0x5b, 0xf1, 0x32, 0x31, 0xf9, 0x17, 0xbf, 0x9c, 0x88, 0xd5, 0xe7, 0x50, 0x94, 0x50, 0xc1, + 0xd0, 0xae, 0x3d, 0x56, 0xf7, 0x6b, 0xe1, 0x6f, 0x31, 0x6d, 0x78, 0x29, 0xd0, 0x17, 0x53, 0xc7, + 0xe7, 0x43, 0x75, 0x71, 0x8a, 0x83, 0x6b, 0x54, 0x40, 0xc4, 0x00, 0x85, 0x19, 0xe2, 0x7a, 0x17, + 0xae, 0xbc, 0x36, 0xa1, 0xe8, 0x04, 0xcf, 0xc4, 0xa3, 0xc1, 0xa0, 0x81, 0x37, 0xec, 0x4d, 0x3c, + 0x5f, 0x6d, 0x4e, 0xc6, 0x4f, 0x32, 0xd0, 0x90, 0xab, 0x2b, 0xc2, 0xe9, 0x56, 0x40, 0xe1, 0xba, + 0x2c, 0x84, 0x17, 0x5f, 0x83, 0x62, 0x40, 0x0d, 0x9d, 0x1f, 0xd1, 0x4e, 0x45, 0xce, 0x9b, 0x8a, + 0x00, 0xee, 0xc8, 0xdd, 0xea, 0x75, 0xa8, 0xa8, 0x0c, 0xe8, 0xb1, 0x33, 0x52, 0xf7, 0x5d, 0x53, + 0x0a, 0xf4, 0xbe, 0x33, 0x52, 0x1b, 0x9d, 0x6f, 0xcb, 0x53, 0x90, 0x19, 0xdc, 0xe8, 0x4c, 0x3b, + 0xe4, 0xc6, 0xbf, 0xc9, 0xc0, 0x92, 0x36, 0x14, 0xb9, 0x6e, 0x3f, 0x82, 0x6a, 0x74, 0xb5, 0x25, + 0x8f, 0x34, 0xaf, 0xf5, 0xa4, 0xa0, 0x89, 0x8b, 0x55, 0x06, 0x11, 0x24, 0x10, 0x9d, 0x19, 0xda, + 0x57, 0x94, 0xa6, 0x3b, 0x1d, 0x2b, 0xe3, 0x66, 0x68, 0x5f, 0xed, 0x70, 0xde, 0x9b, 0x8e, 0x85, + 0xe9, 0x7a, 0xc1, 0xf9, 0xf3, 0x88, 0x80, 0x74, 0x2e, 0x10, 0x30, 0x49, 0x61, 0x40, 0x6d, 0xec, + 0xb9, 0xe1, 0x59, 0x44, 0x22, 0xb5, 0x4e, 0x04, 0x12, 0x8d, 0xf1, 0xe7, 0x59, 0x58, 0x26, 0x17, + 0x9b, 0x74, 0x6d, 0x4a, 0xd1, 0xd5, 0x84, 0x05, 0xf2, 0x36, 0x92, 0xf0, 0xda, 0xbd, 0x61, 0xca, + 0x67, 0xf6, 0xcd, 0x57, 0x74, 0x0b, 0xaa, 0x83, 0x96, 0xd7, 0x4c, 0x7f, 0x6e, 0x7e, 0xfa, 0xaf, + 0x9f, 0xde, 0xb4, 0x30, 0x67, 0x21, 0x2d, 0xcc, 0xf9, 0x2a, 0xc1, 0xc5, 0xb9, 0xd3, 0x88, 0x45, + 0x49, 0xa3, 0x9d, 0x46, 0x7c, 0x02, 0xeb, 0x09, 0x1a, 0x94, 0xd6, 0xce, 0x89, 0xc3, 0xd5, 0xad, + 0x14, 0x2b, 0x1a, 0x75, 0x4f, 0xe1, 0x36, 0x8b, 0x50, 0x08, 0x06, 0xde, 0x84, 0x1b, 0x6b, 0xb0, + 0x92, 0x9c, 0x55, 0xb9, 0x4d, 0xfc, 0x5e, 0x06, 0x9a, 0x32, 0x29, 0xc5, 0x71, 0x4f, 0x77, 0x9d, + 0x20, 0xf4, 0xfc, 0xe8, 0x0a, 0xc8, 0xdb, 0x00, 0x41, 0x68, 0xfb, 0xd2, 0xda, 0x94, 0xf7, 0x30, + 0x20, 0x04, 0x2d, 0xc9, 0x9b, 0x50, 0xe2, 0xee, 0x90, 0x90, 0xc4, 0x0d, 0x45, 0xee, 0x0e, 0x95, + 0x1d, 0x3a, 0xa7, 0x7f, 0xd7, 0x92, 0xe6, 0x85, 0x3c, 0x16, 0x2d, 0x66, 0x87, 0x9f, 0xe3, 0xc6, + 0x9b, 0x8f, 0x8e, 0x45, 0xef, 0xdb, 0x97, 0x98, 0xe2, 0x19, 0x18, 0xff, 0x30, 0x0b, 0x8b, 0x71, + 0xff, 0xe8, 0x4e, 0x85, 0x17, 0xdf, 0x0e, 0x71, 0x57, 0xb2, 0x83, 0x23, 0xf4, 0x77, 0xcd, 0xf1, + 0x58, 0xa2, 0xc5, 0xd9, 0x71, 0x99, 0x01, 0x15, 0x45, 0xe1, 0x4d, 0x43, 0xed, 0x26, 0xb6, 0x32, + 0x91, 0x1c, 0x4c, 0x43, 0x61, 0x70, 0x09, 0xcb, 0xd3, 0x71, 0xa5, 0xc9, 0x53, 0xb0, 0xc7, 0x61, + 0x07, 0x2f, 0x78, 0x17, 0x60, 0x51, 0x8c, 0x5e, 0xa4, 0xa0, 0x12, 0xf4, 0x0d, 0xd2, 0xb3, 0xe9, + 0xcd, 0xa1, 0x8e, 0xad, 0x2b, 0xa1, 0x74, 0xd7, 0x6d, 0xa4, 0x84, 0xbe, 0x0e, 0x15, 0xaa, 0x3c, + 0x3e, 0x7c, 0x9a, 0x37, 0xcb, 0xd8, 0x02, 0xe2, 0xa5, 0x13, 0xc8, 0x9b, 0x26, 0x4c, 0x5f, 0xa0, + 0xa6, 0x30, 0xe7, 0xe3, 0xef, 0x66, 0xe0, 0x66, 0xca, 0x6b, 0x93, 0xab, 0x7c, 0x0b, 0x96, 0x4e, + 0x22, 0xa4, 0x9a, 0x5d, 0x5a, 0xea, 0x6b, 0x4a, 0xac, 0x26, 0xe7, 0xd4, 0x6c, 0x9c, 0x24, 0x01, + 0xb1, 0xd1, 0x45, 0x6f, 0x30, 0x71, 0xbe, 0x18, 0x8d, 0x2e, 0x7a, 0x8d, 0x64, 0xef, 0x1c, 0xc2, + 0x46, 0xfb, 0x52, 0x48, 0x8c, 0x2d, 0xfd, 0x0b, 0x05, 0x8a, 0x8d, 0x92, 0x0e, 0xe6, 0xcc, 0x2b, + 0x39, 0x98, 0x87, 0x74, 0x8c, 0x32, 0xaa, 0xeb, 0x67, 0xa9, 0x04, 0x37, 0x50, 0x51, 0x86, 0xbe, + 0xb0, 0xa0, 0xce, 0x38, 0x0f, 0xa2, 0x2f, 0x2b, 0x18, 0x01, 0x2c, 0xee, 0x4f, 0x47, 0xa1, 0x13, + 0x7f, 0x6c, 0x81, 0x7d, 0x53, 0x96, 0xc1, 0x76, 0xd4, 0xac, 0xa5, 0x36, 0x04, 0x51, 0x43, 0x38, + 0x59, 0x63, 0x51, 0x91, 0x35, 0xdf, 0xde, 0xe2, 0x38, 0xd9, 0x82, 0x71, 0x13, 0xd6, 0xe3, 0x27, + 0x9a, 0x36, 0xb5, 0xd5, 0xfc, 0xb3, 0x0c, 0xe5, 0x93, 0x27, 0x3f, 0xfc, 0xc0, 0xda, 0xb0, 0x1c, + 0x38, 0xee, 0xe9, 0x88, 0xeb, 0xd5, 0x07, 0x72, 0x12, 0x56, 0x93, 0x7d, 0x93, 0x1f, 0x87, 0x30, + 0x97, 0xa8, 0x44, 0x5c, 0x5b, 0xc0, 0x36, 0xaf, 0xeb, 0x64, 0xcc, 0x16, 0x33, 0xb3, 0x31, 0xdf, + 0xf9, 0x0e, 0xd4, 0x93, 0x0d, 0xb1, 0x6f, 0xc9, 0x23, 0xc4, 0x71, 0xaf, 0x72, 0x33, 0x87, 0x3d, + 0x63, 0x86, 0xa8, 0xc4, 0x73, 0x1f, 0x18, 0x7f, 0x3f, 0x03, 0x4d, 0x93, 0x0b, 0xce, 0xd5, 0x7a, + 0xa9, 0x78, 0xe6, 0xa3, 0xb9, 0x5a, 0xaf, 0x1f, 0xab, 0x3a, 0x99, 0xac, 0x7a, 0xf4, 0xfe, 0xb5, + 0x2f, 0x63, 0xf7, 0xc6, 0xdc, 0x88, 0x36, 0x4b, 0xb0, 0x40, 0x24, 0xc6, 0x3a, 0xac, 0xca, 0xfe, + 0xa8, 0xbe, 0xc4, 0xd1, 0xc3, 0x44, 0x8b, 0x89, 0xe8, 0xe1, 0x06, 0x34, 0xe9, 0x26, 0x4f, 0x7d, + 0x10, 0xb2, 0xe0, 0x36, 0xb0, 0x7d, 0x7b, 0x60, 0xfb, 0x9e, 0xe7, 0x1e, 0x72, 0x5f, 0x66, 0xe7, + 0xa2, 0x86, 0x89, 0xc1, 0x35, 0xa5, 0x0a, 0xd3, 0x93, 0xba, 0x7f, 0xd2, 0x73, 0x55, 0x32, 0x12, + 0x3d, 0x19, 0x26, 0x2c, 0x6f, 0xda, 0xcf, 0xb9, 0xaa, 0x49, 0x4d, 0xd1, 0xc7, 0x50, 0x99, 0x44, + 0x95, 0xaa, 0x79, 0x57, 0xf7, 0x0c, 0xcc, 0x37, 0x6b, 0xea, 0xd4, 0xc6, 0x63, 0x58, 0x49, 0xd6, + 0x29, 0x45, 0xc7, 0x06, 0x94, 0xc6, 0x12, 0x26, 0x7b, 0x17, 0x3d, 0x1b, 0xbf, 0x53, 0x82, 0xa2, + 0xb4, 0xe7, 0xd8, 0x03, 0xc8, 0x0f, 0x54, 0x42, 0x58, 0x7c, 0x7d, 0x8d, 0xc4, 0xaa, 0xff, 0x5b, + 0x98, 0x16, 0x26, 0xe8, 0xd8, 0xc7, 0x50, 0x4f, 0x46, 0x45, 0x67, 0x0e, 0x31, 0x27, 0xc3, 0x99, + 0xb5, 0xc1, 0x4c, 0xfc, 0xab, 0x1c, 0x6f, 0x8e, 0xa4, 0x33, 0x94, 0xce, 0xb4, 0xdd, 0xd3, 0x73, + 0x85, 0xbe, 0x1d, 0x9c, 0xd9, 0xd6, 0xe3, 0x27, 0x1f, 0xca, 0x53, 0xcc, 0x15, 0x04, 0xf6, 0xce, + 0xec, 0xc7, 0x4f, 0x3e, 0x9c, 0xd5, 0xa4, 0xe5, 0x19, 0x66, 0x4d, 0x93, 0x5e, 0x81, 0x02, 0x5d, + 0xb4, 0x48, 0x99, 0x3d, 0xf4, 0xc0, 0x1e, 0xc1, 0x8a, 0x34, 0x5b, 0x2d, 0x99, 0x83, 0x4d, 0x52, + 0xb0, 0x44, 0xc7, 0xde, 0x24, 0xae, 0x87, 0x28, 0xf2, 0x0d, 0xad, 0xc1, 0xc2, 0x59, 0x7c, 0x6b, + 0x66, 0xcd, 0x94, 0x4f, 0xc6, 0x9f, 0x17, 0xa0, 0xa2, 0x4d, 0x0a, 0xab, 0x42, 0xc9, 0x6c, 0xf7, + 0xda, 0xe6, 0xa7, 0xed, 0xed, 0xc6, 0x0d, 0x76, 0x0f, 0xde, 0xea, 0x74, 0xb7, 0x0e, 0x4c, 0xb3, + 0xbd, 0xd5, 0xb7, 0x0e, 0x4c, 0x4b, 0x5d, 0xa2, 0x74, 0xd8, 0xfa, 0x7c, 0xbf, 0xdd, 0xed, 0x5b, + 0xdb, 0xed, 0x7e, 0xab, 0xb3, 0xd7, 0x6b, 0x64, 0xd8, 0x6b, 0xd0, 0x8c, 0x29, 0x15, 0xba, 0xb5, + 0x7f, 0x70, 0xd4, 0xed, 0x37, 0xb2, 0xec, 0x0e, 0xdc, 0xda, 0xe9, 0x74, 0x5b, 0x7b, 0x56, 0x4c, + 0xb3, 0xb5, 0xd7, 0xff, 0xd4, 0x6a, 0xff, 0xfa, 0x61, 0xc7, 0xfc, 0xbc, 0x91, 0x4b, 0x23, 0x10, + 0xc6, 0xb8, 0xaa, 0x21, 0xcf, 0x6e, 0xc2, 0x2a, 0x11, 0x50, 0x11, 0xab, 0x7f, 0x70, 0x60, 0xf5, + 0x0e, 0x0e, 0xba, 0x8d, 0x02, 0x5b, 0x82, 0x5a, 0xa7, 0xfb, 0x69, 0x6b, 0xaf, 0xb3, 0x6d, 0x99, + 0xed, 0xd6, 0xde, 0x7e, 0x63, 0x81, 0x2d, 0xc3, 0xe2, 0x2c, 0x5d, 0x51, 0x54, 0xa1, 0xe8, 0x0e, + 0xba, 0x9d, 0x83, 0xae, 0xf5, 0x69, 0xdb, 0xec, 0x75, 0x0e, 0xba, 0x8d, 0x12, 0x5b, 0x03, 0x96, + 0x44, 0xed, 0xee, 0xb7, 0xb6, 0x1a, 0x65, 0xb6, 0x0a, 0x4b, 0x49, 0xf8, 0xb3, 0xf6, 0xe7, 0x0d, + 0x60, 0x4d, 0x58, 0xa1, 0x8e, 0x59, 0x9b, 0xed, 0xbd, 0x83, 0xcf, 0xac, 0xfd, 0x4e, 0xb7, 0xb3, + 0x7f, 0xb4, 0xdf, 0xa8, 0xe0, 0xb5, 0x6e, 0xed, 0xb6, 0xd5, 0xe9, 0xf6, 0x8e, 0x76, 0x76, 0x3a, + 0x5b, 0x9d, 0x76, 0xb7, 0xdf, 0xa8, 0x52, 0xcb, 0x69, 0x03, 0xaf, 0x89, 0x02, 0xf2, 0xa0, 0x86, + 0xb5, 0xdd, 0xe9, 0xb5, 0x36, 0xf7, 0xda, 0xdb, 0x8d, 0x3a, 0xbb, 0x0d, 0x37, 0xfb, 0xed, 0xfd, + 0xc3, 0x03, 0xb3, 0x65, 0x7e, 0xae, 0x0e, 0x72, 0x58, 0x3b, 0xad, 0xce, 0xde, 0x91, 0xd9, 0x6e, + 0x2c, 0xb2, 0x37, 0xe0, 0xb6, 0xd9, 0xfe, 0xe4, 0xa8, 0x63, 0xb6, 0xb7, 0xad, 0xee, 0xc1, 0x76, + 0xdb, 0xda, 0x69, 0xb7, 0xfa, 0x47, 0x66, 0xdb, 0xda, 0xef, 0xf4, 0x7a, 0x9d, 0xee, 0xd3, 0x46, + 0x83, 0xbd, 0x05, 0x77, 0x23, 0x92, 0xa8, 0x82, 0x19, 0xaa, 0x25, 0x31, 0x3e, 0xf5, 0x4a, 0xbb, + 0xed, 0x5f, 0xef, 0x5b, 0x87, 0xed, 0xb6, 0xd9, 0x60, 0x6c, 0x03, 0xd6, 0xe2, 0xe6, 0xa9, 0x01, + 0xd9, 0xf6, 0xb2, 0xc0, 0x1d, 0xb6, 0xcd, 0xfd, 0x56, 0x57, 0xbc, 0xe0, 0x04, 0x6e, 0x45, 0x74, + 0x3b, 0xc6, 0xcd, 0x76, 0x7b, 0x95, 0x31, 0xa8, 0x6b, 0x6f, 0x65, 0xa7, 0x65, 0x36, 0xd6, 0xd8, + 0x22, 0x54, 0xf6, 0x0f, 0x0f, 0xad, 0x7e, 0x67, 0xbf, 0x7d, 0x70, 0xd4, 0x6f, 0xac, 0xb3, 0x55, + 0x68, 0x74, 0xba, 0xfd, 0xb6, 0x29, 0xde, 0xb5, 0x2a, 0xfa, 0xbf, 0x8a, 0x6c, 0x05, 0x16, 0x55, + 0x4f, 0x15, 0xf4, 0xa7, 0x45, 0xb6, 0x0e, 0xec, 0xa8, 0x6b, 0xb6, 0x5b, 0xdb, 0x62, 0xe2, 0x22, + 0xc4, 0xff, 0x2e, 0xca, 0x08, 0xc9, 0x4f, 0x72, 0xd1, 0x66, 0x1d, 0xa7, 0x1c, 0x24, 0xef, 0x50, + 0xae, 0x6a, 0x77, 0x1f, 0xbf, 0xec, 0xeb, 0x06, 0x9a, 0x69, 0x95, 0x9b, 0x33, 0xad, 0xe6, 0x6c, + 0xf7, 0x9a, 0xae, 0xfb, 0xbd, 0x09, 0xb5, 0x31, 0xdd, 0xa7, 0x2c, 0xef, 0x4d, 0x05, 0x99, 0x7f, + 0x43, 0x40, 0xba, 0x34, 0x75, 0xee, 0x7a, 0xff, 0xc2, 0xfc, 0xf5, 0xfe, 0x69, 0xfa, 0xfd, 0x42, + 0x9a, 0x7e, 0x7f, 0x1f, 0x96, 0x48, 0x34, 0x39, 0xae, 0x33, 0x56, 0x56, 0x33, 0x69, 0x81, 0x8b, + 0x28, 0xa2, 0x08, 0xae, 0xcc, 0x09, 0x65, 0x72, 0x48, 0x11, 0x52, 0x94, 0xd6, 0x46, 0xc2, 0xd2, + 0x20, 0xc9, 0x11, 0x59, 0x1a, 0x51, 0x0b, 0xf6, 0x65, 0xdc, 0x42, 0x45, 0x6b, 0x81, 0xe0, 0xd8, + 0xc2, 0x7d, 0x58, 0xe2, 0x97, 0xa1, 0x6f, 0x5b, 0xde, 0xc4, 0xfe, 0x62, 0x8a, 0x21, 0x5c, 0x1b, + 0x6d, 0xf8, 0xaa, 0xb9, 0x88, 0x88, 0x03, 0x84, 0x6f, 0xdb, 0xa1, 0x7d, 0xff, 0x4b, 0xa8, 0x68, + 0x77, 0x6d, 0xb3, 0x75, 0x58, 0xfe, 0xac, 0xd3, 0xef, 0xb6, 0x7b, 0x3d, 0xeb, 0xf0, 0x68, 0xf3, + 0x59, 0xfb, 0x73, 0x6b, 0xb7, 0xd5, 0xdb, 0x6d, 0xdc, 0x10, 0x8b, 0xb6, 0xdb, 0xee, 0xf5, 0xdb, + 0xdb, 0x09, 0x78, 0x86, 0xbd, 0x0e, 0x1b, 0x47, 0xdd, 0xa3, 0x5e, 0x7b, 0xdb, 0x4a, 0x2b, 0x97, + 0x15, 0x5c, 0x2a, 0xf1, 0x29, 0xc5, 0x73, 0xf7, 0xbf, 0x0b, 0xf5, 0xe4, 0x05, 0xb0, 0x0c, 0x60, + 0x61, 0xaf, 0xfd, 0xb4, 0xb5, 0xf5, 0x39, 0x5d, 0xfc, 0xd8, 0xeb, 0xb7, 0xfa, 0x9d, 0x2d, 0x4b, + 0x5e, 0xf4, 0x28, 0x24, 0x42, 0x86, 0x55, 0xa0, 0xd8, 0xea, 0x6e, 0xed, 0x1e, 0x98, 0xbd, 0x46, + 0xf6, 0xfe, 0xfb, 0x50, 0x4f, 0xe6, 0xd6, 0x89, 0x45, 0xb3, 0xd9, 0xee, 0x7f, 0xd6, 0x6e, 0x77, + 0xb1, 0x3f, 0x5b, 0xed, 0x6e, 0xdf, 0x6c, 0xed, 0x75, 0xfa, 0x9f, 0x37, 0x6e, 0xdc, 0xff, 0x18, + 0x1a, 0xb3, 0xd1, 0xab, 0x44, 0xb8, 0xef, 0x45, 0x71, 0xc1, 0xfb, 0xff, 0x32, 0x07, 0x10, 0x9f, + 0xe9, 0x10, 0x82, 0x69, 0xbb, 0xd5, 0x6f, 0xed, 0x1d, 0x88, 0x41, 0x9b, 0x07, 0x7d, 0x21, 0x6f, + 0xcc, 0xf6, 0x27, 0x8d, 0x1b, 0xa9, 0x98, 0x83, 0xc3, 0x7e, 0x23, 0x23, 0xe6, 0xb7, 0xd3, 0xed, + 0xf4, 0x3b, 0xad, 0x3d, 0xcb, 0x3c, 0x38, 0xea, 0x74, 0x9f, 0xd2, 0xfd, 0x77, 0x28, 0x93, 0x8f, + 0x0e, 0x77, 0xcc, 0x83, 0x6e, 0xdf, 0xea, 0xed, 0x1e, 0xf5, 0xb7, 0xf1, 0xf6, 0xbc, 0x2d, 0xb3, + 0x73, 0x48, 0x75, 0xe6, 0x5f, 0x44, 0x20, 0xaa, 0x2e, 0x88, 0x37, 0xf4, 0xf4, 0xa0, 0xd7, 0xeb, + 0x1c, 0x5a, 0x9f, 0x1c, 0xb5, 0xcd, 0x4e, 0xbb, 0x87, 0x05, 0x17, 0x52, 0xe0, 0x82, 0xbe, 0x28, + 0x24, 0x79, 0x7f, 0xef, 0x53, 0x29, 0x6a, 0x05, 0x69, 0x29, 0x09, 0x12, 0x54, 0x65, 0x31, 0x99, + 0x42, 0x56, 0xa5, 0xd4, 0x0c, 0xd7, 0xe0, 0x44, 0xb9, 0x8a, 0x90, 0xc2, 0x73, 0xaf, 0x0e, 0x8b, + 0x55, 0xd3, 0x51, 0xa2, 0x14, 0x0a, 0xe8, 0x68, 0x3b, 0xdb, 0xde, 0x36, 0xb1, 0x40, 0x7d, 0x0e, + 0x2a, 0x68, 0x17, 0xc5, 0x8b, 0x12, 0xc2, 0x4c, 0x90, 0x34, 0xd4, 0x83, 0xc0, 0x2c, 0x3d, 0xfe, + 0xed, 0x1c, 0xd4, 0xe9, 0x7c, 0x1d, 0x7d, 0x18, 0x8d, 0xfb, 0x6c, 0x1f, 0x8a, 0xf2, 0x0b, 0x7b, + 0x6c, 0x35, 0xba, 0x9a, 0x4c, 0xff, 0xa6, 0xdf, 0xc6, 0xda, 0x2c, 0x58, 0x2a, 0x6f, 0xcb, 0x7f, + 0xe3, 0xcf, 0xfe, 0xe7, 0x3f, 0xc8, 0xd6, 0x58, 0xe5, 0xe1, 0xf9, 0x07, 0x0f, 0x4f, 0xb9, 0x1b, + 0x88, 0x3a, 0xfe, 0x7f, 0x80, 0xf8, 0xbb, 0x71, 0xac, 0x19, 0x85, 0xac, 0x66, 0x3e, 0xaa, 0xb7, + 0x71, 0x33, 0x05, 0x23, 0xeb, 0xbd, 0x89, 0xf5, 0x2e, 0x1b, 0x75, 0x51, 0xaf, 0xe3, 0x3a, 0x21, + 0x7d, 0x43, 0xee, 0xa3, 0xcc, 0x7d, 0x36, 0x84, 0xaa, 0xfe, 0x45, 0x37, 0xa6, 0xf4, 0xaa, 0x94, + 0x6f, 0xd2, 0x6d, 0xdc, 0x4a, 0xc5, 0x29, 0x8d, 0x15, 0xdb, 0x58, 0x35, 0x1a, 0xa2, 0x8d, 0x29, + 0x52, 0xc4, 0xad, 0x8c, 0x48, 0x87, 0x8f, 0x3f, 0xdc, 0xc6, 0x5e, 0xd3, 0xb4, 0xb0, 0xb9, 0xcf, + 0xc6, 0x6d, 0xdc, 0xbe, 0x06, 0x2b, 0xdb, 0xba, 0x8d, 0x6d, 0xad, 0x1b, 0x4c, 0xb4, 0x35, 0x40, + 0x1a, 0xf5, 0xd9, 0xb8, 0x8f, 0x32, 0xf7, 0x1f, 0xff, 0x87, 0x77, 0xa1, 0x1c, 0xe5, 0xdb, 0xb2, + 0xdf, 0x84, 0x5a, 0xe2, 0x00, 0x24, 0x53, 0xc3, 0x48, 0x3b, 0x2f, 0xb9, 0xf1, 0x5a, 0x3a, 0x52, + 0x36, 0xfc, 0x3a, 0x36, 0xdc, 0x64, 0x6b, 0xa2, 0x61, 0x79, 0xc0, 0xf0, 0x21, 0x1e, 0x58, 0xa6, + 0x8b, 0xde, 0x9e, 0x6b, 0xb6, 0x0a, 0x35, 0xf6, 0xda, 0xac, 0xfd, 0x90, 0x68, 0xed, 0xf6, 0x35, + 0x58, 0xd9, 0xdc, 0x6b, 0xd8, 0xdc, 0x1a, 0x5b, 0xd1, 0x9b, 0x53, 0x89, 0x9a, 0x8c, 0xe3, 0xe5, + 0x8a, 0xfa, 0x77, 0xcd, 0xd8, 0xed, 0xf8, 0x2a, 0xbc, 0x94, 0xef, 0x9d, 0x45, 0x2c, 0x32, 0xff, + 0xd1, 0x33, 0xa3, 0x89, 0x4d, 0x31, 0x86, 0xaf, 0x4f, 0xff, 0xac, 0x19, 0x3b, 0x86, 0x8a, 0xf6, + 0x29, 0x10, 0x76, 0xf3, 0xda, 0xcf, 0x96, 0x6c, 0x6c, 0xa4, 0xa1, 0xd2, 0x86, 0xa2, 0xd7, 0xff, + 0xf0, 0x84, 0x73, 0xf6, 0x03, 0x28, 0x47, 0x1f, 0x98, 0x60, 0xeb, 0xda, 0x07, 0x3f, 0xf4, 0x0f, + 0x62, 0x6c, 0x34, 0xe7, 0x11, 0x69, 0xcc, 0xa7, 0xd7, 0x2e, 0x98, 0xef, 0x33, 0xa8, 0x68, 0x1f, + 0x91, 0x88, 0x06, 0x30, 0xff, 0xa1, 0x8a, 0x68, 0x00, 0x29, 0xdf, 0x9c, 0x30, 0x96, 0xb0, 0x89, + 0x0a, 0x2b, 0x23, 0x7f, 0x87, 0x97, 0x5e, 0xc0, 0xf6, 0x60, 0x55, 0xda, 0x65, 0xc7, 0xfc, 0xab, + 0xbc, 0x86, 0x94, 0x4f, 0xc9, 0x3d, 0xca, 0xb0, 0x8f, 0xa1, 0xa4, 0xbe, 0x15, 0xc2, 0xd6, 0xd2, + 0xbf, 0x79, 0xb2, 0xb1, 0x3e, 0x07, 0x97, 0x46, 0xd4, 0xe7, 0x00, 0xf1, 0x17, 0x2b, 0x22, 0x21, + 0x31, 0xf7, 0x05, 0x8c, 0x88, 0x03, 0xe6, 0x3f, 0x6f, 0x61, 0xac, 0xe1, 0x00, 0x1b, 0x0c, 0x85, + 0x84, 0xcb, 0x2f, 0xd4, 0x0d, 0xb8, 0x3f, 0x84, 0x8a, 0xf6, 0xd1, 0x8a, 0x68, 0xfa, 0xe6, 0x3f, + 0x78, 0x11, 0x4d, 0x5f, 0xca, 0x37, 0x2e, 0x8c, 0x0d, 0xac, 0x7d, 0xc5, 0x58, 0x14, 0xb5, 0x0b, + 0xc5, 0x4c, 0x2a, 0x48, 0xe2, 0x05, 0x9d, 0x41, 0x2d, 0xf1, 0x65, 0x8a, 0x68, 0x85, 0xa6, 0x7d, + 0xf7, 0x22, 0x5a, 0xa1, 0xa9, 0x1f, 0xb3, 0x50, 0x7c, 0x66, 0x2c, 0x89, 0x76, 0xce, 0x91, 0x44, + 0x6b, 0xe9, 0xfb, 0x50, 0xd1, 0xbe, 0x32, 0x11, 0x8d, 0x65, 0xfe, 0x83, 0x16, 0xd1, 0x58, 0xd2, + 0x3e, 0x4a, 0xb1, 0x82, 0x6d, 0xd4, 0x0d, 0x64, 0x05, 0xbc, 0xc3, 0x53, 0xd4, 0xfd, 0x9b, 0x50, + 0x4f, 0x7e, 0x78, 0x22, 0x5a, 0xfb, 0xa9, 0x5f, 0xb0, 0x88, 0xd6, 0xfe, 0x35, 0x5f, 0xab, 0x90, + 0x2c, 0x7d, 0x7f, 0x39, 0x6a, 0xe4, 0xe1, 0x8f, 0xe5, 0xc9, 0xa1, 0x2f, 0xd9, 0x27, 0x42, 0xc0, + 0xc9, 0x2b, 0x64, 0xd9, 0xba, 0xc6, 0xb5, 0xfa, 0x5d, 0xb4, 0xd1, 0x7a, 0x99, 0xbb, 0x6d, 0x36, + 0xc9, 0xcc, 0x58, 0x39, 0x7b, 0x0a, 0xcb, 0x11, 0x33, 0x47, 0x77, 0xc2, 0x06, 0xd1, 0x18, 0x52, + 0x6f, 0x9e, 0xdd, 0x68, 0xcc, 0x62, 0x1f, 0x65, 0x68, 0xfb, 0xc3, 0x9b, 0x38, 0xb5, 0xed, 0x4f, + 0xbf, 0x16, 0x56, 0xdb, 0xfe, 0x12, 0x17, 0x76, 0xce, 0x6e, 0x7f, 0xa1, 0x23, 0xea, 0x70, 0x61, + 0x71, 0xf6, 0x86, 0xd6, 0xdb, 0xd7, 0xdd, 0xcc, 0x40, 0xd5, 0xbf, 0xfe, 0xe2, 0x8b, 0x1b, 0x92, + 0xa2, 0x48, 0x49, 0xd3, 0x87, 0x32, 0x55, 0x85, 0xfd, 0x06, 0x54, 0xf5, 0xcb, 0xea, 0x99, 0x2e, + 0x13, 0x66, 0x5b, 0xba, 0x95, 0x8a, 0x4b, 0x72, 0x09, 0xab, 0xea, 0xcd, 0xb0, 0x4f, 0x61, 0x2d, + 0x9a, 0x66, 0xfd, 0x6a, 0x81, 0x80, 0xdd, 0x49, 0xb9, 0x70, 0x20, 0x31, 0xd9, 0x37, 0xaf, 0xbd, + 0x91, 0xe0, 0x51, 0x46, 0x70, 0x5f, 0xf2, 0xd6, 0xec, 0x78, 0xe7, 0x49, 0xbb, 0x2c, 0x3c, 0xde, + 0x79, 0x52, 0xaf, 0xda, 0x56, 0xdc, 0xc7, 0x96, 0x13, 0x73, 0x44, 0x49, 0xbc, 0xec, 0xfb, 0xb0, + 0xa8, 0xdd, 0x9b, 0xd0, 0xbb, 0x72, 0x07, 0xd1, 0x4a, 0x9a, 0xbf, 0xf6, 0x71, 0x23, 0xcd, 0x93, + 0x69, 0xac, 0x63, 0xfd, 0x4b, 0x46, 0x62, 0x72, 0xc4, 0x2a, 0xda, 0x82, 0x8a, 0x7e, 0x27, 0xc3, + 0x0b, 0xea, 0x5d, 0xd7, 0x50, 0xfa, 0x0d, 0x83, 0x8f, 0x32, 0x6c, 0x0f, 0x1a, 0xb3, 0xf7, 0x9d, + 0x45, 0x32, 0x25, 0xed, 0x8e, 0xb6, 0x8d, 0x19, 0x64, 0xe2, 0x96, 0x34, 0x76, 0x48, 0xc7, 0x40, + 0xa2, 0xef, 0xae, 0x79, 0xfe, 0xec, 0xae, 0x9e, 0xfc, 0x1e, 0x5b, 0x54, 0x5b, 0xda, 0x97, 0xf8, + 0xee, 0x65, 0x1e, 0x65, 0xd8, 0xef, 0x66, 0xa0, 0x9a, 0xb8, 0x41, 0x28, 0x91, 0x68, 0x3f, 0x33, + 0xce, 0xa6, 0x8e, 0xd3, 0x07, 0x6a, 0x98, 0x38, 0x89, 0x7b, 0xf7, 0xbf, 0x97, 0x78, 0x49, 0x3f, + 0x4e, 0x04, 0x02, 0x1f, 0xcc, 0x7e, 0x98, 0xed, 0xcb, 0x59, 0x02, 0xfd, 0x36, 0xcf, 0x2f, 0x1f, + 0x65, 0xd8, 0xbf, 0xce, 0x40, 0x3d, 0x19, 0xe1, 0x8f, 0x86, 0x9b, 0x9a, 0x4b, 0x10, 0xb1, 0xd2, + 0x35, 0x69, 0x01, 0xdf, 0xc7, 0x5e, 0xf6, 0xef, 0x9b, 0x89, 0x5e, 0xca, 0xfb, 0xde, 0x7f, 0xbe, + 0xde, 0xb2, 0x8f, 0xe8, 0x3b, 0xa8, 0x2a, 0xf1, 0x89, 0xcd, 0x7f, 0x37, 0x33, 0x62, 0x3f, 0xfd, + 0x2b, 0x93, 0xf8, 0x12, 0x7e, 0x48, 0x1f, 0x20, 0x53, 0x79, 0x34, 0x82, 0x8b, 0x5f, 0xb5, 0xbc, + 0xf1, 0x16, 0x8e, 0xe9, 0x75, 0xe3, 0x66, 0x62, 0x4c, 0xb3, 0x8a, 0x47, 0x8b, 0x7a, 0x27, 0x3f, + 0x12, 0x19, 0xef, 0x9c, 0x73, 0x1f, 0x8e, 0xbc, 0xbe, 0x93, 0x63, 0xea, 0xa4, 0x24, 0x4f, 0x2c, + 0xb5, 0x57, 0xac, 0xc6, 0xb8, 0x8f, 0x7d, 0x7d, 0xcb, 0xb8, 0x73, 0x6d, 0x5f, 0x1f, 0x62, 0xb4, + 0x5e, 0xf4, 0xf8, 0x10, 0x20, 0x4e, 0x4c, 0x64, 0x33, 0xe9, 0x71, 0x91, 0x00, 0x9a, 0xcf, 0x5d, + 0x4c, 0xae, 0x67, 0x95, 0x45, 0x27, 0x6a, 0xfc, 0x01, 0x89, 0xd3, 0x28, 0x71, 0x4f, 0xd7, 0xbe, + 0x92, 0x39, 0x84, 0x09, 0xed, 0x6b, 0xb6, 0xfe, 0x84, 0x30, 0x8d, 0xb2, 0xf4, 0x8e, 0xa0, 0xb6, + 0xe7, 0x79, 0xcf, 0xa7, 0x93, 0x28, 0x19, 0x3e, 0x99, 0x42, 0xb3, 0x6b, 0x07, 0x67, 0x1b, 0x33, + 0xa3, 0x30, 0xee, 0x62, 0x55, 0x1b, 0xac, 0xa9, 0x55, 0xf5, 0xf0, 0xc7, 0x71, 0x36, 0xe4, 0x97, + 0xcc, 0x86, 0xa5, 0x48, 0x46, 0xc7, 0x19, 0x87, 0xc9, 0x6a, 0x12, 0x92, 0x79, 0xb6, 0x89, 0x84, + 0x99, 0xa0, 0x7a, 0xfb, 0x30, 0x50, 0x75, 0x3e, 0xca, 0xb0, 0x43, 0xa8, 0x6e, 0xf3, 0x01, 0xde, + 0xa5, 0x80, 0x89, 0x28, 0xcb, 0x89, 0xa4, 0x06, 0xca, 0x60, 0xd9, 0xa8, 0x25, 0x80, 0xc9, 0x7d, + 0x6b, 0x62, 0x5f, 0xf9, 0xfc, 0x8b, 0x87, 0x3f, 0x96, 0x29, 0x2e, 0x5f, 0xaa, 0x7d, 0x4b, 0xa5, + 0x00, 0x25, 0xf6, 0xad, 0x99, 0x9c, 0xa1, 0xc4, 0xbe, 0x35, 0x97, 0x33, 0x94, 0x98, 0x6a, 0x95, + 0x82, 0xc4, 0x46, 0xb0, 0x34, 0x97, 0x66, 0x14, 0x6d, 0x59, 0xd7, 0x25, 0x27, 0x6d, 0xdc, 0xbd, + 0x9e, 0x20, 0xd9, 0xda, 0xfd, 0x64, 0x6b, 0x3d, 0xa8, 0xd1, 0x05, 0xa3, 0xc7, 0x9c, 0x4e, 0x55, + 0xce, 0x5c, 0x49, 0xa4, 0x1f, 0xd9, 0x9c, 0xdd, 0x60, 0x10, 0x97, 0xd4, 0x70, 0xf0, 0x64, 0x1d, + 0x3b, 0xc1, 0xfb, 0xe9, 0xb5, 0x63, 0x8c, 0x11, 0x33, 0xce, 0x1f, 0xad, 0x8c, 0x98, 0x31, 0xe5, + 0xd4, 0xa3, 0x32, 0x3f, 0xd9, 0x6a, 0x54, 0xf7, 0x43, 0xd7, 0x1b, 0xf2, 0xb1, 0xac, 0xf5, 0x07, + 0x50, 0x79, 0xca, 0x43, 0x75, 0x72, 0x30, 0xd2, 0xe5, 0x67, 0x8e, 0x12, 0x6e, 0xa4, 0x9c, 0xf6, + 0x4c, 0xf2, 0x26, 0xd5, 0xcc, 0x87, 0xa7, 0x9c, 0x84, 0xa0, 0xe5, 0x0c, 0xbf, 0x64, 0xbf, 0x8e, + 0x95, 0x47, 0xa7, 0xe4, 0xd7, 0xb4, 0x6e, 0xea, 0x95, 0x2f, 0xce, 0xc0, 0xd3, 0x6a, 0x16, 0x7d, + 0xd6, 0x74, 0x4a, 0x17, 0x2a, 0xda, 0x6d, 0x1a, 0xd1, 0xdc, 0xcc, 0xdf, 0x9e, 0x12, 0xcd, 0x4d, + 0xca, 0xe5, 0x1b, 0xc6, 0x3d, 0x6c, 0xc7, 0x60, 0x77, 0xe3, 0x76, 0xe8, 0xc2, 0x8d, 0xb8, 0xa5, + 0x87, 0x3f, 0xb6, 0xc7, 0xe1, 0x97, 0xec, 0x33, 0x7a, 0x1d, 0xda, 0xc9, 0xc8, 0xd8, 0x38, 0x99, + 0x3d, 0x44, 0x19, 0x4d, 0x96, 0x86, 0x4a, 0x1a, 0x2c, 0xd4, 0x14, 0x6a, 0x8c, 0x4f, 0x00, 0x7a, + 0xa1, 0x37, 0xd9, 0xb6, 0xf9, 0xd8, 0x73, 0x63, 0x99, 0x1e, 0x9f, 0xd5, 0x8b, 0xe5, 0xa4, 0x76, + 0x60, 0x8f, 0x7d, 0xa6, 0x59, 0x73, 0x89, 0x13, 0xbd, 0x8a, 0x89, 0xaf, 0x3d, 0xce, 0x17, 0x4d, + 0x48, 0xca, 0x91, 0xbe, 0x47, 0x19, 0xd6, 0x02, 0x88, 0xf3, 0xd9, 0x22, 0xdb, 0x6c, 0x2e, 0x55, + 0x2e, 0x12, 0xaf, 0x29, 0xc9, 0x6f, 0x87, 0x50, 0x8e, 0x13, 0x81, 0xd6, 0xe3, 0xcb, 0x81, 0x12, + 0x69, 0x43, 0x91, 0xa6, 0x30, 0x97, 0x84, 0x63, 0x34, 0x70, 0xaa, 0x80, 0x95, 0xc4, 0x54, 0x9d, + 0x70, 0x1e, 0x30, 0x07, 0x96, 0xa9, 0x83, 0x91, 0x5a, 0x86, 0x67, 0xcc, 0xa2, 0xaf, 0x42, 0xcc, + 0xe7, 0xc3, 0x44, 0x52, 0x23, 0x35, 0xab, 0x23, 0xe1, 0x62, 0x12, 0xdc, 0x4a, 0xe7, 0xdb, 0xc4, + 0x16, 0x30, 0x86, 0xa5, 0xb9, 0xc4, 0x81, 0x48, 0x74, 0x5c, 0x97, 0x09, 0x12, 0x89, 0x8e, 0x6b, + 0x73, 0x0e, 0x8c, 0x55, 0x6c, 0x72, 0xd1, 0x00, 0x34, 0x29, 0x2f, 0x9c, 0x70, 0x70, 0x26, 0x9a, + 0xfb, 0xfd, 0x0c, 0x2c, 0xa7, 0xa4, 0x06, 0xb0, 0x37, 0x94, 0x77, 0xe2, 0xda, 0xb4, 0x81, 0x8d, + 0xd4, 0x10, 0xb2, 0xd1, 0xc3, 0x76, 0xf6, 0xd9, 0xb3, 0xc4, 0x06, 0x4a, 0x11, 0x5c, 0xb9, 0x32, + 0x5f, 0xa8, 0xbc, 0xa4, 0x6a, 0x2e, 0x5f, 0xc0, 0x3a, 0x75, 0xa4, 0x35, 0x1a, 0xcd, 0x84, 0xb7, + 0x5f, 0xd7, 0x7a, 0x91, 0x12, 0xb2, 0x4f, 0xd8, 0x01, 0xc9, 0xb0, 0xfd, 0x35, 0x6a, 0x3b, 0x75, + 0x95, 0x4d, 0xa1, 0x31, 0x1b, 0x36, 0x66, 0xd7, 0xd7, 0xb5, 0x71, 0x27, 0x61, 0x67, 0xa7, 0x84, + 0x9a, 0xbf, 0x86, 0x8d, 0xdd, 0x31, 0x36, 0xd2, 0xe6, 0x85, 0x4c, 0x6f, 0xf1, 0x3e, 0xfe, 0x7a, + 0x14, 0xe3, 0x9e, 0x19, 0xa7, 0x6a, 0xe0, 0xba, 0x88, 0x7c, 0x64, 0xe9, 0xa7, 0x87, 0xc8, 0xdf, + 0xc6, 0xe6, 0xef, 0x1a, 0xb7, 0xd2, 0x9a, 0xf7, 0xa9, 0x08, 0xd9, 0xfc, 0xeb, 0xb3, 0xeb, 0x5a, + 0xf5, 0xe0, 0x6e, 0xda, 0xfb, 0xbe, 0xd6, 0xe6, 0x9a, 0x99, 0xeb, 0x1b, 0xa8, 0x43, 0x56, 0xf5, + 0x98, 0x76, 0xb4, 0x7c, 0x52, 0x82, 0xe7, 0xd1, 0xf2, 0x49, 0x0b, 0x82, 0x27, 0xf5, 0x27, 0x15, + 0xfe, 0xfe, 0x28, 0x73, 0x7f, 0xf3, 0x9d, 0xef, 0x7f, 0xed, 0xd4, 0x09, 0xcf, 0xa6, 0xc7, 0x0f, + 0x06, 0xde, 0xf8, 0xe1, 0x48, 0x79, 0x35, 0xe5, 0x41, 0xec, 0x87, 0x23, 0x77, 0xf8, 0x10, 0xab, + 0x3d, 0x5e, 0x98, 0xf8, 0x5e, 0xe8, 0x7d, 0xe3, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x4f, 0xc5, + 0x60, 0x26, 0x72, 0x86, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -12577,6 +12750,10 @@ type LightningClient interface { //the node directional specific routing policy which includes: the time lock //delta, fee information, etc. DescribeGraph(ctx context.Context, in *ChannelGraphRequest, opts ...grpc.CallOption) (*ChannelGraph, error) + //* lncli: `getnodemetrics` + //GetNodeMetrics returns node metrics calculated from the graph. Currently + //the only supported metric is betweenness centrality of individual nodes. + GetNodeMetrics(ctx context.Context, in *NodeMetricsRequest, opts ...grpc.CallOption) (*NodeMetricsResponse, error) //* lncli: `getchaninfo` //GetChanInfo returns the latest authenticated network announcement for the //given channel identified by its channel ID: an 8-byte integer which @@ -13232,6 +13409,15 @@ func (c *lightningClient) DescribeGraph(ctx context.Context, in *ChannelGraphReq return out, nil } +func (c *lightningClient) GetNodeMetrics(ctx context.Context, in *NodeMetricsRequest, opts ...grpc.CallOption) (*NodeMetricsResponse, error) { + out := new(NodeMetricsResponse) + err := c.cc.Invoke(ctx, "/lnrpc.Lightning/GetNodeMetrics", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *lightningClient) GetChanInfo(ctx context.Context, in *ChanInfoRequest, opts ...grpc.CallOption) (*ChannelEdge, error) { out := new(ChannelEdge) err := c.cc.Invoke(ctx, "/lnrpc.Lightning/GetChanInfo", in, out, opts...) @@ -13639,6 +13825,10 @@ type LightningServer interface { //the node directional specific routing policy which includes: the time lock //delta, fee information, etc. DescribeGraph(context.Context, *ChannelGraphRequest) (*ChannelGraph, error) + //* lncli: `getnodemetrics` + //GetNodeMetrics returns node metrics calculated from the graph. Currently + //the only supported metric is betweenness centrality of individual nodes. + GetNodeMetrics(context.Context, *NodeMetricsRequest) (*NodeMetricsResponse, error) //* lncli: `getchaninfo` //GetChanInfo returns the latest authenticated network announcement for the //given channel identified by its channel ID: an 8-byte integer which @@ -14470,6 +14660,24 @@ func _Lightning_DescribeGraph_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Lightning_GetNodeMetrics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodeMetricsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(LightningServer).GetNodeMetrics(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/lnrpc.Lightning/GetNodeMetrics", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(LightningServer).GetNodeMetrics(ctx, req.(*NodeMetricsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Lightning_GetChanInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ChanInfoRequest) if err := dec(in); err != nil { @@ -14884,6 +15092,10 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{ MethodName: "DescribeGraph", Handler: _Lightning_DescribeGraph_Handler, }, + { + MethodName: "GetNodeMetrics", + Handler: _Lightning_GetNodeMetrics_Handler, + }, { MethodName: "GetChanInfo", Handler: _Lightning_GetChanInfo_Handler, diff --git a/lnrpc/rpc.pb.gw.go b/lnrpc/rpc.pb.gw.go index 55ac162c88..78aae3c181 100644 --- a/lnrpc/rpc.pb.gw.go +++ b/lnrpc/rpc.pb.gw.go @@ -653,6 +653,23 @@ func request_Lightning_DescribeGraph_0(ctx context.Context, marshaler runtime.Ma } +var ( + filter_Lightning_GetNodeMetrics_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Lightning_GetNodeMetrics_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq NodeMetricsRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_Lightning_GetNodeMetrics_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GetNodeMetrics(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + func request_Lightning_GetChanInfo_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ChanInfoRequest var metadata runtime.ServerMetadata @@ -1678,6 +1695,26 @@ func RegisterLightningHandlerClient(ctx context.Context, mux *runtime.ServeMux, }) + mux.Handle("GET", pattern_Lightning_GetNodeMetrics_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Lightning_GetNodeMetrics_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Lightning_GetNodeMetrics_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Lightning_GetChanInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1980,6 +2017,8 @@ var ( pattern_Lightning_DescribeGraph_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "graph"}, "")) + pattern_Lightning_GetNodeMetrics_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "graph", "nodemetrics"}, "")) + pattern_Lightning_GetChanInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "graph", "edge", "chan_id"}, "")) pattern_Lightning_GetNodeInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "graph", "node", "pub_key"}, "")) @@ -2064,6 +2103,8 @@ var ( forward_Lightning_DescribeGraph_0 = runtime.ForwardResponseMessage + forward_Lightning_GetNodeMetrics_0 = runtime.ForwardResponseMessage + forward_Lightning_GetChanInfo_0 = runtime.ForwardResponseMessage forward_Lightning_GetNodeInfo_0 = runtime.ForwardResponseMessage diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 536eb46a2d..1417a3f130 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -641,6 +641,17 @@ service Lightning { }; } + /** lncli: `getnodemetrics` + GetNodeMetrics returns node metrics calculated from the graph. Currently + the only supported metric is betweenness centrality of individual nodes. + */ + rpc GetNodeMetrics (NodeMetricsRequest) returns (NodeMetricsResponse) { + option (google.api.http) = { + get: "/v1/graph/nodemetrics" + }; + } + + /** lncli: `getchaninfo` GetChanInfo returns the latest authenticated network announcement for the given channel identified by its channel ID: an 8-byte integer which @@ -2516,6 +2527,34 @@ message ChannelGraph { repeated ChannelEdge edges = 2; } +enum NodeMetricType { + BETWEENNESS_CENTRALITY = 0; +} + +message NodeMetricsRequest { + /// The requesteded node metrics. + repeated NodeMetricType types = 1; +} + +message NodeMetricsResponse { + /** + Betweenness centrality is the sum of the ratio of shortest paths that pass + through the node for each pair of nodes in the graph (not counting paths + starting or ending at this node). + Map of node pubkey to betweenness centrality of the node. Normalized + values are in the [0,1] closed interval. + */ + map betweenness_centrality = 1; +} + +message FloatValue { + /// Arbitrary float value. + double value = 1; + + /// The value normalized to [0,1] or [-1,1]. + double normalized_value = 2; +} + message ChanInfoRequest { /** The unique channel ID for the channel. The first 3 bytes are the block diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index b6c9f5bb49..7aedb11388 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -718,6 +718,39 @@ ] } }, + "/v1/graph/nodemetrics": { + "get": { + "summary": "* lncli: `getnodemetrics`\nGetNodeMetrics returns node metrics calculated from the graph. Currently\nthe only supported metric is betweenness centrality of individual nodes.", + "operationId": "GetNodeMetrics", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/lnrpcNodeMetricsResponse" + } + } + }, + "parameters": [ + { + "name": "types", + "description": "/ The requesteded node metrics.", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "BETWEENNESS_CENTRALITY" + ] + }, + "collectionFormat": "multi" + } + ], + "tags": [ + "Lightning" + ] + } + }, "/v1/graph/routes/{pub_key}/{amt}": { "get": { "summary": "* lncli: `queryroutes`\nQueryRoutes attempts to query the daemon's Channel Router for a possible\nroute to a target destination capable of carrying a specific amount of\nsatoshis. The returned route contains the full details required to craft and\nsend an HTLC, also including the necessary information that should be\npresent within the Sphinx packet encapsulated within the HTLC.", @@ -2684,6 +2717,21 @@ } } }, + "lnrpcFloatValue": { + "type": "object", + "properties": { + "value": { + "type": "number", + "format": "double", + "description": "/ Arbitrary float value." + }, + "normalized_value": { + "type": "number", + "format": "double", + "description": "/ The value normalized to [0,1] or [-1,1]." + } + } + }, "lnrpcForwardingEvent": { "type": "object", "properties": { @@ -3574,6 +3622,25 @@ } } }, + "lnrpcNodeMetricType": { + "type": "string", + "enum": [ + "BETWEENNESS_CENTRALITY" + ], + "default": "BETWEENNESS_CENTRALITY" + }, + "lnrpcNodeMetricsResponse": { + "type": "object", + "properties": { + "betweenness_centrality": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/lnrpcFloatValue" + }, + "description": "*\nBetweenness centrality is the sum of the ratio of shortest paths that pass\nthrough the node for each pair of nodes in the graph (not counting paths\nstarting or ending at this node).\nMap of node pubkey to betweenness centrality of the node. Normalized\nvalues are in the [0,1] closed interval." + } + } + }, "lnrpcNodePair": { "type": "object", "properties": { diff --git a/rpcserver.go b/rpcserver.go index 721b4fad4f..995cc7b6b4 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -354,6 +354,10 @@ func mainRPCServerPermissions() map[string][]bakery.Op { Entity: "info", Action: "read", }}, + "/lnrpc.Lightning/GetNodeMetrics": {{ + Entity: "info", + Action: "read", + }}, "/lnrpc.Lightning/GetChanInfo": {{ Entity: "info", Action: "read", @@ -4561,14 +4565,16 @@ func (r *rpcServer) DescribeGraph(ctx context.Context, nodeAddrs = append(nodeAddrs, nodeAddr) } - resp.Nodes = append(resp.Nodes, &lnrpc.LightningNode{ + lnNode := &lnrpc.LightningNode{ LastUpdate: uint32(node.LastUpdate.Unix()), PubKey: hex.EncodeToString(node.PubKeyBytes[:]), Addresses: nodeAddrs, Alias: node.Alias, Color: routing.EncodeHexColor(node.Color), Features: invoicesrpc.CreateRPCFeatures(node.Features), - }) + } + + resp.Nodes = append(resp.Nodes, lnNode) return nil }) @@ -4657,6 +4663,57 @@ func marshalDbEdge(edgeInfo *channeldb.ChannelEdgeInfo, return edge } +// GetNodeMetrics returns all available node metrics calculated from the +// current channel graph. +func (r *rpcServer) GetNodeMetrics(ctx context.Context, + req *lnrpc.NodeMetricsRequest) (*lnrpc.NodeMetricsResponse, error) { + + // Get requested metric types. + getCentrality := false + for _, t := range req.Types { + if t == lnrpc.NodeMetricType_BETWEENNESS_CENTRALITY { + getCentrality = true + } + } + + // Only centrality can be requested for now. + if !getCentrality { + return nil, nil + } + + resp := &lnrpc.NodeMetricsResponse{ + BetweennessCentrality: make(map[string]*lnrpc.FloatValue), + } + + // Obtain the pointer to the global singleton channel graph, this will + // provide a consistent view of the graph due to bolt db's + // transactional model. + graph := r.server.chanDB.ChannelGraph() + + // Calculate betweenness centrality if requested. Note that depending on the + // graph size, this may take up to a few minutes. + channelGraph := autopilot.ChannelGraphFromDatabase(graph) + centralityMetric := autopilot.NewBetweennessCentralityMetric() + if err := centralityMetric.Refresh(channelGraph); err != nil { + return nil, err + } + + // Fill normalized and non normalized centrality. + centrality := centralityMetric.GetMetric(true) + for nodeID, val := range centrality { + resp.BetweennessCentrality[hex.EncodeToString(nodeID[:])] = &lnrpc.FloatValue{ + NormalizedValue: val, + } + } + + centrality = centralityMetric.GetMetric(false) + for nodeID, val := range centrality { + resp.BetweennessCentrality[hex.EncodeToString(nodeID[:])].Value = val + } + + return resp, nil +} + // GetChanInfo returns the latest authenticated network announcement for the // given channel identified by its channel ID: an 8-byte integer which uniquely // identifies the location of transaction's funding output within the block From 608354032c15f35f141329d960b8228529ce9cd7 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Tue, 24 Mar 2020 17:28:55 +0100 Subject: [PATCH 322/562] autopilot: parallelize betweenness centrality This commit parallelizes betweenness centrality calculation, by distributing the algo to N workers and creating partial results. --- autopilot/betweenness_centrality.go | 73 +++++++++++++--- autopilot/betweenness_centrality_test.go | 101 +++++++++++++++-------- rpcserver.go | 8 +- 3 files changed, 136 insertions(+), 46 deletions(-) diff --git a/autopilot/betweenness_centrality.go b/autopilot/betweenness_centrality.go index bfc15e368a..34a10f7a1e 100644 --- a/autopilot/betweenness_centrality.go +++ b/autopilot/betweenness_centrality.go @@ -1,5 +1,10 @@ package autopilot +import ( + "fmt" + "sync" +) + // stack is a simple int stack to help with readability of Brandes' // betweenness centrality implementation below. type stack struct { @@ -50,6 +55,10 @@ func (q *queue) empty() bool { // shortest paths starting or ending at that node. This is a useful metric // to measure control of individual nodes over the whole network. type BetweennessCentrality struct { + // workers number of goroutines are used to parallelize + // centrality calculation. + workers int + // centrality stores original (not normalized) centrality values for // each node in the graph. centrality map[NodeID]float64 @@ -62,8 +71,15 @@ type BetweennessCentrality struct { } // NewBetweennessCentralityMetric creates a new BetweennessCentrality instance. -func NewBetweennessCentralityMetric() *BetweennessCentrality { - return &BetweennessCentrality{} +// Users can specify the number of workers to use for calculating centrality. +func NewBetweennessCentralityMetric(workers int) (*BetweennessCentrality, error) { + // There should be at least one worker. + if workers < 1 { + return nil, fmt.Errorf("workers must be positive") + } + return &BetweennessCentrality{ + workers: workers, + }, nil } // Name returns the name of the metric. @@ -158,10 +174,47 @@ func (bc *BetweennessCentrality) Refresh(graph ChannelGraph) error { return err } - // TODO: parallelize updates to centrality. - centrality := make([]float64, len(cache.Nodes)) + var wg sync.WaitGroup + work := make(chan int) + partials := make(chan []float64, bc.workers) + + // Each worker will compute a partial result. This + // partial result is a sum of centrality updates on + // roughly N / workers nodes. + worker := func() { + defer wg.Done() + partial := make([]float64, len(cache.Nodes)) + + // Consume the next node, update centrality + // parital to avoid unnecessary synchronizaton. + for node := range work { + betweennessCentrality(cache, node, partial) + } + partials <- partial + } + + // Now start the N workers. + wg.Add(bc.workers) + for i := 0; i < bc.workers; i++ { + go worker() + } + + // Distribute work amongst workers Should be + // fair when graph is sufficiently large. for node := range cache.Nodes { - betweennessCentrality(cache, node, centrality) + work <- node + } + + close(work) + wg.Wait() + close(partials) + + // Collect and sum partials for final result. + centrality := make([]float64, len(cache.Nodes)) + for partial := range partials { + for i := 0; i < len(partial); i++ { + centrality[i] += partial[i] + } } // Get min/max to be able to normalize @@ -169,11 +222,11 @@ func (bc *BetweennessCentrality) Refresh(graph ChannelGraph) error { bc.min = 0 bc.max = 0 if len(centrality) > 0 { - for i := 1; i < len(centrality); i++ { - if centrality[i] < bc.min { - bc.min = centrality[i] - } else if centrality[i] > bc.max { - bc.max = centrality[i] + for _, v := range centrality { + if v < bc.min { + bc.min = v + } else if v > bc.max { + bc.max = v } } } diff --git a/autopilot/betweenness_centrality_test.go b/autopilot/betweenness_centrality_test.go index 09fd7fc3d0..4b71f77f6e 100644 --- a/autopilot/betweenness_centrality_test.go +++ b/autopilot/betweenness_centrality_test.go @@ -1,15 +1,38 @@ package autopilot import ( + "fmt" "testing" "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil" ) +func TestBetweennessCentralityMetricConstruction(t *testing.T) { + failing := []int{-1, 0} + ok := []int{1, 10} + + for _, workers := range failing { + m, err := NewBetweennessCentralityMetric(workers) + if m != nil || err == nil { + t.Fatalf("construction must fail with <= 0 workers") + } + } + + for _, workers := range ok { + m, err := NewBetweennessCentralityMetric(workers) + if m == nil || err != nil { + t.Fatalf("construction must succeed with >= 1 workers") + } + } +} + // Tests that empty graph results in empty centrality result. func TestBetweennessCentralityEmptyGraph(t *testing.T) { - centralityMetric := NewBetweennessCentralityMetric() + centralityMetric, err := NewBetweennessCentralityMetric(1) + if err != nil { + t.Fatalf("construction must succeed with positive number of workers") + } for _, chanGraph := range chanGraphs { graph, cleanup, err := chanGraph.genFunc() @@ -91,8 +114,9 @@ func TestBetweennessCentralityWithNonEmptyGraph(t *testing.T) { }, } - tests := []struct { - name string + workers := []int{1, 3, 9, 100} + + results := []struct { normalize bool centrality []float64 }{ @@ -110,47 +134,54 @@ func TestBetweennessCentralityWithNonEmptyGraph(t *testing.T) { }, } - for _, chanGraph := range chanGraphs { - graph, cleanup, err := chanGraph.genFunc() - if err != nil { - t.Fatalf("unable to create graph: %v", err) - } - if cleanup != nil { - defer cleanup() - } - - success := t.Run(chanGraph.name, func(t1 *testing.T) { - centralityMetric := NewBetweennessCentralityMetric() - graphNodes := buildTestGraph(t1, graph, graphDesc) - - if err := centralityMetric.Refresh(graph); err != nil { - t1.Fatalf("error while calculating betweeness centrality") + for _, numWorkers := range workers { + for _, chanGraph := range chanGraphs { + numWorkers := numWorkers + graph, cleanup, err := chanGraph.genFunc() + if err != nil { + t.Fatalf("unable to create graph: %v", err) + } + if cleanup != nil { + defer cleanup() } - for _, test := range tests { - test := test - centrality := centralityMetric.GetMetric(test.normalize) - if len(centrality) != graphDesc.nodes { - t.Fatalf("expected %v values, got: %v", - graphDesc.nodes, len(centrality)) + testName := fmt.Sprintf("%v %d workers", chanGraph.name, numWorkers) + success := t.Run(testName, func(t1 *testing.T) { + centralityMetric, err := NewBetweennessCentralityMetric(numWorkers) + if err != nil { + t.Fatalf("construction must succeed with positive number of workers") + } + + graphNodes := buildTestGraph(t1, graph, graphDesc) + if err := centralityMetric.Refresh(graph); err != nil { + t1.Fatalf("error while calculating betweeness centrality") } + for _, expected := range results { + expected := expected + centrality := centralityMetric.GetMetric(expected.normalize) - for node, nodeCentrality := range test.centrality { - nodeID := NewNodeID(graphNodes[node]) - calculatedCentrality, ok := centrality[nodeID] - if !ok { - t1.Fatalf("no result for node: %x (%v)", nodeID, node) + if len(centrality) != graphDesc.nodes { + t.Fatalf("expected %v values, got: %v", + graphDesc.nodes, len(centrality)) } - if nodeCentrality != calculatedCentrality { - t1.Errorf("centrality for node: %v should be %v, got: %v", - node, test.centrality[node], calculatedCentrality) + for node, nodeCentrality := range expected.centrality { + nodeID := NewNodeID(graphNodes[node]) + calculatedCentrality, ok := centrality[nodeID] + if !ok { + t1.Fatalf("no result for node: %x (%v)", nodeID, node) + } + + if nodeCentrality != calculatedCentrality { + t1.Errorf("centrality for node: %v should be %v, got: %v", + node, nodeCentrality, calculatedCentrality) + } } } + }) + if !success { + break } - }) - if !success { - break } } } diff --git a/rpcserver.go b/rpcserver.go index 995cc7b6b4..5cb8ade2b1 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -10,6 +10,7 @@ import ( "io" "math" "net/http" + "runtime" "sort" "strings" "sync" @@ -4693,7 +4694,12 @@ func (r *rpcServer) GetNodeMetrics(ctx context.Context, // Calculate betweenness centrality if requested. Note that depending on the // graph size, this may take up to a few minutes. channelGraph := autopilot.ChannelGraphFromDatabase(graph) - centralityMetric := autopilot.NewBetweennessCentralityMetric() + centralityMetric, err := autopilot.NewBetweennessCentralityMetric( + runtime.NumCPU(), + ) + if err != nil { + return nil, err + } if err := centralityMetric.Refresh(channelGraph); err != nil { return nil, err } From 5a4d595e5388b2199bb12af603645a5f581a6dda Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Fri, 27 Mar 2020 10:43:32 +0100 Subject: [PATCH 323/562] lncli: group graph queries under Graph category This commit moves DescribeGraph, GetNodeInfo and GetChanInfo under the Graph category. --- cmd/lncli/commands.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index b9fc4089d5..2136677410 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -2942,7 +2942,7 @@ func listInvoices(ctx *cli.Context) error { var describeGraphCommand = cli.Command{ Name: "describegraph", - Category: "Peers", + Category: "Graph", Description: "Prints a human readable version of the known channel " + "graph from the PoV of the node", Usage: "Describe the network graph.", @@ -3031,7 +3031,7 @@ func listPayments(ctx *cli.Context) error { var getChanInfoCommand = cli.Command{ Name: "getchaninfo", - Category: "Channels", + Category: "Graph", Usage: "Get the state of a channel.", Description: "Prints out the latest authenticated state for a " + "particular channel", @@ -3082,7 +3082,7 @@ func getChanInfo(ctx *cli.Context) error { var getNodeInfoCommand = cli.Command{ Name: "getnodeinfo", - Category: "Peers", + Category: "Graph", Usage: "Get information on a specific node.", Description: "Prints out the latest authenticated node state for an " + "advertised node", From 1a6b28553adfbf5e929e273522c4513fbedaed38 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 23 Mar 2020 19:59:16 +0100 Subject: [PATCH 324/562] routing: stricter mission control state failure updates This commit puts a mechanism in place to prevent a failure for a low amount from being overwritten very soon after by a higher amount failure. --- routing/missioncontrol.go | 12 ++++++- routing/missioncontrol_state.go | 30 ++++++++++++++++-- routing/missioncontrol_state_test.go | 47 ++++++++++++++++++++++++++++ server.go | 11 ++++--- 4 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 routing/missioncontrol_state_test.go diff --git a/routing/missioncontrol.go b/routing/missioncontrol.go index 963ea886b0..da3f38b6de 100644 --- a/routing/missioncontrol.go +++ b/routing/missioncontrol.go @@ -50,6 +50,11 @@ const ( // DefaultAprioriWeight is the default a priori weight. See // MissionControlConfig for further explanation. DefaultAprioriWeight = 0.5 + + // DefaultMinFailureRelaxInterval is the default minimum time that must + // have passed since the previously recorded failure before the failure + // amount may be raised. + DefaultMinFailureRelaxInterval = time.Minute ) // NodeResults contains previous results from a node to its peers. @@ -113,6 +118,11 @@ type MissionControlConfig struct { // results, unless there are none available. AprioriWeight float64 + // MinFailureRelaxInterval is the minimum time that must have passed + // since the previously recorded failure before the failure amount may + // be raised. + MinFailureRelaxInterval time.Duration + // SelfNode is our own pubkey. SelfNode route.Vertex } @@ -188,7 +198,7 @@ func NewMissionControl(db kvdb.Backend, cfg *MissionControlConfig) ( } mc := &MissionControl{ - state: newMissionControlState(), + state: newMissionControlState(cfg.MinFailureRelaxInterval), now: time.Now, cfg: cfg, store: store, diff --git a/routing/missioncontrol_state.go b/routing/missioncontrol_state.go index 9b342f6d2a..06e2ef13a3 100644 --- a/routing/missioncontrol_state.go +++ b/routing/missioncontrol_state.go @@ -19,13 +19,21 @@ type missionControlState struct { // lastSecondChance tracks the last time a second chance was granted for // a directed node pair. lastSecondChance map[DirectedNodePair]time.Time + + // minFailureRelaxInterval is the minimum time that must have passed + // since the previously recorded failure before the failure amount may + // be raised. + minFailureRelaxInterval time.Duration } // newMissionControlState instantiates a new mission control state object. -func newMissionControlState() *missionControlState { +func newMissionControlState( + minFailureRelaxInterval time.Duration) *missionControlState { + return &missionControlState{ - lastPairResult: make(map[route.Vertex]NodeResults), - lastSecondChance: make(map[DirectedNodePair]time.Time), + lastPairResult: make(map[route.Vertex]NodeResults), + lastSecondChance: make(map[DirectedNodePair]time.Time), + minFailureRelaxInterval: minFailureRelaxInterval, } } @@ -87,6 +95,22 @@ func (m *missionControlState) setLastPairResult(fromNode, toNode route.Vertex, // condition) to be revived as if it just happened. failAmt := result.amt + // Drop result if it would increase the failure amount too soon + // after a previous failure. This can happen if htlc results + // come in out of order. This check makes it easier for payment + // processes to converge to a final state. + failInterval := timestamp.Sub(current.FailTime) + if failAmt > current.FailAmt && + failInterval < m.minFailureRelaxInterval { + + log.Debugf("Ignoring higher amount failure within min "+ + "failure relaxation interval: prev_fail_amt=%v, "+ + "fail_amt=%v, interval=%v", + current.FailAmt, failAmt, failInterval) + + return + } + current.FailTime = timestamp current.FailAmt = failAmt diff --git a/routing/missioncontrol_state_test.go b/routing/missioncontrol_state_test.go new file mode 100644 index 0000000000..28635d4375 --- /dev/null +++ b/routing/missioncontrol_state_test.go @@ -0,0 +1,47 @@ +package routing + +import ( + "testing" + "time" + + "github.com/lightningnetwork/lnd/routing/route" +) + +// TestMissionControlStateFailureResult tests setting failure results on the +// mission control state. +func TestMissionControlStateFailureResult(t *testing.T) { + const minFailureRelaxInterval = time.Minute + state := newMissionControlState(minFailureRelaxInterval) + + var ( + from = route.Vertex{1} + to = route.Vertex{2} + timestamp = testTime + ) + + // Report a 1000 sat failure. + state.setLastPairResult(from, to, timestamp, &pairResult{amt: 1000}) + result, _ := state.getLastPairResult(from) + if result[to].FailAmt != 1000 { + t.Fatalf("unexpected fail amount %v", result[to].FailAmt) + } + + // Report an 1100 sat failure one hour later. It is expected to + // overwrite the previous failure. + timestamp = timestamp.Add(time.Hour) + state.setLastPairResult(from, to, timestamp, &pairResult{amt: 1100}) + result, _ = state.getLastPairResult(from) + if result[to].FailAmt != 1100 { + t.Fatalf("unexpected fail amount %v", result[to].FailAmt) + } + + // Report a 1200 sat failure one second later. Because this increase of + // the failure amount is too soon after the previous failure, the result + // is not applied. + timestamp = timestamp.Add(time.Second) + state.setLastPairResult(from, to, timestamp, &pairResult{amt: 1200}) + result, _ = state.getLastPairResult(from) + if result[to].FailAmt != 1100 { + t.Fatalf("unexpected fail amount %v", result[to].FailAmt) + } +} diff --git a/server.go b/server.go index b9a628e3d9..fe935f3c8e 100644 --- a/server.go +++ b/server.go @@ -710,11 +710,12 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, s.missionControl, err = routing.NewMissionControl( chanDB, &routing.MissionControlConfig{ - AprioriHopProbability: routingConfig.AprioriHopProbability, - PenaltyHalfLife: routingConfig.PenaltyHalfLife, - MaxMcHistory: routingConfig.MaxMcHistory, - AprioriWeight: routingConfig.AprioriWeight, - SelfNode: selfNode.PubKeyBytes, + AprioriHopProbability: routingConfig.AprioriHopProbability, + PenaltyHalfLife: routingConfig.PenaltyHalfLife, + MaxMcHistory: routingConfig.MaxMcHistory, + AprioriWeight: routingConfig.AprioriWeight, + SelfNode: selfNode.PubKeyBytes, + MinFailureRelaxInterval: routing.DefaultMinFailureRelaxInterval, }, ) if err != nil { From f1fd5e86c073e7060a381529937de448823a4d3d Mon Sep 17 00:00:00 2001 From: nsa Date: Tue, 17 Mar 2020 10:53:17 -0400 Subject: [PATCH 325/562] config: add WatchtowerKeyPath Tor option Co-authored-by: Turtle --- config.go | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/config.go b/config.go index 040f68e29a..773c5d00b9 100644 --- a/config.go +++ b/config.go @@ -221,16 +221,17 @@ type autoPilotConfig struct { } type torConfig struct { - Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"` - SOCKS string `long:"socks" description:"The host:port that Tor's exposed SOCKS5 proxy is listening on"` - DNS string `long:"dns" description:"The DNS server as host:port that Tor will use for SRV queries - NOTE must have TCP resolution enabled"` - StreamIsolation bool `long:"streamisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` - Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` - TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"` - Password string `long:"password" description:"The password used to arrive at the HashedControlPassword for the control port. If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` - V2 bool `long:"v2" description:"Automatically set up a v2 onion service to listen for inbound connections"` - V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` - PrivateKeyPath string `long:"privatekeypath" description:"The path to the private key of the onion service being created"` + Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"` + SOCKS string `long:"socks" description:"The host:port that Tor's exposed SOCKS5 proxy is listening on"` + DNS string `long:"dns" description:"The DNS server as host:port that Tor will use for SRV queries - NOTE must have TCP resolution enabled"` + StreamIsolation bool `long:"streamisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` + Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` + TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"` + Password string `long:"password" description:"The password used to arrive at the HashedControlPassword for the control port. If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` + V2 bool `long:"v2" description:"Automatically set up a v2 onion service to listen for inbound connections"` + V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` + PrivateKeyPath string `long:"privatekeypath" description:"The path to the private key of the onion service being created"` + WatchtowerKeyPath string `long:"watchtowerkeypath" description:"The path to the private key of the watchtower onion service being created"` } // config defines the configuration options for lnd. @@ -567,6 +568,7 @@ func loadConfig() (*config, error) { cfg.BitcoindMode.Dir = cleanAndExpandPath(cfg.BitcoindMode.Dir) cfg.LitecoindMode.Dir = cleanAndExpandPath(cfg.LitecoindMode.Dir) cfg.Tor.PrivateKeyPath = cleanAndExpandPath(cfg.Tor.PrivateKeyPath) + cfg.Tor.WatchtowerKeyPath = cleanAndExpandPath(cfg.Tor.WatchtowerKeyPath) cfg.Watchtower.TowerDir = cleanAndExpandPath(cfg.Watchtower.TowerDir) // Ensure that the user didn't attempt to specify negative values for @@ -682,6 +684,19 @@ func loadConfig() (*config, error) { } } + if cfg.Tor.WatchtowerKeyPath == "" { + switch { + case cfg.Tor.V2: + cfg.Tor.WatchtowerKeyPath = filepath.Join( + cfg.Watchtower.TowerDir, defaultTorV2PrivateKeyFilename, + ) + case cfg.Tor.V3: + cfg.Tor.WatchtowerKeyPath = filepath.Join( + cfg.Watchtower.TowerDir, defaultTorV3PrivateKeyFilename, + ) + } + } + // Set up the network-related functions that will be used throughout // the daemon. We use the standard Go "net" package functions by // default. If we should be proxying all traffic through Tor, then From ada0b78dfc568b37708d87b1bb0330e93c2f45c4 Mon Sep 17 00:00:00 2001 From: nsa Date: Tue, 17 Mar 2020 10:58:36 -0400 Subject: [PATCH 326/562] lnd+server+watchtower: allow Standalone access to the tor controller This commit lets the watchtower automatically create hidden services by giving it a pointer to a TorController. The server was also slightly refactored so that it was not the sole owner of the TorController. --- lnd.go | 44 ++++++++++++++++++++++++++++++++++++++-- server.go | 32 ++++++++--------------------- watchtower/config.go | 16 +++++++++++++-- watchtower/standalone.go | 43 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 28 deletions(-) diff --git a/lnd.go b/lnd.go index 3e6ed885b1..875f0e7377 100644 --- a/lnd.go +++ b/lnd.go @@ -45,6 +45,7 @@ import ( "github.com/lightningnetwork/lnd/lnwallet/btcwallet" "github.com/lightningnetwork/lnd/macaroons" "github.com/lightningnetwork/lnd/signal" + "github.com/lightningnetwork/lnd/tor" "github.com/lightningnetwork/lnd/walletunlocker" "github.com/lightningnetwork/lnd/watchtower" "github.com/lightningnetwork/lnd/watchtower/wtdb" @@ -473,6 +474,28 @@ func Main(lisCfg ListenerCfg) error { defer towerClientDB.Close() } + // If tor is active and either v2 or v3 onion services have been specified, + // make a tor controller and pass it into both the watchtower server and + // the regular lnd server. + var torController *tor.Controller + if cfg.Tor.Active && (cfg.Tor.V2 || cfg.Tor.V3) { + torController = tor.NewController( + cfg.Tor.Control, cfg.Tor.TargetIPAddress, cfg.Tor.Password, + ) + + // Start the tor controller before giving it to any other subsystems. + if err := torController.Start(); err != nil { + err := fmt.Errorf("unable to initialize tor controller: %v", err) + ltndLog.Error(err) + return err + } + defer func() { + if err := torController.Stop(); err != nil { + ltndLog.Errorf("error stopping tor controller: %v", err) + } + }() + } + var tower *watchtower.Standalone if cfg.Watchtower.Active { // Segment the watchtower directory by chain and network. @@ -506,7 +529,7 @@ func Main(lisCfg ListenerCfg) error { return err } - wtConfig, err := cfg.Watchtower.Apply(&watchtower.Config{ + wtCfg := &watchtower.Config{ BlockFetcher: activeChainControl.chainIO, DB: towerDB, EpochRegistrar: activeChainControl.chainNotifier, @@ -519,7 +542,23 @@ func Main(lisCfg ListenerCfg) error { NodePrivKey: towerPrivKey, PublishTx: activeChainControl.wallet.PublishTransaction, ChainHash: *activeNetParams.GenesisHash, - }, lncfg.NormalizeAddresses) + } + + // If there is a tor controller (user wants auto hidden services), then + // store a pointer in the watchtower config. + if torController != nil { + wtCfg.TorController = torController + wtCfg.WatchtowerKeyPath = cfg.Tor.WatchtowerKeyPath + + switch { + case cfg.Tor.V2: + wtCfg.Type = tor.V2 + case cfg.Tor.V3: + wtCfg.Type = tor.V3 + } + } + + wtConfig, err := cfg.Watchtower.Apply(wtCfg, lncfg.NormalizeAddresses) if err != nil { err := fmt.Errorf("Unable to configure watchtower: %v", err) @@ -543,6 +582,7 @@ func Main(lisCfg ListenerCfg) error { server, err := newServer( cfg.Listeners, chanDB, towerClientDB, activeChainControl, idPrivKey, walletInitParams.ChansToRestore, chainedAcceptor, + torController, ) if err != nil { err := fmt.Errorf("Unable to create server: %v", err) diff --git a/server.go b/server.go index fe935f3c8e..a1dce6ec0d 100644 --- a/server.go +++ b/server.go @@ -322,7 +322,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, towerClientDB *wtdb.ClientDB, cc *chainControl, privKey *btcec.PrivateKey, chansToRestore walletunlocker.ChannelsToRecover, - chanPredicate chanacceptor.ChannelAcceptor) (*server, error) { + chanPredicate chanacceptor.ChannelAcceptor, + torController *tor.Controller) (*server, error) { var err error @@ -428,6 +429,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, // schedule sphinx: hop.NewOnionProcessor(sphinxRouter), + torController: torController, + persistentPeers: make(map[string]bool), persistentPeersBackoff: make(map[string]time.Duration), persistentConnReqs: make(map[string][]*connmgr.ConnReq), @@ -598,16 +601,6 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, selfAddrs = append(selfAddrs, ip) } - // If we were requested to route connections through Tor and to - // automatically create an onion service, we'll initiate our Tor - // controller and establish a connection to the Tor server. - if cfg.Tor.Active && (cfg.Tor.V2 || cfg.Tor.V3) { - s.torController = tor.NewController( - cfg.Tor.Control, cfg.Tor.TargetIPAddress, - cfg.Tor.Password, - ) - } - chanGraph := chanDB.ChannelGraph() // We'll now reconstruct a node announcement based on our current @@ -1251,7 +1244,7 @@ func (s *server) Start() error { var startErr error s.start.Do(func() { if s.torController != nil { - if err := s.initTorController(); err != nil { + if err := s.createNewHiddenService(); err != nil { startErr = err return } @@ -1442,10 +1435,6 @@ func (s *server) Stop() error { close(s.quit) - if s.torController != nil { - s.torController.Stop() - } - // Shutdown the wallet, funding manager, and the rpc server. s.chanStatusMgr.Stop() s.cc.chainNotifier.Stop() @@ -1965,14 +1954,9 @@ func (s *server) initialPeerBootstrap(ignore map[autopilot.NodeID]struct{}, } } -// initTorController initiliazes the Tor controller backed by lnd and -// automatically sets up a v2 onion service in order to listen for inbound -// connections over Tor. -func (s *server) initTorController() error { - if err := s.torController.Start(); err != nil { - return err - } - +// createNewHiddenService automatically sets up a v2 or v3 onion service in +// order to listen for inbound connections over Tor. +func (s *server) createNewHiddenService() error { // Determine the different ports the server is listening on. The onion // service's virtual port will map to these ports and one will be picked // at random when the onion service is being accessed. diff --git a/watchtower/config.go b/watchtower/config.go index 26dfac75a6..a71bd0433c 100644 --- a/watchtower/config.go +++ b/watchtower/config.go @@ -34,8 +34,8 @@ var ( ) // Config defines the resources and parameters used to configure a Watchtower. -// All nil-able elements with the Config must be set in order for the Watchtower -// to function properly. +// All nil-able elements besides tor-related ones must be set in order for the +// Watchtower to function properly. type Config struct { // ChainHash identifies the chain that the watchtower will be monitoring // for breaches and that will be advertised in the server's Init message @@ -89,4 +89,16 @@ type Config struct { // message from the other end, if the connection has stopped buffering // the server's replies. WriteTimeout time.Duration + + // TorController allows the watchtower to optionally setup an onion hidden + // service. + TorController *tor.Controller + + // WatchtowerKeyPath allows the watchtower to specify where the private key + // for a watchtower hidden service should be stored. + WatchtowerKeyPath string + + // Type specifies the hidden service type (V2 or V3) that the watchtower + // will create. + Type tor.OnionType } diff --git a/watchtower/standalone.go b/watchtower/standalone.go index 8f50dc65a0..b1a36bb520 100644 --- a/watchtower/standalone.go +++ b/watchtower/standalone.go @@ -6,6 +6,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/lightningnetwork/lnd/brontide" + "github.com/lightningnetwork/lnd/tor" "github.com/lightningnetwork/lnd/watchtower/lookout" "github.com/lightningnetwork/lnd/watchtower/wtserver" ) @@ -112,6 +113,15 @@ func (w *Standalone) Start() error { log.Infof("Starting watchtower") + // If a tor controller exists in the config, then automatically create a + // hidden service for the watchtower to accept inbound connections from. + if w.cfg.TorController != nil { + log.Infof("Creating watchtower hidden service") + if err := w.createNewHiddenService(); err != nil { + return err + } + } + if err := w.lookout.Start(); err != nil { return err } @@ -142,6 +152,39 @@ func (w *Standalone) Stop() error { return nil } +// createNewHiddenService automatically sets up a v2 or v3 onion service in +// order to listen for inbound connections over Tor. +func (w *Standalone) createNewHiddenService() error { + // Get all the ports the watchtower is listening on. These will be used to + // map the hidden service's virtual port. + listenPorts := make([]int, 0, len(w.listeners)) + for _, listener := range w.listeners { + port := listener.Addr().(*net.TCPAddr).Port + listenPorts = append(listenPorts, port) + } + + // Once we've created the port mapping, we can automatically create the + // hidden service. The service's private key will be saved on disk in order + // to persistently have access to this hidden service across restarts. + onionCfg := tor.AddOnionConfig{ + VirtualPort: DefaultPeerPort, + TargetPorts: listenPorts, + Store: tor.NewOnionFile(w.cfg.WatchtowerKeyPath, 0600), + Type: w.cfg.Type, + } + + addr, err := w.cfg.TorController.AddOnion(onionCfg) + if err != nil { + return err + } + + // Append this address to ExternalIPs so that it will be exposed in + // tower info calls. + w.cfg.ExternalIPs = append(w.cfg.ExternalIPs, addr) + + return nil +} + // PubKey returns the public key for the watchtower used to authentication and // encrypt traffic with clients. // From 93cb05142a3b32c61c5ae917e1bd6f11656450bc Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Sat, 28 Mar 2020 16:14:26 +0100 Subject: [PATCH 327/562] lnrpc: rename FloatValue to FloatMetric This commit renames lnrpc.FloatValue to lnrpc.FloatMetric as requested in the final review of centrality PR. --- lnrpc/rpc.pb.go | 1391 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 22 +- lnrpc/rpc.swagger.json | 10 +- rpcserver.go | 9 +- 4 files changed, 719 insertions(+), 713 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 04be015618..86bc642496 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -102,15 +102,18 @@ func (CommitmentType) EnumDescriptor() ([]byte, []int) { type NodeMetricType int32 const ( - NodeMetricType_BETWEENNESS_CENTRALITY NodeMetricType = 0 + NodeMetricType_UNKNOWN NodeMetricType = 0 + NodeMetricType_BETWEENNESS_CENTRALITY NodeMetricType = 1 ) var NodeMetricType_name = map[int32]string{ - 0: "BETWEENNESS_CENTRALITY", + 0: "UNKNOWN", + 1: "BETWEENNESS_CENTRALITY", } var NodeMetricType_value = map[string]int32{ - "BETWEENNESS_CENTRALITY": 0, + "UNKNOWN": 0, + "BETWEENNESS_CENTRALITY": 1, } func (x NodeMetricType) String() string { @@ -7622,7 +7625,7 @@ func (m *ChannelGraph) GetEdges() []*ChannelEdge { } type NodeMetricsRequest struct { - /// The requesteded node metrics. + /// The requested node metrics. Types []NodeMetricType `protobuf:"varint,1,rep,packed,name=types,proto3,enum=lnrpc.NodeMetricType" json:"types,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -7668,10 +7671,10 @@ type NodeMetricsResponse struct { //starting or ending at this node). //Map of node pubkey to betweenness centrality of the node. Normalized //values are in the [0,1] closed interval. - BetweennessCentrality map[string]*FloatValue `protobuf:"bytes,1,rep,name=betweenness_centrality,json=betweennessCentrality,proto3" json:"betweenness_centrality,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + BetweennessCentrality map[string]*FloatMetric `protobuf:"bytes,1,rep,name=betweenness_centrality,json=betweennessCentrality,proto3" json:"betweenness_centrality,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *NodeMetricsResponse) Reset() { *m = NodeMetricsResponse{} } @@ -7699,14 +7702,14 @@ func (m *NodeMetricsResponse) XXX_DiscardUnknown() { var xxx_messageInfo_NodeMetricsResponse proto.InternalMessageInfo -func (m *NodeMetricsResponse) GetBetweennessCentrality() map[string]*FloatValue { +func (m *NodeMetricsResponse) GetBetweennessCentrality() map[string]*FloatMetric { if m != nil { return m.BetweennessCentrality } return nil } -type FloatValue struct { +type FloatMetric struct { /// Arbitrary float value. Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` /// The value normalized to [0,1] or [-1,1]. @@ -7716,39 +7719,39 @@ type FloatValue struct { XXX_sizecache int32 `json:"-"` } -func (m *FloatValue) Reset() { *m = FloatValue{} } -func (m *FloatValue) String() string { return proto.CompactTextString(m) } -func (*FloatValue) ProtoMessage() {} -func (*FloatValue) Descriptor() ([]byte, []int) { +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{96} } -func (m *FloatValue) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FloatValue.Unmarshal(m, b) +func (m *FloatMetric) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FloatMetric.Unmarshal(m, b) } -func (m *FloatValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FloatValue.Marshal(b, m, deterministic) +func (m *FloatMetric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FloatMetric.Marshal(b, m, deterministic) } -func (m *FloatValue) XXX_Merge(src proto.Message) { - xxx_messageInfo_FloatValue.Merge(m, src) +func (m *FloatMetric) XXX_Merge(src proto.Message) { + xxx_messageInfo_FloatMetric.Merge(m, src) } -func (m *FloatValue) XXX_Size() int { - return xxx_messageInfo_FloatValue.Size(m) +func (m *FloatMetric) XXX_Size() int { + return xxx_messageInfo_FloatMetric.Size(m) } -func (m *FloatValue) XXX_DiscardUnknown() { - xxx_messageInfo_FloatValue.DiscardUnknown(m) +func (m *FloatMetric) XXX_DiscardUnknown() { + xxx_messageInfo_FloatMetric.DiscardUnknown(m) } -var xxx_messageInfo_FloatValue proto.InternalMessageInfo +var xxx_messageInfo_FloatMetric proto.InternalMessageInfo -func (m *FloatValue) GetValue() float64 { +func (m *FloatMetric) GetValue() float64 { if m != nil { return m.Value } return 0 } -func (m *FloatValue) GetNormalizedValue() float64 { +func (m *FloatMetric) GetNormalizedValue() float64 { if m != nil { return m.NormalizedValue } @@ -11508,8 +11511,8 @@ func init() { proto.RegisterType((*ChannelGraph)(nil), "lnrpc.ChannelGraph") proto.RegisterType((*NodeMetricsRequest)(nil), "lnrpc.NodeMetricsRequest") proto.RegisterType((*NodeMetricsResponse)(nil), "lnrpc.NodeMetricsResponse") - proto.RegisterMapType((map[string]*FloatValue)(nil), "lnrpc.NodeMetricsResponse.BetweennessCentralityEntry") - proto.RegisterType((*FloatValue)(nil), "lnrpc.FloatValue") + proto.RegisterMapType((map[string]*FloatMetric)(nil), "lnrpc.NodeMetricsResponse.BetweennessCentralityEntry") + proto.RegisterType((*FloatMetric)(nil), "lnrpc.FloatMetric") proto.RegisterType((*ChanInfoRequest)(nil), "lnrpc.ChanInfoRequest") proto.RegisterType((*NetworkInfoRequest)(nil), "lnrpc.NetworkInfoRequest") proto.RegisterType((*NetworkInfo)(nil), "lnrpc.NetworkInfo") @@ -11573,38 +11576,38 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11638 bytes of a gzipped FileDescriptorProto + // 11641 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x6f, 0x23, 0x59, 0x76, 0x18, 0xde, 0x7c, 0x89, 0xe4, 0xe1, 0x43, 0xd4, 0xd5, 0x8b, 0xad, 0x9e, 0x9e, 0xee, 0xa9, - 0x99, 0x9d, 0xe9, 0xe9, 0x99, 0xed, 0xee, 0xe9, 0xdd, 0x9e, 0x5d, 0xcf, 0xfc, 0xbc, 0x5e, 0x4a, - 0xa2, 0x5a, 0xdc, 0x96, 0x28, 0x4d, 0x91, 0x9a, 0xf1, 0xec, 0xfe, 0x9c, 0xda, 0x12, 0x79, 0x25, + 0x99, 0x9d, 0xe9, 0xe9, 0xd9, 0xed, 0xee, 0xe9, 0xdd, 0x9e, 0xdd, 0x9d, 0xf9, 0x79, 0xbd, 0x94, + 0x44, 0xb5, 0xb8, 0x2d, 0x51, 0x9a, 0x22, 0x35, 0xe3, 0x59, 0xdb, 0xbf, 0xda, 0x12, 0x79, 0x25, 0x95, 0x9b, 0xac, 0xe2, 0x54, 0x15, 0xf5, 0xd8, 0xc5, 0xe4, 0x43, 0x90, 0x18, 0x41, 0x90, 0x04, 0x30, 0x12, 0x07, 0x88, 0x13, 0x23, 0x41, 0x8c, 0x20, 0x08, 0x0c, 0x18, 0x06, 0xd6, 0x01, 0x12, - 0x20, 0xdf, 0x8d, 0x00, 0x09, 0x8c, 0xc0, 0xce, 0x97, 0xc0, 0x30, 0x12, 0x24, 0xd9, 0x7c, 0x0b, - 0xfc, 0x27, 0x04, 0xf7, 0x9c, 0x7b, 0xab, 0x6e, 0x91, 0xa5, 0xee, 0x9e, 0xdd, 0xcd, 0x7e, 0x91, + 0x20, 0xdf, 0x8d, 0x00, 0x09, 0x8c, 0xc0, 0xce, 0x97, 0xc0, 0x30, 0x10, 0x24, 0xd9, 0x7c, 0x0b, + 0xfc, 0x27, 0x04, 0xf7, 0x9c, 0x7b, 0xab, 0x6e, 0x91, 0xa5, 0xee, 0x9e, 0xdd, 0xc9, 0x7e, 0x91, 0x58, 0xe7, 0x9c, 0xfb, 0xac, 0x73, 0xcf, 0x3d, 0xaf, 0x7b, 0x0b, 0xca, 0xfe, 0x64, 0xf0, 0x60, 0xe2, 0x7b, 0xa1, 0xc7, 0x0a, 0x23, 0xd7, 0x9f, 0x0c, 0x36, 0x5e, 0x3b, 0xf5, 0xbc, 0xd3, 0x11, 0x7f, 0x68, 0x4f, 0x9c, 0x87, 0xb6, 0xeb, 0x7a, 0xa1, 0x1d, 0x3a, 0x9e, 0x1b, 0x10, 0x91, 0xf1, - 0x43, 0xa8, 0x3f, 0xe5, 0x6e, 0x8f, 0xf3, 0xa1, 0xc9, 0xbf, 0x98, 0xf2, 0x20, 0x64, 0xef, 0xc1, - 0x92, 0xcd, 0x7f, 0xc4, 0xf9, 0xd0, 0x9a, 0xd8, 0x41, 0x30, 0x39, 0xf3, 0xed, 0x80, 0x37, 0x33, + 0x23, 0xa8, 0x3f, 0xe5, 0x6e, 0x8f, 0xf3, 0xa1, 0xc9, 0x3f, 0x9f, 0xf2, 0x20, 0x64, 0xef, 0xc1, + 0x92, 0xcd, 0x7f, 0xcc, 0xf9, 0xd0, 0x9a, 0xd8, 0x41, 0x30, 0x39, 0xf3, 0xed, 0x80, 0x37, 0x33, 0x77, 0x33, 0xf7, 0xaa, 0x66, 0x83, 0x10, 0x87, 0x11, 0x9c, 0xbd, 0x01, 0xd5, 0x40, 0x90, 0x72, 0x37, 0xf4, 0xbd, 0xc9, 0x55, 0x33, 0x8b, 0x74, 0x15, 0x01, 0x6b, 0x13, 0xc8, 0x18, 0xc1, 0x62, 0xd4, 0x42, 0x30, 0xf1, 0xdc, 0x80, 0xb3, 0x47, 0xb0, 0x32, 0x70, 0x26, 0x67, 0xdc, 0xb7, 0xb0, 0xf0, 0xd8, 0xe5, 0x63, 0xcf, 0x75, 0x06, 0xcd, 0xcc, 0xdd, 0xdc, 0xbd, 0xb2, 0xc9, 0x08, 0x27, 0x4a, 0xec, 0x4b, 0x0c, 0x7b, 0x07, 0x16, 0xb9, 0x4b, 0x70, 0x3e, 0xc4, 0x52, 0xb2, 0xa9, 0x7a, - 0x0c, 0x16, 0x05, 0x8c, 0xbf, 0x9d, 0x85, 0xa5, 0x8e, 0xeb, 0x84, 0x9f, 0xd9, 0xa3, 0x11, 0x0f, + 0x0c, 0x16, 0x05, 0x8c, 0xbf, 0x93, 0x85, 0xa5, 0x8e, 0xeb, 0x84, 0x9f, 0xda, 0xa3, 0x11, 0x0f, 0xd5, 0x98, 0xde, 0x81, 0xc5, 0x0b, 0x04, 0xe0, 0x98, 0x2e, 0x3c, 0x7f, 0x28, 0x47, 0x54, 0x27, 0xf0, 0xa1, 0x84, 0x5e, 0xdb, 0xb3, 0xec, 0xb5, 0x3d, 0x4b, 0x9d, 0xae, 0xdc, 0x35, 0xd3, 0xf5, 0x0e, 0x2c, 0xfa, 0x7c, 0xe0, 0x9d, 0x73, 0xff, 0xca, 0xba, 0x70, 0xdc, 0xa1, 0x77, 0xd1, 0xcc, - 0xdf, 0xcd, 0xdc, 0x2b, 0x98, 0x75, 0x05, 0xfe, 0x0c, 0xa1, 0x6c, 0x13, 0x16, 0x07, 0x67, 0xb6, + 0xdf, 0xcd, 0xdc, 0x2b, 0x98, 0x75, 0x05, 0xfe, 0x14, 0xa1, 0x6c, 0x13, 0x16, 0x07, 0x67, 0xb6, 0xeb, 0xf2, 0x91, 0x75, 0x6c, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xb3, 0x70, 0x37, 0x73, 0xaf, 0xf2, 0xf8, 0xe6, 0x03, 0x7c, 0xab, 0x0f, 0xb6, 0xce, 0x6c, 0x77, 0x13, 0x31, 0x3d, 0xd7, 0x9e, 0x04, 0x67, 0x5e, 0x68, 0xd6, 0x65, 0x09, 0x02, 0x07, 0xc6, 0x0a, 0x30, 0x7d, 0x26, 0x68, 0xee, 0x8d, - 0x3f, 0xc8, 0xc0, 0xf2, 0x91, 0x3b, 0xf2, 0x06, 0xcf, 0x7f, 0xc6, 0x29, 0x4a, 0x19, 0x43, 0xf6, - 0x55, 0xc7, 0x90, 0xfb, 0xaa, 0x63, 0x58, 0x83, 0x95, 0x64, 0x67, 0xe5, 0x28, 0x38, 0xac, 0x8a, + 0x3f, 0xcc, 0xc0, 0xf2, 0x91, 0x3b, 0xf2, 0x06, 0xcf, 0x7f, 0xce, 0x29, 0x4a, 0x19, 0x43, 0xf6, + 0x55, 0xc7, 0x90, 0xfb, 0xb2, 0x63, 0x58, 0x83, 0x95, 0x64, 0x67, 0xe5, 0x28, 0x38, 0xac, 0x8a, 0xd2, 0xa7, 0x5c, 0x75, 0x4b, 0x0d, 0xe3, 0x5d, 0x68, 0x0c, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x71, 0x2c, 0x4a, 0x78, 0x34, 0x90, 0x37, 0xa0, 0xea, 0xf2, 0x8b, 0x98, 0x4c, 0xf2, 0xae, 0xcb, 0x2f, - 0x14, 0x89, 0xd1, 0x84, 0xb5, 0xd9, 0x66, 0x64, 0x07, 0x7e, 0x9a, 0x81, 0xfc, 0x51, 0x78, 0xe9, + 0x14, 0x89, 0xd1, 0x84, 0xb5, 0xd9, 0x66, 0x64, 0x07, 0x7e, 0x96, 0x81, 0xfc, 0x51, 0x78, 0xe9, 0xb1, 0x27, 0x50, 0xb5, 0x87, 0x43, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x4d, 0x68, 0xa5, 0xd4, 0x1f, 0x33, 0x39, 0xc4, 0x16, 0xa1, 0xfa, 0x57, 0x13, 0x6e, 0x56, 0xec, 0xf8, 0x81, 0x35, 0xa1, 0x28, 0x1f, 0xb1, 0xdd, 0xb2, 0xa9, 0x1e, 0xd9, 0x6d, 0x00, 0x7b, 0xec, 0x4d, 0xdd, 0xd0, 0x0a, 0xec, @@ -11612,7 +11615,7 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xf0, 0x9d, 0x49, 0x88, 0xcc, 0x53, 0x36, 0x4b, 0x93, 0xe7, 0x3d, 0x7c, 0x66, 0xef, 0x41, 0xc9, 0x9b, 0x86, 0x13, 0xcf, 0x71, 0x43, 0xc9, 0x2f, 0x8b, 0xb2, 0x23, 0x07, 0xd3, 0xf0, 0x50, 0x80, 0xcd, 0x88, 0x80, 0xbd, 0x05, 0xb5, 0x81, 0xe7, 0x9e, 0x38, 0xfe, 0x98, 0x24, 0x42, 0x73, 0x01, - 0xdb, 0x4a, 0x02, 0x8d, 0x3f, 0xca, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, + 0xdb, 0x4a, 0x02, 0x8d, 0x3f, 0xce, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, 0x43, 0x31, 0xbc, 0xb4, 0xce, 0xec, 0xe0, 0x0c, 0x87, 0x5a, 0x36, 0x17, 0xc2, 0xcb, 0x5d, 0x3b, 0x38, 0x63, 0x6b, 0xb0, 0x40, 0xbd, 0xc4, 0x01, 0xe5, 0x4c, 0xf9, 0x24, 0x16, 0x88, 0x3b, 0x1d, 0x5b, 0xc9, 0xa6, 0x72, 0xc8, 0x31, 0x0d, 0x77, 0x3a, 0xde, 0xd2, 0xe1, 0x62, 0xf0, 0xc7, 0xe2, @@ -11623,12 +11626,12 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0xcb, 0xe0, 0x41, 0xb3, 0x84, 0x2b, 0xbf, 0x26, 0xa0, 0x2d, 0x05, 0x64, 0xaf, 0x01, 0xf8, 0xf6, 0x85, 0x25, 0x26, 0x82, 0x5f, 0x36, 0xcb, 0xf4, 0x16, 0x7c, 0xfb, 0xa2, 0x7f, 0xb9, 0xcb, 0x2f, 0x05, 0xd7, 0x3c, 0xe5, 0xa1, 0x36, 0x69, 0x81, 0xe4, 0x4e, 0x63, 0x0f, 0x98, 0x06, 0xde, 0xe6, - 0xa1, 0xed, 0x8c, 0x02, 0xf6, 0x21, 0x54, 0x43, 0x8d, 0x18, 0xc5, 0x60, 0x25, 0x62, 0x21, 0xad, + 0xa1, 0xed, 0x8c, 0x02, 0xf6, 0x01, 0x54, 0x43, 0x8d, 0x18, 0xc5, 0x60, 0x25, 0x62, 0x21, 0xad, 0x80, 0x99, 0xa0, 0x33, 0xce, 0xa0, 0xb4, 0xc3, 0xf9, 0x9e, 0x33, 0x76, 0x42, 0xb6, 0x06, 0x85, 0x13, 0xe7, 0x92, 0x13, 0xb3, 0xe7, 0x76, 0x6f, 0x98, 0xf4, 0xc8, 0xee, 0x00, 0xe0, 0x0f, 0x6b, 0x1c, 0x71, 0xd3, 0xee, 0x0d, 0xb3, 0x8c, 0xb0, 0xfd, 0xc0, 0x0e, 0xd9, 0x06, 0x14, 0x27, 0xdc, 0x1f, 0x70, 0xf5, 0xde, 0x76, 0x6f, 0x98, 0x0a, 0xb0, 0x59, 0x84, 0xc2, 0x48, 0xd4, 0x6e, 0xfc, - 0x49, 0x01, 0x2a, 0x3d, 0xee, 0x46, 0xab, 0x8c, 0x41, 0x5e, 0x4c, 0x88, 0x5c, 0x59, 0xf8, 0x9b, + 0x69, 0x01, 0x2a, 0x3d, 0xee, 0x46, 0xab, 0x8c, 0x41, 0x5e, 0x4c, 0x88, 0x5c, 0x59, 0xf8, 0x9b, 0xbd, 0x09, 0x15, 0x9c, 0xba, 0x20, 0xf4, 0x1d, 0xf7, 0x94, 0xb8, 0x7a, 0x33, 0xdb, 0xcc, 0x98, 0x20, 0xc0, 0x3d, 0x84, 0xb2, 0x06, 0xe4, 0xec, 0xb1, 0xe2, 0x6a, 0xf1, 0x93, 0xdd, 0x84, 0x92, 0x3d, 0x0e, 0xa9, 0x7b, 0x55, 0x04, 0x17, 0xed, 0x71, 0x88, 0x5d, 0x7b, 0x03, 0xaa, 0x13, 0xfb, @@ -11636,207 +11639,207 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0x51, 0x8d, 0x17, 0xa2, 0xc6, 0x97, 0x34, 0x6a, 0xd9, 0x87, 0x77, 0x60, 0x51, 0x95, 0xf1, 0x69, 0x3c, 0xc8, 0x26, 0x65, 0xb3, 0x2e, 0xc1, 0x6a, 0x94, 0xf7, 0xa0, 0x71, 0xe2, 0xb8, 0xf6, 0xc8, 0x1a, 0x8c, 0xc2, 0x73, 0x6b, 0xc8, 0x47, 0xa1, 0x8d, 0x1c, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1a, - 0x85, 0xe7, 0xdb, 0x02, 0xca, 0xde, 0x87, 0xf2, 0x09, 0xe7, 0x16, 0x4e, 0x56, 0xb3, 0x94, 0x58, - 0x78, 0xea, 0x0d, 0x99, 0xa5, 0x13, 0xf5, 0xae, 0xde, 0x87, 0x86, 0x37, 0x0d, 0x4f, 0x3d, 0xc7, - 0x3d, 0xb5, 0x84, 0xbc, 0xb3, 0x9c, 0x21, 0xf2, 0x50, 0x7e, 0x33, 0xfb, 0x28, 0x63, 0xd6, 0x15, - 0x4e, 0x48, 0x9e, 0xce, 0x90, 0xbd, 0x0d, 0x8b, 0x23, 0x3b, 0x08, 0xad, 0x33, 0x6f, 0x62, 0x4d, - 0xa6, 0xc7, 0xcf, 0xf9, 0x55, 0xb3, 0x86, 0x13, 0x51, 0x13, 0xe0, 0x5d, 0x6f, 0x72, 0x88, 0x40, - 0xc1, 0xd9, 0xd8, 0x4f, 0xea, 0x04, 0xdc, 0xcd, 0xdc, 0xab, 0x99, 0x65, 0x01, 0xa1, 0x46, 0x3f, - 0x87, 0x65, 0x7c, 0x3d, 0x83, 0x69, 0x10, 0x7a, 0x63, 0x4b, 0xc8, 0x6a, 0x7f, 0x18, 0x34, 0x2b, - 0xc8, 0x6b, 0xef, 0xca, 0xce, 0x6a, 0xef, 0xf8, 0xc1, 0x36, 0x0f, 0xc2, 0x2d, 0x24, 0x36, 0x89, - 0x56, 0x6c, 0xe8, 0x57, 0xe6, 0xd2, 0x70, 0x16, 0xce, 0xde, 0x07, 0x66, 0x8f, 0x46, 0xde, 0x85, - 0x15, 0xf0, 0xd1, 0x89, 0x25, 0x27, 0xb1, 0x59, 0xbf, 0x9b, 0xb9, 0x57, 0x32, 0x1b, 0x88, 0xe9, - 0xf1, 0xd1, 0xc9, 0x21, 0xc1, 0xd9, 0x87, 0x80, 0x8b, 0xc9, 0x3a, 0xe1, 0x76, 0x38, 0xf5, 0x79, - 0xd0, 0x5c, 0xbc, 0x9b, 0xbb, 0x57, 0x7f, 0xbc, 0x14, 0xcd, 0x17, 0x82, 0x37, 0x9d, 0xd0, 0xac, - 0x0a, 0x3a, 0xf9, 0x1c, 0x6c, 0x6c, 0xc3, 0x5a, 0x7a, 0x97, 0x04, 0x53, 0x89, 0x59, 0x11, 0xcc, - 0x98, 0x37, 0xc5, 0x4f, 0xb6, 0x02, 0x85, 0x73, 0x7b, 0x34, 0xe5, 0x52, 0xa6, 0xd3, 0xc3, 0x47, - 0xd9, 0x6f, 0x67, 0x8c, 0x3f, 0xce, 0x40, 0x95, 0x46, 0x29, 0x75, 0x91, 0x37, 0xa1, 0xa6, 0xb8, - 0x81, 0xfb, 0xbe, 0xe7, 0x4b, 0xa9, 0xa6, 0x38, 0xaf, 0x2d, 0x60, 0x62, 0x57, 0x51, 0x44, 0x13, - 0x9f, 0x3b, 0x63, 0xfb, 0x54, 0x55, 0xad, 0x58, 0xe9, 0x50, 0x82, 0xd9, 0x07, 0x71, 0x7d, 0xbe, - 0x37, 0x0d, 0xb9, 0xdc, 0xf3, 0xaa, 0x72, 0x78, 0xa6, 0x80, 0x45, 0xb5, 0xe3, 0xd3, 0x2b, 0xf0, - 0xb9, 0xf1, 0x3b, 0x19, 0x60, 0xa2, 0xdb, 0x7d, 0x8f, 0x2a, 0x90, 0x1c, 0x3a, 0x5b, 0x32, 0xf3, - 0xca, 0x2b, 0x24, 0xfb, 0xa2, 0x15, 0x62, 0x40, 0x81, 0xfa, 0x9e, 0x4f, 0xe9, 0x3b, 0xa1, 0xbe, - 0x97, 0x2f, 0xe5, 0x1a, 0x79, 0xe3, 0xbf, 0xe6, 0x60, 0x65, 0x8b, 0xb6, 0xec, 0xd6, 0x60, 0xc0, - 0x27, 0xd1, 0xda, 0xb9, 0x03, 0x15, 0xd7, 0x1b, 0x72, 0xc5, 0xb1, 0xd4, 0x31, 0x10, 0x20, 0x8d, - 0x5d, 0xcf, 0x6c, 0xc7, 0xa5, 0x8e, 0xd3, 0x64, 0x96, 0x11, 0x82, 0xdd, 0x7e, 0x1b, 0x16, 0x27, - 0xdc, 0x1d, 0xea, 0x4b, 0x84, 0x94, 0xaa, 0x9a, 0x04, 0xcb, 0xd5, 0x71, 0x07, 0x2a, 0x27, 0x53, - 0xa2, 0x13, 0x82, 0x25, 0x8f, 0x3c, 0x00, 0x12, 0xd4, 0x22, 0xf9, 0x32, 0x99, 0x06, 0x67, 0x88, - 0x2d, 0x20, 0xb6, 0x28, 0x9e, 0x05, 0xea, 0x36, 0xc0, 0x70, 0x1a, 0x84, 0x72, 0xc5, 0x2c, 0x20, - 0xb2, 0x2c, 0x20, 0xb4, 0x62, 0xbe, 0x0e, 0xcb, 0x63, 0xfb, 0xd2, 0x42, 0xde, 0xb1, 0x1c, 0xd7, - 0x3a, 0x19, 0xe1, 0x9e, 0x53, 0x44, 0xba, 0xc6, 0xd8, 0xbe, 0xfc, 0x54, 0x60, 0x3a, 0xee, 0x0e, - 0xc2, 0x85, 0x58, 0x51, 0xea, 0x8e, 0xcf, 0x03, 0xee, 0x9f, 0x73, 0x94, 0x04, 0xf9, 0x48, 0xa7, - 0x31, 0x09, 0x2a, 0x7a, 0x34, 0x16, 0xe3, 0x0e, 0x47, 0x03, 0x5a, 0xf6, 0x66, 0x71, 0xec, 0xb8, - 0xbb, 0xe1, 0x68, 0x20, 0xf6, 0x15, 0x21, 0x47, 0x26, 0xdc, 0xb7, 0x9e, 0x5f, 0xe0, 0x1a, 0xce, - 0xa3, 0xdc, 0x38, 0xe4, 0xfe, 0xb3, 0x0b, 0xb1, 0xf5, 0x0f, 0x02, 0x14, 0x44, 0xf6, 0x55, 0xb3, - 0x82, 0x0b, 0xbc, 0x34, 0x08, 0x84, 0x08, 0xb2, 0xaf, 0xc4, 0x22, 0x14, 0xbd, 0xb5, 0xf1, 0x2d, - 0xf0, 0x21, 0x56, 0x1f, 0xa0, 0x44, 0xad, 0x61, 0x67, 0x5b, 0x12, 0x21, 0xda, 0x09, 0x04, 0xd7, - 0xab, 0xce, 0x9e, 0x8c, 0xec, 0xd3, 0x00, 0x45, 0x4a, 0xcd, 0xac, 0x4a, 0xe0, 0x8e, 0x80, 0x19, - 0x9f, 0x91, 0x92, 0xa5, 0xbd, 0x5b, 0xb9, 0x66, 0xc4, 0x56, 0x8f, 0x10, 0x7c, 0xaf, 0x25, 0x53, - 0x3e, 0xa5, 0xbd, 0xb4, 0x6c, 0xca, 0x4b, 0x33, 0x7e, 0x2f, 0x03, 0x55, 0x59, 0x33, 0x2a, 0x25, - 0xec, 0x01, 0x30, 0xf5, 0x16, 0xc3, 0x4b, 0x67, 0x68, 0x1d, 0x5f, 0x85, 0x3c, 0x20, 0xa6, 0xd9, - 0xbd, 0x61, 0x36, 0x24, 0xae, 0x7f, 0xe9, 0x0c, 0x37, 0x05, 0x86, 0xdd, 0x87, 0x46, 0x82, 0x3e, - 0x08, 0x7d, 0xe2, 0xe8, 0xdd, 0x1b, 0x66, 0x5d, 0xa3, 0xee, 0x85, 0xbe, 0x58, 0x23, 0x42, 0xe5, - 0x99, 0x86, 0x96, 0xe3, 0x0e, 0xf9, 0x25, 0xb2, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x23, 0x40, 0x9b, - 0x75, 0xa8, 0xea, 0xd5, 0x19, 0xa7, 0x50, 0x52, 0xfa, 0x12, 0x2a, 0x0c, 0x33, 0x5d, 0x32, 0xcb, - 0x61, 0xd4, 0x93, 0x9b, 0x50, 0x4a, 0xf6, 0xc0, 0x2c, 0x86, 0xaf, 0xdc, 0xb0, 0xf1, 0x1d, 0x68, - 0xec, 0x09, 0xe6, 0x71, 0x05, 0xb3, 0x4a, 0xfd, 0x6f, 0x0d, 0x16, 0xb4, 0x45, 0x53, 0x36, 0xe5, - 0x93, 0xd8, 0x73, 0xcf, 0xbc, 0x20, 0x94, 0xad, 0xe0, 0x6f, 0xe3, 0x4f, 0x32, 0xc0, 0xda, 0x41, - 0xe8, 0x8c, 0xed, 0x90, 0xef, 0xf0, 0x48, 0x2c, 0x1c, 0x40, 0x55, 0xd4, 0xd6, 0xf7, 0x5a, 0xa4, - 0x90, 0x91, 0x42, 0xf1, 0x9e, 0x5c, 0xc6, 0xf3, 0x05, 0x1e, 0xe8, 0xd4, 0x24, 0xe6, 0x13, 0x15, - 0x88, 0x55, 0x16, 0xda, 0xfe, 0x29, 0x0f, 0x51, 0x8d, 0x93, 0xfa, 0x3e, 0x10, 0x48, 0x28, 0x70, - 0x1b, 0xbf, 0x06, 0x4b, 0x73, 0x75, 0xe8, 0x72, 0xb9, 0x9c, 0x22, 0x97, 0x73, 0xba, 0x5c, 0xb6, - 0x60, 0x39, 0xd1, 0x2f, 0xc9, 0x69, 0xeb, 0x50, 0x14, 0x0b, 0x42, 0x28, 0x07, 0x19, 0xd2, 0x2a, - 0x4f, 0x38, 0x17, 0x6a, 0xf0, 0x43, 0x58, 0x39, 0xe1, 0xdc, 0xb7, 0x43, 0x44, 0xe2, 0x8a, 0x11, - 0x6f, 0x48, 0x56, 0xbc, 0x24, 0x71, 0x3d, 0x3b, 0x3c, 0xe4, 0xbe, 0x78, 0x53, 0xc6, 0xff, 0xc8, - 0xc0, 0xa2, 0x90, 0xa0, 0xfb, 0xb6, 0x7b, 0xa5, 0xe6, 0x69, 0x2f, 0x75, 0x9e, 0xee, 0x69, 0x9b, - 0xa1, 0x46, 0xfd, 0x55, 0x27, 0x29, 0x37, 0x3b, 0x49, 0xec, 0x2e, 0x54, 0x13, 0x7d, 0x2d, 0x60, - 0x5f, 0x21, 0x88, 0x3a, 0xf9, 0xf3, 0x4f, 0xe3, 0xdb, 0xd0, 0x88, 0xbb, 0x2d, 0xe7, 0x90, 0x41, - 0x5e, 0xb0, 0xa4, 0xac, 0x00, 0x7f, 0x1b, 0xff, 0x34, 0x43, 0x84, 0x5b, 0x9e, 0x13, 0x69, 0xa7, - 0x82, 0x50, 0xe8, 0xbd, 0x8a, 0x50, 0xfc, 0xbe, 0x56, 0xab, 0xff, 0xf9, 0x07, 0x2b, 0x96, 0x4e, - 0xc0, 0xdd, 0xa1, 0x65, 0x8f, 0x46, 0x28, 0x7c, 0x4b, 0x66, 0x51, 0x3c, 0xb7, 0x46, 0x23, 0xe3, - 0x1d, 0x58, 0xd2, 0x7a, 0xf7, 0x82, 0x71, 0x74, 0x81, 0xed, 0x39, 0x41, 0x78, 0xe4, 0x06, 0x13, - 0x4d, 0x71, 0xbb, 0x05, 0x65, 0x21, 0x61, 0x45, 0xcf, 0x68, 0xc9, 0x16, 0x4c, 0x21, 0x72, 0x45, - 0xbf, 0x02, 0x44, 0xda, 0x97, 0x12, 0x99, 0x95, 0x48, 0xfb, 0x12, 0x91, 0xc6, 0xb7, 0x61, 0x39, - 0x51, 0x9f, 0x6c, 0xfa, 0x0d, 0x28, 0x4c, 0xc3, 0x4b, 0x4f, 0xa9, 0xe6, 0x15, 0xc9, 0x21, 0xc2, - 0x00, 0x34, 0x09, 0x63, 0x7c, 0x0c, 0x4b, 0x5d, 0x7e, 0x21, 0x17, 0xb1, 0xea, 0xc8, 0xdb, 0x90, - 0x7f, 0x89, 0x51, 0x88, 0x78, 0xe3, 0x01, 0x30, 0xbd, 0xb0, 0x6c, 0x55, 0xb3, 0x11, 0x33, 0x09, - 0x1b, 0xd1, 0x78, 0x1b, 0x58, 0xcf, 0x39, 0x75, 0xf7, 0x79, 0x10, 0xd8, 0xa7, 0xd1, 0xb2, 0x6f, - 0x40, 0x6e, 0x1c, 0x9c, 0x4a, 0x19, 0x25, 0x7e, 0x1a, 0xdf, 0x80, 0xe5, 0x04, 0x9d, 0xac, 0xf8, - 0x35, 0x28, 0x07, 0xce, 0xa9, 0x8b, 0x8a, 0x95, 0xac, 0x3a, 0x06, 0x18, 0x3b, 0xb0, 0xf2, 0x29, - 0xf7, 0x9d, 0x93, 0xab, 0x97, 0x55, 0x9f, 0xac, 0x27, 0x3b, 0x5b, 0x4f, 0x1b, 0x56, 0x67, 0xea, - 0x91, 0xcd, 0x13, 0xfb, 0xca, 0x37, 0x59, 0x32, 0xe9, 0x41, 0x93, 0x7b, 0x59, 0x5d, 0xee, 0x19, - 0x47, 0xc0, 0xb6, 0x3c, 0xd7, 0xe5, 0x83, 0xf0, 0x90, 0x73, 0x3f, 0xf6, 0x52, 0xc5, 0xbc, 0x5a, - 0x79, 0xbc, 0x2e, 0x67, 0x76, 0x56, 0x98, 0x4a, 0x26, 0x66, 0x90, 0x9f, 0x70, 0x7f, 0x8c, 0x15, - 0x97, 0x4c, 0xfc, 0x6d, 0xac, 0xc2, 0x72, 0xa2, 0x5a, 0x69, 0xd7, 0x3f, 0x82, 0xd5, 0x6d, 0x27, - 0x18, 0xcc, 0x37, 0xb8, 0x0e, 0xc5, 0xc9, 0xf4, 0xd8, 0x4a, 0xca, 0xe5, 0x67, 0xfc, 0x4a, 0x58, - 0x7b, 0xb3, 0x25, 0x64, 0x5d, 0x7f, 0x33, 0x03, 0xf9, 0xdd, 0xfe, 0xde, 0x16, 0xdb, 0x80, 0x92, - 0xe3, 0x0e, 0xbc, 0xb1, 0x50, 0xbc, 0x68, 0xcc, 0xd1, 0xf3, 0xb5, 0x0b, 0xec, 0x16, 0x94, 0x51, - 0x5f, 0x13, 0xa6, 0xad, 0x54, 0x7d, 0x4a, 0x02, 0xb0, 0xe7, 0x0d, 0x9e, 0x0b, 0x9b, 0x9a, 0x5f, - 0x4e, 0x1c, 0x1f, 0xad, 0x66, 0x65, 0x0c, 0xe7, 0x69, 0xaf, 0x8f, 0x11, 0x64, 0x11, 0x1b, 0xff, - 0xae, 0x04, 0x45, 0xb9, 0xdb, 0xd2, 0xce, 0x1d, 0x3a, 0xe7, 0x3c, 0xde, 0xb9, 0xc5, 0x93, 0xd0, - 0x07, 0x7c, 0x3e, 0xf6, 0xc2, 0x48, 0x61, 0xa3, 0x77, 0x50, 0x25, 0xa0, 0x54, 0xd9, 0x34, 0xa5, - 0x81, 0x5c, 0x0c, 0x39, 0x22, 0x1a, 0xe8, 0x5b, 0xf9, 0x2d, 0x28, 0xaa, 0xbd, 0x3f, 0x1f, 0xd9, - 0x34, 0x0b, 0x03, 0xd2, 0xd6, 0x36, 0xa0, 0x34, 0xb0, 0x27, 0xf6, 0xc0, 0x09, 0xaf, 0xa4, 0x40, - 0x88, 0x9e, 0x45, 0xed, 0x23, 0x6f, 0x60, 0x8f, 0xac, 0x63, 0x7b, 0x64, 0xbb, 0x03, 0x2e, 0x6d, - 0xf7, 0x2a, 0x02, 0x37, 0x09, 0x26, 0xec, 0x73, 0xd9, 0x4f, 0x45, 0x45, 0x26, 0xbc, 0xec, 0xbd, - 0x22, 0x13, 0xca, 0xa5, 0x37, 0x1e, 0x3b, 0xc2, 0xca, 0x20, 0x35, 0x2c, 0x67, 0x96, 0x09, 0xb2, - 0xc3, 0x71, 0xb4, 0x12, 0x7d, 0x41, 0x53, 0x57, 0xa6, 0xa6, 0x08, 0xf8, 0x19, 0x39, 0x12, 0xe6, - 0x75, 0xb1, 0x9c, 0xa6, 0x8b, 0xbd, 0x07, 0x4b, 0x53, 0x37, 0xe0, 0x61, 0x38, 0xe2, 0xc3, 0xa8, - 0x2f, 0x15, 0x24, 0x6a, 0x44, 0x08, 0xd5, 0x9d, 0x07, 0xb0, 0x4c, 0x4e, 0x87, 0xc0, 0x0e, 0xbd, - 0xe0, 0xcc, 0x09, 0xac, 0x40, 0x58, 0x48, 0x64, 0xee, 0x2e, 0x21, 0xaa, 0x27, 0x31, 0x3d, 0x32, - 0x91, 0xd6, 0x67, 0xe8, 0x7d, 0x3e, 0xe0, 0xce, 0x39, 0x1f, 0xa2, 0x9e, 0x96, 0x33, 0x57, 0x13, - 0x65, 0x4c, 0x89, 0x44, 0xa5, 0x7b, 0x3a, 0xb6, 0xa6, 0x93, 0xa1, 0x2d, 0x94, 0x95, 0x3a, 0x29, - 0xc3, 0xee, 0x74, 0x7c, 0x44, 0x10, 0xf6, 0x08, 0x94, 0x26, 0x26, 0xf5, 0xc3, 0xc5, 0x84, 0x3c, - 0x13, 0xcc, 0x6a, 0x56, 0x25, 0x05, 0x29, 0x8a, 0x09, 0x9d, 0xb3, 0x31, 0xa3, 0x73, 0x36, 0xa1, - 0x38, 0xf1, 0x9d, 0x73, 0x3b, 0xe4, 0xcd, 0x25, 0x12, 0xe0, 0xf2, 0x51, 0x48, 0x06, 0xc7, 0x75, - 0x42, 0xc7, 0x0e, 0x3d, 0xbf, 0xc9, 0x10, 0x17, 0x03, 0xd8, 0x7d, 0x58, 0x42, 0x1e, 0x09, 0x42, - 0x3b, 0x9c, 0x06, 0x52, 0x03, 0x5d, 0x46, 0x66, 0x42, 0x1d, 0xba, 0x87, 0x70, 0x54, 0x42, 0xd9, - 0x37, 0x60, 0x8d, 0xd8, 0x02, 0x4b, 0x48, 0xcd, 0x1a, 0x15, 0x82, 0x15, 0x9c, 0x8a, 0x65, 0xc4, - 0x0a, 0xfe, 0x96, 0xfa, 0xb5, 0xd0, 0x0e, 0x9e, 0xc0, 0xba, 0x64, 0x93, 0xb9, 0x52, 0xab, 0x58, - 0x6a, 0x85, 0xd0, 0x33, 0xc5, 0x1e, 0xc0, 0x92, 0xe8, 0x92, 0x33, 0xb0, 0x64, 0x69, 0xb1, 0x12, - 0xd6, 0x44, 0xef, 0xd1, 0x52, 0x5a, 0x24, 0xa4, 0x89, 0xb8, 0x67, 0xfc, 0x8a, 0x7d, 0x07, 0x16, - 0x89, 0x65, 0xd0, 0xbc, 0x42, 0x49, 0xbf, 0x81, 0x92, 0x7e, 0x55, 0x79, 0x38, 0x23, 0x2c, 0x0a, - 0xfb, 0xfa, 0x20, 0xf1, 0x2c, 0x96, 0xc3, 0xc8, 0x39, 0xe1, 0xa1, 0x33, 0xe6, 0xcd, 0x75, 0x62, - 0x30, 0xf5, 0x2c, 0x56, 0xea, 0x74, 0x82, 0x98, 0x26, 0xc9, 0x05, 0x7a, 0x42, 0xde, 0x1d, 0x79, - 0x01, 0x57, 0x2e, 0xaa, 0xe6, 0x4d, 0xb9, 0x08, 0x05, 0x50, 0xe9, 0x90, 0x42, 0x11, 0x27, 0xa3, - 0x27, 0x72, 0x24, 0xde, 0x42, 0x66, 0xa8, 0x91, 0xed, 0xa3, 0x9c, 0x89, 0x62, 0x17, 0x3f, 0xb3, - 0x2f, 0x94, 0x04, 0x79, 0x0d, 0xdf, 0x2f, 0x08, 0x90, 0x94, 0x1d, 0x3f, 0xc9, 0xd0, 0x86, 0x28, - 0xe5, 0x47, 0xa0, 0x99, 0x77, 0x24, 0x39, 0x2c, 0xcf, 0x1d, 0x5d, 0x49, 0x61, 0x02, 0x04, 0x3a, - 0x70, 0x47, 0xb8, 0x9a, 0x1d, 0x57, 0x27, 0x21, 0xd9, 0x5b, 0x55, 0x40, 0x24, 0xba, 0x03, 0x95, - 0xc9, 0xf4, 0x78, 0xe4, 0x0c, 0x88, 0x24, 0x47, 0xb5, 0x10, 0x08, 0x09, 0x84, 0x7d, 0x4b, 0x1c, - 0x45, 0x14, 0x79, 0xa4, 0xa8, 0x48, 0x18, 0x92, 0xa0, 0x6c, 0xe7, 0x3e, 0x8a, 0x93, 0xaa, 0x89, - 0xbf, 0x8d, 0x4d, 0x58, 0x49, 0x76, 0x5a, 0x6e, 0x3c, 0xf7, 0xa1, 0x24, 0x65, 0x95, 0x72, 0x7c, - 0xd4, 0x35, 0x57, 0xb4, 0x30, 0xd1, 0x22, 0xbc, 0xf1, 0x5b, 0x0b, 0xb0, 0x2c, 0xa1, 0x5b, 0x62, - 0x6a, 0x7b, 0xd3, 0xf1, 0xd8, 0xf6, 0x53, 0x84, 0x60, 0xe6, 0xc5, 0x42, 0x30, 0x3b, 0x27, 0x04, - 0x93, 0x96, 0x2f, 0xc9, 0xd0, 0xa4, 0xe5, 0x2b, 0xde, 0x25, 0x19, 0x23, 0xba, 0x1f, 0xb4, 0x26, - 0xc1, 0x7d, 0xf2, 0xb7, 0xce, 0x89, 0xec, 0x42, 0x8a, 0xc8, 0xd6, 0x05, 0xee, 0xc2, 0x8c, 0xc0, - 0x7d, 0x03, 0x88, 0x69, 0xd4, 0xdb, 0x2f, 0x92, 0x7d, 0x82, 0x30, 0xe9, 0x4c, 0x7d, 0x07, 0x16, - 0x67, 0x65, 0x1c, 0x09, 0xd3, 0x7a, 0x8a, 0x84, 0x73, 0xc6, 0x1c, 0x77, 0x2b, 0x8d, 0xb8, 0x2c, - 0x25, 0x9c, 0x33, 0xe6, 0x7b, 0x88, 0x51, 0xf4, 0x6d, 0x00, 0x6a, 0x1b, 0x17, 0x0d, 0xe0, 0xa2, - 0x79, 0x3b, 0xf9, 0x2e, 0xf4, 0x59, 0x7f, 0x20, 0x1e, 0xa6, 0x3e, 0xc7, 0x55, 0x54, 0xc6, 0x92, - 0xb8, 0x80, 0x9e, 0x41, 0xdd, 0x9b, 0x70, 0xd7, 0x8a, 0x65, 0x4d, 0x05, 0xab, 0x7a, 0xeb, 0x05, - 0x55, 0x75, 0x14, 0xad, 0x59, 0x13, 0x65, 0xa3, 0x47, 0xb6, 0x4f, 0x13, 0xcf, 0xb5, 0xda, 0xaa, - 0x5f, 0xa1, 0xb6, 0x3a, 0x16, 0x8e, 0x9e, 0x8d, 0xbf, 0x93, 0x81, 0x8a, 0xd6, 0x6d, 0xb6, 0x0a, - 0x4b, 0x5b, 0x07, 0x07, 0x87, 0x6d, 0xb3, 0xd5, 0xef, 0x7c, 0xda, 0xb6, 0xb6, 0xf6, 0x0e, 0x7a, - 0xed, 0xc6, 0x0d, 0x01, 0xde, 0x3b, 0xd8, 0x6a, 0xed, 0x59, 0x3b, 0x07, 0xe6, 0x96, 0x02, 0x67, - 0xd8, 0x1a, 0x30, 0xb3, 0xbd, 0x7f, 0xd0, 0x6f, 0x27, 0xe0, 0x59, 0xd6, 0x80, 0xea, 0xa6, 0xd9, - 0x6e, 0x6d, 0xed, 0x4a, 0x48, 0x8e, 0xad, 0x40, 0x63, 0xe7, 0xa8, 0xbb, 0xdd, 0xe9, 0x3e, 0xb5, - 0xb6, 0x5a, 0xdd, 0xad, 0xf6, 0x5e, 0x7b, 0xbb, 0x91, 0x67, 0x35, 0x28, 0xb7, 0x36, 0x5b, 0xdd, - 0xed, 0x83, 0x6e, 0x7b, 0xbb, 0x51, 0x30, 0x7e, 0x05, 0xca, 0xf1, 0x40, 0x2b, 0x50, 0x3c, 0xea, - 0x3e, 0xeb, 0x1e, 0x7c, 0xd6, 0x6d, 0xdc, 0x60, 0x65, 0x28, 0x60, 0xfb, 0x8d, 0x0c, 0x03, 0x58, - 0xa0, 0x36, 0x1b, 0x59, 0x56, 0x82, 0xfc, 0xe6, 0x41, 0x7f, 0xb7, 0x91, 0x33, 0xfe, 0x32, 0x03, - 0xab, 0x38, 0xe4, 0xe1, 0xac, 0x10, 0xb8, 0x0b, 0x95, 0x81, 0xe7, 0x4d, 0x84, 0xa5, 0x15, 0x6b, - 0x14, 0x3a, 0x48, 0x2c, 0x70, 0x12, 0xde, 0x27, 0x9e, 0x3f, 0xe0, 0x52, 0x06, 0x00, 0x82, 0x76, - 0x04, 0x44, 0xf0, 0xa0, 0x64, 0x62, 0xa2, 0x20, 0x11, 0x50, 0x21, 0x18, 0x91, 0xac, 0xc1, 0xc2, - 0xb1, 0xcf, 0xed, 0xc1, 0x99, 0x5c, 0xfd, 0xf2, 0x89, 0xbd, 0x1b, 0xfb, 0x00, 0x06, 0x82, 0xa7, - 0x46, 0x7c, 0x88, 0x4b, 0xa0, 0x64, 0x2e, 0x4a, 0xf8, 0x96, 0x04, 0x8b, 0xdd, 0xc8, 0x3e, 0xb6, - 0xdd, 0xa1, 0xe7, 0xf2, 0xa1, 0x34, 0x35, 0x62, 0x80, 0x71, 0x08, 0x6b, 0xb3, 0xe3, 0x93, 0xf2, - 0xe2, 0x43, 0x4d, 0x5e, 0x90, 0xe6, 0xbf, 0x71, 0x3d, 0x2b, 0x68, 0xb2, 0xe3, 0xef, 0xe5, 0x21, - 0x2f, 0x34, 0xc1, 0x6b, 0x95, 0x46, 0x5d, 0xb5, 0xcf, 0xcd, 0x85, 0x7f, 0xd0, 0xd5, 0x40, 0x2a, - 0x02, 0xf9, 0xb3, 0xca, 0x08, 0x41, 0xd5, 0x20, 0x42, 0xfb, 0x7c, 0x70, 0x2e, 0x1d, 0x5a, 0x84, - 0x36, 0xf9, 0xe0, 0x1c, 0x6d, 0x2a, 0x3b, 0xa4, 0xb2, 0xb4, 0xde, 0x8b, 0x81, 0x1d, 0x62, 0x49, - 0x89, 0xc2, 0x72, 0xc5, 0x08, 0x85, 0xa5, 0x9a, 0x50, 0x74, 0xdc, 0x63, 0x6f, 0xea, 0x0e, 0x71, - 0x79, 0x97, 0x4c, 0xf5, 0x88, 0xd1, 0x26, 0x94, 0x44, 0x62, 0x23, 0xa2, 0xd5, 0x5c, 0x12, 0x80, - 0xbe, 0xd8, 0x8a, 0x3e, 0x80, 0x72, 0x70, 0xe5, 0x0e, 0xf4, 0x35, 0xbc, 0x22, 0xe7, 0x47, 0x8c, - 0xfe, 0x41, 0xef, 0xca, 0x1d, 0xe0, 0x8a, 0x2d, 0x05, 0xf2, 0x17, 0x7b, 0x02, 0xa5, 0xc8, 0xef, - 0x4b, 0x12, 0xf8, 0xa6, 0x5e, 0x42, 0x39, 0x7b, 0xc9, 0xbc, 0x8e, 0x48, 0xd9, 0x43, 0x58, 0x40, - 0xe7, 0x6c, 0xd0, 0xac, 0x62, 0x21, 0xa5, 0xef, 0x8b, 0x6e, 0x60, 0xa0, 0x87, 0x0f, 0xd1, 0x51, - 0x6b, 0x4a, 0xb2, 0x8d, 0x67, 0x50, 0x4b, 0xd4, 0xa5, 0x1b, 0xd1, 0x35, 0x32, 0xa2, 0xdf, 0xd2, - 0x8d, 0xe8, 0x78, 0x27, 0x90, 0xc5, 0x74, 0xa3, 0xfa, 0xd7, 0xa0, 0xa4, 0x86, 0x22, 0xd6, 0x9f, - 0x5c, 0x3b, 0x56, 0xef, 0xf3, 0xee, 0x56, 0xe3, 0x06, 0x5b, 0x84, 0x4a, 0x6b, 0x0b, 0x97, 0x34, - 0x02, 0x32, 0x82, 0xe4, 0xb0, 0xd5, 0xeb, 0x45, 0x90, 0xac, 0xb1, 0x03, 0x8d, 0xd9, 0x9e, 0x0a, - 0x9e, 0x0c, 0x15, 0x4c, 0xba, 0xae, 0x63, 0x80, 0x30, 0x91, 0xc8, 0x1b, 0x4d, 0x7a, 0x38, 0x3d, - 0x18, 0x4f, 0xa0, 0x21, 0xf6, 0x35, 0x31, 0x55, 0x81, 0xe6, 0x02, 0x1e, 0x09, 0xdd, 0x4e, 0x77, - 0x5f, 0x97, 0xcc, 0x0a, 0xc1, 0xb0, 0x29, 0xe3, 0x43, 0x58, 0xd2, 0x8a, 0xc5, 0x26, 0xad, 0xd8, - 0x2b, 0x67, 0x4d, 0x5a, 0x34, 0x60, 0x08, 0x63, 0xac, 0xc3, 0xaa, 0x78, 0x6c, 0x9f, 0x73, 0x37, - 0xec, 0x4d, 0x8f, 0x29, 0xe6, 0xe8, 0x78, 0xae, 0x30, 0x6c, 0xca, 0x11, 0xe6, 0x7a, 0x26, 0x7f, - 0x20, 0xad, 0xdf, 0x2c, 0xb2, 0xc6, 0x86, 0xd6, 0x02, 0x16, 0x7c, 0x80, 0x7f, 0x13, 0x56, 0x70, - 0x39, 0x02, 0x89, 0x69, 0x3d, 0x6c, 0xb7, 0x4d, 0xeb, 0xa0, 0xbb, 0xd7, 0xe9, 0x0a, 0x41, 0x29, - 0xa6, 0x15, 0x01, 0x3b, 0x3b, 0x08, 0xc9, 0x18, 0x0d, 0xa8, 0x3f, 0xe5, 0x61, 0xc7, 0x3d, 0xf1, - 0x54, 0x7c, 0xed, 0xa7, 0x05, 0x58, 0x8c, 0x40, 0xb1, 0x15, 0x7d, 0xce, 0xfd, 0xc0, 0xf1, 0x5c, - 0x54, 0x88, 0xcb, 0xa6, 0x7a, 0x14, 0xbb, 0x9b, 0x33, 0xe4, 0x6e, 0xe8, 0x84, 0x57, 0x56, 0xc2, - 0xe5, 0x56, 0x57, 0x60, 0xb9, 0x8b, 0xae, 0x40, 0xc1, 0x1e, 0x39, 0xb6, 0x0a, 0xd5, 0xd2, 0x83, - 0x80, 0x0e, 0xbc, 0x91, 0xe7, 0xa3, 0xee, 0x5b, 0x36, 0xe9, 0x81, 0x3d, 0x82, 0x15, 0xa1, 0x83, - 0xeb, 0x7e, 0x50, 0x94, 0x1f, 0xe4, 0xfd, 0x63, 0xee, 0x74, 0x7c, 0x18, 0xfb, 0x42, 0x05, 0x46, - 0xec, 0x9d, 0xa2, 0x84, 0x54, 0x96, 0xa2, 0x02, 0x64, 0xce, 0x2d, 0xb9, 0xd3, 0x71, 0x0b, 0x31, - 0x11, 0xfd, 0x63, 0x58, 0x15, 0xf4, 0x91, 0x7a, 0x15, 0x95, 0x58, 0xc4, 0x12, 0xa2, 0xb2, 0x8e, - 0xc4, 0x45, 0x65, 0x6e, 0x41, 0x99, 0x7a, 0x25, 0xde, 0x78, 0x81, 0xd4, 0x78, 0xec, 0x0a, 0xf7, - 0x83, 0xb9, 0xa8, 0xea, 0x02, 0x29, 0x02, 0x33, 0x51, 0x55, 0x2d, 0x2e, 0x5b, 0x9a, 0x8d, 0xcb, - 0x3e, 0x86, 0xd5, 0x63, 0xc1, 0x82, 0x67, 0xdc, 0x1e, 0x72, 0xdf, 0x8a, 0x19, 0x9b, 0xcc, 0x95, - 0x65, 0x81, 0xdc, 0x45, 0x5c, 0xb4, 0x0e, 0x84, 0x9e, 0x23, 0xc4, 0x02, 0x1f, 0x5a, 0xa1, 0x67, - 0xa1, 0xfa, 0x83, 0x02, 0xa6, 0x64, 0xd6, 0x08, 0xdc, 0xf7, 0xb6, 0x04, 0x30, 0x49, 0x77, 0xea, - 0xdb, 0x93, 0x33, 0x69, 0x50, 0x44, 0x74, 0x4f, 0x05, 0x90, 0xbd, 0x06, 0x45, 0xc1, 0xf2, 0x2e, - 0xa7, 0xe0, 0x17, 0xa9, 0xec, 0x0a, 0xc4, 0xde, 0x82, 0x05, 0x6c, 0x23, 0x68, 0x36, 0x90, 0xdf, - 0xab, 0xb1, 0x20, 0x77, 0x5c, 0x53, 0xe2, 0x84, 0x32, 0x39, 0xf5, 0x1d, 0x92, 0x32, 0x65, 0x13, - 0x7f, 0xb3, 0xef, 0x6a, 0x22, 0x6b, 0x19, 0xcb, 0x2a, 0x7d, 0x60, 0x86, 0xd3, 0xae, 0x93, 0x5e, - 0xbf, 0x50, 0x61, 0xf4, 0xbd, 0x7c, 0xa9, 0xd2, 0xa8, 0x1a, 0xdf, 0x82, 0x02, 0xcd, 0x8e, 0x60, - 0x42, 0x9c, 0xbb, 0x8c, 0x64, 0x42, 0x84, 0x36, 0xa1, 0xe8, 0xf2, 0xf0, 0xc2, 0xf3, 0x9f, 0x2b, - 0xa7, 0xb4, 0x7c, 0x34, 0x7e, 0x84, 0xde, 0x94, 0x28, 0xe2, 0x4e, 0x86, 0xa1, 0x60, 0x0f, 0x7a, - 0xbd, 0xc1, 0x99, 0x2d, 0x1d, 0x3c, 0x25, 0x04, 0xf4, 0xce, 0xec, 0x39, 0xf6, 0xc8, 0xce, 0x07, - 0xdd, 0xdf, 0x82, 0xba, 0x8a, 0xf1, 0x07, 0xd6, 0x88, 0x9f, 0x84, 0x92, 0xdd, 0xab, 0x32, 0xc0, - 0x1f, 0xec, 0xf1, 0x93, 0xd0, 0xd8, 0x87, 0x25, 0xc9, 0x90, 0x07, 0x13, 0xae, 0x9a, 0xfe, 0x76, - 0x9a, 0x3e, 0x5d, 0x79, 0xbc, 0x9c, 0xdc, 0x68, 0x29, 0x77, 0x21, 0xa1, 0x64, 0x1b, 0x9f, 0x00, - 0xd3, 0xb7, 0x61, 0x59, 0x9f, 0xd4, 0x6a, 0x95, 0x2f, 0x5f, 0x85, 0xc4, 0x22, 0xdd, 0xd9, 0x19, - 0x8a, 0xd9, 0x09, 0xa6, 0x83, 0x81, 0xca, 0xbd, 0x28, 0x99, 0xea, 0xd1, 0xf8, 0xb3, 0x0c, 0x2c, - 0x63, 0x65, 0xca, 0x1e, 0x90, 0x42, 0xf6, 0x67, 0xee, 0xa4, 0x78, 0x3f, 0xba, 0xee, 0x43, 0x0f, - 0x5f, 0xdd, 0x7b, 0x9a, 0x9f, 0xf3, 0x9e, 0xbe, 0x0b, 0x8d, 0x21, 0x1f, 0x39, 0x98, 0x86, 0xa3, - 0x54, 0x09, 0xb2, 0x00, 0x16, 0x15, 0x5c, 0x5a, 0x83, 0xc6, 0x3f, 0xca, 0xc0, 0x12, 0x69, 0x2a, - 0x68, 0x57, 0xcb, 0x89, 0xfa, 0x58, 0x19, 0x92, 0x52, 0x54, 0xc9, 0x31, 0xc5, 0x3b, 0x38, 0x42, - 0x89, 0x78, 0xf7, 0x86, 0x34, 0x30, 0x25, 0x94, 0x7d, 0x84, 0x36, 0x8c, 0x6b, 0x21, 0x30, 0x25, - 0xad, 0x27, 0xf9, 0x52, 0x76, 0x6f, 0xa0, 0x81, 0xe3, 0x22, 0x68, 0xb3, 0x24, 0x2c, 0x5b, 0x01, - 0x36, 0x76, 0xa0, 0x96, 0x68, 0x26, 0xe1, 0xe2, 0xad, 0x92, 0x8b, 0x77, 0x2e, 0x8c, 0x92, 0x9d, - 0x0f, 0xa3, 0xfc, 0xad, 0x3c, 0x30, 0xc1, 0x52, 0x33, 0x6f, 0x6d, 0x26, 0x06, 0x99, 0x9d, 0x8b, - 0x41, 0x3e, 0x02, 0xa6, 0x11, 0xa8, 0xd0, 0x68, 0x2e, 0x0a, 0x8d, 0x36, 0x62, 0x5a, 0x19, 0x19, - 0x7d, 0x04, 0x2b, 0x52, 0xa1, 0x8d, 0x82, 0x8e, 0xe8, 0xbb, 0xa3, 0xf7, 0xc3, 0x48, 0xb3, 0x55, - 0xc1, 0x47, 0xf4, 0xe3, 0xa9, 0xf8, 0xa3, 0xb0, 0xc1, 0xc9, 0xe5, 0x85, 0xf1, 0x47, 0x65, 0x7d, - 0x6b, 0x5c, 0xb0, 0xf0, 0x52, 0x2e, 0x28, 0xce, 0x71, 0x81, 0xe6, 0x81, 0x29, 0x25, 0x3d, 0x30, - 0x06, 0xd4, 0x54, 0x94, 0x91, 0x92, 0x2b, 0x48, 0x7b, 0xab, 0xc8, 0x50, 0x23, 0x26, 0x58, 0xdc, - 0x83, 0x86, 0x72, 0x93, 0x44, 0x3e, 0x1e, 0x4a, 0x1c, 0x90, 0x5e, 0xb6, 0x2d, 0xe5, 0xe9, 0x49, - 0x78, 0xd4, 0x2b, 0x33, 0x1e, 0xf5, 0xf7, 0x60, 0x29, 0x10, 0x4c, 0x64, 0x4d, 0x5d, 0x99, 0xe5, - 0xc3, 0x87, 0x68, 0x3a, 0x95, 0xcc, 0x06, 0x22, 0x8e, 0x62, 0xf8, 0xbc, 0xff, 0xa2, 0x96, 0xe2, - 0xbf, 0x78, 0x12, 0x07, 0xe4, 0x82, 0x33, 0x67, 0x8c, 0x1b, 0x77, 0x9c, 0x11, 0x23, 0x27, 0xb8, - 0x77, 0xe6, 0x8c, 0x4d, 0x15, 0xfd, 0x15, 0x0f, 0xc6, 0xbf, 0xcd, 0x40, 0x43, 0xf0, 0x41, 0x82, - 0xcf, 0x7f, 0x05, 0x70, 0x45, 0xbe, 0x22, 0x9b, 0x57, 0x04, 0xad, 0xe2, 0xf2, 0x6f, 0x01, 0xb2, + 0x85, 0xe7, 0xdb, 0x02, 0xca, 0xbe, 0x0e, 0xe5, 0x13, 0xce, 0x2d, 0x9c, 0xac, 0x66, 0x29, 0xb1, + 0xf0, 0xd4, 0x1b, 0x32, 0x4b, 0x27, 0xea, 0x5d, 0x7d, 0x1d, 0x1a, 0xde, 0x34, 0x3c, 0xf5, 0x1c, + 0xf7, 0xd4, 0x12, 0xf2, 0xce, 0x72, 0x86, 0xc8, 0x43, 0xf9, 0xcd, 0xec, 0xa3, 0x8c, 0x59, 0x57, + 0x38, 0x21, 0x79, 0x3a, 0x43, 0xf6, 0x36, 0x2c, 0x8e, 0xec, 0x20, 0xb4, 0xce, 0xbc, 0x89, 0x35, + 0x99, 0x1e, 0x3f, 0xe7, 0x57, 0xcd, 0x1a, 0x4e, 0x44, 0x4d, 0x80, 0x77, 0xbd, 0xc9, 0x21, 0x02, + 0x05, 0x67, 0x63, 0x3f, 0xa9, 0x13, 0x70, 0x37, 0x73, 0xaf, 0x66, 0x96, 0x05, 0x84, 0x1a, 0xfd, + 0x0c, 0x96, 0xf1, 0xf5, 0x0c, 0xa6, 0x41, 0xe8, 0x8d, 0x2d, 0x21, 0xab, 0xfd, 0x61, 0xd0, 0xac, + 0x20, 0xaf, 0xbd, 0x2b, 0x3b, 0xab, 0xbd, 0xe3, 0x07, 0xdb, 0x3c, 0x08, 0xb7, 0x90, 0xd8, 0x24, + 0x5a, 0xb1, 0xa1, 0x5f, 0x99, 0x4b, 0xc3, 0x59, 0x38, 0xfb, 0x3a, 0x30, 0x7b, 0x34, 0xf2, 0x2e, + 0xac, 0x80, 0x8f, 0x4e, 0x2c, 0x39, 0x89, 0xcd, 0xfa, 0xdd, 0xcc, 0xbd, 0x92, 0xd9, 0x40, 0x4c, + 0x8f, 0x8f, 0x4e, 0x0e, 0x09, 0xce, 0x3e, 0x00, 0x5c, 0x4c, 0xd6, 0x09, 0xb7, 0xc3, 0xa9, 0xcf, + 0x83, 0xe6, 0xe2, 0xdd, 0xdc, 0xbd, 0xfa, 0xe3, 0xa5, 0x68, 0xbe, 0x10, 0xbc, 0xe9, 0x84, 0x66, + 0x55, 0xd0, 0xc9, 0xe7, 0x60, 0x63, 0x1b, 0xd6, 0xd2, 0xbb, 0x24, 0x98, 0x4a, 0xcc, 0x8a, 0x60, + 0xc6, 0xbc, 0x29, 0x7e, 0xb2, 0x15, 0x28, 0x9c, 0xdb, 0xa3, 0x29, 0x97, 0x32, 0x9d, 0x1e, 0x3e, + 0xcc, 0x7e, 0x27, 0x63, 0xfc, 0x49, 0x06, 0xaa, 0x34, 0x4a, 0xa9, 0x8b, 0xbc, 0x09, 0x35, 0xc5, + 0x0d, 0xdc, 0xf7, 0x3d, 0x5f, 0x4a, 0x35, 0xc5, 0x79, 0x6d, 0x01, 0x13, 0xbb, 0x8a, 0x22, 0x9a, + 0xf8, 0xdc, 0x19, 0xdb, 0xa7, 0xaa, 0x6a, 0xc5, 0x4a, 0x87, 0x12, 0xcc, 0xde, 0x8f, 0xeb, 0xf3, + 0xbd, 0x69, 0xc8, 0xe5, 0x9e, 0x57, 0x95, 0xc3, 0x33, 0x05, 0x2c, 0xaa, 0x1d, 0x9f, 0x5e, 0x81, + 0xcf, 0x8d, 0xdf, 0xcd, 0x00, 0x13, 0xdd, 0xee, 0x7b, 0x54, 0x81, 0xe4, 0xd0, 0xd9, 0x92, 0x99, + 0x57, 0x5e, 0x21, 0xd9, 0x17, 0xad, 0x10, 0x03, 0x0a, 0xd4, 0xf7, 0x7c, 0x4a, 0xdf, 0x09, 0xf5, + 0x83, 0x7c, 0x29, 0xd7, 0xc8, 0x1b, 0xff, 0x2d, 0x07, 0x2b, 0x5b, 0xb4, 0x65, 0xb7, 0x06, 0x03, + 0x3e, 0x89, 0xd6, 0xce, 0x1d, 0xa8, 0xb8, 0xde, 0x90, 0x2b, 0x8e, 0xa5, 0x8e, 0x81, 0x00, 0x69, + 0xec, 0x7a, 0x66, 0x3b, 0x2e, 0x75, 0x9c, 0x26, 0xb3, 0x8c, 0x10, 0xec, 0xf6, 0xdb, 0xb0, 0x38, + 0xe1, 0xee, 0x50, 0x5f, 0x22, 0xa4, 0x54, 0xd5, 0x24, 0x58, 0xae, 0x8e, 0x3b, 0x50, 0x39, 0x99, + 0x12, 0x9d, 0x10, 0x2c, 0x79, 0xe4, 0x01, 0x90, 0xa0, 0x16, 0xc9, 0x97, 0xc9, 0x34, 0x38, 0x43, + 0x6c, 0x01, 0xb1, 0x45, 0xf1, 0x2c, 0x50, 0xb7, 0x01, 0x86, 0xd3, 0x20, 0x94, 0x2b, 0x66, 0x01, + 0x91, 0x65, 0x01, 0xa1, 0x15, 0xf3, 0x0d, 0x58, 0x1e, 0xdb, 0x97, 0x16, 0xf2, 0x8e, 0xe5, 0xb8, + 0xd6, 0xc9, 0x08, 0xf7, 0x9c, 0x22, 0xd2, 0x35, 0xc6, 0xf6, 0xe5, 0x27, 0x02, 0xd3, 0x71, 0x77, + 0x10, 0x2e, 0xc4, 0x8a, 0x52, 0x77, 0x7c, 0x1e, 0x70, 0xff, 0x9c, 0xa3, 0x24, 0xc8, 0x47, 0x3a, + 0x8d, 0x49, 0x50, 0xd1, 0xa3, 0xb1, 0x18, 0x77, 0x38, 0x1a, 0xd0, 0xb2, 0x37, 0x8b, 0x63, 0xc7, + 0xdd, 0x0d, 0x47, 0x03, 0xb1, 0xaf, 0x08, 0x39, 0x32, 0xe1, 0xbe, 0xf5, 0xfc, 0x02, 0xd7, 0x70, + 0x1e, 0xe5, 0xc6, 0x21, 0xf7, 0x9f, 0x5d, 0x88, 0xad, 0x7f, 0x10, 0xa0, 0x20, 0xb2, 0xaf, 0x9a, + 0x15, 0x5c, 0xe0, 0xa5, 0x41, 0x20, 0x44, 0x90, 0x7d, 0x25, 0x16, 0xa1, 0xe8, 0xad, 0x8d, 0x6f, + 0x81, 0x0f, 0xb1, 0xfa, 0x00, 0x25, 0x6a, 0x0d, 0x3b, 0xdb, 0x92, 0x08, 0xd1, 0x4e, 0x20, 0xb8, + 0x5e, 0x75, 0xf6, 0x64, 0x64, 0x9f, 0x06, 0x28, 0x52, 0x6a, 0x66, 0x55, 0x02, 0x77, 0x04, 0xcc, + 0xf8, 0x94, 0x94, 0x2c, 0xed, 0xdd, 0xca, 0x35, 0x23, 0xb6, 0x7a, 0x84, 0xe0, 0x7b, 0x2d, 0x99, + 0xf2, 0x29, 0xed, 0xa5, 0x65, 0x53, 0x5e, 0x9a, 0xf1, 0xfb, 0x19, 0xa8, 0xca, 0x9a, 0x51, 0x29, + 0x61, 0x0f, 0x80, 0xa9, 0xb7, 0x18, 0x5e, 0x3a, 0x43, 0xeb, 0xf8, 0x2a, 0xe4, 0x01, 0x31, 0xcd, + 0xee, 0x0d, 0xb3, 0x21, 0x71, 0xfd, 0x4b, 0x67, 0xb8, 0x29, 0x30, 0xec, 0x3e, 0x34, 0x12, 0xf4, + 0x41, 0xe8, 0x13, 0x47, 0xef, 0xde, 0x30, 0xeb, 0x1a, 0x75, 0x2f, 0xf4, 0xc5, 0x1a, 0x11, 0x2a, + 0xcf, 0x34, 0xb4, 0x1c, 0x77, 0xc8, 0x2f, 0x91, 0x8d, 0x6a, 0x66, 0x85, 0x60, 0x1d, 0x01, 0xda, + 0xac, 0x43, 0x55, 0xaf, 0xce, 0x38, 0x85, 0x92, 0xd2, 0x97, 0x50, 0x61, 0x98, 0xe9, 0x92, 0x59, + 0x0e, 0xa3, 0x9e, 0xdc, 0x84, 0x52, 0xb2, 0x07, 0x66, 0x31, 0x7c, 0xe5, 0x86, 0x8d, 0xef, 0x41, + 0x63, 0x4f, 0x30, 0x8f, 0x2b, 0x98, 0x55, 0xea, 0x7f, 0x6b, 0xb0, 0xa0, 0x2d, 0x9a, 0xb2, 0x29, + 0x9f, 0xc4, 0x9e, 0x7b, 0xe6, 0x05, 0xa1, 0x6c, 0x05, 0x7f, 0x1b, 0x7f, 0x9a, 0x01, 0xd6, 0x0e, + 0x42, 0x67, 0x6c, 0x87, 0x7c, 0x87, 0x47, 0x62, 0xe1, 0x00, 0xaa, 0xa2, 0xb6, 0xbe, 0xd7, 0x22, + 0x85, 0x8c, 0x14, 0x8a, 0xf7, 0xe4, 0x32, 0x9e, 0x2f, 0xf0, 0x40, 0xa7, 0x26, 0x31, 0x9f, 0xa8, + 0x40, 0xac, 0xb2, 0xd0, 0xf6, 0x4f, 0x79, 0x88, 0x6a, 0x9c, 0xd4, 0xf7, 0x81, 0x40, 0x42, 0x81, + 0xdb, 0xf8, 0x55, 0x58, 0x9a, 0xab, 0x43, 0x97, 0xcb, 0xe5, 0x14, 0xb9, 0x9c, 0xd3, 0xe5, 0xb2, + 0x05, 0xcb, 0x89, 0x7e, 0x49, 0x4e, 0x5b, 0x87, 0xa2, 0x58, 0x10, 0x42, 0x39, 0xc8, 0x90, 0x56, + 0x79, 0xc2, 0xb9, 0x50, 0x83, 0x1f, 0xc2, 0xca, 0x09, 0xe7, 0xbe, 0x1d, 0x22, 0x12, 0x57, 0x8c, + 0x78, 0x43, 0xb2, 0xe2, 0x25, 0x89, 0xeb, 0xd9, 0xe1, 0x21, 0xf7, 0xc5, 0x9b, 0x32, 0xfe, 0x47, + 0x06, 0x16, 0x85, 0x04, 0xdd, 0xb7, 0xdd, 0x2b, 0x35, 0x4f, 0x7b, 0xa9, 0xf3, 0x74, 0x4f, 0xdb, + 0x0c, 0x35, 0xea, 0x2f, 0x3b, 0x49, 0xb9, 0xd9, 0x49, 0x62, 0x77, 0xa1, 0x9a, 0xe8, 0x6b, 0x01, + 0xfb, 0x0a, 0x41, 0xd4, 0xc9, 0x5f, 0x7c, 0x1a, 0xdf, 0x86, 0x46, 0xdc, 0x6d, 0x39, 0x87, 0x0c, + 0xf2, 0x82, 0x25, 0x65, 0x05, 0xf8, 0xdb, 0xf8, 0x67, 0x19, 0x22, 0xdc, 0xf2, 0x9c, 0x48, 0x3b, + 0x15, 0x84, 0x42, 0xef, 0x55, 0x84, 0xe2, 0xf7, 0xb5, 0x5a, 0xfd, 0x2f, 0x3e, 0x58, 0xb1, 0x74, + 0x02, 0xee, 0x0e, 0x2d, 0x7b, 0x34, 0x42, 0xe1, 0x5b, 0x32, 0x8b, 0xe2, 0xb9, 0x35, 0x1a, 0x19, + 0xef, 0xc0, 0x92, 0xd6, 0xbb, 0x17, 0x8c, 0xa3, 0x0b, 0x6c, 0xcf, 0x09, 0xc2, 0x23, 0x37, 0x98, + 0x68, 0x8a, 0xdb, 0x2d, 0x28, 0x0b, 0x09, 0x2b, 0x7a, 0x46, 0x4b, 0xb6, 0x60, 0x0a, 0x91, 0x2b, + 0xfa, 0x15, 0x20, 0xd2, 0xbe, 0x94, 0xc8, 0xac, 0x44, 0xda, 0x97, 0x88, 0x34, 0xbe, 0x03, 0xcb, + 0x89, 0xfa, 0x64, 0xd3, 0x6f, 0x40, 0x61, 0x1a, 0x5e, 0x7a, 0x4a, 0x35, 0xaf, 0x48, 0x0e, 0x11, + 0x06, 0xa0, 0x49, 0x18, 0xe3, 0x23, 0x58, 0xea, 0xf2, 0x0b, 0xb9, 0x88, 0x55, 0x47, 0xde, 0x86, + 0xfc, 0x4b, 0x8c, 0x42, 0xc4, 0x1b, 0x0f, 0x80, 0xe9, 0x85, 0x65, 0xab, 0x9a, 0x8d, 0x98, 0x49, + 0xd8, 0x88, 0xc6, 0xdb, 0xc0, 0x7a, 0xce, 0xa9, 0xbb, 0xcf, 0x83, 0xc0, 0x3e, 0x8d, 0x96, 0x7d, + 0x03, 0x72, 0xe3, 0xe0, 0x54, 0xca, 0x28, 0xf1, 0xd3, 0xf8, 0x26, 0x2c, 0x27, 0xe8, 0x64, 0xc5, + 0xaf, 0x41, 0x39, 0x70, 0x4e, 0x5d, 0x54, 0xac, 0x64, 0xd5, 0x31, 0xc0, 0xd8, 0x81, 0x95, 0x4f, + 0xb8, 0xef, 0x9c, 0x5c, 0xbd, 0xac, 0xfa, 0x64, 0x3d, 0xd9, 0xd9, 0x7a, 0xda, 0xb0, 0x3a, 0x53, + 0x8f, 0x6c, 0x9e, 0xd8, 0x57, 0xbe, 0xc9, 0x92, 0x49, 0x0f, 0x9a, 0xdc, 0xcb, 0xea, 0x72, 0xcf, + 0x38, 0x02, 0xb6, 0xe5, 0xb9, 0x2e, 0x1f, 0x84, 0x87, 0x9c, 0xfb, 0xb1, 0x97, 0x2a, 0xe6, 0xd5, + 0xca, 0xe3, 0x75, 0x39, 0xb3, 0xb3, 0xc2, 0x54, 0x32, 0x31, 0x83, 0xfc, 0x84, 0xfb, 0x63, 0xac, + 0xb8, 0x64, 0xe2, 0x6f, 0x63, 0x15, 0x96, 0x13, 0xd5, 0x4a, 0xbb, 0xfe, 0x11, 0xac, 0x6e, 0x3b, + 0xc1, 0x60, 0xbe, 0xc1, 0x75, 0x28, 0x4e, 0xa6, 0xc7, 0x56, 0x52, 0x2e, 0x3f, 0xe3, 0x57, 0xc2, + 0xda, 0x9b, 0x2d, 0x21, 0xeb, 0xfa, 0x5b, 0x19, 0xc8, 0xef, 0xf6, 0xf7, 0xb6, 0xd8, 0x06, 0x94, + 0x1c, 0x77, 0xe0, 0x8d, 0x85, 0xe2, 0x45, 0x63, 0x8e, 0x9e, 0xaf, 0x5d, 0x60, 0xb7, 0xa0, 0x8c, + 0xfa, 0x9a, 0x30, 0x6d, 0xa5, 0xea, 0x53, 0x12, 0x80, 0x3d, 0x6f, 0xf0, 0x5c, 0xd8, 0xd4, 0xfc, + 0x72, 0xe2, 0xf8, 0x68, 0x35, 0x2b, 0x63, 0x38, 0x4f, 0x7b, 0x7d, 0x8c, 0x20, 0x8b, 0xd8, 0xf8, + 0xf7, 0x25, 0x28, 0xca, 0xdd, 0x96, 0x76, 0xee, 0xd0, 0x39, 0xe7, 0xf1, 0xce, 0x2d, 0x9e, 0x84, + 0x3e, 0xe0, 0xf3, 0xb1, 0x17, 0x46, 0x0a, 0x1b, 0xbd, 0x83, 0x2a, 0x01, 0xa5, 0xca, 0xa6, 0x29, + 0x0d, 0xe4, 0x62, 0xc8, 0x11, 0xd1, 0x40, 0xdf, 0xca, 0x6f, 0x41, 0x51, 0xed, 0xfd, 0xf9, 0xc8, + 0xa6, 0x59, 0x18, 0x90, 0xb6, 0xb6, 0x01, 0xa5, 0x81, 0x3d, 0xb1, 0x07, 0x4e, 0x78, 0x25, 0x05, + 0x42, 0xf4, 0x2c, 0x6a, 0x1f, 0x79, 0x03, 0x7b, 0x64, 0x1d, 0xdb, 0x23, 0xdb, 0x1d, 0x70, 0x69, + 0xbb, 0x57, 0x11, 0xb8, 0x49, 0x30, 0x61, 0x9f, 0xcb, 0x7e, 0x2a, 0x2a, 0x32, 0xe1, 0x65, 0xef, + 0x15, 0x99, 0x50, 0x2e, 0xbd, 0xf1, 0xd8, 0x11, 0x56, 0x06, 0xa9, 0x61, 0x39, 0xb3, 0x4c, 0x90, + 0x1d, 0x8e, 0xa3, 0x95, 0xe8, 0x0b, 0x9a, 0xba, 0x32, 0x35, 0x45, 0xc0, 0x4f, 0xc9, 0x91, 0x30, + 0xaf, 0x8b, 0xe5, 0x34, 0x5d, 0xec, 0x3d, 0x58, 0x9a, 0xba, 0x01, 0x0f, 0xc3, 0x11, 0x1f, 0x46, + 0x7d, 0xa9, 0x20, 0x51, 0x23, 0x42, 0xa8, 0xee, 0x3c, 0x80, 0x65, 0x72, 0x3a, 0x04, 0x76, 0xe8, + 0x05, 0x67, 0x4e, 0x60, 0x05, 0xc2, 0x42, 0x22, 0x73, 0x77, 0x09, 0x51, 0x3d, 0x89, 0xe9, 0x91, + 0x89, 0xb4, 0x3e, 0x43, 0xef, 0xf3, 0x01, 0x77, 0xce, 0xf9, 0x10, 0xf5, 0xb4, 0x9c, 0xb9, 0x9a, + 0x28, 0x63, 0x4a, 0x24, 0x2a, 0xdd, 0xd3, 0xb1, 0x35, 0x9d, 0x0c, 0x6d, 0xa1, 0xac, 0xd4, 0x49, + 0x19, 0x76, 0xa7, 0xe3, 0x23, 0x82, 0xb0, 0x47, 0xa0, 0x34, 0x31, 0xa9, 0x1f, 0x2e, 0x26, 0xe4, + 0x99, 0x60, 0x56, 0xb3, 0x2a, 0x29, 0x48, 0x51, 0x4c, 0xe8, 0x9c, 0x8d, 0x19, 0x9d, 0xb3, 0x09, + 0xc5, 0x89, 0xef, 0x9c, 0xdb, 0x21, 0x6f, 0x2e, 0x91, 0x00, 0x97, 0x8f, 0x42, 0x32, 0x38, 0xae, + 0x13, 0x3a, 0x76, 0xe8, 0xf9, 0x4d, 0x86, 0xb8, 0x18, 0xc0, 0xee, 0xc3, 0x12, 0xf2, 0x48, 0x10, + 0xda, 0xe1, 0x34, 0x90, 0x1a, 0xe8, 0x32, 0x32, 0x13, 0xea, 0xd0, 0x3d, 0x84, 0xa3, 0x12, 0xca, + 0xbe, 0x09, 0x6b, 0xc4, 0x16, 0x58, 0x42, 0x6a, 0xd6, 0xa8, 0x10, 0xac, 0xe0, 0x54, 0x2c, 0x23, + 0x56, 0xf0, 0xb7, 0xd4, 0xaf, 0x85, 0x76, 0xf0, 0x04, 0xd6, 0x25, 0x9b, 0xcc, 0x95, 0x5a, 0xc5, + 0x52, 0x2b, 0x84, 0x9e, 0x29, 0xf6, 0x00, 0x96, 0x44, 0x97, 0x9c, 0x81, 0x25, 0x4b, 0x8b, 0x95, + 0xb0, 0x26, 0x7a, 0x8f, 0x96, 0xd2, 0x22, 0x21, 0x4d, 0xc4, 0x3d, 0xe3, 0x57, 0xec, 0x7b, 0xb0, + 0x48, 0x2c, 0x83, 0xe6, 0x15, 0x4a, 0xfa, 0x0d, 0x94, 0xf4, 0xab, 0xca, 0xc3, 0x19, 0x61, 0x51, + 0xd8, 0xd7, 0x07, 0x89, 0x67, 0xb1, 0x1c, 0x46, 0xce, 0x09, 0x0f, 0x9d, 0x31, 0x6f, 0xae, 0x13, + 0x83, 0xa9, 0x67, 0xb1, 0x52, 0xa7, 0x13, 0xc4, 0x34, 0x49, 0x2e, 0xd0, 0x13, 0xf2, 0xee, 0xc8, + 0x0b, 0xb8, 0x72, 0x51, 0x35, 0x6f, 0xca, 0x45, 0x28, 0x80, 0x4a, 0x87, 0x14, 0x8a, 0x38, 0x19, + 0x3d, 0x91, 0x23, 0xf1, 0x16, 0x32, 0x43, 0x8d, 0x6c, 0x1f, 0xe5, 0x4c, 0x14, 0xbb, 0xf8, 0x99, + 0x7d, 0xa1, 0x24, 0xc8, 0x6b, 0xf8, 0x7e, 0x41, 0x80, 0xa4, 0xec, 0xf8, 0x69, 0x86, 0x36, 0x44, + 0x29, 0x3f, 0x02, 0xcd, 0xbc, 0x23, 0xc9, 0x61, 0x79, 0xee, 0xe8, 0x4a, 0x0a, 0x13, 0x20, 0xd0, + 0x81, 0x3b, 0xc2, 0xd5, 0xec, 0xb8, 0x3a, 0x09, 0xc9, 0xde, 0xaa, 0x02, 0x22, 0xd1, 0x1d, 0xa8, + 0x4c, 0xa6, 0xc7, 0x23, 0x67, 0x40, 0x24, 0x39, 0xaa, 0x85, 0x40, 0x48, 0x20, 0xec, 0x5b, 0xe2, + 0x28, 0xa2, 0xc8, 0x23, 0x45, 0x45, 0xc2, 0x90, 0x04, 0x65, 0x3b, 0xf7, 0x51, 0x9c, 0x54, 0x4d, + 0xfc, 0x6d, 0x6c, 0xc2, 0x4a, 0xb2, 0xd3, 0x72, 0xe3, 0xb9, 0x0f, 0x25, 0x29, 0xab, 0x94, 0xe3, + 0xa3, 0xae, 0xb9, 0xa2, 0x85, 0x89, 0x16, 0xe1, 0x8d, 0xdf, 0x5e, 0x80, 0x65, 0x09, 0xdd, 0x12, + 0x53, 0xdb, 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0x22, 0x04, 0x33, 0x2f, 0x16, 0x82, 0xd9, 0x39, 0x21, + 0x98, 0xb4, 0x7c, 0x49, 0x86, 0x26, 0x2d, 0x5f, 0xf1, 0x2e, 0xc9, 0x18, 0xd1, 0xfd, 0xa0, 0x35, + 0x09, 0xee, 0x93, 0xbf, 0x75, 0x4e, 0x64, 0x17, 0x52, 0x44, 0xb6, 0x2e, 0x70, 0x17, 0x66, 0x04, + 0xee, 0x1b, 0x40, 0x4c, 0xa3, 0xde, 0x7e, 0x91, 0xec, 0x13, 0x84, 0x49, 0x67, 0xea, 0x3b, 0xb0, + 0x38, 0x2b, 0xe3, 0x48, 0x98, 0xd6, 0x53, 0x24, 0x9c, 0x33, 0xe6, 0xb8, 0x5b, 0x69, 0xc4, 0x65, + 0x29, 0xe1, 0x9c, 0x31, 0xdf, 0x43, 0x8c, 0xa2, 0x6f, 0x03, 0x50, 0xdb, 0xb8, 0x68, 0x00, 0x17, + 0xcd, 0xdb, 0xc9, 0x77, 0xa1, 0xcf, 0xfa, 0x03, 0xf1, 0x30, 0xf5, 0x39, 0xae, 0xa2, 0x32, 0x96, + 0xc4, 0x05, 0xf4, 0x0c, 0xea, 0xde, 0x84, 0xbb, 0x56, 0x2c, 0x6b, 0x2a, 0x58, 0xd5, 0x5b, 0x2f, + 0xa8, 0xaa, 0xa3, 0x68, 0xcd, 0x9a, 0x28, 0x1b, 0x3d, 0xb2, 0x7d, 0x9a, 0x78, 0xae, 0xd5, 0x56, + 0xfd, 0x12, 0xb5, 0xd5, 0xb1, 0x70, 0xf4, 0x6c, 0xfc, 0xdd, 0x0c, 0x54, 0xb4, 0x6e, 0xb3, 0x55, + 0x58, 0xda, 0x3a, 0x38, 0x38, 0x6c, 0x9b, 0xad, 0x7e, 0xe7, 0x93, 0xb6, 0xb5, 0xb5, 0x77, 0xd0, + 0x6b, 0x37, 0x6e, 0x08, 0xf0, 0xde, 0xc1, 0x56, 0x6b, 0xcf, 0xda, 0x39, 0x30, 0xb7, 0x14, 0x38, + 0xc3, 0xd6, 0x80, 0x99, 0xed, 0xfd, 0x83, 0x7e, 0x3b, 0x01, 0xcf, 0xb2, 0x06, 0x54, 0x37, 0xcd, + 0x76, 0x6b, 0x6b, 0x57, 0x42, 0x72, 0x6c, 0x05, 0x1a, 0x3b, 0x47, 0xdd, 0xed, 0x4e, 0xf7, 0xa9, + 0xb5, 0xd5, 0xea, 0x6e, 0xb5, 0xf7, 0xda, 0xdb, 0x8d, 0x3c, 0xab, 0x41, 0xb9, 0xb5, 0xd9, 0xea, + 0x6e, 0x1f, 0x74, 0xdb, 0xdb, 0x8d, 0x82, 0xf1, 0x5d, 0x28, 0xc7, 0x03, 0xad, 0x40, 0xf1, 0xa8, + 0xfb, 0xac, 0x7b, 0xf0, 0x69, 0xb7, 0x71, 0x83, 0x95, 0xa1, 0x80, 0xed, 0x37, 0x32, 0x0c, 0x60, + 0x81, 0xda, 0x6c, 0x64, 0x59, 0x09, 0xf2, 0x9b, 0x07, 0xfd, 0xdd, 0x46, 0xce, 0xf8, 0xab, 0x0c, + 0xac, 0xe2, 0x90, 0x87, 0xb3, 0x42, 0xe0, 0x2e, 0x54, 0x06, 0x9e, 0x37, 0x11, 0x96, 0x56, 0xac, + 0x51, 0xe8, 0x20, 0xb1, 0xc0, 0x49, 0x78, 0x9f, 0x78, 0xfe, 0x80, 0x4b, 0x19, 0x00, 0x08, 0xda, + 0x11, 0x10, 0xc1, 0x83, 0x92, 0x89, 0x89, 0x82, 0x44, 0x40, 0x85, 0x60, 0x44, 0xb2, 0x06, 0x0b, + 0xc7, 0x3e, 0xb7, 0x07, 0x67, 0x72, 0xf5, 0xcb, 0x27, 0xf6, 0x6e, 0xec, 0x03, 0x18, 0x08, 0x9e, + 0x1a, 0xf1, 0x21, 0x2e, 0x81, 0x92, 0xb9, 0x28, 0xe1, 0x5b, 0x12, 0x2c, 0x76, 0x23, 0xfb, 0xd8, + 0x76, 0x87, 0x9e, 0xcb, 0x87, 0xd2, 0xd4, 0x88, 0x01, 0xc6, 0x21, 0xac, 0xcd, 0x8e, 0x4f, 0xca, + 0x8b, 0x0f, 0x34, 0x79, 0x41, 0x9a, 0xff, 0xc6, 0xf5, 0xac, 0xa0, 0xc9, 0x8e, 0xbf, 0x9f, 0x87, + 0xbc, 0xd0, 0x04, 0xaf, 0x55, 0x1a, 0x75, 0xd5, 0x3e, 0x37, 0x17, 0xfe, 0x41, 0x57, 0x03, 0xa9, + 0x08, 0xe4, 0xcf, 0x2a, 0x23, 0x04, 0x55, 0x83, 0x08, 0xed, 0xf3, 0xc1, 0xb9, 0x74, 0x68, 0x11, + 0xda, 0xe4, 0x83, 0x73, 0xb4, 0xa9, 0xec, 0x90, 0xca, 0xd2, 0x7a, 0x2f, 0x06, 0x76, 0x88, 0x25, + 0x25, 0x0a, 0xcb, 0x15, 0x23, 0x14, 0x96, 0x6a, 0x42, 0xd1, 0x71, 0x8f, 0xbd, 0xa9, 0x3b, 0xc4, + 0xe5, 0x5d, 0x32, 0xd5, 0x23, 0x46, 0x9b, 0x50, 0x12, 0x89, 0x8d, 0x88, 0x56, 0x73, 0x49, 0x00, + 0xfa, 0x62, 0x2b, 0x7a, 0x1f, 0xca, 0xc1, 0x95, 0x3b, 0xd0, 0xd7, 0xf0, 0x8a, 0x9c, 0x1f, 0x31, + 0xfa, 0x07, 0xbd, 0x2b, 0x77, 0x80, 0x2b, 0xb6, 0x14, 0xc8, 0x5f, 0xec, 0x09, 0x94, 0x22, 0xbf, + 0x2f, 0x49, 0xe0, 0x9b, 0x7a, 0x09, 0xe5, 0xec, 0x25, 0xf3, 0x3a, 0x22, 0x65, 0x0f, 0x61, 0x01, + 0x9d, 0xb3, 0x41, 0xb3, 0x8a, 0x85, 0x94, 0xbe, 0x2f, 0xba, 0x81, 0x81, 0x1e, 0x3e, 0x44, 0x47, + 0xad, 0x29, 0xc9, 0x36, 0x9e, 0x41, 0x2d, 0x51, 0x97, 0x6e, 0x44, 0xd7, 0xc8, 0x88, 0x7e, 0x4b, + 0x37, 0xa2, 0xe3, 0x9d, 0x40, 0x16, 0xd3, 0x8d, 0xea, 0x5f, 0x85, 0x92, 0x1a, 0x8a, 0x58, 0x7f, + 0x72, 0xed, 0x58, 0xbd, 0xcf, 0xba, 0x5b, 0x8d, 0x1b, 0x6c, 0x11, 0x2a, 0xad, 0x2d, 0x5c, 0xd2, + 0x08, 0xc8, 0x08, 0x92, 0xc3, 0x56, 0xaf, 0x17, 0x41, 0xb2, 0xc6, 0x0e, 0x34, 0x66, 0x7b, 0x2a, + 0x78, 0x32, 0x54, 0x30, 0xe9, 0xba, 0x8e, 0x01, 0xc2, 0x44, 0x22, 0x6f, 0x34, 0xe9, 0xe1, 0xf4, + 0x60, 0x3c, 0x81, 0x86, 0xd8, 0xd7, 0xc4, 0x54, 0x05, 0x9a, 0x0b, 0x78, 0x24, 0x74, 0x3b, 0xdd, + 0x7d, 0x5d, 0x32, 0x2b, 0x04, 0xc3, 0xa6, 0x8c, 0x0f, 0x60, 0x49, 0x2b, 0x16, 0x9b, 0xb4, 0x62, + 0xaf, 0x9c, 0x35, 0x69, 0xd1, 0x80, 0x21, 0x8c, 0xb1, 0x0e, 0xab, 0xe2, 0xb1, 0x7d, 0xce, 0xdd, + 0xb0, 0x37, 0x3d, 0xa6, 0x98, 0xa3, 0xe3, 0xb9, 0xc2, 0xb0, 0x29, 0x47, 0x98, 0xeb, 0x99, 0xfc, + 0x81, 0xb4, 0x7e, 0xb3, 0xc8, 0x1a, 0x1b, 0x5a, 0x0b, 0x58, 0xf0, 0x01, 0xfe, 0x4d, 0x58, 0xc1, + 0xe5, 0x08, 0x24, 0xa6, 0xf5, 0xb0, 0xdd, 0x36, 0xad, 0x83, 0xee, 0x5e, 0xa7, 0x2b, 0x04, 0xa5, + 0x98, 0x56, 0x04, 0xec, 0xec, 0x20, 0x24, 0x63, 0x34, 0xa0, 0xfe, 0x94, 0x87, 0x1d, 0xf7, 0xc4, + 0x53, 0xf1, 0xb5, 0x9f, 0x15, 0x60, 0x31, 0x02, 0xc5, 0x56, 0xf4, 0x39, 0xf7, 0x03, 0xc7, 0x73, + 0x51, 0x21, 0x2e, 0x9b, 0xea, 0x51, 0xec, 0x6e, 0xce, 0x90, 0xbb, 0xa1, 0x13, 0x5e, 0x59, 0x09, + 0x97, 0x5b, 0x5d, 0x81, 0xe5, 0x2e, 0xba, 0x02, 0x05, 0x7b, 0xe4, 0xd8, 0x2a, 0x54, 0x4b, 0x0f, + 0x02, 0x3a, 0xf0, 0x46, 0x9e, 0x8f, 0xba, 0x6f, 0xd9, 0xa4, 0x07, 0xf6, 0x08, 0x56, 0x84, 0x0e, + 0xae, 0xfb, 0x41, 0x51, 0x7e, 0x90, 0xf7, 0x8f, 0xb9, 0xd3, 0xf1, 0x61, 0xec, 0x0b, 0x15, 0x18, + 0xb1, 0x77, 0x8a, 0x12, 0x52, 0x59, 0x8a, 0x0a, 0x90, 0x39, 0xb7, 0xe4, 0x4e, 0xc7, 0x2d, 0xc4, + 0x44, 0xf4, 0x8f, 0x61, 0x55, 0xd0, 0x47, 0xea, 0x55, 0x54, 0x62, 0x11, 0x4b, 0x88, 0xca, 0x3a, + 0x12, 0x17, 0x95, 0xb9, 0x05, 0x65, 0xea, 0x95, 0x78, 0xe3, 0x05, 0x52, 0xe3, 0xb1, 0x2b, 0xdc, + 0x0f, 0xe6, 0xa2, 0xaa, 0x0b, 0xa4, 0x08, 0xcc, 0x44, 0x55, 0xb5, 0xb8, 0x6c, 0x69, 0x36, 0x2e, + 0xfb, 0x18, 0x56, 0x8f, 0x05, 0x0b, 0x9e, 0x71, 0x7b, 0xc8, 0x7d, 0x2b, 0x66, 0x6c, 0x32, 0x57, + 0x96, 0x05, 0x72, 0x17, 0x71, 0xd1, 0x3a, 0x10, 0x7a, 0x8e, 0x10, 0x0b, 0x7c, 0x68, 0x85, 0x9e, + 0x85, 0xea, 0x0f, 0x0a, 0x98, 0x92, 0x59, 0x23, 0x70, 0xdf, 0xdb, 0x12, 0xc0, 0x24, 0xdd, 0xa9, + 0x6f, 0x4f, 0xce, 0xa4, 0x41, 0x11, 0xd1, 0x3d, 0x15, 0x40, 0xf6, 0x1a, 0x14, 0x05, 0xcb, 0xbb, + 0x9c, 0x82, 0x5f, 0xa4, 0xb2, 0x2b, 0x10, 0x7b, 0x0b, 0x16, 0xb0, 0x8d, 0xa0, 0xd9, 0x40, 0x7e, + 0xaf, 0xc6, 0x82, 0xdc, 0x71, 0x4d, 0x89, 0x13, 0xca, 0xe4, 0xd4, 0x77, 0x48, 0xca, 0x94, 0x4d, + 0xfc, 0xcd, 0xbe, 0xaf, 0x89, 0xac, 0x65, 0x2c, 0xab, 0xf4, 0x81, 0x19, 0x4e, 0xbb, 0x4e, 0x7a, + 0x7d, 0xa5, 0xc2, 0xe8, 0x07, 0xf9, 0x52, 0xa5, 0x51, 0x35, 0xbe, 0x0d, 0x05, 0x9a, 0x1d, 0xc1, + 0x84, 0x38, 0x77, 0x19, 0xc9, 0x84, 0x08, 0x6d, 0x42, 0xd1, 0xe5, 0xe1, 0x85, 0xe7, 0x3f, 0x57, + 0x4e, 0x69, 0xf9, 0x68, 0xfc, 0x18, 0xbd, 0x29, 0x51, 0xc4, 0x9d, 0x0c, 0x43, 0xc1, 0x1e, 0xf4, + 0x7a, 0x83, 0x33, 0x5b, 0x3a, 0x78, 0x4a, 0x08, 0xe8, 0x9d, 0xd9, 0x73, 0xec, 0x91, 0x9d, 0x0f, + 0xba, 0xbf, 0x05, 0x75, 0x15, 0xe3, 0x0f, 0xac, 0x11, 0x3f, 0x09, 0x25, 0xbb, 0x57, 0x65, 0x80, + 0x3f, 0xd8, 0xe3, 0x27, 0xa1, 0xb1, 0x0f, 0x4b, 0x92, 0x21, 0x0f, 0x26, 0x5c, 0x35, 0xfd, 0x9d, + 0x34, 0x7d, 0xba, 0xf2, 0x78, 0x39, 0xb9, 0xd1, 0x52, 0xee, 0x42, 0x42, 0xc9, 0x36, 0x3e, 0x06, + 0xa6, 0x6f, 0xc3, 0xb2, 0x3e, 0xa9, 0xd5, 0x2a, 0x5f, 0xbe, 0x0a, 0x89, 0x45, 0xba, 0xb3, 0x33, + 0x14, 0xb3, 0x13, 0x4c, 0x07, 0x03, 0x95, 0x7b, 0x51, 0x32, 0xd5, 0xa3, 0xf1, 0xe7, 0x19, 0x58, + 0xc6, 0xca, 0x94, 0x3d, 0x20, 0x85, 0xec, 0xcf, 0xdd, 0x49, 0xf1, 0x7e, 0x74, 0xdd, 0x87, 0x1e, + 0xbe, 0xbc, 0xf7, 0x34, 0x3f, 0xe7, 0x3d, 0x7d, 0x17, 0x1a, 0x43, 0x3e, 0x72, 0x30, 0x0d, 0x47, + 0xa9, 0x12, 0x64, 0x01, 0x2c, 0x2a, 0xb8, 0xb4, 0x06, 0x8d, 0x7f, 0x9c, 0x81, 0x25, 0xd2, 0x54, + 0xd0, 0xae, 0x96, 0x13, 0xf5, 0x91, 0x32, 0x24, 0xa5, 0xa8, 0x92, 0x63, 0x8a, 0x77, 0x70, 0x84, + 0x12, 0xf1, 0xee, 0x0d, 0x69, 0x60, 0x4a, 0x28, 0xfb, 0x10, 0x6d, 0x18, 0xd7, 0x42, 0x60, 0x4a, + 0x5a, 0x4f, 0xf2, 0xa5, 0xec, 0xde, 0x40, 0x03, 0xc7, 0x45, 0xd0, 0x66, 0x49, 0x58, 0xb6, 0x02, + 0x6c, 0xec, 0x40, 0x2d, 0xd1, 0x4c, 0xc2, 0xc5, 0x5b, 0x25, 0x17, 0xef, 0x5c, 0x18, 0x25, 0x3b, + 0x1f, 0x46, 0xf9, 0xdb, 0x79, 0x60, 0x82, 0xa5, 0x66, 0xde, 0xda, 0x4c, 0x0c, 0x32, 0x3b, 0x17, + 0x83, 0x7c, 0x04, 0x4c, 0x23, 0x50, 0xa1, 0xd1, 0x5c, 0x14, 0x1a, 0x6d, 0xc4, 0xb4, 0x32, 0x32, + 0xfa, 0x08, 0x56, 0xa4, 0x42, 0x1b, 0x05, 0x1d, 0xd1, 0x77, 0x47, 0xef, 0x87, 0x91, 0x66, 0xab, + 0x82, 0x8f, 0xe8, 0xc7, 0x53, 0xf1, 0x47, 0x61, 0x83, 0x93, 0xcb, 0x0b, 0xe3, 0x8f, 0xca, 0xfa, + 0xd6, 0xb8, 0x60, 0xe1, 0xa5, 0x5c, 0x50, 0x9c, 0xe3, 0x02, 0xcd, 0x03, 0x53, 0x4a, 0x7a, 0x60, + 0x0c, 0xa8, 0xa9, 0x28, 0x23, 0x25, 0x57, 0x90, 0xf6, 0x56, 0x91, 0xa1, 0x46, 0x4c, 0xb0, 0xb8, + 0x07, 0x0d, 0xe5, 0x26, 0x89, 0x7c, 0x3c, 0x94, 0x38, 0x20, 0xbd, 0x6c, 0x5b, 0xca, 0xd3, 0x93, + 0xf0, 0xa8, 0x57, 0x66, 0x3c, 0xea, 0xef, 0xc1, 0x52, 0x20, 0x98, 0xc8, 0x9a, 0xba, 0x32, 0xcb, + 0x87, 0x0f, 0xd1, 0x74, 0x2a, 0x99, 0x0d, 0x44, 0x1c, 0xc5, 0xf0, 0x79, 0xff, 0x45, 0x2d, 0xc5, + 0x7f, 0xf1, 0x24, 0x0e, 0xc8, 0x05, 0x67, 0xce, 0x18, 0x37, 0xee, 0x38, 0x23, 0x46, 0x4e, 0x70, + 0xef, 0xcc, 0x19, 0x9b, 0x2a, 0xfa, 0x2b, 0x1e, 0x8c, 0x7f, 0x97, 0x81, 0x86, 0xe0, 0x83, 0x04, + 0x9f, 0x7f, 0x17, 0x70, 0x45, 0xbe, 0x22, 0x9b, 0x57, 0x04, 0xad, 0xe2, 0xf2, 0x6f, 0x03, 0xb2, 0xad, 0x25, 0xec, 0x44, 0xc9, 0xe4, 0xcd, 0x24, 0x93, 0xc7, 0x82, 0x6c, 0xf7, 0x06, 0x19, 0x00, 0x02, 0x92, 0x16, 0x08, 0xcd, 0xa7, 0x04, 0x42, 0xb5, 0xa5, 0xb0, 0x0b, 0xf0, 0x8c, 0x5f, 0xed, 0x79, 0x03, 0xb4, 0xd0, 0x6e, 0x03, 0x08, 0x86, 0x3c, 0xb1, 0xc7, 0x8e, 0xf4, 0xae, 0x14, 0xcc, @@ -11844,464 +11847,464 @@ var fileDescriptor_77a6da22d6a3feb1 = []byte{ 0x5f, 0xd1, 0x62, 0xb0, 0xa0, 0xf6, 0x8c, 0x5f, 0x6d, 0x73, 0x52, 0xd7, 0x3c, 0x5f, 0x70, 0x82, 0x6f, 0x5f, 0x08, 0xfd, 0x2c, 0x11, 0xc4, 0xac, 0xf8, 0xf6, 0xc5, 0x33, 0x7e, 0xa5, 0x02, 0xaa, 0x45, 0x81, 0x1f, 0x79, 0x03, 0xb9, 0x03, 0xa9, 0x74, 0x8c, 0xb8, 0x53, 0xe6, 0xc2, 0x73, 0xfc, - 0x6d, 0xfc, 0x55, 0x06, 0x6a, 0xa2, 0xff, 0x28, 0xe0, 0xc4, 0xbc, 0xab, 0xac, 0x9e, 0x4c, 0x9c, - 0xd5, 0xf3, 0x58, 0xca, 0x07, 0x92, 0x96, 0xd9, 0xeb, 0xa5, 0x25, 0x4e, 0x30, 0x89, 0xca, 0x0f, - 0xa0, 0x4c, 0x6b, 0x4b, 0x2c, 0xd6, 0x5c, 0xe2, 0x2d, 0x25, 0x06, 0x64, 0x96, 0x90, 0xec, 0x19, + 0x6d, 0xfc, 0x75, 0x06, 0x6a, 0xa2, 0xff, 0x28, 0xe0, 0xc4, 0xbc, 0xab, 0xac, 0x9e, 0x4c, 0x9c, + 0xd5, 0xf3, 0x58, 0xca, 0x07, 0x92, 0x96, 0xd9, 0xeb, 0xa5, 0x25, 0x4e, 0x30, 0x89, 0xca, 0xf7, + 0xa1, 0x4c, 0x6b, 0x4b, 0x2c, 0xd6, 0x5c, 0xe2, 0x2d, 0x25, 0x06, 0x64, 0x96, 0x90, 0xec, 0x19, 0x25, 0x11, 0x68, 0x9e, 0x3a, 0x9a, 0xe2, 0xb2, 0x1f, 0xf9, 0xe7, 0x52, 0x5e, 0x43, 0xe1, 0x9a, 0x24, 0x02, 0xdd, 0x0d, 0xb6, 0x30, 0xe7, 0x06, 0x3b, 0x82, 0x8a, 0xc6, 0x74, 0xe8, 0xf7, 0x8b, 0x46, 0x47, 0x1c, 0x9a, 0xe4, 0xaa, 0xc4, 0xf4, 0xec, 0xde, 0x30, 0x6b, 0x03, 0x1d, 0xb0, 0xb9, - 0x00, 0x79, 0x51, 0xc8, 0xf8, 0x18, 0x96, 0xb4, 0x6a, 0xc9, 0x5c, 0x4d, 0xeb, 0x74, 0x26, 0x2d, - 0x88, 0xfe, 0x8f, 0x33, 0xb0, 0x22, 0x4b, 0x63, 0x8a, 0x98, 0x23, 0xf6, 0xf3, 0xfd, 0xe0, 0x94, - 0xfd, 0x0a, 0xd4, 0x44, 0xed, 0x96, 0xcf, 0x4f, 0x9d, 0x20, 0xe4, 0x2a, 0x46, 0x92, 0xb2, 0x7a, - 0x84, 0x58, 0x17, 0xa4, 0xa6, 0xa4, 0x64, 0x1f, 0x43, 0x05, 0x8b, 0x92, 0x41, 0x2d, 0xdf, 0x5b, - 0x73, 0xbe, 0x20, 0x75, 0x75, 0xf7, 0x86, 0x09, 0x41, 0xf4, 0xb4, 0x59, 0x86, 0x62, 0xe8, 0x3b, - 0xa7, 0xa7, 0xdc, 0x37, 0xd6, 0xa2, 0xae, 0x89, 0xa5, 0xc8, 0x7b, 0x21, 0x9f, 0x08, 0x2d, 0xc9, - 0xf8, 0x8f, 0x19, 0xa8, 0xc8, 0xc5, 0xf5, 0x33, 0x07, 0x46, 0x36, 0xb4, 0x1c, 0x47, 0xb2, 0x9d, - 0xe3, 0x94, 0xc6, 0x77, 0x60, 0x71, 0x2c, 0x34, 0x26, 0xa1, 0xd1, 0x27, 0xa2, 0x22, 0x75, 0x05, - 0x96, 0x0a, 0xcb, 0x03, 0x58, 0x46, 0xfd, 0x25, 0xb0, 0x42, 0x67, 0x64, 0x29, 0xa4, 0xcc, 0x27, - 0x5c, 0x22, 0x54, 0xdf, 0x19, 0xed, 0x4b, 0x84, 0xd8, 0xc6, 0x83, 0xd0, 0x3e, 0xe5, 0x92, 0x37, - 0xe8, 0xc1, 0x68, 0xc2, 0xda, 0x8c, 0x32, 0xaf, 0x0c, 0x91, 0x3f, 0x58, 0x82, 0xf5, 0x39, 0x94, - 0x34, 0x48, 0xa2, 0x68, 0xc0, 0xc8, 0x19, 0x1f, 0x7b, 0x91, 0xaf, 0x2c, 0xa3, 0x45, 0x03, 0xf6, - 0x04, 0x46, 0xf9, 0xca, 0x38, 0xac, 0x2a, 0x86, 0x40, 0x67, 0x57, 0xa4, 0xef, 0x67, 0x51, 0x1b, - 0xfd, 0x20, 0x29, 0xc9, 0x66, 0x9b, 0x53, 0x70, 0x7d, 0x7f, 0x5c, 0x9e, 0xcc, 0xc1, 0x02, 0xf6, - 0x9b, 0xd0, 0x8c, 0xf8, 0x4e, 0x2a, 0x50, 0x9a, 0xf1, 0x22, 0x5a, 0x7a, 0xff, 0x25, 0x2d, 0x25, + 0x00, 0x79, 0x51, 0xc8, 0xf8, 0x08, 0x96, 0xb4, 0x6a, 0xc9, 0x5c, 0x4d, 0xeb, 0x74, 0x26, 0x2d, + 0x88, 0xfe, 0x4f, 0x32, 0xb0, 0x22, 0x4b, 0x63, 0x8a, 0x98, 0x23, 0xf6, 0xf3, 0xfd, 0xe0, 0x94, + 0x7d, 0x17, 0x6a, 0xa2, 0x76, 0xcb, 0xe7, 0xa7, 0x4e, 0x10, 0x72, 0x15, 0x23, 0x49, 0x59, 0x3d, + 0x42, 0xac, 0x0b, 0x52, 0x53, 0x52, 0xb2, 0x8f, 0xa0, 0x82, 0x45, 0xc9, 0xa0, 0x96, 0xef, 0xad, + 0x39, 0x5f, 0x90, 0xba, 0xba, 0x7b, 0xc3, 0x84, 0x20, 0x7a, 0xda, 0x2c, 0x43, 0x31, 0xf4, 0x9d, + 0xd3, 0x53, 0xee, 0x1b, 0x6b, 0x51, 0xd7, 0xc4, 0x52, 0xe4, 0xbd, 0x90, 0x4f, 0x84, 0x96, 0x64, + 0xfc, 0xa7, 0x0c, 0x54, 0xe4, 0xe2, 0xfa, 0xb9, 0x03, 0x23, 0x1b, 0x5a, 0x8e, 0x23, 0xd9, 0xce, + 0x71, 0x4a, 0xe3, 0x3b, 0xb0, 0x38, 0x16, 0x1a, 0x93, 0xd0, 0xe8, 0x13, 0x51, 0x91, 0xba, 0x02, + 0x4b, 0x85, 0xe5, 0x01, 0x2c, 0xa3, 0xfe, 0x12, 0x58, 0xa1, 0x33, 0xb2, 0x14, 0x52, 0xe6, 0x13, + 0x2e, 0x11, 0xaa, 0xef, 0x8c, 0xf6, 0x25, 0x42, 0x6c, 0xe3, 0x41, 0x68, 0x9f, 0x72, 0xc9, 0x1b, + 0xf4, 0x60, 0x34, 0x61, 0x6d, 0x46, 0x99, 0x57, 0x86, 0xc8, 0x1f, 0x2e, 0xc1, 0xfa, 0x1c, 0x4a, + 0x1a, 0x24, 0x51, 0x34, 0x60, 0xe4, 0x8c, 0x8f, 0xbd, 0xc8, 0x57, 0x96, 0xd1, 0xa2, 0x01, 0x7b, + 0x02, 0xa3, 0x7c, 0x65, 0x1c, 0x56, 0x15, 0x43, 0xa0, 0xb3, 0x2b, 0xd2, 0xf7, 0xb3, 0xa8, 0x8d, + 0xbe, 0x9f, 0x94, 0x64, 0xb3, 0xcd, 0x29, 0xb8, 0xbe, 0x3f, 0x2e, 0x4f, 0xe6, 0x60, 0x01, 0xfb, + 0x2d, 0x68, 0x46, 0x7c, 0x27, 0x15, 0x28, 0xcd, 0x78, 0x11, 0x2d, 0x7d, 0xfd, 0x25, 0x2d, 0x25, 0xbc, 0x28, 0xb8, 0x81, 0xae, 0x29, 0x96, 0xa5, 0x0a, 0xa3, 0xb6, 0xce, 0xe1, 0x75, 0xd5, 0x16, 0x2a, 0x44, 0xf3, 0x2d, 0xe6, 0x5f, 0x69, 0x6c, 0xe8, 0x21, 0x4a, 0x34, 0x6b, 0xde, 0x92, 0x15, 0x47, 0x28, 0xbd, 0xdd, 0x33, 0x58, 0xbb, 0xb0, 0x9d, 0x50, 0x8d, 0x51, 0xb3, 0x9d, 0x0a, 0xd8, - 0xde, 0xe3, 0x97, 0xb4, 0xf7, 0x19, 0x15, 0x4e, 0xa8, 0x88, 0x2b, 0x17, 0xf3, 0xc0, 0x60, 0xe3, - 0x4f, 0xb3, 0x50, 0x4f, 0xd6, 0x22, 0x16, 0xb6, 0x14, 0x56, 0x4a, 0xe9, 0x90, 0x4a, 0xbb, 0xf4, + 0xde, 0xe3, 0x97, 0xb4, 0xf7, 0x29, 0x15, 0x4e, 0xa8, 0x88, 0x2b, 0x17, 0xf3, 0xc0, 0x60, 0xe3, + 0xcf, 0xb2, 0x50, 0x4f, 0xd6, 0x22, 0x16, 0xb6, 0x14, 0x56, 0x4a, 0xe9, 0x90, 0x4a, 0xbb, 0xf4, 0xe3, 0x76, 0x49, 0xd9, 0x98, 0xf7, 0x30, 0x67, 0x53, 0x3c, 0xcc, 0xba, 0x63, 0x37, 0xf7, 0xb2, - 0x48, 0x5a, 0xfe, 0x95, 0x22, 0x69, 0x85, 0xb4, 0x48, 0xda, 0xf5, 0xe1, 0x97, 0x85, 0x9f, 0x29, - 0xfc, 0x52, 0x7c, 0x41, 0xf8, 0x25, 0x11, 0x34, 0x2a, 0xcd, 0x04, 0x8d, 0x36, 0xfe, 0x2a, 0x03, - 0x6c, 0x9e, 0x97, 0xd9, 0x53, 0x72, 0xb5, 0xbb, 0x7c, 0x24, 0xe5, 0xdc, 0xd7, 0x5f, 0x6d, 0x3d, + 0x48, 0x5a, 0xfe, 0x95, 0x22, 0x69, 0x85, 0xb4, 0x48, 0xda, 0xf5, 0xe1, 0x97, 0x85, 0x9f, 0x2b, + 0xfc, 0x52, 0x7c, 0x41, 0xf8, 0x25, 0x11, 0x34, 0x2a, 0xcd, 0x04, 0x8d, 0x36, 0xfe, 0x3a, 0x03, + 0x6c, 0x9e, 0x97, 0xd9, 0x53, 0x72, 0xb5, 0xbb, 0x7c, 0x24, 0xe5, 0xdc, 0x37, 0x5e, 0x6d, 0x3d, 0xa8, 0xd7, 0xa7, 0x4a, 0xb3, 0x87, 0xb0, 0xac, 0xe7, 0x28, 0xeb, 0xd6, 0x4e, 0xcd, 0x64, 0x3a, 0x2a, 0xb6, 0x89, 0xb5, 0x20, 0x63, 0xfe, 0xa5, 0x41, 0xc6, 0xc2, 0x4b, 0x83, 0x8c, 0x0b, 0xc9, - 0x20, 0xe3, 0xc6, 0x7f, 0xce, 0xc0, 0x72, 0x0a, 0xcb, 0xfd, 0xe2, 0xc6, 0x2c, 0x38, 0x25, 0x21, - 0x84, 0xb2, 0x92, 0x53, 0x74, 0xf9, 0xb3, 0x07, 0x95, 0x38, 0x6e, 0xa5, 0x72, 0xf8, 0xef, 0xbf, - 0x4c, 0x16, 0xc4, 0x25, 0x4c, 0xbd, 0xf8, 0xc6, 0xef, 0x67, 0xa1, 0xa2, 0x21, 0xc5, 0x2c, 0x12, - 0x83, 0x69, 0xb9, 0x1d, 0xa4, 0x07, 0xa0, 0xad, 0x76, 0x07, 0xa4, 0x33, 0x98, 0xf0, 0xb4, 0x14, - 0xe4, 0xa6, 0x8f, 0x04, 0x0f, 0x60, 0x59, 0x85, 0x41, 0x78, 0x9c, 0xc2, 0x25, 0x77, 0x86, 0x25, - 0x19, 0x0c, 0xe1, 0x51, 0x46, 0x18, 0x7b, 0xa8, 0x34, 0xf8, 0xf8, 0xdd, 0x21, 0x63, 0x92, 0xa7, - 0x75, 0x89, 0xd8, 0x59, 0xbd, 0x44, 0xc1, 0x95, 0x1f, 0xc0, 0xaa, 0x62, 0xe6, 0x64, 0x09, 0x72, - 0xbe, 0x32, 0xc9, 0xca, 0x7a, 0x91, 0xef, 0xc2, 0xed, 0x99, 0x3e, 0xcd, 0x14, 0xa5, 0x5c, 0xc3, - 0x9b, 0x89, 0xde, 0xe9, 0x35, 0x6c, 0xfc, 0x18, 0x6a, 0x09, 0xb1, 0xf6, 0x8b, 0x7b, 0xe5, 0xb3, - 0xf6, 0x31, 0xcd, 0xa8, 0x6e, 0x1f, 0x6f, 0xfc, 0x9f, 0x1c, 0xb0, 0x79, 0xc9, 0xfa, 0xcb, 0xec, - 0xc2, 0x3c, 0x63, 0xe6, 0x52, 0x18, 0xf3, 0xff, 0xd9, 0x6e, 0xff, 0x1e, 0x2c, 0xc9, 0xb3, 0x2c, - 0x5a, 0x2c, 0x8b, 0x16, 0x67, 0x23, 0x42, 0xa8, 0x5e, 0x7c, 0x6b, 0x36, 0xa6, 0x5e, 0x4a, 0xa4, - 0xef, 0x6b, 0xea, 0xce, 0x4c, 0x68, 0xfd, 0x08, 0x16, 0x6c, 0x77, 0x70, 0xe6, 0xf9, 0x68, 0x9a, - 0xd5, 0x1f, 0xff, 0xea, 0x57, 0xde, 0xec, 0x1e, 0xb4, 0xb0, 0x3c, 0xea, 0x58, 0xa6, 0xac, 0xcc, - 0xf8, 0x00, 0x2a, 0x1a, 0x18, 0xe3, 0x3b, 0x9d, 0xfd, 0xcd, 0x83, 0xc6, 0x0d, 0x56, 0x83, 0xb2, - 0xd9, 0xde, 0x3a, 0xf8, 0xb4, 0x6d, 0xb6, 0xb7, 0x1b, 0x19, 0x56, 0x82, 0xfc, 0xde, 0x41, 0xaf, - 0xdf, 0xc8, 0x1a, 0x1b, 0xd0, 0x94, 0x35, 0xce, 0xfb, 0x7a, 0x7f, 0x27, 0x1f, 0xb9, 0x59, 0x10, - 0x29, 0xad, 0xaa, 0x6f, 0x40, 0x55, 0x57, 0x46, 0x24, 0x47, 0xcc, 0x84, 0x53, 0x85, 0x3d, 0xe5, - 0x69, 0xb2, 0x7a, 0x0b, 0x28, 0x48, 0x36, 0x8c, 0x8a, 0x91, 0x86, 0xf9, 0x82, 0xa8, 0x0a, 0x2a, - 0xcf, 0x09, 0x36, 0xfc, 0xff, 0xa0, 0x9e, 0x74, 0x7c, 0x4a, 0x89, 0x94, 0x66, 0x5e, 0x88, 0xd2, - 0x09, 0x4f, 0x28, 0xfb, 0x2e, 0x34, 0x66, 0x1d, 0xa7, 0x32, 0xcb, 0xf9, 0x9a, 0xf2, 0x8b, 0x4e, - 0xd2, 0x97, 0xca, 0x76, 0x61, 0x25, 0x4d, 0x1d, 0x43, 0xfe, 0xb8, 0xde, 0xae, 0x64, 0xf3, 0x2a, - 0x17, 0xfb, 0xb6, 0xf4, 0x8f, 0x17, 0xd2, 0xa2, 0x8c, 0xda, 0x64, 0x3f, 0xa0, 0x7f, 0x9a, 0xa7, - 0xfc, 0x1c, 0x20, 0x86, 0xb1, 0x06, 0x54, 0x0f, 0x0e, 0xdb, 0x5d, 0x6b, 0x6b, 0xb7, 0xd5, 0xed, - 0xb6, 0xf7, 0x1a, 0x37, 0x18, 0x83, 0x3a, 0x86, 0x07, 0xb7, 0x23, 0x58, 0x46, 0xc0, 0x64, 0x9c, - 0x42, 0xc1, 0xb2, 0x6c, 0x05, 0x1a, 0x9d, 0xee, 0x0c, 0x34, 0xc7, 0x9a, 0xb0, 0x72, 0xd8, 0xa6, - 0x88, 0x62, 0xa2, 0xde, 0xbc, 0x50, 0xf1, 0xe5, 0x70, 0x85, 0x8a, 0x4f, 0x67, 0xb2, 0xe4, 0x3a, - 0x50, 0x9a, 0xef, 0xef, 0x66, 0x60, 0x75, 0x06, 0x11, 0x67, 0xda, 0x93, 0xde, 0x9b, 0xd4, 0x78, - 0xab, 0x08, 0x54, 0xab, 0xe9, 0x3d, 0x58, 0x8a, 0x7c, 0x05, 0x33, 0xbb, 0x52, 0x23, 0x42, 0x28, - 0xe2, 0x87, 0xb0, 0xac, 0xb9, 0x1c, 0x66, 0x64, 0x05, 0xd3, 0x50, 0xb2, 0x80, 0xb1, 0x1e, 0x65, - 0x34, 0xcf, 0xf4, 0x7a, 0x48, 0x07, 0xbd, 0x74, 0x44, 0x1c, 0x3e, 0x48, 0xf6, 0x57, 0x3d, 0xb2, - 0x47, 0x33, 0x8c, 0x90, 0xec, 0xad, 0xfe, 0xc2, 0x55, 0xf3, 0x7f, 0xb8, 0x00, 0xec, 0x93, 0x29, - 0xf7, 0xaf, 0x30, 0x93, 0x3e, 0x78, 0x59, 0x6a, 0x99, 0xb2, 0xab, 0xb3, 0xaf, 0x74, 0x5a, 0x26, - 0xed, 0xb4, 0x4a, 0xfe, 0xe5, 0xa7, 0x55, 0x0a, 0x2f, 0x3b, 0xad, 0xf2, 0x26, 0xd4, 0x9c, 0x53, - 0xd7, 0x13, 0xa2, 0x50, 0xe8, 0xad, 0x41, 0x73, 0xe1, 0x6e, 0xee, 0x5e, 0xd5, 0xac, 0x4a, 0xa0, - 0xd0, 0x5a, 0x03, 0xf6, 0x71, 0x4c, 0xc4, 0x87, 0xa7, 0x78, 0xb2, 0x4a, 0x17, 0x82, 0xed, 0xe1, - 0x29, 0x97, 0x6e, 0x04, 0xb4, 0x0b, 0x54, 0x61, 0x01, 0x0f, 0xd8, 0x5b, 0x50, 0x0f, 0xbc, 0xa9, - 0x30, 0x03, 0xd4, 0x34, 0x50, 0x80, 0xa1, 0x4a, 0xd0, 0x43, 0x15, 0x4d, 0x5a, 0x9e, 0x06, 0xdc, - 0x1a, 0x3b, 0x41, 0x20, 0xd4, 0xb3, 0x81, 0xe7, 0x86, 0xbe, 0x37, 0x92, 0x31, 0x83, 0xa5, 0x69, - 0xc0, 0xf7, 0x09, 0xb3, 0x45, 0x08, 0xf6, 0xcd, 0xb8, 0x4b, 0x13, 0xdb, 0xf1, 0x83, 0x26, 0x60, - 0x97, 0xd4, 0x48, 0x51, 0xdb, 0xb6, 0x1d, 0x3f, 0xea, 0x8b, 0x78, 0x08, 0x66, 0x4e, 0xd1, 0x54, - 0x66, 0x4f, 0xd1, 0xfc, 0x30, 0xfd, 0x14, 0x4d, 0x0d, 0xab, 0x7e, 0x24, 0xab, 0x9e, 0x7f, 0xc5, - 0x5f, 0xe9, 0x30, 0xcd, 0xfc, 0xe1, 0xa0, 0xfa, 0x57, 0x39, 0x1c, 0xb4, 0x98, 0x76, 0x38, 0xe8, - 0x03, 0xa8, 0xe0, 0xb1, 0x0d, 0xeb, 0xcc, 0x11, 0x3a, 0x1c, 0xc5, 0x40, 0x1a, 0xfa, 0xb9, 0x8e, - 0x5d, 0xc7, 0x0d, 0x4d, 0xf0, 0xd5, 0xcf, 0x60, 0xfe, 0x9c, 0xce, 0xd2, 0x2f, 0xf1, 0x9c, 0x8e, - 0x3c, 0x5e, 0xf2, 0x00, 0x4a, 0xea, 0x3d, 0x31, 0x06, 0xf9, 0x13, 0xdf, 0x1b, 0x2b, 0xdf, 0xb0, - 0xf8, 0xcd, 0xea, 0x90, 0x0d, 0x3d, 0x59, 0x38, 0x1b, 0x7a, 0xc6, 0x6f, 0x40, 0x45, 0x63, 0x35, - 0xf6, 0x06, 0x79, 0xa1, 0x84, 0x25, 0x25, 0x75, 0x4b, 0x9a, 0xc5, 0xb2, 0x84, 0x76, 0x86, 0x42, - 0xde, 0x0c, 0x1d, 0x9f, 0xe3, 0x89, 0x3a, 0xcb, 0xe7, 0xe7, 0xdc, 0x0f, 0x94, 0xaf, 0xbe, 0x11, - 0x21, 0x4c, 0x82, 0x1b, 0x7f, 0x0d, 0x96, 0x13, 0xef, 0x56, 0x8a, 0x88, 0xb7, 0x60, 0x01, 0xe7, - 0x4d, 0xc5, 0x52, 0x93, 0xe7, 0x65, 0x24, 0x0e, 0x8f, 0x4a, 0x53, 0x98, 0xc1, 0x9a, 0xf8, 0xde, - 0x31, 0x36, 0x92, 0x31, 0x2b, 0x12, 0x76, 0xe8, 0x7b, 0xc7, 0xc6, 0x5f, 0xe4, 0x20, 0xb7, 0xeb, - 0x4d, 0xf4, 0xf4, 0xa1, 0xcc, 0x5c, 0xfa, 0x90, 0x34, 0x0f, 0xad, 0xc8, 0xfc, 0x93, 0x3a, 0x3b, - 0x3a, 0xd8, 0x95, 0x09, 0x78, 0x0f, 0xea, 0x42, 0x4e, 0x84, 0x9e, 0xb0, 0xaf, 0x2f, 0x6c, 0x9f, - 0x14, 0xe2, 0x1c, 0x2d, 0x3e, 0x7b, 0x1c, 0xf6, 0xbd, 0x1d, 0x82, 0xb3, 0x15, 0xc8, 0x45, 0xe6, - 0x0b, 0xa2, 0xc5, 0x23, 0x5b, 0x83, 0x05, 0xcc, 0x23, 0xbd, 0x92, 0xc1, 0x42, 0xf9, 0xc4, 0xbe, - 0x0e, 0xcb, 0xc9, 0x7a, 0x49, 0x14, 0x49, 0xdd, 0x48, 0xaf, 0x18, 0x65, 0xd2, 0x4d, 0x10, 0x72, - 0x84, 0x68, 0x64, 0xce, 0xc1, 0x09, 0xe7, 0x88, 0xd2, 0x84, 0x5e, 0x29, 0x21, 0xf4, 0xee, 0x40, - 0x25, 0x1c, 0x9d, 0x5b, 0x13, 0xfb, 0x6a, 0xe4, 0xd9, 0x43, 0xb9, 0xbe, 0x21, 0x1c, 0x9d, 0x1f, - 0x12, 0x84, 0x3d, 0x04, 0x18, 0x4f, 0x26, 0x72, 0xed, 0xa1, 0xbf, 0x3a, 0x66, 0xe5, 0xfd, 0xc3, - 0x43, 0x62, 0x39, 0xb3, 0x3c, 0x9e, 0x4c, 0xe8, 0x27, 0xdb, 0x86, 0x7a, 0xea, 0xa9, 0xb7, 0xdb, - 0x2a, 0xed, 0xd1, 0x9b, 0x3c, 0x48, 0x59, 0x9c, 0xb5, 0x81, 0x0e, 0xdb, 0xf8, 0x2e, 0xb0, 0x9f, - 0xf3, 0xec, 0x59, 0x1f, 0xca, 0x51, 0xff, 0xf4, 0xa3, 0x5b, 0x98, 0xc8, 0x5c, 0x49, 0x1c, 0xdd, - 0x6a, 0x0d, 0x87, 0xbe, 0x90, 0x8b, 0xb4, 0x61, 0x46, 0x22, 0x1f, 0xb4, 0x1d, 0xb3, 0x45, 0x72, - 0xdf, 0xf8, 0xef, 0x19, 0x28, 0xd0, 0x39, 0xb2, 0xb7, 0x61, 0x91, 0xe8, 0xa3, 0x54, 0x2c, 0x19, - 0x62, 0xa4, 0x7d, 0xb7, 0x2f, 0xb3, 0xb0, 0xc4, 0xb2, 0xd0, 0xce, 0xc0, 0x66, 0xa3, 0x37, 0xaf, - 0x9d, 0x83, 0xbd, 0x03, 0xe5, 0xa8, 0x69, 0x8d, 0x75, 0x4a, 0xaa, 0x65, 0xf6, 0x3a, 0xe4, 0xcf, - 0xbc, 0x89, 0xf2, 0xd3, 0x40, 0x3c, 0x93, 0x26, 0xc2, 0xe3, 0xbe, 0x88, 0x36, 0xa8, 0xf3, 0xd2, - 0xbf, 0x10, 0x35, 0x82, 0x6c, 0x30, 0x3f, 0xc6, 0x85, 0x94, 0x31, 0x1e, 0xc1, 0xa2, 0x90, 0x03, - 0x5a, 0xa8, 0xff, 0xfa, 0x4d, 0xf3, 0x5d, 0xa1, 0xe1, 0x0d, 0x46, 0xd3, 0x21, 0xd7, 0x3d, 0x65, - 0x98, 0x17, 0x24, 0xe1, 0x4a, 0xb3, 0x36, 0xfe, 0x30, 0x43, 0xf2, 0x45, 0xd4, 0xcb, 0xee, 0x41, - 0x5e, 0xec, 0x6f, 0x33, 0x9e, 0xdc, 0x28, 0xa3, 0x5c, 0xd0, 0x99, 0x48, 0x81, 0x07, 0xc7, 0xa7, - 0xe3, 0x64, 0xed, 0x35, 0xb3, 0xe2, 0x4e, 0xc7, 0x91, 0xa3, 0xe9, 0x6b, 0x6a, 0x58, 0x33, 0x4e, - 0x1a, 0x1a, 0x7d, 0xb4, 0x4c, 0x1f, 0x68, 0x09, 0x46, 0xf9, 0xc4, 0x8e, 0xa9, 0xb4, 0xc0, 0xe1, - 0x29, 0xd7, 0x12, 0x8b, 0xfe, 0x38, 0x0b, 0xb5, 0x44, 0x8f, 0x30, 0xc3, 0x4a, 0x6c, 0x00, 0x14, - 0x46, 0x90, 0xef, 0x1b, 0x04, 0x48, 0x2a, 0xea, 0xda, 0x3c, 0x65, 0x13, 0xf3, 0x14, 0x25, 0x35, - 0xe4, 0xf4, 0xa4, 0x86, 0x47, 0x50, 0x8e, 0xcf, 0x3e, 0x27, 0xbb, 0x24, 0xda, 0x53, 0x79, 0xf5, - 0x31, 0x51, 0x9c, 0x06, 0x51, 0xd0, 0xd3, 0x20, 0xbe, 0xa3, 0x45, 0xcd, 0x17, 0xb0, 0x1a, 0x23, - 0x6d, 0x46, 0x7f, 0x29, 0x31, 0x73, 0xe3, 0x63, 0xa8, 0x68, 0x9d, 0xd7, 0xa3, 0xe3, 0x99, 0x44, - 0x74, 0x3c, 0x3a, 0x01, 0x93, 0x8d, 0x4f, 0xc0, 0x18, 0xbf, 0x95, 0x85, 0x9a, 0x58, 0x5f, 0x8e, - 0x7b, 0x7a, 0xe8, 0x8d, 0x9c, 0x01, 0x86, 0x15, 0xa2, 0x15, 0x26, 0x15, 0x2d, 0xb5, 0xce, 0xe4, - 0x12, 0x23, 0x3d, 0x4b, 0x3f, 0xe8, 0x47, 0x42, 0x3a, 0x3a, 0xe8, 0x67, 0x40, 0x4d, 0x08, 0xc6, - 0x63, 0x3b, 0xe0, 0xda, 0xc9, 0x6c, 0xb3, 0x72, 0xc2, 0xf9, 0xa6, 0x1d, 0x90, 0x84, 0xfc, 0x3a, - 0x2c, 0x0b, 0x1a, 0x3c, 0xe3, 0x34, 0x76, 0x46, 0x23, 0x87, 0x28, 0xc9, 0xd1, 0xd4, 0x38, 0xe1, - 0xdc, 0xb4, 0x43, 0xbe, 0x2f, 0x10, 0xf2, 0x20, 0x77, 0x69, 0xe8, 0x04, 0xf6, 0x71, 0x9c, 0x07, - 0x17, 0x3d, 0x63, 0x30, 0xd0, 0xbe, 0xd4, 0x82, 0x81, 0xe4, 0x80, 0xa8, 0x8c, 0xed, 0xcb, 0x28, - 0x18, 0x38, 0xc3, 0x49, 0xc5, 0x59, 0x4e, 0x32, 0xfe, 0x7d, 0x16, 0x2a, 0x1a, 0x5b, 0xbe, 0xca, - 0xee, 0x7a, 0x7b, 0x2e, 0x0c, 0x54, 0xd6, 0x23, 0x3e, 0x6f, 0x26, 0x9b, 0xc4, 0x9c, 0x01, 0x3a, - 0x32, 0xae, 0x31, 0xf0, 0x2d, 0x28, 0x8b, 0x55, 0xf7, 0x01, 0x3a, 0x4c, 0xe5, 0x85, 0x07, 0x08, - 0x38, 0x9c, 0x1e, 0x2b, 0xe4, 0x63, 0x44, 0x16, 0x62, 0xe4, 0x63, 0x81, 0x7c, 0x51, 0xf2, 0xeb, - 0xb7, 0xa0, 0x2a, 0x6b, 0xc5, 0x77, 0x8a, 0xc3, 0x8d, 0x57, 0x7d, 0xe2, 0x7d, 0x9b, 0x15, 0x6a, - 0x8e, 0x5e, 0xbe, 0x2c, 0xf8, 0x58, 0x15, 0x2c, 0xbd, 0xac, 0xe0, 0x63, 0x7a, 0x30, 0x76, 0xa2, - 0x7c, 0x62, 0xcc, 0x57, 0x51, 0x72, 0xec, 0x21, 0x2c, 0x2b, 0x71, 0x35, 0x75, 0x6d, 0xd7, 0xf5, - 0xa6, 0xee, 0x80, 0xab, 0xa3, 0x31, 0x4c, 0xa2, 0x8e, 0x62, 0x8c, 0x31, 0x8c, 0xce, 0x4e, 0x52, - 0xde, 0xcb, 0x7d, 0x28, 0x90, 0x5e, 0x4e, 0xca, 0x47, 0xba, 0xe0, 0x22, 0x12, 0x76, 0x0f, 0x0a, - 0xa4, 0x9e, 0x67, 0xaf, 0x15, 0x36, 0x44, 0x60, 0xb4, 0x80, 0x89, 0x82, 0xfb, 0x3c, 0xf4, 0x9d, - 0x41, 0x10, 0x9f, 0xba, 0x29, 0x08, 0xfb, 0x93, 0xda, 0x8a, 0xd3, 0xdc, 0x63, 0x4a, 0xb4, 0x51, - 0x89, 0xc6, 0xf8, 0x6f, 0x19, 0x58, 0x4e, 0xd4, 0x21, 0xd5, 0xa5, 0x11, 0xac, 0x1d, 0xf3, 0xf0, - 0x82, 0x73, 0xd7, 0x15, 0xca, 0xd0, 0x80, 0xbb, 0xa1, 0x6f, 0x8f, 0xc4, 0x4b, 0xa2, 0x11, 0x3c, - 0x99, 0xab, 0x35, 0xf6, 0x81, 0x6c, 0xc6, 0x05, 0xb7, 0xa2, 0x72, 0x24, 0x3b, 0x56, 0x8f, 0xd3, - 0x70, 0x1b, 0x3f, 0x80, 0x8d, 0xeb, 0x0b, 0xa5, 0x9c, 0xad, 0x7b, 0x27, 0x29, 0x55, 0x22, 0x75, - 0x77, 0xe4, 0xd9, 0x21, 0x1e, 0xf8, 0xd5, 0x05, 0xcb, 0x3e, 0x40, 0x8c, 0x88, 0x77, 0xfe, 0x0c, - 0xaa, 0x76, 0xf4, 0x20, 0xf6, 0x23, 0xd7, 0xf3, 0xc7, 0xf6, 0xc8, 0xf9, 0x11, 0x1f, 0x5a, 0x71, - 0xdd, 0x19, 0x73, 0x31, 0x86, 0x63, 0x05, 0xc6, 0x03, 0x58, 0x44, 0xbd, 0x5e, 0xdb, 0xe6, 0x5e, - 0xa4, 0x0a, 0x1a, 0x2b, 0xc0, 0xba, 0x24, 0xb9, 0xf4, 0x24, 0xb8, 0xff, 0x92, 0x83, 0x8a, 0x06, - 0x16, 0x7b, 0x11, 0xa6, 0x4d, 0x59, 0x43, 0xc7, 0x1e, 0x73, 0x15, 0x10, 0xac, 0x99, 0x35, 0x84, - 0x6e, 0x4b, 0xa0, 0xd8, 0x89, 0xed, 0xf3, 0x53, 0xcb, 0x9b, 0x86, 0xd6, 0x90, 0x9f, 0xfa, 0x5c, - 0xf5, 0xb2, 0x6a, 0x9f, 0x9f, 0x1e, 0x4c, 0xc3, 0x6d, 0x84, 0x09, 0x2a, 0x21, 0x49, 0x34, 0x2a, - 0x99, 0xe9, 0x33, 0xb6, 0x2f, 0x63, 0x2a, 0x99, 0x6e, 0x46, 0x7c, 0x99, 0x8f, 0xd2, 0xcd, 0xc8, - 0x56, 0x9c, 0xdd, 0x3e, 0x0b, 0xf3, 0xdb, 0xe7, 0x37, 0x61, 0x8d, 0xb6, 0x4f, 0x29, 0x98, 0xad, - 0x99, 0x75, 0xbc, 0x82, 0x58, 0x39, 0x48, 0x4d, 0xe9, 0x6d, 0x88, 0x11, 0x28, 0xa1, 0x14, 0x38, - 0x3f, 0x22, 0x31, 0x96, 0x31, 0xc5, 0xc8, 0x64, 0xe5, 0x3d, 0xe7, 0x47, 0x5c, 0x50, 0x62, 0x3a, - 0x83, 0x4e, 0x29, 0x13, 0xdb, 0xc7, 0x8e, 0x3b, 0x4b, 0x69, 0x5f, 0x26, 0x29, 0xcb, 0x92, 0xd2, - 0xbe, 0xd4, 0x29, 0x9f, 0xc0, 0xfa, 0x98, 0x0f, 0x1d, 0x3b, 0x59, 0xad, 0x15, 0xab, 0x6d, 0x2b, - 0x84, 0xd6, 0xca, 0xf4, 0xc8, 0x6c, 0x17, 0xb3, 0xf1, 0x23, 0x6f, 0x7c, 0xec, 0x90, 0xc6, 0x42, - 0x09, 0x16, 0x79, 0xb3, 0xee, 0x4e, 0xc7, 0xdf, 0x47, 0xb0, 0x28, 0x12, 0x18, 0x35, 0xa8, 0xf4, - 0x42, 0x6f, 0xa2, 0x5e, 0x73, 0x1d, 0xaa, 0xf4, 0x28, 0x4f, 0x9b, 0xdd, 0x82, 0x9b, 0x28, 0x10, - 0xfa, 0xde, 0xc4, 0x1b, 0x79, 0xa7, 0x57, 0x09, 0x2f, 0xde, 0x7f, 0xca, 0xc0, 0x72, 0x02, 0x2b, - 0x85, 0xeb, 0x37, 0x49, 0x9a, 0x45, 0x47, 0x86, 0x68, 0x05, 0x2e, 0x69, 0x2b, 0x90, 0x08, 0x49, - 0x94, 0xa9, 0x63, 0x44, 0xad, 0xf8, 0xa8, 0xbb, 0x2a, 0x48, 0x02, 0xa5, 0x39, 0x2f, 0x50, 0x64, - 0x79, 0x75, 0x08, 0x5e, 0x55, 0xf1, 0xab, 0xf2, 0xf0, 0xc1, 0x50, 0x0e, 0x39, 0x97, 0x4c, 0xaf, - 0xd6, 0x3d, 0x7e, 0xaa, 0x07, 0xb1, 0x1b, 0x30, 0x30, 0xfe, 0x45, 0x06, 0x20, 0xee, 0x1d, 0x26, - 0x78, 0x47, 0x5a, 0x0b, 0xdd, 0x22, 0xa5, 0x69, 0x28, 0x6f, 0x40, 0x35, 0xca, 0xf3, 0x8c, 0xf5, - 0xa0, 0x8a, 0x82, 0x3d, 0xc3, 0x55, 0xbf, 0x78, 0x3a, 0xf2, 0x8e, 0x51, 0x5f, 0x95, 0x5a, 0x0b, - 0x9d, 0xb9, 0xab, 0x13, 0x58, 0xe9, 0x22, 0xb1, 0xd6, 0x94, 0x4f, 0x4d, 0x05, 0xd5, 0x75, 0x20, - 0xe3, 0xb7, 0xb3, 0x51, 0xc2, 0x5b, 0x3c, 0x13, 0x2f, 0x36, 0xee, 0x7e, 0x96, 0xbc, 0x89, 0x17, - 0x85, 0x02, 0x3f, 0x86, 0xba, 0x4f, 0x5b, 0x92, 0xda, 0xaf, 0xf2, 0x2f, 0xd8, 0xaf, 0x6a, 0x7e, - 0x42, 0xcf, 0x79, 0x17, 0x1a, 0xf6, 0xf0, 0x9c, 0xfb, 0xa1, 0x83, 0xbe, 0x7a, 0xd4, 0x8e, 0x65, - 0x8a, 0x99, 0x06, 0x47, 0x35, 0xf4, 0x1d, 0x58, 0x94, 0x27, 0x20, 0x23, 0x4a, 0x79, 0xa7, 0x4a, - 0x0c, 0x16, 0x84, 0xc6, 0xbf, 0x52, 0x19, 0x76, 0xc9, 0xb7, 0xfb, 0xe2, 0x59, 0xd1, 0x47, 0x98, - 0x9d, 0x0f, 0x76, 0x4a, 0x46, 0x92, 0x21, 0x00, 0x29, 0x8f, 0x08, 0x28, 0x03, 0x00, 0xc9, 0x69, - 0xcd, 0xbf, 0xca, 0xb4, 0x1a, 0x7f, 0x9a, 0x81, 0xe2, 0xae, 0x37, 0xd9, 0x75, 0x28, 0xc5, 0x19, - 0x97, 0x49, 0x14, 0xa1, 0x5a, 0x10, 0x8f, 0x9d, 0xe1, 0x8b, 0x0f, 0xfa, 0xa4, 0x2a, 0x79, 0xb5, - 0xa4, 0x92, 0xf7, 0x1d, 0xb8, 0x85, 0x01, 0x40, 0xdf, 0x9b, 0x78, 0xbe, 0x58, 0xaa, 0xf6, 0x88, - 0x94, 0x3d, 0xcf, 0x0d, 0xcf, 0x94, 0xec, 0xbc, 0x79, 0xc2, 0xf9, 0xa1, 0x46, 0xb1, 0x1f, 0x11, - 0xe0, 0x51, 0xba, 0x51, 0x78, 0x6e, 0x91, 0x7d, 0x2e, 0xb5, 0x51, 0x92, 0xa8, 0x8b, 0x02, 0xd1, - 0x46, 0x38, 0xea, 0xa3, 0xc6, 0xb7, 0xa1, 0x1c, 0xb9, 0x7a, 0xd8, 0x7b, 0x50, 0x3e, 0xf3, 0x26, - 0xd2, 0x1f, 0x94, 0x49, 0x1c, 0x86, 0x92, 0xa3, 0x36, 0x4b, 0x67, 0xf4, 0x23, 0x30, 0xfe, 0xa2, - 0x08, 0xc5, 0x8e, 0x7b, 0xee, 0x39, 0x03, 0xcc, 0xd1, 0x1b, 0xf3, 0xb1, 0xa7, 0x8e, 0x61, 0x8b, - 0xdf, 0x98, 0x87, 0x13, 0xdf, 0x8c, 0x92, 0x93, 0x79, 0x38, 0xd1, 0x9d, 0x28, 0xab, 0xb0, 0xe0, - 0xeb, 0x57, 0x9b, 0x14, 0x7c, 0xcc, 0x1a, 0x8e, 0xf6, 0xcb, 0x82, 0x76, 0x8c, 0x5d, 0xd4, 0x45, - 0x57, 0x6e, 0xe0, 0x94, 0xd1, 0xb1, 0xb8, 0x32, 0x42, 0x70, 0xc2, 0x5e, 0x83, 0xa2, 0x3c, 0x7b, - 0x44, 0x27, 0x39, 0x28, 0xcd, 0x57, 0x82, 0x90, 0x1b, 0x7c, 0x4e, 0x01, 0xdc, 0x48, 0x8d, 0xcd, - 0x99, 0x55, 0x05, 0xdc, 0x16, 0xbc, 0x76, 0x07, 0x2a, 0x44, 0x4f, 0x24, 0x25, 0x99, 0x55, 0x87, - 0x20, 0x24, 0x48, 0xb9, 0x21, 0xa8, 0x9c, 0x7a, 0x43, 0x10, 0x26, 0x61, 0x46, 0x52, 0x96, 0x86, - 0x08, 0x74, 0x2f, 0x8c, 0x06, 0x57, 0xd7, 0x63, 0x49, 0x8f, 0x0a, 0x9d, 0x12, 0x55, 0x1e, 0x95, - 0x37, 0xa1, 0x76, 0x62, 0x8f, 0x46, 0xc7, 0xf6, 0xe0, 0x39, 0x39, 0x02, 0xaa, 0xe4, 0xfb, 0x54, - 0x40, 0xf4, 0x04, 0xdc, 0x81, 0x8a, 0xf6, 0x96, 0x31, 0x65, 0x2e, 0x6f, 0x42, 0xfc, 0x7e, 0x67, - 0xfd, 0x7b, 0xf5, 0x57, 0xf0, 0xef, 0x69, 0xa9, 0x83, 0x8b, 0xc9, 0xd4, 0xc1, 0x5b, 0x28, 0x4d, - 0x65, 0x7a, 0x59, 0x83, 0x2e, 0x21, 0xb1, 0x87, 0x43, 0x4c, 0x2f, 0xa3, 0x1b, 0xff, 0x70, 0xf2, - 0x08, 0xbf, 0x44, 0x96, 0x04, 0xc1, 0x88, 0xe4, 0x36, 0x39, 0xa9, 0x27, 0xb6, 0x33, 0xc4, 0x54, - 0x6d, 0xf2, 0x1d, 0x14, 0xed, 0x71, 0x78, 0x68, 0x3b, 0x43, 0x76, 0x17, 0xaa, 0x0a, 0x8d, 0xbb, - 0xe3, 0x32, 0xcd, 0xbf, 0x44, 0x8b, 0x3d, 0xd1, 0x80, 0x5a, 0x44, 0x31, 0x8e, 0x8f, 0x7a, 0x56, - 0x24, 0x09, 0xf2, 0xc1, 0x07, 0x98, 0x91, 0x13, 0x72, 0x3c, 0xd0, 0x59, 0x7f, 0x7c, 0x4b, 0x8e, - 0x55, 0x72, 0xa9, 0xfa, 0x4f, 0xa1, 0x31, 0xa2, 0x14, 0xda, 0x2f, 0x45, 0xe8, 0xd6, 0x12, 0xda, - 0xaf, 0x24, 0xc5, 0x08, 0x1d, 0x11, 0xb0, 0x6f, 0x6b, 0xd6, 0x6b, 0x13, 0x89, 0x5f, 0x9b, 0xa9, - 0xff, 0xba, 0x93, 0x2a, 0xb7, 0x01, 0x9c, 0x40, 0xec, 0x32, 0x01, 0x77, 0x87, 0x78, 0x36, 0xb3, - 0x64, 0x96, 0x9d, 0xe0, 0x19, 0x01, 0x7e, 0xb1, 0x66, 0x6d, 0x0b, 0xaa, 0xfa, 0x30, 0x59, 0x09, - 0xf2, 0x07, 0x87, 0xed, 0x6e, 0xe3, 0x06, 0xab, 0x40, 0xb1, 0xd7, 0xee, 0xf7, 0xf7, 0x30, 0xce, - 0x57, 0x85, 0x52, 0x74, 0x30, 0x2c, 0x2b, 0x9e, 0x5a, 0x5b, 0x5b, 0xed, 0xc3, 0x7e, 0x7b, 0xbb, - 0x91, 0xfb, 0x5e, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0xbf, 0xcc, 0x41, 0x45, 0x9b, 0x85, 0x17, 0x0b, - 0xe3, 0xdb, 0x00, 0x68, 0x47, 0xc6, 0xd9, 0x87, 0x79, 0xb3, 0x2c, 0x20, 0xf4, 0xf2, 0xf5, 0x08, - 0x45, 0x8e, 0x6e, 0xb7, 0x51, 0x11, 0x8a, 0x37, 0xa1, 0x46, 0x17, 0xc5, 0xe8, 0xd1, 0xda, 0x82, - 0x59, 0x25, 0xa0, 0x14, 0xd5, 0x78, 0xb2, 0x14, 0x89, 0xf0, 0xcc, 0x91, 0xbc, 0x36, 0x82, 0x40, - 0x78, 0xea, 0x08, 0x8f, 0x8c, 0x05, 0xde, 0xe8, 0x9c, 0x13, 0x05, 0x69, 0x84, 0x15, 0x09, 0xeb, - 0xcb, 0x33, 0xb2, 0x52, 0x1e, 0x6a, 0x47, 0x1b, 0x0b, 0x66, 0x95, 0x80, 0xb2, 0xa1, 0xaf, 0x2b, - 0x06, 0x2a, 0x21, 0x03, 0xad, 0xcf, 0x73, 0x43, 0x82, 0x79, 0xf6, 0xe6, 0x9c, 0x88, 0x65, 0x64, - 0x8c, 0xaf, 0xcd, 0x97, 0x7b, 0xb9, 0x33, 0x91, 0xbd, 0x07, 0x6c, 0x3c, 0x99, 0x58, 0x29, 0xee, - 0xbd, 0xbc, 0xb9, 0x38, 0x9e, 0x4c, 0xfa, 0x9a, 0xf7, 0xeb, 0x17, 0xe0, 0x79, 0xfc, 0x02, 0x58, - 0x4b, 0x2c, 0x60, 0xec, 0x62, 0x64, 0x88, 0xc5, 0x62, 0x39, 0xa3, 0x8b, 0xe5, 0x14, 0xe9, 0x97, - 0x4d, 0x95, 0x7e, 0x2f, 0x92, 0x13, 0xc6, 0x0e, 0x54, 0x0e, 0xb5, 0x6b, 0xa8, 0xee, 0x8a, 0x1d, - 0x42, 0x5d, 0x40, 0x45, 0x7b, 0x07, 0x79, 0x14, 0x7d, 0x79, 0xef, 0x94, 0xd6, 0x9b, 0xac, 0xd6, - 0x1b, 0xe3, 0x9f, 0x67, 0xe8, 0x8a, 0x8f, 0xa8, 0xf3, 0xf1, 0xcd, 0x57, 0x2a, 0xf8, 0x16, 0x9f, - 0x40, 0xae, 0xa8, 0xa0, 0x9b, 0x3c, 0x3c, 0x8c, 0x5d, 0xb3, 0xbc, 0x93, 0x93, 0x80, 0xab, 0x0c, - 0x8f, 0x0a, 0xc2, 0x0e, 0x10, 0xa4, 0x94, 0x6f, 0xa1, 0xe1, 0x3b, 0x54, 0x7f, 0x20, 0xd3, 0x3a, - 0x84, 0xf2, 0xbd, 0x6f, 0x5f, 0xca, 0x56, 0x03, 0xa1, 0x82, 0xc8, 0xe8, 0x80, 0x3a, 0x41, 0x18, - 0x3d, 0x1b, 0xff, 0x44, 0x1e, 0x92, 0x9e, 0x9d, 0xdf, 0xfb, 0x50, 0x8a, 0x6a, 0x4d, 0xee, 0xb0, - 0x8a, 0x32, 0xc2, 0x8b, 0x7d, 0x1c, 0x5d, 0x21, 0x89, 0x1e, 0xd3, 0xe2, 0xc2, 0x08, 0x4f, 0x47, - 0xeb, 0xf5, 0xfb, 0xc0, 0x4e, 0x1c, 0x7f, 0x96, 0x98, 0x16, 0x5b, 0x03, 0x31, 0x1a, 0xb5, 0x71, - 0x04, 0xcb, 0x4a, 0x4a, 0x68, 0x16, 0x41, 0xf2, 0xe5, 0x65, 0x5e, 0x22, 0xe4, 0xb3, 0x73, 0x42, - 0xde, 0xf8, 0x49, 0x1e, 0x8a, 0xea, 0x4a, 0xb7, 0xb4, 0x6b, 0xc8, 0xca, 0xc9, 0x6b, 0xc8, 0x9a, - 0x89, 0x2b, 0x6b, 0xf0, 0xd5, 0xcb, 0xfd, 0xfe, 0x9d, 0xd9, 0x2d, 0x5b, 0x8b, 0x54, 0x24, 0xb6, - 0xed, 0x35, 0xc8, 0x4f, 0xec, 0xf0, 0x0c, 0xbd, 0x92, 0xc4, 0x3c, 0xf8, 0xac, 0x22, 0x18, 0x85, - 0x64, 0x04, 0x23, 0xed, 0xca, 0x36, 0x52, 0x49, 0xe7, 0xae, 0x6c, 0xbb, 0x05, 0xa4, 0x5f, 0x68, - 0x09, 0x6a, 0x25, 0x04, 0x88, 0xbd, 0x28, 0xa9, 0x8e, 0x94, 0x66, 0xd5, 0x91, 0x57, 0x56, 0x15, - 0xbe, 0x09, 0x0b, 0x74, 0xdd, 0x81, 0x3c, 0x29, 0xa9, 0x36, 0x14, 0x39, 0x87, 0xea, 0x3f, 0xa5, - 0xae, 0x9b, 0x92, 0x56, 0xbf, 0xff, 0xa8, 0x92, 0xb8, 0xff, 0x48, 0x8f, 0xac, 0x54, 0x93, 0x91, - 0x95, 0x7b, 0xd0, 0x88, 0x26, 0x14, 0xfd, 0x94, 0x6e, 0x20, 0xcf, 0x61, 0xd5, 0x15, 0x5c, 0x48, - 0xc9, 0x6e, 0x10, 0x6f, 0x88, 0xf5, 0xc4, 0x86, 0x28, 0x64, 0x58, 0x2b, 0x0c, 0xf9, 0x78, 0x12, - 0xca, 0x0d, 0x11, 0x4f, 0x6a, 0xe8, 0x1d, 0x4c, 0x9e, 0x21, 0xae, 0x41, 0xb9, 0xd3, 0xb5, 0x76, - 0xf6, 0x3a, 0x4f, 0x77, 0xfb, 0x8d, 0x8c, 0x78, 0xec, 0x1d, 0x6d, 0x6d, 0xb5, 0xdb, 0xdb, 0xb8, - 0xe3, 0x00, 0x2c, 0xec, 0xb4, 0x3a, 0x62, 0xf7, 0xc9, 0x19, 0xbf, 0x9b, 0x85, 0x8a, 0x56, 0x3d, - 0x7b, 0x12, 0xcd, 0x0a, 0x5d, 0x91, 0x73, 0x7b, 0xbe, 0x0b, 0x0f, 0x94, 0x28, 0xd6, 0xa6, 0x25, - 0xba, 0xa0, 0x2e, 0x7b, 0xed, 0x05, 0x75, 0xec, 0x6d, 0x58, 0xb4, 0xa9, 0x86, 0x68, 0x16, 0xa4, - 0x0f, 0x5e, 0x82, 0xe5, 0x24, 0x60, 0x5a, 0x66, 0xbc, 0x9f, 0x08, 0xba, 0xbc, 0xca, 0x84, 0x8c, - 0xb6, 0x14, 0x9c, 0xac, 0xe2, 0x89, 0xed, 0x8c, 0xa6, 0x3e, 0x97, 0x31, 0xf3, 0x68, 0x67, 0x26, - 0xa8, 0xa9, 0xd0, 0xc6, 0x87, 0x00, 0x71, 0x9f, 0x93, 0x93, 0x73, 0x23, 0x39, 0x39, 0x19, 0x6d, - 0x72, 0xb2, 0xc6, 0x36, 0x89, 0x11, 0x39, 0xd1, 0x91, 0xd3, 0xed, 0xeb, 0xa0, 0xdc, 0x80, 0x16, - 0x26, 0x47, 0x4f, 0x46, 0x3c, 0x54, 0xa7, 0xad, 0x97, 0x24, 0xa6, 0x13, 0x21, 0xd4, 0xe5, 0x07, - 0x71, 0x2d, 0xb1, 0x34, 0x92, 0x2c, 0x39, 0x2b, 0x8d, 0x24, 0xa9, 0x19, 0xe1, 0x8d, 0x0d, 0x68, - 0x6e, 0x73, 0x51, 0x5b, 0x6b, 0x34, 0x9a, 0xe9, 0x8e, 0x71, 0x0b, 0x6e, 0xa6, 0xe0, 0xa4, 0x13, - 0xe2, 0x13, 0x58, 0x6d, 0xd1, 0xc1, 0xea, 0x5f, 0xd4, 0x09, 0x2a, 0xa3, 0x09, 0x6b, 0xb3, 0x55, - 0xca, 0xc6, 0x76, 0x60, 0x69, 0x9b, 0x1f, 0x4f, 0x4f, 0xf7, 0xf8, 0x79, 0xdc, 0x10, 0x83, 0x7c, - 0x70, 0xe6, 0x5d, 0xc8, 0xf9, 0xc1, 0xdf, 0x98, 0x63, 0x28, 0x68, 0xac, 0x60, 0xc2, 0x07, 0xca, - 0x0d, 0x8d, 0x90, 0xde, 0x84, 0x0f, 0x8c, 0x27, 0xc0, 0xf4, 0x7a, 0xe4, 0x7c, 0x09, 0x2b, 0x61, - 0x7a, 0x6c, 0x05, 0x57, 0x41, 0xc8, 0xc7, 0xea, 0x06, 0x26, 0x08, 0xa6, 0xc7, 0x3d, 0x82, 0x18, - 0xef, 0x40, 0xf5, 0xd0, 0xbe, 0x32, 0xf9, 0x17, 0xf2, 0x6c, 0xd0, 0x3a, 0x14, 0x27, 0xf6, 0x95, - 0x10, 0x03, 0x51, 0x44, 0x0a, 0xd1, 0xc6, 0x1f, 0xe5, 0x61, 0x81, 0x28, 0xd9, 0x5d, 0xba, 0x24, - 0xd5, 0x71, 0x71, 0x19, 0x2a, 0x41, 0xa9, 0x81, 0xe6, 0x64, 0x69, 0x76, 0x5e, 0x96, 0x4a, 0x07, - 0x9a, 0xba, 0x1c, 0x46, 0xc5, 0x0e, 0xdc, 0xe9, 0x58, 0xdd, 0x08, 0x93, 0x3c, 0x5d, 0x9c, 0x8f, - 0x2f, 0xc1, 0xa5, 0xa3, 0x97, 0xc9, 0xe8, 0x6e, 0x6c, 0x8b, 0x50, 0xef, 0xd4, 0x16, 0x21, 0xc5, - 0xa5, 0x0e, 0x4a, 0x35, 0x78, 0x8a, 0xea, 0xd4, 0x59, 0xd2, 0xe0, 0x99, 0x33, 0x6c, 0x4a, 0x2f, - 0x37, 0x6c, 0xc8, 0xb3, 0xf6, 0x02, 0xc3, 0x06, 0x5e, 0xc1, 0xb0, 0x79, 0x85, 0xc8, 0xea, 0x4d, - 0x28, 0xe1, 0xbe, 0xaf, 0x49, 0x4f, 0xb1, 0xdf, 0x0b, 0xe9, 0xf9, 0x2d, 0x4d, 0xf5, 0xa7, 0xb4, - 0x8e, 0x5b, 0xf1, 0x32, 0x31, 0xf9, 0x17, 0xbf, 0x9c, 0x88, 0xd5, 0xe7, 0x50, 0x94, 0x50, 0xc1, - 0xd0, 0xae, 0x3d, 0x56, 0xf7, 0x6b, 0xe1, 0x6f, 0x31, 0x6d, 0x78, 0x29, 0xd0, 0x17, 0x53, 0xc7, - 0xe7, 0x43, 0x75, 0x71, 0x8a, 0x83, 0x6b, 0x54, 0x40, 0xc4, 0x00, 0x85, 0x19, 0xe2, 0x7a, 0x17, - 0xae, 0xbc, 0x36, 0xa1, 0xe8, 0x04, 0xcf, 0xc4, 0xa3, 0xc1, 0xa0, 0x81, 0x37, 0xec, 0x4d, 0x3c, - 0x5f, 0x6d, 0x4e, 0xc6, 0x4f, 0x32, 0xd0, 0x90, 0xab, 0x2b, 0xc2, 0xe9, 0x56, 0x40, 0xe1, 0xba, - 0x2c, 0x84, 0x17, 0x5f, 0x83, 0x62, 0x40, 0x0d, 0x9d, 0x1f, 0xd1, 0x4e, 0x45, 0xce, 0x9b, 0x8a, - 0x00, 0xee, 0xc8, 0xdd, 0xea, 0x75, 0xa8, 0xa8, 0x0c, 0xe8, 0xb1, 0x33, 0x52, 0xf7, 0x5d, 0x53, - 0x0a, 0xf4, 0xbe, 0x33, 0x52, 0x1b, 0x9d, 0x6f, 0xcb, 0x53, 0x90, 0x19, 0xdc, 0xe8, 0x4c, 0x3b, - 0xe4, 0xc6, 0xbf, 0xc9, 0xc0, 0x92, 0x36, 0x14, 0xb9, 0x6e, 0x3f, 0x82, 0x6a, 0x74, 0xb5, 0x25, - 0x8f, 0x34, 0xaf, 0xf5, 0xa4, 0xa0, 0x89, 0x8b, 0x55, 0x06, 0x11, 0x24, 0x10, 0x9d, 0x19, 0xda, - 0x57, 0x94, 0xa6, 0x3b, 0x1d, 0x2b, 0xe3, 0x66, 0x68, 0x5f, 0xed, 0x70, 0xde, 0x9b, 0x8e, 0x85, - 0xe9, 0x7a, 0xc1, 0xf9, 0xf3, 0x88, 0x80, 0x74, 0x2e, 0x10, 0x30, 0x49, 0x61, 0x40, 0x6d, 0xec, - 0xb9, 0xe1, 0x59, 0x44, 0x22, 0xb5, 0x4e, 0x04, 0x12, 0x8d, 0xf1, 0xe7, 0x59, 0x58, 0x26, 0x17, - 0x9b, 0x74, 0x6d, 0x4a, 0xd1, 0xd5, 0x84, 0x05, 0xf2, 0x36, 0x92, 0xf0, 0xda, 0xbd, 0x61, 0xca, - 0x67, 0xf6, 0xcd, 0x57, 0x74, 0x0b, 0xaa, 0x83, 0x96, 0xd7, 0x4c, 0x7f, 0x6e, 0x7e, 0xfa, 0xaf, - 0x9f, 0xde, 0xb4, 0x30, 0x67, 0x21, 0x2d, 0xcc, 0xf9, 0x2a, 0xc1, 0xc5, 0xb9, 0xd3, 0x88, 0x45, - 0x49, 0xa3, 0x9d, 0x46, 0x7c, 0x02, 0xeb, 0x09, 0x1a, 0x94, 0xd6, 0xce, 0x89, 0xc3, 0xd5, 0xad, - 0x14, 0x2b, 0x1a, 0x75, 0x4f, 0xe1, 0x36, 0x8b, 0x50, 0x08, 0x06, 0xde, 0x84, 0x1b, 0x6b, 0xb0, - 0x92, 0x9c, 0x55, 0xb9, 0x4d, 0xfc, 0x5e, 0x06, 0x9a, 0x32, 0x29, 0xc5, 0x71, 0x4f, 0x77, 0x9d, - 0x20, 0xf4, 0xfc, 0xe8, 0x0a, 0xc8, 0xdb, 0x00, 0x41, 0x68, 0xfb, 0xd2, 0xda, 0x94, 0xf7, 0x30, - 0x20, 0x04, 0x2d, 0xc9, 0x9b, 0x50, 0xe2, 0xee, 0x90, 0x90, 0xc4, 0x0d, 0x45, 0xee, 0x0e, 0x95, - 0x1d, 0x3a, 0xa7, 0x7f, 0xd7, 0x92, 0xe6, 0x85, 0x3c, 0x16, 0x2d, 0x66, 0x87, 0x9f, 0xe3, 0xc6, - 0x9b, 0x8f, 0x8e, 0x45, 0xef, 0xdb, 0x97, 0x98, 0xe2, 0x19, 0x18, 0xff, 0x30, 0x0b, 0x8b, 0x71, - 0xff, 0xe8, 0x4e, 0x85, 0x17, 0xdf, 0x0e, 0x71, 0x57, 0xb2, 0x83, 0x23, 0xf4, 0x77, 0xcd, 0xf1, - 0x58, 0xa2, 0xc5, 0xd9, 0x71, 0x99, 0x01, 0x15, 0x45, 0xe1, 0x4d, 0x43, 0xed, 0x26, 0xb6, 0x32, - 0x91, 0x1c, 0x4c, 0x43, 0x61, 0x70, 0x09, 0xcb, 0xd3, 0x71, 0xa5, 0xc9, 0x53, 0xb0, 0xc7, 0x61, - 0x07, 0x2f, 0x78, 0x17, 0x60, 0x51, 0x8c, 0x5e, 0xa4, 0xa0, 0x12, 0xf4, 0x0d, 0xd2, 0xb3, 0xe9, - 0xcd, 0xa1, 0x8e, 0xad, 0x2b, 0xa1, 0x74, 0xd7, 0x6d, 0xa4, 0x84, 0xbe, 0x0e, 0x15, 0xaa, 0x3c, - 0x3e, 0x7c, 0x9a, 0x37, 0xcb, 0xd8, 0x02, 0xe2, 0xa5, 0x13, 0xc8, 0x9b, 0x26, 0x4c, 0x5f, 0xa0, - 0xa6, 0x30, 0xe7, 0xe3, 0xef, 0x66, 0xe0, 0x66, 0xca, 0x6b, 0x93, 0xab, 0x7c, 0x0b, 0x96, 0x4e, - 0x22, 0xa4, 0x9a, 0x5d, 0x5a, 0xea, 0x6b, 0x4a, 0xac, 0x26, 0xe7, 0xd4, 0x6c, 0x9c, 0x24, 0x01, - 0xb1, 0xd1, 0x45, 0x6f, 0x30, 0x71, 0xbe, 0x18, 0x8d, 0x2e, 0x7a, 0x8d, 0x64, 0xef, 0x1c, 0xc2, - 0x46, 0xfb, 0x52, 0x48, 0x8c, 0x2d, 0xfd, 0x0b, 0x05, 0x8a, 0x8d, 0x92, 0x0e, 0xe6, 0xcc, 0x2b, - 0x39, 0x98, 0x87, 0x74, 0x8c, 0x32, 0xaa, 0xeb, 0x67, 0xa9, 0x04, 0x37, 0x50, 0x51, 0x86, 0xbe, - 0xb0, 0xa0, 0xce, 0x38, 0x0f, 0xa2, 0x2f, 0x2b, 0x18, 0x01, 0x2c, 0xee, 0x4f, 0x47, 0xa1, 0x13, - 0x7f, 0x6c, 0x81, 0x7d, 0x53, 0x96, 0xc1, 0x76, 0xd4, 0xac, 0xa5, 0x36, 0x04, 0x51, 0x43, 0x38, - 0x59, 0x63, 0x51, 0x91, 0x35, 0xdf, 0xde, 0xe2, 0x38, 0xd9, 0x82, 0x71, 0x13, 0xd6, 0xe3, 0x27, - 0x9a, 0x36, 0xb5, 0xd5, 0xfc, 0xb3, 0x0c, 0xe5, 0x93, 0x27, 0x3f, 0xfc, 0xc0, 0xda, 0xb0, 0x1c, - 0x38, 0xee, 0xe9, 0x88, 0xeb, 0xd5, 0x07, 0x72, 0x12, 0x56, 0x93, 0x7d, 0x93, 0x1f, 0x87, 0x30, - 0x97, 0xa8, 0x44, 0x5c, 0x5b, 0xc0, 0x36, 0xaf, 0xeb, 0x64, 0xcc, 0x16, 0x33, 0xb3, 0x31, 0xdf, - 0xf9, 0x0e, 0xd4, 0x93, 0x0d, 0xb1, 0x6f, 0xc9, 0x23, 0xc4, 0x71, 0xaf, 0x72, 0x33, 0x87, 0x3d, - 0x63, 0x86, 0xa8, 0xc4, 0x73, 0x1f, 0x18, 0x7f, 0x3f, 0x03, 0x4d, 0x93, 0x0b, 0xce, 0xd5, 0x7a, - 0xa9, 0x78, 0xe6, 0xa3, 0xb9, 0x5a, 0xaf, 0x1f, 0xab, 0x3a, 0x99, 0xac, 0x7a, 0xf4, 0xfe, 0xb5, - 0x2f, 0x63, 0xf7, 0xc6, 0xdc, 0x88, 0x36, 0x4b, 0xb0, 0x40, 0x24, 0xc6, 0x3a, 0xac, 0xca, 0xfe, - 0xa8, 0xbe, 0xc4, 0xd1, 0xc3, 0x44, 0x8b, 0x89, 0xe8, 0xe1, 0x06, 0x34, 0xe9, 0x26, 0x4f, 0x7d, - 0x10, 0xb2, 0xe0, 0x36, 0xb0, 0x7d, 0x7b, 0x60, 0xfb, 0x9e, 0xe7, 0x1e, 0x72, 0x5f, 0x66, 0xe7, - 0xa2, 0x86, 0x89, 0xc1, 0x35, 0xa5, 0x0a, 0xd3, 0x93, 0xba, 0x7f, 0xd2, 0x73, 0x55, 0x32, 0x12, - 0x3d, 0x19, 0x26, 0x2c, 0x6f, 0xda, 0xcf, 0xb9, 0xaa, 0x49, 0x4d, 0xd1, 0xc7, 0x50, 0x99, 0x44, - 0x95, 0xaa, 0x79, 0x57, 0xf7, 0x0c, 0xcc, 0x37, 0x6b, 0xea, 0xd4, 0xc6, 0x63, 0x58, 0x49, 0xd6, - 0x29, 0x45, 0xc7, 0x06, 0x94, 0xc6, 0x12, 0x26, 0x7b, 0x17, 0x3d, 0x1b, 0xbf, 0x53, 0x82, 0xa2, - 0xb4, 0xe7, 0xd8, 0x03, 0xc8, 0x0f, 0x54, 0x42, 0x58, 0x7c, 0x7d, 0x8d, 0xc4, 0xaa, 0xff, 0x5b, - 0x98, 0x16, 0x26, 0xe8, 0xd8, 0xc7, 0x50, 0x4f, 0x46, 0x45, 0x67, 0x0e, 0x31, 0x27, 0xc3, 0x99, - 0xb5, 0xc1, 0x4c, 0xfc, 0xab, 0x1c, 0x6f, 0x8e, 0xa4, 0x33, 0x94, 0xce, 0xb4, 0xdd, 0xd3, 0x73, - 0x85, 0xbe, 0x1d, 0x9c, 0xd9, 0xd6, 0xe3, 0x27, 0x1f, 0xca, 0x53, 0xcc, 0x15, 0x04, 0xf6, 0xce, - 0xec, 0xc7, 0x4f, 0x3e, 0x9c, 0xd5, 0xa4, 0xe5, 0x19, 0x66, 0x4d, 0x93, 0x5e, 0x81, 0x02, 0x5d, - 0xb4, 0x48, 0x99, 0x3d, 0xf4, 0xc0, 0x1e, 0xc1, 0x8a, 0x34, 0x5b, 0x2d, 0x99, 0x83, 0x4d, 0x52, - 0xb0, 0x44, 0xc7, 0xde, 0x24, 0xae, 0x87, 0x28, 0xf2, 0x0d, 0xad, 0xc1, 0xc2, 0x59, 0x7c, 0x6b, - 0x66, 0xcd, 0x94, 0x4f, 0xc6, 0x9f, 0x17, 0xa0, 0xa2, 0x4d, 0x0a, 0xab, 0x42, 0xc9, 0x6c, 0xf7, - 0xda, 0xe6, 0xa7, 0xed, 0xed, 0xc6, 0x0d, 0x76, 0x0f, 0xde, 0xea, 0x74, 0xb7, 0x0e, 0x4c, 0xb3, - 0xbd, 0xd5, 0xb7, 0x0e, 0x4c, 0x4b, 0x5d, 0xa2, 0x74, 0xd8, 0xfa, 0x7c, 0xbf, 0xdd, 0xed, 0x5b, - 0xdb, 0xed, 0x7e, 0xab, 0xb3, 0xd7, 0x6b, 0x64, 0xd8, 0x6b, 0xd0, 0x8c, 0x29, 0x15, 0xba, 0xb5, - 0x7f, 0x70, 0xd4, 0xed, 0x37, 0xb2, 0xec, 0x0e, 0xdc, 0xda, 0xe9, 0x74, 0x5b, 0x7b, 0x56, 0x4c, - 0xb3, 0xb5, 0xd7, 0xff, 0xd4, 0x6a, 0xff, 0xfa, 0x61, 0xc7, 0xfc, 0xbc, 0x91, 0x4b, 0x23, 0x10, - 0xc6, 0xb8, 0xaa, 0x21, 0xcf, 0x6e, 0xc2, 0x2a, 0x11, 0x50, 0x11, 0xab, 0x7f, 0x70, 0x60, 0xf5, - 0x0e, 0x0e, 0xba, 0x8d, 0x02, 0x5b, 0x82, 0x5a, 0xa7, 0xfb, 0x69, 0x6b, 0xaf, 0xb3, 0x6d, 0x99, - 0xed, 0xd6, 0xde, 0x7e, 0x63, 0x81, 0x2d, 0xc3, 0xe2, 0x2c, 0x5d, 0x51, 0x54, 0xa1, 0xe8, 0x0e, - 0xba, 0x9d, 0x83, 0xae, 0xf5, 0x69, 0xdb, 0xec, 0x75, 0x0e, 0xba, 0x8d, 0x12, 0x5b, 0x03, 0x96, - 0x44, 0xed, 0xee, 0xb7, 0xb6, 0x1a, 0x65, 0xb6, 0x0a, 0x4b, 0x49, 0xf8, 0xb3, 0xf6, 0xe7, 0x0d, - 0x60, 0x4d, 0x58, 0xa1, 0x8e, 0x59, 0x9b, 0xed, 0xbd, 0x83, 0xcf, 0xac, 0xfd, 0x4e, 0xb7, 0xb3, - 0x7f, 0xb4, 0xdf, 0xa8, 0xe0, 0xb5, 0x6e, 0xed, 0xb6, 0xd5, 0xe9, 0xf6, 0x8e, 0x76, 0x76, 0x3a, - 0x5b, 0x9d, 0x76, 0xb7, 0xdf, 0xa8, 0x52, 0xcb, 0x69, 0x03, 0xaf, 0x89, 0x02, 0xf2, 0xa0, 0x86, - 0xb5, 0xdd, 0xe9, 0xb5, 0x36, 0xf7, 0xda, 0xdb, 0x8d, 0x3a, 0xbb, 0x0d, 0x37, 0xfb, 0xed, 0xfd, - 0xc3, 0x03, 0xb3, 0x65, 0x7e, 0xae, 0x0e, 0x72, 0x58, 0x3b, 0xad, 0xce, 0xde, 0x91, 0xd9, 0x6e, - 0x2c, 0xb2, 0x37, 0xe0, 0xb6, 0xd9, 0xfe, 0xe4, 0xa8, 0x63, 0xb6, 0xb7, 0xad, 0xee, 0xc1, 0x76, - 0xdb, 0xda, 0x69, 0xb7, 0xfa, 0x47, 0x66, 0xdb, 0xda, 0xef, 0xf4, 0x7a, 0x9d, 0xee, 0xd3, 0x46, - 0x83, 0xbd, 0x05, 0x77, 0x23, 0x92, 0xa8, 0x82, 0x19, 0xaa, 0x25, 0x31, 0x3e, 0xf5, 0x4a, 0xbb, - 0xed, 0x5f, 0xef, 0x5b, 0x87, 0xed, 0xb6, 0xd9, 0x60, 0x6c, 0x03, 0xd6, 0xe2, 0xe6, 0xa9, 0x01, - 0xd9, 0xf6, 0xb2, 0xc0, 0x1d, 0xb6, 0xcd, 0xfd, 0x56, 0x57, 0xbc, 0xe0, 0x04, 0x6e, 0x45, 0x74, - 0x3b, 0xc6, 0xcd, 0x76, 0x7b, 0x95, 0x31, 0xa8, 0x6b, 0x6f, 0x65, 0xa7, 0x65, 0x36, 0xd6, 0xd8, - 0x22, 0x54, 0xf6, 0x0f, 0x0f, 0xad, 0x7e, 0x67, 0xbf, 0x7d, 0x70, 0xd4, 0x6f, 0xac, 0xb3, 0x55, - 0x68, 0x74, 0xba, 0xfd, 0xb6, 0x29, 0xde, 0xb5, 0x2a, 0xfa, 0xbf, 0x8a, 0x6c, 0x05, 0x16, 0x55, - 0x4f, 0x15, 0xf4, 0xa7, 0x45, 0xb6, 0x0e, 0xec, 0xa8, 0x6b, 0xb6, 0x5b, 0xdb, 0x62, 0xe2, 0x22, - 0xc4, 0xff, 0x2e, 0xca, 0x08, 0xc9, 0x4f, 0x72, 0xd1, 0x66, 0x1d, 0xa7, 0x1c, 0x24, 0xef, 0x50, - 0xae, 0x6a, 0x77, 0x1f, 0xbf, 0xec, 0xeb, 0x06, 0x9a, 0x69, 0x95, 0x9b, 0x33, 0xad, 0xe6, 0x6c, - 0xf7, 0x9a, 0xae, 0xfb, 0xbd, 0x09, 0xb5, 0x31, 0xdd, 0xa7, 0x2c, 0xef, 0x4d, 0x05, 0x99, 0x7f, - 0x43, 0x40, 0xba, 0x34, 0x75, 0xee, 0x7a, 0xff, 0xc2, 0xfc, 0xf5, 0xfe, 0x69, 0xfa, 0xfd, 0x42, - 0x9a, 0x7e, 0x7f, 0x1f, 0x96, 0x48, 0x34, 0x39, 0xae, 0x33, 0x56, 0x56, 0x33, 0x69, 0x81, 0x8b, - 0x28, 0xa2, 0x08, 0xae, 0xcc, 0x09, 0x65, 0x72, 0x48, 0x11, 0x52, 0x94, 0xd6, 0x46, 0xc2, 0xd2, - 0x20, 0xc9, 0x11, 0x59, 0x1a, 0x51, 0x0b, 0xf6, 0x65, 0xdc, 0x42, 0x45, 0x6b, 0x81, 0xe0, 0xd8, - 0xc2, 0x7d, 0x58, 0xe2, 0x97, 0xa1, 0x6f, 0x5b, 0xde, 0xc4, 0xfe, 0x62, 0x8a, 0x21, 0x5c, 0x1b, - 0x6d, 0xf8, 0xaa, 0xb9, 0x88, 0x88, 0x03, 0x84, 0x6f, 0xdb, 0xa1, 0x7d, 0xff, 0x4b, 0xa8, 0x68, - 0x77, 0x6d, 0xb3, 0x75, 0x58, 0xfe, 0xac, 0xd3, 0xef, 0xb6, 0x7b, 0x3d, 0xeb, 0xf0, 0x68, 0xf3, - 0x59, 0xfb, 0x73, 0x6b, 0xb7, 0xd5, 0xdb, 0x6d, 0xdc, 0x10, 0x8b, 0xb6, 0xdb, 0xee, 0xf5, 0xdb, - 0xdb, 0x09, 0x78, 0x86, 0xbd, 0x0e, 0x1b, 0x47, 0xdd, 0xa3, 0x5e, 0x7b, 0xdb, 0x4a, 0x2b, 0x97, - 0x15, 0x5c, 0x2a, 0xf1, 0x29, 0xc5, 0x73, 0xf7, 0xbf, 0x0b, 0xf5, 0xe4, 0x05, 0xb0, 0x0c, 0x60, - 0x61, 0xaf, 0xfd, 0xb4, 0xb5, 0xf5, 0x39, 0x5d, 0xfc, 0xd8, 0xeb, 0xb7, 0xfa, 0x9d, 0x2d, 0x4b, - 0x5e, 0xf4, 0x28, 0x24, 0x42, 0x86, 0x55, 0xa0, 0xd8, 0xea, 0x6e, 0xed, 0x1e, 0x98, 0xbd, 0x46, - 0xf6, 0xfe, 0xfb, 0x50, 0x4f, 0xe6, 0xd6, 0x89, 0x45, 0xb3, 0xd9, 0xee, 0x7f, 0xd6, 0x6e, 0x77, - 0xb1, 0x3f, 0x5b, 0xed, 0x6e, 0xdf, 0x6c, 0xed, 0x75, 0xfa, 0x9f, 0x37, 0x6e, 0xdc, 0xff, 0x18, - 0x1a, 0xb3, 0xd1, 0xab, 0x44, 0xb8, 0xef, 0x45, 0x71, 0xc1, 0xfb, 0xff, 0x32, 0x07, 0x10, 0x9f, - 0xe9, 0x10, 0x82, 0x69, 0xbb, 0xd5, 0x6f, 0xed, 0x1d, 0x88, 0x41, 0x9b, 0x07, 0x7d, 0x21, 0x6f, - 0xcc, 0xf6, 0x27, 0x8d, 0x1b, 0xa9, 0x98, 0x83, 0xc3, 0x7e, 0x23, 0x23, 0xe6, 0xb7, 0xd3, 0xed, - 0xf4, 0x3b, 0xad, 0x3d, 0xcb, 0x3c, 0x38, 0xea, 0x74, 0x9f, 0xd2, 0xfd, 0x77, 0x28, 0x93, 0x8f, - 0x0e, 0x77, 0xcc, 0x83, 0x6e, 0xdf, 0xea, 0xed, 0x1e, 0xf5, 0xb7, 0xf1, 0xf6, 0xbc, 0x2d, 0xb3, - 0x73, 0x48, 0x75, 0xe6, 0x5f, 0x44, 0x20, 0xaa, 0x2e, 0x88, 0x37, 0xf4, 0xf4, 0xa0, 0xd7, 0xeb, - 0x1c, 0x5a, 0x9f, 0x1c, 0xb5, 0xcd, 0x4e, 0xbb, 0x87, 0x05, 0x17, 0x52, 0xe0, 0x82, 0xbe, 0x28, - 0x24, 0x79, 0x7f, 0xef, 0x53, 0x29, 0x6a, 0x05, 0x69, 0x29, 0x09, 0x12, 0x54, 0x65, 0x31, 0x99, - 0x42, 0x56, 0xa5, 0xd4, 0x0c, 0xd7, 0xe0, 0x44, 0xb9, 0x8a, 0x90, 0xc2, 0x73, 0xaf, 0x0e, 0x8b, - 0x55, 0xd3, 0x51, 0xa2, 0x14, 0x0a, 0xe8, 0x68, 0x3b, 0xdb, 0xde, 0x36, 0xb1, 0x40, 0x7d, 0x0e, - 0x2a, 0x68, 0x17, 0xc5, 0x8b, 0x12, 0xc2, 0x4c, 0x90, 0x34, 0xd4, 0x83, 0xc0, 0x2c, 0x3d, 0xfe, - 0xed, 0x1c, 0xd4, 0xe9, 0x7c, 0x1d, 0x7d, 0x18, 0x8d, 0xfb, 0x6c, 0x1f, 0x8a, 0xf2, 0x0b, 0x7b, - 0x6c, 0x35, 0xba, 0x9a, 0x4c, 0xff, 0xa6, 0xdf, 0xc6, 0xda, 0x2c, 0x58, 0x2a, 0x6f, 0xcb, 0x7f, - 0xe3, 0xcf, 0xfe, 0xe7, 0x3f, 0xc8, 0xd6, 0x58, 0xe5, 0xe1, 0xf9, 0x07, 0x0f, 0x4f, 0xb9, 0x1b, - 0x88, 0x3a, 0xfe, 0x7f, 0x80, 0xf8, 0xbb, 0x71, 0xac, 0x19, 0x85, 0xac, 0x66, 0x3e, 0xaa, 0xb7, - 0x71, 0x33, 0x05, 0x23, 0xeb, 0xbd, 0x89, 0xf5, 0x2e, 0x1b, 0x75, 0x51, 0xaf, 0xe3, 0x3a, 0x21, - 0x7d, 0x43, 0xee, 0xa3, 0xcc, 0x7d, 0x36, 0x84, 0xaa, 0xfe, 0x45, 0x37, 0xa6, 0xf4, 0xaa, 0x94, - 0x6f, 0xd2, 0x6d, 0xdc, 0x4a, 0xc5, 0x29, 0x8d, 0x15, 0xdb, 0x58, 0x35, 0x1a, 0xa2, 0x8d, 0x29, - 0x52, 0xc4, 0xad, 0x8c, 0x48, 0x87, 0x8f, 0x3f, 0xdc, 0xc6, 0x5e, 0xd3, 0xb4, 0xb0, 0xb9, 0xcf, - 0xc6, 0x6d, 0xdc, 0xbe, 0x06, 0x2b, 0xdb, 0xba, 0x8d, 0x6d, 0xad, 0x1b, 0x4c, 0xb4, 0x35, 0x40, - 0x1a, 0xf5, 0xd9, 0xb8, 0x8f, 0x32, 0xf7, 0x1f, 0xff, 0x87, 0x77, 0xa1, 0x1c, 0xe5, 0xdb, 0xb2, - 0xdf, 0x84, 0x5a, 0xe2, 0x00, 0x24, 0x53, 0xc3, 0x48, 0x3b, 0x2f, 0xb9, 0xf1, 0x5a, 0x3a, 0x52, - 0x36, 0xfc, 0x3a, 0x36, 0xdc, 0x64, 0x6b, 0xa2, 0x61, 0x79, 0xc0, 0xf0, 0x21, 0x1e, 0x58, 0xa6, - 0x8b, 0xde, 0x9e, 0x6b, 0xb6, 0x0a, 0x35, 0xf6, 0xda, 0xac, 0xfd, 0x90, 0x68, 0xed, 0xf6, 0x35, - 0x58, 0xd9, 0xdc, 0x6b, 0xd8, 0xdc, 0x1a, 0x5b, 0xd1, 0x9b, 0x53, 0x89, 0x9a, 0x8c, 0xe3, 0xe5, - 0x8a, 0xfa, 0x77, 0xcd, 0xd8, 0xed, 0xf8, 0x2a, 0xbc, 0x94, 0xef, 0x9d, 0x45, 0x2c, 0x32, 0xff, - 0xd1, 0x33, 0xa3, 0x89, 0x4d, 0x31, 0x86, 0xaf, 0x4f, 0xff, 0xac, 0x19, 0x3b, 0x86, 0x8a, 0xf6, - 0x29, 0x10, 0x76, 0xf3, 0xda, 0xcf, 0x96, 0x6c, 0x6c, 0xa4, 0xa1, 0xd2, 0x86, 0xa2, 0xd7, 0xff, - 0xf0, 0x84, 0x73, 0xf6, 0x03, 0x28, 0x47, 0x1f, 0x98, 0x60, 0xeb, 0xda, 0x07, 0x3f, 0xf4, 0x0f, - 0x62, 0x6c, 0x34, 0xe7, 0x11, 0x69, 0xcc, 0xa7, 0xd7, 0x2e, 0x98, 0xef, 0x33, 0xa8, 0x68, 0x1f, - 0x91, 0x88, 0x06, 0x30, 0xff, 0xa1, 0x8a, 0x68, 0x00, 0x29, 0xdf, 0x9c, 0x30, 0x96, 0xb0, 0x89, - 0x0a, 0x2b, 0x23, 0x7f, 0x87, 0x97, 0x5e, 0xc0, 0xf6, 0x60, 0x55, 0xda, 0x65, 0xc7, 0xfc, 0xab, - 0xbc, 0x86, 0x94, 0x4f, 0xc9, 0x3d, 0xca, 0xb0, 0x8f, 0xa1, 0xa4, 0xbe, 0x15, 0xc2, 0xd6, 0xd2, - 0xbf, 0x79, 0xb2, 0xb1, 0x3e, 0x07, 0x97, 0x46, 0xd4, 0xe7, 0x00, 0xf1, 0x17, 0x2b, 0x22, 0x21, - 0x31, 0xf7, 0x05, 0x8c, 0x88, 0x03, 0xe6, 0x3f, 0x6f, 0x61, 0xac, 0xe1, 0x00, 0x1b, 0x0c, 0x85, - 0x84, 0xcb, 0x2f, 0xd4, 0x0d, 0xb8, 0x3f, 0x84, 0x8a, 0xf6, 0xd1, 0x8a, 0x68, 0xfa, 0xe6, 0x3f, - 0x78, 0x11, 0x4d, 0x5f, 0xca, 0x37, 0x2e, 0x8c, 0x0d, 0xac, 0x7d, 0xc5, 0x58, 0x14, 0xb5, 0x0b, - 0xc5, 0x4c, 0x2a, 0x48, 0xe2, 0x05, 0x9d, 0x41, 0x2d, 0xf1, 0x65, 0x8a, 0x68, 0x85, 0xa6, 0x7d, - 0xf7, 0x22, 0x5a, 0xa1, 0xa9, 0x1f, 0xb3, 0x50, 0x7c, 0x66, 0x2c, 0x89, 0x76, 0xce, 0x91, 0x44, - 0x6b, 0xe9, 0xfb, 0x50, 0xd1, 0xbe, 0x32, 0x11, 0x8d, 0x65, 0xfe, 0x83, 0x16, 0xd1, 0x58, 0xd2, - 0x3e, 0x4a, 0xb1, 0x82, 0x6d, 0xd4, 0x0d, 0x64, 0x05, 0xbc, 0xc3, 0x53, 0xd4, 0xfd, 0x9b, 0x50, - 0x4f, 0x7e, 0x78, 0x22, 0x5a, 0xfb, 0xa9, 0x5f, 0xb0, 0x88, 0xd6, 0xfe, 0x35, 0x5f, 0xab, 0x90, - 0x2c, 0x7d, 0x7f, 0x39, 0x6a, 0xe4, 0xe1, 0x8f, 0xe5, 0xc9, 0xa1, 0x2f, 0xd9, 0x27, 0x42, 0xc0, - 0xc9, 0x2b, 0x64, 0xd9, 0xba, 0xc6, 0xb5, 0xfa, 0x5d, 0xb4, 0xd1, 0x7a, 0x99, 0xbb, 0x6d, 0x36, - 0xc9, 0xcc, 0x58, 0x39, 0x7b, 0x0a, 0xcb, 0x11, 0x33, 0x47, 0x77, 0xc2, 0x06, 0xd1, 0x18, 0x52, - 0x6f, 0x9e, 0xdd, 0x68, 0xcc, 0x62, 0x1f, 0x65, 0x68, 0xfb, 0xc3, 0x9b, 0x38, 0xb5, 0xed, 0x4f, - 0xbf, 0x16, 0x56, 0xdb, 0xfe, 0x12, 0x17, 0x76, 0xce, 0x6e, 0x7f, 0xa1, 0x23, 0xea, 0x70, 0x61, - 0x71, 0xf6, 0x86, 0xd6, 0xdb, 0xd7, 0xdd, 0xcc, 0x40, 0xd5, 0xbf, 0xfe, 0xe2, 0x8b, 0x1b, 0x92, - 0xa2, 0x48, 0x49, 0xd3, 0x87, 0x32, 0x55, 0x85, 0xfd, 0x06, 0x54, 0xf5, 0xcb, 0xea, 0x99, 0x2e, - 0x13, 0x66, 0x5b, 0xba, 0x95, 0x8a, 0x4b, 0x72, 0x09, 0xab, 0xea, 0xcd, 0xb0, 0x4f, 0x61, 0x2d, - 0x9a, 0x66, 0xfd, 0x6a, 0x81, 0x80, 0xdd, 0x49, 0xb9, 0x70, 0x20, 0x31, 0xd9, 0x37, 0xaf, 0xbd, - 0x91, 0xe0, 0x51, 0x46, 0x70, 0x5f, 0xf2, 0xd6, 0xec, 0x78, 0xe7, 0x49, 0xbb, 0x2c, 0x3c, 0xde, - 0x79, 0x52, 0xaf, 0xda, 0x56, 0xdc, 0xc7, 0x96, 0x13, 0x73, 0x44, 0x49, 0xbc, 0xec, 0xfb, 0xb0, - 0xa8, 0xdd, 0x9b, 0xd0, 0xbb, 0x72, 0x07, 0xd1, 0x4a, 0x9a, 0xbf, 0xf6, 0x71, 0x23, 0xcd, 0x93, - 0x69, 0xac, 0x63, 0xfd, 0x4b, 0x46, 0x62, 0x72, 0xc4, 0x2a, 0xda, 0x82, 0x8a, 0x7e, 0x27, 0xc3, - 0x0b, 0xea, 0x5d, 0xd7, 0x50, 0xfa, 0x0d, 0x83, 0x8f, 0x32, 0x6c, 0x0f, 0x1a, 0xb3, 0xf7, 0x9d, - 0x45, 0x32, 0x25, 0xed, 0x8e, 0xb6, 0x8d, 0x19, 0x64, 0xe2, 0x96, 0x34, 0x76, 0x48, 0xc7, 0x40, - 0xa2, 0xef, 0xae, 0x79, 0xfe, 0xec, 0xae, 0x9e, 0xfc, 0x1e, 0x5b, 0x54, 0x5b, 0xda, 0x97, 0xf8, - 0xee, 0x65, 0x1e, 0x65, 0xd8, 0xef, 0x66, 0xa0, 0x9a, 0xb8, 0x41, 0x28, 0x91, 0x68, 0x3f, 0x33, - 0xce, 0xa6, 0x8e, 0xd3, 0x07, 0x6a, 0x98, 0x38, 0x89, 0x7b, 0xf7, 0xbf, 0x97, 0x78, 0x49, 0x3f, - 0x4e, 0x04, 0x02, 0x1f, 0xcc, 0x7e, 0x98, 0xed, 0xcb, 0x59, 0x02, 0xfd, 0x36, 0xcf, 0x2f, 0x1f, - 0x65, 0xd8, 0xbf, 0xce, 0x40, 0x3d, 0x19, 0xe1, 0x8f, 0x86, 0x9b, 0x9a, 0x4b, 0x10, 0xb1, 0xd2, - 0x35, 0x69, 0x01, 0xdf, 0xc7, 0x5e, 0xf6, 0xef, 0x9b, 0x89, 0x5e, 0xca, 0xfb, 0xde, 0x7f, 0xbe, - 0xde, 0xb2, 0x8f, 0xe8, 0x3b, 0xa8, 0x2a, 0xf1, 0x89, 0xcd, 0x7f, 0x37, 0x33, 0x62, 0x3f, 0xfd, - 0x2b, 0x93, 0xf8, 0x12, 0x7e, 0x48, 0x1f, 0x20, 0x53, 0x79, 0x34, 0x82, 0x8b, 0x5f, 0xb5, 0xbc, - 0xf1, 0x16, 0x8e, 0xe9, 0x75, 0xe3, 0x66, 0x62, 0x4c, 0xb3, 0x8a, 0x47, 0x8b, 0x7a, 0x27, 0x3f, - 0x12, 0x19, 0xef, 0x9c, 0x73, 0x1f, 0x8e, 0xbc, 0xbe, 0x93, 0x63, 0xea, 0xa4, 0x24, 0x4f, 0x2c, - 0xb5, 0x57, 0xac, 0xc6, 0xb8, 0x8f, 0x7d, 0x7d, 0xcb, 0xb8, 0x73, 0x6d, 0x5f, 0x1f, 0x62, 0xb4, - 0x5e, 0xf4, 0xf8, 0x10, 0x20, 0x4e, 0x4c, 0x64, 0x33, 0xe9, 0x71, 0x91, 0x00, 0x9a, 0xcf, 0x5d, - 0x4c, 0xae, 0x67, 0x95, 0x45, 0x27, 0x6a, 0xfc, 0x01, 0x89, 0xd3, 0x28, 0x71, 0x4f, 0xd7, 0xbe, - 0x92, 0x39, 0x84, 0x09, 0xed, 0x6b, 0xb6, 0xfe, 0x84, 0x30, 0x8d, 0xb2, 0xf4, 0x8e, 0xa0, 0xb6, - 0xe7, 0x79, 0xcf, 0xa7, 0x93, 0x28, 0x19, 0x3e, 0x99, 0x42, 0xb3, 0x6b, 0x07, 0x67, 0x1b, 0x33, - 0xa3, 0x30, 0xee, 0x62, 0x55, 0x1b, 0xac, 0xa9, 0x55, 0xf5, 0xf0, 0xc7, 0x71, 0x36, 0xe4, 0x97, - 0xcc, 0x86, 0xa5, 0x48, 0x46, 0xc7, 0x19, 0x87, 0xc9, 0x6a, 0x12, 0x92, 0x79, 0xb6, 0x89, 0x84, - 0x99, 0xa0, 0x7a, 0xfb, 0x30, 0x50, 0x75, 0x3e, 0xca, 0xb0, 0x43, 0xa8, 0x6e, 0xf3, 0x01, 0xde, - 0xa5, 0x80, 0x89, 0x28, 0xcb, 0x89, 0xa4, 0x06, 0xca, 0x60, 0xd9, 0xa8, 0x25, 0x80, 0xc9, 0x7d, - 0x6b, 0x62, 0x5f, 0xf9, 0xfc, 0x8b, 0x87, 0x3f, 0x96, 0x29, 0x2e, 0x5f, 0xaa, 0x7d, 0x4b, 0xa5, - 0x00, 0x25, 0xf6, 0xad, 0x99, 0x9c, 0xa1, 0xc4, 0xbe, 0x35, 0x97, 0x33, 0x94, 0x98, 0x6a, 0x95, - 0x82, 0xc4, 0x46, 0xb0, 0x34, 0x97, 0x66, 0x14, 0x6d, 0x59, 0xd7, 0x25, 0x27, 0x6d, 0xdc, 0xbd, - 0x9e, 0x20, 0xd9, 0xda, 0xfd, 0x64, 0x6b, 0x3d, 0xa8, 0xd1, 0x05, 0xa3, 0xc7, 0x9c, 0x4e, 0x55, - 0xce, 0x5c, 0x49, 0xa4, 0x1f, 0xd9, 0x9c, 0xdd, 0x60, 0x10, 0x97, 0xd4, 0x70, 0xf0, 0x64, 0x1d, - 0x3b, 0xc1, 0xfb, 0xe9, 0xb5, 0x63, 0x8c, 0x11, 0x33, 0xce, 0x1f, 0xad, 0x8c, 0x98, 0x31, 0xe5, - 0xd4, 0xa3, 0x32, 0x3f, 0xd9, 0x6a, 0x54, 0xf7, 0x43, 0xd7, 0x1b, 0xf2, 0xb1, 0xac, 0xf5, 0x07, - 0x50, 0x79, 0xca, 0x43, 0x75, 0x72, 0x30, 0xd2, 0xe5, 0x67, 0x8e, 0x12, 0x6e, 0xa4, 0x9c, 0xf6, - 0x4c, 0xf2, 0x26, 0xd5, 0xcc, 0x87, 0xa7, 0x9c, 0x84, 0xa0, 0xe5, 0x0c, 0xbf, 0x64, 0xbf, 0x8e, - 0x95, 0x47, 0xa7, 0xe4, 0xd7, 0xb4, 0x6e, 0xea, 0x95, 0x2f, 0xce, 0xc0, 0xd3, 0x6a, 0x16, 0x7d, - 0xd6, 0x74, 0x4a, 0x17, 0x2a, 0xda, 0x6d, 0x1a, 0xd1, 0xdc, 0xcc, 0xdf, 0x9e, 0x12, 0xcd, 0x4d, - 0xca, 0xe5, 0x1b, 0xc6, 0x3d, 0x6c, 0xc7, 0x60, 0x77, 0xe3, 0x76, 0xe8, 0xc2, 0x8d, 0xb8, 0xa5, - 0x87, 0x3f, 0xb6, 0xc7, 0xe1, 0x97, 0xec, 0x33, 0x7a, 0x1d, 0xda, 0xc9, 0xc8, 0xd8, 0x38, 0x99, - 0x3d, 0x44, 0x19, 0x4d, 0x96, 0x86, 0x4a, 0x1a, 0x2c, 0xd4, 0x14, 0x6a, 0x8c, 0x4f, 0x00, 0x7a, - 0xa1, 0x37, 0xd9, 0xb6, 0xf9, 0xd8, 0x73, 0x63, 0x99, 0x1e, 0x9f, 0xd5, 0x8b, 0xe5, 0xa4, 0x76, - 0x60, 0x8f, 0x7d, 0xa6, 0x59, 0x73, 0x89, 0x13, 0xbd, 0x8a, 0x89, 0xaf, 0x3d, 0xce, 0x17, 0x4d, - 0x48, 0xca, 0x91, 0xbe, 0x47, 0x19, 0xd6, 0x02, 0x88, 0xf3, 0xd9, 0x22, 0xdb, 0x6c, 0x2e, 0x55, - 0x2e, 0x12, 0xaf, 0x29, 0xc9, 0x6f, 0x87, 0x50, 0x8e, 0x13, 0x81, 0xd6, 0xe3, 0xcb, 0x81, 0x12, - 0x69, 0x43, 0x91, 0xa6, 0x30, 0x97, 0x84, 0x63, 0x34, 0x70, 0xaa, 0x80, 0x95, 0xc4, 0x54, 0x9d, - 0x70, 0x1e, 0x30, 0x07, 0x96, 0xa9, 0x83, 0x91, 0x5a, 0x86, 0x67, 0xcc, 0xa2, 0xaf, 0x42, 0xcc, - 0xe7, 0xc3, 0x44, 0x52, 0x23, 0x35, 0xab, 0x23, 0xe1, 0x62, 0x12, 0xdc, 0x4a, 0xe7, 0xdb, 0xc4, - 0x16, 0x30, 0x86, 0xa5, 0xb9, 0xc4, 0x81, 0x48, 0x74, 0x5c, 0x97, 0x09, 0x12, 0x89, 0x8e, 0x6b, - 0x73, 0x0e, 0x8c, 0x55, 0x6c, 0x72, 0xd1, 0x00, 0x34, 0x29, 0x2f, 0x9c, 0x70, 0x70, 0x26, 0x9a, - 0xfb, 0xfd, 0x0c, 0x2c, 0xa7, 0xa4, 0x06, 0xb0, 0x37, 0x94, 0x77, 0xe2, 0xda, 0xb4, 0x81, 0x8d, - 0xd4, 0x10, 0xb2, 0xd1, 0xc3, 0x76, 0xf6, 0xd9, 0xb3, 0xc4, 0x06, 0x4a, 0x11, 0x5c, 0xb9, 0x32, - 0x5f, 0xa8, 0xbc, 0xa4, 0x6a, 0x2e, 0x5f, 0xc0, 0x3a, 0x75, 0xa4, 0x35, 0x1a, 0xcd, 0x84, 0xb7, - 0x5f, 0xd7, 0x7a, 0x91, 0x12, 0xb2, 0x4f, 0xd8, 0x01, 0xc9, 0xb0, 0xfd, 0x35, 0x6a, 0x3b, 0x75, - 0x95, 0x4d, 0xa1, 0x31, 0x1b, 0x36, 0x66, 0xd7, 0xd7, 0xb5, 0x71, 0x27, 0x61, 0x67, 0xa7, 0x84, - 0x9a, 0xbf, 0x86, 0x8d, 0xdd, 0x31, 0x36, 0xd2, 0xe6, 0x85, 0x4c, 0x6f, 0xf1, 0x3e, 0xfe, 0x7a, - 0x14, 0xe3, 0x9e, 0x19, 0xa7, 0x6a, 0xe0, 0xba, 0x88, 0x7c, 0x64, 0xe9, 0xa7, 0x87, 0xc8, 0xdf, - 0xc6, 0xe6, 0xef, 0x1a, 0xb7, 0xd2, 0x9a, 0xf7, 0xa9, 0x08, 0xd9, 0xfc, 0xeb, 0xb3, 0xeb, 0x5a, - 0xf5, 0xe0, 0x6e, 0xda, 0xfb, 0xbe, 0xd6, 0xe6, 0x9a, 0x99, 0xeb, 0x1b, 0xa8, 0x43, 0x56, 0xf5, - 0x98, 0x76, 0xb4, 0x7c, 0x52, 0x82, 0xe7, 0xd1, 0xf2, 0x49, 0x0b, 0x82, 0x27, 0xf5, 0x27, 0x15, - 0xfe, 0xfe, 0x28, 0x73, 0x7f, 0xf3, 0x9d, 0xef, 0x7f, 0xed, 0xd4, 0x09, 0xcf, 0xa6, 0xc7, 0x0f, - 0x06, 0xde, 0xf8, 0xe1, 0x48, 0x79, 0x35, 0xe5, 0x41, 0xec, 0x87, 0x23, 0x77, 0xf8, 0x10, 0xab, - 0x3d, 0x5e, 0x98, 0xf8, 0x5e, 0xe8, 0x7d, 0xe3, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x4f, 0xc5, - 0x60, 0x26, 0x72, 0x86, 0x00, 0x00, + 0x20, 0xe3, 0xc6, 0x7f, 0xc9, 0xc0, 0x72, 0x0a, 0xcb, 0x7d, 0x75, 0x63, 0x16, 0x9c, 0x92, 0x10, + 0x42, 0x59, 0xc9, 0x29, 0xba, 0xfc, 0xd9, 0x83, 0x4a, 0x1c, 0xb7, 0x52, 0x39, 0xfc, 0xf7, 0x5f, + 0x26, 0x0b, 0xe2, 0x12, 0xa6, 0x5e, 0x7c, 0xe3, 0x0f, 0xb2, 0x50, 0xd1, 0x90, 0x62, 0x16, 0x89, + 0xc1, 0xb4, 0xdc, 0x0e, 0xd2, 0x03, 0xd0, 0x56, 0xbb, 0x03, 0xd2, 0x19, 0x4c, 0x78, 0x5a, 0x0a, + 0x72, 0xd3, 0x47, 0x82, 0x07, 0xb0, 0xac, 0xc2, 0x20, 0x3c, 0x4e, 0xe1, 0x92, 0x3b, 0xc3, 0x92, + 0x0c, 0x86, 0xf0, 0x28, 0x23, 0x8c, 0x3d, 0x54, 0x1a, 0x7c, 0xfc, 0xee, 0x90, 0x31, 0xc9, 0xd3, + 0xba, 0x44, 0xec, 0xac, 0x5e, 0xa2, 0xe0, 0xca, 0xf7, 0x61, 0x55, 0x31, 0x73, 0xb2, 0x04, 0x39, + 0x5f, 0x99, 0x64, 0x65, 0xbd, 0xc8, 0xf7, 0xe1, 0xf6, 0x4c, 0x9f, 0x66, 0x8a, 0x52, 0xae, 0xe1, + 0xcd, 0x44, 0xef, 0xf4, 0x1a, 0x36, 0x7e, 0x02, 0xb5, 0x84, 0x58, 0xfb, 0xea, 0x5e, 0xf9, 0xac, + 0x7d, 0x4c, 0x33, 0xaa, 0xdb, 0xc7, 0x1b, 0xff, 0x27, 0x07, 0x6c, 0x5e, 0xb2, 0xfe, 0x32, 0xbb, + 0x30, 0xcf, 0x98, 0xb9, 0x14, 0xc6, 0xfc, 0x7f, 0xb6, 0xdb, 0xbf, 0x07, 0x4b, 0xf2, 0x2c, 0x8b, + 0x16, 0xcb, 0xa2, 0xc5, 0xd9, 0x88, 0x10, 0xaa, 0x17, 0xdf, 0x9e, 0x8d, 0xa9, 0x97, 0x12, 0xe9, + 0xfb, 0x9a, 0xba, 0x33, 0x13, 0x5a, 0x3f, 0x82, 0x05, 0xdb, 0x1d, 0x9c, 0x79, 0x3e, 0x9a, 0x66, + 0xf5, 0xc7, 0xbf, 0xf2, 0xa5, 0x37, 0xbb, 0x07, 0x2d, 0x2c, 0x8f, 0x3a, 0x96, 0x29, 0x2b, 0x33, + 0xde, 0x87, 0x8a, 0x06, 0xc6, 0xf8, 0x4e, 0x67, 0x7f, 0xf3, 0xa0, 0x71, 0x83, 0xd5, 0xa0, 0x6c, + 0xb6, 0xb7, 0x0e, 0x3e, 0x69, 0x9b, 0xed, 0xed, 0x46, 0x86, 0x95, 0x20, 0xbf, 0x77, 0xd0, 0xeb, + 0x37, 0xb2, 0xc6, 0x06, 0x34, 0x65, 0x8d, 0xf3, 0xbe, 0xde, 0xdf, 0xcd, 0x47, 0x6e, 0x16, 0x44, + 0x4a, 0xab, 0xea, 0x9b, 0x50, 0xd5, 0x95, 0x11, 0xc9, 0x11, 0x33, 0xe1, 0x54, 0x61, 0x4f, 0x79, + 0x9a, 0xac, 0xde, 0x02, 0x0a, 0x92, 0x0d, 0xa3, 0x62, 0xa4, 0x61, 0xbe, 0x20, 0xaa, 0x82, 0xca, + 0x73, 0x82, 0x0d, 0xff, 0x3f, 0xa8, 0x27, 0x1d, 0x9f, 0x52, 0x22, 0xa5, 0x99, 0x17, 0xa2, 0x74, + 0xc2, 0x13, 0xca, 0xbe, 0x0f, 0x8d, 0x59, 0xc7, 0xa9, 0xcc, 0x72, 0xbe, 0xa6, 0xfc, 0xa2, 0x93, + 0xf4, 0xa5, 0xb2, 0x5d, 0x58, 0x49, 0x53, 0xc7, 0x90, 0x3f, 0xae, 0xb7, 0x2b, 0xd9, 0xbc, 0xca, + 0xc5, 0xbe, 0x23, 0xfd, 0xe3, 0x85, 0xb4, 0x28, 0xa3, 0x36, 0xd9, 0x0f, 0xe8, 0x9f, 0xe6, 0x29, + 0x3f, 0x07, 0x88, 0x61, 0xac, 0x01, 0xd5, 0x83, 0xc3, 0x76, 0xd7, 0xda, 0xda, 0x6d, 0x75, 0xbb, + 0xed, 0xbd, 0xc6, 0x0d, 0xc6, 0xa0, 0x8e, 0xe1, 0xc1, 0xed, 0x08, 0x96, 0x11, 0x30, 0x19, 0xa7, + 0x50, 0xb0, 0x2c, 0x5b, 0x81, 0x46, 0xa7, 0x3b, 0x03, 0xcd, 0xb1, 0x26, 0xac, 0x1c, 0xb6, 0x29, + 0xa2, 0x98, 0xa8, 0x37, 0x2f, 0x54, 0x7c, 0x39, 0x5c, 0xa1, 0xe2, 0xd3, 0x99, 0x2c, 0xb9, 0x0e, + 0x94, 0xe6, 0xfb, 0x7b, 0x19, 0x58, 0x9d, 0x41, 0xc4, 0x99, 0xf6, 0xa4, 0xf7, 0x26, 0x35, 0xde, + 0x2a, 0x02, 0xd5, 0x6a, 0x7a, 0x0f, 0x96, 0x22, 0x5f, 0xc1, 0xcc, 0xae, 0xd4, 0x88, 0x10, 0x8a, + 0xf8, 0x21, 0x2c, 0x6b, 0x2e, 0x87, 0x19, 0x59, 0xc1, 0x34, 0x94, 0x2c, 0x60, 0xac, 0x47, 0x19, + 0xcd, 0x33, 0xbd, 0x1e, 0xd2, 0x41, 0x2f, 0x1d, 0x11, 0x87, 0x0f, 0x92, 0xfd, 0x55, 0x8f, 0xec, + 0xd1, 0x0c, 0x23, 0x24, 0x7b, 0xab, 0xbf, 0x70, 0xd5, 0xfc, 0x1f, 0x2d, 0x00, 0xfb, 0x78, 0xca, + 0xfd, 0x2b, 0xcc, 0xa4, 0x0f, 0x5e, 0x96, 0x5a, 0xa6, 0xec, 0xea, 0xec, 0x2b, 0x9d, 0x96, 0x49, + 0x3b, 0xad, 0x92, 0x7f, 0xf9, 0x69, 0x95, 0xc2, 0xcb, 0x4e, 0xab, 0xbc, 0x09, 0x35, 0xe7, 0xd4, + 0xf5, 0x84, 0x28, 0x14, 0x7a, 0x6b, 0xd0, 0x5c, 0xb8, 0x9b, 0xbb, 0x57, 0x35, 0xab, 0x12, 0x28, + 0xb4, 0xd6, 0x80, 0x7d, 0x14, 0x13, 0xf1, 0xe1, 0x29, 0x9e, 0xac, 0xd2, 0x85, 0x60, 0x7b, 0x78, + 0xca, 0xa5, 0x1b, 0x01, 0xed, 0x02, 0x55, 0x58, 0xc0, 0x03, 0xf6, 0x16, 0xd4, 0x03, 0x6f, 0x2a, + 0xcc, 0x00, 0x35, 0x0d, 0x14, 0x60, 0xa8, 0x12, 0xf4, 0x50, 0x45, 0x93, 0x96, 0xa7, 0x01, 0xb7, + 0xc6, 0x4e, 0x10, 0x08, 0xf5, 0x6c, 0xe0, 0xb9, 0xa1, 0xef, 0x8d, 0x64, 0xcc, 0x60, 0x69, 0x1a, + 0xf0, 0x7d, 0xc2, 0x6c, 0x11, 0x82, 0x7d, 0x2b, 0xee, 0xd2, 0xc4, 0x76, 0xfc, 0xa0, 0x09, 0xd8, + 0x25, 0x35, 0x52, 0xd4, 0xb6, 0x6d, 0xc7, 0x8f, 0xfa, 0x22, 0x1e, 0x82, 0x99, 0x53, 0x34, 0x95, + 0xd9, 0x53, 0x34, 0x3f, 0x4a, 0x3f, 0x45, 0x53, 0xc3, 0xaa, 0x1f, 0xc9, 0xaa, 0xe7, 0x5f, 0xf1, + 0x97, 0x3a, 0x4c, 0x33, 0x7f, 0x38, 0xa8, 0xfe, 0x65, 0x0e, 0x07, 0x2d, 0xa6, 0x1d, 0x0e, 0x7a, + 0x1f, 0x2a, 0x78, 0x6c, 0xc3, 0x3a, 0x73, 0x84, 0x0e, 0x47, 0x31, 0x90, 0x86, 0x7e, 0xae, 0x63, + 0xd7, 0x71, 0x43, 0x13, 0x7c, 0xf5, 0x33, 0x98, 0x3f, 0xa7, 0xb3, 0xf4, 0x4b, 0x3c, 0xa7, 0x23, + 0x8f, 0x97, 0x3c, 0x80, 0x92, 0x7a, 0x4f, 0x8c, 0x41, 0xfe, 0xc4, 0xf7, 0xc6, 0xca, 0x37, 0x2c, + 0x7e, 0xb3, 0x3a, 0x64, 0x43, 0x4f, 0x16, 0xce, 0x86, 0x9e, 0xf1, 0x9b, 0x50, 0xd1, 0x58, 0x8d, + 0xbd, 0x41, 0x5e, 0x28, 0x61, 0x49, 0x49, 0xdd, 0x92, 0x66, 0xb1, 0x2c, 0xa1, 0x9d, 0xa1, 0x90, + 0x37, 0x43, 0xc7, 0xe7, 0x78, 0xa2, 0xce, 0xf2, 0xf9, 0x39, 0xf7, 0x03, 0xe5, 0xab, 0x6f, 0x44, + 0x08, 0x93, 0xe0, 0xc6, 0xff, 0x0f, 0xcb, 0x89, 0x77, 0x2b, 0x45, 0xc4, 0x5b, 0xb0, 0x80, 0xf3, + 0xa6, 0x62, 0xa9, 0xc9, 0xf3, 0x32, 0x12, 0x87, 0x47, 0xa5, 0x29, 0xcc, 0x60, 0x4d, 0x7c, 0xef, + 0x18, 0x1b, 0xc9, 0x98, 0x15, 0x09, 0x3b, 0xf4, 0xbd, 0x63, 0xe3, 0x2f, 0x73, 0x90, 0xdb, 0xf5, + 0x26, 0x7a, 0xfa, 0x50, 0x66, 0x2e, 0x7d, 0x48, 0x9a, 0x87, 0x56, 0x64, 0xfe, 0x49, 0x9d, 0x1d, + 0x1d, 0xec, 0xca, 0x04, 0xbc, 0x07, 0x75, 0x21, 0x27, 0x42, 0x4f, 0xd8, 0xd7, 0x17, 0xb6, 0x4f, + 0x0a, 0x71, 0x8e, 0x16, 0x9f, 0x3d, 0x0e, 0xfb, 0xde, 0x0e, 0xc1, 0xd9, 0x0a, 0xe4, 0x22, 0xf3, + 0x05, 0xd1, 0xe2, 0x91, 0xad, 0xc1, 0x02, 0xe6, 0x91, 0x5e, 0xc9, 0x60, 0xa1, 0x7c, 0x62, 0xdf, + 0x80, 0xe5, 0x64, 0xbd, 0x24, 0x8a, 0xa4, 0x6e, 0xa4, 0x57, 0x8c, 0x32, 0xe9, 0x26, 0x08, 0x39, + 0x42, 0x34, 0x32, 0xe7, 0xe0, 0x84, 0x73, 0x44, 0x69, 0x42, 0xaf, 0x94, 0x10, 0x7a, 0x77, 0xa0, + 0x12, 0x8e, 0xce, 0xad, 0x89, 0x7d, 0x35, 0xf2, 0xec, 0xa1, 0x5c, 0xdf, 0x10, 0x8e, 0xce, 0x0f, + 0x09, 0xc2, 0x1e, 0x02, 0x8c, 0x27, 0x13, 0xb9, 0xf6, 0xd0, 0x5f, 0x1d, 0xb3, 0xf2, 0xfe, 0xe1, + 0x21, 0xb1, 0x9c, 0x59, 0x1e, 0x4f, 0x26, 0xf4, 0x93, 0x6d, 0x43, 0x3d, 0xf5, 0xd4, 0xdb, 0x6d, + 0x95, 0xf6, 0xe8, 0x4d, 0x1e, 0xa4, 0x2c, 0xce, 0xda, 0x40, 0x87, 0x6d, 0x7c, 0x1f, 0xd8, 0x2f, + 0x78, 0xf6, 0xac, 0x0f, 0xe5, 0xa8, 0x7f, 0xfa, 0xd1, 0x2d, 0x4c, 0x64, 0xae, 0x24, 0x8e, 0x6e, + 0xb5, 0x86, 0x43, 0x5f, 0xc8, 0x45, 0xda, 0x30, 0x23, 0x91, 0x0f, 0xda, 0x8e, 0xd9, 0x22, 0xb9, + 0x6f, 0xfc, 0xf7, 0x0c, 0x14, 0xe8, 0x1c, 0xd9, 0xdb, 0xb0, 0x48, 0xf4, 0x51, 0x2a, 0x96, 0x0c, + 0x31, 0xd2, 0xbe, 0xdb, 0x97, 0x59, 0x58, 0x62, 0x59, 0x68, 0x67, 0x60, 0xb3, 0xd1, 0x9b, 0xd7, + 0xce, 0xc1, 0xde, 0x81, 0x72, 0xd4, 0xb4, 0xc6, 0x3a, 0x25, 0xd5, 0x32, 0x7b, 0x1d, 0xf2, 0x67, + 0xde, 0x44, 0xf9, 0x69, 0x20, 0x9e, 0x49, 0x13, 0xe1, 0x71, 0x5f, 0x44, 0x1b, 0xd4, 0x79, 0xe9, + 0x5f, 0x88, 0x1a, 0x41, 0x36, 0x98, 0x1f, 0xe3, 0x42, 0xca, 0x18, 0x8f, 0x60, 0x51, 0xc8, 0x01, + 0x2d, 0xd4, 0x7f, 0xfd, 0xa6, 0xf9, 0xae, 0xd0, 0xf0, 0x06, 0xa3, 0xe9, 0x90, 0xeb, 0x9e, 0x32, + 0xcc, 0x0b, 0x92, 0x70, 0xa5, 0x59, 0x1b, 0x7f, 0x94, 0x21, 0xf9, 0x22, 0xea, 0x65, 0xf7, 0x20, + 0x2f, 0xf6, 0xb7, 0x19, 0x4f, 0x6e, 0x94, 0x51, 0x2e, 0xe8, 0x4c, 0xa4, 0xc0, 0x83, 0xe3, 0xd3, + 0x71, 0xb2, 0xf6, 0x9a, 0x59, 0x71, 0xa7, 0xe3, 0xc8, 0xd1, 0xf4, 0x35, 0x35, 0xac, 0x19, 0x27, + 0x0d, 0x8d, 0x3e, 0x5a, 0xa6, 0x0f, 0xb4, 0x04, 0xa3, 0x7c, 0x62, 0xc7, 0x54, 0x5a, 0xe0, 0xf0, + 0x94, 0x6b, 0x89, 0x45, 0x7f, 0x92, 0x85, 0x5a, 0xa2, 0x47, 0x98, 0x61, 0x25, 0x36, 0x00, 0x0a, + 0x23, 0xc8, 0xf7, 0x0d, 0x02, 0x24, 0x15, 0x75, 0x6d, 0x9e, 0xb2, 0x89, 0x79, 0x8a, 0x92, 0x1a, + 0x72, 0x7a, 0x52, 0xc3, 0x23, 0x28, 0xc7, 0x67, 0x9f, 0x93, 0x5d, 0x12, 0xed, 0xa9, 0xbc, 0xfa, + 0x98, 0x28, 0x4e, 0x83, 0x28, 0xe8, 0x69, 0x10, 0xdf, 0xd3, 0xa2, 0xe6, 0x0b, 0x58, 0x8d, 0x91, + 0x36, 0xa3, 0xbf, 0x94, 0x98, 0xb9, 0xf1, 0x11, 0x54, 0xb4, 0xce, 0xeb, 0xd1, 0xf1, 0x4c, 0x22, + 0x3a, 0x1e, 0x9d, 0x80, 0xc9, 0xc6, 0x27, 0x60, 0x8c, 0xdf, 0xce, 0x42, 0x4d, 0xac, 0x2f, 0xc7, + 0x3d, 0x3d, 0xf4, 0x46, 0xce, 0x00, 0xc3, 0x0a, 0xd1, 0x0a, 0x93, 0x8a, 0x96, 0x5a, 0x67, 0x72, + 0x89, 0x91, 0x9e, 0xa5, 0x1f, 0xf4, 0x23, 0x21, 0x1d, 0x1d, 0xf4, 0x33, 0xa0, 0x26, 0x04, 0xe3, + 0xb1, 0x1d, 0x70, 0xed, 0x64, 0xb6, 0x59, 0x39, 0xe1, 0x7c, 0xd3, 0x0e, 0x48, 0x42, 0x7e, 0x03, + 0x96, 0x05, 0x0d, 0x9e, 0x71, 0x1a, 0x3b, 0xa3, 0x91, 0x43, 0x94, 0xe4, 0x68, 0x6a, 0x9c, 0x70, + 0x6e, 0xda, 0x21, 0xdf, 0x17, 0x08, 0x79, 0x90, 0xbb, 0x34, 0x74, 0x02, 0xfb, 0x38, 0xce, 0x83, + 0x8b, 0x9e, 0x31, 0x18, 0x68, 0x5f, 0x6a, 0xc1, 0x40, 0x72, 0x40, 0x54, 0xc6, 0xf6, 0x65, 0x14, + 0x0c, 0x9c, 0xe1, 0xa4, 0xe2, 0x2c, 0x27, 0x19, 0xff, 0x21, 0x0b, 0x15, 0x8d, 0x2d, 0x5f, 0x65, + 0x77, 0xbd, 0x3d, 0x17, 0x06, 0x2a, 0xeb, 0x11, 0x9f, 0x37, 0x93, 0x4d, 0x62, 0xce, 0x00, 0x1d, + 0x19, 0xd7, 0x18, 0xf8, 0x16, 0x94, 0xc5, 0xaa, 0x7b, 0x1f, 0x1d, 0xa6, 0xf2, 0xc2, 0x03, 0x04, + 0x1c, 0x4e, 0x8f, 0x15, 0xf2, 0x31, 0x22, 0x0b, 0x31, 0xf2, 0xb1, 0x40, 0xbe, 0x28, 0xf9, 0xf5, + 0xdb, 0x50, 0x95, 0xb5, 0xe2, 0x3b, 0xc5, 0xe1, 0xc6, 0xab, 0x3e, 0xf1, 0xbe, 0xcd, 0x0a, 0x35, + 0x47, 0x2f, 0x5f, 0x16, 0x7c, 0xac, 0x0a, 0x96, 0x5e, 0x56, 0xf0, 0x31, 0x3d, 0x18, 0x3b, 0x51, + 0x3e, 0x31, 0xe6, 0xab, 0x28, 0x39, 0xf6, 0x10, 0x96, 0x95, 0xb8, 0x9a, 0xba, 0xb6, 0xeb, 0x7a, + 0x53, 0x77, 0xc0, 0xd5, 0xd1, 0x18, 0x26, 0x51, 0x47, 0x31, 0xc6, 0x18, 0x46, 0x67, 0x27, 0x29, + 0xef, 0xe5, 0x3e, 0x14, 0x48, 0x2f, 0x27, 0xe5, 0x23, 0x5d, 0x70, 0x11, 0x09, 0xbb, 0x07, 0x05, + 0x52, 0xcf, 0xb3, 0xd7, 0x0a, 0x1b, 0x22, 0x30, 0x5a, 0xc0, 0x44, 0xc1, 0x7d, 0x1e, 0xfa, 0xce, + 0x20, 0x88, 0x4f, 0xdd, 0x14, 0x84, 0xfd, 0x49, 0x6d, 0xc5, 0x69, 0xee, 0x31, 0x25, 0xda, 0xa8, + 0x44, 0x23, 0x36, 0xa6, 0xe5, 0x44, 0x1d, 0x52, 0x5d, 0x1a, 0xc1, 0xda, 0x31, 0x0f, 0x2f, 0x38, + 0x77, 0x5d, 0xa1, 0x0c, 0x0d, 0xb8, 0x1b, 0xfa, 0xf6, 0x48, 0xbc, 0x24, 0x1a, 0xc1, 0x93, 0xb9, + 0x5a, 0x63, 0x1f, 0xc8, 0x66, 0x5c, 0x70, 0x2b, 0x2a, 0x47, 0xb2, 0x63, 0xf5, 0x38, 0x0d, 0xb7, + 0xf1, 0x1b, 0xb0, 0x71, 0x7d, 0xa1, 0x94, 0xb3, 0x75, 0xf7, 0x92, 0x52, 0x25, 0x8a, 0x9a, 0x8d, + 0x3c, 0x3b, 0xa4, 0xde, 0xe8, 0x92, 0xa5, 0x0b, 0x15, 0x0d, 0x13, 0xef, 0xfd, 0x19, 0x54, 0xee, + 0xe8, 0x41, 0xec, 0x48, 0xae, 0xe7, 0x8f, 0xed, 0x91, 0xf3, 0x63, 0x3e, 0xb4, 0xe2, 0xda, 0x33, + 0xe6, 0x62, 0x0c, 0xc7, 0xc3, 0xc4, 0xc6, 0x03, 0x58, 0x44, 0xcd, 0x5e, 0xdb, 0xe8, 0x5e, 0xa4, + 0x0c, 0x1a, 0x2b, 0xc0, 0xba, 0x24, 0xbb, 0xf4, 0x34, 0xb8, 0xff, 0x9a, 0x83, 0x8a, 0x06, 0x16, + 0xbb, 0x11, 0x26, 0x4e, 0x59, 0x43, 0xc7, 0x1e, 0x73, 0x15, 0x12, 0xac, 0x99, 0x35, 0x84, 0x6e, + 0x4b, 0xa0, 0xd8, 0x8b, 0xed, 0xf3, 0x53, 0xcb, 0x9b, 0x86, 0xd6, 0x90, 0x9f, 0xfa, 0x5c, 0xf5, + 0xb2, 0x6a, 0x9f, 0x9f, 0x1e, 0x4c, 0xc3, 0x6d, 0x84, 0x09, 0x2a, 0x21, 0x4b, 0x34, 0x2a, 0x99, + 0xeb, 0x33, 0xb6, 0x2f, 0x63, 0x2a, 0x99, 0x70, 0x46, 0x9c, 0x99, 0x8f, 0x12, 0xce, 0xc8, 0x5a, + 0x9c, 0xdd, 0x40, 0x0b, 0xf3, 0x1b, 0xe8, 0xb7, 0x60, 0x8d, 0x36, 0x50, 0x29, 0x9a, 0xad, 0x99, + 0x95, 0xbc, 0x82, 0x58, 0x39, 0x48, 0x4d, 0xed, 0x6d, 0x88, 0x11, 0x28, 0xb1, 0x14, 0x38, 0x3f, + 0x26, 0x41, 0x96, 0x31, 0xc5, 0xc8, 0x64, 0xe5, 0x3d, 0xe7, 0xc7, 0x5c, 0x50, 0x62, 0x42, 0x83, + 0x4e, 0x29, 0x53, 0xdb, 0xc7, 0x8e, 0x3b, 0x4b, 0x69, 0x5f, 0x26, 0x29, 0xcb, 0x92, 0xd2, 0xbe, + 0xd4, 0x29, 0x9f, 0xc0, 0xfa, 0x98, 0x0f, 0x1d, 0x3b, 0x59, 0xad, 0x15, 0x2b, 0x6e, 0x2b, 0x84, + 0xd6, 0xca, 0xf4, 0xc8, 0x70, 0x17, 0xb3, 0xf1, 0x63, 0x6f, 0x7c, 0xec, 0x90, 0xce, 0x42, 0x29, + 0x16, 0x79, 0xb3, 0xee, 0x4e, 0xc7, 0x3f, 0x44, 0xb0, 0x28, 0x12, 0x18, 0x35, 0xa8, 0xf4, 0x42, + 0x6f, 0xa2, 0x5e, 0x73, 0x1d, 0xaa, 0xf4, 0x28, 0xcf, 0x9b, 0xdd, 0x82, 0x9b, 0x28, 0x12, 0xfa, + 0xde, 0xc4, 0x1b, 0x79, 0xa7, 0x57, 0x09, 0x3f, 0xde, 0x7f, 0xce, 0xc0, 0x72, 0x02, 0x2b, 0xc5, + 0xeb, 0xb7, 0x48, 0x9e, 0x45, 0x87, 0x86, 0x68, 0x0d, 0x2e, 0x69, 0x6b, 0x90, 0x08, 0x49, 0x98, + 0xa9, 0x83, 0x44, 0xad, 0xf8, 0xb0, 0xbb, 0x2a, 0x48, 0x22, 0xa5, 0x39, 0x2f, 0x52, 0x64, 0x79, + 0x75, 0x0c, 0x5e, 0x55, 0xf1, 0x2b, 0xf2, 0xf8, 0xc1, 0x50, 0x0e, 0x39, 0x97, 0x4c, 0xb0, 0xd6, + 0x7d, 0x7e, 0xaa, 0x07, 0xb1, 0x23, 0x30, 0x30, 0xfe, 0x65, 0x06, 0x20, 0xee, 0x1d, 0xa6, 0x78, + 0x47, 0x7a, 0x0b, 0xdd, 0x23, 0xa5, 0xe9, 0x28, 0x6f, 0x40, 0x35, 0xca, 0xf4, 0x8c, 0x35, 0xa1, + 0x8a, 0x82, 0x09, 0x75, 0xe8, 0x1d, 0x58, 0x3c, 0x1d, 0x79, 0xc7, 0xa8, 0xb1, 0x4a, 0xbd, 0x85, + 0x4e, 0xdd, 0xd5, 0x09, 0xac, 0xb4, 0x91, 0x58, 0x6f, 0xca, 0xa7, 0x26, 0x83, 0xea, 0x5a, 0x90, + 0xf1, 0x3b, 0xd9, 0x28, 0xe5, 0x2d, 0x9e, 0x89, 0x17, 0x9b, 0x77, 0x3f, 0x4f, 0xe6, 0xc4, 0x8b, + 0x82, 0x81, 0x1f, 0x41, 0xdd, 0xa7, 0x4d, 0x49, 0xed, 0x58, 0xf9, 0x17, 0xec, 0x58, 0x35, 0x3f, + 0xa1, 0xe9, 0xbc, 0x0b, 0x0d, 0x7b, 0x78, 0xce, 0xfd, 0xd0, 0x41, 0x6f, 0x3d, 0xea, 0xc7, 0x32, + 0xc9, 0x4c, 0x83, 0xa3, 0x22, 0xfa, 0x0e, 0x2c, 0xca, 0x33, 0x90, 0x11, 0xa5, 0xbc, 0x55, 0x25, + 0x06, 0x0b, 0x42, 0xe3, 0x5f, 0xab, 0x1c, 0xbb, 0xe4, 0xdb, 0x7d, 0xf1, 0xac, 0xe8, 0x23, 0xcc, + 0xce, 0x87, 0x3b, 0x25, 0x23, 0xc9, 0x20, 0x80, 0x94, 0x47, 0x04, 0x94, 0x21, 0x80, 0xe4, 0xb4, + 0xe6, 0x5f, 0x65, 0x5a, 0x8d, 0x3f, 0xcb, 0x40, 0x71, 0xd7, 0x9b, 0xec, 0x3a, 0x94, 0xe4, 0x8c, + 0xcb, 0x24, 0x8a, 0x51, 0x2d, 0x88, 0xc7, 0xce, 0xf0, 0xc5, 0x47, 0x7d, 0x52, 0xd5, 0xbc, 0x5a, + 0x52, 0xcd, 0xfb, 0x1e, 0xdc, 0xc2, 0x10, 0xa0, 0xef, 0x4d, 0x3c, 0x5f, 0x2c, 0x55, 0x7b, 0x44, + 0xea, 0x9e, 0xe7, 0x86, 0x67, 0x4a, 0x76, 0xde, 0x3c, 0xe1, 0xfc, 0x50, 0xa3, 0xd8, 0x8f, 0x08, + 0xf0, 0x30, 0xdd, 0x28, 0x3c, 0xb7, 0xc8, 0x42, 0x97, 0xfa, 0x28, 0x49, 0xd4, 0x45, 0x81, 0x68, + 0x23, 0x1c, 0x35, 0x52, 0xe3, 0x3b, 0x50, 0x8e, 0x9c, 0x3d, 0xec, 0x3d, 0x28, 0x9f, 0x79, 0x13, + 0xe9, 0x11, 0xca, 0x24, 0x8e, 0x43, 0xc9, 0x51, 0x9b, 0xa5, 0x33, 0xfa, 0x11, 0x18, 0x7f, 0x59, + 0x84, 0x62, 0xc7, 0x3d, 0xf7, 0x9c, 0x01, 0x66, 0xe9, 0x8d, 0xf9, 0xd8, 0x53, 0x07, 0xb1, 0xc5, + 0x6f, 0xcc, 0xc4, 0x89, 0xef, 0x46, 0xc9, 0xc9, 0x4c, 0x9c, 0xe8, 0x56, 0x94, 0x55, 0x58, 0xf0, + 0xf5, 0xcb, 0x4d, 0x0a, 0x3e, 0xe6, 0x0d, 0x47, 0xfb, 0x65, 0x41, 0x3b, 0xc8, 0x2e, 0xea, 0xa2, + 0x4b, 0x37, 0x70, 0xca, 0xe8, 0x60, 0x5c, 0x19, 0x21, 0x38, 0x61, 0xaf, 0x41, 0x51, 0x9e, 0x3e, + 0xa2, 0xb3, 0x1c, 0x94, 0xe8, 0x2b, 0x41, 0xc8, 0x0d, 0x3e, 0xa7, 0x10, 0x6e, 0xa4, 0xc8, 0xe6, + 0xcc, 0xaa, 0x02, 0x6e, 0x0b, 0x5e, 0xbb, 0x03, 0x15, 0xa2, 0x27, 0x92, 0x92, 0xcc, 0xab, 0x43, + 0x10, 0x12, 0xa4, 0xdc, 0x11, 0x54, 0x4e, 0xbd, 0x23, 0x08, 0xd3, 0x30, 0x23, 0x29, 0x4b, 0x43, + 0x04, 0xba, 0x19, 0x46, 0x83, 0xab, 0x0b, 0xb2, 0xa4, 0x4f, 0x85, 0xce, 0x89, 0x2a, 0x9f, 0xca, + 0x9b, 0x50, 0x3b, 0xb1, 0x47, 0xa3, 0x63, 0x7b, 0xf0, 0x9c, 0x5c, 0x01, 0x55, 0xf2, 0x7e, 0x2a, + 0x20, 0xfa, 0x02, 0xee, 0x40, 0x45, 0x7b, 0xcb, 0x98, 0x34, 0x97, 0x37, 0x21, 0x7e, 0xbf, 0xb3, + 0x1e, 0xbe, 0xfa, 0x2b, 0x78, 0xf8, 0xb4, 0xe4, 0xc1, 0xc5, 0x64, 0xf2, 0xe0, 0x2d, 0x94, 0xa6, + 0x32, 0xc1, 0xac, 0x41, 0xd7, 0x90, 0xd8, 0xc3, 0x21, 0x26, 0x98, 0xd1, 0x9d, 0x7f, 0x38, 0x79, + 0x84, 0x5f, 0x22, 0x5b, 0x82, 0x60, 0x44, 0x72, 0x9b, 0xdc, 0xd4, 0x13, 0xdb, 0x19, 0x62, 0xb2, + 0x36, 0x79, 0x0f, 0x8a, 0xf6, 0x38, 0x3c, 0xb4, 0x9d, 0x21, 0xbb, 0x0b, 0x55, 0x85, 0xc6, 0xdd, + 0x71, 0x99, 0xe6, 0x5f, 0xa2, 0xc5, 0x9e, 0x68, 0x40, 0x2d, 0xa2, 0x18, 0xc7, 0x87, 0x3d, 0x2b, + 0x92, 0x04, 0xf9, 0xe0, 0x7d, 0xcc, 0xc9, 0x09, 0x39, 0x1e, 0xe9, 0xac, 0x3f, 0xbe, 0x25, 0xc7, + 0x2a, 0xb9, 0x54, 0xfd, 0xa7, 0xe0, 0x18, 0x51, 0x0a, 0xe5, 0x8e, 0x62, 0x74, 0x6b, 0x09, 0xfd, + 0x57, 0x92, 0x62, 0x8c, 0x8e, 0x08, 0xd8, 0x77, 0x34, 0xfb, 0xb5, 0x89, 0xc4, 0xaf, 0xcd, 0xd4, + 0x7f, 0xdd, 0x59, 0x95, 0xdb, 0x00, 0x4e, 0x20, 0x76, 0x99, 0x80, 0xbb, 0x43, 0x3c, 0x9d, 0x59, + 0x32, 0xcb, 0x4e, 0xf0, 0x8c, 0x00, 0x5f, 0xad, 0x61, 0xdb, 0x82, 0xaa, 0x3e, 0x4c, 0x56, 0x82, + 0xfc, 0xc1, 0x61, 0xbb, 0xdb, 0xb8, 0xc1, 0x2a, 0x50, 0xec, 0xb5, 0xfb, 0xfd, 0x3d, 0x8c, 0xf4, + 0x55, 0xa1, 0x14, 0x1d, 0x0d, 0xcb, 0x8a, 0xa7, 0xd6, 0xd6, 0x56, 0xfb, 0xb0, 0xdf, 0xde, 0x6e, + 0xe4, 0x7e, 0x90, 0x2f, 0x65, 0x1b, 0x39, 0xe3, 0xaf, 0x72, 0x50, 0xd1, 0x66, 0xe1, 0xc5, 0xc2, + 0xf8, 0x36, 0x00, 0x5a, 0x92, 0x71, 0xfe, 0x61, 0xde, 0x2c, 0x0b, 0x08, 0xbd, 0x7c, 0x3d, 0x46, + 0x91, 0xa3, 0xfb, 0x6d, 0x54, 0x8c, 0xe2, 0x4d, 0xa8, 0xd1, 0x55, 0x31, 0x7a, 0xbc, 0xb6, 0x60, + 0x56, 0x09, 0x28, 0x45, 0x35, 0x9e, 0x2d, 0x45, 0x22, 0x3c, 0x75, 0x24, 0x2f, 0x8e, 0x20, 0x10, + 0x9e, 0x3b, 0xc2, 0x43, 0x63, 0x81, 0x37, 0x3a, 0xe7, 0x44, 0x41, 0x1a, 0x61, 0x45, 0xc2, 0xfa, + 0xf2, 0x94, 0xac, 0x94, 0x87, 0xda, 0xe1, 0xc6, 0x82, 0x59, 0x25, 0xa0, 0x6c, 0xe8, 0x1b, 0x8a, + 0x81, 0x4a, 0xc8, 0x40, 0xeb, 0xf3, 0xdc, 0x90, 0x60, 0x9e, 0xbd, 0x39, 0x37, 0x62, 0x19, 0x19, + 0xe3, 0x6b, 0xf3, 0xe5, 0x5e, 0xee, 0x4e, 0x64, 0xef, 0x01, 0x1b, 0x4f, 0x26, 0x56, 0x8a, 0x83, + 0x2f, 0x6f, 0x2e, 0x8e, 0x27, 0x93, 0xbe, 0xe6, 0xff, 0xfa, 0x0a, 0x7c, 0x8f, 0x9f, 0x03, 0x6b, + 0x89, 0x05, 0x8c, 0x5d, 0x8c, 0x4c, 0xb1, 0x58, 0x2c, 0x67, 0x74, 0xb1, 0x9c, 0x22, 0xfd, 0xb2, + 0xa9, 0xd2, 0xef, 0x45, 0x72, 0xc2, 0xd8, 0x81, 0xca, 0xa1, 0x76, 0x11, 0xd5, 0x5d, 0xb1, 0x43, + 0xa8, 0x2b, 0xa8, 0x68, 0xef, 0x20, 0x9f, 0xa2, 0x2f, 0x6f, 0x9e, 0xd2, 0x7a, 0x93, 0xd5, 0x7a, + 0x63, 0xfc, 0x8b, 0x0c, 0x5d, 0xf2, 0x11, 0x75, 0x3e, 0xbe, 0xfb, 0x4a, 0x85, 0xdf, 0xe2, 0x33, + 0xc8, 0x15, 0x15, 0x76, 0x93, 0xc7, 0x87, 0xb1, 0x6b, 0x96, 0x77, 0x72, 0x12, 0x70, 0x95, 0xe3, + 0x51, 0x41, 0xd8, 0x01, 0x82, 0x94, 0xf2, 0x2d, 0x34, 0x7c, 0x87, 0xea, 0x0f, 0x64, 0x62, 0x87, + 0x50, 0xbe, 0xf7, 0xed, 0x4b, 0xd9, 0x6a, 0x20, 0x54, 0x10, 0x19, 0x1f, 0x50, 0x67, 0x08, 0xa3, + 0x67, 0xe3, 0x9f, 0xca, 0x63, 0xd2, 0xb3, 0xf3, 0x7b, 0x1f, 0x4a, 0x51, 0xad, 0xc9, 0x1d, 0x56, + 0x51, 0x46, 0x78, 0xb1, 0x8f, 0xa3, 0x33, 0x24, 0xd1, 0x63, 0x5a, 0x5c, 0x18, 0xe3, 0xe9, 0x68, + 0xbd, 0xfe, 0x3a, 0xb0, 0x13, 0xc7, 0x9f, 0x25, 0xa6, 0xc5, 0xd6, 0x40, 0x8c, 0x46, 0x6d, 0x1c, + 0xc1, 0xb2, 0x92, 0x12, 0x9a, 0x45, 0x90, 0x7c, 0x79, 0x99, 0x97, 0x08, 0xf9, 0xec, 0x9c, 0x90, + 0x37, 0x7e, 0x9a, 0x87, 0xa2, 0xba, 0xd4, 0x2d, 0xed, 0x22, 0xb2, 0x72, 0xf2, 0x22, 0xb2, 0x66, + 0xe2, 0xd2, 0x1a, 0x7c, 0xf5, 0x72, 0xbf, 0x7f, 0x67, 0x76, 0xcb, 0xd6, 0x62, 0x15, 0x89, 0x6d, + 0x7b, 0x0d, 0xf2, 0x13, 0x3b, 0x3c, 0x43, 0xbf, 0x24, 0x31, 0x0f, 0x3e, 0xab, 0x18, 0x46, 0x21, + 0x19, 0xc3, 0x48, 0xbb, 0xb4, 0x8d, 0x54, 0xd2, 0xb9, 0x4b, 0xdb, 0x6e, 0x01, 0xe9, 0x17, 0x5a, + 0x8a, 0x5a, 0x09, 0x01, 0x62, 0x2f, 0x4a, 0xaa, 0x23, 0xa5, 0x59, 0x75, 0xe4, 0x95, 0x55, 0x85, + 0x6f, 0xc1, 0x02, 0x5d, 0x78, 0x20, 0xcf, 0x4a, 0xaa, 0x0d, 0x45, 0xce, 0xa1, 0xfa, 0x4f, 0xc9, + 0xeb, 0xa6, 0xa4, 0xd5, 0x6f, 0x40, 0xaa, 0x24, 0x6e, 0x40, 0xd2, 0x63, 0x2b, 0xd5, 0x64, 0x6c, + 0xe5, 0x1e, 0x34, 0xa2, 0x09, 0x45, 0x4f, 0xa5, 0x1b, 0xc8, 0x93, 0x58, 0x75, 0x05, 0x17, 0x52, + 0xb2, 0x1b, 0xc4, 0x1b, 0x62, 0x3d, 0xb1, 0x21, 0x0a, 0x19, 0xd6, 0x0a, 0x43, 0x3e, 0x9e, 0x84, + 0x72, 0x43, 0xc4, 0xb3, 0x1a, 0x7a, 0x07, 0x93, 0xa7, 0x88, 0x6b, 0x50, 0xee, 0x74, 0xad, 0x9d, + 0xbd, 0xce, 0xd3, 0xdd, 0x7e, 0x23, 0x23, 0x1e, 0x7b, 0x47, 0x5b, 0x5b, 0xed, 0xf6, 0x36, 0xee, + 0x38, 0x00, 0x0b, 0x3b, 0xad, 0x8e, 0xd8, 0x7d, 0x72, 0xc6, 0xef, 0x65, 0xa1, 0xa2, 0x55, 0xcf, + 0x9e, 0x44, 0xb3, 0x42, 0x97, 0xe4, 0xdc, 0x9e, 0xef, 0xc2, 0x03, 0x25, 0x8a, 0xb5, 0x69, 0x89, + 0xae, 0xa8, 0xcb, 0x5e, 0x7b, 0x45, 0x1d, 0x7b, 0x1b, 0x16, 0x6d, 0xaa, 0x21, 0x9a, 0x05, 0xe9, + 0x85, 0x97, 0x60, 0x39, 0x09, 0x98, 0x98, 0x19, 0xef, 0x27, 0x82, 0x2e, 0xaf, 0x72, 0x21, 0xa3, + 0x2d, 0x05, 0x27, 0xab, 0x78, 0x62, 0x3b, 0xa3, 0xa9, 0xcf, 0x65, 0xd4, 0x3c, 0xda, 0x99, 0x09, + 0x6a, 0x2a, 0xb4, 0xf1, 0x01, 0x40, 0xdc, 0xe7, 0xe4, 0xe4, 0xdc, 0x48, 0x4e, 0x4e, 0x46, 0x9b, + 0x9c, 0xac, 0xb1, 0x4d, 0x62, 0x44, 0x4e, 0x74, 0xe4, 0x76, 0xfb, 0x06, 0x28, 0x47, 0xa0, 0x85, + 0xe9, 0xd1, 0x93, 0x11, 0x0f, 0xd5, 0x79, 0xeb, 0x25, 0x89, 0xe9, 0x44, 0x08, 0x75, 0xfd, 0x41, + 0x5c, 0x4b, 0x2c, 0x8d, 0x24, 0x4b, 0xce, 0x4a, 0x23, 0x49, 0x6a, 0x46, 0x78, 0x63, 0x03, 0x9a, + 0xdb, 0x5c, 0xd4, 0xd6, 0x1a, 0x8d, 0x66, 0xba, 0x63, 0xdc, 0x82, 0x9b, 0x29, 0x38, 0xe9, 0x84, + 0xf8, 0x18, 0x56, 0x5b, 0x74, 0xb4, 0xfa, 0xab, 0x3a, 0x43, 0x65, 0x34, 0x61, 0x6d, 0xb6, 0x4a, + 0xd9, 0xd8, 0x0e, 0x2c, 0x6d, 0xf3, 0xe3, 0xe9, 0xe9, 0x1e, 0x3f, 0x8f, 0x1b, 0x62, 0x90, 0x0f, + 0xce, 0xbc, 0x0b, 0x39, 0x3f, 0xf8, 0x1b, 0xb3, 0x0c, 0x05, 0x8d, 0x15, 0x4c, 0xf8, 0x40, 0x39, + 0xa2, 0x11, 0xd2, 0x9b, 0xf0, 0x81, 0xf1, 0x04, 0x98, 0x5e, 0x8f, 0x9c, 0x2f, 0x61, 0x25, 0x4c, + 0x8f, 0xad, 0xe0, 0x2a, 0x08, 0xf9, 0x58, 0xdd, 0xc1, 0x04, 0xc1, 0xf4, 0xb8, 0x47, 0x10, 0xe3, + 0x1d, 0xa8, 0x1e, 0xda, 0x57, 0x26, 0xff, 0x5c, 0x9e, 0x0e, 0x5a, 0x87, 0xe2, 0xc4, 0xbe, 0x12, + 0x62, 0x20, 0x8a, 0x49, 0x21, 0xda, 0xf8, 0xe3, 0x3c, 0x2c, 0x10, 0x25, 0xbb, 0x4b, 0xd7, 0xa4, + 0x3a, 0x2e, 0x2e, 0x43, 0x25, 0x28, 0x35, 0xd0, 0x9c, 0x2c, 0xcd, 0xce, 0xcb, 0x52, 0xe9, 0x40, + 0x53, 0xd7, 0xc3, 0xa8, 0xe8, 0x81, 0x3b, 0x1d, 0xab, 0x3b, 0x61, 0x92, 0xe7, 0x8b, 0xf3, 0xf1, + 0x35, 0xb8, 0x74, 0xf8, 0x32, 0x19, 0xdf, 0x8d, 0x6d, 0x11, 0xea, 0x9d, 0xda, 0x22, 0xa4, 0xb8, + 0xd4, 0x41, 0xa9, 0x06, 0x4f, 0x51, 0x9d, 0x3b, 0x4b, 0x1a, 0x3c, 0x73, 0x86, 0x4d, 0xe9, 0xe5, + 0x86, 0x0d, 0x79, 0xd6, 0x5e, 0x60, 0xd8, 0xc0, 0x2b, 0x18, 0x36, 0xaf, 0x10, 0x5b, 0xbd, 0x09, + 0x25, 0xdc, 0xf7, 0x35, 0xe9, 0x29, 0xf6, 0x7b, 0x21, 0x3d, 0xbf, 0xad, 0xa9, 0xfe, 0x94, 0xd8, + 0x71, 0x2b, 0x5e, 0x26, 0x26, 0xff, 0xfc, 0x97, 0x13, 0xb3, 0xfa, 0x0c, 0x8a, 0x12, 0x2a, 0x18, + 0xda, 0xb5, 0xc7, 0xea, 0x86, 0x2d, 0xfc, 0x2d, 0xa6, 0x0d, 0xaf, 0x05, 0xfa, 0x7c, 0xea, 0xf8, + 0x7c, 0xa8, 0xae, 0x4e, 0x71, 0x70, 0x8d, 0x0a, 0x88, 0x18, 0xa0, 0x30, 0x43, 0x5c, 0xef, 0xc2, + 0x95, 0x17, 0x27, 0x14, 0x9d, 0xe0, 0x99, 0x78, 0x34, 0x18, 0x34, 0xf0, 0x8e, 0xbd, 0x89, 0xe7, + 0xab, 0xcd, 0xc9, 0xf8, 0x69, 0x06, 0x1a, 0x72, 0x75, 0x45, 0x38, 0xdd, 0x0a, 0x28, 0x5c, 0x97, + 0x87, 0xf0, 0xe2, 0x8b, 0x50, 0x0c, 0xa8, 0xa1, 0xf3, 0x23, 0xda, 0xa9, 0xc8, 0x79, 0x53, 0x11, + 0xc0, 0x1d, 0xb9, 0x5b, 0xbd, 0x0e, 0x15, 0x95, 0x03, 0x3d, 0x76, 0x46, 0xea, 0xc6, 0x6b, 0x4a, + 0x82, 0xde, 0x77, 0x46, 0x6a, 0xa3, 0xf3, 0x6d, 0x79, 0x0e, 0x32, 0x83, 0x1b, 0x9d, 0x69, 0x87, + 0xdc, 0xf8, 0xb7, 0x19, 0x58, 0xd2, 0x86, 0x22, 0xd7, 0xed, 0x87, 0x50, 0x8d, 0x2e, 0xb7, 0xe4, + 0x91, 0xe6, 0xb5, 0x9e, 0x14, 0x34, 0x71, 0xb1, 0xca, 0x20, 0x82, 0x04, 0xa2, 0x33, 0x43, 0xfb, + 0x8a, 0x12, 0x75, 0xa7, 0x63, 0x65, 0xdc, 0x0c, 0xed, 0xab, 0x1d, 0xce, 0x7b, 0xd3, 0xb1, 0x30, + 0x5d, 0x2f, 0x38, 0x7f, 0x1e, 0x11, 0x90, 0xce, 0x05, 0x02, 0x26, 0x29, 0x0c, 0xa8, 0x8d, 0x3d, + 0x37, 0x3c, 0x8b, 0x48, 0xa4, 0xd6, 0x89, 0x40, 0xa2, 0x31, 0xfe, 0x22, 0x0b, 0xcb, 0xe4, 0x62, + 0x93, 0xae, 0x4d, 0x29, 0xba, 0x9a, 0xb0, 0x40, 0xde, 0x46, 0x12, 0x5e, 0xbb, 0x37, 0x4c, 0xf9, + 0xcc, 0xbe, 0xf5, 0x8a, 0x6e, 0x41, 0x75, 0xd4, 0xf2, 0x9a, 0xe9, 0xcf, 0xcd, 0x4f, 0xff, 0xf5, + 0xd3, 0x9b, 0x16, 0xe8, 0x2c, 0xa4, 0x05, 0x3a, 0x5f, 0x25, 0xbc, 0x38, 0x77, 0x1e, 0xb1, 0x28, + 0x69, 0xb4, 0xf3, 0x88, 0x4f, 0x60, 0x3d, 0x41, 0x83, 0xd2, 0xda, 0x39, 0x71, 0xb8, 0xba, 0x97, + 0x62, 0x45, 0xa3, 0xee, 0x29, 0xdc, 0x66, 0x11, 0x0a, 0xc1, 0xc0, 0x9b, 0x70, 0x63, 0x0d, 0x56, + 0x92, 0xb3, 0x2a, 0xb7, 0x89, 0xdf, 0xcf, 0x40, 0x53, 0xa6, 0xa5, 0x38, 0xee, 0xe9, 0xae, 0x13, + 0x84, 0x9e, 0x1f, 0x5d, 0x02, 0x79, 0x1b, 0x20, 0x08, 0x6d, 0x5f, 0x5a, 0x9b, 0xf2, 0x26, 0x06, + 0x84, 0xa0, 0x25, 0x79, 0x13, 0x4a, 0xdc, 0x1d, 0x12, 0x92, 0xb8, 0xa1, 0xc8, 0xdd, 0xa1, 0xb2, + 0x43, 0xe7, 0xf4, 0xef, 0x5a, 0xd2, 0xbc, 0x90, 0x07, 0xa3, 0xc5, 0xec, 0xf0, 0x73, 0xdc, 0x78, + 0xf3, 0xd1, 0xc1, 0xe8, 0x7d, 0xfb, 0x12, 0x93, 0x3c, 0x03, 0xe3, 0x1f, 0x65, 0x61, 0x31, 0xee, + 0x1f, 0xdd, 0xaa, 0xf0, 0xe2, 0xfb, 0x21, 0xee, 0x4a, 0x76, 0x70, 0x84, 0xfe, 0xae, 0x39, 0x1e, + 0x4b, 0xb4, 0x38, 0x3b, 0x2e, 0x33, 0xa0, 0xa2, 0x28, 0xbc, 0x69, 0xa8, 0xdd, 0xc5, 0x56, 0x26, + 0x92, 0x83, 0x69, 0x28, 0x0c, 0x2e, 0x61, 0x79, 0x3a, 0xae, 0x34, 0x79, 0x0a, 0xf6, 0x38, 0xec, + 0xe0, 0x15, 0xef, 0x02, 0x2c, 0x8a, 0xd1, 0x8b, 0x14, 0x54, 0x82, 0xbe, 0x41, 0x7a, 0x36, 0xbd, + 0x39, 0xd4, 0xb1, 0x75, 0x25, 0x94, 0x6e, 0xbb, 0x8d, 0x94, 0xd0, 0xd7, 0xa1, 0x42, 0x95, 0xc7, + 0xc7, 0x4f, 0xf3, 0x66, 0x19, 0x5b, 0x40, 0xbc, 0x74, 0x02, 0x79, 0xd3, 0x84, 0xe9, 0x0b, 0xd4, + 0x14, 0x66, 0x7d, 0xfc, 0xbd, 0x0c, 0xdc, 0x4c, 0x79, 0x6d, 0x72, 0x95, 0x6f, 0xc1, 0xd2, 0x49, + 0x84, 0x54, 0xb3, 0x4b, 0x4b, 0x7d, 0x4d, 0x89, 0xd5, 0xe4, 0x9c, 0x9a, 0x8d, 0x93, 0x24, 0x20, + 0x36, 0xba, 0xe8, 0x0d, 0x26, 0x4e, 0x18, 0xa3, 0xd1, 0x45, 0xaf, 0x91, 0xec, 0x9d, 0x43, 0xd8, + 0x68, 0x5f, 0x0a, 0x89, 0xb1, 0xa5, 0x7f, 0xa3, 0x40, 0xb1, 0x51, 0xd2, 0xc1, 0x9c, 0x79, 0x25, + 0x07, 0xf3, 0x90, 0x0e, 0x52, 0x46, 0x75, 0xfd, 0x3c, 0x95, 0xe0, 0x06, 0x2a, 0xca, 0xd0, 0x37, + 0x16, 0xd4, 0x29, 0xe7, 0x41, 0xf4, 0x6d, 0x05, 0x23, 0x80, 0xc5, 0xfd, 0xe9, 0x28, 0x74, 0xe2, + 0xcf, 0x2d, 0xb0, 0x6f, 0xc9, 0x32, 0xd8, 0x8e, 0x9a, 0xb5, 0xd4, 0x86, 0x20, 0x6a, 0x08, 0x27, + 0x6b, 0x2c, 0x2a, 0xb2, 0xe6, 0xdb, 0x5b, 0x1c, 0x27, 0x5b, 0x30, 0x6e, 0xc2, 0x7a, 0xfc, 0x44, + 0xd3, 0xa6, 0xb6, 0x9a, 0x7f, 0x9e, 0xa1, 0x8c, 0xf2, 0xe4, 0xa7, 0x1f, 0x58, 0x1b, 0x96, 0x03, + 0xc7, 0x3d, 0x1d, 0x71, 0xbd, 0xfa, 0x40, 0x4e, 0xc2, 0x6a, 0xb2, 0x6f, 0xf2, 0xf3, 0x10, 0xe6, + 0x12, 0x95, 0x88, 0x6b, 0x0b, 0xd8, 0xe6, 0x75, 0x9d, 0x8c, 0xd9, 0x62, 0x66, 0x36, 0xe6, 0x3b, + 0xdf, 0x81, 0x7a, 0xb2, 0x21, 0xf6, 0x6d, 0x79, 0x88, 0x38, 0xee, 0x55, 0x6e, 0xe6, 0xb8, 0x67, + 0xcc, 0x10, 0x95, 0x78, 0xee, 0x03, 0xe3, 0x1f, 0x64, 0xa0, 0x69, 0x72, 0xc1, 0xb9, 0x5a, 0x2f, + 0x15, 0xcf, 0x7c, 0x38, 0x57, 0xeb, 0xf5, 0x63, 0x55, 0x67, 0x93, 0x55, 0x8f, 0xbe, 0x7e, 0xed, + 0xcb, 0xd8, 0xbd, 0x31, 0x37, 0xa2, 0xcd, 0x12, 0x2c, 0x10, 0x89, 0xb1, 0x0e, 0xab, 0xb2, 0x3f, + 0xaa, 0x2f, 0x71, 0xf4, 0x30, 0xd1, 0x62, 0x22, 0x7a, 0xb8, 0x01, 0x4d, 0xba, 0xcb, 0x53, 0x1f, + 0x84, 0x2c, 0xb8, 0x0d, 0x6c, 0xdf, 0x1e, 0xd8, 0xbe, 0xe7, 0xb9, 0x87, 0xdc, 0x97, 0xf9, 0xb9, + 0xa8, 0x61, 0x62, 0x70, 0x4d, 0xa9, 0xc2, 0xf4, 0xa4, 0x6e, 0xa0, 0xf4, 0x5c, 0x95, 0x8e, 0x44, + 0x4f, 0x86, 0x09, 0xcb, 0x9b, 0xf6, 0x73, 0xae, 0x6a, 0x52, 0x53, 0xf4, 0x11, 0x54, 0x26, 0x51, + 0xa5, 0x6a, 0xde, 0xd5, 0x4d, 0x03, 0xf3, 0xcd, 0x9a, 0x3a, 0xb5, 0xf1, 0x18, 0x56, 0x92, 0x75, + 0x4a, 0xd1, 0xb1, 0x01, 0xa5, 0xb1, 0x84, 0xc9, 0xde, 0x45, 0xcf, 0xc6, 0xef, 0x96, 0xa0, 0x28, + 0xed, 0x39, 0xf6, 0x00, 0xf2, 0x03, 0x95, 0x12, 0x16, 0x5f, 0x60, 0x23, 0xb1, 0xea, 0xff, 0x16, + 0x26, 0x86, 0x09, 0x3a, 0xf6, 0x11, 0xd4, 0x93, 0x51, 0xd1, 0x99, 0x63, 0xcc, 0xc9, 0x70, 0x66, + 0x6d, 0x30, 0x13, 0xff, 0x2a, 0xc7, 0x9b, 0x23, 0xe9, 0x0c, 0xa5, 0x33, 0x6d, 0xf7, 0xf4, 0x5c, + 0xa1, 0x6f, 0x07, 0x67, 0xb6, 0xf5, 0xf8, 0xc9, 0x07, 0xf2, 0x1c, 0x73, 0x05, 0x81, 0xbd, 0x33, + 0xfb, 0xf1, 0x93, 0x0f, 0x66, 0x35, 0x69, 0x79, 0x8a, 0x59, 0xd3, 0xa4, 0x57, 0xa0, 0x40, 0x57, + 0x2d, 0x52, 0x6e, 0x0f, 0x3d, 0xb0, 0x47, 0xb0, 0x22, 0xcd, 0x56, 0x4b, 0x66, 0x61, 0x93, 0x14, + 0x2c, 0xd1, 0xc1, 0x37, 0x89, 0xeb, 0x21, 0x8a, 0x7c, 0x43, 0x6b, 0xb0, 0x70, 0x16, 0xdf, 0x9b, + 0x59, 0x33, 0xe5, 0x93, 0xf1, 0x17, 0x05, 0xa8, 0x68, 0x93, 0xc2, 0xaa, 0x50, 0x32, 0xdb, 0xbd, + 0xb6, 0xf9, 0x49, 0x7b, 0xbb, 0x71, 0x83, 0xdd, 0x83, 0xb7, 0x3a, 0xdd, 0xad, 0x03, 0xd3, 0x6c, + 0x6f, 0xf5, 0xad, 0x03, 0xd3, 0x52, 0xd7, 0x28, 0x1d, 0xb6, 0x3e, 0xdb, 0x6f, 0x77, 0xfb, 0xd6, + 0x76, 0xbb, 0xdf, 0xea, 0xec, 0xf5, 0x1a, 0x19, 0xf6, 0x1a, 0x34, 0x63, 0x4a, 0x85, 0x6e, 0xed, + 0x1f, 0x1c, 0x75, 0xfb, 0x8d, 0x2c, 0xbb, 0x03, 0xb7, 0x76, 0x3a, 0xdd, 0xd6, 0x9e, 0x15, 0xd3, + 0x6c, 0xed, 0xf5, 0x3f, 0xb1, 0xda, 0xbf, 0x76, 0xd8, 0x31, 0x3f, 0x6b, 0xe4, 0xd2, 0x08, 0x84, + 0x31, 0xae, 0x6a, 0xc8, 0xb3, 0x9b, 0xb0, 0x4a, 0x04, 0x54, 0xc4, 0xea, 0x1f, 0x1c, 0x58, 0xbd, + 0x83, 0x83, 0x6e, 0xa3, 0xc0, 0x96, 0xa0, 0xd6, 0xe9, 0x7e, 0xd2, 0xda, 0xeb, 0x6c, 0x5b, 0x66, + 0xbb, 0xb5, 0xb7, 0xdf, 0x58, 0x60, 0xcb, 0xb0, 0x38, 0x4b, 0x57, 0x14, 0x55, 0x28, 0xba, 0x83, + 0x6e, 0xe7, 0xa0, 0x6b, 0x7d, 0xd2, 0x36, 0x7b, 0x9d, 0x83, 0x6e, 0xa3, 0xc4, 0xd6, 0x80, 0x25, + 0x51, 0xbb, 0xfb, 0xad, 0xad, 0x46, 0x99, 0xad, 0xc2, 0x52, 0x12, 0xfe, 0xac, 0xfd, 0x59, 0x03, + 0x58, 0x13, 0x56, 0xa8, 0x63, 0xd6, 0x66, 0x7b, 0xef, 0xe0, 0x53, 0x6b, 0xbf, 0xd3, 0xed, 0xec, + 0x1f, 0xed, 0x37, 0x2a, 0x78, 0xb1, 0x5b, 0xbb, 0x6d, 0x75, 0xba, 0xbd, 0xa3, 0x9d, 0x9d, 0xce, + 0x56, 0xa7, 0xdd, 0xed, 0x37, 0xaa, 0xd4, 0x72, 0xda, 0xc0, 0x6b, 0xa2, 0x80, 0x3c, 0xaa, 0x61, + 0x6d, 0x77, 0x7a, 0xad, 0xcd, 0xbd, 0xf6, 0x76, 0xa3, 0xce, 0x6e, 0xc3, 0xcd, 0x7e, 0x7b, 0xff, + 0xf0, 0xc0, 0x6c, 0x99, 0x9f, 0xa9, 0xa3, 0x1c, 0xd6, 0x4e, 0xab, 0xb3, 0x77, 0x64, 0xb6, 0x1b, + 0x8b, 0xec, 0x0d, 0xb8, 0x6d, 0xb6, 0x3f, 0x3e, 0xea, 0x98, 0xed, 0x6d, 0xab, 0x7b, 0xb0, 0xdd, + 0xb6, 0x76, 0xda, 0xad, 0xfe, 0x91, 0xd9, 0xb6, 0xf6, 0x3b, 0xbd, 0x5e, 0xa7, 0xfb, 0xb4, 0xd1, + 0x60, 0x6f, 0xc1, 0xdd, 0x88, 0x24, 0xaa, 0x60, 0x86, 0x6a, 0x49, 0x8c, 0x4f, 0xbd, 0xd2, 0x6e, + 0xfb, 0xd7, 0xfa, 0xd6, 0x61, 0xbb, 0x6d, 0x36, 0x18, 0xdb, 0x80, 0xb5, 0xb8, 0x79, 0x6a, 0x40, + 0xb6, 0xbd, 0x2c, 0x70, 0x87, 0x6d, 0x73, 0xbf, 0xd5, 0x15, 0x2f, 0x38, 0x81, 0x5b, 0x11, 0xdd, + 0x8e, 0x71, 0xb3, 0xdd, 0x5e, 0x65, 0x0c, 0xea, 0xda, 0x5b, 0xd9, 0x69, 0x99, 0x8d, 0x35, 0xb6, + 0x08, 0x95, 0xfd, 0xc3, 0x43, 0xab, 0xdf, 0xd9, 0x6f, 0x1f, 0x1c, 0xf5, 0x1b, 0xeb, 0x6c, 0x15, + 0x1a, 0x9d, 0x6e, 0xbf, 0x6d, 0x8a, 0x77, 0xad, 0x8a, 0xfe, 0xaf, 0x22, 0x5b, 0x81, 0x45, 0xd5, + 0x53, 0x05, 0xfd, 0x59, 0x91, 0xad, 0x03, 0x3b, 0xea, 0x9a, 0xed, 0xd6, 0xb6, 0x98, 0xb8, 0x08, + 0xf1, 0xbf, 0x8b, 0x32, 0x42, 0xf2, 0xd3, 0x5c, 0xb4, 0x59, 0xc7, 0x29, 0x07, 0xc9, 0x5b, 0x94, + 0xab, 0xda, 0xed, 0xc7, 0x2f, 0xfb, 0xbe, 0x81, 0x66, 0x5a, 0xe5, 0xe6, 0x4c, 0xab, 0x39, 0xdb, + 0xbd, 0xa6, 0xeb, 0x7e, 0x6f, 0x42, 0x6d, 0x4c, 0x37, 0x2a, 0xcb, 0x9b, 0x53, 0x41, 0xe6, 0xdf, + 0x10, 0x90, 0xae, 0x4d, 0x9d, 0xbb, 0xe0, 0xbf, 0x30, 0x7f, 0xc1, 0x7f, 0x9a, 0x7e, 0xbf, 0x90, + 0xa6, 0xdf, 0xdf, 0x87, 0x25, 0x12, 0x4d, 0x8e, 0xeb, 0x8c, 0x95, 0xd5, 0x4c, 0x5a, 0xe0, 0x22, + 0x8a, 0x28, 0x82, 0x2b, 0x73, 0x42, 0x99, 0x1c, 0x52, 0x84, 0x14, 0xa5, 0xb5, 0x91, 0xb0, 0x34, + 0x48, 0x72, 0x44, 0x96, 0x46, 0xd4, 0x82, 0x7d, 0x19, 0xb7, 0x50, 0xd1, 0x5a, 0x20, 0x38, 0xb6, + 0x70, 0x1f, 0x96, 0xf8, 0x65, 0xe8, 0xdb, 0x96, 0x37, 0xb1, 0x3f, 0x9f, 0x62, 0x08, 0xd7, 0x46, + 0x1b, 0xbe, 0x6a, 0x2e, 0x22, 0xe2, 0x00, 0xe1, 0xdb, 0x76, 0x68, 0xdf, 0xff, 0x02, 0x2a, 0xda, + 0x6d, 0xdb, 0x6c, 0x1d, 0x96, 0x3f, 0xed, 0xf4, 0xbb, 0xed, 0x5e, 0xcf, 0x3a, 0x3c, 0xda, 0x7c, + 0xd6, 0xfe, 0xcc, 0xda, 0x6d, 0xf5, 0x76, 0x1b, 0x37, 0xc4, 0xa2, 0xed, 0xb6, 0x7b, 0xfd, 0xf6, + 0x76, 0x02, 0x9e, 0x61, 0xaf, 0xc3, 0xc6, 0x51, 0xf7, 0xa8, 0xd7, 0xde, 0xb6, 0xd2, 0xca, 0x65, + 0x05, 0x97, 0x4a, 0x7c, 0x4a, 0xf1, 0xdc, 0xfd, 0xef, 0x43, 0x3d, 0x79, 0x05, 0x2c, 0x03, 0x58, + 0xd8, 0x6b, 0x3f, 0x6d, 0x6d, 0x7d, 0x46, 0x57, 0x3f, 0xf6, 0xfa, 0xad, 0x7e, 0x67, 0xcb, 0x92, + 0x57, 0x3d, 0x0a, 0x89, 0x90, 0x61, 0x15, 0x28, 0xb6, 0xba, 0x5b, 0xbb, 0x07, 0x66, 0xaf, 0x91, + 0xbd, 0xff, 0x5d, 0xa8, 0x27, 0xb3, 0xeb, 0x92, 0x7e, 0xd7, 0x0d, 0x58, 0xdb, 0x6c, 0xf7, 0x3f, + 0x6d, 0xb7, 0xbb, 0xd8, 0xb9, 0xad, 0x76, 0xb7, 0x6f, 0xb6, 0xf6, 0x3a, 0xfd, 0xcf, 0x1a, 0x99, + 0xfb, 0x1f, 0x41, 0x63, 0x36, 0x94, 0x95, 0x88, 0xfd, 0xbd, 0x28, 0x48, 0x78, 0xff, 0x5f, 0xe5, + 0x00, 0xe2, 0x23, 0x1e, 0x42, 0x4a, 0x6d, 0xb7, 0xfa, 0xad, 0xbd, 0x03, 0x31, 0x03, 0xe6, 0x41, + 0x5f, 0x08, 0x1f, 0xb3, 0xfd, 0x71, 0xe3, 0x46, 0x2a, 0xe6, 0xe0, 0xb0, 0xdf, 0xc8, 0x88, 0xc9, + 0xee, 0x74, 0x3b, 0xfd, 0x4e, 0x6b, 0xcf, 0x32, 0x0f, 0x8e, 0x3a, 0xdd, 0xa7, 0x74, 0x1d, 0x1e, + 0x0a, 0xe8, 0xa3, 0xc3, 0x1d, 0xf3, 0xa0, 0xdb, 0xb7, 0x7a, 0xbb, 0x47, 0xfd, 0x6d, 0xbc, 0x4c, + 0x6f, 0xcb, 0xec, 0x1c, 0x52, 0x9d, 0xf9, 0x17, 0x11, 0x88, 0xaa, 0x0b, 0xe2, 0x75, 0x3d, 0x3d, + 0xe8, 0xf5, 0x3a, 0x87, 0xd6, 0xc7, 0x47, 0x6d, 0xb3, 0xd3, 0xee, 0x61, 0xc1, 0x85, 0x14, 0xb8, + 0xa0, 0x2f, 0x0a, 0xb1, 0xde, 0xdf, 0xfb, 0x44, 0xca, 0x5d, 0x41, 0x5a, 0x4a, 0x82, 0x04, 0x55, + 0x59, 0x4c, 0xa6, 0x10, 0x5c, 0x29, 0x35, 0xc3, 0x35, 0x38, 0x51, 0xae, 0x22, 0x44, 0xf2, 0xdc, + 0x7b, 0xc4, 0x62, 0xd5, 0x74, 0x94, 0x28, 0x85, 0xd2, 0x3a, 0xda, 0xdb, 0xb6, 0xb7, 0x4d, 0x2c, + 0x50, 0x9f, 0x83, 0x0a, 0xda, 0x45, 0xf1, 0xa2, 0x84, 0x64, 0x13, 0x24, 0x0d, 0xf5, 0x20, 0x30, + 0x4b, 0x8f, 0x7f, 0x27, 0x07, 0x75, 0x3a, 0x6e, 0x47, 0xdf, 0x49, 0xe3, 0x3e, 0xdb, 0x87, 0xa2, + 0xfc, 0xe0, 0x1e, 0x5b, 0x8d, 0x6e, 0x2a, 0xd3, 0x3f, 0xf1, 0xb7, 0xb1, 0x36, 0x0b, 0x96, 0x9a, + 0xdc, 0xf2, 0xdf, 0xfc, 0xf3, 0xff, 0xf9, 0x0f, 0xb3, 0x35, 0x56, 0x79, 0x78, 0xfe, 0xfe, 0xc3, + 0x53, 0xee, 0x06, 0xa2, 0x8e, 0xdf, 0x00, 0x88, 0x3f, 0x23, 0xc7, 0x9a, 0x51, 0xfc, 0x6a, 0xe6, + 0x1b, 0x7b, 0x1b, 0x37, 0x53, 0x30, 0xb2, 0xde, 0x9b, 0x58, 0xef, 0xb2, 0x51, 0x17, 0xf5, 0x3a, + 0xae, 0x13, 0xd2, 0x27, 0xe5, 0x3e, 0xcc, 0xdc, 0x67, 0x43, 0xa8, 0xea, 0x1f, 0x78, 0x63, 0x4a, + 0xc9, 0x4a, 0xf9, 0x44, 0xdd, 0xc6, 0xad, 0x54, 0x9c, 0x52, 0x5f, 0xb1, 0x8d, 0x55, 0xa3, 0x21, + 0xda, 0x98, 0x22, 0x45, 0xdc, 0xca, 0x88, 0x14, 0xfa, 0xf8, 0x3b, 0x6e, 0xec, 0x35, 0x4d, 0x25, + 0x9b, 0xfb, 0x8a, 0xdc, 0xc6, 0xed, 0x6b, 0xb0, 0xb2, 0xad, 0xdb, 0xd8, 0xd6, 0xba, 0xc1, 0x44, + 0x5b, 0x03, 0xa4, 0x51, 0x5f, 0x91, 0xfb, 0x30, 0x73, 0xff, 0xf1, 0x7f, 0x7c, 0x17, 0xca, 0x51, + 0xfa, 0x2d, 0xfb, 0x2d, 0xa8, 0x25, 0xce, 0x43, 0x32, 0x35, 0x8c, 0xb4, 0xe3, 0x93, 0x1b, 0xaf, + 0xa5, 0x23, 0x65, 0xc3, 0xaf, 0x63, 0xc3, 0x4d, 0xb6, 0x26, 0x1a, 0x96, 0xe7, 0x0d, 0x1f, 0xe2, + 0xf9, 0x65, 0xba, 0xf7, 0xed, 0xb9, 0x66, 0xb8, 0x50, 0x63, 0xaf, 0xcd, 0x1a, 0x13, 0x89, 0xd6, + 0x6e, 0x5f, 0x83, 0x95, 0xcd, 0xbd, 0x86, 0xcd, 0xad, 0xb1, 0x15, 0xbd, 0x39, 0x95, 0xb5, 0xc9, + 0x38, 0xde, 0xb5, 0xa8, 0x7f, 0xe6, 0x8c, 0xdd, 0x8e, 0x6f, 0xc6, 0x4b, 0xf9, 0xfc, 0x59, 0xc4, + 0x22, 0xf3, 0xdf, 0x40, 0x33, 0x9a, 0xd8, 0x14, 0x63, 0xf8, 0xfa, 0xf4, 0xaf, 0x9c, 0xb1, 0x63, + 0xa8, 0x68, 0x5f, 0x06, 0x61, 0x37, 0xaf, 0xfd, 0x8a, 0xc9, 0xc6, 0x46, 0x1a, 0x2a, 0x6d, 0x28, + 0x7a, 0xfd, 0x0f, 0x4f, 0x38, 0x67, 0xbf, 0x0e, 0xe5, 0xe8, 0x7b, 0x13, 0x6c, 0x5d, 0xfb, 0xfe, + 0x87, 0xfe, 0x7d, 0x8c, 0x8d, 0xe6, 0x3c, 0x22, 0x8d, 0xf9, 0xf4, 0xda, 0x05, 0xf3, 0x7d, 0x0a, + 0x15, 0xed, 0x9b, 0x12, 0xd1, 0x00, 0xe6, 0xbf, 0x5b, 0x11, 0x0d, 0x20, 0xe5, 0x13, 0x14, 0xc6, + 0x12, 0x36, 0x51, 0x61, 0x65, 0xe4, 0xef, 0xf0, 0xd2, 0x0b, 0xd8, 0x1e, 0xac, 0x4a, 0x23, 0xed, + 0x98, 0x7f, 0x99, 0xd7, 0x90, 0xf2, 0x65, 0xb9, 0x47, 0x19, 0xf6, 0x11, 0x94, 0xd4, 0xa7, 0x43, + 0xd8, 0x5a, 0xfa, 0x27, 0x50, 0x36, 0xd6, 0xe7, 0xe0, 0xd2, 0xa2, 0xfa, 0x0c, 0x20, 0xfe, 0x80, + 0x45, 0x24, 0x24, 0xe6, 0x3e, 0x88, 0x11, 0x71, 0xc0, 0xfc, 0xd7, 0x2e, 0x8c, 0x35, 0x1c, 0x60, + 0x83, 0xa1, 0x90, 0x70, 0xf9, 0x85, 0xba, 0x10, 0xf7, 0x47, 0x50, 0xd1, 0xbe, 0x61, 0x11, 0x4d, + 0xdf, 0xfc, 0xf7, 0x2f, 0xa2, 0xe9, 0x4b, 0xf9, 0xe4, 0x85, 0xb1, 0x81, 0xb5, 0xaf, 0x18, 0x8b, + 0xa2, 0x76, 0xa1, 0xa5, 0x49, 0x6d, 0x49, 0xbc, 0xa0, 0x33, 0xa8, 0x25, 0x3e, 0x54, 0x11, 0xad, + 0xd0, 0xb4, 0xcf, 0x60, 0x44, 0x2b, 0x34, 0xf5, 0xdb, 0x16, 0x8a, 0xcf, 0x8c, 0x25, 0xd1, 0xce, + 0x39, 0x92, 0x68, 0x2d, 0xfd, 0x10, 0x2a, 0xda, 0x47, 0x27, 0xa2, 0xb1, 0xcc, 0x7f, 0xdf, 0x22, + 0x1a, 0x4b, 0xda, 0x37, 0x2a, 0x56, 0xb0, 0x8d, 0xba, 0x81, 0xac, 0x80, 0x57, 0x7a, 0x8a, 0xba, + 0x7f, 0x0b, 0xea, 0xc9, 0xef, 0x50, 0x44, 0x6b, 0x3f, 0xf5, 0x83, 0x16, 0xd1, 0xda, 0xbf, 0xe6, + 0xe3, 0x15, 0x92, 0xa5, 0xef, 0x2f, 0x47, 0x8d, 0x3c, 0xfc, 0x89, 0x3c, 0x48, 0xf4, 0x05, 0xfb, + 0x58, 0x08, 0x38, 0x79, 0xa3, 0x2c, 0x5b, 0xd7, 0xb8, 0x56, 0xbf, 0x9a, 0x36, 0x5a, 0x2f, 0x73, + 0x97, 0xcf, 0x26, 0x99, 0x19, 0x2b, 0x67, 0x4f, 0x61, 0x39, 0x62, 0xe6, 0xe8, 0x8a, 0xd8, 0x20, + 0x1a, 0x43, 0xea, 0x45, 0xb4, 0x1b, 0x8d, 0x59, 0xec, 0xa3, 0x0c, 0x6d, 0x7f, 0x78, 0x31, 0xa7, + 0xb6, 0xfd, 0xe9, 0xb7, 0xc4, 0x6a, 0xdb, 0x5f, 0xe2, 0xfe, 0xce, 0xd9, 0xed, 0x2f, 0x74, 0x44, + 0x1d, 0x2e, 0x2c, 0xce, 0x5e, 0xd8, 0x7a, 0xfb, 0xba, 0x8b, 0x1a, 0xa8, 0xfa, 0xd7, 0x5f, 0x7c, + 0x8f, 0x43, 0x52, 0x14, 0x29, 0x69, 0xfa, 0x50, 0xe6, 0xad, 0xb0, 0xdf, 0x84, 0xaa, 0x7e, 0x77, + 0x3d, 0xd3, 0x65, 0xc2, 0x6c, 0x4b, 0xb7, 0x52, 0x71, 0x49, 0x2e, 0x61, 0x55, 0xbd, 0x19, 0xf6, + 0x09, 0xac, 0x45, 0xd3, 0xac, 0xdf, 0x34, 0x10, 0xb0, 0x3b, 0x29, 0xf7, 0x0f, 0x24, 0x26, 0xfb, + 0xe6, 0xb5, 0x17, 0x14, 0x3c, 0xca, 0x08, 0xee, 0x4b, 0x5e, 0xa2, 0x1d, 0xef, 0x3c, 0x69, 0x77, + 0x87, 0xc7, 0x3b, 0x4f, 0xea, 0xcd, 0xdb, 0x8a, 0xfb, 0xd8, 0x72, 0x62, 0x8e, 0x28, 0xa3, 0x97, + 0xfd, 0x10, 0x16, 0xb5, 0x6b, 0x14, 0x7a, 0x57, 0xee, 0x20, 0x5a, 0x49, 0xf3, 0xb7, 0x40, 0x6e, + 0xa4, 0xb9, 0x35, 0x8d, 0x75, 0xac, 0x7f, 0xc9, 0x48, 0x4c, 0x8e, 0x58, 0x45, 0x5b, 0x50, 0xd1, + 0xaf, 0x68, 0x78, 0x41, 0xbd, 0xeb, 0x1a, 0x4a, 0xbf, 0x70, 0xf0, 0x51, 0x86, 0xed, 0x41, 0x63, + 0xf6, 0xfa, 0xb3, 0x48, 0xa6, 0xa4, 0x5d, 0xd9, 0xb6, 0x31, 0x83, 0x4c, 0x5c, 0x9a, 0xc6, 0x0e, + 0xe9, 0x4c, 0x48, 0xf4, 0x19, 0x36, 0xcf, 0x9f, 0xdd, 0xd5, 0x93, 0x9f, 0x67, 0x8b, 0x6a, 0x4b, + 0xfb, 0x30, 0xdf, 0xbd, 0xcc, 0xa3, 0x0c, 0xfb, 0xbd, 0x0c, 0x54, 0x13, 0x17, 0x0a, 0x25, 0xb2, + 0xee, 0x67, 0xc6, 0xd9, 0xd4, 0x71, 0xfa, 0x40, 0x0d, 0x13, 0x27, 0x71, 0xef, 0xfe, 0x0f, 0x12, + 0x2f, 0xe9, 0x27, 0x89, 0xa8, 0xe0, 0x83, 0xd9, 0xef, 0xb4, 0x7d, 0x31, 0x4b, 0xa0, 0x5f, 0xee, + 0xf9, 0xc5, 0xa3, 0x0c, 0xfb, 0x37, 0x19, 0xa8, 0x27, 0xc3, 0xfd, 0xd1, 0x70, 0x53, 0x13, 0x0b, + 0x22, 0x56, 0xba, 0x26, 0x47, 0xe0, 0x87, 0xd8, 0xcb, 0xfe, 0x7d, 0x33, 0xd1, 0x4b, 0x79, 0xfd, + 0xfb, 0x2f, 0xd6, 0x5b, 0xf6, 0x21, 0x7d, 0x16, 0x55, 0x65, 0x41, 0xb1, 0xf9, 0xcf, 0x68, 0x46, + 0xec, 0xa7, 0x7f, 0x74, 0x12, 0x5f, 0xc2, 0x8f, 0xe8, 0x7b, 0x64, 0x2a, 0xa9, 0x46, 0x70, 0xf1, + 0xab, 0x96, 0x37, 0xde, 0xc2, 0x31, 0xbd, 0x6e, 0xdc, 0x4c, 0x8c, 0x69, 0x56, 0xf1, 0x68, 0x51, + 0xef, 0xe4, 0x37, 0x23, 0xe3, 0x9d, 0x73, 0xee, 0x3b, 0x92, 0xd7, 0x77, 0x72, 0x4c, 0x9d, 0x94, + 0xe4, 0x89, 0xa5, 0xf6, 0x8a, 0xd5, 0x18, 0xf7, 0xb1, 0xaf, 0x6f, 0x19, 0x77, 0xae, 0xed, 0xeb, + 0x43, 0x0c, 0xdd, 0x8b, 0x1e, 0x1f, 0x02, 0xc4, 0x59, 0x8a, 0x6c, 0x26, 0x57, 0x2e, 0x12, 0x40, + 0xf3, 0x89, 0x8c, 0xc9, 0xf5, 0xac, 0x52, 0xea, 0x44, 0x8d, 0xbf, 0x4e, 0xe2, 0x34, 0xca, 0xe2, + 0xd3, 0xb5, 0xaf, 0x64, 0x42, 0x61, 0x42, 0xfb, 0x9a, 0xad, 0x3f, 0x21, 0x4c, 0xa3, 0x94, 0xbd, + 0x23, 0xa8, 0xed, 0x79, 0xde, 0xf3, 0xe9, 0x24, 0xca, 0x8c, 0x4f, 0xe6, 0xd3, 0xec, 0xda, 0xc1, + 0xd9, 0xc6, 0xcc, 0x28, 0x8c, 0xbb, 0x58, 0xd5, 0x06, 0x6b, 0x6a, 0x55, 0x3d, 0xfc, 0x49, 0x9c, + 0x1a, 0xf9, 0x05, 0xb3, 0x61, 0x29, 0x92, 0xd1, 0x71, 0xfa, 0x61, 0xb2, 0x9a, 0x84, 0x64, 0x9e, + 0x6d, 0x22, 0x61, 0x26, 0xa8, 0xde, 0x3e, 0x0c, 0x54, 0x9d, 0x8f, 0x32, 0xec, 0x10, 0xaa, 0xdb, + 0x7c, 0x80, 0x57, 0x2b, 0x60, 0x56, 0xca, 0x72, 0x22, 0xc3, 0x81, 0xd2, 0x59, 0x36, 0x6a, 0x09, + 0x60, 0x72, 0xdf, 0x9a, 0xd8, 0x57, 0x3e, 0xff, 0xfc, 0xe1, 0x4f, 0x64, 0xbe, 0xcb, 0x17, 0x6a, + 0xdf, 0x52, 0xf9, 0x40, 0x89, 0x7d, 0x6b, 0x26, 0x81, 0x28, 0xb1, 0x6f, 0xcd, 0x25, 0x10, 0x25, + 0xa6, 0x5a, 0xe5, 0x23, 0xb1, 0x11, 0x2c, 0xcd, 0xe5, 0x1c, 0x45, 0x5b, 0xd6, 0x75, 0x99, 0x4a, + 0x1b, 0x77, 0xaf, 0x27, 0x48, 0xb6, 0x76, 0x3f, 0xd9, 0x5a, 0x0f, 0x6a, 0x74, 0xdf, 0xe8, 0x31, + 0xa7, 0x43, 0x96, 0x33, 0x37, 0x14, 0xe9, 0x27, 0x38, 0x67, 0x37, 0x18, 0xc4, 0x25, 0x35, 0x1c, + 0x3c, 0x66, 0xc7, 0x4e, 0xf0, 0xba, 0x7a, 0xed, 0x54, 0x63, 0xc4, 0x8c, 0xf3, 0x27, 0x2d, 0x23, + 0x66, 0x4c, 0x39, 0x04, 0xa9, 0xcc, 0x4f, 0xb6, 0x1a, 0xd5, 0xfd, 0xd0, 0xf5, 0x86, 0x7c, 0x2c, + 0x6b, 0xfd, 0x75, 0xa8, 0x3c, 0xe5, 0xa1, 0x3a, 0x46, 0x18, 0xe9, 0xf2, 0x33, 0xe7, 0x0a, 0x37, + 0x52, 0x0e, 0x7f, 0x26, 0x79, 0x93, 0x6a, 0xe6, 0xc3, 0x53, 0x4e, 0x42, 0xd0, 0x72, 0x86, 0x5f, + 0xb0, 0x5f, 0xc3, 0xca, 0xa3, 0x43, 0xf3, 0x6b, 0x5a, 0x37, 0xf5, 0xca, 0x17, 0x67, 0xe0, 0x69, + 0x35, 0x8b, 0x3e, 0x6b, 0x3a, 0xa5, 0x0b, 0x15, 0xed, 0x72, 0x8d, 0x68, 0x6e, 0xe6, 0x2f, 0x53, + 0x89, 0xe6, 0x26, 0xe5, 0x2e, 0x0e, 0xe3, 0x1e, 0xb6, 0x63, 0xb0, 0xbb, 0x71, 0x3b, 0x74, 0xff, + 0x46, 0xdc, 0xd2, 0xc3, 0x9f, 0xd8, 0xe3, 0xf0, 0x0b, 0xf6, 0x29, 0xbd, 0x0e, 0xed, 0x98, 0x64, + 0x6c, 0x9c, 0xcc, 0x9e, 0xa8, 0x8c, 0x26, 0x4b, 0x43, 0x25, 0x0d, 0x16, 0x6a, 0x0a, 0x35, 0xc6, + 0x27, 0x00, 0xbd, 0xd0, 0x9b, 0x6c, 0xdb, 0x7c, 0xec, 0xb9, 0xb1, 0x4c, 0x8f, 0x0f, 0xee, 0xc5, + 0x72, 0x52, 0x3b, 0xbd, 0xc7, 0x3e, 0xd5, 0xac, 0xb9, 0xc4, 0x01, 0x5f, 0xc5, 0xc4, 0xd7, 0x9e, + 0xed, 0x8b, 0x26, 0x24, 0xe5, 0x7c, 0xdf, 0xa3, 0x0c, 0x6b, 0x01, 0xc4, 0xc9, 0x6d, 0x91, 0x6d, + 0x36, 0x97, 0x37, 0x17, 0x89, 0xd7, 0x94, 0x4c, 0xb8, 0x43, 0x28, 0xc7, 0x59, 0x41, 0xeb, 0xf1, + 0x5d, 0x41, 0x89, 0x1c, 0xa2, 0x48, 0x53, 0x98, 0xcb, 0xc8, 0x31, 0x1a, 0x38, 0x55, 0xc0, 0x4a, + 0x62, 0xaa, 0x4e, 0x38, 0x0f, 0x98, 0x03, 0xcb, 0xd4, 0xc1, 0x48, 0x2d, 0xc3, 0x03, 0x67, 0xd1, + 0x47, 0x22, 0xe6, 0x93, 0x63, 0x22, 0xa9, 0x91, 0x9a, 0xe2, 0x91, 0x70, 0x31, 0x09, 0x6e, 0xa5, + 0xc3, 0x6e, 0x62, 0x0b, 0x18, 0xc3, 0xd2, 0x5c, 0x16, 0x41, 0x24, 0x3a, 0xae, 0x4b, 0x0b, 0x89, + 0x44, 0xc7, 0xb5, 0x09, 0x08, 0xc6, 0x2a, 0x36, 0xb9, 0x68, 0x00, 0x9a, 0x94, 0x17, 0x4e, 0x38, + 0x38, 0x13, 0xcd, 0xfd, 0x41, 0x06, 0x96, 0x53, 0xf2, 0x04, 0xd8, 0x1b, 0xca, 0x3b, 0x71, 0x6d, + 0x0e, 0xc1, 0x46, 0x6a, 0x3c, 0xd9, 0xe8, 0x61, 0x3b, 0xfb, 0xec, 0x59, 0x62, 0x03, 0xa5, 0x70, + 0xae, 0x5c, 0x99, 0x2f, 0x54, 0x5e, 0x52, 0x35, 0x97, 0xcf, 0x61, 0x9d, 0x3a, 0xd2, 0x1a, 0x8d, + 0x66, 0x62, 0xdd, 0xaf, 0x6b, 0xbd, 0x48, 0x89, 0xdf, 0x27, 0xec, 0x80, 0x64, 0x0c, 0xff, 0x1a, + 0xb5, 0x9d, 0xba, 0xca, 0xa6, 0xd0, 0x98, 0x8d, 0x21, 0xb3, 0xeb, 0xeb, 0xda, 0xb8, 0x93, 0xb0, + 0xb3, 0x53, 0xe2, 0xce, 0x5f, 0xc3, 0xc6, 0xee, 0x18, 0x1b, 0x69, 0xf3, 0x42, 0xa6, 0xb7, 0x78, + 0x1f, 0x7f, 0x23, 0x0a, 0x78, 0xcf, 0x8c, 0x53, 0x35, 0x70, 0x5d, 0x78, 0x3e, 0xb2, 0xf4, 0xd3, + 0xe3, 0xe5, 0x6f, 0x63, 0xf3, 0x77, 0x8d, 0x5b, 0x69, 0xcd, 0xfb, 0x54, 0x84, 0x6c, 0xfe, 0xf5, + 0xd9, 0x75, 0xad, 0x7a, 0x70, 0x37, 0xed, 0x7d, 0x5f, 0x6b, 0x73, 0xcd, 0xcc, 0xf5, 0x0d, 0xd4, + 0x21, 0xab, 0x7a, 0x80, 0x3b, 0x5a, 0x3e, 0x29, 0x91, 0xf4, 0x68, 0xf9, 0xa4, 0x45, 0xc4, 0x93, + 0xfa, 0x93, 0x8a, 0x85, 0x7f, 0x98, 0xb9, 0xbf, 0xf9, 0xce, 0x0f, 0xbf, 0x76, 0xea, 0x84, 0x67, + 0xd3, 0xe3, 0x07, 0x03, 0x6f, 0xfc, 0x70, 0xa4, 0xbc, 0x9a, 0xf2, 0x54, 0xf6, 0xc3, 0x91, 0x3b, + 0x7c, 0x88, 0xd5, 0x1e, 0x2f, 0x4c, 0x7c, 0x2f, 0xf4, 0xbe, 0xf9, 0x7f, 0x03, 0x00, 0x00, 0xff, + 0xff, 0x25, 0xc9, 0xbe, 0xb5, 0x81, 0x86, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 1417a3f130..410fb20cad 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -651,7 +651,6 @@ service Lightning { }; } - /** lncli: `getchaninfo` GetChanInfo returns the latest authenticated network announcement for the given channel identified by its channel ID: an 8-byte integer which @@ -2527,13 +2526,14 @@ message ChannelGraph { repeated ChannelEdge edges = 2; } -enum NodeMetricType { - BETWEENNESS_CENTRALITY = 0; +enum NodeMetricType { + UNKNOWN = 0; + BETWEENNESS_CENTRALITY = 1; } message NodeMetricsRequest { - /// The requesteded node metrics. - repeated NodeMetricType types = 1; + /// The requested node metrics. + repeated NodeMetricType types = 1; } message NodeMetricsResponse { @@ -2544,15 +2544,15 @@ message NodeMetricsResponse { Map of node pubkey to betweenness centrality of the node. Normalized values are in the [0,1] closed interval. */ - map betweenness_centrality = 1; + map betweenness_centrality = 1; } -message FloatValue { - /// Arbitrary float value. - double value = 1; +message FloatMetric { + /// Arbitrary float value. + double value = 1; - /// The value normalized to [0,1] or [-1,1]. - double normalized_value = 2; + /// The value normalized to [0,1] or [-1,1]. + double normalized_value = 2; } message ChanInfoRequest { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 7aedb11388..22fb90ce22 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -733,13 +733,14 @@ "parameters": [ { "name": "types", - "description": "/ The requesteded node metrics.", + "description": "/ The requested node metrics.", "in": "query", "required": false, "type": "array", "items": { "type": "string", "enum": [ + "UNKNOWN", "BETWEENNESS_CENTRALITY" ] }, @@ -2717,7 +2718,7 @@ } } }, - "lnrpcFloatValue": { + "lnrpcFloatMetric": { "type": "object", "properties": { "value": { @@ -3625,9 +3626,10 @@ "lnrpcNodeMetricType": { "type": "string", "enum": [ + "UNKNOWN", "BETWEENNESS_CENTRALITY" ], - "default": "BETWEENNESS_CENTRALITY" + "default": "UNKNOWN" }, "lnrpcNodeMetricsResponse": { "type": "object", @@ -3635,7 +3637,7 @@ "betweenness_centrality": { "type": "object", "additionalProperties": { - "$ref": "#/definitions/lnrpcFloatValue" + "$ref": "#/definitions/lnrpcFloatMetric" }, "description": "*\nBetweenness centrality is the sum of the ratio of shortest paths that pass\nthrough the node for each pair of nodes in the graph (not counting paths\nstarting or ending at this node).\nMap of node pubkey to betweenness centrality of the node. Normalized\nvalues are in the [0,1] closed interval." } diff --git a/rpcserver.go b/rpcserver.go index f2ab704a86..ad2040a58a 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -4688,7 +4688,7 @@ func (r *rpcServer) GetNodeMetrics(ctx context.Context, } resp := &lnrpc.NodeMetricsResponse{ - BetweennessCentrality: make(map[string]*lnrpc.FloatValue), + BetweennessCentrality: make(map[string]*lnrpc.FloatMetric), } // Obtain the pointer to the global singleton channel graph, this will @@ -4712,9 +4712,10 @@ func (r *rpcServer) GetNodeMetrics(ctx context.Context, // Fill normalized and non normalized centrality. centrality := centralityMetric.GetMetric(true) for nodeID, val := range centrality { - resp.BetweennessCentrality[hex.EncodeToString(nodeID[:])] = &lnrpc.FloatValue{ - NormalizedValue: val, - } + resp.BetweennessCentrality[hex.EncodeToString(nodeID[:])] = + &lnrpc.FloatMetric{ + NormalizedValue: val, + } } centrality = centralityMetric.GetMetric(false) From 919710467e4b10da421b135a27d3bd3f4b2c8aa7 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Sat, 28 Mar 2020 16:38:46 +0100 Subject: [PATCH 328/562] autopilot: tidying up source code to fit to 80 cols --- autopilot/betweenness_centrality.go | 18 +++++++++--------- autopilot/betweenness_centrality_test.go | 15 ++++++++++----- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/autopilot/betweenness_centrality.go b/autopilot/betweenness_centrality.go index 34a10f7a1e..85041864f9 100644 --- a/autopilot/betweenness_centrality.go +++ b/autopilot/betweenness_centrality.go @@ -98,13 +98,13 @@ func betweennessCentrality(g *SimpleGraph, s int, centrality []float64) { // shortest path from s to t for each node t. pred := make([][]int, len(g.Nodes)) - // sigma[t] is the number of shortest paths between nodes s and t for - // each node t. + // sigma[t] is the number of shortest paths between nodes s and t + // for each node t. sigma := make([]int, len(g.Nodes)) sigma[s] = 1 - // dist[t] holds the distance between s and t for each node t. We initialize - // this to -1 (meaning infinity) for each t != s. + // dist[t] holds the distance between s and t for each node t. + // We initialize this to -1 (meaning infinity) for each t != s. dist := make([]int, len(g.Nodes)) for i := range dist { dist[i] = -1 @@ -178,9 +178,9 @@ func (bc *BetweennessCentrality) Refresh(graph ChannelGraph) error { work := make(chan int) partials := make(chan []float64, bc.workers) - // Each worker will compute a partial result. This - // partial result is a sum of centrality updates on - // roughly N / workers nodes. + // Each worker will compute a partial result. + // This partial result is a sum of centrality updates + // on roughly N / workers nodes. worker := func() { defer wg.Done() partial := make([]float64, len(cache.Nodes)) @@ -199,8 +199,8 @@ func (bc *BetweennessCentrality) Refresh(graph ChannelGraph) error { go worker() } - // Distribute work amongst workers Should be - // fair when graph is sufficiently large. + // Distribute work amongst workers. + // Should be fair when the graph is sufficiently large. for node := range cache.Nodes { work <- node } diff --git a/autopilot/betweenness_centrality_test.go b/autopilot/betweenness_centrality_test.go index 4b71f77f6e..76ece3ceab 100644 --- a/autopilot/betweenness_centrality_test.go +++ b/autopilot/betweenness_centrality_test.go @@ -91,7 +91,7 @@ func buildTestGraph(t *testing.T, for _, v := range neighbors { _, _, err := graph.addRandChannel(nodes[u], nodes[v], chanCapacity) if err != nil { - t.Fatalf("unexpected error while adding random channel: %v", err) + t.Fatalf("unexpected error adding random channel: %v", err) } } } @@ -147,9 +147,12 @@ func TestBetweennessCentralityWithNonEmptyGraph(t *testing.T) { testName := fmt.Sprintf("%v %d workers", chanGraph.name, numWorkers) success := t.Run(testName, func(t1 *testing.T) { - centralityMetric, err := NewBetweennessCentralityMetric(numWorkers) + centralityMetric, err := NewBetweennessCentralityMetric( + numWorkers, + ) if err != nil { - t.Fatalf("construction must succeed with positive number of workers") + t.Fatalf("construction must succeed with " + + "positive number of workers") } graphNodes := buildTestGraph(t1, graph, graphDesc) @@ -169,11 +172,13 @@ func TestBetweennessCentralityWithNonEmptyGraph(t *testing.T) { nodeID := NewNodeID(graphNodes[node]) calculatedCentrality, ok := centrality[nodeID] if !ok { - t1.Fatalf("no result for node: %x (%v)", nodeID, node) + t1.Fatalf("no result for node: %x (%v)", + nodeID, node) } if nodeCentrality != calculatedCentrality { - t1.Errorf("centrality for node: %v should be %v, got: %v", + t1.Errorf("centrality for node: %v "+ + "should be %v, got: %v", node, nodeCentrality, calculatedCentrality) } } From 2848eb1d53694bac51e8c1bf14ef32fa9fd48fbe Mon Sep 17 00:00:00 2001 From: nsa Date: Tue, 24 Mar 2020 16:10:12 -0400 Subject: [PATCH 329/562] docs: detail watchtower tor hidden service configuration --- docs/watchtower.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/watchtower.md b/docs/watchtower.md index 772d456e29..870ec1e8ff 100644 --- a/docs/watchtower.md +++ b/docs/watchtower.md @@ -102,6 +102,24 @@ If the watchtower's clients will need remote access, be sure to either: - Use a proxy to direct traffic from an open port to the watchtower's listening address. +### Tor Hidden Services + +Watchtowers have tor hidden service support and can automatically generate a +hidden service on startup with the following flags: + +``` +🏔 lnd --tor.active --tor.v3 --watchtower.active +``` + +The onion address is then shown in the "uris" field when queried with `lncli tower info`: + +``` +... +"uris": [ + "03281d603b2c5e19b8893a484eb938d7377179a9ef1a6bca4c0bcbbfc291657b63@bn2kxggzjysvsd5o3uqe4h7655u7v2ydhxzy7ea2fx26duaixlwuguad.onion:9911" +] +``` + Note: *The watchtower’s public key is distinct from `lnd`’s node public key. For now this acts as a soft whitelist as it requires clients to know the tower’s public key in order to use it for backups before more advanced whitelisting From f97339c3e859556557c3775302fad42f82055fc3 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:12 +0200 Subject: [PATCH 330/562] mod: add PSBT dependency --- go.mod | 7 ++++++- go.sum | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5abf1a58dd..75a4f3f482 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d + github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059 github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7 github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 @@ -45,7 +46,7 @@ require ( github.com/rogpeppe/fastuuid v1.2.0 // indirect github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 github.com/urfave/cli v1.18.0 - golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 + golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 @@ -64,4 +65,8 @@ replace github.com/lightningnetwork/lnd/cert => ./cert replace git.schwanenlied.me/yawning/bsaes.git => github.com/Yawning/bsaes v0.0.0-20180720073208-c0276d75487e +// Pin this version that we know works explicitly, even though the +// btcsuite/btcutil package requests a newer version. +replace golang.org/x/crypto => golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 + go 1.12 diff --git a/go.sum b/go.sum index 7fff12d554..483b544b65 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059 h1:RU+MRFz83kf5hgJrGryakeYv/Xj2wZ7pwu9Eb7tna30= +github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7 h1:ubYJYIi13atgwPCX7FZQZV2mytkaRHWPycDFdF28U0o= github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7/go.mod h1:1O1uRHMPXHdwA4/od8nqYqrgclVKp+wtfXUAqHmeRvE= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= @@ -182,8 +184,6 @@ github.com/urfave/cli v1.18.0 h1:m9MfmZWX7bwr9kUcs/Asr95j0IVXzGNNc+/5ku2m26Q= github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= From 357f5978ad84fefa9bf2f84a365ea0c7c4b04df8 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:13 +0200 Subject: [PATCH 331/562] lnrpc: add new PSBT funding step messages --- lnrpc/rpc.pb.go | 1964 +++++++++++++++++++++++----------------- lnrpc/rpc.proto | 105 ++- lnrpc/rpc.swagger.json | 81 +- 3 files changed, 1313 insertions(+), 837 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 86bc642496..8fe57ae356 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -374,7 +374,7 @@ func (x PendingChannelsResponse_ForceClosedChannel_AnchorState) String() string } func (PendingChannelsResponse_ForceClosedChannel_AnchorState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 5, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{76, 5, 0} } type ChannelEventUpdate_UpdateType int32 @@ -408,7 +408,7 @@ func (x ChannelEventUpdate_UpdateType) String() string { } func (ChannelEventUpdate_UpdateType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{74, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{78, 0} } type Invoice_InvoiceState int32 @@ -439,7 +439,7 @@ func (x Invoice_InvoiceState) String() string { } func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{109, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{113, 0} } type Payment_PaymentStatus int32 @@ -470,7 +470,7 @@ func (x Payment_PaymentStatus) String() string { } func (Payment_PaymentStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{116, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{120, 0} } type HTLCAttempt_HTLCStatus int32 @@ -498,7 +498,7 @@ func (x HTLCAttempt_HTLCStatus) String() string { } func (HTLCAttempt_HTLCStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{117, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{121, 0} } type Failure_FailureCode int32 @@ -609,7 +609,7 @@ func (x Failure_FailureCode) String() string { } func (Failure_FailureCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{150, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{154, 0} } type GenSeedRequest struct { @@ -4694,6 +4694,72 @@ func (m *PendingUpdate) GetOutputIndex() uint32 { return 0 } +type ReadyForPsbtFunding struct { + //* + //The P2WSH address of the channel funding multisig address that the below + //specified amount in satoshis needs to be sent to. + FundingAddress string `protobuf:"bytes,1,opt,name=funding_address,json=fundingAddress,proto3" json:"funding_address,omitempty"` + //* + //The exact amount in satoshis that needs to be sent to the above address to + //fund the pending channel. + FundingAmount int64 `protobuf:"varint,2,opt,name=funding_amount,json=fundingAmount,proto3" json:"funding_amount,omitempty"` + //* + //A raw PSBT that contains the pending channel output. If a base PSBT was + //provided in the PsbtShim, this is the base PSBT with one additional output. + //If no base PSBT was specified, this is an otherwise empty PSBT with exactly + //one output. + Psbt []byte `protobuf:"bytes,3,opt,name=psbt,proto3" json:"psbt,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ReadyForPsbtFunding) Reset() { *m = ReadyForPsbtFunding{} } +func (m *ReadyForPsbtFunding) String() string { return proto.CompactTextString(m) } +func (*ReadyForPsbtFunding) ProtoMessage() {} +func (*ReadyForPsbtFunding) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{61} +} + +func (m *ReadyForPsbtFunding) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ReadyForPsbtFunding.Unmarshal(m, b) +} +func (m *ReadyForPsbtFunding) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ReadyForPsbtFunding.Marshal(b, m, deterministic) +} +func (m *ReadyForPsbtFunding) XXX_Merge(src proto.Message) { + xxx_messageInfo_ReadyForPsbtFunding.Merge(m, src) +} +func (m *ReadyForPsbtFunding) XXX_Size() int { + return xxx_messageInfo_ReadyForPsbtFunding.Size(m) +} +func (m *ReadyForPsbtFunding) XXX_DiscardUnknown() { + xxx_messageInfo_ReadyForPsbtFunding.DiscardUnknown(m) +} + +var xxx_messageInfo_ReadyForPsbtFunding proto.InternalMessageInfo + +func (m *ReadyForPsbtFunding) GetFundingAddress() string { + if m != nil { + return m.FundingAddress + } + return "" +} + +func (m *ReadyForPsbtFunding) GetFundingAmount() int64 { + if m != nil { + return m.FundingAmount + } + return 0 +} + +func (m *ReadyForPsbtFunding) GetPsbt() []byte { + if m != nil { + return m.Psbt + } + return nil +} + type OpenChannelRequest struct { //* //The pubkey of the node to open a channel with. When using REST, this field @@ -4755,7 +4821,7 @@ func (m *OpenChannelRequest) Reset() { *m = OpenChannelRequest{} } func (m *OpenChannelRequest) String() string { return proto.CompactTextString(m) } func (*OpenChannelRequest) ProtoMessage() {} func (*OpenChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{61} + return fileDescriptor_77a6da22d6a3feb1, []int{62} } func (m *OpenChannelRequest) XXX_Unmarshal(b []byte) error { @@ -4872,6 +4938,7 @@ type OpenStatusUpdate struct { // Types that are valid to be assigned to Update: // *OpenStatusUpdate_ChanPending // *OpenStatusUpdate_ChanOpen + // *OpenStatusUpdate_PsbtFund Update isOpenStatusUpdate_Update `protobuf_oneof:"update"` //* //The pending channel ID of the created channel. This value may be used to @@ -4886,7 +4953,7 @@ func (m *OpenStatusUpdate) Reset() { *m = OpenStatusUpdate{} } func (m *OpenStatusUpdate) String() string { return proto.CompactTextString(m) } func (*OpenStatusUpdate) ProtoMessage() {} func (*OpenStatusUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{62} + return fileDescriptor_77a6da22d6a3feb1, []int{63} } func (m *OpenStatusUpdate) XXX_Unmarshal(b []byte) error { @@ -4919,10 +4986,16 @@ type OpenStatusUpdate_ChanOpen struct { ChanOpen *ChannelOpenUpdate `protobuf:"bytes,3,opt,name=chan_open,json=chanOpen,proto3,oneof"` } +type OpenStatusUpdate_PsbtFund struct { + PsbtFund *ReadyForPsbtFunding `protobuf:"bytes,5,opt,name=psbt_fund,json=psbtFund,proto3,oneof"` +} + func (*OpenStatusUpdate_ChanPending) isOpenStatusUpdate_Update() {} func (*OpenStatusUpdate_ChanOpen) isOpenStatusUpdate_Update() {} +func (*OpenStatusUpdate_PsbtFund) isOpenStatusUpdate_Update() {} + func (m *OpenStatusUpdate) GetUpdate() isOpenStatusUpdate_Update { if m != nil { return m.Update @@ -4944,6 +5017,13 @@ func (m *OpenStatusUpdate) GetChanOpen() *ChannelOpenUpdate { return nil } +func (m *OpenStatusUpdate) GetPsbtFund() *ReadyForPsbtFunding { + if x, ok := m.GetUpdate().(*OpenStatusUpdate_PsbtFund); ok { + return x.PsbtFund + } + return nil +} + func (m *OpenStatusUpdate) GetPendingChanId() []byte { if m != nil { return m.PendingChanId @@ -4956,6 +5036,7 @@ func (*OpenStatusUpdate) XXX_OneofWrappers() []interface{} { return []interface{}{ (*OpenStatusUpdate_ChanPending)(nil), (*OpenStatusUpdate_ChanOpen)(nil), + (*OpenStatusUpdate_PsbtFund)(nil), } } @@ -4973,7 +5054,7 @@ func (m *KeyLocator) Reset() { *m = KeyLocator{} } func (m *KeyLocator) String() string { return proto.CompactTextString(m) } func (*KeyLocator) ProtoMessage() {} func (*KeyLocator) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{63} + return fileDescriptor_77a6da22d6a3feb1, []int{64} } func (m *KeyLocator) XXX_Unmarshal(b []byte) error { @@ -5024,7 +5105,7 @@ func (m *KeyDescriptor) Reset() { *m = KeyDescriptor{} } func (m *KeyDescriptor) String() string { return proto.CompactTextString(m) } func (*KeyDescriptor) ProtoMessage() {} func (*KeyDescriptor) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{64} + return fileDescriptor_77a6da22d6a3feb1, []int{65} } func (m *KeyDescriptor) XXX_Unmarshal(b []byte) error { @@ -5091,7 +5172,7 @@ func (m *ChanPointShim) Reset() { *m = ChanPointShim{} } func (m *ChanPointShim) String() string { return proto.CompactTextString(m) } func (*ChanPointShim) ProtoMessage() {} func (*ChanPointShim) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{65} + return fileDescriptor_77a6da22d6a3feb1, []int{66} } func (m *ChanPointShim) XXX_Unmarshal(b []byte) error { @@ -5154,9 +5235,64 @@ func (m *ChanPointShim) GetThawHeight() uint32 { return 0 } +type PsbtShim struct { + //* + //A unique identifier of 32 random bytes that will be used as the pending + //channel ID to identify the PSBT state machine when interacting with it and + //on the wire protocol to initiate the funding request. + PendingChanId []byte `protobuf:"bytes,1,opt,name=pending_chan_id,json=pendingChanId,proto3" json:"pending_chan_id,omitempty"` + //* + //An optional base PSBT the new channel output will be added to. If this is + //non-empty, it must be a binary serialized PSBT. + BasePsbt []byte `protobuf:"bytes,2,opt,name=base_psbt,json=basePsbt,proto3" json:"base_psbt,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PsbtShim) Reset() { *m = PsbtShim{} } +func (m *PsbtShim) String() string { return proto.CompactTextString(m) } +func (*PsbtShim) ProtoMessage() {} +func (*PsbtShim) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{67} +} + +func (m *PsbtShim) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PsbtShim.Unmarshal(m, b) +} +func (m *PsbtShim) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PsbtShim.Marshal(b, m, deterministic) +} +func (m *PsbtShim) XXX_Merge(src proto.Message) { + xxx_messageInfo_PsbtShim.Merge(m, src) +} +func (m *PsbtShim) XXX_Size() int { + return xxx_messageInfo_PsbtShim.Size(m) +} +func (m *PsbtShim) XXX_DiscardUnknown() { + xxx_messageInfo_PsbtShim.DiscardUnknown(m) +} + +var xxx_messageInfo_PsbtShim proto.InternalMessageInfo + +func (m *PsbtShim) GetPendingChanId() []byte { + if m != nil { + return m.PendingChanId + } + return nil +} + +func (m *PsbtShim) GetBasePsbt() []byte { + if m != nil { + return m.BasePsbt + } + return nil +} + type FundingShim struct { // Types that are valid to be assigned to Shim: // *FundingShim_ChanPointShim + // *FundingShim_PsbtShim Shim isFundingShim_Shim `protobuf_oneof:"shim"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -5167,7 +5303,7 @@ func (m *FundingShim) Reset() { *m = FundingShim{} } func (m *FundingShim) String() string { return proto.CompactTextString(m) } func (*FundingShim) ProtoMessage() {} func (*FundingShim) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{66} + return fileDescriptor_77a6da22d6a3feb1, []int{68} } func (m *FundingShim) XXX_Unmarshal(b []byte) error { @@ -5196,8 +5332,14 @@ type FundingShim_ChanPointShim struct { ChanPointShim *ChanPointShim `protobuf:"bytes,1,opt,name=chan_point_shim,json=chanPointShim,proto3,oneof"` } +type FundingShim_PsbtShim struct { + PsbtShim *PsbtShim `protobuf:"bytes,2,opt,name=psbt_shim,json=psbtShim,proto3,oneof"` +} + func (*FundingShim_ChanPointShim) isFundingShim_Shim() {} +func (*FundingShim_PsbtShim) isFundingShim_Shim() {} + func (m *FundingShim) GetShim() isFundingShim_Shim { if m != nil { return m.Shim @@ -5212,10 +5354,18 @@ func (m *FundingShim) GetChanPointShim() *ChanPointShim { return nil } +func (m *FundingShim) GetPsbtShim() *PsbtShim { + if x, ok := m.GetShim().(*FundingShim_PsbtShim); ok { + return x.PsbtShim + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*FundingShim) XXX_OneofWrappers() []interface{} { return []interface{}{ (*FundingShim_ChanPointShim)(nil), + (*FundingShim_PsbtShim)(nil), } } @@ -5231,7 +5381,7 @@ func (m *FundingShimCancel) Reset() { *m = FundingShimCancel{} } func (m *FundingShimCancel) String() string { return proto.CompactTextString(m) } func (*FundingShimCancel) ProtoMessage() {} func (*FundingShimCancel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{67} + return fileDescriptor_77a6da22d6a3feb1, []int{69} } func (m *FundingShimCancel) XXX_Unmarshal(b []byte) error { @@ -5259,10 +5409,116 @@ func (m *FundingShimCancel) GetPendingChanId() []byte { return nil } +type FundingPsbtVerify struct { + //* + //The funded but not yet signed PSBT that sends the exact channel capacity + //amount to the PK script returned in the open channel message in a previous + //step. + FundedPsbt []byte `protobuf:"bytes,1,opt,name=funded_psbt,json=fundedPsbt,proto3" json:"funded_psbt,omitempty"` + /// The pending channel ID of the channel to get the PSBT for. + PendingChanId []byte `protobuf:"bytes,2,opt,name=pending_chan_id,json=pendingChanId,proto3" json:"pending_chan_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FundingPsbtVerify) Reset() { *m = FundingPsbtVerify{} } +func (m *FundingPsbtVerify) String() string { return proto.CompactTextString(m) } +func (*FundingPsbtVerify) ProtoMessage() {} +func (*FundingPsbtVerify) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{70} +} + +func (m *FundingPsbtVerify) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FundingPsbtVerify.Unmarshal(m, b) +} +func (m *FundingPsbtVerify) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FundingPsbtVerify.Marshal(b, m, deterministic) +} +func (m *FundingPsbtVerify) XXX_Merge(src proto.Message) { + xxx_messageInfo_FundingPsbtVerify.Merge(m, src) +} +func (m *FundingPsbtVerify) XXX_Size() int { + return xxx_messageInfo_FundingPsbtVerify.Size(m) +} +func (m *FundingPsbtVerify) XXX_DiscardUnknown() { + xxx_messageInfo_FundingPsbtVerify.DiscardUnknown(m) +} + +var xxx_messageInfo_FundingPsbtVerify proto.InternalMessageInfo + +func (m *FundingPsbtVerify) GetFundedPsbt() []byte { + if m != nil { + return m.FundedPsbt + } + return nil +} + +func (m *FundingPsbtVerify) GetPendingChanId() []byte { + if m != nil { + return m.PendingChanId + } + return nil +} + +type FundingPsbtFinalize struct { + //* + //The funded PSBT that contains all witness data to send the exact channel + //capacity amount to the PK script returned in the open channel message in a + //previous step. + SignedPsbt []byte `protobuf:"bytes,1,opt,name=signed_psbt,json=signedPsbt,proto3" json:"signed_psbt,omitempty"` + /// The pending channel ID of the channel to get the PSBT for. + PendingChanId []byte `protobuf:"bytes,2,opt,name=pending_chan_id,json=pendingChanId,proto3" json:"pending_chan_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FundingPsbtFinalize) Reset() { *m = FundingPsbtFinalize{} } +func (m *FundingPsbtFinalize) String() string { return proto.CompactTextString(m) } +func (*FundingPsbtFinalize) ProtoMessage() {} +func (*FundingPsbtFinalize) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{71} +} + +func (m *FundingPsbtFinalize) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FundingPsbtFinalize.Unmarshal(m, b) +} +func (m *FundingPsbtFinalize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FundingPsbtFinalize.Marshal(b, m, deterministic) +} +func (m *FundingPsbtFinalize) XXX_Merge(src proto.Message) { + xxx_messageInfo_FundingPsbtFinalize.Merge(m, src) +} +func (m *FundingPsbtFinalize) XXX_Size() int { + return xxx_messageInfo_FundingPsbtFinalize.Size(m) +} +func (m *FundingPsbtFinalize) XXX_DiscardUnknown() { + xxx_messageInfo_FundingPsbtFinalize.DiscardUnknown(m) +} + +var xxx_messageInfo_FundingPsbtFinalize proto.InternalMessageInfo + +func (m *FundingPsbtFinalize) GetSignedPsbt() []byte { + if m != nil { + return m.SignedPsbt + } + return nil +} + +func (m *FundingPsbtFinalize) GetPendingChanId() []byte { + if m != nil { + return m.PendingChanId + } + return nil +} + type FundingTransitionMsg struct { // Types that are valid to be assigned to Trigger: // *FundingTransitionMsg_ShimRegister // *FundingTransitionMsg_ShimCancel + // *FundingTransitionMsg_PsbtVerify + // *FundingTransitionMsg_PsbtFinalize Trigger isFundingTransitionMsg_Trigger `protobuf_oneof:"trigger"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -5273,7 +5529,7 @@ func (m *FundingTransitionMsg) Reset() { *m = FundingTransitionMsg{} } func (m *FundingTransitionMsg) String() string { return proto.CompactTextString(m) } func (*FundingTransitionMsg) ProtoMessage() {} func (*FundingTransitionMsg) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{68} + return fileDescriptor_77a6da22d6a3feb1, []int{72} } func (m *FundingTransitionMsg) XXX_Unmarshal(b []byte) error { @@ -5306,10 +5562,22 @@ type FundingTransitionMsg_ShimCancel struct { ShimCancel *FundingShimCancel `protobuf:"bytes,2,opt,name=shim_cancel,json=shimCancel,proto3,oneof"` } +type FundingTransitionMsg_PsbtVerify struct { + PsbtVerify *FundingPsbtVerify `protobuf:"bytes,3,opt,name=psbt_verify,json=psbtVerify,proto3,oneof"` +} + +type FundingTransitionMsg_PsbtFinalize struct { + PsbtFinalize *FundingPsbtFinalize `protobuf:"bytes,4,opt,name=psbt_finalize,json=psbtFinalize,proto3,oneof"` +} + func (*FundingTransitionMsg_ShimRegister) isFundingTransitionMsg_Trigger() {} func (*FundingTransitionMsg_ShimCancel) isFundingTransitionMsg_Trigger() {} +func (*FundingTransitionMsg_PsbtVerify) isFundingTransitionMsg_Trigger() {} + +func (*FundingTransitionMsg_PsbtFinalize) isFundingTransitionMsg_Trigger() {} + func (m *FundingTransitionMsg) GetTrigger() isFundingTransitionMsg_Trigger { if m != nil { return m.Trigger @@ -5331,11 +5599,27 @@ func (m *FundingTransitionMsg) GetShimCancel() *FundingShimCancel { return nil } +func (m *FundingTransitionMsg) GetPsbtVerify() *FundingPsbtVerify { + if x, ok := m.GetTrigger().(*FundingTransitionMsg_PsbtVerify); ok { + return x.PsbtVerify + } + return nil +} + +func (m *FundingTransitionMsg) GetPsbtFinalize() *FundingPsbtFinalize { + if x, ok := m.GetTrigger().(*FundingTransitionMsg_PsbtFinalize); ok { + return x.PsbtFinalize + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*FundingTransitionMsg) XXX_OneofWrappers() []interface{} { return []interface{}{ (*FundingTransitionMsg_ShimRegister)(nil), (*FundingTransitionMsg_ShimCancel)(nil), + (*FundingTransitionMsg_PsbtVerify)(nil), + (*FundingTransitionMsg_PsbtFinalize)(nil), } } @@ -5349,7 +5633,7 @@ func (m *FundingStateStepResp) Reset() { *m = FundingStateStepResp{} } func (m *FundingStateStepResp) String() string { return proto.CompactTextString(m) } func (*FundingStateStepResp) ProtoMessage() {} func (*FundingStateStepResp) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{69} + return fileDescriptor_77a6da22d6a3feb1, []int{73} } func (m *FundingStateStepResp) XXX_Unmarshal(b []byte) error { @@ -5395,7 +5679,7 @@ func (m *PendingHTLC) Reset() { *m = PendingHTLC{} } func (m *PendingHTLC) String() string { return proto.CompactTextString(m) } func (*PendingHTLC) ProtoMessage() {} func (*PendingHTLC) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{70} + return fileDescriptor_77a6da22d6a3feb1, []int{74} } func (m *PendingHTLC) XXX_Unmarshal(b []byte) error { @@ -5468,7 +5752,7 @@ func (m *PendingChannelsRequest) Reset() { *m = PendingChannelsRequest{} func (m *PendingChannelsRequest) String() string { return proto.CompactTextString(m) } func (*PendingChannelsRequest) ProtoMessage() {} func (*PendingChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{71} + return fileDescriptor_77a6da22d6a3feb1, []int{75} } func (m *PendingChannelsRequest) XXX_Unmarshal(b []byte) error { @@ -5512,7 +5796,7 @@ func (m *PendingChannelsResponse) Reset() { *m = PendingChannelsResponse func (m *PendingChannelsResponse) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse) ProtoMessage() {} func (*PendingChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72} + return fileDescriptor_77a6da22d6a3feb1, []int{76} } func (m *PendingChannelsResponse) XXX_Unmarshal(b []byte) error { @@ -5595,7 +5879,7 @@ func (m *PendingChannelsResponse_PendingChannel) Reset() { func (m *PendingChannelsResponse_PendingChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_PendingChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{76, 0} } func (m *PendingChannelsResponse_PendingChannel) XXX_Unmarshal(b []byte) error { @@ -5704,7 +5988,7 @@ func (m *PendingChannelsResponse_PendingOpenChannel) String() string { } func (*PendingChannelsResponse_PendingOpenChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingOpenChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 1} + return fileDescriptor_77a6da22d6a3feb1, []int{76, 1} } func (m *PendingChannelsResponse_PendingOpenChannel) XXX_Unmarshal(b []byte) error { @@ -5782,7 +6066,7 @@ func (m *PendingChannelsResponse_WaitingCloseChannel) String() string { } func (*PendingChannelsResponse_WaitingCloseChannel) ProtoMessage() {} func (*PendingChannelsResponse_WaitingCloseChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 2} + return fileDescriptor_77a6da22d6a3feb1, []int{76, 2} } func (m *PendingChannelsResponse_WaitingCloseChannel) XXX_Unmarshal(b []byte) error { @@ -5852,7 +6136,7 @@ func (m *PendingChannelsResponse_Commitments) Reset() { *m = PendingChan func (m *PendingChannelsResponse_Commitments) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_Commitments) ProtoMessage() {} func (*PendingChannelsResponse_Commitments) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 3} + return fileDescriptor_77a6da22d6a3feb1, []int{76, 3} } func (m *PendingChannelsResponse_Commitments) XXX_Unmarshal(b []byte) error { @@ -5929,7 +6213,7 @@ func (m *PendingChannelsResponse_ClosedChannel) Reset() { *m = PendingCh func (m *PendingChannelsResponse_ClosedChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_ClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 4} + return fileDescriptor_77a6da22d6a3feb1, []int{76, 4} } func (m *PendingChannelsResponse_ClosedChannel) XXX_Unmarshal(b []byte) error { @@ -5995,7 +6279,7 @@ func (m *PendingChannelsResponse_ForceClosedChannel) String() string { } func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ForceClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72, 5} + return fileDescriptor_77a6da22d6a3feb1, []int{76, 5} } func (m *PendingChannelsResponse_ForceClosedChannel) XXX_Unmarshal(b []byte) error { @@ -6082,7 +6366,7 @@ func (m *ChannelEventSubscription) Reset() { *m = ChannelEventSubscripti func (m *ChannelEventSubscription) String() string { return proto.CompactTextString(m) } func (*ChannelEventSubscription) ProtoMessage() {} func (*ChannelEventSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{73} + return fileDescriptor_77a6da22d6a3feb1, []int{77} } func (m *ChannelEventSubscription) XXX_Unmarshal(b []byte) error { @@ -6121,7 +6405,7 @@ func (m *ChannelEventUpdate) Reset() { *m = ChannelEventUpdate{} } func (m *ChannelEventUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelEventUpdate) ProtoMessage() {} func (*ChannelEventUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{74} + return fileDescriptor_77a6da22d6a3feb1, []int{78} } func (m *ChannelEventUpdate) XXX_Unmarshal(b []byte) error { @@ -6246,7 +6530,7 @@ func (m *WalletBalanceRequest) Reset() { *m = WalletBalanceRequest{} } func (m *WalletBalanceRequest) String() string { return proto.CompactTextString(m) } func (*WalletBalanceRequest) ProtoMessage() {} func (*WalletBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{75} + return fileDescriptor_77a6da22d6a3feb1, []int{79} } func (m *WalletBalanceRequest) XXX_Unmarshal(b []byte) error { @@ -6283,7 +6567,7 @@ func (m *WalletBalanceResponse) Reset() { *m = WalletBalanceResponse{} } func (m *WalletBalanceResponse) String() string { return proto.CompactTextString(m) } func (*WalletBalanceResponse) ProtoMessage() {} func (*WalletBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{76} + return fileDescriptor_77a6da22d6a3feb1, []int{80} } func (m *WalletBalanceResponse) XXX_Unmarshal(b []byte) error { @@ -6335,7 +6619,7 @@ func (m *ChannelBalanceRequest) Reset() { *m = ChannelBalanceRequest{} } func (m *ChannelBalanceRequest) String() string { return proto.CompactTextString(m) } func (*ChannelBalanceRequest) ProtoMessage() {} func (*ChannelBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{77} + return fileDescriptor_77a6da22d6a3feb1, []int{81} } func (m *ChannelBalanceRequest) XXX_Unmarshal(b []byte) error { @@ -6370,7 +6654,7 @@ func (m *ChannelBalanceResponse) Reset() { *m = ChannelBalanceResponse{} func (m *ChannelBalanceResponse) String() string { return proto.CompactTextString(m) } func (*ChannelBalanceResponse) ProtoMessage() {} func (*ChannelBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{78} + return fileDescriptor_77a6da22d6a3feb1, []int{82} } func (m *ChannelBalanceResponse) XXX_Unmarshal(b []byte) error { @@ -6488,7 +6772,7 @@ func (m *QueryRoutesRequest) Reset() { *m = QueryRoutesRequest{} } func (m *QueryRoutesRequest) String() string { return proto.CompactTextString(m) } func (*QueryRoutesRequest) ProtoMessage() {} func (*QueryRoutesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{79} + return fileDescriptor_77a6da22d6a3feb1, []int{83} } func (m *QueryRoutesRequest) XXX_Unmarshal(b []byte) error { @@ -6640,7 +6924,7 @@ func (m *NodePair) Reset() { *m = NodePair{} } func (m *NodePair) String() string { return proto.CompactTextString(m) } func (*NodePair) ProtoMessage() {} func (*NodePair) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{80} + return fileDescriptor_77a6da22d6a3feb1, []int{84} } func (m *NodePair) XXX_Unmarshal(b []byte) error { @@ -6693,7 +6977,7 @@ func (m *EdgeLocator) Reset() { *m = EdgeLocator{} } func (m *EdgeLocator) String() string { return proto.CompactTextString(m) } func (*EdgeLocator) ProtoMessage() {} func (*EdgeLocator) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{81} + return fileDescriptor_77a6da22d6a3feb1, []int{85} } func (m *EdgeLocator) XXX_Unmarshal(b []byte) error { @@ -6746,7 +7030,7 @@ func (m *QueryRoutesResponse) Reset() { *m = QueryRoutesResponse{} } func (m *QueryRoutesResponse) String() string { return proto.CompactTextString(m) } func (*QueryRoutesResponse) ProtoMessage() {} func (*QueryRoutesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{82} + return fileDescriptor_77a6da22d6a3feb1, []int{86} } func (m *QueryRoutesResponse) XXX_Unmarshal(b []byte) error { @@ -6822,7 +7106,7 @@ func (m *Hop) Reset() { *m = Hop{} } func (m *Hop) String() string { return proto.CompactTextString(m) } func (*Hop) ProtoMessage() {} func (*Hop) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{83} + return fileDescriptor_77a6da22d6a3feb1, []int{87} } func (m *Hop) XXX_Unmarshal(b []byte) error { @@ -6944,7 +7228,7 @@ func (m *MPPRecord) Reset() { *m = MPPRecord{} } func (m *MPPRecord) String() string { return proto.CompactTextString(m) } func (*MPPRecord) ProtoMessage() {} func (*MPPRecord) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{84} + return fileDescriptor_77a6da22d6a3feb1, []int{88} } func (m *MPPRecord) XXX_Unmarshal(b []byte) error { @@ -7022,7 +7306,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{85} + return fileDescriptor_77a6da22d6a3feb1, []int{89} } func (m *Route) XXX_Unmarshal(b []byte) error { @@ -7101,7 +7385,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{86} + return fileDescriptor_77a6da22d6a3feb1, []int{90} } func (m *NodeInfoRequest) XXX_Unmarshal(b []byte) error { @@ -7158,7 +7442,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{87} + return fileDescriptor_77a6da22d6a3feb1, []int{91} } func (m *NodeInfo) XXX_Unmarshal(b []byte) error { @@ -7228,7 +7512,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{88} + return fileDescriptor_77a6da22d6a3feb1, []int{92} } func (m *LightningNode) XXX_Unmarshal(b []byte) error { @@ -7303,7 +7587,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{89} + return fileDescriptor_77a6da22d6a3feb1, []int{93} } func (m *NodeAddress) XXX_Unmarshal(b []byte) error { @@ -7355,7 +7639,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{90} + return fileDescriptor_77a6da22d6a3feb1, []int{94} } func (m *RoutingPolicy) XXX_Unmarshal(b []byte) error { @@ -7453,7 +7737,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{91} + return fileDescriptor_77a6da22d6a3feb1, []int{95} } func (m *ChannelEdge) XXX_Unmarshal(b []byte) error { @@ -7546,7 +7830,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{92} + return fileDescriptor_77a6da22d6a3feb1, []int{96} } func (m *ChannelGraphRequest) XXX_Unmarshal(b []byte) error { @@ -7589,7 +7873,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{93} + return fileDescriptor_77a6da22d6a3feb1, []int{97} } func (m *ChannelGraph) XXX_Unmarshal(b []byte) error { @@ -7636,7 +7920,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{94} + return fileDescriptor_77a6da22d6a3feb1, []int{98} } func (m *NodeMetricsRequest) XXX_Unmarshal(b []byte) error { @@ -7681,7 +7965,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{95} + return fileDescriptor_77a6da22d6a3feb1, []int{99} } func (m *NodeMetricsResponse) XXX_Unmarshal(b []byte) error { @@ -7723,7 +8007,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{96} + return fileDescriptor_77a6da22d6a3feb1, []int{100} } func (m *FloatMetric) XXX_Unmarshal(b []byte) error { @@ -7773,7 +8057,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{97} + return fileDescriptor_77a6da22d6a3feb1, []int{101} } func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error { @@ -7811,7 +8095,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{98} + return fileDescriptor_77a6da22d6a3feb1, []int{102} } func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error { @@ -7854,7 +8138,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{99} + return fileDescriptor_77a6da22d6a3feb1, []int{103} } func (m *NetworkInfo) XXX_Unmarshal(b []byte) error { @@ -7962,7 +8246,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{100} + return fileDescriptor_77a6da22d6a3feb1, []int{104} } func (m *StopRequest) XXX_Unmarshal(b []byte) error { @@ -7993,7 +8277,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{101} + return fileDescriptor_77a6da22d6a3feb1, []int{105} } func (m *StopResponse) XXX_Unmarshal(b []byte) error { @@ -8024,7 +8308,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{102} + return fileDescriptor_77a6da22d6a3feb1, []int{106} } func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error { @@ -8058,7 +8342,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{103} + return fileDescriptor_77a6da22d6a3feb1, []int{107} } func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error { @@ -8115,7 +8399,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{104} + return fileDescriptor_77a6da22d6a3feb1, []int{108} } func (m *NodeUpdate) XXX_Unmarshal(b []byte) error { @@ -8191,7 +8475,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{105} + return fileDescriptor_77a6da22d6a3feb1, []int{109} } func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error { @@ -8272,7 +8556,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{106} + return fileDescriptor_77a6da22d6a3feb1, []int{110} } func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error { @@ -8343,7 +8627,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{107} + return fileDescriptor_77a6da22d6a3feb1, []int{111} } func (m *HopHint) XXX_Unmarshal(b []byte) error { @@ -8413,7 +8697,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{108} + return fileDescriptor_77a6da22d6a3feb1, []int{112} } func (m *RouteHint) XXX_Unmarshal(b []byte) error { @@ -8546,7 +8830,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{109} + return fileDescriptor_77a6da22d6a3feb1, []int{113} } func (m *Invoice) XXX_Unmarshal(b []byte) error { @@ -8768,7 +9052,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{110} + return fileDescriptor_77a6da22d6a3feb1, []int{114} } func (m *InvoiceHTLC) XXX_Unmarshal(b []byte) error { @@ -8881,7 +9165,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{111} + return fileDescriptor_77a6da22d6a3feb1, []int{115} } func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error { @@ -8943,7 +9227,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{112} + return fileDescriptor_77a6da22d6a3feb1, []int{116} } func (m *PaymentHash) XXX_Unmarshal(b []byte) error { @@ -9003,7 +9287,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{113} + return fileDescriptor_77a6da22d6a3feb1, []int{117} } func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error { @@ -9074,7 +9358,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{114} + return fileDescriptor_77a6da22d6a3feb1, []int{118} } func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error { @@ -9138,7 +9422,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{115} + return fileDescriptor_77a6da22d6a3feb1, []int{119} } func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error { @@ -9211,7 +9495,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{116} + return fileDescriptor_77a6da22d6a3feb1, []int{120} } func (m *Payment) XXX_Unmarshal(b []byte) error { @@ -9356,7 +9640,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{117} + return fileDescriptor_77a6da22d6a3feb1, []int{121} } func (m *HTLCAttempt) XXX_Unmarshal(b []byte) error { @@ -9427,7 +9711,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{118} + return fileDescriptor_77a6da22d6a3feb1, []int{122} } func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error { @@ -9467,7 +9751,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{119} + return fileDescriptor_77a6da22d6a3feb1, []int{123} } func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error { @@ -9505,7 +9789,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{120} + return fileDescriptor_77a6da22d6a3feb1, []int{124} } func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error { @@ -9536,7 +9820,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{121} + return fileDescriptor_77a6da22d6a3feb1, []int{125} } func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error { @@ -9568,7 +9852,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{122} + return fileDescriptor_77a6da22d6a3feb1, []int{126} } func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error { @@ -9606,7 +9890,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{123} + return fileDescriptor_77a6da22d6a3feb1, []int{127} } func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error { @@ -9639,7 +9923,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{124} + return fileDescriptor_77a6da22d6a3feb1, []int{128} } func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error { @@ -9685,7 +9969,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{125} + return fileDescriptor_77a6da22d6a3feb1, []int{129} } func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error { @@ -9725,7 +10009,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{126} + return fileDescriptor_77a6da22d6a3feb1, []int{130} } func (m *PayReqString) XXX_Unmarshal(b []byte) error { @@ -9776,7 +10060,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{127} + return fileDescriptor_77a6da22d6a3feb1, []int{131} } func (m *PayReq) XXX_Unmarshal(b []byte) error { @@ -9901,7 +10185,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{128} + return fileDescriptor_77a6da22d6a3feb1, []int{132} } func (m *Feature) XXX_Unmarshal(b []byte) error { @@ -9953,7 +10237,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{129} + return fileDescriptor_77a6da22d6a3feb1, []int{133} } func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error { @@ -9996,7 +10280,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{130} + return fileDescriptor_77a6da22d6a3feb1, []int{134} } func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error { @@ -10074,7 +10358,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{131} + return fileDescriptor_77a6da22d6a3feb1, []int{135} } func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error { @@ -10152,7 +10436,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{132} + return fileDescriptor_77a6da22d6a3feb1, []int{136} } func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error { @@ -10270,7 +10554,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{133} + return fileDescriptor_77a6da22d6a3feb1, []int{137} } func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error { @@ -10315,7 +10599,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{134} + return fileDescriptor_77a6da22d6a3feb1, []int{138} } func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error { @@ -10398,7 +10682,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{135} + return fileDescriptor_77a6da22d6a3feb1, []int{139} } func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error { @@ -10498,7 +10782,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{136} + return fileDescriptor_77a6da22d6a3feb1, []int{140} } func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error { @@ -10545,7 +10829,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{137} + return fileDescriptor_77a6da22d6a3feb1, []int{141} } func (m *ExportChannelBackupRequest) XXX_Unmarshal(b []byte) error { @@ -10592,7 +10876,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{138} + return fileDescriptor_77a6da22d6a3feb1, []int{142} } func (m *ChannelBackup) XXX_Unmarshal(b []byte) error { @@ -10646,7 +10930,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{139} + return fileDescriptor_77a6da22d6a3feb1, []int{143} } func (m *MultiChanBackup) XXX_Unmarshal(b []byte) error { @@ -10691,7 +10975,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{140} + return fileDescriptor_77a6da22d6a3feb1, []int{144} } func (m *ChanBackupExportRequest) XXX_Unmarshal(b []byte) error { @@ -10730,7 +11014,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{141} + return fileDescriptor_77a6da22d6a3feb1, []int{145} } func (m *ChanBackupSnapshot) XXX_Unmarshal(b []byte) error { @@ -10778,7 +11062,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{142} + return fileDescriptor_77a6da22d6a3feb1, []int{146} } func (m *ChannelBackups) XXX_Unmarshal(b []byte) error { @@ -10820,7 +11104,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{143} + return fileDescriptor_77a6da22d6a3feb1, []int{147} } func (m *RestoreChanBackupRequest) XXX_Unmarshal(b []byte) error { @@ -10896,7 +11180,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{144} + return fileDescriptor_77a6da22d6a3feb1, []int{148} } func (m *RestoreBackupResponse) XXX_Unmarshal(b []byte) error { @@ -10927,7 +11211,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{145} + return fileDescriptor_77a6da22d6a3feb1, []int{149} } func (m *ChannelBackupSubscription) XXX_Unmarshal(b []byte) error { @@ -10958,7 +11242,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{146} + return fileDescriptor_77a6da22d6a3feb1, []int{150} } func (m *VerifyChanBackupResponse) XXX_Unmarshal(b []byte) error { @@ -10993,7 +11277,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{147} + return fileDescriptor_77a6da22d6a3feb1, []int{151} } func (m *MacaroonPermission) XXX_Unmarshal(b []byte) error { @@ -11040,7 +11324,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{148} + return fileDescriptor_77a6da22d6a3feb1, []int{152} } func (m *BakeMacaroonRequest) XXX_Unmarshal(b []byte) error { @@ -11080,7 +11364,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{149} + return fileDescriptor_77a6da22d6a3feb1, []int{153} } func (m *BakeMacaroonResponse) XXX_Unmarshal(b []byte) error { @@ -11136,7 +11420,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{150} + return fileDescriptor_77a6da22d6a3feb1, []int{154} } func (m *Failure) XXX_Unmarshal(b []byte) error { @@ -11280,7 +11564,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{151} + return fileDescriptor_77a6da22d6a3feb1, []int{155} } func (m *ChannelUpdate) XXX_Unmarshal(b []byte) error { @@ -11467,13 +11751,17 @@ func init() { proto.RegisterType((*CloseChannelRequest)(nil), "lnrpc.CloseChannelRequest") proto.RegisterType((*CloseStatusUpdate)(nil), "lnrpc.CloseStatusUpdate") proto.RegisterType((*PendingUpdate)(nil), "lnrpc.PendingUpdate") + proto.RegisterType((*ReadyForPsbtFunding)(nil), "lnrpc.ReadyForPsbtFunding") proto.RegisterType((*OpenChannelRequest)(nil), "lnrpc.OpenChannelRequest") proto.RegisterType((*OpenStatusUpdate)(nil), "lnrpc.OpenStatusUpdate") proto.RegisterType((*KeyLocator)(nil), "lnrpc.KeyLocator") proto.RegisterType((*KeyDescriptor)(nil), "lnrpc.KeyDescriptor") proto.RegisterType((*ChanPointShim)(nil), "lnrpc.ChanPointShim") + proto.RegisterType((*PsbtShim)(nil), "lnrpc.PsbtShim") proto.RegisterType((*FundingShim)(nil), "lnrpc.FundingShim") proto.RegisterType((*FundingShimCancel)(nil), "lnrpc.FundingShimCancel") + proto.RegisterType((*FundingPsbtVerify)(nil), "lnrpc.FundingPsbtVerify") + proto.RegisterType((*FundingPsbtFinalize)(nil), "lnrpc.FundingPsbtFinalize") proto.RegisterType((*FundingTransitionMsg)(nil), "lnrpc.FundingTransitionMsg") proto.RegisterType((*FundingStateStepResp)(nil), "lnrpc.FundingStateStepResp") proto.RegisterType((*PendingHTLC)(nil), "lnrpc.PendingHTLC") @@ -11576,735 +11864,747 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11641 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x6f, 0x23, 0x59, - 0x76, 0x18, 0xde, 0x7c, 0x89, 0xe4, 0xe1, 0x43, 0xd4, 0xd5, 0x8b, 0xad, 0x9e, 0x9e, 0xee, 0xa9, - 0x99, 0x9d, 0xe9, 0xe9, 0xd9, 0xed, 0xee, 0xe9, 0xdd, 0x9e, 0xdd, 0x9d, 0xf9, 0x79, 0xbd, 0x94, - 0x44, 0xb5, 0xb8, 0x2d, 0x51, 0x9a, 0x22, 0x35, 0xe3, 0x59, 0xdb, 0xbf, 0xda, 0x12, 0x79, 0x25, - 0x95, 0x9b, 0xac, 0xe2, 0x54, 0x15, 0xf5, 0xd8, 0xc5, 0xe4, 0x43, 0x90, 0x18, 0x41, 0x90, 0x04, - 0x30, 0x12, 0x07, 0x88, 0x13, 0x23, 0x41, 0x8c, 0x20, 0x08, 0x0c, 0x18, 0x06, 0xd6, 0x01, 0x12, - 0x20, 0xdf, 0x8d, 0x00, 0x09, 0x8c, 0xc0, 0xce, 0x97, 0xc0, 0x30, 0x10, 0x24, 0xd9, 0x7c, 0x0b, - 0xfc, 0x27, 0x04, 0xf7, 0x9c, 0x7b, 0xab, 0x6e, 0x91, 0xa5, 0xee, 0x9e, 0xdd, 0xc9, 0x7e, 0x91, - 0x58, 0xe7, 0x9c, 0xfb, 0xac, 0x73, 0xcf, 0x3d, 0xaf, 0x7b, 0x0b, 0xca, 0xfe, 0x64, 0xf0, 0x60, - 0xe2, 0x7b, 0xa1, 0xc7, 0x0a, 0x23, 0xd7, 0x9f, 0x0c, 0x36, 0x5e, 0x3b, 0xf5, 0xbc, 0xd3, 0x11, - 0x7f, 0x68, 0x4f, 0x9c, 0x87, 0xb6, 0xeb, 0x7a, 0xa1, 0x1d, 0x3a, 0x9e, 0x1b, 0x10, 0x91, 0xf1, - 0x23, 0xa8, 0x3f, 0xe5, 0x6e, 0x8f, 0xf3, 0xa1, 0xc9, 0x3f, 0x9f, 0xf2, 0x20, 0x64, 0xef, 0xc1, - 0x92, 0xcd, 0x7f, 0xcc, 0xf9, 0xd0, 0x9a, 0xd8, 0x41, 0x30, 0x39, 0xf3, 0xed, 0x80, 0x37, 0x33, - 0x77, 0x33, 0xf7, 0xaa, 0x66, 0x83, 0x10, 0x87, 0x11, 0x9c, 0xbd, 0x01, 0xd5, 0x40, 0x90, 0x72, - 0x37, 0xf4, 0xbd, 0xc9, 0x55, 0x33, 0x8b, 0x74, 0x15, 0x01, 0x6b, 0x13, 0xc8, 0x18, 0xc1, 0x62, - 0xd4, 0x42, 0x30, 0xf1, 0xdc, 0x80, 0xb3, 0x47, 0xb0, 0x32, 0x70, 0x26, 0x67, 0xdc, 0xb7, 0xb0, - 0xf0, 0xd8, 0xe5, 0x63, 0xcf, 0x75, 0x06, 0xcd, 0xcc, 0xdd, 0xdc, 0xbd, 0xb2, 0xc9, 0x08, 0x27, - 0x4a, 0xec, 0x4b, 0x0c, 0x7b, 0x07, 0x16, 0xb9, 0x4b, 0x70, 0x3e, 0xc4, 0x52, 0xb2, 0xa9, 0x7a, - 0x0c, 0x16, 0x05, 0x8c, 0xbf, 0x93, 0x85, 0xa5, 0x8e, 0xeb, 0x84, 0x9f, 0xda, 0xa3, 0x11, 0x0f, - 0xd5, 0x98, 0xde, 0x81, 0xc5, 0x0b, 0x04, 0xe0, 0x98, 0x2e, 0x3c, 0x7f, 0x28, 0x47, 0x54, 0x27, - 0xf0, 0xa1, 0x84, 0x5e, 0xdb, 0xb3, 0xec, 0xb5, 0x3d, 0x4b, 0x9d, 0xae, 0xdc, 0x35, 0xd3, 0xf5, - 0x0e, 0x2c, 0xfa, 0x7c, 0xe0, 0x9d, 0x73, 0xff, 0xca, 0xba, 0x70, 0xdc, 0xa1, 0x77, 0xd1, 0xcc, - 0xdf, 0xcd, 0xdc, 0x2b, 0x98, 0x75, 0x05, 0xfe, 0x14, 0xa1, 0x6c, 0x13, 0x16, 0x07, 0x67, 0xb6, - 0xeb, 0xf2, 0x91, 0x75, 0x6c, 0x0f, 0x9e, 0x4f, 0x27, 0x41, 0xb3, 0x70, 0x37, 0x73, 0xaf, 0xf2, - 0xf8, 0xe6, 0x03, 0x7c, 0xab, 0x0f, 0xb6, 0xce, 0x6c, 0x77, 0x13, 0x31, 0x3d, 0xd7, 0x9e, 0x04, - 0x67, 0x5e, 0x68, 0xd6, 0x65, 0x09, 0x02, 0x07, 0xc6, 0x0a, 0x30, 0x7d, 0x26, 0x68, 0xee, 0x8d, - 0x3f, 0xcc, 0xc0, 0xf2, 0x91, 0x3b, 0xf2, 0x06, 0xcf, 0x7f, 0xce, 0x29, 0x4a, 0x19, 0x43, 0xf6, - 0x55, 0xc7, 0x90, 0xfb, 0xb2, 0x63, 0x58, 0x83, 0x95, 0x64, 0x67, 0xe5, 0x28, 0x38, 0xac, 0x8a, - 0xd2, 0xa7, 0x5c, 0x75, 0x4b, 0x0d, 0xe3, 0x5d, 0x68, 0x0c, 0xa6, 0xbe, 0xcf, 0xdd, 0xb9, 0x71, - 0x2c, 0x4a, 0x78, 0x34, 0x90, 0x37, 0xa0, 0xea, 0xf2, 0x8b, 0x98, 0x4c, 0xf2, 0xae, 0xcb, 0x2f, - 0x14, 0x89, 0xd1, 0x84, 0xb5, 0xd9, 0x66, 0x64, 0x07, 0x7e, 0x96, 0x81, 0xfc, 0x51, 0x78, 0xe9, - 0xb1, 0x27, 0x50, 0xb5, 0x87, 0x43, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x4d, 0x68, 0xa5, 0xd4, 0x1f, - 0x33, 0x39, 0xc4, 0x16, 0xa1, 0xfa, 0x57, 0x13, 0x6e, 0x56, 0xec, 0xf8, 0x81, 0x35, 0xa1, 0x28, - 0x1f, 0xb1, 0xdd, 0xb2, 0xa9, 0x1e, 0xd9, 0x6d, 0x00, 0x7b, 0xec, 0x4d, 0xdd, 0xd0, 0x0a, 0xec, - 0x10, 0x67, 0x2c, 0x67, 0x96, 0x09, 0xd2, 0xb3, 0x43, 0x76, 0x0b, 0xca, 0x93, 0xe7, 0x56, 0x30, - 0xf0, 0x9d, 0x49, 0x88, 0xcc, 0x53, 0x36, 0x4b, 0x93, 0xe7, 0x3d, 0x7c, 0x66, 0xef, 0x41, 0xc9, - 0x9b, 0x86, 0x13, 0xcf, 0x71, 0x43, 0xc9, 0x2f, 0x8b, 0xb2, 0x23, 0x07, 0xd3, 0xf0, 0x50, 0x80, - 0xcd, 0x88, 0x80, 0xbd, 0x05, 0xb5, 0x81, 0xe7, 0x9e, 0x38, 0xfe, 0x98, 0x24, 0x42, 0x73, 0x01, - 0xdb, 0x4a, 0x02, 0x8d, 0x3f, 0xce, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, - 0x43, 0x31, 0xbc, 0xb4, 0xce, 0xec, 0xe0, 0x0c, 0x87, 0x5a, 0x36, 0x17, 0xc2, 0xcb, 0x5d, 0x3b, - 0x38, 0x63, 0x6b, 0xb0, 0x40, 0xbd, 0xc4, 0x01, 0xe5, 0x4c, 0xf9, 0x24, 0x16, 0x88, 0x3b, 0x1d, - 0x5b, 0xc9, 0xa6, 0x72, 0xc8, 0x31, 0x0d, 0x77, 0x3a, 0xde, 0xd2, 0xe1, 0x62, 0xf0, 0xc7, 0xe2, - 0x75, 0x53, 0x03, 0x34, 0xbc, 0x32, 0x42, 0xb0, 0x8d, 0x37, 0xa0, 0x2a, 0xd1, 0xdc, 0x39, 0x3d, - 0xa3, 0x31, 0x16, 0xcc, 0x0a, 0x11, 0x20, 0x48, 0xd4, 0x10, 0x3a, 0x63, 0x6e, 0x05, 0xa1, 0x3d, - 0x9e, 0xc8, 0x21, 0x95, 0x05, 0xa4, 0x27, 0x00, 0x88, 0xf6, 0x42, 0x7b, 0x64, 0x9d, 0x70, 0x1e, - 0x34, 0x8b, 0x12, 0x2d, 0x20, 0x3b, 0x9c, 0x07, 0xec, 0x6b, 0x50, 0x1f, 0xf2, 0x20, 0xb4, 0xe4, - 0xcb, 0xe0, 0x41, 0xb3, 0x84, 0x2b, 0xbf, 0x26, 0xa0, 0x2d, 0x05, 0x64, 0xaf, 0x01, 0xf8, 0xf6, - 0x85, 0x25, 0x26, 0x82, 0x5f, 0x36, 0xcb, 0xf4, 0x16, 0x7c, 0xfb, 0xa2, 0x7f, 0xb9, 0xcb, 0x2f, - 0x05, 0xd7, 0x3c, 0xe5, 0xa1, 0x36, 0x69, 0x81, 0xe4, 0x4e, 0x63, 0x0f, 0x98, 0x06, 0xde, 0xe6, - 0xa1, 0xed, 0x8c, 0x02, 0xf6, 0x01, 0x54, 0x43, 0x8d, 0x18, 0xc5, 0x60, 0x25, 0x62, 0x21, 0xad, - 0x80, 0x99, 0xa0, 0x33, 0xce, 0xa0, 0xb4, 0xc3, 0xf9, 0x9e, 0x33, 0x76, 0x42, 0xb6, 0x06, 0x85, - 0x13, 0xe7, 0x92, 0x13, 0xb3, 0xe7, 0x76, 0x6f, 0x98, 0xf4, 0xc8, 0xee, 0x00, 0xe0, 0x0f, 0x6b, - 0x1c, 0x71, 0xd3, 0xee, 0x0d, 0xb3, 0x8c, 0xb0, 0xfd, 0xc0, 0x0e, 0xd9, 0x06, 0x14, 0x27, 0xdc, - 0x1f, 0x70, 0xf5, 0xde, 0x76, 0x6f, 0x98, 0x0a, 0xb0, 0x59, 0x84, 0xc2, 0x48, 0xd4, 0x6e, 0xfc, - 0x69, 0x01, 0x2a, 0x3d, 0xee, 0x46, 0xab, 0x8c, 0x41, 0x5e, 0x4c, 0x88, 0x5c, 0x59, 0xf8, 0x9b, - 0xbd, 0x09, 0x15, 0x9c, 0xba, 0x20, 0xf4, 0x1d, 0xf7, 0x94, 0xb8, 0x7a, 0x33, 0xdb, 0xcc, 0x98, - 0x20, 0xc0, 0x3d, 0x84, 0xb2, 0x06, 0xe4, 0xec, 0xb1, 0xe2, 0x6a, 0xf1, 0x93, 0xdd, 0x84, 0x92, - 0x3d, 0x0e, 0xa9, 0x7b, 0x55, 0x04, 0x17, 0xed, 0x71, 0x88, 0x5d, 0x7b, 0x03, 0xaa, 0x13, 0xfb, - 0x6a, 0x2c, 0xd6, 0x72, 0xc4, 0x0e, 0x55, 0xb3, 0x22, 0x61, 0xc8, 0x10, 0x8f, 0x61, 0x59, 0x27, - 0x51, 0x8d, 0x17, 0xa2, 0xc6, 0x97, 0x34, 0x6a, 0xd9, 0x87, 0x77, 0x60, 0x51, 0x95, 0xf1, 0x69, - 0x3c, 0xc8, 0x26, 0x65, 0xb3, 0x2e, 0xc1, 0x6a, 0x94, 0xf7, 0xa0, 0x71, 0xe2, 0xb8, 0xf6, 0xc8, - 0x1a, 0x8c, 0xc2, 0x73, 0x6b, 0xc8, 0x47, 0xa1, 0x8d, 0x1c, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1a, - 0x85, 0xe7, 0xdb, 0x02, 0xca, 0xbe, 0x0e, 0xe5, 0x13, 0xce, 0x2d, 0x9c, 0xac, 0x66, 0x29, 0xb1, - 0xf0, 0xd4, 0x1b, 0x32, 0x4b, 0x27, 0xea, 0x5d, 0x7d, 0x1d, 0x1a, 0xde, 0x34, 0x3c, 0xf5, 0x1c, - 0xf7, 0xd4, 0x12, 0xf2, 0xce, 0x72, 0x86, 0xc8, 0x43, 0xf9, 0xcd, 0xec, 0xa3, 0x8c, 0x59, 0x57, - 0x38, 0x21, 0x79, 0x3a, 0x43, 0xf6, 0x36, 0x2c, 0x8e, 0xec, 0x20, 0xb4, 0xce, 0xbc, 0x89, 0x35, - 0x99, 0x1e, 0x3f, 0xe7, 0x57, 0xcd, 0x1a, 0x4e, 0x44, 0x4d, 0x80, 0x77, 0xbd, 0xc9, 0x21, 0x02, - 0x05, 0x67, 0x63, 0x3f, 0xa9, 0x13, 0x70, 0x37, 0x73, 0xaf, 0x66, 0x96, 0x05, 0x84, 0x1a, 0xfd, - 0x0c, 0x96, 0xf1, 0xf5, 0x0c, 0xa6, 0x41, 0xe8, 0x8d, 0x2d, 0x21, 0xab, 0xfd, 0x61, 0xd0, 0xac, - 0x20, 0xaf, 0xbd, 0x2b, 0x3b, 0xab, 0xbd, 0xe3, 0x07, 0xdb, 0x3c, 0x08, 0xb7, 0x90, 0xd8, 0x24, - 0x5a, 0xb1, 0xa1, 0x5f, 0x99, 0x4b, 0xc3, 0x59, 0x38, 0xfb, 0x3a, 0x30, 0x7b, 0x34, 0xf2, 0x2e, - 0xac, 0x80, 0x8f, 0x4e, 0x2c, 0x39, 0x89, 0xcd, 0xfa, 0xdd, 0xcc, 0xbd, 0x92, 0xd9, 0x40, 0x4c, - 0x8f, 0x8f, 0x4e, 0x0e, 0x09, 0xce, 0x3e, 0x00, 0x5c, 0x4c, 0xd6, 0x09, 0xb7, 0xc3, 0xa9, 0xcf, - 0x83, 0xe6, 0xe2, 0xdd, 0xdc, 0xbd, 0xfa, 0xe3, 0xa5, 0x68, 0xbe, 0x10, 0xbc, 0xe9, 0x84, 0x66, - 0x55, 0xd0, 0xc9, 0xe7, 0x60, 0x63, 0x1b, 0xd6, 0xd2, 0xbb, 0x24, 0x98, 0x4a, 0xcc, 0x8a, 0x60, - 0xc6, 0xbc, 0x29, 0x7e, 0xb2, 0x15, 0x28, 0x9c, 0xdb, 0xa3, 0x29, 0x97, 0x32, 0x9d, 0x1e, 0x3e, - 0xcc, 0x7e, 0x27, 0x63, 0xfc, 0x49, 0x06, 0xaa, 0x34, 0x4a, 0xa9, 0x8b, 0xbc, 0x09, 0x35, 0xc5, - 0x0d, 0xdc, 0xf7, 0x3d, 0x5f, 0x4a, 0x35, 0xc5, 0x79, 0x6d, 0x01, 0x13, 0xbb, 0x8a, 0x22, 0x9a, - 0xf8, 0xdc, 0x19, 0xdb, 0xa7, 0xaa, 0x6a, 0xc5, 0x4a, 0x87, 0x12, 0xcc, 0xde, 0x8f, 0xeb, 0xf3, - 0xbd, 0x69, 0xc8, 0xe5, 0x9e, 0x57, 0x95, 0xc3, 0x33, 0x05, 0x2c, 0xaa, 0x1d, 0x9f, 0x5e, 0x81, - 0xcf, 0x8d, 0xdf, 0xcd, 0x00, 0x13, 0xdd, 0xee, 0x7b, 0x54, 0x81, 0xe4, 0xd0, 0xd9, 0x92, 0x99, - 0x57, 0x5e, 0x21, 0xd9, 0x17, 0xad, 0x10, 0x03, 0x0a, 0xd4, 0xf7, 0x7c, 0x4a, 0xdf, 0x09, 0xf5, - 0x83, 0x7c, 0x29, 0xd7, 0xc8, 0x1b, 0xff, 0x2d, 0x07, 0x2b, 0x5b, 0xb4, 0x65, 0xb7, 0x06, 0x03, - 0x3e, 0x89, 0xd6, 0xce, 0x1d, 0xa8, 0xb8, 0xde, 0x90, 0x2b, 0x8e, 0xa5, 0x8e, 0x81, 0x00, 0x69, - 0xec, 0x7a, 0x66, 0x3b, 0x2e, 0x75, 0x9c, 0x26, 0xb3, 0x8c, 0x10, 0xec, 0xf6, 0xdb, 0xb0, 0x38, - 0xe1, 0xee, 0x50, 0x5f, 0x22, 0xa4, 0x54, 0xd5, 0x24, 0x58, 0xae, 0x8e, 0x3b, 0x50, 0x39, 0x99, - 0x12, 0x9d, 0x10, 0x2c, 0x79, 0xe4, 0x01, 0x90, 0xa0, 0x16, 0xc9, 0x97, 0xc9, 0x34, 0x38, 0x43, - 0x6c, 0x01, 0xb1, 0x45, 0xf1, 0x2c, 0x50, 0xb7, 0x01, 0x86, 0xd3, 0x20, 0x94, 0x2b, 0x66, 0x01, - 0x91, 0x65, 0x01, 0xa1, 0x15, 0xf3, 0x0d, 0x58, 0x1e, 0xdb, 0x97, 0x16, 0xf2, 0x8e, 0xe5, 0xb8, - 0xd6, 0xc9, 0x08, 0xf7, 0x9c, 0x22, 0xd2, 0x35, 0xc6, 0xf6, 0xe5, 0x27, 0x02, 0xd3, 0x71, 0x77, - 0x10, 0x2e, 0xc4, 0x8a, 0x52, 0x77, 0x7c, 0x1e, 0x70, 0xff, 0x9c, 0xa3, 0x24, 0xc8, 0x47, 0x3a, - 0x8d, 0x49, 0x50, 0xd1, 0xa3, 0xb1, 0x18, 0x77, 0x38, 0x1a, 0xd0, 0xb2, 0x37, 0x8b, 0x63, 0xc7, - 0xdd, 0x0d, 0x47, 0x03, 0xb1, 0xaf, 0x08, 0x39, 0x32, 0xe1, 0xbe, 0xf5, 0xfc, 0x02, 0xd7, 0x70, - 0x1e, 0xe5, 0xc6, 0x21, 0xf7, 0x9f, 0x5d, 0x88, 0xad, 0x7f, 0x10, 0xa0, 0x20, 0xb2, 0xaf, 0x9a, - 0x15, 0x5c, 0xe0, 0xa5, 0x41, 0x20, 0x44, 0x90, 0x7d, 0x25, 0x16, 0xa1, 0xe8, 0xad, 0x8d, 0x6f, - 0x81, 0x0f, 0xb1, 0xfa, 0x00, 0x25, 0x6a, 0x0d, 0x3b, 0xdb, 0x92, 0x08, 0xd1, 0x4e, 0x20, 0xb8, - 0x5e, 0x75, 0xf6, 0x64, 0x64, 0x9f, 0x06, 0x28, 0x52, 0x6a, 0x66, 0x55, 0x02, 0x77, 0x04, 0xcc, - 0xf8, 0x94, 0x94, 0x2c, 0xed, 0xdd, 0xca, 0x35, 0x23, 0xb6, 0x7a, 0x84, 0xe0, 0x7b, 0x2d, 0x99, - 0xf2, 0x29, 0xed, 0xa5, 0x65, 0x53, 0x5e, 0x9a, 0xf1, 0xfb, 0x19, 0xa8, 0xca, 0x9a, 0x51, 0x29, - 0x61, 0x0f, 0x80, 0xa9, 0xb7, 0x18, 0x5e, 0x3a, 0x43, 0xeb, 0xf8, 0x2a, 0xe4, 0x01, 0x31, 0xcd, - 0xee, 0x0d, 0xb3, 0x21, 0x71, 0xfd, 0x4b, 0x67, 0xb8, 0x29, 0x30, 0xec, 0x3e, 0x34, 0x12, 0xf4, - 0x41, 0xe8, 0x13, 0x47, 0xef, 0xde, 0x30, 0xeb, 0x1a, 0x75, 0x2f, 0xf4, 0xc5, 0x1a, 0x11, 0x2a, - 0xcf, 0x34, 0xb4, 0x1c, 0x77, 0xc8, 0x2f, 0x91, 0x8d, 0x6a, 0x66, 0x85, 0x60, 0x1d, 0x01, 0xda, - 0xac, 0x43, 0x55, 0xaf, 0xce, 0x38, 0x85, 0x92, 0xd2, 0x97, 0x50, 0x61, 0x98, 0xe9, 0x92, 0x59, - 0x0e, 0xa3, 0x9e, 0xdc, 0x84, 0x52, 0xb2, 0x07, 0x66, 0x31, 0x7c, 0xe5, 0x86, 0x8d, 0xef, 0x41, - 0x63, 0x4f, 0x30, 0x8f, 0x2b, 0x98, 0x55, 0xea, 0x7f, 0x6b, 0xb0, 0xa0, 0x2d, 0x9a, 0xb2, 0x29, - 0x9f, 0xc4, 0x9e, 0x7b, 0xe6, 0x05, 0xa1, 0x6c, 0x05, 0x7f, 0x1b, 0x7f, 0x9a, 0x01, 0xd6, 0x0e, - 0x42, 0x67, 0x6c, 0x87, 0x7c, 0x87, 0x47, 0x62, 0xe1, 0x00, 0xaa, 0xa2, 0xb6, 0xbe, 0xd7, 0x22, - 0x85, 0x8c, 0x14, 0x8a, 0xf7, 0xe4, 0x32, 0x9e, 0x2f, 0xf0, 0x40, 0xa7, 0x26, 0x31, 0x9f, 0xa8, - 0x40, 0xac, 0xb2, 0xd0, 0xf6, 0x4f, 0x79, 0x88, 0x6a, 0x9c, 0xd4, 0xf7, 0x81, 0x40, 0x42, 0x81, - 0xdb, 0xf8, 0x55, 0x58, 0x9a, 0xab, 0x43, 0x97, 0xcb, 0xe5, 0x14, 0xb9, 0x9c, 0xd3, 0xe5, 0xb2, - 0x05, 0xcb, 0x89, 0x7e, 0x49, 0x4e, 0x5b, 0x87, 0xa2, 0x58, 0x10, 0x42, 0x39, 0xc8, 0x90, 0x56, - 0x79, 0xc2, 0xb9, 0x50, 0x83, 0x1f, 0xc2, 0xca, 0x09, 0xe7, 0xbe, 0x1d, 0x22, 0x12, 0x57, 0x8c, - 0x78, 0x43, 0xb2, 0xe2, 0x25, 0x89, 0xeb, 0xd9, 0xe1, 0x21, 0xf7, 0xc5, 0x9b, 0x32, 0xfe, 0x47, - 0x06, 0x16, 0x85, 0x04, 0xdd, 0xb7, 0xdd, 0x2b, 0x35, 0x4f, 0x7b, 0xa9, 0xf3, 0x74, 0x4f, 0xdb, - 0x0c, 0x35, 0xea, 0x2f, 0x3b, 0x49, 0xb9, 0xd9, 0x49, 0x62, 0x77, 0xa1, 0x9a, 0xe8, 0x6b, 0x01, - 0xfb, 0x0a, 0x41, 0xd4, 0xc9, 0x5f, 0x7c, 0x1a, 0xdf, 0x86, 0x46, 0xdc, 0x6d, 0x39, 0x87, 0x0c, - 0xf2, 0x82, 0x25, 0x65, 0x05, 0xf8, 0xdb, 0xf8, 0x67, 0x19, 0x22, 0xdc, 0xf2, 0x9c, 0x48, 0x3b, - 0x15, 0x84, 0x42, 0xef, 0x55, 0x84, 0xe2, 0xf7, 0xb5, 0x5a, 0xfd, 0x2f, 0x3e, 0x58, 0xb1, 0x74, - 0x02, 0xee, 0x0e, 0x2d, 0x7b, 0x34, 0x42, 0xe1, 0x5b, 0x32, 0x8b, 0xe2, 0xb9, 0x35, 0x1a, 0x19, - 0xef, 0xc0, 0x92, 0xd6, 0xbb, 0x17, 0x8c, 0xa3, 0x0b, 0x6c, 0xcf, 0x09, 0xc2, 0x23, 0x37, 0x98, - 0x68, 0x8a, 0xdb, 0x2d, 0x28, 0x0b, 0x09, 0x2b, 0x7a, 0x46, 0x4b, 0xb6, 0x60, 0x0a, 0x91, 0x2b, - 0xfa, 0x15, 0x20, 0xd2, 0xbe, 0x94, 0xc8, 0xac, 0x44, 0xda, 0x97, 0x88, 0x34, 0xbe, 0x03, 0xcb, - 0x89, 0xfa, 0x64, 0xd3, 0x6f, 0x40, 0x61, 0x1a, 0x5e, 0x7a, 0x4a, 0x35, 0xaf, 0x48, 0x0e, 0x11, - 0x06, 0xa0, 0x49, 0x18, 0xe3, 0x23, 0x58, 0xea, 0xf2, 0x0b, 0xb9, 0x88, 0x55, 0x47, 0xde, 0x86, - 0xfc, 0x4b, 0x8c, 0x42, 0xc4, 0x1b, 0x0f, 0x80, 0xe9, 0x85, 0x65, 0xab, 0x9a, 0x8d, 0x98, 0x49, - 0xd8, 0x88, 0xc6, 0xdb, 0xc0, 0x7a, 0xce, 0xa9, 0xbb, 0xcf, 0x83, 0xc0, 0x3e, 0x8d, 0x96, 0x7d, - 0x03, 0x72, 0xe3, 0xe0, 0x54, 0xca, 0x28, 0xf1, 0xd3, 0xf8, 0x26, 0x2c, 0x27, 0xe8, 0x64, 0xc5, - 0xaf, 0x41, 0x39, 0x70, 0x4e, 0x5d, 0x54, 0xac, 0x64, 0xd5, 0x31, 0xc0, 0xd8, 0x81, 0x95, 0x4f, - 0xb8, 0xef, 0x9c, 0x5c, 0xbd, 0xac, 0xfa, 0x64, 0x3d, 0xd9, 0xd9, 0x7a, 0xda, 0xb0, 0x3a, 0x53, - 0x8f, 0x6c, 0x9e, 0xd8, 0x57, 0xbe, 0xc9, 0x92, 0x49, 0x0f, 0x9a, 0xdc, 0xcb, 0xea, 0x72, 0xcf, - 0x38, 0x02, 0xb6, 0xe5, 0xb9, 0x2e, 0x1f, 0x84, 0x87, 0x9c, 0xfb, 0xb1, 0x97, 0x2a, 0xe6, 0xd5, - 0xca, 0xe3, 0x75, 0x39, 0xb3, 0xb3, 0xc2, 0x54, 0x32, 0x31, 0x83, 0xfc, 0x84, 0xfb, 0x63, 0xac, - 0xb8, 0x64, 0xe2, 0x6f, 0x63, 0x15, 0x96, 0x13, 0xd5, 0x4a, 0xbb, 0xfe, 0x11, 0xac, 0x6e, 0x3b, - 0xc1, 0x60, 0xbe, 0xc1, 0x75, 0x28, 0x4e, 0xa6, 0xc7, 0x56, 0x52, 0x2e, 0x3f, 0xe3, 0x57, 0xc2, - 0xda, 0x9b, 0x2d, 0x21, 0xeb, 0xfa, 0x5b, 0x19, 0xc8, 0xef, 0xf6, 0xf7, 0xb6, 0xd8, 0x06, 0x94, - 0x1c, 0x77, 0xe0, 0x8d, 0x85, 0xe2, 0x45, 0x63, 0x8e, 0x9e, 0xaf, 0x5d, 0x60, 0xb7, 0xa0, 0x8c, - 0xfa, 0x9a, 0x30, 0x6d, 0xa5, 0xea, 0x53, 0x12, 0x80, 0x3d, 0x6f, 0xf0, 0x5c, 0xd8, 0xd4, 0xfc, - 0x72, 0xe2, 0xf8, 0x68, 0x35, 0x2b, 0x63, 0x38, 0x4f, 0x7b, 0x7d, 0x8c, 0x20, 0x8b, 0xd8, 0xf8, - 0xf7, 0x25, 0x28, 0xca, 0xdd, 0x96, 0x76, 0xee, 0xd0, 0x39, 0xe7, 0xf1, 0xce, 0x2d, 0x9e, 0x84, - 0x3e, 0xe0, 0xf3, 0xb1, 0x17, 0x46, 0x0a, 0x1b, 0xbd, 0x83, 0x2a, 0x01, 0xa5, 0xca, 0xa6, 0x29, - 0x0d, 0xe4, 0x62, 0xc8, 0x11, 0xd1, 0x40, 0xdf, 0xca, 0x6f, 0x41, 0x51, 0xed, 0xfd, 0xf9, 0xc8, - 0xa6, 0x59, 0x18, 0x90, 0xb6, 0xb6, 0x01, 0xa5, 0x81, 0x3d, 0xb1, 0x07, 0x4e, 0x78, 0x25, 0x05, - 0x42, 0xf4, 0x2c, 0x6a, 0x1f, 0x79, 0x03, 0x7b, 0x64, 0x1d, 0xdb, 0x23, 0xdb, 0x1d, 0x70, 0x69, - 0xbb, 0x57, 0x11, 0xb8, 0x49, 0x30, 0x61, 0x9f, 0xcb, 0x7e, 0x2a, 0x2a, 0x32, 0xe1, 0x65, 0xef, - 0x15, 0x99, 0x50, 0x2e, 0xbd, 0xf1, 0xd8, 0x11, 0x56, 0x06, 0xa9, 0x61, 0x39, 0xb3, 0x4c, 0x90, - 0x1d, 0x8e, 0xa3, 0x95, 0xe8, 0x0b, 0x9a, 0xba, 0x32, 0x35, 0x45, 0xc0, 0x4f, 0xc9, 0x91, 0x30, - 0xaf, 0x8b, 0xe5, 0x34, 0x5d, 0xec, 0x3d, 0x58, 0x9a, 0xba, 0x01, 0x0f, 0xc3, 0x11, 0x1f, 0x46, - 0x7d, 0xa9, 0x20, 0x51, 0x23, 0x42, 0xa8, 0xee, 0x3c, 0x80, 0x65, 0x72, 0x3a, 0x04, 0x76, 0xe8, - 0x05, 0x67, 0x4e, 0x60, 0x05, 0xc2, 0x42, 0x22, 0x73, 0x77, 0x09, 0x51, 0x3d, 0x89, 0xe9, 0x91, - 0x89, 0xb4, 0x3e, 0x43, 0xef, 0xf3, 0x01, 0x77, 0xce, 0xf9, 0x10, 0xf5, 0xb4, 0x9c, 0xb9, 0x9a, - 0x28, 0x63, 0x4a, 0x24, 0x2a, 0xdd, 0xd3, 0xb1, 0x35, 0x9d, 0x0c, 0x6d, 0xa1, 0xac, 0xd4, 0x49, - 0x19, 0x76, 0xa7, 0xe3, 0x23, 0x82, 0xb0, 0x47, 0xa0, 0x34, 0x31, 0xa9, 0x1f, 0x2e, 0x26, 0xe4, - 0x99, 0x60, 0x56, 0xb3, 0x2a, 0x29, 0x48, 0x51, 0x4c, 0xe8, 0x9c, 0x8d, 0x19, 0x9d, 0xb3, 0x09, - 0xc5, 0x89, 0xef, 0x9c, 0xdb, 0x21, 0x6f, 0x2e, 0x91, 0x00, 0x97, 0x8f, 0x42, 0x32, 0x38, 0xae, - 0x13, 0x3a, 0x76, 0xe8, 0xf9, 0x4d, 0x86, 0xb8, 0x18, 0xc0, 0xee, 0xc3, 0x12, 0xf2, 0x48, 0x10, - 0xda, 0xe1, 0x34, 0x90, 0x1a, 0xe8, 0x32, 0x32, 0x13, 0xea, 0xd0, 0x3d, 0x84, 0xa3, 0x12, 0xca, - 0xbe, 0x09, 0x6b, 0xc4, 0x16, 0x58, 0x42, 0x6a, 0xd6, 0xa8, 0x10, 0xac, 0xe0, 0x54, 0x2c, 0x23, - 0x56, 0xf0, 0xb7, 0xd4, 0xaf, 0x85, 0x76, 0xf0, 0x04, 0xd6, 0x25, 0x9b, 0xcc, 0x95, 0x5a, 0xc5, - 0x52, 0x2b, 0x84, 0x9e, 0x29, 0xf6, 0x00, 0x96, 0x44, 0x97, 0x9c, 0x81, 0x25, 0x4b, 0x8b, 0x95, - 0xb0, 0x26, 0x7a, 0x8f, 0x96, 0xd2, 0x22, 0x21, 0x4d, 0xc4, 0x3d, 0xe3, 0x57, 0xec, 0x7b, 0xb0, - 0x48, 0x2c, 0x83, 0xe6, 0x15, 0x4a, 0xfa, 0x0d, 0x94, 0xf4, 0xab, 0xca, 0xc3, 0x19, 0x61, 0x51, - 0xd8, 0xd7, 0x07, 0x89, 0x67, 0xb1, 0x1c, 0x46, 0xce, 0x09, 0x0f, 0x9d, 0x31, 0x6f, 0xae, 0x13, - 0x83, 0xa9, 0x67, 0xb1, 0x52, 0xa7, 0x13, 0xc4, 0x34, 0x49, 0x2e, 0xd0, 0x13, 0xf2, 0xee, 0xc8, - 0x0b, 0xb8, 0x72, 0x51, 0x35, 0x6f, 0xca, 0x45, 0x28, 0x80, 0x4a, 0x87, 0x14, 0x8a, 0x38, 0x19, - 0x3d, 0x91, 0x23, 0xf1, 0x16, 0x32, 0x43, 0x8d, 0x6c, 0x1f, 0xe5, 0x4c, 0x14, 0xbb, 0xf8, 0x99, - 0x7d, 0xa1, 0x24, 0xc8, 0x6b, 0xf8, 0x7e, 0x41, 0x80, 0xa4, 0xec, 0xf8, 0x69, 0x86, 0x36, 0x44, - 0x29, 0x3f, 0x02, 0xcd, 0xbc, 0x23, 0xc9, 0x61, 0x79, 0xee, 0xe8, 0x4a, 0x0a, 0x13, 0x20, 0xd0, - 0x81, 0x3b, 0xc2, 0xd5, 0xec, 0xb8, 0x3a, 0x09, 0xc9, 0xde, 0xaa, 0x02, 0x22, 0xd1, 0x1d, 0xa8, - 0x4c, 0xa6, 0xc7, 0x23, 0x67, 0x40, 0x24, 0x39, 0xaa, 0x85, 0x40, 0x48, 0x20, 0xec, 0x5b, 0xe2, - 0x28, 0xa2, 0xc8, 0x23, 0x45, 0x45, 0xc2, 0x90, 0x04, 0x65, 0x3b, 0xf7, 0x51, 0x9c, 0x54, 0x4d, - 0xfc, 0x6d, 0x6c, 0xc2, 0x4a, 0xb2, 0xd3, 0x72, 0xe3, 0xb9, 0x0f, 0x25, 0x29, 0xab, 0x94, 0xe3, - 0xa3, 0xae, 0xb9, 0xa2, 0x85, 0x89, 0x16, 0xe1, 0x8d, 0xdf, 0x5e, 0x80, 0x65, 0x09, 0xdd, 0x12, - 0x53, 0xdb, 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0x22, 0x04, 0x33, 0x2f, 0x16, 0x82, 0xd9, 0x39, 0x21, - 0x98, 0xb4, 0x7c, 0x49, 0x86, 0x26, 0x2d, 0x5f, 0xf1, 0x2e, 0xc9, 0x18, 0xd1, 0xfd, 0xa0, 0x35, - 0x09, 0xee, 0x93, 0xbf, 0x75, 0x4e, 0x64, 0x17, 0x52, 0x44, 0xb6, 0x2e, 0x70, 0x17, 0x66, 0x04, - 0xee, 0x1b, 0x40, 0x4c, 0xa3, 0xde, 0x7e, 0x91, 0xec, 0x13, 0x84, 0x49, 0x67, 0xea, 0x3b, 0xb0, - 0x38, 0x2b, 0xe3, 0x48, 0x98, 0xd6, 0x53, 0x24, 0x9c, 0x33, 0xe6, 0xb8, 0x5b, 0x69, 0xc4, 0x65, - 0x29, 0xe1, 0x9c, 0x31, 0xdf, 0x43, 0x8c, 0xa2, 0x6f, 0x03, 0x50, 0xdb, 0xb8, 0x68, 0x00, 0x17, - 0xcd, 0xdb, 0xc9, 0x77, 0xa1, 0xcf, 0xfa, 0x03, 0xf1, 0x30, 0xf5, 0x39, 0xae, 0xa2, 0x32, 0x96, - 0xc4, 0x05, 0xf4, 0x0c, 0xea, 0xde, 0x84, 0xbb, 0x56, 0x2c, 0x6b, 0x2a, 0x58, 0xd5, 0x5b, 0x2f, - 0xa8, 0xaa, 0xa3, 0x68, 0xcd, 0x9a, 0x28, 0x1b, 0x3d, 0xb2, 0x7d, 0x9a, 0x78, 0xae, 0xd5, 0x56, - 0xfd, 0x12, 0xb5, 0xd5, 0xb1, 0x70, 0xf4, 0x6c, 0xfc, 0xdd, 0x0c, 0x54, 0xb4, 0x6e, 0xb3, 0x55, - 0x58, 0xda, 0x3a, 0x38, 0x38, 0x6c, 0x9b, 0xad, 0x7e, 0xe7, 0x93, 0xb6, 0xb5, 0xb5, 0x77, 0xd0, - 0x6b, 0x37, 0x6e, 0x08, 0xf0, 0xde, 0xc1, 0x56, 0x6b, 0xcf, 0xda, 0x39, 0x30, 0xb7, 0x14, 0x38, - 0xc3, 0xd6, 0x80, 0x99, 0xed, 0xfd, 0x83, 0x7e, 0x3b, 0x01, 0xcf, 0xb2, 0x06, 0x54, 0x37, 0xcd, - 0x76, 0x6b, 0x6b, 0x57, 0x42, 0x72, 0x6c, 0x05, 0x1a, 0x3b, 0x47, 0xdd, 0xed, 0x4e, 0xf7, 0xa9, - 0xb5, 0xd5, 0xea, 0x6e, 0xb5, 0xf7, 0xda, 0xdb, 0x8d, 0x3c, 0xab, 0x41, 0xb9, 0xb5, 0xd9, 0xea, - 0x6e, 0x1f, 0x74, 0xdb, 0xdb, 0x8d, 0x82, 0xf1, 0x5d, 0x28, 0xc7, 0x03, 0xad, 0x40, 0xf1, 0xa8, - 0xfb, 0xac, 0x7b, 0xf0, 0x69, 0xb7, 0x71, 0x83, 0x95, 0xa1, 0x80, 0xed, 0x37, 0x32, 0x0c, 0x60, - 0x81, 0xda, 0x6c, 0x64, 0x59, 0x09, 0xf2, 0x9b, 0x07, 0xfd, 0xdd, 0x46, 0xce, 0xf8, 0xab, 0x0c, - 0xac, 0xe2, 0x90, 0x87, 0xb3, 0x42, 0xe0, 0x2e, 0x54, 0x06, 0x9e, 0x37, 0x11, 0x96, 0x56, 0xac, - 0x51, 0xe8, 0x20, 0xb1, 0xc0, 0x49, 0x78, 0x9f, 0x78, 0xfe, 0x80, 0x4b, 0x19, 0x00, 0x08, 0xda, - 0x11, 0x10, 0xc1, 0x83, 0x92, 0x89, 0x89, 0x82, 0x44, 0x40, 0x85, 0x60, 0x44, 0xb2, 0x06, 0x0b, - 0xc7, 0x3e, 0xb7, 0x07, 0x67, 0x72, 0xf5, 0xcb, 0x27, 0xf6, 0x6e, 0xec, 0x03, 0x18, 0x08, 0x9e, - 0x1a, 0xf1, 0x21, 0x2e, 0x81, 0x92, 0xb9, 0x28, 0xe1, 0x5b, 0x12, 0x2c, 0x76, 0x23, 0xfb, 0xd8, - 0x76, 0x87, 0x9e, 0xcb, 0x87, 0xd2, 0xd4, 0x88, 0x01, 0xc6, 0x21, 0xac, 0xcd, 0x8e, 0x4f, 0xca, - 0x8b, 0x0f, 0x34, 0x79, 0x41, 0x9a, 0xff, 0xc6, 0xf5, 0xac, 0xa0, 0xc9, 0x8e, 0xbf, 0x9f, 0x87, - 0xbc, 0xd0, 0x04, 0xaf, 0x55, 0x1a, 0x75, 0xd5, 0x3e, 0x37, 0x17, 0xfe, 0x41, 0x57, 0x03, 0xa9, - 0x08, 0xe4, 0xcf, 0x2a, 0x23, 0x04, 0x55, 0x83, 0x08, 0xed, 0xf3, 0xc1, 0xb9, 0x74, 0x68, 0x11, - 0xda, 0xe4, 0x83, 0x73, 0xb4, 0xa9, 0xec, 0x90, 0xca, 0xd2, 0x7a, 0x2f, 0x06, 0x76, 0x88, 0x25, - 0x25, 0x0a, 0xcb, 0x15, 0x23, 0x14, 0x96, 0x6a, 0x42, 0xd1, 0x71, 0x8f, 0xbd, 0xa9, 0x3b, 0xc4, - 0xe5, 0x5d, 0x32, 0xd5, 0x23, 0x46, 0x9b, 0x50, 0x12, 0x89, 0x8d, 0x88, 0x56, 0x73, 0x49, 0x00, - 0xfa, 0x62, 0x2b, 0x7a, 0x1f, 0xca, 0xc1, 0x95, 0x3b, 0xd0, 0xd7, 0xf0, 0x8a, 0x9c, 0x1f, 0x31, - 0xfa, 0x07, 0xbd, 0x2b, 0x77, 0x80, 0x2b, 0xb6, 0x14, 0xc8, 0x5f, 0xec, 0x09, 0x94, 0x22, 0xbf, - 0x2f, 0x49, 0xe0, 0x9b, 0x7a, 0x09, 0xe5, 0xec, 0x25, 0xf3, 0x3a, 0x22, 0x65, 0x0f, 0x61, 0x01, - 0x9d, 0xb3, 0x41, 0xb3, 0x8a, 0x85, 0x94, 0xbe, 0x2f, 0xba, 0x81, 0x81, 0x1e, 0x3e, 0x44, 0x47, - 0xad, 0x29, 0xc9, 0x36, 0x9e, 0x41, 0x2d, 0x51, 0x97, 0x6e, 0x44, 0xd7, 0xc8, 0x88, 0x7e, 0x4b, - 0x37, 0xa2, 0xe3, 0x9d, 0x40, 0x16, 0xd3, 0x8d, 0xea, 0x5f, 0x85, 0x92, 0x1a, 0x8a, 0x58, 0x7f, - 0x72, 0xed, 0x58, 0xbd, 0xcf, 0xba, 0x5b, 0x8d, 0x1b, 0x6c, 0x11, 0x2a, 0xad, 0x2d, 0x5c, 0xd2, - 0x08, 0xc8, 0x08, 0x92, 0xc3, 0x56, 0xaf, 0x17, 0x41, 0xb2, 0xc6, 0x0e, 0x34, 0x66, 0x7b, 0x2a, - 0x78, 0x32, 0x54, 0x30, 0xe9, 0xba, 0x8e, 0x01, 0xc2, 0x44, 0x22, 0x6f, 0x34, 0xe9, 0xe1, 0xf4, - 0x60, 0x3c, 0x81, 0x86, 0xd8, 0xd7, 0xc4, 0x54, 0x05, 0x9a, 0x0b, 0x78, 0x24, 0x74, 0x3b, 0xdd, - 0x7d, 0x5d, 0x32, 0x2b, 0x04, 0xc3, 0xa6, 0x8c, 0x0f, 0x60, 0x49, 0x2b, 0x16, 0x9b, 0xb4, 0x62, - 0xaf, 0x9c, 0x35, 0x69, 0xd1, 0x80, 0x21, 0x8c, 0xb1, 0x0e, 0xab, 0xe2, 0xb1, 0x7d, 0xce, 0xdd, - 0xb0, 0x37, 0x3d, 0xa6, 0x98, 0xa3, 0xe3, 0xb9, 0xc2, 0xb0, 0x29, 0x47, 0x98, 0xeb, 0x99, 0xfc, - 0x81, 0xb4, 0x7e, 0xb3, 0xc8, 0x1a, 0x1b, 0x5a, 0x0b, 0x58, 0xf0, 0x01, 0xfe, 0x4d, 0x58, 0xc1, - 0xe5, 0x08, 0x24, 0xa6, 0xf5, 0xb0, 0xdd, 0x36, 0xad, 0x83, 0xee, 0x5e, 0xa7, 0x2b, 0x04, 0xa5, - 0x98, 0x56, 0x04, 0xec, 0xec, 0x20, 0x24, 0x63, 0x34, 0xa0, 0xfe, 0x94, 0x87, 0x1d, 0xf7, 0xc4, - 0x53, 0xf1, 0xb5, 0x9f, 0x15, 0x60, 0x31, 0x02, 0xc5, 0x56, 0xf4, 0x39, 0xf7, 0x03, 0xc7, 0x73, - 0x51, 0x21, 0x2e, 0x9b, 0xea, 0x51, 0xec, 0x6e, 0xce, 0x90, 0xbb, 0xa1, 0x13, 0x5e, 0x59, 0x09, - 0x97, 0x5b, 0x5d, 0x81, 0xe5, 0x2e, 0xba, 0x02, 0x05, 0x7b, 0xe4, 0xd8, 0x2a, 0x54, 0x4b, 0x0f, - 0x02, 0x3a, 0xf0, 0x46, 0x9e, 0x8f, 0xba, 0x6f, 0xd9, 0xa4, 0x07, 0xf6, 0x08, 0x56, 0x84, 0x0e, - 0xae, 0xfb, 0x41, 0x51, 0x7e, 0x90, 0xf7, 0x8f, 0xb9, 0xd3, 0xf1, 0x61, 0xec, 0x0b, 0x15, 0x18, - 0xb1, 0x77, 0x8a, 0x12, 0x52, 0x59, 0x8a, 0x0a, 0x90, 0x39, 0xb7, 0xe4, 0x4e, 0xc7, 0x2d, 0xc4, - 0x44, 0xf4, 0x8f, 0x61, 0x55, 0xd0, 0x47, 0xea, 0x55, 0x54, 0x62, 0x11, 0x4b, 0x88, 0xca, 0x3a, - 0x12, 0x17, 0x95, 0xb9, 0x05, 0x65, 0xea, 0x95, 0x78, 0xe3, 0x05, 0x52, 0xe3, 0xb1, 0x2b, 0xdc, - 0x0f, 0xe6, 0xa2, 0xaa, 0x0b, 0xa4, 0x08, 0xcc, 0x44, 0x55, 0xb5, 0xb8, 0x6c, 0x69, 0x36, 0x2e, - 0xfb, 0x18, 0x56, 0x8f, 0x05, 0x0b, 0x9e, 0x71, 0x7b, 0xc8, 0x7d, 0x2b, 0x66, 0x6c, 0x32, 0x57, - 0x96, 0x05, 0x72, 0x17, 0x71, 0xd1, 0x3a, 0x10, 0x7a, 0x8e, 0x10, 0x0b, 0x7c, 0x68, 0x85, 0x9e, - 0x85, 0xea, 0x0f, 0x0a, 0x98, 0x92, 0x59, 0x23, 0x70, 0xdf, 0xdb, 0x12, 0xc0, 0x24, 0xdd, 0xa9, - 0x6f, 0x4f, 0xce, 0xa4, 0x41, 0x11, 0xd1, 0x3d, 0x15, 0x40, 0xf6, 0x1a, 0x14, 0x05, 0xcb, 0xbb, - 0x9c, 0x82, 0x5f, 0xa4, 0xb2, 0x2b, 0x10, 0x7b, 0x0b, 0x16, 0xb0, 0x8d, 0xa0, 0xd9, 0x40, 0x7e, - 0xaf, 0xc6, 0x82, 0xdc, 0x71, 0x4d, 0x89, 0x13, 0xca, 0xe4, 0xd4, 0x77, 0x48, 0xca, 0x94, 0x4d, - 0xfc, 0xcd, 0xbe, 0xaf, 0x89, 0xac, 0x65, 0x2c, 0xab, 0xf4, 0x81, 0x19, 0x4e, 0xbb, 0x4e, 0x7a, - 0x7d, 0xa5, 0xc2, 0xe8, 0x07, 0xf9, 0x52, 0xa5, 0x51, 0x35, 0xbe, 0x0d, 0x05, 0x9a, 0x1d, 0xc1, - 0x84, 0x38, 0x77, 0x19, 0xc9, 0x84, 0x08, 0x6d, 0x42, 0xd1, 0xe5, 0xe1, 0x85, 0xe7, 0x3f, 0x57, - 0x4e, 0x69, 0xf9, 0x68, 0xfc, 0x18, 0xbd, 0x29, 0x51, 0xc4, 0x9d, 0x0c, 0x43, 0xc1, 0x1e, 0xf4, - 0x7a, 0x83, 0x33, 0x5b, 0x3a, 0x78, 0x4a, 0x08, 0xe8, 0x9d, 0xd9, 0x73, 0xec, 0x91, 0x9d, 0x0f, - 0xba, 0xbf, 0x05, 0x75, 0x15, 0xe3, 0x0f, 0xac, 0x11, 0x3f, 0x09, 0x25, 0xbb, 0x57, 0x65, 0x80, - 0x3f, 0xd8, 0xe3, 0x27, 0xa1, 0xb1, 0x0f, 0x4b, 0x92, 0x21, 0x0f, 0x26, 0x5c, 0x35, 0xfd, 0x9d, - 0x34, 0x7d, 0xba, 0xf2, 0x78, 0x39, 0xb9, 0xd1, 0x52, 0xee, 0x42, 0x42, 0xc9, 0x36, 0x3e, 0x06, - 0xa6, 0x6f, 0xc3, 0xb2, 0x3e, 0xa9, 0xd5, 0x2a, 0x5f, 0xbe, 0x0a, 0x89, 0x45, 0xba, 0xb3, 0x33, - 0x14, 0xb3, 0x13, 0x4c, 0x07, 0x03, 0x95, 0x7b, 0x51, 0x32, 0xd5, 0xa3, 0xf1, 0xe7, 0x19, 0x58, - 0xc6, 0xca, 0x94, 0x3d, 0x20, 0x85, 0xec, 0xcf, 0xdd, 0x49, 0xf1, 0x7e, 0x74, 0xdd, 0x87, 0x1e, - 0xbe, 0xbc, 0xf7, 0x34, 0x3f, 0xe7, 0x3d, 0x7d, 0x17, 0x1a, 0x43, 0x3e, 0x72, 0x30, 0x0d, 0x47, - 0xa9, 0x12, 0x64, 0x01, 0x2c, 0x2a, 0xb8, 0xb4, 0x06, 0x8d, 0x7f, 0x9c, 0x81, 0x25, 0xd2, 0x54, - 0xd0, 0xae, 0x96, 0x13, 0xf5, 0x91, 0x32, 0x24, 0xa5, 0xa8, 0x92, 0x63, 0x8a, 0x77, 0x70, 0x84, - 0x12, 0xf1, 0xee, 0x0d, 0x69, 0x60, 0x4a, 0x28, 0xfb, 0x10, 0x6d, 0x18, 0xd7, 0x42, 0x60, 0x4a, - 0x5a, 0x4f, 0xf2, 0xa5, 0xec, 0xde, 0x40, 0x03, 0xc7, 0x45, 0xd0, 0x66, 0x49, 0x58, 0xb6, 0x02, - 0x6c, 0xec, 0x40, 0x2d, 0xd1, 0x4c, 0xc2, 0xc5, 0x5b, 0x25, 0x17, 0xef, 0x5c, 0x18, 0x25, 0x3b, - 0x1f, 0x46, 0xf9, 0xdb, 0x79, 0x60, 0x82, 0xa5, 0x66, 0xde, 0xda, 0x4c, 0x0c, 0x32, 0x3b, 0x17, - 0x83, 0x7c, 0x04, 0x4c, 0x23, 0x50, 0xa1, 0xd1, 0x5c, 0x14, 0x1a, 0x6d, 0xc4, 0xb4, 0x32, 0x32, - 0xfa, 0x08, 0x56, 0xa4, 0x42, 0x1b, 0x05, 0x1d, 0xd1, 0x77, 0x47, 0xef, 0x87, 0x91, 0x66, 0xab, - 0x82, 0x8f, 0xe8, 0xc7, 0x53, 0xf1, 0x47, 0x61, 0x83, 0x93, 0xcb, 0x0b, 0xe3, 0x8f, 0xca, 0xfa, - 0xd6, 0xb8, 0x60, 0xe1, 0xa5, 0x5c, 0x50, 0x9c, 0xe3, 0x02, 0xcd, 0x03, 0x53, 0x4a, 0x7a, 0x60, - 0x0c, 0xa8, 0xa9, 0x28, 0x23, 0x25, 0x57, 0x90, 0xf6, 0x56, 0x91, 0xa1, 0x46, 0x4c, 0xb0, 0xb8, - 0x07, 0x0d, 0xe5, 0x26, 0x89, 0x7c, 0x3c, 0x94, 0x38, 0x20, 0xbd, 0x6c, 0x5b, 0xca, 0xd3, 0x93, - 0xf0, 0xa8, 0x57, 0x66, 0x3c, 0xea, 0xef, 0xc1, 0x52, 0x20, 0x98, 0xc8, 0x9a, 0xba, 0x32, 0xcb, - 0x87, 0x0f, 0xd1, 0x74, 0x2a, 0x99, 0x0d, 0x44, 0x1c, 0xc5, 0xf0, 0x79, 0xff, 0x45, 0x2d, 0xc5, - 0x7f, 0xf1, 0x24, 0x0e, 0xc8, 0x05, 0x67, 0xce, 0x18, 0x37, 0xee, 0x38, 0x23, 0x46, 0x4e, 0x70, - 0xef, 0xcc, 0x19, 0x9b, 0x2a, 0xfa, 0x2b, 0x1e, 0x8c, 0x7f, 0x97, 0x81, 0x86, 0xe0, 0x83, 0x04, - 0x9f, 0x7f, 0x17, 0x70, 0x45, 0xbe, 0x22, 0x9b, 0x57, 0x04, 0xad, 0xe2, 0xf2, 0x6f, 0x03, 0xb2, - 0xad, 0x25, 0xec, 0x44, 0xc9, 0xe4, 0xcd, 0x24, 0x93, 0xc7, 0x82, 0x6c, 0xf7, 0x06, 0x19, 0x00, - 0x02, 0x92, 0x16, 0x08, 0xcd, 0xa7, 0x04, 0x42, 0xb5, 0xa5, 0xb0, 0x0b, 0xf0, 0x8c, 0x5f, 0xed, - 0x79, 0x03, 0xb4, 0xd0, 0x6e, 0x03, 0x08, 0x86, 0x3c, 0xb1, 0xc7, 0x8e, 0xf4, 0xae, 0x14, 0xcc, - 0xf2, 0x73, 0x7e, 0xb5, 0x83, 0x00, 0xf1, 0x36, 0x04, 0x3a, 0x5e, 0x0f, 0x05, 0xb3, 0xf4, 0x9c, - 0x5f, 0xd1, 0x62, 0xb0, 0xa0, 0xf6, 0x8c, 0x5f, 0x6d, 0x73, 0x52, 0xd7, 0x3c, 0x5f, 0x70, 0x82, - 0x6f, 0x5f, 0x08, 0xfd, 0x2c, 0x11, 0xc4, 0xac, 0xf8, 0xf6, 0xc5, 0x33, 0x7e, 0xa5, 0x02, 0xaa, - 0x45, 0x81, 0x1f, 0x79, 0x03, 0xb9, 0x03, 0xa9, 0x74, 0x8c, 0xb8, 0x53, 0xe6, 0xc2, 0x73, 0xfc, - 0x6d, 0xfc, 0x75, 0x06, 0x6a, 0xa2, 0xff, 0x28, 0xe0, 0xc4, 0xbc, 0xab, 0xac, 0x9e, 0x4c, 0x9c, - 0xd5, 0xf3, 0x58, 0xca, 0x07, 0x92, 0x96, 0xd9, 0xeb, 0xa5, 0x25, 0x4e, 0x30, 0x89, 0xca, 0xf7, - 0xa1, 0x4c, 0x6b, 0x4b, 0x2c, 0xd6, 0x5c, 0xe2, 0x2d, 0x25, 0x06, 0x64, 0x96, 0x90, 0xec, 0x19, - 0x25, 0x11, 0x68, 0x9e, 0x3a, 0x9a, 0xe2, 0xb2, 0x1f, 0xf9, 0xe7, 0x52, 0x5e, 0x43, 0xe1, 0x9a, - 0x24, 0x02, 0xdd, 0x0d, 0xb6, 0x30, 0xe7, 0x06, 0x3b, 0x82, 0x8a, 0xc6, 0x74, 0xe8, 0xf7, 0x8b, - 0x46, 0x47, 0x1c, 0x9a, 0xe4, 0xaa, 0xc4, 0xf4, 0xec, 0xde, 0x30, 0x6b, 0x03, 0x1d, 0xb0, 0xb9, - 0x00, 0x79, 0x51, 0xc8, 0xf8, 0x08, 0x96, 0xb4, 0x6a, 0xc9, 0x5c, 0x4d, 0xeb, 0x74, 0x26, 0x2d, - 0x88, 0xfe, 0x4f, 0x32, 0xb0, 0x22, 0x4b, 0x63, 0x8a, 0x98, 0x23, 0xf6, 0xf3, 0xfd, 0xe0, 0x94, - 0x7d, 0x17, 0x6a, 0xa2, 0x76, 0xcb, 0xe7, 0xa7, 0x4e, 0x10, 0x72, 0x15, 0x23, 0x49, 0x59, 0x3d, - 0x42, 0xac, 0x0b, 0x52, 0x53, 0x52, 0xb2, 0x8f, 0xa0, 0x82, 0x45, 0xc9, 0xa0, 0x96, 0xef, 0xad, - 0x39, 0x5f, 0x90, 0xba, 0xba, 0x7b, 0xc3, 0x84, 0x20, 0x7a, 0xda, 0x2c, 0x43, 0x31, 0xf4, 0x9d, - 0xd3, 0x53, 0xee, 0x1b, 0x6b, 0x51, 0xd7, 0xc4, 0x52, 0xe4, 0xbd, 0x90, 0x4f, 0x84, 0x96, 0x64, - 0xfc, 0xa7, 0x0c, 0x54, 0xe4, 0xe2, 0xfa, 0xb9, 0x03, 0x23, 0x1b, 0x5a, 0x8e, 0x23, 0xd9, 0xce, - 0x71, 0x4a, 0xe3, 0x3b, 0xb0, 0x38, 0x16, 0x1a, 0x93, 0xd0, 0xe8, 0x13, 0x51, 0x91, 0xba, 0x02, - 0x4b, 0x85, 0xe5, 0x01, 0x2c, 0xa3, 0xfe, 0x12, 0x58, 0xa1, 0x33, 0xb2, 0x14, 0x52, 0xe6, 0x13, - 0x2e, 0x11, 0xaa, 0xef, 0x8c, 0xf6, 0x25, 0x42, 0x6c, 0xe3, 0x41, 0x68, 0x9f, 0x72, 0xc9, 0x1b, - 0xf4, 0x60, 0x34, 0x61, 0x6d, 0x46, 0x99, 0x57, 0x86, 0xc8, 0x1f, 0x2e, 0xc1, 0xfa, 0x1c, 0x4a, - 0x1a, 0x24, 0x51, 0x34, 0x60, 0xe4, 0x8c, 0x8f, 0xbd, 0xc8, 0x57, 0x96, 0xd1, 0xa2, 0x01, 0x7b, - 0x02, 0xa3, 0x7c, 0x65, 0x1c, 0x56, 0x15, 0x43, 0xa0, 0xb3, 0x2b, 0xd2, 0xf7, 0xb3, 0xa8, 0x8d, - 0xbe, 0x9f, 0x94, 0x64, 0xb3, 0xcd, 0x29, 0xb8, 0xbe, 0x3f, 0x2e, 0x4f, 0xe6, 0x60, 0x01, 0xfb, - 0x2d, 0x68, 0x46, 0x7c, 0x27, 0x15, 0x28, 0xcd, 0x78, 0x11, 0x2d, 0x7d, 0xfd, 0x25, 0x2d, 0x25, - 0xbc, 0x28, 0xb8, 0x81, 0xae, 0x29, 0x96, 0xa5, 0x0a, 0xa3, 0xb6, 0xce, 0xe1, 0x75, 0xd5, 0x16, - 0x2a, 0x44, 0xf3, 0x2d, 0xe6, 0x5f, 0x69, 0x6c, 0xe8, 0x21, 0x4a, 0x34, 0x6b, 0xde, 0x92, 0x15, - 0x47, 0x28, 0xbd, 0xdd, 0x33, 0x58, 0xbb, 0xb0, 0x9d, 0x50, 0x8d, 0x51, 0xb3, 0x9d, 0x0a, 0xd8, - 0xde, 0xe3, 0x97, 0xb4, 0xf7, 0x29, 0x15, 0x4e, 0xa8, 0x88, 0x2b, 0x17, 0xf3, 0xc0, 0x60, 0xe3, - 0xcf, 0xb2, 0x50, 0x4f, 0xd6, 0x22, 0x16, 0xb6, 0x14, 0x56, 0x4a, 0xe9, 0x90, 0x4a, 0xbb, 0xf4, - 0xe3, 0x76, 0x49, 0xd9, 0x98, 0xf7, 0x30, 0x67, 0x53, 0x3c, 0xcc, 0xba, 0x63, 0x37, 0xf7, 0xb2, - 0x48, 0x5a, 0xfe, 0x95, 0x22, 0x69, 0x85, 0xb4, 0x48, 0xda, 0xf5, 0xe1, 0x97, 0x85, 0x9f, 0x2b, - 0xfc, 0x52, 0x7c, 0x41, 0xf8, 0x25, 0x11, 0x34, 0x2a, 0xcd, 0x04, 0x8d, 0x36, 0xfe, 0x3a, 0x03, - 0x6c, 0x9e, 0x97, 0xd9, 0x53, 0x72, 0xb5, 0xbb, 0x7c, 0x24, 0xe5, 0xdc, 0x37, 0x5e, 0x6d, 0x3d, - 0xa8, 0xd7, 0xa7, 0x4a, 0xb3, 0x87, 0xb0, 0xac, 0xe7, 0x28, 0xeb, 0xd6, 0x4e, 0xcd, 0x64, 0x3a, - 0x2a, 0xb6, 0x89, 0xb5, 0x20, 0x63, 0xfe, 0xa5, 0x41, 0xc6, 0xc2, 0x4b, 0x83, 0x8c, 0x0b, 0xc9, - 0x20, 0xe3, 0xc6, 0x7f, 0xc9, 0xc0, 0x72, 0x0a, 0xcb, 0x7d, 0x75, 0x63, 0x16, 0x9c, 0x92, 0x10, - 0x42, 0x59, 0xc9, 0x29, 0xba, 0xfc, 0xd9, 0x83, 0x4a, 0x1c, 0xb7, 0x52, 0x39, 0xfc, 0xf7, 0x5f, - 0x26, 0x0b, 0xe2, 0x12, 0xa6, 0x5e, 0x7c, 0xe3, 0x0f, 0xb2, 0x50, 0xd1, 0x90, 0x62, 0x16, 0x89, - 0xc1, 0xb4, 0xdc, 0x0e, 0xd2, 0x03, 0xd0, 0x56, 0xbb, 0x03, 0xd2, 0x19, 0x4c, 0x78, 0x5a, 0x0a, - 0x72, 0xd3, 0x47, 0x82, 0x07, 0xb0, 0xac, 0xc2, 0x20, 0x3c, 0x4e, 0xe1, 0x92, 0x3b, 0xc3, 0x92, - 0x0c, 0x86, 0xf0, 0x28, 0x23, 0x8c, 0x3d, 0x54, 0x1a, 0x7c, 0xfc, 0xee, 0x90, 0x31, 0xc9, 0xd3, - 0xba, 0x44, 0xec, 0xac, 0x5e, 0xa2, 0xe0, 0xca, 0xf7, 0x61, 0x55, 0x31, 0x73, 0xb2, 0x04, 0x39, - 0x5f, 0x99, 0x64, 0x65, 0xbd, 0xc8, 0xf7, 0xe1, 0xf6, 0x4c, 0x9f, 0x66, 0x8a, 0x52, 0xae, 0xe1, - 0xcd, 0x44, 0xef, 0xf4, 0x1a, 0x36, 0x7e, 0x02, 0xb5, 0x84, 0x58, 0xfb, 0xea, 0x5e, 0xf9, 0xac, - 0x7d, 0x4c, 0x33, 0xaa, 0xdb, 0xc7, 0x1b, 0xff, 0x27, 0x07, 0x6c, 0x5e, 0xb2, 0xfe, 0x32, 0xbb, - 0x30, 0xcf, 0x98, 0xb9, 0x14, 0xc6, 0xfc, 0x7f, 0xb6, 0xdb, 0xbf, 0x07, 0x4b, 0xf2, 0x2c, 0x8b, - 0x16, 0xcb, 0xa2, 0xc5, 0xd9, 0x88, 0x10, 0xaa, 0x17, 0xdf, 0x9e, 0x8d, 0xa9, 0x97, 0x12, 0xe9, - 0xfb, 0x9a, 0xba, 0x33, 0x13, 0x5a, 0x3f, 0x82, 0x05, 0xdb, 0x1d, 0x9c, 0x79, 0x3e, 0x9a, 0x66, - 0xf5, 0xc7, 0xbf, 0xf2, 0xa5, 0x37, 0xbb, 0x07, 0x2d, 0x2c, 0x8f, 0x3a, 0x96, 0x29, 0x2b, 0x33, - 0xde, 0x87, 0x8a, 0x06, 0xc6, 0xf8, 0x4e, 0x67, 0x7f, 0xf3, 0xa0, 0x71, 0x83, 0xd5, 0xa0, 0x6c, - 0xb6, 0xb7, 0x0e, 0x3e, 0x69, 0x9b, 0xed, 0xed, 0x46, 0x86, 0x95, 0x20, 0xbf, 0x77, 0xd0, 0xeb, - 0x37, 0xb2, 0xc6, 0x06, 0x34, 0x65, 0x8d, 0xf3, 0xbe, 0xde, 0xdf, 0xcd, 0x47, 0x6e, 0x16, 0x44, - 0x4a, 0xab, 0xea, 0x9b, 0x50, 0xd5, 0x95, 0x11, 0xc9, 0x11, 0x33, 0xe1, 0x54, 0x61, 0x4f, 0x79, - 0x9a, 0xac, 0xde, 0x02, 0x0a, 0x92, 0x0d, 0xa3, 0x62, 0xa4, 0x61, 0xbe, 0x20, 0xaa, 0x82, 0xca, - 0x73, 0x82, 0x0d, 0xff, 0x3f, 0xa8, 0x27, 0x1d, 0x9f, 0x52, 0x22, 0xa5, 0x99, 0x17, 0xa2, 0x74, - 0xc2, 0x13, 0xca, 0xbe, 0x0f, 0x8d, 0x59, 0xc7, 0xa9, 0xcc, 0x72, 0xbe, 0xa6, 0xfc, 0xa2, 0x93, - 0xf4, 0xa5, 0xb2, 0x5d, 0x58, 0x49, 0x53, 0xc7, 0x90, 0x3f, 0xae, 0xb7, 0x2b, 0xd9, 0xbc, 0xca, - 0xc5, 0xbe, 0x23, 0xfd, 0xe3, 0x85, 0xb4, 0x28, 0xa3, 0x36, 0xd9, 0x0f, 0xe8, 0x9f, 0xe6, 0x29, - 0x3f, 0x07, 0x88, 0x61, 0xac, 0x01, 0xd5, 0x83, 0xc3, 0x76, 0xd7, 0xda, 0xda, 0x6d, 0x75, 0xbb, - 0xed, 0xbd, 0xc6, 0x0d, 0xc6, 0xa0, 0x8e, 0xe1, 0xc1, 0xed, 0x08, 0x96, 0x11, 0x30, 0x19, 0xa7, - 0x50, 0xb0, 0x2c, 0x5b, 0x81, 0x46, 0xa7, 0x3b, 0x03, 0xcd, 0xb1, 0x26, 0xac, 0x1c, 0xb6, 0x29, - 0xa2, 0x98, 0xa8, 0x37, 0x2f, 0x54, 0x7c, 0x39, 0x5c, 0xa1, 0xe2, 0xd3, 0x99, 0x2c, 0xb9, 0x0e, - 0x94, 0xe6, 0xfb, 0x7b, 0x19, 0x58, 0x9d, 0x41, 0xc4, 0x99, 0xf6, 0xa4, 0xf7, 0x26, 0x35, 0xde, - 0x2a, 0x02, 0xd5, 0x6a, 0x7a, 0x0f, 0x96, 0x22, 0x5f, 0xc1, 0xcc, 0xae, 0xd4, 0x88, 0x10, 0x8a, - 0xf8, 0x21, 0x2c, 0x6b, 0x2e, 0x87, 0x19, 0x59, 0xc1, 0x34, 0x94, 0x2c, 0x60, 0xac, 0x47, 0x19, - 0xcd, 0x33, 0xbd, 0x1e, 0xd2, 0x41, 0x2f, 0x1d, 0x11, 0x87, 0x0f, 0x92, 0xfd, 0x55, 0x8f, 0xec, - 0xd1, 0x0c, 0x23, 0x24, 0x7b, 0xab, 0xbf, 0x70, 0xd5, 0xfc, 0x1f, 0x2d, 0x00, 0xfb, 0x78, 0xca, - 0xfd, 0x2b, 0xcc, 0xa4, 0x0f, 0x5e, 0x96, 0x5a, 0xa6, 0xec, 0xea, 0xec, 0x2b, 0x9d, 0x96, 0x49, - 0x3b, 0xad, 0x92, 0x7f, 0xf9, 0x69, 0x95, 0xc2, 0xcb, 0x4e, 0xab, 0xbc, 0x09, 0x35, 0xe7, 0xd4, - 0xf5, 0x84, 0x28, 0x14, 0x7a, 0x6b, 0xd0, 0x5c, 0xb8, 0x9b, 0xbb, 0x57, 0x35, 0xab, 0x12, 0x28, - 0xb4, 0xd6, 0x80, 0x7d, 0x14, 0x13, 0xf1, 0xe1, 0x29, 0x9e, 0xac, 0xd2, 0x85, 0x60, 0x7b, 0x78, - 0xca, 0xa5, 0x1b, 0x01, 0xed, 0x02, 0x55, 0x58, 0xc0, 0x03, 0xf6, 0x16, 0xd4, 0x03, 0x6f, 0x2a, - 0xcc, 0x00, 0x35, 0x0d, 0x14, 0x60, 0xa8, 0x12, 0xf4, 0x50, 0x45, 0x93, 0x96, 0xa7, 0x01, 0xb7, - 0xc6, 0x4e, 0x10, 0x08, 0xf5, 0x6c, 0xe0, 0xb9, 0xa1, 0xef, 0x8d, 0x64, 0xcc, 0x60, 0x69, 0x1a, - 0xf0, 0x7d, 0xc2, 0x6c, 0x11, 0x82, 0x7d, 0x2b, 0xee, 0xd2, 0xc4, 0x76, 0xfc, 0xa0, 0x09, 0xd8, - 0x25, 0x35, 0x52, 0xd4, 0xb6, 0x6d, 0xc7, 0x8f, 0xfa, 0x22, 0x1e, 0x82, 0x99, 0x53, 0x34, 0x95, - 0xd9, 0x53, 0x34, 0x3f, 0x4a, 0x3f, 0x45, 0x53, 0xc3, 0xaa, 0x1f, 0xc9, 0xaa, 0xe7, 0x5f, 0xf1, - 0x97, 0x3a, 0x4c, 0x33, 0x7f, 0x38, 0xa8, 0xfe, 0x65, 0x0e, 0x07, 0x2d, 0xa6, 0x1d, 0x0e, 0x7a, - 0x1f, 0x2a, 0x78, 0x6c, 0xc3, 0x3a, 0x73, 0x84, 0x0e, 0x47, 0x31, 0x90, 0x86, 0x7e, 0xae, 0x63, - 0xd7, 0x71, 0x43, 0x13, 0x7c, 0xf5, 0x33, 0x98, 0x3f, 0xa7, 0xb3, 0xf4, 0x4b, 0x3c, 0xa7, 0x23, - 0x8f, 0x97, 0x3c, 0x80, 0x92, 0x7a, 0x4f, 0x8c, 0x41, 0xfe, 0xc4, 0xf7, 0xc6, 0xca, 0x37, 0x2c, - 0x7e, 0xb3, 0x3a, 0x64, 0x43, 0x4f, 0x16, 0xce, 0x86, 0x9e, 0xf1, 0x9b, 0x50, 0xd1, 0x58, 0x8d, - 0xbd, 0x41, 0x5e, 0x28, 0x61, 0x49, 0x49, 0xdd, 0x92, 0x66, 0xb1, 0x2c, 0xa1, 0x9d, 0xa1, 0x90, - 0x37, 0x43, 0xc7, 0xe7, 0x78, 0xa2, 0xce, 0xf2, 0xf9, 0x39, 0xf7, 0x03, 0xe5, 0xab, 0x6f, 0x44, - 0x08, 0x93, 0xe0, 0xc6, 0xff, 0x0f, 0xcb, 0x89, 0x77, 0x2b, 0x45, 0xc4, 0x5b, 0xb0, 0x80, 0xf3, - 0xa6, 0x62, 0xa9, 0xc9, 0xf3, 0x32, 0x12, 0x87, 0x47, 0xa5, 0x29, 0xcc, 0x60, 0x4d, 0x7c, 0xef, - 0x18, 0x1b, 0xc9, 0x98, 0x15, 0x09, 0x3b, 0xf4, 0xbd, 0x63, 0xe3, 0x2f, 0x73, 0x90, 0xdb, 0xf5, - 0x26, 0x7a, 0xfa, 0x50, 0x66, 0x2e, 0x7d, 0x48, 0x9a, 0x87, 0x56, 0x64, 0xfe, 0x49, 0x9d, 0x1d, - 0x1d, 0xec, 0xca, 0x04, 0xbc, 0x07, 0x75, 0x21, 0x27, 0x42, 0x4f, 0xd8, 0xd7, 0x17, 0xb6, 0x4f, - 0x0a, 0x71, 0x8e, 0x16, 0x9f, 0x3d, 0x0e, 0xfb, 0xde, 0x0e, 0xc1, 0xd9, 0x0a, 0xe4, 0x22, 0xf3, - 0x05, 0xd1, 0xe2, 0x91, 0xad, 0xc1, 0x02, 0xe6, 0x91, 0x5e, 0xc9, 0x60, 0xa1, 0x7c, 0x62, 0xdf, - 0x80, 0xe5, 0x64, 0xbd, 0x24, 0x8a, 0xa4, 0x6e, 0xa4, 0x57, 0x8c, 0x32, 0xe9, 0x26, 0x08, 0x39, - 0x42, 0x34, 0x32, 0xe7, 0xe0, 0x84, 0x73, 0x44, 0x69, 0x42, 0xaf, 0x94, 0x10, 0x7a, 0x77, 0xa0, - 0x12, 0x8e, 0xce, 0xad, 0x89, 0x7d, 0x35, 0xf2, 0xec, 0xa1, 0x5c, 0xdf, 0x10, 0x8e, 0xce, 0x0f, - 0x09, 0xc2, 0x1e, 0x02, 0x8c, 0x27, 0x13, 0xb9, 0xf6, 0xd0, 0x5f, 0x1d, 0xb3, 0xf2, 0xfe, 0xe1, - 0x21, 0xb1, 0x9c, 0x59, 0x1e, 0x4f, 0x26, 0xf4, 0x93, 0x6d, 0x43, 0x3d, 0xf5, 0xd4, 0xdb, 0x6d, - 0x95, 0xf6, 0xe8, 0x4d, 0x1e, 0xa4, 0x2c, 0xce, 0xda, 0x40, 0x87, 0x6d, 0x7c, 0x1f, 0xd8, 0x2f, - 0x78, 0xf6, 0xac, 0x0f, 0xe5, 0xa8, 0x7f, 0xfa, 0xd1, 0x2d, 0x4c, 0x64, 0xae, 0x24, 0x8e, 0x6e, - 0xb5, 0x86, 0x43, 0x5f, 0xc8, 0x45, 0xda, 0x30, 0x23, 0x91, 0x0f, 0xda, 0x8e, 0xd9, 0x22, 0xb9, - 0x6f, 0xfc, 0xf7, 0x0c, 0x14, 0xe8, 0x1c, 0xd9, 0xdb, 0xb0, 0x48, 0xf4, 0x51, 0x2a, 0x96, 0x0c, - 0x31, 0xd2, 0xbe, 0xdb, 0x97, 0x59, 0x58, 0x62, 0x59, 0x68, 0x67, 0x60, 0xb3, 0xd1, 0x9b, 0xd7, - 0xce, 0xc1, 0xde, 0x81, 0x72, 0xd4, 0xb4, 0xc6, 0x3a, 0x25, 0xd5, 0x32, 0x7b, 0x1d, 0xf2, 0x67, - 0xde, 0x44, 0xf9, 0x69, 0x20, 0x9e, 0x49, 0x13, 0xe1, 0x71, 0x5f, 0x44, 0x1b, 0xd4, 0x79, 0xe9, - 0x5f, 0x88, 0x1a, 0x41, 0x36, 0x98, 0x1f, 0xe3, 0x42, 0xca, 0x18, 0x8f, 0x60, 0x51, 0xc8, 0x01, - 0x2d, 0xd4, 0x7f, 0xfd, 0xa6, 0xf9, 0xae, 0xd0, 0xf0, 0x06, 0xa3, 0xe9, 0x90, 0xeb, 0x9e, 0x32, - 0xcc, 0x0b, 0x92, 0x70, 0xa5, 0x59, 0x1b, 0x7f, 0x94, 0x21, 0xf9, 0x22, 0xea, 0x65, 0xf7, 0x20, - 0x2f, 0xf6, 0xb7, 0x19, 0x4f, 0x6e, 0x94, 0x51, 0x2e, 0xe8, 0x4c, 0xa4, 0xc0, 0x83, 0xe3, 0xd3, - 0x71, 0xb2, 0xf6, 0x9a, 0x59, 0x71, 0xa7, 0xe3, 0xc8, 0xd1, 0xf4, 0x35, 0x35, 0xac, 0x19, 0x27, - 0x0d, 0x8d, 0x3e, 0x5a, 0xa6, 0x0f, 0xb4, 0x04, 0xa3, 0x7c, 0x62, 0xc7, 0x54, 0x5a, 0xe0, 0xf0, - 0x94, 0x6b, 0x89, 0x45, 0x7f, 0x92, 0x85, 0x5a, 0xa2, 0x47, 0x98, 0x61, 0x25, 0x36, 0x00, 0x0a, - 0x23, 0xc8, 0xf7, 0x0d, 0x02, 0x24, 0x15, 0x75, 0x6d, 0x9e, 0xb2, 0x89, 0x79, 0x8a, 0x92, 0x1a, - 0x72, 0x7a, 0x52, 0xc3, 0x23, 0x28, 0xc7, 0x67, 0x9f, 0x93, 0x5d, 0x12, 0xed, 0xa9, 0xbc, 0xfa, - 0x98, 0x28, 0x4e, 0x83, 0x28, 0xe8, 0x69, 0x10, 0xdf, 0xd3, 0xa2, 0xe6, 0x0b, 0x58, 0x8d, 0x91, - 0x36, 0xa3, 0xbf, 0x94, 0x98, 0xb9, 0xf1, 0x11, 0x54, 0xb4, 0xce, 0xeb, 0xd1, 0xf1, 0x4c, 0x22, - 0x3a, 0x1e, 0x9d, 0x80, 0xc9, 0xc6, 0x27, 0x60, 0x8c, 0xdf, 0xce, 0x42, 0x4d, 0xac, 0x2f, 0xc7, - 0x3d, 0x3d, 0xf4, 0x46, 0xce, 0x00, 0xc3, 0x0a, 0xd1, 0x0a, 0x93, 0x8a, 0x96, 0x5a, 0x67, 0x72, - 0x89, 0x91, 0x9e, 0xa5, 0x1f, 0xf4, 0x23, 0x21, 0x1d, 0x1d, 0xf4, 0x33, 0xa0, 0x26, 0x04, 0xe3, - 0xb1, 0x1d, 0x70, 0xed, 0x64, 0xb6, 0x59, 0x39, 0xe1, 0x7c, 0xd3, 0x0e, 0x48, 0x42, 0x7e, 0x03, - 0x96, 0x05, 0x0d, 0x9e, 0x71, 0x1a, 0x3b, 0xa3, 0x91, 0x43, 0x94, 0xe4, 0x68, 0x6a, 0x9c, 0x70, - 0x6e, 0xda, 0x21, 0xdf, 0x17, 0x08, 0x79, 0x90, 0xbb, 0x34, 0x74, 0x02, 0xfb, 0x38, 0xce, 0x83, - 0x8b, 0x9e, 0x31, 0x18, 0x68, 0x5f, 0x6a, 0xc1, 0x40, 0x72, 0x40, 0x54, 0xc6, 0xf6, 0x65, 0x14, - 0x0c, 0x9c, 0xe1, 0xa4, 0xe2, 0x2c, 0x27, 0x19, 0xff, 0x21, 0x0b, 0x15, 0x8d, 0x2d, 0x5f, 0x65, - 0x77, 0xbd, 0x3d, 0x17, 0x06, 0x2a, 0xeb, 0x11, 0x9f, 0x37, 0x93, 0x4d, 0x62, 0xce, 0x00, 0x1d, - 0x19, 0xd7, 0x18, 0xf8, 0x16, 0x94, 0xc5, 0xaa, 0x7b, 0x1f, 0x1d, 0xa6, 0xf2, 0xc2, 0x03, 0x04, - 0x1c, 0x4e, 0x8f, 0x15, 0xf2, 0x31, 0x22, 0x0b, 0x31, 0xf2, 0xb1, 0x40, 0xbe, 0x28, 0xf9, 0xf5, - 0xdb, 0x50, 0x95, 0xb5, 0xe2, 0x3b, 0xc5, 0xe1, 0xc6, 0xab, 0x3e, 0xf1, 0xbe, 0xcd, 0x0a, 0x35, - 0x47, 0x2f, 0x5f, 0x16, 0x7c, 0xac, 0x0a, 0x96, 0x5e, 0x56, 0xf0, 0x31, 0x3d, 0x18, 0x3b, 0x51, - 0x3e, 0x31, 0xe6, 0xab, 0x28, 0x39, 0xf6, 0x10, 0x96, 0x95, 0xb8, 0x9a, 0xba, 0xb6, 0xeb, 0x7a, - 0x53, 0x77, 0xc0, 0xd5, 0xd1, 0x18, 0x26, 0x51, 0x47, 0x31, 0xc6, 0x18, 0x46, 0x67, 0x27, 0x29, - 0xef, 0xe5, 0x3e, 0x14, 0x48, 0x2f, 0x27, 0xe5, 0x23, 0x5d, 0x70, 0x11, 0x09, 0xbb, 0x07, 0x05, - 0x52, 0xcf, 0xb3, 0xd7, 0x0a, 0x1b, 0x22, 0x30, 0x5a, 0xc0, 0x44, 0xc1, 0x7d, 0x1e, 0xfa, 0xce, - 0x20, 0x88, 0x4f, 0xdd, 0x14, 0x84, 0xfd, 0x49, 0x6d, 0xc5, 0x69, 0xee, 0x31, 0x25, 0xda, 0xa8, - 0x44, 0x23, 0x36, 0xa6, 0xe5, 0x44, 0x1d, 0x52, 0x5d, 0x1a, 0xc1, 0xda, 0x31, 0x0f, 0x2f, 0x38, - 0x77, 0x5d, 0xa1, 0x0c, 0x0d, 0xb8, 0x1b, 0xfa, 0xf6, 0x48, 0xbc, 0x24, 0x1a, 0xc1, 0x93, 0xb9, - 0x5a, 0x63, 0x1f, 0xc8, 0x66, 0x5c, 0x70, 0x2b, 0x2a, 0x47, 0xb2, 0x63, 0xf5, 0x38, 0x0d, 0xb7, - 0xf1, 0x1b, 0xb0, 0x71, 0x7d, 0xa1, 0x94, 0xb3, 0x75, 0xf7, 0x92, 0x52, 0x25, 0x8a, 0x9a, 0x8d, - 0x3c, 0x3b, 0xa4, 0xde, 0xe8, 0x92, 0xa5, 0x0b, 0x15, 0x0d, 0x13, 0xef, 0xfd, 0x19, 0x54, 0xee, - 0xe8, 0x41, 0xec, 0x48, 0xae, 0xe7, 0x8f, 0xed, 0x91, 0xf3, 0x63, 0x3e, 0xb4, 0xe2, 0xda, 0x33, - 0xe6, 0x62, 0x0c, 0xc7, 0xc3, 0xc4, 0xc6, 0x03, 0x58, 0x44, 0xcd, 0x5e, 0xdb, 0xe8, 0x5e, 0xa4, - 0x0c, 0x1a, 0x2b, 0xc0, 0xba, 0x24, 0xbb, 0xf4, 0x34, 0xb8, 0xff, 0x9a, 0x83, 0x8a, 0x06, 0x16, - 0xbb, 0x11, 0x26, 0x4e, 0x59, 0x43, 0xc7, 0x1e, 0x73, 0x15, 0x12, 0xac, 0x99, 0x35, 0x84, 0x6e, - 0x4b, 0xa0, 0xd8, 0x8b, 0xed, 0xf3, 0x53, 0xcb, 0x9b, 0x86, 0xd6, 0x90, 0x9f, 0xfa, 0x5c, 0xf5, - 0xb2, 0x6a, 0x9f, 0x9f, 0x1e, 0x4c, 0xc3, 0x6d, 0x84, 0x09, 0x2a, 0x21, 0x4b, 0x34, 0x2a, 0x99, - 0xeb, 0x33, 0xb6, 0x2f, 0x63, 0x2a, 0x99, 0x70, 0x46, 0x9c, 0x99, 0x8f, 0x12, 0xce, 0xc8, 0x5a, - 0x9c, 0xdd, 0x40, 0x0b, 0xf3, 0x1b, 0xe8, 0xb7, 0x60, 0x8d, 0x36, 0x50, 0x29, 0x9a, 0xad, 0x99, - 0x95, 0xbc, 0x82, 0x58, 0x39, 0x48, 0x4d, 0xed, 0x6d, 0x88, 0x11, 0x28, 0xb1, 0x14, 0x38, 0x3f, - 0x26, 0x41, 0x96, 0x31, 0xc5, 0xc8, 0x64, 0xe5, 0x3d, 0xe7, 0xc7, 0x5c, 0x50, 0x62, 0x42, 0x83, - 0x4e, 0x29, 0x53, 0xdb, 0xc7, 0x8e, 0x3b, 0x4b, 0x69, 0x5f, 0x26, 0x29, 0xcb, 0x92, 0xd2, 0xbe, - 0xd4, 0x29, 0x9f, 0xc0, 0xfa, 0x98, 0x0f, 0x1d, 0x3b, 0x59, 0xad, 0x15, 0x2b, 0x6e, 0x2b, 0x84, - 0xd6, 0xca, 0xf4, 0xc8, 0x70, 0x17, 0xb3, 0xf1, 0x63, 0x6f, 0x7c, 0xec, 0x90, 0xce, 0x42, 0x29, - 0x16, 0x79, 0xb3, 0xee, 0x4e, 0xc7, 0x3f, 0x44, 0xb0, 0x28, 0x12, 0x18, 0x35, 0xa8, 0xf4, 0x42, - 0x6f, 0xa2, 0x5e, 0x73, 0x1d, 0xaa, 0xf4, 0x28, 0xcf, 0x9b, 0xdd, 0x82, 0x9b, 0x28, 0x12, 0xfa, - 0xde, 0xc4, 0x1b, 0x79, 0xa7, 0x57, 0x09, 0x3f, 0xde, 0x7f, 0xce, 0xc0, 0x72, 0x02, 0x2b, 0xc5, - 0xeb, 0xb7, 0x48, 0x9e, 0x45, 0x87, 0x86, 0x68, 0x0d, 0x2e, 0x69, 0x6b, 0x90, 0x08, 0x49, 0x98, - 0xa9, 0x83, 0x44, 0xad, 0xf8, 0xb0, 0xbb, 0x2a, 0x48, 0x22, 0xa5, 0x39, 0x2f, 0x52, 0x64, 0x79, - 0x75, 0x0c, 0x5e, 0x55, 0xf1, 0x2b, 0xf2, 0xf8, 0xc1, 0x50, 0x0e, 0x39, 0x97, 0x4c, 0xb0, 0xd6, - 0x7d, 0x7e, 0xaa, 0x07, 0xb1, 0x23, 0x30, 0x30, 0xfe, 0x65, 0x06, 0x20, 0xee, 0x1d, 0xa6, 0x78, - 0x47, 0x7a, 0x0b, 0xdd, 0x23, 0xa5, 0xe9, 0x28, 0x6f, 0x40, 0x35, 0xca, 0xf4, 0x8c, 0x35, 0xa1, - 0x8a, 0x82, 0x09, 0x75, 0xe8, 0x1d, 0x58, 0x3c, 0x1d, 0x79, 0xc7, 0xa8, 0xb1, 0x4a, 0xbd, 0x85, - 0x4e, 0xdd, 0xd5, 0x09, 0xac, 0xb4, 0x91, 0x58, 0x6f, 0xca, 0xa7, 0x26, 0x83, 0xea, 0x5a, 0x90, - 0xf1, 0x3b, 0xd9, 0x28, 0xe5, 0x2d, 0x9e, 0x89, 0x17, 0x9b, 0x77, 0x3f, 0x4f, 0xe6, 0xc4, 0x8b, - 0x82, 0x81, 0x1f, 0x41, 0xdd, 0xa7, 0x4d, 0x49, 0xed, 0x58, 0xf9, 0x17, 0xec, 0x58, 0x35, 0x3f, - 0xa1, 0xe9, 0xbc, 0x0b, 0x0d, 0x7b, 0x78, 0xce, 0xfd, 0xd0, 0x41, 0x6f, 0x3d, 0xea, 0xc7, 0x32, - 0xc9, 0x4c, 0x83, 0xa3, 0x22, 0xfa, 0x0e, 0x2c, 0xca, 0x33, 0x90, 0x11, 0xa5, 0xbc, 0x55, 0x25, - 0x06, 0x0b, 0x42, 0xe3, 0x5f, 0xab, 0x1c, 0xbb, 0xe4, 0xdb, 0x7d, 0xf1, 0xac, 0xe8, 0x23, 0xcc, - 0xce, 0x87, 0x3b, 0x25, 0x23, 0xc9, 0x20, 0x80, 0x94, 0x47, 0x04, 0x94, 0x21, 0x80, 0xe4, 0xb4, - 0xe6, 0x5f, 0x65, 0x5a, 0x8d, 0x3f, 0xcb, 0x40, 0x71, 0xd7, 0x9b, 0xec, 0x3a, 0x94, 0xe4, 0x8c, - 0xcb, 0x24, 0x8a, 0x51, 0x2d, 0x88, 0xc7, 0xce, 0xf0, 0xc5, 0x47, 0x7d, 0x52, 0xd5, 0xbc, 0x5a, - 0x52, 0xcd, 0xfb, 0x1e, 0xdc, 0xc2, 0x10, 0xa0, 0xef, 0x4d, 0x3c, 0x5f, 0x2c, 0x55, 0x7b, 0x44, - 0xea, 0x9e, 0xe7, 0x86, 0x67, 0x4a, 0x76, 0xde, 0x3c, 0xe1, 0xfc, 0x50, 0xa3, 0xd8, 0x8f, 0x08, - 0xf0, 0x30, 0xdd, 0x28, 0x3c, 0xb7, 0xc8, 0x42, 0x97, 0xfa, 0x28, 0x49, 0xd4, 0x45, 0x81, 0x68, - 0x23, 0x1c, 0x35, 0x52, 0xe3, 0x3b, 0x50, 0x8e, 0x9c, 0x3d, 0xec, 0x3d, 0x28, 0x9f, 0x79, 0x13, - 0xe9, 0x11, 0xca, 0x24, 0x8e, 0x43, 0xc9, 0x51, 0x9b, 0xa5, 0x33, 0xfa, 0x11, 0x18, 0x7f, 0x59, - 0x84, 0x62, 0xc7, 0x3d, 0xf7, 0x9c, 0x01, 0x66, 0xe9, 0x8d, 0xf9, 0xd8, 0x53, 0x07, 0xb1, 0xc5, - 0x6f, 0xcc, 0xc4, 0x89, 0xef, 0x46, 0xc9, 0xc9, 0x4c, 0x9c, 0xe8, 0x56, 0x94, 0x55, 0x58, 0xf0, - 0xf5, 0xcb, 0x4d, 0x0a, 0x3e, 0xe6, 0x0d, 0x47, 0xfb, 0x65, 0x41, 0x3b, 0xc8, 0x2e, 0xea, 0xa2, - 0x4b, 0x37, 0x70, 0xca, 0xe8, 0x60, 0x5c, 0x19, 0x21, 0x38, 0x61, 0xaf, 0x41, 0x51, 0x9e, 0x3e, - 0xa2, 0xb3, 0x1c, 0x94, 0xe8, 0x2b, 0x41, 0xc8, 0x0d, 0x3e, 0xa7, 0x10, 0x6e, 0xa4, 0xc8, 0xe6, - 0xcc, 0xaa, 0x02, 0x6e, 0x0b, 0x5e, 0xbb, 0x03, 0x15, 0xa2, 0x27, 0x92, 0x92, 0xcc, 0xab, 0x43, - 0x10, 0x12, 0xa4, 0xdc, 0x11, 0x54, 0x4e, 0xbd, 0x23, 0x08, 0xd3, 0x30, 0x23, 0x29, 0x4b, 0x43, - 0x04, 0xba, 0x19, 0x46, 0x83, 0xab, 0x0b, 0xb2, 0xa4, 0x4f, 0x85, 0xce, 0x89, 0x2a, 0x9f, 0xca, - 0x9b, 0x50, 0x3b, 0xb1, 0x47, 0xa3, 0x63, 0x7b, 0xf0, 0x9c, 0x5c, 0x01, 0x55, 0xf2, 0x7e, 0x2a, - 0x20, 0xfa, 0x02, 0xee, 0x40, 0x45, 0x7b, 0xcb, 0x98, 0x34, 0x97, 0x37, 0x21, 0x7e, 0xbf, 0xb3, - 0x1e, 0xbe, 0xfa, 0x2b, 0x78, 0xf8, 0xb4, 0xe4, 0xc1, 0xc5, 0x64, 0xf2, 0xe0, 0x2d, 0x94, 0xa6, - 0x32, 0xc1, 0xac, 0x41, 0xd7, 0x90, 0xd8, 0xc3, 0x21, 0x26, 0x98, 0xd1, 0x9d, 0x7f, 0x38, 0x79, - 0x84, 0x5f, 0x22, 0x5b, 0x82, 0x60, 0x44, 0x72, 0x9b, 0xdc, 0xd4, 0x13, 0xdb, 0x19, 0x62, 0xb2, - 0x36, 0x79, 0x0f, 0x8a, 0xf6, 0x38, 0x3c, 0xb4, 0x9d, 0x21, 0xbb, 0x0b, 0x55, 0x85, 0xc6, 0xdd, - 0x71, 0x99, 0xe6, 0x5f, 0xa2, 0xc5, 0x9e, 0x68, 0x40, 0x2d, 0xa2, 0x18, 0xc7, 0x87, 0x3d, 0x2b, - 0x92, 0x04, 0xf9, 0xe0, 0x7d, 0xcc, 0xc9, 0x09, 0x39, 0x1e, 0xe9, 0xac, 0x3f, 0xbe, 0x25, 0xc7, - 0x2a, 0xb9, 0x54, 0xfd, 0xa7, 0xe0, 0x18, 0x51, 0x0a, 0xe5, 0x8e, 0x62, 0x74, 0x6b, 0x09, 0xfd, - 0x57, 0x92, 0x62, 0x8c, 0x8e, 0x08, 0xd8, 0x77, 0x34, 0xfb, 0xb5, 0x89, 0xc4, 0xaf, 0xcd, 0xd4, - 0x7f, 0xdd, 0x59, 0x95, 0xdb, 0x00, 0x4e, 0x20, 0x76, 0x99, 0x80, 0xbb, 0x43, 0x3c, 0x9d, 0x59, - 0x32, 0xcb, 0x4e, 0xf0, 0x8c, 0x00, 0x5f, 0xad, 0x61, 0xdb, 0x82, 0xaa, 0x3e, 0x4c, 0x56, 0x82, - 0xfc, 0xc1, 0x61, 0xbb, 0xdb, 0xb8, 0xc1, 0x2a, 0x50, 0xec, 0xb5, 0xfb, 0xfd, 0x3d, 0x8c, 0xf4, - 0x55, 0xa1, 0x14, 0x1d, 0x0d, 0xcb, 0x8a, 0xa7, 0xd6, 0xd6, 0x56, 0xfb, 0xb0, 0xdf, 0xde, 0x6e, - 0xe4, 0x7e, 0x90, 0x2f, 0x65, 0x1b, 0x39, 0xe3, 0xaf, 0x72, 0x50, 0xd1, 0x66, 0xe1, 0xc5, 0xc2, - 0xf8, 0x36, 0x00, 0x5a, 0x92, 0x71, 0xfe, 0x61, 0xde, 0x2c, 0x0b, 0x08, 0xbd, 0x7c, 0x3d, 0x46, - 0x91, 0xa3, 0xfb, 0x6d, 0x54, 0x8c, 0xe2, 0x4d, 0xa8, 0xd1, 0x55, 0x31, 0x7a, 0xbc, 0xb6, 0x60, - 0x56, 0x09, 0x28, 0x45, 0x35, 0x9e, 0x2d, 0x45, 0x22, 0x3c, 0x75, 0x24, 0x2f, 0x8e, 0x20, 0x10, - 0x9e, 0x3b, 0xc2, 0x43, 0x63, 0x81, 0x37, 0x3a, 0xe7, 0x44, 0x41, 0x1a, 0x61, 0x45, 0xc2, 0xfa, - 0xf2, 0x94, 0xac, 0x94, 0x87, 0xda, 0xe1, 0xc6, 0x82, 0x59, 0x25, 0xa0, 0x6c, 0xe8, 0x1b, 0x8a, - 0x81, 0x4a, 0xc8, 0x40, 0xeb, 0xf3, 0xdc, 0x90, 0x60, 0x9e, 0xbd, 0x39, 0x37, 0x62, 0x19, 0x19, - 0xe3, 0x6b, 0xf3, 0xe5, 0x5e, 0xee, 0x4e, 0x64, 0xef, 0x01, 0x1b, 0x4f, 0x26, 0x56, 0x8a, 0x83, - 0x2f, 0x6f, 0x2e, 0x8e, 0x27, 0x93, 0xbe, 0xe6, 0xff, 0xfa, 0x0a, 0x7c, 0x8f, 0x9f, 0x03, 0x6b, - 0x89, 0x05, 0x8c, 0x5d, 0x8c, 0x4c, 0xb1, 0x58, 0x2c, 0x67, 0x74, 0xb1, 0x9c, 0x22, 0xfd, 0xb2, - 0xa9, 0xd2, 0xef, 0x45, 0x72, 0xc2, 0xd8, 0x81, 0xca, 0xa1, 0x76, 0x11, 0xd5, 0x5d, 0xb1, 0x43, - 0xa8, 0x2b, 0xa8, 0x68, 0xef, 0x20, 0x9f, 0xa2, 0x2f, 0x6f, 0x9e, 0xd2, 0x7a, 0x93, 0xd5, 0x7a, - 0x63, 0xfc, 0x8b, 0x0c, 0x5d, 0xf2, 0x11, 0x75, 0x3e, 0xbe, 0xfb, 0x4a, 0x85, 0xdf, 0xe2, 0x33, - 0xc8, 0x15, 0x15, 0x76, 0x93, 0xc7, 0x87, 0xb1, 0x6b, 0x96, 0x77, 0x72, 0x12, 0x70, 0x95, 0xe3, - 0x51, 0x41, 0xd8, 0x01, 0x82, 0x94, 0xf2, 0x2d, 0x34, 0x7c, 0x87, 0xea, 0x0f, 0x64, 0x62, 0x87, - 0x50, 0xbe, 0xf7, 0xed, 0x4b, 0xd9, 0x6a, 0x20, 0x54, 0x10, 0x19, 0x1f, 0x50, 0x67, 0x08, 0xa3, - 0x67, 0xe3, 0x9f, 0xca, 0x63, 0xd2, 0xb3, 0xf3, 0x7b, 0x1f, 0x4a, 0x51, 0xad, 0xc9, 0x1d, 0x56, - 0x51, 0x46, 0x78, 0xb1, 0x8f, 0xa3, 0x33, 0x24, 0xd1, 0x63, 0x5a, 0x5c, 0x18, 0xe3, 0xe9, 0x68, - 0xbd, 0xfe, 0x3a, 0xb0, 0x13, 0xc7, 0x9f, 0x25, 0xa6, 0xc5, 0xd6, 0x40, 0x8c, 0x46, 0x6d, 0x1c, - 0xc1, 0xb2, 0x92, 0x12, 0x9a, 0x45, 0x90, 0x7c, 0x79, 0x99, 0x97, 0x08, 0xf9, 0xec, 0x9c, 0x90, - 0x37, 0x7e, 0x9a, 0x87, 0xa2, 0xba, 0xd4, 0x2d, 0xed, 0x22, 0xb2, 0x72, 0xf2, 0x22, 0xb2, 0x66, - 0xe2, 0xd2, 0x1a, 0x7c, 0xf5, 0x72, 0xbf, 0x7f, 0x67, 0x76, 0xcb, 0xd6, 0x62, 0x15, 0x89, 0x6d, - 0x7b, 0x0d, 0xf2, 0x13, 0x3b, 0x3c, 0x43, 0xbf, 0x24, 0x31, 0x0f, 0x3e, 0xab, 0x18, 0x46, 0x21, - 0x19, 0xc3, 0x48, 0xbb, 0xb4, 0x8d, 0x54, 0xd2, 0xb9, 0x4b, 0xdb, 0x6e, 0x01, 0xe9, 0x17, 0x5a, - 0x8a, 0x5a, 0x09, 0x01, 0x62, 0x2f, 0x4a, 0xaa, 0x23, 0xa5, 0x59, 0x75, 0xe4, 0x95, 0x55, 0x85, - 0x6f, 0xc1, 0x02, 0x5d, 0x78, 0x20, 0xcf, 0x4a, 0xaa, 0x0d, 0x45, 0xce, 0xa1, 0xfa, 0x4f, 0xc9, - 0xeb, 0xa6, 0xa4, 0xd5, 0x6f, 0x40, 0xaa, 0x24, 0x6e, 0x40, 0xd2, 0x63, 0x2b, 0xd5, 0x64, 0x6c, - 0xe5, 0x1e, 0x34, 0xa2, 0x09, 0x45, 0x4f, 0xa5, 0x1b, 0xc8, 0x93, 0x58, 0x75, 0x05, 0x17, 0x52, - 0xb2, 0x1b, 0xc4, 0x1b, 0x62, 0x3d, 0xb1, 0x21, 0x0a, 0x19, 0xd6, 0x0a, 0x43, 0x3e, 0x9e, 0x84, - 0x72, 0x43, 0xc4, 0xb3, 0x1a, 0x7a, 0x07, 0x93, 0xa7, 0x88, 0x6b, 0x50, 0xee, 0x74, 0xad, 0x9d, - 0xbd, 0xce, 0xd3, 0xdd, 0x7e, 0x23, 0x23, 0x1e, 0x7b, 0x47, 0x5b, 0x5b, 0xed, 0xf6, 0x36, 0xee, - 0x38, 0x00, 0x0b, 0x3b, 0xad, 0x8e, 0xd8, 0x7d, 0x72, 0xc6, 0xef, 0x65, 0xa1, 0xa2, 0x55, 0xcf, - 0x9e, 0x44, 0xb3, 0x42, 0x97, 0xe4, 0xdc, 0x9e, 0xef, 0xc2, 0x03, 0x25, 0x8a, 0xb5, 0x69, 0x89, - 0xae, 0xa8, 0xcb, 0x5e, 0x7b, 0x45, 0x1d, 0x7b, 0x1b, 0x16, 0x6d, 0xaa, 0x21, 0x9a, 0x05, 0xe9, - 0x85, 0x97, 0x60, 0x39, 0x09, 0x98, 0x98, 0x19, 0xef, 0x27, 0x82, 0x2e, 0xaf, 0x72, 0x21, 0xa3, - 0x2d, 0x05, 0x27, 0xab, 0x78, 0x62, 0x3b, 0xa3, 0xa9, 0xcf, 0x65, 0xd4, 0x3c, 0xda, 0x99, 0x09, - 0x6a, 0x2a, 0xb4, 0xf1, 0x01, 0x40, 0xdc, 0xe7, 0xe4, 0xe4, 0xdc, 0x48, 0x4e, 0x4e, 0x46, 0x9b, - 0x9c, 0xac, 0xb1, 0x4d, 0x62, 0x44, 0x4e, 0x74, 0xe4, 0x76, 0xfb, 0x06, 0x28, 0x47, 0xa0, 0x85, - 0xe9, 0xd1, 0x93, 0x11, 0x0f, 0xd5, 0x79, 0xeb, 0x25, 0x89, 0xe9, 0x44, 0x08, 0x75, 0xfd, 0x41, - 0x5c, 0x4b, 0x2c, 0x8d, 0x24, 0x4b, 0xce, 0x4a, 0x23, 0x49, 0x6a, 0x46, 0x78, 0x63, 0x03, 0x9a, - 0xdb, 0x5c, 0xd4, 0xd6, 0x1a, 0x8d, 0x66, 0xba, 0x63, 0xdc, 0x82, 0x9b, 0x29, 0x38, 0xe9, 0x84, - 0xf8, 0x18, 0x56, 0x5b, 0x74, 0xb4, 0xfa, 0xab, 0x3a, 0x43, 0x65, 0x34, 0x61, 0x6d, 0xb6, 0x4a, - 0xd9, 0xd8, 0x0e, 0x2c, 0x6d, 0xf3, 0xe3, 0xe9, 0xe9, 0x1e, 0x3f, 0x8f, 0x1b, 0x62, 0x90, 0x0f, - 0xce, 0xbc, 0x0b, 0x39, 0x3f, 0xf8, 0x1b, 0xb3, 0x0c, 0x05, 0x8d, 0x15, 0x4c, 0xf8, 0x40, 0x39, - 0xa2, 0x11, 0xd2, 0x9b, 0xf0, 0x81, 0xf1, 0x04, 0x98, 0x5e, 0x8f, 0x9c, 0x2f, 0x61, 0x25, 0x4c, - 0x8f, 0xad, 0xe0, 0x2a, 0x08, 0xf9, 0x58, 0xdd, 0xc1, 0x04, 0xc1, 0xf4, 0xb8, 0x47, 0x10, 0xe3, - 0x1d, 0xa8, 0x1e, 0xda, 0x57, 0x26, 0xff, 0x5c, 0x9e, 0x0e, 0x5a, 0x87, 0xe2, 0xc4, 0xbe, 0x12, - 0x62, 0x20, 0x8a, 0x49, 0x21, 0xda, 0xf8, 0xe3, 0x3c, 0x2c, 0x10, 0x25, 0xbb, 0x4b, 0xd7, 0xa4, - 0x3a, 0x2e, 0x2e, 0x43, 0x25, 0x28, 0x35, 0xd0, 0x9c, 0x2c, 0xcd, 0xce, 0xcb, 0x52, 0xe9, 0x40, - 0x53, 0xd7, 0xc3, 0xa8, 0xe8, 0x81, 0x3b, 0x1d, 0xab, 0x3b, 0x61, 0x92, 0xe7, 0x8b, 0xf3, 0xf1, - 0x35, 0xb8, 0x74, 0xf8, 0x32, 0x19, 0xdf, 0x8d, 0x6d, 0x11, 0xea, 0x9d, 0xda, 0x22, 0xa4, 0xb8, - 0xd4, 0x41, 0xa9, 0x06, 0x4f, 0x51, 0x9d, 0x3b, 0x4b, 0x1a, 0x3c, 0x73, 0x86, 0x4d, 0xe9, 0xe5, - 0x86, 0x0d, 0x79, 0xd6, 0x5e, 0x60, 0xd8, 0xc0, 0x2b, 0x18, 0x36, 0xaf, 0x10, 0x5b, 0xbd, 0x09, - 0x25, 0xdc, 0xf7, 0x35, 0xe9, 0x29, 0xf6, 0x7b, 0x21, 0x3d, 0xbf, 0xad, 0xa9, 0xfe, 0x94, 0xd8, - 0x71, 0x2b, 0x5e, 0x26, 0x26, 0xff, 0xfc, 0x97, 0x13, 0xb3, 0xfa, 0x0c, 0x8a, 0x12, 0x2a, 0x18, - 0xda, 0xb5, 0xc7, 0xea, 0x86, 0x2d, 0xfc, 0x2d, 0xa6, 0x0d, 0xaf, 0x05, 0xfa, 0x7c, 0xea, 0xf8, - 0x7c, 0xa8, 0xae, 0x4e, 0x71, 0x70, 0x8d, 0x0a, 0x88, 0x18, 0xa0, 0x30, 0x43, 0x5c, 0xef, 0xc2, - 0x95, 0x17, 0x27, 0x14, 0x9d, 0xe0, 0x99, 0x78, 0x34, 0x18, 0x34, 0xf0, 0x8e, 0xbd, 0x89, 0xe7, - 0xab, 0xcd, 0xc9, 0xf8, 0x69, 0x06, 0x1a, 0x72, 0x75, 0x45, 0x38, 0xdd, 0x0a, 0x28, 0x5c, 0x97, - 0x87, 0xf0, 0xe2, 0x8b, 0x50, 0x0c, 0xa8, 0xa1, 0xf3, 0x23, 0xda, 0xa9, 0xc8, 0x79, 0x53, 0x11, - 0xc0, 0x1d, 0xb9, 0x5b, 0xbd, 0x0e, 0x15, 0x95, 0x03, 0x3d, 0x76, 0x46, 0xea, 0xc6, 0x6b, 0x4a, - 0x82, 0xde, 0x77, 0x46, 0x6a, 0xa3, 0xf3, 0x6d, 0x79, 0x0e, 0x32, 0x83, 0x1b, 0x9d, 0x69, 0x87, - 0xdc, 0xf8, 0xb7, 0x19, 0x58, 0xd2, 0x86, 0x22, 0xd7, 0xed, 0x87, 0x50, 0x8d, 0x2e, 0xb7, 0xe4, - 0x91, 0xe6, 0xb5, 0x9e, 0x14, 0x34, 0x71, 0xb1, 0xca, 0x20, 0x82, 0x04, 0xa2, 0x33, 0x43, 0xfb, - 0x8a, 0x12, 0x75, 0xa7, 0x63, 0x65, 0xdc, 0x0c, 0xed, 0xab, 0x1d, 0xce, 0x7b, 0xd3, 0xb1, 0x30, - 0x5d, 0x2f, 0x38, 0x7f, 0x1e, 0x11, 0x90, 0xce, 0x05, 0x02, 0x26, 0x29, 0x0c, 0xa8, 0x8d, 0x3d, - 0x37, 0x3c, 0x8b, 0x48, 0xa4, 0xd6, 0x89, 0x40, 0xa2, 0x31, 0xfe, 0x22, 0x0b, 0xcb, 0xe4, 0x62, - 0x93, 0xae, 0x4d, 0x29, 0xba, 0x9a, 0xb0, 0x40, 0xde, 0x46, 0x12, 0x5e, 0xbb, 0x37, 0x4c, 0xf9, - 0xcc, 0xbe, 0xf5, 0x8a, 0x6e, 0x41, 0x75, 0xd4, 0xf2, 0x9a, 0xe9, 0xcf, 0xcd, 0x4f, 0xff, 0xf5, - 0xd3, 0x9b, 0x16, 0xe8, 0x2c, 0xa4, 0x05, 0x3a, 0x5f, 0x25, 0xbc, 0x38, 0x77, 0x1e, 0xb1, 0x28, - 0x69, 0xb4, 0xf3, 0x88, 0x4f, 0x60, 0x3d, 0x41, 0x83, 0xd2, 0xda, 0x39, 0x71, 0xb8, 0xba, 0x97, - 0x62, 0x45, 0xa3, 0xee, 0x29, 0xdc, 0x66, 0x11, 0x0a, 0xc1, 0xc0, 0x9b, 0x70, 0x63, 0x0d, 0x56, - 0x92, 0xb3, 0x2a, 0xb7, 0x89, 0xdf, 0xcf, 0x40, 0x53, 0xa6, 0xa5, 0x38, 0xee, 0xe9, 0xae, 0x13, - 0x84, 0x9e, 0x1f, 0x5d, 0x02, 0x79, 0x1b, 0x20, 0x08, 0x6d, 0x5f, 0x5a, 0x9b, 0xf2, 0x26, 0x06, - 0x84, 0xa0, 0x25, 0x79, 0x13, 0x4a, 0xdc, 0x1d, 0x12, 0x92, 0xb8, 0xa1, 0xc8, 0xdd, 0xa1, 0xb2, - 0x43, 0xe7, 0xf4, 0xef, 0x5a, 0xd2, 0xbc, 0x90, 0x07, 0xa3, 0xc5, 0xec, 0xf0, 0x73, 0xdc, 0x78, - 0xf3, 0xd1, 0xc1, 0xe8, 0x7d, 0xfb, 0x12, 0x93, 0x3c, 0x03, 0xe3, 0x1f, 0x65, 0x61, 0x31, 0xee, - 0x1f, 0xdd, 0xaa, 0xf0, 0xe2, 0xfb, 0x21, 0xee, 0x4a, 0x76, 0x70, 0x84, 0xfe, 0xae, 0x39, 0x1e, - 0x4b, 0xb4, 0x38, 0x3b, 0x2e, 0x33, 0xa0, 0xa2, 0x28, 0xbc, 0x69, 0xa8, 0xdd, 0xc5, 0x56, 0x26, - 0x92, 0x83, 0x69, 0x28, 0x0c, 0x2e, 0x61, 0x79, 0x3a, 0xae, 0x34, 0x79, 0x0a, 0xf6, 0x38, 0xec, - 0xe0, 0x15, 0xef, 0x02, 0x2c, 0x8a, 0xd1, 0x8b, 0x14, 0x54, 0x82, 0xbe, 0x41, 0x7a, 0x36, 0xbd, - 0x39, 0xd4, 0xb1, 0x75, 0x25, 0x94, 0x6e, 0xbb, 0x8d, 0x94, 0xd0, 0xd7, 0xa1, 0x42, 0x95, 0xc7, - 0xc7, 0x4f, 0xf3, 0x66, 0x19, 0x5b, 0x40, 0xbc, 0x74, 0x02, 0x79, 0xd3, 0x84, 0xe9, 0x0b, 0xd4, - 0x14, 0x66, 0x7d, 0xfc, 0xbd, 0x0c, 0xdc, 0x4c, 0x79, 0x6d, 0x72, 0x95, 0x6f, 0xc1, 0xd2, 0x49, - 0x84, 0x54, 0xb3, 0x4b, 0x4b, 0x7d, 0x4d, 0x89, 0xd5, 0xe4, 0x9c, 0x9a, 0x8d, 0x93, 0x24, 0x20, - 0x36, 0xba, 0xe8, 0x0d, 0x26, 0x4e, 0x18, 0xa3, 0xd1, 0x45, 0xaf, 0x91, 0xec, 0x9d, 0x43, 0xd8, - 0x68, 0x5f, 0x0a, 0x89, 0xb1, 0xa5, 0x7f, 0xa3, 0x40, 0xb1, 0x51, 0xd2, 0xc1, 0x9c, 0x79, 0x25, - 0x07, 0xf3, 0x90, 0x0e, 0x52, 0x46, 0x75, 0xfd, 0x3c, 0x95, 0xe0, 0x06, 0x2a, 0xca, 0xd0, 0x37, - 0x16, 0xd4, 0x29, 0xe7, 0x41, 0xf4, 0x6d, 0x05, 0x23, 0x80, 0xc5, 0xfd, 0xe9, 0x28, 0x74, 0xe2, - 0xcf, 0x2d, 0xb0, 0x6f, 0xc9, 0x32, 0xd8, 0x8e, 0x9a, 0xb5, 0xd4, 0x86, 0x20, 0x6a, 0x08, 0x27, - 0x6b, 0x2c, 0x2a, 0xb2, 0xe6, 0xdb, 0x5b, 0x1c, 0x27, 0x5b, 0x30, 0x6e, 0xc2, 0x7a, 0xfc, 0x44, - 0xd3, 0xa6, 0xb6, 0x9a, 0x7f, 0x9e, 0xa1, 0x8c, 0xf2, 0xe4, 0xa7, 0x1f, 0x58, 0x1b, 0x96, 0x03, - 0xc7, 0x3d, 0x1d, 0x71, 0xbd, 0xfa, 0x40, 0x4e, 0xc2, 0x6a, 0xb2, 0x6f, 0xf2, 0xf3, 0x10, 0xe6, - 0x12, 0x95, 0x88, 0x6b, 0x0b, 0xd8, 0xe6, 0x75, 0x9d, 0x8c, 0xd9, 0x62, 0x66, 0x36, 0xe6, 0x3b, - 0xdf, 0x81, 0x7a, 0xb2, 0x21, 0xf6, 0x6d, 0x79, 0x88, 0x38, 0xee, 0x55, 0x6e, 0xe6, 0xb8, 0x67, - 0xcc, 0x10, 0x95, 0x78, 0xee, 0x03, 0xe3, 0x1f, 0x64, 0xa0, 0x69, 0x72, 0xc1, 0xb9, 0x5a, 0x2f, - 0x15, 0xcf, 0x7c, 0x38, 0x57, 0xeb, 0xf5, 0x63, 0x55, 0x67, 0x93, 0x55, 0x8f, 0xbe, 0x7e, 0xed, - 0xcb, 0xd8, 0xbd, 0x31, 0x37, 0xa2, 0xcd, 0x12, 0x2c, 0x10, 0x89, 0xb1, 0x0e, 0xab, 0xb2, 0x3f, - 0xaa, 0x2f, 0x71, 0xf4, 0x30, 0xd1, 0x62, 0x22, 0x7a, 0xb8, 0x01, 0x4d, 0xba, 0xcb, 0x53, 0x1f, - 0x84, 0x2c, 0xb8, 0x0d, 0x6c, 0xdf, 0x1e, 0xd8, 0xbe, 0xe7, 0xb9, 0x87, 0xdc, 0x97, 0xf9, 0xb9, - 0xa8, 0x61, 0x62, 0x70, 0x4d, 0xa9, 0xc2, 0xf4, 0xa4, 0x6e, 0xa0, 0xf4, 0x5c, 0x95, 0x8e, 0x44, - 0x4f, 0x86, 0x09, 0xcb, 0x9b, 0xf6, 0x73, 0xae, 0x6a, 0x52, 0x53, 0xf4, 0x11, 0x54, 0x26, 0x51, - 0xa5, 0x6a, 0xde, 0xd5, 0x4d, 0x03, 0xf3, 0xcd, 0x9a, 0x3a, 0xb5, 0xf1, 0x18, 0x56, 0x92, 0x75, - 0x4a, 0xd1, 0xb1, 0x01, 0xa5, 0xb1, 0x84, 0xc9, 0xde, 0x45, 0xcf, 0xc6, 0xef, 0x96, 0xa0, 0x28, - 0xed, 0x39, 0xf6, 0x00, 0xf2, 0x03, 0x95, 0x12, 0x16, 0x5f, 0x60, 0x23, 0xb1, 0xea, 0xff, 0x16, - 0x26, 0x86, 0x09, 0x3a, 0xf6, 0x11, 0xd4, 0x93, 0x51, 0xd1, 0x99, 0x63, 0xcc, 0xc9, 0x70, 0x66, - 0x6d, 0x30, 0x13, 0xff, 0x2a, 0xc7, 0x9b, 0x23, 0xe9, 0x0c, 0xa5, 0x33, 0x6d, 0xf7, 0xf4, 0x5c, - 0xa1, 0x6f, 0x07, 0x67, 0xb6, 0xf5, 0xf8, 0xc9, 0x07, 0xf2, 0x1c, 0x73, 0x05, 0x81, 0xbd, 0x33, - 0xfb, 0xf1, 0x93, 0x0f, 0x66, 0x35, 0x69, 0x79, 0x8a, 0x59, 0xd3, 0xa4, 0x57, 0xa0, 0x40, 0x57, - 0x2d, 0x52, 0x6e, 0x0f, 0x3d, 0xb0, 0x47, 0xb0, 0x22, 0xcd, 0x56, 0x4b, 0x66, 0x61, 0x93, 0x14, - 0x2c, 0xd1, 0xc1, 0x37, 0x89, 0xeb, 0x21, 0x8a, 0x7c, 0x43, 0x6b, 0xb0, 0x70, 0x16, 0xdf, 0x9b, - 0x59, 0x33, 0xe5, 0x93, 0xf1, 0x17, 0x05, 0xa8, 0x68, 0x93, 0xc2, 0xaa, 0x50, 0x32, 0xdb, 0xbd, - 0xb6, 0xf9, 0x49, 0x7b, 0xbb, 0x71, 0x83, 0xdd, 0x83, 0xb7, 0x3a, 0xdd, 0xad, 0x03, 0xd3, 0x6c, - 0x6f, 0xf5, 0xad, 0x03, 0xd3, 0x52, 0xd7, 0x28, 0x1d, 0xb6, 0x3e, 0xdb, 0x6f, 0x77, 0xfb, 0xd6, - 0x76, 0xbb, 0xdf, 0xea, 0xec, 0xf5, 0x1a, 0x19, 0xf6, 0x1a, 0x34, 0x63, 0x4a, 0x85, 0x6e, 0xed, - 0x1f, 0x1c, 0x75, 0xfb, 0x8d, 0x2c, 0xbb, 0x03, 0xb7, 0x76, 0x3a, 0xdd, 0xd6, 0x9e, 0x15, 0xd3, - 0x6c, 0xed, 0xf5, 0x3f, 0xb1, 0xda, 0xbf, 0x76, 0xd8, 0x31, 0x3f, 0x6b, 0xe4, 0xd2, 0x08, 0x84, - 0x31, 0xae, 0x6a, 0xc8, 0xb3, 0x9b, 0xb0, 0x4a, 0x04, 0x54, 0xc4, 0xea, 0x1f, 0x1c, 0x58, 0xbd, - 0x83, 0x83, 0x6e, 0xa3, 0xc0, 0x96, 0xa0, 0xd6, 0xe9, 0x7e, 0xd2, 0xda, 0xeb, 0x6c, 0x5b, 0x66, - 0xbb, 0xb5, 0xb7, 0xdf, 0x58, 0x60, 0xcb, 0xb0, 0x38, 0x4b, 0x57, 0x14, 0x55, 0x28, 0xba, 0x83, - 0x6e, 0xe7, 0xa0, 0x6b, 0x7d, 0xd2, 0x36, 0x7b, 0x9d, 0x83, 0x6e, 0xa3, 0xc4, 0xd6, 0x80, 0x25, - 0x51, 0xbb, 0xfb, 0xad, 0xad, 0x46, 0x99, 0xad, 0xc2, 0x52, 0x12, 0xfe, 0xac, 0xfd, 0x59, 0x03, - 0x58, 0x13, 0x56, 0xa8, 0x63, 0xd6, 0x66, 0x7b, 0xef, 0xe0, 0x53, 0x6b, 0xbf, 0xd3, 0xed, 0xec, - 0x1f, 0xed, 0x37, 0x2a, 0x78, 0xb1, 0x5b, 0xbb, 0x6d, 0x75, 0xba, 0xbd, 0xa3, 0x9d, 0x9d, 0xce, - 0x56, 0xa7, 0xdd, 0xed, 0x37, 0xaa, 0xd4, 0x72, 0xda, 0xc0, 0x6b, 0xa2, 0x80, 0x3c, 0xaa, 0x61, - 0x6d, 0x77, 0x7a, 0xad, 0xcd, 0xbd, 0xf6, 0x76, 0xa3, 0xce, 0x6e, 0xc3, 0xcd, 0x7e, 0x7b, 0xff, - 0xf0, 0xc0, 0x6c, 0x99, 0x9f, 0xa9, 0xa3, 0x1c, 0xd6, 0x4e, 0xab, 0xb3, 0x77, 0x64, 0xb6, 0x1b, - 0x8b, 0xec, 0x0d, 0xb8, 0x6d, 0xb6, 0x3f, 0x3e, 0xea, 0x98, 0xed, 0x6d, 0xab, 0x7b, 0xb0, 0xdd, - 0xb6, 0x76, 0xda, 0xad, 0xfe, 0x91, 0xd9, 0xb6, 0xf6, 0x3b, 0xbd, 0x5e, 0xa7, 0xfb, 0xb4, 0xd1, - 0x60, 0x6f, 0xc1, 0xdd, 0x88, 0x24, 0xaa, 0x60, 0x86, 0x6a, 0x49, 0x8c, 0x4f, 0xbd, 0xd2, 0x6e, - 0xfb, 0xd7, 0xfa, 0xd6, 0x61, 0xbb, 0x6d, 0x36, 0x18, 0xdb, 0x80, 0xb5, 0xb8, 0x79, 0x6a, 0x40, - 0xb6, 0xbd, 0x2c, 0x70, 0x87, 0x6d, 0x73, 0xbf, 0xd5, 0x15, 0x2f, 0x38, 0x81, 0x5b, 0x11, 0xdd, - 0x8e, 0x71, 0xb3, 0xdd, 0x5e, 0x65, 0x0c, 0xea, 0xda, 0x5b, 0xd9, 0x69, 0x99, 0x8d, 0x35, 0xb6, - 0x08, 0x95, 0xfd, 0xc3, 0x43, 0xab, 0xdf, 0xd9, 0x6f, 0x1f, 0x1c, 0xf5, 0x1b, 0xeb, 0x6c, 0x15, - 0x1a, 0x9d, 0x6e, 0xbf, 0x6d, 0x8a, 0x77, 0xad, 0x8a, 0xfe, 0xaf, 0x22, 0x5b, 0x81, 0x45, 0xd5, - 0x53, 0x05, 0xfd, 0x59, 0x91, 0xad, 0x03, 0x3b, 0xea, 0x9a, 0xed, 0xd6, 0xb6, 0x98, 0xb8, 0x08, - 0xf1, 0xbf, 0x8b, 0x32, 0x42, 0xf2, 0xd3, 0x5c, 0xb4, 0x59, 0xc7, 0x29, 0x07, 0xc9, 0x5b, 0x94, - 0xab, 0xda, 0xed, 0xc7, 0x2f, 0xfb, 0xbe, 0x81, 0x66, 0x5a, 0xe5, 0xe6, 0x4c, 0xab, 0x39, 0xdb, - 0xbd, 0xa6, 0xeb, 0x7e, 0x6f, 0x42, 0x6d, 0x4c, 0x37, 0x2a, 0xcb, 0x9b, 0x53, 0x41, 0xe6, 0xdf, - 0x10, 0x90, 0xae, 0x4d, 0x9d, 0xbb, 0xe0, 0xbf, 0x30, 0x7f, 0xc1, 0x7f, 0x9a, 0x7e, 0xbf, 0x90, - 0xa6, 0xdf, 0xdf, 0x87, 0x25, 0x12, 0x4d, 0x8e, 0xeb, 0x8c, 0x95, 0xd5, 0x4c, 0x5a, 0xe0, 0x22, - 0x8a, 0x28, 0x82, 0x2b, 0x73, 0x42, 0x99, 0x1c, 0x52, 0x84, 0x14, 0xa5, 0xb5, 0x91, 0xb0, 0x34, - 0x48, 0x72, 0x44, 0x96, 0x46, 0xd4, 0x82, 0x7d, 0x19, 0xb7, 0x50, 0xd1, 0x5a, 0x20, 0x38, 0xb6, - 0x70, 0x1f, 0x96, 0xf8, 0x65, 0xe8, 0xdb, 0x96, 0x37, 0xb1, 0x3f, 0x9f, 0x62, 0x08, 0xd7, 0x46, - 0x1b, 0xbe, 0x6a, 0x2e, 0x22, 0xe2, 0x00, 0xe1, 0xdb, 0x76, 0x68, 0xdf, 0xff, 0x02, 0x2a, 0xda, - 0x6d, 0xdb, 0x6c, 0x1d, 0x96, 0x3f, 0xed, 0xf4, 0xbb, 0xed, 0x5e, 0xcf, 0x3a, 0x3c, 0xda, 0x7c, - 0xd6, 0xfe, 0xcc, 0xda, 0x6d, 0xf5, 0x76, 0x1b, 0x37, 0xc4, 0xa2, 0xed, 0xb6, 0x7b, 0xfd, 0xf6, - 0x76, 0x02, 0x9e, 0x61, 0xaf, 0xc3, 0xc6, 0x51, 0xf7, 0xa8, 0xd7, 0xde, 0xb6, 0xd2, 0xca, 0x65, - 0x05, 0x97, 0x4a, 0x7c, 0x4a, 0xf1, 0xdc, 0xfd, 0xef, 0x43, 0x3d, 0x79, 0x05, 0x2c, 0x03, 0x58, - 0xd8, 0x6b, 0x3f, 0x6d, 0x6d, 0x7d, 0x46, 0x57, 0x3f, 0xf6, 0xfa, 0xad, 0x7e, 0x67, 0xcb, 0x92, - 0x57, 0x3d, 0x0a, 0x89, 0x90, 0x61, 0x15, 0x28, 0xb6, 0xba, 0x5b, 0xbb, 0x07, 0x66, 0xaf, 0x91, - 0xbd, 0xff, 0x5d, 0xa8, 0x27, 0xb3, 0xeb, 0x92, 0x7e, 0xd7, 0x0d, 0x58, 0xdb, 0x6c, 0xf7, 0x3f, - 0x6d, 0xb7, 0xbb, 0xd8, 0xb9, 0xad, 0x76, 0xb7, 0x6f, 0xb6, 0xf6, 0x3a, 0xfd, 0xcf, 0x1a, 0x99, - 0xfb, 0x1f, 0x41, 0x63, 0x36, 0x94, 0x95, 0x88, 0xfd, 0xbd, 0x28, 0x48, 0x78, 0xff, 0x5f, 0xe5, - 0x00, 0xe2, 0x23, 0x1e, 0x42, 0x4a, 0x6d, 0xb7, 0xfa, 0xad, 0xbd, 0x03, 0x31, 0x03, 0xe6, 0x41, - 0x5f, 0x08, 0x1f, 0xb3, 0xfd, 0x71, 0xe3, 0x46, 0x2a, 0xe6, 0xe0, 0xb0, 0xdf, 0xc8, 0x88, 0xc9, - 0xee, 0x74, 0x3b, 0xfd, 0x4e, 0x6b, 0xcf, 0x32, 0x0f, 0x8e, 0x3a, 0xdd, 0xa7, 0x74, 0x1d, 0x1e, - 0x0a, 0xe8, 0xa3, 0xc3, 0x1d, 0xf3, 0xa0, 0xdb, 0xb7, 0x7a, 0xbb, 0x47, 0xfd, 0x6d, 0xbc, 0x4c, - 0x6f, 0xcb, 0xec, 0x1c, 0x52, 0x9d, 0xf9, 0x17, 0x11, 0x88, 0xaa, 0x0b, 0xe2, 0x75, 0x3d, 0x3d, - 0xe8, 0xf5, 0x3a, 0x87, 0xd6, 0xc7, 0x47, 0x6d, 0xb3, 0xd3, 0xee, 0x61, 0xc1, 0x85, 0x14, 0xb8, - 0xa0, 0x2f, 0x0a, 0xb1, 0xde, 0xdf, 0xfb, 0x44, 0xca, 0x5d, 0x41, 0x5a, 0x4a, 0x82, 0x04, 0x55, - 0x59, 0x4c, 0xa6, 0x10, 0x5c, 0x29, 0x35, 0xc3, 0x35, 0x38, 0x51, 0xae, 0x22, 0x44, 0xf2, 0xdc, - 0x7b, 0xc4, 0x62, 0xd5, 0x74, 0x94, 0x28, 0x85, 0xd2, 0x3a, 0xda, 0xdb, 0xb6, 0xb7, 0x4d, 0x2c, - 0x50, 0x9f, 0x83, 0x0a, 0xda, 0x45, 0xf1, 0xa2, 0x84, 0x64, 0x13, 0x24, 0x0d, 0xf5, 0x20, 0x30, - 0x4b, 0x8f, 0x7f, 0x27, 0x07, 0x75, 0x3a, 0x6e, 0x47, 0xdf, 0x49, 0xe3, 0x3e, 0xdb, 0x87, 0xa2, - 0xfc, 0xe0, 0x1e, 0x5b, 0x8d, 0x6e, 0x2a, 0xd3, 0x3f, 0xf1, 0xb7, 0xb1, 0x36, 0x0b, 0x96, 0x9a, - 0xdc, 0xf2, 0xdf, 0xfc, 0xf3, 0xff, 0xf9, 0x0f, 0xb3, 0x35, 0x56, 0x79, 0x78, 0xfe, 0xfe, 0xc3, - 0x53, 0xee, 0x06, 0xa2, 0x8e, 0xdf, 0x00, 0x88, 0x3f, 0x23, 0xc7, 0x9a, 0x51, 0xfc, 0x6a, 0xe6, - 0x1b, 0x7b, 0x1b, 0x37, 0x53, 0x30, 0xb2, 0xde, 0x9b, 0x58, 0xef, 0xb2, 0x51, 0x17, 0xf5, 0x3a, - 0xae, 0x13, 0xd2, 0x27, 0xe5, 0x3e, 0xcc, 0xdc, 0x67, 0x43, 0xa8, 0xea, 0x1f, 0x78, 0x63, 0x4a, - 0xc9, 0x4a, 0xf9, 0x44, 0xdd, 0xc6, 0xad, 0x54, 0x9c, 0x52, 0x5f, 0xb1, 0x8d, 0x55, 0xa3, 0x21, - 0xda, 0x98, 0x22, 0x45, 0xdc, 0xca, 0x88, 0x14, 0xfa, 0xf8, 0x3b, 0x6e, 0xec, 0x35, 0x4d, 0x25, - 0x9b, 0xfb, 0x8a, 0xdc, 0xc6, 0xed, 0x6b, 0xb0, 0xb2, 0xad, 0xdb, 0xd8, 0xd6, 0xba, 0xc1, 0x44, - 0x5b, 0x03, 0xa4, 0x51, 0x5f, 0x91, 0xfb, 0x30, 0x73, 0xff, 0xf1, 0x7f, 0x7c, 0x17, 0xca, 0x51, - 0xfa, 0x2d, 0xfb, 0x2d, 0xa8, 0x25, 0xce, 0x43, 0x32, 0x35, 0x8c, 0xb4, 0xe3, 0x93, 0x1b, 0xaf, - 0xa5, 0x23, 0x65, 0xc3, 0xaf, 0x63, 0xc3, 0x4d, 0xb6, 0x26, 0x1a, 0x96, 0xe7, 0x0d, 0x1f, 0xe2, - 0xf9, 0x65, 0xba, 0xf7, 0xed, 0xb9, 0x66, 0xb8, 0x50, 0x63, 0xaf, 0xcd, 0x1a, 0x13, 0x89, 0xd6, - 0x6e, 0x5f, 0x83, 0x95, 0xcd, 0xbd, 0x86, 0xcd, 0xad, 0xb1, 0x15, 0xbd, 0x39, 0x95, 0xb5, 0xc9, - 0x38, 0xde, 0xb5, 0xa8, 0x7f, 0xe6, 0x8c, 0xdd, 0x8e, 0x6f, 0xc6, 0x4b, 0xf9, 0xfc, 0x59, 0xc4, - 0x22, 0xf3, 0xdf, 0x40, 0x33, 0x9a, 0xd8, 0x14, 0x63, 0xf8, 0xfa, 0xf4, 0xaf, 0x9c, 0xb1, 0x63, - 0xa8, 0x68, 0x5f, 0x06, 0x61, 0x37, 0xaf, 0xfd, 0x8a, 0xc9, 0xc6, 0x46, 0x1a, 0x2a, 0x6d, 0x28, - 0x7a, 0xfd, 0x0f, 0x4f, 0x38, 0x67, 0xbf, 0x0e, 0xe5, 0xe8, 0x7b, 0x13, 0x6c, 0x5d, 0xfb, 0xfe, - 0x87, 0xfe, 0x7d, 0x8c, 0x8d, 0xe6, 0x3c, 0x22, 0x8d, 0xf9, 0xf4, 0xda, 0x05, 0xf3, 0x7d, 0x0a, - 0x15, 0xed, 0x9b, 0x12, 0xd1, 0x00, 0xe6, 0xbf, 0x5b, 0x11, 0x0d, 0x20, 0xe5, 0x13, 0x14, 0xc6, - 0x12, 0x36, 0x51, 0x61, 0x65, 0xe4, 0xef, 0xf0, 0xd2, 0x0b, 0xd8, 0x1e, 0xac, 0x4a, 0x23, 0xed, - 0x98, 0x7f, 0x99, 0xd7, 0x90, 0xf2, 0x65, 0xb9, 0x47, 0x19, 0xf6, 0x11, 0x94, 0xd4, 0xa7, 0x43, - 0xd8, 0x5a, 0xfa, 0x27, 0x50, 0x36, 0xd6, 0xe7, 0xe0, 0xd2, 0xa2, 0xfa, 0x0c, 0x20, 0xfe, 0x80, - 0x45, 0x24, 0x24, 0xe6, 0x3e, 0x88, 0x11, 0x71, 0xc0, 0xfc, 0xd7, 0x2e, 0x8c, 0x35, 0x1c, 0x60, - 0x83, 0xa1, 0x90, 0x70, 0xf9, 0x85, 0xba, 0x10, 0xf7, 0x47, 0x50, 0xd1, 0xbe, 0x61, 0x11, 0x4d, - 0xdf, 0xfc, 0xf7, 0x2f, 0xa2, 0xe9, 0x4b, 0xf9, 0xe4, 0x85, 0xb1, 0x81, 0xb5, 0xaf, 0x18, 0x8b, - 0xa2, 0x76, 0xa1, 0xa5, 0x49, 0x6d, 0x49, 0xbc, 0xa0, 0x33, 0xa8, 0x25, 0x3e, 0x54, 0x11, 0xad, - 0xd0, 0xb4, 0xcf, 0x60, 0x44, 0x2b, 0x34, 0xf5, 0xdb, 0x16, 0x8a, 0xcf, 0x8c, 0x25, 0xd1, 0xce, - 0x39, 0x92, 0x68, 0x2d, 0xfd, 0x10, 0x2a, 0xda, 0x47, 0x27, 0xa2, 0xb1, 0xcc, 0x7f, 0xdf, 0x22, - 0x1a, 0x4b, 0xda, 0x37, 0x2a, 0x56, 0xb0, 0x8d, 0xba, 0x81, 0xac, 0x80, 0x57, 0x7a, 0x8a, 0xba, - 0x7f, 0x0b, 0xea, 0xc9, 0xef, 0x50, 0x44, 0x6b, 0x3f, 0xf5, 0x83, 0x16, 0xd1, 0xda, 0xbf, 0xe6, - 0xe3, 0x15, 0x92, 0xa5, 0xef, 0x2f, 0x47, 0x8d, 0x3c, 0xfc, 0x89, 0x3c, 0x48, 0xf4, 0x05, 0xfb, - 0x58, 0x08, 0x38, 0x79, 0xa3, 0x2c, 0x5b, 0xd7, 0xb8, 0x56, 0xbf, 0x9a, 0x36, 0x5a, 0x2f, 0x73, - 0x97, 0xcf, 0x26, 0x99, 0x19, 0x2b, 0x67, 0x4f, 0x61, 0x39, 0x62, 0xe6, 0xe8, 0x8a, 0xd8, 0x20, - 0x1a, 0x43, 0xea, 0x45, 0xb4, 0x1b, 0x8d, 0x59, 0xec, 0xa3, 0x0c, 0x6d, 0x7f, 0x78, 0x31, 0xa7, - 0xb6, 0xfd, 0xe9, 0xb7, 0xc4, 0x6a, 0xdb, 0x5f, 0xe2, 0xfe, 0xce, 0xd9, 0xed, 0x2f, 0x74, 0x44, - 0x1d, 0x2e, 0x2c, 0xce, 0x5e, 0xd8, 0x7a, 0xfb, 0xba, 0x8b, 0x1a, 0xa8, 0xfa, 0xd7, 0x5f, 0x7c, - 0x8f, 0x43, 0x52, 0x14, 0x29, 0x69, 0xfa, 0x50, 0xe6, 0xad, 0xb0, 0xdf, 0x84, 0xaa, 0x7e, 0x77, - 0x3d, 0xd3, 0x65, 0xc2, 0x6c, 0x4b, 0xb7, 0x52, 0x71, 0x49, 0x2e, 0x61, 0x55, 0xbd, 0x19, 0xf6, - 0x09, 0xac, 0x45, 0xd3, 0xac, 0xdf, 0x34, 0x10, 0xb0, 0x3b, 0x29, 0xf7, 0x0f, 0x24, 0x26, 0xfb, - 0xe6, 0xb5, 0x17, 0x14, 0x3c, 0xca, 0x08, 0xee, 0x4b, 0x5e, 0xa2, 0x1d, 0xef, 0x3c, 0x69, 0x77, - 0x87, 0xc7, 0x3b, 0x4f, 0xea, 0xcd, 0xdb, 0x8a, 0xfb, 0xd8, 0x72, 0x62, 0x8e, 0x28, 0xa3, 0x97, - 0xfd, 0x10, 0x16, 0xb5, 0x6b, 0x14, 0x7a, 0x57, 0xee, 0x20, 0x5a, 0x49, 0xf3, 0xb7, 0x40, 0x6e, - 0xa4, 0xb9, 0x35, 0x8d, 0x75, 0xac, 0x7f, 0xc9, 0x48, 0x4c, 0x8e, 0x58, 0x45, 0x5b, 0x50, 0xd1, - 0xaf, 0x68, 0x78, 0x41, 0xbd, 0xeb, 0x1a, 0x4a, 0xbf, 0x70, 0xf0, 0x51, 0x86, 0xed, 0x41, 0x63, - 0xf6, 0xfa, 0xb3, 0x48, 0xa6, 0xa4, 0x5d, 0xd9, 0xb6, 0x31, 0x83, 0x4c, 0x5c, 0x9a, 0xc6, 0x0e, - 0xe9, 0x4c, 0x48, 0xf4, 0x19, 0x36, 0xcf, 0x9f, 0xdd, 0xd5, 0x93, 0x9f, 0x67, 0x8b, 0x6a, 0x4b, - 0xfb, 0x30, 0xdf, 0xbd, 0xcc, 0xa3, 0x0c, 0xfb, 0xbd, 0x0c, 0x54, 0x13, 0x17, 0x0a, 0x25, 0xb2, - 0xee, 0x67, 0xc6, 0xd9, 0xd4, 0x71, 0xfa, 0x40, 0x0d, 0x13, 0x27, 0x71, 0xef, 0xfe, 0x0f, 0x12, - 0x2f, 0xe9, 0x27, 0x89, 0xa8, 0xe0, 0x83, 0xd9, 0xef, 0xb4, 0x7d, 0x31, 0x4b, 0xa0, 0x5f, 0xee, - 0xf9, 0xc5, 0xa3, 0x0c, 0xfb, 0x37, 0x19, 0xa8, 0x27, 0xc3, 0xfd, 0xd1, 0x70, 0x53, 0x13, 0x0b, - 0x22, 0x56, 0xba, 0x26, 0x47, 0xe0, 0x87, 0xd8, 0xcb, 0xfe, 0x7d, 0x33, 0xd1, 0x4b, 0x79, 0xfd, - 0xfb, 0x2f, 0xd6, 0x5b, 0xf6, 0x21, 0x7d, 0x16, 0x55, 0x65, 0x41, 0xb1, 0xf9, 0xcf, 0x68, 0x46, - 0xec, 0xa7, 0x7f, 0x74, 0x12, 0x5f, 0xc2, 0x8f, 0xe8, 0x7b, 0x64, 0x2a, 0xa9, 0x46, 0x70, 0xf1, - 0xab, 0x96, 0x37, 0xde, 0xc2, 0x31, 0xbd, 0x6e, 0xdc, 0x4c, 0x8c, 0x69, 0x56, 0xf1, 0x68, 0x51, - 0xef, 0xe4, 0x37, 0x23, 0xe3, 0x9d, 0x73, 0xee, 0x3b, 0x92, 0xd7, 0x77, 0x72, 0x4c, 0x9d, 0x94, - 0xe4, 0x89, 0xa5, 0xf6, 0x8a, 0xd5, 0x18, 0xf7, 0xb1, 0xaf, 0x6f, 0x19, 0x77, 0xae, 0xed, 0xeb, - 0x43, 0x0c, 0xdd, 0x8b, 0x1e, 0x1f, 0x02, 0xc4, 0x59, 0x8a, 0x6c, 0x26, 0x57, 0x2e, 0x12, 0x40, - 0xf3, 0x89, 0x8c, 0xc9, 0xf5, 0xac, 0x52, 0xea, 0x44, 0x8d, 0xbf, 0x4e, 0xe2, 0x34, 0xca, 0xe2, - 0xd3, 0xb5, 0xaf, 0x64, 0x42, 0x61, 0x42, 0xfb, 0x9a, 0xad, 0x3f, 0x21, 0x4c, 0xa3, 0x94, 0xbd, - 0x23, 0xa8, 0xed, 0x79, 0xde, 0xf3, 0xe9, 0x24, 0xca, 0x8c, 0x4f, 0xe6, 0xd3, 0xec, 0xda, 0xc1, - 0xd9, 0xc6, 0xcc, 0x28, 0x8c, 0xbb, 0x58, 0xd5, 0x06, 0x6b, 0x6a, 0x55, 0x3d, 0xfc, 0x49, 0x9c, - 0x1a, 0xf9, 0x05, 0xb3, 0x61, 0x29, 0x92, 0xd1, 0x71, 0xfa, 0x61, 0xb2, 0x9a, 0x84, 0x64, 0x9e, - 0x6d, 0x22, 0x61, 0x26, 0xa8, 0xde, 0x3e, 0x0c, 0x54, 0x9d, 0x8f, 0x32, 0xec, 0x10, 0xaa, 0xdb, - 0x7c, 0x80, 0x57, 0x2b, 0x60, 0x56, 0xca, 0x72, 0x22, 0xc3, 0x81, 0xd2, 0x59, 0x36, 0x6a, 0x09, - 0x60, 0x72, 0xdf, 0x9a, 0xd8, 0x57, 0x3e, 0xff, 0xfc, 0xe1, 0x4f, 0x64, 0xbe, 0xcb, 0x17, 0x6a, - 0xdf, 0x52, 0xf9, 0x40, 0x89, 0x7d, 0x6b, 0x26, 0x81, 0x28, 0xb1, 0x6f, 0xcd, 0x25, 0x10, 0x25, - 0xa6, 0x5a, 0xe5, 0x23, 0xb1, 0x11, 0x2c, 0xcd, 0xe5, 0x1c, 0x45, 0x5b, 0xd6, 0x75, 0x99, 0x4a, - 0x1b, 0x77, 0xaf, 0x27, 0x48, 0xb6, 0x76, 0x3f, 0xd9, 0x5a, 0x0f, 0x6a, 0x74, 0xdf, 0xe8, 0x31, - 0xa7, 0x43, 0x96, 0x33, 0x37, 0x14, 0xe9, 0x27, 0x38, 0x67, 0x37, 0x18, 0xc4, 0x25, 0x35, 0x1c, - 0x3c, 0x66, 0xc7, 0x4e, 0xf0, 0xba, 0x7a, 0xed, 0x54, 0x63, 0xc4, 0x8c, 0xf3, 0x27, 0x2d, 0x23, - 0x66, 0x4c, 0x39, 0x04, 0xa9, 0xcc, 0x4f, 0xb6, 0x1a, 0xd5, 0xfd, 0xd0, 0xf5, 0x86, 0x7c, 0x2c, - 0x6b, 0xfd, 0x75, 0xa8, 0x3c, 0xe5, 0xa1, 0x3a, 0x46, 0x18, 0xe9, 0xf2, 0x33, 0xe7, 0x0a, 0x37, - 0x52, 0x0e, 0x7f, 0x26, 0x79, 0x93, 0x6a, 0xe6, 0xc3, 0x53, 0x4e, 0x42, 0xd0, 0x72, 0x86, 0x5f, - 0xb0, 0x5f, 0xc3, 0xca, 0xa3, 0x43, 0xf3, 0x6b, 0x5a, 0x37, 0xf5, 0xca, 0x17, 0x67, 0xe0, 0x69, - 0x35, 0x8b, 0x3e, 0x6b, 0x3a, 0xa5, 0x0b, 0x15, 0xed, 0x72, 0x8d, 0x68, 0x6e, 0xe6, 0x2f, 0x53, - 0x89, 0xe6, 0x26, 0xe5, 0x2e, 0x0e, 0xe3, 0x1e, 0xb6, 0x63, 0xb0, 0xbb, 0x71, 0x3b, 0x74, 0xff, - 0x46, 0xdc, 0xd2, 0xc3, 0x9f, 0xd8, 0xe3, 0xf0, 0x0b, 0xf6, 0x29, 0xbd, 0x0e, 0xed, 0x98, 0x64, - 0x6c, 0x9c, 0xcc, 0x9e, 0xa8, 0x8c, 0x26, 0x4b, 0x43, 0x25, 0x0d, 0x16, 0x6a, 0x0a, 0x35, 0xc6, - 0x27, 0x00, 0xbd, 0xd0, 0x9b, 0x6c, 0xdb, 0x7c, 0xec, 0xb9, 0xb1, 0x4c, 0x8f, 0x0f, 0xee, 0xc5, - 0x72, 0x52, 0x3b, 0xbd, 0xc7, 0x3e, 0xd5, 0xac, 0xb9, 0xc4, 0x01, 0x5f, 0xc5, 0xc4, 0xd7, 0x9e, - 0xed, 0x8b, 0x26, 0x24, 0xe5, 0x7c, 0xdf, 0xa3, 0x0c, 0x6b, 0x01, 0xc4, 0xc9, 0x6d, 0x91, 0x6d, - 0x36, 0x97, 0x37, 0x17, 0x89, 0xd7, 0x94, 0x4c, 0xb8, 0x43, 0x28, 0xc7, 0x59, 0x41, 0xeb, 0xf1, - 0x5d, 0x41, 0x89, 0x1c, 0xa2, 0x48, 0x53, 0x98, 0xcb, 0xc8, 0x31, 0x1a, 0x38, 0x55, 0xc0, 0x4a, - 0x62, 0xaa, 0x4e, 0x38, 0x0f, 0x98, 0x03, 0xcb, 0xd4, 0xc1, 0x48, 0x2d, 0xc3, 0x03, 0x67, 0xd1, - 0x47, 0x22, 0xe6, 0x93, 0x63, 0x22, 0xa9, 0x91, 0x9a, 0xe2, 0x91, 0x70, 0x31, 0x09, 0x6e, 0xa5, - 0xc3, 0x6e, 0x62, 0x0b, 0x18, 0xc3, 0xd2, 0x5c, 0x16, 0x41, 0x24, 0x3a, 0xae, 0x4b, 0x0b, 0x89, - 0x44, 0xc7, 0xb5, 0x09, 0x08, 0xc6, 0x2a, 0x36, 0xb9, 0x68, 0x00, 0x9a, 0x94, 0x17, 0x4e, 0x38, - 0x38, 0x13, 0xcd, 0xfd, 0x41, 0x06, 0x96, 0x53, 0xf2, 0x04, 0xd8, 0x1b, 0xca, 0x3b, 0x71, 0x6d, - 0x0e, 0xc1, 0x46, 0x6a, 0x3c, 0xd9, 0xe8, 0x61, 0x3b, 0xfb, 0xec, 0x59, 0x62, 0x03, 0xa5, 0x70, - 0xae, 0x5c, 0x99, 0x2f, 0x54, 0x5e, 0x52, 0x35, 0x97, 0xcf, 0x61, 0x9d, 0x3a, 0xd2, 0x1a, 0x8d, - 0x66, 0x62, 0xdd, 0xaf, 0x6b, 0xbd, 0x48, 0x89, 0xdf, 0x27, 0xec, 0x80, 0x64, 0x0c, 0xff, 0x1a, - 0xb5, 0x9d, 0xba, 0xca, 0xa6, 0xd0, 0x98, 0x8d, 0x21, 0xb3, 0xeb, 0xeb, 0xda, 0xb8, 0x93, 0xb0, - 0xb3, 0x53, 0xe2, 0xce, 0x5f, 0xc3, 0xc6, 0xee, 0x18, 0x1b, 0x69, 0xf3, 0x42, 0xa6, 0xb7, 0x78, - 0x1f, 0x7f, 0x23, 0x0a, 0x78, 0xcf, 0x8c, 0x53, 0x35, 0x70, 0x5d, 0x78, 0x3e, 0xb2, 0xf4, 0xd3, - 0xe3, 0xe5, 0x6f, 0x63, 0xf3, 0x77, 0x8d, 0x5b, 0x69, 0xcd, 0xfb, 0x54, 0x84, 0x6c, 0xfe, 0xf5, - 0xd9, 0x75, 0xad, 0x7a, 0x70, 0x37, 0xed, 0x7d, 0x5f, 0x6b, 0x73, 0xcd, 0xcc, 0xf5, 0x0d, 0xd4, - 0x21, 0xab, 0x7a, 0x80, 0x3b, 0x5a, 0x3e, 0x29, 0x91, 0xf4, 0x68, 0xf9, 0xa4, 0x45, 0xc4, 0x93, - 0xfa, 0x93, 0x8a, 0x85, 0x7f, 0x98, 0xb9, 0xbf, 0xf9, 0xce, 0x0f, 0xbf, 0x76, 0xea, 0x84, 0x67, - 0xd3, 0xe3, 0x07, 0x03, 0x6f, 0xfc, 0x70, 0xa4, 0xbc, 0x9a, 0xf2, 0x54, 0xf6, 0xc3, 0x91, 0x3b, - 0x7c, 0x88, 0xd5, 0x1e, 0x2f, 0x4c, 0x7c, 0x2f, 0xf4, 0xbe, 0xf9, 0x7f, 0x03, 0x00, 0x00, 0xff, - 0xff, 0x25, 0xc9, 0xbe, 0xb5, 0x81, 0x86, 0x00, 0x00, + // 11837 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5d, 0x6f, 0x24, 0x49, + 0x72, 0xd8, 0xf4, 0x17, 0xbb, 0x3b, 0xfa, 0x83, 0xcd, 0xe4, 0x57, 0x0f, 0x67, 0x67, 0x67, 0xb6, + 0x6e, 0x6f, 0x77, 0x76, 0xf6, 0x8e, 0x33, 0x3b, 0x77, 0xbb, 0x77, 0xb7, 0x6b, 0x9d, 0xae, 0x49, + 0x36, 0x87, 0x7d, 0x43, 0x36, 0xb9, 0xd5, 0xcd, 0x5d, 0xed, 0xe9, 0xa3, 0xae, 0xd8, 0x9d, 0x24, + 0x4b, 0xd3, 0x5d, 0xd5, 0x5b, 0x55, 0xcd, 0x8f, 0x3b, 0xac, 0x1f, 0x0c, 0x5b, 0x30, 0x0c, 0xdb, + 0x80, 0x60, 0xcb, 0x80, 0x65, 0x0b, 0x36, 0x2c, 0x18, 0x86, 0x21, 0x40, 0x10, 0x70, 0xf2, 0x83, + 0x01, 0xbf, 0x0b, 0x06, 0x6c, 0x08, 0x86, 0xe4, 0x17, 0x43, 0x10, 0x60, 0xd8, 0x96, 0xdf, 0x0c, + 0x01, 0xfe, 0x03, 0x46, 0x46, 0x64, 0x56, 0x65, 0x75, 0x17, 0x67, 0x66, 0xef, 0xce, 0xf7, 0x42, + 0x76, 0x45, 0x46, 0x7e, 0x47, 0x46, 0x46, 0x64, 0x44, 0x64, 0x42, 0xd9, 0x9f, 0x0c, 0x36, 0x27, + 0xbe, 0x17, 0x7a, 0xac, 0x30, 0x72, 0xfd, 0xc9, 0x60, 0xe3, 0xb5, 0x33, 0xcf, 0x3b, 0x1b, 0xf1, + 0x47, 0xf6, 0xc4, 0x79, 0x64, 0xbb, 0xae, 0x17, 0xda, 0xa1, 0xe3, 0xb9, 0x01, 0x21, 0x19, 0x3f, + 0x84, 0xfa, 0x53, 0xee, 0xf6, 0x38, 0x1f, 0x9a, 0xfc, 0xf3, 0x29, 0x0f, 0x42, 0xf6, 0x2e, 0x2c, + 0xd9, 0xfc, 0x47, 0x9c, 0x0f, 0xad, 0x89, 0x1d, 0x04, 0x93, 0x73, 0xdf, 0x0e, 0x78, 0x33, 0x73, + 0x3f, 0xf3, 0xa0, 0x6a, 0x36, 0x28, 0xe1, 0x28, 0x82, 0xb3, 0x37, 0xa0, 0x1a, 0x08, 0x54, 0xee, + 0x86, 0xbe, 0x37, 0xb9, 0x6e, 0x66, 0x11, 0xaf, 0x22, 0x60, 0x6d, 0x02, 0x19, 0x23, 0x58, 0x8c, + 0x6a, 0x08, 0x26, 0x9e, 0x1b, 0x70, 0xf6, 0x18, 0x56, 0x06, 0xce, 0xe4, 0x9c, 0xfb, 0x16, 0x66, + 0x1e, 0xbb, 0x7c, 0xec, 0xb9, 0xce, 0xa0, 0x99, 0xb9, 0x9f, 0x7b, 0x50, 0x36, 0x19, 0xa5, 0x89, + 0x1c, 0x07, 0x32, 0x85, 0xbd, 0x0d, 0x8b, 0xdc, 0x25, 0x38, 0x1f, 0x62, 0x2e, 0x59, 0x55, 0x3d, + 0x06, 0x8b, 0x0c, 0xc6, 0xdf, 0xcd, 0xc2, 0x52, 0xc7, 0x75, 0xc2, 0x4f, 0xed, 0xd1, 0x88, 0x87, + 0xaa, 0x4f, 0x6f, 0xc3, 0xe2, 0x25, 0x02, 0xb0, 0x4f, 0x97, 0x9e, 0x3f, 0x94, 0x3d, 0xaa, 0x13, + 0xf8, 0x48, 0x42, 0x6f, 0x6c, 0x59, 0xf6, 0xc6, 0x96, 0xa5, 0x0e, 0x57, 0xee, 0x86, 0xe1, 0x7a, + 0x1b, 0x16, 0x7d, 0x3e, 0xf0, 0x2e, 0xb8, 0x7f, 0x6d, 0x5d, 0x3a, 0xee, 0xd0, 0xbb, 0x6c, 0xe6, + 0xef, 0x67, 0x1e, 0x14, 0xcc, 0xba, 0x02, 0x7f, 0x8a, 0x50, 0xb6, 0x05, 0x8b, 0x83, 0x73, 0xdb, + 0x75, 0xf9, 0xc8, 0x3a, 0xb1, 0x07, 0xcf, 0xa7, 0x93, 0xa0, 0x59, 0xb8, 0x9f, 0x79, 0x50, 0x79, + 0x72, 0x7b, 0x13, 0x67, 0x75, 0x73, 0xfb, 0xdc, 0x76, 0xb7, 0x30, 0xa5, 0xe7, 0xda, 0x93, 0xe0, + 0xdc, 0x0b, 0xcd, 0xba, 0xcc, 0x41, 0xe0, 0xc0, 0x58, 0x01, 0xa6, 0x8f, 0x04, 0x8d, 0xbd, 0xf1, + 0x07, 0x19, 0x58, 0x3e, 0x76, 0x47, 0xde, 0xe0, 0xf9, 0x4f, 0x39, 0x44, 0x29, 0x7d, 0xc8, 0xbe, + 0x6a, 0x1f, 0x72, 0x5f, 0xb6, 0x0f, 0x6b, 0xb0, 0x92, 0x6c, 0xac, 0xec, 0x05, 0x87, 0x55, 0x91, + 0xfb, 0x8c, 0xab, 0x66, 0xa9, 0x6e, 0xbc, 0x03, 0x8d, 0xc1, 0xd4, 0xf7, 0xb9, 0x3b, 0xd7, 0x8f, + 0x45, 0x09, 0x8f, 0x3a, 0xf2, 0x06, 0x54, 0x5d, 0x7e, 0x19, 0xa3, 0x49, 0xda, 0x75, 0xf9, 0xa5, + 0x42, 0x31, 0x9a, 0xb0, 0x36, 0x5b, 0x8d, 0x6c, 0xc0, 0x5f, 0x65, 0x20, 0x7f, 0x1c, 0x5e, 0x79, + 0xec, 0x7d, 0xa8, 0xda, 0xc3, 0xa1, 0xcf, 0x83, 0xc0, 0x0a, 0xaf, 0x27, 0xb4, 0x52, 0xea, 0x4f, + 0x98, 0xec, 0x62, 0x8b, 0x92, 0xfa, 0xd7, 0x13, 0x6e, 0x56, 0xec, 0xf8, 0x83, 0x35, 0xa1, 0x28, + 0x3f, 0xb1, 0xde, 0xb2, 0xa9, 0x3e, 0xd9, 0x5d, 0x00, 0x7b, 0xec, 0x4d, 0xdd, 0xd0, 0x0a, 0xec, + 0x10, 0x47, 0x2c, 0x67, 0x96, 0x09, 0xd2, 0xb3, 0x43, 0x76, 0x07, 0xca, 0x93, 0xe7, 0x56, 0x30, + 0xf0, 0x9d, 0x49, 0x88, 0xc4, 0x53, 0x36, 0x4b, 0x93, 0xe7, 0x3d, 0xfc, 0x66, 0xef, 0x42, 0xc9, + 0x9b, 0x86, 0x13, 0xcf, 0x71, 0x43, 0x49, 0x2f, 0x8b, 0xb2, 0x21, 0x87, 0xd3, 0xf0, 0x48, 0x80, + 0xcd, 0x08, 0x81, 0xbd, 0x09, 0xb5, 0x81, 0xe7, 0x9e, 0x3a, 0xfe, 0x98, 0x38, 0x42, 0x73, 0x01, + 0xeb, 0x4a, 0x02, 0x8d, 0x3f, 0xca, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, + 0x43, 0x31, 0xbc, 0xb2, 0xce, 0xed, 0xe0, 0x1c, 0xbb, 0x5a, 0x36, 0x17, 0xc2, 0xab, 0x3d, 0x3b, + 0x38, 0x67, 0x6b, 0xb0, 0x40, 0xad, 0xc4, 0x0e, 0xe5, 0x4c, 0xf9, 0x25, 0x16, 0x88, 0x3b, 0x1d, + 0x5b, 0xc9, 0xaa, 0x72, 0x48, 0x31, 0x0d, 0x77, 0x3a, 0xde, 0xd6, 0xe1, 0xa2, 0xf3, 0x27, 0x62, + 0xba, 0xa9, 0x02, 0xea, 0x5e, 0x19, 0x21, 0x58, 0xc7, 0x1b, 0x50, 0x95, 0xc9, 0xdc, 0x39, 0x3b, + 0xa7, 0x3e, 0x16, 0xcc, 0x0a, 0x21, 0x20, 0x48, 0x94, 0x10, 0x3a, 0x63, 0x6e, 0x05, 0xa1, 0x3d, + 0x9e, 0xc8, 0x2e, 0x95, 0x05, 0xa4, 0x27, 0x00, 0x98, 0xec, 0x85, 0xf6, 0xc8, 0x3a, 0xe5, 0x3c, + 0x68, 0x16, 0x65, 0xb2, 0x80, 0xec, 0x72, 0x1e, 0xb0, 0xaf, 0x42, 0x7d, 0xc8, 0x83, 0xd0, 0x92, + 0x93, 0xc1, 0x83, 0x66, 0x09, 0x57, 0x7e, 0x4d, 0x40, 0x5b, 0x0a, 0xc8, 0x5e, 0x03, 0xf0, 0xed, + 0x4b, 0x4b, 0x0c, 0x04, 0xbf, 0x6a, 0x96, 0x69, 0x16, 0x7c, 0xfb, 0xb2, 0x7f, 0xb5, 0xc7, 0xaf, + 0x04, 0xd5, 0x3c, 0xe5, 0xa1, 0x36, 0x68, 0x81, 0xa4, 0x4e, 0x63, 0x1f, 0x98, 0x06, 0xde, 0xe1, + 0xa1, 0xed, 0x8c, 0x02, 0xf6, 0x01, 0x54, 0x43, 0x0d, 0x19, 0xd9, 0x60, 0x25, 0x22, 0x21, 0x2d, + 0x83, 0x99, 0xc0, 0x33, 0xce, 0xa1, 0xb4, 0xcb, 0xf9, 0xbe, 0x33, 0x76, 0x42, 0xb6, 0x06, 0x85, + 0x53, 0xe7, 0x8a, 0x13, 0xb1, 0xe7, 0xf6, 0x6e, 0x99, 0xf4, 0xc9, 0xee, 0x01, 0xe0, 0x0f, 0x6b, + 0x1c, 0x51, 0xd3, 0xde, 0x2d, 0xb3, 0x8c, 0xb0, 0x83, 0xc0, 0x0e, 0xd9, 0x06, 0x14, 0x27, 0xdc, + 0x1f, 0x70, 0x35, 0x6f, 0x7b, 0xb7, 0x4c, 0x05, 0xd8, 0x2a, 0x42, 0x61, 0x24, 0x4a, 0x37, 0xfe, + 0xa4, 0x00, 0x95, 0x1e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, 0xcd, + 0xbe, 0x02, 0x15, 0x1c, 0xba, 0x20, 0xf4, 0x1d, 0xf7, 0x8c, 0xa8, 0x7a, 0x2b, 0xdb, 0xcc, 0x98, + 0x20, 0xc0, 0x3d, 0x84, 0xb2, 0x06, 0xe4, 0xec, 0xb1, 0xa2, 0x6a, 0xf1, 0x93, 0xdd, 0x86, 0x92, + 0x3d, 0x0e, 0xa9, 0x79, 0x55, 0x04, 0x17, 0xed, 0x71, 0x88, 0x4d, 0x7b, 0x03, 0xaa, 0x13, 0xfb, + 0x7a, 0x2c, 0xd6, 0x72, 0x44, 0x0e, 0x55, 0xb3, 0x22, 0x61, 0x48, 0x10, 0x4f, 0x60, 0x59, 0x47, + 0x51, 0x95, 0x17, 0xa2, 0xca, 0x97, 0x34, 0x6c, 0xd9, 0x86, 0xb7, 0x61, 0x51, 0xe5, 0xf1, 0xa9, + 0x3f, 0x48, 0x26, 0x65, 0xb3, 0x2e, 0xc1, 0xaa, 0x97, 0x0f, 0xa0, 0x71, 0xea, 0xb8, 0xf6, 0xc8, + 0x1a, 0x8c, 0xc2, 0x0b, 0x6b, 0xc8, 0x47, 0xa1, 0x8d, 0x14, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1e, + 0x85, 0x17, 0x3b, 0x02, 0xca, 0xbe, 0x06, 0xe5, 0x53, 0xce, 0x2d, 0x1c, 0xac, 0x66, 0x29, 0xb1, + 0xf0, 0xd4, 0x0c, 0x99, 0xa5, 0x53, 0x35, 0x57, 0x5f, 0x83, 0x86, 0x37, 0x0d, 0xcf, 0x3c, 0xc7, + 0x3d, 0xb3, 0x04, 0xbf, 0xb3, 0x9c, 0x21, 0xd2, 0x50, 0x7e, 0x2b, 0xfb, 0x38, 0x63, 0xd6, 0x55, + 0x9a, 0xe0, 0x3c, 0x9d, 0x21, 0x7b, 0x0b, 0x16, 0x47, 0x76, 0x10, 0x5a, 0xe7, 0xde, 0xc4, 0x9a, + 0x4c, 0x4f, 0x9e, 0xf3, 0xeb, 0x66, 0x0d, 0x07, 0xa2, 0x26, 0xc0, 0x7b, 0xde, 0xe4, 0x08, 0x81, + 0x82, 0xb2, 0xb1, 0x9d, 0xd4, 0x08, 0xb8, 0x9f, 0x79, 0x50, 0x33, 0xcb, 0x02, 0x42, 0x95, 0x7e, + 0x06, 0xcb, 0x38, 0x3d, 0x83, 0x69, 0x10, 0x7a, 0x63, 0x4b, 0xf0, 0x6a, 0x7f, 0x18, 0x34, 0x2b, + 0x48, 0x6b, 0xef, 0xc8, 0xc6, 0x6a, 0x73, 0xbc, 0xb9, 0xc3, 0x83, 0x70, 0x1b, 0x91, 0x4d, 0xc2, + 0x15, 0x1b, 0xfa, 0xb5, 0xb9, 0x34, 0x9c, 0x85, 0xb3, 0xaf, 0x01, 0xb3, 0x47, 0x23, 0xef, 0xd2, + 0x0a, 0xf8, 0xe8, 0xd4, 0x92, 0x83, 0xd8, 0xac, 0xdf, 0xcf, 0x3c, 0x28, 0x99, 0x0d, 0x4c, 0xe9, + 0xf1, 0xd1, 0xe9, 0x11, 0xc1, 0xd9, 0x07, 0x80, 0x8b, 0xc9, 0x3a, 0xe5, 0x76, 0x38, 0xf5, 0x79, + 0xd0, 0x5c, 0xbc, 0x9f, 0x7b, 0x50, 0x7f, 0xb2, 0x14, 0x8d, 0x17, 0x82, 0xb7, 0x9c, 0xd0, 0xac, + 0x0a, 0x3c, 0xf9, 0x1d, 0x6c, 0xec, 0xc0, 0x5a, 0x7a, 0x93, 0x04, 0x51, 0x89, 0x51, 0x11, 0xc4, + 0x98, 0x37, 0xc5, 0x4f, 0xb6, 0x02, 0x85, 0x0b, 0x7b, 0x34, 0xe5, 0x92, 0xa7, 0xd3, 0xc7, 0x87, + 0xd9, 0x6f, 0x67, 0x8c, 0x3f, 0xce, 0x40, 0x95, 0x7a, 0x29, 0x65, 0x91, 0xaf, 0x40, 0x4d, 0x51, + 0x03, 0xf7, 0x7d, 0xcf, 0x97, 0x5c, 0x4d, 0x51, 0x5e, 0x5b, 0xc0, 0xc4, 0xae, 0xa2, 0x90, 0x26, + 0x3e, 0x77, 0xc6, 0xf6, 0x99, 0x2a, 0x5a, 0x91, 0xd2, 0x91, 0x04, 0xb3, 0xf7, 0xe2, 0xf2, 0x7c, + 0x6f, 0x1a, 0x72, 0xb9, 0xe7, 0x55, 0x65, 0xf7, 0x4c, 0x01, 0x8b, 0x4a, 0xc7, 0xaf, 0x57, 0xa0, + 0x73, 0xe3, 0x77, 0x32, 0xc0, 0x44, 0xb3, 0xfb, 0x1e, 0x15, 0x20, 0x29, 0x74, 0x36, 0x67, 0xe6, + 0x95, 0x57, 0x48, 0xf6, 0x45, 0x2b, 0xc4, 0x80, 0x02, 0xb5, 0x3d, 0x9f, 0xd2, 0x76, 0x4a, 0xfa, + 0x7e, 0xbe, 0x94, 0x6b, 0xe4, 0x8d, 0xff, 0x96, 0x83, 0x95, 0x6d, 0xda, 0xb2, 0x5b, 0x83, 0x01, + 0x9f, 0x44, 0x6b, 0xe7, 0x1e, 0x54, 0x5c, 0x6f, 0xc8, 0x15, 0xc5, 0x52, 0xc3, 0x40, 0x80, 0x34, + 0x72, 0x3d, 0xb7, 0x1d, 0x97, 0x1a, 0x4e, 0x83, 0x59, 0x46, 0x08, 0x36, 0xfb, 0x2d, 0x58, 0x9c, + 0x70, 0x77, 0xa8, 0x2f, 0x11, 0x12, 0xaa, 0x6a, 0x12, 0x2c, 0x57, 0xc7, 0x3d, 0xa8, 0x9c, 0x4e, + 0x09, 0x4f, 0x30, 0x96, 0x3c, 0xd2, 0x00, 0x48, 0x50, 0x8b, 0xf8, 0xcb, 0x64, 0x1a, 0x9c, 0x63, + 0x6a, 0x01, 0x53, 0x8b, 0xe2, 0x5b, 0x24, 0xdd, 0x05, 0x18, 0x4e, 0x83, 0x50, 0xae, 0x98, 0x05, + 0x4c, 0x2c, 0x0b, 0x08, 0xad, 0x98, 0xaf, 0xc3, 0xf2, 0xd8, 0xbe, 0xb2, 0x90, 0x76, 0x2c, 0xc7, + 0xb5, 0x4e, 0x47, 0xb8, 0xe7, 0x14, 0x11, 0xaf, 0x31, 0xb6, 0xaf, 0x3e, 0x11, 0x29, 0x1d, 0x77, + 0x17, 0xe1, 0x82, 0xad, 0x28, 0x71, 0xc7, 0xe7, 0x01, 0xf7, 0x2f, 0x38, 0x72, 0x82, 0x7c, 0x24, + 0xd3, 0x98, 0x04, 0x15, 0x2d, 0x1a, 0x8b, 0x7e, 0x87, 0xa3, 0x01, 0x2d, 0x7b, 0xb3, 0x38, 0x76, + 0xdc, 0xbd, 0x70, 0x34, 0x10, 0xfb, 0x8a, 0xe0, 0x23, 0x13, 0xee, 0x5b, 0xcf, 0x2f, 0x71, 0x0d, + 0xe7, 0x91, 0x6f, 0x1c, 0x71, 0xff, 0xd9, 0xa5, 0xd8, 0xfa, 0x07, 0x01, 0x32, 0x22, 0xfb, 0xba, + 0x59, 0xc1, 0x05, 0x5e, 0x1a, 0x04, 0x82, 0x05, 0xd9, 0xd7, 0x62, 0x11, 0x8a, 0xd6, 0xda, 0x38, + 0x0b, 0x7c, 0x88, 0xc5, 0x07, 0xc8, 0x51, 0x6b, 0xd8, 0xd8, 0x96, 0x4c, 0x10, 0xf5, 0x04, 0x82, + 0xea, 0x55, 0x63, 0x4f, 0x47, 0xf6, 0x59, 0x80, 0x2c, 0xa5, 0x66, 0x56, 0x25, 0x70, 0x57, 0xc0, + 0x8c, 0x4f, 0x49, 0xc8, 0xd2, 0xe6, 0x56, 0xae, 0x19, 0xb1, 0xd5, 0x23, 0x04, 0xe7, 0xb5, 0x64, + 0xca, 0xaf, 0xb4, 0x49, 0xcb, 0xa6, 0x4c, 0x9a, 0xf1, 0x7b, 0x19, 0xa8, 0xca, 0x92, 0x51, 0x28, + 0x61, 0x9b, 0xc0, 0xd4, 0x2c, 0x86, 0x57, 0xce, 0xd0, 0x3a, 0xb9, 0x0e, 0x79, 0x40, 0x44, 0xb3, + 0x77, 0xcb, 0x6c, 0xc8, 0xb4, 0xfe, 0x95, 0x33, 0xdc, 0x12, 0x29, 0xec, 0x21, 0x34, 0x12, 0xf8, + 0x41, 0xe8, 0x13, 0x45, 0xef, 0xdd, 0x32, 0xeb, 0x1a, 0x76, 0x2f, 0xf4, 0xc5, 0x1a, 0x11, 0x22, + 0xcf, 0x34, 0xb4, 0x1c, 0x77, 0xc8, 0xaf, 0x90, 0x8c, 0x6a, 0x66, 0x85, 0x60, 0x1d, 0x01, 0xda, + 0xaa, 0x43, 0x55, 0x2f, 0xce, 0x38, 0x83, 0x92, 0x92, 0x97, 0x50, 0x60, 0x98, 0x69, 0x92, 0x59, + 0x0e, 0xa3, 0x96, 0xdc, 0x86, 0x52, 0xb2, 0x05, 0x66, 0x31, 0x7c, 0xe5, 0x8a, 0x8d, 0xef, 0x42, + 0x63, 0x5f, 0x10, 0x8f, 0x2b, 0x88, 0x55, 0xca, 0x7f, 0x6b, 0xb0, 0xa0, 0x2d, 0x9a, 0xb2, 0x29, + 0xbf, 0xc4, 0x9e, 0x7b, 0xee, 0x05, 0xa1, 0xac, 0x05, 0x7f, 0x1b, 0x7f, 0x92, 0x01, 0xd6, 0x0e, + 0x42, 0x67, 0x6c, 0x87, 0x7c, 0x97, 0x47, 0x6c, 0xe1, 0x10, 0xaa, 0xa2, 0xb4, 0xbe, 0xd7, 0x22, + 0x81, 0x8c, 0x04, 0x8a, 0x77, 0xe5, 0x32, 0x9e, 0xcf, 0xb0, 0xa9, 0x63, 0x13, 0x9b, 0x4f, 0x14, + 0x20, 0x56, 0x59, 0x68, 0xfb, 0x67, 0x3c, 0x44, 0x31, 0x4e, 0xca, 0xfb, 0x40, 0x20, 0x21, 0xc0, + 0x6d, 0xfc, 0x32, 0x2c, 0xcd, 0x95, 0xa1, 0xf3, 0xe5, 0x72, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, + 0x82, 0xe5, 0x44, 0xbb, 0x24, 0xa5, 0xad, 0x43, 0x51, 0x2c, 0x08, 0x21, 0x1c, 0x64, 0x48, 0xaa, + 0x3c, 0xe5, 0x5c, 0x88, 0xc1, 0x8f, 0x60, 0xe5, 0x94, 0x73, 0xdf, 0x0e, 0x31, 0x11, 0x57, 0x8c, + 0x98, 0x21, 0x59, 0xf0, 0x92, 0x4c, 0xeb, 0xd9, 0xe1, 0x11, 0xf7, 0xc5, 0x4c, 0x19, 0xff, 0x23, + 0x03, 0x8b, 0x82, 0x83, 0x1e, 0xd8, 0xee, 0xb5, 0x1a, 0xa7, 0xfd, 0xd4, 0x71, 0x7a, 0xa0, 0x6d, + 0x86, 0x1a, 0xf6, 0x97, 0x1d, 0xa4, 0xdc, 0xec, 0x20, 0xb1, 0xfb, 0x50, 0x4d, 0xb4, 0xb5, 0x80, + 0x6d, 0x85, 0x20, 0x6a, 0xe4, 0xcf, 0x3e, 0x8c, 0x6f, 0x41, 0x23, 0x6e, 0xb6, 0x1c, 0x43, 0x06, + 0x79, 0x41, 0x92, 0xb2, 0x00, 0xfc, 0x6d, 0xfc, 0xf3, 0x0c, 0x21, 0x6e, 0x7b, 0x4e, 0x24, 0x9d, + 0x0a, 0x44, 0x21, 0xf7, 0x2a, 0x44, 0xf1, 0xfb, 0x46, 0xa9, 0xfe, 0x67, 0xef, 0xac, 0x58, 0x3a, + 0x01, 0x77, 0x87, 0x96, 0x3d, 0x1a, 0x21, 0xf3, 0x2d, 0x99, 0x45, 0xf1, 0xdd, 0x1a, 0x8d, 0x8c, + 0xb7, 0x61, 0x49, 0x6b, 0xdd, 0x0b, 0xfa, 0xd1, 0x05, 0xb6, 0xef, 0x04, 0xe1, 0xb1, 0x1b, 0x4c, + 0x34, 0xc1, 0xed, 0x0e, 0x94, 0x05, 0x87, 0x15, 0x2d, 0xa3, 0x25, 0x5b, 0x30, 0x05, 0xcb, 0x15, + 0xed, 0x0a, 0x30, 0xd1, 0xbe, 0x92, 0x89, 0x59, 0x99, 0x68, 0x5f, 0x61, 0xa2, 0xf1, 0x6d, 0x58, + 0x4e, 0x94, 0x27, 0xab, 0x7e, 0x03, 0x0a, 0xd3, 0xf0, 0xca, 0x53, 0xa2, 0x79, 0x45, 0x52, 0x88, + 0x50, 0x00, 0x4d, 0x4a, 0x31, 0x3e, 0x82, 0xa5, 0x2e, 0xbf, 0x94, 0x8b, 0x58, 0x35, 0xe4, 0x2d, + 0xc8, 0xbf, 0x44, 0x29, 0xc4, 0x74, 0x63, 0x13, 0x98, 0x9e, 0x59, 0xd6, 0xaa, 0xe9, 0x88, 0x99, + 0x84, 0x8e, 0x68, 0xbc, 0x05, 0xac, 0xe7, 0x9c, 0xb9, 0x07, 0x3c, 0x08, 0xec, 0xb3, 0x68, 0xd9, + 0x37, 0x20, 0x37, 0x0e, 0xce, 0x24, 0x8f, 0x12, 0x3f, 0x8d, 0x6f, 0xc0, 0x72, 0x02, 0x4f, 0x16, + 0xfc, 0x1a, 0x94, 0x03, 0xe7, 0xcc, 0x45, 0xc1, 0x4a, 0x16, 0x1d, 0x03, 0x8c, 0x5d, 0x58, 0xf9, + 0x84, 0xfb, 0xce, 0xe9, 0xf5, 0xcb, 0x8a, 0x4f, 0x96, 0x93, 0x9d, 0x2d, 0xa7, 0x0d, 0xab, 0x33, + 0xe5, 0xc8, 0xea, 0x89, 0x7c, 0xe5, 0x4c, 0x96, 0x4c, 0xfa, 0xd0, 0xf8, 0x5e, 0x56, 0xe7, 0x7b, + 0xc6, 0x31, 0xb0, 0x6d, 0xcf, 0x75, 0xf9, 0x20, 0x3c, 0xe2, 0xdc, 0x8f, 0x4f, 0xa9, 0x62, 0x5a, + 0xad, 0x3c, 0x59, 0x97, 0x23, 0x3b, 0xcb, 0x4c, 0x25, 0x11, 0x33, 0xc8, 0x4f, 0xb8, 0x3f, 0xc6, + 0x82, 0x4b, 0x26, 0xfe, 0x36, 0x56, 0x61, 0x39, 0x51, 0xac, 0xd4, 0xeb, 0x1f, 0xc3, 0xea, 0x8e, + 0x13, 0x0c, 0xe6, 0x2b, 0x5c, 0x87, 0xe2, 0x64, 0x7a, 0x62, 0x25, 0xf9, 0xf2, 0x33, 0x7e, 0x2d, + 0xb4, 0xbd, 0xd9, 0x1c, 0xb2, 0xac, 0xbf, 0x9d, 0x81, 0xfc, 0x5e, 0x7f, 0x7f, 0x9b, 0x6d, 0x40, + 0xc9, 0x71, 0x07, 0xde, 0x58, 0x08, 0x5e, 0xd4, 0xe7, 0xe8, 0xfb, 0xc6, 0x05, 0x76, 0x07, 0xca, + 0x28, 0xaf, 0x09, 0xd5, 0x56, 0x8a, 0x3e, 0x25, 0x01, 0xd8, 0xf7, 0x06, 0xcf, 0x85, 0x4e, 0xcd, + 0xaf, 0x26, 0x8e, 0x8f, 0x5a, 0xb3, 0x52, 0x86, 0xf3, 0xb4, 0xd7, 0xc7, 0x09, 0xa4, 0x11, 0x1b, + 0xff, 0xbe, 0x04, 0x45, 0xb9, 0xdb, 0xd2, 0xce, 0x1d, 0x3a, 0x17, 0x3c, 0xde, 0xb9, 0xc5, 0x97, + 0x90, 0x07, 0x7c, 0x3e, 0xf6, 0xc2, 0x48, 0x60, 0xa3, 0x39, 0xa8, 0x12, 0x50, 0x8a, 0x6c, 0x9a, + 0xd0, 0x40, 0x47, 0x0c, 0x39, 0x42, 0x1a, 0xe8, 0x5b, 0xf9, 0x1d, 0x28, 0xaa, 0xbd, 0x3f, 0x1f, + 0xe9, 0x34, 0x0b, 0x03, 0x92, 0xd6, 0x36, 0xa0, 0x34, 0xb0, 0x27, 0xf6, 0xc0, 0x09, 0xaf, 0x25, + 0x43, 0x88, 0xbe, 0x45, 0xe9, 0x23, 0x6f, 0x60, 0x8f, 0xac, 0x13, 0x7b, 0x64, 0xbb, 0x03, 0x2e, + 0x75, 0xf7, 0x2a, 0x02, 0xb7, 0x08, 0x26, 0xf4, 0x73, 0xd9, 0x4e, 0x85, 0x45, 0x2a, 0xbc, 0x6c, + 0xbd, 0x42, 0x13, 0xc2, 0xa5, 0x37, 0x1e, 0x3b, 0x42, 0xcb, 0x20, 0x31, 0x2c, 0x67, 0x96, 0x09, + 0xb2, 0xcb, 0xb1, 0xb7, 0x32, 0xf9, 0x92, 0x86, 0xae, 0x4c, 0x55, 0x11, 0xf0, 0x53, 0x3a, 0x48, + 0x98, 0x97, 0xc5, 0x72, 0x9a, 0x2c, 0xf6, 0x2e, 0x2c, 0x4d, 0xdd, 0x80, 0x87, 0xe1, 0x88, 0x0f, + 0xa3, 0xb6, 0x54, 0x10, 0xa9, 0x11, 0x25, 0xa8, 0xe6, 0x6c, 0xc2, 0x32, 0x1d, 0x3a, 0x04, 0x76, + 0xe8, 0x05, 0xe7, 0x4e, 0x60, 0x05, 0x42, 0x43, 0x22, 0x75, 0x77, 0x09, 0x93, 0x7a, 0x32, 0xa5, + 0x47, 0x2a, 0xd2, 0xfa, 0x0c, 0xbe, 0xcf, 0x07, 0xdc, 0xb9, 0xe0, 0x43, 0x94, 0xd3, 0x72, 0xe6, + 0x6a, 0x22, 0x8f, 0x29, 0x13, 0x51, 0xe8, 0x9e, 0x8e, 0xad, 0xe9, 0x64, 0x68, 0x0b, 0x61, 0xa5, + 0x4e, 0xc2, 0xb0, 0x3b, 0x1d, 0x1f, 0x13, 0x84, 0x3d, 0x06, 0x25, 0x89, 0x49, 0xf9, 0x70, 0x31, + 0xc1, 0xcf, 0x04, 0xb1, 0x9a, 0x55, 0x89, 0x41, 0x82, 0x62, 0x42, 0xe6, 0x6c, 0xcc, 0xc8, 0x9c, + 0x4d, 0x28, 0x4e, 0x7c, 0xe7, 0xc2, 0x0e, 0x79, 0x73, 0x89, 0x18, 0xb8, 0xfc, 0x14, 0x9c, 0xc1, + 0x71, 0x9d, 0xd0, 0xb1, 0x43, 0xcf, 0x6f, 0x32, 0x4c, 0x8b, 0x01, 0xec, 0x21, 0x2c, 0x21, 0x8d, + 0x04, 0xa1, 0x1d, 0x4e, 0x03, 0x29, 0x81, 0x2e, 0x23, 0x31, 0xa1, 0x0c, 0xdd, 0x43, 0x38, 0x0a, + 0xa1, 0xec, 0x1b, 0xb0, 0x46, 0x64, 0x81, 0x39, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x0a, 0x0e, 0xc5, + 0x32, 0xa6, 0x0a, 0xfa, 0x96, 0xf2, 0xb5, 0x90, 0x0e, 0xde, 0x87, 0x75, 0x49, 0x26, 0x73, 0xb9, + 0x56, 0x31, 0xd7, 0x0a, 0x25, 0xcf, 0x64, 0xdb, 0x84, 0x25, 0xd1, 0x24, 0x67, 0x60, 0xc9, 0xdc, + 0x62, 0x25, 0xac, 0x89, 0xd6, 0xa3, 0xa6, 0xb4, 0x48, 0x89, 0x26, 0xa6, 0x3d, 0xe3, 0xd7, 0xec, + 0xbb, 0xb0, 0x48, 0x24, 0x83, 0xea, 0x15, 0x72, 0xfa, 0x0d, 0xe4, 0xf4, 0xab, 0xea, 0x84, 0x33, + 0x4a, 0x45, 0x66, 0x5f, 0x1f, 0x24, 0xbe, 0xc5, 0x72, 0x18, 0x39, 0xa7, 0x3c, 0x74, 0xc6, 0xbc, + 0xb9, 0x4e, 0x04, 0xa6, 0xbe, 0xc5, 0x4a, 0x9d, 0x4e, 0x30, 0xa5, 0x49, 0x7c, 0x81, 0xbe, 0x90, + 0x76, 0x47, 0x5e, 0xc0, 0xd5, 0x11, 0x55, 0xf3, 0xb6, 0x5c, 0x84, 0x02, 0xa8, 0x64, 0x48, 0x21, + 0x88, 0x93, 0xd2, 0x13, 0x1d, 0x24, 0xde, 0x41, 0x62, 0xa8, 0x91, 0xee, 0xa3, 0x0e, 0x13, 0xc5, + 0x2e, 0x7e, 0x6e, 0x5f, 0x2a, 0x0e, 0xf2, 0x1a, 0xce, 0x2f, 0x08, 0x90, 0xe4, 0x1d, 0x3f, 0xc9, + 0xd0, 0x86, 0x28, 0xf9, 0x47, 0xa0, 0xa9, 0x77, 0xc4, 0x39, 0x2c, 0xcf, 0x1d, 0x5d, 0x4b, 0x66, + 0x02, 0x04, 0x3a, 0x74, 0x47, 0xb8, 0x9a, 0x1d, 0x57, 0x47, 0x21, 0xde, 0x5b, 0x55, 0x40, 0x44, + 0xba, 0x07, 0x95, 0xc9, 0xf4, 0x64, 0xe4, 0x0c, 0x08, 0x25, 0x47, 0xa5, 0x10, 0x08, 0x11, 0x84, + 0x7e, 0x4b, 0x14, 0x45, 0x18, 0x79, 0xc4, 0xa8, 0x48, 0x18, 0xa2, 0x20, 0x6f, 0xe7, 0x3e, 0xb2, + 0x93, 0xaa, 0x89, 0xbf, 0x8d, 0x2d, 0x58, 0x49, 0x36, 0x5a, 0x6e, 0x3c, 0x0f, 0xa1, 0x24, 0x79, + 0x95, 0x3a, 0xf8, 0xa8, 0x6b, 0x47, 0xd1, 0x42, 0x45, 0x8b, 0xd2, 0x8d, 0xdf, 0x5a, 0x80, 0x65, + 0x09, 0xdd, 0x16, 0x43, 0xdb, 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0xc2, 0x04, 0x33, 0x2f, 0x66, 0x82, + 0xd9, 0x39, 0x26, 0x98, 0xd4, 0x7c, 0x89, 0x87, 0x26, 0x35, 0x5f, 0x31, 0x97, 0xa4, 0x8c, 0xe8, + 0xe7, 0xa0, 0x35, 0x09, 0xee, 0xd3, 0x79, 0xeb, 0x1c, 0xcb, 0x2e, 0xa4, 0xb0, 0x6c, 0x9d, 0xe1, + 0x2e, 0xcc, 0x30, 0xdc, 0x37, 0x80, 0x88, 0x46, 0xcd, 0x7e, 0x91, 0xf4, 0x13, 0x84, 0xc9, 0xc3, + 0xd4, 0xb7, 0x61, 0x71, 0x96, 0xc7, 0x11, 0x33, 0xad, 0xa7, 0x70, 0x38, 0x67, 0xcc, 0x71, 0xb7, + 0xd2, 0x90, 0xcb, 0x92, 0xc3, 0x39, 0x63, 0xbe, 0x8f, 0x29, 0x0a, 0xbf, 0x0d, 0x40, 0x75, 0xe3, + 0xa2, 0x01, 0x5c, 0x34, 0x6f, 0x25, 0xe7, 0x42, 0x1f, 0xf5, 0x4d, 0xf1, 0x31, 0xf5, 0x39, 0xae, + 0xa2, 0x32, 0xe6, 0xc4, 0x05, 0xf4, 0x0c, 0xea, 0xde, 0x84, 0xbb, 0x56, 0xcc, 0x6b, 0x2a, 0x58, + 0xd4, 0x9b, 0x2f, 0x28, 0xaa, 0xa3, 0x70, 0xcd, 0x9a, 0xc8, 0x1b, 0x7d, 0xb2, 0x03, 0x1a, 0x78, + 0xae, 0x95, 0x56, 0xfd, 0x12, 0xa5, 0xd5, 0x31, 0x73, 0xf4, 0x6d, 0xfc, 0xbd, 0x0c, 0x54, 0xb4, + 0x66, 0xb3, 0x55, 0x58, 0xda, 0x3e, 0x3c, 0x3c, 0x6a, 0x9b, 0xad, 0x7e, 0xe7, 0x93, 0xb6, 0xb5, + 0xbd, 0x7f, 0xd8, 0x6b, 0x37, 0x6e, 0x09, 0xf0, 0xfe, 0xe1, 0x76, 0x6b, 0xdf, 0xda, 0x3d, 0x34, + 0xb7, 0x15, 0x38, 0xc3, 0xd6, 0x80, 0x99, 0xed, 0x83, 0xc3, 0x7e, 0x3b, 0x01, 0xcf, 0xb2, 0x06, + 0x54, 0xb7, 0xcc, 0x76, 0x6b, 0x7b, 0x4f, 0x42, 0x72, 0x6c, 0x05, 0x1a, 0xbb, 0xc7, 0xdd, 0x9d, + 0x4e, 0xf7, 0xa9, 0xb5, 0xdd, 0xea, 0x6e, 0xb7, 0xf7, 0xdb, 0x3b, 0x8d, 0x3c, 0xab, 0x41, 0xb9, + 0xb5, 0xd5, 0xea, 0xee, 0x1c, 0x76, 0xdb, 0x3b, 0x8d, 0x82, 0xf1, 0x1d, 0x28, 0xc7, 0x1d, 0xad, + 0x40, 0xf1, 0xb8, 0xfb, 0xac, 0x7b, 0xf8, 0x69, 0xb7, 0x71, 0x8b, 0x95, 0xa1, 0x80, 0xf5, 0x37, + 0x32, 0x0c, 0x60, 0x81, 0xea, 0x6c, 0x64, 0x59, 0x09, 0xf2, 0x5b, 0x87, 0xfd, 0xbd, 0x46, 0xce, + 0xf8, 0xcb, 0x0c, 0xac, 0x62, 0x97, 0x87, 0xb3, 0x4c, 0xe0, 0x3e, 0x54, 0x06, 0x9e, 0x37, 0x11, + 0x9a, 0x56, 0x2c, 0x51, 0xe8, 0x20, 0xb1, 0xc0, 0x89, 0x79, 0x9f, 0x7a, 0xfe, 0x80, 0x4b, 0x1e, + 0x00, 0x08, 0xda, 0x15, 0x10, 0x41, 0x83, 0x92, 0x88, 0x09, 0x83, 0x58, 0x40, 0x85, 0x60, 0x84, + 0xb2, 0x06, 0x0b, 0x27, 0x3e, 0xb7, 0x07, 0xe7, 0x72, 0xf5, 0xcb, 0x2f, 0xf6, 0x4e, 0x7c, 0x06, + 0x30, 0x10, 0x34, 0x35, 0xe2, 0x43, 0x5c, 0x02, 0x25, 0x73, 0x51, 0xc2, 0xb7, 0x25, 0x58, 0xec, + 0x46, 0xf6, 0x89, 0xed, 0x0e, 0x3d, 0x97, 0x0f, 0xa5, 0xaa, 0x11, 0x03, 0x8c, 0x23, 0x58, 0x9b, + 0xed, 0x9f, 0xe4, 0x17, 0x1f, 0x68, 0xfc, 0x82, 0x24, 0xff, 0x8d, 0x9b, 0x49, 0x41, 0xe3, 0x1d, + 0xff, 0x20, 0x0f, 0x79, 0x21, 0x09, 0xde, 0x28, 0x34, 0xea, 0xa2, 0x7d, 0x6e, 0xce, 0xfc, 0x83, + 0x47, 0x0d, 0x24, 0x22, 0xd0, 0x79, 0x56, 0x19, 0x21, 0x28, 0x1a, 0x44, 0xc9, 0x3e, 0x1f, 0x5c, + 0xc8, 0x03, 0x2d, 0x4a, 0x36, 0xf9, 0xe0, 0x02, 0x75, 0x2a, 0x3b, 0xa4, 0xbc, 0xb4, 0xde, 0x8b, + 0x81, 0x1d, 0x62, 0x4e, 0x99, 0x84, 0xf9, 0x8a, 0x51, 0x12, 0xe6, 0x6a, 0x42, 0xd1, 0x71, 0x4f, + 0xbc, 0xa9, 0x3b, 0xc4, 0xe5, 0x5d, 0x32, 0xd5, 0x27, 0x5a, 0x9b, 0x90, 0x13, 0x89, 0x8d, 0x88, + 0x56, 0x73, 0x49, 0x00, 0xfa, 0x62, 0x2b, 0x7a, 0x0f, 0xca, 0xc1, 0xb5, 0x3b, 0xd0, 0xd7, 0xf0, + 0x8a, 0x1c, 0x1f, 0xd1, 0xfb, 0xcd, 0xde, 0xb5, 0x3b, 0xc0, 0x15, 0x5b, 0x0a, 0xe4, 0x2f, 0xf6, + 0x3e, 0x94, 0xa2, 0x73, 0x5f, 0xe2, 0xc0, 0xb7, 0xf5, 0x1c, 0xea, 0xb0, 0x97, 0xd4, 0xeb, 0x08, + 0x95, 0x3d, 0x82, 0x05, 0x3c, 0x9c, 0x0d, 0x9a, 0x55, 0xcc, 0xa4, 0xe4, 0x7d, 0xd1, 0x0c, 0x34, + 0xf4, 0xf0, 0x21, 0x1e, 0xd4, 0x9a, 0x12, 0x6d, 0xe3, 0x19, 0xd4, 0x12, 0x65, 0xe9, 0x4a, 0x74, + 0x8d, 0x94, 0xe8, 0x37, 0x75, 0x25, 0x3a, 0xde, 0x09, 0x64, 0x36, 0x5d, 0xa9, 0xfe, 0x65, 0x28, + 0xa9, 0xae, 0x88, 0xf5, 0x27, 0xd7, 0x8e, 0xd5, 0xfb, 0xac, 0xbb, 0xdd, 0xb8, 0xc5, 0x16, 0xa1, + 0xd2, 0xda, 0xc6, 0x25, 0x8d, 0x80, 0x8c, 0x40, 0x39, 0x6a, 0xf5, 0x7a, 0x11, 0x24, 0x6b, 0xec, + 0x42, 0x63, 0xb6, 0xa5, 0x82, 0x26, 0x43, 0x05, 0x93, 0x47, 0xd7, 0x31, 0x40, 0xa8, 0x48, 0x74, + 0x1a, 0x4d, 0x72, 0x38, 0x7d, 0x18, 0xef, 0x43, 0x43, 0xec, 0x6b, 0x62, 0xa8, 0x02, 0xed, 0x08, + 0x78, 0x24, 0x64, 0x3b, 0xfd, 0xf8, 0xba, 0x64, 0x56, 0x08, 0x86, 0x55, 0x19, 0x1f, 0xc0, 0x92, + 0x96, 0x2d, 0x56, 0x69, 0xc5, 0x5e, 0x39, 0xab, 0xd2, 0xa2, 0x02, 0x43, 0x29, 0xc6, 0x3a, 0xac, + 0x8a, 0xcf, 0xf6, 0x05, 0x77, 0xc3, 0xde, 0xf4, 0x84, 0x6c, 0x8e, 0x8e, 0xe7, 0x0a, 0xc5, 0xa6, + 0x1c, 0xa5, 0xdc, 0x4c, 0xe4, 0x9b, 0x52, 0xfb, 0xcd, 0x22, 0x69, 0x6c, 0x68, 0x35, 0x60, 0xc6, + 0x4d, 0xfc, 0x9b, 0xd0, 0x82, 0xcb, 0x11, 0x48, 0x0c, 0xeb, 0x51, 0xbb, 0x6d, 0x5a, 0x87, 0xdd, + 0xfd, 0x4e, 0x57, 0x30, 0x4a, 0x31, 0xac, 0x08, 0xd8, 0xdd, 0x45, 0x48, 0xc6, 0x68, 0x40, 0xfd, + 0x29, 0x0f, 0x3b, 0xee, 0xa9, 0xa7, 0xec, 0x6b, 0x7f, 0x55, 0x80, 0xc5, 0x08, 0x14, 0x6b, 0xd1, + 0x17, 0xdc, 0x0f, 0x1c, 0xcf, 0x45, 0x81, 0xb8, 0x6c, 0xaa, 0x4f, 0xb1, 0xbb, 0x39, 0x43, 0xee, + 0x86, 0x4e, 0x78, 0x6d, 0x25, 0x8e, 0xdc, 0xea, 0x0a, 0x2c, 0x77, 0xd1, 0x15, 0x28, 0xd8, 0x23, + 0xc7, 0x56, 0xa6, 0x5a, 0xfa, 0x10, 0xd0, 0x81, 0x37, 0xf2, 0x7c, 0x94, 0x7d, 0xcb, 0x26, 0x7d, + 0xb0, 0xc7, 0xb0, 0x22, 0x64, 0x70, 0xfd, 0x1c, 0x14, 0xf9, 0x07, 0x9d, 0xfe, 0x31, 0x77, 0x3a, + 0x3e, 0x8a, 0xcf, 0x42, 0x45, 0x8a, 0xd8, 0x3b, 0x45, 0x0e, 0x29, 0x2c, 0x45, 0x19, 0x48, 0x9d, + 0x5b, 0x72, 0xa7, 0xe3, 0x16, 0xa6, 0x44, 0xf8, 0x4f, 0x60, 0x55, 0xe0, 0x47, 0xe2, 0x55, 0x94, + 0x63, 0x11, 0x73, 0x88, 0xc2, 0x3a, 0x32, 0x2d, 0xca, 0x73, 0x07, 0xca, 0xd4, 0x2a, 0x31, 0xe3, + 0x05, 0x12, 0xe3, 0xb1, 0x29, 0xdc, 0x0f, 0xe6, 0xac, 0xaa, 0x0b, 0x24, 0x08, 0xcc, 0x58, 0x55, + 0x35, 0xbb, 0x6c, 0x69, 0xd6, 0x2e, 0xfb, 0x04, 0x56, 0x4f, 0x04, 0x09, 0x9e, 0x73, 0x7b, 0xc8, + 0x7d, 0x2b, 0x26, 0x6c, 0x52, 0x57, 0x96, 0x45, 0xe2, 0x1e, 0xa6, 0x45, 0xeb, 0x40, 0xc8, 0x39, + 0x82, 0x2d, 0xf0, 0xa1, 0x15, 0x7a, 0x16, 0x8a, 0x3f, 0xc8, 0x60, 0x4a, 0x66, 0x8d, 0xc0, 0x7d, + 0x6f, 0x5b, 0x00, 0x93, 0x78, 0x67, 0xbe, 0x3d, 0x39, 0x97, 0x0a, 0x45, 0x84, 0xf7, 0x54, 0x00, + 0xd9, 0x6b, 0x50, 0x14, 0x24, 0xef, 0x72, 0x32, 0x7e, 0x91, 0xc8, 0xae, 0x40, 0xec, 0x4d, 0x58, + 0xc0, 0x3a, 0x82, 0x66, 0x03, 0xe9, 0xbd, 0x1a, 0x33, 0x72, 0xc7, 0x35, 0x65, 0x9a, 0x10, 0x26, + 0xa7, 0xbe, 0x43, 0x5c, 0xa6, 0x6c, 0xe2, 0x6f, 0xf6, 0x3d, 0x8d, 0x65, 0x2d, 0x63, 0x5e, 0x25, + 0x0f, 0xcc, 0x50, 0xda, 0x4d, 0xdc, 0xeb, 0xe7, 0xca, 0x8c, 0xbe, 0x9f, 0x2f, 0x55, 0x1a, 0x55, + 0xe3, 0x5b, 0x50, 0xa0, 0xd1, 0x11, 0x44, 0x88, 0x63, 0x97, 0x91, 0x44, 0x88, 0xd0, 0x26, 0x14, + 0x5d, 0x1e, 0x5e, 0x7a, 0xfe, 0x73, 0x75, 0x28, 0x2d, 0x3f, 0x8d, 0x1f, 0xe1, 0x69, 0x4a, 0x64, + 0x71, 0x27, 0xc5, 0x50, 0x90, 0x07, 0x4d, 0x6f, 0x70, 0x6e, 0xcb, 0x03, 0x9e, 0x12, 0x02, 0x7a, + 0xe7, 0xf6, 0x1c, 0x79, 0x64, 0xe7, 0x8d, 0xee, 0x6f, 0x42, 0x5d, 0xd9, 0xf8, 0x03, 0x6b, 0xc4, + 0x4f, 0x43, 0x49, 0xee, 0x55, 0x69, 0xe0, 0x0f, 0xf6, 0xf9, 0x69, 0x68, 0x1c, 0xc0, 0x92, 0x24, + 0xc8, 0xc3, 0x09, 0x57, 0x55, 0x7f, 0x3b, 0x4d, 0x9e, 0xae, 0x3c, 0x59, 0x4e, 0x6e, 0xb4, 0xe4, + 0xbb, 0x90, 0x10, 0xb2, 0x8d, 0x8f, 0x81, 0xe9, 0xdb, 0xb0, 0x2c, 0x4f, 0x4a, 0xb5, 0xea, 0x2c, + 0x5f, 0x99, 0xc4, 0x22, 0xd9, 0xd9, 0x19, 0x8a, 0xd1, 0x09, 0xa6, 0x83, 0x81, 0xf2, 0xbd, 0x28, + 0x99, 0xea, 0xd3, 0xf8, 0xb3, 0x0c, 0x2c, 0x63, 0x61, 0x4a, 0x1f, 0x90, 0x4c, 0xf6, 0xa7, 0x6e, + 0xa4, 0x98, 0x1f, 0x5d, 0xf6, 0xa1, 0x8f, 0x2f, 0x7f, 0x7a, 0x9a, 0x9f, 0x3b, 0x3d, 0x7d, 0x07, + 0x1a, 0x43, 0x3e, 0x72, 0xd0, 0x0d, 0x47, 0x89, 0x12, 0xa4, 0x01, 0x2c, 0x2a, 0xb8, 0xd4, 0x06, + 0x8d, 0x7f, 0x92, 0x81, 0x25, 0x92, 0x54, 0x50, 0xaf, 0x96, 0x03, 0xf5, 0x91, 0x52, 0x24, 0x25, + 0xab, 0x92, 0x7d, 0x8a, 0x77, 0x70, 0x84, 0x12, 0xf2, 0xde, 0x2d, 0xa9, 0x60, 0x4a, 0x28, 0xfb, + 0x10, 0x75, 0x18, 0xd7, 0x42, 0x60, 0x8a, 0x5b, 0x4f, 0x72, 0x52, 0xf6, 0x6e, 0xa1, 0x82, 0xe3, + 0x22, 0x68, 0xab, 0x24, 0x34, 0x5b, 0x01, 0x36, 0x76, 0xa1, 0x96, 0xa8, 0x26, 0x71, 0xc4, 0x5b, + 0xa5, 0x23, 0xde, 0x39, 0x33, 0x4a, 0x76, 0xde, 0x8c, 0x72, 0x0d, 0xcb, 0x26, 0xb7, 0x87, 0xd7, + 0xbb, 0x9e, 0x7f, 0x14, 0x9c, 0x84, 0xbb, 0x24, 0xfe, 0x09, 0xfe, 0x1e, 0xd9, 0x06, 0x13, 0xe7, + 0xa8, 0xca, 0x44, 0xa4, 0xd4, 0xe5, 0xaf, 0x42, 0x3d, 0x36, 0x22, 0x6a, 0x67, 0x71, 0xb5, 0xc8, + 0x8e, 0x88, 0x47, 0x72, 0x42, 0xd5, 0x0c, 0x4e, 0x42, 0x79, 0x1a, 0x87, 0xbf, 0x8d, 0xbf, 0x93, + 0x07, 0x26, 0xa8, 0x79, 0x86, 0x60, 0x66, 0xcc, 0x9f, 0xd9, 0x39, 0xf3, 0xe7, 0x63, 0x60, 0x1a, + 0x82, 0xb2, 0xca, 0xe6, 0x22, 0xab, 0x6c, 0x23, 0xc6, 0x95, 0x46, 0xd9, 0xc7, 0xb0, 0x22, 0x65, + 0xe9, 0x64, 0x53, 0x89, 0x34, 0x18, 0x09, 0xd5, 0x89, 0xf6, 0x2a, 0xd3, 0xa7, 0x50, 0xff, 0xe9, + 0xb4, 0x0d, 0x4d, 0x9f, 0x4a, 0xf1, 0xd7, 0x08, 0x70, 0xe1, 0xa5, 0x04, 0x58, 0x9c, 0x23, 0x40, + 0xed, 0xf0, 0xa7, 0x94, 0x3c, 0xfc, 0x31, 0xa0, 0xa6, 0x0c, 0x9c, 0xe4, 0xd7, 0x41, 0x82, 0x63, + 0x45, 0x5a, 0x39, 0xd1, 0xb7, 0xe3, 0x01, 0x34, 0xd4, 0x09, 0x4d, 0x74, 0xbc, 0x44, 0x3e, 0x0b, + 0xf2, 0x80, 0x6f, 0x5b, 0x1d, 0x32, 0x25, 0x0e, 0xf3, 0x2b, 0x33, 0x87, 0xf9, 0xef, 0xc2, 0x52, + 0x20, 0xe8, 0xd7, 0x9a, 0xba, 0xd2, 0xc1, 0x88, 0x0f, 0x51, 0x6b, 0x2b, 0x99, 0x0d, 0x4c, 0x38, + 0x8e, 0xe1, 0xf3, 0x47, 0x27, 0xb5, 0x94, 0xa3, 0x93, 0xf7, 0x63, 0x5b, 0x60, 0x70, 0xee, 0x8c, + 0x51, 0x66, 0x88, 0x9d, 0x71, 0xe4, 0x00, 0xf7, 0xce, 0x9d, 0xb1, 0xa9, 0x0c, 0xcf, 0xe2, 0xc3, + 0xf8, 0xbf, 0x19, 0x68, 0x08, 0x3a, 0x48, 0x2c, 0xb1, 0xef, 0x00, 0x32, 0x83, 0x57, 0x5c, 0x61, + 0x15, 0x81, 0xab, 0x16, 0xd8, 0xb7, 0x00, 0x57, 0x8c, 0x25, 0x54, 0x54, 0xb9, 0xbe, 0x9a, 0xc9, + 0xf5, 0x15, 0xf3, 0xd0, 0xbd, 0x5b, 0xa4, 0x7b, 0x08, 0x08, 0xfb, 0x0e, 0x94, 0x05, 0x61, 0x22, + 0x95, 0x48, 0x1f, 0x30, 0x25, 0x79, 0xa5, 0xac, 0x11, 0x91, 0x75, 0x22, 0x3f, 0xd3, 0xcc, 0xb7, + 0xf9, 0x14, 0xf3, 0xad, 0xb6, 0x80, 0xf7, 0x00, 0x9e, 0xf1, 0xeb, 0x7d, 0x6f, 0x80, 0x7a, 0xe5, + 0x5d, 0x00, 0x41, 0xcb, 0xa7, 0xf6, 0xd8, 0x91, 0x67, 0x42, 0x05, 0xb3, 0xfc, 0x9c, 0x5f, 0xef, + 0x22, 0x40, 0x4c, 0xa4, 0x48, 0x8e, 0x57, 0x71, 0xc1, 0x2c, 0x3d, 0xe7, 0xd7, 0xb4, 0x84, 0x2d, + 0xa8, 0x3d, 0xe3, 0xd7, 0x3b, 0x9c, 0x84, 0x4c, 0xcf, 0x17, 0x44, 0xe4, 0xdb, 0x97, 0x42, 0xaa, + 0x4c, 0x98, 0x5e, 0x2b, 0xbe, 0x7d, 0xf9, 0x8c, 0x5f, 0x2b, 0x33, 0x70, 0x51, 0xa4, 0x8f, 0xbc, + 0x81, 0xdc, 0x37, 0x95, 0x13, 0x49, 0xdc, 0x28, 0x73, 0xe1, 0x39, 0xfe, 0x36, 0xfe, 0x3a, 0x03, + 0x35, 0xd1, 0x7e, 0x64, 0xcb, 0x62, 0xca, 0x94, 0x2f, 0x52, 0x26, 0xf6, 0x45, 0x7a, 0x22, 0xb9, + 0x1a, 0xf1, 0xf8, 0xec, 0xcd, 0x3c, 0x1e, 0xe7, 0x86, 0x18, 0xfc, 0x7b, 0x50, 0xa6, 0x65, 0x29, + 0xd6, 0x79, 0x2e, 0x31, 0xc1, 0x89, 0x0e, 0x99, 0x25, 0x44, 0x7b, 0x46, 0xae, 0x0f, 0xda, 0xf9, + 0x22, 0x0d, 0x71, 0xd9, 0x8f, 0x4e, 0x15, 0x53, 0xa6, 0xa1, 0x70, 0x83, 0xeb, 0x83, 0x7e, 0x78, + 0xb7, 0x30, 0x77, 0x78, 0x77, 0x08, 0x25, 0x31, 0xd5, 0xd8, 0xd9, 0x94, 0x42, 0x33, 0x69, 0x85, + 0x0a, 0x49, 0xc0, 0x16, 0x9b, 0x82, 0x60, 0x74, 0x59, 0x29, 0x09, 0xd8, 0x01, 0x3f, 0x42, 0x66, + 0x97, 0x81, 0x8a, 0xb6, 0x02, 0xf0, 0xfc, 0x33, 0x1a, 0x2f, 0x5a, 0x2e, 0x49, 0x12, 0x4f, 0x0c, + 0xf8, 0xde, 0x2d, 0xb3, 0x36, 0x48, 0xcc, 0xc0, 0xa6, 0xa4, 0x55, 0xcc, 0x99, 0x4d, 0xb8, 0x4d, + 0xa9, 0x86, 0x2b, 0x02, 0x15, 0xbf, 0xb7, 0x16, 0x20, 0x2f, 0x50, 0x8d, 0x8f, 0x60, 0x49, 0x6b, + 0x06, 0xa9, 0xf9, 0xaf, 0xda, 0x43, 0xe3, 0xd7, 0xa2, 0xcc, 0xa2, 0x0e, 0xb2, 0x50, 0x29, 0x37, + 0x12, 0x3e, 0xa4, 0x8e, 0x4b, 0x77, 0x15, 0x02, 0x09, 0xb4, 0x57, 0x76, 0x6d, 0xf8, 0x0d, 0x58, + 0xd6, 0x4a, 0xdf, 0x75, 0x5c, 0x7b, 0xe4, 0xfc, 0x08, 0x37, 0xfc, 0xc0, 0x39, 0x73, 0x67, 0xca, + 0x27, 0xd0, 0x97, 0x2a, 0xff, 0x9f, 0x66, 0x61, 0x45, 0x56, 0x80, 0x8e, 0x81, 0x8e, 0x90, 0xe2, + 0x0e, 0x82, 0x33, 0xf6, 0x1d, 0xa8, 0x89, 0xb1, 0xb1, 0x7c, 0x7e, 0xe6, 0x04, 0x21, 0x57, 0x96, + 0xb1, 0x14, 0xc6, 0x25, 0x36, 0x73, 0x81, 0x6a, 0x4a, 0x4c, 0xf6, 0x11, 0x54, 0x30, 0x2b, 0x1d, + 0xa3, 0xc8, 0x89, 0x68, 0xce, 0x67, 0xa4, 0x81, 0xde, 0xbb, 0x65, 0x42, 0x10, 0x0f, 0xfb, 0x47, + 0x50, 0xc1, 0x39, 0xbc, 0xc0, 0x81, 0x9c, 0x61, 0x55, 0x73, 0x03, 0x2d, 0x32, 0x4f, 0xe2, 0x61, + 0x6f, 0x41, 0x8d, 0x98, 0x95, 0x1c, 0x27, 0xe9, 0x70, 0xb4, 0x31, 0x9f, 0x5d, 0x8d, 0xa4, 0x68, + 0xfc, 0x44, 0xfb, 0xde, 0x2a, 0x43, 0x31, 0xf4, 0x9d, 0xb3, 0x33, 0xee, 0x1b, 0x6b, 0xd1, 0xd0, + 0x08, 0x2e, 0xcc, 0x7b, 0x21, 0x9f, 0x08, 0xd9, 0xdc, 0xf8, 0x4f, 0x19, 0xa8, 0x48, 0xbe, 0xfa, + 0x53, 0x9b, 0xe3, 0x36, 0x34, 0xcf, 0x5a, 0x3a, 0xb1, 0x89, 0x1d, 0x69, 0xdf, 0x86, 0xc5, 0xb1, + 0x90, 0xd3, 0x85, 0x1e, 0x99, 0xb0, 0xc5, 0xd5, 0x15, 0x58, 0x8a, 0xc9, 0x9b, 0xb0, 0x8c, 0x52, + 0x73, 0x60, 0x85, 0xce, 0xc8, 0x52, 0x89, 0xd2, 0x8b, 0x75, 0x89, 0x92, 0xfa, 0xce, 0xe8, 0x40, + 0x26, 0x08, 0xe1, 0x31, 0x08, 0xed, 0x33, 0x2e, 0xd7, 0x36, 0x7d, 0x18, 0x4d, 0x58, 0x9b, 0x51, + 0x21, 0x95, 0xfa, 0xfb, 0x07, 0x4b, 0xb0, 0x3e, 0x97, 0x24, 0xd5, 0xe0, 0xc8, 0x06, 0x35, 0x72, + 0xc6, 0x27, 0x5e, 0x74, 0x42, 0x9b, 0xd1, 0x6c, 0x50, 0xfb, 0x22, 0x45, 0x9d, 0xd0, 0x72, 0x58, + 0x55, 0x04, 0x89, 0x47, 0xac, 0x91, 0x96, 0x99, 0x45, 0x1d, 0xe8, 0xbd, 0xe4, 0x26, 0x36, 0x5b, + 0x9d, 0x82, 0xeb, 0xa2, 0xd1, 0xf2, 0x64, 0x0e, 0x16, 0xb0, 0xdf, 0x84, 0x66, 0x44, 0xf7, 0x52, + 0x6c, 0xd7, 0x54, 0x66, 0x51, 0xd3, 0xd7, 0x5e, 0x52, 0x53, 0xe2, 0xec, 0x0e, 0x65, 0xa7, 0x35, + 0xb5, 0x64, 0xa8, 0xc0, 0xa8, 0xae, 0x0b, 0x78, 0x5d, 0xd5, 0x85, 0x62, 0xf8, 0x7c, 0x8d, 0xf9, + 0x57, 0xea, 0x1b, 0x9e, 0x4b, 0x26, 0xaa, 0x35, 0xef, 0xc8, 0x82, 0xa3, 0x24, 0xbd, 0xde, 0x73, + 0x58, 0xbb, 0xb4, 0x9d, 0x50, 0xf5, 0x51, 0xd3, 0xd8, 0x0b, 0x58, 0xdf, 0x93, 0x97, 0xd4, 0xf7, + 0x29, 0x65, 0x4e, 0x28, 0x26, 0x2b, 0x97, 0xf3, 0xc0, 0x60, 0xe3, 0x4f, 0xb3, 0x50, 0x4f, 0x96, + 0x22, 0x18, 0x8b, 0xdc, 0x6c, 0x94, 0xbc, 0x29, 0x85, 0x60, 0x69, 0x3d, 0xe8, 0x92, 0x9c, 0x39, + 0x6f, 0xd7, 0xc8, 0xa6, 0xd8, 0x35, 0x74, 0x73, 0x42, 0xee, 0x65, 0xf6, 0xdb, 0xfc, 0x2b, 0xd9, + 0x6f, 0x0b, 0x69, 0xf6, 0xdb, 0x9b, 0x8d, 0x7e, 0x0b, 0x3f, 0x95, 0xd1, 0xaf, 0xf8, 0x02, 0xa3, + 0x5f, 0xc2, 0x54, 0x59, 0x9a, 0x31, 0x55, 0x6e, 0xfc, 0x75, 0x06, 0xd8, 0x3c, 0x2d, 0xb3, 0xa7, + 0x64, 0xe0, 0x71, 0xf9, 0x48, 0xf2, 0xd9, 0xaf, 0xbf, 0xda, 0x7a, 0x50, 0xd3, 0xa7, 0x72, 0xb3, + 0x47, 0xb0, 0xac, 0x7b, 0xc6, 0xeb, 0x3a, 0x76, 0xcd, 0x64, 0x7a, 0x52, 0x7c, 0x12, 0xa3, 0x99, + 0xb6, 0xf3, 0x2f, 0x35, 0x6d, 0x17, 0x5e, 0x6a, 0xda, 0x5e, 0x48, 0x9a, 0xb6, 0x37, 0xfe, 0x4b, + 0x06, 0x96, 0x53, 0x48, 0xee, 0xe7, 0xd7, 0x67, 0x41, 0x29, 0x09, 0x26, 0x94, 0x95, 0x94, 0xa2, + 0xf3, 0x9f, 0x7d, 0xa8, 0xc4, 0xd6, 0x52, 0x15, 0x39, 0xf2, 0xf0, 0x65, 0xbc, 0x20, 0xce, 0x61, + 0xea, 0xd9, 0x37, 0x7e, 0x3f, 0x0b, 0x15, 0x2d, 0x51, 0x8c, 0x22, 0x11, 0x98, 0xe6, 0x51, 0x44, + 0x72, 0x1c, 0x9e, 0x10, 0xdc, 0x03, 0x69, 0x82, 0xa0, 0x74, 0x5a, 0x0a, 0x52, 0x68, 0x43, 0x84, + 0x4d, 0x58, 0x56, 0xc6, 0x37, 0x1e, 0x3b, 0x0e, 0xca, 0x9d, 0x61, 0x49, 0x9a, 0xe0, 0x78, 0xe4, + 0x87, 0xc8, 0x1e, 0x29, 0xe5, 0x2d, 0x9e, 0x3b, 0x24, 0x4c, 0x3a, 0xdf, 0x5f, 0x22, 0x72, 0x56, + 0x93, 0x28, 0xa8, 0xf2, 0x3d, 0x58, 0x55, 0xc4, 0x9c, 0xcc, 0x41, 0x47, 0xfe, 0x4c, 0x92, 0xb2, + 0x9e, 0xe5, 0x7b, 0x70, 0x77, 0xa6, 0x4d, 0x33, 0x59, 0xc9, 0xc3, 0xf5, 0x76, 0xa2, 0x75, 0x7a, + 0x09, 0x1b, 0x3f, 0x86, 0x5a, 0x82, 0xad, 0xfd, 0xfc, 0xa6, 0x7c, 0xf6, 0x54, 0x86, 0x46, 0x54, + 0x3f, 0x95, 0xd9, 0xf8, 0x3f, 0x39, 0x60, 0xf3, 0x9c, 0xf5, 0x17, 0xd9, 0x84, 0x79, 0xc2, 0xcc, + 0xa5, 0x10, 0xe6, 0xff, 0xb7, 0xdd, 0xfe, 0x5d, 0x58, 0x92, 0x11, 0x54, 0x9a, 0x05, 0x95, 0x16, + 0x67, 0x23, 0x4a, 0x50, 0xad, 0xf8, 0xd6, 0xac, 0x27, 0x47, 0x29, 0x11, 0x34, 0xa2, 0x89, 0x3b, + 0x33, 0x0e, 0x1d, 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, 0x47, 0xad, 0xbc, 0xfe, 0xe4, 0x97, + 0xbe, 0xf4, 0x66, 0xb7, 0xd9, 0xc2, 0xfc, 0x28, 0x63, 0x99, 0xb2, 0x30, 0xe3, 0x3d, 0xa8, 0x68, + 0x60, 0xb4, 0x2a, 0x76, 0x0e, 0xb6, 0x0e, 0x1b, 0xb7, 0x58, 0x0d, 0xca, 0x66, 0x7b, 0xfb, 0xf0, + 0x93, 0xb6, 0xd9, 0xde, 0x69, 0x64, 0x58, 0x09, 0xf2, 0xfb, 0x87, 0xbd, 0x7e, 0x23, 0x6b, 0x6c, + 0x40, 0x53, 0x96, 0x38, 0x6f, 0x61, 0xf8, 0x9d, 0x7c, 0x74, 0xb8, 0x87, 0x89, 0x52, 0xa1, 0xfe, + 0x06, 0x54, 0x75, 0x61, 0x44, 0x52, 0xc4, 0x8c, 0x11, 0x5f, 0xa8, 0xd2, 0x9e, 0xc6, 0xab, 0xb7, + 0x81, 0x4c, 0xb3, 0xc3, 0x28, 0x5b, 0x36, 0x21, 0x65, 0xa6, 0xd8, 0xf2, 0x50, 0x55, 0x49, 0x90, + 0xe1, 0xdf, 0x80, 0x7a, 0xf2, 0xb8, 0x5d, 0x72, 0xa4, 0x34, 0xf5, 0x50, 0xe4, 0x4e, 0x9c, 0xbf, + 0xb3, 0xef, 0x41, 0x63, 0xf6, 0xb8, 0x5e, 0x8a, 0xba, 0x37, 0xe4, 0x5f, 0x74, 0x92, 0x27, 0xf8, + 0x6c, 0x0f, 0x56, 0xd2, 0xc4, 0x31, 0xa4, 0x8f, 0x9b, 0x8f, 0x14, 0xd8, 0xbc, 0xc8, 0xc5, 0xbe, + 0x2d, 0xad, 0x32, 0x85, 0x34, 0xdb, 0xb6, 0x36, 0xd8, 0x9b, 0xf4, 0x4f, 0xb3, 0xcf, 0x5c, 0x00, + 0xc4, 0x30, 0xd6, 0x80, 0xea, 0xe1, 0x51, 0xbb, 0x6b, 0x6d, 0xef, 0xb5, 0xba, 0xdd, 0xf6, 0x7e, + 0xe3, 0x16, 0x63, 0x50, 0x47, 0xa3, 0xf4, 0x4e, 0x04, 0xcb, 0x08, 0x98, 0xb4, 0x8e, 0x29, 0x58, + 0x96, 0xad, 0x40, 0xa3, 0xd3, 0x9d, 0x81, 0xe6, 0x58, 0x13, 0x56, 0x8e, 0xda, 0x64, 0xc7, 0x4e, + 0x94, 0x9b, 0x17, 0x22, 0xbe, 0xec, 0xae, 0x10, 0xf1, 0x29, 0x12, 0x50, 0xae, 0x03, 0x25, 0xf9, + 0xfe, 0x6e, 0x06, 0x56, 0x67, 0x12, 0xe2, 0xf8, 0x0e, 0x92, 0x7b, 0x93, 0x12, 0x6f, 0x15, 0x81, + 0x6a, 0x35, 0xbd, 0x0b, 0x4b, 0xd1, 0x31, 0xd1, 0xcc, 0xae, 0xd4, 0x88, 0x12, 0x14, 0xf2, 0x23, + 0x58, 0xd6, 0x4e, 0x9b, 0x66, 0x78, 0x05, 0xd3, 0x92, 0x64, 0x06, 0x63, 0x3d, 0xf2, 0xa3, 0x9f, + 0x69, 0xf5, 0x90, 0xc2, 0x0b, 0xf5, 0x84, 0xd8, 0x68, 0x95, 0x6c, 0xaf, 0xfa, 0x64, 0x8f, 0x67, + 0x08, 0x21, 0xd9, 0x5a, 0x7d, 0xc2, 0x55, 0xf5, 0x7f, 0xb8, 0x00, 0xec, 0xe3, 0x29, 0xf7, 0xaf, + 0x31, 0x7e, 0x23, 0x78, 0x99, 0x43, 0xa3, 0x3a, 0x17, 0xc9, 0xbe, 0x52, 0x8c, 0x56, 0x5a, 0x8c, + 0x54, 0xfe, 0xe5, 0x31, 0x52, 0x85, 0x97, 0xc5, 0x48, 0x7d, 0x05, 0x6a, 0xce, 0x99, 0xeb, 0x09, + 0x56, 0x28, 0xe4, 0xd6, 0xa0, 0xb9, 0x70, 0x3f, 0xf7, 0xa0, 0x6a, 0x56, 0x25, 0x50, 0x48, 0xad, + 0x01, 0xfb, 0x28, 0x46, 0xe2, 0xc3, 0x33, 0x8c, 0xe7, 0xd3, 0x99, 0x60, 0x7b, 0x78, 0xc6, 0xe5, + 0x31, 0x10, 0xea, 0x05, 0x2a, 0xb3, 0x80, 0x07, 0xec, 0x4d, 0xa8, 0x07, 0xde, 0x54, 0xa8, 0x01, + 0x6a, 0x18, 0xc8, 0xac, 0x55, 0x25, 0xe8, 0x91, 0xb2, 0x61, 0x2e, 0x4f, 0x03, 0x6e, 0x8d, 0x9d, + 0x20, 0x10, 0xe2, 0xd9, 0xc0, 0x73, 0x43, 0xdf, 0x1b, 0x49, 0x4b, 0xd5, 0xd2, 0x34, 0xe0, 0x07, + 0x94, 0xb2, 0x4d, 0x09, 0xec, 0x9b, 0x71, 0x93, 0x26, 0xb6, 0xe3, 0x07, 0x4d, 0xc0, 0x26, 0xa9, + 0x9e, 0xa2, 0xb4, 0x6d, 0x3b, 0x7e, 0xd4, 0x16, 0xf1, 0x11, 0xcc, 0xc4, 0x6e, 0x55, 0x66, 0x63, + 0xb7, 0x7e, 0x98, 0x1e, 0xbb, 0x55, 0xc3, 0xa2, 0x1f, 0xcb, 0xa2, 0xe7, 0xa7, 0xf8, 0x4b, 0x85, + 0x70, 0xcd, 0x87, 0xa4, 0xd5, 0xbf, 0x4c, 0x48, 0xda, 0x62, 0x5a, 0x48, 0xda, 0x7b, 0x50, 0xc1, + 0x60, 0x21, 0xeb, 0xdc, 0x11, 0x32, 0x1c, 0x59, 0xde, 0x1a, 0x7a, 0x34, 0xd1, 0x9e, 0xe3, 0x86, + 0x26, 0xf8, 0xea, 0x67, 0x30, 0x1f, 0x1d, 0xb6, 0xf4, 0x0b, 0x8c, 0x0e, 0x93, 0x41, 0x4d, 0x9b, + 0x50, 0x52, 0xf3, 0xc4, 0x18, 0xe4, 0x4f, 0x7d, 0x6f, 0xac, 0x2c, 0x12, 0xe2, 0x37, 0xab, 0x43, + 0x36, 0xf4, 0x64, 0xe6, 0x6c, 0xe8, 0x19, 0xbf, 0x0e, 0x15, 0x8d, 0xd4, 0xd8, 0x1b, 0x74, 0x8a, + 0x28, 0x34, 0x29, 0x29, 0x5b, 0xd2, 0x28, 0x96, 0x25, 0xb4, 0x33, 0x14, 0xfc, 0x66, 0xe8, 0xf8, + 0x1c, 0xe3, 0x38, 0x2d, 0x9f, 0x5f, 0x70, 0x3f, 0x50, 0x16, 0xa2, 0x46, 0x94, 0x60, 0x12, 0xdc, + 0xf8, 0x0d, 0x58, 0x4e, 0xcc, 0xad, 0x64, 0x11, 0x6f, 0xc2, 0x02, 0x8e, 0x9b, 0xb2, 0xe0, 0x27, + 0xa3, 0xb4, 0x64, 0x1a, 0x06, 0xe8, 0x93, 0x71, 0xcb, 0x9a, 0xf8, 0xde, 0x09, 0x56, 0x92, 0x31, + 0x2b, 0x12, 0x76, 0xe4, 0x7b, 0x27, 0xc6, 0x5f, 0xe4, 0x20, 0xb7, 0xe7, 0x4d, 0x74, 0xa7, 0xb5, + 0xcc, 0x9c, 0xd3, 0x9a, 0x54, 0x0f, 0xad, 0x48, 0xfd, 0x93, 0x32, 0x3b, 0x9a, 0x75, 0x94, 0x0a, + 0xf8, 0x00, 0xea, 0x82, 0x4f, 0x84, 0x9e, 0xd0, 0xaf, 0x2f, 0x6d, 0x9f, 0x04, 0xe2, 0x1c, 0x2d, + 0x3e, 0x7b, 0x1c, 0xf6, 0xbd, 0x5d, 0x82, 0xb3, 0x15, 0xc8, 0x45, 0xea, 0x0b, 0x26, 0x8b, 0x4f, + 0xb6, 0x06, 0x0b, 0xe8, 0xbd, 0x7c, 0x2d, 0x4d, 0xd4, 0xf2, 0x8b, 0x7d, 0x1d, 0x96, 0x93, 0xe5, + 0x12, 0x2b, 0x92, 0xb2, 0x91, 0x5e, 0x30, 0xf2, 0xa4, 0xdb, 0x20, 0xf8, 0x08, 0xe1, 0x48, 0x4f, + 0x97, 0x53, 0xce, 0x31, 0x49, 0x63, 0x7a, 0xa5, 0x04, 0xd3, 0xbb, 0x07, 0x95, 0x70, 0x74, 0x61, + 0x4d, 0xec, 0xeb, 0x91, 0x67, 0x0f, 0xe5, 0xfa, 0x86, 0x70, 0x74, 0x71, 0x44, 0x10, 0xf6, 0x08, + 0x60, 0x3c, 0x99, 0xc8, 0xb5, 0x87, 0xa6, 0x8a, 0x98, 0x94, 0x0f, 0x8e, 0x8e, 0x88, 0xe4, 0xcc, + 0xf2, 0x78, 0x32, 0xa1, 0x9f, 0x6c, 0x07, 0xea, 0xa9, 0xb1, 0x96, 0x77, 0x95, 0xb3, 0xad, 0x37, + 0xd9, 0x4c, 0x59, 0x9c, 0xb5, 0x81, 0x0e, 0xdb, 0xf8, 0x1e, 0xb0, 0x9f, 0x31, 0xe2, 0xb1, 0x0f, + 0xe5, 0xa8, 0x7d, 0x7a, 0xc0, 0x20, 0xba, 0xcf, 0x57, 0x12, 0x01, 0x83, 0xad, 0xe1, 0xd0, 0x17, + 0x7c, 0x91, 0x36, 0xcc, 0x88, 0xe5, 0x83, 0xb6, 0x63, 0xb6, 0x88, 0xef, 0x1b, 0xff, 0x3d, 0x03, + 0x05, 0x8a, 0x5e, 0x7c, 0x0b, 0x16, 0x09, 0x3f, 0x72, 0x00, 0x94, 0x86, 0x6d, 0xda, 0x77, 0xfb, + 0xd2, 0xf7, 0x4f, 0x2c, 0x0b, 0x2d, 0xf2, 0x3a, 0x1b, 0xcd, 0xbc, 0x16, 0x7d, 0x7d, 0x0f, 0xca, + 0x51, 0xd5, 0x1a, 0xe9, 0x94, 0x54, 0xcd, 0xec, 0x75, 0xc8, 0x9f, 0x7b, 0x13, 0x75, 0x4e, 0x03, + 0xf1, 0x48, 0x9a, 0x08, 0x8f, 0xdb, 0x22, 0xea, 0xa0, 0xc6, 0xcb, 0xf3, 0x85, 0xa8, 0x12, 0x24, + 0x83, 0xf9, 0x3e, 0x2e, 0xa4, 0xf4, 0xf1, 0x18, 0x16, 0x05, 0x1f, 0xd0, 0x1c, 0x4c, 0x6e, 0xde, + 0x34, 0xdf, 0x11, 0x12, 0xde, 0x60, 0x34, 0x1d, 0x72, 0xfd, 0xa4, 0x0c, 0xbd, 0xd1, 0x24, 0x5c, + 0x49, 0xd6, 0xc6, 0x1f, 0x66, 0x88, 0xbf, 0x88, 0x72, 0xd9, 0x03, 0xc8, 0x8b, 0xfd, 0x6d, 0xe6, + 0xdc, 0x3c, 0x8a, 0x63, 0x10, 0x78, 0x26, 0x62, 0xe0, 0x75, 0x05, 0xd3, 0x71, 0xb2, 0xf4, 0x9a, + 0x59, 0x71, 0xa7, 0xe3, 0xe8, 0xa0, 0xe9, 0xab, 0xaa, 0x5b, 0x33, 0x87, 0x34, 0xd4, 0xfb, 0x68, + 0x99, 0x6e, 0x6a, 0x6e, 0x6d, 0xf9, 0xc4, 0x8e, 0xa9, 0xa4, 0xc0, 0xe1, 0x19, 0xd7, 0xdc, 0xd9, + 0xfe, 0x38, 0x0b, 0xb5, 0x44, 0x8b, 0xd0, 0xaf, 0x4f, 0x6c, 0x00, 0x64, 0x06, 0x92, 0xf3, 0x0d, + 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9c, 0xb2, 0x89, 0x71, 0x8a, 0x5c, 0x69, 0x72, 0xba, 0x2b, 0xcd, + 0x63, 0x28, 0xc7, 0x11, 0xf7, 0xc9, 0x26, 0x89, 0xfa, 0x54, 0x34, 0x47, 0x8c, 0x14, 0x3b, 0xdf, + 0x14, 0x74, 0xe7, 0x9b, 0xef, 0x6a, 0xbe, 0x1a, 0x0b, 0x58, 0x8c, 0x91, 0x36, 0xa2, 0xbf, 0x10, + 0x4f, 0x0d, 0xe3, 0x23, 0xa8, 0x68, 0x8d, 0xd7, 0x7d, 0x32, 0x32, 0x09, 0x9f, 0x8c, 0x28, 0xee, + 0x2a, 0x1b, 0xc7, 0x5d, 0x19, 0xbf, 0x95, 0x85, 0x9a, 0x58, 0x5f, 0x8e, 0x7b, 0x76, 0xe4, 0x8d, + 0x9c, 0x01, 0x9a, 0x85, 0xa2, 0x15, 0x26, 0x05, 0x2d, 0xb5, 0xce, 0xe4, 0x12, 0x23, 0x39, 0x4b, + 0x0f, 0x2f, 0x25, 0x26, 0x1d, 0x85, 0x97, 0x1a, 0x50, 0x13, 0x8c, 0x11, 0x0d, 0x3c, 0xf1, 0x7d, + 0x00, 0x66, 0xe5, 0x94, 0xf3, 0x2d, 0x3b, 0x20, 0x0e, 0xf9, 0x75, 0x58, 0x16, 0x38, 0x18, 0x59, + 0x37, 0x76, 0x46, 0x23, 0x87, 0x30, 0xe9, 0xa0, 0xa9, 0x71, 0xca, 0xb9, 0x69, 0x87, 0xfc, 0x40, + 0x24, 0xc8, 0xeb, 0x03, 0x4a, 0x43, 0x27, 0xb0, 0x4f, 0x62, 0xef, 0xcb, 0xe8, 0x1b, 0xed, 0xc0, + 0xf6, 0x95, 0x66, 0x07, 0xa6, 0x03, 0x88, 0xca, 0xd8, 0xbe, 0x8a, 0xec, 0xc0, 0x33, 0x94, 0x54, + 0x9c, 0xa5, 0x24, 0xe3, 0x3f, 0x64, 0xa1, 0xa2, 0x91, 0xe5, 0xab, 0xec, 0xae, 0x77, 0xe7, 0xcc, + 0x78, 0x65, 0xdd, 0x62, 0xf7, 0x95, 0x64, 0x95, 0xe8, 0xa9, 0x42, 0x17, 0x15, 0x68, 0x04, 0x7c, + 0x07, 0xca, 0x62, 0xd5, 0xbd, 0x87, 0x07, 0xa6, 0xf2, 0x9a, 0x0d, 0x04, 0x1c, 0x4d, 0x4f, 0x54, + 0xe2, 0x13, 0x4c, 0x2c, 0xc4, 0x89, 0x4f, 0x44, 0xe2, 0x8b, 0x5c, 0xae, 0xbf, 0x05, 0x55, 0x59, + 0x2a, 0xce, 0x29, 0x76, 0x37, 0x5e, 0xf5, 0x89, 0xf9, 0x36, 0x2b, 0x54, 0x1d, 0x4d, 0xbe, 0xcc, + 0xf8, 0x44, 0x65, 0x2c, 0xbd, 0x2c, 0xe3, 0x13, 0xfa, 0x30, 0x76, 0x23, 0x2f, 0x76, 0xf4, 0x92, + 0x52, 0x7c, 0xec, 0x11, 0x2c, 0x2b, 0x76, 0x35, 0x75, 0x6d, 0xd7, 0xf5, 0xa6, 0xee, 0x80, 0xab, + 0x80, 0x2c, 0x26, 0x93, 0x8e, 0xe3, 0x14, 0x63, 0x18, 0x45, 0xec, 0x92, 0xb7, 0xd5, 0x43, 0x28, + 0x90, 0x5c, 0x4e, 0xc2, 0x47, 0x3a, 0xe3, 0x22, 0x14, 0xf6, 0x00, 0x0a, 0x24, 0x9e, 0x67, 0x6f, + 0x64, 0x36, 0x84, 0x60, 0xb4, 0x80, 0x89, 0x8c, 0x07, 0x3c, 0xf4, 0x9d, 0x41, 0x10, 0xc7, 0x7a, + 0x15, 0x84, 0xfe, 0x49, 0x75, 0xc5, 0xc1, 0x15, 0x31, 0x26, 0xea, 0xa8, 0x84, 0x23, 0x36, 0xa6, + 0xe5, 0x44, 0x19, 0x52, 0x5c, 0x1a, 0xc1, 0xda, 0x09, 0x0f, 0x2f, 0x39, 0x77, 0x5d, 0x21, 0x0c, + 0x0d, 0xb8, 0x1b, 0xfa, 0xf6, 0x48, 0x4c, 0x12, 0xf5, 0xe0, 0xfd, 0xb9, 0x52, 0xe3, 0x33, 0x90, + 0xad, 0x38, 0xe3, 0x76, 0x94, 0x8f, 0x78, 0xc7, 0xea, 0x49, 0x5a, 0xda, 0xc6, 0xaf, 0xc1, 0xc6, + 0xcd, 0x99, 0x52, 0x22, 0x3a, 0x1f, 0x24, 0xb9, 0x4a, 0x64, 0xb5, 0x1b, 0x79, 0x76, 0x48, 0xad, + 0xd1, 0x39, 0x4b, 0x17, 0x2a, 0x5a, 0x4a, 0xbc, 0xf7, 0x67, 0x50, 0xb8, 0xa3, 0x0f, 0xb1, 0x23, + 0xb9, 0x9e, 0x3f, 0x46, 0x2b, 0xd9, 0xd0, 0x8a, 0x4b, 0xcf, 0x98, 0x8b, 0x31, 0x1c, 0x43, 0xd8, + 0x8d, 0x4d, 0x58, 0x44, 0xc9, 0x5e, 0xdb, 0xe8, 0x5e, 0x24, 0x0c, 0x1a, 0x2b, 0xc0, 0xba, 0xc4, + 0xbb, 0x74, 0xe7, 0xcb, 0xff, 0x9a, 0x83, 0x8a, 0x06, 0x16, 0xbb, 0x11, 0xba, 0xeb, 0x59, 0x43, + 0xc7, 0x1e, 0x73, 0x65, 0x92, 0xac, 0x99, 0x35, 0x84, 0xee, 0x48, 0xa0, 0xd8, 0x8b, 0xed, 0x8b, + 0x33, 0xcb, 0x9b, 0x86, 0xd6, 0x90, 0x9f, 0xf9, 0x5c, 0xb5, 0xb2, 0x6a, 0x5f, 0x9c, 0x1d, 0x4e, + 0xc3, 0x1d, 0x84, 0x09, 0x2c, 0xc1, 0x4b, 0x34, 0x2c, 0xe9, 0x61, 0x36, 0xb6, 0xaf, 0x62, 0x2c, + 0xe9, 0xe6, 0x48, 0x94, 0x99, 0x8f, 0xdc, 0x1c, 0x49, 0x5b, 0x9c, 0xdd, 0x40, 0x0b, 0xf3, 0x1b, + 0xe8, 0x37, 0x61, 0x8d, 0x36, 0x50, 0xc9, 0x9a, 0xad, 0x99, 0x95, 0xbc, 0x82, 0xa9, 0xb2, 0x93, + 0x9a, 0xd8, 0xdb, 0x10, 0x3d, 0x50, 0x6c, 0x29, 0x70, 0x7e, 0x44, 0x8c, 0x2c, 0x63, 0x8a, 0x9e, + 0xc9, 0xc2, 0x7b, 0xce, 0x8f, 0xb8, 0xc0, 0x44, 0x5f, 0x16, 0x1d, 0x53, 0x06, 0x54, 0x8c, 0x1d, + 0x77, 0x16, 0xd3, 0xbe, 0x4a, 0x62, 0x96, 0x25, 0xa6, 0x7d, 0xa5, 0x63, 0xbe, 0x0f, 0xeb, 0x63, + 0x3e, 0x74, 0xec, 0x64, 0xb1, 0x56, 0x2c, 0xb8, 0xad, 0x50, 0xb2, 0x96, 0xa7, 0x47, 0x8a, 0xbb, + 0x18, 0x8d, 0x1f, 0x79, 0xe3, 0x13, 0x87, 0x64, 0x16, 0xf2, 0xae, 0xc9, 0x9b, 0x75, 0x77, 0x3a, + 0xfe, 0x01, 0x82, 0x45, 0x96, 0xc0, 0xa8, 0x41, 0xa5, 0x17, 0x7a, 0x13, 0x35, 0xcd, 0x75, 0xa8, + 0xd2, 0xa7, 0x8c, 0x72, 0xbc, 0x03, 0xb7, 0x91, 0x25, 0xf4, 0xbd, 0x89, 0x37, 0xf2, 0xce, 0xae, + 0x13, 0xe7, 0x78, 0xff, 0x39, 0x03, 0xcb, 0x89, 0x54, 0xc9, 0x5e, 0xbf, 0x49, 0xfc, 0x2c, 0x0a, + 0x55, 0xa3, 0x35, 0xb8, 0xa4, 0xad, 0x41, 0x42, 0x24, 0x66, 0xa6, 0xc2, 0xd7, 0x5a, 0xf1, 0x15, + 0x0b, 0x2a, 0x23, 0xb1, 0x94, 0xe6, 0x3c, 0x4b, 0x91, 0xf9, 0xd5, 0xe5, 0x0b, 0xaa, 0x88, 0x5f, + 0x92, 0x41, 0x2f, 0x43, 0xd9, 0xe5, 0x5c, 0xd2, 0xad, 0x5f, 0x3f, 0xf3, 0x53, 0x2d, 0x88, 0x0f, + 0x02, 0x03, 0xe3, 0x5f, 0x65, 0x00, 0xe2, 0xd6, 0x61, 0x60, 0x41, 0x24, 0xb7, 0xd0, 0xed, 0x65, + 0x9a, 0x8c, 0xf2, 0x06, 0x54, 0x23, 0xff, 0xe2, 0x58, 0x12, 0xaa, 0x28, 0x98, 0x10, 0x87, 0xde, + 0x86, 0xc5, 0xb3, 0x91, 0x77, 0x82, 0x12, 0xab, 0x94, 0x5b, 0xc8, 0xbb, 0xac, 0x4e, 0x60, 0x25, + 0x8d, 0xc4, 0x72, 0x53, 0x3e, 0xd5, 0x05, 0x59, 0x97, 0x82, 0x8c, 0xdf, 0xce, 0x46, 0x8e, 0x96, + 0xf1, 0x48, 0xbc, 0x58, 0xbd, 0xfb, 0x69, 0x3c, 0x5f, 0x5e, 0x64, 0x0c, 0xfc, 0x08, 0xea, 0x3e, + 0x6d, 0x4a, 0x6a, 0xc7, 0xca, 0xbf, 0x60, 0xc7, 0xaa, 0xf9, 0x09, 0x49, 0xe7, 0x1d, 0x68, 0xd8, + 0xc3, 0x0b, 0xee, 0x87, 0x0e, 0x9e, 0xd6, 0xa3, 0x7c, 0x2c, 0x5d, 0x1b, 0x35, 0x38, 0x0a, 0xa2, + 0x6f, 0xc3, 0xa2, 0x8c, 0xbc, 0x8d, 0x30, 0xe5, 0x5d, 0x3e, 0x31, 0x58, 0x20, 0x1a, 0xff, 0x46, + 0x79, 0x76, 0x26, 0x67, 0xf7, 0xc5, 0xa3, 0xa2, 0xf7, 0x30, 0x3b, 0x6f, 0xee, 0x94, 0x84, 0x24, + 0x8d, 0x00, 0x92, 0x1f, 0x11, 0x50, 0x9a, 0x00, 0x92, 0xc3, 0x9a, 0x7f, 0x95, 0x61, 0x35, 0xfe, + 0x34, 0x03, 0xc5, 0x3d, 0x6f, 0xb2, 0xe7, 0x90, 0x6b, 0x3d, 0x2e, 0x93, 0xc8, 0x46, 0xb5, 0x20, + 0x3e, 0xd1, 0x4d, 0xe7, 0x05, 0x01, 0x66, 0xa9, 0x62, 0x5e, 0x2d, 0x29, 0xe6, 0x7d, 0x17, 0xee, + 0xa0, 0x09, 0xd0, 0xf7, 0x26, 0x9e, 0x2f, 0x96, 0xaa, 0x3d, 0x22, 0x71, 0xcf, 0x73, 0xc3, 0x73, + 0xc5, 0x3b, 0x6f, 0x9f, 0x72, 0x7e, 0xa4, 0x61, 0x1c, 0x44, 0x08, 0x18, 0xc2, 0x39, 0x0a, 0x2f, + 0x2c, 0xd2, 0xd0, 0xa5, 0x3c, 0x4a, 0x1c, 0x75, 0x51, 0x24, 0xb4, 0x11, 0x8e, 0x12, 0xa9, 0xf1, + 0x6d, 0x28, 0x47, 0x87, 0x3d, 0xec, 0x5d, 0x28, 0x9f, 0x7b, 0x13, 0x79, 0x22, 0x94, 0x49, 0x04, + 0xe1, 0xc9, 0x5e, 0x9b, 0xa5, 0x73, 0xfa, 0x11, 0x18, 0x7f, 0x51, 0x84, 0x62, 0xc7, 0xbd, 0xf0, + 0x9c, 0x01, 0xfa, 0x86, 0x8e, 0xf9, 0xd8, 0x53, 0xe1, 0xff, 0xe2, 0x37, 0x7a, 0x52, 0xc5, 0x37, + 0xf2, 0xe4, 0xa4, 0x27, 0x55, 0x74, 0x17, 0xcf, 0x2a, 0x2c, 0xf8, 0xfa, 0x95, 0x3a, 0x05, 0x1f, + 0xbd, 0xd5, 0xa3, 0xfd, 0xb2, 0xa0, 0x5d, 0x9f, 0x20, 0xca, 0xa2, 0xab, 0x5e, 0x70, 0xc8, 0x28, + 0x1c, 0xb3, 0x8c, 0x10, 0x1c, 0xb0, 0xd7, 0xa0, 0x28, 0x63, 0xde, 0x28, 0x82, 0x88, 0xdc, 0xcb, + 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0x64, 0xc2, 0x8d, 0x04, 0xd9, 0x9c, 0x59, 0x55, 0xc0, 0x1d, 0x41, + 0x6b, 0xf7, 0xa0, 0x42, 0xf8, 0x84, 0x52, 0x92, 0x2e, 0x95, 0x08, 0x42, 0x84, 0x94, 0x9b, 0xa9, + 0xca, 0xa9, 0x37, 0x53, 0xa1, 0xf3, 0x6f, 0xc4, 0x65, 0xa9, 0x8b, 0x40, 0xf7, 0x11, 0x69, 0x70, + 0x75, 0x2d, 0x9b, 0x3c, 0x53, 0xa1, 0xe8, 0x64, 0x75, 0xa6, 0xf2, 0x15, 0xa8, 0x9d, 0xda, 0xa3, + 0xd1, 0x89, 0x3d, 0x78, 0x4e, 0x47, 0x01, 0x55, 0x3a, 0xfd, 0x54, 0x40, 0x3c, 0x0b, 0xb8, 0x07, + 0x15, 0x6d, 0x96, 0xd1, 0x5f, 0x32, 0x6f, 0x42, 0x3c, 0xbf, 0xb3, 0x27, 0x7c, 0xf5, 0x57, 0x38, + 0xe1, 0xd3, 0xfc, 0x46, 0x17, 0x93, 0x7e, 0xa3, 0x77, 0x90, 0x9b, 0x4a, 0x07, 0xc1, 0x06, 0x5d, + 0x7e, 0x63, 0x0f, 0x87, 0xe8, 0x20, 0x48, 0x37, 0x4d, 0xe2, 0xe0, 0x51, 0xfa, 0x12, 0xe9, 0x12, + 0x04, 0x23, 0x94, 0xbb, 0x74, 0x4c, 0x3d, 0xb1, 0x9d, 0x21, 0x86, 0x08, 0xd0, 0xe9, 0x41, 0xd1, + 0x1e, 0x87, 0x47, 0xb6, 0x33, 0x64, 0xf7, 0xa1, 0xaa, 0x92, 0x71, 0x77, 0x5c, 0xa6, 0xf1, 0x97, + 0xc9, 0x62, 0x4f, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe3, 0x10, 0xe3, 0x8a, 0x44, 0x41, 0x3a, 0x78, + 0x0f, 0x7d, 0x72, 0x42, 0x8e, 0x81, 0xc4, 0xf5, 0x27, 0x77, 0x64, 0x5f, 0x25, 0x95, 0xaa, 0xff, + 0x64, 0x1c, 0x23, 0x4c, 0x21, 0xdc, 0x91, 0x8d, 0x6e, 0x2d, 0x21, 0xff, 0x4a, 0x54, 0xb4, 0xd1, + 0x11, 0x02, 0xfb, 0xb6, 0xa6, 0xbf, 0x36, 0x11, 0xf9, 0xb5, 0x99, 0xf2, 0x6f, 0x8a, 0x90, 0xba, + 0x0b, 0xe0, 0x04, 0x62, 0x97, 0x09, 0xb8, 0x3b, 0xc4, 0x98, 0xe0, 0x92, 0x59, 0x76, 0x82, 0x67, + 0x04, 0xf8, 0xf9, 0x2a, 0xb6, 0x2d, 0xa8, 0xea, 0xdd, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0xb5, 0xbb, + 0x8d, 0x5b, 0xac, 0x02, 0xc5, 0x5e, 0xbb, 0xdf, 0xdf, 0x47, 0x4b, 0x5f, 0x15, 0x4a, 0x51, 0x40, + 0x62, 0x56, 0x7c, 0xb5, 0xb6, 0xb7, 0xdb, 0x47, 0xfd, 0xf6, 0x4e, 0x23, 0xf7, 0xfd, 0x7c, 0x29, + 0xdb, 0xc8, 0x19, 0x7f, 0x99, 0x83, 0x8a, 0x36, 0x0a, 0x2f, 0x66, 0xc6, 0x77, 0x01, 0x50, 0x93, + 0x8c, 0xfd, 0x47, 0xf3, 0x66, 0x59, 0x40, 0x68, 0xf2, 0x75, 0x1b, 0x45, 0x8e, 0x6e, 0x55, 0x52, + 0x36, 0x8a, 0xaf, 0x40, 0x8d, 0x2e, 0x28, 0xd2, 0xed, 0xb5, 0x05, 0xb3, 0x4a, 0x40, 0xc9, 0xaa, + 0x31, 0xa2, 0x19, 0x91, 0x30, 0xd6, 0x4d, 0x5e, 0x57, 0x42, 0x20, 0x8c, 0x76, 0xc3, 0x50, 0xc5, + 0xc0, 0x1b, 0x5d, 0x70, 0xc2, 0x20, 0x89, 0xb0, 0x22, 0x61, 0x7d, 0x19, 0x9b, 0x2d, 0xf9, 0xa1, + 0x16, 0x52, 0x5b, 0x30, 0xab, 0x04, 0x94, 0x15, 0x7d, 0x5d, 0x11, 0x50, 0x09, 0x09, 0x68, 0x7d, + 0x9e, 0x1a, 0x12, 0xc4, 0xb3, 0x3f, 0x77, 0x8c, 0x58, 0x46, 0xc2, 0xf8, 0xea, 0x7c, 0xbe, 0x97, + 0x1f, 0x27, 0xb2, 0x77, 0x81, 0x8d, 0x27, 0x13, 0x2b, 0xe5, 0x80, 0x2f, 0x6f, 0x2e, 0x8e, 0x27, + 0x93, 0xbe, 0x76, 0xfe, 0xf5, 0x73, 0x38, 0x7b, 0xfc, 0x1c, 0x58, 0x4b, 0x2c, 0x60, 0x6c, 0x62, + 0xa4, 0x8a, 0xc5, 0x6c, 0x39, 0xa3, 0xb3, 0xe5, 0x14, 0xee, 0x97, 0x4d, 0xe5, 0x7e, 0x2f, 0xe2, + 0x13, 0xc6, 0x2e, 0x54, 0x8e, 0xb4, 0xeb, 0xcf, 0xee, 0x8b, 0x1d, 0x42, 0x5d, 0x7c, 0x46, 0x7b, + 0x07, 0x9d, 0x29, 0xfa, 0xf2, 0xbe, 0x33, 0xad, 0x35, 0x59, 0xad, 0x35, 0xc6, 0xbf, 0xcc, 0xd0, + 0xd5, 0x32, 0x51, 0xe3, 0xe3, 0x1b, 0xd7, 0x94, 0xf9, 0x2d, 0x8e, 0x7c, 0xaf, 0x28, 0xb3, 0x9b, + 0x0c, 0x5a, 0xc7, 0xa6, 0x59, 0xde, 0xe9, 0x69, 0xc0, 0x95, 0x8f, 0x47, 0x05, 0x61, 0x87, 0x08, + 0x52, 0xc2, 0xb7, 0x90, 0xf0, 0x1d, 0x2a, 0x3f, 0x90, 0x8e, 0x1d, 0x42, 0xf8, 0x3e, 0xb0, 0xaf, + 0x64, 0xad, 0x81, 0x10, 0x41, 0xa4, 0x7d, 0x40, 0x45, 0xae, 0x46, 0xdf, 0xc6, 0x3f, 0x93, 0xc1, + 0xf9, 0xb3, 0xe3, 0xfb, 0x10, 0x4a, 0x51, 0xa9, 0xc9, 0x1d, 0x56, 0x61, 0x46, 0xe9, 0x62, 0x1f, + 0xc7, 0xc3, 0x90, 0x44, 0x8b, 0x69, 0x71, 0xa1, 0x8d, 0xa7, 0xa3, 0xb5, 0xfa, 0x6b, 0xc0, 0x4e, + 0x1d, 0x7f, 0x16, 0x99, 0x16, 0x5b, 0x03, 0x53, 0x34, 0x6c, 0xe3, 0x18, 0x96, 0x15, 0x97, 0xd0, + 0x34, 0x82, 0xe4, 0xe4, 0x65, 0x5e, 0xc2, 0xe4, 0xb3, 0x73, 0x4c, 0xde, 0xf8, 0x49, 0x1e, 0x8a, + 0xea, 0x2a, 0xc1, 0xb4, 0xeb, 0xef, 0xca, 0xc9, 0xeb, 0xef, 0x9a, 0x89, 0xab, 0x92, 0x70, 0xea, + 0xe5, 0x7e, 0xff, 0xf6, 0xec, 0x96, 0xad, 0xd9, 0x2a, 0x12, 0xdb, 0xf6, 0x1a, 0xe4, 0x27, 0x76, + 0x78, 0x8e, 0xe7, 0x92, 0x44, 0x3c, 0xf8, 0xad, 0x6c, 0x18, 0x85, 0xa4, 0x0d, 0x23, 0xed, 0xaa, + 0x40, 0x12, 0x49, 0xe7, 0xae, 0x0a, 0xbc, 0x03, 0x24, 0x5f, 0x68, 0x2e, 0x6a, 0x25, 0x04, 0x88, + 0xbd, 0x28, 0x29, 0x8e, 0x94, 0x66, 0xc5, 0x91, 0x57, 0x16, 0x15, 0xbe, 0x09, 0x0b, 0x74, 0xcd, + 0x86, 0x8c, 0xd0, 0x55, 0x1b, 0x8a, 0x1c, 0x43, 0xf5, 0x9f, 0xe2, 0x16, 0x4c, 0x89, 0xab, 0xdf, + 0xbb, 0x55, 0x49, 0xdc, 0xbb, 0xa5, 0xdb, 0x56, 0xaa, 0x49, 0xdb, 0xca, 0x03, 0x68, 0x44, 0x03, + 0x8a, 0x27, 0x95, 0x6e, 0x20, 0xe3, 0xff, 0xea, 0x0a, 0x2e, 0xb8, 0x64, 0x37, 0x88, 0x37, 0xc4, + 0x7a, 0x62, 0x43, 0x14, 0x3c, 0xac, 0x15, 0x86, 0x7c, 0x3c, 0x09, 0xe5, 0x86, 0x88, 0x11, 0x42, + 0x7a, 0x03, 0x93, 0xb1, 0xeb, 0x35, 0x28, 0x77, 0xba, 0xd6, 0xee, 0x7e, 0xe7, 0xe9, 0x5e, 0xbf, + 0x91, 0x11, 0x9f, 0xbd, 0xe3, 0xed, 0xed, 0x76, 0x7b, 0x07, 0x77, 0x1c, 0x80, 0x85, 0xdd, 0x56, + 0x47, 0xec, 0x3e, 0x39, 0xe3, 0x77, 0xb3, 0x50, 0xd1, 0x8a, 0x67, 0xef, 0x47, 0xa3, 0x42, 0x57, + 0x33, 0xdd, 0x9d, 0x6f, 0xc2, 0xa6, 0x62, 0xc5, 0xda, 0xb0, 0x44, 0x17, 0x23, 0x66, 0x6f, 0xbc, + 0x18, 0x91, 0xbd, 0x05, 0x8b, 0x36, 0x95, 0x10, 0x8d, 0x82, 0x3c, 0x85, 0x97, 0x60, 0x39, 0x08, + 0xe8, 0x98, 0x19, 0xef, 0x27, 0x02, 0x2f, 0xaf, 0x7c, 0x21, 0xa3, 0x2d, 0x05, 0x07, 0xab, 0x78, + 0x6a, 0x3b, 0xa3, 0xa9, 0xcf, 0xa5, 0xd5, 0x3c, 0xda, 0x99, 0x09, 0x6a, 0xaa, 0x64, 0xe3, 0x03, + 0x80, 0xb8, 0xcd, 0xc9, 0xc1, 0xb9, 0x95, 0x1c, 0x9c, 0x8c, 0x36, 0x38, 0x59, 0x63, 0x87, 0xd8, + 0x88, 0x1c, 0xe8, 0xe8, 0xd8, 0xed, 0xeb, 0xa0, 0x0e, 0x02, 0x2d, 0x74, 0x8f, 0x9e, 0x8c, 0x78, + 0xa8, 0xa2, 0xfc, 0x97, 0x64, 0x4a, 0x27, 0x4a, 0x50, 0x97, 0x6e, 0xc4, 0xa5, 0xc4, 0xdc, 0x48, + 0x92, 0xe4, 0x2c, 0x37, 0x92, 0xa8, 0x66, 0x94, 0x6e, 0x6c, 0x40, 0x73, 0x87, 0x8b, 0xd2, 0x5a, + 0xa3, 0xd1, 0x4c, 0x73, 0x8c, 0x3b, 0x70, 0x3b, 0x25, 0x4d, 0x1e, 0x42, 0x7c, 0x0c, 0xab, 0x2d, + 0x0a, 0xe8, 0xff, 0x79, 0x45, 0xee, 0x19, 0x4d, 0x58, 0x9b, 0x2d, 0x52, 0x56, 0xb6, 0x0b, 0x4b, + 0x3b, 0xfc, 0x64, 0x7a, 0xb6, 0xcf, 0x2f, 0xe2, 0x8a, 0x18, 0xe4, 0x83, 0x73, 0xef, 0x52, 0x8e, + 0x0f, 0xfe, 0x46, 0x2f, 0x43, 0x81, 0x63, 0x05, 0x13, 0x3e, 0x50, 0x07, 0xd1, 0x08, 0xe9, 0x4d, + 0xf8, 0xc0, 0x78, 0x1f, 0x98, 0x5e, 0x8e, 0x1c, 0x2f, 0xa1, 0x25, 0x4c, 0x4f, 0xac, 0xe0, 0x3a, + 0x08, 0xf9, 0x58, 0x45, 0xac, 0x41, 0x30, 0x3d, 0xe9, 0x11, 0xc4, 0x78, 0x1b, 0xaa, 0x47, 0xf6, + 0xb5, 0xc9, 0x3f, 0x97, 0x81, 0x61, 0xeb, 0x50, 0x9c, 0xd8, 0xd7, 0x82, 0x0d, 0x44, 0x36, 0x29, + 0x4c, 0x36, 0xfe, 0x28, 0x0f, 0x0b, 0x84, 0xc9, 0xee, 0xd3, 0xe5, 0xbc, 0x8e, 0x8b, 0xcb, 0x50, + 0x31, 0x4a, 0x0d, 0x34, 0xc7, 0x4b, 0xb3, 0xf3, 0xbc, 0x54, 0x1e, 0xa0, 0xa9, 0x4b, 0x89, 0x94, + 0xf5, 0xc0, 0x9d, 0x8e, 0xd5, 0x4d, 0x44, 0xc9, 0xa8, 0xf6, 0x7c, 0x7c, 0xf9, 0x32, 0x85, 0xfc, + 0x26, 0xed, 0xbb, 0xb1, 0x2e, 0x42, 0xad, 0x53, 0x5b, 0x84, 0x64, 0x97, 0x3a, 0x28, 0x55, 0xe1, + 0x29, 0xaa, 0x68, 0xc7, 0xa4, 0xc2, 0x33, 0xa7, 0xd8, 0x94, 0x5e, 0xae, 0xd8, 0xd0, 0xc9, 0xda, + 0x0b, 0x14, 0x1b, 0x78, 0x05, 0xc5, 0xe6, 0x15, 0x6c, 0xab, 0xb7, 0xa1, 0x84, 0xfb, 0xbe, 0xc6, + 0x3d, 0xc5, 0x7e, 0x2f, 0xb8, 0xe7, 0xb7, 0x34, 0xd1, 0x9f, 0x1c, 0x3b, 0xee, 0xc4, 0xcb, 0xc4, + 0xe4, 0x9f, 0xff, 0x62, 0x6c, 0x56, 0x9f, 0x41, 0x51, 0x42, 0x05, 0x41, 0xbb, 0xf6, 0x58, 0xdd, + 0xeb, 0x86, 0xbf, 0xc5, 0xb0, 0xe1, 0x65, 0x54, 0x9f, 0x4f, 0x1d, 0x9f, 0x0f, 0xd5, 0x85, 0x3d, + 0x0e, 0xae, 0x51, 0x01, 0x11, 0x1d, 0x14, 0x6a, 0x88, 0xeb, 0x5d, 0xba, 0xf2, 0xba, 0x8e, 0xa2, + 0x13, 0x3c, 0x13, 0x9f, 0x06, 0x83, 0x06, 0xde, 0xec, 0x38, 0xf1, 0x7c, 0xb5, 0x39, 0x19, 0x3f, + 0xc9, 0x40, 0x43, 0xae, 0xae, 0x28, 0x4d, 0xd7, 0x02, 0x0a, 0x37, 0xf9, 0x21, 0xbc, 0xf8, 0xfa, + 0x1d, 0x03, 0x6a, 0x78, 0xf8, 0x11, 0xed, 0x54, 0x74, 0x78, 0x53, 0x11, 0xc0, 0x5d, 0xb9, 0x5b, + 0xbd, 0x0e, 0x15, 0xe5, 0x03, 0x3d, 0x76, 0x46, 0xea, 0x9e, 0x75, 0x72, 0x82, 0x3e, 0x70, 0x46, + 0x6a, 0xa3, 0xf3, 0x6d, 0x19, 0x7d, 0x9b, 0xc1, 0x8d, 0xce, 0xb4, 0x43, 0x6e, 0xfc, 0xbb, 0x0c, + 0x2c, 0x69, 0x5d, 0x91, 0xeb, 0xf6, 0x43, 0xa8, 0x46, 0x57, 0xaa, 0xf2, 0x48, 0xf2, 0x5a, 0x4f, + 0x32, 0x9a, 0x38, 0x5b, 0x65, 0x10, 0x41, 0x02, 0xd1, 0x98, 0xa1, 0x7d, 0x4d, 0x8e, 0xba, 0xd3, + 0xb1, 0x52, 0x6e, 0x86, 0xf6, 0xf5, 0x2e, 0xe7, 0xbd, 0xe9, 0x58, 0xa8, 0xae, 0x97, 0x9c, 0x3f, + 0x8f, 0x10, 0x48, 0xe6, 0x02, 0x01, 0x93, 0x18, 0x06, 0xd4, 0xc6, 0x9e, 0x1b, 0x9e, 0x47, 0x28, + 0x52, 0xea, 0x44, 0x20, 0xe1, 0x18, 0x7f, 0x9e, 0x85, 0x65, 0x3a, 0x62, 0x93, 0x47, 0x9b, 0x92, + 0x75, 0x35, 0x61, 0x81, 0x4e, 0x1b, 0x89, 0x79, 0xed, 0xdd, 0x32, 0xe5, 0x37, 0xfb, 0xe6, 0x2b, + 0x1e, 0x0b, 0xaa, 0x00, 0xdf, 0x1b, 0x86, 0x3f, 0x37, 0x3f, 0xfc, 0x37, 0x0f, 0x6f, 0x9a, 0xa1, + 0xb3, 0x90, 0x66, 0xe8, 0x7c, 0x15, 0xf3, 0xe2, 0x5c, 0x28, 0x6a, 0x51, 0xe2, 0x68, 0xa1, 0xa8, + 0xef, 0xc3, 0x7a, 0x02, 0x07, 0xb9, 0xb5, 0x73, 0xea, 0x70, 0x75, 0x1b, 0xca, 0x8a, 0x86, 0xdd, + 0x53, 0x69, 0x5b, 0x45, 0x28, 0x04, 0x03, 0x6f, 0xc2, 0x8d, 0x35, 0x58, 0x49, 0x8e, 0xaa, 0xdc, + 0x26, 0x7e, 0x2f, 0x03, 0x4d, 0xe9, 0x96, 0xe2, 0xb8, 0x67, 0x7b, 0x4e, 0x10, 0x7a, 0x7e, 0x74, + 0xf5, 0xe8, 0x5d, 0x80, 0x20, 0xb4, 0x7d, 0xa9, 0x6d, 0xca, 0xfb, 0x3f, 0x10, 0x82, 0x9a, 0xe4, + 0x6d, 0x28, 0x71, 0x77, 0x48, 0x89, 0x44, 0x0d, 0x45, 0xee, 0x0e, 0x95, 0x1e, 0x3a, 0x27, 0x7f, + 0xd7, 0x92, 0xea, 0x85, 0x0c, 0xc7, 0x17, 0xa3, 0xc3, 0x2f, 0x70, 0xe3, 0xcd, 0x47, 0xe1, 0xf8, + 0x07, 0xf6, 0x15, 0x3a, 0x79, 0x06, 0xc6, 0x3f, 0xce, 0xc2, 0x62, 0xdc, 0x3e, 0xba, 0xcb, 0xe3, + 0xc5, 0xb7, 0x92, 0xdc, 0x97, 0xe4, 0xe0, 0x08, 0xf9, 0x5d, 0x3b, 0x78, 0x2c, 0xd1, 0xe2, 0xec, + 0xb8, 0xcc, 0x80, 0x8a, 0xc2, 0xf0, 0xa6, 0xa1, 0x76, 0x03, 0x60, 0x99, 0x50, 0x0e, 0xa7, 0xa1, + 0x50, 0xb8, 0x84, 0xe6, 0xe9, 0xb8, 0x52, 0xe5, 0x29, 0xd8, 0xe3, 0xb0, 0x83, 0x0f, 0x0b, 0x08, + 0xb0, 0xc8, 0x46, 0x13, 0x29, 0xb0, 0x04, 0x7e, 0x83, 0xe4, 0x6c, 0x9a, 0x39, 0x94, 0xb1, 0x75, + 0x21, 0x94, 0xee, 0x58, 0x8e, 0x84, 0xd0, 0xd7, 0xa1, 0x42, 0x85, 0xc7, 0x91, 0xc7, 0x79, 0xb3, + 0x8c, 0x35, 0x60, 0xba, 0x3c, 0x04, 0xf2, 0xa6, 0x09, 0xd5, 0x17, 0xa8, 0x2a, 0xf4, 0xfa, 0xf8, + 0xfb, 0x19, 0xb8, 0x9d, 0x32, 0x6d, 0x72, 0x95, 0x6f, 0xc3, 0xd2, 0x69, 0x94, 0xa8, 0x46, 0x97, + 0x96, 0xfa, 0x9a, 0x62, 0xab, 0xc9, 0x31, 0x35, 0x1b, 0xa7, 0x49, 0x40, 0xac, 0x74, 0xd1, 0x0c, + 0x26, 0xe2, 0xda, 0x51, 0xe9, 0xa2, 0x69, 0x24, 0x7d, 0xe7, 0x08, 0x36, 0xda, 0x57, 0x82, 0x63, + 0x6c, 0xeb, 0x2f, 0x63, 0x28, 0x32, 0x4a, 0x1e, 0x30, 0x67, 0x5e, 0xe9, 0x80, 0x79, 0x48, 0x81, + 0xb0, 0x51, 0x59, 0x3f, 0x4d, 0x21, 0xb8, 0x81, 0x8a, 0x3c, 0xf4, 0xb2, 0x87, 0x0a, 0x70, 0x1f, + 0x44, 0x2f, 0x7a, 0x18, 0x01, 0x2c, 0x1e, 0x4c, 0x47, 0xa1, 0x13, 0x3f, 0xf2, 0xc1, 0xbe, 0x29, + 0xf3, 0x60, 0x3d, 0x6a, 0xd4, 0x52, 0x2b, 0x82, 0xa8, 0x22, 0x1c, 0xac, 0xb1, 0x28, 0xc8, 0x9a, + 0xaf, 0x6f, 0x71, 0x9c, 0xac, 0xc1, 0xb8, 0x0d, 0xeb, 0xf1, 0x17, 0x0d, 0x9b, 0xda, 0x6a, 0xfe, + 0x45, 0x86, 0x3c, 0xca, 0x93, 0x0f, 0x8e, 0xb0, 0x36, 0x2c, 0x07, 0x8e, 0x7b, 0x36, 0xe2, 0x7a, + 0xf1, 0x81, 0x1c, 0x84, 0xd5, 0x64, 0xdb, 0xe4, 0xa3, 0x24, 0xe6, 0x12, 0xe5, 0x88, 0x4b, 0x0b, + 0xd8, 0xd6, 0x4d, 0x8d, 0x8c, 0xc9, 0x62, 0x66, 0x34, 0xe6, 0x1b, 0xdf, 0x81, 0x7a, 0xb2, 0x22, + 0xf6, 0x2d, 0x19, 0x3f, 0x1e, 0xb7, 0x2a, 0x37, 0x13, 0x5c, 0x1b, 0x13, 0x44, 0x25, 0x1e, 0xfb, + 0xc0, 0xf8, 0x87, 0x19, 0x68, 0x9a, 0x5c, 0x50, 0xae, 0xd6, 0x4a, 0x45, 0x33, 0x1f, 0xce, 0x95, + 0x7a, 0x73, 0x5f, 0x55, 0x58, 0xba, 0x6a, 0xd1, 0xd7, 0x6e, 0x9c, 0x8c, 0xbd, 0x5b, 0x73, 0x3d, + 0xda, 0x2a, 0xc1, 0x02, 0xa1, 0x18, 0xeb, 0xb0, 0x2a, 0xdb, 0xa3, 0xda, 0x12, 0x5b, 0x0f, 0x13, + 0x35, 0x26, 0xac, 0x87, 0x1b, 0xd0, 0xa4, 0x40, 0x51, 0xbd, 0x13, 0x32, 0xe3, 0x0e, 0xb0, 0x03, + 0x7b, 0x60, 0xfb, 0x9e, 0xe7, 0x1e, 0x71, 0x5f, 0xfa, 0xe7, 0xa2, 0x84, 0x89, 0xc6, 0x35, 0x25, + 0x0a, 0xd3, 0x97, 0xba, 0xf7, 0xd4, 0x73, 0x95, 0x3b, 0x12, 0x7d, 0x19, 0x26, 0x2c, 0x6f, 0xd9, + 0xcf, 0xb9, 0x2a, 0x49, 0x0d, 0xd1, 0x47, 0x50, 0x99, 0x44, 0x85, 0xaa, 0x71, 0x57, 0xf7, 0x5b, + 0xcc, 0x57, 0x6b, 0xea, 0xd8, 0xc6, 0x13, 0x58, 0x49, 0x96, 0x29, 0x59, 0xc7, 0x06, 0x94, 0xc6, + 0x12, 0x26, 0x5b, 0x17, 0x7d, 0x1b, 0xbf, 0x53, 0x82, 0xa2, 0xd4, 0xe7, 0xd8, 0x26, 0xe4, 0x07, + 0xca, 0x25, 0x2c, 0xbe, 0x36, 0x49, 0xa6, 0xaa, 0xff, 0xdb, 0xe8, 0x18, 0x26, 0xf0, 0xd8, 0x47, + 0x50, 0x4f, 0x5a, 0x45, 0x67, 0xc2, 0xd0, 0x93, 0xe6, 0xcc, 0xda, 0x60, 0xc6, 0xfe, 0x55, 0x8e, + 0x37, 0x47, 0x92, 0x19, 0x4a, 0xe7, 0xda, 0xee, 0xe9, 0xb9, 0x42, 0xde, 0x0e, 0xce, 0x6d, 0xeb, + 0xc9, 0xfb, 0x1f, 0xc8, 0x38, 0xf4, 0x0a, 0x02, 0x7b, 0xe7, 0xf6, 0x93, 0xf7, 0x3f, 0x98, 0x95, + 0xa4, 0x65, 0x14, 0xba, 0x26, 0x49, 0xaf, 0x40, 0x81, 0x2e, 0xf8, 0x24, 0xdf, 0x1e, 0xfa, 0x60, + 0x8f, 0x61, 0x45, 0xaa, 0xad, 0x96, 0xf4, 0xc2, 0x26, 0x2e, 0x58, 0xa2, 0xc0, 0x37, 0x99, 0xd6, + 0xc3, 0x24, 0x3a, 0x1b, 0x5a, 0x83, 0x85, 0xf3, 0xf8, 0xb6, 0xd6, 0x9a, 0x29, 0xbf, 0x8c, 0x3f, + 0x2f, 0x40, 0x45, 0x1b, 0x14, 0x56, 0x85, 0x92, 0xd9, 0xee, 0xb5, 0xcd, 0x4f, 0xda, 0x3b, 0x8d, + 0x5b, 0xec, 0x01, 0xbc, 0xd9, 0xe9, 0x6e, 0x1f, 0x9a, 0x66, 0x7b, 0xbb, 0x6f, 0x1d, 0x9a, 0x96, + 0xba, 0xbc, 0xeb, 0xa8, 0xf5, 0xd9, 0x41, 0xbb, 0xdb, 0xb7, 0x76, 0xda, 0xfd, 0x56, 0x67, 0xbf, + 0xd7, 0xc8, 0xb0, 0xd7, 0xa0, 0x19, 0x63, 0xaa, 0xe4, 0xd6, 0xc1, 0xe1, 0x71, 0xb7, 0xdf, 0xc8, + 0xb2, 0x7b, 0x70, 0x67, 0xb7, 0xd3, 0x6d, 0xed, 0x5b, 0x31, 0xce, 0xf6, 0x7e, 0xff, 0x13, 0xab, + 0xfd, 0x2b, 0x47, 0x1d, 0xf3, 0xb3, 0x46, 0x2e, 0x0d, 0x41, 0x28, 0xe3, 0xaa, 0x84, 0x3c, 0xbb, + 0x0d, 0xab, 0x84, 0x40, 0x59, 0xac, 0xfe, 0xe1, 0xa1, 0xd5, 0x3b, 0x3c, 0xec, 0x36, 0x0a, 0x6c, + 0x09, 0x6a, 0x9d, 0xee, 0x27, 0xad, 0xfd, 0xce, 0x8e, 0x65, 0xb6, 0x5b, 0xfb, 0x07, 0x8d, 0x05, + 0xb6, 0x0c, 0x8b, 0xb3, 0x78, 0x45, 0x51, 0x84, 0xc2, 0x3b, 0xec, 0x76, 0x0e, 0xbb, 0xd6, 0x27, + 0x6d, 0xb3, 0xd7, 0x39, 0xec, 0x36, 0x4a, 0x6c, 0x0d, 0x58, 0x32, 0x69, 0xef, 0xa0, 0xb5, 0xdd, + 0x28, 0xb3, 0x55, 0x58, 0x4a, 0xc2, 0x9f, 0xb5, 0x3f, 0x6b, 0x00, 0x6b, 0xc2, 0x0a, 0x35, 0xcc, + 0xda, 0x6a, 0xef, 0x1f, 0x7e, 0x6a, 0x1d, 0x74, 0xba, 0x9d, 0x83, 0xe3, 0x83, 0x46, 0x05, 0xaf, + 0x13, 0x6c, 0xb7, 0xad, 0x4e, 0xb7, 0x77, 0xbc, 0xbb, 0xdb, 0xd9, 0xee, 0xb4, 0xbb, 0xfd, 0x46, + 0x95, 0x6a, 0x4e, 0xeb, 0x78, 0x4d, 0x64, 0x90, 0xa1, 0x1a, 0xd6, 0x4e, 0xa7, 0xd7, 0xda, 0xda, + 0x6f, 0xef, 0x34, 0xea, 0xec, 0x2e, 0xdc, 0xee, 0xb7, 0x0f, 0x8e, 0x0e, 0xcd, 0x96, 0xf9, 0x99, + 0x0a, 0xe5, 0xb0, 0x76, 0x5b, 0x9d, 0xfd, 0x63, 0xb3, 0xdd, 0x58, 0x64, 0x6f, 0xc0, 0x5d, 0xb3, + 0xfd, 0xf1, 0x71, 0xc7, 0x6c, 0xef, 0x58, 0xdd, 0xc3, 0x9d, 0xb6, 0xb5, 0xdb, 0x6e, 0xf5, 0x8f, + 0xcd, 0xb6, 0x75, 0xd0, 0xe9, 0xf5, 0x3a, 0xdd, 0xa7, 0x8d, 0x06, 0x7b, 0x13, 0xee, 0x47, 0x28, + 0x51, 0x01, 0x33, 0x58, 0x4b, 0xa2, 0x7f, 0x6a, 0x4a, 0xbb, 0xed, 0x5f, 0xe9, 0x5b, 0x47, 0xed, + 0xb6, 0xd9, 0x60, 0x6c, 0x03, 0xd6, 0xe2, 0xea, 0xa9, 0x02, 0x59, 0xf7, 0xb2, 0x48, 0x3b, 0x6a, + 0x9b, 0x07, 0xad, 0xae, 0x98, 0xe0, 0x44, 0xda, 0x8a, 0x68, 0x76, 0x9c, 0x36, 0xdb, 0xec, 0x55, + 0xc6, 0xa0, 0xae, 0xcd, 0xca, 0x6e, 0xcb, 0x6c, 0xac, 0xb1, 0x45, 0xa8, 0x1c, 0x1c, 0x1d, 0x59, + 0xfd, 0xce, 0x41, 0xfb, 0xf0, 0xb8, 0xdf, 0x58, 0x67, 0xab, 0xd0, 0xe8, 0x74, 0xfb, 0x6d, 0x53, + 0xcc, 0xb5, 0xca, 0xfa, 0xbf, 0x8a, 0x6c, 0x05, 0x16, 0x55, 0x4b, 0x15, 0xf4, 0xaf, 0x8a, 0x6c, + 0x1d, 0xd8, 0x71, 0xd7, 0x6c, 0xb7, 0x76, 0xc4, 0xc0, 0x45, 0x09, 0xff, 0xbb, 0x28, 0x2d, 0x24, + 0x3f, 0xc9, 0x45, 0x9b, 0x75, 0xec, 0x72, 0x90, 0xbc, 0xbb, 0xbb, 0xaa, 0xdd, 0xb9, 0xfd, 0xb2, + 0x57, 0x35, 0x34, 0xd5, 0x2a, 0x37, 0xa7, 0x5a, 0xcd, 0xe9, 0xee, 0x35, 0x5d, 0xf6, 0xfb, 0x0a, + 0xd4, 0xc6, 0x74, 0x8f, 0xb7, 0xbc, 0xaf, 0x17, 0xa4, 0xff, 0x0d, 0x01, 0xe9, 0xb2, 0xde, 0xb9, + 0x67, 0x25, 0x0a, 0xf3, 0xcf, 0x4a, 0xa4, 0xc9, 0xf7, 0x0b, 0x69, 0xf2, 0xfd, 0x43, 0x58, 0x22, + 0xd6, 0xe4, 0xb8, 0xce, 0x58, 0x69, 0xcd, 0x24, 0x05, 0x2e, 0x22, 0x8b, 0x22, 0xb8, 0x52, 0x27, + 0x94, 0xca, 0x21, 0x59, 0x48, 0x51, 0x6a, 0x1b, 0x09, 0x4d, 0x83, 0x38, 0x47, 0xa4, 0x69, 0x44, + 0x35, 0xd8, 0x57, 0x71, 0x0d, 0x15, 0xad, 0x06, 0x82, 0x63, 0x0d, 0x0f, 0x61, 0x89, 0x5f, 0x85, + 0xbe, 0x6d, 0x79, 0x13, 0xfb, 0xf3, 0x29, 0x9a, 0x70, 0x6d, 0xd4, 0xe1, 0xab, 0xe6, 0x22, 0x26, + 0x1c, 0x22, 0x7c, 0xc7, 0x0e, 0xed, 0x87, 0x5f, 0x40, 0x45, 0xbb, 0xe3, 0x9d, 0xad, 0xc3, 0xf2, + 0xa7, 0x9d, 0x7e, 0xb7, 0xdd, 0xeb, 0x59, 0x47, 0xc7, 0x5b, 0xcf, 0xda, 0x9f, 0x59, 0x7b, 0xad, + 0xde, 0x5e, 0xe3, 0x96, 0x58, 0xb4, 0xdd, 0x76, 0xaf, 0xdf, 0xde, 0x49, 0xc0, 0x33, 0xec, 0x75, + 0xd8, 0x38, 0xee, 0x1e, 0xf7, 0xda, 0x3b, 0x56, 0x5a, 0xbe, 0xac, 0xa0, 0x52, 0x99, 0x9e, 0x92, + 0x3d, 0xf7, 0xf0, 0x7b, 0x50, 0x4f, 0x5e, 0x3c, 0xcc, 0x00, 0x16, 0xf6, 0xdb, 0x4f, 0x5b, 0xdb, + 0x9f, 0xd1, 0x85, 0xa3, 0xbd, 0x7e, 0xab, 0xdf, 0xd9, 0xb6, 0xe4, 0x05, 0xa3, 0x82, 0x23, 0x64, + 0x58, 0x05, 0x8a, 0xad, 0xee, 0xf6, 0xde, 0xa1, 0xd9, 0x6b, 0x64, 0x1f, 0x7e, 0x07, 0xea, 0x49, + 0xef, 0xba, 0xe4, 0xb9, 0xeb, 0x06, 0xac, 0x6d, 0xb5, 0xfb, 0x9f, 0xb6, 0xdb, 0x5d, 0x6c, 0xdc, + 0x76, 0xbb, 0xdb, 0x37, 0x5b, 0xfb, 0x9d, 0xfe, 0x67, 0x8d, 0xcc, 0xc3, 0x8f, 0xa0, 0x31, 0x6b, + 0xca, 0x4a, 0xd8, 0xfe, 0x5e, 0x64, 0x24, 0x7c, 0xf8, 0xaf, 0x73, 0x00, 0x71, 0x88, 0x87, 0xe0, + 0x52, 0x3b, 0xad, 0x7e, 0x6b, 0xff, 0x50, 0x8c, 0x80, 0x79, 0xd8, 0x17, 0xcc, 0xc7, 0x6c, 0x7f, + 0xdc, 0xb8, 0x95, 0x9a, 0x72, 0x78, 0xd4, 0x6f, 0x64, 0xc4, 0x60, 0x77, 0xba, 0x9d, 0x7e, 0xa7, + 0xb5, 0x6f, 0x99, 0x87, 0xc7, 0x9d, 0xee, 0x53, 0xba, 0x84, 0x11, 0x19, 0xf4, 0xf1, 0xd1, 0xae, + 0x79, 0xd8, 0xed, 0x5b, 0xbd, 0xbd, 0xe3, 0xfe, 0x0e, 0x5e, 0xe1, 0xb8, 0x6d, 0x76, 0x8e, 0xa8, + 0xcc, 0xfc, 0x8b, 0x10, 0x44, 0xd1, 0x05, 0x31, 0x5d, 0x4f, 0x0f, 0x7b, 0xbd, 0xce, 0x91, 0xf5, + 0xf1, 0x71, 0xdb, 0xec, 0xb4, 0x7b, 0x98, 0x71, 0x21, 0x05, 0x2e, 0xf0, 0x8b, 0x82, 0xad, 0xf7, + 0xf7, 0x3f, 0x91, 0x7c, 0x57, 0xa0, 0x96, 0x92, 0x20, 0x81, 0x55, 0x16, 0x83, 0x29, 0x18, 0x57, + 0x4a, 0xc9, 0x70, 0x43, 0x9a, 0xc8, 0x57, 0x11, 0x2c, 0x79, 0x6e, 0x1e, 0x31, 0x5b, 0x35, 0x3d, + 0x49, 0xe4, 0x42, 0x6e, 0x1d, 0xed, 0x6d, 0x3b, 0x3b, 0x26, 0x66, 0xa8, 0xcf, 0x41, 0x05, 0xee, + 0xa2, 0x98, 0x28, 0xc1, 0xd9, 0x04, 0x4a, 0x43, 0x7d, 0x88, 0x94, 0xa5, 0x27, 0xbf, 0x9d, 0x83, + 0x3a, 0x85, 0xdb, 0xd1, 0xeb, 0x7c, 0xdc, 0x67, 0x07, 0x50, 0x94, 0xcf, 0x3c, 0xb2, 0xd5, 0xe8, + 0x7e, 0x3c, 0xfd, 0x61, 0xc9, 0x8d, 0xb5, 0x59, 0xb0, 0x94, 0xe4, 0x96, 0xff, 0xd6, 0x9f, 0xfd, + 0xcf, 0x7f, 0x94, 0xad, 0xb1, 0xca, 0xa3, 0x8b, 0xf7, 0x1e, 0x9d, 0x71, 0x37, 0x10, 0x65, 0xfc, + 0x1a, 0x40, 0xfc, 0x78, 0x21, 0x6b, 0x46, 0xf6, 0xab, 0x99, 0x97, 0x1d, 0x37, 0x6e, 0xa7, 0xa4, + 0xc8, 0x72, 0x6f, 0x63, 0xb9, 0xcb, 0x46, 0x5d, 0x94, 0xeb, 0xb8, 0x4e, 0x48, 0x0f, 0x19, 0x7e, + 0x98, 0x79, 0xc8, 0x86, 0x50, 0xd5, 0x9f, 0x15, 0x64, 0x4a, 0xc8, 0x4a, 0x79, 0x18, 0x71, 0xe3, + 0x4e, 0x6a, 0x9a, 0x12, 0x5f, 0xb1, 0x8e, 0x55, 0xa3, 0x21, 0xea, 0x98, 0x22, 0x46, 0x5c, 0xcb, + 0x88, 0x04, 0xfa, 0xf8, 0xf5, 0x40, 0xf6, 0x9a, 0x26, 0x92, 0xcd, 0xbd, 0x5d, 0xb8, 0x71, 0xf7, + 0x86, 0x54, 0x59, 0xd7, 0x5d, 0xac, 0x6b, 0xdd, 0x60, 0xa2, 0xae, 0x01, 0xe2, 0xa8, 0xb7, 0x0b, + 0x3f, 0xcc, 0x3c, 0x7c, 0xf2, 0x1f, 0xdf, 0x81, 0x72, 0xe4, 0x7e, 0xcb, 0x7e, 0x13, 0x6a, 0x89, + 0x78, 0x48, 0xa6, 0xba, 0x91, 0x16, 0x3e, 0xb9, 0xf1, 0x5a, 0x7a, 0xa2, 0xac, 0xf8, 0x75, 0xac, + 0xb8, 0xc9, 0xd6, 0x44, 0xc5, 0x32, 0xde, 0xf0, 0x11, 0xc6, 0x2f, 0xd3, 0x6d, 0x83, 0xcf, 0x35, + 0xc5, 0x85, 0x2a, 0x7b, 0x6d, 0x56, 0x99, 0x48, 0xd4, 0x76, 0xf7, 0x86, 0x54, 0x59, 0xdd, 0x6b, + 0x58, 0xdd, 0x1a, 0x5b, 0xd1, 0xab, 0x53, 0x5e, 0x9b, 0x8c, 0xe3, 0x0d, 0x9f, 0xfa, 0xe3, 0x7a, + 0xec, 0x6e, 0x7c, 0x1f, 0x63, 0xca, 0xa3, 0x7b, 0x11, 0x89, 0xcc, 0xbf, 0xbc, 0x67, 0x34, 0xb1, + 0x2a, 0xc6, 0x70, 0xfa, 0xf4, 0xb7, 0xf5, 0xd8, 0x09, 0x54, 0xb4, 0xf7, 0x68, 0xd8, 0xed, 0x1b, + 0xdf, 0xce, 0xd9, 0xd8, 0x48, 0x4b, 0x4a, 0xeb, 0x8a, 0x5e, 0xfe, 0xa3, 0x53, 0xce, 0xd9, 0xaf, + 0x42, 0x39, 0x7a, 0xe5, 0x84, 0xad, 0x6b, 0xaf, 0xce, 0xe8, 0xaf, 0xb2, 0x6c, 0x34, 0xe7, 0x13, + 0xd2, 0x88, 0x4f, 0x2f, 0x5d, 0x10, 0xdf, 0xa7, 0x50, 0xd1, 0x5e, 0x32, 0x89, 0x3a, 0x30, 0xff, + 0x5a, 0x4a, 0xd4, 0x81, 0x94, 0x87, 0x4f, 0x8c, 0x25, 0xac, 0xa2, 0xc2, 0xca, 0x48, 0xdf, 0xe1, + 0x95, 0x17, 0xb0, 0x7d, 0x58, 0x95, 0x4a, 0xda, 0x09, 0xff, 0x32, 0xd3, 0x90, 0xf2, 0x9e, 0xe1, + 0xe3, 0x0c, 0xfb, 0x08, 0x4a, 0xea, 0xc1, 0x1a, 0xb6, 0x96, 0xfe, 0xf0, 0xce, 0xc6, 0xfa, 0x1c, + 0x5c, 0x6a, 0x54, 0x9f, 0x01, 0xc4, 0xcf, 0xa6, 0x44, 0x4c, 0x62, 0xee, 0x19, 0x96, 0x88, 0x02, + 0xe6, 0xdf, 0x58, 0x31, 0xd6, 0xb0, 0x83, 0x0d, 0x86, 0x4c, 0xc2, 0xe5, 0x97, 0xea, 0x1a, 0xe6, + 0x1f, 0x42, 0x45, 0x7b, 0x39, 0x25, 0x1a, 0xbe, 0xf9, 0x57, 0x57, 0xa2, 0xe1, 0x4b, 0x79, 0x68, + 0xc5, 0xd8, 0xc0, 0xd2, 0x57, 0x8c, 0x45, 0x51, 0xba, 0x90, 0xd2, 0xa4, 0xb4, 0x24, 0x26, 0xe8, + 0x1c, 0x6a, 0x89, 0xe7, 0x51, 0xa2, 0x15, 0x9a, 0xf6, 0xf8, 0x4a, 0xb4, 0x42, 0x53, 0x5f, 0x54, + 0x51, 0x74, 0x66, 0x2c, 0x89, 0x7a, 0xe8, 0x26, 0x26, 0xad, 0xa6, 0x1f, 0x40, 0x45, 0x7b, 0xea, + 0x24, 0xea, 0xcb, 0xfc, 0xab, 0x2a, 0x51, 0x5f, 0xd2, 0x5e, 0x46, 0x59, 0xc1, 0x3a, 0xea, 0x06, + 0x92, 0x02, 0x5e, 0x24, 0x2b, 0xca, 0xfe, 0x4d, 0xa8, 0x27, 0x5f, 0x3f, 0x89, 0xd6, 0x7e, 0xea, + 0x33, 0x2a, 0xd1, 0xda, 0xbf, 0xe1, 0xc9, 0x14, 0x49, 0xd2, 0x0f, 0x97, 0xa3, 0x4a, 0x1e, 0xfd, + 0x58, 0x06, 0x12, 0x7d, 0xc1, 0x3e, 0x16, 0x0c, 0x4e, 0xde, 0x63, 0xcc, 0xd6, 0x35, 0xaa, 0xd5, + 0x2f, 0x44, 0x8e, 0xd6, 0xcb, 0xdc, 0x95, 0xc7, 0x49, 0x62, 0xc6, 0xc2, 0xd9, 0x53, 0x58, 0x8e, + 0x88, 0x39, 0xba, 0x98, 0x38, 0x88, 0xfa, 0x90, 0x7a, 0xfd, 0xf1, 0x46, 0x63, 0x36, 0xf5, 0x71, + 0x86, 0xb6, 0x3f, 0xbc, 0x0e, 0x56, 0xdb, 0xfe, 0xf4, 0xbb, 0x89, 0xb5, 0xed, 0x2f, 0x71, 0x6b, + 0xec, 0xec, 0xf6, 0x17, 0x3a, 0xa2, 0x0c, 0x17, 0x16, 0x67, 0xaf, 0x09, 0xbe, 0x7b, 0xd3, 0x45, + 0x0d, 0x54, 0xfc, 0xeb, 0x2f, 0xbe, 0xc7, 0x21, 0xc9, 0x8a, 0x14, 0x37, 0x7d, 0x24, 0xfd, 0x56, + 0xd8, 0xaf, 0x43, 0x55, 0x7f, 0x31, 0x81, 0xe9, 0x3c, 0x61, 0xb6, 0xa6, 0x3b, 0xa9, 0x69, 0x49, + 0x2a, 0x61, 0x55, 0xbd, 0x1a, 0xf6, 0x09, 0xac, 0x45, 0xc3, 0xac, 0xdf, 0x34, 0x10, 0xb0, 0x7b, + 0x29, 0xf7, 0x0f, 0x24, 0x06, 0xfb, 0xf6, 0x8d, 0x17, 0x14, 0x3c, 0xce, 0x08, 0xea, 0x4b, 0x5e, + 0xdd, 0x1e, 0xef, 0x3c, 0x69, 0x37, 0xd6, 0xc7, 0x3b, 0x4f, 0xea, 0x7d, 0xef, 0x8a, 0xfa, 0xd8, + 0x72, 0x62, 0x8c, 0xc8, 0xa3, 0x97, 0xfd, 0x00, 0x16, 0xb5, 0x6b, 0x14, 0x7a, 0xd7, 0xee, 0x20, + 0x5a, 0x49, 0xf3, 0x17, 0x80, 0x6e, 0xa4, 0x1d, 0x6b, 0x1a, 0xeb, 0x58, 0xfe, 0x92, 0x91, 0x18, + 0x1c, 0xb1, 0x8a, 0xb6, 0xa1, 0xa2, 0x5f, 0xd1, 0xf0, 0x82, 0x72, 0xd7, 0xb5, 0x24, 0xfd, 0xae, + 0xc9, 0xc7, 0x19, 0xb6, 0x0f, 0x8d, 0xd9, 0xeb, 0xcf, 0x22, 0x9e, 0x92, 0x76, 0x65, 0xdc, 0xc6, + 0x4c, 0x62, 0xe2, 0xd2, 0x34, 0x76, 0x44, 0x31, 0x21, 0xd1, 0xe3, 0x7f, 0x9e, 0x3f, 0xbb, 0xab, + 0x27, 0x1f, 0x05, 0x8c, 0x4a, 0x4b, 0x7b, 0x0e, 0xf2, 0x41, 0xe6, 0x71, 0x86, 0xfd, 0x6e, 0x06, + 0xaa, 0x89, 0x0b, 0x85, 0x12, 0x5e, 0xf7, 0x33, 0xfd, 0x6c, 0xea, 0x69, 0x7a, 0x47, 0x0d, 0x13, + 0x07, 0x71, 0xff, 0xe1, 0xf7, 0x13, 0x93, 0xf4, 0xe3, 0x84, 0x55, 0x70, 0x73, 0xf6, 0x75, 0xc0, + 0x2f, 0x66, 0x11, 0xf4, 0x2b, 0x65, 0xbf, 0x78, 0x9c, 0x61, 0xff, 0x36, 0x03, 0xf5, 0xa4, 0xb9, + 0x3f, 0xea, 0x6e, 0xaa, 0x63, 0x41, 0x44, 0x4a, 0x37, 0xf8, 0x08, 0xfc, 0x00, 0x5b, 0xd9, 0x7f, + 0x68, 0x26, 0x5a, 0x29, 0x1f, 0x1d, 0xf8, 0xd9, 0x5a, 0xcb, 0x3e, 0xa4, 0xc7, 0x78, 0x95, 0x17, + 0x14, 0x9b, 0x7f, 0xbc, 0x35, 0x22, 0x3f, 0xfd, 0xa9, 0x53, 0x9c, 0x84, 0x1f, 0xd2, 0x2b, 0x78, + 0xca, 0xa9, 0x46, 0x50, 0xf1, 0xab, 0xe6, 0x37, 0xde, 0xc4, 0x3e, 0xbd, 0x6e, 0xdc, 0x4e, 0xf4, + 0x69, 0x56, 0xf0, 0x68, 0x51, 0xeb, 0xe4, 0x4b, 0xa5, 0xf1, 0xce, 0x39, 0xf7, 0x7a, 0xe9, 0xcd, + 0x8d, 0x1c, 0x53, 0x23, 0x25, 0x7a, 0x62, 0xa9, 0xbd, 0x62, 0x31, 0xc6, 0x43, 0x6c, 0xeb, 0x9b, + 0xc6, 0xbd, 0x1b, 0xdb, 0xfa, 0x08, 0x4d, 0xf7, 0xa2, 0xc5, 0x47, 0x00, 0xb1, 0x97, 0x22, 0x9b, + 0xf1, 0x95, 0x8b, 0x18, 0xd0, 0xbc, 0x23, 0x63, 0x72, 0x3d, 0x2b, 0x97, 0x3a, 0x51, 0xe2, 0xaf, + 0x12, 0x3b, 0x8d, 0xbc, 0xf8, 0x74, 0xe9, 0x2b, 0xe9, 0x50, 0x98, 0x90, 0xbe, 0x66, 0xcb, 0x4f, + 0x30, 0xd3, 0xc8, 0x65, 0xef, 0x18, 0x6a, 0xfb, 0x9e, 0xf7, 0x7c, 0x3a, 0x89, 0x3c, 0xe3, 0x93, + 0xfe, 0x34, 0x7b, 0x76, 0x70, 0xbe, 0x31, 0xd3, 0x0b, 0xe3, 0x3e, 0x16, 0xb5, 0xc1, 0x9a, 0x5a, + 0x51, 0x8f, 0x7e, 0x1c, 0xbb, 0x46, 0x7e, 0xc1, 0x6c, 0x58, 0x8a, 0x78, 0x74, 0xec, 0x7e, 0x98, + 0x2c, 0x26, 0xc1, 0x99, 0x67, 0xab, 0x48, 0xa8, 0x09, 0xaa, 0xb5, 0x8f, 0x02, 0x55, 0xe6, 0xe3, + 0x0c, 0x3b, 0x82, 0xea, 0x0e, 0x1f, 0xe0, 0xd5, 0x0a, 0xe8, 0x95, 0xb2, 0x9c, 0xf0, 0x70, 0x20, + 0x77, 0x96, 0x8d, 0x5a, 0x02, 0x98, 0xdc, 0xb7, 0x26, 0xf6, 0xb5, 0xcf, 0x3f, 0x7f, 0xf4, 0x63, + 0xe9, 0xef, 0xf2, 0x85, 0xda, 0xb7, 0x94, 0x3f, 0x50, 0x62, 0xdf, 0x9a, 0x71, 0x20, 0x4a, 0xec, + 0x5b, 0x73, 0x0e, 0x44, 0x89, 0xa1, 0x56, 0xfe, 0x48, 0x6c, 0x04, 0x4b, 0x73, 0x3e, 0x47, 0xd1, + 0x96, 0x75, 0x93, 0xa7, 0xd2, 0xc6, 0xfd, 0x9b, 0x11, 0x92, 0xb5, 0x3d, 0x4c, 0xd6, 0xd6, 0x83, + 0x1a, 0xdd, 0x17, 0x7b, 0xc2, 0x29, 0xc8, 0x72, 0xe6, 0x86, 0x22, 0x3d, 0x82, 0x73, 0x76, 0x83, + 0xc1, 0xb4, 0xa4, 0x84, 0x83, 0x61, 0x76, 0xec, 0x14, 0x1f, 0x49, 0xd0, 0xa2, 0x1a, 0x23, 0x62, + 0x9c, 0x8f, 0xb4, 0x8c, 0x88, 0x31, 0x25, 0x08, 0x52, 0xa9, 0x9f, 0x6c, 0x35, 0x2a, 0xfb, 0x91, + 0xeb, 0x0d, 0xf9, 0x58, 0x96, 0xfa, 0xab, 0x50, 0x79, 0xca, 0x43, 0x15, 0x46, 0x18, 0xc9, 0xf2, + 0x33, 0x71, 0x85, 0x1b, 0x29, 0xc1, 0x9f, 0x49, 0xda, 0xa4, 0x92, 0xf9, 0xf0, 0x8c, 0x13, 0x13, + 0xb4, 0x9c, 0xe1, 0x17, 0xec, 0x57, 0xb0, 0xf0, 0x28, 0x68, 0x7e, 0x4d, 0x6b, 0xa6, 0x5e, 0xf8, + 0xe2, 0x0c, 0x3c, 0xad, 0x64, 0xd1, 0x66, 0x4d, 0xa6, 0x74, 0xa1, 0xa2, 0x5d, 0xae, 0x11, 0x8d, + 0xcd, 0xfc, 0x65, 0x2a, 0xd1, 0xd8, 0xa4, 0xdc, 0xc5, 0x61, 0x3c, 0xc0, 0x7a, 0x0c, 0x76, 0x3f, + 0xae, 0x87, 0xee, 0xdf, 0x88, 0x6b, 0x7a, 0xf4, 0x63, 0x7b, 0x1c, 0x7e, 0xc1, 0x3e, 0xa5, 0xe9, + 0xd0, 0xc2, 0x24, 0x63, 0xe5, 0x64, 0x36, 0xa2, 0x32, 0x1a, 0x2c, 0x2d, 0x29, 0xa9, 0xb0, 0x50, + 0x55, 0x28, 0x31, 0xbe, 0x0f, 0xd0, 0x0b, 0xbd, 0xc9, 0x8e, 0xcd, 0xc7, 0x9e, 0x1b, 0xf3, 0xf4, + 0x38, 0x70, 0x2f, 0xe6, 0x93, 0x5a, 0xf4, 0x1e, 0xfb, 0x54, 0xd3, 0xe6, 0x12, 0x01, 0xbe, 0x8a, + 0x88, 0x6f, 0x8c, 0xed, 0x8b, 0x06, 0x24, 0x25, 0xbe, 0xef, 0x71, 0x86, 0xb5, 0x00, 0x62, 0xe7, + 0xb6, 0x48, 0x37, 0x9b, 0xf3, 0x9b, 0x8b, 0xd8, 0x6b, 0x8a, 0x27, 0xdc, 0x11, 0x94, 0x63, 0xaf, + 0xa0, 0xf5, 0xf8, 0xae, 0xa0, 0x84, 0x0f, 0x51, 0x24, 0x29, 0xcc, 0x79, 0xe4, 0x18, 0x0d, 0x1c, + 0x2a, 0x60, 0x25, 0x31, 0x54, 0xa7, 0x9c, 0x07, 0xcc, 0x81, 0x65, 0x6a, 0x60, 0x24, 0x96, 0x61, + 0xc0, 0x59, 0xf4, 0x34, 0xc9, 0xbc, 0x73, 0x4c, 0xc4, 0x35, 0x52, 0x5d, 0x3c, 0x12, 0x47, 0x4c, + 0x82, 0x5a, 0x29, 0xd8, 0x4d, 0x6c, 0x01, 0x63, 0x58, 0x9a, 0xf3, 0x22, 0x88, 0x58, 0xc7, 0x4d, + 0x6e, 0x21, 0x11, 0xeb, 0xb8, 0xd1, 0x01, 0xc1, 0x58, 0xc5, 0x2a, 0x17, 0x0d, 0x40, 0x95, 0xf2, + 0xd2, 0x09, 0x07, 0xe7, 0xa2, 0xba, 0xdf, 0xcf, 0xc0, 0x72, 0x8a, 0x9f, 0x00, 0x7b, 0x43, 0x9d, + 0x4e, 0xdc, 0xe8, 0x43, 0xb0, 0x91, 0x6a, 0x4f, 0x36, 0x7a, 0x58, 0xcf, 0x01, 0x7b, 0x96, 0xd8, + 0x40, 0xc9, 0x9c, 0x2b, 0x57, 0xe6, 0x0b, 0x85, 0x97, 0x54, 0xc9, 0xe5, 0x73, 0x58, 0xa7, 0x86, + 0xb4, 0x46, 0xa3, 0x19, 0x5b, 0xf7, 0xeb, 0x5a, 0x2b, 0x52, 0xec, 0xf7, 0x09, 0x3d, 0x20, 0x69, + 0xc3, 0xbf, 0x41, 0x6c, 0xa7, 0xa6, 0xb2, 0x29, 0x34, 0x66, 0x6d, 0xc8, 0xec, 0xe6, 0xb2, 0x36, + 0xee, 0x25, 0xf4, 0xec, 0x14, 0xbb, 0xf3, 0x57, 0xb1, 0xb2, 0x7b, 0xc6, 0x46, 0xda, 0xb8, 0x90, + 0xea, 0x2d, 0xe6, 0xe3, 0x6f, 0x46, 0x06, 0xef, 0x99, 0x7e, 0xde, 0x8b, 0x2e, 0x63, 0x4f, 0x37, + 0xcf, 0x47, 0x9a, 0x7e, 0xba, 0xbd, 0xfc, 0x2d, 0xac, 0xfe, 0xbe, 0x71, 0x27, 0xad, 0x7a, 0x9f, + 0xb2, 0x90, 0xce, 0xbf, 0x3e, 0xbb, 0xae, 0x55, 0x0b, 0xee, 0xa7, 0xcd, 0xf7, 0x8d, 0x3a, 0xd7, + 0xcc, 0x58, 0xdf, 0x42, 0x19, 0xb2, 0xaa, 0x1b, 0xb8, 0xa3, 0xe5, 0x93, 0x62, 0x49, 0x8f, 0x96, + 0x4f, 0x9a, 0x45, 0x3c, 0x29, 0x3f, 0x29, 0x5b, 0xf8, 0x87, 0x99, 0x87, 0x5b, 0x6f, 0xff, 0xe0, + 0xab, 0x67, 0x4e, 0x78, 0x3e, 0x3d, 0xd9, 0x1c, 0x78, 0xe3, 0x47, 0x23, 0x75, 0xaa, 0x29, 0xa3, + 0xb2, 0x1f, 0x8d, 0xdc, 0xe1, 0x23, 0x2c, 0xf6, 0x64, 0x61, 0xe2, 0x7b, 0xa1, 0xf7, 0x8d, 0xff, + 0x17, 0x00, 0x00, 0xff, 0xff, 0x66, 0xe1, 0x62, 0xc2, 0xf7, 0x88, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 410fb20cad..b7003395b2 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1775,6 +1775,28 @@ message PendingUpdate { uint32 output_index = 2; } +message ReadyForPsbtFunding { + /** + The P2WSH address of the channel funding multisig address that the below + specified amount in satoshis needs to be sent to. + */ + string funding_address = 1; + + /** + The exact amount in satoshis that needs to be sent to the above address to + fund the pending channel. + */ + int64 funding_amount = 2; + + /** + A raw PSBT that contains the pending channel output. If a base PSBT was + provided in the PsbtShim, this is the base PSBT with one additional output. + If no base PSBT was specified, this is an otherwise empty PSBT with exactly + one output. + */ + bytes psbt = 3; +} + message OpenChannelRequest { /** The pubkey of the node to open a channel with. When using REST, this field @@ -1846,8 +1868,23 @@ message OpenChannelRequest { } message OpenStatusUpdate { oneof update { + /** + Signals that the channel is now fully negotiated and the funding + transaction published. + */ PendingUpdate chan_pending = 1; + + /** + Signals that the channel's funding transaction has now reached the + required number of confirmations on chain and can be used. + */ ChannelOpenUpdate chan_open = 3; + + /** + Signals that the funding process has been suspended and the construction + of a PSBT that funds the channel PK script is now required. + */ + ReadyForPsbtFunding psbt_fund = 5; } /** @@ -1910,9 +1947,34 @@ message ChanPointShim { uint32 thaw_height = 6; } +message PsbtShim { + /** + A unique identifier of 32 random bytes that will be used as the pending + channel ID to identify the PSBT state machine when interacting with it and + on the wire protocol to initiate the funding request. + */ + bytes pending_chan_id = 1; + + /** + An optional base PSBT the new channel output will be added to. If this is + non-empty, it must be a binary serialized PSBT. + */ + bytes base_psbt = 2; +} + message FundingShim { oneof shim { + /** + A channel shim where the channel point was fully constructed outside + of lnd's wallet and the transaction might already be published. + */ ChanPointShim chan_point_shim = 1; + + /** + A channel shim that uses a PSBT to fund and sign the channel funding + transaction. + */ + PsbtShim psbt_shim = 2; } } @@ -1921,17 +1983,56 @@ message FundingShimCancel { bytes pending_chan_id = 1; } +message FundingPsbtVerify { + /** + The funded but not yet signed PSBT that sends the exact channel capacity + amount to the PK script returned in the open channel message in a previous + step. + */ + bytes funded_psbt = 1; + + /// The pending channel ID of the channel to get the PSBT for. + bytes pending_chan_id = 2; +} + +message FundingPsbtFinalize { + /** + The funded PSBT that contains all witness data to send the exact channel + capacity amount to the PK script returned in the open channel message in a + previous step. + */ + bytes signed_psbt = 1; + + /// The pending channel ID of the channel to get the PSBT for. + bytes pending_chan_id = 2; +} + message FundingTransitionMsg { oneof trigger { /** - The funding shim to regsiter. This should be used before any + The funding shim to register. This should be used before any channel funding has began by the remote party, as it is intended as a - prepatory step for the full channel funding. + preparatory step for the full channel funding. */ FundingShim shim_register = 1; /// Used to cancel an existing registered funding shim. FundingShimCancel shim_cancel = 2; + + /** + Used to continue a funding flow that was initiated to be executed + through a PSBT. This step verifies that the PSBT contains the correct + outputs to fund the channel. + */ + FundingPsbtVerify psbt_verify = 3; + + /** + Used to continue a funding flow that was initiated to be executed + through a PSBT. This step finalizes the funded and signed PSBT, finishes + negotiation with the peer and finally publishes the resulting funding + transaction. + */ + FundingPsbtFinalize psbt_finalize = 4; } } diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 22fb90ce22..173c8c2d38 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -2825,11 +2825,46 @@ } } }, + "lnrpcFundingPsbtFinalize": { + "type": "object", + "properties": { + "signed_psbt": { + "type": "string", + "format": "byte", + "description": "*\nThe funded PSBT that contains all witness data to send the exact channel\ncapacity amount to the PK script returned in the open channel message in a\nprevious step." + }, + "pending_chan_id": { + "type": "string", + "format": "byte", + "description": "/ The pending channel ID of the channel to get the PSBT for." + } + } + }, + "lnrpcFundingPsbtVerify": { + "type": "object", + "properties": { + "funded_psbt": { + "type": "string", + "format": "byte", + "description": "*\nThe funded but not yet signed PSBT that sends the exact channel capacity\namount to the PK script returned in the open channel message in a previous\nstep." + }, + "pending_chan_id": { + "type": "string", + "format": "byte", + "description": "/ The pending channel ID of the channel to get the PSBT for." + } + } + }, "lnrpcFundingShim": { "type": "object", "properties": { "chan_point_shim": { - "$ref": "#/definitions/lnrpcChanPointShim" + "$ref": "#/definitions/lnrpcChanPointShim", + "description": "*\nA channel shim where the channel point was fully constructed outside\nof lnd's wallet and the transaction might already be published." + }, + "psbt_shim": { + "$ref": "#/definitions/lnrpcPsbtShim", + "description": "*\nA channel shim that uses a PSBT to fund and sign the channel funding\ntransaction." } } }, @@ -3753,10 +3788,16 @@ "type": "object", "properties": { "chan_pending": { - "$ref": "#/definitions/lnrpcPendingUpdate" + "$ref": "#/definitions/lnrpcPendingUpdate", + "description": "*\nSignals that the channel is now fully negotiated and the funding\ntransaction published." }, "chan_open": { - "$ref": "#/definitions/lnrpcChannelOpenUpdate" + "$ref": "#/definitions/lnrpcChannelOpenUpdate", + "description": "*\nSignals that the channel's funding transaction has now reached the\nrequired number of confirmations on chain and can be used." + }, + "psbt_fund": { + "$ref": "#/definitions/lnrpcReadyForPsbtFunding", + "description": "*\nSignals that the funding process has been suspended and the construction\nof a PSBT that funds the channel PK script is now required." }, "pending_chan_id": { "type": "string", @@ -4120,6 +4161,21 @@ "lnrpcPolicyUpdateResponse": { "type": "object" }, + "lnrpcPsbtShim": { + "type": "object", + "properties": { + "pending_chan_id": { + "type": "string", + "format": "byte", + "description": "*\nA unique identifier of 32 random bytes that will be used as the pending\nchannel ID to identify the PSBT state machine when interacting with it and\non the wire protocol to initiate the funding request." + }, + "base_psbt": { + "type": "string", + "format": "byte", + "description": "*\nAn optional base PSBT the new channel output will be added to. If this is\nnon-empty, it must be a binary serialized PSBT." + } + } + }, "lnrpcQueryRoutesResponse": { "type": "object", "properties": { @@ -4137,6 +4193,25 @@ } } }, + "lnrpcReadyForPsbtFunding": { + "type": "object", + "properties": { + "funding_address": { + "type": "string", + "description": "*\nThe P2WSH address of the channel funding multisig address that the below\nspecified amount in satoshis needs to be sent to." + }, + "funding_amount": { + "type": "string", + "format": "int64", + "description": "*\nThe exact amount in satoshis that needs to be sent to the above address to\nfund the pending channel." + }, + "psbt": { + "type": "string", + "format": "byte", + "description": "*\nA raw PSBT that contains the pending channel output. If a base PSBT was\nprovided in the PsbtShim, this is the base PSBT with one additional output.\nIf no base PSBT was specified, this is an otherwise empty PSBT with exactly\none output." + } + } + }, "lnrpcRestoreBackupResponse": { "type": "object" }, From 126f79dbb14be5f66eff5a810d92ea68c1503892 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:15 +0200 Subject: [PATCH 332/562] chanfunding: add PSBT assembler and intent We add a new funding assembler and intent type that handle channel funding through the use of a PSBT. The PsbtIntent is in itself a simple state machine that can be stepped through the process of assembling the required information for the funding output, verifying a user supplied PSBT for correctness, accepting a fully signed PSBT and then assembling the funding wire message. --- lnwallet/chanfunding/assembler.go | 2 +- lnwallet/chanfunding/psbt_assembler.go | 524 ++++++++++++++++++ lnwallet/chanfunding/psbt_assembler_test.go | 577 ++++++++++++++++++++ 3 files changed, 1102 insertions(+), 1 deletion(-) create mode 100644 lnwallet/chanfunding/psbt_assembler.go create mode 100644 lnwallet/chanfunding/psbt_assembler_test.go diff --git a/lnwallet/chanfunding/assembler.go b/lnwallet/chanfunding/assembler.go index d06de903dc..208cab68bb 100644 --- a/lnwallet/chanfunding/assembler.go +++ b/lnwallet/chanfunding/assembler.go @@ -126,7 +126,7 @@ type Assembler interface { // FundingTxAssembler is a super-set of the regular Assembler interface that's // also able to provide a fully populated funding transaction via the intents -// that it produuces. +// that it produces. type FundingTxAssembler interface { Assembler diff --git a/lnwallet/chanfunding/psbt_assembler.go b/lnwallet/chanfunding/psbt_assembler.go new file mode 100644 index 0000000000..a65cc624a2 --- /dev/null +++ b/lnwallet/chanfunding/psbt_assembler.go @@ -0,0 +1,524 @@ +package chanfunding + +import ( + "bytes" + "crypto/sha256" + "errors" + "fmt" + "sync" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/psbt" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" +) + +// PsbtState is a type for the state of the PSBT intent state machine. +type PsbtState uint8 + +const ( + // PsbtShimRegistered denotes a channel funding process has started with + // a PSBT shim attached. This is the default state for a PsbtIntent. We + // don't use iota here because the values have to be in sync with the + // RPC constants. + PsbtShimRegistered PsbtState = 1 + + // PsbtOutputKnown denotes that the local and remote peer have + // negotiated the multisig keys to be used as the channel funding output + // and therefore the PSBT funding process can now start. + PsbtOutputKnown PsbtState = 2 + + // PsbtVerified denotes that a potential PSBT has been presented to the + // intent and passed all checks. The verified PSBT can be given to a/the + // signer(s). + PsbtVerified PsbtState = 3 + + // PsbtFinalized denotes that a fully signed PSBT has been given to the + // intent that looks identical to the previously verified transaction + // but has all witness data added and is therefore completely signed. + PsbtFinalized PsbtState = 4 + + // PsbtFundingTxCompiled denotes that the PSBT processed by this intent + // has been successfully converted into a protocol transaction. It is + // not yet completely certain that the resulting transaction will be + // published because the commitment transactions between the channel + // peers first need to be counter signed. But the job of the intent is + // hereby completed. + PsbtFundingTxCompiled PsbtState = 5 + + // PsbtInitiatorCanceled denotes that the user has canceled the intent. + PsbtInitiatorCanceled PsbtState = 6 + + // PsbtResponderCanceled denotes that the remote peer has canceled the + // funding, likely due to a timeout. + PsbtResponderCanceled PsbtState = 7 +) + +// String returns a string representation of the PsbtState. +func (s PsbtState) String() string { + switch s { + case PsbtShimRegistered: + return "shim_registered" + + case PsbtOutputKnown: + return "output_known" + + case PsbtVerified: + return "verified" + + case PsbtFinalized: + return "finalized" + + case PsbtFundingTxCompiled: + return "funding_tx_compiled" + + case PsbtInitiatorCanceled: + return "user_canceled" + + case PsbtResponderCanceled: + return "remote_canceled" + + default: + return fmt.Sprintf("", s) + } +} + +var ( + // ErrRemoteCanceled is the error that is returned to the user if the + // funding flow was canceled by the remote peer. + ErrRemoteCanceled = errors.New("remote canceled funding, possibly " + + "timed out") + + // ErrUserCanceled is the error that is returned through the PsbtReady + // channel if the user canceled the funding flow. + ErrUserCanceled = errors.New("user canceled funding") +) + +// PsbtIntent is an intent created by the PsbtAssembler which represents a +// funding output to be created by a PSBT. This might be used when a hardware +// wallet, or a channel factory is the entity crafting the funding transaction, +// and not lnd. +type PsbtIntent struct { + // ShimIntent is the wrapped basic intent that contains common fields + // we also use in the PSBT funding case. + ShimIntent + + // State is the current state the intent state machine is in. + State PsbtState + + // BasePsbt is the user-supplied base PSBT the channel output should be + // added to. If this is nil we will create a new, empty PSBT as the base + // for the funding transaction. + BasePsbt *psbt.Packet + + // PendingPsbt is the parsed version of the current PSBT. This can be + // in two stages: If the user has not yet provided any PSBT, this is + // nil. Once the user sends us an unsigned funded PSBT, we verify that + // we have a valid transaction that sends to the channel output PK + // script and has an input large enough to pay for it. We keep this + // verified but not yet signed version around until the fully signed + // transaction is submitted by the user. At that point we make sure the + // inputs and outputs haven't changed to what was previously verified. + // Only witness data should be added after the verification process. + PendingPsbt *psbt.Packet + + // PsbtReady is an error channel the funding manager will listen for + // a signal about the PSBT being ready to continue the funding flow. In + // the normal, happy flow, this channel is only ever closed. If a + // non-nil error is sent through the channel, the funding flow will be + // canceled. + // + // NOTE: This channel must always be buffered. + PsbtReady chan error + + // signalPsbtReady is a Once guard to make sure the PsbtReady channel is + // only closed exactly once. + signalPsbtReady sync.Once + + // netParams are the network parameters used to encode the P2WSH funding + // address. + netParams *chaincfg.Params +} + +// BindKeys sets both the remote and local node's keys that will be used for the +// channel funding multisig output. +func (i *PsbtIntent) BindKeys(localKey *keychain.KeyDescriptor, + remoteKey *btcec.PublicKey) { + + i.localKey = localKey + i.remoteKey = remoteKey + i.State = PsbtOutputKnown +} + +// FundingParams returns the parameters that are necessary to start funding the +// channel output this intent was created for. It returns the P2WSH funding +// address, the exact funding amount and a PSBT packet that contains exactly one +// output that encodes the previous two parameters. +func (i *PsbtIntent) FundingParams() (btcutil.Address, int64, *psbt.Packet, + error) { + + if i.State != PsbtOutputKnown { + return nil, 0, nil, fmt.Errorf("invalid state, got %v "+ + "expected %v", i.State, PsbtOutputKnown) + } + + // The funding output needs to be known already at this point, which + // means we need to have the local and remote multisig keys bound + // already. + witnessScript, out, err := i.FundingOutput() + if err != nil { + return nil, 0, nil, fmt.Errorf("unable to create funding "+ + "output: %v", err) + } + witnessScriptHash := sha256.Sum256(witnessScript) + + // Encode the address in the human readable bech32 format. + addr, err := btcutil.NewAddressWitnessScriptHash( + witnessScriptHash[:], i.netParams, + ) + if err != nil { + return nil, 0, nil, fmt.Errorf("unable to encode address: %v", + err) + } + + // We'll also encode the address/amount in a machine readable raw PSBT + // format. If the user supplied a base PSBT, we'll add the output to + // that one, otherwise we'll create a new one. + packet := i.BasePsbt + if packet == nil { + packet, err = psbt.New(nil, nil, 2, 0, nil) + if err != nil { + return nil, 0, nil, fmt.Errorf("unable to create "+ + "PSBT: %v", err) + } + } + packet.UnsignedTx.TxOut = append(packet.UnsignedTx.TxOut, out) + packet.Outputs = append(packet.Outputs, psbt.POutput{}) + return addr, out.Value, packet, nil +} + +// Verify makes sure the PSBT that is given to the intent has an output that +// sends to the channel funding multisig address with the correct amount. A +// simple check that at least a single input has been specified is performed. +func (i *PsbtIntent) Verify(packet *psbt.Packet) error { + if packet == nil { + return fmt.Errorf("PSBT is nil") + } + if i.State != PsbtOutputKnown { + return fmt.Errorf("invalid state. got %v expected %v", i.State, + PsbtOutputKnown) + } + + // Try to locate the channel funding multisig output. + _, expectedOutput, err := i.FundingOutput() + if err != nil { + return fmt.Errorf("funding output cannot be created: %v", err) + } + outputFound := false + outputSum := int64(0) + for _, out := range packet.UnsignedTx.TxOut { + outputSum += out.Value + if txOutsEqual(out, expectedOutput) { + outputFound = true + } + } + if !outputFound { + return fmt.Errorf("funding output not found in PSBT") + } + + // At least one input needs to be specified and it must be large enough + // to pay for all outputs. We don't want to dive into fee estimation + // here so we just assume that if the input amount exceeds the output + // amount, the chosen fee is sufficient. + if len(packet.UnsignedTx.TxIn) == 0 { + return fmt.Errorf("PSBT has no inputs") + } + sum, err := sumUtxoInputValues(packet) + if err != nil { + return fmt.Errorf("error determining input sum: %v", err) + } + if sum <= outputSum { + return fmt.Errorf("input amount sum must be larger than " + + "output amount sum") + } + + i.PendingPsbt = packet + i.State = PsbtVerified + return nil +} + +// Finalize makes sure the final PSBT that is given to the intent is fully valid +// and signed but still contains the same UTXOs and outputs as the pending +// transaction we previously verified. If everything checks out, the funding +// manager is informed that the channel can now be opened and the funding +// transaction be broadcast. +func (i *PsbtIntent) Finalize(packet *psbt.Packet) error { + if packet == nil { + return fmt.Errorf("PSBT is nil") + } + if i.State != PsbtVerified { + return fmt.Errorf("invalid state. got %v expected %v", i.State, + PsbtVerified) + } + + // Make sure the PSBT itself thinks it's finalized and ready to be + // broadcast. + err := psbt.MaybeFinalizeAll(packet) + if err != nil { + return fmt.Errorf("error finalizing PSBT: %v", err) + } + _, err = psbt.Extract(packet) + if err != nil { + return fmt.Errorf("unable to extract funding TX: %v", err) + } + + // Do a basic check that this is still the same PSBT that we verified in + // the previous step. This is to protect the user from unwanted + // modifications. We only check the outputs and previous outpoints of + // the inputs of the wire transaction because the fields in the PSBT + // part are allowed to change. + if i.PendingPsbt == nil { + return fmt.Errorf("PSBT was not verified first") + } + err = verifyOutputsEqual( + packet.UnsignedTx.TxOut, i.PendingPsbt.UnsignedTx.TxOut, + ) + if err != nil { + return fmt.Errorf("outputs differ from verified PSBT: %v", err) + } + err = verifyInputPrevOutpointsEqual( + packet.UnsignedTx.TxIn, i.PendingPsbt.UnsignedTx.TxIn, + ) + if err != nil { + return fmt.Errorf("inputs differ from verified PSBT: %v", err) + } + + // As far as we can tell, this PSBT is ok to be used as a funding + // transaction. + i.PendingPsbt = packet + i.State = PsbtFinalized + + // Signal the funding manager that it can now finally continue with its + // funding flow as the PSBT is now ready to be converted into a real + // transaction and be published. + i.signalPsbtReady.Do(func() { + close(i.PsbtReady) + }) + return nil +} + +// CompileFundingTx finalizes the previously verified PSBT and returns the +// extracted binary serialized transaction from it. It also prepares the channel +// point for which this funding intent was initiated for. +func (i *PsbtIntent) CompileFundingTx() (*wire.MsgTx, error) { + if i.State != PsbtFinalized { + return nil, fmt.Errorf("invalid state. got %v expected %v", + i.State, PsbtFinalized) + } + + // Make sure the PSBT can be finalized and extracted. + err := psbt.MaybeFinalizeAll(i.PendingPsbt) + if err != nil { + return nil, fmt.Errorf("error finalizing PSBT: %v", err) + } + fundingTx, err := psbt.Extract(i.PendingPsbt) + if err != nil { + return nil, fmt.Errorf("unable to extract funding TX: %v", err) + } + + // Identify our funding outpoint now that we know everything's ready. + _, txOut, err := i.FundingOutput() + if err != nil { + return nil, fmt.Errorf("cannot get funding output: %v", err) + } + ok, idx := input.FindScriptOutputIndex(fundingTx, txOut.PkScript) + if !ok { + return nil, fmt.Errorf("funding output not found in PSBT") + } + i.chanPoint = &wire.OutPoint{ + Hash: fundingTx.TxHash(), + Index: idx, + } + i.State = PsbtFundingTxCompiled + + return fundingTx, nil +} + +// RemoteCanceled informs the listener of the PSBT ready channel that the +// funding has been canceled by the remote peer and that we can no longer +// continue with it. +func (i *PsbtIntent) RemoteCanceled() { + log.Debugf("PSBT funding intent canceled by remote, state=%v", i.State) + i.signalPsbtReady.Do(func() { + i.PsbtReady <- ErrRemoteCanceled + i.State = PsbtResponderCanceled + }) + i.ShimIntent.Cancel() +} + +// Cancel allows the caller to cancel a funding Intent at any time. This will +// return make sure the channel funding flow with the remote peer is failed and +// any reservations are canceled. +// +// NOTE: Part of the chanfunding.Intent interface. +func (i *PsbtIntent) Cancel() { + log.Debugf("PSBT funding intent canceled, state=%v", i.State) + i.signalPsbtReady.Do(func() { + i.PsbtReady <- ErrUserCanceled + i.State = PsbtInitiatorCanceled + }) + i.ShimIntent.Cancel() +} + +// PsbtAssembler is a type of chanfunding.Assembler wherein the funding +// transaction is constructed outside of lnd by using partially signed bitcoin +// transactions (PSBT). +type PsbtAssembler struct { + // fundingAmt is the total amount of coins in the funding output. + fundingAmt btcutil.Amount + + // basePsbt is the user-supplied base PSBT the channel output should be + // added to. + basePsbt *psbt.Packet + + // netParams are the network parameters used to encode the P2WSH funding + // address. + netParams *chaincfg.Params +} + +// NewPsbtAssembler creates a new CannedAssembler from the material required +// to construct a funding output and channel point. An optional base PSBT can +// be supplied which will be used to add the channel output to instead of +// creating a new one. +func NewPsbtAssembler(fundingAmt btcutil.Amount, basePsbt *psbt.Packet, + netParams *chaincfg.Params) *PsbtAssembler { + + return &PsbtAssembler{ + fundingAmt: fundingAmt, + basePsbt: basePsbt, + netParams: netParams, + } +} + +// ProvisionChannel creates a new ShimIntent given the passed funding Request. +// The returned intent is immediately able to provide the channel point and +// funding output as they've already been created outside lnd. +// +// NOTE: This method satisfies the chanfunding.Assembler interface. +func (p *PsbtAssembler) ProvisionChannel(req *Request) (Intent, error) { + // We'll exit out if this field is set as the funding transaction will + // be assembled externally, so we don't influence coin selection. + if req.SubtractFees { + return nil, fmt.Errorf("SubtractFees not supported for PSBT") + } + + intent := &PsbtIntent{ + ShimIntent: ShimIntent{ + localFundingAmt: p.fundingAmt, + }, + State: PsbtShimRegistered, + BasePsbt: p.basePsbt, + PsbtReady: make(chan error, 1), + netParams: p.netParams, + } + + // A simple sanity check to ensure the provisioned request matches the + // re-made shim intent. + if req.LocalAmt+req.RemoteAmt != p.fundingAmt { + return nil, fmt.Errorf("intent doesn't match PSBT "+ + "assembler: local_amt=%v, remote_amt=%v, funding_amt=%v", + req.LocalAmt, req.RemoteAmt, p.fundingAmt) + } + + return intent, nil +} + +// FundingTxAvailable is an empty method that an assembler can implement to +// signal to callers that its able to provide the funding transaction for the +// channel via the intent it returns. +// +// NOTE: This method is a part of the FundingTxAssembler interface. +func (p *PsbtAssembler) FundingTxAvailable() {} + +// A compile-time assertion to ensure PsbtAssembler meets the Assembler +// interface. +var _ Assembler = (*PsbtAssembler)(nil) + +// sumUtxoInputValues tries to extract the sum of all inputs specified in the +// UTXO fields of the PSBT. An error is returned if an input is specified that +// does not contain any UTXO information. +func sumUtxoInputValues(packet *psbt.Packet) (int64, error) { + // We take the TX ins of the unsigned TX as the truth for how many + // inputs there should be, as the fields in the extra data part of the + // PSBT can be empty. + if len(packet.UnsignedTx.TxIn) != len(packet.Inputs) { + return 0, fmt.Errorf("TX input length doesn't match PSBT " + + "input length") + } + inputSum := int64(0) + for idx, in := range packet.Inputs { + switch { + case in.WitnessUtxo != nil: + // Witness UTXOs only need to reference the TxOut. + inputSum += in.WitnessUtxo.Value + + case in.NonWitnessUtxo != nil: + // Non-witness UTXOs reference to the whole transaction + // the UTXO resides in. + utxOuts := in.NonWitnessUtxo.TxOut + txIn := packet.UnsignedTx.TxIn[idx] + inputSum += utxOuts[txIn.PreviousOutPoint.Index].Value + + default: + return 0, fmt.Errorf("input %d has no UTXO information", + idx) + } + } + return inputSum, nil +} + +// txOutsEqual returns true if two transaction outputs are equal. +func txOutsEqual(out1, out2 *wire.TxOut) bool { + if out1 == nil || out2 == nil { + return out1 == out2 + } + return out1.Value == out2.Value && + bytes.Equal(out1.PkScript, out2.PkScript) +} + +// verifyOutputsEqual verifies that the two slices of transaction outputs are +// deep equal to each other. We do the length check and manual loop to provide +// better error messages to the user than just returning "not equal". +func verifyOutputsEqual(outs1, outs2 []*wire.TxOut) error { + if len(outs1) != len(outs2) { + return fmt.Errorf("number of outputs are different") + } + for idx, out := range outs1 { + // There is a byte slice in the output so we can't use the + // equality operator. + if !txOutsEqual(out, outs2[idx]) { + return fmt.Errorf("output %d is different", idx) + } + } + return nil +} + +// verifyInputPrevOutpointsEqual verifies that the previous outpoints of the +// two slices of transaction inputs are deep equal to each other. We do the +// length check and manual loop to provide better error messages to the user +// than just returning "not equal". +func verifyInputPrevOutpointsEqual(ins1, ins2 []*wire.TxIn) error { + if len(ins1) != len(ins2) { + return fmt.Errorf("number of inputs are different") + } + for idx, in := range ins1 { + if in.PreviousOutPoint != ins2[idx].PreviousOutPoint { + return fmt.Errorf("previous outpoint of input %d is "+ + "different", idx) + } + } + return nil +} diff --git a/lnwallet/chanfunding/psbt_assembler_test.go b/lnwallet/chanfunding/psbt_assembler_test.go new file mode 100644 index 0000000000..5367ecdbe6 --- /dev/null +++ b/lnwallet/chanfunding/psbt_assembler_test.go @@ -0,0 +1,577 @@ +package chanfunding + +import ( + "bytes" + "crypto/sha256" + "fmt" + "reflect" + "sync" + "testing" + "time" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/psbt" + "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" +) + +var ( + localPrivkey = []byte{1, 2, 3, 4, 5, 6} + remotePrivkey = []byte{6, 5, 4, 3, 2, 1} + chanCapacity btcutil.Amount = 644000 + params = chaincfg.RegressionNetParams + defaultTimeout = 50 * time.Millisecond +) + +// TestPsbtIntent tests the basic happy path of the PSBT assembler and intent. +func TestPsbtIntent(t *testing.T) { + t.Parallel() + + // Create a simple assembler and ask it to provision a channel to get + // the funding intent. + a := NewPsbtAssembler(chanCapacity, nil, ¶ms) + intent, err := a.ProvisionChannel(&Request{LocalAmt: chanCapacity}) + if err != nil { + t.Fatalf("error provisioning channel: %v", err) + } + psbtIntent, ok := intent.(*PsbtIntent) + if !ok { + t.Fatalf("intent was not a PsbtIntent") + } + if psbtIntent.State != PsbtShimRegistered { + t.Fatalf("unexpected state. got %d wanted %d", psbtIntent.State, + PsbtShimRegistered) + } + + // The first step with the intent is that the funding manager starts + // negotiating with the remote peer and they accept. By accepting, they + // send over their multisig key that's going to be used for the funding + // output. With that known, we can start crafting a PSBT. + _, localPubkey := btcec.PrivKeyFromBytes(btcec.S256(), localPrivkey) + _, remotePubkey := btcec.PrivKeyFromBytes(btcec.S256(), remotePrivkey) + psbtIntent.BindKeys( + &keychain.KeyDescriptor{PubKey: localPubkey}, remotePubkey, + ) + if psbtIntent.State != PsbtOutputKnown { + t.Fatalf("unexpected state. got %d wanted %d", psbtIntent.State, + PsbtOutputKnown) + } + + // Make sure the output script address is correct. + script, _, err := input.GenFundingPkScript( + localPubkey.SerializeCompressed(), + remotePubkey.SerializeCompressed(), int64(chanCapacity), + ) + if err != nil { + t.Fatalf("error calculating script: %v", err) + } + witnessScriptHash := sha256.Sum256(script) + addr, err := btcutil.NewAddressWitnessScriptHash( + witnessScriptHash[:], ¶ms, + ) + if err != nil { + t.Fatalf("unable to encode address: %v", err) + } + fundingAddr, amt, pendingPsbt, err := psbtIntent.FundingParams() + if err != nil { + t.Fatalf("unable to get funding params: %v", err) + } + if addr.EncodeAddress() != fundingAddr.EncodeAddress() { + t.Fatalf("unexpected address. got %s wanted %s", fundingAddr, + addr) + } + if amt != int64(chanCapacity) { + t.Fatalf("unexpected amount. got %d wanted %d", amt, + chanCapacity) + } + + // Parse and check the returned PSBT packet. + if pendingPsbt == nil { + t.Fatalf("expected pending PSBT to be returned") + } + if len(pendingPsbt.UnsignedTx.TxOut) != 1 { + t.Fatalf("unexpected number of outputs. got %d wanted %d", + len(pendingPsbt.UnsignedTx.TxOut), 1) + } + txOut := pendingPsbt.UnsignedTx.TxOut[0] + if !bytes.Equal(txOut.PkScript[2:], witnessScriptHash[:]) { + t.Fatalf("unexpected PK script in output. got %x wanted %x", + txOut.PkScript[2:], witnessScriptHash) + } + if txOut.Value != int64(chanCapacity) { + t.Fatalf("unexpected value in output. got %d wanted %d", + txOut.Value, chanCapacity) + } + + // Add an input to the pending TX to simulate it being funded. + pendingPsbt.UnsignedTx.TxIn = []*wire.TxIn{ + {PreviousOutPoint: wire.OutPoint{Index: 0}}, + } + pendingPsbt.Inputs = []psbt.PInput{ + {WitnessUtxo: &wire.TxOut{Value: int64(chanCapacity + 1)}}, + } + + // Verify the dummy PSBT with the intent. + err = psbtIntent.Verify(pendingPsbt) + if err != nil { + t.Fatalf("error verifying pending PSBT: %v", err) + } + if psbtIntent.State != PsbtVerified { + t.Fatalf("unexpected state. got %d wanted %d", psbtIntent.State, + PsbtVerified) + } + + // Add some fake witness data to the transaction so it thinks it's + // signed. + pendingPsbt.Inputs[0].WitnessUtxo = &wire.TxOut{ + Value: int64(chanCapacity) * 2, + PkScript: []byte{99, 99, 99}, + } + pendingPsbt.Inputs[0].FinalScriptSig = []byte{88, 88, 88} + pendingPsbt.Inputs[0].FinalScriptWitness = []byte{2, 0, 0} + + // If we call Finalize, the intent will signal to the funding manager + // that it can continue with the funding flow. We want to make sure + // the signal arrives. + var wg sync.WaitGroup + errChan := make(chan error, 1) + wg.Add(1) + go func() { + defer wg.Done() + select { + case err := <-psbtIntent.PsbtReady: + errChan <- err + + case <-time.After(defaultTimeout): + errChan <- fmt.Errorf("timed out") + } + }() + err = psbtIntent.Finalize(pendingPsbt) + if err != nil { + t.Fatalf("error finalizing pending PSBT: %v", err) + } + wg.Wait() + + // We should have a nil error in our channel now. + err = <-errChan + if err != nil { + t.Fatalf("unexpected error after finalize: %v", err) + } + if psbtIntent.State != PsbtFinalized { + t.Fatalf("unexpected state. got %d wanted %d", psbtIntent.State, + PsbtFinalized) + } + + // Make sure the funding transaction can be compiled. + _, err = psbtIntent.CompileFundingTx() + if err != nil { + t.Fatalf("error compiling funding TX from PSBT: %v", err) + } + if psbtIntent.State != PsbtFundingTxCompiled { + t.Fatalf("unexpected state. got %d wanted %d", psbtIntent.State, + PsbtFundingTxCompiled) + } +} + +// TestPsbtIntentBasePsbt tests that a channel funding output can be appended to +// a given base PSBT in the funding flow. +func TestPsbtIntentBasePsbt(t *testing.T) { + t.Parallel() + + // First create a dummy PSBT with a single output. + pendingPsbt, err := psbt.New( + []*wire.OutPoint{{}}, []*wire.TxOut{ + {Value: 999, PkScript: []byte{99, 88, 77}}, + }, 2, 0, []uint32{0}, + ) + if err != nil { + t.Fatalf("unable to create dummy PSBT") + } + + // Generate the funding multisig keys and the address so we can compare + // it to the output of the intent. + _, localPubkey := btcec.PrivKeyFromBytes(btcec.S256(), localPrivkey) + _, remotePubkey := btcec.PrivKeyFromBytes(btcec.S256(), remotePrivkey) + // Make sure the output script address is correct. + script, _, err := input.GenFundingPkScript( + localPubkey.SerializeCompressed(), + remotePubkey.SerializeCompressed(), int64(chanCapacity), + ) + if err != nil { + t.Fatalf("error calculating script: %v", err) + } + witnessScriptHash := sha256.Sum256(script) + addr, err := btcutil.NewAddressWitnessScriptHash( + witnessScriptHash[:], ¶ms, + ) + if err != nil { + t.Fatalf("unable to encode address: %v", err) + } + + // Now as the next step, create a new assembler/intent pair with a base + // PSBT to see that we can add an additional output to it. + a := NewPsbtAssembler(chanCapacity, pendingPsbt, ¶ms) + intent, err := a.ProvisionChannel(&Request{LocalAmt: chanCapacity}) + if err != nil { + t.Fatalf("error provisioning channel: %v", err) + } + psbtIntent, ok := intent.(*PsbtIntent) + if !ok { + t.Fatalf("intent was not a PsbtIntent") + } + psbtIntent.BindKeys( + &keychain.KeyDescriptor{PubKey: localPubkey}, remotePubkey, + ) + newAddr, amt, twoOutPsbt, err := psbtIntent.FundingParams() + if err != nil { + t.Fatalf("unable to get funding params: %v", err) + } + if addr.EncodeAddress() != newAddr.EncodeAddress() { + t.Fatalf("unexpected address. got %s wanted %s", newAddr, + addr) + } + if amt != int64(chanCapacity) { + t.Fatalf("unexpected amount. got %d wanted %d", amt, + chanCapacity) + } + if len(twoOutPsbt.UnsignedTx.TxOut) != 2 { + t.Fatalf("unexpected number of outputs. got %d wanted %d", + len(twoOutPsbt.UnsignedTx.TxOut), 2) + } + if len(twoOutPsbt.UnsignedTx.TxIn) != 1 { + t.Fatalf("unexpected number of inputs. got %d wanted %d", + len(twoOutPsbt.UnsignedTx.TxIn), 1) + } + txOld := pendingPsbt.UnsignedTx + txNew := twoOutPsbt.UnsignedTx + prevoutEqual := reflect.DeepEqual( + txOld.TxIn[0].PreviousOutPoint, txNew.TxIn[0].PreviousOutPoint, + ) + if !prevoutEqual { + t.Fatalf("inputs changed. got %s wanted %s", + spew.Sdump(txOld.TxIn[0].PreviousOutPoint), + spew.Sdump(txNew.TxIn[0].PreviousOutPoint)) + } + if !reflect.DeepEqual(txOld.TxOut[0], txNew.TxOut[0]) { + t.Fatalf("existing output changed. got %v wanted %v", + txOld.TxOut[0], txNew.TxOut[0]) + } +} + +// TestPsbtVerify tests the PSBT verification process more deeply than just +// the happy path. +func TestPsbtVerify(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + expectedErr string + doVerify func(int64, *psbt.Packet, *PsbtIntent) error + }{ + { + name: "nil packet", + expectedErr: "PSBT is nil", + doVerify: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + return i.Verify(nil) + }, + }, + { + name: "wrong state", + expectedErr: "invalid state. got user_canceled " + + "expected output_known", + doVerify: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + i.State = PsbtInitiatorCanceled + return i.Verify(p) + }, + }, + { + name: "output not found, value wrong", + expectedErr: "funding output not found in PSBT", + doVerify: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + p.UnsignedTx.TxOut[0].Value = 123 + return i.Verify(p) + }, + }, + { + name: "output not found, pk script wrong", + expectedErr: "funding output not found in PSBT", + doVerify: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + p.UnsignedTx.TxOut[0].PkScript = []byte{1, 2, 3} + return i.Verify(p) + }, + }, + { + name: "no inputs", + expectedErr: "PSBT has no inputs", + doVerify: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + return i.Verify(p) + }, + }, + { + name: "input(s) too small", + expectedErr: "input amount sum must be larger than " + + "output amount sum", + doVerify: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + p.UnsignedTx.TxIn = []*wire.TxIn{{}} + p.Inputs = []psbt.PInput{{ + WitnessUtxo: &wire.TxOut{ + Value: int64(chanCapacity), + }, + }} + return i.Verify(p) + }, + }, + { + name: "input correct", + expectedErr: "", + doVerify: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + txOut := &wire.TxOut{ + Value: int64(chanCapacity/2) + 1, + } + p.UnsignedTx.TxIn = []*wire.TxIn{ + {}, + { + PreviousOutPoint: wire.OutPoint{ + Index: 0, + }, + }, + } + p.Inputs = []psbt.PInput{ + { + WitnessUtxo: txOut, + }, + { + NonWitnessUtxo: &wire.MsgTx{ + TxOut: []*wire.TxOut{ + txOut, + }, + }, + }} + return i.Verify(p) + }, + }, + } + + // Create a simple assembler and ask it to provision a channel to get + // the funding intent. + a := NewPsbtAssembler(chanCapacity, nil, ¶ms) + intent, err := a.ProvisionChannel(&Request{LocalAmt: chanCapacity}) + if err != nil { + t.Fatalf("error provisioning channel: %v", err) + } + psbtIntent := intent.(*PsbtIntent) + + // Bind our test keys to get the funding parameters. + _, localPubkey := btcec.PrivKeyFromBytes(btcec.S256(), localPrivkey) + _, remotePubkey := btcec.PrivKeyFromBytes(btcec.S256(), remotePrivkey) + psbtIntent.BindKeys( + &keychain.KeyDescriptor{PubKey: localPubkey}, remotePubkey, + ) + + // Loop through all our test cases. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + // Reset the state from a previous test and create a new + // pending PSBT that we can manipulate. + psbtIntent.State = PsbtOutputKnown + _, amt, pendingPsbt, err := psbtIntent.FundingParams() + if err != nil { + t.Fatalf("unable to get funding params: %v", err) + } + + err = tc.doVerify(amt, pendingPsbt, psbtIntent) + if err != nil && tc.expectedErr != "" && + err.Error() != tc.expectedErr { + + t.Fatalf("unexpected error, got '%v' wanted "+ + "'%v'", err, tc.expectedErr) + } + }) + } +} + +// TestPsbtFinalize tests the PSBT finalization process more deeply than just +// the happy path. +func TestPsbtFinalize(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + expectedErr string + doFinalize func(int64, *psbt.Packet, *PsbtIntent) error + }{ + { + name: "nil packet", + expectedErr: "PSBT is nil", + doFinalize: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + return i.Finalize(nil) + }, + }, + { + name: "wrong state", + expectedErr: "invalid state. got user_canceled " + + "expected verified", + doFinalize: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + i.State = PsbtInitiatorCanceled + return i.Finalize(p) + }, + }, + { + name: "not verified first", + expectedErr: "PSBT was not verified first", + doFinalize: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + i.State = PsbtVerified + i.PendingPsbt = nil + return i.Finalize(p) + }, + }, + { + name: "output value changed", + expectedErr: "outputs differ from verified PSBT: " + + "output 0 is different", + doFinalize: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + p.UnsignedTx.TxOut[0].Value = 123 + return i.Finalize(p) + }, + }, + { + name: "output pk script changed", + expectedErr: "outputs differ from verified PSBT: " + + "output 0 is different", + doFinalize: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + p.UnsignedTx.TxOut[0].PkScript = []byte{3, 2, 1} + return i.Finalize(p) + }, + }, + { + name: "input previous outpoint index changed", + expectedErr: "inputs differ from verified PSBT: " + + "previous outpoint of input 0 is different", + doFinalize: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + p.UnsignedTx.TxIn[0].PreviousOutPoint.Index = 0 + return i.Finalize(p) + }, + }, + { + name: "input previous outpoint hash changed", + expectedErr: "inputs differ from verified PSBT: " + + "previous outpoint of input 0 is different", + doFinalize: func(amt int64, p *psbt.Packet, + i *PsbtIntent) error { + + prevout := &p.UnsignedTx.TxIn[0].PreviousOutPoint + prevout.Hash = chainhash.Hash{77, 88, 99, 11} + return i.Finalize(p) + }, + }, + } + + // Create a simple assembler and ask it to provision a channel to get + // the funding intent. + a := NewPsbtAssembler(chanCapacity, nil, ¶ms) + intent, err := a.ProvisionChannel(&Request{LocalAmt: chanCapacity}) + if err != nil { + t.Fatalf("error provisioning channel: %v", err) + } + psbtIntent := intent.(*PsbtIntent) + + // Bind our test keys to get the funding parameters. + _, localPubkey := btcec.PrivKeyFromBytes(btcec.S256(), localPrivkey) + _, remotePubkey := btcec.PrivKeyFromBytes(btcec.S256(), remotePrivkey) + psbtIntent.BindKeys( + &keychain.KeyDescriptor{PubKey: localPubkey}, remotePubkey, + ) + + // Loop through all our test cases. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + // Reset the state from a previous test and create a new + // pending PSBT that we can manipulate. + psbtIntent.State = PsbtOutputKnown + _, amt, pendingPsbt, err := psbtIntent.FundingParams() + if err != nil { + t.Fatalf("unable to get funding params: %v", err) + } + + // We need to have a simulated transaction here that is + // fully funded and signed. + pendingPsbt.UnsignedTx.TxIn = []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{ + Index: 1, + Hash: chainhash.Hash{1, 2, 3}, + }, + }} + pendingPsbt.Inputs = []psbt.PInput{{ + WitnessUtxo: &wire.TxOut{ + Value: int64(chanCapacity) + 1, + PkScript: []byte{1, 2, 3}, + }, + FinalScriptWitness: []byte{0x01, 0x00}, + }} + err = psbtIntent.Verify(pendingPsbt) + if err != nil { + t.Fatalf("error verifying PSBT: %v", err) + } + + // Deep clone the PSBT so we don't modify the pending + // one that was registered during Verify. + pendingPsbt = clonePsbt(t, pendingPsbt) + + err = tc.doFinalize(amt, pendingPsbt, psbtIntent) + if (err == nil && tc.expectedErr != "") || + (err != nil && err.Error() != tc.expectedErr) { + + t.Fatalf("unexpected error, got '%v' wanted "+ + "'%v'", err, tc.expectedErr) + } + }) + } +} + +// clonePsbt creates a clone of a PSBT packet by serializing then de-serializing +// it. +func clonePsbt(t *testing.T, p *psbt.Packet) *psbt.Packet { + var buf bytes.Buffer + err := p.Serialize(&buf) + if err != nil { + t.Fatalf("error serializing PSBT: %v", err) + } + newPacket, err := psbt.NewFromRawBytes(&buf, false) + if err != nil { + t.Fatalf("error unserializing PSBT: %v", err) + } + return newPacket +} From 5a52420ab643acecc85b3bca39aee747cbe247fe Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:16 +0200 Subject: [PATCH 333/562] lnwallet+fundingmgr: interrupt funding flow for PSBT In case the funding manager detects that a funding flow is requested to be executed with the help of a PsbtIntent, the normal channel negotiation with the remote peer is interrupted, as soon as the accept_channel message was received. With the remote peer's funding multisig key and our local key, we can derive the funding output script and its address. This is enough to start the PSBT funding and signing process which the user will do externally to the daemon. --- fundingmanager.go | 180 ++++++++++++++++++++++++++++-- lnwallet/interface_test.go | 5 + lnwallet/reservation.go | 31 ++++++ lnwallet/wallet.go | 222 +++++++++++++++++++++++++++++++++++-- 4 files changed, 419 insertions(+), 19 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index 0bd64430a4..23126c30c1 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -26,6 +26,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" + "github.com/lightningnetwork/lnd/lnwallet/chanfunding" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing" "golang.org/x/crypto/salsa20" @@ -698,7 +699,7 @@ func (f *fundingManager) failFundingFlow(peer lnpeer.Peer, tempChanID [32]byte, fndgLog.Debugf("Failing funding flow for pending_id=%x: %v", tempChanID, fundingErr) - ctx, err := f.cancelReservationCtx(peer.IdentityKey(), tempChanID) + ctx, err := f.cancelReservationCtx(peer.IdentityKey(), tempChanID, false) if err != nil { fndgLog.Errorf("unable to cancel reservation: %v", err) } @@ -1547,7 +1548,42 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { UpfrontShutdown: msg.UpfrontShutdownScript, } err = resCtx.reservation.ProcessContribution(remoteContribution) - if err != nil { + + // The wallet has detected that a PSBT funding process was requested by + // the user and has halted the funding process after negotiating the + // multisig keys. We now have everything that is needed for the user to + // start constructing a PSBT that sends to the multisig funding address. + var psbtIntent *chanfunding.PsbtIntent + if psbtErr, ok := err.(*lnwallet.PsbtFundingRequired); ok { + // Return the information that is needed by the user to + // construct the PSBT back to the caller. + addr, amt, packet, err := psbtErr.Intent.FundingParams() + if err != nil { + fndgLog.Errorf("Unable to process PSBT funding params "+ + "for contribution from %v: %v", peerKey, err) + f.failFundingFlow(fmsg.peer, msg.PendingChannelID, err) + return + } + var buf bytes.Buffer + err = packet.Serialize(&buf) + if err != nil { + fndgLog.Errorf("Unable to serialize PSBT for "+ + "contribution from %v: %v", peerKey, err) + f.failFundingFlow(fmsg.peer, msg.PendingChannelID, err) + return + } + resCtx.updates <- &lnrpc.OpenStatusUpdate{ + PendingChanId: pendingChanID[:], + Update: &lnrpc.OpenStatusUpdate_PsbtFund{ + PsbtFund: &lnrpc.ReadyForPsbtFunding{ + FundingAddress: addr.EncodeAddress(), + FundingAmount: amt, + Psbt: buf.Bytes(), + }, + }, + } + psbtIntent = psbtErr.Intent + } else if err != nil { fndgLog.Errorf("Unable to process contribution from %v: %v", peerKey, err) f.failFundingFlow(fmsg.peer, msg.PendingChannelID, err) @@ -1559,6 +1595,105 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { fndgLog.Debugf("Remote party accepted commitment constraints: %v", spew.Sdump(remoteContribution.ChannelConfig.ChannelConstraints)) + // If the user requested funding through a PSBT, we cannot directly + // continue now and need to wait for the fully funded and signed PSBT + // to arrive. To not block any other channels from opening, we wait in + // a separate goroutine. + if psbtIntent != nil { + f.wg.Add(1) + go func() { + defer f.wg.Done() + f.waitForPsbt(psbtIntent, resCtx, pendingChanID) + }() + + // With the new goroutine spawned, we can now exit to unblock + // the main event loop. + return + } + + // In a normal, non-PSBT funding flow, we can jump directly to the next + // step where we expect our contribution to be finalized. + f.continueFundingAccept(resCtx, pendingChanID) +} + +// waitForPsbt blocks until either a signed PSBT arrives, an error occurs or +// the funding manager shuts down. In the case of a valid PSBT, the funding flow +// is continued. +// +// NOTE: This method must be called as a goroutine. +func (f *fundingManager) waitForPsbt(intent *chanfunding.PsbtIntent, + resCtx *reservationWithCtx, pendingChanID [32]byte) { + + // failFlow is a helper that logs an error message with the current + // context and then fails the funding flow. + peerKey := resCtx.peer.IdentityKey() + failFlow := func(errMsg string, cause error) { + fndgLog.Errorf("Unable to handle funding accept message "+ + "for peer_key=%x, pending_chan_id=%x: %s: %v", + peerKey.SerializeCompressed(), pendingChanID, errMsg, + cause) + f.failFundingFlow(resCtx.peer, pendingChanID, cause) + } + + // We'll now wait until the intent has received the final and complete + // funding transaction. If the channel is closed without any error being + // sent, we know everything's going as expected. + select { + case err := <-intent.PsbtReady: + switch err { + // If the user canceled the funding reservation, we need to + // inform the other peer about us canceling the reservation. + case chanfunding.ErrUserCanceled: + failFlow("aborting PSBT flow", err) + return + + // If the remote canceled the funding reservation, we don't need + // to send another fail message. But we want to inform the user + // about what happened. + case chanfunding.ErrRemoteCanceled: + fndgLog.Infof("Remote canceled, aborting PSBT flow "+ + "for peer_key=%x, pending_chan_id=%x", + peerKey.SerializeCompressed(), pendingChanID) + return + + // Nil error means the flow continues normally now. + case nil: + + // For any other error, we'll fail the funding flow. + default: + failFlow("error waiting for PSBT flow", err) + return + } + + // A non-nil error means we can continue the funding flow. + // Notify the wallet so it can prepare everything we need to + // continue. + err = resCtx.reservation.ProcessPsbt() + if err != nil { + failFlow("error continuing PSBT flow", err) + return + } + + // We are now ready to continue the funding flow. + f.continueFundingAccept(resCtx, pendingChanID) + + // Handle a server shutdown as well because the reservation won't + // survive a restart as it's in memory only. + case <-f.quit: + fndgLog.Errorf("Unable to handle funding accept message "+ + "for peer_key=%x, pending_chan_id=%x: funding manager "+ + "shutting down", peerKey.SerializeCompressed(), + pendingChanID) + return + } +} + +// continueFundingAccept continues the channel funding flow once our +// contribution is finalized, the channel output is known and the funding +// transaction is signed. +func (f *fundingManager) continueFundingAccept(resCtx *reservationWithCtx, + pendingChanID [32]byte) { + // Now that we have their contribution, we can extract, then send over // both the funding out point and our signature for their version of // the commitment transaction to the remote peer. @@ -1586,6 +1721,7 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { fndgLog.Infof("Generated ChannelPoint(%v) for pending_id(%x)", outPoint, pendingChanID[:]) + var err error fundingCreated := &lnwire.FundingCreated{ PendingChannelID: pendingChanID, FundingPoint: *outPoint, @@ -1593,12 +1729,12 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { fundingCreated.CommitSig, err = lnwire.NewSigFromRawSignature(sig) if err != nil { fndgLog.Errorf("Unable to parse signature: %v", err) - f.failFundingFlow(fmsg.peer, msg.PendingChannelID, err) + f.failFundingFlow(resCtx.peer, pendingChanID, err) return } - if err := fmsg.peer.SendMessage(true, fundingCreated); err != nil { + if err := resCtx.peer.SendMessage(true, fundingCreated); err != nil { fndgLog.Errorf("Unable to send funding complete message: %v", err) - f.failFundingFlow(fmsg.peer, msg.PendingChannelID, err) + f.failFundingFlow(resCtx.peer, pendingChanID, err) return } } @@ -3070,7 +3206,8 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { // Since we were unable to send the initial message to the peer // and start the funding flow, we'll cancel this reservation. - if _, err := f.cancelReservationCtx(peerKey, chanID); err != nil { + _, err := f.cancelReservationCtx(peerKey, chanID, false) + if err != nil { fndgLog.Errorf("unable to cancel reservation: %v", err) } @@ -3130,7 +3267,7 @@ func (f *fundingManager) handleErrorMsg(fmsg *fundingErrorMsg) { // First, we'll attempt to retrieve and cancel the funding workflow // that this error was tied to. If we're unable to do so, then we'll // exit early as this was an unwarranted error. - resCtx, err := f.cancelReservationCtx(fmsg.peerKey, chanID) + resCtx, err := f.cancelReservationCtx(fmsg.peerKey, chanID, true) if err != nil { fndgLog.Warnf("Received error for non-existent funding "+ "flow: %v (%v)", err, protocolErr.Error()) @@ -3144,6 +3281,14 @@ func (f *fundingManager) handleErrorMsg(fmsg *fundingErrorMsg) { ) fndgLog.Errorf(fundingErr.Error()) + // If this was a PSBT funding flow, the remote likely timed out because + // we waited too long. Return a nice error message to the user in that + // case so the user knows what's the problem. + if resCtx.reservation.IsPsbt() { + fundingErr = fmt.Errorf("%w: %v", chanfunding.ErrRemoteCanceled, + fundingErr) + } + resCtx.err <- fundingErr } @@ -3160,7 +3305,14 @@ func (f *fundingManager) pruneZombieReservations() { continue } - if time.Since(resCtx.lastUpdated) > f.cfg.ReservationTimeout { + // We don't want to expire PSBT funding reservations. + // These reservations are always initiated by us and the + // remote peer is likely going to cancel them after some + // idle time anyway. So no need for us to also prune + // them. + sinceLastUpdate := time.Since(resCtx.lastUpdated) + isExpired := sinceLastUpdate > f.cfg.ReservationTimeout + if !resCtx.reservation.IsPsbt() && isExpired { zombieReservations[pendingChanID] = resCtx } } @@ -3169,7 +3321,7 @@ func (f *fundingManager) pruneZombieReservations() { for pendingChanID, resCtx := range zombieReservations { err := fmt.Errorf("reservation timed out waiting for peer "+ - "(peer_id:%v, chan_id:%x)", resCtx.peer.IdentityKey(), + "(peer_id:%x, chan_id:%x)", resCtx.peer.IdentityKey(), pendingChanID[:]) fndgLog.Warnf(err.Error()) f.failFundingFlow(resCtx.peer, pendingChanID, err) @@ -3179,7 +3331,7 @@ func (f *fundingManager) pruneZombieReservations() { // cancelReservationCtx does all needed work in order to securely cancel the // reservation. func (f *fundingManager) cancelReservationCtx(peerKey *btcec.PublicKey, - pendingChanID [32]byte) (*reservationWithCtx, error) { + pendingChanID [32]byte, byRemote bool) (*reservationWithCtx, error) { fndgLog.Infof("Cancelling funding reservation for node_key=%x, "+ "chan_id=%x", peerKey.SerializeCompressed(), pendingChanID[:]) @@ -3201,6 +3353,14 @@ func (f *fundingManager) cancelReservationCtx(peerKey *btcec.PublicKey, "peer(%x)", pendingChanID[:], peerIDKey[:]) } + // If the reservation was a PSBT funding flow and it was canceled by the + // remote peer, then we need to thread through a different error message + // to the subroutine that's waiting for the user input so it can return + // a nice error message to the user. + if ctx.reservation.IsPsbt() && byRemote { + ctx.reservation.RemoteCanceled() + } + if err := ctx.reservation.Cancel(); err != nil { return nil, errors.Errorf("unable to cancel reservation: %v", err) diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index faadaca22d..2fe3da53bf 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -590,6 +590,7 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness, FundingFeePerKw: feePerKw, PushMSat: 0, Flags: lnwire.FFAnnounceChannel, + PendingChanID: [32]byte{0, 1, 2, 3}, } if _, err := alice.InitChannelReservation(req); err != nil { t.Fatalf("unable to initialize funding reservation 1: %v", err) @@ -612,6 +613,7 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness, FundingFeePerKw: feePerKw, PushMSat: 0, Flags: lnwire.FFAnnounceChannel, + PendingChanID: [32]byte{1, 2, 3, 4}, } failedReservation, err := alice.InitChannelReservation(failedReq) if err == nil { @@ -648,6 +650,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, FundingFeePerKw: feePerKw, PushMSat: 0, Flags: lnwire.FFAnnounceChannel, + PendingChanID: [32]byte{2, 3, 4, 5}, } chanReservation, err := alice.InitChannelReservation(req) if err != nil { @@ -655,6 +658,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, } // Attempt to create another channel with 44 BTC, this should fail. + req.PendingChanID = [32]byte{3, 4, 5, 6} _, err = alice.InitChannelReservation(req) if _, ok := err.(*chanfunding.ErrInsufficientFunds); !ok { t.Fatalf("coin selection succeeded should have insufficient funds: %v", @@ -684,6 +688,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, // attempting coin selection. // Request to fund a new channel should now succeed. + req.PendingChanID = [32]byte{4, 5, 6, 7, 8} if _, err := alice.InitChannelReservation(req); err != nil { t.Fatalf("unable to initialize funding reservation: %v", err) } diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 3c9188a655..1925135180 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -471,6 +471,37 @@ func (r *ChannelReservation) ProcessContribution(theirContribution *ChannelContr return <-errChan } +// IsPsbt returns true if there is a PSBT funding intent mapped to this +// reservation. +func (r *ChannelReservation) IsPsbt() bool { + _, ok := r.fundingIntent.(*chanfunding.PsbtIntent) + return ok +} + +// ProcessPsbt continues a previously paused funding flow that involves PSBT to +// construct the funding transaction. This method can be called once the PSBT is +// finalized and the signed transaction is available. +func (r *ChannelReservation) ProcessPsbt() error { + errChan := make(chan error, 1) + + r.wallet.msgChan <- &continueContributionMsg{ + pendingFundingID: r.reservationID, + err: errChan, + } + + return <-errChan +} + +// RemoteCanceled informs the PSBT funding state machine that the remote peer +// has canceled the pending reservation, likely due to a timeout. +func (r *ChannelReservation) RemoteCanceled() { + psbtIntent, ok := r.fundingIntent.(*chanfunding.PsbtIntent) + if !ok { + return + } + psbtIntent.RemoteCanceled() +} + // ProcessSingleContribution verifies, and records the initiator's contribution // to this pending single funder channel. Internally, no further action is // taken other than recording the initiator's contribution to the single funder diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 06fb9bb7e8..f7d66b6bab 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -15,6 +15,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/psbt" "github.com/btcsuite/btcutil/txsort" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" @@ -33,6 +34,28 @@ const ( msgBufferSize = 100 ) +var ( + // ErrPsbtFundingRequired is the error that is returned during the + // contribution handling process if the process should be paused for + // the construction of a PSBT outside of lnd's wallet. + ErrPsbtFundingRequired = errors.New("PSBT funding required") +) + +// PsbtFundingRequired is a type that implements the error interface and +// contains the information needed to construct a PSBT. +type PsbtFundingRequired struct { + // Intent is the pending PSBT funding intent that needs to be funded + // if the wrapping error is returned. + Intent *chanfunding.PsbtIntent +} + +// Error returns the underlying error. +// +// NOTE: This method is part of the error interface. +func (p *PsbtFundingRequired) Error() string { + return ErrPsbtFundingRequired.Error() +} + // InitFundingReserveMsg is the first message sent to initiate the workflow // required to open a payment channel with a remote peer. The initial required // parameters are configurable across channels. These parameters are to be @@ -150,6 +173,16 @@ type addContributionMsg struct { err chan error } +// continueContributionMsg represents a message that signals that the +// interrupted funding process involving a PSBT can now be continued because the +// finalized transaction is now available. +type continueContributionMsg struct { + pendingFundingID uint64 + + // NOTE: In order to avoid deadlocks, this channel MUST be buffered. + err chan error +} + // addSingleContributionMsg represents a message executing the second phase of // a single funder channel reservation workflow. This messages carries the // counterparty's "contribution" to the payment channel. As this message is @@ -395,6 +428,8 @@ out: l.handleSingleContribution(msg) case *addContributionMsg: l.handleContributionMsg(msg) + case *continueContributionMsg: + l.handleChanPointReady(msg) case *addSingleFunderSigsMsg: l.handleSingleFunderSigs(msg) case *addCounterPartySigsMsg: @@ -462,17 +497,74 @@ func (l *LightningWallet) RegisterFundingIntent(expectedID [32]byte, return nil } +// PsbtFundingVerify looks up a previously registered funding intent by its +// pending channel ID and tries to advance the state machine by verifying the +// passed PSBT. +func (l *LightningWallet) PsbtFundingVerify(pid [32]byte, + packet *psbt.Packet) error { + + l.intentMtx.Lock() + defer l.intentMtx.Unlock() + + intent, ok := l.fundingIntents[pid] + if !ok { + return fmt.Errorf("no funding intent found for "+ + "pendingChannelID(%x)", pid[:]) + } + psbtIntent, ok := intent.(*chanfunding.PsbtIntent) + if !ok { + return fmt.Errorf("incompatible funding intent") + } + err := psbtIntent.Verify(packet) + if err != nil { + return fmt.Errorf("error verifying PSBT: %v", err) + } + + return nil +} + +// PsbtFundingFinalize looks up a previously registered funding intent by its +// pending channel ID and tries to advance the state machine by finalizing the +// passed PSBT. +func (l *LightningWallet) PsbtFundingFinalize(pid [32]byte, + packet *psbt.Packet) error { + + l.intentMtx.Lock() + defer l.intentMtx.Unlock() + + intent, ok := l.fundingIntents[pid] + if !ok { + return fmt.Errorf("no funding intent found for "+ + "pendingChannelID(%x)", pid[:]) + } + psbtIntent, ok := intent.(*chanfunding.PsbtIntent) + if !ok { + return fmt.Errorf("incompatible funding intent") + } + err := psbtIntent.Finalize(packet) + if err != nil { + return fmt.Errorf("error finalizing PSBT: %v", err) + } + + return nil +} + // CancelFundingIntent allows a caller to cancel a previously registered // funding intent. If no intent was found, then an error will be returned. func (l *LightningWallet) CancelFundingIntent(pid [32]byte) error { l.intentMtx.Lock() defer l.intentMtx.Unlock() - if _, ok := l.fundingIntents[pid]; !ok { + intent, ok := l.fundingIntents[pid] + if !ok { return fmt.Errorf("no funding intent found for "+ "pendingChannelID(%x)", pid[:]) } + // Give the intent a chance to clean up after itself, removing coin + // locks or similar reserved resources. + intent.Cancel() + delete(l.fundingIntents, pid) return nil @@ -556,10 +648,28 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg return } + // Register the funding intent now in case we need to access it + // again later, as it's the case for the PSBT state machine for + // example. + err = l.RegisterFundingIntent(req.PendingChanID, fundingIntent) + if err != nil { + req.err <- err + req.resp <- nil + return + } + localFundingAmt = fundingIntent.LocalFundingAmt() remoteFundingAmt = fundingIntent.RemoteFundingAmt() } + // At this point there _has_ to be a funding intent, otherwise something + // went really wrong. + if fundingIntent == nil { + req.err <- fmt.Errorf("no funding intent present") + req.resp <- nil + return + } + // If this is a shim intent, then it may be attempting to use an // existing set of keys for the funding workflow. In this case, we'll // make a simple wrapper keychain.KeyRing that will proxy certain @@ -592,9 +702,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg thawHeight, ) if err != nil { - if fundingIntent != nil { - fundingIntent.Cancel() - } + fundingIntent.Cancel() req.err <- err req.resp <- nil @@ -605,9 +713,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg reservation, fundingIntent, req.NodeAddr, req.NodeID, keyRing, ) if err != nil { - if fundingIntent != nil { - fundingIntent.Cancel() - } + fundingIntent.Cancel() req.err <- err req.resp <- nil @@ -852,6 +958,9 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { // which type of intent we obtained from our chanfunding.Assembler, // we'll carry out a distinct set of steps. switch fundingIntent := pendingReservation.fundingIntent.(type) { + // The transaction was created outside of the wallet and might already + // be published. Nothing left to do other than using the correct + // outpoint. case *chanfunding.ShimIntent: chanPoint, err = fundingIntent.ChanPoint() if err != nil { @@ -861,6 +970,38 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { pendingReservation.partialState.FundingOutpoint = *chanPoint + // The user has signaled that they want to use a PSBT to construct the + // funding transaction. Because we now have the multisig keys from both + // parties, we can create the multisig script that needs to be funded + // and then pause the process until the user supplies the PSBT + // containing the eventual funding transaction. + case *chanfunding.PsbtIntent: + if fundingIntent.PendingPsbt != nil { + req.err <- fmt.Errorf("PSBT funding already in" + + "progress") + return + } + + // Now that we know our contribution, we can bind both the local + // and remote key which will be needed to calculate the multisig + // funding output in a next step. + pendingChanID := pendingReservation.pendingChanID + walletLog.Debugf("Advancing PSBT funding flow for "+ + "pending_id(%x), binding keys local_key=%v, "+ + "remote_key=%x", pendingChanID, + &ourContribution.MultiSigKey, + theirContribution.MultiSigKey.PubKey.SerializeCompressed()) + fundingIntent.BindKeys( + &ourContribution.MultiSigKey, + theirContribution.MultiSigKey.PubKey, + ) + + // Exit early because we can't continue the funding flow yet. + req.err <- &PsbtFundingRequired{ + Intent: fundingIntent, + } + return + case *chanfunding.FullIntent: // Now that we know their public key, we can bind theirs as // well as ours to the funding intent. @@ -915,6 +1056,69 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { "generated: %v", chanPoint, spew.Sdump(fundingTx)) } + // If we landed here and didn't exit early, it means we already have + // the channel point ready. We can jump directly to the next step. + l.handleChanPointReady(&continueContributionMsg{ + pendingFundingID: req.pendingFundingID, + err: req.err, + }) +} + +// handleChanPointReady continues the funding process once the channel point +// is known and the funding transaction can be completed. +func (l *LightningWallet) handleChanPointReady(req *continueContributionMsg) { + l.limboMtx.Lock() + pendingReservation, ok := l.fundingLimbo[req.pendingFundingID] + l.limboMtx.Unlock() + if !ok { + req.err <- fmt.Errorf("attempted to update non-existent " + + "funding state") + return + } + ourContribution := pendingReservation.ourContribution + theirContribution := pendingReservation.theirContribution + chanPoint := pendingReservation.partialState.FundingOutpoint + + // If we're in the PSBT funding flow, we now should have everything that + // is needed to construct and publish the full funding transaction. + intent := pendingReservation.fundingIntent + if psbtIntent, ok := intent.(*chanfunding.PsbtIntent); ok { + // With our keys bound, we can now construct+sign the final + // funding transaction and also obtain the chanPoint that + // creates the channel. + fundingTx, err := psbtIntent.CompileFundingTx() + if err != nil { + req.err <- fmt.Errorf("unable to construct funding "+ + "tx: %v", err) + return + } + chanPointPtr, err := psbtIntent.ChanPoint() + if err != nil { + req.err <- fmt.Errorf("unable to obtain chan "+ + "point: %v", err) + return + } + + // Finally, we'll populate the relevant information in our + // pendingReservation so the rest of the funding flow can + // continue as normal. + pendingReservation.fundingTx = fundingTx + pendingReservation.partialState.FundingOutpoint = *chanPointPtr + chanPoint = *chanPointPtr + pendingReservation.ourFundingInputScripts = make( + []*input.Script, 0, len(ourContribution.Inputs), + ) + for _, txIn := range fundingTx.TxIn { + pendingReservation.ourFundingInputScripts = append( + pendingReservation.ourFundingInputScripts, + &input.Script{ + Witness: txIn.Witness, + SigScript: txIn.SignatureScript, + }, + ) + } + } + // Initialize an empty sha-chain for them, tracking the current pending // revocation hash (we don't yet know the preimage so we can't add it // to the chain). @@ -930,7 +1134,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { // Create the txin to our commitment transaction; required to construct // the commitment transactions. fundingTxIn := wire.TxIn{ - PreviousOutPoint: *chanPoint, + PreviousOutPoint: chanPoint, } // With the funding tx complete, create both commitment transactions. @@ -991,7 +1195,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { chanPoint, spew.Sdump(theirCommitTx)) // Record newly available information within the open channel state. - chanState.FundingOutpoint = *chanPoint + chanState.FundingOutpoint = chanPoint chanState.LocalCommitment.CommitTx = ourCommitTx chanState.RemoteCommitment.CommitTx = theirCommitTx From 376a747bb2cc3cfcff989066fc260ef130935396 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:17 +0200 Subject: [PATCH 334/562] rpcserver: implement PSBT funding flow A PSBT funding flow consists of multiple steps. We add new RPC messages that can trigger the underlying state machine to transition to a new state. We also add new response messages that tell the API user what the current state is. --- rpcserver.go | 134 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 7 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index ad2040a58a..e68e0ffd90 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -19,10 +19,12 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/psbt" "github.com/btcsuite/btcwallet/wallet/txauthor" "github.com/davecgh/go-spew/spew" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" @@ -1556,6 +1558,51 @@ func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, initiator bool, ), nil } +// newFundingShimAssembler returns a new fully populated +// chanfunding.PsbtAssembler using a FundingShim obtained from an RPC caller. +func newPsbtAssembler(req *lnrpc.OpenChannelRequest, normalizedMinConfs int32, + psbtShim *lnrpc.PsbtShim, netParams *chaincfg.Params) ( + chanfunding.Assembler, error) { + + var ( + packet *psbt.Packet + err error + ) + + // Perform some basic sanity checks to ensure that all the expected + // fields are populated and none of the incompatible fields are. + if len(psbtShim.PendingChanId) != 32 { + return nil, fmt.Errorf("pending chan ID not set") + } + if normalizedMinConfs != 1 { + return nil, fmt.Errorf("setting non-default values for " + + "minimum confirmation is not supported for PSBT " + + "funding") + } + if req.SatPerByte != 0 || req.TargetConf != 0 { + return nil, fmt.Errorf("specifying fee estimation parameters " + + "is not supported for PSBT funding") + } + + // The base PSBT is optional. But if it's set, it has to be a valid, + // binary serialized PSBT. + if len(psbtShim.BasePsbt) > 0 { + packet, err = psbt.NewFromRawBytes( + bytes.NewReader(psbtShim.BasePsbt), false, + ) + if err != nil { + return nil, fmt.Errorf("error parsing base PSBT: %v", + err) + } + } + + // With all the parts assembled, we can now make the canned assembler + // to pass into the wallet. + return chanfunding.NewPsbtAssembler( + btcutil.Amount(req.LocalFundingAmount), packet, netParams, + ), nil +} + // OpenChannel attempts to open a singly funded channel specified in the // request to a remote peer. func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, @@ -1675,10 +1722,11 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, // If the user has provided a shim, then we'll now augment the based // open channel request with this additional logic. if in.FundingShim != nil { + switch { // If we have a chan point shim, then this means the funding // transaction was crafted externally. In this case we only // need to hand a channel point down into the wallet. - if in.FundingShim.GetChanPointShim() != nil { + case in.FundingShim.GetChanPointShim() != nil: chanPointShim := in.FundingShim.GetChanPointShim() // Map the channel point shim into a new @@ -1691,6 +1739,25 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, if err != nil { return err } + + // If we have a PSBT shim, then this means the funding + // transaction will be crafted outside of the wallet, once the + // funding multisig output script is known. We'll create an + // intent that will supervise the multi-step process. + case in.FundingShim.GetPsbtShim() != nil: + psbtShim := in.FundingShim.GetPsbtShim() + + // Instruct the wallet to use the new + // chanfunding.PsbtAssembler to construct the funding + // transaction. + copy(req.pendingChanID[:], psbtShim.PendingChanId) + req.chanFunder, err = newPsbtAssembler( + in, minConfs, psbtShim, + &r.server.cc.wallet.Cfg.NetParams, + ) + if err != nil { + return err + } } } @@ -6236,6 +6303,7 @@ func (r *rpcServer) BakeMacaroon(ctx context.Context, func (r *rpcServer) FundingStateStep(ctx context.Context, in *lnrpc.FundingTransitionMsg) (*lnrpc.FundingStateStepResp, error) { + var pendingChanID [32]byte switch { // If this is a message to register a new shim that is an external @@ -6269,7 +6337,6 @@ func (r *rpcServer) FundingStateStep(ctx context.Context, // Once we receive an incoming funding request that uses this // pending channel ID, then this shim will be dispatched in // place of our regular funding workflow. - var pendingChanID [32]byte copy(pendingChanID[:], rpcShimIntent.PendingChanId) err = r.server.cc.wallet.RegisterFundingIntent( pendingChanID, shimIntent, @@ -6278,18 +6345,71 @@ func (r *rpcServer) FundingStateStep(ctx context.Context, return nil, err } + // There is no need to register a PSBT shim before opening the channel, + // even though our RPC message structure allows for it. Inform the user + // by returning a proper error instead of just doing nothing. + case in.GetShimRegister() != nil && + in.GetShimRegister().GetPsbtShim() != nil: + + return nil, fmt.Errorf("PSBT shim must only be sent when " + + "opening a channel") + // If this is a transition to cancel an existing shim, then we'll pass - // this message along to the wallet. + // this message along to the wallet, informing it that the intent no + // longer needs to be considered and should be cleaned up. case in.GetShimCancel() != nil: - pid := in.GetShimCancel().PendingChanId - - var pendingChanID [32]byte - copy(pendingChanID[:], pid) + rpcsLog.Debugf("Canceling funding shim for pending_id=%x", + in.GetShimCancel().PendingChanId) + copy(pendingChanID[:], in.GetShimCancel().PendingChanId) err := r.server.cc.wallet.CancelFundingIntent(pendingChanID) if err != nil { return nil, err } + + // If this is a transition to verify the PSBT for an existing shim, + // we'll do so and then store the verified PSBT for later so we can + // compare it to the final, signed one. + case in.GetPsbtVerify() != nil: + rpcsLog.Debugf("Verifying PSBT for pending_id=%x", + in.GetPsbtVerify().PendingChanId) + + copy(pendingChanID[:], in.GetPsbtVerify().PendingChanId) + packet, err := psbt.NewFromRawBytes( + bytes.NewReader(in.GetPsbtVerify().FundedPsbt), false, + ) + if err != nil { + return nil, fmt.Errorf("error parsing psbt: %v", err) + } + + err = r.server.cc.wallet.PsbtFundingVerify( + pendingChanID, packet, + ) + if err != nil { + return nil, err + } + + // If this is a transition to finalize the PSBT funding flow, we compare + // the final PSBT to the previously verified one and if nothing + // unexpected was changed, continue the channel opening process. + case in.GetPsbtFinalize() != nil: + rpcsLog.Debugf("Finalizing PSBT for pending_id=%x", + in.GetPsbtFinalize().PendingChanId) + + copy(pendingChanID[:], in.GetPsbtFinalize().PendingChanId) + packet, err := psbt.NewFromRawBytes( + bytes.NewReader(in.GetPsbtFinalize().SignedPsbt), false, + ) + if err != nil { + return nil, fmt.Errorf("error parsing psbt: %v", err) + } + + err = r.server.cc.wallet.PsbtFundingFinalize( + pendingChanID, packet, + ) + if err != nil { + return nil, err + } } // TODO(roasbeef): extend PendingChannels to also show shims From 8b05d1b61fb858518b93a378f5bf422a9e4b9345 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:19 +0200 Subject: [PATCH 335/562] lncli: move openChannel command to new file This is a pure code move! --- cmd/lncli/cmd_open_channel.go | 277 ++++++++++++++++++++++++++++++++++ cmd/lncli/commands.go | 263 -------------------------------- 2 files changed, 277 insertions(+), 263 deletions(-) create mode 100644 cmd/lncli/cmd_open_channel.go diff --git a/cmd/lncli/cmd_open_channel.go b/cmd/lncli/cmd_open_channel.go new file mode 100644 index 0000000000..ef2ccc2e33 --- /dev/null +++ b/cmd/lncli/cmd_open_channel.go @@ -0,0 +1,277 @@ +package main + +import ( + "context" + "encoding/hex" + "fmt" + "io" + "strconv" + "strings" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/urfave/cli" +) + +// TODO(roasbeef): change default number of confirmations +var openChannelCommand = cli.Command{ + Name: "openchannel", + Category: "Channels", + Usage: "Open a channel to a node or an existing peer.", + Description: ` + Attempt to open a new channel to an existing peer with the key node-key + optionally blocking until the channel is 'open'. + + One can also connect to a node before opening a new channel to it by + setting its host:port via the --connect argument. For this to work, + the node_key must be provided, rather than the peer_id. This is optional. + + The channel will be initialized with local-amt satoshis local and push-amt + satoshis for the remote node. Note that specifying push-amt means you give that + amount to the remote node as part of the channel opening. Once the channel is open, + a channelPoint (txid:vout) of the funding output is returned. + + If the remote peer supports the option upfront shutdown feature bit (query + listpeers to see their supported feature bits), an address to enforce + payout of funds on cooperative close can optionally be provided. Note that + if you set this value, you will not be able to cooperatively close out to + another address. + + One can manually set the fee to be used for the funding transaction via either + the --conf_target or --sat_per_byte arguments. This is optional.`, + ArgsUsage: "node-key local-amt push-amt", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "node_key", + Usage: "the identity public key of the target node/peer " + + "serialized in compressed format", + }, + cli.StringFlag{ + Name: "connect", + Usage: "(optional) the host:port of the target node", + }, + cli.IntFlag{ + Name: "local_amt", + Usage: "the number of satoshis the wallet should commit to the channel", + }, + cli.IntFlag{ + Name: "push_amt", + Usage: "the number of satoshis to give the remote side " + + "as part of the initial commitment state, " + + "this is equivalent to first opening a " + + "channel and sending the remote party funds, " + + "but done all in one step", + }, + cli.BoolFlag{ + Name: "block", + Usage: "block and wait until the channel is fully open", + }, + cli.Int64Flag{ + Name: "conf_target", + Usage: "(optional) the number of blocks that the " + + "transaction *should* confirm in, will be " + + "used for fee estimation", + }, + cli.Int64Flag{ + Name: "sat_per_byte", + Usage: "(optional) a manual fee expressed in " + + "sat/byte that should be used when crafting " + + "the transaction", + }, + cli.BoolFlag{ + Name: "private", + Usage: "make the channel private, such that it won't " + + "be announced to the greater network, and " + + "nodes other than the two channel endpoints " + + "must be explicitly told about it to be able " + + "to route through it", + }, + cli.Int64Flag{ + Name: "min_htlc_msat", + Usage: "(optional) the minimum value we will require " + + "for incoming HTLCs on the channel", + }, + cli.Uint64Flag{ + Name: "remote_csv_delay", + Usage: "(optional) the number of blocks we will require " + + "our channel counterparty to wait before accessing " + + "its funds in case of unilateral close. If this is " + + "not set, we will scale the value according to the " + + "channel size", + }, + cli.Uint64Flag{ + Name: "min_confs", + Usage: "(optional) the minimum number of confirmations " + + "each one of your outputs used for the funding " + + "transaction must satisfy", + Value: 1, + }, + cli.StringFlag{ + Name: "close_address", + Usage: "(optional) an address to enforce payout of our " + + "funds to on cooperative close. Note that if this " + + "value is set on channel open, you will *not* be " + + "able to cooperatively close to a different address.", + }, + }, + Action: actionDecorator(openChannel), +} + +func openChannel(ctx *cli.Context) error { + // TODO(roasbeef): add deadline to context + ctxb := context.Background() + client, cleanUp := getClient(ctx) + defer cleanUp() + + args := ctx.Args() + var err error + + // Show command help if no arguments provided + if ctx.NArg() == 0 && ctx.NumFlags() == 0 { + cli.ShowCommandHelp(ctx, "openchannel") + return nil + } + + minConfs := int32(ctx.Uint64("min_confs")) + req := &lnrpc.OpenChannelRequest{ + TargetConf: int32(ctx.Int64("conf_target")), + SatPerByte: ctx.Int64("sat_per_byte"), + MinHtlcMsat: ctx.Int64("min_htlc_msat"), + RemoteCsvDelay: uint32(ctx.Uint64("remote_csv_delay")), + MinConfs: minConfs, + SpendUnconfirmed: minConfs == 0, + CloseAddress: ctx.String("close_address"), + } + + switch { + case ctx.IsSet("node_key"): + nodePubHex, err := hex.DecodeString(ctx.String("node_key")) + if err != nil { + return fmt.Errorf("unable to decode node public key: %v", err) + } + req.NodePubkey = nodePubHex + + case args.Present(): + nodePubHex, err := hex.DecodeString(args.First()) + if err != nil { + return fmt.Errorf("unable to decode node public key: %v", err) + } + args = args.Tail() + req.NodePubkey = nodePubHex + default: + return fmt.Errorf("node id argument missing") + } + + // As soon as we can confirm that the node's node_key was set, rather + // than the peer_id, we can check if the host:port was also set to + // connect to it before opening the channel. + if req.NodePubkey != nil && ctx.IsSet("connect") { + addr := &lnrpc.LightningAddress{ + Pubkey: hex.EncodeToString(req.NodePubkey), + Host: ctx.String("connect"), + } + + req := &lnrpc.ConnectPeerRequest{ + Addr: addr, + Perm: false, + } + + // Check if connecting to the node was successful. + // We discard the peer id returned as it is not needed. + _, err := client.ConnectPeer(ctxb, req) + if err != nil && + !strings.Contains(err.Error(), "already connected") { + return err + } + } + + switch { + case ctx.IsSet("local_amt"): + req.LocalFundingAmount = int64(ctx.Int("local_amt")) + case args.Present(): + req.LocalFundingAmount, err = strconv.ParseInt(args.First(), 10, 64) + if err != nil { + return fmt.Errorf("unable to decode local amt: %v", err) + } + args = args.Tail() + default: + return fmt.Errorf("local amt argument missing") + } + + if ctx.IsSet("push_amt") { + req.PushSat = int64(ctx.Int("push_amt")) + } else if args.Present() { + req.PushSat, err = strconv.ParseInt(args.First(), 10, 64) + if err != nil { + return fmt.Errorf("unable to decode push amt: %v", err) + } + } + + req.Private = ctx.Bool("private") + + stream, err := client.OpenChannel(ctxb, req) + if err != nil { + return err + } + + for { + resp, err := stream.Recv() + if err == io.EOF { + return nil + } else if err != nil { + return err + } + + switch update := resp.Update.(type) { + case *lnrpc.OpenStatusUpdate_ChanPending: + txid, err := chainhash.NewHash(update.ChanPending.Txid) + if err != nil { + return err + } + + printJSON(struct { + FundingTxid string `json:"funding_txid"` + }{ + FundingTxid: txid.String(), + }, + ) + + if !ctx.Bool("block") { + return nil + } + + case *lnrpc.OpenStatusUpdate_ChanOpen: + channelPoint := update.ChanOpen.ChannelPoint + + // A channel point's funding txid can be get/set as a + // byte slice or a string. In the case it is a string, + // decode it. + var txidHash []byte + switch channelPoint.GetFundingTxid().(type) { + case *lnrpc.ChannelPoint_FundingTxidBytes: + txidHash = channelPoint.GetFundingTxidBytes() + case *lnrpc.ChannelPoint_FundingTxidStr: + s := channelPoint.GetFundingTxidStr() + h, err := chainhash.NewHashFromStr(s) + if err != nil { + return err + } + + txidHash = h[:] + } + + txid, err := chainhash.NewHash(txidHash) + if err != nil { + return err + } + + index := channelPoint.OutputIndex + printJSON(struct { + ChannelPoint string `json:"channel_point"` + }{ + ChannelPoint: fmt.Sprintf("%v:%v", txid, index), + }, + ) + } + } +} diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 2136677410..9446c4d398 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -577,269 +577,6 @@ func disconnectPeer(ctx *cli.Context) error { return nil } -// TODO(roasbeef): change default number of confirmations -var openChannelCommand = cli.Command{ - Name: "openchannel", - Category: "Channels", - Usage: "Open a channel to a node or an existing peer.", - Description: ` - Attempt to open a new channel to an existing peer with the key node-key - optionally blocking until the channel is 'open'. - - One can also connect to a node before opening a new channel to it by - setting its host:port via the --connect argument. For this to work, - the node_key must be provided, rather than the peer_id. This is optional. - - The channel will be initialized with local-amt satoshis local and push-amt - satoshis for the remote node. Note that specifying push-amt means you give that - amount to the remote node as part of the channel opening. Once the channel is open, - a channelPoint (txid:vout) of the funding output is returned. - - If the remote peer supports the option upfront shutdown feature bit (query - listpeers to see their supported feature bits), an address to enforce - payout of funds on cooperative close can optionally be provided. Note that - if you set this value, you will not be able to cooperatively close out to - another address. - - One can manually set the fee to be used for the funding transaction via either - the --conf_target or --sat_per_byte arguments. This is optional.`, - ArgsUsage: "node-key local-amt push-amt", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "node_key", - Usage: "the identity public key of the target node/peer " + - "serialized in compressed format", - }, - cli.StringFlag{ - Name: "connect", - Usage: "(optional) the host:port of the target node", - }, - cli.IntFlag{ - Name: "local_amt", - Usage: "the number of satoshis the wallet should commit to the channel", - }, - cli.IntFlag{ - Name: "push_amt", - Usage: "the number of satoshis to give the remote side " + - "as part of the initial commitment state, " + - "this is equivalent to first opening a " + - "channel and sending the remote party funds, " + - "but done all in one step", - }, - cli.BoolFlag{ - Name: "block", - Usage: "block and wait until the channel is fully open", - }, - cli.Int64Flag{ - Name: "conf_target", - Usage: "(optional) the number of blocks that the " + - "transaction *should* confirm in, will be " + - "used for fee estimation", - }, - cli.Int64Flag{ - Name: "sat_per_byte", - Usage: "(optional) a manual fee expressed in " + - "sat/byte that should be used when crafting " + - "the transaction", - }, - cli.BoolFlag{ - Name: "private", - Usage: "make the channel private, such that it won't " + - "be announced to the greater network, and " + - "nodes other than the two channel endpoints " + - "must be explicitly told about it to be able " + - "to route through it", - }, - cli.Int64Flag{ - Name: "min_htlc_msat", - Usage: "(optional) the minimum value we will require " + - "for incoming HTLCs on the channel", - }, - cli.Uint64Flag{ - Name: "remote_csv_delay", - Usage: "(optional) the number of blocks we will require " + - "our channel counterparty to wait before accessing " + - "its funds in case of unilateral close. If this is " + - "not set, we will scale the value according to the " + - "channel size", - }, - cli.Uint64Flag{ - Name: "min_confs", - Usage: "(optional) the minimum number of confirmations " + - "each one of your outputs used for the funding " + - "transaction must satisfy", - Value: 1, - }, - cli.StringFlag{ - Name: "close_address", - Usage: "(optional) an address to enforce payout of our " + - "funds to on cooperative close. Note that if this " + - "value is set on channel open, you will *not* be " + - "able to cooperatively close to a different address.", - }, - }, - Action: actionDecorator(openChannel), -} - -func openChannel(ctx *cli.Context) error { - // TODO(roasbeef): add deadline to context - ctxb := context.Background() - client, cleanUp := getClient(ctx) - defer cleanUp() - - args := ctx.Args() - var err error - - // Show command help if no arguments provided - if ctx.NArg() == 0 && ctx.NumFlags() == 0 { - cli.ShowCommandHelp(ctx, "openchannel") - return nil - } - - minConfs := int32(ctx.Uint64("min_confs")) - req := &lnrpc.OpenChannelRequest{ - TargetConf: int32(ctx.Int64("conf_target")), - SatPerByte: ctx.Int64("sat_per_byte"), - MinHtlcMsat: ctx.Int64("min_htlc_msat"), - RemoteCsvDelay: uint32(ctx.Uint64("remote_csv_delay")), - MinConfs: minConfs, - SpendUnconfirmed: minConfs == 0, - CloseAddress: ctx.String("close_address"), - } - - switch { - case ctx.IsSet("node_key"): - nodePubHex, err := hex.DecodeString(ctx.String("node_key")) - if err != nil { - return fmt.Errorf("unable to decode node public key: %v", err) - } - req.NodePubkey = nodePubHex - - case args.Present(): - nodePubHex, err := hex.DecodeString(args.First()) - if err != nil { - return fmt.Errorf("unable to decode node public key: %v", err) - } - args = args.Tail() - req.NodePubkey = nodePubHex - default: - return fmt.Errorf("node id argument missing") - } - - // As soon as we can confirm that the node's node_key was set, rather - // than the peer_id, we can check if the host:port was also set to - // connect to it before opening the channel. - if req.NodePubkey != nil && ctx.IsSet("connect") { - addr := &lnrpc.LightningAddress{ - Pubkey: hex.EncodeToString(req.NodePubkey), - Host: ctx.String("connect"), - } - - req := &lnrpc.ConnectPeerRequest{ - Addr: addr, - Perm: false, - } - - // Check if connecting to the node was successful. - // We discard the peer id returned as it is not needed. - _, err := client.ConnectPeer(ctxb, req) - if err != nil && - !strings.Contains(err.Error(), "already connected") { - return err - } - } - - switch { - case ctx.IsSet("local_amt"): - req.LocalFundingAmount = int64(ctx.Int("local_amt")) - case args.Present(): - req.LocalFundingAmount, err = strconv.ParseInt(args.First(), 10, 64) - if err != nil { - return fmt.Errorf("unable to decode local amt: %v", err) - } - args = args.Tail() - default: - return fmt.Errorf("local amt argument missing") - } - - if ctx.IsSet("push_amt") { - req.PushSat = int64(ctx.Int("push_amt")) - } else if args.Present() { - req.PushSat, err = strconv.ParseInt(args.First(), 10, 64) - if err != nil { - return fmt.Errorf("unable to decode push amt: %v", err) - } - } - - req.Private = ctx.Bool("private") - - stream, err := client.OpenChannel(ctxb, req) - if err != nil { - return err - } - - for { - resp, err := stream.Recv() - if err == io.EOF { - return nil - } else if err != nil { - return err - } - - switch update := resp.Update.(type) { - case *lnrpc.OpenStatusUpdate_ChanPending: - txid, err := chainhash.NewHash(update.ChanPending.Txid) - if err != nil { - return err - } - - printJSON(struct { - FundingTxid string `json:"funding_txid"` - }{ - FundingTxid: txid.String(), - }, - ) - - if !ctx.Bool("block") { - return nil - } - - case *lnrpc.OpenStatusUpdate_ChanOpen: - channelPoint := update.ChanOpen.ChannelPoint - - // A channel point's funding txid can be get/set as a - // byte slice or a string. In the case it is a string, - // decode it. - var txidHash []byte - switch channelPoint.GetFundingTxid().(type) { - case *lnrpc.ChannelPoint_FundingTxidBytes: - txidHash = channelPoint.GetFundingTxidBytes() - case *lnrpc.ChannelPoint_FundingTxidStr: - s := channelPoint.GetFundingTxidStr() - h, err := chainhash.NewHashFromStr(s) - if err != nil { - return err - } - - txidHash = h[:] - } - - txid, err := chainhash.NewHash(txidHash) - if err != nil { - return err - } - - index := channelPoint.OutputIndex - printJSON(struct { - ChannelPoint string `json:"channel_point"` - }{ - ChannelPoint: fmt.Sprintf("%v:%v", txid, index), - }, - ) - } - } -} - // TODO(roasbeef): also allow short relative channel ID. var closeChannelCommand = cli.Command{ From c8922279533e147b818ddbad2d16ab8799a28111 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:20 +0200 Subject: [PATCH 336/562] lncli: add PSBT to openchannel command We add a new flag --psbt to the openchannel command which triggers an interactive conversation between the command line and the user. --- cmd/lncli/cmd_open_channel.go | 452 +++++++++++++++++++++++++++++++--- 1 file changed, 418 insertions(+), 34 deletions(-) diff --git a/cmd/lncli/cmd_open_channel.go b/cmd/lncli/cmd_open_channel.go index ef2ccc2e33..d86b65cf08 100644 --- a/cmd/lncli/cmd_open_channel.go +++ b/cmd/lncli/cmd_open_channel.go @@ -2,6 +2,8 @@ package main import ( "context" + "crypto/rand" + "encoding/base64" "encoding/hex" "fmt" "io" @@ -9,10 +11,39 @@ import ( "strings" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnwallet/chanfunding" + "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" ) +const ( + defaultUtxoMinConf = 1 + userMsgFund = `PSBT funding initiated with peer %x. +Please create a PSBT that sends %v (%d satoshi) to the funding address %s. + +Note: The whole process should be completed within 10 minutes, otherwise there +is a risk of the remote node timing out and canceling the funding process. + +Example with bitcoind: + bitcoin-cli walletcreatefundedpsbt [] '[{"%s":%.8f}]' + +If you are using a wallet that can fund a PSBT directly (currently not possible +with bitcoind), you can use this PSBT that contains the same address and amount: +%s + +Paste the funded PSBT here to continue the funding flow. +Base64 encoded PSBT: ` + + userMsgSign = ` +PSBT verified by lnd, please continue the funding flow by signing the PSBT by +all required parties/devices. Once the transaction is fully signed, paste it +again here. + +Base64 encoded signed PSBT: ` +) + // TODO(roasbeef): change default number of confirmations var openChannelCommand = cli.Command{ Name: "openchannel", @@ -104,7 +135,7 @@ var openChannelCommand = cli.Command{ Usage: "(optional) the minimum number of confirmations " + "each one of your outputs used for the funding " + "transaction must satisfy", - Value: 1, + Value: defaultUtxoMinConf, }, cli.StringFlag{ Name: "close_address", @@ -113,6 +144,21 @@ var openChannelCommand = cli.Command{ "value is set on channel open, you will *not* be " + "able to cooperatively close to a different address.", }, + cli.BoolFlag{ + Name: "psbt", + Usage: "start an interactive mode that initiates " + + "funding through a partially signed bitcoin " + + "transaction (PSBT), allowing the channel " + + "funds to be added and signed from a hardware " + + "or other offline device.", + }, + cli.StringFlag{ + Name: "base_psbt", + Usage: "when using the interactive PSBT mode to open " + + "a new channel, use this base64 encoded PSBT " + + "as a base and add the new channel output to " + + "it instead of creating a new, empty one.", + }, }, Action: actionDecorator(openChannel), } @@ -128,7 +174,7 @@ func openChannel(ctx *cli.Context) error { // Show command help if no arguments provided if ctx.NArg() == 0 && ctx.NumFlags() == 0 { - cli.ShowCommandHelp(ctx, "openchannel") + _ = cli.ShowCommandHelp(ctx, "openchannel") return nil } @@ -209,6 +255,12 @@ func openChannel(ctx *cli.Context) error { req.Private = ctx.Bool("private") + // PSBT funding is a more involved, interactive process that is too + // large to also fit into this already long function. + if ctx.Bool("psbt") { + return openChannelPsbt(ctx, client, req) + } + stream, err := client.OpenChannel(ctxb, req) if err != nil { return err @@ -224,54 +276,386 @@ func openChannel(ctx *cli.Context) error { switch update := resp.Update.(type) { case *lnrpc.OpenStatusUpdate_ChanPending: - txid, err := chainhash.NewHash(update.ChanPending.Txid) + err := printChanPending(update) if err != nil { return err } - printJSON(struct { - FundingTxid string `json:"funding_txid"` - }{ - FundingTxid: txid.String(), + if !ctx.Bool("block") { + return nil + } + + case *lnrpc.OpenStatusUpdate_ChanOpen: + return printChanOpen(update) + } + } +} + +// openChannelPsbt starts an interactive channel open protocol that uses a +// partially signed bitcoin transaction (PSBT) to fund the channel output. The +// protocol involves several steps between the RPC server and the CLI client: +// +// RPC server CLI client +// | | +// | |<------open channel (stream)-----| +// | |-------ready for funding----->| | +// | |<------PSBT verify------------| | +// | |-------ready for signing----->| | +// | |<------PSBT finalize----------| | +// | |-------channel pending------->| | +// | |-------channel open------------->| +// | | +func openChannelPsbt(ctx *cli.Context, client lnrpc.LightningClient, + req *lnrpc.OpenChannelRequest) error { + + var ( + pendingChanID [32]byte + shimPending = true + basePsbtBytes []byte + quit = make(chan struct{}) + srvMsg = make(chan *lnrpc.OpenStatusUpdate, 1) + srvErr = make(chan error, 1) + ctxc, cancel = context.WithCancel(context.Background()) + ) + defer cancel() + + // Make sure the user didn't supply any command line flags that are + // incompatible with PSBT funding. + err := checkPsbtFlags(req) + if err != nil { + return err + } + + // If the user supplied a base PSBT, only make sure it's valid base64. + // The RPC server will make sure it's also a valid PSBT. + basePsbt := ctx.String("base_psbt") + if basePsbt != "" { + basePsbtBytes, err = base64.StdEncoding.DecodeString(basePsbt) + if err != nil { + return fmt.Errorf("error parsing base PSBT: %v", err) + } + } + + // Generate a new, random pending channel ID that we'll use as the main + // identifier when sending update messages to the RPC server. + if _, err := rand.Read(pendingChanID[:]); err != nil { + return fmt.Errorf("unable to generate random chan ID: %v", err) + } + fmt.Printf("Starting PSBT funding flow with pending channel ID %x.\n", + pendingChanID) + + // maybeCancelShim is a helper function that cancels the funding shim + // with the RPC server in case we end up aborting early. + maybeCancelShim := func() { + // If the user canceled while there was still a shim registered + // with the wallet, release the resources now. + if shimPending { + fmt.Printf("Canceling PSBT funding flow for pending "+ + "channel ID %x.\n", pendingChanID) + cancelMsg := &lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_ShimCancel{ + ShimCancel: &lnrpc.FundingShimCancel{ + PendingChanId: pendingChanID[:], + }, + }, + } + err := sendFundingState(ctxc, ctx, cancelMsg) + if err != nil { + fmt.Printf("Error canceling shim: %v\n", err) + } + shimPending = false + } + + // Abort the stream connection to the server. + cancel() + } + defer maybeCancelShim() + + // Create the PSBT funding shim that will tell the funding manager we + // want to use a PSBT. + req.FundingShim = &lnrpc.FundingShim{ + Shim: &lnrpc.FundingShim_PsbtShim{ + PsbtShim: &lnrpc.PsbtShim{ + PendingChanId: pendingChanID[:], + BasePsbt: basePsbtBytes, }, + }, + } + + // Start the interactive process by opening the stream connection to the + // daemon. If the user cancels by pressing we need to cancel + // the shim. To not just kill the process on interrupt, we need to + // explicitly capture the signal. + stream, err := client.OpenChannel(ctxc, req) + if err != nil { + return fmt.Errorf("opening stream to server failed: %v", err) + } + signal.Intercept() + + // We also need to spawn a goroutine that reads from the server. This + // will copy the messages to the channel as long as they come in or add + // exactly one error to the error stream and then bail out. + go func() { + for { + // Recv blocks until a message or error arrives. + resp, err := stream.Recv() + if err == io.EOF { + srvErr <- fmt.Errorf("lnd shutting down: %v", + err) + return + } else if err != nil { + srvErr <- fmt.Errorf("got error from server: "+ + "%v", err) + return + } + + // Don't block on sending in case of shutting down. + select { + case srvMsg <- resp: + case <-quit: + return + } + } + }() + + // Spawn another goroutine that only handles abort from user or errors + // from the server. Both will trigger an attempt to cancel the shim with + // the server. + go func() { + select { + case <-signal.ShutdownChannel(): + fmt.Printf("\nInterrupt signal received.\n") + close(quit) + + case err := <-srvErr: + fmt.Printf("\nError received: %v\n", err) + + // If the remote peer canceled on us, the reservation + // has already been deleted. We don't need to try to + // remove it again, this would just produce another + // error. + cancelErr := chanfunding.ErrRemoteCanceled.Error() + if err != nil && strings.Contains(err.Error(), cancelErr) { + shimPending = false + } + close(quit) + + case <-quit: + } + }() + + // Our main event loop where we wait for triggers + for { + var srvResponse *lnrpc.OpenStatusUpdate + select { + case srvResponse = <-srvMsg: + case <-quit: + return nil + } + + switch update := srvResponse.Update.(type) { + case *lnrpc.OpenStatusUpdate_PsbtFund: + // First tell the user how to create the PSBT with the + // address and amount we now know. + amt := btcutil.Amount(update.PsbtFund.FundingAmount) + addr := update.PsbtFund.FundingAddress + fmt.Printf( + userMsgFund, req.NodePubkey, amt, amt, addr, + addr, amt.ToBTC(), + base64.StdEncoding.EncodeToString( + update.PsbtFund.Psbt, + ), ) - if !ctx.Bool("block") { + // Read the user's response and send it to the server to + // verify everything's correct before anything is + // signed. + psbtBase64, err := readLine(quit) + if err == io.EOF { return nil } + if err != nil { + return fmt.Errorf("reading from console "+ + "failed: %v", err) + } + psbt, err := base64.StdEncoding.DecodeString( + strings.TrimSpace(psbtBase64), + ) + if err != nil { + return fmt.Errorf("base64 decode failed: %v", + err) + } + verifyMsg := &lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{ + PsbtVerify: &lnrpc.FundingPsbtVerify{ + FundedPsbt: psbt, + PendingChanId: pendingChanID[:], + }, + }, + } + err = sendFundingState(ctxc, ctx, verifyMsg) + if err != nil { + return fmt.Errorf("verifying PSBT by lnd "+ + "failed: %v", err) + } - case *lnrpc.OpenStatusUpdate_ChanOpen: - channelPoint := update.ChanOpen.ChannelPoint - - // A channel point's funding txid can be get/set as a - // byte slice or a string. In the case it is a string, - // decode it. - var txidHash []byte - switch channelPoint.GetFundingTxid().(type) { - case *lnrpc.ChannelPoint_FundingTxidBytes: - txidHash = channelPoint.GetFundingTxidBytes() - case *lnrpc.ChannelPoint_FundingTxidStr: - s := channelPoint.GetFundingTxidStr() - h, err := chainhash.NewHashFromStr(s) - if err != nil { - return err - } - - txidHash = h[:] + // Now that we know the PSBT looks good, we can let it + // be signed by the user. + fmt.Print(userMsgSign) + + // Read the signed PSBT and send it to lnd. + psbtBase64, err = readLine(quit) + if err == io.EOF { + return nil + } + if err != nil { + return fmt.Errorf("reading from console "+ + "failed: %v", err) + } + psbt, err = base64.StdEncoding.DecodeString( + strings.TrimSpace(psbtBase64), + ) + if err != nil { + return fmt.Errorf("base64 decode failed: %v", + err) } + finalizeMsg := &lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_PsbtFinalize{ + PsbtFinalize: &lnrpc.FundingPsbtFinalize{ + SignedPsbt: psbt, + PendingChanId: pendingChanID[:], + }, + }, + } + err = sendFundingState(ctxc, ctx, finalizeMsg) + if err != nil { + return fmt.Errorf("finalizing PSBT funding "+ + "flow failed: %v", err) + } + + case *lnrpc.OpenStatusUpdate_ChanPending: + // As soon as the channel is pending, there is no more + // shim that needs to be canceled. If the user + // interrupts now, we don't need to clean up anything. + shimPending = false - txid, err := chainhash.NewHash(txidHash) + err := printChanPending(update) if err != nil { return err } - index := channelPoint.OutputIndex - printJSON(struct { - ChannelPoint string `json:"channel_point"` - }{ - ChannelPoint: fmt.Sprintf("%v:%v", txid, index), - }, - ) + if !ctx.Bool("block") { + return nil + } + + case *lnrpc.OpenStatusUpdate_ChanOpen: + return printChanOpen(update) + } + } +} + +// printChanOpen prints the channel point of the channel open message. +func printChanOpen(update *lnrpc.OpenStatusUpdate_ChanOpen) error { + channelPoint := update.ChanOpen.ChannelPoint + + // A channel point's funding txid can be get/set as a + // byte slice or a string. In the case it is a string, + // decode it. + var txidHash []byte + switch channelPoint.GetFundingTxid().(type) { + case *lnrpc.ChannelPoint_FundingTxidBytes: + txidHash = channelPoint.GetFundingTxidBytes() + case *lnrpc.ChannelPoint_FundingTxidStr: + s := channelPoint.GetFundingTxidStr() + h, err := chainhash.NewHashFromStr(s) + if err != nil { + return err + } + + txidHash = h[:] + } + + txid, err := chainhash.NewHash(txidHash) + if err != nil { + return err + } + + index := channelPoint.OutputIndex + printJSON(struct { + ChannelPoint string `json:"channel_point"` + }{ + ChannelPoint: fmt.Sprintf("%v:%v", txid, index), + }) + return nil +} + +// printChanPending prints the funding transaction ID of the channel pending +// message. +func printChanPending(update *lnrpc.OpenStatusUpdate_ChanPending) error { + txid, err := chainhash.NewHash(update.ChanPending.Txid) + if err != nil { + return err + } + + printJSON(struct { + FundingTxid string `json:"funding_txid"` + }{ + FundingTxid: txid.String(), + }) + return nil +} + +// readLine reads a line from standard in but does not block in case of a +// system interrupt like syscall.SIGINT (Ctrl+C). +func readLine(quit chan struct{}) (string, error) { + msg := make(chan string, 1) + + // In a normal console, reading from stdin won't signal EOF when the + // user presses Ctrl+C. That's why we need to put this in a separate + // goroutine so it doesn't block. + go func() { + for { + var str string + _, _ = fmt.Scan(&str) + msg <- str + return } + }() + for { + select { + case <-quit: + return "", io.EOF + + case str := <-msg: + return str, nil + } + } +} + +// checkPsbtFlags make sure a request to open a channel doesn't set any +// parameters that are incompatible with the PSBT funding flow. +func checkPsbtFlags(req *lnrpc.OpenChannelRequest) error { + if req.MinConfs != defaultUtxoMinConf || req.SpendUnconfirmed { + return fmt.Errorf("specifying minimum confirmations for PSBT " + + "funding is not supported") } + if req.TargetConf != 0 || req.SatPerByte != 0 { + return fmt.Errorf("setting fee estimation parameters not " + + "supported for PSBT funding") + } + return nil +} + +// sendFundingState sends a single funding state step message by using a new +// client connection. This is necessary if the whole funding flow takes longer +// than the default macaroon timeout, then we cannot use a single client +// connection. +func sendFundingState(cancelCtx context.Context, cliCtx *cli.Context, + msg *lnrpc.FundingTransitionMsg) error { + + client, cleanUp := getClient(cliCtx) + defer cleanUp() + + _, err := client.FundingStateStep(cancelCtx, msg) + return err } From c4f20dada4f997c9f48b6ed5b7da871dea37ef7c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:21 +0200 Subject: [PATCH 337/562] lntest: test PSBT channel funding --- lntest/itest/lnd_test.go | 4 + lntest/itest/psbt.go | 350 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+) create mode 100644 lntest/itest/psbt.go diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 61645517da..f0ccc4075c 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -14875,6 +14875,10 @@ var testsCases = []*testCase{ name: "external channel funding", test: testExternalFundingChanPoint, }, + { + name: "psbt channel funding", + test: testPsbtChanFunding, + }, } // TestLightningNetworkDaemon performs a series of integration tests amongst a diff --git a/lntest/itest/psbt.go b/lntest/itest/psbt.go new file mode 100644 index 0000000000..86f2462439 --- /dev/null +++ b/lntest/itest/psbt.go @@ -0,0 +1,350 @@ +// +build rpctest + +package itest + +import ( + "bytes" + "context" + "crypto/rand" + "fmt" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/psbt" + "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lntest" +) + +// testPsbtChanFunding makes sure a channel can be opened between carol and dave +// by using a Partially Signed Bitcoin Transaction that funds the channel +// multisig funding output. +func testPsbtChanFunding(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() + const chanSize = lnd.MaxBtcFundingAmount + + // First, we'll create two new nodes that we'll use to open channel + // between for this test. + carol, err := net.NewNode("carol", nil) + if err != nil { + t.Fatalf("unable to start new node: %v", err) + } + defer shutdownAndAssert(net, t, carol) + + dave, err := net.NewNode("dave", nil) + if err != nil { + t.Fatalf("unable to start new node: %v", err) + } + defer shutdownAndAssert(net, t, dave) + + // Before we start the test, we'll ensure both sides are connected so + // the funding flow can be properly executed. + ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + err = net.EnsureConnected(ctxt, carol, dave) + if err != nil { + t.Fatalf("unable to connect peers: %v", err) + } + + // At this point, we can begin our PSBT channel funding workflow. We'll + // start by generating a pending channel ID externally that will be used + // to track this new funding type. + var pendingChanID [32]byte + if _, err := rand.Read(pendingChanID[:]); err != nil { + t.Fatalf("unable to gen pending chan ID: %v", err) + } + + // Now that we have the pending channel ID, Carol will open the channel + // by specifying a PSBT shim. + ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + chanUpdates, psbtBytes, err := openChannelPsbt( + ctxt, carol, dave, lntest.OpenChannelParams{ + Amt: chanSize, + FundingShim: &lnrpc.FundingShim{ + Shim: &lnrpc.FundingShim_PsbtShim{ + PsbtShim: &lnrpc.PsbtShim{ + PendingChanId: pendingChanID[:], + }, + }, + }, + }, + ) + if err != nil { + t.Fatalf("unable to open channel: %v", err) + } + packet, err := psbt.NewFromRawBytes(bytes.NewReader(psbtBytes), false) + if err != nil { + t.Fatalf("unable to parse returned PSBT: %v", err) + } + + // We'll now create a fully signed transaction that sends to the outputs + // encoded in the PSBT. We'll let the miner do it and convert the final + // TX into a PSBT, that's way easier than assembling a PSBT manually. + tx, err := net.Miner.CreateTransaction(packet.UnsignedTx.TxOut, 5, true) + if err != nil { + t.Fatalf("unable to create funding transaction: %v", err) + } + + // The helper function splits the final TX into the non-witness data + // encoded in a PSBT and the witness data returned separately. + unsignedPsbt, scripts, witnesses, err := createPsbtFromSignedTx(tx) + if err != nil { + t.Fatalf("unable to convert funding transaction into PSBT: %v", + err) + } + + // The PSBT will also be checked if there are large enough inputs + // present. We need to add some fake UTXO information to the PSBT to + // tell it what size of inputs we have. + for idx, txIn := range unsignedPsbt.UnsignedTx.TxIn { + utxPrevOut := txIn.PreviousOutPoint.Index + fakeUtxo := &wire.MsgTx{ + Version: 2, + TxIn: []*wire.TxIn{{}}, + TxOut: make([]*wire.TxOut, utxPrevOut+1), + } + for idx := range fakeUtxo.TxOut { + fakeUtxo.TxOut[idx] = &wire.TxOut{} + } + fakeUtxo.TxOut[utxPrevOut].Value = 10000000000 + unsignedPsbt.Inputs[idx].NonWitnessUtxo = fakeUtxo + } + + // Serialize the PSBT with the faked UTXO information. + var buf bytes.Buffer + err = unsignedPsbt.Serialize(&buf) + if err != nil { + t.Fatalf("error serializing PSBT: %v", err) + } + + // We have a PSBT that has no witness data yet, which is exactly what we + // need for the next step: Verify the PSBT with the funding intent. + _, err = carol.FundingStateStep(ctxb, &lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{ + PsbtVerify: &lnrpc.FundingPsbtVerify{ + PendingChanId: pendingChanID[:], + FundedPsbt: buf.Bytes(), + }, + }, + }) + if err != nil { + t.Fatalf("error verifying PSBT with funding intent: %v", err) + } + + // Now we'll add the witness data back into the PSBT to make it a + // complete and signed transaction that can be finalized. We'll trick + // a bit by putting the script sig back directly, because we know we + // will only get non-witness outputs from the miner wallet. + for idx := range tx.TxIn { + if len(witnesses[idx]) > 0 { + t.Fatalf("unexpected witness inputs in wallet TX") + } + unsignedPsbt.Inputs[idx].FinalScriptSig = scripts[idx] + } + + // We've signed our PSBT now, let's pass it to the intent again. + buf.Reset() + err = unsignedPsbt.Serialize(&buf) + if err != nil { + t.Fatalf("error serializing PSBT: %v", err) + } + _, err = carol.FundingStateStep(ctxb, &lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_PsbtFinalize{ + PsbtFinalize: &lnrpc.FundingPsbtFinalize{ + PendingChanId: pendingChanID[:], + SignedPsbt: buf.Bytes(), + }, + }, + }) + if err != nil { + t.Fatalf("error finalizing PSBT with funding intent: %v", err) + } + + // Consume the "channel pending" update. This waits until the funding + // transaction has been published. + ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + updateResp, err := receiveChanUpdate(ctxt, chanUpdates) + if err != nil { + t.Fatalf("unable to consume channel update message: %v", err) + } + upd, ok := updateResp.Update.(*lnrpc.OpenStatusUpdate_ChanPending) + if !ok { + t.Fatalf("expected PSBT funding update, instead got %v", + updateResp) + } + chanPoint := &lnrpc.ChannelPoint{ + FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ + FundingTxidBytes: upd.ChanPending.Txid, + }, + OutputIndex: upd.ChanPending.OutputIndex, + } + + // Great, now we can mine a block to get the transaction confirmed, then + // wait for the new channel to be propagated through the network. + txHash := tx.TxHash() + block := mineBlocks(t, net, 6, 1)[0] + assertTxInBlock(t, block, &txHash) + ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + err = carol.WaitForNetworkChannelOpen(ctxt, chanPoint) + if err != nil { + t.Fatalf("carol didn't report channel: %v", err) + } + + // With the channel open, ensure that it is counted towards Carol's + // total channel balance. + balReq := &lnrpc.ChannelBalanceRequest{} + ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + balRes, err := carol.ChannelBalance(ctxt, balReq) + if err != nil { + t.Fatalf("unable to get carol's balance: %v", err) + } + if balRes.Balance == 0 { + t.Fatalf("carol has an empty channel balance") + } + + // Next, to make sure the channel functions as normal, we'll make some + // payments within the channel. + payAmt := btcutil.Amount(100000) + invoice := &lnrpc.Invoice{ + Memo: "new chans", + Value: int64(payAmt), + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + resp, err := dave.AddInvoice(ctxt, invoice) + if err != nil { + t.Fatalf("unable to add invoice: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = completePaymentRequests( + ctxt, carol, []string{resp.PaymentRequest}, true, + ) + if err != nil { + t.Fatalf("unable to make payments between Carol and Dave") + } + + // To conclude, we'll close the newly created channel between Carol and + // Dave. This function will also block until the channel is closed and + // will additionally assert the relevant channel closing post + // conditions. + ctxt, cancel = context.WithTimeout(ctxb, channelCloseTimeout) + defer cancel() + closeChannelAndAssert(ctxt, t, net, carol, chanPoint, false) +} + +// openChannelPsbt attempts to open a channel between srcNode and destNode with +// the passed channel funding parameters. If the passed context has a timeout, +// then if the timeout is reached before the channel pending notification is +// received, an error is returned. An error is returned if the expected step +// of funding the PSBT is not received from the source node. +func openChannelPsbt(ctx context.Context, srcNode, destNode *lntest.HarnessNode, + p lntest.OpenChannelParams) (lnrpc.Lightning_OpenChannelClient, []byte, + error) { + + // Wait until srcNode and destNode have the latest chain synced. + // Otherwise, we may run into a check within the funding manager that + // prevents any funding workflows from being kicked off if the chain + // isn't yet synced. + if err := srcNode.WaitForBlockchainSync(ctx); err != nil { + return nil, nil, fmt.Errorf("unable to sync srcNode chain: %v", + err) + } + if err := destNode.WaitForBlockchainSync(ctx); err != nil { + return nil, nil, fmt.Errorf("unable to sync destNode chain: %v", + err) + } + + // Send the request to open a channel to the source node now. This will + // open a long-lived stream where we'll receive status updates about the + // progress of the channel. + respStream, err := srcNode.OpenChannel(ctx, &lnrpc.OpenChannelRequest{ + NodePubkey: destNode.PubKey[:], + LocalFundingAmount: int64(p.Amt), + PushSat: int64(p.PushAmt), + Private: p.Private, + SpendUnconfirmed: p.SpendUnconfirmed, + MinHtlcMsat: int64(p.MinHtlc), + FundingShim: p.FundingShim, + }) + if err != nil { + return nil, nil, fmt.Errorf("unable to open channel between "+ + "source and dest: %v", err) + } + + // Consume the "PSBT funding ready" update. This waits until the node + // notifies us that the PSBT can now be funded. + resp, err := receiveChanUpdate(ctx, respStream) + if err != nil { + return nil, nil, fmt.Errorf("unable to consume channel update "+ + "message: %v", err) + } + upd, ok := resp.Update.(*lnrpc.OpenStatusUpdate_PsbtFund) + if !ok { + return nil, nil, fmt.Errorf("expected PSBT funding update, "+ + "instead got %v", resp) + } + return respStream, upd.PsbtFund.Psbt, nil +} + +// receiveChanUpdate waits until a message is received on the stream or the +// context is canceled. The context must have a timeout or must be canceled +// in case no message is received, otherwise this function will block forever. +func receiveChanUpdate(ctx context.Context, + stream lnrpc.Lightning_OpenChannelClient) (*lnrpc.OpenStatusUpdate, + error) { + + chanMsg := make(chan *lnrpc.OpenStatusUpdate) + errChan := make(chan error) + go func() { + // Consume one message. This will block until the message is + // recieved. + resp, err := stream.Recv() + if err != nil { + errChan <- err + return + } + chanMsg <- resp + }() + + select { + case <-ctx.Done(): + return nil, fmt.Errorf("timeout reached before chan pending " + + "update sent") + + case err := <-errChan: + return nil, err + + case updateMsg := <-chanMsg: + return updateMsg, nil + } +} + +// createPsbtFromSignedTx is a utility function to create a PSBT from an +// already-signed transaction, so we can test reconstructing, signing and +// extracting it. Returned are: an unsigned transaction serialization, a list +// of scriptSigs, one per input, and a list of witnesses, one per input. +func createPsbtFromSignedTx(tx *wire.MsgTx) (*psbt.Packet, [][]byte, + []wire.TxWitness, error) { + + scriptSigs := make([][]byte, 0, len(tx.TxIn)) + witnesses := make([]wire.TxWitness, 0, len(tx.TxIn)) + tx2 := tx.Copy() + + // Blank out signature info in inputs + for i, tin := range tx2.TxIn { + tin.SignatureScript = nil + scriptSigs = append(scriptSigs, tx.TxIn[i].SignatureScript) + tin.Witness = nil + witnesses = append(witnesses, tx.TxIn[i].Witness) + } + + // Outputs always contain: (value, scriptPubkey) so don't need + // amending. Now tx2 is tx with all signing data stripped out + unsignedPsbt, err := psbt.NewFromUnsignedTx(tx2) + if err != nil { + return nil, nil, nil, err + } + return unsignedPsbt, scriptSigs, witnesses, nil +} From 2f371556da05d5954d000255ebbb56cf476872c3 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 31 Mar 2020 09:13:23 +0200 Subject: [PATCH 338/562] docs: add PSBT funding tutorial --- docs/psbt.md | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 docs/psbt.md diff --git a/docs/psbt.md b/docs/psbt.md new file mode 100644 index 0000000000..3d51dbc7fb --- /dev/null +++ b/docs/psbt.md @@ -0,0 +1,216 @@ +# PSBT + +This document describes various use cases around the topic of Partially Signed +Bitcoin Transactions (PSBTs). Currently only channel funding is possible with +PSBTs but more features are planned. + +See [BIP174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) for +a full description of the PSBT format and the different _roles_ that a +participant in a PSBT can have. + +## Opening a channel by using a PSBT + +This is a step-by-step guide on how to open a channel with `lnd` by using a PSBT +as the funding transaction. +We will use `bitcoind` to create and sign the transaction just to keep the +example simple. Of course any other PSBT compatible wallet could be used and the +process would likely be spread out over multiple signing steps. The goal of this +example is not to cover each and every possible edge case but to help users of +`lnd` understand what inputs the `lncli` utility expects. + +The goal is to open a channel of 1'234'567 satoshis to the node +`03db1e56e5f76bc4018cf6f03d1bb98a7ae96e3f18535e929034f85e7f1ca2b8ac` by using +a PSBT. That means, `lnd` can have a wallet balance of `0` and is still able to +open a channel. We'll jump into an example right away. + +The new funding flow has a small caveat: _Time matters_. + +When opening a channel using the PSBT flow, we start the negotiation +with the remote peer immediately so we can obtain their multisig key they are +going to use for the channel. Then we pause the whole process until we get a +fully signed transaction back from the user. Unfortunately there is no reliable +way to know after how much time the remote node starts to clean up and "forgets" +about the pending channel. If the remote node is an `lnd` node, we know it's +after 10 minutes. **So as long as the whole process takes less than 10 minutes, +everything should work fine.** + +### 1. Use the new `--psbt` flag in `lncli openchannel` + +The new `--psbt` flag in the `openchannel` command starts an interactive dialog +between `lncli` and the user. Below the command you see an example output from +a regtest setup. Of course all values will be different. + +```bash +$ lncli openchannel --node_key 03db1e56e5f76bc4018cf6f03d1bb98a7ae96e3f18535e929034f85e7f1ca2b8ac --local_amt 1234567 --psbt + +Starting PSBT funding flow with pending channel ID fc7853889a04d33b8115bd79ebc99c5eea80d894a0bead40fae5a06bcbdccd3d. +PSBT funding initiated with peer 03db1e56e5f76bc4018cf6f03d1bb98a7ae96e3f18535e929034f85e7f1ca2b8ac. +Please create a PSBT that sends 0.01234567 BTC (1234567 satoshi) to the funding address bcrt1qh33ghvgjj3ef625nl9jxz6nnrz2z9e65vsdey7w5msrklgr6rc0sv0s08q. + +Example with bitcoind: + bitcoin-cli walletcreatefundedpsbt [] '[{"bcrt1qh33ghvgjj3ef625nl9jxz6nnrz2z9e65vsdey7w5msrklgr6rc0sv0s08q":0.01234567}]' + +Or if you are using a wallet that can fund a PSBT directly (currently not +possible with bitcoind), you can use this PSBT that contains the same address +and amount: cHNidP8BADUCAAAAAAGH1hIAAAAAACIAILxii7ESlHKdKpP5ZGFqcxiUIudUZBuSedTcB2+geh4fAAAAAAAA + +Paste the funded PSBT here to continue the funding flow. +Base64 encoded PSBT: +``` + +The command line now waits until a PSBT is entered. We'll create one in the next +step. Make sure to use a new shell window/tab for the next commands and leave +the prompt from the `openchannel` running as is. + +### 2. Use `bitcoind` to create a funding transaction + +The output of the last command already gave us an example command to use with +`bitcoind`. We'll go ahead and execute it now. The meaning of this command is +something like "bitcoind, give me a PSBT that sends the given amount to the +given address, choose any input you see fit": + +```bash +$ bitcoin-cli walletcreatefundedpsbt [] '[{"bcrt1qh33ghvgjj3ef625nl9jxz6nnrz2z9e65vsdey7w5msrklgr6rc0sv0s08q":0.01234567}]' + +{ + "psbt": "cHNidP8BAH0CAAAAAbxLLf9+AYfqfF69QAQuETnL6cas7GDiWBZF+3xxc/Y/AAAAAAD+////AofWEgAAAAAAIgAgvGKLsRKUcp0qk/lkYWpzGJQi51RkG5J51NwHb6B6Hh+1If0jAQAAABYAFL+6THEGhybJnOkFGSRFbtCcPOG8AAAAAAABAR8wBBAkAQAAABYAFHemJ11XF7CU7WXBIJLD/qZF+6jrAAAA", + "fee": 0.00003060, + "changepos": 1 +} +``` + +We see that `bitcoind` has given us a transaction that would pay `3060` satoshi +in fees. Fee estimation/calculation can be changed with parameters of the +`walletcreatefundedpsbt` command. To see all options, use +`bitcoin-cli help walletcreatefundedpsbt`. + +If we want to know what exactly is in this PSBT, we can look at it with the +`decodepsbt` command: + +```bash +$ bitcoin-cli decodepsbt cHNidP8BAH0CAAAAAbxLLf9+AYfqfF69QAQuETnL6cas7GDiWBZF+3xxc/Y/AAAAAAD+////AofWEgAAAAAAIgAgvGKLsRKUcp0qk/lkYWpzGJQi51RkG5J51NwHb6B6Hh+1If0jAQAAABYAFL+6THEGhybJnOkFGSRFbtCcPOG8AAAAAAABAR8wBBAkAQAAABYAFHemJ11XF7CU7WXBIJLD/qZF+6jrAAAA + +{ + "tx": { + "txid": "374504e4246a93a45b4a2c2bc31d8adc8525aa101c7b9065db6dc01c4bdfce0a", + "hash": "374504e4246a93a45b4a2c2bc31d8adc8525aa101c7b9065db6dc01c4bdfce0a", + "version": 2, + "size": 125, + "vsize": 125, + "weight": 500, + "locktime": 0, + "vin": [ + { + "txid": "3ff673717cfb451658e260ecacc6e9cb39112e0440bd5e7cea87017eff2d4bbc", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967294 + } + ], + "vout": [ + { + "value": 0.01234567, + "n": 0, + "scriptPubKey": { + "asm": "0 bc628bb11294729d2a93f964616a73189422e754641b9279d4dc076fa07a1e1f", + "hex": "0020bc628bb11294729d2a93f964616a73189422e754641b9279d4dc076fa07a1e1f", + "reqSigs": 1, + "type": "witness_v0_scripthash", + "addresses": [ + "bcrt1qh33ghvgjj3ef625nl9jxz6nnrz2z9e65vsdey7w5msrklgr6rc0sv0s08q" + ] + } + }, + { + "value": 48.98759093, + "n": 1, + "scriptPubKey": { + "asm": "0 bfba4c71068726c99ce9051924456ed09c3ce1bc", + "hex": "0014bfba4c71068726c99ce9051924456ed09c3ce1bc", + "reqSigs": 1, + "type": "witness_v0_keyhash", + "addresses": [ + "bcrt1qh7aycugxsunvn88fq5vjg3tw6zwrecduvvgre5" + ] + } + } + ] + }, + "unknown": { + }, + "inputs": [ + { + "witness_utxo": { + "amount": 48.99996720, + "scriptPubKey": { + "asm": "0 77a6275d5717b094ed65c12092c3fea645fba8eb", + "hex": "001477a6275d5717b094ed65c12092c3fea645fba8eb", + "type": "witness_v0_keyhash", + "address": "bcrt1qw7nzwh2hz7cffmt9cysf9sl75ezlh28tzl4n4e" + } + } + } + ], + "outputs": [ + { + }, + { + } + ], + "fee": 0.00003060 +} +``` + +This tells us that we got a PSBT with a big input, the channel output and a +change output for the rest. Everything is there but the signatures/witness data, +which is exactly what we need. + +### 3. Verify and sign the PSBT + +Now that we have a valid PSBT that has everything but the final +signatures/witness data, we can paste it into the prompt in `lncli` that is +still waiting for our input. + +```bash +... +Base64 encoded PSBT: cHNidP8BAH0CAAAAAbxLLf9+AYfqfF69QAQuETnL6cas7GDiWBZF+3xxc/Y/AAAAAAD+////AofWEgAAAAAAIgAgvGKLsRKUcp0qk/lkYWpzGJQi51RkG5J51NwHb6B6Hh+1If0jAQAAABYAFL+6THEGhybJnOkFGSRFbtCcPOG8AAAAAAABAR8wBBAkAQAAABYAFHemJ11XF7CU7WXBIJLD/qZF+6jrAAAA + +PSBT verified by lnd, please continue the funding flow by signing the PSBT by +all required parties/devices. Once the transaction is fully signed, paste it +again here. + +Base64 encoded PSBT: +``` + +We can now go ahead and sign the transaction. We are going to use `bitcoind` for +this again, but in practice this would now happen on a hardware wallet and +perhaps `bitcoind` would only know the public keys and couldn't sign for the +transaction itself. Again, this is only an example and can't reflect all +real-world use cases. + +```bash +$ bitcoin-cli walletprocesspsbt cHNidP8BAH0CAAAAAbxLLf9+AYfqfF69QAQuETnL6cas7GDiWBZF+3xxc/Y/AAAAAAD+////AofWEgAAAAAAIgAgvGKLsRKUcp0qk/lkYWpzGJQi51RkG5J51NwHb6B6Hh+1If0jAQAAABYAFL+6THEGhybJnOkFGSRFbtCcPOG8AAAAAAABAR8wBBAkAQAAABYAFHemJ11XF7CU7WXBIJLD/qZF+6jrAAAA + +{ +"psbt": "cHNidP8BAH0CAAAAAbxLLf9+AYfqfF69QAQuETnL6cas7GDiWBZF+3xxc/Y/AAAAAAD+////AofWEgAAAAAAIgAgvGKLsRKUcp0qk/lkYWpzGJQi51RkG5J51NwHb6B6Hh+1If0jAQAAABYAFL+6THEGhybJnOkFGSRFbtCcPOG8AAAAAAABAR8wBBAkAQAAABYAFHemJ11XF7CU7WXBIJLD/qZF+6jrAQhrAkcwRAIgHKQbenZYvgADRd9TKGVO36NnaIgW3S12OUg8XGtSrE8CICmeaYoJ/U7Ecm+/GneY8i2hu2QCaQnuomJgzn+JAnrDASEDUBmCLcsybA5qXSRBBdZ0Uk/FQiay9NgOpv4D26yeJpAAAAA=", +"complete": true +} +``` + +Interpreting the output, we now have a complete, final, and signed transaction +inside the PSBT. Let's give it to `lncli` to continue: + +```bash +... +Base64 encoded PSBT: cHNidP8BAH0CAAAAAbxLLf9+AYfqfF69QAQuETnL6cas7GDiWBZF+3xxc/Y/AAAAAAD+////AofWEgAAAAAAIgAgvGKLsRKUcp0qk/lkYWpzGJQi51RkG5J51NwHb6B6Hh+1If0jAQAAABYAFL+6THEGhybJnOkFGSRFbtCcPOG8AAAAAAABAR8wBBAkAQAAABYAFHemJ11XF7CU7WXBIJLD/qZF+6jrAQhrAkcwRAIgHKQbenZYvgADRd9TKGVO36NnaIgW3S12OUg8XGtSrE8CICmeaYoJ/U7Ecm+/GneY8i2hu2QCaQnuomJgzn+JAnrDASEDUBmCLcsybA5qXSRBBdZ0Uk/FQiay9NgOpv4D26yeJpAAAAA= +{ + "funding_txid": "374504e4246a93a45b4a2c2bc31d8adc8525aa101c7b9065db6dc01c4bdfce0a" +} +``` + +Success! We now have the final transaction ID of the published funding +transaction. Now we only have to wait for some confirmations, then we can start +using the freshly created channel. From 73c542c93451b6ee12626a3a883d5bd2d12f386e Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Sat, 28 Mar 2020 10:39:17 +0100 Subject: [PATCH 339/562] travis+lint+make: limit lint concurrency only on travis Since linting is much faster by using the defaults locally. --- .golangci.yml | 4 ---- .travis.yml | 2 +- Makefile | 8 +++++++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index b3289f16b5..e05628a804 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,10 +2,6 @@ run: # timeout for analysis deadline: 4m - # Linting uses a lot of memory. Keep it under control by only running a single - # worker. - concurrency: 1 - # Skip autogenerated files for mobile. skip-files: - "mobile\\/.*generated\\.go" diff --git a/.travis.yml b/.travis.yml index 32a9f5b560..138d0b2bc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,7 +41,7 @@ jobs: script: - make rpc-check - make unit pkg=... case=_NONE_ - - make lint + - make lint workers=1 - make btcd - LNDBUILDSYS=windows-amd64 bash ./build/release/release.sh - stage: Test diff --git a/Makefile b/Makefile index d049579350..5ecd492911 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,13 @@ include make/testing_flags.mk DEV_TAGS := $(if ${tags},$(DEV_TAGS) ${tags},$(DEV_TAGS)) -LINT = $(LINT_BIN) run -v +# Linting uses a lot of memory, so keep it under control by limiting the number +# of workers if requested. +ifneq ($(workers),) +LINT_WORKERS = --concurrency=$(workers) +endif + +LINT = $(LINT_BIN) run -v $(LINT_WORKERS) GREEN := "\\033[0;32m" NC := "\\033[0m" From 5660a26b602da096bd103a453ddebeb301679f9d Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 16:55:16 -0700 Subject: [PATCH 340/562] rpcserver: add wallet sync check to OpenChannel --- lntest/itest/lnd_test.go | 12 +++++++++--- rpcserver.go | 11 +++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index f0ccc4075c..1a11339979 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -214,9 +214,15 @@ func openChannelAndAssert(ctx context.Context, t *harnessTest, net *lntest.NetworkHarness, alice, bob *lntest.HarnessNode, p lntest.OpenChannelParams) *lnrpc.ChannelPoint { - chanOpenUpdate, err := net.OpenChannel( - ctx, alice, bob, p, - ) + // Wait until we are able to fund a channel successfully. This wait + // prevents us from erroring out when trying to create a channel while + // the node is starting up. + var chanOpenUpdate lnrpc.Lightning_OpenChannelClient + err := wait.NoError(func() error { + var err error + chanOpenUpdate, err = net.OpenChannel(ctx, alice, bob, p) + return err + }, defaultTimeout) if err != nil { t.Fatalf("unable to open channel: %v", err) } diff --git a/rpcserver.go b/rpcserver.go index e68e0ffd90..4b5f56bc27 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1616,6 +1616,17 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, return ErrServerNotActive } + // Creation of channels before the wallet syncs up is currently + // disallowed. + isSynced, _, err := r.server.cc.wallet.IsSynced() + if err != nil { + return err + } + if !isSynced { + return errors.New("channels cannot be created before the " + + "wallet is fully synced") + } + localFundingAmt := btcutil.Amount(in.LocalFundingAmount) remoteInitialBalance := btcutil.Amount(in.PushSat) minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat) From 1823840ed6830d1f30ec86296f7e5ec9bdb605c3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 16:55:31 -0700 Subject: [PATCH 341/562] rpcserver: add missing channel limit check to OpenChannelSync --- rpcserver.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index 4b5f56bc27..01faa0d33b 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1870,6 +1870,14 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, "initial state must be below the local funding amount") } + // Ensure that the user doesn't exceed the current soft-limit for + // channel size. If the funding amount is above the soft-limit, then + // we'll reject the request. + if localFundingAmt > MaxFundingAmount { + return nil, fmt.Errorf("funding amount is too large, the max "+ + "channel size is: %v", MaxFundingAmount) + } + // Restrict the size of the channel we'll actually open. At a later // level, we'll ensure that the output we create after accounting for // fees that a dust output isn't created. From 303d441d4d7cd5b256070f18c81ac4bd3513df81 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 16:56:12 -0700 Subject: [PATCH 342/562] rpcserver: ensure OpenChannel+OpenChannelSync parse NodePubkey --- rpcserver.go | 52 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 01faa0d33b..f9753bbbe6 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1666,13 +1666,10 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, return err } - var ( - nodePubKey *btcec.PublicKey - nodePubKeyBytes []byte - ) - // TODO(roasbeef): also return channel ID? + var nodePubKey *btcec.PublicKey + // Ensure that the NodePubKey is set before attempting to use it if len(in.NodePubkey) == 0 { return fmt.Errorf("NodePubKey is not set") @@ -1691,8 +1688,6 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, return fmt.Errorf("cannot open channel to self") } - nodePubKeyBytes = nodePubKey.SerializeCompressed() - // Based on the passed fee related parameters, we'll determine an // appropriate fee rate for the funding transaction. satPerKw := chainfee.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight() @@ -1780,7 +1775,7 @@ out: select { case err := <-errChan: rpcsLog.Errorf("unable to open channel to NodeKey(%x): %v", - nodePubKeyBytes, err) + nodePubKey.SerializeCompressed(), err) return err case fundingUpdate := <-updateChan: rpcsLog.Tracef("[openchannel] sending update: %v", @@ -1812,7 +1807,7 @@ out: } rpcsLog.Tracef("[openchannel] success NodeKey(%x), ChannelPoint(%v)", - nodePubKeyBytes, outpoint) + nodePubKey.SerializeCompressed(), outpoint) return nil } @@ -1845,16 +1840,31 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, "wallet is fully synced") } - // Decode the provided target node's public key, parsing it into a pub - // key object. For all sync call, byte slices are expected to be - // encoded as hex strings. - keyBytes, err := hex.DecodeString(in.NodePubkeyString) - if err != nil { - return nil, err - } - nodepubKey, err := btcec.ParsePubKey(keyBytes, btcec.S256()) - if err != nil { - return nil, err + var nodePubKey *btcec.PublicKey + + // Parse the remote pubkey the NodePubkey field of the request. If it's + // not present, we'll fallback to the deprecated version that parses the + // key from a hex string. + if len(in.NodePubkey) > 0 { + // Parse the raw bytes of the node key into a pubkey object so we + // can easily manipulate it. + nodePubKey, err = btcec.ParsePubKey(in.NodePubkey, btcec.S256()) + if err != nil { + return nil, err + } + } else { + // Decode the provided target node's public key, parsing it into + // a pub key object. For all sync call, byte slices are expected + // to be encoded as hex strings. + keyBytes, err := hex.DecodeString(in.NodePubkeyString) + if err != nil { + return nil, err + } + + nodePubKey, err = btcec.ParsePubKey(keyBytes, btcec.S256()) + if err != nil { + return nil, err + } } localFundingAmt := btcutil.Amount(in.LocalFundingAmount) @@ -1916,7 +1926,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, } req := &openChanReq{ - targetPubkey: nodepubKey, + targetPubkey: nodePubKey, chainHash: *activeNetParams.GenesisHash, localFundingAmt: localFundingAmt, pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance), @@ -1933,7 +1943,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, // If an error occurs them immediately return the error to the client. case err := <-errChan: rpcsLog.Errorf("unable to open channel to NodeKey(%x): %v", - nodepubKey, err) + nodePubKey.SerializeCompressed(), err) return nil, err // Otherwise, wait for the first channel update. The first update sent From c1f9c56e5b5a2ebfb6013b4dd0644db97472103e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 15:15:15 -0700 Subject: [PATCH 343/562] rpcserver: add self-node check in OpenChannelSync --- rpcserver.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index f9753bbbe6..5ff15de2ff 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1867,6 +1867,12 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, } } + // Making a channel to ourselves wouldn't be of any use, so we + // explicitly disallow them. + if nodePubKey.IsEqual(r.server.identityPriv.PubKey()) { + return nil, fmt.Errorf("cannot open channel to self") + } + localFundingAmt := btcutil.Amount(in.LocalFundingAmount) remoteInitialBalance := btcutil.Amount(in.PushSat) minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat) From 41573004a36ec152bc00f4216f53667dc85cf210 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 20:35:24 +0200 Subject: [PATCH 344/562] lnrpc: extract rpcCommitmentType --- rpcserver.go | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index e68e0ffd90..1c83ad5ec1 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3220,6 +3220,23 @@ func (r *rpcServer) ListChannels(ctx context.Context, return resp, nil } +// rpcCommitmentType takes the channel type and converts it to an rpc commitment +// type value. +func rpcCommitmentType(chanType channeldb.ChannelType) lnrpc.CommitmentType { + // Extract the commitment type from the channel type flags. We must + // first check whether it has anchors, since in that case it would also + // be tweakless. + if chanType.HasAnchors() { + return lnrpc.CommitmentType_ANCHORS + } + + if chanType.IsTweakless() { + return lnrpc.CommitmentType_STATIC_REMOTE_KEY + } + + return lnrpc.CommitmentType_LEGACY +} + // createRPCOpenChannel creates an *lnrpc.Channel from the *channeldb.Channel. func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, dbChannel *channeldb.OpenChannel, isActive bool) (*lnrpc.Channel, error) { @@ -3257,15 +3274,8 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, } externalCommitFee := dbChannel.Capacity - sumOutputs - // Extract the commitment type from the channel type flags. We must - // first check whether it has anchors, since in that case it would also - // be tweakless. - commitmentType := lnrpc.CommitmentType_LEGACY - if dbChannel.ChanType.HasAnchors() { - commitmentType = lnrpc.CommitmentType_ANCHORS - } else if dbChannel.ChanType.IsTweakless() { - commitmentType = lnrpc.CommitmentType_STATIC_REMOTE_KEY - } + // Extract the commitment type from the channel type flags. + commitmentType := rpcCommitmentType(dbChannel.ChanType) channel := &lnrpc.Channel{ Active: isActive, From baffe156db5e98c2ae56781d2a612b52bf238ec5 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 20:36:38 +0200 Subject: [PATCH 345/562] lnrpc: expose commitment type on pending open and waiting close channels --- lnrpc/rpc.pb.go | 1514 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 8 + lnrpc/rpc.swagger.json | 9 +- rpcserver.go | 14 +- 4 files changed, 790 insertions(+), 755 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 8fe57ae356..2f7826cc08 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -77,18 +77,23 @@ const ( //commitments, allowing fee bumping after a force close transaction has //been broadcast. CommitmentType_ANCHORS CommitmentType = 2 + //* + //Returned when the commitment type isn't known or unavailable. + CommitmentType_UNKNOWN_COMMITMENT_TYPE CommitmentType = 999 ) var CommitmentType_name = map[int32]string{ - 0: "LEGACY", - 1: "STATIC_REMOTE_KEY", - 2: "ANCHORS", + 0: "LEGACY", + 1: "STATIC_REMOTE_KEY", + 2: "ANCHORS", + 999: "UNKNOWN_COMMITMENT_TYPE", } var CommitmentType_value = map[string]int32{ - "LEGACY": 0, - "STATIC_REMOTE_KEY": 1, - "ANCHORS": 2, + "LEGACY": 0, + "STATIC_REMOTE_KEY": 1, + "ANCHORS": 2, + "UNKNOWN_COMMITMENT_TYPE": 999, } func (x CommitmentType) String() string { @@ -5867,10 +5872,12 @@ type PendingChannelsResponse_PendingChannel struct { //balance. RemoteChanReserveSat int64 `protobuf:"varint,7,opt,name=remote_chan_reserve_sat,json=remoteChanReserveSat,proto3" json:"remote_chan_reserve_sat,omitempty"` // True if we initiated opening the channel. - Initiator bool `protobuf:"varint,8,opt,name=initiator,proto3" json:"initiator,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Initiator bool `protobuf:"varint,8,opt,name=initiator,proto3" json:"initiator,omitempty"` + /// The commitment type used by this channel. + CommitmentType CommitmentType `protobuf:"varint,9,opt,name=commitment_type,json=commitmentType,proto3,enum=lnrpc.CommitmentType" json:"commitment_type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *PendingChannelsResponse_PendingChannel) Reset() { @@ -5956,6 +5963,13 @@ func (m *PendingChannelsResponse_PendingChannel) GetInitiator() bool { return false } +func (m *PendingChannelsResponse_PendingChannel) GetCommitmentType() CommitmentType { + if m != nil { + return m.CommitmentType + } + return CommitmentType_LEGACY +} + type PendingChannelsResponse_PendingOpenChannel struct { /// The pending channel Channel *PendingChannelsResponse_PendingChannel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` @@ -11864,747 +11878,749 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11837 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5d, 0x6f, 0x24, 0x49, - 0x72, 0xd8, 0xf4, 0x17, 0xbb, 0x3b, 0xfa, 0x83, 0xcd, 0xe4, 0x57, 0x0f, 0x67, 0x67, 0x67, 0xb6, - 0x6e, 0x6f, 0x77, 0x76, 0xf6, 0x8e, 0x33, 0x3b, 0x77, 0xbb, 0x77, 0xb7, 0x6b, 0x9d, 0xae, 0x49, - 0x36, 0x87, 0x7d, 0x43, 0x36, 0xb9, 0xd5, 0xcd, 0x5d, 0xed, 0xe9, 0xa3, 0xae, 0xd8, 0x9d, 0x24, - 0x4b, 0xd3, 0x5d, 0xd5, 0x5b, 0x55, 0xcd, 0x8f, 0x3b, 0xac, 0x1f, 0x0c, 0x5b, 0x30, 0x0c, 0xdb, - 0x80, 0x60, 0xcb, 0x80, 0x65, 0x0b, 0x36, 0x2c, 0x18, 0x86, 0x21, 0x40, 0x10, 0x70, 0xf2, 0x83, - 0x01, 0xbf, 0x0b, 0x06, 0x6c, 0x08, 0x86, 0xe4, 0x17, 0x43, 0x10, 0x60, 0xd8, 0x96, 0xdf, 0x0c, - 0x01, 0xfe, 0x03, 0x46, 0x46, 0x64, 0x56, 0x65, 0x75, 0x17, 0x67, 0x66, 0xef, 0xce, 0xf7, 0x42, - 0x76, 0x45, 0x46, 0x7e, 0x47, 0x46, 0x46, 0x64, 0x44, 0x64, 0x42, 0xd9, 0x9f, 0x0c, 0x36, 0x27, - 0xbe, 0x17, 0x7a, 0xac, 0x30, 0x72, 0xfd, 0xc9, 0x60, 0xe3, 0xb5, 0x33, 0xcf, 0x3b, 0x1b, 0xf1, - 0x47, 0xf6, 0xc4, 0x79, 0x64, 0xbb, 0xae, 0x17, 0xda, 0xa1, 0xe3, 0xb9, 0x01, 0x21, 0x19, 0x3f, - 0x84, 0xfa, 0x53, 0xee, 0xf6, 0x38, 0x1f, 0x9a, 0xfc, 0xf3, 0x29, 0x0f, 0x42, 0xf6, 0x2e, 0x2c, - 0xd9, 0xfc, 0x47, 0x9c, 0x0f, 0xad, 0x89, 0x1d, 0x04, 0x93, 0x73, 0xdf, 0x0e, 0x78, 0x33, 0x73, - 0x3f, 0xf3, 0xa0, 0x6a, 0x36, 0x28, 0xe1, 0x28, 0x82, 0xb3, 0x37, 0xa0, 0x1a, 0x08, 0x54, 0xee, - 0x86, 0xbe, 0x37, 0xb9, 0x6e, 0x66, 0x11, 0xaf, 0x22, 0x60, 0x6d, 0x02, 0x19, 0x23, 0x58, 0x8c, - 0x6a, 0x08, 0x26, 0x9e, 0x1b, 0x70, 0xf6, 0x18, 0x56, 0x06, 0xce, 0xe4, 0x9c, 0xfb, 0x16, 0x66, - 0x1e, 0xbb, 0x7c, 0xec, 0xb9, 0xce, 0xa0, 0x99, 0xb9, 0x9f, 0x7b, 0x50, 0x36, 0x19, 0xa5, 0x89, - 0x1c, 0x07, 0x32, 0x85, 0xbd, 0x0d, 0x8b, 0xdc, 0x25, 0x38, 0x1f, 0x62, 0x2e, 0x59, 0x55, 0x3d, - 0x06, 0x8b, 0x0c, 0xc6, 0xdf, 0xcd, 0xc2, 0x52, 0xc7, 0x75, 0xc2, 0x4f, 0xed, 0xd1, 0x88, 0x87, - 0xaa, 0x4f, 0x6f, 0xc3, 0xe2, 0x25, 0x02, 0xb0, 0x4f, 0x97, 0x9e, 0x3f, 0x94, 0x3d, 0xaa, 0x13, - 0xf8, 0x48, 0x42, 0x6f, 0x6c, 0x59, 0xf6, 0xc6, 0x96, 0xa5, 0x0e, 0x57, 0xee, 0x86, 0xe1, 0x7a, - 0x1b, 0x16, 0x7d, 0x3e, 0xf0, 0x2e, 0xb8, 0x7f, 0x6d, 0x5d, 0x3a, 0xee, 0xd0, 0xbb, 0x6c, 0xe6, - 0xef, 0x67, 0x1e, 0x14, 0xcc, 0xba, 0x02, 0x7f, 0x8a, 0x50, 0xb6, 0x05, 0x8b, 0x83, 0x73, 0xdb, - 0x75, 0xf9, 0xc8, 0x3a, 0xb1, 0x07, 0xcf, 0xa7, 0x93, 0xa0, 0x59, 0xb8, 0x9f, 0x79, 0x50, 0x79, - 0x72, 0x7b, 0x13, 0x67, 0x75, 0x73, 0xfb, 0xdc, 0x76, 0xb7, 0x30, 0xa5, 0xe7, 0xda, 0x93, 0xe0, - 0xdc, 0x0b, 0xcd, 0xba, 0xcc, 0x41, 0xe0, 0xc0, 0x58, 0x01, 0xa6, 0x8f, 0x04, 0x8d, 0xbd, 0xf1, - 0x07, 0x19, 0x58, 0x3e, 0x76, 0x47, 0xde, 0xe0, 0xf9, 0x4f, 0x39, 0x44, 0x29, 0x7d, 0xc8, 0xbe, - 0x6a, 0x1f, 0x72, 0x5f, 0xb6, 0x0f, 0x6b, 0xb0, 0x92, 0x6c, 0xac, 0xec, 0x05, 0x87, 0x55, 0x91, - 0xfb, 0x8c, 0xab, 0x66, 0xa9, 0x6e, 0xbc, 0x03, 0x8d, 0xc1, 0xd4, 0xf7, 0xb9, 0x3b, 0xd7, 0x8f, - 0x45, 0x09, 0x8f, 0x3a, 0xf2, 0x06, 0x54, 0x5d, 0x7e, 0x19, 0xa3, 0x49, 0xda, 0x75, 0xf9, 0xa5, - 0x42, 0x31, 0x9a, 0xb0, 0x36, 0x5b, 0x8d, 0x6c, 0xc0, 0x5f, 0x65, 0x20, 0x7f, 0x1c, 0x5e, 0x79, - 0xec, 0x7d, 0xa8, 0xda, 0xc3, 0xa1, 0xcf, 0x83, 0xc0, 0x0a, 0xaf, 0x27, 0xb4, 0x52, 0xea, 0x4f, - 0x98, 0xec, 0x62, 0x8b, 0x92, 0xfa, 0xd7, 0x13, 0x6e, 0x56, 0xec, 0xf8, 0x83, 0x35, 0xa1, 0x28, - 0x3f, 0xb1, 0xde, 0xb2, 0xa9, 0x3e, 0xd9, 0x5d, 0x00, 0x7b, 0xec, 0x4d, 0xdd, 0xd0, 0x0a, 0xec, - 0x10, 0x47, 0x2c, 0x67, 0x96, 0x09, 0xd2, 0xb3, 0x43, 0x76, 0x07, 0xca, 0x93, 0xe7, 0x56, 0x30, - 0xf0, 0x9d, 0x49, 0x88, 0xc4, 0x53, 0x36, 0x4b, 0x93, 0xe7, 0x3d, 0xfc, 0x66, 0xef, 0x42, 0xc9, - 0x9b, 0x86, 0x13, 0xcf, 0x71, 0x43, 0x49, 0x2f, 0x8b, 0xb2, 0x21, 0x87, 0xd3, 0xf0, 0x48, 0x80, - 0xcd, 0x08, 0x81, 0xbd, 0x09, 0xb5, 0x81, 0xe7, 0x9e, 0x3a, 0xfe, 0x98, 0x38, 0x42, 0x73, 0x01, - 0xeb, 0x4a, 0x02, 0x8d, 0x3f, 0xca, 0x42, 0xa5, 0xef, 0xdb, 0x6e, 0x60, 0x0f, 0x04, 0x80, 0xad, - 0x43, 0x31, 0xbc, 0xb2, 0xce, 0xed, 0xe0, 0x1c, 0xbb, 0x5a, 0x36, 0x17, 0xc2, 0xab, 0x3d, 0x3b, - 0x38, 0x67, 0x6b, 0xb0, 0x40, 0xad, 0xc4, 0x0e, 0xe5, 0x4c, 0xf9, 0x25, 0x16, 0x88, 0x3b, 0x1d, - 0x5b, 0xc9, 0xaa, 0x72, 0x48, 0x31, 0x0d, 0x77, 0x3a, 0xde, 0xd6, 0xe1, 0xa2, 0xf3, 0x27, 0x62, - 0xba, 0xa9, 0x02, 0xea, 0x5e, 0x19, 0x21, 0x58, 0xc7, 0x1b, 0x50, 0x95, 0xc9, 0xdc, 0x39, 0x3b, - 0xa7, 0x3e, 0x16, 0xcc, 0x0a, 0x21, 0x20, 0x48, 0x94, 0x10, 0x3a, 0x63, 0x6e, 0x05, 0xa1, 0x3d, - 0x9e, 0xc8, 0x2e, 0x95, 0x05, 0xa4, 0x27, 0x00, 0x98, 0xec, 0x85, 0xf6, 0xc8, 0x3a, 0xe5, 0x3c, - 0x68, 0x16, 0x65, 0xb2, 0x80, 0xec, 0x72, 0x1e, 0xb0, 0xaf, 0x42, 0x7d, 0xc8, 0x83, 0xd0, 0x92, - 0x93, 0xc1, 0x83, 0x66, 0x09, 0x57, 0x7e, 0x4d, 0x40, 0x5b, 0x0a, 0xc8, 0x5e, 0x03, 0xf0, 0xed, - 0x4b, 0x4b, 0x0c, 0x04, 0xbf, 0x6a, 0x96, 0x69, 0x16, 0x7c, 0xfb, 0xb2, 0x7f, 0xb5, 0xc7, 0xaf, - 0x04, 0xd5, 0x3c, 0xe5, 0xa1, 0x36, 0x68, 0x81, 0xa4, 0x4e, 0x63, 0x1f, 0x98, 0x06, 0xde, 0xe1, - 0xa1, 0xed, 0x8c, 0x02, 0xf6, 0x01, 0x54, 0x43, 0x0d, 0x19, 0xd9, 0x60, 0x25, 0x22, 0x21, 0x2d, - 0x83, 0x99, 0xc0, 0x33, 0xce, 0xa1, 0xb4, 0xcb, 0xf9, 0xbe, 0x33, 0x76, 0x42, 0xb6, 0x06, 0x85, - 0x53, 0xe7, 0x8a, 0x13, 0xb1, 0xe7, 0xf6, 0x6e, 0x99, 0xf4, 0xc9, 0xee, 0x01, 0xe0, 0x0f, 0x6b, - 0x1c, 0x51, 0xd3, 0xde, 0x2d, 0xb3, 0x8c, 0xb0, 0x83, 0xc0, 0x0e, 0xd9, 0x06, 0x14, 0x27, 0xdc, - 0x1f, 0x70, 0x35, 0x6f, 0x7b, 0xb7, 0x4c, 0x05, 0xd8, 0x2a, 0x42, 0x61, 0x24, 0x4a, 0x37, 0xfe, - 0xa4, 0x00, 0x95, 0x1e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, 0xcd, - 0xbe, 0x02, 0x15, 0x1c, 0xba, 0x20, 0xf4, 0x1d, 0xf7, 0x8c, 0xa8, 0x7a, 0x2b, 0xdb, 0xcc, 0x98, - 0x20, 0xc0, 0x3d, 0x84, 0xb2, 0x06, 0xe4, 0xec, 0xb1, 0xa2, 0x6a, 0xf1, 0x93, 0xdd, 0x86, 0x92, - 0x3d, 0x0e, 0xa9, 0x79, 0x55, 0x04, 0x17, 0xed, 0x71, 0x88, 0x4d, 0x7b, 0x03, 0xaa, 0x13, 0xfb, - 0x7a, 0x2c, 0xd6, 0x72, 0x44, 0x0e, 0x55, 0xb3, 0x22, 0x61, 0x48, 0x10, 0x4f, 0x60, 0x59, 0x47, - 0x51, 0x95, 0x17, 0xa2, 0xca, 0x97, 0x34, 0x6c, 0xd9, 0x86, 0xb7, 0x61, 0x51, 0xe5, 0xf1, 0xa9, - 0x3f, 0x48, 0x26, 0x65, 0xb3, 0x2e, 0xc1, 0xaa, 0x97, 0x0f, 0xa0, 0x71, 0xea, 0xb8, 0xf6, 0xc8, - 0x1a, 0x8c, 0xc2, 0x0b, 0x6b, 0xc8, 0x47, 0xa1, 0x8d, 0x14, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1e, - 0x85, 0x17, 0x3b, 0x02, 0xca, 0xbe, 0x06, 0xe5, 0x53, 0xce, 0x2d, 0x1c, 0xac, 0x66, 0x29, 0xb1, - 0xf0, 0xd4, 0x0c, 0x99, 0xa5, 0x53, 0x35, 0x57, 0x5f, 0x83, 0x86, 0x37, 0x0d, 0xcf, 0x3c, 0xc7, - 0x3d, 0xb3, 0x04, 0xbf, 0xb3, 0x9c, 0x21, 0xd2, 0x50, 0x7e, 0x2b, 0xfb, 0x38, 0x63, 0xd6, 0x55, - 0x9a, 0xe0, 0x3c, 0x9d, 0x21, 0x7b, 0x0b, 0x16, 0x47, 0x76, 0x10, 0x5a, 0xe7, 0xde, 0xc4, 0x9a, - 0x4c, 0x4f, 0x9e, 0xf3, 0xeb, 0x66, 0x0d, 0x07, 0xa2, 0x26, 0xc0, 0x7b, 0xde, 0xe4, 0x08, 0x81, - 0x82, 0xb2, 0xb1, 0x9d, 0xd4, 0x08, 0xb8, 0x9f, 0x79, 0x50, 0x33, 0xcb, 0x02, 0x42, 0x95, 0x7e, - 0x06, 0xcb, 0x38, 0x3d, 0x83, 0x69, 0x10, 0x7a, 0x63, 0x4b, 0xf0, 0x6a, 0x7f, 0x18, 0x34, 0x2b, - 0x48, 0x6b, 0xef, 0xc8, 0xc6, 0x6a, 0x73, 0xbc, 0xb9, 0xc3, 0x83, 0x70, 0x1b, 0x91, 0x4d, 0xc2, - 0x15, 0x1b, 0xfa, 0xb5, 0xb9, 0x34, 0x9c, 0x85, 0xb3, 0xaf, 0x01, 0xb3, 0x47, 0x23, 0xef, 0xd2, - 0x0a, 0xf8, 0xe8, 0xd4, 0x92, 0x83, 0xd8, 0xac, 0xdf, 0xcf, 0x3c, 0x28, 0x99, 0x0d, 0x4c, 0xe9, - 0xf1, 0xd1, 0xe9, 0x11, 0xc1, 0xd9, 0x07, 0x80, 0x8b, 0xc9, 0x3a, 0xe5, 0x76, 0x38, 0xf5, 0x79, - 0xd0, 0x5c, 0xbc, 0x9f, 0x7b, 0x50, 0x7f, 0xb2, 0x14, 0x8d, 0x17, 0x82, 0xb7, 0x9c, 0xd0, 0xac, - 0x0a, 0x3c, 0xf9, 0x1d, 0x6c, 0xec, 0xc0, 0x5a, 0x7a, 0x93, 0x04, 0x51, 0x89, 0x51, 0x11, 0xc4, - 0x98, 0x37, 0xc5, 0x4f, 0xb6, 0x02, 0x85, 0x0b, 0x7b, 0x34, 0xe5, 0x92, 0xa7, 0xd3, 0xc7, 0x87, - 0xd9, 0x6f, 0x67, 0x8c, 0x3f, 0xce, 0x40, 0x95, 0x7a, 0x29, 0x65, 0x91, 0xaf, 0x40, 0x4d, 0x51, - 0x03, 0xf7, 0x7d, 0xcf, 0x97, 0x5c, 0x4d, 0x51, 0x5e, 0x5b, 0xc0, 0xc4, 0xae, 0xa2, 0x90, 0x26, - 0x3e, 0x77, 0xc6, 0xf6, 0x99, 0x2a, 0x5a, 0x91, 0xd2, 0x91, 0x04, 0xb3, 0xf7, 0xe2, 0xf2, 0x7c, - 0x6f, 0x1a, 0x72, 0xb9, 0xe7, 0x55, 0x65, 0xf7, 0x4c, 0x01, 0x8b, 0x4a, 0xc7, 0xaf, 0x57, 0xa0, - 0x73, 0xe3, 0x77, 0x32, 0xc0, 0x44, 0xb3, 0xfb, 0x1e, 0x15, 0x20, 0x29, 0x74, 0x36, 0x67, 0xe6, - 0x95, 0x57, 0x48, 0xf6, 0x45, 0x2b, 0xc4, 0x80, 0x02, 0xb5, 0x3d, 0x9f, 0xd2, 0x76, 0x4a, 0xfa, - 0x7e, 0xbe, 0x94, 0x6b, 0xe4, 0x8d, 0xff, 0x96, 0x83, 0x95, 0x6d, 0xda, 0xb2, 0x5b, 0x83, 0x01, - 0x9f, 0x44, 0x6b, 0xe7, 0x1e, 0x54, 0x5c, 0x6f, 0xc8, 0x15, 0xc5, 0x52, 0xc3, 0x40, 0x80, 0x34, - 0x72, 0x3d, 0xb7, 0x1d, 0x97, 0x1a, 0x4e, 0x83, 0x59, 0x46, 0x08, 0x36, 0xfb, 0x2d, 0x58, 0x9c, - 0x70, 0x77, 0xa8, 0x2f, 0x11, 0x12, 0xaa, 0x6a, 0x12, 0x2c, 0x57, 0xc7, 0x3d, 0xa8, 0x9c, 0x4e, - 0x09, 0x4f, 0x30, 0x96, 0x3c, 0xd2, 0x00, 0x48, 0x50, 0x8b, 0xf8, 0xcb, 0x64, 0x1a, 0x9c, 0x63, - 0x6a, 0x01, 0x53, 0x8b, 0xe2, 0x5b, 0x24, 0xdd, 0x05, 0x18, 0x4e, 0x83, 0x50, 0xae, 0x98, 0x05, - 0x4c, 0x2c, 0x0b, 0x08, 0xad, 0x98, 0xaf, 0xc3, 0xf2, 0xd8, 0xbe, 0xb2, 0x90, 0x76, 0x2c, 0xc7, - 0xb5, 0x4e, 0x47, 0xb8, 0xe7, 0x14, 0x11, 0xaf, 0x31, 0xb6, 0xaf, 0x3e, 0x11, 0x29, 0x1d, 0x77, - 0x17, 0xe1, 0x82, 0xad, 0x28, 0x71, 0xc7, 0xe7, 0x01, 0xf7, 0x2f, 0x38, 0x72, 0x82, 0x7c, 0x24, - 0xd3, 0x98, 0x04, 0x15, 0x2d, 0x1a, 0x8b, 0x7e, 0x87, 0xa3, 0x01, 0x2d, 0x7b, 0xb3, 0x38, 0x76, - 0xdc, 0xbd, 0x70, 0x34, 0x10, 0xfb, 0x8a, 0xe0, 0x23, 0x13, 0xee, 0x5b, 0xcf, 0x2f, 0x71, 0x0d, - 0xe7, 0x91, 0x6f, 0x1c, 0x71, 0xff, 0xd9, 0xa5, 0xd8, 0xfa, 0x07, 0x01, 0x32, 0x22, 0xfb, 0xba, - 0x59, 0xc1, 0x05, 0x5e, 0x1a, 0x04, 0x82, 0x05, 0xd9, 0xd7, 0x62, 0x11, 0x8a, 0xd6, 0xda, 0x38, - 0x0b, 0x7c, 0x88, 0xc5, 0x07, 0xc8, 0x51, 0x6b, 0xd8, 0xd8, 0x96, 0x4c, 0x10, 0xf5, 0x04, 0x82, - 0xea, 0x55, 0x63, 0x4f, 0x47, 0xf6, 0x59, 0x80, 0x2c, 0xa5, 0x66, 0x56, 0x25, 0x70, 0x57, 0xc0, - 0x8c, 0x4f, 0x49, 0xc8, 0xd2, 0xe6, 0x56, 0xae, 0x19, 0xb1, 0xd5, 0x23, 0x04, 0xe7, 0xb5, 0x64, - 0xca, 0xaf, 0xb4, 0x49, 0xcb, 0xa6, 0x4c, 0x9a, 0xf1, 0x7b, 0x19, 0xa8, 0xca, 0x92, 0x51, 0x28, - 0x61, 0x9b, 0xc0, 0xd4, 0x2c, 0x86, 0x57, 0xce, 0xd0, 0x3a, 0xb9, 0x0e, 0x79, 0x40, 0x44, 0xb3, - 0x77, 0xcb, 0x6c, 0xc8, 0xb4, 0xfe, 0x95, 0x33, 0xdc, 0x12, 0x29, 0xec, 0x21, 0x34, 0x12, 0xf8, - 0x41, 0xe8, 0x13, 0x45, 0xef, 0xdd, 0x32, 0xeb, 0x1a, 0x76, 0x2f, 0xf4, 0xc5, 0x1a, 0x11, 0x22, - 0xcf, 0x34, 0xb4, 0x1c, 0x77, 0xc8, 0xaf, 0x90, 0x8c, 0x6a, 0x66, 0x85, 0x60, 0x1d, 0x01, 0xda, - 0xaa, 0x43, 0x55, 0x2f, 0xce, 0x38, 0x83, 0x92, 0x92, 0x97, 0x50, 0x60, 0x98, 0x69, 0x92, 0x59, - 0x0e, 0xa3, 0x96, 0xdc, 0x86, 0x52, 0xb2, 0x05, 0x66, 0x31, 0x7c, 0xe5, 0x8a, 0x8d, 0xef, 0x42, - 0x63, 0x5f, 0x10, 0x8f, 0x2b, 0x88, 0x55, 0xca, 0x7f, 0x6b, 0xb0, 0xa0, 0x2d, 0x9a, 0xb2, 0x29, - 0xbf, 0xc4, 0x9e, 0x7b, 0xee, 0x05, 0xa1, 0xac, 0x05, 0x7f, 0x1b, 0x7f, 0x92, 0x01, 0xd6, 0x0e, - 0x42, 0x67, 0x6c, 0x87, 0x7c, 0x97, 0x47, 0x6c, 0xe1, 0x10, 0xaa, 0xa2, 0xb4, 0xbe, 0xd7, 0x22, - 0x81, 0x8c, 0x04, 0x8a, 0x77, 0xe5, 0x32, 0x9e, 0xcf, 0xb0, 0xa9, 0x63, 0x13, 0x9b, 0x4f, 0x14, - 0x20, 0x56, 0x59, 0x68, 0xfb, 0x67, 0x3c, 0x44, 0x31, 0x4e, 0xca, 0xfb, 0x40, 0x20, 0x21, 0xc0, - 0x6d, 0xfc, 0x32, 0x2c, 0xcd, 0x95, 0xa1, 0xf3, 0xe5, 0x72, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, - 0x82, 0xe5, 0x44, 0xbb, 0x24, 0xa5, 0xad, 0x43, 0x51, 0x2c, 0x08, 0x21, 0x1c, 0x64, 0x48, 0xaa, - 0x3c, 0xe5, 0x5c, 0x88, 0xc1, 0x8f, 0x60, 0xe5, 0x94, 0x73, 0xdf, 0x0e, 0x31, 0x11, 0x57, 0x8c, - 0x98, 0x21, 0x59, 0xf0, 0x92, 0x4c, 0xeb, 0xd9, 0xe1, 0x11, 0xf7, 0xc5, 0x4c, 0x19, 0xff, 0x23, - 0x03, 0x8b, 0x82, 0x83, 0x1e, 0xd8, 0xee, 0xb5, 0x1a, 0xa7, 0xfd, 0xd4, 0x71, 0x7a, 0xa0, 0x6d, - 0x86, 0x1a, 0xf6, 0x97, 0x1d, 0xa4, 0xdc, 0xec, 0x20, 0xb1, 0xfb, 0x50, 0x4d, 0xb4, 0xb5, 0x80, - 0x6d, 0x85, 0x20, 0x6a, 0xe4, 0xcf, 0x3e, 0x8c, 0x6f, 0x41, 0x23, 0x6e, 0xb6, 0x1c, 0x43, 0x06, - 0x79, 0x41, 0x92, 0xb2, 0x00, 0xfc, 0x6d, 0xfc, 0xf3, 0x0c, 0x21, 0x6e, 0x7b, 0x4e, 0x24, 0x9d, - 0x0a, 0x44, 0x21, 0xf7, 0x2a, 0x44, 0xf1, 0xfb, 0x46, 0xa9, 0xfe, 0x67, 0xef, 0xac, 0x58, 0x3a, - 0x01, 0x77, 0x87, 0x96, 0x3d, 0x1a, 0x21, 0xf3, 0x2d, 0x99, 0x45, 0xf1, 0xdd, 0x1a, 0x8d, 0x8c, - 0xb7, 0x61, 0x49, 0x6b, 0xdd, 0x0b, 0xfa, 0xd1, 0x05, 0xb6, 0xef, 0x04, 0xe1, 0xb1, 0x1b, 0x4c, - 0x34, 0xc1, 0xed, 0x0e, 0x94, 0x05, 0x87, 0x15, 0x2d, 0xa3, 0x25, 0x5b, 0x30, 0x05, 0xcb, 0x15, - 0xed, 0x0a, 0x30, 0xd1, 0xbe, 0x92, 0x89, 0x59, 0x99, 0x68, 0x5f, 0x61, 0xa2, 0xf1, 0x6d, 0x58, - 0x4e, 0x94, 0x27, 0xab, 0x7e, 0x03, 0x0a, 0xd3, 0xf0, 0xca, 0x53, 0xa2, 0x79, 0x45, 0x52, 0x88, - 0x50, 0x00, 0x4d, 0x4a, 0x31, 0x3e, 0x82, 0xa5, 0x2e, 0xbf, 0x94, 0x8b, 0x58, 0x35, 0xe4, 0x2d, - 0xc8, 0xbf, 0x44, 0x29, 0xc4, 0x74, 0x63, 0x13, 0x98, 0x9e, 0x59, 0xd6, 0xaa, 0xe9, 0x88, 0x99, - 0x84, 0x8e, 0x68, 0xbc, 0x05, 0xac, 0xe7, 0x9c, 0xb9, 0x07, 0x3c, 0x08, 0xec, 0xb3, 0x68, 0xd9, - 0x37, 0x20, 0x37, 0x0e, 0xce, 0x24, 0x8f, 0x12, 0x3f, 0x8d, 0x6f, 0xc0, 0x72, 0x02, 0x4f, 0x16, - 0xfc, 0x1a, 0x94, 0x03, 0xe7, 0xcc, 0x45, 0xc1, 0x4a, 0x16, 0x1d, 0x03, 0x8c, 0x5d, 0x58, 0xf9, - 0x84, 0xfb, 0xce, 0xe9, 0xf5, 0xcb, 0x8a, 0x4f, 0x96, 0x93, 0x9d, 0x2d, 0xa7, 0x0d, 0xab, 0x33, - 0xe5, 0xc8, 0xea, 0x89, 0x7c, 0xe5, 0x4c, 0x96, 0x4c, 0xfa, 0xd0, 0xf8, 0x5e, 0x56, 0xe7, 0x7b, - 0xc6, 0x31, 0xb0, 0x6d, 0xcf, 0x75, 0xf9, 0x20, 0x3c, 0xe2, 0xdc, 0x8f, 0x4f, 0xa9, 0x62, 0x5a, - 0xad, 0x3c, 0x59, 0x97, 0x23, 0x3b, 0xcb, 0x4c, 0x25, 0x11, 0x33, 0xc8, 0x4f, 0xb8, 0x3f, 0xc6, - 0x82, 0x4b, 0x26, 0xfe, 0x36, 0x56, 0x61, 0x39, 0x51, 0xac, 0xd4, 0xeb, 0x1f, 0xc3, 0xea, 0x8e, - 0x13, 0x0c, 0xe6, 0x2b, 0x5c, 0x87, 0xe2, 0x64, 0x7a, 0x62, 0x25, 0xf9, 0xf2, 0x33, 0x7e, 0x2d, - 0xb4, 0xbd, 0xd9, 0x1c, 0xb2, 0xac, 0xbf, 0x9d, 0x81, 0xfc, 0x5e, 0x7f, 0x7f, 0x9b, 0x6d, 0x40, - 0xc9, 0x71, 0x07, 0xde, 0x58, 0x08, 0x5e, 0xd4, 0xe7, 0xe8, 0xfb, 0xc6, 0x05, 0x76, 0x07, 0xca, - 0x28, 0xaf, 0x09, 0xd5, 0x56, 0x8a, 0x3e, 0x25, 0x01, 0xd8, 0xf7, 0x06, 0xcf, 0x85, 0x4e, 0xcd, - 0xaf, 0x26, 0x8e, 0x8f, 0x5a, 0xb3, 0x52, 0x86, 0xf3, 0xb4, 0xd7, 0xc7, 0x09, 0xa4, 0x11, 0x1b, - 0xff, 0xbe, 0x04, 0x45, 0xb9, 0xdb, 0xd2, 0xce, 0x1d, 0x3a, 0x17, 0x3c, 0xde, 0xb9, 0xc5, 0x97, - 0x90, 0x07, 0x7c, 0x3e, 0xf6, 0xc2, 0x48, 0x60, 0xa3, 0x39, 0xa8, 0x12, 0x50, 0x8a, 0x6c, 0x9a, - 0xd0, 0x40, 0x47, 0x0c, 0x39, 0x42, 0x1a, 0xe8, 0x5b, 0xf9, 0x1d, 0x28, 0xaa, 0xbd, 0x3f, 0x1f, - 0xe9, 0x34, 0x0b, 0x03, 0x92, 0xd6, 0x36, 0xa0, 0x34, 0xb0, 0x27, 0xf6, 0xc0, 0x09, 0xaf, 0x25, - 0x43, 0x88, 0xbe, 0x45, 0xe9, 0x23, 0x6f, 0x60, 0x8f, 0xac, 0x13, 0x7b, 0x64, 0xbb, 0x03, 0x2e, - 0x75, 0xf7, 0x2a, 0x02, 0xb7, 0x08, 0x26, 0xf4, 0x73, 0xd9, 0x4e, 0x85, 0x45, 0x2a, 0xbc, 0x6c, - 0xbd, 0x42, 0x13, 0xc2, 0xa5, 0x37, 0x1e, 0x3b, 0x42, 0xcb, 0x20, 0x31, 0x2c, 0x67, 0x96, 0x09, - 0xb2, 0xcb, 0xb1, 0xb7, 0x32, 0xf9, 0x92, 0x86, 0xae, 0x4c, 0x55, 0x11, 0xf0, 0x53, 0x3a, 0x48, - 0x98, 0x97, 0xc5, 0x72, 0x9a, 0x2c, 0xf6, 0x2e, 0x2c, 0x4d, 0xdd, 0x80, 0x87, 0xe1, 0x88, 0x0f, - 0xa3, 0xb6, 0x54, 0x10, 0xa9, 0x11, 0x25, 0xa8, 0xe6, 0x6c, 0xc2, 0x32, 0x1d, 0x3a, 0x04, 0x76, - 0xe8, 0x05, 0xe7, 0x4e, 0x60, 0x05, 0x42, 0x43, 0x22, 0x75, 0x77, 0x09, 0x93, 0x7a, 0x32, 0xa5, - 0x47, 0x2a, 0xd2, 0xfa, 0x0c, 0xbe, 0xcf, 0x07, 0xdc, 0xb9, 0xe0, 0x43, 0x94, 0xd3, 0x72, 0xe6, - 0x6a, 0x22, 0x8f, 0x29, 0x13, 0x51, 0xe8, 0x9e, 0x8e, 0xad, 0xe9, 0x64, 0x68, 0x0b, 0x61, 0xa5, - 0x4e, 0xc2, 0xb0, 0x3b, 0x1d, 0x1f, 0x13, 0x84, 0x3d, 0x06, 0x25, 0x89, 0x49, 0xf9, 0x70, 0x31, - 0xc1, 0xcf, 0x04, 0xb1, 0x9a, 0x55, 0x89, 0x41, 0x82, 0x62, 0x42, 0xe6, 0x6c, 0xcc, 0xc8, 0x9c, - 0x4d, 0x28, 0x4e, 0x7c, 0xe7, 0xc2, 0x0e, 0x79, 0x73, 0x89, 0x18, 0xb8, 0xfc, 0x14, 0x9c, 0xc1, - 0x71, 0x9d, 0xd0, 0xb1, 0x43, 0xcf, 0x6f, 0x32, 0x4c, 0x8b, 0x01, 0xec, 0x21, 0x2c, 0x21, 0x8d, - 0x04, 0xa1, 0x1d, 0x4e, 0x03, 0x29, 0x81, 0x2e, 0x23, 0x31, 0xa1, 0x0c, 0xdd, 0x43, 0x38, 0x0a, - 0xa1, 0xec, 0x1b, 0xb0, 0x46, 0x64, 0x81, 0x39, 0xa4, 0x64, 0x8d, 0x02, 0xc1, 0x0a, 0x0e, 0xc5, - 0x32, 0xa6, 0x0a, 0xfa, 0x96, 0xf2, 0xb5, 0x90, 0x0e, 0xde, 0x87, 0x75, 0x49, 0x26, 0x73, 0xb9, - 0x56, 0x31, 0xd7, 0x0a, 0x25, 0xcf, 0x64, 0xdb, 0x84, 0x25, 0xd1, 0x24, 0x67, 0x60, 0xc9, 0xdc, - 0x62, 0x25, 0xac, 0x89, 0xd6, 0xa3, 0xa6, 0xb4, 0x48, 0x89, 0x26, 0xa6, 0x3d, 0xe3, 0xd7, 0xec, - 0xbb, 0xb0, 0x48, 0x24, 0x83, 0xea, 0x15, 0x72, 0xfa, 0x0d, 0xe4, 0xf4, 0xab, 0xea, 0x84, 0x33, - 0x4a, 0x45, 0x66, 0x5f, 0x1f, 0x24, 0xbe, 0xc5, 0x72, 0x18, 0x39, 0xa7, 0x3c, 0x74, 0xc6, 0xbc, - 0xb9, 0x4e, 0x04, 0xa6, 0xbe, 0xc5, 0x4a, 0x9d, 0x4e, 0x30, 0xa5, 0x49, 0x7c, 0x81, 0xbe, 0x90, - 0x76, 0x47, 0x5e, 0xc0, 0xd5, 0x11, 0x55, 0xf3, 0xb6, 0x5c, 0x84, 0x02, 0xa8, 0x64, 0x48, 0x21, - 0x88, 0x93, 0xd2, 0x13, 0x1d, 0x24, 0xde, 0x41, 0x62, 0xa8, 0x91, 0xee, 0xa3, 0x0e, 0x13, 0xc5, - 0x2e, 0x7e, 0x6e, 0x5f, 0x2a, 0x0e, 0xf2, 0x1a, 0xce, 0x2f, 0x08, 0x90, 0xe4, 0x1d, 0x3f, 0xc9, - 0xd0, 0x86, 0x28, 0xf9, 0x47, 0xa0, 0xa9, 0x77, 0xc4, 0x39, 0x2c, 0xcf, 0x1d, 0x5d, 0x4b, 0x66, - 0x02, 0x04, 0x3a, 0x74, 0x47, 0xb8, 0x9a, 0x1d, 0x57, 0x47, 0x21, 0xde, 0x5b, 0x55, 0x40, 0x44, - 0xba, 0x07, 0x95, 0xc9, 0xf4, 0x64, 0xe4, 0x0c, 0x08, 0x25, 0x47, 0xa5, 0x10, 0x08, 0x11, 0x84, - 0x7e, 0x4b, 0x14, 0x45, 0x18, 0x79, 0xc4, 0xa8, 0x48, 0x18, 0xa2, 0x20, 0x6f, 0xe7, 0x3e, 0xb2, - 0x93, 0xaa, 0x89, 0xbf, 0x8d, 0x2d, 0x58, 0x49, 0x36, 0x5a, 0x6e, 0x3c, 0x0f, 0xa1, 0x24, 0x79, - 0x95, 0x3a, 0xf8, 0xa8, 0x6b, 0x47, 0xd1, 0x42, 0x45, 0x8b, 0xd2, 0x8d, 0xdf, 0x5a, 0x80, 0x65, - 0x09, 0xdd, 0x16, 0x43, 0xdb, 0x9b, 0x8e, 0xc7, 0xb6, 0x9f, 0xc2, 0x04, 0x33, 0x2f, 0x66, 0x82, - 0xd9, 0x39, 0x26, 0x98, 0xd4, 0x7c, 0x89, 0x87, 0x26, 0x35, 0x5f, 0x31, 0x97, 0xa4, 0x8c, 0xe8, - 0xe7, 0xa0, 0x35, 0x09, 0xee, 0xd3, 0x79, 0xeb, 0x1c, 0xcb, 0x2e, 0xa4, 0xb0, 0x6c, 0x9d, 0xe1, - 0x2e, 0xcc, 0x30, 0xdc, 0x37, 0x80, 0x88, 0x46, 0xcd, 0x7e, 0x91, 0xf4, 0x13, 0x84, 0xc9, 0xc3, - 0xd4, 0xb7, 0x61, 0x71, 0x96, 0xc7, 0x11, 0x33, 0xad, 0xa7, 0x70, 0x38, 0x67, 0xcc, 0x71, 0xb7, - 0xd2, 0x90, 0xcb, 0x92, 0xc3, 0x39, 0x63, 0xbe, 0x8f, 0x29, 0x0a, 0xbf, 0x0d, 0x40, 0x75, 0xe3, - 0xa2, 0x01, 0x5c, 0x34, 0x6f, 0x25, 0xe7, 0x42, 0x1f, 0xf5, 0x4d, 0xf1, 0x31, 0xf5, 0x39, 0xae, - 0xa2, 0x32, 0xe6, 0xc4, 0x05, 0xf4, 0x0c, 0xea, 0xde, 0x84, 0xbb, 0x56, 0xcc, 0x6b, 0x2a, 0x58, - 0xd4, 0x9b, 0x2f, 0x28, 0xaa, 0xa3, 0x70, 0xcd, 0x9a, 0xc8, 0x1b, 0x7d, 0xb2, 0x03, 0x1a, 0x78, - 0xae, 0x95, 0x56, 0xfd, 0x12, 0xa5, 0xd5, 0x31, 0x73, 0xf4, 0x6d, 0xfc, 0xbd, 0x0c, 0x54, 0xb4, - 0x66, 0xb3, 0x55, 0x58, 0xda, 0x3e, 0x3c, 0x3c, 0x6a, 0x9b, 0xad, 0x7e, 0xe7, 0x93, 0xb6, 0xb5, - 0xbd, 0x7f, 0xd8, 0x6b, 0x37, 0x6e, 0x09, 0xf0, 0xfe, 0xe1, 0x76, 0x6b, 0xdf, 0xda, 0x3d, 0x34, - 0xb7, 0x15, 0x38, 0xc3, 0xd6, 0x80, 0x99, 0xed, 0x83, 0xc3, 0x7e, 0x3b, 0x01, 0xcf, 0xb2, 0x06, - 0x54, 0xb7, 0xcc, 0x76, 0x6b, 0x7b, 0x4f, 0x42, 0x72, 0x6c, 0x05, 0x1a, 0xbb, 0xc7, 0xdd, 0x9d, - 0x4e, 0xf7, 0xa9, 0xb5, 0xdd, 0xea, 0x6e, 0xb7, 0xf7, 0xdb, 0x3b, 0x8d, 0x3c, 0xab, 0x41, 0xb9, - 0xb5, 0xd5, 0xea, 0xee, 0x1c, 0x76, 0xdb, 0x3b, 0x8d, 0x82, 0xf1, 0x1d, 0x28, 0xc7, 0x1d, 0xad, - 0x40, 0xf1, 0xb8, 0xfb, 0xac, 0x7b, 0xf8, 0x69, 0xb7, 0x71, 0x8b, 0x95, 0xa1, 0x80, 0xf5, 0x37, - 0x32, 0x0c, 0x60, 0x81, 0xea, 0x6c, 0x64, 0x59, 0x09, 0xf2, 0x5b, 0x87, 0xfd, 0xbd, 0x46, 0xce, - 0xf8, 0xcb, 0x0c, 0xac, 0x62, 0x97, 0x87, 0xb3, 0x4c, 0xe0, 0x3e, 0x54, 0x06, 0x9e, 0x37, 0x11, - 0x9a, 0x56, 0x2c, 0x51, 0xe8, 0x20, 0xb1, 0xc0, 0x89, 0x79, 0x9f, 0x7a, 0xfe, 0x80, 0x4b, 0x1e, - 0x00, 0x08, 0xda, 0x15, 0x10, 0x41, 0x83, 0x92, 0x88, 0x09, 0x83, 0x58, 0x40, 0x85, 0x60, 0x84, - 0xb2, 0x06, 0x0b, 0x27, 0x3e, 0xb7, 0x07, 0xe7, 0x72, 0xf5, 0xcb, 0x2f, 0xf6, 0x4e, 0x7c, 0x06, - 0x30, 0x10, 0x34, 0x35, 0xe2, 0x43, 0x5c, 0x02, 0x25, 0x73, 0x51, 0xc2, 0xb7, 0x25, 0x58, 0xec, - 0x46, 0xf6, 0x89, 0xed, 0x0e, 0x3d, 0x97, 0x0f, 0xa5, 0xaa, 0x11, 0x03, 0x8c, 0x23, 0x58, 0x9b, - 0xed, 0x9f, 0xe4, 0x17, 0x1f, 0x68, 0xfc, 0x82, 0x24, 0xff, 0x8d, 0x9b, 0x49, 0x41, 0xe3, 0x1d, - 0xff, 0x20, 0x0f, 0x79, 0x21, 0x09, 0xde, 0x28, 0x34, 0xea, 0xa2, 0x7d, 0x6e, 0xce, 0xfc, 0x83, - 0x47, 0x0d, 0x24, 0x22, 0xd0, 0x79, 0x56, 0x19, 0x21, 0x28, 0x1a, 0x44, 0xc9, 0x3e, 0x1f, 0x5c, - 0xc8, 0x03, 0x2d, 0x4a, 0x36, 0xf9, 0xe0, 0x02, 0x75, 0x2a, 0x3b, 0xa4, 0xbc, 0xb4, 0xde, 0x8b, - 0x81, 0x1d, 0x62, 0x4e, 0x99, 0x84, 0xf9, 0x8a, 0x51, 0x12, 0xe6, 0x6a, 0x42, 0xd1, 0x71, 0x4f, - 0xbc, 0xa9, 0x3b, 0xc4, 0xe5, 0x5d, 0x32, 0xd5, 0x27, 0x5a, 0x9b, 0x90, 0x13, 0x89, 0x8d, 0x88, - 0x56, 0x73, 0x49, 0x00, 0xfa, 0x62, 0x2b, 0x7a, 0x0f, 0xca, 0xc1, 0xb5, 0x3b, 0xd0, 0xd7, 0xf0, - 0x8a, 0x1c, 0x1f, 0xd1, 0xfb, 0xcd, 0xde, 0xb5, 0x3b, 0xc0, 0x15, 0x5b, 0x0a, 0xe4, 0x2f, 0xf6, - 0x3e, 0x94, 0xa2, 0x73, 0x5f, 0xe2, 0xc0, 0xb7, 0xf5, 0x1c, 0xea, 0xb0, 0x97, 0xd4, 0xeb, 0x08, - 0x95, 0x3d, 0x82, 0x05, 0x3c, 0x9c, 0x0d, 0x9a, 0x55, 0xcc, 0xa4, 0xe4, 0x7d, 0xd1, 0x0c, 0x34, - 0xf4, 0xf0, 0x21, 0x1e, 0xd4, 0x9a, 0x12, 0x6d, 0xe3, 0x19, 0xd4, 0x12, 0x65, 0xe9, 0x4a, 0x74, - 0x8d, 0x94, 0xe8, 0x37, 0x75, 0x25, 0x3a, 0xde, 0x09, 0x64, 0x36, 0x5d, 0xa9, 0xfe, 0x65, 0x28, - 0xa9, 0xae, 0x88, 0xf5, 0x27, 0xd7, 0x8e, 0xd5, 0xfb, 0xac, 0xbb, 0xdd, 0xb8, 0xc5, 0x16, 0xa1, - 0xd2, 0xda, 0xc6, 0x25, 0x8d, 0x80, 0x8c, 0x40, 0x39, 0x6a, 0xf5, 0x7a, 0x11, 0x24, 0x6b, 0xec, - 0x42, 0x63, 0xb6, 0xa5, 0x82, 0x26, 0x43, 0x05, 0x93, 0x47, 0xd7, 0x31, 0x40, 0xa8, 0x48, 0x74, - 0x1a, 0x4d, 0x72, 0x38, 0x7d, 0x18, 0xef, 0x43, 0x43, 0xec, 0x6b, 0x62, 0xa8, 0x02, 0xed, 0x08, - 0x78, 0x24, 0x64, 0x3b, 0xfd, 0xf8, 0xba, 0x64, 0x56, 0x08, 0x86, 0x55, 0x19, 0x1f, 0xc0, 0x92, - 0x96, 0x2d, 0x56, 0x69, 0xc5, 0x5e, 0x39, 0xab, 0xd2, 0xa2, 0x02, 0x43, 0x29, 0xc6, 0x3a, 0xac, - 0x8a, 0xcf, 0xf6, 0x05, 0x77, 0xc3, 0xde, 0xf4, 0x84, 0x6c, 0x8e, 0x8e, 0xe7, 0x0a, 0xc5, 0xa6, - 0x1c, 0xa5, 0xdc, 0x4c, 0xe4, 0x9b, 0x52, 0xfb, 0xcd, 0x22, 0x69, 0x6c, 0x68, 0x35, 0x60, 0xc6, - 0x4d, 0xfc, 0x9b, 0xd0, 0x82, 0xcb, 0x11, 0x48, 0x0c, 0xeb, 0x51, 0xbb, 0x6d, 0x5a, 0x87, 0xdd, - 0xfd, 0x4e, 0x57, 0x30, 0x4a, 0x31, 0xac, 0x08, 0xd8, 0xdd, 0x45, 0x48, 0xc6, 0x68, 0x40, 0xfd, - 0x29, 0x0f, 0x3b, 0xee, 0xa9, 0xa7, 0xec, 0x6b, 0x7f, 0x55, 0x80, 0xc5, 0x08, 0x14, 0x6b, 0xd1, - 0x17, 0xdc, 0x0f, 0x1c, 0xcf, 0x45, 0x81, 0xb8, 0x6c, 0xaa, 0x4f, 0xb1, 0xbb, 0x39, 0x43, 0xee, - 0x86, 0x4e, 0x78, 0x6d, 0x25, 0x8e, 0xdc, 0xea, 0x0a, 0x2c, 0x77, 0xd1, 0x15, 0x28, 0xd8, 0x23, - 0xc7, 0x56, 0xa6, 0x5a, 0xfa, 0x10, 0xd0, 0x81, 0x37, 0xf2, 0x7c, 0x94, 0x7d, 0xcb, 0x26, 0x7d, - 0xb0, 0xc7, 0xb0, 0x22, 0x64, 0x70, 0xfd, 0x1c, 0x14, 0xf9, 0x07, 0x9d, 0xfe, 0x31, 0x77, 0x3a, - 0x3e, 0x8a, 0xcf, 0x42, 0x45, 0x8a, 0xd8, 0x3b, 0x45, 0x0e, 0x29, 0x2c, 0x45, 0x19, 0x48, 0x9d, - 0x5b, 0x72, 0xa7, 0xe3, 0x16, 0xa6, 0x44, 0xf8, 0x4f, 0x60, 0x55, 0xe0, 0x47, 0xe2, 0x55, 0x94, - 0x63, 0x11, 0x73, 0x88, 0xc2, 0x3a, 0x32, 0x2d, 0xca, 0x73, 0x07, 0xca, 0xd4, 0x2a, 0x31, 0xe3, - 0x05, 0x12, 0xe3, 0xb1, 0x29, 0xdc, 0x0f, 0xe6, 0xac, 0xaa, 0x0b, 0x24, 0x08, 0xcc, 0x58, 0x55, - 0x35, 0xbb, 0x6c, 0x69, 0xd6, 0x2e, 0xfb, 0x04, 0x56, 0x4f, 0x04, 0x09, 0x9e, 0x73, 0x7b, 0xc8, - 0x7d, 0x2b, 0x26, 0x6c, 0x52, 0x57, 0x96, 0x45, 0xe2, 0x1e, 0xa6, 0x45, 0xeb, 0x40, 0xc8, 0x39, - 0x82, 0x2d, 0xf0, 0xa1, 0x15, 0x7a, 0x16, 0x8a, 0x3f, 0xc8, 0x60, 0x4a, 0x66, 0x8d, 0xc0, 0x7d, - 0x6f, 0x5b, 0x00, 0x93, 0x78, 0x67, 0xbe, 0x3d, 0x39, 0x97, 0x0a, 0x45, 0x84, 0xf7, 0x54, 0x00, - 0xd9, 0x6b, 0x50, 0x14, 0x24, 0xef, 0x72, 0x32, 0x7e, 0x91, 0xc8, 0xae, 0x40, 0xec, 0x4d, 0x58, - 0xc0, 0x3a, 0x82, 0x66, 0x03, 0xe9, 0xbd, 0x1a, 0x33, 0x72, 0xc7, 0x35, 0x65, 0x9a, 0x10, 0x26, - 0xa7, 0xbe, 0x43, 0x5c, 0xa6, 0x6c, 0xe2, 0x6f, 0xf6, 0x3d, 0x8d, 0x65, 0x2d, 0x63, 0x5e, 0x25, - 0x0f, 0xcc, 0x50, 0xda, 0x4d, 0xdc, 0xeb, 0xe7, 0xca, 0x8c, 0xbe, 0x9f, 0x2f, 0x55, 0x1a, 0x55, - 0xe3, 0x5b, 0x50, 0xa0, 0xd1, 0x11, 0x44, 0x88, 0x63, 0x97, 0x91, 0x44, 0x88, 0xd0, 0x26, 0x14, - 0x5d, 0x1e, 0x5e, 0x7a, 0xfe, 0x73, 0x75, 0x28, 0x2d, 0x3f, 0x8d, 0x1f, 0xe1, 0x69, 0x4a, 0x64, - 0x71, 0x27, 0xc5, 0x50, 0x90, 0x07, 0x4d, 0x6f, 0x70, 0x6e, 0xcb, 0x03, 0x9e, 0x12, 0x02, 0x7a, - 0xe7, 0xf6, 0x1c, 0x79, 0x64, 0xe7, 0x8d, 0xee, 0x6f, 0x42, 0x5d, 0xd9, 0xf8, 0x03, 0x6b, 0xc4, - 0x4f, 0x43, 0x49, 0xee, 0x55, 0x69, 0xe0, 0x0f, 0xf6, 0xf9, 0x69, 0x68, 0x1c, 0xc0, 0x92, 0x24, - 0xc8, 0xc3, 0x09, 0x57, 0x55, 0x7f, 0x3b, 0x4d, 0x9e, 0xae, 0x3c, 0x59, 0x4e, 0x6e, 0xb4, 0xe4, - 0xbb, 0x90, 0x10, 0xb2, 0x8d, 0x8f, 0x81, 0xe9, 0xdb, 0xb0, 0x2c, 0x4f, 0x4a, 0xb5, 0xea, 0x2c, - 0x5f, 0x99, 0xc4, 0x22, 0xd9, 0xd9, 0x19, 0x8a, 0xd1, 0x09, 0xa6, 0x83, 0x81, 0xf2, 0xbd, 0x28, - 0x99, 0xea, 0xd3, 0xf8, 0xb3, 0x0c, 0x2c, 0x63, 0x61, 0x4a, 0x1f, 0x90, 0x4c, 0xf6, 0xa7, 0x6e, - 0xa4, 0x98, 0x1f, 0x5d, 0xf6, 0xa1, 0x8f, 0x2f, 0x7f, 0x7a, 0x9a, 0x9f, 0x3b, 0x3d, 0x7d, 0x07, - 0x1a, 0x43, 0x3e, 0x72, 0xd0, 0x0d, 0x47, 0x89, 0x12, 0xa4, 0x01, 0x2c, 0x2a, 0xb8, 0xd4, 0x06, - 0x8d, 0x7f, 0x92, 0x81, 0x25, 0x92, 0x54, 0x50, 0xaf, 0x96, 0x03, 0xf5, 0x91, 0x52, 0x24, 0x25, - 0xab, 0x92, 0x7d, 0x8a, 0x77, 0x70, 0x84, 0x12, 0xf2, 0xde, 0x2d, 0xa9, 0x60, 0x4a, 0x28, 0xfb, - 0x10, 0x75, 0x18, 0xd7, 0x42, 0x60, 0x8a, 0x5b, 0x4f, 0x72, 0x52, 0xf6, 0x6e, 0xa1, 0x82, 0xe3, - 0x22, 0x68, 0xab, 0x24, 0x34, 0x5b, 0x01, 0x36, 0x76, 0xa1, 0x96, 0xa8, 0x26, 0x71, 0xc4, 0x5b, - 0xa5, 0x23, 0xde, 0x39, 0x33, 0x4a, 0x76, 0xde, 0x8c, 0x72, 0x0d, 0xcb, 0x26, 0xb7, 0x87, 0xd7, - 0xbb, 0x9e, 0x7f, 0x14, 0x9c, 0x84, 0xbb, 0x24, 0xfe, 0x09, 0xfe, 0x1e, 0xd9, 0x06, 0x13, 0xe7, - 0xa8, 0xca, 0x44, 0xa4, 0xd4, 0xe5, 0xaf, 0x42, 0x3d, 0x36, 0x22, 0x6a, 0x67, 0x71, 0xb5, 0xc8, - 0x8e, 0x88, 0x47, 0x72, 0x42, 0xd5, 0x0c, 0x4e, 0x42, 0x79, 0x1a, 0x87, 0xbf, 0x8d, 0xbf, 0x93, - 0x07, 0x26, 0xa8, 0x79, 0x86, 0x60, 0x66, 0xcc, 0x9f, 0xd9, 0x39, 0xf3, 0xe7, 0x63, 0x60, 0x1a, - 0x82, 0xb2, 0xca, 0xe6, 0x22, 0xab, 0x6c, 0x23, 0xc6, 0x95, 0x46, 0xd9, 0xc7, 0xb0, 0x22, 0x65, - 0xe9, 0x64, 0x53, 0x89, 0x34, 0x18, 0x09, 0xd5, 0x89, 0xf6, 0x2a, 0xd3, 0xa7, 0x50, 0xff, 0xe9, - 0xb4, 0x0d, 0x4d, 0x9f, 0x4a, 0xf1, 0xd7, 0x08, 0x70, 0xe1, 0xa5, 0x04, 0x58, 0x9c, 0x23, 0x40, - 0xed, 0xf0, 0xa7, 0x94, 0x3c, 0xfc, 0x31, 0xa0, 0xa6, 0x0c, 0x9c, 0xe4, 0xd7, 0x41, 0x82, 0x63, - 0x45, 0x5a, 0x39, 0xd1, 0xb7, 0xe3, 0x01, 0x34, 0xd4, 0x09, 0x4d, 0x74, 0xbc, 0x44, 0x3e, 0x0b, - 0xf2, 0x80, 0x6f, 0x5b, 0x1d, 0x32, 0x25, 0x0e, 0xf3, 0x2b, 0x33, 0x87, 0xf9, 0xef, 0xc2, 0x52, - 0x20, 0xe8, 0xd7, 0x9a, 0xba, 0xd2, 0xc1, 0x88, 0x0f, 0x51, 0x6b, 0x2b, 0x99, 0x0d, 0x4c, 0x38, - 0x8e, 0xe1, 0xf3, 0x47, 0x27, 0xb5, 0x94, 0xa3, 0x93, 0xf7, 0x63, 0x5b, 0x60, 0x70, 0xee, 0x8c, - 0x51, 0x66, 0x88, 0x9d, 0x71, 0xe4, 0x00, 0xf7, 0xce, 0x9d, 0xb1, 0xa9, 0x0c, 0xcf, 0xe2, 0xc3, - 0xf8, 0xbf, 0x19, 0x68, 0x08, 0x3a, 0x48, 0x2c, 0xb1, 0xef, 0x00, 0x32, 0x83, 0x57, 0x5c, 0x61, - 0x15, 0x81, 0xab, 0x16, 0xd8, 0xb7, 0x00, 0x57, 0x8c, 0x25, 0x54, 0x54, 0xb9, 0xbe, 0x9a, 0xc9, - 0xf5, 0x15, 0xf3, 0xd0, 0xbd, 0x5b, 0xa4, 0x7b, 0x08, 0x08, 0xfb, 0x0e, 0x94, 0x05, 0x61, 0x22, - 0x95, 0x48, 0x1f, 0x30, 0x25, 0x79, 0xa5, 0xac, 0x11, 0x91, 0x75, 0x22, 0x3f, 0xd3, 0xcc, 0xb7, - 0xf9, 0x14, 0xf3, 0xad, 0xb6, 0x80, 0xf7, 0x00, 0x9e, 0xf1, 0xeb, 0x7d, 0x6f, 0x80, 0x7a, 0xe5, - 0x5d, 0x00, 0x41, 0xcb, 0xa7, 0xf6, 0xd8, 0x91, 0x67, 0x42, 0x05, 0xb3, 0xfc, 0x9c, 0x5f, 0xef, - 0x22, 0x40, 0x4c, 0xa4, 0x48, 0x8e, 0x57, 0x71, 0xc1, 0x2c, 0x3d, 0xe7, 0xd7, 0xb4, 0x84, 0x2d, - 0xa8, 0x3d, 0xe3, 0xd7, 0x3b, 0x9c, 0x84, 0x4c, 0xcf, 0x17, 0x44, 0xe4, 0xdb, 0x97, 0x42, 0xaa, - 0x4c, 0x98, 0x5e, 0x2b, 0xbe, 0x7d, 0xf9, 0x8c, 0x5f, 0x2b, 0x33, 0x70, 0x51, 0xa4, 0x8f, 0xbc, - 0x81, 0xdc, 0x37, 0x95, 0x13, 0x49, 0xdc, 0x28, 0x73, 0xe1, 0x39, 0xfe, 0x36, 0xfe, 0x3a, 0x03, - 0x35, 0xd1, 0x7e, 0x64, 0xcb, 0x62, 0xca, 0x94, 0x2f, 0x52, 0x26, 0xf6, 0x45, 0x7a, 0x22, 0xb9, - 0x1a, 0xf1, 0xf8, 0xec, 0xcd, 0x3c, 0x1e, 0xe7, 0x86, 0x18, 0xfc, 0x7b, 0x50, 0xa6, 0x65, 0x29, + // 11862 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x6f, 0x24, 0x49, + 0x72, 0xd8, 0xf4, 0x8b, 0xdd, 0x1d, 0xfd, 0x60, 0x33, 0xf9, 0xea, 0xe1, 0xcc, 0xec, 0xcc, 0xd6, + 0xee, 0xed, 0xce, 0xce, 0xde, 0x71, 0x66, 0xe7, 0x6e, 0xf6, 0xee, 0x76, 0xad, 0xd3, 0x35, 0xc9, + 0xe6, 0xb0, 0x6f, 0xf8, 0xda, 0xea, 0xe6, 0xae, 0xe6, 0xf4, 0xa8, 0x2b, 0x76, 0x27, 0xc9, 0xd2, + 0x74, 0x57, 0xf5, 0x56, 0x55, 0xf3, 0x71, 0x87, 0xf5, 0x07, 0xc3, 0x16, 0x0c, 0xc3, 0x0f, 0x08, + 0xb6, 0x0c, 0x58, 0xb6, 0x60, 0xc3, 0x82, 0x61, 0x18, 0x06, 0x04, 0x01, 0x27, 0x7f, 0x30, 0xe0, + 0xef, 0x82, 0x01, 0x1b, 0x86, 0x21, 0xf9, 0x8b, 0x21, 0x08, 0x30, 0x6c, 0xcb, 0x1f, 0x0c, 0x18, + 0x02, 0xfc, 0x07, 0x8c, 0x8c, 0xc8, 0xac, 0xca, 0xea, 0x2e, 0xce, 0xcc, 0xde, 0xad, 0xef, 0x0b, + 0xd9, 0x15, 0x19, 0xf9, 0x8e, 0x8c, 0x8c, 0xc8, 0x88, 0xc8, 0x84, 0xb2, 0x3f, 0xee, 0xaf, 0x8f, + 0x7d, 0x2f, 0xf4, 0x58, 0x61, 0xe8, 0xfa, 0xe3, 0xfe, 0xda, 0xed, 0x53, 0xcf, 0x3b, 0x1d, 0xf2, + 0x87, 0xf6, 0xd8, 0x79, 0x68, 0xbb, 0xae, 0x17, 0xda, 0xa1, 0xe3, 0xb9, 0x01, 0x21, 0x19, 0x3f, + 0x82, 0xfa, 0x53, 0xee, 0x76, 0x39, 0x1f, 0x98, 0xfc, 0xf3, 0x09, 0x0f, 0x42, 0xf6, 0x3e, 0x2c, + 0xd8, 0xfc, 0xc7, 0x9c, 0x0f, 0xac, 0xb1, 0x1d, 0x04, 0xe3, 0x33, 0xdf, 0x0e, 0x78, 0x33, 0x73, + 0x2f, 0x73, 0xbf, 0x6a, 0x36, 0x28, 0xe1, 0x30, 0x82, 0xb3, 0x37, 0xa1, 0x1a, 0x08, 0x54, 0xee, + 0x86, 0xbe, 0x37, 0xbe, 0x6a, 0x66, 0x11, 0xaf, 0x22, 0x60, 0x6d, 0x02, 0x19, 0x43, 0x98, 0x8f, + 0x6a, 0x08, 0xc6, 0x9e, 0x1b, 0x70, 0xf6, 0x08, 0x96, 0xfa, 0xce, 0xf8, 0x8c, 0xfb, 0x16, 0x66, + 0x1e, 0xb9, 0x7c, 0xe4, 0xb9, 0x4e, 0xbf, 0x99, 0xb9, 0x97, 0xbb, 0x5f, 0x36, 0x19, 0xa5, 0x89, + 0x1c, 0x7b, 0x32, 0x85, 0xbd, 0x0b, 0xf3, 0xdc, 0x25, 0x38, 0x1f, 0x60, 0x2e, 0x59, 0x55, 0x3d, + 0x06, 0x8b, 0x0c, 0xc6, 0xdf, 0xcc, 0xc2, 0x42, 0xc7, 0x75, 0xc2, 0xcf, 0xec, 0xe1, 0x90, 0x87, + 0xaa, 0x4f, 0xef, 0xc2, 0xfc, 0x05, 0x02, 0xb0, 0x4f, 0x17, 0x9e, 0x3f, 0x90, 0x3d, 0xaa, 0x13, + 0xf8, 0x50, 0x42, 0xaf, 0x6d, 0x59, 0xf6, 0xda, 0x96, 0xa5, 0x0e, 0x57, 0xee, 0x9a, 0xe1, 0x7a, + 0x17, 0xe6, 0x7d, 0xde, 0xf7, 0xce, 0xb9, 0x7f, 0x65, 0x5d, 0x38, 0xee, 0xc0, 0xbb, 0x68, 0xe6, + 0xef, 0x65, 0xee, 0x17, 0xcc, 0xba, 0x02, 0x7f, 0x86, 0x50, 0xb6, 0x01, 0xf3, 0xfd, 0x33, 0xdb, + 0x75, 0xf9, 0xd0, 0x3a, 0xb6, 0xfb, 0x2f, 0x26, 0xe3, 0xa0, 0x59, 0xb8, 0x97, 0xb9, 0x5f, 0x79, + 0x7c, 0x73, 0x1d, 0x67, 0x75, 0x7d, 0xf3, 0xcc, 0x76, 0x37, 0x30, 0xa5, 0xeb, 0xda, 0xe3, 0xe0, + 0xcc, 0x0b, 0xcd, 0xba, 0xcc, 0x41, 0xe0, 0xc0, 0x58, 0x02, 0xa6, 0x8f, 0x04, 0x8d, 0xbd, 0xf1, + 0xaf, 0x33, 0xb0, 0x78, 0xe4, 0x0e, 0xbd, 0xfe, 0x8b, 0x9f, 0x71, 0x88, 0x52, 0xfa, 0x90, 0x7d, + 0xdd, 0x3e, 0xe4, 0xbe, 0x6c, 0x1f, 0x56, 0x60, 0x29, 0xd9, 0x58, 0xd9, 0x0b, 0x0e, 0xcb, 0x22, + 0xf7, 0x29, 0x57, 0xcd, 0x52, 0xdd, 0x78, 0x0f, 0x1a, 0xfd, 0x89, 0xef, 0x73, 0x77, 0xa6, 0x1f, + 0xf3, 0x12, 0x1e, 0x75, 0xe4, 0x4d, 0xa8, 0xba, 0xfc, 0x22, 0x46, 0x93, 0xb4, 0xeb, 0xf2, 0x0b, + 0x85, 0x62, 0x34, 0x61, 0x65, 0xba, 0x1a, 0xd9, 0x80, 0xbf, 0xc8, 0x40, 0xfe, 0x28, 0xbc, 0xf4, + 0xd8, 0x13, 0xa8, 0xda, 0x83, 0x81, 0xcf, 0x83, 0xc0, 0x0a, 0xaf, 0xc6, 0xb4, 0x52, 0xea, 0x8f, + 0x99, 0xec, 0x62, 0x8b, 0x92, 0x7a, 0x57, 0x63, 0x6e, 0x56, 0xec, 0xf8, 0x83, 0x35, 0xa1, 0x28, + 0x3f, 0xb1, 0xde, 0xb2, 0xa9, 0x3e, 0xd9, 0x1d, 0x00, 0x7b, 0xe4, 0x4d, 0xdc, 0xd0, 0x0a, 0xec, + 0x10, 0x47, 0x2c, 0x67, 0x96, 0x09, 0xd2, 0xb5, 0x43, 0x76, 0x0b, 0xca, 0xe3, 0x17, 0x56, 0xd0, + 0xf7, 0x9d, 0x71, 0x88, 0xc4, 0x53, 0x36, 0x4b, 0xe3, 0x17, 0x5d, 0xfc, 0x66, 0xef, 0x43, 0xc9, + 0x9b, 0x84, 0x63, 0xcf, 0x71, 0x43, 0x49, 0x2f, 0xf3, 0xb2, 0x21, 0x07, 0x93, 0xf0, 0x50, 0x80, + 0xcd, 0x08, 0x81, 0xbd, 0x0d, 0xb5, 0xbe, 0xe7, 0x9e, 0x38, 0xfe, 0x88, 0x38, 0x42, 0x73, 0x0e, + 0xeb, 0x4a, 0x02, 0x8d, 0x3f, 0xcc, 0x42, 0xa5, 0xe7, 0xdb, 0x6e, 0x60, 0xf7, 0x05, 0x80, 0xad, + 0x42, 0x31, 0xbc, 0xb4, 0xce, 0xec, 0xe0, 0x0c, 0xbb, 0x5a, 0x36, 0xe7, 0xc2, 0xcb, 0x1d, 0x3b, + 0x38, 0x63, 0x2b, 0x30, 0x47, 0xad, 0xc4, 0x0e, 0xe5, 0x4c, 0xf9, 0x25, 0x16, 0x88, 0x3b, 0x19, + 0x59, 0xc9, 0xaa, 0x72, 0x48, 0x31, 0x0d, 0x77, 0x32, 0xda, 0xd4, 0xe1, 0xa2, 0xf3, 0xc7, 0x62, + 0xba, 0xa9, 0x02, 0xea, 0x5e, 0x19, 0x21, 0x58, 0xc7, 0x9b, 0x50, 0x95, 0xc9, 0xdc, 0x39, 0x3d, + 0xa3, 0x3e, 0x16, 0xcc, 0x0a, 0x21, 0x20, 0x48, 0x94, 0x10, 0x3a, 0x23, 0x6e, 0x05, 0xa1, 0x3d, + 0x1a, 0xcb, 0x2e, 0x95, 0x05, 0xa4, 0x2b, 0x00, 0x98, 0xec, 0x85, 0xf6, 0xd0, 0x3a, 0xe1, 0x3c, + 0x68, 0x16, 0x65, 0xb2, 0x80, 0x6c, 0x73, 0x1e, 0xb0, 0xaf, 0x41, 0x7d, 0xc0, 0x83, 0xd0, 0x92, + 0x93, 0xc1, 0x83, 0x66, 0x09, 0x57, 0x7e, 0x4d, 0x40, 0x5b, 0x0a, 0xc8, 0x6e, 0x03, 0xf8, 0xf6, + 0x85, 0x25, 0x06, 0x82, 0x5f, 0x36, 0xcb, 0x34, 0x0b, 0xbe, 0x7d, 0xd1, 0xbb, 0xdc, 0xe1, 0x97, + 0x82, 0x6a, 0x9e, 0xf2, 0x50, 0x1b, 0xb4, 0x40, 0x52, 0xa7, 0xb1, 0x0b, 0x4c, 0x03, 0x6f, 0xf1, + 0xd0, 0x76, 0x86, 0x01, 0xfb, 0x10, 0xaa, 0xa1, 0x86, 0x8c, 0x6c, 0xb0, 0x12, 0x91, 0x90, 0x96, + 0xc1, 0x4c, 0xe0, 0x19, 0x67, 0x50, 0xda, 0xe6, 0x7c, 0xd7, 0x19, 0x39, 0x21, 0x5b, 0x81, 0xc2, + 0x89, 0x73, 0xc9, 0x89, 0xd8, 0x73, 0x3b, 0x37, 0x4c, 0xfa, 0x64, 0x77, 0x01, 0xf0, 0x87, 0x35, + 0x8a, 0xa8, 0x69, 0xe7, 0x86, 0x59, 0x46, 0xd8, 0x5e, 0x60, 0x87, 0x6c, 0x0d, 0x8a, 0x63, 0xee, + 0xf7, 0xb9, 0x9a, 0xb7, 0x9d, 0x1b, 0xa6, 0x02, 0x6c, 0x14, 0xa1, 0x30, 0x14, 0xa5, 0x1b, 0x7f, + 0x5c, 0x80, 0x4a, 0x97, 0xbb, 0xd1, 0x2a, 0x63, 0x90, 0x17, 0x03, 0x22, 0x57, 0x16, 0xfe, 0x66, + 0x6f, 0x41, 0x05, 0x87, 0x2e, 0x08, 0x7d, 0xc7, 0x3d, 0x25, 0xaa, 0xde, 0xc8, 0x36, 0x33, 0x26, + 0x08, 0x70, 0x17, 0xa1, 0xac, 0x01, 0x39, 0x7b, 0xa4, 0xa8, 0x5a, 0xfc, 0x64, 0x37, 0xa1, 0x64, + 0x8f, 0x42, 0x6a, 0x5e, 0x15, 0xc1, 0x45, 0x7b, 0x14, 0x62, 0xd3, 0xde, 0x84, 0xea, 0xd8, 0xbe, + 0x1a, 0x89, 0xb5, 0x1c, 0x91, 0x43, 0xd5, 0xac, 0x48, 0x18, 0x12, 0xc4, 0x63, 0x58, 0xd4, 0x51, + 0x54, 0xe5, 0x85, 0xa8, 0xf2, 0x05, 0x0d, 0x5b, 0xb6, 0xe1, 0x5d, 0x98, 0x57, 0x79, 0x7c, 0xea, + 0x0f, 0x92, 0x49, 0xd9, 0xac, 0x4b, 0xb0, 0xea, 0xe5, 0x7d, 0x68, 0x9c, 0x38, 0xae, 0x3d, 0xb4, + 0xfa, 0xc3, 0xf0, 0xdc, 0x1a, 0xf0, 0x61, 0x68, 0x23, 0xc5, 0x14, 0xcc, 0x3a, 0xc2, 0x37, 0x87, + 0xe1, 0xf9, 0x96, 0x80, 0xb2, 0xaf, 0x43, 0xf9, 0x84, 0x73, 0x0b, 0x07, 0xab, 0x59, 0x4a, 0x2c, + 0x3c, 0x35, 0x43, 0x66, 0xe9, 0x44, 0xcd, 0xd5, 0xd7, 0xa1, 0xe1, 0x4d, 0xc2, 0x53, 0xcf, 0x71, + 0x4f, 0x2d, 0xc1, 0xef, 0x2c, 0x67, 0x80, 0x34, 0x94, 0xdf, 0xc8, 0x3e, 0xca, 0x98, 0x75, 0x95, + 0x26, 0x38, 0x4f, 0x67, 0xc0, 0xde, 0x81, 0xf9, 0xa1, 0x1d, 0x84, 0xd6, 0x99, 0x37, 0xb6, 0xc6, + 0x93, 0xe3, 0x17, 0xfc, 0xaa, 0x59, 0xc3, 0x81, 0xa8, 0x09, 0xf0, 0x8e, 0x37, 0x3e, 0x44, 0xa0, + 0xa0, 0x6c, 0x6c, 0x27, 0x35, 0x02, 0xee, 0x65, 0xee, 0xd7, 0xcc, 0xb2, 0x80, 0x50, 0xa5, 0xcf, + 0x61, 0x11, 0xa7, 0xa7, 0x3f, 0x09, 0x42, 0x6f, 0x64, 0x09, 0x5e, 0xed, 0x0f, 0x82, 0x66, 0x05, + 0x69, 0xed, 0x3d, 0xd9, 0x58, 0x6d, 0x8e, 0xd7, 0xb7, 0x78, 0x10, 0x6e, 0x22, 0xb2, 0x49, 0xb8, + 0x62, 0x43, 0xbf, 0x32, 0x17, 0x06, 0xd3, 0x70, 0xf6, 0x75, 0x60, 0xf6, 0x70, 0xe8, 0x5d, 0x58, + 0x01, 0x1f, 0x9e, 0x58, 0x72, 0x10, 0x9b, 0xf5, 0x7b, 0x99, 0xfb, 0x25, 0xb3, 0x81, 0x29, 0x5d, + 0x3e, 0x3c, 0x39, 0x24, 0x38, 0xfb, 0x10, 0x70, 0x31, 0x59, 0x27, 0xdc, 0x0e, 0x27, 0x3e, 0x0f, + 0x9a, 0xf3, 0xf7, 0x72, 0xf7, 0xeb, 0x8f, 0x17, 0xa2, 0xf1, 0x42, 0xf0, 0x86, 0x13, 0x9a, 0x55, + 0x81, 0x27, 0xbf, 0x83, 0xb5, 0x2d, 0x58, 0x49, 0x6f, 0x92, 0x20, 0x2a, 0x31, 0x2a, 0x82, 0x18, + 0xf3, 0xa6, 0xf8, 0xc9, 0x96, 0xa0, 0x70, 0x6e, 0x0f, 0x27, 0x5c, 0xf2, 0x74, 0xfa, 0xf8, 0x28, + 0xfb, 0x9d, 0x8c, 0xf1, 0x47, 0x19, 0xa8, 0x52, 0x2f, 0xa5, 0x2c, 0xf2, 0x16, 0xd4, 0x14, 0x35, + 0x70, 0xdf, 0xf7, 0x7c, 0xc9, 0xd5, 0x14, 0xe5, 0xb5, 0x05, 0x4c, 0xec, 0x2a, 0x0a, 0x69, 0xec, + 0x73, 0x67, 0x64, 0x9f, 0xaa, 0xa2, 0x15, 0x29, 0x1d, 0x4a, 0x30, 0xfb, 0x20, 0x2e, 0xcf, 0xf7, + 0x26, 0x21, 0x97, 0x7b, 0x5e, 0x55, 0x76, 0xcf, 0x14, 0xb0, 0xa8, 0x74, 0xfc, 0x7a, 0x0d, 0x3a, + 0x37, 0x7e, 0x27, 0x03, 0x4c, 0x34, 0xbb, 0xe7, 0x51, 0x01, 0x92, 0x42, 0xa7, 0x73, 0x66, 0x5e, + 0x7b, 0x85, 0x64, 0x5f, 0xb6, 0x42, 0x0c, 0x28, 0x50, 0xdb, 0xf3, 0x29, 0x6d, 0xa7, 0xa4, 0x1f, + 0xe4, 0x4b, 0xb9, 0x46, 0xde, 0xf8, 0xaf, 0x39, 0x58, 0xda, 0xa4, 0x2d, 0xbb, 0xd5, 0xef, 0xf3, + 0x71, 0xb4, 0x76, 0xee, 0x42, 0xc5, 0xf5, 0x06, 0x5c, 0x51, 0x2c, 0x35, 0x0c, 0x04, 0x48, 0x23, + 0xd7, 0x33, 0xdb, 0x71, 0xa9, 0xe1, 0x34, 0x98, 0x65, 0x84, 0x60, 0xb3, 0xdf, 0x81, 0xf9, 0x31, + 0x77, 0x07, 0xfa, 0x12, 0x21, 0xa1, 0xaa, 0x26, 0xc1, 0x72, 0x75, 0xdc, 0x85, 0xca, 0xc9, 0x84, + 0xf0, 0x04, 0x63, 0xc9, 0x23, 0x0d, 0x80, 0x04, 0xb5, 0x88, 0xbf, 0x8c, 0x27, 0xc1, 0x19, 0xa6, + 0x16, 0x30, 0xb5, 0x28, 0xbe, 0x45, 0xd2, 0x1d, 0x80, 0xc1, 0x24, 0x08, 0xe5, 0x8a, 0x99, 0xc3, + 0xc4, 0xb2, 0x80, 0xd0, 0x8a, 0xf9, 0x06, 0x2c, 0x8e, 0xec, 0x4b, 0x0b, 0x69, 0xc7, 0x72, 0x5c, + 0xeb, 0x64, 0x88, 0x7b, 0x4e, 0x11, 0xf1, 0x1a, 0x23, 0xfb, 0xf2, 0x53, 0x91, 0xd2, 0x71, 0xb7, + 0x11, 0x2e, 0xd8, 0x8a, 0x12, 0x77, 0x7c, 0x1e, 0x70, 0xff, 0x9c, 0x23, 0x27, 0xc8, 0x47, 0x32, + 0x8d, 0x49, 0x50, 0xd1, 0xa2, 0x91, 0xe8, 0x77, 0x38, 0xec, 0xd3, 0xb2, 0x37, 0x8b, 0x23, 0xc7, + 0xdd, 0x09, 0x87, 0x7d, 0xb1, 0xaf, 0x08, 0x3e, 0x32, 0xe6, 0xbe, 0xf5, 0xe2, 0x02, 0xd7, 0x70, + 0x1e, 0xf9, 0xc6, 0x21, 0xf7, 0x9f, 0x5d, 0x88, 0xad, 0xbf, 0x1f, 0x20, 0x23, 0xb2, 0xaf, 0x9a, + 0x15, 0x5c, 0xe0, 0xa5, 0x7e, 0x20, 0x58, 0x90, 0x7d, 0x25, 0x16, 0xa1, 0x68, 0xad, 0x8d, 0xb3, + 0xc0, 0x07, 0x58, 0x7c, 0x80, 0x1c, 0xb5, 0x86, 0x8d, 0x6d, 0xc9, 0x04, 0x51, 0x4f, 0x20, 0xa8, + 0x5e, 0x35, 0xf6, 0x64, 0x68, 0x9f, 0x06, 0xc8, 0x52, 0x6a, 0x66, 0x55, 0x02, 0xb7, 0x05, 0xcc, + 0xf8, 0x8c, 0x84, 0x2c, 0x6d, 0x6e, 0xe5, 0x9a, 0x11, 0x5b, 0x3d, 0x42, 0x70, 0x5e, 0x4b, 0xa6, + 0xfc, 0x4a, 0x9b, 0xb4, 0x6c, 0xca, 0xa4, 0x19, 0xbf, 0x97, 0x81, 0xaa, 0x2c, 0x19, 0x85, 0x12, + 0xb6, 0x0e, 0x4c, 0xcd, 0x62, 0x78, 0xe9, 0x0c, 0xac, 0xe3, 0xab, 0x90, 0x07, 0x44, 0x34, 0x3b, + 0x37, 0xcc, 0x86, 0x4c, 0xeb, 0x5d, 0x3a, 0x83, 0x0d, 0x91, 0xc2, 0x1e, 0x40, 0x23, 0x81, 0x1f, + 0x84, 0x3e, 0x51, 0xf4, 0xce, 0x0d, 0xb3, 0xae, 0x61, 0x77, 0x43, 0x5f, 0xac, 0x11, 0x21, 0xf2, + 0x4c, 0x42, 0xcb, 0x71, 0x07, 0xfc, 0x12, 0xc9, 0xa8, 0x66, 0x56, 0x08, 0xd6, 0x11, 0xa0, 0x8d, + 0x3a, 0x54, 0xf5, 0xe2, 0x8c, 0x53, 0x28, 0x29, 0x79, 0x09, 0x05, 0x86, 0xa9, 0x26, 0x99, 0xe5, + 0x30, 0x6a, 0xc9, 0x4d, 0x28, 0x25, 0x5b, 0x60, 0x16, 0xc3, 0xd7, 0xae, 0xd8, 0xf8, 0x1e, 0x34, + 0x76, 0x05, 0xf1, 0xb8, 0x82, 0x58, 0xa5, 0xfc, 0xb7, 0x02, 0x73, 0xda, 0xa2, 0x29, 0x9b, 0xf2, + 0x4b, 0xec, 0xb9, 0x67, 0x5e, 0x10, 0xca, 0x5a, 0xf0, 0xb7, 0xf1, 0xc7, 0x19, 0x60, 0xed, 0x20, + 0x74, 0x46, 0x76, 0xc8, 0xb7, 0x79, 0xc4, 0x16, 0x0e, 0xa0, 0x2a, 0x4a, 0xeb, 0x79, 0x2d, 0x12, + 0xc8, 0x48, 0xa0, 0x78, 0x5f, 0x2e, 0xe3, 0xd9, 0x0c, 0xeb, 0x3a, 0x36, 0xb1, 0xf9, 0x44, 0x01, + 0x62, 0x95, 0x85, 0xb6, 0x7f, 0xca, 0x43, 0x14, 0xe3, 0xa4, 0xbc, 0x0f, 0x04, 0x12, 0x02, 0xdc, + 0xda, 0x2f, 0xc3, 0xc2, 0x4c, 0x19, 0x3a, 0x5f, 0x2e, 0xa7, 0xf0, 0xe5, 0x9c, 0xce, 0x97, 0x2d, + 0x58, 0x4c, 0xb4, 0x4b, 0x52, 0xda, 0x2a, 0x14, 0xc5, 0x82, 0x10, 0xc2, 0x41, 0x86, 0xa4, 0xca, + 0x13, 0xce, 0x85, 0x18, 0xfc, 0x10, 0x96, 0x4e, 0x38, 0xf7, 0xed, 0x10, 0x13, 0x71, 0xc5, 0x88, + 0x19, 0x92, 0x05, 0x2f, 0xc8, 0xb4, 0xae, 0x1d, 0x1e, 0x72, 0x5f, 0xcc, 0x94, 0xf1, 0xdf, 0x33, + 0x30, 0x2f, 0x38, 0xe8, 0x9e, 0xed, 0x5e, 0xa9, 0x71, 0xda, 0x4d, 0x1d, 0xa7, 0xfb, 0xda, 0x66, + 0xa8, 0x61, 0x7f, 0xd9, 0x41, 0xca, 0x4d, 0x0f, 0x12, 0xbb, 0x07, 0xd5, 0x44, 0x5b, 0x0b, 0xd8, + 0x56, 0x08, 0xa2, 0x46, 0xfe, 0xfc, 0xc3, 0xf8, 0x0e, 0x34, 0xe2, 0x66, 0xcb, 0x31, 0x64, 0x90, + 0x17, 0x24, 0x29, 0x0b, 0xc0, 0xdf, 0xc6, 0x3f, 0xc9, 0x10, 0xe2, 0xa6, 0xe7, 0x44, 0xd2, 0xa9, + 0x40, 0x14, 0x72, 0xaf, 0x42, 0x14, 0xbf, 0xaf, 0x95, 0xea, 0x7f, 0xfe, 0xce, 0x8a, 0xa5, 0x13, + 0x70, 0x77, 0x60, 0xd9, 0xc3, 0x21, 0x32, 0xdf, 0x92, 0x59, 0x14, 0xdf, 0xad, 0xe1, 0xd0, 0x78, + 0x17, 0x16, 0xb4, 0xd6, 0xbd, 0xa4, 0x1f, 0xfb, 0xc0, 0x76, 0x9d, 0x20, 0x3c, 0x72, 0x83, 0xb1, + 0x26, 0xb8, 0xdd, 0x82, 0xb2, 0xe0, 0xb0, 0xa2, 0x65, 0xb4, 0x64, 0x0b, 0xa6, 0x60, 0xb9, 0xa2, + 0x5d, 0x01, 0x26, 0xda, 0x97, 0x32, 0x31, 0x2b, 0x13, 0xed, 0x4b, 0x4c, 0x34, 0xbe, 0x03, 0x8b, + 0x89, 0xf2, 0x64, 0xd5, 0x6f, 0x42, 0x61, 0x12, 0x5e, 0x7a, 0x4a, 0x34, 0xaf, 0x48, 0x0a, 0x11, + 0x0a, 0xa0, 0x49, 0x29, 0xc6, 0xc7, 0xb0, 0xb0, 0xcf, 0x2f, 0xe4, 0x22, 0x56, 0x0d, 0x79, 0x07, + 0xf2, 0xaf, 0x50, 0x0a, 0x31, 0xdd, 0x58, 0x07, 0xa6, 0x67, 0x96, 0xb5, 0x6a, 0x3a, 0x62, 0x26, + 0xa1, 0x23, 0x1a, 0xef, 0x00, 0xeb, 0x3a, 0xa7, 0xee, 0x1e, 0x0f, 0x02, 0xfb, 0x34, 0x5a, 0xf6, + 0x0d, 0xc8, 0x8d, 0x82, 0x53, 0xc9, 0xa3, 0xc4, 0x4f, 0xe3, 0x9b, 0xb0, 0x98, 0xc0, 0x93, 0x05, + 0xdf, 0x86, 0x72, 0xe0, 0x9c, 0xba, 0x28, 0x58, 0xc9, 0xa2, 0x63, 0x80, 0xb1, 0x0d, 0x4b, 0x9f, + 0x72, 0xdf, 0x39, 0xb9, 0x7a, 0x55, 0xf1, 0xc9, 0x72, 0xb2, 0xd3, 0xe5, 0xb4, 0x61, 0x79, 0xaa, + 0x1c, 0x59, 0x3d, 0x91, 0xaf, 0x9c, 0xc9, 0x92, 0x49, 0x1f, 0x1a, 0xdf, 0xcb, 0xea, 0x7c, 0xcf, + 0x38, 0x02, 0xb6, 0xe9, 0xb9, 0x2e, 0xef, 0x87, 0x87, 0x9c, 0xfb, 0xf1, 0x29, 0x55, 0x4c, 0xab, + 0x95, 0xc7, 0xab, 0x72, 0x64, 0xa7, 0x99, 0xa9, 0x24, 0x62, 0x06, 0xf9, 0x31, 0xf7, 0x47, 0x58, + 0x70, 0xc9, 0xc4, 0xdf, 0xc6, 0x32, 0x2c, 0x26, 0x8a, 0x95, 0x7a, 0xfd, 0x23, 0x58, 0xde, 0x72, + 0x82, 0xfe, 0x6c, 0x85, 0xab, 0x50, 0x1c, 0x4f, 0x8e, 0xad, 0x24, 0x5f, 0x7e, 0xc6, 0xaf, 0x84, + 0xb6, 0x37, 0x9d, 0x43, 0x96, 0xf5, 0xd7, 0x33, 0x90, 0xdf, 0xe9, 0xed, 0x6e, 0xb2, 0x35, 0x28, + 0x39, 0x6e, 0xdf, 0x1b, 0x09, 0xc1, 0x8b, 0xfa, 0x1c, 0x7d, 0x5f, 0xbb, 0xc0, 0x6e, 0x41, 0x19, + 0xe5, 0x35, 0xa1, 0xda, 0x4a, 0xd1, 0xa7, 0x24, 0x00, 0xbb, 0x5e, 0xff, 0x85, 0xd0, 0xa9, 0xf9, + 0xe5, 0xd8, 0xf1, 0x51, 0x6b, 0x56, 0xca, 0x70, 0x9e, 0xf6, 0xfa, 0x38, 0x81, 0x34, 0x62, 0xe3, + 0xdf, 0x96, 0xa0, 0x28, 0x77, 0x5b, 0xda, 0xb9, 0x43, 0xe7, 0x9c, 0xc7, 0x3b, 0xb7, 0xf8, 0x12, + 0xf2, 0x80, 0xcf, 0x47, 0x5e, 0x18, 0x09, 0x6c, 0x34, 0x07, 0x55, 0x02, 0x4a, 0x91, 0x4d, 0x13, + 0x1a, 0xe8, 0x88, 0x21, 0x47, 0x48, 0x7d, 0x7d, 0x2b, 0xbf, 0x05, 0x45, 0xb5, 0xf7, 0xe7, 0x23, + 0x9d, 0x66, 0xae, 0x4f, 0xd2, 0xda, 0x1a, 0x94, 0xfa, 0xf6, 0xd8, 0xee, 0x3b, 0xe1, 0x95, 0x64, + 0x08, 0xd1, 0xb7, 0x28, 0x7d, 0xe8, 0xf5, 0xed, 0xa1, 0x75, 0x6c, 0x0f, 0x6d, 0xb7, 0xcf, 0xa5, + 0xee, 0x5e, 0x45, 0xe0, 0x06, 0xc1, 0x84, 0x7e, 0x2e, 0xdb, 0xa9, 0xb0, 0x48, 0x85, 0x97, 0xad, + 0x57, 0x68, 0x42, 0xb8, 0xf4, 0x46, 0x23, 0x47, 0x68, 0x19, 0x24, 0x86, 0xe5, 0xcc, 0x32, 0x41, + 0xb6, 0x39, 0xf6, 0x56, 0x26, 0x5f, 0xd0, 0xd0, 0x95, 0xa9, 0x2a, 0x02, 0x7e, 0x46, 0x07, 0x09, + 0xb3, 0xb2, 0x58, 0x4e, 0x93, 0xc5, 0xde, 0x87, 0x85, 0x89, 0x1b, 0xf0, 0x30, 0x1c, 0xf2, 0x41, + 0xd4, 0x96, 0x0a, 0x22, 0x35, 0xa2, 0x04, 0xd5, 0x9c, 0x75, 0x58, 0xa4, 0x43, 0x87, 0xc0, 0x0e, + 0xbd, 0xe0, 0xcc, 0x09, 0xac, 0x40, 0x68, 0x48, 0xa4, 0xee, 0x2e, 0x60, 0x52, 0x57, 0xa6, 0x74, + 0x49, 0x45, 0x5a, 0x9d, 0xc2, 0xf7, 0x79, 0x9f, 0x3b, 0xe7, 0x7c, 0x80, 0x72, 0x5a, 0xce, 0x5c, + 0x4e, 0xe4, 0x31, 0x65, 0x22, 0x0a, 0xdd, 0x93, 0x91, 0x35, 0x19, 0x0f, 0x6c, 0x21, 0xac, 0xd4, + 0x49, 0x18, 0x76, 0x27, 0xa3, 0x23, 0x82, 0xb0, 0x47, 0xa0, 0x24, 0x31, 0x29, 0x1f, 0xce, 0x27, + 0xf8, 0x99, 0x20, 0x56, 0xb3, 0x2a, 0x31, 0x48, 0x50, 0x4c, 0xc8, 0x9c, 0x8d, 0x29, 0x99, 0xb3, + 0x09, 0xc5, 0xb1, 0xef, 0x9c, 0xdb, 0x21, 0x6f, 0x2e, 0x10, 0x03, 0x97, 0x9f, 0x82, 0x33, 0x38, + 0xae, 0x13, 0x3a, 0x76, 0xe8, 0xf9, 0x4d, 0x86, 0x69, 0x31, 0x80, 0x3d, 0x80, 0x05, 0xa4, 0x91, + 0x20, 0xb4, 0xc3, 0x49, 0x20, 0x25, 0xd0, 0x45, 0x24, 0x26, 0x94, 0xa1, 0xbb, 0x08, 0x47, 0x21, + 0x94, 0x7d, 0x13, 0x56, 0x88, 0x2c, 0x30, 0x87, 0x94, 0xac, 0x51, 0x20, 0x58, 0xc2, 0xa1, 0x58, + 0xc4, 0x54, 0x41, 0xdf, 0x52, 0xbe, 0x16, 0xd2, 0xc1, 0x13, 0x58, 0x95, 0x64, 0x32, 0x93, 0x6b, + 0x19, 0x73, 0x2d, 0x51, 0xf2, 0x54, 0xb6, 0x75, 0x58, 0x10, 0x4d, 0x72, 0xfa, 0x96, 0xcc, 0x2d, + 0x56, 0xc2, 0x8a, 0x68, 0x3d, 0x6a, 0x4a, 0xf3, 0x94, 0x68, 0x62, 0xda, 0x33, 0x7e, 0xc5, 0xbe, + 0x07, 0xf3, 0x44, 0x32, 0xa8, 0x5e, 0x21, 0xa7, 0x5f, 0x43, 0x4e, 0xbf, 0xac, 0x4e, 0x38, 0xa3, + 0x54, 0x64, 0xf6, 0xf5, 0x7e, 0xe2, 0x5b, 0x2c, 0x87, 0xa1, 0x73, 0xc2, 0x43, 0x67, 0xc4, 0x9b, + 0xab, 0x44, 0x60, 0xea, 0x5b, 0xac, 0xd4, 0xc9, 0x18, 0x53, 0x9a, 0xc4, 0x17, 0xe8, 0x0b, 0x69, + 0x77, 0xe8, 0x05, 0x5c, 0x1d, 0x51, 0x35, 0x6f, 0xca, 0x45, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, + 0x38, 0x29, 0x3d, 0xd1, 0x41, 0xe2, 0x2d, 0x24, 0x86, 0x1a, 0xe9, 0x3e, 0xea, 0x30, 0x51, 0xec, + 0xe2, 0x67, 0xf6, 0x85, 0xe2, 0x20, 0xb7, 0x71, 0x7e, 0x41, 0x80, 0x24, 0xef, 0xf8, 0x69, 0x86, + 0x36, 0x44, 0xc9, 0x3f, 0x02, 0x4d, 0xbd, 0x23, 0xce, 0x61, 0x79, 0xee, 0xf0, 0x4a, 0x32, 0x13, + 0x20, 0xd0, 0x81, 0x3b, 0xc4, 0xd5, 0xec, 0xb8, 0x3a, 0x0a, 0xf1, 0xde, 0xaa, 0x02, 0x22, 0xd2, + 0x5d, 0xa8, 0x8c, 0x27, 0xc7, 0x43, 0xa7, 0x4f, 0x28, 0x39, 0x2a, 0x85, 0x40, 0x88, 0x20, 0xf4, + 0x5b, 0xa2, 0x28, 0xc2, 0xc8, 0x23, 0x46, 0x45, 0xc2, 0x10, 0x05, 0x79, 0x3b, 0xf7, 0x91, 0x9d, + 0x54, 0x4d, 0xfc, 0x6d, 0x6c, 0xc0, 0x52, 0xb2, 0xd1, 0x72, 0xe3, 0x79, 0x00, 0x25, 0xc9, 0xab, + 0xd4, 0xc1, 0x47, 0x5d, 0x3b, 0x8a, 0x16, 0x2a, 0x5a, 0x94, 0x6e, 0xfc, 0xd6, 0x1c, 0x2c, 0x4a, + 0xe8, 0xa6, 0x18, 0xda, 0xee, 0x64, 0x34, 0xb2, 0xfd, 0x14, 0x26, 0x98, 0x79, 0x39, 0x13, 0xcc, + 0xce, 0x30, 0xc1, 0xa4, 0xe6, 0x4b, 0x3c, 0x34, 0xa9, 0xf9, 0x8a, 0xb9, 0x24, 0x65, 0x44, 0x3f, + 0x07, 0xad, 0x49, 0x70, 0x8f, 0xce, 0x5b, 0x67, 0x58, 0x76, 0x21, 0x85, 0x65, 0xeb, 0x0c, 0x77, + 0x6e, 0x8a, 0xe1, 0xbe, 0x09, 0x44, 0x34, 0x6a, 0xf6, 0x8b, 0xa4, 0x9f, 0x20, 0x4c, 0x1e, 0xa6, + 0xbe, 0x0b, 0xf3, 0xd3, 0x3c, 0x8e, 0x98, 0x69, 0x3d, 0x85, 0xc3, 0x39, 0x23, 0x8e, 0xbb, 0x95, + 0x86, 0x5c, 0x96, 0x1c, 0xce, 0x19, 0xf1, 0x5d, 0x4c, 0x51, 0xf8, 0x6d, 0x00, 0xaa, 0x1b, 0x17, + 0x0d, 0xe0, 0xa2, 0x79, 0x27, 0x39, 0x17, 0xfa, 0xa8, 0xaf, 0x8b, 0x8f, 0x89, 0xcf, 0x71, 0x15, + 0x95, 0x31, 0x27, 0x2e, 0xa0, 0x67, 0x50, 0xf7, 0xc6, 0xdc, 0xb5, 0x62, 0x5e, 0x53, 0xc1, 0xa2, + 0xde, 0x7e, 0x49, 0x51, 0x1d, 0x85, 0x6b, 0xd6, 0x44, 0xde, 0xe8, 0x93, 0xed, 0xd1, 0xc0, 0x73, + 0xad, 0xb4, 0xea, 0x97, 0x28, 0xad, 0x8e, 0x99, 0xa3, 0x6f, 0xe3, 0x6f, 0x65, 0xa0, 0xa2, 0x35, + 0x9b, 0x2d, 0xc3, 0xc2, 0xe6, 0xc1, 0xc1, 0x61, 0xdb, 0x6c, 0xf5, 0x3a, 0x9f, 0xb6, 0xad, 0xcd, + 0xdd, 0x83, 0x6e, 0xbb, 0x71, 0x43, 0x80, 0x77, 0x0f, 0x36, 0x5b, 0xbb, 0xd6, 0xf6, 0x81, 0xb9, + 0xa9, 0xc0, 0x19, 0xb6, 0x02, 0xcc, 0x6c, 0xef, 0x1d, 0xf4, 0xda, 0x09, 0x78, 0x96, 0x35, 0xa0, + 0xba, 0x61, 0xb6, 0x5b, 0x9b, 0x3b, 0x12, 0x92, 0x63, 0x4b, 0xd0, 0xd8, 0x3e, 0xda, 0xdf, 0xea, + 0xec, 0x3f, 0xb5, 0x36, 0x5b, 0xfb, 0x9b, 0xed, 0xdd, 0xf6, 0x56, 0x23, 0xcf, 0x6a, 0x50, 0x6e, + 0x6d, 0xb4, 0xf6, 0xb7, 0x0e, 0xf6, 0xdb, 0x5b, 0x8d, 0x82, 0xf1, 0x5d, 0x28, 0xc7, 0x1d, 0xad, + 0x40, 0xf1, 0x68, 0xff, 0xd9, 0xfe, 0xc1, 0x67, 0xfb, 0x8d, 0x1b, 0xac, 0x0c, 0x05, 0xac, 0xbf, + 0x91, 0x61, 0x00, 0x73, 0x54, 0x67, 0x23, 0xcb, 0x4a, 0x90, 0xdf, 0x38, 0xe8, 0xed, 0x34, 0x72, + 0xc6, 0x9f, 0x67, 0x60, 0x19, 0xbb, 0x3c, 0x98, 0x66, 0x02, 0xf7, 0xa0, 0xd2, 0xf7, 0xbc, 0xb1, + 0xd0, 0xb4, 0x62, 0x89, 0x42, 0x07, 0x89, 0x05, 0x4e, 0xcc, 0xfb, 0xc4, 0xf3, 0xfb, 0x5c, 0xf2, + 0x00, 0x40, 0xd0, 0xb6, 0x80, 0x08, 0x1a, 0x94, 0x44, 0x4c, 0x18, 0xc4, 0x02, 0x2a, 0x04, 0x23, + 0x94, 0x15, 0x98, 0x3b, 0xf6, 0xb9, 0xdd, 0x3f, 0x93, 0xab, 0x5f, 0x7e, 0xb1, 0xf7, 0xe2, 0x33, + 0x80, 0xbe, 0xa0, 0xa9, 0x21, 0x1f, 0xe0, 0x12, 0x28, 0x99, 0xf3, 0x12, 0xbe, 0x29, 0xc1, 0x62, + 0x37, 0xb2, 0x8f, 0x6d, 0x77, 0xe0, 0xb9, 0x7c, 0x20, 0x55, 0x8d, 0x18, 0x60, 0x1c, 0xc2, 0xca, + 0x74, 0xff, 0x24, 0xbf, 0xf8, 0x50, 0xe3, 0x17, 0x24, 0xf9, 0xaf, 0x5d, 0x4f, 0x0a, 0x1a, 0xef, + 0xf8, 0x3b, 0x79, 0xc8, 0x0b, 0x49, 0xf0, 0x5a, 0xa1, 0x51, 0x17, 0xed, 0x73, 0x33, 0xe6, 0x1f, + 0x3c, 0x6a, 0x20, 0x11, 0x81, 0xce, 0xb3, 0xca, 0x08, 0x41, 0xd1, 0x20, 0x4a, 0xf6, 0x79, 0xff, + 0x5c, 0x1e, 0x68, 0x51, 0xb2, 0xc9, 0xfb, 0xe7, 0xa8, 0x53, 0xd9, 0x21, 0xe5, 0xa5, 0xf5, 0x5e, + 0x0c, 0xec, 0x10, 0x73, 0xca, 0x24, 0xcc, 0x57, 0x8c, 0x92, 0x30, 0x57, 0x13, 0x8a, 0x8e, 0x7b, + 0xec, 0x4d, 0xdc, 0x01, 0x2e, 0xef, 0x92, 0xa9, 0x3e, 0xd1, 0xda, 0x84, 0x9c, 0x48, 0x6c, 0x44, + 0xb4, 0x9a, 0x4b, 0x02, 0xd0, 0x13, 0x5b, 0xd1, 0x07, 0x50, 0x0e, 0xae, 0xdc, 0xbe, 0xbe, 0x86, + 0x97, 0xe4, 0xf8, 0x88, 0xde, 0xaf, 0x77, 0xaf, 0xdc, 0x3e, 0xae, 0xd8, 0x52, 0x20, 0x7f, 0xb1, + 0x27, 0x50, 0x8a, 0xce, 0x7d, 0x89, 0x03, 0xdf, 0xd4, 0x73, 0xa8, 0xc3, 0x5e, 0x52, 0xaf, 0x23, + 0x54, 0xf6, 0x10, 0xe6, 0xf0, 0x70, 0x36, 0x68, 0x56, 0x31, 0x93, 0x92, 0xf7, 0x45, 0x33, 0xd0, + 0xd0, 0xc3, 0x07, 0x78, 0x50, 0x6b, 0x4a, 0xb4, 0xb5, 0x67, 0x50, 0x4b, 0x94, 0xa5, 0x2b, 0xd1, + 0x35, 0x52, 0xa2, 0xdf, 0xd6, 0x95, 0xe8, 0x78, 0x27, 0x90, 0xd9, 0x74, 0xa5, 0xfa, 0x97, 0xa1, + 0xa4, 0xba, 0x22, 0xd6, 0x9f, 0x5c, 0x3b, 0x56, 0xf7, 0xf9, 0xfe, 0x66, 0xe3, 0x06, 0x9b, 0x87, + 0x4a, 0x6b, 0x13, 0x97, 0x34, 0x02, 0x32, 0x02, 0xe5, 0xb0, 0xd5, 0xed, 0x46, 0x90, 0xac, 0xb1, + 0x0d, 0x8d, 0xe9, 0x96, 0x0a, 0x9a, 0x0c, 0x15, 0x4c, 0x1e, 0x5d, 0xc7, 0x00, 0xa1, 0x22, 0xd1, + 0x69, 0x34, 0xc9, 0xe1, 0xf4, 0x61, 0x3c, 0x81, 0x86, 0xd8, 0xd7, 0xc4, 0x50, 0x05, 0xda, 0x11, + 0xf0, 0x50, 0xc8, 0x76, 0xfa, 0xf1, 0x75, 0xc9, 0xac, 0x10, 0x0c, 0xab, 0x32, 0x3e, 0x84, 0x05, + 0x2d, 0x5b, 0xac, 0xd2, 0x8a, 0xbd, 0x72, 0x5a, 0xa5, 0x45, 0x05, 0x86, 0x52, 0x8c, 0x55, 0x58, + 0x16, 0x9f, 0xed, 0x73, 0xee, 0x86, 0xdd, 0xc9, 0x31, 0xd9, 0x1c, 0x1d, 0xcf, 0x15, 0x8a, 0x4d, + 0x39, 0x4a, 0xb9, 0x9e, 0xc8, 0xd7, 0xa5, 0xf6, 0x9b, 0x45, 0xd2, 0x58, 0xd3, 0x6a, 0xc0, 0x8c, + 0xeb, 0xf8, 0x37, 0xa1, 0x05, 0x97, 0x23, 0x90, 0x18, 0xd6, 0xc3, 0x76, 0xdb, 0xb4, 0x0e, 0xf6, + 0x77, 0x3b, 0xfb, 0x82, 0x51, 0x8a, 0x61, 0x45, 0xc0, 0xf6, 0x36, 0x42, 0x32, 0x46, 0x03, 0xea, + 0x4f, 0x79, 0xd8, 0x71, 0x4f, 0x3c, 0x65, 0x5f, 0xfb, 0x8b, 0x02, 0xcc, 0x47, 0xa0, 0x58, 0x8b, + 0x3e, 0xe7, 0x7e, 0xe0, 0x78, 0x2e, 0x0a, 0xc4, 0x65, 0x53, 0x7d, 0x8a, 0xdd, 0xcd, 0x19, 0x70, + 0x37, 0x74, 0xc2, 0x2b, 0x2b, 0x71, 0xe4, 0x56, 0x57, 0x60, 0xb9, 0x8b, 0x2e, 0x41, 0xc1, 0x1e, + 0x3a, 0xb6, 0x32, 0xd5, 0xd2, 0x87, 0x80, 0xf6, 0xbd, 0xa1, 0xe7, 0xa3, 0xec, 0x5b, 0x36, 0xe9, + 0x83, 0x3d, 0x82, 0x25, 0x21, 0x83, 0xeb, 0xe7, 0xa0, 0xc8, 0x3f, 0xe8, 0xf4, 0x8f, 0xb9, 0x93, + 0xd1, 0x61, 0x7c, 0x16, 0x2a, 0x52, 0xc4, 0xde, 0x29, 0x72, 0x48, 0x61, 0x29, 0xca, 0x40, 0xea, + 0xdc, 0x82, 0x3b, 0x19, 0xb5, 0x30, 0x25, 0xc2, 0x7f, 0x0c, 0xcb, 0x02, 0x3f, 0x12, 0xaf, 0xa2, + 0x1c, 0xf3, 0x98, 0x43, 0x14, 0xd6, 0x91, 0x69, 0x51, 0x9e, 0x5b, 0x50, 0xa6, 0x56, 0x89, 0x19, + 0x2f, 0x90, 0x18, 0x8f, 0x4d, 0xe1, 0x7e, 0x30, 0x63, 0x55, 0x9d, 0x23, 0x41, 0x60, 0xca, 0xaa, + 0xaa, 0xd9, 0x65, 0x4b, 0xd3, 0x76, 0xd9, 0xc7, 0xb0, 0x7c, 0x2c, 0x48, 0xf0, 0x8c, 0xdb, 0x03, + 0xee, 0x5b, 0x31, 0x61, 0x93, 0xba, 0xb2, 0x28, 0x12, 0x77, 0x30, 0x2d, 0x5a, 0x07, 0x42, 0xce, + 0x11, 0x6c, 0x81, 0x0f, 0xac, 0xd0, 0xb3, 0x50, 0xfc, 0x41, 0x06, 0x53, 0x32, 0x6b, 0x04, 0xee, + 0x79, 0x9b, 0x02, 0x98, 0xc4, 0x3b, 0xf5, 0xed, 0xf1, 0x99, 0x54, 0x28, 0x22, 0xbc, 0xa7, 0x02, + 0xc8, 0x6e, 0x43, 0x51, 0x90, 0xbc, 0xcb, 0xc9, 0xf8, 0x45, 0x22, 0xbb, 0x02, 0xb1, 0xb7, 0x61, + 0x0e, 0xeb, 0x08, 0x9a, 0x0d, 0xa4, 0xf7, 0x6a, 0xcc, 0xc8, 0x1d, 0xd7, 0x94, 0x69, 0x42, 0x98, + 0x9c, 0xf8, 0x0e, 0x71, 0x99, 0xb2, 0x89, 0xbf, 0xd9, 0xf7, 0x35, 0x96, 0xb5, 0x88, 0x79, 0x95, + 0x3c, 0x30, 0x45, 0x69, 0xd7, 0x71, 0xaf, 0xaf, 0x94, 0x19, 0xfd, 0x20, 0x5f, 0xaa, 0x34, 0xaa, + 0xc6, 0xb7, 0xa1, 0x40, 0xa3, 0x23, 0x88, 0x10, 0xc7, 0x2e, 0x23, 0x89, 0x10, 0xa1, 0x4d, 0x28, + 0xba, 0x3c, 0xbc, 0xf0, 0xfc, 0x17, 0xea, 0x50, 0x5a, 0x7e, 0x1a, 0x3f, 0xc6, 0xd3, 0x94, 0xc8, + 0xe2, 0x4e, 0x8a, 0xa1, 0x20, 0x0f, 0x9a, 0xde, 0xe0, 0xcc, 0x96, 0x07, 0x3c, 0x25, 0x04, 0x74, + 0xcf, 0xec, 0x19, 0xf2, 0xc8, 0xce, 0x1a, 0xdd, 0xdf, 0x86, 0xba, 0xb2, 0xf1, 0x07, 0xd6, 0x90, + 0x9f, 0x84, 0x92, 0xdc, 0xab, 0xd2, 0xc0, 0x1f, 0xec, 0xf2, 0x93, 0xd0, 0xd8, 0x83, 0x05, 0x49, + 0x90, 0x07, 0x63, 0xae, 0xaa, 0xfe, 0x4e, 0x9a, 0x3c, 0x5d, 0x79, 0xbc, 0x98, 0xdc, 0x68, 0xc9, + 0x77, 0x21, 0x21, 0x64, 0x1b, 0x9f, 0x00, 0xd3, 0xb7, 0x61, 0x59, 0x9e, 0x94, 0x6a, 0xd5, 0x59, + 0xbe, 0x32, 0x89, 0x45, 0xb2, 0xb3, 0x33, 0x10, 0xa3, 0x13, 0x4c, 0xfa, 0x7d, 0xe5, 0x7b, 0x51, + 0x32, 0xd5, 0xa7, 0xf1, 0x27, 0x19, 0x58, 0xc4, 0xc2, 0x94, 0x3e, 0x20, 0x99, 0xec, 0xcf, 0xdc, + 0x48, 0x31, 0x3f, 0xba, 0xec, 0x43, 0x1f, 0x5f, 0xfe, 0xf4, 0x34, 0x3f, 0x73, 0x7a, 0xfa, 0x1e, + 0x34, 0x06, 0x7c, 0xe8, 0xa0, 0x1b, 0x8e, 0x12, 0x25, 0x48, 0x03, 0x98, 0x57, 0x70, 0xa9, 0x0d, + 0x1a, 0xff, 0x30, 0x03, 0x0b, 0x24, 0xa9, 0xa0, 0x5e, 0x2d, 0x07, 0xea, 0x63, 0xa5, 0x48, 0x4a, + 0x56, 0x25, 0xfb, 0x14, 0xef, 0xe0, 0x08, 0x25, 0xe4, 0x9d, 0x1b, 0x52, 0xc1, 0x94, 0x50, 0xf6, + 0x11, 0xea, 0x30, 0xae, 0x85, 0xc0, 0x14, 0xb7, 0x9e, 0xe4, 0xa4, 0xec, 0xdc, 0x40, 0x05, 0xc7, + 0x45, 0xd0, 0x46, 0x49, 0x68, 0xb6, 0x02, 0x6c, 0x6c, 0x43, 0x2d, 0x51, 0x4d, 0xe2, 0x88, 0xb7, + 0x4a, 0x47, 0xbc, 0x33, 0x66, 0x94, 0xec, 0xac, 0x19, 0xe5, 0x0a, 0x16, 0x4d, 0x6e, 0x0f, 0xae, + 0xb6, 0x3d, 0xff, 0x30, 0x38, 0x0e, 0xb7, 0x49, 0xfc, 0x13, 0xfc, 0x3d, 0xb2, 0x0d, 0x26, 0xce, + 0x51, 0x95, 0x89, 0x48, 0xa9, 0xcb, 0x5f, 0x83, 0x7a, 0x6c, 0x44, 0xd4, 0xce, 0xe2, 0x6a, 0x91, + 0x1d, 0x11, 0x8f, 0xe4, 0x84, 0xaa, 0x19, 0x1c, 0x87, 0xf2, 0x34, 0x0e, 0x7f, 0x1b, 0x7f, 0x23, + 0x0f, 0x4c, 0x50, 0xf3, 0x14, 0xc1, 0x4c, 0x99, 0x3f, 0xb3, 0x33, 0xe6, 0xcf, 0x47, 0xc0, 0x34, + 0x04, 0x65, 0x95, 0xcd, 0x45, 0x56, 0xd9, 0x46, 0x8c, 0x2b, 0x8d, 0xb2, 0x8f, 0x60, 0x49, 0xca, + 0xd2, 0xc9, 0xa6, 0x12, 0x69, 0x30, 0x12, 0xaa, 0x13, 0xed, 0x55, 0xa6, 0x4f, 0xa1, 0xfe, 0xd3, + 0x69, 0x1b, 0x9a, 0x3e, 0x95, 0xe2, 0xaf, 0x11, 0xe0, 0xdc, 0x2b, 0x09, 0xb0, 0x38, 0x43, 0x80, + 0xda, 0xe1, 0x4f, 0x29, 0x79, 0xf8, 0x63, 0x40, 0x4d, 0x19, 0x38, 0xc9, 0xaf, 0x83, 0x04, 0xc7, + 0x8a, 0xb4, 0x72, 0xa2, 0x6f, 0xc7, 0x7d, 0x68, 0xa8, 0x13, 0x9a, 0xe8, 0x78, 0x89, 0x7c, 0x16, + 0xe4, 0x01, 0xdf, 0xa6, 0x3a, 0x64, 0x4a, 0x1c, 0xe6, 0x57, 0xa6, 0x0e, 0xf3, 0xdf, 0x87, 0x85, + 0x40, 0xd0, 0xaf, 0x35, 0x71, 0xa5, 0x83, 0x11, 0x1f, 0xa0, 0xd6, 0x56, 0x32, 0x1b, 0x98, 0x70, + 0x14, 0xc3, 0x67, 0x8f, 0x4e, 0x6a, 0x29, 0x47, 0x27, 0x4f, 0x62, 0x5b, 0x60, 0x70, 0xe6, 0x8c, + 0x50, 0x66, 0x88, 0x9d, 0x71, 0xe4, 0x00, 0x77, 0xcf, 0x9c, 0x91, 0xa9, 0x0c, 0xcf, 0xe2, 0xc3, + 0xf8, 0xbf, 0x19, 0x68, 0x08, 0x3a, 0x48, 0x2c, 0xb1, 0xef, 0x02, 0x32, 0x83, 0xd7, 0x5c, 0x61, + 0x15, 0x81, 0xab, 0x16, 0xd8, 0xb7, 0x01, 0x57, 0x8c, 0x25, 0x54, 0x54, 0xb9, 0xbe, 0x9a, 0xc9, + 0xf5, 0x15, 0xf3, 0xd0, 0x9d, 0x1b, 0xa4, 0x7b, 0x08, 0x08, 0xfb, 0x2e, 0x94, 0x05, 0x61, 0x22, + 0x95, 0x48, 0x1f, 0x30, 0x25, 0x79, 0xa5, 0xac, 0x11, 0x91, 0x75, 0x2c, 0x3f, 0xd3, 0xcc, 0xb7, + 0xf9, 0x14, 0xf3, 0xad, 0xb6, 0x80, 0x77, 0x00, 0x9e, 0xf1, 0xab, 0x5d, 0xaf, 0x8f, 0x7a, 0xe5, + 0x1d, 0x00, 0x41, 0xcb, 0x27, 0xf6, 0xc8, 0x91, 0x67, 0x42, 0x05, 0xb3, 0xfc, 0x82, 0x5f, 0x6d, + 0x23, 0x40, 0x4c, 0xa4, 0x48, 0x8e, 0x57, 0x71, 0xc1, 0x2c, 0xbd, 0xe0, 0x57, 0xb4, 0x84, 0x2d, + 0xa8, 0x3d, 0xe3, 0x57, 0x5b, 0x9c, 0x84, 0x4c, 0xcf, 0x17, 0x44, 0xe4, 0xdb, 0x17, 0x42, 0xaa, + 0x4c, 0x98, 0x5e, 0x2b, 0xbe, 0x7d, 0xf1, 0x8c, 0x5f, 0x29, 0x33, 0x70, 0x51, 0xa4, 0x0f, 0xbd, + 0xbe, 0xdc, 0x37, 0x95, 0x13, 0x49, 0xdc, 0x28, 0x73, 0xee, 0x05, 0xfe, 0x36, 0xfe, 0x32, 0x03, + 0x35, 0xd1, 0x7e, 0x64, 0xcb, 0x62, 0xca, 0x94, 0x2f, 0x52, 0x26, 0xf6, 0x45, 0x7a, 0x2c, 0xb9, + 0x1a, 0xf1, 0xf8, 0xec, 0xf5, 0x3c, 0x1e, 0xe7, 0x86, 0x18, 0xfc, 0x07, 0x50, 0xa6, 0x65, 0x29, 0xd6, 0x79, 0x2e, 0x31, 0xc1, 0x89, 0x0e, 0x99, 0x25, 0x44, 0x7b, 0x46, 0xae, 0x0f, 0xda, 0xf9, - 0x22, 0x0d, 0x71, 0xd9, 0x8f, 0x4e, 0x15, 0x53, 0xa6, 0xa1, 0x70, 0x83, 0xeb, 0x83, 0x7e, 0x78, - 0xb7, 0x30, 0x77, 0x78, 0x77, 0x08, 0x25, 0x31, 0xd5, 0xd8, 0xd9, 0x94, 0x42, 0x33, 0x69, 0x85, - 0x0a, 0x49, 0xc0, 0x16, 0x9b, 0x82, 0x60, 0x74, 0x59, 0x29, 0x09, 0xd8, 0x01, 0x3f, 0x42, 0x66, + 0x22, 0x0d, 0x71, 0xd9, 0x8f, 0x4e, 0x15, 0x53, 0xa6, 0xa1, 0x70, 0x8d, 0xeb, 0x83, 0x7e, 0x78, + 0x37, 0x37, 0x73, 0x78, 0x77, 0x00, 0x25, 0x31, 0xd5, 0xd8, 0xd9, 0x94, 0x42, 0x33, 0x69, 0x85, + 0x0a, 0x49, 0xc0, 0x16, 0x9b, 0x82, 0x60, 0x74, 0x59, 0x29, 0x09, 0xd8, 0x01, 0x3f, 0x44, 0x66, 0x97, 0x81, 0x8a, 0xb6, 0x02, 0xf0, 0xfc, 0x33, 0x1a, 0x2f, 0x5a, 0x2e, 0x49, 0x12, 0x4f, 0x0c, - 0xf8, 0xde, 0x2d, 0xb3, 0x36, 0x48, 0xcc, 0xc0, 0xa6, 0xa4, 0x55, 0xcc, 0x99, 0x4d, 0xb8, 0x4d, - 0xa9, 0x86, 0x2b, 0x02, 0x15, 0xbf, 0xb7, 0x16, 0x20, 0x2f, 0x50, 0x8d, 0x8f, 0x60, 0x49, 0x6b, - 0x06, 0xa9, 0xf9, 0xaf, 0xda, 0x43, 0xe3, 0xd7, 0xa2, 0xcc, 0xa2, 0x0e, 0xb2, 0x50, 0x29, 0x37, - 0x12, 0x3e, 0xa4, 0x8e, 0x4b, 0x77, 0x15, 0x02, 0x09, 0xb4, 0x57, 0x76, 0x6d, 0xf8, 0x0d, 0x58, - 0xd6, 0x4a, 0xdf, 0x75, 0x5c, 0x7b, 0xe4, 0xfc, 0x08, 0x37, 0xfc, 0xc0, 0x39, 0x73, 0x67, 0xca, - 0x27, 0xd0, 0x97, 0x2a, 0xff, 0x9f, 0x66, 0x61, 0x45, 0x56, 0x80, 0x8e, 0x81, 0x8e, 0x90, 0xe2, - 0x0e, 0x82, 0x33, 0xf6, 0x1d, 0xa8, 0x89, 0xb1, 0xb1, 0x7c, 0x7e, 0xe6, 0x04, 0x21, 0x57, 0x96, - 0xb1, 0x14, 0xc6, 0x25, 0x36, 0x73, 0x81, 0x6a, 0x4a, 0x4c, 0xf6, 0x11, 0x54, 0x30, 0x2b, 0x1d, - 0xa3, 0xc8, 0x89, 0x68, 0xce, 0x67, 0xa4, 0x81, 0xde, 0xbb, 0x65, 0x42, 0x10, 0x0f, 0xfb, 0x47, - 0x50, 0xc1, 0x39, 0xbc, 0xc0, 0x81, 0x9c, 0x61, 0x55, 0x73, 0x03, 0x2d, 0x32, 0x4f, 0xe2, 0x61, - 0x6f, 0x41, 0x8d, 0x98, 0x95, 0x1c, 0x27, 0xe9, 0x70, 0xb4, 0x31, 0x9f, 0x5d, 0x8d, 0xa4, 0x68, - 0xfc, 0x44, 0xfb, 0xde, 0x2a, 0x43, 0x31, 0xf4, 0x9d, 0xb3, 0x33, 0xee, 0x1b, 0x6b, 0xd1, 0xd0, - 0x08, 0x2e, 0xcc, 0x7b, 0x21, 0x9f, 0x08, 0xd9, 0xdc, 0xf8, 0x4f, 0x19, 0xa8, 0x48, 0xbe, 0xfa, - 0x53, 0x9b, 0xe3, 0x36, 0x34, 0xcf, 0x5a, 0x3a, 0xb1, 0x89, 0x1d, 0x69, 0xdf, 0x86, 0xc5, 0xb1, - 0x90, 0xd3, 0x85, 0x1e, 0x99, 0xb0, 0xc5, 0xd5, 0x15, 0x58, 0x8a, 0xc9, 0x9b, 0xb0, 0x8c, 0x52, - 0x73, 0x60, 0x85, 0xce, 0xc8, 0x52, 0x89, 0xd2, 0x8b, 0x75, 0x89, 0x92, 0xfa, 0xce, 0xe8, 0x40, - 0x26, 0x08, 0xe1, 0x31, 0x08, 0xed, 0x33, 0x2e, 0xd7, 0x36, 0x7d, 0x18, 0x4d, 0x58, 0x9b, 0x51, - 0x21, 0x95, 0xfa, 0xfb, 0x07, 0x4b, 0xb0, 0x3e, 0x97, 0x24, 0xd5, 0xe0, 0xc8, 0x06, 0x35, 0x72, - 0xc6, 0x27, 0x5e, 0x74, 0x42, 0x9b, 0xd1, 0x6c, 0x50, 0xfb, 0x22, 0x45, 0x9d, 0xd0, 0x72, 0x58, - 0x55, 0x04, 0x89, 0x47, 0xac, 0x91, 0x96, 0x99, 0x45, 0x1d, 0xe8, 0xbd, 0xe4, 0x26, 0x36, 0x5b, - 0x9d, 0x82, 0xeb, 0xa2, 0xd1, 0xf2, 0x64, 0x0e, 0x16, 0xb0, 0xdf, 0x84, 0x66, 0x44, 0xf7, 0x52, - 0x6c, 0xd7, 0x54, 0x66, 0x51, 0xd3, 0xd7, 0x5e, 0x52, 0x53, 0xe2, 0xec, 0x0e, 0x65, 0xa7, 0x35, - 0xb5, 0x64, 0xa8, 0xc0, 0xa8, 0xae, 0x0b, 0x78, 0x5d, 0xd5, 0x85, 0x62, 0xf8, 0x7c, 0x8d, 0xf9, - 0x57, 0xea, 0x1b, 0x9e, 0x4b, 0x26, 0xaa, 0x35, 0xef, 0xc8, 0x82, 0xa3, 0x24, 0xbd, 0xde, 0x73, - 0x58, 0xbb, 0xb4, 0x9d, 0x50, 0xf5, 0x51, 0xd3, 0xd8, 0x0b, 0x58, 0xdf, 0x93, 0x97, 0xd4, 0xf7, - 0x29, 0x65, 0x4e, 0x28, 0x26, 0x2b, 0x97, 0xf3, 0xc0, 0x60, 0xe3, 0x4f, 0xb3, 0x50, 0x4f, 0x96, - 0x22, 0x18, 0x8b, 0xdc, 0x6c, 0x94, 0xbc, 0x29, 0x85, 0x60, 0x69, 0x3d, 0xe8, 0x92, 0x9c, 0x39, - 0x6f, 0xd7, 0xc8, 0xa6, 0xd8, 0x35, 0x74, 0x73, 0x42, 0xee, 0x65, 0xf6, 0xdb, 0xfc, 0x2b, 0xd9, - 0x6f, 0x0b, 0x69, 0xf6, 0xdb, 0x9b, 0x8d, 0x7e, 0x0b, 0x3f, 0x95, 0xd1, 0xaf, 0xf8, 0x02, 0xa3, - 0x5f, 0xc2, 0x54, 0x59, 0x9a, 0x31, 0x55, 0x6e, 0xfc, 0x75, 0x06, 0xd8, 0x3c, 0x2d, 0xb3, 0xa7, - 0x64, 0xe0, 0x71, 0xf9, 0x48, 0xf2, 0xd9, 0xaf, 0xbf, 0xda, 0x7a, 0x50, 0xd3, 0xa7, 0x72, 0xb3, - 0x47, 0xb0, 0xac, 0x7b, 0xc6, 0xeb, 0x3a, 0x76, 0xcd, 0x64, 0x7a, 0x52, 0x7c, 0x12, 0xa3, 0x99, - 0xb6, 0xf3, 0x2f, 0x35, 0x6d, 0x17, 0x5e, 0x6a, 0xda, 0x5e, 0x48, 0x9a, 0xb6, 0x37, 0xfe, 0x4b, - 0x06, 0x96, 0x53, 0x48, 0xee, 0xe7, 0xd7, 0x67, 0x41, 0x29, 0x09, 0x26, 0x94, 0x95, 0x94, 0xa2, - 0xf3, 0x9f, 0x7d, 0xa8, 0xc4, 0xd6, 0x52, 0x15, 0x39, 0xf2, 0xf0, 0x65, 0xbc, 0x20, 0xce, 0x61, - 0xea, 0xd9, 0x37, 0x7e, 0x3f, 0x0b, 0x15, 0x2d, 0x51, 0x8c, 0x22, 0x11, 0x98, 0xe6, 0x51, 0x44, - 0x72, 0x1c, 0x9e, 0x10, 0xdc, 0x03, 0x69, 0x82, 0xa0, 0x74, 0x5a, 0x0a, 0x52, 0x68, 0x43, 0x84, - 0x4d, 0x58, 0x56, 0xc6, 0x37, 0x1e, 0x3b, 0x0e, 0xca, 0x9d, 0x61, 0x49, 0x9a, 0xe0, 0x78, 0xe4, - 0x87, 0xc8, 0x1e, 0x29, 0xe5, 0x2d, 0x9e, 0x3b, 0x24, 0x4c, 0x3a, 0xdf, 0x5f, 0x22, 0x72, 0x56, - 0x93, 0x28, 0xa8, 0xf2, 0x3d, 0x58, 0x55, 0xc4, 0x9c, 0xcc, 0x41, 0x47, 0xfe, 0x4c, 0x92, 0xb2, - 0x9e, 0xe5, 0x7b, 0x70, 0x77, 0xa6, 0x4d, 0x33, 0x59, 0xc9, 0xc3, 0xf5, 0x76, 0xa2, 0x75, 0x7a, - 0x09, 0x1b, 0x3f, 0x86, 0x5a, 0x82, 0xad, 0xfd, 0xfc, 0xa6, 0x7c, 0xf6, 0x54, 0x86, 0x46, 0x54, - 0x3f, 0x95, 0xd9, 0xf8, 0x3f, 0x39, 0x60, 0xf3, 0x9c, 0xf5, 0x17, 0xd9, 0x84, 0x79, 0xc2, 0xcc, - 0xa5, 0x10, 0xe6, 0xff, 0xb7, 0xdd, 0xfe, 0x5d, 0x58, 0x92, 0x11, 0x54, 0x9a, 0x05, 0x95, 0x16, - 0x67, 0x23, 0x4a, 0x50, 0xad, 0xf8, 0xd6, 0xac, 0x27, 0x47, 0x29, 0x11, 0x34, 0xa2, 0x89, 0x3b, - 0x33, 0x0e, 0x1d, 0xc7, 0xb0, 0x60, 0xbb, 0x83, 0x73, 0xcf, 0x47, 0xad, 0xbc, 0xfe, 0xe4, 0x97, - 0xbe, 0xf4, 0x66, 0xb7, 0xd9, 0xc2, 0xfc, 0x28, 0x63, 0x99, 0xb2, 0x30, 0xe3, 0x3d, 0xa8, 0x68, - 0x60, 0xb4, 0x2a, 0x76, 0x0e, 0xb6, 0x0e, 0x1b, 0xb7, 0x58, 0x0d, 0xca, 0x66, 0x7b, 0xfb, 0xf0, - 0x93, 0xb6, 0xd9, 0xde, 0x69, 0x64, 0x58, 0x09, 0xf2, 0xfb, 0x87, 0xbd, 0x7e, 0x23, 0x6b, 0x6c, - 0x40, 0x53, 0x96, 0x38, 0x6f, 0x61, 0xf8, 0x9d, 0x7c, 0x74, 0xb8, 0x87, 0x89, 0x52, 0xa1, 0xfe, - 0x06, 0x54, 0x75, 0x61, 0x44, 0x52, 0xc4, 0x8c, 0x11, 0x5f, 0xa8, 0xd2, 0x9e, 0xc6, 0xab, 0xb7, - 0x81, 0x4c, 0xb3, 0xc3, 0x28, 0x5b, 0x36, 0x21, 0x65, 0xa6, 0xd8, 0xf2, 0x50, 0x55, 0x49, 0x90, - 0xe1, 0xdf, 0x80, 0x7a, 0xf2, 0xb8, 0x5d, 0x72, 0xa4, 0x34, 0xf5, 0x50, 0xe4, 0x4e, 0x9c, 0xbf, - 0xb3, 0xef, 0x41, 0x63, 0xf6, 0xb8, 0x5e, 0x8a, 0xba, 0x37, 0xe4, 0x5f, 0x74, 0x92, 0x27, 0xf8, - 0x6c, 0x0f, 0x56, 0xd2, 0xc4, 0x31, 0xa4, 0x8f, 0x9b, 0x8f, 0x14, 0xd8, 0xbc, 0xc8, 0xc5, 0xbe, - 0x2d, 0xad, 0x32, 0x85, 0x34, 0xdb, 0xb6, 0x36, 0xd8, 0x9b, 0xf4, 0x4f, 0xb3, 0xcf, 0x5c, 0x00, - 0xc4, 0x30, 0xd6, 0x80, 0xea, 0xe1, 0x51, 0xbb, 0x6b, 0x6d, 0xef, 0xb5, 0xba, 0xdd, 0xf6, 0x7e, - 0xe3, 0x16, 0x63, 0x50, 0x47, 0xa3, 0xf4, 0x4e, 0x04, 0xcb, 0x08, 0x98, 0xb4, 0x8e, 0x29, 0x58, - 0x96, 0xad, 0x40, 0xa3, 0xd3, 0x9d, 0x81, 0xe6, 0x58, 0x13, 0x56, 0x8e, 0xda, 0x64, 0xc7, 0x4e, - 0x94, 0x9b, 0x17, 0x22, 0xbe, 0xec, 0xae, 0x10, 0xf1, 0x29, 0x12, 0x50, 0xae, 0x03, 0x25, 0xf9, - 0xfe, 0x6e, 0x06, 0x56, 0x67, 0x12, 0xe2, 0xf8, 0x0e, 0x92, 0x7b, 0x93, 0x12, 0x6f, 0x15, 0x81, - 0x6a, 0x35, 0xbd, 0x0b, 0x4b, 0xd1, 0x31, 0xd1, 0xcc, 0xae, 0xd4, 0x88, 0x12, 0x14, 0xf2, 0x23, - 0x58, 0xd6, 0x4e, 0x9b, 0x66, 0x78, 0x05, 0xd3, 0x92, 0x64, 0x06, 0x63, 0x3d, 0xf2, 0xa3, 0x9f, - 0x69, 0xf5, 0x90, 0xc2, 0x0b, 0xf5, 0x84, 0xd8, 0x68, 0x95, 0x6c, 0xaf, 0xfa, 0x64, 0x8f, 0x67, - 0x08, 0x21, 0xd9, 0x5a, 0x7d, 0xc2, 0x55, 0xf5, 0x7f, 0xb8, 0x00, 0xec, 0xe3, 0x29, 0xf7, 0xaf, - 0x31, 0x7e, 0x23, 0x78, 0x99, 0x43, 0xa3, 0x3a, 0x17, 0xc9, 0xbe, 0x52, 0x8c, 0x56, 0x5a, 0x8c, - 0x54, 0xfe, 0xe5, 0x31, 0x52, 0x85, 0x97, 0xc5, 0x48, 0x7d, 0x05, 0x6a, 0xce, 0x99, 0xeb, 0x09, - 0x56, 0x28, 0xe4, 0xd6, 0xa0, 0xb9, 0x70, 0x3f, 0xf7, 0xa0, 0x6a, 0x56, 0x25, 0x50, 0x48, 0xad, - 0x01, 0xfb, 0x28, 0x46, 0xe2, 0xc3, 0x33, 0x8c, 0xe7, 0xd3, 0x99, 0x60, 0x7b, 0x78, 0xc6, 0xe5, - 0x31, 0x10, 0xea, 0x05, 0x2a, 0xb3, 0x80, 0x07, 0xec, 0x4d, 0xa8, 0x07, 0xde, 0x54, 0xa8, 0x01, - 0x6a, 0x18, 0xc8, 0xac, 0x55, 0x25, 0xe8, 0x91, 0xb2, 0x61, 0x2e, 0x4f, 0x03, 0x6e, 0x8d, 0x9d, - 0x20, 0x10, 0xe2, 0xd9, 0xc0, 0x73, 0x43, 0xdf, 0x1b, 0x49, 0x4b, 0xd5, 0xd2, 0x34, 0xe0, 0x07, - 0x94, 0xb2, 0x4d, 0x09, 0xec, 0x9b, 0x71, 0x93, 0x26, 0xb6, 0xe3, 0x07, 0x4d, 0xc0, 0x26, 0xa9, - 0x9e, 0xa2, 0xb4, 0x6d, 0x3b, 0x7e, 0xd4, 0x16, 0xf1, 0x11, 0xcc, 0xc4, 0x6e, 0x55, 0x66, 0x63, - 0xb7, 0x7e, 0x98, 0x1e, 0xbb, 0x55, 0xc3, 0xa2, 0x1f, 0xcb, 0xa2, 0xe7, 0xa7, 0xf8, 0x4b, 0x85, - 0x70, 0xcd, 0x87, 0xa4, 0xd5, 0xbf, 0x4c, 0x48, 0xda, 0x62, 0x5a, 0x48, 0xda, 0x7b, 0x50, 0xc1, - 0x60, 0x21, 0xeb, 0xdc, 0x11, 0x32, 0x1c, 0x59, 0xde, 0x1a, 0x7a, 0x34, 0xd1, 0x9e, 0xe3, 0x86, - 0x26, 0xf8, 0xea, 0x67, 0x30, 0x1f, 0x1d, 0xb6, 0xf4, 0x0b, 0x8c, 0x0e, 0x93, 0x41, 0x4d, 0x9b, - 0x50, 0x52, 0xf3, 0xc4, 0x18, 0xe4, 0x4f, 0x7d, 0x6f, 0xac, 0x2c, 0x12, 0xe2, 0x37, 0xab, 0x43, - 0x36, 0xf4, 0x64, 0xe6, 0x6c, 0xe8, 0x19, 0xbf, 0x0e, 0x15, 0x8d, 0xd4, 0xd8, 0x1b, 0x74, 0x8a, - 0x28, 0x34, 0x29, 0x29, 0x5b, 0xd2, 0x28, 0x96, 0x25, 0xb4, 0x33, 0x14, 0xfc, 0x66, 0xe8, 0xf8, - 0x1c, 0xe3, 0x38, 0x2d, 0x9f, 0x5f, 0x70, 0x3f, 0x50, 0x16, 0xa2, 0x46, 0x94, 0x60, 0x12, 0xdc, - 0xf8, 0x0d, 0x58, 0x4e, 0xcc, 0xad, 0x64, 0x11, 0x6f, 0xc2, 0x02, 0x8e, 0x9b, 0xb2, 0xe0, 0x27, - 0xa3, 0xb4, 0x64, 0x1a, 0x06, 0xe8, 0x93, 0x71, 0xcb, 0x9a, 0xf8, 0xde, 0x09, 0x56, 0x92, 0x31, - 0x2b, 0x12, 0x76, 0xe4, 0x7b, 0x27, 0xc6, 0x5f, 0xe4, 0x20, 0xb7, 0xe7, 0x4d, 0x74, 0xa7, 0xb5, - 0xcc, 0x9c, 0xd3, 0x9a, 0x54, 0x0f, 0xad, 0x48, 0xfd, 0x93, 0x32, 0x3b, 0x9a, 0x75, 0x94, 0x0a, - 0xf8, 0x00, 0xea, 0x82, 0x4f, 0x84, 0x9e, 0xd0, 0xaf, 0x2f, 0x6d, 0x9f, 0x04, 0xe2, 0x1c, 0x2d, - 0x3e, 0x7b, 0x1c, 0xf6, 0xbd, 0x5d, 0x82, 0xb3, 0x15, 0xc8, 0x45, 0xea, 0x0b, 0x26, 0x8b, 0x4f, - 0xb6, 0x06, 0x0b, 0xe8, 0xbd, 0x7c, 0x2d, 0x4d, 0xd4, 0xf2, 0x8b, 0x7d, 0x1d, 0x96, 0x93, 0xe5, - 0x12, 0x2b, 0x92, 0xb2, 0x91, 0x5e, 0x30, 0xf2, 0xa4, 0xdb, 0x20, 0xf8, 0x08, 0xe1, 0x48, 0x4f, - 0x97, 0x53, 0xce, 0x31, 0x49, 0x63, 0x7a, 0xa5, 0x04, 0xd3, 0xbb, 0x07, 0x95, 0x70, 0x74, 0x61, - 0x4d, 0xec, 0xeb, 0x91, 0x67, 0x0f, 0xe5, 0xfa, 0x86, 0x70, 0x74, 0x71, 0x44, 0x10, 0xf6, 0x08, - 0x60, 0x3c, 0x99, 0xc8, 0xb5, 0x87, 0xa6, 0x8a, 0x98, 0x94, 0x0f, 0x8e, 0x8e, 0x88, 0xe4, 0xcc, - 0xf2, 0x78, 0x32, 0xa1, 0x9f, 0x6c, 0x07, 0xea, 0xa9, 0xb1, 0x96, 0x77, 0x95, 0xb3, 0xad, 0x37, - 0xd9, 0x4c, 0x59, 0x9c, 0xb5, 0x81, 0x0e, 0xdb, 0xf8, 0x1e, 0xb0, 0x9f, 0x31, 0xe2, 0xb1, 0x0f, - 0xe5, 0xa8, 0x7d, 0x7a, 0xc0, 0x20, 0xba, 0xcf, 0x57, 0x12, 0x01, 0x83, 0xad, 0xe1, 0xd0, 0x17, - 0x7c, 0x91, 0x36, 0xcc, 0x88, 0xe5, 0x83, 0xb6, 0x63, 0xb6, 0x88, 0xef, 0x1b, 0xff, 0x3d, 0x03, - 0x05, 0x8a, 0x5e, 0x7c, 0x0b, 0x16, 0x09, 0x3f, 0x72, 0x00, 0x94, 0x86, 0x6d, 0xda, 0x77, 0xfb, - 0xd2, 0xf7, 0x4f, 0x2c, 0x0b, 0x2d, 0xf2, 0x3a, 0x1b, 0xcd, 0xbc, 0x16, 0x7d, 0x7d, 0x0f, 0xca, - 0x51, 0xd5, 0x1a, 0xe9, 0x94, 0x54, 0xcd, 0xec, 0x75, 0xc8, 0x9f, 0x7b, 0x13, 0x75, 0x4e, 0x03, - 0xf1, 0x48, 0x9a, 0x08, 0x8f, 0xdb, 0x22, 0xea, 0xa0, 0xc6, 0xcb, 0xf3, 0x85, 0xa8, 0x12, 0x24, - 0x83, 0xf9, 0x3e, 0x2e, 0xa4, 0xf4, 0xf1, 0x18, 0x16, 0x05, 0x1f, 0xd0, 0x1c, 0x4c, 0x6e, 0xde, - 0x34, 0xdf, 0x11, 0x12, 0xde, 0x60, 0x34, 0x1d, 0x72, 0xfd, 0xa4, 0x0c, 0xbd, 0xd1, 0x24, 0x5c, - 0x49, 0xd6, 0xc6, 0x1f, 0x66, 0x88, 0xbf, 0x88, 0x72, 0xd9, 0x03, 0xc8, 0x8b, 0xfd, 0x6d, 0xe6, - 0xdc, 0x3c, 0x8a, 0x63, 0x10, 0x78, 0x26, 0x62, 0xe0, 0x75, 0x05, 0xd3, 0x71, 0xb2, 0xf4, 0x9a, - 0x59, 0x71, 0xa7, 0xe3, 0xe8, 0xa0, 0xe9, 0xab, 0xaa, 0x5b, 0x33, 0x87, 0x34, 0xd4, 0xfb, 0x68, - 0x99, 0x6e, 0x6a, 0x6e, 0x6d, 0xf9, 0xc4, 0x8e, 0xa9, 0xa4, 0xc0, 0xe1, 0x19, 0xd7, 0xdc, 0xd9, - 0xfe, 0x38, 0x0b, 0xb5, 0x44, 0x8b, 0xd0, 0xaf, 0x4f, 0x6c, 0x00, 0x64, 0x06, 0x92, 0xf3, 0x0d, - 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9c, 0xb2, 0x89, 0x71, 0x8a, 0x5c, 0x69, 0x72, 0xba, 0x2b, 0xcd, - 0x63, 0x28, 0xc7, 0x11, 0xf7, 0xc9, 0x26, 0x89, 0xfa, 0x54, 0x34, 0x47, 0x8c, 0x14, 0x3b, 0xdf, - 0x14, 0x74, 0xe7, 0x9b, 0xef, 0x6a, 0xbe, 0x1a, 0x0b, 0x58, 0x8c, 0x91, 0x36, 0xa2, 0xbf, 0x10, - 0x4f, 0x0d, 0xe3, 0x23, 0xa8, 0x68, 0x8d, 0xd7, 0x7d, 0x32, 0x32, 0x09, 0x9f, 0x8c, 0x28, 0xee, - 0x2a, 0x1b, 0xc7, 0x5d, 0x19, 0xbf, 0x95, 0x85, 0x9a, 0x58, 0x5f, 0x8e, 0x7b, 0x76, 0xe4, 0x8d, - 0x9c, 0x01, 0x9a, 0x85, 0xa2, 0x15, 0x26, 0x05, 0x2d, 0xb5, 0xce, 0xe4, 0x12, 0x23, 0x39, 0x4b, - 0x0f, 0x2f, 0x25, 0x26, 0x1d, 0x85, 0x97, 0x1a, 0x50, 0x13, 0x8c, 0x11, 0x0d, 0x3c, 0xf1, 0x7d, - 0x00, 0x66, 0xe5, 0x94, 0xf3, 0x2d, 0x3b, 0x20, 0x0e, 0xf9, 0x75, 0x58, 0x16, 0x38, 0x18, 0x59, - 0x37, 0x76, 0x46, 0x23, 0x87, 0x30, 0xe9, 0xa0, 0xa9, 0x71, 0xca, 0xb9, 0x69, 0x87, 0xfc, 0x40, - 0x24, 0xc8, 0xeb, 0x03, 0x4a, 0x43, 0x27, 0xb0, 0x4f, 0x62, 0xef, 0xcb, 0xe8, 0x1b, 0xed, 0xc0, - 0xf6, 0x95, 0x66, 0x07, 0xa6, 0x03, 0x88, 0xca, 0xd8, 0xbe, 0x8a, 0xec, 0xc0, 0x33, 0x94, 0x54, - 0x9c, 0xa5, 0x24, 0xe3, 0x3f, 0x64, 0xa1, 0xa2, 0x91, 0xe5, 0xab, 0xec, 0xae, 0x77, 0xe7, 0xcc, - 0x78, 0x65, 0xdd, 0x62, 0xf7, 0x95, 0x64, 0x95, 0xe8, 0xa9, 0x42, 0x17, 0x15, 0x68, 0x04, 0x7c, - 0x07, 0xca, 0x62, 0xd5, 0xbd, 0x87, 0x07, 0xa6, 0xf2, 0x9a, 0x0d, 0x04, 0x1c, 0x4d, 0x4f, 0x54, - 0xe2, 0x13, 0x4c, 0x2c, 0xc4, 0x89, 0x4f, 0x44, 0xe2, 0x8b, 0x5c, 0xae, 0xbf, 0x05, 0x55, 0x59, - 0x2a, 0xce, 0x29, 0x76, 0x37, 0x5e, 0xf5, 0x89, 0xf9, 0x36, 0x2b, 0x54, 0x1d, 0x4d, 0xbe, 0xcc, - 0xf8, 0x44, 0x65, 0x2c, 0xbd, 0x2c, 0xe3, 0x13, 0xfa, 0x30, 0x76, 0x23, 0x2f, 0x76, 0xf4, 0x92, - 0x52, 0x7c, 0xec, 0x11, 0x2c, 0x2b, 0x76, 0x35, 0x75, 0x6d, 0xd7, 0xf5, 0xa6, 0xee, 0x80, 0xab, - 0x80, 0x2c, 0x26, 0x93, 0x8e, 0xe3, 0x14, 0x63, 0x18, 0x45, 0xec, 0x92, 0xb7, 0xd5, 0x43, 0x28, - 0x90, 0x5c, 0x4e, 0xc2, 0x47, 0x3a, 0xe3, 0x22, 0x14, 0xf6, 0x00, 0x0a, 0x24, 0x9e, 0x67, 0x6f, - 0x64, 0x36, 0x84, 0x60, 0xb4, 0x80, 0x89, 0x8c, 0x07, 0x3c, 0xf4, 0x9d, 0x41, 0x10, 0xc7, 0x7a, - 0x15, 0x84, 0xfe, 0x49, 0x75, 0xc5, 0xc1, 0x15, 0x31, 0x26, 0xea, 0xa8, 0x84, 0x23, 0x36, 0xa6, - 0xe5, 0x44, 0x19, 0x52, 0x5c, 0x1a, 0xc1, 0xda, 0x09, 0x0f, 0x2f, 0x39, 0x77, 0x5d, 0x21, 0x0c, - 0x0d, 0xb8, 0x1b, 0xfa, 0xf6, 0x48, 0x4c, 0x12, 0xf5, 0xe0, 0xfd, 0xb9, 0x52, 0xe3, 0x33, 0x90, - 0xad, 0x38, 0xe3, 0x76, 0x94, 0x8f, 0x78, 0xc7, 0xea, 0x49, 0x5a, 0xda, 0xc6, 0xaf, 0xc1, 0xc6, - 0xcd, 0x99, 0x52, 0x22, 0x3a, 0x1f, 0x24, 0xb9, 0x4a, 0x64, 0xb5, 0x1b, 0x79, 0x76, 0x48, 0xad, - 0xd1, 0x39, 0x4b, 0x17, 0x2a, 0x5a, 0x4a, 0xbc, 0xf7, 0x67, 0x50, 0xb8, 0xa3, 0x0f, 0xb1, 0x23, - 0xb9, 0x9e, 0x3f, 0x46, 0x2b, 0xd9, 0xd0, 0x8a, 0x4b, 0xcf, 0x98, 0x8b, 0x31, 0x1c, 0x43, 0xd8, - 0x8d, 0x4d, 0x58, 0x44, 0xc9, 0x5e, 0xdb, 0xe8, 0x5e, 0x24, 0x0c, 0x1a, 0x2b, 0xc0, 0xba, 0xc4, - 0xbb, 0x74, 0xe7, 0xcb, 0xff, 0x9a, 0x83, 0x8a, 0x06, 0x16, 0xbb, 0x11, 0xba, 0xeb, 0x59, 0x43, - 0xc7, 0x1e, 0x73, 0x65, 0x92, 0xac, 0x99, 0x35, 0x84, 0xee, 0x48, 0xa0, 0xd8, 0x8b, 0xed, 0x8b, - 0x33, 0xcb, 0x9b, 0x86, 0xd6, 0x90, 0x9f, 0xf9, 0x5c, 0xb5, 0xb2, 0x6a, 0x5f, 0x9c, 0x1d, 0x4e, - 0xc3, 0x1d, 0x84, 0x09, 0x2c, 0xc1, 0x4b, 0x34, 0x2c, 0xe9, 0x61, 0x36, 0xb6, 0xaf, 0x62, 0x2c, - 0xe9, 0xe6, 0x48, 0x94, 0x99, 0x8f, 0xdc, 0x1c, 0x49, 0x5b, 0x9c, 0xdd, 0x40, 0x0b, 0xf3, 0x1b, - 0xe8, 0x37, 0x61, 0x8d, 0x36, 0x50, 0xc9, 0x9a, 0xad, 0x99, 0x95, 0xbc, 0x82, 0xa9, 0xb2, 0x93, - 0x9a, 0xd8, 0xdb, 0x10, 0x3d, 0x50, 0x6c, 0x29, 0x70, 0x7e, 0x44, 0x8c, 0x2c, 0x63, 0x8a, 0x9e, - 0xc9, 0xc2, 0x7b, 0xce, 0x8f, 0xb8, 0xc0, 0x44, 0x5f, 0x16, 0x1d, 0x53, 0x06, 0x54, 0x8c, 0x1d, - 0x77, 0x16, 0xd3, 0xbe, 0x4a, 0x62, 0x96, 0x25, 0xa6, 0x7d, 0xa5, 0x63, 0xbe, 0x0f, 0xeb, 0x63, - 0x3e, 0x74, 0xec, 0x64, 0xb1, 0x56, 0x2c, 0xb8, 0xad, 0x50, 0xb2, 0x96, 0xa7, 0x47, 0x8a, 0xbb, - 0x18, 0x8d, 0x1f, 0x79, 0xe3, 0x13, 0x87, 0x64, 0x16, 0xf2, 0xae, 0xc9, 0x9b, 0x75, 0x77, 0x3a, - 0xfe, 0x01, 0x82, 0x45, 0x96, 0xc0, 0xa8, 0x41, 0xa5, 0x17, 0x7a, 0x13, 0x35, 0xcd, 0x75, 0xa8, - 0xd2, 0xa7, 0x8c, 0x72, 0xbc, 0x03, 0xb7, 0x91, 0x25, 0xf4, 0xbd, 0x89, 0x37, 0xf2, 0xce, 0xae, - 0x13, 0xe7, 0x78, 0xff, 0x39, 0x03, 0xcb, 0x89, 0x54, 0xc9, 0x5e, 0xbf, 0x49, 0xfc, 0x2c, 0x0a, - 0x55, 0xa3, 0x35, 0xb8, 0xa4, 0xad, 0x41, 0x42, 0x24, 0x66, 0xa6, 0xc2, 0xd7, 0x5a, 0xf1, 0x15, - 0x0b, 0x2a, 0x23, 0xb1, 0x94, 0xe6, 0x3c, 0x4b, 0x91, 0xf9, 0xd5, 0xe5, 0x0b, 0xaa, 0x88, 0x5f, - 0x92, 0x41, 0x2f, 0x43, 0xd9, 0xe5, 0x5c, 0xd2, 0xad, 0x5f, 0x3f, 0xf3, 0x53, 0x2d, 0x88, 0x0f, - 0x02, 0x03, 0xe3, 0x5f, 0x65, 0x00, 0xe2, 0xd6, 0x61, 0x60, 0x41, 0x24, 0xb7, 0xd0, 0xed, 0x65, - 0x9a, 0x8c, 0xf2, 0x06, 0x54, 0x23, 0xff, 0xe2, 0x58, 0x12, 0xaa, 0x28, 0x98, 0x10, 0x87, 0xde, - 0x86, 0xc5, 0xb3, 0x91, 0x77, 0x82, 0x12, 0xab, 0x94, 0x5b, 0xc8, 0xbb, 0xac, 0x4e, 0x60, 0x25, - 0x8d, 0xc4, 0x72, 0x53, 0x3e, 0xd5, 0x05, 0x59, 0x97, 0x82, 0x8c, 0xdf, 0xce, 0x46, 0x8e, 0x96, - 0xf1, 0x48, 0xbc, 0x58, 0xbd, 0xfb, 0x69, 0x3c, 0x5f, 0x5e, 0x64, 0x0c, 0xfc, 0x08, 0xea, 0x3e, - 0x6d, 0x4a, 0x6a, 0xc7, 0xca, 0xbf, 0x60, 0xc7, 0xaa, 0xf9, 0x09, 0x49, 0xe7, 0x1d, 0x68, 0xd8, - 0xc3, 0x0b, 0xee, 0x87, 0x0e, 0x9e, 0xd6, 0xa3, 0x7c, 0x2c, 0x5d, 0x1b, 0x35, 0x38, 0x0a, 0xa2, - 0x6f, 0xc3, 0xa2, 0x8c, 0xbc, 0x8d, 0x30, 0xe5, 0x5d, 0x3e, 0x31, 0x58, 0x20, 0x1a, 0xff, 0x46, - 0x79, 0x76, 0x26, 0x67, 0xf7, 0xc5, 0xa3, 0xa2, 0xf7, 0x30, 0x3b, 0x6f, 0xee, 0x94, 0x84, 0x24, - 0x8d, 0x00, 0x92, 0x1f, 0x11, 0x50, 0x9a, 0x00, 0x92, 0xc3, 0x9a, 0x7f, 0x95, 0x61, 0x35, 0xfe, - 0x34, 0x03, 0xc5, 0x3d, 0x6f, 0xb2, 0xe7, 0x90, 0x6b, 0x3d, 0x2e, 0x93, 0xc8, 0x46, 0xb5, 0x20, - 0x3e, 0xd1, 0x4d, 0xe7, 0x05, 0x01, 0x66, 0xa9, 0x62, 0x5e, 0x2d, 0x29, 0xe6, 0x7d, 0x17, 0xee, - 0xa0, 0x09, 0xd0, 0xf7, 0x26, 0x9e, 0x2f, 0x96, 0xaa, 0x3d, 0x22, 0x71, 0xcf, 0x73, 0xc3, 0x73, - 0xc5, 0x3b, 0x6f, 0x9f, 0x72, 0x7e, 0xa4, 0x61, 0x1c, 0x44, 0x08, 0x18, 0xc2, 0x39, 0x0a, 0x2f, - 0x2c, 0xd2, 0xd0, 0xa5, 0x3c, 0x4a, 0x1c, 0x75, 0x51, 0x24, 0xb4, 0x11, 0x8e, 0x12, 0xa9, 0xf1, - 0x6d, 0x28, 0x47, 0x87, 0x3d, 0xec, 0x5d, 0x28, 0x9f, 0x7b, 0x13, 0x79, 0x22, 0x94, 0x49, 0x04, - 0xe1, 0xc9, 0x5e, 0x9b, 0xa5, 0x73, 0xfa, 0x11, 0x18, 0x7f, 0x51, 0x84, 0x62, 0xc7, 0xbd, 0xf0, - 0x9c, 0x01, 0xfa, 0x86, 0x8e, 0xf9, 0xd8, 0x53, 0xe1, 0xff, 0xe2, 0x37, 0x7a, 0x52, 0xc5, 0x37, - 0xf2, 0xe4, 0xa4, 0x27, 0x55, 0x74, 0x17, 0xcf, 0x2a, 0x2c, 0xf8, 0xfa, 0x95, 0x3a, 0x05, 0x1f, - 0xbd, 0xd5, 0xa3, 0xfd, 0xb2, 0xa0, 0x5d, 0x9f, 0x20, 0xca, 0xa2, 0xab, 0x5e, 0x70, 0xc8, 0x28, - 0x1c, 0xb3, 0x8c, 0x10, 0x1c, 0xb0, 0xd7, 0xa0, 0x28, 0x63, 0xde, 0x28, 0x82, 0x88, 0xdc, 0xcb, - 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0x64, 0xc2, 0x8d, 0x04, 0xd9, 0x9c, 0x59, 0x55, 0xc0, 0x1d, 0x41, - 0x6b, 0xf7, 0xa0, 0x42, 0xf8, 0x84, 0x52, 0x92, 0x2e, 0x95, 0x08, 0x42, 0x84, 0x94, 0x9b, 0xa9, - 0xca, 0xa9, 0x37, 0x53, 0xa1, 0xf3, 0x6f, 0xc4, 0x65, 0xa9, 0x8b, 0x40, 0xf7, 0x11, 0x69, 0x70, - 0x75, 0x2d, 0x9b, 0x3c, 0x53, 0xa1, 0xe8, 0x64, 0x75, 0xa6, 0xf2, 0x15, 0xa8, 0x9d, 0xda, 0xa3, - 0xd1, 0x89, 0x3d, 0x78, 0x4e, 0x47, 0x01, 0x55, 0x3a, 0xfd, 0x54, 0x40, 0x3c, 0x0b, 0xb8, 0x07, - 0x15, 0x6d, 0x96, 0xd1, 0x5f, 0x32, 0x6f, 0x42, 0x3c, 0xbf, 0xb3, 0x27, 0x7c, 0xf5, 0x57, 0x38, - 0xe1, 0xd3, 0xfc, 0x46, 0x17, 0x93, 0x7e, 0xa3, 0x77, 0x90, 0x9b, 0x4a, 0x07, 0xc1, 0x06, 0x5d, - 0x7e, 0x63, 0x0f, 0x87, 0xe8, 0x20, 0x48, 0x37, 0x4d, 0xe2, 0xe0, 0x51, 0xfa, 0x12, 0xe9, 0x12, - 0x04, 0x23, 0x94, 0xbb, 0x74, 0x4c, 0x3d, 0xb1, 0x9d, 0x21, 0x86, 0x08, 0xd0, 0xe9, 0x41, 0xd1, - 0x1e, 0x87, 0x47, 0xb6, 0x33, 0x64, 0xf7, 0xa1, 0xaa, 0x92, 0x71, 0x77, 0x5c, 0xa6, 0xf1, 0x97, - 0xc9, 0x62, 0x4f, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe3, 0x10, 0xe3, 0x8a, 0x44, 0x41, 0x3a, 0x78, - 0x0f, 0x7d, 0x72, 0x42, 0x8e, 0x81, 0xc4, 0xf5, 0x27, 0x77, 0x64, 0x5f, 0x25, 0x95, 0xaa, 0xff, - 0x64, 0x1c, 0x23, 0x4c, 0x21, 0xdc, 0x91, 0x8d, 0x6e, 0x2d, 0x21, 0xff, 0x4a, 0x54, 0xb4, 0xd1, - 0x11, 0x02, 0xfb, 0xb6, 0xa6, 0xbf, 0x36, 0x11, 0xf9, 0xb5, 0x99, 0xf2, 0x6f, 0x8a, 0x90, 0xba, - 0x0b, 0xe0, 0x04, 0x62, 0x97, 0x09, 0xb8, 0x3b, 0xc4, 0x98, 0xe0, 0x92, 0x59, 0x76, 0x82, 0x67, - 0x04, 0xf8, 0xf9, 0x2a, 0xb6, 0x2d, 0xa8, 0xea, 0xdd, 0x64, 0x25, 0xc8, 0x1f, 0x1e, 0xb5, 0xbb, - 0x8d, 0x5b, 0xac, 0x02, 0xc5, 0x5e, 0xbb, 0xdf, 0xdf, 0x47, 0x4b, 0x5f, 0x15, 0x4a, 0x51, 0x40, - 0x62, 0x56, 0x7c, 0xb5, 0xb6, 0xb7, 0xdb, 0x47, 0xfd, 0xf6, 0x4e, 0x23, 0xf7, 0xfd, 0x7c, 0x29, - 0xdb, 0xc8, 0x19, 0x7f, 0x99, 0x83, 0x8a, 0x36, 0x0a, 0x2f, 0x66, 0xc6, 0x77, 0x01, 0x50, 0x93, - 0x8c, 0xfd, 0x47, 0xf3, 0x66, 0x59, 0x40, 0x68, 0xf2, 0x75, 0x1b, 0x45, 0x8e, 0x6e, 0x55, 0x52, - 0x36, 0x8a, 0xaf, 0x40, 0x8d, 0x2e, 0x28, 0xd2, 0xed, 0xb5, 0x05, 0xb3, 0x4a, 0x40, 0xc9, 0xaa, - 0x31, 0xa2, 0x19, 0x91, 0x30, 0xd6, 0x4d, 0x5e, 0x57, 0x42, 0x20, 0x8c, 0x76, 0xc3, 0x50, 0xc5, - 0xc0, 0x1b, 0x5d, 0x70, 0xc2, 0x20, 0x89, 0xb0, 0x22, 0x61, 0x7d, 0x19, 0x9b, 0x2d, 0xf9, 0xa1, - 0x16, 0x52, 0x5b, 0x30, 0xab, 0x04, 0x94, 0x15, 0x7d, 0x5d, 0x11, 0x50, 0x09, 0x09, 0x68, 0x7d, - 0x9e, 0x1a, 0x12, 0xc4, 0xb3, 0x3f, 0x77, 0x8c, 0x58, 0x46, 0xc2, 0xf8, 0xea, 0x7c, 0xbe, 0x97, - 0x1f, 0x27, 0xb2, 0x77, 0x81, 0x8d, 0x27, 0x13, 0x2b, 0xe5, 0x80, 0x2f, 0x6f, 0x2e, 0x8e, 0x27, - 0x93, 0xbe, 0x76, 0xfe, 0xf5, 0x73, 0x38, 0x7b, 0xfc, 0x1c, 0x58, 0x4b, 0x2c, 0x60, 0x6c, 0x62, - 0xa4, 0x8a, 0xc5, 0x6c, 0x39, 0xa3, 0xb3, 0xe5, 0x14, 0xee, 0x97, 0x4d, 0xe5, 0x7e, 0x2f, 0xe2, - 0x13, 0xc6, 0x2e, 0x54, 0x8e, 0xb4, 0xeb, 0xcf, 0xee, 0x8b, 0x1d, 0x42, 0x5d, 0x7c, 0x46, 0x7b, - 0x07, 0x9d, 0x29, 0xfa, 0xf2, 0xbe, 0x33, 0xad, 0x35, 0x59, 0xad, 0x35, 0xc6, 0xbf, 0xcc, 0xd0, - 0xd5, 0x32, 0x51, 0xe3, 0xe3, 0x1b, 0xd7, 0x94, 0xf9, 0x2d, 0x8e, 0x7c, 0xaf, 0x28, 0xb3, 0x9b, - 0x0c, 0x5a, 0xc7, 0xa6, 0x59, 0xde, 0xe9, 0x69, 0xc0, 0x95, 0x8f, 0x47, 0x05, 0x61, 0x87, 0x08, - 0x52, 0xc2, 0xb7, 0x90, 0xf0, 0x1d, 0x2a, 0x3f, 0x90, 0x8e, 0x1d, 0x42, 0xf8, 0x3e, 0xb0, 0xaf, - 0x64, 0xad, 0x81, 0x10, 0x41, 0xa4, 0x7d, 0x40, 0x45, 0xae, 0x46, 0xdf, 0xc6, 0x3f, 0x93, 0xc1, - 0xf9, 0xb3, 0xe3, 0xfb, 0x10, 0x4a, 0x51, 0xa9, 0xc9, 0x1d, 0x56, 0x61, 0x46, 0xe9, 0x62, 0x1f, - 0xc7, 0xc3, 0x90, 0x44, 0x8b, 0x69, 0x71, 0xa1, 0x8d, 0xa7, 0xa3, 0xb5, 0xfa, 0x6b, 0xc0, 0x4e, - 0x1d, 0x7f, 0x16, 0x99, 0x16, 0x5b, 0x03, 0x53, 0x34, 0x6c, 0xe3, 0x18, 0x96, 0x15, 0x97, 0xd0, - 0x34, 0x82, 0xe4, 0xe4, 0x65, 0x5e, 0xc2, 0xe4, 0xb3, 0x73, 0x4c, 0xde, 0xf8, 0x49, 0x1e, 0x8a, - 0xea, 0x2a, 0xc1, 0xb4, 0xeb, 0xef, 0xca, 0xc9, 0xeb, 0xef, 0x9a, 0x89, 0xab, 0x92, 0x70, 0xea, - 0xe5, 0x7e, 0xff, 0xf6, 0xec, 0x96, 0xad, 0xd9, 0x2a, 0x12, 0xdb, 0xf6, 0x1a, 0xe4, 0x27, 0x76, - 0x78, 0x8e, 0xe7, 0x92, 0x44, 0x3c, 0xf8, 0xad, 0x6c, 0x18, 0x85, 0xa4, 0x0d, 0x23, 0xed, 0xaa, - 0x40, 0x12, 0x49, 0xe7, 0xae, 0x0a, 0xbc, 0x03, 0x24, 0x5f, 0x68, 0x2e, 0x6a, 0x25, 0x04, 0x88, - 0xbd, 0x28, 0x29, 0x8e, 0x94, 0x66, 0xc5, 0x91, 0x57, 0x16, 0x15, 0xbe, 0x09, 0x0b, 0x74, 0xcd, - 0x86, 0x8c, 0xd0, 0x55, 0x1b, 0x8a, 0x1c, 0x43, 0xf5, 0x9f, 0xe2, 0x16, 0x4c, 0x89, 0xab, 0xdf, - 0xbb, 0x55, 0x49, 0xdc, 0xbb, 0xa5, 0xdb, 0x56, 0xaa, 0x49, 0xdb, 0xca, 0x03, 0x68, 0x44, 0x03, - 0x8a, 0x27, 0x95, 0x6e, 0x20, 0xe3, 0xff, 0xea, 0x0a, 0x2e, 0xb8, 0x64, 0x37, 0x88, 0x37, 0xc4, - 0x7a, 0x62, 0x43, 0x14, 0x3c, 0xac, 0x15, 0x86, 0x7c, 0x3c, 0x09, 0xe5, 0x86, 0x88, 0x11, 0x42, - 0x7a, 0x03, 0x93, 0xb1, 0xeb, 0x35, 0x28, 0x77, 0xba, 0xd6, 0xee, 0x7e, 0xe7, 0xe9, 0x5e, 0xbf, - 0x91, 0x11, 0x9f, 0xbd, 0xe3, 0xed, 0xed, 0x76, 0x7b, 0x07, 0x77, 0x1c, 0x80, 0x85, 0xdd, 0x56, - 0x47, 0xec, 0x3e, 0x39, 0xe3, 0x77, 0xb3, 0x50, 0xd1, 0x8a, 0x67, 0xef, 0x47, 0xa3, 0x42, 0x57, - 0x33, 0xdd, 0x9d, 0x6f, 0xc2, 0xa6, 0x62, 0xc5, 0xda, 0xb0, 0x44, 0x17, 0x23, 0x66, 0x6f, 0xbc, - 0x18, 0x91, 0xbd, 0x05, 0x8b, 0x36, 0x95, 0x10, 0x8d, 0x82, 0x3c, 0x85, 0x97, 0x60, 0x39, 0x08, - 0xe8, 0x98, 0x19, 0xef, 0x27, 0x02, 0x2f, 0xaf, 0x7c, 0x21, 0xa3, 0x2d, 0x05, 0x07, 0xab, 0x78, - 0x6a, 0x3b, 0xa3, 0xa9, 0xcf, 0xa5, 0xd5, 0x3c, 0xda, 0x99, 0x09, 0x6a, 0xaa, 0x64, 0xe3, 0x03, - 0x80, 0xb8, 0xcd, 0xc9, 0xc1, 0xb9, 0x95, 0x1c, 0x9c, 0x8c, 0x36, 0x38, 0x59, 0x63, 0x87, 0xd8, - 0x88, 0x1c, 0xe8, 0xe8, 0xd8, 0xed, 0xeb, 0xa0, 0x0e, 0x02, 0x2d, 0x74, 0x8f, 0x9e, 0x8c, 0x78, - 0xa8, 0xa2, 0xfc, 0x97, 0x64, 0x4a, 0x27, 0x4a, 0x50, 0x97, 0x6e, 0xc4, 0xa5, 0xc4, 0xdc, 0x48, - 0x92, 0xe4, 0x2c, 0x37, 0x92, 0xa8, 0x66, 0x94, 0x6e, 0x6c, 0x40, 0x73, 0x87, 0x8b, 0xd2, 0x5a, - 0xa3, 0xd1, 0x4c, 0x73, 0x8c, 0x3b, 0x70, 0x3b, 0x25, 0x4d, 0x1e, 0x42, 0x7c, 0x0c, 0xab, 0x2d, - 0x0a, 0xe8, 0xff, 0x79, 0x45, 0xee, 0x19, 0x4d, 0x58, 0x9b, 0x2d, 0x52, 0x56, 0xb6, 0x0b, 0x4b, - 0x3b, 0xfc, 0x64, 0x7a, 0xb6, 0xcf, 0x2f, 0xe2, 0x8a, 0x18, 0xe4, 0x83, 0x73, 0xef, 0x52, 0x8e, - 0x0f, 0xfe, 0x46, 0x2f, 0x43, 0x81, 0x63, 0x05, 0x13, 0x3e, 0x50, 0x07, 0xd1, 0x08, 0xe9, 0x4d, - 0xf8, 0xc0, 0x78, 0x1f, 0x98, 0x5e, 0x8e, 0x1c, 0x2f, 0xa1, 0x25, 0x4c, 0x4f, 0xac, 0xe0, 0x3a, - 0x08, 0xf9, 0x58, 0x45, 0xac, 0x41, 0x30, 0x3d, 0xe9, 0x11, 0xc4, 0x78, 0x1b, 0xaa, 0x47, 0xf6, - 0xb5, 0xc9, 0x3f, 0x97, 0x81, 0x61, 0xeb, 0x50, 0x9c, 0xd8, 0xd7, 0x82, 0x0d, 0x44, 0x36, 0x29, - 0x4c, 0x36, 0xfe, 0x28, 0x0f, 0x0b, 0x84, 0xc9, 0xee, 0xd3, 0xe5, 0xbc, 0x8e, 0x8b, 0xcb, 0x50, - 0x31, 0x4a, 0x0d, 0x34, 0xc7, 0x4b, 0xb3, 0xf3, 0xbc, 0x54, 0x1e, 0xa0, 0xa9, 0x4b, 0x89, 0x94, - 0xf5, 0xc0, 0x9d, 0x8e, 0xd5, 0x4d, 0x44, 0xc9, 0xa8, 0xf6, 0x7c, 0x7c, 0xf9, 0x32, 0x85, 0xfc, - 0x26, 0xed, 0xbb, 0xb1, 0x2e, 0x42, 0xad, 0x53, 0x5b, 0x84, 0x64, 0x97, 0x3a, 0x28, 0x55, 0xe1, - 0x29, 0xaa, 0x68, 0xc7, 0xa4, 0xc2, 0x33, 0xa7, 0xd8, 0x94, 0x5e, 0xae, 0xd8, 0xd0, 0xc9, 0xda, - 0x0b, 0x14, 0x1b, 0x78, 0x05, 0xc5, 0xe6, 0x15, 0x6c, 0xab, 0xb7, 0xa1, 0x84, 0xfb, 0xbe, 0xc6, - 0x3d, 0xc5, 0x7e, 0x2f, 0xb8, 0xe7, 0xb7, 0x34, 0xd1, 0x9f, 0x1c, 0x3b, 0xee, 0xc4, 0xcb, 0xc4, - 0xe4, 0x9f, 0xff, 0x62, 0x6c, 0x56, 0x9f, 0x41, 0x51, 0x42, 0x05, 0x41, 0xbb, 0xf6, 0x58, 0xdd, - 0xeb, 0x86, 0xbf, 0xc5, 0xb0, 0xe1, 0x65, 0x54, 0x9f, 0x4f, 0x1d, 0x9f, 0x0f, 0xd5, 0x85, 0x3d, - 0x0e, 0xae, 0x51, 0x01, 0x11, 0x1d, 0x14, 0x6a, 0x88, 0xeb, 0x5d, 0xba, 0xf2, 0xba, 0x8e, 0xa2, - 0x13, 0x3c, 0x13, 0x9f, 0x06, 0x83, 0x06, 0xde, 0xec, 0x38, 0xf1, 0x7c, 0xb5, 0x39, 0x19, 0x3f, - 0xc9, 0x40, 0x43, 0xae, 0xae, 0x28, 0x4d, 0xd7, 0x02, 0x0a, 0x37, 0xf9, 0x21, 0xbc, 0xf8, 0xfa, - 0x1d, 0x03, 0x6a, 0x78, 0xf8, 0x11, 0xed, 0x54, 0x74, 0x78, 0x53, 0x11, 0xc0, 0x5d, 0xb9, 0x5b, - 0xbd, 0x0e, 0x15, 0xe5, 0x03, 0x3d, 0x76, 0x46, 0xea, 0x9e, 0x75, 0x72, 0x82, 0x3e, 0x70, 0x46, - 0x6a, 0xa3, 0xf3, 0x6d, 0x19, 0x7d, 0x9b, 0xc1, 0x8d, 0xce, 0xb4, 0x43, 0x6e, 0xfc, 0xbb, 0x0c, - 0x2c, 0x69, 0x5d, 0x91, 0xeb, 0xf6, 0x43, 0xa8, 0x46, 0x57, 0xaa, 0xf2, 0x48, 0xf2, 0x5a, 0x4f, - 0x32, 0x9a, 0x38, 0x5b, 0x65, 0x10, 0x41, 0x02, 0xd1, 0x98, 0xa1, 0x7d, 0x4d, 0x8e, 0xba, 0xd3, - 0xb1, 0x52, 0x6e, 0x86, 0xf6, 0xf5, 0x2e, 0xe7, 0xbd, 0xe9, 0x58, 0xa8, 0xae, 0x97, 0x9c, 0x3f, - 0x8f, 0x10, 0x48, 0xe6, 0x02, 0x01, 0x93, 0x18, 0x06, 0xd4, 0xc6, 0x9e, 0x1b, 0x9e, 0x47, 0x28, - 0x52, 0xea, 0x44, 0x20, 0xe1, 0x18, 0x7f, 0x9e, 0x85, 0x65, 0x3a, 0x62, 0x93, 0x47, 0x9b, 0x92, - 0x75, 0x35, 0x61, 0x81, 0x4e, 0x1b, 0x89, 0x79, 0xed, 0xdd, 0x32, 0xe5, 0x37, 0xfb, 0xe6, 0x2b, - 0x1e, 0x0b, 0xaa, 0x00, 0xdf, 0x1b, 0x86, 0x3f, 0x37, 0x3f, 0xfc, 0x37, 0x0f, 0x6f, 0x9a, 0xa1, - 0xb3, 0x90, 0x66, 0xe8, 0x7c, 0x15, 0xf3, 0xe2, 0x5c, 0x28, 0x6a, 0x51, 0xe2, 0x68, 0xa1, 0xa8, - 0xef, 0xc3, 0x7a, 0x02, 0x07, 0xb9, 0xb5, 0x73, 0xea, 0x70, 0x75, 0x1b, 0xca, 0x8a, 0x86, 0xdd, - 0x53, 0x69, 0x5b, 0x45, 0x28, 0x04, 0x03, 0x6f, 0xc2, 0x8d, 0x35, 0x58, 0x49, 0x8e, 0xaa, 0xdc, - 0x26, 0x7e, 0x2f, 0x03, 0x4d, 0xe9, 0x96, 0xe2, 0xb8, 0x67, 0x7b, 0x4e, 0x10, 0x7a, 0x7e, 0x74, - 0xf5, 0xe8, 0x5d, 0x80, 0x20, 0xb4, 0x7d, 0xa9, 0x6d, 0xca, 0xfb, 0x3f, 0x10, 0x82, 0x9a, 0xe4, - 0x6d, 0x28, 0x71, 0x77, 0x48, 0x89, 0x44, 0x0d, 0x45, 0xee, 0x0e, 0x95, 0x1e, 0x3a, 0x27, 0x7f, - 0xd7, 0x92, 0xea, 0x85, 0x0c, 0xc7, 0x17, 0xa3, 0xc3, 0x2f, 0x70, 0xe3, 0xcd, 0x47, 0xe1, 0xf8, - 0x07, 0xf6, 0x15, 0x3a, 0x79, 0x06, 0xc6, 0x3f, 0xce, 0xc2, 0x62, 0xdc, 0x3e, 0xba, 0xcb, 0xe3, - 0xc5, 0xb7, 0x92, 0xdc, 0x97, 0xe4, 0xe0, 0x08, 0xf9, 0x5d, 0x3b, 0x78, 0x2c, 0xd1, 0xe2, 0xec, - 0xb8, 0xcc, 0x80, 0x8a, 0xc2, 0xf0, 0xa6, 0xa1, 0x76, 0x03, 0x60, 0x99, 0x50, 0x0e, 0xa7, 0xa1, - 0x50, 0xb8, 0x84, 0xe6, 0xe9, 0xb8, 0x52, 0xe5, 0x29, 0xd8, 0xe3, 0xb0, 0x83, 0x0f, 0x0b, 0x08, - 0xb0, 0xc8, 0x46, 0x13, 0x29, 0xb0, 0x04, 0x7e, 0x83, 0xe4, 0x6c, 0x9a, 0x39, 0x94, 0xb1, 0x75, - 0x21, 0x94, 0xee, 0x58, 0x8e, 0x84, 0xd0, 0xd7, 0xa1, 0x42, 0x85, 0xc7, 0x91, 0xc7, 0x79, 0xb3, - 0x8c, 0x35, 0x60, 0xba, 0x3c, 0x04, 0xf2, 0xa6, 0x09, 0xd5, 0x17, 0xa8, 0x2a, 0xf4, 0xfa, 0xf8, - 0xfb, 0x19, 0xb8, 0x9d, 0x32, 0x6d, 0x72, 0x95, 0x6f, 0xc3, 0xd2, 0x69, 0x94, 0xa8, 0x46, 0x97, - 0x96, 0xfa, 0x9a, 0x62, 0xab, 0xc9, 0x31, 0x35, 0x1b, 0xa7, 0x49, 0x40, 0xac, 0x74, 0xd1, 0x0c, - 0x26, 0xe2, 0xda, 0x51, 0xe9, 0xa2, 0x69, 0x24, 0x7d, 0xe7, 0x08, 0x36, 0xda, 0x57, 0x82, 0x63, - 0x6c, 0xeb, 0x2f, 0x63, 0x28, 0x32, 0x4a, 0x1e, 0x30, 0x67, 0x5e, 0xe9, 0x80, 0x79, 0x48, 0x81, - 0xb0, 0x51, 0x59, 0x3f, 0x4d, 0x21, 0xb8, 0x81, 0x8a, 0x3c, 0xf4, 0xb2, 0x87, 0x0a, 0x70, 0x1f, - 0x44, 0x2f, 0x7a, 0x18, 0x01, 0x2c, 0x1e, 0x4c, 0x47, 0xa1, 0x13, 0x3f, 0xf2, 0xc1, 0xbe, 0x29, - 0xf3, 0x60, 0x3d, 0x6a, 0xd4, 0x52, 0x2b, 0x82, 0xa8, 0x22, 0x1c, 0xac, 0xb1, 0x28, 0xc8, 0x9a, - 0xaf, 0x6f, 0x71, 0x9c, 0xac, 0xc1, 0xb8, 0x0d, 0xeb, 0xf1, 0x17, 0x0d, 0x9b, 0xda, 0x6a, 0xfe, - 0x45, 0x86, 0x3c, 0xca, 0x93, 0x0f, 0x8e, 0xb0, 0x36, 0x2c, 0x07, 0x8e, 0x7b, 0x36, 0xe2, 0x7a, - 0xf1, 0x81, 0x1c, 0x84, 0xd5, 0x64, 0xdb, 0xe4, 0xa3, 0x24, 0xe6, 0x12, 0xe5, 0x88, 0x4b, 0x0b, - 0xd8, 0xd6, 0x4d, 0x8d, 0x8c, 0xc9, 0x62, 0x66, 0x34, 0xe6, 0x1b, 0xdf, 0x81, 0x7a, 0xb2, 0x22, - 0xf6, 0x2d, 0x19, 0x3f, 0x1e, 0xb7, 0x2a, 0x37, 0x13, 0x5c, 0x1b, 0x13, 0x44, 0x25, 0x1e, 0xfb, - 0xc0, 0xf8, 0x87, 0x19, 0x68, 0x9a, 0x5c, 0x50, 0xae, 0xd6, 0x4a, 0x45, 0x33, 0x1f, 0xce, 0x95, - 0x7a, 0x73, 0x5f, 0x55, 0x58, 0xba, 0x6a, 0xd1, 0xd7, 0x6e, 0x9c, 0x8c, 0xbd, 0x5b, 0x73, 0x3d, - 0xda, 0x2a, 0xc1, 0x02, 0xa1, 0x18, 0xeb, 0xb0, 0x2a, 0xdb, 0xa3, 0xda, 0x12, 0x5b, 0x0f, 0x13, - 0x35, 0x26, 0xac, 0x87, 0x1b, 0xd0, 0xa4, 0x40, 0x51, 0xbd, 0x13, 0x32, 0xe3, 0x0e, 0xb0, 0x03, - 0x7b, 0x60, 0xfb, 0x9e, 0xe7, 0x1e, 0x71, 0x5f, 0xfa, 0xe7, 0xa2, 0x84, 0x89, 0xc6, 0x35, 0x25, - 0x0a, 0xd3, 0x97, 0xba, 0xf7, 0xd4, 0x73, 0x95, 0x3b, 0x12, 0x7d, 0x19, 0x26, 0x2c, 0x6f, 0xd9, - 0xcf, 0xb9, 0x2a, 0x49, 0x0d, 0xd1, 0x47, 0x50, 0x99, 0x44, 0x85, 0xaa, 0x71, 0x57, 0xf7, 0x5b, - 0xcc, 0x57, 0x6b, 0xea, 0xd8, 0xc6, 0x13, 0x58, 0x49, 0x96, 0x29, 0x59, 0xc7, 0x06, 0x94, 0xc6, - 0x12, 0x26, 0x5b, 0x17, 0x7d, 0x1b, 0xbf, 0x53, 0x82, 0xa2, 0xd4, 0xe7, 0xd8, 0x26, 0xe4, 0x07, - 0xca, 0x25, 0x2c, 0xbe, 0x36, 0x49, 0xa6, 0xaa, 0xff, 0xdb, 0xe8, 0x18, 0x26, 0xf0, 0xd8, 0x47, - 0x50, 0x4f, 0x5a, 0x45, 0x67, 0xc2, 0xd0, 0x93, 0xe6, 0xcc, 0xda, 0x60, 0xc6, 0xfe, 0x55, 0x8e, - 0x37, 0x47, 0x92, 0x19, 0x4a, 0xe7, 0xda, 0xee, 0xe9, 0xb9, 0x42, 0xde, 0x0e, 0xce, 0x6d, 0xeb, - 0xc9, 0xfb, 0x1f, 0xc8, 0x38, 0xf4, 0x0a, 0x02, 0x7b, 0xe7, 0xf6, 0x93, 0xf7, 0x3f, 0x98, 0x95, - 0xa4, 0x65, 0x14, 0xba, 0x26, 0x49, 0xaf, 0x40, 0x81, 0x2e, 0xf8, 0x24, 0xdf, 0x1e, 0xfa, 0x60, - 0x8f, 0x61, 0x45, 0xaa, 0xad, 0x96, 0xf4, 0xc2, 0x26, 0x2e, 0x58, 0xa2, 0xc0, 0x37, 0x99, 0xd6, - 0xc3, 0x24, 0x3a, 0x1b, 0x5a, 0x83, 0x85, 0xf3, 0xf8, 0xb6, 0xd6, 0x9a, 0x29, 0xbf, 0x8c, 0x3f, - 0x2f, 0x40, 0x45, 0x1b, 0x14, 0x56, 0x85, 0x92, 0xd9, 0xee, 0xb5, 0xcd, 0x4f, 0xda, 0x3b, 0x8d, - 0x5b, 0xec, 0x01, 0xbc, 0xd9, 0xe9, 0x6e, 0x1f, 0x9a, 0x66, 0x7b, 0xbb, 0x6f, 0x1d, 0x9a, 0x96, - 0xba, 0xbc, 0xeb, 0xa8, 0xf5, 0xd9, 0x41, 0xbb, 0xdb, 0xb7, 0x76, 0xda, 0xfd, 0x56, 0x67, 0xbf, - 0xd7, 0xc8, 0xb0, 0xd7, 0xa0, 0x19, 0x63, 0xaa, 0xe4, 0xd6, 0xc1, 0xe1, 0x71, 0xb7, 0xdf, 0xc8, - 0xb2, 0x7b, 0x70, 0x67, 0xb7, 0xd3, 0x6d, 0xed, 0x5b, 0x31, 0xce, 0xf6, 0x7e, 0xff, 0x13, 0xab, - 0xfd, 0x2b, 0x47, 0x1d, 0xf3, 0xb3, 0x46, 0x2e, 0x0d, 0x41, 0x28, 0xe3, 0xaa, 0x84, 0x3c, 0xbb, - 0x0d, 0xab, 0x84, 0x40, 0x59, 0xac, 0xfe, 0xe1, 0xa1, 0xd5, 0x3b, 0x3c, 0xec, 0x36, 0x0a, 0x6c, - 0x09, 0x6a, 0x9d, 0xee, 0x27, 0xad, 0xfd, 0xce, 0x8e, 0x65, 0xb6, 0x5b, 0xfb, 0x07, 0x8d, 0x05, - 0xb6, 0x0c, 0x8b, 0xb3, 0x78, 0x45, 0x51, 0x84, 0xc2, 0x3b, 0xec, 0x76, 0x0e, 0xbb, 0xd6, 0x27, - 0x6d, 0xb3, 0xd7, 0x39, 0xec, 0x36, 0x4a, 0x6c, 0x0d, 0x58, 0x32, 0x69, 0xef, 0xa0, 0xb5, 0xdd, - 0x28, 0xb3, 0x55, 0x58, 0x4a, 0xc2, 0x9f, 0xb5, 0x3f, 0x6b, 0x00, 0x6b, 0xc2, 0x0a, 0x35, 0xcc, - 0xda, 0x6a, 0xef, 0x1f, 0x7e, 0x6a, 0x1d, 0x74, 0xba, 0x9d, 0x83, 0xe3, 0x83, 0x46, 0x05, 0xaf, - 0x13, 0x6c, 0xb7, 0xad, 0x4e, 0xb7, 0x77, 0xbc, 0xbb, 0xdb, 0xd9, 0xee, 0xb4, 0xbb, 0xfd, 0x46, - 0x95, 0x6a, 0x4e, 0xeb, 0x78, 0x4d, 0x64, 0x90, 0xa1, 0x1a, 0xd6, 0x4e, 0xa7, 0xd7, 0xda, 0xda, - 0x6f, 0xef, 0x34, 0xea, 0xec, 0x2e, 0xdc, 0xee, 0xb7, 0x0f, 0x8e, 0x0e, 0xcd, 0x96, 0xf9, 0x99, - 0x0a, 0xe5, 0xb0, 0x76, 0x5b, 0x9d, 0xfd, 0x63, 0xb3, 0xdd, 0x58, 0x64, 0x6f, 0xc0, 0x5d, 0xb3, - 0xfd, 0xf1, 0x71, 0xc7, 0x6c, 0xef, 0x58, 0xdd, 0xc3, 0x9d, 0xb6, 0xb5, 0xdb, 0x6e, 0xf5, 0x8f, - 0xcd, 0xb6, 0x75, 0xd0, 0xe9, 0xf5, 0x3a, 0xdd, 0xa7, 0x8d, 0x06, 0x7b, 0x13, 0xee, 0x47, 0x28, - 0x51, 0x01, 0x33, 0x58, 0x4b, 0xa2, 0x7f, 0x6a, 0x4a, 0xbb, 0xed, 0x5f, 0xe9, 0x5b, 0x47, 0xed, - 0xb6, 0xd9, 0x60, 0x6c, 0x03, 0xd6, 0xe2, 0xea, 0xa9, 0x02, 0x59, 0xf7, 0xb2, 0x48, 0x3b, 0x6a, - 0x9b, 0x07, 0xad, 0xae, 0x98, 0xe0, 0x44, 0xda, 0x8a, 0x68, 0x76, 0x9c, 0x36, 0xdb, 0xec, 0x55, - 0xc6, 0xa0, 0xae, 0xcd, 0xca, 0x6e, 0xcb, 0x6c, 0xac, 0xb1, 0x45, 0xa8, 0x1c, 0x1c, 0x1d, 0x59, - 0xfd, 0xce, 0x41, 0xfb, 0xf0, 0xb8, 0xdf, 0x58, 0x67, 0xab, 0xd0, 0xe8, 0x74, 0xfb, 0x6d, 0x53, - 0xcc, 0xb5, 0xca, 0xfa, 0xbf, 0x8a, 0x6c, 0x05, 0x16, 0x55, 0x4b, 0x15, 0xf4, 0xaf, 0x8a, 0x6c, - 0x1d, 0xd8, 0x71, 0xd7, 0x6c, 0xb7, 0x76, 0xc4, 0xc0, 0x45, 0x09, 0xff, 0xbb, 0x28, 0x2d, 0x24, - 0x3f, 0xc9, 0x45, 0x9b, 0x75, 0xec, 0x72, 0x90, 0xbc, 0xbb, 0xbb, 0xaa, 0xdd, 0xb9, 0xfd, 0xb2, - 0x57, 0x35, 0x34, 0xd5, 0x2a, 0x37, 0xa7, 0x5a, 0xcd, 0xe9, 0xee, 0x35, 0x5d, 0xf6, 0xfb, 0x0a, - 0xd4, 0xc6, 0x74, 0x8f, 0xb7, 0xbc, 0xaf, 0x17, 0xa4, 0xff, 0x0d, 0x01, 0xe9, 0xb2, 0xde, 0xb9, - 0x67, 0x25, 0x0a, 0xf3, 0xcf, 0x4a, 0xa4, 0xc9, 0xf7, 0x0b, 0x69, 0xf2, 0xfd, 0x43, 0x58, 0x22, - 0xd6, 0xe4, 0xb8, 0xce, 0x58, 0x69, 0xcd, 0x24, 0x05, 0x2e, 0x22, 0x8b, 0x22, 0xb8, 0x52, 0x27, - 0x94, 0xca, 0x21, 0x59, 0x48, 0x51, 0x6a, 0x1b, 0x09, 0x4d, 0x83, 0x38, 0x47, 0xa4, 0x69, 0x44, - 0x35, 0xd8, 0x57, 0x71, 0x0d, 0x15, 0xad, 0x06, 0x82, 0x63, 0x0d, 0x0f, 0x61, 0x89, 0x5f, 0x85, - 0xbe, 0x6d, 0x79, 0x13, 0xfb, 0xf3, 0x29, 0x9a, 0x70, 0x6d, 0xd4, 0xe1, 0xab, 0xe6, 0x22, 0x26, - 0x1c, 0x22, 0x7c, 0xc7, 0x0e, 0xed, 0x87, 0x5f, 0x40, 0x45, 0xbb, 0xe3, 0x9d, 0xad, 0xc3, 0xf2, - 0xa7, 0x9d, 0x7e, 0xb7, 0xdd, 0xeb, 0x59, 0x47, 0xc7, 0x5b, 0xcf, 0xda, 0x9f, 0x59, 0x7b, 0xad, - 0xde, 0x5e, 0xe3, 0x96, 0x58, 0xb4, 0xdd, 0x76, 0xaf, 0xdf, 0xde, 0x49, 0xc0, 0x33, 0xec, 0x75, - 0xd8, 0x38, 0xee, 0x1e, 0xf7, 0xda, 0x3b, 0x56, 0x5a, 0xbe, 0xac, 0xa0, 0x52, 0x99, 0x9e, 0x92, - 0x3d, 0xf7, 0xf0, 0x7b, 0x50, 0x4f, 0x5e, 0x3c, 0xcc, 0x00, 0x16, 0xf6, 0xdb, 0x4f, 0x5b, 0xdb, - 0x9f, 0xd1, 0x85, 0xa3, 0xbd, 0x7e, 0xab, 0xdf, 0xd9, 0xb6, 0xe4, 0x05, 0xa3, 0x82, 0x23, 0x64, - 0x58, 0x05, 0x8a, 0xad, 0xee, 0xf6, 0xde, 0xa1, 0xd9, 0x6b, 0x64, 0x1f, 0x7e, 0x07, 0xea, 0x49, - 0xef, 0xba, 0xe4, 0xb9, 0xeb, 0x06, 0xac, 0x6d, 0xb5, 0xfb, 0x9f, 0xb6, 0xdb, 0x5d, 0x6c, 0xdc, - 0x76, 0xbb, 0xdb, 0x37, 0x5b, 0xfb, 0x9d, 0xfe, 0x67, 0x8d, 0xcc, 0xc3, 0x8f, 0xa0, 0x31, 0x6b, - 0xca, 0x4a, 0xd8, 0xfe, 0x5e, 0x64, 0x24, 0x7c, 0xf8, 0xaf, 0x73, 0x00, 0x71, 0x88, 0x87, 0xe0, - 0x52, 0x3b, 0xad, 0x7e, 0x6b, 0xff, 0x50, 0x8c, 0x80, 0x79, 0xd8, 0x17, 0xcc, 0xc7, 0x6c, 0x7f, - 0xdc, 0xb8, 0x95, 0x9a, 0x72, 0x78, 0xd4, 0x6f, 0x64, 0xc4, 0x60, 0x77, 0xba, 0x9d, 0x7e, 0xa7, - 0xb5, 0x6f, 0x99, 0x87, 0xc7, 0x9d, 0xee, 0x53, 0xba, 0x84, 0x11, 0x19, 0xf4, 0xf1, 0xd1, 0xae, - 0x79, 0xd8, 0xed, 0x5b, 0xbd, 0xbd, 0xe3, 0xfe, 0x0e, 0x5e, 0xe1, 0xb8, 0x6d, 0x76, 0x8e, 0xa8, - 0xcc, 0xfc, 0x8b, 0x10, 0x44, 0xd1, 0x05, 0x31, 0x5d, 0x4f, 0x0f, 0x7b, 0xbd, 0xce, 0x91, 0xf5, - 0xf1, 0x71, 0xdb, 0xec, 0xb4, 0x7b, 0x98, 0x71, 0x21, 0x05, 0x2e, 0xf0, 0x8b, 0x82, 0xad, 0xf7, - 0xf7, 0x3f, 0x91, 0x7c, 0x57, 0xa0, 0x96, 0x92, 0x20, 0x81, 0x55, 0x16, 0x83, 0x29, 0x18, 0x57, - 0x4a, 0xc9, 0x70, 0x43, 0x9a, 0xc8, 0x57, 0x11, 0x2c, 0x79, 0x6e, 0x1e, 0x31, 0x5b, 0x35, 0x3d, - 0x49, 0xe4, 0x42, 0x6e, 0x1d, 0xed, 0x6d, 0x3b, 0x3b, 0x26, 0x66, 0xa8, 0xcf, 0x41, 0x05, 0xee, - 0xa2, 0x98, 0x28, 0xc1, 0xd9, 0x04, 0x4a, 0x43, 0x7d, 0x88, 0x94, 0xa5, 0x27, 0xbf, 0x9d, 0x83, - 0x3a, 0x85, 0xdb, 0xd1, 0xeb, 0x7c, 0xdc, 0x67, 0x07, 0x50, 0x94, 0xcf, 0x3c, 0xb2, 0xd5, 0xe8, - 0x7e, 0x3c, 0xfd, 0x61, 0xc9, 0x8d, 0xb5, 0x59, 0xb0, 0x94, 0xe4, 0x96, 0xff, 0xd6, 0x9f, 0xfd, - 0xcf, 0x7f, 0x94, 0xad, 0xb1, 0xca, 0xa3, 0x8b, 0xf7, 0x1e, 0x9d, 0x71, 0x37, 0x10, 0x65, 0xfc, - 0x1a, 0x40, 0xfc, 0x78, 0x21, 0x6b, 0x46, 0xf6, 0xab, 0x99, 0x97, 0x1d, 0x37, 0x6e, 0xa7, 0xa4, - 0xc8, 0x72, 0x6f, 0x63, 0xb9, 0xcb, 0x46, 0x5d, 0x94, 0xeb, 0xb8, 0x4e, 0x48, 0x0f, 0x19, 0x7e, - 0x98, 0x79, 0xc8, 0x86, 0x50, 0xd5, 0x9f, 0x15, 0x64, 0x4a, 0xc8, 0x4a, 0x79, 0x18, 0x71, 0xe3, - 0x4e, 0x6a, 0x9a, 0x12, 0x5f, 0xb1, 0x8e, 0x55, 0xa3, 0x21, 0xea, 0x98, 0x22, 0x46, 0x5c, 0xcb, - 0x88, 0x04, 0xfa, 0xf8, 0xf5, 0x40, 0xf6, 0x9a, 0x26, 0x92, 0xcd, 0xbd, 0x5d, 0xb8, 0x71, 0xf7, - 0x86, 0x54, 0x59, 0xd7, 0x5d, 0xac, 0x6b, 0xdd, 0x60, 0xa2, 0xae, 0x01, 0xe2, 0xa8, 0xb7, 0x0b, - 0x3f, 0xcc, 0x3c, 0x7c, 0xf2, 0x1f, 0xdf, 0x81, 0x72, 0xe4, 0x7e, 0xcb, 0x7e, 0x13, 0x6a, 0x89, - 0x78, 0x48, 0xa6, 0xba, 0x91, 0x16, 0x3e, 0xb9, 0xf1, 0x5a, 0x7a, 0xa2, 0xac, 0xf8, 0x75, 0xac, - 0xb8, 0xc9, 0xd6, 0x44, 0xc5, 0x32, 0xde, 0xf0, 0x11, 0xc6, 0x2f, 0xd3, 0x6d, 0x83, 0xcf, 0x35, - 0xc5, 0x85, 0x2a, 0x7b, 0x6d, 0x56, 0x99, 0x48, 0xd4, 0x76, 0xf7, 0x86, 0x54, 0x59, 0xdd, 0x6b, - 0x58, 0xdd, 0x1a, 0x5b, 0xd1, 0xab, 0x53, 0x5e, 0x9b, 0x8c, 0xe3, 0x0d, 0x9f, 0xfa, 0xe3, 0x7a, - 0xec, 0x6e, 0x7c, 0x1f, 0x63, 0xca, 0xa3, 0x7b, 0x11, 0x89, 0xcc, 0xbf, 0xbc, 0x67, 0x34, 0xb1, - 0x2a, 0xc6, 0x70, 0xfa, 0xf4, 0xb7, 0xf5, 0xd8, 0x09, 0x54, 0xb4, 0xf7, 0x68, 0xd8, 0xed, 0x1b, - 0xdf, 0xce, 0xd9, 0xd8, 0x48, 0x4b, 0x4a, 0xeb, 0x8a, 0x5e, 0xfe, 0xa3, 0x53, 0xce, 0xd9, 0xaf, - 0x42, 0x39, 0x7a, 0xe5, 0x84, 0xad, 0x6b, 0xaf, 0xce, 0xe8, 0xaf, 0xb2, 0x6c, 0x34, 0xe7, 0x13, - 0xd2, 0x88, 0x4f, 0x2f, 0x5d, 0x10, 0xdf, 0xa7, 0x50, 0xd1, 0x5e, 0x32, 0x89, 0x3a, 0x30, 0xff, - 0x5a, 0x4a, 0xd4, 0x81, 0x94, 0x87, 0x4f, 0x8c, 0x25, 0xac, 0xa2, 0xc2, 0xca, 0x48, 0xdf, 0xe1, - 0x95, 0x17, 0xb0, 0x7d, 0x58, 0x95, 0x4a, 0xda, 0x09, 0xff, 0x32, 0xd3, 0x90, 0xf2, 0x9e, 0xe1, - 0xe3, 0x0c, 0xfb, 0x08, 0x4a, 0xea, 0xc1, 0x1a, 0xb6, 0x96, 0xfe, 0xf0, 0xce, 0xc6, 0xfa, 0x1c, - 0x5c, 0x6a, 0x54, 0x9f, 0x01, 0xc4, 0xcf, 0xa6, 0x44, 0x4c, 0x62, 0xee, 0x19, 0x96, 0x88, 0x02, - 0xe6, 0xdf, 0x58, 0x31, 0xd6, 0xb0, 0x83, 0x0d, 0x86, 0x4c, 0xc2, 0xe5, 0x97, 0xea, 0x1a, 0xe6, - 0x1f, 0x42, 0x45, 0x7b, 0x39, 0x25, 0x1a, 0xbe, 0xf9, 0x57, 0x57, 0xa2, 0xe1, 0x4b, 0x79, 0x68, - 0xc5, 0xd8, 0xc0, 0xd2, 0x57, 0x8c, 0x45, 0x51, 0xba, 0x90, 0xd2, 0xa4, 0xb4, 0x24, 0x26, 0xe8, - 0x1c, 0x6a, 0x89, 0xe7, 0x51, 0xa2, 0x15, 0x9a, 0xf6, 0xf8, 0x4a, 0xb4, 0x42, 0x53, 0x5f, 0x54, - 0x51, 0x74, 0x66, 0x2c, 0x89, 0x7a, 0xe8, 0x26, 0x26, 0xad, 0xa6, 0x1f, 0x40, 0x45, 0x7b, 0xea, - 0x24, 0xea, 0xcb, 0xfc, 0xab, 0x2a, 0x51, 0x5f, 0xd2, 0x5e, 0x46, 0x59, 0xc1, 0x3a, 0xea, 0x06, - 0x92, 0x02, 0x5e, 0x24, 0x2b, 0xca, 0xfe, 0x4d, 0xa8, 0x27, 0x5f, 0x3f, 0x89, 0xd6, 0x7e, 0xea, - 0x33, 0x2a, 0xd1, 0xda, 0xbf, 0xe1, 0xc9, 0x14, 0x49, 0xd2, 0x0f, 0x97, 0xa3, 0x4a, 0x1e, 0xfd, - 0x58, 0x06, 0x12, 0x7d, 0xc1, 0x3e, 0x16, 0x0c, 0x4e, 0xde, 0x63, 0xcc, 0xd6, 0x35, 0xaa, 0xd5, - 0x2f, 0x44, 0x8e, 0xd6, 0xcb, 0xdc, 0x95, 0xc7, 0x49, 0x62, 0xc6, 0xc2, 0xd9, 0x53, 0x58, 0x8e, - 0x88, 0x39, 0xba, 0x98, 0x38, 0x88, 0xfa, 0x90, 0x7a, 0xfd, 0xf1, 0x46, 0x63, 0x36, 0xf5, 0x71, - 0x86, 0xb6, 0x3f, 0xbc, 0x0e, 0x56, 0xdb, 0xfe, 0xf4, 0xbb, 0x89, 0xb5, 0xed, 0x2f, 0x71, 0x6b, - 0xec, 0xec, 0xf6, 0x17, 0x3a, 0xa2, 0x0c, 0x17, 0x16, 0x67, 0xaf, 0x09, 0xbe, 0x7b, 0xd3, 0x45, - 0x0d, 0x54, 0xfc, 0xeb, 0x2f, 0xbe, 0xc7, 0x21, 0xc9, 0x8a, 0x14, 0x37, 0x7d, 0x24, 0xfd, 0x56, - 0xd8, 0xaf, 0x43, 0x55, 0x7f, 0x31, 0x81, 0xe9, 0x3c, 0x61, 0xb6, 0xa6, 0x3b, 0xa9, 0x69, 0x49, - 0x2a, 0x61, 0x55, 0xbd, 0x1a, 0xf6, 0x09, 0xac, 0x45, 0xc3, 0xac, 0xdf, 0x34, 0x10, 0xb0, 0x7b, - 0x29, 0xf7, 0x0f, 0x24, 0x06, 0xfb, 0xf6, 0x8d, 0x17, 0x14, 0x3c, 0xce, 0x08, 0xea, 0x4b, 0x5e, - 0xdd, 0x1e, 0xef, 0x3c, 0x69, 0x37, 0xd6, 0xc7, 0x3b, 0x4f, 0xea, 0x7d, 0xef, 0x8a, 0xfa, 0xd8, - 0x72, 0x62, 0x8c, 0xc8, 0xa3, 0x97, 0xfd, 0x00, 0x16, 0xb5, 0x6b, 0x14, 0x7a, 0xd7, 0xee, 0x20, - 0x5a, 0x49, 0xf3, 0x17, 0x80, 0x6e, 0xa4, 0x1d, 0x6b, 0x1a, 0xeb, 0x58, 0xfe, 0x92, 0x91, 0x18, - 0x1c, 0xb1, 0x8a, 0xb6, 0xa1, 0xa2, 0x5f, 0xd1, 0xf0, 0x82, 0x72, 0xd7, 0xb5, 0x24, 0xfd, 0xae, - 0xc9, 0xc7, 0x19, 0xb6, 0x0f, 0x8d, 0xd9, 0xeb, 0xcf, 0x22, 0x9e, 0x92, 0x76, 0x65, 0xdc, 0xc6, - 0x4c, 0x62, 0xe2, 0xd2, 0x34, 0x76, 0x44, 0x31, 0x21, 0xd1, 0xe3, 0x7f, 0x9e, 0x3f, 0xbb, 0xab, - 0x27, 0x1f, 0x05, 0x8c, 0x4a, 0x4b, 0x7b, 0x0e, 0xf2, 0x41, 0xe6, 0x71, 0x86, 0xfd, 0x6e, 0x06, - 0xaa, 0x89, 0x0b, 0x85, 0x12, 0x5e, 0xf7, 0x33, 0xfd, 0x6c, 0xea, 0x69, 0x7a, 0x47, 0x0d, 0x13, - 0x07, 0x71, 0xff, 0xe1, 0xf7, 0x13, 0x93, 0xf4, 0xe3, 0x84, 0x55, 0x70, 0x73, 0xf6, 0x75, 0xc0, - 0x2f, 0x66, 0x11, 0xf4, 0x2b, 0x65, 0xbf, 0x78, 0x9c, 0x61, 0xff, 0x36, 0x03, 0xf5, 0xa4, 0xb9, - 0x3f, 0xea, 0x6e, 0xaa, 0x63, 0x41, 0x44, 0x4a, 0x37, 0xf8, 0x08, 0xfc, 0x00, 0x5b, 0xd9, 0x7f, - 0x68, 0x26, 0x5a, 0x29, 0x1f, 0x1d, 0xf8, 0xd9, 0x5a, 0xcb, 0x3e, 0xa4, 0xc7, 0x78, 0x95, 0x17, - 0x14, 0x9b, 0x7f, 0xbc, 0x35, 0x22, 0x3f, 0xfd, 0xa9, 0x53, 0x9c, 0x84, 0x1f, 0xd2, 0x2b, 0x78, - 0xca, 0xa9, 0x46, 0x50, 0xf1, 0xab, 0xe6, 0x37, 0xde, 0xc4, 0x3e, 0xbd, 0x6e, 0xdc, 0x4e, 0xf4, - 0x69, 0x56, 0xf0, 0x68, 0x51, 0xeb, 0xe4, 0x4b, 0xa5, 0xf1, 0xce, 0x39, 0xf7, 0x7a, 0xe9, 0xcd, - 0x8d, 0x1c, 0x53, 0x23, 0x25, 0x7a, 0x62, 0xa9, 0xbd, 0x62, 0x31, 0xc6, 0x43, 0x6c, 0xeb, 0x9b, - 0xc6, 0xbd, 0x1b, 0xdb, 0xfa, 0x08, 0x4d, 0xf7, 0xa2, 0xc5, 0x47, 0x00, 0xb1, 0x97, 0x22, 0x9b, - 0xf1, 0x95, 0x8b, 0x18, 0xd0, 0xbc, 0x23, 0x63, 0x72, 0x3d, 0x2b, 0x97, 0x3a, 0x51, 0xe2, 0xaf, - 0x12, 0x3b, 0x8d, 0xbc, 0xf8, 0x74, 0xe9, 0x2b, 0xe9, 0x50, 0x98, 0x90, 0xbe, 0x66, 0xcb, 0x4f, - 0x30, 0xd3, 0xc8, 0x65, 0xef, 0x18, 0x6a, 0xfb, 0x9e, 0xf7, 0x7c, 0x3a, 0x89, 0x3c, 0xe3, 0x93, - 0xfe, 0x34, 0x7b, 0x76, 0x70, 0xbe, 0x31, 0xd3, 0x0b, 0xe3, 0x3e, 0x16, 0xb5, 0xc1, 0x9a, 0x5a, - 0x51, 0x8f, 0x7e, 0x1c, 0xbb, 0x46, 0x7e, 0xc1, 0x6c, 0x58, 0x8a, 0x78, 0x74, 0xec, 0x7e, 0x98, - 0x2c, 0x26, 0xc1, 0x99, 0x67, 0xab, 0x48, 0xa8, 0x09, 0xaa, 0xb5, 0x8f, 0x02, 0x55, 0xe6, 0xe3, - 0x0c, 0x3b, 0x82, 0xea, 0x0e, 0x1f, 0xe0, 0xd5, 0x0a, 0xe8, 0x95, 0xb2, 0x9c, 0xf0, 0x70, 0x20, - 0x77, 0x96, 0x8d, 0x5a, 0x02, 0x98, 0xdc, 0xb7, 0x26, 0xf6, 0xb5, 0xcf, 0x3f, 0x7f, 0xf4, 0x63, - 0xe9, 0xef, 0xf2, 0x85, 0xda, 0xb7, 0x94, 0x3f, 0x50, 0x62, 0xdf, 0x9a, 0x71, 0x20, 0x4a, 0xec, - 0x5b, 0x73, 0x0e, 0x44, 0x89, 0xa1, 0x56, 0xfe, 0x48, 0x6c, 0x04, 0x4b, 0x73, 0x3e, 0x47, 0xd1, - 0x96, 0x75, 0x93, 0xa7, 0xd2, 0xc6, 0xfd, 0x9b, 0x11, 0x92, 0xb5, 0x3d, 0x4c, 0xd6, 0xd6, 0x83, - 0x1a, 0xdd, 0x17, 0x7b, 0xc2, 0x29, 0xc8, 0x72, 0xe6, 0x86, 0x22, 0x3d, 0x82, 0x73, 0x76, 0x83, - 0xc1, 0xb4, 0xa4, 0x84, 0x83, 0x61, 0x76, 0xec, 0x14, 0x1f, 0x49, 0xd0, 0xa2, 0x1a, 0x23, 0x62, - 0x9c, 0x8f, 0xb4, 0x8c, 0x88, 0x31, 0x25, 0x08, 0x52, 0xa9, 0x9f, 0x6c, 0x35, 0x2a, 0xfb, 0x91, - 0xeb, 0x0d, 0xf9, 0x58, 0x96, 0xfa, 0xab, 0x50, 0x79, 0xca, 0x43, 0x15, 0x46, 0x18, 0xc9, 0xf2, - 0x33, 0x71, 0x85, 0x1b, 0x29, 0xc1, 0x9f, 0x49, 0xda, 0xa4, 0x92, 0xf9, 0xf0, 0x8c, 0x13, 0x13, - 0xb4, 0x9c, 0xe1, 0x17, 0xec, 0x57, 0xb0, 0xf0, 0x28, 0x68, 0x7e, 0x4d, 0x6b, 0xa6, 0x5e, 0xf8, - 0xe2, 0x0c, 0x3c, 0xad, 0x64, 0xd1, 0x66, 0x4d, 0xa6, 0x74, 0xa1, 0xa2, 0x5d, 0xae, 0x11, 0x8d, - 0xcd, 0xfc, 0x65, 0x2a, 0xd1, 0xd8, 0xa4, 0xdc, 0xc5, 0x61, 0x3c, 0xc0, 0x7a, 0x0c, 0x76, 0x3f, - 0xae, 0x87, 0xee, 0xdf, 0x88, 0x6b, 0x7a, 0xf4, 0x63, 0x7b, 0x1c, 0x7e, 0xc1, 0x3e, 0xa5, 0xe9, - 0xd0, 0xc2, 0x24, 0x63, 0xe5, 0x64, 0x36, 0xa2, 0x32, 0x1a, 0x2c, 0x2d, 0x29, 0xa9, 0xb0, 0x50, - 0x55, 0x28, 0x31, 0xbe, 0x0f, 0xd0, 0x0b, 0xbd, 0xc9, 0x8e, 0xcd, 0xc7, 0x9e, 0x1b, 0xf3, 0xf4, - 0x38, 0x70, 0x2f, 0xe6, 0x93, 0x5a, 0xf4, 0x1e, 0xfb, 0x54, 0xd3, 0xe6, 0x12, 0x01, 0xbe, 0x8a, - 0x88, 0x6f, 0x8c, 0xed, 0x8b, 0x06, 0x24, 0x25, 0xbe, 0xef, 0x71, 0x86, 0xb5, 0x00, 0x62, 0xe7, - 0xb6, 0x48, 0x37, 0x9b, 0xf3, 0x9b, 0x8b, 0xd8, 0x6b, 0x8a, 0x27, 0xdc, 0x11, 0x94, 0x63, 0xaf, - 0xa0, 0xf5, 0xf8, 0xae, 0xa0, 0x84, 0x0f, 0x51, 0x24, 0x29, 0xcc, 0x79, 0xe4, 0x18, 0x0d, 0x1c, - 0x2a, 0x60, 0x25, 0x31, 0x54, 0xa7, 0x9c, 0x07, 0xcc, 0x81, 0x65, 0x6a, 0x60, 0x24, 0x96, 0x61, - 0xc0, 0x59, 0xf4, 0x34, 0xc9, 0xbc, 0x73, 0x4c, 0xc4, 0x35, 0x52, 0x5d, 0x3c, 0x12, 0x47, 0x4c, - 0x82, 0x5a, 0x29, 0xd8, 0x4d, 0x6c, 0x01, 0x63, 0x58, 0x9a, 0xf3, 0x22, 0x88, 0x58, 0xc7, 0x4d, - 0x6e, 0x21, 0x11, 0xeb, 0xb8, 0xd1, 0x01, 0xc1, 0x58, 0xc5, 0x2a, 0x17, 0x0d, 0x40, 0x95, 0xf2, - 0xd2, 0x09, 0x07, 0xe7, 0xa2, 0xba, 0xdf, 0xcf, 0xc0, 0x72, 0x8a, 0x9f, 0x00, 0x7b, 0x43, 0x9d, - 0x4e, 0xdc, 0xe8, 0x43, 0xb0, 0x91, 0x6a, 0x4f, 0x36, 0x7a, 0x58, 0xcf, 0x01, 0x7b, 0x96, 0xd8, - 0x40, 0xc9, 0x9c, 0x2b, 0x57, 0xe6, 0x0b, 0x85, 0x97, 0x54, 0xc9, 0xe5, 0x73, 0x58, 0xa7, 0x86, - 0xb4, 0x46, 0xa3, 0x19, 0x5b, 0xf7, 0xeb, 0x5a, 0x2b, 0x52, 0xec, 0xf7, 0x09, 0x3d, 0x20, 0x69, - 0xc3, 0xbf, 0x41, 0x6c, 0xa7, 0xa6, 0xb2, 0x29, 0x34, 0x66, 0x6d, 0xc8, 0xec, 0xe6, 0xb2, 0x36, - 0xee, 0x25, 0xf4, 0xec, 0x14, 0xbb, 0xf3, 0x57, 0xb1, 0xb2, 0x7b, 0xc6, 0x46, 0xda, 0xb8, 0x90, - 0xea, 0x2d, 0xe6, 0xe3, 0x6f, 0x46, 0x06, 0xef, 0x99, 0x7e, 0xde, 0x8b, 0x2e, 0x63, 0x4f, 0x37, - 0xcf, 0x47, 0x9a, 0x7e, 0xba, 0xbd, 0xfc, 0x2d, 0xac, 0xfe, 0xbe, 0x71, 0x27, 0xad, 0x7a, 0x9f, - 0xb2, 0x90, 0xce, 0xbf, 0x3e, 0xbb, 0xae, 0x55, 0x0b, 0xee, 0xa7, 0xcd, 0xf7, 0x8d, 0x3a, 0xd7, - 0xcc, 0x58, 0xdf, 0x42, 0x19, 0xb2, 0xaa, 0x1b, 0xb8, 0xa3, 0xe5, 0x93, 0x62, 0x49, 0x8f, 0x96, - 0x4f, 0x9a, 0x45, 0x3c, 0x29, 0x3f, 0x29, 0x5b, 0xf8, 0x87, 0x99, 0x87, 0x5b, 0x6f, 0xff, 0xe0, - 0xab, 0x67, 0x4e, 0x78, 0x3e, 0x3d, 0xd9, 0x1c, 0x78, 0xe3, 0x47, 0x23, 0x75, 0xaa, 0x29, 0xa3, - 0xb2, 0x1f, 0x8d, 0xdc, 0xe1, 0x23, 0x2c, 0xf6, 0x64, 0x61, 0xe2, 0x7b, 0xa1, 0xf7, 0x8d, 0xff, - 0x17, 0x00, 0x00, 0xff, 0xff, 0x66, 0xe1, 0x62, 0xc2, 0xf7, 0x88, 0x00, 0x00, + 0xf8, 0xce, 0x0d, 0xb3, 0xd6, 0x4f, 0xcc, 0xc0, 0xba, 0xa4, 0x55, 0xcc, 0x99, 0x4d, 0xb8, 0x4d, + 0xa9, 0x86, 0x2b, 0x02, 0x15, 0xbf, 0x37, 0xe6, 0x20, 0x2f, 0x50, 0x8d, 0x8f, 0x61, 0x41, 0x6b, + 0x06, 0xa9, 0xf9, 0xaf, 0xdb, 0x43, 0xe3, 0xd7, 0xa2, 0xcc, 0xa2, 0x0e, 0xb2, 0x50, 0x29, 0x37, + 0x12, 0x3e, 0xa0, 0x8e, 0x4b, 0x77, 0x15, 0x02, 0x09, 0xb4, 0xd7, 0x76, 0x6d, 0xf8, 0x0d, 0x58, + 0xd4, 0x4a, 0xdf, 0x76, 0x5c, 0x7b, 0xe8, 0xfc, 0x18, 0x37, 0xfc, 0xc0, 0x39, 0x75, 0xa7, 0xca, + 0x27, 0xd0, 0x97, 0x2a, 0xff, 0x1f, 0x65, 0x61, 0x49, 0x56, 0x80, 0x8e, 0x81, 0x8e, 0x90, 0xe2, + 0xf6, 0x82, 0x53, 0xf6, 0x5d, 0xa8, 0x89, 0xb1, 0xb1, 0x7c, 0x7e, 0xea, 0x04, 0x21, 0x57, 0x96, + 0xb1, 0x14, 0xc6, 0x25, 0x36, 0x73, 0x81, 0x6a, 0x4a, 0x4c, 0xf6, 0x31, 0x54, 0x30, 0x2b, 0x1d, + 0xa3, 0xc8, 0x89, 0x68, 0xce, 0x66, 0xa4, 0x81, 0xde, 0xb9, 0x61, 0x42, 0x10, 0x0f, 0xfb, 0xc7, + 0x50, 0xc1, 0x39, 0x3c, 0xc7, 0x81, 0x9c, 0x62, 0x55, 0x33, 0x03, 0x2d, 0x32, 0x8f, 0xe3, 0x61, + 0x6f, 0x41, 0x8d, 0x98, 0x95, 0x1c, 0x27, 0xe9, 0x70, 0xb4, 0x36, 0x9b, 0x5d, 0x8d, 0xa4, 0x68, + 0xfc, 0x58, 0xfb, 0xde, 0x28, 0x43, 0x31, 0xf4, 0x9d, 0xd3, 0x53, 0xee, 0x1b, 0x2b, 0xd1, 0xd0, + 0x08, 0x2e, 0xcc, 0xbb, 0x21, 0x1f, 0x0b, 0xd9, 0xdc, 0xf8, 0x0f, 0x19, 0xa8, 0x48, 0xbe, 0xfa, + 0x33, 0x9b, 0xe3, 0xd6, 0x34, 0xcf, 0x5a, 0x3a, 0xb1, 0x89, 0x1d, 0x69, 0xdf, 0x85, 0xf9, 0x91, + 0x90, 0xd3, 0x85, 0x1e, 0x99, 0xb0, 0xc5, 0xd5, 0x15, 0x58, 0x8a, 0xc9, 0xeb, 0xb0, 0x88, 0x52, + 0x73, 0x60, 0x85, 0xce, 0xd0, 0x52, 0x89, 0xd2, 0x8b, 0x75, 0x81, 0x92, 0x7a, 0xce, 0x70, 0x4f, + 0x26, 0x08, 0xe1, 0x31, 0x08, 0xed, 0x53, 0x2e, 0xd7, 0x36, 0x7d, 0x18, 0x4d, 0x58, 0x99, 0x52, + 0x21, 0x95, 0xfa, 0xfb, 0xbf, 0x17, 0x60, 0x75, 0x26, 0x49, 0xaa, 0xc1, 0x91, 0x0d, 0x6a, 0xe8, + 0x8c, 0x8e, 0xbd, 0xe8, 0x84, 0x36, 0xa3, 0xd9, 0xa0, 0x76, 0x45, 0x8a, 0x3a, 0xa1, 0xe5, 0xb0, + 0xac, 0x08, 0x12, 0x8f, 0x58, 0x23, 0x2d, 0x33, 0x8b, 0x3a, 0xd0, 0x07, 0xc9, 0x4d, 0x6c, 0xba, + 0x3a, 0x05, 0xd7, 0x45, 0xa3, 0xc5, 0xf1, 0x0c, 0x2c, 0x60, 0xbf, 0x09, 0xcd, 0x88, 0xee, 0xa5, + 0xd8, 0xae, 0xa9, 0xcc, 0xa2, 0xa6, 0xaf, 0xbf, 0xa2, 0xa6, 0xc4, 0xd9, 0x1d, 0xca, 0x4e, 0x2b, + 0x6a, 0xc9, 0x50, 0x81, 0x51, 0x5d, 0xe7, 0xf0, 0x86, 0xaa, 0x0b, 0xc5, 0xf0, 0xd9, 0x1a, 0xf3, + 0xaf, 0xd5, 0x37, 0x3c, 0x97, 0x4c, 0x54, 0x6b, 0xde, 0x92, 0x05, 0x47, 0x49, 0x7a, 0xbd, 0x67, + 0xb0, 0x72, 0x61, 0x3b, 0xa1, 0xea, 0xa3, 0xa6, 0xb1, 0x17, 0xb0, 0xbe, 0xc7, 0xaf, 0xa8, 0xef, + 0x33, 0xca, 0x9c, 0x50, 0x4c, 0x96, 0x2e, 0x66, 0x81, 0xc1, 0xda, 0xdf, 0xcb, 0x41, 0x3d, 0x59, + 0x8a, 0x60, 0x2c, 0x72, 0xb3, 0x51, 0xf2, 0xa6, 0x14, 0x82, 0xa5, 0xf5, 0x60, 0x9f, 0xe4, 0xcc, + 0x59, 0xbb, 0x46, 0x36, 0xc5, 0xae, 0xa1, 0x9b, 0x13, 0x72, 0xaf, 0xb2, 0xdf, 0xe6, 0x5f, 0xcb, + 0x7e, 0x5b, 0x48, 0xb3, 0xdf, 0x5e, 0x6f, 0xf4, 0x9b, 0xfb, 0x99, 0x8c, 0x7e, 0xc5, 0x97, 0x18, + 0xfd, 0x12, 0xa6, 0xca, 0xd2, 0xb4, 0xa9, 0x32, 0xc5, 0xc4, 0x57, 0xfe, 0x12, 0x26, 0xbe, 0xb5, + 0xbf, 0xcc, 0x00, 0x9b, 0x5d, 0x0b, 0xec, 0x29, 0x19, 0x88, 0x5c, 0x3e, 0x94, 0x7c, 0xfa, 0x1b, + 0xaf, 0xb7, 0x9e, 0xd4, 0xf4, 0xab, 0xdc, 0xec, 0x21, 0x2c, 0xea, 0x9e, 0xf5, 0xba, 0x8e, 0x5e, + 0x33, 0x99, 0x9e, 0x14, 0x9f, 0xe4, 0x68, 0xa6, 0xf1, 0xfc, 0x2b, 0x4d, 0xe3, 0x85, 0x57, 0x9a, + 0xc6, 0xe7, 0x92, 0xa6, 0xf1, 0xb5, 0xff, 0x9c, 0x81, 0xc5, 0x14, 0x92, 0xfd, 0xea, 0xfa, 0x2c, + 0x28, 0x2d, 0xc1, 0xc4, 0xb2, 0x92, 0xd2, 0x74, 0xfe, 0xb5, 0x0b, 0x95, 0x78, 0x2a, 0x54, 0xe4, + 0xc9, 0x83, 0x57, 0xf1, 0x92, 0x38, 0x87, 0xa9, 0x67, 0x5f, 0xfb, 0xfd, 0x2c, 0x54, 0xb4, 0x44, + 0x31, 0x8a, 0x44, 0xa0, 0x9a, 0x47, 0x12, 0xc9, 0x81, 0x78, 0xc2, 0x70, 0x17, 0xa4, 0x09, 0x83, + 0xd2, 0x69, 0x29, 0x49, 0xa1, 0x0f, 0x11, 0xd6, 0x61, 0x51, 0x19, 0xef, 0x78, 0xec, 0x78, 0x28, + 0x77, 0x96, 0x05, 0x69, 0xc2, 0xe3, 0x91, 0x1f, 0x23, 0x7b, 0xa8, 0x94, 0xbf, 0x78, 0xee, 0x90, + 0xb0, 0xc9, 0x3e, 0xb0, 0x40, 0xcb, 0x41, 0x4d, 0xa2, 0xa0, 0xea, 0x0f, 0x60, 0x59, 0x2d, 0x86, + 0x64, 0x0e, 0x32, 0x19, 0x30, 0xb9, 0x14, 0xf4, 0x2c, 0xdf, 0x87, 0x3b, 0x53, 0x6d, 0x9a, 0xca, + 0x4a, 0x1e, 0xb2, 0x37, 0x13, 0xad, 0xd3, 0x4b, 0x58, 0xfb, 0x09, 0xd4, 0x12, 0x6c, 0xf1, 0xab, + 0x9b, 0xf2, 0xe9, 0x53, 0x1d, 0x1a, 0x51, 0xfd, 0x54, 0x67, 0xed, 0xff, 0xe4, 0x80, 0xcd, 0x72, + 0xe6, 0x5f, 0x64, 0x13, 0x66, 0x09, 0x33, 0x97, 0x42, 0x98, 0xff, 0xdf, 0xa4, 0x85, 0xf7, 0x61, + 0x41, 0x46, 0x60, 0x69, 0x16, 0x58, 0x5a, 0x9c, 0x8d, 0x28, 0x41, 0xb5, 0xe2, 0xdb, 0xd3, 0x9e, + 0x20, 0xa5, 0x44, 0xd0, 0x89, 0x26, 0x2e, 0x4d, 0x39, 0x84, 0x1c, 0xc1, 0x9c, 0xed, 0xf6, 0xcf, + 0x3c, 0x5f, 0xf2, 0xc1, 0x5f, 0xfa, 0xd2, 0x9b, 0xe5, 0x7a, 0x0b, 0xf3, 0xa3, 0x8c, 0x66, 0xca, + 0xc2, 0x8c, 0x0f, 0xa0, 0xa2, 0x81, 0xd1, 0x2a, 0xd9, 0xd9, 0xdb, 0x38, 0x68, 0xdc, 0x60, 0x35, + 0x28, 0x9b, 0xed, 0xcd, 0x83, 0x4f, 0xdb, 0x66, 0x7b, 0xab, 0x91, 0x61, 0x25, 0xc8, 0xef, 0x1e, + 0x74, 0x7b, 0x8d, 0xac, 0xb1, 0x06, 0x4d, 0x59, 0xe2, 0xac, 0x85, 0xe2, 0x77, 0xf2, 0xd1, 0xe1, + 0x20, 0x26, 0x4a, 0x85, 0xfc, 0x9b, 0x50, 0xd5, 0x85, 0x19, 0x49, 0x11, 0x53, 0x4e, 0x00, 0x42, + 0x15, 0xf7, 0x34, 0x5e, 0xbd, 0x09, 0x64, 0xda, 0x1d, 0x44, 0xd9, 0xb2, 0x09, 0x29, 0x35, 0xc5, + 0x16, 0x88, 0xaa, 0x4e, 0x82, 0x0c, 0xff, 0x0a, 0xd4, 0x93, 0xc7, 0xf5, 0x92, 0x23, 0xa5, 0xa9, + 0x97, 0x22, 0x77, 0xe2, 0xfc, 0x9e, 0x7d, 0x1f, 0x1a, 0xd3, 0xc7, 0xfd, 0x52, 0x54, 0xbe, 0x26, + 0xff, 0xbc, 0x93, 0xb4, 0x00, 0xb0, 0x1d, 0x58, 0x4a, 0x13, 0xe7, 0x90, 0x3e, 0xae, 0x3f, 0x92, + 0x60, 0xb3, 0x22, 0x1b, 0xfb, 0x8e, 0xb4, 0xea, 0x14, 0xd2, 0x6c, 0xe3, 0xda, 0x60, 0xaf, 0xd3, + 0x3f, 0xcd, 0xbe, 0x73, 0x0e, 0x10, 0xc3, 0x58, 0x03, 0xaa, 0x07, 0x87, 0xed, 0x7d, 0x6b, 0x73, + 0xa7, 0xb5, 0xbf, 0xdf, 0xde, 0x6d, 0xdc, 0x60, 0x0c, 0xea, 0x68, 0xd4, 0xde, 0x8a, 0x60, 0x19, + 0x01, 0x93, 0xd6, 0x35, 0x05, 0xcb, 0xb2, 0x25, 0x68, 0x74, 0xf6, 0xa7, 0xa0, 0x39, 0xd6, 0x84, + 0xa5, 0xc3, 0x36, 0xd9, 0xc1, 0x13, 0xe5, 0xe6, 0x85, 0x8a, 0x20, 0xbb, 0x2b, 0x54, 0x04, 0x8a, + 0x24, 0x94, 0xeb, 0x40, 0x49, 0xce, 0xbf, 0x9b, 0x81, 0xe5, 0xa9, 0x84, 0x38, 0x3e, 0x84, 0xe4, + 0xe6, 0xa4, 0xc4, 0x5c, 0x45, 0xa0, 0x5a, 0x4d, 0xef, 0xc3, 0x42, 0x74, 0xcc, 0x34, 0xb5, 0x2b, + 0x35, 0xa2, 0x04, 0x85, 0xfc, 0x10, 0x16, 0xb5, 0xd3, 0xaa, 0x29, 0x5e, 0xc1, 0xb4, 0x24, 0x99, + 0xc1, 0x58, 0x8d, 0xfc, 0xf0, 0xa7, 0x5a, 0x3d, 0xa0, 0xf0, 0x44, 0x3d, 0x21, 0x36, 0x7a, 0x25, + 0xdb, 0xab, 0x3e, 0xd9, 0xa3, 0x29, 0x42, 0x48, 0xb6, 0x56, 0x9f, 0x70, 0x55, 0xfd, 0x1f, 0xcc, + 0x01, 0xfb, 0x64, 0xc2, 0xfd, 0x2b, 0x8c, 0xff, 0x08, 0x5e, 0xe5, 0x10, 0xa9, 0xce, 0x55, 0xb2, + 0xaf, 0x15, 0xe3, 0x95, 0x16, 0x63, 0x95, 0x7f, 0x75, 0x8c, 0x55, 0xe1, 0x55, 0x31, 0x56, 0x6f, + 0x41, 0xcd, 0x39, 0x75, 0x3d, 0xc1, 0x0a, 0x85, 0xdc, 0x1b, 0x34, 0xe7, 0xee, 0xe5, 0xee, 0x57, + 0xcd, 0xaa, 0x04, 0x0a, 0xa9, 0x37, 0x60, 0x1f, 0xc7, 0x48, 0x7c, 0x70, 0x8a, 0xf1, 0x80, 0x3a, + 0x13, 0x6c, 0x0f, 0x4e, 0xb9, 0x3c, 0x46, 0x42, 0xbd, 0x42, 0x65, 0x16, 0xf0, 0x80, 0xbd, 0x0d, + 0xf5, 0xc0, 0x9b, 0x08, 0x35, 0x42, 0x0d, 0x03, 0x99, 0xc5, 0xaa, 0x04, 0x3d, 0x54, 0x36, 0xd0, + 0xc5, 0x49, 0xc0, 0xad, 0x91, 0x13, 0x04, 0x42, 0x3c, 0xeb, 0x7b, 0x6e, 0xe8, 0x7b, 0x43, 0x69, + 0xe9, 0x5a, 0x98, 0x04, 0x7c, 0x8f, 0x52, 0x36, 0x29, 0x81, 0x7d, 0x2b, 0x6e, 0xd2, 0xd8, 0x76, + 0xfc, 0xa0, 0x09, 0xd8, 0x24, 0xd5, 0x53, 0x94, 0xd6, 0x6d, 0xc7, 0x8f, 0xda, 0x22, 0x3e, 0x82, + 0xa9, 0xd8, 0xaf, 0xca, 0x74, 0xec, 0xd7, 0x8f, 0xd2, 0x63, 0xbf, 0x6a, 0x58, 0xf4, 0x23, 0x59, + 0xf4, 0xec, 0x14, 0x7f, 0xa9, 0x10, 0xb0, 0xd9, 0x90, 0xb6, 0xfa, 0x97, 0x09, 0x69, 0x9b, 0x4f, + 0x0b, 0x69, 0xfb, 0x00, 0x2a, 0x18, 0x6c, 0x64, 0x9d, 0x39, 0x42, 0x86, 0x23, 0xcb, 0x5d, 0x43, + 0x8f, 0x46, 0xda, 0x71, 0xdc, 0xd0, 0x04, 0x5f, 0xfd, 0x0c, 0x66, 0xa3, 0xcb, 0x16, 0x7e, 0x81, + 0xd1, 0x65, 0x32, 0x28, 0x6a, 0x1d, 0x4a, 0x6a, 0x9e, 0x18, 0x83, 0xfc, 0x89, 0xef, 0x8d, 0x94, + 0x45, 0x43, 0xfc, 0x66, 0x75, 0xc8, 0x86, 0x9e, 0xcc, 0x9c, 0x0d, 0x3d, 0xe3, 0xd7, 0xa1, 0xa2, + 0x91, 0x1a, 0x7b, 0x93, 0x4e, 0x21, 0x85, 0x26, 0x26, 0x65, 0x4b, 0x1a, 0xc5, 0xb2, 0x84, 0x76, + 0x06, 0x82, 0xdf, 0x0c, 0x1c, 0x9f, 0x63, 0x1c, 0xa8, 0xe5, 0xf3, 0x73, 0xee, 0x07, 0xca, 0xc2, + 0xd4, 0x88, 0x12, 0x4c, 0x82, 0x1b, 0xbf, 0x01, 0x8b, 0x89, 0xb9, 0x95, 0x2c, 0xe2, 0x6d, 0x98, + 0xc3, 0x71, 0x53, 0x1e, 0x00, 0xc9, 0x28, 0x2f, 0x99, 0x86, 0x01, 0xfe, 0x64, 0x1c, 0xb3, 0xc6, + 0xbe, 0x77, 0x8c, 0x95, 0x64, 0xcc, 0x8a, 0x84, 0x1d, 0xfa, 0xde, 0xb1, 0xf1, 0x67, 0x39, 0xc8, + 0xed, 0x78, 0x63, 0xdd, 0xe9, 0x2d, 0x33, 0xe3, 0xf4, 0x26, 0xd5, 0x4b, 0x2b, 0x52, 0x1f, 0xa5, + 0xcc, 0x8e, 0x66, 0x21, 0xa5, 0x42, 0xde, 0x87, 0xba, 0xe0, 0x13, 0xa1, 0x27, 0xf4, 0xf3, 0x0b, + 0xdb, 0x27, 0x81, 0x38, 0x47, 0x8b, 0xcf, 0x1e, 0x85, 0x3d, 0x6f, 0x9b, 0xe0, 0x6c, 0x09, 0x72, + 0x91, 0xfa, 0x82, 0xc9, 0xe2, 0x93, 0xad, 0xc0, 0x1c, 0x7a, 0x3f, 0x5f, 0x49, 0x13, 0xb7, 0xfc, + 0x62, 0xdf, 0x80, 0xc5, 0x64, 0xb9, 0xc4, 0x8a, 0xa4, 0x6c, 0xa4, 0x17, 0x8c, 0x3c, 0xe9, 0x26, + 0x08, 0x3e, 0x42, 0x38, 0xd2, 0x53, 0xe6, 0x84, 0x73, 0x4c, 0xd2, 0x98, 0x5e, 0x29, 0xc1, 0xf4, + 0xee, 0x42, 0x25, 0x1c, 0x9e, 0x5b, 0x63, 0xfb, 0x6a, 0xe8, 0xd9, 0x03, 0xb9, 0xbe, 0x21, 0x1c, + 0x9e, 0x1f, 0x12, 0x84, 0x3d, 0x04, 0x18, 0x8d, 0xc7, 0x72, 0xed, 0xa1, 0xa9, 0x23, 0x26, 0xe5, + 0xbd, 0xc3, 0x43, 0x22, 0x39, 0xb3, 0x3c, 0x1a, 0x8f, 0xe9, 0x27, 0xdb, 0x82, 0x7a, 0x6a, 0xac, + 0xe6, 0x1d, 0xe5, 0xac, 0xeb, 0x8d, 0xd7, 0x53, 0x16, 0x67, 0xad, 0xaf, 0xc3, 0xd6, 0xbe, 0x0f, + 0xec, 0xe7, 0x8c, 0x98, 0xec, 0x41, 0x39, 0x6a, 0x9f, 0x1e, 0x70, 0x88, 0xee, 0xf7, 0x95, 0x44, + 0xc0, 0x61, 0x6b, 0x30, 0xf0, 0x05, 0x5f, 0xa4, 0x0d, 0x33, 0x62, 0xf9, 0xa0, 0xed, 0x98, 0x2d, + 0xe2, 0xfb, 0xc6, 0x7f, 0xcb, 0x40, 0x81, 0xa2, 0x1f, 0xdf, 0x81, 0x79, 0xc2, 0x8f, 0x1c, 0x08, + 0xa5, 0x61, 0x9c, 0xf6, 0xdd, 0x9e, 0xf4, 0x1d, 0x14, 0xcb, 0x42, 0x8b, 0xdc, 0xce, 0x46, 0x33, + 0xaf, 0x45, 0x6f, 0xdf, 0x85, 0x72, 0x54, 0xb5, 0x46, 0x3a, 0x25, 0x55, 0x33, 0x7b, 0x03, 0xf2, + 0x67, 0xde, 0x58, 0x9d, 0xf3, 0x40, 0x3c, 0x92, 0x26, 0xc2, 0xe3, 0xb6, 0x88, 0x3a, 0xa8, 0xf1, + 0xf2, 0x7c, 0x22, 0xaa, 0x04, 0xc9, 0x60, 0xb6, 0x8f, 0x73, 0x29, 0x7d, 0x3c, 0x82, 0x79, 0xc1, + 0x07, 0x34, 0x07, 0x95, 0xeb, 0x37, 0xcd, 0xf7, 0x84, 0x84, 0xd7, 0x1f, 0x4e, 0x06, 0x5c, 0x3f, + 0x69, 0x43, 0x6f, 0x36, 0x09, 0x57, 0x92, 0xb5, 0xf1, 0x07, 0x19, 0xe2, 0x2f, 0xa2, 0x5c, 0x76, + 0x1f, 0xf2, 0x62, 0x7f, 0x9b, 0x3a, 0x77, 0x8f, 0xe2, 0x20, 0x04, 0x9e, 0x89, 0x18, 0x78, 0xdd, + 0xc1, 0x64, 0x94, 0x2c, 0xbd, 0x66, 0x56, 0xdc, 0xc9, 0x28, 0x3a, 0xa8, 0xfa, 0x9a, 0xea, 0xd6, + 0xd4, 0x21, 0x0f, 0xf5, 0x3e, 0x5a, 0xa6, 0xeb, 0x9a, 0x5b, 0x5c, 0x3e, 0xb1, 0x63, 0x2a, 0x29, + 0x70, 0x70, 0xca, 0x35, 0x77, 0xb8, 0x3f, 0xca, 0x42, 0x2d, 0xd1, 0x22, 0xf4, 0x0b, 0x14, 0x1b, + 0x00, 0x99, 0x91, 0xe4, 0x7c, 0x83, 0x00, 0x49, 0x41, 0x5d, 0x1b, 0xa7, 0x6c, 0x62, 0x9c, 0x22, + 0x57, 0x9c, 0x9c, 0xee, 0x8a, 0xf3, 0x08, 0xca, 0x71, 0xc4, 0x7e, 0xb2, 0x49, 0xa2, 0x3e, 0x15, + 0x0d, 0x12, 0x23, 0xc5, 0xce, 0x3b, 0x05, 0xdd, 0x79, 0xe7, 0x7b, 0x9a, 0xaf, 0xc7, 0x1c, 0x16, + 0x63, 0xa4, 0x8d, 0xe8, 0x2f, 0xc4, 0xd3, 0xc3, 0xf8, 0x18, 0x2a, 0x5a, 0xe3, 0x75, 0x9f, 0x8e, + 0x4c, 0xc2, 0xa7, 0x23, 0x8a, 0xdb, 0xca, 0xc6, 0x71, 0x5b, 0xc6, 0x6f, 0x65, 0xa1, 0x26, 0xd6, + 0x97, 0xe3, 0x9e, 0x1e, 0x7a, 0x43, 0xa7, 0x8f, 0x66, 0xa5, 0x68, 0x85, 0x49, 0x41, 0x4b, 0xad, + 0x33, 0xb9, 0xc4, 0x48, 0xce, 0xd2, 0xc3, 0x53, 0x89, 0x49, 0x47, 0xe1, 0xa9, 0x06, 0xd4, 0x04, + 0x63, 0x44, 0x03, 0x51, 0x7c, 0x9f, 0x80, 0x59, 0x39, 0xe1, 0x7c, 0xc3, 0x0e, 0x88, 0x43, 0x7e, + 0x03, 0x16, 0x05, 0x0e, 0x46, 0xe6, 0x8d, 0x9c, 0xe1, 0xd0, 0x21, 0x4c, 0x3a, 0x68, 0x6a, 0x9c, + 0x70, 0x6e, 0xda, 0x21, 0xdf, 0x13, 0x09, 0xf2, 0xfa, 0x81, 0xd2, 0xc0, 0x09, 0xec, 0xe3, 0xd8, + 0x7b, 0x33, 0xfa, 0x46, 0x3b, 0xb2, 0x7d, 0xa9, 0xd9, 0x91, 0xe9, 0x00, 0xa2, 0x32, 0xb2, 0x2f, + 0x23, 0x3b, 0xf2, 0x14, 0x25, 0x15, 0xa7, 0x29, 0xc9, 0xf8, 0x77, 0x59, 0xa8, 0x68, 0x64, 0xf9, + 0x3a, 0xbb, 0xeb, 0x9d, 0x19, 0x33, 0x60, 0x59, 0xb7, 0xf8, 0xbd, 0x95, 0xac, 0x12, 0x3d, 0x5d, + 0xe8, 0xa2, 0x03, 0x8d, 0x80, 0x6f, 0x41, 0x59, 0xac, 0xba, 0x0f, 0xf0, 0xc0, 0x55, 0x5e, 0xd3, + 0x81, 0x80, 0xc3, 0xc9, 0xb1, 0x4a, 0x7c, 0x8c, 0x89, 0x85, 0x38, 0xf1, 0xb1, 0x48, 0x7c, 0x99, + 0xcb, 0xf6, 0xb7, 0xa1, 0x2a, 0x4b, 0xc5, 0x39, 0xc5, 0xee, 0xc6, 0xab, 0x3e, 0x31, 0xdf, 0x66, + 0x85, 0xaa, 0xa3, 0xc9, 0x97, 0x19, 0x1f, 0xab, 0x8c, 0xa5, 0x57, 0x65, 0x7c, 0x4c, 0x1f, 0xc6, + 0x76, 0xe4, 0x05, 0x8f, 0x5e, 0x56, 0x8a, 0x8f, 0x3d, 0x84, 0x45, 0xc5, 0xae, 0x26, 0xae, 0xed, + 0xba, 0xde, 0xc4, 0xed, 0x73, 0x15, 0xd0, 0xc5, 0x64, 0xd2, 0x51, 0x9c, 0x62, 0x0c, 0xa2, 0x88, + 0x5f, 0xf2, 0xd6, 0x7a, 0x00, 0x05, 0x92, 0xcb, 0x49, 0xf8, 0x48, 0x67, 0x5c, 0x84, 0xc2, 0xee, + 0x43, 0x81, 0xc4, 0xf3, 0xec, 0xb5, 0xcc, 0x86, 0x10, 0x8c, 0x16, 0x30, 0x91, 0x71, 0x8f, 0x87, + 0xbe, 0xd3, 0x0f, 0xe2, 0x58, 0xb1, 0x82, 0xd0, 0x3f, 0xa9, 0xae, 0xf8, 0xe4, 0x36, 0xc6, 0x44, + 0x1d, 0x95, 0x70, 0xc4, 0xc6, 0xb4, 0x98, 0x28, 0x43, 0x8a, 0x4b, 0x43, 0x58, 0x39, 0xe6, 0xe1, + 0x05, 0xe7, 0xae, 0x2b, 0x84, 0xa1, 0x3e, 0x77, 0x43, 0xdf, 0x1e, 0x8a, 0x49, 0xa2, 0x1e, 0x3c, + 0x99, 0x29, 0x35, 0x3e, 0x03, 0xd9, 0x88, 0x33, 0x6e, 0x46, 0xf9, 0x88, 0x77, 0x2c, 0x1f, 0xa7, + 0xa5, 0xad, 0xfd, 0x1a, 0xac, 0x5d, 0x9f, 0x29, 0x25, 0x22, 0xf4, 0x7e, 0x92, 0xab, 0x44, 0x56, + 0xbf, 0xa1, 0x67, 0x87, 0xd4, 0x1a, 0x9d, 0xb3, 0xec, 0x43, 0x45, 0x4b, 0x89, 0xf7, 0xfe, 0x0c, + 0x0a, 0x77, 0xf4, 0x21, 0x76, 0x24, 0xd7, 0xf3, 0x47, 0x68, 0x65, 0x1b, 0x58, 0x71, 0xe9, 0x19, + 0x73, 0x3e, 0x86, 0x63, 0x08, 0xbc, 0xb1, 0x0e, 0xf3, 0x28, 0xd9, 0x6b, 0x1b, 0xdd, 0xcb, 0x84, + 0x41, 0x63, 0x09, 0xd8, 0x3e, 0xf1, 0x2e, 0xdd, 0x79, 0xf3, 0xbf, 0xe4, 0xa0, 0xa2, 0x81, 0xc5, + 0x6e, 0x84, 0xee, 0x7e, 0xd6, 0xc0, 0xb1, 0x47, 0x5c, 0x99, 0x34, 0x6b, 0x66, 0x0d, 0xa1, 0x5b, + 0x12, 0x28, 0xf6, 0x62, 0xfb, 0xfc, 0xd4, 0xf2, 0x26, 0xa1, 0x35, 0xe0, 0xa7, 0x3e, 0x57, 0xad, + 0xac, 0xda, 0xe7, 0xa7, 0x07, 0x93, 0x70, 0x0b, 0x61, 0x02, 0x4b, 0xf0, 0x12, 0x0d, 0x4b, 0x7a, + 0xa8, 0x8d, 0xec, 0xcb, 0x18, 0x4b, 0xba, 0x49, 0x12, 0x65, 0xe6, 0x23, 0x37, 0x49, 0xd2, 0x16, + 0xa7, 0x37, 0xd0, 0xc2, 0xec, 0x06, 0xfa, 0x2d, 0x58, 0xa1, 0x0d, 0x54, 0xb2, 0x66, 0x6b, 0x6a, + 0x25, 0x2f, 0x61, 0xaa, 0xec, 0xa4, 0x26, 0xf6, 0x36, 0x44, 0x0f, 0x14, 0x5b, 0x0a, 0x9c, 0x1f, + 0x13, 0x23, 0xcb, 0x98, 0xa2, 0x67, 0xb2, 0xf0, 0xae, 0xf3, 0x63, 0x2e, 0x30, 0xd1, 0x17, 0x46, + 0xc7, 0x94, 0x01, 0x19, 0x23, 0xc7, 0x9d, 0xc6, 0xb4, 0x2f, 0x93, 0x98, 0x65, 0x89, 0x69, 0x5f, + 0xea, 0x98, 0x4f, 0x60, 0x75, 0xc4, 0x07, 0x8e, 0x9d, 0x2c, 0xd6, 0x8a, 0x05, 0xb7, 0x25, 0x4a, + 0xd6, 0xf2, 0x74, 0x49, 0x71, 0x17, 0xa3, 0xf1, 0x63, 0x6f, 0x74, 0xec, 0x90, 0xcc, 0x42, 0xde, + 0x39, 0x79, 0xb3, 0xee, 0x4e, 0x46, 0x3f, 0x44, 0xb0, 0xc8, 0x12, 0x18, 0x35, 0xa8, 0x74, 0x43, + 0x6f, 0xac, 0xa6, 0xb9, 0x0e, 0x55, 0xfa, 0x94, 0x51, 0x92, 0xb7, 0xe0, 0x26, 0xb2, 0x84, 0x9e, + 0x37, 0xf6, 0x86, 0xde, 0xe9, 0x55, 0xe2, 0x1c, 0xef, 0x3f, 0x66, 0x60, 0x31, 0x91, 0x2a, 0xd9, + 0xeb, 0xb7, 0x88, 0x9f, 0x45, 0xa1, 0x6e, 0xb4, 0x06, 0x17, 0xb4, 0x35, 0x48, 0x88, 0xc4, 0xcc, + 0x54, 0xf8, 0x5b, 0x2b, 0xbe, 0xa2, 0x41, 0x65, 0x24, 0x96, 0xd2, 0x9c, 0x65, 0x29, 0x32, 0xbf, + 0xba, 0xbc, 0x41, 0x15, 0xf1, 0x4b, 0x32, 0x68, 0x66, 0x20, 0xbb, 0x9c, 0x4b, 0x86, 0x05, 0xe8, + 0x67, 0x7e, 0xaa, 0x05, 0xf1, 0x41, 0x60, 0x60, 0xfc, 0xf3, 0x0c, 0x40, 0xdc, 0x3a, 0x0c, 0x4c, + 0x88, 0xe4, 0x16, 0xba, 0xfd, 0x4c, 0x93, 0x51, 0xde, 0x84, 0x6a, 0xe4, 0x9f, 0x1c, 0x4b, 0x42, + 0x15, 0x05, 0x13, 0xe2, 0xd0, 0xbb, 0x30, 0x7f, 0x3a, 0xf4, 0x8e, 0x51, 0x62, 0x95, 0x72, 0x0b, + 0x79, 0xa7, 0xd5, 0x09, 0xac, 0xa4, 0x91, 0x58, 0x6e, 0xca, 0xa7, 0xba, 0x30, 0xeb, 0x52, 0x90, + 0xf1, 0xdb, 0xd9, 0xc8, 0x51, 0x33, 0x1e, 0x89, 0x97, 0xab, 0x77, 0x3f, 0x8b, 0xe7, 0xcc, 0xcb, + 0x8c, 0x89, 0x1f, 0x43, 0xdd, 0xa7, 0x4d, 0x49, 0xed, 0x58, 0xf9, 0x97, 0xec, 0x58, 0x35, 0x3f, + 0x21, 0xe9, 0xbc, 0x07, 0x0d, 0x7b, 0x70, 0xce, 0xfd, 0xd0, 0xc1, 0xd3, 0x7a, 0x94, 0x8f, 0xa5, + 0x6b, 0xa4, 0x06, 0x47, 0x41, 0xf4, 0x5d, 0x98, 0x97, 0x91, 0xbb, 0x11, 0xa6, 0xbc, 0x0b, 0x28, + 0x06, 0x0b, 0x44, 0xe3, 0x5f, 0x2a, 0xcf, 0xd0, 0xe4, 0xec, 0xbe, 0x7c, 0x54, 0xf4, 0x1e, 0x66, + 0x67, 0xcd, 0xa5, 0x92, 0x90, 0xa4, 0x11, 0x40, 0xf2, 0x23, 0x02, 0x4a, 0x13, 0x40, 0x72, 0x58, + 0xf3, 0xaf, 0x33, 0xac, 0xc6, 0x7f, 0xca, 0x40, 0x71, 0xc7, 0x1b, 0xef, 0x38, 0xe4, 0x9a, 0x8f, + 0xcb, 0x24, 0xb2, 0x51, 0xcd, 0x89, 0x4f, 0x74, 0xf3, 0x79, 0x49, 0x80, 0x5a, 0xaa, 0x98, 0x57, + 0x4b, 0x8a, 0x79, 0xdf, 0x83, 0x5b, 0x68, 0x02, 0xf4, 0xbd, 0xb1, 0xe7, 0x8b, 0xa5, 0x6a, 0x0f, + 0x49, 0xdc, 0xf3, 0xdc, 0xf0, 0x4c, 0xf1, 0xce, 0x9b, 0x27, 0x9c, 0x1f, 0x6a, 0x18, 0x7b, 0x11, + 0x02, 0x86, 0x80, 0x0e, 0xc3, 0x73, 0x8b, 0x34, 0x74, 0x29, 0x8f, 0x12, 0x47, 0x9d, 0x17, 0x09, + 0x6d, 0x84, 0xa3, 0x44, 0x6a, 0x7c, 0x07, 0xca, 0xd1, 0x61, 0x0f, 0x7b, 0x1f, 0xca, 0x67, 0xde, + 0x58, 0x9e, 0x08, 0x65, 0x12, 0x41, 0x7c, 0xb2, 0xd7, 0x66, 0xe9, 0x8c, 0x7e, 0x04, 0xc6, 0x9f, + 0x15, 0xa1, 0xd8, 0x71, 0xcf, 0x3d, 0xa7, 0x8f, 0xbe, 0xa5, 0x23, 0x3e, 0xf2, 0xd4, 0xf5, 0x01, + 0xe2, 0x37, 0x7a, 0x62, 0xc5, 0x37, 0xfa, 0xe4, 0xa4, 0x27, 0x56, 0x74, 0x97, 0xcf, 0x32, 0xcc, + 0xf9, 0xfa, 0x95, 0x3c, 0x05, 0x1f, 0xbd, 0xdd, 0xa3, 0xfd, 0xb2, 0xa0, 0x5d, 0xbf, 0x20, 0xca, + 0xa2, 0xab, 0x62, 0x70, 0xc8, 0x28, 0x9c, 0xb3, 0x8c, 0x10, 0x1c, 0xb0, 0xdb, 0x50, 0x94, 0x31, + 0x73, 0x14, 0x81, 0x44, 0xee, 0xe9, 0x12, 0x84, 0xd4, 0xe0, 0x73, 0x32, 0xe1, 0x46, 0x82, 0x6c, + 0xce, 0xac, 0x2a, 0xe0, 0x96, 0xa0, 0xb5, 0xbb, 0x50, 0x21, 0x7c, 0x42, 0x29, 0x49, 0x97, 0x4c, + 0x04, 0x21, 0x42, 0xca, 0xcd, 0x56, 0xe5, 0xd4, 0x9b, 0xad, 0xd0, 0x79, 0x38, 0xe2, 0xb2, 0xd4, + 0x45, 0xa0, 0xfb, 0x8c, 0x34, 0xb8, 0xba, 0xd6, 0x4d, 0x9e, 0xa9, 0x50, 0x74, 0xb3, 0x3a, 0x53, + 0x79, 0x0b, 0x6a, 0x27, 0xf6, 0x70, 0x78, 0x6c, 0xf7, 0x5f, 0xd0, 0x51, 0x40, 0x95, 0x4e, 0x3f, + 0x15, 0x10, 0xcf, 0x02, 0xee, 0x42, 0x45, 0x9b, 0x65, 0xf4, 0xb7, 0xcc, 0x9b, 0x10, 0xcf, 0xef, + 0xf4, 0x09, 0x5f, 0xfd, 0x35, 0x4e, 0xf8, 0x34, 0xbf, 0xd3, 0xf9, 0xa4, 0xdf, 0xe9, 0x2d, 0xe4, + 0xa6, 0xd2, 0xc1, 0xb0, 0x41, 0x97, 0xe7, 0xd8, 0x83, 0x01, 0x3a, 0x18, 0xd2, 0x4d, 0x95, 0x38, + 0x78, 0x94, 0xbe, 0x40, 0xba, 0x04, 0xc1, 0x08, 0xe5, 0x0e, 0x1d, 0x53, 0x8f, 0x6d, 0x67, 0x80, + 0x21, 0x06, 0x74, 0x7a, 0x50, 0xb4, 0x47, 0xe1, 0xa1, 0xed, 0x0c, 0xd8, 0x3d, 0xa8, 0xaa, 0x64, + 0xdc, 0x1d, 0x17, 0x69, 0xfc, 0x65, 0xb2, 0xd8, 0x13, 0x0d, 0xa8, 0x45, 0x18, 0xa3, 0x38, 0x44, + 0xb9, 0x22, 0x51, 0x90, 0x0e, 0x3e, 0x40, 0x9f, 0x9e, 0x90, 0x63, 0x20, 0x72, 0xfd, 0xf1, 0x2d, + 0xd9, 0x57, 0x49, 0xa5, 0xea, 0x3f, 0x19, 0xc7, 0x08, 0x53, 0x08, 0x77, 0x64, 0xa3, 0x5b, 0x49, + 0xc8, 0xbf, 0x12, 0x15, 0x6d, 0x74, 0x84, 0xc0, 0xbe, 0xa3, 0xe9, 0xaf, 0x4d, 0x44, 0xbe, 0x3d, + 0x55, 0xfe, 0x75, 0x11, 0x56, 0x77, 0x00, 0x9c, 0x40, 0xec, 0x32, 0x01, 0x77, 0x07, 0x18, 0x53, + 0x5c, 0x32, 0xcb, 0x4e, 0xf0, 0x8c, 0x00, 0x5f, 0xad, 0x62, 0xdb, 0x82, 0xaa, 0xde, 0x4d, 0x56, + 0x82, 0xfc, 0xc1, 0x61, 0x7b, 0xbf, 0x71, 0x83, 0x55, 0xa0, 0xd8, 0x6d, 0xf7, 0x7a, 0xbb, 0x68, + 0xe9, 0xab, 0x42, 0x29, 0x0a, 0x68, 0xcc, 0x8a, 0xaf, 0xd6, 0xe6, 0x66, 0xfb, 0xb0, 0xd7, 0xde, + 0x6a, 0xe4, 0x7e, 0x90, 0x2f, 0x65, 0x1b, 0x39, 0xe3, 0xcf, 0x73, 0x50, 0xd1, 0x46, 0xe1, 0xe5, + 0xcc, 0xf8, 0x0e, 0x00, 0x6a, 0x92, 0xb1, 0xff, 0x69, 0xde, 0x2c, 0x0b, 0x08, 0x4d, 0xbe, 0x6e, + 0xa3, 0xc8, 0xd1, 0xad, 0x4c, 0xca, 0x46, 0xf1, 0x16, 0xd4, 0xe8, 0x82, 0x23, 0xdd, 0x5e, 0x5b, + 0x30, 0xab, 0x04, 0x94, 0xac, 0x1a, 0x23, 0xa2, 0x11, 0x09, 0x63, 0xe5, 0xe4, 0x75, 0x27, 0x04, + 0xc2, 0x68, 0x39, 0x0c, 0x75, 0x0c, 0xbc, 0xe1, 0x39, 0x27, 0x0c, 0x92, 0x08, 0x2b, 0x12, 0xd6, + 0x93, 0xb1, 0xdd, 0x92, 0x1f, 0x6a, 0x21, 0xb9, 0x05, 0xb3, 0x4a, 0x40, 0x59, 0xd1, 0x37, 0x14, + 0x01, 0x95, 0x90, 0x80, 0x56, 0x67, 0xa9, 0x21, 0x41, 0x3c, 0xbb, 0x33, 0xc7, 0x88, 0x65, 0x24, + 0x8c, 0xaf, 0xcd, 0xe6, 0x7b, 0xf5, 0x71, 0x22, 0x7b, 0x1f, 0xd8, 0x68, 0x3c, 0xb6, 0x52, 0x0e, + 0xf8, 0xf2, 0xe6, 0xfc, 0x68, 0x3c, 0xee, 0x69, 0xe7, 0x5f, 0x5f, 0xc1, 0xd9, 0xe3, 0xe7, 0xc0, + 0x5a, 0x62, 0x01, 0x63, 0x13, 0x23, 0x55, 0x2c, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, 0x70, 0xbf, + 0x6c, 0x2a, 0xf7, 0x7b, 0x19, 0x9f, 0x30, 0xb6, 0xa1, 0x72, 0xa8, 0x5d, 0x9f, 0x76, 0x4f, 0xec, + 0x10, 0xea, 0xe2, 0x34, 0xda, 0x3b, 0xe8, 0x4c, 0xd1, 0x97, 0xf7, 0xa5, 0x69, 0xad, 0xc9, 0x6a, + 0xad, 0x31, 0xfe, 0x59, 0x86, 0xae, 0xa6, 0x89, 0x1a, 0x1f, 0xdf, 0xd8, 0xa6, 0xcc, 0x6f, 0x71, + 0xe4, 0x7c, 0x45, 0x99, 0xdd, 0x64, 0xd0, 0x3b, 0x36, 0xcd, 0xf2, 0x4e, 0x4e, 0x02, 0xae, 0x7c, + 0x3c, 0x2a, 0x08, 0x3b, 0x40, 0x90, 0x12, 0xbe, 0x85, 0x84, 0xef, 0x50, 0xf9, 0x81, 0x74, 0xec, + 0x10, 0xc2, 0xf7, 0x9e, 0x7d, 0x29, 0x6b, 0x0d, 0x84, 0x08, 0x22, 0xed, 0x03, 0x2a, 0xf2, 0x35, + 0xfa, 0x36, 0xfe, 0xb1, 0x0c, 0xee, 0x9f, 0x1e, 0xdf, 0x07, 0x50, 0x8a, 0x4a, 0x4d, 0xee, 0xb0, + 0x0a, 0x33, 0x4a, 0x17, 0xfb, 0x38, 0x1e, 0x86, 0x24, 0x5a, 0x4c, 0x8b, 0x0b, 0x6d, 0x3c, 0x1d, + 0xad, 0xd5, 0x5f, 0x07, 0x76, 0xe2, 0xf8, 0xd3, 0xc8, 0xb4, 0xd8, 0x1a, 0x98, 0xa2, 0x61, 0x1b, + 0x47, 0xb0, 0xa8, 0xb8, 0x84, 0xa6, 0x11, 0x24, 0x27, 0x2f, 0xf3, 0x0a, 0x26, 0x9f, 0x9d, 0x61, + 0xf2, 0xc6, 0x4f, 0xf3, 0x50, 0x54, 0x57, 0x11, 0xa6, 0x5d, 0x9f, 0x57, 0x4e, 0x5e, 0x9f, 0xd7, + 0x4c, 0x5c, 0xb5, 0x84, 0x53, 0x2f, 0xf7, 0xfb, 0x77, 0xa7, 0xb7, 0x6c, 0xcd, 0x56, 0x91, 0xd8, + 0xb6, 0x57, 0x20, 0x3f, 0xb6, 0xc3, 0x33, 0x3c, 0x97, 0x24, 0xe2, 0xc1, 0x6f, 0x65, 0xc3, 0x28, + 0x24, 0x6d, 0x18, 0x69, 0x57, 0x0d, 0x92, 0x48, 0x3a, 0x73, 0xd5, 0xe0, 0x2d, 0x20, 0xf9, 0x42, + 0x73, 0x71, 0x2b, 0x21, 0x40, 0xec, 0x45, 0x49, 0x71, 0xa4, 0x34, 0x2d, 0x8e, 0xbc, 0xb6, 0xa8, + 0xf0, 0x2d, 0x98, 0xa3, 0x6b, 0x3a, 0x64, 0x84, 0xaf, 0xda, 0x50, 0xe4, 0x18, 0xaa, 0xff, 0x14, + 0xf7, 0x60, 0x4a, 0x5c, 0xfd, 0xde, 0xae, 0x4a, 0xe2, 0xde, 0x2e, 0xdd, 0xb6, 0x52, 0x4d, 0xda, + 0x56, 0xee, 0x43, 0x23, 0x1a, 0x50, 0x3c, 0xa9, 0x74, 0x03, 0x19, 0x3f, 0x58, 0x57, 0x70, 0xc1, + 0x25, 0xf7, 0x83, 0x78, 0x43, 0xac, 0x27, 0x36, 0x44, 0xc1, 0xc3, 0x5a, 0x61, 0xc8, 0x47, 0xe3, + 0x50, 0x6e, 0x88, 0x18, 0x61, 0xa4, 0x37, 0x30, 0x19, 0xfb, 0x5e, 0x83, 0x72, 0x67, 0xdf, 0xda, + 0xde, 0xed, 0x3c, 0xdd, 0xe9, 0x35, 0x32, 0xe2, 0xb3, 0x7b, 0xb4, 0xb9, 0xd9, 0x6e, 0x6f, 0xe1, + 0x8e, 0x03, 0x30, 0xb7, 0xdd, 0xea, 0x88, 0xdd, 0x27, 0x67, 0xfc, 0x6e, 0x16, 0x2a, 0x5a, 0xf1, + 0xec, 0x49, 0x34, 0x2a, 0x74, 0xb5, 0xd3, 0x9d, 0xd9, 0x26, 0xac, 0x2b, 0x56, 0xac, 0x0d, 0x4b, + 0x74, 0xb1, 0x62, 0xf6, 0xda, 0x8b, 0x15, 0xd9, 0x3b, 0x30, 0x6f, 0x53, 0x09, 0xd1, 0x28, 0xc8, + 0x53, 0x78, 0x09, 0x96, 0x83, 0x80, 0x8e, 0x9d, 0xf1, 0x7e, 0x22, 0xf0, 0xf2, 0xca, 0x97, 0x32, + 0xda, 0x52, 0x70, 0xb0, 0x8a, 0x27, 0xb6, 0x33, 0x9c, 0xf8, 0x5c, 0x5a, 0xcd, 0xa3, 0x9d, 0x99, + 0xa0, 0xa6, 0x4a, 0x36, 0x3e, 0x04, 0x88, 0xdb, 0x9c, 0x1c, 0x9c, 0x1b, 0xc9, 0xc1, 0xc9, 0x68, + 0x83, 0x93, 0x35, 0xb6, 0x88, 0x8d, 0xc8, 0x81, 0x8e, 0x8e, 0xdd, 0xbe, 0x01, 0xea, 0x20, 0xd0, + 0x42, 0xf7, 0xea, 0xf1, 0x90, 0x87, 0xea, 0x96, 0x80, 0x05, 0x99, 0xd2, 0x89, 0x12, 0xd4, 0xa5, + 0x1d, 0x71, 0x29, 0x31, 0x37, 0x92, 0x24, 0x39, 0xcd, 0x8d, 0x24, 0xaa, 0x19, 0xa5, 0x1b, 0x6b, + 0xd0, 0xdc, 0xe2, 0xa2, 0xb4, 0xd6, 0x70, 0x38, 0xd5, 0x1c, 0xe3, 0x16, 0xdc, 0x4c, 0x49, 0x93, + 0x87, 0x10, 0x9f, 0xc0, 0x72, 0x8b, 0x2e, 0x04, 0xf8, 0xaa, 0x22, 0xff, 0x8c, 0x26, 0xac, 0x4c, + 0x17, 0x29, 0x2b, 0xdb, 0x86, 0x85, 0x2d, 0x7e, 0x3c, 0x39, 0xdd, 0xe5, 0xe7, 0x71, 0x45, 0x0c, + 0xf2, 0xc1, 0x99, 0x77, 0x21, 0xc7, 0x07, 0x7f, 0xa3, 0x97, 0xa1, 0xc0, 0xb1, 0x82, 0x31, 0xef, + 0xab, 0x83, 0x68, 0x84, 0x74, 0xc7, 0xbc, 0x6f, 0x3c, 0x01, 0xa6, 0x97, 0x23, 0xc7, 0x4b, 0x68, + 0x09, 0x93, 0x63, 0x2b, 0xb8, 0x0a, 0x42, 0x3e, 0x52, 0x11, 0x6f, 0x10, 0x4c, 0x8e, 0xbb, 0x04, + 0x31, 0xde, 0x85, 0xea, 0xa1, 0x7d, 0x65, 0xf2, 0xcf, 0x65, 0x60, 0xd9, 0x2a, 0x14, 0xc7, 0xf6, + 0x95, 0x60, 0x03, 0x91, 0x4d, 0x0a, 0x93, 0x8d, 0x3f, 0xcc, 0xc3, 0x1c, 0x61, 0xb2, 0x7b, 0x74, + 0xb9, 0xaf, 0xe3, 0xe2, 0x32, 0x54, 0x8c, 0x52, 0x03, 0xcd, 0xf0, 0xd2, 0xec, 0x2c, 0x2f, 0x95, + 0x07, 0x68, 0xea, 0x52, 0x23, 0x65, 0x3d, 0x70, 0x27, 0x23, 0x75, 0x93, 0x51, 0x32, 0x2a, 0x3e, + 0x1f, 0x5f, 0xde, 0x4c, 0x21, 0xc3, 0x49, 0xfb, 0x6e, 0xac, 0x8b, 0x50, 0xeb, 0xd4, 0x16, 0x21, + 0xd9, 0xa5, 0x0e, 0x4a, 0x55, 0x78, 0x8a, 0x2a, 0x5a, 0x32, 0xa9, 0xf0, 0xcc, 0x28, 0x36, 0xa5, + 0x57, 0x2b, 0x36, 0x74, 0xb2, 0xf6, 0x12, 0xc5, 0x06, 0x5e, 0x43, 0xb1, 0x79, 0x0d, 0xdb, 0xea, + 0x4d, 0x28, 0xe1, 0xbe, 0xaf, 0x71, 0x4f, 0xb1, 0xdf, 0x0b, 0xee, 0xf9, 0x6d, 0x4d, 0xf4, 0x27, + 0xc7, 0x8e, 0x5b, 0xf1, 0x32, 0x31, 0xf9, 0xe7, 0xbf, 0x18, 0x9b, 0xd5, 0x73, 0x28, 0x4a, 0xa8, + 0x20, 0x68, 0xd7, 0x1e, 0xa9, 0x7b, 0xe1, 0xf0, 0xb7, 0x18, 0x36, 0xbc, 0xcc, 0xea, 0xf3, 0x89, + 0xe3, 0xf3, 0x81, 0xba, 0xf0, 0xc7, 0xc1, 0x35, 0x2a, 0x20, 0xa2, 0x83, 0x42, 0x0d, 0x71, 0xbd, + 0x0b, 0x57, 0x5e, 0xf7, 0x51, 0x74, 0x82, 0x67, 0xe2, 0xd3, 0x60, 0xd0, 0xc0, 0x9b, 0x21, 0xc7, + 0x9e, 0xaf, 0x36, 0x27, 0xe3, 0xa7, 0x19, 0x68, 0xc8, 0xd5, 0x15, 0xa5, 0xe9, 0x5a, 0x40, 0xe1, + 0x3a, 0x3f, 0x84, 0x97, 0x5f, 0xdf, 0x63, 0x40, 0x0d, 0x0f, 0x3f, 0xa2, 0x9d, 0x8a, 0x0e, 0x6f, + 0x2a, 0x02, 0xb8, 0x2d, 0x77, 0xab, 0x37, 0xa0, 0xa2, 0x7c, 0xa0, 0x47, 0xce, 0x50, 0xdd, 0xd3, + 0x4e, 0x4e, 0xd0, 0x7b, 0xce, 0x50, 0x6d, 0x74, 0xbe, 0x2d, 0xa3, 0x77, 0x33, 0xb8, 0xd1, 0x99, + 0x76, 0xc8, 0x8d, 0x7f, 0x93, 0x81, 0x05, 0xad, 0x2b, 0x72, 0xdd, 0x7e, 0x04, 0xd5, 0xe8, 0x4a, + 0x56, 0x1e, 0x49, 0x5e, 0xab, 0x49, 0x46, 0x13, 0x67, 0xab, 0xf4, 0x23, 0x48, 0x20, 0x1a, 0x33, + 0xb0, 0xaf, 0xc8, 0x51, 0x77, 0x32, 0x52, 0xca, 0xcd, 0xc0, 0xbe, 0xda, 0xe6, 0xbc, 0x3b, 0x19, + 0x09, 0xd5, 0xf5, 0x82, 0xf3, 0x17, 0x11, 0x02, 0xc9, 0x5c, 0x20, 0x60, 0x12, 0xc3, 0x80, 0xda, + 0xc8, 0x73, 0xc3, 0xb3, 0x08, 0x45, 0x4a, 0x9d, 0x08, 0x24, 0x1c, 0xe3, 0x4f, 0xb3, 0xb0, 0x48, + 0x47, 0x6c, 0xf2, 0x68, 0x53, 0xb2, 0xae, 0x26, 0xcc, 0xd1, 0x69, 0x23, 0x31, 0xaf, 0x9d, 0x1b, + 0xa6, 0xfc, 0x66, 0xdf, 0x7a, 0xcd, 0x63, 0x41, 0x15, 0x20, 0x7c, 0xcd, 0xf0, 0xe7, 0x66, 0x87, + 0xff, 0xfa, 0xe1, 0x4d, 0x33, 0x74, 0x16, 0xd2, 0x0c, 0x9d, 0xaf, 0x63, 0x5e, 0x9c, 0x09, 0x65, + 0x2d, 0x4a, 0x1c, 0x2d, 0x94, 0xf5, 0x09, 0xac, 0x26, 0x70, 0x90, 0x5b, 0x3b, 0x27, 0x0e, 0x57, + 0xb7, 0xa9, 0x2c, 0x69, 0xd8, 0x5d, 0x95, 0xb6, 0x51, 0x84, 0x42, 0xd0, 0xf7, 0xc6, 0xdc, 0x58, + 0x81, 0xa5, 0xe4, 0xa8, 0xca, 0x6d, 0xe2, 0xf7, 0x32, 0xd0, 0x94, 0x6e, 0x29, 0x8e, 0x7b, 0xba, + 0xe3, 0x04, 0xa1, 0xe7, 0x47, 0x57, 0x97, 0xde, 0x01, 0x08, 0x42, 0xdb, 0x97, 0xda, 0xa6, 0xbc, + 0x3f, 0x04, 0x21, 0xa8, 0x49, 0xde, 0x84, 0x12, 0x77, 0x07, 0x94, 0x48, 0xd4, 0x50, 0xe4, 0xee, + 0x40, 0xe9, 0xa1, 0x33, 0xf2, 0x77, 0x2d, 0xa9, 0x5e, 0xc8, 0x70, 0x7e, 0x31, 0x3a, 0xfc, 0x1c, + 0x37, 0xde, 0x7c, 0x14, 0xce, 0xbf, 0x67, 0x5f, 0xa2, 0x93, 0x67, 0x60, 0xfc, 0x83, 0x2c, 0xcc, + 0xc7, 0xed, 0xa3, 0xbb, 0x40, 0x5e, 0x7e, 0xab, 0xc9, 0x3d, 0x49, 0x0e, 0x8e, 0x90, 0xdf, 0xb5, + 0x83, 0xc7, 0x12, 0x2d, 0xce, 0x8e, 0xcb, 0x0c, 0xa8, 0x28, 0x0c, 0x6f, 0x12, 0x6a, 0x37, 0x08, + 0x96, 0x09, 0xe5, 0x60, 0x12, 0x0a, 0x85, 0x4b, 0x68, 0x9e, 0x8e, 0x2b, 0x55, 0x9e, 0x82, 0x3d, + 0x0a, 0x3b, 0xf8, 0x30, 0x81, 0x00, 0x8b, 0x6c, 0x34, 0x91, 0x02, 0x4b, 0xe0, 0x37, 0x48, 0xce, + 0xa6, 0x99, 0x43, 0x19, 0x5b, 0x17, 0x42, 0xe9, 0x8e, 0xe6, 0x48, 0x08, 0x7d, 0x03, 0x2a, 0x54, + 0x78, 0x1c, 0xb9, 0x9c, 0x37, 0xcb, 0x58, 0x03, 0xa6, 0xcb, 0x43, 0x20, 0x6f, 0x92, 0x50, 0x7d, + 0x81, 0xaa, 0x42, 0xaf, 0x8f, 0xbf, 0x9d, 0x81, 0x9b, 0x29, 0xd3, 0x26, 0x57, 0xf9, 0x26, 0x2c, + 0x9c, 0x44, 0x89, 0x6a, 0x74, 0x69, 0xa9, 0xaf, 0x28, 0xb6, 0x9a, 0x1c, 0x53, 0xb3, 0x71, 0x92, + 0x04, 0xc4, 0x4a, 0x17, 0xcd, 0x60, 0x22, 0x2e, 0x1e, 0x95, 0x2e, 0x9a, 0x46, 0xd2, 0x77, 0x0e, + 0x61, 0xad, 0x7d, 0x29, 0x38, 0xc6, 0xa6, 0xfe, 0xb2, 0x86, 0x22, 0xa3, 0xe4, 0x01, 0x73, 0xe6, + 0xb5, 0x0e, 0x98, 0x07, 0x14, 0x48, 0x1b, 0x95, 0xf5, 0xb3, 0x14, 0x82, 0x1b, 0xa8, 0xc8, 0x43, + 0x2f, 0x83, 0xa8, 0x00, 0xf9, 0x7e, 0xf4, 0x22, 0x88, 0x11, 0xc0, 0xfc, 0xde, 0x64, 0x18, 0x3a, + 0xf1, 0x23, 0x21, 0xec, 0x5b, 0x32, 0x0f, 0xd6, 0xa3, 0x46, 0x2d, 0xb5, 0x22, 0x88, 0x2a, 0xc2, + 0xc1, 0x1a, 0x89, 0x82, 0xac, 0xd9, 0xfa, 0xe6, 0x47, 0xc9, 0x1a, 0x8c, 0x9b, 0xb0, 0x1a, 0x7f, + 0xd1, 0xb0, 0xa9, 0xad, 0xe6, 0x9f, 0x66, 0xc8, 0xa3, 0x3c, 0xf9, 0x60, 0x09, 0x6b, 0xc3, 0x62, + 0xe0, 0xb8, 0xa7, 0x43, 0xae, 0x17, 0x1f, 0xc8, 0x41, 0x58, 0x4e, 0xb6, 0x4d, 0x3e, 0x6a, 0x62, + 0x2e, 0x50, 0x8e, 0xb8, 0xb4, 0x80, 0x6d, 0x5c, 0xd7, 0xc8, 0x98, 0x2c, 0xa6, 0x46, 0x63, 0xb6, + 0xf1, 0x1d, 0xa8, 0x27, 0x2b, 0x62, 0xdf, 0x96, 0xf1, 0xe7, 0x71, 0xab, 0x72, 0x53, 0xc1, 0xb9, + 0x31, 0x41, 0x54, 0xe2, 0xb1, 0x0f, 0x8c, 0xbf, 0x9b, 0x81, 0xa6, 0xc9, 0x05, 0xe5, 0x6a, 0xad, + 0x54, 0x34, 0xf3, 0xd1, 0x4c, 0xa9, 0xd7, 0xf7, 0x55, 0x85, 0xb5, 0xab, 0x16, 0x7d, 0xfd, 0xda, + 0xc9, 0xd8, 0xb9, 0x31, 0xd3, 0xa3, 0x8d, 0x12, 0xcc, 0x11, 0x8a, 0xb1, 0x0a, 0xcb, 0xb2, 0x3d, + 0xaa, 0x2d, 0xb1, 0xf5, 0x30, 0x51, 0x63, 0xc2, 0x7a, 0xb8, 0x06, 0x4d, 0x0a, 0x34, 0xd5, 0x3b, + 0x21, 0x33, 0x6e, 0x01, 0xdb, 0xb3, 0xfb, 0xb6, 0xef, 0x79, 0xee, 0x21, 0xf7, 0xa5, 0x7f, 0x2e, + 0x4a, 0x98, 0x68, 0x5c, 0x53, 0xa2, 0x30, 0x7d, 0xa9, 0x7b, 0x53, 0x3d, 0x57, 0xb9, 0x23, 0xd1, + 0x97, 0x61, 0xc2, 0xe2, 0x86, 0xfd, 0x82, 0xab, 0x92, 0xd4, 0x10, 0x7d, 0x0c, 0x95, 0x71, 0x54, + 0xa8, 0x1a, 0x77, 0x75, 0x3f, 0xc6, 0x6c, 0xb5, 0xa6, 0x8e, 0x6d, 0x3c, 0x86, 0xa5, 0x64, 0x99, + 0x92, 0x75, 0xac, 0x41, 0x69, 0x24, 0x61, 0xb2, 0x75, 0xd1, 0xb7, 0xf1, 0x3b, 0x25, 0x28, 0x4a, + 0x7d, 0x8e, 0xad, 0x43, 0xbe, 0xaf, 0x5c, 0xc2, 0xe2, 0x6b, 0x97, 0x64, 0xaa, 0xfa, 0xbf, 0x89, + 0x8e, 0x61, 0x02, 0x8f, 0x7d, 0x0c, 0xf5, 0xa4, 0x55, 0x74, 0x2a, 0x8c, 0x3d, 0x69, 0xce, 0xac, + 0xf5, 0xa7, 0xec, 0x5f, 0xe5, 0x78, 0x73, 0x24, 0x99, 0xa1, 0x74, 0xa6, 0xed, 0x9e, 0x9e, 0x2b, + 0xe4, 0xed, 0xe0, 0xcc, 0xb6, 0x1e, 0x3f, 0xf9, 0x50, 0xc6, 0xb1, 0x57, 0x10, 0xd8, 0x3d, 0xb3, + 0x1f, 0x3f, 0xf9, 0x70, 0x5a, 0x92, 0x96, 0x51, 0xec, 0x9a, 0x24, 0xbd, 0x04, 0x05, 0xba, 0x20, + 0x94, 0x7c, 0x7b, 0xe8, 0x83, 0x3d, 0x82, 0x25, 0xa9, 0xb6, 0x5a, 0xd2, 0x0b, 0x9b, 0xb8, 0x60, + 0x89, 0x02, 0xdf, 0x64, 0x5a, 0x17, 0x93, 0xe8, 0x6c, 0x68, 0x05, 0xe6, 0xce, 0xe2, 0xdb, 0x5e, + 0x6b, 0xa6, 0xfc, 0x32, 0xfe, 0xb4, 0x00, 0x15, 0x6d, 0x50, 0x58, 0x15, 0x4a, 0x66, 0xbb, 0xdb, + 0x36, 0x3f, 0x6d, 0x6f, 0x35, 0x6e, 0xb0, 0xfb, 0xf0, 0x76, 0x67, 0x7f, 0xf3, 0xc0, 0x34, 0xdb, + 0x9b, 0x3d, 0xeb, 0xc0, 0xb4, 0xd4, 0xe5, 0x5f, 0x87, 0xad, 0xe7, 0x7b, 0xed, 0xfd, 0x9e, 0xb5, + 0xd5, 0xee, 0xb5, 0x3a, 0xbb, 0xdd, 0x46, 0x86, 0xdd, 0x86, 0x66, 0x8c, 0xa9, 0x92, 0x5b, 0x7b, + 0x07, 0x47, 0xfb, 0xbd, 0x46, 0x96, 0xdd, 0x85, 0x5b, 0xdb, 0x9d, 0xfd, 0xd6, 0xae, 0x15, 0xe3, + 0x6c, 0xee, 0xf6, 0x3e, 0xb5, 0xda, 0xbf, 0x72, 0xd8, 0x31, 0x9f, 0x37, 0x72, 0x69, 0x08, 0x42, + 0x19, 0x57, 0x25, 0xe4, 0xd9, 0x4d, 0x58, 0x26, 0x04, 0xca, 0x62, 0xf5, 0x0e, 0x0e, 0xac, 0xee, + 0xc1, 0xc1, 0x7e, 0xa3, 0xc0, 0x16, 0xa0, 0xd6, 0xd9, 0xff, 0xb4, 0xb5, 0xdb, 0xd9, 0xb2, 0xcc, + 0x76, 0x6b, 0x77, 0xaf, 0x31, 0xc7, 0x16, 0x61, 0x7e, 0x1a, 0xaf, 0x28, 0x8a, 0x50, 0x78, 0x07, + 0xfb, 0x9d, 0x83, 0x7d, 0xeb, 0xd3, 0xb6, 0xd9, 0xed, 0x1c, 0xec, 0x37, 0x4a, 0x6c, 0x05, 0x58, + 0x32, 0x69, 0x67, 0xaf, 0xb5, 0xd9, 0x28, 0xb3, 0x65, 0x58, 0x48, 0xc2, 0x9f, 0xb5, 0x9f, 0x37, + 0x80, 0x35, 0x61, 0x89, 0x1a, 0x66, 0x6d, 0xb4, 0x77, 0x0f, 0x3e, 0xb3, 0xf6, 0x3a, 0xfb, 0x9d, + 0xbd, 0xa3, 0xbd, 0x46, 0x05, 0xaf, 0x23, 0x6c, 0xb7, 0xad, 0xce, 0x7e, 0xf7, 0x68, 0x7b, 0xbb, + 0xb3, 0xd9, 0x69, 0xef, 0xf7, 0x1a, 0x55, 0xaa, 0x39, 0xad, 0xe3, 0x35, 0x91, 0x41, 0x86, 0x6a, + 0x58, 0x5b, 0x9d, 0x6e, 0x6b, 0x63, 0xb7, 0xbd, 0xd5, 0xa8, 0xb3, 0x3b, 0x70, 0xb3, 0xd7, 0xde, + 0x3b, 0x3c, 0x30, 0x5b, 0xe6, 0x73, 0x15, 0xca, 0x61, 0x6d, 0xb7, 0x3a, 0xbb, 0x47, 0x66, 0xbb, + 0x31, 0xcf, 0xde, 0x84, 0x3b, 0x66, 0xfb, 0x93, 0xa3, 0x8e, 0xd9, 0xde, 0xb2, 0xf6, 0x0f, 0xb6, + 0xda, 0xd6, 0x76, 0xbb, 0xd5, 0x3b, 0x32, 0xdb, 0xd6, 0x5e, 0xa7, 0xdb, 0xed, 0xec, 0x3f, 0x6d, + 0x34, 0xd8, 0xdb, 0x70, 0x2f, 0x42, 0x89, 0x0a, 0x98, 0xc2, 0x5a, 0x10, 0xfd, 0x53, 0x53, 0xba, + 0xdf, 0xfe, 0x95, 0x9e, 0x75, 0xd8, 0x6e, 0x9b, 0x0d, 0xc6, 0xd6, 0x60, 0x25, 0xae, 0x9e, 0x2a, + 0x90, 0x75, 0x2f, 0x8a, 0xb4, 0xc3, 0xb6, 0xb9, 0xd7, 0xda, 0x17, 0x13, 0x9c, 0x48, 0x5b, 0x12, + 0xcd, 0x8e, 0xd3, 0xa6, 0x9b, 0xbd, 0xcc, 0x18, 0xd4, 0xb5, 0x59, 0xd9, 0x6e, 0x99, 0x8d, 0x15, + 0x36, 0x0f, 0x95, 0xbd, 0xc3, 0x43, 0xab, 0xd7, 0xd9, 0x6b, 0x1f, 0x1c, 0xf5, 0x1a, 0xab, 0x6c, + 0x19, 0x1a, 0x9d, 0xfd, 0x5e, 0xdb, 0x14, 0x73, 0xad, 0xb2, 0xfe, 0xcf, 0x22, 0x5b, 0x82, 0x79, + 0xd5, 0x52, 0x05, 0xfd, 0x8b, 0x22, 0x5b, 0x05, 0x76, 0xb4, 0x6f, 0xb6, 0x5b, 0x5b, 0x62, 0xe0, + 0xa2, 0x84, 0xff, 0x55, 0x94, 0x16, 0x92, 0x9f, 0xe6, 0xa2, 0xcd, 0x3a, 0x76, 0x39, 0x48, 0xde, + 0xfd, 0x5d, 0xd5, 0xee, 0xec, 0x7e, 0xd5, 0xab, 0x1c, 0x9a, 0x6a, 0x95, 0x9b, 0x51, 0xad, 0x66, + 0x74, 0xf7, 0x9a, 0x2e, 0xfb, 0xbd, 0x05, 0xb5, 0x11, 0xdd, 0x03, 0x2e, 0xef, 0xfb, 0x05, 0xe9, + 0x7f, 0x43, 0x40, 0xba, 0xec, 0x77, 0xe6, 0x59, 0x8a, 0xc2, 0xec, 0xb3, 0x14, 0x69, 0xf2, 0xfd, + 0x5c, 0x9a, 0x7c, 0xff, 0x00, 0x16, 0x88, 0x35, 0x39, 0xae, 0x33, 0x52, 0x5a, 0x33, 0x49, 0x81, + 0xf3, 0xc8, 0xa2, 0x08, 0xae, 0xd4, 0x09, 0xa5, 0x72, 0x48, 0x16, 0x52, 0x94, 0xda, 0x46, 0x42, + 0xd3, 0x20, 0xce, 0x11, 0x69, 0x1a, 0x51, 0x0d, 0xf6, 0x65, 0x5c, 0x43, 0x45, 0xab, 0x81, 0xe0, + 0x58, 0xc3, 0x03, 0x58, 0xe0, 0x97, 0xa1, 0x6f, 0x5b, 0xde, 0xd8, 0xfe, 0x7c, 0x82, 0x26, 0x5c, + 0x1b, 0x75, 0xf8, 0xaa, 0x39, 0x8f, 0x09, 0x07, 0x08, 0xdf, 0xb2, 0x43, 0xfb, 0xc1, 0x17, 0x50, + 0xd1, 0xee, 0x88, 0x67, 0xab, 0xb0, 0xf8, 0x59, 0xa7, 0xb7, 0xdf, 0xee, 0x76, 0xad, 0xc3, 0xa3, + 0x8d, 0x67, 0xed, 0xe7, 0xd6, 0x4e, 0xab, 0xbb, 0xd3, 0xb8, 0x21, 0x16, 0xed, 0x7e, 0xbb, 0xdb, + 0x6b, 0x6f, 0x25, 0xe0, 0x19, 0xf6, 0x06, 0xac, 0x1d, 0xed, 0x1f, 0x75, 0xdb, 0x5b, 0x56, 0x5a, + 0xbe, 0xac, 0xa0, 0x52, 0x99, 0x9e, 0x92, 0x3d, 0xf7, 0xe0, 0x37, 0xa0, 0x9e, 0x8c, 0x6a, 0x66, + 0x00, 0x73, 0xbb, 0xed, 0xa7, 0xad, 0xcd, 0xe7, 0x74, 0x61, 0x69, 0xb7, 0xd7, 0xea, 0x75, 0x36, + 0x2d, 0x79, 0x41, 0xa9, 0xe0, 0x08, 0x19, 0x56, 0x81, 0x62, 0x6b, 0x7f, 0x73, 0xe7, 0xc0, 0xec, + 0x36, 0xb2, 0xec, 0x36, 0xac, 0x2a, 0x5a, 0xdd, 0x3c, 0xd8, 0xdb, 0xeb, 0xf4, 0x90, 0x19, 0xf6, + 0x9e, 0x1f, 0x0a, 0xd2, 0x7c, 0xf0, 0x5d, 0xa8, 0x27, 0x7d, 0xef, 0x92, 0xa7, 0xb2, 0x6b, 0xb0, + 0xb2, 0xd1, 0xee, 0x7d, 0xd6, 0x6e, 0xef, 0x63, 0xd3, 0x37, 0xdb, 0xfb, 0x3d, 0xb3, 0xb5, 0xdb, + 0xe9, 0x3d, 0x6f, 0x64, 0x1e, 0x7c, 0x0c, 0x8d, 0x69, 0x43, 0x57, 0xc2, 0x32, 0xf8, 0x32, 0x13, + 0xe2, 0x83, 0x7f, 0x91, 0x03, 0x88, 0x03, 0x40, 0x04, 0x0f, 0xdb, 0x6a, 0xf5, 0x5a, 0xbb, 0x07, + 0x62, 0x7c, 0xcc, 0x83, 0x9e, 0x60, 0x4d, 0x66, 0xfb, 0x93, 0xc6, 0x8d, 0xd4, 0x94, 0x83, 0xc3, + 0x5e, 0x23, 0x23, 0xa6, 0xa2, 0xb3, 0xdf, 0xe9, 0x75, 0x5a, 0xbb, 0x96, 0x79, 0x70, 0xd4, 0xd9, + 0x7f, 0x4a, 0x57, 0x3c, 0x22, 0xfb, 0x3e, 0x3a, 0xdc, 0x36, 0x0f, 0xf6, 0x7b, 0x56, 0x77, 0xe7, + 0xa8, 0xb7, 0x85, 0x17, 0x44, 0x6e, 0x9a, 0x9d, 0x43, 0x2a, 0x33, 0xff, 0x32, 0x04, 0x51, 0x74, + 0x41, 0x4c, 0xe6, 0xd3, 0x83, 0x6e, 0xb7, 0x73, 0x68, 0x7d, 0x72, 0xd4, 0x36, 0x3b, 0xed, 0x2e, + 0x66, 0x9c, 0x4b, 0x81, 0x0b, 0xfc, 0xa2, 0x60, 0xfa, 0xbd, 0xdd, 0x4f, 0x25, 0x57, 0x16, 0xa8, + 0xa5, 0x24, 0x48, 0x60, 0x95, 0xc5, 0x60, 0x0a, 0xb6, 0x96, 0x52, 0x32, 0x5c, 0x93, 0x26, 0xf2, + 0x55, 0x04, 0xc3, 0x9e, 0x99, 0x65, 0xcc, 0x56, 0x4d, 0x4f, 0x12, 0xb9, 0x90, 0x97, 0x47, 0x3b, + 0xdf, 0xd6, 0x96, 0x89, 0x19, 0xea, 0x33, 0x50, 0x81, 0x3b, 0x2f, 0x26, 0x4a, 0xf0, 0x3d, 0x81, + 0xd2, 0x50, 0x1f, 0x22, 0x65, 0xe1, 0xf1, 0x6f, 0xe7, 0xa0, 0x4e, 0xc1, 0x78, 0xf4, 0xf6, 0x1f, + 0xf7, 0xd9, 0x1e, 0x14, 0xe5, 0x23, 0x92, 0x6c, 0x39, 0xba, 0x7d, 0x4f, 0x7f, 0xb6, 0x72, 0x6d, + 0x65, 0x1a, 0x2c, 0xe5, 0xbc, 0xc5, 0xbf, 0xf6, 0x27, 0xff, 0xe3, 0xef, 0x67, 0x6b, 0xac, 0xf2, + 0xf0, 0xfc, 0x83, 0x87, 0xa7, 0xdc, 0x0d, 0x44, 0x19, 0xbf, 0x06, 0x10, 0x3f, 0x8d, 0xc8, 0x9a, + 0x91, 0x75, 0x6b, 0xea, 0xdd, 0xc8, 0xb5, 0x9b, 0x29, 0x29, 0xb2, 0xdc, 0x9b, 0x58, 0xee, 0xa2, + 0x51, 0x17, 0xe5, 0x3a, 0xae, 0x13, 0xd2, 0x33, 0x89, 0x1f, 0x65, 0x1e, 0xb0, 0x01, 0x54, 0xf5, + 0x47, 0x0b, 0x99, 0x12, 0xc1, 0x52, 0x9e, 0x5d, 0x5c, 0xbb, 0x95, 0x9a, 0xa6, 0x84, 0x5b, 0xac, + 0x63, 0xd9, 0x68, 0x88, 0x3a, 0x26, 0x88, 0x11, 0xd7, 0x32, 0x24, 0x71, 0x3f, 0x7e, 0x9b, 0x90, + 0xdd, 0xd6, 0x04, 0xb6, 0x99, 0x97, 0x11, 0xd7, 0xee, 0x5c, 0x93, 0x2a, 0xeb, 0xba, 0x83, 0x75, + 0xad, 0x1a, 0x4c, 0xd4, 0xd5, 0x47, 0x1c, 0xf5, 0x32, 0xe2, 0x47, 0x99, 0x07, 0x8f, 0xff, 0xfd, + 0x7b, 0x50, 0x8e, 0x9c, 0x73, 0xd9, 0x6f, 0x42, 0x2d, 0x11, 0x2d, 0xc9, 0x54, 0x37, 0xd2, 0x82, + 0x2b, 0xd7, 0x6e, 0xa7, 0x27, 0xca, 0x8a, 0xdf, 0xc0, 0x8a, 0x9b, 0x6c, 0x45, 0x54, 0x2c, 0xa3, + 0x11, 0x1f, 0x62, 0x74, 0x33, 0xdd, 0x65, 0xf8, 0x42, 0x53, 0x6b, 0xa8, 0xb2, 0xdb, 0xd3, 0xaa, + 0x46, 0xa2, 0xb6, 0x3b, 0xd7, 0xa4, 0xca, 0xea, 0x6e, 0x63, 0x75, 0x2b, 0x6c, 0x49, 0xaf, 0x4e, + 0xf9, 0x74, 0x32, 0x8e, 0xf7, 0x87, 0xea, 0x4f, 0xf7, 0xb1, 0x3b, 0xf1, 0x6d, 0x8f, 0x29, 0x4f, + 0xfa, 0x45, 0x24, 0x32, 0xfb, 0xae, 0x9f, 0xd1, 0xc4, 0xaa, 0x18, 0xc3, 0xe9, 0xd3, 0x5f, 0xee, + 0x63, 0xc7, 0x50, 0xd1, 0x5e, 0xbb, 0x61, 0x37, 0xaf, 0x7d, 0x99, 0x67, 0x6d, 0x2d, 0x2d, 0x29, + 0xad, 0x2b, 0x7a, 0xf9, 0x0f, 0x4f, 0x38, 0x67, 0xbf, 0x0a, 0xe5, 0xe8, 0x0d, 0x15, 0xb6, 0xaa, + 0xbd, 0x69, 0xa3, 0xbf, 0xf9, 0xb2, 0xd6, 0x9c, 0x4d, 0x48, 0x23, 0x3e, 0xbd, 0x74, 0x41, 0x7c, + 0x9f, 0x41, 0x45, 0x7b, 0x27, 0x25, 0xea, 0xc0, 0xec, 0x5b, 0x2c, 0x51, 0x07, 0x52, 0x9e, 0x55, + 0x31, 0x16, 0xb0, 0x8a, 0x0a, 0x2b, 0x23, 0x7d, 0x87, 0x97, 0x5e, 0xc0, 0x76, 0x61, 0x59, 0xaa, + 0x70, 0xc7, 0xfc, 0xcb, 0x4c, 0x43, 0xca, 0x6b, 0x89, 0x8f, 0x32, 0xec, 0x63, 0x28, 0xa9, 0xe7, + 0x70, 0xd8, 0x4a, 0xfa, 0xb3, 0x3e, 0x6b, 0xab, 0x33, 0x70, 0xa9, 0x6f, 0x3d, 0x07, 0x88, 0x1f, + 0x65, 0x89, 0x98, 0xc4, 0xcc, 0x23, 0x2f, 0x11, 0x05, 0xcc, 0xbe, 0xe0, 0x62, 0xac, 0x60, 0x07, + 0x1b, 0x0c, 0x99, 0x84, 0xcb, 0x2f, 0xd4, 0x25, 0xcf, 0x3f, 0x82, 0x8a, 0xf6, 0x2e, 0x4b, 0x34, + 0x7c, 0xb3, 0x6f, 0xba, 0x44, 0xc3, 0x97, 0xf2, 0x8c, 0x8b, 0xb1, 0x86, 0xa5, 0x2f, 0x19, 0xf3, + 0xa2, 0x74, 0x21, 0xc3, 0x49, 0x59, 0x4a, 0x4c, 0xd0, 0x19, 0xd4, 0x12, 0x8f, 0xaf, 0x44, 0x2b, + 0x34, 0xed, 0x69, 0x97, 0x68, 0x85, 0xa6, 0xbe, 0xd7, 0xa2, 0xe8, 0xcc, 0x58, 0x10, 0xf5, 0xd0, + 0x3d, 0x4f, 0x5a, 0x4d, 0x3f, 0x84, 0x8a, 0xf6, 0x90, 0x4a, 0xd4, 0x97, 0xd9, 0x37, 0x5b, 0xa2, + 0xbe, 0xa4, 0xbd, 0xbb, 0xb2, 0x84, 0x75, 0xd4, 0x0d, 0x24, 0x05, 0xbc, 0xa6, 0x56, 0x94, 0xfd, + 0x9b, 0x50, 0x4f, 0xbe, 0xad, 0x12, 0xad, 0xfd, 0xd4, 0x47, 0x5a, 0xa2, 0xb5, 0x7f, 0xcd, 0x83, + 0x2c, 0x92, 0xa4, 0x1f, 0x2c, 0x46, 0x95, 0x3c, 0xfc, 0x89, 0x0c, 0x33, 0xfa, 0x82, 0x7d, 0x22, + 0x18, 0x9c, 0xbc, 0x25, 0x99, 0xad, 0x6a, 0x54, 0xab, 0x5f, 0xb7, 0x1c, 0xad, 0x97, 0x99, 0x0b, + 0x95, 0x93, 0xc4, 0x8c, 0x85, 0xb3, 0xa7, 0xb0, 0x18, 0x11, 0x73, 0x74, 0xed, 0x71, 0x10, 0xf5, + 0x21, 0xf5, 0x72, 0xe5, 0xb5, 0xc6, 0x74, 0xea, 0xa3, 0x0c, 0x6d, 0x7f, 0x78, 0xd9, 0xac, 0xb6, + 0xfd, 0xe9, 0x37, 0x1f, 0x6b, 0xdb, 0x5f, 0xe2, 0x4e, 0xda, 0xe9, 0xed, 0x2f, 0x74, 0x44, 0x19, + 0x2e, 0xcc, 0x4f, 0x5f, 0x42, 0x7c, 0xe7, 0xba, 0x6b, 0x1c, 0xa8, 0xf8, 0x37, 0x5e, 0x7e, 0xcb, + 0x43, 0x92, 0x15, 0x29, 0x6e, 0xfa, 0x50, 0x7a, 0xb5, 0xb0, 0x5f, 0x87, 0xaa, 0xfe, 0x1e, 0x03, + 0xd3, 0x79, 0xc2, 0x74, 0x4d, 0xb7, 0x52, 0xd3, 0x92, 0x54, 0xc2, 0xaa, 0x7a, 0x35, 0xec, 0x53, + 0x58, 0x89, 0x86, 0x59, 0xbf, 0x87, 0x20, 0x60, 0x77, 0x53, 0x6e, 0x27, 0x48, 0x0c, 0xf6, 0xcd, + 0x6b, 0xaf, 0x2f, 0x78, 0x94, 0x11, 0xd4, 0x97, 0xbc, 0x18, 0x3e, 0xde, 0x79, 0xd2, 0xee, 0xc3, + 0x8f, 0x77, 0x9e, 0xd4, 0xdb, 0xe4, 0x15, 0xf5, 0xb1, 0xc5, 0xc4, 0x18, 0x91, 0xbf, 0x2f, 0xfb, + 0x21, 0xcc, 0x6b, 0x97, 0x2c, 0x74, 0xaf, 0xdc, 0x7e, 0xb4, 0x92, 0x66, 0xaf, 0x17, 0x5d, 0x4b, + 0x3b, 0xf4, 0x34, 0x56, 0xb1, 0xfc, 0x05, 0x23, 0x31, 0x38, 0x62, 0x15, 0x6d, 0x42, 0x45, 0xbf, + 0xc0, 0xe1, 0x25, 0xe5, 0xae, 0x6a, 0x49, 0xfa, 0x4d, 0x96, 0x8f, 0x32, 0x6c, 0x17, 0x1a, 0xd3, + 0x97, 0xab, 0x45, 0x3c, 0x25, 0xed, 0x42, 0xba, 0xb5, 0xa9, 0xc4, 0xc4, 0x95, 0x6c, 0xec, 0x90, + 0x22, 0x46, 0xa2, 0xa7, 0x05, 0x3d, 0x7f, 0x7a, 0x57, 0x4f, 0x3e, 0x39, 0x18, 0x95, 0x96, 0xf6, + 0xd8, 0xe4, 0xfd, 0xcc, 0xa3, 0x0c, 0xfb, 0xdd, 0x0c, 0x54, 0x13, 0xd7, 0x0d, 0x25, 0x7c, 0xf2, + 0xa7, 0xfa, 0xd9, 0xd4, 0xd3, 0xf4, 0x8e, 0x1a, 0x26, 0x0e, 0xe2, 0xee, 0x83, 0x1f, 0x24, 0x26, + 0xe9, 0x27, 0x09, 0x9b, 0xe1, 0xfa, 0xf4, 0xdb, 0x83, 0x5f, 0x4c, 0x23, 0xe8, 0x17, 0xd6, 0x7e, + 0xf1, 0x28, 0xc3, 0xfe, 0x55, 0x06, 0xea, 0x49, 0x67, 0x80, 0xa8, 0xbb, 0xa9, 0x6e, 0x07, 0x11, + 0x29, 0x5d, 0xe3, 0x41, 0xf0, 0x43, 0x6c, 0x65, 0xef, 0x81, 0x99, 0x68, 0xa5, 0x7c, 0xd2, 0xe0, + 0xe7, 0x6b, 0x2d, 0xfb, 0x88, 0x9e, 0xfa, 0x55, 0x3e, 0x52, 0x6c, 0xf6, 0x69, 0xd8, 0x88, 0xfc, + 0xf4, 0x87, 0x54, 0x71, 0x12, 0x7e, 0x44, 0x6f, 0xec, 0x29, 0x97, 0x1b, 0x41, 0xc5, 0xaf, 0x9b, + 0xdf, 0x78, 0x1b, 0xfb, 0xf4, 0x86, 0x71, 0x33, 0xd1, 0xa7, 0x69, 0xc1, 0xa3, 0x45, 0xad, 0x93, + 0xef, 0xa0, 0xc6, 0x3b, 0xe7, 0xcc, 0xdb, 0xa8, 0xd7, 0x37, 0x72, 0x44, 0x8d, 0x94, 0xe8, 0x89, + 0xa5, 0xf6, 0x9a, 0xc5, 0x18, 0x0f, 0xb0, 0xad, 0x6f, 0x1b, 0x77, 0xaf, 0x6d, 0xeb, 0x43, 0x34, + 0xec, 0x8b, 0x16, 0x1f, 0x02, 0xc4, 0x3e, 0x8c, 0x6c, 0xca, 0x93, 0x2e, 0x62, 0x40, 0xb3, 0x6e, + 0x8e, 0xc9, 0xf5, 0xac, 0x1c, 0xee, 0x44, 0x89, 0xbf, 0x4a, 0xec, 0x34, 0xf2, 0xf1, 0xd3, 0xa5, + 0xaf, 0xa4, 0xbb, 0x61, 0x42, 0xfa, 0x9a, 0x2e, 0x3f, 0xc1, 0x4c, 0x23, 0x87, 0xbe, 0x23, 0xa8, + 0xed, 0x7a, 0xde, 0x8b, 0xc9, 0x38, 0xf2, 0x9b, 0x4f, 0x7a, 0xdb, 0xec, 0xd8, 0xc1, 0xd9, 0xda, + 0x54, 0x2f, 0x8c, 0x7b, 0x58, 0xd4, 0x1a, 0x6b, 0x6a, 0x45, 0x3d, 0xfc, 0x49, 0xec, 0x38, 0xf9, + 0x05, 0xb3, 0x61, 0x21, 0xe2, 0xd1, 0xb1, 0x73, 0x62, 0xb2, 0x98, 0x04, 0x67, 0x9e, 0xae, 0x22, + 0xa1, 0x26, 0xa8, 0xd6, 0x3e, 0x0c, 0x54, 0x99, 0x8f, 0x32, 0xec, 0x10, 0xaa, 0x5b, 0xbc, 0x8f, + 0x17, 0x2f, 0xa0, 0xcf, 0xca, 0x62, 0xc2, 0xff, 0x81, 0x9c, 0x5d, 0xd6, 0x6a, 0x09, 0x60, 0x72, + 0xdf, 0x1a, 0xdb, 0x57, 0x3e, 0xff, 0xfc, 0xe1, 0x4f, 0xa4, 0x37, 0xcc, 0x17, 0x6a, 0xdf, 0x52, + 0xde, 0x42, 0x89, 0x7d, 0x6b, 0xca, 0xbd, 0x28, 0xb1, 0x6f, 0xcd, 0xb8, 0x17, 0x25, 0x86, 0x5a, + 0x79, 0x2b, 0xb1, 0x21, 0x2c, 0xcc, 0x78, 0x24, 0x45, 0x5b, 0xd6, 0x75, 0x7e, 0x4c, 0x6b, 0xf7, + 0xae, 0x47, 0x48, 0xd6, 0xf6, 0x20, 0x59, 0x5b, 0x17, 0x6a, 0x74, 0x1b, 0xed, 0x31, 0xa7, 0x10, + 0xcc, 0xa9, 0xfb, 0x8b, 0xf4, 0xf8, 0xce, 0xe9, 0x0d, 0x06, 0xd3, 0x92, 0x12, 0x0e, 0x06, 0xe1, + 0xb1, 0x13, 0x7c, 0x82, 0x41, 0x8b, 0x79, 0x8c, 0x88, 0x71, 0x36, 0x0e, 0x33, 0x22, 0xc6, 0x94, + 0x10, 0x49, 0xa5, 0x7e, 0xb2, 0xe5, 0xa8, 0xec, 0x87, 0xae, 0x37, 0xe0, 0x23, 0x59, 0xea, 0xaf, + 0x42, 0xe5, 0x29, 0x0f, 0x55, 0x90, 0x61, 0x24, 0xcb, 0x4f, 0x45, 0x1d, 0xae, 0xa5, 0x84, 0x86, + 0x26, 0x69, 0x93, 0x4a, 0xe6, 0x83, 0x53, 0x4e, 0x4c, 0xd0, 0x72, 0x06, 0x5f, 0xb0, 0x5f, 0xc1, + 0xc2, 0xa3, 0x90, 0xfa, 0x15, 0xad, 0x99, 0x7a, 0xe1, 0xf3, 0x53, 0xf0, 0xb4, 0x92, 0x45, 0x9b, + 0x35, 0x99, 0xd2, 0x85, 0x8a, 0x76, 0xf5, 0x46, 0x34, 0x36, 0xb3, 0x57, 0xad, 0x44, 0x63, 0x93, + 0x72, 0x53, 0x87, 0x71, 0x1f, 0xeb, 0x31, 0xd8, 0xbd, 0xb8, 0x1e, 0xba, 0x9d, 0x23, 0xae, 0xe9, + 0xe1, 0x4f, 0xec, 0x51, 0xf8, 0x05, 0xfb, 0x8c, 0xa6, 0x43, 0x0b, 0xa2, 0x8c, 0x95, 0x93, 0xe9, + 0x78, 0xcb, 0x68, 0xb0, 0xb4, 0xa4, 0xa4, 0xc2, 0x42, 0x55, 0xa1, 0xc4, 0xf8, 0x04, 0xa0, 0x1b, + 0x7a, 0xe3, 0x2d, 0x9b, 0x8f, 0x3c, 0x37, 0xe6, 0xe9, 0x71, 0x58, 0x5f, 0xcc, 0x27, 0xb5, 0xd8, + 0x3e, 0xf6, 0x99, 0xa6, 0xcd, 0x25, 0xc2, 0x7f, 0x15, 0x11, 0x5f, 0x1b, 0xf9, 0x17, 0x0d, 0x48, + 0x4a, 0xf4, 0xdf, 0xa3, 0x0c, 0x6b, 0x01, 0xc4, 0xae, 0x6f, 0x91, 0x6e, 0x36, 0xe3, 0x55, 0x17, + 0xb1, 0xd7, 0x14, 0x3f, 0xb9, 0x43, 0x28, 0xc7, 0x3e, 0x43, 0xab, 0xf1, 0x4d, 0x42, 0x09, 0x0f, + 0xa3, 0x48, 0x52, 0x98, 0xf1, 0xd7, 0x31, 0x1a, 0x38, 0x54, 0xc0, 0x4a, 0x62, 0xa8, 0x4e, 0x38, + 0x0f, 0x98, 0x03, 0x8b, 0xd4, 0xc0, 0x48, 0x2c, 0xc3, 0x70, 0xb4, 0xe8, 0xe1, 0x93, 0x59, 0xd7, + 0x99, 0x88, 0x6b, 0xa4, 0x3a, 0x80, 0x24, 0x8e, 0x98, 0x04, 0xb5, 0x52, 0x28, 0x9c, 0xd8, 0x02, + 0x46, 0xb0, 0x30, 0xe3, 0x63, 0x10, 0xb1, 0x8e, 0xeb, 0x9c, 0x46, 0x22, 0xd6, 0x71, 0xad, 0x7b, + 0x82, 0xb1, 0x8c, 0x55, 0xce, 0x1b, 0x80, 0x2a, 0xe5, 0x85, 0x13, 0xf6, 0xcf, 0x44, 0x75, 0xbf, + 0x9f, 0x81, 0xc5, 0x14, 0x2f, 0x02, 0xf6, 0xa6, 0x3a, 0x9d, 0xb8, 0xd6, 0xc3, 0x60, 0x2d, 0xd5, + 0xda, 0x6c, 0x74, 0xb1, 0x9e, 0x3d, 0xf6, 0x2c, 0xb1, 0x81, 0x92, 0xb1, 0x57, 0xae, 0xcc, 0x97, + 0x0a, 0x2f, 0xa9, 0x92, 0xcb, 0xe7, 0xb0, 0x4a, 0x0d, 0x69, 0x0d, 0x87, 0x53, 0x96, 0xf0, 0x37, + 0xb4, 0x56, 0xa4, 0x58, 0xf7, 0x13, 0x7a, 0x40, 0xd2, 0xc2, 0x7f, 0x8d, 0xd8, 0x4e, 0x4d, 0x65, + 0x13, 0x68, 0x4c, 0x5b, 0x98, 0xd9, 0xf5, 0x65, 0xad, 0xdd, 0x4d, 0xe8, 0xd9, 0x29, 0x56, 0xe9, + 0xaf, 0x61, 0x65, 0x77, 0x8d, 0xb5, 0xb4, 0x71, 0x21, 0xd5, 0x5b, 0xcc, 0xc7, 0x5f, 0x8d, 0xcc, + 0xe1, 0x53, 0xfd, 0xbc, 0x1b, 0x5d, 0xf5, 0x9e, 0x6e, 0xbc, 0x8f, 0x34, 0xfd, 0x74, 0x6b, 0xfa, + 0x3b, 0x58, 0xfd, 0x3d, 0xe3, 0x56, 0x5a, 0xf5, 0x3e, 0x65, 0x21, 0x9d, 0x7f, 0x75, 0x7a, 0x5d, + 0xab, 0x16, 0xdc, 0x4b, 0x9b, 0xef, 0x6b, 0x75, 0xae, 0xa9, 0xb1, 0xbe, 0x81, 0x32, 0x64, 0x55, + 0x37, 0x7f, 0x47, 0xcb, 0x27, 0xc5, 0xce, 0x1e, 0x2d, 0x9f, 0x34, 0x7b, 0x79, 0x52, 0x7e, 0x52, + 0x96, 0xf2, 0x8f, 0x32, 0x0f, 0x36, 0xde, 0xfd, 0xe1, 0xd7, 0x4e, 0x9d, 0xf0, 0x6c, 0x72, 0xbc, + 0xde, 0xf7, 0x46, 0x0f, 0x87, 0xea, 0x54, 0x53, 0xc6, 0x6c, 0x3f, 0x1c, 0xba, 0x83, 0x87, 0x58, + 0xec, 0xf1, 0xdc, 0xd8, 0xf7, 0x42, 0xef, 0x9b, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x21, + 0x23, 0x29, 0x55, 0x89, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index b7003395b2..df2ed7ee92 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1314,6 +1314,11 @@ enum CommitmentType { been broadcast. */ ANCHORS = 2; + + /** + Returned when the commitment type isn't known or unavailable. + */ + UNKNOWN_COMMITMENT_TYPE = 999; } message Channel { @@ -2087,6 +2092,9 @@ message PendingChannelsResponse { // True if we initiated opening the channel. bool initiator = 8; + + /// The commitment type used by this channel. + CommitmentType commitment_type = 9; } message PendingOpenChannel { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 173c8c2d38..e8f73c82f8 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1746,6 +1746,10 @@ "type": "boolean", "format": "boolean", "description": "True if we initiated opening the channel." + }, + "commitment_type": { + "$ref": "#/definitions/lnrpcCommitmentType", + "description": "/ The commitment type used by this channel." } } }, @@ -2523,10 +2527,11 @@ "enum": [ "LEGACY", "STATIC_REMOTE_KEY", - "ANCHORS" + "ANCHORS", + "UNKNOWN_COMMITMENT_TYPE" ], "default": "LEGACY", - "description": " - LEGACY: *\nA channel using the legacy commitment format having tweaked to_remote\nkeys.\n - STATIC_REMOTE_KEY: *\nA channel that uses the modern commitment format where the key in the\noutput of the remote party does not change each state. This makes back\nup and recovery easier as when the channel is closed, the funds go\ndirectly to that key.\n - ANCHORS: *\nA channel that uses a commitment format that has anchor outputs on the\ncommitments, allowing fee bumping after a force close transaction has\nbeen broadcast." + "description": " - LEGACY: *\nA channel using the legacy commitment format having tweaked to_remote\nkeys.\n - STATIC_REMOTE_KEY: *\nA channel that uses the modern commitment format where the key in the\noutput of the remote party does not change each state. This makes back\nup and recovery easier as when the channel is closed, the funds go\ndirectly to that key.\n - ANCHORS: *\nA channel that uses a commitment format that has anchor outputs on the\ncommitments, allowing fee bumping after a force close transaction has\nbeen broadcast.\n - UNKNOWN_COMMITMENT_TYPE: *\nReturned when the commitment type isn't known or unavailable." }, "lnrpcConnectPeerRequest": { "type": "object", diff --git a/rpcserver.go b/rpcserver.go index 1c83ad5ec1..2dc345c8c7 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2738,6 +2738,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context, LocalChanReserveSat: int64(pendingChan.LocalChanCfg.ChanReserve), RemoteChanReserveSat: int64(pendingChan.RemoteChanCfg.ChanReserve), Initiator: pendingChan.IsInitiator, + CommitmentType: rpcCommitmentType(pendingChan.ChanType), }, CommitWeight: commitWeight, CommitFee: int64(localCommitment.CommitFee), @@ -2764,10 +2765,11 @@ func (r *rpcServer) PendingChannels(ctx context.Context, pub := pendingClose.RemotePub.SerializeCompressed() chanPoint := pendingClose.ChanPoint channel := &lnrpc.PendingChannelsResponse_PendingChannel{ - RemoteNodePub: hex.EncodeToString(pub), - ChannelPoint: chanPoint.String(), - Capacity: int64(pendingClose.Capacity), - LocalBalance: int64(pendingClose.SettledBalance), + RemoteNodePub: hex.EncodeToString(pub), + ChannelPoint: chanPoint.String(), + Capacity: int64(pendingClose.Capacity), + LocalBalance: int64(pendingClose.SettledBalance), + CommitmentType: lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, } // Lookup the channel in the historical channel bucket to obtain @@ -2786,6 +2788,9 @@ func (r *rpcServer) PendingChannels(ctx context.Context, case nil: channel.Initiator = historical.IsInitiator + channel.CommitmentType = rpcCommitmentType( + historical.ChanType, + ) // If the error is non-nil, and not due to older versions of lnd // not persisting historical channels, return it. @@ -2913,6 +2918,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context, LocalChanReserveSat: int64(waitingClose.LocalChanCfg.ChanReserve), RemoteChanReserveSat: int64(waitingClose.RemoteChanCfg.ChanReserve), Initiator: waitingClose.IsInitiator, + CommitmentType: rpcCommitmentType(waitingClose.ChanType), } waitingCloseResp := &lnrpc.PendingChannelsResponse_WaitingCloseChannel{ From 66d02504f9246ec3bd83308a2f325b066491ce42 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 16:59:53 -0700 Subject: [PATCH 346/562] rpcserver: align OpenChannel+OpenChannelSync req parsing This commit consolidates our request parsing for OpenChannel and OpenChannelSync which removes a good deal of code duplication. --- rpcserver.go | 228 +++++++++++++++++---------------------------------- 1 file changed, 77 insertions(+), 151 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 5ff15de2ff..fff3a18e13 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1603,15 +1603,10 @@ func newPsbtAssembler(req *lnrpc.OpenChannelRequest, normalizedMinConfs int32, ), nil } -// OpenChannel attempts to open a singly funded channel specified in the -// request to a remote peer. -func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, - updateStream lnrpc.Lightning_OpenChannelServer) error { - - rpcsLog.Tracef("[openchannel] request to NodeKey(%v) "+ - "allocation(us=%v, them=%v)", in.NodePubkeyString, - in.LocalFundingAmount, in.PushSat) - +// canOpenChannel returns an error if the necessary subsystems for channel +// funding are not ready. +func (r *rpcServer) canOpenChannel() error { + // We can't open a channel until the main server has started. if !r.server.Started() { return ErrServerNotActive } @@ -1627,6 +1622,19 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, "wallet is fully synced") } + return nil +} + +// praseOpenChannelReq parses an OpenChannelRequest message into the server's +// native openChanReq struct. The logic is abstracted so that it can be shared +// between OpenChannel and OpenChannelSync. +func (r *rpcServer) parseOpenChannelReq(in *lnrpc.OpenChannelRequest, + isSync bool) (*openChanReq, error) { + + rpcsLog.Debugf("[openchannel] request to NodeKey(%x) "+ + "allocation(us=%v, them=%v)", in.NodePubkey, + in.LocalFundingAmount, in.PushSat) + localFundingAmt := btcutil.Amount(in.LocalFundingAmount) remoteInitialBalance := btcutil.Amount(in.PushSat) minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat) @@ -1638,15 +1646,15 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, // // TODO(roasbeef): incorporate base fee? if remoteInitialBalance >= localFundingAmt { - return fmt.Errorf("amount pushed to remote peer for initial " + - "state must be below the local funding amount") + return nil, fmt.Errorf("amount pushed to remote peer for " + + "initial state must be below the local funding amount") } // Ensure that the user doesn't exceed the current soft-limit for // channel size. If the funding amount is above the soft-limit, then // we'll reject the request. if localFundingAmt > MaxFundingAmount { - return fmt.Errorf("funding amount is too large, the max "+ + return nil, fmt.Errorf("funding amount is too large, the max "+ "channel size is: %v", MaxFundingAmount) } @@ -1654,8 +1662,8 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, // level, we'll ensure that the output we create after accounting for // fees that a dust output isn't created. if localFundingAmt < minChanFundingSize { - return fmt.Errorf("channel is too small, the minimum channel "+ - "size is: %v SAT", int64(minChanFundingSize)) + return nil, fmt.Errorf("channel is too small, the minimum "+ + "channel size is: %v SAT", int64(minChanFundingSize)) } // Then, we'll extract the minimum number of confirmations that each @@ -1663,29 +1671,48 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, // satisfy. minConfs, err := extractOpenChannelMinConfs(in) if err != nil { - return err + return nil, err } // TODO(roasbeef): also return channel ID? var nodePubKey *btcec.PublicKey - // Ensure that the NodePubKey is set before attempting to use it - if len(in.NodePubkey) == 0 { - return fmt.Errorf("NodePubKey is not set") - } + // Parse the remote pubkey the NodePubkey field of the request. If it's + // not present, we'll fallback to the deprecated version that parses the + // key from a hex string if this is for REST for backwards compatibility. + switch { - // Parse the raw bytes of the node key into a pubkey object so we - // can easily manipulate it. - nodePubKey, err = btcec.ParsePubKey(in.NodePubkey, btcec.S256()) - if err != nil { - return err + // Parse the raw bytes of the node key into a pubkey object so we can + // easily manipulate it. + case len(in.NodePubkey) > 0: + nodePubKey, err = btcec.ParsePubKey(in.NodePubkey, btcec.S256()) + if err != nil { + return nil, err + } + + // Decode the provided target node's public key, parsing it into a pub + // key object. For all sync call, byte slices are expected to be encoded + // as hex strings. + case isSync: + keyBytes, err := hex.DecodeString(in.NodePubkeyString) + if err != nil { + return nil, err + } + + nodePubKey, err = btcec.ParsePubKey(keyBytes, btcec.S256()) + if err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("NodePubkey is not set") } // Making a channel to ourselves wouldn't be of any use, so we // explicitly disallow them. if nodePubKey.IsEqual(r.server.identityPriv.PubKey()) { - return fmt.Errorf("cannot open channel to self") + return nil, fmt.Errorf("cannot open channel to self") } // Based on the passed fee related parameters, we'll determine an @@ -1698,7 +1725,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, }, ) if err != nil { - return err + return nil, err } rpcsLog.Debugf("[openchannel]: using fee of %v sat/kw for funding tx", @@ -1706,13 +1733,14 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, script, err := parseUpfrontShutdownAddress(in.CloseAddress) if err != nil { - return fmt.Errorf("error parsing upfront shutdown: %v", err) + return nil, fmt.Errorf("error parsing upfront shutdown: %v", + err) } // Instruct the server to trigger the necessary events to attempt to // open a new channel. A stream is returned in place, this stream will // be used to consume updates of the state of the pending channel. - req := &openChanReq{ + return &openChanReq{ targetPubkey: nodePubKey, chainHash: *activeNetParams.GenesisHash, localFundingAmt: localFundingAmt, @@ -1723,6 +1751,21 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, remoteCsvDelay: remoteCsvDelay, minConfs: minConfs, shutdownScript: script, + }, nil +} + +// OpenChannel attempts to open a singly funded channel specified in the +// request to a remote peer. +func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, + updateStream lnrpc.Lightning_OpenChannelServer) error { + + if err := r.canOpenChannel(); err != nil { + return err + } + + req, err := r.parseOpenChannelReq(in, false) + if err != nil { + return err } // If the user has provided a shim, then we'll now augment the based @@ -1758,7 +1801,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, // transaction. copy(req.pendingChanID[:], psbtShim.PendingChanId) req.chanFunder, err = newPsbtAssembler( - in, minConfs, psbtShim, + in, req.minConfs, psbtShim, &r.server.cc.wallet.Cfg.NetParams, ) if err != nil { @@ -1775,7 +1818,7 @@ out: select { case err := <-errChan: rpcsLog.Errorf("unable to open channel to NodeKey(%x): %v", - nodePubKey.SerializeCompressed(), err) + req.targetPubkey.SerializeCompressed(), err) return err case fundingUpdate := <-updateChan: rpcsLog.Tracef("[openchannel] sending update: %v", @@ -1807,7 +1850,7 @@ out: } rpcsLog.Tracef("[openchannel] success NodeKey(%x), ChannelPoint(%v)", - nodePubKey.SerializeCompressed(), outpoint) + req.targetPubkey.SerializeCompressed(), outpoint) return nil } @@ -1818,138 +1861,21 @@ out: func (r *rpcServer) OpenChannelSync(ctx context.Context, in *lnrpc.OpenChannelRequest) (*lnrpc.ChannelPoint, error) { - rpcsLog.Tracef("[openchannel] request to NodeKey(%v) "+ - "allocation(us=%v, them=%v)", in.NodePubkeyString, - in.LocalFundingAmount, in.PushSat) - - // We don't allow new channels to be open while the server is still - // syncing, as otherwise we may not be able to obtain the relevant - // notifications. - if !r.server.Started() { - return nil, ErrServerNotActive - } - - // Creation of channels before the wallet syncs up is currently - // disallowed. - isSynced, _, err := r.server.cc.wallet.IsSynced() - if err != nil { - return nil, err - } - if !isSynced { - return nil, errors.New("channels cannot be created before the " + - "wallet is fully synced") - } - - var nodePubKey *btcec.PublicKey - - // Parse the remote pubkey the NodePubkey field of the request. If it's - // not present, we'll fallback to the deprecated version that parses the - // key from a hex string. - if len(in.NodePubkey) > 0 { - // Parse the raw bytes of the node key into a pubkey object so we - // can easily manipulate it. - nodePubKey, err = btcec.ParsePubKey(in.NodePubkey, btcec.S256()) - if err != nil { - return nil, err - } - } else { - // Decode the provided target node's public key, parsing it into - // a pub key object. For all sync call, byte slices are expected - // to be encoded as hex strings. - keyBytes, err := hex.DecodeString(in.NodePubkeyString) - if err != nil { - return nil, err - } - - nodePubKey, err = btcec.ParsePubKey(keyBytes, btcec.S256()) - if err != nil { - return nil, err - } - } - - // Making a channel to ourselves wouldn't be of any use, so we - // explicitly disallow them. - if nodePubKey.IsEqual(r.server.identityPriv.PubKey()) { - return nil, fmt.Errorf("cannot open channel to self") - } - - localFundingAmt := btcutil.Amount(in.LocalFundingAmount) - remoteInitialBalance := btcutil.Amount(in.PushSat) - minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat) - remoteCsvDelay := uint16(in.RemoteCsvDelay) - - // Ensure that the initial balance of the remote party (if pushing - // satoshis) does not exceed the amount the local party has requested - // for funding. - if remoteInitialBalance >= localFundingAmt { - return nil, fmt.Errorf("amount pushed to remote peer for " + - "initial state must be below the local funding amount") - } - - // Ensure that the user doesn't exceed the current soft-limit for - // channel size. If the funding amount is above the soft-limit, then - // we'll reject the request. - if localFundingAmt > MaxFundingAmount { - return nil, fmt.Errorf("funding amount is too large, the max "+ - "channel size is: %v", MaxFundingAmount) - } - - // Restrict the size of the channel we'll actually open. At a later - // level, we'll ensure that the output we create after accounting for - // fees that a dust output isn't created. - if localFundingAmt < minChanFundingSize { - return nil, fmt.Errorf("channel is too small, the minimum channel "+ - "size is: %v SAT", int64(minChanFundingSize)) - } - - // Then, we'll extract the minimum number of confirmations that each - // output we use to fund the channel's funding transaction should - // satisfy. - minConfs, err := extractOpenChannelMinConfs(in) - if err != nil { + if err := r.canOpenChannel(); err != nil { return nil, err } - // Based on the passed fee related parameters, we'll determine an - // appropriate fee rate for the funding transaction. - satPerKw := chainfee.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight() - feeRate, err := sweep.DetermineFeePerKw( - r.server.cc.feeEstimator, sweep.FeePreference{ - ConfTarget: uint32(in.TargetConf), - FeeRate: satPerKw, - }, - ) + req, err := r.parseOpenChannelReq(in, true) if err != nil { return nil, err } - rpcsLog.Tracef("[openchannel] target sat/kw for funding tx: %v", - int64(feeRate)) - - script, err := parseUpfrontShutdownAddress(in.CloseAddress) - if err != nil { - return nil, fmt.Errorf("error parsing upfront shutdown: %v", err) - } - - req := &openChanReq{ - targetPubkey: nodePubKey, - chainHash: *activeNetParams.GenesisHash, - localFundingAmt: localFundingAmt, - pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance), - minHtlcIn: minHtlcIn, - fundingFeePerKw: feeRate, - private: in.Private, - remoteCsvDelay: remoteCsvDelay, - minConfs: minConfs, - shutdownScript: script, - } - updateChan, errChan := r.server.OpenChannel(req) select { // If an error occurs them immediately return the error to the client. case err := <-errChan: rpcsLog.Errorf("unable to open channel to NodeKey(%x): %v", - nodePubKey.SerializeCompressed(), err) + req.targetPubkey.SerializeCompressed(), err) return nil, err // Otherwise, wait for the first channel update. The first update sent From bc7ee9a7d08f0397b08f8a9bce3321de1a6898ed Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 31 Mar 2020 13:42:36 +0200 Subject: [PATCH 347/562] routerrpc: fix empty payment request bug --- lnrpc/routerrpc/router_backend.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 259f78f7c4..6465c26863 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -650,6 +650,7 @@ func (r *RouterBackend) extractIntentFromSendRequest( ) payIntent.DestFeatures = payReq.Features payIntent.PaymentAddr = payReq.PaymentAddr + payIntent.PaymentRequest = []byte(rpcPayReq.PaymentRequest) } else { // Otherwise, If the payment request field was not specified // (and a custom route wasn't specified), construct the payment From e11a3b24d802b67d37039b8fecff89be4c0692fb Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 10:45:59 +0200 Subject: [PATCH 348/562] lnrpc/routerrpc: rename RoutingConfig file --- lnrpc/routerrpc/{config.go => routing_config.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lnrpc/routerrpc/{config.go => routing_config.go} (100%) diff --git a/lnrpc/routerrpc/config.go b/lnrpc/routerrpc/routing_config.go similarity index 100% rename from lnrpc/routerrpc/config.go rename to lnrpc/routerrpc/routing_config.go From ffa7bed7f0ffcf8cb3ef4a612b6d5761e40b3f42 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 10:53:49 +0200 Subject: [PATCH 349/562] build+routerrpc+lncli: remove routerrpc conditional compilation --- .golangci.yml | 1 - Dockerfile | 2 +- build/release/release.sh | 4 +-- cmd/lncli/cmd_build_route.go | 2 -- cmd/lncli/cmd_query_mission_control.go | 2 -- cmd/lncli/cmd_query_probability.go | 2 -- cmd/lncli/cmd_reset_mission_control.go | 2 -- .../{routerrpc_active.go => routerrpc.go} | 4 +-- cmd/lncli/routerrpc_default.go | 10 ------- docker/lnd/Dockerfile | 2 +- .../routerrpc/{config_active.go => config.go} | 2 -- lnrpc/routerrpc/config_default.go | 28 ------------------- lnrpc/routerrpc/driver.go | 2 -- lnrpc/routerrpc/router_server.go | 2 -- lnrpc/routerrpc/subscribe_events.go | 2 -- make/testing_flags.mk | 2 +- mobile/README.md | 4 +-- 17 files changed, 8 insertions(+), 65 deletions(-) rename cmd/lncli/{routerrpc_active.go => routerrpc.go} (72%) delete mode 100644 cmd/lncli/routerrpc_default.go rename lnrpc/routerrpc/{config_active.go => config.go} (99%) delete mode 100644 lnrpc/routerrpc/config_default.go diff --git a/.golangci.yml b/.golangci.yml index b3289f16b5..00fc7b2738 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -17,7 +17,6 @@ run: - autopilotrpc - chainrpc - invoicesrpc - - routerrpc - signrpc - walletrpc - watchtowerrpc diff --git a/Dockerfile b/Dockerfile index fc61fd834f..12c6ece657 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ RUN apk add --no-cache --update alpine-sdk \ && cd /go/src/github.com/lightningnetwork/lnd \ && git checkout $checkout \ && make \ -&& make install tags="signrpc walletrpc chainrpc invoicesrpc routerrpc" +&& make install tags="signrpc walletrpc chainrpc invoicesrpc" # Start a new, final image. FROM alpine as final diff --git a/build/release/release.sh b/build/release/release.sh index 28236f55f3..46ce14a8c6 100755 --- a/build/release/release.sh +++ b/build/release/release.sh @@ -130,8 +130,8 @@ for i in $SYS; do cd $PACKAGE-$i-$TAG echo "Building:" $OS $ARCH $ARM - env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -trimpath -ldflags="-s -w -buildid= $COMMITFLAGS" -tags="autopilotrpc signrpc walletrpc chainrpc invoicesrpc routerrpc watchtowerrpc" github.com/lightningnetwork/lnd/cmd/lnd - env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -trimpath -ldflags="-s -w -buildid= $COMMITFLAGS" -tags="autopilotrpc invoicesrpc walletrpc routerrpc watchtowerrpc" github.com/lightningnetwork/lnd/cmd/lncli + env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -trimpath -ldflags="-s -w -buildid= $COMMITFLAGS" -tags="autopilotrpc signrpc walletrpc chainrpc invoicesrpc watchtowerrpc" github.com/lightningnetwork/lnd/cmd/lnd + env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -trimpath -ldflags="-s -w -buildid= $COMMITFLAGS" -tags="autopilotrpc invoicesrpc walletrpc watchtowerrpc" github.com/lightningnetwork/lnd/cmd/lncli cd .. if [[ $OS = "windows" ]]; then diff --git a/cmd/lncli/cmd_build_route.go b/cmd/lncli/cmd_build_route.go index 685989d423..81c5bfb04f 100644 --- a/cmd/lncli/cmd_build_route.go +++ b/cmd/lncli/cmd_build_route.go @@ -1,5 +1,3 @@ -// +build routerrpc - package main import ( diff --git a/cmd/lncli/cmd_query_mission_control.go b/cmd/lncli/cmd_query_mission_control.go index 6071d0a4e3..93cf71c9c9 100644 --- a/cmd/lncli/cmd_query_mission_control.go +++ b/cmd/lncli/cmd_query_mission_control.go @@ -1,5 +1,3 @@ -// +build routerrpc - package main import ( diff --git a/cmd/lncli/cmd_query_probability.go b/cmd/lncli/cmd_query_probability.go index 58c8ba1b42..4eaa075c98 100644 --- a/cmd/lncli/cmd_query_probability.go +++ b/cmd/lncli/cmd_query_probability.go @@ -1,5 +1,3 @@ -// +build routerrpc - package main import ( diff --git a/cmd/lncli/cmd_reset_mission_control.go b/cmd/lncli/cmd_reset_mission_control.go index db37fd4b19..b571a9e9a4 100644 --- a/cmd/lncli/cmd_reset_mission_control.go +++ b/cmd/lncli/cmd_reset_mission_control.go @@ -1,5 +1,3 @@ -// +build routerrpc - package main import ( diff --git a/cmd/lncli/routerrpc_active.go b/cmd/lncli/routerrpc.go similarity index 72% rename from cmd/lncli/routerrpc_active.go rename to cmd/lncli/routerrpc.go index f8903d808e..819f66d22f 100644 --- a/cmd/lncli/routerrpc_active.go +++ b/cmd/lncli/routerrpc.go @@ -1,10 +1,8 @@ -// +build routerrpc - package main import "github.com/urfave/cli" -// routerCommands will return nil for non-routerrpc builds. +// routerCommands returns a list of routerrpc commands. func routerCommands() []cli.Command { return []cli.Command{ queryMissionControlCommand, diff --git a/cmd/lncli/routerrpc_default.go b/cmd/lncli/routerrpc_default.go deleted file mode 100644 index c2a5fe7bed..0000000000 --- a/cmd/lncli/routerrpc_default.go +++ /dev/null @@ -1,10 +0,0 @@ -// +build !routerrpc - -package main - -import "github.com/urfave/cli" - -// routerCommands will return nil for non-routerrpc builds. -func routerCommands() []cli.Command { - return nil -} diff --git a/docker/lnd/Dockerfile b/docker/lnd/Dockerfile index 424e2c74a5..db55ce1272 100644 --- a/docker/lnd/Dockerfile +++ b/docker/lnd/Dockerfile @@ -16,7 +16,7 @@ COPY . /go/src/github.com/lightningnetwork/lnd RUN cd /go/src/github.com/lightningnetwork/lnd \ && make \ -&& make install tags="signrpc walletrpc chainrpc invoicesrpc routerrpc" +&& make install tags="signrpc walletrpc chainrpc invoicesrpc" # Start a new, final image to reduce size. FROM alpine as final diff --git a/lnrpc/routerrpc/config_active.go b/lnrpc/routerrpc/config.go similarity index 99% rename from lnrpc/routerrpc/config_active.go rename to lnrpc/routerrpc/config.go index a8393fc615..045561dbfd 100644 --- a/lnrpc/routerrpc/config_active.go +++ b/lnrpc/routerrpc/config.go @@ -1,5 +1,3 @@ -// +build routerrpc - package routerrpc import ( diff --git a/lnrpc/routerrpc/config_default.go b/lnrpc/routerrpc/config_default.go deleted file mode 100644 index 6fcc74a77d..0000000000 --- a/lnrpc/routerrpc/config_default.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build !routerrpc - -package routerrpc - -import "github.com/lightningnetwork/lnd/routing" - -// Config is the default config struct for the package. When the build tag isn't -// specified, then we output a blank config. -type Config struct{} - -// DefaultConfig defines the config defaults. Without the sub server enabled, -// there are no defaults to set. -func DefaultConfig() *Config { - return &Config{} -} - -// GetRoutingConfig returns the routing config based on this sub server config. -func GetRoutingConfig(cfg *Config) *RoutingConfig { - return &RoutingConfig{ - AprioriHopProbability: routing.DefaultAprioriHopProbability, - AprioriWeight: routing.DefaultAprioriWeight, - MinRouteProbability: routing.DefaultMinRouteProbability, - AttemptCost: routing.DefaultPaymentAttemptPenalty. - ToSatoshis(), - PenaltyHalfLife: routing.DefaultPenaltyHalfLife, - MaxMcHistory: routing.DefaultMaxMcHistory, - } -} diff --git a/lnrpc/routerrpc/driver.go b/lnrpc/routerrpc/driver.go index 05cc0c4b00..e174e2222e 100644 --- a/lnrpc/routerrpc/driver.go +++ b/lnrpc/routerrpc/driver.go @@ -1,5 +1,3 @@ -// +build routerrpc - package routerrpc import ( diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 17434699a8..acdc8da343 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -1,5 +1,3 @@ -// +build routerrpc - package routerrpc import ( diff --git a/lnrpc/routerrpc/subscribe_events.go b/lnrpc/routerrpc/subscribe_events.go index ce65a6c8a5..4454dbda2f 100644 --- a/lnrpc/routerrpc/subscribe_events.go +++ b/lnrpc/routerrpc/subscribe_events.go @@ -1,5 +1,3 @@ -// +build routerrpc - package routerrpc import ( diff --git a/make/testing_flags.mk b/make/testing_flags.mk index e4f5661c0d..aab09bb5eb 100644 --- a/make/testing_flags.mk +++ b/make/testing_flags.mk @@ -61,6 +61,6 @@ backend = btcd endif # Construct the integration test command with the added build flags. -ITEST_TAGS := $(DEV_TAGS) rpctest chainrpc walletrpc signrpc invoicesrpc autopilotrpc routerrpc watchtowerrpc $(backend) +ITEST_TAGS := $(DEV_TAGS) rpctest chainrpc walletrpc signrpc invoicesrpc autopilotrpc watchtowerrpc $(backend) ITEST := rm lntest/itest/*.log; date; $(GOTEST) -v ./lntest/itest -tags="$(ITEST_TAGS)" $(TEST_FLAGS) -logoutput -goroutinedump diff --git a/mobile/README.md b/mobile/README.md index 077e9498ef..3a2662323c 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -53,14 +53,14 @@ Similar to lnd, subservers can be conditionally compiled with the build by setting the tags argument: ``` -make ios tags="routerrpc" +make ios ``` To support subservers that have APIs with name conflicts, pass the "prefix" flag. This will add the subserver name as a prefix to each method name: ``` -make ios tags="routerrpc" prefix=1 +make ios prefix=1 ``` ### API docs From 767c4f2298203c3f941007e420e45c71c596fbe6 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 11:09:17 +0200 Subject: [PATCH 350/562] routerrpc: remove reflection-based initialization --- subrpcserver_config.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/subrpcserver_config.go b/subrpcserver_config.go index 31e8220b41..4855911881 100644 --- a/subrpcserver_config.go +++ b/subrpcserver_config.go @@ -219,21 +219,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl, reflect.ValueOf(genInvoiceFeatures), ) + // RouterRPC isn't conditionally compiled and doesn't need to be + // populated using reflection. case *routerrpc.Config: - subCfgValue := extractReflectValue(subCfg) - - subCfgValue.FieldByName("NetworkDir").Set( - reflect.ValueOf(networkDir), - ) - subCfgValue.FieldByName("MacService").Set( - reflect.ValueOf(macService), - ) - subCfgValue.FieldByName("Router").Set( - reflect.ValueOf(chanRouter), - ) - subCfgValue.FieldByName("RouterBackend").Set( - reflect.ValueOf(routerBackend), - ) case *watchtowerrpc.Config: subCfgValue := extractReflectValue(subCfg) @@ -266,6 +254,12 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl, } } + // Populate routerrpc dependencies. + s.RouterRPC.NetworkDir = networkDir + s.RouterRPC.MacService = macService + s.RouterRPC.Router = chanRouter + s.RouterRPC.RouterBackend = routerBackend + return nil } From f060da3971925422a72d4972a1f0ba4227546c0c Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 12:41:32 +0200 Subject: [PATCH 351/562] lncli: move payment commands to separate file --- cmd/lncli/cmd_pay.go | 581 ++++++++++++++++++++++++++++++++++++++++++ cmd/lncli/commands.go | 564 ---------------------------------------- 2 files changed, 581 insertions(+), 564 deletions(-) create mode 100644 cmd/lncli/cmd_pay.go diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go new file mode 100644 index 0000000000..e2414f27ad --- /dev/null +++ b/cmd/lncli/cmd_pay.go @@ -0,0 +1,581 @@ +package main + +import ( + "context" + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "io/ioutil" + "os" + "strconv" + "strings" + + "github.com/lightninglabs/protobuf-hex-display/jsonpb" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/record" + "github.com/lightningnetwork/lnd/routing/route" + "github.com/urfave/cli" +) + +var ( + cltvLimitFlag = cli.UintFlag{ + Name: "cltv_limit", + Usage: "the maximum time lock that may be used for " + + "this payment", + } + + lastHopFlag = cli.StringFlag{ + Name: "last_hop", + Usage: "pubkey of the last hop (penultimate node in the path) " + + "to route through for this payment", + } + + dataFlag = cli.StringFlag{ + Name: "data", + Usage: "attach custom data to the payment. The required " + + "format is: =,=" + + ",.. For example: --data 3438382=0a21ff. " + + "Custom record ids start from 65536.", + } +) + +// paymentFlags returns common flags for sendpayment and payinvoice. +func paymentFlags() []cli.Flag { + return []cli.Flag{ + cli.StringFlag{ + Name: "pay_req", + Usage: "a zpay32 encoded payment request to fulfill", + }, + cli.Int64Flag{ + Name: "fee_limit", + Usage: "maximum fee allowed in satoshis when " + + "sending the payment", + }, + cli.Int64Flag{ + Name: "fee_limit_percent", + Usage: "percentage of the payment's amount used as " + + "the maximum fee allowed when sending the " + + "payment", + }, + cltvLimitFlag, + lastHopFlag, + cli.Uint64Flag{ + Name: "outgoing_chan_id", + Usage: "short channel id of the outgoing channel to " + + "use for the first hop of the payment", + Value: 0, + }, + cli.BoolFlag{ + Name: "force, f", + Usage: "will skip payment request confirmation", + }, + cli.BoolFlag{ + Name: "allow_self_payment", + Usage: "allow sending a circular payment to self", + }, + dataFlag, + } +} + +var sendPaymentCommand = cli.Command{ + Name: "sendpayment", + Category: "Payments", + Usage: "Send a payment over lightning.", + Description: ` + Send a payment over Lightning. One can either specify the full + parameters of the payment, or just use a payment request which encodes + all the payment details. + + If payment isn't manually specified, then only a payment request needs + to be passed using the --pay_req argument. + + If the payment *is* manually specified, then all four alternative + arguments need to be specified in order to complete the payment: + * --dest=N + * --amt=A + * --final_cltv_delta=T + * --payment_hash=H + `, + ArgsUsage: "dest amt payment_hash final_cltv_delta | --pay_req=[payment request]", + Flags: append(paymentFlags(), + cli.StringFlag{ + Name: "dest, d", + Usage: "the compressed identity pubkey of the " + + "payment recipient", + }, + cli.Int64Flag{ + Name: "amt, a", + Usage: "number of satoshis to send", + }, + cli.StringFlag{ + Name: "payment_hash, r", + Usage: "the hash to use within the payment's HTLC", + }, + cli.Int64Flag{ + Name: "final_cltv_delta", + Usage: "the number of blocks the last hop has to reveal the preimage", + }, + cli.BoolFlag{ + Name: "keysend", + Usage: "will generate a pre-image and encode it in the sphinx packet, a dest must be set [experimental]", + }, + ), + Action: sendPayment, +} + +// retrieveFeeLimit retrieves the fee limit based on the different fee limit +// flags passed. +func retrieveFeeLimit(ctx *cli.Context) (*lnrpc.FeeLimit, error) { + switch { + case ctx.IsSet("fee_limit") && ctx.IsSet("fee_limit_percent"): + return nil, fmt.Errorf("either fee_limit or fee_limit_percent " + + "can be set, but not both") + case ctx.IsSet("fee_limit"): + return &lnrpc.FeeLimit{ + Limit: &lnrpc.FeeLimit_Fixed{ + Fixed: ctx.Int64("fee_limit"), + }, + }, nil + case ctx.IsSet("fee_limit_percent"): + return &lnrpc.FeeLimit{ + Limit: &lnrpc.FeeLimit_Percent{ + Percent: ctx.Int64("fee_limit_percent"), + }, + }, nil + } + + // Since the fee limit flags aren't required, we don't return an error + // if they're not set. + return nil, nil +} + +func confirmPayReq(resp *lnrpc.PayReq, amt int64) error { + fmt.Printf("Description: %v\n", resp.GetDescription()) + fmt.Printf("Amount (in satoshis): %v\n", amt) + fmt.Printf("Destination: %v\n", resp.GetDestination()) + + confirm := promptForConfirmation("Confirm payment (yes/no): ") + if !confirm { + return fmt.Errorf("payment not confirmed") + } + + return nil +} + +func sendPayment(ctx *cli.Context) error { + // Show command help if no arguments provided + if ctx.NArg() == 0 && ctx.NumFlags() == 0 { + _ = cli.ShowCommandHelp(ctx, "sendpayment") + return nil + } + + // If a payment request was provided, we can exit early since all of the + // details of the payment are encoded within the request. + if ctx.IsSet("pay_req") { + req := &lnrpc.SendRequest{ + PaymentRequest: ctx.String("pay_req"), + Amt: ctx.Int64("amt"), + } + + return sendPaymentRequest(ctx, req) + } + + var ( + destNode []byte + amount int64 + err error + ) + + args := ctx.Args() + + switch { + case ctx.IsSet("dest"): + destNode, err = hex.DecodeString(ctx.String("dest")) + case args.Present(): + destNode, err = hex.DecodeString(args.First()) + args = args.Tail() + default: + return fmt.Errorf("destination txid argument missing") + } + if err != nil { + return err + } + + if len(destNode) != 33 { + return fmt.Errorf("dest node pubkey must be exactly 33 bytes, is "+ + "instead: %v", len(destNode)) + } + + if ctx.IsSet("amt") { + amount = ctx.Int64("amt") + } else if args.Present() { + amount, err = strconv.ParseInt(args.First(), 10, 64) + args = args.Tail() + if err != nil { + return fmt.Errorf("unable to decode payment amount: %v", err) + } + } + + req := &lnrpc.SendRequest{ + Dest: destNode, + Amt: amount, + DestCustomRecords: make(map[uint64][]byte), + } + + var rHash []byte + + if ctx.Bool("keysend") { + if ctx.IsSet("payment_hash") { + return errors.New("cannot set payment hash when using " + + "keysend") + } + var preimage lntypes.Preimage + if _, err := rand.Read(preimage[:]); err != nil { + return err + } + + // Set the preimage. If the user supplied a preimage with the + // data flag, the preimage that is set here will be overwritten + // later. + req.DestCustomRecords[record.KeySendType] = preimage[:] + + hash := preimage.Hash() + rHash = hash[:] + } else { + switch { + case ctx.IsSet("payment_hash"): + rHash, err = hex.DecodeString(ctx.String("payment_hash")) + case args.Present(): + rHash, err = hex.DecodeString(args.First()) + args = args.Tail() + default: + return fmt.Errorf("payment hash argument missing") + } + } + + if err != nil { + return err + } + if len(rHash) != 32 { + return fmt.Errorf("payment hash must be exactly 32 "+ + "bytes, is instead %v", len(rHash)) + } + req.PaymentHash = rHash + + switch { + case ctx.IsSet("final_cltv_delta"): + req.FinalCltvDelta = int32(ctx.Int64("final_cltv_delta")) + case args.Present(): + delta, err := strconv.ParseInt(args.First(), 10, 64) + if err != nil { + return err + } + req.FinalCltvDelta = int32(delta) + } + + return sendPaymentRequest(ctx, req) +} + +func sendPaymentRequest(ctx *cli.Context, req *lnrpc.SendRequest) error { + client, cleanUp := getClient(ctx) + defer cleanUp() + + // First, we'll retrieve the fee limit value passed since it can apply + // to both ways of sending payments (with the payment request or + // providing the details manually). + feeLimit, err := retrieveFeeLimit(ctx) + if err != nil { + return err + } + req.FeeLimit = feeLimit + + req.OutgoingChanId = ctx.Uint64("outgoing_chan_id") + if ctx.IsSet(lastHopFlag.Name) { + lastHop, err := route.NewVertexFromStr( + ctx.String(lastHopFlag.Name), + ) + if err != nil { + return err + } + req.LastHopPubkey = lastHop[:] + } + + req.CltvLimit = uint32(ctx.Int(cltvLimitFlag.Name)) + + req.AllowSelfPayment = ctx.Bool("allow_self_payment") + + // Parse custom data records. + data := ctx.String(dataFlag.Name) + if data != "" { + records := strings.Split(data, ",") + for _, r := range records { + kv := strings.Split(r, "=") + if len(kv) != 2 { + return errors.New("invalid data format: " + + "multiple equal signs in record") + } + + recordID, err := strconv.ParseUint(kv[0], 10, 64) + if err != nil { + return fmt.Errorf("invalid data format: %v", + err) + } + + hexValue, err := hex.DecodeString(kv[1]) + if err != nil { + return fmt.Errorf("invalid data format: %v", + err) + } + + req.DestCustomRecords[recordID] = hexValue + } + } + + amt := req.Amt + + if req.PaymentRequest != "" { + req := &lnrpc.PayReqString{PayReq: req.PaymentRequest} + resp, err := client.DecodePayReq(context.Background(), req) + if err != nil { + return err + } + + invoiceAmt := resp.GetNumSatoshis() + if invoiceAmt != 0 { + amt = invoiceAmt + } + + if !ctx.Bool("force") { + err := confirmPayReq(resp, amt) + if err != nil { + return err + } + } + } + + paymentStream, err := client.SendPayment(context.Background()) + if err != nil { + return err + } + + if err := paymentStream.Send(req); err != nil { + return err + } + + resp, err := paymentStream.Recv() + if err != nil { + return err + } + + paymentStream.CloseSend() + + printRespJSON(resp) + + // If we get a payment error back, we pass an error + // up to main which eventually calls fatal() and returns + // with a non-zero exit code. + if resp.PaymentError != "" { + return errors.New(resp.PaymentError) + } + + return nil +} + +var payInvoiceCommand = cli.Command{ + Name: "payinvoice", + Category: "Payments", + Usage: "Pay an invoice over lightning.", + ArgsUsage: "pay_req", + Flags: append(paymentFlags(), + cli.Int64Flag{ + Name: "amt", + Usage: "(optional) number of satoshis to fulfill the " + + "invoice", + }, + ), + Action: actionDecorator(payInvoice), +} + +func payInvoice(ctx *cli.Context) error { + args := ctx.Args() + + var payReq string + switch { + case ctx.IsSet("pay_req"): + payReq = ctx.String("pay_req") + case args.Present(): + payReq = args.First() + default: + return fmt.Errorf("pay_req argument missing") + } + + req := &lnrpc.SendRequest{ + PaymentRequest: payReq, + Amt: ctx.Int64("amt"), + DestCustomRecords: make(map[uint64][]byte), + } + + return sendPaymentRequest(ctx, req) +} + +var sendToRouteCommand = cli.Command{ + Name: "sendtoroute", + Category: "Payments", + Usage: "Send a payment over a predefined route.", + Description: ` + Send a payment over Lightning using a specific route. One must specify + the route to attempt and the payment hash. This command can even + be chained with the response to queryroutes or buildroute. This command + can be used to implement channel rebalancing by crafting a self-route, + or even atomic swaps using a self-route that crosses multiple chains. + + There are three ways to specify a route: + * using the --routes parameter to manually specify a JSON encoded + route in the format of the return value of queryroutes or + buildroute: + (lncli sendtoroute --payment_hash= --routes=) + + * passing the route as a positional argument: + (lncli sendtoroute --payment_hash=pay_hash ) + + * or reading in the route from stdin, which can allow chaining the + response from queryroutes or buildroute, or even read in a file + with a pre-computed route: + (lncli queryroutes --args.. | lncli sendtoroute --payment_hash= - + + notice the '-' at the end, which signals that lncli should read + the route in from stdin + `, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "payment_hash, pay_hash", + Usage: "the hash to use within the payment's HTLC", + }, + cli.StringFlag{ + Name: "routes, r", + Usage: "a json array string in the format of the response " + + "of queryroutes that denotes which routes to use", + }, + }, + Action: sendToRoute, +} + +func sendToRoute(ctx *cli.Context) error { + // Show command help if no arguments provided. + if ctx.NArg() == 0 && ctx.NumFlags() == 0 { + _ = cli.ShowCommandHelp(ctx, "sendtoroute") + return nil + } + + args := ctx.Args() + + var ( + rHash []byte + err error + ) + switch { + case ctx.IsSet("payment_hash"): + rHash, err = hex.DecodeString(ctx.String("payment_hash")) + case args.Present(): + rHash, err = hex.DecodeString(args.First()) + + args = args.Tail() + default: + return fmt.Errorf("payment hash argument missing") + } + + if err != nil { + return err + } + + if len(rHash) != 32 { + return fmt.Errorf("payment hash must be exactly 32 "+ + "bytes, is instead %d", len(rHash)) + } + + var jsonRoutes string + switch { + // The user is specifying the routes explicitly via the key word + // argument. + case ctx.IsSet("routes"): + jsonRoutes = ctx.String("routes") + + // The user is specifying the routes as a positional argument. + case args.Present() && args.First() != "-": + jsonRoutes = args.First() + + // The user is signalling that we should read stdin in order to parse + // the set of target routes. + case args.Present() && args.First() == "-": + b, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return err + } + if len(b) == 0 { + return fmt.Errorf("queryroutes output is empty") + } + + jsonRoutes = string(b) + } + + // Try to parse the provided json both in the legacy QueryRoutes format + // that contains a list of routes and the single route BuildRoute + // format. + var route *lnrpc.Route + routes := &lnrpc.QueryRoutesResponse{} + err = jsonpb.UnmarshalString(jsonRoutes, routes) + if err == nil { + if len(routes.Routes) == 0 { + return fmt.Errorf("no routes provided") + } + + if len(routes.Routes) != 1 { + return fmt.Errorf("expected a single route, but got %v", + len(routes.Routes)) + } + + route = routes.Routes[0] + } else { + routes := &routerrpc.BuildRouteResponse{} + err = jsonpb.UnmarshalString(jsonRoutes, routes) + if err != nil { + return fmt.Errorf("unable to unmarshal json string "+ + "from incoming array of routes: %v", err) + } + + route = routes.Route + } + + req := &lnrpc.SendToRouteRequest{ + PaymentHash: rHash, + Route: route, + } + + return sendToRouteRequest(ctx, req) +} + +func sendToRouteRequest(ctx *cli.Context, req *lnrpc.SendToRouteRequest) error { + client, cleanUp := getClient(ctx) + defer cleanUp() + + paymentStream, err := client.SendToRoute(context.Background()) + if err != nil { + return err + } + + if err := paymentStream.Send(req); err != nil { + return err + } + + resp, err := paymentStream.Recv() + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 9446c4d398..c9cd0732ab 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -4,7 +4,6 @@ import ( "bufio" "bytes" "context" - "crypto/rand" "encoding/hex" "errors" "fmt" @@ -24,9 +23,6 @@ import ( "github.com/lightninglabs/protobuf-hex-display/jsonpb" "github.com/lightninglabs/protobuf-hex-display/proto" "github.com/lightningnetwork/lnd/lnrpc" - "github.com/lightningnetwork/lnd/lnrpc/routerrpc" - "github.com/lightningnetwork/lnd/lntypes" - "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/walletunlocker" "github.com/urfave/cli" @@ -1882,566 +1878,6 @@ func closedChannels(ctx *cli.Context) error { return nil } -var ( - cltvLimitFlag = cli.UintFlag{ - Name: "cltv_limit", - Usage: "the maximum time lock that may be used for " + - "this payment", - } - - lastHopFlag = cli.StringFlag{ - Name: "last_hop", - Usage: "pubkey of the last hop (penultimate node in the path) " + - "to route through for this payment", - } - - dataFlag = cli.StringFlag{ - Name: "data", - Usage: "attach custom data to the payment. The required " + - "format is: =,=" + - ",.. For example: --data 3438382=0a21ff. " + - "Custom record ids start from 65536.", - } -) - -// paymentFlags returns common flags for sendpayment and payinvoice. -func paymentFlags() []cli.Flag { - return []cli.Flag{ - cli.StringFlag{ - Name: "pay_req", - Usage: "a zpay32 encoded payment request to fulfill", - }, - cli.Int64Flag{ - Name: "fee_limit", - Usage: "maximum fee allowed in satoshis when " + - "sending the payment", - }, - cli.Int64Flag{ - Name: "fee_limit_percent", - Usage: "percentage of the payment's amount used as " + - "the maximum fee allowed when sending the " + - "payment", - }, - cltvLimitFlag, - lastHopFlag, - cli.Uint64Flag{ - Name: "outgoing_chan_id", - Usage: "short channel id of the outgoing channel to " + - "use for the first hop of the payment", - Value: 0, - }, - cli.BoolFlag{ - Name: "force, f", - Usage: "will skip payment request confirmation", - }, - cli.BoolFlag{ - Name: "allow_self_payment", - Usage: "allow sending a circular payment to self", - }, - dataFlag, - } -} - -var sendPaymentCommand = cli.Command{ - Name: "sendpayment", - Category: "Payments", - Usage: "Send a payment over lightning.", - Description: ` - Send a payment over Lightning. One can either specify the full - parameters of the payment, or just use a payment request which encodes - all the payment details. - - If payment isn't manually specified, then only a payment request needs - to be passed using the --pay_req argument. - - If the payment *is* manually specified, then all four alternative - arguments need to be specified in order to complete the payment: - * --dest=N - * --amt=A - * --final_cltv_delta=T - * --payment_hash=H - `, - ArgsUsage: "dest amt payment_hash final_cltv_delta | --pay_req=[payment request]", - Flags: append(paymentFlags(), - cli.StringFlag{ - Name: "dest, d", - Usage: "the compressed identity pubkey of the " + - "payment recipient", - }, - cli.Int64Flag{ - Name: "amt, a", - Usage: "number of satoshis to send", - }, - cli.StringFlag{ - Name: "payment_hash, r", - Usage: "the hash to use within the payment's HTLC", - }, - cli.Int64Flag{ - Name: "final_cltv_delta", - Usage: "the number of blocks the last hop has to reveal the preimage", - }, - cli.BoolFlag{ - Name: "keysend", - Usage: "will generate a pre-image and encode it in the sphinx packet, a dest must be set [experimental]", - }, - ), - Action: sendPayment, -} - -// retrieveFeeLimit retrieves the fee limit based on the different fee limit -// flags passed. -func retrieveFeeLimit(ctx *cli.Context) (*lnrpc.FeeLimit, error) { - switch { - case ctx.IsSet("fee_limit") && ctx.IsSet("fee_limit_percent"): - return nil, fmt.Errorf("either fee_limit or fee_limit_percent " + - "can be set, but not both") - case ctx.IsSet("fee_limit"): - return &lnrpc.FeeLimit{ - Limit: &lnrpc.FeeLimit_Fixed{ - Fixed: ctx.Int64("fee_limit"), - }, - }, nil - case ctx.IsSet("fee_limit_percent"): - return &lnrpc.FeeLimit{ - Limit: &lnrpc.FeeLimit_Percent{ - Percent: ctx.Int64("fee_limit_percent"), - }, - }, nil - } - - // Since the fee limit flags aren't required, we don't return an error - // if they're not set. - return nil, nil -} - -func confirmPayReq(resp *lnrpc.PayReq, amt int64) error { - fmt.Printf("Description: %v\n", resp.GetDescription()) - fmt.Printf("Amount (in satoshis): %v\n", amt) - fmt.Printf("Destination: %v\n", resp.GetDestination()) - - confirm := promptForConfirmation("Confirm payment (yes/no): ") - if !confirm { - return fmt.Errorf("payment not confirmed") - } - - return nil -} - -func sendPayment(ctx *cli.Context) error { - // Show command help if no arguments provided - if ctx.NArg() == 0 && ctx.NumFlags() == 0 { - cli.ShowCommandHelp(ctx, "sendpayment") - return nil - } - - // If a payment request was provided, we can exit early since all of the - // details of the payment are encoded within the request. - if ctx.IsSet("pay_req") { - req := &lnrpc.SendRequest{ - PaymentRequest: ctx.String("pay_req"), - Amt: ctx.Int64("amt"), - } - - return sendPaymentRequest(ctx, req) - } - - var ( - destNode []byte - amount int64 - err error - ) - - args := ctx.Args() - - switch { - case ctx.IsSet("dest"): - destNode, err = hex.DecodeString(ctx.String("dest")) - case args.Present(): - destNode, err = hex.DecodeString(args.First()) - args = args.Tail() - default: - return fmt.Errorf("destination txid argument missing") - } - if err != nil { - return err - } - - if len(destNode) != 33 { - return fmt.Errorf("dest node pubkey must be exactly 33 bytes, is "+ - "instead: %v", len(destNode)) - } - - if ctx.IsSet("amt") { - amount = ctx.Int64("amt") - } else if args.Present() { - amount, err = strconv.ParseInt(args.First(), 10, 64) - args = args.Tail() - if err != nil { - return fmt.Errorf("unable to decode payment amount: %v", err) - } - } - - req := &lnrpc.SendRequest{ - Dest: destNode, - Amt: amount, - DestCustomRecords: make(map[uint64][]byte), - } - - var rHash []byte - - if ctx.Bool("keysend") { - if ctx.IsSet("payment_hash") { - return errors.New("cannot set payment hash when using " + - "keysend") - } - var preimage lntypes.Preimage - if _, err := rand.Read(preimage[:]); err != nil { - return err - } - - // Set the preimage. If the user supplied a preimage with the - // data flag, the preimage that is set here will be overwritten - // later. - req.DestCustomRecords[record.KeySendType] = preimage[:] - - hash := preimage.Hash() - rHash = hash[:] - } else { - switch { - case ctx.IsSet("payment_hash"): - rHash, err = hex.DecodeString(ctx.String("payment_hash")) - case args.Present(): - rHash, err = hex.DecodeString(args.First()) - args = args.Tail() - default: - return fmt.Errorf("payment hash argument missing") - } - } - - if err != nil { - return err - } - if len(rHash) != 32 { - return fmt.Errorf("payment hash must be exactly 32 "+ - "bytes, is instead %v", len(rHash)) - } - req.PaymentHash = rHash - - switch { - case ctx.IsSet("final_cltv_delta"): - req.FinalCltvDelta = int32(ctx.Int64("final_cltv_delta")) - case args.Present(): - delta, err := strconv.ParseInt(args.First(), 10, 64) - if err != nil { - return err - } - req.FinalCltvDelta = int32(delta) - } - - return sendPaymentRequest(ctx, req) -} - -func sendPaymentRequest(ctx *cli.Context, req *lnrpc.SendRequest) error { - client, cleanUp := getClient(ctx) - defer cleanUp() - - // First, we'll retrieve the fee limit value passed since it can apply - // to both ways of sending payments (with the payment request or - // providing the details manually). - feeLimit, err := retrieveFeeLimit(ctx) - if err != nil { - return err - } - req.FeeLimit = feeLimit - - req.OutgoingChanId = ctx.Uint64("outgoing_chan_id") - if ctx.IsSet(lastHopFlag.Name) { - lastHop, err := route.NewVertexFromStr( - ctx.String(lastHopFlag.Name), - ) - if err != nil { - return err - } - req.LastHopPubkey = lastHop[:] - } - - req.CltvLimit = uint32(ctx.Int(cltvLimitFlag.Name)) - - req.AllowSelfPayment = ctx.Bool("allow_self_payment") - - // Parse custom data records. - data := ctx.String(dataFlag.Name) - if data != "" { - records := strings.Split(data, ",") - for _, r := range records { - kv := strings.Split(r, "=") - if len(kv) != 2 { - return errors.New("invalid data format: " + - "multiple equal signs in record") - } - - recordID, err := strconv.ParseUint(kv[0], 10, 64) - if err != nil { - return fmt.Errorf("invalid data format: %v", - err) - } - - hexValue, err := hex.DecodeString(kv[1]) - if err != nil { - return fmt.Errorf("invalid data format: %v", - err) - } - - req.DestCustomRecords[recordID] = hexValue - } - } - - amt := req.Amt - - if req.PaymentRequest != "" { - req := &lnrpc.PayReqString{PayReq: req.PaymentRequest} - resp, err := client.DecodePayReq(context.Background(), req) - if err != nil { - return err - } - - invoiceAmt := resp.GetNumSatoshis() - if invoiceAmt != 0 { - amt = invoiceAmt - } - - if !ctx.Bool("force") { - err := confirmPayReq(resp, amt) - if err != nil { - return err - } - } - } - - paymentStream, err := client.SendPayment(context.Background()) - if err != nil { - return err - } - - if err := paymentStream.Send(req); err != nil { - return err - } - - resp, err := paymentStream.Recv() - if err != nil { - return err - } - - paymentStream.CloseSend() - - printRespJSON(resp) - - // If we get a payment error back, we pass an error - // up to main which eventually calls fatal() and returns - // with a non-zero exit code. - if resp.PaymentError != "" { - return errors.New(resp.PaymentError) - } - - return nil -} - -var payInvoiceCommand = cli.Command{ - Name: "payinvoice", - Category: "Payments", - Usage: "Pay an invoice over lightning.", - ArgsUsage: "pay_req", - Flags: append(paymentFlags(), - cli.Int64Flag{ - Name: "amt", - Usage: "(optional) number of satoshis to fulfill the " + - "invoice", - }, - ), - Action: actionDecorator(payInvoice), -} - -func payInvoice(ctx *cli.Context) error { - args := ctx.Args() - - var payReq string - switch { - case ctx.IsSet("pay_req"): - payReq = ctx.String("pay_req") - case args.Present(): - payReq = args.First() - default: - return fmt.Errorf("pay_req argument missing") - } - - req := &lnrpc.SendRequest{ - PaymentRequest: payReq, - Amt: ctx.Int64("amt"), - DestCustomRecords: make(map[uint64][]byte), - } - - return sendPaymentRequest(ctx, req) -} - -var sendToRouteCommand = cli.Command{ - Name: "sendtoroute", - Category: "Payments", - Usage: "Send a payment over a predefined route.", - Description: ` - Send a payment over Lightning using a specific route. One must specify - the route to attempt and the payment hash. This command can even - be chained with the response to queryroutes or buildroute. This command - can be used to implement channel rebalancing by crafting a self-route, - or even atomic swaps using a self-route that crosses multiple chains. - - There are three ways to specify a route: - * using the --routes parameter to manually specify a JSON encoded - route in the format of the return value of queryroutes or - buildroute: - (lncli sendtoroute --payment_hash= --routes=) - - * passing the route as a positional argument: - (lncli sendtoroute --payment_hash=pay_hash ) - - * or reading in the route from stdin, which can allow chaining the - response from queryroutes or buildroute, or even read in a file - with a pre-computed route: - (lncli queryroutes --args.. | lncli sendtoroute --payment_hash= - - - notice the '-' at the end, which signals that lncli should read - the route in from stdin - `, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "payment_hash, pay_hash", - Usage: "the hash to use within the payment's HTLC", - }, - cli.StringFlag{ - Name: "routes, r", - Usage: "a json array string in the format of the response " + - "of queryroutes that denotes which routes to use", - }, - }, - Action: sendToRoute, -} - -func sendToRoute(ctx *cli.Context) error { - // Show command help if no arguments provided. - if ctx.NArg() == 0 && ctx.NumFlags() == 0 { - cli.ShowCommandHelp(ctx, "sendtoroute") - return nil - } - - args := ctx.Args() - - var ( - rHash []byte - err error - ) - switch { - case ctx.IsSet("payment_hash"): - rHash, err = hex.DecodeString(ctx.String("payment_hash")) - case args.Present(): - rHash, err = hex.DecodeString(args.First()) - - args = args.Tail() - default: - return fmt.Errorf("payment hash argument missing") - } - - if err != nil { - return err - } - - if len(rHash) != 32 { - return fmt.Errorf("payment hash must be exactly 32 "+ - "bytes, is instead %d", len(rHash)) - } - - var jsonRoutes string - switch { - // The user is specifying the routes explicitly via the key word - // argument. - case ctx.IsSet("routes"): - jsonRoutes = ctx.String("routes") - - // The user is specifying the routes as a positional argument. - case args.Present() && args.First() != "-": - jsonRoutes = args.First() - - // The user is signalling that we should read stdin in order to parse - // the set of target routes. - case args.Present() && args.First() == "-": - b, err := ioutil.ReadAll(os.Stdin) - if err != nil { - return err - } - if len(b) == 0 { - return fmt.Errorf("queryroutes output is empty") - } - - jsonRoutes = string(b) - } - - // Try to parse the provided json both in the legacy QueryRoutes format - // that contains a list of routes and the single route BuildRoute - // format. - var route *lnrpc.Route - routes := &lnrpc.QueryRoutesResponse{} - err = jsonpb.UnmarshalString(jsonRoutes, routes) - if err == nil { - if len(routes.Routes) == 0 { - return fmt.Errorf("no routes provided") - } - - if len(routes.Routes) != 1 { - return fmt.Errorf("expected a single route, but got %v", - len(routes.Routes)) - } - - route = routes.Routes[0] - } else { - routes := &routerrpc.BuildRouteResponse{} - err = jsonpb.UnmarshalString(jsonRoutes, routes) - if err != nil { - return fmt.Errorf("unable to unmarshal json string "+ - "from incoming array of routes: %v", err) - } - - route = routes.Route - } - - req := &lnrpc.SendToRouteRequest{ - PaymentHash: rHash, - Route: route, - } - - return sendToRouteRequest(ctx, req) -} - -func sendToRouteRequest(ctx *cli.Context, req *lnrpc.SendToRouteRequest) error { - client, cleanUp := getClient(ctx) - defer cleanUp() - - paymentStream, err := client.SendToRoute(context.Background()) - if err != nil { - return err - } - - if err := paymentStream.Send(req); err != nil { - return err - } - - resp, err := paymentStream.Recv() - if err != nil { - return err - } - - printRespJSON(resp) - - return nil -} - var addInvoiceCommand = cli.Command{ Name: "addinvoice", Category: "Payments", From dead6a772a765d7d023f4c04d5c313744a2240b6 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 12:45:14 +0200 Subject: [PATCH 352/562] lncli: use routerrpc for payments --- cmd/lncli/cmd_pay.go | 136 +++++++++++++++++++++++++----------------- cmd/lncli/commands.go | 34 ++++++++++- 2 files changed, 113 insertions(+), 57 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index e2414f27ad..55741bc185 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -20,6 +20,12 @@ import ( "github.com/urfave/cli" ) +const ( + // paymentTimeoutSeconds is the default timeout for the payment loop in + // lnd. No new attempts will be started after the timeout. + paymentTimeoutSeconds = 60 +) + var ( cltvLimitFlag = cli.UintFlag{ Name: "cltv_limit", @@ -127,34 +133,36 @@ var sendPaymentCommand = cli.Command{ } // retrieveFeeLimit retrieves the fee limit based on the different fee limit -// flags passed. -func retrieveFeeLimit(ctx *cli.Context) (*lnrpc.FeeLimit, error) { +// flags passed. It always returns a value and doesn't rely on lnd applying a +// default. +func retrieveFeeLimit(ctx *cli.Context, amt int64) (int64, error) { switch { + case ctx.IsSet("fee_limit") && ctx.IsSet("fee_limit_percent"): - return nil, fmt.Errorf("either fee_limit or fee_limit_percent " + + return 0, fmt.Errorf("either fee_limit or fee_limit_percent " + "can be set, but not both") + case ctx.IsSet("fee_limit"): - return &lnrpc.FeeLimit{ - Limit: &lnrpc.FeeLimit_Fixed{ - Fixed: ctx.Int64("fee_limit"), - }, - }, nil + return ctx.Int64("fee_limit"), nil + case ctx.IsSet("fee_limit_percent"): - return &lnrpc.FeeLimit{ - Limit: &lnrpc.FeeLimit_Percent{ - Percent: ctx.Int64("fee_limit_percent"), - }, - }, nil + // Round up the fee limit to prevent hitting zero on small + // amounts. + feeLimitRoundedUp := + (amt*ctx.Int64("fee_limit_percent") + 99) / 100 + + return feeLimitRoundedUp, nil } - // Since the fee limit flags aren't required, we don't return an error - // if they're not set. - return nil, nil + // If no fee limit is set, use the payment amount as a limit (100%). + return amt, nil } -func confirmPayReq(resp *lnrpc.PayReq, amt int64) error { +func confirmPayReq(resp *lnrpc.PayReq, amt, feeLimit int64) error { + fmt.Printf("Payment hash: %v\n", resp.GetPaymentHash()) fmt.Printf("Description: %v\n", resp.GetDescription()) fmt.Printf("Amount (in satoshis): %v\n", amt) + fmt.Printf("Fee limit (in satoshis): %v\n", feeLimit) fmt.Printf("Destination: %v\n", resp.GetDestination()) confirm := promptForConfirmation("Confirm payment (yes/no): ") @@ -175,7 +183,7 @@ func sendPayment(ctx *cli.Context) error { // If a payment request was provided, we can exit early since all of the // details of the payment are encoded within the request. if ctx.IsSet("pay_req") { - req := &lnrpc.SendRequest{ + req := &routerrpc.SendPaymentRequest{ PaymentRequest: ctx.String("pay_req"), Amt: ctx.Int64("amt"), } @@ -219,7 +227,7 @@ func sendPayment(ctx *cli.Context) error { } } - req := &lnrpc.SendRequest{ + req := &routerrpc.SendPaymentRequest{ Dest: destNode, Amt: amount, DestCustomRecords: make(map[uint64][]byte), @@ -279,18 +287,14 @@ func sendPayment(ctx *cli.Context) error { return sendPaymentRequest(ctx, req) } -func sendPaymentRequest(ctx *cli.Context, req *lnrpc.SendRequest) error { - client, cleanUp := getClient(ctx) - defer cleanUp() +func sendPaymentRequest(ctx *cli.Context, + req *routerrpc.SendPaymentRequest) error { - // First, we'll retrieve the fee limit value passed since it can apply - // to both ways of sending payments (with the payment request or - // providing the details manually). - feeLimit, err := retrieveFeeLimit(ctx) - if err != nil { - return err - } - req.FeeLimit = feeLimit + conn := getClientConn(ctx, false) + defer conn.Close() + + client := lnrpc.NewLightningClient(conn) + routerClient := routerrpc.NewRouterClient(conn) req.OutgoingChanId = ctx.Uint64("outgoing_chan_id") if ctx.IsSet(lastHopFlag.Name) { @@ -303,7 +307,8 @@ func sendPaymentRequest(ctx *cli.Context, req *lnrpc.SendRequest) error { req.LastHopPubkey = lastHop[:] } - req.CltvLimit = uint32(ctx.Int(cltvLimitFlag.Name)) + req.CltvLimit = int32(ctx.Int(cltvLimitFlag.Name)) + req.TimeoutSeconds = paymentTimeoutSeconds req.AllowSelfPayment = ctx.Bool("allow_self_payment") @@ -334,54 +339,73 @@ func sendPaymentRequest(ctx *cli.Context, req *lnrpc.SendRequest) error { } } - amt := req.Amt - + var feeLimit int64 if req.PaymentRequest != "" { - req := &lnrpc.PayReqString{PayReq: req.PaymentRequest} - resp, err := client.DecodePayReq(context.Background(), req) + // Decode payment request to find out the amount. + decodeReq := &lnrpc.PayReqString{PayReq: req.PaymentRequest} + decodeResp, err := client.DecodePayReq( + context.Background(), decodeReq, + ) if err != nil { return err } - invoiceAmt := resp.GetNumSatoshis() + // If amount is present in the request, override the request + // amount. + amt := req.Amt + invoiceAmt := decodeResp.GetNumSatoshis() if invoiceAmt != 0 { amt = invoiceAmt } + // Calculate fee limit based on the determined amount. + feeLimit, err = retrieveFeeLimit(ctx, amt) + if err != nil { + return err + } + + // Ask for confirmation of amount and fee limit if payment is + // forced. if !ctx.Bool("force") { - err := confirmPayReq(resp, amt) + err := confirmPayReq(decodeResp, amt, feeLimit) if err != nil { return err } } + } else { + var err error + feeLimit, err = retrieveFeeLimit(ctx, req.Amt) + if err != nil { + return err + } } - paymentStream, err := client.SendPayment(context.Background()) - if err != nil { - return err - } - - if err := paymentStream.Send(req); err != nil { - return err - } + req.FeeLimitSat = feeLimit - resp, err := paymentStream.Recv() + stream, err := routerClient.SendPayment(context.Background(), req) if err != nil { return err } - paymentStream.CloseSend() + for { + status, err := stream.Recv() + if err != nil { + return err + } - printRespJSON(resp) + if status.State != routerrpc.PaymentState_IN_FLIGHT { + printRespJSON(status) - // If we get a payment error back, we pass an error - // up to main which eventually calls fatal() and returns - // with a non-zero exit code. - if resp.PaymentError != "" { - return errors.New(resp.PaymentError) - } + // If we get a payment error back, we pass an error up + // to main which eventually calls fatal() and returns + // with a non-zero exit code. + if status.State != routerrpc.PaymentState_SUCCEEDED { + return errors.New(status.State.String()) + } - return nil + return nil + } + } } var payInvoiceCommand = cli.Command{ @@ -412,7 +436,7 @@ func payInvoice(ctx *cli.Context) error { return fmt.Errorf("pay_req argument missing") } - req := &lnrpc.SendRequest{ + req := &routerrpc.SendPaymentRequest{ PaymentRequest: payReq, Amt: ctx.Int64("amt"), DestCustomRecords: make(map[uint64][]byte), diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index c9cd0732ab..5ab5fd52be 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -2380,7 +2380,7 @@ func queryRoutes(ctx *cli.Context) error { return fmt.Errorf("amt argument missing") } - feeLimit, err := retrieveFeeLimit(ctx) + feeLimit, err := retrieveFeeLimitLegacy(ctx) if err != nil { return err } @@ -2403,6 +2403,38 @@ func queryRoutes(ctx *cli.Context) error { return nil } +// retrieveFeeLimitLegacy retrieves the fee limit based on the different fee +// limit flags passed. This function will eventually disappear in favor of +// retrieveFeeLimit and the new payment rpc. +func retrieveFeeLimitLegacy(ctx *cli.Context) (*lnrpc.FeeLimit, error) { + switch { + case ctx.IsSet("fee_limit") && ctx.IsSet("fee_limit_percent"): + return nil, fmt.Errorf("either fee_limit or fee_limit_percent " + + "can be set, but not both") + case ctx.IsSet("fee_limit"): + return &lnrpc.FeeLimit{ + Limit: &lnrpc.FeeLimit_Fixed{ + Fixed: ctx.Int64("fee_limit"), + }, + }, nil + case ctx.IsSet("fee_limit_percent"): + feeLimitPercent := ctx.Int64("fee_limit_percent") + if feeLimitPercent < 0 { + return nil, errors.New("negative fee limit percentage " + + "provided") + } + return &lnrpc.FeeLimit{ + Limit: &lnrpc.FeeLimit_Percent{ + Percent: feeLimitPercent, + }, + }, nil + } + + // Since the fee limit flags aren't required, we don't return an error + // if they're not set. + return nil, nil +} + var getNetworkInfoCommand = cli.Command{ Name: "getnetworkinfo", Category: "Channels", From acefb642078aa73b28d4afe59cdb018686f10bfd Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 15:03:50 +0200 Subject: [PATCH 353/562] routerrpc: remove payment-level route field With multi-part payments, a payment-level route field does not make sense anymore. --- lnrpc/routerrpc/router.pb.go | 284 +++++++++++++++---------------- lnrpc/routerrpc/router.proto | 7 +- lnrpc/routerrpc/router_server.go | 29 ---- 3 files changed, 139 insertions(+), 181 deletions(-) diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index ea4f940fb7..c9254c2848 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -467,10 +467,7 @@ type PaymentStatus struct { //The pre-image of the payment when state is SUCCEEDED. Preimage []byte `protobuf:"bytes,2,opt,name=preimage,proto3" json:"preimage,omitempty"` //* - //The taken route when state is SUCCEEDED. - Route *lnrpc.Route `protobuf:"bytes,3,opt,name=route,proto3" json:"route,omitempty"` - //* - //The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. + //The HTLCs made in attempt to settle the payment. Htlcs []*lnrpc.HTLCAttempt `protobuf:"bytes,4,rep,name=htlcs,proto3" json:"htlcs,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -516,13 +513,6 @@ func (m *PaymentStatus) GetPreimage() []byte { return nil } -func (m *PaymentStatus) GetRoute() *lnrpc.Route { - if m != nil { - return m.Route - } - return nil -} - func (m *PaymentStatus) GetHtlcs() []*lnrpc.HTLCAttempt { if m != nil { return m.Htlcs @@ -1723,142 +1713,142 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2155 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xdd, 0x72, 0xdb, 0xc6, - 0x15, 0x36, 0x28, 0x50, 0x22, 0x0f, 0x7f, 0x04, 0xad, 0x1c, 0x99, 0xa5, 0xec, 0x44, 0x41, 0x13, - 0x9b, 0xe3, 0x3a, 0x92, 0xa3, 0x76, 0x5a, 0x4f, 0xdb, 0xa4, 0x43, 0x91, 0x90, 0x09, 0x99, 0x02, - 0x98, 0x25, 0xe4, 0x9f, 0xfa, 0x62, 0x07, 0x22, 0x97, 0x22, 0x2a, 0x10, 0x60, 0x81, 0xa5, 0x3d, - 0xba, 0xec, 0xf4, 0xae, 0x2f, 0xd2, 0x5e, 0xf5, 0x09, 0xfa, 0x2e, 0xbd, 0xed, 0x13, 0x74, 0x7a, - 0xd9, 0xd9, 0xc5, 0x82, 0x04, 0x29, 0xca, 0xc9, 0x8d, 0x4d, 0x7c, 0xe7, 0xdb, 0xb3, 0xe7, 0x77, - 0xcf, 0xae, 0x60, 0x2f, 0x0a, 0x67, 0x8c, 0x46, 0xd1, 0x74, 0x70, 0x94, 0xfc, 0x3a, 0x9c, 0x46, - 0x21, 0x0b, 0x51, 0x71, 0x8e, 0xd7, 0x8b, 0xd1, 0x74, 0x90, 0xa0, 0xfa, 0xff, 0xf2, 0x80, 0xfa, - 0x34, 0x18, 0xf6, 0xdc, 0x9b, 0x09, 0x0d, 0x18, 0xa6, 0x7f, 0x9e, 0xd1, 0x98, 0x21, 0x04, 0xea, - 0x90, 0xc6, 0xac, 0xa6, 0x1c, 0x28, 0x8d, 0x32, 0x16, 0xbf, 0x91, 0x06, 0x1b, 0xee, 0x84, 0xd5, - 0x72, 0x07, 0x4a, 0x63, 0x03, 0xf3, 0x9f, 0xe8, 0x67, 0x50, 0x70, 0x27, 0x8c, 0x4c, 0x62, 0x97, - 0xd5, 0xca, 0x02, 0xde, 0x72, 0x27, 0xec, 0x3c, 0x76, 0x19, 0xfa, 0x12, 0xca, 0xd3, 0x44, 0x25, - 0x19, 0xbb, 0xf1, 0xb8, 0xb6, 0x21, 0x14, 0x95, 0x24, 0xd6, 0x71, 0xe3, 0x31, 0x6a, 0x80, 0x36, - 0xf2, 0x02, 0xd7, 0x27, 0x03, 0x9f, 0x7d, 0x20, 0x43, 0xea, 0x33, 0xb7, 0xa6, 0x1e, 0x28, 0x8d, - 0x3c, 0xae, 0x0a, 0xbc, 0xe5, 0xb3, 0x0f, 0x6d, 0x8e, 0xa2, 0x27, 0xb0, 0x9d, 0x2a, 0x8b, 0x12, - 0x03, 0x6b, 0xf9, 0x03, 0xa5, 0x51, 0xc4, 0xd5, 0xe9, 0xb2, 0xd9, 0x4f, 0x60, 0x9b, 0x79, 0x13, - 0x1a, 0xce, 0x18, 0x89, 0xe9, 0x20, 0x0c, 0x86, 0x71, 0x6d, 0x33, 0xd1, 0x28, 0xe1, 0x7e, 0x82, - 0x22, 0x1d, 0x2a, 0x23, 0x4a, 0x89, 0xef, 0x4d, 0x3c, 0x46, 0xb8, 0xf9, 0x5b, 0xc2, 0xfc, 0xd2, - 0x88, 0xd2, 0x2e, 0xc7, 0xfa, 0x2e, 0x43, 0x5f, 0x41, 0x75, 0xc1, 0x11, 0x3e, 0x56, 0x04, 0xa9, - 0x9c, 0x92, 0x84, 0xa3, 0xcf, 0x40, 0x0b, 0x67, 0xec, 0x2a, 0xf4, 0x82, 0x2b, 0x32, 0x18, 0xbb, - 0x01, 0xf1, 0x86, 0xb5, 0xc2, 0x81, 0xd2, 0x50, 0x4f, 0x72, 0xcf, 0x15, 0x5c, 0x4d, 0x65, 0xad, - 0xb1, 0x1b, 0x98, 0x43, 0xf4, 0x18, 0xb6, 0x7d, 0x37, 0x66, 0x64, 0x1c, 0x4e, 0xc9, 0x74, 0x76, - 0x79, 0x4d, 0x6f, 0x6a, 0x55, 0x11, 0x99, 0x0a, 0x87, 0x3b, 0xe1, 0xb4, 0x27, 0x40, 0xf4, 0x08, - 0x40, 0x44, 0x45, 0x6c, 0x5e, 0x2b, 0x0a, 0x1f, 0x8a, 0x1c, 0x11, 0x1b, 0xa3, 0x6f, 0xa1, 0x24, - 0xb2, 0x49, 0xc6, 0x5e, 0xc0, 0xe2, 0x1a, 0x1c, 0x6c, 0x34, 0x4a, 0xc7, 0xda, 0xa1, 0x1f, 0xf0, - 0xc4, 0x62, 0x2e, 0xe9, 0x78, 0x01, 0xc3, 0x10, 0xa5, 0x3f, 0x63, 0x34, 0x84, 0x5d, 0x9e, 0x45, - 0x32, 0x98, 0xc5, 0x2c, 0x9c, 0x90, 0x88, 0x0e, 0xc2, 0x68, 0x18, 0xd7, 0x4a, 0x62, 0xe9, 0xaf, - 0x0e, 0xe7, 0xc5, 0x71, 0x78, 0xbb, 0x1a, 0x0e, 0xdb, 0x34, 0x66, 0x2d, 0xb1, 0x0e, 0x27, 0xcb, - 0x8c, 0x80, 0x45, 0x37, 0x78, 0x67, 0xb8, 0x8a, 0xa3, 0x67, 0x80, 0x5c, 0xdf, 0x0f, 0x3f, 0x92, - 0x98, 0xfa, 0x23, 0x22, 0xb3, 0x53, 0xdb, 0x3e, 0x50, 0x1a, 0x05, 0xac, 0x09, 0x49, 0x9f, 0xfa, - 0x23, 0xa9, 0x1e, 0xfd, 0x1a, 0x2a, 0xc2, 0xa6, 0x11, 0x75, 0xd9, 0x2c, 0xa2, 0x71, 0x4d, 0x3b, - 0xd8, 0x68, 0x54, 0x8f, 0x77, 0xa4, 0x23, 0xa7, 0x09, 0x7c, 0xe2, 0x31, 0x5c, 0xe6, 0x3c, 0xf9, - 0x1d, 0xd7, 0xdb, 0xb0, 0xb7, 0xde, 0x24, 0x5e, 0xa3, 0x3c, 0xa6, 0xbc, 0x6c, 0x55, 0xcc, 0x7f, - 0xa2, 0xfb, 0x90, 0xff, 0xe0, 0xfa, 0x33, 0x2a, 0xea, 0xb6, 0x8c, 0x93, 0x8f, 0xdf, 0xe6, 0x5e, - 0x28, 0xfa, 0x0b, 0xd8, 0x75, 0x22, 0x77, 0x70, 0xbd, 0x52, 0xfa, 0xab, 0x95, 0xab, 0xdc, 0xaa, - 0x5c, 0xfd, 0x1f, 0x0a, 0x54, 0xe4, 0xaa, 0x3e, 0x73, 0xd9, 0x2c, 0x46, 0xdf, 0x40, 0x3e, 0x66, - 0x2e, 0xa3, 0x82, 0x5d, 0x3d, 0x7e, 0x90, 0x89, 0x67, 0x86, 0x48, 0x71, 0xc2, 0x42, 0x75, 0x28, - 0x4c, 0x23, 0xea, 0x4d, 0xdc, 0xab, 0xd4, 0xae, 0xf9, 0x37, 0xd2, 0x21, 0x2f, 0x16, 0x8b, 0x96, - 0x29, 0x1d, 0x97, 0xb3, 0x59, 0xc5, 0x89, 0x08, 0x35, 0x20, 0x3f, 0x66, 0xfe, 0x20, 0xae, 0xa9, - 0x22, 0x7d, 0x48, 0x72, 0x3a, 0x4e, 0xb7, 0xd5, 0x64, 0x8c, 0x4e, 0xa6, 0x0c, 0x27, 0x04, 0xfd, - 0x7b, 0xd8, 0x16, 0x2b, 0x4f, 0x29, 0xfd, 0x54, 0x6f, 0x3f, 0x00, 0xde, 0xb9, 0xa2, 0x13, 0x92, - 0xfe, 0xde, 0x74, 0x27, 0xbc, 0x09, 0xf4, 0x21, 0x68, 0x8b, 0xf5, 0xf1, 0x34, 0x0c, 0x62, 0xbe, - 0xbb, 0xc6, 0xcd, 0xe0, 0x15, 0xcf, 0x1b, 0x44, 0xb4, 0x86, 0x22, 0x56, 0x55, 0x25, 0x7e, 0x4a, - 0xa9, 0x68, 0x8e, 0xc7, 0x49, 0x3f, 0x12, 0x3f, 0x1c, 0x5c, 0xf3, 0x0e, 0x77, 0x6f, 0xa4, 0xfa, - 0x0a, 0x87, 0xbb, 0xe1, 0xe0, 0xba, 0xcd, 0x41, 0xfd, 0x7d, 0x72, 0x08, 0x39, 0x61, 0xe2, 0xe5, - 0x4f, 0xce, 0xc4, 0x22, 0x58, 0xb9, 0x3b, 0x83, 0xa5, 0xbf, 0x87, 0xdd, 0x25, 0xe5, 0xd2, 0x8b, - 0x6c, 0x0e, 0x94, 0x95, 0x1c, 0x34, 0x60, 0x6b, 0xe4, 0x7a, 0xfe, 0x2c, 0x4a, 0x15, 0x57, 0xd3, - 0x92, 0x4c, 0x50, 0x9c, 0x8a, 0xf5, 0x87, 0x50, 0xc7, 0x34, 0xa6, 0xec, 0xdc, 0x8b, 0x63, 0x2f, - 0x0c, 0x5a, 0x61, 0xc0, 0xa2, 0xd0, 0x97, 0x1e, 0xe8, 0x8f, 0x60, 0x7f, 0xad, 0x34, 0x31, 0x81, - 0x2f, 0xfe, 0x61, 0x46, 0xa3, 0x9b, 0xf5, 0x8b, 0x7f, 0x80, 0xfd, 0xb5, 0x52, 0x69, 0xff, 0x33, - 0xc8, 0x4f, 0x5d, 0x2f, 0x8a, 0x6b, 0x39, 0x51, 0x03, 0x7b, 0x4b, 0x25, 0xe7, 0x45, 0x1d, 0x2f, - 0x66, 0x61, 0x74, 0x83, 0x13, 0xd2, 0x99, 0x5a, 0x50, 0xb4, 0x9c, 0xfe, 0x37, 0x05, 0x4a, 0x19, - 0x21, 0xda, 0x87, 0x62, 0x10, 0x0e, 0x29, 0x19, 0x45, 0xe1, 0x24, 0x0d, 0x02, 0x07, 0x4e, 0xa3, - 0x70, 0xc2, 0x6b, 0x42, 0x08, 0x59, 0x28, 0x6b, 0x74, 0x93, 0x7f, 0x3a, 0x21, 0xfa, 0x06, 0xb6, - 0xc6, 0x89, 0x02, 0x71, 0x6c, 0x96, 0x8e, 0x77, 0x57, 0xf6, 0x6e, 0xbb, 0xcc, 0xc5, 0x29, 0xe7, - 0x4c, 0x2d, 0x6c, 0x68, 0xea, 0x99, 0x5a, 0x50, 0xb5, 0xfc, 0x99, 0x5a, 0xc8, 0x6b, 0x9b, 0x67, - 0x6a, 0x61, 0x53, 0xdb, 0xd2, 0xff, 0xa3, 0x40, 0x21, 0x65, 0x73, 0x4b, 0x78, 0x48, 0x09, 0xaf, - 0x0b, 0x59, 0x4c, 0x05, 0x0e, 0x38, 0xde, 0x84, 0xa2, 0x03, 0x28, 0x0b, 0xe1, 0x72, 0x89, 0x02, - 0xc7, 0x9a, 0xa2, 0x4c, 0xc5, 0x79, 0x9e, 0x32, 0x44, 0x3d, 0xaa, 0xf2, 0x3c, 0x4f, 0x28, 0xe9, - 0x48, 0x8a, 0x67, 0x83, 0x01, 0x8d, 0xe3, 0x64, 0x97, 0x7c, 0x42, 0x91, 0x98, 0xd8, 0xe8, 0x31, - 0x6c, 0xa7, 0x94, 0x74, 0xaf, 0xcd, 0xa4, 0x5e, 0x25, 0x2c, 0xb7, 0x6b, 0x80, 0x96, 0xe5, 0x4d, - 0x16, 0x13, 0xa4, 0xba, 0x20, 0xf2, 0x4d, 0x13, 0xe7, 0xf5, 0x3f, 0xc1, 0x03, 0x91, 0xca, 0x5e, - 0x14, 0x5e, 0xba, 0x97, 0x9e, 0xef, 0xb1, 0x9b, 0xb4, 0xc8, 0xb9, 0xe3, 0x51, 0x38, 0x21, 0x3c, - 0xb6, 0x69, 0x0a, 0x38, 0x60, 0x85, 0x43, 0xca, 0x53, 0xc0, 0xc2, 0x44, 0x24, 0x53, 0xc0, 0x42, - 0x21, 0xc8, 0x4e, 0xde, 0x8d, 0xa5, 0xc9, 0xab, 0x5f, 0x43, 0xed, 0xf6, 0x5e, 0xb2, 0x66, 0x0e, - 0xa0, 0x34, 0x5d, 0xc0, 0x62, 0x3b, 0x05, 0x67, 0xa1, 0x6c, 0x6e, 0x73, 0x3f, 0x9e, 0x5b, 0xfd, - 0xef, 0x0a, 0xec, 0x9c, 0xcc, 0x3c, 0x7f, 0xb8, 0xd4, 0xb8, 0x59, 0xeb, 0x94, 0xe5, 0x7b, 0xc1, - 0xba, 0xa1, 0x9f, 0x5b, 0x3b, 0xf4, 0xd7, 0x0d, 0xd6, 0x8d, 0x3b, 0x07, 0xeb, 0x17, 0x50, 0x5a, - 0xcc, 0xd4, 0xe4, 0x5c, 0x2c, 0x63, 0x18, 0xa7, 0x03, 0x35, 0xd6, 0x5f, 0x00, 0xca, 0x1a, 0x2a, - 0x03, 0x32, 0x3f, 0x3f, 0x94, 0xbb, 0xcf, 0x8f, 0x87, 0x50, 0xef, 0xcf, 0x2e, 0xe3, 0x41, 0xe4, - 0x5d, 0xd2, 0x0e, 0xf3, 0x07, 0xc6, 0x07, 0x1a, 0xb0, 0x38, 0xed, 0xd2, 0xff, 0xaa, 0x50, 0x9c, - 0xa3, 0xe8, 0x10, 0x76, 0xbd, 0x60, 0x10, 0x4e, 0x52, 0xa3, 0x03, 0xea, 0x73, 0xbb, 0x93, 0x79, - 0xb4, 0x93, 0x8a, 0x5a, 0x89, 0xc4, 0x1c, 0x72, 0xfe, 0x92, 0x93, 0x92, 0x9f, 0x4b, 0xf8, 0x59, - 0x1f, 0x13, 0x7e, 0x03, 0xb4, 0xb9, 0x7e, 0x7e, 0xc0, 0xcf, 0x83, 0x82, 0xab, 0x29, 0xce, 0x8d, - 0x49, 0x98, 0x73, 0xcd, 0x29, 0x53, 0x4d, 0x98, 0x29, 0x2e, 0x99, 0x5f, 0x42, 0x99, 0xf7, 0x43, - 0xcc, 0xdc, 0xc9, 0x94, 0x04, 0xb1, 0xe8, 0x0b, 0x15, 0x97, 0xe6, 0x98, 0x15, 0xa3, 0xef, 0x00, - 0x28, 0xf7, 0x8f, 0xb0, 0x9b, 0x29, 0x15, 0x2d, 0x51, 0x3d, 0xfe, 0x3c, 0x53, 0x18, 0xf3, 0x00, - 0x1c, 0x8a, 0x7f, 0x9d, 0x9b, 0x29, 0xc5, 0x45, 0x9a, 0xfe, 0x44, 0xdf, 0x43, 0x65, 0x14, 0x46, - 0x1f, 0xdd, 0x68, 0x48, 0x04, 0x28, 0x8f, 0x8d, 0xec, 0x94, 0x3c, 0x4d, 0xe4, 0x62, 0x79, 0xe7, - 0x1e, 0x2e, 0x8f, 0x32, 0xdf, 0xe8, 0x15, 0xa0, 0x74, 0xbd, 0xe8, 0xf2, 0x44, 0x49, 0x41, 0x28, - 0xd9, 0xbf, 0xad, 0x84, 0x1f, 0xd2, 0xa9, 0x22, 0x6d, 0xb4, 0x82, 0xa1, 0xdf, 0x41, 0x39, 0xa6, - 0x8c, 0xf9, 0x54, 0xaa, 0x29, 0x0a, 0x35, 0x7b, 0x4b, 0x37, 0x20, 0x2e, 0x4e, 0x35, 0x94, 0xe2, - 0xc5, 0x27, 0x3a, 0x81, 0x6d, 0xdf, 0x0b, 0xae, 0xb3, 0x66, 0x80, 0x58, 0x5f, 0xcb, 0xac, 0xef, - 0x7a, 0xc1, 0x75, 0xd6, 0x86, 0x8a, 0x9f, 0x05, 0xf4, 0xdf, 0x43, 0x71, 0x1e, 0x25, 0x54, 0x82, - 0xad, 0x0b, 0xeb, 0x95, 0x65, 0xbf, 0xb1, 0xb4, 0x7b, 0xa8, 0x00, 0x6a, 0xdf, 0xb0, 0xda, 0x9a, - 0xc2, 0x61, 0x6c, 0xb4, 0x0c, 0xf3, 0xb5, 0xa1, 0xe5, 0xf8, 0xc7, 0xa9, 0x8d, 0xdf, 0x34, 0x71, - 0x5b, 0xdb, 0x38, 0xd9, 0x82, 0xbc, 0xd8, 0x57, 0xff, 0x97, 0x02, 0x05, 0x91, 0xc1, 0x60, 0x14, - 0xa2, 0x5f, 0xc0, 0xbc, 0xb8, 0xc4, 0xe1, 0xc6, 0x07, 0xae, 0xa8, 0xba, 0x0a, 0x9e, 0x17, 0x8c, - 0x23, 0x71, 0x4e, 0x9e, 0x97, 0xc6, 0x9c, 0x9c, 0x4b, 0xc8, 0xa9, 0x60, 0x4e, 0x7e, 0x9a, 0xd1, - 0xbc, 0x74, 0xe4, 0xa8, 0x78, 0x3b, 0x15, 0xa4, 0x27, 0xec, 0xd3, 0x8c, 0xe2, 0xa5, 0x93, 0x58, - 0xc5, 0xdb, 0xa9, 0x40, 0x72, 0xf5, 0xdf, 0x40, 0x39, 0x9b, 0x73, 0xf4, 0x04, 0x54, 0x2f, 0x18, - 0x85, 0xb2, 0x11, 0x77, 0x57, 0x8a, 0x8b, 0x3b, 0x89, 0x05, 0x41, 0x47, 0xa0, 0xad, 0xe6, 0x59, - 0xaf, 0x40, 0x29, 0x93, 0x34, 0xfd, 0xdf, 0x0a, 0x54, 0x96, 0x92, 0xf0, 0x93, 0xb5, 0xa3, 0xef, - 0xa0, 0xfc, 0xd1, 0x8b, 0x28, 0xc9, 0x8e, 0xff, 0xea, 0x71, 0x7d, 0x79, 0xfc, 0xa7, 0xff, 0xb7, - 0xc2, 0x21, 0xc5, 0x25, 0xce, 0x97, 0x00, 0xfa, 0x03, 0x54, 0xe5, 0x4a, 0x32, 0xa4, 0xcc, 0xf5, - 0x7c, 0x11, 0xaa, 0xea, 0x52, 0x79, 0x48, 0x6e, 0x5b, 0xc8, 0x71, 0x65, 0x94, 0xfd, 0x44, 0x5f, - 0x2f, 0x14, 0xc4, 0x2c, 0xf2, 0x82, 0x2b, 0x11, 0xbf, 0xe2, 0x9c, 0xd6, 0x17, 0xe0, 0xd3, 0x7f, - 0x2a, 0x50, 0xce, 0x5e, 0x2c, 0x51, 0x05, 0x8a, 0xa6, 0x45, 0x4e, 0xbb, 0xe6, 0xcb, 0x8e, 0xa3, - 0xdd, 0xe3, 0x9f, 0xfd, 0x8b, 0x56, 0xcb, 0x30, 0xda, 0x06, 0x2f, 0x27, 0x04, 0xd5, 0xd3, 0xa6, - 0xd9, 0x35, 0xda, 0xc4, 0x31, 0xcf, 0x0d, 0xfb, 0xc2, 0xd1, 0x72, 0x68, 0x17, 0xb6, 0x25, 0x66, - 0xd9, 0x04, 0xdb, 0x17, 0x8e, 0xa1, 0x6d, 0x20, 0x0d, 0xca, 0x12, 0x34, 0x30, 0xb6, 0xb1, 0xa6, - 0xa2, 0xaf, 0xe0, 0x40, 0x22, 0xa6, 0xd5, 0xb2, 0x31, 0x36, 0x5a, 0x0e, 0xe9, 0x35, 0xdf, 0x9d, - 0x1b, 0x96, 0x43, 0xda, 0x86, 0xd3, 0x34, 0xbb, 0x7d, 0x2d, 0x8f, 0xbe, 0x80, 0xfd, 0x39, 0xab, - 0x7f, 0x71, 0x7a, 0x6a, 0xb6, 0x4c, 0x4e, 0x38, 0x69, 0x76, 0x9b, 0x56, 0xcb, 0xd0, 0x36, 0x9f, - 0xfe, 0x45, 0x85, 0xca, 0x92, 0xe3, 0xcb, 0x95, 0x5f, 0x81, 0xa2, 0x65, 0x4b, 0x7d, 0x9a, 0xc2, - 0xcd, 0xb0, 0x2d, 0xd3, 0xb6, 0x48, 0xdb, 0x68, 0xd9, 0x6d, 0xde, 0x03, 0x9f, 0xc1, 0x4e, 0xd7, - 0xb4, 0x5e, 0x11, 0xcb, 0x76, 0x88, 0xd1, 0x35, 0x5f, 0x9a, 0x27, 0x5d, 0x6e, 0xef, 0x7d, 0xd0, - 0x6c, 0x8b, 0xb4, 0x3a, 0x4d, 0xd3, 0x9a, 0xbb, 0xa6, 0x72, 0x94, 0x5f, 0x85, 0x89, 0xf1, 0x96, - 0x47, 0xa0, 0x4f, 0xce, 0x9b, 0x6f, 0xb5, 0x3c, 0xaa, 0xc1, 0xfd, 0xf5, 0xc6, 0xa1, 0x3d, 0x40, - 0xdc, 0xb9, 0xf3, 0x5e, 0xd7, 0x70, 0x0c, 0x92, 0xf6, 0xda, 0x16, 0x0f, 0x91, 0xd0, 0xd3, 0x6c, - 0xb7, 0x49, 0xe2, 0x9e, 0x56, 0xe0, 0x96, 0x48, 0x46, 0x9f, 0xb4, 0xcd, 0x7e, 0xf3, 0x84, 0xc3, - 0x45, 0xbe, 0xa7, 0x69, 0xbd, 0xb6, 0xcd, 0x96, 0x41, 0x5a, 0x5c, 0x2d, 0x47, 0x81, 0x93, 0x53, - 0xf4, 0xc2, 0x6a, 0x1b, 0xb8, 0xd7, 0x34, 0xdb, 0x5a, 0x09, 0xed, 0xc3, 0x83, 0x14, 0x36, 0xde, - 0xf6, 0x4c, 0xfc, 0x8e, 0x38, 0xb6, 0x4d, 0xfa, 0xb6, 0x6d, 0x69, 0xe5, 0xac, 0x26, 0xee, 0xad, - 0xdd, 0x33, 0x2c, 0xad, 0x82, 0x1e, 0xc0, 0xee, 0x79, 0xaf, 0x47, 0x52, 0x49, 0xea, 0x6c, 0x95, - 0xd3, 0x9b, 0xed, 0x36, 0x36, 0xfa, 0x7d, 0x72, 0x6e, 0xf6, 0xcf, 0x9b, 0x4e, 0xab, 0xa3, 0x6d, - 0x73, 0x97, 0xfa, 0x86, 0x43, 0x1c, 0xdb, 0x69, 0x76, 0x17, 0xb8, 0xc6, 0x0d, 0x5a, 0xe0, 0x7c, - 0xd3, 0xae, 0xfd, 0x46, 0xdb, 0xe1, 0x01, 0xe7, 0xb0, 0xfd, 0x5a, 0x9a, 0x88, 0xb8, 0xef, 0x32, - 0x3d, 0xe9, 0x9e, 0xda, 0x2e, 0x07, 0x4d, 0xeb, 0x75, 0xb3, 0x6b, 0xb6, 0xc9, 0x2b, 0xe3, 0x9d, - 0x38, 0xab, 0xee, 0x73, 0x30, 0xb1, 0x8c, 0xf4, 0xb0, 0xfd, 0x92, 0x1b, 0xa2, 0x7d, 0xc6, 0x2b, - 0xae, 0x65, 0xe2, 0xd6, 0x45, 0xb7, 0x89, 0x65, 0x71, 0xed, 0x1d, 0xff, 0x75, 0x13, 0x36, 0xc5, - 0x64, 0x8d, 0x50, 0x87, 0x37, 0xec, 0xfc, 0x9d, 0x89, 0x1e, 0x7d, 0xf2, 0xfd, 0x59, 0xaf, 0xad, - 0x7f, 0x4e, 0xcd, 0xe2, 0xe7, 0x0a, 0x3a, 0x83, 0x72, 0xf6, 0x15, 0x87, 0xb2, 0x63, 0x69, 0xcd, - 0xf3, 0xee, 0x93, 0xba, 0x5e, 0x81, 0x66, 0xc4, 0xcc, 0x9b, 0xf0, 0x97, 0x9a, 0x7c, 0xf4, 0xa0, - 0x7a, 0x86, 0xbf, 0xf2, 0x92, 0xaa, 0xef, 0xaf, 0x95, 0xc9, 0xab, 0x45, 0x37, 0x71, 0x51, 0x3e, - 0x3b, 0x6e, 0xb9, 0xb8, 0xfc, 0xd6, 0xa9, 0x7f, 0x7e, 0x97, 0x58, 0x6a, 0x1b, 0xc2, 0xee, 0x9a, - 0x97, 0x04, 0xfa, 0x3a, 0x6b, 0xc1, 0x9d, 0xef, 0x90, 0xfa, 0xe3, 0x1f, 0xa3, 0x2d, 0x76, 0x59, - 0xf3, 0xe4, 0x58, 0xda, 0xe5, 0xee, 0x07, 0xcb, 0xd2, 0x2e, 0x9f, 0x7a, 0xb9, 0xbc, 0x07, 0x6d, - 0xf5, 0x86, 0x8a, 0xf4, 0xd5, 0xb5, 0xb7, 0xaf, 0xca, 0xf5, 0x9f, 0x7f, 0x92, 0x23, 0x95, 0x9b, - 0x00, 0x8b, 0x7b, 0x1e, 0x7a, 0x98, 0x59, 0x72, 0xeb, 0x9e, 0x5a, 0x7f, 0x74, 0x87, 0x54, 0xaa, - 0x72, 0x60, 0x77, 0xcd, 0xc5, 0x6f, 0x29, 0x1a, 0x77, 0x5f, 0x0c, 0xeb, 0xf7, 0xd7, 0xdd, 0x8f, - 0x9e, 0x2b, 0x27, 0xdf, 0xfe, 0xf1, 0xe8, 0xca, 0x63, 0xe3, 0xd9, 0xe5, 0xe1, 0x20, 0x9c, 0x1c, - 0xf9, 0xde, 0xd5, 0x98, 0x05, 0x5e, 0x70, 0x15, 0x50, 0xf6, 0x31, 0x8c, 0xae, 0x8f, 0xfc, 0x60, - 0x78, 0x24, 0x86, 0xcd, 0xd1, 0x7c, 0xf9, 0xe5, 0xa6, 0xf8, 0x5b, 0xdd, 0x2f, 0xff, 0x1f, 0x00, - 0x00, 0xff, 0xff, 0xe9, 0x0c, 0xc3, 0x27, 0xdb, 0x13, 0x00, 0x00, + // 2150 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xdd, 0x72, 0xdb, 0xb8, + 0x15, 0x0e, 0x6d, 0xca, 0x96, 0x8e, 0x7e, 0x4c, 0x43, 0x59, 0x47, 0x95, 0x93, 0x5d, 0x2d, 0xbb, + 0x9b, 0x68, 0xd2, 0xac, 0x9d, 0x75, 0x3b, 0x6d, 0xa6, 0xed, 0x6e, 0x47, 0x96, 0xe8, 0x88, 0x8e, + 0x4c, 0x6a, 0x21, 0x3a, 0x3f, 0xcd, 0x05, 0x86, 0x96, 0x20, 0x8b, 0x35, 0x45, 0xaa, 0x24, 0x94, + 0x8c, 0x2f, 0x3b, 0xbd, 0xeb, 0x8b, 0xf4, 0xae, 0x4f, 0xd0, 0x77, 0xe9, 0x6d, 0x9f, 0xa0, 0xd3, + 0xcb, 0x1d, 0x80, 0xa0, 0x44, 0xd9, 0x72, 0x76, 0x6f, 0x12, 0xf1, 0x3b, 0x1f, 0x0e, 0xce, 0x39, + 0xf8, 0x80, 0x03, 0x18, 0xf6, 0xa2, 0x70, 0xce, 0x68, 0x14, 0xcd, 0x86, 0x87, 0xc9, 0xaf, 0x83, + 0x59, 0x14, 0xb2, 0x10, 0x15, 0x16, 0x78, 0xbd, 0x10, 0xcd, 0x86, 0x09, 0xaa, 0xff, 0x3f, 0x07, + 0x68, 0x40, 0x83, 0x51, 0xdf, 0xbd, 0x9e, 0xd2, 0x80, 0x61, 0xfa, 0xd7, 0x39, 0x8d, 0x19, 0x42, + 0xa0, 0x8e, 0x68, 0xcc, 0x6a, 0x4a, 0x43, 0x69, 0x96, 0xb0, 0xf8, 0x8d, 0x34, 0xd8, 0x74, 0xa7, + 0xac, 0xb6, 0xd1, 0x50, 0x9a, 0x9b, 0x98, 0xff, 0x44, 0xbf, 0x80, 0xbc, 0x3b, 0x65, 0x64, 0x1a, + 0xbb, 0xac, 0x56, 0x12, 0xf0, 0xb6, 0x3b, 0x65, 0x67, 0xb1, 0xcb, 0xd0, 0x97, 0x50, 0x9a, 0x25, + 0x2e, 0xc9, 0xc4, 0x8d, 0x27, 0xb5, 0x4d, 0xe1, 0xa8, 0x28, 0xb1, 0xae, 0x1b, 0x4f, 0x50, 0x13, + 0xb4, 0xb1, 0x17, 0xb8, 0x3e, 0x19, 0xfa, 0xec, 0x03, 0x19, 0x51, 0x9f, 0xb9, 0x35, 0xb5, 0xa1, + 0x34, 0x73, 0xb8, 0x22, 0xf0, 0xb6, 0xcf, 0x3e, 0x74, 0x38, 0x8a, 0x9e, 0xc0, 0x4e, 0xea, 0x2c, + 0x4a, 0x02, 0xac, 0xe5, 0x1a, 0x4a, 0xb3, 0x80, 0x2b, 0xb3, 0xd5, 0xb0, 0x9f, 0xc0, 0x0e, 0xf3, + 0xa6, 0x34, 0x9c, 0x33, 0x12, 0xd3, 0x61, 0x18, 0x8c, 0xe2, 0xda, 0x56, 0xe2, 0x51, 0xc2, 0x83, + 0x04, 0x45, 0x3a, 0x94, 0xc7, 0x94, 0x12, 0xdf, 0x9b, 0x7a, 0x8c, 0xf0, 0xf0, 0xb7, 0x45, 0xf8, + 0xc5, 0x31, 0xa5, 0x3d, 0x8e, 0x0d, 0x5c, 0x86, 0xbe, 0x82, 0xca, 0x92, 0x23, 0x72, 0x2c, 0x0b, + 0x52, 0x29, 0x25, 0x89, 0x44, 0x9f, 0x81, 0x16, 0xce, 0xd9, 0x65, 0xe8, 0x05, 0x97, 0x64, 0x38, + 0x71, 0x03, 0xe2, 0x8d, 0x6a, 0xf9, 0x86, 0xd2, 0x54, 0x8f, 0x37, 0x9e, 0x2b, 0xb8, 0x92, 0xda, + 0xda, 0x13, 0x37, 0x30, 0x47, 0xe8, 0x31, 0xec, 0xf8, 0x6e, 0xcc, 0xc8, 0x24, 0x9c, 0x91, 0xd9, + 0xfc, 0xe2, 0x8a, 0x5e, 0xd7, 0x2a, 0xa2, 0x32, 0x65, 0x0e, 0x77, 0xc3, 0x59, 0x5f, 0x80, 0xe8, + 0x11, 0x80, 0xa8, 0x8a, 0x98, 0xbc, 0x56, 0x10, 0x39, 0x14, 0x38, 0x22, 0x26, 0x46, 0xdf, 0x42, + 0x51, 0xac, 0x26, 0x99, 0x78, 0x01, 0x8b, 0x6b, 0xd0, 0xd8, 0x6c, 0x16, 0x8f, 0xb4, 0x03, 0x3f, + 0xe0, 0x0b, 0x8b, 0xb9, 0xa5, 0xeb, 0x05, 0x0c, 0x43, 0x94, 0xfe, 0x8c, 0xd1, 0x08, 0xaa, 0x7c, + 0x15, 0xc9, 0x70, 0x1e, 0xb3, 0x70, 0x4a, 0x22, 0x3a, 0x0c, 0xa3, 0x51, 0x5c, 0x2b, 0x8a, 0xa1, + 0xbf, 0x39, 0x58, 0x88, 0xe3, 0xe0, 0xb6, 0x1a, 0x0e, 0x3a, 0x34, 0x66, 0x6d, 0x31, 0x0e, 0x27, + 0xc3, 0x8c, 0x80, 0x45, 0xd7, 0x78, 0x77, 0x74, 0x13, 0x47, 0xcf, 0x00, 0xb9, 0xbe, 0x1f, 0x7e, + 0x24, 0x31, 0xf5, 0xc7, 0x44, 0xae, 0x4e, 0x6d, 0xa7, 0xa1, 0x34, 0xf3, 0x58, 0x13, 0x96, 0x01, + 0xf5, 0xc7, 0xd2, 0x3d, 0xfa, 0x2d, 0x94, 0x45, 0x4c, 0x63, 0xea, 0xb2, 0x79, 0x44, 0xe3, 0x9a, + 0xd6, 0xd8, 0x6c, 0x56, 0x8e, 0x76, 0x65, 0x22, 0x27, 0x09, 0x7c, 0xec, 0x31, 0x5c, 0xe2, 0x3c, + 0xf9, 0x1d, 0xd7, 0x3b, 0xb0, 0xb7, 0x3e, 0x24, 0xae, 0x51, 0x5e, 0x53, 0x2e, 0x5b, 0x15, 0xf3, + 0x9f, 0xe8, 0x3e, 0xe4, 0x3e, 0xb8, 0xfe, 0x9c, 0x0a, 0xdd, 0x96, 0x70, 0xf2, 0xf1, 0xfb, 0x8d, + 0x17, 0x8a, 0xfe, 0x02, 0xaa, 0x4e, 0xe4, 0x0e, 0xaf, 0x6e, 0x48, 0xff, 0xa6, 0x72, 0x95, 0x5b, + 0xca, 0xd5, 0xff, 0xa1, 0x40, 0x59, 0x8e, 0x1a, 0x30, 0x97, 0xcd, 0x63, 0xf4, 0x0d, 0xe4, 0x62, + 0xe6, 0x32, 0x2a, 0xd8, 0x95, 0xa3, 0x07, 0x99, 0x7a, 0x66, 0x88, 0x14, 0x27, 0x2c, 0x54, 0x87, + 0xfc, 0x2c, 0xa2, 0xde, 0xd4, 0xbd, 0x4c, 0xe3, 0x5a, 0x7c, 0xa3, 0x26, 0xe4, 0x26, 0xcc, 0x1f, + 0xc6, 0x35, 0x55, 0x2c, 0x0d, 0x92, 0xc5, 0xe8, 0x3a, 0xbd, 0x76, 0x8b, 0x31, 0x3a, 0x9d, 0x31, + 0x9c, 0x10, 0x4e, 0xd5, 0xfc, 0xa6, 0xa6, 0xea, 0xdf, 0xc3, 0x8e, 0x58, 0xf1, 0x13, 0x4a, 0x3f, + 0xb5, 0x7b, 0x1f, 0x00, 0xdf, 0x9b, 0x42, 0xeb, 0xc9, 0x0e, 0xde, 0x72, 0xa7, 0x5c, 0xe6, 0xfa, + 0x08, 0xb4, 0xe5, 0xf8, 0x78, 0x16, 0x06, 0x31, 0x8f, 0x41, 0xe3, 0x09, 0x70, 0x4d, 0xf3, 0x2d, + 0x20, 0xc4, 0xaf, 0x88, 0x51, 0x15, 0x89, 0x9f, 0x50, 0x2a, 0xe4, 0xff, 0x38, 0xd9, 0x71, 0xc4, + 0x0f, 0x87, 0x57, 0x7c, 0x0f, 0xbb, 0xd7, 0xd2, 0x7d, 0x99, 0xc3, 0xbd, 0x70, 0x78, 0xd5, 0xe1, + 0xa0, 0xfe, 0x3e, 0x39, 0x66, 0x9c, 0x50, 0xcc, 0xf5, 0xf3, 0x6b, 0x8d, 0x74, 0xc8, 0x89, 0x5a, + 0x0a, 0xb7, 0xc5, 0xa3, 0x52, 0x56, 0xe4, 0x38, 0x31, 0xe9, 0xef, 0xa1, 0xba, 0xe2, 0x5c, 0x66, + 0x91, 0xad, 0xb2, 0x72, 0xab, 0xca, 0xdb, 0x63, 0xd7, 0xf3, 0xe7, 0x51, 0xea, 0xb8, 0x92, 0x8a, + 0x2e, 0x41, 0x71, 0x6a, 0xd6, 0x1f, 0x42, 0x1d, 0xd3, 0x98, 0xb2, 0x33, 0x2f, 0x8e, 0xbd, 0x30, + 0x68, 0x87, 0x01, 0x8b, 0x42, 0x5f, 0x66, 0xa0, 0x3f, 0x82, 0xfd, 0xb5, 0xd6, 0x24, 0x04, 0x3e, + 0xf8, 0x87, 0x39, 0x8d, 0xae, 0xd7, 0x0f, 0xfe, 0x01, 0xf6, 0xd7, 0x5a, 0x65, 0xfc, 0xcf, 0x20, + 0x37, 0x73, 0xbd, 0x28, 0xae, 0x6d, 0x08, 0x25, 0xec, 0xad, 0x88, 0xca, 0x8b, 0xba, 0x5e, 0xcc, + 0xc2, 0xe8, 0x1a, 0x27, 0xa4, 0x53, 0x35, 0xaf, 0x68, 0x1b, 0x5c, 0x9a, 0xc5, 0x8c, 0x11, 0xed, + 0x43, 0x21, 0x08, 0x47, 0x94, 0x8c, 0xa3, 0x70, 0x9a, 0x16, 0x81, 0x03, 0x27, 0x51, 0x38, 0xe5, + 0x9a, 0x10, 0x46, 0x16, 0x4a, 0x15, 0x6e, 0xf1, 0x4f, 0x27, 0x44, 0xdf, 0xc0, 0xf6, 0x24, 0x71, + 0x20, 0x0e, 0xc6, 0xe2, 0x51, 0xf5, 0xc6, 0xdc, 0x1d, 0x97, 0xb9, 0x38, 0xe5, 0x24, 0x42, 0x3c, + 0x55, 0xf3, 0xaa, 0x96, 0x3b, 0x55, 0xf3, 0x39, 0x6d, 0xeb, 0x54, 0xcd, 0x6f, 0x69, 0xdb, 0xfa, + 0x7f, 0x15, 0xc8, 0xa7, 0x6c, 0x1e, 0x09, 0x2f, 0x29, 0xe1, 0xba, 0x90, 0x62, 0xca, 0x73, 0xc0, + 0xf1, 0xa6, 0x14, 0x35, 0xa0, 0x24, 0x8c, 0xab, 0x12, 0x05, 0x8e, 0xb5, 0x84, 0x4c, 0xc5, 0x89, + 0x9d, 0x32, 0x84, 0x1e, 0x55, 0x79, 0x62, 0x27, 0x94, 0xb4, 0xe9, 0xc4, 0xf3, 0xe1, 0x90, 0xc6, + 0x71, 0x32, 0x4b, 0x2e, 0xa1, 0x48, 0x4c, 0x4c, 0xf4, 0x18, 0x76, 0x52, 0x4a, 0x3a, 0xd7, 0x56, + 0xa2, 0x57, 0x09, 0xcb, 0xe9, 0x9a, 0xa0, 0x65, 0x79, 0xd3, 0x65, 0x8f, 0xa8, 0x2c, 0x89, 0x7c, + 0x52, 0xb9, 0x0b, 0xff, 0x02, 0x0f, 0xc4, 0x52, 0xf6, 0xa3, 0xf0, 0xc2, 0xbd, 0xf0, 0x7c, 0x8f, + 0x5d, 0xa7, 0x22, 0xe7, 0x89, 0x47, 0xe1, 0x94, 0xf0, 0xda, 0xa6, 0x4b, 0xc0, 0x01, 0x2b, 0x1c, + 0x51, 0xbe, 0x04, 0x2c, 0x4c, 0x4c, 0x72, 0x09, 0x58, 0x28, 0x0c, 0xd9, 0xde, 0xba, 0xb9, 0xd2, + 0x5b, 0xf5, 0x2b, 0xa8, 0xdd, 0x9e, 0x4b, 0x6a, 0xa6, 0x01, 0xc5, 0xd9, 0x12, 0x16, 0xd3, 0x29, + 0x38, 0x0b, 0x65, 0xd7, 0x76, 0xe3, 0xa7, 0xd7, 0x56, 0xff, 0xa7, 0x02, 0xbb, 0xc7, 0x73, 0xcf, + 0x1f, 0xad, 0x6c, 0xdc, 0x6c, 0x74, 0xca, 0x6a, 0xe7, 0x5f, 0xd7, 0xd6, 0x37, 0xd6, 0xb6, 0xf5, + 0x75, 0xad, 0x73, 0xf3, 0xce, 0xd6, 0xf9, 0x05, 0x14, 0x97, 0x5d, 0x33, 0x39, 0x1d, 0x4b, 0x18, + 0x26, 0x69, 0xcb, 0x8c, 0xf5, 0x17, 0x80, 0xb2, 0x81, 0xca, 0x82, 0x2c, 0xce, 0x0f, 0xe5, 0xee, + 0xf3, 0xe3, 0x21, 0xd4, 0x07, 0xf3, 0x8b, 0x78, 0x18, 0x79, 0x17, 0xb4, 0xcb, 0xfc, 0xa1, 0xf1, + 0x81, 0x06, 0x2c, 0x4e, 0x77, 0xe9, 0xff, 0x54, 0x28, 0x2c, 0x50, 0x74, 0x00, 0x55, 0x2f, 0x18, + 0x86, 0xd3, 0x34, 0xe8, 0x80, 0xfa, 0x3c, 0xee, 0xa4, 0xe3, 0xec, 0xa6, 0xa6, 0x76, 0x62, 0x31, + 0x47, 0x9c, 0xbf, 0x92, 0xa4, 0xe4, 0x6f, 0x24, 0xfc, 0x6c, 0x8e, 0x09, 0xbf, 0x09, 0xda, 0xc2, + 0x3f, 0x3f, 0xe6, 0x17, 0x45, 0xc1, 0x95, 0x14, 0xe7, 0xc1, 0x24, 0xcc, 0x85, 0xe7, 0x94, 0xa9, + 0x26, 0xcc, 0x14, 0x97, 0xcc, 0x2f, 0xa1, 0xc4, 0xf7, 0x43, 0xcc, 0xdc, 0xe9, 0x8c, 0x04, 0xb1, + 0xd8, 0x17, 0x2a, 0x2e, 0x2e, 0x30, 0x2b, 0x46, 0xdf, 0x01, 0x50, 0x9e, 0x1f, 0x61, 0xd7, 0x33, + 0x2a, 0xb6, 0x44, 0xe5, 0xe8, 0xf3, 0x8c, 0x30, 0x16, 0x05, 0x38, 0x10, 0xff, 0x3a, 0xd7, 0x33, + 0x8a, 0x0b, 0x34, 0xfd, 0x89, 0xbe, 0x87, 0xf2, 0x38, 0x8c, 0x3e, 0xba, 0xd1, 0x88, 0x08, 0x50, + 0x1e, 0x1b, 0xd9, 0x3e, 0x78, 0x92, 0xd8, 0xc5, 0xf0, 0xee, 0x3d, 0x5c, 0x1a, 0x67, 0xbe, 0xd1, + 0x2b, 0x40, 0xe9, 0x78, 0xb1, 0xcb, 0x13, 0x27, 0x79, 0xe1, 0x64, 0xff, 0xb6, 0x13, 0x7e, 0x48, + 0xa7, 0x8e, 0xb4, 0xf1, 0x0d, 0x0c, 0xfd, 0x01, 0x4a, 0x31, 0x65, 0xcc, 0xa7, 0xd2, 0x4d, 0x41, + 0xb8, 0xd9, 0x5b, 0xb9, 0xe3, 0x70, 0x73, 0xea, 0xa1, 0x18, 0x2f, 0x3f, 0xd1, 0x31, 0xec, 0xf8, + 0x5e, 0x70, 0x95, 0x0d, 0x03, 0xc4, 0xf8, 0x5a, 0x66, 0x7c, 0xcf, 0x0b, 0xae, 0xb2, 0x31, 0x94, + 0xfd, 0x2c, 0xa0, 0xff, 0x11, 0x0a, 0x8b, 0x2a, 0xa1, 0x22, 0x6c, 0x9f, 0x5b, 0xaf, 0x2c, 0xfb, + 0x8d, 0xa5, 0xdd, 0x43, 0x79, 0x50, 0x07, 0x86, 0xd5, 0xd1, 0x14, 0x0e, 0x63, 0xa3, 0x6d, 0x98, + 0xaf, 0x0d, 0x6d, 0x83, 0x7f, 0x9c, 0xd8, 0xf8, 0x4d, 0x0b, 0x77, 0xb4, 0xcd, 0xe3, 0x6d, 0xc8, + 0x89, 0x79, 0xf5, 0x7f, 0x2b, 0x90, 0x17, 0x2b, 0x18, 0x8c, 0x43, 0xf4, 0x2b, 0x58, 0x88, 0x4b, + 0x1c, 0x6e, 0xbc, 0xe1, 0x0a, 0xd5, 0x95, 0xf1, 0x42, 0x30, 0x8e, 0xc4, 0x39, 0x79, 0x21, 0x8d, + 0x05, 0x79, 0x23, 0x21, 0xa7, 0x86, 0x05, 0xf9, 0x69, 0xc6, 0xf3, 0xca, 0x91, 0xa3, 0xe2, 0x9d, + 0xd4, 0x90, 0x9e, 0xb0, 0x4f, 0x33, 0x8e, 0x57, 0x4e, 0x62, 0x15, 0xef, 0xa4, 0x06, 0xc9, 0xd5, + 0x7f, 0x07, 0xa5, 0xec, 0x9a, 0xa3, 0x27, 0xa0, 0x7a, 0xc1, 0x38, 0x94, 0x1b, 0xb1, 0x7a, 0x43, + 0x5c, 0x3c, 0x49, 0x2c, 0x08, 0x3a, 0x02, 0xed, 0xe6, 0x3a, 0xeb, 0x65, 0x28, 0x66, 0x16, 0x4d, + 0xff, 0x8f, 0x02, 0xe5, 0x95, 0x45, 0xf8, 0xd9, 0xde, 0xd1, 0x77, 0x50, 0xfa, 0xe8, 0x45, 0x94, + 0x64, 0xdb, 0x7f, 0xe5, 0xa8, 0xbe, 0xda, 0xfe, 0xd3, 0xff, 0xdb, 0xe1, 0x88, 0xe2, 0x22, 0xe7, + 0x4b, 0x00, 0xfd, 0x09, 0x2a, 0x72, 0x24, 0x19, 0x51, 0xe6, 0x7a, 0xbe, 0x28, 0x55, 0x65, 0x45, + 0x1e, 0x92, 0xdb, 0x11, 0x76, 0x5c, 0x1e, 0x67, 0x3f, 0xd1, 0xd7, 0x4b, 0x07, 0x31, 0x8b, 0xbc, + 0xe0, 0x52, 0xd4, 0xaf, 0xb0, 0xa0, 0x0d, 0x04, 0xf8, 0xf4, 0x5f, 0x0a, 0x94, 0xb2, 0x57, 0x47, + 0x54, 0x86, 0x82, 0x69, 0x91, 0x93, 0x9e, 0xf9, 0xb2, 0xeb, 0x68, 0xf7, 0xf8, 0xe7, 0xe0, 0xbc, + 0xdd, 0x36, 0x8c, 0x8e, 0xc1, 0xe5, 0x84, 0xa0, 0x72, 0xd2, 0x32, 0x7b, 0x46, 0x87, 0x38, 0xe6, + 0x99, 0x61, 0x9f, 0x3b, 0xda, 0x06, 0xaa, 0xc2, 0x8e, 0xc4, 0x2c, 0x9b, 0x60, 0xfb, 0xdc, 0x31, + 0xb4, 0x4d, 0xa4, 0x41, 0x49, 0x82, 0x06, 0xc6, 0x36, 0xd6, 0x54, 0xf4, 0x15, 0x34, 0x24, 0x62, + 0x5a, 0x6d, 0x1b, 0x63, 0xa3, 0xed, 0x90, 0x7e, 0xeb, 0xdd, 0x99, 0x61, 0x39, 0xa4, 0x63, 0x38, + 0x2d, 0xb3, 0x37, 0xd0, 0x72, 0xe8, 0x0b, 0xd8, 0x5f, 0xb0, 0x06, 0xe7, 0x27, 0x27, 0x66, 0xdb, + 0xe4, 0x84, 0xe3, 0x56, 0xaf, 0x65, 0xb5, 0x0d, 0x6d, 0xeb, 0xe9, 0xdf, 0x54, 0x28, 0xaf, 0x24, + 0xbe, 0xaa, 0xfc, 0x32, 0x14, 0x2c, 0x5b, 0xfa, 0xd3, 0x14, 0x1e, 0x86, 0x6d, 0x99, 0xb6, 0x45, + 0x3a, 0x46, 0xdb, 0xee, 0xf0, 0x3d, 0xf0, 0x19, 0xec, 0xf6, 0x4c, 0xeb, 0x15, 0xb1, 0x6c, 0x87, + 0x18, 0x3d, 0xf3, 0xa5, 0x79, 0xdc, 0xe3, 0xf1, 0xde, 0x07, 0xcd, 0xb6, 0x48, 0xbb, 0xdb, 0x32, + 0xad, 0x45, 0x6a, 0x2a, 0x47, 0xf9, 0x85, 0x98, 0x18, 0x6f, 0x79, 0x05, 0x06, 0xe4, 0xac, 0xf5, + 0x56, 0xcb, 0xa1, 0x1a, 0xdc, 0x5f, 0x1f, 0x1c, 0xda, 0x03, 0xc4, 0x93, 0x3b, 0xeb, 0xf7, 0x0c, + 0xc7, 0x20, 0xe9, 0x5e, 0xdb, 0xe6, 0x25, 0x12, 0x7e, 0x5a, 0x9d, 0x0e, 0x49, 0xd2, 0xd3, 0xf2, + 0x3c, 0x12, 0xc9, 0x18, 0x90, 0x8e, 0x39, 0x68, 0x1d, 0x73, 0xb8, 0xc0, 0xe7, 0x34, 0xad, 0xd7, + 0xb6, 0xd9, 0x36, 0x48, 0x9b, 0xbb, 0xe5, 0x28, 0x70, 0x72, 0x8a, 0x9e, 0x5b, 0x1d, 0x03, 0xf7, + 0x5b, 0x66, 0x47, 0x2b, 0xa2, 0x7d, 0x78, 0x90, 0xc2, 0xc6, 0xdb, 0xbe, 0x89, 0xdf, 0x11, 0xc7, + 0xb6, 0xc9, 0xc0, 0xb6, 0x2d, 0xad, 0x94, 0xf5, 0xc4, 0xb3, 0xb5, 0xfb, 0x86, 0xa5, 0x95, 0xd1, + 0x03, 0xa8, 0x9e, 0xf5, 0xfb, 0x24, 0xb5, 0xa4, 0xc9, 0x56, 0x38, 0xbd, 0xd5, 0xe9, 0x60, 0x63, + 0x30, 0x20, 0x67, 0xe6, 0xe0, 0xac, 0xe5, 0xb4, 0xbb, 0xda, 0x0e, 0x4f, 0x69, 0x60, 0x38, 0xc4, + 0xb1, 0x9d, 0x56, 0x6f, 0x89, 0x6b, 0x3c, 0xa0, 0x25, 0xce, 0x27, 0xed, 0xd9, 0x6f, 0xb4, 0x5d, + 0x5e, 0x70, 0x0e, 0xdb, 0xaf, 0x65, 0x88, 0x88, 0xe7, 0x2e, 0x97, 0x27, 0x9d, 0x53, 0xab, 0x72, + 0xd0, 0xb4, 0x5e, 0xb7, 0x7a, 0x66, 0x87, 0xbc, 0x32, 0xde, 0x89, 0xb3, 0xea, 0x3e, 0x07, 0x93, + 0xc8, 0x48, 0x1f, 0xdb, 0x2f, 0x79, 0x20, 0xda, 0x67, 0x5c, 0x71, 0x6d, 0x13, 0xb7, 0xcf, 0x7b, + 0x2d, 0x2c, 0xc5, 0xb5, 0x77, 0xf4, 0xf7, 0x2d, 0xd8, 0x12, 0x9d, 0x35, 0x42, 0x5d, 0xbe, 0x61, + 0x17, 0x2f, 0x49, 0xf4, 0xe8, 0x93, 0x2f, 0xcc, 0x7a, 0x6d, 0xfd, 0x83, 0x69, 0x1e, 0x3f, 0x57, + 0xd0, 0x29, 0x94, 0xb2, 0xef, 0x34, 0x94, 0x6d, 0x4b, 0x6b, 0x1e, 0x70, 0x9f, 0xf4, 0xf5, 0x0a, + 0x34, 0x23, 0x66, 0xde, 0x94, 0xbf, 0xc5, 0xe4, 0xa3, 0x07, 0xd5, 0x33, 0xfc, 0x1b, 0x2f, 0xa9, + 0xfa, 0xfe, 0x5a, 0x9b, 0xbc, 0x5a, 0xf4, 0x92, 0x14, 0xe5, 0xb3, 0xe3, 0x56, 0x8a, 0xab, 0x6f, + 0x9d, 0xfa, 0xe7, 0x77, 0x99, 0xa5, 0xb7, 0x11, 0x54, 0xd7, 0xbc, 0x24, 0xd0, 0xd7, 0xd9, 0x08, + 0xee, 0x7c, 0x87, 0xd4, 0x1f, 0xff, 0x14, 0x6d, 0x39, 0xcb, 0x9a, 0x27, 0xc7, 0xca, 0x2c, 0x77, + 0x3f, 0x58, 0x56, 0x66, 0xf9, 0xd4, 0xcb, 0xe5, 0x3d, 0x68, 0x37, 0x6f, 0xa8, 0x48, 0xbf, 0x39, + 0xf6, 0xf6, 0x55, 0xb9, 0xfe, 0xcb, 0x4f, 0x72, 0xa4, 0x73, 0x13, 0x60, 0x79, 0xcf, 0x43, 0x0f, + 0x33, 0x43, 0x6e, 0xdd, 0x53, 0xeb, 0x8f, 0xee, 0xb0, 0x4a, 0x57, 0x0e, 0x54, 0xd7, 0x5c, 0xfc, + 0x56, 0xaa, 0x71, 0xf7, 0xc5, 0xb0, 0x7e, 0x7f, 0xdd, 0xfd, 0xe8, 0xb9, 0x72, 0xfc, 0xed, 0x9f, + 0x0f, 0x2f, 0x3d, 0x36, 0x99, 0x5f, 0x1c, 0x0c, 0xc3, 0xe9, 0xa1, 0xef, 0x5d, 0x4e, 0x58, 0xe0, + 0x05, 0x97, 0x01, 0x65, 0x1f, 0xc3, 0xe8, 0xea, 0xd0, 0x0f, 0x46, 0x87, 0xa2, 0xd9, 0x1c, 0x2e, + 0x86, 0x5f, 0x6c, 0x89, 0xbf, 0xc6, 0xfd, 0xfa, 0xc7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x84, + 0xd2, 0x59, 0xbd, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 7a63f86aea..4ff1135d9c 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -169,13 +169,10 @@ message PaymentStatus { */ bytes preimage = 2; - /** - The taken route when state is SUCCEEDED. - */ - lnrpc.Route route = 3; + reserved 3; /** - The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. + The HTLCs made in attempt to settle the payment. */ repeated lnrpc.HTLCAttempt htlcs = 4; } diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index acdc8da343..80e4ebf450 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -485,35 +485,6 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash, status.State = state } - // Extract the last route from the given list of HTLCs. This - // will populate the legacy route field for backwards - // compatibility. - // - // NOTE: For now there will be at most one HTLC, this code - // should be revisted or the field removed when multiple HTLCs - // are permitted. - var legacyRoute *route.Route - for _, htlc := range result.HTLCs { - switch { - case htlc.Settle != nil: - legacyRoute = &htlc.Route - - // Only display the route for failed payments if we got - // an incorrect payment details error, so that it can be - // used for probing or fee estimation. - case htlc.Failure != nil && result.FailureReason == - channeldb.FailureReasonPaymentDetails: - - legacyRoute = &htlc.Route - } - } - if legacyRoute != nil { - status.Route, err = router.MarshallRoute(legacyRoute) - if err != nil { - return err - } - } - // Marshal our list of HTLCs that have been tried for this // payment. htlcs := make([]*lnrpc.HTLCAttempt, 0, len(result.HTLCs)) From 37849194f452e46ec1e0b6e53a4de140df8b1c46 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 12:55:10 +0200 Subject: [PATCH 354/562] lncli: add trackpayment command --- cmd/lncli/cmd_pay.go | 52 ++++++++++++++++++++++++++++++++++++++++++++ cmd/lncli/main.go | 1 + 2 files changed, 53 insertions(+) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 55741bc185..3923bee7ea 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -408,6 +408,58 @@ func sendPaymentRequest(ctx *cli.Context, } } +var trackPaymentCommand = cli.Command{ + Name: "trackpayment", + Category: "Payments", + Usage: "Track progress of an existing payment.", + Description: ` + Pick up monitoring the progression of a previously initiated payment + specified by the hash argument. + `, + ArgsUsage: "hash", + Action: actionDecorator(trackPayment), +} + +func trackPayment(ctx *cli.Context) error { + args := ctx.Args() + + conn := getClientConn(ctx, false) + defer conn.Close() + + client := routerrpc.NewRouterClient(conn) + + if !args.Present() { + return fmt.Errorf("hash argument missing") + } + + hash, err := hex.DecodeString(args.First()) + if err != nil { + return err + } + + req := &routerrpc.TrackPaymentRequest{ + PaymentHash: hash, + } + + stream, err := client.TrackPayment(context.Background(), req) + if err != nil { + return err + } + + for { + status, err := stream.Recv() + if err != nil { + return err + } + + printRespJSON(status) + + if status.State != routerrpc.PaymentState_IN_FLIGHT { + return nil + } + } +} + var payInvoiceCommand = cli.Command{ Name: "payinvoice", Category: "Payments", diff --git a/cmd/lncli/main.go b/cmd/lncli/main.go index e8170c5939..6f0640802f 100644 --- a/cmd/lncli/main.go +++ b/cmd/lncli/main.go @@ -300,6 +300,7 @@ func main() { verifyChanBackupCommand, restoreChanBackupCommand, bakeMacaroonCommand, + trackPaymentCommand, } // Add any extra commands determined by build flags. From 3191b949f5bba2895a4ece1e2114ccb045c0a926 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 30 Mar 2020 15:50:41 +0200 Subject: [PATCH 355/562] lnrpc: deprecate SendPayment There is an alternative in routerrpc now. It doesn't support REST yet, but the main rpc SendPayment with its bidirectional streaming isn't usable via REST either. SendPaymentSync still serves REST users and cannot be deprecated yet. --- lnrpc/rpc.pb.go | 1505 ++++++++++++++++++++++++----------------------- lnrpc/rpc.proto | 15 +- 2 files changed, 763 insertions(+), 757 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 2f7826cc08..77325c1c37 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -11878,749 +11878,749 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11862 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x6f, 0x24, 0x49, - 0x72, 0xd8, 0xf4, 0x8b, 0xdd, 0x1d, 0xfd, 0x60, 0x33, 0xf9, 0xea, 0xe1, 0xcc, 0xec, 0xcc, 0xd6, - 0xee, 0xed, 0xce, 0xce, 0xde, 0x71, 0x66, 0xe7, 0x6e, 0xf6, 0xee, 0x76, 0xad, 0xd3, 0x35, 0xc9, - 0xe6, 0xb0, 0x6f, 0xf8, 0xda, 0xea, 0xe6, 0xae, 0xe6, 0xf4, 0xa8, 0x2b, 0x76, 0x27, 0xc9, 0xd2, - 0x74, 0x57, 0xf5, 0x56, 0x55, 0xf3, 0x71, 0x87, 0xf5, 0x07, 0xc3, 0x16, 0x0c, 0xc3, 0x0f, 0x08, - 0xb6, 0x0c, 0x58, 0xb6, 0x60, 0xc3, 0x82, 0x61, 0x18, 0x06, 0x04, 0x01, 0x27, 0x7f, 0x30, 0xe0, - 0xef, 0x82, 0x01, 0x1b, 0x86, 0x21, 0xf9, 0x8b, 0x21, 0x08, 0x30, 0x6c, 0xcb, 0x1f, 0x0c, 0x18, - 0x02, 0xfc, 0x07, 0x8c, 0x8c, 0xc8, 0xac, 0xca, 0xea, 0x2e, 0xce, 0xcc, 0xde, 0xad, 0xef, 0x0b, - 0xd9, 0x15, 0x19, 0xf9, 0x8e, 0x8c, 0x8c, 0xc8, 0x88, 0xc8, 0x84, 0xb2, 0x3f, 0xee, 0xaf, 0x8f, - 0x7d, 0x2f, 0xf4, 0x58, 0x61, 0xe8, 0xfa, 0xe3, 0xfe, 0xda, 0xed, 0x53, 0xcf, 0x3b, 0x1d, 0xf2, - 0x87, 0xf6, 0xd8, 0x79, 0x68, 0xbb, 0xae, 0x17, 0xda, 0xa1, 0xe3, 0xb9, 0x01, 0x21, 0x19, 0x3f, - 0x82, 0xfa, 0x53, 0xee, 0x76, 0x39, 0x1f, 0x98, 0xfc, 0xf3, 0x09, 0x0f, 0x42, 0xf6, 0x3e, 0x2c, - 0xd8, 0xfc, 0xc7, 0x9c, 0x0f, 0xac, 0xb1, 0x1d, 0x04, 0xe3, 0x33, 0xdf, 0x0e, 0x78, 0x33, 0x73, - 0x2f, 0x73, 0xbf, 0x6a, 0x36, 0x28, 0xe1, 0x30, 0x82, 0xb3, 0x37, 0xa1, 0x1a, 0x08, 0x54, 0xee, - 0x86, 0xbe, 0x37, 0xbe, 0x6a, 0x66, 0x11, 0xaf, 0x22, 0x60, 0x6d, 0x02, 0x19, 0x43, 0x98, 0x8f, - 0x6a, 0x08, 0xc6, 0x9e, 0x1b, 0x70, 0xf6, 0x08, 0x96, 0xfa, 0xce, 0xf8, 0x8c, 0xfb, 0x16, 0x66, - 0x1e, 0xb9, 0x7c, 0xe4, 0xb9, 0x4e, 0xbf, 0x99, 0xb9, 0x97, 0xbb, 0x5f, 0x36, 0x19, 0xa5, 0x89, - 0x1c, 0x7b, 0x32, 0x85, 0xbd, 0x0b, 0xf3, 0xdc, 0x25, 0x38, 0x1f, 0x60, 0x2e, 0x59, 0x55, 0x3d, - 0x06, 0x8b, 0x0c, 0xc6, 0xdf, 0xcc, 0xc2, 0x42, 0xc7, 0x75, 0xc2, 0xcf, 0xec, 0xe1, 0x90, 0x87, - 0xaa, 0x4f, 0xef, 0xc2, 0xfc, 0x05, 0x02, 0xb0, 0x4f, 0x17, 0x9e, 0x3f, 0x90, 0x3d, 0xaa, 0x13, - 0xf8, 0x50, 0x42, 0xaf, 0x6d, 0x59, 0xf6, 0xda, 0x96, 0xa5, 0x0e, 0x57, 0xee, 0x9a, 0xe1, 0x7a, - 0x17, 0xe6, 0x7d, 0xde, 0xf7, 0xce, 0xb9, 0x7f, 0x65, 0x5d, 0x38, 0xee, 0xc0, 0xbb, 0x68, 0xe6, - 0xef, 0x65, 0xee, 0x17, 0xcc, 0xba, 0x02, 0x7f, 0x86, 0x50, 0xb6, 0x01, 0xf3, 0xfd, 0x33, 0xdb, - 0x75, 0xf9, 0xd0, 0x3a, 0xb6, 0xfb, 0x2f, 0x26, 0xe3, 0xa0, 0x59, 0xb8, 0x97, 0xb9, 0x5f, 0x79, - 0x7c, 0x73, 0x1d, 0x67, 0x75, 0x7d, 0xf3, 0xcc, 0x76, 0x37, 0x30, 0xa5, 0xeb, 0xda, 0xe3, 0xe0, - 0xcc, 0x0b, 0xcd, 0xba, 0xcc, 0x41, 0xe0, 0xc0, 0x58, 0x02, 0xa6, 0x8f, 0x04, 0x8d, 0xbd, 0xf1, - 0xaf, 0x33, 0xb0, 0x78, 0xe4, 0x0e, 0xbd, 0xfe, 0x8b, 0x9f, 0x71, 0x88, 0x52, 0xfa, 0x90, 0x7d, - 0xdd, 0x3e, 0xe4, 0xbe, 0x6c, 0x1f, 0x56, 0x60, 0x29, 0xd9, 0x58, 0xd9, 0x0b, 0x0e, 0xcb, 0x22, - 0xf7, 0x29, 0x57, 0xcd, 0x52, 0xdd, 0x78, 0x0f, 0x1a, 0xfd, 0x89, 0xef, 0x73, 0x77, 0xa6, 0x1f, - 0xf3, 0x12, 0x1e, 0x75, 0xe4, 0x4d, 0xa8, 0xba, 0xfc, 0x22, 0x46, 0x93, 0xb4, 0xeb, 0xf2, 0x0b, - 0x85, 0x62, 0x34, 0x61, 0x65, 0xba, 0x1a, 0xd9, 0x80, 0xbf, 0xc8, 0x40, 0xfe, 0x28, 0xbc, 0xf4, - 0xd8, 0x13, 0xa8, 0xda, 0x83, 0x81, 0xcf, 0x83, 0xc0, 0x0a, 0xaf, 0xc6, 0xb4, 0x52, 0xea, 0x8f, - 0x99, 0xec, 0x62, 0x8b, 0x92, 0x7a, 0x57, 0x63, 0x6e, 0x56, 0xec, 0xf8, 0x83, 0x35, 0xa1, 0x28, - 0x3f, 0xb1, 0xde, 0xb2, 0xa9, 0x3e, 0xd9, 0x1d, 0x00, 0x7b, 0xe4, 0x4d, 0xdc, 0xd0, 0x0a, 0xec, - 0x10, 0x47, 0x2c, 0x67, 0x96, 0x09, 0xd2, 0xb5, 0x43, 0x76, 0x0b, 0xca, 0xe3, 0x17, 0x56, 0xd0, - 0xf7, 0x9d, 0x71, 0x88, 0xc4, 0x53, 0x36, 0x4b, 0xe3, 0x17, 0x5d, 0xfc, 0x66, 0xef, 0x43, 0xc9, - 0x9b, 0x84, 0x63, 0xcf, 0x71, 0x43, 0x49, 0x2f, 0xf3, 0xb2, 0x21, 0x07, 0x93, 0xf0, 0x50, 0x80, - 0xcd, 0x08, 0x81, 0xbd, 0x0d, 0xb5, 0xbe, 0xe7, 0x9e, 0x38, 0xfe, 0x88, 0x38, 0x42, 0x73, 0x0e, - 0xeb, 0x4a, 0x02, 0x8d, 0x3f, 0xcc, 0x42, 0xa5, 0xe7, 0xdb, 0x6e, 0x60, 0xf7, 0x05, 0x80, 0xad, - 0x42, 0x31, 0xbc, 0xb4, 0xce, 0xec, 0xe0, 0x0c, 0xbb, 0x5a, 0x36, 0xe7, 0xc2, 0xcb, 0x1d, 0x3b, - 0x38, 0x63, 0x2b, 0x30, 0x47, 0xad, 0xc4, 0x0e, 0xe5, 0x4c, 0xf9, 0x25, 0x16, 0x88, 0x3b, 0x19, - 0x59, 0xc9, 0xaa, 0x72, 0x48, 0x31, 0x0d, 0x77, 0x32, 0xda, 0xd4, 0xe1, 0xa2, 0xf3, 0xc7, 0x62, - 0xba, 0xa9, 0x02, 0xea, 0x5e, 0x19, 0x21, 0x58, 0xc7, 0x9b, 0x50, 0x95, 0xc9, 0xdc, 0x39, 0x3d, - 0xa3, 0x3e, 0x16, 0xcc, 0x0a, 0x21, 0x20, 0x48, 0x94, 0x10, 0x3a, 0x23, 0x6e, 0x05, 0xa1, 0x3d, - 0x1a, 0xcb, 0x2e, 0x95, 0x05, 0xa4, 0x2b, 0x00, 0x98, 0xec, 0x85, 0xf6, 0xd0, 0x3a, 0xe1, 0x3c, - 0x68, 0x16, 0x65, 0xb2, 0x80, 0x6c, 0x73, 0x1e, 0xb0, 0xaf, 0x41, 0x7d, 0xc0, 0x83, 0xd0, 0x92, - 0x93, 0xc1, 0x83, 0x66, 0x09, 0x57, 0x7e, 0x4d, 0x40, 0x5b, 0x0a, 0xc8, 0x6e, 0x03, 0xf8, 0xf6, - 0x85, 0x25, 0x06, 0x82, 0x5f, 0x36, 0xcb, 0x34, 0x0b, 0xbe, 0x7d, 0xd1, 0xbb, 0xdc, 0xe1, 0x97, - 0x82, 0x6a, 0x9e, 0xf2, 0x50, 0x1b, 0xb4, 0x40, 0x52, 0xa7, 0xb1, 0x0b, 0x4c, 0x03, 0x6f, 0xf1, - 0xd0, 0x76, 0x86, 0x01, 0xfb, 0x10, 0xaa, 0xa1, 0x86, 0x8c, 0x6c, 0xb0, 0x12, 0x91, 0x90, 0x96, - 0xc1, 0x4c, 0xe0, 0x19, 0x67, 0x50, 0xda, 0xe6, 0x7c, 0xd7, 0x19, 0x39, 0x21, 0x5b, 0x81, 0xc2, - 0x89, 0x73, 0xc9, 0x89, 0xd8, 0x73, 0x3b, 0x37, 0x4c, 0xfa, 0x64, 0x77, 0x01, 0xf0, 0x87, 0x35, - 0x8a, 0xa8, 0x69, 0xe7, 0x86, 0x59, 0x46, 0xd8, 0x5e, 0x60, 0x87, 0x6c, 0x0d, 0x8a, 0x63, 0xee, - 0xf7, 0xb9, 0x9a, 0xb7, 0x9d, 0x1b, 0xa6, 0x02, 0x6c, 0x14, 0xa1, 0x30, 0x14, 0xa5, 0x1b, 0x7f, - 0x5c, 0x80, 0x4a, 0x97, 0xbb, 0xd1, 0x2a, 0x63, 0x90, 0x17, 0x03, 0x22, 0x57, 0x16, 0xfe, 0x66, - 0x6f, 0x41, 0x05, 0x87, 0x2e, 0x08, 0x7d, 0xc7, 0x3d, 0x25, 0xaa, 0xde, 0xc8, 0x36, 0x33, 0x26, - 0x08, 0x70, 0x17, 0xa1, 0xac, 0x01, 0x39, 0x7b, 0xa4, 0xa8, 0x5a, 0xfc, 0x64, 0x37, 0xa1, 0x64, - 0x8f, 0x42, 0x6a, 0x5e, 0x15, 0xc1, 0x45, 0x7b, 0x14, 0x62, 0xd3, 0xde, 0x84, 0xea, 0xd8, 0xbe, - 0x1a, 0x89, 0xb5, 0x1c, 0x91, 0x43, 0xd5, 0xac, 0x48, 0x18, 0x12, 0xc4, 0x63, 0x58, 0xd4, 0x51, - 0x54, 0xe5, 0x85, 0xa8, 0xf2, 0x05, 0x0d, 0x5b, 0xb6, 0xe1, 0x5d, 0x98, 0x57, 0x79, 0x7c, 0xea, - 0x0f, 0x92, 0x49, 0xd9, 0xac, 0x4b, 0xb0, 0xea, 0xe5, 0x7d, 0x68, 0x9c, 0x38, 0xae, 0x3d, 0xb4, - 0xfa, 0xc3, 0xf0, 0xdc, 0x1a, 0xf0, 0x61, 0x68, 0x23, 0xc5, 0x14, 0xcc, 0x3a, 0xc2, 0x37, 0x87, - 0xe1, 0xf9, 0x96, 0x80, 0xb2, 0xaf, 0x43, 0xf9, 0x84, 0x73, 0x0b, 0x07, 0xab, 0x59, 0x4a, 0x2c, - 0x3c, 0x35, 0x43, 0x66, 0xe9, 0x44, 0xcd, 0xd5, 0xd7, 0xa1, 0xe1, 0x4d, 0xc2, 0x53, 0xcf, 0x71, - 0x4f, 0x2d, 0xc1, 0xef, 0x2c, 0x67, 0x80, 0x34, 0x94, 0xdf, 0xc8, 0x3e, 0xca, 0x98, 0x75, 0x95, - 0x26, 0x38, 0x4f, 0x67, 0xc0, 0xde, 0x81, 0xf9, 0xa1, 0x1d, 0x84, 0xd6, 0x99, 0x37, 0xb6, 0xc6, - 0x93, 0xe3, 0x17, 0xfc, 0xaa, 0x59, 0xc3, 0x81, 0xa8, 0x09, 0xf0, 0x8e, 0x37, 0x3e, 0x44, 0xa0, - 0xa0, 0x6c, 0x6c, 0x27, 0x35, 0x02, 0xee, 0x65, 0xee, 0xd7, 0xcc, 0xb2, 0x80, 0x50, 0xa5, 0xcf, - 0x61, 0x11, 0xa7, 0xa7, 0x3f, 0x09, 0x42, 0x6f, 0x64, 0x09, 0x5e, 0xed, 0x0f, 0x82, 0x66, 0x05, - 0x69, 0xed, 0x3d, 0xd9, 0x58, 0x6d, 0x8e, 0xd7, 0xb7, 0x78, 0x10, 0x6e, 0x22, 0xb2, 0x49, 0xb8, - 0x62, 0x43, 0xbf, 0x32, 0x17, 0x06, 0xd3, 0x70, 0xf6, 0x75, 0x60, 0xf6, 0x70, 0xe8, 0x5d, 0x58, - 0x01, 0x1f, 0x9e, 0x58, 0x72, 0x10, 0x9b, 0xf5, 0x7b, 0x99, 0xfb, 0x25, 0xb3, 0x81, 0x29, 0x5d, - 0x3e, 0x3c, 0x39, 0x24, 0x38, 0xfb, 0x10, 0x70, 0x31, 0x59, 0x27, 0xdc, 0x0e, 0x27, 0x3e, 0x0f, - 0x9a, 0xf3, 0xf7, 0x72, 0xf7, 0xeb, 0x8f, 0x17, 0xa2, 0xf1, 0x42, 0xf0, 0x86, 0x13, 0x9a, 0x55, - 0x81, 0x27, 0xbf, 0x83, 0xb5, 0x2d, 0x58, 0x49, 0x6f, 0x92, 0x20, 0x2a, 0x31, 0x2a, 0x82, 0x18, - 0xf3, 0xa6, 0xf8, 0xc9, 0x96, 0xa0, 0x70, 0x6e, 0x0f, 0x27, 0x5c, 0xf2, 0x74, 0xfa, 0xf8, 0x28, - 0xfb, 0x9d, 0x8c, 0xf1, 0x47, 0x19, 0xa8, 0x52, 0x2f, 0xa5, 0x2c, 0xf2, 0x16, 0xd4, 0x14, 0x35, - 0x70, 0xdf, 0xf7, 0x7c, 0xc9, 0xd5, 0x14, 0xe5, 0xb5, 0x05, 0x4c, 0xec, 0x2a, 0x0a, 0x69, 0xec, - 0x73, 0x67, 0x64, 0x9f, 0xaa, 0xa2, 0x15, 0x29, 0x1d, 0x4a, 0x30, 0xfb, 0x20, 0x2e, 0xcf, 0xf7, - 0x26, 0x21, 0x97, 0x7b, 0x5e, 0x55, 0x76, 0xcf, 0x14, 0xb0, 0xa8, 0x74, 0xfc, 0x7a, 0x0d, 0x3a, - 0x37, 0x7e, 0x27, 0x03, 0x4c, 0x34, 0xbb, 0xe7, 0x51, 0x01, 0x92, 0x42, 0xa7, 0x73, 0x66, 0x5e, - 0x7b, 0x85, 0x64, 0x5f, 0xb6, 0x42, 0x0c, 0x28, 0x50, 0xdb, 0xf3, 0x29, 0x6d, 0xa7, 0xa4, 0x1f, - 0xe4, 0x4b, 0xb9, 0x46, 0xde, 0xf8, 0xaf, 0x39, 0x58, 0xda, 0xa4, 0x2d, 0xbb, 0xd5, 0xef, 0xf3, - 0x71, 0xb4, 0x76, 0xee, 0x42, 0xc5, 0xf5, 0x06, 0x5c, 0x51, 0x2c, 0x35, 0x0c, 0x04, 0x48, 0x23, - 0xd7, 0x33, 0xdb, 0x71, 0xa9, 0xe1, 0x34, 0x98, 0x65, 0x84, 0x60, 0xb3, 0xdf, 0x81, 0xf9, 0x31, - 0x77, 0x07, 0xfa, 0x12, 0x21, 0xa1, 0xaa, 0x26, 0xc1, 0x72, 0x75, 0xdc, 0x85, 0xca, 0xc9, 0x84, - 0xf0, 0x04, 0x63, 0xc9, 0x23, 0x0d, 0x80, 0x04, 0xb5, 0x88, 0xbf, 0x8c, 0x27, 0xc1, 0x19, 0xa6, - 0x16, 0x30, 0xb5, 0x28, 0xbe, 0x45, 0xd2, 0x1d, 0x80, 0xc1, 0x24, 0x08, 0xe5, 0x8a, 0x99, 0xc3, - 0xc4, 0xb2, 0x80, 0xd0, 0x8a, 0xf9, 0x06, 0x2c, 0x8e, 0xec, 0x4b, 0x0b, 0x69, 0xc7, 0x72, 0x5c, - 0xeb, 0x64, 0x88, 0x7b, 0x4e, 0x11, 0xf1, 0x1a, 0x23, 0xfb, 0xf2, 0x53, 0x91, 0xd2, 0x71, 0xb7, - 0x11, 0x2e, 0xd8, 0x8a, 0x12, 0x77, 0x7c, 0x1e, 0x70, 0xff, 0x9c, 0x23, 0x27, 0xc8, 0x47, 0x32, - 0x8d, 0x49, 0x50, 0xd1, 0xa2, 0x91, 0xe8, 0x77, 0x38, 0xec, 0xd3, 0xb2, 0x37, 0x8b, 0x23, 0xc7, - 0xdd, 0x09, 0x87, 0x7d, 0xb1, 0xaf, 0x08, 0x3e, 0x32, 0xe6, 0xbe, 0xf5, 0xe2, 0x02, 0xd7, 0x70, - 0x1e, 0xf9, 0xc6, 0x21, 0xf7, 0x9f, 0x5d, 0x88, 0xad, 0xbf, 0x1f, 0x20, 0x23, 0xb2, 0xaf, 0x9a, - 0x15, 0x5c, 0xe0, 0xa5, 0x7e, 0x20, 0x58, 0x90, 0x7d, 0x25, 0x16, 0xa1, 0x68, 0xad, 0x8d, 0xb3, - 0xc0, 0x07, 0x58, 0x7c, 0x80, 0x1c, 0xb5, 0x86, 0x8d, 0x6d, 0xc9, 0x04, 0x51, 0x4f, 0x20, 0xa8, - 0x5e, 0x35, 0xf6, 0x64, 0x68, 0x9f, 0x06, 0xc8, 0x52, 0x6a, 0x66, 0x55, 0x02, 0xb7, 0x05, 0xcc, - 0xf8, 0x8c, 0x84, 0x2c, 0x6d, 0x6e, 0xe5, 0x9a, 0x11, 0x5b, 0x3d, 0x42, 0x70, 0x5e, 0x4b, 0xa6, - 0xfc, 0x4a, 0x9b, 0xb4, 0x6c, 0xca, 0xa4, 0x19, 0xbf, 0x97, 0x81, 0xaa, 0x2c, 0x19, 0x85, 0x12, - 0xb6, 0x0e, 0x4c, 0xcd, 0x62, 0x78, 0xe9, 0x0c, 0xac, 0xe3, 0xab, 0x90, 0x07, 0x44, 0x34, 0x3b, - 0x37, 0xcc, 0x86, 0x4c, 0xeb, 0x5d, 0x3a, 0x83, 0x0d, 0x91, 0xc2, 0x1e, 0x40, 0x23, 0x81, 0x1f, - 0x84, 0x3e, 0x51, 0xf4, 0xce, 0x0d, 0xb3, 0xae, 0x61, 0x77, 0x43, 0x5f, 0xac, 0x11, 0x21, 0xf2, - 0x4c, 0x42, 0xcb, 0x71, 0x07, 0xfc, 0x12, 0xc9, 0xa8, 0x66, 0x56, 0x08, 0xd6, 0x11, 0xa0, 0x8d, - 0x3a, 0x54, 0xf5, 0xe2, 0x8c, 0x53, 0x28, 0x29, 0x79, 0x09, 0x05, 0x86, 0xa9, 0x26, 0x99, 0xe5, - 0x30, 0x6a, 0xc9, 0x4d, 0x28, 0x25, 0x5b, 0x60, 0x16, 0xc3, 0xd7, 0xae, 0xd8, 0xf8, 0x1e, 0x34, - 0x76, 0x05, 0xf1, 0xb8, 0x82, 0x58, 0xa5, 0xfc, 0xb7, 0x02, 0x73, 0xda, 0xa2, 0x29, 0x9b, 0xf2, - 0x4b, 0xec, 0xb9, 0x67, 0x5e, 0x10, 0xca, 0x5a, 0xf0, 0xb7, 0xf1, 0xc7, 0x19, 0x60, 0xed, 0x20, - 0x74, 0x46, 0x76, 0xc8, 0xb7, 0x79, 0xc4, 0x16, 0x0e, 0xa0, 0x2a, 0x4a, 0xeb, 0x79, 0x2d, 0x12, - 0xc8, 0x48, 0xa0, 0x78, 0x5f, 0x2e, 0xe3, 0xd9, 0x0c, 0xeb, 0x3a, 0x36, 0xb1, 0xf9, 0x44, 0x01, - 0x62, 0x95, 0x85, 0xb6, 0x7f, 0xca, 0x43, 0x14, 0xe3, 0xa4, 0xbc, 0x0f, 0x04, 0x12, 0x02, 0xdc, - 0xda, 0x2f, 0xc3, 0xc2, 0x4c, 0x19, 0x3a, 0x5f, 0x2e, 0xa7, 0xf0, 0xe5, 0x9c, 0xce, 0x97, 0x2d, - 0x58, 0x4c, 0xb4, 0x4b, 0x52, 0xda, 0x2a, 0x14, 0xc5, 0x82, 0x10, 0xc2, 0x41, 0x86, 0xa4, 0xca, - 0x13, 0xce, 0x85, 0x18, 0xfc, 0x10, 0x96, 0x4e, 0x38, 0xf7, 0xed, 0x10, 0x13, 0x71, 0xc5, 0x88, - 0x19, 0x92, 0x05, 0x2f, 0xc8, 0xb4, 0xae, 0x1d, 0x1e, 0x72, 0x5f, 0xcc, 0x94, 0xf1, 0xdf, 0x33, - 0x30, 0x2f, 0x38, 0xe8, 0x9e, 0xed, 0x5e, 0xa9, 0x71, 0xda, 0x4d, 0x1d, 0xa7, 0xfb, 0xda, 0x66, - 0xa8, 0x61, 0x7f, 0xd9, 0x41, 0xca, 0x4d, 0x0f, 0x12, 0xbb, 0x07, 0xd5, 0x44, 0x5b, 0x0b, 0xd8, - 0x56, 0x08, 0xa2, 0x46, 0xfe, 0xfc, 0xc3, 0xf8, 0x0e, 0x34, 0xe2, 0x66, 0xcb, 0x31, 0x64, 0x90, - 0x17, 0x24, 0x29, 0x0b, 0xc0, 0xdf, 0xc6, 0x3f, 0xc9, 0x10, 0xe2, 0xa6, 0xe7, 0x44, 0xd2, 0xa9, - 0x40, 0x14, 0x72, 0xaf, 0x42, 0x14, 0xbf, 0xaf, 0x95, 0xea, 0x7f, 0xfe, 0xce, 0x8a, 0xa5, 0x13, - 0x70, 0x77, 0x60, 0xd9, 0xc3, 0x21, 0x32, 0xdf, 0x92, 0x59, 0x14, 0xdf, 0xad, 0xe1, 0xd0, 0x78, - 0x17, 0x16, 0xb4, 0xd6, 0xbd, 0xa4, 0x1f, 0xfb, 0xc0, 0x76, 0x9d, 0x20, 0x3c, 0x72, 0x83, 0xb1, - 0x26, 0xb8, 0xdd, 0x82, 0xb2, 0xe0, 0xb0, 0xa2, 0x65, 0xb4, 0x64, 0x0b, 0xa6, 0x60, 0xb9, 0xa2, - 0x5d, 0x01, 0x26, 0xda, 0x97, 0x32, 0x31, 0x2b, 0x13, 0xed, 0x4b, 0x4c, 0x34, 0xbe, 0x03, 0x8b, - 0x89, 0xf2, 0x64, 0xd5, 0x6f, 0x42, 0x61, 0x12, 0x5e, 0x7a, 0x4a, 0x34, 0xaf, 0x48, 0x0a, 0x11, - 0x0a, 0xa0, 0x49, 0x29, 0xc6, 0xc7, 0xb0, 0xb0, 0xcf, 0x2f, 0xe4, 0x22, 0x56, 0x0d, 0x79, 0x07, - 0xf2, 0xaf, 0x50, 0x0a, 0x31, 0xdd, 0x58, 0x07, 0xa6, 0x67, 0x96, 0xb5, 0x6a, 0x3a, 0x62, 0x26, - 0xa1, 0x23, 0x1a, 0xef, 0x00, 0xeb, 0x3a, 0xa7, 0xee, 0x1e, 0x0f, 0x02, 0xfb, 0x34, 0x5a, 0xf6, - 0x0d, 0xc8, 0x8d, 0x82, 0x53, 0xc9, 0xa3, 0xc4, 0x4f, 0xe3, 0x9b, 0xb0, 0x98, 0xc0, 0x93, 0x05, - 0xdf, 0x86, 0x72, 0xe0, 0x9c, 0xba, 0x28, 0x58, 0xc9, 0xa2, 0x63, 0x80, 0xb1, 0x0d, 0x4b, 0x9f, - 0x72, 0xdf, 0x39, 0xb9, 0x7a, 0x55, 0xf1, 0xc9, 0x72, 0xb2, 0xd3, 0xe5, 0xb4, 0x61, 0x79, 0xaa, - 0x1c, 0x59, 0x3d, 0x91, 0xaf, 0x9c, 0xc9, 0x92, 0x49, 0x1f, 0x1a, 0xdf, 0xcb, 0xea, 0x7c, 0xcf, - 0x38, 0x02, 0xb6, 0xe9, 0xb9, 0x2e, 0xef, 0x87, 0x87, 0x9c, 0xfb, 0xf1, 0x29, 0x55, 0x4c, 0xab, - 0x95, 0xc7, 0xab, 0x72, 0x64, 0xa7, 0x99, 0xa9, 0x24, 0x62, 0x06, 0xf9, 0x31, 0xf7, 0x47, 0x58, - 0x70, 0xc9, 0xc4, 0xdf, 0xc6, 0x32, 0x2c, 0x26, 0x8a, 0x95, 0x7a, 0xfd, 0x23, 0x58, 0xde, 0x72, - 0x82, 0xfe, 0x6c, 0x85, 0xab, 0x50, 0x1c, 0x4f, 0x8e, 0xad, 0x24, 0x5f, 0x7e, 0xc6, 0xaf, 0x84, - 0xb6, 0x37, 0x9d, 0x43, 0x96, 0xf5, 0xd7, 0x33, 0x90, 0xdf, 0xe9, 0xed, 0x6e, 0xb2, 0x35, 0x28, - 0x39, 0x6e, 0xdf, 0x1b, 0x09, 0xc1, 0x8b, 0xfa, 0x1c, 0x7d, 0x5f, 0xbb, 0xc0, 0x6e, 0x41, 0x19, - 0xe5, 0x35, 0xa1, 0xda, 0x4a, 0xd1, 0xa7, 0x24, 0x00, 0xbb, 0x5e, 0xff, 0x85, 0xd0, 0xa9, 0xf9, - 0xe5, 0xd8, 0xf1, 0x51, 0x6b, 0x56, 0xca, 0x70, 0x9e, 0xf6, 0xfa, 0x38, 0x81, 0x34, 0x62, 0xe3, - 0xdf, 0x96, 0xa0, 0x28, 0x77, 0x5b, 0xda, 0xb9, 0x43, 0xe7, 0x9c, 0xc7, 0x3b, 0xb7, 0xf8, 0x12, - 0xf2, 0x80, 0xcf, 0x47, 0x5e, 0x18, 0x09, 0x6c, 0x34, 0x07, 0x55, 0x02, 0x4a, 0x91, 0x4d, 0x13, - 0x1a, 0xe8, 0x88, 0x21, 0x47, 0x48, 0x7d, 0x7d, 0x2b, 0xbf, 0x05, 0x45, 0xb5, 0xf7, 0xe7, 0x23, - 0x9d, 0x66, 0xae, 0x4f, 0xd2, 0xda, 0x1a, 0x94, 0xfa, 0xf6, 0xd8, 0xee, 0x3b, 0xe1, 0x95, 0x64, - 0x08, 0xd1, 0xb7, 0x28, 0x7d, 0xe8, 0xf5, 0xed, 0xa1, 0x75, 0x6c, 0x0f, 0x6d, 0xb7, 0xcf, 0xa5, - 0xee, 0x5e, 0x45, 0xe0, 0x06, 0xc1, 0x84, 0x7e, 0x2e, 0xdb, 0xa9, 0xb0, 0x48, 0x85, 0x97, 0xad, - 0x57, 0x68, 0x42, 0xb8, 0xf4, 0x46, 0x23, 0x47, 0x68, 0x19, 0x24, 0x86, 0xe5, 0xcc, 0x32, 0x41, - 0xb6, 0x39, 0xf6, 0x56, 0x26, 0x5f, 0xd0, 0xd0, 0x95, 0xa9, 0x2a, 0x02, 0x7e, 0x46, 0x07, 0x09, - 0xb3, 0xb2, 0x58, 0x4e, 0x93, 0xc5, 0xde, 0x87, 0x85, 0x89, 0x1b, 0xf0, 0x30, 0x1c, 0xf2, 0x41, - 0xd4, 0x96, 0x0a, 0x22, 0x35, 0xa2, 0x04, 0xd5, 0x9c, 0x75, 0x58, 0xa4, 0x43, 0x87, 0xc0, 0x0e, - 0xbd, 0xe0, 0xcc, 0x09, 0xac, 0x40, 0x68, 0x48, 0xa4, 0xee, 0x2e, 0x60, 0x52, 0x57, 0xa6, 0x74, - 0x49, 0x45, 0x5a, 0x9d, 0xc2, 0xf7, 0x79, 0x9f, 0x3b, 0xe7, 0x7c, 0x80, 0x72, 0x5a, 0xce, 0x5c, - 0x4e, 0xe4, 0x31, 0x65, 0x22, 0x0a, 0xdd, 0x93, 0x91, 0x35, 0x19, 0x0f, 0x6c, 0x21, 0xac, 0xd4, - 0x49, 0x18, 0x76, 0x27, 0xa3, 0x23, 0x82, 0xb0, 0x47, 0xa0, 0x24, 0x31, 0x29, 0x1f, 0xce, 0x27, - 0xf8, 0x99, 0x20, 0x56, 0xb3, 0x2a, 0x31, 0x48, 0x50, 0x4c, 0xc8, 0x9c, 0x8d, 0x29, 0x99, 0xb3, - 0x09, 0xc5, 0xb1, 0xef, 0x9c, 0xdb, 0x21, 0x6f, 0x2e, 0x10, 0x03, 0x97, 0x9f, 0x82, 0x33, 0x38, - 0xae, 0x13, 0x3a, 0x76, 0xe8, 0xf9, 0x4d, 0x86, 0x69, 0x31, 0x80, 0x3d, 0x80, 0x05, 0xa4, 0x91, - 0x20, 0xb4, 0xc3, 0x49, 0x20, 0x25, 0xd0, 0x45, 0x24, 0x26, 0x94, 0xa1, 0xbb, 0x08, 0x47, 0x21, - 0x94, 0x7d, 0x13, 0x56, 0x88, 0x2c, 0x30, 0x87, 0x94, 0xac, 0x51, 0x20, 0x58, 0xc2, 0xa1, 0x58, - 0xc4, 0x54, 0x41, 0xdf, 0x52, 0xbe, 0x16, 0xd2, 0xc1, 0x13, 0x58, 0x95, 0x64, 0x32, 0x93, 0x6b, - 0x19, 0x73, 0x2d, 0x51, 0xf2, 0x54, 0xb6, 0x75, 0x58, 0x10, 0x4d, 0x72, 0xfa, 0x96, 0xcc, 0x2d, - 0x56, 0xc2, 0x8a, 0x68, 0x3d, 0x6a, 0x4a, 0xf3, 0x94, 0x68, 0x62, 0xda, 0x33, 0x7e, 0xc5, 0xbe, - 0x07, 0xf3, 0x44, 0x32, 0xa8, 0x5e, 0x21, 0xa7, 0x5f, 0x43, 0x4e, 0xbf, 0xac, 0x4e, 0x38, 0xa3, - 0x54, 0x64, 0xf6, 0xf5, 0x7e, 0xe2, 0x5b, 0x2c, 0x87, 0xa1, 0x73, 0xc2, 0x43, 0x67, 0xc4, 0x9b, - 0xab, 0x44, 0x60, 0xea, 0x5b, 0xac, 0xd4, 0xc9, 0x18, 0x53, 0x9a, 0xc4, 0x17, 0xe8, 0x0b, 0x69, - 0x77, 0xe8, 0x05, 0x5c, 0x1d, 0x51, 0x35, 0x6f, 0xca, 0x45, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, - 0x38, 0x29, 0x3d, 0xd1, 0x41, 0xe2, 0x2d, 0x24, 0x86, 0x1a, 0xe9, 0x3e, 0xea, 0x30, 0x51, 0xec, - 0xe2, 0x67, 0xf6, 0x85, 0xe2, 0x20, 0xb7, 0x71, 0x7e, 0x41, 0x80, 0x24, 0xef, 0xf8, 0x69, 0x86, - 0x36, 0x44, 0xc9, 0x3f, 0x02, 0x4d, 0xbd, 0x23, 0xce, 0x61, 0x79, 0xee, 0xf0, 0x4a, 0x32, 0x13, - 0x20, 0xd0, 0x81, 0x3b, 0xc4, 0xd5, 0xec, 0xb8, 0x3a, 0x0a, 0xf1, 0xde, 0xaa, 0x02, 0x22, 0xd2, - 0x5d, 0xa8, 0x8c, 0x27, 0xc7, 0x43, 0xa7, 0x4f, 0x28, 0x39, 0x2a, 0x85, 0x40, 0x88, 0x20, 0xf4, - 0x5b, 0xa2, 0x28, 0xc2, 0xc8, 0x23, 0x46, 0x45, 0xc2, 0x10, 0x05, 0x79, 0x3b, 0xf7, 0x91, 0x9d, - 0x54, 0x4d, 0xfc, 0x6d, 0x6c, 0xc0, 0x52, 0xb2, 0xd1, 0x72, 0xe3, 0x79, 0x00, 0x25, 0xc9, 0xab, - 0xd4, 0xc1, 0x47, 0x5d, 0x3b, 0x8a, 0x16, 0x2a, 0x5a, 0x94, 0x6e, 0xfc, 0xd6, 0x1c, 0x2c, 0x4a, - 0xe8, 0xa6, 0x18, 0xda, 0xee, 0x64, 0x34, 0xb2, 0xfd, 0x14, 0x26, 0x98, 0x79, 0x39, 0x13, 0xcc, - 0xce, 0x30, 0xc1, 0xa4, 0xe6, 0x4b, 0x3c, 0x34, 0xa9, 0xf9, 0x8a, 0xb9, 0x24, 0x65, 0x44, 0x3f, - 0x07, 0xad, 0x49, 0x70, 0x8f, 0xce, 0x5b, 0x67, 0x58, 0x76, 0x21, 0x85, 0x65, 0xeb, 0x0c, 0x77, - 0x6e, 0x8a, 0xe1, 0xbe, 0x09, 0x44, 0x34, 0x6a, 0xf6, 0x8b, 0xa4, 0x9f, 0x20, 0x4c, 0x1e, 0xa6, - 0xbe, 0x0b, 0xf3, 0xd3, 0x3c, 0x8e, 0x98, 0x69, 0x3d, 0x85, 0xc3, 0x39, 0x23, 0x8e, 0xbb, 0x95, - 0x86, 0x5c, 0x96, 0x1c, 0xce, 0x19, 0xf1, 0x5d, 0x4c, 0x51, 0xf8, 0x6d, 0x00, 0xaa, 0x1b, 0x17, - 0x0d, 0xe0, 0xa2, 0x79, 0x27, 0x39, 0x17, 0xfa, 0xa8, 0xaf, 0x8b, 0x8f, 0x89, 0xcf, 0x71, 0x15, - 0x95, 0x31, 0x27, 0x2e, 0xa0, 0x67, 0x50, 0xf7, 0xc6, 0xdc, 0xb5, 0x62, 0x5e, 0x53, 0xc1, 0xa2, - 0xde, 0x7e, 0x49, 0x51, 0x1d, 0x85, 0x6b, 0xd6, 0x44, 0xde, 0xe8, 0x93, 0xed, 0xd1, 0xc0, 0x73, - 0xad, 0xb4, 0xea, 0x97, 0x28, 0xad, 0x8e, 0x99, 0xa3, 0x6f, 0xe3, 0x6f, 0x65, 0xa0, 0xa2, 0x35, - 0x9b, 0x2d, 0xc3, 0xc2, 0xe6, 0xc1, 0xc1, 0x61, 0xdb, 0x6c, 0xf5, 0x3a, 0x9f, 0xb6, 0xad, 0xcd, - 0xdd, 0x83, 0x6e, 0xbb, 0x71, 0x43, 0x80, 0x77, 0x0f, 0x36, 0x5b, 0xbb, 0xd6, 0xf6, 0x81, 0xb9, - 0xa9, 0xc0, 0x19, 0xb6, 0x02, 0xcc, 0x6c, 0xef, 0x1d, 0xf4, 0xda, 0x09, 0x78, 0x96, 0x35, 0xa0, - 0xba, 0x61, 0xb6, 0x5b, 0x9b, 0x3b, 0x12, 0x92, 0x63, 0x4b, 0xd0, 0xd8, 0x3e, 0xda, 0xdf, 0xea, - 0xec, 0x3f, 0xb5, 0x36, 0x5b, 0xfb, 0x9b, 0xed, 0xdd, 0xf6, 0x56, 0x23, 0xcf, 0x6a, 0x50, 0x6e, - 0x6d, 0xb4, 0xf6, 0xb7, 0x0e, 0xf6, 0xdb, 0x5b, 0x8d, 0x82, 0xf1, 0x5d, 0x28, 0xc7, 0x1d, 0xad, - 0x40, 0xf1, 0x68, 0xff, 0xd9, 0xfe, 0xc1, 0x67, 0xfb, 0x8d, 0x1b, 0xac, 0x0c, 0x05, 0xac, 0xbf, - 0x91, 0x61, 0x00, 0x73, 0x54, 0x67, 0x23, 0xcb, 0x4a, 0x90, 0xdf, 0x38, 0xe8, 0xed, 0x34, 0x72, - 0xc6, 0x9f, 0x67, 0x60, 0x19, 0xbb, 0x3c, 0x98, 0x66, 0x02, 0xf7, 0xa0, 0xd2, 0xf7, 0xbc, 0xb1, - 0xd0, 0xb4, 0x62, 0x89, 0x42, 0x07, 0x89, 0x05, 0x4e, 0xcc, 0xfb, 0xc4, 0xf3, 0xfb, 0x5c, 0xf2, - 0x00, 0x40, 0xd0, 0xb6, 0x80, 0x08, 0x1a, 0x94, 0x44, 0x4c, 0x18, 0xc4, 0x02, 0x2a, 0x04, 0x23, - 0x94, 0x15, 0x98, 0x3b, 0xf6, 0xb9, 0xdd, 0x3f, 0x93, 0xab, 0x5f, 0x7e, 0xb1, 0xf7, 0xe2, 0x33, - 0x80, 0xbe, 0xa0, 0xa9, 0x21, 0x1f, 0xe0, 0x12, 0x28, 0x99, 0xf3, 0x12, 0xbe, 0x29, 0xc1, 0x62, - 0x37, 0xb2, 0x8f, 0x6d, 0x77, 0xe0, 0xb9, 0x7c, 0x20, 0x55, 0x8d, 0x18, 0x60, 0x1c, 0xc2, 0xca, - 0x74, 0xff, 0x24, 0xbf, 0xf8, 0x50, 0xe3, 0x17, 0x24, 0xf9, 0xaf, 0x5d, 0x4f, 0x0a, 0x1a, 0xef, - 0xf8, 0x3b, 0x79, 0xc8, 0x0b, 0x49, 0xf0, 0x5a, 0xa1, 0x51, 0x17, 0xed, 0x73, 0x33, 0xe6, 0x1f, - 0x3c, 0x6a, 0x20, 0x11, 0x81, 0xce, 0xb3, 0xca, 0x08, 0x41, 0xd1, 0x20, 0x4a, 0xf6, 0x79, 0xff, - 0x5c, 0x1e, 0x68, 0x51, 0xb2, 0xc9, 0xfb, 0xe7, 0xa8, 0x53, 0xd9, 0x21, 0xe5, 0xa5, 0xf5, 0x5e, - 0x0c, 0xec, 0x10, 0x73, 0xca, 0x24, 0xcc, 0x57, 0x8c, 0x92, 0x30, 0x57, 0x13, 0x8a, 0x8e, 0x7b, - 0xec, 0x4d, 0xdc, 0x01, 0x2e, 0xef, 0x92, 0xa9, 0x3e, 0xd1, 0xda, 0x84, 0x9c, 0x48, 0x6c, 0x44, - 0xb4, 0x9a, 0x4b, 0x02, 0xd0, 0x13, 0x5b, 0xd1, 0x07, 0x50, 0x0e, 0xae, 0xdc, 0xbe, 0xbe, 0x86, - 0x97, 0xe4, 0xf8, 0x88, 0xde, 0xaf, 0x77, 0xaf, 0xdc, 0x3e, 0xae, 0xd8, 0x52, 0x20, 0x7f, 0xb1, - 0x27, 0x50, 0x8a, 0xce, 0x7d, 0x89, 0x03, 0xdf, 0xd4, 0x73, 0xa8, 0xc3, 0x5e, 0x52, 0xaf, 0x23, - 0x54, 0xf6, 0x10, 0xe6, 0xf0, 0x70, 0x36, 0x68, 0x56, 0x31, 0x93, 0x92, 0xf7, 0x45, 0x33, 0xd0, - 0xd0, 0xc3, 0x07, 0x78, 0x50, 0x6b, 0x4a, 0xb4, 0xb5, 0x67, 0x50, 0x4b, 0x94, 0xa5, 0x2b, 0xd1, - 0x35, 0x52, 0xa2, 0xdf, 0xd6, 0x95, 0xe8, 0x78, 0x27, 0x90, 0xd9, 0x74, 0xa5, 0xfa, 0x97, 0xa1, - 0xa4, 0xba, 0x22, 0xd6, 0x9f, 0x5c, 0x3b, 0x56, 0xf7, 0xf9, 0xfe, 0x66, 0xe3, 0x06, 0x9b, 0x87, - 0x4a, 0x6b, 0x13, 0x97, 0x34, 0x02, 0x32, 0x02, 0xe5, 0xb0, 0xd5, 0xed, 0x46, 0x90, 0xac, 0xb1, - 0x0d, 0x8d, 0xe9, 0x96, 0x0a, 0x9a, 0x0c, 0x15, 0x4c, 0x1e, 0x5d, 0xc7, 0x00, 0xa1, 0x22, 0xd1, - 0x69, 0x34, 0xc9, 0xe1, 0xf4, 0x61, 0x3c, 0x81, 0x86, 0xd8, 0xd7, 0xc4, 0x50, 0x05, 0xda, 0x11, - 0xf0, 0x50, 0xc8, 0x76, 0xfa, 0xf1, 0x75, 0xc9, 0xac, 0x10, 0x0c, 0xab, 0x32, 0x3e, 0x84, 0x05, - 0x2d, 0x5b, 0xac, 0xd2, 0x8a, 0xbd, 0x72, 0x5a, 0xa5, 0x45, 0x05, 0x86, 0x52, 0x8c, 0x55, 0x58, - 0x16, 0x9f, 0xed, 0x73, 0xee, 0x86, 0xdd, 0xc9, 0x31, 0xd9, 0x1c, 0x1d, 0xcf, 0x15, 0x8a, 0x4d, - 0x39, 0x4a, 0xb9, 0x9e, 0xc8, 0xd7, 0xa5, 0xf6, 0x9b, 0x45, 0xd2, 0x58, 0xd3, 0x6a, 0xc0, 0x8c, - 0xeb, 0xf8, 0x37, 0xa1, 0x05, 0x97, 0x23, 0x90, 0x18, 0xd6, 0xc3, 0x76, 0xdb, 0xb4, 0x0e, 0xf6, - 0x77, 0x3b, 0xfb, 0x82, 0x51, 0x8a, 0x61, 0x45, 0xc0, 0xf6, 0x36, 0x42, 0x32, 0x46, 0x03, 0xea, - 0x4f, 0x79, 0xd8, 0x71, 0x4f, 0x3c, 0x65, 0x5f, 0xfb, 0x8b, 0x02, 0xcc, 0x47, 0xa0, 0x58, 0x8b, - 0x3e, 0xe7, 0x7e, 0xe0, 0x78, 0x2e, 0x0a, 0xc4, 0x65, 0x53, 0x7d, 0x8a, 0xdd, 0xcd, 0x19, 0x70, - 0x37, 0x74, 0xc2, 0x2b, 0x2b, 0x71, 0xe4, 0x56, 0x57, 0x60, 0xb9, 0x8b, 0x2e, 0x41, 0xc1, 0x1e, - 0x3a, 0xb6, 0x32, 0xd5, 0xd2, 0x87, 0x80, 0xf6, 0xbd, 0xa1, 0xe7, 0xa3, 0xec, 0x5b, 0x36, 0xe9, - 0x83, 0x3d, 0x82, 0x25, 0x21, 0x83, 0xeb, 0xe7, 0xa0, 0xc8, 0x3f, 0xe8, 0xf4, 0x8f, 0xb9, 0x93, - 0xd1, 0x61, 0x7c, 0x16, 0x2a, 0x52, 0xc4, 0xde, 0x29, 0x72, 0x48, 0x61, 0x29, 0xca, 0x40, 0xea, - 0xdc, 0x82, 0x3b, 0x19, 0xb5, 0x30, 0x25, 0xc2, 0x7f, 0x0c, 0xcb, 0x02, 0x3f, 0x12, 0xaf, 0xa2, - 0x1c, 0xf3, 0x98, 0x43, 0x14, 0xd6, 0x91, 0x69, 0x51, 0x9e, 0x5b, 0x50, 0xa6, 0x56, 0x89, 0x19, - 0x2f, 0x90, 0x18, 0x8f, 0x4d, 0xe1, 0x7e, 0x30, 0x63, 0x55, 0x9d, 0x23, 0x41, 0x60, 0xca, 0xaa, - 0xaa, 0xd9, 0x65, 0x4b, 0xd3, 0x76, 0xd9, 0xc7, 0xb0, 0x7c, 0x2c, 0x48, 0xf0, 0x8c, 0xdb, 0x03, - 0xee, 0x5b, 0x31, 0x61, 0x93, 0xba, 0xb2, 0x28, 0x12, 0x77, 0x30, 0x2d, 0x5a, 0x07, 0x42, 0xce, - 0x11, 0x6c, 0x81, 0x0f, 0xac, 0xd0, 0xb3, 0x50, 0xfc, 0x41, 0x06, 0x53, 0x32, 0x6b, 0x04, 0xee, - 0x79, 0x9b, 0x02, 0x98, 0xc4, 0x3b, 0xf5, 0xed, 0xf1, 0x99, 0x54, 0x28, 0x22, 0xbc, 0xa7, 0x02, - 0xc8, 0x6e, 0x43, 0x51, 0x90, 0xbc, 0xcb, 0xc9, 0xf8, 0x45, 0x22, 0xbb, 0x02, 0xb1, 0xb7, 0x61, - 0x0e, 0xeb, 0x08, 0x9a, 0x0d, 0xa4, 0xf7, 0x6a, 0xcc, 0xc8, 0x1d, 0xd7, 0x94, 0x69, 0x42, 0x98, - 0x9c, 0xf8, 0x0e, 0x71, 0x99, 0xb2, 0x89, 0xbf, 0xd9, 0xf7, 0x35, 0x96, 0xb5, 0x88, 0x79, 0x95, - 0x3c, 0x30, 0x45, 0x69, 0xd7, 0x71, 0xaf, 0xaf, 0x94, 0x19, 0xfd, 0x20, 0x5f, 0xaa, 0x34, 0xaa, - 0xc6, 0xb7, 0xa1, 0x40, 0xa3, 0x23, 0x88, 0x10, 0xc7, 0x2e, 0x23, 0x89, 0x10, 0xa1, 0x4d, 0x28, - 0xba, 0x3c, 0xbc, 0xf0, 0xfc, 0x17, 0xea, 0x50, 0x5a, 0x7e, 0x1a, 0x3f, 0xc6, 0xd3, 0x94, 0xc8, - 0xe2, 0x4e, 0x8a, 0xa1, 0x20, 0x0f, 0x9a, 0xde, 0xe0, 0xcc, 0x96, 0x07, 0x3c, 0x25, 0x04, 0x74, - 0xcf, 0xec, 0x19, 0xf2, 0xc8, 0xce, 0x1a, 0xdd, 0xdf, 0x86, 0xba, 0xb2, 0xf1, 0x07, 0xd6, 0x90, - 0x9f, 0x84, 0x92, 0xdc, 0xab, 0xd2, 0xc0, 0x1f, 0xec, 0xf2, 0x93, 0xd0, 0xd8, 0x83, 0x05, 0x49, - 0x90, 0x07, 0x63, 0xae, 0xaa, 0xfe, 0x4e, 0x9a, 0x3c, 0x5d, 0x79, 0xbc, 0x98, 0xdc, 0x68, 0xc9, - 0x77, 0x21, 0x21, 0x64, 0x1b, 0x9f, 0x00, 0xd3, 0xb7, 0x61, 0x59, 0x9e, 0x94, 0x6a, 0xd5, 0x59, - 0xbe, 0x32, 0x89, 0x45, 0xb2, 0xb3, 0x33, 0x10, 0xa3, 0x13, 0x4c, 0xfa, 0x7d, 0xe5, 0x7b, 0x51, - 0x32, 0xd5, 0xa7, 0xf1, 0x27, 0x19, 0x58, 0xc4, 0xc2, 0x94, 0x3e, 0x20, 0x99, 0xec, 0xcf, 0xdc, - 0x48, 0x31, 0x3f, 0xba, 0xec, 0x43, 0x1f, 0x5f, 0xfe, 0xf4, 0x34, 0x3f, 0x73, 0x7a, 0xfa, 0x1e, - 0x34, 0x06, 0x7c, 0xe8, 0xa0, 0x1b, 0x8e, 0x12, 0x25, 0x48, 0x03, 0x98, 0x57, 0x70, 0xa9, 0x0d, - 0x1a, 0xff, 0x30, 0x03, 0x0b, 0x24, 0xa9, 0xa0, 0x5e, 0x2d, 0x07, 0xea, 0x63, 0xa5, 0x48, 0x4a, - 0x56, 0x25, 0xfb, 0x14, 0xef, 0xe0, 0x08, 0x25, 0xe4, 0x9d, 0x1b, 0x52, 0xc1, 0x94, 0x50, 0xf6, - 0x11, 0xea, 0x30, 0xae, 0x85, 0xc0, 0x14, 0xb7, 0x9e, 0xe4, 0xa4, 0xec, 0xdc, 0x40, 0x05, 0xc7, - 0x45, 0xd0, 0x46, 0x49, 0x68, 0xb6, 0x02, 0x6c, 0x6c, 0x43, 0x2d, 0x51, 0x4d, 0xe2, 0x88, 0xb7, - 0x4a, 0x47, 0xbc, 0x33, 0x66, 0x94, 0xec, 0xac, 0x19, 0xe5, 0x0a, 0x16, 0x4d, 0x6e, 0x0f, 0xae, - 0xb6, 0x3d, 0xff, 0x30, 0x38, 0x0e, 0xb7, 0x49, 0xfc, 0x13, 0xfc, 0x3d, 0xb2, 0x0d, 0x26, 0xce, - 0x51, 0x95, 0x89, 0x48, 0xa9, 0xcb, 0x5f, 0x83, 0x7a, 0x6c, 0x44, 0xd4, 0xce, 0xe2, 0x6a, 0x91, - 0x1d, 0x11, 0x8f, 0xe4, 0x84, 0xaa, 0x19, 0x1c, 0x87, 0xf2, 0x34, 0x0e, 0x7f, 0x1b, 0x7f, 0x23, - 0x0f, 0x4c, 0x50, 0xf3, 0x14, 0xc1, 0x4c, 0x99, 0x3f, 0xb3, 0x33, 0xe6, 0xcf, 0x47, 0xc0, 0x34, - 0x04, 0x65, 0x95, 0xcd, 0x45, 0x56, 0xd9, 0x46, 0x8c, 0x2b, 0x8d, 0xb2, 0x8f, 0x60, 0x49, 0xca, - 0xd2, 0xc9, 0xa6, 0x12, 0x69, 0x30, 0x12, 0xaa, 0x13, 0xed, 0x55, 0xa6, 0x4f, 0xa1, 0xfe, 0xd3, - 0x69, 0x1b, 0x9a, 0x3e, 0x95, 0xe2, 0xaf, 0x11, 0xe0, 0xdc, 0x2b, 0x09, 0xb0, 0x38, 0x43, 0x80, - 0xda, 0xe1, 0x4f, 0x29, 0x79, 0xf8, 0x63, 0x40, 0x4d, 0x19, 0x38, 0xc9, 0xaf, 0x83, 0x04, 0xc7, - 0x8a, 0xb4, 0x72, 0xa2, 0x6f, 0xc7, 0x7d, 0x68, 0xa8, 0x13, 0x9a, 0xe8, 0x78, 0x89, 0x7c, 0x16, - 0xe4, 0x01, 0xdf, 0xa6, 0x3a, 0x64, 0x4a, 0x1c, 0xe6, 0x57, 0xa6, 0x0e, 0xf3, 0xdf, 0x87, 0x85, - 0x40, 0xd0, 0xaf, 0x35, 0x71, 0xa5, 0x83, 0x11, 0x1f, 0xa0, 0xd6, 0x56, 0x32, 0x1b, 0x98, 0x70, - 0x14, 0xc3, 0x67, 0x8f, 0x4e, 0x6a, 0x29, 0x47, 0x27, 0x4f, 0x62, 0x5b, 0x60, 0x70, 0xe6, 0x8c, - 0x50, 0x66, 0x88, 0x9d, 0x71, 0xe4, 0x00, 0x77, 0xcf, 0x9c, 0x91, 0xa9, 0x0c, 0xcf, 0xe2, 0xc3, - 0xf8, 0xbf, 0x19, 0x68, 0x08, 0x3a, 0x48, 0x2c, 0xb1, 0xef, 0x02, 0x32, 0x83, 0xd7, 0x5c, 0x61, - 0x15, 0x81, 0xab, 0x16, 0xd8, 0xb7, 0x01, 0x57, 0x8c, 0x25, 0x54, 0x54, 0xb9, 0xbe, 0x9a, 0xc9, - 0xf5, 0x15, 0xf3, 0xd0, 0x9d, 0x1b, 0xa4, 0x7b, 0x08, 0x08, 0xfb, 0x2e, 0x94, 0x05, 0x61, 0x22, - 0x95, 0x48, 0x1f, 0x30, 0x25, 0x79, 0xa5, 0xac, 0x11, 0x91, 0x75, 0x2c, 0x3f, 0xd3, 0xcc, 0xb7, - 0xf9, 0x14, 0xf3, 0xad, 0xb6, 0x80, 0x77, 0x00, 0x9e, 0xf1, 0xab, 0x5d, 0xaf, 0x8f, 0x7a, 0xe5, - 0x1d, 0x00, 0x41, 0xcb, 0x27, 0xf6, 0xc8, 0x91, 0x67, 0x42, 0x05, 0xb3, 0xfc, 0x82, 0x5f, 0x6d, - 0x23, 0x40, 0x4c, 0xa4, 0x48, 0x8e, 0x57, 0x71, 0xc1, 0x2c, 0xbd, 0xe0, 0x57, 0xb4, 0x84, 0x2d, - 0xa8, 0x3d, 0xe3, 0x57, 0x5b, 0x9c, 0x84, 0x4c, 0xcf, 0x17, 0x44, 0xe4, 0xdb, 0x17, 0x42, 0xaa, - 0x4c, 0x98, 0x5e, 0x2b, 0xbe, 0x7d, 0xf1, 0x8c, 0x5f, 0x29, 0x33, 0x70, 0x51, 0xa4, 0x0f, 0xbd, - 0xbe, 0xdc, 0x37, 0x95, 0x13, 0x49, 0xdc, 0x28, 0x73, 0xee, 0x05, 0xfe, 0x36, 0xfe, 0x32, 0x03, - 0x35, 0xd1, 0x7e, 0x64, 0xcb, 0x62, 0xca, 0x94, 0x2f, 0x52, 0x26, 0xf6, 0x45, 0x7a, 0x2c, 0xb9, - 0x1a, 0xf1, 0xf8, 0xec, 0xf5, 0x3c, 0x1e, 0xe7, 0x86, 0x18, 0xfc, 0x07, 0x50, 0xa6, 0x65, 0x29, - 0xd6, 0x79, 0x2e, 0x31, 0xc1, 0x89, 0x0e, 0x99, 0x25, 0x44, 0x7b, 0x46, 0xae, 0x0f, 0xda, 0xf9, - 0x22, 0x0d, 0x71, 0xd9, 0x8f, 0x4e, 0x15, 0x53, 0xa6, 0xa1, 0x70, 0x8d, 0xeb, 0x83, 0x7e, 0x78, - 0x37, 0x37, 0x73, 0x78, 0x77, 0x00, 0x25, 0x31, 0xd5, 0xd8, 0xd9, 0x94, 0x42, 0x33, 0x69, 0x85, - 0x0a, 0x49, 0xc0, 0x16, 0x9b, 0x82, 0x60, 0x74, 0x59, 0x29, 0x09, 0xd8, 0x01, 0x3f, 0x44, 0x66, - 0x97, 0x81, 0x8a, 0xb6, 0x02, 0xf0, 0xfc, 0x33, 0x1a, 0x2f, 0x5a, 0x2e, 0x49, 0x12, 0x4f, 0x0c, - 0xf8, 0xce, 0x0d, 0xb3, 0xd6, 0x4f, 0xcc, 0xc0, 0xba, 0xa4, 0x55, 0xcc, 0x99, 0x4d, 0xb8, 0x4d, - 0xa9, 0x86, 0x2b, 0x02, 0x15, 0xbf, 0x37, 0xe6, 0x20, 0x2f, 0x50, 0x8d, 0x8f, 0x61, 0x41, 0x6b, - 0x06, 0xa9, 0xf9, 0xaf, 0xdb, 0x43, 0xe3, 0xd7, 0xa2, 0xcc, 0xa2, 0x0e, 0xb2, 0x50, 0x29, 0x37, - 0x12, 0x3e, 0xa0, 0x8e, 0x4b, 0x77, 0x15, 0x02, 0x09, 0xb4, 0xd7, 0x76, 0x6d, 0xf8, 0x0d, 0x58, - 0xd4, 0x4a, 0xdf, 0x76, 0x5c, 0x7b, 0xe8, 0xfc, 0x18, 0x37, 0xfc, 0xc0, 0x39, 0x75, 0xa7, 0xca, - 0x27, 0xd0, 0x97, 0x2a, 0xff, 0x1f, 0x65, 0x61, 0x49, 0x56, 0x80, 0x8e, 0x81, 0x8e, 0x90, 0xe2, - 0xf6, 0x82, 0x53, 0xf6, 0x5d, 0xa8, 0x89, 0xb1, 0xb1, 0x7c, 0x7e, 0xea, 0x04, 0x21, 0x57, 0x96, - 0xb1, 0x14, 0xc6, 0x25, 0x36, 0x73, 0x81, 0x6a, 0x4a, 0x4c, 0xf6, 0x31, 0x54, 0x30, 0x2b, 0x1d, - 0xa3, 0xc8, 0x89, 0x68, 0xce, 0x66, 0xa4, 0x81, 0xde, 0xb9, 0x61, 0x42, 0x10, 0x0f, 0xfb, 0xc7, - 0x50, 0xc1, 0x39, 0x3c, 0xc7, 0x81, 0x9c, 0x62, 0x55, 0x33, 0x03, 0x2d, 0x32, 0x8f, 0xe3, 0x61, - 0x6f, 0x41, 0x8d, 0x98, 0x95, 0x1c, 0x27, 0xe9, 0x70, 0xb4, 0x36, 0x9b, 0x5d, 0x8d, 0xa4, 0x68, - 0xfc, 0x58, 0xfb, 0xde, 0x28, 0x43, 0x31, 0xf4, 0x9d, 0xd3, 0x53, 0xee, 0x1b, 0x2b, 0xd1, 0xd0, - 0x08, 0x2e, 0xcc, 0xbb, 0x21, 0x1f, 0x0b, 0xd9, 0xdc, 0xf8, 0x0f, 0x19, 0xa8, 0x48, 0xbe, 0xfa, - 0x33, 0x9b, 0xe3, 0xd6, 0x34, 0xcf, 0x5a, 0x3a, 0xb1, 0x89, 0x1d, 0x69, 0xdf, 0x85, 0xf9, 0x91, - 0x90, 0xd3, 0x85, 0x1e, 0x99, 0xb0, 0xc5, 0xd5, 0x15, 0x58, 0x8a, 0xc9, 0xeb, 0xb0, 0x88, 0x52, - 0x73, 0x60, 0x85, 0xce, 0xd0, 0x52, 0x89, 0xd2, 0x8b, 0x75, 0x81, 0x92, 0x7a, 0xce, 0x70, 0x4f, - 0x26, 0x08, 0xe1, 0x31, 0x08, 0xed, 0x53, 0x2e, 0xd7, 0x36, 0x7d, 0x18, 0x4d, 0x58, 0x99, 0x52, - 0x21, 0x95, 0xfa, 0xfb, 0xbf, 0x17, 0x60, 0x75, 0x26, 0x49, 0xaa, 0xc1, 0x91, 0x0d, 0x6a, 0xe8, - 0x8c, 0x8e, 0xbd, 0xe8, 0x84, 0x36, 0xa3, 0xd9, 0xa0, 0x76, 0x45, 0x8a, 0x3a, 0xa1, 0xe5, 0xb0, - 0xac, 0x08, 0x12, 0x8f, 0x58, 0x23, 0x2d, 0x33, 0x8b, 0x3a, 0xd0, 0x07, 0xc9, 0x4d, 0x6c, 0xba, - 0x3a, 0x05, 0xd7, 0x45, 0xa3, 0xc5, 0xf1, 0x0c, 0x2c, 0x60, 0xbf, 0x09, 0xcd, 0x88, 0xee, 0xa5, - 0xd8, 0xae, 0xa9, 0xcc, 0xa2, 0xa6, 0xaf, 0xbf, 0xa2, 0xa6, 0xc4, 0xd9, 0x1d, 0xca, 0x4e, 0x2b, - 0x6a, 0xc9, 0x50, 0x81, 0x51, 0x5d, 0xe7, 0xf0, 0x86, 0xaa, 0x0b, 0xc5, 0xf0, 0xd9, 0x1a, 0xf3, - 0xaf, 0xd5, 0x37, 0x3c, 0x97, 0x4c, 0x54, 0x6b, 0xde, 0x92, 0x05, 0x47, 0x49, 0x7a, 0xbd, 0x67, - 0xb0, 0x72, 0x61, 0x3b, 0xa1, 0xea, 0xa3, 0xa6, 0xb1, 0x17, 0xb0, 0xbe, 0xc7, 0xaf, 0xa8, 0xef, - 0x33, 0xca, 0x9c, 0x50, 0x4c, 0x96, 0x2e, 0x66, 0x81, 0xc1, 0xda, 0xdf, 0xcb, 0x41, 0x3d, 0x59, - 0x8a, 0x60, 0x2c, 0x72, 0xb3, 0x51, 0xf2, 0xa6, 0x14, 0x82, 0xa5, 0xf5, 0x60, 0x9f, 0xe4, 0xcc, - 0x59, 0xbb, 0x46, 0x36, 0xc5, 0xae, 0xa1, 0x9b, 0x13, 0x72, 0xaf, 0xb2, 0xdf, 0xe6, 0x5f, 0xcb, - 0x7e, 0x5b, 0x48, 0xb3, 0xdf, 0x5e, 0x6f, 0xf4, 0x9b, 0xfb, 0x99, 0x8c, 0x7e, 0xc5, 0x97, 0x18, - 0xfd, 0x12, 0xa6, 0xca, 0xd2, 0xb4, 0xa9, 0x32, 0xc5, 0xc4, 0x57, 0xfe, 0x12, 0x26, 0xbe, 0xb5, - 0xbf, 0xcc, 0x00, 0x9b, 0x5d, 0x0b, 0xec, 0x29, 0x19, 0x88, 0x5c, 0x3e, 0x94, 0x7c, 0xfa, 0x1b, - 0xaf, 0xb7, 0x9e, 0xd4, 0xf4, 0xab, 0xdc, 0xec, 0x21, 0x2c, 0xea, 0x9e, 0xf5, 0xba, 0x8e, 0x5e, - 0x33, 0x99, 0x9e, 0x14, 0x9f, 0xe4, 0x68, 0xa6, 0xf1, 0xfc, 0x2b, 0x4d, 0xe3, 0x85, 0x57, 0x9a, - 0xc6, 0xe7, 0x92, 0xa6, 0xf1, 0xb5, 0xff, 0x9c, 0x81, 0xc5, 0x14, 0x92, 0xfd, 0xea, 0xfa, 0x2c, - 0x28, 0x2d, 0xc1, 0xc4, 0xb2, 0x92, 0xd2, 0x74, 0xfe, 0xb5, 0x0b, 0x95, 0x78, 0x2a, 0x54, 0xe4, - 0xc9, 0x83, 0x57, 0xf1, 0x92, 0x38, 0x87, 0xa9, 0x67, 0x5f, 0xfb, 0xfd, 0x2c, 0x54, 0xb4, 0x44, - 0x31, 0x8a, 0x44, 0xa0, 0x9a, 0x47, 0x12, 0xc9, 0x81, 0x78, 0xc2, 0x70, 0x17, 0xa4, 0x09, 0x83, - 0xd2, 0x69, 0x29, 0x49, 0xa1, 0x0f, 0x11, 0xd6, 0x61, 0x51, 0x19, 0xef, 0x78, 0xec, 0x78, 0x28, - 0x77, 0x96, 0x05, 0x69, 0xc2, 0xe3, 0x91, 0x1f, 0x23, 0x7b, 0xa8, 0x94, 0xbf, 0x78, 0xee, 0x90, - 0xb0, 0xc9, 0x3e, 0xb0, 0x40, 0xcb, 0x41, 0x4d, 0xa2, 0xa0, 0xea, 0x0f, 0x60, 0x59, 0x2d, 0x86, - 0x64, 0x0e, 0x32, 0x19, 0x30, 0xb9, 0x14, 0xf4, 0x2c, 0xdf, 0x87, 0x3b, 0x53, 0x6d, 0x9a, 0xca, - 0x4a, 0x1e, 0xb2, 0x37, 0x13, 0xad, 0xd3, 0x4b, 0x58, 0xfb, 0x09, 0xd4, 0x12, 0x6c, 0xf1, 0xab, - 0x9b, 0xf2, 0xe9, 0x53, 0x1d, 0x1a, 0x51, 0xfd, 0x54, 0x67, 0xed, 0xff, 0xe4, 0x80, 0xcd, 0x72, - 0xe6, 0x5f, 0x64, 0x13, 0x66, 0x09, 0x33, 0x97, 0x42, 0x98, 0xff, 0xdf, 0xa4, 0x85, 0xf7, 0x61, - 0x41, 0x46, 0x60, 0x69, 0x16, 0x58, 0x5a, 0x9c, 0x8d, 0x28, 0x41, 0xb5, 0xe2, 0xdb, 0xd3, 0x9e, - 0x20, 0xa5, 0x44, 0xd0, 0x89, 0x26, 0x2e, 0x4d, 0x39, 0x84, 0x1c, 0xc1, 0x9c, 0xed, 0xf6, 0xcf, - 0x3c, 0x5f, 0xf2, 0xc1, 0x5f, 0xfa, 0xd2, 0x9b, 0xe5, 0x7a, 0x0b, 0xf3, 0xa3, 0x8c, 0x66, 0xca, - 0xc2, 0x8c, 0x0f, 0xa0, 0xa2, 0x81, 0xd1, 0x2a, 0xd9, 0xd9, 0xdb, 0x38, 0x68, 0xdc, 0x60, 0x35, - 0x28, 0x9b, 0xed, 0xcd, 0x83, 0x4f, 0xdb, 0x66, 0x7b, 0xab, 0x91, 0x61, 0x25, 0xc8, 0xef, 0x1e, - 0x74, 0x7b, 0x8d, 0xac, 0xb1, 0x06, 0x4d, 0x59, 0xe2, 0xac, 0x85, 0xe2, 0x77, 0xf2, 0xd1, 0xe1, - 0x20, 0x26, 0x4a, 0x85, 0xfc, 0x9b, 0x50, 0xd5, 0x85, 0x19, 0x49, 0x11, 0x53, 0x4e, 0x00, 0x42, - 0x15, 0xf7, 0x34, 0x5e, 0xbd, 0x09, 0x64, 0xda, 0x1d, 0x44, 0xd9, 0xb2, 0x09, 0x29, 0x35, 0xc5, - 0x16, 0x88, 0xaa, 0x4e, 0x82, 0x0c, 0xff, 0x0a, 0xd4, 0x93, 0xc7, 0xf5, 0x92, 0x23, 0xa5, 0xa9, - 0x97, 0x22, 0x77, 0xe2, 0xfc, 0x9e, 0x7d, 0x1f, 0x1a, 0xd3, 0xc7, 0xfd, 0x52, 0x54, 0xbe, 0x26, - 0xff, 0xbc, 0x93, 0xb4, 0x00, 0xb0, 0x1d, 0x58, 0x4a, 0x13, 0xe7, 0x90, 0x3e, 0xae, 0x3f, 0x92, - 0x60, 0xb3, 0x22, 0x1b, 0xfb, 0x8e, 0xb4, 0xea, 0x14, 0xd2, 0x6c, 0xe3, 0xda, 0x60, 0xaf, 0xd3, - 0x3f, 0xcd, 0xbe, 0x73, 0x0e, 0x10, 0xc3, 0x58, 0x03, 0xaa, 0x07, 0x87, 0xed, 0x7d, 0x6b, 0x73, - 0xa7, 0xb5, 0xbf, 0xdf, 0xde, 0x6d, 0xdc, 0x60, 0x0c, 0xea, 0x68, 0xd4, 0xde, 0x8a, 0x60, 0x19, - 0x01, 0x93, 0xd6, 0x35, 0x05, 0xcb, 0xb2, 0x25, 0x68, 0x74, 0xf6, 0xa7, 0xa0, 0x39, 0xd6, 0x84, - 0xa5, 0xc3, 0x36, 0xd9, 0xc1, 0x13, 0xe5, 0xe6, 0x85, 0x8a, 0x20, 0xbb, 0x2b, 0x54, 0x04, 0x8a, - 0x24, 0x94, 0xeb, 0x40, 0x49, 0xce, 0xbf, 0x9b, 0x81, 0xe5, 0xa9, 0x84, 0x38, 0x3e, 0x84, 0xe4, - 0xe6, 0xa4, 0xc4, 0x5c, 0x45, 0xa0, 0x5a, 0x4d, 0xef, 0xc3, 0x42, 0x74, 0xcc, 0x34, 0xb5, 0x2b, - 0x35, 0xa2, 0x04, 0x85, 0xfc, 0x10, 0x16, 0xb5, 0xd3, 0xaa, 0x29, 0x5e, 0xc1, 0xb4, 0x24, 0x99, - 0xc1, 0x58, 0x8d, 0xfc, 0xf0, 0xa7, 0x5a, 0x3d, 0xa0, 0xf0, 0x44, 0x3d, 0x21, 0x36, 0x7a, 0x25, - 0xdb, 0xab, 0x3e, 0xd9, 0xa3, 0x29, 0x42, 0x48, 0xb6, 0x56, 0x9f, 0x70, 0x55, 0xfd, 0x1f, 0xcc, - 0x01, 0xfb, 0x64, 0xc2, 0xfd, 0x2b, 0x8c, 0xff, 0x08, 0x5e, 0xe5, 0x10, 0xa9, 0xce, 0x55, 0xb2, - 0xaf, 0x15, 0xe3, 0x95, 0x16, 0x63, 0x95, 0x7f, 0x75, 0x8c, 0x55, 0xe1, 0x55, 0x31, 0x56, 0x6f, - 0x41, 0xcd, 0x39, 0x75, 0x3d, 0xc1, 0x0a, 0x85, 0xdc, 0x1b, 0x34, 0xe7, 0xee, 0xe5, 0xee, 0x57, - 0xcd, 0xaa, 0x04, 0x0a, 0xa9, 0x37, 0x60, 0x1f, 0xc7, 0x48, 0x7c, 0x70, 0x8a, 0xf1, 0x80, 0x3a, - 0x13, 0x6c, 0x0f, 0x4e, 0xb9, 0x3c, 0x46, 0x42, 0xbd, 0x42, 0x65, 0x16, 0xf0, 0x80, 0xbd, 0x0d, - 0xf5, 0xc0, 0x9b, 0x08, 0x35, 0x42, 0x0d, 0x03, 0x99, 0xc5, 0xaa, 0x04, 0x3d, 0x54, 0x36, 0xd0, - 0xc5, 0x49, 0xc0, 0xad, 0x91, 0x13, 0x04, 0x42, 0x3c, 0xeb, 0x7b, 0x6e, 0xe8, 0x7b, 0x43, 0x69, - 0xe9, 0x5a, 0x98, 0x04, 0x7c, 0x8f, 0x52, 0x36, 0x29, 0x81, 0x7d, 0x2b, 0x6e, 0xd2, 0xd8, 0x76, - 0xfc, 0xa0, 0x09, 0xd8, 0x24, 0xd5, 0x53, 0x94, 0xd6, 0x6d, 0xc7, 0x8f, 0xda, 0x22, 0x3e, 0x82, - 0xa9, 0xd8, 0xaf, 0xca, 0x74, 0xec, 0xd7, 0x8f, 0xd2, 0x63, 0xbf, 0x6a, 0x58, 0xf4, 0x23, 0x59, - 0xf4, 0xec, 0x14, 0x7f, 0xa9, 0x10, 0xb0, 0xd9, 0x90, 0xb6, 0xfa, 0x97, 0x09, 0x69, 0x9b, 0x4f, - 0x0b, 0x69, 0xfb, 0x00, 0x2a, 0x18, 0x6c, 0x64, 0x9d, 0x39, 0x42, 0x86, 0x23, 0xcb, 0x5d, 0x43, - 0x8f, 0x46, 0xda, 0x71, 0xdc, 0xd0, 0x04, 0x5f, 0xfd, 0x0c, 0x66, 0xa3, 0xcb, 0x16, 0x7e, 0x81, - 0xd1, 0x65, 0x32, 0x28, 0x6a, 0x1d, 0x4a, 0x6a, 0x9e, 0x18, 0x83, 0xfc, 0x89, 0xef, 0x8d, 0x94, - 0x45, 0x43, 0xfc, 0x66, 0x75, 0xc8, 0x86, 0x9e, 0xcc, 0x9c, 0x0d, 0x3d, 0xe3, 0xd7, 0xa1, 0xa2, - 0x91, 0x1a, 0x7b, 0x93, 0x4e, 0x21, 0x85, 0x26, 0x26, 0x65, 0x4b, 0x1a, 0xc5, 0xb2, 0x84, 0x76, - 0x06, 0x82, 0xdf, 0x0c, 0x1c, 0x9f, 0x63, 0x1c, 0xa8, 0xe5, 0xf3, 0x73, 0xee, 0x07, 0xca, 0xc2, - 0xd4, 0x88, 0x12, 0x4c, 0x82, 0x1b, 0xbf, 0x01, 0x8b, 0x89, 0xb9, 0x95, 0x2c, 0xe2, 0x6d, 0x98, - 0xc3, 0x71, 0x53, 0x1e, 0x00, 0xc9, 0x28, 0x2f, 0x99, 0x86, 0x01, 0xfe, 0x64, 0x1c, 0xb3, 0xc6, - 0xbe, 0x77, 0x8c, 0x95, 0x64, 0xcc, 0x8a, 0x84, 0x1d, 0xfa, 0xde, 0xb1, 0xf1, 0x67, 0x39, 0xc8, - 0xed, 0x78, 0x63, 0xdd, 0xe9, 0x2d, 0x33, 0xe3, 0xf4, 0x26, 0xd5, 0x4b, 0x2b, 0x52, 0x1f, 0xa5, - 0xcc, 0x8e, 0x66, 0x21, 0xa5, 0x42, 0xde, 0x87, 0xba, 0xe0, 0x13, 0xa1, 0x27, 0xf4, 0xf3, 0x0b, - 0xdb, 0x27, 0x81, 0x38, 0x47, 0x8b, 0xcf, 0x1e, 0x85, 0x3d, 0x6f, 0x9b, 0xe0, 0x6c, 0x09, 0x72, - 0x91, 0xfa, 0x82, 0xc9, 0xe2, 0x93, 0xad, 0xc0, 0x1c, 0x7a, 0x3f, 0x5f, 0x49, 0x13, 0xb7, 0xfc, - 0x62, 0xdf, 0x80, 0xc5, 0x64, 0xb9, 0xc4, 0x8a, 0xa4, 0x6c, 0xa4, 0x17, 0x8c, 0x3c, 0xe9, 0x26, - 0x08, 0x3e, 0x42, 0x38, 0xd2, 0x53, 0xe6, 0x84, 0x73, 0x4c, 0xd2, 0x98, 0x5e, 0x29, 0xc1, 0xf4, - 0xee, 0x42, 0x25, 0x1c, 0x9e, 0x5b, 0x63, 0xfb, 0x6a, 0xe8, 0xd9, 0x03, 0xb9, 0xbe, 0x21, 0x1c, - 0x9e, 0x1f, 0x12, 0x84, 0x3d, 0x04, 0x18, 0x8d, 0xc7, 0x72, 0xed, 0xa1, 0xa9, 0x23, 0x26, 0xe5, - 0xbd, 0xc3, 0x43, 0x22, 0x39, 0xb3, 0x3c, 0x1a, 0x8f, 0xe9, 0x27, 0xdb, 0x82, 0x7a, 0x6a, 0xac, - 0xe6, 0x1d, 0xe5, 0xac, 0xeb, 0x8d, 0xd7, 0x53, 0x16, 0x67, 0xad, 0xaf, 0xc3, 0xd6, 0xbe, 0x0f, - 0xec, 0xe7, 0x8c, 0x98, 0xec, 0x41, 0x39, 0x6a, 0x9f, 0x1e, 0x70, 0x88, 0xee, 0xf7, 0x95, 0x44, - 0xc0, 0x61, 0x6b, 0x30, 0xf0, 0x05, 0x5f, 0xa4, 0x0d, 0x33, 0x62, 0xf9, 0xa0, 0xed, 0x98, 0x2d, - 0xe2, 0xfb, 0xc6, 0x7f, 0xcb, 0x40, 0x81, 0xa2, 0x1f, 0xdf, 0x81, 0x79, 0xc2, 0x8f, 0x1c, 0x08, - 0xa5, 0x61, 0x9c, 0xf6, 0xdd, 0x9e, 0xf4, 0x1d, 0x14, 0xcb, 0x42, 0x8b, 0xdc, 0xce, 0x46, 0x33, - 0xaf, 0x45, 0x6f, 0xdf, 0x85, 0x72, 0x54, 0xb5, 0x46, 0x3a, 0x25, 0x55, 0x33, 0x7b, 0x03, 0xf2, - 0x67, 0xde, 0x58, 0x9d, 0xf3, 0x40, 0x3c, 0x92, 0x26, 0xc2, 0xe3, 0xb6, 0x88, 0x3a, 0xa8, 0xf1, - 0xf2, 0x7c, 0x22, 0xaa, 0x04, 0xc9, 0x60, 0xb6, 0x8f, 0x73, 0x29, 0x7d, 0x3c, 0x82, 0x79, 0xc1, - 0x07, 0x34, 0x07, 0x95, 0xeb, 0x37, 0xcd, 0xf7, 0x84, 0x84, 0xd7, 0x1f, 0x4e, 0x06, 0x5c, 0x3f, - 0x69, 0x43, 0x6f, 0x36, 0x09, 0x57, 0x92, 0xb5, 0xf1, 0x07, 0x19, 0xe2, 0x2f, 0xa2, 0x5c, 0x76, - 0x1f, 0xf2, 0x62, 0x7f, 0x9b, 0x3a, 0x77, 0x8f, 0xe2, 0x20, 0x04, 0x9e, 0x89, 0x18, 0x78, 0xdd, - 0xc1, 0x64, 0x94, 0x2c, 0xbd, 0x66, 0x56, 0xdc, 0xc9, 0x28, 0x3a, 0xa8, 0xfa, 0x9a, 0xea, 0xd6, - 0xd4, 0x21, 0x0f, 0xf5, 0x3e, 0x5a, 0xa6, 0xeb, 0x9a, 0x5b, 0x5c, 0x3e, 0xb1, 0x63, 0x2a, 0x29, - 0x70, 0x70, 0xca, 0x35, 0x77, 0xb8, 0x3f, 0xca, 0x42, 0x2d, 0xd1, 0x22, 0xf4, 0x0b, 0x14, 0x1b, - 0x00, 0x99, 0x91, 0xe4, 0x7c, 0x83, 0x00, 0x49, 0x41, 0x5d, 0x1b, 0xa7, 0x6c, 0x62, 0x9c, 0x22, - 0x57, 0x9c, 0x9c, 0xee, 0x8a, 0xf3, 0x08, 0xca, 0x71, 0xc4, 0x7e, 0xb2, 0x49, 0xa2, 0x3e, 0x15, - 0x0d, 0x12, 0x23, 0xc5, 0xce, 0x3b, 0x05, 0xdd, 0x79, 0xe7, 0x7b, 0x9a, 0xaf, 0xc7, 0x1c, 0x16, - 0x63, 0xa4, 0x8d, 0xe8, 0x2f, 0xc4, 0xd3, 0xc3, 0xf8, 0x18, 0x2a, 0x5a, 0xe3, 0x75, 0x9f, 0x8e, - 0x4c, 0xc2, 0xa7, 0x23, 0x8a, 0xdb, 0xca, 0xc6, 0x71, 0x5b, 0xc6, 0x6f, 0x65, 0xa1, 0x26, 0xd6, - 0x97, 0xe3, 0x9e, 0x1e, 0x7a, 0x43, 0xa7, 0x8f, 0x66, 0xa5, 0x68, 0x85, 0x49, 0x41, 0x4b, 0xad, - 0x33, 0xb9, 0xc4, 0x48, 0xce, 0xd2, 0xc3, 0x53, 0x89, 0x49, 0x47, 0xe1, 0xa9, 0x06, 0xd4, 0x04, - 0x63, 0x44, 0x03, 0x51, 0x7c, 0x9f, 0x80, 0x59, 0x39, 0xe1, 0x7c, 0xc3, 0x0e, 0x88, 0x43, 0x7e, - 0x03, 0x16, 0x05, 0x0e, 0x46, 0xe6, 0x8d, 0x9c, 0xe1, 0xd0, 0x21, 0x4c, 0x3a, 0x68, 0x6a, 0x9c, - 0x70, 0x6e, 0xda, 0x21, 0xdf, 0x13, 0x09, 0xf2, 0xfa, 0x81, 0xd2, 0xc0, 0x09, 0xec, 0xe3, 0xd8, - 0x7b, 0x33, 0xfa, 0x46, 0x3b, 0xb2, 0x7d, 0xa9, 0xd9, 0x91, 0xe9, 0x00, 0xa2, 0x32, 0xb2, 0x2f, - 0x23, 0x3b, 0xf2, 0x14, 0x25, 0x15, 0xa7, 0x29, 0xc9, 0xf8, 0x77, 0x59, 0xa8, 0x68, 0x64, 0xf9, - 0x3a, 0xbb, 0xeb, 0x9d, 0x19, 0x33, 0x60, 0x59, 0xb7, 0xf8, 0xbd, 0x95, 0xac, 0x12, 0x3d, 0x5d, - 0xe8, 0xa2, 0x03, 0x8d, 0x80, 0x6f, 0x41, 0x59, 0xac, 0xba, 0x0f, 0xf0, 0xc0, 0x55, 0x5e, 0xd3, - 0x81, 0x80, 0xc3, 0xc9, 0xb1, 0x4a, 0x7c, 0x8c, 0x89, 0x85, 0x38, 0xf1, 0xb1, 0x48, 0x7c, 0x99, - 0xcb, 0xf6, 0xb7, 0xa1, 0x2a, 0x4b, 0xc5, 0x39, 0xc5, 0xee, 0xc6, 0xab, 0x3e, 0x31, 0xdf, 0x66, - 0x85, 0xaa, 0xa3, 0xc9, 0x97, 0x19, 0x1f, 0xab, 0x8c, 0xa5, 0x57, 0x65, 0x7c, 0x4c, 0x1f, 0xc6, - 0x76, 0xe4, 0x05, 0x8f, 0x5e, 0x56, 0x8a, 0x8f, 0x3d, 0x84, 0x45, 0xc5, 0xae, 0x26, 0xae, 0xed, - 0xba, 0xde, 0xc4, 0xed, 0x73, 0x15, 0xd0, 0xc5, 0x64, 0xd2, 0x51, 0x9c, 0x62, 0x0c, 0xa2, 0x88, - 0x5f, 0xf2, 0xd6, 0x7a, 0x00, 0x05, 0x92, 0xcb, 0x49, 0xf8, 0x48, 0x67, 0x5c, 0x84, 0xc2, 0xee, - 0x43, 0x81, 0xc4, 0xf3, 0xec, 0xb5, 0xcc, 0x86, 0x10, 0x8c, 0x16, 0x30, 0x91, 0x71, 0x8f, 0x87, - 0xbe, 0xd3, 0x0f, 0xe2, 0x58, 0xb1, 0x82, 0xd0, 0x3f, 0xa9, 0xae, 0xf8, 0xe4, 0x36, 0xc6, 0x44, - 0x1d, 0x95, 0x70, 0xc4, 0xc6, 0xb4, 0x98, 0x28, 0x43, 0x8a, 0x4b, 0x43, 0x58, 0x39, 0xe6, 0xe1, - 0x05, 0xe7, 0xae, 0x2b, 0x84, 0xa1, 0x3e, 0x77, 0x43, 0xdf, 0x1e, 0x8a, 0x49, 0xa2, 0x1e, 0x3c, - 0x99, 0x29, 0x35, 0x3e, 0x03, 0xd9, 0x88, 0x33, 0x6e, 0x46, 0xf9, 0x88, 0x77, 0x2c, 0x1f, 0xa7, - 0xa5, 0xad, 0xfd, 0x1a, 0xac, 0x5d, 0x9f, 0x29, 0x25, 0x22, 0xf4, 0x7e, 0x92, 0xab, 0x44, 0x56, - 0xbf, 0xa1, 0x67, 0x87, 0xd4, 0x1a, 0x9d, 0xb3, 0xec, 0x43, 0x45, 0x4b, 0x89, 0xf7, 0xfe, 0x0c, - 0x0a, 0x77, 0xf4, 0x21, 0x76, 0x24, 0xd7, 0xf3, 0x47, 0x68, 0x65, 0x1b, 0x58, 0x71, 0xe9, 0x19, - 0x73, 0x3e, 0x86, 0x63, 0x08, 0xbc, 0xb1, 0x0e, 0xf3, 0x28, 0xd9, 0x6b, 0x1b, 0xdd, 0xcb, 0x84, - 0x41, 0x63, 0x09, 0xd8, 0x3e, 0xf1, 0x2e, 0xdd, 0x79, 0xf3, 0xbf, 0xe4, 0xa0, 0xa2, 0x81, 0xc5, - 0x6e, 0x84, 0xee, 0x7e, 0xd6, 0xc0, 0xb1, 0x47, 0x5c, 0x99, 0x34, 0x6b, 0x66, 0x0d, 0xa1, 0x5b, - 0x12, 0x28, 0xf6, 0x62, 0xfb, 0xfc, 0xd4, 0xf2, 0x26, 0xa1, 0x35, 0xe0, 0xa7, 0x3e, 0x57, 0xad, - 0xac, 0xda, 0xe7, 0xa7, 0x07, 0x93, 0x70, 0x0b, 0x61, 0x02, 0x4b, 0xf0, 0x12, 0x0d, 0x4b, 0x7a, - 0xa8, 0x8d, 0xec, 0xcb, 0x18, 0x4b, 0xba, 0x49, 0x12, 0x65, 0xe6, 0x23, 0x37, 0x49, 0xd2, 0x16, - 0xa7, 0x37, 0xd0, 0xc2, 0xec, 0x06, 0xfa, 0x2d, 0x58, 0xa1, 0x0d, 0x54, 0xb2, 0x66, 0x6b, 0x6a, - 0x25, 0x2f, 0x61, 0xaa, 0xec, 0xa4, 0x26, 0xf6, 0x36, 0x44, 0x0f, 0x14, 0x5b, 0x0a, 0x9c, 0x1f, - 0x13, 0x23, 0xcb, 0x98, 0xa2, 0x67, 0xb2, 0xf0, 0xae, 0xf3, 0x63, 0x2e, 0x30, 0xd1, 0x17, 0x46, - 0xc7, 0x94, 0x01, 0x19, 0x23, 0xc7, 0x9d, 0xc6, 0xb4, 0x2f, 0x93, 0x98, 0x65, 0x89, 0x69, 0x5f, - 0xea, 0x98, 0x4f, 0x60, 0x75, 0xc4, 0x07, 0x8e, 0x9d, 0x2c, 0xd6, 0x8a, 0x05, 0xb7, 0x25, 0x4a, - 0xd6, 0xf2, 0x74, 0x49, 0x71, 0x17, 0xa3, 0xf1, 0x63, 0x6f, 0x74, 0xec, 0x90, 0xcc, 0x42, 0xde, - 0x39, 0x79, 0xb3, 0xee, 0x4e, 0x46, 0x3f, 0x44, 0xb0, 0xc8, 0x12, 0x18, 0x35, 0xa8, 0x74, 0x43, - 0x6f, 0xac, 0xa6, 0xb9, 0x0e, 0x55, 0xfa, 0x94, 0x51, 0x92, 0xb7, 0xe0, 0x26, 0xb2, 0x84, 0x9e, - 0x37, 0xf6, 0x86, 0xde, 0xe9, 0x55, 0xe2, 0x1c, 0xef, 0x3f, 0x66, 0x60, 0x31, 0x91, 0x2a, 0xd9, - 0xeb, 0xb7, 0x88, 0x9f, 0x45, 0xa1, 0x6e, 0xb4, 0x06, 0x17, 0xb4, 0x35, 0x48, 0x88, 0xc4, 0xcc, - 0x54, 0xf8, 0x5b, 0x2b, 0xbe, 0xa2, 0x41, 0x65, 0x24, 0x96, 0xd2, 0x9c, 0x65, 0x29, 0x32, 0xbf, - 0xba, 0xbc, 0x41, 0x15, 0xf1, 0x4b, 0x32, 0x68, 0x66, 0x20, 0xbb, 0x9c, 0x4b, 0x86, 0x05, 0xe8, - 0x67, 0x7e, 0xaa, 0x05, 0xf1, 0x41, 0x60, 0x60, 0xfc, 0xf3, 0x0c, 0x40, 0xdc, 0x3a, 0x0c, 0x4c, - 0x88, 0xe4, 0x16, 0xba, 0xfd, 0x4c, 0x93, 0x51, 0xde, 0x84, 0x6a, 0xe4, 0x9f, 0x1c, 0x4b, 0x42, - 0x15, 0x05, 0x13, 0xe2, 0xd0, 0xbb, 0x30, 0x7f, 0x3a, 0xf4, 0x8e, 0x51, 0x62, 0x95, 0x72, 0x0b, - 0x79, 0xa7, 0xd5, 0x09, 0xac, 0xa4, 0x91, 0x58, 0x6e, 0xca, 0xa7, 0xba, 0x30, 0xeb, 0x52, 0x90, - 0xf1, 0xdb, 0xd9, 0xc8, 0x51, 0x33, 0x1e, 0x89, 0x97, 0xab, 0x77, 0x3f, 0x8b, 0xe7, 0xcc, 0xcb, - 0x8c, 0x89, 0x1f, 0x43, 0xdd, 0xa7, 0x4d, 0x49, 0xed, 0x58, 0xf9, 0x97, 0xec, 0x58, 0x35, 0x3f, - 0x21, 0xe9, 0xbc, 0x07, 0x0d, 0x7b, 0x70, 0xce, 0xfd, 0xd0, 0xc1, 0xd3, 0x7a, 0x94, 0x8f, 0xa5, - 0x6b, 0xa4, 0x06, 0x47, 0x41, 0xf4, 0x5d, 0x98, 0x97, 0x91, 0xbb, 0x11, 0xa6, 0xbc, 0x0b, 0x28, - 0x06, 0x0b, 0x44, 0xe3, 0x5f, 0x2a, 0xcf, 0xd0, 0xe4, 0xec, 0xbe, 0x7c, 0x54, 0xf4, 0x1e, 0x66, - 0x67, 0xcd, 0xa5, 0x92, 0x90, 0xa4, 0x11, 0x40, 0xf2, 0x23, 0x02, 0x4a, 0x13, 0x40, 0x72, 0x58, - 0xf3, 0xaf, 0x33, 0xac, 0xc6, 0x7f, 0xca, 0x40, 0x71, 0xc7, 0x1b, 0xef, 0x38, 0xe4, 0x9a, 0x8f, - 0xcb, 0x24, 0xb2, 0x51, 0xcd, 0x89, 0x4f, 0x74, 0xf3, 0x79, 0x49, 0x80, 0x5a, 0xaa, 0x98, 0x57, - 0x4b, 0x8a, 0x79, 0xdf, 0x83, 0x5b, 0x68, 0x02, 0xf4, 0xbd, 0xb1, 0xe7, 0x8b, 0xa5, 0x6a, 0x0f, - 0x49, 0xdc, 0xf3, 0xdc, 0xf0, 0x4c, 0xf1, 0xce, 0x9b, 0x27, 0x9c, 0x1f, 0x6a, 0x18, 0x7b, 0x11, - 0x02, 0x86, 0x80, 0x0e, 0xc3, 0x73, 0x8b, 0x34, 0x74, 0x29, 0x8f, 0x12, 0x47, 0x9d, 0x17, 0x09, - 0x6d, 0x84, 0xa3, 0x44, 0x6a, 0x7c, 0x07, 0xca, 0xd1, 0x61, 0x0f, 0x7b, 0x1f, 0xca, 0x67, 0xde, - 0x58, 0x9e, 0x08, 0x65, 0x12, 0x41, 0x7c, 0xb2, 0xd7, 0x66, 0xe9, 0x8c, 0x7e, 0x04, 0xc6, 0x9f, - 0x15, 0xa1, 0xd8, 0x71, 0xcf, 0x3d, 0xa7, 0x8f, 0xbe, 0xa5, 0x23, 0x3e, 0xf2, 0xd4, 0xf5, 0x01, - 0xe2, 0x37, 0x7a, 0x62, 0xc5, 0x37, 0xfa, 0xe4, 0xa4, 0x27, 0x56, 0x74, 0x97, 0xcf, 0x32, 0xcc, - 0xf9, 0xfa, 0x95, 0x3c, 0x05, 0x1f, 0xbd, 0xdd, 0xa3, 0xfd, 0xb2, 0xa0, 0x5d, 0xbf, 0x20, 0xca, - 0xa2, 0xab, 0x62, 0x70, 0xc8, 0x28, 0x9c, 0xb3, 0x8c, 0x10, 0x1c, 0xb0, 0xdb, 0x50, 0x94, 0x31, - 0x73, 0x14, 0x81, 0x44, 0xee, 0xe9, 0x12, 0x84, 0xd4, 0xe0, 0x73, 0x32, 0xe1, 0x46, 0x82, 0x6c, - 0xce, 0xac, 0x2a, 0xe0, 0x96, 0xa0, 0xb5, 0xbb, 0x50, 0x21, 0x7c, 0x42, 0x29, 0x49, 0x97, 0x4c, - 0x04, 0x21, 0x42, 0xca, 0xcd, 0x56, 0xe5, 0xd4, 0x9b, 0xad, 0xd0, 0x79, 0x38, 0xe2, 0xb2, 0xd4, - 0x45, 0xa0, 0xfb, 0x8c, 0x34, 0xb8, 0xba, 0xd6, 0x4d, 0x9e, 0xa9, 0x50, 0x74, 0xb3, 0x3a, 0x53, - 0x79, 0x0b, 0x6a, 0x27, 0xf6, 0x70, 0x78, 0x6c, 0xf7, 0x5f, 0xd0, 0x51, 0x40, 0x95, 0x4e, 0x3f, - 0x15, 0x10, 0xcf, 0x02, 0xee, 0x42, 0x45, 0x9b, 0x65, 0xf4, 0xb7, 0xcc, 0x9b, 0x10, 0xcf, 0xef, - 0xf4, 0x09, 0x5f, 0xfd, 0x35, 0x4e, 0xf8, 0x34, 0xbf, 0xd3, 0xf9, 0xa4, 0xdf, 0xe9, 0x2d, 0xe4, - 0xa6, 0xd2, 0xc1, 0xb0, 0x41, 0x97, 0xe7, 0xd8, 0x83, 0x01, 0x3a, 0x18, 0xd2, 0x4d, 0x95, 0x38, - 0x78, 0x94, 0xbe, 0x40, 0xba, 0x04, 0xc1, 0x08, 0xe5, 0x0e, 0x1d, 0x53, 0x8f, 0x6d, 0x67, 0x80, - 0x21, 0x06, 0x74, 0x7a, 0x50, 0xb4, 0x47, 0xe1, 0xa1, 0xed, 0x0c, 0xd8, 0x3d, 0xa8, 0xaa, 0x64, - 0xdc, 0x1d, 0x17, 0x69, 0xfc, 0x65, 0xb2, 0xd8, 0x13, 0x0d, 0xa8, 0x45, 0x18, 0xa3, 0x38, 0x44, - 0xb9, 0x22, 0x51, 0x90, 0x0e, 0x3e, 0x40, 0x9f, 0x9e, 0x90, 0x63, 0x20, 0x72, 0xfd, 0xf1, 0x2d, - 0xd9, 0x57, 0x49, 0xa5, 0xea, 0x3f, 0x19, 0xc7, 0x08, 0x53, 0x08, 0x77, 0x64, 0xa3, 0x5b, 0x49, - 0xc8, 0xbf, 0x12, 0x15, 0x6d, 0x74, 0x84, 0xc0, 0xbe, 0xa3, 0xe9, 0xaf, 0x4d, 0x44, 0xbe, 0x3d, - 0x55, 0xfe, 0x75, 0x11, 0x56, 0x77, 0x00, 0x9c, 0x40, 0xec, 0x32, 0x01, 0x77, 0x07, 0x18, 0x53, - 0x5c, 0x32, 0xcb, 0x4e, 0xf0, 0x8c, 0x00, 0x5f, 0xad, 0x62, 0xdb, 0x82, 0xaa, 0xde, 0x4d, 0x56, - 0x82, 0xfc, 0xc1, 0x61, 0x7b, 0xbf, 0x71, 0x83, 0x55, 0xa0, 0xd8, 0x6d, 0xf7, 0x7a, 0xbb, 0x68, - 0xe9, 0xab, 0x42, 0x29, 0x0a, 0x68, 0xcc, 0x8a, 0xaf, 0xd6, 0xe6, 0x66, 0xfb, 0xb0, 0xd7, 0xde, - 0x6a, 0xe4, 0x7e, 0x90, 0x2f, 0x65, 0x1b, 0x39, 0xe3, 0xcf, 0x73, 0x50, 0xd1, 0x46, 0xe1, 0xe5, - 0xcc, 0xf8, 0x0e, 0x00, 0x6a, 0x92, 0xb1, 0xff, 0x69, 0xde, 0x2c, 0x0b, 0x08, 0x4d, 0xbe, 0x6e, - 0xa3, 0xc8, 0xd1, 0xad, 0x4c, 0xca, 0x46, 0xf1, 0x16, 0xd4, 0xe8, 0x82, 0x23, 0xdd, 0x5e, 0x5b, - 0x30, 0xab, 0x04, 0x94, 0xac, 0x1a, 0x23, 0xa2, 0x11, 0x09, 0x63, 0xe5, 0xe4, 0x75, 0x27, 0x04, - 0xc2, 0x68, 0x39, 0x0c, 0x75, 0x0c, 0xbc, 0xe1, 0x39, 0x27, 0x0c, 0x92, 0x08, 0x2b, 0x12, 0xd6, - 0x93, 0xb1, 0xdd, 0x92, 0x1f, 0x6a, 0x21, 0xb9, 0x05, 0xb3, 0x4a, 0x40, 0x59, 0xd1, 0x37, 0x14, - 0x01, 0x95, 0x90, 0x80, 0x56, 0x67, 0xa9, 0x21, 0x41, 0x3c, 0xbb, 0x33, 0xc7, 0x88, 0x65, 0x24, - 0x8c, 0xaf, 0xcd, 0xe6, 0x7b, 0xf5, 0x71, 0x22, 0x7b, 0x1f, 0xd8, 0x68, 0x3c, 0xb6, 0x52, 0x0e, - 0xf8, 0xf2, 0xe6, 0xfc, 0x68, 0x3c, 0xee, 0x69, 0xe7, 0x5f, 0x5f, 0xc1, 0xd9, 0xe3, 0xe7, 0xc0, - 0x5a, 0x62, 0x01, 0x63, 0x13, 0x23, 0x55, 0x2c, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, 0x70, 0xbf, - 0x6c, 0x2a, 0xf7, 0x7b, 0x19, 0x9f, 0x30, 0xb6, 0xa1, 0x72, 0xa8, 0x5d, 0x9f, 0x76, 0x4f, 0xec, - 0x10, 0xea, 0xe2, 0x34, 0xda, 0x3b, 0xe8, 0x4c, 0xd1, 0x97, 0xf7, 0xa5, 0x69, 0xad, 0xc9, 0x6a, - 0xad, 0x31, 0xfe, 0x59, 0x86, 0xae, 0xa6, 0x89, 0x1a, 0x1f, 0xdf, 0xd8, 0xa6, 0xcc, 0x6f, 0x71, - 0xe4, 0x7c, 0x45, 0x99, 0xdd, 0x64, 0xd0, 0x3b, 0x36, 0xcd, 0xf2, 0x4e, 0x4e, 0x02, 0xae, 0x7c, - 0x3c, 0x2a, 0x08, 0x3b, 0x40, 0x90, 0x12, 0xbe, 0x85, 0x84, 0xef, 0x50, 0xf9, 0x81, 0x74, 0xec, - 0x10, 0xc2, 0xf7, 0x9e, 0x7d, 0x29, 0x6b, 0x0d, 0x84, 0x08, 0x22, 0xed, 0x03, 0x2a, 0xf2, 0x35, - 0xfa, 0x36, 0xfe, 0xb1, 0x0c, 0xee, 0x9f, 0x1e, 0xdf, 0x07, 0x50, 0x8a, 0x4a, 0x4d, 0xee, 0xb0, - 0x0a, 0x33, 0x4a, 0x17, 0xfb, 0x38, 0x1e, 0x86, 0x24, 0x5a, 0x4c, 0x8b, 0x0b, 0x6d, 0x3c, 0x1d, - 0xad, 0xd5, 0x5f, 0x07, 0x76, 0xe2, 0xf8, 0xd3, 0xc8, 0xb4, 0xd8, 0x1a, 0x98, 0xa2, 0x61, 0x1b, - 0x47, 0xb0, 0xa8, 0xb8, 0x84, 0xa6, 0x11, 0x24, 0x27, 0x2f, 0xf3, 0x0a, 0x26, 0x9f, 0x9d, 0x61, - 0xf2, 0xc6, 0x4f, 0xf3, 0x50, 0x54, 0x57, 0x11, 0xa6, 0x5d, 0x9f, 0x57, 0x4e, 0x5e, 0x9f, 0xd7, - 0x4c, 0x5c, 0xb5, 0x84, 0x53, 0x2f, 0xf7, 0xfb, 0x77, 0xa7, 0xb7, 0x6c, 0xcd, 0x56, 0x91, 0xd8, - 0xb6, 0x57, 0x20, 0x3f, 0xb6, 0xc3, 0x33, 0x3c, 0x97, 0x24, 0xe2, 0xc1, 0x6f, 0x65, 0xc3, 0x28, - 0x24, 0x6d, 0x18, 0x69, 0x57, 0x0d, 0x92, 0x48, 0x3a, 0x73, 0xd5, 0xe0, 0x2d, 0x20, 0xf9, 0x42, - 0x73, 0x71, 0x2b, 0x21, 0x40, 0xec, 0x45, 0x49, 0x71, 0xa4, 0x34, 0x2d, 0x8e, 0xbc, 0xb6, 0xa8, - 0xf0, 0x2d, 0x98, 0xa3, 0x6b, 0x3a, 0x64, 0x84, 0xaf, 0xda, 0x50, 0xe4, 0x18, 0xaa, 0xff, 0x14, - 0xf7, 0x60, 0x4a, 0x5c, 0xfd, 0xde, 0xae, 0x4a, 0xe2, 0xde, 0x2e, 0xdd, 0xb6, 0x52, 0x4d, 0xda, - 0x56, 0xee, 0x43, 0x23, 0x1a, 0x50, 0x3c, 0xa9, 0x74, 0x03, 0x19, 0x3f, 0x58, 0x57, 0x70, 0xc1, - 0x25, 0xf7, 0x83, 0x78, 0x43, 0xac, 0x27, 0x36, 0x44, 0xc1, 0xc3, 0x5a, 0x61, 0xc8, 0x47, 0xe3, - 0x50, 0x6e, 0x88, 0x18, 0x61, 0xa4, 0x37, 0x30, 0x19, 0xfb, 0x5e, 0x83, 0x72, 0x67, 0xdf, 0xda, - 0xde, 0xed, 0x3c, 0xdd, 0xe9, 0x35, 0x32, 0xe2, 0xb3, 0x7b, 0xb4, 0xb9, 0xd9, 0x6e, 0x6f, 0xe1, - 0x8e, 0x03, 0x30, 0xb7, 0xdd, 0xea, 0x88, 0xdd, 0x27, 0x67, 0xfc, 0x6e, 0x16, 0x2a, 0x5a, 0xf1, - 0xec, 0x49, 0x34, 0x2a, 0x74, 0xb5, 0xd3, 0x9d, 0xd9, 0x26, 0xac, 0x2b, 0x56, 0xac, 0x0d, 0x4b, - 0x74, 0xb1, 0x62, 0xf6, 0xda, 0x8b, 0x15, 0xd9, 0x3b, 0x30, 0x6f, 0x53, 0x09, 0xd1, 0x28, 0xc8, - 0x53, 0x78, 0x09, 0x96, 0x83, 0x80, 0x8e, 0x9d, 0xf1, 0x7e, 0x22, 0xf0, 0xf2, 0xca, 0x97, 0x32, - 0xda, 0x52, 0x70, 0xb0, 0x8a, 0x27, 0xb6, 0x33, 0x9c, 0xf8, 0x5c, 0x5a, 0xcd, 0xa3, 0x9d, 0x99, - 0xa0, 0xa6, 0x4a, 0x36, 0x3e, 0x04, 0x88, 0xdb, 0x9c, 0x1c, 0x9c, 0x1b, 0xc9, 0xc1, 0xc9, 0x68, - 0x83, 0x93, 0x35, 0xb6, 0x88, 0x8d, 0xc8, 0x81, 0x8e, 0x8e, 0xdd, 0xbe, 0x01, 0xea, 0x20, 0xd0, - 0x42, 0xf7, 0xea, 0xf1, 0x90, 0x87, 0xea, 0x96, 0x80, 0x05, 0x99, 0xd2, 0x89, 0x12, 0xd4, 0xa5, - 0x1d, 0x71, 0x29, 0x31, 0x37, 0x92, 0x24, 0x39, 0xcd, 0x8d, 0x24, 0xaa, 0x19, 0xa5, 0x1b, 0x6b, - 0xd0, 0xdc, 0xe2, 0xa2, 0xb4, 0xd6, 0x70, 0x38, 0xd5, 0x1c, 0xe3, 0x16, 0xdc, 0x4c, 0x49, 0x93, - 0x87, 0x10, 0x9f, 0xc0, 0x72, 0x8b, 0x2e, 0x04, 0xf8, 0xaa, 0x22, 0xff, 0x8c, 0x26, 0xac, 0x4c, - 0x17, 0x29, 0x2b, 0xdb, 0x86, 0x85, 0x2d, 0x7e, 0x3c, 0x39, 0xdd, 0xe5, 0xe7, 0x71, 0x45, 0x0c, - 0xf2, 0xc1, 0x99, 0x77, 0x21, 0xc7, 0x07, 0x7f, 0xa3, 0x97, 0xa1, 0xc0, 0xb1, 0x82, 0x31, 0xef, - 0xab, 0x83, 0x68, 0x84, 0x74, 0xc7, 0xbc, 0x6f, 0x3c, 0x01, 0xa6, 0x97, 0x23, 0xc7, 0x4b, 0x68, - 0x09, 0x93, 0x63, 0x2b, 0xb8, 0x0a, 0x42, 0x3e, 0x52, 0x11, 0x6f, 0x10, 0x4c, 0x8e, 0xbb, 0x04, - 0x31, 0xde, 0x85, 0xea, 0xa1, 0x7d, 0x65, 0xf2, 0xcf, 0x65, 0x60, 0xd9, 0x2a, 0x14, 0xc7, 0xf6, - 0x95, 0x60, 0x03, 0x91, 0x4d, 0x0a, 0x93, 0x8d, 0x3f, 0xcc, 0xc3, 0x1c, 0x61, 0xb2, 0x7b, 0x74, - 0xb9, 0xaf, 0xe3, 0xe2, 0x32, 0x54, 0x8c, 0x52, 0x03, 0xcd, 0xf0, 0xd2, 0xec, 0x2c, 0x2f, 0x95, - 0x07, 0x68, 0xea, 0x52, 0x23, 0x65, 0x3d, 0x70, 0x27, 0x23, 0x75, 0x93, 0x51, 0x32, 0x2a, 0x3e, - 0x1f, 0x5f, 0xde, 0x4c, 0x21, 0xc3, 0x49, 0xfb, 0x6e, 0xac, 0x8b, 0x50, 0xeb, 0xd4, 0x16, 0x21, - 0xd9, 0xa5, 0x0e, 0x4a, 0x55, 0x78, 0x8a, 0x2a, 0x5a, 0x32, 0xa9, 0xf0, 0xcc, 0x28, 0x36, 0xa5, - 0x57, 0x2b, 0x36, 0x74, 0xb2, 0xf6, 0x12, 0xc5, 0x06, 0x5e, 0x43, 0xb1, 0x79, 0x0d, 0xdb, 0xea, - 0x4d, 0x28, 0xe1, 0xbe, 0xaf, 0x71, 0x4f, 0xb1, 0xdf, 0x0b, 0xee, 0xf9, 0x6d, 0x4d, 0xf4, 0x27, - 0xc7, 0x8e, 0x5b, 0xf1, 0x32, 0x31, 0xf9, 0xe7, 0xbf, 0x18, 0x9b, 0xd5, 0x73, 0x28, 0x4a, 0xa8, - 0x20, 0x68, 0xd7, 0x1e, 0xa9, 0x7b, 0xe1, 0xf0, 0xb7, 0x18, 0x36, 0xbc, 0xcc, 0xea, 0xf3, 0x89, - 0xe3, 0xf3, 0x81, 0xba, 0xf0, 0xc7, 0xc1, 0x35, 0x2a, 0x20, 0xa2, 0x83, 0x42, 0x0d, 0x71, 0xbd, - 0x0b, 0x57, 0x5e, 0xf7, 0x51, 0x74, 0x82, 0x67, 0xe2, 0xd3, 0x60, 0xd0, 0xc0, 0x9b, 0x21, 0xc7, - 0x9e, 0xaf, 0x36, 0x27, 0xe3, 0xa7, 0x19, 0x68, 0xc8, 0xd5, 0x15, 0xa5, 0xe9, 0x5a, 0x40, 0xe1, - 0x3a, 0x3f, 0x84, 0x97, 0x5f, 0xdf, 0x63, 0x40, 0x0d, 0x0f, 0x3f, 0xa2, 0x9d, 0x8a, 0x0e, 0x6f, - 0x2a, 0x02, 0xb8, 0x2d, 0x77, 0xab, 0x37, 0xa0, 0xa2, 0x7c, 0xa0, 0x47, 0xce, 0x50, 0xdd, 0xd3, - 0x4e, 0x4e, 0xd0, 0x7b, 0xce, 0x50, 0x6d, 0x74, 0xbe, 0x2d, 0xa3, 0x77, 0x33, 0xb8, 0xd1, 0x99, - 0x76, 0xc8, 0x8d, 0x7f, 0x93, 0x81, 0x05, 0xad, 0x2b, 0x72, 0xdd, 0x7e, 0x04, 0xd5, 0xe8, 0x4a, - 0x56, 0x1e, 0x49, 0x5e, 0xab, 0x49, 0x46, 0x13, 0x67, 0xab, 0xf4, 0x23, 0x48, 0x20, 0x1a, 0x33, - 0xb0, 0xaf, 0xc8, 0x51, 0x77, 0x32, 0x52, 0xca, 0xcd, 0xc0, 0xbe, 0xda, 0xe6, 0xbc, 0x3b, 0x19, - 0x09, 0xd5, 0xf5, 0x82, 0xf3, 0x17, 0x11, 0x02, 0xc9, 0x5c, 0x20, 0x60, 0x12, 0xc3, 0x80, 0xda, - 0xc8, 0x73, 0xc3, 0xb3, 0x08, 0x45, 0x4a, 0x9d, 0x08, 0x24, 0x1c, 0xe3, 0x4f, 0xb3, 0xb0, 0x48, - 0x47, 0x6c, 0xf2, 0x68, 0x53, 0xb2, 0xae, 0x26, 0xcc, 0xd1, 0x69, 0x23, 0x31, 0xaf, 0x9d, 0x1b, - 0xa6, 0xfc, 0x66, 0xdf, 0x7a, 0xcd, 0x63, 0x41, 0x15, 0x20, 0x7c, 0xcd, 0xf0, 0xe7, 0x66, 0x87, - 0xff, 0xfa, 0xe1, 0x4d, 0x33, 0x74, 0x16, 0xd2, 0x0c, 0x9d, 0xaf, 0x63, 0x5e, 0x9c, 0x09, 0x65, - 0x2d, 0x4a, 0x1c, 0x2d, 0x94, 0xf5, 0x09, 0xac, 0x26, 0x70, 0x90, 0x5b, 0x3b, 0x27, 0x0e, 0x57, - 0xb7, 0xa9, 0x2c, 0x69, 0xd8, 0x5d, 0x95, 0xb6, 0x51, 0x84, 0x42, 0xd0, 0xf7, 0xc6, 0xdc, 0x58, - 0x81, 0xa5, 0xe4, 0xa8, 0xca, 0x6d, 0xe2, 0xf7, 0x32, 0xd0, 0x94, 0x6e, 0x29, 0x8e, 0x7b, 0xba, - 0xe3, 0x04, 0xa1, 0xe7, 0x47, 0x57, 0x97, 0xde, 0x01, 0x08, 0x42, 0xdb, 0x97, 0xda, 0xa6, 0xbc, - 0x3f, 0x04, 0x21, 0xa8, 0x49, 0xde, 0x84, 0x12, 0x77, 0x07, 0x94, 0x48, 0xd4, 0x50, 0xe4, 0xee, - 0x40, 0xe9, 0xa1, 0x33, 0xf2, 0x77, 0x2d, 0xa9, 0x5e, 0xc8, 0x70, 0x7e, 0x31, 0x3a, 0xfc, 0x1c, - 0x37, 0xde, 0x7c, 0x14, 0xce, 0xbf, 0x67, 0x5f, 0xa2, 0x93, 0x67, 0x60, 0xfc, 0x83, 0x2c, 0xcc, - 0xc7, 0xed, 0xa3, 0xbb, 0x40, 0x5e, 0x7e, 0xab, 0xc9, 0x3d, 0x49, 0x0e, 0x8e, 0x90, 0xdf, 0xb5, - 0x83, 0xc7, 0x12, 0x2d, 0xce, 0x8e, 0xcb, 0x0c, 0xa8, 0x28, 0x0c, 0x6f, 0x12, 0x6a, 0x37, 0x08, - 0x96, 0x09, 0xe5, 0x60, 0x12, 0x0a, 0x85, 0x4b, 0x68, 0x9e, 0x8e, 0x2b, 0x55, 0x9e, 0x82, 0x3d, - 0x0a, 0x3b, 0xf8, 0x30, 0x81, 0x00, 0x8b, 0x6c, 0x34, 0x91, 0x02, 0x4b, 0xe0, 0x37, 0x48, 0xce, - 0xa6, 0x99, 0x43, 0x19, 0x5b, 0x17, 0x42, 0xe9, 0x8e, 0xe6, 0x48, 0x08, 0x7d, 0x03, 0x2a, 0x54, - 0x78, 0x1c, 0xb9, 0x9c, 0x37, 0xcb, 0x58, 0x03, 0xa6, 0xcb, 0x43, 0x20, 0x6f, 0x92, 0x50, 0x7d, - 0x81, 0xaa, 0x42, 0xaf, 0x8f, 0xbf, 0x9d, 0x81, 0x9b, 0x29, 0xd3, 0x26, 0x57, 0xf9, 0x26, 0x2c, - 0x9c, 0x44, 0x89, 0x6a, 0x74, 0x69, 0xa9, 0xaf, 0x28, 0xb6, 0x9a, 0x1c, 0x53, 0xb3, 0x71, 0x92, - 0x04, 0xc4, 0x4a, 0x17, 0xcd, 0x60, 0x22, 0x2e, 0x1e, 0x95, 0x2e, 0x9a, 0x46, 0xd2, 0x77, 0x0e, - 0x61, 0xad, 0x7d, 0x29, 0x38, 0xc6, 0xa6, 0xfe, 0xb2, 0x86, 0x22, 0xa3, 0xe4, 0x01, 0x73, 0xe6, - 0xb5, 0x0e, 0x98, 0x07, 0x14, 0x48, 0x1b, 0x95, 0xf5, 0xb3, 0x14, 0x82, 0x1b, 0xa8, 0xc8, 0x43, - 0x2f, 0x83, 0xa8, 0x00, 0xf9, 0x7e, 0xf4, 0x22, 0x88, 0x11, 0xc0, 0xfc, 0xde, 0x64, 0x18, 0x3a, - 0xf1, 0x23, 0x21, 0xec, 0x5b, 0x32, 0x0f, 0xd6, 0xa3, 0x46, 0x2d, 0xb5, 0x22, 0x88, 0x2a, 0xc2, - 0xc1, 0x1a, 0x89, 0x82, 0xac, 0xd9, 0xfa, 0xe6, 0x47, 0xc9, 0x1a, 0x8c, 0x9b, 0xb0, 0x1a, 0x7f, - 0xd1, 0xb0, 0xa9, 0xad, 0xe6, 0x9f, 0x66, 0xc8, 0xa3, 0x3c, 0xf9, 0x60, 0x09, 0x6b, 0xc3, 0x62, - 0xe0, 0xb8, 0xa7, 0x43, 0xae, 0x17, 0x1f, 0xc8, 0x41, 0x58, 0x4e, 0xb6, 0x4d, 0x3e, 0x6a, 0x62, - 0x2e, 0x50, 0x8e, 0xb8, 0xb4, 0x80, 0x6d, 0x5c, 0xd7, 0xc8, 0x98, 0x2c, 0xa6, 0x46, 0x63, 0xb6, - 0xf1, 0x1d, 0xa8, 0x27, 0x2b, 0x62, 0xdf, 0x96, 0xf1, 0xe7, 0x71, 0xab, 0x72, 0x53, 0xc1, 0xb9, - 0x31, 0x41, 0x54, 0xe2, 0xb1, 0x0f, 0x8c, 0xbf, 0x9b, 0x81, 0xa6, 0xc9, 0x05, 0xe5, 0x6a, 0xad, - 0x54, 0x34, 0xf3, 0xd1, 0x4c, 0xa9, 0xd7, 0xf7, 0x55, 0x85, 0xb5, 0xab, 0x16, 0x7d, 0xfd, 0xda, - 0xc9, 0xd8, 0xb9, 0x31, 0xd3, 0xa3, 0x8d, 0x12, 0xcc, 0x11, 0x8a, 0xb1, 0x0a, 0xcb, 0xb2, 0x3d, - 0xaa, 0x2d, 0xb1, 0xf5, 0x30, 0x51, 0x63, 0xc2, 0x7a, 0xb8, 0x06, 0x4d, 0x0a, 0x34, 0xd5, 0x3b, - 0x21, 0x33, 0x6e, 0x01, 0xdb, 0xb3, 0xfb, 0xb6, 0xef, 0x79, 0xee, 0x21, 0xf7, 0xa5, 0x7f, 0x2e, - 0x4a, 0x98, 0x68, 0x5c, 0x53, 0xa2, 0x30, 0x7d, 0xa9, 0x7b, 0x53, 0x3d, 0x57, 0xb9, 0x23, 0xd1, - 0x97, 0x61, 0xc2, 0xe2, 0x86, 0xfd, 0x82, 0xab, 0x92, 0xd4, 0x10, 0x7d, 0x0c, 0x95, 0x71, 0x54, - 0xa8, 0x1a, 0x77, 0x75, 0x3f, 0xc6, 0x6c, 0xb5, 0xa6, 0x8e, 0x6d, 0x3c, 0x86, 0xa5, 0x64, 0x99, - 0x92, 0x75, 0xac, 0x41, 0x69, 0x24, 0x61, 0xb2, 0x75, 0xd1, 0xb7, 0xf1, 0x3b, 0x25, 0x28, 0x4a, - 0x7d, 0x8e, 0xad, 0x43, 0xbe, 0xaf, 0x5c, 0xc2, 0xe2, 0x6b, 0x97, 0x64, 0xaa, 0xfa, 0xbf, 0x89, - 0x8e, 0x61, 0x02, 0x8f, 0x7d, 0x0c, 0xf5, 0xa4, 0x55, 0x74, 0x2a, 0x8c, 0x3d, 0x69, 0xce, 0xac, - 0xf5, 0xa7, 0xec, 0x5f, 0xe5, 0x78, 0x73, 0x24, 0x99, 0xa1, 0x74, 0xa6, 0xed, 0x9e, 0x9e, 0x2b, - 0xe4, 0xed, 0xe0, 0xcc, 0xb6, 0x1e, 0x3f, 0xf9, 0x50, 0xc6, 0xb1, 0x57, 0x10, 0xd8, 0x3d, 0xb3, - 0x1f, 0x3f, 0xf9, 0x70, 0x5a, 0x92, 0x96, 0x51, 0xec, 0x9a, 0x24, 0xbd, 0x04, 0x05, 0xba, 0x20, - 0x94, 0x7c, 0x7b, 0xe8, 0x83, 0x3d, 0x82, 0x25, 0xa9, 0xb6, 0x5a, 0xd2, 0x0b, 0x9b, 0xb8, 0x60, - 0x89, 0x02, 0xdf, 0x64, 0x5a, 0x17, 0x93, 0xe8, 0x6c, 0x68, 0x05, 0xe6, 0xce, 0xe2, 0xdb, 0x5e, - 0x6b, 0xa6, 0xfc, 0x32, 0xfe, 0xb4, 0x00, 0x15, 0x6d, 0x50, 0x58, 0x15, 0x4a, 0x66, 0xbb, 0xdb, - 0x36, 0x3f, 0x6d, 0x6f, 0x35, 0x6e, 0xb0, 0xfb, 0xf0, 0x76, 0x67, 0x7f, 0xf3, 0xc0, 0x34, 0xdb, - 0x9b, 0x3d, 0xeb, 0xc0, 0xb4, 0xd4, 0xe5, 0x5f, 0x87, 0xad, 0xe7, 0x7b, 0xed, 0xfd, 0x9e, 0xb5, - 0xd5, 0xee, 0xb5, 0x3a, 0xbb, 0xdd, 0x46, 0x86, 0xdd, 0x86, 0x66, 0x8c, 0xa9, 0x92, 0x5b, 0x7b, - 0x07, 0x47, 0xfb, 0xbd, 0x46, 0x96, 0xdd, 0x85, 0x5b, 0xdb, 0x9d, 0xfd, 0xd6, 0xae, 0x15, 0xe3, - 0x6c, 0xee, 0xf6, 0x3e, 0xb5, 0xda, 0xbf, 0x72, 0xd8, 0x31, 0x9f, 0x37, 0x72, 0x69, 0x08, 0x42, - 0x19, 0x57, 0x25, 0xe4, 0xd9, 0x4d, 0x58, 0x26, 0x04, 0xca, 0x62, 0xf5, 0x0e, 0x0e, 0xac, 0xee, - 0xc1, 0xc1, 0x7e, 0xa3, 0xc0, 0x16, 0xa0, 0xd6, 0xd9, 0xff, 0xb4, 0xb5, 0xdb, 0xd9, 0xb2, 0xcc, - 0x76, 0x6b, 0x77, 0xaf, 0x31, 0xc7, 0x16, 0x61, 0x7e, 0x1a, 0xaf, 0x28, 0x8a, 0x50, 0x78, 0x07, - 0xfb, 0x9d, 0x83, 0x7d, 0xeb, 0xd3, 0xb6, 0xd9, 0xed, 0x1c, 0xec, 0x37, 0x4a, 0x6c, 0x05, 0x58, - 0x32, 0x69, 0x67, 0xaf, 0xb5, 0xd9, 0x28, 0xb3, 0x65, 0x58, 0x48, 0xc2, 0x9f, 0xb5, 0x9f, 0x37, - 0x80, 0x35, 0x61, 0x89, 0x1a, 0x66, 0x6d, 0xb4, 0x77, 0x0f, 0x3e, 0xb3, 0xf6, 0x3a, 0xfb, 0x9d, - 0xbd, 0xa3, 0xbd, 0x46, 0x05, 0xaf, 0x23, 0x6c, 0xb7, 0xad, 0xce, 0x7e, 0xf7, 0x68, 0x7b, 0xbb, - 0xb3, 0xd9, 0x69, 0xef, 0xf7, 0x1a, 0x55, 0xaa, 0x39, 0xad, 0xe3, 0x35, 0x91, 0x41, 0x86, 0x6a, - 0x58, 0x5b, 0x9d, 0x6e, 0x6b, 0x63, 0xb7, 0xbd, 0xd5, 0xa8, 0xb3, 0x3b, 0x70, 0xb3, 0xd7, 0xde, - 0x3b, 0x3c, 0x30, 0x5b, 0xe6, 0x73, 0x15, 0xca, 0x61, 0x6d, 0xb7, 0x3a, 0xbb, 0x47, 0x66, 0xbb, - 0x31, 0xcf, 0xde, 0x84, 0x3b, 0x66, 0xfb, 0x93, 0xa3, 0x8e, 0xd9, 0xde, 0xb2, 0xf6, 0x0f, 0xb6, - 0xda, 0xd6, 0x76, 0xbb, 0xd5, 0x3b, 0x32, 0xdb, 0xd6, 0x5e, 0xa7, 0xdb, 0xed, 0xec, 0x3f, 0x6d, - 0x34, 0xd8, 0xdb, 0x70, 0x2f, 0x42, 0x89, 0x0a, 0x98, 0xc2, 0x5a, 0x10, 0xfd, 0x53, 0x53, 0xba, - 0xdf, 0xfe, 0x95, 0x9e, 0x75, 0xd8, 0x6e, 0x9b, 0x0d, 0xc6, 0xd6, 0x60, 0x25, 0xae, 0x9e, 0x2a, - 0x90, 0x75, 0x2f, 0x8a, 0xb4, 0xc3, 0xb6, 0xb9, 0xd7, 0xda, 0x17, 0x13, 0x9c, 0x48, 0x5b, 0x12, - 0xcd, 0x8e, 0xd3, 0xa6, 0x9b, 0xbd, 0xcc, 0x18, 0xd4, 0xb5, 0x59, 0xd9, 0x6e, 0x99, 0x8d, 0x15, - 0x36, 0x0f, 0x95, 0xbd, 0xc3, 0x43, 0xab, 0xd7, 0xd9, 0x6b, 0x1f, 0x1c, 0xf5, 0x1a, 0xab, 0x6c, - 0x19, 0x1a, 0x9d, 0xfd, 0x5e, 0xdb, 0x14, 0x73, 0xad, 0xb2, 0xfe, 0xcf, 0x22, 0x5b, 0x82, 0x79, - 0xd5, 0x52, 0x05, 0xfd, 0x8b, 0x22, 0x5b, 0x05, 0x76, 0xb4, 0x6f, 0xb6, 0x5b, 0x5b, 0x62, 0xe0, - 0xa2, 0x84, 0xff, 0x55, 0x94, 0x16, 0x92, 0x9f, 0xe6, 0xa2, 0xcd, 0x3a, 0x76, 0x39, 0x48, 0xde, - 0xfd, 0x5d, 0xd5, 0xee, 0xec, 0x7e, 0xd5, 0xab, 0x1c, 0x9a, 0x6a, 0x95, 0x9b, 0x51, 0xad, 0x66, - 0x74, 0xf7, 0x9a, 0x2e, 0xfb, 0xbd, 0x05, 0xb5, 0x11, 0xdd, 0x03, 0x2e, 0xef, 0xfb, 0x05, 0xe9, - 0x7f, 0x43, 0x40, 0xba, 0xec, 0x77, 0xe6, 0x59, 0x8a, 0xc2, 0xec, 0xb3, 0x14, 0x69, 0xf2, 0xfd, - 0x5c, 0x9a, 0x7c, 0xff, 0x00, 0x16, 0x88, 0x35, 0x39, 0xae, 0x33, 0x52, 0x5a, 0x33, 0x49, 0x81, - 0xf3, 0xc8, 0xa2, 0x08, 0xae, 0xd4, 0x09, 0xa5, 0x72, 0x48, 0x16, 0x52, 0x94, 0xda, 0x46, 0x42, - 0xd3, 0x20, 0xce, 0x11, 0x69, 0x1a, 0x51, 0x0d, 0xf6, 0x65, 0x5c, 0x43, 0x45, 0xab, 0x81, 0xe0, - 0x58, 0xc3, 0x03, 0x58, 0xe0, 0x97, 0xa1, 0x6f, 0x5b, 0xde, 0xd8, 0xfe, 0x7c, 0x82, 0x26, 0x5c, - 0x1b, 0x75, 0xf8, 0xaa, 0x39, 0x8f, 0x09, 0x07, 0x08, 0xdf, 0xb2, 0x43, 0xfb, 0xc1, 0x17, 0x50, - 0xd1, 0xee, 0x88, 0x67, 0xab, 0xb0, 0xf8, 0x59, 0xa7, 0xb7, 0xdf, 0xee, 0x76, 0xad, 0xc3, 0xa3, - 0x8d, 0x67, 0xed, 0xe7, 0xd6, 0x4e, 0xab, 0xbb, 0xd3, 0xb8, 0x21, 0x16, 0xed, 0x7e, 0xbb, 0xdb, - 0x6b, 0x6f, 0x25, 0xe0, 0x19, 0xf6, 0x06, 0xac, 0x1d, 0xed, 0x1f, 0x75, 0xdb, 0x5b, 0x56, 0x5a, - 0xbe, 0xac, 0xa0, 0x52, 0x99, 0x9e, 0x92, 0x3d, 0xf7, 0xe0, 0x37, 0xa0, 0x9e, 0x8c, 0x6a, 0x66, - 0x00, 0x73, 0xbb, 0xed, 0xa7, 0xad, 0xcd, 0xe7, 0x74, 0x61, 0x69, 0xb7, 0xd7, 0xea, 0x75, 0x36, - 0x2d, 0x79, 0x41, 0xa9, 0xe0, 0x08, 0x19, 0x56, 0x81, 0x62, 0x6b, 0x7f, 0x73, 0xe7, 0xc0, 0xec, - 0x36, 0xb2, 0xec, 0x36, 0xac, 0x2a, 0x5a, 0xdd, 0x3c, 0xd8, 0xdb, 0xeb, 0xf4, 0x90, 0x19, 0xf6, - 0x9e, 0x1f, 0x0a, 0xd2, 0x7c, 0xf0, 0x5d, 0xa8, 0x27, 0x7d, 0xef, 0x92, 0xa7, 0xb2, 0x6b, 0xb0, - 0xb2, 0xd1, 0xee, 0x7d, 0xd6, 0x6e, 0xef, 0x63, 0xd3, 0x37, 0xdb, 0xfb, 0x3d, 0xb3, 0xb5, 0xdb, - 0xe9, 0x3d, 0x6f, 0x64, 0x1e, 0x7c, 0x0c, 0x8d, 0x69, 0x43, 0x57, 0xc2, 0x32, 0xf8, 0x32, 0x13, - 0xe2, 0x83, 0x7f, 0x91, 0x03, 0x88, 0x03, 0x40, 0x04, 0x0f, 0xdb, 0x6a, 0xf5, 0x5a, 0xbb, 0x07, - 0x62, 0x7c, 0xcc, 0x83, 0x9e, 0x60, 0x4d, 0x66, 0xfb, 0x93, 0xc6, 0x8d, 0xd4, 0x94, 0x83, 0xc3, - 0x5e, 0x23, 0x23, 0xa6, 0xa2, 0xb3, 0xdf, 0xe9, 0x75, 0x5a, 0xbb, 0x96, 0x79, 0x70, 0xd4, 0xd9, - 0x7f, 0x4a, 0x57, 0x3c, 0x22, 0xfb, 0x3e, 0x3a, 0xdc, 0x36, 0x0f, 0xf6, 0x7b, 0x56, 0x77, 0xe7, - 0xa8, 0xb7, 0x85, 0x17, 0x44, 0x6e, 0x9a, 0x9d, 0x43, 0x2a, 0x33, 0xff, 0x32, 0x04, 0x51, 0x74, - 0x41, 0x4c, 0xe6, 0xd3, 0x83, 0x6e, 0xb7, 0x73, 0x68, 0x7d, 0x72, 0xd4, 0x36, 0x3b, 0xed, 0x2e, - 0x66, 0x9c, 0x4b, 0x81, 0x0b, 0xfc, 0xa2, 0x60, 0xfa, 0xbd, 0xdd, 0x4f, 0x25, 0x57, 0x16, 0xa8, - 0xa5, 0x24, 0x48, 0x60, 0x95, 0xc5, 0x60, 0x0a, 0xb6, 0x96, 0x52, 0x32, 0x5c, 0x93, 0x26, 0xf2, - 0x55, 0x04, 0xc3, 0x9e, 0x99, 0x65, 0xcc, 0x56, 0x4d, 0x4f, 0x12, 0xb9, 0x90, 0x97, 0x47, 0x3b, - 0xdf, 0xd6, 0x96, 0x89, 0x19, 0xea, 0x33, 0x50, 0x81, 0x3b, 0x2f, 0x26, 0x4a, 0xf0, 0x3d, 0x81, - 0xd2, 0x50, 0x1f, 0x22, 0x65, 0xe1, 0xf1, 0x6f, 0xe7, 0xa0, 0x4e, 0xc1, 0x78, 0xf4, 0xf6, 0x1f, - 0xf7, 0xd9, 0x1e, 0x14, 0xe5, 0x23, 0x92, 0x6c, 0x39, 0xba, 0x7d, 0x4f, 0x7f, 0xb6, 0x72, 0x6d, - 0x65, 0x1a, 0x2c, 0xe5, 0xbc, 0xc5, 0xbf, 0xf6, 0x27, 0xff, 0xe3, 0xef, 0x67, 0x6b, 0xac, 0xf2, - 0xf0, 0xfc, 0x83, 0x87, 0xa7, 0xdc, 0x0d, 0x44, 0x19, 0xbf, 0x06, 0x10, 0x3f, 0x8d, 0xc8, 0x9a, - 0x91, 0x75, 0x6b, 0xea, 0xdd, 0xc8, 0xb5, 0x9b, 0x29, 0x29, 0xb2, 0xdc, 0x9b, 0x58, 0xee, 0xa2, - 0x51, 0x17, 0xe5, 0x3a, 0xae, 0x13, 0xd2, 0x33, 0x89, 0x1f, 0x65, 0x1e, 0xb0, 0x01, 0x54, 0xf5, - 0x47, 0x0b, 0x99, 0x12, 0xc1, 0x52, 0x9e, 0x5d, 0x5c, 0xbb, 0x95, 0x9a, 0xa6, 0x84, 0x5b, 0xac, - 0x63, 0xd9, 0x68, 0x88, 0x3a, 0x26, 0x88, 0x11, 0xd7, 0x32, 0x24, 0x71, 0x3f, 0x7e, 0x9b, 0x90, - 0xdd, 0xd6, 0x04, 0xb6, 0x99, 0x97, 0x11, 0xd7, 0xee, 0x5c, 0x93, 0x2a, 0xeb, 0xba, 0x83, 0x75, - 0xad, 0x1a, 0x4c, 0xd4, 0xd5, 0x47, 0x1c, 0xf5, 0x32, 0xe2, 0x47, 0x99, 0x07, 0x8f, 0xff, 0xfd, - 0x7b, 0x50, 0x8e, 0x9c, 0x73, 0xd9, 0x6f, 0x42, 0x2d, 0x11, 0x2d, 0xc9, 0x54, 0x37, 0xd2, 0x82, - 0x2b, 0xd7, 0x6e, 0xa7, 0x27, 0xca, 0x8a, 0xdf, 0xc0, 0x8a, 0x9b, 0x6c, 0x45, 0x54, 0x2c, 0xa3, - 0x11, 0x1f, 0x62, 0x74, 0x33, 0xdd, 0x65, 0xf8, 0x42, 0x53, 0x6b, 0xa8, 0xb2, 0xdb, 0xd3, 0xaa, - 0x46, 0xa2, 0xb6, 0x3b, 0xd7, 0xa4, 0xca, 0xea, 0x6e, 0x63, 0x75, 0x2b, 0x6c, 0x49, 0xaf, 0x4e, - 0xf9, 0x74, 0x32, 0x8e, 0xf7, 0x87, 0xea, 0x4f, 0xf7, 0xb1, 0x3b, 0xf1, 0x6d, 0x8f, 0x29, 0x4f, - 0xfa, 0x45, 0x24, 0x32, 0xfb, 0xae, 0x9f, 0xd1, 0xc4, 0xaa, 0x18, 0xc3, 0xe9, 0xd3, 0x5f, 0xee, - 0x63, 0xc7, 0x50, 0xd1, 0x5e, 0xbb, 0x61, 0x37, 0xaf, 0x7d, 0x99, 0x67, 0x6d, 0x2d, 0x2d, 0x29, - 0xad, 0x2b, 0x7a, 0xf9, 0x0f, 0x4f, 0x38, 0x67, 0xbf, 0x0a, 0xe5, 0xe8, 0x0d, 0x15, 0xb6, 0xaa, - 0xbd, 0x69, 0xa3, 0xbf, 0xf9, 0xb2, 0xd6, 0x9c, 0x4d, 0x48, 0x23, 0x3e, 0xbd, 0x74, 0x41, 0x7c, - 0x9f, 0x41, 0x45, 0x7b, 0x27, 0x25, 0xea, 0xc0, 0xec, 0x5b, 0x2c, 0x51, 0x07, 0x52, 0x9e, 0x55, - 0x31, 0x16, 0xb0, 0x8a, 0x0a, 0x2b, 0x23, 0x7d, 0x87, 0x97, 0x5e, 0xc0, 0x76, 0x61, 0x59, 0xaa, - 0x70, 0xc7, 0xfc, 0xcb, 0x4c, 0x43, 0xca, 0x6b, 0x89, 0x8f, 0x32, 0xec, 0x63, 0x28, 0xa9, 0xe7, - 0x70, 0xd8, 0x4a, 0xfa, 0xb3, 0x3e, 0x6b, 0xab, 0x33, 0x70, 0xa9, 0x6f, 0x3d, 0x07, 0x88, 0x1f, - 0x65, 0x89, 0x98, 0xc4, 0xcc, 0x23, 0x2f, 0x11, 0x05, 0xcc, 0xbe, 0xe0, 0x62, 0xac, 0x60, 0x07, - 0x1b, 0x0c, 0x99, 0x84, 0xcb, 0x2f, 0xd4, 0x25, 0xcf, 0x3f, 0x82, 0x8a, 0xf6, 0x2e, 0x4b, 0x34, - 0x7c, 0xb3, 0x6f, 0xba, 0x44, 0xc3, 0x97, 0xf2, 0x8c, 0x8b, 0xb1, 0x86, 0xa5, 0x2f, 0x19, 0xf3, - 0xa2, 0x74, 0x21, 0xc3, 0x49, 0x59, 0x4a, 0x4c, 0xd0, 0x19, 0xd4, 0x12, 0x8f, 0xaf, 0x44, 0x2b, - 0x34, 0xed, 0x69, 0x97, 0x68, 0x85, 0xa6, 0xbe, 0xd7, 0xa2, 0xe8, 0xcc, 0x58, 0x10, 0xf5, 0xd0, - 0x3d, 0x4f, 0x5a, 0x4d, 0x3f, 0x84, 0x8a, 0xf6, 0x90, 0x4a, 0xd4, 0x97, 0xd9, 0x37, 0x5b, 0xa2, - 0xbe, 0xa4, 0xbd, 0xbb, 0xb2, 0x84, 0x75, 0xd4, 0x0d, 0x24, 0x05, 0xbc, 0xa6, 0x56, 0x94, 0xfd, - 0x9b, 0x50, 0x4f, 0xbe, 0xad, 0x12, 0xad, 0xfd, 0xd4, 0x47, 0x5a, 0xa2, 0xb5, 0x7f, 0xcd, 0x83, - 0x2c, 0x92, 0xa4, 0x1f, 0x2c, 0x46, 0x95, 0x3c, 0xfc, 0x89, 0x0c, 0x33, 0xfa, 0x82, 0x7d, 0x22, - 0x18, 0x9c, 0xbc, 0x25, 0x99, 0xad, 0x6a, 0x54, 0xab, 0x5f, 0xb7, 0x1c, 0xad, 0x97, 0x99, 0x0b, - 0x95, 0x93, 0xc4, 0x8c, 0x85, 0xb3, 0xa7, 0xb0, 0x18, 0x11, 0x73, 0x74, 0xed, 0x71, 0x10, 0xf5, - 0x21, 0xf5, 0x72, 0xe5, 0xb5, 0xc6, 0x74, 0xea, 0xa3, 0x0c, 0x6d, 0x7f, 0x78, 0xd9, 0xac, 0xb6, - 0xfd, 0xe9, 0x37, 0x1f, 0x6b, 0xdb, 0x5f, 0xe2, 0x4e, 0xda, 0xe9, 0xed, 0x2f, 0x74, 0x44, 0x19, - 0x2e, 0xcc, 0x4f, 0x5f, 0x42, 0x7c, 0xe7, 0xba, 0x6b, 0x1c, 0xa8, 0xf8, 0x37, 0x5e, 0x7e, 0xcb, - 0x43, 0x92, 0x15, 0x29, 0x6e, 0xfa, 0x50, 0x7a, 0xb5, 0xb0, 0x5f, 0x87, 0xaa, 0xfe, 0x1e, 0x03, - 0xd3, 0x79, 0xc2, 0x74, 0x4d, 0xb7, 0x52, 0xd3, 0x92, 0x54, 0xc2, 0xaa, 0x7a, 0x35, 0xec, 0x53, - 0x58, 0x89, 0x86, 0x59, 0xbf, 0x87, 0x20, 0x60, 0x77, 0x53, 0x6e, 0x27, 0x48, 0x0c, 0xf6, 0xcd, - 0x6b, 0xaf, 0x2f, 0x78, 0x94, 0x11, 0xd4, 0x97, 0xbc, 0x18, 0x3e, 0xde, 0x79, 0xd2, 0xee, 0xc3, - 0x8f, 0x77, 0x9e, 0xd4, 0xdb, 0xe4, 0x15, 0xf5, 0xb1, 0xc5, 0xc4, 0x18, 0x91, 0xbf, 0x2f, 0xfb, - 0x21, 0xcc, 0x6b, 0x97, 0x2c, 0x74, 0xaf, 0xdc, 0x7e, 0xb4, 0x92, 0x66, 0xaf, 0x17, 0x5d, 0x4b, - 0x3b, 0xf4, 0x34, 0x56, 0xb1, 0xfc, 0x05, 0x23, 0x31, 0x38, 0x62, 0x15, 0x6d, 0x42, 0x45, 0xbf, - 0xc0, 0xe1, 0x25, 0xe5, 0xae, 0x6a, 0x49, 0xfa, 0x4d, 0x96, 0x8f, 0x32, 0x6c, 0x17, 0x1a, 0xd3, - 0x97, 0xab, 0x45, 0x3c, 0x25, 0xed, 0x42, 0xba, 0xb5, 0xa9, 0xc4, 0xc4, 0x95, 0x6c, 0xec, 0x90, - 0x22, 0x46, 0xa2, 0xa7, 0x05, 0x3d, 0x7f, 0x7a, 0x57, 0x4f, 0x3e, 0x39, 0x18, 0x95, 0x96, 0xf6, - 0xd8, 0xe4, 0xfd, 0xcc, 0xa3, 0x0c, 0xfb, 0xdd, 0x0c, 0x54, 0x13, 0xd7, 0x0d, 0x25, 0x7c, 0xf2, - 0xa7, 0xfa, 0xd9, 0xd4, 0xd3, 0xf4, 0x8e, 0x1a, 0x26, 0x0e, 0xe2, 0xee, 0x83, 0x1f, 0x24, 0x26, - 0xe9, 0x27, 0x09, 0x9b, 0xe1, 0xfa, 0xf4, 0xdb, 0x83, 0x5f, 0x4c, 0x23, 0xe8, 0x17, 0xd6, 0x7e, - 0xf1, 0x28, 0xc3, 0xfe, 0x55, 0x06, 0xea, 0x49, 0x67, 0x80, 0xa8, 0xbb, 0xa9, 0x6e, 0x07, 0x11, - 0x29, 0x5d, 0xe3, 0x41, 0xf0, 0x43, 0x6c, 0x65, 0xef, 0x81, 0x99, 0x68, 0xa5, 0x7c, 0xd2, 0xe0, - 0xe7, 0x6b, 0x2d, 0xfb, 0x88, 0x9e, 0xfa, 0x55, 0x3e, 0x52, 0x6c, 0xf6, 0x69, 0xd8, 0x88, 0xfc, - 0xf4, 0x87, 0x54, 0x71, 0x12, 0x7e, 0x44, 0x6f, 0xec, 0x29, 0x97, 0x1b, 0x41, 0xc5, 0xaf, 0x9b, - 0xdf, 0x78, 0x1b, 0xfb, 0xf4, 0x86, 0x71, 0x33, 0xd1, 0xa7, 0x69, 0xc1, 0xa3, 0x45, 0xad, 0x93, - 0xef, 0xa0, 0xc6, 0x3b, 0xe7, 0xcc, 0xdb, 0xa8, 0xd7, 0x37, 0x72, 0x44, 0x8d, 0x94, 0xe8, 0x89, - 0xa5, 0xf6, 0x9a, 0xc5, 0x18, 0x0f, 0xb0, 0xad, 0x6f, 0x1b, 0x77, 0xaf, 0x6d, 0xeb, 0x43, 0x34, - 0xec, 0x8b, 0x16, 0x1f, 0x02, 0xc4, 0x3e, 0x8c, 0x6c, 0xca, 0x93, 0x2e, 0x62, 0x40, 0xb3, 0x6e, - 0x8e, 0xc9, 0xf5, 0xac, 0x1c, 0xee, 0x44, 0x89, 0xbf, 0x4a, 0xec, 0x34, 0xf2, 0xf1, 0xd3, 0xa5, - 0xaf, 0xa4, 0xbb, 0x61, 0x42, 0xfa, 0x9a, 0x2e, 0x3f, 0xc1, 0x4c, 0x23, 0x87, 0xbe, 0x23, 0xa8, - 0xed, 0x7a, 0xde, 0x8b, 0xc9, 0x38, 0xf2, 0x9b, 0x4f, 0x7a, 0xdb, 0xec, 0xd8, 0xc1, 0xd9, 0xda, - 0x54, 0x2f, 0x8c, 0x7b, 0x58, 0xd4, 0x1a, 0x6b, 0x6a, 0x45, 0x3d, 0xfc, 0x49, 0xec, 0x38, 0xf9, - 0x05, 0xb3, 0x61, 0x21, 0xe2, 0xd1, 0xb1, 0x73, 0x62, 0xb2, 0x98, 0x04, 0x67, 0x9e, 0xae, 0x22, - 0xa1, 0x26, 0xa8, 0xd6, 0x3e, 0x0c, 0x54, 0x99, 0x8f, 0x32, 0xec, 0x10, 0xaa, 0x5b, 0xbc, 0x8f, - 0x17, 0x2f, 0xa0, 0xcf, 0xca, 0x62, 0xc2, 0xff, 0x81, 0x9c, 0x5d, 0xd6, 0x6a, 0x09, 0x60, 0x72, - 0xdf, 0x1a, 0xdb, 0x57, 0x3e, 0xff, 0xfc, 0xe1, 0x4f, 0xa4, 0x37, 0xcc, 0x17, 0x6a, 0xdf, 0x52, - 0xde, 0x42, 0x89, 0x7d, 0x6b, 0xca, 0xbd, 0x28, 0xb1, 0x6f, 0xcd, 0xb8, 0x17, 0x25, 0x86, 0x5a, - 0x79, 0x2b, 0xb1, 0x21, 0x2c, 0xcc, 0x78, 0x24, 0x45, 0x5b, 0xd6, 0x75, 0x7e, 0x4c, 0x6b, 0xf7, - 0xae, 0x47, 0x48, 0xd6, 0xf6, 0x20, 0x59, 0x5b, 0x17, 0x6a, 0x74, 0x1b, 0xed, 0x31, 0xa7, 0x10, - 0xcc, 0xa9, 0xfb, 0x8b, 0xf4, 0xf8, 0xce, 0xe9, 0x0d, 0x06, 0xd3, 0x92, 0x12, 0x0e, 0x06, 0xe1, - 0xb1, 0x13, 0x7c, 0x82, 0x41, 0x8b, 0x79, 0x8c, 0x88, 0x71, 0x36, 0x0e, 0x33, 0x22, 0xc6, 0x94, - 0x10, 0x49, 0xa5, 0x7e, 0xb2, 0xe5, 0xa8, 0xec, 0x87, 0xae, 0x37, 0xe0, 0x23, 0x59, 0xea, 0xaf, - 0x42, 0xe5, 0x29, 0x0f, 0x55, 0x90, 0x61, 0x24, 0xcb, 0x4f, 0x45, 0x1d, 0xae, 0xa5, 0x84, 0x86, - 0x26, 0x69, 0x93, 0x4a, 0xe6, 0x83, 0x53, 0x4e, 0x4c, 0xd0, 0x72, 0x06, 0x5f, 0xb0, 0x5f, 0xc1, - 0xc2, 0xa3, 0x90, 0xfa, 0x15, 0xad, 0x99, 0x7a, 0xe1, 0xf3, 0x53, 0xf0, 0xb4, 0x92, 0x45, 0x9b, - 0x35, 0x99, 0xd2, 0x85, 0x8a, 0x76, 0xf5, 0x46, 0x34, 0x36, 0xb3, 0x57, 0xad, 0x44, 0x63, 0x93, - 0x72, 0x53, 0x87, 0x71, 0x1f, 0xeb, 0x31, 0xd8, 0xbd, 0xb8, 0x1e, 0xba, 0x9d, 0x23, 0xae, 0xe9, - 0xe1, 0x4f, 0xec, 0x51, 0xf8, 0x05, 0xfb, 0x8c, 0xa6, 0x43, 0x0b, 0xa2, 0x8c, 0x95, 0x93, 0xe9, - 0x78, 0xcb, 0x68, 0xb0, 0xb4, 0xa4, 0xa4, 0xc2, 0x42, 0x55, 0xa1, 0xc4, 0xf8, 0x04, 0xa0, 0x1b, - 0x7a, 0xe3, 0x2d, 0x9b, 0x8f, 0x3c, 0x37, 0xe6, 0xe9, 0x71, 0x58, 0x5f, 0xcc, 0x27, 0xb5, 0xd8, - 0x3e, 0xf6, 0x99, 0xa6, 0xcd, 0x25, 0xc2, 0x7f, 0x15, 0x11, 0x5f, 0x1b, 0xf9, 0x17, 0x0d, 0x48, - 0x4a, 0xf4, 0xdf, 0xa3, 0x0c, 0x6b, 0x01, 0xc4, 0xae, 0x6f, 0x91, 0x6e, 0x36, 0xe3, 0x55, 0x17, - 0xb1, 0xd7, 0x14, 0x3f, 0xb9, 0x43, 0x28, 0xc7, 0x3e, 0x43, 0xab, 0xf1, 0x4d, 0x42, 0x09, 0x0f, - 0xa3, 0x48, 0x52, 0x98, 0xf1, 0xd7, 0x31, 0x1a, 0x38, 0x54, 0xc0, 0x4a, 0x62, 0xa8, 0x4e, 0x38, - 0x0f, 0x98, 0x03, 0x8b, 0xd4, 0xc0, 0x48, 0x2c, 0xc3, 0x70, 0xb4, 0xe8, 0xe1, 0x93, 0x59, 0xd7, - 0x99, 0x88, 0x6b, 0xa4, 0x3a, 0x80, 0x24, 0x8e, 0x98, 0x04, 0xb5, 0x52, 0x28, 0x9c, 0xd8, 0x02, - 0x46, 0xb0, 0x30, 0xe3, 0x63, 0x10, 0xb1, 0x8e, 0xeb, 0x9c, 0x46, 0x22, 0xd6, 0x71, 0xad, 0x7b, - 0x82, 0xb1, 0x8c, 0x55, 0xce, 0x1b, 0x80, 0x2a, 0xe5, 0x85, 0x13, 0xf6, 0xcf, 0x44, 0x75, 0xbf, - 0x9f, 0x81, 0xc5, 0x14, 0x2f, 0x02, 0xf6, 0xa6, 0x3a, 0x9d, 0xb8, 0xd6, 0xc3, 0x60, 0x2d, 0xd5, - 0xda, 0x6c, 0x74, 0xb1, 0x9e, 0x3d, 0xf6, 0x2c, 0xb1, 0x81, 0x92, 0xb1, 0x57, 0xae, 0xcc, 0x97, - 0x0a, 0x2f, 0xa9, 0x92, 0xcb, 0xe7, 0xb0, 0x4a, 0x0d, 0x69, 0x0d, 0x87, 0x53, 0x96, 0xf0, 0x37, - 0xb4, 0x56, 0xa4, 0x58, 0xf7, 0x13, 0x7a, 0x40, 0xd2, 0xc2, 0x7f, 0x8d, 0xd8, 0x4e, 0x4d, 0x65, - 0x13, 0x68, 0x4c, 0x5b, 0x98, 0xd9, 0xf5, 0x65, 0xad, 0xdd, 0x4d, 0xe8, 0xd9, 0x29, 0x56, 0xe9, - 0xaf, 0x61, 0x65, 0x77, 0x8d, 0xb5, 0xb4, 0x71, 0x21, 0xd5, 0x5b, 0xcc, 0xc7, 0x5f, 0x8d, 0xcc, - 0xe1, 0x53, 0xfd, 0xbc, 0x1b, 0x5d, 0xf5, 0x9e, 0x6e, 0xbc, 0x8f, 0x34, 0xfd, 0x74, 0x6b, 0xfa, - 0x3b, 0x58, 0xfd, 0x3d, 0xe3, 0x56, 0x5a, 0xf5, 0x3e, 0x65, 0x21, 0x9d, 0x7f, 0x75, 0x7a, 0x5d, - 0xab, 0x16, 0xdc, 0x4b, 0x9b, 0xef, 0x6b, 0x75, 0xae, 0xa9, 0xb1, 0xbe, 0x81, 0x32, 0x64, 0x55, - 0x37, 0x7f, 0x47, 0xcb, 0x27, 0xc5, 0xce, 0x1e, 0x2d, 0x9f, 0x34, 0x7b, 0x79, 0x52, 0x7e, 0x52, - 0x96, 0xf2, 0x8f, 0x32, 0x0f, 0x36, 0xde, 0xfd, 0xe1, 0xd7, 0x4e, 0x9d, 0xf0, 0x6c, 0x72, 0xbc, - 0xde, 0xf7, 0x46, 0x0f, 0x87, 0xea, 0x54, 0x53, 0xc6, 0x6c, 0x3f, 0x1c, 0xba, 0x83, 0x87, 0x58, - 0xec, 0xf1, 0xdc, 0xd8, 0xf7, 0x42, 0xef, 0x9b, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x21, - 0x23, 0x29, 0x55, 0x89, 0x00, 0x00, + // 11870 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x6f, 0x24, 0x49, + 0x72, 0x18, 0x3e, 0xfd, 0x62, 0x77, 0x47, 0x3f, 0xd8, 0x4c, 0xbe, 0x7a, 0x38, 0x33, 0x3b, 0xb3, + 0xb5, 0x7b, 0xbb, 0xb3, 0xb3, 0x77, 0x9c, 0xd9, 0xb9, 0x9b, 0xbd, 0xbb, 0xdd, 0x9f, 0x4e, 0xd7, + 0x24, 0x9b, 0xc3, 0xbe, 0xe1, 0x6b, 0xab, 0x9b, 0xbb, 0x9a, 0xd3, 0xa3, 0xae, 0xd8, 0x9d, 0x24, + 0x4b, 0xd3, 0x5d, 0xd5, 0x5b, 0x55, 0xcd, 0xc7, 0x1d, 0xf6, 0xf7, 0xc1, 0xb0, 0x05, 0xc1, 0xf0, + 0x03, 0x82, 0x2d, 0x03, 0x96, 0x2d, 0xd8, 0xb0, 0x60, 0x18, 0x86, 0x01, 0x41, 0xc0, 0xc9, 0x1f, + 0x0c, 0xf8, 0xbb, 0xbe, 0xf8, 0x01, 0x43, 0xf2, 0x17, 0x43, 0x10, 0x60, 0xd8, 0x96, 0x3f, 0x18, + 0x30, 0x04, 0xf8, 0x1f, 0x30, 0x32, 0x22, 0xb3, 0x2a, 0xab, 0xbb, 0x38, 0x33, 0x7b, 0xb7, 0xbe, + 0x2f, 0x64, 0x57, 0x64, 0xe4, 0x3b, 0x32, 0x32, 0x22, 0x23, 0x22, 0x13, 0xca, 0xfe, 0xb8, 0xbf, + 0x3e, 0xf6, 0xbd, 0xd0, 0x63, 0x85, 0xa1, 0xeb, 0x8f, 0xfb, 0x6b, 0xb7, 0x4f, 0x3d, 0xef, 0x74, + 0xc8, 0x1f, 0xda, 0x63, 0xe7, 0xa1, 0xed, 0xba, 0x5e, 0x68, 0x87, 0x8e, 0xe7, 0x06, 0x84, 0x64, + 0xfc, 0x08, 0xea, 0x4f, 0xb9, 0xdb, 0xe5, 0x7c, 0x60, 0xf2, 0xcf, 0x27, 0x3c, 0x08, 0xd9, 0xfb, + 0xb0, 0x60, 0xf3, 0x1f, 0x73, 0x3e, 0xb0, 0xc6, 0x76, 0x10, 0x8c, 0xcf, 0x7c, 0x3b, 0xe0, 0xcd, + 0xcc, 0xbd, 0xcc, 0xfd, 0xaa, 0xd9, 0xa0, 0x84, 0xc3, 0x08, 0xce, 0xde, 0x84, 0x6a, 0x20, 0x50, + 0xb9, 0x1b, 0xfa, 0xde, 0xf8, 0xaa, 0x99, 0x45, 0xbc, 0x8a, 0x80, 0xb5, 0x09, 0x64, 0x0c, 0x61, + 0x3e, 0xaa, 0x21, 0x18, 0x7b, 0x6e, 0xc0, 0xd9, 0x23, 0x58, 0xea, 0x3b, 0xe3, 0x33, 0xee, 0x5b, + 0x98, 0x79, 0xe4, 0xf2, 0x91, 0xe7, 0x3a, 0xfd, 0x66, 0xe6, 0x5e, 0xee, 0x7e, 0xd9, 0x64, 0x94, + 0x26, 0x72, 0xec, 0xc9, 0x14, 0xf6, 0x2e, 0xcc, 0x73, 0x97, 0xe0, 0x7c, 0x80, 0xb9, 0x64, 0x55, + 0xf5, 0x18, 0x2c, 0x32, 0x18, 0xbf, 0x9d, 0x85, 0x85, 0x8e, 0xeb, 0x84, 0x9f, 0xd9, 0xc3, 0x21, + 0x0f, 0x55, 0x9f, 0xde, 0x85, 0xf9, 0x0b, 0x04, 0x60, 0x9f, 0x2e, 0x3c, 0x7f, 0x20, 0x7b, 0x54, + 0x27, 0xf0, 0xa1, 0x84, 0x5e, 0xdb, 0xb2, 0xec, 0xb5, 0x2d, 0x4b, 0x1d, 0xae, 0xdc, 0x35, 0xc3, + 0xf5, 0x2e, 0xcc, 0xfb, 0xbc, 0xef, 0x9d, 0x73, 0xff, 0xca, 0xba, 0x70, 0xdc, 0x81, 0x77, 0xd1, + 0xcc, 0xdf, 0xcb, 0xdc, 0x2f, 0x98, 0x75, 0x05, 0xfe, 0x0c, 0xa1, 0x6c, 0x03, 0xe6, 0xfb, 0x67, + 0xb6, 0xeb, 0xf2, 0xa1, 0x75, 0x6c, 0xf7, 0x5f, 0x4c, 0xc6, 0x41, 0xb3, 0x70, 0x2f, 0x73, 0xbf, + 0xf2, 0xf8, 0xe6, 0x3a, 0xce, 0xea, 0xfa, 0xe6, 0x99, 0xed, 0x6e, 0x60, 0x4a, 0xd7, 0xb5, 0xc7, + 0xc1, 0x99, 0x17, 0x9a, 0x75, 0x99, 0x83, 0xc0, 0x81, 0xb1, 0x04, 0x4c, 0x1f, 0x09, 0x1a, 0x7b, + 0xe3, 0x5f, 0x65, 0x60, 0xf1, 0xc8, 0x1d, 0x7a, 0xfd, 0x17, 0x3f, 0xe3, 0x10, 0xa5, 0xf4, 0x21, + 0xfb, 0xba, 0x7d, 0xc8, 0x7d, 0xd9, 0x3e, 0xac, 0xc0, 0x52, 0xb2, 0xb1, 0xb2, 0x17, 0x1c, 0x96, + 0x45, 0xee, 0x53, 0xae, 0x9a, 0xa5, 0xba, 0xf1, 0x1e, 0x34, 0xfa, 0x13, 0xdf, 0xe7, 0xee, 0x4c, + 0x3f, 0xe6, 0x25, 0x3c, 0xea, 0xc8, 0x9b, 0x50, 0x75, 0xf9, 0x45, 0x8c, 0x26, 0x69, 0xd7, 0xe5, + 0x17, 0x0a, 0xc5, 0x68, 0xc2, 0xca, 0x74, 0x35, 0xb2, 0x01, 0x7f, 0x99, 0x81, 0xfc, 0x51, 0x78, + 0xe9, 0xb1, 0x27, 0x50, 0xb5, 0x07, 0x03, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x8d, 0x69, 0xa5, 0xd4, + 0x1f, 0x33, 0xd9, 0xc5, 0x16, 0x25, 0xf5, 0xae, 0xc6, 0xdc, 0xac, 0xd8, 0xf1, 0x07, 0x6b, 0x42, + 0x51, 0x7e, 0x62, 0xbd, 0x65, 0x53, 0x7d, 0xb2, 0x3b, 0x00, 0xf6, 0xc8, 0x9b, 0xb8, 0xa1, 0x15, + 0xd8, 0x21, 0x8e, 0x58, 0xce, 0x2c, 0x13, 0xa4, 0x6b, 0x87, 0xec, 0x16, 0x94, 0xc7, 0x2f, 0xac, + 0xa0, 0xef, 0x3b, 0xe3, 0x10, 0x89, 0xa7, 0x6c, 0x96, 0xc6, 0x2f, 0xba, 0xf8, 0xcd, 0xde, 0x87, + 0x92, 0x37, 0x09, 0xc7, 0x9e, 0xe3, 0x86, 0x92, 0x5e, 0xe6, 0x65, 0x43, 0x0e, 0x26, 0xe1, 0xa1, + 0x00, 0x9b, 0x11, 0x02, 0x7b, 0x1b, 0x6a, 0x7d, 0xcf, 0x3d, 0x71, 0xfc, 0x11, 0x71, 0x84, 0xe6, + 0x1c, 0xd6, 0x95, 0x04, 0x1a, 0x7f, 0x94, 0x85, 0x4a, 0xcf, 0xb7, 0xdd, 0xc0, 0xee, 0x0b, 0x00, + 0x5b, 0x85, 0x62, 0x78, 0x69, 0x9d, 0xd9, 0xc1, 0x19, 0x76, 0xb5, 0x6c, 0xce, 0x85, 0x97, 0x3b, + 0x76, 0x70, 0xc6, 0x56, 0x60, 0x8e, 0x5a, 0x89, 0x1d, 0xca, 0x99, 0xf2, 0x4b, 0x2c, 0x10, 0x77, + 0x32, 0xb2, 0x92, 0x55, 0xe5, 0x90, 0x62, 0x1a, 0xee, 0x64, 0xb4, 0xa9, 0xc3, 0x45, 0xe7, 0x8f, + 0xc5, 0x74, 0x53, 0x05, 0xd4, 0xbd, 0x32, 0x42, 0xb0, 0x8e, 0x37, 0xa1, 0x2a, 0x93, 0xb9, 0x73, + 0x7a, 0x46, 0x7d, 0x2c, 0x98, 0x15, 0x42, 0x40, 0x90, 0x28, 0x21, 0x74, 0x46, 0xdc, 0x0a, 0x42, + 0x7b, 0x34, 0x96, 0x5d, 0x2a, 0x0b, 0x48, 0x57, 0x00, 0x30, 0xd9, 0x0b, 0xed, 0xa1, 0x75, 0xc2, + 0x79, 0xd0, 0x2c, 0xca, 0x64, 0x01, 0xd9, 0xe6, 0x3c, 0x60, 0x5f, 0x83, 0xfa, 0x80, 0x07, 0xa1, + 0x25, 0x27, 0x83, 0x07, 0xcd, 0x12, 0xae, 0xfc, 0x9a, 0x80, 0xb6, 0x14, 0x90, 0xdd, 0x06, 0xf0, + 0xed, 0x0b, 0x4b, 0x0c, 0x04, 0xbf, 0x6c, 0x96, 0x69, 0x16, 0x7c, 0xfb, 0xa2, 0x77, 0xb9, 0xc3, + 0x2f, 0x05, 0xd5, 0x3c, 0xe5, 0xa1, 0x36, 0x68, 0x81, 0xa4, 0x4e, 0x63, 0x17, 0x98, 0x06, 0xde, + 0xe2, 0xa1, 0xed, 0x0c, 0x03, 0xf6, 0x21, 0x54, 0x43, 0x0d, 0x19, 0xd9, 0x60, 0x25, 0x22, 0x21, + 0x2d, 0x83, 0x99, 0xc0, 0x33, 0xce, 0xa0, 0xb4, 0xcd, 0xf9, 0xae, 0x33, 0x72, 0x42, 0xb6, 0x02, + 0x85, 0x13, 0xe7, 0x92, 0x13, 0xb1, 0xe7, 0x76, 0x6e, 0x98, 0xf4, 0xc9, 0xee, 0x02, 0xe0, 0x0f, + 0x6b, 0x14, 0x51, 0xd3, 0xce, 0x0d, 0xb3, 0x8c, 0xb0, 0xbd, 0xc0, 0x0e, 0xd9, 0x1a, 0x14, 0xc7, + 0xdc, 0xef, 0x73, 0x35, 0x6f, 0x3b, 0x37, 0x4c, 0x05, 0xd8, 0x28, 0x42, 0x61, 0x28, 0x4a, 0x37, + 0xfe, 0xa4, 0x00, 0x95, 0x2e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, + 0xcd, 0xde, 0x82, 0x0a, 0x0e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x91, 0x6d, 0x66, + 0x4c, 0x10, 0xe0, 0x2e, 0x42, 0x59, 0x03, 0x72, 0xf6, 0x48, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x42, + 0xc9, 0x1e, 0x85, 0xd4, 0xbc, 0x2a, 0x82, 0x8b, 0xf6, 0x28, 0xc4, 0xa6, 0xbd, 0x09, 0xd5, 0xb1, + 0x7d, 0x35, 0x12, 0x6b, 0x39, 0x22, 0x87, 0xaa, 0x59, 0x91, 0x30, 0x24, 0x88, 0xc7, 0xb0, 0xa8, + 0xa3, 0xa8, 0xca, 0x0b, 0x51, 0xe5, 0x0b, 0x1a, 0xb6, 0x6c, 0xc3, 0xbb, 0x30, 0xaf, 0xf2, 0xf8, + 0xd4, 0x1f, 0x24, 0x93, 0xb2, 0x59, 0x97, 0x60, 0xd5, 0xcb, 0xfb, 0xd0, 0x38, 0x71, 0x5c, 0x7b, + 0x68, 0xf5, 0x87, 0xe1, 0xb9, 0x35, 0xe0, 0xc3, 0xd0, 0x46, 0x8a, 0x29, 0x98, 0x75, 0x84, 0x6f, + 0x0e, 0xc3, 0xf3, 0x2d, 0x01, 0x65, 0x5f, 0x87, 0xf2, 0x09, 0xe7, 0x16, 0x0e, 0x56, 0xb3, 0x94, + 0x58, 0x78, 0x6a, 0x86, 0xcc, 0xd2, 0x89, 0x9a, 0xab, 0xaf, 0x43, 0xc3, 0x9b, 0x84, 0xa7, 0x9e, + 0xe3, 0x9e, 0x5a, 0x82, 0xdf, 0x59, 0xce, 0x00, 0x69, 0x28, 0xbf, 0x91, 0x7d, 0x94, 0x31, 0xeb, + 0x2a, 0x4d, 0x70, 0x9e, 0xce, 0x80, 0xbd, 0x03, 0xf3, 0x43, 0x3b, 0x08, 0xad, 0x33, 0x6f, 0x6c, + 0x8d, 0x27, 0xc7, 0x2f, 0xf8, 0x55, 0xb3, 0x86, 0x03, 0x51, 0x13, 0xe0, 0x1d, 0x6f, 0x7c, 0x88, + 0x40, 0x41, 0xd9, 0xd8, 0x4e, 0x6a, 0x04, 0xdc, 0xcb, 0xdc, 0xaf, 0x99, 0x65, 0x01, 0xa1, 0x4a, + 0x9f, 0xc3, 0x22, 0x4e, 0x4f, 0x7f, 0x12, 0x84, 0xde, 0xc8, 0x12, 0xbc, 0xda, 0x1f, 0x04, 0xcd, + 0x0a, 0xd2, 0xda, 0x7b, 0xb2, 0xb1, 0xda, 0x1c, 0xaf, 0x6f, 0xf1, 0x20, 0xdc, 0x44, 0x64, 0x93, + 0x70, 0xc5, 0x86, 0x7e, 0x65, 0x2e, 0x0c, 0xa6, 0xe1, 0xec, 0xeb, 0xc0, 0xec, 0xe1, 0xd0, 0xbb, + 0xb0, 0x02, 0x3e, 0x3c, 0xb1, 0xe4, 0x20, 0x36, 0xeb, 0xf7, 0x32, 0xf7, 0x4b, 0x66, 0x03, 0x53, + 0xba, 0x7c, 0x78, 0x72, 0x48, 0x70, 0xf6, 0x21, 0xe0, 0x62, 0xb2, 0x4e, 0xb8, 0x1d, 0x4e, 0x7c, + 0x1e, 0x34, 0xe7, 0xef, 0xe5, 0xee, 0xd7, 0x1f, 0x2f, 0x44, 0xe3, 0x85, 0xe0, 0x0d, 0x27, 0x34, + 0xab, 0x02, 0x4f, 0x7e, 0x07, 0x6b, 0x5b, 0xb0, 0x92, 0xde, 0x24, 0x41, 0x54, 0x62, 0x54, 0x04, + 0x31, 0xe6, 0x4d, 0xf1, 0x93, 0x2d, 0x41, 0xe1, 0xdc, 0x1e, 0x4e, 0xb8, 0xe4, 0xe9, 0xf4, 0xf1, + 0x51, 0xf6, 0x3b, 0x19, 0xe3, 0x8f, 0x33, 0x50, 0xa5, 0x5e, 0x4a, 0x59, 0xe4, 0x2d, 0xa8, 0x29, + 0x6a, 0xe0, 0xbe, 0xef, 0xf9, 0x92, 0xab, 0x29, 0xca, 0x6b, 0x0b, 0x98, 0xd8, 0x55, 0x14, 0xd2, + 0xd8, 0xe7, 0xce, 0xc8, 0x3e, 0x55, 0x45, 0x2b, 0x52, 0x3a, 0x94, 0x60, 0xf6, 0x41, 0x5c, 0x9e, + 0xef, 0x4d, 0x42, 0x2e, 0xf7, 0xbc, 0xaa, 0xec, 0x9e, 0x29, 0x60, 0x51, 0xe9, 0xf8, 0xf5, 0x1a, + 0x74, 0x6e, 0xfc, 0x6e, 0x06, 0x98, 0x68, 0x76, 0xcf, 0xa3, 0x02, 0x24, 0x85, 0x4e, 0xe7, 0xcc, + 0xbc, 0xf6, 0x0a, 0xc9, 0xbe, 0x6c, 0x85, 0x18, 0x50, 0xa0, 0xb6, 0xe7, 0x53, 0xda, 0x4e, 0x49, + 0x3f, 0xc8, 0x97, 0x72, 0x8d, 0xbc, 0xf1, 0x5f, 0x72, 0xb0, 0xb4, 0x49, 0x5b, 0x76, 0xab, 0xdf, + 0xe7, 0xe3, 0x68, 0xed, 0xdc, 0x85, 0x8a, 0xeb, 0x0d, 0xb8, 0xa2, 0x58, 0x6a, 0x18, 0x08, 0x90, + 0x46, 0xae, 0x67, 0xb6, 0xe3, 0x52, 0xc3, 0x69, 0x30, 0xcb, 0x08, 0xc1, 0x66, 0xbf, 0x03, 0xf3, + 0x63, 0xee, 0x0e, 0xf4, 0x25, 0x42, 0x42, 0x55, 0x4d, 0x82, 0xe5, 0xea, 0xb8, 0x0b, 0x95, 0x93, + 0x09, 0xe1, 0x09, 0xc6, 0x92, 0x47, 0x1a, 0x00, 0x09, 0x6a, 0x11, 0x7f, 0x19, 0x4f, 0x82, 0x33, + 0x4c, 0x2d, 0x60, 0x6a, 0x51, 0x7c, 0x8b, 0xa4, 0x3b, 0x00, 0x83, 0x49, 0x10, 0xca, 0x15, 0x33, + 0x87, 0x89, 0x65, 0x01, 0xa1, 0x15, 0xf3, 0x0d, 0x58, 0x1c, 0xd9, 0x97, 0x16, 0xd2, 0x8e, 0xe5, + 0xb8, 0xd6, 0xc9, 0x10, 0xf7, 0x9c, 0x22, 0xe2, 0x35, 0x46, 0xf6, 0xe5, 0xa7, 0x22, 0xa5, 0xe3, + 0x6e, 0x23, 0x5c, 0xb0, 0x15, 0x25, 0xee, 0xf8, 0x3c, 0xe0, 0xfe, 0x39, 0x47, 0x4e, 0x90, 0x8f, + 0x64, 0x1a, 0x93, 0xa0, 0xa2, 0x45, 0x23, 0xd1, 0xef, 0x70, 0xd8, 0xa7, 0x65, 0x6f, 0x16, 0x47, + 0x8e, 0xbb, 0x13, 0x0e, 0xfb, 0x62, 0x5f, 0x11, 0x7c, 0x64, 0xcc, 0x7d, 0xeb, 0xc5, 0x05, 0xae, + 0xe1, 0x3c, 0xf2, 0x8d, 0x43, 0xee, 0x3f, 0xbb, 0x10, 0x5b, 0x7f, 0x3f, 0x40, 0x46, 0x64, 0x5f, + 0x35, 0x2b, 0xb8, 0xc0, 0x4b, 0xfd, 0x40, 0xb0, 0x20, 0xfb, 0x4a, 0x2c, 0x42, 0xd1, 0x5a, 0x1b, + 0x67, 0x81, 0x0f, 0xb0, 0xf8, 0x00, 0x39, 0x6a, 0x0d, 0x1b, 0xdb, 0x92, 0x09, 0xa2, 0x9e, 0x40, + 0x50, 0xbd, 0x6a, 0xec, 0xc9, 0xd0, 0x3e, 0x0d, 0x90, 0xa5, 0xd4, 0xcc, 0xaa, 0x04, 0x6e, 0x0b, + 0x98, 0xf1, 0x19, 0x09, 0x59, 0xda, 0xdc, 0xca, 0x35, 0x23, 0xb6, 0x7a, 0x84, 0xe0, 0xbc, 0x96, + 0x4c, 0xf9, 0x95, 0x36, 0x69, 0xd9, 0x94, 0x49, 0x33, 0x7e, 0x3f, 0x03, 0x55, 0x59, 0x32, 0x0a, + 0x25, 0x6c, 0x1d, 0x98, 0x9a, 0xc5, 0xf0, 0xd2, 0x19, 0x58, 0xc7, 0x57, 0x21, 0x0f, 0x88, 0x68, + 0x76, 0x6e, 0x98, 0x0d, 0x99, 0xd6, 0xbb, 0x74, 0x06, 0x1b, 0x22, 0x85, 0x3d, 0x80, 0x46, 0x02, + 0x3f, 0x08, 0x7d, 0xa2, 0xe8, 0x9d, 0x1b, 0x66, 0x5d, 0xc3, 0xee, 0x86, 0xbe, 0x58, 0x23, 0x42, + 0xe4, 0x99, 0x84, 0x96, 0xe3, 0x0e, 0xf8, 0x25, 0x92, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x23, 0x40, + 0x1b, 0x75, 0xa8, 0xea, 0xc5, 0x19, 0xa7, 0x50, 0x52, 0xf2, 0x12, 0x0a, 0x0c, 0x53, 0x4d, 0x32, + 0xcb, 0x61, 0xd4, 0x92, 0x9b, 0x50, 0x4a, 0xb6, 0xc0, 0x2c, 0x86, 0xaf, 0x5d, 0xb1, 0xf1, 0x3d, + 0x68, 0xec, 0x0a, 0xe2, 0x71, 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x05, 0xe6, 0xb4, 0x45, 0x53, 0x36, + 0xe5, 0x97, 0xd8, 0x73, 0xcf, 0xbc, 0x20, 0x94, 0xb5, 0xe0, 0x6f, 0xe3, 0x4f, 0x32, 0xc0, 0xda, + 0x41, 0xe8, 0x8c, 0xec, 0x90, 0x6f, 0xf3, 0x88, 0x2d, 0x1c, 0x40, 0x55, 0x94, 0xd6, 0xf3, 0x5a, + 0x24, 0x90, 0x91, 0x40, 0xf1, 0xbe, 0x5c, 0xc6, 0xb3, 0x19, 0xd6, 0x75, 0x6c, 0x62, 0xf3, 0x89, + 0x02, 0xc4, 0x2a, 0x0b, 0x6d, 0xff, 0x94, 0x87, 0x28, 0xc6, 0x49, 0x79, 0x1f, 0x08, 0x24, 0x04, + 0xb8, 0xb5, 0x5f, 0x86, 0x85, 0x99, 0x32, 0x74, 0xbe, 0x5c, 0x4e, 0xe1, 0xcb, 0x39, 0x9d, 0x2f, + 0x5b, 0xb0, 0x98, 0x68, 0x97, 0xa4, 0xb4, 0x55, 0x28, 0x8a, 0x05, 0x21, 0x84, 0x83, 0x0c, 0x49, + 0x95, 0x27, 0x9c, 0x0b, 0x31, 0xf8, 0x21, 0x2c, 0x9d, 0x70, 0xee, 0xdb, 0x21, 0x26, 0xe2, 0x8a, + 0x11, 0x33, 0x24, 0x0b, 0x5e, 0x90, 0x69, 0x5d, 0x3b, 0x3c, 0xe4, 0xbe, 0x98, 0x29, 0xe3, 0xbf, + 0x65, 0x60, 0x5e, 0x70, 0xd0, 0x3d, 0xdb, 0xbd, 0x52, 0xe3, 0xb4, 0x9b, 0x3a, 0x4e, 0xf7, 0xb5, + 0xcd, 0x50, 0xc3, 0xfe, 0xb2, 0x83, 0x94, 0x9b, 0x1e, 0x24, 0x76, 0x0f, 0xaa, 0x89, 0xb6, 0x16, + 0xb0, 0xad, 0x10, 0x44, 0x8d, 0xfc, 0xf9, 0x87, 0xf1, 0x1d, 0x68, 0xc4, 0xcd, 0x96, 0x63, 0xc8, + 0x20, 0x2f, 0x48, 0x52, 0x16, 0x80, 0xbf, 0x8d, 0x7f, 0x9c, 0x21, 0xc4, 0x4d, 0xcf, 0x89, 0xa4, + 0x53, 0x81, 0x28, 0xe4, 0x5e, 0x85, 0x28, 0x7e, 0x5f, 0x2b, 0xd5, 0xff, 0xfc, 0x9d, 0x15, 0x4b, + 0x27, 0xe0, 0xee, 0xc0, 0xb2, 0x87, 0x43, 0x64, 0xbe, 0x25, 0xb3, 0x28, 0xbe, 0x5b, 0xc3, 0xa1, + 0xf1, 0x2e, 0x2c, 0x68, 0xad, 0x7b, 0x49, 0x3f, 0xf6, 0x81, 0xed, 0x3a, 0x41, 0x78, 0xe4, 0x06, + 0x63, 0x4d, 0x70, 0xbb, 0x05, 0x65, 0xc1, 0x61, 0x45, 0xcb, 0x68, 0xc9, 0x16, 0x4c, 0xc1, 0x72, + 0x45, 0xbb, 0x02, 0x4c, 0xb4, 0x2f, 0x65, 0x62, 0x56, 0x26, 0xda, 0x97, 0x98, 0x68, 0x7c, 0x07, + 0x16, 0x13, 0xe5, 0xc9, 0xaa, 0xdf, 0x84, 0xc2, 0x24, 0xbc, 0xf4, 0x94, 0x68, 0x5e, 0x91, 0x14, + 0x22, 0x14, 0x40, 0x93, 0x52, 0x8c, 0x8f, 0x61, 0x61, 0x9f, 0x5f, 0xc8, 0x45, 0xac, 0x1a, 0xf2, + 0x0e, 0xe4, 0x5f, 0xa1, 0x14, 0x62, 0xba, 0xb1, 0x0e, 0x4c, 0xcf, 0x2c, 0x6b, 0xd5, 0x74, 0xc4, + 0x4c, 0x42, 0x47, 0x34, 0xde, 0x01, 0xd6, 0x75, 0x4e, 0xdd, 0x3d, 0x1e, 0x04, 0xf6, 0x69, 0xb4, + 0xec, 0x1b, 0x90, 0x1b, 0x05, 0xa7, 0x92, 0x47, 0x89, 0x9f, 0xc6, 0x37, 0x61, 0x31, 0x81, 0x27, + 0x0b, 0xbe, 0x0d, 0xe5, 0xc0, 0x39, 0x75, 0x51, 0xb0, 0x92, 0x45, 0xc7, 0x00, 0x63, 0x1b, 0x96, + 0x3e, 0xe5, 0xbe, 0x73, 0x72, 0xf5, 0xaa, 0xe2, 0x93, 0xe5, 0x64, 0xa7, 0xcb, 0x69, 0xc3, 0xf2, + 0x54, 0x39, 0xb2, 0x7a, 0x22, 0x5f, 0x39, 0x93, 0x25, 0x93, 0x3e, 0x34, 0xbe, 0x97, 0xd5, 0xf9, + 0x9e, 0x71, 0x04, 0x6c, 0xd3, 0x73, 0x5d, 0xde, 0x0f, 0x0f, 0x39, 0xf7, 0xe3, 0x53, 0xaa, 0x98, + 0x56, 0x2b, 0x8f, 0x57, 0xe5, 0xc8, 0x4e, 0x33, 0x53, 0x49, 0xc4, 0x0c, 0xf2, 0x63, 0xee, 0x8f, + 0xb0, 0xe0, 0x92, 0x89, 0xbf, 0x8d, 0x65, 0x58, 0x4c, 0x14, 0x2b, 0xf5, 0xfa, 0x47, 0xb0, 0xbc, + 0xe5, 0x04, 0xfd, 0xd9, 0x0a, 0x57, 0xa1, 0x38, 0x9e, 0x1c, 0x5b, 0x49, 0xbe, 0xfc, 0x8c, 0x5f, + 0x09, 0x6d, 0x6f, 0x3a, 0x87, 0x2c, 0xeb, 0xaf, 0x67, 0x20, 0xbf, 0xd3, 0xdb, 0xdd, 0x64, 0x6b, + 0x50, 0x72, 0xdc, 0xbe, 0x37, 0x12, 0x82, 0x17, 0xf5, 0x39, 0xfa, 0xbe, 0x76, 0x81, 0xdd, 0x82, + 0x32, 0xca, 0x6b, 0x42, 0xb5, 0x95, 0xa2, 0x4f, 0x49, 0x00, 0x76, 0xbd, 0xfe, 0x0b, 0xa1, 0x53, + 0xf3, 0xcb, 0xb1, 0xe3, 0xa3, 0xd6, 0xac, 0x94, 0xe1, 0x3c, 0xed, 0xf5, 0x71, 0x02, 0x69, 0xc4, + 0xc6, 0xbf, 0x29, 0x41, 0x51, 0xee, 0xb6, 0xb4, 0x73, 0x87, 0xce, 0x39, 0x8f, 0x77, 0x6e, 0xf1, + 0x25, 0xe4, 0x01, 0x9f, 0x8f, 0xbc, 0x30, 0x12, 0xd8, 0x68, 0x0e, 0xaa, 0x04, 0x94, 0x22, 0x9b, + 0x26, 0x34, 0xd0, 0x11, 0x43, 0x8e, 0x90, 0xfa, 0xfa, 0x56, 0x7e, 0x0b, 0x8a, 0x6a, 0xef, 0xcf, + 0x47, 0x3a, 0xcd, 0x5c, 0x9f, 0xa4, 0xb5, 0x35, 0x28, 0xf5, 0xed, 0xb1, 0xdd, 0x77, 0xc2, 0x2b, + 0xc9, 0x10, 0xa2, 0x6f, 0x51, 0xfa, 0xd0, 0xeb, 0xdb, 0x43, 0xeb, 0xd8, 0x1e, 0xda, 0x6e, 0x9f, + 0x4b, 0xdd, 0xbd, 0x8a, 0xc0, 0x0d, 0x82, 0x09, 0xfd, 0x5c, 0xb6, 0x53, 0x61, 0x91, 0x0a, 0x2f, + 0x5b, 0xaf, 0xd0, 0x84, 0x70, 0xe9, 0x8d, 0x46, 0x8e, 0xd0, 0x32, 0x48, 0x0c, 0xcb, 0x99, 0x65, + 0x82, 0x6c, 0x73, 0xec, 0xad, 0x4c, 0xbe, 0xa0, 0xa1, 0x2b, 0x53, 0x55, 0x04, 0xfc, 0x8c, 0x0e, + 0x12, 0x66, 0x65, 0xb1, 0x9c, 0x26, 0x8b, 0xbd, 0x0f, 0x0b, 0x13, 0x37, 0xe0, 0x61, 0x38, 0xe4, + 0x83, 0xa8, 0x2d, 0x15, 0x44, 0x6a, 0x44, 0x09, 0xaa, 0x39, 0xeb, 0xb0, 0x48, 0x87, 0x0e, 0x81, + 0x1d, 0x7a, 0xc1, 0x99, 0x13, 0x58, 0x81, 0xd0, 0x90, 0x48, 0xdd, 0x5d, 0xc0, 0xa4, 0xae, 0x4c, + 0xe9, 0x92, 0x8a, 0xb4, 0x3a, 0x85, 0xef, 0xf3, 0x3e, 0x77, 0xce, 0xf9, 0x00, 0xe5, 0xb4, 0x9c, + 0xb9, 0x9c, 0xc8, 0x63, 0xca, 0x44, 0x14, 0xba, 0x27, 0x23, 0x6b, 0x32, 0x1e, 0xd8, 0x42, 0x58, + 0xa9, 0x93, 0x30, 0xec, 0x4e, 0x46, 0x47, 0x04, 0x61, 0x8f, 0x40, 0x49, 0x62, 0x52, 0x3e, 0x9c, + 0x4f, 0xf0, 0x33, 0x41, 0xac, 0x66, 0x55, 0x62, 0x90, 0xa0, 0x98, 0x90, 0x39, 0x1b, 0x53, 0x32, + 0x67, 0x13, 0x8a, 0x63, 0xdf, 0x39, 0xb7, 0x43, 0xde, 0x5c, 0x20, 0x06, 0x2e, 0x3f, 0x05, 0x67, + 0x70, 0x5c, 0x27, 0x74, 0xec, 0xd0, 0xf3, 0x9b, 0x0c, 0xd3, 0x62, 0x00, 0x7b, 0x00, 0x0b, 0x48, + 0x23, 0x41, 0x68, 0x87, 0x93, 0x40, 0x4a, 0xa0, 0x8b, 0x48, 0x4c, 0x28, 0x43, 0x77, 0x11, 0x8e, + 0x42, 0x28, 0xfb, 0x26, 0xac, 0x10, 0x59, 0x60, 0x0e, 0x29, 0x59, 0xa3, 0x40, 0xb0, 0x84, 0x43, + 0xb1, 0x88, 0xa9, 0x82, 0xbe, 0xa5, 0x7c, 0x2d, 0xa4, 0x83, 0x27, 0xb0, 0x2a, 0xc9, 0x64, 0x26, + 0xd7, 0x32, 0xe6, 0x5a, 0xa2, 0xe4, 0xa9, 0x6c, 0xeb, 0xb0, 0x20, 0x9a, 0xe4, 0xf4, 0x2d, 0x99, + 0x5b, 0xac, 0x84, 0x15, 0xd1, 0x7a, 0xd4, 0x94, 0xe6, 0x29, 0xd1, 0xc4, 0xb4, 0x67, 0xfc, 0x8a, + 0x7d, 0x0f, 0xe6, 0x89, 0x64, 0x50, 0xbd, 0x42, 0x4e, 0xbf, 0x86, 0x9c, 0x7e, 0x59, 0x9d, 0x70, + 0x46, 0xa9, 0xc8, 0xec, 0xeb, 0xfd, 0xc4, 0xb7, 0x58, 0x0e, 0x43, 0xe7, 0x84, 0x87, 0xce, 0x88, + 0x37, 0x57, 0x89, 0xc0, 0xd4, 0xb7, 0x58, 0xa9, 0x93, 0x31, 0xa6, 0x34, 0x89, 0x2f, 0xd0, 0x17, + 0xd2, 0xee, 0xd0, 0x0b, 0xb8, 0x3a, 0xa2, 0x6a, 0xde, 0x94, 0x8b, 0x50, 0x00, 0x95, 0x0c, 0x29, + 0x04, 0x71, 0x52, 0x7a, 0xa2, 0x83, 0xc4, 0x5b, 0x48, 0x0c, 0x35, 0xd2, 0x7d, 0xd4, 0x61, 0xa2, + 0xd8, 0xc5, 0xcf, 0xec, 0x0b, 0xc5, 0x41, 0x6e, 0xe3, 0xfc, 0x82, 0x00, 0x49, 0xde, 0xf1, 0xd3, + 0x0c, 0x6d, 0x88, 0x92, 0x7f, 0x04, 0x9a, 0x7a, 0x47, 0x9c, 0xc3, 0xf2, 0xdc, 0xe1, 0x95, 0x64, + 0x26, 0x40, 0xa0, 0x03, 0x77, 0x88, 0xab, 0xd9, 0x71, 0x75, 0x14, 0xe2, 0xbd, 0x55, 0x05, 0x44, + 0xa4, 0xbb, 0x50, 0x19, 0x4f, 0x8e, 0x87, 0x4e, 0x9f, 0x50, 0x72, 0x54, 0x0a, 0x81, 0x10, 0x41, + 0xe8, 0xb7, 0x44, 0x51, 0x84, 0x91, 0x47, 0x8c, 0x8a, 0x84, 0x21, 0x0a, 0xf2, 0x76, 0xee, 0x23, + 0x3b, 0xa9, 0x9a, 0xf8, 0xdb, 0xd8, 0x80, 0xa5, 0x64, 0xa3, 0xe5, 0xc6, 0xf3, 0x00, 0x4a, 0x92, + 0x57, 0xa9, 0x83, 0x8f, 0xba, 0x76, 0x14, 0x2d, 0x54, 0xb4, 0x28, 0xdd, 0xf8, 0xad, 0x39, 0x58, + 0x94, 0xd0, 0x4d, 0x31, 0xb4, 0xdd, 0xc9, 0x68, 0x64, 0xfb, 0x29, 0x4c, 0x30, 0xf3, 0x72, 0x26, + 0x98, 0x9d, 0x61, 0x82, 0x49, 0xcd, 0x97, 0x78, 0x68, 0x52, 0xf3, 0x15, 0x73, 0x49, 0xca, 0x88, + 0x7e, 0x0e, 0x5a, 0x93, 0xe0, 0x1e, 0x9d, 0xb7, 0xce, 0xb0, 0xec, 0x42, 0x0a, 0xcb, 0xd6, 0x19, + 0xee, 0xdc, 0x14, 0xc3, 0x7d, 0x13, 0x88, 0x68, 0xd4, 0xec, 0x17, 0x49, 0x3f, 0x41, 0x98, 0x3c, + 0x4c, 0x7d, 0x17, 0xe6, 0xa7, 0x79, 0x1c, 0x31, 0xd3, 0x7a, 0x0a, 0x87, 0x73, 0x46, 0x1c, 0x77, + 0x2b, 0x0d, 0xb9, 0x2c, 0x39, 0x9c, 0x33, 0xe2, 0xbb, 0x98, 0xa2, 0xf0, 0xdb, 0x00, 0x54, 0x37, + 0x2e, 0x1a, 0xc0, 0x45, 0xf3, 0x4e, 0x72, 0x2e, 0xf4, 0x51, 0x5f, 0x17, 0x1f, 0x13, 0x9f, 0xe3, + 0x2a, 0x2a, 0x63, 0x4e, 0x5c, 0x40, 0xcf, 0xa0, 0xee, 0x8d, 0xb9, 0x6b, 0xc5, 0xbc, 0xa6, 0x82, + 0x45, 0xbd, 0xfd, 0x92, 0xa2, 0x3a, 0x0a, 0xd7, 0xac, 0x89, 0xbc, 0xd1, 0x27, 0xdb, 0xa3, 0x81, + 0xe7, 0x5a, 0x69, 0xd5, 0x2f, 0x51, 0x5a, 0x1d, 0x33, 0x47, 0xdf, 0xc6, 0xdf, 0xcc, 0x40, 0x45, + 0x6b, 0x36, 0x5b, 0x86, 0x85, 0xcd, 0x83, 0x83, 0xc3, 0xb6, 0xd9, 0xea, 0x75, 0x3e, 0x6d, 0x5b, + 0x9b, 0xbb, 0x07, 0xdd, 0x76, 0xe3, 0x86, 0x00, 0xef, 0x1e, 0x6c, 0xb6, 0x76, 0xad, 0xed, 0x03, + 0x73, 0x53, 0x81, 0x33, 0x6c, 0x05, 0x98, 0xd9, 0xde, 0x3b, 0xe8, 0xb5, 0x13, 0xf0, 0x2c, 0x6b, + 0x40, 0x75, 0xc3, 0x6c, 0xb7, 0x36, 0x77, 0x24, 0x24, 0xc7, 0x96, 0xa0, 0xb1, 0x7d, 0xb4, 0xbf, + 0xd5, 0xd9, 0x7f, 0x6a, 0x6d, 0xb6, 0xf6, 0x37, 0xdb, 0xbb, 0xed, 0xad, 0x46, 0x9e, 0xd5, 0xa0, + 0xdc, 0xda, 0x68, 0xed, 0x6f, 0x1d, 0xec, 0xb7, 0xb7, 0x1a, 0x05, 0xe3, 0xbb, 0x50, 0x8e, 0x3b, + 0x5a, 0x81, 0xe2, 0xd1, 0xfe, 0xb3, 0xfd, 0x83, 0xcf, 0xf6, 0x1b, 0x37, 0x58, 0x19, 0x0a, 0x58, + 0x7f, 0x23, 0xc3, 0x00, 0xe6, 0xa8, 0xce, 0x46, 0x96, 0x95, 0x20, 0xbf, 0x71, 0xd0, 0xdb, 0x69, + 0xe4, 0x8c, 0xbf, 0xc8, 0xc0, 0x32, 0x76, 0x79, 0x30, 0xcd, 0x04, 0xee, 0x41, 0xa5, 0xef, 0x79, + 0x63, 0xa1, 0x69, 0xc5, 0x12, 0x85, 0x0e, 0x12, 0x0b, 0x9c, 0x98, 0xf7, 0x89, 0xe7, 0xf7, 0xb9, + 0xe4, 0x01, 0x80, 0xa0, 0x6d, 0x01, 0x11, 0x34, 0x28, 0x89, 0x98, 0x30, 0x88, 0x05, 0x54, 0x08, + 0x46, 0x28, 0x2b, 0x30, 0x77, 0xec, 0x73, 0xbb, 0x7f, 0x26, 0x57, 0xbf, 0xfc, 0x62, 0xef, 0xc5, + 0x67, 0x00, 0x7d, 0x41, 0x53, 0x43, 0x3e, 0xc0, 0x25, 0x50, 0x32, 0xe7, 0x25, 0x7c, 0x53, 0x82, + 0xc5, 0x6e, 0x64, 0x1f, 0xdb, 0xee, 0xc0, 0x73, 0xf9, 0x40, 0xaa, 0x1a, 0x31, 0xc0, 0x38, 0x84, + 0x95, 0xe9, 0xfe, 0x49, 0x7e, 0xf1, 0xa1, 0xc6, 0x2f, 0x48, 0xf2, 0x5f, 0xbb, 0x9e, 0x14, 0x34, + 0xde, 0xf1, 0xb7, 0xf3, 0x90, 0x17, 0x92, 0xe0, 0xb5, 0x42, 0xa3, 0x2e, 0xda, 0xe7, 0x66, 0xcc, + 0x3f, 0x78, 0xd4, 0x40, 0x22, 0x02, 0x9d, 0x67, 0x95, 0x11, 0x82, 0xa2, 0x41, 0x94, 0xec, 0xf3, + 0xfe, 0xb9, 0x3c, 0xd0, 0xa2, 0x64, 0x93, 0xf7, 0xcf, 0x51, 0xa7, 0xb2, 0x43, 0xca, 0x4b, 0xeb, + 0xbd, 0x18, 0xd8, 0x21, 0xe6, 0x94, 0x49, 0x98, 0xaf, 0x18, 0x25, 0x61, 0xae, 0x26, 0x14, 0x1d, + 0xf7, 0xd8, 0x9b, 0xb8, 0x03, 0x5c, 0xde, 0x25, 0x53, 0x7d, 0xa2, 0xb5, 0x09, 0x39, 0x91, 0xd8, + 0x88, 0x68, 0x35, 0x97, 0x04, 0xa0, 0x27, 0xb6, 0xa2, 0x0f, 0xa0, 0x1c, 0x5c, 0xb9, 0x7d, 0x7d, + 0x0d, 0x2f, 0xc9, 0xf1, 0x11, 0xbd, 0x5f, 0xef, 0x5e, 0xb9, 0x7d, 0x5c, 0xb1, 0xa5, 0x40, 0xfe, + 0x62, 0x4f, 0xa0, 0x14, 0x9d, 0xfb, 0x12, 0x07, 0xbe, 0xa9, 0xe7, 0x50, 0x87, 0xbd, 0xa4, 0x5e, + 0x47, 0xa8, 0xec, 0x21, 0xcc, 0xe1, 0xe1, 0x6c, 0xd0, 0xac, 0x62, 0x26, 0x25, 0xef, 0x8b, 0x66, + 0xa0, 0xa1, 0x87, 0x0f, 0xf0, 0xa0, 0xd6, 0x94, 0x68, 0x6b, 0xcf, 0xa0, 0x96, 0x28, 0x4b, 0x57, + 0xa2, 0x6b, 0xa4, 0x44, 0xbf, 0xad, 0x2b, 0xd1, 0xf1, 0x4e, 0x20, 0xb3, 0xe9, 0x4a, 0xf5, 0x2f, + 0x43, 0x49, 0x75, 0x45, 0xac, 0x3f, 0xb9, 0x76, 0xac, 0xee, 0xf3, 0xfd, 0xcd, 0xc6, 0x0d, 0x36, + 0x0f, 0x95, 0xd6, 0x26, 0x2e, 0x69, 0x04, 0x64, 0x04, 0xca, 0x61, 0xab, 0xdb, 0x8d, 0x20, 0x59, + 0x63, 0x1b, 0x1a, 0xd3, 0x2d, 0x15, 0x34, 0x19, 0x2a, 0x98, 0x3c, 0xba, 0x8e, 0x01, 0x42, 0x45, + 0xa2, 0xd3, 0x68, 0x92, 0xc3, 0xe9, 0xc3, 0x78, 0x02, 0x0d, 0xb1, 0xaf, 0x89, 0xa1, 0x0a, 0xb4, + 0x23, 0xe0, 0xa1, 0x90, 0xed, 0xf4, 0xe3, 0xeb, 0x92, 0x59, 0x21, 0x18, 0x56, 0x65, 0x7c, 0x08, + 0x0b, 0x5a, 0xb6, 0x58, 0xa5, 0x15, 0x7b, 0xe5, 0xb4, 0x4a, 0x8b, 0x0a, 0x0c, 0xa5, 0x18, 0xab, + 0xb0, 0x2c, 0x3e, 0xdb, 0xe7, 0xdc, 0x0d, 0xbb, 0x93, 0x63, 0xb2, 0x39, 0x3a, 0x9e, 0x2b, 0x14, + 0x9b, 0x72, 0x94, 0x72, 0x3d, 0x91, 0xaf, 0x4b, 0xed, 0x37, 0x8b, 0xa4, 0xb1, 0xa6, 0xd5, 0x80, + 0x19, 0xd7, 0xf1, 0x6f, 0x42, 0x0b, 0x2e, 0x47, 0x20, 0x31, 0xac, 0x87, 0xed, 0xb6, 0x69, 0x1d, + 0xec, 0xef, 0x76, 0xf6, 0x05, 0xa3, 0x14, 0xc3, 0x8a, 0x80, 0xed, 0x6d, 0x84, 0x64, 0x8c, 0x06, + 0xd4, 0x9f, 0xf2, 0xb0, 0xe3, 0x9e, 0x78, 0xca, 0xbe, 0xf6, 0x97, 0x05, 0x98, 0x8f, 0x40, 0xb1, + 0x16, 0x7d, 0xce, 0xfd, 0xc0, 0xf1, 0x5c, 0x14, 0x88, 0xcb, 0xa6, 0xfa, 0x14, 0xbb, 0x9b, 0x33, + 0xe0, 0x6e, 0xe8, 0x84, 0x57, 0x56, 0xe2, 0xc8, 0xad, 0xae, 0xc0, 0x72, 0x17, 0x5d, 0x82, 0x82, + 0x3d, 0x74, 0x6c, 0x65, 0xaa, 0xa5, 0x0f, 0x01, 0xed, 0x7b, 0x43, 0xcf, 0x47, 0xd9, 0xb7, 0x6c, + 0xd2, 0x07, 0x7b, 0x04, 0x4b, 0x42, 0x06, 0xd7, 0xcf, 0x41, 0x91, 0x7f, 0xd0, 0xe9, 0x1f, 0x73, + 0x27, 0xa3, 0xc3, 0xf8, 0x2c, 0x54, 0xa4, 0x88, 0xbd, 0x53, 0xe4, 0x90, 0xc2, 0x52, 0x94, 0x81, + 0xd4, 0xb9, 0x05, 0x77, 0x32, 0x6a, 0x61, 0x4a, 0x84, 0xff, 0x18, 0x96, 0x05, 0x7e, 0x24, 0x5e, + 0x45, 0x39, 0xe6, 0x31, 0x87, 0x28, 0xac, 0x23, 0xd3, 0xa2, 0x3c, 0xb7, 0xa0, 0x4c, 0xad, 0x12, + 0x33, 0x5e, 0x20, 0x31, 0x1e, 0x9b, 0xc2, 0xfd, 0x60, 0xc6, 0xaa, 0x3a, 0x47, 0x82, 0xc0, 0x94, + 0x55, 0x55, 0xb3, 0xcb, 0x96, 0xa6, 0xed, 0xb2, 0x8f, 0x61, 0xf9, 0x58, 0x90, 0xe0, 0x19, 0xb7, + 0x07, 0xdc, 0xb7, 0x62, 0xc2, 0x26, 0x75, 0x65, 0x51, 0x24, 0xee, 0x60, 0x5a, 0xb4, 0x0e, 0x84, + 0x9c, 0x23, 0xd8, 0x02, 0x1f, 0x58, 0xa1, 0x67, 0xa1, 0xf8, 0x83, 0x0c, 0xa6, 0x64, 0xd6, 0x08, + 0xdc, 0xf3, 0x36, 0x05, 0x30, 0x89, 0x77, 0xea, 0xdb, 0xe3, 0x33, 0xa9, 0x50, 0x44, 0x78, 0x4f, + 0x05, 0x90, 0xdd, 0x86, 0xa2, 0x20, 0x79, 0x97, 0x93, 0xf1, 0x8b, 0x44, 0x76, 0x05, 0x62, 0x6f, + 0xc3, 0x1c, 0xd6, 0x11, 0x34, 0x1b, 0x48, 0xef, 0xd5, 0x98, 0x91, 0x3b, 0xae, 0x29, 0xd3, 0x84, + 0x30, 0x39, 0xf1, 0x1d, 0xe2, 0x32, 0x65, 0x13, 0x7f, 0xb3, 0xef, 0x6b, 0x2c, 0x6b, 0x11, 0xf3, + 0x2a, 0x79, 0x60, 0x8a, 0xd2, 0xae, 0xe3, 0x5e, 0x5f, 0x29, 0x33, 0xfa, 0x41, 0xbe, 0x54, 0x69, + 0x54, 0x8d, 0x6f, 0x43, 0x81, 0x46, 0x47, 0x10, 0x21, 0x8e, 0x5d, 0x46, 0x12, 0x21, 0x42, 0x9b, + 0x50, 0x74, 0x79, 0x78, 0xe1, 0xf9, 0x2f, 0xd4, 0xa1, 0xb4, 0xfc, 0x34, 0x7e, 0x8c, 0xa7, 0x29, + 0x91, 0xc5, 0x9d, 0x14, 0x43, 0x41, 0x1e, 0x34, 0xbd, 0xc1, 0x99, 0x2d, 0x0f, 0x78, 0x4a, 0x08, + 0xe8, 0x9e, 0xd9, 0x33, 0xe4, 0x91, 0x9d, 0x35, 0xba, 0xbf, 0x0d, 0x75, 0x65, 0xe3, 0x0f, 0xac, + 0x21, 0x3f, 0x09, 0x25, 0xb9, 0x57, 0xa5, 0x81, 0x3f, 0xd8, 0xe5, 0x27, 0xa1, 0xb1, 0x07, 0x0b, + 0x92, 0x20, 0x0f, 0xc6, 0x5c, 0x55, 0xfd, 0x9d, 0x34, 0x79, 0xba, 0xf2, 0x78, 0x31, 0xb9, 0xd1, + 0x92, 0xef, 0x42, 0x42, 0xc8, 0x36, 0x3e, 0x01, 0xa6, 0x6f, 0xc3, 0xb2, 0x3c, 0x29, 0xd5, 0xaa, + 0xb3, 0x7c, 0x65, 0x12, 0x8b, 0x64, 0x67, 0x67, 0x20, 0x46, 0x27, 0x98, 0xf4, 0xfb, 0xca, 0xf7, + 0xa2, 0x64, 0xaa, 0x4f, 0xe3, 0x4f, 0x33, 0xb0, 0x88, 0x85, 0x29, 0x7d, 0x40, 0x32, 0xd9, 0x9f, + 0xb9, 0x91, 0x62, 0x7e, 0x74, 0xd9, 0x87, 0x3e, 0xbe, 0xfc, 0xe9, 0x69, 0x7e, 0xe6, 0xf4, 0xf4, + 0x3d, 0x68, 0x0c, 0xf8, 0xd0, 0x41, 0x37, 0x1c, 0x25, 0x4a, 0x90, 0x06, 0x30, 0xaf, 0xe0, 0x52, + 0x1b, 0x34, 0xfe, 0x41, 0x06, 0x16, 0x48, 0x52, 0x41, 0xbd, 0x5a, 0x0e, 0xd4, 0xc7, 0x4a, 0x91, + 0x94, 0xac, 0x4a, 0xf6, 0x29, 0xde, 0xc1, 0x11, 0x4a, 0xc8, 0x3b, 0x37, 0xa4, 0x82, 0x29, 0xa1, + 0xec, 0x23, 0xd4, 0x61, 0x5c, 0x0b, 0x81, 0x29, 0x6e, 0x3d, 0xc9, 0x49, 0xd9, 0xb9, 0x81, 0x0a, + 0x8e, 0x8b, 0xa0, 0x8d, 0x92, 0xd0, 0x6c, 0x05, 0xd8, 0xd8, 0x86, 0x5a, 0xa2, 0x9a, 0xc4, 0x11, + 0x6f, 0x95, 0x8e, 0x78, 0x67, 0xcc, 0x28, 0xd9, 0x59, 0x33, 0xca, 0x15, 0x2c, 0x9a, 0xdc, 0x1e, + 0x5c, 0x6d, 0x7b, 0xfe, 0x61, 0x70, 0x1c, 0x6e, 0x93, 0xf8, 0x27, 0xf8, 0x7b, 0x64, 0x1b, 0x4c, + 0x9c, 0xa3, 0x2a, 0x13, 0x91, 0x52, 0x97, 0xbf, 0x06, 0xf5, 0xd8, 0x88, 0xa8, 0x9d, 0xc5, 0xd5, + 0x22, 0x3b, 0x22, 0x1e, 0xc9, 0x09, 0x55, 0x33, 0x38, 0x0e, 0xe5, 0x69, 0x1c, 0xfe, 0x36, 0xfe, + 0x46, 0x1e, 0x98, 0xa0, 0xe6, 0x29, 0x82, 0x99, 0x32, 0x7f, 0x66, 0x67, 0xcc, 0x9f, 0x8f, 0x80, + 0x69, 0x08, 0xca, 0x2a, 0x9b, 0x8b, 0xac, 0xb2, 0x8d, 0x18, 0x57, 0x1a, 0x65, 0x1f, 0xc1, 0x92, + 0x94, 0xa5, 0x93, 0x4d, 0x25, 0xd2, 0x60, 0x24, 0x54, 0x27, 0xda, 0xab, 0x4c, 0x9f, 0x42, 0xfd, + 0xa7, 0xd3, 0x36, 0x34, 0x7d, 0x2a, 0xc5, 0x5f, 0x23, 0xc0, 0xb9, 0x57, 0x12, 0x60, 0x71, 0x86, + 0x00, 0xb5, 0xc3, 0x9f, 0x52, 0xf2, 0xf0, 0xc7, 0x80, 0x9a, 0x32, 0x70, 0x92, 0x5f, 0x07, 0x09, + 0x8e, 0x15, 0x69, 0xe5, 0x44, 0xdf, 0x8e, 0xfb, 0xd0, 0x50, 0x27, 0x34, 0xd1, 0xf1, 0x12, 0xf9, + 0x2c, 0xc8, 0x03, 0xbe, 0x4d, 0x75, 0xc8, 0x94, 0x38, 0xcc, 0xaf, 0x4c, 0x1d, 0xe6, 0xbf, 0x0f, + 0x0b, 0x81, 0xa0, 0x5f, 0x6b, 0xe2, 0x4a, 0x07, 0x23, 0x3e, 0x40, 0xad, 0xad, 0x64, 0x36, 0x30, + 0xe1, 0x28, 0x86, 0xcf, 0x1e, 0x9d, 0xd4, 0x52, 0x8e, 0x4e, 0x9e, 0xc4, 0xb6, 0xc0, 0xe0, 0xcc, + 0x19, 0xa1, 0xcc, 0x10, 0x3b, 0xe3, 0xc8, 0x01, 0xee, 0x9e, 0x39, 0x23, 0x53, 0x19, 0x9e, 0xc5, + 0x87, 0xf1, 0x7f, 0x32, 0xd0, 0x10, 0x74, 0x90, 0x58, 0x62, 0xdf, 0x05, 0x64, 0x06, 0xaf, 0xb9, + 0xc2, 0x2a, 0x02, 0x57, 0x2d, 0xb0, 0x6f, 0x03, 0xae, 0x18, 0x4b, 0xa8, 0xa8, 0x72, 0x7d, 0x35, + 0x93, 0xeb, 0x2b, 0xe6, 0xa1, 0x3b, 0x37, 0x48, 0xf7, 0x10, 0x10, 0xf6, 0x5d, 0x28, 0x0b, 0xc2, + 0x44, 0x2a, 0x91, 0x3e, 0x60, 0x4a, 0xf2, 0x4a, 0x59, 0x23, 0x22, 0xeb, 0x58, 0x7e, 0xa6, 0x99, + 0x6f, 0xf3, 0x29, 0xe6, 0x5b, 0x6d, 0x01, 0xef, 0x00, 0x3c, 0xe3, 0x57, 0xbb, 0x5e, 0x1f, 0xf5, + 0xca, 0x3b, 0x00, 0x82, 0x96, 0x4f, 0xec, 0x91, 0x23, 0xcf, 0x84, 0x0a, 0x66, 0xf9, 0x05, 0xbf, + 0xda, 0x46, 0x80, 0x98, 0x48, 0x91, 0x1c, 0xaf, 0xe2, 0x82, 0x59, 0x7a, 0xc1, 0xaf, 0x68, 0x09, + 0x5b, 0x50, 0x7b, 0xc6, 0xaf, 0xb6, 0x38, 0x09, 0x99, 0x9e, 0x2f, 0x88, 0xc8, 0xb7, 0x2f, 0x84, + 0x54, 0x99, 0x30, 0xbd, 0x56, 0x7c, 0xfb, 0xe2, 0x19, 0xbf, 0x52, 0x66, 0xe0, 0xa2, 0x48, 0x1f, + 0x7a, 0x7d, 0xb9, 0x6f, 0x2a, 0x27, 0x92, 0xb8, 0x51, 0xe6, 0xdc, 0x0b, 0xfc, 0x6d, 0xfc, 0x55, + 0x06, 0x6a, 0xa2, 0xfd, 0xc8, 0x96, 0xc5, 0x94, 0x29, 0x5f, 0xa4, 0x4c, 0xec, 0x8b, 0xf4, 0x58, + 0x72, 0x35, 0xe2, 0xf1, 0xd9, 0xeb, 0x79, 0x3c, 0xce, 0x0d, 0x31, 0xf8, 0x0f, 0xa0, 0x4c, 0xcb, + 0x52, 0xac, 0xf3, 0x5c, 0x62, 0x82, 0x13, 0x1d, 0x32, 0x4b, 0x88, 0xf6, 0x8c, 0x5c, 0x1f, 0xb4, + 0xf3, 0x45, 0x1a, 0xe2, 0xb2, 0x1f, 0x9d, 0x2a, 0xa6, 0x4c, 0x43, 0xe1, 0x1a, 0xd7, 0x07, 0xfd, + 0xf0, 0x6e, 0x6e, 0xe6, 0xf0, 0xee, 0x00, 0x4a, 0x62, 0xaa, 0xb1, 0xb3, 0x29, 0x85, 0x66, 0xd2, + 0x0a, 0x15, 0x92, 0x80, 0x2d, 0x36, 0x05, 0xc1, 0xe8, 0xb2, 0x52, 0x12, 0xb0, 0x03, 0x7e, 0x88, + 0xcc, 0x2e, 0x03, 0x15, 0x6d, 0x05, 0xe0, 0xf9, 0x67, 0x34, 0x5e, 0xb4, 0x5c, 0x92, 0x24, 0x9e, + 0x18, 0xf0, 0x9d, 0x1b, 0x66, 0xad, 0x9f, 0x98, 0x81, 0x75, 0x49, 0xab, 0x98, 0x33, 0x9b, 0x70, + 0x9b, 0x52, 0x0d, 0x57, 0x04, 0x2a, 0x7e, 0x6f, 0xcc, 0x41, 0x5e, 0xa0, 0x1a, 0x1f, 0xc3, 0x82, + 0xd6, 0x0c, 0x52, 0xf3, 0x5f, 0xb7, 0x87, 0xc6, 0xaf, 0x45, 0x99, 0x45, 0x1d, 0x64, 0xa1, 0x52, + 0x6e, 0x24, 0x7c, 0x40, 0x1d, 0x97, 0xee, 0x2a, 0x04, 0x12, 0x68, 0xaf, 0xed, 0xda, 0xf0, 0x1b, + 0xb0, 0xa8, 0x95, 0xbe, 0xed, 0xb8, 0xf6, 0xd0, 0xf9, 0x31, 0x6e, 0xf8, 0x81, 0x73, 0xea, 0x4e, + 0x95, 0x4f, 0xa0, 0x2f, 0x55, 0xfe, 0x3f, 0xcc, 0xc2, 0x92, 0xac, 0x00, 0x1d, 0x03, 0x1d, 0x21, + 0xc5, 0xed, 0x05, 0xa7, 0xec, 0xbb, 0x50, 0x13, 0x63, 0x63, 0xf9, 0xfc, 0xd4, 0x09, 0x42, 0xae, + 0x2c, 0x63, 0x29, 0x8c, 0x4b, 0x6c, 0xe6, 0x02, 0xd5, 0x94, 0x98, 0xec, 0x63, 0xa8, 0x60, 0x56, + 0x3a, 0x46, 0x91, 0x13, 0xd1, 0x9c, 0xcd, 0x48, 0x03, 0xbd, 0x73, 0xc3, 0x84, 0x20, 0x1e, 0xf6, + 0x8f, 0xa1, 0x82, 0x73, 0x78, 0x8e, 0x03, 0x39, 0xc5, 0xaa, 0x66, 0x06, 0x5a, 0x64, 0x1e, 0xc7, + 0xc3, 0xde, 0x82, 0x1a, 0x31, 0x2b, 0x39, 0x4e, 0xd2, 0xe1, 0x68, 0x6d, 0x36, 0xbb, 0x1a, 0x49, + 0xd1, 0xf8, 0xb1, 0xf6, 0xbd, 0x51, 0x86, 0x62, 0xe8, 0x3b, 0xa7, 0xa7, 0xdc, 0x37, 0x56, 0xa2, + 0xa1, 0x11, 0x5c, 0x98, 0x77, 0x43, 0x3e, 0x16, 0xb2, 0xb9, 0xf1, 0xef, 0x32, 0x50, 0x91, 0x7c, + 0xf5, 0x67, 0x36, 0xc7, 0xad, 0x69, 0x9e, 0xb5, 0x74, 0x62, 0x13, 0x3b, 0xd2, 0xbe, 0x0b, 0xf3, + 0x23, 0x21, 0xa7, 0x0b, 0x3d, 0x32, 0x61, 0x8b, 0xab, 0x2b, 0xb0, 0x14, 0x93, 0xd7, 0x61, 0x11, + 0xa5, 0xe6, 0xc0, 0x0a, 0x9d, 0xa1, 0xa5, 0x12, 0xa5, 0x17, 0xeb, 0x02, 0x25, 0xf5, 0x9c, 0xe1, + 0x9e, 0x4c, 0x10, 0xc2, 0x63, 0x10, 0xda, 0xa7, 0x5c, 0xae, 0x6d, 0xfa, 0x30, 0x9a, 0xb0, 0x32, + 0xa5, 0x42, 0x2a, 0xf5, 0xf7, 0x7f, 0x2d, 0xc0, 0xea, 0x4c, 0x92, 0x54, 0x83, 0x23, 0x1b, 0xd4, + 0xd0, 0x19, 0x1d, 0x7b, 0xd1, 0x09, 0x6d, 0x46, 0xb3, 0x41, 0xed, 0x8a, 0x14, 0x75, 0x42, 0xcb, + 0x61, 0x59, 0x11, 0x24, 0x1e, 0xb1, 0x46, 0x5a, 0x66, 0x16, 0x75, 0xa0, 0x0f, 0x92, 0x9b, 0xd8, + 0x74, 0x75, 0x0a, 0xae, 0x8b, 0x46, 0x8b, 0xe3, 0x19, 0x58, 0xc0, 0x7e, 0x13, 0x9a, 0x11, 0xdd, + 0x4b, 0xb1, 0x5d, 0x53, 0x99, 0x45, 0x4d, 0x5f, 0x7f, 0x45, 0x4d, 0x89, 0xb3, 0x3b, 0x94, 0x9d, + 0x56, 0xd4, 0x92, 0xa1, 0x02, 0xa3, 0xba, 0xce, 0xe1, 0x0d, 0x55, 0x17, 0x8a, 0xe1, 0xb3, 0x35, + 0xe6, 0x5f, 0xab, 0x6f, 0x78, 0x2e, 0x99, 0xa8, 0xd6, 0xbc, 0x25, 0x0b, 0x8e, 0x92, 0xf4, 0x7a, + 0xcf, 0x60, 0xe5, 0xc2, 0x76, 0x42, 0xd5, 0x47, 0x4d, 0x63, 0x2f, 0x60, 0x7d, 0x8f, 0x5f, 0x51, + 0xdf, 0x67, 0x94, 0x39, 0xa1, 0x98, 0x2c, 0x5d, 0xcc, 0x02, 0x83, 0xb5, 0xbf, 0x9b, 0x83, 0x7a, + 0xb2, 0x14, 0xc1, 0x58, 0xe4, 0x66, 0xa3, 0xe4, 0x4d, 0x29, 0x04, 0x4b, 0xeb, 0xc1, 0x3e, 0xc9, + 0x99, 0xb3, 0x76, 0x8d, 0x6c, 0x8a, 0x5d, 0x43, 0x37, 0x27, 0xe4, 0x5e, 0x65, 0xbf, 0xcd, 0xbf, + 0x96, 0xfd, 0xb6, 0x90, 0x66, 0xbf, 0xbd, 0xde, 0xe8, 0x37, 0xf7, 0x33, 0x19, 0xfd, 0x8a, 0x2f, + 0x31, 0xfa, 0x25, 0x4c, 0x95, 0xa5, 0x69, 0x53, 0x65, 0x8a, 0x89, 0xaf, 0xfc, 0x25, 0x4c, 0x7c, + 0x6b, 0x7f, 0x95, 0x01, 0x36, 0xbb, 0x16, 0xd8, 0x53, 0x32, 0x10, 0xb9, 0x7c, 0x28, 0xf9, 0xf4, + 0x37, 0x5e, 0x6f, 0x3d, 0xa9, 0xe9, 0x57, 0xb9, 0xd9, 0x43, 0x58, 0xd4, 0x3d, 0xeb, 0x75, 0x1d, + 0xbd, 0x66, 0x32, 0x3d, 0x29, 0x3e, 0xc9, 0xd1, 0x4c, 0xe3, 0xf9, 0x57, 0x9a, 0xc6, 0x0b, 0xaf, + 0x34, 0x8d, 0xcf, 0x25, 0x4d, 0xe3, 0x6b, 0xff, 0x29, 0x03, 0x8b, 0x29, 0x24, 0xfb, 0xd5, 0xf5, + 0x59, 0x50, 0x5a, 0x82, 0x89, 0x65, 0x25, 0xa5, 0xe9, 0xfc, 0x6b, 0x17, 0x2a, 0xf1, 0x54, 0xa8, + 0xc8, 0x93, 0x07, 0xaf, 0xe2, 0x25, 0x71, 0x0e, 0x53, 0xcf, 0xbe, 0xf6, 0x07, 0x59, 0xa8, 0x68, + 0x89, 0x62, 0x14, 0x89, 0x40, 0x35, 0x8f, 0x24, 0x92, 0x03, 0xf1, 0x84, 0xe1, 0x2e, 0x48, 0x13, + 0x06, 0xa5, 0xd3, 0x52, 0x92, 0x42, 0x1f, 0x22, 0xac, 0xc3, 0xa2, 0x32, 0xde, 0xf1, 0xd8, 0xf1, + 0x50, 0xee, 0x2c, 0x0b, 0xd2, 0x84, 0xc7, 0x23, 0x3f, 0x46, 0xf6, 0x50, 0x29, 0x7f, 0xf1, 0xdc, + 0x21, 0x61, 0x93, 0x7d, 0x60, 0x81, 0x96, 0x83, 0x9a, 0x44, 0x41, 0xd5, 0x1f, 0xc0, 0xb2, 0x5a, + 0x0c, 0xc9, 0x1c, 0x64, 0x32, 0x60, 0x72, 0x29, 0xe8, 0x59, 0xbe, 0x0f, 0x77, 0xa6, 0xda, 0x34, + 0x95, 0x95, 0x3c, 0x64, 0x6f, 0x26, 0x5a, 0xa7, 0x97, 0xb0, 0xf6, 0x13, 0xa8, 0x25, 0xd8, 0xe2, + 0x57, 0x37, 0xe5, 0xd3, 0xa7, 0x3a, 0x34, 0xa2, 0xfa, 0xa9, 0xce, 0xda, 0xff, 0xce, 0x01, 0x9b, + 0xe5, 0xcc, 0xbf, 0xc8, 0x26, 0xcc, 0x12, 0x66, 0x2e, 0x85, 0x30, 0xff, 0x9f, 0x49, 0x0b, 0xef, + 0xc3, 0x82, 0x8c, 0xc0, 0xd2, 0x2c, 0xb0, 0xb4, 0x38, 0x1b, 0x51, 0x82, 0x6a, 0xc5, 0xb7, 0xa7, + 0x3d, 0x41, 0x4a, 0x89, 0xa0, 0x13, 0x4d, 0x5c, 0x9a, 0x72, 0x08, 0x39, 0x82, 0x39, 0xdb, 0xed, + 0x9f, 0x79, 0xbe, 0xe4, 0x83, 0xbf, 0xf4, 0xa5, 0x37, 0xcb, 0xf5, 0x16, 0xe6, 0x47, 0x19, 0xcd, + 0x94, 0x85, 0x19, 0x1f, 0x40, 0x45, 0x03, 0xa3, 0x55, 0xb2, 0xb3, 0xb7, 0x71, 0xd0, 0xb8, 0xc1, + 0x6a, 0x50, 0x36, 0xdb, 0x9b, 0x07, 0x9f, 0xb6, 0xcd, 0xf6, 0x56, 0x23, 0xc3, 0x4a, 0x90, 0xdf, + 0x3d, 0xe8, 0xf6, 0x1a, 0x59, 0x63, 0x0d, 0x9a, 0xb2, 0xc4, 0x59, 0x0b, 0xc5, 0xef, 0xe6, 0xa3, + 0xc3, 0x41, 0x4c, 0x94, 0x0a, 0xf9, 0x37, 0xa1, 0xaa, 0x0b, 0x33, 0x92, 0x22, 0xa6, 0x9c, 0x00, + 0x84, 0x2a, 0xee, 0x69, 0xbc, 0x7a, 0x13, 0xc8, 0xb4, 0x3b, 0x88, 0xb2, 0x65, 0x13, 0x52, 0x6a, + 0x8a, 0x2d, 0x10, 0x55, 0x9d, 0x04, 0x19, 0xfe, 0x7f, 0x50, 0x4f, 0x1e, 0xd7, 0x4b, 0x8e, 0x94, + 0xa6, 0x5e, 0x8a, 0xdc, 0x89, 0xf3, 0x7b, 0xf6, 0x7d, 0x68, 0x4c, 0x1f, 0xf7, 0x4b, 0x51, 0xf9, + 0x9a, 0xfc, 0xf3, 0x4e, 0xd2, 0x02, 0xc0, 0x76, 0x60, 0x29, 0x4d, 0x9c, 0x43, 0xfa, 0xb8, 0xfe, + 0x48, 0x82, 0xcd, 0x8a, 0x6c, 0xec, 0x3b, 0xd2, 0xaa, 0x53, 0x48, 0xb3, 0x8d, 0x6b, 0x83, 0xbd, + 0x4e, 0xff, 0x34, 0xfb, 0xce, 0x39, 0x40, 0x0c, 0x63, 0x0d, 0xa8, 0x1e, 0x1c, 0xb6, 0xf7, 0xad, + 0xcd, 0x9d, 0xd6, 0xfe, 0x7e, 0x7b, 0xb7, 0x71, 0x83, 0x31, 0xa8, 0xa3, 0x51, 0x7b, 0x2b, 0x82, + 0x65, 0x04, 0x4c, 0x5a, 0xd7, 0x14, 0x2c, 0xcb, 0x96, 0xa0, 0xd1, 0xd9, 0x9f, 0x82, 0xe6, 0x58, + 0x13, 0x96, 0x0e, 0xdb, 0x64, 0x07, 0x4f, 0x94, 0x9b, 0x17, 0x2a, 0x82, 0xec, 0xae, 0x50, 0x11, + 0x28, 0x92, 0x50, 0xae, 0x03, 0x25, 0x39, 0xff, 0x5e, 0x06, 0x96, 0xa7, 0x12, 0xe2, 0xf8, 0x10, + 0x92, 0x9b, 0x93, 0x12, 0x73, 0x15, 0x81, 0x6a, 0x35, 0xbd, 0x0f, 0x0b, 0xd1, 0x31, 0xd3, 0xd4, + 0xae, 0xd4, 0x88, 0x12, 0x14, 0xf2, 0x43, 0x58, 0xd4, 0x4e, 0xab, 0xa6, 0x78, 0x05, 0xd3, 0x92, + 0x64, 0x06, 0x63, 0x35, 0xf2, 0xc3, 0x9f, 0x6a, 0xf5, 0x80, 0xc2, 0x13, 0xf5, 0x84, 0xd8, 0xe8, + 0x95, 0x6c, 0xaf, 0xfa, 0x64, 0x8f, 0xa6, 0x08, 0x21, 0xd9, 0x5a, 0x7d, 0xc2, 0x55, 0xf5, 0x7f, + 0x38, 0x07, 0xec, 0x93, 0x09, 0xf7, 0xaf, 0x30, 0xfe, 0x23, 0x78, 0x95, 0x43, 0xa4, 0x3a, 0x57, + 0xc9, 0xbe, 0x56, 0x8c, 0x57, 0x5a, 0x8c, 0x55, 0xfe, 0xd5, 0x31, 0x56, 0x85, 0x57, 0xc5, 0x58, + 0xbd, 0x05, 0x35, 0xe7, 0xd4, 0xf5, 0x04, 0x2b, 0x14, 0x72, 0x6f, 0xd0, 0x9c, 0xbb, 0x97, 0xbb, + 0x5f, 0x35, 0xab, 0x12, 0x28, 0xa4, 0xde, 0x80, 0x7d, 0x1c, 0x23, 0xf1, 0xc1, 0x29, 0xc6, 0x03, + 0xea, 0x4c, 0xb0, 0x3d, 0x38, 0xe5, 0xf2, 0x18, 0x09, 0xf5, 0x0a, 0x95, 0x59, 0xc0, 0x03, 0xf6, + 0x36, 0xd4, 0x03, 0x6f, 0x22, 0xd4, 0x08, 0x35, 0x0c, 0x64, 0x16, 0xab, 0x12, 0xf4, 0x50, 0xd9, + 0x40, 0x17, 0x27, 0x01, 0xb7, 0x46, 0x4e, 0x10, 0x08, 0xf1, 0xac, 0xef, 0xb9, 0xa1, 0xef, 0x0d, + 0xa5, 0xa5, 0x6b, 0x61, 0x12, 0xf0, 0x3d, 0x4a, 0xd9, 0xa4, 0x04, 0xf6, 0xad, 0xb8, 0x49, 0x63, + 0xdb, 0xf1, 0x83, 0x26, 0x60, 0x93, 0x54, 0x4f, 0x51, 0x5a, 0xb7, 0x1d, 0x3f, 0x6a, 0x8b, 0xf8, + 0x08, 0xa6, 0x62, 0xbf, 0x2a, 0xd3, 0xb1, 0x5f, 0x3f, 0x4a, 0x8f, 0xfd, 0xaa, 0x61, 0xd1, 0x8f, + 0x64, 0xd1, 0xb3, 0x53, 0xfc, 0xa5, 0x42, 0xc0, 0x66, 0x43, 0xda, 0xea, 0x5f, 0x26, 0xa4, 0x6d, + 0x3e, 0x2d, 0xa4, 0xed, 0x03, 0xa8, 0x60, 0xb0, 0x91, 0x75, 0xe6, 0x08, 0x19, 0x8e, 0x2c, 0x77, + 0x0d, 0x3d, 0x1a, 0x69, 0xc7, 0x71, 0x43, 0x13, 0x7c, 0xf5, 0x33, 0x98, 0x8d, 0x2e, 0x5b, 0xf8, + 0x05, 0x46, 0x97, 0xc9, 0xa0, 0xa8, 0x75, 0x28, 0xa9, 0x79, 0x62, 0x0c, 0xf2, 0x27, 0xbe, 0x37, + 0x52, 0x16, 0x0d, 0xf1, 0x9b, 0xd5, 0x21, 0x1b, 0x7a, 0x32, 0x73, 0x36, 0xf4, 0x8c, 0x5f, 0x87, + 0x8a, 0x46, 0x6a, 0xec, 0x4d, 0x3a, 0x85, 0x14, 0x9a, 0x98, 0x94, 0x2d, 0x69, 0x14, 0xcb, 0x12, + 0xda, 0x19, 0x08, 0x7e, 0x33, 0x70, 0x7c, 0x8e, 0x71, 0xa0, 0x96, 0xcf, 0xcf, 0xb9, 0x1f, 0x28, + 0x0b, 0x53, 0x23, 0x4a, 0x30, 0x09, 0x6e, 0xfc, 0x06, 0x2c, 0x26, 0xe6, 0x56, 0xb2, 0x88, 0xb7, + 0x61, 0x0e, 0xc7, 0x4d, 0x79, 0x00, 0x24, 0xa3, 0xbc, 0x64, 0x1a, 0x06, 0xf8, 0x93, 0x71, 0xcc, + 0x1a, 0xfb, 0xde, 0x31, 0x56, 0x92, 0x31, 0x2b, 0x12, 0x76, 0xe8, 0x7b, 0xc7, 0xc6, 0x9f, 0xe7, + 0x20, 0xb7, 0xe3, 0x8d, 0x75, 0xa7, 0xb7, 0xcc, 0x8c, 0xd3, 0x9b, 0x54, 0x2f, 0xad, 0x48, 0x7d, + 0x94, 0x32, 0x3b, 0x9a, 0x85, 0x94, 0x0a, 0x79, 0x1f, 0xea, 0x82, 0x4f, 0x84, 0x9e, 0xd0, 0xcf, + 0x2f, 0x6c, 0x9f, 0x04, 0xe2, 0x1c, 0x2d, 0x3e, 0x7b, 0x14, 0xf6, 0xbc, 0x6d, 0x82, 0xb3, 0x25, + 0xc8, 0x45, 0xea, 0x0b, 0x26, 0x8b, 0x4f, 0xb6, 0x02, 0x73, 0xe8, 0xfd, 0x7c, 0x25, 0x4d, 0xdc, + 0xf2, 0x8b, 0x7d, 0x03, 0x16, 0x93, 0xe5, 0x12, 0x2b, 0x92, 0xb2, 0x91, 0x5e, 0x30, 0xf2, 0xa4, + 0x9b, 0x20, 0xf8, 0x08, 0xe1, 0x48, 0x4f, 0x99, 0x13, 0xce, 0x31, 0x49, 0x63, 0x7a, 0xa5, 0x04, + 0xd3, 0xbb, 0x0b, 0x95, 0x70, 0x78, 0x6e, 0x8d, 0xed, 0xab, 0xa1, 0x67, 0x0f, 0xe4, 0xfa, 0x86, + 0x70, 0x78, 0x7e, 0x48, 0x10, 0xf6, 0x10, 0x60, 0x34, 0x1e, 0xcb, 0xb5, 0x87, 0xa6, 0x8e, 0x98, + 0x94, 0xf7, 0x0e, 0x0f, 0x89, 0xe4, 0xcc, 0xf2, 0x68, 0x3c, 0xa6, 0x9f, 0x6c, 0x0b, 0xea, 0xa9, + 0xb1, 0x9a, 0x77, 0x94, 0xb3, 0xae, 0x37, 0x5e, 0x4f, 0x59, 0x9c, 0xb5, 0xbe, 0x0e, 0x5b, 0xfb, + 0x3e, 0xb0, 0x9f, 0x33, 0x62, 0xb2, 0x07, 0xe5, 0xa8, 0x7d, 0x7a, 0xc0, 0x21, 0xba, 0xdf, 0x57, + 0x12, 0x01, 0x87, 0xad, 0xc1, 0xc0, 0x17, 0x7c, 0x91, 0x36, 0xcc, 0x88, 0xe5, 0x83, 0xb6, 0x63, + 0xb6, 0x88, 0xef, 0x1b, 0xff, 0x35, 0x03, 0x05, 0x8a, 0x7e, 0x7c, 0x07, 0xe6, 0x09, 0x3f, 0x72, + 0x20, 0x94, 0x86, 0x71, 0xda, 0x77, 0x7b, 0xd2, 0x77, 0x50, 0x2c, 0x0b, 0x2d, 0x72, 0x3b, 0x1b, + 0xcd, 0xbc, 0x16, 0xbd, 0x7d, 0x17, 0xca, 0x51, 0xd5, 0x1a, 0xe9, 0x94, 0x54, 0xcd, 0xec, 0x0d, + 0xc8, 0x9f, 0x79, 0x63, 0x75, 0xce, 0x03, 0xf1, 0x48, 0x9a, 0x08, 0x8f, 0xdb, 0x22, 0xea, 0xa0, + 0xc6, 0xcb, 0xf3, 0x89, 0xa8, 0x12, 0x24, 0x83, 0xd9, 0x3e, 0xce, 0xa5, 0xf4, 0xf1, 0x08, 0xe6, + 0x05, 0x1f, 0xd0, 0x1c, 0x54, 0xae, 0xdf, 0x34, 0xdf, 0x13, 0x12, 0x5e, 0x7f, 0x38, 0x19, 0x70, + 0xfd, 0xa4, 0x0d, 0xbd, 0xd9, 0x24, 0x5c, 0x49, 0xd6, 0xc6, 0x1f, 0x66, 0x88, 0xbf, 0x88, 0x72, + 0xd9, 0x7d, 0xc8, 0x8b, 0xfd, 0x6d, 0xea, 0xdc, 0x3d, 0x8a, 0x83, 0x10, 0x78, 0x26, 0x62, 0xe0, + 0x75, 0x07, 0x93, 0x51, 0xb2, 0xf4, 0x9a, 0x59, 0x71, 0x27, 0xa3, 0xe8, 0xa0, 0xea, 0x6b, 0xaa, + 0x5b, 0x53, 0x87, 0x3c, 0xd4, 0xfb, 0x68, 0x99, 0xae, 0x6b, 0x6e, 0x71, 0xf9, 0xc4, 0x8e, 0xa9, + 0xa4, 0xc0, 0xc1, 0x29, 0xd7, 0xdc, 0xe1, 0xfe, 0x38, 0x0b, 0xb5, 0x44, 0x8b, 0xd0, 0x2f, 0x50, + 0x6c, 0x00, 0x64, 0x46, 0x92, 0xf3, 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9c, 0xb2, 0x89, 0x71, + 0x8a, 0x5c, 0x71, 0x72, 0xba, 0x2b, 0xce, 0x23, 0x28, 0xc7, 0x11, 0xfb, 0xc9, 0x26, 0x89, 0xfa, + 0x54, 0x34, 0x48, 0x8c, 0x14, 0x3b, 0xef, 0x14, 0x74, 0xe7, 0x9d, 0xef, 0x69, 0xbe, 0x1e, 0x73, + 0x58, 0x8c, 0x91, 0x36, 0xa2, 0xbf, 0x10, 0x4f, 0x0f, 0xe3, 0x63, 0xa8, 0x68, 0x8d, 0xd7, 0x7d, + 0x3a, 0x32, 0x09, 0x9f, 0x8e, 0x28, 0x6e, 0x2b, 0x1b, 0xc7, 0x6d, 0x19, 0xbf, 0x95, 0x85, 0x9a, + 0x58, 0x5f, 0x8e, 0x7b, 0x7a, 0xe8, 0x0d, 0x9d, 0x3e, 0x9a, 0x95, 0xa2, 0x15, 0x26, 0x05, 0x2d, + 0xb5, 0xce, 0xe4, 0x12, 0x23, 0x39, 0x4b, 0x0f, 0x4f, 0x25, 0x26, 0x1d, 0x85, 0xa7, 0x1a, 0x50, + 0x13, 0x8c, 0x11, 0x0d, 0x44, 0xf1, 0x7d, 0x02, 0x66, 0xe5, 0x84, 0xf3, 0x0d, 0x3b, 0x20, 0x0e, + 0xf9, 0x0d, 0x58, 0x14, 0x38, 0x18, 0x99, 0x37, 0x72, 0x86, 0x43, 0x87, 0x30, 0xe9, 0xa0, 0xa9, + 0x71, 0xc2, 0xb9, 0x69, 0x87, 0x7c, 0x4f, 0x24, 0xc8, 0xeb, 0x07, 0x4a, 0x03, 0x27, 0xb0, 0x8f, + 0x63, 0xef, 0xcd, 0xe8, 0x1b, 0xed, 0xc8, 0xf6, 0xa5, 0x66, 0x47, 0xa6, 0x03, 0x88, 0xca, 0xc8, + 0xbe, 0x8c, 0xec, 0xc8, 0x53, 0x94, 0x54, 0x9c, 0xa6, 0x24, 0xe3, 0xdf, 0x66, 0xa1, 0xa2, 0x91, + 0xe5, 0xeb, 0xec, 0xae, 0x77, 0x66, 0xcc, 0x80, 0x65, 0xdd, 0xe2, 0xf7, 0x56, 0xb2, 0x4a, 0xf4, + 0x74, 0xa1, 0x8b, 0x0e, 0x34, 0x02, 0xbe, 0x05, 0x65, 0xb1, 0xea, 0x3e, 0xc0, 0x03, 0x57, 0x79, + 0x4d, 0x07, 0x02, 0x0e, 0x27, 0xc7, 0x2a, 0xf1, 0x31, 0x26, 0x16, 0xe2, 0xc4, 0xc7, 0x22, 0xf1, + 0x65, 0x2e, 0xdb, 0xdf, 0x86, 0xaa, 0x2c, 0x15, 0xe7, 0x14, 0xbb, 0x1b, 0xaf, 0xfa, 0xc4, 0x7c, + 0x9b, 0x15, 0xaa, 0x8e, 0x26, 0x5f, 0x66, 0x7c, 0xac, 0x32, 0x96, 0x5e, 0x95, 0xf1, 0x31, 0x7d, + 0x18, 0xdb, 0x91, 0x17, 0x3c, 0x7a, 0x59, 0x29, 0x3e, 0xf6, 0x10, 0x16, 0x15, 0xbb, 0x9a, 0xb8, + 0xb6, 0xeb, 0x7a, 0x13, 0xb7, 0xcf, 0x55, 0x40, 0x17, 0x93, 0x49, 0x47, 0x71, 0x8a, 0x31, 0x88, + 0x22, 0x7e, 0xc9, 0x5b, 0xeb, 0x01, 0x14, 0x48, 0x2e, 0x27, 0xe1, 0x23, 0x9d, 0x71, 0x11, 0x0a, + 0xbb, 0x0f, 0x05, 0x12, 0xcf, 0xb3, 0xd7, 0x32, 0x1b, 0x42, 0x30, 0x5a, 0xc0, 0x44, 0xc6, 0x3d, + 0x1e, 0xfa, 0x4e, 0x3f, 0x88, 0x63, 0xc5, 0x0a, 0x42, 0xff, 0xa4, 0xba, 0xe2, 0x93, 0xdb, 0x18, + 0x13, 0x75, 0x54, 0xc2, 0x11, 0x1b, 0xd3, 0x62, 0xa2, 0x0c, 0x29, 0x2e, 0x0d, 0x61, 0xe5, 0x98, + 0x87, 0x17, 0x9c, 0xbb, 0xae, 0x10, 0x86, 0xfa, 0xdc, 0x0d, 0x7d, 0x7b, 0x28, 0x26, 0x89, 0x7a, + 0xf0, 0x64, 0xa6, 0xd4, 0xf8, 0x0c, 0x64, 0x23, 0xce, 0xb8, 0x19, 0xe5, 0x23, 0xde, 0xb1, 0x7c, + 0x9c, 0x96, 0xb6, 0xf6, 0x6b, 0xb0, 0x76, 0x7d, 0xa6, 0x94, 0x88, 0xd0, 0xfb, 0x49, 0xae, 0x12, + 0x59, 0xfd, 0x86, 0x9e, 0x1d, 0x52, 0x6b, 0x74, 0xce, 0xb2, 0x0f, 0x15, 0x2d, 0x25, 0xde, 0xfb, + 0x33, 0x28, 0xdc, 0xd1, 0x87, 0xd8, 0x91, 0x5c, 0xcf, 0x1f, 0xa1, 0x95, 0x6d, 0x60, 0xc5, 0xa5, + 0x67, 0xcc, 0xf9, 0x18, 0x8e, 0x21, 0xf0, 0xc6, 0x3a, 0xcc, 0xa3, 0x64, 0xaf, 0x6d, 0x74, 0x2f, + 0x13, 0x06, 0x8d, 0x25, 0x60, 0xfb, 0xc4, 0xbb, 0x74, 0xe7, 0xcd, 0xff, 0x9c, 0x83, 0x8a, 0x06, + 0x16, 0xbb, 0x11, 0xba, 0xfb, 0x59, 0x03, 0xc7, 0x1e, 0x71, 0x65, 0xd2, 0xac, 0x99, 0x35, 0x84, + 0x6e, 0x49, 0xa0, 0xd8, 0x8b, 0xed, 0xf3, 0x53, 0xcb, 0x9b, 0x84, 0xd6, 0x80, 0x9f, 0xfa, 0x5c, + 0xb5, 0xb2, 0x6a, 0x9f, 0x9f, 0x1e, 0x4c, 0xc2, 0x2d, 0x84, 0x09, 0x2c, 0xc1, 0x4b, 0x34, 0x2c, + 0xe9, 0xa1, 0x36, 0xb2, 0x2f, 0x63, 0x2c, 0xe9, 0x26, 0x49, 0x94, 0x99, 0x8f, 0xdc, 0x24, 0x49, + 0x5b, 0x9c, 0xde, 0x40, 0x0b, 0xb3, 0x1b, 0xe8, 0xb7, 0x60, 0x85, 0x36, 0x50, 0xc9, 0x9a, 0xad, + 0xa9, 0x95, 0xbc, 0x84, 0xa9, 0xb2, 0x93, 0x9a, 0xd8, 0xdb, 0x10, 0x3d, 0x50, 0x6c, 0x29, 0x70, + 0x7e, 0x4c, 0x8c, 0x2c, 0x63, 0x8a, 0x9e, 0xc9, 0xc2, 0xbb, 0xce, 0x8f, 0xb9, 0xc0, 0x44, 0x5f, + 0x18, 0x1d, 0x53, 0x06, 0x64, 0x8c, 0x1c, 0x77, 0x1a, 0xd3, 0xbe, 0x4c, 0x62, 0x96, 0x25, 0xa6, + 0x7d, 0xa9, 0x63, 0x3e, 0x81, 0xd5, 0x11, 0x1f, 0x38, 0x76, 0xb2, 0x58, 0x2b, 0x16, 0xdc, 0x96, + 0x28, 0x59, 0xcb, 0xd3, 0x25, 0xc5, 0x5d, 0x8c, 0xc6, 0x8f, 0xbd, 0xd1, 0xb1, 0x43, 0x32, 0x0b, + 0x79, 0xe7, 0xe4, 0xcd, 0xba, 0x3b, 0x19, 0xfd, 0x10, 0xc1, 0x22, 0x4b, 0x60, 0xd4, 0xa0, 0xd2, + 0x0d, 0xbd, 0xb1, 0x9a, 0xe6, 0x3a, 0x54, 0xe9, 0x53, 0x46, 0x49, 0xde, 0x82, 0x9b, 0xc8, 0x12, + 0x7a, 0xde, 0xd8, 0x1b, 0x7a, 0xa7, 0x57, 0x89, 0x73, 0xbc, 0x7f, 0x9f, 0x81, 0xc5, 0x44, 0xaa, + 0x64, 0xaf, 0xdf, 0x22, 0x7e, 0x16, 0x85, 0xba, 0xd1, 0x1a, 0x5c, 0xd0, 0xd6, 0x20, 0x21, 0x12, + 0x33, 0x53, 0xe1, 0x6f, 0xad, 0xf8, 0x8a, 0x06, 0x95, 0x91, 0x58, 0x4a, 0x73, 0x96, 0xa5, 0xc8, + 0xfc, 0xea, 0xf2, 0x06, 0x55, 0xc4, 0x2f, 0xc9, 0xa0, 0x99, 0x81, 0xec, 0x72, 0x2e, 0x19, 0x16, + 0xa0, 0x9f, 0xf9, 0xa9, 0x16, 0xc4, 0x07, 0x81, 0x81, 0xf1, 0xcf, 0x32, 0x00, 0x71, 0xeb, 0x30, + 0x30, 0x21, 0x92, 0x5b, 0xe8, 0xf6, 0x33, 0x4d, 0x46, 0x79, 0x13, 0xaa, 0x91, 0x7f, 0x72, 0x2c, + 0x09, 0x55, 0x14, 0x4c, 0x88, 0x43, 0xef, 0xc2, 0xfc, 0xe9, 0xd0, 0x3b, 0x46, 0x89, 0x55, 0xca, + 0x2d, 0xe4, 0x9d, 0x56, 0x27, 0xb0, 0x92, 0x46, 0x62, 0xb9, 0x29, 0x9f, 0xea, 0xc2, 0xac, 0x4b, + 0x41, 0xc6, 0xef, 0x64, 0x23, 0x47, 0xcd, 0x78, 0x24, 0x5e, 0xae, 0xde, 0xfd, 0x2c, 0x9e, 0x33, + 0x2f, 0x33, 0x26, 0x7e, 0x0c, 0x75, 0x9f, 0x36, 0x25, 0xb5, 0x63, 0xe5, 0x5f, 0xb2, 0x63, 0xd5, + 0xfc, 0x84, 0xa4, 0xf3, 0x1e, 0x34, 0xec, 0xc1, 0x39, 0xf7, 0x43, 0x07, 0x4f, 0xeb, 0x51, 0x3e, + 0x96, 0xae, 0x91, 0x1a, 0x1c, 0x05, 0xd1, 0x77, 0x61, 0x5e, 0x46, 0xee, 0x46, 0x98, 0xf2, 0x2e, + 0xa0, 0x18, 0x2c, 0x10, 0x8d, 0x7f, 0xa1, 0x3c, 0x43, 0x93, 0xb3, 0xfb, 0xf2, 0x51, 0xd1, 0x7b, + 0x98, 0x9d, 0x35, 0x97, 0x4a, 0x42, 0x92, 0x46, 0x00, 0xc9, 0x8f, 0x08, 0x28, 0x4d, 0x00, 0xc9, + 0x61, 0xcd, 0xbf, 0xce, 0xb0, 0x1a, 0xff, 0x31, 0x03, 0xc5, 0x1d, 0x6f, 0xbc, 0xe3, 0x90, 0x6b, + 0x3e, 0x2e, 0x93, 0xc8, 0x46, 0x35, 0x27, 0x3e, 0xd1, 0xcd, 0xe7, 0x25, 0x01, 0x6a, 0xa9, 0x62, + 0x5e, 0x2d, 0x29, 0xe6, 0x7d, 0x0f, 0x6e, 0xa1, 0x09, 0xd0, 0xf7, 0xc6, 0x9e, 0x2f, 0x96, 0xaa, + 0x3d, 0x24, 0x71, 0xcf, 0x73, 0xc3, 0x33, 0xc5, 0x3b, 0x6f, 0x9e, 0x70, 0x7e, 0xa8, 0x61, 0xec, + 0x45, 0x08, 0x18, 0x02, 0x3a, 0x0c, 0xcf, 0x2d, 0xd2, 0xd0, 0xa5, 0x3c, 0x4a, 0x1c, 0x75, 0x5e, + 0x24, 0xb4, 0x11, 0x8e, 0x12, 0xa9, 0xf1, 0x1d, 0x28, 0x47, 0x87, 0x3d, 0xec, 0x7d, 0x28, 0x9f, + 0x79, 0x63, 0x79, 0x22, 0x94, 0x49, 0x04, 0xf1, 0xc9, 0x5e, 0x9b, 0xa5, 0x33, 0xfa, 0x11, 0x18, + 0x7f, 0x5e, 0x84, 0x62, 0xc7, 0x3d, 0xf7, 0x9c, 0x3e, 0xfa, 0x96, 0x8e, 0xf8, 0xc8, 0x53, 0xd7, + 0x07, 0x88, 0xdf, 0xe8, 0x89, 0x15, 0xdf, 0xe8, 0x93, 0x93, 0x9e, 0x58, 0xd1, 0x5d, 0x3e, 0xcb, + 0x30, 0xe7, 0xeb, 0x57, 0xf2, 0x14, 0x7c, 0xf4, 0x76, 0x8f, 0xf6, 0xcb, 0x82, 0x76, 0xfd, 0x82, + 0x28, 0x8b, 0xae, 0x8a, 0xc1, 0x21, 0xa3, 0x70, 0xce, 0x32, 0x42, 0x70, 0xc0, 0x6e, 0x43, 0x51, + 0xc6, 0xcc, 0x51, 0x04, 0x12, 0xb9, 0xa7, 0x4b, 0x10, 0x52, 0x83, 0xcf, 0xc9, 0x84, 0x1b, 0x09, + 0xb2, 0x39, 0xb3, 0xaa, 0x80, 0x5b, 0x82, 0xd6, 0xee, 0x42, 0x85, 0xf0, 0x09, 0xa5, 0x24, 0x5d, + 0x32, 0x11, 0x84, 0x08, 0x29, 0x37, 0x5b, 0x95, 0x53, 0x6f, 0xb6, 0x42, 0xe7, 0xe1, 0x88, 0xcb, + 0x52, 0x17, 0x81, 0xee, 0x33, 0xd2, 0xe0, 0xea, 0x5a, 0x37, 0x79, 0xa6, 0x42, 0xd1, 0xcd, 0xea, + 0x4c, 0xe5, 0x2d, 0xa8, 0x9d, 0xd8, 0xc3, 0xe1, 0xb1, 0xdd, 0x7f, 0x41, 0x47, 0x01, 0x55, 0x3a, + 0xfd, 0x54, 0x40, 0x3c, 0x0b, 0xb8, 0x0b, 0x15, 0x6d, 0x96, 0xd1, 0xdf, 0x32, 0x6f, 0x42, 0x3c, + 0xbf, 0xd3, 0x27, 0x7c, 0xf5, 0xd7, 0x38, 0xe1, 0xd3, 0xfc, 0x4e, 0xe7, 0x93, 0x7e, 0xa7, 0xb7, + 0x90, 0x9b, 0x4a, 0x07, 0xc3, 0x06, 0x5d, 0x9e, 0x63, 0x0f, 0x06, 0xe8, 0x60, 0x48, 0x37, 0x55, + 0xe2, 0xe0, 0x51, 0xfa, 0x02, 0xe9, 0x12, 0x04, 0x23, 0x94, 0x3b, 0x74, 0x4c, 0x3d, 0xb6, 0x9d, + 0x01, 0x86, 0x18, 0xd0, 0xe9, 0x41, 0xd1, 0x1e, 0x85, 0x87, 0xb6, 0x33, 0x60, 0xf7, 0xa0, 0xaa, + 0x92, 0x71, 0x77, 0x5c, 0xa4, 0xf1, 0x97, 0xc9, 0x62, 0x4f, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe2, + 0x10, 0xe5, 0x8a, 0x44, 0x41, 0x3a, 0xf8, 0x00, 0x7d, 0x7a, 0x42, 0x8e, 0x81, 0xc8, 0xf5, 0xc7, + 0xb7, 0x64, 0x5f, 0x25, 0x95, 0xaa, 0xff, 0x64, 0x1c, 0x23, 0x4c, 0x21, 0xdc, 0x91, 0x8d, 0x6e, + 0x25, 0x21, 0xff, 0x4a, 0x54, 0xb4, 0xd1, 0x11, 0x02, 0xfb, 0x8e, 0xa6, 0xbf, 0x36, 0x11, 0xf9, + 0xf6, 0x54, 0xf9, 0xd7, 0x45, 0x58, 0xdd, 0x01, 0x70, 0x02, 0xb1, 0xcb, 0x04, 0xdc, 0x1d, 0x60, + 0x4c, 0x71, 0xc9, 0x2c, 0x3b, 0xc1, 0x33, 0x02, 0x7c, 0xb5, 0x8a, 0x6d, 0x0b, 0xaa, 0x7a, 0x37, + 0x59, 0x09, 0xf2, 0x07, 0x87, 0xed, 0xfd, 0xc6, 0x0d, 0x56, 0x81, 0x62, 0xb7, 0xdd, 0xeb, 0xed, + 0xa2, 0xa5, 0xaf, 0x0a, 0xa5, 0x28, 0xa0, 0x31, 0x2b, 0xbe, 0x5a, 0x9b, 0x9b, 0xed, 0xc3, 0x5e, + 0x7b, 0xab, 0x91, 0xfb, 0x41, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0xbf, 0xc8, 0x41, 0x45, 0x1b, 0x85, + 0x97, 0x33, 0xe3, 0x3b, 0x00, 0xa8, 0x49, 0xc6, 0xfe, 0xa7, 0x79, 0xb3, 0x2c, 0x20, 0x34, 0xf9, + 0xba, 0x8d, 0x22, 0x47, 0xb7, 0x32, 0x29, 0x1b, 0xc5, 0x5b, 0x50, 0xa3, 0x0b, 0x8e, 0x74, 0x7b, + 0x6d, 0xc1, 0xac, 0x12, 0x50, 0xb2, 0x6a, 0x8c, 0x88, 0x46, 0x24, 0x8c, 0x95, 0x93, 0xd7, 0x9d, + 0x10, 0x08, 0xa3, 0xe5, 0x30, 0xd4, 0x31, 0xf0, 0x86, 0xe7, 0x9c, 0x30, 0x48, 0x22, 0xac, 0x48, + 0x58, 0x4f, 0xc6, 0x76, 0x4b, 0x7e, 0xa8, 0x85, 0xe4, 0x16, 0xcc, 0x2a, 0x01, 0x65, 0x45, 0xdf, + 0x50, 0x04, 0x54, 0x42, 0x02, 0x5a, 0x9d, 0xa5, 0x86, 0x04, 0xf1, 0xec, 0xce, 0x1c, 0x23, 0x96, + 0x91, 0x30, 0xbe, 0x36, 0x9b, 0xef, 0xd5, 0xc7, 0x89, 0xec, 0x7d, 0x60, 0xa3, 0xf1, 0xd8, 0x4a, + 0x39, 0xe0, 0xcb, 0x9b, 0xf3, 0xa3, 0xf1, 0xb8, 0xa7, 0x9d, 0x7f, 0x7d, 0x05, 0x67, 0x8f, 0x9f, + 0x03, 0x6b, 0x89, 0x05, 0x8c, 0x4d, 0x8c, 0x54, 0xb1, 0x98, 0x2d, 0x67, 0x74, 0xb6, 0x9c, 0xc2, + 0xfd, 0xb2, 0xa9, 0xdc, 0xef, 0x65, 0x7c, 0xc2, 0xd8, 0x86, 0xca, 0xa1, 0x76, 0x7d, 0xda, 0x3d, + 0xb1, 0x43, 0xa8, 0x8b, 0xd3, 0x68, 0xef, 0xa0, 0x33, 0x45, 0x5f, 0xde, 0x97, 0xa6, 0xb5, 0x26, + 0xab, 0xb5, 0xc6, 0xf8, 0xa7, 0x19, 0xba, 0x9a, 0x26, 0x6a, 0x7c, 0x7c, 0x63, 0x9b, 0x32, 0xbf, + 0xc5, 0x91, 0xf3, 0x15, 0x65, 0x76, 0x93, 0x41, 0xef, 0xd8, 0x34, 0xcb, 0x3b, 0x39, 0x09, 0xb8, + 0xf2, 0xf1, 0xa8, 0x20, 0xec, 0x00, 0x41, 0x4a, 0xf8, 0x16, 0x12, 0xbe, 0x43, 0xe5, 0x07, 0xd2, + 0xb1, 0x43, 0x08, 0xdf, 0x7b, 0xf6, 0xa5, 0xac, 0x35, 0x10, 0x22, 0x88, 0xb4, 0x0f, 0xa8, 0xc8, + 0xd7, 0xe8, 0xdb, 0xf8, 0x47, 0x32, 0xb8, 0x7f, 0x7a, 0x7c, 0x1f, 0x40, 0x29, 0x2a, 0x35, 0xb9, + 0xc3, 0x2a, 0xcc, 0x28, 0x5d, 0xec, 0xe3, 0x78, 0x18, 0x92, 0x68, 0x31, 0x2d, 0x2e, 0xb4, 0xf1, + 0x74, 0xb4, 0x56, 0x7f, 0x1d, 0xd8, 0x89, 0xe3, 0x4f, 0x23, 0xd3, 0x62, 0x6b, 0x60, 0x8a, 0x86, + 0x6d, 0x1c, 0xc1, 0xa2, 0xe2, 0x12, 0x9a, 0x46, 0x90, 0x9c, 0xbc, 0xcc, 0x2b, 0x98, 0x7c, 0x76, + 0x86, 0xc9, 0x1b, 0x3f, 0xcd, 0x43, 0x51, 0x5d, 0x45, 0x98, 0x76, 0x7d, 0x5e, 0x39, 0x79, 0x7d, + 0x5e, 0x33, 0x71, 0xd5, 0x12, 0x4e, 0xbd, 0xdc, 0xef, 0xdf, 0x9d, 0xde, 0xb2, 0x35, 0x5b, 0x45, + 0x62, 0xdb, 0x5e, 0x81, 0xfc, 0xd8, 0x0e, 0xcf, 0xf0, 0x5c, 0x92, 0x88, 0x07, 0xbf, 0x95, 0x0d, + 0xa3, 0x90, 0xb4, 0x61, 0xa4, 0x5d, 0x35, 0x48, 0x22, 0xe9, 0xcc, 0x55, 0x83, 0xb7, 0x80, 0xe4, + 0x0b, 0xcd, 0xc5, 0xad, 0x84, 0x00, 0xb1, 0x17, 0x25, 0xc5, 0x91, 0xd2, 0xb4, 0x38, 0xf2, 0xda, + 0xa2, 0xc2, 0xb7, 0x60, 0x8e, 0xae, 0xe9, 0x90, 0x11, 0xbe, 0x6a, 0x43, 0x91, 0x63, 0xa8, 0xfe, + 0x53, 0xdc, 0x83, 0x29, 0x71, 0xf5, 0x7b, 0xbb, 0x2a, 0x89, 0x7b, 0xbb, 0x74, 0xdb, 0x4a, 0x35, + 0x69, 0x5b, 0xb9, 0x0f, 0x8d, 0x68, 0x40, 0xf1, 0xa4, 0xd2, 0x0d, 0x64, 0xfc, 0x60, 0x5d, 0xc1, + 0x05, 0x97, 0xdc, 0x0f, 0xe2, 0x0d, 0xb1, 0x9e, 0xd8, 0x10, 0x05, 0x0f, 0x6b, 0x85, 0x21, 0x1f, + 0x8d, 0x43, 0xb9, 0x21, 0x62, 0x84, 0x91, 0xde, 0xc0, 0x64, 0xec, 0x7b, 0x0d, 0xca, 0x9d, 0x7d, + 0x6b, 0x7b, 0xb7, 0xf3, 0x74, 0xa7, 0xd7, 0xc8, 0x88, 0xcf, 0xee, 0xd1, 0xe6, 0x66, 0xbb, 0xbd, + 0x85, 0x3b, 0x0e, 0xc0, 0xdc, 0x76, 0xab, 0x23, 0x76, 0x9f, 0x9c, 0xf1, 0x7b, 0x59, 0xa8, 0x68, + 0xc5, 0xb3, 0x27, 0xd1, 0xa8, 0xd0, 0xd5, 0x4e, 0x77, 0x66, 0x9b, 0xb0, 0xae, 0x58, 0xb1, 0x36, + 0x2c, 0xd1, 0xc5, 0x8a, 0xd9, 0x6b, 0x2f, 0x56, 0x64, 0xef, 0xc0, 0xbc, 0x4d, 0x25, 0x44, 0xa3, + 0x20, 0x4f, 0xe1, 0x25, 0x58, 0x0e, 0x02, 0x3a, 0x76, 0xc6, 0xfb, 0x89, 0xc0, 0xcb, 0x2b, 0x5f, + 0xca, 0x68, 0x4b, 0xc1, 0xc1, 0x2a, 0x9e, 0xd8, 0xce, 0x70, 0xe2, 0x73, 0x69, 0x35, 0x8f, 0x76, + 0x66, 0x82, 0x9a, 0x2a, 0xd9, 0xf8, 0x10, 0x20, 0x6e, 0x73, 0x72, 0x70, 0x6e, 0x24, 0x07, 0x27, + 0xa3, 0x0d, 0x4e, 0xd6, 0xd8, 0x22, 0x36, 0x22, 0x07, 0x3a, 0x3a, 0x76, 0xfb, 0x06, 0xa8, 0x83, + 0x40, 0x0b, 0xdd, 0xab, 0xc7, 0x43, 0x1e, 0xaa, 0x5b, 0x02, 0x16, 0x64, 0x4a, 0x27, 0x4a, 0x50, + 0x97, 0x76, 0xc4, 0xa5, 0xc4, 0xdc, 0x48, 0x92, 0xe4, 0x34, 0x37, 0x92, 0xa8, 0x66, 0x94, 0x6e, + 0xac, 0x41, 0x73, 0x8b, 0x8b, 0xd2, 0x5a, 0xc3, 0xe1, 0x54, 0x73, 0x8c, 0x5b, 0x70, 0x33, 0x25, + 0x4d, 0x1e, 0x42, 0x7c, 0x02, 0xcb, 0x2d, 0xba, 0x10, 0xe0, 0xab, 0x8a, 0xfc, 0x33, 0x9a, 0xb0, + 0x32, 0x5d, 0xa4, 0xac, 0x6c, 0x1b, 0x16, 0xb6, 0xf8, 0xf1, 0xe4, 0x74, 0x97, 0x9f, 0xc7, 0x15, + 0x31, 0xc8, 0x07, 0x67, 0xde, 0x85, 0x1c, 0x1f, 0xfc, 0x8d, 0x5e, 0x86, 0x02, 0xc7, 0x0a, 0xc6, + 0xbc, 0xaf, 0x0e, 0xa2, 0x11, 0xd2, 0x1d, 0xf3, 0xbe, 0xf1, 0x04, 0x98, 0x5e, 0x8e, 0x1c, 0x2f, + 0xa1, 0x25, 0x4c, 0x8e, 0xad, 0xe0, 0x2a, 0x08, 0xf9, 0x48, 0x45, 0xbc, 0x41, 0x30, 0x39, 0xee, + 0x12, 0xc4, 0x78, 0x17, 0xaa, 0x87, 0xf6, 0x95, 0xc9, 0x3f, 0x97, 0x81, 0x65, 0xab, 0x50, 0x1c, + 0xdb, 0x57, 0x82, 0x0d, 0x44, 0x36, 0x29, 0x4c, 0x36, 0xfe, 0x28, 0x0f, 0x73, 0x84, 0xc9, 0xee, + 0xd1, 0xe5, 0xbe, 0x8e, 0x8b, 0xcb, 0x50, 0x31, 0x4a, 0x0d, 0x34, 0xc3, 0x4b, 0xb3, 0xb3, 0xbc, + 0x54, 0x1e, 0xa0, 0xa9, 0x4b, 0x8d, 0x94, 0xf5, 0xc0, 0x9d, 0x8c, 0xd4, 0x4d, 0x46, 0xc9, 0xa8, + 0xf8, 0x7c, 0x7c, 0x79, 0x33, 0x85, 0x0c, 0x27, 0xed, 0xbb, 0xb1, 0x2e, 0x42, 0xad, 0x53, 0x5b, + 0x84, 0x64, 0x97, 0x3a, 0x28, 0x55, 0xe1, 0x29, 0xaa, 0x68, 0xc9, 0xa4, 0xc2, 0x33, 0xa3, 0xd8, + 0x94, 0x5e, 0xad, 0xd8, 0xd0, 0xc9, 0xda, 0x4b, 0x14, 0x1b, 0x78, 0x0d, 0xc5, 0xe6, 0x35, 0x6c, + 0xab, 0x37, 0xa1, 0x84, 0xfb, 0xbe, 0xc6, 0x3d, 0xc5, 0x7e, 0x2f, 0xb8, 0xe7, 0xb7, 0x35, 0xd1, + 0x9f, 0x1c, 0x3b, 0x6e, 0xc5, 0xcb, 0xc4, 0xe4, 0x9f, 0xff, 0x62, 0x6c, 0x56, 0xcf, 0xa1, 0x28, + 0xa1, 0x82, 0xa0, 0x5d, 0x7b, 0xa4, 0xee, 0x85, 0xc3, 0xdf, 0x62, 0xd8, 0xf0, 0x32, 0xab, 0xcf, + 0x27, 0x8e, 0xcf, 0x07, 0xea, 0xc2, 0x1f, 0x07, 0xd7, 0xa8, 0x80, 0x88, 0x0e, 0x0a, 0x35, 0xc4, + 0xf5, 0x2e, 0x5c, 0x79, 0xdd, 0x47, 0xd1, 0x09, 0x9e, 0x89, 0x4f, 0x83, 0x41, 0x03, 0x6f, 0x86, + 0x1c, 0x7b, 0xbe, 0xda, 0x9c, 0x8c, 0x9f, 0x66, 0xa0, 0x21, 0x57, 0x57, 0x94, 0xa6, 0x6b, 0x01, + 0x85, 0xeb, 0xfc, 0x10, 0x5e, 0x7e, 0x7d, 0x8f, 0x01, 0x35, 0x3c, 0xfc, 0x88, 0x76, 0x2a, 0x3a, + 0xbc, 0xa9, 0x08, 0xe0, 0xb6, 0xdc, 0xad, 0xde, 0x80, 0x8a, 0xf2, 0x81, 0x1e, 0x39, 0x43, 0x75, + 0x4f, 0x3b, 0x39, 0x41, 0xef, 0x39, 0x43, 0xb5, 0xd1, 0xf9, 0xb6, 0x8c, 0xde, 0xcd, 0xe0, 0x46, + 0x67, 0xda, 0x21, 0x37, 0xfe, 0x75, 0x06, 0x16, 0xb4, 0xae, 0xc8, 0x75, 0xfb, 0x11, 0x54, 0xa3, + 0x2b, 0x59, 0x79, 0x24, 0x79, 0xad, 0x26, 0x19, 0x4d, 0x9c, 0xad, 0xd2, 0x8f, 0x20, 0x81, 0x68, + 0xcc, 0xc0, 0xbe, 0x22, 0x47, 0xdd, 0xc9, 0x48, 0x29, 0x37, 0x03, 0xfb, 0x6a, 0x9b, 0xf3, 0xee, + 0x64, 0x24, 0x54, 0xd7, 0x0b, 0xce, 0x5f, 0x44, 0x08, 0x24, 0x73, 0x81, 0x80, 0x49, 0x0c, 0x03, + 0x6a, 0x23, 0xcf, 0x0d, 0xcf, 0x22, 0x14, 0x29, 0x75, 0x22, 0x90, 0x70, 0x8c, 0x3f, 0xcb, 0xc2, + 0x22, 0x1d, 0xb1, 0xc9, 0xa3, 0x4d, 0xc9, 0xba, 0x9a, 0x30, 0x47, 0xa7, 0x8d, 0xc4, 0xbc, 0x76, + 0x6e, 0x98, 0xf2, 0x9b, 0x7d, 0xeb, 0x35, 0x8f, 0x05, 0x55, 0x80, 0xf0, 0x35, 0xc3, 0x9f, 0x9b, + 0x1d, 0xfe, 0xeb, 0x87, 0x37, 0xcd, 0xd0, 0x59, 0x48, 0x33, 0x74, 0xbe, 0x8e, 0x79, 0x71, 0x26, + 0x94, 0xb5, 0x28, 0x71, 0xb4, 0x50, 0xd6, 0x27, 0xb0, 0x9a, 0xc0, 0x41, 0x6e, 0xed, 0x9c, 0x38, + 0x5c, 0xdd, 0xa6, 0xb2, 0xa4, 0x61, 0x77, 0x55, 0xda, 0x46, 0x11, 0x0a, 0x41, 0xdf, 0x1b, 0x73, + 0x63, 0x05, 0x96, 0x92, 0xa3, 0x2a, 0xb7, 0x89, 0xdf, 0xcf, 0x40, 0x53, 0xba, 0xa5, 0x38, 0xee, + 0xe9, 0x8e, 0x13, 0x84, 0x9e, 0x1f, 0x5d, 0x5d, 0x7a, 0x07, 0x20, 0x08, 0x6d, 0x5f, 0x6a, 0x9b, + 0xf2, 0xfe, 0x10, 0x84, 0xa0, 0x26, 0x79, 0x13, 0x4a, 0xdc, 0x1d, 0x50, 0x22, 0x51, 0x43, 0x91, + 0xbb, 0x03, 0xa5, 0x87, 0xce, 0xc8, 0xdf, 0xb5, 0xa4, 0x7a, 0x21, 0xc3, 0xf9, 0xc5, 0xe8, 0xf0, + 0x73, 0xdc, 0x78, 0xf3, 0x51, 0x38, 0xff, 0x9e, 0x7d, 0x89, 0x4e, 0x9e, 0x81, 0xf1, 0xf7, 0xb3, + 0x30, 0x1f, 0xb7, 0x8f, 0xee, 0x02, 0x79, 0xf9, 0xad, 0x26, 0xf7, 0x24, 0x39, 0x38, 0x42, 0x7e, + 0xd7, 0x0e, 0x1e, 0x4b, 0xb4, 0x38, 0x3b, 0x2e, 0x33, 0xa0, 0xa2, 0x30, 0xbc, 0x49, 0xa8, 0xdd, + 0x20, 0x58, 0x26, 0x94, 0x83, 0x49, 0x28, 0x14, 0x2e, 0xa1, 0x79, 0x3a, 0xae, 0x54, 0x79, 0x0a, + 0xf6, 0x28, 0xec, 0xe0, 0xc3, 0x04, 0x02, 0x2c, 0xb2, 0xd1, 0x44, 0x0a, 0x2c, 0x81, 0xdf, 0x20, + 0x39, 0x9b, 0x66, 0x0e, 0x65, 0x6c, 0x5d, 0x08, 0xa5, 0x3b, 0x9a, 0x23, 0x21, 0xf4, 0x0d, 0xa8, + 0x50, 0xe1, 0x71, 0xe4, 0x72, 0xde, 0x2c, 0x63, 0x0d, 0x98, 0x2e, 0x0f, 0x81, 0xbc, 0x49, 0x42, + 0xf5, 0x05, 0xaa, 0x0a, 0xbd, 0x3e, 0xfe, 0x56, 0x06, 0x6e, 0xa6, 0x4c, 0x9b, 0x5c, 0xe5, 0x9b, + 0xb0, 0x70, 0x12, 0x25, 0xaa, 0xd1, 0xa5, 0xa5, 0xbe, 0xa2, 0xd8, 0x6a, 0x72, 0x4c, 0xcd, 0xc6, + 0x49, 0x12, 0x10, 0x2b, 0x5d, 0x34, 0x83, 0x89, 0xb8, 0x78, 0x54, 0xba, 0x68, 0x1a, 0x49, 0xdf, + 0x39, 0x84, 0xb5, 0xf6, 0xa5, 0xe0, 0x18, 0x9b, 0xfa, 0xcb, 0x1a, 0x8a, 0x8c, 0x92, 0x07, 0xcc, + 0x99, 0xd7, 0x3a, 0x60, 0x1e, 0x50, 0x20, 0x6d, 0x54, 0xd6, 0xcf, 0x52, 0x08, 0x6e, 0xa0, 0x22, + 0x0f, 0xbd, 0x0c, 0xa2, 0x02, 0xe4, 0xfb, 0xd1, 0x8b, 0x20, 0x46, 0x00, 0xf3, 0x7b, 0x93, 0x61, + 0xe8, 0xc4, 0x8f, 0x84, 0xb0, 0x6f, 0xc9, 0x3c, 0x58, 0x8f, 0x1a, 0xb5, 0xd4, 0x8a, 0x20, 0xaa, + 0x08, 0x07, 0x6b, 0x24, 0x0a, 0xb2, 0x66, 0xeb, 0x9b, 0x1f, 0x25, 0x6b, 0x30, 0x6e, 0xc2, 0x6a, + 0xfc, 0x45, 0xc3, 0xa6, 0xb6, 0x9a, 0x7f, 0x92, 0x21, 0x8f, 0xf2, 0xe4, 0x83, 0x25, 0xac, 0x0d, + 0x8b, 0x81, 0xe3, 0x9e, 0x0e, 0xb9, 0x5e, 0x7c, 0x20, 0x07, 0x61, 0x39, 0xd9, 0x36, 0xf9, 0xa8, + 0x89, 0xb9, 0x40, 0x39, 0xe2, 0xd2, 0x02, 0xb6, 0x71, 0x5d, 0x23, 0x63, 0xb2, 0x98, 0x1a, 0x8d, + 0xd9, 0xc6, 0x77, 0xa0, 0x9e, 0xac, 0x88, 0x7d, 0x5b, 0xc6, 0x9f, 0xc7, 0xad, 0xca, 0x4d, 0x05, + 0xe7, 0xc6, 0x04, 0x51, 0x89, 0xc7, 0x3e, 0x30, 0xfe, 0x4e, 0x06, 0x9a, 0x26, 0x17, 0x94, 0xab, + 0xb5, 0x52, 0xd1, 0xcc, 0x47, 0x33, 0xa5, 0x5e, 0xdf, 0x57, 0x15, 0xd6, 0xae, 0x5a, 0xf4, 0xf5, + 0x6b, 0x27, 0x63, 0xe7, 0xc6, 0x4c, 0x8f, 0x36, 0x4a, 0x30, 0x47, 0x28, 0xc6, 0x2a, 0x2c, 0xcb, + 0xf6, 0xa8, 0xb6, 0xc4, 0xd6, 0xc3, 0x44, 0x8d, 0x09, 0xeb, 0xe1, 0x1a, 0x34, 0x29, 0xd0, 0x54, + 0xef, 0x84, 0xcc, 0xb8, 0x05, 0x6c, 0xcf, 0xee, 0xdb, 0xbe, 0xe7, 0xb9, 0x87, 0xdc, 0x97, 0xfe, + 0xb9, 0x28, 0x61, 0xa2, 0x71, 0x4d, 0x89, 0xc2, 0xf4, 0xa5, 0xee, 0x4d, 0xf5, 0x5c, 0xe5, 0x8e, + 0x44, 0x5f, 0x86, 0x09, 0x8b, 0x1b, 0xf6, 0x0b, 0xae, 0x4a, 0x52, 0x43, 0xf4, 0x31, 0x54, 0xc6, + 0x51, 0xa1, 0x6a, 0xdc, 0xd5, 0xfd, 0x18, 0xb3, 0xd5, 0x9a, 0x3a, 0xb6, 0xf1, 0x18, 0x96, 0x92, + 0x65, 0x4a, 0xd6, 0xb1, 0x06, 0xa5, 0x91, 0x84, 0xc9, 0xd6, 0x45, 0xdf, 0xc6, 0xef, 0x96, 0xa0, + 0x28, 0xf5, 0x39, 0xb6, 0x0e, 0xf9, 0xbe, 0x72, 0x09, 0x8b, 0xaf, 0x5d, 0x92, 0xa9, 0xea, 0xff, + 0x26, 0x3a, 0x86, 0x09, 0x3c, 0xf6, 0x31, 0xd4, 0x93, 0x56, 0xd1, 0xa9, 0x30, 0xf6, 0xa4, 0x39, + 0xb3, 0xd6, 0x9f, 0xb2, 0x7f, 0x95, 0xe3, 0xcd, 0x91, 0x64, 0x86, 0xd2, 0x99, 0xb6, 0x7b, 0x7a, + 0xae, 0x90, 0xb7, 0x83, 0x33, 0xdb, 0x7a, 0xfc, 0xe4, 0x43, 0x19, 0xc7, 0x5e, 0x41, 0x60, 0xf7, + 0xcc, 0x7e, 0xfc, 0xe4, 0xc3, 0x69, 0x49, 0x5a, 0x46, 0xb1, 0x6b, 0x92, 0xf4, 0x12, 0x14, 0xe8, + 0x82, 0x50, 0xf2, 0xed, 0xa1, 0x0f, 0xf6, 0x08, 0x96, 0xa4, 0xda, 0x6a, 0x49, 0x2f, 0x6c, 0xe2, + 0x82, 0x25, 0x0a, 0x7c, 0x93, 0x69, 0x5d, 0x4c, 0xa2, 0xb3, 0xa1, 0x15, 0x98, 0x3b, 0x8b, 0x6f, + 0x7b, 0xad, 0x99, 0xf2, 0xcb, 0xf8, 0xb3, 0x02, 0x54, 0xb4, 0x41, 0x61, 0x55, 0x28, 0x99, 0xed, + 0x6e, 0xdb, 0xfc, 0xb4, 0xbd, 0xd5, 0xb8, 0xc1, 0xee, 0xc3, 0xdb, 0x9d, 0xfd, 0xcd, 0x03, 0xd3, + 0x6c, 0x6f, 0xf6, 0xac, 0x03, 0xd3, 0x52, 0x97, 0x7f, 0x1d, 0xb6, 0x9e, 0xef, 0xb5, 0xf7, 0x7b, + 0xd6, 0x56, 0xbb, 0xd7, 0xea, 0xec, 0x76, 0x1b, 0x19, 0x76, 0x1b, 0x9a, 0x31, 0xa6, 0x4a, 0x6e, + 0xed, 0x1d, 0x1c, 0xed, 0xf7, 0x1a, 0x59, 0x76, 0x17, 0x6e, 0x6d, 0x77, 0xf6, 0x5b, 0xbb, 0x56, + 0x8c, 0xb3, 0xb9, 0xdb, 0xfb, 0xd4, 0x6a, 0xff, 0xca, 0x61, 0xc7, 0x7c, 0xde, 0xc8, 0xa5, 0x21, + 0x08, 0x65, 0x5c, 0x95, 0x90, 0x67, 0x37, 0x61, 0x99, 0x10, 0x28, 0x8b, 0xd5, 0x3b, 0x38, 0xb0, + 0xba, 0x07, 0x07, 0xfb, 0x8d, 0x02, 0x5b, 0x80, 0x5a, 0x67, 0xff, 0xd3, 0xd6, 0x6e, 0x67, 0xcb, + 0x32, 0xdb, 0xad, 0xdd, 0xbd, 0xc6, 0x1c, 0x5b, 0x84, 0xf9, 0x69, 0xbc, 0xa2, 0x28, 0x42, 0xe1, + 0x1d, 0xec, 0x77, 0x0e, 0xf6, 0xad, 0x4f, 0xdb, 0x66, 0xb7, 0x73, 0xb0, 0xdf, 0x28, 0xb1, 0x15, + 0x60, 0xc9, 0xa4, 0x9d, 0xbd, 0xd6, 0x66, 0xa3, 0xcc, 0x96, 0x61, 0x21, 0x09, 0x7f, 0xd6, 0x7e, + 0xde, 0x00, 0xd6, 0x84, 0x25, 0x6a, 0x98, 0xb5, 0xd1, 0xde, 0x3d, 0xf8, 0xcc, 0xda, 0xeb, 0xec, + 0x77, 0xf6, 0x8e, 0xf6, 0x1a, 0x15, 0xbc, 0x8e, 0xb0, 0xdd, 0xb6, 0x3a, 0xfb, 0xdd, 0xa3, 0xed, + 0xed, 0xce, 0x66, 0xa7, 0xbd, 0xdf, 0x6b, 0x54, 0xa9, 0xe6, 0xb4, 0x8e, 0xd7, 0x44, 0x06, 0x19, + 0xaa, 0x61, 0x6d, 0x75, 0xba, 0xad, 0x8d, 0xdd, 0xf6, 0x56, 0xa3, 0xce, 0xee, 0xc0, 0xcd, 0x5e, + 0x7b, 0xef, 0xf0, 0xc0, 0x6c, 0x99, 0xcf, 0x55, 0x28, 0x87, 0xb5, 0xdd, 0xea, 0xec, 0x1e, 0x99, + 0xed, 0xc6, 0x3c, 0x7b, 0x13, 0xee, 0x98, 0xed, 0x4f, 0x8e, 0x3a, 0x66, 0x7b, 0xcb, 0xda, 0x3f, + 0xd8, 0x6a, 0x5b, 0xdb, 0xed, 0x56, 0xef, 0xc8, 0x6c, 0x5b, 0x7b, 0x9d, 0x6e, 0xb7, 0xb3, 0xff, + 0xb4, 0xd1, 0x60, 0x6f, 0xc3, 0xbd, 0x08, 0x25, 0x2a, 0x60, 0x0a, 0x6b, 0x41, 0xf4, 0x4f, 0x4d, + 0xe9, 0x7e, 0xfb, 0x57, 0x7a, 0xd6, 0x61, 0xbb, 0x6d, 0x36, 0x18, 0x5b, 0x83, 0x95, 0xb8, 0x7a, + 0xaa, 0x40, 0xd6, 0xbd, 0x28, 0xd2, 0x0e, 0xdb, 0xe6, 0x5e, 0x6b, 0x5f, 0x4c, 0x70, 0x22, 0x6d, + 0x49, 0x34, 0x3b, 0x4e, 0x9b, 0x6e, 0xf6, 0x32, 0x63, 0x50, 0xd7, 0x66, 0x65, 0xbb, 0x65, 0x36, + 0x56, 0xd8, 0x3c, 0x54, 0xf6, 0x0e, 0x0f, 0xad, 0x5e, 0x67, 0xaf, 0x7d, 0x70, 0xd4, 0x6b, 0xac, + 0xb2, 0x65, 0x68, 0x74, 0xf6, 0x7b, 0x6d, 0x53, 0xcc, 0xb5, 0xca, 0xfa, 0x3f, 0x8a, 0x6c, 0x09, + 0xe6, 0x55, 0x4b, 0x15, 0xf4, 0x2f, 0x8b, 0x6c, 0x15, 0xd8, 0xd1, 0xbe, 0xd9, 0x6e, 0x6d, 0x89, + 0x81, 0x8b, 0x12, 0xfe, 0x67, 0x51, 0x5a, 0x48, 0x7e, 0x9a, 0x8b, 0x36, 0xeb, 0xd8, 0xe5, 0x20, + 0x79, 0xf7, 0x77, 0x55, 0xbb, 0xb3, 0xfb, 0x55, 0xaf, 0x72, 0x68, 0xaa, 0x55, 0x6e, 0x46, 0xb5, + 0x9a, 0xd1, 0xdd, 0x6b, 0xba, 0xec, 0xf7, 0x16, 0xd4, 0x46, 0x74, 0x0f, 0xb8, 0xbc, 0xef, 0x17, + 0xa4, 0xff, 0x0d, 0x01, 0xe9, 0xb2, 0xdf, 0x99, 0x67, 0x29, 0x0a, 0xb3, 0xcf, 0x52, 0xa4, 0xc9, + 0xf7, 0x73, 0x69, 0xf2, 0xfd, 0x03, 0x58, 0x20, 0xd6, 0xe4, 0xb8, 0xce, 0x48, 0x69, 0xcd, 0x24, + 0x05, 0xce, 0x23, 0x8b, 0x22, 0xb8, 0x52, 0x27, 0x94, 0xca, 0x21, 0x59, 0x48, 0x51, 0x6a, 0x1b, + 0x09, 0x4d, 0x83, 0x38, 0x47, 0xa4, 0x69, 0x44, 0x35, 0xd8, 0x97, 0x71, 0x0d, 0x15, 0xad, 0x06, + 0x82, 0x63, 0x0d, 0x0f, 0x60, 0x81, 0x5f, 0x86, 0xbe, 0x6d, 0x79, 0x63, 0xfb, 0xf3, 0x09, 0x9a, + 0x70, 0x6d, 0xd4, 0xe1, 0xab, 0xe6, 0x3c, 0x26, 0x1c, 0x20, 0x7c, 0xcb, 0x0e, 0xed, 0x07, 0x5f, + 0x40, 0x45, 0xbb, 0x23, 0x9e, 0xad, 0xc2, 0xe2, 0x67, 0x9d, 0xde, 0x7e, 0xbb, 0xdb, 0xb5, 0x0e, + 0x8f, 0x36, 0x9e, 0xb5, 0x9f, 0x5b, 0x3b, 0xad, 0xee, 0x4e, 0xe3, 0x86, 0x58, 0xb4, 0xfb, 0xed, + 0x6e, 0xaf, 0xbd, 0x95, 0x80, 0x67, 0xd8, 0x1b, 0xb0, 0x76, 0xb4, 0x7f, 0xd4, 0x6d, 0x6f, 0x59, + 0x69, 0xf9, 0xb2, 0x82, 0x4a, 0x65, 0x7a, 0x4a, 0xf6, 0xdc, 0x83, 0xdf, 0x80, 0x7a, 0x32, 0xaa, + 0x99, 0x01, 0xcc, 0xed, 0xb6, 0x9f, 0xb6, 0x36, 0x9f, 0xd3, 0x85, 0xa5, 0xdd, 0x5e, 0xab, 0xd7, + 0xd9, 0xb4, 0xe4, 0x05, 0xa5, 0x82, 0x23, 0x64, 0x58, 0x05, 0x8a, 0xad, 0xfd, 0xcd, 0x9d, 0x03, + 0xb3, 0xdb, 0xc8, 0xb2, 0xdb, 0xb0, 0xaa, 0x68, 0x75, 0xf3, 0x60, 0x6f, 0xaf, 0xd3, 0x43, 0x66, + 0xd8, 0x7b, 0x7e, 0x28, 0x48, 0xf3, 0xc1, 0x77, 0xa1, 0x9e, 0xf4, 0xbd, 0x4b, 0x9e, 0xca, 0xae, + 0xc1, 0xca, 0x46, 0xbb, 0xf7, 0x59, 0xbb, 0xbd, 0x8f, 0x4d, 0xdf, 0x6c, 0xef, 0xf7, 0xcc, 0xd6, + 0x6e, 0xa7, 0xf7, 0xbc, 0x91, 0x79, 0xf0, 0x31, 0x34, 0xa6, 0x0d, 0x5d, 0x09, 0xcb, 0xe0, 0xcb, + 0x4c, 0x88, 0x0f, 0xfe, 0x79, 0x0e, 0x20, 0x0e, 0x00, 0x11, 0x3c, 0x6c, 0xab, 0xd5, 0x6b, 0xed, + 0x1e, 0x88, 0xf1, 0x31, 0x0f, 0x7a, 0x82, 0x35, 0x99, 0xed, 0x4f, 0x1a, 0x37, 0x52, 0x53, 0x0e, + 0x0e, 0x7b, 0x8d, 0x8c, 0x98, 0x8a, 0xce, 0x7e, 0xa7, 0xd7, 0x69, 0xed, 0x5a, 0xe6, 0xc1, 0x51, + 0x67, 0xff, 0x29, 0x5d, 0xf1, 0x88, 0xec, 0xfb, 0xe8, 0x70, 0xdb, 0x3c, 0xd8, 0xef, 0x59, 0xdd, + 0x9d, 0xa3, 0xde, 0x16, 0x5e, 0x10, 0xb9, 0x69, 0x76, 0x0e, 0xa9, 0xcc, 0xfc, 0xcb, 0x10, 0x44, + 0xd1, 0x05, 0x31, 0x99, 0x4f, 0x0f, 0xba, 0xdd, 0xce, 0xa1, 0xf5, 0xc9, 0x51, 0xdb, 0xec, 0xb4, + 0xbb, 0x98, 0x71, 0x2e, 0x05, 0x2e, 0xf0, 0x8b, 0x82, 0xe9, 0xf7, 0x76, 0x3f, 0x95, 0x5c, 0x59, + 0xa0, 0x96, 0x92, 0x20, 0x81, 0x55, 0x16, 0x83, 0x29, 0xd8, 0x5a, 0x4a, 0xc9, 0x70, 0x4d, 0x9a, + 0xc8, 0x57, 0x11, 0x0c, 0x7b, 0x66, 0x96, 0x31, 0x5b, 0x35, 0x3d, 0x49, 0xe4, 0x42, 0x5e, 0x1e, + 0xed, 0x7c, 0x5b, 0x5b, 0x26, 0x66, 0xa8, 0xcf, 0x40, 0x05, 0xee, 0xbc, 0x98, 0x28, 0xc1, 0xf7, + 0x04, 0x4a, 0x43, 0x7d, 0x88, 0x94, 0x85, 0xc7, 0xbf, 0x93, 0x83, 0x3a, 0x05, 0xe3, 0xd1, 0xdb, + 0x7f, 0xdc, 0x67, 0x7b, 0x50, 0x94, 0x8f, 0x48, 0xb2, 0xe5, 0xe8, 0xf6, 0x3d, 0xfd, 0xd9, 0xca, + 0xb5, 0x95, 0x69, 0xb0, 0x94, 0xf3, 0x16, 0xff, 0xda, 0x9f, 0xfe, 0xf7, 0xbf, 0x97, 0xad, 0xb1, + 0xca, 0xc3, 0xf3, 0x0f, 0x1e, 0x9e, 0x72, 0x37, 0x10, 0x65, 0xfc, 0x1a, 0x40, 0xfc, 0x34, 0x22, + 0x6b, 0x46, 0xd6, 0xad, 0xa9, 0x77, 0x23, 0xd7, 0x6e, 0xa6, 0xa4, 0xc8, 0x72, 0x6f, 0x62, 0xb9, + 0x8b, 0x46, 0x5d, 0x94, 0xeb, 0xb8, 0x4e, 0x48, 0xcf, 0x24, 0x7e, 0x94, 0x79, 0xc0, 0x06, 0x50, + 0xd5, 0x1f, 0x2d, 0x64, 0x4a, 0x04, 0x4b, 0x79, 0x76, 0x71, 0xed, 0x56, 0x6a, 0x9a, 0x12, 0x6e, + 0xb1, 0x8e, 0x65, 0xa3, 0x21, 0xea, 0x98, 0x20, 0x46, 0x5c, 0xcb, 0x90, 0xc4, 0xfd, 0xf8, 0x6d, + 0x42, 0x76, 0x5b, 0x13, 0xd8, 0x66, 0x5e, 0x46, 0x5c, 0xbb, 0x73, 0x4d, 0xaa, 0xac, 0xeb, 0x0e, + 0xd6, 0xb5, 0x6a, 0x30, 0x51, 0x57, 0x1f, 0x71, 0xd4, 0xcb, 0x88, 0x1f, 0x65, 0x1e, 0x3c, 0xfe, + 0x0f, 0xef, 0x41, 0x39, 0x72, 0xce, 0x65, 0xbf, 0x09, 0xb5, 0x44, 0xb4, 0x24, 0x53, 0xdd, 0x48, + 0x0b, 0xae, 0x5c, 0xbb, 0x9d, 0x9e, 0x28, 0x2b, 0x7e, 0x03, 0x2b, 0x6e, 0xb2, 0x15, 0x51, 0xb1, + 0x8c, 0x46, 0x7c, 0x88, 0xd1, 0xcd, 0x74, 0x97, 0xe1, 0x0b, 0x4d, 0xad, 0xa1, 0xca, 0x6e, 0x4f, + 0xab, 0x1a, 0x89, 0xda, 0xee, 0x5c, 0x93, 0x2a, 0xab, 0xbb, 0x8d, 0xd5, 0xad, 0xb0, 0x25, 0xbd, + 0x3a, 0xe5, 0xd3, 0xc9, 0x38, 0xde, 0x1f, 0xaa, 0x3f, 0xdd, 0xc7, 0xee, 0xc4, 0xb7, 0x3d, 0xa6, + 0x3c, 0xe9, 0x17, 0x91, 0xc8, 0xec, 0xbb, 0x7e, 0x46, 0x13, 0xab, 0x62, 0x0c, 0xa7, 0x4f, 0x7f, + 0xb9, 0x8f, 0x1d, 0x43, 0x45, 0x7b, 0xed, 0x86, 0xdd, 0xbc, 0xf6, 0x65, 0x9e, 0xb5, 0xb5, 0xb4, + 0xa4, 0xb4, 0xae, 0xe8, 0xe5, 0x3f, 0x3c, 0xe1, 0x9c, 0xfd, 0x2a, 0x94, 0xa3, 0x37, 0x54, 0xd8, + 0xaa, 0xf6, 0xa6, 0x8d, 0xfe, 0xe6, 0xcb, 0x5a, 0x73, 0x36, 0x21, 0x8d, 0xf8, 0xf4, 0xd2, 0x05, + 0xf1, 0x7d, 0x06, 0x15, 0xed, 0x9d, 0x94, 0xa8, 0x03, 0xb3, 0x6f, 0xb1, 0x44, 0x1d, 0x48, 0x79, + 0x56, 0xc5, 0x58, 0xc0, 0x2a, 0x2a, 0xac, 0x8c, 0xf4, 0x1d, 0x5e, 0x7a, 0x01, 0xdb, 0x85, 0x65, + 0xa9, 0xc2, 0x1d, 0xf3, 0x2f, 0x33, 0x0d, 0x29, 0xaf, 0x25, 0x3e, 0xca, 0xb0, 0x8f, 0xa1, 0xa4, + 0x9e, 0xc3, 0x61, 0x2b, 0xe9, 0xcf, 0xfa, 0xac, 0xad, 0xce, 0xc0, 0xa5, 0xbe, 0xf5, 0x1c, 0x20, + 0x7e, 0x94, 0x25, 0x62, 0x12, 0x33, 0x8f, 0xbc, 0x44, 0x14, 0x30, 0xfb, 0x82, 0x8b, 0xb1, 0x82, + 0x1d, 0x6c, 0x30, 0x64, 0x12, 0x2e, 0xbf, 0x50, 0x97, 0x3c, 0xff, 0x08, 0x2a, 0xda, 0xbb, 0x2c, + 0xd1, 0xf0, 0xcd, 0xbe, 0xe9, 0x12, 0x0d, 0x5f, 0xca, 0x33, 0x2e, 0xc6, 0x1a, 0x96, 0xbe, 0x64, + 0xcc, 0x8b, 0xd2, 0x85, 0x0c, 0x27, 0x65, 0x29, 0x31, 0x41, 0x67, 0x50, 0x4b, 0x3c, 0xbe, 0x12, + 0xad, 0xd0, 0xb4, 0xa7, 0x5d, 0xa2, 0x15, 0x9a, 0xfa, 0x5e, 0x8b, 0xa2, 0x33, 0x63, 0x41, 0xd4, + 0x43, 0xf7, 0x3c, 0x69, 0x35, 0xfd, 0x10, 0x2a, 0xda, 0x43, 0x2a, 0x51, 0x5f, 0x66, 0xdf, 0x6c, + 0x89, 0xfa, 0x92, 0xf6, 0xee, 0xca, 0x12, 0xd6, 0x51, 0x37, 0x90, 0x14, 0xf0, 0x9a, 0x5a, 0x51, + 0xf6, 0x6f, 0x42, 0x3d, 0xf9, 0xb6, 0x4a, 0xb4, 0xf6, 0x53, 0x1f, 0x69, 0x89, 0xd6, 0xfe, 0x35, + 0x0f, 0xb2, 0x48, 0x92, 0x7e, 0xb0, 0x18, 0x55, 0xf2, 0xf0, 0x27, 0x32, 0xcc, 0xe8, 0x0b, 0xf6, + 0x89, 0x60, 0x70, 0xf2, 0x96, 0x64, 0xb6, 0xaa, 0x51, 0xad, 0x7e, 0xdd, 0x72, 0xb4, 0x5e, 0x66, + 0x2e, 0x54, 0x4e, 0x12, 0x33, 0x16, 0xce, 0x9e, 0xc2, 0x62, 0x44, 0xcc, 0xd1, 0xb5, 0xc7, 0x41, + 0xd4, 0x87, 0xd4, 0xcb, 0x95, 0xd7, 0x1a, 0xd3, 0xa9, 0x8f, 0x32, 0xb4, 0xfd, 0xe1, 0x65, 0xb3, + 0xda, 0xf6, 0xa7, 0xdf, 0x7c, 0xac, 0x6d, 0x7f, 0x89, 0x3b, 0x69, 0xa7, 0xb7, 0xbf, 0xd0, 0x11, + 0x65, 0xb8, 0x30, 0x3f, 0x7d, 0x09, 0xf1, 0x9d, 0xeb, 0xae, 0x71, 0xa0, 0xe2, 0xdf, 0x78, 0xf9, + 0x2d, 0x0f, 0x49, 0x56, 0xa4, 0xb8, 0xe9, 0x43, 0xe9, 0xd5, 0xc2, 0x7e, 0x1d, 0xaa, 0xfa, 0x7b, + 0x0c, 0x4c, 0xe7, 0x09, 0xd3, 0x35, 0xdd, 0x4a, 0x4d, 0x4b, 0x52, 0x09, 0xab, 0xea, 0xd5, 0xb0, + 0x4f, 0x61, 0x25, 0x1a, 0x66, 0xfd, 0x1e, 0x82, 0x80, 0xdd, 0x4d, 0xb9, 0x9d, 0x20, 0x31, 0xd8, + 0x37, 0xaf, 0xbd, 0xbe, 0xe0, 0x51, 0x46, 0x50, 0x5f, 0xf2, 0x62, 0xf8, 0x78, 0xe7, 0x49, 0xbb, + 0x0f, 0x3f, 0xde, 0x79, 0x52, 0x6f, 0x93, 0x57, 0xd4, 0xc7, 0x16, 0x13, 0x63, 0x44, 0xfe, 0xbe, + 0xec, 0x87, 0x30, 0xaf, 0x5d, 0xb2, 0xd0, 0xbd, 0x72, 0xfb, 0xd1, 0x4a, 0x9a, 0xbd, 0x5e, 0x74, + 0x2d, 0xed, 0xd0, 0xd3, 0x58, 0xc5, 0xf2, 0x17, 0x8c, 0xc4, 0xe0, 0x88, 0x55, 0xb4, 0x09, 0x15, + 0xfd, 0x02, 0x87, 0x97, 0x94, 0xbb, 0xaa, 0x25, 0xe9, 0x37, 0x59, 0x3e, 0xca, 0xb0, 0x5d, 0x68, + 0x4c, 0x5f, 0xae, 0x16, 0xf1, 0x94, 0xb4, 0x0b, 0xe9, 0xd6, 0xa6, 0x12, 0x13, 0x57, 0xb2, 0xb1, + 0x43, 0x8a, 0x18, 0x89, 0x9e, 0x16, 0xf4, 0xfc, 0xe9, 0x5d, 0x3d, 0xf9, 0xe4, 0x60, 0x54, 0x5a, + 0xda, 0x63, 0x93, 0xf7, 0x33, 0x8f, 0x32, 0xec, 0xf7, 0x32, 0x50, 0x4d, 0x5c, 0x37, 0x94, 0xf0, + 0xc9, 0x9f, 0xea, 0x67, 0x53, 0x4f, 0xd3, 0x3b, 0x6a, 0x98, 0x38, 0x88, 0xbb, 0x0f, 0x7e, 0x90, + 0x98, 0xa4, 0x9f, 0x24, 0x6c, 0x86, 0xeb, 0xd3, 0x6f, 0x0f, 0x7e, 0x31, 0x8d, 0xa0, 0x5f, 0x58, + 0xfb, 0xc5, 0xa3, 0x0c, 0xfb, 0x97, 0x19, 0xa8, 0x27, 0x9d, 0x01, 0xa2, 0xee, 0xa6, 0xba, 0x1d, + 0x44, 0xa4, 0x74, 0x8d, 0x07, 0xc1, 0x0f, 0xb1, 0x95, 0xbd, 0x07, 0x66, 0xa2, 0x95, 0xf2, 0x49, + 0x83, 0x9f, 0xaf, 0xb5, 0xec, 0x97, 0xe9, 0xa9, 0x5f, 0xe5, 0x23, 0xc5, 0x66, 0x9f, 0x86, 0x8d, + 0xc8, 0x4f, 0x7f, 0x48, 0xd5, 0xc8, 0xfd, 0x76, 0x36, 0x83, 0x33, 0xf1, 0x23, 0x7a, 0x68, 0x4f, + 0xf9, 0xdd, 0x08, 0x52, 0x7e, 0xed, 0x42, 0xde, 0xc6, 0x8e, 0xbd, 0x61, 0xdc, 0x4c, 0x74, 0x6c, + 0x5a, 0xfa, 0x68, 0x51, 0x13, 0xe5, 0x63, 0xa8, 0xf1, 0xf6, 0x39, 0xf3, 0x40, 0x6a, 0x6a, 0x25, + 0xd8, 0xc8, 0x11, 0x35, 0x52, 0xa2, 0x27, 0xd6, 0xdb, 0x6b, 0x16, 0x63, 0x3c, 0xc0, 0xb6, 0xbe, + 0x6d, 0xdc, 0xbd, 0xb6, 0xad, 0x0f, 0xd1, 0xba, 0x2f, 0x5a, 0x7c, 0x08, 0x10, 0x3b, 0x32, 0xb2, + 0x29, 0x77, 0xba, 0x88, 0x0b, 0xcd, 0xfa, 0x3a, 0x26, 0x17, 0xb5, 0xf2, 0xba, 0x13, 0x25, 0xfe, + 0x2a, 0xf1, 0xd4, 0xc8, 0xd1, 0x4f, 0x17, 0xc1, 0x92, 0x3e, 0x87, 0x09, 0x11, 0x6c, 0xba, 0xfc, + 0x04, 0x47, 0x8d, 0xbc, 0xfa, 0x8e, 0xa0, 0xb6, 0xeb, 0x79, 0x2f, 0x26, 0xe3, 0xc8, 0x79, 0x3e, + 0xe9, 0x72, 0xb3, 0x63, 0x07, 0x67, 0x6b, 0x53, 0xbd, 0x30, 0xee, 0x61, 0x51, 0x6b, 0xac, 0xa9, + 0x15, 0xf5, 0xf0, 0x27, 0xb1, 0xf7, 0xe4, 0x17, 0xcc, 0x86, 0x85, 0x88, 0x51, 0xc7, 0x1e, 0x8a, + 0xc9, 0x62, 0x12, 0xec, 0x79, 0xba, 0x8a, 0x84, 0xae, 0xa0, 0x5a, 0xfb, 0x30, 0x50, 0x65, 0x3e, + 0xca, 0xb0, 0x43, 0xa8, 0x6e, 0xf1, 0x3e, 0xde, 0xbe, 0x80, 0x8e, 0x2b, 0x8b, 0x09, 0x27, 0x08, + 0xf2, 0x78, 0x59, 0xab, 0x25, 0x80, 0xc9, 0xcd, 0x6b, 0x6c, 0x5f, 0xf9, 0xfc, 0xf3, 0x87, 0x3f, + 0x91, 0x2e, 0x31, 0x5f, 0xa8, 0xcd, 0x4b, 0xb9, 0x0c, 0x25, 0x36, 0xaf, 0x29, 0x1f, 0xa3, 0xc4, + 0xe6, 0x35, 0xe3, 0x63, 0x94, 0x18, 0x6a, 0xe5, 0xb2, 0xc4, 0x86, 0xb0, 0x30, 0xe3, 0x96, 0x14, + 0xed, 0x5b, 0xd7, 0x39, 0x33, 0xad, 0xdd, 0xbb, 0x1e, 0x21, 0x59, 0xdb, 0x83, 0x64, 0x6d, 0x5d, + 0xa8, 0xd1, 0x95, 0xb4, 0xc7, 0x9c, 0xe2, 0x30, 0xa7, 0x2e, 0x31, 0xd2, 0x83, 0x3c, 0xa7, 0x77, + 0x19, 0x4c, 0x4b, 0x8a, 0x39, 0x18, 0x89, 0xc7, 0x4e, 0xf0, 0x1d, 0x06, 0x2d, 0xf0, 0x31, 0x22, + 0xc6, 0xd9, 0x60, 0xcc, 0x88, 0x18, 0x53, 0xe2, 0x24, 0x95, 0x0e, 0xca, 0x96, 0xa3, 0xb2, 0x1f, + 0xba, 0xde, 0x80, 0x8f, 0x64, 0xa9, 0xbf, 0x0a, 0x95, 0xa7, 0x3c, 0x54, 0x91, 0x86, 0x91, 0x40, + 0x3f, 0x15, 0x7a, 0xb8, 0x96, 0x12, 0x1f, 0x9a, 0xa4, 0x4d, 0x2a, 0x99, 0x0f, 0x4e, 0x39, 0x71, + 0x42, 0xcb, 0x19, 0x7c, 0xc1, 0x7e, 0x05, 0x0b, 0x8f, 0xe2, 0xea, 0x57, 0xb4, 0x66, 0xea, 0x85, + 0xcf, 0x4f, 0xc1, 0xd3, 0x4a, 0x16, 0x6d, 0xd6, 0x04, 0x4b, 0x17, 0x2a, 0xda, 0xfd, 0x1b, 0xd1, + 0xd8, 0xcc, 0xde, 0xb7, 0x12, 0x8d, 0x4d, 0xca, 0x75, 0x1d, 0xc6, 0x7d, 0xac, 0xc7, 0x60, 0xf7, + 0xe2, 0x7a, 0xe8, 0x8a, 0x8e, 0xb8, 0xa6, 0x87, 0x3f, 0xb1, 0x47, 0xe1, 0x17, 0xec, 0x33, 0x9a, + 0x0e, 0x2d, 0x92, 0x32, 0xd6, 0x50, 0xa6, 0x83, 0x2e, 0xa3, 0xc1, 0xd2, 0x92, 0x92, 0x5a, 0x0b, + 0x55, 0x85, 0x62, 0xe3, 0x13, 0x80, 0x6e, 0xe8, 0x8d, 0xb7, 0x6c, 0x3e, 0xf2, 0xdc, 0x98, 0xa7, + 0xc7, 0xb1, 0x7d, 0x31, 0x9f, 0xd4, 0x02, 0xfc, 0xd8, 0x67, 0x9a, 0x4a, 0x97, 0x88, 0x01, 0x56, + 0x44, 0x7c, 0x6d, 0xf8, 0x5f, 0x34, 0x20, 0x29, 0x21, 0x80, 0x8f, 0x32, 0xac, 0x05, 0x10, 0xfb, + 0xbf, 0x45, 0x0a, 0xda, 0x8c, 0x6b, 0x5d, 0xc4, 0x5e, 0x53, 0x9c, 0xe5, 0x0e, 0xa1, 0x1c, 0x3b, + 0x0e, 0xad, 0xc6, 0xd7, 0x09, 0x25, 0xdc, 0x8c, 0x22, 0x71, 0x61, 0xc6, 0x69, 0xc7, 0x68, 0xe0, + 0x50, 0x01, 0x2b, 0x89, 0xa1, 0x3a, 0xe1, 0x3c, 0x60, 0x0e, 0x2c, 0x52, 0x03, 0x23, 0xd9, 0x0c, + 0x63, 0xd2, 0xa2, 0xd7, 0x4f, 0x66, 0xfd, 0x67, 0x22, 0xae, 0x91, 0xea, 0x05, 0x92, 0x38, 0x67, + 0x12, 0xd4, 0x4a, 0xf1, 0x70, 0x62, 0x0b, 0x18, 0xc1, 0xc2, 0x8c, 0xa3, 0x41, 0xc4, 0x3a, 0xae, + 0xf3, 0x1c, 0x89, 0x58, 0xc7, 0xb5, 0x3e, 0x0a, 0xc6, 0x32, 0x56, 0x39, 0x6f, 0x00, 0xea, 0x95, + 0x17, 0x4e, 0xd8, 0x3f, 0x13, 0xd5, 0xfd, 0x41, 0x06, 0x16, 0x53, 0x5c, 0x09, 0xd8, 0x9b, 0xea, + 0x88, 0xe2, 0x5a, 0x37, 0x83, 0xb5, 0x54, 0x93, 0xb3, 0xd1, 0xc5, 0x7a, 0xf6, 0xd8, 0xb3, 0xc4, + 0x06, 0x4a, 0x16, 0x5f, 0xb9, 0x32, 0x5f, 0x2a, 0xc1, 0xa4, 0x8a, 0x2f, 0x9f, 0xc3, 0x2a, 0x35, + 0xa4, 0x35, 0x1c, 0x4e, 0x99, 0xc3, 0xdf, 0xd0, 0x5a, 0x91, 0x62, 0xe2, 0x4f, 0x28, 0x03, 0x49, + 0x33, 0xff, 0x35, 0xb2, 0x3b, 0x35, 0x95, 0x4d, 0xa0, 0x31, 0x6d, 0x66, 0x66, 0xd7, 0x97, 0xb5, + 0x76, 0x37, 0xa1, 0x6c, 0xa7, 0x98, 0xa6, 0xbf, 0x86, 0x95, 0xdd, 0x35, 0xd6, 0xd2, 0xc6, 0x85, + 0xf4, 0x6f, 0x31, 0x1f, 0xff, 0x7f, 0x64, 0x13, 0x9f, 0xea, 0xe7, 0xdd, 0xe8, 0xbe, 0xf7, 0x74, + 0x0b, 0x7e, 0xa4, 0xee, 0xa7, 0x9b, 0xd4, 0xdf, 0xc1, 0xea, 0xef, 0x19, 0xb7, 0xd2, 0xaa, 0xf7, + 0x29, 0x0b, 0x29, 0xfe, 0xab, 0xd3, 0xeb, 0x5a, 0xb5, 0xe0, 0x5e, 0xda, 0x7c, 0x5f, 0xab, 0x78, + 0x4d, 0x8d, 0xf5, 0x0d, 0x94, 0x21, 0xab, 0xba, 0x0d, 0x3c, 0x5a, 0x3e, 0x29, 0xc6, 0xf6, 0x68, + 0xf9, 0xa4, 0x19, 0xcd, 0x93, 0xf2, 0x93, 0x32, 0x97, 0x7f, 0x94, 0x79, 0xb0, 0xf1, 0xee, 0x0f, + 0xbf, 0x76, 0xea, 0x84, 0x67, 0x93, 0xe3, 0xf5, 0xbe, 0x37, 0x7a, 0x38, 0x54, 0x47, 0x9b, 0x32, + 0x70, 0xfb, 0xe1, 0xd0, 0x1d, 0x3c, 0xc4, 0x62, 0x8f, 0xe7, 0xc6, 0xbe, 0x17, 0x7a, 0xdf, 0xfc, + 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x4e, 0xb1, 0xa4, 0x40, 0x5a, 0x89, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -12999,10 +12999,11 @@ type LightningClient interface { //when in debug builds of lnd. AbandonChannel(ctx context.Context, in *AbandonChannelRequest, opts ...grpc.CallOption) (*AbandonChannelResponse, error) //* lncli: `sendpayment` - //SendPayment dispatches a bi-directional streaming RPC for sending payments - //through the Lightning Network. A single RPC invocation creates a persistent - //bi-directional stream allowing clients to rapidly send payments through the - //Lightning Network with a single persistent connection. + //Deprecated, use routerrpc.SendPayment. SendPayment dispatches a + //bi-directional streaming RPC for sending payments through the Lightning + //Network. A single RPC invocation creates a persistent bi-directional + //stream allowing clients to rapidly send payments through the Lightning + //Network with a single persistent connection. SendPayment(ctx context.Context, opts ...grpc.CallOption) (Lightning_SendPaymentClient, error) //* //SendPaymentSync is the synchronous non-streaming version of SendPayment. @@ -13553,6 +13554,7 @@ func (c *lightningClient) AbandonChannel(ctx context.Context, in *AbandonChannel return out, nil } +// Deprecated: Do not use. func (c *lightningClient) SendPayment(ctx context.Context, opts ...grpc.CallOption) (Lightning_SendPaymentClient, error) { stream, err := c.cc.NewStream(ctx, &_Lightning_serviceDesc.Streams[6], "/lnrpc.Lightning/SendPayment", opts...) if err != nil { @@ -14074,10 +14076,11 @@ type LightningServer interface { //when in debug builds of lnd. AbandonChannel(context.Context, *AbandonChannelRequest) (*AbandonChannelResponse, error) //* lncli: `sendpayment` - //SendPayment dispatches a bi-directional streaming RPC for sending payments - //through the Lightning Network. A single RPC invocation creates a persistent - //bi-directional stream allowing clients to rapidly send payments through the - //Lightning Network with a single persistent connection. + //Deprecated, use routerrpc.SendPayment. SendPayment dispatches a + //bi-directional streaming RPC for sending payments through the Lightning + //Network. A single RPC invocation creates a persistent bi-directional + //stream allowing clients to rapidly send payments through the Lightning + //Network with a single persistent connection. SendPayment(Lightning_SendPaymentServer) error //* //SendPaymentSync is the synchronous non-streaming version of SendPayment. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index df2ed7ee92..001944a0c2 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -503,12 +503,15 @@ service Lightning { } /** lncli: `sendpayment` - SendPayment dispatches a bi-directional streaming RPC for sending payments - through the Lightning Network. A single RPC invocation creates a persistent - bi-directional stream allowing clients to rapidly send payments through the - Lightning Network with a single persistent connection. - */ - rpc SendPayment (stream SendRequest) returns (stream SendResponse); + Deprecated, use routerrpc.SendPayment. SendPayment dispatches a + bi-directional streaming RPC for sending payments through the Lightning + Network. A single RPC invocation creates a persistent bi-directional + stream allowing clients to rapidly send payments through the Lightning + Network with a single persistent connection. + */ + rpc SendPayment (stream SendRequest) returns (stream SendResponse) { + option deprecated = true; + } /** SendPaymentSync is the synchronous non-streaming version of SendPayment. From 6b649eeb1095653b05596ce898a3323de36076fc Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 31 Mar 2020 22:04:57 +0200 Subject: [PATCH 356/562] lncli: remove unused type chain --- cmd/lncli/commands.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 5ab5fd52be..79313d252d 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1705,11 +1705,6 @@ var getInfoCommand = cli.Command{ Action: actionDecorator(getInfo), } -type chain struct { - Chain string `json:"chain"` - Network string `json:"network"` -} - func getInfo(ctx *cli.Context) error { ctxb := context.Background() client, cleanUp := getClient(ctx) From c2301c14b2357edb33e86fbf7a7868862b1900d6 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:22 +0200 Subject: [PATCH 357/562] routing/payment_session: make NewPaymentSession take payment directly This commit moves supplying of the information in the LightningPayment to the initialization of the paymentSession, away from every call to RequestRoute. Instead the paymentSession will store this information internally, as it doesn't change between payment attempts. This is done to rid the RequestRoute call of the LightingPayment argument, as for SendToRoute calls, it is not needed to supply the next route. --- routing/mock_test.go | 9 +++------ routing/payment_lifecycle.go | 21 +++++++++----------- routing/payment_session.go | 33 ++++++++++++++++--------------- routing/payment_session_source.go | 7 ++++--- routing/payment_session_test.go | 19 +++++++++--------- routing/router.go | 22 +++++++++------------ 6 files changed, 52 insertions(+), 59 deletions(-) diff --git a/routing/mock_test.go b/routing/mock_test.go index 6332bea8f6..64a1e4f655 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -10,7 +10,6 @@ import ( "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" - "github.com/lightningnetwork/lnd/zpay32" ) type mockPaymentAttemptDispatcher struct { @@ -78,8 +77,8 @@ type mockPaymentSessionSource struct { var _ PaymentSessionSource = (*mockPaymentSessionSource)(nil) -func (m *mockPaymentSessionSource) NewPaymentSession(routeHints [][]zpay32.HopHint, - target route.Vertex) (PaymentSession, error) { +func (m *mockPaymentSessionSource) NewPaymentSession( + _ *LightningPayment) (PaymentSession, error) { return &mockPaymentSession{m.routes}, nil } @@ -123,9 +122,7 @@ type mockPaymentSession struct { var _ PaymentSession = (*mockPaymentSession)(nil) -func (m *mockPaymentSession) RequestRoute(payment *LightningPayment, - height uint32, finalCltvDelta uint16) (*route.Route, error) { - +func (m *mockPaymentSession) RequestRoute(height uint32) (*route.Route, error) { if len(m.routes) == 0 { return nil, fmt.Errorf("no routes") } diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 96441d179d..58bafc7d92 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -29,15 +29,14 @@ func (e errNoRoute) Error() string { // paymentLifecycle holds all information about the current state of a payment // needed to resume if from any point. type paymentLifecycle struct { - router *ChannelRouter - payment *LightningPayment - paySession PaymentSession - timeoutChan <-chan time.Time - currentHeight int32 - finalCLTVDelta uint16 - attempt *channeldb.HTLCAttemptInfo - circuit *sphinx.Circuit - lastError error + router *ChannelRouter + payment *LightningPayment + paySession PaymentSession + timeoutChan <-chan time.Time + currentHeight int32 + attempt *channeldb.HTLCAttemptInfo + circuit *sphinx.Circuit + lastError error } // resumePayment resumes the paymentLifecycle from the current state. @@ -267,9 +266,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, } // Create a new payment attempt from the given payment session. - rt, err := p.paySession.RequestRoute( - p.payment, uint32(p.currentHeight), p.finalCLTVDelta, - ) + rt, err := p.paySession.RequestRoute(uint32(p.currentHeight)) if err != nil { log.Warnf("Failed to find route for payment %x: %v", p.payment.PaymentHash, err) diff --git a/routing/payment_session.go b/routing/payment_session.go index 47732e01ad..fda93536ee 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -24,8 +24,7 @@ var ( type PaymentSession interface { // RequestRoute returns the next route to attempt for routing the // specified HTLC payment to the target node. - RequestRoute(payment *LightningPayment, - height uint32, finalCltvDelta uint16) (*route.Route, error) + RequestRoute(height uint32) (*route.Route, error) } // paymentSession is used during an HTLC routings session to prune the local @@ -43,6 +42,8 @@ type paymentSession struct { sessionSource *SessionSource + payment *LightningPayment + preBuiltRoute *route.Route preBuiltRouteTried bool @@ -58,8 +59,7 @@ type paymentSession struct { // // NOTE: This function is safe for concurrent access. // NOTE: Part of the PaymentSession interface. -func (p *paymentSession) RequestRoute(payment *LightningPayment, - height uint32, finalCltvDelta uint16) (*route.Route, error) { +func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) { switch { @@ -77,12 +77,13 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment, // Add BlockPadding to the finalCltvDelta so that the receiving node // does not reject the HTLC if some blocks are mined while it's in-flight. + finalCltvDelta := p.payment.FinalCLTVDelta finalCltvDelta += BlockPadding // We need to subtract the final delta before passing it into path // finding. The optimal path is independent of the final cltv delta and // the path finding algorithm is unaware of this value. - cltvLimit := payment.CltvLimit - uint32(finalCltvDelta) + cltvLimit := p.payment.CltvLimit - uint32(finalCltvDelta) // TODO(roasbeef): sync logic amongst dist sys @@ -93,13 +94,13 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment, restrictions := &RestrictParams{ ProbabilitySource: ss.MissionControl.GetProbability, - FeeLimit: payment.FeeLimit, - OutgoingChannelID: payment.OutgoingChannelID, - LastHop: payment.LastHop, + FeeLimit: p.payment.FeeLimit, + OutgoingChannelID: p.payment.OutgoingChannelID, + LastHop: p.payment.LastHop, CltvLimit: cltvLimit, - DestCustomRecords: payment.DestCustomRecords, - DestFeatures: payment.DestFeatures, - PaymentAddr: payment.PaymentAddr, + DestCustomRecords: p.payment.DestCustomRecords, + DestFeatures: p.payment.DestFeatures, + PaymentAddr: p.payment.PaymentAddr, } // We'll also obtain a set of bandwidthHints from the lower layer for @@ -122,8 +123,8 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment, bandwidthHints: bandwidthHints, }, restrictions, &ss.PathFindingConfig, - ss.SelfNode.PubKeyBytes, payment.Target, - payment.Amount, finalHtlcExpiry, + ss.SelfNode.PubKeyBytes, p.payment.Target, + p.payment.Amount, finalHtlcExpiry, ) if err != nil { return nil, err @@ -135,10 +136,10 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment, route, err := newRoute( sourceVertex, path, height, finalHopParams{ - amt: payment.Amount, + amt: p.payment.Amount, cltvDelta: finalCltvDelta, - records: payment.DestCustomRecords, - paymentAddr: payment.PaymentAddr, + records: p.payment.DestCustomRecords, + paymentAddr: p.payment.PaymentAddr, }, ) if err != nil { diff --git a/routing/payment_session_source.go b/routing/payment_session_source.go index 05295b58d3..f3fd968e85 100644 --- a/routing/payment_session_source.go +++ b/routing/payment_session_source.go @@ -47,10 +47,10 @@ type SessionSource struct { // view from Mission Control. An optional set of routing hints can be provided // in order to populate additional edges to explore when finding a path to the // payment's destination. -func (m *SessionSource) NewPaymentSession(routeHints [][]zpay32.HopHint, - target route.Vertex) (PaymentSession, error) { +func (m *SessionSource) NewPaymentSession(p *LightningPayment) ( + PaymentSession, error) { - edges, err := RouteHintsToEdges(routeHints, target) + edges, err := RouteHintsToEdges(p.RouteHints, p.Target) if err != nil { return nil, err } @@ -70,6 +70,7 @@ func (m *SessionSource) NewPaymentSession(routeHints [][]zpay32.HopHint, additionalEdges: edges, getBandwidthHints: getBandwidthHints, sessionSource: m, + payment: p, pathFinder: findPath, }, nil } diff --git a/routing/payment_session_test.go b/routing/payment_session_test.go index 55549c4488..6d795b89d7 100644 --- a/routing/payment_session_test.go +++ b/routing/payment_session_test.go @@ -44,6 +44,14 @@ func TestRequestRoute(t *testing.T) { }, } + cltvLimit := uint32(30) + finalCltvDelta := uint16(8) + + payment := &LightningPayment{ + CltvLimit: cltvLimit, + FinalCLTVDelta: finalCltvDelta, + } + session := &paymentSession{ getBandwidthHints: func() (map[uint64]lnwire.MilliSatoshi, error) { @@ -51,18 +59,11 @@ func TestRequestRoute(t *testing.T) { return nil, nil }, sessionSource: sessionSource, + payment: payment, pathFinder: findPath, } - cltvLimit := uint32(30) - finalCltvDelta := uint16(8) - - payment := &LightningPayment{ - CltvLimit: cltvLimit, - FinalCLTVDelta: finalCltvDelta, - } - - route, err := session.RequestRoute(payment, height, finalCltvDelta) + route, err := session.RequestRoute(height) if err != nil { t.Fatal(err) } diff --git a/routing/router.go b/routing/router.go index ca7a20f806..5ef4dcaa37 100644 --- a/routing/router.go +++ b/routing/router.go @@ -159,8 +159,7 @@ type PaymentSessionSource interface { // routes to the given target. An optional set of routing hints can be // provided in order to populate additional edges to explore when // finding a path to the payment's destination. - NewPaymentSession(routeHints [][]zpay32.HopHint, - target route.Vertex) (PaymentSession, error) + NewPaymentSession(p *LightningPayment) (PaymentSession, error) // NewPaymentSessionForRoute creates a new paymentSession instance that // is just used for failure reporting to missioncontrol, and will only @@ -1677,9 +1676,7 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) ( // Before starting the HTLC routing attempt, we'll create a fresh // payment session which will report our errors back to mission // control. - paySession, err := r.cfg.SessionSource.NewPaymentSession( - payment.RouteHints, payment.Target, - ) + paySession, err := r.cfg.SessionSource.NewPaymentSession(payment) if err != nil { return nil, err } @@ -1813,14 +1810,13 @@ func (r *ChannelRouter) sendPayment( // Now set up a paymentLifecycle struct with these params, such that we // can resume the payment from the current state. p := &paymentLifecycle{ - router: r, - payment: payment, - paySession: paySession, - currentHeight: currentHeight, - finalCLTVDelta: uint16(payment.FinalCLTVDelta), - attempt: existingAttempt, - circuit: nil, - lastError: nil, + router: r, + payment: payment, + paySession: paySession, + currentHeight: currentHeight, + attempt: existingAttempt, + circuit: nil, + lastError: nil, } // If a timeout is specified, create a timeout channel. If no timeout is From f9eeb6b41ff5e78da97deff24be27add956586b5 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:22 +0200 Subject: [PATCH 358/562] routing/router+lifecycle: remove LightningPayment from payment lifecycle Now that the information needed is stored by the paymentSession, we no longer need to pass the LightningPayment into the payment lifecycle. --- routing/payment_lifecycle.go | 43 +++++++------ routing/router.go | 121 +++++++++++++++++++---------------- 2 files changed, 88 insertions(+), 76 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 58bafc7d92..a0cb566a61 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -8,6 +8,7 @@ import ( sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/htlcswitch" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -30,7 +31,7 @@ func (e errNoRoute) Error() string { // needed to resume if from any point. type paymentLifecycle struct { router *ChannelRouter - payment *LightningPayment + paymentHash lntypes.Hash paySession PaymentSession timeoutChan <-chan time.Time currentHeight int32 @@ -84,7 +85,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // from an invalid route, because the sphinx packet has // been successfully generated before. _, c, err := generateSphinxPacket( - &p.attempt.Route, p.payment.PaymentHash[:], + &p.attempt.Route, p.paymentHash[:], p.attempt.SessionKey, ) if err != nil { @@ -103,7 +104,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // Now ask the switch to return the result of the payment when // available. resultChan, err := p.router.cfg.Payer.GetPaymentResult( - p.attempt.AttemptID, p.payment.PaymentHash, errorDecryptor, + p.attempt.AttemptID, p.paymentHash, errorDecryptor, ) switch { @@ -114,7 +115,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { case err == htlcswitch.ErrPaymentIDNotFound: log.Debugf("Payment ID %v for hash %x not found in "+ "the Switch, retrying.", p.attempt.AttemptID, - p.payment.PaymentHash) + p.paymentHash) err = p.failAttempt(err) if err != nil { @@ -155,7 +156,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // whether we should retry. if result.Error != nil { log.Errorf("Attempt to send payment %x failed: %v", - p.payment.PaymentHash, result.Error) + p.paymentHash, result.Error) err = p.failAttempt(result.Error) if err != nil { @@ -177,7 +178,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // We successfully got a payment result back from the switch. log.Debugf("Payment %x succeeded with pid=%v", - p.payment.PaymentHash, p.attempt.AttemptID) + p.paymentHash, p.attempt.AttemptID) // Report success to mission control. err = p.router.cfg.MissionControl.ReportPaymentSuccess( @@ -191,7 +192,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // In case of success we atomically store the db payment and // move the payment to the success state. err = p.router.cfg.Control.SettleAttempt( - p.payment.PaymentHash, p.attempt.AttemptID, + p.paymentHash, p.attempt.AttemptID, &channeldb.HTLCSettleInfo{ Preimage: result.Preimage, SettleTime: p.router.cfg.Clock.Now(), @@ -243,7 +244,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, // Mark the payment as failed because of the // timeout. err := p.router.cfg.Control.Fail( - p.payment.PaymentHash, channeldb.FailureReasonTimeout, + p.paymentHash, channeldb.FailureReasonTimeout, ) if err != nil { return lnwire.ShortChannelID{}, nil, err @@ -269,7 +270,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, rt, err := p.paySession.RequestRoute(uint32(p.currentHeight)) if err != nil { log.Warnf("Failed to find route for payment %x: %v", - p.payment.PaymentHash, err) + p.paymentHash, err) // Convert error to payment-level failure. failure := errorToPaymentFailure(err) @@ -278,7 +279,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, // any of the routes we've found, then mark the payment // as permanently failed. saveErr := p.router.cfg.Control.Fail( - p.payment.PaymentHash, failure, + p.paymentHash, failure, ) if saveErr != nil { return lnwire.ShortChannelID{}, nil, saveErr @@ -304,7 +305,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, // with the htlcAdd message that we send directly to the // switch. onionBlob, c, err := generateSphinxPacket( - rt, p.payment.PaymentHash[:], sessionKey, + rt, p.paymentHash[:], sessionKey, ) // With SendToRoute, it can happen that the route exceeds protocol @@ -313,10 +314,10 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, err == sphinx.ErrMaxRoutingInfoSizeExceeded { log.Debugf("Invalid route provided for payment %x: %v", - p.payment.PaymentHash, err) + p.paymentHash, err) controlErr := p.router.cfg.Control.Fail( - p.payment.PaymentHash, channeldb.FailureReasonError, + p.paymentHash, channeldb.FailureReasonError, ) if controlErr != nil { return lnwire.ShortChannelID{}, nil, controlErr @@ -338,7 +339,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, htlcAdd := &lnwire.UpdateAddHTLC{ Amount: rt.TotalAmount, Expiry: rt.TotalTimeLock, - PaymentHash: p.payment.PaymentHash, + PaymentHash: p.paymentHash, } copy(htlcAdd.OnionBlob[:], onionBlob) @@ -371,7 +372,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, // such that we can query the Switch for its whereabouts. The // route is needed to handle the result when it eventually // comes back. - err = p.router.cfg.Control.RegisterAttempt(p.payment.PaymentHash, p.attempt) + err = p.router.cfg.Control.RegisterAttempt(p.paymentHash, p.attempt) if err != nil { return lnwire.ShortChannelID{}, nil, err } @@ -384,7 +385,7 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, htlcAdd *lnwire.UpdateAddHTLC) error { log.Tracef("Attempting to send payment %x (pid=%v), "+ - "using route: %v", p.payment.PaymentHash, p.attempt.AttemptID, + "using route: %v", p.paymentHash, p.attempt.AttemptID, newLogClosure(func() string { return spew.Sdump(p.attempt.Route) }), @@ -400,12 +401,12 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, if err != nil { log.Errorf("Failed sending attempt %d for payment "+ "%x to switch: %v", p.attempt.AttemptID, - p.payment.PaymentHash, err) + p.paymentHash, err) return err } log.Debugf("Payment %x (pid=%v) successfully sent to switch, route: %v", - p.payment.PaymentHash, p.attempt.AttemptID, &p.attempt.Route) + p.paymentHash, p.attempt.AttemptID, &p.attempt.Route) return nil } @@ -426,14 +427,14 @@ func (p *paymentLifecycle) handleSendError(sendErr error) error { } log.Debugf("Payment %x failed: final_outcome=%v, raw_err=%v", - p.payment.PaymentHash, *reason, sendErr) + p.paymentHash, *reason, sendErr) // Mark the payment failed with no route. // // TODO(halseth): make payment codes for the actual reason we don't // continue path finding. err := p.router.cfg.Control.Fail( - p.payment.PaymentHash, *reason, + p.paymentHash, *reason, ) if err != nil { return err @@ -451,7 +452,7 @@ func (p *paymentLifecycle) failAttempt(sendError error) error { ) return p.router.cfg.Control.FailAttempt( - p.payment.PaymentHash, p.attempt.AttemptID, + p.paymentHash, p.attempt.AttemptID, failInfo, ) } diff --git a/routing/router.go b/routing/router.go index 5ef4dcaa37..581671c180 100644 --- a/routing/router.go +++ b/routing/router.go @@ -531,15 +531,8 @@ func (r *ChannelRouter) Start() error { // We create a dummy, empty payment session such that // we won't make another payment attempt when the // result for the in-flight attempt is received. - // - // PayAttemptTime doesn't need to be set, as there is - // only a single attempt. paySession := r.cfg.SessionSource.NewPaymentSessionEmpty() - lPayment := &LightningPayment{ - PaymentHash: payment.Info.PaymentHash, - } - // TODO(joostjager): For mpp, possibly relaunch multiple // in-flight htlcs here. var attempt *channeldb.HTLCAttemptInfo @@ -547,7 +540,13 @@ func (r *ChannelRouter) Start() error { attempt = &payment.Attempts[0] } - _, _, err := r.sendPayment(attempt, lPayment, paySession) + // We pass in a zero timeout value, to indicate we + // don't need it to timeout. It will stop immediately + // after the existing attempt has finished anyway. + _, _, err := r.sendPayment( + attempt, + payment.Info.PaymentHash, 0, paySession, + ) if err != nil { log.Errorf("Resuming payment with hash %v "+ "failed: %v.", payment.Info.PaymentHash, err) @@ -1639,9 +1638,15 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, return [32]byte{}, nil, err } + log.Tracef("Dispatching SendPayment for lightning payment: %v", + spewPayment(payment)) + // Since this is the first time this payment is being made, we pass nil // for the existing attempt. - return r.sendPayment(nil, payment, paySession) + return r.sendPayment( + nil, payment.PaymentHash, + payment.PayAttemptTimeout, paySession, + ) } // SendPaymentAsync is the non-blocking version of SendPayment. The payment @@ -1658,7 +1663,13 @@ func (r *ChannelRouter) SendPaymentAsync(payment *LightningPayment) error { go func() { defer r.wg.Done() - _, _, err := r.sendPayment(nil, payment, paySession) + log.Tracef("Dispatching SendPayment for lightning payment: %v", + spewPayment(payment)) + + _, _, err := r.sendPayment( + nil, payment.PaymentHash, + payment.PayAttemptTimeout, paySession, + ) if err != nil { log.Errorf("Payment with hash %x failed: %v", payment.PaymentHash, err) @@ -1668,6 +1679,28 @@ func (r *ChannelRouter) SendPaymentAsync(payment *LightningPayment) error { return nil } +// spewPayment returns a log closures that provides a spewed string +// representation of the passed payment. +func spewPayment(payment *LightningPayment) logClosure { + return newLogClosure(func() string { + // Make a copy of the payment with a nilled Curve + // before spewing. + var routeHints [][]zpay32.HopHint + for _, routeHint := range payment.RouteHints { + var hopHints []zpay32.HopHint + for _, hopHint := range routeHint { + h := hopHint.Copy() + h.NodeID.Curve = nil + hopHints = append(hopHints, h) + } + routeHints = append(routeHints, hopHints) + } + p := *payment + p.RouteHints = routeHints + return spew.Sdump(p) + }) +} + // preparePayment creates the payment session and registers the payment with the // control tower. func (r *ChannelRouter) preparePayment(payment *LightningPayment) ( @@ -1726,20 +1759,17 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( return [32]byte{}, err } - // Create a (mostly) dummy payment, as the created payment session is - // not going to do path finding. - // TODO(halseth): sendPayment doesn't really need LightningPayment, make - // it take just needed fields instead. - // - // PayAttemptTime doesn't need to be set, as there is only a single - // attempt. - payment := &LightningPayment{ - PaymentHash: hash, - } + log.Tracef("Dispatching SendToRoute for hash %v: %v", + hash, newLogClosure(func() string { + return spew.Sdump(route) + }), + ) - // Since this is the first time this payment is being made, we pass nil - // for the existing attempt. - preimage, _, err := r.sendPayment(nil, payment, paySession) + // We set the timeout to a zero value, indicating the payment shouldn't + // timeout. It is only a single attempt, so no more attempts will be + // done anyway. Since this is the first time this payment is being + // made, we pass nil for the existing attempt. + preimage, _, err := r.sendPayment(nil, hash, 0, paySession) if err != nil { // SendToRoute should return a structured error. In case the // provided route fails, payment lifecycle will return a @@ -1759,13 +1789,13 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( return preimage, nil } -// sendPayment attempts to send a payment as described within the passed -// LightningPayment. This function is blocking and will return either: when the -// payment is successful, or all candidates routes have been attempted and -// resulted in a failed payment. If the payment succeeds, then a non-nil Route -// will be returned which describes the path the successful payment traversed -// within the network to reach the destination. Additionally, the payment -// preimage will also be returned. +// sendPayment attempts to send a payment to the passed payment hash. This +// function is blocking and will return either: when the payment is successful, +// or all candidates routes have been attempted and resulted in a failed +// payment. If the payment succeeds, then a non-nil Route will be returned +// which describes the path the successful payment traversed within the network +// to reach the destination. Additionally, the payment preimage will also be +// returned. // // The existing attempt argument should be set to nil if this is a payment that // haven't had any payment attempt sent to the switch yet. If it has had an @@ -1777,28 +1807,9 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( // the ControlTower. func (r *ChannelRouter) sendPayment( existingAttempt *channeldb.HTLCAttemptInfo, - payment *LightningPayment, paySession PaymentSession) ( - [32]byte, *route.Route, error) { - - log.Tracef("Dispatching route for lightning payment: %v", - newLogClosure(func() string { - // Make a copy of the payment with a nilled Curve - // before spewing. - var routeHints [][]zpay32.HopHint - for _, routeHint := range payment.RouteHints { - var hopHints []zpay32.HopHint - for _, hopHint := range routeHint { - h := hopHint.Copy() - h.NodeID.Curve = nil - hopHints = append(hopHints, h) - } - routeHints = append(routeHints, hopHints) - } - p := *payment - p.RouteHints = routeHints - return spew.Sdump(p) - }), - ) + paymentHash lntypes.Hash, + timeout time.Duration, + paySession PaymentSession) ([32]byte, *route.Route, error) { // We'll also fetch the current block height so we can properly // calculate the required HTLC time locks within the route. @@ -1811,7 +1822,7 @@ func (r *ChannelRouter) sendPayment( // can resume the payment from the current state. p := &paymentLifecycle{ router: r, - payment: payment, + paymentHash: paymentHash, paySession: paySession, currentHeight: currentHeight, attempt: existingAttempt, @@ -1822,8 +1833,8 @@ func (r *ChannelRouter) sendPayment( // If a timeout is specified, create a timeout channel. If no timeout is // specified, the channel is left nil and will never abort the payment // loop. - if payment.PayAttemptTimeout != 0 { - p.timeoutChan = time.After(payment.PayAttemptTimeout) + if timeout != 0 { + p.timeoutChan = time.After(timeout) } return p.resumePayment() From 00903ef9f51f0d10636e7381332dba48a6d7a1c9 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:22 +0200 Subject: [PATCH 359/562] routing/payment_session: make RequestRoute take max amt, fee limit and active shards In preparation for doing pathfinding for routes sending a value less than the total payment amount, we let the payment session take the max amount to send and the fee limit as arguments to RequestRoute. --- routing/mock_test.go | 4 +++- routing/payment_lifecycle.go | 6 +++++- routing/payment_session.go | 19 +++++++++++++------ routing/payment_session_test.go | 6 +++++- routing/router.go | 25 ++++++++++++++++++------- 5 files changed, 44 insertions(+), 16 deletions(-) diff --git a/routing/mock_test.go b/routing/mock_test.go index 64a1e4f655..c6a780bb57 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -122,7 +122,9 @@ type mockPaymentSession struct { var _ PaymentSession = (*mockPaymentSession)(nil) -func (m *mockPaymentSession) RequestRoute(height uint32) (*route.Route, error) { +func (m *mockPaymentSession) RequestRoute(_, _ lnwire.MilliSatoshi, + _, height uint32) (*route.Route, error) { + if len(m.routes) == 0 { return nil, fmt.Errorf("no routes") } diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index a0cb566a61..f153d4b64d 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -31,6 +31,8 @@ func (e errNoRoute) Error() string { // needed to resume if from any point. type paymentLifecycle struct { router *ChannelRouter + totalAmount lnwire.MilliSatoshi + feeLimit lnwire.MilliSatoshi paymentHash lntypes.Hash paySession PaymentSession timeoutChan <-chan time.Time @@ -267,7 +269,9 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, } // Create a new payment attempt from the given payment session. - rt, err := p.paySession.RequestRoute(uint32(p.currentHeight)) + rt, err := p.paySession.RequestRoute( + p.totalAmount, p.feeLimit, 0, uint32(p.currentHeight), + ) if err != nil { log.Warnf("Failed to find route for payment %x: %v", p.paymentHash, err) diff --git a/routing/payment_session.go b/routing/payment_session.go index fda93536ee..a5c0426673 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -23,8 +23,14 @@ var ( // information learned during the previous attempts. type PaymentSession interface { // RequestRoute returns the next route to attempt for routing the - // specified HTLC payment to the target node. - RequestRoute(height uint32) (*route.Route, error) + // specified HTLC payment to the target node. The returned route should + // carry at most maxAmt to the target node, and pay at most feeLimit in + // fees. It can carry less if the payment is MPP. The activeShards + // argument should be set to instruct the payment session about the + // number of in flight HTLCS for the payment, such that it can choose + // splitting strategy accordingly. + RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, + activeShards, height uint32) (*route.Route, error) } // paymentSession is used during an HTLC routings session to prune the local @@ -59,7 +65,8 @@ type paymentSession struct { // // NOTE: This function is safe for concurrent access. // NOTE: Part of the PaymentSession interface. -func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) { +func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, + activeShards, height uint32) (*route.Route, error) { switch { @@ -94,7 +101,7 @@ func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) { restrictions := &RestrictParams{ ProbabilitySource: ss.MissionControl.GetProbability, - FeeLimit: p.payment.FeeLimit, + FeeLimit: feeLimit, OutgoingChannelID: p.payment.OutgoingChannelID, LastHop: p.payment.LastHop, CltvLimit: cltvLimit, @@ -124,7 +131,7 @@ func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) { }, restrictions, &ss.PathFindingConfig, ss.SelfNode.PubKeyBytes, p.payment.Target, - p.payment.Amount, finalHtlcExpiry, + maxAmt, finalHtlcExpiry, ) if err != nil { return nil, err @@ -136,7 +143,7 @@ func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) { route, err := newRoute( sourceVertex, path, height, finalHopParams{ - amt: p.payment.Amount, + amt: maxAmt, cltvDelta: finalCltvDelta, records: p.payment.DestCustomRecords, paymentAddr: p.payment.PaymentAddr, diff --git a/routing/payment_session_test.go b/routing/payment_session_test.go index 6d795b89d7..a916580438 100644 --- a/routing/payment_session_test.go +++ b/routing/payment_session_test.go @@ -50,6 +50,8 @@ func TestRequestRoute(t *testing.T) { payment := &LightningPayment{ CltvLimit: cltvLimit, FinalCLTVDelta: finalCltvDelta, + Amount: 1000, + FeeLimit: 1000, } session := &paymentSession{ @@ -63,7 +65,9 @@ func TestRequestRoute(t *testing.T) { pathFinder: findPath, } - route, err := session.RequestRoute(height) + route, err := session.RequestRoute( + payment.Amount, payment.FeeLimit, 0, height, + ) if err != nil { t.Fatal(err) } diff --git a/routing/router.go b/routing/router.go index 581671c180..18e1689b9a 100644 --- a/routing/router.go +++ b/routing/router.go @@ -542,9 +542,11 @@ func (r *ChannelRouter) Start() error { // We pass in a zero timeout value, to indicate we // don't need it to timeout. It will stop immediately - // after the existing attempt has finished anyway. + // after the existing attempt has finished anyway. We + // also set a zero fee limit, as no more routes should + // be tried. _, _, err := r.sendPayment( - attempt, + attempt, payment.Info.Value, 0, payment.Info.PaymentHash, 0, paySession, ) if err != nil { @@ -1644,7 +1646,7 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, // Since this is the first time this payment is being made, we pass nil // for the existing attempt. return r.sendPayment( - nil, payment.PaymentHash, + nil, payment.Amount, payment.FeeLimit, payment.PaymentHash, payment.PayAttemptTimeout, paySession, ) } @@ -1667,8 +1669,9 @@ func (r *ChannelRouter) SendPaymentAsync(payment *LightningPayment) error { spewPayment(payment)) _, _, err := r.sendPayment( - nil, payment.PaymentHash, - payment.PayAttemptTimeout, paySession, + nil, payment.Amount, payment.FeeLimit, + payment.PaymentHash, payment.PayAttemptTimeout, + paySession, ) if err != nil { log.Errorf("Payment with hash %x failed: %v", @@ -1769,7 +1772,13 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( // timeout. It is only a single attempt, so no more attempts will be // done anyway. Since this is the first time this payment is being // made, we pass nil for the existing attempt. - preimage, _, err := r.sendPayment(nil, hash, 0, paySession) + // We pass the route receiver amount as the total payment amount such + // that the payment loop will request a route for this amount. As fee + // limit we pass the route's total fees, since we already know this is + // the route that is going to be used. + preimage, _, err := r.sendPayment( + nil, amt, route.TotalFees(), hash, 0, paySession, + ) if err != nil { // SendToRoute should return a structured error. In case the // provided route fails, payment lifecycle will return a @@ -1807,7 +1816,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( // the ControlTower. func (r *ChannelRouter) sendPayment( existingAttempt *channeldb.HTLCAttemptInfo, - paymentHash lntypes.Hash, + totalAmt, feeLimit lnwire.MilliSatoshi, paymentHash lntypes.Hash, timeout time.Duration, paySession PaymentSession) ([32]byte, *route.Route, error) { @@ -1822,6 +1831,8 @@ func (r *ChannelRouter) sendPayment( // can resume the payment from the current state. p := &paymentLifecycle{ router: r, + totalAmount: totalAmt, + feeLimit: feeLimit, paymentHash: paymentHash, paySession: paySession, currentHeight: currentHeight, From e61fcda6a946720aa3dc6b31ba4ccfabd8f4ee45 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:23 +0200 Subject: [PATCH 360/562] routing/payment_lifecycle: move requesting route out of createNewPaymentAttempt To prepare for having more than one payment attempt in flight at the same time, we decouple fetching the next route from crafting the payment attempt. --- routing/payment_lifecycle.go | 131 ++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index f153d4b64d..49bf8dfd6b 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -51,7 +51,72 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // If this payment had no existing payment attempt, we create // and send one now. if p.attempt == nil { - firstHop, htlcAdd, err := p.createNewPaymentAttempt() + // Before we attempt this next payment, we'll check to see if either + // we've gone past the payment attempt timeout, or the router is + // exiting. In either case, we'll stop this payment attempt short. If a + // timeout is not applicable, timeoutChan will be nil. + select { + case <-p.timeoutChan: + // Mark the payment as failed because of the + // timeout. + err := p.router.cfg.Control.Fail( + p.paymentHash, channeldb.FailureReasonTimeout, + ) + if err != nil { + return [32]byte{}, nil, err + } + + errStr := fmt.Sprintf("payment attempt not completed " + + "before timeout") + + return [32]byte{}, nil, newErr(ErrPaymentAttemptTimeout, errStr) + + // The payment will be resumed from the current state + // after restart. + case <-p.router.quit: + return [32]byte{}, nil, ErrRouterShuttingDown + + // Fall through if we haven't hit our time limit or are + // exiting. + default: + } + + // Create a new payment attempt from the given payment session. + rt, err := p.paySession.RequestRoute( + p.totalAmount, p.feeLimit, 0, uint32(p.currentHeight), + ) + if err != nil { + log.Warnf("Failed to find route for payment %x: %v", + p.paymentHash, err) + + // Convert error to payment-level failure. + failure := errorToPaymentFailure(err) + + // If we're unable to successfully make a payment using + // any of the routes we've found, then mark the payment + // as permanently failed. + saveErr := p.router.cfg.Control.Fail( + p.paymentHash, failure, + ) + if saveErr != nil { + return [32]byte{}, nil, saveErr + } + + // If there was an error already recorded for this + // payment, we'll return that. + if p.lastError != nil { + return [32]byte{}, nil, errNoRoute{lastError: p.lastError} + } + + // Terminal state, return. + return [32]byte{}, nil, err + } + + // Using the route received from the payment session, + // create a new shard to send. + firstHop, htlcAdd, err := p.createNewPaymentAttempt( + rt, + ) if err != nil { return [32]byte{}, nil, err } @@ -234,71 +299,9 @@ func errorToPaymentFailure(err error) channeldb.FailureReason { // createNewPaymentAttempt creates and stores a new payment attempt to the // database. -func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, +func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) (lnwire.ShortChannelID, *lnwire.UpdateAddHTLC, error) { - // Before we attempt this next payment, we'll check to see if either - // we've gone past the payment attempt timeout, or the router is - // exiting. In either case, we'll stop this payment attempt short. If a - // timeout is not applicable, timeoutChan will be nil. - select { - case <-p.timeoutChan: - // Mark the payment as failed because of the - // timeout. - err := p.router.cfg.Control.Fail( - p.paymentHash, channeldb.FailureReasonTimeout, - ) - if err != nil { - return lnwire.ShortChannelID{}, nil, err - } - - errStr := fmt.Sprintf("payment attempt not completed " + - "before timeout") - - return lnwire.ShortChannelID{}, nil, - newErr(ErrPaymentAttemptTimeout, errStr) - - case <-p.router.quit: - // The payment will be resumed from the current state - // after restart. - return lnwire.ShortChannelID{}, nil, ErrRouterShuttingDown - - default: - // Fall through if we haven't hit our time limit, or - // are expiring. - } - - // Create a new payment attempt from the given payment session. - rt, err := p.paySession.RequestRoute( - p.totalAmount, p.feeLimit, 0, uint32(p.currentHeight), - ) - if err != nil { - log.Warnf("Failed to find route for payment %x: %v", - p.paymentHash, err) - - // Convert error to payment-level failure. - failure := errorToPaymentFailure(err) - - // If we're unable to successfully make a payment using - // any of the routes we've found, then mark the payment - // as permanently failed. - saveErr := p.router.cfg.Control.Fail( - p.paymentHash, failure, - ) - if saveErr != nil { - return lnwire.ShortChannelID{}, nil, saveErr - } - - // If there was an error already recorded for this - // payment, we'll return that. - if p.lastError != nil { - return lnwire.ShortChannelID{}, nil, - errNoRoute{lastError: p.lastError} - } - // Terminal state, return. - return lnwire.ShortChannelID{}, nil, err - } - // Generate a new key to be used for this attempt. sessionKey, err := generateNewSessionKey() if err != nil { From 362072139129e8d6aa487e5e6460a3d57df21759 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:23 +0200 Subject: [PATCH 361/562] routing/payment_lifecycle: move attempt DB checkpointing into payment loop To prepare for multiple in flight payment attempts, we move checkpointing the payment attempt out of createNewPaymentAttempt and into the main payment lifecycle loop. We'll attempt to move all calls to the DB via the ControlTower into this loop, so we can more easily handle them in sequence. --- routing/payment_lifecycle.go | 45 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 49bf8dfd6b..7ef02eeb52 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -114,12 +114,24 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // Using the route received from the payment session, // create a new shard to send. - firstHop, htlcAdd, err := p.createNewPaymentAttempt( + firstHop, htlcAdd, attempt, err := p.createNewPaymentAttempt( rt, ) if err != nil { return [32]byte{}, nil, err } + p.attempt = attempt + + // Before sending this HTLC to the switch, we checkpoint the + // fresh paymentID and route to the DB. This lets us know on + // startup the ID of the payment that we attempted to send, + // such that we can query the Switch for its whereabouts. The + // route is needed to handle the result when it eventually + // comes back. + err = p.router.cfg.Control.RegisterAttempt(p.paymentHash, attempt) + if err != nil { + return [32]byte{}, nil, err + } // Now that the attempt is created and checkpointed to // the DB, we send it. @@ -297,15 +309,15 @@ func errorToPaymentFailure(err error) channeldb.FailureReason { return channeldb.FailureReasonError } -// createNewPaymentAttempt creates and stores a new payment attempt to the -// database. -func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) (lnwire.ShortChannelID, - *lnwire.UpdateAddHTLC, error) { +// createNewPaymentAttempt creates a new payment attempt from the given route. +func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) ( + lnwire.ShortChannelID, *lnwire.UpdateAddHTLC, + *channeldb.HTLCAttemptInfo, error) { // Generate a new key to be used for this attempt. sessionKey, err := generateNewSessionKey() if err != nil { - return lnwire.ShortChannelID{}, nil, err + return lnwire.ShortChannelID{}, nil, nil, err } // Generate the raw encoded sphinx packet to be included along @@ -327,13 +339,13 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) (lnwire.Shor p.paymentHash, channeldb.FailureReasonError, ) if controlErr != nil { - return lnwire.ShortChannelID{}, nil, controlErr + return lnwire.ShortChannelID{}, nil, nil, controlErr } } // In any case, don't continue if there is an error. if err != nil { - return lnwire.ShortChannelID{}, nil, err + return lnwire.ShortChannelID{}, nil, nil, err } // Update our cached circuit with the newly generated @@ -361,30 +373,19 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) (lnwire.Shor // this HTLC. attemptID, err := p.router.cfg.NextPaymentID() if err != nil { - return lnwire.ShortChannelID{}, nil, err + return lnwire.ShortChannelID{}, nil, nil, err } // We now have all the information needed to populate // the current attempt information. - p.attempt = &channeldb.HTLCAttemptInfo{ + attempt := &channeldb.HTLCAttemptInfo{ AttemptID: attemptID, AttemptTime: p.router.cfg.Clock.Now(), SessionKey: sessionKey, Route: *rt, } - // Before sending this HTLC to the switch, we checkpoint the - // fresh attemptID and route to the DB. This lets us know on - // startup the ID of the payment that we attempted to send, - // such that we can query the Switch for its whereabouts. The - // route is needed to handle the result when it eventually - // comes back. - err = p.router.cfg.Control.RegisterAttempt(p.paymentHash, p.attempt) - if err != nil { - return lnwire.ShortChannelID{}, nil, err - } - - return firstHop, htlcAdd, nil + return firstHop, htlcAdd, attempt, nil } // sendPaymentAttempt attempts to send the current attempt to the switch. From 4485e8261f1eb8e1daa64b9c8d83f4674e824528 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:23 +0200 Subject: [PATCH 362/562] routing/payment_lifecycle: move Fail call to payment loop In our quest to move calls to the ControlTower into the main payment lifecycle loop, we move the edge case of a too long route out of createNewPaymentAttempt. --- routing/payment_lifecycle.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 7ef02eeb52..f2c533ec67 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -117,9 +117,27 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { firstHop, htlcAdd, attempt, err := p.createNewPaymentAttempt( rt, ) + // With SendToRoute, it can happen that the route exceeds protocol + // constraints. Mark the payment as failed with an internal error. + if err == route.ErrMaxRouteHopsExceeded || + err == sphinx.ErrMaxRoutingInfoSizeExceeded { + + log.Debugf("Invalid route provided for payment %x: %v", + p.paymentHash, err) + + controlErr := p.router.cfg.Control.Fail( + p.paymentHash, channeldb.FailureReasonError, + ) + if controlErr != nil { + return [32]byte{}, nil, controlErr + } + } + + // In any case, don't continue if there is an error. if err != nil { return [32]byte{}, nil, err } + p.attempt = attempt // Before sending this HTLC to the switch, we checkpoint the @@ -326,24 +344,6 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) ( onionBlob, c, err := generateSphinxPacket( rt, p.paymentHash[:], sessionKey, ) - - // With SendToRoute, it can happen that the route exceeds protocol - // constraints. Mark the payment as failed with an internal error. - if err == route.ErrMaxRouteHopsExceeded || - err == sphinx.ErrMaxRoutingInfoSizeExceeded { - - log.Debugf("Invalid route provided for payment %x: %v", - p.paymentHash, err) - - controlErr := p.router.cfg.Control.Fail( - p.paymentHash, channeldb.FailureReasonError, - ) - if controlErr != nil { - return lnwire.ShortChannelID{}, nil, nil, controlErr - } - } - - // In any case, don't continue if there is an error. if err != nil { return lnwire.ShortChannelID{}, nil, nil, err } From 79227bab3a05a25418c7b76470d1ed42293a7ad3 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:23 +0200 Subject: [PATCH 363/562] routing/route: define route.ReceiverAmt() method --- routing/route/route.go | 11 ++++++++++- routing/route/route_test.go | 23 ++++++++++++++++++++--- routing/router.go | 2 +- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/routing/route/route.go b/routing/route/route.go index f4de728fc7..31fa3bf50d 100644 --- a/routing/route/route.go +++ b/routing/route/route.go @@ -308,7 +308,16 @@ func (r *Route) TotalFees() lnwire.MilliSatoshi { return 0 } - return r.TotalAmount - r.Hops[len(r.Hops)-1].AmtToForward + return r.TotalAmount - r.ReceiverAmt() +} + +// ReceiverAmt is the amount received by the final hop of this route. +func (r *Route) ReceiverAmt() lnwire.MilliSatoshi { + if len(r.Hops) == 0 { + return 0 + } + + return r.Hops[len(r.Hops)-1].AmtToForward } // NewRouteFromHops creates a new Route structure from the minimally required diff --git a/routing/route/route_test.go b/routing/route/route_test.go index 2095430b8c..991175f493 100644 --- a/routing/route/route_test.go +++ b/routing/route/route_test.go @@ -20,15 +20,24 @@ var ( func TestRouteTotalFees(t *testing.T) { t.Parallel() - // Make sure empty route returns a 0 fee. + // Make sure empty route returns a 0 fee, and zero amount. r := &Route{} if r.TotalFees() != 0 { t.Fatalf("expected 0 fees, got %v", r.TotalFees()) } + if r.ReceiverAmt() != 0 { + t.Fatalf("expected 0 amt, got %v", r.ReceiverAmt()) + } + + // Make sure empty route won't be allowed in the constructor. + amt := lnwire.MilliSatoshi(1000) + _, err := NewRouteFromHops(amt, 100, Vertex{}, []*Hop{}) + if err != ErrNoRouteHopsProvided { + t.Fatalf("expected ErrNoRouteHopsProvided, got %v", err) + } // For one-hop routes the fee should be 0, since the last node will // receive the full amount. - amt := lnwire.MilliSatoshi(1000) hops := []*Hop{ { PubKeyBytes: Vertex{}, @@ -37,7 +46,7 @@ func TestRouteTotalFees(t *testing.T) { AmtToForward: amt, }, } - r, err := NewRouteFromHops(amt, 100, Vertex{}, hops) + r, err = NewRouteFromHops(amt, 100, Vertex{}, hops) if err != nil { t.Fatal(err) } @@ -46,6 +55,10 @@ func TestRouteTotalFees(t *testing.T) { t.Fatalf("expected 0 fees, got %v", r.TotalFees()) } + if r.ReceiverAmt() != amt { + t.Fatalf("expected %v amt, got %v", amt, r.ReceiverAmt()) + } + // Append the route with a node, making the first one take a fee. fee := lnwire.MilliSatoshi(100) hops = append(hops, &Hop{ @@ -64,6 +77,10 @@ func TestRouteTotalFees(t *testing.T) { if r.TotalFees() != fee { t.Fatalf("expected %v fees, got %v", fee, r.TotalFees()) } + + if r.ReceiverAmt() != amt-fee { + t.Fatalf("expected %v amt, got %v", amt-fee, r.ReceiverAmt()) + } } var ( diff --git a/routing/router.go b/routing/router.go index 18e1689b9a..9595b0054e 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1746,7 +1746,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( paySession := r.cfg.SessionSource.NewPaymentSessionForRoute(route) // Calculate amount paid to receiver. - amt := route.TotalAmount - route.TotalFees() + amt := route.ReceiverAmt() // Record this payment hash with the ControlTower, ensuring it is not // already in-flight. From 6d9f9c31f42b5fe7c51f767b5b62a0f74fa0aa54 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:23 +0200 Subject: [PATCH 364/562] routing/router_test: remove preimage overwrite The test case's preimage was (mistakenly) overwritten after crafting the lightning payment, causing the parts of the testcases use the same preimage causing problems when we are using the payment hash and preimage in the mock control tower to distinguish paymennts. --- routing/router_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/routing/router_test.go b/routing/router_test.go index 42020b7ead..d8550ac735 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -3025,8 +3025,6 @@ func TestRouterPaymentStateMachine(t *testing.T) { PaymentHash: payHash, } - copy(preImage[:], bytes.Repeat([]byte{9}, 32)) - router.cfg.SessionSource = &mockPaymentSessionSource{ routes: test.routes, } From e1f4d89ad924decd22b81963021baf4ea07bdfcd Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:23 +0200 Subject: [PATCH 365/562] routing: add FetchPayment method to ControlTower This method is used to fetch a payment and all HTLC attempt that have been made for that payment. It will both be used to resume inflight attempts, and to fetch the final outcome of previous attempts. We also update the the mock control tower to mimic the real control tower, by letting it track multiple HTLC attempts for a given payment hash, laying the groundwork for later enabling it for MPP. --- routing/control_tower.go | 11 +++ routing/mock_test.go | 181 +++++++++++++++++++++++++++++++++------ 2 files changed, 168 insertions(+), 24 deletions(-) diff --git a/routing/control_tower.go b/routing/control_tower.go index 5ade611cc8..da7d4d2bc2 100644 --- a/routing/control_tower.go +++ b/routing/control_tower.go @@ -34,6 +34,10 @@ type ControlTower interface { // FailAttempt marks the given payment attempt failed. FailAttempt(lntypes.Hash, uint64, *channeldb.HTLCFailInfo) error + // FetchPayment fetches the payment corresponding to the given payment + // hash. + FetchPayment(paymentHash lntypes.Hash) (*channeldb.MPPayment, error) + // Fail transitions a payment into the Failed state, and records the // ultimate reason the payment failed. Note that this should only be // called when all active active attempts are already failed. After @@ -132,6 +136,13 @@ func (p *controlTower) FailAttempt(paymentHash lntypes.Hash, return p.db.FailAttempt(paymentHash, attemptID, failInfo) } +// FetchPayment fetches the payment corresponding to the given payment hash. +func (p *controlTower) FetchPayment(paymentHash lntypes.Hash) ( + *channeldb.MPPayment, error) { + + return p.db.FetchPayment(paymentHash) +} + // createSuccessResult creates a success result to send to subscribers. func createSuccessResult(htlcs []channeldb.HTLCAttempt) *PaymentResult { // Extract any preimage from the list of HTLCs. diff --git a/routing/mock_test.go b/routing/mock_test.go index c6a780bb57..c66c70b1e4 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -188,9 +188,15 @@ type failArgs struct { reason channeldb.FailureReason } +type testPayment struct { + info channeldb.PaymentCreationInfo + attempts []channeldb.HTLCAttempt +} + type mockControlTower struct { - inflights map[lntypes.Hash]channeldb.InFlightPayment + payments map[lntypes.Hash]*testPayment successful map[lntypes.Hash]struct{} + failed map[lntypes.Hash]channeldb.FailureReason init chan initArgs register chan registerArgs @@ -205,8 +211,9 @@ var _ ControlTower = (*mockControlTower)(nil) func makeMockControlTower() *mockControlTower { return &mockControlTower{ - inflights: make(map[lntypes.Hash]channeldb.InFlightPayment), + payments: make(map[lntypes.Hash]*testPayment), successful: make(map[lntypes.Hash]struct{}), + failed: make(map[lntypes.Hash]channeldb.FailureReason), } } @@ -220,18 +227,22 @@ func (m *mockControlTower) InitPayment(phash lntypes.Hash, m.init <- initArgs{c} } + // Don't allow re-init a successful payment. if _, ok := m.successful[phash]; ok { - return fmt.Errorf("already successful") + return channeldb.ErrAlreadyPaid } - _, ok := m.inflights[phash] - if ok { - return fmt.Errorf("in flight") + _, failed := m.failed[phash] + _, ok := m.payments[phash] + + // If the payment is known, only allow re-init if failed. + if ok && !failed { + return channeldb.ErrPaymentInFlight } - m.inflights[phash] = channeldb.InFlightPayment{ - Info: c, - Attempts: make([]channeldb.HTLCAttemptInfo, 0), + delete(m.failed, phash) + m.payments[phash] = &testPayment{ + info: *c, } return nil @@ -247,13 +258,24 @@ func (m *mockControlTower) RegisterAttempt(phash lntypes.Hash, m.register <- registerArgs{a} } - p, ok := m.inflights[phash] + // Cannot register attempts for successful or failed payments. + if _, ok := m.successful[phash]; ok { + return channeldb.ErrPaymentAlreadySucceeded + } + + if _, ok := m.failed[phash]; ok { + return channeldb.ErrPaymentAlreadyFailed + } + + p, ok := m.payments[phash] if !ok { - return fmt.Errorf("not in flight") + return channeldb.ErrPaymentNotInitiated } - p.Attempts = append(p.Attempts, *a) - m.inflights[phash] = p + p.attempts = append(p.attempts, channeldb.HTLCAttempt{ + HTLCAttemptInfo: *a, + }) + m.payments[phash] = p return nil } @@ -268,9 +290,69 @@ func (m *mockControlTower) SettleAttempt(phash lntypes.Hash, m.success <- successArgs{settleInfo.Preimage} } - delete(m.inflights, phash) - m.successful[phash] = struct{}{} - return nil + // Only allow setting attempts for payments not yet succeeded or + // failed. + if _, ok := m.successful[phash]; ok { + return channeldb.ErrPaymentAlreadySucceeded + } + + if _, ok := m.failed[phash]; ok { + return channeldb.ErrPaymentAlreadyFailed + } + + p, ok := m.payments[phash] + if !ok { + return channeldb.ErrPaymentNotInitiated + } + + // Find the attempt with this pid, and set the settle info. + for i, a := range p.attempts { + if a.AttemptID != pid { + continue + } + + p.attempts[i].Settle = settleInfo + + // Mark the payment successful on first settled attempt. + m.successful[phash] = struct{}{} + return nil + } + + return fmt.Errorf("pid not found") +} + +func (m *mockControlTower) FailAttempt(phash lntypes.Hash, pid uint64, + failInfo *channeldb.HTLCFailInfo) error { + + m.Lock() + defer m.Unlock() + + // Only allow failing attempts for payments not yet succeeded or + // failed. + if _, ok := m.successful[phash]; ok { + return channeldb.ErrPaymentAlreadySucceeded + } + + if _, ok := m.failed[phash]; ok { + return channeldb.ErrPaymentAlreadyFailed + } + + p, ok := m.payments[phash] + if !ok { + return channeldb.ErrPaymentNotInitiated + } + + // Find the attempt with this pid, and set the failure info. + for i, a := range p.attempts { + if a.AttemptID != pid { + continue + } + + p.attempts[i].Failure = failInfo + return nil + } + + return fmt.Errorf("pid not found") } func (m *mockControlTower) Fail(phash lntypes.Hash, @@ -283,10 +365,50 @@ func (m *mockControlTower) Fail(phash lntypes.Hash, m.fail <- failArgs{reason} } - delete(m.inflights, phash) + // Cannot fail already successful or failed payments. + if _, ok := m.successful[phash]; ok { + return channeldb.ErrPaymentAlreadySucceeded + } + + if _, ok := m.failed[phash]; ok { + return channeldb.ErrPaymentAlreadyFailed + } + + if _, ok := m.payments[phash]; !ok { + return channeldb.ErrPaymentNotInitiated + } + + m.failed[phash] = reason + return nil } +func (m *mockControlTower) FetchPayment(phash lntypes.Hash) ( + *channeldb.MPPayment, error) { + + m.Lock() + defer m.Unlock() + + p, ok := m.payments[phash] + if !ok { + return nil, channeldb.ErrPaymentNotInitiated + } + + mp := &channeldb.MPPayment{ + Info: &p.info, + } + + reason, ok := m.failed[phash] + if ok { + mp.FailureReason = &reason + } + + // Return a copy of the current attempts. + mp.HTLCs = append(mp.HTLCs, p.attempts...) + + return mp, nil +} + func (m *mockControlTower) FetchInFlightPayments() ( []*channeldb.InFlightPayment, error) { @@ -297,8 +419,25 @@ func (m *mockControlTower) FetchInFlightPayments() ( m.fetchInFlight <- struct{}{} } + // In flight are all payments not successful or failed. var fl []*channeldb.InFlightPayment - for _, ifl := range m.inflights { + for hash, p := range m.payments { + if _, ok := m.successful[hash]; ok { + continue + } + if _, ok := m.failed[hash]; ok { + continue + } + + var attempts []channeldb.HTLCAttemptInfo + for _, a := range p.attempts { + attempts = append(attempts, a.HTLCAttemptInfo) + } + ifl := channeldb.InFlightPayment{ + Info: &p.info, + Attempts: attempts, + } + fl = append(fl, &ifl) } @@ -310,9 +449,3 @@ func (m *mockControlTower) SubscribePayment(paymentHash lntypes.Hash) ( return false, nil, errors.New("not implemented") } - -func (m *mockControlTower) FailAttempt(hash lntypes.Hash, pid uint64, - failInfo *channeldb.HTLCFailInfo) error { - - return nil -} From 9bcf41d40116eac9f65d852c3c1501f3ddd8a5df Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:24 +0200 Subject: [PATCH 366/562] channeldb: make FailureReason Error() --- channeldb/payments.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/channeldb/payments.go b/channeldb/payments.go index a1ea379b2e..adf5cf8c23 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -123,7 +123,12 @@ const ( // LocalLiquidityInsufficient, RemoteCapacityInsufficient. ) -// String returns a human readable FailureReason +// Error returns a human readable error string for the FailureReason. +func (r FailureReason) Error() string { + return r.String() +} + +// String returns a human readable FailureReason. func (r FailureReason) String() string { switch r { case FailureReasonTimeout: From bcca1ab82137e57c2e4868a52f513d3ad2e5d5b3 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:24 +0200 Subject: [PATCH 367/562] routing/payment_lifeycle: remove payment level attempt and circuit We replace the cached attempt, and instead use the control tower (database) to fetch any in-flight attempt. This is done as a preparation for having multiple attempts in flight. In addition we remove the cached circuit, as it won't be applicable when multiple shards are in flight. Instead of tracking the attemp we consult the database on every iteration, and pick up any existing attempt. This also let us avoid having to pass in the existing attempts from the payment loop, as we just fetch them direclty. --- routing/payment_lifecycle.go | 137 +++++++++++++++++++++-------------- routing/router.go | 25 ++----- 2 files changed, 90 insertions(+), 72 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index f2c533ec67..4deddefe06 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -37,8 +37,6 @@ type paymentLifecycle struct { paySession PaymentSession timeoutChan <-chan time.Time currentHeight int32 - attempt *channeldb.HTLCAttemptInfo - circuit *sphinx.Circuit lastError error } @@ -47,10 +45,52 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // We'll continue until either our payment succeeds, or we encounter a // critical error during path finding. for { + // We start every iteration by fetching the lastest state of + // the payment from the ControlTower. This ensures that we will + // act on the latest available information, whether we are + // resuming an existing payment or just sent a new attempt. + payment, err := p.router.cfg.Control.FetchPayment( + p.paymentHash, + ) + if err != nil { + return [32]byte{}, nil, err + } + + // Go through the HTLCs for this payment, determining if there + // are any in flight or settled. + var ( + attempt *channeldb.HTLCAttemptInfo + settle *channeldb.HTLCAttempt + ) + for _, a := range payment.HTLCs { + a := a + + // We have a settled HTLC, and should return when all + // shards are back. + if a.Settle != nil { + settle = &a + continue + } + + // This HTLC already failed, ignore. + if a.Failure != nil { + continue + } + + // HTLC was neither setteld nor failed, it is still in + // flight. + attempt = &a.HTLCAttemptInfo + break + } + + // Terminal state, return the preimage and the route taken. + if attempt == nil && settle != nil { + return settle.Settle.Preimage, &settle.Route, nil + } // If this payment had no existing payment attempt, we create // and send one now. - if p.attempt == nil { + if attempt == nil { // Before we attempt this next payment, we'll check to see if either // we've gone past the payment attempt timeout, or the router is // exiting. In either case, we'll stop this payment attempt short. If a @@ -114,7 +154,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // Using the route received from the payment session, // create a new shard to send. - firstHop, htlcAdd, attempt, err := p.createNewPaymentAttempt( + firstHop, htlcAdd, a, err := p.createNewPaymentAttempt( rt, ) // With SendToRoute, it can happen that the route exceeds protocol @@ -138,7 +178,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { return [32]byte{}, nil, err } - p.attempt = attempt + attempt = a // Before sending this HTLC to the switch, we checkpoint the // fresh paymentID and route to the DB. This lets us know on @@ -153,11 +193,13 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // Now that the attempt is created and checkpointed to // the DB, we send it. - sendErr := p.sendPaymentAttempt(firstHop, htlcAdd) + sendErr := p.sendPaymentAttempt( + attempt, firstHop, htlcAdd, + ) if sendErr != nil { // TODO(joostjager): Distinguish unexpected // internal errors from real send errors. - err = p.failAttempt(sendErr) + err = p.failAttempt(attempt, sendErr) if err != nil { return [32]byte{}, nil, err } @@ -165,7 +207,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // We must inspect the error to know whether it // was critical or not, to decide whether we // should continue trying. - err := p.handleSendError(sendErr) + err := p.handleSendError(attempt, sendErr) if err != nil { return [32]byte{}, nil, err } @@ -173,35 +215,29 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // Error was handled successfully, reset the // attempt to indicate we want to make a new // attempt. - p.attempt = nil continue } - } else { - // If this was a resumed attempt, we must regenerate the - // circuit. We don't need to check for errors resulting - // from an invalid route, because the sphinx packet has - // been successfully generated before. - _, c, err := generateSphinxPacket( - &p.attempt.Route, p.paymentHash[:], - p.attempt.SessionKey, - ) - if err != nil { - return [32]byte{}, nil, err - } - p.circuit = c + } + + // Regenerate the circuit for this attempt. + _, circuit, err := generateSphinxPacket( + &attempt.Route, p.paymentHash[:], attempt.SessionKey, + ) + if err != nil { + return [32]byte{}, nil, err } // Using the created circuit, initialize the error decrypter so we can // parse+decode any failures incurred by this payment within the // switch. errorDecryptor := &htlcswitch.SphinxErrorDecrypter{ - OnionErrorDecrypter: sphinx.NewOnionErrorDecrypter(p.circuit), + OnionErrorDecrypter: sphinx.NewOnionErrorDecrypter(circuit), } // Now ask the switch to return the result of the payment when // available. resultChan, err := p.router.cfg.Payer.GetPaymentResult( - p.attempt.AttemptID, p.paymentHash, errorDecryptor, + attempt.AttemptID, p.paymentHash, errorDecryptor, ) switch { @@ -211,23 +247,22 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // attempt, and wait for its result to be available. case err == htlcswitch.ErrPaymentIDNotFound: log.Debugf("Payment ID %v for hash %x not found in "+ - "the Switch, retrying.", p.attempt.AttemptID, + "the Switch, retrying.", attempt.AttemptID, p.paymentHash) - err = p.failAttempt(err) + err = p.failAttempt(attempt, err) if err != nil { return [32]byte{}, nil, err } // Reset the attempt to indicate we want to make a new // attempt. - p.attempt = nil continue // A critical, unexpected error was encountered. case err != nil: log.Errorf("Failed getting result for attemptID %d "+ - "from switch: %v", p.attempt.AttemptID, err) + "from switch: %v", attempt.AttemptID, err) return [32]byte{}, nil, err } @@ -255,7 +290,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { log.Errorf("Attempt to send payment %x failed: %v", p.paymentHash, result.Error) - err = p.failAttempt(result.Error) + err = p.failAttempt(attempt, result.Error) if err != nil { return [32]byte{}, nil, err } @@ -263,23 +298,22 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // We must inspect the error to know whether it was // critical or not, to decide whether we should // continue trying. - if err := p.handleSendError(result.Error); err != nil { + if err := p.handleSendError(attempt, result.Error); err != nil { return [32]byte{}, nil, err } // Error was handled successfully, reset the attempt to // indicate we want to make a new attempt. - p.attempt = nil continue } // We successfully got a payment result back from the switch. log.Debugf("Payment %x succeeded with pid=%v", - p.paymentHash, p.attempt.AttemptID) + p.paymentHash, attempt.AttemptID) // Report success to mission control. err = p.router.cfg.MissionControl.ReportPaymentSuccess( - p.attempt.AttemptID, &p.attempt.Route, + attempt.AttemptID, &attempt.Route, ) if err != nil { log.Errorf("Error reporting payment success to mc: %v", @@ -289,7 +323,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // In case of success we atomically store the db payment and // move the payment to the success state. err = p.router.cfg.Control.SettleAttempt( - p.paymentHash, p.attempt.AttemptID, + p.paymentHash, attempt.AttemptID, &channeldb.HTLCSettleInfo{ Preimage: result.Preimage, SettleTime: p.router.cfg.Clock.Now(), @@ -300,12 +334,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { "attempt: %v", err) return [32]byte{}, nil, err } - - // Terminal state, return the preimage and the route - // taken. - return result.Preimage, &p.attempt.Route, nil } - } // errorToPaymentFailure takes a path finding error and converts it into a @@ -341,17 +370,13 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) ( // Generate the raw encoded sphinx packet to be included along // with the htlcAdd message that we send directly to the // switch. - onionBlob, c, err := generateSphinxPacket( + onionBlob, _, err := generateSphinxPacket( rt, p.paymentHash[:], sessionKey, ) if err != nil { return lnwire.ShortChannelID{}, nil, nil, err } - // Update our cached circuit with the newly generated - // one. - p.circuit = c - // Craft an HTLC packet to send to the layer 2 switch. The // metadata within this packet will be used to route the // payment through the network, starting with the first-hop. @@ -389,13 +414,14 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) ( } // sendPaymentAttempt attempts to send the current attempt to the switch. -func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, +func (p *paymentLifecycle) sendPaymentAttempt( + attempt *channeldb.HTLCAttemptInfo, firstHop lnwire.ShortChannelID, htlcAdd *lnwire.UpdateAddHTLC) error { log.Tracef("Attempting to send payment %x (pid=%v), "+ - "using route: %v", p.paymentHash, p.attempt.AttemptID, + "using route: %v", p.paymentHash, attempt.AttemptID, newLogClosure(func() string { - return spew.Sdump(p.attempt.Route) + return spew.Sdump(attempt.Route) }), ) @@ -404,27 +430,28 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, // such that we can resume waiting for the result after a // restart. err := p.router.cfg.Payer.SendHTLC( - firstHop, p.attempt.AttemptID, htlcAdd, + firstHop, attempt.AttemptID, htlcAdd, ) if err != nil { log.Errorf("Failed sending attempt %d for payment "+ - "%x to switch: %v", p.attempt.AttemptID, + "%x to switch: %v", attempt.AttemptID, p.paymentHash, err) return err } log.Debugf("Payment %x (pid=%v) successfully sent to switch, route: %v", - p.paymentHash, p.attempt.AttemptID, &p.attempt.Route) + p.paymentHash, attempt.AttemptID, &attempt.Route) return nil } // handleSendError inspects the given error from the Switch and determines // whether we should make another payment attempt. -func (p *paymentLifecycle) handleSendError(sendErr error) error { +func (p *paymentLifecycle) handleSendError(attempt *channeldb.HTLCAttemptInfo, + sendErr error) error { reason := p.router.processSendError( - p.attempt.AttemptID, &p.attempt.Route, sendErr, + attempt.AttemptID, &attempt.Route, sendErr, ) if reason == nil { // Save the forwarding error so it can be returned if @@ -453,14 +480,16 @@ func (p *paymentLifecycle) handleSendError(sendErr error) error { } // failAttempt calls control tower to fail the current payment attempt. -func (p *paymentLifecycle) failAttempt(sendError error) error { +func (p *paymentLifecycle) failAttempt(attempt *channeldb.HTLCAttemptInfo, + sendError error) error { + failInfo := marshallError( sendError, p.router.cfg.Clock.Now(), ) return p.router.cfg.Control.FailAttempt( - p.paymentHash, p.attempt.AttemptID, + p.paymentHash, attempt.AttemptID, failInfo, ) } diff --git a/routing/router.go b/routing/router.go index 9595b0054e..20c25a87d9 100644 --- a/routing/router.go +++ b/routing/router.go @@ -533,20 +533,13 @@ func (r *ChannelRouter) Start() error { // result for the in-flight attempt is received. paySession := r.cfg.SessionSource.NewPaymentSessionEmpty() - // TODO(joostjager): For mpp, possibly relaunch multiple - // in-flight htlcs here. - var attempt *channeldb.HTLCAttemptInfo - if len(payment.Attempts) > 0 { - attempt = &payment.Attempts[0] - } - // We pass in a zero timeout value, to indicate we // don't need it to timeout. It will stop immediately // after the existing attempt has finished anyway. We // also set a zero fee limit, as no more routes should // be tried. _, _, err := r.sendPayment( - attempt, payment.Info.Value, 0, + payment.Info.Value, 0, payment.Info.PaymentHash, 0, paySession, ) if err != nil { @@ -1646,7 +1639,7 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, // Since this is the first time this payment is being made, we pass nil // for the existing attempt. return r.sendPayment( - nil, payment.Amount, payment.FeeLimit, payment.PaymentHash, + payment.Amount, payment.FeeLimit, payment.PaymentHash, payment.PayAttemptTimeout, paySession, ) } @@ -1669,9 +1662,8 @@ func (r *ChannelRouter) SendPaymentAsync(payment *LightningPayment) error { spewPayment(payment)) _, _, err := r.sendPayment( - nil, payment.Amount, payment.FeeLimit, - payment.PaymentHash, payment.PayAttemptTimeout, - paySession, + payment.Amount, payment.FeeLimit, payment.PaymentHash, + payment.PayAttemptTimeout, paySession, ) if err != nil { log.Errorf("Payment with hash %x failed: %v", @@ -1770,14 +1762,14 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( // We set the timeout to a zero value, indicating the payment shouldn't // timeout. It is only a single attempt, so no more attempts will be - // done anyway. Since this is the first time this payment is being - // made, we pass nil for the existing attempt. + // done anyway. + // // We pass the route receiver amount as the total payment amount such // that the payment loop will request a route for this amount. As fee // limit we pass the route's total fees, since we already know this is // the route that is going to be used. preimage, _, err := r.sendPayment( - nil, amt, route.TotalFees(), hash, 0, paySession, + amt, route.TotalFees(), hash, 0, paySession, ) if err != nil { // SendToRoute should return a structured error. In case the @@ -1815,7 +1807,6 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( // router will call this method for every payment still in-flight according to // the ControlTower. func (r *ChannelRouter) sendPayment( - existingAttempt *channeldb.HTLCAttemptInfo, totalAmt, feeLimit lnwire.MilliSatoshi, paymentHash lntypes.Hash, timeout time.Duration, paySession PaymentSession) ([32]byte, *route.Route, error) { @@ -1836,8 +1827,6 @@ func (r *ChannelRouter) sendPayment( paymentHash: paymentHash, paySession: paySession, currentHeight: currentHeight, - attempt: existingAttempt, - circuit: nil, lastError: nil, } From 9712dd1a7fec8c6cc1cfd0b59a8fd38b77f891e3 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:24 +0200 Subject: [PATCH 368/562] routing/payment_lifecycle: extract attempt sending logic Define shardHandler which is a struct holding what is needed to send attempts along given routes. The reason we define the logic on this struct instead of the paymentLifecycle is that we later will make SendToRoute calls not go through the payment lifecycle, but only using this struct. The launch shard is responsible for registering the attempt with the control tower, failing it if the launch fails. Note that it is NOT responsible for marking the _payment_ failed in case a terminal error is encountered. This is important since we will later reuse this method for SendToRoute, where whether to fail the payment cannot be decided on the shard level. --- routing/payment_lifecycle.go | 145 ++++++++++++++++++++++++----------- routing/router.go | 1 - 2 files changed, 99 insertions(+), 47 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 4deddefe06..801dad2c9e 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -37,11 +37,15 @@ type paymentLifecycle struct { paySession PaymentSession timeoutChan <-chan time.Time currentHeight int32 - lastError error } // resumePayment resumes the paymentLifecycle from the current state. func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { + shardHandler := &shardHandler{ + router: p.router, + paymentHash: p.paymentHash, + } + // We'll continue until either our payment succeeds, or we encounter a // critical error during path finding. for { @@ -144,19 +148,20 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // If there was an error already recorded for this // payment, we'll return that. - if p.lastError != nil { - return [32]byte{}, nil, errNoRoute{lastError: p.lastError} + if shardHandler.lastError != nil { + return [32]byte{}, nil, errNoRoute{ + lastError: shardHandler.lastError, + } } // Terminal state, return. return [32]byte{}, nil, err } - // Using the route received from the payment session, - // create a new shard to send. - firstHop, htlcAdd, a, err := p.createNewPaymentAttempt( - rt, - ) + // With the route in hand, launch a new shard. + var outcome *launchOutcome + attempt, outcome, err = shardHandler.launchShard(rt) + // With SendToRoute, it can happen that the route exceeds protocol // constraints. Mark the payment as failed with an internal error. if err == route.ErrMaxRouteHopsExceeded || @@ -178,43 +183,21 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { return [32]byte{}, nil, err } - attempt = a - - // Before sending this HTLC to the switch, we checkpoint the - // fresh paymentID and route to the DB. This lets us know on - // startup the ID of the payment that we attempted to send, - // such that we can query the Switch for its whereabouts. The - // route is needed to handle the result when it eventually - // comes back. - err = p.router.cfg.Control.RegisterAttempt(p.paymentHash, attempt) - if err != nil { - return [32]byte{}, nil, err - } - - // Now that the attempt is created and checkpointed to - // the DB, we send it. - sendErr := p.sendPaymentAttempt( - attempt, firstHop, htlcAdd, - ) - if sendErr != nil { - // TODO(joostjager): Distinguish unexpected - // internal errors from real send errors. - err = p.failAttempt(attempt, sendErr) - if err != nil { - return [32]byte{}, nil, err - } - + // We ew encountered a non-critical error when + // launching the shard, handle it + if outcome.err != nil { // We must inspect the error to know whether it // was critical or not, to decide whether we // should continue trying. - err := p.handleSendError(attempt, sendErr) + err = shardHandler.handleSendError( + attempt, outcome.err, + ) if err != nil { return [32]byte{}, nil, err } - // Error was handled successfully, reset the - // attempt to indicate we want to make a new - // attempt. + // Error was handled successfully, continue to + // make a new attempt. continue } } @@ -250,7 +233,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { "the Switch, retrying.", attempt.AttemptID, p.paymentHash) - err = p.failAttempt(attempt, err) + err = shardHandler.failAttempt(attempt, err) if err != nil { return [32]byte{}, nil, err } @@ -290,7 +273,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { log.Errorf("Attempt to send payment %x failed: %v", p.paymentHash, result.Error) - err = p.failAttempt(attempt, result.Error) + err = shardHandler.failAttempt(attempt, result.Error) if err != nil { return [32]byte{}, nil, err } @@ -298,7 +281,10 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // We must inspect the error to know whether it was // critical or not, to decide whether we should // continue trying. - if err := p.handleSendError(attempt, result.Error); err != nil { + err := shardHandler.handleSendError( + attempt, result.Error, + ) + if err != nil { return [32]byte{}, nil, err } @@ -337,6 +323,74 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { } } +// shardHandler holds what is necessary to send and collect the result of +// shards. +type shardHandler struct { + paymentHash lntypes.Hash + router *ChannelRouter + + lastError error +} + +// launchOutcome is a type returned from launchShard that indicates whether the +// shard was successfully send onto the network. +type launchOutcome struct { + // err is non-nil if a non-critical error was encountered when trying + // to send the shard, and we successfully updated the control tower to + // reflect this error. This can be errors like not enough local + // balance for the given route etc. + err error +} + +// launchShard creates and sends an HTLC attempt along the given route, +// registering it with the control tower before sending it. It returns the +// HTLCAttemptInfo that was created for the shard, along with a launchOutcome. +// The launchOutcome is used to indicate whether the attempt was successfully +// sent. If the launchOutcome wraps a non-nil error, it means that the attempt +// was not sent onto the network, so no result will be available in the future +// for it. +func (p *shardHandler) launchShard(rt *route.Route) (*channeldb.HTLCAttemptInfo, + *launchOutcome, error) { + + // Using the route received from the payment session, create a new + // shard to send. + firstHop, htlcAdd, attempt, err := p.createNewPaymentAttempt( + rt, + ) + if err != nil { + return nil, nil, err + } + + // Before sending this HTLC to the switch, we checkpoint the fresh + // paymentID and route to the DB. This lets us know on startup the ID + // of the payment that we attempted to send, such that we can query the + // Switch for its whereabouts. The route is needed to handle the result + // when it eventually comes back. + err = p.router.cfg.Control.RegisterAttempt(p.paymentHash, attempt) + if err != nil { + return nil, nil, err + } + + // Now that the attempt is created and checkpointed to the DB, we send + // it. + sendErr := p.sendPaymentAttempt(attempt, firstHop, htlcAdd) + if sendErr != nil { + // TODO(joostjager): Distinguish unexpected internal errors + // from real send errors. + err := p.failAttempt(attempt, sendErr) + if err != nil { + return nil, nil, err + } + + // Return a launchOutcome indicating the shard failed. + return attempt, &launchOutcome{ + err: sendErr, + }, nil + } + + return attempt, &launchOutcome{}, nil +} + // errorToPaymentFailure takes a path finding error and converts it into a // payment-level failure. func errorToPaymentFailure(err error) channeldb.FailureReason { @@ -357,7 +411,7 @@ func errorToPaymentFailure(err error) channeldb.FailureReason { } // createNewPaymentAttempt creates a new payment attempt from the given route. -func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) ( +func (p *shardHandler) createNewPaymentAttempt(rt *route.Route) ( lnwire.ShortChannelID, *lnwire.UpdateAddHTLC, *channeldb.HTLCAttemptInfo, error) { @@ -414,7 +468,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route) ( } // sendPaymentAttempt attempts to send the current attempt to the switch. -func (p *paymentLifecycle) sendPaymentAttempt( +func (p *shardHandler) sendPaymentAttempt( attempt *channeldb.HTLCAttemptInfo, firstHop lnwire.ShortChannelID, htlcAdd *lnwire.UpdateAddHTLC) error { @@ -447,7 +501,7 @@ func (p *paymentLifecycle) sendPaymentAttempt( // handleSendError inspects the given error from the Switch and determines // whether we should make another payment attempt. -func (p *paymentLifecycle) handleSendError(attempt *channeldb.HTLCAttemptInfo, +func (p *shardHandler) handleSendError(attempt *channeldb.HTLCAttemptInfo, sendErr error) error { reason := p.router.processSendError( @@ -457,7 +511,6 @@ func (p *paymentLifecycle) handleSendError(attempt *channeldb.HTLCAttemptInfo, // Save the forwarding error so it can be returned if // this turns out to be the last attempt. p.lastError = sendErr - return nil } @@ -480,7 +533,7 @@ func (p *paymentLifecycle) handleSendError(attempt *channeldb.HTLCAttemptInfo, } // failAttempt calls control tower to fail the current payment attempt. -func (p *paymentLifecycle) failAttempt(attempt *channeldb.HTLCAttemptInfo, +func (p *shardHandler) failAttempt(attempt *channeldb.HTLCAttemptInfo, sendError error) error { failInfo := marshallError( diff --git a/routing/router.go b/routing/router.go index 20c25a87d9..117bf7cbb9 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1827,7 +1827,6 @@ func (r *ChannelRouter) sendPayment( paymentHash: paymentHash, paySession: paySession, currentHeight: currentHeight, - lastError: nil, } // If a timeout is specified, create a timeout channel. If no timeout is From 2c01e79eb554d72c1b50603eebc00edb376fa3e4 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:24 +0200 Subject: [PATCH 369/562] routing/payment_lifecycle: extract result collection into collectResult Fetching the final shard result will also be done for calls to SendToRoute, so we extract this code into a new method. We move the call to the ControlTower to set the payment level failure out into the payment loop, as this must be handled differently when multiple shards are in flight, and for SendToRoute. --- routing/payment_lifecycle.go | 244 ++++++++++++++++++++--------------- 1 file changed, 139 insertions(+), 105 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 801dad2c9e..c386c49f0a 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -202,124 +202,28 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { } } - // Regenerate the circuit for this attempt. - _, circuit, err := generateSphinxPacket( - &attempt.Route, p.paymentHash[:], attempt.SessionKey, - ) + // Whether this was an existing attempt or one we just sent, + // we'll now collect its result. We ignore the result for now + // if it is a success, as we will look it up in the control + // tower on the next loop iteration. + result, err := shardHandler.collectResult(attempt) if err != nil { return [32]byte{}, nil, err } - // Using the created circuit, initialize the error decrypter so we can - // parse+decode any failures incurred by this payment within the - // switch. - errorDecryptor := &htlcswitch.SphinxErrorDecrypter{ - OnionErrorDecrypter: sphinx.NewOnionErrorDecrypter(circuit), - } - - // Now ask the switch to return the result of the payment when - // available. - resultChan, err := p.router.cfg.Payer.GetPaymentResult( - attempt.AttemptID, p.paymentHash, errorDecryptor, - ) - switch { - - // If this attempt ID is unknown to the Switch, it means it was - // never checkpointed and forwarded by the switch before a - // restart. In this case we can safely send a new payment - // attempt, and wait for its result to be available. - case err == htlcswitch.ErrPaymentIDNotFound: - log.Debugf("Payment ID %v for hash %x not found in "+ - "the Switch, retrying.", attempt.AttemptID, - p.paymentHash) - - err = shardHandler.failAttempt(attempt, err) - if err != nil { - return [32]byte{}, nil, err - } - - // Reset the attempt to indicate we want to make a new - // attempt. - continue - - // A critical, unexpected error was encountered. - case err != nil: - log.Errorf("Failed getting result for attemptID %d "+ - "from switch: %v", attempt.AttemptID, err) - - return [32]byte{}, nil, err - } - - // The switch knows about this payment, we'll wait for a result - // to be available. - var ( - result *htlcswitch.PaymentResult - ok bool - ) - - select { - case result, ok = <-resultChan: - if !ok { - return [32]byte{}, nil, htlcswitch.ErrSwitchExiting - } - - case <-p.router.quit: - return [32]byte{}, nil, ErrRouterShuttingDown - } - - // In case of a payment failure, we use the error to decide - // whether we should retry. - if result.Error != nil { - log.Errorf("Attempt to send payment %x failed: %v", - p.paymentHash, result.Error) - - err = shardHandler.failAttempt(attempt, result.Error) - if err != nil { - return [32]byte{}, nil, err - } - + if result.err != nil { // We must inspect the error to know whether it was // critical or not, to decide whether we should // continue trying. - err := shardHandler.handleSendError( - attempt, result.Error, - ) + err = shardHandler.handleSendError(attempt, result.err) if err != nil { return [32]byte{}, nil, err } - // Error was handled successfully, reset the attempt to - // indicate we want to make a new attempt. + // Error was handled successfully, continue to make a + // new attempt. continue } - - // We successfully got a payment result back from the switch. - log.Debugf("Payment %x succeeded with pid=%v", - p.paymentHash, attempt.AttemptID) - - // Report success to mission control. - err = p.router.cfg.MissionControl.ReportPaymentSuccess( - attempt.AttemptID, &attempt.Route, - ) - if err != nil { - log.Errorf("Error reporting payment success to mc: %v", - err) - } - - // In case of success we atomically store the db payment and - // move the payment to the success state. - err = p.router.cfg.Control.SettleAttempt( - p.paymentHash, attempt.AttemptID, - &channeldb.HTLCSettleInfo{ - Preimage: result.Preimage, - SettleTime: p.router.cfg.Clock.Now(), - }, - ) - if err != nil { - log.Errorf("Unable to succeed payment "+ - "attempt: %v", err) - return [32]byte{}, nil, err - } } } @@ -391,6 +295,136 @@ func (p *shardHandler) launchShard(rt *route.Route) (*channeldb.HTLCAttemptInfo, return attempt, &launchOutcome{}, nil } +// shardResult holds the resulting outcome of a shard sent. +type shardResult struct { + // preimage is the payment preimage in case of a settled HTLC. Only set + // if err is non-nil. + preimage lntypes.Preimage + + // err indicates that the shard failed. + err error +} + +// collectResult waits for the result for the given attempt to be available +// from the Switch, then records the attempt outcome with the control tower. A +// shardResult is returned, indicating the final outcome of this HTLC attempt. +func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) ( + *shardResult, error) { + + // Regenerate the circuit for this attempt. + _, circuit, err := generateSphinxPacket( + &attempt.Route, p.paymentHash[:], + attempt.SessionKey, + ) + if err != nil { + return nil, err + } + + // Using the created circuit, initialize the error decrypter so we can + // parse+decode any failures incurred by this payment within the + // switch. + errorDecryptor := &htlcswitch.SphinxErrorDecrypter{ + OnionErrorDecrypter: sphinx.NewOnionErrorDecrypter(circuit), + } + + // Now ask the switch to return the result of the payment when + // available. + resultChan, err := p.router.cfg.Payer.GetPaymentResult( + attempt.AttemptID, p.paymentHash, errorDecryptor, + ) + switch { + + // If this attempt ID is unknown to the Switch, it means it was never + // checkpointed and forwarded by the switch before a restart. In this + // case we can safely send a new payment attempt, and wait for its + // result to be available. + case err == htlcswitch.ErrPaymentIDNotFound: + log.Debugf("Payment ID %v for hash %x not found in "+ + "the Switch, retrying.", attempt.AttemptID, + p.paymentHash) + + cErr := p.failAttempt(attempt, err) + if cErr != nil { + return nil, cErr + } + + return &shardResult{ + err: err, + }, nil + + // A critical, unexpected error was encountered. + case err != nil: + log.Errorf("Failed getting result for attemptID %d "+ + "from switch: %v", attempt.AttemptID, err) + + return nil, err + } + + // The switch knows about this payment, we'll wait for a result to be + // available. + var ( + result *htlcswitch.PaymentResult + ok bool + ) + + select { + case result, ok = <-resultChan: + if !ok { + return nil, htlcswitch.ErrSwitchExiting + } + + case <-p.router.quit: + return nil, ErrRouterShuttingDown + } + + // In case of a payment failure, fail the attempt with the control + // tower and return. + if result.Error != nil { + log.Errorf("Attempt to send payment %x failed: %v", + p.paymentHash, result.Error) + + err := p.failAttempt(attempt, result.Error) + if err != nil { + return nil, err + } + + return &shardResult{ + err: result.Error, + }, nil + } + + // We successfully got a payment result back from the switch. + log.Debugf("Payment %x succeeded with pid=%v", + p.paymentHash, attempt.AttemptID) + + // Report success to mission control. + err = p.router.cfg.MissionControl.ReportPaymentSuccess( + attempt.AttemptID, &attempt.Route, + ) + if err != nil { + log.Errorf("Error reporting payment success to mc: %v", + err) + } + + // In case of success we atomically store settle result to the DB move + // the shard to the settled state. + err = p.router.cfg.Control.SettleAttempt( + p.paymentHash, attempt.AttemptID, + &channeldb.HTLCSettleInfo{ + Preimage: result.Preimage, + SettleTime: p.router.cfg.Clock.Now(), + }, + ) + if err != nil { + log.Errorf("Unable to succeed payment attempt: %v", err) + return nil, err + } + + return &shardResult{ + preimage: result.Preimage, + }, nil +} + // errorToPaymentFailure takes a path finding error and converts it into a // payment-level failure. func errorToPaymentFailure(err error) channeldb.FailureReason { From 6cc162e0b0155fca694f0395286dec8e1aa5853b Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:24 +0200 Subject: [PATCH 370/562] router: make sendToRoute omit payment lifecycle Instead of having SendToRoute pull routes from the payment session in the payment lifecycle, we utilize the new methods on the paymentShard to launch and collect the result for this single route. This also let us remove the check for noRouteError, as we will always have the result from the tried attempt returned. A result of this is that we can finally remove lastError from the payment lifecycle (see next commits). --- routing/router.go | 68 ++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/routing/router.go b/routing/router.go index 117bf7cbb9..2ceefe9408 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1734,9 +1734,6 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) ( func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( lntypes.Preimage, error) { - // Create a payment session for just this route. - paySession := r.cfg.SessionSource.NewPaymentSessionForRoute(route) - // Calculate amount paid to receiver. amt := route.ReceiverAmt() @@ -1760,34 +1757,57 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( }), ) - // We set the timeout to a zero value, indicating the payment shouldn't - // timeout. It is only a single attempt, so no more attempts will be - // done anyway. - // - // We pass the route receiver amount as the total payment amount such - // that the payment loop will request a route for this amount. As fee - // limit we pass the route's total fees, since we already know this is - // the route that is going to be used. - preimage, _, err := r.sendPayment( - amt, route.TotalFees(), hash, 0, paySession, - ) + // Launch a shard along the given route. + sh := &shardHandler{ + router: r, + paymentHash: hash, + } + + var shardError error + attempt, outcome, err := sh.launchShard(route) if err != nil { - // SendToRoute should return a structured error. In case the - // provided route fails, payment lifecycle will return a - // noRouteError with the structured error embedded. - if noRouteError, ok := err.(errNoRoute); ok { - if noRouteError.lastError == nil { - return lntypes.Preimage{}, - errors.New("failure message missing") - } + return lntypes.Preimage{}, err + } + + switch { + // Failed to launch shard. + case outcome.err != nil: + shardError = outcome.err - return lntypes.Preimage{}, noRouteError.lastError + // Shard successfully launched, wait for the result to be available. + default: + result, err := sh.collectResult(attempt) + if err != nil { + return lntypes.Preimage{}, err } + // We got a successful result. + if result.err == nil { + return result.preimage, nil + } + + // The shard failed, break switch to handle it. + shardError = result.err + } + + // Since for SendToRoute we won't retry in case the shard fails, we'll + // mark the payment failed with the control tower immediately. Process + // the error to check if it maps into a terminal error code, if not use + // a generic NO_ROUTE error. + reason := r.processSendError( + attempt.AttemptID, &attempt.Route, shardError, + ) + if reason == nil { + r := channeldb.FailureReasonNoRoute + reason = &r + } + + err = r.cfg.Control.Fail(hash, *reason) + if err != nil { return lntypes.Preimage{}, err } - return preimage, nil + return lntypes.Preimage{}, shardError } // sendPayment attempts to send a payment to the passed payment hash. This From a979b91b27d6533db8c02862c73b79aec3f065df Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:24 +0200 Subject: [PATCH 371/562] routing: remove errNoRoute and lastError Now that SendToRoute is no longer using the payment lifecycle, we remove the error structs and vars used to cache the last encountered error. For SendToRoute this will now be returned directly after a shard has failed. For SendPayment this means that the last error encountered durinng pathfinding no longer will be returned. All errors encounterd can instead be inspected from the HTLC list. --- routing/payment_lifecycle.go | 27 --------------------------- routing/router_test.go | 25 ++++++++++++++++++++++++- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index c386c49f0a..40089479fb 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -13,20 +13,6 @@ import ( "github.com/lightningnetwork/lnd/routing/route" ) -// errNoRoute is returned when all routes from the payment session have been -// attempted. -type errNoRoute struct { - // lastError is the error encountered during the last payment attempt, - // if at least one attempt has been made. - lastError error -} - -// Error returns a string representation of the error. -func (e errNoRoute) Error() string { - return fmt.Sprintf("unable to route payment to destination: %v", - e.lastError) -} - // paymentLifecycle holds all information about the current state of a payment // needed to resume if from any point. type paymentLifecycle struct { @@ -146,14 +132,6 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { return [32]byte{}, nil, saveErr } - // If there was an error already recorded for this - // payment, we'll return that. - if shardHandler.lastError != nil { - return [32]byte{}, nil, errNoRoute{ - lastError: shardHandler.lastError, - } - } - // Terminal state, return. return [32]byte{}, nil, err } @@ -232,8 +210,6 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { type shardHandler struct { paymentHash lntypes.Hash router *ChannelRouter - - lastError error } // launchOutcome is a type returned from launchShard that indicates whether the @@ -542,9 +518,6 @@ func (p *shardHandler) handleSendError(attempt *channeldb.HTLCAttemptInfo, attempt.AttemptID, &attempt.Route, sendErr, ) if reason == nil { - // Save the forwarding error so it can be returned if - // this turns out to be the last attempt. - p.lastError = sendErr return nil } diff --git a/routing/router_test.go b/routing/router_test.go index d8550ac735..d3c866ae94 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -792,10 +792,33 @@ func TestSendPaymentErrorPathPruning(t *testing.T) { // The final error returned should also indicate that the peer wasn't // online (the last error we returned). - if !strings.Contains(err.Error(), "UnknownNextPeer") { + // TODO: proper err code + if !strings.Contains(err.Error(), "unable to find") { t.Fatalf("expected UnknownNextPeer instead got: %v", err) } + // Inspect the two attempts that were made before the payment failed. + p, err := ctx.router.cfg.Control.FetchPayment(payHash) + if err != nil { + t.Fatal(err) + } + + if len(p.HTLCs) != 2 { + t.Fatalf("expected two attempts got %v", len(p.HTLCs)) + } + + // We expect the first attempt to have failed with a + // TemporaryChannelFailure, the second with UnknownNextPeer. + msg := p.HTLCs[0].Failure.Message + if _, ok := msg.(*lnwire.FailTemporaryChannelFailure); !ok { + t.Fatalf("unexpected fail message: %T", msg) + } + + msg = p.HTLCs[1].Failure.Message + if _, ok := msg.(*lnwire.FailUnknownNextPeer); !ok { + t.Fatalf("unexpected fail message: %T", msg) + } + ctx.router.cfg.MissionControl.(*MissionControl).ResetHistory() // Next, we'll modify the SendToSwitch method to indicate that the From 4509c4f3a9430074b8daabdd5b99510159c28760 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:24 +0200 Subject: [PATCH 372/562] routing: move ErrMaxRouteHopsExceeded check Now that SendToRoute is no longer using the payment lifecycle, we move the max hop check out of the payment shard's launch() method, and return the error directly, such that it can be handled in SendToRoute. --- routing/payment_lifecycle.go | 18 ------------------ routing/router.go | 26 ++++++++++++++++++++++---- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 40089479fb..802a80b21b 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -139,24 +139,6 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // With the route in hand, launch a new shard. var outcome *launchOutcome attempt, outcome, err = shardHandler.launchShard(rt) - - // With SendToRoute, it can happen that the route exceeds protocol - // constraints. Mark the payment as failed with an internal error. - if err == route.ErrMaxRouteHopsExceeded || - err == sphinx.ErrMaxRoutingInfoSizeExceeded { - - log.Debugf("Invalid route provided for payment %x: %v", - p.paymentHash, err) - - controlErr := p.router.cfg.Control.Fail( - p.paymentHash, channeldb.FailureReasonError, - ) - if controlErr != nil { - return [32]byte{}, nil, controlErr - } - } - - // In any case, don't continue if there is an error. if err != nil { return [32]byte{}, nil, err } diff --git a/routing/router.go b/routing/router.go index 2ceefe9408..7f860c8935 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1731,11 +1731,11 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) ( // SendToRoute attempts to send a payment with the given hash through the // provided route. This function is blocking and will return the obtained // preimage if the payment is successful or the full error in case of a failure. -func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( +func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) ( lntypes.Preimage, error) { // Calculate amount paid to receiver. - amt := route.ReceiverAmt() + amt := rt.ReceiverAmt() // Record this payment hash with the ControlTower, ensuring it is not // already in-flight. @@ -1753,7 +1753,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( log.Tracef("Dispatching SendToRoute for hash %v: %v", hash, newLogClosure(func() string { - return spew.Sdump(route) + return spew.Sdump(rt) }), ) @@ -1764,7 +1764,25 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( } var shardError error - attempt, outcome, err := sh.launchShard(route) + attempt, outcome, err := sh.launchShard(rt) + + // With SendToRoute, it can happen that the route exceeds protocol + // constraints. Mark the payment as failed with an internal error. + if err == route.ErrMaxRouteHopsExceeded || + err == sphinx.ErrMaxRoutingInfoSizeExceeded { + + log.Debugf("Invalid route provided for payment %x: %v", + hash, err) + + controlErr := r.cfg.Control.Fail( + hash, channeldb.FailureReasonError, + ) + if controlErr != nil { + return [32]byte{}, controlErr + } + } + + // In any case, don't continue if there is an error. if err != nil { return lntypes.Preimage{}, err } From 49efbefb431b76bf438493d4f15b41af2c046e56 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:25 +0200 Subject: [PATCH 373/562] routing/payment_session: remove prebuilt payment session Since we no longer use payment sessions for send to route, we remove the prebuilt one. --- routing/payment_lifecycle.go | 2 +- routing/payment_session.go | 23 ++++++----------------- routing/payment_session_source.go | 14 ++------------ routing/router.go | 5 ----- 4 files changed, 9 insertions(+), 35 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 802a80b21b..473244c027 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -391,7 +391,7 @@ func errorToPaymentFailure(err error) channeldb.FailureReason { errNoTlvPayload, errNoPaymentAddr, errNoPathFound, - errPrebuiltRouteTried: + errEmptyPaySession: return channeldb.FailureReasonNoRoute diff --git a/routing/payment_session.go b/routing/payment_session.go index a5c0426673..f8c297552d 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -13,9 +13,9 @@ import ( const BlockPadding uint16 = 3 var ( - // errPrebuiltRouteTried is returned when the single pre-built route - // failed and there is nothing more we can do. - errPrebuiltRouteTried = errors.New("pre-built route already tried") + // errEmptyPaySession is returned when the empty payment session is + // queried for a route. + errEmptyPaySession = errors.New("empty payment session") ) // PaymentSession is used during SendPayment attempts to provide routes to @@ -50,8 +50,7 @@ type paymentSession struct { payment *LightningPayment - preBuiltRoute *route.Route - preBuiltRouteTried bool + empty bool pathFinder pathFinder } @@ -68,18 +67,8 @@ type paymentSession struct { func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, activeShards, height uint32) (*route.Route, error) { - switch { - - // If we have a pre-built route, use that directly. - case p.preBuiltRoute != nil && !p.preBuiltRouteTried: - p.preBuiltRouteTried = true - - return p.preBuiltRoute, nil - - // If the pre-built route has been tried already, the payment session is - // over. - case p.preBuiltRoute != nil: - return nil, errPrebuiltRouteTried + if p.empty { + return nil, errEmptyPaySession } // Add BlockPadding to the finalCltvDelta so that the receiving node diff --git a/routing/payment_session_source.go b/routing/payment_session_source.go index f3fd968e85..3d6cfedf2b 100644 --- a/routing/payment_session_source.go +++ b/routing/payment_session_source.go @@ -75,23 +75,13 @@ func (m *SessionSource) NewPaymentSession(p *LightningPayment) ( }, nil } -// NewPaymentSessionForRoute creates a new paymentSession instance that is just -// used for failure reporting to missioncontrol. -func (m *SessionSource) NewPaymentSessionForRoute(preBuiltRoute *route.Route) PaymentSession { - return &paymentSession{ - sessionSource: m, - preBuiltRoute: preBuiltRoute, - } -} - // NewPaymentSessionEmpty creates a new paymentSession instance that is empty, // and will be exhausted immediately. Used for failure reporting to // missioncontrol for resumed payment we don't want to make more attempts for. func (m *SessionSource) NewPaymentSessionEmpty() PaymentSession { return &paymentSession{ - sessionSource: m, - preBuiltRoute: &route.Route{}, - preBuiltRouteTried: true, + sessionSource: m, + empty: true, } } diff --git a/routing/router.go b/routing/router.go index 7f860c8935..a5cf84881d 100644 --- a/routing/router.go +++ b/routing/router.go @@ -161,11 +161,6 @@ type PaymentSessionSource interface { // finding a path to the payment's destination. NewPaymentSession(p *LightningPayment) (PaymentSession, error) - // NewPaymentSessionForRoute creates a new paymentSession instance that - // is just used for failure reporting to missioncontrol, and will only - // attempt the given route. - NewPaymentSessionForRoute(preBuiltRoute *route.Route) PaymentSession - // NewPaymentSessionEmpty creates a new paymentSession instance that is // empty, and will be exhausted immediately. Used for failure reporting // to missioncontrol for resumed payment we don't want to make more From 7b5c10814b98886d6f65c6c652150e8a69d6f797 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:25 +0200 Subject: [PATCH 374/562] routing/payment_lifecycle+channeldb: collect existing outcome first To move towards how we will handle existing attempt in case of MPP (collecting their outcome will be done in separate goroutines separate from the payment loop), we move to collect their outcome first. To easily fetch HTLCs that are still not resolved, we add the utility method InFlightHTLCs to channeldb.MPPayment. --- channeldb/mp_payment.go | 15 ++++++++++ routing/payment_lifecycle.go | 55 ++++++++++++++++++++++++------------ 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index d46e590913..fa58b49891 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -131,6 +131,21 @@ type MPPayment struct { Status PaymentStatus } +// InFlightHTLCs returns the HTLCs that are still in-flight, meaning they have +// not been settled or failed. +func (m *MPPayment) InFlightHTLCs() []HTLCAttempt { + var inflights []HTLCAttempt + for _, h := range m.HTLCs { + if h.Settle != nil || h.Failure != nil { + continue + } + + inflights = append(inflights, h) + } + + return inflights +} + // serializeHTLCSettleInfo serializes the details of a settled htlc. func serializeHTLCSettleInfo(w io.Writer, s *HTLCSettleInfo) error { if _, err := w.Write(s.Preimage[:]); err != nil { diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 473244c027..dacd4fc446 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -32,6 +32,23 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { paymentHash: p.paymentHash, } + // If we have an existing attempt, we'll start by collecting its result. + payment, err := p.router.cfg.Control.FetchPayment( + p.paymentHash, + ) + if err != nil { + return [32]byte{}, nil, err + } + + for _, a := range payment.InFlightHTLCs() { + a := a + + _, err := shardHandler.collectResult(&a.HTLCAttemptInfo) + if err != nil { + return [32]byte{}, nil, err + } + } + // We'll continue until either our payment succeeds, or we encounter a // critical error during path finding. for { @@ -160,29 +177,31 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // make a new attempt. continue } - } - // Whether this was an existing attempt or one we just sent, - // we'll now collect its result. We ignore the result for now - // if it is a success, as we will look it up in the control - // tower on the next loop iteration. - result, err := shardHandler.collectResult(attempt) - if err != nil { - return [32]byte{}, nil, err - } - - if result.err != nil { - // We must inspect the error to know whether it was - // critical or not, to decide whether we should - // continue trying. - err = shardHandler.handleSendError(attempt, result.err) + // We'll collect the result of the shard just sent. We + // ignore the result for now if it is a success, as we + // will look it up in the control tower on the next + // loop iteration. + result, err := shardHandler.collectResult(attempt) if err != nil { return [32]byte{}, nil, err } - // Error was handled successfully, continue to make a - // new attempt. - continue + if result.err != nil { + // We must inspect the error to know whether it + // was critical or not, to decide whether we + // should continue trying. + err := shardHandler.handleSendError( + attempt, result.err, + ) + if err != nil { + return [32]byte{}, nil, err + } + + // Error was handled successfully, continue to + // make a new attempt. + continue + } } } } From 5adfc968df004f1248b9b0ecaa263c4d8db22169 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:25 +0200 Subject: [PATCH 375/562] routing/payment_lifecycle: return recorded errors In preparation for MPP we return the terminal errors recorded with the control tower. The reason is that we cannot return immediately when a shard fails for MPP, since there might be more shards in flight that we must wait for. For that reason we instead mark the payment failed in the control tower, then return this error when we inspect the payment, seeing it has been failed and there are no shards in flight. --- lntest/itest/lnd_test.go | 91 ++++++++++++++++++++++-------------- routing/errors.go | 4 -- routing/payment_lifecycle.go | 30 ++++++------ routing/router_test.go | 6 +-- 4 files changed, 72 insertions(+), 59 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 1a11339979..70febd9fa9 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -1915,8 +1915,9 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) { // Alice knows about the channel policy of Carol and should therefore // not be able to find a path during routing. + expErr := channeldb.FailureReasonNoRoute.Error() if err == nil || - !strings.Contains(err.Error(), "unable to find a path") { + !strings.Contains(err.Error(), expErr) { t.Fatalf("expected payment to fail, instead got %v", err) } @@ -3995,6 +3996,41 @@ func assertAmountSent(amt btcutil.Amount, sndr, rcvr *lntest.HarnessNode) func() } } +// assertLastHTLCError checks that the last sent HTLC of the last payment sent +// by the given node failed with the expected failure code. +func assertLastHTLCError(t *harnessTest, node *lntest.HarnessNode, + code lnrpc.Failure_FailureCode) { + + req := &lnrpc.ListPaymentsRequest{ + IncludeIncomplete: true, + } + ctxt, _ := context.WithTimeout(context.Background(), defaultTimeout) + paymentsResp, err := node.ListPayments(ctxt, req) + if err != nil { + t.Fatalf("error when obtaining payments: %v", err) + } + + payments := paymentsResp.Payments + if len(payments) == 0 { + t.Fatalf("no payments found") + } + + payment := payments[len(payments)-1] + htlcs := payment.Htlcs + if len(htlcs) == 0 { + t.Fatalf("no htlcs") + } + + htlc := htlcs[len(htlcs)-1] + if htlc.Failure == nil { + t.Fatalf("expected failure") + } + + if htlc.Failure.Code != code { + t.Fatalf("expected failure %v, got %v", code, htlc.Failure.Code) + } +} + // testSphinxReplayPersistence verifies that replayed onion packets are rejected // by a remote peer after a restart. We use a combination of unsafe // configuration arguments to force Carol to replay the same sphinx packet after @@ -4134,11 +4170,10 @@ func testSphinxReplayPersistence(net *lntest.NetworkHarness, t *harnessTest) { // Construct the response we expect after sending a duplicate packet // that fails due to sphinx replay detection. - replayErr := "InvalidOnionKey" - if !strings.Contains(resp.PaymentError, replayErr) { - t.Fatalf("received payment error: %v, expected %v", - resp.PaymentError, replayErr) + if resp.PaymentError == "" { + t.Fatalf("expected payment error") } + assertLastHTLCError(t, carol, lnrpc.Failure_INVALID_ONION_KEY) // Since the payment failed, the balance should still be left // unaltered. @@ -9452,12 +9487,11 @@ out: t.Fatalf("payment should have been rejected due to invalid " + "payment hash") } - expectedErrorCode := lnwire.CodeIncorrectOrUnknownPaymentDetails.String() - if !strings.Contains(resp.PaymentError, expectedErrorCode) { - // TODO(roasbeef): make into proper gRPC error code - t.Fatalf("payment should have failed due to unknown payment hash, "+ - "instead failed due to: %v", resp.PaymentError) - } + + assertLastHTLCError( + t, net.Alice, + lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, + ) // The balances of all parties should be the same as initially since // the HTLC was canceled. @@ -9484,18 +9518,11 @@ out: t.Fatalf("payment should have been rejected due to wrong " + "HTLC amount") } - expectedErrorCode = lnwire.CodeIncorrectOrUnknownPaymentDetails.String() - if !strings.Contains(resp.PaymentError, expectedErrorCode) { - t.Fatalf("payment should have failed due to wrong amount, "+ - "instead failed due to: %v", resp.PaymentError) - } - // We'll also ensure that the encoded error includes the invlaid HTLC - // amount. - if !strings.Contains(resp.PaymentError, htlcAmt.String()) { - t.Fatalf("error didn't include expected payment amt of %v: "+ - "%v", htlcAmt, resp.PaymentError) - } + assertLastHTLCError( + t, net.Alice, + lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, + ) // The balances of all parties should be the same as initially since // the HTLC was canceled. @@ -9574,12 +9601,12 @@ out: if resp.PaymentError == "" { t.Fatalf("payment should fail due to insufficient "+ "capacity: %v", err) - } else if !strings.Contains(resp.PaymentError, - lnwire.CodeTemporaryChannelFailure.String()) { - t.Fatalf("payment should fail due to insufficient capacity, "+ - "instead: %v", resp.PaymentError) } + assertLastHTLCError( + t, net.Alice, lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE, + ) + // Generate new invoice to not pay same invoice twice. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) carolInvoice, err = carol.AddInvoice(ctxt, invoiceReq) @@ -9616,11 +9643,8 @@ out: if resp.PaymentError == "" { t.Fatalf("payment should have failed") } - expectedErrorCode = lnwire.CodeUnknownNextPeer.String() - if !strings.Contains(resp.PaymentError, expectedErrorCode) { - t.Fatalf("payment should fail due to unknown hop, instead: %v", - resp.PaymentError) - } + + assertLastHTLCError(t, net.Alice, lnrpc.Failure_UNKNOWN_NEXT_PEER) // Finally, immediately close the channel. This function will also // block until the channel is closed and will additionally assert the @@ -9787,9 +9811,8 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) { "should have been rejected, carol will not accept forwarded htlcs", ) } - if !strings.Contains(err.Error(), lnwire.CodeChannelDisabled.String()) { - t.Fatalf("error returned should have been Channel Disabled") - } + + assertLastHTLCError(t, net.Alice, lnrpc.Failure_CHANNEL_DISABLED) // Close all channels. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) diff --git a/routing/errors.go b/routing/errors.go index 3166f73907..3beac229af 100644 --- a/routing/errors.go +++ b/routing/errors.go @@ -15,10 +15,6 @@ const ( // this update can't bring us something new, or because a node // announcement was given for node not found in any channel. ErrIgnored - - // ErrPaymentAttemptTimeout is an error that indicates that a payment - // attempt timed out before we were able to successfully route an HTLC. - ErrPaymentAttemptTimeout ) // routerError is a structure that represent the error inside the routing package, diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index dacd4fc446..6e98eb1b08 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -1,7 +1,6 @@ package routing import ( - "fmt" "time" "github.com/davecgh/go-spew/spew" @@ -95,6 +94,12 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { return settle.Settle.Preimage, &settle.Route, nil } + // If the payment already is failed, and there is no in-flight + // HTLC, return immediately. + if attempt == nil && payment.FailureReason != nil { + return [32]byte{}, nil, *payment.FailureReason + } + // If this payment had no existing payment attempt, we create // and send one now. if attempt == nil { @@ -113,10 +118,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { return [32]byte{}, nil, err } - errStr := fmt.Sprintf("payment attempt not completed " + - "before timeout") - - return [32]byte{}, nil, newErr(ErrPaymentAttemptTimeout, errStr) + continue // The payment will be resumed from the current state // after restart. @@ -149,8 +151,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { return [32]byte{}, nil, saveErr } - // Terminal state, return. - return [32]byte{}, nil, err + continue } // With the route in hand, launch a new shard. @@ -511,7 +512,9 @@ func (p *shardHandler) sendPaymentAttempt( } // handleSendError inspects the given error from the Switch and determines -// whether we should make another payment attempt. +// whether we should make another payment attempt, or if it should be +// considered a terminal error. Terminal errors will be recorded with the +// control tower. func (p *shardHandler) handleSendError(attempt *channeldb.HTLCAttemptInfo, sendErr error) error { @@ -525,19 +528,12 @@ func (p *shardHandler) handleSendError(attempt *channeldb.HTLCAttemptInfo, log.Debugf("Payment %x failed: final_outcome=%v, raw_err=%v", p.paymentHash, *reason, sendErr) - // Mark the payment failed with no route. - // - // TODO(halseth): make payment codes for the actual reason we don't - // continue path finding. - err := p.router.cfg.Control.Fail( - p.paymentHash, *reason, - ) + err := p.router.cfg.Control.Fail(p.paymentHash, *reason) if err != nil { return err } - // Terminal state, return the error we encountered. - return sendErr + return nil } // failAttempt calls control tower to fail the current payment attempt. diff --git a/routing/router_test.go b/routing/router_test.go index d3c866ae94..08499c5a30 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -7,7 +7,6 @@ import ( "image/color" "math" "math/rand" - "strings" "sync/atomic" "testing" "time" @@ -792,9 +791,8 @@ func TestSendPaymentErrorPathPruning(t *testing.T) { // The final error returned should also indicate that the peer wasn't // online (the last error we returned). - // TODO: proper err code - if !strings.Contains(err.Error(), "unable to find") { - t.Fatalf("expected UnknownNextPeer instead got: %v", err) + if err != channeldb.FailureReasonNoRoute { + t.Fatalf("expected no route instead got: %v", err) } // Inspect the two attempts that were made before the payment failed. From f6c97daf0caafc8120b2ea55ca29e200e371901d Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:25 +0200 Subject: [PATCH 376/562] channeldb/payment_control_test: simplify HTLC status assertion --- channeldb/payment_control_test.go | 127 ++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 40 deletions(-) diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 272de68c9b..1228d6631b 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -53,7 +53,7 @@ func genInfo() (*PaymentCreationInfo, *HTLCAttemptInfo, PaymentRequest: []byte("hola"), }, &HTLCAttemptInfo{ - AttemptID: 1, + AttemptID: 0, SessionKey: priv, Route: testRoute, }, preimage, nil @@ -85,8 +85,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, nil, lntypes.Preimage{}, - nil, + t, pControl, info.PaymentHash, info, nil, nil, ) // Fail the payment, which should moved it to Failed. @@ -99,8 +98,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { // Verify the status is indeed Failed. assertPaymentStatus(t, pControl, info.PaymentHash, StatusFailed) assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, nil, lntypes.Preimage{}, - &failReason, + t, pControl, info.PaymentHash, info, &failReason, nil, ) // Sends the htlc again, which should succeed since the prior payment @@ -112,44 +110,57 @@ func TestPaymentControlSwitchFail(t *testing.T) { assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, nil, lntypes.Preimage{}, - nil, + t, pControl, info.PaymentHash, info, nil, nil, ) // Record a new attempt. In this test scenario, the attempt fails. // However, this is not communicated to control tower in the current // implementation. It only registers the initiation of the attempt. - attempt.AttemptID = 2 err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to register attempt: %v", err) } + htlcReason := HTLCFailUnreadable err = pControl.FailAttempt( - info.PaymentHash, 2, &HTLCFailInfo{ - Reason: HTLCFailUnreadable, + info.PaymentHash, attempt.AttemptID, + &HTLCFailInfo{ + Reason: htlcReason, }, ) if err != nil { t.Fatal(err) } + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) + + htlc := &htlcStatus{ + HTLCAttemptInfo: attempt, + failure: &htlcReason, + } + + assertPaymentInfo(t, pControl, info.PaymentHash, info, nil, htlc) // Record another attempt. - attempt.AttemptID = 3 + attempt.AttemptID = 1 err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) } assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) + + htlc = &htlcStatus{ + HTLCAttemptInfo: attempt, + } + assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, attempt, lntypes.Preimage{}, - nil, + t, pControl, info.PaymentHash, info, nil, htlc, ) - // Settle the attempt and verify that status was changed to StatusSucceeded. + // Settle the attempt and verify that status was changed to + // StatusSucceeded. var payment *MPPayment payment, err = pControl.SettleAttempt( - info.PaymentHash, 3, + info.PaymentHash, attempt.AttemptID, &HTLCSettleInfo{ Preimage: preimg, }, @@ -171,7 +182,11 @@ func TestPaymentControlSwitchFail(t *testing.T) { } assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) - assertPaymentInfo(t, pControl, info.PaymentHash, info, 1, attempt, preimg, nil) + + htlc.settle = &preimg + assertPaymentInfo( + t, pControl, info.PaymentHash, info, nil, htlc, + ) // Attempt a final payment, which should now fail since the prior // payment succeed. @@ -207,8 +222,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, nil, lntypes.Preimage{}, - nil, + t, pControl, info.PaymentHash, info, nil, nil, ) // Try to initiate double sending of htlc message with the same @@ -226,9 +240,12 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { t.Fatalf("unable to send htlc message: %v", err) } assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) + + htlc := &htlcStatus{ + HTLCAttemptInfo: attempt, + } assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, attempt, lntypes.Preimage{}, - nil, + t, pControl, info.PaymentHash, info, nil, htlc, ) // Sends base htlc message which initiate StatusInFlight. @@ -240,7 +257,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { // After settling, the error should be ErrAlreadyPaid. _, err = pControl.SettleAttempt( - info.PaymentHash, 1, + info.PaymentHash, attempt.AttemptID, &HTLCSettleInfo{ Preimage: preimg, }, @@ -249,7 +266,9 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { t.Fatalf("error shouldn't have been received, got: %v", err) } assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) - assertPaymentInfo(t, pControl, info.PaymentHash, info, 0, attempt, preimg, nil) + + htlc.settle = &preimg + assertPaymentInfo(t, pControl, info.PaymentHash, info, nil, htlc) err = pControl.InitPayment(info.PaymentHash, info) if err != ErrAlreadyPaid { @@ -360,12 +379,17 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { t.Fatalf("unable to send htlc message: %v", err) } + htlc := &htlcStatus{ + HTLCAttemptInfo: attempt, + } + if p.failed { // Fail the payment attempt. + htlcFailure := HTLCFailUnreadable err := pControl.FailAttempt( info.PaymentHash, attempt.AttemptID, &HTLCFailInfo{ - Reason: HTLCFailUnreadable, + Reason: htlcFailure, }, ) if err != nil { @@ -381,14 +405,16 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { // Verify the status is indeed Failed. assertPaymentStatus(t, pControl, info.PaymentHash, StatusFailed) + + htlc.failure = &htlcFailure assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, attempt, - lntypes.Preimage{}, &failReason, + t, pControl, info.PaymentHash, info, + &failReason, htlc, ) } else if p.success { // Verifies that status was changed to StatusSucceeded. _, err := pControl.SettleAttempt( - info.PaymentHash, 1, + info.PaymentHash, attempt.AttemptID, &HTLCSettleInfo{ Preimage: preimg, }, @@ -398,14 +424,15 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { } assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded) + + htlc.settle = &preimg assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, attempt, preimg, nil, + t, pControl, info.PaymentHash, info, nil, htlc, ) } else { assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) assertPaymentInfo( - t, pControl, info.PaymentHash, info, 0, attempt, - lntypes.Preimage{}, nil, + t, pControl, info.PaymentHash, info, nil, htlc, ) } } @@ -452,11 +479,16 @@ func assertPaymentStatus(t *testing.T, p *PaymentControl, } } +type htlcStatus struct { + *HTLCAttemptInfo + settle *lntypes.Preimage + failure *HTLCFailReason +} + // assertPaymentInfo retrieves the payment referred to by hash and verifies the // expected values. func assertPaymentInfo(t *testing.T, p *PaymentControl, hash lntypes.Hash, - c *PaymentCreationInfo, aIdx int, a *HTLCAttemptInfo, s lntypes.Preimage, - f *FailureReason) { + c *PaymentCreationInfo, f *FailureReason, a *htlcStatus) { t.Helper() @@ -487,20 +519,35 @@ func assertPaymentInfo(t *testing.T, p *PaymentControl, hash lntypes.Hash, return } - htlc := payment.HTLCs[aIdx] + htlc := payment.HTLCs[a.AttemptID] if err := assertRouteEqual(&htlc.Route, &a.Route); err != nil { t.Fatal("routes do not match") } - var zeroPreimage = lntypes.Preimage{} - if s != zeroPreimage { - if htlc.Settle.Preimage != s { - t.Fatalf("Preimages don't match: %x vs %x", - htlc.Settle.Preimage, s) + if htlc.AttemptID != a.AttemptID { + t.Fatalf("unnexpected attempt ID %v, expected %v", + htlc.AttemptID, a.AttemptID) + } + + if a.failure != nil { + if htlc.Failure == nil { + t.Fatalf("expected HTLC to be failed") } - } else { - if htlc.Settle != nil { - t.Fatal("expected no settle info") + + if htlc.Failure.Reason != *a.failure { + t.Fatalf("expected HTLC failure %v, had %v", + *a.failure, htlc.Failure.Reason) + } + } else if htlc.Failure != nil { + t.Fatalf("expected no HTLC failure") + } + + if a.settle != nil { + if htlc.Settle.Preimage != *a.settle { + t.Fatalf("Preimages don't match: %x vs %x", + htlc.Settle.Preimage, a.settle) } + } else if htlc.Settle != nil { + t.Fatal("expected no settle info") } } From 40f97e6c4701456ce5f6a46d4289643ef7d65be3 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 31 Mar 2020 10:35:02 -0700 Subject: [PATCH 377/562] peer: send local node announcement upon establishing peer connections We'll only do so when we have at least one confirmed advertised channel with the remote peer. This ensures that our node announcement can propagate throughout the network even for nodes that were offline when we initially broadcast it. --- peer.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/peer.go b/peer.go index df77c4fd6f..fd1dac55f7 100644 --- a/peer.go +++ b/peer.go @@ -425,6 +425,19 @@ func (p *peer) Start() error { } } + // Node announcements don't propagate very well throughout the network + // as there isn't a way to efficiently query for them through their + // timestamp, mostly affecting nodes that were offline during the time + // of broadcast. We'll resend our node announcement to the remote peer + // as a best-effort delivery such that it can also propagate to their + // peers. To ensure they can successfully process it in most cases, + // we'll only resend it as long as we have at least one confirmed + // advertised channel with the remote peer. + // + // TODO(wilmer): Remove this once we're able to query for node + // announcements through their timestamps. + p.maybeSendNodeAnn(activeChans) + return nil } @@ -688,6 +701,37 @@ func (p *peer) addLink(chanPoint *wire.OutPoint, return p.server.htlcSwitch.AddLink(link) } +// maybeSendNodeAnn sends our node announcement to the remote peer if at least +// one confirmed advertised channel exists with them. +func (p *peer) maybeSendNodeAnn(channels []*channeldb.OpenChannel) { + hasConfirmedPublicChan := false + for _, channel := range channels { + if channel.IsPending { + continue + } + if channel.ChannelFlags&lnwire.FFAnnounceChannel == 0 { + continue + } + + hasConfirmedPublicChan = true + break + } + if !hasConfirmedPublicChan { + return + } + + ourNodeAnn, err := p.server.genNodeAnnouncement(false) + if err != nil { + srvrLog.Debugf("Unable to retrieve node announcement: %v", err) + return + } + + if err := p.SendMessageLazy(false, &ourNodeAnn); err != nil { + srvrLog.Debugf("Unable to resend node announcement to %x: %v", + p.pubKeyBytes, err) + } +} + // WaitForDisconnect waits until the peer has disconnected. A peer may be // disconnected if the local or remote side terminating the connection, or an // irrecoverable protocol error has been encountered. This method will only From 70202be5806c0da07d069445676974b58b7b6dd8 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:25 +0200 Subject: [PATCH 378/562] channeldb: make database logic MPP compatible This commit redefines how the control tower handles shard and payment level settles and failures. We now consider the payment in flight as long it has active shards, or it has no active shards but has not reached a terminal condition (settle of one of the shards, or a payment level failure has been encountered). We also make it possible to settle/fail shards regardless of the payment level status (since we must allow late shards recording their status even though we have already settled/failed the payment). Finally, we make it possible to Fail the payment when it is already failed. This is to allow multiple concurrent shards that reach terminal errors to mark the payment failed, without havinng to synchronize. --- channeldb/mp_payment.go | 13 ++++ channeldb/payment_control.go | 116 ++++++++++++++++++++--------------- channeldb/payments.go | 46 ++++++++++++-- routing/mock_test.go | 46 +++++--------- 4 files changed, 138 insertions(+), 83 deletions(-) diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index fa58b49891..bf2f65ef35 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -131,6 +131,19 @@ type MPPayment struct { Status PaymentStatus } +// TerminalInfo returns any HTLC settle info recorded. If no settle info is +// recorded, any payment level failure will be returned. If neither a settle +// nor a failure is recorded, both return values will be nil. +func (m *MPPayment) TerminalInfo() (*HTLCSettleInfo, *FailureReason) { + for _, h := range m.HTLCs { + if h.Settle != nil { + return h.Settle, nil + } + } + + return nil, m.FailureReason +} + // InFlightHTLCs returns the HTLCs that are still in-flight, meaning they have // not been settled or failed. func (m *MPPayment) InFlightHTLCs() []HTLCAttempt { diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 64d7a39198..81b4d94400 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -18,22 +18,33 @@ var ( // already "in flight" on the network. ErrPaymentInFlight = errors.New("payment is in transition") - // ErrPaymentNotInitiated is returned if payment wasn't initiated in - // switch. + // ErrPaymentNotInitiated is returned if the payment wasn't initiated. ErrPaymentNotInitiated = errors.New("payment isn't initiated") // ErrPaymentAlreadySucceeded is returned in the event we attempt to // change the status of a payment already succeeded. ErrPaymentAlreadySucceeded = errors.New("payment is already succeeded") - // ErrPaymentAlreadyFailed is returned in the event we attempt to - // re-fail a failed payment. + // ErrPaymentAlreadyFailed is returned in the event we attempt to alter + // a failed payment. ErrPaymentAlreadyFailed = errors.New("payment has already failed") // ErrUnknownPaymentStatus is returned when we do not recognize the // existing state of a payment. ErrUnknownPaymentStatus = errors.New("unknown payment status") + // ErrPaymentTerminal is returned if we attempt to alter a payment that + // already has reached a terminal condition. + ErrPaymentTerminal = errors.New("payment has reached terminal condition") + + // ErrAttemptAlreadySettled is returned if we try to alter an already + // settled HTLC attempt. + ErrAttemptAlreadySettled = errors.New("attempt already settled") + + // ErrAttemptAlreadyFailed is returned if we try to alter an already + // failed HTLC attempt. + ErrAttemptAlreadyFailed = errors.New("attempt already failed") + // errNoAttemptInfo is returned when no attempt info is stored yet. errNoAttemptInfo = errors.New("unable to find attempt info for " + "inflight payment") @@ -52,7 +63,7 @@ func NewPaymentControl(db *DB) *PaymentControl { } // InitPayment checks or records the given PaymentCreationInfo with the DB, -// making sure it does not already exist as an in-flight payment. Then this +// making sure it does not already exist as an in-flight payment. When this // method returns successfully, the payment is guranteeed to be in the InFlight // state. func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, @@ -168,12 +179,21 @@ func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, return err } - // We can only register attempts for payments that are - // in-flight. - if err := ensureInFlight(bucket); err != nil { + payment, err := fetchPayment(bucket) + if err != nil { + return err + } + + // Ensure the payment is in-flight. + if err := ensureInFlight(payment); err != nil { return err } + settle, fail := payment.TerminalInfo() + if settle != nil || fail != nil { + return ErrPaymentTerminal + } + htlcsBucket, err := bucket.CreateBucketIfNotExists( paymentHtlcsBucket, ) @@ -241,8 +261,15 @@ func (p *PaymentControl) updateHtlcKey(paymentHash lntypes.Hash, return err } - // We can only update keys of in-flight payments. - if err := ensureInFlight(bucket); err != nil { + p, err := fetchPayment(bucket) + if err != nil { + return err + } + + // We can only update keys of in-flight payments. We allow + // updating keys even if the payment has reached a terminal + // condition, since the HTLC outcomes must still be updated. + if err := ensureInFlight(p); err != nil { return err } @@ -257,6 +284,15 @@ func (p *PaymentControl) updateHtlcKey(paymentHash lntypes.Hash, attemptID) } + // Make sure the shard is not already failed or settled. + if htlcBucket.Get(htlcFailInfoKey) != nil { + return ErrAttemptAlreadyFailed + } + + if htlcBucket.Get(htlcSettleInfoKey) != nil { + return ErrAttemptAlreadySettled + } + // Add or update the key for this htlc. err = htlcBucket.Put(key, value) if err != nil { @@ -299,9 +335,17 @@ func (p *PaymentControl) Fail(paymentHash lntypes.Hash, return err } - // We can only mark in-flight payments as failed. - if err := ensureInFlight(bucket); err != nil { - updateErr = err + // We mark the payent as failed as long as it is known. This + // lets the last attempt to fail with a terminal write its + // failure to the PaymentControl without synchronizing with + // other attempts. + paymentStatus, err := fetchPaymentStatus(bucket) + if err != nil { + return err + } + + if paymentStatus == StatusUnknown { + updateErr = ErrPaymentNotInitiated return nil } @@ -318,14 +362,6 @@ func (p *PaymentControl) Fail(paymentHash lntypes.Hash, return err } - // Final sanity check to see if there are no in-flight htlcs. - for _, htlc := range payment.HTLCs { - if htlc.Settle == nil && htlc.Failure == nil { - return errors.New("payment failed with " + - "in-flight htlc(s)") - } - } - return nil }) if err != nil { @@ -428,45 +464,29 @@ func nextPaymentSequence(tx kvdb.RwTx) ([]byte, error) { // fetchPaymentStatus fetches the payment status of the payment. If the payment // isn't found, it will default to "StatusUnknown". func fetchPaymentStatus(bucket kvdb.ReadBucket) (PaymentStatus, error) { - htlcsBucket := bucket.NestedReadBucket(paymentHtlcsBucket) - if htlcsBucket != nil { - htlcs, err := fetchHtlcAttempts(htlcsBucket) - if err != nil { - return 0, err - } - - // Go through all HTLCs, and return StatusSucceeded if any of - // them did succeed. - for _, h := range htlcs { - if h.Settle != nil { - return StatusSucceeded, nil - } - } - } - - if bucket.Get(paymentFailInfoKey) != nil { - return StatusFailed, nil + // Creation info should be set for all payments, regardless of state. + // If not, it is unknown. + if bucket.Get(paymentCreationInfoKey) == nil { + return StatusUnknown, nil } - if bucket.Get(paymentCreationInfoKey) != nil { - return StatusInFlight, nil + payment, err := fetchPayment(bucket) + if err != nil { + return 0, err } - return StatusUnknown, nil + return payment.Status, nil } // ensureInFlight checks whether the payment found in the given bucket has // status InFlight, and returns an error otherwise. This should be used to // ensure we only mark in-flight payments as succeeded or failed. -func ensureInFlight(bucket kvdb.ReadBucket) error { - paymentStatus, err := fetchPaymentStatus(bucket) - if err != nil { - return err - } +func ensureInFlight(payment *MPPayment) error { + paymentStatus := payment.Status switch { - // The payment was indeed InFlight, return. + // The payment was indeed InFlight. case paymentStatus == StatusInFlight: return nil diff --git a/channeldb/payments.go b/channeldb/payments.go index adf5cf8c23..c07005ab43 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -260,12 +260,6 @@ func fetchPayment(bucket kvdb.ReadBucket) (*MPPayment, error) { sequenceNum := binary.BigEndian.Uint64(seqBytes) - // Get the payment status. - paymentStatus, err := fetchPaymentStatus(bucket) - if err != nil { - return nil, err - } - // Get the PaymentCreationInfo. b := bucket.Get(paymentCreationInfoKey) if b == nil { @@ -297,6 +291,44 @@ func fetchPayment(bucket kvdb.ReadBucket) (*MPPayment, error) { failureReason = &reason } + // Go through all HTLCs for this payment, noting whether we have any + // settled HTLC, and any still in-flight. + var inflight, settled bool + for _, h := range htlcs { + if h.Failure != nil { + continue + } + + if h.Settle != nil { + settled = true + continue + } + + // If any of the HTLCs are not failed nor settled, we + // still have inflight HTLCs. + inflight = true + } + + // Use the DB state to determine the status of the payment. + var paymentStatus PaymentStatus + + switch { + + // If any of the the HTLCs did succeed and there are no HTLCs in + // flight, the payment succeeded. + case !inflight && settled: + paymentStatus = StatusSucceeded + + // If we have no in-flight HTLCs, and the payment failure is set, the + // payment is considered failed. + case !inflight && failureReason != nil: + paymentStatus = StatusFailed + + // Otherwise it is still in flight. + default: + paymentStatus = StatusInFlight + } + return &MPPayment{ sequenceNum: sequenceNum, Info: creationInfo, @@ -412,6 +444,8 @@ func (db *DB) DeletePayments() error { return err } + // If the status is InFlight, we cannot safely delete + // the payment information, so we return early. if paymentStatus == StatusInFlight { return nil } diff --git a/routing/mock_test.go b/routing/mock_test.go index c66c70b1e4..be62d9102e 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -290,16 +290,7 @@ func (m *mockControlTower) SettleAttempt(phash lntypes.Hash, m.success <- successArgs{settleInfo.Preimage} } - // Only allow setting attempts for payments not yet succeeded or - // failed. - if _, ok := m.successful[phash]; ok { - return channeldb.ErrPaymentAlreadySucceeded - } - - if _, ok := m.failed[phash]; ok { - return channeldb.ErrPaymentAlreadyFailed - } - + // Only allow setting attempts if the payment is known. p, ok := m.payments[phash] if !ok { return channeldb.ErrPaymentNotInitiated @@ -311,6 +302,13 @@ func (m *mockControlTower) SettleAttempt(phash lntypes.Hash, continue } + if a.Settle != nil { + return channeldb.ErrAttemptAlreadySettled + } + if a.Failure != nil { + return channeldb.ErrAttemptAlreadyFailed + } + p.attempts[i].Settle = settleInfo // Mark the payment successful on first settled attempt. @@ -327,16 +325,7 @@ func (m *mockControlTower) FailAttempt(phash lntypes.Hash, pid uint64, m.Lock() defer m.Unlock() - // Only allow failing attempts for payments not yet succeeded or - // failed. - if _, ok := m.successful[phash]; ok { - return channeldb.ErrPaymentAlreadySucceeded - } - - if _, ok := m.failed[phash]; ok { - return channeldb.ErrPaymentAlreadyFailed - } - + // Only allow failing attempts if the payment is known. p, ok := m.payments[phash] if !ok { return channeldb.ErrPaymentNotInitiated @@ -348,6 +337,13 @@ func (m *mockControlTower) FailAttempt(phash lntypes.Hash, pid uint64, continue } + if a.Settle != nil { + return channeldb.ErrAttemptAlreadySettled + } + if a.Failure != nil { + return channeldb.ErrAttemptAlreadyFailed + } + p.attempts[i].Failure = failInfo return nil } @@ -365,15 +361,7 @@ func (m *mockControlTower) Fail(phash lntypes.Hash, m.fail <- failArgs{reason} } - // Cannot fail already successful or failed payments. - if _, ok := m.successful[phash]; ok { - return channeldb.ErrPaymentAlreadySucceeded - } - - if _, ok := m.failed[phash]; ok { - return channeldb.ErrPaymentAlreadyFailed - } - + // Payment must be known. if _, ok := m.payments[phash]; !ok { return channeldb.ErrPaymentNotInitiated } From 3610824abd46ddb5e42a13711b06ab0fa61a5424 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:25 +0200 Subject: [PATCH 379/562] channeldb/payment_control_test: add TestPaymentControlMultiShard --- channeldb/payment_control_test.go | 247 ++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 1228d6631b..015aa23186 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -458,6 +458,253 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { } } +// TestPaymentControlMultiShard checks the ability of payment control to +// have multiple in-flight HTLCs for a single payment. +func TestPaymentControlMultiShard(t *testing.T) { + t.Parallel() + + // We will register three HTLC attempts, and always fail the second + // one. We'll generate all combinations of settling/failing the first + // and third HTLC, and assert that the payment status end up as we + // expect. + type testCase struct { + settleFirst bool + settleLast bool + } + + var tests []testCase + for _, f := range []bool{true, false} { + for _, l := range []bool{true, false} { + tests = append(tests, testCase{f, l}) + } + } + + runSubTest := func(t *testing.T, test testCase) { + db, err := initDB() + if err != nil { + t.Fatalf("unable to init db: %v", err) + } + + pControl := NewPaymentControl(db) + + info, attempt, preimg, err := genInfo() + if err != nil { + t.Fatalf("unable to generate htlc message: %v", err) + } + + // Init the payment, moving it to the StatusInFlight state. + err = pControl.InitPayment(info.PaymentHash, info) + if err != nil { + t.Fatalf("unable to send htlc message: %v", err) + } + + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) + assertPaymentInfo( + t, pControl, info.PaymentHash, info, nil, nil, + ) + + // Create three unique attempts we'll use for the test, and + // register them with the payment control. + var attempts []*HTLCAttemptInfo + for i := uint64(0); i < 3; i++ { + a := *attempt + a.AttemptID = i + attempts = append(attempts, &a) + + err = pControl.RegisterAttempt(info.PaymentHash, &a) + if err != nil { + t.Fatalf("unable to send htlc message: %v", err) + } + assertPaymentStatus( + t, pControl, info.PaymentHash, StatusInFlight, + ) + + htlc := &htlcStatus{ + HTLCAttemptInfo: &a, + } + assertPaymentInfo( + t, pControl, info.PaymentHash, info, nil, htlc, + ) + } + + // Fail the second attempt. + a := attempts[1] + htlcFail := HTLCFailUnreadable + err = pControl.FailAttempt( + info.PaymentHash, a.AttemptID, + &HTLCFailInfo{ + Reason: htlcFail, + }, + ) + if err != nil { + t.Fatal(err) + } + + htlc := &htlcStatus{ + HTLCAttemptInfo: a, + failure: &htlcFail, + } + assertPaymentInfo( + t, pControl, info.PaymentHash, info, nil, htlc, + ) + + // Payment should still be in-flight. + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) + + // Depending on the test case, settle or fail the first attempt. + a = attempts[0] + htlc = &htlcStatus{ + HTLCAttemptInfo: a, + } + + var firstFailReason *FailureReason + if test.settleFirst { + _, err := pControl.SettleAttempt( + info.PaymentHash, a.AttemptID, + &HTLCSettleInfo{ + Preimage: preimg, + }, + ) + if err != nil { + t.Fatalf("error shouldn't have been "+ + "received, got: %v", err) + } + + // Assert that the HTLC has had the preimage recorded. + htlc.settle = &preimg + assertPaymentInfo( + t, pControl, info.PaymentHash, info, nil, htlc, + ) + } else { + err := pControl.FailAttempt( + info.PaymentHash, a.AttemptID, + &HTLCFailInfo{ + Reason: htlcFail, + }, + ) + if err != nil { + t.Fatalf("error shouldn't have been "+ + "received, got: %v", err) + } + + // Assert the failure was recorded. + htlc.failure = &htlcFail + assertPaymentInfo( + t, pControl, info.PaymentHash, info, nil, htlc, + ) + + // We also record a payment level fail, to move it into + // a terminal state. + failReason := FailureReasonNoRoute + _, err = pControl.Fail(info.PaymentHash, failReason) + if err != nil { + t.Fatalf("unable to fail payment hash: %v", err) + } + + // Record the reason we failed the payment, such that + // we can assert this later in the test. + firstFailReason = &failReason + } + + // The payment should still be considered in-flight, since there + // is still an active HTLC. + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) + + // Try to register yet another attempt. This should fail now + // that the payment has reached a terminal condition. + b := *attempt + b.AttemptID = 3 + err = pControl.RegisterAttempt(info.PaymentHash, &b) + if err != ErrPaymentTerminal { + t.Fatalf("expected ErrPaymentTerminal, got: %v", err) + } + + assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight) + + // Settle or fail the remaining attempt based on the testcase. + a = attempts[2] + htlc = &htlcStatus{ + HTLCAttemptInfo: a, + } + if test.settleLast { + // Settle the last outstanding attempt. + _, err = pControl.SettleAttempt( + info.PaymentHash, a.AttemptID, + &HTLCSettleInfo{ + Preimage: preimg, + }, + ) + if err != nil { + t.Fatalf("error shouldn't have been "+ + "received, got: %v", err) + } + + htlc.settle = &preimg + assertPaymentInfo( + t, pControl, info.PaymentHash, info, + firstFailReason, htlc, + ) + } else { + // Fail the attempt. + err := pControl.FailAttempt( + info.PaymentHash, a.AttemptID, + &HTLCFailInfo{ + Reason: htlcFail, + }, + ) + if err != nil { + t.Fatalf("error shouldn't have been "+ + "received, got: %v", err) + } + + // Assert the failure was recorded. + htlc.failure = &htlcFail + assertPaymentInfo( + t, pControl, info.PaymentHash, info, + firstFailReason, htlc, + ) + + // Check that we can override any perevious terminal + // failure. This is to allow multiple concurrent shard + // write a terminal failure to the database without + // syncing. + failReason := FailureReasonPaymentDetails + _, err = pControl.Fail(info.PaymentHash, failReason) + if err != nil { + t.Fatalf("unable to fail payment hash: %v", err) + } + } + + // If any of the two attempts settled, the payment should end + // up in the Succeeded state. If both failed the payment should + // also be Failed at this poinnt. + finalStatus := StatusFailed + expRegErr := ErrPaymentAlreadyFailed + if test.settleFirst || test.settleLast { + finalStatus = StatusSucceeded + expRegErr = ErrPaymentAlreadySucceeded + } + + assertPaymentStatus(t, pControl, info.PaymentHash, finalStatus) + + // Finally assert we cannot register more attempts. + err = pControl.RegisterAttempt(info.PaymentHash, &b) + if err != expRegErr { + t.Fatalf("expected error %v, got: %v", expRegErr, err) + } + } + + for _, test := range tests { + test := test + subTest := fmt.Sprintf("first=%v, second=%v", + test.settleFirst, test.settleLast) + + t.Run(subTest, func(t *testing.T) { + runSubTest(t, test) + }) + } +} + // assertPaymentStatus retrieves the status of the payment referred to by hash // and compares it with the expected state. func assertPaymentStatus(t *testing.T, p *PaymentControl, From 4d343bbb468ee36f6737379ab1b6bd517e709225 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:26 +0200 Subject: [PATCH 380/562] routing tests: move TestRouterPaymentStateMachine to own file (almost) PURE CODE MOVE The only code change is to change a few select cases from case _ <- channel: to case <- channel: to please the linter. The test is testing the payment lifecycle, so move it to payment_lifecycle_test.go --- routing/payment_lifecycle_test.go | 653 ++++++++++++++++++++++++++++++ routing/router_test.go | 632 ----------------------------- 2 files changed, 653 insertions(+), 632 deletions(-) create mode 100644 routing/payment_lifecycle_test.go diff --git a/routing/payment_lifecycle_test.go b/routing/payment_lifecycle_test.go new file mode 100644 index 0000000000..addca00576 --- /dev/null +++ b/routing/payment_lifecycle_test.go @@ -0,0 +1,653 @@ +package routing + +import ( + "crypto/rand" + "fmt" + "sync/atomic" + "testing" + "time" + + "github.com/btcsuite/btcutil" + "github.com/go-errors/errors" + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/clock" + "github.com/lightningnetwork/lnd/htlcswitch" + "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" +) + +// TestRouterPaymentStateMachine tests that the router interacts as expected +// with the ControlTower during a payment lifecycle, such that it payment +// attempts are not sent twice to the switch, and results are handled after a +// restart. +func TestRouterPaymentStateMachine(t *testing.T) { + t.Parallel() + + const startingBlockHeight = 101 + + // Setup two simple channels such that we can mock sending along this + // route. + chanCapSat := btcutil.Amount(100000) + testChannels := []*testChannel{ + symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{ + Expiry: 144, + FeeRate: 400, + MinHTLC: 1, + MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat), + }, 1), + symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{ + Expiry: 144, + FeeRate: 400, + MinHTLC: 1, + MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat), + }, 2), + } + + testGraph, err := createTestGraphFromChannels(testChannels, "a") + if err != nil { + t.Fatalf("unable to create graph: %v", err) + } + defer testGraph.cleanUp() + + hop1 := testGraph.aliasMap["b"] + hop2 := testGraph.aliasMap["c"] + hops := []*route.Hop{ + { + ChannelID: 1, + PubKeyBytes: hop1, + LegacyPayload: true, + }, + { + ChannelID: 2, + PubKeyBytes: hop2, + LegacyPayload: true, + }, + } + + // We create a simple route that we will supply every time the router + // requests one. + rt, err := route.NewRouteFromHops( + lnwire.MilliSatoshi(10000), 100, testGraph.aliasMap["a"], hops, + ) + if err != nil { + t.Fatalf("unable to create route: %v", err) + } + + // A payment state machine test case consists of several ordered steps, + // that we use for driving the scenario. + type testCase struct { + // steps is a list of steps to perform during the testcase. + steps []string + + // routes is the sequence of routes we will provide to the + // router when it requests a new route. + routes []*route.Route + } + + const ( + // routerInitPayment is a test step where we expect the router + // to call the InitPayment method on the control tower. + routerInitPayment = "Router:init-payment" + + // routerRegisterAttempt is a test step where we expect the + // router to call the RegisterAttempt method on the control + // tower. + routerRegisterAttempt = "Router:register-attempt" + + // routerSuccess is a test step where we expect the router to + // call the Success method on the control tower. + routerSuccess = "Router:success" + + // routerFail is a test step where we expect the router to call + // the Fail method on the control tower. + routerFail = "Router:fail" + + // sendToSwitchSuccess is a step where we expect the router to + // call send the payment attempt to the switch, and we will + // respond with a non-error, indicating that the payment + // attempt was successfully forwarded. + sendToSwitchSuccess = "SendToSwitch:success" + + // sendToSwitchResultFailure is a step where we expect the + // router to send the payment attempt to the switch, and we + // will respond with a forwarding error. This can happen when + // forwarding fail on our local links. + sendToSwitchResultFailure = "SendToSwitch:failure" + + // getPaymentResultSuccess is a test step where we expect the + // router to call the GetPaymentResult method, and we will + // respond with a successful payment result. + getPaymentResultSuccess = "GetPaymentResult:success" + + // getPaymentResultFailure is a test step where we expect the + // router to call the GetPaymentResult method, and we will + // respond with a forwarding error. + getPaymentResultFailure = "GetPaymentResult:failure" + + // resendPayment is a test step where we manually try to resend + // the same payment, making sure the router responds with an + // error indicating that it is already in flight. + resendPayment = "ResendPayment" + + // startRouter is a step where we manually start the router, + // used to test that it automatically will resume payments at + // startup. + startRouter = "StartRouter" + + // stopRouter is a test step where we manually make the router + // shut down. + stopRouter = "StopRouter" + + // paymentSuccess is a step where assert that we receive a + // successful result for the original payment made. + paymentSuccess = "PaymentSuccess" + + // paymentError is a step where assert that we receive an error + // for the original payment made. + paymentError = "PaymentError" + + // resentPaymentSuccess is a step where assert that we receive + // a successful result for a payment that was resent. + resentPaymentSuccess = "ResentPaymentSuccess" + + // resentPaymentError is a step where assert that we receive an + // error for a payment that was resent. + resentPaymentError = "ResentPaymentError" + ) + + tests := []testCase{ + { + // Tests a normal payment flow that succeeds. + steps: []string{ + routerInitPayment, + routerRegisterAttempt, + sendToSwitchSuccess, + getPaymentResultSuccess, + routerSuccess, + paymentSuccess, + }, + routes: []*route.Route{rt}, + }, + { + // A payment flow with a failure on the first attempt, + // but that succeeds on the second attempt. + steps: []string{ + routerInitPayment, + routerRegisterAttempt, + sendToSwitchSuccess, + + // Make the first sent attempt fail. + getPaymentResultFailure, + + // The router should retry. + routerRegisterAttempt, + sendToSwitchSuccess, + + // Make the second sent attempt succeed. + getPaymentResultSuccess, + routerSuccess, + paymentSuccess, + }, + routes: []*route.Route{rt, rt}, + }, + { + // A payment flow with a forwarding failure first time + // sending to the switch, but that succeeds on the + // second attempt. + steps: []string{ + routerInitPayment, + routerRegisterAttempt, + + // Make the first sent attempt fail. + sendToSwitchResultFailure, + + // The router should retry. + routerRegisterAttempt, + sendToSwitchSuccess, + + // Make the second sent attempt succeed. + getPaymentResultSuccess, + routerSuccess, + paymentSuccess, + }, + routes: []*route.Route{rt, rt}, + }, + { + // A payment that fails on the first attempt, and has + // only one route available to try. It will therefore + // fail permanently. + steps: []string{ + routerInitPayment, + routerRegisterAttempt, + sendToSwitchSuccess, + + // Make the first sent attempt fail. + getPaymentResultFailure, + + // Since there are no more routes to try, the + // payment should fail. + routerFail, + paymentError, + }, + routes: []*route.Route{rt}, + }, + { + // We expect the payment to fail immediately if we have + // no routes to try. + steps: []string{ + routerInitPayment, + routerFail, + paymentError, + }, + routes: []*route.Route{}, + }, + { + // A normal payment flow, where we attempt to resend + // the same payment after each step. This ensures that + // the router don't attempt to resend a payment already + // in flight. + steps: []string{ + routerInitPayment, + routerRegisterAttempt, + + // Manually resend the payment, the router + // should attempt to init with the control + // tower, but fail since it is already in + // flight. + resendPayment, + routerInitPayment, + resentPaymentError, + + // The original payment should proceed as + // normal. + sendToSwitchSuccess, + + // Again resend the payment and assert it's not + // allowed. + resendPayment, + routerInitPayment, + resentPaymentError, + + // Notify about a success for the original + // payment. + getPaymentResultSuccess, + routerSuccess, + + // Now that the original payment finished, + // resend it again to ensure this is not + // allowed. + resendPayment, + routerInitPayment, + resentPaymentError, + paymentSuccess, + }, + routes: []*route.Route{rt}, + }, + { + // Tests that the router is able to handle the + // receieved payment result after a restart. + steps: []string{ + routerInitPayment, + routerRegisterAttempt, + sendToSwitchSuccess, + + // Shut down the router. The original caller + // should get notified about this. + stopRouter, + paymentError, + + // Start the router again, and ensure the + // router registers the success with the + // control tower. + startRouter, + getPaymentResultSuccess, + routerSuccess, + }, + routes: []*route.Route{rt}, + }, + { + // Tests that we are allowed to resend a payment after + // it has permanently failed. + steps: []string{ + routerInitPayment, + routerRegisterAttempt, + sendToSwitchSuccess, + + // Resending the payment at this stage should + // not be allowed. + resendPayment, + routerInitPayment, + resentPaymentError, + + // Make the first attempt fail. + getPaymentResultFailure, + routerFail, + + // Since we have no more routes to try, the + // original payment should fail. + paymentError, + + // Now resend the payment again. This should be + // allowed, since the payment has failed. + resendPayment, + routerInitPayment, + routerRegisterAttempt, + sendToSwitchSuccess, + getPaymentResultSuccess, + routerSuccess, + resentPaymentSuccess, + }, + routes: []*route.Route{rt}, + }, + } + + // Create a mock control tower with channels set up, that we use to + // synchronize and listen for events. + control := makeMockControlTower() + control.init = make(chan initArgs) + control.register = make(chan registerArgs) + control.success = make(chan successArgs) + control.fail = make(chan failArgs) + control.fetchInFlight = make(chan struct{}) + + quit := make(chan struct{}) + defer close(quit) + + // setupRouter is a helper method that creates and starts the router in + // the desired configuration for this test. + setupRouter := func() (*ChannelRouter, chan error, + chan *htlcswitch.PaymentResult, chan error) { + + chain := newMockChain(startingBlockHeight) + chainView := newMockChainView(chain) + + // We set uo the use the following channels and a mock Payer to + // synchonize with the interaction to the Switch. + sendResult := make(chan error) + paymentResultErr := make(chan error) + paymentResult := make(chan *htlcswitch.PaymentResult) + + payer := &mockPayer{ + sendResult: sendResult, + paymentResult: paymentResult, + paymentResultErr: paymentResultErr, + } + + router, err := New(Config{ + Graph: testGraph.graph, + Chain: chain, + ChainView: chainView, + Control: control, + SessionSource: &mockPaymentSessionSource{}, + MissionControl: &mockMissionControl{}, + Payer: payer, + ChannelPruneExpiry: time.Hour * 24, + GraphPruneInterval: time.Hour * 2, + QueryBandwidth: func(e *channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi { + return lnwire.NewMSatFromSatoshis(e.Capacity) + }, + NextPaymentID: func() (uint64, error) { + next := atomic.AddUint64(&uniquePaymentID, 1) + return next, nil + }, + Clock: clock.NewTestClock(time.Unix(1, 0)), + }) + if err != nil { + t.Fatalf("unable to create router %v", err) + } + + // On startup, the router should fetch all pending payments + // from the ControlTower, so assert that here. + errCh := make(chan error) + go func() { + close(errCh) + select { + case <-control.fetchInFlight: + return + case <-time.After(1 * time.Second): + errCh <- errors.New("router did not fetch in flight " + + "payments") + } + }() + + if err := router.Start(); err != nil { + t.Fatalf("unable to start router: %v", err) + } + + select { + case err := <-errCh: + if err != nil { + t.Fatalf("error in anonymous goroutine: %s", err) + } + case <-time.After(1 * time.Second): + t.Fatalf("did not fetch in flight payments at startup") + } + + return router, sendResult, paymentResult, paymentResultErr + } + + router, sendResult, getPaymentResult, getPaymentResultErr := setupRouter() + defer func() { + if err := router.Stop(); err != nil { + t.Fatal(err) + } + }() + + for _, test := range tests { + // Craft a LightningPayment struct. + var preImage lntypes.Preimage + if _, err := rand.Read(preImage[:]); err != nil { + t.Fatalf("unable to generate preimage") + } + + payHash := preImage.Hash() + + paymentAmt := lnwire.NewMSatFromSatoshis(1000) + payment := LightningPayment{ + Target: testGraph.aliasMap["c"], + Amount: paymentAmt, + FeeLimit: noFeeLimit, + PaymentHash: payHash, + } + + router.cfg.SessionSource = &mockPaymentSessionSource{ + routes: test.routes, + } + + router.cfg.MissionControl = &mockMissionControl{} + + // Send the payment. Since this is new payment hash, the + // information should be registered with the ControlTower. + paymentResult := make(chan error) + go func() { + _, _, err := router.SendPayment(&payment) + paymentResult <- err + }() + + var resendResult chan error + for _, step := range test.steps { + switch step { + + case routerInitPayment: + var args initArgs + select { + case args = <-control.init: + case <-time.After(1 * time.Second): + t.Fatalf("no init payment with control") + } + + if args.c == nil { + t.Fatalf("expected non-nil CreationInfo") + } + + // In this step we expect the router to make a call to + // register a new attempt with the ControlTower. + case routerRegisterAttempt: + var args registerArgs + select { + case args = <-control.register: + case <-time.After(1 * time.Second): + t.Fatalf("not registered with control") + } + + if args.a == nil { + t.Fatalf("expected non-nil AttemptInfo") + } + + // In this step we expect the router to call the + // ControlTower's Succcess method with the preimage. + case routerSuccess: + select { + case <-control.success: + case <-time.After(1 * time.Second): + t.Fatalf("not registered with control") + } + + // In this step we expect the router to call the + // ControlTower's Fail method, to indicate that the + // payment failed. + case routerFail: + select { + case <-control.fail: + case <-time.After(1 * time.Second): + t.Fatalf("not registered with control") + } + + // In this step we expect the SendToSwitch method to be + // called, and we respond with a nil-error. + case sendToSwitchSuccess: + select { + case sendResult <- nil: + case <-time.After(1 * time.Second): + t.Fatalf("unable to send result") + } + + // In this step we expect the SendToSwitch method to be + // called, and we respond with a forwarding error + case sendToSwitchResultFailure: + select { + case sendResult <- htlcswitch.NewForwardingError( + &lnwire.FailTemporaryChannelFailure{}, + 1, + ): + case <-time.After(1 * time.Second): + t.Fatalf("unable to send result") + } + + // In this step we expect the GetPaymentResult method + // to be called, and we respond with the preimage to + // complete the payment. + case getPaymentResultSuccess: + select { + case getPaymentResult <- &htlcswitch.PaymentResult{ + Preimage: preImage, + }: + case <-time.After(1 * time.Second): + t.Fatalf("unable to send result") + } + + // In this state we expect the GetPaymentResult method + // to be called, and we respond with a forwarding + // error, indicating that the router should retry. + case getPaymentResultFailure: + failure := htlcswitch.NewForwardingError( + &lnwire.FailTemporaryChannelFailure{}, + 1, + ) + + select { + case getPaymentResult <- &htlcswitch.PaymentResult{ + Error: failure, + }: + case <-time.After(1 * time.Second): + t.Fatalf("unable to get result") + } + + // In this step we manually try to resend the same + // payment, making sure the router responds with an + // error indicating that it is already in flight. + case resendPayment: + resendResult = make(chan error) + go func() { + _, _, err := router.SendPayment(&payment) + resendResult <- err + }() + + // In this step we manually stop the router. + case stopRouter: + select { + case getPaymentResultErr <- fmt.Errorf( + "shutting down"): + case <-time.After(1 * time.Second): + t.Fatalf("unable to send payment " + + "result error") + } + + if err := router.Stop(); err != nil { + t.Fatalf("unable to restart: %v", err) + } + + // In this step we manually start the router. + case startRouter: + router, sendResult, getPaymentResult, + getPaymentResultErr = setupRouter() + + // In this state we expect to receive an error for the + // original payment made. + case paymentError: + select { + case err := <-paymentResult: + if err == nil { + t.Fatalf("expected error") + } + + case <-time.After(1 * time.Second): + t.Fatalf("got no payment result") + } + + // In this state we expect the original payment to + // succeed. + case paymentSuccess: + select { + case err := <-paymentResult: + if err != nil { + t.Fatalf("did not expecte error %v", err) + } + + case <-time.After(1 * time.Second): + t.Fatalf("got no payment result") + } + + // In this state we expect to receive an error for the + // resent payment made. + case resentPaymentError: + select { + case err := <-resendResult: + if err == nil { + t.Fatalf("expected error") + } + + case <-time.After(1 * time.Second): + t.Fatalf("got no payment result") + } + + // In this state we expect the resent payment to + // succeed. + case resentPaymentSuccess: + select { + case err := <-resendResult: + if err != nil { + t.Fatalf("did not expect error %v", err) + } + + case <-time.After(1 * time.Second): + t.Fatalf("got no payment result") + } + + default: + t.Fatalf("unknown step %v", step) + } + } + } +} diff --git a/routing/router_test.go b/routing/router_test.go index 08499c5a30..0bb90d7154 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -2,7 +2,6 @@ package routing import ( "bytes" - "errors" "fmt" "image/color" "math" @@ -2616,637 +2615,6 @@ func assertChannelsPruned(t *testing.T, graph *channeldb.ChannelGraph, } } -// TestRouterPaymentStateMachine tests that the router interacts as expected -// with the ControlTower during a payment lifecycle, such that it payment -// attempts are not sent twice to the switch, and results are handled after a -// restart. -func TestRouterPaymentStateMachine(t *testing.T) { - t.Parallel() - - const startingBlockHeight = 101 - - // Setup two simple channels such that we can mock sending along this - // route. - chanCapSat := btcutil.Amount(100000) - testChannels := []*testChannel{ - symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{ - Expiry: 144, - FeeRate: 400, - MinHTLC: 1, - MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat), - }, 1), - symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{ - Expiry: 144, - FeeRate: 400, - MinHTLC: 1, - MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat), - }, 2), - } - - testGraph, err := createTestGraphFromChannels(testChannels, "a") - if err != nil { - t.Fatalf("unable to create graph: %v", err) - } - defer testGraph.cleanUp() - - hop1 := testGraph.aliasMap["b"] - hop2 := testGraph.aliasMap["c"] - hops := []*route.Hop{ - { - ChannelID: 1, - PubKeyBytes: hop1, - LegacyPayload: true, - }, - { - ChannelID: 2, - PubKeyBytes: hop2, - LegacyPayload: true, - }, - } - - // We create a simple route that we will supply every time the router - // requests one. - rt, err := route.NewRouteFromHops( - lnwire.MilliSatoshi(10000), 100, testGraph.aliasMap["a"], hops, - ) - if err != nil { - t.Fatalf("unable to create route: %v", err) - } - - // A payment state machine test case consists of several ordered steps, - // that we use for driving the scenario. - type testCase struct { - // steps is a list of steps to perform during the testcase. - steps []string - - // routes is the sequence of routes we will provide to the - // router when it requests a new route. - routes []*route.Route - } - - const ( - // routerInitPayment is a test step where we expect the router - // to call the InitPayment method on the control tower. - routerInitPayment = "Router:init-payment" - - // routerRegisterAttempt is a test step where we expect the - // router to call the RegisterAttempt method on the control - // tower. - routerRegisterAttempt = "Router:register-attempt" - - // routerSuccess is a test step where we expect the router to - // call the Success method on the control tower. - routerSuccess = "Router:success" - - // routerFail is a test step where we expect the router to call - // the Fail method on the control tower. - routerFail = "Router:fail" - - // sendToSwitchSuccess is a step where we expect the router to - // call send the payment attempt to the switch, and we will - // respond with a non-error, indicating that the payment - // attempt was successfully forwarded. - sendToSwitchSuccess = "SendToSwitch:success" - - // sendToSwitchResultFailure is a step where we expect the - // router to send the payment attempt to the switch, and we - // will respond with a forwarding error. This can happen when - // forwarding fail on our local links. - sendToSwitchResultFailure = "SendToSwitch:failure" - - // getPaymentResultSuccess is a test step where we expect the - // router to call the GetPaymentResult method, and we will - // respond with a successful payment result. - getPaymentResultSuccess = "GetPaymentResult:success" - - // getPaymentResultFailure is a test step where we expect the - // router to call the GetPaymentResult method, and we will - // respond with a forwarding error. - getPaymentResultFailure = "GetPaymentResult:failure" - - // resendPayment is a test step where we manually try to resend - // the same payment, making sure the router responds with an - // error indicating that it is alreayd in flight. - resendPayment = "ResendPayment" - - // startRouter is a step where we manually start the router, - // used to test that it automatically will resume payments at - // startup. - startRouter = "StartRouter" - - // stopRouter is a test step where we manually make the router - // shut down. - stopRouter = "StopRouter" - - // paymentSuccess is a step where assert that we receive a - // successful result for the original payment made. - paymentSuccess = "PaymentSuccess" - - // paymentError is a step where assert that we receive an error - // for the original payment made. - paymentError = "PaymentError" - - // resentPaymentSuccess is a step where assert that we receive - // a successful result for a payment that was resent. - resentPaymentSuccess = "ResentPaymentSuccess" - - // resentPaymentError is a step where assert that we receive an - // error for a payment that was resent. - resentPaymentError = "ResentPaymentError" - ) - - tests := []testCase{ - { - // Tests a normal payment flow that succeeds. - steps: []string{ - routerInitPayment, - routerRegisterAttempt, - sendToSwitchSuccess, - getPaymentResultSuccess, - routerSuccess, - paymentSuccess, - }, - routes: []*route.Route{rt}, - }, - { - // A payment flow with a failure on the first attempt, - // but that succeeds on the second attempt. - steps: []string{ - routerInitPayment, - routerRegisterAttempt, - sendToSwitchSuccess, - - // Make the first sent attempt fail. - getPaymentResultFailure, - - // The router should retry. - routerRegisterAttempt, - sendToSwitchSuccess, - - // Make the second sent attempt succeed. - getPaymentResultSuccess, - routerSuccess, - paymentSuccess, - }, - routes: []*route.Route{rt, rt}, - }, - { - // A payment flow with a forwarding failure first time - // sending to the switch, but that succeeds on the - // second attempt. - steps: []string{ - routerInitPayment, - routerRegisterAttempt, - - // Make the first sent attempt fail. - sendToSwitchResultFailure, - - // The router should retry. - routerRegisterAttempt, - sendToSwitchSuccess, - - // Make the second sent attempt succeed. - getPaymentResultSuccess, - routerSuccess, - paymentSuccess, - }, - routes: []*route.Route{rt, rt}, - }, - { - // A payment that fails on the first attempt, and has - // only one route available to try. It will therefore - // fail permanently. - steps: []string{ - routerInitPayment, - routerRegisterAttempt, - sendToSwitchSuccess, - - // Make the first sent attempt fail. - getPaymentResultFailure, - - // Since there are no more routes to try, the - // payment should fail. - routerFail, - paymentError, - }, - routes: []*route.Route{rt}, - }, - { - // We expect the payment to fail immediately if we have - // no routes to try. - steps: []string{ - routerInitPayment, - routerFail, - paymentError, - }, - routes: []*route.Route{}, - }, - { - // A normal payment flow, where we attempt to resend - // the same payment after each step. This ensures that - // the router don't attempt to resend a payment already - // in flight. - steps: []string{ - routerInitPayment, - routerRegisterAttempt, - - // Manually resend the payment, the router - // should attempt to init with the control - // tower, but fail since it is already in - // flight. - resendPayment, - routerInitPayment, - resentPaymentError, - - // The original payment should proceed as - // normal. - sendToSwitchSuccess, - - // Again resend the payment and assert it's not - // allowed. - resendPayment, - routerInitPayment, - resentPaymentError, - - // Notify about a success for the original - // payment. - getPaymentResultSuccess, - routerSuccess, - - // Now that the original payment finished, - // resend it again to ensure this is not - // allowed. - resendPayment, - routerInitPayment, - resentPaymentError, - paymentSuccess, - }, - routes: []*route.Route{rt}, - }, - { - // Tests that the router is able to handle the - // receieved payment result after a restart. - steps: []string{ - routerInitPayment, - routerRegisterAttempt, - sendToSwitchSuccess, - - // Shut down the router. The original caller - // should get notified about this. - stopRouter, - paymentError, - - // Start the router again, and ensure the - // router registers the success with the - // control tower. - startRouter, - getPaymentResultSuccess, - routerSuccess, - }, - routes: []*route.Route{rt}, - }, - { - // Tests that we are allowed to resend a payment after - // it has permanently failed. - steps: []string{ - routerInitPayment, - routerRegisterAttempt, - sendToSwitchSuccess, - - // Resending the payment at this stage should - // not be allowed. - resendPayment, - routerInitPayment, - resentPaymentError, - - // Make the first attempt fail. - getPaymentResultFailure, - routerFail, - - // Since we have no more routes to try, the - // original payment should fail. - paymentError, - - // Now resend the payment again. This should be - // allowed, since the payment has failed. - resendPayment, - routerInitPayment, - routerRegisterAttempt, - sendToSwitchSuccess, - getPaymentResultSuccess, - routerSuccess, - resentPaymentSuccess, - }, - routes: []*route.Route{rt}, - }, - } - - // Create a mock control tower with channels set up, that we use to - // synchronize and listen for events. - control := makeMockControlTower() - control.init = make(chan initArgs) - control.register = make(chan registerArgs) - control.success = make(chan successArgs) - control.fail = make(chan failArgs) - control.fetchInFlight = make(chan struct{}) - - quit := make(chan struct{}) - defer close(quit) - - // setupRouter is a helper method that creates and starts the router in - // the desired configuration for this test. - setupRouter := func() (*ChannelRouter, chan error, - chan *htlcswitch.PaymentResult, chan error) { - - chain := newMockChain(startingBlockHeight) - chainView := newMockChainView(chain) - - // We set uo the use the following channels and a mock Payer to - // synchonize with the interaction to the Switch. - sendResult := make(chan error) - paymentResultErr := make(chan error) - paymentResult := make(chan *htlcswitch.PaymentResult) - - payer := &mockPayer{ - sendResult: sendResult, - paymentResult: paymentResult, - paymentResultErr: paymentResultErr, - } - - router, err := New(Config{ - Graph: testGraph.graph, - Chain: chain, - ChainView: chainView, - Control: control, - SessionSource: &mockPaymentSessionSource{}, - MissionControl: &mockMissionControl{}, - Payer: payer, - ChannelPruneExpiry: time.Hour * 24, - GraphPruneInterval: time.Hour * 2, - QueryBandwidth: func(e *channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi { - return lnwire.NewMSatFromSatoshis(e.Capacity) - }, - NextPaymentID: func() (uint64, error) { - next := atomic.AddUint64(&uniquePaymentID, 1) - return next, nil - }, - Clock: clock.NewTestClock(time.Unix(1, 0)), - }) - if err != nil { - t.Fatalf("unable to create router %v", err) - } - - // On startup, the router should fetch all pending payments - // from the ControlTower, so assert that here. - errCh := make(chan error) - go func() { - close(errCh) - select { - case <-control.fetchInFlight: - return - case <-time.After(1 * time.Second): - errCh <- errors.New("router did not fetch in flight " + - "payments") - } - }() - - if err := router.Start(); err != nil { - t.Fatalf("unable to start router: %v", err) - } - - select { - case err := <-errCh: - if err != nil { - t.Fatalf("error in anonymous goroutine: %s", err) - } - case <-time.After(1 * time.Second): - t.Fatalf("did not fetch in flight payments at startup") - } - - return router, sendResult, paymentResult, paymentResultErr - } - - router, sendResult, getPaymentResult, getPaymentResultErr := setupRouter() - defer router.Stop() - - for _, test := range tests { - // Craft a LightningPayment struct. - var preImage lntypes.Preimage - if _, err := rand.Read(preImage[:]); err != nil { - t.Fatalf("unable to generate preimage") - } - - payHash := preImage.Hash() - - paymentAmt := lnwire.NewMSatFromSatoshis(1000) - payment := LightningPayment{ - Target: testGraph.aliasMap["c"], - Amount: paymentAmt, - FeeLimit: noFeeLimit, - PaymentHash: payHash, - } - - router.cfg.SessionSource = &mockPaymentSessionSource{ - routes: test.routes, - } - - router.cfg.MissionControl = &mockMissionControl{} - - // Send the payment. Since this is new payment hash, the - // information should be registered with the ControlTower. - paymentResult := make(chan error) - go func() { - _, _, err := router.SendPayment(&payment) - paymentResult <- err - }() - - var resendResult chan error - for _, step := range test.steps { - switch step { - - case routerInitPayment: - var args initArgs - select { - case args = <-control.init: - case <-time.After(1 * time.Second): - t.Fatalf("no init payment with control") - } - - if args.c == nil { - t.Fatalf("expected non-nil CreationInfo") - } - - // In this step we expect the router to make a call to - // register a new attempt with the ControlTower. - case routerRegisterAttempt: - var args registerArgs - select { - case args = <-control.register: - case <-time.After(1 * time.Second): - t.Fatalf("not registered with control") - } - - if args.a == nil { - t.Fatalf("expected non-nil AttemptInfo") - } - - // In this step we expect the router to call the - // ControlTower's Succcess method with the preimage. - case routerSuccess: - select { - case _ = <-control.success: - case <-time.After(1 * time.Second): - t.Fatalf("not registered with control") - } - - // In this step we expect the router to call the - // ControlTower's Fail method, to indicate that the - // payment failed. - case routerFail: - select { - case _ = <-control.fail: - case <-time.After(1 * time.Second): - t.Fatalf("not registered with control") - } - - // In this step we expect the SendToSwitch method to be - // called, and we respond with a nil-error. - case sendToSwitchSuccess: - select { - case sendResult <- nil: - case <-time.After(1 * time.Second): - t.Fatalf("unable to send result") - } - - // In this step we expect the SendToSwitch method to be - // called, and we respond with a forwarding error - case sendToSwitchResultFailure: - select { - case sendResult <- htlcswitch.NewForwardingError( - &lnwire.FailTemporaryChannelFailure{}, - 1, - ): - case <-time.After(1 * time.Second): - t.Fatalf("unable to send result") - } - - // In this step we expect the GetPaymentResult method - // to be called, and we respond with the preimage to - // complete the payment. - case getPaymentResultSuccess: - select { - case getPaymentResult <- &htlcswitch.PaymentResult{ - Preimage: preImage, - }: - case <-time.After(1 * time.Second): - t.Fatalf("unable to send result") - } - - // In this state we expect the GetPaymentResult method - // to be called, and we respond with a forwarding - // error, indicating that the router should retry. - case getPaymentResultFailure: - failure := htlcswitch.NewForwardingError( - &lnwire.FailTemporaryChannelFailure{}, - 1, - ) - - select { - case getPaymentResult <- &htlcswitch.PaymentResult{ - Error: failure, - }: - case <-time.After(1 * time.Second): - t.Fatalf("unable to get result") - } - - // In this step we manually try to resend the same - // payment, making sure the router responds with an - // error indicating that it is alreayd in flight. - case resendPayment: - resendResult = make(chan error) - go func() { - _, _, err := router.SendPayment(&payment) - resendResult <- err - }() - - // In this step we manually stop the router. - case stopRouter: - select { - case getPaymentResultErr <- fmt.Errorf( - "shutting down"): - case <-time.After(1 * time.Second): - t.Fatalf("unable to send payment " + - "result error") - } - - if err := router.Stop(); err != nil { - t.Fatalf("unable to restart: %v", err) - } - - // In this step we manually start the router. - case startRouter: - router, sendResult, getPaymentResult, - getPaymentResultErr = setupRouter() - - // In this state we expect to receive an error for the - // original payment made. - case paymentError: - select { - case err := <-paymentResult: - if err == nil { - t.Fatalf("expected error") - } - - case <-time.After(1 * time.Second): - t.Fatalf("got no payment result") - } - - // In this state we expect the original payment to - // succeed. - case paymentSuccess: - select { - case err := <-paymentResult: - if err != nil { - t.Fatalf("did not expecte error %v", err) - } - - case <-time.After(1 * time.Second): - t.Fatalf("got no payment result") - } - - // In this state we expect to receive an error for the - // resent payment made. - case resentPaymentError: - select { - case err := <-resendResult: - if err == nil { - t.Fatalf("expected error") - } - - case <-time.After(1 * time.Second): - t.Fatalf("got no payment result") - } - - // In this state we expect the resent payment to - // succeed. - case resentPaymentSuccess: - select { - case err := <-resendResult: - if err != nil { - t.Fatalf("did not expect error %v", err) - } - - case <-time.After(1 * time.Second): - t.Fatalf("got no payment result") - } - - default: - t.Fatalf("unknown step %v", step) - } - } - } -} - // TestSendToRouteStructuredError asserts that SendToRoute returns a structured // error. func TestSendToRouteStructuredError(t *testing.T) { From aa9c971dc0ebe1f05866187ec90336d8352af16a Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:26 +0200 Subject: [PATCH 381/562] routing/payment_lifecycle_test: extract route creation into method This also fixes a test bug that the manually created route didn't match the actual payment amount in the test cases, and adds some fees to the route. --- routing/payment_lifecycle_test.go | 49 +++++++++++++++++++------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/routing/payment_lifecycle_test.go b/routing/payment_lifecycle_test.go index addca00576..5e62c33f93 100644 --- a/routing/payment_lifecycle_test.go +++ b/routing/payment_lifecycle_test.go @@ -17,6 +17,35 @@ import ( "github.com/lightningnetwork/lnd/routing/route" ) +// createTestRoute builds a route a->b->c paying the given amt to c. +func createTestRoute(amt lnwire.MilliSatoshi, + aliasMap map[string]route.Vertex) (*route.Route, error) { + + hopFee := lnwire.NewMSatFromSatoshis(3) + hop1 := aliasMap["b"] + hop2 := aliasMap["c"] + hops := []*route.Hop{ + { + ChannelID: 1, + PubKeyBytes: hop1, + LegacyPayload: true, + AmtToForward: amt + hopFee, + }, + { + ChannelID: 2, + PubKeyBytes: hop2, + LegacyPayload: true, + AmtToForward: amt, + }, + } + + // We create a simple route that we will supply every time the router + // requests one. + return route.NewRouteFromHops( + amt+2*hopFee, 100, aliasMap["a"], hops, + ) +} + // TestRouterPaymentStateMachine tests that the router interacts as expected // with the ControlTower during a payment lifecycle, such that it payment // attempts are not sent twice to the switch, and results are handled after a @@ -50,26 +79,11 @@ func TestRouterPaymentStateMachine(t *testing.T) { } defer testGraph.cleanUp() - hop1 := testGraph.aliasMap["b"] - hop2 := testGraph.aliasMap["c"] - hops := []*route.Hop{ - { - ChannelID: 1, - PubKeyBytes: hop1, - LegacyPayload: true, - }, - { - ChannelID: 2, - PubKeyBytes: hop2, - LegacyPayload: true, - }, - } + paymentAmt := lnwire.NewMSatFromSatoshis(1000) // We create a simple route that we will supply every time the router // requests one. - rt, err := route.NewRouteFromHops( - lnwire.MilliSatoshi(10000), 100, testGraph.aliasMap["a"], hops, - ) + rt, err := createTestRoute(paymentAmt, testGraph.aliasMap) if err != nil { t.Fatalf("unable to create route: %v", err) } @@ -443,7 +457,6 @@ func TestRouterPaymentStateMachine(t *testing.T) { payHash := preImage.Hash() - paymentAmt := lnwire.NewMSatFromSatoshis(1000) payment := LightningPayment{ Target: testGraph.aliasMap["c"], Amount: paymentAmt, From 2e63b518b78e90db053efae9c8b56f58a171c3f7 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:26 +0200 Subject: [PATCH 382/562] routing/payment_lifecycle_test+mock: set up listener for FailAttempt Also rename Success to SettleAttempt in the tests. --- routing/mock_test.go | 37 ++++++++------ routing/payment_lifecycle_test.go | 83 ++++++++++++++++++++----------- 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/routing/mock_test.go b/routing/mock_test.go index be62d9102e..594c14834f 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -176,15 +176,19 @@ type initArgs struct { c *channeldb.PaymentCreationInfo } -type registerArgs struct { +type registerAttemptArgs struct { a *channeldb.HTLCAttemptInfo } -type successArgs struct { +type settleAttemptArgs struct { preimg lntypes.Preimage } -type failArgs struct { +type failAttemptArgs struct { + reason *channeldb.HTLCFailInfo +} + +type failPaymentArgs struct { reason channeldb.FailureReason } @@ -198,11 +202,12 @@ type mockControlTower struct { successful map[lntypes.Hash]struct{} failed map[lntypes.Hash]channeldb.FailureReason - init chan initArgs - register chan registerArgs - success chan successArgs - fail chan failArgs - fetchInFlight chan struct{} + init chan initArgs + registerAttempt chan registerAttemptArgs + settleAttempt chan settleAttemptArgs + failAttempt chan failAttemptArgs + failPayment chan failPaymentArgs + fetchInFlight chan struct{} sync.Mutex } @@ -254,8 +259,8 @@ func (m *mockControlTower) RegisterAttempt(phash lntypes.Hash, m.Lock() defer m.Unlock() - if m.register != nil { - m.register <- registerArgs{a} + if m.registerAttempt != nil { + m.registerAttempt <- registerAttemptArgs{a} } // Cannot register attempts for successful or failed payments. @@ -286,8 +291,8 @@ func (m *mockControlTower) SettleAttempt(phash lntypes.Hash, m.Lock() defer m.Unlock() - if m.success != nil { - m.success <- successArgs{settleInfo.Preimage} + if m.settleAttempt != nil { + m.settleAttempt <- settleAttemptArgs{settleInfo.Preimage} } // Only allow setting attempts if the payment is known. @@ -325,6 +330,10 @@ func (m *mockControlTower) FailAttempt(phash lntypes.Hash, pid uint64, m.Lock() defer m.Unlock() + if m.failAttempt != nil { + m.failAttempt <- failAttemptArgs{failInfo} + } + // Only allow failing attempts if the payment is known. p, ok := m.payments[phash] if !ok { @@ -357,8 +366,8 @@ func (m *mockControlTower) Fail(phash lntypes.Hash, m.Lock() defer m.Unlock() - if m.fail != nil { - m.fail <- failArgs{reason} + if m.failPayment != nil { + m.failPayment <- failPaymentArgs{reason} } // Payment must be known. diff --git a/routing/payment_lifecycle_test.go b/routing/payment_lifecycle_test.go index 5e62c33f93..4c371b0665 100644 --- a/routing/payment_lifecycle_test.go +++ b/routing/payment_lifecycle_test.go @@ -109,13 +109,18 @@ func TestRouterPaymentStateMachine(t *testing.T) { // tower. routerRegisterAttempt = "Router:register-attempt" - // routerSuccess is a test step where we expect the router to - // call the Success method on the control tower. - routerSuccess = "Router:success" + // routerSettleAttempt is a test step where we expect the + // router to call the SettleAttempt method on the control + // tower. + routerSettleAttempt = "Router:settle-attempt" + + // routerFailAttempt is a test step where we expect the router + // to call the FailAttempt method on the control tower. + routerFailAttempt = "Router:fail-attempt" - // routerFail is a test step where we expect the router to call - // the Fail method on the control tower. - routerFail = "Router:fail" + // routerFailPayment is a test step where we expect the router + // to call the Fail method on the control tower. + routerFailPayment = "Router:fail-payment" // sendToSwitchSuccess is a step where we expect the router to // call send the payment attempt to the switch, and we will @@ -178,7 +183,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { routerRegisterAttempt, sendToSwitchSuccess, getPaymentResultSuccess, - routerSuccess, + routerSettleAttempt, paymentSuccess, }, routes: []*route.Route{rt}, @@ -193,6 +198,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { // Make the first sent attempt fail. getPaymentResultFailure, + routerFailAttempt, // The router should retry. routerRegisterAttempt, @@ -200,7 +206,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { // Make the second sent attempt succeed. getPaymentResultSuccess, - routerSuccess, + routerSettleAttempt, paymentSuccess, }, routes: []*route.Route{rt, rt}, @@ -215,6 +221,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { // Make the first sent attempt fail. sendToSwitchResultFailure, + routerFailAttempt, // The router should retry. routerRegisterAttempt, @@ -222,7 +229,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { // Make the second sent attempt succeed. getPaymentResultSuccess, - routerSuccess, + routerSettleAttempt, paymentSuccess, }, routes: []*route.Route{rt, rt}, @@ -238,10 +245,11 @@ func TestRouterPaymentStateMachine(t *testing.T) { // Make the first sent attempt fail. getPaymentResultFailure, + routerFailAttempt, // Since there are no more routes to try, the // payment should fail. - routerFail, + routerFailPayment, paymentError, }, routes: []*route.Route{rt}, @@ -251,7 +259,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { // no routes to try. steps: []string{ routerInitPayment, - routerFail, + routerFailPayment, paymentError, }, routes: []*route.Route{}, @@ -286,7 +294,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { // Notify about a success for the original // payment. getPaymentResultSuccess, - routerSuccess, + routerSettleAttempt, // Now that the original payment finished, // resend it again to ensure this is not @@ -316,7 +324,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { // control tower. startRouter, getPaymentResultSuccess, - routerSuccess, + routerSettleAttempt, }, routes: []*route.Route{rt}, }, @@ -336,10 +344,11 @@ func TestRouterPaymentStateMachine(t *testing.T) { // Make the first attempt fail. getPaymentResultFailure, - routerFail, + routerFailAttempt, // Since we have no more routes to try, the // original payment should fail. + routerFailPayment, paymentError, // Now resend the payment again. This should be @@ -349,7 +358,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { routerRegisterAttempt, sendToSwitchSuccess, getPaymentResultSuccess, - routerSuccess, + routerSettleAttempt, resentPaymentSuccess, }, routes: []*route.Route{rt}, @@ -360,9 +369,10 @@ func TestRouterPaymentStateMachine(t *testing.T) { // synchronize and listen for events. control := makeMockControlTower() control.init = make(chan initArgs) - control.register = make(chan registerArgs) - control.success = make(chan successArgs) - control.fail = make(chan failArgs) + control.registerAttempt = make(chan registerAttemptArgs) + control.settleAttempt = make(chan settleAttemptArgs) + control.failAttempt = make(chan failAttemptArgs) + control.failPayment = make(chan failPaymentArgs) control.fetchInFlight = make(chan struct{}) quit := make(chan struct{}) @@ -497,11 +507,12 @@ func TestRouterPaymentStateMachine(t *testing.T) { // In this step we expect the router to make a call to // register a new attempt with the ControlTower. case routerRegisterAttempt: - var args registerArgs + var args registerAttemptArgs select { - case args = <-control.register: + case args = <-control.registerAttempt: case <-time.After(1 * time.Second): - t.Fatalf("not registered with control") + t.Fatalf("attempt not registered " + + "with control") } if args.a == nil { @@ -509,22 +520,35 @@ func TestRouterPaymentStateMachine(t *testing.T) { } // In this step we expect the router to call the - // ControlTower's Succcess method with the preimage. - case routerSuccess: + // ControlTower's SettleAttempt method with the preimage. + case routerSettleAttempt: + select { + case <-control.settleAttempt: + case <-time.After(1 * time.Second): + t.Fatalf("attempt settle not " + + "registered with control") + } + + // In this step we expect the router to call the + // ControlTower's FailAttempt method with a HTLC fail + // info. + case routerFailAttempt: select { - case <-control.success: + case <-control.failAttempt: case <-time.After(1 * time.Second): - t.Fatalf("not registered with control") + t.Fatalf("attempt fail not " + + "registered with control") } // In this step we expect the router to call the // ControlTower's Fail method, to indicate that the // payment failed. - case routerFail: + case routerFailPayment: select { - case <-control.fail: + case <-control.failPayment: case <-time.After(1 * time.Second): - t.Fatalf("not registered with control") + t.Fatalf("payment fail not " + + "registered with control") } // In this step we expect the SendToSwitch method to be @@ -625,7 +649,8 @@ func TestRouterPaymentStateMachine(t *testing.T) { select { case err := <-paymentResult: if err != nil { - t.Fatalf("did not expecte error %v", err) + t.Fatalf("did not expect "+ + "error %v", err) } case <-time.After(1 * time.Second): From 0fd71cd5965171a8925ebcdeb139868a69d5c3e0 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:26 +0200 Subject: [PATCH 383/562] routing/payment_lifecycle_test: add step for terminal failure And modify the MissionControl mock to return a non-nil failure reason in this case. --- routing/mock_test.go | 7 ++++++ routing/payment_lifecycle_test.go | 38 +++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/routing/mock_test.go b/routing/mock_test.go index 594c14834f..36523a973d 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -101,6 +101,13 @@ func (m *mockMissionControl) ReportPaymentFail(paymentID uint64, rt *route.Route failureSourceIdx *int, failure lnwire.FailureMessage) ( *channeldb.FailureReason, error) { + // Report a permanent failure if this is an error caused + // by incorrect details. + if failure.Code() == lnwire.CodeIncorrectOrUnknownPaymentDetails { + reason := channeldb.FailureReasonPaymentDetails + return &reason, nil + } + return nil, nil } diff --git a/routing/payment_lifecycle_test.go b/routing/payment_lifecycle_test.go index 4c371b0665..7e492ea755 100644 --- a/routing/payment_lifecycle_test.go +++ b/routing/payment_lifecycle_test.go @@ -139,10 +139,16 @@ func TestRouterPaymentStateMachine(t *testing.T) { // respond with a successful payment result. getPaymentResultSuccess = "GetPaymentResult:success" - // getPaymentResultFailure is a test step where we expect the + // getPaymentResultTempFailure is a test step where we expect the // router to call the GetPaymentResult method, and we will - // respond with a forwarding error. - getPaymentResultFailure = "GetPaymentResult:failure" + // respond with a forwarding error, expecting the router to retry. + getPaymentResultTempFailure = "GetPaymentResult:temp-failure" + + // getPaymentResultTerminalFailure is a test step where we + // expect the router to call the GetPaymentResult method, and + // we will respond with a terminal error, expecting the router + // to stop making payment attempts. + getPaymentResultTerminalFailure = "GetPaymentResult:terminal-failure" // resendPayment is a test step where we manually try to resend // the same payment, making sure the router responds with an @@ -197,7 +203,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { sendToSwitchSuccess, // Make the first sent attempt fail. - getPaymentResultFailure, + getPaymentResultTempFailure, routerFailAttempt, // The router should retry. @@ -244,7 +250,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { sendToSwitchSuccess, // Make the first sent attempt fail. - getPaymentResultFailure, + getPaymentResultTempFailure, routerFailAttempt, // Since there are no more routes to try, the @@ -343,7 +349,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { resentPaymentError, // Make the first attempt fail. - getPaymentResultFailure, + getPaymentResultTempFailure, routerFailAttempt, // Since we have no more routes to try, the @@ -587,7 +593,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { // In this state we expect the GetPaymentResult method // to be called, and we respond with a forwarding // error, indicating that the router should retry. - case getPaymentResultFailure: + case getPaymentResultTempFailure: failure := htlcswitch.NewForwardingError( &lnwire.FailTemporaryChannelFailure{}, 1, @@ -601,6 +607,24 @@ func TestRouterPaymentStateMachine(t *testing.T) { t.Fatalf("unable to get result") } + // In this state we expect the router to call the + // GetPaymentResult method, and we will respond with a + // terminal error, indiating the router should stop + // making payment attempts. + case getPaymentResultTerminalFailure: + failure := htlcswitch.NewForwardingError( + &lnwire.FailIncorrectDetails{}, + 1, + ) + + select { + case getPaymentResult <- &htlcswitch.PaymentResult{ + Error: failure, + }: + case <-time.After(1 * time.Second): + t.Fatalf("unable to get result") + } + // In this step we manually try to resend the same // payment, making sure the router responds with an // error indicating that it is already in flight. From 7b318a4be7808b7f40e10e38864a95c2fc2a05b5 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:26 +0200 Subject: [PATCH 384/562] routing/payment_lifecycle+channeldb: enable multi shard send This commit finally enables MP payments within the payment lifecycle (used for SendPayment). This is done by letting the loop launch shards as long as there is value remaining to send, inspecting the outcomes for the sent shards when the full payment amount has been filled. The method channeldb.MPPayment.SentAmt() is added to easily look up how much value we have sent for the payment. --- channeldb/mp_payment.go | 18 ++ routing/payment_lifecycle.go | 412 +++++++++++++++++++++++++---------- 2 files changed, 309 insertions(+), 121 deletions(-) diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index bf2f65ef35..e359ff03df 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -144,6 +144,24 @@ func (m *MPPayment) TerminalInfo() (*HTLCSettleInfo, *FailureReason) { return nil, m.FailureReason } +// SentAmt returns the sum of sent amount and fees for HTLCs that are either +// settled or still in flight. +func (m *MPPayment) SentAmt() (lnwire.MilliSatoshi, lnwire.MilliSatoshi) { + var sent, fees lnwire.MilliSatoshi + for _, h := range m.HTLCs { + if h.Failure != nil { + continue + } + + // The attempt was not failed, meaning the amount was + // potentially sent to the receiver. + sent += h.Route.ReceiverAmt() + fees += h.Route.TotalFees() + } + + return sent, fees +} + // InFlightHTLCs returns the HTLCs that are still in-flight, meaning they have // not been settled or failed. func (m *MPPayment) InFlightHTLCs() []HTLCAttempt { diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 6e98eb1b08..3a0eb75b89 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -1,6 +1,8 @@ package routing import ( + "fmt" + "sync" "time" "github.com/davecgh/go-spew/spew" @@ -24,14 +26,74 @@ type paymentLifecycle struct { currentHeight int32 } +// payemntState holds a number of key insights learned from a given MPPayment +// that we use to determine what to do on each payment loop iteration. +type paymentState struct { + numShardsInFlight int + remainingAmt lnwire.MilliSatoshi + remainingFees lnwire.MilliSatoshi + terminate bool +} + +// paymentState uses the passed payment to find the latest information we need +// to act on every iteration of the payment loop. +func (p *paymentLifecycle) paymentState(payment *channeldb.MPPayment) ( + *paymentState, error) { + + // Fetch the total amount and fees that has already been sent in + // settled and still in-flight shards. + sentAmt, fees := payment.SentAmt() + + // Sanity check we haven't sent a value larger than the payment amount. + if sentAmt > p.totalAmount { + return nil, fmt.Errorf("amount sent %v exceeds "+ + "total amount %v", sentAmt, p.totalAmount) + } + + // We'll subtract the used fee from our fee budget, but allow the fees + // of the already sent shards to exceed our budget (can happen after + // restarts). + feeBudget := p.feeLimit + if fees <= feeBudget { + feeBudget -= fees + } else { + feeBudget = 0 + } + + // Get any terminal info for this payment. + settle, failure := payment.TerminalInfo() + + // If either an HTLC settled, or the payment has a payment level + // failure recorded, it means we should terminate the moment all shards + // have returned with a result. + terminate := settle != nil || failure != nil + + activeShards := payment.InFlightHTLCs() + return &paymentState{ + numShardsInFlight: len(activeShards), + remainingAmt: p.totalAmount - sentAmt, + remainingFees: feeBudget, + terminate: terminate, + }, nil +} + // resumePayment resumes the paymentLifecycle from the current state. func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { shardHandler := &shardHandler{ router: p.router, paymentHash: p.paymentHash, + shardErrors: make(chan error), + quit: make(chan struct{}), } - // If we have an existing attempt, we'll start by collecting its result. + // When the payment lifecycle loop exits, we make sure to signal any + // sub goroutine of the shardHandler to exit, then wait for them to + // return. + defer shardHandler.stop() + + // If we had any existing attempts outstanding, we'll start by spinning + // up goroutines that'll collect their results and deliver them to the + // lifecycle loop below. payment, err := p.router.cfg.Control.FetchPayment( p.paymentHash, ) @@ -42,15 +104,21 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { for _, a := range payment.InFlightHTLCs() { a := a - _, err := shardHandler.collectResult(&a.HTLCAttemptInfo) - if err != nil { - return [32]byte{}, nil, err - } + log.Debugf("Resuming payment shard %v for hash %v", + a.AttemptID, p.paymentHash) + + shardHandler.collectResultAsync(&a.HTLCAttemptInfo) } // We'll continue until either our payment succeeds, or we encounter a // critical error during path finding. for { + // Start by quickly checking if there are any outcomes already + // available to handle before we reevaluate our state. + if err := shardHandler.checkShards(); err != nil { + return [32]byte{}, nil, err + } + // We start every iteration by fetching the lastest state of // the payment from the ControlTower. This ensures that we will // act on the latest available information, whether we are @@ -62,90 +130,97 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { return [32]byte{}, nil, err } - // Go through the HTLCs for this payment, determining if there - // are any in flight or settled. - var ( - attempt *channeldb.HTLCAttemptInfo - settle *channeldb.HTLCAttempt - ) - for _, a := range payment.HTLCs { - a := a - - // We have a settled HTLC, and should return when all - // shards are back. - if a.Settle != nil { - settle = &a - continue - } - - // This HTLC already failed, ignore. - if a.Failure != nil { - continue - } - - // HTLC was neither setteld nor failed, it is still in - // flight. - attempt = &a.HTLCAttemptInfo - break + // Using this latest state of the payment, calculate + // information about our active shards and terminal conditions. + state, err := p.paymentState(payment) + if err != nil { + return [32]byte{}, nil, err } - // Terminal state, return the preimage and the route taken. - if attempt == nil && settle != nil { - return settle.Settle.Preimage, &settle.Route, nil - } + log.Debugf("Payment %v in state terminate=%v, "+ + "active_shards=%v, rem_value=%v, fee_limit=%v", + p.paymentHash, state.terminate, state.numShardsInFlight, + state.remainingAmt, state.remainingFees) + + switch { + + // We have a terminal condition and no active shards, we are + // ready to exit. + case state.terminate && state.numShardsInFlight == 0: + // Find the first successful shard and return + // the preimage and route. + for _, a := range payment.HTLCs { + if a.Settle != nil { + return a.Settle.Preimage, &a.Route, nil + } + } - // If the payment already is failed, and there is no in-flight - // HTLC, return immediately. - if attempt == nil && payment.FailureReason != nil { + // Payment failed. return [32]byte{}, nil, *payment.FailureReason - } - // If this payment had no existing payment attempt, we create - // and send one now. - if attempt == nil { - // Before we attempt this next payment, we'll check to see if either - // we've gone past the payment attempt timeout, or the router is - // exiting. In either case, we'll stop this payment attempt short. If a - // timeout is not applicable, timeoutChan will be nil. - select { - case <-p.timeoutChan: - // Mark the payment as failed because of the - // timeout. - err := p.router.cfg.Control.Fail( - p.paymentHash, channeldb.FailureReasonTimeout, - ) - if err != nil { - return [32]byte{}, nil, err - } + // If we either reached a terminal error condition (but had + // active shards still) or there is no remaining value to send, + // we'll wait for a shard outcome. + case state.terminate || state.remainingAmt == 0: + // We still have outstanding shards, so wait for a new + // outcome to be available before re-evaluating our + // state. + if err := shardHandler.waitForShard(); err != nil { + return [32]byte{}, nil, err + } + continue + } - continue + // Before we attempt any new shard, we'll check to see if + // either we've gone past the payment attempt timeout, or the + // router is exiting. In either case, we'll stop this payment + // attempt short. If a timeout is not applicable, timeoutChan + // will be nil. + select { + case <-p.timeoutChan: + log.Warnf("payment attempt not completed before " + + "timeout") + + // By marking the payment failed with the control + // tower, no further shards will be launched and we'll + // return with an error the moment all active shards + // have finished. + saveErr := p.router.cfg.Control.Fail( + p.paymentHash, channeldb.FailureReasonTimeout, + ) + if saveErr != nil { + return [32]byte{}, nil, saveErr + } - // The payment will be resumed from the current state - // after restart. - case <-p.router.quit: - return [32]byte{}, nil, ErrRouterShuttingDown + continue - // Fall through if we haven't hit our time limit or are - // exiting. - default: - } + case <-p.router.quit: + return [32]byte{}, nil, ErrRouterShuttingDown - // Create a new payment attempt from the given payment session. - rt, err := p.paySession.RequestRoute( - p.totalAmount, p.feeLimit, 0, uint32(p.currentHeight), - ) - if err != nil { - log.Warnf("Failed to find route for payment %x: %v", - p.paymentHash, err) + // Fall through if we haven't hit our time limit. + default: + } - // Convert error to payment-level failure. - failure := errorToPaymentFailure(err) + // Create a new payment attempt from the given payment session. + rt, err := p.paySession.RequestRoute( + state.remainingAmt, state.remainingFees, + uint32(state.numShardsInFlight), uint32(p.currentHeight), + ) + if err != nil { + log.Warnf("Failed to find route for payment %x: %v", + p.paymentHash, err) + + // There is no route to try, and we have no active + // shards. This means that there is no way for us to + // send the payment, so mark it failed with no route. + if state.numShardsInFlight == 0 { + failureCode := errorToPaymentFailure(err) + log.Debugf("Marking payment %v permanently "+ + "failed with no route: %v", + p.paymentHash, failureCode) - // If we're unable to successfully make a payment using - // any of the routes we've found, then mark the payment - // as permanently failed. saveErr := p.router.cfg.Control.Fail( - p.paymentHash, failure, + p.paymentHash, failureCode, ) if saveErr != nil { return [32]byte{}, nil, saveErr @@ -154,56 +229,45 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { continue } - // With the route in hand, launch a new shard. - var outcome *launchOutcome - attempt, outcome, err = shardHandler.launchShard(rt) - if err != nil { + // We still have active shards, we'll wait for an + // outcome to be available before retrying. + if err := shardHandler.waitForShard(); err != nil { return [32]byte{}, nil, err } + continue + } - // We ew encountered a non-critical error when - // launching the shard, handle it - if outcome.err != nil { - // We must inspect the error to know whether it - // was critical or not, to decide whether we - // should continue trying. - err = shardHandler.handleSendError( - attempt, outcome.err, - ) - if err != nil { - return [32]byte{}, nil, err - } - - // Error was handled successfully, continue to - // make a new attempt. - continue - } + // We found a route to try, launch a new shard. + attempt, outcome, err := shardHandler.launchShard(rt) + if err != nil { + return [32]byte{}, nil, err + } - // We'll collect the result of the shard just sent. We - // ignore the result for now if it is a success, as we - // will look it up in the control tower on the next - // loop iteration. - result, err := shardHandler.collectResult(attempt) + // If we encountered a non-critical error when launching the + // shard, handle it. + if outcome.err != nil { + log.Warnf("Failed to launch shard %v for "+ + "payment %v: %v", attempt.AttemptID, + p.paymentHash, outcome.err) + + // We must inspect the error to know whether it was + // critical or not, to decide whether we should + // continue trying. + err := shardHandler.handleSendError( + attempt, outcome.err, + ) if err != nil { return [32]byte{}, nil, err } - if result.err != nil { - // We must inspect the error to know whether it - // was critical or not, to decide whether we - // should continue trying. - err := shardHandler.handleSendError( - attempt, result.err, - ) - if err != nil { - return [32]byte{}, nil, err - } - - // Error was handled successfully, continue to - // make a new attempt. - continue - } + // Error was handled successfully, continue to make a + // new attempt. + continue } + + // Now that the shard was successfully sent, launch a go + // routine that will handle its result when its back. + shardHandler.collectResultAsync(attempt) } } @@ -212,6 +276,60 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { type shardHandler struct { paymentHash lntypes.Hash router *ChannelRouter + + // shardErrors is a channel where errors collected by calling + // collectResultAsync will be delivered. These results are meant to be + // inspected by calling waitForShard or checkShards, and the channel + // doesn't need to be initiated if the caller is using the sync + // collectResult directly. + shardErrors chan error + + // quit is closed to signal the sub goroutines of the payment lifecycle + // to stop. + quit chan struct{} + wg sync.WaitGroup +} + +// stop signals any active shard goroutine to exit and waits for them to exit. +func (p *shardHandler) stop() { + close(p.quit) + p.wg.Wait() +} + +// waitForShard blocks until any of the outstanding shards return. +func (p *shardHandler) waitForShard() error { + select { + case err := <-p.shardErrors: + return err + + case <-p.quit: + return fmt.Errorf("shard handler quitting") + + case <-p.router.quit: + return ErrRouterShuttingDown + } +} + +// checkShards is a non-blocking method that check if any shards has finished +// their execution. +func (p *shardHandler) checkShards() error { + for { + select { + case err := <-p.shardErrors: + if err != nil { + return err + } + + case <-p.quit: + return fmt.Errorf("shard handler quitting") + + case <-p.router.quit: + return ErrRouterShuttingDown + + default: + return nil + } + } } // launchOutcome is a type returned from launchShard that indicates whether the @@ -283,6 +401,55 @@ type shardResult struct { err error } +// collectResultAsync launches a goroutine that will wait for the result of the +// given HTLC attempt to be available then handle its result. Note that it will +// fail the payment with the control tower if a terminal error is encountered. +func (p *shardHandler) collectResultAsync(attempt *channeldb.HTLCAttemptInfo) { + p.wg.Add(1) + go func() { + defer p.wg.Done() + + // Block until the result is available. + result, err := p.collectResult(attempt) + if err != nil { + if err != ErrRouterShuttingDown && + err != htlcswitch.ErrSwitchExiting { + + log.Errorf("Error collecting result for "+ + "shard %v for payment %v: %v", + attempt.AttemptID, p.paymentHash, err) + } + + select { + case p.shardErrors <- err: + case <-p.router.quit: + case <-p.quit: + } + return + } + + // If a non-critical error was encountered handle it and mark + // the payment failed if the failure was terminal. + if result.err != nil { + err := p.handleSendError(attempt, result.err) + if err != nil { + select { + case p.shardErrors <- err: + case <-p.router.quit: + case <-p.quit: + } + return + } + } + + select { + case p.shardErrors <- nil: + case <-p.router.quit: + case <-p.quit: + } + }() +} + // collectResult waits for the result for the given attempt to be available // from the Switch, then records the attempt outcome with the control tower. A // shardResult is returned, indicating the final outcome of this HTLC attempt. @@ -353,14 +520,14 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) ( case <-p.router.quit: return nil, ErrRouterShuttingDown + + case <-p.quit: + return nil, fmt.Errorf("shard handler exiting") } // In case of a payment failure, fail the attempt with the control // tower and return. if result.Error != nil { - log.Errorf("Attempt to send payment %x failed: %v", - p.paymentHash, result.Error) - err := p.failAttempt(attempt, result.Error) if err != nil { return nil, err @@ -540,6 +707,9 @@ func (p *shardHandler) handleSendError(attempt *channeldb.HTLCAttemptInfo, func (p *shardHandler) failAttempt(attempt *channeldb.HTLCAttemptInfo, sendError error) error { + log.Warnf("Attempt %v for payment %v failed: %v", attempt.AttemptID, + p.paymentHash, sendError) + failInfo := marshallError( sendError, p.router.cfg.Clock.Now(), From 431372c0cfc18242a9a8470f7673a797ef29a2fc Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:26 +0200 Subject: [PATCH 385/562] routing/payment_lifecycle_test: add MPP test cases --- routing/payment_lifecycle_test.go | 225 +++++++++++++++++++++++++++--- 1 file changed, 204 insertions(+), 21 deletions(-) diff --git a/routing/payment_lifecycle_test.go b/routing/payment_lifecycle_test.go index 7e492ea755..e83ac17f44 100644 --- a/routing/payment_lifecycle_test.go +++ b/routing/payment_lifecycle_test.go @@ -17,6 +17,8 @@ import ( "github.com/lightningnetwork/lnd/routing/route" ) +const stepTimeout = 5 * time.Second + // createTestRoute builds a route a->b->c paying the given amt to c. func createTestRoute(amt lnwire.MilliSatoshi, aliasMap map[string]route.Vertex) (*route.Route, error) { @@ -88,6 +90,11 @@ func TestRouterPaymentStateMachine(t *testing.T) { t.Fatalf("unable to create route: %v", err) } + shard, err := createTestRoute(paymentAmt/4, testGraph.aliasMap) + if err != nil { + t.Fatalf("unable to create route: %v", err) + } + // A payment state machine test case consists of several ordered steps, // that we use for driving the scenario. type testCase struct { @@ -369,17 +376,193 @@ func TestRouterPaymentStateMachine(t *testing.T) { }, routes: []*route.Route{rt}, }, + + // ===================================== + // || MPP scenarios || + // ===================================== + { + // Tests a simple successful MP payment of 4 shards. + steps: []string{ + routerInitPayment, + + // shard 0 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 1 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 2 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 3 + routerRegisterAttempt, + sendToSwitchSuccess, + + // All shards succeed. + getPaymentResultSuccess, + getPaymentResultSuccess, + getPaymentResultSuccess, + getPaymentResultSuccess, + + // Router should settle them all. + routerSettleAttempt, + routerSettleAttempt, + routerSettleAttempt, + routerSettleAttempt, + + // And the final result is obviously + // successful. + paymentSuccess, + }, + routes: []*route.Route{shard, shard, shard, shard}, + }, + { + // An MP payment scenario where we need several extra + // attempts before the payment finally settle. + steps: []string{ + routerInitPayment, + + // shard 0 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 1 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 2 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 3 + routerRegisterAttempt, + sendToSwitchSuccess, + + // First two shards fail, two new ones are sent. + getPaymentResultTempFailure, + getPaymentResultTempFailure, + routerFailAttempt, + routerFailAttempt, + + routerRegisterAttempt, + sendToSwitchSuccess, + routerRegisterAttempt, + sendToSwitchSuccess, + + // The four shards settle. + getPaymentResultSuccess, + getPaymentResultSuccess, + getPaymentResultSuccess, + getPaymentResultSuccess, + routerSettleAttempt, + routerSettleAttempt, + routerSettleAttempt, + routerSettleAttempt, + + // Overall payment succeeds. + paymentSuccess, + }, + routes: []*route.Route{ + shard, shard, shard, shard, shard, shard, + }, + }, + { + // An MP payment scenario where 3 of the shards fail. + // However the last shard settle, which means we get + // the preimage and should consider the overall payment + // a success. + steps: []string{ + routerInitPayment, + + // shard 0 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 1 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 2 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 3 + routerRegisterAttempt, + sendToSwitchSuccess, + + // 3 shards fail, and should be failed by the + // router. + getPaymentResultTempFailure, + getPaymentResultTempFailure, + getPaymentResultTempFailure, + routerFailAttempt, + routerFailAttempt, + routerFailAttempt, + + // The fourth shard succeed against all odds, + // making the overall payment succeed. + getPaymentResultSuccess, + routerSettleAttempt, + paymentSuccess, + }, + routes: []*route.Route{shard, shard, shard, shard}, + }, + { + // An MP payment scenario a shard fail with a terminal + // error, causing the router to stop attempting. + steps: []string{ + routerInitPayment, + + // shard 0 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 1 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 2 + routerRegisterAttempt, + sendToSwitchSuccess, + + // shard 3 + routerRegisterAttempt, + sendToSwitchSuccess, + + // The first shard fail with a terminal error. + getPaymentResultTerminalFailure, + routerFailAttempt, + routerFailPayment, + + // Remaining 3 shards fail. + getPaymentResultTempFailure, + getPaymentResultTempFailure, + getPaymentResultTempFailure, + routerFailAttempt, + routerFailAttempt, + routerFailAttempt, + + // Payment fails. + paymentError, + }, + routes: []*route.Route{ + shard, shard, shard, shard, shard, shard, + }, + }, } // Create a mock control tower with channels set up, that we use to // synchronize and listen for events. control := makeMockControlTower() - control.init = make(chan initArgs) - control.registerAttempt = make(chan registerAttemptArgs) - control.settleAttempt = make(chan settleAttemptArgs) - control.failAttempt = make(chan failAttemptArgs) - control.failPayment = make(chan failPaymentArgs) - control.fetchInFlight = make(chan struct{}) + control.init = make(chan initArgs, 20) + control.registerAttempt = make(chan registerAttemptArgs, 20) + control.settleAttempt = make(chan settleAttemptArgs, 20) + control.failAttempt = make(chan failAttemptArgs, 20) + control.failPayment = make(chan failPaymentArgs, 20) + control.fetchInFlight = make(chan struct{}, 20) quit := make(chan struct{}) defer close(quit) @@ -502,7 +685,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { var args initArgs select { case args = <-control.init: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("no init payment with control") } @@ -516,7 +699,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { var args registerAttemptArgs select { case args = <-control.registerAttempt: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("attempt not registered " + "with control") } @@ -530,7 +713,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { case routerSettleAttempt: select { case <-control.settleAttempt: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("attempt settle not " + "registered with control") } @@ -541,7 +724,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { case routerFailAttempt: select { case <-control.failAttempt: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("attempt fail not " + "registered with control") } @@ -552,7 +735,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { case routerFailPayment: select { case <-control.failPayment: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("payment fail not " + "registered with control") } @@ -562,7 +745,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { case sendToSwitchSuccess: select { case sendResult <- nil: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("unable to send result") } @@ -574,7 +757,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { &lnwire.FailTemporaryChannelFailure{}, 1, ): - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("unable to send result") } @@ -586,7 +769,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { case getPaymentResult <- &htlcswitch.PaymentResult{ Preimage: preImage, }: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("unable to send result") } @@ -603,7 +786,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { case getPaymentResult <- &htlcswitch.PaymentResult{ Error: failure, }: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("unable to get result") } @@ -621,7 +804,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { case getPaymentResult <- &htlcswitch.PaymentResult{ Error: failure, }: - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("unable to get result") } @@ -640,7 +823,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { select { case getPaymentResultErr <- fmt.Errorf( "shutting down"): - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("unable to send payment " + "result error") } @@ -663,7 +846,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { t.Fatalf("expected error") } - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("got no payment result") } @@ -677,7 +860,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { "error %v", err) } - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("got no payment result") } @@ -690,7 +873,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { t.Fatalf("expected error") } - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("got no payment result") } @@ -703,7 +886,7 @@ func TestRouterPaymentStateMachine(t *testing.T) { t.Fatalf("did not expect error %v", err) } - case <-time.After(1 * time.Second): + case <-time.After(stepTimeout): t.Fatalf("got no payment result") } From 36a80b4d51e2a94ebe5ba68abb14a0a4e4ab8e35 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:27 +0200 Subject: [PATCH 386/562] routing/router: enable MPP sends for SendToRoute This commit enables MPP sends for SendToRoute, by allowing launching another payment attempt if the hash is already registered with the ControlTower. We also set the total payment amount of of the payment from mpp record, to indicate that the shard value might be different from the total payment value. We only mark non-MPP payments as failed in the database after encountering a failure, since we might want to try more shards for MPP. For now this means that MPP sendToRoute payments will be failed only after a restart has happened. --- routing/router.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/routing/router.go b/routing/router.go index a5cf84881d..cac3e69d46 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1732,6 +1732,14 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) ( // Calculate amount paid to receiver. amt := rt.ReceiverAmt() + // If this is meant as a MP payment shard, we set the amount + // for the creating info to the total amount of the payment. + finalHop := rt.Hops[len(rt.Hops)-1] + mpp := finalHop.MPP + if mpp != nil { + amt = mpp.TotalMsat() + } + // Record this payment hash with the ControlTower, ensuring it is not // already in-flight. info := &channeldb.PaymentCreationInfo{ @@ -1742,7 +1750,13 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) ( } err := r.cfg.Control.InitPayment(hash, info) - if err != nil { + switch { + // If this is an MPP attempt and the hash is already registered with + // the database, we can go on to launch the shard. + case err == channeldb.ErrPaymentInFlight && mpp != nil: + + // Any other error is not tolerated. + case err != nil: return [32]byte{}, err } From 9a1ec950bd9198a6e334d553a096914882670b5f Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:27 +0200 Subject: [PATCH 387/562] channeldb/payments: extract common info fetch into fetchCreationInfo --- channeldb/payment_control.go | 9 +-------- channeldb/payments.go | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 81b4d94400..d0bbae7550 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -548,14 +548,7 @@ func (p *PaymentControl) FetchInFlightPayments() ([]*InFlightPayment, error) { inFlight := &InFlightPayment{} // Get the CreationInfo. - b := bucket.Get(paymentCreationInfoKey) - if b == nil { - return fmt.Errorf("unable to find creation " + - "info for inflight payment") - } - - r := bytes.NewReader(b) - inFlight.Info, err = deserializePaymentCreationInfo(r) + inFlight.Info, err = fetchCreationInfo(bucket) if err != nil { return err } diff --git a/channeldb/payments.go b/channeldb/payments.go index c07005ab43..6c5730435f 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -252,6 +252,16 @@ func (db *DB) FetchPayments() ([]*MPPayment, error) { return payments, nil } +func fetchCreationInfo(bucket kvdb.ReadBucket) (*PaymentCreationInfo, error) { + b := bucket.Get(paymentCreationInfoKey) + if b == nil { + return nil, fmt.Errorf("creation info not found") + } + + r := bytes.NewReader(b) + return deserializePaymentCreationInfo(r) +} + func fetchPayment(bucket kvdb.ReadBucket) (*MPPayment, error) { seqBytes := bucket.Get(paymentSequenceKey) if seqBytes == nil { @@ -261,13 +271,7 @@ func fetchPayment(bucket kvdb.ReadBucket) (*MPPayment, error) { sequenceNum := binary.BigEndian.Uint64(seqBytes) // Get the PaymentCreationInfo. - b := bucket.Get(paymentCreationInfoKey) - if b == nil { - return nil, fmt.Errorf("creation info not found") - } - - r := bytes.NewReader(b) - creationInfo, err := deserializePaymentCreationInfo(r) + creationInfo, err := fetchCreationInfo(bucket) if err != nil { return nil, err @@ -285,7 +289,7 @@ func fetchPayment(bucket kvdb.ReadBucket) (*MPPayment, error) { // Get failure reason if available. var failureReason *FailureReason - b = bucket.Get(paymentFailInfoKey) + b := bucket.Get(paymentFailInfoKey) if b != nil { reason := FailureReason(b[0]) failureReason = &reason From 864e64e725b520fa22c771b755904b82bd43060c Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:27 +0200 Subject: [PATCH 388/562] channeldb: validate MPP options when registering attempts We add validation making sure we are not trying to register MPP shards for non-MPP payments, and vice versa. We also add validtion of total sent amount against payment value, and matching MPP options. We also add methods for copying Route/Hop, since it is useful to use for modifying the route amount in the test. --- channeldb/payment_control.go | 74 ++++++++++++++++++ channeldb/payment_control_test.go | 122 +++++++++++++++++++++++++++++- routing/control_tower_test.go | 2 +- routing/route/route.go | 38 ++++++++++ 4 files changed, 231 insertions(+), 5 deletions(-) diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index d0bbae7550..ca5b6998b1 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -45,6 +45,32 @@ var ( // failed HTLC attempt. ErrAttemptAlreadyFailed = errors.New("attempt already failed") + // ErrValueMismatch is returned if we try to register a non-MPP attempt + // with an amount that doesn't match the payment amount. + ErrValueMismatch = errors.New("attempted value doesn't match payment" + + "amount") + + // ErrValueExceedsAmt is returned if we try to register an attempt that + // would take the total sent amount above the payment amount. + ErrValueExceedsAmt = errors.New("attempted value exceeds payment" + + "amount") + + // ErrNonMPPayment is returned if we try to register an MPP attempt for + // a payment that already has a non-MPP attempt regitered. + ErrNonMPPayment = errors.New("payment has non-MPP attempts") + + // ErrMPPayment is returned if we try to register a non-MPP attempt for + // a payment that already has an MPP attempt regitered. + ErrMPPayment = errors.New("payment has MPP attempts") + + // ErrMPPPaymentAddrMismatch is returned if we try to register an MPP + // shard where the payment address doesn't match existing shards. + ErrMPPPaymentAddrMismatch = errors.New("payment address mismatch") + + // ErrMPPTotalAmountMismatch is returned if we try to register an MPP + // shard where the total amount doesn't match existing shards. + ErrMPPTotalAmountMismatch = errors.New("mp payment total amount mismatch") + // errNoAttemptInfo is returned when no attempt info is stored yet. errNoAttemptInfo = errors.New("unable to find attempt info for " + "inflight payment") @@ -189,11 +215,59 @@ func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, return err } + // We cannot register a new attempt if the payment already has + // reached a terminal condition: settle, fail := payment.TerminalInfo() if settle != nil || fail != nil { return ErrPaymentTerminal } + // Make sure any existing shards match the new one with regards + // to MPP options. + mpp := attempt.Route.FinalHop().MPP + for _, h := range payment.InFlightHTLCs() { + hMpp := h.Route.FinalHop().MPP + + switch { + + // We tried to register a non-MPP attempt for a MPP + // payment. + case mpp == nil && hMpp != nil: + return ErrMPPayment + + // We tried to register a MPP shard for a non-MPP + // payment. + case mpp != nil && hMpp == nil: + return ErrNonMPPayment + + // Non-MPP payment, nothing more to validate. + case mpp == nil: + continue + } + + // Check that MPP options match. + if mpp.PaymentAddr() != hMpp.PaymentAddr() { + return ErrMPPPaymentAddrMismatch + } + + if mpp.TotalMsat() != hMpp.TotalMsat() { + return ErrMPPTotalAmountMismatch + } + } + + // If this is a non-MPP attempt, it must match the total amount + // exactly. + amt := attempt.Route.ReceiverAmt() + if mpp == nil && amt != payment.Info.Value { + return ErrValueMismatch + } + + // Ensure we aren't sending more than the total payment amount. + sentAmt, _ := payment.SentAmt() + if sentAmt+amt > payment.Info.Value { + return ErrValueExceedsAmt + } + htlcsBucket, err := bucket.CreateBucketIfNotExists( paymentHtlcsBucket, ) diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index 015aa23186..abd2722a57 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/fastsha256" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/record" ) func initDB() (*DB, error) { @@ -48,14 +49,14 @@ func genInfo() (*PaymentCreationInfo, *HTLCAttemptInfo, rhash := fastsha256.Sum256(preimage[:]) return &PaymentCreationInfo{ PaymentHash: rhash, - Value: 1, + Value: testRoute.ReceiverAmt(), CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte("hola"), }, &HTLCAttemptInfo{ AttemptID: 0, SessionKey: priv, - Route: testRoute, + Route: *testRoute.Copy(), }, preimage, nil } @@ -504,7 +505,15 @@ func TestPaymentControlMultiShard(t *testing.T) { ) // Create three unique attempts we'll use for the test, and - // register them with the payment control. + // register them with the payment control. We set each + // attempts's value to one third of the payment amount, and + // populate the MPP options. + shardAmt := info.Value / 3 + attempt.Route.FinalHop().AmtToForward = shardAmt + attempt.Route.FinalHop().MPP = record.NewMPP( + info.Value, [32]byte{1}, + ) + var attempts []*HTLCAttemptInfo for i := uint64(0); i < 3; i++ { a := *attempt @@ -527,6 +536,17 @@ func TestPaymentControlMultiShard(t *testing.T) { ) } + // For a fourth attempt, check that attempting to + // register it will fail since the total sent amount + // will be too large. + b := *attempt + b.AttemptID = 3 + err = pControl.RegisterAttempt(info.PaymentHash, &b) + if err != ErrValueExceedsAmt { + t.Fatalf("expected ErrValueExceedsAmt, got: %v", + err) + } + // Fail the second attempt. a := attempts[1] htlcFail := HTLCFailUnreadable @@ -612,7 +632,7 @@ func TestPaymentControlMultiShard(t *testing.T) { // Try to register yet another attempt. This should fail now // that the payment has reached a terminal condition. - b := *attempt + b = *attempt b.AttemptID = 3 err = pControl.RegisterAttempt(info.PaymentHash, &b) if err != ErrPaymentTerminal { @@ -705,6 +725,100 @@ func TestPaymentControlMultiShard(t *testing.T) { } } +func TestPaymentControlMPPRecordValidation(t *testing.T) { + t.Parallel() + + db, err := initDB() + if err != nil { + t.Fatalf("unable to init db: %v", err) + } + + pControl := NewPaymentControl(db) + + info, attempt, _, err := genInfo() + if err != nil { + t.Fatalf("unable to generate htlc message: %v", err) + } + + // Init the payment. + err = pControl.InitPayment(info.PaymentHash, info) + if err != nil { + t.Fatalf("unable to send htlc message: %v", err) + } + + // Create three unique attempts we'll use for the test, and + // register them with the payment control. We set each + // attempts's value to one third of the payment amount, and + // populate the MPP options. + shardAmt := info.Value / 3 + attempt.Route.FinalHop().AmtToForward = shardAmt + attempt.Route.FinalHop().MPP = record.NewMPP( + info.Value, [32]byte{1}, + ) + + err = pControl.RegisterAttempt(info.PaymentHash, attempt) + if err != nil { + t.Fatalf("unable to send htlc message: %v", err) + } + + // Now try to register a non-MPP attempt, which should fail. + b := *attempt + b.AttemptID = 1 + b.Route.FinalHop().MPP = nil + err = pControl.RegisterAttempt(info.PaymentHash, &b) + if err != ErrMPPayment { + t.Fatalf("expected ErrMPPayment, got: %v", err) + } + + // Try to register attempt one with a different payment address. + b.Route.FinalHop().MPP = record.NewMPP( + info.Value, [32]byte{2}, + ) + err = pControl.RegisterAttempt(info.PaymentHash, &b) + if err != ErrMPPPaymentAddrMismatch { + t.Fatalf("expected ErrMPPPaymentAddrMismatch, got: %v", err) + } + + // Try registering one with a different total amount. + b.Route.FinalHop().MPP = record.NewMPP( + info.Value/2, [32]byte{1}, + ) + err = pControl.RegisterAttempt(info.PaymentHash, &b) + if err != ErrMPPTotalAmountMismatch { + t.Fatalf("expected ErrMPPTotalAmountMismatch, got: %v", err) + } + + // Create and init a new payment. This time we'll check that we cannot + // register an MPP attempt if we already registered a non-MPP one. + info, attempt, _, err = genInfo() + if err != nil { + t.Fatalf("unable to generate htlc message: %v", err) + } + + err = pControl.InitPayment(info.PaymentHash, info) + if err != nil { + t.Fatalf("unable to send htlc message: %v", err) + } + + attempt.Route.FinalHop().MPP = nil + err = pControl.RegisterAttempt(info.PaymentHash, attempt) + if err != nil { + t.Fatalf("unable to send htlc message: %v", err) + } + + // Attempt to register an MPP attempt, which should fail. + b = *attempt + b.AttemptID = 1 + b.Route.FinalHop().MPP = record.NewMPP( + info.Value, [32]byte{1}, + ) + + err = pControl.RegisterAttempt(info.PaymentHash, &b) + if err != ErrNonMPPayment { + t.Fatalf("expected ErrNonMPPayment, got: %v", err) + } +} + // assertPaymentStatus retrieves the status of the payment referred to by hash // and compares it with the expected state. func assertPaymentStatus(t *testing.T, p *PaymentControl, diff --git a/routing/control_tower_test.go b/routing/control_tower_test.go index 6bc8ffd7d9..82dc2706f6 100644 --- a/routing/control_tower_test.go +++ b/routing/control_tower_test.go @@ -324,7 +324,7 @@ func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.HTLCAttemptInfo, rhash := sha256.Sum256(preimage[:]) return &channeldb.PaymentCreationInfo{ PaymentHash: rhash, - Value: 1, + Value: testRoute.ReceiverAmt(), CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte("hola"), }, diff --git a/routing/route/route.go b/routing/route/route.go index 31fa3bf50d..63944af18a 100644 --- a/routing/route/route.go +++ b/routing/route/route.go @@ -129,6 +129,23 @@ type Hop struct { LegacyPayload bool } +// Copy returns a deep copy of the Hop. +func (h *Hop) Copy() *Hop { + c := *h + + if h.MPP != nil { + m := *h.MPP + c.MPP = &m + } + + if h.AMP != nil { + a := *h.AMP + c.AMP = &a + } + + return &c +} + // PackHopPayload writes to the passed io.Writer, the series of byes that can // be placed directly into the per-hop payload (EOB) for this hop. This will // include the required routing fields, as well as serializing any of the @@ -287,6 +304,18 @@ type Route struct { Hops []*Hop } +// Copy returns a deep copy of the Route. +func (r *Route) Copy() *Route { + c := *r + + c.Hops = make([]*Hop, len(r.Hops)) + for i := range r.Hops { + c.Hops[i] = r.Hops[i].Copy() + } + + return &c +} + // HopFee returns the fee charged by the route hop indicated by hopIndex. func (r *Route) HopFee(hopIndex int) lnwire.MilliSatoshi { var incomingAmt lnwire.MilliSatoshi @@ -320,6 +349,15 @@ func (r *Route) ReceiverAmt() lnwire.MilliSatoshi { return r.Hops[len(r.Hops)-1].AmtToForward } +// FinalHop returns the last hop of the route, or nil if the route is empty. +func (r *Route) FinalHop() *Hop { + if len(r.Hops) == 0 { + return nil + } + + return r.Hops[len(r.Hops)-1] +} + // NewRouteFromHops creates a new Route structure from the minimally required // information to perform the payment. It infers fee amounts and populates the // node, chan and prev/next hop maps. From 95c5a123c8661918723566740e50de573b9d0942 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:27 +0200 Subject: [PATCH 389/562] routing/router_test: add TestSendToRouteMultiShardSend --- routing/mock_test.go | 16 +++-- routing/router_test.go | 133 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 4 deletions(-) diff --git a/routing/mock_test.go b/routing/mock_test.go index 36523a973d..f47a942040 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -15,6 +15,8 @@ import ( type mockPaymentAttemptDispatcher struct { onPayment func(firstHop lnwire.ShortChannelID) ([32]byte, error) results map[uint64]*htlcswitch.PaymentResult + + sync.Mutex } var _ PaymentAttemptDispatcher = (*mockPaymentAttemptDispatcher)(nil) @@ -27,10 +29,6 @@ func (m *mockPaymentAttemptDispatcher) SendHTLC(firstHop lnwire.ShortChannelID, return nil } - if m.results == nil { - m.results = make(map[uint64]*htlcswitch.PaymentResult) - } - var result *htlcswitch.PaymentResult preimage, err := m.onPayment(firstHop) if err != nil { @@ -45,7 +43,13 @@ func (m *mockPaymentAttemptDispatcher) SendHTLC(firstHop lnwire.ShortChannelID, result = &htlcswitch.PaymentResult{Preimage: preimage} } + m.Lock() + if m.results == nil { + m.results = make(map[uint64]*htlcswitch.PaymentResult) + } + m.results[pid] = result + m.Unlock() return nil } @@ -55,7 +59,11 @@ func (m *mockPaymentAttemptDispatcher) GetPaymentResult(paymentID uint64, <-chan *htlcswitch.PaymentResult, error) { c := make(chan *htlcswitch.PaymentResult, 1) + + m.Lock() res, ok := m.results[paymentID] + m.Unlock() + if !ok { return nil, htlcswitch.ErrPaymentIDNotFound } diff --git a/routing/router_test.go b/routing/router_test.go index 0bb90d7154..7ac7527c52 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -21,6 +21,7 @@ import ( "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/zpay32" ) @@ -2725,6 +2726,138 @@ func TestSendToRouteStructuredError(t *testing.T) { } } +// TestSendToRouteMultiShardSend checks that a 3-shard payment can be executed +// using SendToRoute. +func TestSendToRouteMultiShardSend(t *testing.T) { + t.Parallel() + + ctx, cleanup, err := createTestCtxSingleNode(0) + if err != nil { + t.Fatal(err) + } + defer cleanup() + + const numShards = 3 + const payAmt = lnwire.MilliSatoshi(numShards * 10000) + node, err := createTestNode() + if err != nil { + t.Fatal(err) + } + + // Create a simple 1-hop route that we will use for all three shards. + hops := []*route.Hop{ + { + ChannelID: 1, + PubKeyBytes: node.PubKeyBytes, + AmtToForward: payAmt / numShards, + MPP: record.NewMPP(payAmt, [32]byte{}), + }, + } + + sourceNode, err := ctx.graph.SourceNode() + if err != nil { + t.Fatal(err) + } + + rt, err := route.NewRouteFromHops( + payAmt, 100, sourceNode.PubKeyBytes, hops, + ) + if err != nil { + t.Fatalf("unable to create route: %v", err) + } + + // The first shard we send we'll fail immediately, to check that we are + // still allowed to retry with other shards after a failed one. + ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult( + func(firstHop lnwire.ShortChannelID) ([32]byte, error) { + return [32]byte{}, htlcswitch.NewForwardingError( + &lnwire.FailFeeInsufficient{ + Update: lnwire.ChannelUpdate{}, + }, 1, + ) + }) + + // The payment parameter is mostly redundant in SendToRoute. Can be left + // empty for this test. + var payment lntypes.Hash + + // Send the shard using the created route, and expect an error to be + // returned. + _, err = ctx.router.SendToRoute(payment, rt) + if err == nil { + t.Fatalf("expected forwarding error") + } + + // Now we'll modify the SendToSwitch method again to wait until all + // three shards are initiated before returning a result. We do this by + // signalling when the method has been called, and then stop to wait + // for the test to deliver the final result on the channel below. + waitForResultSignal := make(chan struct{}, numShards) + results := make(chan lntypes.Preimage, numShards) + + ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult( + func(firstHop lnwire.ShortChannelID) ([32]byte, error) { + + // Signal that the shard has been initiated and is + // waiting for a result. + waitForResultSignal <- struct{}{} + + // Wait for a result before returning it. + res, ok := <-results + if !ok { + return [32]byte{}, fmt.Errorf("failure") + } + return res, nil + }) + + // Launch three shards by calling SendToRoute in three goroutines, + // returning their final error on the channel. + errChan := make(chan error) + successes := make(chan lntypes.Preimage) + + for i := 0; i < numShards; i++ { + go func() { + preimg, err := ctx.router.SendToRoute(payment, rt) + if err != nil { + errChan <- err + return + } + + successes <- preimg + }() + } + + // Wait for all shards to signal they have been initiated. + for i := 0; i < numShards; i++ { + select { + case <-waitForResultSignal: + case <-time.After(5 * time.Second): + t.Fatalf("not waiting for results") + } + } + + // Deliver a dummy preimage to all the shard handlers. + preimage := lntypes.Preimage{} + preimage[4] = 42 + for i := 0; i < numShards; i++ { + results <- preimage + } + + // Finally expect all shards to return with the above preimage. + for i := 0; i < numShards; i++ { + select { + case p := <-successes: + if p != preimage { + t.Fatalf("preimage mismatch") + } + case err := <-errChan: + t.Fatalf("unexpected error from SendToRoute: %v", err) + case <-time.After(5 * time.Second): + t.Fatalf("result not received") + } + } +} + // TestSendToRouteMaxHops asserts that SendToRoute fails when using a route that // exceeds the maximum number of hops. func TestSendToRouteMaxHops(t *testing.T) { From fee5fd0093b578e2a515969d49a99ddd7dd3ddf1 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:27 +0200 Subject: [PATCH 390/562] itest: add testSendToRouteMultiPath testSendToRouteMultiPath tests that we are able to successfully route a payment using multiple shards across different paths, by using SendToRoute. Co-authored-by: Joost Jager --- lntest/itest/lnd_mpp_test.go | 357 +++++++++++++++++++++++++++++++++++ lntest/itest/lnd_test.go | 4 + 2 files changed, 361 insertions(+) create mode 100644 lntest/itest/lnd_mpp_test.go diff --git a/lntest/itest/lnd_mpp_test.go b/lntest/itest/lnd_mpp_test.go new file mode 100644 index 0000000000..9b338baf05 --- /dev/null +++ b/lntest/itest/lnd_mpp_test.go @@ -0,0 +1,357 @@ +// +build rpctest + +package itest + +import ( + "bytes" + "context" + "fmt" + "time" + + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/lntest" + "github.com/lightningnetwork/lnd/routing/route" +) + +// testSendToRouteMultiPath tests that we are able to successfully route a +// payment using multiple shards across different paths, by using SendToRoute. +func testSendToRouteMultiPath(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() + + // To ensure the payment goes through seperate paths, we'll set a + // channel size that can only carry one shard at a time. We'll divide + // the payment into 3 shards. + const ( + paymentAmt = btcutil.Amount(300000) + shardAmt = paymentAmt / 3 + chanAmt = shardAmt * 3 / 2 + ) + + // Set up a network with three different paths Alice <-> Bob. + // _ Eve _ + // / \ + // Alice -- Carol ---- Bob + // \ / + // \__ Dave ____/ + // + // + // Create the three nodes in addition to Alice and Bob. + alice := net.Alice + bob := net.Bob + carol, err := net.NewNode("carol", nil) + if err != nil { + t.Fatalf("unable to create carol: %v", err) + } + defer shutdownAndAssert(net, t, carol) + + dave, err := net.NewNode("dave", nil) + if err != nil { + t.Fatalf("unable to create dave: %v", err) + } + defer shutdownAndAssert(net, t, dave) + + eve, err := net.NewNode("eve", nil) + if err != nil { + t.Fatalf("unable to create eve: %v", err) + } + defer shutdownAndAssert(net, t, eve) + + nodes := []*lntest.HarnessNode{alice, bob, carol, dave, eve} + + // Connect nodes to ensure propagation of channels. + for i := 0; i < len(nodes); i++ { + for j := i + 1; j < len(nodes); j++ { + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + if err := net.EnsureConnected(ctxt, nodes[i], nodes[j]); err != nil { + t.Fatalf("unable to connect nodes: %v", err) + } + } + } + + // We'll send shards along three routes from Alice. + sendRoutes := [][]*lntest.HarnessNode{ + {carol, bob}, + {dave, bob}, + {carol, eve, bob}, + } + + // Keep a list of all our active channels. + var networkChans []*lnrpc.ChannelPoint + var closeChannelFuncs []func() + + // openChannel is a helper to open a channel from->to. + openChannel := func(from, to *lntest.HarnessNode, chanSize btcutil.Amount) { + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + err := net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, from) + if err != nil { + t.Fatalf("unable to send coins : %v", err) + } + + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) + chanPoint := openChannelAndAssert( + ctxt, t, net, from, to, + lntest.OpenChannelParams{ + Amt: chanSize, + }, + ) + + closeChannelFuncs = append(closeChannelFuncs, func() { + ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert( + ctxt, t, net, from, chanPoint, false, + ) + }) + + networkChans = append(networkChans, chanPoint) + } + + // Open channels between the nodes. + openChannel(carol, bob, chanAmt) + openChannel(dave, bob, chanAmt) + openChannel(alice, dave, chanAmt) + openChannel(eve, bob, chanAmt) + openChannel(carol, eve, chanAmt) + + // Since the channel Alice-> Carol will have to carry two + // shards, we make it larger. + openChannel(alice, carol, chanAmt+shardAmt) + + for _, f := range closeChannelFuncs { + defer f() + } + + // Wait for all nodes to have seen all channels. + for _, chanPoint := range networkChans { + for _, node := range nodes { + txid, err := lnd.GetChanPointFundingTxid(chanPoint) + if err != nil { + t.Fatalf("unable to get txid: %v", err) + } + point := wire.OutPoint{ + Hash: *txid, + Index: chanPoint.OutputIndex, + } + + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + err = node.WaitForNetworkChannelOpen(ctxt, chanPoint) + if err != nil { + t.Fatalf("(%d): timeout waiting for "+ + "channel(%s) open: %v", + node.NodeID, point, err) + } + } + } + + // Make Bob create an invoice for Alice to pay. + payReqs, rHashes, invoices, err := createPayReqs( + net.Bob, paymentAmt, 1, + ) + if err != nil { + t.Fatalf("unable to create pay reqs: %v", err) + } + + rHash := rHashes[0] + payReq := payReqs[0] + + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + decodeResp, err := net.Bob.DecodePayReq( + ctxt, &lnrpc.PayReqString{PayReq: payReq}, + ) + if err != nil { + t.Fatalf("decode pay req: %v", err) + } + + 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: lnd.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 + } + + responses := make(chan *routerrpc.SendToRouteResponse, len(sendRoutes)) + for _, hops := range sendRoutes { + // Build a route for the specified hops. + r, err := buildRoute(shardAmt, 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), + } + + // Send the shard. + sendReq := &routerrpc.SendToRouteRequest{ + PaymentHash: rHash, + 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.SendToRoute(ctxt, sendReq) + if err != nil { + t.Fatalf("unable to send payment: %v", err) + } + + responses <- resp + }() + } + + // Wait for all responses to be back, and check that they all + // succeeded. + for range sendRoutes { + var resp *routerrpc.SendToRouteResponse + 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) + } + + // All shards should come back with the preimage. + if !bytes.Equal(resp.Preimage, invoices[0].RPreimage) { + t.Fatalf("preimage doesn't match") + } + } + + // assertNumHtlcs is a helper that checks the node's latest payment, + // and asserts it was split into num shards. + assertNumHtlcs := func(node *lntest.HarnessNode, num int) { + req := &lnrpc.ListPaymentsRequest{ + IncludeIncomplete: true, + } + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + paymentsResp, err := node.ListPayments(ctxt, req) + if err != nil { + t.Fatalf("error when obtaining payments: %v", + err) + } + + payments := paymentsResp.Payments + if len(payments) == 0 { + t.Fatalf("no payments found") + } + + payment := payments[len(payments)-1] + htlcs := payment.Htlcs + if len(htlcs) == 0 { + t.Fatalf("no htlcs") + } + + succeeded := 0 + for _, htlc := range htlcs { + if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED { + succeeded++ + } + } + + if succeeded != num { + t.Fatalf("expected %v succussful HTLCs, got %v", num, + succeeded) + } + } + + // assertSettledInvoice checks that the invoice for the given payment + // hash is settled, and has been paid using num HTLCs. + assertSettledInvoice := func(node *lntest.HarnessNode, rhash []byte, + num int) { + + found := false + offset := uint64(0) + for !found { + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + invoicesResp, err := node.ListInvoices( + ctxt, &lnrpc.ListInvoiceRequest{ + IndexOffset: offset, + }, + ) + if err != nil { + t.Fatalf("error when obtaining payments: %v", + err) + } + + if len(invoicesResp.Invoices) == 0 { + break + } + + for _, inv := range invoicesResp.Invoices { + if !bytes.Equal(inv.RHash, rhash) { + continue + } + + // Assert that the amount paid to the invoice is + // correct. + if inv.AmtPaidSat != int64(paymentAmt) { + t.Fatalf("incorrect payment amt for "+ + "invoicewant: %d, got %d", + paymentAmt, inv.AmtPaidSat) + } + + if inv.State != lnrpc.Invoice_SETTLED { + t.Fatalf("Invoice not settled: %v", + inv.State) + } + + if len(inv.Htlcs) != num { + t.Fatalf("expected invoice to be "+ + "settled with %v HTLCs, had %v", + num, len(inv.Htlcs)) + } + + found = true + break + } + + offset = invoicesResp.LastIndexOffset + } + + if !found { + t.Fatalf("invoice not found") + } + } + + // Finally check that the payment shows up with three settled HTLCs in + // Alice's list of payments... + assertNumHtlcs(net.Alice, 3) + + // ...and in Bob's list of paid invoices. + assertSettledInvoice(net.Bob, rHash, 3) +} diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 70febd9fa9..d35fca729d 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -14908,6 +14908,10 @@ var testsCases = []*testCase{ name: "psbt channel funding", test: testPsbtChanFunding, }, + { + name: "sendtoroute multi path payment", + test: testSendToRouteMultiPath, + }, } // TestLightningNetworkDaemon performs a series of integration tests amongst a From 5e72a4b77c7019b6fa1987d99f9212e9beaeb41f Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 1 Apr 2020 00:13:27 +0200 Subject: [PATCH 391/562] routing: exit on unexpected RequestRoute error We whitelist a set of "expected" errors that can be returned from RequestRoute, by converting them into a new type noRouteError. For any other error returned by RequestRoute, we'll now exit immediately. --- routing/mock_test.go | 2 +- routing/pathfind.go | 18 ---------- routing/payment_lifecycle.go | 26 ++++---------- routing/payment_session.go | 70 +++++++++++++++++++++++++++++++++--- 4 files changed, 73 insertions(+), 43 deletions(-) diff --git a/routing/mock_test.go b/routing/mock_test.go index f47a942040..9645f73bf9 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -141,7 +141,7 @@ func (m *mockPaymentSession) RequestRoute(_, _ lnwire.MilliSatoshi, _, height uint32) (*route.Route, error) { if len(m.routes) == 0 { - return nil, fmt.Errorf("no routes") + return nil, errNoPathFound } r := m.routes[0] diff --git a/routing/pathfind.go b/routing/pathfind.go index 549d341667..1365958c6a 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -58,24 +58,6 @@ var ( // DefaultAprioriHopProbability is the default a priori probability for // a hop. DefaultAprioriHopProbability = float64(0.6) - - // errNoTlvPayload is returned when the destination hop does not support - // a tlv payload. - errNoTlvPayload = errors.New("destination hop doesn't " + - "understand new TLV payloads") - - // errNoPaymentAddr is returned when the destination hop does not - // support payment addresses. - errNoPaymentAddr = errors.New("destination hop doesn't " + - "understand payment addresses") - - // errNoPathFound is returned when a path to the target destination does - // not exist in the graph. - errNoPathFound = errors.New("unable to find a path to destination") - - // errInsufficientLocalBalance is returned when none of the local - // channels have enough balance for the payment. - errInsufficientBalance = errors.New("insufficient local balance") ) // edgePolicyWithSource is a helper struct to keep track of the source node diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 3a0eb75b89..6ac79400a6 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -210,11 +210,16 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { log.Warnf("Failed to find route for payment %x: %v", p.paymentHash, err) + routeErr, ok := err.(noRouteError) + if !ok { + return [32]byte{}, nil, err + } + // There is no route to try, and we have no active // shards. This means that there is no way for us to // send the payment, so mark it failed with no route. if state.numShardsInFlight == 0 { - failureCode := errorToPaymentFailure(err) + failureCode := routeErr.FailureReason() log.Debugf("Marking payment %v permanently "+ "failed with no route: %v", p.paymentHash, failureCode) @@ -570,25 +575,6 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) ( }, nil } -// errorToPaymentFailure takes a path finding error and converts it into a -// payment-level failure. -func errorToPaymentFailure(err error) channeldb.FailureReason { - switch err { - case - errNoTlvPayload, - errNoPaymentAddr, - errNoPathFound, - errEmptyPaySession: - - return channeldb.FailureReasonNoRoute - - case errInsufficientBalance: - return channeldb.FailureReasonInsufficientBalance - } - - return channeldb.FailureReasonError -} - // createNewPaymentAttempt creates a new payment attempt from the given route. func (p *shardHandler) createNewPaymentAttempt(rt *route.Route) ( lnwire.ShortChannelID, *lnwire.UpdateAddHTLC, diff --git a/routing/payment_session.go b/routing/payment_session.go index f8c297552d..6a597ff01e 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -1,8 +1,6 @@ package routing import ( - "errors" - "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -12,12 +10,73 @@ import ( // to prevent an HTLC being failed if some blocks are mined while it's in-flight. const BlockPadding uint16 = 3 -var ( +// noRouteError encodes a non-critical error encountered during path finding. +type noRouteError uint8 + +const ( + // errNoTlvPayload is returned when the destination hop does not support + // a tlv payload. + errNoTlvPayload noRouteError = iota + + // errNoPaymentAddr is returned when the destination hop does not + // support payment addresses. + errNoPaymentAddr + + // errNoPathFound is returned when a path to the target destination does + // not exist in the graph. + errNoPathFound + + // errInsufficientLocalBalance is returned when none of the local + // channels have enough balance for the payment. + errInsufficientBalance + // errEmptyPaySession is returned when the empty payment session is // queried for a route. - errEmptyPaySession = errors.New("empty payment session") + errEmptyPaySession ) +// Error returns the string representation of the noRouteError +func (e noRouteError) Error() string { + switch e { + case errNoTlvPayload: + return "destination hop doesn't understand new TLV payloads" + + case errNoPaymentAddr: + return "destination hop doesn't understand payment addresses" + + case errNoPathFound: + return "unable to find a path to destination" + + case errEmptyPaySession: + return "empty payment session" + + case errInsufficientBalance: + return "insufficient local balance" + + default: + return "unknown no-route error" + } +} + +// FailureReason converts a path finding error into a payment-level failure. +func (e noRouteError) FailureReason() channeldb.FailureReason { + switch e { + case + errNoTlvPayload, + errNoPaymentAddr, + errNoPathFound, + errEmptyPaySession: + + return channeldb.FailureReasonNoRoute + + case errInsufficientBalance: + return channeldb.FailureReasonInsufficientBalance + + default: + return channeldb.FailureReasonError + } +} + // PaymentSession is used during SendPayment attempts to provide routes to // attempt. It also defines methods to give the PaymentSession additional // information learned during the previous attempts. @@ -29,6 +88,9 @@ type PaymentSession interface { // argument should be set to instruct the payment session about the // number of in flight HTLCS for the payment, such that it can choose // splitting strategy accordingly. + // + // A noRouteError is returned if a non-critical error is encountered + // during path finding. RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, activeShards, height uint32) (*route.Route, error) } From 9b39692bb28166c20fe17d17dbd0ea9c384a8a02 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 29 Mar 2020 17:20:44 -0700 Subject: [PATCH 392/562] contractcourt: add additional logging of commitments at play In this commit, we add some additional logging of the commitments at play when we detect a channel closure on-chain. This should help to debug things more in the future as we don't log the full commitments anywhere. We also now also print the type of commitment as well, as a follow up from the recent anchor outputs work. In the near future, as we implement a dynamic commitments update protocol, always logging the commitment type as well will likely be useful for debugging purposes. --- contractcourt/chain_watcher.go | 176 +++++++++++++++++++++++---------- 1 file changed, 122 insertions(+), 54 deletions(-) diff --git a/contractcourt/chain_watcher.go b/contractcourt/chain_watcher.go index bbb3cbb1e2..3be9f08df5 100644 --- a/contractcourt/chain_watcher.go +++ b/contractcourt/chain_watcher.go @@ -393,6 +393,99 @@ func isOurCommitment(localChanCfg, remoteChanCfg channeldb.ChannelConfig, return false, nil } +// chainSet includes all the information we need to dispatch a channel close +// event to any subscribers. +type chainSet struct { + // remoteStateNum is the commitment number of the lowest valid + // commitment the remote party holds from our PoV. This value is used + // to determine if the remote party is playing a state that's behind, + // in line, or ahead of the latest state we know for it. + remoteStateNum uint64 + + // commitSet includes information pertaining to the set of active HTLCs + // on each commitment. + commitSet CommitSet + + // remoteCommit is the current commitment of the remote party. + remoteCommit channeldb.ChannelCommitment + + // localCommit is our current commitment. + localCommit channeldb.ChannelCommitment + + // remotePendingCommit points to the dangling commitment of the remote + // party, if it exists. If there's no dangling commitment, then this + // pointer will be nil. + remotePendingCommit *channeldb.ChannelCommitment +} + +// newChainSet creates a new chainSet given the current up to date channel +// state. +func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) { + // First, we'll grab the current unrevoked commitments for ourselves + // and the remote party. + localCommit, remoteCommit, err := chanState.LatestCommitments() + if err != nil { + return nil, fmt.Errorf("unable to fetch channel state for "+ + "chan_point=%v", chanState.FundingOutpoint) + } + + log.Debugf("ChannelPoint(%v): local_commit_type=%v, local_commit=%v", + chanState.ChanType, spew.Sdump(localCommit)) + log.Debugf("ChannelPoint(%v): remote_commit_type=%v, remote_commit=%v", + chanState.ChanType, spew.Sdump(remoteCommit)) + + // Fetch the current known commit height for the remote party, and + // their pending commitment chain tip if it exists. + remoteStateNum := remoteCommit.CommitHeight + remoteChainTip, err := chanState.RemoteCommitChainTip() + if err != nil && err != channeldb.ErrNoPendingCommit { + return nil, fmt.Errorf("unable to obtain chain tip for "+ + "ChannelPoint(%v): %v", + chanState.FundingOutpoint, err) + } + + // Now that we have all the possible valid commitments, we'll make the + // CommitSet the ChannelArbitrator will need in order to carry out its + // duty. + commitSet := CommitSet{ + HtlcSets: map[HtlcSetKey][]channeldb.HTLC{ + LocalHtlcSet: localCommit.Htlcs, + RemoteHtlcSet: remoteCommit.Htlcs, + }, + } + + var remotePendingCommit *channeldb.ChannelCommitment + if remoteChainTip != nil { + remotePendingCommit = &remoteChainTip.Commitment + log.Debugf("ChannelPoint(%v): remote_pending_commit_type=%v, "+ + "remote_pending_commit=%v", + chanState.ChanType, + spew.Sdump(remoteChainTip.Commitment)) + + htlcs := remoteChainTip.Commitment.Htlcs + commitSet.HtlcSets[RemotePendingHtlcSet] = htlcs + } + + // We'll now retrieve the latest state of the revocation store so we + // can populate the revocation information within the channel state + // object that we have. + // + // TODO(roasbeef): mutation is bad mkay + _, err = chanState.RemoteRevocationStore() + if err != nil { + return nil, fmt.Errorf("unable to fetch revocation state for "+ + "chan_point=%v", chanState.FundingOutpoint) + } + + return &chainSet{ + remoteStateNum: remoteStateNum, + commitSet: commitSet, + localCommit: *localCommit, + remoteCommit: *remoteCommit, + remotePendingCommit: remotePendingCommit, + }, nil +} + // closeObserver is a dedicated goroutine that will watch for any closes of the // channel that it's watching on chain. In the event of an on-chain event, the // close observer will assembled the proper materials required to claim the @@ -423,46 +516,12 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) { // revoked state...!!! commitTxBroadcast := commitSpend.SpendingTx - localCommit, remoteCommit, err := c.cfg.chanState.LatestCommitments() - if err != nil { - log.Errorf("Unable to fetch channel state for "+ - "chan_point=%v", c.cfg.chanState.FundingOutpoint) - return - } - - // Fetch the current known commit height for the remote party, - // and their pending commitment chain tip if it exist. - remoteStateNum := remoteCommit.CommitHeight - remoteChainTip, err := c.cfg.chanState.RemoteCommitChainTip() - if err != nil && err != channeldb.ErrNoPendingCommit { - log.Errorf("unable to obtain chain tip for "+ - "ChannelPoint(%v): %v", - c.cfg.chanState.FundingOutpoint, err) - return - } - - // Now that we have all the possible valid commitments, we'll - // make the CommitSet the ChannelArbitrator will need it in - // order to carry out its duty. - commitSet := CommitSet{ - HtlcSets: make(map[HtlcSetKey][]channeldb.HTLC), - } - commitSet.HtlcSets[LocalHtlcSet] = localCommit.Htlcs - commitSet.HtlcSets[RemoteHtlcSet] = remoteCommit.Htlcs - if remoteChainTip != nil { - htlcs := remoteChainTip.Commitment.Htlcs - commitSet.HtlcSets[RemotePendingHtlcSet] = htlcs - } - - // We'll not retrieve the latest sate of the revocation store - // so we can populate the information within the channel state - // object that we have. - // - // TODO(roasbeef): mutation is bad mkay - _, err = c.cfg.chanState.RemoteRevocationStore() + // First, we'll construct the chainset which includes all the + // data we need to dispatch an event to our subscribers about + // this possible channel close event. + chainSet, err := newChainSet(c.cfg.chanState) if err != nil { - log.Errorf("Unable to fetch revocation state for "+ - "chan_point=%v", c.cfg.chanState.FundingOutpoint) + log.Errorf("unable to create commit set: %v", err) return } @@ -493,10 +552,11 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) { // as we don't have any further processing we need to do (we // can't cheat ourselves :p). if isOurCommit { - commitSet.ConfCommitKey = &LocalHtlcSet + chainSet.commitSet.ConfCommitKey = &LocalHtlcSet if err := c.dispatchLocalForceClose( - commitSpend, *localCommit, commitSet, + commitSpend, chainSet.localCommit, + chainSet.commitSet, ); err != nil { log.Errorf("unable to handle local"+ "close for chan_point=%v: %v", @@ -537,11 +597,16 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) { // latest state, then they've initiated a unilateral close. So // we'll trigger the unilateral close signal so subscribers can // clean up the state as necessary. - case broadcastStateNum == remoteStateNum && !isRecoveredChan: - commitSet.ConfCommitKey = &RemoteHtlcSet + case broadcastStateNum == chainSet.remoteStateNum && + !isRecoveredChan: + + log.Infof("Remote party broadcast base set, "+ + "commit_num=%v", chainSet.remoteStateNum) + chainSet.commitSet.ConfCommitKey = &RemoteHtlcSet err := c.dispatchRemoteForceClose( - commitSpend, *remoteCommit, commitSet, + commitSpend, chainSet.remoteCommit, + chainSet.commitSet, c.cfg.chanState.RemoteCurrentRevocation, ) if err != nil { @@ -555,13 +620,16 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) { // This case can arise when we initiate a state transition, but // the remote party has a fail crash _after_ accepting the new // state, but _before_ sending their signature to us. - case broadcastStateNum == remoteStateNum+1 && - remoteChainTip != nil && !isRecoveredChan: + case broadcastStateNum == chainSet.remoteStateNum+1 && + chainSet.remotePendingCommit != nil && !isRecoveredChan: - commitSet.ConfCommitKey = &RemotePendingHtlcSet + log.Infof("Remote party broadcast pending set, "+ + "commit_num=%v", chainSet.remoteStateNum+1) + chainSet.commitSet.ConfCommitKey = &RemotePendingHtlcSet err := c.dispatchRemoteForceClose( - commitSpend, *remoteCommit, commitSet, + commitSpend, *chainSet.remotePendingCommit, + chainSet.commitSet, c.cfg.chanState.RemoteNextRevocation, ) if err != nil { @@ -579,11 +647,11 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) { // current state is, so we assume either the remote party // forced closed or we've been breached. In the latter case, // our tower will take care of us. - case broadcastStateNum > remoteStateNum || isRecoveredChan: + case broadcastStateNum > chainSet.remoteStateNum || isRecoveredChan: log.Warnf("Remote node broadcast state #%v, "+ "which is more than 1 beyond best known "+ "state #%v!!! Attempting recovery...", - broadcastStateNum, remoteStateNum) + broadcastStateNum, chainSet.remoteStateNum) // If this isn't a tweakless commitment, then we'll // need to wait for the remote party's latest unrevoked @@ -617,10 +685,10 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) { // able to recover any HTLC funds. // // TODO(halseth): can we try to recover some HTLCs? - commitSet.ConfCommitKey = &RemoteHtlcSet + chainSet.commitSet.ConfCommitKey = &RemoteHtlcSet err = c.dispatchRemoteForceClose( commitSpend, channeldb.ChannelCommitment{}, - commitSet, commitPoint, + chainSet.commitSet, commitPoint, ) if err != nil { log.Errorf("unable to handle remote "+ @@ -633,9 +701,9 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) { // VIOLATE THE CONTRACT LAID OUT WITHIN THE PAYMENT CHANNEL. // Therefore we close the signal indicating a revoked broadcast // to allow subscribers to swiftly dispatch justice!!! - case broadcastStateNum < remoteStateNum: + case broadcastStateNum < chainSet.remoteStateNum: err := c.dispatchContractBreach( - commitSpend, remoteCommit, + commitSpend, &chainSet.remoteCommit, broadcastStateNum, ) if err != nil { From 422928b8a3e82a52cfa2c5b8c5183872d4a53ab6 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 2 Apr 2020 17:38:54 -0700 Subject: [PATCH 393/562] lnwallet/channel: remove unused RemoteCommitHeight method --- lnwallet/channel.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 6f64d34d5e..9d820c8fcc 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -6667,14 +6667,6 @@ func (lc *LightningChannel) NextLocalHtlcIndex() (uint64, error) { return lc.channelState.NextLocalHtlcIndex() } -// RemoteCommitHeight returns the commitment height of the remote chain. -func (lc *LightningChannel) RemoteCommitHeight() uint64 { - lc.RLock() - defer lc.RUnlock() - - return lc.channelState.RemoteCommitment.CommitHeight -} - // FwdMinHtlc returns the minimum HTLC value required by the remote node, i.e. // the minimum value HTLC we can forward on this channel. func (lc *LightningChannel) FwdMinHtlc() lnwire.MilliSatoshi { From 9385b8cdc637e7fbdae819338adec13c6e997747 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 2 Apr 2020 17:39:10 -0700 Subject: [PATCH 394/562] channeldb+lnwallet: move ActiveHtlcs calc to OpenChannel --- channeldb/channel.go | 31 +++++++++++++++++++++++++++++++ lnwallet/channel.go | 22 +--------------------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index 7189e56af7..21468b7f32 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -2,6 +2,7 @@ package channeldb import ( "bytes" + "crypto/sha256" "encoding/binary" "errors" "fmt" @@ -1483,6 +1484,36 @@ func (c *OpenChannel) BalancesAtHeight(height uint64) (lnwire.MilliSatoshi, return commit.LocalBalance, commit.RemoteBalance, nil } +// ActiveHtlcs returns a slice of HTLC's which are currently active on *both* +// commitment transactions. +func (c *OpenChannel) ActiveHtlcs() []HTLC { + c.RLock() + defer c.RUnlock() + + // We'll only return HTLC's that are locked into *both* commitment + // transactions. So we'll iterate through their set of HTLC's to note + // which ones are present on their commitment. + remoteHtlcs := make(map[[32]byte]struct{}) + for _, htlc := range c.RemoteCommitment.Htlcs { + onionHash := sha256.Sum256(htlc.OnionBlob) + remoteHtlcs[onionHash] = struct{}{} + } + + // Now that we know which HTLC's they have, we'll only mark the HTLC's + // as active if *we* know them as well. + activeHtlcs := make([]HTLC, 0, len(remoteHtlcs)) + for _, htlc := range c.LocalCommitment.Htlcs { + onionHash := sha256.Sum256(htlc.OnionBlob) + if _, ok := remoteHtlcs[onionHash]; !ok { + continue + } + + activeHtlcs = append(activeHtlcs, htlc) + } + + return activeHtlcs +} + // HTLC is the on-disk representation of a hash time-locked contract. HTLCs are // contained within ChannelDeltas which encode the current state of the // commitment between state updates. diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 9d820c8fcc..fbf6116f8e 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -6628,27 +6628,7 @@ func (lc *LightningChannel) ActiveHtlcs() []channeldb.HTLC { lc.RLock() defer lc.RUnlock() - // We'll only return HTLC's that are locked into *both* commitment - // transactions. So we'll iterate through their set of HTLC's to note - // which ones are present on their commitment. - remoteHtlcs := make(map[[32]byte]struct{}) - for _, htlc := range lc.channelState.RemoteCommitment.Htlcs { - onionHash := sha256.Sum256(htlc.OnionBlob[:]) - remoteHtlcs[onionHash] = struct{}{} - } - - // Now that we know which HTLC's they have, we'll only mark the HTLC's - // as active if *we* know them as well. - activeHtlcs := make([]channeldb.HTLC, 0, len(remoteHtlcs)) - for _, htlc := range lc.channelState.LocalCommitment.Htlcs { - if _, ok := remoteHtlcs[sha256.Sum256(htlc.OnionBlob[:])]; !ok { - continue - } - - activeHtlcs = append(activeHtlcs, htlc) - } - - return activeHtlcs + return lc.channelState.ActiveHtlcs() } // LocalChanReserve returns our local ChanReserve requirement for the remote party. From ec784db511edfc8182fbb5d252b2ac22fbfd310a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 2 Apr 2020 17:39:29 -0700 Subject: [PATCH 395/562] multi: remove returned error from WipeChannel The linter complains about not checking the return value from WipeChannel in certain places. Instead of checking we simply remove the returned error because the in-memory modifications cannot fail. --- discovery/mock_test.go | 4 ++-- fundingmanager_test.go | 4 +--- htlcswitch/link.go | 6 +----- htlcswitch/link_test.go | 4 +--- htlcswitch/mock.go | 4 +--- lnpeer/peer.go | 2 +- peer.go | 24 ++++-------------------- rpcserver.go | 5 +---- 8 files changed, 12 insertions(+), 41 deletions(-) diff --git a/discovery/mock_test.go b/discovery/mock_test.go index f3f707d50f..714f6b4ac0 100644 --- a/discovery/mock_test.go +++ b/discovery/mock_test.go @@ -45,8 +45,8 @@ func (p *mockPeer) SendMessageLazy(sync bool, msgs ...lnwire.Message) error { func (p *mockPeer) AddNewChannel(_ *channeldb.OpenChannel, _ <-chan struct{}) error { return nil } -func (p *mockPeer) WipeChannel(_ *wire.OutPoint) error { return nil } -func (p *mockPeer) IdentityKey() *btcec.PublicKey { return p.pk } +func (p *mockPeer) WipeChannel(_ *wire.OutPoint) {} +func (p *mockPeer) IdentityKey() *btcec.PublicKey { return p.pk } func (p *mockPeer) PubKey() [33]byte { var pubkey [33]byte copy(pubkey[:], p.pk.SerializeCompressed()) diff --git a/fundingmanager_test.go b/fundingmanager_test.go index f1ff528d6c..c7247136da 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -201,9 +201,7 @@ func (n *testNode) SendMessageLazy(sync bool, msgs ...lnwire.Message) error { return n.SendMessage(sync, msgs...) } -func (n *testNode) WipeChannel(_ *wire.OutPoint) error { - return nil -} +func (n *testNode) WipeChannel(_ *wire.OutPoint) {} func (n *testNode) QuitSignal() <-chan struct{} { return n.shutdownChannel diff --git a/htlcswitch/link.go b/htlcswitch/link.go index d91bc85685..6eec8d382d 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1084,11 +1084,7 @@ out: // TODO(roasbeef): remove all together go func() { chanPoint := l.channel.ChannelPoint() - err := l.cfg.Peer.WipeChannel(chanPoint) - if err != nil { - l.log.Errorf("unable to wipe channel "+ - "%v", err) - } + l.cfg.Peer.WipeChannel(chanPoint) }() break out diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index d150ddc55c..965ecdb2e5 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -1652,9 +1652,7 @@ func (m *mockPeer) AddNewChannel(_ *channeldb.OpenChannel, _ <-chan struct{}) error { return nil } -func (m *mockPeer) WipeChannel(*wire.OutPoint) error { - return nil -} +func (m *mockPeer) WipeChannel(*wire.OutPoint) {} func (m *mockPeer) PubKey() [33]byte { return [33]byte{} } diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index 0c7f1ed85a..cefb673a9b 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -602,9 +602,7 @@ func (s *mockServer) AddNewChannel(channel *channeldb.OpenChannel, return nil } -func (s *mockServer) WipeChannel(*wire.OutPoint) error { - return nil -} +func (s *mockServer) WipeChannel(*wire.OutPoint) {} func (s *mockServer) LocalFeatures() *lnwire.FeatureVector { return nil diff --git a/lnpeer/peer.go b/lnpeer/peer.go index 53f571314f..1b118bfb14 100644 --- a/lnpeer/peer.go +++ b/lnpeer/peer.go @@ -30,7 +30,7 @@ type Peer interface { // WipeChannel removes the channel uniquely identified by its channel // point from all indexes associated with the peer. - WipeChannel(*wire.OutPoint) error + WipeChannel(*wire.OutPoint) // PubKey returns the serialized public key of the remote peer. PubKey() [33]byte diff --git a/peer.go b/peer.go index df77c4fd6f..5cd431c8db 100644 --- a/peer.go +++ b/peer.go @@ -2401,13 +2401,7 @@ func (p *peer) handleLocalCloseReq(req *htlcswitch.ChanClose) { // TODO(roasbeef): no longer need with newer beach logic? peerLog.Infof("ChannelPoint(%v) has been breached, wiping "+ "channel", req.ChanPoint) - if err := p.WipeChannel(req.ChanPoint); err != nil { - peerLog.Infof("Unable to wipe channel after detected "+ - "breach: %v", err) - req.Err <- err - return - } - return + p.WipeChannel(req.ChanPoint) } } @@ -2434,11 +2428,7 @@ func (p *peer) handleLinkFailure(failure linkFailureReport) { // link and cancel back any adds in its mailboxes such that we can // safely force close without the link being added again and updates // being applied. - if err := p.WipeChannel(&failure.chanPoint); err != nil { - peerLog.Errorf("Unable to wipe link for chanpoint=%v", - failure.chanPoint) - return - } + p.WipeChannel(&failure.chanPoint) // If the error encountered was severe enough, we'll now force close the // channel to prevent readding it to the switch in the future. @@ -2490,11 +2480,7 @@ func (p *peer) finalizeChanClosure(chanCloser *channelCloser) { // First, we'll clear all indexes related to the channel in question. chanPoint := chanCloser.cfg.channel.ChannelPoint() - if err := p.WipeChannel(chanPoint); err != nil { - if closeReq != nil { - closeReq.Err <- err - } - } + p.WipeChannel(chanPoint) // Next, we'll launch a goroutine which will request to be notified by // the ChainNotifier once the closure transaction obtains a single @@ -2584,7 +2570,7 @@ func waitForChanToClose(bestHeight uint32, notifier chainntnfs.ChainNotifier, // WipeChannel removes the passed channel point from all indexes associated with // the peer, and the switch. -func (p *peer) WipeChannel(chanPoint *wire.OutPoint) error { +func (p *peer) WipeChannel(chanPoint *wire.OutPoint) { chanID := lnwire.NewChanIDFromOutPoint(chanPoint) p.activeChanMtx.Lock() @@ -2594,8 +2580,6 @@ func (p *peer) WipeChannel(chanPoint *wire.OutPoint) error { // Instruct the HtlcSwitch to close this link as the channel is no // longer active. p.server.htlcSwitch.RemoveLink(chanID) - - return nil } // handleInitMsg handles the incoming init message which contains global and diff --git a/rpcserver.go b/rpcserver.go index c016ab5a4c..18a81b905c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2259,10 +2259,7 @@ func (r *rpcServer) AbandonChannel(ctx context.Context, } remotePub := dbChan.IdentityPub if peer, err := r.server.FindPeer(remotePub); err == nil { - if err := peer.WipeChannel(chanPoint); err != nil { - return nil, fmt.Errorf("unable to wipe "+ - "channel state: %v", err) - } + peer.WipeChannel(chanPoint) } default: From 3c371dd63346728e2ec2767ba6eb14aeca916498 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 2 Apr 2020 17:39:47 -0700 Subject: [PATCH 396/562] rpcserver: remove NewLightningChannel usage in CloseChannel --- rpcserver.go | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 18a81b905c..bb540d2c5f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1985,7 +1985,7 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, // First, we'll fetch the channel as is, as we'll need to examine it // regardless of if this is a force close or not. - channel, err := r.fetchActiveChannel(*chanPoint) + channel, err := r.server.chanDB.FetchChannel(*chanPoint) if err != nil { return err } @@ -1996,12 +1996,12 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, if err != nil { return err } - if channel.State().ChanType.IsFrozen() && channel.IsInitiator() && - uint32(bestHeight) < channel.State().ThawHeight { + if channel.ChanType.IsFrozen() && channel.IsInitiator && + uint32(bestHeight) < channel.ThawHeight { return fmt.Errorf("cannot co-op close frozen channel as "+ "initiator until height=%v, (current_height=%v)", - channel.State().ThawHeight, bestHeight) + channel.ThawHeight, bestHeight) } // If a force closure was requested, then we'll handle all the details @@ -2014,14 +2014,14 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, // ensure that the switch doesn't continue to see this channel // as eligible for forwarding HTLC's. If the peer is online, // then we'll also purge all of its indexes. - remotePub := &channel.StateSnapshot().RemoteIdentity + remotePub := channel.IdentityPub if peer, err := r.server.FindPeer(remotePub); err == nil { // TODO(roasbeef): actually get the active channel // instead too? // * so only need to grab from database - peer.WipeChannel(channel.ChannelPoint()) + peer.WipeChannel(&channel.FundingOutpoint) } else { - chanID := lnwire.NewChanIDFromOutPoint(channel.ChannelPoint()) + chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint) r.server.htlcSwitch.RemoveLink(chanID) } @@ -2302,25 +2302,6 @@ func (r *rpcServer) AbandonChannel(ctx context.Context, return &lnrpc.AbandonChannelResponse{}, nil } -// fetchActiveChannel attempts to locate a channel identified by its channel -// point from the database's set of all currently opened channels and -// return it as a fully populated state machine -func (r *rpcServer) fetchActiveChannel(chanPoint wire.OutPoint) ( - *lnwallet.LightningChannel, error) { - - dbChan, err := r.server.chanDB.FetchChannel(chanPoint) - if err != nil { - return nil, err - } - - // If the channel is successfully fetched from the database, - // we create a fully populated channel state machine which - // uses the db channel as backing storage. - return lnwallet.NewLightningChannel( - r.server.cc.wallet.Cfg.Signer, dbChan, nil, - ) -} - // GetInfo returns general information concerning the lightning node including // its identity pubkey, alias, the chains it is connected to, and information // concerning the number of open+pending channels. From d1fa33c8eb2b1333a5525b194faa1f1eb15f7898 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 2 Apr 2020 17:40:08 -0700 Subject: [PATCH 397/562] rpcserver: only block co-op close for frozen chans This commit fixes a recent issue from #4081 that would prevent a frozen channel from being force closed via the rpc. We correct this, so that only the co-op path is inhibited. --- rpcserver.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index bb540d2c5f..e0e119eb01 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1990,19 +1990,12 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, return err } - // If this is a frozen channel, then we only allow the close to proceed - // if we were the responder to this channel. + // Retrieve the best height of the chain, which we'll use to complete + // either closing flow. _, bestHeight, err := r.server.cc.chainIO.GetBestBlock() if err != nil { return err } - if channel.ChanType.IsFrozen() && channel.IsInitiator && - uint32(bestHeight) < channel.ThawHeight { - - return fmt.Errorf("cannot co-op close frozen channel as "+ - "initiator until height=%v, (current_height=%v)", - channel.ThawHeight, bestHeight) - } // If a force closure was requested, then we'll handle all the details // around the creation and broadcast of the unilateral closure @@ -2057,6 +2050,17 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, } }) } else { + // If this is a frozen channel, then we only allow the co-op + // close to proceed if we were the responder to this channel. + if channel.ChanType.IsFrozen() && channel.IsInitiator && + uint32(bestHeight) < channel.ThawHeight { + + return fmt.Errorf("cannot co-op close frozen channel "+ + "as initiator until height=%v, "+ + "(current_height=%v)", channel.ThawHeight, + bestHeight) + } + // If the link is not known by the switch, we cannot gracefully close // the channel. channelID := lnwire.NewChanIDFromOutPoint(chanPoint) From 97761833d215bb5387bf337dc258a5fa749be823 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 15:49:16 -0700 Subject: [PATCH 398/562] lnwallet/channel: populate htlc indexes from disk commit We currently write each HTLCs OutputIndex to disk, but we don't use it when restoring. The restoration is modified to use these directly, since we will have lost access to the sorting of CLTVs after the initial signing process. --- lnwallet/channel.go | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 6f64d34d5e..cc00c7caf4 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -766,7 +766,8 @@ func (c *commitment) toDiskCommit(ourCommit bool) *channeldb.ChannelCommitment { // restart a channel session. func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, commitHeight uint64, htlc *channeldb.HTLC, localCommitKeys, - remoteCommitKeys *CommitmentKeyRing) (PaymentDescriptor, error) { + remoteCommitKeys *CommitmentKeyRing, isLocal bool) (PaymentDescriptor, + error) { // The proper pkScripts for this PaymentDescriptor must be // generated so we can easily locate them within the commitment @@ -811,6 +812,19 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, } } + // Reconstruct the proper local/remote output indexes from the HTLC's + // persisted output index depending on whose commitment we are + // generating. + var ( + localOutputIndex int32 + remoteOutputIndex int32 + ) + if isLocal { + localOutputIndex = htlc.OutputIndex + } else { + remoteOutputIndex = htlc.OutputIndex + } + // With the scripts reconstructed (depending on if this is our commit // vs theirs or a pending commit for the remote party), we can now // re-create the original payment descriptor. @@ -822,6 +836,8 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, HtlcIndex: htlc.HtlcIndex, LogIndex: htlc.LogIndex, OnionBlob: htlc.OnionBlob, + localOutputIndex: localOutputIndex, + remoteOutputIndex: remoteOutputIndex, ourPkScript: ourP2WSH, ourWitnessScript: ourWitnessScript, theirPkScript: theirP2WSH, @@ -837,7 +853,8 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight, // for each side. func (lc *LightningChannel) extractPayDescs(commitHeight uint64, feeRate chainfee.SatPerKWeight, htlcs []channeldb.HTLC, localCommitKeys, - remoteCommitKeys *CommitmentKeyRing) ([]PaymentDescriptor, []PaymentDescriptor, error) { + remoteCommitKeys *CommitmentKeyRing, isLocal bool) ([]PaymentDescriptor, + []PaymentDescriptor, error) { var ( incomingHtlcs []PaymentDescriptor @@ -855,6 +872,7 @@ func (lc *LightningChannel) extractPayDescs(commitHeight uint64, payDesc, err := lc.diskHtlcToPayDesc( feeRate, commitHeight, &htlc, localCommitKeys, remoteCommitKeys, + isLocal, ) if err != nil { return incomingHtlcs, outgoingHtlcs, err @@ -905,6 +923,7 @@ func (lc *LightningChannel) diskCommitToMemCommit(isLocal bool, diskCommit.CommitHeight, chainfee.SatPerKWeight(diskCommit.FeePerKw), diskCommit.Htlcs, localCommitKeys, remoteCommitKeys, + isLocal, ) if err != nil { return nil, err @@ -934,13 +953,6 @@ func (lc *LightningChannel) diskCommitToMemCommit(isLocal bool, commit.dustLimit = lc.channelState.RemoteChanCfg.DustLimit } - // Finally, we'll re-populate the HTLC index for this state so we can - // properly locate each HTLC within the commitment transaction. - err = commit.populateHtlcIndexes(lc.channelState.ChanType) - if err != nil { - return nil, err - } - return commit, nil } From 294e13eefcf2eee9d075908a23234738e8f3ff4d Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 15:49:43 -0700 Subject: [PATCH 399/562] lnwallet/commitment: split our/theirBalance comment --- lnwallet/commitment.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 251f7b2078..2c794b4ce6 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -371,11 +371,16 @@ type unsignedCommitmentTx struct { // fee is the total fee of the commitment transaction. fee btcutil.Amount - // ourBalance|theirBalance are the balances of this commitment *after* - // subtracting commitment fees and anchor outputs. This can be - // different than the balances before creating the commitment - // transaction as one party must pay the commitment fee. - ourBalance lnwire.MilliSatoshi + // ourBalance is our balance on this commitment *after* subtracting + // commitment fees and anchor outputs. This can be different than the + // balances before creating the commitment transaction as one party must + // pay the commitment fee. + ourBalance lnwire.MilliSatoshi + + // theirBalance is their balance of this commitment *after* subtracting + // commitment fees and anchor outputs. This can be different than the + // balances before creating the commitment transaction as one party must + // pay the commitment fee. theirBalance lnwire.MilliSatoshi } From 3ea3b1d0b53b1c6dc2bafc4ebcb57de1a62834b6 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 15:50:10 -0700 Subject: [PATCH 400/562] lnwallet/channel: tie-break HTLCs by cltv when locating This commit fixes #4118 by properly sorting the HTLC signatures sent over the wire to match the BOLT3 BIP69+CLTV sorting of the commitment outputs. To do so, we expose the slice of cltv deltas for HTLCs on the unsigned commitment after applying the commitment sorting. This will be used to locate the proper output index, as the CLTV serves as a tie breaker between HTLCs that otherwise have the same payment hash and amount. Note that #3412 fixed the issue partially by ensuring the commitment was constructed properly (and the second-level prev outpoint's txid was correct), but failed to address that the HTLC signatures were still sent out in the incorrect order. With this, we pass the test case introduce in the next commit. --- lnwallet/channel.go | 26 +++++++++++++++++--------- lnwallet/commitment.go | 5 +++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index cc00c7caf4..c08a90b111 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -549,7 +549,7 @@ type commitment struct { // transition. This ensures that we don't assign multiple HTLC's to the same // index within the commitment transaction. func locateOutputIndex(p *PaymentDescriptor, tx *wire.MsgTx, ourCommit bool, - dups map[PaymentHash][]int32) (int32, error) { + dups map[PaymentHash][]int32, cltvs []uint32) (int32, error) { // Checks to see if element (e) exists in slice (s). contains := func(s []int32, e int32) bool { @@ -571,8 +571,11 @@ func locateOutputIndex(p *PaymentDescriptor, tx *wire.MsgTx, ourCommit bool, } for i, txOut := range tx.TxOut { + cltv := cltvs[i] + if bytes.Equal(txOut.PkScript, pkScript) && - txOut.Value == int64(p.Amount.ToSatoshis()) { + txOut.Value == int64(p.Amount.ToSatoshis()) && + cltv == p.Timeout { // If this payment hash and index has already been // found, then we'll continue in order to avoid any @@ -587,8 +590,8 @@ func locateOutputIndex(p *PaymentDescriptor, tx *wire.MsgTx, ourCommit bool, } } - return 0, fmt.Errorf("unable to find htlc: script=%x, value=%v", - pkScript, p.Amount) + return 0, fmt.Errorf("unable to find htlc: script=%x, value=%v, "+ + "cltv=%v", pkScript, p.Amount, p.Timeout) } // populateHtlcIndexes modifies the set of HTLC's locked-into the target view @@ -596,7 +599,9 @@ func locateOutputIndex(p *PaymentDescriptor, tx *wire.MsgTx, ourCommit bool, // we need to keep track of the indexes of each HTLC in order to properly write // the current state to disk, and also to locate the PaymentDescriptor // corresponding to HTLC outputs in the commitment transaction. -func (c *commitment) populateHtlcIndexes(chanType channeldb.ChannelType) error { +func (c *commitment) populateHtlcIndexes(chanType channeldb.ChannelType, + cltvs []uint32) error { + // First, we'll set up some state to allow us to locate the output // index of the all the HTLC's within the commitment transaction. We // must keep this index so we can validate the HTLC signatures sent to @@ -632,7 +637,7 @@ func (c *commitment) populateHtlcIndexes(chanType channeldb.ChannelType) error { // signatures. case c.isOurs: htlc.localOutputIndex, err = locateOutputIndex( - htlc, c.txn, c.isOurs, dups, + htlc, c.txn, c.isOurs, dups, cltvs, ) if err != nil { return err @@ -653,7 +658,7 @@ func (c *commitment) populateHtlcIndexes(chanType channeldb.ChannelType) error { // index within the HTLC index. case !c.isOurs: htlc.remoteOutputIndex, err = locateOutputIndex( - htlc, c.txn, c.isOurs, dups, + htlc, c.txn, c.isOurs, dups, cltvs, ) if err != nil { return err @@ -2440,8 +2445,11 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool, } // Finally, we'll populate all the HTLC indexes so we can track the - // locations of each HTLC in the commitment state. - if err := c.populateHtlcIndexes(lc.channelState.ChanType); err != nil { + // locations of each HTLC in the commitment state. We pass in the sorted + // slice of CLTV deltas in order to properly locate HTLCs that otherwise + // have the same payment hash and amount. + err = c.populateHtlcIndexes(lc.channelState.ChanType, commitTx.cltvs) + if err != nil { return nil, err } diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 2c794b4ce6..d70f3ca0ee 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -382,6 +382,10 @@ type unsignedCommitmentTx struct { // balances before creating the commitment transaction as one party must // pay the commitment fee. theirBalance lnwire.MilliSatoshi + + // cltvs is a sorted list of CLTV deltas for each HTLC on the commitment + // transaction. Any non-htlc outputs will have a CLTV delay of zero. + cltvs []uint32 } // createUnsignedCommitmentTx generates the unsigned commitment transaction for @@ -562,6 +566,7 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, fee: commitFee, ourBalance: ourBalance, theirBalance: theirBalance, + cltvs: cltvs, }, nil } From b0c3072ff798a31965fd4b9976804188055e0e75 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 30 Mar 2020 15:50:25 -0700 Subject: [PATCH 401/562] lnwallet/channel_test: assert commit sorting of commit diff htlcs This commit adds a test to exercise that HTLC signatures are sent in the correct order, i.e. they match the sorting of the HTLC outputs on the commitment after applying BOLT 3's BIP69+CLTV sort. --- lnwallet/channel_test.go | 133 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 47355f5706..f5c6fb35b1 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -450,6 +450,139 @@ func TestCheckCommitTxSize(t *testing.T) { } } +// TestCommitHTLCSigTieBreak asserts that HTLC signatures are sent the proper +// BIP69+CLTV sorting expected by BOLT 3 when multiple HTLCs have identical +// payment hashes and amounts, but differing CLTVs. This is exercised by adding +// the HTLCs in the descending order of their CLTVs, and asserting that their +// order is reversed when signing. +func TestCommitHTLCSigTieBreak(t *testing.T) { + t.Run("no restart", func(t *testing.T) { + testCommitHTLCSigTieBreak(t, false) + }) + t.Run("restart", func(t *testing.T) { + testCommitHTLCSigTieBreak(t, true) + }) +} + +func testCommitHTLCSigTieBreak(t *testing.T, restart bool) { + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) + if err != nil { + t.Fatalf("unable to create test channels; %v", err) + } + defer cleanUp() + + const ( + htlcAmt = lnwire.MilliSatoshi(20000000) + numHtlcs = 2 + ) + + // Add HTLCs with identical payment hashes and amounts, but descending + // CLTV values. We will expect the signatures to appear in the reverse + // order that the HTLCs are added due to the commitment sorting. + for i := 0; i < numHtlcs; i++ { + var ( + preimage lntypes.Preimage + hash = preimage.Hash() + ) + + htlc := &lnwire.UpdateAddHTLC{ + ID: uint64(i), + PaymentHash: hash, + Amount: htlcAmt, + Expiry: uint32(numHtlcs - i), + } + + if _, err := aliceChannel.AddHTLC(htlc, nil); err != nil { + t.Fatalf("alice unable to add htlc: %v", err) + } + if _, err := bobChannel.ReceiveHTLC(htlc); err != nil { + t.Fatalf("bob unable to receive htlc: %v", err) + } + } + + // Have Alice initiate the first half of the commitment dance. The + // tie-breaking for commitment sorting won't affect the commitment + // signed by Alice because received HTLC scripts commit to the CLTV + // directly, so the outputs will have different scriptPubkeys. + aliceSig, aliceHtlcSigs, _, err := aliceChannel.SignNextCommitment() + if err != nil { + t.Fatalf("unable to sign alice's commitment: %v", err) + } + + err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs) + if err != nil { + t.Fatalf("unable to receive alice's commitment: %v", err) + } + + bobRevocation, _, err := bobChannel.RevokeCurrentCommitment() + if err != nil { + t.Fatalf("unable to revoke bob's commitment: %v", err) + } + _, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation) + if err != nil { + t.Fatalf("unable to receive bob's revocation: %v", err) + } + + // Now have Bob initiate the second half of the commitment dance. Here + // the offered HTLC scripts he adds for Alice will need to have the + // tie-breaking applied because the CLTV is not committed, but instead + // implicit via the construction of the second-level transactions. + bobSig, bobHtlcSigs, bobHtlcs, err := bobChannel.SignNextCommitment() + if err != nil { + t.Fatalf("unable to sign bob's commitment: %v", err) + } + + if len(bobHtlcs) != numHtlcs { + t.Fatalf("expected %d htlcs, got: %v", numHtlcs, len(bobHtlcs)) + } + + // Ensure that our HTLCs appear in the reverse order from which they + // were added by inspecting each's outpoint index. We expect the output + // indexes to be in descending order, i.e. the first HTLC added had the + // highest CLTV and should end up last. + lastIndex := bobHtlcs[0].OutputIndex + for i, htlc := range bobHtlcs[1:] { + if htlc.OutputIndex >= lastIndex { + t.Fatalf("htlc %d output index %d is not descending", + i, htlc.OutputIndex) + } + + lastIndex = htlc.OutputIndex + } + + // If requsted, restart Alice so that we can test that the necessary + // indexes can be reconstructed before needing to validate the + // signatures from Bob. + if restart { + aliceState := aliceChannel.channelState + aliceChannels, err := aliceState.Db.FetchOpenChannels( + aliceState.IdentityPub, + ) + if err != nil { + t.Fatalf("unable to fetch channel: %v", err) + } + + aliceChannelNew, err := NewLightningChannel( + aliceChannel.Signer, aliceChannels[0], + aliceChannel.sigPool, + ) + if err != nil { + t.Fatalf("unable to create new channel: %v", err) + } + + aliceChannel = aliceChannelNew + } + + // Finally, have Alice validate the signatures to ensure that she is + // expecting the signatures in the proper order. + err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs) + if err != nil { + t.Fatalf("unable to receive bob's commitment: %v", err) + } +} + func TestCooperativeChannelClosure(t *testing.T) { t.Parallel() From ae41623a91fd3bffd6fce6412afc198d695e4370 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 2 Apr 2020 14:29:50 -0700 Subject: [PATCH 402/562] lntest/itest/lnd_test: wait when calling OpenChannel In #4130, OpenChannel was changed to assert that the wallet is fully synced before allowing a channel open. This introduced flakes on travis, which are resolved here by using a wait predicate when calling OpenChannel. Note there is one existing call that was not converted, because it is interested in the returned error. This call does not have a wait predicate surrounding it, but this shouldn't cause a flake because other channels are opened earlier in the test that will have already waited for the wallet to sync up. --- lntest/itest/lnd_test.go | 59 ++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 1a11339979..1a372167a5 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -205,14 +205,14 @@ func mineBlocks(t *harnessTest, net *lntest.NetworkHarness, return blocks } -// openChannelAndAssert attempts to open a channel with the specified -// parameters extended from Alice to Bob. Additionally, two items are asserted -// after the channel is considered open: the funding transaction should be -// found within a block, and that Alice can report the status of the new -// channel. -func openChannelAndAssert(ctx context.Context, t *harnessTest, +// openChannelStream blocks until an OpenChannel request for a channel funding +// by alice succeeds. If it does, a stream client is returned to receive events +// about the opening channel. +func openChannelStream(ctx context.Context, t *harnessTest, net *lntest.NetworkHarness, alice, bob *lntest.HarnessNode, - p lntest.OpenChannelParams) *lnrpc.ChannelPoint { + p lntest.OpenChannelParams) lnrpc.Lightning_OpenChannelClient { + + t.t.Helper() // Wait until we are able to fund a channel successfully. This wait // prevents us from erroring out when trying to create a channel while @@ -227,6 +227,22 @@ func openChannelAndAssert(ctx context.Context, t *harnessTest, t.Fatalf("unable to open channel: %v", err) } + return chanOpenUpdate +} + +// openChannelAndAssert attempts to open a channel with the specified +// parameters extended from Alice to Bob. Additionally, two items are asserted +// after the channel is considered open: the funding transaction should be +// found within a block, and that Alice can report the status of the new +// channel. +func openChannelAndAssert(ctx context.Context, t *harnessTest, + net *lntest.NetworkHarness, alice, bob *lntest.HarnessNode, + p lntest.OpenChannelParams) *lnrpc.ChannelPoint { + + t.t.Helper() + + chanOpenUpdate := openChannelStream(ctx, t, net, alice, bob, p) + // Mine 6 blocks, then wait for Alice's node to notify us that the // channel has been opened. The funding transaction should be found // within the first newly mined block. We mine 6 blocks so that in the @@ -1353,23 +1369,20 @@ func testUnconfirmedChannelFunding(net *lntest.NetworkHarness, t *harnessTest) { // Now, we'll connect her to Alice so that they can open a channel // together. The funding flow should select Carol's unconfirmed output // as she doesn't have any other funds since it's a new node. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) if err := net.ConnectNodes(ctxt, carol, net.Alice); err != nil { t.Fatalf("unable to connect dave to alice: %v", err) } - ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - chanOpenUpdate, err := net.OpenChannel( - ctxt, carol, net.Alice, + + chanOpenUpdate := openChannelStream( + ctxt, t, net, carol, net.Alice, lntest.OpenChannelParams{ Amt: chanAmt, PushAmt: pushAmt, SpendUnconfirmed: true, }, ) - if err != nil { - t.Fatalf("unable to open channel between carol and alice: %v", - err) - } // Confirm the channel and wait for it to be recognized by both // parties. Two transactions should be mined, the unconfirmed spend and @@ -5452,15 +5465,12 @@ func testUnannouncedChannels(net *lntest.NetworkHarness, t *harnessTest) { // Open a channel between Alice and Bob, ensuring the // channel has been opened properly. ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) - chanOpenUpdate, err := net.OpenChannel( - ctxt, net.Alice, net.Bob, + chanOpenUpdate := openChannelStream( + ctxt, t, net, net.Alice, net.Bob, lntest.OpenChannelParams{ Amt: amount, }, ) - if err != nil { - t.Fatalf("unable to open channel: %v", err) - } // Mine 2 blocks, and check that the channel is opened but not yet // announced to the network. @@ -5690,8 +5700,8 @@ func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("unable to connect dave to alice: %v", err) } ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - chanOpenUpdate, err := net.OpenChannel( - ctxt, carol, net.Alice, + chanOpenUpdate := openChannelStream( + ctxt, t, net, carol, net.Alice, lntest.OpenChannelParams{ Amt: chanAmt, Private: true, @@ -6870,15 +6880,12 @@ func testMaxPendingChannels(net *lntest.NetworkHarness, t *harnessTest) { openStreams := make([]lnrpc.Lightning_OpenChannelClient, maxPendingChannels) for i := 0; i < maxPendingChannels; i++ { ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - stream, err := net.OpenChannel( - ctxt, net.Alice, carol, + stream := openChannelStream( + ctxt, t, net, net.Alice, carol, lntest.OpenChannelParams{ Amt: amount, }, ) - if err != nil { - t.Fatalf("unable to open channel: %v", err) - } openStreams[i] = stream } From 3f4dc0decd192ecdf5878fb554fdeebe3f9660b3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 2 Apr 2020 09:31:51 -0700 Subject: [PATCH 403/562] lnwallet/channel: increase htlc validation strictness This commit adds an additional santity check that rejects zero-value HTLCs, preventing them from being added to the channel state even if the channel config's minhtlc value is zero. --- lnwallet/channel.go | 9 +++++++++ lnwallet/channel_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index c08a90b111..96f53e3ef6 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -67,6 +67,10 @@ var ( ErrBelowMinHTLC = fmt.Errorf("proposed HTLC value is below minimum " + "allowed HTLC value") + // ErrInvalidHTLCAmt signals that a proposed HTLC has a value that is + // not positive. + ErrInvalidHTLCAmt = fmt.Errorf("proposed HTLC value must be positive") + // ErrCannotSyncCommitChains is returned if, upon receiving a ChanSync // message, the state machine deems that is unable to properly // synchronize states with the remote peer. In this case we should fail @@ -3234,6 +3238,11 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter, amtInFlight += entry.Amount numInFlight++ + // Check that the HTLC amount is positive. + if entry.Amount == 0 { + return ErrInvalidHTLCAmt + } + // Check that the value of the HTLC they added // is above our minimum. if entry.Amount < constraints.MinHTLC { diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index f5c6fb35b1..c266db1c80 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -6636,6 +6636,41 @@ func TestMinHTLC(t *testing.T) { } } +// TestInvalidHTLCAmt tests that ErrInvalidHTLCAmt is returned when trying to +// add HTLCs that don't carry a positive value. +func TestInvalidHTLCAmt(t *testing.T) { + t.Parallel() + + // We'll kick off the test by creating our channels which both are + // loaded with 5 BTC each. + aliceChannel, bobChannel, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) + if err != nil { + t.Fatalf("unable to create test channels: %v", err) + } + defer cleanUp() + + // We'll set the min HTLC values for each party to zero, which + // technically would permit zero-value HTLCs. + aliceChannel.channelState.LocalChanCfg.MinHTLC = 0 + bobChannel.channelState.RemoteChanCfg.MinHTLC = 0 + + // Create a zero-value HTLC. + htlcAmt := lnwire.MilliSatoshi(0) + htlc, _ := createHTLC(0, htlcAmt) + + // Sending or receiving the HTLC should fail with ErrInvalidHTLCAmt. + _, err = aliceChannel.AddHTLC(htlc, nil) + if err != ErrInvalidHTLCAmt { + t.Fatalf("expected ErrInvalidHTLCAmt, got: %v", err) + } + _, err = bobChannel.ReceiveHTLC(htlc) + if err != ErrInvalidHTLCAmt { + t.Fatalf("expected ErrInvalidHTLCAmt, got: %v", err) + } +} + // TestNewBreachRetributionSkipsDustHtlcs ensures that in the case of a // contract breach, all dust HTLCs are ignored and not reflected in the // produced BreachRetribution struct. We ignore these HTLCs as they aren't From 0512b39f23006eba8710d12bde3359c1ef5e1b11 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 3 Apr 2020 09:09:23 +0200 Subject: [PATCH 404/562] lnrpc: format protobuf file --- lnrpc/rpc.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 001944a0c2..5b6b3630a5 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2638,9 +2638,9 @@ message ChannelGraph { repeated ChannelEdge edges = 2; } -enum NodeMetricType { +enum NodeMetricType { UNKNOWN = 0; - BETWEENNESS_CENTRALITY = 1; + BETWEENNESS_CENTRALITY = 1; } message NodeMetricsRequest { From 2ae61162dbe357e6f2cd34b1f20250e296a8baed Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 3 Apr 2020 09:09:39 +0200 Subject: [PATCH 405/562] lnrpc: move initiator enum out of close summary Move enum out of CloseSummary struct for more general use. This does not change the encoding of the enum, and will only cause compile time errors for existing clients. This enum has not been included in a release yet, so we can make this move without much disruption. --- lnrpc/rpc.pb.go | 1575 +++++++++++++++++++------------------- lnrpc/rpc.proto | 14 +- lnrpc/rpc.swagger.json | 24 +- lntest/itest/lnd_test.go | 8 +- rpcserver.go | 22 +- 5 files changed, 822 insertions(+), 821 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 77325c1c37..ad59f22df9 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -104,6 +104,37 @@ func (CommitmentType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_77a6da22d6a3feb1, []int{1} } +type Initiator int32 + +const ( + Initiator_INITIATOR_UNKNOWN Initiator = 0 + Initiator_INITIATOR_LOCAL Initiator = 1 + Initiator_INITIATOR_REMOTE Initiator = 2 + Initiator_INITIATOR_BOTH Initiator = 3 +) + +var Initiator_name = map[int32]string{ + 0: "INITIATOR_UNKNOWN", + 1: "INITIATOR_LOCAL", + 2: "INITIATOR_REMOTE", + 3: "INITIATOR_BOTH", +} + +var Initiator_value = map[string]int32{ + "INITIATOR_UNKNOWN": 0, + "INITIATOR_LOCAL": 1, + "INITIATOR_REMOTE": 2, + "INITIATOR_BOTH": 3, +} + +func (x Initiator) String() string { + return proto.EnumName(Initiator_name, int32(x)) +} + +func (Initiator) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{2} +} + type NodeMetricType int32 const ( @@ -126,7 +157,7 @@ func (x NodeMetricType) String() string { } func (NodeMetricType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{2} + return fileDescriptor_77a6da22d6a3feb1, []int{3} } type InvoiceHTLCState int32 @@ -154,7 +185,7 @@ func (x InvoiceHTLCState) String() string { } func (InvoiceHTLCState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{3} + return fileDescriptor_77a6da22d6a3feb1, []int{4} } type FeatureBit int32 @@ -224,7 +255,7 @@ func (x FeatureBit) String() string { } func (FeatureBit) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{4} + return fileDescriptor_77a6da22d6a3feb1, []int{5} } type ChannelCloseSummary_ClosureType int32 @@ -264,37 +295,6 @@ func (ChannelCloseSummary_ClosureType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_77a6da22d6a3feb1, []int{43, 0} } -type ChannelCloseSummary_Initiator int32 - -const ( - ChannelCloseSummary_UNKNOWN ChannelCloseSummary_Initiator = 0 - ChannelCloseSummary_LOCAL ChannelCloseSummary_Initiator = 1 - ChannelCloseSummary_REMOTE ChannelCloseSummary_Initiator = 2 - ChannelCloseSummary_BOTH ChannelCloseSummary_Initiator = 3 -) - -var ChannelCloseSummary_Initiator_name = map[int32]string{ - 0: "UNKNOWN", - 1: "LOCAL", - 2: "REMOTE", - 3: "BOTH", -} - -var ChannelCloseSummary_Initiator_value = map[string]int32{ - "UNKNOWN": 0, - "LOCAL": 1, - "REMOTE": 2, - "BOTH": 3, -} - -func (x ChannelCloseSummary_Initiator) String() string { - return proto.EnumName(ChannelCloseSummary_Initiator_name, int32(x)) -} - -func (ChannelCloseSummary_Initiator) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{43, 1} -} - type Peer_SyncType int32 const ( @@ -3490,17 +3490,17 @@ type ChannelCloseSummary struct { //Open initiator is the party that initiated opening the channel. Note that //this value may be unknown if the channel was closed before we migrated to //store open channel information after close. - OpenInitiator ChannelCloseSummary_Initiator `protobuf:"varint,11,opt,name=open_initiator,json=openInitiator,proto3,enum=lnrpc.ChannelCloseSummary_Initiator" json:"open_initiator,omitempty"` + OpenInitiator Initiator `protobuf:"varint,11,opt,name=open_initiator,json=openInitiator,proto3,enum=lnrpc.Initiator" json:"open_initiator,omitempty"` //* //Close initiator indicates which party initiated the close. This value will //be unknown for channels that were cooperatively closed before we started //tracking cooperative close initiators. Note that this indicates which party //initiated a close, and it is possible for both to initiate cooperative or //force closes, although only one party's close will be confirmed on chain. - CloseInitiator ChannelCloseSummary_Initiator `protobuf:"varint,12,opt,name=close_initiator,json=closeInitiator,proto3,enum=lnrpc.ChannelCloseSummary_Initiator" json:"close_initiator,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + CloseInitiator Initiator `protobuf:"varint,12,opt,name=close_initiator,json=closeInitiator,proto3,enum=lnrpc.Initiator" json:"close_initiator,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ChannelCloseSummary) Reset() { *m = ChannelCloseSummary{} } @@ -3598,18 +3598,18 @@ func (m *ChannelCloseSummary) GetCloseType() ChannelCloseSummary_ClosureType { return ChannelCloseSummary_COOPERATIVE_CLOSE } -func (m *ChannelCloseSummary) GetOpenInitiator() ChannelCloseSummary_Initiator { +func (m *ChannelCloseSummary) GetOpenInitiator() Initiator { if m != nil { return m.OpenInitiator } - return ChannelCloseSummary_UNKNOWN + return Initiator_INITIATOR_UNKNOWN } -func (m *ChannelCloseSummary) GetCloseInitiator() ChannelCloseSummary_Initiator { +func (m *ChannelCloseSummary) GetCloseInitiator() Initiator { if m != nil { return m.CloseInitiator } - return ChannelCloseSummary_UNKNOWN + return Initiator_INITIATOR_UNKNOWN } type ClosedChannelsRequest struct { @@ -11686,11 +11686,11 @@ func (m *ChannelUpdate) GetExtraOpaqueData() []byte { func init() { proto.RegisterEnum("lnrpc.AddressType", AddressType_name, AddressType_value) proto.RegisterEnum("lnrpc.CommitmentType", CommitmentType_name, CommitmentType_value) + proto.RegisterEnum("lnrpc.Initiator", Initiator_name, Initiator_value) proto.RegisterEnum("lnrpc.NodeMetricType", NodeMetricType_name, NodeMetricType_value) proto.RegisterEnum("lnrpc.InvoiceHTLCState", InvoiceHTLCState_name, InvoiceHTLCState_value) proto.RegisterEnum("lnrpc.FeatureBit", FeatureBit_name, FeatureBit_value) proto.RegisterEnum("lnrpc.ChannelCloseSummary_ClosureType", ChannelCloseSummary_ClosureType_name, ChannelCloseSummary_ClosureType_value) - proto.RegisterEnum("lnrpc.ChannelCloseSummary_Initiator", ChannelCloseSummary_Initiator_name, ChannelCloseSummary_Initiator_value) proto.RegisterEnum("lnrpc.Peer_SyncType", Peer_SyncType_name, Peer_SyncType_value) proto.RegisterEnum("lnrpc.PeerEvent_EventType", PeerEvent_EventType_name, PeerEvent_EventType_value) proto.RegisterEnum("lnrpc.PendingChannelsResponse_ForceClosedChannel_AnchorState", PendingChannelsResponse_ForceClosedChannel_AnchorState_name, PendingChannelsResponse_ForceClosedChannel_AnchorState_value) @@ -11878,749 +11878,750 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11870 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0xeb, 0x6f, 0x24, 0x49, - 0x72, 0x18, 0x3e, 0xfd, 0x62, 0x77, 0x47, 0x3f, 0xd8, 0x4c, 0xbe, 0x7a, 0x38, 0x33, 0x3b, 0xb3, - 0xb5, 0x7b, 0xbb, 0xb3, 0xb3, 0x77, 0x9c, 0xd9, 0xb9, 0x9b, 0xbd, 0xbb, 0xdd, 0x9f, 0x4e, 0xd7, - 0x24, 0x9b, 0xc3, 0xbe, 0xe1, 0x6b, 0xab, 0x9b, 0xbb, 0x9a, 0xd3, 0xa3, 0xae, 0xd8, 0x9d, 0x24, - 0x4b, 0xd3, 0x5d, 0xd5, 0x5b, 0x55, 0xcd, 0xc7, 0x1d, 0xf6, 0xf7, 0xc1, 0xb0, 0x05, 0xc1, 0xf0, - 0x03, 0x82, 0x2d, 0x03, 0x96, 0x2d, 0xd8, 0xb0, 0x60, 0x18, 0x86, 0x01, 0x41, 0xc0, 0xc9, 0x1f, - 0x0c, 0xf8, 0xbb, 0xbe, 0xf8, 0x01, 0x43, 0xf2, 0x17, 0x43, 0x10, 0x60, 0xd8, 0x96, 0x3f, 0x18, - 0x30, 0x04, 0xf8, 0x1f, 0x30, 0x32, 0x22, 0xb3, 0x2a, 0xab, 0xbb, 0x38, 0x33, 0x7b, 0xb7, 0xbe, - 0x2f, 0x64, 0x57, 0x64, 0xe4, 0x3b, 0x32, 0x32, 0x22, 0x23, 0x22, 0x13, 0xca, 0xfe, 0xb8, 0xbf, - 0x3e, 0xf6, 0xbd, 0xd0, 0x63, 0x85, 0xa1, 0xeb, 0x8f, 0xfb, 0x6b, 0xb7, 0x4f, 0x3d, 0xef, 0x74, - 0xc8, 0x1f, 0xda, 0x63, 0xe7, 0xa1, 0xed, 0xba, 0x5e, 0x68, 0x87, 0x8e, 0xe7, 0x06, 0x84, 0x64, - 0xfc, 0x08, 0xea, 0x4f, 0xb9, 0xdb, 0xe5, 0x7c, 0x60, 0xf2, 0xcf, 0x27, 0x3c, 0x08, 0xd9, 0xfb, - 0xb0, 0x60, 0xf3, 0x1f, 0x73, 0x3e, 0xb0, 0xc6, 0x76, 0x10, 0x8c, 0xcf, 0x7c, 0x3b, 0xe0, 0xcd, - 0xcc, 0xbd, 0xcc, 0xfd, 0xaa, 0xd9, 0xa0, 0x84, 0xc3, 0x08, 0xce, 0xde, 0x84, 0x6a, 0x20, 0x50, - 0xb9, 0x1b, 0xfa, 0xde, 0xf8, 0xaa, 0x99, 0x45, 0xbc, 0x8a, 0x80, 0xb5, 0x09, 0x64, 0x0c, 0x61, - 0x3e, 0xaa, 0x21, 0x18, 0x7b, 0x6e, 0xc0, 0xd9, 0x23, 0x58, 0xea, 0x3b, 0xe3, 0x33, 0xee, 0x5b, - 0x98, 0x79, 0xe4, 0xf2, 0x91, 0xe7, 0x3a, 0xfd, 0x66, 0xe6, 0x5e, 0xee, 0x7e, 0xd9, 0x64, 0x94, - 0x26, 0x72, 0xec, 0xc9, 0x14, 0xf6, 0x2e, 0xcc, 0x73, 0x97, 0xe0, 0x7c, 0x80, 0xb9, 0x64, 0x55, - 0xf5, 0x18, 0x2c, 0x32, 0x18, 0xbf, 0x9d, 0x85, 0x85, 0x8e, 0xeb, 0x84, 0x9f, 0xd9, 0xc3, 0x21, - 0x0f, 0x55, 0x9f, 0xde, 0x85, 0xf9, 0x0b, 0x04, 0x60, 0x9f, 0x2e, 0x3c, 0x7f, 0x20, 0x7b, 0x54, - 0x27, 0xf0, 0xa1, 0x84, 0x5e, 0xdb, 0xb2, 0xec, 0xb5, 0x2d, 0x4b, 0x1d, 0xae, 0xdc, 0x35, 0xc3, - 0xf5, 0x2e, 0xcc, 0xfb, 0xbc, 0xef, 0x9d, 0x73, 0xff, 0xca, 0xba, 0x70, 0xdc, 0x81, 0x77, 0xd1, - 0xcc, 0xdf, 0xcb, 0xdc, 0x2f, 0x98, 0x75, 0x05, 0xfe, 0x0c, 0xa1, 0x6c, 0x03, 0xe6, 0xfb, 0x67, - 0xb6, 0xeb, 0xf2, 0xa1, 0x75, 0x6c, 0xf7, 0x5f, 0x4c, 0xc6, 0x41, 0xb3, 0x70, 0x2f, 0x73, 0xbf, - 0xf2, 0xf8, 0xe6, 0x3a, 0xce, 0xea, 0xfa, 0xe6, 0x99, 0xed, 0x6e, 0x60, 0x4a, 0xd7, 0xb5, 0xc7, - 0xc1, 0x99, 0x17, 0x9a, 0x75, 0x99, 0x83, 0xc0, 0x81, 0xb1, 0x04, 0x4c, 0x1f, 0x09, 0x1a, 0x7b, - 0xe3, 0x5f, 0x65, 0x60, 0xf1, 0xc8, 0x1d, 0x7a, 0xfd, 0x17, 0x3f, 0xe3, 0x10, 0xa5, 0xf4, 0x21, - 0xfb, 0xba, 0x7d, 0xc8, 0x7d, 0xd9, 0x3e, 0xac, 0xc0, 0x52, 0xb2, 0xb1, 0xb2, 0x17, 0x1c, 0x96, - 0x45, 0xee, 0x53, 0xae, 0x9a, 0xa5, 0xba, 0xf1, 0x1e, 0x34, 0xfa, 0x13, 0xdf, 0xe7, 0xee, 0x4c, - 0x3f, 0xe6, 0x25, 0x3c, 0xea, 0xc8, 0x9b, 0x50, 0x75, 0xf9, 0x45, 0x8c, 0x26, 0x69, 0xd7, 0xe5, - 0x17, 0x0a, 0xc5, 0x68, 0xc2, 0xca, 0x74, 0x35, 0xb2, 0x01, 0x7f, 0x99, 0x81, 0xfc, 0x51, 0x78, - 0xe9, 0xb1, 0x27, 0x50, 0xb5, 0x07, 0x03, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x8d, 0x69, 0xa5, 0xd4, - 0x1f, 0x33, 0xd9, 0xc5, 0x16, 0x25, 0xf5, 0xae, 0xc6, 0xdc, 0xac, 0xd8, 0xf1, 0x07, 0x6b, 0x42, - 0x51, 0x7e, 0x62, 0xbd, 0x65, 0x53, 0x7d, 0xb2, 0x3b, 0x00, 0xf6, 0xc8, 0x9b, 0xb8, 0xa1, 0x15, - 0xd8, 0x21, 0x8e, 0x58, 0xce, 0x2c, 0x13, 0xa4, 0x6b, 0x87, 0xec, 0x16, 0x94, 0xc7, 0x2f, 0xac, - 0xa0, 0xef, 0x3b, 0xe3, 0x10, 0x89, 0xa7, 0x6c, 0x96, 0xc6, 0x2f, 0xba, 0xf8, 0xcd, 0xde, 0x87, - 0x92, 0x37, 0x09, 0xc7, 0x9e, 0xe3, 0x86, 0x92, 0x5e, 0xe6, 0x65, 0x43, 0x0e, 0x26, 0xe1, 0xa1, - 0x00, 0x9b, 0x11, 0x02, 0x7b, 0x1b, 0x6a, 0x7d, 0xcf, 0x3d, 0x71, 0xfc, 0x11, 0x71, 0x84, 0xe6, - 0x1c, 0xd6, 0x95, 0x04, 0x1a, 0x7f, 0x94, 0x85, 0x4a, 0xcf, 0xb7, 0xdd, 0xc0, 0xee, 0x0b, 0x00, - 0x5b, 0x85, 0x62, 0x78, 0x69, 0x9d, 0xd9, 0xc1, 0x19, 0x76, 0xb5, 0x6c, 0xce, 0x85, 0x97, 0x3b, - 0x76, 0x70, 0xc6, 0x56, 0x60, 0x8e, 0x5a, 0x89, 0x1d, 0xca, 0x99, 0xf2, 0x4b, 0x2c, 0x10, 0x77, - 0x32, 0xb2, 0x92, 0x55, 0xe5, 0x90, 0x62, 0x1a, 0xee, 0x64, 0xb4, 0xa9, 0xc3, 0x45, 0xe7, 0x8f, - 0xc5, 0x74, 0x53, 0x05, 0xd4, 0xbd, 0x32, 0x42, 0xb0, 0x8e, 0x37, 0xa1, 0x2a, 0x93, 0xb9, 0x73, - 0x7a, 0x46, 0x7d, 0x2c, 0x98, 0x15, 0x42, 0x40, 0x90, 0x28, 0x21, 0x74, 0x46, 0xdc, 0x0a, 0x42, - 0x7b, 0x34, 0x96, 0x5d, 0x2a, 0x0b, 0x48, 0x57, 0x00, 0x30, 0xd9, 0x0b, 0xed, 0xa1, 0x75, 0xc2, - 0x79, 0xd0, 0x2c, 0xca, 0x64, 0x01, 0xd9, 0xe6, 0x3c, 0x60, 0x5f, 0x83, 0xfa, 0x80, 0x07, 0xa1, - 0x25, 0x27, 0x83, 0x07, 0xcd, 0x12, 0xae, 0xfc, 0x9a, 0x80, 0xb6, 0x14, 0x90, 0xdd, 0x06, 0xf0, - 0xed, 0x0b, 0x4b, 0x0c, 0x04, 0xbf, 0x6c, 0x96, 0x69, 0x16, 0x7c, 0xfb, 0xa2, 0x77, 0xb9, 0xc3, - 0x2f, 0x05, 0xd5, 0x3c, 0xe5, 0xa1, 0x36, 0x68, 0x81, 0xa4, 0x4e, 0x63, 0x17, 0x98, 0x06, 0xde, - 0xe2, 0xa1, 0xed, 0x0c, 0x03, 0xf6, 0x21, 0x54, 0x43, 0x0d, 0x19, 0xd9, 0x60, 0x25, 0x22, 0x21, - 0x2d, 0x83, 0x99, 0xc0, 0x33, 0xce, 0xa0, 0xb4, 0xcd, 0xf9, 0xae, 0x33, 0x72, 0x42, 0xb6, 0x02, - 0x85, 0x13, 0xe7, 0x92, 0x13, 0xb1, 0xe7, 0x76, 0x6e, 0x98, 0xf4, 0xc9, 0xee, 0x02, 0xe0, 0x0f, - 0x6b, 0x14, 0x51, 0xd3, 0xce, 0x0d, 0xb3, 0x8c, 0xb0, 0xbd, 0xc0, 0x0e, 0xd9, 0x1a, 0x14, 0xc7, - 0xdc, 0xef, 0x73, 0x35, 0x6f, 0x3b, 0x37, 0x4c, 0x05, 0xd8, 0x28, 0x42, 0x61, 0x28, 0x4a, 0x37, - 0xfe, 0xa4, 0x00, 0x95, 0x2e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, - 0xcd, 0xde, 0x82, 0x0a, 0x0e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x91, 0x6d, 0x66, - 0x4c, 0x10, 0xe0, 0x2e, 0x42, 0x59, 0x03, 0x72, 0xf6, 0x48, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x42, - 0xc9, 0x1e, 0x85, 0xd4, 0xbc, 0x2a, 0x82, 0x8b, 0xf6, 0x28, 0xc4, 0xa6, 0xbd, 0x09, 0xd5, 0xb1, - 0x7d, 0x35, 0x12, 0x6b, 0x39, 0x22, 0x87, 0xaa, 0x59, 0x91, 0x30, 0x24, 0x88, 0xc7, 0xb0, 0xa8, - 0xa3, 0xa8, 0xca, 0x0b, 0x51, 0xe5, 0x0b, 0x1a, 0xb6, 0x6c, 0xc3, 0xbb, 0x30, 0xaf, 0xf2, 0xf8, - 0xd4, 0x1f, 0x24, 0x93, 0xb2, 0x59, 0x97, 0x60, 0xd5, 0xcb, 0xfb, 0xd0, 0x38, 0x71, 0x5c, 0x7b, - 0x68, 0xf5, 0x87, 0xe1, 0xb9, 0x35, 0xe0, 0xc3, 0xd0, 0x46, 0x8a, 0x29, 0x98, 0x75, 0x84, 0x6f, - 0x0e, 0xc3, 0xf3, 0x2d, 0x01, 0x65, 0x5f, 0x87, 0xf2, 0x09, 0xe7, 0x16, 0x0e, 0x56, 0xb3, 0x94, - 0x58, 0x78, 0x6a, 0x86, 0xcc, 0xd2, 0x89, 0x9a, 0xab, 0xaf, 0x43, 0xc3, 0x9b, 0x84, 0xa7, 0x9e, - 0xe3, 0x9e, 0x5a, 0x82, 0xdf, 0x59, 0xce, 0x00, 0x69, 0x28, 0xbf, 0x91, 0x7d, 0x94, 0x31, 0xeb, - 0x2a, 0x4d, 0x70, 0x9e, 0xce, 0x80, 0xbd, 0x03, 0xf3, 0x43, 0x3b, 0x08, 0xad, 0x33, 0x6f, 0x6c, - 0x8d, 0x27, 0xc7, 0x2f, 0xf8, 0x55, 0xb3, 0x86, 0x03, 0x51, 0x13, 0xe0, 0x1d, 0x6f, 0x7c, 0x88, - 0x40, 0x41, 0xd9, 0xd8, 0x4e, 0x6a, 0x04, 0xdc, 0xcb, 0xdc, 0xaf, 0x99, 0x65, 0x01, 0xa1, 0x4a, - 0x9f, 0xc3, 0x22, 0x4e, 0x4f, 0x7f, 0x12, 0x84, 0xde, 0xc8, 0x12, 0xbc, 0xda, 0x1f, 0x04, 0xcd, - 0x0a, 0xd2, 0xda, 0x7b, 0xb2, 0xb1, 0xda, 0x1c, 0xaf, 0x6f, 0xf1, 0x20, 0xdc, 0x44, 0x64, 0x93, - 0x70, 0xc5, 0x86, 0x7e, 0x65, 0x2e, 0x0c, 0xa6, 0xe1, 0xec, 0xeb, 0xc0, 0xec, 0xe1, 0xd0, 0xbb, - 0xb0, 0x02, 0x3e, 0x3c, 0xb1, 0xe4, 0x20, 0x36, 0xeb, 0xf7, 0x32, 0xf7, 0x4b, 0x66, 0x03, 0x53, - 0xba, 0x7c, 0x78, 0x72, 0x48, 0x70, 0xf6, 0x21, 0xe0, 0x62, 0xb2, 0x4e, 0xb8, 0x1d, 0x4e, 0x7c, - 0x1e, 0x34, 0xe7, 0xef, 0xe5, 0xee, 0xd7, 0x1f, 0x2f, 0x44, 0xe3, 0x85, 0xe0, 0x0d, 0x27, 0x34, - 0xab, 0x02, 0x4f, 0x7e, 0x07, 0x6b, 0x5b, 0xb0, 0x92, 0xde, 0x24, 0x41, 0x54, 0x62, 0x54, 0x04, - 0x31, 0xe6, 0x4d, 0xf1, 0x93, 0x2d, 0x41, 0xe1, 0xdc, 0x1e, 0x4e, 0xb8, 0xe4, 0xe9, 0xf4, 0xf1, - 0x51, 0xf6, 0x3b, 0x19, 0xe3, 0x8f, 0x33, 0x50, 0xa5, 0x5e, 0x4a, 0x59, 0xe4, 0x2d, 0xa8, 0x29, - 0x6a, 0xe0, 0xbe, 0xef, 0xf9, 0x92, 0xab, 0x29, 0xca, 0x6b, 0x0b, 0x98, 0xd8, 0x55, 0x14, 0xd2, - 0xd8, 0xe7, 0xce, 0xc8, 0x3e, 0x55, 0x45, 0x2b, 0x52, 0x3a, 0x94, 0x60, 0xf6, 0x41, 0x5c, 0x9e, - 0xef, 0x4d, 0x42, 0x2e, 0xf7, 0xbc, 0xaa, 0xec, 0x9e, 0x29, 0x60, 0x51, 0xe9, 0xf8, 0xf5, 0x1a, - 0x74, 0x6e, 0xfc, 0x6e, 0x06, 0x98, 0x68, 0x76, 0xcf, 0xa3, 0x02, 0x24, 0x85, 0x4e, 0xe7, 0xcc, - 0xbc, 0xf6, 0x0a, 0xc9, 0xbe, 0x6c, 0x85, 0x18, 0x50, 0xa0, 0xb6, 0xe7, 0x53, 0xda, 0x4e, 0x49, - 0x3f, 0xc8, 0x97, 0x72, 0x8d, 0xbc, 0xf1, 0x5f, 0x72, 0xb0, 0xb4, 0x49, 0x5b, 0x76, 0xab, 0xdf, - 0xe7, 0xe3, 0x68, 0xed, 0xdc, 0x85, 0x8a, 0xeb, 0x0d, 0xb8, 0xa2, 0x58, 0x6a, 0x18, 0x08, 0x90, - 0x46, 0xae, 0x67, 0xb6, 0xe3, 0x52, 0xc3, 0x69, 0x30, 0xcb, 0x08, 0xc1, 0x66, 0xbf, 0x03, 0xf3, - 0x63, 0xee, 0x0e, 0xf4, 0x25, 0x42, 0x42, 0x55, 0x4d, 0x82, 0xe5, 0xea, 0xb8, 0x0b, 0x95, 0x93, - 0x09, 0xe1, 0x09, 0xc6, 0x92, 0x47, 0x1a, 0x00, 0x09, 0x6a, 0x11, 0x7f, 0x19, 0x4f, 0x82, 0x33, - 0x4c, 0x2d, 0x60, 0x6a, 0x51, 0x7c, 0x8b, 0xa4, 0x3b, 0x00, 0x83, 0x49, 0x10, 0xca, 0x15, 0x33, - 0x87, 0x89, 0x65, 0x01, 0xa1, 0x15, 0xf3, 0x0d, 0x58, 0x1c, 0xd9, 0x97, 0x16, 0xd2, 0x8e, 0xe5, - 0xb8, 0xd6, 0xc9, 0x10, 0xf7, 0x9c, 0x22, 0xe2, 0x35, 0x46, 0xf6, 0xe5, 0xa7, 0x22, 0xa5, 0xe3, - 0x6e, 0x23, 0x5c, 0xb0, 0x15, 0x25, 0xee, 0xf8, 0x3c, 0xe0, 0xfe, 0x39, 0x47, 0x4e, 0x90, 0x8f, - 0x64, 0x1a, 0x93, 0xa0, 0xa2, 0x45, 0x23, 0xd1, 0xef, 0x70, 0xd8, 0xa7, 0x65, 0x6f, 0x16, 0x47, - 0x8e, 0xbb, 0x13, 0x0e, 0xfb, 0x62, 0x5f, 0x11, 0x7c, 0x64, 0xcc, 0x7d, 0xeb, 0xc5, 0x05, 0xae, - 0xe1, 0x3c, 0xf2, 0x8d, 0x43, 0xee, 0x3f, 0xbb, 0x10, 0x5b, 0x7f, 0x3f, 0x40, 0x46, 0x64, 0x5f, - 0x35, 0x2b, 0xb8, 0xc0, 0x4b, 0xfd, 0x40, 0xb0, 0x20, 0xfb, 0x4a, 0x2c, 0x42, 0xd1, 0x5a, 0x1b, - 0x67, 0x81, 0x0f, 0xb0, 0xf8, 0x00, 0x39, 0x6a, 0x0d, 0x1b, 0xdb, 0x92, 0x09, 0xa2, 0x9e, 0x40, - 0x50, 0xbd, 0x6a, 0xec, 0xc9, 0xd0, 0x3e, 0x0d, 0x90, 0xa5, 0xd4, 0xcc, 0xaa, 0x04, 0x6e, 0x0b, - 0x98, 0xf1, 0x19, 0x09, 0x59, 0xda, 0xdc, 0xca, 0x35, 0x23, 0xb6, 0x7a, 0x84, 0xe0, 0xbc, 0x96, - 0x4c, 0xf9, 0x95, 0x36, 0x69, 0xd9, 0x94, 0x49, 0x33, 0x7e, 0x3f, 0x03, 0x55, 0x59, 0x32, 0x0a, - 0x25, 0x6c, 0x1d, 0x98, 0x9a, 0xc5, 0xf0, 0xd2, 0x19, 0x58, 0xc7, 0x57, 0x21, 0x0f, 0x88, 0x68, - 0x76, 0x6e, 0x98, 0x0d, 0x99, 0xd6, 0xbb, 0x74, 0x06, 0x1b, 0x22, 0x85, 0x3d, 0x80, 0x46, 0x02, - 0x3f, 0x08, 0x7d, 0xa2, 0xe8, 0x9d, 0x1b, 0x66, 0x5d, 0xc3, 0xee, 0x86, 0xbe, 0x58, 0x23, 0x42, - 0xe4, 0x99, 0x84, 0x96, 0xe3, 0x0e, 0xf8, 0x25, 0x92, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x23, 0x40, - 0x1b, 0x75, 0xa8, 0xea, 0xc5, 0x19, 0xa7, 0x50, 0x52, 0xf2, 0x12, 0x0a, 0x0c, 0x53, 0x4d, 0x32, - 0xcb, 0x61, 0xd4, 0x92, 0x9b, 0x50, 0x4a, 0xb6, 0xc0, 0x2c, 0x86, 0xaf, 0x5d, 0xb1, 0xf1, 0x3d, - 0x68, 0xec, 0x0a, 0xe2, 0x71, 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x05, 0xe6, 0xb4, 0x45, 0x53, 0x36, - 0xe5, 0x97, 0xd8, 0x73, 0xcf, 0xbc, 0x20, 0x94, 0xb5, 0xe0, 0x6f, 0xe3, 0x4f, 0x32, 0xc0, 0xda, - 0x41, 0xe8, 0x8c, 0xec, 0x90, 0x6f, 0xf3, 0x88, 0x2d, 0x1c, 0x40, 0x55, 0x94, 0xd6, 0xf3, 0x5a, - 0x24, 0x90, 0x91, 0x40, 0xf1, 0xbe, 0x5c, 0xc6, 0xb3, 0x19, 0xd6, 0x75, 0x6c, 0x62, 0xf3, 0x89, - 0x02, 0xc4, 0x2a, 0x0b, 0x6d, 0xff, 0x94, 0x87, 0x28, 0xc6, 0x49, 0x79, 0x1f, 0x08, 0x24, 0x04, - 0xb8, 0xb5, 0x5f, 0x86, 0x85, 0x99, 0x32, 0x74, 0xbe, 0x5c, 0x4e, 0xe1, 0xcb, 0x39, 0x9d, 0x2f, - 0x5b, 0xb0, 0x98, 0x68, 0x97, 0xa4, 0xb4, 0x55, 0x28, 0x8a, 0x05, 0x21, 0x84, 0x83, 0x0c, 0x49, - 0x95, 0x27, 0x9c, 0x0b, 0x31, 0xf8, 0x21, 0x2c, 0x9d, 0x70, 0xee, 0xdb, 0x21, 0x26, 0xe2, 0x8a, - 0x11, 0x33, 0x24, 0x0b, 0x5e, 0x90, 0x69, 0x5d, 0x3b, 0x3c, 0xe4, 0xbe, 0x98, 0x29, 0xe3, 0xbf, - 0x65, 0x60, 0x5e, 0x70, 0xd0, 0x3d, 0xdb, 0xbd, 0x52, 0xe3, 0xb4, 0x9b, 0x3a, 0x4e, 0xf7, 0xb5, - 0xcd, 0x50, 0xc3, 0xfe, 0xb2, 0x83, 0x94, 0x9b, 0x1e, 0x24, 0x76, 0x0f, 0xaa, 0x89, 0xb6, 0x16, - 0xb0, 0xad, 0x10, 0x44, 0x8d, 0xfc, 0xf9, 0x87, 0xf1, 0x1d, 0x68, 0xc4, 0xcd, 0x96, 0x63, 0xc8, - 0x20, 0x2f, 0x48, 0x52, 0x16, 0x80, 0xbf, 0x8d, 0x7f, 0x9c, 0x21, 0xc4, 0x4d, 0xcf, 0x89, 0xa4, - 0x53, 0x81, 0x28, 0xe4, 0x5e, 0x85, 0x28, 0x7e, 0x5f, 0x2b, 0xd5, 0xff, 0xfc, 0x9d, 0x15, 0x4b, - 0x27, 0xe0, 0xee, 0xc0, 0xb2, 0x87, 0x43, 0x64, 0xbe, 0x25, 0xb3, 0x28, 0xbe, 0x5b, 0xc3, 0xa1, - 0xf1, 0x2e, 0x2c, 0x68, 0xad, 0x7b, 0x49, 0x3f, 0xf6, 0x81, 0xed, 0x3a, 0x41, 0x78, 0xe4, 0x06, - 0x63, 0x4d, 0x70, 0xbb, 0x05, 0x65, 0xc1, 0x61, 0x45, 0xcb, 0x68, 0xc9, 0x16, 0x4c, 0xc1, 0x72, - 0x45, 0xbb, 0x02, 0x4c, 0xb4, 0x2f, 0x65, 0x62, 0x56, 0x26, 0xda, 0x97, 0x98, 0x68, 0x7c, 0x07, - 0x16, 0x13, 0xe5, 0xc9, 0xaa, 0xdf, 0x84, 0xc2, 0x24, 0xbc, 0xf4, 0x94, 0x68, 0x5e, 0x91, 0x14, - 0x22, 0x14, 0x40, 0x93, 0x52, 0x8c, 0x8f, 0x61, 0x61, 0x9f, 0x5f, 0xc8, 0x45, 0xac, 0x1a, 0xf2, - 0x0e, 0xe4, 0x5f, 0xa1, 0x14, 0x62, 0xba, 0xb1, 0x0e, 0x4c, 0xcf, 0x2c, 0x6b, 0xd5, 0x74, 0xc4, - 0x4c, 0x42, 0x47, 0x34, 0xde, 0x01, 0xd6, 0x75, 0x4e, 0xdd, 0x3d, 0x1e, 0x04, 0xf6, 0x69, 0xb4, - 0xec, 0x1b, 0x90, 0x1b, 0x05, 0xa7, 0x92, 0x47, 0x89, 0x9f, 0xc6, 0x37, 0x61, 0x31, 0x81, 0x27, - 0x0b, 0xbe, 0x0d, 0xe5, 0xc0, 0x39, 0x75, 0x51, 0xb0, 0x92, 0x45, 0xc7, 0x00, 0x63, 0x1b, 0x96, - 0x3e, 0xe5, 0xbe, 0x73, 0x72, 0xf5, 0xaa, 0xe2, 0x93, 0xe5, 0x64, 0xa7, 0xcb, 0x69, 0xc3, 0xf2, - 0x54, 0x39, 0xb2, 0x7a, 0x22, 0x5f, 0x39, 0x93, 0x25, 0x93, 0x3e, 0x34, 0xbe, 0x97, 0xd5, 0xf9, - 0x9e, 0x71, 0x04, 0x6c, 0xd3, 0x73, 0x5d, 0xde, 0x0f, 0x0f, 0x39, 0xf7, 0xe3, 0x53, 0xaa, 0x98, - 0x56, 0x2b, 0x8f, 0x57, 0xe5, 0xc8, 0x4e, 0x33, 0x53, 0x49, 0xc4, 0x0c, 0xf2, 0x63, 0xee, 0x8f, - 0xb0, 0xe0, 0x92, 0x89, 0xbf, 0x8d, 0x65, 0x58, 0x4c, 0x14, 0x2b, 0xf5, 0xfa, 0x47, 0xb0, 0xbc, - 0xe5, 0x04, 0xfd, 0xd9, 0x0a, 0x57, 0xa1, 0x38, 0x9e, 0x1c, 0x5b, 0x49, 0xbe, 0xfc, 0x8c, 0x5f, - 0x09, 0x6d, 0x6f, 0x3a, 0x87, 0x2c, 0xeb, 0xaf, 0x67, 0x20, 0xbf, 0xd3, 0xdb, 0xdd, 0x64, 0x6b, - 0x50, 0x72, 0xdc, 0xbe, 0x37, 0x12, 0x82, 0x17, 0xf5, 0x39, 0xfa, 0xbe, 0x76, 0x81, 0xdd, 0x82, - 0x32, 0xca, 0x6b, 0x42, 0xb5, 0x95, 0xa2, 0x4f, 0x49, 0x00, 0x76, 0xbd, 0xfe, 0x0b, 0xa1, 0x53, - 0xf3, 0xcb, 0xb1, 0xe3, 0xa3, 0xd6, 0xac, 0x94, 0xe1, 0x3c, 0xed, 0xf5, 0x71, 0x02, 0x69, 0xc4, - 0xc6, 0xbf, 0x29, 0x41, 0x51, 0xee, 0xb6, 0xb4, 0x73, 0x87, 0xce, 0x39, 0x8f, 0x77, 0x6e, 0xf1, - 0x25, 0xe4, 0x01, 0x9f, 0x8f, 0xbc, 0x30, 0x12, 0xd8, 0x68, 0x0e, 0xaa, 0x04, 0x94, 0x22, 0x9b, - 0x26, 0x34, 0xd0, 0x11, 0x43, 0x8e, 0x90, 0xfa, 0xfa, 0x56, 0x7e, 0x0b, 0x8a, 0x6a, 0xef, 0xcf, - 0x47, 0x3a, 0xcd, 0x5c, 0x9f, 0xa4, 0xb5, 0x35, 0x28, 0xf5, 0xed, 0xb1, 0xdd, 0x77, 0xc2, 0x2b, - 0xc9, 0x10, 0xa2, 0x6f, 0x51, 0xfa, 0xd0, 0xeb, 0xdb, 0x43, 0xeb, 0xd8, 0x1e, 0xda, 0x6e, 0x9f, - 0x4b, 0xdd, 0xbd, 0x8a, 0xc0, 0x0d, 0x82, 0x09, 0xfd, 0x5c, 0xb6, 0x53, 0x61, 0x91, 0x0a, 0x2f, - 0x5b, 0xaf, 0xd0, 0x84, 0x70, 0xe9, 0x8d, 0x46, 0x8e, 0xd0, 0x32, 0x48, 0x0c, 0xcb, 0x99, 0x65, - 0x82, 0x6c, 0x73, 0xec, 0xad, 0x4c, 0xbe, 0xa0, 0xa1, 0x2b, 0x53, 0x55, 0x04, 0xfc, 0x8c, 0x0e, - 0x12, 0x66, 0x65, 0xb1, 0x9c, 0x26, 0x8b, 0xbd, 0x0f, 0x0b, 0x13, 0x37, 0xe0, 0x61, 0x38, 0xe4, - 0x83, 0xa8, 0x2d, 0x15, 0x44, 0x6a, 0x44, 0x09, 0xaa, 0x39, 0xeb, 0xb0, 0x48, 0x87, 0x0e, 0x81, - 0x1d, 0x7a, 0xc1, 0x99, 0x13, 0x58, 0x81, 0xd0, 0x90, 0x48, 0xdd, 0x5d, 0xc0, 0xa4, 0xae, 0x4c, - 0xe9, 0x92, 0x8a, 0xb4, 0x3a, 0x85, 0xef, 0xf3, 0x3e, 0x77, 0xce, 0xf9, 0x00, 0xe5, 0xb4, 0x9c, - 0xb9, 0x9c, 0xc8, 0x63, 0xca, 0x44, 0x14, 0xba, 0x27, 0x23, 0x6b, 0x32, 0x1e, 0xd8, 0x42, 0x58, - 0xa9, 0x93, 0x30, 0xec, 0x4e, 0x46, 0x47, 0x04, 0x61, 0x8f, 0x40, 0x49, 0x62, 0x52, 0x3e, 0x9c, - 0x4f, 0xf0, 0x33, 0x41, 0xac, 0x66, 0x55, 0x62, 0x90, 0xa0, 0x98, 0x90, 0x39, 0x1b, 0x53, 0x32, - 0x67, 0x13, 0x8a, 0x63, 0xdf, 0x39, 0xb7, 0x43, 0xde, 0x5c, 0x20, 0x06, 0x2e, 0x3f, 0x05, 0x67, - 0x70, 0x5c, 0x27, 0x74, 0xec, 0xd0, 0xf3, 0x9b, 0x0c, 0xd3, 0x62, 0x00, 0x7b, 0x00, 0x0b, 0x48, - 0x23, 0x41, 0x68, 0x87, 0x93, 0x40, 0x4a, 0xa0, 0x8b, 0x48, 0x4c, 0x28, 0x43, 0x77, 0x11, 0x8e, - 0x42, 0x28, 0xfb, 0x26, 0xac, 0x10, 0x59, 0x60, 0x0e, 0x29, 0x59, 0xa3, 0x40, 0xb0, 0x84, 0x43, - 0xb1, 0x88, 0xa9, 0x82, 0xbe, 0xa5, 0x7c, 0x2d, 0xa4, 0x83, 0x27, 0xb0, 0x2a, 0xc9, 0x64, 0x26, - 0xd7, 0x32, 0xe6, 0x5a, 0xa2, 0xe4, 0xa9, 0x6c, 0xeb, 0xb0, 0x20, 0x9a, 0xe4, 0xf4, 0x2d, 0x99, - 0x5b, 0xac, 0x84, 0x15, 0xd1, 0x7a, 0xd4, 0x94, 0xe6, 0x29, 0xd1, 0xc4, 0xb4, 0x67, 0xfc, 0x8a, - 0x7d, 0x0f, 0xe6, 0x89, 0x64, 0x50, 0xbd, 0x42, 0x4e, 0xbf, 0x86, 0x9c, 0x7e, 0x59, 0x9d, 0x70, - 0x46, 0xa9, 0xc8, 0xec, 0xeb, 0xfd, 0xc4, 0xb7, 0x58, 0x0e, 0x43, 0xe7, 0x84, 0x87, 0xce, 0x88, - 0x37, 0x57, 0x89, 0xc0, 0xd4, 0xb7, 0x58, 0xa9, 0x93, 0x31, 0xa6, 0x34, 0x89, 0x2f, 0xd0, 0x17, - 0xd2, 0xee, 0xd0, 0x0b, 0xb8, 0x3a, 0xa2, 0x6a, 0xde, 0x94, 0x8b, 0x50, 0x00, 0x95, 0x0c, 0x29, - 0x04, 0x71, 0x52, 0x7a, 0xa2, 0x83, 0xc4, 0x5b, 0x48, 0x0c, 0x35, 0xd2, 0x7d, 0xd4, 0x61, 0xa2, - 0xd8, 0xc5, 0xcf, 0xec, 0x0b, 0xc5, 0x41, 0x6e, 0xe3, 0xfc, 0x82, 0x00, 0x49, 0xde, 0xf1, 0xd3, - 0x0c, 0x6d, 0x88, 0x92, 0x7f, 0x04, 0x9a, 0x7a, 0x47, 0x9c, 0xc3, 0xf2, 0xdc, 0xe1, 0x95, 0x64, - 0x26, 0x40, 0xa0, 0x03, 0x77, 0x88, 0xab, 0xd9, 0x71, 0x75, 0x14, 0xe2, 0xbd, 0x55, 0x05, 0x44, - 0xa4, 0xbb, 0x50, 0x19, 0x4f, 0x8e, 0x87, 0x4e, 0x9f, 0x50, 0x72, 0x54, 0x0a, 0x81, 0x10, 0x41, - 0xe8, 0xb7, 0x44, 0x51, 0x84, 0x91, 0x47, 0x8c, 0x8a, 0x84, 0x21, 0x0a, 0xf2, 0x76, 0xee, 0x23, - 0x3b, 0xa9, 0x9a, 0xf8, 0xdb, 0xd8, 0x80, 0xa5, 0x64, 0xa3, 0xe5, 0xc6, 0xf3, 0x00, 0x4a, 0x92, - 0x57, 0xa9, 0x83, 0x8f, 0xba, 0x76, 0x14, 0x2d, 0x54, 0xb4, 0x28, 0xdd, 0xf8, 0xad, 0x39, 0x58, - 0x94, 0xd0, 0x4d, 0x31, 0xb4, 0xdd, 0xc9, 0x68, 0x64, 0xfb, 0x29, 0x4c, 0x30, 0xf3, 0x72, 0x26, - 0x98, 0x9d, 0x61, 0x82, 0x49, 0xcd, 0x97, 0x78, 0x68, 0x52, 0xf3, 0x15, 0x73, 0x49, 0xca, 0x88, - 0x7e, 0x0e, 0x5a, 0x93, 0xe0, 0x1e, 0x9d, 0xb7, 0xce, 0xb0, 0xec, 0x42, 0x0a, 0xcb, 0xd6, 0x19, - 0xee, 0xdc, 0x14, 0xc3, 0x7d, 0x13, 0x88, 0x68, 0xd4, 0xec, 0x17, 0x49, 0x3f, 0x41, 0x98, 0x3c, - 0x4c, 0x7d, 0x17, 0xe6, 0xa7, 0x79, 0x1c, 0x31, 0xd3, 0x7a, 0x0a, 0x87, 0x73, 0x46, 0x1c, 0x77, - 0x2b, 0x0d, 0xb9, 0x2c, 0x39, 0x9c, 0x33, 0xe2, 0xbb, 0x98, 0xa2, 0xf0, 0xdb, 0x00, 0x54, 0x37, - 0x2e, 0x1a, 0xc0, 0x45, 0xf3, 0x4e, 0x72, 0x2e, 0xf4, 0x51, 0x5f, 0x17, 0x1f, 0x13, 0x9f, 0xe3, - 0x2a, 0x2a, 0x63, 0x4e, 0x5c, 0x40, 0xcf, 0xa0, 0xee, 0x8d, 0xb9, 0x6b, 0xc5, 0xbc, 0xa6, 0x82, - 0x45, 0xbd, 0xfd, 0x92, 0xa2, 0x3a, 0x0a, 0xd7, 0xac, 0x89, 0xbc, 0xd1, 0x27, 0xdb, 0xa3, 0x81, - 0xe7, 0x5a, 0x69, 0xd5, 0x2f, 0x51, 0x5a, 0x1d, 0x33, 0x47, 0xdf, 0xc6, 0xdf, 0xcc, 0x40, 0x45, - 0x6b, 0x36, 0x5b, 0x86, 0x85, 0xcd, 0x83, 0x83, 0xc3, 0xb6, 0xd9, 0xea, 0x75, 0x3e, 0x6d, 0x5b, - 0x9b, 0xbb, 0x07, 0xdd, 0x76, 0xe3, 0x86, 0x00, 0xef, 0x1e, 0x6c, 0xb6, 0x76, 0xad, 0xed, 0x03, - 0x73, 0x53, 0x81, 0x33, 0x6c, 0x05, 0x98, 0xd9, 0xde, 0x3b, 0xe8, 0xb5, 0x13, 0xf0, 0x2c, 0x6b, - 0x40, 0x75, 0xc3, 0x6c, 0xb7, 0x36, 0x77, 0x24, 0x24, 0xc7, 0x96, 0xa0, 0xb1, 0x7d, 0xb4, 0xbf, - 0xd5, 0xd9, 0x7f, 0x6a, 0x6d, 0xb6, 0xf6, 0x37, 0xdb, 0xbb, 0xed, 0xad, 0x46, 0x9e, 0xd5, 0xa0, - 0xdc, 0xda, 0x68, 0xed, 0x6f, 0x1d, 0xec, 0xb7, 0xb7, 0x1a, 0x05, 0xe3, 0xbb, 0x50, 0x8e, 0x3b, - 0x5a, 0x81, 0xe2, 0xd1, 0xfe, 0xb3, 0xfd, 0x83, 0xcf, 0xf6, 0x1b, 0x37, 0x58, 0x19, 0x0a, 0x58, - 0x7f, 0x23, 0xc3, 0x00, 0xe6, 0xa8, 0xce, 0x46, 0x96, 0x95, 0x20, 0xbf, 0x71, 0xd0, 0xdb, 0x69, - 0xe4, 0x8c, 0xbf, 0xc8, 0xc0, 0x32, 0x76, 0x79, 0x30, 0xcd, 0x04, 0xee, 0x41, 0xa5, 0xef, 0x79, - 0x63, 0xa1, 0x69, 0xc5, 0x12, 0x85, 0x0e, 0x12, 0x0b, 0x9c, 0x98, 0xf7, 0x89, 0xe7, 0xf7, 0xb9, - 0xe4, 0x01, 0x80, 0xa0, 0x6d, 0x01, 0x11, 0x34, 0x28, 0x89, 0x98, 0x30, 0x88, 0x05, 0x54, 0x08, - 0x46, 0x28, 0x2b, 0x30, 0x77, 0xec, 0x73, 0xbb, 0x7f, 0x26, 0x57, 0xbf, 0xfc, 0x62, 0xef, 0xc5, - 0x67, 0x00, 0x7d, 0x41, 0x53, 0x43, 0x3e, 0xc0, 0x25, 0x50, 0x32, 0xe7, 0x25, 0x7c, 0x53, 0x82, - 0xc5, 0x6e, 0x64, 0x1f, 0xdb, 0xee, 0xc0, 0x73, 0xf9, 0x40, 0xaa, 0x1a, 0x31, 0xc0, 0x38, 0x84, - 0x95, 0xe9, 0xfe, 0x49, 0x7e, 0xf1, 0xa1, 0xc6, 0x2f, 0x48, 0xf2, 0x5f, 0xbb, 0x9e, 0x14, 0x34, - 0xde, 0xf1, 0xb7, 0xf3, 0x90, 0x17, 0x92, 0xe0, 0xb5, 0x42, 0xa3, 0x2e, 0xda, 0xe7, 0x66, 0xcc, - 0x3f, 0x78, 0xd4, 0x40, 0x22, 0x02, 0x9d, 0x67, 0x95, 0x11, 0x82, 0xa2, 0x41, 0x94, 0xec, 0xf3, - 0xfe, 0xb9, 0x3c, 0xd0, 0xa2, 0x64, 0x93, 0xf7, 0xcf, 0x51, 0xa7, 0xb2, 0x43, 0xca, 0x4b, 0xeb, - 0xbd, 0x18, 0xd8, 0x21, 0xe6, 0x94, 0x49, 0x98, 0xaf, 0x18, 0x25, 0x61, 0xae, 0x26, 0x14, 0x1d, - 0xf7, 0xd8, 0x9b, 0xb8, 0x03, 0x5c, 0xde, 0x25, 0x53, 0x7d, 0xa2, 0xb5, 0x09, 0x39, 0x91, 0xd8, - 0x88, 0x68, 0x35, 0x97, 0x04, 0xa0, 0x27, 0xb6, 0xa2, 0x0f, 0xa0, 0x1c, 0x5c, 0xb9, 0x7d, 0x7d, - 0x0d, 0x2f, 0xc9, 0xf1, 0x11, 0xbd, 0x5f, 0xef, 0x5e, 0xb9, 0x7d, 0x5c, 0xb1, 0xa5, 0x40, 0xfe, - 0x62, 0x4f, 0xa0, 0x14, 0x9d, 0xfb, 0x12, 0x07, 0xbe, 0xa9, 0xe7, 0x50, 0x87, 0xbd, 0xa4, 0x5e, - 0x47, 0xa8, 0xec, 0x21, 0xcc, 0xe1, 0xe1, 0x6c, 0xd0, 0xac, 0x62, 0x26, 0x25, 0xef, 0x8b, 0x66, - 0xa0, 0xa1, 0x87, 0x0f, 0xf0, 0xa0, 0xd6, 0x94, 0x68, 0x6b, 0xcf, 0xa0, 0x96, 0x28, 0x4b, 0x57, - 0xa2, 0x6b, 0xa4, 0x44, 0xbf, 0xad, 0x2b, 0xd1, 0xf1, 0x4e, 0x20, 0xb3, 0xe9, 0x4a, 0xf5, 0x2f, - 0x43, 0x49, 0x75, 0x45, 0xac, 0x3f, 0xb9, 0x76, 0xac, 0xee, 0xf3, 0xfd, 0xcd, 0xc6, 0x0d, 0x36, - 0x0f, 0x95, 0xd6, 0x26, 0x2e, 0x69, 0x04, 0x64, 0x04, 0xca, 0x61, 0xab, 0xdb, 0x8d, 0x20, 0x59, - 0x63, 0x1b, 0x1a, 0xd3, 0x2d, 0x15, 0x34, 0x19, 0x2a, 0x98, 0x3c, 0xba, 0x8e, 0x01, 0x42, 0x45, - 0xa2, 0xd3, 0x68, 0x92, 0xc3, 0xe9, 0xc3, 0x78, 0x02, 0x0d, 0xb1, 0xaf, 0x89, 0xa1, 0x0a, 0xb4, - 0x23, 0xe0, 0xa1, 0x90, 0xed, 0xf4, 0xe3, 0xeb, 0x92, 0x59, 0x21, 0x18, 0x56, 0x65, 0x7c, 0x08, - 0x0b, 0x5a, 0xb6, 0x58, 0xa5, 0x15, 0x7b, 0xe5, 0xb4, 0x4a, 0x8b, 0x0a, 0x0c, 0xa5, 0x18, 0xab, - 0xb0, 0x2c, 0x3e, 0xdb, 0xe7, 0xdc, 0x0d, 0xbb, 0x93, 0x63, 0xb2, 0x39, 0x3a, 0x9e, 0x2b, 0x14, - 0x9b, 0x72, 0x94, 0x72, 0x3d, 0x91, 0xaf, 0x4b, 0xed, 0x37, 0x8b, 0xa4, 0xb1, 0xa6, 0xd5, 0x80, - 0x19, 0xd7, 0xf1, 0x6f, 0x42, 0x0b, 0x2e, 0x47, 0x20, 0x31, 0xac, 0x87, 0xed, 0xb6, 0x69, 0x1d, - 0xec, 0xef, 0x76, 0xf6, 0x05, 0xa3, 0x14, 0xc3, 0x8a, 0x80, 0xed, 0x6d, 0x84, 0x64, 0x8c, 0x06, - 0xd4, 0x9f, 0xf2, 0xb0, 0xe3, 0x9e, 0x78, 0xca, 0xbe, 0xf6, 0x97, 0x05, 0x98, 0x8f, 0x40, 0xb1, - 0x16, 0x7d, 0xce, 0xfd, 0xc0, 0xf1, 0x5c, 0x14, 0x88, 0xcb, 0xa6, 0xfa, 0x14, 0xbb, 0x9b, 0x33, - 0xe0, 0x6e, 0xe8, 0x84, 0x57, 0x56, 0xe2, 0xc8, 0xad, 0xae, 0xc0, 0x72, 0x17, 0x5d, 0x82, 0x82, - 0x3d, 0x74, 0x6c, 0x65, 0xaa, 0xa5, 0x0f, 0x01, 0xed, 0x7b, 0x43, 0xcf, 0x47, 0xd9, 0xb7, 0x6c, - 0xd2, 0x07, 0x7b, 0x04, 0x4b, 0x42, 0x06, 0xd7, 0xcf, 0x41, 0x91, 0x7f, 0xd0, 0xe9, 0x1f, 0x73, - 0x27, 0xa3, 0xc3, 0xf8, 0x2c, 0x54, 0xa4, 0x88, 0xbd, 0x53, 0xe4, 0x90, 0xc2, 0x52, 0x94, 0x81, - 0xd4, 0xb9, 0x05, 0x77, 0x32, 0x6a, 0x61, 0x4a, 0x84, 0xff, 0x18, 0x96, 0x05, 0x7e, 0x24, 0x5e, - 0x45, 0x39, 0xe6, 0x31, 0x87, 0x28, 0xac, 0x23, 0xd3, 0xa2, 0x3c, 0xb7, 0xa0, 0x4c, 0xad, 0x12, - 0x33, 0x5e, 0x20, 0x31, 0x1e, 0x9b, 0xc2, 0xfd, 0x60, 0xc6, 0xaa, 0x3a, 0x47, 0x82, 0xc0, 0x94, - 0x55, 0x55, 0xb3, 0xcb, 0x96, 0xa6, 0xed, 0xb2, 0x8f, 0x61, 0xf9, 0x58, 0x90, 0xe0, 0x19, 0xb7, - 0x07, 0xdc, 0xb7, 0x62, 0xc2, 0x26, 0x75, 0x65, 0x51, 0x24, 0xee, 0x60, 0x5a, 0xb4, 0x0e, 0x84, - 0x9c, 0x23, 0xd8, 0x02, 0x1f, 0x58, 0xa1, 0x67, 0xa1, 0xf8, 0x83, 0x0c, 0xa6, 0x64, 0xd6, 0x08, - 0xdc, 0xf3, 0x36, 0x05, 0x30, 0x89, 0x77, 0xea, 0xdb, 0xe3, 0x33, 0xa9, 0x50, 0x44, 0x78, 0x4f, - 0x05, 0x90, 0xdd, 0x86, 0xa2, 0x20, 0x79, 0x97, 0x93, 0xf1, 0x8b, 0x44, 0x76, 0x05, 0x62, 0x6f, - 0xc3, 0x1c, 0xd6, 0x11, 0x34, 0x1b, 0x48, 0xef, 0xd5, 0x98, 0x91, 0x3b, 0xae, 0x29, 0xd3, 0x84, - 0x30, 0x39, 0xf1, 0x1d, 0xe2, 0x32, 0x65, 0x13, 0x7f, 0xb3, 0xef, 0x6b, 0x2c, 0x6b, 0x11, 0xf3, - 0x2a, 0x79, 0x60, 0x8a, 0xd2, 0xae, 0xe3, 0x5e, 0x5f, 0x29, 0x33, 0xfa, 0x41, 0xbe, 0x54, 0x69, - 0x54, 0x8d, 0x6f, 0x43, 0x81, 0x46, 0x47, 0x10, 0x21, 0x8e, 0x5d, 0x46, 0x12, 0x21, 0x42, 0x9b, - 0x50, 0x74, 0x79, 0x78, 0xe1, 0xf9, 0x2f, 0xd4, 0xa1, 0xb4, 0xfc, 0x34, 0x7e, 0x8c, 0xa7, 0x29, - 0x91, 0xc5, 0x9d, 0x14, 0x43, 0x41, 0x1e, 0x34, 0xbd, 0xc1, 0x99, 0x2d, 0x0f, 0x78, 0x4a, 0x08, - 0xe8, 0x9e, 0xd9, 0x33, 0xe4, 0x91, 0x9d, 0x35, 0xba, 0xbf, 0x0d, 0x75, 0x65, 0xe3, 0x0f, 0xac, - 0x21, 0x3f, 0x09, 0x25, 0xb9, 0x57, 0xa5, 0x81, 0x3f, 0xd8, 0xe5, 0x27, 0xa1, 0xb1, 0x07, 0x0b, - 0x92, 0x20, 0x0f, 0xc6, 0x5c, 0x55, 0xfd, 0x9d, 0x34, 0x79, 0xba, 0xf2, 0x78, 0x31, 0xb9, 0xd1, - 0x92, 0xef, 0x42, 0x42, 0xc8, 0x36, 0x3e, 0x01, 0xa6, 0x6f, 0xc3, 0xb2, 0x3c, 0x29, 0xd5, 0xaa, - 0xb3, 0x7c, 0x65, 0x12, 0x8b, 0x64, 0x67, 0x67, 0x20, 0x46, 0x27, 0x98, 0xf4, 0xfb, 0xca, 0xf7, - 0xa2, 0x64, 0xaa, 0x4f, 0xe3, 0x4f, 0x33, 0xb0, 0x88, 0x85, 0x29, 0x7d, 0x40, 0x32, 0xd9, 0x9f, - 0xb9, 0x91, 0x62, 0x7e, 0x74, 0xd9, 0x87, 0x3e, 0xbe, 0xfc, 0xe9, 0x69, 0x7e, 0xe6, 0xf4, 0xf4, - 0x3d, 0x68, 0x0c, 0xf8, 0xd0, 0x41, 0x37, 0x1c, 0x25, 0x4a, 0x90, 0x06, 0x30, 0xaf, 0xe0, 0x52, - 0x1b, 0x34, 0xfe, 0x41, 0x06, 0x16, 0x48, 0x52, 0x41, 0xbd, 0x5a, 0x0e, 0xd4, 0xc7, 0x4a, 0x91, - 0x94, 0xac, 0x4a, 0xf6, 0x29, 0xde, 0xc1, 0x11, 0x4a, 0xc8, 0x3b, 0x37, 0xa4, 0x82, 0x29, 0xa1, - 0xec, 0x23, 0xd4, 0x61, 0x5c, 0x0b, 0x81, 0x29, 0x6e, 0x3d, 0xc9, 0x49, 0xd9, 0xb9, 0x81, 0x0a, - 0x8e, 0x8b, 0xa0, 0x8d, 0x92, 0xd0, 0x6c, 0x05, 0xd8, 0xd8, 0x86, 0x5a, 0xa2, 0x9a, 0xc4, 0x11, - 0x6f, 0x95, 0x8e, 0x78, 0x67, 0xcc, 0x28, 0xd9, 0x59, 0x33, 0xca, 0x15, 0x2c, 0x9a, 0xdc, 0x1e, - 0x5c, 0x6d, 0x7b, 0xfe, 0x61, 0x70, 0x1c, 0x6e, 0x93, 0xf8, 0x27, 0xf8, 0x7b, 0x64, 0x1b, 0x4c, - 0x9c, 0xa3, 0x2a, 0x13, 0x91, 0x52, 0x97, 0xbf, 0x06, 0xf5, 0xd8, 0x88, 0xa8, 0x9d, 0xc5, 0xd5, - 0x22, 0x3b, 0x22, 0x1e, 0xc9, 0x09, 0x55, 0x33, 0x38, 0x0e, 0xe5, 0x69, 0x1c, 0xfe, 0x36, 0xfe, - 0x46, 0x1e, 0x98, 0xa0, 0xe6, 0x29, 0x82, 0x99, 0x32, 0x7f, 0x66, 0x67, 0xcc, 0x9f, 0x8f, 0x80, - 0x69, 0x08, 0xca, 0x2a, 0x9b, 0x8b, 0xac, 0xb2, 0x8d, 0x18, 0x57, 0x1a, 0x65, 0x1f, 0xc1, 0x92, - 0x94, 0xa5, 0x93, 0x4d, 0x25, 0xd2, 0x60, 0x24, 0x54, 0x27, 0xda, 0xab, 0x4c, 0x9f, 0x42, 0xfd, - 0xa7, 0xd3, 0x36, 0x34, 0x7d, 0x2a, 0xc5, 0x5f, 0x23, 0xc0, 0xb9, 0x57, 0x12, 0x60, 0x71, 0x86, - 0x00, 0xb5, 0xc3, 0x9f, 0x52, 0xf2, 0xf0, 0xc7, 0x80, 0x9a, 0x32, 0x70, 0x92, 0x5f, 0x07, 0x09, - 0x8e, 0x15, 0x69, 0xe5, 0x44, 0xdf, 0x8e, 0xfb, 0xd0, 0x50, 0x27, 0x34, 0xd1, 0xf1, 0x12, 0xf9, - 0x2c, 0xc8, 0x03, 0xbe, 0x4d, 0x75, 0xc8, 0x94, 0x38, 0xcc, 0xaf, 0x4c, 0x1d, 0xe6, 0xbf, 0x0f, - 0x0b, 0x81, 0xa0, 0x5f, 0x6b, 0xe2, 0x4a, 0x07, 0x23, 0x3e, 0x40, 0xad, 0xad, 0x64, 0x36, 0x30, - 0xe1, 0x28, 0x86, 0xcf, 0x1e, 0x9d, 0xd4, 0x52, 0x8e, 0x4e, 0x9e, 0xc4, 0xb6, 0xc0, 0xe0, 0xcc, - 0x19, 0xa1, 0xcc, 0x10, 0x3b, 0xe3, 0xc8, 0x01, 0xee, 0x9e, 0x39, 0x23, 0x53, 0x19, 0x9e, 0xc5, - 0x87, 0xf1, 0x7f, 0x32, 0xd0, 0x10, 0x74, 0x90, 0x58, 0x62, 0xdf, 0x05, 0x64, 0x06, 0xaf, 0xb9, - 0xc2, 0x2a, 0x02, 0x57, 0x2d, 0xb0, 0x6f, 0x03, 0xae, 0x18, 0x4b, 0xa8, 0xa8, 0x72, 0x7d, 0x35, - 0x93, 0xeb, 0x2b, 0xe6, 0xa1, 0x3b, 0x37, 0x48, 0xf7, 0x10, 0x10, 0xf6, 0x5d, 0x28, 0x0b, 0xc2, - 0x44, 0x2a, 0x91, 0x3e, 0x60, 0x4a, 0xf2, 0x4a, 0x59, 0x23, 0x22, 0xeb, 0x58, 0x7e, 0xa6, 0x99, - 0x6f, 0xf3, 0x29, 0xe6, 0x5b, 0x6d, 0x01, 0xef, 0x00, 0x3c, 0xe3, 0x57, 0xbb, 0x5e, 0x1f, 0xf5, - 0xca, 0x3b, 0x00, 0x82, 0x96, 0x4f, 0xec, 0x91, 0x23, 0xcf, 0x84, 0x0a, 0x66, 0xf9, 0x05, 0xbf, - 0xda, 0x46, 0x80, 0x98, 0x48, 0x91, 0x1c, 0xaf, 0xe2, 0x82, 0x59, 0x7a, 0xc1, 0xaf, 0x68, 0x09, - 0x5b, 0x50, 0x7b, 0xc6, 0xaf, 0xb6, 0x38, 0x09, 0x99, 0x9e, 0x2f, 0x88, 0xc8, 0xb7, 0x2f, 0x84, - 0x54, 0x99, 0x30, 0xbd, 0x56, 0x7c, 0xfb, 0xe2, 0x19, 0xbf, 0x52, 0x66, 0xe0, 0xa2, 0x48, 0x1f, - 0x7a, 0x7d, 0xb9, 0x6f, 0x2a, 0x27, 0x92, 0xb8, 0x51, 0xe6, 0xdc, 0x0b, 0xfc, 0x6d, 0xfc, 0x55, - 0x06, 0x6a, 0xa2, 0xfd, 0xc8, 0x96, 0xc5, 0x94, 0x29, 0x5f, 0xa4, 0x4c, 0xec, 0x8b, 0xf4, 0x58, - 0x72, 0x35, 0xe2, 0xf1, 0xd9, 0xeb, 0x79, 0x3c, 0xce, 0x0d, 0x31, 0xf8, 0x0f, 0xa0, 0x4c, 0xcb, - 0x52, 0xac, 0xf3, 0x5c, 0x62, 0x82, 0x13, 0x1d, 0x32, 0x4b, 0x88, 0xf6, 0x8c, 0x5c, 0x1f, 0xb4, - 0xf3, 0x45, 0x1a, 0xe2, 0xb2, 0x1f, 0x9d, 0x2a, 0xa6, 0x4c, 0x43, 0xe1, 0x1a, 0xd7, 0x07, 0xfd, - 0xf0, 0x6e, 0x6e, 0xe6, 0xf0, 0xee, 0x00, 0x4a, 0x62, 0xaa, 0xb1, 0xb3, 0x29, 0x85, 0x66, 0xd2, - 0x0a, 0x15, 0x92, 0x80, 0x2d, 0x36, 0x05, 0xc1, 0xe8, 0xb2, 0x52, 0x12, 0xb0, 0x03, 0x7e, 0x88, - 0xcc, 0x2e, 0x03, 0x15, 0x6d, 0x05, 0xe0, 0xf9, 0x67, 0x34, 0x5e, 0xb4, 0x5c, 0x92, 0x24, 0x9e, - 0x18, 0xf0, 0x9d, 0x1b, 0x66, 0xad, 0x9f, 0x98, 0x81, 0x75, 0x49, 0xab, 0x98, 0x33, 0x9b, 0x70, - 0x9b, 0x52, 0x0d, 0x57, 0x04, 0x2a, 0x7e, 0x6f, 0xcc, 0x41, 0x5e, 0xa0, 0x1a, 0x1f, 0xc3, 0x82, - 0xd6, 0x0c, 0x52, 0xf3, 0x5f, 0xb7, 0x87, 0xc6, 0xaf, 0x45, 0x99, 0x45, 0x1d, 0x64, 0xa1, 0x52, - 0x6e, 0x24, 0x7c, 0x40, 0x1d, 0x97, 0xee, 0x2a, 0x04, 0x12, 0x68, 0xaf, 0xed, 0xda, 0xf0, 0x1b, - 0xb0, 0xa8, 0x95, 0xbe, 0xed, 0xb8, 0xf6, 0xd0, 0xf9, 0x31, 0x6e, 0xf8, 0x81, 0x73, 0xea, 0x4e, - 0x95, 0x4f, 0xa0, 0x2f, 0x55, 0xfe, 0x3f, 0xcc, 0xc2, 0x92, 0xac, 0x00, 0x1d, 0x03, 0x1d, 0x21, - 0xc5, 0xed, 0x05, 0xa7, 0xec, 0xbb, 0x50, 0x13, 0x63, 0x63, 0xf9, 0xfc, 0xd4, 0x09, 0x42, 0xae, - 0x2c, 0x63, 0x29, 0x8c, 0x4b, 0x6c, 0xe6, 0x02, 0xd5, 0x94, 0x98, 0xec, 0x63, 0xa8, 0x60, 0x56, - 0x3a, 0x46, 0x91, 0x13, 0xd1, 0x9c, 0xcd, 0x48, 0x03, 0xbd, 0x73, 0xc3, 0x84, 0x20, 0x1e, 0xf6, - 0x8f, 0xa1, 0x82, 0x73, 0x78, 0x8e, 0x03, 0x39, 0xc5, 0xaa, 0x66, 0x06, 0x5a, 0x64, 0x1e, 0xc7, - 0xc3, 0xde, 0x82, 0x1a, 0x31, 0x2b, 0x39, 0x4e, 0xd2, 0xe1, 0x68, 0x6d, 0x36, 0xbb, 0x1a, 0x49, - 0xd1, 0xf8, 0xb1, 0xf6, 0xbd, 0x51, 0x86, 0x62, 0xe8, 0x3b, 0xa7, 0xa7, 0xdc, 0x37, 0x56, 0xa2, - 0xa1, 0x11, 0x5c, 0x98, 0x77, 0x43, 0x3e, 0x16, 0xb2, 0xb9, 0xf1, 0xef, 0x32, 0x50, 0x91, 0x7c, - 0xf5, 0x67, 0x36, 0xc7, 0xad, 0x69, 0x9e, 0xb5, 0x74, 0x62, 0x13, 0x3b, 0xd2, 0xbe, 0x0b, 0xf3, - 0x23, 0x21, 0xa7, 0x0b, 0x3d, 0x32, 0x61, 0x8b, 0xab, 0x2b, 0xb0, 0x14, 0x93, 0xd7, 0x61, 0x11, - 0xa5, 0xe6, 0xc0, 0x0a, 0x9d, 0xa1, 0xa5, 0x12, 0xa5, 0x17, 0xeb, 0x02, 0x25, 0xf5, 0x9c, 0xe1, - 0x9e, 0x4c, 0x10, 0xc2, 0x63, 0x10, 0xda, 0xa7, 0x5c, 0xae, 0x6d, 0xfa, 0x30, 0x9a, 0xb0, 0x32, - 0xa5, 0x42, 0x2a, 0xf5, 0xf7, 0x7f, 0x2d, 0xc0, 0xea, 0x4c, 0x92, 0x54, 0x83, 0x23, 0x1b, 0xd4, - 0xd0, 0x19, 0x1d, 0x7b, 0xd1, 0x09, 0x6d, 0x46, 0xb3, 0x41, 0xed, 0x8a, 0x14, 0x75, 0x42, 0xcb, - 0x61, 0x59, 0x11, 0x24, 0x1e, 0xb1, 0x46, 0x5a, 0x66, 0x16, 0x75, 0xa0, 0x0f, 0x92, 0x9b, 0xd8, - 0x74, 0x75, 0x0a, 0xae, 0x8b, 0x46, 0x8b, 0xe3, 0x19, 0x58, 0xc0, 0x7e, 0x13, 0x9a, 0x11, 0xdd, - 0x4b, 0xb1, 0x5d, 0x53, 0x99, 0x45, 0x4d, 0x5f, 0x7f, 0x45, 0x4d, 0x89, 0xb3, 0x3b, 0x94, 0x9d, - 0x56, 0xd4, 0x92, 0xa1, 0x02, 0xa3, 0xba, 0xce, 0xe1, 0x0d, 0x55, 0x17, 0x8a, 0xe1, 0xb3, 0x35, - 0xe6, 0x5f, 0xab, 0x6f, 0x78, 0x2e, 0x99, 0xa8, 0xd6, 0xbc, 0x25, 0x0b, 0x8e, 0x92, 0xf4, 0x7a, - 0xcf, 0x60, 0xe5, 0xc2, 0x76, 0x42, 0xd5, 0x47, 0x4d, 0x63, 0x2f, 0x60, 0x7d, 0x8f, 0x5f, 0x51, - 0xdf, 0x67, 0x94, 0x39, 0xa1, 0x98, 0x2c, 0x5d, 0xcc, 0x02, 0x83, 0xb5, 0xbf, 0x9b, 0x83, 0x7a, - 0xb2, 0x14, 0xc1, 0x58, 0xe4, 0x66, 0xa3, 0xe4, 0x4d, 0x29, 0x04, 0x4b, 0xeb, 0xc1, 0x3e, 0xc9, - 0x99, 0xb3, 0x76, 0x8d, 0x6c, 0x8a, 0x5d, 0x43, 0x37, 0x27, 0xe4, 0x5e, 0x65, 0xbf, 0xcd, 0xbf, - 0x96, 0xfd, 0xb6, 0x90, 0x66, 0xbf, 0xbd, 0xde, 0xe8, 0x37, 0xf7, 0x33, 0x19, 0xfd, 0x8a, 0x2f, - 0x31, 0xfa, 0x25, 0x4c, 0x95, 0xa5, 0x69, 0x53, 0x65, 0x8a, 0x89, 0xaf, 0xfc, 0x25, 0x4c, 0x7c, - 0x6b, 0x7f, 0x95, 0x01, 0x36, 0xbb, 0x16, 0xd8, 0x53, 0x32, 0x10, 0xb9, 0x7c, 0x28, 0xf9, 0xf4, - 0x37, 0x5e, 0x6f, 0x3d, 0xa9, 0xe9, 0x57, 0xb9, 0xd9, 0x43, 0x58, 0xd4, 0x3d, 0xeb, 0x75, 0x1d, - 0xbd, 0x66, 0x32, 0x3d, 0x29, 0x3e, 0xc9, 0xd1, 0x4c, 0xe3, 0xf9, 0x57, 0x9a, 0xc6, 0x0b, 0xaf, - 0x34, 0x8d, 0xcf, 0x25, 0x4d, 0xe3, 0x6b, 0xff, 0x29, 0x03, 0x8b, 0x29, 0x24, 0xfb, 0xd5, 0xf5, - 0x59, 0x50, 0x5a, 0x82, 0x89, 0x65, 0x25, 0xa5, 0xe9, 0xfc, 0x6b, 0x17, 0x2a, 0xf1, 0x54, 0xa8, - 0xc8, 0x93, 0x07, 0xaf, 0xe2, 0x25, 0x71, 0x0e, 0x53, 0xcf, 0xbe, 0xf6, 0x07, 0x59, 0xa8, 0x68, - 0x89, 0x62, 0x14, 0x89, 0x40, 0x35, 0x8f, 0x24, 0x92, 0x03, 0xf1, 0x84, 0xe1, 0x2e, 0x48, 0x13, - 0x06, 0xa5, 0xd3, 0x52, 0x92, 0x42, 0x1f, 0x22, 0xac, 0xc3, 0xa2, 0x32, 0xde, 0xf1, 0xd8, 0xf1, - 0x50, 0xee, 0x2c, 0x0b, 0xd2, 0x84, 0xc7, 0x23, 0x3f, 0x46, 0xf6, 0x50, 0x29, 0x7f, 0xf1, 0xdc, - 0x21, 0x61, 0x93, 0x7d, 0x60, 0x81, 0x96, 0x83, 0x9a, 0x44, 0x41, 0xd5, 0x1f, 0xc0, 0xb2, 0x5a, - 0x0c, 0xc9, 0x1c, 0x64, 0x32, 0x60, 0x72, 0x29, 0xe8, 0x59, 0xbe, 0x0f, 0x77, 0xa6, 0xda, 0x34, - 0x95, 0x95, 0x3c, 0x64, 0x6f, 0x26, 0x5a, 0xa7, 0x97, 0xb0, 0xf6, 0x13, 0xa8, 0x25, 0xd8, 0xe2, - 0x57, 0x37, 0xe5, 0xd3, 0xa7, 0x3a, 0x34, 0xa2, 0xfa, 0xa9, 0xce, 0xda, 0xff, 0xce, 0x01, 0x9b, - 0xe5, 0xcc, 0xbf, 0xc8, 0x26, 0xcc, 0x12, 0x66, 0x2e, 0x85, 0x30, 0xff, 0x9f, 0x49, 0x0b, 0xef, - 0xc3, 0x82, 0x8c, 0xc0, 0xd2, 0x2c, 0xb0, 0xb4, 0x38, 0x1b, 0x51, 0x82, 0x6a, 0xc5, 0xb7, 0xa7, - 0x3d, 0x41, 0x4a, 0x89, 0xa0, 0x13, 0x4d, 0x5c, 0x9a, 0x72, 0x08, 0x39, 0x82, 0x39, 0xdb, 0xed, - 0x9f, 0x79, 0xbe, 0xe4, 0x83, 0xbf, 0xf4, 0xa5, 0x37, 0xcb, 0xf5, 0x16, 0xe6, 0x47, 0x19, 0xcd, - 0x94, 0x85, 0x19, 0x1f, 0x40, 0x45, 0x03, 0xa3, 0x55, 0xb2, 0xb3, 0xb7, 0x71, 0xd0, 0xb8, 0xc1, - 0x6a, 0x50, 0x36, 0xdb, 0x9b, 0x07, 0x9f, 0xb6, 0xcd, 0xf6, 0x56, 0x23, 0xc3, 0x4a, 0x90, 0xdf, - 0x3d, 0xe8, 0xf6, 0x1a, 0x59, 0x63, 0x0d, 0x9a, 0xb2, 0xc4, 0x59, 0x0b, 0xc5, 0xef, 0xe6, 0xa3, - 0xc3, 0x41, 0x4c, 0x94, 0x0a, 0xf9, 0x37, 0xa1, 0xaa, 0x0b, 0x33, 0x92, 0x22, 0xa6, 0x9c, 0x00, - 0x84, 0x2a, 0xee, 0x69, 0xbc, 0x7a, 0x13, 0xc8, 0xb4, 0x3b, 0x88, 0xb2, 0x65, 0x13, 0x52, 0x6a, - 0x8a, 0x2d, 0x10, 0x55, 0x9d, 0x04, 0x19, 0xfe, 0x7f, 0x50, 0x4f, 0x1e, 0xd7, 0x4b, 0x8e, 0x94, - 0xa6, 0x5e, 0x8a, 0xdc, 0x89, 0xf3, 0x7b, 0xf6, 0x7d, 0x68, 0x4c, 0x1f, 0xf7, 0x4b, 0x51, 0xf9, - 0x9a, 0xfc, 0xf3, 0x4e, 0xd2, 0x02, 0xc0, 0x76, 0x60, 0x29, 0x4d, 0x9c, 0x43, 0xfa, 0xb8, 0xfe, - 0x48, 0x82, 0xcd, 0x8a, 0x6c, 0xec, 0x3b, 0xd2, 0xaa, 0x53, 0x48, 0xb3, 0x8d, 0x6b, 0x83, 0xbd, - 0x4e, 0xff, 0x34, 0xfb, 0xce, 0x39, 0x40, 0x0c, 0x63, 0x0d, 0xa8, 0x1e, 0x1c, 0xb6, 0xf7, 0xad, - 0xcd, 0x9d, 0xd6, 0xfe, 0x7e, 0x7b, 0xb7, 0x71, 0x83, 0x31, 0xa8, 0xa3, 0x51, 0x7b, 0x2b, 0x82, - 0x65, 0x04, 0x4c, 0x5a, 0xd7, 0x14, 0x2c, 0xcb, 0x96, 0xa0, 0xd1, 0xd9, 0x9f, 0x82, 0xe6, 0x58, - 0x13, 0x96, 0x0e, 0xdb, 0x64, 0x07, 0x4f, 0x94, 0x9b, 0x17, 0x2a, 0x82, 0xec, 0xae, 0x50, 0x11, - 0x28, 0x92, 0x50, 0xae, 0x03, 0x25, 0x39, 0xff, 0x5e, 0x06, 0x96, 0xa7, 0x12, 0xe2, 0xf8, 0x10, - 0x92, 0x9b, 0x93, 0x12, 0x73, 0x15, 0x81, 0x6a, 0x35, 0xbd, 0x0f, 0x0b, 0xd1, 0x31, 0xd3, 0xd4, - 0xae, 0xd4, 0x88, 0x12, 0x14, 0xf2, 0x43, 0x58, 0xd4, 0x4e, 0xab, 0xa6, 0x78, 0x05, 0xd3, 0x92, - 0x64, 0x06, 0x63, 0x35, 0xf2, 0xc3, 0x9f, 0x6a, 0xf5, 0x80, 0xc2, 0x13, 0xf5, 0x84, 0xd8, 0xe8, - 0x95, 0x6c, 0xaf, 0xfa, 0x64, 0x8f, 0xa6, 0x08, 0x21, 0xd9, 0x5a, 0x7d, 0xc2, 0x55, 0xf5, 0x7f, - 0x38, 0x07, 0xec, 0x93, 0x09, 0xf7, 0xaf, 0x30, 0xfe, 0x23, 0x78, 0x95, 0x43, 0xa4, 0x3a, 0x57, - 0xc9, 0xbe, 0x56, 0x8c, 0x57, 0x5a, 0x8c, 0x55, 0xfe, 0xd5, 0x31, 0x56, 0x85, 0x57, 0xc5, 0x58, - 0xbd, 0x05, 0x35, 0xe7, 0xd4, 0xf5, 0x04, 0x2b, 0x14, 0x72, 0x6f, 0xd0, 0x9c, 0xbb, 0x97, 0xbb, - 0x5f, 0x35, 0xab, 0x12, 0x28, 0xa4, 0xde, 0x80, 0x7d, 0x1c, 0x23, 0xf1, 0xc1, 0x29, 0xc6, 0x03, - 0xea, 0x4c, 0xb0, 0x3d, 0x38, 0xe5, 0xf2, 0x18, 0x09, 0xf5, 0x0a, 0x95, 0x59, 0xc0, 0x03, 0xf6, - 0x36, 0xd4, 0x03, 0x6f, 0x22, 0xd4, 0x08, 0x35, 0x0c, 0x64, 0x16, 0xab, 0x12, 0xf4, 0x50, 0xd9, - 0x40, 0x17, 0x27, 0x01, 0xb7, 0x46, 0x4e, 0x10, 0x08, 0xf1, 0xac, 0xef, 0xb9, 0xa1, 0xef, 0x0d, - 0xa5, 0xa5, 0x6b, 0x61, 0x12, 0xf0, 0x3d, 0x4a, 0xd9, 0xa4, 0x04, 0xf6, 0xad, 0xb8, 0x49, 0x63, - 0xdb, 0xf1, 0x83, 0x26, 0x60, 0x93, 0x54, 0x4f, 0x51, 0x5a, 0xb7, 0x1d, 0x3f, 0x6a, 0x8b, 0xf8, - 0x08, 0xa6, 0x62, 0xbf, 0x2a, 0xd3, 0xb1, 0x5f, 0x3f, 0x4a, 0x8f, 0xfd, 0xaa, 0x61, 0xd1, 0x8f, - 0x64, 0xd1, 0xb3, 0x53, 0xfc, 0xa5, 0x42, 0xc0, 0x66, 0x43, 0xda, 0xea, 0x5f, 0x26, 0xa4, 0x6d, - 0x3e, 0x2d, 0xa4, 0xed, 0x03, 0xa8, 0x60, 0xb0, 0x91, 0x75, 0xe6, 0x08, 0x19, 0x8e, 0x2c, 0x77, - 0x0d, 0x3d, 0x1a, 0x69, 0xc7, 0x71, 0x43, 0x13, 0x7c, 0xf5, 0x33, 0x98, 0x8d, 0x2e, 0x5b, 0xf8, - 0x05, 0x46, 0x97, 0xc9, 0xa0, 0xa8, 0x75, 0x28, 0xa9, 0x79, 0x62, 0x0c, 0xf2, 0x27, 0xbe, 0x37, - 0x52, 0x16, 0x0d, 0xf1, 0x9b, 0xd5, 0x21, 0x1b, 0x7a, 0x32, 0x73, 0x36, 0xf4, 0x8c, 0x5f, 0x87, - 0x8a, 0x46, 0x6a, 0xec, 0x4d, 0x3a, 0x85, 0x14, 0x9a, 0x98, 0x94, 0x2d, 0x69, 0x14, 0xcb, 0x12, - 0xda, 0x19, 0x08, 0x7e, 0x33, 0x70, 0x7c, 0x8e, 0x71, 0xa0, 0x96, 0xcf, 0xcf, 0xb9, 0x1f, 0x28, - 0x0b, 0x53, 0x23, 0x4a, 0x30, 0x09, 0x6e, 0xfc, 0x06, 0x2c, 0x26, 0xe6, 0x56, 0xb2, 0x88, 0xb7, - 0x61, 0x0e, 0xc7, 0x4d, 0x79, 0x00, 0x24, 0xa3, 0xbc, 0x64, 0x1a, 0x06, 0xf8, 0x93, 0x71, 0xcc, - 0x1a, 0xfb, 0xde, 0x31, 0x56, 0x92, 0x31, 0x2b, 0x12, 0x76, 0xe8, 0x7b, 0xc7, 0xc6, 0x9f, 0xe7, - 0x20, 0xb7, 0xe3, 0x8d, 0x75, 0xa7, 0xb7, 0xcc, 0x8c, 0xd3, 0x9b, 0x54, 0x2f, 0xad, 0x48, 0x7d, - 0x94, 0x32, 0x3b, 0x9a, 0x85, 0x94, 0x0a, 0x79, 0x1f, 0xea, 0x82, 0x4f, 0x84, 0x9e, 0xd0, 0xcf, - 0x2f, 0x6c, 0x9f, 0x04, 0xe2, 0x1c, 0x2d, 0x3e, 0x7b, 0x14, 0xf6, 0xbc, 0x6d, 0x82, 0xb3, 0x25, - 0xc8, 0x45, 0xea, 0x0b, 0x26, 0x8b, 0x4f, 0xb6, 0x02, 0x73, 0xe8, 0xfd, 0x7c, 0x25, 0x4d, 0xdc, - 0xf2, 0x8b, 0x7d, 0x03, 0x16, 0x93, 0xe5, 0x12, 0x2b, 0x92, 0xb2, 0x91, 0x5e, 0x30, 0xf2, 0xa4, - 0x9b, 0x20, 0xf8, 0x08, 0xe1, 0x48, 0x4f, 0x99, 0x13, 0xce, 0x31, 0x49, 0x63, 0x7a, 0xa5, 0x04, - 0xd3, 0xbb, 0x0b, 0x95, 0x70, 0x78, 0x6e, 0x8d, 0xed, 0xab, 0xa1, 0x67, 0x0f, 0xe4, 0xfa, 0x86, - 0x70, 0x78, 0x7e, 0x48, 0x10, 0xf6, 0x10, 0x60, 0x34, 0x1e, 0xcb, 0xb5, 0x87, 0xa6, 0x8e, 0x98, - 0x94, 0xf7, 0x0e, 0x0f, 0x89, 0xe4, 0xcc, 0xf2, 0x68, 0x3c, 0xa6, 0x9f, 0x6c, 0x0b, 0xea, 0xa9, - 0xb1, 0x9a, 0x77, 0x94, 0xb3, 0xae, 0x37, 0x5e, 0x4f, 0x59, 0x9c, 0xb5, 0xbe, 0x0e, 0x5b, 0xfb, - 0x3e, 0xb0, 0x9f, 0x33, 0x62, 0xb2, 0x07, 0xe5, 0xa8, 0x7d, 0x7a, 0xc0, 0x21, 0xba, 0xdf, 0x57, - 0x12, 0x01, 0x87, 0xad, 0xc1, 0xc0, 0x17, 0x7c, 0x91, 0x36, 0xcc, 0x88, 0xe5, 0x83, 0xb6, 0x63, - 0xb6, 0x88, 0xef, 0x1b, 0xff, 0x35, 0x03, 0x05, 0x8a, 0x7e, 0x7c, 0x07, 0xe6, 0x09, 0x3f, 0x72, - 0x20, 0x94, 0x86, 0x71, 0xda, 0x77, 0x7b, 0xd2, 0x77, 0x50, 0x2c, 0x0b, 0x2d, 0x72, 0x3b, 0x1b, - 0xcd, 0xbc, 0x16, 0xbd, 0x7d, 0x17, 0xca, 0x51, 0xd5, 0x1a, 0xe9, 0x94, 0x54, 0xcd, 0xec, 0x0d, - 0xc8, 0x9f, 0x79, 0x63, 0x75, 0xce, 0x03, 0xf1, 0x48, 0x9a, 0x08, 0x8f, 0xdb, 0x22, 0xea, 0xa0, - 0xc6, 0xcb, 0xf3, 0x89, 0xa8, 0x12, 0x24, 0x83, 0xd9, 0x3e, 0xce, 0xa5, 0xf4, 0xf1, 0x08, 0xe6, - 0x05, 0x1f, 0xd0, 0x1c, 0x54, 0xae, 0xdf, 0x34, 0xdf, 0x13, 0x12, 0x5e, 0x7f, 0x38, 0x19, 0x70, - 0xfd, 0xa4, 0x0d, 0xbd, 0xd9, 0x24, 0x5c, 0x49, 0xd6, 0xc6, 0x1f, 0x66, 0x88, 0xbf, 0x88, 0x72, - 0xd9, 0x7d, 0xc8, 0x8b, 0xfd, 0x6d, 0xea, 0xdc, 0x3d, 0x8a, 0x83, 0x10, 0x78, 0x26, 0x62, 0xe0, - 0x75, 0x07, 0x93, 0x51, 0xb2, 0xf4, 0x9a, 0x59, 0x71, 0x27, 0xa3, 0xe8, 0xa0, 0xea, 0x6b, 0xaa, - 0x5b, 0x53, 0x87, 0x3c, 0xd4, 0xfb, 0x68, 0x99, 0xae, 0x6b, 0x6e, 0x71, 0xf9, 0xc4, 0x8e, 0xa9, - 0xa4, 0xc0, 0xc1, 0x29, 0xd7, 0xdc, 0xe1, 0xfe, 0x38, 0x0b, 0xb5, 0x44, 0x8b, 0xd0, 0x2f, 0x50, - 0x6c, 0x00, 0x64, 0x46, 0x92, 0xf3, 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9c, 0xb2, 0x89, 0x71, - 0x8a, 0x5c, 0x71, 0x72, 0xba, 0x2b, 0xce, 0x23, 0x28, 0xc7, 0x11, 0xfb, 0xc9, 0x26, 0x89, 0xfa, - 0x54, 0x34, 0x48, 0x8c, 0x14, 0x3b, 0xef, 0x14, 0x74, 0xe7, 0x9d, 0xef, 0x69, 0xbe, 0x1e, 0x73, - 0x58, 0x8c, 0x91, 0x36, 0xa2, 0xbf, 0x10, 0x4f, 0x0f, 0xe3, 0x63, 0xa8, 0x68, 0x8d, 0xd7, 0x7d, - 0x3a, 0x32, 0x09, 0x9f, 0x8e, 0x28, 0x6e, 0x2b, 0x1b, 0xc7, 0x6d, 0x19, 0xbf, 0x95, 0x85, 0x9a, - 0x58, 0x5f, 0x8e, 0x7b, 0x7a, 0xe8, 0x0d, 0x9d, 0x3e, 0x9a, 0x95, 0xa2, 0x15, 0x26, 0x05, 0x2d, - 0xb5, 0xce, 0xe4, 0x12, 0x23, 0x39, 0x4b, 0x0f, 0x4f, 0x25, 0x26, 0x1d, 0x85, 0xa7, 0x1a, 0x50, - 0x13, 0x8c, 0x11, 0x0d, 0x44, 0xf1, 0x7d, 0x02, 0x66, 0xe5, 0x84, 0xf3, 0x0d, 0x3b, 0x20, 0x0e, - 0xf9, 0x0d, 0x58, 0x14, 0x38, 0x18, 0x99, 0x37, 0x72, 0x86, 0x43, 0x87, 0x30, 0xe9, 0xa0, 0xa9, - 0x71, 0xc2, 0xb9, 0x69, 0x87, 0x7c, 0x4f, 0x24, 0xc8, 0xeb, 0x07, 0x4a, 0x03, 0x27, 0xb0, 0x8f, - 0x63, 0xef, 0xcd, 0xe8, 0x1b, 0xed, 0xc8, 0xf6, 0xa5, 0x66, 0x47, 0xa6, 0x03, 0x88, 0xca, 0xc8, - 0xbe, 0x8c, 0xec, 0xc8, 0x53, 0x94, 0x54, 0x9c, 0xa6, 0x24, 0xe3, 0xdf, 0x66, 0xa1, 0xa2, 0x91, - 0xe5, 0xeb, 0xec, 0xae, 0x77, 0x66, 0xcc, 0x80, 0x65, 0xdd, 0xe2, 0xf7, 0x56, 0xb2, 0x4a, 0xf4, - 0x74, 0xa1, 0x8b, 0x0e, 0x34, 0x02, 0xbe, 0x05, 0x65, 0xb1, 0xea, 0x3e, 0xc0, 0x03, 0x57, 0x79, - 0x4d, 0x07, 0x02, 0x0e, 0x27, 0xc7, 0x2a, 0xf1, 0x31, 0x26, 0x16, 0xe2, 0xc4, 0xc7, 0x22, 0xf1, - 0x65, 0x2e, 0xdb, 0xdf, 0x86, 0xaa, 0x2c, 0x15, 0xe7, 0x14, 0xbb, 0x1b, 0xaf, 0xfa, 0xc4, 0x7c, - 0x9b, 0x15, 0xaa, 0x8e, 0x26, 0x5f, 0x66, 0x7c, 0xac, 0x32, 0x96, 0x5e, 0x95, 0xf1, 0x31, 0x7d, - 0x18, 0xdb, 0x91, 0x17, 0x3c, 0x7a, 0x59, 0x29, 0x3e, 0xf6, 0x10, 0x16, 0x15, 0xbb, 0x9a, 0xb8, - 0xb6, 0xeb, 0x7a, 0x13, 0xb7, 0xcf, 0x55, 0x40, 0x17, 0x93, 0x49, 0x47, 0x71, 0x8a, 0x31, 0x88, - 0x22, 0x7e, 0xc9, 0x5b, 0xeb, 0x01, 0x14, 0x48, 0x2e, 0x27, 0xe1, 0x23, 0x9d, 0x71, 0x11, 0x0a, - 0xbb, 0x0f, 0x05, 0x12, 0xcf, 0xb3, 0xd7, 0x32, 0x1b, 0x42, 0x30, 0x5a, 0xc0, 0x44, 0xc6, 0x3d, - 0x1e, 0xfa, 0x4e, 0x3f, 0x88, 0x63, 0xc5, 0x0a, 0x42, 0xff, 0xa4, 0xba, 0xe2, 0x93, 0xdb, 0x18, - 0x13, 0x75, 0x54, 0xc2, 0x11, 0x1b, 0xd3, 0x62, 0xa2, 0x0c, 0x29, 0x2e, 0x0d, 0x61, 0xe5, 0x98, - 0x87, 0x17, 0x9c, 0xbb, 0xae, 0x10, 0x86, 0xfa, 0xdc, 0x0d, 0x7d, 0x7b, 0x28, 0x26, 0x89, 0x7a, - 0xf0, 0x64, 0xa6, 0xd4, 0xf8, 0x0c, 0x64, 0x23, 0xce, 0xb8, 0x19, 0xe5, 0x23, 0xde, 0xb1, 0x7c, - 0x9c, 0x96, 0xb6, 0xf6, 0x6b, 0xb0, 0x76, 0x7d, 0xa6, 0x94, 0x88, 0xd0, 0xfb, 0x49, 0xae, 0x12, - 0x59, 0xfd, 0x86, 0x9e, 0x1d, 0x52, 0x6b, 0x74, 0xce, 0xb2, 0x0f, 0x15, 0x2d, 0x25, 0xde, 0xfb, - 0x33, 0x28, 0xdc, 0xd1, 0x87, 0xd8, 0x91, 0x5c, 0xcf, 0x1f, 0xa1, 0x95, 0x6d, 0x60, 0xc5, 0xa5, - 0x67, 0xcc, 0xf9, 0x18, 0x8e, 0x21, 0xf0, 0xc6, 0x3a, 0xcc, 0xa3, 0x64, 0xaf, 0x6d, 0x74, 0x2f, - 0x13, 0x06, 0x8d, 0x25, 0x60, 0xfb, 0xc4, 0xbb, 0x74, 0xe7, 0xcd, 0xff, 0x9c, 0x83, 0x8a, 0x06, - 0x16, 0xbb, 0x11, 0xba, 0xfb, 0x59, 0x03, 0xc7, 0x1e, 0x71, 0x65, 0xd2, 0xac, 0x99, 0x35, 0x84, - 0x6e, 0x49, 0xa0, 0xd8, 0x8b, 0xed, 0xf3, 0x53, 0xcb, 0x9b, 0x84, 0xd6, 0x80, 0x9f, 0xfa, 0x5c, - 0xb5, 0xb2, 0x6a, 0x9f, 0x9f, 0x1e, 0x4c, 0xc2, 0x2d, 0x84, 0x09, 0x2c, 0xc1, 0x4b, 0x34, 0x2c, - 0xe9, 0xa1, 0x36, 0xb2, 0x2f, 0x63, 0x2c, 0xe9, 0x26, 0x49, 0x94, 0x99, 0x8f, 0xdc, 0x24, 0x49, - 0x5b, 0x9c, 0xde, 0x40, 0x0b, 0xb3, 0x1b, 0xe8, 0xb7, 0x60, 0x85, 0x36, 0x50, 0xc9, 0x9a, 0xad, - 0xa9, 0x95, 0xbc, 0x84, 0xa9, 0xb2, 0x93, 0x9a, 0xd8, 0xdb, 0x10, 0x3d, 0x50, 0x6c, 0x29, 0x70, - 0x7e, 0x4c, 0x8c, 0x2c, 0x63, 0x8a, 0x9e, 0xc9, 0xc2, 0xbb, 0xce, 0x8f, 0xb9, 0xc0, 0x44, 0x5f, - 0x18, 0x1d, 0x53, 0x06, 0x64, 0x8c, 0x1c, 0x77, 0x1a, 0xd3, 0xbe, 0x4c, 0x62, 0x96, 0x25, 0xa6, - 0x7d, 0xa9, 0x63, 0x3e, 0x81, 0xd5, 0x11, 0x1f, 0x38, 0x76, 0xb2, 0x58, 0x2b, 0x16, 0xdc, 0x96, - 0x28, 0x59, 0xcb, 0xd3, 0x25, 0xc5, 0x5d, 0x8c, 0xc6, 0x8f, 0xbd, 0xd1, 0xb1, 0x43, 0x32, 0x0b, - 0x79, 0xe7, 0xe4, 0xcd, 0xba, 0x3b, 0x19, 0xfd, 0x10, 0xc1, 0x22, 0x4b, 0x60, 0xd4, 0xa0, 0xd2, - 0x0d, 0xbd, 0xb1, 0x9a, 0xe6, 0x3a, 0x54, 0xe9, 0x53, 0x46, 0x49, 0xde, 0x82, 0x9b, 0xc8, 0x12, - 0x7a, 0xde, 0xd8, 0x1b, 0x7a, 0xa7, 0x57, 0x89, 0x73, 0xbc, 0x7f, 0x9f, 0x81, 0xc5, 0x44, 0xaa, - 0x64, 0xaf, 0xdf, 0x22, 0x7e, 0x16, 0x85, 0xba, 0xd1, 0x1a, 0x5c, 0xd0, 0xd6, 0x20, 0x21, 0x12, - 0x33, 0x53, 0xe1, 0x6f, 0xad, 0xf8, 0x8a, 0x06, 0x95, 0x91, 0x58, 0x4a, 0x73, 0x96, 0xa5, 0xc8, - 0xfc, 0xea, 0xf2, 0x06, 0x55, 0xc4, 0x2f, 0xc9, 0xa0, 0x99, 0x81, 0xec, 0x72, 0x2e, 0x19, 0x16, - 0xa0, 0x9f, 0xf9, 0xa9, 0x16, 0xc4, 0x07, 0x81, 0x81, 0xf1, 0xcf, 0x32, 0x00, 0x71, 0xeb, 0x30, - 0x30, 0x21, 0x92, 0x5b, 0xe8, 0xf6, 0x33, 0x4d, 0x46, 0x79, 0x13, 0xaa, 0x91, 0x7f, 0x72, 0x2c, - 0x09, 0x55, 0x14, 0x4c, 0x88, 0x43, 0xef, 0xc2, 0xfc, 0xe9, 0xd0, 0x3b, 0x46, 0x89, 0x55, 0xca, - 0x2d, 0xe4, 0x9d, 0x56, 0x27, 0xb0, 0x92, 0x46, 0x62, 0xb9, 0x29, 0x9f, 0xea, 0xc2, 0xac, 0x4b, - 0x41, 0xc6, 0xef, 0x64, 0x23, 0x47, 0xcd, 0x78, 0x24, 0x5e, 0xae, 0xde, 0xfd, 0x2c, 0x9e, 0x33, - 0x2f, 0x33, 0x26, 0x7e, 0x0c, 0x75, 0x9f, 0x36, 0x25, 0xb5, 0x63, 0xe5, 0x5f, 0xb2, 0x63, 0xd5, - 0xfc, 0x84, 0xa4, 0xf3, 0x1e, 0x34, 0xec, 0xc1, 0x39, 0xf7, 0x43, 0x07, 0x4f, 0xeb, 0x51, 0x3e, - 0x96, 0xae, 0x91, 0x1a, 0x1c, 0x05, 0xd1, 0x77, 0x61, 0x5e, 0x46, 0xee, 0x46, 0x98, 0xf2, 0x2e, - 0xa0, 0x18, 0x2c, 0x10, 0x8d, 0x7f, 0xa1, 0x3c, 0x43, 0x93, 0xb3, 0xfb, 0xf2, 0x51, 0xd1, 0x7b, - 0x98, 0x9d, 0x35, 0x97, 0x4a, 0x42, 0x92, 0x46, 0x00, 0xc9, 0x8f, 0x08, 0x28, 0x4d, 0x00, 0xc9, - 0x61, 0xcd, 0xbf, 0xce, 0xb0, 0x1a, 0xff, 0x31, 0x03, 0xc5, 0x1d, 0x6f, 0xbc, 0xe3, 0x90, 0x6b, - 0x3e, 0x2e, 0x93, 0xc8, 0x46, 0x35, 0x27, 0x3e, 0xd1, 0xcd, 0xe7, 0x25, 0x01, 0x6a, 0xa9, 0x62, - 0x5e, 0x2d, 0x29, 0xe6, 0x7d, 0x0f, 0x6e, 0xa1, 0x09, 0xd0, 0xf7, 0xc6, 0x9e, 0x2f, 0x96, 0xaa, - 0x3d, 0x24, 0x71, 0xcf, 0x73, 0xc3, 0x33, 0xc5, 0x3b, 0x6f, 0x9e, 0x70, 0x7e, 0xa8, 0x61, 0xec, - 0x45, 0x08, 0x18, 0x02, 0x3a, 0x0c, 0xcf, 0x2d, 0xd2, 0xd0, 0xa5, 0x3c, 0x4a, 0x1c, 0x75, 0x5e, - 0x24, 0xb4, 0x11, 0x8e, 0x12, 0xa9, 0xf1, 0x1d, 0x28, 0x47, 0x87, 0x3d, 0xec, 0x7d, 0x28, 0x9f, - 0x79, 0x63, 0x79, 0x22, 0x94, 0x49, 0x04, 0xf1, 0xc9, 0x5e, 0x9b, 0xa5, 0x33, 0xfa, 0x11, 0x18, - 0x7f, 0x5e, 0x84, 0x62, 0xc7, 0x3d, 0xf7, 0x9c, 0x3e, 0xfa, 0x96, 0x8e, 0xf8, 0xc8, 0x53, 0xd7, - 0x07, 0x88, 0xdf, 0xe8, 0x89, 0x15, 0xdf, 0xe8, 0x93, 0x93, 0x9e, 0x58, 0xd1, 0x5d, 0x3e, 0xcb, - 0x30, 0xe7, 0xeb, 0x57, 0xf2, 0x14, 0x7c, 0xf4, 0x76, 0x8f, 0xf6, 0xcb, 0x82, 0x76, 0xfd, 0x82, - 0x28, 0x8b, 0xae, 0x8a, 0xc1, 0x21, 0xa3, 0x70, 0xce, 0x32, 0x42, 0x70, 0xc0, 0x6e, 0x43, 0x51, - 0xc6, 0xcc, 0x51, 0x04, 0x12, 0xb9, 0xa7, 0x4b, 0x10, 0x52, 0x83, 0xcf, 0xc9, 0x84, 0x1b, 0x09, - 0xb2, 0x39, 0xb3, 0xaa, 0x80, 0x5b, 0x82, 0xd6, 0xee, 0x42, 0x85, 0xf0, 0x09, 0xa5, 0x24, 0x5d, - 0x32, 0x11, 0x84, 0x08, 0x29, 0x37, 0x5b, 0x95, 0x53, 0x6f, 0xb6, 0x42, 0xe7, 0xe1, 0x88, 0xcb, - 0x52, 0x17, 0x81, 0xee, 0x33, 0xd2, 0xe0, 0xea, 0x5a, 0x37, 0x79, 0xa6, 0x42, 0xd1, 0xcd, 0xea, - 0x4c, 0xe5, 0x2d, 0xa8, 0x9d, 0xd8, 0xc3, 0xe1, 0xb1, 0xdd, 0x7f, 0x41, 0x47, 0x01, 0x55, 0x3a, - 0xfd, 0x54, 0x40, 0x3c, 0x0b, 0xb8, 0x0b, 0x15, 0x6d, 0x96, 0xd1, 0xdf, 0x32, 0x6f, 0x42, 0x3c, - 0xbf, 0xd3, 0x27, 0x7c, 0xf5, 0xd7, 0x38, 0xe1, 0xd3, 0xfc, 0x4e, 0xe7, 0x93, 0x7e, 0xa7, 0xb7, - 0x90, 0x9b, 0x4a, 0x07, 0xc3, 0x06, 0x5d, 0x9e, 0x63, 0x0f, 0x06, 0xe8, 0x60, 0x48, 0x37, 0x55, - 0xe2, 0xe0, 0x51, 0xfa, 0x02, 0xe9, 0x12, 0x04, 0x23, 0x94, 0x3b, 0x74, 0x4c, 0x3d, 0xb6, 0x9d, - 0x01, 0x86, 0x18, 0xd0, 0xe9, 0x41, 0xd1, 0x1e, 0x85, 0x87, 0xb6, 0x33, 0x60, 0xf7, 0xa0, 0xaa, - 0x92, 0x71, 0x77, 0x5c, 0xa4, 0xf1, 0x97, 0xc9, 0x62, 0x4f, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe2, - 0x10, 0xe5, 0x8a, 0x44, 0x41, 0x3a, 0xf8, 0x00, 0x7d, 0x7a, 0x42, 0x8e, 0x81, 0xc8, 0xf5, 0xc7, - 0xb7, 0x64, 0x5f, 0x25, 0x95, 0xaa, 0xff, 0x64, 0x1c, 0x23, 0x4c, 0x21, 0xdc, 0x91, 0x8d, 0x6e, - 0x25, 0x21, 0xff, 0x4a, 0x54, 0xb4, 0xd1, 0x11, 0x02, 0xfb, 0x8e, 0xa6, 0xbf, 0x36, 0x11, 0xf9, - 0xf6, 0x54, 0xf9, 0xd7, 0x45, 0x58, 0xdd, 0x01, 0x70, 0x02, 0xb1, 0xcb, 0x04, 0xdc, 0x1d, 0x60, - 0x4c, 0x71, 0xc9, 0x2c, 0x3b, 0xc1, 0x33, 0x02, 0x7c, 0xb5, 0x8a, 0x6d, 0x0b, 0xaa, 0x7a, 0x37, - 0x59, 0x09, 0xf2, 0x07, 0x87, 0xed, 0xfd, 0xc6, 0x0d, 0x56, 0x81, 0x62, 0xb7, 0xdd, 0xeb, 0xed, - 0xa2, 0xa5, 0xaf, 0x0a, 0xa5, 0x28, 0xa0, 0x31, 0x2b, 0xbe, 0x5a, 0x9b, 0x9b, 0xed, 0xc3, 0x5e, - 0x7b, 0xab, 0x91, 0xfb, 0x41, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0xbf, 0xc8, 0x41, 0x45, 0x1b, 0x85, - 0x97, 0x33, 0xe3, 0x3b, 0x00, 0xa8, 0x49, 0xc6, 0xfe, 0xa7, 0x79, 0xb3, 0x2c, 0x20, 0x34, 0xf9, - 0xba, 0x8d, 0x22, 0x47, 0xb7, 0x32, 0x29, 0x1b, 0xc5, 0x5b, 0x50, 0xa3, 0x0b, 0x8e, 0x74, 0x7b, - 0x6d, 0xc1, 0xac, 0x12, 0x50, 0xb2, 0x6a, 0x8c, 0x88, 0x46, 0x24, 0x8c, 0x95, 0x93, 0xd7, 0x9d, - 0x10, 0x08, 0xa3, 0xe5, 0x30, 0xd4, 0x31, 0xf0, 0x86, 0xe7, 0x9c, 0x30, 0x48, 0x22, 0xac, 0x48, - 0x58, 0x4f, 0xc6, 0x76, 0x4b, 0x7e, 0xa8, 0x85, 0xe4, 0x16, 0xcc, 0x2a, 0x01, 0x65, 0x45, 0xdf, - 0x50, 0x04, 0x54, 0x42, 0x02, 0x5a, 0x9d, 0xa5, 0x86, 0x04, 0xf1, 0xec, 0xce, 0x1c, 0x23, 0x96, - 0x91, 0x30, 0xbe, 0x36, 0x9b, 0xef, 0xd5, 0xc7, 0x89, 0xec, 0x7d, 0x60, 0xa3, 0xf1, 0xd8, 0x4a, - 0x39, 0xe0, 0xcb, 0x9b, 0xf3, 0xa3, 0xf1, 0xb8, 0xa7, 0x9d, 0x7f, 0x7d, 0x05, 0x67, 0x8f, 0x9f, - 0x03, 0x6b, 0x89, 0x05, 0x8c, 0x4d, 0x8c, 0x54, 0xb1, 0x98, 0x2d, 0x67, 0x74, 0xb6, 0x9c, 0xc2, - 0xfd, 0xb2, 0xa9, 0xdc, 0xef, 0x65, 0x7c, 0xc2, 0xd8, 0x86, 0xca, 0xa1, 0x76, 0x7d, 0xda, 0x3d, - 0xb1, 0x43, 0xa8, 0x8b, 0xd3, 0x68, 0xef, 0xa0, 0x33, 0x45, 0x5f, 0xde, 0x97, 0xa6, 0xb5, 0x26, - 0xab, 0xb5, 0xc6, 0xf8, 0xa7, 0x19, 0xba, 0x9a, 0x26, 0x6a, 0x7c, 0x7c, 0x63, 0x9b, 0x32, 0xbf, - 0xc5, 0x91, 0xf3, 0x15, 0x65, 0x76, 0x93, 0x41, 0xef, 0xd8, 0x34, 0xcb, 0x3b, 0x39, 0x09, 0xb8, - 0xf2, 0xf1, 0xa8, 0x20, 0xec, 0x00, 0x41, 0x4a, 0xf8, 0x16, 0x12, 0xbe, 0x43, 0xe5, 0x07, 0xd2, - 0xb1, 0x43, 0x08, 0xdf, 0x7b, 0xf6, 0xa5, 0xac, 0x35, 0x10, 0x22, 0x88, 0xb4, 0x0f, 0xa8, 0xc8, - 0xd7, 0xe8, 0xdb, 0xf8, 0x47, 0x32, 0xb8, 0x7f, 0x7a, 0x7c, 0x1f, 0x40, 0x29, 0x2a, 0x35, 0xb9, - 0xc3, 0x2a, 0xcc, 0x28, 0x5d, 0xec, 0xe3, 0x78, 0x18, 0x92, 0x68, 0x31, 0x2d, 0x2e, 0xb4, 0xf1, - 0x74, 0xb4, 0x56, 0x7f, 0x1d, 0xd8, 0x89, 0xe3, 0x4f, 0x23, 0xd3, 0x62, 0x6b, 0x60, 0x8a, 0x86, - 0x6d, 0x1c, 0xc1, 0xa2, 0xe2, 0x12, 0x9a, 0x46, 0x90, 0x9c, 0xbc, 0xcc, 0x2b, 0x98, 0x7c, 0x76, - 0x86, 0xc9, 0x1b, 0x3f, 0xcd, 0x43, 0x51, 0x5d, 0x45, 0x98, 0x76, 0x7d, 0x5e, 0x39, 0x79, 0x7d, - 0x5e, 0x33, 0x71, 0xd5, 0x12, 0x4e, 0xbd, 0xdc, 0xef, 0xdf, 0x9d, 0xde, 0xb2, 0x35, 0x5b, 0x45, - 0x62, 0xdb, 0x5e, 0x81, 0xfc, 0xd8, 0x0e, 0xcf, 0xf0, 0x5c, 0x92, 0x88, 0x07, 0xbf, 0x95, 0x0d, - 0xa3, 0x90, 0xb4, 0x61, 0xa4, 0x5d, 0x35, 0x48, 0x22, 0xe9, 0xcc, 0x55, 0x83, 0xb7, 0x80, 0xe4, - 0x0b, 0xcd, 0xc5, 0xad, 0x84, 0x00, 0xb1, 0x17, 0x25, 0xc5, 0x91, 0xd2, 0xb4, 0x38, 0xf2, 0xda, - 0xa2, 0xc2, 0xb7, 0x60, 0x8e, 0xae, 0xe9, 0x90, 0x11, 0xbe, 0x6a, 0x43, 0x91, 0x63, 0xa8, 0xfe, - 0x53, 0xdc, 0x83, 0x29, 0x71, 0xf5, 0x7b, 0xbb, 0x2a, 0x89, 0x7b, 0xbb, 0x74, 0xdb, 0x4a, 0x35, - 0x69, 0x5b, 0xb9, 0x0f, 0x8d, 0x68, 0x40, 0xf1, 0xa4, 0xd2, 0x0d, 0x64, 0xfc, 0x60, 0x5d, 0xc1, - 0x05, 0x97, 0xdc, 0x0f, 0xe2, 0x0d, 0xb1, 0x9e, 0xd8, 0x10, 0x05, 0x0f, 0x6b, 0x85, 0x21, 0x1f, - 0x8d, 0x43, 0xb9, 0x21, 0x62, 0x84, 0x91, 0xde, 0xc0, 0x64, 0xec, 0x7b, 0x0d, 0xca, 0x9d, 0x7d, - 0x6b, 0x7b, 0xb7, 0xf3, 0x74, 0xa7, 0xd7, 0xc8, 0x88, 0xcf, 0xee, 0xd1, 0xe6, 0x66, 0xbb, 0xbd, - 0x85, 0x3b, 0x0e, 0xc0, 0xdc, 0x76, 0xab, 0x23, 0x76, 0x9f, 0x9c, 0xf1, 0x7b, 0x59, 0xa8, 0x68, - 0xc5, 0xb3, 0x27, 0xd1, 0xa8, 0xd0, 0xd5, 0x4e, 0x77, 0x66, 0x9b, 0xb0, 0xae, 0x58, 0xb1, 0x36, - 0x2c, 0xd1, 0xc5, 0x8a, 0xd9, 0x6b, 0x2f, 0x56, 0x64, 0xef, 0xc0, 0xbc, 0x4d, 0x25, 0x44, 0xa3, - 0x20, 0x4f, 0xe1, 0x25, 0x58, 0x0e, 0x02, 0x3a, 0x76, 0xc6, 0xfb, 0x89, 0xc0, 0xcb, 0x2b, 0x5f, - 0xca, 0x68, 0x4b, 0xc1, 0xc1, 0x2a, 0x9e, 0xd8, 0xce, 0x70, 0xe2, 0x73, 0x69, 0x35, 0x8f, 0x76, - 0x66, 0x82, 0x9a, 0x2a, 0xd9, 0xf8, 0x10, 0x20, 0x6e, 0x73, 0x72, 0x70, 0x6e, 0x24, 0x07, 0x27, - 0xa3, 0x0d, 0x4e, 0xd6, 0xd8, 0x22, 0x36, 0x22, 0x07, 0x3a, 0x3a, 0x76, 0xfb, 0x06, 0xa8, 0x83, - 0x40, 0x0b, 0xdd, 0xab, 0xc7, 0x43, 0x1e, 0xaa, 0x5b, 0x02, 0x16, 0x64, 0x4a, 0x27, 0x4a, 0x50, - 0x97, 0x76, 0xc4, 0xa5, 0xc4, 0xdc, 0x48, 0x92, 0xe4, 0x34, 0x37, 0x92, 0xa8, 0x66, 0x94, 0x6e, - 0xac, 0x41, 0x73, 0x8b, 0x8b, 0xd2, 0x5a, 0xc3, 0xe1, 0x54, 0x73, 0x8c, 0x5b, 0x70, 0x33, 0x25, - 0x4d, 0x1e, 0x42, 0x7c, 0x02, 0xcb, 0x2d, 0xba, 0x10, 0xe0, 0xab, 0x8a, 0xfc, 0x33, 0x9a, 0xb0, - 0x32, 0x5d, 0xa4, 0xac, 0x6c, 0x1b, 0x16, 0xb6, 0xf8, 0xf1, 0xe4, 0x74, 0x97, 0x9f, 0xc7, 0x15, - 0x31, 0xc8, 0x07, 0x67, 0xde, 0x85, 0x1c, 0x1f, 0xfc, 0x8d, 0x5e, 0x86, 0x02, 0xc7, 0x0a, 0xc6, - 0xbc, 0xaf, 0x0e, 0xa2, 0x11, 0xd2, 0x1d, 0xf3, 0xbe, 0xf1, 0x04, 0x98, 0x5e, 0x8e, 0x1c, 0x2f, - 0xa1, 0x25, 0x4c, 0x8e, 0xad, 0xe0, 0x2a, 0x08, 0xf9, 0x48, 0x45, 0xbc, 0x41, 0x30, 0x39, 0xee, - 0x12, 0xc4, 0x78, 0x17, 0xaa, 0x87, 0xf6, 0x95, 0xc9, 0x3f, 0x97, 0x81, 0x65, 0xab, 0x50, 0x1c, - 0xdb, 0x57, 0x82, 0x0d, 0x44, 0x36, 0x29, 0x4c, 0x36, 0xfe, 0x28, 0x0f, 0x73, 0x84, 0xc9, 0xee, - 0xd1, 0xe5, 0xbe, 0x8e, 0x8b, 0xcb, 0x50, 0x31, 0x4a, 0x0d, 0x34, 0xc3, 0x4b, 0xb3, 0xb3, 0xbc, - 0x54, 0x1e, 0xa0, 0xa9, 0x4b, 0x8d, 0x94, 0xf5, 0xc0, 0x9d, 0x8c, 0xd4, 0x4d, 0x46, 0xc9, 0xa8, - 0xf8, 0x7c, 0x7c, 0x79, 0x33, 0x85, 0x0c, 0x27, 0xed, 0xbb, 0xb1, 0x2e, 0x42, 0xad, 0x53, 0x5b, - 0x84, 0x64, 0x97, 0x3a, 0x28, 0x55, 0xe1, 0x29, 0xaa, 0x68, 0xc9, 0xa4, 0xc2, 0x33, 0xa3, 0xd8, - 0x94, 0x5e, 0xad, 0xd8, 0xd0, 0xc9, 0xda, 0x4b, 0x14, 0x1b, 0x78, 0x0d, 0xc5, 0xe6, 0x35, 0x6c, - 0xab, 0x37, 0xa1, 0x84, 0xfb, 0xbe, 0xc6, 0x3d, 0xc5, 0x7e, 0x2f, 0xb8, 0xe7, 0xb7, 0x35, 0xd1, - 0x9f, 0x1c, 0x3b, 0x6e, 0xc5, 0xcb, 0xc4, 0xe4, 0x9f, 0xff, 0x62, 0x6c, 0x56, 0xcf, 0xa1, 0x28, - 0xa1, 0x82, 0xa0, 0x5d, 0x7b, 0xa4, 0xee, 0x85, 0xc3, 0xdf, 0x62, 0xd8, 0xf0, 0x32, 0xab, 0xcf, - 0x27, 0x8e, 0xcf, 0x07, 0xea, 0xc2, 0x1f, 0x07, 0xd7, 0xa8, 0x80, 0x88, 0x0e, 0x0a, 0x35, 0xc4, - 0xf5, 0x2e, 0x5c, 0x79, 0xdd, 0x47, 0xd1, 0x09, 0x9e, 0x89, 0x4f, 0x83, 0x41, 0x03, 0x6f, 0x86, - 0x1c, 0x7b, 0xbe, 0xda, 0x9c, 0x8c, 0x9f, 0x66, 0xa0, 0x21, 0x57, 0x57, 0x94, 0xa6, 0x6b, 0x01, - 0x85, 0xeb, 0xfc, 0x10, 0x5e, 0x7e, 0x7d, 0x8f, 0x01, 0x35, 0x3c, 0xfc, 0x88, 0x76, 0x2a, 0x3a, - 0xbc, 0xa9, 0x08, 0xe0, 0xb6, 0xdc, 0xad, 0xde, 0x80, 0x8a, 0xf2, 0x81, 0x1e, 0x39, 0x43, 0x75, - 0x4f, 0x3b, 0x39, 0x41, 0xef, 0x39, 0x43, 0xb5, 0xd1, 0xf9, 0xb6, 0x8c, 0xde, 0xcd, 0xe0, 0x46, - 0x67, 0xda, 0x21, 0x37, 0xfe, 0x75, 0x06, 0x16, 0xb4, 0xae, 0xc8, 0x75, 0xfb, 0x11, 0x54, 0xa3, - 0x2b, 0x59, 0x79, 0x24, 0x79, 0xad, 0x26, 0x19, 0x4d, 0x9c, 0xad, 0xd2, 0x8f, 0x20, 0x81, 0x68, - 0xcc, 0xc0, 0xbe, 0x22, 0x47, 0xdd, 0xc9, 0x48, 0x29, 0x37, 0x03, 0xfb, 0x6a, 0x9b, 0xf3, 0xee, - 0x64, 0x24, 0x54, 0xd7, 0x0b, 0xce, 0x5f, 0x44, 0x08, 0x24, 0x73, 0x81, 0x80, 0x49, 0x0c, 0x03, - 0x6a, 0x23, 0xcf, 0x0d, 0xcf, 0x22, 0x14, 0x29, 0x75, 0x22, 0x90, 0x70, 0x8c, 0x3f, 0xcb, 0xc2, - 0x22, 0x1d, 0xb1, 0xc9, 0xa3, 0x4d, 0xc9, 0xba, 0x9a, 0x30, 0x47, 0xa7, 0x8d, 0xc4, 0xbc, 0x76, - 0x6e, 0x98, 0xf2, 0x9b, 0x7d, 0xeb, 0x35, 0x8f, 0x05, 0x55, 0x80, 0xf0, 0x35, 0xc3, 0x9f, 0x9b, - 0x1d, 0xfe, 0xeb, 0x87, 0x37, 0xcd, 0xd0, 0x59, 0x48, 0x33, 0x74, 0xbe, 0x8e, 0x79, 0x71, 0x26, - 0x94, 0xb5, 0x28, 0x71, 0xb4, 0x50, 0xd6, 0x27, 0xb0, 0x9a, 0xc0, 0x41, 0x6e, 0xed, 0x9c, 0x38, - 0x5c, 0xdd, 0xa6, 0xb2, 0xa4, 0x61, 0x77, 0x55, 0xda, 0x46, 0x11, 0x0a, 0x41, 0xdf, 0x1b, 0x73, - 0x63, 0x05, 0x96, 0x92, 0xa3, 0x2a, 0xb7, 0x89, 0xdf, 0xcf, 0x40, 0x53, 0xba, 0xa5, 0x38, 0xee, - 0xe9, 0x8e, 0x13, 0x84, 0x9e, 0x1f, 0x5d, 0x5d, 0x7a, 0x07, 0x20, 0x08, 0x6d, 0x5f, 0x6a, 0x9b, - 0xf2, 0xfe, 0x10, 0x84, 0xa0, 0x26, 0x79, 0x13, 0x4a, 0xdc, 0x1d, 0x50, 0x22, 0x51, 0x43, 0x91, - 0xbb, 0x03, 0xa5, 0x87, 0xce, 0xc8, 0xdf, 0xb5, 0xa4, 0x7a, 0x21, 0xc3, 0xf9, 0xc5, 0xe8, 0xf0, - 0x73, 0xdc, 0x78, 0xf3, 0x51, 0x38, 0xff, 0x9e, 0x7d, 0x89, 0x4e, 0x9e, 0x81, 0xf1, 0xf7, 0xb3, - 0x30, 0x1f, 0xb7, 0x8f, 0xee, 0x02, 0x79, 0xf9, 0xad, 0x26, 0xf7, 0x24, 0x39, 0x38, 0x42, 0x7e, - 0xd7, 0x0e, 0x1e, 0x4b, 0xb4, 0x38, 0x3b, 0x2e, 0x33, 0xa0, 0xa2, 0x30, 0xbc, 0x49, 0xa8, 0xdd, - 0x20, 0x58, 0x26, 0x94, 0x83, 0x49, 0x28, 0x14, 0x2e, 0xa1, 0x79, 0x3a, 0xae, 0x54, 0x79, 0x0a, - 0xf6, 0x28, 0xec, 0xe0, 0xc3, 0x04, 0x02, 0x2c, 0xb2, 0xd1, 0x44, 0x0a, 0x2c, 0x81, 0xdf, 0x20, - 0x39, 0x9b, 0x66, 0x0e, 0x65, 0x6c, 0x5d, 0x08, 0xa5, 0x3b, 0x9a, 0x23, 0x21, 0xf4, 0x0d, 0xa8, - 0x50, 0xe1, 0x71, 0xe4, 0x72, 0xde, 0x2c, 0x63, 0x0d, 0x98, 0x2e, 0x0f, 0x81, 0xbc, 0x49, 0x42, - 0xf5, 0x05, 0xaa, 0x0a, 0xbd, 0x3e, 0xfe, 0x56, 0x06, 0x6e, 0xa6, 0x4c, 0x9b, 0x5c, 0xe5, 0x9b, - 0xb0, 0x70, 0x12, 0x25, 0xaa, 0xd1, 0xa5, 0xa5, 0xbe, 0xa2, 0xd8, 0x6a, 0x72, 0x4c, 0xcd, 0xc6, - 0x49, 0x12, 0x10, 0x2b, 0x5d, 0x34, 0x83, 0x89, 0xb8, 0x78, 0x54, 0xba, 0x68, 0x1a, 0x49, 0xdf, - 0x39, 0x84, 0xb5, 0xf6, 0xa5, 0xe0, 0x18, 0x9b, 0xfa, 0xcb, 0x1a, 0x8a, 0x8c, 0x92, 0x07, 0xcc, - 0x99, 0xd7, 0x3a, 0x60, 0x1e, 0x50, 0x20, 0x6d, 0x54, 0xd6, 0xcf, 0x52, 0x08, 0x6e, 0xa0, 0x22, - 0x0f, 0xbd, 0x0c, 0xa2, 0x02, 0xe4, 0xfb, 0xd1, 0x8b, 0x20, 0x46, 0x00, 0xf3, 0x7b, 0x93, 0x61, - 0xe8, 0xc4, 0x8f, 0x84, 0xb0, 0x6f, 0xc9, 0x3c, 0x58, 0x8f, 0x1a, 0xb5, 0xd4, 0x8a, 0x20, 0xaa, - 0x08, 0x07, 0x6b, 0x24, 0x0a, 0xb2, 0x66, 0xeb, 0x9b, 0x1f, 0x25, 0x6b, 0x30, 0x6e, 0xc2, 0x6a, - 0xfc, 0x45, 0xc3, 0xa6, 0xb6, 0x9a, 0x7f, 0x92, 0x21, 0x8f, 0xf2, 0xe4, 0x83, 0x25, 0xac, 0x0d, - 0x8b, 0x81, 0xe3, 0x9e, 0x0e, 0xb9, 0x5e, 0x7c, 0x20, 0x07, 0x61, 0x39, 0xd9, 0x36, 0xf9, 0xa8, - 0x89, 0xb9, 0x40, 0x39, 0xe2, 0xd2, 0x02, 0xb6, 0x71, 0x5d, 0x23, 0x63, 0xb2, 0x98, 0x1a, 0x8d, - 0xd9, 0xc6, 0x77, 0xa0, 0x9e, 0xac, 0x88, 0x7d, 0x5b, 0xc6, 0x9f, 0xc7, 0xad, 0xca, 0x4d, 0x05, - 0xe7, 0xc6, 0x04, 0x51, 0x89, 0xc7, 0x3e, 0x30, 0xfe, 0x4e, 0x06, 0x9a, 0x26, 0x17, 0x94, 0xab, - 0xb5, 0x52, 0xd1, 0xcc, 0x47, 0x33, 0xa5, 0x5e, 0xdf, 0x57, 0x15, 0xd6, 0xae, 0x5a, 0xf4, 0xf5, - 0x6b, 0x27, 0x63, 0xe7, 0xc6, 0x4c, 0x8f, 0x36, 0x4a, 0x30, 0x47, 0x28, 0xc6, 0x2a, 0x2c, 0xcb, - 0xf6, 0xa8, 0xb6, 0xc4, 0xd6, 0xc3, 0x44, 0x8d, 0x09, 0xeb, 0xe1, 0x1a, 0x34, 0x29, 0xd0, 0x54, - 0xef, 0x84, 0xcc, 0xb8, 0x05, 0x6c, 0xcf, 0xee, 0xdb, 0xbe, 0xe7, 0xb9, 0x87, 0xdc, 0x97, 0xfe, - 0xb9, 0x28, 0x61, 0xa2, 0x71, 0x4d, 0x89, 0xc2, 0xf4, 0xa5, 0xee, 0x4d, 0xf5, 0x5c, 0xe5, 0x8e, - 0x44, 0x5f, 0x86, 0x09, 0x8b, 0x1b, 0xf6, 0x0b, 0xae, 0x4a, 0x52, 0x43, 0xf4, 0x31, 0x54, 0xc6, - 0x51, 0xa1, 0x6a, 0xdc, 0xd5, 0xfd, 0x18, 0xb3, 0xd5, 0x9a, 0x3a, 0xb6, 0xf1, 0x18, 0x96, 0x92, - 0x65, 0x4a, 0xd6, 0xb1, 0x06, 0xa5, 0x91, 0x84, 0xc9, 0xd6, 0x45, 0xdf, 0xc6, 0xef, 0x96, 0xa0, - 0x28, 0xf5, 0x39, 0xb6, 0x0e, 0xf9, 0xbe, 0x72, 0x09, 0x8b, 0xaf, 0x5d, 0x92, 0xa9, 0xea, 0xff, - 0x26, 0x3a, 0x86, 0x09, 0x3c, 0xf6, 0x31, 0xd4, 0x93, 0x56, 0xd1, 0xa9, 0x30, 0xf6, 0xa4, 0x39, - 0xb3, 0xd6, 0x9f, 0xb2, 0x7f, 0x95, 0xe3, 0xcd, 0x91, 0x64, 0x86, 0xd2, 0x99, 0xb6, 0x7b, 0x7a, - 0xae, 0x90, 0xb7, 0x83, 0x33, 0xdb, 0x7a, 0xfc, 0xe4, 0x43, 0x19, 0xc7, 0x5e, 0x41, 0x60, 0xf7, - 0xcc, 0x7e, 0xfc, 0xe4, 0xc3, 0x69, 0x49, 0x5a, 0x46, 0xb1, 0x6b, 0x92, 0xf4, 0x12, 0x14, 0xe8, - 0x82, 0x50, 0xf2, 0xed, 0xa1, 0x0f, 0xf6, 0x08, 0x96, 0xa4, 0xda, 0x6a, 0x49, 0x2f, 0x6c, 0xe2, - 0x82, 0x25, 0x0a, 0x7c, 0x93, 0x69, 0x5d, 0x4c, 0xa2, 0xb3, 0xa1, 0x15, 0x98, 0x3b, 0x8b, 0x6f, - 0x7b, 0xad, 0x99, 0xf2, 0xcb, 0xf8, 0xb3, 0x02, 0x54, 0xb4, 0x41, 0x61, 0x55, 0x28, 0x99, 0xed, - 0x6e, 0xdb, 0xfc, 0xb4, 0xbd, 0xd5, 0xb8, 0xc1, 0xee, 0xc3, 0xdb, 0x9d, 0xfd, 0xcd, 0x03, 0xd3, - 0x6c, 0x6f, 0xf6, 0xac, 0x03, 0xd3, 0x52, 0x97, 0x7f, 0x1d, 0xb6, 0x9e, 0xef, 0xb5, 0xf7, 0x7b, - 0xd6, 0x56, 0xbb, 0xd7, 0xea, 0xec, 0x76, 0x1b, 0x19, 0x76, 0x1b, 0x9a, 0x31, 0xa6, 0x4a, 0x6e, - 0xed, 0x1d, 0x1c, 0xed, 0xf7, 0x1a, 0x59, 0x76, 0x17, 0x6e, 0x6d, 0x77, 0xf6, 0x5b, 0xbb, 0x56, - 0x8c, 0xb3, 0xb9, 0xdb, 0xfb, 0xd4, 0x6a, 0xff, 0xca, 0x61, 0xc7, 0x7c, 0xde, 0xc8, 0xa5, 0x21, - 0x08, 0x65, 0x5c, 0x95, 0x90, 0x67, 0x37, 0x61, 0x99, 0x10, 0x28, 0x8b, 0xd5, 0x3b, 0x38, 0xb0, - 0xba, 0x07, 0x07, 0xfb, 0x8d, 0x02, 0x5b, 0x80, 0x5a, 0x67, 0xff, 0xd3, 0xd6, 0x6e, 0x67, 0xcb, - 0x32, 0xdb, 0xad, 0xdd, 0xbd, 0xc6, 0x1c, 0x5b, 0x84, 0xf9, 0x69, 0xbc, 0xa2, 0x28, 0x42, 0xe1, - 0x1d, 0xec, 0x77, 0x0e, 0xf6, 0xad, 0x4f, 0xdb, 0x66, 0xb7, 0x73, 0xb0, 0xdf, 0x28, 0xb1, 0x15, - 0x60, 0xc9, 0xa4, 0x9d, 0xbd, 0xd6, 0x66, 0xa3, 0xcc, 0x96, 0x61, 0x21, 0x09, 0x7f, 0xd6, 0x7e, - 0xde, 0x00, 0xd6, 0x84, 0x25, 0x6a, 0x98, 0xb5, 0xd1, 0xde, 0x3d, 0xf8, 0xcc, 0xda, 0xeb, 0xec, - 0x77, 0xf6, 0x8e, 0xf6, 0x1a, 0x15, 0xbc, 0x8e, 0xb0, 0xdd, 0xb6, 0x3a, 0xfb, 0xdd, 0xa3, 0xed, - 0xed, 0xce, 0x66, 0xa7, 0xbd, 0xdf, 0x6b, 0x54, 0xa9, 0xe6, 0xb4, 0x8e, 0xd7, 0x44, 0x06, 0x19, - 0xaa, 0x61, 0x6d, 0x75, 0xba, 0xad, 0x8d, 0xdd, 0xf6, 0x56, 0xa3, 0xce, 0xee, 0xc0, 0xcd, 0x5e, - 0x7b, 0xef, 0xf0, 0xc0, 0x6c, 0x99, 0xcf, 0x55, 0x28, 0x87, 0xb5, 0xdd, 0xea, 0xec, 0x1e, 0x99, - 0xed, 0xc6, 0x3c, 0x7b, 0x13, 0xee, 0x98, 0xed, 0x4f, 0x8e, 0x3a, 0x66, 0x7b, 0xcb, 0xda, 0x3f, - 0xd8, 0x6a, 0x5b, 0xdb, 0xed, 0x56, 0xef, 0xc8, 0x6c, 0x5b, 0x7b, 0x9d, 0x6e, 0xb7, 0xb3, 0xff, - 0xb4, 0xd1, 0x60, 0x6f, 0xc3, 0xbd, 0x08, 0x25, 0x2a, 0x60, 0x0a, 0x6b, 0x41, 0xf4, 0x4f, 0x4d, - 0xe9, 0x7e, 0xfb, 0x57, 0x7a, 0xd6, 0x61, 0xbb, 0x6d, 0x36, 0x18, 0x5b, 0x83, 0x95, 0xb8, 0x7a, - 0xaa, 0x40, 0xd6, 0xbd, 0x28, 0xd2, 0x0e, 0xdb, 0xe6, 0x5e, 0x6b, 0x5f, 0x4c, 0x70, 0x22, 0x6d, - 0x49, 0x34, 0x3b, 0x4e, 0x9b, 0x6e, 0xf6, 0x32, 0x63, 0x50, 0xd7, 0x66, 0x65, 0xbb, 0x65, 0x36, - 0x56, 0xd8, 0x3c, 0x54, 0xf6, 0x0e, 0x0f, 0xad, 0x5e, 0x67, 0xaf, 0x7d, 0x70, 0xd4, 0x6b, 0xac, - 0xb2, 0x65, 0x68, 0x74, 0xf6, 0x7b, 0x6d, 0x53, 0xcc, 0xb5, 0xca, 0xfa, 0x3f, 0x8a, 0x6c, 0x09, - 0xe6, 0x55, 0x4b, 0x15, 0xf4, 0x2f, 0x8b, 0x6c, 0x15, 0xd8, 0xd1, 0xbe, 0xd9, 0x6e, 0x6d, 0x89, - 0x81, 0x8b, 0x12, 0xfe, 0x67, 0x51, 0x5a, 0x48, 0x7e, 0x9a, 0x8b, 0x36, 0xeb, 0xd8, 0xe5, 0x20, - 0x79, 0xf7, 0x77, 0x55, 0xbb, 0xb3, 0xfb, 0x55, 0xaf, 0x72, 0x68, 0xaa, 0x55, 0x6e, 0x46, 0xb5, - 0x9a, 0xd1, 0xdd, 0x6b, 0xba, 0xec, 0xf7, 0x16, 0xd4, 0x46, 0x74, 0x0f, 0xb8, 0xbc, 0xef, 0x17, - 0xa4, 0xff, 0x0d, 0x01, 0xe9, 0xb2, 0xdf, 0x99, 0x67, 0x29, 0x0a, 0xb3, 0xcf, 0x52, 0xa4, 0xc9, - 0xf7, 0x73, 0x69, 0xf2, 0xfd, 0x03, 0x58, 0x20, 0xd6, 0xe4, 0xb8, 0xce, 0x48, 0x69, 0xcd, 0x24, - 0x05, 0xce, 0x23, 0x8b, 0x22, 0xb8, 0x52, 0x27, 0x94, 0xca, 0x21, 0x59, 0x48, 0x51, 0x6a, 0x1b, - 0x09, 0x4d, 0x83, 0x38, 0x47, 0xa4, 0x69, 0x44, 0x35, 0xd8, 0x97, 0x71, 0x0d, 0x15, 0xad, 0x06, - 0x82, 0x63, 0x0d, 0x0f, 0x60, 0x81, 0x5f, 0x86, 0xbe, 0x6d, 0x79, 0x63, 0xfb, 0xf3, 0x09, 0x9a, - 0x70, 0x6d, 0xd4, 0xe1, 0xab, 0xe6, 0x3c, 0x26, 0x1c, 0x20, 0x7c, 0xcb, 0x0e, 0xed, 0x07, 0x5f, - 0x40, 0x45, 0xbb, 0x23, 0x9e, 0xad, 0xc2, 0xe2, 0x67, 0x9d, 0xde, 0x7e, 0xbb, 0xdb, 0xb5, 0x0e, - 0x8f, 0x36, 0x9e, 0xb5, 0x9f, 0x5b, 0x3b, 0xad, 0xee, 0x4e, 0xe3, 0x86, 0x58, 0xb4, 0xfb, 0xed, - 0x6e, 0xaf, 0xbd, 0x95, 0x80, 0x67, 0xd8, 0x1b, 0xb0, 0x76, 0xb4, 0x7f, 0xd4, 0x6d, 0x6f, 0x59, - 0x69, 0xf9, 0xb2, 0x82, 0x4a, 0x65, 0x7a, 0x4a, 0xf6, 0xdc, 0x83, 0xdf, 0x80, 0x7a, 0x32, 0xaa, - 0x99, 0x01, 0xcc, 0xed, 0xb6, 0x9f, 0xb6, 0x36, 0x9f, 0xd3, 0x85, 0xa5, 0xdd, 0x5e, 0xab, 0xd7, - 0xd9, 0xb4, 0xe4, 0x05, 0xa5, 0x82, 0x23, 0x64, 0x58, 0x05, 0x8a, 0xad, 0xfd, 0xcd, 0x9d, 0x03, - 0xb3, 0xdb, 0xc8, 0xb2, 0xdb, 0xb0, 0xaa, 0x68, 0x75, 0xf3, 0x60, 0x6f, 0xaf, 0xd3, 0x43, 0x66, - 0xd8, 0x7b, 0x7e, 0x28, 0x48, 0xf3, 0xc1, 0x77, 0xa1, 0x9e, 0xf4, 0xbd, 0x4b, 0x9e, 0xca, 0xae, - 0xc1, 0xca, 0x46, 0xbb, 0xf7, 0x59, 0xbb, 0xbd, 0x8f, 0x4d, 0xdf, 0x6c, 0xef, 0xf7, 0xcc, 0xd6, - 0x6e, 0xa7, 0xf7, 0xbc, 0x91, 0x79, 0xf0, 0x31, 0x34, 0xa6, 0x0d, 0x5d, 0x09, 0xcb, 0xe0, 0xcb, - 0x4c, 0x88, 0x0f, 0xfe, 0x79, 0x0e, 0x20, 0x0e, 0x00, 0x11, 0x3c, 0x6c, 0xab, 0xd5, 0x6b, 0xed, - 0x1e, 0x88, 0xf1, 0x31, 0x0f, 0x7a, 0x82, 0x35, 0x99, 0xed, 0x4f, 0x1a, 0x37, 0x52, 0x53, 0x0e, - 0x0e, 0x7b, 0x8d, 0x8c, 0x98, 0x8a, 0xce, 0x7e, 0xa7, 0xd7, 0x69, 0xed, 0x5a, 0xe6, 0xc1, 0x51, - 0x67, 0xff, 0x29, 0x5d, 0xf1, 0x88, 0xec, 0xfb, 0xe8, 0x70, 0xdb, 0x3c, 0xd8, 0xef, 0x59, 0xdd, - 0x9d, 0xa3, 0xde, 0x16, 0x5e, 0x10, 0xb9, 0x69, 0x76, 0x0e, 0xa9, 0xcc, 0xfc, 0xcb, 0x10, 0x44, - 0xd1, 0x05, 0x31, 0x99, 0x4f, 0x0f, 0xba, 0xdd, 0xce, 0xa1, 0xf5, 0xc9, 0x51, 0xdb, 0xec, 0xb4, - 0xbb, 0x98, 0x71, 0x2e, 0x05, 0x2e, 0xf0, 0x8b, 0x82, 0xe9, 0xf7, 0x76, 0x3f, 0x95, 0x5c, 0x59, - 0xa0, 0x96, 0x92, 0x20, 0x81, 0x55, 0x16, 0x83, 0x29, 0xd8, 0x5a, 0x4a, 0xc9, 0x70, 0x4d, 0x9a, - 0xc8, 0x57, 0x11, 0x0c, 0x7b, 0x66, 0x96, 0x31, 0x5b, 0x35, 0x3d, 0x49, 0xe4, 0x42, 0x5e, 0x1e, - 0xed, 0x7c, 0x5b, 0x5b, 0x26, 0x66, 0xa8, 0xcf, 0x40, 0x05, 0xee, 0xbc, 0x98, 0x28, 0xc1, 0xf7, - 0x04, 0x4a, 0x43, 0x7d, 0x88, 0x94, 0x85, 0xc7, 0xbf, 0x93, 0x83, 0x3a, 0x05, 0xe3, 0xd1, 0xdb, - 0x7f, 0xdc, 0x67, 0x7b, 0x50, 0x94, 0x8f, 0x48, 0xb2, 0xe5, 0xe8, 0xf6, 0x3d, 0xfd, 0xd9, 0xca, - 0xb5, 0x95, 0x69, 0xb0, 0x94, 0xf3, 0x16, 0xff, 0xda, 0x9f, 0xfe, 0xf7, 0xbf, 0x97, 0xad, 0xb1, - 0xca, 0xc3, 0xf3, 0x0f, 0x1e, 0x9e, 0x72, 0x37, 0x10, 0x65, 0xfc, 0x1a, 0x40, 0xfc, 0x34, 0x22, - 0x6b, 0x46, 0xd6, 0xad, 0xa9, 0x77, 0x23, 0xd7, 0x6e, 0xa6, 0xa4, 0xc8, 0x72, 0x6f, 0x62, 0xb9, - 0x8b, 0x46, 0x5d, 0x94, 0xeb, 0xb8, 0x4e, 0x48, 0xcf, 0x24, 0x7e, 0x94, 0x79, 0xc0, 0x06, 0x50, - 0xd5, 0x1f, 0x2d, 0x64, 0x4a, 0x04, 0x4b, 0x79, 0x76, 0x71, 0xed, 0x56, 0x6a, 0x9a, 0x12, 0x6e, - 0xb1, 0x8e, 0x65, 0xa3, 0x21, 0xea, 0x98, 0x20, 0x46, 0x5c, 0xcb, 0x90, 0xc4, 0xfd, 0xf8, 0x6d, - 0x42, 0x76, 0x5b, 0x13, 0xd8, 0x66, 0x5e, 0x46, 0x5c, 0xbb, 0x73, 0x4d, 0xaa, 0xac, 0xeb, 0x0e, - 0xd6, 0xb5, 0x6a, 0x30, 0x51, 0x57, 0x1f, 0x71, 0xd4, 0xcb, 0x88, 0x1f, 0x65, 0x1e, 0x3c, 0xfe, - 0x0f, 0xef, 0x41, 0x39, 0x72, 0xce, 0x65, 0xbf, 0x09, 0xb5, 0x44, 0xb4, 0x24, 0x53, 0xdd, 0x48, - 0x0b, 0xae, 0x5c, 0xbb, 0x9d, 0x9e, 0x28, 0x2b, 0x7e, 0x03, 0x2b, 0x6e, 0xb2, 0x15, 0x51, 0xb1, - 0x8c, 0x46, 0x7c, 0x88, 0xd1, 0xcd, 0x74, 0x97, 0xe1, 0x0b, 0x4d, 0xad, 0xa1, 0xca, 0x6e, 0x4f, - 0xab, 0x1a, 0x89, 0xda, 0xee, 0x5c, 0x93, 0x2a, 0xab, 0xbb, 0x8d, 0xd5, 0xad, 0xb0, 0x25, 0xbd, - 0x3a, 0xe5, 0xd3, 0xc9, 0x38, 0xde, 0x1f, 0xaa, 0x3f, 0xdd, 0xc7, 0xee, 0xc4, 0xb7, 0x3d, 0xa6, - 0x3c, 0xe9, 0x17, 0x91, 0xc8, 0xec, 0xbb, 0x7e, 0x46, 0x13, 0xab, 0x62, 0x0c, 0xa7, 0x4f, 0x7f, - 0xb9, 0x8f, 0x1d, 0x43, 0x45, 0x7b, 0xed, 0x86, 0xdd, 0xbc, 0xf6, 0x65, 0x9e, 0xb5, 0xb5, 0xb4, - 0xa4, 0xb4, 0xae, 0xe8, 0xe5, 0x3f, 0x3c, 0xe1, 0x9c, 0xfd, 0x2a, 0x94, 0xa3, 0x37, 0x54, 0xd8, - 0xaa, 0xf6, 0xa6, 0x8d, 0xfe, 0xe6, 0xcb, 0x5a, 0x73, 0x36, 0x21, 0x8d, 0xf8, 0xf4, 0xd2, 0x05, - 0xf1, 0x7d, 0x06, 0x15, 0xed, 0x9d, 0x94, 0xa8, 0x03, 0xb3, 0x6f, 0xb1, 0x44, 0x1d, 0x48, 0x79, - 0x56, 0xc5, 0x58, 0xc0, 0x2a, 0x2a, 0xac, 0x8c, 0xf4, 0x1d, 0x5e, 0x7a, 0x01, 0xdb, 0x85, 0x65, - 0xa9, 0xc2, 0x1d, 0xf3, 0x2f, 0x33, 0x0d, 0x29, 0xaf, 0x25, 0x3e, 0xca, 0xb0, 0x8f, 0xa1, 0xa4, - 0x9e, 0xc3, 0x61, 0x2b, 0xe9, 0xcf, 0xfa, 0xac, 0xad, 0xce, 0xc0, 0xa5, 0xbe, 0xf5, 0x1c, 0x20, - 0x7e, 0x94, 0x25, 0x62, 0x12, 0x33, 0x8f, 0xbc, 0x44, 0x14, 0x30, 0xfb, 0x82, 0x8b, 0xb1, 0x82, - 0x1d, 0x6c, 0x30, 0x64, 0x12, 0x2e, 0xbf, 0x50, 0x97, 0x3c, 0xff, 0x08, 0x2a, 0xda, 0xbb, 0x2c, - 0xd1, 0xf0, 0xcd, 0xbe, 0xe9, 0x12, 0x0d, 0x5f, 0xca, 0x33, 0x2e, 0xc6, 0x1a, 0x96, 0xbe, 0x64, - 0xcc, 0x8b, 0xd2, 0x85, 0x0c, 0x27, 0x65, 0x29, 0x31, 0x41, 0x67, 0x50, 0x4b, 0x3c, 0xbe, 0x12, - 0xad, 0xd0, 0xb4, 0xa7, 0x5d, 0xa2, 0x15, 0x9a, 0xfa, 0x5e, 0x8b, 0xa2, 0x33, 0x63, 0x41, 0xd4, - 0x43, 0xf7, 0x3c, 0x69, 0x35, 0xfd, 0x10, 0x2a, 0xda, 0x43, 0x2a, 0x51, 0x5f, 0x66, 0xdf, 0x6c, - 0x89, 0xfa, 0x92, 0xf6, 0xee, 0xca, 0x12, 0xd6, 0x51, 0x37, 0x90, 0x14, 0xf0, 0x9a, 0x5a, 0x51, - 0xf6, 0x6f, 0x42, 0x3d, 0xf9, 0xb6, 0x4a, 0xb4, 0xf6, 0x53, 0x1f, 0x69, 0x89, 0xd6, 0xfe, 0x35, - 0x0f, 0xb2, 0x48, 0x92, 0x7e, 0xb0, 0x18, 0x55, 0xf2, 0xf0, 0x27, 0x32, 0xcc, 0xe8, 0x0b, 0xf6, - 0x89, 0x60, 0x70, 0xf2, 0x96, 0x64, 0xb6, 0xaa, 0x51, 0xad, 0x7e, 0xdd, 0x72, 0xb4, 0x5e, 0x66, - 0x2e, 0x54, 0x4e, 0x12, 0x33, 0x16, 0xce, 0x9e, 0xc2, 0x62, 0x44, 0xcc, 0xd1, 0xb5, 0xc7, 0x41, - 0xd4, 0x87, 0xd4, 0xcb, 0x95, 0xd7, 0x1a, 0xd3, 0xa9, 0x8f, 0x32, 0xb4, 0xfd, 0xe1, 0x65, 0xb3, - 0xda, 0xf6, 0xa7, 0xdf, 0x7c, 0xac, 0x6d, 0x7f, 0x89, 0x3b, 0x69, 0xa7, 0xb7, 0xbf, 0xd0, 0x11, - 0x65, 0xb8, 0x30, 0x3f, 0x7d, 0x09, 0xf1, 0x9d, 0xeb, 0xae, 0x71, 0xa0, 0xe2, 0xdf, 0x78, 0xf9, - 0x2d, 0x0f, 0x49, 0x56, 0xa4, 0xb8, 0xe9, 0x43, 0xe9, 0xd5, 0xc2, 0x7e, 0x1d, 0xaa, 0xfa, 0x7b, - 0x0c, 0x4c, 0xe7, 0x09, 0xd3, 0x35, 0xdd, 0x4a, 0x4d, 0x4b, 0x52, 0x09, 0xab, 0xea, 0xd5, 0xb0, - 0x4f, 0x61, 0x25, 0x1a, 0x66, 0xfd, 0x1e, 0x82, 0x80, 0xdd, 0x4d, 0xb9, 0x9d, 0x20, 0x31, 0xd8, - 0x37, 0xaf, 0xbd, 0xbe, 0xe0, 0x51, 0x46, 0x50, 0x5f, 0xf2, 0x62, 0xf8, 0x78, 0xe7, 0x49, 0xbb, - 0x0f, 0x3f, 0xde, 0x79, 0x52, 0x6f, 0x93, 0x57, 0xd4, 0xc7, 0x16, 0x13, 0x63, 0x44, 0xfe, 0xbe, - 0xec, 0x87, 0x30, 0xaf, 0x5d, 0xb2, 0xd0, 0xbd, 0x72, 0xfb, 0xd1, 0x4a, 0x9a, 0xbd, 0x5e, 0x74, - 0x2d, 0xed, 0xd0, 0xd3, 0x58, 0xc5, 0xf2, 0x17, 0x8c, 0xc4, 0xe0, 0x88, 0x55, 0xb4, 0x09, 0x15, - 0xfd, 0x02, 0x87, 0x97, 0x94, 0xbb, 0xaa, 0x25, 0xe9, 0x37, 0x59, 0x3e, 0xca, 0xb0, 0x5d, 0x68, - 0x4c, 0x5f, 0xae, 0x16, 0xf1, 0x94, 0xb4, 0x0b, 0xe9, 0xd6, 0xa6, 0x12, 0x13, 0x57, 0xb2, 0xb1, - 0x43, 0x8a, 0x18, 0x89, 0x9e, 0x16, 0xf4, 0xfc, 0xe9, 0x5d, 0x3d, 0xf9, 0xe4, 0x60, 0x54, 0x5a, - 0xda, 0x63, 0x93, 0xf7, 0x33, 0x8f, 0x32, 0xec, 0xf7, 0x32, 0x50, 0x4d, 0x5c, 0x37, 0x94, 0xf0, - 0xc9, 0x9f, 0xea, 0x67, 0x53, 0x4f, 0xd3, 0x3b, 0x6a, 0x98, 0x38, 0x88, 0xbb, 0x0f, 0x7e, 0x90, - 0x98, 0xa4, 0x9f, 0x24, 0x6c, 0x86, 0xeb, 0xd3, 0x6f, 0x0f, 0x7e, 0x31, 0x8d, 0xa0, 0x5f, 0x58, - 0xfb, 0xc5, 0xa3, 0x0c, 0xfb, 0x97, 0x19, 0xa8, 0x27, 0x9d, 0x01, 0xa2, 0xee, 0xa6, 0xba, 0x1d, - 0x44, 0xa4, 0x74, 0x8d, 0x07, 0xc1, 0x0f, 0xb1, 0x95, 0xbd, 0x07, 0x66, 0xa2, 0x95, 0xf2, 0x49, - 0x83, 0x9f, 0xaf, 0xb5, 0xec, 0x97, 0xe9, 0xa9, 0x5f, 0xe5, 0x23, 0xc5, 0x66, 0x9f, 0x86, 0x8d, - 0xc8, 0x4f, 0x7f, 0x48, 0xd5, 0xc8, 0xfd, 0x76, 0x36, 0x83, 0x33, 0xf1, 0x23, 0x7a, 0x68, 0x4f, - 0xf9, 0xdd, 0x08, 0x52, 0x7e, 0xed, 0x42, 0xde, 0xc6, 0x8e, 0xbd, 0x61, 0xdc, 0x4c, 0x74, 0x6c, - 0x5a, 0xfa, 0x68, 0x51, 0x13, 0xe5, 0x63, 0xa8, 0xf1, 0xf6, 0x39, 0xf3, 0x40, 0x6a, 0x6a, 0x25, - 0xd8, 0xc8, 0x11, 0x35, 0x52, 0xa2, 0x27, 0xd6, 0xdb, 0x6b, 0x16, 0x63, 0x3c, 0xc0, 0xb6, 0xbe, - 0x6d, 0xdc, 0xbd, 0xb6, 0xad, 0x0f, 0xd1, 0xba, 0x2f, 0x5a, 0x7c, 0x08, 0x10, 0x3b, 0x32, 0xb2, - 0x29, 0x77, 0xba, 0x88, 0x0b, 0xcd, 0xfa, 0x3a, 0x26, 0x17, 0xb5, 0xf2, 0xba, 0x13, 0x25, 0xfe, - 0x2a, 0xf1, 0xd4, 0xc8, 0xd1, 0x4f, 0x17, 0xc1, 0x92, 0x3e, 0x87, 0x09, 0x11, 0x6c, 0xba, 0xfc, - 0x04, 0x47, 0x8d, 0xbc, 0xfa, 0x8e, 0xa0, 0xb6, 0xeb, 0x79, 0x2f, 0x26, 0xe3, 0xc8, 0x79, 0x3e, - 0xe9, 0x72, 0xb3, 0x63, 0x07, 0x67, 0x6b, 0x53, 0xbd, 0x30, 0xee, 0x61, 0x51, 0x6b, 0xac, 0xa9, - 0x15, 0xf5, 0xf0, 0x27, 0xb1, 0xf7, 0xe4, 0x17, 0xcc, 0x86, 0x85, 0x88, 0x51, 0xc7, 0x1e, 0x8a, - 0xc9, 0x62, 0x12, 0xec, 0x79, 0xba, 0x8a, 0x84, 0xae, 0xa0, 0x5a, 0xfb, 0x30, 0x50, 0x65, 0x3e, - 0xca, 0xb0, 0x43, 0xa8, 0x6e, 0xf1, 0x3e, 0xde, 0xbe, 0x80, 0x8e, 0x2b, 0x8b, 0x09, 0x27, 0x08, - 0xf2, 0x78, 0x59, 0xab, 0x25, 0x80, 0xc9, 0xcd, 0x6b, 0x6c, 0x5f, 0xf9, 0xfc, 0xf3, 0x87, 0x3f, - 0x91, 0x2e, 0x31, 0x5f, 0xa8, 0xcd, 0x4b, 0xb9, 0x0c, 0x25, 0x36, 0xaf, 0x29, 0x1f, 0xa3, 0xc4, - 0xe6, 0x35, 0xe3, 0x63, 0x94, 0x18, 0x6a, 0xe5, 0xb2, 0xc4, 0x86, 0xb0, 0x30, 0xe3, 0x96, 0x14, - 0xed, 0x5b, 0xd7, 0x39, 0x33, 0xad, 0xdd, 0xbb, 0x1e, 0x21, 0x59, 0xdb, 0x83, 0x64, 0x6d, 0x5d, - 0xa8, 0xd1, 0x95, 0xb4, 0xc7, 0x9c, 0xe2, 0x30, 0xa7, 0x2e, 0x31, 0xd2, 0x83, 0x3c, 0xa7, 0x77, - 0x19, 0x4c, 0x4b, 0x8a, 0x39, 0x18, 0x89, 0xc7, 0x4e, 0xf0, 0x1d, 0x06, 0x2d, 0xf0, 0x31, 0x22, - 0xc6, 0xd9, 0x60, 0xcc, 0x88, 0x18, 0x53, 0xe2, 0x24, 0x95, 0x0e, 0xca, 0x96, 0xa3, 0xb2, 0x1f, - 0xba, 0xde, 0x80, 0x8f, 0x64, 0xa9, 0xbf, 0x0a, 0x95, 0xa7, 0x3c, 0x54, 0x91, 0x86, 0x91, 0x40, - 0x3f, 0x15, 0x7a, 0xb8, 0x96, 0x12, 0x1f, 0x9a, 0xa4, 0x4d, 0x2a, 0x99, 0x0f, 0x4e, 0x39, 0x71, - 0x42, 0xcb, 0x19, 0x7c, 0xc1, 0x7e, 0x05, 0x0b, 0x8f, 0xe2, 0xea, 0x57, 0xb4, 0x66, 0xea, 0x85, - 0xcf, 0x4f, 0xc1, 0xd3, 0x4a, 0x16, 0x6d, 0xd6, 0x04, 0x4b, 0x17, 0x2a, 0xda, 0xfd, 0x1b, 0xd1, - 0xd8, 0xcc, 0xde, 0xb7, 0x12, 0x8d, 0x4d, 0xca, 0x75, 0x1d, 0xc6, 0x7d, 0xac, 0xc7, 0x60, 0xf7, - 0xe2, 0x7a, 0xe8, 0x8a, 0x8e, 0xb8, 0xa6, 0x87, 0x3f, 0xb1, 0x47, 0xe1, 0x17, 0xec, 0x33, 0x9a, - 0x0e, 0x2d, 0x92, 0x32, 0xd6, 0x50, 0xa6, 0x83, 0x2e, 0xa3, 0xc1, 0xd2, 0x92, 0x92, 0x5a, 0x0b, - 0x55, 0x85, 0x62, 0xe3, 0x13, 0x80, 0x6e, 0xe8, 0x8d, 0xb7, 0x6c, 0x3e, 0xf2, 0xdc, 0x98, 0xa7, - 0xc7, 0xb1, 0x7d, 0x31, 0x9f, 0xd4, 0x02, 0xfc, 0xd8, 0x67, 0x9a, 0x4a, 0x97, 0x88, 0x01, 0x56, - 0x44, 0x7c, 0x6d, 0xf8, 0x5f, 0x34, 0x20, 0x29, 0x21, 0x80, 0x8f, 0x32, 0xac, 0x05, 0x10, 0xfb, - 0xbf, 0x45, 0x0a, 0xda, 0x8c, 0x6b, 0x5d, 0xc4, 0x5e, 0x53, 0x9c, 0xe5, 0x0e, 0xa1, 0x1c, 0x3b, - 0x0e, 0xad, 0xc6, 0xd7, 0x09, 0x25, 0xdc, 0x8c, 0x22, 0x71, 0x61, 0xc6, 0x69, 0xc7, 0x68, 0xe0, - 0x50, 0x01, 0x2b, 0x89, 0xa1, 0x3a, 0xe1, 0x3c, 0x60, 0x0e, 0x2c, 0x52, 0x03, 0x23, 0xd9, 0x0c, - 0x63, 0xd2, 0xa2, 0xd7, 0x4f, 0x66, 0xfd, 0x67, 0x22, 0xae, 0x91, 0xea, 0x05, 0x92, 0x38, 0x67, - 0x12, 0xd4, 0x4a, 0xf1, 0x70, 0x62, 0x0b, 0x18, 0xc1, 0xc2, 0x8c, 0xa3, 0x41, 0xc4, 0x3a, 0xae, - 0xf3, 0x1c, 0x89, 0x58, 0xc7, 0xb5, 0x3e, 0x0a, 0xc6, 0x32, 0x56, 0x39, 0x6f, 0x00, 0xea, 0x95, - 0x17, 0x4e, 0xd8, 0x3f, 0x13, 0xd5, 0xfd, 0x41, 0x06, 0x16, 0x53, 0x5c, 0x09, 0xd8, 0x9b, 0xea, - 0x88, 0xe2, 0x5a, 0x37, 0x83, 0xb5, 0x54, 0x93, 0xb3, 0xd1, 0xc5, 0x7a, 0xf6, 0xd8, 0xb3, 0xc4, - 0x06, 0x4a, 0x16, 0x5f, 0xb9, 0x32, 0x5f, 0x2a, 0xc1, 0xa4, 0x8a, 0x2f, 0x9f, 0xc3, 0x2a, 0x35, - 0xa4, 0x35, 0x1c, 0x4e, 0x99, 0xc3, 0xdf, 0xd0, 0x5a, 0x91, 0x62, 0xe2, 0x4f, 0x28, 0x03, 0x49, - 0x33, 0xff, 0x35, 0xb2, 0x3b, 0x35, 0x95, 0x4d, 0xa0, 0x31, 0x6d, 0x66, 0x66, 0xd7, 0x97, 0xb5, - 0x76, 0x37, 0xa1, 0x6c, 0xa7, 0x98, 0xa6, 0xbf, 0x86, 0x95, 0xdd, 0x35, 0xd6, 0xd2, 0xc6, 0x85, - 0xf4, 0x6f, 0x31, 0x1f, 0xff, 0x7f, 0x64, 0x13, 0x9f, 0xea, 0xe7, 0xdd, 0xe8, 0xbe, 0xf7, 0x74, - 0x0b, 0x7e, 0xa4, 0xee, 0xa7, 0x9b, 0xd4, 0xdf, 0xc1, 0xea, 0xef, 0x19, 0xb7, 0xd2, 0xaa, 0xf7, - 0x29, 0x0b, 0x29, 0xfe, 0xab, 0xd3, 0xeb, 0x5a, 0xb5, 0xe0, 0x5e, 0xda, 0x7c, 0x5f, 0xab, 0x78, - 0x4d, 0x8d, 0xf5, 0x0d, 0x94, 0x21, 0xab, 0xba, 0x0d, 0x3c, 0x5a, 0x3e, 0x29, 0xc6, 0xf6, 0x68, - 0xf9, 0xa4, 0x19, 0xcd, 0x93, 0xf2, 0x93, 0x32, 0x97, 0x7f, 0x94, 0x79, 0xb0, 0xf1, 0xee, 0x0f, - 0xbf, 0x76, 0xea, 0x84, 0x67, 0x93, 0xe3, 0xf5, 0xbe, 0x37, 0x7a, 0x38, 0x54, 0x47, 0x9b, 0x32, - 0x70, 0xfb, 0xe1, 0xd0, 0x1d, 0x3c, 0xc4, 0x62, 0x8f, 0xe7, 0xc6, 0xbe, 0x17, 0x7a, 0xdf, 0xfc, - 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x4e, 0xb1, 0xa4, 0x40, 0x5a, 0x89, 0x00, 0x00, + // 11878 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x6f, 0x24, 0x49, + 0x72, 0xd8, 0xf4, 0x8b, 0xdd, 0x1d, 0xfd, 0x60, 0x33, 0xf9, 0xea, 0xe1, 0xcc, 0xec, 0xcc, 0xd6, + 0xee, 0xed, 0xce, 0xce, 0xde, 0x71, 0x66, 0xe7, 0x6e, 0x76, 0xef, 0x76, 0xad, 0xd3, 0x35, 0xc9, + 0xe6, 0xb0, 0x6f, 0xf8, 0xda, 0xea, 0xe6, 0xae, 0xe6, 0xf4, 0xa8, 0x2b, 0x76, 0x27, 0xc9, 0xd2, + 0x74, 0x57, 0xf5, 0x56, 0x55, 0xf3, 0x71, 0x87, 0xf5, 0x07, 0xc3, 0x36, 0x04, 0xc3, 0x0f, 0x08, + 0xb6, 0x0c, 0x58, 0xb6, 0x60, 0xc3, 0x82, 0x61, 0x18, 0x06, 0x04, 0x01, 0x27, 0x7f, 0x30, 0xe0, + 0xef, 0xfa, 0xe2, 0x07, 0x0c, 0xc9, 0x5f, 0x0c, 0x41, 0x80, 0x61, 0x5b, 0xfe, 0x60, 0xc0, 0x10, + 0xe0, 0x3f, 0x60, 0x64, 0x44, 0x66, 0x55, 0x56, 0x77, 0x71, 0x66, 0xf6, 0xee, 0x7c, 0x5f, 0xc8, + 0xae, 0xc8, 0xc8, 0x77, 0x64, 0x64, 0x44, 0x46, 0x44, 0x26, 0x94, 0xfd, 0x71, 0x7f, 0x7d, 0xec, + 0x7b, 0xa1, 0xc7, 0x0a, 0x43, 0xd7, 0x1f, 0xf7, 0xd7, 0x6e, 0x9f, 0x7a, 0xde, 0xe9, 0x90, 0x3f, + 0xb4, 0xc7, 0xce, 0x43, 0xdb, 0x75, 0xbd, 0xd0, 0x0e, 0x1d, 0xcf, 0x0d, 0x08, 0xc9, 0xf8, 0x21, + 0xd4, 0x9f, 0x72, 0xb7, 0xcb, 0xf9, 0xc0, 0xe4, 0x5f, 0x4c, 0x78, 0x10, 0xb2, 0xf7, 0x61, 0xc1, + 0xe6, 0x3f, 0xe2, 0x7c, 0x60, 0x8d, 0xed, 0x20, 0x18, 0x9f, 0xf9, 0x76, 0xc0, 0x9b, 0x99, 0x7b, + 0x99, 0xfb, 0x55, 0xb3, 0x41, 0x09, 0x87, 0x11, 0x9c, 0xbd, 0x09, 0xd5, 0x40, 0xa0, 0x72, 0x37, + 0xf4, 0xbd, 0xf1, 0x55, 0x33, 0x8b, 0x78, 0x15, 0x01, 0x6b, 0x13, 0xc8, 0x18, 0xc2, 0x7c, 0x54, + 0x43, 0x30, 0xf6, 0xdc, 0x80, 0xb3, 0x47, 0xb0, 0xd4, 0x77, 0xc6, 0x67, 0xdc, 0xb7, 0x30, 0xf3, + 0xc8, 0xe5, 0x23, 0xcf, 0x75, 0xfa, 0xcd, 0xcc, 0xbd, 0xdc, 0xfd, 0xb2, 0xc9, 0x28, 0x4d, 0xe4, + 0xd8, 0x93, 0x29, 0xec, 0x5d, 0x98, 0xe7, 0x2e, 0xc1, 0xf9, 0x00, 0x73, 0xc9, 0xaa, 0xea, 0x31, + 0x58, 0x64, 0x30, 0x7e, 0x2b, 0x0b, 0x0b, 0x1d, 0xd7, 0x09, 0x3f, 0xb7, 0x87, 0x43, 0x1e, 0xaa, + 0x3e, 0xbd, 0x0b, 0xf3, 0x17, 0x08, 0xc0, 0x3e, 0x5d, 0x78, 0xfe, 0x40, 0xf6, 0xa8, 0x4e, 0xe0, + 0x43, 0x09, 0xbd, 0xb6, 0x65, 0xd9, 0x6b, 0x5b, 0x96, 0x3a, 0x5c, 0xb9, 0x6b, 0x86, 0xeb, 0x5d, + 0x98, 0xf7, 0x79, 0xdf, 0x3b, 0xe7, 0xfe, 0x95, 0x75, 0xe1, 0xb8, 0x03, 0xef, 0xa2, 0x99, 0xbf, + 0x97, 0xb9, 0x5f, 0x30, 0xeb, 0x0a, 0xfc, 0x39, 0x42, 0xd9, 0x06, 0xcc, 0xf7, 0xcf, 0x6c, 0xd7, + 0xe5, 0x43, 0xeb, 0xd8, 0xee, 0xbf, 0x98, 0x8c, 0x83, 0x66, 0xe1, 0x5e, 0xe6, 0x7e, 0xe5, 0xf1, + 0xcd, 0x75, 0x9c, 0xd5, 0xf5, 0xcd, 0x33, 0xdb, 0xdd, 0xc0, 0x94, 0xae, 0x6b, 0x8f, 0x83, 0x33, + 0x2f, 0x34, 0xeb, 0x32, 0x07, 0x81, 0x03, 0x63, 0x09, 0x98, 0x3e, 0x12, 0x34, 0xf6, 0xc6, 0xbf, + 0xce, 0xc0, 0xe2, 0x91, 0x3b, 0xf4, 0xfa, 0x2f, 0x7e, 0xca, 0x21, 0x4a, 0xe9, 0x43, 0xf6, 0x75, + 0xfb, 0x90, 0xfb, 0xaa, 0x7d, 0x58, 0x81, 0xa5, 0x64, 0x63, 0x65, 0x2f, 0x38, 0x2c, 0x8b, 0xdc, + 0xa7, 0x5c, 0x35, 0x4b, 0x75, 0xe3, 0x3d, 0x68, 0xf4, 0x27, 0xbe, 0xcf, 0xdd, 0x99, 0x7e, 0xcc, + 0x4b, 0x78, 0xd4, 0x91, 0x37, 0xa1, 0xea, 0xf2, 0x8b, 0x18, 0x4d, 0xd2, 0xae, 0xcb, 0x2f, 0x14, + 0x8a, 0xd1, 0x84, 0x95, 0xe9, 0x6a, 0x64, 0x03, 0xfe, 0x22, 0x03, 0xf9, 0xa3, 0xf0, 0xd2, 0x63, + 0x4f, 0xa0, 0x6a, 0x0f, 0x06, 0x3e, 0x0f, 0x02, 0x2b, 0xbc, 0x1a, 0xd3, 0x4a, 0xa9, 0x3f, 0x66, + 0xb2, 0x8b, 0x2d, 0x4a, 0xea, 0x5d, 0x8d, 0xb9, 0x59, 0xb1, 0xe3, 0x0f, 0xd6, 0x84, 0xa2, 0xfc, + 0xc4, 0x7a, 0xcb, 0xa6, 0xfa, 0x64, 0x77, 0x00, 0xec, 0x91, 0x37, 0x71, 0x43, 0x2b, 0xb0, 0x43, + 0x1c, 0xb1, 0x9c, 0x59, 0x26, 0x48, 0xd7, 0x0e, 0xd9, 0x2d, 0x28, 0x8f, 0x5f, 0x58, 0x41, 0xdf, + 0x77, 0xc6, 0x21, 0x12, 0x4f, 0xd9, 0x2c, 0x8d, 0x5f, 0x74, 0xf1, 0x9b, 0xbd, 0x0f, 0x25, 0x6f, + 0x12, 0x8e, 0x3d, 0xc7, 0x0d, 0x25, 0xbd, 0xcc, 0xcb, 0x86, 0x1c, 0x4c, 0xc2, 0x43, 0x01, 0x36, + 0x23, 0x04, 0xf6, 0x36, 0xd4, 0xfa, 0x9e, 0x7b, 0xe2, 0xf8, 0x23, 0xe2, 0x08, 0xcd, 0x39, 0xac, + 0x2b, 0x09, 0x34, 0xfe, 0x30, 0x0b, 0x95, 0x9e, 0x6f, 0xbb, 0x81, 0xdd, 0x17, 0x00, 0xb6, 0x0a, + 0xc5, 0xf0, 0xd2, 0x3a, 0xb3, 0x83, 0x33, 0xec, 0x6a, 0xd9, 0x9c, 0x0b, 0x2f, 0x77, 0xec, 0xe0, + 0x8c, 0xad, 0xc0, 0x1c, 0xb5, 0x12, 0x3b, 0x94, 0x33, 0xe5, 0x97, 0x58, 0x20, 0xee, 0x64, 0x64, + 0x25, 0xab, 0xca, 0x21, 0xc5, 0x34, 0xdc, 0xc9, 0x68, 0x53, 0x87, 0x8b, 0xce, 0x1f, 0x8b, 0xe9, + 0xa6, 0x0a, 0xa8, 0x7b, 0x65, 0x84, 0x60, 0x1d, 0x6f, 0x42, 0x55, 0x26, 0x73, 0xe7, 0xf4, 0x8c, + 0xfa, 0x58, 0x30, 0x2b, 0x84, 0x80, 0x20, 0x51, 0x42, 0xe8, 0x8c, 0xb8, 0x15, 0x84, 0xf6, 0x68, + 0x2c, 0xbb, 0x54, 0x16, 0x90, 0xae, 0x00, 0x60, 0xb2, 0x17, 0xda, 0x43, 0xeb, 0x84, 0xf3, 0xa0, + 0x59, 0x94, 0xc9, 0x02, 0xb2, 0xcd, 0x79, 0xc0, 0xbe, 0x06, 0xf5, 0x01, 0x0f, 0x42, 0x4b, 0x4e, + 0x06, 0x0f, 0x9a, 0x25, 0x5c, 0xf9, 0x35, 0x01, 0x6d, 0x29, 0x20, 0xbb, 0x0d, 0xe0, 0xdb, 0x17, + 0x96, 0x18, 0x08, 0x7e, 0xd9, 0x2c, 0xd3, 0x2c, 0xf8, 0xf6, 0x45, 0xef, 0x72, 0x87, 0x5f, 0x0a, + 0xaa, 0x79, 0xca, 0x43, 0x6d, 0xd0, 0x02, 0x49, 0x9d, 0xc6, 0x2e, 0x30, 0x0d, 0xbc, 0xc5, 0x43, + 0xdb, 0x19, 0x06, 0xec, 0x43, 0xa8, 0x86, 0x1a, 0x32, 0xb2, 0xc1, 0x4a, 0x44, 0x42, 0x5a, 0x06, + 0x33, 0x81, 0x67, 0x9c, 0x41, 0x69, 0x9b, 0xf3, 0x5d, 0x67, 0xe4, 0x84, 0x6c, 0x05, 0x0a, 0x27, + 0xce, 0x25, 0x27, 0x62, 0xcf, 0xed, 0xdc, 0x30, 0xe9, 0x93, 0xdd, 0x05, 0xc0, 0x1f, 0xd6, 0x28, + 0xa2, 0xa6, 0x9d, 0x1b, 0x66, 0x19, 0x61, 0x7b, 0x81, 0x1d, 0xb2, 0x35, 0x28, 0x8e, 0xb9, 0xdf, + 0xe7, 0x6a, 0xde, 0x76, 0x6e, 0x98, 0x0a, 0xb0, 0x51, 0x84, 0xc2, 0x50, 0x94, 0x6e, 0xfc, 0x71, + 0x01, 0x2a, 0x5d, 0xee, 0x46, 0xab, 0x8c, 0x41, 0x5e, 0x0c, 0x88, 0x5c, 0x59, 0xf8, 0x9b, 0xbd, + 0x05, 0x15, 0x1c, 0xba, 0x20, 0xf4, 0x1d, 0xf7, 0x94, 0xa8, 0x7a, 0x23, 0xdb, 0xcc, 0x98, 0x20, + 0xc0, 0x5d, 0x84, 0xb2, 0x06, 0xe4, 0xec, 0x91, 0xa2, 0x6a, 0xf1, 0x93, 0xdd, 0x84, 0x92, 0x3d, + 0x0a, 0xa9, 0x79, 0x55, 0x04, 0x17, 0xed, 0x51, 0x88, 0x4d, 0x7b, 0x13, 0xaa, 0x63, 0xfb, 0x6a, + 0x24, 0xd6, 0x72, 0x44, 0x0e, 0x55, 0xb3, 0x22, 0x61, 0x48, 0x10, 0x8f, 0x61, 0x51, 0x47, 0x51, + 0x95, 0x17, 0xa2, 0xca, 0x17, 0x34, 0x6c, 0xd9, 0x86, 0x77, 0x61, 0x5e, 0xe5, 0xf1, 0xa9, 0x3f, + 0x48, 0x26, 0x65, 0xb3, 0x2e, 0xc1, 0xaa, 0x97, 0xf7, 0xa1, 0x71, 0xe2, 0xb8, 0xf6, 0xd0, 0xea, + 0x0f, 0xc3, 0x73, 0x6b, 0xc0, 0x87, 0xa1, 0x8d, 0x14, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1c, 0x86, + 0xe7, 0x5b, 0x02, 0xca, 0xbe, 0x0e, 0xe5, 0x13, 0xce, 0x2d, 0x1c, 0xac, 0x66, 0x29, 0xb1, 0xf0, + 0xd4, 0x0c, 0x99, 0xa5, 0x13, 0x35, 0x57, 0x5f, 0x87, 0x86, 0x37, 0x09, 0x4f, 0x3d, 0xc7, 0x3d, + 0xb5, 0x04, 0xbf, 0xb3, 0x9c, 0x01, 0xd2, 0x50, 0x7e, 0x23, 0xfb, 0x28, 0x63, 0xd6, 0x55, 0x9a, + 0xe0, 0x3c, 0x9d, 0x01, 0x7b, 0x07, 0xe6, 0x87, 0x76, 0x10, 0x5a, 0x67, 0xde, 0xd8, 0x1a, 0x4f, + 0x8e, 0x5f, 0xf0, 0xab, 0x66, 0x0d, 0x07, 0xa2, 0x26, 0xc0, 0x3b, 0xde, 0xf8, 0x10, 0x81, 0x82, + 0xb2, 0xb1, 0x9d, 0xd4, 0x08, 0xb8, 0x97, 0xb9, 0x5f, 0x33, 0xcb, 0x02, 0x42, 0x95, 0x3e, 0x87, + 0x45, 0x9c, 0x9e, 0xfe, 0x24, 0x08, 0xbd, 0x91, 0x25, 0x78, 0xb5, 0x3f, 0x08, 0x9a, 0x15, 0xa4, + 0xb5, 0xf7, 0x64, 0x63, 0xb5, 0x39, 0x5e, 0xdf, 0xe2, 0x41, 0xb8, 0x89, 0xc8, 0x26, 0xe1, 0x8a, + 0x0d, 0xfd, 0xca, 0x5c, 0x18, 0x4c, 0xc3, 0xd9, 0xd7, 0x81, 0xd9, 0xc3, 0xa1, 0x77, 0x61, 0x05, + 0x7c, 0x78, 0x62, 0xc9, 0x41, 0x6c, 0xd6, 0xef, 0x65, 0xee, 0x97, 0xcc, 0x06, 0xa6, 0x74, 0xf9, + 0xf0, 0xe4, 0x90, 0xe0, 0xec, 0x43, 0xc0, 0xc5, 0x64, 0x9d, 0x70, 0x3b, 0x9c, 0xf8, 0x3c, 0x68, + 0xce, 0xdf, 0xcb, 0xdd, 0xaf, 0x3f, 0x5e, 0x88, 0xc6, 0x0b, 0xc1, 0x1b, 0x4e, 0x68, 0x56, 0x05, + 0x9e, 0xfc, 0x0e, 0xd6, 0xb6, 0x60, 0x25, 0xbd, 0x49, 0x82, 0xa8, 0xc4, 0xa8, 0x08, 0x62, 0xcc, + 0x9b, 0xe2, 0x27, 0x5b, 0x82, 0xc2, 0xb9, 0x3d, 0x9c, 0x70, 0xc9, 0xd3, 0xe9, 0xe3, 0xe3, 0xec, + 0xb7, 0x33, 0xc6, 0x1f, 0x65, 0xa0, 0x4a, 0xbd, 0x94, 0xb2, 0xc8, 0x5b, 0x50, 0x53, 0xd4, 0xc0, + 0x7d, 0xdf, 0xf3, 0x25, 0x57, 0x53, 0x94, 0xd7, 0x16, 0x30, 0xb1, 0xab, 0x28, 0xa4, 0xb1, 0xcf, + 0x9d, 0x91, 0x7d, 0xaa, 0x8a, 0x56, 0xa4, 0x74, 0x28, 0xc1, 0xec, 0x83, 0xb8, 0x3c, 0xdf, 0x9b, + 0x84, 0x5c, 0xee, 0x79, 0x55, 0xd9, 0x3d, 0x53, 0xc0, 0xa2, 0xd2, 0xf1, 0xeb, 0x35, 0xe8, 0xdc, + 0xf8, 0x9d, 0x0c, 0x30, 0xd1, 0xec, 0x9e, 0x47, 0x05, 0x48, 0x0a, 0x9d, 0xce, 0x99, 0x79, 0xed, + 0x15, 0x92, 0x7d, 0xd9, 0x0a, 0x31, 0xa0, 0x40, 0x6d, 0xcf, 0xa7, 0xb4, 0x9d, 0x92, 0xbe, 0x9f, + 0x2f, 0xe5, 0x1a, 0x79, 0xe3, 0xbf, 0xe6, 0x60, 0x69, 0x93, 0xb6, 0xec, 0x56, 0xbf, 0xcf, 0xc7, + 0xd1, 0xda, 0xb9, 0x0b, 0x15, 0xd7, 0x1b, 0x70, 0x45, 0xb1, 0xd4, 0x30, 0x10, 0x20, 0x8d, 0x5c, + 0xcf, 0x6c, 0xc7, 0xa5, 0x86, 0xd3, 0x60, 0x96, 0x11, 0x82, 0xcd, 0x7e, 0x07, 0xe6, 0xc7, 0xdc, + 0x1d, 0xe8, 0x4b, 0x84, 0x84, 0xaa, 0x9a, 0x04, 0xcb, 0xd5, 0x71, 0x17, 0x2a, 0x27, 0x13, 0xc2, + 0x13, 0x8c, 0x25, 0x8f, 0x34, 0x00, 0x12, 0xd4, 0x22, 0xfe, 0x32, 0x9e, 0x04, 0x67, 0x98, 0x5a, + 0xc0, 0xd4, 0xa2, 0xf8, 0x16, 0x49, 0x77, 0x00, 0x06, 0x93, 0x20, 0x94, 0x2b, 0x66, 0x0e, 0x13, + 0xcb, 0x02, 0x42, 0x2b, 0xe6, 0x1b, 0xb0, 0x38, 0xb2, 0x2f, 0x2d, 0xa4, 0x1d, 0xcb, 0x71, 0xad, + 0x93, 0x21, 0xee, 0x39, 0x45, 0xc4, 0x6b, 0x8c, 0xec, 0xcb, 0xcf, 0x44, 0x4a, 0xc7, 0xdd, 0x46, + 0xb8, 0x60, 0x2b, 0x4a, 0xdc, 0xf1, 0x79, 0xc0, 0xfd, 0x73, 0x8e, 0x9c, 0x20, 0x1f, 0xc9, 0x34, + 0x26, 0x41, 0x45, 0x8b, 0x46, 0xa2, 0xdf, 0xe1, 0xb0, 0x4f, 0xcb, 0xde, 0x2c, 0x8e, 0x1c, 0x77, + 0x27, 0x1c, 0xf6, 0xc5, 0xbe, 0x22, 0xf8, 0xc8, 0x98, 0xfb, 0xd6, 0x8b, 0x0b, 0x5c, 0xc3, 0x79, + 0xe4, 0x1b, 0x87, 0xdc, 0x7f, 0x76, 0x21, 0xb6, 0xfe, 0x7e, 0x80, 0x8c, 0xc8, 0xbe, 0x6a, 0x56, + 0x70, 0x81, 0x97, 0xfa, 0x81, 0x60, 0x41, 0xf6, 0x95, 0x58, 0x84, 0xa2, 0xb5, 0x36, 0xce, 0x02, + 0x1f, 0x60, 0xf1, 0x01, 0x72, 0xd4, 0x1a, 0x36, 0xb6, 0x25, 0x13, 0x44, 0x3d, 0x81, 0xa0, 0x7a, + 0xd5, 0xd8, 0x93, 0xa1, 0x7d, 0x1a, 0x20, 0x4b, 0xa9, 0x99, 0x55, 0x09, 0xdc, 0x16, 0x30, 0xe3, + 0x73, 0x12, 0xb2, 0xb4, 0xb9, 0x95, 0x6b, 0x46, 0x6c, 0xf5, 0x08, 0xc1, 0x79, 0x2d, 0x99, 0xf2, + 0x2b, 0x6d, 0xd2, 0xb2, 0x29, 0x93, 0x66, 0xfc, 0x5e, 0x06, 0xaa, 0xb2, 0x64, 0x14, 0x4a, 0xd8, + 0x3a, 0x30, 0x35, 0x8b, 0xe1, 0xa5, 0x33, 0xb0, 0x8e, 0xaf, 0x42, 0x1e, 0x10, 0xd1, 0xec, 0xdc, + 0x30, 0x1b, 0x32, 0xad, 0x77, 0xe9, 0x0c, 0x36, 0x44, 0x0a, 0x7b, 0x00, 0x8d, 0x04, 0x7e, 0x10, + 0xfa, 0x44, 0xd1, 0x3b, 0x37, 0xcc, 0xba, 0x86, 0xdd, 0x0d, 0x7d, 0xb1, 0x46, 0x84, 0xc8, 0x33, + 0x09, 0x2d, 0xc7, 0x1d, 0xf0, 0x4b, 0x24, 0xa3, 0x9a, 0x59, 0x21, 0x58, 0x47, 0x80, 0x36, 0xea, + 0x50, 0xd5, 0x8b, 0x33, 0x4e, 0xa1, 0xa4, 0xe4, 0x25, 0x14, 0x18, 0xa6, 0x9a, 0x64, 0x96, 0xc3, + 0xa8, 0x25, 0x37, 0xa1, 0x94, 0x6c, 0x81, 0x59, 0x0c, 0x5f, 0xbb, 0x62, 0xe3, 0xbb, 0xd0, 0xd8, + 0x15, 0xc4, 0xe3, 0x0a, 0x62, 0x95, 0xf2, 0xdf, 0x0a, 0xcc, 0x69, 0x8b, 0xa6, 0x6c, 0xca, 0x2f, + 0xb1, 0xe7, 0x9e, 0x79, 0x41, 0x28, 0x6b, 0xc1, 0xdf, 0xc6, 0x1f, 0x67, 0x80, 0xb5, 0x83, 0xd0, + 0x19, 0xd9, 0x21, 0xdf, 0xe6, 0x11, 0x5b, 0x38, 0x80, 0xaa, 0x28, 0xad, 0xe7, 0xb5, 0x48, 0x20, + 0x23, 0x81, 0xe2, 0x7d, 0xb9, 0x8c, 0x67, 0x33, 0xac, 0xeb, 0xd8, 0xc4, 0xe6, 0x13, 0x05, 0x88, + 0x55, 0x16, 0xda, 0xfe, 0x29, 0x0f, 0x51, 0x8c, 0x93, 0xf2, 0x3e, 0x10, 0x48, 0x08, 0x70, 0x6b, + 0xbf, 0x0c, 0x0b, 0x33, 0x65, 0xe8, 0x7c, 0xb9, 0x9c, 0xc2, 0x97, 0x73, 0x3a, 0x5f, 0xb6, 0x60, + 0x31, 0xd1, 0x2e, 0x49, 0x69, 0xab, 0x50, 0x14, 0x0b, 0x42, 0x08, 0x07, 0x19, 0x92, 0x2a, 0x4f, + 0x38, 0x17, 0x62, 0xf0, 0x43, 0x58, 0x3a, 0xe1, 0xdc, 0xb7, 0x43, 0x4c, 0xc4, 0x15, 0x23, 0x66, + 0x48, 0x16, 0xbc, 0x20, 0xd3, 0xba, 0x76, 0x78, 0xc8, 0x7d, 0x31, 0x53, 0xc6, 0x7f, 0xcf, 0xc0, + 0xbc, 0xe0, 0xa0, 0x7b, 0xb6, 0x7b, 0xa5, 0xc6, 0x69, 0x37, 0x75, 0x9c, 0xee, 0x6b, 0x9b, 0xa1, + 0x86, 0xfd, 0x55, 0x07, 0x29, 0x37, 0x3d, 0x48, 0xec, 0x1e, 0x54, 0x13, 0x6d, 0x2d, 0x60, 0x5b, + 0x21, 0x88, 0x1a, 0xf9, 0xb3, 0x0f, 0xe3, 0x3b, 0xd0, 0x88, 0x9b, 0x2d, 0xc7, 0x90, 0x41, 0x5e, + 0x90, 0xa4, 0x2c, 0x00, 0x7f, 0x1b, 0xff, 0x24, 0x43, 0x88, 0x9b, 0x9e, 0x13, 0x49, 0xa7, 0x02, + 0x51, 0xc8, 0xbd, 0x0a, 0x51, 0xfc, 0xbe, 0x56, 0xaa, 0xff, 0xd9, 0x3b, 0x2b, 0x96, 0x4e, 0xc0, + 0xdd, 0x81, 0x65, 0x0f, 0x87, 0xc8, 0x7c, 0x4b, 0x66, 0x51, 0x7c, 0xb7, 0x86, 0x43, 0xe3, 0x5d, + 0x58, 0xd0, 0x5a, 0xf7, 0x92, 0x7e, 0xec, 0x03, 0xdb, 0x75, 0x82, 0xf0, 0xc8, 0x0d, 0xc6, 0x9a, + 0xe0, 0x76, 0x0b, 0xca, 0x82, 0xc3, 0x8a, 0x96, 0xd1, 0x92, 0x2d, 0x98, 0x82, 0xe5, 0x8a, 0x76, + 0x05, 0x98, 0x68, 0x5f, 0xca, 0xc4, 0xac, 0x4c, 0xb4, 0x2f, 0x31, 0xd1, 0xf8, 0x36, 0x2c, 0x26, + 0xca, 0x93, 0x55, 0xbf, 0x09, 0x85, 0x49, 0x78, 0xe9, 0x29, 0xd1, 0xbc, 0x22, 0x29, 0x44, 0x28, + 0x80, 0x26, 0xa5, 0x18, 0x9f, 0xc0, 0xc2, 0x3e, 0xbf, 0x90, 0x8b, 0x58, 0x35, 0xe4, 0x1d, 0xc8, + 0xbf, 0x42, 0x29, 0xc4, 0x74, 0x63, 0x1d, 0x98, 0x9e, 0x59, 0xd6, 0xaa, 0xe9, 0x88, 0x99, 0x84, + 0x8e, 0x68, 0xbc, 0x03, 0xac, 0xeb, 0x9c, 0xba, 0x7b, 0x3c, 0x08, 0xec, 0xd3, 0x68, 0xd9, 0x37, + 0x20, 0x37, 0x0a, 0x4e, 0x25, 0x8f, 0x12, 0x3f, 0x8d, 0x6f, 0xc2, 0x62, 0x02, 0x4f, 0x16, 0x7c, + 0x1b, 0xca, 0x81, 0x73, 0xea, 0xa2, 0x60, 0x25, 0x8b, 0x8e, 0x01, 0xc6, 0x36, 0x2c, 0x7d, 0xc6, + 0x7d, 0xe7, 0xe4, 0xea, 0x55, 0xc5, 0x27, 0xcb, 0xc9, 0x4e, 0x97, 0xd3, 0x86, 0xe5, 0xa9, 0x72, + 0x64, 0xf5, 0x44, 0xbe, 0x72, 0x26, 0x4b, 0x26, 0x7d, 0x68, 0x7c, 0x2f, 0xab, 0xf3, 0x3d, 0xe3, + 0x08, 0xd8, 0xa6, 0xe7, 0xba, 0xbc, 0x1f, 0x1e, 0x72, 0xee, 0xc7, 0xa7, 0x54, 0x31, 0xad, 0x56, + 0x1e, 0xaf, 0xca, 0x91, 0x9d, 0x66, 0xa6, 0x92, 0x88, 0x19, 0xe4, 0xc7, 0xdc, 0x1f, 0x61, 0xc1, + 0x25, 0x13, 0x7f, 0x1b, 0xcb, 0xb0, 0x98, 0x28, 0x56, 0xea, 0xf5, 0x8f, 0x60, 0x79, 0xcb, 0x09, + 0xfa, 0xb3, 0x15, 0xae, 0x42, 0x71, 0x3c, 0x39, 0xb6, 0x92, 0x7c, 0xf9, 0x19, 0xbf, 0x12, 0xda, + 0xde, 0x74, 0x0e, 0x59, 0xd6, 0x5f, 0xcf, 0x40, 0x7e, 0xa7, 0xb7, 0xbb, 0xc9, 0xd6, 0xa0, 0xe4, + 0xb8, 0x7d, 0x6f, 0x24, 0x04, 0x2f, 0xea, 0x73, 0xf4, 0x7d, 0xed, 0x02, 0xbb, 0x05, 0x65, 0x94, + 0xd7, 0x84, 0x6a, 0x2b, 0x45, 0x9f, 0x92, 0x00, 0xec, 0x7a, 0xfd, 0x17, 0x42, 0xa7, 0xe6, 0x97, + 0x63, 0xc7, 0x47, 0xad, 0x59, 0x29, 0xc3, 0x79, 0xda, 0xeb, 0xe3, 0x04, 0xd2, 0x88, 0x8d, 0x7f, + 0x5b, 0x82, 0xa2, 0xdc, 0x6d, 0x69, 0xe7, 0x0e, 0x9d, 0x73, 0x1e, 0xef, 0xdc, 0xe2, 0x4b, 0xc8, + 0x03, 0x3e, 0x1f, 0x79, 0x61, 0x24, 0xb0, 0xd1, 0x1c, 0x54, 0x09, 0x28, 0x45, 0x36, 0x4d, 0x68, + 0xa0, 0x23, 0x86, 0x1c, 0x21, 0xf5, 0xf5, 0xad, 0xfc, 0x16, 0x14, 0xd5, 0xde, 0x9f, 0x8f, 0x74, + 0x9a, 0xb9, 0x3e, 0x49, 0x6b, 0x6b, 0x50, 0xea, 0xdb, 0x63, 0xbb, 0xef, 0x84, 0x57, 0x92, 0x21, + 0x44, 0xdf, 0xa2, 0xf4, 0xa1, 0xd7, 0xb7, 0x87, 0xd6, 0xb1, 0x3d, 0xb4, 0xdd, 0x3e, 0x97, 0xba, + 0x7b, 0x15, 0x81, 0x1b, 0x04, 0x13, 0xfa, 0xb9, 0x6c, 0xa7, 0xc2, 0x22, 0x15, 0x5e, 0xb6, 0x5e, + 0xa1, 0x09, 0xe1, 0xd2, 0x1b, 0x8d, 0x1c, 0xa1, 0x65, 0x90, 0x18, 0x96, 0x33, 0xcb, 0x04, 0xd9, + 0xe6, 0xd8, 0x5b, 0x99, 0x7c, 0x41, 0x43, 0x57, 0xa6, 0xaa, 0x08, 0xf8, 0x39, 0x1d, 0x24, 0xcc, + 0xca, 0x62, 0x39, 0x4d, 0x16, 0x7b, 0x1f, 0x16, 0x26, 0x6e, 0xc0, 0xc3, 0x70, 0xc8, 0x07, 0x51, + 0x5b, 0x2a, 0x88, 0xd4, 0x88, 0x12, 0x54, 0x73, 0xd6, 0x61, 0x91, 0x0e, 0x1d, 0x02, 0x3b, 0xf4, + 0x82, 0x33, 0x27, 0xb0, 0x02, 0xa1, 0x21, 0x91, 0xba, 0xbb, 0x80, 0x49, 0x5d, 0x99, 0xd2, 0x25, + 0x15, 0x69, 0x75, 0x0a, 0xdf, 0xe7, 0x7d, 0xee, 0x9c, 0xf3, 0x01, 0xca, 0x69, 0x39, 0x73, 0x39, + 0x91, 0xc7, 0x94, 0x89, 0x28, 0x74, 0x4f, 0x46, 0xd6, 0x64, 0x3c, 0xb0, 0x85, 0xb0, 0x52, 0x27, + 0x61, 0xd8, 0x9d, 0x8c, 0x8e, 0x08, 0xc2, 0x1e, 0x81, 0x92, 0xc4, 0xa4, 0x7c, 0x38, 0x9f, 0xe0, + 0x67, 0x82, 0x58, 0xcd, 0xaa, 0xc4, 0x20, 0x41, 0x31, 0x21, 0x73, 0x36, 0xa6, 0x64, 0xce, 0x26, + 0x14, 0xc7, 0xbe, 0x73, 0x6e, 0x87, 0xbc, 0xb9, 0x40, 0x0c, 0x5c, 0x7e, 0x0a, 0xce, 0xe0, 0xb8, + 0x4e, 0xe8, 0xd8, 0xa1, 0xe7, 0x37, 0x19, 0xa6, 0xc5, 0x00, 0xf6, 0x00, 0x16, 0x90, 0x46, 0x82, + 0xd0, 0x0e, 0x27, 0x81, 0x94, 0x40, 0x17, 0x91, 0x98, 0x50, 0x86, 0xee, 0x22, 0x1c, 0x85, 0x50, + 0xf6, 0x4d, 0x58, 0x21, 0xb2, 0xc0, 0x1c, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x09, 0x87, 0x62, 0x11, + 0x53, 0x05, 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0x4f, 0x60, 0x55, 0x92, 0xc9, 0x4c, 0xae, 0x65, + 0xcc, 0xb5, 0x44, 0xc9, 0x53, 0xd9, 0xd6, 0x61, 0x41, 0x34, 0xc9, 0xe9, 0x5b, 0x32, 0xb7, 0x58, + 0x09, 0x2b, 0xa2, 0xf5, 0xa8, 0x29, 0xcd, 0x53, 0xa2, 0x89, 0x69, 0xcf, 0xf8, 0x15, 0xfb, 0x2e, + 0xcc, 0x13, 0xc9, 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x0d, 0x39, 0xfd, 0xb2, 0x3a, 0xe1, 0x8c, 0x52, + 0x91, 0xd9, 0xd7, 0xfb, 0x89, 0x6f, 0xb1, 0x1c, 0x86, 0xce, 0x09, 0x0f, 0x9d, 0x11, 0x6f, 0xae, + 0x12, 0x81, 0xa9, 0x6f, 0xb1, 0x52, 0x27, 0x63, 0x4c, 0x69, 0x12, 0x5f, 0xa0, 0x2f, 0xa4, 0xdd, + 0xa1, 0x17, 0x70, 0x75, 0x44, 0xd5, 0xbc, 0x29, 0x17, 0xa1, 0x00, 0x2a, 0x19, 0x52, 0x08, 0xe2, + 0xa4, 0xf4, 0x44, 0x07, 0x89, 0xb7, 0x90, 0x18, 0x6a, 0xa4, 0xfb, 0xa8, 0xc3, 0x44, 0xb1, 0x8b, + 0x9f, 0xd9, 0x17, 0x8a, 0x83, 0xdc, 0xc6, 0xf9, 0x05, 0x01, 0x92, 0xbc, 0xe3, 0x27, 0x19, 0xda, + 0x10, 0x25, 0xff, 0x08, 0x34, 0xf5, 0x8e, 0x38, 0x87, 0xe5, 0xb9, 0xc3, 0x2b, 0xc9, 0x4c, 0x80, + 0x40, 0x07, 0xee, 0x10, 0x57, 0xb3, 0xe3, 0xea, 0x28, 0xc4, 0x7b, 0xab, 0x0a, 0x88, 0x48, 0x77, + 0xa1, 0x32, 0x9e, 0x1c, 0x0f, 0x9d, 0x3e, 0xa1, 0xe4, 0xa8, 0x14, 0x02, 0x21, 0x82, 0xd0, 0x6f, + 0x89, 0xa2, 0x08, 0x23, 0x8f, 0x18, 0x15, 0x09, 0x43, 0x14, 0xe4, 0xed, 0xdc, 0x47, 0x76, 0x52, + 0x35, 0xf1, 0xb7, 0xb1, 0x01, 0x4b, 0xc9, 0x46, 0xcb, 0x8d, 0xe7, 0x01, 0x94, 0x24, 0xaf, 0x52, + 0x07, 0x1f, 0x75, 0xed, 0x28, 0x5a, 0xa8, 0x68, 0x51, 0xba, 0xf1, 0xfb, 0x05, 0x58, 0x94, 0xd0, + 0x4d, 0x31, 0xb4, 0xdd, 0xc9, 0x68, 0x64, 0xfb, 0x29, 0x4c, 0x30, 0xf3, 0x72, 0x26, 0x98, 0x9d, + 0x61, 0x82, 0x49, 0xcd, 0x97, 0x78, 0x68, 0x52, 0xf3, 0x15, 0x73, 0x49, 0xca, 0x88, 0x7e, 0x0e, + 0x5a, 0x93, 0xe0, 0x1e, 0x9d, 0xb7, 0xce, 0xb0, 0xec, 0x42, 0x0a, 0xcb, 0xd6, 0x19, 0xee, 0xdc, + 0x14, 0xc3, 0x7d, 0x13, 0x88, 0x68, 0xd4, 0xec, 0x17, 0x49, 0x3f, 0x41, 0x98, 0x3c, 0x4c, 0x7d, + 0x17, 0xe6, 0xa7, 0x79, 0x1c, 0x31, 0xd3, 0x7a, 0x0a, 0x87, 0x73, 0x46, 0x1c, 0x77, 0x2b, 0x0d, + 0xb9, 0x2c, 0x39, 0x9c, 0x33, 0xe2, 0xbb, 0x98, 0xa2, 0xf0, 0xdb, 0x00, 0x54, 0x37, 0x2e, 0x1a, + 0xc0, 0x45, 0xf3, 0x4e, 0x72, 0x2e, 0xf4, 0x51, 0x5f, 0x17, 0x1f, 0x13, 0x9f, 0xe3, 0x2a, 0x2a, + 0x63, 0x4e, 0x5c, 0x40, 0x1f, 0x41, 0xdd, 0x1b, 0x73, 0xd7, 0x8a, 0x79, 0x4d, 0x05, 0x8b, 0x6a, + 0xc8, 0xa2, 0x3a, 0x0a, 0x6e, 0xd6, 0x04, 0x5e, 0xf4, 0xc9, 0xbe, 0x43, 0x83, 0xcc, 0xb5, 0x9c, + 0xd5, 0x6b, 0x72, 0xd6, 0x11, 0x31, 0xfa, 0x36, 0xfe, 0x56, 0x06, 0x2a, 0x5a, 0x73, 0xd8, 0x32, + 0x2c, 0x6c, 0x1e, 0x1c, 0x1c, 0xb6, 0xcd, 0x56, 0xaf, 0xf3, 0x59, 0xdb, 0xda, 0xdc, 0x3d, 0xe8, + 0xb6, 0x1b, 0x37, 0x04, 0x78, 0xf7, 0x60, 0xb3, 0xb5, 0x6b, 0x6d, 0x1f, 0x98, 0x9b, 0x0a, 0x9c, + 0x61, 0x2b, 0xc0, 0xcc, 0xf6, 0xde, 0x41, 0xaf, 0x9d, 0x80, 0x67, 0x59, 0x03, 0xaa, 0x1b, 0x66, + 0xbb, 0xb5, 0xb9, 0x23, 0x21, 0x39, 0xb6, 0x04, 0x8d, 0xed, 0xa3, 0xfd, 0xad, 0xce, 0xfe, 0x53, + 0x6b, 0xb3, 0xb5, 0xbf, 0xd9, 0xde, 0x6d, 0x6f, 0x35, 0xf2, 0xac, 0x06, 0xe5, 0xd6, 0x46, 0x6b, + 0x7f, 0xeb, 0x60, 0xbf, 0xbd, 0xd5, 0x28, 0x18, 0x7f, 0x9e, 0x81, 0x65, 0x1c, 0xa8, 0xc1, 0xf4, + 0x0a, 0xbd, 0x07, 0x95, 0xbe, 0xe7, 0x8d, 0x85, 0x1a, 0x14, 0x6f, 0xf7, 0x3a, 0x48, 0xac, 0x3e, + 0xe2, 0xac, 0x27, 0x9e, 0xdf, 0xe7, 0x72, 0x81, 0x02, 0x82, 0xb6, 0x05, 0x44, 0x10, 0x88, 0xa4, + 0x30, 0xc2, 0xa0, 0xf5, 0x59, 0x21, 0x18, 0xa1, 0xac, 0xc0, 0xdc, 0xb1, 0xcf, 0xed, 0xfe, 0x99, + 0x5c, 0x9a, 0xf2, 0x8b, 0xbd, 0x17, 0x2b, 0xe8, 0x7d, 0x31, 0xe1, 0x43, 0x3e, 0x40, 0xfa, 0x2c, + 0x99, 0xf3, 0x12, 0xbe, 0x29, 0xc1, 0x62, 0xab, 0xb0, 0x8f, 0x6d, 0x77, 0xe0, 0xb9, 0x7c, 0x20, + 0xf5, 0x80, 0x18, 0x60, 0x1c, 0xc2, 0xca, 0x74, 0xff, 0xe4, 0x62, 0xfe, 0x50, 0x5b, 0xcc, 0x24, + 0x96, 0xaf, 0x5d, 0x4f, 0x40, 0xda, 0xc2, 0xfe, 0x3b, 0x79, 0xc8, 0x0b, 0x31, 0xed, 0x5a, 0x89, + 0x4e, 0x97, 0xbb, 0x73, 0x33, 0xb6, 0x19, 0x3c, 0x07, 0xa0, 0xfd, 0x9b, 0x0e, 0x9b, 0xca, 0x08, + 0xc1, 0x7d, 0x3b, 0x4a, 0xf6, 0x79, 0xff, 0x5c, 0x9e, 0x36, 0x51, 0xb2, 0xc9, 0xfb, 0xe7, 0xa8, + 0xf0, 0xd8, 0x21, 0xe5, 0xa5, 0xc5, 0x58, 0x0c, 0xec, 0x10, 0x73, 0xca, 0x24, 0xcc, 0x57, 0x8c, + 0x92, 0x30, 0x57, 0x13, 0x8a, 0x8e, 0x7b, 0xec, 0x4d, 0xdc, 0x01, 0xae, 0xbd, 0x92, 0xa9, 0x3e, + 0xd1, 0x14, 0x84, 0x6c, 0x42, 0xec, 0x12, 0xb4, 0xd4, 0x4a, 0x02, 0xd0, 0x13, 0xfb, 0xc4, 0x07, + 0x50, 0x0e, 0xae, 0xdc, 0xbe, 0xbe, 0xc0, 0x96, 0xe4, 0xf8, 0x88, 0xde, 0xaf, 0x77, 0xaf, 0xdc, + 0x3e, 0x2e, 0xa7, 0x52, 0x20, 0x7f, 0xb1, 0x27, 0x50, 0x8a, 0x0e, 0x65, 0x89, 0x3d, 0xde, 0xd4, + 0x73, 0xa8, 0x93, 0x58, 0xd2, 0x7d, 0x23, 0x54, 0xf6, 0x10, 0xe6, 0xf0, 0xe4, 0x34, 0x68, 0x56, + 0x31, 0x93, 0x12, 0xc6, 0x45, 0x33, 0xd0, 0x0a, 0xc3, 0x07, 0x78, 0x8a, 0x6a, 0x4a, 0xb4, 0xb5, + 0x67, 0x50, 0x4b, 0x94, 0xa5, 0x6b, 0xb8, 0x35, 0xd2, 0x70, 0xdf, 0xd6, 0x35, 0xdc, 0x98, 0x4d, + 0xcb, 0x6c, 0xba, 0xc6, 0xfb, 0xcb, 0x50, 0x52, 0x5d, 0x11, 0x8b, 0xe8, 0x68, 0xff, 0xd9, 0xfe, + 0xc1, 0xe7, 0xfb, 0x56, 0xf7, 0xf9, 0xfe, 0x66, 0xe3, 0x06, 0x9b, 0x87, 0x4a, 0x6b, 0x13, 0xd7, + 0x25, 0x02, 0x32, 0x02, 0xe5, 0xb0, 0xd5, 0xed, 0x46, 0x90, 0xac, 0xb1, 0x0d, 0x8d, 0xe9, 0x96, + 0x0a, 0x9a, 0x0c, 0x15, 0x4c, 0x9e, 0x2b, 0xc7, 0x00, 0xa1, 0xbf, 0xd0, 0x51, 0x31, 0x09, 0xc9, + 0xf4, 0x61, 0x3c, 0x81, 0x86, 0xd8, 0x74, 0xc4, 0x50, 0x05, 0xda, 0xf9, 0xec, 0x50, 0x08, 0x5e, + 0xfa, 0xd9, 0x72, 0xc9, 0xac, 0x10, 0x0c, 0xab, 0x32, 0x3e, 0x84, 0x05, 0x2d, 0x5b, 0xac, 0x6f, + 0x8a, 0x8d, 0x6c, 0x5a, 0xdf, 0x44, 0xed, 0x82, 0x52, 0x8c, 0x55, 0x58, 0x16, 0x9f, 0xed, 0x73, + 0xee, 0x86, 0xdd, 0xc9, 0x31, 0x19, 0x04, 0x1d, 0xcf, 0x15, 0x5a, 0x47, 0x39, 0x4a, 0xb9, 0x9e, + 0xc8, 0xd7, 0xa5, 0x6a, 0x9a, 0x45, 0xd2, 0x58, 0xd3, 0x6a, 0xc0, 0x8c, 0xeb, 0xf8, 0x37, 0xa1, + 0xa2, 0x96, 0x23, 0x90, 0x18, 0xd6, 0xc3, 0x76, 0xdb, 0xb4, 0x0e, 0xf6, 0x77, 0x3b, 0xfb, 0x82, + 0xdb, 0x89, 0x61, 0x45, 0xc0, 0xf6, 0x36, 0x42, 0x32, 0x46, 0x03, 0xea, 0x4f, 0x79, 0xd8, 0x71, + 0x4f, 0x3c, 0x65, 0xfc, 0xfa, 0x8b, 0x02, 0xcc, 0x47, 0xa0, 0x58, 0xc5, 0x3d, 0xe7, 0x7e, 0xe0, + 0x78, 0x2e, 0x4a, 0xab, 0x65, 0x53, 0x7d, 0x8a, 0xad, 0xc7, 0x19, 0x70, 0x37, 0x74, 0xc2, 0x2b, + 0x2b, 0x71, 0x1e, 0x56, 0x57, 0x60, 0xb9, 0xc5, 0x2d, 0x41, 0xc1, 0x1e, 0x3a, 0xb6, 0xb2, 0xa3, + 0xd2, 0x87, 0x80, 0xf6, 0xbd, 0xa1, 0xe7, 0xa3, 0x60, 0x5a, 0x36, 0xe9, 0x83, 0x3d, 0x82, 0x25, + 0x21, 0x20, 0xeb, 0x87, 0x94, 0xc8, 0x3f, 0xe8, 0x68, 0x8e, 0xb9, 0x93, 0xd1, 0x61, 0x7c, 0x50, + 0x29, 0x52, 0xc4, 0xc6, 0x26, 0x72, 0x48, 0x49, 0x26, 0xca, 0x40, 0xba, 0xd6, 0x82, 0x3b, 0x19, + 0xb5, 0x30, 0x25, 0xc2, 0x7f, 0x0c, 0xcb, 0x02, 0x3f, 0x92, 0x7d, 0xa2, 0x1c, 0xf3, 0x98, 0x43, + 0x14, 0xd6, 0x91, 0x69, 0x51, 0x9e, 0x5b, 0x50, 0xa6, 0x56, 0x89, 0x19, 0x2f, 0x90, 0x8c, 0x8d, + 0x4d, 0xe1, 0x7e, 0x30, 0x63, 0xf2, 0x9c, 0xa3, 0x5d, 0x7a, 0xca, 0xe4, 0xa9, 0x19, 0x4d, 0x4b, + 0xd3, 0x46, 0xd3, 0xc7, 0xb0, 0x7c, 0x2c, 0x48, 0xf0, 0x8c, 0xdb, 0x03, 0xee, 0x5b, 0x31, 0x61, + 0x93, 0x2e, 0xb1, 0x28, 0x12, 0x77, 0x30, 0x2d, 0x5a, 0x07, 0x42, 0x08, 0x11, 0x6c, 0x81, 0x0f, + 0xac, 0xd0, 0xb3, 0x50, 0x36, 0x41, 0x06, 0x53, 0x32, 0x6b, 0x04, 0xee, 0x79, 0x9b, 0x02, 0x98, + 0xc4, 0x3b, 0xf5, 0xed, 0xf1, 0x99, 0x94, 0xf6, 0x23, 0xbc, 0xa7, 0x02, 0xc8, 0x6e, 0x43, 0x51, + 0x90, 0xbc, 0xcb, 0xc9, 0x32, 0x45, 0xf2, 0xb4, 0x02, 0xb1, 0xb7, 0x61, 0x0e, 0xeb, 0x08, 0x9a, + 0x0d, 0xa4, 0xf7, 0x6a, 0xcc, 0xc8, 0x1d, 0xd7, 0x94, 0x69, 0x42, 0xd2, 0x9b, 0xf8, 0x0e, 0x71, + 0x99, 0xb2, 0x89, 0xbf, 0xd9, 0xf7, 0x34, 0x96, 0xb5, 0x88, 0x79, 0xdf, 0x96, 0x79, 0xa7, 0x28, + 0xed, 0x3a, 0xee, 0xf5, 0x73, 0x65, 0x46, 0xdf, 0xcf, 0x97, 0x2a, 0x8d, 0xaa, 0xf1, 0x11, 0x14, + 0x68, 0x74, 0x04, 0x11, 0xe2, 0xd8, 0x65, 0x24, 0x11, 0x22, 0xb4, 0x09, 0x45, 0x97, 0x87, 0x17, + 0x9e, 0xff, 0x42, 0x9d, 0x18, 0xcb, 0x4f, 0xe3, 0x47, 0x78, 0xd4, 0x11, 0x99, 0xc3, 0x49, 0x6b, + 0x13, 0xe4, 0x41, 0xd3, 0x1b, 0x9c, 0xd9, 0xf2, 0xf4, 0xa5, 0x84, 0x80, 0xee, 0x99, 0x3d, 0x43, + 0x1e, 0xd9, 0x59, 0x8b, 0xf8, 0xdb, 0x50, 0x57, 0x06, 0xf8, 0xc0, 0x1a, 0xf2, 0x93, 0x50, 0x92, + 0x7b, 0x55, 0x5a, 0xdf, 0x83, 0x5d, 0x7e, 0x12, 0x1a, 0x7b, 0xb0, 0x20, 0x09, 0xf2, 0x60, 0xcc, + 0x55, 0xd5, 0xdf, 0x4e, 0x13, 0x76, 0x2b, 0x8f, 0x17, 0x93, 0x1b, 0x2d, 0x39, 0x16, 0x24, 0x24, + 0x60, 0xe3, 0x53, 0x60, 0xfa, 0x36, 0x2c, 0xcb, 0x93, 0x22, 0xa7, 0x3a, 0x68, 0x57, 0xf6, 0xaa, + 0x48, 0xb0, 0x75, 0x06, 0x62, 0x74, 0x82, 0x49, 0xbf, 0xaf, 0x1c, 0x23, 0x4a, 0xa6, 0xfa, 0x34, + 0xfe, 0x24, 0x03, 0x8b, 0x58, 0x98, 0x12, 0xd6, 0x25, 0x93, 0xfd, 0xa9, 0x1b, 0x29, 0xe6, 0x47, + 0x97, 0x7d, 0xe8, 0xe3, 0xab, 0x1f, 0x6d, 0xe6, 0x67, 0x8e, 0x36, 0xdf, 0x83, 0xc6, 0x80, 0x0f, + 0x1d, 0xf4, 0x91, 0x51, 0xa2, 0x04, 0x89, 0xe7, 0xf3, 0x0a, 0x2e, 0x55, 0x35, 0xe3, 0x1f, 0x66, + 0x60, 0x81, 0x24, 0x15, 0x54, 0x7a, 0xe5, 0x40, 0x7d, 0xa2, 0xb4, 0x3c, 0xc9, 0xaa, 0x64, 0x9f, + 0xe2, 0x1d, 0x1c, 0xa1, 0x84, 0xbc, 0x73, 0x43, 0x6a, 0x7f, 0x12, 0xca, 0x3e, 0x46, 0x05, 0xc3, + 0xb5, 0x10, 0x98, 0xe2, 0x73, 0x93, 0x9c, 0x94, 0x9d, 0x1b, 0xa8, 0x7d, 0xb8, 0x08, 0xda, 0x28, + 0x09, 0xb5, 0x53, 0x80, 0x8d, 0x6d, 0xa8, 0x25, 0xaa, 0x49, 0x9c, 0xbf, 0x56, 0xe9, 0xfc, 0x75, + 0xc6, 0xc6, 0x91, 0x9d, 0xb5, 0x71, 0x5c, 0xc1, 0xa2, 0xc9, 0xed, 0xc1, 0xd5, 0xb6, 0xe7, 0x1f, + 0x06, 0xc7, 0xe1, 0x36, 0x89, 0x7f, 0x82, 0xbf, 0x47, 0x86, 0xbb, 0xc4, 0x21, 0xa7, 0xb2, 0xdf, + 0x28, 0x5d, 0xf6, 0x6b, 0x50, 0x8f, 0x2d, 0x7c, 0xda, 0x41, 0x59, 0x2d, 0x32, 0xf2, 0xe1, 0x79, + 0x99, 0xd0, 0x03, 0x83, 0xe3, 0x50, 0x1e, 0x95, 0xe1, 0x6f, 0xe3, 0x6f, 0xe4, 0x81, 0x09, 0x6a, + 0x9e, 0x22, 0x98, 0x29, 0xdb, 0x64, 0x76, 0xc6, 0x36, 0xf9, 0x08, 0x98, 0x86, 0xa0, 0x4c, 0xa6, + 0xb9, 0xc8, 0x64, 0xda, 0x88, 0x71, 0xa5, 0xc5, 0xf4, 0x11, 0x2c, 0x49, 0x59, 0x3a, 0xd9, 0x54, + 0x22, 0x0d, 0x46, 0x42, 0x75, 0xa2, 0xbd, 0xca, 0x2e, 0x29, 0x74, 0x73, 0x3a, 0x0a, 0x43, 0xbb, + 0xa4, 0xd2, 0xca, 0x35, 0x02, 0x9c, 0x7b, 0x25, 0x01, 0x16, 0x67, 0x08, 0x50, 0x3b, 0x99, 0x29, + 0x25, 0x4f, 0x66, 0x0c, 0xa8, 0x29, 0xeb, 0x23, 0x39, 0x5d, 0x90, 0xe0, 0x58, 0x91, 0x26, 0x48, + 0x74, 0xbc, 0xb8, 0x0f, 0x0d, 0x75, 0x7c, 0x12, 0x9d, 0xfd, 0x90, 0x43, 0x81, 0x3c, 0x7d, 0xdb, + 0x54, 0x27, 0x40, 0x89, 0x93, 0xf6, 0xca, 0xd4, 0x49, 0xfb, 0xfb, 0xb0, 0x10, 0x08, 0xfa, 0xb5, + 0x26, 0xae, 0xf4, 0xfe, 0xe1, 0x03, 0x54, 0xb3, 0x4a, 0x66, 0x03, 0x13, 0x8e, 0x62, 0xf8, 0xec, + 0xb9, 0x46, 0x2d, 0xe5, 0x5c, 0xe3, 0x49, 0x6c, 0xa8, 0x0b, 0xce, 0x9c, 0x11, 0xca, 0x0c, 0xb1, + 0xa7, 0x8c, 0x1c, 0xe0, 0xee, 0x99, 0x33, 0x32, 0x95, 0x55, 0x58, 0x7c, 0x18, 0xff, 0x37, 0x03, + 0x0d, 0x41, 0x07, 0x89, 0x25, 0xf6, 0x1d, 0x40, 0x66, 0xf0, 0x9a, 0x2b, 0xac, 0x22, 0x70, 0xd5, + 0x02, 0xfb, 0x08, 0x70, 0xc5, 0x58, 0x42, 0xa7, 0x94, 0xeb, 0xab, 0x99, 0x5c, 0x5f, 0x31, 0x0f, + 0xdd, 0xb9, 0x41, 0xba, 0x87, 0x80, 0xb0, 0xef, 0x40, 0x59, 0x10, 0x26, 0x52, 0x89, 0x74, 0xd0, + 0x52, 0x92, 0x57, 0xca, 0x1a, 0x11, 0x59, 0xc7, 0xf2, 0x33, 0xcd, 0xb6, 0x9a, 0x4f, 0xb1, 0xad, + 0x6a, 0x0b, 0x78, 0x07, 0xe0, 0x19, 0xbf, 0xda, 0xf5, 0xfa, 0xa8, 0xf1, 0xde, 0x01, 0x10, 0xb4, + 0x7c, 0x62, 0x8f, 0x1c, 0x79, 0x60, 0x53, 0x30, 0xcb, 0x2f, 0xf8, 0xd5, 0x36, 0x02, 0xc4, 0x44, + 0x8a, 0xe4, 0x78, 0x15, 0x17, 0xcc, 0xd2, 0x0b, 0x7e, 0x45, 0x4b, 0xd8, 0x82, 0xda, 0x33, 0x7e, + 0xb5, 0xc5, 0x49, 0xc8, 0xf4, 0x7c, 0x41, 0x44, 0xbe, 0x7d, 0x21, 0xa4, 0xca, 0x84, 0x5d, 0xb4, + 0xe2, 0xdb, 0x17, 0xcf, 0xf8, 0x95, 0xb2, 0xd1, 0x16, 0x45, 0xfa, 0xd0, 0xeb, 0xcb, 0x7d, 0x53, + 0x79, 0x78, 0xc4, 0x8d, 0x32, 0xe7, 0x5e, 0xe0, 0x6f, 0xe3, 0x2f, 0x33, 0x50, 0x13, 0xed, 0x47, + 0xb6, 0x2c, 0xa6, 0x4c, 0x39, 0x0a, 0x65, 0x62, 0x47, 0xa1, 0xc7, 0x92, 0xab, 0x11, 0x8f, 0xcf, + 0x5e, 0xcf, 0xe3, 0x71, 0x6e, 0x88, 0xc1, 0x7f, 0x00, 0x65, 0x5a, 0x96, 0x62, 0x9d, 0xe7, 0x12, + 0x13, 0x9c, 0xe8, 0x90, 0x59, 0x42, 0xb4, 0x67, 0xe4, 0x97, 0xa0, 0x1d, 0xfe, 0xd1, 0x10, 0x97, + 0xfd, 0xe8, 0xc8, 0x2f, 0x65, 0x1a, 0x0a, 0xd7, 0xf8, 0x25, 0xe8, 0x27, 0x6b, 0x73, 0x33, 0x27, + 0x6b, 0x07, 0x50, 0x12, 0x53, 0x8d, 0x9d, 0x4d, 0x29, 0x34, 0x93, 0x56, 0xa8, 0x90, 0x04, 0x6c, + 0xb1, 0x29, 0x08, 0x46, 0x97, 0x95, 0x92, 0x80, 0x1d, 0xf0, 0x43, 0x64, 0x76, 0x19, 0xa8, 0x68, + 0x2b, 0x00, 0x0f, 0x27, 0xa3, 0xf1, 0xa2, 0xe5, 0x92, 0x24, 0xf1, 0xc4, 0x80, 0xef, 0xdc, 0x30, + 0x6b, 0xfd, 0xc4, 0x0c, 0xac, 0x4b, 0x5a, 0xc5, 0x9c, 0xd9, 0x84, 0x4f, 0x93, 0x6a, 0xb8, 0x22, + 0x50, 0xf1, 0x7b, 0x63, 0x0e, 0xf2, 0x02, 0xd5, 0xf8, 0x04, 0x16, 0xb4, 0x66, 0x90, 0x9a, 0xff, + 0xba, 0x3d, 0x34, 0x7e, 0x2d, 0xca, 0x2c, 0xea, 0x20, 0xf3, 0x91, 0xf2, 0xf1, 0xe0, 0x03, 0xea, + 0xb8, 0xf4, 0x25, 0x21, 0x90, 0x40, 0x7b, 0x6d, 0xbf, 0x83, 0xdf, 0x80, 0x45, 0xad, 0xf4, 0x6d, + 0xc7, 0xb5, 0x87, 0xce, 0x8f, 0x70, 0xc3, 0x0f, 0x9c, 0x53, 0x77, 0xaa, 0x7c, 0x02, 0x7d, 0xa5, + 0xf2, 0xff, 0x51, 0x16, 0x96, 0x64, 0x05, 0xe8, 0xb5, 0xe7, 0x08, 0x29, 0x6e, 0x2f, 0x38, 0x65, + 0xdf, 0x81, 0x9a, 0x18, 0x1b, 0xcb, 0xe7, 0xa7, 0x4e, 0x10, 0x72, 0x65, 0xb6, 0x4a, 0x61, 0x5c, + 0x62, 0x33, 0x17, 0xa8, 0xa6, 0xc4, 0x64, 0x9f, 0x40, 0x05, 0xb3, 0xd2, 0x31, 0x8a, 0x9c, 0x88, + 0xe6, 0x6c, 0x46, 0x1a, 0xe8, 0x9d, 0x1b, 0x26, 0x04, 0xf1, 0xb0, 0x7f, 0x02, 0x15, 0x9c, 0xc3, + 0x73, 0x1c, 0xc8, 0x29, 0x56, 0x35, 0x33, 0xd0, 0x22, 0xf3, 0x38, 0x1e, 0xf6, 0x16, 0xd4, 0x88, + 0x59, 0xc9, 0x71, 0x92, 0xde, 0x40, 0x6b, 0xb3, 0xd9, 0xd5, 0x48, 0x8a, 0xc6, 0x8f, 0xb5, 0xef, + 0x8d, 0x32, 0x14, 0x43, 0xdf, 0x39, 0x3d, 0xe5, 0xbe, 0xb1, 0x12, 0x0d, 0x8d, 0xe0, 0xc2, 0xbc, + 0x1b, 0xf2, 0xb1, 0x90, 0xcd, 0x8d, 0x7f, 0x9f, 0x81, 0x8a, 0xe4, 0xab, 0x3f, 0xb5, 0xad, 0x6c, + 0x4d, 0x73, 0x7b, 0xa5, 0x13, 0x9b, 0xd8, 0xcb, 0xf5, 0x5d, 0x98, 0x1f, 0x09, 0x39, 0x5d, 0xe8, + 0x91, 0x09, 0x43, 0x59, 0x5d, 0x81, 0xa5, 0x98, 0xbc, 0x0e, 0x8b, 0x28, 0x35, 0x07, 0x56, 0xe8, + 0x0c, 0x2d, 0x95, 0x28, 0x5d, 0x4c, 0x17, 0x28, 0xa9, 0xe7, 0x0c, 0xf7, 0x64, 0x82, 0x10, 0x1e, + 0x83, 0xd0, 0x3e, 0xe5, 0x72, 0x6d, 0xd3, 0x87, 0xd1, 0x84, 0x95, 0x29, 0x15, 0x52, 0xa9, 0xbf, + 0xff, 0x7b, 0x01, 0x56, 0x67, 0x92, 0xa4, 0x1a, 0x1c, 0x19, 0x88, 0x86, 0xce, 0xe8, 0xd8, 0x8b, + 0x8e, 0x4f, 0x33, 0x9a, 0x81, 0x68, 0x57, 0xa4, 0xa8, 0xe3, 0x53, 0x0e, 0xcb, 0x8a, 0x20, 0xf1, + 0xfc, 0x33, 0xd2, 0x32, 0xb3, 0xa8, 0x03, 0x7d, 0x90, 0xdc, 0xc4, 0xa6, 0xab, 0x53, 0x70, 0x5d, + 0x34, 0x5a, 0x1c, 0xcf, 0xc0, 0x02, 0xf6, 0x9b, 0xd0, 0x8c, 0xe8, 0x5e, 0x8a, 0xed, 0x9a, 0xca, + 0x2c, 0x6a, 0xfa, 0xfa, 0x2b, 0x6a, 0x4a, 0x9c, 0xdd, 0xa1, 0xec, 0xb4, 0xa2, 0x96, 0x0c, 0x15, + 0x18, 0xd5, 0x75, 0x0e, 0x6f, 0xa8, 0xba, 0x50, 0x0c, 0x9f, 0xad, 0x31, 0xff, 0x5a, 0x7d, 0xc3, + 0x73, 0xc9, 0x44, 0xb5, 0xe6, 0x2d, 0x59, 0x70, 0x94, 0xa4, 0xd7, 0x7b, 0x06, 0x2b, 0x17, 0xb6, + 0x13, 0xaa, 0x3e, 0x6a, 0x1a, 0x7b, 0x01, 0xeb, 0x7b, 0xfc, 0x8a, 0xfa, 0x3e, 0xa7, 0xcc, 0x09, + 0xc5, 0x64, 0xe9, 0x62, 0x16, 0x18, 0xac, 0xfd, 0xbd, 0x1c, 0xd4, 0x93, 0xa5, 0x08, 0xc6, 0x22, + 0x37, 0x1b, 0x25, 0x6f, 0x4a, 0x21, 0x58, 0x1e, 0xed, 0xef, 0x93, 0x9c, 0x39, 0x6b, 0x74, 0xc8, + 0xa6, 0x18, 0x1d, 0xf4, 0xb3, 0xfe, 0xdc, 0xab, 0x8c, 0xab, 0xf9, 0xd7, 0x32, 0xae, 0x16, 0xd2, + 0x8c, 0xab, 0xd7, 0x5b, 0xe4, 0xe6, 0x7e, 0x2a, 0x8b, 0x5c, 0xf1, 0x25, 0x16, 0xb9, 0x84, 0x1d, + 0xb1, 0x34, 0x6d, 0x47, 0x4c, 0xb1, 0xbf, 0x95, 0xbf, 0x82, 0xfd, 0x6d, 0xed, 0x2f, 0x33, 0xc0, + 0x66, 0xd7, 0x02, 0x7b, 0x4a, 0xd6, 0x1b, 0x97, 0x0f, 0x25, 0x9f, 0xfe, 0xc6, 0xeb, 0xad, 0x27, + 0x35, 0xfd, 0x2a, 0x37, 0x7b, 0x08, 0x8b, 0xba, 0xdb, 0xbb, 0xae, 0xa3, 0xd7, 0x4c, 0xa6, 0x27, + 0xc5, 0x27, 0x39, 0x9a, 0xdd, 0x3a, 0xff, 0x4a, 0xbb, 0x75, 0xe1, 0x95, 0x76, 0xeb, 0xb9, 0xa4, + 0xdd, 0x7a, 0xed, 0x3f, 0x67, 0x60, 0x31, 0x85, 0x64, 0x7f, 0x7e, 0x7d, 0x16, 0x94, 0x96, 0x60, + 0x62, 0x59, 0x49, 0x69, 0x3a, 0xff, 0xda, 0x85, 0x4a, 0x3c, 0x15, 0x2a, 0x2c, 0xe4, 0xc1, 0xab, + 0x78, 0x49, 0x9c, 0xc3, 0xd4, 0xb3, 0xaf, 0xfd, 0x7e, 0x16, 0x2a, 0x5a, 0xa2, 0x18, 0x45, 0x22, + 0x50, 0xcd, 0x5d, 0x88, 0xe4, 0x40, 0x3c, 0x61, 0xb8, 0x0b, 0xd2, 0x84, 0x41, 0xe9, 0xb4, 0x94, + 0xa4, 0xd0, 0x87, 0x08, 0xeb, 0xb0, 0xa8, 0x2c, 0x6b, 0x3c, 0xf6, 0x0a, 0x94, 0x3b, 0xcb, 0x82, + 0xb4, 0xaf, 0xf1, 0xc8, 0xc9, 0x90, 0x3d, 0x54, 0xca, 0x5f, 0x3c, 0x77, 0x48, 0xd8, 0x64, 0x1f, + 0x58, 0xa0, 0xe5, 0xa0, 0x26, 0x51, 0x50, 0xf5, 0x07, 0xb0, 0xac, 0x16, 0x43, 0x32, 0x07, 0x99, + 0x0c, 0x98, 0x5c, 0x0a, 0x7a, 0x96, 0xef, 0xc1, 0x9d, 0xa9, 0x36, 0x4d, 0x65, 0x25, 0xf7, 0xd5, + 0x9b, 0x89, 0xd6, 0xe9, 0x25, 0xac, 0xfd, 0x18, 0x6a, 0x09, 0xb6, 0xf8, 0xf3, 0x9b, 0xf2, 0xe9, + 0x53, 0x1d, 0x1a, 0x51, 0xfd, 0x54, 0x67, 0xed, 0xff, 0xe4, 0x80, 0xcd, 0x72, 0xe6, 0x5f, 0x64, + 0x13, 0x66, 0x09, 0x33, 0x97, 0x42, 0x98, 0xff, 0xdf, 0xa4, 0x85, 0xf7, 0x61, 0x41, 0x86, 0x47, + 0x69, 0xe6, 0x51, 0x5a, 0x9c, 0x8d, 0x28, 0x41, 0xb5, 0xe2, 0xa3, 0x69, 0x37, 0x8d, 0x52, 0x22, + 0x22, 0x44, 0x13, 0x97, 0xa6, 0xbc, 0x35, 0x8e, 0x60, 0xce, 0x76, 0xfb, 0x67, 0x9e, 0x2f, 0xf9, + 0xe0, 0x2f, 0x7d, 0xe5, 0xcd, 0x72, 0xbd, 0x85, 0xf9, 0x51, 0x46, 0x33, 0x65, 0x61, 0xc6, 0x07, + 0x50, 0xd1, 0xc0, 0xac, 0x0c, 0x85, 0xdd, 0xce, 0xde, 0xc6, 0x41, 0xe3, 0x06, 0xab, 0x41, 0xd9, + 0x6c, 0x6f, 0x1e, 0x7c, 0xd6, 0x36, 0xdb, 0x5b, 0x8d, 0x0c, 0x2b, 0x41, 0x7e, 0xf7, 0xa0, 0xdb, + 0x6b, 0x64, 0x8d, 0x35, 0x68, 0xca, 0x12, 0x67, 0x2d, 0x14, 0xbf, 0x93, 0x8f, 0x0e, 0x07, 0x31, + 0x51, 0x2a, 0xe4, 0xdf, 0x84, 0xaa, 0x2e, 0xcc, 0x48, 0x8a, 0x98, 0xb2, 0xd0, 0x0b, 0x55, 0xdc, + 0xd3, 0x78, 0xf5, 0x26, 0x90, 0x7d, 0x76, 0x10, 0x65, 0xcb, 0x26, 0xa4, 0xd4, 0x14, 0x5b, 0x20, + 0xaa, 0x3a, 0x09, 0x32, 0xfc, 0x2b, 0x50, 0x4f, 0x1e, 0xd7, 0x4b, 0x8e, 0x94, 0xa6, 0x5e, 0x8a, + 0xdc, 0x89, 0xf3, 0x7b, 0xf6, 0x3d, 0x68, 0x4c, 0x1f, 0xf7, 0x4b, 0x51, 0xf9, 0x9a, 0xfc, 0xf3, + 0x4e, 0xd2, 0x02, 0xc0, 0x76, 0x60, 0x29, 0x4d, 0x9c, 0x43, 0xfa, 0xb8, 0xfe, 0x48, 0x82, 0xcd, + 0x8a, 0x6c, 0xec, 0xdb, 0xd2, 0xaa, 0x53, 0xc0, 0xe9, 0x7f, 0x3b, 0x59, 0xbf, 0x36, 0xd8, 0xeb, + 0xf4, 0x4f, 0xb3, 0xef, 0x9c, 0x03, 0xc4, 0x30, 0xd6, 0x80, 0xea, 0xc1, 0x61, 0x7b, 0xdf, 0xda, + 0xdc, 0x69, 0xed, 0xef, 0xb7, 0x77, 0x1b, 0x37, 0x18, 0x83, 0x3a, 0x5a, 0xa6, 0xb7, 0x22, 0x58, + 0x46, 0xc0, 0xa4, 0x75, 0x4d, 0xc1, 0xb2, 0x6c, 0x09, 0x1a, 0x9d, 0xfd, 0x29, 0x68, 0x8e, 0x35, + 0x61, 0xe9, 0xb0, 0x4d, 0xc6, 0xec, 0x44, 0xb9, 0x79, 0xa1, 0x22, 0xc8, 0xee, 0x0a, 0x15, 0x81, + 0xc2, 0xfc, 0xe4, 0x3a, 0x50, 0x92, 0xf3, 0xef, 0x66, 0x60, 0x79, 0x2a, 0x21, 0x0e, 0xde, 0x20, + 0xb9, 0x39, 0x29, 0x31, 0x57, 0x11, 0xa8, 0x56, 0xd3, 0xfb, 0xb0, 0x10, 0x1d, 0x33, 0x4d, 0xed, + 0x4a, 0x8d, 0x28, 0x41, 0x21, 0x3f, 0x84, 0x45, 0xed, 0xb4, 0x6a, 0x8a, 0x57, 0x30, 0x2d, 0x49, + 0x66, 0x30, 0x56, 0x23, 0x27, 0xf9, 0xa9, 0x56, 0x0f, 0x28, 0x76, 0x50, 0x4f, 0x88, 0x8d, 0x5e, + 0xc9, 0xf6, 0xaa, 0x4f, 0xf6, 0x68, 0x8a, 0x10, 0x92, 0xad, 0xd5, 0x27, 0x5c, 0x55, 0xff, 0x07, + 0x73, 0xc0, 0x3e, 0x9d, 0x70, 0xff, 0x0a, 0x83, 0x33, 0x82, 0x57, 0x79, 0x2b, 0xaa, 0x73, 0x95, + 0xec, 0x6b, 0x05, 0x60, 0xa5, 0x05, 0x40, 0xe5, 0x5f, 0x1d, 0x00, 0x55, 0x78, 0x55, 0x00, 0xd4, + 0x5b, 0x50, 0x73, 0x4e, 0x5d, 0x4f, 0xb0, 0x42, 0x21, 0xf7, 0x06, 0xcd, 0xb9, 0x7b, 0xb9, 0xfb, + 0x55, 0xb3, 0x2a, 0x81, 0x42, 0xea, 0x0d, 0xd8, 0x27, 0x31, 0x12, 0x1f, 0x9c, 0x62, 0xb0, 0x9e, + 0xce, 0x04, 0xdb, 0x83, 0x53, 0x2e, 0x8f, 0x91, 0x50, 0xaf, 0x50, 0x99, 0x05, 0x3c, 0x60, 0x6f, + 0x43, 0x3d, 0xf0, 0x26, 0x42, 0x8d, 0x50, 0xc3, 0x40, 0x66, 0xb1, 0x2a, 0x41, 0x0f, 0x95, 0x0d, + 0x74, 0x71, 0x12, 0x70, 0x6b, 0xe4, 0x04, 0x81, 0x10, 0xcf, 0xfa, 0x9e, 0x1b, 0xfa, 0xde, 0x50, + 0x5a, 0xba, 0x16, 0x26, 0x01, 0xdf, 0xa3, 0x94, 0x4d, 0x4a, 0x60, 0xdf, 0x8a, 0x9b, 0x34, 0xb6, + 0x1d, 0x3f, 0x68, 0x02, 0x36, 0x49, 0xf5, 0x14, 0xa5, 0x75, 0xdb, 0xf1, 0xa3, 0xb6, 0x88, 0x8f, + 0x60, 0x2a, 0x30, 0xab, 0x32, 0x1d, 0x98, 0xf5, 0xc3, 0xf4, 0xc0, 0xac, 0x1a, 0x16, 0xfd, 0x48, + 0x16, 0x3d, 0x3b, 0xc5, 0x5f, 0x29, 0x3e, 0x6b, 0x36, 0xde, 0xac, 0xfe, 0x55, 0xe2, 0xcd, 0xe6, + 0xd3, 0xe2, 0xcd, 0x3e, 0x80, 0x0a, 0x46, 0x02, 0x59, 0x67, 0x8e, 0x90, 0xe1, 0xc8, 0x72, 0xd7, + 0xd0, 0x43, 0x85, 0x76, 0x1c, 0x37, 0x34, 0xc1, 0x57, 0x3f, 0x83, 0xd9, 0xd0, 0xaf, 0x85, 0x5f, + 0x60, 0xe8, 0x97, 0x8c, 0x58, 0x5a, 0x87, 0x92, 0x9a, 0x27, 0xc6, 0x20, 0x7f, 0xe2, 0x7b, 0x23, + 0x65, 0xd1, 0x10, 0xbf, 0x59, 0x1d, 0xb2, 0xa1, 0x27, 0x33, 0x67, 0x43, 0xcf, 0xf8, 0x75, 0xa8, + 0x68, 0xa4, 0xc6, 0xde, 0xa4, 0x53, 0x48, 0xa1, 0x89, 0x49, 0xd9, 0x92, 0x46, 0xb1, 0x2c, 0xa1, + 0x9d, 0x81, 0xe0, 0x37, 0x03, 0xc7, 0xe7, 0x18, 0xa4, 0x69, 0xf9, 0xfc, 0x9c, 0xfb, 0x81, 0xb2, + 0x30, 0x35, 0xa2, 0x04, 0x93, 0xe0, 0xc6, 0x6f, 0xc0, 0x62, 0x62, 0x6e, 0x25, 0x8b, 0x78, 0x1b, + 0xe6, 0x70, 0xdc, 0x94, 0x07, 0x40, 0x32, 0x04, 0x4b, 0xa6, 0x61, 0xf4, 0x3d, 0x19, 0xc7, 0xac, + 0xb1, 0xef, 0x1d, 0x63, 0x25, 0x19, 0xb3, 0x22, 0x61, 0x87, 0xbe, 0x77, 0x6c, 0xfc, 0x59, 0x0e, + 0x72, 0x3b, 0xde, 0x58, 0xf7, 0x48, 0xcb, 0xcc, 0x78, 0xa4, 0x49, 0xf5, 0xd2, 0x8a, 0xd4, 0x47, + 0x29, 0xb3, 0xa3, 0x59, 0x48, 0xa9, 0x90, 0xf7, 0xa1, 0x2e, 0xf8, 0x44, 0xe8, 0x09, 0xfd, 0xfc, + 0xc2, 0xf6, 0x49, 0x20, 0xce, 0xd1, 0xe2, 0xb3, 0x47, 0x61, 0xcf, 0xdb, 0x26, 0x38, 0x5b, 0x82, + 0x5c, 0xa4, 0xbe, 0x60, 0xb2, 0xf8, 0x64, 0x2b, 0x30, 0x87, 0xae, 0xc9, 0x57, 0xd2, 0xc4, 0x2d, + 0xbf, 0xd8, 0x37, 0x60, 0x31, 0x59, 0x2e, 0xb1, 0x22, 0x29, 0x1b, 0xe9, 0x05, 0x23, 0x4f, 0xba, + 0x09, 0x82, 0x8f, 0x10, 0x8e, 0xf4, 0x94, 0x39, 0xe1, 0x1c, 0x93, 0x34, 0xa6, 0x57, 0x4a, 0x30, + 0xbd, 0xbb, 0x50, 0x09, 0x87, 0xe7, 0xd6, 0xd8, 0xbe, 0x1a, 0x7a, 0xf6, 0x40, 0xae, 0x6f, 0x08, + 0x87, 0xe7, 0x87, 0x04, 0x61, 0x0f, 0x01, 0x46, 0xe3, 0xb1, 0x5c, 0x7b, 0x68, 0xea, 0x88, 0x49, + 0x79, 0xef, 0xf0, 0x90, 0x48, 0xce, 0x2c, 0x8f, 0xc6, 0x63, 0xfa, 0xc9, 0xb6, 0xa0, 0x9e, 0x1a, + 0x48, 0x79, 0x47, 0x79, 0xd2, 0x7a, 0xe3, 0xf5, 0x94, 0xc5, 0x59, 0xeb, 0xeb, 0xb0, 0xb5, 0xef, + 0x01, 0xfb, 0x19, 0xc3, 0x19, 0x7b, 0x50, 0x8e, 0xda, 0xa7, 0x47, 0x03, 0xa2, 0x6f, 0x7c, 0x25, + 0x11, 0x0d, 0xd8, 0x1a, 0x0c, 0x7c, 0xc1, 0x17, 0x69, 0xc3, 0x8c, 0x58, 0x3e, 0x68, 0x3b, 0x66, + 0x8b, 0xf8, 0xbe, 0xf1, 0xdf, 0x32, 0x50, 0xa0, 0xd0, 0xc4, 0x77, 0x60, 0x9e, 0xf0, 0x23, 0xef, + 0x3e, 0x69, 0x18, 0xa7, 0x7d, 0xb7, 0x27, 0x1d, 0xfb, 0xc4, 0xb2, 0xd0, 0xc2, 0xaa, 0xb3, 0xd1, + 0xcc, 0x6b, 0xa1, 0xd5, 0x77, 0xa1, 0x1c, 0x55, 0xad, 0x91, 0x4e, 0x49, 0xd5, 0xcc, 0xde, 0x80, + 0xfc, 0x99, 0x37, 0x56, 0xe7, 0x3c, 0x10, 0x8f, 0xa4, 0x89, 0xf0, 0xb8, 0x2d, 0xa2, 0x0e, 0x6a, + 0xbc, 0x3c, 0x9f, 0x88, 0x2a, 0x41, 0x32, 0x98, 0xed, 0xe3, 0x5c, 0x4a, 0x1f, 0x8f, 0x60, 0x5e, + 0xf0, 0x01, 0xcd, 0x41, 0xe5, 0xfa, 0x4d, 0xf3, 0x3d, 0x21, 0xe1, 0xf5, 0x87, 0x93, 0x01, 0xd7, + 0x4f, 0xda, 0xd0, 0x9b, 0x4d, 0xc2, 0x95, 0x64, 0x6d, 0xfc, 0x41, 0x86, 0xf8, 0x8b, 0x28, 0x97, + 0xdd, 0x87, 0xbc, 0xd8, 0xdf, 0xa6, 0xce, 0xdd, 0xa3, 0x20, 0x05, 0x81, 0x67, 0x22, 0x06, 0xde, + 0x45, 0x30, 0x19, 0x25, 0x4b, 0xaf, 0x99, 0x15, 0x77, 0x32, 0x8a, 0x0e, 0xaa, 0xbe, 0xa6, 0xba, + 0x35, 0x75, 0xc8, 0x43, 0xbd, 0x8f, 0x96, 0xe9, 0xba, 0xe6, 0x16, 0x97, 0x4f, 0xec, 0x98, 0x4a, + 0x0a, 0x1c, 0x9c, 0x72, 0xcd, 0x1d, 0xee, 0x8f, 0xb2, 0x50, 0x4b, 0xb4, 0x08, 0xfd, 0x02, 0xc5, + 0x06, 0x40, 0x66, 0x24, 0x39, 0xdf, 0x20, 0x40, 0x52, 0x50, 0xd7, 0xc6, 0x29, 0x9b, 0x18, 0xa7, + 0xc8, 0x15, 0x27, 0xa7, 0xbb, 0xe2, 0x3c, 0x82, 0x72, 0x1c, 0x4e, 0x9f, 0x6c, 0x92, 0xa8, 0x4f, + 0x85, 0x6a, 0xc4, 0x48, 0xb1, 0xf3, 0x4e, 0x41, 0x77, 0xde, 0xf9, 0xae, 0xe6, 0xeb, 0x31, 0x87, + 0xc5, 0x18, 0x69, 0x23, 0xfa, 0x0b, 0xf1, 0xf4, 0x30, 0x3e, 0x81, 0x8a, 0xd6, 0x78, 0xdd, 0xa7, + 0x23, 0x93, 0xf0, 0xe9, 0x88, 0x82, 0xaa, 0xb2, 0x71, 0x50, 0x95, 0xf1, 0x37, 0xb3, 0x50, 0x13, + 0xeb, 0xcb, 0x71, 0x4f, 0x0f, 0xbd, 0xa1, 0xd3, 0x47, 0xb3, 0x52, 0xb4, 0xc2, 0xa4, 0xa0, 0xa5, + 0xd6, 0x99, 0x5c, 0x62, 0x24, 0x67, 0xe9, 0xb1, 0xa3, 0xc4, 0xa4, 0xa3, 0xd8, 0x51, 0x03, 0x6a, + 0x82, 0x31, 0xa2, 0x81, 0x28, 0x0e, 0xf6, 0x37, 0x2b, 0x27, 0x9c, 0x6f, 0xd8, 0x01, 0x71, 0xc8, + 0x6f, 0xc0, 0xa2, 0xc0, 0xc1, 0xb0, 0xb9, 0x91, 0x33, 0x1c, 0x3a, 0x84, 0x49, 0x07, 0x4d, 0x8d, + 0x13, 0xce, 0x4d, 0x3b, 0xe4, 0x7b, 0x22, 0x41, 0xde, 0x0d, 0x50, 0x1a, 0x38, 0x81, 0x7d, 0x1c, + 0x7b, 0x6f, 0x46, 0xdf, 0x68, 0x47, 0xb6, 0x2f, 0x35, 0x3b, 0x32, 0x1d, 0x40, 0x54, 0x46, 0xf6, + 0x65, 0x64, 0x47, 0x9e, 0xa2, 0xa4, 0xe2, 0x34, 0x25, 0x19, 0xff, 0x2e, 0x0b, 0x15, 0x8d, 0x2c, + 0x5f, 0x67, 0x77, 0xbd, 0x33, 0x63, 0x06, 0x2c, 0xeb, 0x16, 0xbf, 0xb7, 0x92, 0x55, 0xa2, 0xa7, + 0x0b, 0xdd, 0x42, 0xa0, 0x11, 0xf0, 0x2d, 0x28, 0x8b, 0x55, 0xf7, 0x01, 0x1e, 0xb8, 0xca, 0x3b, + 0x34, 0x10, 0x70, 0x38, 0x39, 0x56, 0x89, 0x8f, 0x31, 0xb1, 0x10, 0x27, 0x3e, 0x16, 0x89, 0x2f, + 0xf3, 0xa7, 0xfe, 0x08, 0xaa, 0xb2, 0x54, 0x9c, 0x53, 0xec, 0x6e, 0xbc, 0xea, 0x13, 0xf3, 0x6d, + 0x56, 0xa8, 0x3a, 0x9a, 0x7c, 0x99, 0xf1, 0xb1, 0xca, 0x58, 0x7a, 0x55, 0xc6, 0xc7, 0xf4, 0x61, + 0x6c, 0x47, 0x2e, 0xea, 0xe8, 0x65, 0xa5, 0xf8, 0xd8, 0x43, 0x58, 0x54, 0xec, 0x6a, 0xe2, 0xda, + 0xae, 0xeb, 0x4d, 0xdc, 0x3e, 0x57, 0xd1, 0x56, 0x4c, 0x26, 0x1d, 0xc5, 0x29, 0xc6, 0x20, 0x0a, + 0xc7, 0x25, 0x6f, 0xad, 0x07, 0x50, 0x20, 0xb9, 0x9c, 0x84, 0x8f, 0x74, 0xc6, 0x45, 0x28, 0xec, + 0x3e, 0x14, 0x48, 0x3c, 0xcf, 0x5e, 0xcb, 0x6c, 0x08, 0xc1, 0x68, 0x01, 0x13, 0x19, 0xf7, 0x78, + 0xe8, 0x3b, 0xfd, 0x20, 0x0e, 0xe4, 0x2a, 0x08, 0xfd, 0x93, 0xea, 0x8a, 0x4f, 0x6e, 0x63, 0x4c, + 0xd4, 0x51, 0x09, 0x47, 0x6c, 0x4c, 0x8b, 0x89, 0x32, 0xa4, 0xb8, 0x34, 0x84, 0x95, 0x63, 0x1e, + 0x5e, 0x70, 0xee, 0xba, 0x42, 0x18, 0xea, 0x73, 0x37, 0xf4, 0xed, 0xa1, 0x98, 0x24, 0xea, 0xc1, + 0x93, 0x99, 0x52, 0xe3, 0x33, 0x90, 0x8d, 0x38, 0xe3, 0x66, 0x94, 0x8f, 0x78, 0xc7, 0xf2, 0x71, + 0x5a, 0xda, 0xda, 0xaf, 0xc1, 0xda, 0xf5, 0x99, 0x52, 0xc2, 0x35, 0xef, 0x27, 0xb9, 0x4a, 0x64, + 0xf5, 0x1b, 0x7a, 0x76, 0x48, 0xad, 0xd1, 0x39, 0xcb, 0x3e, 0x54, 0xb4, 0x94, 0x78, 0xef, 0xcf, + 0xa0, 0x70, 0x47, 0x1f, 0x62, 0x47, 0x72, 0x3d, 0x7f, 0x84, 0x56, 0xb6, 0x81, 0x15, 0x97, 0x9e, + 0x31, 0xe7, 0x63, 0x38, 0xc6, 0xa7, 0x1b, 0xeb, 0x30, 0x8f, 0x92, 0xbd, 0xb6, 0xd1, 0xbd, 0x4c, + 0x18, 0x34, 0x96, 0x80, 0xed, 0x13, 0xef, 0xd2, 0x9d, 0x37, 0xff, 0x4b, 0x0e, 0x2a, 0x1a, 0x58, + 0xec, 0x46, 0xe8, 0xee, 0x67, 0x0d, 0x1c, 0x7b, 0xc4, 0x95, 0x49, 0xb3, 0x66, 0xd6, 0x10, 0xba, + 0x25, 0x81, 0x62, 0x2f, 0xb6, 0xcf, 0x4f, 0x2d, 0x6f, 0x12, 0x5a, 0x03, 0x7e, 0xea, 0x73, 0xd5, + 0xca, 0xaa, 0x7d, 0x7e, 0x7a, 0x30, 0x09, 0xb7, 0x10, 0x26, 0xb0, 0x04, 0x2f, 0xd1, 0xb0, 0xa4, + 0x87, 0xda, 0xc8, 0xbe, 0x8c, 0xb1, 0xa4, 0x9b, 0x24, 0x51, 0x66, 0x3e, 0x72, 0x93, 0x24, 0x6d, + 0x71, 0x7a, 0x03, 0x2d, 0xcc, 0x6e, 0xa0, 0xdf, 0x82, 0x15, 0xda, 0x40, 0x25, 0x6b, 0xb6, 0xa6, + 0x56, 0xf2, 0x12, 0xa6, 0xca, 0x4e, 0x6a, 0x62, 0x6f, 0x43, 0xf4, 0x40, 0xb1, 0xa5, 0xc0, 0xf9, + 0x11, 0x31, 0xb2, 0x8c, 0x29, 0x7a, 0x26, 0x0b, 0xef, 0x3a, 0x3f, 0xe2, 0x02, 0x13, 0x7d, 0x61, + 0x74, 0x4c, 0x19, 0x2d, 0x31, 0x72, 0xdc, 0x69, 0x4c, 0xfb, 0x32, 0x89, 0x59, 0x96, 0x98, 0xf6, + 0xa5, 0x8e, 0xf9, 0x04, 0x56, 0x47, 0x7c, 0xe0, 0xd8, 0xc9, 0x62, 0xad, 0x58, 0x70, 0x5b, 0xa2, + 0x64, 0x2d, 0x4f, 0x97, 0x14, 0x77, 0x31, 0x1a, 0x3f, 0xf2, 0x46, 0xc7, 0x0e, 0xc9, 0x2c, 0xe4, + 0x9d, 0x93, 0x37, 0xeb, 0xee, 0x64, 0xf4, 0x03, 0x04, 0x8b, 0x2c, 0x81, 0x51, 0x83, 0x4a, 0x37, + 0xf4, 0xc6, 0x6a, 0x9a, 0xeb, 0x50, 0xa5, 0x4f, 0x19, 0xc2, 0x78, 0x0b, 0x6e, 0x22, 0x4b, 0xe8, + 0x79, 0x63, 0x6f, 0xe8, 0x9d, 0x5e, 0x25, 0xce, 0xf1, 0xfe, 0x43, 0x06, 0x16, 0x13, 0xa9, 0x92, + 0xbd, 0x7e, 0x8b, 0xf8, 0x59, 0x14, 0x87, 0x46, 0x6b, 0x70, 0x41, 0x5b, 0x83, 0x84, 0x48, 0xcc, + 0x4c, 0xc5, 0xa6, 0xb5, 0xe2, 0xfb, 0x13, 0x54, 0x46, 0x62, 0x29, 0xcd, 0x59, 0x96, 0x22, 0xf3, + 0xab, 0x9b, 0x15, 0x54, 0x11, 0xbf, 0x24, 0x23, 0x5a, 0x06, 0xb2, 0xcb, 0xb9, 0x64, 0x58, 0x80, + 0x7e, 0xe6, 0xa7, 0x5a, 0x10, 0x1f, 0x04, 0x06, 0xc6, 0x3f, 0xcf, 0x00, 0xc4, 0xad, 0xc3, 0xc0, + 0x84, 0x48, 0x6e, 0xa1, 0xab, 0xc9, 0x34, 0x19, 0xe5, 0x4d, 0xa8, 0x46, 0xfe, 0xc9, 0xb1, 0x24, + 0x54, 0x51, 0x30, 0x21, 0x0e, 0xbd, 0x0b, 0xf3, 0xa7, 0x43, 0xef, 0x18, 0x25, 0x56, 0x29, 0xb7, + 0x90, 0x77, 0x5a, 0x9d, 0xc0, 0x4a, 0x1a, 0x89, 0xe5, 0xa6, 0x7c, 0xaa, 0x0b, 0xb3, 0x2e, 0x05, + 0x19, 0xbf, 0x9d, 0x8d, 0x1c, 0x35, 0xe3, 0x91, 0x78, 0xb9, 0x7a, 0xf7, 0xd3, 0x78, 0xce, 0xbc, + 0xcc, 0x98, 0xf8, 0x09, 0xd4, 0x7d, 0xda, 0x94, 0xd4, 0x8e, 0x95, 0x7f, 0xc9, 0x8e, 0x55, 0xf3, + 0x13, 0x92, 0xce, 0x7b, 0xd0, 0xb0, 0x07, 0xe7, 0xdc, 0x0f, 0x1d, 0x3c, 0xad, 0x47, 0xf9, 0x58, + 0xba, 0x46, 0x6a, 0x70, 0x14, 0x44, 0xdf, 0x85, 0x79, 0x19, 0x56, 0x1b, 0x61, 0xca, 0x8b, 0x7a, + 0x62, 0xb0, 0x40, 0x34, 0xfe, 0xa5, 0xf2, 0x0c, 0x4d, 0xce, 0xee, 0xcb, 0x47, 0x45, 0xef, 0x61, + 0x76, 0xd6, 0x5c, 0x2a, 0x09, 0x49, 0x1a, 0x01, 0x24, 0x3f, 0x22, 0xa0, 0x34, 0x01, 0x24, 0x87, + 0x35, 0xff, 0x3a, 0xc3, 0x6a, 0xfc, 0xa7, 0x0c, 0x14, 0x77, 0xbc, 0xf1, 0x8e, 0x43, 0xae, 0xf9, + 0xb8, 0x4c, 0x22, 0x1b, 0xd5, 0x9c, 0xf8, 0x44, 0x37, 0x9f, 0x97, 0x44, 0x8f, 0xa5, 0x8a, 0x79, + 0xb5, 0xa4, 0x98, 0xf7, 0x5d, 0xb8, 0x85, 0x26, 0x40, 0xdf, 0x1b, 0x7b, 0xbe, 0x58, 0xaa, 0xf6, + 0x90, 0xc4, 0x3d, 0xcf, 0x0d, 0xcf, 0x14, 0xef, 0xbc, 0x79, 0xc2, 0xf9, 0xa1, 0x86, 0xb1, 0x17, + 0x21, 0x60, 0x7c, 0xe6, 0x30, 0x3c, 0xb7, 0x48, 0x43, 0x97, 0xf2, 0x28, 0x71, 0xd4, 0x79, 0x91, + 0xd0, 0x46, 0x38, 0x4a, 0xa4, 0xc6, 0xb7, 0xa1, 0x1c, 0x1d, 0xf6, 0xb0, 0xf7, 0xa1, 0x7c, 0xe6, + 0x8d, 0xe5, 0x89, 0x50, 0x26, 0x11, 0x61, 0x27, 0x7b, 0x6d, 0x96, 0xce, 0xe8, 0x47, 0x60, 0xfc, + 0x59, 0x11, 0x8a, 0x1d, 0xf7, 0xdc, 0x73, 0xfa, 0xe8, 0x5b, 0x3a, 0xe2, 0x23, 0x4f, 0xc5, 0xf6, + 0x8b, 0xdf, 0xe8, 0x89, 0x15, 0x5f, 0xb7, 0x93, 0x93, 0x9e, 0x58, 0xd1, 0x45, 0x3b, 0xcb, 0x30, + 0xe7, 0xeb, 0xf7, 0xe5, 0x14, 0x7c, 0xf4, 0x76, 0x8f, 0xf6, 0xcb, 0x82, 0x76, 0x37, 0x82, 0x28, + 0x8b, 0xee, 0x71, 0xc1, 0x21, 0xa3, 0x58, 0xcb, 0x32, 0x42, 0x70, 0xc0, 0x6e, 0x43, 0x51, 0x06, + 0xb4, 0x51, 0x04, 0x12, 0xb9, 0xa7, 0x4b, 0x10, 0x52, 0x83, 0xcf, 0xc9, 0x84, 0x1b, 0x09, 0xb2, + 0x39, 0xb3, 0xaa, 0x80, 0x5b, 0x82, 0xd6, 0xee, 0x42, 0x85, 0xf0, 0x09, 0xa5, 0x24, 0x5d, 0x32, + 0x11, 0x84, 0x08, 0x29, 0xd7, 0x4e, 0x95, 0x53, 0xaf, 0x9d, 0x42, 0xe7, 0xe1, 0x88, 0xcb, 0x52, + 0x17, 0x81, 0x2e, 0x1b, 0xd2, 0xe0, 0xea, 0xce, 0x35, 0x79, 0xa6, 0x42, 0xa1, 0xc7, 0xea, 0x4c, + 0xe5, 0x2d, 0xa8, 0x9d, 0xd8, 0xc3, 0xe1, 0xb1, 0xdd, 0x7f, 0x41, 0x47, 0x01, 0x55, 0x3a, 0xfd, + 0x54, 0x40, 0x3c, 0x0b, 0xb8, 0x0b, 0x15, 0x6d, 0x96, 0xd1, 0xdf, 0x32, 0x6f, 0x42, 0x3c, 0xbf, + 0xd3, 0x27, 0x7c, 0xf5, 0xd7, 0x38, 0xe1, 0xd3, 0xfc, 0x4e, 0xe7, 0x93, 0x7e, 0xa7, 0xb7, 0x90, + 0x9b, 0x4a, 0x07, 0xc3, 0x06, 0xdd, 0x6c, 0x63, 0x0f, 0x06, 0xe8, 0x60, 0x48, 0xd7, 0x48, 0xe2, + 0xe0, 0x51, 0xfa, 0x02, 0xe9, 0x12, 0x04, 0x23, 0x94, 0x3b, 0x74, 0x4c, 0x3d, 0xb6, 0x9d, 0x01, + 0x86, 0x18, 0xd0, 0xe9, 0x41, 0xd1, 0x1e, 0x85, 0x87, 0xb6, 0x33, 0x60, 0xf7, 0xa0, 0xaa, 0x92, + 0x71, 0x77, 0x5c, 0xa4, 0xf1, 0x97, 0xc9, 0x62, 0x4f, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe2, 0xf8, + 0xe1, 0x8a, 0x44, 0x41, 0x3a, 0xf8, 0x00, 0x7d, 0x7a, 0x42, 0x8e, 0x51, 0xc2, 0xf5, 0xc7, 0xb7, + 0xa2, 0x60, 0x40, 0xa4, 0x52, 0xf5, 0x9f, 0x8c, 0x63, 0x84, 0x29, 0x84, 0x3b, 0xb2, 0xd1, 0xad, + 0x24, 0xe4, 0x5f, 0x89, 0x8a, 0x36, 0x3a, 0x42, 0x60, 0xdf, 0xd6, 0xf4, 0xd7, 0x26, 0x22, 0xdf, + 0x9e, 0x2a, 0xff, 0xba, 0x08, 0xab, 0x3b, 0x00, 0x4e, 0x20, 0x76, 0x99, 0x80, 0xbb, 0x03, 0x0c, + 0xf8, 0x2d, 0x99, 0x65, 0x27, 0x78, 0x46, 0x80, 0x9f, 0xaf, 0x62, 0xdb, 0x82, 0xaa, 0xde, 0x4d, + 0x56, 0x82, 0xfc, 0xc1, 0x61, 0x7b, 0xbf, 0x71, 0x83, 0x55, 0xa0, 0xd8, 0x6d, 0xf7, 0x7a, 0xbb, + 0x68, 0xe9, 0xab, 0x42, 0x29, 0x8a, 0x4a, 0xcc, 0x8a, 0xaf, 0xd6, 0xe6, 0x66, 0xfb, 0xb0, 0xd7, + 0xde, 0x6a, 0xe4, 0xbe, 0x9f, 0x2f, 0x65, 0x1b, 0x39, 0xe3, 0xcf, 0x73, 0x50, 0xd1, 0x46, 0xe1, + 0xe5, 0xcc, 0xf8, 0x0e, 0x00, 0x6a, 0x92, 0xb1, 0xff, 0x69, 0xde, 0x2c, 0x0b, 0x08, 0x4d, 0xbe, + 0x6e, 0xa3, 0xc8, 0xd1, 0x95, 0x49, 0xca, 0x46, 0xf1, 0x16, 0xd4, 0xe8, 0xf6, 0x21, 0xdd, 0x5e, + 0x5b, 0x30, 0xab, 0x04, 0x94, 0xac, 0x1a, 0xc3, 0x95, 0x11, 0x09, 0x63, 0xe5, 0xe4, 0x5d, 0x24, + 0x04, 0xc2, 0x68, 0x39, 0x0c, 0x75, 0x0c, 0xbc, 0xe1, 0x39, 0x27, 0x0c, 0x92, 0x08, 0x2b, 0x12, + 0xd6, 0x93, 0x81, 0xd7, 0x92, 0x1f, 0x6a, 0xf1, 0xb2, 0x05, 0xb3, 0x4a, 0x40, 0x59, 0xd1, 0x37, + 0x14, 0x01, 0x95, 0x90, 0x80, 0x56, 0x67, 0xa9, 0x21, 0x41, 0x3c, 0xbb, 0x33, 0xc7, 0x88, 0x65, + 0x24, 0x8c, 0xaf, 0xcd, 0xe6, 0x7b, 0xf5, 0x71, 0x22, 0x7b, 0x1f, 0xd8, 0x68, 0x3c, 0xb6, 0x52, + 0x0e, 0xf8, 0xf2, 0xe6, 0xfc, 0x68, 0x3c, 0xee, 0x69, 0xe7, 0x5f, 0x3f, 0x87, 0xb3, 0xc7, 0x2f, + 0x80, 0xb5, 0xc4, 0x02, 0xc6, 0x26, 0x46, 0xaa, 0x58, 0xcc, 0x96, 0x33, 0x3a, 0x5b, 0x4e, 0xe1, + 0x7e, 0xd9, 0x54, 0xee, 0xf7, 0x32, 0x3e, 0x61, 0x6c, 0x43, 0xe5, 0x50, 0xbb, 0xdb, 0xec, 0x9e, + 0xd8, 0x21, 0xd4, 0xad, 0x66, 0xb4, 0x77, 0xd0, 0x99, 0xa2, 0x2f, 0x2f, 0x33, 0xd3, 0x5a, 0x93, + 0xd5, 0x5a, 0x63, 0xfc, 0xb3, 0x0c, 0xdd, 0x1b, 0x13, 0x35, 0x3e, 0xbe, 0x4e, 0x4d, 0x99, 0xdf, + 0xe2, 0xb0, 0xf6, 0x8a, 0x32, 0xbb, 0xc9, 0x88, 0x74, 0x6c, 0x9a, 0xe5, 0x9d, 0x9c, 0x04, 0x5c, + 0xf9, 0x78, 0x54, 0x10, 0x76, 0x80, 0x20, 0x25, 0x7c, 0x0b, 0x09, 0xdf, 0xa1, 0xf2, 0x03, 0xe9, + 0xd8, 0x21, 0x84, 0xef, 0x3d, 0xfb, 0x52, 0xd6, 0x1a, 0x08, 0x11, 0x44, 0xda, 0x07, 0x54, 0xe4, + 0x6b, 0xf4, 0x6d, 0xfc, 0x63, 0x19, 0x79, 0x3f, 0x3d, 0xbe, 0x0f, 0xa0, 0x14, 0x95, 0x9a, 0xdc, + 0x61, 0x15, 0x66, 0x94, 0x2e, 0xf6, 0x71, 0x3c, 0x0c, 0x49, 0xb4, 0x98, 0x16, 0x17, 0xda, 0x78, + 0x3a, 0x5a, 0xab, 0xbf, 0x0e, 0xec, 0xc4, 0xf1, 0xa7, 0x91, 0x69, 0xb1, 0x35, 0x30, 0x45, 0xc3, + 0x36, 0x8e, 0x60, 0x51, 0x71, 0x09, 0x4d, 0x23, 0x48, 0x4e, 0x5e, 0xe6, 0x15, 0x4c, 0x3e, 0x3b, + 0xc3, 0xe4, 0x8d, 0x9f, 0xe4, 0xa1, 0xa8, 0xee, 0x09, 0x4c, 0xbb, 0xdb, 0xae, 0x9c, 0xbc, 0xdb, + 0xae, 0x99, 0xb8, 0x07, 0x09, 0xa7, 0x5e, 0xee, 0xf7, 0xef, 0x4e, 0x6f, 0xd9, 0x9a, 0xad, 0x22, + 0xb1, 0x6d, 0xaf, 0x40, 0x7e, 0x6c, 0x87, 0x67, 0x78, 0x2e, 0x49, 0xc4, 0x83, 0xdf, 0xca, 0x86, + 0x51, 0x48, 0xda, 0x30, 0xd2, 0xee, 0x01, 0x24, 0x91, 0x74, 0xe6, 0x1e, 0xc0, 0x5b, 0x40, 0xf2, + 0x85, 0xe6, 0xe2, 0x56, 0x42, 0x80, 0xd8, 0x8b, 0x92, 0xe2, 0x48, 0x69, 0x5a, 0x1c, 0x79, 0x6d, + 0x51, 0xe1, 0x5b, 0x30, 0x47, 0x77, 0x68, 0xc8, 0x08, 0x5f, 0xb5, 0xa1, 0xc8, 0x31, 0x54, 0xff, + 0x29, 0xee, 0xc1, 0x94, 0xb8, 0xfa, 0xa5, 0x5a, 0x95, 0xc4, 0xa5, 0x5a, 0xba, 0x6d, 0xa5, 0x9a, + 0xb4, 0xad, 0xdc, 0x87, 0x46, 0x34, 0xa0, 0x78, 0x52, 0xe9, 0x06, 0x32, 0x7e, 0xb0, 0xae, 0xe0, + 0x82, 0x4b, 0xee, 0x07, 0xf1, 0x86, 0x58, 0x4f, 0x6c, 0x88, 0x82, 0x87, 0xb5, 0xc2, 0x90, 0x8f, + 0xc6, 0xa1, 0xdc, 0x10, 0x31, 0xc2, 0x48, 0x6f, 0xa0, 0xd8, 0x61, 0x64, 0xfc, 0x2e, 0xb9, 0x96, + 0x74, 0xf6, 0xad, 0xed, 0xdd, 0xce, 0xd3, 0x9d, 0x5e, 0x23, 0x23, 0x3e, 0xbb, 0x47, 0x9b, 0x9b, + 0xed, 0xf6, 0x16, 0xee, 0x38, 0x00, 0x73, 0xdb, 0xad, 0x8e, 0xd8, 0x7d, 0x72, 0xc6, 0xef, 0x66, + 0xa1, 0xa2, 0x15, 0xcf, 0x9e, 0x44, 0xa3, 0x42, 0xf7, 0x2e, 0xdd, 0x99, 0x6d, 0xc2, 0xba, 0x62, + 0xc5, 0xda, 0xb0, 0x44, 0xb7, 0x1e, 0x66, 0xaf, 0xbd, 0xf5, 0x90, 0xbd, 0x03, 0xf3, 0x36, 0x95, + 0x10, 0x8d, 0x82, 0x3c, 0x85, 0x97, 0x60, 0x39, 0x08, 0xe8, 0xd8, 0x19, 0xef, 0x27, 0x02, 0x2f, + 0xaf, 0x7c, 0x29, 0xa3, 0x2d, 0x05, 0x07, 0xab, 0x78, 0x62, 0x3b, 0xc3, 0x89, 0xcf, 0xa5, 0xd5, + 0x3c, 0xda, 0x99, 0x09, 0x6a, 0xaa, 0x64, 0xe3, 0x43, 0x80, 0xb8, 0xcd, 0xc9, 0xc1, 0xb9, 0x91, + 0x1c, 0x9c, 0x8c, 0x36, 0x38, 0x59, 0x63, 0x8b, 0xd8, 0x88, 0x1c, 0xe8, 0xe8, 0xd8, 0xed, 0x1b, + 0xa0, 0x0e, 0x02, 0x2d, 0x74, 0xaf, 0x1e, 0x0f, 0x79, 0xa8, 0x6e, 0x09, 0x58, 0x90, 0x29, 0x9d, + 0x28, 0x41, 0xdd, 0xa8, 0x11, 0x97, 0x12, 0x73, 0x23, 0x49, 0x92, 0xd3, 0xdc, 0x48, 0xa2, 0x9a, + 0x51, 0xba, 0xb1, 0x06, 0xcd, 0x2d, 0x2e, 0x4a, 0x6b, 0x0d, 0x87, 0x53, 0xcd, 0x31, 0x6e, 0xc1, + 0xcd, 0x94, 0x34, 0x79, 0x08, 0xf1, 0x29, 0x2c, 0xb7, 0xe8, 0x42, 0x80, 0x9f, 0x57, 0xe4, 0x9f, + 0xd1, 0x84, 0x95, 0xe9, 0x22, 0x65, 0x65, 0xdb, 0xb0, 0xb0, 0xc5, 0x8f, 0x27, 0xa7, 0xbb, 0xfc, + 0x3c, 0xae, 0x88, 0x41, 0x3e, 0x38, 0xf3, 0x2e, 0xe4, 0xf8, 0xe0, 0x6f, 0xf4, 0x32, 0x14, 0x38, + 0x56, 0x30, 0xe6, 0x7d, 0x75, 0x10, 0x8d, 0x90, 0xee, 0x98, 0xf7, 0x8d, 0x27, 0xc0, 0xf4, 0x72, + 0xe4, 0x78, 0x09, 0x2d, 0x61, 0x72, 0x6c, 0x05, 0x57, 0x41, 0xc8, 0x47, 0x2a, 0xe2, 0x0d, 0x82, + 0xc9, 0x71, 0x97, 0x20, 0xc6, 0xbb, 0x50, 0x3d, 0xb4, 0xaf, 0x4c, 0xfe, 0x85, 0x0c, 0x2c, 0x5b, + 0x85, 0xe2, 0xd8, 0xbe, 0x12, 0x6c, 0x20, 0xb2, 0x49, 0x61, 0xb2, 0xf1, 0x87, 0x79, 0x98, 0x23, + 0x4c, 0x76, 0x8f, 0x6e, 0xde, 0x75, 0x5c, 0x5c, 0x86, 0x8a, 0x51, 0x6a, 0xa0, 0x19, 0x5e, 0x9a, + 0x9d, 0xe5, 0xa5, 0xf2, 0x00, 0x4d, 0xdd, 0x38, 0xa4, 0xac, 0x07, 0xee, 0x64, 0xa4, 0xae, 0x19, + 0x4a, 0x46, 0xc5, 0xe7, 0xe3, 0x9b, 0x95, 0x29, 0x64, 0x38, 0x69, 0xdf, 0x8d, 0x75, 0x11, 0x6a, + 0x9d, 0xda, 0x22, 0x24, 0xbb, 0xd4, 0x41, 0xa9, 0x0a, 0x4f, 0x51, 0x45, 0x4b, 0x26, 0x15, 0x9e, + 0x19, 0xc5, 0xa6, 0xf4, 0x6a, 0xc5, 0x86, 0x4e, 0xd6, 0x5e, 0xa2, 0xd8, 0xc0, 0x6b, 0x28, 0x36, + 0xaf, 0x61, 0x5b, 0xbd, 0x09, 0x25, 0xdc, 0xf7, 0x35, 0xee, 0x29, 0xf6, 0x7b, 0xc1, 0x3d, 0x3f, + 0xd2, 0x44, 0x7f, 0x72, 0xec, 0xb8, 0x15, 0x2f, 0x13, 0x93, 0x7f, 0xf1, 0x8b, 0xb1, 0x59, 0x3d, + 0x87, 0xa2, 0x84, 0x0a, 0x82, 0x76, 0xed, 0x91, 0xba, 0xb4, 0x0d, 0x7f, 0x8b, 0x61, 0xc3, 0x9b, + 0xa6, 0xbe, 0x98, 0x38, 0x3e, 0x1f, 0xa8, 0xdb, 0x78, 0x1c, 0x5c, 0xa3, 0x02, 0x22, 0x3a, 0x28, + 0xd4, 0x10, 0xd7, 0xbb, 0x70, 0xe5, 0x75, 0x1f, 0x45, 0x27, 0x78, 0x26, 0x3e, 0x0d, 0x06, 0x0d, + 0xbc, 0xb6, 0x71, 0xec, 0xf9, 0x6a, 0x73, 0x32, 0x7e, 0x92, 0x81, 0x86, 0x5c, 0x5d, 0x51, 0x9a, + 0xae, 0x05, 0x14, 0xae, 0xf3, 0x43, 0x78, 0xf9, 0xdd, 0x3a, 0x06, 0xd4, 0xf0, 0xf0, 0x23, 0xda, + 0xa9, 0xe8, 0xf0, 0xa6, 0x22, 0x80, 0xdb, 0x72, 0xb7, 0x7a, 0x03, 0x2a, 0xca, 0x07, 0x7a, 0xe4, + 0x0c, 0xd5, 0x25, 0xea, 0xe4, 0x04, 0xbd, 0xe7, 0x0c, 0xd5, 0x46, 0xe7, 0xdb, 0x32, 0x7a, 0x37, + 0x83, 0x1b, 0x9d, 0x69, 0x87, 0xdc, 0xf8, 0x37, 0x19, 0x58, 0xd0, 0xba, 0x22, 0xd7, 0xed, 0xc7, + 0x50, 0x8d, 0xee, 0x4b, 0xe5, 0x91, 0xe4, 0xb5, 0x9a, 0x64, 0x34, 0x71, 0xb6, 0x4a, 0x3f, 0x82, + 0x04, 0xa2, 0x31, 0x03, 0xfb, 0x8a, 0x1c, 0x75, 0x27, 0x23, 0xa5, 0xdc, 0x0c, 0xec, 0xab, 0x6d, + 0xce, 0xbb, 0x93, 0x91, 0x50, 0x5d, 0x2f, 0x38, 0x7f, 0x11, 0x21, 0x90, 0xcc, 0x05, 0x02, 0x26, + 0x31, 0x0c, 0xa8, 0x8d, 0x3c, 0x37, 0x3c, 0x8b, 0x50, 0xa4, 0xd4, 0x89, 0x40, 0xc2, 0x31, 0xfe, + 0x34, 0x0b, 0x8b, 0x74, 0xc4, 0x26, 0x8f, 0x36, 0x25, 0xeb, 0x6a, 0xc2, 0x1c, 0x9d, 0x36, 0x12, + 0xf3, 0xda, 0xb9, 0x61, 0xca, 0x6f, 0xf6, 0xad, 0xd7, 0x3c, 0x16, 0x54, 0x01, 0xc2, 0xd7, 0x0c, + 0x7f, 0x6e, 0x76, 0xf8, 0xaf, 0x1f, 0xde, 0x34, 0x43, 0x67, 0x21, 0xcd, 0xd0, 0xf9, 0x3a, 0xe6, + 0xc5, 0x99, 0x50, 0xd6, 0xa2, 0xc4, 0xd1, 0x42, 0x59, 0x9f, 0xc0, 0x6a, 0x02, 0x07, 0xb9, 0xb5, + 0x73, 0xe2, 0x70, 0x75, 0x9b, 0xca, 0x92, 0x86, 0xdd, 0x55, 0x69, 0x1b, 0x45, 0x28, 0x04, 0x7d, + 0x6f, 0xcc, 0x8d, 0x15, 0x58, 0x4a, 0x8e, 0xaa, 0xdc, 0x26, 0x7e, 0x2f, 0x03, 0x4d, 0xe9, 0x96, + 0xe2, 0xb8, 0xa7, 0x3b, 0x4e, 0x10, 0x7a, 0x7e, 0x74, 0xaf, 0xe8, 0x1d, 0x80, 0x20, 0xb4, 0x7d, + 0xa9, 0x6d, 0xca, 0xfb, 0x43, 0x10, 0x82, 0x9a, 0xe4, 0x4d, 0x28, 0x71, 0x77, 0x40, 0x89, 0x44, + 0x0d, 0x45, 0xee, 0x0e, 0x94, 0x1e, 0x3a, 0x23, 0x7f, 0xd7, 0x92, 0xea, 0x85, 0x0c, 0xe7, 0x17, + 0xa3, 0xc3, 0xcf, 0x71, 0xe3, 0xcd, 0x47, 0xe1, 0xfc, 0x7b, 0xf6, 0x25, 0x3a, 0x79, 0x06, 0xc6, + 0x3f, 0xc8, 0xc2, 0x7c, 0xdc, 0x3e, 0xba, 0x0b, 0xe4, 0xe5, 0xb7, 0x9a, 0xdc, 0x93, 0xe4, 0xe0, + 0x08, 0xf9, 0x5d, 0x3b, 0x78, 0x2c, 0xd1, 0xe2, 0xec, 0xb8, 0xcc, 0x80, 0x8a, 0xc2, 0xf0, 0x26, + 0xa1, 0x76, 0xbd, 0x5f, 0x99, 0x50, 0x0e, 0x26, 0xa1, 0x50, 0xb8, 0x84, 0xe6, 0xe9, 0xb8, 0x52, + 0xe5, 0x29, 0xd8, 0xa3, 0xb0, 0x83, 0xaf, 0x06, 0x08, 0xb0, 0xc8, 0x46, 0x13, 0x29, 0xb0, 0x04, + 0x7e, 0x83, 0xe4, 0x6c, 0x9a, 0x39, 0x94, 0xb1, 0x75, 0x21, 0x94, 0x2e, 0x50, 0x8e, 0x84, 0xd0, + 0x37, 0xa0, 0x42, 0x85, 0xc7, 0x91, 0xcb, 0x79, 0xb3, 0x8c, 0x35, 0x60, 0xba, 0x3c, 0x04, 0xf2, + 0x26, 0x09, 0xd5, 0x17, 0xa8, 0x2a, 0xf4, 0xfa, 0xf8, 0xdb, 0x19, 0xb8, 0x99, 0x32, 0x6d, 0x72, + 0x95, 0x6f, 0xc2, 0xc2, 0x49, 0x94, 0xa8, 0x46, 0x97, 0x96, 0xfa, 0x8a, 0x62, 0xab, 0xc9, 0x31, + 0x35, 0x1b, 0x27, 0x49, 0x40, 0xac, 0x74, 0xd1, 0x0c, 0x26, 0xe2, 0xe2, 0x51, 0xe9, 0xa2, 0x69, + 0x24, 0x7d, 0xe7, 0x10, 0xd6, 0xda, 0x97, 0x82, 0x63, 0x6c, 0xea, 0xcf, 0x5e, 0x28, 0x32, 0x4a, + 0x1e, 0x30, 0x67, 0x5e, 0xeb, 0x80, 0x79, 0x40, 0x81, 0xb4, 0x51, 0x59, 0x3f, 0x4d, 0x21, 0xb8, + 0x81, 0x8a, 0x3c, 0xf4, 0x6c, 0x87, 0x0a, 0x90, 0xef, 0x47, 0xcf, 0x75, 0x18, 0x01, 0xcc, 0xef, + 0x4d, 0x86, 0xa1, 0x13, 0xbf, 0xe0, 0xc1, 0xbe, 0x25, 0xf3, 0x60, 0x3d, 0x6a, 0xd4, 0x52, 0x2b, + 0x82, 0xa8, 0x22, 0x1c, 0xac, 0x91, 0x28, 0xc8, 0x9a, 0xad, 0x6f, 0x7e, 0x94, 0xac, 0xc1, 0xb8, + 0x09, 0xab, 0xf1, 0x17, 0x0d, 0x9b, 0xda, 0x6a, 0xfe, 0x69, 0x86, 0x3c, 0xca, 0x93, 0xaf, 0x89, + 0xb0, 0x36, 0x2c, 0x06, 0x8e, 0x7b, 0x3a, 0xe4, 0x7a, 0xf1, 0x81, 0x1c, 0x84, 0xe5, 0x64, 0xdb, + 0xe4, 0x8b, 0x23, 0xe6, 0x02, 0xe5, 0x88, 0x4b, 0x0b, 0xd8, 0xc6, 0x75, 0x8d, 0x8c, 0xc9, 0x62, + 0x6a, 0x34, 0x66, 0x1b, 0xdf, 0x81, 0x7a, 0xb2, 0x22, 0xf6, 0x91, 0x8c, 0x3f, 0x8f, 0x5b, 0x95, + 0x9b, 0x0a, 0xce, 0x8d, 0x09, 0xa2, 0x12, 0x8f, 0x7d, 0x60, 0xfc, 0xdd, 0x0c, 0x34, 0x4d, 0x2e, + 0x28, 0x57, 0x6b, 0xa5, 0xa2, 0x99, 0x8f, 0x67, 0x4a, 0xbd, 0xbe, 0xaf, 0x2a, 0xac, 0x5d, 0xb5, + 0xe8, 0xeb, 0xd7, 0x4e, 0xc6, 0xce, 0x8d, 0x99, 0x1e, 0x6d, 0x94, 0x60, 0x8e, 0x50, 0x8c, 0x55, + 0x58, 0x96, 0xed, 0x51, 0x6d, 0x89, 0xad, 0x87, 0x89, 0x1a, 0x13, 0xd6, 0xc3, 0x35, 0x68, 0x52, + 0xa0, 0xa9, 0xde, 0x09, 0x99, 0x71, 0x0b, 0xd8, 0x9e, 0xdd, 0xb7, 0x7d, 0xcf, 0x73, 0x0f, 0xb9, + 0x2f, 0xfd, 0x73, 0x51, 0xc2, 0x44, 0xe3, 0x9a, 0x12, 0x85, 0xe9, 0x4b, 0x5d, 0x6a, 0xea, 0xb9, + 0xca, 0x1d, 0x89, 0xbe, 0x0c, 0x13, 0x16, 0x37, 0xec, 0x17, 0x5c, 0x95, 0xa4, 0x86, 0xe8, 0x13, + 0xa8, 0x8c, 0xa3, 0x42, 0xd5, 0xb8, 0xab, 0xfb, 0x31, 0x66, 0xab, 0x35, 0x75, 0x6c, 0xe3, 0x31, + 0x2c, 0x25, 0xcb, 0x94, 0xac, 0x63, 0x0d, 0x4a, 0x23, 0x09, 0x93, 0xad, 0x8b, 0xbe, 0x8d, 0xdf, + 0x29, 0x41, 0x51, 0xea, 0x73, 0x6c, 0x1d, 0xf2, 0x7d, 0xe5, 0x12, 0x16, 0x5f, 0xbb, 0x24, 0x53, + 0xd5, 0xff, 0x4d, 0x74, 0x0c, 0x13, 0x78, 0xec, 0x13, 0xa8, 0x27, 0xad, 0xa2, 0x53, 0x61, 0xec, + 0x49, 0x73, 0x66, 0xad, 0x3f, 0x65, 0xff, 0x2a, 0xc7, 0x9b, 0x23, 0xc9, 0x0c, 0xa5, 0x33, 0x6d, + 0xf7, 0xf4, 0x5c, 0x21, 0x6f, 0x07, 0x67, 0xb6, 0xf5, 0xf8, 0xc9, 0x87, 0x32, 0x8e, 0xbd, 0x82, + 0xc0, 0xee, 0x99, 0xfd, 0xf8, 0xc9, 0x87, 0xd3, 0x92, 0xb4, 0x8c, 0x62, 0xd7, 0x24, 0xe9, 0x25, + 0x28, 0xd0, 0xed, 0x9d, 0xe4, 0xdb, 0x43, 0x1f, 0xec, 0x11, 0x2c, 0x49, 0xb5, 0xd5, 0x92, 0x5e, + 0xd8, 0xc4, 0x05, 0x4b, 0x14, 0xf8, 0x26, 0xd3, 0xba, 0x98, 0x44, 0x67, 0x43, 0x2b, 0x30, 0x77, + 0x16, 0x5f, 0xc5, 0x5a, 0x33, 0xe5, 0x97, 0xf1, 0xa7, 0x05, 0xa8, 0x68, 0x83, 0xc2, 0xaa, 0x50, + 0x32, 0xdb, 0xdd, 0xb6, 0xf9, 0x59, 0x7b, 0xab, 0x71, 0x83, 0xdd, 0x87, 0xb7, 0x3b, 0xfb, 0x9b, + 0x07, 0xa6, 0xd9, 0xde, 0xec, 0x59, 0x07, 0xa6, 0xa5, 0x2e, 0xff, 0x3a, 0x6c, 0x3d, 0xdf, 0x6b, + 0xef, 0xf7, 0xac, 0xad, 0x76, 0xaf, 0xd5, 0xd9, 0xed, 0x36, 0x32, 0xec, 0x36, 0x34, 0x63, 0x4c, + 0x95, 0xdc, 0xda, 0x3b, 0x38, 0xda, 0xef, 0x35, 0xb2, 0xec, 0x2e, 0xdc, 0xda, 0xee, 0xec, 0xb7, + 0x76, 0xad, 0x18, 0x67, 0x73, 0xb7, 0xf7, 0x99, 0xd5, 0xfe, 0x95, 0xc3, 0x8e, 0xf9, 0xbc, 0x91, + 0x4b, 0x43, 0x10, 0xca, 0xb8, 0x2a, 0x21, 0xcf, 0x6e, 0xc2, 0x32, 0x21, 0x50, 0x16, 0xab, 0x77, + 0x70, 0x60, 0x75, 0x0f, 0x0e, 0xf6, 0x1b, 0x05, 0xb6, 0x00, 0xb5, 0xce, 0xfe, 0x67, 0xad, 0xdd, + 0xce, 0x96, 0x65, 0xb6, 0x5b, 0xbb, 0x7b, 0x8d, 0x39, 0xb6, 0x08, 0xf3, 0xd3, 0x78, 0x45, 0x51, + 0x84, 0xc2, 0x3b, 0xd8, 0xef, 0x1c, 0xec, 0x5b, 0x9f, 0xb5, 0xcd, 0x6e, 0xe7, 0x60, 0xbf, 0x51, + 0x62, 0x2b, 0xc0, 0x92, 0x49, 0x3b, 0x7b, 0xad, 0xcd, 0x46, 0x99, 0x2d, 0xc3, 0x42, 0x12, 0xfe, + 0xac, 0xfd, 0xbc, 0x01, 0xac, 0x09, 0x4b, 0xd4, 0x30, 0x6b, 0xa3, 0xbd, 0x7b, 0xf0, 0xb9, 0xb5, + 0xd7, 0xd9, 0xef, 0xec, 0x1d, 0xed, 0x35, 0x2a, 0x78, 0xa7, 0x60, 0xbb, 0x6d, 0x75, 0xf6, 0xbb, + 0x47, 0xdb, 0xdb, 0x9d, 0xcd, 0x4e, 0x7b, 0xbf, 0xd7, 0xa8, 0x52, 0xcd, 0x69, 0x1d, 0xaf, 0x89, + 0x0c, 0x32, 0x54, 0xc3, 0xda, 0xea, 0x74, 0x5b, 0x1b, 0xbb, 0xed, 0xad, 0x46, 0x9d, 0xdd, 0x81, + 0x9b, 0xbd, 0xf6, 0xde, 0xe1, 0x81, 0xd9, 0x32, 0x9f, 0xab, 0x50, 0x0e, 0x6b, 0xbb, 0xd5, 0xd9, + 0x3d, 0x32, 0xdb, 0x8d, 0x79, 0xf6, 0x26, 0xdc, 0x31, 0xdb, 0x9f, 0x1e, 0x75, 0xcc, 0xf6, 0x96, + 0xb5, 0x7f, 0xb0, 0xd5, 0xb6, 0xb6, 0xdb, 0xad, 0xde, 0x91, 0xd9, 0xb6, 0xf6, 0x3a, 0xdd, 0x6e, + 0x67, 0xff, 0x69, 0xa3, 0xc1, 0xde, 0x86, 0x7b, 0x11, 0x4a, 0x54, 0xc0, 0x14, 0xd6, 0x82, 0xe8, + 0x9f, 0x9a, 0xd2, 0xfd, 0xf6, 0xaf, 0xf4, 0xac, 0xc3, 0x76, 0xdb, 0x6c, 0x30, 0xb6, 0x06, 0x2b, + 0x71, 0xf5, 0x54, 0x81, 0xac, 0x7b, 0x51, 0xa4, 0x1d, 0xb6, 0xcd, 0xbd, 0xd6, 0xbe, 0x98, 0xe0, + 0x44, 0xda, 0x92, 0x68, 0x76, 0x9c, 0x36, 0xdd, 0xec, 0x65, 0xc6, 0xa0, 0xae, 0xcd, 0xca, 0x76, + 0xcb, 0x6c, 0xac, 0xb0, 0x79, 0xa8, 0xec, 0x1d, 0x1e, 0x5a, 0xbd, 0xce, 0x5e, 0xfb, 0xe0, 0xa8, + 0xd7, 0x58, 0x65, 0xcb, 0xd0, 0xe8, 0xec, 0xf7, 0xda, 0xa6, 0x98, 0x6b, 0x95, 0xf5, 0x7f, 0x16, + 0xd9, 0x12, 0xcc, 0xab, 0x96, 0x2a, 0xe8, 0x5f, 0x14, 0xd9, 0x2a, 0xb0, 0xa3, 0x7d, 0xb3, 0xdd, + 0xda, 0x12, 0x03, 0x17, 0x25, 0xfc, 0xaf, 0xa2, 0xb4, 0x90, 0xfc, 0x24, 0x17, 0x6d, 0xd6, 0xb1, + 0xcb, 0x41, 0xf2, 0x62, 0xee, 0xaa, 0x76, 0xa1, 0xf6, 0xab, 0x9e, 0xcc, 0xd0, 0x54, 0xab, 0xdc, + 0x8c, 0x6a, 0x35, 0xa3, 0xbb, 0xd7, 0x74, 0xd9, 0xef, 0x2d, 0xa8, 0x8d, 0xe8, 0x92, 0x6e, 0x79, + 0x19, 0x2f, 0x48, 0xff, 0x1b, 0x02, 0xd2, 0x4d, 0xbc, 0x33, 0x6f, 0x46, 0x14, 0x66, 0xdf, 0x8c, + 0x48, 0x93, 0xef, 0xe7, 0xd2, 0xe4, 0xfb, 0x07, 0xb0, 0x40, 0xac, 0xc9, 0x71, 0x9d, 0x91, 0xd2, + 0x9a, 0x49, 0x0a, 0x9c, 0x47, 0x16, 0x45, 0x70, 0xa5, 0x4e, 0x28, 0x95, 0x43, 0xb2, 0x90, 0xa2, + 0xd4, 0x36, 0x12, 0x9a, 0x06, 0x71, 0x8e, 0x48, 0xd3, 0x88, 0x6a, 0xb0, 0x2f, 0xe3, 0x1a, 0x2a, + 0x5a, 0x0d, 0x04, 0xc7, 0x1a, 0x1e, 0xc0, 0x02, 0xbf, 0x0c, 0x7d, 0xdb, 0xf2, 0xc6, 0xf6, 0x17, + 0x13, 0x34, 0xe1, 0xda, 0xa8, 0xc3, 0x57, 0xcd, 0x79, 0x4c, 0x38, 0x40, 0xf8, 0x96, 0x1d, 0xda, + 0x0f, 0xbe, 0x84, 0x8a, 0x76, 0x81, 0x3b, 0x5b, 0x85, 0xc5, 0xcf, 0x3b, 0xbd, 0xfd, 0x76, 0xb7, + 0x6b, 0x1d, 0x1e, 0x6d, 0x3c, 0x6b, 0x3f, 0xb7, 0x76, 0x5a, 0xdd, 0x9d, 0xc6, 0x0d, 0xb1, 0x68, + 0xf7, 0xdb, 0xdd, 0x5e, 0x7b, 0x2b, 0x01, 0xcf, 0xb0, 0x37, 0x60, 0xed, 0x68, 0xff, 0xa8, 0xdb, + 0xde, 0xb2, 0xd2, 0xf2, 0x65, 0x05, 0x95, 0xca, 0xf4, 0x94, 0xec, 0xb9, 0x07, 0xbf, 0x01, 0xf5, + 0x64, 0x54, 0x33, 0x03, 0x98, 0xdb, 0x6d, 0x3f, 0x6d, 0x6d, 0x3e, 0xa7, 0x5b, 0x47, 0xbb, 0xbd, + 0x56, 0xaf, 0xb3, 0x69, 0xc9, 0x5b, 0x46, 0x05, 0x47, 0xc8, 0xb0, 0x0a, 0x14, 0x5b, 0xfb, 0x9b, + 0x3b, 0x07, 0x66, 0xb7, 0x91, 0x65, 0xb7, 0x61, 0x55, 0xd1, 0xea, 0xe6, 0xc1, 0xde, 0x5e, 0xa7, + 0x87, 0xcc, 0xb0, 0xf7, 0xfc, 0x50, 0x90, 0xe6, 0x03, 0x1b, 0xca, 0xf1, 0x35, 0xa9, 0xc8, 0x60, + 0x3a, 0xbd, 0x4e, 0xab, 0x17, 0x73, 0xd7, 0xc6, 0x0d, 0xc1, 0xbf, 0x62, 0x30, 0xde, 0x72, 0xda, + 0xc8, 0x50, 0xe0, 0x97, 0x02, 0x52, 0xed, 0x8d, 0xac, 0x58, 0x54, 0x31, 0x74, 0xe3, 0xa0, 0x27, + 0xba, 0xf0, 0x1d, 0xa8, 0x27, 0xdd, 0xfb, 0x92, 0x07, 0xbf, 0x6b, 0xb0, 0xb2, 0xd1, 0xee, 0x7d, + 0xde, 0x6e, 0xef, 0xe3, 0xe8, 0x6c, 0xb6, 0xf7, 0x7b, 0x66, 0x6b, 0xb7, 0xd3, 0x7b, 0xde, 0xc8, + 0x3c, 0xf8, 0x04, 0x1a, 0xd3, 0xb6, 0xb4, 0x84, 0xf1, 0xf1, 0x65, 0x56, 0xca, 0x07, 0xff, 0x22, + 0x07, 0x10, 0xc7, 0x98, 0x08, 0x36, 0xb9, 0xd5, 0xea, 0xb5, 0x76, 0x0f, 0xc4, 0x14, 0x98, 0x07, + 0x3d, 0xc1, 0xfd, 0xcc, 0xf6, 0xa7, 0x8d, 0x1b, 0xa9, 0x29, 0x07, 0x87, 0xbd, 0x46, 0x46, 0xcc, + 0x36, 0x75, 0x67, 0xd7, 0x32, 0x0f, 0x8e, 0x3a, 0xfb, 0x4f, 0xe9, 0x16, 0x49, 0xdc, 0x21, 0x8e, + 0x0e, 0xb7, 0xcd, 0x83, 0xfd, 0x9e, 0xd5, 0xdd, 0x39, 0xea, 0x6d, 0xe1, 0x1d, 0x94, 0x9b, 0x66, + 0xe7, 0x90, 0xca, 0xcc, 0xbf, 0x0c, 0x41, 0x14, 0x5d, 0x10, 0xf4, 0xf2, 0xf4, 0xa0, 0xdb, 0xed, + 0x1c, 0x5a, 0x9f, 0x1e, 0xb5, 0xcd, 0x4e, 0xbb, 0x8b, 0x19, 0xe7, 0x52, 0xe0, 0x02, 0xbf, 0x28, + 0xf6, 0x95, 0xde, 0xee, 0x67, 0x92, 0xf1, 0x0b, 0xd4, 0x52, 0x12, 0x24, 0xb0, 0xca, 0x62, 0x30, + 0x05, 0xe7, 0x4c, 0x29, 0x19, 0xae, 0x49, 0x13, 0xf9, 0x2a, 0x62, 0x4f, 0x98, 0x21, 0x24, 0xcc, + 0x56, 0x4d, 0x4f, 0x12, 0xb9, 0x70, 0xbb, 0x88, 0x36, 0xd7, 0xad, 0x2d, 0x13, 0x33, 0xd4, 0x67, + 0xa0, 0x02, 0x77, 0x5e, 0x4c, 0x94, 0x60, 0xad, 0x02, 0xa5, 0xa1, 0x3e, 0x44, 0xca, 0xc2, 0xe3, + 0xdf, 0xce, 0x41, 0x9d, 0xe2, 0xfd, 0xe8, 0xed, 0x3f, 0xee, 0xb3, 0x3d, 0x28, 0xca, 0x47, 0x24, + 0xd9, 0x72, 0x74, 0xc1, 0x9f, 0xfe, 0x6c, 0xe5, 0xda, 0xca, 0x34, 0x58, 0x8a, 0x92, 0x8b, 0x7f, + 0xed, 0x4f, 0xfe, 0xc7, 0xdf, 0xcf, 0xd6, 0x58, 0xe5, 0xe1, 0xf9, 0x07, 0x0f, 0x4f, 0xb9, 0x1b, + 0x88, 0x32, 0x7e, 0x0d, 0x20, 0x7e, 0x1a, 0x91, 0x35, 0xb5, 0x3b, 0x7f, 0x13, 0x8f, 0x22, 0xae, + 0xdd, 0x4c, 0x49, 0x91, 0xe5, 0xde, 0xc4, 0x72, 0x17, 0x8d, 0xba, 0x28, 0xd7, 0x71, 0x9d, 0x90, + 0x9e, 0x49, 0xfc, 0x38, 0xf3, 0x80, 0x0d, 0xa0, 0xaa, 0x3f, 0x5a, 0xc8, 0x94, 0x94, 0x97, 0xf2, + 0xec, 0xe2, 0xda, 0xad, 0xd4, 0x34, 0x25, 0x3f, 0x63, 0x1d, 0xcb, 0x46, 0x43, 0xd4, 0x31, 0x41, + 0x8c, 0xb8, 0x96, 0x21, 0x69, 0x14, 0xf1, 0xdb, 0x84, 0xec, 0xb6, 0x26, 0x13, 0xce, 0xbc, 0x8c, + 0xb8, 0x76, 0xe7, 0x9a, 0x54, 0x59, 0xd7, 0x1d, 0xac, 0x6b, 0xd5, 0x60, 0xa2, 0xae, 0x3e, 0xe2, + 0xa8, 0x97, 0x11, 0x3f, 0xce, 0x3c, 0x78, 0xfc, 0x1f, 0xdf, 0x83, 0x72, 0xe4, 0xff, 0xcb, 0x7e, + 0x13, 0x6a, 0x89, 0x80, 0x4c, 0xa6, 0xba, 0x91, 0x16, 0xbf, 0xb9, 0x76, 0x3b, 0x3d, 0x51, 0x56, + 0xfc, 0x06, 0x56, 0xdc, 0x64, 0x2b, 0xa2, 0x62, 0x19, 0xf0, 0xf8, 0x10, 0x03, 0xa8, 0xe9, 0xba, + 0xc4, 0x17, 0x9a, 0xe6, 0x44, 0x95, 0xdd, 0x9e, 0xd6, 0x66, 0x12, 0xb5, 0xdd, 0xb9, 0x26, 0x55, + 0x56, 0x77, 0x1b, 0xab, 0x5b, 0x61, 0x4b, 0x7a, 0x75, 0xca, 0x6d, 0x94, 0x71, 0xbc, 0xa2, 0x54, + 0x7f, 0xba, 0x8f, 0xdd, 0x89, 0x2f, 0x94, 0x4c, 0x79, 0xd2, 0x2f, 0x22, 0x91, 0xd9, 0x77, 0xfd, + 0x8c, 0x26, 0x56, 0xc5, 0x18, 0x4e, 0x9f, 0xfe, 0x72, 0x1f, 0x3b, 0x86, 0x8a, 0xf6, 0xda, 0x0d, + 0xbb, 0x79, 0xed, 0xcb, 0x3c, 0x6b, 0x6b, 0x69, 0x49, 0x69, 0x5d, 0xd1, 0xcb, 0x7f, 0x78, 0xc2, + 0x39, 0xfb, 0x55, 0x28, 0x47, 0x6f, 0xa8, 0xb0, 0x55, 0xed, 0x4d, 0x1b, 0xfd, 0xcd, 0x97, 0xb5, + 0xe6, 0x6c, 0x42, 0x1a, 0xf1, 0xe9, 0xa5, 0x0b, 0xe2, 0xfb, 0x1c, 0x2a, 0xda, 0x3b, 0x29, 0x51, + 0x07, 0x66, 0xdf, 0x62, 0x89, 0x3a, 0x90, 0xf2, 0xac, 0x8a, 0xb1, 0x80, 0x55, 0x54, 0x58, 0x19, + 0xe9, 0x3b, 0xbc, 0xf4, 0x02, 0xb6, 0x0b, 0xcb, 0x52, 0x4b, 0x3c, 0xe6, 0x5f, 0x65, 0x1a, 0x52, + 0x5e, 0x4b, 0x7c, 0x94, 0x61, 0x9f, 0x40, 0x49, 0x3d, 0x87, 0xc3, 0x56, 0xd2, 0x9f, 0xf5, 0x59, + 0x5b, 0x9d, 0x81, 0x4b, 0x95, 0xee, 0x39, 0x40, 0xfc, 0x28, 0x4b, 0xc4, 0x24, 0x66, 0x1e, 0x79, + 0x89, 0x28, 0x60, 0xf6, 0x05, 0x17, 0x63, 0x05, 0x3b, 0xd8, 0x60, 0xc8, 0x24, 0x5c, 0x7e, 0xa1, + 0xee, 0x91, 0xfe, 0x21, 0x54, 0xb4, 0x77, 0x59, 0xa2, 0xe1, 0x9b, 0x7d, 0xd3, 0x25, 0x1a, 0xbe, + 0x94, 0x67, 0x5c, 0x8c, 0x35, 0x2c, 0x7d, 0xc9, 0x98, 0x17, 0xa5, 0x0b, 0x31, 0x51, 0x8a, 0x6b, + 0x62, 0x82, 0xce, 0xa0, 0x96, 0x78, 0x7c, 0x25, 0x5a, 0xa1, 0x69, 0x4f, 0xbb, 0x44, 0x2b, 0x34, + 0xf5, 0xbd, 0x16, 0x45, 0x67, 0xc6, 0x82, 0xa8, 0x87, 0xae, 0x92, 0xd2, 0x6a, 0xfa, 0x01, 0x54, + 0xb4, 0x87, 0x54, 0xa2, 0xbe, 0xcc, 0xbe, 0xd9, 0x12, 0xf5, 0x25, 0xed, 0xdd, 0x95, 0x25, 0xac, + 0xa3, 0x6e, 0x20, 0x29, 0xe0, 0x4d, 0xb8, 0xa2, 0xec, 0xdf, 0x84, 0x7a, 0xf2, 0x6d, 0x95, 0x68, + 0xed, 0xa7, 0x3e, 0xd2, 0x12, 0xad, 0xfd, 0x6b, 0x1e, 0x64, 0x91, 0x24, 0xfd, 0x60, 0x31, 0xaa, + 0xe4, 0xe1, 0x8f, 0x65, 0x24, 0xd3, 0x97, 0xec, 0x53, 0xc1, 0xe0, 0xe4, 0x45, 0xcc, 0x6c, 0x55, + 0xa3, 0x5a, 0xfd, 0x46, 0xe7, 0x68, 0xbd, 0xcc, 0xdc, 0xd9, 0x9c, 0x24, 0x66, 0x2c, 0x9c, 0x3d, + 0x85, 0xc5, 0x88, 0x98, 0xa3, 0x9b, 0x95, 0x83, 0xa8, 0x0f, 0xa9, 0xf7, 0x37, 0xaf, 0x35, 0xa6, + 0x53, 0x1f, 0x65, 0x68, 0xfb, 0xc3, 0xfb, 0x6c, 0xb5, 0xed, 0x4f, 0xbf, 0x5c, 0x59, 0xdb, 0xfe, + 0x12, 0xd7, 0xde, 0x4e, 0x6f, 0x7f, 0xa1, 0x23, 0xca, 0x70, 0x61, 0x7e, 0xfa, 0x9e, 0xe3, 0x3b, + 0xd7, 0xdd, 0x14, 0x41, 0xc5, 0xbf, 0xf1, 0xf2, 0x8b, 0x24, 0x92, 0xac, 0x48, 0x71, 0xd3, 0x87, + 0xd2, 0x71, 0x86, 0xfd, 0x3a, 0x54, 0xf5, 0xf7, 0x18, 0x98, 0xce, 0x13, 0xa6, 0x6b, 0xba, 0x95, + 0x9a, 0x96, 0xa4, 0x12, 0x56, 0xd5, 0xab, 0x61, 0x9f, 0xc1, 0x4a, 0x34, 0xcc, 0xfa, 0x55, 0x07, + 0x01, 0xbb, 0x9b, 0x72, 0x01, 0x42, 0x62, 0xb0, 0x6f, 0x5e, 0x7b, 0x43, 0xc2, 0xa3, 0x8c, 0xa0, + 0xbe, 0xe4, 0xdd, 0xf3, 0xf1, 0xce, 0x93, 0x76, 0xe5, 0x7e, 0xbc, 0xf3, 0xa4, 0x5e, 0x58, 0xaf, + 0xa8, 0x8f, 0x2d, 0x26, 0xc6, 0x88, 0x5c, 0x8a, 0xd9, 0x0f, 0x60, 0x5e, 0xbb, 0xc7, 0xa1, 0x7b, + 0xe5, 0xf6, 0xa3, 0x95, 0x34, 0x7b, 0x83, 0xe9, 0x5a, 0xda, 0xb9, 0xaa, 0xb1, 0x8a, 0xe5, 0x2f, + 0x18, 0x89, 0xc1, 0x11, 0xab, 0x68, 0x13, 0x2a, 0xfa, 0x1d, 0x11, 0x2f, 0x29, 0x77, 0x55, 0x4b, + 0xd2, 0x2f, 0xcb, 0x7c, 0x94, 0x61, 0xbb, 0xd0, 0x98, 0xbe, 0xbf, 0x2d, 0xe2, 0x29, 0x69, 0x77, + 0xde, 0xad, 0x4d, 0x25, 0x26, 0x6e, 0x7d, 0x63, 0x87, 0x14, 0x94, 0x12, 0x3d, 0x2d, 0xe8, 0xf9, + 0xd3, 0xbb, 0x7a, 0xf2, 0xc9, 0xc1, 0xa8, 0xb4, 0xb4, 0xc7, 0x26, 0xef, 0x67, 0x1e, 0x65, 0xd8, + 0xef, 0x66, 0xa0, 0x9a, 0xb8, 0xd1, 0x28, 0xe1, 0xf6, 0x3f, 0xd5, 0xcf, 0xa6, 0x9e, 0xa6, 0x77, + 0xd4, 0x30, 0x71, 0x10, 0x77, 0x1f, 0x7c, 0x3f, 0x31, 0x49, 0x3f, 0x4e, 0x98, 0x25, 0xd7, 0xa7, + 0xdf, 0x1e, 0xfc, 0x72, 0x1a, 0x41, 0xbf, 0x13, 0xf7, 0xcb, 0x47, 0x19, 0xf6, 0xaf, 0x32, 0x50, + 0x4f, 0xfa, 0x1b, 0x44, 0xdd, 0x4d, 0xf5, 0x6c, 0x88, 0x48, 0xe9, 0x1a, 0x27, 0x85, 0x1f, 0x60, + 0x2b, 0x7b, 0x0f, 0xcc, 0x44, 0x2b, 0xe5, 0xab, 0x09, 0x3f, 0x5b, 0x6b, 0xd9, 0x2f, 0xd3, 0x53, + 0xbf, 0xca, 0x0d, 0x8b, 0xcd, 0x3e, 0x0d, 0x1b, 0x91, 0x9f, 0xfe, 0x90, 0xaa, 0x91, 0xfb, 0xad, + 0x6c, 0x06, 0x67, 0xe2, 0x87, 0xf4, 0xd0, 0x9e, 0x72, 0xed, 0x11, 0xa4, 0xfc, 0xda, 0x85, 0xbc, + 0x8d, 0x1d, 0x7b, 0xc3, 0xb8, 0x99, 0xe8, 0xd8, 0xb4, 0xf4, 0xd1, 0xa2, 0x26, 0xca, 0xc7, 0x50, + 0xe3, 0xed, 0x73, 0xe6, 0x81, 0xd4, 0xd4, 0x4a, 0xb0, 0x91, 0x23, 0x6a, 0xa4, 0x44, 0x4f, 0xac, + 0xb7, 0xd7, 0x2c, 0xc6, 0x78, 0x80, 0x6d, 0x7d, 0xdb, 0xb8, 0x7b, 0x6d, 0x5b, 0x1f, 0xa2, 0x03, + 0x81, 0x68, 0xf1, 0x21, 0x40, 0xec, 0x2b, 0xc9, 0xa6, 0x3c, 0xf6, 0x22, 0x2e, 0x34, 0xeb, 0x4e, + 0x99, 0x5c, 0xd4, 0xca, 0xb1, 0x4f, 0x94, 0xf8, 0xab, 0xc4, 0x53, 0x23, 0x5f, 0x42, 0x5d, 0x04, + 0x4b, 0xba, 0x35, 0x26, 0x44, 0xb0, 0xe9, 0xf2, 0x13, 0x1c, 0x35, 0x72, 0x1c, 0x3c, 0x82, 0xda, + 0xae, 0xe7, 0xbd, 0x98, 0x8c, 0x23, 0xff, 0xfc, 0xa4, 0x57, 0xcf, 0x8e, 0x1d, 0x9c, 0xad, 0x4d, + 0xf5, 0xc2, 0xb8, 0x87, 0x45, 0xad, 0xb1, 0xa6, 0x56, 0xd4, 0xc3, 0x1f, 0xc7, 0x0e, 0x9a, 0x5f, + 0x32, 0x1b, 0x16, 0x22, 0x46, 0x1d, 0x3b, 0x41, 0x26, 0x8b, 0x49, 0xb0, 0xe7, 0xe9, 0x2a, 0x12, + 0xba, 0x82, 0x6a, 0xed, 0xc3, 0x40, 0x95, 0xf9, 0x28, 0xc3, 0x0e, 0xa1, 0xba, 0xc5, 0xfb, 0x78, + 0xc1, 0x03, 0xfa, 0xc6, 0x2c, 0x26, 0xfc, 0x2c, 0xc8, 0xa9, 0x66, 0xad, 0x96, 0x00, 0x26, 0x37, + 0xaf, 0xb1, 0x7d, 0xe5, 0xf3, 0x2f, 0x1e, 0xfe, 0x58, 0x7a, 0xdd, 0x7c, 0xa9, 0x36, 0x2f, 0xe5, + 0x95, 0x94, 0xd8, 0xbc, 0xa6, 0xdc, 0x98, 0x12, 0x9b, 0xd7, 0x8c, 0x1b, 0x53, 0x62, 0xa8, 0x95, + 0x57, 0x14, 0x1b, 0xc2, 0xc2, 0x8c, 0xe7, 0x53, 0xb4, 0x6f, 0x5d, 0xe7, 0x2f, 0xb5, 0x76, 0xef, + 0x7a, 0x84, 0x64, 0x6d, 0x0f, 0x92, 0xb5, 0x75, 0xa1, 0x46, 0xb7, 0xde, 0x1e, 0x73, 0x0a, 0xf5, + 0x9c, 0xba, 0x27, 0x49, 0x8f, 0x23, 0x9d, 0xde, 0x65, 0x30, 0x2d, 0x29, 0xe6, 0x60, 0xb0, 0x1f, + 0x3b, 0xc1, 0xa7, 0x1e, 0xb4, 0xd8, 0xca, 0x88, 0x18, 0x67, 0xe3, 0x3d, 0x23, 0x62, 0x4c, 0x09, + 0xc5, 0x54, 0x3a, 0x28, 0x5b, 0x8e, 0xca, 0x7e, 0xe8, 0x7a, 0x03, 0x3e, 0x92, 0xa5, 0xfe, 0x2a, + 0x54, 0x9e, 0xf2, 0x50, 0x05, 0x33, 0x46, 0x02, 0xfd, 0x54, 0x74, 0xe3, 0x5a, 0x4a, 0x08, 0x6a, + 0x92, 0x36, 0xa9, 0x64, 0x3e, 0x38, 0xe5, 0xc4, 0x09, 0x2d, 0x67, 0xf0, 0x25, 0xfb, 0x15, 0x2c, + 0x3c, 0x0a, 0xdd, 0x5f, 0xd1, 0x9a, 0xa9, 0x17, 0x3e, 0x3f, 0x05, 0x4f, 0x2b, 0x59, 0xb4, 0x59, + 0x13, 0x2c, 0x5d, 0xa8, 0x68, 0x57, 0x7c, 0x44, 0x63, 0x33, 0x7b, 0xa5, 0x4b, 0x34, 0x36, 0x29, + 0x37, 0x82, 0x18, 0xf7, 0xb1, 0x1e, 0x83, 0xdd, 0x8b, 0xeb, 0xa1, 0x5b, 0x40, 0xe2, 0x9a, 0x1e, + 0xfe, 0xd8, 0x1e, 0x85, 0x5f, 0xb2, 0xcf, 0x69, 0x3a, 0xb4, 0x60, 0xcd, 0x58, 0x43, 0x99, 0x8e, + 0xeb, 0x8c, 0x06, 0x4b, 0x4b, 0x4a, 0x6a, 0x2d, 0x54, 0x15, 0x8a, 0x8d, 0x4f, 0x00, 0xba, 0xa1, + 0x37, 0xde, 0xb2, 0xf9, 0xc8, 0x73, 0x63, 0x9e, 0x1e, 0x87, 0x0f, 0xc6, 0x7c, 0x52, 0x8b, 0x21, + 0x64, 0x9f, 0x6b, 0x2a, 0x5d, 0x22, 0xcc, 0x58, 0x11, 0xf1, 0xb5, 0x11, 0x86, 0xd1, 0x80, 0xa4, + 0x44, 0x19, 0x3e, 0xca, 0xb0, 0x16, 0x40, 0xec, 0x62, 0x17, 0x29, 0x68, 0x33, 0xde, 0x7b, 0x11, + 0x7b, 0x4d, 0xf1, 0xc7, 0x3b, 0x84, 0x72, 0xec, 0x9b, 0xb4, 0x1a, 0xdf, 0x58, 0x94, 0xf0, 0x64, + 0x8a, 0xc4, 0x85, 0x19, 0xbf, 0x20, 0xa3, 0x81, 0x43, 0x05, 0xac, 0x24, 0x86, 0xea, 0x84, 0xf3, + 0x80, 0x39, 0xb0, 0x48, 0x0d, 0x8c, 0x64, 0x33, 0x0c, 0x7b, 0x8b, 0x1e, 0x58, 0x99, 0x75, 0xd1, + 0x89, 0xb8, 0x46, 0xaa, 0xa3, 0x49, 0xe2, 0x9c, 0x49, 0x50, 0x2b, 0x85, 0xdc, 0x89, 0x2d, 0x60, + 0x04, 0x0b, 0x33, 0xbe, 0x0c, 0x11, 0xeb, 0xb8, 0xce, 0x39, 0x25, 0x62, 0x1d, 0xd7, 0xba, 0x41, + 0x18, 0xcb, 0x58, 0xe5, 0xbc, 0x01, 0xa8, 0x57, 0x5e, 0x38, 0x61, 0xff, 0x4c, 0x54, 0xf7, 0xfb, + 0x19, 0x58, 0x4c, 0xf1, 0x56, 0x60, 0x6f, 0xaa, 0x23, 0x8a, 0x6b, 0x3d, 0x19, 0xd6, 0x52, 0xad, + 0xda, 0x46, 0x17, 0xeb, 0xd9, 0x63, 0xcf, 0x12, 0x1b, 0x28, 0x19, 0x95, 0xe5, 0xca, 0x7c, 0xa9, + 0x04, 0x93, 0x2a, 0xbe, 0x7c, 0x01, 0xab, 0xd4, 0x90, 0xd6, 0x70, 0x38, 0x65, 0x71, 0x7f, 0x43, + 0x6b, 0x45, 0x8a, 0x17, 0x41, 0x42, 0x19, 0x48, 0x7a, 0x12, 0x5c, 0x23, 0xbb, 0x53, 0x53, 0xd9, + 0x04, 0x1a, 0xd3, 0x96, 0x6c, 0x76, 0x7d, 0x59, 0x6b, 0x77, 0x13, 0xca, 0x76, 0x8a, 0xf5, 0xfb, + 0x6b, 0x58, 0xd9, 0x5d, 0x63, 0x2d, 0x6d, 0x5c, 0x48, 0xff, 0x16, 0xf3, 0xf1, 0x57, 0x23, 0xb3, + 0xfb, 0x54, 0x3f, 0xef, 0x46, 0x57, 0xca, 0xa7, 0x3b, 0x09, 0x44, 0xea, 0x7e, 0xba, 0xd5, 0xfe, + 0x1d, 0xac, 0xfe, 0x9e, 0x71, 0x2b, 0xad, 0x7a, 0x9f, 0xb2, 0x90, 0xe2, 0xbf, 0x3a, 0xbd, 0xae, + 0x55, 0x0b, 0xee, 0xa5, 0xcd, 0xf7, 0xb5, 0x8a, 0xd7, 0xd4, 0x58, 0xdf, 0x40, 0x19, 0xb2, 0xaa, + 0x9b, 0xd9, 0xa3, 0xe5, 0x93, 0x62, 0xcf, 0x8f, 0x96, 0x4f, 0x9a, 0x5d, 0x3e, 0x29, 0x3f, 0x29, + 0x8b, 0xfc, 0xc7, 0x99, 0x07, 0x1b, 0xef, 0xfe, 0xe0, 0x6b, 0xa7, 0x4e, 0x78, 0x36, 0x39, 0x5e, + 0xef, 0x7b, 0xa3, 0x87, 0x43, 0x75, 0xb4, 0x29, 0x63, 0xc3, 0x1f, 0x0e, 0xdd, 0xc1, 0x43, 0x2c, + 0xf6, 0x78, 0x6e, 0xec, 0x7b, 0xa1, 0xf7, 0xcd, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xad, + 0x0f, 0x96, 0x5a, 0x89, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 5b6b3630a5..46c60ade47 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1483,6 +1483,13 @@ message ListChannelsResponse { repeated Channel channels = 11; } +enum Initiator { + INITIATOR_UNKNOWN = 0; + INITIATOR_LOCAL = 1; + INITIATOR_REMOTE = 2; + INITIATOR_BOTH = 3; +} + message ChannelCloseSummary { /// The outpoint (txid:index) of the funding transaction. string channel_point = 1; @@ -1523,13 +1530,6 @@ message ChannelCloseSummary { /// Details on how the channel was closed. ClosureType close_type = 10; - enum Initiator { - UNKNOWN = 0; - LOCAL = 1; - REMOTE = 2; - BOTH = 3; - } - /** Open initiator is the party that initiated opening the channel. Note that this value may be unknown if the channel was closed before we migrated to diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index e8f73c82f8..683ca13cf0 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1513,16 +1513,6 @@ ], "default": "COOPERATIVE_CLOSE" }, - "ChannelCloseSummaryInitiator": { - "type": "string", - "enum": [ - "UNKNOWN", - "LOCAL", - "REMOTE", - "BOTH" - ], - "default": "UNKNOWN" - }, "ChannelEventUpdateUpdateType": { "type": "string", "enum": [ @@ -2233,11 +2223,11 @@ "description": "/ Details on how the channel was closed." }, "open_initiator": { - "$ref": "#/definitions/ChannelCloseSummaryInitiator", + "$ref": "#/definitions/lnrpcInitiator", "description": "*\nOpen initiator is the party that initiated opening the channel. Note that\nthis value may be unknown if the channel was closed before we migrated to\nstore open channel information after close." }, "close_initiator": { - "$ref": "#/definitions/ChannelCloseSummaryInitiator", + "$ref": "#/definitions/lnrpcInitiator", "description": "*\nClose initiator indicates which party initiated the close. This value will\nbe unknown for channels that were cooperatively closed before we started\ntracking cooperative close initiators. Note that this indicates which party\ninitiated a close, and it is possible for both to initiate cooperative or\nforce closes, although only one party's close will be confirmed on chain." } } @@ -3183,6 +3173,16 @@ "lnrpcInitWalletResponse": { "type": "object" }, + "lnrpcInitiator": { + "type": "string", + "enum": [ + "INITIATOR_UNKNOWN", + "INITIATOR_LOCAL", + "INITIATOR_REMOTE", + "INITIATOR_BOTH" + ], + "default": "INITIATOR_UNKNOWN" + }, "lnrpcInvoice": { "type": "object", "properties": { diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 1a11339979..59bb3039ad 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -6628,7 +6628,7 @@ func subscribeChannelNotifications(ctxb context.Context, t *harnessTest, // expected type. func verifyCloseUpdate(chanUpdate *lnrpc.ChannelEventUpdate, closeType lnrpc.ChannelCloseSummary_ClosureType, - closeInitiator lnrpc.ChannelCloseSummary_Initiator) error { + closeInitiator lnrpc.Initiator) error { // We should receive one inactive and one closed notification // for each channel. @@ -6772,7 +6772,7 @@ func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTe // receive the correct channel updates in order. verifyCloseUpdatesReceived := func(sub channelSubscription, forceType lnrpc.ChannelCloseSummary_ClosureType, - closeInitiator lnrpc.ChannelCloseSummary_Initiator) error { + closeInitiator lnrpc.Initiator) error { // Ensure one inactive and one closed notification is received for each // closed channel. @@ -6818,7 +6818,7 @@ func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTe // close initiator because Alice closed the channels. if err := verifyCloseUpdatesReceived(bobChanSub, lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE, - lnrpc.ChannelCloseSummary_REMOTE); err != nil { + lnrpc.Initiator_INITIATOR_REMOTE); err != nil { t.Fatalf("errored verifying close updates: %v", err) } @@ -6828,7 +6828,7 @@ func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTe // close initiator because Alice closed the channels. if err := verifyCloseUpdatesReceived(aliceChanSub, lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE, - lnrpc.ChannelCloseSummary_LOCAL); err != nil { + lnrpc.Initiator_INITIATOR_LOCAL); err != nil { t.Fatalf("errored verifying close updates: %v", err) } } diff --git a/rpcserver.go b/rpcserver.go index c016ab5a4c..cd5da7d0e1 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3370,8 +3370,8 @@ func (r *rpcServer) createRPCClosedChannel( var ( closeType lnrpc.ChannelCloseSummary_ClosureType - openInit lnrpc.ChannelCloseSummary_Initiator - closeInitiator lnrpc.ChannelCloseSummary_Initiator + openInit lnrpc.Initiator + closeInitiator lnrpc.Initiator err error ) @@ -3422,12 +3422,12 @@ func (r *rpcServer) createRPCClosedChannel( // channel is not present (which indicates that it was closed before we started // writing channels to the historical close bucket). func (r *rpcServer) getInitiators(chanPoint *wire.OutPoint) ( - lnrpc.ChannelCloseSummary_Initiator, - lnrpc.ChannelCloseSummary_Initiator, error) { + lnrpc.Initiator, + lnrpc.Initiator, error) { var ( - openInitiator = lnrpc.ChannelCloseSummary_UNKNOWN - closeInitiator = lnrpc.ChannelCloseSummary_UNKNOWN + openInitiator = lnrpc.Initiator_INITIATOR_UNKNOWN + closeInitiator = lnrpc.Initiator_INITIATOR_UNKNOWN ) // To get the close initiator for cooperative closes, we need @@ -3452,9 +3452,9 @@ func (r *rpcServer) getInitiators(chanPoint *wire.OutPoint) ( // If we successfully looked up the channel, determine initiator based // on channels status. if histChan.IsInitiator { - openInitiator = lnrpc.ChannelCloseSummary_LOCAL + openInitiator = lnrpc.Initiator_INITIATOR_LOCAL } else { - openInitiator = lnrpc.ChannelCloseSummary_REMOTE + openInitiator = lnrpc.Initiator_INITIATOR_REMOTE } localInit := histChan.HasChanStatus( @@ -3470,13 +3470,13 @@ func (r *rpcServer) getInitiators(chanPoint *wire.OutPoint) ( // We return the initiator as both in this case to provide full // information about the close. case localInit && remoteInit: - closeInitiator = lnrpc.ChannelCloseSummary_BOTH + closeInitiator = lnrpc.Initiator_INITIATOR_BOTH case localInit: - closeInitiator = lnrpc.ChannelCloseSummary_LOCAL + closeInitiator = lnrpc.Initiator_INITIATOR_LOCAL case remoteInit: - closeInitiator = lnrpc.ChannelCloseSummary_REMOTE + closeInitiator = lnrpc.Initiator_INITIATOR_REMOTE } return openInitiator, closeInitiator, nil From d66ff04583794c22f795e57c843700bcda2e6492 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 3 Apr 2020 09:13:53 +0200 Subject: [PATCH 406/562] lnrpc: use initiator enum for pending channel channel intiator Update the PendingChannel message from a bool to an enum to differentiate between the case where the remote party initiated the channel and we have no record of the channel initiator. The previous field has not been included in a release of lnd, so we can replace the field directly. --- lnrpc/rpc.pb.go | 1490 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 4 +- lnrpc/rpc.swagger.json | 5 +- rpcserver.go | 22 +- 4 files changed, 768 insertions(+), 753 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index ad59f22df9..de67ce9757 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -5871,8 +5871,8 @@ type PendingChannelsResponse_PendingChannel struct { //The minimum satoshis the other node is required to reserve in its //balance. RemoteChanReserveSat int64 `protobuf:"varint,7,opt,name=remote_chan_reserve_sat,json=remoteChanReserveSat,proto3" json:"remote_chan_reserve_sat,omitempty"` - // True if we initiated opening the channel. - Initiator bool `protobuf:"varint,8,opt,name=initiator,proto3" json:"initiator,omitempty"` + // The party that initiated opening the channel. + Initiator Initiator `protobuf:"varint,8,opt,name=initiator,proto3,enum=lnrpc.Initiator" json:"initiator,omitempty"` /// The commitment type used by this channel. CommitmentType CommitmentType `protobuf:"varint,9,opt,name=commitment_type,json=commitmentType,proto3,enum=lnrpc.CommitmentType" json:"commitment_type,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -5956,11 +5956,11 @@ func (m *PendingChannelsResponse_PendingChannel) GetRemoteChanReserveSat() int64 return 0 } -func (m *PendingChannelsResponse_PendingChannel) GetInitiator() bool { +func (m *PendingChannelsResponse_PendingChannel) GetInitiator() Initiator { if m != nil { return m.Initiator } - return false + return Initiator_INITIATOR_UNKNOWN } func (m *PendingChannelsResponse_PendingChannel) GetCommitmentType() CommitmentType { @@ -11878,750 +11878,750 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11878 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x6b, 0x6f, 0x24, 0x49, + // 11879 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x6c, 0x24, 0x49, 0x72, 0xd8, 0xf4, 0x8b, 0xdd, 0x1d, 0xfd, 0x60, 0x33, 0xf9, 0xea, 0xe1, 0xcc, 0xec, 0xcc, 0xd6, 0xee, 0xed, 0xce, 0xce, 0xde, 0x71, 0x66, 0xe7, 0x6e, 0x76, 0xef, 0x76, 0xad, 0xd3, 0x35, 0xc9, 0xe6, 0xb0, 0x6f, 0xf8, 0xda, 0xea, 0xe6, 0xae, 0xe6, 0xf4, 0xa8, 0x2b, 0x76, 0x27, 0xc9, 0xd2, - 0x74, 0x57, 0xf5, 0x56, 0x55, 0xf3, 0x71, 0x87, 0xf5, 0x07, 0xc3, 0x36, 0x04, 0xc3, 0x0f, 0x08, - 0xb6, 0x0c, 0x58, 0xb6, 0x60, 0xc3, 0x82, 0x61, 0x18, 0x06, 0x04, 0x01, 0x27, 0x7f, 0x30, 0xe0, - 0xef, 0xfa, 0xe2, 0x07, 0x0c, 0xc9, 0x5f, 0x0c, 0x41, 0x80, 0x61, 0x5b, 0xfe, 0x60, 0xc0, 0x10, - 0xe0, 0x3f, 0x60, 0x64, 0x44, 0x66, 0x55, 0x56, 0x77, 0x71, 0x66, 0xf6, 0xee, 0x7c, 0x5f, 0xc8, - 0xae, 0xc8, 0xc8, 0x77, 0x64, 0x64, 0x44, 0x46, 0x44, 0x26, 0x94, 0xfd, 0x71, 0x7f, 0x7d, 0xec, - 0x7b, 0xa1, 0xc7, 0x0a, 0x43, 0xd7, 0x1f, 0xf7, 0xd7, 0x6e, 0x9f, 0x7a, 0xde, 0xe9, 0x90, 0x3f, - 0xb4, 0xc7, 0xce, 0x43, 0xdb, 0x75, 0xbd, 0xd0, 0x0e, 0x1d, 0xcf, 0x0d, 0x08, 0xc9, 0xf8, 0x21, - 0xd4, 0x9f, 0x72, 0xb7, 0xcb, 0xf9, 0xc0, 0xe4, 0x5f, 0x4c, 0x78, 0x10, 0xb2, 0xf7, 0x61, 0xc1, - 0xe6, 0x3f, 0xe2, 0x7c, 0x60, 0x8d, 0xed, 0x20, 0x18, 0x9f, 0xf9, 0x76, 0xc0, 0x9b, 0x99, 0x7b, - 0x99, 0xfb, 0x55, 0xb3, 0x41, 0x09, 0x87, 0x11, 0x9c, 0xbd, 0x09, 0xd5, 0x40, 0xa0, 0x72, 0x37, - 0xf4, 0xbd, 0xf1, 0x55, 0x33, 0x8b, 0x78, 0x15, 0x01, 0x6b, 0x13, 0xc8, 0x18, 0xc2, 0x7c, 0x54, - 0x43, 0x30, 0xf6, 0xdc, 0x80, 0xb3, 0x47, 0xb0, 0xd4, 0x77, 0xc6, 0x67, 0xdc, 0xb7, 0x30, 0xf3, - 0xc8, 0xe5, 0x23, 0xcf, 0x75, 0xfa, 0xcd, 0xcc, 0xbd, 0xdc, 0xfd, 0xb2, 0xc9, 0x28, 0x4d, 0xe4, - 0xd8, 0x93, 0x29, 0xec, 0x5d, 0x98, 0xe7, 0x2e, 0xc1, 0xf9, 0x00, 0x73, 0xc9, 0xaa, 0xea, 0x31, - 0x58, 0x64, 0x30, 0x7e, 0x2b, 0x0b, 0x0b, 0x1d, 0xd7, 0x09, 0x3f, 0xb7, 0x87, 0x43, 0x1e, 0xaa, - 0x3e, 0xbd, 0x0b, 0xf3, 0x17, 0x08, 0xc0, 0x3e, 0x5d, 0x78, 0xfe, 0x40, 0xf6, 0xa8, 0x4e, 0xe0, - 0x43, 0x09, 0xbd, 0xb6, 0x65, 0xd9, 0x6b, 0x5b, 0x96, 0x3a, 0x5c, 0xb9, 0x6b, 0x86, 0xeb, 0x5d, - 0x98, 0xf7, 0x79, 0xdf, 0x3b, 0xe7, 0xfe, 0x95, 0x75, 0xe1, 0xb8, 0x03, 0xef, 0xa2, 0x99, 0xbf, - 0x97, 0xb9, 0x5f, 0x30, 0xeb, 0x0a, 0xfc, 0x39, 0x42, 0xd9, 0x06, 0xcc, 0xf7, 0xcf, 0x6c, 0xd7, - 0xe5, 0x43, 0xeb, 0xd8, 0xee, 0xbf, 0x98, 0x8c, 0x83, 0x66, 0xe1, 0x5e, 0xe6, 0x7e, 0xe5, 0xf1, - 0xcd, 0x75, 0x9c, 0xd5, 0xf5, 0xcd, 0x33, 0xdb, 0xdd, 0xc0, 0x94, 0xae, 0x6b, 0x8f, 0x83, 0x33, - 0x2f, 0x34, 0xeb, 0x32, 0x07, 0x81, 0x03, 0x63, 0x09, 0x98, 0x3e, 0x12, 0x34, 0xf6, 0xc6, 0xbf, - 0xce, 0xc0, 0xe2, 0x91, 0x3b, 0xf4, 0xfa, 0x2f, 0x7e, 0xca, 0x21, 0x4a, 0xe9, 0x43, 0xf6, 0x75, - 0xfb, 0x90, 0xfb, 0xaa, 0x7d, 0x58, 0x81, 0xa5, 0x64, 0x63, 0x65, 0x2f, 0x38, 0x2c, 0x8b, 0xdc, - 0xa7, 0x5c, 0x35, 0x4b, 0x75, 0xe3, 0x3d, 0x68, 0xf4, 0x27, 0xbe, 0xcf, 0xdd, 0x99, 0x7e, 0xcc, - 0x4b, 0x78, 0xd4, 0x91, 0x37, 0xa1, 0xea, 0xf2, 0x8b, 0x18, 0x4d, 0xd2, 0xae, 0xcb, 0x2f, 0x14, - 0x8a, 0xd1, 0x84, 0x95, 0xe9, 0x6a, 0x64, 0x03, 0xfe, 0x22, 0x03, 0xf9, 0xa3, 0xf0, 0xd2, 0x63, - 0x4f, 0xa0, 0x6a, 0x0f, 0x06, 0x3e, 0x0f, 0x02, 0x2b, 0xbc, 0x1a, 0xd3, 0x4a, 0xa9, 0x3f, 0x66, - 0xb2, 0x8b, 0x2d, 0x4a, 0xea, 0x5d, 0x8d, 0xb9, 0x59, 0xb1, 0xe3, 0x0f, 0xd6, 0x84, 0xa2, 0xfc, - 0xc4, 0x7a, 0xcb, 0xa6, 0xfa, 0x64, 0x77, 0x00, 0xec, 0x91, 0x37, 0x71, 0x43, 0x2b, 0xb0, 0x43, - 0x1c, 0xb1, 0x9c, 0x59, 0x26, 0x48, 0xd7, 0x0e, 0xd9, 0x2d, 0x28, 0x8f, 0x5f, 0x58, 0x41, 0xdf, - 0x77, 0xc6, 0x21, 0x12, 0x4f, 0xd9, 0x2c, 0x8d, 0x5f, 0x74, 0xf1, 0x9b, 0xbd, 0x0f, 0x25, 0x6f, - 0x12, 0x8e, 0x3d, 0xc7, 0x0d, 0x25, 0xbd, 0xcc, 0xcb, 0x86, 0x1c, 0x4c, 0xc2, 0x43, 0x01, 0x36, - 0x23, 0x04, 0xf6, 0x36, 0xd4, 0xfa, 0x9e, 0x7b, 0xe2, 0xf8, 0x23, 0xe2, 0x08, 0xcd, 0x39, 0xac, - 0x2b, 0x09, 0x34, 0xfe, 0x30, 0x0b, 0x95, 0x9e, 0x6f, 0xbb, 0x81, 0xdd, 0x17, 0x00, 0xb6, 0x0a, - 0xc5, 0xf0, 0xd2, 0x3a, 0xb3, 0x83, 0x33, 0xec, 0x6a, 0xd9, 0x9c, 0x0b, 0x2f, 0x77, 0xec, 0xe0, - 0x8c, 0xad, 0xc0, 0x1c, 0xb5, 0x12, 0x3b, 0x94, 0x33, 0xe5, 0x97, 0x58, 0x20, 0xee, 0x64, 0x64, - 0x25, 0xab, 0xca, 0x21, 0xc5, 0x34, 0xdc, 0xc9, 0x68, 0x53, 0x87, 0x8b, 0xce, 0x1f, 0x8b, 0xe9, - 0xa6, 0x0a, 0xa8, 0x7b, 0x65, 0x84, 0x60, 0x1d, 0x6f, 0x42, 0x55, 0x26, 0x73, 0xe7, 0xf4, 0x8c, - 0xfa, 0x58, 0x30, 0x2b, 0x84, 0x80, 0x20, 0x51, 0x42, 0xe8, 0x8c, 0xb8, 0x15, 0x84, 0xf6, 0x68, - 0x2c, 0xbb, 0x54, 0x16, 0x90, 0xae, 0x00, 0x60, 0xb2, 0x17, 0xda, 0x43, 0xeb, 0x84, 0xf3, 0xa0, - 0x59, 0x94, 0xc9, 0x02, 0xb2, 0xcd, 0x79, 0xc0, 0xbe, 0x06, 0xf5, 0x01, 0x0f, 0x42, 0x4b, 0x4e, - 0x06, 0x0f, 0x9a, 0x25, 0x5c, 0xf9, 0x35, 0x01, 0x6d, 0x29, 0x20, 0xbb, 0x0d, 0xe0, 0xdb, 0x17, - 0x96, 0x18, 0x08, 0x7e, 0xd9, 0x2c, 0xd3, 0x2c, 0xf8, 0xf6, 0x45, 0xef, 0x72, 0x87, 0x5f, 0x0a, - 0xaa, 0x79, 0xca, 0x43, 0x6d, 0xd0, 0x02, 0x49, 0x9d, 0xc6, 0x2e, 0x30, 0x0d, 0xbc, 0xc5, 0x43, - 0xdb, 0x19, 0x06, 0xec, 0x43, 0xa8, 0x86, 0x1a, 0x32, 0xb2, 0xc1, 0x4a, 0x44, 0x42, 0x5a, 0x06, - 0x33, 0x81, 0x67, 0x9c, 0x41, 0x69, 0x9b, 0xf3, 0x5d, 0x67, 0xe4, 0x84, 0x6c, 0x05, 0x0a, 0x27, - 0xce, 0x25, 0x27, 0x62, 0xcf, 0xed, 0xdc, 0x30, 0xe9, 0x93, 0xdd, 0x05, 0xc0, 0x1f, 0xd6, 0x28, - 0xa2, 0xa6, 0x9d, 0x1b, 0x66, 0x19, 0x61, 0x7b, 0x81, 0x1d, 0xb2, 0x35, 0x28, 0x8e, 0xb9, 0xdf, - 0xe7, 0x6a, 0xde, 0x76, 0x6e, 0x98, 0x0a, 0xb0, 0x51, 0x84, 0xc2, 0x50, 0x94, 0x6e, 0xfc, 0x71, - 0x01, 0x2a, 0x5d, 0xee, 0x46, 0xab, 0x8c, 0x41, 0x5e, 0x0c, 0x88, 0x5c, 0x59, 0xf8, 0x9b, 0xbd, - 0x05, 0x15, 0x1c, 0xba, 0x20, 0xf4, 0x1d, 0xf7, 0x94, 0xa8, 0x7a, 0x23, 0xdb, 0xcc, 0x98, 0x20, - 0xc0, 0x5d, 0x84, 0xb2, 0x06, 0xe4, 0xec, 0x91, 0xa2, 0x6a, 0xf1, 0x93, 0xdd, 0x84, 0x92, 0x3d, - 0x0a, 0xa9, 0x79, 0x55, 0x04, 0x17, 0xed, 0x51, 0x88, 0x4d, 0x7b, 0x13, 0xaa, 0x63, 0xfb, 0x6a, - 0x24, 0xd6, 0x72, 0x44, 0x0e, 0x55, 0xb3, 0x22, 0x61, 0x48, 0x10, 0x8f, 0x61, 0x51, 0x47, 0x51, - 0x95, 0x17, 0xa2, 0xca, 0x17, 0x34, 0x6c, 0xd9, 0x86, 0x77, 0x61, 0x5e, 0xe5, 0xf1, 0xa9, 0x3f, - 0x48, 0x26, 0x65, 0xb3, 0x2e, 0xc1, 0xaa, 0x97, 0xf7, 0xa1, 0x71, 0xe2, 0xb8, 0xf6, 0xd0, 0xea, - 0x0f, 0xc3, 0x73, 0x6b, 0xc0, 0x87, 0xa1, 0x8d, 0x14, 0x53, 0x30, 0xeb, 0x08, 0xdf, 0x1c, 0x86, - 0xe7, 0x5b, 0x02, 0xca, 0xbe, 0x0e, 0xe5, 0x13, 0xce, 0x2d, 0x1c, 0xac, 0x66, 0x29, 0xb1, 0xf0, - 0xd4, 0x0c, 0x99, 0xa5, 0x13, 0x35, 0x57, 0x5f, 0x87, 0x86, 0x37, 0x09, 0x4f, 0x3d, 0xc7, 0x3d, - 0xb5, 0x04, 0xbf, 0xb3, 0x9c, 0x01, 0xd2, 0x50, 0x7e, 0x23, 0xfb, 0x28, 0x63, 0xd6, 0x55, 0x9a, - 0xe0, 0x3c, 0x9d, 0x01, 0x7b, 0x07, 0xe6, 0x87, 0x76, 0x10, 0x5a, 0x67, 0xde, 0xd8, 0x1a, 0x4f, - 0x8e, 0x5f, 0xf0, 0xab, 0x66, 0x0d, 0x07, 0xa2, 0x26, 0xc0, 0x3b, 0xde, 0xf8, 0x10, 0x81, 0x82, - 0xb2, 0xb1, 0x9d, 0xd4, 0x08, 0xb8, 0x97, 0xb9, 0x5f, 0x33, 0xcb, 0x02, 0x42, 0x95, 0x3e, 0x87, - 0x45, 0x9c, 0x9e, 0xfe, 0x24, 0x08, 0xbd, 0x91, 0x25, 0x78, 0xb5, 0x3f, 0x08, 0x9a, 0x15, 0xa4, - 0xb5, 0xf7, 0x64, 0x63, 0xb5, 0x39, 0x5e, 0xdf, 0xe2, 0x41, 0xb8, 0x89, 0xc8, 0x26, 0xe1, 0x8a, - 0x0d, 0xfd, 0xca, 0x5c, 0x18, 0x4c, 0xc3, 0xd9, 0xd7, 0x81, 0xd9, 0xc3, 0xa1, 0x77, 0x61, 0x05, - 0x7c, 0x78, 0x62, 0xc9, 0x41, 0x6c, 0xd6, 0xef, 0x65, 0xee, 0x97, 0xcc, 0x06, 0xa6, 0x74, 0xf9, - 0xf0, 0xe4, 0x90, 0xe0, 0xec, 0x43, 0xc0, 0xc5, 0x64, 0x9d, 0x70, 0x3b, 0x9c, 0xf8, 0x3c, 0x68, - 0xce, 0xdf, 0xcb, 0xdd, 0xaf, 0x3f, 0x5e, 0x88, 0xc6, 0x0b, 0xc1, 0x1b, 0x4e, 0x68, 0x56, 0x05, - 0x9e, 0xfc, 0x0e, 0xd6, 0xb6, 0x60, 0x25, 0xbd, 0x49, 0x82, 0xa8, 0xc4, 0xa8, 0x08, 0x62, 0xcc, - 0x9b, 0xe2, 0x27, 0x5b, 0x82, 0xc2, 0xb9, 0x3d, 0x9c, 0x70, 0xc9, 0xd3, 0xe9, 0xe3, 0xe3, 0xec, - 0xb7, 0x33, 0xc6, 0x1f, 0x65, 0xa0, 0x4a, 0xbd, 0x94, 0xb2, 0xc8, 0x5b, 0x50, 0x53, 0xd4, 0xc0, - 0x7d, 0xdf, 0xf3, 0x25, 0x57, 0x53, 0x94, 0xd7, 0x16, 0x30, 0xb1, 0xab, 0x28, 0xa4, 0xb1, 0xcf, - 0x9d, 0x91, 0x7d, 0xaa, 0x8a, 0x56, 0xa4, 0x74, 0x28, 0xc1, 0xec, 0x83, 0xb8, 0x3c, 0xdf, 0x9b, - 0x84, 0x5c, 0xee, 0x79, 0x55, 0xd9, 0x3d, 0x53, 0xc0, 0xa2, 0xd2, 0xf1, 0xeb, 0x35, 0xe8, 0xdc, - 0xf8, 0x9d, 0x0c, 0x30, 0xd1, 0xec, 0x9e, 0x47, 0x05, 0x48, 0x0a, 0x9d, 0xce, 0x99, 0x79, 0xed, - 0x15, 0x92, 0x7d, 0xd9, 0x0a, 0x31, 0xa0, 0x40, 0x6d, 0xcf, 0xa7, 0xb4, 0x9d, 0x92, 0xbe, 0x9f, - 0x2f, 0xe5, 0x1a, 0x79, 0xe3, 0xbf, 0xe6, 0x60, 0x69, 0x93, 0xb6, 0xec, 0x56, 0xbf, 0xcf, 0xc7, - 0xd1, 0xda, 0xb9, 0x0b, 0x15, 0xd7, 0x1b, 0x70, 0x45, 0xb1, 0xd4, 0x30, 0x10, 0x20, 0x8d, 0x5c, - 0xcf, 0x6c, 0xc7, 0xa5, 0x86, 0xd3, 0x60, 0x96, 0x11, 0x82, 0xcd, 0x7e, 0x07, 0xe6, 0xc7, 0xdc, - 0x1d, 0xe8, 0x4b, 0x84, 0x84, 0xaa, 0x9a, 0x04, 0xcb, 0xd5, 0x71, 0x17, 0x2a, 0x27, 0x13, 0xc2, - 0x13, 0x8c, 0x25, 0x8f, 0x34, 0x00, 0x12, 0xd4, 0x22, 0xfe, 0x32, 0x9e, 0x04, 0x67, 0x98, 0x5a, - 0xc0, 0xd4, 0xa2, 0xf8, 0x16, 0x49, 0x77, 0x00, 0x06, 0x93, 0x20, 0x94, 0x2b, 0x66, 0x0e, 0x13, - 0xcb, 0x02, 0x42, 0x2b, 0xe6, 0x1b, 0xb0, 0x38, 0xb2, 0x2f, 0x2d, 0xa4, 0x1d, 0xcb, 0x71, 0xad, - 0x93, 0x21, 0xee, 0x39, 0x45, 0xc4, 0x6b, 0x8c, 0xec, 0xcb, 0xcf, 0x44, 0x4a, 0xc7, 0xdd, 0x46, - 0xb8, 0x60, 0x2b, 0x4a, 0xdc, 0xf1, 0x79, 0xc0, 0xfd, 0x73, 0x8e, 0x9c, 0x20, 0x1f, 0xc9, 0x34, - 0x26, 0x41, 0x45, 0x8b, 0x46, 0xa2, 0xdf, 0xe1, 0xb0, 0x4f, 0xcb, 0xde, 0x2c, 0x8e, 0x1c, 0x77, - 0x27, 0x1c, 0xf6, 0xc5, 0xbe, 0x22, 0xf8, 0xc8, 0x98, 0xfb, 0xd6, 0x8b, 0x0b, 0x5c, 0xc3, 0x79, - 0xe4, 0x1b, 0x87, 0xdc, 0x7f, 0x76, 0x21, 0xb6, 0xfe, 0x7e, 0x80, 0x8c, 0xc8, 0xbe, 0x6a, 0x56, - 0x70, 0x81, 0x97, 0xfa, 0x81, 0x60, 0x41, 0xf6, 0x95, 0x58, 0x84, 0xa2, 0xb5, 0x36, 0xce, 0x02, - 0x1f, 0x60, 0xf1, 0x01, 0x72, 0xd4, 0x1a, 0x36, 0xb6, 0x25, 0x13, 0x44, 0x3d, 0x81, 0xa0, 0x7a, - 0xd5, 0xd8, 0x93, 0xa1, 0x7d, 0x1a, 0x20, 0x4b, 0xa9, 0x99, 0x55, 0x09, 0xdc, 0x16, 0x30, 0xe3, - 0x73, 0x12, 0xb2, 0xb4, 0xb9, 0x95, 0x6b, 0x46, 0x6c, 0xf5, 0x08, 0xc1, 0x79, 0x2d, 0x99, 0xf2, - 0x2b, 0x6d, 0xd2, 0xb2, 0x29, 0x93, 0x66, 0xfc, 0x5e, 0x06, 0xaa, 0xb2, 0x64, 0x14, 0x4a, 0xd8, - 0x3a, 0x30, 0x35, 0x8b, 0xe1, 0xa5, 0x33, 0xb0, 0x8e, 0xaf, 0x42, 0x1e, 0x10, 0xd1, 0xec, 0xdc, - 0x30, 0x1b, 0x32, 0xad, 0x77, 0xe9, 0x0c, 0x36, 0x44, 0x0a, 0x7b, 0x00, 0x8d, 0x04, 0x7e, 0x10, - 0xfa, 0x44, 0xd1, 0x3b, 0x37, 0xcc, 0xba, 0x86, 0xdd, 0x0d, 0x7d, 0xb1, 0x46, 0x84, 0xc8, 0x33, - 0x09, 0x2d, 0xc7, 0x1d, 0xf0, 0x4b, 0x24, 0xa3, 0x9a, 0x59, 0x21, 0x58, 0x47, 0x80, 0x36, 0xea, - 0x50, 0xd5, 0x8b, 0x33, 0x4e, 0xa1, 0xa4, 0xe4, 0x25, 0x14, 0x18, 0xa6, 0x9a, 0x64, 0x96, 0xc3, - 0xa8, 0x25, 0x37, 0xa1, 0x94, 0x6c, 0x81, 0x59, 0x0c, 0x5f, 0xbb, 0x62, 0xe3, 0xbb, 0xd0, 0xd8, - 0x15, 0xc4, 0xe3, 0x0a, 0x62, 0x95, 0xf2, 0xdf, 0x0a, 0xcc, 0x69, 0x8b, 0xa6, 0x6c, 0xca, 0x2f, - 0xb1, 0xe7, 0x9e, 0x79, 0x41, 0x28, 0x6b, 0xc1, 0xdf, 0xc6, 0x1f, 0x67, 0x80, 0xb5, 0x83, 0xd0, - 0x19, 0xd9, 0x21, 0xdf, 0xe6, 0x11, 0x5b, 0x38, 0x80, 0xaa, 0x28, 0xad, 0xe7, 0xb5, 0x48, 0x20, - 0x23, 0x81, 0xe2, 0x7d, 0xb9, 0x8c, 0x67, 0x33, 0xac, 0xeb, 0xd8, 0xc4, 0xe6, 0x13, 0x05, 0x88, - 0x55, 0x16, 0xda, 0xfe, 0x29, 0x0f, 0x51, 0x8c, 0x93, 0xf2, 0x3e, 0x10, 0x48, 0x08, 0x70, 0x6b, - 0xbf, 0x0c, 0x0b, 0x33, 0x65, 0xe8, 0x7c, 0xb9, 0x9c, 0xc2, 0x97, 0x73, 0x3a, 0x5f, 0xb6, 0x60, - 0x31, 0xd1, 0x2e, 0x49, 0x69, 0xab, 0x50, 0x14, 0x0b, 0x42, 0x08, 0x07, 0x19, 0x92, 0x2a, 0x4f, - 0x38, 0x17, 0x62, 0xf0, 0x43, 0x58, 0x3a, 0xe1, 0xdc, 0xb7, 0x43, 0x4c, 0xc4, 0x15, 0x23, 0x66, - 0x48, 0x16, 0xbc, 0x20, 0xd3, 0xba, 0x76, 0x78, 0xc8, 0x7d, 0x31, 0x53, 0xc6, 0x7f, 0xcf, 0xc0, - 0xbc, 0xe0, 0xa0, 0x7b, 0xb6, 0x7b, 0xa5, 0xc6, 0x69, 0x37, 0x75, 0x9c, 0xee, 0x6b, 0x9b, 0xa1, - 0x86, 0xfd, 0x55, 0x07, 0x29, 0x37, 0x3d, 0x48, 0xec, 0x1e, 0x54, 0x13, 0x6d, 0x2d, 0x60, 0x5b, - 0x21, 0x88, 0x1a, 0xf9, 0xb3, 0x0f, 0xe3, 0x3b, 0xd0, 0x88, 0x9b, 0x2d, 0xc7, 0x90, 0x41, 0x5e, - 0x90, 0xa4, 0x2c, 0x00, 0x7f, 0x1b, 0xff, 0x24, 0x43, 0x88, 0x9b, 0x9e, 0x13, 0x49, 0xa7, 0x02, - 0x51, 0xc8, 0xbd, 0x0a, 0x51, 0xfc, 0xbe, 0x56, 0xaa, 0xff, 0xd9, 0x3b, 0x2b, 0x96, 0x4e, 0xc0, - 0xdd, 0x81, 0x65, 0x0f, 0x87, 0xc8, 0x7c, 0x4b, 0x66, 0x51, 0x7c, 0xb7, 0x86, 0x43, 0xe3, 0x5d, - 0x58, 0xd0, 0x5a, 0xf7, 0x92, 0x7e, 0xec, 0x03, 0xdb, 0x75, 0x82, 0xf0, 0xc8, 0x0d, 0xc6, 0x9a, - 0xe0, 0x76, 0x0b, 0xca, 0x82, 0xc3, 0x8a, 0x96, 0xd1, 0x92, 0x2d, 0x98, 0x82, 0xe5, 0x8a, 0x76, - 0x05, 0x98, 0x68, 0x5f, 0xca, 0xc4, 0xac, 0x4c, 0xb4, 0x2f, 0x31, 0xd1, 0xf8, 0x36, 0x2c, 0x26, - 0xca, 0x93, 0x55, 0xbf, 0x09, 0x85, 0x49, 0x78, 0xe9, 0x29, 0xd1, 0xbc, 0x22, 0x29, 0x44, 0x28, - 0x80, 0x26, 0xa5, 0x18, 0x9f, 0xc0, 0xc2, 0x3e, 0xbf, 0x90, 0x8b, 0x58, 0x35, 0xe4, 0x1d, 0xc8, - 0xbf, 0x42, 0x29, 0xc4, 0x74, 0x63, 0x1d, 0x98, 0x9e, 0x59, 0xd6, 0xaa, 0xe9, 0x88, 0x99, 0x84, - 0x8e, 0x68, 0xbc, 0x03, 0xac, 0xeb, 0x9c, 0xba, 0x7b, 0x3c, 0x08, 0xec, 0xd3, 0x68, 0xd9, 0x37, - 0x20, 0x37, 0x0a, 0x4e, 0x25, 0x8f, 0x12, 0x3f, 0x8d, 0x6f, 0xc2, 0x62, 0x02, 0x4f, 0x16, 0x7c, - 0x1b, 0xca, 0x81, 0x73, 0xea, 0xa2, 0x60, 0x25, 0x8b, 0x8e, 0x01, 0xc6, 0x36, 0x2c, 0x7d, 0xc6, - 0x7d, 0xe7, 0xe4, 0xea, 0x55, 0xc5, 0x27, 0xcb, 0xc9, 0x4e, 0x97, 0xd3, 0x86, 0xe5, 0xa9, 0x72, - 0x64, 0xf5, 0x44, 0xbe, 0x72, 0x26, 0x4b, 0x26, 0x7d, 0x68, 0x7c, 0x2f, 0xab, 0xf3, 0x3d, 0xe3, - 0x08, 0xd8, 0xa6, 0xe7, 0xba, 0xbc, 0x1f, 0x1e, 0x72, 0xee, 0xc7, 0xa7, 0x54, 0x31, 0xad, 0x56, - 0x1e, 0xaf, 0xca, 0x91, 0x9d, 0x66, 0xa6, 0x92, 0x88, 0x19, 0xe4, 0xc7, 0xdc, 0x1f, 0x61, 0xc1, - 0x25, 0x13, 0x7f, 0x1b, 0xcb, 0xb0, 0x98, 0x28, 0x56, 0xea, 0xf5, 0x8f, 0x60, 0x79, 0xcb, 0x09, - 0xfa, 0xb3, 0x15, 0xae, 0x42, 0x71, 0x3c, 0x39, 0xb6, 0x92, 0x7c, 0xf9, 0x19, 0xbf, 0x12, 0xda, - 0xde, 0x74, 0x0e, 0x59, 0xd6, 0x5f, 0xcf, 0x40, 0x7e, 0xa7, 0xb7, 0xbb, 0xc9, 0xd6, 0xa0, 0xe4, - 0xb8, 0x7d, 0x6f, 0x24, 0x04, 0x2f, 0xea, 0x73, 0xf4, 0x7d, 0xed, 0x02, 0xbb, 0x05, 0x65, 0x94, - 0xd7, 0x84, 0x6a, 0x2b, 0x45, 0x9f, 0x92, 0x00, 0xec, 0x7a, 0xfd, 0x17, 0x42, 0xa7, 0xe6, 0x97, - 0x63, 0xc7, 0x47, 0xad, 0x59, 0x29, 0xc3, 0x79, 0xda, 0xeb, 0xe3, 0x04, 0xd2, 0x88, 0x8d, 0x7f, - 0x5b, 0x82, 0xa2, 0xdc, 0x6d, 0x69, 0xe7, 0x0e, 0x9d, 0x73, 0x1e, 0xef, 0xdc, 0xe2, 0x4b, 0xc8, - 0x03, 0x3e, 0x1f, 0x79, 0x61, 0x24, 0xb0, 0xd1, 0x1c, 0x54, 0x09, 0x28, 0x45, 0x36, 0x4d, 0x68, - 0xa0, 0x23, 0x86, 0x1c, 0x21, 0xf5, 0xf5, 0xad, 0xfc, 0x16, 0x14, 0xd5, 0xde, 0x9f, 0x8f, 0x74, - 0x9a, 0xb9, 0x3e, 0x49, 0x6b, 0x6b, 0x50, 0xea, 0xdb, 0x63, 0xbb, 0xef, 0x84, 0x57, 0x92, 0x21, - 0x44, 0xdf, 0xa2, 0xf4, 0xa1, 0xd7, 0xb7, 0x87, 0xd6, 0xb1, 0x3d, 0xb4, 0xdd, 0x3e, 0x97, 0xba, - 0x7b, 0x15, 0x81, 0x1b, 0x04, 0x13, 0xfa, 0xb9, 0x6c, 0xa7, 0xc2, 0x22, 0x15, 0x5e, 0xb6, 0x5e, - 0xa1, 0x09, 0xe1, 0xd2, 0x1b, 0x8d, 0x1c, 0xa1, 0x65, 0x90, 0x18, 0x96, 0x33, 0xcb, 0x04, 0xd9, - 0xe6, 0xd8, 0x5b, 0x99, 0x7c, 0x41, 0x43, 0x57, 0xa6, 0xaa, 0x08, 0xf8, 0x39, 0x1d, 0x24, 0xcc, - 0xca, 0x62, 0x39, 0x4d, 0x16, 0x7b, 0x1f, 0x16, 0x26, 0x6e, 0xc0, 0xc3, 0x70, 0xc8, 0x07, 0x51, - 0x5b, 0x2a, 0x88, 0xd4, 0x88, 0x12, 0x54, 0x73, 0xd6, 0x61, 0x91, 0x0e, 0x1d, 0x02, 0x3b, 0xf4, - 0x82, 0x33, 0x27, 0xb0, 0x02, 0xa1, 0x21, 0x91, 0xba, 0xbb, 0x80, 0x49, 0x5d, 0x99, 0xd2, 0x25, - 0x15, 0x69, 0x75, 0x0a, 0xdf, 0xe7, 0x7d, 0xee, 0x9c, 0xf3, 0x01, 0xca, 0x69, 0x39, 0x73, 0x39, - 0x91, 0xc7, 0x94, 0x89, 0x28, 0x74, 0x4f, 0x46, 0xd6, 0x64, 0x3c, 0xb0, 0x85, 0xb0, 0x52, 0x27, - 0x61, 0xd8, 0x9d, 0x8c, 0x8e, 0x08, 0xc2, 0x1e, 0x81, 0x92, 0xc4, 0xa4, 0x7c, 0x38, 0x9f, 0xe0, - 0x67, 0x82, 0x58, 0xcd, 0xaa, 0xc4, 0x20, 0x41, 0x31, 0x21, 0x73, 0x36, 0xa6, 0x64, 0xce, 0x26, - 0x14, 0xc7, 0xbe, 0x73, 0x6e, 0x87, 0xbc, 0xb9, 0x40, 0x0c, 0x5c, 0x7e, 0x0a, 0xce, 0xe0, 0xb8, - 0x4e, 0xe8, 0xd8, 0xa1, 0xe7, 0x37, 0x19, 0xa6, 0xc5, 0x00, 0xf6, 0x00, 0x16, 0x90, 0x46, 0x82, - 0xd0, 0x0e, 0x27, 0x81, 0x94, 0x40, 0x17, 0x91, 0x98, 0x50, 0x86, 0xee, 0x22, 0x1c, 0x85, 0x50, - 0xf6, 0x4d, 0x58, 0x21, 0xb2, 0xc0, 0x1c, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x09, 0x87, 0x62, 0x11, - 0x53, 0x05, 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0x4f, 0x60, 0x55, 0x92, 0xc9, 0x4c, 0xae, 0x65, - 0xcc, 0xb5, 0x44, 0xc9, 0x53, 0xd9, 0xd6, 0x61, 0x41, 0x34, 0xc9, 0xe9, 0x5b, 0x32, 0xb7, 0x58, - 0x09, 0x2b, 0xa2, 0xf5, 0xa8, 0x29, 0xcd, 0x53, 0xa2, 0x89, 0x69, 0xcf, 0xf8, 0x15, 0xfb, 0x2e, - 0xcc, 0x13, 0xc9, 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x0d, 0x39, 0xfd, 0xb2, 0x3a, 0xe1, 0x8c, 0x52, - 0x91, 0xd9, 0xd7, 0xfb, 0x89, 0x6f, 0xb1, 0x1c, 0x86, 0xce, 0x09, 0x0f, 0x9d, 0x11, 0x6f, 0xae, - 0x12, 0x81, 0xa9, 0x6f, 0xb1, 0x52, 0x27, 0x63, 0x4c, 0x69, 0x12, 0x5f, 0xa0, 0x2f, 0xa4, 0xdd, - 0xa1, 0x17, 0x70, 0x75, 0x44, 0xd5, 0xbc, 0x29, 0x17, 0xa1, 0x00, 0x2a, 0x19, 0x52, 0x08, 0xe2, - 0xa4, 0xf4, 0x44, 0x07, 0x89, 0xb7, 0x90, 0x18, 0x6a, 0xa4, 0xfb, 0xa8, 0xc3, 0x44, 0xb1, 0x8b, - 0x9f, 0xd9, 0x17, 0x8a, 0x83, 0xdc, 0xc6, 0xf9, 0x05, 0x01, 0x92, 0xbc, 0xe3, 0x27, 0x19, 0xda, - 0x10, 0x25, 0xff, 0x08, 0x34, 0xf5, 0x8e, 0x38, 0x87, 0xe5, 0xb9, 0xc3, 0x2b, 0xc9, 0x4c, 0x80, - 0x40, 0x07, 0xee, 0x10, 0x57, 0xb3, 0xe3, 0xea, 0x28, 0xc4, 0x7b, 0xab, 0x0a, 0x88, 0x48, 0x77, - 0xa1, 0x32, 0x9e, 0x1c, 0x0f, 0x9d, 0x3e, 0xa1, 0xe4, 0xa8, 0x14, 0x02, 0x21, 0x82, 0xd0, 0x6f, - 0x89, 0xa2, 0x08, 0x23, 0x8f, 0x18, 0x15, 0x09, 0x43, 0x14, 0xe4, 0xed, 0xdc, 0x47, 0x76, 0x52, - 0x35, 0xf1, 0xb7, 0xb1, 0x01, 0x4b, 0xc9, 0x46, 0xcb, 0x8d, 0xe7, 0x01, 0x94, 0x24, 0xaf, 0x52, - 0x07, 0x1f, 0x75, 0xed, 0x28, 0x5a, 0xa8, 0x68, 0x51, 0xba, 0xf1, 0xfb, 0x05, 0x58, 0x94, 0xd0, - 0x4d, 0x31, 0xb4, 0xdd, 0xc9, 0x68, 0x64, 0xfb, 0x29, 0x4c, 0x30, 0xf3, 0x72, 0x26, 0x98, 0x9d, - 0x61, 0x82, 0x49, 0xcd, 0x97, 0x78, 0x68, 0x52, 0xf3, 0x15, 0x73, 0x49, 0xca, 0x88, 0x7e, 0x0e, - 0x5a, 0x93, 0xe0, 0x1e, 0x9d, 0xb7, 0xce, 0xb0, 0xec, 0x42, 0x0a, 0xcb, 0xd6, 0x19, 0xee, 0xdc, - 0x14, 0xc3, 0x7d, 0x13, 0x88, 0x68, 0xd4, 0xec, 0x17, 0x49, 0x3f, 0x41, 0x98, 0x3c, 0x4c, 0x7d, - 0x17, 0xe6, 0xa7, 0x79, 0x1c, 0x31, 0xd3, 0x7a, 0x0a, 0x87, 0x73, 0x46, 0x1c, 0x77, 0x2b, 0x0d, - 0xb9, 0x2c, 0x39, 0x9c, 0x33, 0xe2, 0xbb, 0x98, 0xa2, 0xf0, 0xdb, 0x00, 0x54, 0x37, 0x2e, 0x1a, - 0xc0, 0x45, 0xf3, 0x4e, 0x72, 0x2e, 0xf4, 0x51, 0x5f, 0x17, 0x1f, 0x13, 0x9f, 0xe3, 0x2a, 0x2a, - 0x63, 0x4e, 0x5c, 0x40, 0x1f, 0x41, 0xdd, 0x1b, 0x73, 0xd7, 0x8a, 0x79, 0x4d, 0x05, 0x8b, 0x6a, - 0xc8, 0xa2, 0x3a, 0x0a, 0x6e, 0xd6, 0x04, 0x5e, 0xf4, 0xc9, 0xbe, 0x43, 0x83, 0xcc, 0xb5, 0x9c, - 0xd5, 0x6b, 0x72, 0xd6, 0x11, 0x31, 0xfa, 0x36, 0xfe, 0x56, 0x06, 0x2a, 0x5a, 0x73, 0xd8, 0x32, - 0x2c, 0x6c, 0x1e, 0x1c, 0x1c, 0xb6, 0xcd, 0x56, 0xaf, 0xf3, 0x59, 0xdb, 0xda, 0xdc, 0x3d, 0xe8, - 0xb6, 0x1b, 0x37, 0x04, 0x78, 0xf7, 0x60, 0xb3, 0xb5, 0x6b, 0x6d, 0x1f, 0x98, 0x9b, 0x0a, 0x9c, - 0x61, 0x2b, 0xc0, 0xcc, 0xf6, 0xde, 0x41, 0xaf, 0x9d, 0x80, 0x67, 0x59, 0x03, 0xaa, 0x1b, 0x66, - 0xbb, 0xb5, 0xb9, 0x23, 0x21, 0x39, 0xb6, 0x04, 0x8d, 0xed, 0xa3, 0xfd, 0xad, 0xce, 0xfe, 0x53, - 0x6b, 0xb3, 0xb5, 0xbf, 0xd9, 0xde, 0x6d, 0x6f, 0x35, 0xf2, 0xac, 0x06, 0xe5, 0xd6, 0x46, 0x6b, - 0x7f, 0xeb, 0x60, 0xbf, 0xbd, 0xd5, 0x28, 0x18, 0x7f, 0x9e, 0x81, 0x65, 0x1c, 0xa8, 0xc1, 0xf4, - 0x0a, 0xbd, 0x07, 0x95, 0xbe, 0xe7, 0x8d, 0x85, 0x1a, 0x14, 0x6f, 0xf7, 0x3a, 0x48, 0xac, 0x3e, - 0xe2, 0xac, 0x27, 0x9e, 0xdf, 0xe7, 0x72, 0x81, 0x02, 0x82, 0xb6, 0x05, 0x44, 0x10, 0x88, 0xa4, - 0x30, 0xc2, 0xa0, 0xf5, 0x59, 0x21, 0x18, 0xa1, 0xac, 0xc0, 0xdc, 0xb1, 0xcf, 0xed, 0xfe, 0x99, - 0x5c, 0x9a, 0xf2, 0x8b, 0xbd, 0x17, 0x2b, 0xe8, 0x7d, 0x31, 0xe1, 0x43, 0x3e, 0x40, 0xfa, 0x2c, - 0x99, 0xf3, 0x12, 0xbe, 0x29, 0xc1, 0x62, 0xab, 0xb0, 0x8f, 0x6d, 0x77, 0xe0, 0xb9, 0x7c, 0x20, - 0xf5, 0x80, 0x18, 0x60, 0x1c, 0xc2, 0xca, 0x74, 0xff, 0xe4, 0x62, 0xfe, 0x50, 0x5b, 0xcc, 0x24, - 0x96, 0xaf, 0x5d, 0x4f, 0x40, 0xda, 0xc2, 0xfe, 0x3b, 0x79, 0xc8, 0x0b, 0x31, 0xed, 0x5a, 0x89, - 0x4e, 0x97, 0xbb, 0x73, 0x33, 0xb6, 0x19, 0x3c, 0x07, 0xa0, 0xfd, 0x9b, 0x0e, 0x9b, 0xca, 0x08, - 0xc1, 0x7d, 0x3b, 0x4a, 0xf6, 0x79, 0xff, 0x5c, 0x9e, 0x36, 0x51, 0xb2, 0xc9, 0xfb, 0xe7, 0xa8, - 0xf0, 0xd8, 0x21, 0xe5, 0xa5, 0xc5, 0x58, 0x0c, 0xec, 0x10, 0x73, 0xca, 0x24, 0xcc, 0x57, 0x8c, - 0x92, 0x30, 0x57, 0x13, 0x8a, 0x8e, 0x7b, 0xec, 0x4d, 0xdc, 0x01, 0xae, 0xbd, 0x92, 0xa9, 0x3e, - 0xd1, 0x14, 0x84, 0x6c, 0x42, 0xec, 0x12, 0xb4, 0xd4, 0x4a, 0x02, 0xd0, 0x13, 0xfb, 0xc4, 0x07, - 0x50, 0x0e, 0xae, 0xdc, 0xbe, 0xbe, 0xc0, 0x96, 0xe4, 0xf8, 0x88, 0xde, 0xaf, 0x77, 0xaf, 0xdc, - 0x3e, 0x2e, 0xa7, 0x52, 0x20, 0x7f, 0xb1, 0x27, 0x50, 0x8a, 0x0e, 0x65, 0x89, 0x3d, 0xde, 0xd4, - 0x73, 0xa8, 0x93, 0x58, 0xd2, 0x7d, 0x23, 0x54, 0xf6, 0x10, 0xe6, 0xf0, 0xe4, 0x34, 0x68, 0x56, - 0x31, 0x93, 0x12, 0xc6, 0x45, 0x33, 0xd0, 0x0a, 0xc3, 0x07, 0x78, 0x8a, 0x6a, 0x4a, 0xb4, 0xb5, - 0x67, 0x50, 0x4b, 0x94, 0xa5, 0x6b, 0xb8, 0x35, 0xd2, 0x70, 0xdf, 0xd6, 0x35, 0xdc, 0x98, 0x4d, - 0xcb, 0x6c, 0xba, 0xc6, 0xfb, 0xcb, 0x50, 0x52, 0x5d, 0x11, 0x8b, 0xe8, 0x68, 0xff, 0xd9, 0xfe, - 0xc1, 0xe7, 0xfb, 0x56, 0xf7, 0xf9, 0xfe, 0x66, 0xe3, 0x06, 0x9b, 0x87, 0x4a, 0x6b, 0x13, 0xd7, - 0x25, 0x02, 0x32, 0x02, 0xe5, 0xb0, 0xd5, 0xed, 0x46, 0x90, 0xac, 0xb1, 0x0d, 0x8d, 0xe9, 0x96, - 0x0a, 0x9a, 0x0c, 0x15, 0x4c, 0x9e, 0x2b, 0xc7, 0x00, 0xa1, 0xbf, 0xd0, 0x51, 0x31, 0x09, 0xc9, - 0xf4, 0x61, 0x3c, 0x81, 0x86, 0xd8, 0x74, 0xc4, 0x50, 0x05, 0xda, 0xf9, 0xec, 0x50, 0x08, 0x5e, - 0xfa, 0xd9, 0x72, 0xc9, 0xac, 0x10, 0x0c, 0xab, 0x32, 0x3e, 0x84, 0x05, 0x2d, 0x5b, 0xac, 0x6f, - 0x8a, 0x8d, 0x6c, 0x5a, 0xdf, 0x44, 0xed, 0x82, 0x52, 0x8c, 0x55, 0x58, 0x16, 0x9f, 0xed, 0x73, - 0xee, 0x86, 0xdd, 0xc9, 0x31, 0x19, 0x04, 0x1d, 0xcf, 0x15, 0x5a, 0x47, 0x39, 0x4a, 0xb9, 0x9e, - 0xc8, 0xd7, 0xa5, 0x6a, 0x9a, 0x45, 0xd2, 0x58, 0xd3, 0x6a, 0xc0, 0x8c, 0xeb, 0xf8, 0x37, 0xa1, - 0xa2, 0x96, 0x23, 0x90, 0x18, 0xd6, 0xc3, 0x76, 0xdb, 0xb4, 0x0e, 0xf6, 0x77, 0x3b, 0xfb, 0x82, - 0xdb, 0x89, 0x61, 0x45, 0xc0, 0xf6, 0x36, 0x42, 0x32, 0x46, 0x03, 0xea, 0x4f, 0x79, 0xd8, 0x71, - 0x4f, 0x3c, 0x65, 0xfc, 0xfa, 0x8b, 0x02, 0xcc, 0x47, 0xa0, 0x58, 0xc5, 0x3d, 0xe7, 0x7e, 0xe0, - 0x78, 0x2e, 0x4a, 0xab, 0x65, 0x53, 0x7d, 0x8a, 0xad, 0xc7, 0x19, 0x70, 0x37, 0x74, 0xc2, 0x2b, - 0x2b, 0x71, 0x1e, 0x56, 0x57, 0x60, 0xb9, 0xc5, 0x2d, 0x41, 0xc1, 0x1e, 0x3a, 0xb6, 0xb2, 0xa3, - 0xd2, 0x87, 0x80, 0xf6, 0xbd, 0xa1, 0xe7, 0xa3, 0x60, 0x5a, 0x36, 0xe9, 0x83, 0x3d, 0x82, 0x25, - 0x21, 0x20, 0xeb, 0x87, 0x94, 0xc8, 0x3f, 0xe8, 0x68, 0x8e, 0xb9, 0x93, 0xd1, 0x61, 0x7c, 0x50, - 0x29, 0x52, 0xc4, 0xc6, 0x26, 0x72, 0x48, 0x49, 0x26, 0xca, 0x40, 0xba, 0xd6, 0x82, 0x3b, 0x19, - 0xb5, 0x30, 0x25, 0xc2, 0x7f, 0x0c, 0xcb, 0x02, 0x3f, 0x92, 0x7d, 0xa2, 0x1c, 0xf3, 0x98, 0x43, - 0x14, 0xd6, 0x91, 0x69, 0x51, 0x9e, 0x5b, 0x50, 0xa6, 0x56, 0x89, 0x19, 0x2f, 0x90, 0x8c, 0x8d, - 0x4d, 0xe1, 0x7e, 0x30, 0x63, 0xf2, 0x9c, 0xa3, 0x5d, 0x7a, 0xca, 0xe4, 0xa9, 0x19, 0x4d, 0x4b, - 0xd3, 0x46, 0xd3, 0xc7, 0xb0, 0x7c, 0x2c, 0x48, 0xf0, 0x8c, 0xdb, 0x03, 0xee, 0x5b, 0x31, 0x61, - 0x93, 0x2e, 0xb1, 0x28, 0x12, 0x77, 0x30, 0x2d, 0x5a, 0x07, 0x42, 0x08, 0x11, 0x6c, 0x81, 0x0f, - 0xac, 0xd0, 0xb3, 0x50, 0x36, 0x41, 0x06, 0x53, 0x32, 0x6b, 0x04, 0xee, 0x79, 0x9b, 0x02, 0x98, - 0xc4, 0x3b, 0xf5, 0xed, 0xf1, 0x99, 0x94, 0xf6, 0x23, 0xbc, 0xa7, 0x02, 0xc8, 0x6e, 0x43, 0x51, - 0x90, 0xbc, 0xcb, 0xc9, 0x32, 0x45, 0xf2, 0xb4, 0x02, 0xb1, 0xb7, 0x61, 0x0e, 0xeb, 0x08, 0x9a, - 0x0d, 0xa4, 0xf7, 0x6a, 0xcc, 0xc8, 0x1d, 0xd7, 0x94, 0x69, 0x42, 0xd2, 0x9b, 0xf8, 0x0e, 0x71, - 0x99, 0xb2, 0x89, 0xbf, 0xd9, 0xf7, 0x34, 0x96, 0xb5, 0x88, 0x79, 0xdf, 0x96, 0x79, 0xa7, 0x28, - 0xed, 0x3a, 0xee, 0xf5, 0x73, 0x65, 0x46, 0xdf, 0xcf, 0x97, 0x2a, 0x8d, 0xaa, 0xf1, 0x11, 0x14, - 0x68, 0x74, 0x04, 0x11, 0xe2, 0xd8, 0x65, 0x24, 0x11, 0x22, 0xb4, 0x09, 0x45, 0x97, 0x87, 0x17, - 0x9e, 0xff, 0x42, 0x9d, 0x18, 0xcb, 0x4f, 0xe3, 0x47, 0x78, 0xd4, 0x11, 0x99, 0xc3, 0x49, 0x6b, - 0x13, 0xe4, 0x41, 0xd3, 0x1b, 0x9c, 0xd9, 0xf2, 0xf4, 0xa5, 0x84, 0x80, 0xee, 0x99, 0x3d, 0x43, - 0x1e, 0xd9, 0x59, 0x8b, 0xf8, 0xdb, 0x50, 0x57, 0x06, 0xf8, 0xc0, 0x1a, 0xf2, 0x93, 0x50, 0x92, - 0x7b, 0x55, 0x5a, 0xdf, 0x83, 0x5d, 0x7e, 0x12, 0x1a, 0x7b, 0xb0, 0x20, 0x09, 0xf2, 0x60, 0xcc, - 0x55, 0xd5, 0xdf, 0x4e, 0x13, 0x76, 0x2b, 0x8f, 0x17, 0x93, 0x1b, 0x2d, 0x39, 0x16, 0x24, 0x24, - 0x60, 0xe3, 0x53, 0x60, 0xfa, 0x36, 0x2c, 0xcb, 0x93, 0x22, 0xa7, 0x3a, 0x68, 0x57, 0xf6, 0xaa, - 0x48, 0xb0, 0x75, 0x06, 0x62, 0x74, 0x82, 0x49, 0xbf, 0xaf, 0x1c, 0x23, 0x4a, 0xa6, 0xfa, 0x34, - 0xfe, 0x24, 0x03, 0x8b, 0x58, 0x98, 0x12, 0xd6, 0x25, 0x93, 0xfd, 0xa9, 0x1b, 0x29, 0xe6, 0x47, - 0x97, 0x7d, 0xe8, 0xe3, 0xab, 0x1f, 0x6d, 0xe6, 0x67, 0x8e, 0x36, 0xdf, 0x83, 0xc6, 0x80, 0x0f, - 0x1d, 0xf4, 0x91, 0x51, 0xa2, 0x04, 0x89, 0xe7, 0xf3, 0x0a, 0x2e, 0x55, 0x35, 0xe3, 0x1f, 0x66, - 0x60, 0x81, 0x24, 0x15, 0x54, 0x7a, 0xe5, 0x40, 0x7d, 0xa2, 0xb4, 0x3c, 0xc9, 0xaa, 0x64, 0x9f, - 0xe2, 0x1d, 0x1c, 0xa1, 0x84, 0xbc, 0x73, 0x43, 0x6a, 0x7f, 0x12, 0xca, 0x3e, 0x46, 0x05, 0xc3, - 0xb5, 0x10, 0x98, 0xe2, 0x73, 0x93, 0x9c, 0x94, 0x9d, 0x1b, 0xa8, 0x7d, 0xb8, 0x08, 0xda, 0x28, - 0x09, 0xb5, 0x53, 0x80, 0x8d, 0x6d, 0xa8, 0x25, 0xaa, 0x49, 0x9c, 0xbf, 0x56, 0xe9, 0xfc, 0x75, - 0xc6, 0xc6, 0x91, 0x9d, 0xb5, 0x71, 0x5c, 0xc1, 0xa2, 0xc9, 0xed, 0xc1, 0xd5, 0xb6, 0xe7, 0x1f, - 0x06, 0xc7, 0xe1, 0x36, 0x89, 0x7f, 0x82, 0xbf, 0x47, 0x86, 0xbb, 0xc4, 0x21, 0xa7, 0xb2, 0xdf, - 0x28, 0x5d, 0xf6, 0x6b, 0x50, 0x8f, 0x2d, 0x7c, 0xda, 0x41, 0x59, 0x2d, 0x32, 0xf2, 0xe1, 0x79, - 0x99, 0xd0, 0x03, 0x83, 0xe3, 0x50, 0x1e, 0x95, 0xe1, 0x6f, 0xe3, 0x6f, 0xe4, 0x81, 0x09, 0x6a, - 0x9e, 0x22, 0x98, 0x29, 0xdb, 0x64, 0x76, 0xc6, 0x36, 0xf9, 0x08, 0x98, 0x86, 0xa0, 0x4c, 0xa6, - 0xb9, 0xc8, 0x64, 0xda, 0x88, 0x71, 0xa5, 0xc5, 0xf4, 0x11, 0x2c, 0x49, 0x59, 0x3a, 0xd9, 0x54, - 0x22, 0x0d, 0x46, 0x42, 0x75, 0xa2, 0xbd, 0xca, 0x2e, 0x29, 0x74, 0x73, 0x3a, 0x0a, 0x43, 0xbb, - 0xa4, 0xd2, 0xca, 0x35, 0x02, 0x9c, 0x7b, 0x25, 0x01, 0x16, 0x67, 0x08, 0x50, 0x3b, 0x99, 0x29, - 0x25, 0x4f, 0x66, 0x0c, 0xa8, 0x29, 0xeb, 0x23, 0x39, 0x5d, 0x90, 0xe0, 0x58, 0x91, 0x26, 0x48, - 0x74, 0xbc, 0xb8, 0x0f, 0x0d, 0x75, 0x7c, 0x12, 0x9d, 0xfd, 0x90, 0x43, 0x81, 0x3c, 0x7d, 0xdb, - 0x54, 0x27, 0x40, 0x89, 0x93, 0xf6, 0xca, 0xd4, 0x49, 0xfb, 0xfb, 0xb0, 0x10, 0x08, 0xfa, 0xb5, - 0x26, 0xae, 0xf4, 0xfe, 0xe1, 0x03, 0x54, 0xb3, 0x4a, 0x66, 0x03, 0x13, 0x8e, 0x62, 0xf8, 0xec, - 0xb9, 0x46, 0x2d, 0xe5, 0x5c, 0xe3, 0x49, 0x6c, 0xa8, 0x0b, 0xce, 0x9c, 0x11, 0xca, 0x0c, 0xb1, - 0xa7, 0x8c, 0x1c, 0xe0, 0xee, 0x99, 0x33, 0x32, 0x95, 0x55, 0x58, 0x7c, 0x18, 0xff, 0x37, 0x03, - 0x0d, 0x41, 0x07, 0x89, 0x25, 0xf6, 0x1d, 0x40, 0x66, 0xf0, 0x9a, 0x2b, 0xac, 0x22, 0x70, 0xd5, - 0x02, 0xfb, 0x08, 0x70, 0xc5, 0x58, 0x42, 0xa7, 0x94, 0xeb, 0xab, 0x99, 0x5c, 0x5f, 0x31, 0x0f, - 0xdd, 0xb9, 0x41, 0xba, 0x87, 0x80, 0xb0, 0xef, 0x40, 0x59, 0x10, 0x26, 0x52, 0x89, 0x74, 0xd0, - 0x52, 0x92, 0x57, 0xca, 0x1a, 0x11, 0x59, 0xc7, 0xf2, 0x33, 0xcd, 0xb6, 0x9a, 0x4f, 0xb1, 0xad, - 0x6a, 0x0b, 0x78, 0x07, 0xe0, 0x19, 0xbf, 0xda, 0xf5, 0xfa, 0xa8, 0xf1, 0xde, 0x01, 0x10, 0xb4, - 0x7c, 0x62, 0x8f, 0x1c, 0x79, 0x60, 0x53, 0x30, 0xcb, 0x2f, 0xf8, 0xd5, 0x36, 0x02, 0xc4, 0x44, - 0x8a, 0xe4, 0x78, 0x15, 0x17, 0xcc, 0xd2, 0x0b, 0x7e, 0x45, 0x4b, 0xd8, 0x82, 0xda, 0x33, 0x7e, - 0xb5, 0xc5, 0x49, 0xc8, 0xf4, 0x7c, 0x41, 0x44, 0xbe, 0x7d, 0x21, 0xa4, 0xca, 0x84, 0x5d, 0xb4, - 0xe2, 0xdb, 0x17, 0xcf, 0xf8, 0x95, 0xb2, 0xd1, 0x16, 0x45, 0xfa, 0xd0, 0xeb, 0xcb, 0x7d, 0x53, - 0x79, 0x78, 0xc4, 0x8d, 0x32, 0xe7, 0x5e, 0xe0, 0x6f, 0xe3, 0x2f, 0x33, 0x50, 0x13, 0xed, 0x47, - 0xb6, 0x2c, 0xa6, 0x4c, 0x39, 0x0a, 0x65, 0x62, 0x47, 0xa1, 0xc7, 0x92, 0xab, 0x11, 0x8f, 0xcf, - 0x5e, 0xcf, 0xe3, 0x71, 0x6e, 0x88, 0xc1, 0x7f, 0x00, 0x65, 0x5a, 0x96, 0x62, 0x9d, 0xe7, 0x12, - 0x13, 0x9c, 0xe8, 0x90, 0x59, 0x42, 0xb4, 0x67, 0xe4, 0x97, 0xa0, 0x1d, 0xfe, 0xd1, 0x10, 0x97, - 0xfd, 0xe8, 0xc8, 0x2f, 0x65, 0x1a, 0x0a, 0xd7, 0xf8, 0x25, 0xe8, 0x27, 0x6b, 0x73, 0x33, 0x27, - 0x6b, 0x07, 0x50, 0x12, 0x53, 0x8d, 0x9d, 0x4d, 0x29, 0x34, 0x93, 0x56, 0xa8, 0x90, 0x04, 0x6c, - 0xb1, 0x29, 0x08, 0x46, 0x97, 0x95, 0x92, 0x80, 0x1d, 0xf0, 0x43, 0x64, 0x76, 0x19, 0xa8, 0x68, - 0x2b, 0x00, 0x0f, 0x27, 0xa3, 0xf1, 0xa2, 0xe5, 0x92, 0x24, 0xf1, 0xc4, 0x80, 0xef, 0xdc, 0x30, - 0x6b, 0xfd, 0xc4, 0x0c, 0xac, 0x4b, 0x5a, 0xc5, 0x9c, 0xd9, 0x84, 0x4f, 0x93, 0x6a, 0xb8, 0x22, - 0x50, 0xf1, 0x7b, 0x63, 0x0e, 0xf2, 0x02, 0xd5, 0xf8, 0x04, 0x16, 0xb4, 0x66, 0x90, 0x9a, 0xff, - 0xba, 0x3d, 0x34, 0x7e, 0x2d, 0xca, 0x2c, 0xea, 0x20, 0xf3, 0x91, 0xf2, 0xf1, 0xe0, 0x03, 0xea, - 0xb8, 0xf4, 0x25, 0x21, 0x90, 0x40, 0x7b, 0x6d, 0xbf, 0x83, 0xdf, 0x80, 0x45, 0xad, 0xf4, 0x6d, - 0xc7, 0xb5, 0x87, 0xce, 0x8f, 0x70, 0xc3, 0x0f, 0x9c, 0x53, 0x77, 0xaa, 0x7c, 0x02, 0x7d, 0xa5, - 0xf2, 0xff, 0x51, 0x16, 0x96, 0x64, 0x05, 0xe8, 0xb5, 0xe7, 0x08, 0x29, 0x6e, 0x2f, 0x38, 0x65, - 0xdf, 0x81, 0x9a, 0x18, 0x1b, 0xcb, 0xe7, 0xa7, 0x4e, 0x10, 0x72, 0x65, 0xb6, 0x4a, 0x61, 0x5c, - 0x62, 0x33, 0x17, 0xa8, 0xa6, 0xc4, 0x64, 0x9f, 0x40, 0x05, 0xb3, 0xd2, 0x31, 0x8a, 0x9c, 0x88, - 0xe6, 0x6c, 0x46, 0x1a, 0xe8, 0x9d, 0x1b, 0x26, 0x04, 0xf1, 0xb0, 0x7f, 0x02, 0x15, 0x9c, 0xc3, - 0x73, 0x1c, 0xc8, 0x29, 0x56, 0x35, 0x33, 0xd0, 0x22, 0xf3, 0x38, 0x1e, 0xf6, 0x16, 0xd4, 0x88, - 0x59, 0xc9, 0x71, 0x92, 0xde, 0x40, 0x6b, 0xb3, 0xd9, 0xd5, 0x48, 0x8a, 0xc6, 0x8f, 0xb5, 0xef, - 0x8d, 0x32, 0x14, 0x43, 0xdf, 0x39, 0x3d, 0xe5, 0xbe, 0xb1, 0x12, 0x0d, 0x8d, 0xe0, 0xc2, 0xbc, - 0x1b, 0xf2, 0xb1, 0x90, 0xcd, 0x8d, 0x7f, 0x9f, 0x81, 0x8a, 0xe4, 0xab, 0x3f, 0xb5, 0xad, 0x6c, - 0x4d, 0x73, 0x7b, 0xa5, 0x13, 0x9b, 0xd8, 0xcb, 0xf5, 0x5d, 0x98, 0x1f, 0x09, 0x39, 0x5d, 0xe8, - 0x91, 0x09, 0x43, 0x59, 0x5d, 0x81, 0xa5, 0x98, 0xbc, 0x0e, 0x8b, 0x28, 0x35, 0x07, 0x56, 0xe8, - 0x0c, 0x2d, 0x95, 0x28, 0x5d, 0x4c, 0x17, 0x28, 0xa9, 0xe7, 0x0c, 0xf7, 0x64, 0x82, 0x10, 0x1e, - 0x83, 0xd0, 0x3e, 0xe5, 0x72, 0x6d, 0xd3, 0x87, 0xd1, 0x84, 0x95, 0x29, 0x15, 0x52, 0xa9, 0xbf, - 0xff, 0x7b, 0x01, 0x56, 0x67, 0x92, 0xa4, 0x1a, 0x1c, 0x19, 0x88, 0x86, 0xce, 0xe8, 0xd8, 0x8b, - 0x8e, 0x4f, 0x33, 0x9a, 0x81, 0x68, 0x57, 0xa4, 0xa8, 0xe3, 0x53, 0x0e, 0xcb, 0x8a, 0x20, 0xf1, - 0xfc, 0x33, 0xd2, 0x32, 0xb3, 0xa8, 0x03, 0x7d, 0x90, 0xdc, 0xc4, 0xa6, 0xab, 0x53, 0x70, 0x5d, - 0x34, 0x5a, 0x1c, 0xcf, 0xc0, 0x02, 0xf6, 0x9b, 0xd0, 0x8c, 0xe8, 0x5e, 0x8a, 0xed, 0x9a, 0xca, - 0x2c, 0x6a, 0xfa, 0xfa, 0x2b, 0x6a, 0x4a, 0x9c, 0xdd, 0xa1, 0xec, 0xb4, 0xa2, 0x96, 0x0c, 0x15, - 0x18, 0xd5, 0x75, 0x0e, 0x6f, 0xa8, 0xba, 0x50, 0x0c, 0x9f, 0xad, 0x31, 0xff, 0x5a, 0x7d, 0xc3, - 0x73, 0xc9, 0x44, 0xb5, 0xe6, 0x2d, 0x59, 0x70, 0x94, 0xa4, 0xd7, 0x7b, 0x06, 0x2b, 0x17, 0xb6, - 0x13, 0xaa, 0x3e, 0x6a, 0x1a, 0x7b, 0x01, 0xeb, 0x7b, 0xfc, 0x8a, 0xfa, 0x3e, 0xa7, 0xcc, 0x09, - 0xc5, 0x64, 0xe9, 0x62, 0x16, 0x18, 0xac, 0xfd, 0xbd, 0x1c, 0xd4, 0x93, 0xa5, 0x08, 0xc6, 0x22, - 0x37, 0x1b, 0x25, 0x6f, 0x4a, 0x21, 0x58, 0x1e, 0xed, 0xef, 0x93, 0x9c, 0x39, 0x6b, 0x74, 0xc8, - 0xa6, 0x18, 0x1d, 0xf4, 0xb3, 0xfe, 0xdc, 0xab, 0x8c, 0xab, 0xf9, 0xd7, 0x32, 0xae, 0x16, 0xd2, - 0x8c, 0xab, 0xd7, 0x5b, 0xe4, 0xe6, 0x7e, 0x2a, 0x8b, 0x5c, 0xf1, 0x25, 0x16, 0xb9, 0x84, 0x1d, - 0xb1, 0x34, 0x6d, 0x47, 0x4c, 0xb1, 0xbf, 0x95, 0xbf, 0x82, 0xfd, 0x6d, 0xed, 0x2f, 0x33, 0xc0, - 0x66, 0xd7, 0x02, 0x7b, 0x4a, 0xd6, 0x1b, 0x97, 0x0f, 0x25, 0x9f, 0xfe, 0xc6, 0xeb, 0xad, 0x27, - 0x35, 0xfd, 0x2a, 0x37, 0x7b, 0x08, 0x8b, 0xba, 0xdb, 0xbb, 0xae, 0xa3, 0xd7, 0x4c, 0xa6, 0x27, - 0xc5, 0x27, 0x39, 0x9a, 0xdd, 0x3a, 0xff, 0x4a, 0xbb, 0x75, 0xe1, 0x95, 0x76, 0xeb, 0xb9, 0xa4, - 0xdd, 0x7a, 0xed, 0x3f, 0x67, 0x60, 0x31, 0x85, 0x64, 0x7f, 0x7e, 0x7d, 0x16, 0x94, 0x96, 0x60, - 0x62, 0x59, 0x49, 0x69, 0x3a, 0xff, 0xda, 0x85, 0x4a, 0x3c, 0x15, 0x2a, 0x2c, 0xe4, 0xc1, 0xab, - 0x78, 0x49, 0x9c, 0xc3, 0xd4, 0xb3, 0xaf, 0xfd, 0x7e, 0x16, 0x2a, 0x5a, 0xa2, 0x18, 0x45, 0x22, - 0x50, 0xcd, 0x5d, 0x88, 0xe4, 0x40, 0x3c, 0x61, 0xb8, 0x0b, 0xd2, 0x84, 0x41, 0xe9, 0xb4, 0x94, - 0xa4, 0xd0, 0x87, 0x08, 0xeb, 0xb0, 0xa8, 0x2c, 0x6b, 0x3c, 0xf6, 0x0a, 0x94, 0x3b, 0xcb, 0x82, - 0xb4, 0xaf, 0xf1, 0xc8, 0xc9, 0x90, 0x3d, 0x54, 0xca, 0x5f, 0x3c, 0x77, 0x48, 0xd8, 0x64, 0x1f, - 0x58, 0xa0, 0xe5, 0xa0, 0x26, 0x51, 0x50, 0xf5, 0x07, 0xb0, 0xac, 0x16, 0x43, 0x32, 0x07, 0x99, - 0x0c, 0x98, 0x5c, 0x0a, 0x7a, 0x96, 0xef, 0xc1, 0x9d, 0xa9, 0x36, 0x4d, 0x65, 0x25, 0xf7, 0xd5, - 0x9b, 0x89, 0xd6, 0xe9, 0x25, 0xac, 0xfd, 0x18, 0x6a, 0x09, 0xb6, 0xf8, 0xf3, 0x9b, 0xf2, 0xe9, - 0x53, 0x1d, 0x1a, 0x51, 0xfd, 0x54, 0x67, 0xed, 0xff, 0xe4, 0x80, 0xcd, 0x72, 0xe6, 0x5f, 0x64, - 0x13, 0x66, 0x09, 0x33, 0x97, 0x42, 0x98, 0xff, 0xdf, 0xa4, 0x85, 0xf7, 0x61, 0x41, 0x86, 0x47, - 0x69, 0xe6, 0x51, 0x5a, 0x9c, 0x8d, 0x28, 0x41, 0xb5, 0xe2, 0xa3, 0x69, 0x37, 0x8d, 0x52, 0x22, - 0x22, 0x44, 0x13, 0x97, 0xa6, 0xbc, 0x35, 0x8e, 0x60, 0xce, 0x76, 0xfb, 0x67, 0x9e, 0x2f, 0xf9, - 0xe0, 0x2f, 0x7d, 0xe5, 0xcd, 0x72, 0xbd, 0x85, 0xf9, 0x51, 0x46, 0x33, 0x65, 0x61, 0xc6, 0x07, - 0x50, 0xd1, 0xc0, 0xac, 0x0c, 0x85, 0xdd, 0xce, 0xde, 0xc6, 0x41, 0xe3, 0x06, 0xab, 0x41, 0xd9, - 0x6c, 0x6f, 0x1e, 0x7c, 0xd6, 0x36, 0xdb, 0x5b, 0x8d, 0x0c, 0x2b, 0x41, 0x7e, 0xf7, 0xa0, 0xdb, - 0x6b, 0x64, 0x8d, 0x35, 0x68, 0xca, 0x12, 0x67, 0x2d, 0x14, 0xbf, 0x93, 0x8f, 0x0e, 0x07, 0x31, - 0x51, 0x2a, 0xe4, 0xdf, 0x84, 0xaa, 0x2e, 0xcc, 0x48, 0x8a, 0x98, 0xb2, 0xd0, 0x0b, 0x55, 0xdc, - 0xd3, 0x78, 0xf5, 0x26, 0x90, 0x7d, 0x76, 0x10, 0x65, 0xcb, 0x26, 0xa4, 0xd4, 0x14, 0x5b, 0x20, - 0xaa, 0x3a, 0x09, 0x32, 0xfc, 0x2b, 0x50, 0x4f, 0x1e, 0xd7, 0x4b, 0x8e, 0x94, 0xa6, 0x5e, 0x8a, - 0xdc, 0x89, 0xf3, 0x7b, 0xf6, 0x3d, 0x68, 0x4c, 0x1f, 0xf7, 0x4b, 0x51, 0xf9, 0x9a, 0xfc, 0xf3, - 0x4e, 0xd2, 0x02, 0xc0, 0x76, 0x60, 0x29, 0x4d, 0x9c, 0x43, 0xfa, 0xb8, 0xfe, 0x48, 0x82, 0xcd, - 0x8a, 0x6c, 0xec, 0xdb, 0xd2, 0xaa, 0x53, 0xc0, 0xe9, 0x7f, 0x3b, 0x59, 0xbf, 0x36, 0xd8, 0xeb, - 0xf4, 0x4f, 0xb3, 0xef, 0x9c, 0x03, 0xc4, 0x30, 0xd6, 0x80, 0xea, 0xc1, 0x61, 0x7b, 0xdf, 0xda, - 0xdc, 0x69, 0xed, 0xef, 0xb7, 0x77, 0x1b, 0x37, 0x18, 0x83, 0x3a, 0x5a, 0xa6, 0xb7, 0x22, 0x58, - 0x46, 0xc0, 0xa4, 0x75, 0x4d, 0xc1, 0xb2, 0x6c, 0x09, 0x1a, 0x9d, 0xfd, 0x29, 0x68, 0x8e, 0x35, - 0x61, 0xe9, 0xb0, 0x4d, 0xc6, 0xec, 0x44, 0xb9, 0x79, 0xa1, 0x22, 0xc8, 0xee, 0x0a, 0x15, 0x81, - 0xc2, 0xfc, 0xe4, 0x3a, 0x50, 0x92, 0xf3, 0xef, 0x66, 0x60, 0x79, 0x2a, 0x21, 0x0e, 0xde, 0x20, - 0xb9, 0x39, 0x29, 0x31, 0x57, 0x11, 0xa8, 0x56, 0xd3, 0xfb, 0xb0, 0x10, 0x1d, 0x33, 0x4d, 0xed, - 0x4a, 0x8d, 0x28, 0x41, 0x21, 0x3f, 0x84, 0x45, 0xed, 0xb4, 0x6a, 0x8a, 0x57, 0x30, 0x2d, 0x49, - 0x66, 0x30, 0x56, 0x23, 0x27, 0xf9, 0xa9, 0x56, 0x0f, 0x28, 0x76, 0x50, 0x4f, 0x88, 0x8d, 0x5e, - 0xc9, 0xf6, 0xaa, 0x4f, 0xf6, 0x68, 0x8a, 0x10, 0x92, 0xad, 0xd5, 0x27, 0x5c, 0x55, 0xff, 0x07, - 0x73, 0xc0, 0x3e, 0x9d, 0x70, 0xff, 0x0a, 0x83, 0x33, 0x82, 0x57, 0x79, 0x2b, 0xaa, 0x73, 0x95, - 0xec, 0x6b, 0x05, 0x60, 0xa5, 0x05, 0x40, 0xe5, 0x5f, 0x1d, 0x00, 0x55, 0x78, 0x55, 0x00, 0xd4, - 0x5b, 0x50, 0x73, 0x4e, 0x5d, 0x4f, 0xb0, 0x42, 0x21, 0xf7, 0x06, 0xcd, 0xb9, 0x7b, 0xb9, 0xfb, - 0x55, 0xb3, 0x2a, 0x81, 0x42, 0xea, 0x0d, 0xd8, 0x27, 0x31, 0x12, 0x1f, 0x9c, 0x62, 0xb0, 0x9e, - 0xce, 0x04, 0xdb, 0x83, 0x53, 0x2e, 0x8f, 0x91, 0x50, 0xaf, 0x50, 0x99, 0x05, 0x3c, 0x60, 0x6f, - 0x43, 0x3d, 0xf0, 0x26, 0x42, 0x8d, 0x50, 0xc3, 0x40, 0x66, 0xb1, 0x2a, 0x41, 0x0f, 0x95, 0x0d, - 0x74, 0x71, 0x12, 0x70, 0x6b, 0xe4, 0x04, 0x81, 0x10, 0xcf, 0xfa, 0x9e, 0x1b, 0xfa, 0xde, 0x50, - 0x5a, 0xba, 0x16, 0x26, 0x01, 0xdf, 0xa3, 0x94, 0x4d, 0x4a, 0x60, 0xdf, 0x8a, 0x9b, 0x34, 0xb6, - 0x1d, 0x3f, 0x68, 0x02, 0x36, 0x49, 0xf5, 0x14, 0xa5, 0x75, 0xdb, 0xf1, 0xa3, 0xb6, 0x88, 0x8f, - 0x60, 0x2a, 0x30, 0xab, 0x32, 0x1d, 0x98, 0xf5, 0xc3, 0xf4, 0xc0, 0xac, 0x1a, 0x16, 0xfd, 0x48, - 0x16, 0x3d, 0x3b, 0xc5, 0x5f, 0x29, 0x3e, 0x6b, 0x36, 0xde, 0xac, 0xfe, 0x55, 0xe2, 0xcd, 0xe6, - 0xd3, 0xe2, 0xcd, 0x3e, 0x80, 0x0a, 0x46, 0x02, 0x59, 0x67, 0x8e, 0x90, 0xe1, 0xc8, 0x72, 0xd7, - 0xd0, 0x43, 0x85, 0x76, 0x1c, 0x37, 0x34, 0xc1, 0x57, 0x3f, 0x83, 0xd9, 0xd0, 0xaf, 0x85, 0x5f, - 0x60, 0xe8, 0x97, 0x8c, 0x58, 0x5a, 0x87, 0x92, 0x9a, 0x27, 0xc6, 0x20, 0x7f, 0xe2, 0x7b, 0x23, - 0x65, 0xd1, 0x10, 0xbf, 0x59, 0x1d, 0xb2, 0xa1, 0x27, 0x33, 0x67, 0x43, 0xcf, 0xf8, 0x75, 0xa8, - 0x68, 0xa4, 0xc6, 0xde, 0xa4, 0x53, 0x48, 0xa1, 0x89, 0x49, 0xd9, 0x92, 0x46, 0xb1, 0x2c, 0xa1, - 0x9d, 0x81, 0xe0, 0x37, 0x03, 0xc7, 0xe7, 0x18, 0xa4, 0x69, 0xf9, 0xfc, 0x9c, 0xfb, 0x81, 0xb2, - 0x30, 0x35, 0xa2, 0x04, 0x93, 0xe0, 0xc6, 0x6f, 0xc0, 0x62, 0x62, 0x6e, 0x25, 0x8b, 0x78, 0x1b, - 0xe6, 0x70, 0xdc, 0x94, 0x07, 0x40, 0x32, 0x04, 0x4b, 0xa6, 0x61, 0xf4, 0x3d, 0x19, 0xc7, 0xac, - 0xb1, 0xef, 0x1d, 0x63, 0x25, 0x19, 0xb3, 0x22, 0x61, 0x87, 0xbe, 0x77, 0x6c, 0xfc, 0x59, 0x0e, - 0x72, 0x3b, 0xde, 0x58, 0xf7, 0x48, 0xcb, 0xcc, 0x78, 0xa4, 0x49, 0xf5, 0xd2, 0x8a, 0xd4, 0x47, - 0x29, 0xb3, 0xa3, 0x59, 0x48, 0xa9, 0x90, 0xf7, 0xa1, 0x2e, 0xf8, 0x44, 0xe8, 0x09, 0xfd, 0xfc, - 0xc2, 0xf6, 0x49, 0x20, 0xce, 0xd1, 0xe2, 0xb3, 0x47, 0x61, 0xcf, 0xdb, 0x26, 0x38, 0x5b, 0x82, - 0x5c, 0xa4, 0xbe, 0x60, 0xb2, 0xf8, 0x64, 0x2b, 0x30, 0x87, 0xae, 0xc9, 0x57, 0xd2, 0xc4, 0x2d, - 0xbf, 0xd8, 0x37, 0x60, 0x31, 0x59, 0x2e, 0xb1, 0x22, 0x29, 0x1b, 0xe9, 0x05, 0x23, 0x4f, 0xba, - 0x09, 0x82, 0x8f, 0x10, 0x8e, 0xf4, 0x94, 0x39, 0xe1, 0x1c, 0x93, 0x34, 0xa6, 0x57, 0x4a, 0x30, - 0xbd, 0xbb, 0x50, 0x09, 0x87, 0xe7, 0xd6, 0xd8, 0xbe, 0x1a, 0x7a, 0xf6, 0x40, 0xae, 0x6f, 0x08, - 0x87, 0xe7, 0x87, 0x04, 0x61, 0x0f, 0x01, 0x46, 0xe3, 0xb1, 0x5c, 0x7b, 0x68, 0xea, 0x88, 0x49, - 0x79, 0xef, 0xf0, 0x90, 0x48, 0xce, 0x2c, 0x8f, 0xc6, 0x63, 0xfa, 0xc9, 0xb6, 0xa0, 0x9e, 0x1a, - 0x48, 0x79, 0x47, 0x79, 0xd2, 0x7a, 0xe3, 0xf5, 0x94, 0xc5, 0x59, 0xeb, 0xeb, 0xb0, 0xb5, 0xef, - 0x01, 0xfb, 0x19, 0xc3, 0x19, 0x7b, 0x50, 0x8e, 0xda, 0xa7, 0x47, 0x03, 0xa2, 0x6f, 0x7c, 0x25, - 0x11, 0x0d, 0xd8, 0x1a, 0x0c, 0x7c, 0xc1, 0x17, 0x69, 0xc3, 0x8c, 0x58, 0x3e, 0x68, 0x3b, 0x66, - 0x8b, 0xf8, 0xbe, 0xf1, 0xdf, 0x32, 0x50, 0xa0, 0xd0, 0xc4, 0x77, 0x60, 0x9e, 0xf0, 0x23, 0xef, - 0x3e, 0x69, 0x18, 0xa7, 0x7d, 0xb7, 0x27, 0x1d, 0xfb, 0xc4, 0xb2, 0xd0, 0xc2, 0xaa, 0xb3, 0xd1, - 0xcc, 0x6b, 0xa1, 0xd5, 0x77, 0xa1, 0x1c, 0x55, 0xad, 0x91, 0x4e, 0x49, 0xd5, 0xcc, 0xde, 0x80, - 0xfc, 0x99, 0x37, 0x56, 0xe7, 0x3c, 0x10, 0x8f, 0xa4, 0x89, 0xf0, 0xb8, 0x2d, 0xa2, 0x0e, 0x6a, - 0xbc, 0x3c, 0x9f, 0x88, 0x2a, 0x41, 0x32, 0x98, 0xed, 0xe3, 0x5c, 0x4a, 0x1f, 0x8f, 0x60, 0x5e, - 0xf0, 0x01, 0xcd, 0x41, 0xe5, 0xfa, 0x4d, 0xf3, 0x3d, 0x21, 0xe1, 0xf5, 0x87, 0x93, 0x01, 0xd7, - 0x4f, 0xda, 0xd0, 0x9b, 0x4d, 0xc2, 0x95, 0x64, 0x6d, 0xfc, 0x41, 0x86, 0xf8, 0x8b, 0x28, 0x97, - 0xdd, 0x87, 0xbc, 0xd8, 0xdf, 0xa6, 0xce, 0xdd, 0xa3, 0x20, 0x05, 0x81, 0x67, 0x22, 0x06, 0xde, - 0x45, 0x30, 0x19, 0x25, 0x4b, 0xaf, 0x99, 0x15, 0x77, 0x32, 0x8a, 0x0e, 0xaa, 0xbe, 0xa6, 0xba, - 0x35, 0x75, 0xc8, 0x43, 0xbd, 0x8f, 0x96, 0xe9, 0xba, 0xe6, 0x16, 0x97, 0x4f, 0xec, 0x98, 0x4a, - 0x0a, 0x1c, 0x9c, 0x72, 0xcd, 0x1d, 0xee, 0x8f, 0xb2, 0x50, 0x4b, 0xb4, 0x08, 0xfd, 0x02, 0xc5, - 0x06, 0x40, 0x66, 0x24, 0x39, 0xdf, 0x20, 0x40, 0x52, 0x50, 0xd7, 0xc6, 0x29, 0x9b, 0x18, 0xa7, - 0xc8, 0x15, 0x27, 0xa7, 0xbb, 0xe2, 0x3c, 0x82, 0x72, 0x1c, 0x4e, 0x9f, 0x6c, 0x92, 0xa8, 0x4f, - 0x85, 0x6a, 0xc4, 0x48, 0xb1, 0xf3, 0x4e, 0x41, 0x77, 0xde, 0xf9, 0xae, 0xe6, 0xeb, 0x31, 0x87, - 0xc5, 0x18, 0x69, 0x23, 0xfa, 0x0b, 0xf1, 0xf4, 0x30, 0x3e, 0x81, 0x8a, 0xd6, 0x78, 0xdd, 0xa7, - 0x23, 0x93, 0xf0, 0xe9, 0x88, 0x82, 0xaa, 0xb2, 0x71, 0x50, 0x95, 0xf1, 0x37, 0xb3, 0x50, 0x13, - 0xeb, 0xcb, 0x71, 0x4f, 0x0f, 0xbd, 0xa1, 0xd3, 0x47, 0xb3, 0x52, 0xb4, 0xc2, 0xa4, 0xa0, 0xa5, - 0xd6, 0x99, 0x5c, 0x62, 0x24, 0x67, 0xe9, 0xb1, 0xa3, 0xc4, 0xa4, 0xa3, 0xd8, 0x51, 0x03, 0x6a, - 0x82, 0x31, 0xa2, 0x81, 0x28, 0x0e, 0xf6, 0x37, 0x2b, 0x27, 0x9c, 0x6f, 0xd8, 0x01, 0x71, 0xc8, - 0x6f, 0xc0, 0xa2, 0xc0, 0xc1, 0xb0, 0xb9, 0x91, 0x33, 0x1c, 0x3a, 0x84, 0x49, 0x07, 0x4d, 0x8d, - 0x13, 0xce, 0x4d, 0x3b, 0xe4, 0x7b, 0x22, 0x41, 0xde, 0x0d, 0x50, 0x1a, 0x38, 0x81, 0x7d, 0x1c, - 0x7b, 0x6f, 0x46, 0xdf, 0x68, 0x47, 0xb6, 0x2f, 0x35, 0x3b, 0x32, 0x1d, 0x40, 0x54, 0x46, 0xf6, - 0x65, 0x64, 0x47, 0x9e, 0xa2, 0xa4, 0xe2, 0x34, 0x25, 0x19, 0xff, 0x2e, 0x0b, 0x15, 0x8d, 0x2c, - 0x5f, 0x67, 0x77, 0xbd, 0x33, 0x63, 0x06, 0x2c, 0xeb, 0x16, 0xbf, 0xb7, 0x92, 0x55, 0xa2, 0xa7, - 0x0b, 0xdd, 0x42, 0xa0, 0x11, 0xf0, 0x2d, 0x28, 0x8b, 0x55, 0xf7, 0x01, 0x1e, 0xb8, 0xca, 0x3b, - 0x34, 0x10, 0x70, 0x38, 0x39, 0x56, 0x89, 0x8f, 0x31, 0xb1, 0x10, 0x27, 0x3e, 0x16, 0x89, 0x2f, - 0xf3, 0xa7, 0xfe, 0x08, 0xaa, 0xb2, 0x54, 0x9c, 0x53, 0xec, 0x6e, 0xbc, 0xea, 0x13, 0xf3, 0x6d, - 0x56, 0xa8, 0x3a, 0x9a, 0x7c, 0x99, 0xf1, 0xb1, 0xca, 0x58, 0x7a, 0x55, 0xc6, 0xc7, 0xf4, 0x61, - 0x6c, 0x47, 0x2e, 0xea, 0xe8, 0x65, 0xa5, 0xf8, 0xd8, 0x43, 0x58, 0x54, 0xec, 0x6a, 0xe2, 0xda, - 0xae, 0xeb, 0x4d, 0xdc, 0x3e, 0x57, 0xd1, 0x56, 0x4c, 0x26, 0x1d, 0xc5, 0x29, 0xc6, 0x20, 0x0a, - 0xc7, 0x25, 0x6f, 0xad, 0x07, 0x50, 0x20, 0xb9, 0x9c, 0x84, 0x8f, 0x74, 0xc6, 0x45, 0x28, 0xec, - 0x3e, 0x14, 0x48, 0x3c, 0xcf, 0x5e, 0xcb, 0x6c, 0x08, 0xc1, 0x68, 0x01, 0x13, 0x19, 0xf7, 0x78, - 0xe8, 0x3b, 0xfd, 0x20, 0x0e, 0xe4, 0x2a, 0x08, 0xfd, 0x93, 0xea, 0x8a, 0x4f, 0x6e, 0x63, 0x4c, - 0xd4, 0x51, 0x09, 0x47, 0x6c, 0x4c, 0x8b, 0x89, 0x32, 0xa4, 0xb8, 0x34, 0x84, 0x95, 0x63, 0x1e, - 0x5e, 0x70, 0xee, 0xba, 0x42, 0x18, 0xea, 0x73, 0x37, 0xf4, 0xed, 0xa1, 0x98, 0x24, 0xea, 0xc1, - 0x93, 0x99, 0x52, 0xe3, 0x33, 0x90, 0x8d, 0x38, 0xe3, 0x66, 0x94, 0x8f, 0x78, 0xc7, 0xf2, 0x71, - 0x5a, 0xda, 0xda, 0xaf, 0xc1, 0xda, 0xf5, 0x99, 0x52, 0xc2, 0x35, 0xef, 0x27, 0xb9, 0x4a, 0x64, - 0xf5, 0x1b, 0x7a, 0x76, 0x48, 0xad, 0xd1, 0x39, 0xcb, 0x3e, 0x54, 0xb4, 0x94, 0x78, 0xef, 0xcf, - 0xa0, 0x70, 0x47, 0x1f, 0x62, 0x47, 0x72, 0x3d, 0x7f, 0x84, 0x56, 0xb6, 0x81, 0x15, 0x97, 0x9e, - 0x31, 0xe7, 0x63, 0x38, 0xc6, 0xa7, 0x1b, 0xeb, 0x30, 0x8f, 0x92, 0xbd, 0xb6, 0xd1, 0xbd, 0x4c, - 0x18, 0x34, 0x96, 0x80, 0xed, 0x13, 0xef, 0xd2, 0x9d, 0x37, 0xff, 0x4b, 0x0e, 0x2a, 0x1a, 0x58, - 0xec, 0x46, 0xe8, 0xee, 0x67, 0x0d, 0x1c, 0x7b, 0xc4, 0x95, 0x49, 0xb3, 0x66, 0xd6, 0x10, 0xba, - 0x25, 0x81, 0x62, 0x2f, 0xb6, 0xcf, 0x4f, 0x2d, 0x6f, 0x12, 0x5a, 0x03, 0x7e, 0xea, 0x73, 0xd5, - 0xca, 0xaa, 0x7d, 0x7e, 0x7a, 0x30, 0x09, 0xb7, 0x10, 0x26, 0xb0, 0x04, 0x2f, 0xd1, 0xb0, 0xa4, - 0x87, 0xda, 0xc8, 0xbe, 0x8c, 0xb1, 0xa4, 0x9b, 0x24, 0x51, 0x66, 0x3e, 0x72, 0x93, 0x24, 0x6d, - 0x71, 0x7a, 0x03, 0x2d, 0xcc, 0x6e, 0xa0, 0xdf, 0x82, 0x15, 0xda, 0x40, 0x25, 0x6b, 0xb6, 0xa6, - 0x56, 0xf2, 0x12, 0xa6, 0xca, 0x4e, 0x6a, 0x62, 0x6f, 0x43, 0xf4, 0x40, 0xb1, 0xa5, 0xc0, 0xf9, - 0x11, 0x31, 0xb2, 0x8c, 0x29, 0x7a, 0x26, 0x0b, 0xef, 0x3a, 0x3f, 0xe2, 0x02, 0x13, 0x7d, 0x61, - 0x74, 0x4c, 0x19, 0x2d, 0x31, 0x72, 0xdc, 0x69, 0x4c, 0xfb, 0x32, 0x89, 0x59, 0x96, 0x98, 0xf6, - 0xa5, 0x8e, 0xf9, 0x04, 0x56, 0x47, 0x7c, 0xe0, 0xd8, 0xc9, 0x62, 0xad, 0x58, 0x70, 0x5b, 0xa2, - 0x64, 0x2d, 0x4f, 0x97, 0x14, 0x77, 0x31, 0x1a, 0x3f, 0xf2, 0x46, 0xc7, 0x0e, 0xc9, 0x2c, 0xe4, - 0x9d, 0x93, 0x37, 0xeb, 0xee, 0x64, 0xf4, 0x03, 0x04, 0x8b, 0x2c, 0x81, 0x51, 0x83, 0x4a, 0x37, - 0xf4, 0xc6, 0x6a, 0x9a, 0xeb, 0x50, 0xa5, 0x4f, 0x19, 0xc2, 0x78, 0x0b, 0x6e, 0x22, 0x4b, 0xe8, - 0x79, 0x63, 0x6f, 0xe8, 0x9d, 0x5e, 0x25, 0xce, 0xf1, 0xfe, 0x43, 0x06, 0x16, 0x13, 0xa9, 0x92, - 0xbd, 0x7e, 0x8b, 0xf8, 0x59, 0x14, 0x87, 0x46, 0x6b, 0x70, 0x41, 0x5b, 0x83, 0x84, 0x48, 0xcc, - 0x4c, 0xc5, 0xa6, 0xb5, 0xe2, 0xfb, 0x13, 0x54, 0x46, 0x62, 0x29, 0xcd, 0x59, 0x96, 0x22, 0xf3, - 0xab, 0x9b, 0x15, 0x54, 0x11, 0xbf, 0x24, 0x23, 0x5a, 0x06, 0xb2, 0xcb, 0xb9, 0x64, 0x58, 0x80, - 0x7e, 0xe6, 0xa7, 0x5a, 0x10, 0x1f, 0x04, 0x06, 0xc6, 0x3f, 0xcf, 0x00, 0xc4, 0xad, 0xc3, 0xc0, - 0x84, 0x48, 0x6e, 0xa1, 0xab, 0xc9, 0x34, 0x19, 0xe5, 0x4d, 0xa8, 0x46, 0xfe, 0xc9, 0xb1, 0x24, - 0x54, 0x51, 0x30, 0x21, 0x0e, 0xbd, 0x0b, 0xf3, 0xa7, 0x43, 0xef, 0x18, 0x25, 0x56, 0x29, 0xb7, - 0x90, 0x77, 0x5a, 0x9d, 0xc0, 0x4a, 0x1a, 0x89, 0xe5, 0xa6, 0x7c, 0xaa, 0x0b, 0xb3, 0x2e, 0x05, - 0x19, 0xbf, 0x9d, 0x8d, 0x1c, 0x35, 0xe3, 0x91, 0x78, 0xb9, 0x7a, 0xf7, 0xd3, 0x78, 0xce, 0xbc, - 0xcc, 0x98, 0xf8, 0x09, 0xd4, 0x7d, 0xda, 0x94, 0xd4, 0x8e, 0x95, 0x7f, 0xc9, 0x8e, 0x55, 0xf3, - 0x13, 0x92, 0xce, 0x7b, 0xd0, 0xb0, 0x07, 0xe7, 0xdc, 0x0f, 0x1d, 0x3c, 0xad, 0x47, 0xf9, 0x58, - 0xba, 0x46, 0x6a, 0x70, 0x14, 0x44, 0xdf, 0x85, 0x79, 0x19, 0x56, 0x1b, 0x61, 0xca, 0x8b, 0x7a, - 0x62, 0xb0, 0x40, 0x34, 0xfe, 0xa5, 0xf2, 0x0c, 0x4d, 0xce, 0xee, 0xcb, 0x47, 0x45, 0xef, 0x61, - 0x76, 0xd6, 0x5c, 0x2a, 0x09, 0x49, 0x1a, 0x01, 0x24, 0x3f, 0x22, 0xa0, 0x34, 0x01, 0x24, 0x87, - 0x35, 0xff, 0x3a, 0xc3, 0x6a, 0xfc, 0xa7, 0x0c, 0x14, 0x77, 0xbc, 0xf1, 0x8e, 0x43, 0xae, 0xf9, - 0xb8, 0x4c, 0x22, 0x1b, 0xd5, 0x9c, 0xf8, 0x44, 0x37, 0x9f, 0x97, 0x44, 0x8f, 0xa5, 0x8a, 0x79, - 0xb5, 0xa4, 0x98, 0xf7, 0x5d, 0xb8, 0x85, 0x26, 0x40, 0xdf, 0x1b, 0x7b, 0xbe, 0x58, 0xaa, 0xf6, - 0x90, 0xc4, 0x3d, 0xcf, 0x0d, 0xcf, 0x14, 0xef, 0xbc, 0x79, 0xc2, 0xf9, 0xa1, 0x86, 0xb1, 0x17, - 0x21, 0x60, 0x7c, 0xe6, 0x30, 0x3c, 0xb7, 0x48, 0x43, 0x97, 0xf2, 0x28, 0x71, 0xd4, 0x79, 0x91, - 0xd0, 0x46, 0x38, 0x4a, 0xa4, 0xc6, 0xb7, 0xa1, 0x1c, 0x1d, 0xf6, 0xb0, 0xf7, 0xa1, 0x7c, 0xe6, - 0x8d, 0xe5, 0x89, 0x50, 0x26, 0x11, 0x61, 0x27, 0x7b, 0x6d, 0x96, 0xce, 0xe8, 0x47, 0x60, 0xfc, - 0x59, 0x11, 0x8a, 0x1d, 0xf7, 0xdc, 0x73, 0xfa, 0xe8, 0x5b, 0x3a, 0xe2, 0x23, 0x4f, 0xc5, 0xf6, - 0x8b, 0xdf, 0xe8, 0x89, 0x15, 0x5f, 0xb7, 0x93, 0x93, 0x9e, 0x58, 0xd1, 0x45, 0x3b, 0xcb, 0x30, - 0xe7, 0xeb, 0xf7, 0xe5, 0x14, 0x7c, 0xf4, 0x76, 0x8f, 0xf6, 0xcb, 0x82, 0x76, 0x37, 0x82, 0x28, - 0x8b, 0xee, 0x71, 0xc1, 0x21, 0xa3, 0x58, 0xcb, 0x32, 0x42, 0x70, 0xc0, 0x6e, 0x43, 0x51, 0x06, - 0xb4, 0x51, 0x04, 0x12, 0xb9, 0xa7, 0x4b, 0x10, 0x52, 0x83, 0xcf, 0xc9, 0x84, 0x1b, 0x09, 0xb2, - 0x39, 0xb3, 0xaa, 0x80, 0x5b, 0x82, 0xd6, 0xee, 0x42, 0x85, 0xf0, 0x09, 0xa5, 0x24, 0x5d, 0x32, - 0x11, 0x84, 0x08, 0x29, 0xd7, 0x4e, 0x95, 0x53, 0xaf, 0x9d, 0x42, 0xe7, 0xe1, 0x88, 0xcb, 0x52, - 0x17, 0x81, 0x2e, 0x1b, 0xd2, 0xe0, 0xea, 0xce, 0x35, 0x79, 0xa6, 0x42, 0xa1, 0xc7, 0xea, 0x4c, - 0xe5, 0x2d, 0xa8, 0x9d, 0xd8, 0xc3, 0xe1, 0xb1, 0xdd, 0x7f, 0x41, 0x47, 0x01, 0x55, 0x3a, 0xfd, - 0x54, 0x40, 0x3c, 0x0b, 0xb8, 0x0b, 0x15, 0x6d, 0x96, 0xd1, 0xdf, 0x32, 0x6f, 0x42, 0x3c, 0xbf, - 0xd3, 0x27, 0x7c, 0xf5, 0xd7, 0x38, 0xe1, 0xd3, 0xfc, 0x4e, 0xe7, 0x93, 0x7e, 0xa7, 0xb7, 0x90, - 0x9b, 0x4a, 0x07, 0xc3, 0x06, 0xdd, 0x6c, 0x63, 0x0f, 0x06, 0xe8, 0x60, 0x48, 0xd7, 0x48, 0xe2, - 0xe0, 0x51, 0xfa, 0x02, 0xe9, 0x12, 0x04, 0x23, 0x94, 0x3b, 0x74, 0x4c, 0x3d, 0xb6, 0x9d, 0x01, - 0x86, 0x18, 0xd0, 0xe9, 0x41, 0xd1, 0x1e, 0x85, 0x87, 0xb6, 0x33, 0x60, 0xf7, 0xa0, 0xaa, 0x92, - 0x71, 0x77, 0x5c, 0xa4, 0xf1, 0x97, 0xc9, 0x62, 0x4f, 0x34, 0xa0, 0x16, 0x61, 0x8c, 0xe2, 0xf8, - 0xe1, 0x8a, 0x44, 0x41, 0x3a, 0xf8, 0x00, 0x7d, 0x7a, 0x42, 0x8e, 0x51, 0xc2, 0xf5, 0xc7, 0xb7, - 0xa2, 0x60, 0x40, 0xa4, 0x52, 0xf5, 0x9f, 0x8c, 0x63, 0x84, 0x29, 0x84, 0x3b, 0xb2, 0xd1, 0xad, - 0x24, 0xe4, 0x5f, 0x89, 0x8a, 0x36, 0x3a, 0x42, 0x60, 0xdf, 0xd6, 0xf4, 0xd7, 0x26, 0x22, 0xdf, - 0x9e, 0x2a, 0xff, 0xba, 0x08, 0xab, 0x3b, 0x00, 0x4e, 0x20, 0x76, 0x99, 0x80, 0xbb, 0x03, 0x0c, - 0xf8, 0x2d, 0x99, 0x65, 0x27, 0x78, 0x46, 0x80, 0x9f, 0xaf, 0x62, 0xdb, 0x82, 0xaa, 0xde, 0x4d, - 0x56, 0x82, 0xfc, 0xc1, 0x61, 0x7b, 0xbf, 0x71, 0x83, 0x55, 0xa0, 0xd8, 0x6d, 0xf7, 0x7a, 0xbb, - 0x68, 0xe9, 0xab, 0x42, 0x29, 0x8a, 0x4a, 0xcc, 0x8a, 0xaf, 0xd6, 0xe6, 0x66, 0xfb, 0xb0, 0xd7, - 0xde, 0x6a, 0xe4, 0xbe, 0x9f, 0x2f, 0x65, 0x1b, 0x39, 0xe3, 0xcf, 0x73, 0x50, 0xd1, 0x46, 0xe1, - 0xe5, 0xcc, 0xf8, 0x0e, 0x00, 0x6a, 0x92, 0xb1, 0xff, 0x69, 0xde, 0x2c, 0x0b, 0x08, 0x4d, 0xbe, - 0x6e, 0xa3, 0xc8, 0xd1, 0x95, 0x49, 0xca, 0x46, 0xf1, 0x16, 0xd4, 0xe8, 0xf6, 0x21, 0xdd, 0x5e, - 0x5b, 0x30, 0xab, 0x04, 0x94, 0xac, 0x1a, 0xc3, 0x95, 0x11, 0x09, 0x63, 0xe5, 0xe4, 0x5d, 0x24, - 0x04, 0xc2, 0x68, 0x39, 0x0c, 0x75, 0x0c, 0xbc, 0xe1, 0x39, 0x27, 0x0c, 0x92, 0x08, 0x2b, 0x12, - 0xd6, 0x93, 0x81, 0xd7, 0x92, 0x1f, 0x6a, 0xf1, 0xb2, 0x05, 0xb3, 0x4a, 0x40, 0x59, 0xd1, 0x37, - 0x14, 0x01, 0x95, 0x90, 0x80, 0x56, 0x67, 0xa9, 0x21, 0x41, 0x3c, 0xbb, 0x33, 0xc7, 0x88, 0x65, - 0x24, 0x8c, 0xaf, 0xcd, 0xe6, 0x7b, 0xf5, 0x71, 0x22, 0x7b, 0x1f, 0xd8, 0x68, 0x3c, 0xb6, 0x52, - 0x0e, 0xf8, 0xf2, 0xe6, 0xfc, 0x68, 0x3c, 0xee, 0x69, 0xe7, 0x5f, 0x3f, 0x87, 0xb3, 0xc7, 0x2f, - 0x80, 0xb5, 0xc4, 0x02, 0xc6, 0x26, 0x46, 0xaa, 0x58, 0xcc, 0x96, 0x33, 0x3a, 0x5b, 0x4e, 0xe1, - 0x7e, 0xd9, 0x54, 0xee, 0xf7, 0x32, 0x3e, 0x61, 0x6c, 0x43, 0xe5, 0x50, 0xbb, 0xdb, 0xec, 0x9e, - 0xd8, 0x21, 0xd4, 0xad, 0x66, 0xb4, 0x77, 0xd0, 0x99, 0xa2, 0x2f, 0x2f, 0x33, 0xd3, 0x5a, 0x93, - 0xd5, 0x5a, 0x63, 0xfc, 0xb3, 0x0c, 0xdd, 0x1b, 0x13, 0x35, 0x3e, 0xbe, 0x4e, 0x4d, 0x99, 0xdf, - 0xe2, 0xb0, 0xf6, 0x8a, 0x32, 0xbb, 0xc9, 0x88, 0x74, 0x6c, 0x9a, 0xe5, 0x9d, 0x9c, 0x04, 0x5c, - 0xf9, 0x78, 0x54, 0x10, 0x76, 0x80, 0x20, 0x25, 0x7c, 0x0b, 0x09, 0xdf, 0xa1, 0xf2, 0x03, 0xe9, - 0xd8, 0x21, 0x84, 0xef, 0x3d, 0xfb, 0x52, 0xd6, 0x1a, 0x08, 0x11, 0x44, 0xda, 0x07, 0x54, 0xe4, - 0x6b, 0xf4, 0x6d, 0xfc, 0x63, 0x19, 0x79, 0x3f, 0x3d, 0xbe, 0x0f, 0xa0, 0x14, 0x95, 0x9a, 0xdc, - 0x61, 0x15, 0x66, 0x94, 0x2e, 0xf6, 0x71, 0x3c, 0x0c, 0x49, 0xb4, 0x98, 0x16, 0x17, 0xda, 0x78, - 0x3a, 0x5a, 0xab, 0xbf, 0x0e, 0xec, 0xc4, 0xf1, 0xa7, 0x91, 0x69, 0xb1, 0x35, 0x30, 0x45, 0xc3, - 0x36, 0x8e, 0x60, 0x51, 0x71, 0x09, 0x4d, 0x23, 0x48, 0x4e, 0x5e, 0xe6, 0x15, 0x4c, 0x3e, 0x3b, - 0xc3, 0xe4, 0x8d, 0x9f, 0xe4, 0xa1, 0xa8, 0xee, 0x09, 0x4c, 0xbb, 0xdb, 0xae, 0x9c, 0xbc, 0xdb, - 0xae, 0x99, 0xb8, 0x07, 0x09, 0xa7, 0x5e, 0xee, 0xf7, 0xef, 0x4e, 0x6f, 0xd9, 0x9a, 0xad, 0x22, - 0xb1, 0x6d, 0xaf, 0x40, 0x7e, 0x6c, 0x87, 0x67, 0x78, 0x2e, 0x49, 0xc4, 0x83, 0xdf, 0xca, 0x86, - 0x51, 0x48, 0xda, 0x30, 0xd2, 0xee, 0x01, 0x24, 0x91, 0x74, 0xe6, 0x1e, 0xc0, 0x5b, 0x40, 0xf2, - 0x85, 0xe6, 0xe2, 0x56, 0x42, 0x80, 0xd8, 0x8b, 0x92, 0xe2, 0x48, 0x69, 0x5a, 0x1c, 0x79, 0x6d, - 0x51, 0xe1, 0x5b, 0x30, 0x47, 0x77, 0x68, 0xc8, 0x08, 0x5f, 0xb5, 0xa1, 0xc8, 0x31, 0x54, 0xff, - 0x29, 0xee, 0xc1, 0x94, 0xb8, 0xfa, 0xa5, 0x5a, 0x95, 0xc4, 0xa5, 0x5a, 0xba, 0x6d, 0xa5, 0x9a, - 0xb4, 0xad, 0xdc, 0x87, 0x46, 0x34, 0xa0, 0x78, 0x52, 0xe9, 0x06, 0x32, 0x7e, 0xb0, 0xae, 0xe0, - 0x82, 0x4b, 0xee, 0x07, 0xf1, 0x86, 0x58, 0x4f, 0x6c, 0x88, 0x82, 0x87, 0xb5, 0xc2, 0x90, 0x8f, - 0xc6, 0xa1, 0xdc, 0x10, 0x31, 0xc2, 0x48, 0x6f, 0xa0, 0xd8, 0x61, 0x64, 0xfc, 0x2e, 0xb9, 0x96, - 0x74, 0xf6, 0xad, 0xed, 0xdd, 0xce, 0xd3, 0x9d, 0x5e, 0x23, 0x23, 0x3e, 0xbb, 0x47, 0x9b, 0x9b, - 0xed, 0xf6, 0x16, 0xee, 0x38, 0x00, 0x73, 0xdb, 0xad, 0x8e, 0xd8, 0x7d, 0x72, 0xc6, 0xef, 0x66, - 0xa1, 0xa2, 0x15, 0xcf, 0x9e, 0x44, 0xa3, 0x42, 0xf7, 0x2e, 0xdd, 0x99, 0x6d, 0xc2, 0xba, 0x62, - 0xc5, 0xda, 0xb0, 0x44, 0xb7, 0x1e, 0x66, 0xaf, 0xbd, 0xf5, 0x90, 0xbd, 0x03, 0xf3, 0x36, 0x95, - 0x10, 0x8d, 0x82, 0x3c, 0x85, 0x97, 0x60, 0x39, 0x08, 0xe8, 0xd8, 0x19, 0xef, 0x27, 0x02, 0x2f, - 0xaf, 0x7c, 0x29, 0xa3, 0x2d, 0x05, 0x07, 0xab, 0x78, 0x62, 0x3b, 0xc3, 0x89, 0xcf, 0xa5, 0xd5, - 0x3c, 0xda, 0x99, 0x09, 0x6a, 0xaa, 0x64, 0xe3, 0x43, 0x80, 0xb8, 0xcd, 0xc9, 0xc1, 0xb9, 0x91, - 0x1c, 0x9c, 0x8c, 0x36, 0x38, 0x59, 0x63, 0x8b, 0xd8, 0x88, 0x1c, 0xe8, 0xe8, 0xd8, 0xed, 0x1b, - 0xa0, 0x0e, 0x02, 0x2d, 0x74, 0xaf, 0x1e, 0x0f, 0x79, 0xa8, 0x6e, 0x09, 0x58, 0x90, 0x29, 0x9d, - 0x28, 0x41, 0xdd, 0xa8, 0x11, 0x97, 0x12, 0x73, 0x23, 0x49, 0x92, 0xd3, 0xdc, 0x48, 0xa2, 0x9a, - 0x51, 0xba, 0xb1, 0x06, 0xcd, 0x2d, 0x2e, 0x4a, 0x6b, 0x0d, 0x87, 0x53, 0xcd, 0x31, 0x6e, 0xc1, - 0xcd, 0x94, 0x34, 0x79, 0x08, 0xf1, 0x29, 0x2c, 0xb7, 0xe8, 0x42, 0x80, 0x9f, 0x57, 0xe4, 0x9f, - 0xd1, 0x84, 0x95, 0xe9, 0x22, 0x65, 0x65, 0xdb, 0xb0, 0xb0, 0xc5, 0x8f, 0x27, 0xa7, 0xbb, 0xfc, - 0x3c, 0xae, 0x88, 0x41, 0x3e, 0x38, 0xf3, 0x2e, 0xe4, 0xf8, 0xe0, 0x6f, 0xf4, 0x32, 0x14, 0x38, - 0x56, 0x30, 0xe6, 0x7d, 0x75, 0x10, 0x8d, 0x90, 0xee, 0x98, 0xf7, 0x8d, 0x27, 0xc0, 0xf4, 0x72, - 0xe4, 0x78, 0x09, 0x2d, 0x61, 0x72, 0x6c, 0x05, 0x57, 0x41, 0xc8, 0x47, 0x2a, 0xe2, 0x0d, 0x82, - 0xc9, 0x71, 0x97, 0x20, 0xc6, 0xbb, 0x50, 0x3d, 0xb4, 0xaf, 0x4c, 0xfe, 0x85, 0x0c, 0x2c, 0x5b, - 0x85, 0xe2, 0xd8, 0xbe, 0x12, 0x6c, 0x20, 0xb2, 0x49, 0x61, 0xb2, 0xf1, 0x87, 0x79, 0x98, 0x23, - 0x4c, 0x76, 0x8f, 0x6e, 0xde, 0x75, 0x5c, 0x5c, 0x86, 0x8a, 0x51, 0x6a, 0xa0, 0x19, 0x5e, 0x9a, - 0x9d, 0xe5, 0xa5, 0xf2, 0x00, 0x4d, 0xdd, 0x38, 0xa4, 0xac, 0x07, 0xee, 0x64, 0xa4, 0xae, 0x19, - 0x4a, 0x46, 0xc5, 0xe7, 0xe3, 0x9b, 0x95, 0x29, 0x64, 0x38, 0x69, 0xdf, 0x8d, 0x75, 0x11, 0x6a, - 0x9d, 0xda, 0x22, 0x24, 0xbb, 0xd4, 0x41, 0xa9, 0x0a, 0x4f, 0x51, 0x45, 0x4b, 0x26, 0x15, 0x9e, - 0x19, 0xc5, 0xa6, 0xf4, 0x6a, 0xc5, 0x86, 0x4e, 0xd6, 0x5e, 0xa2, 0xd8, 0xc0, 0x6b, 0x28, 0x36, - 0xaf, 0x61, 0x5b, 0xbd, 0x09, 0x25, 0xdc, 0xf7, 0x35, 0xee, 0x29, 0xf6, 0x7b, 0xc1, 0x3d, 0x3f, - 0xd2, 0x44, 0x7f, 0x72, 0xec, 0xb8, 0x15, 0x2f, 0x13, 0x93, 0x7f, 0xf1, 0x8b, 0xb1, 0x59, 0x3d, - 0x87, 0xa2, 0x84, 0x0a, 0x82, 0x76, 0xed, 0x91, 0xba, 0xb4, 0x0d, 0x7f, 0x8b, 0x61, 0xc3, 0x9b, - 0xa6, 0xbe, 0x98, 0x38, 0x3e, 0x1f, 0xa8, 0xdb, 0x78, 0x1c, 0x5c, 0xa3, 0x02, 0x22, 0x3a, 0x28, - 0xd4, 0x10, 0xd7, 0xbb, 0x70, 0xe5, 0x75, 0x1f, 0x45, 0x27, 0x78, 0x26, 0x3e, 0x0d, 0x06, 0x0d, - 0xbc, 0xb6, 0x71, 0xec, 0xf9, 0x6a, 0x73, 0x32, 0x7e, 0x92, 0x81, 0x86, 0x5c, 0x5d, 0x51, 0x9a, - 0xae, 0x05, 0x14, 0xae, 0xf3, 0x43, 0x78, 0xf9, 0xdd, 0x3a, 0x06, 0xd4, 0xf0, 0xf0, 0x23, 0xda, - 0xa9, 0xe8, 0xf0, 0xa6, 0x22, 0x80, 0xdb, 0x72, 0xb7, 0x7a, 0x03, 0x2a, 0xca, 0x07, 0x7a, 0xe4, - 0x0c, 0xd5, 0x25, 0xea, 0xe4, 0x04, 0xbd, 0xe7, 0x0c, 0xd5, 0x46, 0xe7, 0xdb, 0x32, 0x7a, 0x37, - 0x83, 0x1b, 0x9d, 0x69, 0x87, 0xdc, 0xf8, 0x37, 0x19, 0x58, 0xd0, 0xba, 0x22, 0xd7, 0xed, 0xc7, - 0x50, 0x8d, 0xee, 0x4b, 0xe5, 0x91, 0xe4, 0xb5, 0x9a, 0x64, 0x34, 0x71, 0xb6, 0x4a, 0x3f, 0x82, - 0x04, 0xa2, 0x31, 0x03, 0xfb, 0x8a, 0x1c, 0x75, 0x27, 0x23, 0xa5, 0xdc, 0x0c, 0xec, 0xab, 0x6d, - 0xce, 0xbb, 0x93, 0x91, 0x50, 0x5d, 0x2f, 0x38, 0x7f, 0x11, 0x21, 0x90, 0xcc, 0x05, 0x02, 0x26, - 0x31, 0x0c, 0xa8, 0x8d, 0x3c, 0x37, 0x3c, 0x8b, 0x50, 0xa4, 0xd4, 0x89, 0x40, 0xc2, 0x31, 0xfe, - 0x34, 0x0b, 0x8b, 0x74, 0xc4, 0x26, 0x8f, 0x36, 0x25, 0xeb, 0x6a, 0xc2, 0x1c, 0x9d, 0x36, 0x12, - 0xf3, 0xda, 0xb9, 0x61, 0xca, 0x6f, 0xf6, 0xad, 0xd7, 0x3c, 0x16, 0x54, 0x01, 0xc2, 0xd7, 0x0c, - 0x7f, 0x6e, 0x76, 0xf8, 0xaf, 0x1f, 0xde, 0x34, 0x43, 0x67, 0x21, 0xcd, 0xd0, 0xf9, 0x3a, 0xe6, - 0xc5, 0x99, 0x50, 0xd6, 0xa2, 0xc4, 0xd1, 0x42, 0x59, 0x9f, 0xc0, 0x6a, 0x02, 0x07, 0xb9, 0xb5, - 0x73, 0xe2, 0x70, 0x75, 0x9b, 0xca, 0x92, 0x86, 0xdd, 0x55, 0x69, 0x1b, 0x45, 0x28, 0x04, 0x7d, - 0x6f, 0xcc, 0x8d, 0x15, 0x58, 0x4a, 0x8e, 0xaa, 0xdc, 0x26, 0x7e, 0x2f, 0x03, 0x4d, 0xe9, 0x96, - 0xe2, 0xb8, 0xa7, 0x3b, 0x4e, 0x10, 0x7a, 0x7e, 0x74, 0xaf, 0xe8, 0x1d, 0x80, 0x20, 0xb4, 0x7d, - 0xa9, 0x6d, 0xca, 0xfb, 0x43, 0x10, 0x82, 0x9a, 0xe4, 0x4d, 0x28, 0x71, 0x77, 0x40, 0x89, 0x44, - 0x0d, 0x45, 0xee, 0x0e, 0x94, 0x1e, 0x3a, 0x23, 0x7f, 0xd7, 0x92, 0xea, 0x85, 0x0c, 0xe7, 0x17, - 0xa3, 0xc3, 0xcf, 0x71, 0xe3, 0xcd, 0x47, 0xe1, 0xfc, 0x7b, 0xf6, 0x25, 0x3a, 0x79, 0x06, 0xc6, - 0x3f, 0xc8, 0xc2, 0x7c, 0xdc, 0x3e, 0xba, 0x0b, 0xe4, 0xe5, 0xb7, 0x9a, 0xdc, 0x93, 0xe4, 0xe0, - 0x08, 0xf9, 0x5d, 0x3b, 0x78, 0x2c, 0xd1, 0xe2, 0xec, 0xb8, 0xcc, 0x80, 0x8a, 0xc2, 0xf0, 0x26, - 0xa1, 0x76, 0xbd, 0x5f, 0x99, 0x50, 0x0e, 0x26, 0xa1, 0x50, 0xb8, 0x84, 0xe6, 0xe9, 0xb8, 0x52, - 0xe5, 0x29, 0xd8, 0xa3, 0xb0, 0x83, 0xaf, 0x06, 0x08, 0xb0, 0xc8, 0x46, 0x13, 0x29, 0xb0, 0x04, - 0x7e, 0x83, 0xe4, 0x6c, 0x9a, 0x39, 0x94, 0xb1, 0x75, 0x21, 0x94, 0x2e, 0x50, 0x8e, 0x84, 0xd0, - 0x37, 0xa0, 0x42, 0x85, 0xc7, 0x91, 0xcb, 0x79, 0xb3, 0x8c, 0x35, 0x60, 0xba, 0x3c, 0x04, 0xf2, - 0x26, 0x09, 0xd5, 0x17, 0xa8, 0x2a, 0xf4, 0xfa, 0xf8, 0xdb, 0x19, 0xb8, 0x99, 0x32, 0x6d, 0x72, - 0x95, 0x6f, 0xc2, 0xc2, 0x49, 0x94, 0xa8, 0x46, 0x97, 0x96, 0xfa, 0x8a, 0x62, 0xab, 0xc9, 0x31, - 0x35, 0x1b, 0x27, 0x49, 0x40, 0xac, 0x74, 0xd1, 0x0c, 0x26, 0xe2, 0xe2, 0x51, 0xe9, 0xa2, 0x69, - 0x24, 0x7d, 0xe7, 0x10, 0xd6, 0xda, 0x97, 0x82, 0x63, 0x6c, 0xea, 0xcf, 0x5e, 0x28, 0x32, 0x4a, - 0x1e, 0x30, 0x67, 0x5e, 0xeb, 0x80, 0x79, 0x40, 0x81, 0xb4, 0x51, 0x59, 0x3f, 0x4d, 0x21, 0xb8, - 0x81, 0x8a, 0x3c, 0xf4, 0x6c, 0x87, 0x0a, 0x90, 0xef, 0x47, 0xcf, 0x75, 0x18, 0x01, 0xcc, 0xef, - 0x4d, 0x86, 0xa1, 0x13, 0xbf, 0xe0, 0xc1, 0xbe, 0x25, 0xf3, 0x60, 0x3d, 0x6a, 0xd4, 0x52, 0x2b, - 0x82, 0xa8, 0x22, 0x1c, 0xac, 0x91, 0x28, 0xc8, 0x9a, 0xad, 0x6f, 0x7e, 0x94, 0xac, 0xc1, 0xb8, - 0x09, 0xab, 0xf1, 0x17, 0x0d, 0x9b, 0xda, 0x6a, 0xfe, 0x69, 0x86, 0x3c, 0xca, 0x93, 0xaf, 0x89, - 0xb0, 0x36, 0x2c, 0x06, 0x8e, 0x7b, 0x3a, 0xe4, 0x7a, 0xf1, 0x81, 0x1c, 0x84, 0xe5, 0x64, 0xdb, - 0xe4, 0x8b, 0x23, 0xe6, 0x02, 0xe5, 0x88, 0x4b, 0x0b, 0xd8, 0xc6, 0x75, 0x8d, 0x8c, 0xc9, 0x62, - 0x6a, 0x34, 0x66, 0x1b, 0xdf, 0x81, 0x7a, 0xb2, 0x22, 0xf6, 0x91, 0x8c, 0x3f, 0x8f, 0x5b, 0x95, - 0x9b, 0x0a, 0xce, 0x8d, 0x09, 0xa2, 0x12, 0x8f, 0x7d, 0x60, 0xfc, 0xdd, 0x0c, 0x34, 0x4d, 0x2e, - 0x28, 0x57, 0x6b, 0xa5, 0xa2, 0x99, 0x8f, 0x67, 0x4a, 0xbd, 0xbe, 0xaf, 0x2a, 0xac, 0x5d, 0xb5, - 0xe8, 0xeb, 0xd7, 0x4e, 0xc6, 0xce, 0x8d, 0x99, 0x1e, 0x6d, 0x94, 0x60, 0x8e, 0x50, 0x8c, 0x55, - 0x58, 0x96, 0xed, 0x51, 0x6d, 0x89, 0xad, 0x87, 0x89, 0x1a, 0x13, 0xd6, 0xc3, 0x35, 0x68, 0x52, - 0xa0, 0xa9, 0xde, 0x09, 0x99, 0x71, 0x0b, 0xd8, 0x9e, 0xdd, 0xb7, 0x7d, 0xcf, 0x73, 0x0f, 0xb9, - 0x2f, 0xfd, 0x73, 0x51, 0xc2, 0x44, 0xe3, 0x9a, 0x12, 0x85, 0xe9, 0x4b, 0x5d, 0x6a, 0xea, 0xb9, - 0xca, 0x1d, 0x89, 0xbe, 0x0c, 0x13, 0x16, 0x37, 0xec, 0x17, 0x5c, 0x95, 0xa4, 0x86, 0xe8, 0x13, - 0xa8, 0x8c, 0xa3, 0x42, 0xd5, 0xb8, 0xab, 0xfb, 0x31, 0x66, 0xab, 0x35, 0x75, 0x6c, 0xe3, 0x31, - 0x2c, 0x25, 0xcb, 0x94, 0xac, 0x63, 0x0d, 0x4a, 0x23, 0x09, 0x93, 0xad, 0x8b, 0xbe, 0x8d, 0xdf, - 0x29, 0x41, 0x51, 0xea, 0x73, 0x6c, 0x1d, 0xf2, 0x7d, 0xe5, 0x12, 0x16, 0x5f, 0xbb, 0x24, 0x53, - 0xd5, 0xff, 0x4d, 0x74, 0x0c, 0x13, 0x78, 0xec, 0x13, 0xa8, 0x27, 0xad, 0xa2, 0x53, 0x61, 0xec, - 0x49, 0x73, 0x66, 0xad, 0x3f, 0x65, 0xff, 0x2a, 0xc7, 0x9b, 0x23, 0xc9, 0x0c, 0xa5, 0x33, 0x6d, - 0xf7, 0xf4, 0x5c, 0x21, 0x6f, 0x07, 0x67, 0xb6, 0xf5, 0xf8, 0xc9, 0x87, 0x32, 0x8e, 0xbd, 0x82, - 0xc0, 0xee, 0x99, 0xfd, 0xf8, 0xc9, 0x87, 0xd3, 0x92, 0xb4, 0x8c, 0x62, 0xd7, 0x24, 0xe9, 0x25, - 0x28, 0xd0, 0xed, 0x9d, 0xe4, 0xdb, 0x43, 0x1f, 0xec, 0x11, 0x2c, 0x49, 0xb5, 0xd5, 0x92, 0x5e, - 0xd8, 0xc4, 0x05, 0x4b, 0x14, 0xf8, 0x26, 0xd3, 0xba, 0x98, 0x44, 0x67, 0x43, 0x2b, 0x30, 0x77, - 0x16, 0x5f, 0xc5, 0x5a, 0x33, 0xe5, 0x97, 0xf1, 0xa7, 0x05, 0xa8, 0x68, 0x83, 0xc2, 0xaa, 0x50, - 0x32, 0xdb, 0xdd, 0xb6, 0xf9, 0x59, 0x7b, 0xab, 0x71, 0x83, 0xdd, 0x87, 0xb7, 0x3b, 0xfb, 0x9b, - 0x07, 0xa6, 0xd9, 0xde, 0xec, 0x59, 0x07, 0xa6, 0xa5, 0x2e, 0xff, 0x3a, 0x6c, 0x3d, 0xdf, 0x6b, - 0xef, 0xf7, 0xac, 0xad, 0x76, 0xaf, 0xd5, 0xd9, 0xed, 0x36, 0x32, 0xec, 0x36, 0x34, 0x63, 0x4c, - 0x95, 0xdc, 0xda, 0x3b, 0x38, 0xda, 0xef, 0x35, 0xb2, 0xec, 0x2e, 0xdc, 0xda, 0xee, 0xec, 0xb7, - 0x76, 0xad, 0x18, 0x67, 0x73, 0xb7, 0xf7, 0x99, 0xd5, 0xfe, 0x95, 0xc3, 0x8e, 0xf9, 0xbc, 0x91, - 0x4b, 0x43, 0x10, 0xca, 0xb8, 0x2a, 0x21, 0xcf, 0x6e, 0xc2, 0x32, 0x21, 0x50, 0x16, 0xab, 0x77, - 0x70, 0x60, 0x75, 0x0f, 0x0e, 0xf6, 0x1b, 0x05, 0xb6, 0x00, 0xb5, 0xce, 0xfe, 0x67, 0xad, 0xdd, - 0xce, 0x96, 0x65, 0xb6, 0x5b, 0xbb, 0x7b, 0x8d, 0x39, 0xb6, 0x08, 0xf3, 0xd3, 0x78, 0x45, 0x51, - 0x84, 0xc2, 0x3b, 0xd8, 0xef, 0x1c, 0xec, 0x5b, 0x9f, 0xb5, 0xcd, 0x6e, 0xe7, 0x60, 0xbf, 0x51, - 0x62, 0x2b, 0xc0, 0x92, 0x49, 0x3b, 0x7b, 0xad, 0xcd, 0x46, 0x99, 0x2d, 0xc3, 0x42, 0x12, 0xfe, - 0xac, 0xfd, 0xbc, 0x01, 0xac, 0x09, 0x4b, 0xd4, 0x30, 0x6b, 0xa3, 0xbd, 0x7b, 0xf0, 0xb9, 0xb5, - 0xd7, 0xd9, 0xef, 0xec, 0x1d, 0xed, 0x35, 0x2a, 0x78, 0xa7, 0x60, 0xbb, 0x6d, 0x75, 0xf6, 0xbb, - 0x47, 0xdb, 0xdb, 0x9d, 0xcd, 0x4e, 0x7b, 0xbf, 0xd7, 0xa8, 0x52, 0xcd, 0x69, 0x1d, 0xaf, 0x89, - 0x0c, 0x32, 0x54, 0xc3, 0xda, 0xea, 0x74, 0x5b, 0x1b, 0xbb, 0xed, 0xad, 0x46, 0x9d, 0xdd, 0x81, - 0x9b, 0xbd, 0xf6, 0xde, 0xe1, 0x81, 0xd9, 0x32, 0x9f, 0xab, 0x50, 0x0e, 0x6b, 0xbb, 0xd5, 0xd9, - 0x3d, 0x32, 0xdb, 0x8d, 0x79, 0xf6, 0x26, 0xdc, 0x31, 0xdb, 0x9f, 0x1e, 0x75, 0xcc, 0xf6, 0x96, - 0xb5, 0x7f, 0xb0, 0xd5, 0xb6, 0xb6, 0xdb, 0xad, 0xde, 0x91, 0xd9, 0xb6, 0xf6, 0x3a, 0xdd, 0x6e, - 0x67, 0xff, 0x69, 0xa3, 0xc1, 0xde, 0x86, 0x7b, 0x11, 0x4a, 0x54, 0xc0, 0x14, 0xd6, 0x82, 0xe8, - 0x9f, 0x9a, 0xd2, 0xfd, 0xf6, 0xaf, 0xf4, 0xac, 0xc3, 0x76, 0xdb, 0x6c, 0x30, 0xb6, 0x06, 0x2b, - 0x71, 0xf5, 0x54, 0x81, 0xac, 0x7b, 0x51, 0xa4, 0x1d, 0xb6, 0xcd, 0xbd, 0xd6, 0xbe, 0x98, 0xe0, - 0x44, 0xda, 0x92, 0x68, 0x76, 0x9c, 0x36, 0xdd, 0xec, 0x65, 0xc6, 0xa0, 0xae, 0xcd, 0xca, 0x76, - 0xcb, 0x6c, 0xac, 0xb0, 0x79, 0xa8, 0xec, 0x1d, 0x1e, 0x5a, 0xbd, 0xce, 0x5e, 0xfb, 0xe0, 0xa8, - 0xd7, 0x58, 0x65, 0xcb, 0xd0, 0xe8, 0xec, 0xf7, 0xda, 0xa6, 0x98, 0x6b, 0x95, 0xf5, 0x7f, 0x16, - 0xd9, 0x12, 0xcc, 0xab, 0x96, 0x2a, 0xe8, 0x5f, 0x14, 0xd9, 0x2a, 0xb0, 0xa3, 0x7d, 0xb3, 0xdd, - 0xda, 0x12, 0x03, 0x17, 0x25, 0xfc, 0xaf, 0xa2, 0xb4, 0x90, 0xfc, 0x24, 0x17, 0x6d, 0xd6, 0xb1, - 0xcb, 0x41, 0xf2, 0x62, 0xee, 0xaa, 0x76, 0xa1, 0xf6, 0xab, 0x9e, 0xcc, 0xd0, 0x54, 0xab, 0xdc, - 0x8c, 0x6a, 0x35, 0xa3, 0xbb, 0xd7, 0x74, 0xd9, 0xef, 0x2d, 0xa8, 0x8d, 0xe8, 0x92, 0x6e, 0x79, - 0x19, 0x2f, 0x48, 0xff, 0x1b, 0x02, 0xd2, 0x4d, 0xbc, 0x33, 0x6f, 0x46, 0x14, 0x66, 0xdf, 0x8c, - 0x48, 0x93, 0xef, 0xe7, 0xd2, 0xe4, 0xfb, 0x07, 0xb0, 0x40, 0xac, 0xc9, 0x71, 0x9d, 0x91, 0xd2, - 0x9a, 0x49, 0x0a, 0x9c, 0x47, 0x16, 0x45, 0x70, 0xa5, 0x4e, 0x28, 0x95, 0x43, 0xb2, 0x90, 0xa2, - 0xd4, 0x36, 0x12, 0x9a, 0x06, 0x71, 0x8e, 0x48, 0xd3, 0x88, 0x6a, 0xb0, 0x2f, 0xe3, 0x1a, 0x2a, - 0x5a, 0x0d, 0x04, 0xc7, 0x1a, 0x1e, 0xc0, 0x02, 0xbf, 0x0c, 0x7d, 0xdb, 0xf2, 0xc6, 0xf6, 0x17, - 0x13, 0x34, 0xe1, 0xda, 0xa8, 0xc3, 0x57, 0xcd, 0x79, 0x4c, 0x38, 0x40, 0xf8, 0x96, 0x1d, 0xda, - 0x0f, 0xbe, 0x84, 0x8a, 0x76, 0x81, 0x3b, 0x5b, 0x85, 0xc5, 0xcf, 0x3b, 0xbd, 0xfd, 0x76, 0xb7, - 0x6b, 0x1d, 0x1e, 0x6d, 0x3c, 0x6b, 0x3f, 0xb7, 0x76, 0x5a, 0xdd, 0x9d, 0xc6, 0x0d, 0xb1, 0x68, - 0xf7, 0xdb, 0xdd, 0x5e, 0x7b, 0x2b, 0x01, 0xcf, 0xb0, 0x37, 0x60, 0xed, 0x68, 0xff, 0xa8, 0xdb, - 0xde, 0xb2, 0xd2, 0xf2, 0x65, 0x05, 0x95, 0xca, 0xf4, 0x94, 0xec, 0xb9, 0x07, 0xbf, 0x01, 0xf5, - 0x64, 0x54, 0x33, 0x03, 0x98, 0xdb, 0x6d, 0x3f, 0x6d, 0x6d, 0x3e, 0xa7, 0x5b, 0x47, 0xbb, 0xbd, - 0x56, 0xaf, 0xb3, 0x69, 0xc9, 0x5b, 0x46, 0x05, 0x47, 0xc8, 0xb0, 0x0a, 0x14, 0x5b, 0xfb, 0x9b, - 0x3b, 0x07, 0x66, 0xb7, 0x91, 0x65, 0xb7, 0x61, 0x55, 0xd1, 0xea, 0xe6, 0xc1, 0xde, 0x5e, 0xa7, - 0x87, 0xcc, 0xb0, 0xf7, 0xfc, 0x50, 0x90, 0xe6, 0x03, 0x1b, 0xca, 0xf1, 0x35, 0xa9, 0xc8, 0x60, - 0x3a, 0xbd, 0x4e, 0xab, 0x17, 0x73, 0xd7, 0xc6, 0x0d, 0xc1, 0xbf, 0x62, 0x30, 0xde, 0x72, 0xda, - 0xc8, 0x50, 0xe0, 0x97, 0x02, 0x52, 0xed, 0x8d, 0xac, 0x58, 0x54, 0x31, 0x74, 0xe3, 0xa0, 0x27, - 0xba, 0xf0, 0x1d, 0xa8, 0x27, 0xdd, 0xfb, 0x92, 0x07, 0xbf, 0x6b, 0xb0, 0xb2, 0xd1, 0xee, 0x7d, - 0xde, 0x6e, 0xef, 0xe3, 0xe8, 0x6c, 0xb6, 0xf7, 0x7b, 0x66, 0x6b, 0xb7, 0xd3, 0x7b, 0xde, 0xc8, - 0x3c, 0xf8, 0x04, 0x1a, 0xd3, 0xb6, 0xb4, 0x84, 0xf1, 0xf1, 0x65, 0x56, 0xca, 0x07, 0xff, 0x22, - 0x07, 0x10, 0xc7, 0x98, 0x08, 0x36, 0xb9, 0xd5, 0xea, 0xb5, 0x76, 0x0f, 0xc4, 0x14, 0x98, 0x07, - 0x3d, 0xc1, 0xfd, 0xcc, 0xf6, 0xa7, 0x8d, 0x1b, 0xa9, 0x29, 0x07, 0x87, 0xbd, 0x46, 0x46, 0xcc, - 0x36, 0x75, 0x67, 0xd7, 0x32, 0x0f, 0x8e, 0x3a, 0xfb, 0x4f, 0xe9, 0x16, 0x49, 0xdc, 0x21, 0x8e, - 0x0e, 0xb7, 0xcd, 0x83, 0xfd, 0x9e, 0xd5, 0xdd, 0x39, 0xea, 0x6d, 0xe1, 0x1d, 0x94, 0x9b, 0x66, - 0xe7, 0x90, 0xca, 0xcc, 0xbf, 0x0c, 0x41, 0x14, 0x5d, 0x10, 0xf4, 0xf2, 0xf4, 0xa0, 0xdb, 0xed, - 0x1c, 0x5a, 0x9f, 0x1e, 0xb5, 0xcd, 0x4e, 0xbb, 0x8b, 0x19, 0xe7, 0x52, 0xe0, 0x02, 0xbf, 0x28, - 0xf6, 0x95, 0xde, 0xee, 0x67, 0x92, 0xf1, 0x0b, 0xd4, 0x52, 0x12, 0x24, 0xb0, 0xca, 0x62, 0x30, - 0x05, 0xe7, 0x4c, 0x29, 0x19, 0xae, 0x49, 0x13, 0xf9, 0x2a, 0x62, 0x4f, 0x98, 0x21, 0x24, 0xcc, - 0x56, 0x4d, 0x4f, 0x12, 0xb9, 0x70, 0xbb, 0x88, 0x36, 0xd7, 0xad, 0x2d, 0x13, 0x33, 0xd4, 0x67, - 0xa0, 0x02, 0x77, 0x5e, 0x4c, 0x94, 0x60, 0xad, 0x02, 0xa5, 0xa1, 0x3e, 0x44, 0xca, 0xc2, 0xe3, - 0xdf, 0xce, 0x41, 0x9d, 0xe2, 0xfd, 0xe8, 0xed, 0x3f, 0xee, 0xb3, 0x3d, 0x28, 0xca, 0x47, 0x24, - 0xd9, 0x72, 0x74, 0xc1, 0x9f, 0xfe, 0x6c, 0xe5, 0xda, 0xca, 0x34, 0x58, 0x8a, 0x92, 0x8b, 0x7f, - 0xed, 0x4f, 0xfe, 0xc7, 0xdf, 0xcf, 0xd6, 0x58, 0xe5, 0xe1, 0xf9, 0x07, 0x0f, 0x4f, 0xb9, 0x1b, - 0x88, 0x32, 0x7e, 0x0d, 0x20, 0x7e, 0x1a, 0x91, 0x35, 0xb5, 0x3b, 0x7f, 0x13, 0x8f, 0x22, 0xae, - 0xdd, 0x4c, 0x49, 0x91, 0xe5, 0xde, 0xc4, 0x72, 0x17, 0x8d, 0xba, 0x28, 0xd7, 0x71, 0x9d, 0x90, - 0x9e, 0x49, 0xfc, 0x38, 0xf3, 0x80, 0x0d, 0xa0, 0xaa, 0x3f, 0x5a, 0xc8, 0x94, 0x94, 0x97, 0xf2, - 0xec, 0xe2, 0xda, 0xad, 0xd4, 0x34, 0x25, 0x3f, 0x63, 0x1d, 0xcb, 0x46, 0x43, 0xd4, 0x31, 0x41, - 0x8c, 0xb8, 0x96, 0x21, 0x69, 0x14, 0xf1, 0xdb, 0x84, 0xec, 0xb6, 0x26, 0x13, 0xce, 0xbc, 0x8c, - 0xb8, 0x76, 0xe7, 0x9a, 0x54, 0x59, 0xd7, 0x1d, 0xac, 0x6b, 0xd5, 0x60, 0xa2, 0xae, 0x3e, 0xe2, - 0xa8, 0x97, 0x11, 0x3f, 0xce, 0x3c, 0x78, 0xfc, 0x1f, 0xdf, 0x83, 0x72, 0xe4, 0xff, 0xcb, 0x7e, - 0x13, 0x6a, 0x89, 0x80, 0x4c, 0xa6, 0xba, 0x91, 0x16, 0xbf, 0xb9, 0x76, 0x3b, 0x3d, 0x51, 0x56, - 0xfc, 0x06, 0x56, 0xdc, 0x64, 0x2b, 0xa2, 0x62, 0x19, 0xf0, 0xf8, 0x10, 0x03, 0xa8, 0xe9, 0xba, - 0xc4, 0x17, 0x9a, 0xe6, 0x44, 0x95, 0xdd, 0x9e, 0xd6, 0x66, 0x12, 0xb5, 0xdd, 0xb9, 0x26, 0x55, - 0x56, 0x77, 0x1b, 0xab, 0x5b, 0x61, 0x4b, 0x7a, 0x75, 0xca, 0x6d, 0x94, 0x71, 0xbc, 0xa2, 0x54, - 0x7f, 0xba, 0x8f, 0xdd, 0x89, 0x2f, 0x94, 0x4c, 0x79, 0xd2, 0x2f, 0x22, 0x91, 0xd9, 0x77, 0xfd, - 0x8c, 0x26, 0x56, 0xc5, 0x18, 0x4e, 0x9f, 0xfe, 0x72, 0x1f, 0x3b, 0x86, 0x8a, 0xf6, 0xda, 0x0d, - 0xbb, 0x79, 0xed, 0xcb, 0x3c, 0x6b, 0x6b, 0x69, 0x49, 0x69, 0x5d, 0xd1, 0xcb, 0x7f, 0x78, 0xc2, - 0x39, 0xfb, 0x55, 0x28, 0x47, 0x6f, 0xa8, 0xb0, 0x55, 0xed, 0x4d, 0x1b, 0xfd, 0xcd, 0x97, 0xb5, - 0xe6, 0x6c, 0x42, 0x1a, 0xf1, 0xe9, 0xa5, 0x0b, 0xe2, 0xfb, 0x1c, 0x2a, 0xda, 0x3b, 0x29, 0x51, - 0x07, 0x66, 0xdf, 0x62, 0x89, 0x3a, 0x90, 0xf2, 0xac, 0x8a, 0xb1, 0x80, 0x55, 0x54, 0x58, 0x19, - 0xe9, 0x3b, 0xbc, 0xf4, 0x02, 0xb6, 0x0b, 0xcb, 0x52, 0x4b, 0x3c, 0xe6, 0x5f, 0x65, 0x1a, 0x52, - 0x5e, 0x4b, 0x7c, 0x94, 0x61, 0x9f, 0x40, 0x49, 0x3d, 0x87, 0xc3, 0x56, 0xd2, 0x9f, 0xf5, 0x59, - 0x5b, 0x9d, 0x81, 0x4b, 0x95, 0xee, 0x39, 0x40, 0xfc, 0x28, 0x4b, 0xc4, 0x24, 0x66, 0x1e, 0x79, - 0x89, 0x28, 0x60, 0xf6, 0x05, 0x17, 0x63, 0x05, 0x3b, 0xd8, 0x60, 0xc8, 0x24, 0x5c, 0x7e, 0xa1, - 0xee, 0x91, 0xfe, 0x21, 0x54, 0xb4, 0x77, 0x59, 0xa2, 0xe1, 0x9b, 0x7d, 0xd3, 0x25, 0x1a, 0xbe, - 0x94, 0x67, 0x5c, 0x8c, 0x35, 0x2c, 0x7d, 0xc9, 0x98, 0x17, 0xa5, 0x0b, 0x31, 0x51, 0x8a, 0x6b, - 0x62, 0x82, 0xce, 0xa0, 0x96, 0x78, 0x7c, 0x25, 0x5a, 0xa1, 0x69, 0x4f, 0xbb, 0x44, 0x2b, 0x34, - 0xf5, 0xbd, 0x16, 0x45, 0x67, 0xc6, 0x82, 0xa8, 0x87, 0xae, 0x92, 0xd2, 0x6a, 0xfa, 0x01, 0x54, - 0xb4, 0x87, 0x54, 0xa2, 0xbe, 0xcc, 0xbe, 0xd9, 0x12, 0xf5, 0x25, 0xed, 0xdd, 0x95, 0x25, 0xac, - 0xa3, 0x6e, 0x20, 0x29, 0xe0, 0x4d, 0xb8, 0xa2, 0xec, 0xdf, 0x84, 0x7a, 0xf2, 0x6d, 0x95, 0x68, - 0xed, 0xa7, 0x3e, 0xd2, 0x12, 0xad, 0xfd, 0x6b, 0x1e, 0x64, 0x91, 0x24, 0xfd, 0x60, 0x31, 0xaa, - 0xe4, 0xe1, 0x8f, 0x65, 0x24, 0xd3, 0x97, 0xec, 0x53, 0xc1, 0xe0, 0xe4, 0x45, 0xcc, 0x6c, 0x55, - 0xa3, 0x5a, 0xfd, 0x46, 0xe7, 0x68, 0xbd, 0xcc, 0xdc, 0xd9, 0x9c, 0x24, 0x66, 0x2c, 0x9c, 0x3d, - 0x85, 0xc5, 0x88, 0x98, 0xa3, 0x9b, 0x95, 0x83, 0xa8, 0x0f, 0xa9, 0xf7, 0x37, 0xaf, 0x35, 0xa6, - 0x53, 0x1f, 0x65, 0x68, 0xfb, 0xc3, 0xfb, 0x6c, 0xb5, 0xed, 0x4f, 0xbf, 0x5c, 0x59, 0xdb, 0xfe, - 0x12, 0xd7, 0xde, 0x4e, 0x6f, 0x7f, 0xa1, 0x23, 0xca, 0x70, 0x61, 0x7e, 0xfa, 0x9e, 0xe3, 0x3b, - 0xd7, 0xdd, 0x14, 0x41, 0xc5, 0xbf, 0xf1, 0xf2, 0x8b, 0x24, 0x92, 0xac, 0x48, 0x71, 0xd3, 0x87, - 0xd2, 0x71, 0x86, 0xfd, 0x3a, 0x54, 0xf5, 0xf7, 0x18, 0x98, 0xce, 0x13, 0xa6, 0x6b, 0xba, 0x95, - 0x9a, 0x96, 0xa4, 0x12, 0x56, 0xd5, 0xab, 0x61, 0x9f, 0xc1, 0x4a, 0x34, 0xcc, 0xfa, 0x55, 0x07, - 0x01, 0xbb, 0x9b, 0x72, 0x01, 0x42, 0x62, 0xb0, 0x6f, 0x5e, 0x7b, 0x43, 0xc2, 0xa3, 0x8c, 0xa0, - 0xbe, 0xe4, 0xdd, 0xf3, 0xf1, 0xce, 0x93, 0x76, 0xe5, 0x7e, 0xbc, 0xf3, 0xa4, 0x5e, 0x58, 0xaf, - 0xa8, 0x8f, 0x2d, 0x26, 0xc6, 0x88, 0x5c, 0x8a, 0xd9, 0x0f, 0x60, 0x5e, 0xbb, 0xc7, 0xa1, 0x7b, - 0xe5, 0xf6, 0xa3, 0x95, 0x34, 0x7b, 0x83, 0xe9, 0x5a, 0xda, 0xb9, 0xaa, 0xb1, 0x8a, 0xe5, 0x2f, - 0x18, 0x89, 0xc1, 0x11, 0xab, 0x68, 0x13, 0x2a, 0xfa, 0x1d, 0x11, 0x2f, 0x29, 0x77, 0x55, 0x4b, - 0xd2, 0x2f, 0xcb, 0x7c, 0x94, 0x61, 0xbb, 0xd0, 0x98, 0xbe, 0xbf, 0x2d, 0xe2, 0x29, 0x69, 0x77, - 0xde, 0xad, 0x4d, 0x25, 0x26, 0x6e, 0x7d, 0x63, 0x87, 0x14, 0x94, 0x12, 0x3d, 0x2d, 0xe8, 0xf9, - 0xd3, 0xbb, 0x7a, 0xf2, 0xc9, 0xc1, 0xa8, 0xb4, 0xb4, 0xc7, 0x26, 0xef, 0x67, 0x1e, 0x65, 0xd8, - 0xef, 0x66, 0xa0, 0x9a, 0xb8, 0xd1, 0x28, 0xe1, 0xf6, 0x3f, 0xd5, 0xcf, 0xa6, 0x9e, 0xa6, 0x77, - 0xd4, 0x30, 0x71, 0x10, 0x77, 0x1f, 0x7c, 0x3f, 0x31, 0x49, 0x3f, 0x4e, 0x98, 0x25, 0xd7, 0xa7, - 0xdf, 0x1e, 0xfc, 0x72, 0x1a, 0x41, 0xbf, 0x13, 0xf7, 0xcb, 0x47, 0x19, 0xf6, 0xaf, 0x32, 0x50, - 0x4f, 0xfa, 0x1b, 0x44, 0xdd, 0x4d, 0xf5, 0x6c, 0x88, 0x48, 0xe9, 0x1a, 0x27, 0x85, 0x1f, 0x60, - 0x2b, 0x7b, 0x0f, 0xcc, 0x44, 0x2b, 0xe5, 0xab, 0x09, 0x3f, 0x5b, 0x6b, 0xd9, 0x2f, 0xd3, 0x53, - 0xbf, 0xca, 0x0d, 0x8b, 0xcd, 0x3e, 0x0d, 0x1b, 0x91, 0x9f, 0xfe, 0x90, 0xaa, 0x91, 0xfb, 0xad, - 0x6c, 0x06, 0x67, 0xe2, 0x87, 0xf4, 0xd0, 0x9e, 0x72, 0xed, 0x11, 0xa4, 0xfc, 0xda, 0x85, 0xbc, - 0x8d, 0x1d, 0x7b, 0xc3, 0xb8, 0x99, 0xe8, 0xd8, 0xb4, 0xf4, 0xd1, 0xa2, 0x26, 0xca, 0xc7, 0x50, - 0xe3, 0xed, 0x73, 0xe6, 0x81, 0xd4, 0xd4, 0x4a, 0xb0, 0x91, 0x23, 0x6a, 0xa4, 0x44, 0x4f, 0xac, - 0xb7, 0xd7, 0x2c, 0xc6, 0x78, 0x80, 0x6d, 0x7d, 0xdb, 0xb8, 0x7b, 0x6d, 0x5b, 0x1f, 0xa2, 0x03, - 0x81, 0x68, 0xf1, 0x21, 0x40, 0xec, 0x2b, 0xc9, 0xa6, 0x3c, 0xf6, 0x22, 0x2e, 0x34, 0xeb, 0x4e, - 0x99, 0x5c, 0xd4, 0xca, 0xb1, 0x4f, 0x94, 0xf8, 0xab, 0xc4, 0x53, 0x23, 0x5f, 0x42, 0x5d, 0x04, - 0x4b, 0xba, 0x35, 0x26, 0x44, 0xb0, 0xe9, 0xf2, 0x13, 0x1c, 0x35, 0x72, 0x1c, 0x3c, 0x82, 0xda, - 0xae, 0xe7, 0xbd, 0x98, 0x8c, 0x23, 0xff, 0xfc, 0xa4, 0x57, 0xcf, 0x8e, 0x1d, 0x9c, 0xad, 0x4d, - 0xf5, 0xc2, 0xb8, 0x87, 0x45, 0xad, 0xb1, 0xa6, 0x56, 0xd4, 0xc3, 0x1f, 0xc7, 0x0e, 0x9a, 0x5f, - 0x32, 0x1b, 0x16, 0x22, 0x46, 0x1d, 0x3b, 0x41, 0x26, 0x8b, 0x49, 0xb0, 0xe7, 0xe9, 0x2a, 0x12, - 0xba, 0x82, 0x6a, 0xed, 0xc3, 0x40, 0x95, 0xf9, 0x28, 0xc3, 0x0e, 0xa1, 0xba, 0xc5, 0xfb, 0x78, - 0xc1, 0x03, 0xfa, 0xc6, 0x2c, 0x26, 0xfc, 0x2c, 0xc8, 0xa9, 0x66, 0xad, 0x96, 0x00, 0x26, 0x37, - 0xaf, 0xb1, 0x7d, 0xe5, 0xf3, 0x2f, 0x1e, 0xfe, 0x58, 0x7a, 0xdd, 0x7c, 0xa9, 0x36, 0x2f, 0xe5, - 0x95, 0x94, 0xd8, 0xbc, 0xa6, 0xdc, 0x98, 0x12, 0x9b, 0xd7, 0x8c, 0x1b, 0x53, 0x62, 0xa8, 0x95, - 0x57, 0x14, 0x1b, 0xc2, 0xc2, 0x8c, 0xe7, 0x53, 0xb4, 0x6f, 0x5d, 0xe7, 0x2f, 0xb5, 0x76, 0xef, - 0x7a, 0x84, 0x64, 0x6d, 0x0f, 0x92, 0xb5, 0x75, 0xa1, 0x46, 0xb7, 0xde, 0x1e, 0x73, 0x0a, 0xf5, - 0x9c, 0xba, 0x27, 0x49, 0x8f, 0x23, 0x9d, 0xde, 0x65, 0x30, 0x2d, 0x29, 0xe6, 0x60, 0xb0, 0x1f, - 0x3b, 0xc1, 0xa7, 0x1e, 0xb4, 0xd8, 0xca, 0x88, 0x18, 0x67, 0xe3, 0x3d, 0x23, 0x62, 0x4c, 0x09, - 0xc5, 0x54, 0x3a, 0x28, 0x5b, 0x8e, 0xca, 0x7e, 0xe8, 0x7a, 0x03, 0x3e, 0x92, 0xa5, 0xfe, 0x2a, - 0x54, 0x9e, 0xf2, 0x50, 0x05, 0x33, 0x46, 0x02, 0xfd, 0x54, 0x74, 0xe3, 0x5a, 0x4a, 0x08, 0x6a, - 0x92, 0x36, 0xa9, 0x64, 0x3e, 0x38, 0xe5, 0xc4, 0x09, 0x2d, 0x67, 0xf0, 0x25, 0xfb, 0x15, 0x2c, - 0x3c, 0x0a, 0xdd, 0x5f, 0xd1, 0x9a, 0xa9, 0x17, 0x3e, 0x3f, 0x05, 0x4f, 0x2b, 0x59, 0xb4, 0x59, - 0x13, 0x2c, 0x5d, 0xa8, 0x68, 0x57, 0x7c, 0x44, 0x63, 0x33, 0x7b, 0xa5, 0x4b, 0x34, 0x36, 0x29, - 0x37, 0x82, 0x18, 0xf7, 0xb1, 0x1e, 0x83, 0xdd, 0x8b, 0xeb, 0xa1, 0x5b, 0x40, 0xe2, 0x9a, 0x1e, - 0xfe, 0xd8, 0x1e, 0x85, 0x5f, 0xb2, 0xcf, 0x69, 0x3a, 0xb4, 0x60, 0xcd, 0x58, 0x43, 0x99, 0x8e, - 0xeb, 0x8c, 0x06, 0x4b, 0x4b, 0x4a, 0x6a, 0x2d, 0x54, 0x15, 0x8a, 0x8d, 0x4f, 0x00, 0xba, 0xa1, - 0x37, 0xde, 0xb2, 0xf9, 0xc8, 0x73, 0x63, 0x9e, 0x1e, 0x87, 0x0f, 0xc6, 0x7c, 0x52, 0x8b, 0x21, - 0x64, 0x9f, 0x6b, 0x2a, 0x5d, 0x22, 0xcc, 0x58, 0x11, 0xf1, 0xb5, 0x11, 0x86, 0xd1, 0x80, 0xa4, - 0x44, 0x19, 0x3e, 0xca, 0xb0, 0x16, 0x40, 0xec, 0x62, 0x17, 0x29, 0x68, 0x33, 0xde, 0x7b, 0x11, - 0x7b, 0x4d, 0xf1, 0xc7, 0x3b, 0x84, 0x72, 0xec, 0x9b, 0xb4, 0x1a, 0xdf, 0x58, 0x94, 0xf0, 0x64, - 0x8a, 0xc4, 0x85, 0x19, 0xbf, 0x20, 0xa3, 0x81, 0x43, 0x05, 0xac, 0x24, 0x86, 0xea, 0x84, 0xf3, - 0x80, 0x39, 0xb0, 0x48, 0x0d, 0x8c, 0x64, 0x33, 0x0c, 0x7b, 0x8b, 0x1e, 0x58, 0x99, 0x75, 0xd1, - 0x89, 0xb8, 0x46, 0xaa, 0xa3, 0x49, 0xe2, 0x9c, 0x49, 0x50, 0x2b, 0x85, 0xdc, 0x89, 0x2d, 0x60, - 0x04, 0x0b, 0x33, 0xbe, 0x0c, 0x11, 0xeb, 0xb8, 0xce, 0x39, 0x25, 0x62, 0x1d, 0xd7, 0xba, 0x41, - 0x18, 0xcb, 0x58, 0xe5, 0xbc, 0x01, 0xa8, 0x57, 0x5e, 0x38, 0x61, 0xff, 0x4c, 0x54, 0xf7, 0xfb, - 0x19, 0x58, 0x4c, 0xf1, 0x56, 0x60, 0x6f, 0xaa, 0x23, 0x8a, 0x6b, 0x3d, 0x19, 0xd6, 0x52, 0xad, - 0xda, 0x46, 0x17, 0xeb, 0xd9, 0x63, 0xcf, 0x12, 0x1b, 0x28, 0x19, 0x95, 0xe5, 0xca, 0x7c, 0xa9, - 0x04, 0x93, 0x2a, 0xbe, 0x7c, 0x01, 0xab, 0xd4, 0x90, 0xd6, 0x70, 0x38, 0x65, 0x71, 0x7f, 0x43, - 0x6b, 0x45, 0x8a, 0x17, 0x41, 0x42, 0x19, 0x48, 0x7a, 0x12, 0x5c, 0x23, 0xbb, 0x53, 0x53, 0xd9, - 0x04, 0x1a, 0xd3, 0x96, 0x6c, 0x76, 0x7d, 0x59, 0x6b, 0x77, 0x13, 0xca, 0x76, 0x8a, 0xf5, 0xfb, - 0x6b, 0x58, 0xd9, 0x5d, 0x63, 0x2d, 0x6d, 0x5c, 0x48, 0xff, 0x16, 0xf3, 0xf1, 0x57, 0x23, 0xb3, - 0xfb, 0x54, 0x3f, 0xef, 0x46, 0x57, 0xca, 0xa7, 0x3b, 0x09, 0x44, 0xea, 0x7e, 0xba, 0xd5, 0xfe, - 0x1d, 0xac, 0xfe, 0x9e, 0x71, 0x2b, 0xad, 0x7a, 0x9f, 0xb2, 0x90, 0xe2, 0xbf, 0x3a, 0xbd, 0xae, - 0x55, 0x0b, 0xee, 0xa5, 0xcd, 0xf7, 0xb5, 0x8a, 0xd7, 0xd4, 0x58, 0xdf, 0x40, 0x19, 0xb2, 0xaa, - 0x9b, 0xd9, 0xa3, 0xe5, 0x93, 0x62, 0xcf, 0x8f, 0x96, 0x4f, 0x9a, 0x5d, 0x3e, 0x29, 0x3f, 0x29, - 0x8b, 0xfc, 0xc7, 0x99, 0x07, 0x1b, 0xef, 0xfe, 0xe0, 0x6b, 0xa7, 0x4e, 0x78, 0x36, 0x39, 0x5e, - 0xef, 0x7b, 0xa3, 0x87, 0x43, 0x75, 0xb4, 0x29, 0x63, 0xc3, 0x1f, 0x0e, 0xdd, 0xc1, 0x43, 0x2c, - 0xf6, 0x78, 0x6e, 0xec, 0x7b, 0xa1, 0xf7, 0xcd, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xad, - 0x0f, 0x96, 0x5a, 0x89, 0x00, 0x00, + 0x74, 0x57, 0xf5, 0x56, 0x55, 0xf3, 0x71, 0x87, 0xf5, 0x87, 0x61, 0x1b, 0x82, 0x61, 0x1b, 0x10, + 0x6c, 0x19, 0xb0, 0x6c, 0xc1, 0x0f, 0xc1, 0x30, 0x0c, 0x03, 0x82, 0x80, 0x93, 0x3f, 0x0c, 0xf8, + 0x5f, 0x3f, 0x7e, 0xc0, 0x90, 0xfc, 0x63, 0x08, 0x02, 0x0c, 0xdb, 0xf2, 0x9f, 0x21, 0xc0, 0xdf, + 0x06, 0x8c, 0x8c, 0xc8, 0xac, 0xca, 0xea, 0x2e, 0xce, 0xcc, 0xde, 0x9d, 0xef, 0x87, 0xec, 0x8a, + 0x8c, 0x7c, 0x47, 0x46, 0x46, 0x64, 0x44, 0x64, 0x42, 0xd9, 0x1f, 0xf7, 0xd7, 0xc7, 0xbe, 0x17, + 0x7a, 0xac, 0x30, 0x74, 0xfd, 0x71, 0x7f, 0xed, 0xf6, 0xa9, 0xe7, 0x9d, 0x0e, 0xf9, 0x43, 0x7b, + 0xec, 0x3c, 0xb4, 0x5d, 0xd7, 0x0b, 0xed, 0xd0, 0xf1, 0xdc, 0x80, 0x90, 0x8c, 0x1f, 0x42, 0xfd, + 0x29, 0x77, 0xbb, 0x9c, 0x0f, 0x4c, 0xfe, 0xc5, 0x84, 0x07, 0x21, 0x7b, 0x1f, 0x16, 0x6c, 0xfe, + 0x23, 0xce, 0x07, 0xd6, 0xd8, 0x0e, 0x82, 0xf1, 0x99, 0x6f, 0x07, 0xbc, 0x99, 0xb9, 0x97, 0xb9, + 0x5f, 0x35, 0x1b, 0x94, 0x70, 0x18, 0xc1, 0xd9, 0x9b, 0x50, 0x0d, 0x04, 0x2a, 0x77, 0x43, 0xdf, + 0x1b, 0x5f, 0x35, 0xb3, 0x88, 0x57, 0x11, 0xb0, 0x36, 0x81, 0x8c, 0x21, 0xcc, 0x47, 0x35, 0x04, + 0x63, 0xcf, 0x0d, 0x38, 0x7b, 0x04, 0x4b, 0x7d, 0x67, 0x7c, 0xc6, 0x7d, 0x0b, 0x33, 0x8f, 0x5c, + 0x3e, 0xf2, 0x5c, 0xa7, 0xdf, 0xcc, 0xdc, 0xcb, 0xdd, 0x2f, 0x9b, 0x8c, 0xd2, 0x44, 0x8e, 0x3d, + 0x99, 0xc2, 0xde, 0x85, 0x79, 0xee, 0x12, 0x9c, 0x0f, 0x30, 0x97, 0xac, 0xaa, 0x1e, 0x83, 0x45, + 0x06, 0xe3, 0xb7, 0xb2, 0xb0, 0xd0, 0x71, 0x9d, 0xf0, 0x73, 0x7b, 0x38, 0xe4, 0xa1, 0xea, 0xd3, + 0xbb, 0x30, 0x7f, 0x81, 0x00, 0xec, 0xd3, 0x85, 0xe7, 0x0f, 0x64, 0x8f, 0xea, 0x04, 0x3e, 0x94, + 0xd0, 0x6b, 0x5b, 0x96, 0xbd, 0xb6, 0x65, 0xa9, 0xc3, 0x95, 0xbb, 0x66, 0xb8, 0xde, 0x85, 0x79, + 0x9f, 0xf7, 0xbd, 0x73, 0xee, 0x5f, 0x59, 0x17, 0x8e, 0x3b, 0xf0, 0x2e, 0x9a, 0xf9, 0x7b, 0x99, + 0xfb, 0x05, 0xb3, 0xae, 0xc0, 0x9f, 0x23, 0x94, 0x6d, 0xc0, 0x7c, 0xff, 0xcc, 0x76, 0x5d, 0x3e, + 0xb4, 0x8e, 0xed, 0xfe, 0x8b, 0xc9, 0x38, 0x68, 0x16, 0xee, 0x65, 0xee, 0x57, 0x1e, 0xdf, 0x5c, + 0xc7, 0x59, 0x5d, 0xdf, 0x3c, 0xb3, 0xdd, 0x0d, 0x4c, 0xe9, 0xba, 0xf6, 0x38, 0x38, 0xf3, 0x42, + 0xb3, 0x2e, 0x73, 0x10, 0x38, 0x30, 0x96, 0x80, 0xe9, 0x23, 0x41, 0x63, 0x6f, 0xfc, 0xeb, 0x0c, + 0x2c, 0x1e, 0xb9, 0x43, 0xaf, 0xff, 0xe2, 0xa7, 0x1c, 0xa2, 0x94, 0x3e, 0x64, 0x5f, 0xb7, 0x0f, + 0xb9, 0xaf, 0xda, 0x87, 0x15, 0x58, 0x4a, 0x36, 0x56, 0xf6, 0x82, 0xc3, 0xb2, 0xc8, 0x7d, 0xca, + 0x55, 0xb3, 0x54, 0x37, 0xde, 0x83, 0x46, 0x7f, 0xe2, 0xfb, 0xdc, 0x9d, 0xe9, 0xc7, 0xbc, 0x84, + 0x47, 0x1d, 0x79, 0x13, 0xaa, 0x2e, 0xbf, 0x88, 0xd1, 0x24, 0xed, 0xba, 0xfc, 0x42, 0xa1, 0x18, + 0x4d, 0x58, 0x99, 0xae, 0x46, 0x36, 0xe0, 0x2f, 0x32, 0x90, 0x3f, 0x0a, 0x2f, 0x3d, 0xf6, 0x04, + 0xaa, 0xf6, 0x60, 0xe0, 0xf3, 0x20, 0xb0, 0xc2, 0xab, 0x31, 0xad, 0x94, 0xfa, 0x63, 0x26, 0xbb, + 0xd8, 0xa2, 0xa4, 0xde, 0xd5, 0x98, 0x9b, 0x15, 0x3b, 0xfe, 0x60, 0x4d, 0x28, 0xca, 0x4f, 0xac, + 0xb7, 0x6c, 0xaa, 0x4f, 0x76, 0x07, 0xc0, 0x1e, 0x79, 0x13, 0x37, 0xb4, 0x02, 0x3b, 0xc4, 0x11, + 0xcb, 0x99, 0x65, 0x82, 0x74, 0xed, 0x90, 0xdd, 0x82, 0xf2, 0xf8, 0x85, 0x15, 0xf4, 0x7d, 0x67, + 0x1c, 0x22, 0xf1, 0x94, 0xcd, 0xd2, 0xf8, 0x45, 0x17, 0xbf, 0xd9, 0xfb, 0x50, 0xf2, 0x26, 0xe1, + 0xd8, 0x73, 0xdc, 0x50, 0xd2, 0xcb, 0xbc, 0x6c, 0xc8, 0xc1, 0x24, 0x3c, 0x14, 0x60, 0x33, 0x42, + 0x60, 0x6f, 0x43, 0xad, 0xef, 0xb9, 0x27, 0x8e, 0x3f, 0x22, 0x8e, 0xd0, 0x9c, 0xc3, 0xba, 0x92, + 0x40, 0xe3, 0x0f, 0xb3, 0x50, 0xe9, 0xf9, 0xb6, 0x1b, 0xd8, 0x7d, 0x01, 0x60, 0xab, 0x50, 0x0c, + 0x2f, 0xad, 0x33, 0x3b, 0x38, 0xc3, 0xae, 0x96, 0xcd, 0xb9, 0xf0, 0x72, 0xc7, 0x0e, 0xce, 0xd8, + 0x0a, 0xcc, 0x51, 0x2b, 0xb1, 0x43, 0x39, 0x53, 0x7e, 0x89, 0x05, 0xe2, 0x4e, 0x46, 0x56, 0xb2, + 0xaa, 0x1c, 0x52, 0x4c, 0xc3, 0x9d, 0x8c, 0x36, 0x75, 0xb8, 0xe8, 0xfc, 0xb1, 0x98, 0x6e, 0xaa, + 0x80, 0xba, 0x57, 0x46, 0x08, 0xd6, 0xf1, 0x26, 0x54, 0x65, 0x32, 0x77, 0x4e, 0xcf, 0xa8, 0x8f, + 0x05, 0xb3, 0x42, 0x08, 0x08, 0x12, 0x25, 0x84, 0xce, 0x88, 0x5b, 0x41, 0x68, 0x8f, 0xc6, 0xb2, + 0x4b, 0x65, 0x01, 0xe9, 0x0a, 0x00, 0x26, 0x7b, 0xa1, 0x3d, 0xb4, 0x4e, 0x38, 0x0f, 0x9a, 0x45, + 0x99, 0x2c, 0x20, 0xdb, 0x9c, 0x07, 0xec, 0x6b, 0x50, 0x1f, 0xf0, 0x20, 0xb4, 0xe4, 0x64, 0xf0, + 0xa0, 0x59, 0xc2, 0x95, 0x5f, 0x13, 0xd0, 0x96, 0x02, 0xb2, 0xdb, 0x00, 0xbe, 0x7d, 0x61, 0x89, + 0x81, 0xe0, 0x97, 0xcd, 0x32, 0xcd, 0x82, 0x6f, 0x5f, 0xf4, 0x2e, 0x77, 0xf8, 0xa5, 0xa0, 0x9a, + 0xa7, 0x3c, 0xd4, 0x06, 0x2d, 0x90, 0xd4, 0x69, 0xec, 0x02, 0xd3, 0xc0, 0x5b, 0x3c, 0xb4, 0x9d, + 0x61, 0xc0, 0x3e, 0x84, 0x6a, 0xa8, 0x21, 0x23, 0x1b, 0xac, 0x44, 0x24, 0xa4, 0x65, 0x30, 0x13, + 0x78, 0xc6, 0x19, 0x94, 0xb6, 0x39, 0xdf, 0x75, 0x46, 0x4e, 0xc8, 0x56, 0xa0, 0x70, 0xe2, 0x5c, + 0x72, 0x22, 0xf6, 0xdc, 0xce, 0x0d, 0x93, 0x3e, 0xd9, 0x5d, 0x00, 0xfc, 0x61, 0x8d, 0x22, 0x6a, + 0xda, 0xb9, 0x61, 0x96, 0x11, 0xb6, 0x17, 0xd8, 0x21, 0x5b, 0x83, 0xe2, 0x98, 0xfb, 0x7d, 0xae, + 0xe6, 0x6d, 0xe7, 0x86, 0xa9, 0x00, 0x1b, 0x45, 0x28, 0x0c, 0x45, 0xe9, 0xc6, 0x1f, 0x17, 0xa0, + 0xd2, 0xe5, 0x6e, 0xb4, 0xca, 0x18, 0xe4, 0xc5, 0x80, 0xc8, 0x95, 0x85, 0xbf, 0xd9, 0x5b, 0x50, + 0xc1, 0xa1, 0x0b, 0x42, 0xdf, 0x71, 0x4f, 0x89, 0xaa, 0x37, 0xb2, 0xcd, 0x8c, 0x09, 0x02, 0xdc, + 0x45, 0x28, 0x6b, 0x40, 0xce, 0x1e, 0x29, 0xaa, 0x16, 0x3f, 0xd9, 0x4d, 0x28, 0xd9, 0xa3, 0x90, + 0x9a, 0x57, 0x45, 0x70, 0xd1, 0x1e, 0x85, 0xd8, 0xb4, 0x37, 0xa1, 0x3a, 0xb6, 0xaf, 0x46, 0x62, + 0x2d, 0x47, 0xe4, 0x50, 0x35, 0x2b, 0x12, 0x86, 0x04, 0xf1, 0x18, 0x16, 0x75, 0x14, 0x55, 0x79, + 0x21, 0xaa, 0x7c, 0x41, 0xc3, 0x96, 0x6d, 0x78, 0x17, 0xe6, 0x55, 0x1e, 0x9f, 0xfa, 0x83, 0x64, + 0x52, 0x36, 0xeb, 0x12, 0xac, 0x7a, 0x79, 0x1f, 0x1a, 0x27, 0x8e, 0x6b, 0x0f, 0xad, 0xfe, 0x30, + 0x3c, 0xb7, 0x06, 0x7c, 0x18, 0xda, 0x48, 0x31, 0x05, 0xb3, 0x8e, 0xf0, 0xcd, 0x61, 0x78, 0xbe, + 0x25, 0xa0, 0xec, 0xeb, 0x50, 0x3e, 0xe1, 0xdc, 0xc2, 0xc1, 0x6a, 0x96, 0x12, 0x0b, 0x4f, 0xcd, + 0x90, 0x59, 0x3a, 0x51, 0x73, 0xf5, 0x75, 0x68, 0x78, 0x93, 0xf0, 0xd4, 0x73, 0xdc, 0x53, 0x4b, + 0xf0, 0x3b, 0xcb, 0x19, 0x20, 0x0d, 0xe5, 0x37, 0xb2, 0x8f, 0x32, 0x66, 0x5d, 0xa5, 0x09, 0xce, + 0xd3, 0x19, 0xb0, 0x77, 0x60, 0x7e, 0x68, 0x07, 0xa1, 0x75, 0xe6, 0x8d, 0xad, 0xf1, 0xe4, 0xf8, + 0x05, 0xbf, 0x6a, 0xd6, 0x70, 0x20, 0x6a, 0x02, 0xbc, 0xe3, 0x8d, 0x0f, 0x11, 0x28, 0x28, 0x1b, + 0xdb, 0x49, 0x8d, 0x80, 0x7b, 0x99, 0xfb, 0x35, 0xb3, 0x2c, 0x20, 0x54, 0xe9, 0x73, 0x58, 0xc4, + 0xe9, 0xe9, 0x4f, 0x82, 0xd0, 0x1b, 0x59, 0x82, 0x57, 0xfb, 0x83, 0xa0, 0x59, 0x41, 0x5a, 0x7b, + 0x4f, 0x36, 0x56, 0x9b, 0xe3, 0xf5, 0x2d, 0x1e, 0x84, 0x9b, 0x88, 0x6c, 0x12, 0xae, 0xd8, 0xd0, + 0xaf, 0xcc, 0x85, 0xc1, 0x34, 0x9c, 0x7d, 0x1d, 0x98, 0x3d, 0x1c, 0x7a, 0x17, 0x56, 0xc0, 0x87, + 0x27, 0x96, 0x1c, 0xc4, 0x66, 0xfd, 0x5e, 0xe6, 0x7e, 0xc9, 0x6c, 0x60, 0x4a, 0x97, 0x0f, 0x4f, + 0x0e, 0x09, 0xce, 0x3e, 0x04, 0x5c, 0x4c, 0xd6, 0x09, 0xb7, 0xc3, 0x89, 0xcf, 0x83, 0xe6, 0xfc, + 0xbd, 0xdc, 0xfd, 0xfa, 0xe3, 0x85, 0x68, 0xbc, 0x10, 0xbc, 0xe1, 0x84, 0x66, 0x55, 0xe0, 0xc9, + 0xef, 0x60, 0x6d, 0x0b, 0x56, 0xd2, 0x9b, 0x24, 0x88, 0x4a, 0x8c, 0x8a, 0x20, 0xc6, 0xbc, 0x29, + 0x7e, 0xb2, 0x25, 0x28, 0x9c, 0xdb, 0xc3, 0x09, 0x97, 0x3c, 0x9d, 0x3e, 0x3e, 0xce, 0x7e, 0x3b, + 0x63, 0xfc, 0x51, 0x06, 0xaa, 0xd4, 0x4b, 0x29, 0x8b, 0xbc, 0x05, 0x35, 0x45, 0x0d, 0xdc, 0xf7, + 0x3d, 0x5f, 0x72, 0x35, 0x45, 0x79, 0x6d, 0x01, 0x13, 0xbb, 0x8a, 0x42, 0x1a, 0xfb, 0xdc, 0x19, + 0xd9, 0xa7, 0xaa, 0x68, 0x45, 0x4a, 0x87, 0x12, 0xcc, 0x3e, 0x88, 0xcb, 0xf3, 0xbd, 0x49, 0xc8, + 0xe5, 0x9e, 0x57, 0x95, 0xdd, 0x33, 0x05, 0x2c, 0x2a, 0x1d, 0xbf, 0x5e, 0x83, 0xce, 0x8d, 0xdf, + 0xc9, 0x00, 0x13, 0xcd, 0xee, 0x79, 0x54, 0x80, 0xa4, 0xd0, 0xe9, 0x9c, 0x99, 0xd7, 0x5e, 0x21, + 0xd9, 0x97, 0xad, 0x10, 0x03, 0x0a, 0xd4, 0xf6, 0x7c, 0x4a, 0xdb, 0x29, 0xe9, 0xfb, 0xf9, 0x52, + 0xae, 0x91, 0x37, 0xfe, 0x6b, 0x0e, 0x96, 0x36, 0x69, 0xcb, 0x6e, 0xf5, 0xfb, 0x7c, 0x1c, 0xad, + 0x9d, 0xbb, 0x50, 0x71, 0xbd, 0x01, 0x57, 0x14, 0x4b, 0x0d, 0x03, 0x01, 0xd2, 0xc8, 0xf5, 0xcc, + 0x76, 0x5c, 0x6a, 0x38, 0x0d, 0x66, 0x19, 0x21, 0xd8, 0xec, 0x77, 0x60, 0x7e, 0xcc, 0xdd, 0x81, + 0xbe, 0x44, 0x48, 0xa8, 0xaa, 0x49, 0xb0, 0x5c, 0x1d, 0x77, 0xa1, 0x72, 0x32, 0x21, 0x3c, 0xc1, + 0x58, 0xf2, 0x48, 0x03, 0x20, 0x41, 0x2d, 0xe2, 0x2f, 0xe3, 0x49, 0x70, 0x86, 0xa9, 0x05, 0x4c, + 0x2d, 0x8a, 0x6f, 0x91, 0x74, 0x07, 0x60, 0x30, 0x09, 0x42, 0xb9, 0x62, 0xe6, 0x30, 0xb1, 0x2c, + 0x20, 0xb4, 0x62, 0xbe, 0x01, 0x8b, 0x23, 0xfb, 0xd2, 0x42, 0xda, 0xb1, 0x1c, 0xd7, 0x3a, 0x19, + 0xe2, 0x9e, 0x53, 0x44, 0xbc, 0xc6, 0xc8, 0xbe, 0xfc, 0x4c, 0xa4, 0x74, 0xdc, 0x6d, 0x84, 0x0b, + 0xb6, 0xa2, 0xc4, 0x1d, 0x9f, 0x07, 0xdc, 0x3f, 0xe7, 0xc8, 0x09, 0xf2, 0x91, 0x4c, 0x63, 0x12, + 0x54, 0xb4, 0x68, 0x24, 0xfa, 0x1d, 0x0e, 0xfb, 0xb4, 0xec, 0xcd, 0xe2, 0xc8, 0x71, 0x77, 0xc2, + 0x61, 0x5f, 0xec, 0x2b, 0x82, 0x8f, 0x8c, 0xb9, 0x6f, 0xbd, 0xb8, 0xc0, 0x35, 0x9c, 0x47, 0xbe, + 0x71, 0xc8, 0xfd, 0x67, 0x17, 0x62, 0xeb, 0xef, 0x07, 0xc8, 0x88, 0xec, 0xab, 0x66, 0x05, 0x17, + 0x78, 0xa9, 0x1f, 0x08, 0x16, 0x64, 0x5f, 0x89, 0x45, 0x28, 0x5a, 0x6b, 0xe3, 0x2c, 0xf0, 0x01, + 0x16, 0x1f, 0x20, 0x47, 0xad, 0x61, 0x63, 0x5b, 0x32, 0x41, 0xd4, 0x13, 0x08, 0xaa, 0x57, 0x8d, + 0x3d, 0x19, 0xda, 0xa7, 0x01, 0xb2, 0x94, 0x9a, 0x59, 0x95, 0xc0, 0x6d, 0x01, 0x33, 0x3e, 0x27, + 0x21, 0x4b, 0x9b, 0x5b, 0xb9, 0x66, 0xc4, 0x56, 0x8f, 0x10, 0x9c, 0xd7, 0x92, 0x29, 0xbf, 0xd2, + 0x26, 0x2d, 0x9b, 0x32, 0x69, 0xc6, 0xef, 0x65, 0xa0, 0x2a, 0x4b, 0x46, 0xa1, 0x84, 0xad, 0x03, + 0x53, 0xb3, 0x18, 0x5e, 0x3a, 0x03, 0xeb, 0xf8, 0x2a, 0xe4, 0x01, 0x11, 0xcd, 0xce, 0x0d, 0xb3, + 0x21, 0xd3, 0x7a, 0x97, 0xce, 0x60, 0x43, 0xa4, 0xb0, 0x07, 0xd0, 0x48, 0xe0, 0x07, 0xa1, 0x4f, + 0x14, 0xbd, 0x73, 0xc3, 0xac, 0x6b, 0xd8, 0xdd, 0xd0, 0x17, 0x6b, 0x44, 0x88, 0x3c, 0x93, 0xd0, + 0x72, 0xdc, 0x01, 0xbf, 0x44, 0x32, 0xaa, 0x99, 0x15, 0x82, 0x75, 0x04, 0x68, 0xa3, 0x0e, 0x55, + 0xbd, 0x38, 0xe3, 0x14, 0x4a, 0x4a, 0x5e, 0x42, 0x81, 0x61, 0xaa, 0x49, 0x66, 0x39, 0x8c, 0x5a, + 0x72, 0x13, 0x4a, 0xc9, 0x16, 0x98, 0xc5, 0xf0, 0xb5, 0x2b, 0x36, 0xbe, 0x0b, 0x8d, 0x5d, 0x41, + 0x3c, 0xae, 0x20, 0x56, 0x29, 0xff, 0xad, 0xc0, 0x9c, 0xb6, 0x68, 0xca, 0xa6, 0xfc, 0x12, 0x7b, + 0xee, 0x99, 0x17, 0x84, 0xb2, 0x16, 0xfc, 0x6d, 0xfc, 0x71, 0x06, 0x58, 0x3b, 0x08, 0x9d, 0x91, + 0x1d, 0xf2, 0x6d, 0x1e, 0xb1, 0x85, 0x03, 0xa8, 0x8a, 0xd2, 0x7a, 0x5e, 0x8b, 0x04, 0x32, 0x12, + 0x28, 0xde, 0x97, 0xcb, 0x78, 0x36, 0xc3, 0xba, 0x8e, 0x4d, 0x6c, 0x3e, 0x51, 0x80, 0x58, 0x65, + 0xa1, 0xed, 0x9f, 0xf2, 0x10, 0xc5, 0x38, 0x29, 0xef, 0x03, 0x81, 0x84, 0x00, 0xb7, 0xf6, 0xcb, + 0xb0, 0x30, 0x53, 0x86, 0xce, 0x97, 0xcb, 0x29, 0x7c, 0x39, 0xa7, 0xf3, 0x65, 0x0b, 0x16, 0x13, + 0xed, 0x92, 0x94, 0xb6, 0x0a, 0x45, 0xb1, 0x20, 0x84, 0x70, 0x90, 0x21, 0xa9, 0xf2, 0x84, 0x73, + 0x21, 0x06, 0x3f, 0x84, 0xa5, 0x13, 0xce, 0x7d, 0x3b, 0xc4, 0x44, 0x5c, 0x31, 0x62, 0x86, 0x64, + 0xc1, 0x0b, 0x32, 0xad, 0x6b, 0x87, 0x87, 0xdc, 0x17, 0x33, 0x65, 0xfc, 0xf7, 0x0c, 0xcc, 0x0b, + 0x0e, 0xba, 0x67, 0xbb, 0x57, 0x6a, 0x9c, 0x76, 0x53, 0xc7, 0xe9, 0xbe, 0xb6, 0x19, 0x6a, 0xd8, + 0x5f, 0x75, 0x90, 0x72, 0xd3, 0x83, 0xc4, 0xee, 0x41, 0x35, 0xd1, 0xd6, 0x02, 0xb6, 0x15, 0x82, + 0xa8, 0x91, 0x3f, 0xfb, 0x30, 0xbe, 0x03, 0x8d, 0xb8, 0xd9, 0x72, 0x0c, 0x19, 0xe4, 0x05, 0x49, + 0xca, 0x02, 0xf0, 0xb7, 0xf1, 0x8f, 0x33, 0x84, 0xb8, 0xe9, 0x39, 0x91, 0x74, 0x2a, 0x10, 0x85, + 0xdc, 0xab, 0x10, 0xc5, 0xef, 0x6b, 0xa5, 0xfa, 0x9f, 0xbd, 0xb3, 0x62, 0xe9, 0x04, 0xdc, 0x1d, + 0x58, 0xf6, 0x70, 0x88, 0xcc, 0xb7, 0x64, 0x16, 0xc5, 0x77, 0x6b, 0x38, 0x34, 0xde, 0x85, 0x05, + 0xad, 0x75, 0x2f, 0xe9, 0xc7, 0x3e, 0xb0, 0x5d, 0x27, 0x08, 0x8f, 0xdc, 0x60, 0xac, 0x09, 0x6e, + 0xb7, 0xa0, 0x2c, 0x38, 0xac, 0x68, 0x19, 0x2d, 0xd9, 0x82, 0x29, 0x58, 0xae, 0x68, 0x57, 0x80, + 0x89, 0xf6, 0xa5, 0x4c, 0xcc, 0xca, 0x44, 0xfb, 0x12, 0x13, 0x8d, 0x6f, 0xc3, 0x62, 0xa2, 0x3c, + 0x59, 0xf5, 0x9b, 0x50, 0x98, 0x84, 0x97, 0x9e, 0x12, 0xcd, 0x2b, 0x92, 0x42, 0x84, 0x02, 0x68, + 0x52, 0x8a, 0xf1, 0x09, 0x2c, 0xec, 0xf3, 0x0b, 0xb9, 0x88, 0x55, 0x43, 0xde, 0x81, 0xfc, 0x2b, + 0x94, 0x42, 0x4c, 0x37, 0xd6, 0x81, 0xe9, 0x99, 0x65, 0xad, 0x9a, 0x8e, 0x98, 0x49, 0xe8, 0x88, + 0xc6, 0x3b, 0xc0, 0xba, 0xce, 0xa9, 0xbb, 0xc7, 0x83, 0xc0, 0x3e, 0x8d, 0x96, 0x7d, 0x03, 0x72, + 0xa3, 0xe0, 0x54, 0xf2, 0x28, 0xf1, 0xd3, 0xf8, 0x26, 0x2c, 0x26, 0xf0, 0x64, 0xc1, 0xb7, 0xa1, + 0x1c, 0x38, 0xa7, 0x2e, 0x0a, 0x56, 0xb2, 0xe8, 0x18, 0x60, 0x6c, 0xc3, 0xd2, 0x67, 0xdc, 0x77, + 0x4e, 0xae, 0x5e, 0x55, 0x7c, 0xb2, 0x9c, 0xec, 0x74, 0x39, 0x6d, 0x58, 0x9e, 0x2a, 0x47, 0x56, + 0x4f, 0xe4, 0x2b, 0x67, 0xb2, 0x64, 0xd2, 0x87, 0xc6, 0xf7, 0xb2, 0x3a, 0xdf, 0x33, 0x8e, 0x80, + 0x6d, 0x7a, 0xae, 0xcb, 0xfb, 0xe1, 0x21, 0xe7, 0x7e, 0x7c, 0x4a, 0x15, 0xd3, 0x6a, 0xe5, 0xf1, + 0xaa, 0x1c, 0xd9, 0x69, 0x66, 0x2a, 0x89, 0x98, 0x41, 0x7e, 0xcc, 0xfd, 0x11, 0x16, 0x5c, 0x32, + 0xf1, 0xb7, 0xb1, 0x0c, 0x8b, 0x89, 0x62, 0xa5, 0x5e, 0xff, 0x08, 0x96, 0xb7, 0x9c, 0xa0, 0x3f, + 0x5b, 0xe1, 0x2a, 0x14, 0xc7, 0x93, 0x63, 0x2b, 0xc9, 0x97, 0x9f, 0xf1, 0x2b, 0xa1, 0xed, 0x4d, + 0xe7, 0x90, 0x65, 0xfd, 0xf5, 0x0c, 0xe4, 0x77, 0x7a, 0xbb, 0x9b, 0x6c, 0x0d, 0x4a, 0x8e, 0xdb, + 0xf7, 0x46, 0x42, 0xf0, 0xa2, 0x3e, 0x47, 0xdf, 0xd7, 0x2e, 0xb0, 0x5b, 0x50, 0x46, 0x79, 0x4d, + 0xa8, 0xb6, 0x52, 0xf4, 0x29, 0x09, 0xc0, 0xae, 0xd7, 0x7f, 0x21, 0x74, 0x6a, 0x7e, 0x39, 0x76, + 0x7c, 0xd4, 0x9a, 0x95, 0x32, 0x9c, 0xa7, 0xbd, 0x3e, 0x4e, 0x20, 0x8d, 0xd8, 0xf8, 0xb7, 0x25, + 0x28, 0xca, 0xdd, 0x96, 0x76, 0xee, 0xd0, 0x39, 0xe7, 0xf1, 0xce, 0x2d, 0xbe, 0x84, 0x3c, 0xe0, + 0xf3, 0x91, 0x17, 0x46, 0x02, 0x1b, 0xcd, 0x41, 0x95, 0x80, 0x52, 0x64, 0xd3, 0x84, 0x06, 0x3a, + 0x62, 0xc8, 0x11, 0x52, 0x5f, 0xdf, 0xca, 0x6f, 0x41, 0x51, 0xed, 0xfd, 0xf9, 0x48, 0xa7, 0x99, + 0xeb, 0x93, 0xb4, 0xb6, 0x06, 0xa5, 0xbe, 0x3d, 0xb6, 0xfb, 0x4e, 0x78, 0x25, 0x19, 0x42, 0xf4, + 0x2d, 0x4a, 0x1f, 0x7a, 0x7d, 0x7b, 0x68, 0x1d, 0xdb, 0x43, 0xdb, 0xed, 0x73, 0xa9, 0xbb, 0x57, + 0x11, 0xb8, 0x41, 0x30, 0xa1, 0x9f, 0xcb, 0x76, 0x2a, 0x2c, 0x52, 0xe1, 0x65, 0xeb, 0x15, 0x9a, + 0x10, 0x2e, 0xbd, 0xd1, 0xc8, 0x11, 0x5a, 0x06, 0x89, 0x61, 0x39, 0xb3, 0x4c, 0x90, 0x6d, 0x8e, + 0xbd, 0x95, 0xc9, 0x17, 0x34, 0x74, 0x65, 0xaa, 0x8a, 0x80, 0x9f, 0xd3, 0x41, 0xc2, 0xac, 0x2c, + 0x96, 0xd3, 0x64, 0xb1, 0xf7, 0x61, 0x61, 0xe2, 0x06, 0x3c, 0x0c, 0x87, 0x7c, 0x10, 0xb5, 0xa5, + 0x82, 0x48, 0x8d, 0x28, 0x41, 0x35, 0x67, 0x1d, 0x16, 0xe9, 0xd0, 0x21, 0xb0, 0x43, 0x2f, 0x38, + 0x73, 0x02, 0x2b, 0x10, 0x1a, 0x12, 0xa9, 0xbb, 0x0b, 0x98, 0xd4, 0x95, 0x29, 0x5d, 0x52, 0x91, + 0x56, 0xa7, 0xf0, 0x7d, 0xde, 0xe7, 0xce, 0x39, 0x1f, 0xa0, 0x9c, 0x96, 0x33, 0x97, 0x13, 0x79, + 0x4c, 0x99, 0x88, 0x42, 0xf7, 0x64, 0x64, 0x4d, 0xc6, 0x03, 0x5b, 0x08, 0x2b, 0x75, 0x12, 0x86, + 0xdd, 0xc9, 0xe8, 0x88, 0x20, 0xec, 0x11, 0x28, 0x49, 0x4c, 0xca, 0x87, 0xf3, 0x09, 0x7e, 0x26, + 0x88, 0xd5, 0xac, 0x4a, 0x0c, 0x12, 0x14, 0x13, 0x32, 0x67, 0x63, 0x4a, 0xe6, 0x6c, 0x42, 0x71, + 0xec, 0x3b, 0xe7, 0x76, 0xc8, 0x9b, 0x0b, 0xc4, 0xc0, 0xe5, 0xa7, 0xe0, 0x0c, 0x8e, 0xeb, 0x84, + 0x8e, 0x1d, 0x7a, 0x7e, 0x93, 0x61, 0x5a, 0x0c, 0x60, 0x0f, 0x60, 0x01, 0x69, 0x24, 0x08, 0xed, + 0x70, 0x12, 0x48, 0x09, 0x74, 0x11, 0x89, 0x09, 0x65, 0xe8, 0x2e, 0xc2, 0x51, 0x08, 0x65, 0xdf, + 0x84, 0x15, 0x22, 0x0b, 0xcc, 0x21, 0x25, 0x6b, 0x14, 0x08, 0x96, 0x70, 0x28, 0x16, 0x31, 0x55, + 0xd0, 0xb7, 0x94, 0xaf, 0x85, 0x74, 0xf0, 0x04, 0x56, 0x25, 0x99, 0xcc, 0xe4, 0x5a, 0xc6, 0x5c, + 0x4b, 0x94, 0x3c, 0x95, 0x6d, 0x1d, 0x16, 0x44, 0x93, 0x9c, 0xbe, 0x25, 0x73, 0x8b, 0x95, 0xb0, + 0x22, 0x5a, 0x8f, 0x9a, 0xd2, 0x3c, 0x25, 0x9a, 0x98, 0xf6, 0x8c, 0x5f, 0xb1, 0xef, 0xc2, 0x3c, + 0x91, 0x0c, 0xaa, 0x57, 0xc8, 0xe9, 0xd7, 0x90, 0xd3, 0x2f, 0xab, 0x13, 0xce, 0x28, 0x15, 0x99, + 0x7d, 0xbd, 0x9f, 0xf8, 0x16, 0xcb, 0x61, 0xe8, 0x9c, 0xf0, 0xd0, 0x19, 0xf1, 0xe6, 0x2a, 0x11, + 0x98, 0xfa, 0x16, 0x2b, 0x75, 0x32, 0xc6, 0x94, 0x26, 0xf1, 0x05, 0xfa, 0x42, 0xda, 0x1d, 0x7a, + 0x01, 0x57, 0x47, 0x54, 0xcd, 0x9b, 0x72, 0x11, 0x0a, 0xa0, 0x92, 0x21, 0x85, 0x20, 0x4e, 0x4a, + 0x4f, 0x74, 0x90, 0x78, 0x0b, 0x89, 0xa1, 0x46, 0xba, 0x8f, 0x3a, 0x4c, 0x14, 0xbb, 0xf8, 0x99, + 0x7d, 0xa1, 0x38, 0xc8, 0x6d, 0x9c, 0x5f, 0x10, 0x20, 0xc9, 0x3b, 0x7e, 0x92, 0xa1, 0x0d, 0x51, + 0xf2, 0x8f, 0x40, 0x53, 0xef, 0x88, 0x73, 0x58, 0x9e, 0x3b, 0xbc, 0x92, 0xcc, 0x04, 0x08, 0x74, + 0xe0, 0x0e, 0x71, 0x35, 0x3b, 0xae, 0x8e, 0x42, 0xbc, 0xb7, 0xaa, 0x80, 0x88, 0x74, 0x17, 0x2a, + 0xe3, 0xc9, 0xf1, 0xd0, 0xe9, 0x13, 0x4a, 0x8e, 0x4a, 0x21, 0x10, 0x22, 0x08, 0xfd, 0x96, 0x28, + 0x8a, 0x30, 0xf2, 0x88, 0x51, 0x91, 0x30, 0x44, 0x41, 0xde, 0xce, 0x7d, 0x64, 0x27, 0x55, 0x13, + 0x7f, 0x1b, 0x1b, 0xb0, 0x94, 0x6c, 0xb4, 0xdc, 0x78, 0x1e, 0x40, 0x49, 0xf2, 0x2a, 0x75, 0xf0, + 0x51, 0xd7, 0x8e, 0xa2, 0x85, 0x8a, 0x16, 0xa5, 0x1b, 0xbf, 0x5f, 0x80, 0x45, 0x09, 0xdd, 0x14, + 0x43, 0xdb, 0x9d, 0x8c, 0x46, 0xb6, 0x9f, 0xc2, 0x04, 0x33, 0x2f, 0x67, 0x82, 0xd9, 0x19, 0x26, + 0x98, 0xd4, 0x7c, 0x89, 0x87, 0x26, 0x35, 0x5f, 0x31, 0x97, 0xa4, 0x8c, 0xe8, 0xe7, 0xa0, 0x35, + 0x09, 0xee, 0xd1, 0x79, 0xeb, 0x0c, 0xcb, 0x2e, 0xa4, 0xb0, 0x6c, 0x9d, 0xe1, 0xce, 0x4d, 0x31, + 0xdc, 0x37, 0x81, 0x88, 0x46, 0xcd, 0x7e, 0x91, 0xf4, 0x13, 0x84, 0xc9, 0xc3, 0xd4, 0x77, 0x61, + 0x7e, 0x9a, 0xc7, 0x11, 0x33, 0xad, 0xa7, 0x70, 0x38, 0x67, 0xc4, 0x71, 0xb7, 0xd2, 0x90, 0xcb, + 0x92, 0xc3, 0x39, 0x23, 0xbe, 0x8b, 0x29, 0x0a, 0xbf, 0x0d, 0x40, 0x75, 0xe3, 0xa2, 0x01, 0x5c, + 0x34, 0xef, 0x24, 0xe7, 0x42, 0x1f, 0xf5, 0x75, 0xf1, 0x31, 0xf1, 0x39, 0xae, 0xa2, 0x32, 0xe6, + 0xc4, 0x05, 0xf4, 0x11, 0xd4, 0xbd, 0x31, 0x77, 0xad, 0x98, 0xd7, 0x54, 0xb0, 0xa8, 0x86, 0x2c, + 0xaa, 0xa3, 0xe0, 0x66, 0x4d, 0xe0, 0x45, 0x9f, 0xec, 0x3b, 0x34, 0xc8, 0x5c, 0xcb, 0x59, 0xbd, + 0x26, 0x67, 0x1d, 0x11, 0xa3, 0x6f, 0xe3, 0x6f, 0x65, 0xa0, 0xa2, 0x35, 0x87, 0x2d, 0xc3, 0xc2, + 0xe6, 0xc1, 0xc1, 0x61, 0xdb, 0x6c, 0xf5, 0x3a, 0x9f, 0xb5, 0xad, 0xcd, 0xdd, 0x83, 0x6e, 0xbb, + 0x71, 0x43, 0x80, 0x77, 0x0f, 0x36, 0x5b, 0xbb, 0xd6, 0xf6, 0x81, 0xb9, 0xa9, 0xc0, 0x19, 0xb6, + 0x02, 0xcc, 0x6c, 0xef, 0x1d, 0xf4, 0xda, 0x09, 0x78, 0x96, 0x35, 0xa0, 0xba, 0x61, 0xb6, 0x5b, + 0x9b, 0x3b, 0x12, 0x92, 0x63, 0x4b, 0xd0, 0xd8, 0x3e, 0xda, 0xdf, 0xea, 0xec, 0x3f, 0xb5, 0x36, + 0x5b, 0xfb, 0x9b, 0xed, 0xdd, 0xf6, 0x56, 0x23, 0xcf, 0x6a, 0x50, 0x6e, 0x6d, 0xb4, 0xf6, 0xb7, + 0x0e, 0xf6, 0xdb, 0x5b, 0x8d, 0x82, 0xf1, 0xe7, 0x19, 0x58, 0xc6, 0x81, 0x1a, 0x4c, 0xaf, 0xd0, + 0x7b, 0x50, 0xe9, 0x7b, 0xde, 0x58, 0xa8, 0x41, 0xf1, 0x76, 0xaf, 0x83, 0xc4, 0xea, 0x23, 0xce, + 0x7a, 0xe2, 0xf9, 0x7d, 0x2e, 0x17, 0x28, 0x20, 0x68, 0x5b, 0x40, 0x04, 0x81, 0x48, 0x0a, 0x23, + 0x0c, 0x5a, 0x9f, 0x15, 0x82, 0x11, 0xca, 0x0a, 0xcc, 0x1d, 0xfb, 0xdc, 0xee, 0x9f, 0xc9, 0xa5, + 0x29, 0xbf, 0xd8, 0x7b, 0xb1, 0x82, 0xde, 0x17, 0x13, 0x3e, 0xe4, 0x03, 0xa4, 0xcf, 0x92, 0x39, + 0x2f, 0xe1, 0x9b, 0x12, 0x2c, 0xb6, 0x0a, 0xfb, 0xd8, 0x76, 0x07, 0x9e, 0xcb, 0x07, 0x52, 0x0f, + 0x88, 0x01, 0xc6, 0x21, 0xac, 0x4c, 0xf7, 0x4f, 0x2e, 0xe6, 0x0f, 0xb5, 0xc5, 0x4c, 0x62, 0xf9, + 0xda, 0xf5, 0x04, 0xa4, 0x2d, 0xec, 0xbf, 0x93, 0x87, 0xbc, 0x10, 0xd3, 0xae, 0x95, 0xe8, 0x74, + 0xb9, 0x3b, 0x37, 0x63, 0x9b, 0xc1, 0x73, 0x00, 0xda, 0xbf, 0xe9, 0xb0, 0xa9, 0x8c, 0x10, 0xdc, + 0xb7, 0xa3, 0x64, 0x9f, 0xf7, 0xcf, 0xe5, 0x69, 0x13, 0x25, 0x9b, 0xbc, 0x7f, 0x8e, 0x0a, 0x8f, + 0x1d, 0x52, 0x5e, 0x5a, 0x8c, 0xc5, 0xc0, 0x0e, 0x31, 0xa7, 0x4c, 0xc2, 0x7c, 0xc5, 0x28, 0x09, + 0x73, 0x35, 0xa1, 0xe8, 0xb8, 0xc7, 0xde, 0xc4, 0x1d, 0xe0, 0xda, 0x2b, 0x99, 0xea, 0x13, 0x4d, + 0x41, 0xc8, 0x26, 0xc4, 0x2e, 0x41, 0x4b, 0xad, 0x24, 0x00, 0x3d, 0xb1, 0x4f, 0x7c, 0x00, 0xe5, + 0xe0, 0xca, 0xed, 0xeb, 0x0b, 0x6c, 0x49, 0x8e, 0x8f, 0xe8, 0xfd, 0x7a, 0xf7, 0xca, 0xed, 0xe3, + 0x72, 0x2a, 0x05, 0xf2, 0x17, 0x7b, 0x02, 0xa5, 0xe8, 0x50, 0x96, 0xd8, 0xe3, 0x4d, 0x3d, 0x87, + 0x3a, 0x89, 0x25, 0xdd, 0x37, 0x42, 0x65, 0x0f, 0x61, 0x0e, 0x4f, 0x4e, 0x83, 0x66, 0x15, 0x33, + 0x29, 0x61, 0x5c, 0x34, 0x03, 0xad, 0x30, 0x7c, 0x80, 0xa7, 0xa8, 0xa6, 0x44, 0x5b, 0x7b, 0x06, + 0xb5, 0x44, 0x59, 0xba, 0x86, 0x5b, 0x23, 0x0d, 0xf7, 0x6d, 0x5d, 0xc3, 0x8d, 0xd9, 0xb4, 0xcc, + 0xa6, 0x6b, 0xbc, 0xbf, 0x0c, 0x25, 0xd5, 0x15, 0xb1, 0x88, 0x8e, 0xf6, 0x9f, 0xed, 0x1f, 0x7c, + 0xbe, 0x6f, 0x75, 0x9f, 0xef, 0x6f, 0x36, 0x6e, 0xb0, 0x79, 0xa8, 0xb4, 0x36, 0x71, 0x5d, 0x22, + 0x20, 0x23, 0x50, 0x0e, 0x5b, 0xdd, 0x6e, 0x04, 0xc9, 0x1a, 0xdb, 0xd0, 0x98, 0x6e, 0xa9, 0xa0, + 0xc9, 0x50, 0xc1, 0xe4, 0xb9, 0x72, 0x0c, 0x10, 0xfa, 0x0b, 0x1d, 0x15, 0x93, 0x90, 0x4c, 0x1f, + 0xc6, 0x13, 0x68, 0x88, 0x4d, 0x47, 0x0c, 0x55, 0xa0, 0x9d, 0xcf, 0x0e, 0x85, 0xe0, 0xa5, 0x9f, + 0x2d, 0x97, 0xcc, 0x0a, 0xc1, 0xb0, 0x2a, 0xe3, 0x43, 0x58, 0xd0, 0xb2, 0xc5, 0xfa, 0xa6, 0xd8, + 0xc8, 0xa6, 0xf5, 0x4d, 0xd4, 0x2e, 0x28, 0xc5, 0x58, 0x85, 0x65, 0xf1, 0xd9, 0x3e, 0xe7, 0x6e, + 0xd8, 0x9d, 0x1c, 0x93, 0x41, 0xd0, 0xf1, 0x5c, 0xa1, 0x75, 0x94, 0xa3, 0x94, 0xeb, 0x89, 0x7c, + 0x5d, 0xaa, 0xa6, 0x59, 0x24, 0x8d, 0x35, 0xad, 0x06, 0xcc, 0xb8, 0x8e, 0x7f, 0x13, 0x2a, 0x6a, + 0x39, 0x02, 0x89, 0x61, 0x3d, 0x6c, 0xb7, 0x4d, 0xeb, 0x60, 0x7f, 0xb7, 0xb3, 0x2f, 0xb8, 0x9d, + 0x18, 0x56, 0x04, 0x6c, 0x6f, 0x23, 0x24, 0x63, 0x34, 0xa0, 0xfe, 0x94, 0x87, 0x1d, 0xf7, 0xc4, + 0x53, 0xc6, 0xaf, 0xbf, 0x28, 0xc0, 0x7c, 0x04, 0x8a, 0x55, 0xdc, 0x73, 0xee, 0x07, 0x8e, 0xe7, + 0xa2, 0xb4, 0x5a, 0x36, 0xd5, 0xa7, 0xd8, 0x7a, 0x9c, 0x01, 0x77, 0x43, 0x27, 0xbc, 0xb2, 0x12, + 0xe7, 0x61, 0x75, 0x05, 0x96, 0x5b, 0xdc, 0x12, 0x14, 0xec, 0xa1, 0x63, 0x2b, 0x3b, 0x2a, 0x7d, + 0x08, 0x68, 0xdf, 0x1b, 0x7a, 0x3e, 0x0a, 0xa6, 0x65, 0x93, 0x3e, 0xd8, 0x23, 0x58, 0x12, 0x02, + 0xb2, 0x7e, 0x48, 0x89, 0xfc, 0x83, 0x8e, 0xe6, 0x98, 0x3b, 0x19, 0x1d, 0xc6, 0x07, 0x95, 0x22, + 0x45, 0x6c, 0x6c, 0x22, 0x87, 0x94, 0x64, 0xa2, 0x0c, 0xa4, 0x6b, 0x2d, 0xb8, 0x93, 0x51, 0x0b, + 0x53, 0x22, 0xfc, 0xc7, 0xb0, 0x2c, 0xf0, 0x23, 0xd9, 0x27, 0xca, 0x31, 0x8f, 0x39, 0x44, 0x61, + 0x1d, 0x99, 0x16, 0xe5, 0xb9, 0x05, 0x65, 0x6a, 0x95, 0x98, 0xf1, 0x02, 0xc9, 0xd8, 0xd8, 0x14, + 0xee, 0x07, 0x33, 0x26, 0xcf, 0x39, 0xda, 0xa5, 0xa7, 0x4c, 0x9e, 0x9a, 0xd1, 0xb4, 0x34, 0x6d, + 0x34, 0x7d, 0x0c, 0xcb, 0xc7, 0x82, 0x04, 0xcf, 0xb8, 0x3d, 0xe0, 0xbe, 0x15, 0x13, 0x36, 0xe9, + 0x12, 0x8b, 0x22, 0x71, 0x07, 0xd3, 0xa2, 0x75, 0x20, 0x84, 0x10, 0xc1, 0x16, 0xf8, 0xc0, 0x0a, + 0x3d, 0x0b, 0x65, 0x13, 0x64, 0x30, 0x25, 0xb3, 0x46, 0xe0, 0x9e, 0xb7, 0x29, 0x80, 0x49, 0xbc, + 0x53, 0xdf, 0x1e, 0x9f, 0x49, 0x69, 0x3f, 0xc2, 0x7b, 0x2a, 0x80, 0xec, 0x36, 0x14, 0x05, 0xc9, + 0xbb, 0x9c, 0x2c, 0x53, 0x24, 0x4f, 0x2b, 0x10, 0x7b, 0x1b, 0xe6, 0xb0, 0x8e, 0xa0, 0xd9, 0x40, + 0x7a, 0xaf, 0xc6, 0x8c, 0xdc, 0x71, 0x4d, 0x99, 0x26, 0x24, 0xbd, 0x89, 0xef, 0x10, 0x97, 0x29, + 0x9b, 0xf8, 0x9b, 0x7d, 0x4f, 0x63, 0x59, 0x8b, 0x98, 0xf7, 0x6d, 0x99, 0x77, 0x8a, 0xd2, 0xae, + 0xe3, 0x5e, 0x3f, 0x57, 0x66, 0xf4, 0xfd, 0x7c, 0xa9, 0xd2, 0xa8, 0x1a, 0x1f, 0x41, 0x81, 0x46, + 0x47, 0x10, 0x21, 0x8e, 0x5d, 0x46, 0x12, 0x21, 0x42, 0x9b, 0x50, 0x74, 0x79, 0x78, 0xe1, 0xf9, + 0x2f, 0xd4, 0x89, 0xb1, 0xfc, 0x34, 0x7e, 0x84, 0x47, 0x1d, 0x91, 0x39, 0x9c, 0xb4, 0x36, 0x41, + 0x1e, 0x34, 0xbd, 0xc1, 0x99, 0x2d, 0x4f, 0x5f, 0x4a, 0x08, 0xe8, 0x9e, 0xd9, 0x33, 0xe4, 0x91, + 0x9d, 0xb5, 0x88, 0xbf, 0x0d, 0x75, 0x65, 0x80, 0x0f, 0xac, 0x21, 0x3f, 0x09, 0x25, 0xb9, 0x57, + 0xa5, 0xf5, 0x3d, 0xd8, 0xe5, 0x27, 0xa1, 0xb1, 0x07, 0x0b, 0x92, 0x20, 0x0f, 0xc6, 0x5c, 0x55, + 0xfd, 0xed, 0x34, 0x61, 0xb7, 0xf2, 0x78, 0x31, 0xb9, 0xd1, 0x92, 0x63, 0x41, 0x42, 0x02, 0x36, + 0x3e, 0x05, 0xa6, 0x6f, 0xc3, 0xb2, 0x3c, 0x29, 0x72, 0xaa, 0x83, 0x76, 0x65, 0xaf, 0x8a, 0x04, + 0x5b, 0x67, 0x20, 0x46, 0x27, 0x98, 0xf4, 0xfb, 0xca, 0x31, 0xa2, 0x64, 0xaa, 0x4f, 0xe3, 0x4f, + 0x32, 0xb0, 0x88, 0x85, 0x29, 0x61, 0x5d, 0x32, 0xd9, 0x9f, 0xba, 0x91, 0x62, 0x7e, 0x74, 0xd9, + 0x87, 0x3e, 0xbe, 0xfa, 0xd1, 0x66, 0x7e, 0xe6, 0x68, 0xf3, 0x3d, 0x68, 0x0c, 0xf8, 0xd0, 0x41, + 0x1f, 0x19, 0x25, 0x4a, 0x90, 0x78, 0x3e, 0xaf, 0xe0, 0x52, 0x55, 0x33, 0xfe, 0x41, 0x06, 0x16, + 0x48, 0x52, 0x41, 0xa5, 0x57, 0x0e, 0xd4, 0x27, 0x4a, 0xcb, 0x93, 0xac, 0x4a, 0xf6, 0x29, 0xde, + 0xc1, 0x11, 0x4a, 0xc8, 0x3b, 0x37, 0xa4, 0xf6, 0x27, 0xa1, 0xec, 0x63, 0x54, 0x30, 0x5c, 0x0b, + 0x81, 0x29, 0x3e, 0x37, 0xc9, 0x49, 0xd9, 0xb9, 0x81, 0xda, 0x87, 0x8b, 0xa0, 0x8d, 0x92, 0x50, + 0x3b, 0x05, 0xd8, 0xd8, 0x86, 0x5a, 0xa2, 0x9a, 0xc4, 0xf9, 0x6b, 0x95, 0xce, 0x5f, 0x67, 0x6c, + 0x1c, 0xd9, 0x59, 0x1b, 0xc7, 0x15, 0x2c, 0x9a, 0xdc, 0x1e, 0x5c, 0x6d, 0x7b, 0xfe, 0x61, 0x70, + 0x1c, 0x6e, 0x93, 0xf8, 0x27, 0xf8, 0x7b, 0x64, 0xb8, 0x4b, 0x1c, 0x72, 0x2a, 0xfb, 0x8d, 0xd2, + 0x65, 0xbf, 0x06, 0xf5, 0xd8, 0xc2, 0xa7, 0x1d, 0x94, 0xd5, 0x22, 0x23, 0x1f, 0x9e, 0x97, 0x09, + 0x3d, 0x30, 0x38, 0x0e, 0xe5, 0x51, 0x19, 0xfe, 0x36, 0xfe, 0x46, 0x1e, 0x98, 0xa0, 0xe6, 0x29, + 0x82, 0x99, 0xb2, 0x4d, 0x66, 0x67, 0x6c, 0x93, 0x8f, 0x80, 0x69, 0x08, 0xca, 0x64, 0x9a, 0x8b, + 0x4c, 0xa6, 0x8d, 0x18, 0x57, 0x5a, 0x4c, 0x1f, 0xc1, 0x92, 0x94, 0xa5, 0x93, 0x4d, 0x25, 0xd2, + 0x60, 0x24, 0x54, 0x27, 0xda, 0xab, 0xec, 0x92, 0x42, 0x37, 0xa7, 0xa3, 0x30, 0xb4, 0x4b, 0x2a, + 0xad, 0x5c, 0x23, 0xc0, 0xb9, 0x57, 0x12, 0x60, 0x71, 0x86, 0x00, 0xb5, 0x93, 0x99, 0x52, 0xf2, + 0x64, 0xc6, 0x80, 0x9a, 0xb2, 0x3e, 0x92, 0xd3, 0x05, 0x09, 0x8e, 0x15, 0x69, 0x82, 0x44, 0xc7, + 0x8b, 0xfb, 0xd0, 0x50, 0xc7, 0x27, 0xd1, 0xd9, 0x0f, 0x39, 0x14, 0xc8, 0xd3, 0xb7, 0x4d, 0x75, + 0x02, 0x94, 0x38, 0x69, 0xaf, 0x4c, 0x9d, 0xb4, 0xbf, 0x0f, 0x0b, 0x81, 0xa0, 0x5f, 0x6b, 0xe2, + 0x4a, 0xef, 0x1f, 0x3e, 0x40, 0x35, 0xab, 0x64, 0x36, 0x30, 0xe1, 0x28, 0x86, 0xcf, 0x9e, 0x6b, + 0xd4, 0x52, 0xce, 0x35, 0x9e, 0xc4, 0x86, 0xba, 0xe0, 0xcc, 0x19, 0xa1, 0xcc, 0x10, 0x7b, 0xca, + 0xc8, 0x01, 0xee, 0x9e, 0x39, 0x23, 0x53, 0x59, 0x85, 0xc5, 0x87, 0xf1, 0x7f, 0x32, 0xd0, 0x10, + 0x74, 0x90, 0x58, 0x62, 0xdf, 0x01, 0x64, 0x06, 0xaf, 0xb9, 0xc2, 0x2a, 0x02, 0x57, 0x2d, 0xb0, + 0x8f, 0x00, 0x57, 0x8c, 0x25, 0x74, 0x4a, 0xb9, 0xbe, 0x9a, 0xc9, 0xf5, 0x15, 0xf3, 0xd0, 0x9d, + 0x1b, 0xa4, 0x7b, 0x08, 0x08, 0xfb, 0x0e, 0x94, 0x05, 0x61, 0x22, 0x95, 0x48, 0x07, 0x2d, 0x25, + 0x79, 0xa5, 0xac, 0x11, 0x91, 0x75, 0x2c, 0x3f, 0xd3, 0x6c, 0xab, 0xf9, 0x14, 0xdb, 0xaa, 0xb6, + 0x80, 0x77, 0x00, 0x9e, 0xf1, 0xab, 0x5d, 0xaf, 0x8f, 0x1a, 0xef, 0x1d, 0x00, 0x41, 0xcb, 0x27, + 0xf6, 0xc8, 0x91, 0x07, 0x36, 0x05, 0xb3, 0xfc, 0x82, 0x5f, 0x6d, 0x23, 0x40, 0x4c, 0xa4, 0x48, + 0x8e, 0x57, 0x71, 0xc1, 0x2c, 0xbd, 0xe0, 0x57, 0xb4, 0x84, 0x2d, 0xa8, 0x3d, 0xe3, 0x57, 0x5b, + 0x9c, 0x84, 0x4c, 0xcf, 0x17, 0x44, 0xe4, 0xdb, 0x17, 0x42, 0xaa, 0x4c, 0xd8, 0x45, 0x2b, 0xbe, + 0x7d, 0xf1, 0x8c, 0x5f, 0x29, 0x1b, 0x6d, 0x51, 0xa4, 0x0f, 0xbd, 0xbe, 0xdc, 0x37, 0x95, 0x87, + 0x47, 0xdc, 0x28, 0x73, 0xee, 0x05, 0xfe, 0x36, 0xfe, 0x32, 0x03, 0x35, 0xd1, 0x7e, 0x64, 0xcb, + 0x62, 0xca, 0x94, 0xa3, 0x50, 0x26, 0x76, 0x14, 0x7a, 0x2c, 0xb9, 0x1a, 0xf1, 0xf8, 0xec, 0xf5, + 0x3c, 0x1e, 0xe7, 0x86, 0x18, 0xfc, 0x07, 0x50, 0xa6, 0x65, 0x29, 0xd6, 0x79, 0x2e, 0x31, 0xc1, + 0x89, 0x0e, 0x99, 0x25, 0x44, 0x7b, 0x46, 0x7e, 0x09, 0xda, 0xe1, 0x1f, 0x0d, 0x71, 0xd9, 0x8f, + 0x8e, 0xfc, 0x52, 0xa6, 0xa1, 0x70, 0x8d, 0x5f, 0x82, 0x7e, 0xb2, 0x36, 0x37, 0x73, 0xb2, 0x76, + 0x00, 0x25, 0x31, 0xd5, 0xd8, 0xd9, 0x94, 0x42, 0x33, 0x69, 0x85, 0x0a, 0x49, 0xc0, 0x16, 0x9b, + 0x82, 0x60, 0x74, 0x59, 0x29, 0x09, 0xd8, 0x01, 0x3f, 0x44, 0x66, 0x97, 0x81, 0x8a, 0xb6, 0x02, + 0xf0, 0x70, 0x32, 0x1a, 0x2f, 0x5a, 0x2e, 0x49, 0x12, 0x4f, 0x0c, 0xf8, 0xce, 0x0d, 0xb3, 0xd6, + 0x4f, 0xcc, 0xc0, 0xba, 0xa4, 0x55, 0xcc, 0x99, 0x4d, 0xf8, 0x34, 0xa9, 0x86, 0x2b, 0x02, 0x15, + 0xbf, 0x37, 0xe6, 0x20, 0x2f, 0x50, 0x8d, 0x4f, 0x60, 0x41, 0x6b, 0x06, 0xa9, 0xf9, 0xaf, 0xdb, + 0x43, 0xe3, 0xd7, 0xa2, 0xcc, 0xa2, 0x0e, 0x32, 0x1f, 0x29, 0x1f, 0x0f, 0x3e, 0xa0, 0x8e, 0x4b, + 0x5f, 0x12, 0x02, 0x09, 0xb4, 0xd7, 0xf6, 0x3b, 0xf8, 0x0d, 0x58, 0xd4, 0x4a, 0xdf, 0x76, 0x5c, + 0x7b, 0xe8, 0xfc, 0x08, 0x37, 0xfc, 0xc0, 0x39, 0x75, 0xa7, 0xca, 0x27, 0xd0, 0x57, 0x2a, 0xff, + 0x1f, 0x66, 0x61, 0x49, 0x56, 0x80, 0x5e, 0x7b, 0x8e, 0x90, 0xe2, 0xf6, 0x82, 0x53, 0xf6, 0x1d, + 0xa8, 0x89, 0xb1, 0xb1, 0x7c, 0x7e, 0xea, 0x04, 0x21, 0x57, 0x66, 0xab, 0x14, 0xc6, 0x25, 0x36, + 0x73, 0x81, 0x6a, 0x4a, 0x4c, 0xf6, 0x09, 0x54, 0x30, 0x2b, 0x1d, 0xa3, 0xc8, 0x89, 0x68, 0xce, + 0x66, 0xa4, 0x81, 0xde, 0xb9, 0x61, 0x42, 0x10, 0x0f, 0xfb, 0x27, 0x50, 0xc1, 0x39, 0x3c, 0xc7, + 0x81, 0x9c, 0x62, 0x55, 0x33, 0x03, 0x2d, 0x32, 0x8f, 0xe3, 0x61, 0x6f, 0x41, 0x8d, 0x98, 0x95, + 0x1c, 0x27, 0xe9, 0x0d, 0xb4, 0x36, 0x9b, 0x5d, 0x8d, 0xa4, 0x68, 0xfc, 0x58, 0xfb, 0xde, 0x28, + 0x43, 0x31, 0xf4, 0x9d, 0xd3, 0x53, 0xee, 0x1b, 0x2b, 0xd1, 0xd0, 0x08, 0x2e, 0xcc, 0xbb, 0x21, + 0x1f, 0x0b, 0xd9, 0xdc, 0xf8, 0xf7, 0x19, 0xa8, 0x48, 0xbe, 0xfa, 0x53, 0xdb, 0xca, 0xd6, 0x34, + 0xb7, 0x57, 0x3a, 0xb1, 0x89, 0xbd, 0x5c, 0xdf, 0x85, 0xf9, 0x91, 0x90, 0xd3, 0x85, 0x1e, 0x99, + 0x30, 0x94, 0xd5, 0x15, 0x58, 0x8a, 0xc9, 0xeb, 0xb0, 0x88, 0x52, 0x73, 0x60, 0x85, 0xce, 0xd0, + 0x52, 0x89, 0xd2, 0xc5, 0x74, 0x81, 0x92, 0x7a, 0xce, 0x70, 0x4f, 0x26, 0x08, 0xe1, 0x31, 0x08, + 0xed, 0x53, 0x2e, 0xd7, 0x36, 0x7d, 0x18, 0x4d, 0x58, 0x99, 0x52, 0x21, 0x95, 0xfa, 0xfb, 0x7f, + 0x17, 0x60, 0x75, 0x26, 0x49, 0xaa, 0xc1, 0x91, 0x81, 0x68, 0xe8, 0x8c, 0x8e, 0xbd, 0xe8, 0xf8, + 0x34, 0xa3, 0x19, 0x88, 0x76, 0x45, 0x8a, 0x3a, 0x3e, 0xe5, 0xb0, 0xac, 0x08, 0x12, 0xcf, 0x3f, + 0x23, 0x2d, 0x33, 0x8b, 0x3a, 0xd0, 0x07, 0xc9, 0x4d, 0x6c, 0xba, 0x3a, 0x05, 0xd7, 0x45, 0xa3, + 0xc5, 0xf1, 0x0c, 0x2c, 0x60, 0xbf, 0x09, 0xcd, 0x88, 0xee, 0xa5, 0xd8, 0xae, 0xa9, 0xcc, 0xa2, + 0xa6, 0xaf, 0xbf, 0xa2, 0xa6, 0xc4, 0xd9, 0x1d, 0xca, 0x4e, 0x2b, 0x6a, 0xc9, 0x50, 0x81, 0x51, + 0x5d, 0xe7, 0xf0, 0x86, 0xaa, 0x0b, 0xc5, 0xf0, 0xd9, 0x1a, 0xf3, 0xaf, 0xd5, 0x37, 0x3c, 0x97, + 0x4c, 0x54, 0x6b, 0xde, 0x92, 0x05, 0x47, 0x49, 0x7a, 0xbd, 0x67, 0xb0, 0x72, 0x61, 0x3b, 0xa1, + 0xea, 0xa3, 0xa6, 0xb1, 0x17, 0xb0, 0xbe, 0xc7, 0xaf, 0xa8, 0xef, 0x73, 0xca, 0x9c, 0x50, 0x4c, + 0x96, 0x2e, 0x66, 0x81, 0xc1, 0xda, 0x3f, 0xcb, 0x41, 0x3d, 0x59, 0x8a, 0x60, 0x2c, 0x72, 0xb3, + 0x51, 0xf2, 0xa6, 0x14, 0x82, 0xe5, 0xd1, 0xfe, 0x3e, 0xc9, 0x99, 0xb3, 0x46, 0x87, 0x6c, 0x8a, + 0xd1, 0x41, 0x3f, 0xeb, 0xcf, 0xbd, 0xca, 0xb8, 0x9a, 0x7f, 0x2d, 0xe3, 0x6a, 0x21, 0xcd, 0xb8, + 0x7a, 0xbd, 0x45, 0x6e, 0xee, 0xa7, 0xb2, 0xc8, 0x15, 0x5f, 0x6a, 0x91, 0xd3, 0xec, 0x88, 0xa5, + 0x6b, 0x4e, 0xe8, 0x35, 0xcb, 0x62, 0x8a, 0x45, 0xae, 0xfc, 0x15, 0x2c, 0x72, 0x6b, 0x7f, 0x99, + 0x01, 0x36, 0xbb, 0x3a, 0xd8, 0x53, 0xb2, 0xe7, 0xb8, 0x7c, 0x28, 0x39, 0xf7, 0x37, 0x5e, 0x6f, + 0x85, 0x29, 0x82, 0x50, 0xb9, 0xd9, 0x43, 0x58, 0xd4, 0x1d, 0xe1, 0x75, 0xad, 0xbd, 0x66, 0x32, + 0x3d, 0x29, 0x3e, 0xdb, 0xd1, 0x2c, 0xd9, 0xf9, 0x57, 0x5a, 0xb2, 0x0b, 0xaf, 0xb4, 0x64, 0xcf, + 0x25, 0x2d, 0xd9, 0x6b, 0xff, 0x39, 0x03, 0x8b, 0x29, 0x44, 0xfc, 0xf3, 0xeb, 0xb3, 0xa0, 0xbd, + 0x04, 0x5b, 0xcb, 0x4a, 0xda, 0xd3, 0x39, 0xda, 0x2e, 0x54, 0xe2, 0xa9, 0x50, 0x81, 0x22, 0x0f, + 0x5e, 0xc5, 0x5d, 0xe2, 0x1c, 0xa6, 0x9e, 0x7d, 0xed, 0xf7, 0xb3, 0x50, 0xd1, 0x12, 0xc5, 0x28, + 0x12, 0xc9, 0x6a, 0x0e, 0x44, 0x24, 0x19, 0xe2, 0x99, 0xc3, 0x5d, 0x90, 0x46, 0x0d, 0x4a, 0xa7, + 0xc5, 0x25, 0xc5, 0x40, 0x44, 0x58, 0x87, 0x45, 0x65, 0x6b, 0xe3, 0xb1, 0x9f, 0xa0, 0xdc, 0x6b, + 0x16, 0xa4, 0xc5, 0x8d, 0x47, 0x6e, 0x87, 0xec, 0xa1, 0x52, 0x07, 0xe3, 0xb9, 0x43, 0x52, 0x27, + 0x8b, 0xc1, 0x02, 0x2d, 0x10, 0x35, 0x89, 0x82, 0xce, 0x3f, 0x80, 0x65, 0xb5, 0x3c, 0x92, 0x39, + 0xc8, 0x88, 0xc0, 0xe4, 0xe2, 0xd0, 0xb3, 0x7c, 0x0f, 0xee, 0x4c, 0xb5, 0x69, 0x2a, 0x2b, 0x39, + 0xb4, 0xde, 0x4c, 0xb4, 0x4e, 0x2f, 0x61, 0xed, 0xc7, 0x50, 0x4b, 0x30, 0xca, 0x9f, 0xdf, 0x94, + 0x4f, 0x9f, 0xf3, 0xd0, 0x88, 0xea, 0xe7, 0x3c, 0x6b, 0xff, 0x3b, 0x07, 0x6c, 0x96, 0x57, 0xff, + 0x22, 0x9b, 0x30, 0x4b, 0x98, 0xb9, 0x14, 0xc2, 0xfc, 0xff, 0x26, 0x3f, 0xbc, 0x0f, 0x0b, 0x32, + 0x60, 0x4a, 0x33, 0x98, 0xd2, 0xe2, 0x6c, 0x44, 0x09, 0xaa, 0x15, 0x1f, 0x4d, 0x3b, 0x6e, 0x94, + 0x12, 0x31, 0x22, 0x9a, 0x00, 0x35, 0xe5, 0xbf, 0x71, 0x04, 0x73, 0xb6, 0xdb, 0x3f, 0xf3, 0x7c, + 0xc9, 0x07, 0x7f, 0xe9, 0x2b, 0x6f, 0x9f, 0xeb, 0x2d, 0xcc, 0x8f, 0x52, 0x9b, 0x29, 0x0b, 0x33, + 0x3e, 0x80, 0x8a, 0x06, 0x66, 0x65, 0x28, 0xec, 0x76, 0xf6, 0x36, 0x0e, 0x1a, 0x37, 0x58, 0x0d, + 0xca, 0x66, 0x7b, 0xf3, 0xe0, 0xb3, 0xb6, 0xd9, 0xde, 0x6a, 0x64, 0x58, 0x09, 0xf2, 0xbb, 0x07, + 0xdd, 0x5e, 0x23, 0x6b, 0xac, 0x41, 0x53, 0x96, 0x38, 0x6b, 0xb3, 0xf8, 0x9d, 0x7c, 0x74, 0x5c, + 0x88, 0x89, 0x52, 0x45, 0xff, 0x26, 0x54, 0x75, 0xf1, 0x46, 0x52, 0xc4, 0x94, 0xcd, 0x5e, 0x28, + 0xe7, 0x9e, 0xc6, 0xab, 0x37, 0x81, 0x2c, 0xb6, 0x83, 0x28, 0x5b, 0x36, 0x21, 0xb7, 0xa6, 0x58, + 0x07, 0x51, 0xf9, 0x49, 0x90, 0xe1, 0x5f, 0x81, 0x7a, 0xf2, 0x00, 0x5f, 0x72, 0xa4, 0x34, 0x85, + 0x53, 0xe4, 0x4e, 0x9c, 0xe8, 0xb3, 0xef, 0x41, 0x63, 0xda, 0x00, 0x20, 0x85, 0xe7, 0x6b, 0xf2, + 0xcf, 0x3b, 0x49, 0x9b, 0x00, 0xdb, 0x81, 0xa5, 0x34, 0x01, 0x0f, 0xe9, 0xe3, 0xfa, 0x43, 0x0a, + 0x36, 0x2b, 0xc4, 0xb1, 0x6f, 0x4b, 0x3b, 0x4f, 0x01, 0xa7, 0xff, 0xed, 0x64, 0xfd, 0xda, 0x60, + 0xaf, 0xd3, 0x3f, 0xcd, 0xe2, 0x73, 0x0e, 0x10, 0xc3, 0x58, 0x03, 0xaa, 0x07, 0x87, 0xed, 0x7d, + 0x6b, 0x73, 0xa7, 0xb5, 0xbf, 0xdf, 0xde, 0x6d, 0xdc, 0x60, 0x0c, 0xea, 0x68, 0xab, 0xde, 0x8a, + 0x60, 0x19, 0x01, 0x93, 0xf6, 0x36, 0x05, 0xcb, 0xb2, 0x25, 0x68, 0x74, 0xf6, 0xa7, 0xa0, 0x39, + 0xd6, 0x84, 0xa5, 0xc3, 0x36, 0x99, 0xb7, 0x13, 0xe5, 0xe6, 0x85, 0xd2, 0x20, 0xbb, 0x2b, 0x94, + 0x06, 0x0a, 0xfc, 0x93, 0xeb, 0x40, 0xc9, 0xd2, 0xbf, 0x9b, 0x81, 0xe5, 0xa9, 0x84, 0x38, 0x9c, + 0x83, 0x24, 0xe9, 0xa4, 0x0c, 0x5d, 0x45, 0xa0, 0x5a, 0x4d, 0xef, 0xc3, 0x42, 0x74, 0xf0, 0x34, + 0xb5, 0x2b, 0x35, 0xa2, 0x04, 0x85, 0xfc, 0x10, 0x16, 0xb5, 0xf3, 0xab, 0x29, 0x5e, 0xc1, 0xb4, + 0x24, 0x99, 0xc1, 0x58, 0x8d, 0xdc, 0xe6, 0xa7, 0x5a, 0x3d, 0xa0, 0x68, 0x42, 0x3d, 0x21, 0x36, + 0x83, 0x25, 0xdb, 0xab, 0x3e, 0xd9, 0xa3, 0x29, 0x42, 0x48, 0xb6, 0x56, 0x9f, 0x70, 0x55, 0xfd, + 0x1f, 0xcc, 0x01, 0xfb, 0x74, 0xc2, 0xfd, 0x2b, 0x0c, 0xd7, 0x08, 0x5e, 0xe5, 0xbf, 0xa8, 0x4e, + 0x5a, 0xb2, 0xaf, 0x15, 0x92, 0x95, 0x16, 0x12, 0x95, 0x7f, 0x75, 0x48, 0x54, 0xe1, 0x55, 0x21, + 0x51, 0x6f, 0x41, 0xcd, 0x39, 0x75, 0x3d, 0xc1, 0x0a, 0x85, 0x24, 0x1c, 0x34, 0xe7, 0xee, 0xe5, + 0xee, 0x57, 0xcd, 0xaa, 0x04, 0x0a, 0x39, 0x38, 0x60, 0x9f, 0xc4, 0x48, 0x7c, 0x70, 0x8a, 0xe1, + 0x7b, 0x3a, 0x13, 0x6c, 0x0f, 0x4e, 0xb9, 0x3c, 0x58, 0x42, 0x4d, 0x43, 0x65, 0x16, 0xf0, 0x80, + 0xbd, 0x0d, 0xf5, 0xc0, 0x9b, 0x08, 0xc5, 0x42, 0x0d, 0x03, 0x19, 0xca, 0xaa, 0x04, 0x3d, 0x54, + 0x56, 0xd1, 0xc5, 0x49, 0xc0, 0xad, 0x91, 0x13, 0x04, 0x42, 0x3c, 0xeb, 0x7b, 0x6e, 0xe8, 0x7b, + 0x43, 0x69, 0xfb, 0x5a, 0x98, 0x04, 0x7c, 0x8f, 0x52, 0x36, 0x29, 0x81, 0x7d, 0x2b, 0x6e, 0xd2, + 0xd8, 0x76, 0xfc, 0xa0, 0x09, 0xd8, 0x24, 0xd5, 0x53, 0x94, 0xdf, 0x6d, 0xc7, 0x8f, 0xda, 0x22, + 0x3e, 0x82, 0xa9, 0x50, 0xad, 0xca, 0x74, 0xa8, 0xd6, 0x0f, 0xd3, 0x43, 0xb5, 0x6a, 0x58, 0xf4, + 0x23, 0x59, 0xf4, 0xec, 0x14, 0x7f, 0xa5, 0x88, 0xad, 0xd9, 0x08, 0xb4, 0xfa, 0x57, 0x89, 0x40, + 0x9b, 0x4f, 0x8b, 0x40, 0xfb, 0x00, 0x2a, 0x18, 0x1b, 0x64, 0x9d, 0x39, 0x42, 0x86, 0x23, 0x5b, + 0x5e, 0x43, 0x0f, 0x1e, 0xda, 0x71, 0xdc, 0xd0, 0x04, 0x5f, 0xfd, 0x0c, 0x66, 0x83, 0xc1, 0x16, + 0x7e, 0x81, 0xc1, 0x60, 0x32, 0x86, 0x69, 0x1d, 0x4a, 0x6a, 0x9e, 0x18, 0x83, 0xfc, 0x89, 0xef, + 0x8d, 0x94, 0x8d, 0x43, 0xfc, 0x66, 0x75, 0xc8, 0x86, 0x9e, 0xcc, 0x9c, 0x0d, 0x3d, 0xe3, 0xd7, + 0xa1, 0xa2, 0x91, 0x1a, 0x7b, 0x93, 0xce, 0x25, 0x85, 0x6e, 0x26, 0x65, 0x4b, 0x1a, 0xc5, 0xb2, + 0x84, 0x76, 0x06, 0x82, 0xdf, 0x0c, 0x1c, 0x9f, 0x63, 0xd8, 0xa6, 0xe5, 0xf3, 0x73, 0xee, 0x07, + 0xca, 0xe6, 0xd4, 0x88, 0x12, 0x4c, 0x82, 0x1b, 0xbf, 0x01, 0x8b, 0x89, 0xb9, 0x95, 0x2c, 0xe2, + 0x6d, 0x98, 0xc3, 0x71, 0x53, 0x3e, 0x01, 0xc9, 0xa0, 0x2c, 0x99, 0x86, 0xf1, 0xf8, 0x64, 0x2e, + 0xb3, 0xc6, 0xbe, 0x77, 0x8c, 0x95, 0x64, 0xcc, 0x8a, 0x84, 0x1d, 0xfa, 0xde, 0xb1, 0xf1, 0x67, + 0x39, 0xc8, 0xed, 0x78, 0x63, 0xdd, 0x47, 0x2d, 0x33, 0xe3, 0xa3, 0x26, 0x15, 0x4e, 0x2b, 0x52, + 0x28, 0xa5, 0xcc, 0x8e, 0x86, 0x22, 0xa5, 0x54, 0xde, 0x87, 0xba, 0xe0, 0x13, 0xa1, 0x27, 0x34, + 0xf6, 0x0b, 0xdb, 0x27, 0x81, 0x38, 0x47, 0x8b, 0xcf, 0x1e, 0x85, 0x3d, 0x6f, 0x9b, 0xe0, 0x6c, + 0x09, 0x72, 0x91, 0xfa, 0x82, 0xc9, 0xe2, 0x93, 0xad, 0xc0, 0x1c, 0x3a, 0x2b, 0x5f, 0x49, 0xa3, + 0xb7, 0xfc, 0x62, 0xdf, 0x80, 0xc5, 0x64, 0xb9, 0xc4, 0x8a, 0xa4, 0x6c, 0xa4, 0x17, 0x8c, 0x3c, + 0xe9, 0x26, 0x08, 0x3e, 0x42, 0x38, 0xd2, 0x77, 0xe6, 0x84, 0x73, 0x4c, 0xd2, 0x98, 0x5e, 0x29, + 0xc1, 0xf4, 0xee, 0x42, 0x25, 0x1c, 0x9e, 0x5b, 0x63, 0xfb, 0x6a, 0xe8, 0xd9, 0x03, 0xb9, 0xbe, + 0x21, 0x1c, 0x9e, 0x1f, 0x12, 0x84, 0x3d, 0x04, 0x18, 0x8d, 0xc7, 0x72, 0xed, 0xa1, 0xf1, 0x23, + 0x26, 0xe5, 0xbd, 0xc3, 0x43, 0x22, 0x39, 0xb3, 0x3c, 0x1a, 0x8f, 0xe9, 0x27, 0xdb, 0x82, 0x7a, + 0x6a, 0x68, 0xe5, 0x1d, 0xe5, 0x5b, 0xeb, 0x8d, 0xd7, 0x53, 0x16, 0x67, 0xad, 0xaf, 0xc3, 0xd6, + 0xbe, 0x07, 0xec, 0x67, 0x0c, 0x70, 0xec, 0x41, 0x39, 0x6a, 0x9f, 0x1e, 0x1f, 0x88, 0xde, 0xf2, + 0x95, 0x44, 0x7c, 0x60, 0x6b, 0x30, 0xf0, 0x05, 0x5f, 0xa4, 0x0d, 0x33, 0x62, 0xf9, 0xa0, 0xed, + 0x98, 0x2d, 0xe2, 0xfb, 0xc6, 0x7f, 0xcb, 0x40, 0x81, 0x82, 0x15, 0xdf, 0x81, 0x79, 0xc2, 0x8f, + 0xfc, 0xfd, 0xa4, 0xa9, 0x9c, 0xf6, 0xdd, 0x9e, 0x74, 0xf5, 0x13, 0xcb, 0x42, 0x0b, 0xb4, 0xce, + 0x46, 0x33, 0xaf, 0x05, 0x5b, 0xdf, 0x85, 0x72, 0x54, 0xb5, 0x46, 0x3a, 0x25, 0x55, 0x33, 0x7b, + 0x03, 0xf2, 0x67, 0xde, 0x58, 0x9d, 0xfc, 0x40, 0x3c, 0x92, 0x26, 0xc2, 0xe3, 0xb6, 0x88, 0x3a, + 0xa8, 0xf1, 0xf2, 0xc4, 0x22, 0xaa, 0x04, 0xc9, 0x60, 0xb6, 0x8f, 0x73, 0x29, 0x7d, 0x3c, 0x82, + 0x79, 0xc1, 0x07, 0x34, 0x97, 0x95, 0xeb, 0x37, 0xcd, 0xf7, 0x84, 0x84, 0xd7, 0x1f, 0x4e, 0x06, + 0x5c, 0x3f, 0x7b, 0x43, 0xff, 0x36, 0x09, 0x57, 0x92, 0xb5, 0xf1, 0x07, 0x19, 0xe2, 0x2f, 0xa2, + 0x5c, 0x76, 0x1f, 0xf2, 0x62, 0x7f, 0x9b, 0x3a, 0x89, 0x8f, 0xc2, 0x16, 0x04, 0x9e, 0x89, 0x18, + 0x78, 0x3b, 0xc1, 0x64, 0x94, 0x2c, 0xbd, 0x66, 0x56, 0xdc, 0xc9, 0x28, 0x3a, 0xba, 0xfa, 0x9a, + 0xea, 0xd6, 0xd4, 0xb1, 0x0f, 0xf5, 0x3e, 0x5a, 0xa6, 0xeb, 0x9a, 0xa3, 0x5c, 0x3e, 0xb1, 0x63, + 0x2a, 0x29, 0x70, 0x70, 0xca, 0x35, 0x07, 0xb9, 0x3f, 0xca, 0x42, 0x2d, 0xd1, 0x22, 0xf4, 0x14, + 0x14, 0x1b, 0x00, 0x19, 0x96, 0xe4, 0x7c, 0x83, 0x00, 0x49, 0x41, 0x5d, 0x1b, 0xa7, 0x6c, 0x62, + 0x9c, 0x22, 0xe7, 0x9c, 0x9c, 0xee, 0x9c, 0xf3, 0x08, 0xca, 0x71, 0x80, 0x7d, 0xb2, 0x49, 0xa2, + 0x3e, 0x15, 0xbc, 0x11, 0x23, 0xc5, 0xee, 0x3c, 0x05, 0xdd, 0x9d, 0xe7, 0xbb, 0x9a, 0xf7, 0xc7, + 0x1c, 0x16, 0x63, 0xa4, 0x8d, 0xe8, 0x2f, 0xc4, 0xf7, 0xc3, 0xf8, 0x04, 0x2a, 0x5a, 0xe3, 0x75, + 0x2f, 0x8f, 0x4c, 0xc2, 0xcb, 0x23, 0x0a, 0xb3, 0xca, 0xc6, 0x61, 0x56, 0xc6, 0xdf, 0xcc, 0x42, + 0x4d, 0xac, 0x2f, 0xc7, 0x3d, 0x3d, 0xf4, 0x86, 0x4e, 0x1f, 0x0d, 0x4d, 0xd1, 0x0a, 0x93, 0x82, + 0x96, 0x5a, 0x67, 0x72, 0x89, 0x91, 0x9c, 0xa5, 0x47, 0x93, 0x12, 0x93, 0x8e, 0xa2, 0x49, 0x0d, + 0xa8, 0x09, 0xc6, 0x88, 0x26, 0xa3, 0x38, 0xfc, 0xdf, 0xac, 0x9c, 0x70, 0xbe, 0x61, 0x07, 0xc4, + 0x21, 0xbf, 0x01, 0x8b, 0x02, 0x07, 0x03, 0xe9, 0x46, 0xce, 0x70, 0xe8, 0x10, 0x26, 0x1d, 0x34, + 0x35, 0x4e, 0x38, 0x37, 0xed, 0x90, 0xef, 0x89, 0x04, 0x79, 0x5b, 0x40, 0x69, 0xe0, 0x04, 0xf6, + 0x71, 0xec, 0xcf, 0x19, 0x7d, 0xa3, 0x65, 0xd9, 0xbe, 0xd4, 0x2c, 0xcb, 0x74, 0x00, 0x51, 0x19, + 0xd9, 0x97, 0x91, 0x65, 0x79, 0x8a, 0x92, 0x8a, 0xd3, 0x94, 0x64, 0xfc, 0xbb, 0x2c, 0x54, 0x34, + 0xb2, 0x7c, 0x9d, 0xdd, 0xf5, 0xce, 0x8c, 0x61, 0xb0, 0xac, 0xdb, 0x00, 0xdf, 0x4a, 0x56, 0x89, + 0xbe, 0x2f, 0x74, 0x2f, 0x81, 0x46, 0xc0, 0xb7, 0xa0, 0x2c, 0x56, 0xdd, 0x07, 0x78, 0x04, 0x2b, + 0x6f, 0xd5, 0x40, 0xc0, 0xe1, 0xe4, 0x58, 0x25, 0x3e, 0xc6, 0xc4, 0x42, 0x9c, 0xf8, 0x58, 0x24, + 0xbe, 0xcc, 0xc3, 0xfa, 0x23, 0xa8, 0xca, 0x52, 0x71, 0x4e, 0xb1, 0xbb, 0xf1, 0xaa, 0x4f, 0xcc, + 0xb7, 0x59, 0xa1, 0xea, 0x68, 0xf2, 0x65, 0xc6, 0xc7, 0x2a, 0x63, 0xe9, 0x55, 0x19, 0x1f, 0xd3, + 0x87, 0xb1, 0x1d, 0x39, 0xad, 0xa3, 0xdf, 0x95, 0xe2, 0x63, 0x0f, 0x61, 0x51, 0xb1, 0xab, 0x89, + 0x6b, 0xbb, 0xae, 0x37, 0x71, 0xfb, 0x5c, 0xc5, 0x5f, 0x31, 0x99, 0x74, 0x14, 0xa7, 0x18, 0x83, + 0x28, 0x40, 0x97, 0xfc, 0xb7, 0x1e, 0x40, 0x81, 0xe4, 0x72, 0x12, 0x3e, 0xd2, 0x19, 0x17, 0xa1, + 0xb0, 0xfb, 0x50, 0x20, 0xf1, 0x3c, 0x7b, 0x2d, 0xb3, 0x21, 0x04, 0xa3, 0x05, 0x4c, 0x64, 0xdc, + 0xe3, 0xa1, 0xef, 0xf4, 0x83, 0x38, 0xb4, 0xab, 0x20, 0xf4, 0x4f, 0xaa, 0x2b, 0x3e, 0xb9, 0x8d, + 0x31, 0x51, 0x47, 0x25, 0x1c, 0xb1, 0x31, 0x2d, 0x26, 0xca, 0x90, 0xe2, 0xd2, 0x10, 0x56, 0x8e, + 0x79, 0x78, 0xc1, 0xb9, 0xeb, 0x0a, 0x61, 0xa8, 0xcf, 0xdd, 0xd0, 0xb7, 0x87, 0x62, 0x92, 0xa8, + 0x07, 0x4f, 0x66, 0x4a, 0x8d, 0xcf, 0x40, 0x36, 0xe2, 0x8c, 0x9b, 0x51, 0x3e, 0xe2, 0x1d, 0xcb, + 0xc7, 0x69, 0x69, 0x6b, 0xbf, 0x06, 0x6b, 0xd7, 0x67, 0x4a, 0x09, 0xe0, 0xbc, 0x9f, 0xe4, 0x2a, + 0x91, 0x1d, 0x70, 0xe8, 0xd9, 0x21, 0xb5, 0x46, 0xe7, 0x2c, 0xfb, 0x50, 0xd1, 0x52, 0xe2, 0xbd, + 0x3f, 0x83, 0xc2, 0x1d, 0x7d, 0x88, 0x1d, 0xc9, 0xf5, 0xfc, 0x11, 0xda, 0xdd, 0x06, 0x56, 0x5c, + 0x7a, 0xc6, 0x9c, 0x8f, 0xe1, 0x18, 0xb1, 0x6e, 0xac, 0xc3, 0x3c, 0x4a, 0xf6, 0xda, 0x46, 0xf7, + 0x32, 0x61, 0xd0, 0x58, 0x02, 0xb6, 0x4f, 0xbc, 0x4b, 0x77, 0xe7, 0xfc, 0x2f, 0x39, 0xa8, 0x68, + 0x60, 0xb1, 0x1b, 0xa1, 0x03, 0xa0, 0x35, 0x70, 0xec, 0x11, 0x57, 0x46, 0xce, 0x9a, 0x59, 0x43, + 0xe8, 0x96, 0x04, 0x8a, 0xbd, 0xd8, 0x3e, 0x3f, 0xb5, 0xbc, 0x49, 0x68, 0x0d, 0xf8, 0xa9, 0xcf, + 0x55, 0x2b, 0xab, 0xf6, 0xf9, 0xe9, 0xc1, 0x24, 0xdc, 0x42, 0x98, 0xc0, 0x12, 0xbc, 0x44, 0xc3, + 0x92, 0x3e, 0x6b, 0x23, 0xfb, 0x32, 0xc6, 0x92, 0x8e, 0x93, 0x44, 0x99, 0xf9, 0xc8, 0x71, 0x92, + 0xb4, 0xc5, 0xe9, 0x0d, 0xb4, 0x30, 0xbb, 0x81, 0x7e, 0x0b, 0x56, 0x68, 0x03, 0x95, 0xac, 0xd9, + 0x9a, 0x5a, 0xc9, 0x4b, 0x98, 0x2a, 0x3b, 0xa9, 0x89, 0xbd, 0x0d, 0xd1, 0x03, 0xc5, 0x96, 0x02, + 0xe7, 0x47, 0xc4, 0xc8, 0x32, 0xa6, 0xe8, 0x99, 0x2c, 0xbc, 0xeb, 0xfc, 0x88, 0x0b, 0x4c, 0xf4, + 0x8e, 0xd1, 0x31, 0x65, 0xfc, 0xc4, 0xc8, 0x71, 0xa7, 0x31, 0xed, 0xcb, 0x24, 0x66, 0x59, 0x62, + 0xda, 0x97, 0x3a, 0xe6, 0x13, 0x58, 0x1d, 0xf1, 0x81, 0x63, 0x27, 0x8b, 0xb5, 0x62, 0xc1, 0x6d, + 0x89, 0x92, 0xb5, 0x3c, 0x5d, 0x52, 0xdc, 0xc5, 0x68, 0xfc, 0xc8, 0x1b, 0x1d, 0x3b, 0x24, 0xb3, + 0x90, 0xbf, 0x4e, 0xde, 0xac, 0xbb, 0x93, 0xd1, 0x0f, 0x10, 0x2c, 0xb2, 0x04, 0x46, 0x0d, 0x2a, + 0xdd, 0xd0, 0x1b, 0xab, 0x69, 0xae, 0x43, 0x95, 0x3e, 0x65, 0x50, 0xe3, 0x2d, 0xb8, 0x89, 0x2c, + 0xa1, 0xe7, 0x8d, 0xbd, 0xa1, 0x77, 0x7a, 0x95, 0x38, 0xc7, 0xfb, 0x0f, 0x19, 0x58, 0x4c, 0xa4, + 0x4a, 0xf6, 0xfa, 0x2d, 0xe2, 0x67, 0x51, 0x64, 0x1a, 0xad, 0xc1, 0x05, 0x6d, 0x0d, 0x12, 0x22, + 0x31, 0x33, 0x15, 0xad, 0xd6, 0x8a, 0x6f, 0x54, 0x50, 0x19, 0x89, 0xa5, 0x34, 0x67, 0x59, 0x8a, + 0xcc, 0xaf, 0xee, 0x5a, 0x50, 0x45, 0xfc, 0x92, 0x8c, 0x71, 0x19, 0xc8, 0x2e, 0xe7, 0x92, 0x81, + 0x02, 0xfa, 0x99, 0x9f, 0x6a, 0x41, 0x7c, 0x10, 0x18, 0x18, 0xff, 0x3c, 0x03, 0x10, 0xb7, 0x0e, + 0x43, 0x15, 0x22, 0xb9, 0x85, 0x2e, 0x2b, 0xd3, 0x64, 0x94, 0x37, 0xa1, 0x1a, 0x79, 0x2c, 0xc7, + 0x92, 0x50, 0x45, 0xc1, 0x84, 0x38, 0xf4, 0x2e, 0xcc, 0x9f, 0x0e, 0xbd, 0x63, 0x94, 0x58, 0xa5, + 0xdc, 0x42, 0xfe, 0x6a, 0x75, 0x02, 0x2b, 0x69, 0x24, 0x96, 0x9b, 0xf2, 0xa9, 0x4e, 0xcd, 0xba, + 0x14, 0x64, 0xfc, 0x76, 0x36, 0x72, 0xdd, 0x8c, 0x47, 0xe2, 0xe5, 0xea, 0xdd, 0x4f, 0xe3, 0x4b, + 0xf3, 0x32, 0xf3, 0xe2, 0x27, 0x50, 0xf7, 0x69, 0x53, 0x52, 0x3b, 0x56, 0xfe, 0x25, 0x3b, 0x56, + 0xcd, 0x4f, 0x48, 0x3a, 0xef, 0x41, 0xc3, 0x1e, 0x9c, 0x73, 0x3f, 0x74, 0xf0, 0xb4, 0x1e, 0xe5, + 0x63, 0xe9, 0x2c, 0xa9, 0xc1, 0x51, 0x10, 0x7d, 0x17, 0xe6, 0x65, 0xa0, 0x6d, 0x84, 0x29, 0xaf, + 0xee, 0x89, 0xc1, 0x02, 0xd1, 0xf8, 0x97, 0xca, 0x57, 0x34, 0x39, 0xbb, 0x2f, 0x1f, 0x15, 0xbd, + 0x87, 0xd9, 0x59, 0x03, 0xaa, 0x24, 0x24, 0x69, 0x04, 0x90, 0xfc, 0x88, 0x80, 0xd2, 0x04, 0x90, + 0x1c, 0xd6, 0xfc, 0xeb, 0x0c, 0xab, 0xf1, 0x9f, 0x32, 0x50, 0xdc, 0xf1, 0xc6, 0x3b, 0x0e, 0x39, + 0xeb, 0xe3, 0x32, 0x89, 0x6c, 0x54, 0x73, 0xe2, 0x13, 0x1d, 0x7f, 0x5e, 0x12, 0x4f, 0x96, 0x2a, + 0xe6, 0xd5, 0x92, 0x62, 0xde, 0x77, 0xe1, 0x16, 0x9a, 0x00, 0x7d, 0x6f, 0xec, 0xf9, 0x62, 0xa9, + 0xda, 0x43, 0x12, 0xf7, 0x3c, 0x37, 0x3c, 0x53, 0xbc, 0xf3, 0xe6, 0x09, 0xe7, 0x87, 0x1a, 0xc6, + 0x5e, 0x84, 0x80, 0x11, 0x9b, 0xc3, 0xf0, 0xdc, 0x22, 0x0d, 0x5d, 0xca, 0xa3, 0xc4, 0x51, 0xe7, + 0x45, 0x42, 0x1b, 0xe1, 0x28, 0x91, 0x1a, 0xdf, 0x86, 0x72, 0x74, 0xd8, 0xc3, 0xde, 0x87, 0xf2, + 0x99, 0x37, 0x96, 0x27, 0x42, 0x99, 0x44, 0xcc, 0x9d, 0xec, 0xb5, 0x59, 0x3a, 0xa3, 0x1f, 0x81, + 0xf1, 0x67, 0x45, 0x28, 0x76, 0xdc, 0x73, 0xcf, 0xe9, 0xa3, 0xb7, 0xe9, 0x88, 0x8f, 0x3c, 0x15, + 0xed, 0x2f, 0x7e, 0xa3, 0x6f, 0x56, 0x7c, 0x01, 0x4f, 0x4e, 0xfa, 0x66, 0x45, 0x57, 0xef, 0x2c, + 0xc3, 0x9c, 0xaf, 0xdf, 0xa0, 0x53, 0xf0, 0xd1, 0xff, 0x3d, 0xda, 0x2f, 0x0b, 0xda, 0x6d, 0x09, + 0xa2, 0x2c, 0xba, 0xd9, 0x05, 0x87, 0x8c, 0xa2, 0x2f, 0xcb, 0x08, 0xc1, 0x01, 0xbb, 0x0d, 0x45, + 0x19, 0xe2, 0x46, 0x31, 0x49, 0xe4, 0xb0, 0x2e, 0x41, 0x48, 0x0d, 0x3e, 0x27, 0x13, 0x6e, 0x24, + 0xc8, 0xe6, 0xcc, 0xaa, 0x02, 0x6e, 0x09, 0x5a, 0xbb, 0x0b, 0x15, 0xc2, 0x27, 0x94, 0x92, 0x74, + 0xd2, 0x44, 0x10, 0x22, 0xa4, 0x5c, 0x44, 0x55, 0x4e, 0xbd, 0x88, 0x0a, 0xdd, 0x89, 0x23, 0x2e, + 0x4b, 0x5d, 0x04, 0xba, 0x7e, 0x48, 0x83, 0xab, 0x5b, 0xd8, 0xe4, 0x99, 0x0a, 0x05, 0x23, 0xab, + 0x33, 0x95, 0xb7, 0xa0, 0x76, 0x62, 0x0f, 0x87, 0xc7, 0x76, 0xff, 0x05, 0x1d, 0x05, 0x54, 0xe9, + 0xf4, 0x53, 0x01, 0xf1, 0x2c, 0xe0, 0x2e, 0x54, 0xb4, 0x59, 0x46, 0x0f, 0xcc, 0xbc, 0x09, 0xf1, + 0xfc, 0x4e, 0x9f, 0xf0, 0xd5, 0x5f, 0xe3, 0x84, 0x4f, 0xf3, 0x44, 0x9d, 0x4f, 0x7a, 0xa2, 0xde, + 0x42, 0x6e, 0x2a, 0x5d, 0x0e, 0x1b, 0x74, 0xd7, 0x8d, 0x3d, 0x18, 0xa0, 0xcb, 0x21, 0x5d, 0x2c, + 0x89, 0x83, 0x47, 0xe9, 0x0b, 0xa4, 0x4b, 0x10, 0x8c, 0x50, 0xee, 0xd0, 0x31, 0xf5, 0xd8, 0x76, + 0x06, 0x18, 0x74, 0x40, 0xa7, 0x07, 0x45, 0x7b, 0x14, 0x1e, 0xda, 0xce, 0x80, 0xdd, 0x83, 0xaa, + 0x4a, 0xc6, 0xdd, 0x71, 0x91, 0xc6, 0x5f, 0x26, 0x8b, 0x3d, 0xd1, 0x80, 0x5a, 0x84, 0x31, 0x8a, + 0x23, 0x8a, 0x2b, 0x12, 0x05, 0xe9, 0xe0, 0x03, 0xf4, 0xf2, 0x09, 0x39, 0xc6, 0x0d, 0xd7, 0x1f, + 0xdf, 0x8a, 0x9c, 0x0f, 0x90, 0x4a, 0xd5, 0x7f, 0x32, 0x8e, 0x11, 0xa6, 0x10, 0xee, 0xc8, 0x46, + 0xb7, 0x92, 0x90, 0x7f, 0x25, 0x2a, 0xda, 0xe8, 0x08, 0x81, 0x7d, 0x5b, 0xd3, 0x5f, 0x9b, 0x88, + 0x7c, 0x7b, 0xaa, 0xfc, 0xeb, 0x62, 0xae, 0xee, 0x00, 0x38, 0x81, 0xd8, 0x65, 0x02, 0xee, 0x0e, + 0x30, 0x04, 0xb8, 0x64, 0x96, 0x9d, 0xe0, 0x19, 0x01, 0x7e, 0xbe, 0x8a, 0x6d, 0x0b, 0xaa, 0x7a, + 0x37, 0x59, 0x09, 0xf2, 0x07, 0x87, 0xed, 0xfd, 0xc6, 0x0d, 0x56, 0x81, 0x62, 0xb7, 0xdd, 0xeb, + 0xed, 0xa2, 0xa5, 0xaf, 0x0a, 0xa5, 0x28, 0x4e, 0x31, 0x2b, 0xbe, 0x5a, 0x9b, 0x9b, 0xed, 0xc3, + 0x5e, 0x7b, 0xab, 0x91, 0xfb, 0x7e, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0x3f, 0xcf, 0x41, 0x45, 0x1b, + 0x85, 0x97, 0x33, 0xe3, 0x3b, 0x00, 0xa8, 0x49, 0xc6, 0x1e, 0xa9, 0x79, 0xb3, 0x2c, 0x20, 0x34, + 0xf9, 0xba, 0x8d, 0x22, 0x47, 0x97, 0x28, 0x29, 0x1b, 0xc5, 0x5b, 0x50, 0xa3, 0xfb, 0x88, 0x74, + 0x7b, 0x6d, 0xc1, 0xac, 0x12, 0x50, 0xb2, 0x6a, 0x0c, 0x60, 0x46, 0x24, 0x8c, 0x9e, 0x93, 0xb7, + 0x93, 0x10, 0x08, 0xe3, 0xe7, 0x30, 0xf8, 0x31, 0xf0, 0x86, 0xe7, 0x9c, 0x30, 0x48, 0x22, 0xac, + 0x48, 0x58, 0x4f, 0x86, 0x62, 0x4b, 0x7e, 0xa8, 0x45, 0xd0, 0x16, 0xcc, 0x2a, 0x01, 0x65, 0x45, + 0xdf, 0x50, 0x04, 0x44, 0xde, 0x2b, 0xab, 0xb3, 0xd4, 0x90, 0x20, 0x9e, 0xdd, 0x99, 0x63, 0xc4, + 0x32, 0x12, 0xc6, 0xd7, 0x66, 0xf3, 0xbd, 0xfa, 0x38, 0x91, 0xbd, 0x0f, 0x6c, 0x34, 0x1e, 0x5b, + 0x29, 0x07, 0x7c, 0x79, 0x73, 0x7e, 0x34, 0x1e, 0xf7, 0xb4, 0xf3, 0xaf, 0x9f, 0xc3, 0xd9, 0xe3, + 0x17, 0xc0, 0x5a, 0x62, 0x01, 0x63, 0x13, 0x23, 0x55, 0x2c, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, + 0x70, 0xbf, 0x6c, 0x2a, 0xf7, 0x7b, 0x19, 0x9f, 0x30, 0xb6, 0xa1, 0x72, 0xa8, 0xdd, 0x76, 0x76, + 0x4f, 0xec, 0x10, 0xea, 0x9e, 0x33, 0xda, 0x3b, 0xe8, 0x4c, 0xd1, 0x97, 0xd7, 0x9b, 0x69, 0xad, + 0xc9, 0x6a, 0xad, 0x31, 0xfe, 0x69, 0x86, 0x6e, 0x92, 0x89, 0x1a, 0x1f, 0x5f, 0xb0, 0xa6, 0xcc, + 0x6f, 0x71, 0xa0, 0x7b, 0x45, 0x99, 0xdd, 0x64, 0x8c, 0x3a, 0x36, 0xcd, 0xf2, 0x4e, 0x4e, 0x02, + 0xae, 0x7c, 0x3c, 0x2a, 0x08, 0x3b, 0x40, 0x90, 0x12, 0xbe, 0x85, 0x84, 0xef, 0x50, 0xf9, 0x81, + 0x74, 0xec, 0x10, 0xc2, 0xf7, 0x9e, 0x7d, 0x29, 0x6b, 0x0d, 0x84, 0x08, 0x22, 0xed, 0x03, 0x2a, + 0x16, 0x36, 0xfa, 0x36, 0xfe, 0x91, 0x8c, 0xc5, 0x9f, 0x1e, 0xdf, 0x07, 0x50, 0x8a, 0x4a, 0x4d, + 0xee, 0xb0, 0x0a, 0x33, 0x4a, 0x17, 0xfb, 0x38, 0x1e, 0x86, 0x24, 0x5a, 0x4c, 0x8b, 0x0b, 0x6d, + 0x3c, 0x1d, 0xad, 0xd5, 0x5f, 0x07, 0x76, 0xe2, 0xf8, 0xd3, 0xc8, 0xb4, 0xd8, 0x1a, 0x98, 0xa2, + 0x61, 0x1b, 0x47, 0xb0, 0xa8, 0xb8, 0x84, 0xa6, 0x11, 0x24, 0x27, 0x2f, 0xf3, 0x0a, 0x26, 0x9f, + 0x9d, 0x61, 0xf2, 0xc6, 0x4f, 0xf2, 0x50, 0x54, 0x37, 0x07, 0xa6, 0xdd, 0x76, 0x57, 0x4e, 0xde, + 0x76, 0xd7, 0x4c, 0xdc, 0x8c, 0x84, 0x53, 0x2f, 0xf7, 0xfb, 0x77, 0xa7, 0xb7, 0x6c, 0xcd, 0x56, + 0x91, 0xd8, 0xb6, 0x57, 0x20, 0x3f, 0xb6, 0xc3, 0x33, 0x3c, 0x97, 0x24, 0xe2, 0xc1, 0x6f, 0x65, + 0xc3, 0x28, 0x24, 0x6d, 0x18, 0x69, 0x37, 0x03, 0x92, 0x48, 0x3a, 0x73, 0x33, 0xe0, 0x2d, 0x20, + 0xf9, 0x42, 0x73, 0x7a, 0x2b, 0x21, 0x40, 0xec, 0x45, 0x49, 0x71, 0xa4, 0x34, 0x2d, 0x8e, 0xbc, + 0xb6, 0xa8, 0xf0, 0x2d, 0x98, 0xa3, 0x5b, 0x35, 0x64, 0xcc, 0xaf, 0xda, 0x50, 0xe4, 0x18, 0xaa, + 0xff, 0x14, 0x09, 0x61, 0x4a, 0x5c, 0xfd, 0x9a, 0xad, 0x4a, 0xe2, 0x9a, 0x2d, 0xdd, 0xb6, 0x52, + 0x4d, 0xda, 0x56, 0xee, 0x43, 0x23, 0x1a, 0x50, 0x3c, 0xa9, 0x74, 0x03, 0x19, 0x51, 0x58, 0x57, + 0x70, 0xc1, 0x25, 0xf7, 0x83, 0x78, 0x43, 0xac, 0x27, 0x36, 0x44, 0xc1, 0xc3, 0x5a, 0x61, 0xc8, + 0x47, 0xe3, 0x50, 0x6e, 0x88, 0x18, 0x73, 0xa4, 0x37, 0x50, 0xec, 0x30, 0x32, 0xa2, 0x97, 0x5c, + 0x4b, 0x3a, 0xfb, 0xd6, 0xf6, 0x6e, 0xe7, 0xe9, 0x4e, 0xaf, 0x91, 0x11, 0x9f, 0xdd, 0xa3, 0xcd, + 0xcd, 0x76, 0x7b, 0x0b, 0x77, 0x1c, 0x80, 0xb9, 0xed, 0x56, 0x47, 0xec, 0x3e, 0x39, 0xe3, 0x77, + 0xb3, 0x50, 0xd1, 0x8a, 0x67, 0x4f, 0xa2, 0x51, 0xa1, 0x9b, 0x98, 0xee, 0xcc, 0x36, 0x61, 0x5d, + 0xb1, 0x62, 0x6d, 0x58, 0xa2, 0x7b, 0x10, 0xb3, 0xd7, 0xde, 0x83, 0xc8, 0xde, 0x81, 0x79, 0x9b, + 0x4a, 0x88, 0x46, 0x41, 0x9e, 0xc2, 0x4b, 0xb0, 0x1c, 0x04, 0x74, 0xf5, 0x8c, 0xf7, 0x13, 0x81, + 0x97, 0x57, 0xde, 0x95, 0xd1, 0x96, 0x82, 0x83, 0x55, 0x3c, 0xb1, 0x9d, 0xe1, 0xc4, 0xe7, 0xd2, + 0x6a, 0x1e, 0xed, 0xcc, 0x04, 0x35, 0x55, 0xb2, 0xf1, 0x21, 0x40, 0xdc, 0xe6, 0xe4, 0xe0, 0xdc, + 0x48, 0x0e, 0x4e, 0x46, 0x1b, 0x9c, 0xac, 0xb1, 0x45, 0x6c, 0x44, 0x0e, 0x74, 0x74, 0xec, 0xf6, + 0x0d, 0x50, 0x07, 0x81, 0x16, 0x3a, 0x5c, 0x8f, 0x87, 0x3c, 0x54, 0xf7, 0x06, 0x2c, 0xc8, 0x94, + 0x4e, 0x94, 0xa0, 0xee, 0xd8, 0x88, 0x4b, 0x89, 0xb9, 0x91, 0x24, 0xc9, 0x69, 0x6e, 0x24, 0x51, + 0xcd, 0x28, 0xdd, 0x58, 0x83, 0xe6, 0x16, 0x17, 0xa5, 0xb5, 0x86, 0xc3, 0xa9, 0xe6, 0x18, 0xb7, + 0xe0, 0x66, 0x4a, 0x9a, 0x3c, 0x84, 0xf8, 0x14, 0x96, 0x5b, 0x74, 0x45, 0xc0, 0xcf, 0x2b, 0x16, + 0xd0, 0x68, 0xc2, 0xca, 0x74, 0x91, 0xb2, 0xb2, 0x6d, 0x58, 0xd8, 0xe2, 0xc7, 0x93, 0xd3, 0x5d, + 0x7e, 0x1e, 0x57, 0xc4, 0x20, 0x1f, 0x9c, 0x79, 0x17, 0x72, 0x7c, 0xf0, 0x37, 0x7a, 0x19, 0x0a, + 0x1c, 0x2b, 0x18, 0xf3, 0xbe, 0x3a, 0x88, 0x46, 0x48, 0x77, 0xcc, 0xfb, 0xc6, 0x13, 0x60, 0x7a, + 0x39, 0x72, 0xbc, 0x84, 0x96, 0x30, 0x39, 0xb6, 0x82, 0xab, 0x20, 0xe4, 0x23, 0x15, 0x03, 0x07, + 0xc1, 0xe4, 0xb8, 0x4b, 0x10, 0xe3, 0x5d, 0xa8, 0x1e, 0xda, 0x57, 0x26, 0xff, 0x42, 0x86, 0x9a, + 0xad, 0x42, 0x71, 0x6c, 0x5f, 0x09, 0x36, 0x10, 0xd9, 0xa4, 0x30, 0xd9, 0xf8, 0xc3, 0x3c, 0xcc, + 0x11, 0x26, 0xbb, 0x47, 0x77, 0xf1, 0x3a, 0x2e, 0x2e, 0x43, 0xc5, 0x28, 0x35, 0xd0, 0x0c, 0x2f, + 0xcd, 0xce, 0xf2, 0x52, 0x79, 0x80, 0xa6, 0xee, 0x20, 0x52, 0xd6, 0x03, 0x77, 0x32, 0x52, 0x17, + 0x0f, 0x25, 0xe3, 0xe4, 0xf3, 0xf1, 0x5d, 0xcb, 0x14, 0x44, 0x9c, 0xb4, 0xef, 0xc6, 0xba, 0x08, + 0xb5, 0x4e, 0x6d, 0x11, 0x92, 0x5d, 0xea, 0xa0, 0x54, 0x85, 0xa7, 0xa8, 0xe2, 0x27, 0x93, 0x0a, + 0xcf, 0x8c, 0x62, 0x53, 0x7a, 0xb5, 0x62, 0x43, 0x27, 0x6b, 0x2f, 0x51, 0x6c, 0xe0, 0x35, 0x14, + 0x9b, 0xd7, 0xb0, 0xad, 0xde, 0x84, 0x12, 0xee, 0xfb, 0x1a, 0xf7, 0x14, 0xfb, 0xbd, 0xe0, 0x9e, + 0x1f, 0x69, 0xa2, 0x3f, 0x39, 0x76, 0xdc, 0x8a, 0x97, 0x89, 0xc9, 0xbf, 0xf8, 0xc5, 0xd8, 0xac, + 0x9e, 0x43, 0x51, 0x42, 0x05, 0x41, 0xbb, 0xf6, 0x48, 0x5d, 0xe3, 0x86, 0xbf, 0xc5, 0xb0, 0xe1, + 0xdd, 0x53, 0x5f, 0x4c, 0x1c, 0x9f, 0x0f, 0xd4, 0xfd, 0x3c, 0x0e, 0xae, 0x51, 0x01, 0x11, 0x1d, + 0x14, 0x6a, 0x88, 0xeb, 0x5d, 0xb8, 0xf2, 0x02, 0x90, 0xa2, 0x13, 0x3c, 0x13, 0x9f, 0x06, 0x83, + 0x06, 0x5e, 0xe4, 0x38, 0xf6, 0x7c, 0xb5, 0x39, 0x19, 0x3f, 0xc9, 0x40, 0x43, 0xae, 0xae, 0x28, + 0x4d, 0xd7, 0x02, 0x0a, 0xd7, 0xf9, 0x21, 0xbc, 0xfc, 0xb6, 0x1d, 0x03, 0x6a, 0x78, 0xf8, 0x11, + 0xed, 0x54, 0x74, 0x78, 0x53, 0x11, 0xc0, 0x6d, 0xb9, 0x5b, 0xbd, 0x01, 0x15, 0xe5, 0x03, 0x3d, + 0x72, 0x86, 0xea, 0x5a, 0x75, 0x72, 0x82, 0xde, 0x73, 0x86, 0x6a, 0xa3, 0xf3, 0x6d, 0x19, 0xcf, + 0x9b, 0xc1, 0x8d, 0xce, 0xb4, 0x43, 0x6e, 0xfc, 0x9b, 0x0c, 0x2c, 0x68, 0x5d, 0x91, 0xeb, 0xf6, + 0x63, 0xa8, 0x46, 0x37, 0xa8, 0xf2, 0x48, 0xf2, 0x5a, 0x4d, 0x32, 0x9a, 0x38, 0x5b, 0xa5, 0x1f, + 0x41, 0x02, 0xd1, 0x98, 0x81, 0x7d, 0x45, 0x8e, 0xba, 0x93, 0x91, 0x52, 0x6e, 0x06, 0xf6, 0xd5, + 0x36, 0xe7, 0xdd, 0xc9, 0x48, 0xa8, 0xae, 0x17, 0x9c, 0xbf, 0x88, 0x10, 0x48, 0xe6, 0x02, 0x01, + 0x93, 0x18, 0x06, 0xd4, 0x46, 0x9e, 0x1b, 0x9e, 0x45, 0x28, 0x52, 0xea, 0x44, 0x20, 0xe1, 0x18, + 0x7f, 0x9a, 0x85, 0x45, 0x3a, 0x62, 0x93, 0x47, 0x9b, 0x92, 0x75, 0x35, 0x61, 0x8e, 0x4e, 0x1b, + 0x89, 0x79, 0xed, 0xdc, 0x30, 0xe5, 0x37, 0xfb, 0xd6, 0x6b, 0x1e, 0x0b, 0xaa, 0x90, 0xe1, 0x6b, + 0x86, 0x3f, 0x37, 0x3b, 0xfc, 0xd7, 0x0f, 0x6f, 0x9a, 0xa1, 0xb3, 0x90, 0x66, 0xe8, 0x7c, 0x1d, + 0xf3, 0xe2, 0x4c, 0x70, 0x6b, 0x51, 0xe2, 0x68, 0xc1, 0xad, 0x4f, 0x60, 0x35, 0x81, 0x83, 0xdc, + 0xda, 0x39, 0x71, 0xb8, 0xba, 0x5f, 0x65, 0x49, 0xc3, 0xee, 0xaa, 0xb4, 0x8d, 0x22, 0x14, 0x82, + 0xbe, 0x37, 0xe6, 0xc6, 0x0a, 0x2c, 0x25, 0x47, 0x55, 0x6e, 0x13, 0xbf, 0x97, 0x81, 0xa6, 0x74, + 0x4b, 0x71, 0xdc, 0xd3, 0x1d, 0x27, 0x08, 0x3d, 0x3f, 0xba, 0x69, 0xf4, 0x0e, 0x40, 0x10, 0xda, + 0xbe, 0xd4, 0x36, 0xe5, 0x8d, 0x22, 0x08, 0x41, 0x4d, 0xf2, 0x26, 0x94, 0xb8, 0x3b, 0xa0, 0x44, + 0xa2, 0x86, 0x22, 0x77, 0x07, 0x4a, 0x0f, 0x9d, 0x91, 0xbf, 0x6b, 0x49, 0xf5, 0x42, 0x06, 0xf8, + 0x8b, 0xd1, 0xe1, 0xe7, 0xb8, 0xf1, 0xe6, 0xa3, 0x00, 0xff, 0x3d, 0xfb, 0x12, 0x9d, 0x3c, 0x03, + 0xe3, 0xef, 0x67, 0x61, 0x3e, 0x6e, 0x1f, 0xdd, 0x0e, 0xf2, 0xf2, 0x7b, 0x4e, 0xee, 0x49, 0x72, + 0x70, 0x84, 0xfc, 0xae, 0x1d, 0x3c, 0x96, 0x68, 0x71, 0x76, 0x5c, 0x66, 0x40, 0x45, 0x61, 0x78, + 0x93, 0x50, 0xbb, 0xf0, 0xaf, 0x4c, 0x28, 0x07, 0x93, 0x50, 0x28, 0x5c, 0x42, 0xf3, 0x74, 0x5c, + 0xa9, 0xf2, 0x14, 0xec, 0x51, 0xd8, 0xc1, 0x77, 0x04, 0x04, 0x58, 0x64, 0xa3, 0x89, 0x14, 0x58, + 0x02, 0xbf, 0x41, 0x72, 0x36, 0xcd, 0x1c, 0xca, 0xd8, 0xba, 0x10, 0x4a, 0x57, 0x2a, 0x47, 0x42, + 0xe8, 0x1b, 0x50, 0xa1, 0xc2, 0xe3, 0x58, 0xe6, 0xbc, 0x59, 0xc6, 0x1a, 0x30, 0x5d, 0x1e, 0x02, + 0x79, 0x93, 0x84, 0xea, 0x0b, 0x54, 0x15, 0x7a, 0x7d, 0xfc, 0xed, 0x0c, 0xdc, 0x4c, 0x99, 0x36, + 0xb9, 0xca, 0x37, 0x61, 0xe1, 0x24, 0x4a, 0x54, 0xa3, 0x4b, 0x4b, 0x7d, 0x45, 0xb1, 0xd5, 0xe4, + 0x98, 0x9a, 0x8d, 0x93, 0x24, 0x20, 0x56, 0xba, 0x68, 0x06, 0x13, 0x91, 0xf2, 0xa8, 0x74, 0xd1, + 0x34, 0x92, 0xbe, 0x73, 0x08, 0x6b, 0xed, 0x4b, 0xc1, 0x31, 0x36, 0xf5, 0x87, 0x30, 0x14, 0x19, + 0x25, 0x0f, 0x98, 0x33, 0xaf, 0x75, 0xc0, 0x3c, 0xa0, 0xd0, 0xda, 0xa8, 0xac, 0x9f, 0xa6, 0x10, + 0xdc, 0x40, 0x45, 0x1e, 0x7a, 0xc8, 0x43, 0x85, 0xcc, 0xf7, 0xa3, 0x07, 0x3c, 0x8c, 0x00, 0xe6, + 0xf7, 0x26, 0xc3, 0xd0, 0x89, 0xdf, 0xf4, 0x60, 0xdf, 0x92, 0x79, 0xb0, 0x1e, 0x35, 0x6a, 0xa9, + 0x15, 0x41, 0x54, 0x11, 0x0e, 0xd6, 0x48, 0x14, 0x64, 0xcd, 0xd6, 0x37, 0x3f, 0x4a, 0xd6, 0x60, + 0xdc, 0x84, 0xd5, 0xf8, 0x8b, 0x86, 0x4d, 0x6d, 0x35, 0xff, 0x24, 0x43, 0x1e, 0xe5, 0xc9, 0xf7, + 0x45, 0x58, 0x1b, 0x16, 0x03, 0xc7, 0x3d, 0x1d, 0x72, 0xbd, 0xf8, 0x40, 0x0e, 0xc2, 0x72, 0xb2, + 0x6d, 0xf2, 0x0d, 0x12, 0x73, 0x81, 0x72, 0xc4, 0xa5, 0x05, 0x6c, 0xe3, 0xba, 0x46, 0xc6, 0x64, + 0x31, 0x35, 0x1a, 0xb3, 0x8d, 0xef, 0x40, 0x3d, 0x59, 0x11, 0xfb, 0x48, 0x46, 0xa4, 0xc7, 0xad, + 0xca, 0x4d, 0x85, 0xeb, 0xc6, 0x04, 0x51, 0x89, 0xc7, 0x3e, 0x30, 0xfe, 0x6e, 0x06, 0x9a, 0x26, + 0x17, 0x94, 0xab, 0xb5, 0x52, 0xd1, 0xcc, 0xc7, 0x33, 0xa5, 0x5e, 0xdf, 0x57, 0x15, 0xe8, 0xae, + 0x5a, 0xf4, 0xf5, 0x6b, 0x27, 0x63, 0xe7, 0xc6, 0x4c, 0x8f, 0x36, 0x4a, 0x30, 0x47, 0x28, 0xc6, + 0x2a, 0x2c, 0xcb, 0xf6, 0xa8, 0xb6, 0xc4, 0xd6, 0xc3, 0x44, 0x8d, 0x09, 0xeb, 0xe1, 0x1a, 0x34, + 0x29, 0xf4, 0x54, 0xef, 0x84, 0xcc, 0xb8, 0x05, 0x6c, 0xcf, 0xee, 0xdb, 0xbe, 0xe7, 0xb9, 0x87, + 0xdc, 0x97, 0xfe, 0xb9, 0x28, 0x61, 0xa2, 0x71, 0x4d, 0x89, 0xc2, 0xf4, 0xa5, 0xae, 0x39, 0xf5, + 0x5c, 0xe5, 0x8e, 0x44, 0x5f, 0x86, 0x09, 0x8b, 0x1b, 0xf6, 0x0b, 0xae, 0x4a, 0x52, 0x43, 0xf4, + 0x09, 0x54, 0xc6, 0x51, 0xa1, 0x6a, 0xdc, 0xd5, 0x8d, 0x19, 0xb3, 0xd5, 0x9a, 0x3a, 0xb6, 0xf1, + 0x18, 0x96, 0x92, 0x65, 0x4a, 0xd6, 0xb1, 0x06, 0xa5, 0x91, 0x84, 0xc9, 0xd6, 0x45, 0xdf, 0xc6, + 0xef, 0x94, 0xa0, 0x28, 0xf5, 0x39, 0xb6, 0x0e, 0xf9, 0xbe, 0x72, 0x09, 0x8b, 0x2f, 0x62, 0x92, + 0xa9, 0xea, 0xff, 0x26, 0x3a, 0x86, 0x09, 0x3c, 0xf6, 0x09, 0xd4, 0x93, 0x56, 0xd1, 0xa9, 0xc0, + 0xf6, 0xa4, 0x39, 0xb3, 0xd6, 0x9f, 0xb2, 0x7f, 0x95, 0xe3, 0xcd, 0x91, 0x64, 0x86, 0xd2, 0x99, + 0xb6, 0x7b, 0x7a, 0xae, 0x90, 0xb7, 0x83, 0x33, 0xdb, 0x7a, 0xfc, 0xe4, 0x43, 0x19, 0xd9, 0x5e, + 0x41, 0x60, 0xf7, 0xcc, 0x7e, 0xfc, 0xe4, 0xc3, 0x69, 0x49, 0x5a, 0xc6, 0xb5, 0x6b, 0x92, 0xf4, + 0x12, 0x14, 0xe8, 0x3e, 0x4f, 0xf2, 0xed, 0xa1, 0x0f, 0xf6, 0x08, 0x96, 0xa4, 0xda, 0x6a, 0x49, + 0x2f, 0x6c, 0xe2, 0x82, 0x25, 0x0a, 0x7c, 0x93, 0x69, 0x5d, 0x4c, 0xa2, 0xb3, 0xa1, 0x15, 0x98, + 0x3b, 0x8b, 0x2f, 0x67, 0xad, 0x99, 0xf2, 0xcb, 0xf8, 0xd3, 0x02, 0x54, 0xb4, 0x41, 0x61, 0x55, + 0x28, 0x99, 0xed, 0x6e, 0xdb, 0xfc, 0xac, 0xbd, 0xd5, 0xb8, 0xc1, 0xee, 0xc3, 0xdb, 0x9d, 0xfd, + 0xcd, 0x03, 0xd3, 0x6c, 0x6f, 0xf6, 0xac, 0x03, 0xd3, 0x52, 0xd7, 0x81, 0x1d, 0xb6, 0x9e, 0xef, + 0xb5, 0xf7, 0x7b, 0xd6, 0x56, 0xbb, 0xd7, 0xea, 0xec, 0x76, 0x1b, 0x19, 0x76, 0x1b, 0x9a, 0x31, + 0xa6, 0x4a, 0x6e, 0xed, 0x1d, 0x1c, 0xed, 0xf7, 0x1a, 0x59, 0x76, 0x17, 0x6e, 0x6d, 0x77, 0xf6, + 0x5b, 0xbb, 0x56, 0x8c, 0xb3, 0xb9, 0xdb, 0xfb, 0xcc, 0x6a, 0xff, 0xca, 0x61, 0xc7, 0x7c, 0xde, + 0xc8, 0xa5, 0x21, 0x08, 0x65, 0x5c, 0x95, 0x90, 0x67, 0x37, 0x61, 0x99, 0x10, 0x28, 0x8b, 0xd5, + 0x3b, 0x38, 0xb0, 0xba, 0x07, 0x07, 0xfb, 0x8d, 0x02, 0x5b, 0x80, 0x5a, 0x67, 0xff, 0xb3, 0xd6, + 0x6e, 0x67, 0xcb, 0x32, 0xdb, 0xad, 0xdd, 0xbd, 0xc6, 0x1c, 0x5b, 0x84, 0xf9, 0x69, 0xbc, 0xa2, + 0x28, 0x42, 0xe1, 0x1d, 0xec, 0x77, 0x0e, 0xf6, 0xad, 0xcf, 0xda, 0x66, 0xb7, 0x73, 0xb0, 0xdf, + 0x28, 0xb1, 0x15, 0x60, 0xc9, 0xa4, 0x9d, 0xbd, 0xd6, 0x66, 0xa3, 0xcc, 0x96, 0x61, 0x21, 0x09, + 0x7f, 0xd6, 0x7e, 0xde, 0x00, 0xd6, 0x84, 0x25, 0x6a, 0x98, 0xb5, 0xd1, 0xde, 0x3d, 0xf8, 0xdc, + 0xda, 0xeb, 0xec, 0x77, 0xf6, 0x8e, 0xf6, 0x1a, 0x15, 0xbc, 0x65, 0xb0, 0xdd, 0xb6, 0x3a, 0xfb, + 0xdd, 0xa3, 0xed, 0xed, 0xce, 0x66, 0xa7, 0xbd, 0xdf, 0x6b, 0x54, 0xa9, 0xe6, 0xb4, 0x8e, 0xd7, + 0x44, 0x06, 0x19, 0xaa, 0x61, 0x6d, 0x75, 0xba, 0xad, 0x8d, 0xdd, 0xf6, 0x56, 0xa3, 0xce, 0xee, + 0xc0, 0xcd, 0x5e, 0x7b, 0xef, 0xf0, 0xc0, 0x6c, 0x99, 0xcf, 0x55, 0x28, 0x87, 0xb5, 0xdd, 0xea, + 0xec, 0x1e, 0x99, 0xed, 0xc6, 0x3c, 0x7b, 0x13, 0xee, 0x98, 0xed, 0x4f, 0x8f, 0x3a, 0x66, 0x7b, + 0xcb, 0xda, 0x3f, 0xd8, 0x6a, 0x5b, 0xdb, 0xed, 0x56, 0xef, 0xc8, 0x6c, 0x5b, 0x7b, 0x9d, 0x6e, + 0xb7, 0xb3, 0xff, 0xb4, 0xd1, 0x60, 0x6f, 0xc3, 0xbd, 0x08, 0x25, 0x2a, 0x60, 0x0a, 0x6b, 0x41, + 0xf4, 0x4f, 0x4d, 0xe9, 0x7e, 0xfb, 0x57, 0x7a, 0xd6, 0x61, 0xbb, 0x6d, 0x36, 0x18, 0x5b, 0x83, + 0x95, 0xb8, 0x7a, 0xaa, 0x40, 0xd6, 0xbd, 0x28, 0xd2, 0x0e, 0xdb, 0xe6, 0x5e, 0x6b, 0x5f, 0x4c, + 0x70, 0x22, 0x6d, 0x49, 0x34, 0x3b, 0x4e, 0x9b, 0x6e, 0xf6, 0x32, 0x63, 0x50, 0xd7, 0x66, 0x65, + 0xbb, 0x65, 0x36, 0x56, 0xd8, 0x3c, 0x54, 0xf6, 0x0e, 0x0f, 0xad, 0x5e, 0x67, 0xaf, 0x7d, 0x70, + 0xd4, 0x6b, 0xac, 0xb2, 0x65, 0x68, 0x74, 0xf6, 0x7b, 0x6d, 0x53, 0xcc, 0xb5, 0xca, 0xfa, 0x3f, + 0x8b, 0x6c, 0x09, 0xe6, 0x55, 0x4b, 0x15, 0xf4, 0x2f, 0x8a, 0x6c, 0x15, 0xd8, 0xd1, 0xbe, 0xd9, + 0x6e, 0x6d, 0x89, 0x81, 0x8b, 0x12, 0xfe, 0x57, 0x51, 0x5a, 0x48, 0x7e, 0x92, 0x8b, 0x36, 0xeb, + 0xd8, 0xe5, 0x20, 0x79, 0x55, 0x77, 0x55, 0xbb, 0x62, 0xfb, 0x55, 0x8f, 0x68, 0x68, 0xaa, 0x55, + 0x6e, 0x46, 0xb5, 0x9a, 0xd1, 0xdd, 0x6b, 0xba, 0xec, 0xf7, 0x16, 0xd4, 0x46, 0x74, 0x6d, 0xb7, + 0xbc, 0x9e, 0x17, 0xa4, 0xff, 0x0d, 0x01, 0xe9, 0x6e, 0xde, 0x99, 0x57, 0x24, 0x0a, 0xb3, 0xaf, + 0x48, 0xa4, 0xc9, 0xf7, 0x73, 0x69, 0xf2, 0xfd, 0x03, 0x58, 0x20, 0xd6, 0xe4, 0xb8, 0xce, 0x48, + 0x69, 0xcd, 0x24, 0x05, 0xce, 0x23, 0x8b, 0x22, 0xb8, 0x52, 0x27, 0x94, 0xca, 0x21, 0x59, 0x48, + 0x51, 0x6a, 0x1b, 0x09, 0x4d, 0x83, 0x38, 0x47, 0xa4, 0x69, 0x44, 0x35, 0xd8, 0x97, 0x71, 0x0d, + 0x15, 0xad, 0x06, 0x82, 0x63, 0x0d, 0x0f, 0x60, 0x81, 0x5f, 0x86, 0xbe, 0x6d, 0x79, 0x63, 0xfb, + 0x8b, 0x09, 0x9a, 0x70, 0x6d, 0xd4, 0xe1, 0xab, 0xe6, 0x3c, 0x26, 0x1c, 0x20, 0x7c, 0xcb, 0x0e, + 0xed, 0x07, 0x5f, 0x42, 0x45, 0xbb, 0xd2, 0x9d, 0xad, 0xc2, 0xe2, 0xe7, 0x9d, 0xde, 0x7e, 0xbb, + 0xdb, 0xb5, 0x0e, 0x8f, 0x36, 0x9e, 0xb5, 0x9f, 0x5b, 0x3b, 0xad, 0xee, 0x4e, 0xe3, 0x86, 0x58, + 0xb4, 0xfb, 0xed, 0x6e, 0xaf, 0xbd, 0x95, 0x80, 0x67, 0xd8, 0x1b, 0xb0, 0x76, 0xb4, 0x7f, 0xd4, + 0x6d, 0x6f, 0x59, 0x69, 0xf9, 0xb2, 0x82, 0x4a, 0x65, 0x7a, 0x4a, 0xf6, 0xdc, 0x83, 0xdf, 0x80, + 0x7a, 0x32, 0xaa, 0x99, 0x01, 0xcc, 0xed, 0xb6, 0x9f, 0xb6, 0x36, 0x9f, 0xd3, 0x3d, 0xa4, 0xdd, + 0x5e, 0xab, 0xd7, 0xd9, 0xb4, 0xe4, 0xbd, 0xa3, 0x82, 0x23, 0x64, 0x58, 0x05, 0x8a, 0xad, 0xfd, + 0xcd, 0x9d, 0x03, 0xb3, 0xdb, 0xc8, 0xb2, 0xdb, 0xb0, 0xaa, 0x68, 0x75, 0xf3, 0x60, 0x6f, 0xaf, + 0xd3, 0x43, 0x66, 0xd8, 0x7b, 0x7e, 0x28, 0x48, 0xf3, 0x81, 0x0d, 0xe5, 0xf8, 0xe2, 0x54, 0x64, + 0x30, 0x9d, 0x5e, 0xa7, 0xd5, 0x8b, 0xb9, 0x6b, 0xe3, 0x86, 0xe0, 0x5f, 0x31, 0x18, 0xef, 0x3d, + 0x6d, 0x64, 0x28, 0xf0, 0x4b, 0x01, 0xa9, 0xf6, 0x46, 0x56, 0x2c, 0xaa, 0x18, 0xba, 0x71, 0xd0, + 0x13, 0x5d, 0xf8, 0x0e, 0xd4, 0x93, 0xee, 0x7d, 0xc9, 0x83, 0xdf, 0x35, 0x58, 0xd9, 0x68, 0xf7, + 0x3e, 0x6f, 0xb7, 0xf7, 0x71, 0x74, 0x36, 0xdb, 0xfb, 0x3d, 0xb3, 0xb5, 0xdb, 0xe9, 0x3d, 0x6f, + 0x64, 0x1e, 0x7c, 0x02, 0x8d, 0x69, 0x5b, 0x5a, 0xc2, 0xf8, 0xf8, 0x32, 0x2b, 0xe5, 0x83, 0x7f, + 0x91, 0x03, 0x88, 0x63, 0x4c, 0x04, 0x9b, 0xdc, 0x6a, 0xf5, 0x5a, 0xbb, 0x07, 0x62, 0x0a, 0xcc, + 0x83, 0x9e, 0xe0, 0x7e, 0x66, 0xfb, 0xd3, 0xc6, 0x8d, 0xd4, 0x94, 0x83, 0xc3, 0x5e, 0x23, 0x23, + 0x66, 0x9b, 0xba, 0xb3, 0x6b, 0x99, 0x07, 0x47, 0x9d, 0xfd, 0xa7, 0x74, 0xaf, 0x24, 0xee, 0x10, + 0x47, 0x87, 0xdb, 0xe6, 0xc1, 0x7e, 0xcf, 0xea, 0xee, 0x1c, 0xf5, 0xb6, 0xf0, 0x56, 0xca, 0x4d, + 0xb3, 0x73, 0x48, 0x65, 0xe6, 0x5f, 0x86, 0x20, 0x8a, 0x2e, 0x08, 0x7a, 0x79, 0x7a, 0xd0, 0xed, + 0x76, 0x0e, 0xad, 0x4f, 0x8f, 0xda, 0x66, 0xa7, 0xdd, 0xc5, 0x8c, 0x73, 0x29, 0x70, 0x81, 0x5f, + 0x14, 0xfb, 0x4a, 0x6f, 0xf7, 0x33, 0xc9, 0xf8, 0x05, 0x6a, 0x29, 0x09, 0x12, 0x58, 0x65, 0x31, + 0x98, 0x82, 0x73, 0xa6, 0x94, 0x0c, 0xd7, 0xa4, 0x89, 0x7c, 0x15, 0xb1, 0x27, 0xcc, 0x10, 0x12, + 0x66, 0xab, 0xa6, 0x27, 0x89, 0x5c, 0xb8, 0x5d, 0x44, 0x9b, 0xeb, 0xd6, 0x96, 0x89, 0x19, 0xea, + 0x33, 0x50, 0x81, 0x3b, 0x2f, 0x26, 0x4a, 0xb0, 0x56, 0x81, 0xd2, 0x50, 0x1f, 0x22, 0x65, 0xe1, + 0xf1, 0x6f, 0xe7, 0xa0, 0x4e, 0xf1, 0x7e, 0xf4, 0x1a, 0x20, 0xf7, 0xd9, 0x1e, 0x14, 0xe5, 0xb3, + 0x92, 0x6c, 0x39, 0xba, 0xf2, 0x4f, 0x7f, 0xc8, 0x72, 0x6d, 0x65, 0x1a, 0x2c, 0x45, 0xc9, 0xc5, + 0xbf, 0xf6, 0x27, 0xff, 0xe3, 0xef, 0x65, 0x6b, 0xac, 0xf2, 0xf0, 0xfc, 0x83, 0x87, 0xa7, 0xdc, + 0x0d, 0x44, 0x19, 0xbf, 0x06, 0x10, 0x3f, 0x96, 0xc8, 0x9a, 0xda, 0x1d, 0x03, 0x89, 0x67, 0x12, + 0xd7, 0x6e, 0xa6, 0xa4, 0xc8, 0x72, 0x6f, 0x62, 0xb9, 0x8b, 0x46, 0x5d, 0x94, 0xeb, 0xb8, 0x4e, + 0x48, 0x0f, 0x27, 0x7e, 0x9c, 0x79, 0xc0, 0x06, 0x50, 0xd5, 0x9f, 0x31, 0x64, 0x4a, 0xca, 0x4b, + 0x79, 0x88, 0x71, 0xed, 0x56, 0x6a, 0x9a, 0x92, 0x9f, 0xb1, 0x8e, 0x65, 0xa3, 0x21, 0xea, 0x98, + 0x20, 0x46, 0x5c, 0xcb, 0x90, 0x34, 0x8a, 0xf8, 0xb5, 0x42, 0x76, 0x5b, 0x93, 0x09, 0x67, 0xde, + 0x4a, 0x5c, 0xbb, 0x73, 0x4d, 0xaa, 0xac, 0xeb, 0x0e, 0xd6, 0xb5, 0x6a, 0x30, 0x51, 0x57, 0x1f, + 0x71, 0xd4, 0x5b, 0x89, 0x1f, 0x67, 0x1e, 0x3c, 0xfe, 0x8f, 0xef, 0x41, 0x39, 0xf2, 0xff, 0x65, + 0xbf, 0x09, 0xb5, 0x44, 0x40, 0x26, 0x53, 0xdd, 0x48, 0x8b, 0xdf, 0x5c, 0xbb, 0x9d, 0x9e, 0x28, + 0x2b, 0x7e, 0x03, 0x2b, 0x6e, 0xb2, 0x15, 0x51, 0xb1, 0x0c, 0x78, 0x7c, 0x88, 0x01, 0xd4, 0x74, + 0x81, 0xe2, 0x0b, 0x4d, 0x73, 0xa2, 0xca, 0x6e, 0x4f, 0x6b, 0x33, 0x89, 0xda, 0xee, 0x5c, 0x93, + 0x2a, 0xab, 0xbb, 0x8d, 0xd5, 0xad, 0xb0, 0x25, 0xbd, 0x3a, 0xe5, 0x36, 0xca, 0x38, 0x5e, 0x5a, + 0xaa, 0x3f, 0xe6, 0xc7, 0xee, 0xc4, 0x57, 0x4c, 0xa6, 0x3c, 0xf2, 0x17, 0x91, 0xc8, 0xec, 0x4b, + 0x7f, 0x46, 0x13, 0xab, 0x62, 0x0c, 0xa7, 0x4f, 0x7f, 0xcb, 0x8f, 0x1d, 0x43, 0x45, 0x7b, 0xff, + 0x86, 0xdd, 0xbc, 0xf6, 0xad, 0x9e, 0xb5, 0xb5, 0xb4, 0xa4, 0xb4, 0xae, 0xe8, 0xe5, 0x3f, 0x3c, + 0xe1, 0x9c, 0xfd, 0x2a, 0x94, 0xa3, 0x57, 0x55, 0xd8, 0xaa, 0xf6, 0xca, 0x8d, 0xfe, 0x0a, 0xcc, + 0x5a, 0x73, 0x36, 0x21, 0x8d, 0xf8, 0xf4, 0xd2, 0x05, 0xf1, 0x7d, 0x0e, 0x15, 0xed, 0xe5, 0x94, + 0xa8, 0x03, 0xb3, 0xaf, 0xb3, 0x44, 0x1d, 0x48, 0x79, 0x68, 0xc5, 0x58, 0xc0, 0x2a, 0x2a, 0xac, + 0x8c, 0xf4, 0x1d, 0x5e, 0x7a, 0x01, 0xdb, 0x85, 0x65, 0xa9, 0x25, 0x1e, 0xf3, 0xaf, 0x32, 0x0d, + 0x29, 0xef, 0x27, 0x3e, 0xca, 0xb0, 0x4f, 0xa0, 0xa4, 0x1e, 0xc8, 0x61, 0x2b, 0xe9, 0x0f, 0xfd, + 0xac, 0xad, 0xce, 0xc0, 0xa5, 0x4a, 0xf7, 0x1c, 0x20, 0x7e, 0xa6, 0x25, 0x62, 0x12, 0x33, 0xcf, + 0xbe, 0x44, 0x14, 0x30, 0xfb, 0xa6, 0x8b, 0xb1, 0x82, 0x1d, 0x6c, 0x30, 0x64, 0x12, 0x2e, 0xbf, + 0x50, 0x37, 0x4b, 0xff, 0x10, 0x2a, 0xda, 0x4b, 0x2d, 0xd1, 0xf0, 0xcd, 0xbe, 0xf2, 0x12, 0x0d, + 0x5f, 0xca, 0xc3, 0x2e, 0xc6, 0x1a, 0x96, 0xbe, 0x64, 0xcc, 0x8b, 0xd2, 0x85, 0x98, 0x28, 0xc5, + 0x35, 0x31, 0x41, 0x67, 0x50, 0x4b, 0x3c, 0xc7, 0x12, 0xad, 0xd0, 0xb4, 0xc7, 0x5e, 0xa2, 0x15, + 0x9a, 0xfa, 0x82, 0x8b, 0xa2, 0x33, 0x63, 0x41, 0xd4, 0x43, 0x97, 0x4b, 0x69, 0x35, 0xfd, 0x00, + 0x2a, 0xda, 0xd3, 0x2a, 0x51, 0x5f, 0x66, 0x5f, 0x71, 0x89, 0xfa, 0x92, 0xf6, 0x12, 0xcb, 0x12, + 0xd6, 0x51, 0x37, 0x90, 0x14, 0xf0, 0x6e, 0x5c, 0x51, 0xf6, 0x6f, 0x42, 0x3d, 0xf9, 0xda, 0x4a, + 0xb4, 0xf6, 0x53, 0x9f, 0x6d, 0x89, 0xd6, 0xfe, 0x35, 0x4f, 0xb4, 0x48, 0x92, 0x7e, 0xb0, 0x18, + 0x55, 0xf2, 0xf0, 0xc7, 0x32, 0x92, 0xe9, 0x4b, 0xf6, 0xa9, 0x60, 0x70, 0xf2, 0x6a, 0x66, 0xb6, + 0xaa, 0x51, 0xad, 0x7e, 0xc7, 0x73, 0xb4, 0x5e, 0x66, 0x6e, 0x71, 0x4e, 0x12, 0x33, 0x16, 0xce, + 0x9e, 0xc2, 0x62, 0x44, 0xcc, 0xd1, 0x5d, 0xcb, 0x41, 0xd4, 0x87, 0xd4, 0x1b, 0x9d, 0xd7, 0x1a, + 0xd3, 0xa9, 0x8f, 0x32, 0xb4, 0xfd, 0xe1, 0x0d, 0xb7, 0xda, 0xf6, 0xa7, 0x5f, 0xb7, 0xac, 0x6d, + 0x7f, 0x89, 0x8b, 0x70, 0xa7, 0xb7, 0xbf, 0xd0, 0x11, 0x65, 0xb8, 0x30, 0x3f, 0x7d, 0xf3, 0xf1, + 0x9d, 0xeb, 0x6e, 0x8a, 0xa0, 0xe2, 0xdf, 0x78, 0xf9, 0x45, 0x12, 0x49, 0x56, 0xa4, 0xb8, 0xe9, + 0x43, 0xe9, 0x38, 0xc3, 0x7e, 0x1d, 0xaa, 0xfa, 0x0b, 0x0d, 0x4c, 0xe7, 0x09, 0xd3, 0x35, 0xdd, + 0x4a, 0x4d, 0x4b, 0x52, 0x09, 0xab, 0xea, 0xd5, 0xb0, 0xcf, 0x60, 0x25, 0x1a, 0x66, 0xfd, 0xaa, + 0x83, 0x80, 0xdd, 0x4d, 0xb9, 0x00, 0x21, 0x31, 0xd8, 0x37, 0xaf, 0xbd, 0x21, 0xe1, 0x51, 0x46, + 0x50, 0x5f, 0xf2, 0x36, 0xfa, 0x78, 0xe7, 0x49, 0xbb, 0x84, 0x3f, 0xde, 0x79, 0x52, 0xaf, 0xb0, + 0x57, 0xd4, 0xc7, 0x16, 0x13, 0x63, 0x44, 0x2e, 0xc5, 0xec, 0x07, 0x30, 0xaf, 0xdd, 0xe3, 0xd0, + 0xbd, 0x72, 0xfb, 0xd1, 0x4a, 0x9a, 0xbd, 0xd3, 0x74, 0x2d, 0xed, 0x5c, 0xd5, 0x58, 0xc5, 0xf2, + 0x17, 0x8c, 0xc4, 0xe0, 0x88, 0x55, 0xb4, 0x09, 0x15, 0xfd, 0x8e, 0x88, 0x97, 0x94, 0xbb, 0xaa, + 0x25, 0xe9, 0xd7, 0x67, 0x3e, 0xca, 0xb0, 0x5d, 0x68, 0x4c, 0xdf, 0xe8, 0x16, 0xf1, 0x94, 0xb4, + 0x5b, 0xf0, 0xd6, 0xa6, 0x12, 0x13, 0xf7, 0xc0, 0xb1, 0x43, 0x0a, 0x4a, 0x89, 0x1e, 0x1b, 0xf4, + 0xfc, 0xe9, 0x5d, 0x3d, 0xf9, 0x08, 0x61, 0x54, 0x5a, 0xda, 0xf3, 0x93, 0xf7, 0x33, 0x8f, 0x32, + 0xec, 0x77, 0x33, 0x50, 0x4d, 0xdc, 0x68, 0x94, 0x70, 0xfb, 0x9f, 0xea, 0x67, 0x53, 0x4f, 0xd3, + 0x3b, 0x6a, 0x98, 0x38, 0x88, 0xbb, 0x0f, 0xbe, 0x9f, 0x98, 0xa4, 0x1f, 0x27, 0xcc, 0x92, 0xeb, + 0xd3, 0xaf, 0x11, 0x7e, 0x39, 0x8d, 0xa0, 0xdf, 0x92, 0xfb, 0xe5, 0xa3, 0x0c, 0xfb, 0x57, 0x19, + 0xa8, 0x27, 0xfd, 0x0d, 0xa2, 0xee, 0xa6, 0x7a, 0x36, 0x44, 0xa4, 0x74, 0x8d, 0x93, 0xc2, 0x0f, + 0xb0, 0x95, 0xbd, 0x07, 0x66, 0xa2, 0x95, 0xf2, 0x1d, 0x85, 0x9f, 0xad, 0xb5, 0xec, 0x97, 0xe9, + 0xf1, 0x5f, 0xe5, 0x86, 0xc5, 0x66, 0x1f, 0x8b, 0x8d, 0xc8, 0x4f, 0x7f, 0x5a, 0xd5, 0xc8, 0xfd, + 0x56, 0x36, 0x83, 0x33, 0xf1, 0x43, 0x7a, 0x7a, 0x4f, 0xb9, 0xf6, 0x08, 0x52, 0x7e, 0xed, 0x42, + 0xde, 0xc6, 0x8e, 0xbd, 0x61, 0xdc, 0x4c, 0x74, 0x6c, 0x5a, 0xfa, 0x68, 0x51, 0x13, 0xe5, 0xf3, + 0xa8, 0xf1, 0xf6, 0x39, 0xf3, 0x64, 0x6a, 0x6a, 0x25, 0xd8, 0xc8, 0x11, 0x35, 0x52, 0xa2, 0x27, + 0xd6, 0xdb, 0x6b, 0x16, 0x63, 0x3c, 0xc0, 0xb6, 0xbe, 0x6d, 0xdc, 0xbd, 0xb6, 0xad, 0x0f, 0xd1, + 0x81, 0x40, 0xb4, 0xf8, 0x10, 0x20, 0xf6, 0x95, 0x64, 0x53, 0x1e, 0x7b, 0x11, 0x17, 0x9a, 0x75, + 0xa7, 0x4c, 0x2e, 0x6a, 0xe5, 0xd8, 0x27, 0x4a, 0xfc, 0x55, 0xe2, 0xa9, 0x91, 0x2f, 0xa1, 0x2e, + 0x82, 0x25, 0xdd, 0x1a, 0x13, 0x22, 0xd8, 0x74, 0xf9, 0x09, 0x8e, 0x1a, 0x39, 0x0e, 0x1e, 0x41, + 0x6d, 0xd7, 0xf3, 0x5e, 0x4c, 0xc6, 0x91, 0x7f, 0x7e, 0xd2, 0xab, 0x67, 0xc7, 0x0e, 0xce, 0xd6, + 0xa6, 0x7a, 0x61, 0xdc, 0xc3, 0xa2, 0xd6, 0x58, 0x53, 0x2b, 0xea, 0xe1, 0x8f, 0x63, 0x07, 0xcd, + 0x2f, 0x99, 0x0d, 0x0b, 0x11, 0xa3, 0x8e, 0x9d, 0x20, 0x93, 0xc5, 0x24, 0xd8, 0xf3, 0x74, 0x15, + 0x09, 0x5d, 0x41, 0xb5, 0xf6, 0x61, 0xa0, 0xca, 0x7c, 0x94, 0x61, 0x87, 0x50, 0xdd, 0xe2, 0x7d, + 0xbc, 0xe0, 0x01, 0x7d, 0x63, 0x16, 0x13, 0x7e, 0x16, 0xe4, 0x54, 0xb3, 0x56, 0x4b, 0x00, 0x93, + 0x9b, 0xd7, 0xd8, 0xbe, 0xf2, 0xf9, 0x17, 0x0f, 0x7f, 0x2c, 0xbd, 0x6e, 0xbe, 0x54, 0x9b, 0x97, + 0xf2, 0x4a, 0x4a, 0x6c, 0x5e, 0x53, 0x6e, 0x4c, 0x89, 0xcd, 0x6b, 0xc6, 0x8d, 0x29, 0x31, 0xd4, + 0xca, 0x2b, 0x8a, 0x0d, 0x61, 0x61, 0xc6, 0xf3, 0x29, 0xda, 0xb7, 0xae, 0xf3, 0x97, 0x5a, 0xbb, + 0x77, 0x3d, 0x42, 0xb2, 0xb6, 0x07, 0xc9, 0xda, 0xba, 0x50, 0xa3, 0x7b, 0x70, 0x8f, 0x39, 0x85, + 0x7a, 0x4e, 0xdd, 0x93, 0xa4, 0xc7, 0x91, 0x4e, 0xef, 0x32, 0x98, 0x96, 0x14, 0x73, 0x30, 0xd8, + 0x8f, 0x9d, 0xe0, 0xe3, 0x0f, 0x5a, 0x6c, 0x65, 0x44, 0x8c, 0xb3, 0xf1, 0x9e, 0x11, 0x31, 0xa6, + 0x84, 0x62, 0x2a, 0x1d, 0x94, 0x2d, 0x47, 0x65, 0x3f, 0x74, 0xbd, 0x01, 0x1f, 0xc9, 0x52, 0x7f, + 0x15, 0x2a, 0x4f, 0x79, 0xa8, 0x82, 0x19, 0x23, 0x81, 0x7e, 0x2a, 0xba, 0x71, 0x2d, 0x25, 0x04, + 0x35, 0x49, 0x9b, 0x54, 0x32, 0x1f, 0x9c, 0x72, 0xe2, 0x84, 0x96, 0x33, 0xf8, 0x92, 0xfd, 0x0a, + 0x16, 0x1e, 0x85, 0xee, 0xaf, 0x68, 0xcd, 0xd4, 0x0b, 0x9f, 0x9f, 0x82, 0xa7, 0x95, 0x2c, 0xda, + 0xac, 0x09, 0x96, 0x2e, 0x54, 0xb4, 0x2b, 0x3e, 0xa2, 0xb1, 0x99, 0xbd, 0xd2, 0x25, 0x1a, 0x9b, + 0x94, 0x1b, 0x41, 0x8c, 0xfb, 0x58, 0x8f, 0xc1, 0xee, 0xc5, 0xf5, 0xd0, 0x2d, 0x20, 0x71, 0x4d, + 0x0f, 0x7f, 0x6c, 0x8f, 0xc2, 0x2f, 0xd9, 0xe7, 0x34, 0x1d, 0x5a, 0xb0, 0x66, 0xac, 0xa1, 0x4c, + 0xc7, 0x75, 0x46, 0x83, 0xa5, 0x25, 0x25, 0xb5, 0x16, 0xaa, 0x0a, 0xc5, 0xc6, 0x27, 0x00, 0xdd, + 0xd0, 0x1b, 0x6f, 0xd9, 0x7c, 0xe4, 0xb9, 0x31, 0x4f, 0x8f, 0xc3, 0x07, 0x63, 0x3e, 0xa9, 0xc5, + 0x10, 0xb2, 0xcf, 0x35, 0x95, 0x2e, 0x11, 0x66, 0xac, 0x88, 0xf8, 0xda, 0x08, 0xc3, 0x68, 0x40, + 0x52, 0xa2, 0x0c, 0x1f, 0x65, 0x58, 0x0b, 0x20, 0x76, 0xb1, 0x8b, 0x14, 0xb4, 0x19, 0xef, 0xbd, + 0x88, 0xbd, 0xa6, 0xf8, 0xe3, 0x1d, 0x42, 0x39, 0xf6, 0x4d, 0x5a, 0x8d, 0x6f, 0x2c, 0x4a, 0x78, + 0x32, 0x45, 0xe2, 0xc2, 0x8c, 0x5f, 0x90, 0xd1, 0xc0, 0xa1, 0x02, 0x56, 0x12, 0x43, 0x75, 0xc2, + 0x79, 0xc0, 0x1c, 0x58, 0xa4, 0x06, 0x46, 0xb2, 0x19, 0x86, 0xbd, 0x45, 0x4f, 0xae, 0xcc, 0xba, + 0xe8, 0x44, 0x5c, 0x23, 0xd5, 0xd1, 0x24, 0x71, 0xce, 0x24, 0xa8, 0x95, 0x42, 0xee, 0xc4, 0x16, + 0x30, 0x82, 0x85, 0x19, 0x5f, 0x86, 0x88, 0x75, 0x5c, 0xe7, 0x9c, 0x12, 0xb1, 0x8e, 0x6b, 0xdd, + 0x20, 0x8c, 0x65, 0xac, 0x72, 0xde, 0x00, 0xd4, 0x2b, 0x2f, 0x9c, 0xb0, 0x7f, 0x26, 0xaa, 0xfb, + 0xfd, 0x0c, 0x2c, 0xa6, 0x78, 0x2b, 0xb0, 0x37, 0xd5, 0x11, 0xc5, 0xb5, 0x9e, 0x0c, 0x6b, 0xa9, + 0x56, 0x6d, 0xa3, 0x8b, 0xf5, 0xec, 0xb1, 0x67, 0x89, 0x0d, 0x94, 0x8c, 0xca, 0x72, 0x65, 0xbe, + 0x54, 0x82, 0x49, 0x15, 0x5f, 0xbe, 0x80, 0x55, 0x6a, 0x48, 0x6b, 0x38, 0x9c, 0xb2, 0xb8, 0xbf, + 0xa1, 0xb5, 0x22, 0xc5, 0x8b, 0x20, 0xa1, 0x0c, 0x24, 0x3d, 0x09, 0xae, 0x91, 0xdd, 0xa9, 0xa9, + 0x6c, 0x02, 0x8d, 0x69, 0x4b, 0x36, 0xbb, 0xbe, 0xac, 0xb5, 0xbb, 0x09, 0x65, 0x3b, 0xc5, 0xfa, + 0xfd, 0x35, 0xac, 0xec, 0xae, 0xb1, 0x96, 0x36, 0x2e, 0xa4, 0x7f, 0x8b, 0xf9, 0xf8, 0xab, 0x91, + 0xd9, 0x7d, 0xaa, 0x9f, 0x77, 0xa3, 0x4b, 0xe6, 0xd3, 0x9d, 0x04, 0x22, 0x75, 0x3f, 0xdd, 0x6a, + 0xff, 0x0e, 0x56, 0x7f, 0xcf, 0xb8, 0x95, 0x56, 0xbd, 0x4f, 0x59, 0x48, 0xf1, 0x5f, 0x9d, 0x5e, + 0xd7, 0xaa, 0x05, 0xf7, 0xd2, 0xe6, 0xfb, 0x5a, 0xc5, 0x6b, 0x6a, 0xac, 0x6f, 0xa0, 0x0c, 0x59, + 0xd5, 0xcd, 0xec, 0xd1, 0xf2, 0x49, 0xb1, 0xe7, 0x47, 0xcb, 0x27, 0xcd, 0x2e, 0x9f, 0x94, 0x9f, + 0x94, 0x45, 0xfe, 0xe3, 0xcc, 0x83, 0x8d, 0x77, 0x7f, 0xf0, 0xb5, 0x53, 0x27, 0x3c, 0x9b, 0x1c, + 0xaf, 0xf7, 0xbd, 0xd1, 0xc3, 0xa1, 0x3a, 0xda, 0x94, 0xb1, 0xe1, 0x0f, 0x87, 0xee, 0xe0, 0x21, + 0x16, 0x7b, 0x3c, 0x37, 0xf6, 0xbd, 0xd0, 0xfb, 0xe6, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x6d, + 0x0c, 0xaf, 0xd9, 0x6c, 0x89, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 46c60ade47..ff86b95444 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2093,8 +2093,8 @@ message PendingChannelsResponse { */ int64 remote_chan_reserve_sat = 7; - // True if we initiated opening the channel. - bool initiator = 8; + // The party that initiated opening the channel. + Initiator initiator = 8; /// The commitment type used by this channel. CommitmentType commitment_type = 9; diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 683ca13cf0..6e68328db5 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1733,9 +1733,8 @@ "description": "*\nThe minimum satoshis the other node is required to reserve in its\nbalance." }, "initiator": { - "type": "boolean", - "format": "boolean", - "description": "True if we initiated opening the channel." + "$ref": "#/definitions/lnrpcInitiator", + "description": "The party that initiated opening the channel." }, "commitment_type": { "$ref": "#/definitions/lnrpcCommitmentType", diff --git a/rpcserver.go b/rpcserver.go index cd5da7d0e1..471abcf67b 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2664,6 +2664,16 @@ func (r *rpcServer) PendingChannels(ctx context.Context, resp := &lnrpc.PendingChannelsResponse{} + // rpcInitiator returns the correct lnrpc initiator for channels where + // we have a record of the opening channel. + rpcInitiator := func(isInitiator bool) lnrpc.Initiator { + if isInitiator { + return lnrpc.Initiator_INITIATOR_LOCAL + } + + return lnrpc.Initiator_INITIATOR_REMOTE + } + // First, we'll populate the response with all the channels that are // soon to be opened. We can easily fetch this data from the database // and map the db struct to the proto response. @@ -2698,7 +2708,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context, RemoteBalance: int64(localCommitment.RemoteBalance.ToSatoshis()), LocalChanReserveSat: int64(pendingChan.LocalChanCfg.ChanReserve), RemoteChanReserveSat: int64(pendingChan.RemoteChanCfg.ChanReserve), - Initiator: pendingChan.IsInitiator, + Initiator: rpcInitiator(pendingChan.IsInitiator), CommitmentType: rpcCommitmentType(pendingChan.ChanType), }, CommitWeight: commitWeight, @@ -2725,12 +2735,18 @@ func (r *rpcServer) PendingChannels(ctx context.Context, // needed regardless of how this channel was closed. pub := pendingClose.RemotePub.SerializeCompressed() chanPoint := pendingClose.ChanPoint + + // Create the pending channel. If this channel was closed before + // we started storing historical channel data, we will not know + // who initiated the channel, so we set the initiator field to + // unknown. channel := &lnrpc.PendingChannelsResponse_PendingChannel{ RemoteNodePub: hex.EncodeToString(pub), ChannelPoint: chanPoint.String(), Capacity: int64(pendingClose.Capacity), LocalBalance: int64(pendingClose.SettledBalance), CommitmentType: lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, + Initiator: lnrpc.Initiator_INITIATOR_UNKNOWN, } // Lookup the channel in the historical channel bucket to obtain @@ -2748,7 +2764,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context, case channeldb.ErrChannelNotFound: case nil: - channel.Initiator = historical.IsInitiator + channel.Initiator = rpcInitiator(historical.IsInitiator) channel.CommitmentType = rpcCommitmentType( historical.ChanType, ) @@ -2878,7 +2894,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context, RemoteBalance: int64(waitingClose.LocalCommitment.RemoteBalance.ToSatoshis()), LocalChanReserveSat: int64(waitingClose.LocalChanCfg.ChanReserve), RemoteChanReserveSat: int64(waitingClose.RemoteChanCfg.ChanReserve), - Initiator: waitingClose.IsInitiator, + Initiator: rpcInitiator(waitingClose.IsInitiator), CommitmentType: rpcCommitmentType(waitingClose.ChanType), } From 1a1e8b6dad65d6272a8d0a9863d5fe8d0ea155ac Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 17 Mar 2020 16:54:50 -0700 Subject: [PATCH 407/562] build: update btcwallet dependency to scan/recover all key scopes --- go.mod | 5 ++--- go.sum | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 75a4f3f482..27824c1b8d 100644 --- a/go.mod +++ b/go.mod @@ -9,13 +9,12 @@ require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059 - github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7 + github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 - github.com/btcsuite/btcwallet/walletdb v1.2.0 + github.com/btcsuite/btcwallet/walletdb v1.3.1 github.com/btcsuite/btcwallet/wtxmgr v1.0.0 github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 - github.com/coreos/bbolt v1.3.3 github.com/davecgh/go-spew v1.1.1 github.com/go-errors/errors v1.0.1 github.com/golang/protobuf v1.3.1 diff --git a/go.sum b/go.sum index 483b544b65..09469ecf0d 100644 --- a/go.sum +++ b/go.sum @@ -28,18 +28,19 @@ github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6 github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059 h1:RU+MRFz83kf5hgJrGryakeYv/Xj2wZ7pwu9Eb7tna30= github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= -github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7 h1:ubYJYIi13atgwPCX7FZQZV2mytkaRHWPycDFdF28U0o= -github.com/btcsuite/btcwallet v0.11.1-0.20200323235326-015c045a3bb7/go.mod h1:1O1uRHMPXHdwA4/od8nqYqrgclVKp+wtfXUAqHmeRvE= +github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb h1:kkq2SSCy+OrC7GVZLIqutoHVR2yW4SJQdX70jtmuLDI= +github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb/go.mod h1:9fJNm1aXi4q9P5Nk23mmqppCy1Le3f2/JMWj9UXKkCc= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA= github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0 h1:6DxkcoMnCPY4E9cUDPB5tbuuf40SmmMkSQkoE8vCT+s= github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= -github.com/btcsuite/btcwallet/walletdb v1.0.0 h1:mheT7vCWK5EP6rZzhxsQ7ms9+yX4VE8bwiJctECBeNw= github.com/btcsuite/btcwallet/walletdb v1.0.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= github.com/btcsuite/btcwallet/walletdb v1.2.0 h1:E0+M4jHOToAvGWZ27ew5AaDAHDi6fUiXkjUJUnoEOD0= github.com/btcsuite/btcwallet/walletdb v1.2.0/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= +github.com/btcsuite/btcwallet/walletdb v1.3.1 h1:lW1Ac3F1jJY4K11P+YQtRNcP5jFk27ASfrV7C6mvRU0= +github.com/btcsuite/btcwallet/walletdb v1.3.1/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= github.com/btcsuite/btcwallet/wtxmgr v1.0.0 h1:aIHgViEmZmZfe0tQQqF1xyd2qBqFWxX5vZXkkbjtbeA= github.com/btcsuite/btcwallet/wtxmgr v1.0.0/go.mod h1:vc4gBprll6BP0UJ+AIGDaySoc7MdAmZf8kelfNb8CFY= github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 h1:kij1x2aL7VE6gtx8KMIt8PGPgI5GV9LgtHFG5KaEMPY= From f6ff3131d8b64ef38d45600b9c51fefe8591c815 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 31 Mar 2020 09:36:37 -0700 Subject: [PATCH 408/562] lntest/itest: add change address recovery case to onchain recovery test This is mainly motivated by a now fixed bug in the wallet in which change addresses could at times be created outside of the default key scopes. Recovery only used to be performed on the default key scopes, so ideally this test case would've caught the bug earlier. --- lntest/itest/lnd_test.go | 60 ++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index d35fca729d..f86e393475 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -799,7 +799,7 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) { // method takes the expected value of Carol's balance when using the // given recovery window. Additionally, the caller can specify an action // to perform on the restored node before the node is shutdown. - restoreCheckBalance := func(expAmount int64, expectedNumUTXOs int, + restoreCheckBalance := func(expAmount int64, expectedNumUTXOs uint32, recoveryWindow int32, fn func(*lntest.HarnessNode)) { // Restore Carol, passing in the password, mnemonic, and @@ -825,13 +825,7 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("unable to query wallet balance: %v", err) } - - // Verify that Carol's balance matches our expected - // amount. currBalance = resp.ConfirmedBalance - if expAmount != currBalance { - return false - } utxoReq := &lnrpc.ListUnspentRequest{ MaxConfs: math.MaxInt32, @@ -841,8 +835,13 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) { if err != nil { t.Fatalf("unable to query utxos: %v", err) } + currNumUTXOs = uint32(len(utxoResp.Utxos)) - currNumUTXOs := len(utxoResp.Utxos) + // Verify that Carol's balance and number of UTXOs + // matches what's expected. + if expAmount != currBalance { + return false + } if currNumUTXOs != expectedNumUTXOs { return false } @@ -958,7 +957,50 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) { // Ensure that using a recovery window of 20 succeeds with all UTXOs // found and the final balance reflected. - restoreCheckBalance(6*btcutil.SatoshiPerBitcoin, 6, 20, nil) + + // After these checks are done, we'll want to make sure we can also + // recover change address outputs. This is mainly motivated by a now + // fixed bug in the wallet in which change addresses could at times be + // created outside of the default key scopes. Recovery only used to be + // performed on the default key scopes, so ideally this test case + // would've caught the bug earlier. Carol has received 6 BTC so far from + // the miner, we'll send 5 back to ensure all of her UTXOs get spent to + // avoid fee discrepancies and a change output is formed. + const minerAmt = 5 * btcutil.SatoshiPerBitcoin + const finalBalance = 6 * btcutil.SatoshiPerBitcoin + promptChangeAddr := func(node *lntest.HarnessNode) { + minerAddr, err := net.Miner.NewAddress() + if err != nil { + t.Fatalf("unable to create new miner address: %v", err) + } + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + resp, err := node.SendCoins(ctxt, &lnrpc.SendCoinsRequest{ + Addr: minerAddr.String(), + Amount: minerAmt, + }) + if err != nil { + t.Fatalf("unable to send coins to miner: %v", err) + } + txid, err := waitForTxInMempool( + net.Miner.Node, minerMempoolTimeout, + ) + if err != nil { + t.Fatalf("transaction not found in mempool: %v", err) + } + if resp.Txid != txid.String() { + t.Fatalf("txid mismatch: %v vs %v", resp.Txid, + txid.String()) + } + block := mineBlocks(t, net, 1, 1)[0] + assertTxInBlock(t, block, txid) + } + restoreCheckBalance(finalBalance, 6, 20, promptChangeAddr) + + // We should expect a static fee of 27750 satoshis for spending 6 inputs + // (3 P2WPKH, 3 NP2WPKH) to two P2WPKH outputs. Carol should therefore + // only have one UTXO present (the change output) of 6 - 5 - fee BTC. + const fee = 27750 + restoreCheckBalance(finalBalance-minerAmt-fee, 1, 21, nil) } // commitType is a simple enum used to run though the basic funding flow with From 978ff82f1f84fc647ce778037ac5f81dd8547a53 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 3 Apr 2020 15:28:49 -0700 Subject: [PATCH 409/562] contractcourt/chain_watchter: fix broken log stmts --- contractcourt/chain_watcher.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/contractcourt/chain_watcher.go b/contractcourt/chain_watcher.go index 3be9f08df5..9956550593 100644 --- a/contractcourt/chain_watcher.go +++ b/contractcourt/chain_watcher.go @@ -430,9 +430,11 @@ func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) { } log.Debugf("ChannelPoint(%v): local_commit_type=%v, local_commit=%v", - chanState.ChanType, spew.Sdump(localCommit)) + chanState.FundingOutpoint, chanState.ChanType, + spew.Sdump(localCommit)) log.Debugf("ChannelPoint(%v): remote_commit_type=%v, remote_commit=%v", - chanState.ChanType, spew.Sdump(remoteCommit)) + chanState.FundingOutpoint, chanState.ChanType, + spew.Sdump(remoteCommit)) // Fetch the current known commit height for the remote party, and // their pending commitment chain tip if it exists. @@ -458,7 +460,7 @@ func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) { if remoteChainTip != nil { remotePendingCommit = &remoteChainTip.Commitment log.Debugf("ChannelPoint(%v): remote_pending_commit_type=%v, "+ - "remote_pending_commit=%v", + "remote_pending_commit=%v", chanState.FundingOutpoint, chanState.ChanType, spew.Sdump(remoteChainTip.Commitment)) From 4aceaba1be3f00fa799d328737b625b879613561 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 6 Apr 2020 14:21:38 -0700 Subject: [PATCH 410/562] cmd/lncli: move invoice commands to cmd_invoice.go --- cmd/lncli/cmd_invoice.go | 288 +++++++++++++++++++++++++++++++++++++++ cmd/lncli/commands.go | 277 ------------------------------------- 2 files changed, 288 insertions(+), 277 deletions(-) create mode 100644 cmd/lncli/cmd_invoice.go diff --git a/cmd/lncli/cmd_invoice.go b/cmd/lncli/cmd_invoice.go new file mode 100644 index 0000000000..d2d118edda --- /dev/null +++ b/cmd/lncli/cmd_invoice.go @@ -0,0 +1,288 @@ +package main + +import ( + "context" + "encoding/hex" + "fmt" + "strconv" + + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/urfave/cli" +) + +var addInvoiceCommand = cli.Command{ + Name: "addinvoice", + Category: "Payments", + Usage: "Add a new invoice.", + Description: ` + Add a new invoice, expressing intent for a future payment. + + Invoices without an amount can be created by not supplying any + parameters or providing an amount of 0. These invoices allow the payee + to specify the amount of satoshis they wish to send.`, + ArgsUsage: "value preimage", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "memo", + Usage: "a description of the payment to attach along " + + "with the invoice (default=\"\")", + }, + cli.StringFlag{ + Name: "preimage", + Usage: "the hex-encoded preimage (32 byte) which will " + + "allow settling an incoming HTLC payable to this " + + "preimage. If not set, a random preimage will be " + + "created.", + }, + cli.Int64Flag{ + Name: "amt", + Usage: "the amt of satoshis in this invoice", + }, + cli.StringFlag{ + Name: "description_hash", + Usage: "SHA-256 hash of the description of the payment. " + + "Used if the purpose of payment cannot naturally " + + "fit within the memo. If provided this will be " + + "used instead of the description(memo) field in " + + "the encoded invoice.", + }, + cli.StringFlag{ + Name: "fallback_addr", + Usage: "fallback on-chain address that can be used in " + + "case the lightning payment fails", + }, + cli.Int64Flag{ + Name: "expiry", + Usage: "the invoice's expiry time in seconds. If not " + + "specified an expiry of 3600 seconds (1 hour) " + + "is implied.", + }, + cli.BoolTFlag{ + Name: "private", + Usage: "encode routing hints in the invoice with " + + "private channels in order to assist the " + + "payer in reaching you", + }, + }, + Action: actionDecorator(addInvoice), +} + +func addInvoice(ctx *cli.Context) error { + var ( + preimage []byte + descHash []byte + amt int64 + err error + ) + + client, cleanUp := getClient(ctx) + defer cleanUp() + + args := ctx.Args() + + switch { + case ctx.IsSet("amt"): + amt = ctx.Int64("amt") + case args.Present(): + amt, err = strconv.ParseInt(args.First(), 10, 64) + args = args.Tail() + if err != nil { + return fmt.Errorf("unable to decode amt argument: %v", err) + } + } + + switch { + case ctx.IsSet("preimage"): + preimage, err = hex.DecodeString(ctx.String("preimage")) + case args.Present(): + preimage, err = hex.DecodeString(args.First()) + } + + if err != nil { + return fmt.Errorf("unable to parse preimage: %v", err) + } + + descHash, err = hex.DecodeString(ctx.String("description_hash")) + if err != nil { + return fmt.Errorf("unable to parse description_hash: %v", err) + } + + invoice := &lnrpc.Invoice{ + Memo: ctx.String("memo"), + RPreimage: preimage, + Value: amt, + DescriptionHash: descHash, + FallbackAddr: ctx.String("fallback_addr"), + Expiry: ctx.Int64("expiry"), + Private: ctx.Bool("private"), + } + + resp, err := client.AddInvoice(context.Background(), invoice) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var lookupInvoiceCommand = cli.Command{ + Name: "lookupinvoice", + Category: "Payments", + Usage: "Lookup an existing invoice by its payment hash.", + ArgsUsage: "rhash", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "rhash", + Usage: "the 32 byte payment hash of the invoice to query for, the hash " + + "should be a hex-encoded string", + }, + }, + Action: actionDecorator(lookupInvoice), +} + +func lookupInvoice(ctx *cli.Context) error { + client, cleanUp := getClient(ctx) + defer cleanUp() + + var ( + rHash []byte + err error + ) + + switch { + case ctx.IsSet("rhash"): + rHash, err = hex.DecodeString(ctx.String("rhash")) + case ctx.Args().Present(): + rHash, err = hex.DecodeString(ctx.Args().First()) + default: + return fmt.Errorf("rhash argument missing") + } + + if err != nil { + return fmt.Errorf("unable to decode rhash argument: %v", err) + } + + req := &lnrpc.PaymentHash{ + RHash: rHash, + } + + invoice, err := client.LookupInvoice(context.Background(), req) + if err != nil { + return err + } + + printRespJSON(invoice) + + return nil +} + +var listInvoicesCommand = cli.Command{ + Name: "listinvoices", + Category: "Payments", + Usage: "List all invoices currently stored within the database. Any " + + "active debug invoices are ignored.", + Description: ` + This command enables the retrieval of all invoices currently stored + within the database. It has full support for paginationed responses, + allowing users to query for specific invoices through their add_index. + This can be done by using either the first_index_offset or + last_index_offset fields included in the response as the index_offset of + the next request. Backward pagination is enabled by default to receive + current invoices first. If you wish to paginate forwards, set the + paginate-forwards flag. If none of the parameters are specified, then + the last 100 invoices will be returned. + + For example: if you have 200 invoices, "lncli listinvoices" will return + the last 100 created. If you wish to retrieve the previous 100, the + first_offset_index of the response can be used as the index_offset of + the next listinvoices request.`, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "pending_only", + Usage: "toggles if all invoices should be returned, " + + "or only those that are currently unsettled", + }, + cli.Uint64Flag{ + Name: "index_offset", + Usage: "the index of an invoice that will be used as " + + "either the start or end of a query to " + + "determine which invoices should be returned " + + "in the response", + }, + cli.Uint64Flag{ + Name: "max_invoices", + Usage: "the max number of invoices to return", + }, + cli.BoolFlag{ + Name: "paginate-forwards", + Usage: "if set, invoices succeeding the " + + "index_offset will be returned", + }, + }, + Action: actionDecorator(listInvoices), +} + +func listInvoices(ctx *cli.Context) error { + client, cleanUp := getClient(ctx) + defer cleanUp() + + req := &lnrpc.ListInvoiceRequest{ + PendingOnly: ctx.Bool("pending_only"), + IndexOffset: ctx.Uint64("index_offset"), + NumMaxInvoices: ctx.Uint64("max_invoices"), + Reversed: !ctx.Bool("paginate-forwards"), + } + + invoices, err := client.ListInvoices(context.Background(), req) + if err != nil { + return err + } + + printRespJSON(invoices) + + return nil +} + +var decodePayReqCommand = cli.Command{ + Name: "decodepayreq", + Category: "Payments", + Usage: "Decode a payment request.", + Description: "Decode the passed payment request revealing the destination, payment hash and value of the payment request", + ArgsUsage: "pay_req", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "pay_req", + Usage: "the bech32 encoded payment request", + }, + }, + Action: actionDecorator(decodePayReq), +} + +func decodePayReq(ctx *cli.Context) error { + ctxb := context.Background() + client, cleanUp := getClient(ctx) + defer cleanUp() + + var payreq string + + switch { + case ctx.IsSet("pay_req"): + payreq = ctx.String("pay_req") + case ctx.Args().Present(): + payreq = ctx.Args().First() + default: + return fmt.Errorf("pay_req argument missing") + } + + resp, err := client.DecodePayReq(ctxb, &lnrpc.PayReqString{ + PayReq: payreq, + }) + if err != nil { + return err + } + + printRespJSON(resp) + return nil +} diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 79313d252d..46599902b8 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1873,241 +1873,6 @@ func closedChannels(ctx *cli.Context) error { return nil } -var addInvoiceCommand = cli.Command{ - Name: "addinvoice", - Category: "Payments", - Usage: "Add a new invoice.", - Description: ` - Add a new invoice, expressing intent for a future payment. - - Invoices without an amount can be created by not supplying any - parameters or providing an amount of 0. These invoices allow the payee - to specify the amount of satoshis they wish to send.`, - ArgsUsage: "value preimage", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "memo", - Usage: "a description of the payment to attach along " + - "with the invoice (default=\"\")", - }, - cli.StringFlag{ - Name: "preimage", - Usage: "the hex-encoded preimage (32 byte) which will " + - "allow settling an incoming HTLC payable to this " + - "preimage. If not set, a random preimage will be " + - "created.", - }, - cli.Int64Flag{ - Name: "amt", - Usage: "the amt of satoshis in this invoice", - }, - cli.StringFlag{ - Name: "description_hash", - Usage: "SHA-256 hash of the description of the payment. " + - "Used if the purpose of payment cannot naturally " + - "fit within the memo. If provided this will be " + - "used instead of the description(memo) field in " + - "the encoded invoice.", - }, - cli.StringFlag{ - Name: "fallback_addr", - Usage: "fallback on-chain address that can be used in " + - "case the lightning payment fails", - }, - cli.Int64Flag{ - Name: "expiry", - Usage: "the invoice's expiry time in seconds. If not " + - "specified an expiry of 3600 seconds (1 hour) " + - "is implied.", - }, - cli.BoolTFlag{ - Name: "private", - Usage: "encode routing hints in the invoice with " + - "private channels in order to assist the " + - "payer in reaching you", - }, - }, - Action: actionDecorator(addInvoice), -} - -func addInvoice(ctx *cli.Context) error { - var ( - preimage []byte - descHash []byte - amt int64 - err error - ) - - client, cleanUp := getClient(ctx) - defer cleanUp() - - args := ctx.Args() - - switch { - case ctx.IsSet("amt"): - amt = ctx.Int64("amt") - case args.Present(): - amt, err = strconv.ParseInt(args.First(), 10, 64) - args = args.Tail() - if err != nil { - return fmt.Errorf("unable to decode amt argument: %v", err) - } - } - - switch { - case ctx.IsSet("preimage"): - preimage, err = hex.DecodeString(ctx.String("preimage")) - case args.Present(): - preimage, err = hex.DecodeString(args.First()) - } - - if err != nil { - return fmt.Errorf("unable to parse preimage: %v", err) - } - - descHash, err = hex.DecodeString(ctx.String("description_hash")) - if err != nil { - return fmt.Errorf("unable to parse description_hash: %v", err) - } - - invoice := &lnrpc.Invoice{ - Memo: ctx.String("memo"), - RPreimage: preimage, - Value: amt, - DescriptionHash: descHash, - FallbackAddr: ctx.String("fallback_addr"), - Expiry: ctx.Int64("expiry"), - Private: ctx.Bool("private"), - } - - resp, err := client.AddInvoice(context.Background(), invoice) - if err != nil { - return err - } - - printRespJSON(resp) - - return nil -} - -var lookupInvoiceCommand = cli.Command{ - Name: "lookupinvoice", - Category: "Payments", - Usage: "Lookup an existing invoice by its payment hash.", - ArgsUsage: "rhash", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "rhash", - Usage: "the 32 byte payment hash of the invoice to query for, the hash " + - "should be a hex-encoded string", - }, - }, - Action: actionDecorator(lookupInvoice), -} - -func lookupInvoice(ctx *cli.Context) error { - client, cleanUp := getClient(ctx) - defer cleanUp() - - var ( - rHash []byte - err error - ) - - switch { - case ctx.IsSet("rhash"): - rHash, err = hex.DecodeString(ctx.String("rhash")) - case ctx.Args().Present(): - rHash, err = hex.DecodeString(ctx.Args().First()) - default: - return fmt.Errorf("rhash argument missing") - } - - if err != nil { - return fmt.Errorf("unable to decode rhash argument: %v", err) - } - - req := &lnrpc.PaymentHash{ - RHash: rHash, - } - - invoice, err := client.LookupInvoice(context.Background(), req) - if err != nil { - return err - } - - printRespJSON(invoice) - - return nil -} - -var listInvoicesCommand = cli.Command{ - Name: "listinvoices", - Category: "Payments", - Usage: "List all invoices currently stored within the database. Any " + - "active debug invoices are ignored.", - Description: ` - This command enables the retrieval of all invoices currently stored - within the database. It has full support for paginationed responses, - allowing users to query for specific invoices through their add_index. - This can be done by using either the first_index_offset or - last_index_offset fields included in the response as the index_offset of - the next request. Backward pagination is enabled by default to receive - current invoices first. If you wish to paginate forwards, set the - paginate-forwards flag. If none of the parameters are specified, then - the last 100 invoices will be returned. - - For example: if you have 200 invoices, "lncli listinvoices" will return - the last 100 created. If you wish to retrieve the previous 100, the - first_offset_index of the response can be used as the index_offset of - the next listinvoices request.`, - Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "pending_only", - Usage: "toggles if all invoices should be returned, " + - "or only those that are currently unsettled", - }, - cli.Uint64Flag{ - Name: "index_offset", - Usage: "the index of an invoice that will be used as " + - "either the start or end of a query to " + - "determine which invoices should be returned " + - "in the response", - }, - cli.Uint64Flag{ - Name: "max_invoices", - Usage: "the max number of invoices to return", - }, - cli.BoolFlag{ - Name: "paginate-forwards", - Usage: "if set, invoices succeeding the " + - "index_offset will be returned", - }, - }, - Action: actionDecorator(listInvoices), -} - -func listInvoices(ctx *cli.Context) error { - client, cleanUp := getClient(ctx) - defer cleanUp() - - req := &lnrpc.ListInvoiceRequest{ - PendingOnly: ctx.Bool("pending_only"), - IndexOffset: ctx.Uint64("index_offset"), - NumMaxInvoices: ctx.Uint64("max_invoices"), - Reversed: !ctx.Bool("paginate-forwards"), - } - - invoices, err := client.ListInvoices(context.Background(), req) - if err != nil { - return err - } - - printRespJSON(invoices) - - return nil -} - var describeGraphCommand = cli.Command{ Name: "describegraph", Category: "Graph", @@ -2494,48 +2259,6 @@ func debugLevel(ctx *cli.Context) error { return nil } -var decodePayReqCommand = cli.Command{ - Name: "decodepayreq", - Category: "Payments", - Usage: "Decode a payment request.", - Description: "Decode the passed payment request revealing the destination, payment hash and value of the payment request", - ArgsUsage: "pay_req", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "pay_req", - Usage: "the bech32 encoded payment request", - }, - }, - Action: actionDecorator(decodePayReq), -} - -func decodePayReq(ctx *cli.Context) error { - ctxb := context.Background() - client, cleanUp := getClient(ctx) - defer cleanUp() - - var payreq string - - switch { - case ctx.IsSet("pay_req"): - payreq = ctx.String("pay_req") - case ctx.Args().Present(): - payreq = ctx.Args().First() - default: - return fmt.Errorf("pay_req argument missing") - } - - resp, err := client.DecodePayReq(ctxb, &lnrpc.PayReqString{ - PayReq: payreq, - }) - if err != nil { - return err - } - - printRespJSON(resp) - return nil -} - var listChainTxnsCommand = cli.Command{ Name: "listchaintxns", Category: "On-chain", From 323338875091ed310250b0981fde809f2f76eb78 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 3 Apr 2020 16:40:34 -0700 Subject: [PATCH 411/562] cmd/lncli: move invoice-related cmds to Invoices category The Payments category is getting quite large, so this commit breaks out the invoice-related commands into their own category. --- cmd/lncli/cmd_invoice.go | 8 ++++---- cmd/lncli/invoicesrpc_active.go | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/lncli/cmd_invoice.go b/cmd/lncli/cmd_invoice.go index d2d118edda..feb56553e2 100644 --- a/cmd/lncli/cmd_invoice.go +++ b/cmd/lncli/cmd_invoice.go @@ -12,7 +12,7 @@ import ( var addInvoiceCommand = cli.Command{ Name: "addinvoice", - Category: "Payments", + Category: "Invoices", Usage: "Add a new invoice.", Description: ` Add a new invoice, expressing intent for a future payment. @@ -129,7 +129,7 @@ func addInvoice(ctx *cli.Context) error { var lookupInvoiceCommand = cli.Command{ Name: "lookupinvoice", - Category: "Payments", + Category: "Invoices", Usage: "Lookup an existing invoice by its payment hash.", ArgsUsage: "rhash", Flags: []cli.Flag{ @@ -180,7 +180,7 @@ func lookupInvoice(ctx *cli.Context) error { var listInvoicesCommand = cli.Command{ Name: "listinvoices", - Category: "Payments", + Category: "Invoices", Usage: "List all invoices currently stored within the database. Any " + "active debug invoices are ignored.", Description: ` @@ -247,7 +247,7 @@ func listInvoices(ctx *cli.Context) error { var decodePayReqCommand = cli.Command{ Name: "decodepayreq", - Category: "Payments", + Category: "Invoices", Usage: "Decode a payment request.", Description: "Decode the passed payment request revealing the destination, payment hash and value of the payment request", ArgsUsage: "pay_req", diff --git a/cmd/lncli/invoicesrpc_active.go b/cmd/lncli/invoicesrpc_active.go index d769336d4a..c565e7fef6 100644 --- a/cmd/lncli/invoicesrpc_active.go +++ b/cmd/lncli/invoicesrpc_active.go @@ -34,7 +34,7 @@ func getInvoicesClient(ctx *cli.Context) (invoicesrpc.InvoicesClient, func()) { var settleInvoiceCommand = cli.Command{ Name: "settleinvoice", - Category: "Payments", + Category: "Invoices", Usage: "Reveal a preimage and use it to settle the corresponding invoice.", Description: ` Todo.`, @@ -88,7 +88,7 @@ func settleInvoice(ctx *cli.Context) error { var cancelInvoiceCommand = cli.Command{ Name: "cancelinvoice", - Category: "Payments", + Category: "Invoices", Usage: "Cancels a (hold) invoice", Description: ` Todo.`, @@ -141,7 +141,7 @@ func cancelInvoice(ctx *cli.Context) error { var addHoldInvoiceCommand = cli.Command{ Name: "addholdinvoice", - Category: "Payments", + Category: "Invoices", Usage: "Add a new hold invoice.", Description: ` Add a new invoice, expressing intent for a future payment. From 4800a841221d79ce8f9d399b19d843f572cf7954 Mon Sep 17 00:00:00 2001 From: bitromortac Date: Mon, 30 Mar 2020 10:45:38 +0200 Subject: [PATCH 412/562] channeldb: export sequenceNum in MPPayment Exports sequenceNum in MPPayment for later use in the rpcserver. --- channeldb/duplicate_payments.go | 2 +- channeldb/mp_payment.go | 4 ++-- channeldb/payments.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/channeldb/duplicate_payments.go b/channeldb/duplicate_payments.go index d5cbd1c2aa..c78e2804b7 100644 --- a/channeldb/duplicate_payments.go +++ b/channeldb/duplicate_payments.go @@ -162,7 +162,7 @@ func fetchDuplicatePayment(bucket kvdb.ReadBucket) (*MPPayment, error) { } payment := &MPPayment{ - sequenceNum: sequenceNum, + SequenceNum: sequenceNum, Info: creationInfo, FailureReason: failureReason, Status: paymentStatus, diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index e359ff03df..fd89f3ab45 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -108,9 +108,9 @@ type HTLCFailInfo struct { // have the associated Settle or Fail struct populated if the HTLC is no longer // in-flight. type MPPayment struct { - // sequenceNum is a unique identifier used to sort the payments in + // SequenceNum is a unique identifier used to sort the payments in // order of creation. - sequenceNum uint64 + SequenceNum uint64 // Info holds all static information about this payment, and is // populated when the payment is initiated. diff --git a/channeldb/payments.go b/channeldb/payments.go index 6c5730435f..c355a06b97 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -246,7 +246,7 @@ func (db *DB) FetchPayments() ([]*MPPayment, error) { // Before returning, sort the payments by their sequence number. sort.Slice(payments, func(i, j int) bool { - return payments[i].sequenceNum < payments[j].sequenceNum + return payments[i].SequenceNum < payments[j].SequenceNum }) return payments, nil @@ -334,7 +334,7 @@ func fetchPayment(bucket kvdb.ReadBucket) (*MPPayment, error) { } return &MPPayment{ - sequenceNum: sequenceNum, + SequenceNum: sequenceNum, Info: creationInfo, HTLCs: htlcs, FailureReason: failureReason, From 4c5e8aec41dbd0223ef57abc45a0e39b8e46626f Mon Sep 17 00:00:00 2001 From: bitromortac Date: Fri, 17 Jan 2020 07:23:21 +0100 Subject: [PATCH 413/562] channeldb: add payments query Adds a PaymentsQuery struct, which contains parameters to restrict the response of QueryPayments, returning a PaymentsQuerySlice with the payments query result. The behavior of this api is the same as the QueryInvoices one. --- channeldb/payments.go | 135 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/channeldb/payments.go b/channeldb/payments.go index c355a06b97..7c5f49a2af 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "fmt" "io" + "math" "sort" "time" @@ -423,6 +424,140 @@ func fetchHtlcFailInfo(bucket kvdb.ReadBucket) (*HTLCFailInfo, error) { return deserializeHTLCFailInfo(r) } +// PaymentsQuery represents a query to the payments database starting or ending +// at a certain offset index. The number of retrieved records can be limited. +type PaymentsQuery struct { + // IndexOffset determines the starting point of the payments query and + // is always exclusive. In normal order, the query starts at the next + // higher (available) index compared to IndexOffset. In reversed order, + // the query ends at the next lower (available) index compared to the + // IndexOffset. In the case of a zero index_offset, the query will start + // with the oldest payment when paginating forwards, or will end with + // the most recent payment when paginating backwards. + IndexOffset uint64 + + // MaxPayments is the maximal number of payments returned in the + // payments query. + MaxPayments uint64 + + // Reversed gives a meaning to the IndexOffset. If reversed is set to + // true, the query will fetch payments with indices lower than the + // IndexOffset, otherwise, it will return payments with indices greater + // than the IndexOffset. + Reversed bool + + // If IncludeIncomplete is true, then return payments that have not yet + // fully completed. This means that pending payments, as well as failed + // payments will show up if this field is set to true. + IncludeIncomplete bool +} + +// PaymentsResponse contains the result of a query to the payments database. +// It includes the set of payments that match the query and integers which +// represent the index of the first and last item returned in the series of +// payments. These integers allow callers to resume their query in the event +// that the query's response exceeds the max number of returnable events. +type PaymentsResponse struct { + // Payments is the set of payments returned from the database for the + // PaymentsQuery. + Payments []MPPayment + + // FirstIndexOffset is the index of the first element in the set of + // returned MPPayments. Callers can use this to resume their query + // in the event that the slice has too many events to fit into a single + // response. The offset can be used to continue reverse pagination. + FirstIndexOffset uint64 + + // LastIndexOffset is the index of the last element in the set of + // returned MPPayments. Callers can use this to resume their query + // in the event that the slice has too many events to fit into a single + // response. The offset can be used to continue forward pagination. + LastIndexOffset uint64 +} + +// QueryPayments is a query to the payments database which is restricted +// to a subset of payments by the payments query, containing an offset +// index and a maximum number of returned payments. +func (db *DB) QueryPayments(query PaymentsQuery) (PaymentsResponse, error) { + var resp PaymentsResponse + + allPayments, err := db.FetchPayments() + if err != nil { + return resp, err + } + + if len(allPayments) == 0 { + return resp, nil + } + + indexExclusiveLimit := query.IndexOffset + // In backward pagination, if the index limit is the default 0 value, + // we set our limit to maxint to include all payments from the highest + // sequence number on. + if query.Reversed && indexExclusiveLimit == 0 { + indexExclusiveLimit = math.MaxInt64 + } + + for i := range allPayments { + var payment *MPPayment + + // If we have the max number of payments we want, exit. + if uint64(len(resp.Payments)) == query.MaxPayments { + break + } + + if query.Reversed { + payment = allPayments[len(allPayments)-1-i] + + // In the reversed direction, skip over all payments + // that have sequence numbers greater than or equal to + // the index offset. We skip payments with equal index + // because the offset is exclusive. + if payment.SequenceNum >= indexExclusiveLimit { + continue + } + } else { + payment = allPayments[i] + + // In the forward direction, skip over all payments that + // have sequence numbers less than or equal to the index + // offset. We skip payments with equal indexes because + // the index offset is exclusive. + if payment.SequenceNum <= indexExclusiveLimit { + continue + } + } + + // To keep compatibility with the old API, we only return + // non-succeeded payments if requested. + if payment.Status != StatusSucceeded && + !query.IncludeIncomplete { + + continue + } + + resp.Payments = append(resp.Payments, *payment) + } + + // Need to swap the payments slice order if reversed order. + if query.Reversed { + for l, r := 0, len(resp.Payments)-1; l < r; l, r = l+1, r-1 { + resp.Payments[l], resp.Payments[r] = + resp.Payments[r], resp.Payments[l] + } + } + + // Set the first and last index of the returned payments so that the + // caller can resume from this point later on. + if len(resp.Payments) > 0 { + resp.FirstIndexOffset = resp.Payments[0].SequenceNum + resp.LastIndexOffset = + resp.Payments[len(resp.Payments)-1].SequenceNum + } + + return resp, err +} + // DeletePayments deletes all completed and failed payments from the DB. func (db *DB) DeletePayments() error { return kvdb.Update(db, func(tx kvdb.RwTx) error { From d5dd48fa71f70cd64eb1a852e646119a20cfb2d0 Mon Sep 17 00:00:00 2001 From: bitromortac Date: Fri, 17 Jan 2020 07:31:07 +0100 Subject: [PATCH 414/562] channeldb/test: unit tests for payments query Adds tests for the payments query, where different edge cases for the index offsets and normal and reversed orders are tested. --- channeldb/payments_test.go | 263 +++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) diff --git a/channeldb/payments_test.go b/channeldb/payments_test.go index 3cf3a4bab3..1c6f09e694 100644 --- a/channeldb/payments_test.go +++ b/channeldb/payments_test.go @@ -3,6 +3,7 @@ package channeldb import ( "bytes" "fmt" + "math" "math/rand" "reflect" "testing" @@ -10,6 +11,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing/route" @@ -175,3 +177,264 @@ func TestRouteSerialization(t *testing.T) { spew.Sdump(testRoute), spew.Sdump(route2)) } } + +// deletePayment removes a payment with paymentHash from the payments database. +func deletePayment(t *testing.T, db *DB, paymentHash lntypes.Hash) { + t.Helper() + + err := kvdb.Update(db, func(tx kvdb.RwTx) error { + payments := tx.ReadWriteBucket(paymentsRootBucket) + + err := payments.DeleteNestedBucket(paymentHash[:]) + if err != nil { + return err + } + + return nil + }) + + if err != nil { + t.Fatalf("could not delete "+ + "payment: %v", err) + } +} + +// TestQueryPayments tests retrieval of payments with forwards and reversed +// queries. +func TestQueryPayments(t *testing.T) { + // Define table driven test for QueryPayments. + // Test payments have sequence indices [1, 3, 4, 5, 6, 7]. + tests := []struct { + name string + query PaymentsQuery + firstIndex uint64 + lastIndex uint64 + + // expectedSeqNrs contains the set of sequence numbers we expect + // our query to return. + expectedSeqNrs []uint64 + }{ + { + name: "IndexOffset at the end of the payments range", + query: PaymentsQuery{ + IndexOffset: 7, + MaxPayments: 7, + Reversed: false, + IncludeIncomplete: true, + }, + firstIndex: 0, + lastIndex: 0, + expectedSeqNrs: nil, + }, + { + name: "query in forwards order, start at beginning", + query: PaymentsQuery{ + IndexOffset: 0, + MaxPayments: 2, + Reversed: false, + IncludeIncomplete: true, + }, + firstIndex: 1, + lastIndex: 3, + expectedSeqNrs: []uint64{1, 3}, + }, + { + name: "query in forwards order, start at end, overflow", + query: PaymentsQuery{ + IndexOffset: 6, + MaxPayments: 2, + Reversed: false, + IncludeIncomplete: true, + }, + firstIndex: 7, + lastIndex: 7, + expectedSeqNrs: []uint64{7}, + }, + { + name: "start at offset index outside of payments", + query: PaymentsQuery{ + IndexOffset: 20, + MaxPayments: 2, + Reversed: false, + IncludeIncomplete: true, + }, + firstIndex: 0, + lastIndex: 0, + expectedSeqNrs: nil, + }, + { + name: "overflow in forwards order", + query: PaymentsQuery{ + IndexOffset: 4, + MaxPayments: math.MaxUint64, + Reversed: false, + IncludeIncomplete: true, + }, + firstIndex: 5, + lastIndex: 7, + expectedSeqNrs: []uint64{5, 6, 7}, + }, + { + name: "start at offset index outside of payments, " + + "reversed order", + query: PaymentsQuery{ + IndexOffset: 9, + MaxPayments: 2, + Reversed: true, + IncludeIncomplete: true, + }, + firstIndex: 6, + lastIndex: 7, + expectedSeqNrs: []uint64{6, 7}, + }, + { + name: "query in reverse order, start at end", + query: PaymentsQuery{ + IndexOffset: 0, + MaxPayments: 2, + Reversed: true, + IncludeIncomplete: true, + }, + firstIndex: 6, + lastIndex: 7, + expectedSeqNrs: []uint64{6, 7}, + }, + { + name: "query in reverse order, starting in middle", + query: PaymentsQuery{ + IndexOffset: 4, + MaxPayments: 2, + Reversed: true, + IncludeIncomplete: true, + }, + firstIndex: 1, + lastIndex: 3, + expectedSeqNrs: []uint64{1, 3}, + }, + { + name: "query in reverse order, starting in middle, " + + "with underflow", + query: PaymentsQuery{ + IndexOffset: 4, + MaxPayments: 5, + Reversed: true, + IncludeIncomplete: true, + }, + firstIndex: 1, + lastIndex: 3, + expectedSeqNrs: []uint64{1, 3}, + }, + { + name: "all payments in reverse, order maintained", + query: PaymentsQuery{ + IndexOffset: 0, + MaxPayments: 7, + Reversed: true, + IncludeIncomplete: true, + }, + firstIndex: 1, + lastIndex: 7, + expectedSeqNrs: []uint64{1, 3, 4, 5, 6, 7}, + }, + { + name: "exclude incomplete payments", + query: PaymentsQuery{ + IndexOffset: 0, + MaxPayments: 7, + Reversed: false, + IncludeIncomplete: false, + }, + firstIndex: 0, + lastIndex: 0, + expectedSeqNrs: nil, + }, + { + name: "query payments at index gap", + query: PaymentsQuery{ + IndexOffset: 1, + MaxPayments: 7, + Reversed: false, + IncludeIncomplete: true, + }, + firstIndex: 3, + lastIndex: 7, + expectedSeqNrs: []uint64{3, 4, 5, 6, 7}, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + db, err := initDB() + if err != nil { + t.Fatalf("unable to init db: %v", err) + } + + // Populate the database with a set of test payments. + numberOfPayments := 7 + pControl := NewPaymentControl(db) + + for i := 0; i < numberOfPayments; i++ { + // Generate a test payment. + info, _, _, err := genInfo() + if err != nil { + t.Fatalf("unable to create test "+ + "payment: %v", err) + } + + // Create a new payment entry in the database. + err = pControl.InitPayment(info.PaymentHash, info) + if err != nil { + t.Fatalf("unable to initialize "+ + "payment in database: %v", err) + } + + // Immediately delete the payment with index 2. + if i == 1 { + deletePayment(t, db, info.PaymentHash) + } + } + + // Fetch all payments in the database. + allPayments, err := db.FetchPayments() + if err != nil { + t.Fatalf("payments could not be fetched from "+ + "database: %v", err) + } + + if len(allPayments) != 6 { + t.Fatalf("Number of payments received does not "+ + "match expected one. Got %v, want %v.", + len(allPayments), 6) + } + + querySlice, err := db.QueryPayments(tt.query) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if tt.firstIndex != querySlice.FirstIndexOffset || + tt.lastIndex != querySlice.LastIndexOffset { + t.Errorf("First or last index does not match "+ + "expected index. Want (%d, %d), got (%d, %d).", + tt.firstIndex, tt.lastIndex, + querySlice.FirstIndexOffset, + querySlice.LastIndexOffset) + } + + if len(querySlice.Payments) != len(tt.expectedSeqNrs) { + t.Errorf("expected: %v payments, got: %v", + len(allPayments), len(querySlice.Payments)) + } + + for i, seqNr := range tt.expectedSeqNrs { + q := querySlice.Payments[i] + if seqNr != q.SequenceNum { + t.Errorf("sequence numbers do not match, "+ + "got %v, want %v", q.SequenceNum, seqNr) + } + } + }) + } +} From 39c58d9d149ad80820dd5fe5fa17d992db3af5ef Mon Sep 17 00:00:00 2001 From: bitromortac Date: Fri, 17 Jan 2020 07:35:03 +0100 Subject: [PATCH 415/562] lnrpc: use queried payments to list payments in the rpc Changes the grpc proto file, generates the protobuf, and enables a queried way to retrieve payments in the rpc, where backward compatibility is enforced by returning all payments in the database by default. Adds a payment index field to the returned payments of the rpc call. --- lnrpc/rpc.pb.go | 1582 +++++++++++++++++++++------------------- lnrpc/rpc.proto | 41 +- lnrpc/rpc.swagger.json | 41 +- rpcserver.go | 32 +- 4 files changed, 930 insertions(+), 766 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index de67ce9757..2fcf8553c6 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -9499,10 +9499,15 @@ type Payment struct { /// The time in UNIX nanoseconds at which the payment was created. CreationTimeNs int64 `protobuf:"varint,13,opt,name=creation_time_ns,json=creationTimeNs,proto3" json:"creation_time_ns,omitempty"` /// The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. - Htlcs []*HTLCAttempt `protobuf:"bytes,14,rep,name=htlcs,proto3" json:"htlcs,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Htlcs []*HTLCAttempt `protobuf:"bytes,14,rep,name=htlcs,proto3" json:"htlcs,omitempty"` + //* + //The creation index of this payment. Each payment can be uniquely identified + //by this index, which may not strictly increment by 1 for payments made in + //older versions of lnd. + PaymentIndex uint64 `protobuf:"varint,15,opt,name=payment_index,json=paymentIndex,proto3" json:"payment_index,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Payment) Reset() { *m = Payment{} } @@ -9632,6 +9637,13 @@ func (m *Payment) GetHtlcs() []*HTLCAttempt { return nil } +func (m *Payment) GetPaymentIndex() uint64 { + if m != nil { + return m.PaymentIndex + } + return 0 +} + type HTLCAttempt struct { /// The status of the HTLC. Status HTLCAttempt_HTLCStatus `protobuf:"varint,1,opt,name=status,proto3,enum=lnrpc.HTLCAttempt_HTLCStatus" json:"status,omitempty"` @@ -9714,8 +9726,23 @@ type ListPaymentsRequest struct { //* //If true, then return payments that have not yet fully completed. This means //that pending payments, as well as failed payments will show up if this - //field is set to True. - IncludeIncomplete bool `protobuf:"varint,1,opt,name=include_incomplete,json=includeIncomplete,proto3" json:"include_incomplete,omitempty"` + //field is set to true. This flag doesn't change the meaning of the indices, + //which are tied to individual payments. + IncludeIncomplete bool `protobuf:"varint,1,opt,name=include_incomplete,json=includeIncomplete,proto3" json:"include_incomplete,omitempty"` + //* + //The index of a payment that will be used as either the start or end of a + //query to determine which payments should be returned in the response. The + //index_offset is exclusive. In the case of a zero index_offset, the query + //will start with the oldest payment when paginating forwards, or will end + //with the most recent payment when paginating backwards. + IndexOffset uint64 `protobuf:"varint,2,opt,name=index_offset,json=indexOffset,proto3" json:"index_offset,omitempty"` + /// The maximal number of payments returned in the response to this query. + MaxPayments uint64 `protobuf:"varint,3,opt,name=max_payments,json=maxPayments,proto3" json:"max_payments,omitempty"` + //* + //If set, the payments returned will result from seeking backwards from the + //specified index offset. This can be used to paginate backwards. The order + //of the returned payments is always oldest first (ascending index order). + Reversed bool `protobuf:"varint,4,opt,name=reversed,proto3" json:"reversed,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -9753,12 +9780,41 @@ func (m *ListPaymentsRequest) GetIncludeIncomplete() bool { return false } +func (m *ListPaymentsRequest) GetIndexOffset() uint64 { + if m != nil { + return m.IndexOffset + } + return 0 +} + +func (m *ListPaymentsRequest) GetMaxPayments() uint64 { + if m != nil { + return m.MaxPayments + } + return 0 +} + +func (m *ListPaymentsRequest) GetReversed() bool { + if m != nil { + return m.Reversed + } + return false +} + type ListPaymentsResponse struct { /// The list of payments - Payments []*Payment `protobuf:"bytes,1,rep,name=payments,proto3" json:"payments,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Payments []*Payment `protobuf:"bytes,1,rep,name=payments,proto3" json:"payments,omitempty"` + //* + //The index of the first item in the set of returned payments. This can be + //used as the index_offset to continue seeking backwards in the next request. + FirstIndexOffset uint64 `protobuf:"varint,2,opt,name=first_index_offset,json=firstIndexOffset,proto3" json:"first_index_offset,omitempty"` + //* + //The index of the last item in the set of returned payments. This can be used + //as the index_offset to continue seeking forwards in the next request. + LastIndexOffset uint64 `protobuf:"varint,3,opt,name=last_index_offset,json=lastIndexOffset,proto3" json:"last_index_offset,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ListPaymentsResponse) Reset() { *m = ListPaymentsResponse{} } @@ -9793,6 +9849,20 @@ func (m *ListPaymentsResponse) GetPayments() []*Payment { return nil } +func (m *ListPaymentsResponse) GetFirstIndexOffset() uint64 { + if m != nil { + return m.FirstIndexOffset + } + return 0 +} + +func (m *ListPaymentsResponse) GetLastIndexOffset() uint64 { + if m != nil { + return m.LastIndexOffset + } + return 0 +} + type DeleteAllPaymentsRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -11878,750 +11948,754 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11879 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x6c, 0x24, 0x49, - 0x72, 0xd8, 0xf4, 0x8b, 0xdd, 0x1d, 0xfd, 0x60, 0x33, 0xf9, 0xea, 0xe1, 0xcc, 0xec, 0xcc, 0xd6, - 0xee, 0xed, 0xce, 0xce, 0xde, 0x71, 0x66, 0xe7, 0x6e, 0x76, 0xef, 0x76, 0xad, 0xd3, 0x35, 0xc9, - 0xe6, 0xb0, 0x6f, 0xf8, 0xda, 0xea, 0xe6, 0xae, 0xe6, 0xf4, 0xa8, 0x2b, 0x76, 0x27, 0xc9, 0xd2, - 0x74, 0x57, 0xf5, 0x56, 0x55, 0xf3, 0x71, 0x87, 0xf5, 0x87, 0x61, 0x1b, 0x82, 0x61, 0x1b, 0x10, - 0x6c, 0x19, 0xb0, 0x6c, 0xc1, 0x0f, 0xc1, 0x30, 0x0c, 0x03, 0x82, 0x80, 0x93, 0x3f, 0x0c, 0xf8, - 0x5f, 0x3f, 0x7e, 0xc0, 0x90, 0xfc, 0x63, 0x08, 0x02, 0x0c, 0xdb, 0xf2, 0x9f, 0x21, 0xc0, 0xdf, - 0x06, 0x8c, 0x8c, 0xc8, 0xac, 0xca, 0xea, 0x2e, 0xce, 0xcc, 0xde, 0x9d, 0xef, 0x87, 0xec, 0x8a, - 0x8c, 0x7c, 0x47, 0x46, 0x46, 0x64, 0x44, 0x64, 0x42, 0xd9, 0x1f, 0xf7, 0xd7, 0xc7, 0xbe, 0x17, - 0x7a, 0xac, 0x30, 0x74, 0xfd, 0x71, 0x7f, 0xed, 0xf6, 0xa9, 0xe7, 0x9d, 0x0e, 0xf9, 0x43, 0x7b, - 0xec, 0x3c, 0xb4, 0x5d, 0xd7, 0x0b, 0xed, 0xd0, 0xf1, 0xdc, 0x80, 0x90, 0x8c, 0x1f, 0x42, 0xfd, - 0x29, 0x77, 0xbb, 0x9c, 0x0f, 0x4c, 0xfe, 0xc5, 0x84, 0x07, 0x21, 0x7b, 0x1f, 0x16, 0x6c, 0xfe, - 0x23, 0xce, 0x07, 0xd6, 0xd8, 0x0e, 0x82, 0xf1, 0x99, 0x6f, 0x07, 0xbc, 0x99, 0xb9, 0x97, 0xb9, - 0x5f, 0x35, 0x1b, 0x94, 0x70, 0x18, 0xc1, 0xd9, 0x9b, 0x50, 0x0d, 0x04, 0x2a, 0x77, 0x43, 0xdf, - 0x1b, 0x5f, 0x35, 0xb3, 0x88, 0x57, 0x11, 0xb0, 0x36, 0x81, 0x8c, 0x21, 0xcc, 0x47, 0x35, 0x04, - 0x63, 0xcf, 0x0d, 0x38, 0x7b, 0x04, 0x4b, 0x7d, 0x67, 0x7c, 0xc6, 0x7d, 0x0b, 0x33, 0x8f, 0x5c, - 0x3e, 0xf2, 0x5c, 0xa7, 0xdf, 0xcc, 0xdc, 0xcb, 0xdd, 0x2f, 0x9b, 0x8c, 0xd2, 0x44, 0x8e, 0x3d, - 0x99, 0xc2, 0xde, 0x85, 0x79, 0xee, 0x12, 0x9c, 0x0f, 0x30, 0x97, 0xac, 0xaa, 0x1e, 0x83, 0x45, - 0x06, 0xe3, 0xb7, 0xb2, 0xb0, 0xd0, 0x71, 0x9d, 0xf0, 0x73, 0x7b, 0x38, 0xe4, 0xa1, 0xea, 0xd3, - 0xbb, 0x30, 0x7f, 0x81, 0x00, 0xec, 0xd3, 0x85, 0xe7, 0x0f, 0x64, 0x8f, 0xea, 0x04, 0x3e, 0x94, - 0xd0, 0x6b, 0x5b, 0x96, 0xbd, 0xb6, 0x65, 0xa9, 0xc3, 0x95, 0xbb, 0x66, 0xb8, 0xde, 0x85, 0x79, - 0x9f, 0xf7, 0xbd, 0x73, 0xee, 0x5f, 0x59, 0x17, 0x8e, 0x3b, 0xf0, 0x2e, 0x9a, 0xf9, 0x7b, 0x99, - 0xfb, 0x05, 0xb3, 0xae, 0xc0, 0x9f, 0x23, 0x94, 0x6d, 0xc0, 0x7c, 0xff, 0xcc, 0x76, 0x5d, 0x3e, - 0xb4, 0x8e, 0xed, 0xfe, 0x8b, 0xc9, 0x38, 0x68, 0x16, 0xee, 0x65, 0xee, 0x57, 0x1e, 0xdf, 0x5c, - 0xc7, 0x59, 0x5d, 0xdf, 0x3c, 0xb3, 0xdd, 0x0d, 0x4c, 0xe9, 0xba, 0xf6, 0x38, 0x38, 0xf3, 0x42, - 0xb3, 0x2e, 0x73, 0x10, 0x38, 0x30, 0x96, 0x80, 0xe9, 0x23, 0x41, 0x63, 0x6f, 0xfc, 0xeb, 0x0c, - 0x2c, 0x1e, 0xb9, 0x43, 0xaf, 0xff, 0xe2, 0xa7, 0x1c, 0xa2, 0x94, 0x3e, 0x64, 0x5f, 0xb7, 0x0f, - 0xb9, 0xaf, 0xda, 0x87, 0x15, 0x58, 0x4a, 0x36, 0x56, 0xf6, 0x82, 0xc3, 0xb2, 0xc8, 0x7d, 0xca, - 0x55, 0xb3, 0x54, 0x37, 0xde, 0x83, 0x46, 0x7f, 0xe2, 0xfb, 0xdc, 0x9d, 0xe9, 0xc7, 0xbc, 0x84, - 0x47, 0x1d, 0x79, 0x13, 0xaa, 0x2e, 0xbf, 0x88, 0xd1, 0x24, 0xed, 0xba, 0xfc, 0x42, 0xa1, 0x18, - 0x4d, 0x58, 0x99, 0xae, 0x46, 0x36, 0xe0, 0x2f, 0x32, 0x90, 0x3f, 0x0a, 0x2f, 0x3d, 0xf6, 0x04, - 0xaa, 0xf6, 0x60, 0xe0, 0xf3, 0x20, 0xb0, 0xc2, 0xab, 0x31, 0xad, 0x94, 0xfa, 0x63, 0x26, 0xbb, - 0xd8, 0xa2, 0xa4, 0xde, 0xd5, 0x98, 0x9b, 0x15, 0x3b, 0xfe, 0x60, 0x4d, 0x28, 0xca, 0x4f, 0xac, - 0xb7, 0x6c, 0xaa, 0x4f, 0x76, 0x07, 0xc0, 0x1e, 0x79, 0x13, 0x37, 0xb4, 0x02, 0x3b, 0xc4, 0x11, - 0xcb, 0x99, 0x65, 0x82, 0x74, 0xed, 0x90, 0xdd, 0x82, 0xf2, 0xf8, 0x85, 0x15, 0xf4, 0x7d, 0x67, - 0x1c, 0x22, 0xf1, 0x94, 0xcd, 0xd2, 0xf8, 0x45, 0x17, 0xbf, 0xd9, 0xfb, 0x50, 0xf2, 0x26, 0xe1, - 0xd8, 0x73, 0xdc, 0x50, 0xd2, 0xcb, 0xbc, 0x6c, 0xc8, 0xc1, 0x24, 0x3c, 0x14, 0x60, 0x33, 0x42, - 0x60, 0x6f, 0x43, 0xad, 0xef, 0xb9, 0x27, 0x8e, 0x3f, 0x22, 0x8e, 0xd0, 0x9c, 0xc3, 0xba, 0x92, - 0x40, 0xe3, 0x0f, 0xb3, 0x50, 0xe9, 0xf9, 0xb6, 0x1b, 0xd8, 0x7d, 0x01, 0x60, 0xab, 0x50, 0x0c, - 0x2f, 0xad, 0x33, 0x3b, 0x38, 0xc3, 0xae, 0x96, 0xcd, 0xb9, 0xf0, 0x72, 0xc7, 0x0e, 0xce, 0xd8, - 0x0a, 0xcc, 0x51, 0x2b, 0xb1, 0x43, 0x39, 0x53, 0x7e, 0x89, 0x05, 0xe2, 0x4e, 0x46, 0x56, 0xb2, - 0xaa, 0x1c, 0x52, 0x4c, 0xc3, 0x9d, 0x8c, 0x36, 0x75, 0xb8, 0xe8, 0xfc, 0xb1, 0x98, 0x6e, 0xaa, - 0x80, 0xba, 0x57, 0x46, 0x08, 0xd6, 0xf1, 0x26, 0x54, 0x65, 0x32, 0x77, 0x4e, 0xcf, 0xa8, 0x8f, - 0x05, 0xb3, 0x42, 0x08, 0x08, 0x12, 0x25, 0x84, 0xce, 0x88, 0x5b, 0x41, 0x68, 0x8f, 0xc6, 0xb2, - 0x4b, 0x65, 0x01, 0xe9, 0x0a, 0x00, 0x26, 0x7b, 0xa1, 0x3d, 0xb4, 0x4e, 0x38, 0x0f, 0x9a, 0x45, - 0x99, 0x2c, 0x20, 0xdb, 0x9c, 0x07, 0xec, 0x6b, 0x50, 0x1f, 0xf0, 0x20, 0xb4, 0xe4, 0x64, 0xf0, - 0xa0, 0x59, 0xc2, 0x95, 0x5f, 0x13, 0xd0, 0x96, 0x02, 0xb2, 0xdb, 0x00, 0xbe, 0x7d, 0x61, 0x89, - 0x81, 0xe0, 0x97, 0xcd, 0x32, 0xcd, 0x82, 0x6f, 0x5f, 0xf4, 0x2e, 0x77, 0xf8, 0xa5, 0xa0, 0x9a, - 0xa7, 0x3c, 0xd4, 0x06, 0x2d, 0x90, 0xd4, 0x69, 0xec, 0x02, 0xd3, 0xc0, 0x5b, 0x3c, 0xb4, 0x9d, - 0x61, 0xc0, 0x3e, 0x84, 0x6a, 0xa8, 0x21, 0x23, 0x1b, 0xac, 0x44, 0x24, 0xa4, 0x65, 0x30, 0x13, - 0x78, 0xc6, 0x19, 0x94, 0xb6, 0x39, 0xdf, 0x75, 0x46, 0x4e, 0xc8, 0x56, 0xa0, 0x70, 0xe2, 0x5c, - 0x72, 0x22, 0xf6, 0xdc, 0xce, 0x0d, 0x93, 0x3e, 0xd9, 0x5d, 0x00, 0xfc, 0x61, 0x8d, 0x22, 0x6a, - 0xda, 0xb9, 0x61, 0x96, 0x11, 0xb6, 0x17, 0xd8, 0x21, 0x5b, 0x83, 0xe2, 0x98, 0xfb, 0x7d, 0xae, - 0xe6, 0x6d, 0xe7, 0x86, 0xa9, 0x00, 0x1b, 0x45, 0x28, 0x0c, 0x45, 0xe9, 0xc6, 0x1f, 0x17, 0xa0, - 0xd2, 0xe5, 0x6e, 0xb4, 0xca, 0x18, 0xe4, 0xc5, 0x80, 0xc8, 0x95, 0x85, 0xbf, 0xd9, 0x5b, 0x50, - 0xc1, 0xa1, 0x0b, 0x42, 0xdf, 0x71, 0x4f, 0x89, 0xaa, 0x37, 0xb2, 0xcd, 0x8c, 0x09, 0x02, 0xdc, - 0x45, 0x28, 0x6b, 0x40, 0xce, 0x1e, 0x29, 0xaa, 0x16, 0x3f, 0xd9, 0x4d, 0x28, 0xd9, 0xa3, 0x90, - 0x9a, 0x57, 0x45, 0x70, 0xd1, 0x1e, 0x85, 0xd8, 0xb4, 0x37, 0xa1, 0x3a, 0xb6, 0xaf, 0x46, 0x62, - 0x2d, 0x47, 0xe4, 0x50, 0x35, 0x2b, 0x12, 0x86, 0x04, 0xf1, 0x18, 0x16, 0x75, 0x14, 0x55, 0x79, - 0x21, 0xaa, 0x7c, 0x41, 0xc3, 0x96, 0x6d, 0x78, 0x17, 0xe6, 0x55, 0x1e, 0x9f, 0xfa, 0x83, 0x64, - 0x52, 0x36, 0xeb, 0x12, 0xac, 0x7a, 0x79, 0x1f, 0x1a, 0x27, 0x8e, 0x6b, 0x0f, 0xad, 0xfe, 0x30, - 0x3c, 0xb7, 0x06, 0x7c, 0x18, 0xda, 0x48, 0x31, 0x05, 0xb3, 0x8e, 0xf0, 0xcd, 0x61, 0x78, 0xbe, - 0x25, 0xa0, 0xec, 0xeb, 0x50, 0x3e, 0xe1, 0xdc, 0xc2, 0xc1, 0x6a, 0x96, 0x12, 0x0b, 0x4f, 0xcd, - 0x90, 0x59, 0x3a, 0x51, 0x73, 0xf5, 0x75, 0x68, 0x78, 0x93, 0xf0, 0xd4, 0x73, 0xdc, 0x53, 0x4b, - 0xf0, 0x3b, 0xcb, 0x19, 0x20, 0x0d, 0xe5, 0x37, 0xb2, 0x8f, 0x32, 0x66, 0x5d, 0xa5, 0x09, 0xce, - 0xd3, 0x19, 0xb0, 0x77, 0x60, 0x7e, 0x68, 0x07, 0xa1, 0x75, 0xe6, 0x8d, 0xad, 0xf1, 0xe4, 0xf8, - 0x05, 0xbf, 0x6a, 0xd6, 0x70, 0x20, 0x6a, 0x02, 0xbc, 0xe3, 0x8d, 0x0f, 0x11, 0x28, 0x28, 0x1b, - 0xdb, 0x49, 0x8d, 0x80, 0x7b, 0x99, 0xfb, 0x35, 0xb3, 0x2c, 0x20, 0x54, 0xe9, 0x73, 0x58, 0xc4, - 0xe9, 0xe9, 0x4f, 0x82, 0xd0, 0x1b, 0x59, 0x82, 0x57, 0xfb, 0x83, 0xa0, 0x59, 0x41, 0x5a, 0x7b, - 0x4f, 0x36, 0x56, 0x9b, 0xe3, 0xf5, 0x2d, 0x1e, 0x84, 0x9b, 0x88, 0x6c, 0x12, 0xae, 0xd8, 0xd0, - 0xaf, 0xcc, 0x85, 0xc1, 0x34, 0x9c, 0x7d, 0x1d, 0x98, 0x3d, 0x1c, 0x7a, 0x17, 0x56, 0xc0, 0x87, - 0x27, 0x96, 0x1c, 0xc4, 0x66, 0xfd, 0x5e, 0xe6, 0x7e, 0xc9, 0x6c, 0x60, 0x4a, 0x97, 0x0f, 0x4f, - 0x0e, 0x09, 0xce, 0x3e, 0x04, 0x5c, 0x4c, 0xd6, 0x09, 0xb7, 0xc3, 0x89, 0xcf, 0x83, 0xe6, 0xfc, - 0xbd, 0xdc, 0xfd, 0xfa, 0xe3, 0x85, 0x68, 0xbc, 0x10, 0xbc, 0xe1, 0x84, 0x66, 0x55, 0xe0, 0xc9, - 0xef, 0x60, 0x6d, 0x0b, 0x56, 0xd2, 0x9b, 0x24, 0x88, 0x4a, 0x8c, 0x8a, 0x20, 0xc6, 0xbc, 0x29, - 0x7e, 0xb2, 0x25, 0x28, 0x9c, 0xdb, 0xc3, 0x09, 0x97, 0x3c, 0x9d, 0x3e, 0x3e, 0xce, 0x7e, 0x3b, - 0x63, 0xfc, 0x51, 0x06, 0xaa, 0xd4, 0x4b, 0x29, 0x8b, 0xbc, 0x05, 0x35, 0x45, 0x0d, 0xdc, 0xf7, - 0x3d, 0x5f, 0x72, 0x35, 0x45, 0x79, 0x6d, 0x01, 0x13, 0xbb, 0x8a, 0x42, 0x1a, 0xfb, 0xdc, 0x19, - 0xd9, 0xa7, 0xaa, 0x68, 0x45, 0x4a, 0x87, 0x12, 0xcc, 0x3e, 0x88, 0xcb, 0xf3, 0xbd, 0x49, 0xc8, - 0xe5, 0x9e, 0x57, 0x95, 0xdd, 0x33, 0x05, 0x2c, 0x2a, 0x1d, 0xbf, 0x5e, 0x83, 0xce, 0x8d, 0xdf, - 0xc9, 0x00, 0x13, 0xcd, 0xee, 0x79, 0x54, 0x80, 0xa4, 0xd0, 0xe9, 0x9c, 0x99, 0xd7, 0x5e, 0x21, - 0xd9, 0x97, 0xad, 0x10, 0x03, 0x0a, 0xd4, 0xf6, 0x7c, 0x4a, 0xdb, 0x29, 0xe9, 0xfb, 0xf9, 0x52, - 0xae, 0x91, 0x37, 0xfe, 0x6b, 0x0e, 0x96, 0x36, 0x69, 0xcb, 0x6e, 0xf5, 0xfb, 0x7c, 0x1c, 0xad, - 0x9d, 0xbb, 0x50, 0x71, 0xbd, 0x01, 0x57, 0x14, 0x4b, 0x0d, 0x03, 0x01, 0xd2, 0xc8, 0xf5, 0xcc, - 0x76, 0x5c, 0x6a, 0x38, 0x0d, 0x66, 0x19, 0x21, 0xd8, 0xec, 0x77, 0x60, 0x7e, 0xcc, 0xdd, 0x81, - 0xbe, 0x44, 0x48, 0xa8, 0xaa, 0x49, 0xb0, 0x5c, 0x1d, 0x77, 0xa1, 0x72, 0x32, 0x21, 0x3c, 0xc1, - 0x58, 0xf2, 0x48, 0x03, 0x20, 0x41, 0x2d, 0xe2, 0x2f, 0xe3, 0x49, 0x70, 0x86, 0xa9, 0x05, 0x4c, - 0x2d, 0x8a, 0x6f, 0x91, 0x74, 0x07, 0x60, 0x30, 0x09, 0x42, 0xb9, 0x62, 0xe6, 0x30, 0xb1, 0x2c, - 0x20, 0xb4, 0x62, 0xbe, 0x01, 0x8b, 0x23, 0xfb, 0xd2, 0x42, 0xda, 0xb1, 0x1c, 0xd7, 0x3a, 0x19, - 0xe2, 0x9e, 0x53, 0x44, 0xbc, 0xc6, 0xc8, 0xbe, 0xfc, 0x4c, 0xa4, 0x74, 0xdc, 0x6d, 0x84, 0x0b, - 0xb6, 0xa2, 0xc4, 0x1d, 0x9f, 0x07, 0xdc, 0x3f, 0xe7, 0xc8, 0x09, 0xf2, 0x91, 0x4c, 0x63, 0x12, - 0x54, 0xb4, 0x68, 0x24, 0xfa, 0x1d, 0x0e, 0xfb, 0xb4, 0xec, 0xcd, 0xe2, 0xc8, 0x71, 0x77, 0xc2, - 0x61, 0x5f, 0xec, 0x2b, 0x82, 0x8f, 0x8c, 0xb9, 0x6f, 0xbd, 0xb8, 0xc0, 0x35, 0x9c, 0x47, 0xbe, - 0x71, 0xc8, 0xfd, 0x67, 0x17, 0x62, 0xeb, 0xef, 0x07, 0xc8, 0x88, 0xec, 0xab, 0x66, 0x05, 0x17, - 0x78, 0xa9, 0x1f, 0x08, 0x16, 0x64, 0x5f, 0x89, 0x45, 0x28, 0x5a, 0x6b, 0xe3, 0x2c, 0xf0, 0x01, - 0x16, 0x1f, 0x20, 0x47, 0xad, 0x61, 0x63, 0x5b, 0x32, 0x41, 0xd4, 0x13, 0x08, 0xaa, 0x57, 0x8d, - 0x3d, 0x19, 0xda, 0xa7, 0x01, 0xb2, 0x94, 0x9a, 0x59, 0x95, 0xc0, 0x6d, 0x01, 0x33, 0x3e, 0x27, - 0x21, 0x4b, 0x9b, 0x5b, 0xb9, 0x66, 0xc4, 0x56, 0x8f, 0x10, 0x9c, 0xd7, 0x92, 0x29, 0xbf, 0xd2, - 0x26, 0x2d, 0x9b, 0x32, 0x69, 0xc6, 0xef, 0x65, 0xa0, 0x2a, 0x4b, 0x46, 0xa1, 0x84, 0xad, 0x03, - 0x53, 0xb3, 0x18, 0x5e, 0x3a, 0x03, 0xeb, 0xf8, 0x2a, 0xe4, 0x01, 0x11, 0xcd, 0xce, 0x0d, 0xb3, - 0x21, 0xd3, 0x7a, 0x97, 0xce, 0x60, 0x43, 0xa4, 0xb0, 0x07, 0xd0, 0x48, 0xe0, 0x07, 0xa1, 0x4f, - 0x14, 0xbd, 0x73, 0xc3, 0xac, 0x6b, 0xd8, 0xdd, 0xd0, 0x17, 0x6b, 0x44, 0x88, 0x3c, 0x93, 0xd0, - 0x72, 0xdc, 0x01, 0xbf, 0x44, 0x32, 0xaa, 0x99, 0x15, 0x82, 0x75, 0x04, 0x68, 0xa3, 0x0e, 0x55, - 0xbd, 0x38, 0xe3, 0x14, 0x4a, 0x4a, 0x5e, 0x42, 0x81, 0x61, 0xaa, 0x49, 0x66, 0x39, 0x8c, 0x5a, - 0x72, 0x13, 0x4a, 0xc9, 0x16, 0x98, 0xc5, 0xf0, 0xb5, 0x2b, 0x36, 0xbe, 0x0b, 0x8d, 0x5d, 0x41, - 0x3c, 0xae, 0x20, 0x56, 0x29, 0xff, 0xad, 0xc0, 0x9c, 0xb6, 0x68, 0xca, 0xa6, 0xfc, 0x12, 0x7b, - 0xee, 0x99, 0x17, 0x84, 0xb2, 0x16, 0xfc, 0x6d, 0xfc, 0x71, 0x06, 0x58, 0x3b, 0x08, 0x9d, 0x91, - 0x1d, 0xf2, 0x6d, 0x1e, 0xb1, 0x85, 0x03, 0xa8, 0x8a, 0xd2, 0x7a, 0x5e, 0x8b, 0x04, 0x32, 0x12, - 0x28, 0xde, 0x97, 0xcb, 0x78, 0x36, 0xc3, 0xba, 0x8e, 0x4d, 0x6c, 0x3e, 0x51, 0x80, 0x58, 0x65, - 0xa1, 0xed, 0x9f, 0xf2, 0x10, 0xc5, 0x38, 0x29, 0xef, 0x03, 0x81, 0x84, 0x00, 0xb7, 0xf6, 0xcb, - 0xb0, 0x30, 0x53, 0x86, 0xce, 0x97, 0xcb, 0x29, 0x7c, 0x39, 0xa7, 0xf3, 0x65, 0x0b, 0x16, 0x13, - 0xed, 0x92, 0x94, 0xb6, 0x0a, 0x45, 0xb1, 0x20, 0x84, 0x70, 0x90, 0x21, 0xa9, 0xf2, 0x84, 0x73, - 0x21, 0x06, 0x3f, 0x84, 0xa5, 0x13, 0xce, 0x7d, 0x3b, 0xc4, 0x44, 0x5c, 0x31, 0x62, 0x86, 0x64, - 0xc1, 0x0b, 0x32, 0xad, 0x6b, 0x87, 0x87, 0xdc, 0x17, 0x33, 0x65, 0xfc, 0xf7, 0x0c, 0xcc, 0x0b, - 0x0e, 0xba, 0x67, 0xbb, 0x57, 0x6a, 0x9c, 0x76, 0x53, 0xc7, 0xe9, 0xbe, 0xb6, 0x19, 0x6a, 0xd8, - 0x5f, 0x75, 0x90, 0x72, 0xd3, 0x83, 0xc4, 0xee, 0x41, 0x35, 0xd1, 0xd6, 0x02, 0xb6, 0x15, 0x82, - 0xa8, 0x91, 0x3f, 0xfb, 0x30, 0xbe, 0x03, 0x8d, 0xb8, 0xd9, 0x72, 0x0c, 0x19, 0xe4, 0x05, 0x49, - 0xca, 0x02, 0xf0, 0xb7, 0xf1, 0x8f, 0x33, 0x84, 0xb8, 0xe9, 0x39, 0x91, 0x74, 0x2a, 0x10, 0x85, - 0xdc, 0xab, 0x10, 0xc5, 0xef, 0x6b, 0xa5, 0xfa, 0x9f, 0xbd, 0xb3, 0x62, 0xe9, 0x04, 0xdc, 0x1d, - 0x58, 0xf6, 0x70, 0x88, 0xcc, 0xb7, 0x64, 0x16, 0xc5, 0x77, 0x6b, 0x38, 0x34, 0xde, 0x85, 0x05, - 0xad, 0x75, 0x2f, 0xe9, 0xc7, 0x3e, 0xb0, 0x5d, 0x27, 0x08, 0x8f, 0xdc, 0x60, 0xac, 0x09, 0x6e, - 0xb7, 0xa0, 0x2c, 0x38, 0xac, 0x68, 0x19, 0x2d, 0xd9, 0x82, 0x29, 0x58, 0xae, 0x68, 0x57, 0x80, - 0x89, 0xf6, 0xa5, 0x4c, 0xcc, 0xca, 0x44, 0xfb, 0x12, 0x13, 0x8d, 0x6f, 0xc3, 0x62, 0xa2, 0x3c, - 0x59, 0xf5, 0x9b, 0x50, 0x98, 0x84, 0x97, 0x9e, 0x12, 0xcd, 0x2b, 0x92, 0x42, 0x84, 0x02, 0x68, - 0x52, 0x8a, 0xf1, 0x09, 0x2c, 0xec, 0xf3, 0x0b, 0xb9, 0x88, 0x55, 0x43, 0xde, 0x81, 0xfc, 0x2b, - 0x94, 0x42, 0x4c, 0x37, 0xd6, 0x81, 0xe9, 0x99, 0x65, 0xad, 0x9a, 0x8e, 0x98, 0x49, 0xe8, 0x88, - 0xc6, 0x3b, 0xc0, 0xba, 0xce, 0xa9, 0xbb, 0xc7, 0x83, 0xc0, 0x3e, 0x8d, 0x96, 0x7d, 0x03, 0x72, - 0xa3, 0xe0, 0x54, 0xf2, 0x28, 0xf1, 0xd3, 0xf8, 0x26, 0x2c, 0x26, 0xf0, 0x64, 0xc1, 0xb7, 0xa1, - 0x1c, 0x38, 0xa7, 0x2e, 0x0a, 0x56, 0xb2, 0xe8, 0x18, 0x60, 0x6c, 0xc3, 0xd2, 0x67, 0xdc, 0x77, - 0x4e, 0xae, 0x5e, 0x55, 0x7c, 0xb2, 0x9c, 0xec, 0x74, 0x39, 0x6d, 0x58, 0x9e, 0x2a, 0x47, 0x56, - 0x4f, 0xe4, 0x2b, 0x67, 0xb2, 0x64, 0xd2, 0x87, 0xc6, 0xf7, 0xb2, 0x3a, 0xdf, 0x33, 0x8e, 0x80, - 0x6d, 0x7a, 0xae, 0xcb, 0xfb, 0xe1, 0x21, 0xe7, 0x7e, 0x7c, 0x4a, 0x15, 0xd3, 0x6a, 0xe5, 0xf1, - 0xaa, 0x1c, 0xd9, 0x69, 0x66, 0x2a, 0x89, 0x98, 0x41, 0x7e, 0xcc, 0xfd, 0x11, 0x16, 0x5c, 0x32, - 0xf1, 0xb7, 0xb1, 0x0c, 0x8b, 0x89, 0x62, 0xa5, 0x5e, 0xff, 0x08, 0x96, 0xb7, 0x9c, 0xa0, 0x3f, - 0x5b, 0xe1, 0x2a, 0x14, 0xc7, 0x93, 0x63, 0x2b, 0xc9, 0x97, 0x9f, 0xf1, 0x2b, 0xa1, 0xed, 0x4d, - 0xe7, 0x90, 0x65, 0xfd, 0xf5, 0x0c, 0xe4, 0x77, 0x7a, 0xbb, 0x9b, 0x6c, 0x0d, 0x4a, 0x8e, 0xdb, - 0xf7, 0x46, 0x42, 0xf0, 0xa2, 0x3e, 0x47, 0xdf, 0xd7, 0x2e, 0xb0, 0x5b, 0x50, 0x46, 0x79, 0x4d, - 0xa8, 0xb6, 0x52, 0xf4, 0x29, 0x09, 0xc0, 0xae, 0xd7, 0x7f, 0x21, 0x74, 0x6a, 0x7e, 0x39, 0x76, - 0x7c, 0xd4, 0x9a, 0x95, 0x32, 0x9c, 0xa7, 0xbd, 0x3e, 0x4e, 0x20, 0x8d, 0xd8, 0xf8, 0xb7, 0x25, - 0x28, 0xca, 0xdd, 0x96, 0x76, 0xee, 0xd0, 0x39, 0xe7, 0xf1, 0xce, 0x2d, 0xbe, 0x84, 0x3c, 0xe0, - 0xf3, 0x91, 0x17, 0x46, 0x02, 0x1b, 0xcd, 0x41, 0x95, 0x80, 0x52, 0x64, 0xd3, 0x84, 0x06, 0x3a, - 0x62, 0xc8, 0x11, 0x52, 0x5f, 0xdf, 0xca, 0x6f, 0x41, 0x51, 0xed, 0xfd, 0xf9, 0x48, 0xa7, 0x99, - 0xeb, 0x93, 0xb4, 0xb6, 0x06, 0xa5, 0xbe, 0x3d, 0xb6, 0xfb, 0x4e, 0x78, 0x25, 0x19, 0x42, 0xf4, - 0x2d, 0x4a, 0x1f, 0x7a, 0x7d, 0x7b, 0x68, 0x1d, 0xdb, 0x43, 0xdb, 0xed, 0x73, 0xa9, 0xbb, 0x57, - 0x11, 0xb8, 0x41, 0x30, 0xa1, 0x9f, 0xcb, 0x76, 0x2a, 0x2c, 0x52, 0xe1, 0x65, 0xeb, 0x15, 0x9a, - 0x10, 0x2e, 0xbd, 0xd1, 0xc8, 0x11, 0x5a, 0x06, 0x89, 0x61, 0x39, 0xb3, 0x4c, 0x90, 0x6d, 0x8e, - 0xbd, 0x95, 0xc9, 0x17, 0x34, 0x74, 0x65, 0xaa, 0x8a, 0x80, 0x9f, 0xd3, 0x41, 0xc2, 0xac, 0x2c, - 0x96, 0xd3, 0x64, 0xb1, 0xf7, 0x61, 0x61, 0xe2, 0x06, 0x3c, 0x0c, 0x87, 0x7c, 0x10, 0xb5, 0xa5, - 0x82, 0x48, 0x8d, 0x28, 0x41, 0x35, 0x67, 0x1d, 0x16, 0xe9, 0xd0, 0x21, 0xb0, 0x43, 0x2f, 0x38, - 0x73, 0x02, 0x2b, 0x10, 0x1a, 0x12, 0xa9, 0xbb, 0x0b, 0x98, 0xd4, 0x95, 0x29, 0x5d, 0x52, 0x91, - 0x56, 0xa7, 0xf0, 0x7d, 0xde, 0xe7, 0xce, 0x39, 0x1f, 0xa0, 0x9c, 0x96, 0x33, 0x97, 0x13, 0x79, - 0x4c, 0x99, 0x88, 0x42, 0xf7, 0x64, 0x64, 0x4d, 0xc6, 0x03, 0x5b, 0x08, 0x2b, 0x75, 0x12, 0x86, - 0xdd, 0xc9, 0xe8, 0x88, 0x20, 0xec, 0x11, 0x28, 0x49, 0x4c, 0xca, 0x87, 0xf3, 0x09, 0x7e, 0x26, - 0x88, 0xd5, 0xac, 0x4a, 0x0c, 0x12, 0x14, 0x13, 0x32, 0x67, 0x63, 0x4a, 0xe6, 0x6c, 0x42, 0x71, - 0xec, 0x3b, 0xe7, 0x76, 0xc8, 0x9b, 0x0b, 0xc4, 0xc0, 0xe5, 0xa7, 0xe0, 0x0c, 0x8e, 0xeb, 0x84, - 0x8e, 0x1d, 0x7a, 0x7e, 0x93, 0x61, 0x5a, 0x0c, 0x60, 0x0f, 0x60, 0x01, 0x69, 0x24, 0x08, 0xed, - 0x70, 0x12, 0x48, 0x09, 0x74, 0x11, 0x89, 0x09, 0x65, 0xe8, 0x2e, 0xc2, 0x51, 0x08, 0x65, 0xdf, - 0x84, 0x15, 0x22, 0x0b, 0xcc, 0x21, 0x25, 0x6b, 0x14, 0x08, 0x96, 0x70, 0x28, 0x16, 0x31, 0x55, - 0xd0, 0xb7, 0x94, 0xaf, 0x85, 0x74, 0xf0, 0x04, 0x56, 0x25, 0x99, 0xcc, 0xe4, 0x5a, 0xc6, 0x5c, - 0x4b, 0x94, 0x3c, 0x95, 0x6d, 0x1d, 0x16, 0x44, 0x93, 0x9c, 0xbe, 0x25, 0x73, 0x8b, 0x95, 0xb0, - 0x22, 0x5a, 0x8f, 0x9a, 0xd2, 0x3c, 0x25, 0x9a, 0x98, 0xf6, 0x8c, 0x5f, 0xb1, 0xef, 0xc2, 0x3c, - 0x91, 0x0c, 0xaa, 0x57, 0xc8, 0xe9, 0xd7, 0x90, 0xd3, 0x2f, 0xab, 0x13, 0xce, 0x28, 0x15, 0x99, - 0x7d, 0xbd, 0x9f, 0xf8, 0x16, 0xcb, 0x61, 0xe8, 0x9c, 0xf0, 0xd0, 0x19, 0xf1, 0xe6, 0x2a, 0x11, - 0x98, 0xfa, 0x16, 0x2b, 0x75, 0x32, 0xc6, 0x94, 0x26, 0xf1, 0x05, 0xfa, 0x42, 0xda, 0x1d, 0x7a, - 0x01, 0x57, 0x47, 0x54, 0xcd, 0x9b, 0x72, 0x11, 0x0a, 0xa0, 0x92, 0x21, 0x85, 0x20, 0x4e, 0x4a, - 0x4f, 0x74, 0x90, 0x78, 0x0b, 0x89, 0xa1, 0x46, 0xba, 0x8f, 0x3a, 0x4c, 0x14, 0xbb, 0xf8, 0x99, - 0x7d, 0xa1, 0x38, 0xc8, 0x6d, 0x9c, 0x5f, 0x10, 0x20, 0xc9, 0x3b, 0x7e, 0x92, 0xa1, 0x0d, 0x51, - 0xf2, 0x8f, 0x40, 0x53, 0xef, 0x88, 0x73, 0x58, 0x9e, 0x3b, 0xbc, 0x92, 0xcc, 0x04, 0x08, 0x74, - 0xe0, 0x0e, 0x71, 0x35, 0x3b, 0xae, 0x8e, 0x42, 0xbc, 0xb7, 0xaa, 0x80, 0x88, 0x74, 0x17, 0x2a, - 0xe3, 0xc9, 0xf1, 0xd0, 0xe9, 0x13, 0x4a, 0x8e, 0x4a, 0x21, 0x10, 0x22, 0x08, 0xfd, 0x96, 0x28, - 0x8a, 0x30, 0xf2, 0x88, 0x51, 0x91, 0x30, 0x44, 0x41, 0xde, 0xce, 0x7d, 0x64, 0x27, 0x55, 0x13, - 0x7f, 0x1b, 0x1b, 0xb0, 0x94, 0x6c, 0xb4, 0xdc, 0x78, 0x1e, 0x40, 0x49, 0xf2, 0x2a, 0x75, 0xf0, - 0x51, 0xd7, 0x8e, 0xa2, 0x85, 0x8a, 0x16, 0xa5, 0x1b, 0xbf, 0x5f, 0x80, 0x45, 0x09, 0xdd, 0x14, - 0x43, 0xdb, 0x9d, 0x8c, 0x46, 0xb6, 0x9f, 0xc2, 0x04, 0x33, 0x2f, 0x67, 0x82, 0xd9, 0x19, 0x26, - 0x98, 0xd4, 0x7c, 0x89, 0x87, 0x26, 0x35, 0x5f, 0x31, 0x97, 0xa4, 0x8c, 0xe8, 0xe7, 0xa0, 0x35, - 0x09, 0xee, 0xd1, 0x79, 0xeb, 0x0c, 0xcb, 0x2e, 0xa4, 0xb0, 0x6c, 0x9d, 0xe1, 0xce, 0x4d, 0x31, - 0xdc, 0x37, 0x81, 0x88, 0x46, 0xcd, 0x7e, 0x91, 0xf4, 0x13, 0x84, 0xc9, 0xc3, 0xd4, 0x77, 0x61, - 0x7e, 0x9a, 0xc7, 0x11, 0x33, 0xad, 0xa7, 0x70, 0x38, 0x67, 0xc4, 0x71, 0xb7, 0xd2, 0x90, 0xcb, - 0x92, 0xc3, 0x39, 0x23, 0xbe, 0x8b, 0x29, 0x0a, 0xbf, 0x0d, 0x40, 0x75, 0xe3, 0xa2, 0x01, 0x5c, - 0x34, 0xef, 0x24, 0xe7, 0x42, 0x1f, 0xf5, 0x75, 0xf1, 0x31, 0xf1, 0x39, 0xae, 0xa2, 0x32, 0xe6, - 0xc4, 0x05, 0xf4, 0x11, 0xd4, 0xbd, 0x31, 0x77, 0xad, 0x98, 0xd7, 0x54, 0xb0, 0xa8, 0x86, 0x2c, - 0xaa, 0xa3, 0xe0, 0x66, 0x4d, 0xe0, 0x45, 0x9f, 0xec, 0x3b, 0x34, 0xc8, 0x5c, 0xcb, 0x59, 0xbd, - 0x26, 0x67, 0x1d, 0x11, 0xa3, 0x6f, 0xe3, 0x6f, 0x65, 0xa0, 0xa2, 0x35, 0x87, 0x2d, 0xc3, 0xc2, - 0xe6, 0xc1, 0xc1, 0x61, 0xdb, 0x6c, 0xf5, 0x3a, 0x9f, 0xb5, 0xad, 0xcd, 0xdd, 0x83, 0x6e, 0xbb, - 0x71, 0x43, 0x80, 0x77, 0x0f, 0x36, 0x5b, 0xbb, 0xd6, 0xf6, 0x81, 0xb9, 0xa9, 0xc0, 0x19, 0xb6, - 0x02, 0xcc, 0x6c, 0xef, 0x1d, 0xf4, 0xda, 0x09, 0x78, 0x96, 0x35, 0xa0, 0xba, 0x61, 0xb6, 0x5b, - 0x9b, 0x3b, 0x12, 0x92, 0x63, 0x4b, 0xd0, 0xd8, 0x3e, 0xda, 0xdf, 0xea, 0xec, 0x3f, 0xb5, 0x36, - 0x5b, 0xfb, 0x9b, 0xed, 0xdd, 0xf6, 0x56, 0x23, 0xcf, 0x6a, 0x50, 0x6e, 0x6d, 0xb4, 0xf6, 0xb7, - 0x0e, 0xf6, 0xdb, 0x5b, 0x8d, 0x82, 0xf1, 0xe7, 0x19, 0x58, 0xc6, 0x81, 0x1a, 0x4c, 0xaf, 0xd0, - 0x7b, 0x50, 0xe9, 0x7b, 0xde, 0x58, 0xa8, 0x41, 0xf1, 0x76, 0xaf, 0x83, 0xc4, 0xea, 0x23, 0xce, - 0x7a, 0xe2, 0xf9, 0x7d, 0x2e, 0x17, 0x28, 0x20, 0x68, 0x5b, 0x40, 0x04, 0x81, 0x48, 0x0a, 0x23, - 0x0c, 0x5a, 0x9f, 0x15, 0x82, 0x11, 0xca, 0x0a, 0xcc, 0x1d, 0xfb, 0xdc, 0xee, 0x9f, 0xc9, 0xa5, - 0x29, 0xbf, 0xd8, 0x7b, 0xb1, 0x82, 0xde, 0x17, 0x13, 0x3e, 0xe4, 0x03, 0xa4, 0xcf, 0x92, 0x39, - 0x2f, 0xe1, 0x9b, 0x12, 0x2c, 0xb6, 0x0a, 0xfb, 0xd8, 0x76, 0x07, 0x9e, 0xcb, 0x07, 0x52, 0x0f, - 0x88, 0x01, 0xc6, 0x21, 0xac, 0x4c, 0xf7, 0x4f, 0x2e, 0xe6, 0x0f, 0xb5, 0xc5, 0x4c, 0x62, 0xf9, - 0xda, 0xf5, 0x04, 0xa4, 0x2d, 0xec, 0xbf, 0x93, 0x87, 0xbc, 0x10, 0xd3, 0xae, 0x95, 0xe8, 0x74, - 0xb9, 0x3b, 0x37, 0x63, 0x9b, 0xc1, 0x73, 0x00, 0xda, 0xbf, 0xe9, 0xb0, 0xa9, 0x8c, 0x10, 0xdc, - 0xb7, 0xa3, 0x64, 0x9f, 0xf7, 0xcf, 0xe5, 0x69, 0x13, 0x25, 0x9b, 0xbc, 0x7f, 0x8e, 0x0a, 0x8f, - 0x1d, 0x52, 0x5e, 0x5a, 0x8c, 0xc5, 0xc0, 0x0e, 0x31, 0xa7, 0x4c, 0xc2, 0x7c, 0xc5, 0x28, 0x09, - 0x73, 0x35, 0xa1, 0xe8, 0xb8, 0xc7, 0xde, 0xc4, 0x1d, 0xe0, 0xda, 0x2b, 0x99, 0xea, 0x13, 0x4d, - 0x41, 0xc8, 0x26, 0xc4, 0x2e, 0x41, 0x4b, 0xad, 0x24, 0x00, 0x3d, 0xb1, 0x4f, 0x7c, 0x00, 0xe5, - 0xe0, 0xca, 0xed, 0xeb, 0x0b, 0x6c, 0x49, 0x8e, 0x8f, 0xe8, 0xfd, 0x7a, 0xf7, 0xca, 0xed, 0xe3, - 0x72, 0x2a, 0x05, 0xf2, 0x17, 0x7b, 0x02, 0xa5, 0xe8, 0x50, 0x96, 0xd8, 0xe3, 0x4d, 0x3d, 0x87, - 0x3a, 0x89, 0x25, 0xdd, 0x37, 0x42, 0x65, 0x0f, 0x61, 0x0e, 0x4f, 0x4e, 0x83, 0x66, 0x15, 0x33, - 0x29, 0x61, 0x5c, 0x34, 0x03, 0xad, 0x30, 0x7c, 0x80, 0xa7, 0xa8, 0xa6, 0x44, 0x5b, 0x7b, 0x06, - 0xb5, 0x44, 0x59, 0xba, 0x86, 0x5b, 0x23, 0x0d, 0xf7, 0x6d, 0x5d, 0xc3, 0x8d, 0xd9, 0xb4, 0xcc, - 0xa6, 0x6b, 0xbc, 0xbf, 0x0c, 0x25, 0xd5, 0x15, 0xb1, 0x88, 0x8e, 0xf6, 0x9f, 0xed, 0x1f, 0x7c, - 0xbe, 0x6f, 0x75, 0x9f, 0xef, 0x6f, 0x36, 0x6e, 0xb0, 0x79, 0xa8, 0xb4, 0x36, 0x71, 0x5d, 0x22, - 0x20, 0x23, 0x50, 0x0e, 0x5b, 0xdd, 0x6e, 0x04, 0xc9, 0x1a, 0xdb, 0xd0, 0x98, 0x6e, 0xa9, 0xa0, - 0xc9, 0x50, 0xc1, 0xe4, 0xb9, 0x72, 0x0c, 0x10, 0xfa, 0x0b, 0x1d, 0x15, 0x93, 0x90, 0x4c, 0x1f, - 0xc6, 0x13, 0x68, 0x88, 0x4d, 0x47, 0x0c, 0x55, 0xa0, 0x9d, 0xcf, 0x0e, 0x85, 0xe0, 0xa5, 0x9f, - 0x2d, 0x97, 0xcc, 0x0a, 0xc1, 0xb0, 0x2a, 0xe3, 0x43, 0x58, 0xd0, 0xb2, 0xc5, 0xfa, 0xa6, 0xd8, - 0xc8, 0xa6, 0xf5, 0x4d, 0xd4, 0x2e, 0x28, 0xc5, 0x58, 0x85, 0x65, 0xf1, 0xd9, 0x3e, 0xe7, 0x6e, - 0xd8, 0x9d, 0x1c, 0x93, 0x41, 0xd0, 0xf1, 0x5c, 0xa1, 0x75, 0x94, 0xa3, 0x94, 0xeb, 0x89, 0x7c, - 0x5d, 0xaa, 0xa6, 0x59, 0x24, 0x8d, 0x35, 0xad, 0x06, 0xcc, 0xb8, 0x8e, 0x7f, 0x13, 0x2a, 0x6a, - 0x39, 0x02, 0x89, 0x61, 0x3d, 0x6c, 0xb7, 0x4d, 0xeb, 0x60, 0x7f, 0xb7, 0xb3, 0x2f, 0xb8, 0x9d, - 0x18, 0x56, 0x04, 0x6c, 0x6f, 0x23, 0x24, 0x63, 0x34, 0xa0, 0xfe, 0x94, 0x87, 0x1d, 0xf7, 0xc4, - 0x53, 0xc6, 0xaf, 0xbf, 0x28, 0xc0, 0x7c, 0x04, 0x8a, 0x55, 0xdc, 0x73, 0xee, 0x07, 0x8e, 0xe7, - 0xa2, 0xb4, 0x5a, 0x36, 0xd5, 0xa7, 0xd8, 0x7a, 0x9c, 0x01, 0x77, 0x43, 0x27, 0xbc, 0xb2, 0x12, - 0xe7, 0x61, 0x75, 0x05, 0x96, 0x5b, 0xdc, 0x12, 0x14, 0xec, 0xa1, 0x63, 0x2b, 0x3b, 0x2a, 0x7d, - 0x08, 0x68, 0xdf, 0x1b, 0x7a, 0x3e, 0x0a, 0xa6, 0x65, 0x93, 0x3e, 0xd8, 0x23, 0x58, 0x12, 0x02, - 0xb2, 0x7e, 0x48, 0x89, 0xfc, 0x83, 0x8e, 0xe6, 0x98, 0x3b, 0x19, 0x1d, 0xc6, 0x07, 0x95, 0x22, - 0x45, 0x6c, 0x6c, 0x22, 0x87, 0x94, 0x64, 0xa2, 0x0c, 0xa4, 0x6b, 0x2d, 0xb8, 0x93, 0x51, 0x0b, - 0x53, 0x22, 0xfc, 0xc7, 0xb0, 0x2c, 0xf0, 0x23, 0xd9, 0x27, 0xca, 0x31, 0x8f, 0x39, 0x44, 0x61, - 0x1d, 0x99, 0x16, 0xe5, 0xb9, 0x05, 0x65, 0x6a, 0x95, 0x98, 0xf1, 0x02, 0xc9, 0xd8, 0xd8, 0x14, - 0xee, 0x07, 0x33, 0x26, 0xcf, 0x39, 0xda, 0xa5, 0xa7, 0x4c, 0x9e, 0x9a, 0xd1, 0xb4, 0x34, 0x6d, - 0x34, 0x7d, 0x0c, 0xcb, 0xc7, 0x82, 0x04, 0xcf, 0xb8, 0x3d, 0xe0, 0xbe, 0x15, 0x13, 0x36, 0xe9, - 0x12, 0x8b, 0x22, 0x71, 0x07, 0xd3, 0xa2, 0x75, 0x20, 0x84, 0x10, 0xc1, 0x16, 0xf8, 0xc0, 0x0a, - 0x3d, 0x0b, 0x65, 0x13, 0x64, 0x30, 0x25, 0xb3, 0x46, 0xe0, 0x9e, 0xb7, 0x29, 0x80, 0x49, 0xbc, - 0x53, 0xdf, 0x1e, 0x9f, 0x49, 0x69, 0x3f, 0xc2, 0x7b, 0x2a, 0x80, 0xec, 0x36, 0x14, 0x05, 0xc9, - 0xbb, 0x9c, 0x2c, 0x53, 0x24, 0x4f, 0x2b, 0x10, 0x7b, 0x1b, 0xe6, 0xb0, 0x8e, 0xa0, 0xd9, 0x40, - 0x7a, 0xaf, 0xc6, 0x8c, 0xdc, 0x71, 0x4d, 0x99, 0x26, 0x24, 0xbd, 0x89, 0xef, 0x10, 0x97, 0x29, - 0x9b, 0xf8, 0x9b, 0x7d, 0x4f, 0x63, 0x59, 0x8b, 0x98, 0xf7, 0x6d, 0x99, 0x77, 0x8a, 0xd2, 0xae, - 0xe3, 0x5e, 0x3f, 0x57, 0x66, 0xf4, 0xfd, 0x7c, 0xa9, 0xd2, 0xa8, 0x1a, 0x1f, 0x41, 0x81, 0x46, - 0x47, 0x10, 0x21, 0x8e, 0x5d, 0x46, 0x12, 0x21, 0x42, 0x9b, 0x50, 0x74, 0x79, 0x78, 0xe1, 0xf9, - 0x2f, 0xd4, 0x89, 0xb1, 0xfc, 0x34, 0x7e, 0x84, 0x47, 0x1d, 0x91, 0x39, 0x9c, 0xb4, 0x36, 0x41, - 0x1e, 0x34, 0xbd, 0xc1, 0x99, 0x2d, 0x4f, 0x5f, 0x4a, 0x08, 0xe8, 0x9e, 0xd9, 0x33, 0xe4, 0x91, - 0x9d, 0xb5, 0x88, 0xbf, 0x0d, 0x75, 0x65, 0x80, 0x0f, 0xac, 0x21, 0x3f, 0x09, 0x25, 0xb9, 0x57, - 0xa5, 0xf5, 0x3d, 0xd8, 0xe5, 0x27, 0xa1, 0xb1, 0x07, 0x0b, 0x92, 0x20, 0x0f, 0xc6, 0x5c, 0x55, - 0xfd, 0xed, 0x34, 0x61, 0xb7, 0xf2, 0x78, 0x31, 0xb9, 0xd1, 0x92, 0x63, 0x41, 0x42, 0x02, 0x36, - 0x3e, 0x05, 0xa6, 0x6f, 0xc3, 0xb2, 0x3c, 0x29, 0x72, 0xaa, 0x83, 0x76, 0x65, 0xaf, 0x8a, 0x04, - 0x5b, 0x67, 0x20, 0x46, 0x27, 0x98, 0xf4, 0xfb, 0xca, 0x31, 0xa2, 0x64, 0xaa, 0x4f, 0xe3, 0x4f, - 0x32, 0xb0, 0x88, 0x85, 0x29, 0x61, 0x5d, 0x32, 0xd9, 0x9f, 0xba, 0x91, 0x62, 0x7e, 0x74, 0xd9, - 0x87, 0x3e, 0xbe, 0xfa, 0xd1, 0x66, 0x7e, 0xe6, 0x68, 0xf3, 0x3d, 0x68, 0x0c, 0xf8, 0xd0, 0x41, - 0x1f, 0x19, 0x25, 0x4a, 0x90, 0x78, 0x3e, 0xaf, 0xe0, 0x52, 0x55, 0x33, 0xfe, 0x41, 0x06, 0x16, - 0x48, 0x52, 0x41, 0xa5, 0x57, 0x0e, 0xd4, 0x27, 0x4a, 0xcb, 0x93, 0xac, 0x4a, 0xf6, 0x29, 0xde, - 0xc1, 0x11, 0x4a, 0xc8, 0x3b, 0x37, 0xa4, 0xf6, 0x27, 0xa1, 0xec, 0x63, 0x54, 0x30, 0x5c, 0x0b, - 0x81, 0x29, 0x3e, 0x37, 0xc9, 0x49, 0xd9, 0xb9, 0x81, 0xda, 0x87, 0x8b, 0xa0, 0x8d, 0x92, 0x50, - 0x3b, 0x05, 0xd8, 0xd8, 0x86, 0x5a, 0xa2, 0x9a, 0xc4, 0xf9, 0x6b, 0x95, 0xce, 0x5f, 0x67, 0x6c, - 0x1c, 0xd9, 0x59, 0x1b, 0xc7, 0x15, 0x2c, 0x9a, 0xdc, 0x1e, 0x5c, 0x6d, 0x7b, 0xfe, 0x61, 0x70, - 0x1c, 0x6e, 0x93, 0xf8, 0x27, 0xf8, 0x7b, 0x64, 0xb8, 0x4b, 0x1c, 0x72, 0x2a, 0xfb, 0x8d, 0xd2, - 0x65, 0xbf, 0x06, 0xf5, 0xd8, 0xc2, 0xa7, 0x1d, 0x94, 0xd5, 0x22, 0x23, 0x1f, 0x9e, 0x97, 0x09, - 0x3d, 0x30, 0x38, 0x0e, 0xe5, 0x51, 0x19, 0xfe, 0x36, 0xfe, 0x46, 0x1e, 0x98, 0xa0, 0xe6, 0x29, - 0x82, 0x99, 0xb2, 0x4d, 0x66, 0x67, 0x6c, 0x93, 0x8f, 0x80, 0x69, 0x08, 0xca, 0x64, 0x9a, 0x8b, - 0x4c, 0xa6, 0x8d, 0x18, 0x57, 0x5a, 0x4c, 0x1f, 0xc1, 0x92, 0x94, 0xa5, 0x93, 0x4d, 0x25, 0xd2, - 0x60, 0x24, 0x54, 0x27, 0xda, 0xab, 0xec, 0x92, 0x42, 0x37, 0xa7, 0xa3, 0x30, 0xb4, 0x4b, 0x2a, - 0xad, 0x5c, 0x23, 0xc0, 0xb9, 0x57, 0x12, 0x60, 0x71, 0x86, 0x00, 0xb5, 0x93, 0x99, 0x52, 0xf2, - 0x64, 0xc6, 0x80, 0x9a, 0xb2, 0x3e, 0x92, 0xd3, 0x05, 0x09, 0x8e, 0x15, 0x69, 0x82, 0x44, 0xc7, - 0x8b, 0xfb, 0xd0, 0x50, 0xc7, 0x27, 0xd1, 0xd9, 0x0f, 0x39, 0x14, 0xc8, 0xd3, 0xb7, 0x4d, 0x75, - 0x02, 0x94, 0x38, 0x69, 0xaf, 0x4c, 0x9d, 0xb4, 0xbf, 0x0f, 0x0b, 0x81, 0xa0, 0x5f, 0x6b, 0xe2, - 0x4a, 0xef, 0x1f, 0x3e, 0x40, 0x35, 0xab, 0x64, 0x36, 0x30, 0xe1, 0x28, 0x86, 0xcf, 0x9e, 0x6b, - 0xd4, 0x52, 0xce, 0x35, 0x9e, 0xc4, 0x86, 0xba, 0xe0, 0xcc, 0x19, 0xa1, 0xcc, 0x10, 0x7b, 0xca, - 0xc8, 0x01, 0xee, 0x9e, 0x39, 0x23, 0x53, 0x59, 0x85, 0xc5, 0x87, 0xf1, 0x7f, 0x32, 0xd0, 0x10, - 0x74, 0x90, 0x58, 0x62, 0xdf, 0x01, 0x64, 0x06, 0xaf, 0xb9, 0xc2, 0x2a, 0x02, 0x57, 0x2d, 0xb0, - 0x8f, 0x00, 0x57, 0x8c, 0x25, 0x74, 0x4a, 0xb9, 0xbe, 0x9a, 0xc9, 0xf5, 0x15, 0xf3, 0xd0, 0x9d, - 0x1b, 0xa4, 0x7b, 0x08, 0x08, 0xfb, 0x0e, 0x94, 0x05, 0x61, 0x22, 0x95, 0x48, 0x07, 0x2d, 0x25, - 0x79, 0xa5, 0xac, 0x11, 0x91, 0x75, 0x2c, 0x3f, 0xd3, 0x6c, 0xab, 0xf9, 0x14, 0xdb, 0xaa, 0xb6, - 0x80, 0x77, 0x00, 0x9e, 0xf1, 0xab, 0x5d, 0xaf, 0x8f, 0x1a, 0xef, 0x1d, 0x00, 0x41, 0xcb, 0x27, - 0xf6, 0xc8, 0x91, 0x07, 0x36, 0x05, 0xb3, 0xfc, 0x82, 0x5f, 0x6d, 0x23, 0x40, 0x4c, 0xa4, 0x48, - 0x8e, 0x57, 0x71, 0xc1, 0x2c, 0xbd, 0xe0, 0x57, 0xb4, 0x84, 0x2d, 0xa8, 0x3d, 0xe3, 0x57, 0x5b, - 0x9c, 0x84, 0x4c, 0xcf, 0x17, 0x44, 0xe4, 0xdb, 0x17, 0x42, 0xaa, 0x4c, 0xd8, 0x45, 0x2b, 0xbe, - 0x7d, 0xf1, 0x8c, 0x5f, 0x29, 0x1b, 0x6d, 0x51, 0xa4, 0x0f, 0xbd, 0xbe, 0xdc, 0x37, 0x95, 0x87, - 0x47, 0xdc, 0x28, 0x73, 0xee, 0x05, 0xfe, 0x36, 0xfe, 0x32, 0x03, 0x35, 0xd1, 0x7e, 0x64, 0xcb, - 0x62, 0xca, 0x94, 0xa3, 0x50, 0x26, 0x76, 0x14, 0x7a, 0x2c, 0xb9, 0x1a, 0xf1, 0xf8, 0xec, 0xf5, - 0x3c, 0x1e, 0xe7, 0x86, 0x18, 0xfc, 0x07, 0x50, 0xa6, 0x65, 0x29, 0xd6, 0x79, 0x2e, 0x31, 0xc1, - 0x89, 0x0e, 0x99, 0x25, 0x44, 0x7b, 0x46, 0x7e, 0x09, 0xda, 0xe1, 0x1f, 0x0d, 0x71, 0xd9, 0x8f, - 0x8e, 0xfc, 0x52, 0xa6, 0xa1, 0x70, 0x8d, 0x5f, 0x82, 0x7e, 0xb2, 0x36, 0x37, 0x73, 0xb2, 0x76, - 0x00, 0x25, 0x31, 0xd5, 0xd8, 0xd9, 0x94, 0x42, 0x33, 0x69, 0x85, 0x0a, 0x49, 0xc0, 0x16, 0x9b, - 0x82, 0x60, 0x74, 0x59, 0x29, 0x09, 0xd8, 0x01, 0x3f, 0x44, 0x66, 0x97, 0x81, 0x8a, 0xb6, 0x02, - 0xf0, 0x70, 0x32, 0x1a, 0x2f, 0x5a, 0x2e, 0x49, 0x12, 0x4f, 0x0c, 0xf8, 0xce, 0x0d, 0xb3, 0xd6, - 0x4f, 0xcc, 0xc0, 0xba, 0xa4, 0x55, 0xcc, 0x99, 0x4d, 0xf8, 0x34, 0xa9, 0x86, 0x2b, 0x02, 0x15, - 0xbf, 0x37, 0xe6, 0x20, 0x2f, 0x50, 0x8d, 0x4f, 0x60, 0x41, 0x6b, 0x06, 0xa9, 0xf9, 0xaf, 0xdb, - 0x43, 0xe3, 0xd7, 0xa2, 0xcc, 0xa2, 0x0e, 0x32, 0x1f, 0x29, 0x1f, 0x0f, 0x3e, 0xa0, 0x8e, 0x4b, - 0x5f, 0x12, 0x02, 0x09, 0xb4, 0xd7, 0xf6, 0x3b, 0xf8, 0x0d, 0x58, 0xd4, 0x4a, 0xdf, 0x76, 0x5c, - 0x7b, 0xe8, 0xfc, 0x08, 0x37, 0xfc, 0xc0, 0x39, 0x75, 0xa7, 0xca, 0x27, 0xd0, 0x57, 0x2a, 0xff, - 0x1f, 0x66, 0x61, 0x49, 0x56, 0x80, 0x5e, 0x7b, 0x8e, 0x90, 0xe2, 0xf6, 0x82, 0x53, 0xf6, 0x1d, - 0xa8, 0x89, 0xb1, 0xb1, 0x7c, 0x7e, 0xea, 0x04, 0x21, 0x57, 0x66, 0xab, 0x14, 0xc6, 0x25, 0x36, - 0x73, 0x81, 0x6a, 0x4a, 0x4c, 0xf6, 0x09, 0x54, 0x30, 0x2b, 0x1d, 0xa3, 0xc8, 0x89, 0x68, 0xce, - 0x66, 0xa4, 0x81, 0xde, 0xb9, 0x61, 0x42, 0x10, 0x0f, 0xfb, 0x27, 0x50, 0xc1, 0x39, 0x3c, 0xc7, - 0x81, 0x9c, 0x62, 0x55, 0x33, 0x03, 0x2d, 0x32, 0x8f, 0xe3, 0x61, 0x6f, 0x41, 0x8d, 0x98, 0x95, - 0x1c, 0x27, 0xe9, 0x0d, 0xb4, 0x36, 0x9b, 0x5d, 0x8d, 0xa4, 0x68, 0xfc, 0x58, 0xfb, 0xde, 0x28, - 0x43, 0x31, 0xf4, 0x9d, 0xd3, 0x53, 0xee, 0x1b, 0x2b, 0xd1, 0xd0, 0x08, 0x2e, 0xcc, 0xbb, 0x21, - 0x1f, 0x0b, 0xd9, 0xdc, 0xf8, 0xf7, 0x19, 0xa8, 0x48, 0xbe, 0xfa, 0x53, 0xdb, 0xca, 0xd6, 0x34, - 0xb7, 0x57, 0x3a, 0xb1, 0x89, 0xbd, 0x5c, 0xdf, 0x85, 0xf9, 0x91, 0x90, 0xd3, 0x85, 0x1e, 0x99, - 0x30, 0x94, 0xd5, 0x15, 0x58, 0x8a, 0xc9, 0xeb, 0xb0, 0x88, 0x52, 0x73, 0x60, 0x85, 0xce, 0xd0, - 0x52, 0x89, 0xd2, 0xc5, 0x74, 0x81, 0x92, 0x7a, 0xce, 0x70, 0x4f, 0x26, 0x08, 0xe1, 0x31, 0x08, - 0xed, 0x53, 0x2e, 0xd7, 0x36, 0x7d, 0x18, 0x4d, 0x58, 0x99, 0x52, 0x21, 0x95, 0xfa, 0xfb, 0x7f, - 0x17, 0x60, 0x75, 0x26, 0x49, 0xaa, 0xc1, 0x91, 0x81, 0x68, 0xe8, 0x8c, 0x8e, 0xbd, 0xe8, 0xf8, - 0x34, 0xa3, 0x19, 0x88, 0x76, 0x45, 0x8a, 0x3a, 0x3e, 0xe5, 0xb0, 0xac, 0x08, 0x12, 0xcf, 0x3f, - 0x23, 0x2d, 0x33, 0x8b, 0x3a, 0xd0, 0x07, 0xc9, 0x4d, 0x6c, 0xba, 0x3a, 0x05, 0xd7, 0x45, 0xa3, - 0xc5, 0xf1, 0x0c, 0x2c, 0x60, 0xbf, 0x09, 0xcd, 0x88, 0xee, 0xa5, 0xd8, 0xae, 0xa9, 0xcc, 0xa2, - 0xa6, 0xaf, 0xbf, 0xa2, 0xa6, 0xc4, 0xd9, 0x1d, 0xca, 0x4e, 0x2b, 0x6a, 0xc9, 0x50, 0x81, 0x51, - 0x5d, 0xe7, 0xf0, 0x86, 0xaa, 0x0b, 0xc5, 0xf0, 0xd9, 0x1a, 0xf3, 0xaf, 0xd5, 0x37, 0x3c, 0x97, - 0x4c, 0x54, 0x6b, 0xde, 0x92, 0x05, 0x47, 0x49, 0x7a, 0xbd, 0x67, 0xb0, 0x72, 0x61, 0x3b, 0xa1, - 0xea, 0xa3, 0xa6, 0xb1, 0x17, 0xb0, 0xbe, 0xc7, 0xaf, 0xa8, 0xef, 0x73, 0xca, 0x9c, 0x50, 0x4c, - 0x96, 0x2e, 0x66, 0x81, 0xc1, 0xda, 0x3f, 0xcb, 0x41, 0x3d, 0x59, 0x8a, 0x60, 0x2c, 0x72, 0xb3, - 0x51, 0xf2, 0xa6, 0x14, 0x82, 0xe5, 0xd1, 0xfe, 0x3e, 0xc9, 0x99, 0xb3, 0x46, 0x87, 0x6c, 0x8a, - 0xd1, 0x41, 0x3f, 0xeb, 0xcf, 0xbd, 0xca, 0xb8, 0x9a, 0x7f, 0x2d, 0xe3, 0x6a, 0x21, 0xcd, 0xb8, - 0x7a, 0xbd, 0x45, 0x6e, 0xee, 0xa7, 0xb2, 0xc8, 0x15, 0x5f, 0x6a, 0x91, 0xd3, 0xec, 0x88, 0xa5, - 0x6b, 0x4e, 0xe8, 0x35, 0xcb, 0x62, 0x8a, 0x45, 0xae, 0xfc, 0x15, 0x2c, 0x72, 0x6b, 0x7f, 0x99, - 0x01, 0x36, 0xbb, 0x3a, 0xd8, 0x53, 0xb2, 0xe7, 0xb8, 0x7c, 0x28, 0x39, 0xf7, 0x37, 0x5e, 0x6f, - 0x85, 0x29, 0x82, 0x50, 0xb9, 0xd9, 0x43, 0x58, 0xd4, 0x1d, 0xe1, 0x75, 0xad, 0xbd, 0x66, 0x32, - 0x3d, 0x29, 0x3e, 0xdb, 0xd1, 0x2c, 0xd9, 0xf9, 0x57, 0x5a, 0xb2, 0x0b, 0xaf, 0xb4, 0x64, 0xcf, - 0x25, 0x2d, 0xd9, 0x6b, 0xff, 0x39, 0x03, 0x8b, 0x29, 0x44, 0xfc, 0xf3, 0xeb, 0xb3, 0xa0, 0xbd, - 0x04, 0x5b, 0xcb, 0x4a, 0xda, 0xd3, 0x39, 0xda, 0x2e, 0x54, 0xe2, 0xa9, 0x50, 0x81, 0x22, 0x0f, - 0x5e, 0xc5, 0x5d, 0xe2, 0x1c, 0xa6, 0x9e, 0x7d, 0xed, 0xf7, 0xb3, 0x50, 0xd1, 0x12, 0xc5, 0x28, - 0x12, 0xc9, 0x6a, 0x0e, 0x44, 0x24, 0x19, 0xe2, 0x99, 0xc3, 0x5d, 0x90, 0x46, 0x0d, 0x4a, 0xa7, - 0xc5, 0x25, 0xc5, 0x40, 0x44, 0x58, 0x87, 0x45, 0x65, 0x6b, 0xe3, 0xb1, 0x9f, 0xa0, 0xdc, 0x6b, - 0x16, 0xa4, 0xc5, 0x8d, 0x47, 0x6e, 0x87, 0xec, 0xa1, 0x52, 0x07, 0xe3, 0xb9, 0x43, 0x52, 0x27, - 0x8b, 0xc1, 0x02, 0x2d, 0x10, 0x35, 0x89, 0x82, 0xce, 0x3f, 0x80, 0x65, 0xb5, 0x3c, 0x92, 0x39, - 0xc8, 0x88, 0xc0, 0xe4, 0xe2, 0xd0, 0xb3, 0x7c, 0x0f, 0xee, 0x4c, 0xb5, 0x69, 0x2a, 0x2b, 0x39, - 0xb4, 0xde, 0x4c, 0xb4, 0x4e, 0x2f, 0x61, 0xed, 0xc7, 0x50, 0x4b, 0x30, 0xca, 0x9f, 0xdf, 0x94, - 0x4f, 0x9f, 0xf3, 0xd0, 0x88, 0xea, 0xe7, 0x3c, 0x6b, 0xff, 0x3b, 0x07, 0x6c, 0x96, 0x57, 0xff, - 0x22, 0x9b, 0x30, 0x4b, 0x98, 0xb9, 0x14, 0xc2, 0xfc, 0xff, 0x26, 0x3f, 0xbc, 0x0f, 0x0b, 0x32, - 0x60, 0x4a, 0x33, 0x98, 0xd2, 0xe2, 0x6c, 0x44, 0x09, 0xaa, 0x15, 0x1f, 0x4d, 0x3b, 0x6e, 0x94, - 0x12, 0x31, 0x22, 0x9a, 0x00, 0x35, 0xe5, 0xbf, 0x71, 0x04, 0x73, 0xb6, 0xdb, 0x3f, 0xf3, 0x7c, - 0xc9, 0x07, 0x7f, 0xe9, 0x2b, 0x6f, 0x9f, 0xeb, 0x2d, 0xcc, 0x8f, 0x52, 0x9b, 0x29, 0x0b, 0x33, - 0x3e, 0x80, 0x8a, 0x06, 0x66, 0x65, 0x28, 0xec, 0x76, 0xf6, 0x36, 0x0e, 0x1a, 0x37, 0x58, 0x0d, - 0xca, 0x66, 0x7b, 0xf3, 0xe0, 0xb3, 0xb6, 0xd9, 0xde, 0x6a, 0x64, 0x58, 0x09, 0xf2, 0xbb, 0x07, - 0xdd, 0x5e, 0x23, 0x6b, 0xac, 0x41, 0x53, 0x96, 0x38, 0x6b, 0xb3, 0xf8, 0x9d, 0x7c, 0x74, 0x5c, - 0x88, 0x89, 0x52, 0x45, 0xff, 0x26, 0x54, 0x75, 0xf1, 0x46, 0x52, 0xc4, 0x94, 0xcd, 0x5e, 0x28, - 0xe7, 0x9e, 0xc6, 0xab, 0x37, 0x81, 0x2c, 0xb6, 0x83, 0x28, 0x5b, 0x36, 0x21, 0xb7, 0xa6, 0x58, - 0x07, 0x51, 0xf9, 0x49, 0x90, 0xe1, 0x5f, 0x81, 0x7a, 0xf2, 0x00, 0x5f, 0x72, 0xa4, 0x34, 0x85, - 0x53, 0xe4, 0x4e, 0x9c, 0xe8, 0xb3, 0xef, 0x41, 0x63, 0xda, 0x00, 0x20, 0x85, 0xe7, 0x6b, 0xf2, - 0xcf, 0x3b, 0x49, 0x9b, 0x00, 0xdb, 0x81, 0xa5, 0x34, 0x01, 0x0f, 0xe9, 0xe3, 0xfa, 0x43, 0x0a, - 0x36, 0x2b, 0xc4, 0xb1, 0x6f, 0x4b, 0x3b, 0x4f, 0x01, 0xa7, 0xff, 0xed, 0x64, 0xfd, 0xda, 0x60, - 0xaf, 0xd3, 0x3f, 0xcd, 0xe2, 0x73, 0x0e, 0x10, 0xc3, 0x58, 0x03, 0xaa, 0x07, 0x87, 0xed, 0x7d, - 0x6b, 0x73, 0xa7, 0xb5, 0xbf, 0xdf, 0xde, 0x6d, 0xdc, 0x60, 0x0c, 0xea, 0x68, 0xab, 0xde, 0x8a, - 0x60, 0x19, 0x01, 0x93, 0xf6, 0x36, 0x05, 0xcb, 0xb2, 0x25, 0x68, 0x74, 0xf6, 0xa7, 0xa0, 0x39, - 0xd6, 0x84, 0xa5, 0xc3, 0x36, 0x99, 0xb7, 0x13, 0xe5, 0xe6, 0x85, 0xd2, 0x20, 0xbb, 0x2b, 0x94, - 0x06, 0x0a, 0xfc, 0x93, 0xeb, 0x40, 0xc9, 0xd2, 0xbf, 0x9b, 0x81, 0xe5, 0xa9, 0x84, 0x38, 0x9c, - 0x83, 0x24, 0xe9, 0xa4, 0x0c, 0x5d, 0x45, 0xa0, 0x5a, 0x4d, 0xef, 0xc3, 0x42, 0x74, 0xf0, 0x34, - 0xb5, 0x2b, 0x35, 0xa2, 0x04, 0x85, 0xfc, 0x10, 0x16, 0xb5, 0xf3, 0xab, 0x29, 0x5e, 0xc1, 0xb4, - 0x24, 0x99, 0xc1, 0x58, 0x8d, 0xdc, 0xe6, 0xa7, 0x5a, 0x3d, 0xa0, 0x68, 0x42, 0x3d, 0x21, 0x36, - 0x83, 0x25, 0xdb, 0xab, 0x3e, 0xd9, 0xa3, 0x29, 0x42, 0x48, 0xb6, 0x56, 0x9f, 0x70, 0x55, 0xfd, - 0x1f, 0xcc, 0x01, 0xfb, 0x74, 0xc2, 0xfd, 0x2b, 0x0c, 0xd7, 0x08, 0x5e, 0xe5, 0xbf, 0xa8, 0x4e, - 0x5a, 0xb2, 0xaf, 0x15, 0x92, 0x95, 0x16, 0x12, 0x95, 0x7f, 0x75, 0x48, 0x54, 0xe1, 0x55, 0x21, - 0x51, 0x6f, 0x41, 0xcd, 0x39, 0x75, 0x3d, 0xc1, 0x0a, 0x85, 0x24, 0x1c, 0x34, 0xe7, 0xee, 0xe5, - 0xee, 0x57, 0xcd, 0xaa, 0x04, 0x0a, 0x39, 0x38, 0x60, 0x9f, 0xc4, 0x48, 0x7c, 0x70, 0x8a, 0xe1, - 0x7b, 0x3a, 0x13, 0x6c, 0x0f, 0x4e, 0xb9, 0x3c, 0x58, 0x42, 0x4d, 0x43, 0x65, 0x16, 0xf0, 0x80, - 0xbd, 0x0d, 0xf5, 0xc0, 0x9b, 0x08, 0xc5, 0x42, 0x0d, 0x03, 0x19, 0xca, 0xaa, 0x04, 0x3d, 0x54, - 0x56, 0xd1, 0xc5, 0x49, 0xc0, 0xad, 0x91, 0x13, 0x04, 0x42, 0x3c, 0xeb, 0x7b, 0x6e, 0xe8, 0x7b, - 0x43, 0x69, 0xfb, 0x5a, 0x98, 0x04, 0x7c, 0x8f, 0x52, 0x36, 0x29, 0x81, 0x7d, 0x2b, 0x6e, 0xd2, - 0xd8, 0x76, 0xfc, 0xa0, 0x09, 0xd8, 0x24, 0xd5, 0x53, 0x94, 0xdf, 0x6d, 0xc7, 0x8f, 0xda, 0x22, - 0x3e, 0x82, 0xa9, 0x50, 0xad, 0xca, 0x74, 0xa8, 0xd6, 0x0f, 0xd3, 0x43, 0xb5, 0x6a, 0x58, 0xf4, - 0x23, 0x59, 0xf4, 0xec, 0x14, 0x7f, 0xa5, 0x88, 0xad, 0xd9, 0x08, 0xb4, 0xfa, 0x57, 0x89, 0x40, - 0x9b, 0x4f, 0x8b, 0x40, 0xfb, 0x00, 0x2a, 0x18, 0x1b, 0x64, 0x9d, 0x39, 0x42, 0x86, 0x23, 0x5b, - 0x5e, 0x43, 0x0f, 0x1e, 0xda, 0x71, 0xdc, 0xd0, 0x04, 0x5f, 0xfd, 0x0c, 0x66, 0x83, 0xc1, 0x16, - 0x7e, 0x81, 0xc1, 0x60, 0x32, 0x86, 0x69, 0x1d, 0x4a, 0x6a, 0x9e, 0x18, 0x83, 0xfc, 0x89, 0xef, - 0x8d, 0x94, 0x8d, 0x43, 0xfc, 0x66, 0x75, 0xc8, 0x86, 0x9e, 0xcc, 0x9c, 0x0d, 0x3d, 0xe3, 0xd7, - 0xa1, 0xa2, 0x91, 0x1a, 0x7b, 0x93, 0xce, 0x25, 0x85, 0x6e, 0x26, 0x65, 0x4b, 0x1a, 0xc5, 0xb2, - 0x84, 0x76, 0x06, 0x82, 0xdf, 0x0c, 0x1c, 0x9f, 0x63, 0xd8, 0xa6, 0xe5, 0xf3, 0x73, 0xee, 0x07, - 0xca, 0xe6, 0xd4, 0x88, 0x12, 0x4c, 0x82, 0x1b, 0xbf, 0x01, 0x8b, 0x89, 0xb9, 0x95, 0x2c, 0xe2, - 0x6d, 0x98, 0xc3, 0x71, 0x53, 0x3e, 0x01, 0xc9, 0xa0, 0x2c, 0x99, 0x86, 0xf1, 0xf8, 0x64, 0x2e, - 0xb3, 0xc6, 0xbe, 0x77, 0x8c, 0x95, 0x64, 0xcc, 0x8a, 0x84, 0x1d, 0xfa, 0xde, 0xb1, 0xf1, 0x67, - 0x39, 0xc8, 0xed, 0x78, 0x63, 0xdd, 0x47, 0x2d, 0x33, 0xe3, 0xa3, 0x26, 0x15, 0x4e, 0x2b, 0x52, - 0x28, 0xa5, 0xcc, 0x8e, 0x86, 0x22, 0xa5, 0x54, 0xde, 0x87, 0xba, 0xe0, 0x13, 0xa1, 0x27, 0x34, - 0xf6, 0x0b, 0xdb, 0x27, 0x81, 0x38, 0x47, 0x8b, 0xcf, 0x1e, 0x85, 0x3d, 0x6f, 0x9b, 0xe0, 0x6c, - 0x09, 0x72, 0x91, 0xfa, 0x82, 0xc9, 0xe2, 0x93, 0xad, 0xc0, 0x1c, 0x3a, 0x2b, 0x5f, 0x49, 0xa3, - 0xb7, 0xfc, 0x62, 0xdf, 0x80, 0xc5, 0x64, 0xb9, 0xc4, 0x8a, 0xa4, 0x6c, 0xa4, 0x17, 0x8c, 0x3c, - 0xe9, 0x26, 0x08, 0x3e, 0x42, 0x38, 0xd2, 0x77, 0xe6, 0x84, 0x73, 0x4c, 0xd2, 0x98, 0x5e, 0x29, - 0xc1, 0xf4, 0xee, 0x42, 0x25, 0x1c, 0x9e, 0x5b, 0x63, 0xfb, 0x6a, 0xe8, 0xd9, 0x03, 0xb9, 0xbe, - 0x21, 0x1c, 0x9e, 0x1f, 0x12, 0x84, 0x3d, 0x04, 0x18, 0x8d, 0xc7, 0x72, 0xed, 0xa1, 0xf1, 0x23, - 0x26, 0xe5, 0xbd, 0xc3, 0x43, 0x22, 0x39, 0xb3, 0x3c, 0x1a, 0x8f, 0xe9, 0x27, 0xdb, 0x82, 0x7a, - 0x6a, 0x68, 0xe5, 0x1d, 0xe5, 0x5b, 0xeb, 0x8d, 0xd7, 0x53, 0x16, 0x67, 0xad, 0xaf, 0xc3, 0xd6, - 0xbe, 0x07, 0xec, 0x67, 0x0c, 0x70, 0xec, 0x41, 0x39, 0x6a, 0x9f, 0x1e, 0x1f, 0x88, 0xde, 0xf2, - 0x95, 0x44, 0x7c, 0x60, 0x6b, 0x30, 0xf0, 0x05, 0x5f, 0xa4, 0x0d, 0x33, 0x62, 0xf9, 0xa0, 0xed, - 0x98, 0x2d, 0xe2, 0xfb, 0xc6, 0x7f, 0xcb, 0x40, 0x81, 0x82, 0x15, 0xdf, 0x81, 0x79, 0xc2, 0x8f, - 0xfc, 0xfd, 0xa4, 0xa9, 0x9c, 0xf6, 0xdd, 0x9e, 0x74, 0xf5, 0x13, 0xcb, 0x42, 0x0b, 0xb4, 0xce, - 0x46, 0x33, 0xaf, 0x05, 0x5b, 0xdf, 0x85, 0x72, 0x54, 0xb5, 0x46, 0x3a, 0x25, 0x55, 0x33, 0x7b, - 0x03, 0xf2, 0x67, 0xde, 0x58, 0x9d, 0xfc, 0x40, 0x3c, 0x92, 0x26, 0xc2, 0xe3, 0xb6, 0x88, 0x3a, - 0xa8, 0xf1, 0xf2, 0xc4, 0x22, 0xaa, 0x04, 0xc9, 0x60, 0xb6, 0x8f, 0x73, 0x29, 0x7d, 0x3c, 0x82, - 0x79, 0xc1, 0x07, 0x34, 0x97, 0x95, 0xeb, 0x37, 0xcd, 0xf7, 0x84, 0x84, 0xd7, 0x1f, 0x4e, 0x06, - 0x5c, 0x3f, 0x7b, 0x43, 0xff, 0x36, 0x09, 0x57, 0x92, 0xb5, 0xf1, 0x07, 0x19, 0xe2, 0x2f, 0xa2, - 0x5c, 0x76, 0x1f, 0xf2, 0x62, 0x7f, 0x9b, 0x3a, 0x89, 0x8f, 0xc2, 0x16, 0x04, 0x9e, 0x89, 0x18, - 0x78, 0x3b, 0xc1, 0x64, 0x94, 0x2c, 0xbd, 0x66, 0x56, 0xdc, 0xc9, 0x28, 0x3a, 0xba, 0xfa, 0x9a, - 0xea, 0xd6, 0xd4, 0xb1, 0x0f, 0xf5, 0x3e, 0x5a, 0xa6, 0xeb, 0x9a, 0xa3, 0x5c, 0x3e, 0xb1, 0x63, - 0x2a, 0x29, 0x70, 0x70, 0xca, 0x35, 0x07, 0xb9, 0x3f, 0xca, 0x42, 0x2d, 0xd1, 0x22, 0xf4, 0x14, - 0x14, 0x1b, 0x00, 0x19, 0x96, 0xe4, 0x7c, 0x83, 0x00, 0x49, 0x41, 0x5d, 0x1b, 0xa7, 0x6c, 0x62, - 0x9c, 0x22, 0xe7, 0x9c, 0x9c, 0xee, 0x9c, 0xf3, 0x08, 0xca, 0x71, 0x80, 0x7d, 0xb2, 0x49, 0xa2, - 0x3e, 0x15, 0xbc, 0x11, 0x23, 0xc5, 0xee, 0x3c, 0x05, 0xdd, 0x9d, 0xe7, 0xbb, 0x9a, 0xf7, 0xc7, - 0x1c, 0x16, 0x63, 0xa4, 0x8d, 0xe8, 0x2f, 0xc4, 0xf7, 0xc3, 0xf8, 0x04, 0x2a, 0x5a, 0xe3, 0x75, - 0x2f, 0x8f, 0x4c, 0xc2, 0xcb, 0x23, 0x0a, 0xb3, 0xca, 0xc6, 0x61, 0x56, 0xc6, 0xdf, 0xcc, 0x42, - 0x4d, 0xac, 0x2f, 0xc7, 0x3d, 0x3d, 0xf4, 0x86, 0x4e, 0x1f, 0x0d, 0x4d, 0xd1, 0x0a, 0x93, 0x82, - 0x96, 0x5a, 0x67, 0x72, 0x89, 0x91, 0x9c, 0xa5, 0x47, 0x93, 0x12, 0x93, 0x8e, 0xa2, 0x49, 0x0d, - 0xa8, 0x09, 0xc6, 0x88, 0x26, 0xa3, 0x38, 0xfc, 0xdf, 0xac, 0x9c, 0x70, 0xbe, 0x61, 0x07, 0xc4, - 0x21, 0xbf, 0x01, 0x8b, 0x02, 0x07, 0x03, 0xe9, 0x46, 0xce, 0x70, 0xe8, 0x10, 0x26, 0x1d, 0x34, - 0x35, 0x4e, 0x38, 0x37, 0xed, 0x90, 0xef, 0x89, 0x04, 0x79, 0x5b, 0x40, 0x69, 0xe0, 0x04, 0xf6, - 0x71, 0xec, 0xcf, 0x19, 0x7d, 0xa3, 0x65, 0xd9, 0xbe, 0xd4, 0x2c, 0xcb, 0x74, 0x00, 0x51, 0x19, - 0xd9, 0x97, 0x91, 0x65, 0x79, 0x8a, 0x92, 0x8a, 0xd3, 0x94, 0x64, 0xfc, 0xbb, 0x2c, 0x54, 0x34, - 0xb2, 0x7c, 0x9d, 0xdd, 0xf5, 0xce, 0x8c, 0x61, 0xb0, 0xac, 0xdb, 0x00, 0xdf, 0x4a, 0x56, 0x89, - 0xbe, 0x2f, 0x74, 0x2f, 0x81, 0x46, 0xc0, 0xb7, 0xa0, 0x2c, 0x56, 0xdd, 0x07, 0x78, 0x04, 0x2b, - 0x6f, 0xd5, 0x40, 0xc0, 0xe1, 0xe4, 0x58, 0x25, 0x3e, 0xc6, 0xc4, 0x42, 0x9c, 0xf8, 0x58, 0x24, - 0xbe, 0xcc, 0xc3, 0xfa, 0x23, 0xa8, 0xca, 0x52, 0x71, 0x4e, 0xb1, 0xbb, 0xf1, 0xaa, 0x4f, 0xcc, - 0xb7, 0x59, 0xa1, 0xea, 0x68, 0xf2, 0x65, 0xc6, 0xc7, 0x2a, 0x63, 0xe9, 0x55, 0x19, 0x1f, 0xd3, - 0x87, 0xb1, 0x1d, 0x39, 0xad, 0xa3, 0xdf, 0x95, 0xe2, 0x63, 0x0f, 0x61, 0x51, 0xb1, 0xab, 0x89, - 0x6b, 0xbb, 0xae, 0x37, 0x71, 0xfb, 0x5c, 0xc5, 0x5f, 0x31, 0x99, 0x74, 0x14, 0xa7, 0x18, 0x83, - 0x28, 0x40, 0x97, 0xfc, 0xb7, 0x1e, 0x40, 0x81, 0xe4, 0x72, 0x12, 0x3e, 0xd2, 0x19, 0x17, 0xa1, - 0xb0, 0xfb, 0x50, 0x20, 0xf1, 0x3c, 0x7b, 0x2d, 0xb3, 0x21, 0x04, 0xa3, 0x05, 0x4c, 0x64, 0xdc, - 0xe3, 0xa1, 0xef, 0xf4, 0x83, 0x38, 0xb4, 0xab, 0x20, 0xf4, 0x4f, 0xaa, 0x2b, 0x3e, 0xb9, 0x8d, - 0x31, 0x51, 0x47, 0x25, 0x1c, 0xb1, 0x31, 0x2d, 0x26, 0xca, 0x90, 0xe2, 0xd2, 0x10, 0x56, 0x8e, - 0x79, 0x78, 0xc1, 0xb9, 0xeb, 0x0a, 0x61, 0xa8, 0xcf, 0xdd, 0xd0, 0xb7, 0x87, 0x62, 0x92, 0xa8, - 0x07, 0x4f, 0x66, 0x4a, 0x8d, 0xcf, 0x40, 0x36, 0xe2, 0x8c, 0x9b, 0x51, 0x3e, 0xe2, 0x1d, 0xcb, - 0xc7, 0x69, 0x69, 0x6b, 0xbf, 0x06, 0x6b, 0xd7, 0x67, 0x4a, 0x09, 0xe0, 0xbc, 0x9f, 0xe4, 0x2a, - 0x91, 0x1d, 0x70, 0xe8, 0xd9, 0x21, 0xb5, 0x46, 0xe7, 0x2c, 0xfb, 0x50, 0xd1, 0x52, 0xe2, 0xbd, - 0x3f, 0x83, 0xc2, 0x1d, 0x7d, 0x88, 0x1d, 0xc9, 0xf5, 0xfc, 0x11, 0xda, 0xdd, 0x06, 0x56, 0x5c, - 0x7a, 0xc6, 0x9c, 0x8f, 0xe1, 0x18, 0xb1, 0x6e, 0xac, 0xc3, 0x3c, 0x4a, 0xf6, 0xda, 0x46, 0xf7, - 0x32, 0x61, 0xd0, 0x58, 0x02, 0xb6, 0x4f, 0xbc, 0x4b, 0x77, 0xe7, 0xfc, 0x2f, 0x39, 0xa8, 0x68, - 0x60, 0xb1, 0x1b, 0xa1, 0x03, 0xa0, 0x35, 0x70, 0xec, 0x11, 0x57, 0x46, 0xce, 0x9a, 0x59, 0x43, - 0xe8, 0x96, 0x04, 0x8a, 0xbd, 0xd8, 0x3e, 0x3f, 0xb5, 0xbc, 0x49, 0x68, 0x0d, 0xf8, 0xa9, 0xcf, - 0x55, 0x2b, 0xab, 0xf6, 0xf9, 0xe9, 0xc1, 0x24, 0xdc, 0x42, 0x98, 0xc0, 0x12, 0xbc, 0x44, 0xc3, - 0x92, 0x3e, 0x6b, 0x23, 0xfb, 0x32, 0xc6, 0x92, 0x8e, 0x93, 0x44, 0x99, 0xf9, 0xc8, 0x71, 0x92, - 0xb4, 0xc5, 0xe9, 0x0d, 0xb4, 0x30, 0xbb, 0x81, 0x7e, 0x0b, 0x56, 0x68, 0x03, 0x95, 0xac, 0xd9, - 0x9a, 0x5a, 0xc9, 0x4b, 0x98, 0x2a, 0x3b, 0xa9, 0x89, 0xbd, 0x0d, 0xd1, 0x03, 0xc5, 0x96, 0x02, - 0xe7, 0x47, 0xc4, 0xc8, 0x32, 0xa6, 0xe8, 0x99, 0x2c, 0xbc, 0xeb, 0xfc, 0x88, 0x0b, 0x4c, 0xf4, - 0x8e, 0xd1, 0x31, 0x65, 0xfc, 0xc4, 0xc8, 0x71, 0xa7, 0x31, 0xed, 0xcb, 0x24, 0x66, 0x59, 0x62, - 0xda, 0x97, 0x3a, 0xe6, 0x13, 0x58, 0x1d, 0xf1, 0x81, 0x63, 0x27, 0x8b, 0xb5, 0x62, 0xc1, 0x6d, - 0x89, 0x92, 0xb5, 0x3c, 0x5d, 0x52, 0xdc, 0xc5, 0x68, 0xfc, 0xc8, 0x1b, 0x1d, 0x3b, 0x24, 0xb3, - 0x90, 0xbf, 0x4e, 0xde, 0xac, 0xbb, 0x93, 0xd1, 0x0f, 0x10, 0x2c, 0xb2, 0x04, 0x46, 0x0d, 0x2a, - 0xdd, 0xd0, 0x1b, 0xab, 0x69, 0xae, 0x43, 0x95, 0x3e, 0x65, 0x50, 0xe3, 0x2d, 0xb8, 0x89, 0x2c, - 0xa1, 0xe7, 0x8d, 0xbd, 0xa1, 0x77, 0x7a, 0x95, 0x38, 0xc7, 0xfb, 0x0f, 0x19, 0x58, 0x4c, 0xa4, - 0x4a, 0xf6, 0xfa, 0x2d, 0xe2, 0x67, 0x51, 0x64, 0x1a, 0xad, 0xc1, 0x05, 0x6d, 0x0d, 0x12, 0x22, - 0x31, 0x33, 0x15, 0xad, 0xd6, 0x8a, 0x6f, 0x54, 0x50, 0x19, 0x89, 0xa5, 0x34, 0x67, 0x59, 0x8a, - 0xcc, 0xaf, 0xee, 0x5a, 0x50, 0x45, 0xfc, 0x92, 0x8c, 0x71, 0x19, 0xc8, 0x2e, 0xe7, 0x92, 0x81, - 0x02, 0xfa, 0x99, 0x9f, 0x6a, 0x41, 0x7c, 0x10, 0x18, 0x18, 0xff, 0x3c, 0x03, 0x10, 0xb7, 0x0e, - 0x43, 0x15, 0x22, 0xb9, 0x85, 0x2e, 0x2b, 0xd3, 0x64, 0x94, 0x37, 0xa1, 0x1a, 0x79, 0x2c, 0xc7, - 0x92, 0x50, 0x45, 0xc1, 0x84, 0x38, 0xf4, 0x2e, 0xcc, 0x9f, 0x0e, 0xbd, 0x63, 0x94, 0x58, 0xa5, - 0xdc, 0x42, 0xfe, 0x6a, 0x75, 0x02, 0x2b, 0x69, 0x24, 0x96, 0x9b, 0xf2, 0xa9, 0x4e, 0xcd, 0xba, - 0x14, 0x64, 0xfc, 0x76, 0x36, 0x72, 0xdd, 0x8c, 0x47, 0xe2, 0xe5, 0xea, 0xdd, 0x4f, 0xe3, 0x4b, - 0xf3, 0x32, 0xf3, 0xe2, 0x27, 0x50, 0xf7, 0x69, 0x53, 0x52, 0x3b, 0x56, 0xfe, 0x25, 0x3b, 0x56, - 0xcd, 0x4f, 0x48, 0x3a, 0xef, 0x41, 0xc3, 0x1e, 0x9c, 0x73, 0x3f, 0x74, 0xf0, 0xb4, 0x1e, 0xe5, - 0x63, 0xe9, 0x2c, 0xa9, 0xc1, 0x51, 0x10, 0x7d, 0x17, 0xe6, 0x65, 0xa0, 0x6d, 0x84, 0x29, 0xaf, - 0xee, 0x89, 0xc1, 0x02, 0xd1, 0xf8, 0x97, 0xca, 0x57, 0x34, 0x39, 0xbb, 0x2f, 0x1f, 0x15, 0xbd, - 0x87, 0xd9, 0x59, 0x03, 0xaa, 0x24, 0x24, 0x69, 0x04, 0x90, 0xfc, 0x88, 0x80, 0xd2, 0x04, 0x90, - 0x1c, 0xd6, 0xfc, 0xeb, 0x0c, 0xab, 0xf1, 0x9f, 0x32, 0x50, 0xdc, 0xf1, 0xc6, 0x3b, 0x0e, 0x39, - 0xeb, 0xe3, 0x32, 0x89, 0x6c, 0x54, 0x73, 0xe2, 0x13, 0x1d, 0x7f, 0x5e, 0x12, 0x4f, 0x96, 0x2a, - 0xe6, 0xd5, 0x92, 0x62, 0xde, 0x77, 0xe1, 0x16, 0x9a, 0x00, 0x7d, 0x6f, 0xec, 0xf9, 0x62, 0xa9, - 0xda, 0x43, 0x12, 0xf7, 0x3c, 0x37, 0x3c, 0x53, 0xbc, 0xf3, 0xe6, 0x09, 0xe7, 0x87, 0x1a, 0xc6, - 0x5e, 0x84, 0x80, 0x11, 0x9b, 0xc3, 0xf0, 0xdc, 0x22, 0x0d, 0x5d, 0xca, 0xa3, 0xc4, 0x51, 0xe7, - 0x45, 0x42, 0x1b, 0xe1, 0x28, 0x91, 0x1a, 0xdf, 0x86, 0x72, 0x74, 0xd8, 0xc3, 0xde, 0x87, 0xf2, - 0x99, 0x37, 0x96, 0x27, 0x42, 0x99, 0x44, 0xcc, 0x9d, 0xec, 0xb5, 0x59, 0x3a, 0xa3, 0x1f, 0x81, - 0xf1, 0x67, 0x45, 0x28, 0x76, 0xdc, 0x73, 0xcf, 0xe9, 0xa3, 0xb7, 0xe9, 0x88, 0x8f, 0x3c, 0x15, - 0xed, 0x2f, 0x7e, 0xa3, 0x6f, 0x56, 0x7c, 0x01, 0x4f, 0x4e, 0xfa, 0x66, 0x45, 0x57, 0xef, 0x2c, - 0xc3, 0x9c, 0xaf, 0xdf, 0xa0, 0x53, 0xf0, 0xd1, 0xff, 0x3d, 0xda, 0x2f, 0x0b, 0xda, 0x6d, 0x09, - 0xa2, 0x2c, 0xba, 0xd9, 0x05, 0x87, 0x8c, 0xa2, 0x2f, 0xcb, 0x08, 0xc1, 0x01, 0xbb, 0x0d, 0x45, - 0x19, 0xe2, 0x46, 0x31, 0x49, 0xe4, 0xb0, 0x2e, 0x41, 0x48, 0x0d, 0x3e, 0x27, 0x13, 0x6e, 0x24, - 0xc8, 0xe6, 0xcc, 0xaa, 0x02, 0x6e, 0x09, 0x5a, 0xbb, 0x0b, 0x15, 0xc2, 0x27, 0x94, 0x92, 0x74, - 0xd2, 0x44, 0x10, 0x22, 0xa4, 0x5c, 0x44, 0x55, 0x4e, 0xbd, 0x88, 0x0a, 0xdd, 0x89, 0x23, 0x2e, - 0x4b, 0x5d, 0x04, 0xba, 0x7e, 0x48, 0x83, 0xab, 0x5b, 0xd8, 0xe4, 0x99, 0x0a, 0x05, 0x23, 0xab, - 0x33, 0x95, 0xb7, 0xa0, 0x76, 0x62, 0x0f, 0x87, 0xc7, 0x76, 0xff, 0x05, 0x1d, 0x05, 0x54, 0xe9, - 0xf4, 0x53, 0x01, 0xf1, 0x2c, 0xe0, 0x2e, 0x54, 0xb4, 0x59, 0x46, 0x0f, 0xcc, 0xbc, 0x09, 0xf1, - 0xfc, 0x4e, 0x9f, 0xf0, 0xd5, 0x5f, 0xe3, 0x84, 0x4f, 0xf3, 0x44, 0x9d, 0x4f, 0x7a, 0xa2, 0xde, - 0x42, 0x6e, 0x2a, 0x5d, 0x0e, 0x1b, 0x74, 0xd7, 0x8d, 0x3d, 0x18, 0xa0, 0xcb, 0x21, 0x5d, 0x2c, - 0x89, 0x83, 0x47, 0xe9, 0x0b, 0xa4, 0x4b, 0x10, 0x8c, 0x50, 0xee, 0xd0, 0x31, 0xf5, 0xd8, 0x76, - 0x06, 0x18, 0x74, 0x40, 0xa7, 0x07, 0x45, 0x7b, 0x14, 0x1e, 0xda, 0xce, 0x80, 0xdd, 0x83, 0xaa, - 0x4a, 0xc6, 0xdd, 0x71, 0x91, 0xc6, 0x5f, 0x26, 0x8b, 0x3d, 0xd1, 0x80, 0x5a, 0x84, 0x31, 0x8a, - 0x23, 0x8a, 0x2b, 0x12, 0x05, 0xe9, 0xe0, 0x03, 0xf4, 0xf2, 0x09, 0x39, 0xc6, 0x0d, 0xd7, 0x1f, - 0xdf, 0x8a, 0x9c, 0x0f, 0x90, 0x4a, 0xd5, 0x7f, 0x32, 0x8e, 0x11, 0xa6, 0x10, 0xee, 0xc8, 0x46, - 0xb7, 0x92, 0x90, 0x7f, 0x25, 0x2a, 0xda, 0xe8, 0x08, 0x81, 0x7d, 0x5b, 0xd3, 0x5f, 0x9b, 0x88, - 0x7c, 0x7b, 0xaa, 0xfc, 0xeb, 0x62, 0xae, 0xee, 0x00, 0x38, 0x81, 0xd8, 0x65, 0x02, 0xee, 0x0e, - 0x30, 0x04, 0xb8, 0x64, 0x96, 0x9d, 0xe0, 0x19, 0x01, 0x7e, 0xbe, 0x8a, 0x6d, 0x0b, 0xaa, 0x7a, - 0x37, 0x59, 0x09, 0xf2, 0x07, 0x87, 0xed, 0xfd, 0xc6, 0x0d, 0x56, 0x81, 0x62, 0xb7, 0xdd, 0xeb, - 0xed, 0xa2, 0xa5, 0xaf, 0x0a, 0xa5, 0x28, 0x4e, 0x31, 0x2b, 0xbe, 0x5a, 0x9b, 0x9b, 0xed, 0xc3, - 0x5e, 0x7b, 0xab, 0x91, 0xfb, 0x7e, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0x3f, 0xcf, 0x41, 0x45, 0x1b, - 0x85, 0x97, 0x33, 0xe3, 0x3b, 0x00, 0xa8, 0x49, 0xc6, 0x1e, 0xa9, 0x79, 0xb3, 0x2c, 0x20, 0x34, - 0xf9, 0xba, 0x8d, 0x22, 0x47, 0x97, 0x28, 0x29, 0x1b, 0xc5, 0x5b, 0x50, 0xa3, 0xfb, 0x88, 0x74, - 0x7b, 0x6d, 0xc1, 0xac, 0x12, 0x50, 0xb2, 0x6a, 0x0c, 0x60, 0x46, 0x24, 0x8c, 0x9e, 0x93, 0xb7, - 0x93, 0x10, 0x08, 0xe3, 0xe7, 0x30, 0xf8, 0x31, 0xf0, 0x86, 0xe7, 0x9c, 0x30, 0x48, 0x22, 0xac, - 0x48, 0x58, 0x4f, 0x86, 0x62, 0x4b, 0x7e, 0xa8, 0x45, 0xd0, 0x16, 0xcc, 0x2a, 0x01, 0x65, 0x45, - 0xdf, 0x50, 0x04, 0x44, 0xde, 0x2b, 0xab, 0xb3, 0xd4, 0x90, 0x20, 0x9e, 0xdd, 0x99, 0x63, 0xc4, - 0x32, 0x12, 0xc6, 0xd7, 0x66, 0xf3, 0xbd, 0xfa, 0x38, 0x91, 0xbd, 0x0f, 0x6c, 0x34, 0x1e, 0x5b, - 0x29, 0x07, 0x7c, 0x79, 0x73, 0x7e, 0x34, 0x1e, 0xf7, 0xb4, 0xf3, 0xaf, 0x9f, 0xc3, 0xd9, 0xe3, - 0x17, 0xc0, 0x5a, 0x62, 0x01, 0x63, 0x13, 0x23, 0x55, 0x2c, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, - 0x70, 0xbf, 0x6c, 0x2a, 0xf7, 0x7b, 0x19, 0x9f, 0x30, 0xb6, 0xa1, 0x72, 0xa8, 0xdd, 0x76, 0x76, - 0x4f, 0xec, 0x10, 0xea, 0x9e, 0x33, 0xda, 0x3b, 0xe8, 0x4c, 0xd1, 0x97, 0xd7, 0x9b, 0x69, 0xad, - 0xc9, 0x6a, 0xad, 0x31, 0xfe, 0x69, 0x86, 0x6e, 0x92, 0x89, 0x1a, 0x1f, 0x5f, 0xb0, 0xa6, 0xcc, - 0x6f, 0x71, 0xa0, 0x7b, 0x45, 0x99, 0xdd, 0x64, 0x8c, 0x3a, 0x36, 0xcd, 0xf2, 0x4e, 0x4e, 0x02, - 0xae, 0x7c, 0x3c, 0x2a, 0x08, 0x3b, 0x40, 0x90, 0x12, 0xbe, 0x85, 0x84, 0xef, 0x50, 0xf9, 0x81, - 0x74, 0xec, 0x10, 0xc2, 0xf7, 0x9e, 0x7d, 0x29, 0x6b, 0x0d, 0x84, 0x08, 0x22, 0xed, 0x03, 0x2a, - 0x16, 0x36, 0xfa, 0x36, 0xfe, 0x91, 0x8c, 0xc5, 0x9f, 0x1e, 0xdf, 0x07, 0x50, 0x8a, 0x4a, 0x4d, - 0xee, 0xb0, 0x0a, 0x33, 0x4a, 0x17, 0xfb, 0x38, 0x1e, 0x86, 0x24, 0x5a, 0x4c, 0x8b, 0x0b, 0x6d, - 0x3c, 0x1d, 0xad, 0xd5, 0x5f, 0x07, 0x76, 0xe2, 0xf8, 0xd3, 0xc8, 0xb4, 0xd8, 0x1a, 0x98, 0xa2, - 0x61, 0x1b, 0x47, 0xb0, 0xa8, 0xb8, 0x84, 0xa6, 0x11, 0x24, 0x27, 0x2f, 0xf3, 0x0a, 0x26, 0x9f, - 0x9d, 0x61, 0xf2, 0xc6, 0x4f, 0xf2, 0x50, 0x54, 0x37, 0x07, 0xa6, 0xdd, 0x76, 0x57, 0x4e, 0xde, - 0x76, 0xd7, 0x4c, 0xdc, 0x8c, 0x84, 0x53, 0x2f, 0xf7, 0xfb, 0x77, 0xa7, 0xb7, 0x6c, 0xcd, 0x56, - 0x91, 0xd8, 0xb6, 0x57, 0x20, 0x3f, 0xb6, 0xc3, 0x33, 0x3c, 0x97, 0x24, 0xe2, 0xc1, 0x6f, 0x65, - 0xc3, 0x28, 0x24, 0x6d, 0x18, 0x69, 0x37, 0x03, 0x92, 0x48, 0x3a, 0x73, 0x33, 0xe0, 0x2d, 0x20, - 0xf9, 0x42, 0x73, 0x7a, 0x2b, 0x21, 0x40, 0xec, 0x45, 0x49, 0x71, 0xa4, 0x34, 0x2d, 0x8e, 0xbc, - 0xb6, 0xa8, 0xf0, 0x2d, 0x98, 0xa3, 0x5b, 0x35, 0x64, 0xcc, 0xaf, 0xda, 0x50, 0xe4, 0x18, 0xaa, - 0xff, 0x14, 0x09, 0x61, 0x4a, 0x5c, 0xfd, 0x9a, 0xad, 0x4a, 0xe2, 0x9a, 0x2d, 0xdd, 0xb6, 0x52, - 0x4d, 0xda, 0x56, 0xee, 0x43, 0x23, 0x1a, 0x50, 0x3c, 0xa9, 0x74, 0x03, 0x19, 0x51, 0x58, 0x57, - 0x70, 0xc1, 0x25, 0xf7, 0x83, 0x78, 0x43, 0xac, 0x27, 0x36, 0x44, 0xc1, 0xc3, 0x5a, 0x61, 0xc8, - 0x47, 0xe3, 0x50, 0x6e, 0x88, 0x18, 0x73, 0xa4, 0x37, 0x50, 0xec, 0x30, 0x32, 0xa2, 0x97, 0x5c, - 0x4b, 0x3a, 0xfb, 0xd6, 0xf6, 0x6e, 0xe7, 0xe9, 0x4e, 0xaf, 0x91, 0x11, 0x9f, 0xdd, 0xa3, 0xcd, - 0xcd, 0x76, 0x7b, 0x0b, 0x77, 0x1c, 0x80, 0xb9, 0xed, 0x56, 0x47, 0xec, 0x3e, 0x39, 0xe3, 0x77, - 0xb3, 0x50, 0xd1, 0x8a, 0x67, 0x4f, 0xa2, 0x51, 0xa1, 0x9b, 0x98, 0xee, 0xcc, 0x36, 0x61, 0x5d, - 0xb1, 0x62, 0x6d, 0x58, 0xa2, 0x7b, 0x10, 0xb3, 0xd7, 0xde, 0x83, 0xc8, 0xde, 0x81, 0x79, 0x9b, - 0x4a, 0x88, 0x46, 0x41, 0x9e, 0xc2, 0x4b, 0xb0, 0x1c, 0x04, 0x74, 0xf5, 0x8c, 0xf7, 0x13, 0x81, - 0x97, 0x57, 0xde, 0x95, 0xd1, 0x96, 0x82, 0x83, 0x55, 0x3c, 0xb1, 0x9d, 0xe1, 0xc4, 0xe7, 0xd2, - 0x6a, 0x1e, 0xed, 0xcc, 0x04, 0x35, 0x55, 0xb2, 0xf1, 0x21, 0x40, 0xdc, 0xe6, 0xe4, 0xe0, 0xdc, - 0x48, 0x0e, 0x4e, 0x46, 0x1b, 0x9c, 0xac, 0xb1, 0x45, 0x6c, 0x44, 0x0e, 0x74, 0x74, 0xec, 0xf6, - 0x0d, 0x50, 0x07, 0x81, 0x16, 0x3a, 0x5c, 0x8f, 0x87, 0x3c, 0x54, 0xf7, 0x06, 0x2c, 0xc8, 0x94, - 0x4e, 0x94, 0xa0, 0xee, 0xd8, 0x88, 0x4b, 0x89, 0xb9, 0x91, 0x24, 0xc9, 0x69, 0x6e, 0x24, 0x51, - 0xcd, 0x28, 0xdd, 0x58, 0x83, 0xe6, 0x16, 0x17, 0xa5, 0xb5, 0x86, 0xc3, 0xa9, 0xe6, 0x18, 0xb7, - 0xe0, 0x66, 0x4a, 0x9a, 0x3c, 0x84, 0xf8, 0x14, 0x96, 0x5b, 0x74, 0x45, 0xc0, 0xcf, 0x2b, 0x16, - 0xd0, 0x68, 0xc2, 0xca, 0x74, 0x91, 0xb2, 0xb2, 0x6d, 0x58, 0xd8, 0xe2, 0xc7, 0x93, 0xd3, 0x5d, - 0x7e, 0x1e, 0x57, 0xc4, 0x20, 0x1f, 0x9c, 0x79, 0x17, 0x72, 0x7c, 0xf0, 0x37, 0x7a, 0x19, 0x0a, - 0x1c, 0x2b, 0x18, 0xf3, 0xbe, 0x3a, 0x88, 0x46, 0x48, 0x77, 0xcc, 0xfb, 0xc6, 0x13, 0x60, 0x7a, - 0x39, 0x72, 0xbc, 0x84, 0x96, 0x30, 0x39, 0xb6, 0x82, 0xab, 0x20, 0xe4, 0x23, 0x15, 0x03, 0x07, - 0xc1, 0xe4, 0xb8, 0x4b, 0x10, 0xe3, 0x5d, 0xa8, 0x1e, 0xda, 0x57, 0x26, 0xff, 0x42, 0x86, 0x9a, - 0xad, 0x42, 0x71, 0x6c, 0x5f, 0x09, 0x36, 0x10, 0xd9, 0xa4, 0x30, 0xd9, 0xf8, 0xc3, 0x3c, 0xcc, - 0x11, 0x26, 0xbb, 0x47, 0x77, 0xf1, 0x3a, 0x2e, 0x2e, 0x43, 0xc5, 0x28, 0x35, 0xd0, 0x0c, 0x2f, - 0xcd, 0xce, 0xf2, 0x52, 0x79, 0x80, 0xa6, 0xee, 0x20, 0x52, 0xd6, 0x03, 0x77, 0x32, 0x52, 0x17, - 0x0f, 0x25, 0xe3, 0xe4, 0xf3, 0xf1, 0x5d, 0xcb, 0x14, 0x44, 0x9c, 0xb4, 0xef, 0xc6, 0xba, 0x08, - 0xb5, 0x4e, 0x6d, 0x11, 0x92, 0x5d, 0xea, 0xa0, 0x54, 0x85, 0xa7, 0xa8, 0xe2, 0x27, 0x93, 0x0a, - 0xcf, 0x8c, 0x62, 0x53, 0x7a, 0xb5, 0x62, 0x43, 0x27, 0x6b, 0x2f, 0x51, 0x6c, 0xe0, 0x35, 0x14, - 0x9b, 0xd7, 0xb0, 0xad, 0xde, 0x84, 0x12, 0xee, 0xfb, 0x1a, 0xf7, 0x14, 0xfb, 0xbd, 0xe0, 0x9e, - 0x1f, 0x69, 0xa2, 0x3f, 0x39, 0x76, 0xdc, 0x8a, 0x97, 0x89, 0xc9, 0xbf, 0xf8, 0xc5, 0xd8, 0xac, - 0x9e, 0x43, 0x51, 0x42, 0x05, 0x41, 0xbb, 0xf6, 0x48, 0x5d, 0xe3, 0x86, 0xbf, 0xc5, 0xb0, 0xe1, - 0xdd, 0x53, 0x5f, 0x4c, 0x1c, 0x9f, 0x0f, 0xd4, 0xfd, 0x3c, 0x0e, 0xae, 0x51, 0x01, 0x11, 0x1d, - 0x14, 0x6a, 0x88, 0xeb, 0x5d, 0xb8, 0xf2, 0x02, 0x90, 0xa2, 0x13, 0x3c, 0x13, 0x9f, 0x06, 0x83, - 0x06, 0x5e, 0xe4, 0x38, 0xf6, 0x7c, 0xb5, 0x39, 0x19, 0x3f, 0xc9, 0x40, 0x43, 0xae, 0xae, 0x28, - 0x4d, 0xd7, 0x02, 0x0a, 0xd7, 0xf9, 0x21, 0xbc, 0xfc, 0xb6, 0x1d, 0x03, 0x6a, 0x78, 0xf8, 0x11, - 0xed, 0x54, 0x74, 0x78, 0x53, 0x11, 0xc0, 0x6d, 0xb9, 0x5b, 0xbd, 0x01, 0x15, 0xe5, 0x03, 0x3d, - 0x72, 0x86, 0xea, 0x5a, 0x75, 0x72, 0x82, 0xde, 0x73, 0x86, 0x6a, 0xa3, 0xf3, 0x6d, 0x19, 0xcf, - 0x9b, 0xc1, 0x8d, 0xce, 0xb4, 0x43, 0x6e, 0xfc, 0x9b, 0x0c, 0x2c, 0x68, 0x5d, 0x91, 0xeb, 0xf6, - 0x63, 0xa8, 0x46, 0x37, 0xa8, 0xf2, 0x48, 0xf2, 0x5a, 0x4d, 0x32, 0x9a, 0x38, 0x5b, 0xa5, 0x1f, - 0x41, 0x02, 0xd1, 0x98, 0x81, 0x7d, 0x45, 0x8e, 0xba, 0x93, 0x91, 0x52, 0x6e, 0x06, 0xf6, 0xd5, - 0x36, 0xe7, 0xdd, 0xc9, 0x48, 0xa8, 0xae, 0x17, 0x9c, 0xbf, 0x88, 0x10, 0x48, 0xe6, 0x02, 0x01, - 0x93, 0x18, 0x06, 0xd4, 0x46, 0x9e, 0x1b, 0x9e, 0x45, 0x28, 0x52, 0xea, 0x44, 0x20, 0xe1, 0x18, - 0x7f, 0x9a, 0x85, 0x45, 0x3a, 0x62, 0x93, 0x47, 0x9b, 0x92, 0x75, 0x35, 0x61, 0x8e, 0x4e, 0x1b, - 0x89, 0x79, 0xed, 0xdc, 0x30, 0xe5, 0x37, 0xfb, 0xd6, 0x6b, 0x1e, 0x0b, 0xaa, 0x90, 0xe1, 0x6b, - 0x86, 0x3f, 0x37, 0x3b, 0xfc, 0xd7, 0x0f, 0x6f, 0x9a, 0xa1, 0xb3, 0x90, 0x66, 0xe8, 0x7c, 0x1d, - 0xf3, 0xe2, 0x4c, 0x70, 0x6b, 0x51, 0xe2, 0x68, 0xc1, 0xad, 0x4f, 0x60, 0x35, 0x81, 0x83, 0xdc, - 0xda, 0x39, 0x71, 0xb8, 0xba, 0x5f, 0x65, 0x49, 0xc3, 0xee, 0xaa, 0xb4, 0x8d, 0x22, 0x14, 0x82, - 0xbe, 0x37, 0xe6, 0xc6, 0x0a, 0x2c, 0x25, 0x47, 0x55, 0x6e, 0x13, 0xbf, 0x97, 0x81, 0xa6, 0x74, - 0x4b, 0x71, 0xdc, 0xd3, 0x1d, 0x27, 0x08, 0x3d, 0x3f, 0xba, 0x69, 0xf4, 0x0e, 0x40, 0x10, 0xda, - 0xbe, 0xd4, 0x36, 0xe5, 0x8d, 0x22, 0x08, 0x41, 0x4d, 0xf2, 0x26, 0x94, 0xb8, 0x3b, 0xa0, 0x44, - 0xa2, 0x86, 0x22, 0x77, 0x07, 0x4a, 0x0f, 0x9d, 0x91, 0xbf, 0x6b, 0x49, 0xf5, 0x42, 0x06, 0xf8, - 0x8b, 0xd1, 0xe1, 0xe7, 0xb8, 0xf1, 0xe6, 0xa3, 0x00, 0xff, 0x3d, 0xfb, 0x12, 0x9d, 0x3c, 0x03, - 0xe3, 0xef, 0x67, 0x61, 0x3e, 0x6e, 0x1f, 0xdd, 0x0e, 0xf2, 0xf2, 0x7b, 0x4e, 0xee, 0x49, 0x72, - 0x70, 0x84, 0xfc, 0xae, 0x1d, 0x3c, 0x96, 0x68, 0x71, 0x76, 0x5c, 0x66, 0x40, 0x45, 0x61, 0x78, - 0x93, 0x50, 0xbb, 0xf0, 0xaf, 0x4c, 0x28, 0x07, 0x93, 0x50, 0x28, 0x5c, 0x42, 0xf3, 0x74, 0x5c, - 0xa9, 0xf2, 0x14, 0xec, 0x51, 0xd8, 0xc1, 0x77, 0x04, 0x04, 0x58, 0x64, 0xa3, 0x89, 0x14, 0x58, - 0x02, 0xbf, 0x41, 0x72, 0x36, 0xcd, 0x1c, 0xca, 0xd8, 0xba, 0x10, 0x4a, 0x57, 0x2a, 0x47, 0x42, - 0xe8, 0x1b, 0x50, 0xa1, 0xc2, 0xe3, 0x58, 0xe6, 0xbc, 0x59, 0xc6, 0x1a, 0x30, 0x5d, 0x1e, 0x02, - 0x79, 0x93, 0x84, 0xea, 0x0b, 0x54, 0x15, 0x7a, 0x7d, 0xfc, 0xed, 0x0c, 0xdc, 0x4c, 0x99, 0x36, - 0xb9, 0xca, 0x37, 0x61, 0xe1, 0x24, 0x4a, 0x54, 0xa3, 0x4b, 0x4b, 0x7d, 0x45, 0xb1, 0xd5, 0xe4, - 0x98, 0x9a, 0x8d, 0x93, 0x24, 0x20, 0x56, 0xba, 0x68, 0x06, 0x13, 0x91, 0xf2, 0xa8, 0x74, 0xd1, - 0x34, 0x92, 0xbe, 0x73, 0x08, 0x6b, 0xed, 0x4b, 0xc1, 0x31, 0x36, 0xf5, 0x87, 0x30, 0x14, 0x19, - 0x25, 0x0f, 0x98, 0x33, 0xaf, 0x75, 0xc0, 0x3c, 0xa0, 0xd0, 0xda, 0xa8, 0xac, 0x9f, 0xa6, 0x10, - 0xdc, 0x40, 0x45, 0x1e, 0x7a, 0xc8, 0x43, 0x85, 0xcc, 0xf7, 0xa3, 0x07, 0x3c, 0x8c, 0x00, 0xe6, - 0xf7, 0x26, 0xc3, 0xd0, 0x89, 0xdf, 0xf4, 0x60, 0xdf, 0x92, 0x79, 0xb0, 0x1e, 0x35, 0x6a, 0xa9, - 0x15, 0x41, 0x54, 0x11, 0x0e, 0xd6, 0x48, 0x14, 0x64, 0xcd, 0xd6, 0x37, 0x3f, 0x4a, 0xd6, 0x60, - 0xdc, 0x84, 0xd5, 0xf8, 0x8b, 0x86, 0x4d, 0x6d, 0x35, 0xff, 0x24, 0x43, 0x1e, 0xe5, 0xc9, 0xf7, - 0x45, 0x58, 0x1b, 0x16, 0x03, 0xc7, 0x3d, 0x1d, 0x72, 0xbd, 0xf8, 0x40, 0x0e, 0xc2, 0x72, 0xb2, - 0x6d, 0xf2, 0x0d, 0x12, 0x73, 0x81, 0x72, 0xc4, 0xa5, 0x05, 0x6c, 0xe3, 0xba, 0x46, 0xc6, 0x64, - 0x31, 0x35, 0x1a, 0xb3, 0x8d, 0xef, 0x40, 0x3d, 0x59, 0x11, 0xfb, 0x48, 0x46, 0xa4, 0xc7, 0xad, - 0xca, 0x4d, 0x85, 0xeb, 0xc6, 0x04, 0x51, 0x89, 0xc7, 0x3e, 0x30, 0xfe, 0x6e, 0x06, 0x9a, 0x26, - 0x17, 0x94, 0xab, 0xb5, 0x52, 0xd1, 0xcc, 0xc7, 0x33, 0xa5, 0x5e, 0xdf, 0x57, 0x15, 0xe8, 0xae, - 0x5a, 0xf4, 0xf5, 0x6b, 0x27, 0x63, 0xe7, 0xc6, 0x4c, 0x8f, 0x36, 0x4a, 0x30, 0x47, 0x28, 0xc6, - 0x2a, 0x2c, 0xcb, 0xf6, 0xa8, 0xb6, 0xc4, 0xd6, 0xc3, 0x44, 0x8d, 0x09, 0xeb, 0xe1, 0x1a, 0x34, - 0x29, 0xf4, 0x54, 0xef, 0x84, 0xcc, 0xb8, 0x05, 0x6c, 0xcf, 0xee, 0xdb, 0xbe, 0xe7, 0xb9, 0x87, - 0xdc, 0x97, 0xfe, 0xb9, 0x28, 0x61, 0xa2, 0x71, 0x4d, 0x89, 0xc2, 0xf4, 0xa5, 0xae, 0x39, 0xf5, - 0x5c, 0xe5, 0x8e, 0x44, 0x5f, 0x86, 0x09, 0x8b, 0x1b, 0xf6, 0x0b, 0xae, 0x4a, 0x52, 0x43, 0xf4, - 0x09, 0x54, 0xc6, 0x51, 0xa1, 0x6a, 0xdc, 0xd5, 0x8d, 0x19, 0xb3, 0xd5, 0x9a, 0x3a, 0xb6, 0xf1, - 0x18, 0x96, 0x92, 0x65, 0x4a, 0xd6, 0xb1, 0x06, 0xa5, 0x91, 0x84, 0xc9, 0xd6, 0x45, 0xdf, 0xc6, - 0xef, 0x94, 0xa0, 0x28, 0xf5, 0x39, 0xb6, 0x0e, 0xf9, 0xbe, 0x72, 0x09, 0x8b, 0x2f, 0x62, 0x92, - 0xa9, 0xea, 0xff, 0x26, 0x3a, 0x86, 0x09, 0x3c, 0xf6, 0x09, 0xd4, 0x93, 0x56, 0xd1, 0xa9, 0xc0, - 0xf6, 0xa4, 0x39, 0xb3, 0xd6, 0x9f, 0xb2, 0x7f, 0x95, 0xe3, 0xcd, 0x91, 0x64, 0x86, 0xd2, 0x99, - 0xb6, 0x7b, 0x7a, 0xae, 0x90, 0xb7, 0x83, 0x33, 0xdb, 0x7a, 0xfc, 0xe4, 0x43, 0x19, 0xd9, 0x5e, - 0x41, 0x60, 0xf7, 0xcc, 0x7e, 0xfc, 0xe4, 0xc3, 0x69, 0x49, 0x5a, 0xc6, 0xb5, 0x6b, 0x92, 0xf4, - 0x12, 0x14, 0xe8, 0x3e, 0x4f, 0xf2, 0xed, 0xa1, 0x0f, 0xf6, 0x08, 0x96, 0xa4, 0xda, 0x6a, 0x49, - 0x2f, 0x6c, 0xe2, 0x82, 0x25, 0x0a, 0x7c, 0x93, 0x69, 0x5d, 0x4c, 0xa2, 0xb3, 0xa1, 0x15, 0x98, - 0x3b, 0x8b, 0x2f, 0x67, 0xad, 0x99, 0xf2, 0xcb, 0xf8, 0xd3, 0x02, 0x54, 0xb4, 0x41, 0x61, 0x55, - 0x28, 0x99, 0xed, 0x6e, 0xdb, 0xfc, 0xac, 0xbd, 0xd5, 0xb8, 0xc1, 0xee, 0xc3, 0xdb, 0x9d, 0xfd, - 0xcd, 0x03, 0xd3, 0x6c, 0x6f, 0xf6, 0xac, 0x03, 0xd3, 0x52, 0xd7, 0x81, 0x1d, 0xb6, 0x9e, 0xef, - 0xb5, 0xf7, 0x7b, 0xd6, 0x56, 0xbb, 0xd7, 0xea, 0xec, 0x76, 0x1b, 0x19, 0x76, 0x1b, 0x9a, 0x31, - 0xa6, 0x4a, 0x6e, 0xed, 0x1d, 0x1c, 0xed, 0xf7, 0x1a, 0x59, 0x76, 0x17, 0x6e, 0x6d, 0x77, 0xf6, - 0x5b, 0xbb, 0x56, 0x8c, 0xb3, 0xb9, 0xdb, 0xfb, 0xcc, 0x6a, 0xff, 0xca, 0x61, 0xc7, 0x7c, 0xde, - 0xc8, 0xa5, 0x21, 0x08, 0x65, 0x5c, 0x95, 0x90, 0x67, 0x37, 0x61, 0x99, 0x10, 0x28, 0x8b, 0xd5, - 0x3b, 0x38, 0xb0, 0xba, 0x07, 0x07, 0xfb, 0x8d, 0x02, 0x5b, 0x80, 0x5a, 0x67, 0xff, 0xb3, 0xd6, - 0x6e, 0x67, 0xcb, 0x32, 0xdb, 0xad, 0xdd, 0xbd, 0xc6, 0x1c, 0x5b, 0x84, 0xf9, 0x69, 0xbc, 0xa2, - 0x28, 0x42, 0xe1, 0x1d, 0xec, 0x77, 0x0e, 0xf6, 0xad, 0xcf, 0xda, 0x66, 0xb7, 0x73, 0xb0, 0xdf, - 0x28, 0xb1, 0x15, 0x60, 0xc9, 0xa4, 0x9d, 0xbd, 0xd6, 0x66, 0xa3, 0xcc, 0x96, 0x61, 0x21, 0x09, - 0x7f, 0xd6, 0x7e, 0xde, 0x00, 0xd6, 0x84, 0x25, 0x6a, 0x98, 0xb5, 0xd1, 0xde, 0x3d, 0xf8, 0xdc, - 0xda, 0xeb, 0xec, 0x77, 0xf6, 0x8e, 0xf6, 0x1a, 0x15, 0xbc, 0x65, 0xb0, 0xdd, 0xb6, 0x3a, 0xfb, - 0xdd, 0xa3, 0xed, 0xed, 0xce, 0x66, 0xa7, 0xbd, 0xdf, 0x6b, 0x54, 0xa9, 0xe6, 0xb4, 0x8e, 0xd7, - 0x44, 0x06, 0x19, 0xaa, 0x61, 0x6d, 0x75, 0xba, 0xad, 0x8d, 0xdd, 0xf6, 0x56, 0xa3, 0xce, 0xee, - 0xc0, 0xcd, 0x5e, 0x7b, 0xef, 0xf0, 0xc0, 0x6c, 0x99, 0xcf, 0x55, 0x28, 0x87, 0xb5, 0xdd, 0xea, - 0xec, 0x1e, 0x99, 0xed, 0xc6, 0x3c, 0x7b, 0x13, 0xee, 0x98, 0xed, 0x4f, 0x8f, 0x3a, 0x66, 0x7b, - 0xcb, 0xda, 0x3f, 0xd8, 0x6a, 0x5b, 0xdb, 0xed, 0x56, 0xef, 0xc8, 0x6c, 0x5b, 0x7b, 0x9d, 0x6e, - 0xb7, 0xb3, 0xff, 0xb4, 0xd1, 0x60, 0x6f, 0xc3, 0xbd, 0x08, 0x25, 0x2a, 0x60, 0x0a, 0x6b, 0x41, - 0xf4, 0x4f, 0x4d, 0xe9, 0x7e, 0xfb, 0x57, 0x7a, 0xd6, 0x61, 0xbb, 0x6d, 0x36, 0x18, 0x5b, 0x83, - 0x95, 0xb8, 0x7a, 0xaa, 0x40, 0xd6, 0xbd, 0x28, 0xd2, 0x0e, 0xdb, 0xe6, 0x5e, 0x6b, 0x5f, 0x4c, - 0x70, 0x22, 0x6d, 0x49, 0x34, 0x3b, 0x4e, 0x9b, 0x6e, 0xf6, 0x32, 0x63, 0x50, 0xd7, 0x66, 0x65, - 0xbb, 0x65, 0x36, 0x56, 0xd8, 0x3c, 0x54, 0xf6, 0x0e, 0x0f, 0xad, 0x5e, 0x67, 0xaf, 0x7d, 0x70, - 0xd4, 0x6b, 0xac, 0xb2, 0x65, 0x68, 0x74, 0xf6, 0x7b, 0x6d, 0x53, 0xcc, 0xb5, 0xca, 0xfa, 0x3f, - 0x8b, 0x6c, 0x09, 0xe6, 0x55, 0x4b, 0x15, 0xf4, 0x2f, 0x8a, 0x6c, 0x15, 0xd8, 0xd1, 0xbe, 0xd9, - 0x6e, 0x6d, 0x89, 0x81, 0x8b, 0x12, 0xfe, 0x57, 0x51, 0x5a, 0x48, 0x7e, 0x92, 0x8b, 0x36, 0xeb, - 0xd8, 0xe5, 0x20, 0x79, 0x55, 0x77, 0x55, 0xbb, 0x62, 0xfb, 0x55, 0x8f, 0x68, 0x68, 0xaa, 0x55, - 0x6e, 0x46, 0xb5, 0x9a, 0xd1, 0xdd, 0x6b, 0xba, 0xec, 0xf7, 0x16, 0xd4, 0x46, 0x74, 0x6d, 0xb7, - 0xbc, 0x9e, 0x17, 0xa4, 0xff, 0x0d, 0x01, 0xe9, 0x6e, 0xde, 0x99, 0x57, 0x24, 0x0a, 0xb3, 0xaf, - 0x48, 0xa4, 0xc9, 0xf7, 0x73, 0x69, 0xf2, 0xfd, 0x03, 0x58, 0x20, 0xd6, 0xe4, 0xb8, 0xce, 0x48, - 0x69, 0xcd, 0x24, 0x05, 0xce, 0x23, 0x8b, 0x22, 0xb8, 0x52, 0x27, 0x94, 0xca, 0x21, 0x59, 0x48, - 0x51, 0x6a, 0x1b, 0x09, 0x4d, 0x83, 0x38, 0x47, 0xa4, 0x69, 0x44, 0x35, 0xd8, 0x97, 0x71, 0x0d, - 0x15, 0xad, 0x06, 0x82, 0x63, 0x0d, 0x0f, 0x60, 0x81, 0x5f, 0x86, 0xbe, 0x6d, 0x79, 0x63, 0xfb, - 0x8b, 0x09, 0x9a, 0x70, 0x6d, 0xd4, 0xe1, 0xab, 0xe6, 0x3c, 0x26, 0x1c, 0x20, 0x7c, 0xcb, 0x0e, - 0xed, 0x07, 0x5f, 0x42, 0x45, 0xbb, 0xd2, 0x9d, 0xad, 0xc2, 0xe2, 0xe7, 0x9d, 0xde, 0x7e, 0xbb, - 0xdb, 0xb5, 0x0e, 0x8f, 0x36, 0x9e, 0xb5, 0x9f, 0x5b, 0x3b, 0xad, 0xee, 0x4e, 0xe3, 0x86, 0x58, - 0xb4, 0xfb, 0xed, 0x6e, 0xaf, 0xbd, 0x95, 0x80, 0x67, 0xd8, 0x1b, 0xb0, 0x76, 0xb4, 0x7f, 0xd4, - 0x6d, 0x6f, 0x59, 0x69, 0xf9, 0xb2, 0x82, 0x4a, 0x65, 0x7a, 0x4a, 0xf6, 0xdc, 0x83, 0xdf, 0x80, - 0x7a, 0x32, 0xaa, 0x99, 0x01, 0xcc, 0xed, 0xb6, 0x9f, 0xb6, 0x36, 0x9f, 0xd3, 0x3d, 0xa4, 0xdd, - 0x5e, 0xab, 0xd7, 0xd9, 0xb4, 0xe4, 0xbd, 0xa3, 0x82, 0x23, 0x64, 0x58, 0x05, 0x8a, 0xad, 0xfd, - 0xcd, 0x9d, 0x03, 0xb3, 0xdb, 0xc8, 0xb2, 0xdb, 0xb0, 0xaa, 0x68, 0x75, 0xf3, 0x60, 0x6f, 0xaf, - 0xd3, 0x43, 0x66, 0xd8, 0x7b, 0x7e, 0x28, 0x48, 0xf3, 0x81, 0x0d, 0xe5, 0xf8, 0xe2, 0x54, 0x64, - 0x30, 0x9d, 0x5e, 0xa7, 0xd5, 0x8b, 0xb9, 0x6b, 0xe3, 0x86, 0xe0, 0x5f, 0x31, 0x18, 0xef, 0x3d, - 0x6d, 0x64, 0x28, 0xf0, 0x4b, 0x01, 0xa9, 0xf6, 0x46, 0x56, 0x2c, 0xaa, 0x18, 0xba, 0x71, 0xd0, - 0x13, 0x5d, 0xf8, 0x0e, 0xd4, 0x93, 0xee, 0x7d, 0xc9, 0x83, 0xdf, 0x35, 0x58, 0xd9, 0x68, 0xf7, - 0x3e, 0x6f, 0xb7, 0xf7, 0x71, 0x74, 0x36, 0xdb, 0xfb, 0x3d, 0xb3, 0xb5, 0xdb, 0xe9, 0x3d, 0x6f, - 0x64, 0x1e, 0x7c, 0x02, 0x8d, 0x69, 0x5b, 0x5a, 0xc2, 0xf8, 0xf8, 0x32, 0x2b, 0xe5, 0x83, 0x7f, - 0x91, 0x03, 0x88, 0x63, 0x4c, 0x04, 0x9b, 0xdc, 0x6a, 0xf5, 0x5a, 0xbb, 0x07, 0x62, 0x0a, 0xcc, - 0x83, 0x9e, 0xe0, 0x7e, 0x66, 0xfb, 0xd3, 0xc6, 0x8d, 0xd4, 0x94, 0x83, 0xc3, 0x5e, 0x23, 0x23, - 0x66, 0x9b, 0xba, 0xb3, 0x6b, 0x99, 0x07, 0x47, 0x9d, 0xfd, 0xa7, 0x74, 0xaf, 0x24, 0xee, 0x10, - 0x47, 0x87, 0xdb, 0xe6, 0xc1, 0x7e, 0xcf, 0xea, 0xee, 0x1c, 0xf5, 0xb6, 0xf0, 0x56, 0xca, 0x4d, - 0xb3, 0x73, 0x48, 0x65, 0xe6, 0x5f, 0x86, 0x20, 0x8a, 0x2e, 0x08, 0x7a, 0x79, 0x7a, 0xd0, 0xed, - 0x76, 0x0e, 0xad, 0x4f, 0x8f, 0xda, 0x66, 0xa7, 0xdd, 0xc5, 0x8c, 0x73, 0x29, 0x70, 0x81, 0x5f, - 0x14, 0xfb, 0x4a, 0x6f, 0xf7, 0x33, 0xc9, 0xf8, 0x05, 0x6a, 0x29, 0x09, 0x12, 0x58, 0x65, 0x31, - 0x98, 0x82, 0x73, 0xa6, 0x94, 0x0c, 0xd7, 0xa4, 0x89, 0x7c, 0x15, 0xb1, 0x27, 0xcc, 0x10, 0x12, - 0x66, 0xab, 0xa6, 0x27, 0x89, 0x5c, 0xb8, 0x5d, 0x44, 0x9b, 0xeb, 0xd6, 0x96, 0x89, 0x19, 0xea, - 0x33, 0x50, 0x81, 0x3b, 0x2f, 0x26, 0x4a, 0xb0, 0x56, 0x81, 0xd2, 0x50, 0x1f, 0x22, 0x65, 0xe1, - 0xf1, 0x6f, 0xe7, 0xa0, 0x4e, 0xf1, 0x7e, 0xf4, 0x1a, 0x20, 0xf7, 0xd9, 0x1e, 0x14, 0xe5, 0xb3, - 0x92, 0x6c, 0x39, 0xba, 0xf2, 0x4f, 0x7f, 0xc8, 0x72, 0x6d, 0x65, 0x1a, 0x2c, 0x45, 0xc9, 0xc5, - 0xbf, 0xf6, 0x27, 0xff, 0xe3, 0xef, 0x65, 0x6b, 0xac, 0xf2, 0xf0, 0xfc, 0x83, 0x87, 0xa7, 0xdc, - 0x0d, 0x44, 0x19, 0xbf, 0x06, 0x10, 0x3f, 0x96, 0xc8, 0x9a, 0xda, 0x1d, 0x03, 0x89, 0x67, 0x12, - 0xd7, 0x6e, 0xa6, 0xa4, 0xc8, 0x72, 0x6f, 0x62, 0xb9, 0x8b, 0x46, 0x5d, 0x94, 0xeb, 0xb8, 0x4e, - 0x48, 0x0f, 0x27, 0x7e, 0x9c, 0x79, 0xc0, 0x06, 0x50, 0xd5, 0x9f, 0x31, 0x64, 0x4a, 0xca, 0x4b, - 0x79, 0x88, 0x71, 0xed, 0x56, 0x6a, 0x9a, 0x92, 0x9f, 0xb1, 0x8e, 0x65, 0xa3, 0x21, 0xea, 0x98, - 0x20, 0x46, 0x5c, 0xcb, 0x90, 0x34, 0x8a, 0xf8, 0xb5, 0x42, 0x76, 0x5b, 0x93, 0x09, 0x67, 0xde, - 0x4a, 0x5c, 0xbb, 0x73, 0x4d, 0xaa, 0xac, 0xeb, 0x0e, 0xd6, 0xb5, 0x6a, 0x30, 0x51, 0x57, 0x1f, - 0x71, 0xd4, 0x5b, 0x89, 0x1f, 0x67, 0x1e, 0x3c, 0xfe, 0x8f, 0xef, 0x41, 0x39, 0xf2, 0xff, 0x65, - 0xbf, 0x09, 0xb5, 0x44, 0x40, 0x26, 0x53, 0xdd, 0x48, 0x8b, 0xdf, 0x5c, 0xbb, 0x9d, 0x9e, 0x28, - 0x2b, 0x7e, 0x03, 0x2b, 0x6e, 0xb2, 0x15, 0x51, 0xb1, 0x0c, 0x78, 0x7c, 0x88, 0x01, 0xd4, 0x74, - 0x81, 0xe2, 0x0b, 0x4d, 0x73, 0xa2, 0xca, 0x6e, 0x4f, 0x6b, 0x33, 0x89, 0xda, 0xee, 0x5c, 0x93, - 0x2a, 0xab, 0xbb, 0x8d, 0xd5, 0xad, 0xb0, 0x25, 0xbd, 0x3a, 0xe5, 0x36, 0xca, 0x38, 0x5e, 0x5a, - 0xaa, 0x3f, 0xe6, 0xc7, 0xee, 0xc4, 0x57, 0x4c, 0xa6, 0x3c, 0xf2, 0x17, 0x91, 0xc8, 0xec, 0x4b, - 0x7f, 0x46, 0x13, 0xab, 0x62, 0x0c, 0xa7, 0x4f, 0x7f, 0xcb, 0x8f, 0x1d, 0x43, 0x45, 0x7b, 0xff, - 0x86, 0xdd, 0xbc, 0xf6, 0xad, 0x9e, 0xb5, 0xb5, 0xb4, 0xa4, 0xb4, 0xae, 0xe8, 0xe5, 0x3f, 0x3c, - 0xe1, 0x9c, 0xfd, 0x2a, 0x94, 0xa3, 0x57, 0x55, 0xd8, 0xaa, 0xf6, 0xca, 0x8d, 0xfe, 0x0a, 0xcc, - 0x5a, 0x73, 0x36, 0x21, 0x8d, 0xf8, 0xf4, 0xd2, 0x05, 0xf1, 0x7d, 0x0e, 0x15, 0xed, 0xe5, 0x94, - 0xa8, 0x03, 0xb3, 0xaf, 0xb3, 0x44, 0x1d, 0x48, 0x79, 0x68, 0xc5, 0x58, 0xc0, 0x2a, 0x2a, 0xac, - 0x8c, 0xf4, 0x1d, 0x5e, 0x7a, 0x01, 0xdb, 0x85, 0x65, 0xa9, 0x25, 0x1e, 0xf3, 0xaf, 0x32, 0x0d, - 0x29, 0xef, 0x27, 0x3e, 0xca, 0xb0, 0x4f, 0xa0, 0xa4, 0x1e, 0xc8, 0x61, 0x2b, 0xe9, 0x0f, 0xfd, - 0xac, 0xad, 0xce, 0xc0, 0xa5, 0x4a, 0xf7, 0x1c, 0x20, 0x7e, 0xa6, 0x25, 0x62, 0x12, 0x33, 0xcf, - 0xbe, 0x44, 0x14, 0x30, 0xfb, 0xa6, 0x8b, 0xb1, 0x82, 0x1d, 0x6c, 0x30, 0x64, 0x12, 0x2e, 0xbf, - 0x50, 0x37, 0x4b, 0xff, 0x10, 0x2a, 0xda, 0x4b, 0x2d, 0xd1, 0xf0, 0xcd, 0xbe, 0xf2, 0x12, 0x0d, - 0x5f, 0xca, 0xc3, 0x2e, 0xc6, 0x1a, 0x96, 0xbe, 0x64, 0xcc, 0x8b, 0xd2, 0x85, 0x98, 0x28, 0xc5, - 0x35, 0x31, 0x41, 0x67, 0x50, 0x4b, 0x3c, 0xc7, 0x12, 0xad, 0xd0, 0xb4, 0xc7, 0x5e, 0xa2, 0x15, - 0x9a, 0xfa, 0x82, 0x8b, 0xa2, 0x33, 0x63, 0x41, 0xd4, 0x43, 0x97, 0x4b, 0x69, 0x35, 0xfd, 0x00, - 0x2a, 0xda, 0xd3, 0x2a, 0x51, 0x5f, 0x66, 0x5f, 0x71, 0x89, 0xfa, 0x92, 0xf6, 0x12, 0xcb, 0x12, - 0xd6, 0x51, 0x37, 0x90, 0x14, 0xf0, 0x6e, 0x5c, 0x51, 0xf6, 0x6f, 0x42, 0x3d, 0xf9, 0xda, 0x4a, - 0xb4, 0xf6, 0x53, 0x9f, 0x6d, 0x89, 0xd6, 0xfe, 0x35, 0x4f, 0xb4, 0x48, 0x92, 0x7e, 0xb0, 0x18, - 0x55, 0xf2, 0xf0, 0xc7, 0x32, 0x92, 0xe9, 0x4b, 0xf6, 0xa9, 0x60, 0x70, 0xf2, 0x6a, 0x66, 0xb6, - 0xaa, 0x51, 0xad, 0x7e, 0xc7, 0x73, 0xb4, 0x5e, 0x66, 0x6e, 0x71, 0x4e, 0x12, 0x33, 0x16, 0xce, - 0x9e, 0xc2, 0x62, 0x44, 0xcc, 0xd1, 0x5d, 0xcb, 0x41, 0xd4, 0x87, 0xd4, 0x1b, 0x9d, 0xd7, 0x1a, - 0xd3, 0xa9, 0x8f, 0x32, 0xb4, 0xfd, 0xe1, 0x0d, 0xb7, 0xda, 0xf6, 0xa7, 0x5f, 0xb7, 0xac, 0x6d, - 0x7f, 0x89, 0x8b, 0x70, 0xa7, 0xb7, 0xbf, 0xd0, 0x11, 0x65, 0xb8, 0x30, 0x3f, 0x7d, 0xf3, 0xf1, - 0x9d, 0xeb, 0x6e, 0x8a, 0xa0, 0xe2, 0xdf, 0x78, 0xf9, 0x45, 0x12, 0x49, 0x56, 0xa4, 0xb8, 0xe9, - 0x43, 0xe9, 0x38, 0xc3, 0x7e, 0x1d, 0xaa, 0xfa, 0x0b, 0x0d, 0x4c, 0xe7, 0x09, 0xd3, 0x35, 0xdd, - 0x4a, 0x4d, 0x4b, 0x52, 0x09, 0xab, 0xea, 0xd5, 0xb0, 0xcf, 0x60, 0x25, 0x1a, 0x66, 0xfd, 0xaa, - 0x83, 0x80, 0xdd, 0x4d, 0xb9, 0x00, 0x21, 0x31, 0xd8, 0x37, 0xaf, 0xbd, 0x21, 0xe1, 0x51, 0x46, - 0x50, 0x5f, 0xf2, 0x36, 0xfa, 0x78, 0xe7, 0x49, 0xbb, 0x84, 0x3f, 0xde, 0x79, 0x52, 0xaf, 0xb0, - 0x57, 0xd4, 0xc7, 0x16, 0x13, 0x63, 0x44, 0x2e, 0xc5, 0xec, 0x07, 0x30, 0xaf, 0xdd, 0xe3, 0xd0, - 0xbd, 0x72, 0xfb, 0xd1, 0x4a, 0x9a, 0xbd, 0xd3, 0x74, 0x2d, 0xed, 0x5c, 0xd5, 0x58, 0xc5, 0xf2, - 0x17, 0x8c, 0xc4, 0xe0, 0x88, 0x55, 0xb4, 0x09, 0x15, 0xfd, 0x8e, 0x88, 0x97, 0x94, 0xbb, 0xaa, - 0x25, 0xe9, 0xd7, 0x67, 0x3e, 0xca, 0xb0, 0x5d, 0x68, 0x4c, 0xdf, 0xe8, 0x16, 0xf1, 0x94, 0xb4, - 0x5b, 0xf0, 0xd6, 0xa6, 0x12, 0x13, 0xf7, 0xc0, 0xb1, 0x43, 0x0a, 0x4a, 0x89, 0x1e, 0x1b, 0xf4, - 0xfc, 0xe9, 0x5d, 0x3d, 0xf9, 0x08, 0x61, 0x54, 0x5a, 0xda, 0xf3, 0x93, 0xf7, 0x33, 0x8f, 0x32, - 0xec, 0x77, 0x33, 0x50, 0x4d, 0xdc, 0x68, 0x94, 0x70, 0xfb, 0x9f, 0xea, 0x67, 0x53, 0x4f, 0xd3, - 0x3b, 0x6a, 0x98, 0x38, 0x88, 0xbb, 0x0f, 0xbe, 0x9f, 0x98, 0xa4, 0x1f, 0x27, 0xcc, 0x92, 0xeb, - 0xd3, 0xaf, 0x11, 0x7e, 0x39, 0x8d, 0xa0, 0xdf, 0x92, 0xfb, 0xe5, 0xa3, 0x0c, 0xfb, 0x57, 0x19, - 0xa8, 0x27, 0xfd, 0x0d, 0xa2, 0xee, 0xa6, 0x7a, 0x36, 0x44, 0xa4, 0x74, 0x8d, 0x93, 0xc2, 0x0f, - 0xb0, 0x95, 0xbd, 0x07, 0x66, 0xa2, 0x95, 0xf2, 0x1d, 0x85, 0x9f, 0xad, 0xb5, 0xec, 0x97, 0xe9, - 0xf1, 0x5f, 0xe5, 0x86, 0xc5, 0x66, 0x1f, 0x8b, 0x8d, 0xc8, 0x4f, 0x7f, 0x5a, 0xd5, 0xc8, 0xfd, - 0x56, 0x36, 0x83, 0x33, 0xf1, 0x43, 0x7a, 0x7a, 0x4f, 0xb9, 0xf6, 0x08, 0x52, 0x7e, 0xed, 0x42, - 0xde, 0xc6, 0x8e, 0xbd, 0x61, 0xdc, 0x4c, 0x74, 0x6c, 0x5a, 0xfa, 0x68, 0x51, 0x13, 0xe5, 0xf3, - 0xa8, 0xf1, 0xf6, 0x39, 0xf3, 0x64, 0x6a, 0x6a, 0x25, 0xd8, 0xc8, 0x11, 0x35, 0x52, 0xa2, 0x27, - 0xd6, 0xdb, 0x6b, 0x16, 0x63, 0x3c, 0xc0, 0xb6, 0xbe, 0x6d, 0xdc, 0xbd, 0xb6, 0xad, 0x0f, 0xd1, - 0x81, 0x40, 0xb4, 0xf8, 0x10, 0x20, 0xf6, 0x95, 0x64, 0x53, 0x1e, 0x7b, 0x11, 0x17, 0x9a, 0x75, - 0xa7, 0x4c, 0x2e, 0x6a, 0xe5, 0xd8, 0x27, 0x4a, 0xfc, 0x55, 0xe2, 0xa9, 0x91, 0x2f, 0xa1, 0x2e, - 0x82, 0x25, 0xdd, 0x1a, 0x13, 0x22, 0xd8, 0x74, 0xf9, 0x09, 0x8e, 0x1a, 0x39, 0x0e, 0x1e, 0x41, - 0x6d, 0xd7, 0xf3, 0x5e, 0x4c, 0xc6, 0x91, 0x7f, 0x7e, 0xd2, 0xab, 0x67, 0xc7, 0x0e, 0xce, 0xd6, - 0xa6, 0x7a, 0x61, 0xdc, 0xc3, 0xa2, 0xd6, 0x58, 0x53, 0x2b, 0xea, 0xe1, 0x8f, 0x63, 0x07, 0xcd, - 0x2f, 0x99, 0x0d, 0x0b, 0x11, 0xa3, 0x8e, 0x9d, 0x20, 0x93, 0xc5, 0x24, 0xd8, 0xf3, 0x74, 0x15, - 0x09, 0x5d, 0x41, 0xb5, 0xf6, 0x61, 0xa0, 0xca, 0x7c, 0x94, 0x61, 0x87, 0x50, 0xdd, 0xe2, 0x7d, - 0xbc, 0xe0, 0x01, 0x7d, 0x63, 0x16, 0x13, 0x7e, 0x16, 0xe4, 0x54, 0xb3, 0x56, 0x4b, 0x00, 0x93, - 0x9b, 0xd7, 0xd8, 0xbe, 0xf2, 0xf9, 0x17, 0x0f, 0x7f, 0x2c, 0xbd, 0x6e, 0xbe, 0x54, 0x9b, 0x97, - 0xf2, 0x4a, 0x4a, 0x6c, 0x5e, 0x53, 0x6e, 0x4c, 0x89, 0xcd, 0x6b, 0xc6, 0x8d, 0x29, 0x31, 0xd4, - 0xca, 0x2b, 0x8a, 0x0d, 0x61, 0x61, 0xc6, 0xf3, 0x29, 0xda, 0xb7, 0xae, 0xf3, 0x97, 0x5a, 0xbb, - 0x77, 0x3d, 0x42, 0xb2, 0xb6, 0x07, 0xc9, 0xda, 0xba, 0x50, 0xa3, 0x7b, 0x70, 0x8f, 0x39, 0x85, - 0x7a, 0x4e, 0xdd, 0x93, 0xa4, 0xc7, 0x91, 0x4e, 0xef, 0x32, 0x98, 0x96, 0x14, 0x73, 0x30, 0xd8, - 0x8f, 0x9d, 0xe0, 0xe3, 0x0f, 0x5a, 0x6c, 0x65, 0x44, 0x8c, 0xb3, 0xf1, 0x9e, 0x11, 0x31, 0xa6, - 0x84, 0x62, 0x2a, 0x1d, 0x94, 0x2d, 0x47, 0x65, 0x3f, 0x74, 0xbd, 0x01, 0x1f, 0xc9, 0x52, 0x7f, - 0x15, 0x2a, 0x4f, 0x79, 0xa8, 0x82, 0x19, 0x23, 0x81, 0x7e, 0x2a, 0xba, 0x71, 0x2d, 0x25, 0x04, - 0x35, 0x49, 0x9b, 0x54, 0x32, 0x1f, 0x9c, 0x72, 0xe2, 0x84, 0x96, 0x33, 0xf8, 0x92, 0xfd, 0x0a, - 0x16, 0x1e, 0x85, 0xee, 0xaf, 0x68, 0xcd, 0xd4, 0x0b, 0x9f, 0x9f, 0x82, 0xa7, 0x95, 0x2c, 0xda, - 0xac, 0x09, 0x96, 0x2e, 0x54, 0xb4, 0x2b, 0x3e, 0xa2, 0xb1, 0x99, 0xbd, 0xd2, 0x25, 0x1a, 0x9b, - 0x94, 0x1b, 0x41, 0x8c, 0xfb, 0x58, 0x8f, 0xc1, 0xee, 0xc5, 0xf5, 0xd0, 0x2d, 0x20, 0x71, 0x4d, - 0x0f, 0x7f, 0x6c, 0x8f, 0xc2, 0x2f, 0xd9, 0xe7, 0x34, 0x1d, 0x5a, 0xb0, 0x66, 0xac, 0xa1, 0x4c, - 0xc7, 0x75, 0x46, 0x83, 0xa5, 0x25, 0x25, 0xb5, 0x16, 0xaa, 0x0a, 0xc5, 0xc6, 0x27, 0x00, 0xdd, - 0xd0, 0x1b, 0x6f, 0xd9, 0x7c, 0xe4, 0xb9, 0x31, 0x4f, 0x8f, 0xc3, 0x07, 0x63, 0x3e, 0xa9, 0xc5, - 0x10, 0xb2, 0xcf, 0x35, 0x95, 0x2e, 0x11, 0x66, 0xac, 0x88, 0xf8, 0xda, 0x08, 0xc3, 0x68, 0x40, - 0x52, 0xa2, 0x0c, 0x1f, 0x65, 0x58, 0x0b, 0x20, 0x76, 0xb1, 0x8b, 0x14, 0xb4, 0x19, 0xef, 0xbd, - 0x88, 0xbd, 0xa6, 0xf8, 0xe3, 0x1d, 0x42, 0x39, 0xf6, 0x4d, 0x5a, 0x8d, 0x6f, 0x2c, 0x4a, 0x78, - 0x32, 0x45, 0xe2, 0xc2, 0x8c, 0x5f, 0x90, 0xd1, 0xc0, 0xa1, 0x02, 0x56, 0x12, 0x43, 0x75, 0xc2, - 0x79, 0xc0, 0x1c, 0x58, 0xa4, 0x06, 0x46, 0xb2, 0x19, 0x86, 0xbd, 0x45, 0x4f, 0xae, 0xcc, 0xba, - 0xe8, 0x44, 0x5c, 0x23, 0xd5, 0xd1, 0x24, 0x71, 0xce, 0x24, 0xa8, 0x95, 0x42, 0xee, 0xc4, 0x16, - 0x30, 0x82, 0x85, 0x19, 0x5f, 0x86, 0x88, 0x75, 0x5c, 0xe7, 0x9c, 0x12, 0xb1, 0x8e, 0x6b, 0xdd, - 0x20, 0x8c, 0x65, 0xac, 0x72, 0xde, 0x00, 0xd4, 0x2b, 0x2f, 0x9c, 0xb0, 0x7f, 0x26, 0xaa, 0xfb, - 0xfd, 0x0c, 0x2c, 0xa6, 0x78, 0x2b, 0xb0, 0x37, 0xd5, 0x11, 0xc5, 0xb5, 0x9e, 0x0c, 0x6b, 0xa9, - 0x56, 0x6d, 0xa3, 0x8b, 0xf5, 0xec, 0xb1, 0x67, 0x89, 0x0d, 0x94, 0x8c, 0xca, 0x72, 0x65, 0xbe, - 0x54, 0x82, 0x49, 0x15, 0x5f, 0xbe, 0x80, 0x55, 0x6a, 0x48, 0x6b, 0x38, 0x9c, 0xb2, 0xb8, 0xbf, - 0xa1, 0xb5, 0x22, 0xc5, 0x8b, 0x20, 0xa1, 0x0c, 0x24, 0x3d, 0x09, 0xae, 0x91, 0xdd, 0xa9, 0xa9, - 0x6c, 0x02, 0x8d, 0x69, 0x4b, 0x36, 0xbb, 0xbe, 0xac, 0xb5, 0xbb, 0x09, 0x65, 0x3b, 0xc5, 0xfa, - 0xfd, 0x35, 0xac, 0xec, 0xae, 0xb1, 0x96, 0x36, 0x2e, 0xa4, 0x7f, 0x8b, 0xf9, 0xf8, 0xab, 0x91, - 0xd9, 0x7d, 0xaa, 0x9f, 0x77, 0xa3, 0x4b, 0xe6, 0xd3, 0x9d, 0x04, 0x22, 0x75, 0x3f, 0xdd, 0x6a, - 0xff, 0x0e, 0x56, 0x7f, 0xcf, 0xb8, 0x95, 0x56, 0xbd, 0x4f, 0x59, 0x48, 0xf1, 0x5f, 0x9d, 0x5e, - 0xd7, 0xaa, 0x05, 0xf7, 0xd2, 0xe6, 0xfb, 0x5a, 0xc5, 0x6b, 0x6a, 0xac, 0x6f, 0xa0, 0x0c, 0x59, - 0xd5, 0xcd, 0xec, 0xd1, 0xf2, 0x49, 0xb1, 0xe7, 0x47, 0xcb, 0x27, 0xcd, 0x2e, 0x9f, 0x94, 0x9f, - 0x94, 0x45, 0xfe, 0xe3, 0xcc, 0x83, 0x8d, 0x77, 0x7f, 0xf0, 0xb5, 0x53, 0x27, 0x3c, 0x9b, 0x1c, - 0xaf, 0xf7, 0xbd, 0xd1, 0xc3, 0xa1, 0x3a, 0xda, 0x94, 0xb1, 0xe1, 0x0f, 0x87, 0xee, 0xe0, 0x21, - 0x16, 0x7b, 0x3c, 0x37, 0xf6, 0xbd, 0xd0, 0xfb, 0xe6, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x6d, - 0x0c, 0xaf, 0xd9, 0x6c, 0x89, 0x00, 0x00, + // 11938 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x69, 0x6c, 0x24, 0x49, + 0x76, 0x18, 0xdc, 0x75, 0xb1, 0xaa, 0x5e, 0x1d, 0x2c, 0x06, 0xaf, 0x6a, 0x76, 0xf7, 0x74, 0x4f, + 0xce, 0xec, 0x4c, 0x4f, 0xcf, 0x2e, 0xbb, 0xa7, 0x77, 0x7b, 0x66, 0x77, 0xe6, 0xd3, 0x6a, 0x8b, + 0x64, 0xb1, 0x59, 0xdb, 0xbc, 0x26, 0xab, 0x38, 0xa3, 0x5e, 0x1d, 0xb9, 0xc9, 0xaa, 0x20, 0x99, + 0xea, 0xaa, 0xcc, 0x9a, 0xcc, 0x2c, 0x1e, 0xbb, 0x98, 0xef, 0x87, 0x61, 0x1b, 0x82, 0x61, 0x1b, + 0x10, 0x6c, 0x19, 0xb0, 0x2c, 0xc1, 0x87, 0x60, 0x1b, 0x86, 0x01, 0x41, 0x80, 0xe4, 0x1f, 0x06, + 0xfc, 0x5f, 0x7f, 0x7c, 0xc0, 0x90, 0x0c, 0x18, 0x86, 0x20, 0xc0, 0xb0, 0x2d, 0xff, 0x33, 0x04, + 0xf8, 0xb7, 0x01, 0x23, 0xde, 0x8b, 0xc8, 0x8c, 0xac, 0x4a, 0x76, 0xf7, 0xec, 0xae, 0xf7, 0x0f, + 0x59, 0xf9, 0xe2, 0xc5, 0xfd, 0xe2, 0xc5, 0xbb, 0x22, 0x02, 0xca, 0xfe, 0xb8, 0xbf, 0x3e, 0xf6, + 0xbd, 0xd0, 0x63, 0x85, 0xa1, 0xeb, 0x8f, 0xfb, 0x6b, 0xb7, 0x4f, 0x3d, 0xef, 0x74, 0xc8, 0x1f, + 0xda, 0x63, 0xe7, 0xa1, 0xed, 0xba, 0x5e, 0x68, 0x87, 0x8e, 0xe7, 0x06, 0x84, 0x64, 0xfc, 0x10, + 0xea, 0x4f, 0xb9, 0xdb, 0xe5, 0x7c, 0x60, 0xf2, 0x2f, 0x26, 0x3c, 0x08, 0xd9, 0xfb, 0xb0, 0x60, + 0xf3, 0x1f, 0x71, 0x3e, 0xb0, 0xc6, 0x76, 0x10, 0x8c, 0xcf, 0x7c, 0x3b, 0xe0, 0xcd, 0xcc, 0xbd, + 0xcc, 0xfd, 0xaa, 0xd9, 0xa0, 0x84, 0xc3, 0x08, 0xce, 0xde, 0x84, 0x6a, 0x20, 0x50, 0xb9, 0x1b, + 0xfa, 0xde, 0xf8, 0xaa, 0x99, 0x45, 0xbc, 0x8a, 0x80, 0xb5, 0x09, 0x64, 0x0c, 0x61, 0x3e, 0xaa, + 0x21, 0x18, 0x7b, 0x6e, 0xc0, 0xd9, 0x23, 0x58, 0xea, 0x3b, 0xe3, 0x33, 0xee, 0x5b, 0x98, 0x79, + 0xe4, 0xf2, 0x91, 0xe7, 0x3a, 0xfd, 0x66, 0xe6, 0x5e, 0xee, 0x7e, 0xd9, 0x64, 0x94, 0x26, 0x72, + 0xec, 0xc9, 0x14, 0xf6, 0x2e, 0xcc, 0x73, 0x97, 0xe0, 0x7c, 0x80, 0xb9, 0x64, 0x55, 0xf5, 0x18, + 0x2c, 0x32, 0x18, 0xbf, 0x91, 0x85, 0x85, 0x8e, 0xeb, 0x84, 0x9f, 0xdb, 0xc3, 0x21, 0x0f, 0x55, + 0x9f, 0xde, 0x85, 0xf9, 0x0b, 0x04, 0x60, 0x9f, 0x2e, 0x3c, 0x7f, 0x20, 0x7b, 0x54, 0x27, 0xf0, + 0xa1, 0x84, 0x5e, 0xdb, 0xb2, 0xec, 0xb5, 0x2d, 0x4b, 0x1d, 0xae, 0xdc, 0x35, 0xc3, 0xf5, 0x2e, + 0xcc, 0xfb, 0xbc, 0xef, 0x9d, 0x73, 0xff, 0xca, 0xba, 0x70, 0xdc, 0x81, 0x77, 0xd1, 0xcc, 0xdf, + 0xcb, 0xdc, 0x2f, 0x98, 0x75, 0x05, 0xfe, 0x1c, 0xa1, 0x6c, 0x03, 0xe6, 0xfb, 0x67, 0xb6, 0xeb, + 0xf2, 0xa1, 0x75, 0x6c, 0xf7, 0x5f, 0x4c, 0xc6, 0x41, 0xb3, 0x70, 0x2f, 0x73, 0xbf, 0xf2, 0xf8, + 0xe6, 0x3a, 0xce, 0xea, 0xfa, 0xe6, 0x99, 0xed, 0x6e, 0x60, 0x4a, 0xd7, 0xb5, 0xc7, 0xc1, 0x99, + 0x17, 0x9a, 0x75, 0x99, 0x83, 0xc0, 0x81, 0xb1, 0x04, 0x4c, 0x1f, 0x09, 0x1a, 0x7b, 0xe3, 0x5f, + 0x66, 0x60, 0xf1, 0xc8, 0x1d, 0x7a, 0xfd, 0x17, 0x3f, 0xe1, 0x10, 0xa5, 0xf4, 0x21, 0xfb, 0xba, + 0x7d, 0xc8, 0x7d, 0xd5, 0x3e, 0xac, 0xc0, 0x52, 0xb2, 0xb1, 0xb2, 0x17, 0x1c, 0x96, 0x45, 0xee, + 0x53, 0xae, 0x9a, 0xa5, 0xba, 0xf1, 0x1e, 0x34, 0xfa, 0x13, 0xdf, 0xe7, 0xee, 0x4c, 0x3f, 0xe6, + 0x25, 0x3c, 0xea, 0xc8, 0x9b, 0x50, 0x75, 0xf9, 0x45, 0x8c, 0x26, 0x69, 0xd7, 0xe5, 0x17, 0x0a, + 0xc5, 0x68, 0xc2, 0xca, 0x74, 0x35, 0xb2, 0x01, 0x7f, 0x91, 0x81, 0xfc, 0x51, 0x78, 0xe9, 0xb1, + 0x27, 0x50, 0xb5, 0x07, 0x03, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x8d, 0x69, 0xa5, 0xd4, 0x1f, 0x33, + 0xd9, 0xc5, 0x16, 0x25, 0xf5, 0xae, 0xc6, 0xdc, 0xac, 0xd8, 0xf1, 0x07, 0x6b, 0x42, 0x51, 0x7e, + 0x62, 0xbd, 0x65, 0x53, 0x7d, 0xb2, 0x3b, 0x00, 0xf6, 0xc8, 0x9b, 0xb8, 0xa1, 0x15, 0xd8, 0x21, + 0x8e, 0x58, 0xce, 0x2c, 0x13, 0xa4, 0x6b, 0x87, 0xec, 0x16, 0x94, 0xc7, 0x2f, 0xac, 0xa0, 0xef, + 0x3b, 0xe3, 0x10, 0x89, 0xa7, 0x6c, 0x96, 0xc6, 0x2f, 0xba, 0xf8, 0xcd, 0xde, 0x87, 0x92, 0x37, + 0x09, 0xc7, 0x9e, 0xe3, 0x86, 0x92, 0x5e, 0xe6, 0x65, 0x43, 0x0e, 0x26, 0xe1, 0xa1, 0x00, 0x9b, + 0x11, 0x02, 0x7b, 0x1b, 0x6a, 0x7d, 0xcf, 0x3d, 0x71, 0xfc, 0x11, 0x71, 0x84, 0xe6, 0x1c, 0xd6, + 0x95, 0x04, 0x1a, 0x7f, 0x90, 0x85, 0x4a, 0xcf, 0xb7, 0xdd, 0xc0, 0xee, 0x0b, 0x00, 0x5b, 0x85, + 0x62, 0x78, 0x69, 0x9d, 0xd9, 0xc1, 0x19, 0x76, 0xb5, 0x6c, 0xce, 0x85, 0x97, 0x3b, 0x76, 0x70, + 0xc6, 0x56, 0x60, 0x8e, 0x5a, 0x89, 0x1d, 0xca, 0x99, 0xf2, 0x4b, 0x2c, 0x10, 0x77, 0x32, 0xb2, + 0x92, 0x55, 0xe5, 0x90, 0x62, 0x1a, 0xee, 0x64, 0xb4, 0xa9, 0xc3, 0x45, 0xe7, 0x8f, 0xc5, 0x74, + 0x53, 0x05, 0xd4, 0xbd, 0x32, 0x42, 0xb0, 0x8e, 0x37, 0xa1, 0x2a, 0x93, 0xb9, 0x73, 0x7a, 0x46, + 0x7d, 0x2c, 0x98, 0x15, 0x42, 0x40, 0x90, 0x28, 0x21, 0x74, 0x46, 0xdc, 0x0a, 0x42, 0x7b, 0x34, + 0x96, 0x5d, 0x2a, 0x0b, 0x48, 0x57, 0x00, 0x30, 0xd9, 0x0b, 0xed, 0xa1, 0x75, 0xc2, 0x79, 0xd0, + 0x2c, 0xca, 0x64, 0x01, 0xd9, 0xe6, 0x3c, 0x60, 0x5f, 0x83, 0xfa, 0x80, 0x07, 0xa1, 0x25, 0x27, + 0x83, 0x07, 0xcd, 0x12, 0xae, 0xfc, 0x9a, 0x80, 0xb6, 0x14, 0x90, 0xdd, 0x06, 0xf0, 0xed, 0x0b, + 0x4b, 0x0c, 0x04, 0xbf, 0x6c, 0x96, 0x69, 0x16, 0x7c, 0xfb, 0xa2, 0x77, 0xb9, 0xc3, 0x2f, 0x05, + 0xd5, 0x3c, 0xe5, 0xa1, 0x36, 0x68, 0x81, 0xa4, 0x4e, 0x63, 0x17, 0x98, 0x06, 0xde, 0xe2, 0xa1, + 0xed, 0x0c, 0x03, 0xf6, 0x21, 0x54, 0x43, 0x0d, 0x19, 0xd9, 0x60, 0x25, 0x22, 0x21, 0x2d, 0x83, + 0x99, 0xc0, 0x33, 0xce, 0xa0, 0xb4, 0xcd, 0xf9, 0xae, 0x33, 0x72, 0x42, 0xb6, 0x02, 0x85, 0x13, + 0xe7, 0x92, 0x13, 0xb1, 0xe7, 0x76, 0x6e, 0x98, 0xf4, 0xc9, 0xee, 0x02, 0xe0, 0x0f, 0x6b, 0x14, + 0x51, 0xd3, 0xce, 0x0d, 0xb3, 0x8c, 0xb0, 0xbd, 0xc0, 0x0e, 0xd9, 0x1a, 0x14, 0xc7, 0xdc, 0xef, + 0x73, 0x35, 0x6f, 0x3b, 0x37, 0x4c, 0x05, 0xd8, 0x28, 0x42, 0x61, 0x28, 0x4a, 0x37, 0xfe, 0xb8, + 0x00, 0x95, 0x2e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, 0xcd, 0xde, + 0x82, 0x0a, 0x0e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x91, 0x6d, 0x66, 0x4c, 0x10, + 0xe0, 0x2e, 0x42, 0x59, 0x03, 0x72, 0xf6, 0x48, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x42, 0xc9, 0x1e, + 0x85, 0xd4, 0xbc, 0x2a, 0x82, 0x8b, 0xf6, 0x28, 0xc4, 0xa6, 0xbd, 0x09, 0xd5, 0xb1, 0x7d, 0x35, + 0x12, 0x6b, 0x39, 0x22, 0x87, 0xaa, 0x59, 0x91, 0x30, 0x24, 0x88, 0xc7, 0xb0, 0xa8, 0xa3, 0xa8, + 0xca, 0x0b, 0x51, 0xe5, 0x0b, 0x1a, 0xb6, 0x6c, 0xc3, 0xbb, 0x30, 0xaf, 0xf2, 0xf8, 0xd4, 0x1f, + 0x24, 0x93, 0xb2, 0x59, 0x97, 0x60, 0xd5, 0xcb, 0xfb, 0xd0, 0x38, 0x71, 0x5c, 0x7b, 0x68, 0xf5, + 0x87, 0xe1, 0xb9, 0x35, 0xe0, 0xc3, 0xd0, 0x46, 0x8a, 0x29, 0x98, 0x75, 0x84, 0x6f, 0x0e, 0xc3, + 0xf3, 0x2d, 0x01, 0x65, 0x5f, 0x87, 0xf2, 0x09, 0xe7, 0x16, 0x0e, 0x56, 0xb3, 0x94, 0x58, 0x78, + 0x6a, 0x86, 0xcc, 0xd2, 0x89, 0x9a, 0xab, 0xaf, 0x43, 0xc3, 0x9b, 0x84, 0xa7, 0x9e, 0xe3, 0x9e, + 0x5a, 0x82, 0xdf, 0x59, 0xce, 0x00, 0x69, 0x28, 0xbf, 0x91, 0x7d, 0x94, 0x31, 0xeb, 0x2a, 0x4d, + 0x70, 0x9e, 0xce, 0x80, 0xbd, 0x03, 0xf3, 0x43, 0x3b, 0x08, 0xad, 0x33, 0x6f, 0x6c, 0x8d, 0x27, + 0xc7, 0x2f, 0xf8, 0x55, 0xb3, 0x86, 0x03, 0x51, 0x13, 0xe0, 0x1d, 0x6f, 0x7c, 0x88, 0x40, 0x41, + 0xd9, 0xd8, 0x4e, 0x6a, 0x04, 0xdc, 0xcb, 0xdc, 0xaf, 0x99, 0x65, 0x01, 0xa1, 0x4a, 0x9f, 0xc3, + 0x22, 0x4e, 0x4f, 0x7f, 0x12, 0x84, 0xde, 0xc8, 0x12, 0xbc, 0xda, 0x1f, 0x04, 0xcd, 0x0a, 0xd2, + 0xda, 0x7b, 0xb2, 0xb1, 0xda, 0x1c, 0xaf, 0x6f, 0xf1, 0x20, 0xdc, 0x44, 0x64, 0x93, 0x70, 0xc5, + 0x86, 0x7e, 0x65, 0x2e, 0x0c, 0xa6, 0xe1, 0xec, 0xeb, 0xc0, 0xec, 0xe1, 0xd0, 0xbb, 0xb0, 0x02, + 0x3e, 0x3c, 0xb1, 0xe4, 0x20, 0x36, 0xeb, 0xf7, 0x32, 0xf7, 0x4b, 0x66, 0x03, 0x53, 0xba, 0x7c, + 0x78, 0x72, 0x48, 0x70, 0xf6, 0x21, 0xe0, 0x62, 0xb2, 0x4e, 0xb8, 0x1d, 0x4e, 0x7c, 0x1e, 0x34, + 0xe7, 0xef, 0xe5, 0xee, 0xd7, 0x1f, 0x2f, 0x44, 0xe3, 0x85, 0xe0, 0x0d, 0x27, 0x34, 0xab, 0x02, + 0x4f, 0x7e, 0x07, 0x6b, 0x5b, 0xb0, 0x92, 0xde, 0x24, 0x41, 0x54, 0x62, 0x54, 0x04, 0x31, 0xe6, + 0x4d, 0xf1, 0x93, 0x2d, 0x41, 0xe1, 0xdc, 0x1e, 0x4e, 0xb8, 0xe4, 0xe9, 0xf4, 0xf1, 0x71, 0xf6, + 0xdb, 0x19, 0xe3, 0x8f, 0x32, 0x50, 0xa5, 0x5e, 0x4a, 0x59, 0xe4, 0x2d, 0xa8, 0x29, 0x6a, 0xe0, + 0xbe, 0xef, 0xf9, 0x92, 0xab, 0x29, 0xca, 0x6b, 0x0b, 0x98, 0xd8, 0x55, 0x14, 0xd2, 0xd8, 0xe7, + 0xce, 0xc8, 0x3e, 0x55, 0x45, 0x2b, 0x52, 0x3a, 0x94, 0x60, 0xf6, 0x41, 0x5c, 0x9e, 0xef, 0x4d, + 0x42, 0x2e, 0xf7, 0xbc, 0xaa, 0xec, 0x9e, 0x29, 0x60, 0x51, 0xe9, 0xf8, 0xf5, 0x1a, 0x74, 0x6e, + 0xfc, 0x56, 0x06, 0x98, 0x68, 0x76, 0xcf, 0xa3, 0x02, 0x24, 0x85, 0x4e, 0xe7, 0xcc, 0xbc, 0xf6, + 0x0a, 0xc9, 0xbe, 0x6c, 0x85, 0x18, 0x50, 0xa0, 0xb6, 0xe7, 0x53, 0xda, 0x4e, 0x49, 0xdf, 0xcf, + 0x97, 0x72, 0x8d, 0xbc, 0xf1, 0x5f, 0x72, 0xb0, 0xb4, 0x49, 0x5b, 0x76, 0xab, 0xdf, 0xe7, 0xe3, + 0x68, 0xed, 0xdc, 0x85, 0x8a, 0xeb, 0x0d, 0xb8, 0xa2, 0x58, 0x6a, 0x18, 0x08, 0x90, 0x46, 0xae, + 0x67, 0xb6, 0xe3, 0x52, 0xc3, 0x69, 0x30, 0xcb, 0x08, 0xc1, 0x66, 0xbf, 0x03, 0xf3, 0x63, 0xee, + 0x0e, 0xf4, 0x25, 0x42, 0x42, 0x55, 0x4d, 0x82, 0xe5, 0xea, 0xb8, 0x0b, 0x95, 0x93, 0x09, 0xe1, + 0x09, 0xc6, 0x92, 0x47, 0x1a, 0x00, 0x09, 0x6a, 0x11, 0x7f, 0x19, 0x4f, 0x82, 0x33, 0x4c, 0x2d, + 0x60, 0x6a, 0x51, 0x7c, 0x8b, 0xa4, 0x3b, 0x00, 0x83, 0x49, 0x10, 0xca, 0x15, 0x33, 0x87, 0x89, + 0x65, 0x01, 0xa1, 0x15, 0xf3, 0x0d, 0x58, 0x1c, 0xd9, 0x97, 0x16, 0xd2, 0x8e, 0xe5, 0xb8, 0xd6, + 0xc9, 0x10, 0xf7, 0x9c, 0x22, 0xe2, 0x35, 0x46, 0xf6, 0xe5, 0x67, 0x22, 0xa5, 0xe3, 0x6e, 0x23, + 0x5c, 0xb0, 0x15, 0x25, 0xee, 0xf8, 0x3c, 0xe0, 0xfe, 0x39, 0x47, 0x4e, 0x90, 0x8f, 0x64, 0x1a, + 0x93, 0xa0, 0xa2, 0x45, 0x23, 0xd1, 0xef, 0x70, 0xd8, 0xa7, 0x65, 0x6f, 0x16, 0x47, 0x8e, 0xbb, + 0x13, 0x0e, 0xfb, 0x62, 0x5f, 0x11, 0x7c, 0x64, 0xcc, 0x7d, 0xeb, 0xc5, 0x05, 0xae, 0xe1, 0x3c, + 0xf2, 0x8d, 0x43, 0xee, 0x3f, 0xbb, 0x10, 0x5b, 0x7f, 0x3f, 0x40, 0x46, 0x64, 0x5f, 0x35, 0x2b, + 0xb8, 0xc0, 0x4b, 0xfd, 0x40, 0xb0, 0x20, 0xfb, 0x4a, 0x2c, 0x42, 0xd1, 0x5a, 0x1b, 0x67, 0x81, + 0x0f, 0xb0, 0xf8, 0x00, 0x39, 0x6a, 0x0d, 0x1b, 0xdb, 0x92, 0x09, 0xa2, 0x9e, 0x40, 0x50, 0xbd, + 0x6a, 0xec, 0xc9, 0xd0, 0x3e, 0x0d, 0x90, 0xa5, 0xd4, 0xcc, 0xaa, 0x04, 0x6e, 0x0b, 0x98, 0xf1, + 0x39, 0x09, 0x59, 0xda, 0xdc, 0xca, 0x35, 0x23, 0xb6, 0x7a, 0x84, 0xe0, 0xbc, 0x96, 0x4c, 0xf9, + 0x95, 0x36, 0x69, 0xd9, 0x94, 0x49, 0x33, 0x7e, 0x37, 0x03, 0x55, 0x59, 0x32, 0x0a, 0x25, 0x6c, + 0x1d, 0x98, 0x9a, 0xc5, 0xf0, 0xd2, 0x19, 0x58, 0xc7, 0x57, 0x21, 0x0f, 0x88, 0x68, 0x76, 0x6e, + 0x98, 0x0d, 0x99, 0xd6, 0xbb, 0x74, 0x06, 0x1b, 0x22, 0x85, 0x3d, 0x80, 0x46, 0x02, 0x3f, 0x08, + 0x7d, 0xa2, 0xe8, 0x9d, 0x1b, 0x66, 0x5d, 0xc3, 0xee, 0x86, 0xbe, 0x58, 0x23, 0x42, 0xe4, 0x99, + 0x84, 0x96, 0xe3, 0x0e, 0xf8, 0x25, 0x92, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x23, 0x40, 0x1b, 0x75, + 0xa8, 0xea, 0xc5, 0x19, 0xa7, 0x50, 0x52, 0xf2, 0x12, 0x0a, 0x0c, 0x53, 0x4d, 0x32, 0xcb, 0x61, + 0xd4, 0x92, 0x9b, 0x50, 0x4a, 0xb6, 0xc0, 0x2c, 0x86, 0xaf, 0x5d, 0xb1, 0xf1, 0x5d, 0x68, 0xec, + 0x0a, 0xe2, 0x71, 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x05, 0xe6, 0xb4, 0x45, 0x53, 0x36, 0xe5, 0x97, + 0xd8, 0x73, 0xcf, 0xbc, 0x20, 0x94, 0xb5, 0xe0, 0x6f, 0xe3, 0x8f, 0x33, 0xc0, 0xda, 0x41, 0xe8, + 0x8c, 0xec, 0x90, 0x6f, 0xf3, 0x88, 0x2d, 0x1c, 0x40, 0x55, 0x94, 0xd6, 0xf3, 0x5a, 0x24, 0x90, + 0x91, 0x40, 0xf1, 0xbe, 0x5c, 0xc6, 0xb3, 0x19, 0xd6, 0x75, 0x6c, 0x62, 0xf3, 0x89, 0x02, 0xc4, + 0x2a, 0x0b, 0x6d, 0xff, 0x94, 0x87, 0x28, 0xc6, 0x49, 0x79, 0x1f, 0x08, 0x24, 0x04, 0xb8, 0xb5, + 0x5f, 0x84, 0x85, 0x99, 0x32, 0x74, 0xbe, 0x5c, 0x4e, 0xe1, 0xcb, 0x39, 0x9d, 0x2f, 0x5b, 0xb0, + 0x98, 0x68, 0x97, 0xa4, 0xb4, 0x55, 0x28, 0x8a, 0x05, 0x21, 0x84, 0x83, 0x0c, 0x49, 0x95, 0x27, + 0x9c, 0x0b, 0x31, 0xf8, 0x21, 0x2c, 0x9d, 0x70, 0xee, 0xdb, 0x21, 0x26, 0xe2, 0x8a, 0x11, 0x33, + 0x24, 0x0b, 0x5e, 0x90, 0x69, 0x5d, 0x3b, 0x3c, 0xe4, 0xbe, 0x98, 0x29, 0xe3, 0xbf, 0x65, 0x60, + 0x5e, 0x70, 0xd0, 0x3d, 0xdb, 0xbd, 0x52, 0xe3, 0xb4, 0x9b, 0x3a, 0x4e, 0xf7, 0xb5, 0xcd, 0x50, + 0xc3, 0xfe, 0xaa, 0x83, 0x94, 0x9b, 0x1e, 0x24, 0x76, 0x0f, 0xaa, 0x89, 0xb6, 0x16, 0xb0, 0xad, + 0x10, 0x44, 0x8d, 0xfc, 0xe9, 0x87, 0xf1, 0x1d, 0x68, 0xc4, 0xcd, 0x96, 0x63, 0xc8, 0x20, 0x2f, + 0x48, 0x52, 0x16, 0x80, 0xbf, 0x8d, 0xdf, 0xc9, 0x10, 0xe2, 0xa6, 0xe7, 0x44, 0xd2, 0xa9, 0x40, + 0x14, 0x72, 0xaf, 0x42, 0x14, 0xbf, 0xaf, 0x95, 0xea, 0x7f, 0xfa, 0xce, 0x8a, 0xa5, 0x13, 0x70, + 0x77, 0x60, 0xd9, 0xc3, 0x21, 0x32, 0xdf, 0x92, 0x59, 0x14, 0xdf, 0xad, 0xe1, 0xd0, 0x78, 0x17, + 0x16, 0xb4, 0xd6, 0xbd, 0xa4, 0x1f, 0xfb, 0xc0, 0x76, 0x9d, 0x20, 0x3c, 0x72, 0x83, 0xb1, 0x26, + 0xb8, 0xdd, 0x82, 0xb2, 0xe0, 0xb0, 0xa2, 0x65, 0xb4, 0x64, 0x0b, 0xa6, 0x60, 0xb9, 0xa2, 0x5d, + 0x01, 0x26, 0xda, 0x97, 0x32, 0x31, 0x2b, 0x13, 0xed, 0x4b, 0x4c, 0x34, 0xbe, 0x0d, 0x8b, 0x89, + 0xf2, 0x64, 0xd5, 0x6f, 0x42, 0x61, 0x12, 0x5e, 0x7a, 0x4a, 0x34, 0xaf, 0x48, 0x0a, 0x11, 0x0a, + 0xa0, 0x49, 0x29, 0xc6, 0x27, 0xb0, 0xb0, 0xcf, 0x2f, 0xe4, 0x22, 0x56, 0x0d, 0x79, 0x07, 0xf2, + 0xaf, 0x50, 0x0a, 0x31, 0xdd, 0x58, 0x07, 0xa6, 0x67, 0x96, 0xb5, 0x6a, 0x3a, 0x62, 0x26, 0xa1, + 0x23, 0x1a, 0xef, 0x00, 0xeb, 0x3a, 0xa7, 0xee, 0x1e, 0x0f, 0x02, 0xfb, 0x34, 0x5a, 0xf6, 0x0d, + 0xc8, 0x8d, 0x82, 0x53, 0xc9, 0xa3, 0xc4, 0x4f, 0xe3, 0x9b, 0xb0, 0x98, 0xc0, 0x93, 0x05, 0xdf, + 0x86, 0x72, 0xe0, 0x9c, 0xba, 0x28, 0x58, 0xc9, 0xa2, 0x63, 0x80, 0xb1, 0x0d, 0x4b, 0x9f, 0x71, + 0xdf, 0x39, 0xb9, 0x7a, 0x55, 0xf1, 0xc9, 0x72, 0xb2, 0xd3, 0xe5, 0xb4, 0x61, 0x79, 0xaa, 0x1c, + 0x59, 0x3d, 0x91, 0xaf, 0x9c, 0xc9, 0x92, 0x49, 0x1f, 0x1a, 0xdf, 0xcb, 0xea, 0x7c, 0xcf, 0x38, + 0x02, 0xb6, 0xe9, 0xb9, 0x2e, 0xef, 0x87, 0x87, 0x9c, 0xfb, 0xb1, 0x95, 0x2a, 0xa6, 0xd5, 0xca, + 0xe3, 0x55, 0x39, 0xb2, 0xd3, 0xcc, 0x54, 0x12, 0x31, 0x83, 0xfc, 0x98, 0xfb, 0x23, 0x2c, 0xb8, + 0x64, 0xe2, 0x6f, 0x63, 0x19, 0x16, 0x13, 0xc5, 0x4a, 0xbd, 0xfe, 0x11, 0x2c, 0x6f, 0x39, 0x41, + 0x7f, 0xb6, 0xc2, 0x55, 0x28, 0x8e, 0x27, 0xc7, 0x56, 0x92, 0x2f, 0x3f, 0xe3, 0x57, 0x42, 0xdb, + 0x9b, 0xce, 0x21, 0xcb, 0xfa, 0xab, 0x19, 0xc8, 0xef, 0xf4, 0x76, 0x37, 0xd9, 0x1a, 0x94, 0x1c, + 0xb7, 0xef, 0x8d, 0x84, 0xe0, 0x45, 0x7d, 0x8e, 0xbe, 0xaf, 0x5d, 0x60, 0xb7, 0xa0, 0x8c, 0xf2, + 0x9a, 0x50, 0x6d, 0xa5, 0xe8, 0x53, 0x12, 0x80, 0x5d, 0xaf, 0xff, 0x42, 0xe8, 0xd4, 0xfc, 0x72, + 0xec, 0xf8, 0xa8, 0x35, 0x2b, 0x65, 0x38, 0x4f, 0x7b, 0x7d, 0x9c, 0x40, 0x1a, 0xb1, 0xf1, 0xaf, + 0x4b, 0x50, 0x94, 0xbb, 0x2d, 0xed, 0xdc, 0xa1, 0x73, 0xce, 0xe3, 0x9d, 0x5b, 0x7c, 0x09, 0x79, + 0xc0, 0xe7, 0x23, 0x2f, 0x8c, 0x04, 0x36, 0x9a, 0x83, 0x2a, 0x01, 0xa5, 0xc8, 0xa6, 0x09, 0x0d, + 0x64, 0x62, 0xc8, 0x11, 0x52, 0x5f, 0xdf, 0xca, 0x6f, 0x41, 0x51, 0xed, 0xfd, 0xf9, 0x48, 0xa7, + 0x99, 0xeb, 0x93, 0xb4, 0xb6, 0x06, 0xa5, 0xbe, 0x3d, 0xb6, 0xfb, 0x4e, 0x78, 0x25, 0x19, 0x42, + 0xf4, 0x2d, 0x4a, 0x1f, 0x7a, 0x7d, 0x7b, 0x68, 0x1d, 0xdb, 0x43, 0xdb, 0xed, 0x73, 0xa9, 0xbb, + 0x57, 0x11, 0xb8, 0x41, 0x30, 0xa1, 0x9f, 0xcb, 0x76, 0x2a, 0x2c, 0x52, 0xe1, 0x65, 0xeb, 0x15, + 0x9a, 0x10, 0x2e, 0xbd, 0xd1, 0xc8, 0x11, 0x5a, 0x06, 0x89, 0x61, 0x39, 0xb3, 0x4c, 0x90, 0x6d, + 0x8e, 0xbd, 0x95, 0xc9, 0x17, 0x34, 0x74, 0x65, 0xaa, 0x8a, 0x80, 0x9f, 0x93, 0x21, 0x61, 0x56, + 0x16, 0xcb, 0x69, 0xb2, 0xd8, 0xfb, 0xb0, 0x30, 0x71, 0x03, 0x1e, 0x86, 0x43, 0x3e, 0x88, 0xda, + 0x52, 0x41, 0xa4, 0x46, 0x94, 0xa0, 0x9a, 0xb3, 0x0e, 0x8b, 0x64, 0x74, 0x08, 0xec, 0xd0, 0x0b, + 0xce, 0x9c, 0xc0, 0x0a, 0x84, 0x86, 0x44, 0xea, 0xee, 0x02, 0x26, 0x75, 0x65, 0x4a, 0x97, 0x54, + 0xa4, 0xd5, 0x29, 0x7c, 0x9f, 0xf7, 0xb9, 0x73, 0xce, 0x07, 0x28, 0xa7, 0xe5, 0xcc, 0xe5, 0x44, + 0x1e, 0x53, 0x26, 0xa2, 0xd0, 0x3d, 0x19, 0x59, 0x93, 0xf1, 0xc0, 0x16, 0xc2, 0x4a, 0x9d, 0x84, + 0x61, 0x77, 0x32, 0x3a, 0x22, 0x08, 0x7b, 0x04, 0x4a, 0x12, 0x93, 0xf2, 0xe1, 0x7c, 0x82, 0x9f, + 0x09, 0x62, 0x35, 0xab, 0x12, 0x83, 0x04, 0xc5, 0x84, 0xcc, 0xd9, 0x98, 0x92, 0x39, 0x9b, 0x50, + 0x1c, 0xfb, 0xce, 0xb9, 0x1d, 0xf2, 0xe6, 0x02, 0x31, 0x70, 0xf9, 0x29, 0x38, 0x83, 0xe3, 0x3a, + 0xa1, 0x63, 0x87, 0x9e, 0xdf, 0x64, 0x98, 0x16, 0x03, 0xd8, 0x03, 0x58, 0x40, 0x1a, 0x09, 0x42, + 0x3b, 0x9c, 0x04, 0x52, 0x02, 0x5d, 0x44, 0x62, 0x42, 0x19, 0xba, 0x8b, 0x70, 0x14, 0x42, 0xd9, + 0x37, 0x61, 0x85, 0xc8, 0x02, 0x73, 0x48, 0xc9, 0x1a, 0x05, 0x82, 0x25, 0x1c, 0x8a, 0x45, 0x4c, + 0x15, 0xf4, 0x2d, 0xe5, 0x6b, 0x21, 0x1d, 0x3c, 0x81, 0x55, 0x49, 0x26, 0x33, 0xb9, 0x96, 0x31, + 0xd7, 0x12, 0x25, 0x4f, 0x65, 0x5b, 0x87, 0x05, 0xd1, 0x24, 0xa7, 0x6f, 0xc9, 0xdc, 0x62, 0x25, + 0xac, 0x88, 0xd6, 0xa3, 0xa6, 0x34, 0x4f, 0x89, 0x26, 0xa6, 0x3d, 0xe3, 0x57, 0xec, 0xbb, 0x30, + 0x4f, 0x24, 0x83, 0xea, 0x15, 0x72, 0xfa, 0x35, 0xe4, 0xf4, 0xcb, 0xca, 0xc2, 0x19, 0xa5, 0x22, + 0xb3, 0xaf, 0xf7, 0x13, 0xdf, 0x62, 0x39, 0x0c, 0x9d, 0x13, 0x1e, 0x3a, 0x23, 0xde, 0x5c, 0x25, + 0x02, 0x53, 0xdf, 0x62, 0xa5, 0x4e, 0xc6, 0x98, 0xd2, 0x24, 0xbe, 0x40, 0x5f, 0x48, 0xbb, 0x43, + 0x2f, 0xe0, 0xca, 0x44, 0xd5, 0xbc, 0x29, 0x17, 0xa1, 0x00, 0x2a, 0x19, 0x52, 0x08, 0xe2, 0xa4, + 0xf4, 0x44, 0x86, 0xc4, 0x5b, 0x48, 0x0c, 0x35, 0xd2, 0x7d, 0x94, 0x31, 0x51, 0xec, 0xe2, 0x67, + 0xf6, 0x85, 0xe2, 0x20, 0xb7, 0x71, 0x7e, 0x41, 0x80, 0x24, 0xef, 0xf8, 0xc3, 0x0c, 0x6d, 0x88, + 0x92, 0x7f, 0x04, 0x9a, 0x7a, 0x47, 0x9c, 0xc3, 0xf2, 0xdc, 0xe1, 0x95, 0x64, 0x26, 0x40, 0xa0, + 0x03, 0x77, 0x88, 0xab, 0xd9, 0x71, 0x75, 0x14, 0xe2, 0xbd, 0x55, 0x05, 0x44, 0xa4, 0xbb, 0x50, + 0x19, 0x4f, 0x8e, 0x87, 0x4e, 0x9f, 0x50, 0x72, 0x54, 0x0a, 0x81, 0x10, 0x41, 0xe8, 0xb7, 0x44, + 0x51, 0x84, 0x91, 0x47, 0x8c, 0x8a, 0x84, 0x21, 0x0a, 0xf2, 0x76, 0xee, 0x23, 0x3b, 0xa9, 0x9a, + 0xf8, 0xdb, 0xd8, 0x80, 0xa5, 0x64, 0xa3, 0xe5, 0xc6, 0xf3, 0x00, 0x4a, 0x92, 0x57, 0x29, 0xc3, + 0x47, 0x5d, 0x33, 0x45, 0x0b, 0x15, 0x2d, 0x4a, 0x37, 0x7e, 0xaf, 0x00, 0x8b, 0x12, 0xba, 0x29, + 0x86, 0xb6, 0x3b, 0x19, 0x8d, 0x6c, 0x3f, 0x85, 0x09, 0x66, 0x5e, 0xce, 0x04, 0xb3, 0x33, 0x4c, + 0x30, 0xa9, 0xf9, 0x12, 0x0f, 0x4d, 0x6a, 0xbe, 0x62, 0x2e, 0x49, 0x19, 0xd1, 0xed, 0xa0, 0x35, + 0x09, 0xee, 0x91, 0xbd, 0x75, 0x86, 0x65, 0x17, 0x52, 0x58, 0xb6, 0xce, 0x70, 0xe7, 0xa6, 0x18, + 0xee, 0x9b, 0x40, 0x44, 0xa3, 0x66, 0xbf, 0x48, 0xfa, 0x09, 0xc2, 0xa4, 0x31, 0xf5, 0x5d, 0x98, + 0x9f, 0xe6, 0x71, 0xc4, 0x4c, 0xeb, 0x29, 0x1c, 0xce, 0x19, 0x71, 0xdc, 0xad, 0x34, 0xe4, 0xb2, + 0xe4, 0x70, 0xce, 0x88, 0xef, 0x62, 0x8a, 0xc2, 0x6f, 0x03, 0x50, 0xdd, 0xb8, 0x68, 0x00, 0x17, + 0xcd, 0x3b, 0xc9, 0xb9, 0xd0, 0x47, 0x7d, 0x5d, 0x7c, 0x4c, 0x7c, 0x8e, 0xab, 0xa8, 0x8c, 0x39, + 0x71, 0x01, 0x7d, 0x04, 0x75, 0x6f, 0xcc, 0x5d, 0x2b, 0xe6, 0x35, 0x15, 0x2c, 0xaa, 0x21, 0x8b, + 0xea, 0x28, 0xb8, 0x59, 0x13, 0x78, 0xd1, 0x27, 0xfb, 0x0e, 0x0d, 0x32, 0xd7, 0x72, 0x56, 0xaf, + 0xc9, 0x59, 0x47, 0xc4, 0xe8, 0xdb, 0xf8, 0x1b, 0x19, 0xa8, 0x68, 0xcd, 0x61, 0xcb, 0xb0, 0xb0, + 0x79, 0x70, 0x70, 0xd8, 0x36, 0x5b, 0xbd, 0xce, 0x67, 0x6d, 0x6b, 0x73, 0xf7, 0xa0, 0xdb, 0x6e, + 0xdc, 0x10, 0xe0, 0xdd, 0x83, 0xcd, 0xd6, 0xae, 0xb5, 0x7d, 0x60, 0x6e, 0x2a, 0x70, 0x86, 0xad, + 0x00, 0x33, 0xdb, 0x7b, 0x07, 0xbd, 0x76, 0x02, 0x9e, 0x65, 0x0d, 0xa8, 0x6e, 0x98, 0xed, 0xd6, + 0xe6, 0x8e, 0x84, 0xe4, 0xd8, 0x12, 0x34, 0xb6, 0x8f, 0xf6, 0xb7, 0x3a, 0xfb, 0x4f, 0xad, 0xcd, + 0xd6, 0xfe, 0x66, 0x7b, 0xb7, 0xbd, 0xd5, 0xc8, 0xb3, 0x1a, 0x94, 0x5b, 0x1b, 0xad, 0xfd, 0xad, + 0x83, 0xfd, 0xf6, 0x56, 0xa3, 0x60, 0xfc, 0x79, 0x06, 0x96, 0x71, 0xa0, 0x06, 0xd3, 0x2b, 0xf4, + 0x1e, 0x54, 0xfa, 0x9e, 0x37, 0x16, 0x6a, 0x50, 0xbc, 0xdd, 0xeb, 0x20, 0xb1, 0xfa, 0x88, 0xb3, + 0x9e, 0x78, 0x7e, 0x9f, 0xcb, 0x05, 0x0a, 0x08, 0xda, 0x16, 0x10, 0x41, 0x20, 0x92, 0xc2, 0x08, + 0x83, 0xd6, 0x67, 0x85, 0x60, 0x84, 0xb2, 0x02, 0x73, 0xc7, 0x3e, 0xb7, 0xfb, 0x67, 0x72, 0x69, + 0xca, 0x2f, 0xf6, 0x5e, 0xac, 0xa0, 0xf7, 0xc5, 0x84, 0x0f, 0xf9, 0x00, 0xe9, 0xb3, 0x64, 0xce, + 0x4b, 0xf8, 0xa6, 0x04, 0x8b, 0xad, 0xc2, 0x3e, 0xb6, 0xdd, 0x81, 0xe7, 0xf2, 0x81, 0xd4, 0x03, + 0x62, 0x80, 0x71, 0x08, 0x2b, 0xd3, 0xfd, 0x93, 0x8b, 0xf9, 0x43, 0x6d, 0x31, 0x93, 0x58, 0xbe, + 0x76, 0x3d, 0x01, 0x69, 0x0b, 0xfb, 0x6f, 0xe5, 0x21, 0x2f, 0xc4, 0xb4, 0x6b, 0x25, 0x3a, 0x5d, + 0xee, 0xce, 0xcd, 0xf8, 0x66, 0xd0, 0x0e, 0x40, 0xfb, 0x37, 0x19, 0x9b, 0xca, 0x08, 0xc1, 0x7d, + 0x3b, 0x4a, 0xf6, 0x79, 0xff, 0x5c, 0x5a, 0x9b, 0x28, 0xd9, 0xe4, 0xfd, 0x73, 0x54, 0x78, 0xec, + 0x90, 0xf2, 0xd2, 0x62, 0x2c, 0x06, 0x76, 0x88, 0x39, 0x65, 0x12, 0xe6, 0x2b, 0x46, 0x49, 0x98, + 0xab, 0x09, 0x45, 0xc7, 0x3d, 0xf6, 0x26, 0xee, 0x00, 0xd7, 0x5e, 0xc9, 0x54, 0x9f, 0xe8, 0x0a, + 0x42, 0x36, 0x21, 0x76, 0x09, 0x5a, 0x6a, 0x25, 0x01, 0xe8, 0x89, 0x7d, 0xe2, 0x03, 0x28, 0x07, + 0x57, 0x6e, 0x5f, 0x5f, 0x60, 0x4b, 0x72, 0x7c, 0x44, 0xef, 0xd7, 0xbb, 0x57, 0x6e, 0x1f, 0x97, + 0x53, 0x29, 0x90, 0xbf, 0xd8, 0x13, 0x28, 0x45, 0x46, 0x59, 0x62, 0x8f, 0x37, 0xf5, 0x1c, 0xca, + 0x12, 0x4b, 0xba, 0x6f, 0x84, 0xca, 0x1e, 0xc2, 0x1c, 0x5a, 0x4e, 0x83, 0x66, 0x15, 0x33, 0x29, + 0x61, 0x5c, 0x34, 0x03, 0xbd, 0x30, 0x7c, 0x80, 0x56, 0x54, 0x53, 0xa2, 0xad, 0x3d, 0x83, 0x5a, + 0xa2, 0x2c, 0x5d, 0xc3, 0xad, 0x91, 0x86, 0xfb, 0xb6, 0xae, 0xe1, 0xc6, 0x6c, 0x5a, 0x66, 0xd3, + 0x35, 0xde, 0x5f, 0x84, 0x92, 0xea, 0x8a, 0x58, 0x44, 0x47, 0xfb, 0xcf, 0xf6, 0x0f, 0x3e, 0xdf, + 0xb7, 0xba, 0xcf, 0xf7, 0x37, 0x1b, 0x37, 0xd8, 0x3c, 0x54, 0x5a, 0x9b, 0xb8, 0x2e, 0x11, 0x90, + 0x11, 0x28, 0x87, 0xad, 0x6e, 0x37, 0x82, 0x64, 0x8d, 0x6d, 0x68, 0x4c, 0xb7, 0x54, 0xd0, 0x64, + 0xa8, 0x60, 0xd2, 0xae, 0x1c, 0x03, 0x84, 0xfe, 0x42, 0xa6, 0x62, 0x12, 0x92, 0xe9, 0xc3, 0x78, + 0x02, 0x0d, 0xb1, 0xe9, 0x88, 0xa1, 0x0a, 0x34, 0xfb, 0xec, 0x50, 0x08, 0x5e, 0xba, 0x6d, 0xb9, + 0x64, 0x56, 0x08, 0x86, 0x55, 0x19, 0x1f, 0xc2, 0x82, 0x96, 0x2d, 0xd6, 0x37, 0xc5, 0x46, 0x36, + 0xad, 0x6f, 0xa2, 0x76, 0x41, 0x29, 0xc6, 0x2a, 0x2c, 0x8b, 0xcf, 0xf6, 0x39, 0x77, 0xc3, 0xee, + 0xe4, 0x98, 0x1c, 0x82, 0x8e, 0xe7, 0x0a, 0xad, 0xa3, 0x1c, 0xa5, 0x5c, 0x4f, 0xe4, 0xeb, 0x52, + 0x35, 0xcd, 0x22, 0x69, 0xac, 0x69, 0x35, 0x60, 0xc6, 0x75, 0xfc, 0x9b, 0x50, 0x51, 0xcb, 0x11, + 0x48, 0x0c, 0xeb, 0x61, 0xbb, 0x6d, 0x5a, 0x07, 0xfb, 0xbb, 0x9d, 0x7d, 0xc1, 0xed, 0xc4, 0xb0, + 0x22, 0x60, 0x7b, 0x1b, 0x21, 0x19, 0xa3, 0x01, 0xf5, 0xa7, 0x3c, 0xec, 0xb8, 0x27, 0x9e, 0x72, + 0x7e, 0xfd, 0x45, 0x01, 0xe6, 0x23, 0x50, 0xac, 0xe2, 0x9e, 0x73, 0x3f, 0x70, 0x3c, 0x17, 0xa5, + 0xd5, 0xb2, 0xa9, 0x3e, 0xc5, 0xd6, 0xe3, 0x0c, 0xb8, 0x1b, 0x3a, 0xe1, 0x95, 0x95, 0xb0, 0x87, + 0xd5, 0x15, 0x58, 0x6e, 0x71, 0x4b, 0x50, 0xb0, 0x87, 0x8e, 0xad, 0xfc, 0xa8, 0xf4, 0x21, 0xa0, + 0x7d, 0x6f, 0xe8, 0xf9, 0x28, 0x98, 0x96, 0x4d, 0xfa, 0x60, 0x8f, 0x60, 0x49, 0x08, 0xc8, 0xba, + 0x91, 0x12, 0xf9, 0x07, 0x99, 0xe6, 0x98, 0x3b, 0x19, 0x1d, 0xc6, 0x86, 0x4a, 0x91, 0x22, 0x36, + 0x36, 0x91, 0x43, 0x4a, 0x32, 0x51, 0x06, 0xd2, 0xb5, 0x16, 0xdc, 0xc9, 0xa8, 0x85, 0x29, 0x11, + 0xfe, 0x63, 0x58, 0x16, 0xf8, 0x91, 0xec, 0x13, 0xe5, 0x98, 0xc7, 0x1c, 0xa2, 0xb0, 0x8e, 0x4c, + 0x8b, 0xf2, 0xdc, 0x82, 0x32, 0xb5, 0x4a, 0xcc, 0x78, 0x81, 0x64, 0x6c, 0x6c, 0x0a, 0xf7, 0x83, + 0x19, 0x97, 0xe7, 0x1c, 0xed, 0xd2, 0x53, 0x2e, 0x4f, 0xcd, 0x69, 0x5a, 0x9a, 0x76, 0x9a, 0x3e, + 0x86, 0xe5, 0x63, 0x41, 0x82, 0x67, 0xdc, 0x1e, 0x70, 0xdf, 0x8a, 0x09, 0x9b, 0x74, 0x89, 0x45, + 0x91, 0xb8, 0x83, 0x69, 0xd1, 0x3a, 0x10, 0x42, 0x88, 0x60, 0x0b, 0x7c, 0x60, 0x85, 0x9e, 0x85, + 0xb2, 0x09, 0x32, 0x98, 0x92, 0x59, 0x23, 0x70, 0xcf, 0xdb, 0x14, 0xc0, 0x24, 0xde, 0xa9, 0x6f, + 0x8f, 0xcf, 0xa4, 0xb4, 0x1f, 0xe1, 0x3d, 0x15, 0x40, 0x76, 0x1b, 0x8a, 0x82, 0xe4, 0x5d, 0x4e, + 0x9e, 0x29, 0x92, 0xa7, 0x15, 0x88, 0xbd, 0x0d, 0x73, 0x58, 0x47, 0xd0, 0x6c, 0x20, 0xbd, 0x57, + 0x63, 0x46, 0xee, 0xb8, 0xa6, 0x4c, 0x13, 0x92, 0xde, 0xc4, 0x77, 0x88, 0xcb, 0x94, 0x4d, 0xfc, + 0xcd, 0xbe, 0xa7, 0xb1, 0xac, 0x45, 0xcc, 0xfb, 0xb6, 0xcc, 0x3b, 0x45, 0x69, 0xd7, 0x71, 0xaf, + 0x9f, 0x29, 0x33, 0xfa, 0x7e, 0xbe, 0x54, 0x69, 0x54, 0x8d, 0x8f, 0xa0, 0x40, 0xa3, 0x23, 0x88, + 0x10, 0xc7, 0x2e, 0x23, 0x89, 0x10, 0xa1, 0x4d, 0x28, 0xba, 0x3c, 0xbc, 0xf0, 0xfc, 0x17, 0xca, + 0x62, 0x2c, 0x3f, 0x8d, 0x1f, 0xa1, 0xa9, 0x23, 0x72, 0x87, 0x93, 0xd6, 0x26, 0xc8, 0x83, 0xa6, + 0x37, 0x38, 0xb3, 0xa5, 0xf5, 0xa5, 0x84, 0x80, 0xee, 0x99, 0x3d, 0x43, 0x1e, 0xd9, 0x59, 0x8f, + 0xf8, 0xdb, 0x50, 0x57, 0x0e, 0xf8, 0xc0, 0x1a, 0xf2, 0x93, 0x50, 0x92, 0x7b, 0x55, 0x7a, 0xdf, + 0x83, 0x5d, 0x7e, 0x12, 0x1a, 0x7b, 0xb0, 0x20, 0x09, 0xf2, 0x60, 0xcc, 0x55, 0xd5, 0xdf, 0x4e, + 0x13, 0x76, 0x2b, 0x8f, 0x17, 0x93, 0x1b, 0x2d, 0x05, 0x16, 0x24, 0x24, 0x60, 0xe3, 0x53, 0x60, + 0xfa, 0x36, 0x2c, 0xcb, 0x93, 0x22, 0xa7, 0x32, 0xb4, 0x2b, 0x7f, 0x55, 0x24, 0xd8, 0x3a, 0x03, + 0x31, 0x3a, 0xc1, 0xa4, 0xdf, 0x57, 0x81, 0x11, 0x25, 0x53, 0x7d, 0x1a, 0x7f, 0x92, 0x81, 0x45, + 0x2c, 0x4c, 0x09, 0xeb, 0x92, 0xc9, 0xfe, 0xc4, 0x8d, 0x14, 0xf3, 0xa3, 0xcb, 0x3e, 0xf4, 0xf1, + 0xd5, 0x4d, 0x9b, 0xf9, 0x19, 0xd3, 0xe6, 0x7b, 0xd0, 0x18, 0xf0, 0xa1, 0x83, 0x31, 0x32, 0x4a, + 0x94, 0x20, 0xf1, 0x7c, 0x5e, 0xc1, 0xa5, 0xaa, 0x66, 0xfc, 0xbd, 0x0c, 0x2c, 0x90, 0xa4, 0x82, + 0x4a, 0xaf, 0x1c, 0xa8, 0x4f, 0x94, 0x96, 0x27, 0x59, 0x95, 0xec, 0x53, 0xbc, 0x83, 0x23, 0x94, + 0x90, 0x77, 0x6e, 0x48, 0xed, 0x4f, 0x42, 0xd9, 0xc7, 0xa8, 0x60, 0xb8, 0x16, 0x02, 0x53, 0x62, + 0x6e, 0x92, 0x93, 0xb2, 0x73, 0x03, 0xb5, 0x0f, 0x17, 0x41, 0x1b, 0x25, 0xa1, 0x76, 0x0a, 0xb0, + 0xb1, 0x0d, 0xb5, 0x44, 0x35, 0x09, 0xfb, 0x6b, 0x95, 0xec, 0xaf, 0x33, 0x3e, 0x8e, 0xec, 0xac, + 0x8f, 0xe3, 0x0a, 0x16, 0x4d, 0x6e, 0x0f, 0xae, 0xb6, 0x3d, 0xff, 0x30, 0x38, 0x0e, 0xb7, 0x49, + 0xfc, 0x13, 0xfc, 0x3d, 0x72, 0xdc, 0x25, 0x8c, 0x9c, 0xca, 0x7f, 0xa3, 0x74, 0xd9, 0xaf, 0x41, + 0x3d, 0xf6, 0xf0, 0x69, 0x86, 0xb2, 0x5a, 0xe4, 0xe4, 0x43, 0x7b, 0x99, 0xd0, 0x03, 0x83, 0xe3, + 0x50, 0x9a, 0xca, 0xf0, 0xb7, 0xf1, 0xd7, 0xf2, 0xc0, 0x04, 0x35, 0x4f, 0x11, 0xcc, 0x94, 0x6f, + 0x32, 0x3b, 0xe3, 0x9b, 0x7c, 0x04, 0x4c, 0x43, 0x50, 0x2e, 0xd3, 0x5c, 0xe4, 0x32, 0x6d, 0xc4, + 0xb8, 0xd2, 0x63, 0xfa, 0x08, 0x96, 0xa4, 0x2c, 0x9d, 0x6c, 0x2a, 0x91, 0x06, 0x23, 0xa1, 0x3a, + 0xd1, 0x5e, 0xe5, 0x97, 0x14, 0xba, 0x39, 0x99, 0xc2, 0xd0, 0x2f, 0xa9, 0xb4, 0x72, 0x8d, 0x00, + 0xe7, 0x5e, 0x49, 0x80, 0xc5, 0x19, 0x02, 0xd4, 0x2c, 0x33, 0xa5, 0xa4, 0x65, 0xc6, 0x80, 0x9a, + 0xf2, 0x3e, 0x52, 0xd0, 0x05, 0x09, 0x8e, 0x15, 0xe9, 0x82, 0xc4, 0xc0, 0x8b, 0xfb, 0xd0, 0x50, + 0xe6, 0x93, 0xc8, 0xf6, 0x43, 0x01, 0x05, 0xd2, 0xfa, 0xb6, 0xa9, 0x2c, 0x40, 0x09, 0x4b, 0x7b, + 0x65, 0xca, 0xd2, 0xfe, 0x3e, 0x2c, 0x04, 0x82, 0x7e, 0xad, 0x89, 0x2b, 0xa3, 0x7f, 0xf8, 0x00, + 0xd5, 0xac, 0x92, 0xd9, 0xc0, 0x84, 0xa3, 0x18, 0x3e, 0x6b, 0xd7, 0xa8, 0xa5, 0xd8, 0x35, 0x9e, + 0xc4, 0x8e, 0xba, 0xe0, 0xcc, 0x19, 0xa1, 0xcc, 0x10, 0x47, 0xca, 0xc8, 0x01, 0xee, 0x9e, 0x39, + 0x23, 0x53, 0x79, 0x85, 0xc5, 0x87, 0xf1, 0xbf, 0x33, 0xd0, 0x10, 0x74, 0x90, 0x58, 0x62, 0xdf, + 0x01, 0x64, 0x06, 0xaf, 0xb9, 0xc2, 0x2a, 0x02, 0x57, 0x2d, 0xb0, 0x8f, 0x00, 0x57, 0x8c, 0x25, + 0x74, 0x4a, 0xb9, 0xbe, 0x9a, 0xc9, 0xf5, 0x15, 0xf3, 0xd0, 0x9d, 0x1b, 0xa4, 0x7b, 0x08, 0x08, + 0xfb, 0x0e, 0x94, 0x05, 0x61, 0x22, 0x95, 0xc8, 0x00, 0x2d, 0x25, 0x79, 0xa5, 0xac, 0x11, 0x91, + 0x75, 0x2c, 0x3f, 0xd3, 0x7c, 0xab, 0xf9, 0x14, 0xdf, 0xaa, 0xb6, 0x80, 0x77, 0x00, 0x9e, 0xf1, + 0xab, 0x5d, 0xaf, 0x8f, 0x1a, 0xef, 0x1d, 0x00, 0x41, 0xcb, 0x27, 0xf6, 0xc8, 0x91, 0x06, 0x9b, + 0x82, 0x59, 0x7e, 0xc1, 0xaf, 0xb6, 0x11, 0x20, 0x26, 0x52, 0x24, 0xc7, 0xab, 0xb8, 0x60, 0x96, + 0x5e, 0xf0, 0x2b, 0x5a, 0xc2, 0x16, 0xd4, 0x9e, 0xf1, 0xab, 0x2d, 0x4e, 0x42, 0xa6, 0xe7, 0x0b, + 0x22, 0xf2, 0xed, 0x0b, 0x21, 0x55, 0x26, 0xfc, 0xa2, 0x15, 0xdf, 0xbe, 0x78, 0xc6, 0xaf, 0x94, + 0x8f, 0xb6, 0x28, 0xd2, 0x87, 0x5e, 0x5f, 0xee, 0x9b, 0x2a, 0xc2, 0x23, 0x6e, 0x94, 0x39, 0xf7, + 0x02, 0x7f, 0x1b, 0x7f, 0x99, 0x81, 0x9a, 0x68, 0x3f, 0xb2, 0x65, 0x31, 0x65, 0x2a, 0x50, 0x28, + 0x13, 0x07, 0x0a, 0x3d, 0x96, 0x5c, 0x8d, 0x78, 0x7c, 0xf6, 0x7a, 0x1e, 0x8f, 0x73, 0x43, 0x0c, + 0xfe, 0x03, 0x28, 0xd3, 0xb2, 0x14, 0xeb, 0x3c, 0x97, 0x98, 0xe0, 0x44, 0x87, 0xcc, 0x12, 0xa2, + 0x3d, 0xa3, 0xb8, 0x04, 0xcd, 0xf8, 0x47, 0x43, 0x5c, 0xf6, 0x23, 0x93, 0x5f, 0xca, 0x34, 0x14, + 0xae, 0x89, 0x4b, 0xd0, 0x2d, 0x6b, 0x73, 0x33, 0x96, 0xb5, 0x03, 0x28, 0x89, 0xa9, 0xc6, 0xce, + 0xa6, 0x14, 0x9a, 0x49, 0x2b, 0x54, 0x48, 0x02, 0xb6, 0xd8, 0x14, 0x04, 0xa3, 0xcb, 0x4a, 0x49, + 0xc0, 0x0e, 0xf8, 0x21, 0x32, 0xbb, 0x0c, 0x54, 0xb4, 0x15, 0x80, 0xc6, 0xc9, 0x68, 0xbc, 0x68, + 0xb9, 0x24, 0x49, 0x3c, 0x31, 0xe0, 0x3b, 0x37, 0xcc, 0x5a, 0x3f, 0x31, 0x03, 0xeb, 0x92, 0x56, + 0x31, 0x67, 0x36, 0x11, 0xd3, 0xa4, 0x1a, 0xae, 0x08, 0x54, 0xfc, 0xde, 0x98, 0x83, 0xbc, 0x40, + 0x35, 0x3e, 0x81, 0x05, 0xad, 0x19, 0xa4, 0xe6, 0xbf, 0x6e, 0x0f, 0x8d, 0x5f, 0x89, 0x32, 0x8b, + 0x3a, 0xc8, 0x7d, 0xa4, 0x62, 0x3c, 0xf8, 0x80, 0x3a, 0x2e, 0x63, 0x49, 0x08, 0x24, 0xd0, 0x5e, + 0x3b, 0xee, 0xe0, 0xd7, 0x60, 0x51, 0x2b, 0x7d, 0xdb, 0x71, 0xed, 0xa1, 0xf3, 0x23, 0xdc, 0xf0, + 0x03, 0xe7, 0xd4, 0x9d, 0x2a, 0x9f, 0x40, 0x5f, 0xa9, 0xfc, 0xbf, 0x9f, 0x85, 0x25, 0x59, 0x01, + 0x46, 0xed, 0x39, 0x42, 0x8a, 0xdb, 0x0b, 0x4e, 0xd9, 0x77, 0xa0, 0x26, 0xc6, 0xc6, 0xf2, 0xf9, + 0xa9, 0x13, 0x84, 0x5c, 0xb9, 0xad, 0x52, 0x18, 0x97, 0xd8, 0xcc, 0x05, 0xaa, 0x29, 0x31, 0xd9, + 0x27, 0x50, 0xc1, 0xac, 0x64, 0x46, 0x91, 0x13, 0xd1, 0x9c, 0xcd, 0x48, 0x03, 0xbd, 0x73, 0xc3, + 0x84, 0x20, 0x1e, 0xf6, 0x4f, 0xa0, 0x82, 0x73, 0x78, 0x8e, 0x03, 0x39, 0xc5, 0xaa, 0x66, 0x06, + 0x5a, 0x64, 0x1e, 0xc7, 0xc3, 0xde, 0x82, 0x1a, 0x31, 0x2b, 0x39, 0x4e, 0x32, 0x1a, 0x68, 0x6d, + 0x36, 0xbb, 0x1a, 0x49, 0xd1, 0xf8, 0xb1, 0xf6, 0xbd, 0x51, 0x86, 0x62, 0xe8, 0x3b, 0xa7, 0xa7, + 0xdc, 0x37, 0x56, 0xa2, 0xa1, 0x11, 0x5c, 0x98, 0x77, 0x43, 0x3e, 0x16, 0xb2, 0xb9, 0xf1, 0x6f, + 0x33, 0x50, 0x91, 0x7c, 0xf5, 0x27, 0xf6, 0x95, 0xad, 0x69, 0x61, 0xaf, 0x64, 0xb1, 0x89, 0xa3, + 0x5c, 0xdf, 0x85, 0xf9, 0x91, 0x90, 0xd3, 0x85, 0x1e, 0x99, 0x70, 0x94, 0xd5, 0x15, 0x58, 0x8a, + 0xc9, 0xeb, 0xb0, 0x88, 0x52, 0x73, 0x60, 0x85, 0xce, 0xd0, 0x52, 0x89, 0x32, 0xc4, 0x74, 0x81, + 0x92, 0x7a, 0xce, 0x70, 0x4f, 0x26, 0x08, 0xe1, 0x31, 0x08, 0xed, 0x53, 0x2e, 0xd7, 0x36, 0x7d, + 0x18, 0x4d, 0x58, 0x99, 0x52, 0x21, 0x95, 0xfa, 0xfb, 0x7f, 0x16, 0x60, 0x75, 0x26, 0x49, 0xaa, + 0xc1, 0x91, 0x83, 0x68, 0xe8, 0x8c, 0x8e, 0xbd, 0xc8, 0x7c, 0x9a, 0xd1, 0x1c, 0x44, 0xbb, 0x22, + 0x45, 0x99, 0x4f, 0x39, 0x2c, 0x2b, 0x82, 0x44, 0xfb, 0x67, 0xa4, 0x65, 0x66, 0x51, 0x07, 0xfa, + 0x20, 0xb9, 0x89, 0x4d, 0x57, 0xa7, 0xe0, 0xba, 0x68, 0xb4, 0x38, 0x9e, 0x81, 0x05, 0xec, 0xd7, + 0xa1, 0x19, 0xd1, 0xbd, 0x14, 0xdb, 0x35, 0x95, 0x59, 0xd4, 0xf4, 0xf5, 0x57, 0xd4, 0x94, 0xb0, + 0xdd, 0xa1, 0xec, 0xb4, 0xa2, 0x96, 0x0c, 0x15, 0x18, 0xd5, 0x75, 0x0e, 0x6f, 0xa8, 0xba, 0x50, + 0x0c, 0x9f, 0xad, 0x31, 0xff, 0x5a, 0x7d, 0x43, 0xbb, 0x64, 0xa2, 0x5a, 0xf3, 0x96, 0x2c, 0x38, + 0x4a, 0xd2, 0xeb, 0x3d, 0x83, 0x95, 0x0b, 0xdb, 0x09, 0x55, 0x1f, 0x35, 0x8d, 0xbd, 0x80, 0xf5, + 0x3d, 0x7e, 0x45, 0x7d, 0x9f, 0x53, 0xe6, 0x84, 0x62, 0xb2, 0x74, 0x31, 0x0b, 0x0c, 0xd6, 0xfe, + 0x71, 0x0e, 0xea, 0xc9, 0x52, 0x04, 0x63, 0x91, 0x9b, 0x8d, 0x92, 0x37, 0xa5, 0x10, 0x2c, 0x4d, + 0xfb, 0xfb, 0x24, 0x67, 0xce, 0x3a, 0x1d, 0xb2, 0x29, 0x4e, 0x07, 0xdd, 0xd6, 0x9f, 0x7b, 0x95, + 0x73, 0x35, 0xff, 0x5a, 0xce, 0xd5, 0x42, 0x9a, 0x73, 0xf5, 0x7a, 0x8f, 0xdc, 0xdc, 0x4f, 0xe4, + 0x91, 0x2b, 0xbe, 0xd4, 0x23, 0xa7, 0xf9, 0x11, 0x4b, 0xd7, 0x58, 0xe8, 0x35, 0xcf, 0x62, 0x8a, + 0x47, 0xae, 0xfc, 0x15, 0x3c, 0x72, 0x6b, 0x7f, 0x99, 0x01, 0x36, 0xbb, 0x3a, 0xd8, 0x53, 0xf2, + 0xe7, 0xb8, 0x7c, 0x28, 0x39, 0xf7, 0x37, 0x5e, 0x6f, 0x85, 0x29, 0x82, 0x50, 0xb9, 0xd9, 0x43, + 0x58, 0xd4, 0x03, 0xe1, 0x75, 0xad, 0xbd, 0x66, 0x32, 0x3d, 0x29, 0xb6, 0xed, 0x68, 0x9e, 0xec, + 0xfc, 0x2b, 0x3d, 0xd9, 0x85, 0x57, 0x7a, 0xb2, 0xe7, 0x92, 0x9e, 0xec, 0xb5, 0xff, 0x98, 0x81, + 0xc5, 0x14, 0x22, 0xfe, 0xd9, 0xf5, 0x59, 0xd0, 0x5e, 0x82, 0xad, 0x65, 0x25, 0xed, 0xe9, 0x1c, + 0x6d, 0x17, 0x2a, 0xf1, 0x54, 0xa8, 0x83, 0x22, 0x0f, 0x5e, 0xc5, 0x5d, 0xe2, 0x1c, 0xa6, 0x9e, + 0x7d, 0xed, 0xf7, 0xb2, 0x50, 0xd1, 0x12, 0xc5, 0x28, 0x12, 0xc9, 0x6a, 0x01, 0x44, 0x24, 0x19, + 0xa2, 0xcd, 0xe1, 0x2e, 0x48, 0xa7, 0x06, 0xa5, 0xd3, 0xe2, 0x92, 0x62, 0x20, 0x22, 0xac, 0xc3, + 0xa2, 0xf2, 0xb5, 0xf1, 0x38, 0x4e, 0x50, 0xee, 0x35, 0x0b, 0xd2, 0xe3, 0xc6, 0xa3, 0xb0, 0x43, + 0xf6, 0x50, 0xa9, 0x83, 0xf1, 0xdc, 0x21, 0xa9, 0x93, 0xc7, 0x60, 0x81, 0x16, 0x88, 0x9a, 0x44, + 0x41, 0xe7, 0x1f, 0xc0, 0xb2, 0x5a, 0x1e, 0xc9, 0x1c, 0xe4, 0x44, 0x60, 0x72, 0x71, 0xe8, 0x59, + 0xbe, 0x07, 0x77, 0xa6, 0xda, 0x34, 0x95, 0x95, 0x02, 0x5a, 0x6f, 0x26, 0x5a, 0xa7, 0x97, 0xb0, + 0xf6, 0x63, 0xa8, 0x25, 0x18, 0xe5, 0xcf, 0x6e, 0xca, 0xa7, 0xed, 0x3c, 0x34, 0xa2, 0xba, 0x9d, + 0x67, 0xed, 0x7f, 0xe5, 0x80, 0xcd, 0xf2, 0xea, 0x9f, 0x67, 0x13, 0x66, 0x09, 0x33, 0x97, 0x42, + 0x98, 0xff, 0xcf, 0xe4, 0x87, 0xf7, 0x61, 0x41, 0x1e, 0x98, 0xd2, 0x1c, 0xa6, 0xb4, 0x38, 0x1b, + 0x51, 0x82, 0x6a, 0xc5, 0x47, 0xd3, 0x81, 0x1b, 0xa5, 0xc4, 0x19, 0x11, 0x4d, 0x80, 0x9a, 0x8a, + 0xdf, 0x38, 0x82, 0x39, 0xdb, 0xed, 0x9f, 0x79, 0xbe, 0xe4, 0x83, 0xbf, 0xf0, 0x95, 0xb7, 0xcf, + 0xf5, 0x16, 0xe6, 0x47, 0xa9, 0xcd, 0x94, 0x85, 0x19, 0x1f, 0x40, 0x45, 0x03, 0xb3, 0x32, 0x14, + 0x76, 0x3b, 0x7b, 0x1b, 0x07, 0x8d, 0x1b, 0xac, 0x06, 0x65, 0xb3, 0xbd, 0x79, 0xf0, 0x59, 0xdb, + 0x6c, 0x6f, 0x35, 0x32, 0xac, 0x04, 0xf9, 0xdd, 0x83, 0x6e, 0xaf, 0x91, 0x35, 0xd6, 0xa0, 0x29, + 0x4b, 0x9c, 0xf5, 0x59, 0xfc, 0x56, 0x3e, 0x32, 0x17, 0x62, 0xa2, 0x54, 0xd1, 0xbf, 0x09, 0x55, + 0x5d, 0xbc, 0x91, 0x14, 0x31, 0xe5, 0xb3, 0x17, 0xca, 0xb9, 0xa7, 0xf1, 0xea, 0x4d, 0x20, 0x8f, + 0xed, 0x20, 0xca, 0x96, 0x4d, 0xc8, 0xad, 0x29, 0xde, 0x41, 0x54, 0x7e, 0x12, 0x64, 0xf8, 0xff, + 0x41, 0x3d, 0x69, 0xc0, 0x97, 0x1c, 0x29, 0x4d, 0xe1, 0x14, 0xb9, 0x13, 0x16, 0x7d, 0xf6, 0x3d, + 0x68, 0x4c, 0x3b, 0x00, 0xa4, 0xf0, 0x7c, 0x4d, 0xfe, 0x79, 0x27, 0xe9, 0x13, 0x60, 0x3b, 0xb0, + 0x94, 0x26, 0xe0, 0x21, 0x7d, 0x5c, 0x6f, 0xa4, 0x60, 0xb3, 0x42, 0x1c, 0xfb, 0xb6, 0xf4, 0xf3, + 0x14, 0x70, 0xfa, 0xdf, 0x4e, 0xd6, 0xaf, 0x0d, 0xf6, 0x3a, 0xfd, 0xd3, 0x3c, 0x3e, 0xe7, 0x00, + 0x31, 0x8c, 0x35, 0xa0, 0x7a, 0x70, 0xd8, 0xde, 0xb7, 0x36, 0x77, 0x5a, 0xfb, 0xfb, 0xed, 0xdd, + 0xc6, 0x0d, 0xc6, 0xa0, 0x8e, 0xbe, 0xea, 0xad, 0x08, 0x96, 0x11, 0x30, 0xe9, 0x6f, 0x53, 0xb0, + 0x2c, 0x5b, 0x82, 0x46, 0x67, 0x7f, 0x0a, 0x9a, 0x63, 0x4d, 0x58, 0x3a, 0x6c, 0x93, 0x7b, 0x3b, + 0x51, 0x6e, 0x5e, 0x28, 0x0d, 0xb2, 0xbb, 0x42, 0x69, 0xa0, 0x83, 0x7f, 0x72, 0x1d, 0x28, 0x59, + 0xfa, 0xb7, 0x33, 0xb0, 0x3c, 0x95, 0x10, 0x1f, 0xe7, 0x20, 0x49, 0x3a, 0x29, 0x43, 0x57, 0x11, + 0xa8, 0x56, 0xd3, 0xfb, 0xb0, 0x10, 0x19, 0x9e, 0xa6, 0x76, 0xa5, 0x46, 0x94, 0xa0, 0x90, 0x1f, + 0xc2, 0xa2, 0x66, 0xbf, 0x9a, 0xe2, 0x15, 0x4c, 0x4b, 0x92, 0x19, 0x8c, 0xd5, 0x28, 0x6c, 0x7e, + 0xaa, 0xd5, 0x03, 0x3a, 0x4d, 0xa8, 0x27, 0xc4, 0x6e, 0xb0, 0x64, 0x7b, 0xd5, 0x27, 0x7b, 0x34, + 0x45, 0x08, 0xc9, 0xd6, 0xea, 0x13, 0xae, 0xaa, 0xff, 0xfd, 0x39, 0x60, 0x9f, 0x4e, 0xb8, 0x7f, + 0x85, 0xc7, 0x35, 0x82, 0x57, 0xc5, 0x2f, 0x2a, 0x4b, 0x4b, 0xf6, 0xb5, 0x8e, 0x64, 0xa5, 0x1d, + 0x89, 0xca, 0xbf, 0xfa, 0x48, 0x54, 0xe1, 0x55, 0x47, 0xa2, 0xde, 0x82, 0x9a, 0x73, 0xea, 0x7a, + 0x82, 0x15, 0x0a, 0x49, 0x38, 0x68, 0xce, 0xdd, 0xcb, 0xdd, 0xaf, 0x9a, 0x55, 0x09, 0x14, 0x72, + 0x70, 0xc0, 0x3e, 0x89, 0x91, 0xf8, 0xe0, 0x14, 0x8f, 0xef, 0xe9, 0x4c, 0xb0, 0x3d, 0x38, 0xe5, + 0xd2, 0xb0, 0x84, 0x9a, 0x86, 0xca, 0x2c, 0xe0, 0x01, 0x7b, 0x1b, 0xea, 0x81, 0x37, 0x11, 0x8a, + 0x85, 0x1a, 0x06, 0x72, 0x94, 0x55, 0x09, 0x7a, 0xa8, 0xbc, 0xa2, 0x8b, 0x93, 0x80, 0x5b, 0x23, + 0x27, 0x08, 0x84, 0x78, 0xd6, 0xf7, 0xdc, 0xd0, 0xf7, 0x86, 0xd2, 0xf7, 0xb5, 0x30, 0x09, 0xf8, + 0x1e, 0xa5, 0x6c, 0x52, 0x02, 0xfb, 0x56, 0xdc, 0xa4, 0xb1, 0xed, 0xf8, 0x41, 0x13, 0xb0, 0x49, + 0xaa, 0xa7, 0x28, 0xbf, 0xdb, 0x8e, 0x1f, 0xb5, 0x45, 0x7c, 0x04, 0x53, 0x47, 0xb5, 0x2a, 0xd3, + 0x47, 0xb5, 0x7e, 0x98, 0x7e, 0x54, 0xab, 0x86, 0x45, 0x3f, 0x92, 0x45, 0xcf, 0x4e, 0xf1, 0x57, + 0x3a, 0xb1, 0x35, 0x7b, 0x02, 0xad, 0xfe, 0x55, 0x4e, 0xa0, 0xcd, 0xa7, 0x9d, 0x40, 0xfb, 0x00, + 0x2a, 0x78, 0x36, 0xc8, 0x3a, 0x73, 0x84, 0x0c, 0x47, 0xbe, 0xbc, 0x86, 0x7e, 0x78, 0x68, 0xc7, + 0x71, 0x43, 0x13, 0x7c, 0xf5, 0x33, 0x98, 0x3d, 0x0c, 0xb6, 0xf0, 0x73, 0x3c, 0x0c, 0x26, 0xcf, + 0x30, 0xad, 0x43, 0x49, 0xcd, 0x13, 0x63, 0x90, 0x3f, 0xf1, 0xbd, 0x91, 0xf2, 0x71, 0x88, 0xdf, + 0xac, 0x0e, 0xd9, 0xd0, 0x93, 0x99, 0xb3, 0xa1, 0x67, 0xfc, 0x2a, 0x54, 0x34, 0x52, 0x63, 0x6f, + 0x92, 0x5d, 0x52, 0xe8, 0x66, 0x52, 0xb6, 0xa4, 0x51, 0x2c, 0x4b, 0x68, 0x67, 0x20, 0xf8, 0xcd, + 0xc0, 0xf1, 0x39, 0x1e, 0xdb, 0xb4, 0x7c, 0x7e, 0xce, 0xfd, 0x40, 0xf9, 0x9c, 0x1a, 0x51, 0x82, + 0x49, 0x70, 0xe3, 0xd7, 0x60, 0x31, 0x31, 0xb7, 0x92, 0x45, 0xbc, 0x0d, 0x73, 0x38, 0x6e, 0x2a, + 0x26, 0x20, 0x79, 0x28, 0x4b, 0xa6, 0xe1, 0x79, 0x7c, 0x72, 0x97, 0x59, 0x63, 0xdf, 0x3b, 0xc6, + 0x4a, 0x32, 0x66, 0x45, 0xc2, 0x0e, 0x7d, 0xef, 0xd8, 0xf8, 0xb3, 0x1c, 0xe4, 0x76, 0xbc, 0xb1, + 0x1e, 0xa3, 0x96, 0x99, 0x89, 0x51, 0x93, 0x0a, 0xa7, 0x15, 0x29, 0x94, 0x52, 0x66, 0x47, 0x47, + 0x91, 0x52, 0x2a, 0xef, 0x43, 0x5d, 0xf0, 0x89, 0xd0, 0x13, 0x1a, 0xfb, 0x85, 0xed, 0x93, 0x40, + 0x9c, 0xa3, 0xc5, 0x67, 0x8f, 0xc2, 0x9e, 0xb7, 0x4d, 0x70, 0xb6, 0x04, 0xb9, 0x48, 0x7d, 0xc1, + 0x64, 0xf1, 0xc9, 0x56, 0x60, 0x0e, 0x83, 0x95, 0xaf, 0xa4, 0xd3, 0x5b, 0x7e, 0xb1, 0x6f, 0xc0, + 0x62, 0xb2, 0x5c, 0x62, 0x45, 0x52, 0x36, 0xd2, 0x0b, 0x46, 0x9e, 0x74, 0x13, 0x04, 0x1f, 0x21, + 0x1c, 0x19, 0x3b, 0x73, 0xc2, 0x39, 0x26, 0x69, 0x4c, 0xaf, 0x94, 0x60, 0x7a, 0x77, 0xa1, 0x12, + 0x0e, 0xcf, 0xad, 0xb1, 0x7d, 0x35, 0xf4, 0xec, 0x81, 0x5c, 0xdf, 0x10, 0x0e, 0xcf, 0x0f, 0x09, + 0xc2, 0x1e, 0x02, 0x8c, 0xc6, 0x63, 0xb9, 0xf6, 0xd0, 0xf9, 0x11, 0x93, 0xf2, 0xde, 0xe1, 0x21, + 0x91, 0x9c, 0x59, 0x1e, 0x8d, 0xc7, 0xf4, 0x93, 0x6d, 0x41, 0x3d, 0xf5, 0x68, 0xe5, 0x1d, 0x15, + 0x5b, 0xeb, 0x8d, 0xd7, 0x53, 0x16, 0x67, 0xad, 0xaf, 0xc3, 0xd6, 0xbe, 0x07, 0xec, 0xa7, 0x3c, + 0xe0, 0xd8, 0x83, 0x72, 0xd4, 0x3e, 0xfd, 0x7c, 0x20, 0x46, 0xcb, 0x57, 0x12, 0xe7, 0x03, 0x5b, + 0x83, 0x81, 0x2f, 0xf8, 0x22, 0x6d, 0x98, 0x11, 0xcb, 0x07, 0x6d, 0xc7, 0x6c, 0x11, 0xdf, 0x37, + 0xfe, 0x6b, 0x06, 0x0a, 0x74, 0x58, 0xf1, 0x1d, 0x98, 0x27, 0xfc, 0x28, 0xde, 0x4f, 0xba, 0xca, + 0x69, 0xdf, 0xed, 0xc9, 0x50, 0x3f, 0xb1, 0x2c, 0xb4, 0x83, 0xd6, 0xd9, 0x68, 0xe6, 0xb5, 0xc3, + 0xd6, 0x77, 0xa1, 0x1c, 0x55, 0xad, 0x91, 0x4e, 0x49, 0xd5, 0xcc, 0xde, 0x80, 0xfc, 0x99, 0x37, + 0x56, 0x96, 0x1f, 0x88, 0x47, 0xd2, 0x44, 0x78, 0xdc, 0x16, 0x51, 0x07, 0x35, 0x5e, 0x5a, 0x2c, + 0xa2, 0x4a, 0x90, 0x0c, 0x66, 0xfb, 0x38, 0x97, 0xd2, 0xc7, 0x23, 0x98, 0x17, 0x7c, 0x40, 0x0b, + 0x59, 0xb9, 0x7e, 0xd3, 0x7c, 0x4f, 0x48, 0x78, 0xfd, 0xe1, 0x64, 0xc0, 0x75, 0xdb, 0x1b, 0xc6, + 0xb7, 0x49, 0xb8, 0x92, 0xac, 0x8d, 0xdf, 0xcf, 0x10, 0x7f, 0x11, 0xe5, 0xb2, 0xfb, 0x90, 0x17, + 0xfb, 0xdb, 0x94, 0x25, 0x3e, 0x3a, 0xb6, 0x20, 0xf0, 0x4c, 0xc4, 0xc0, 0xdb, 0x09, 0x26, 0xa3, + 0x64, 0xe9, 0x35, 0xb3, 0xe2, 0x4e, 0x46, 0x91, 0xe9, 0xea, 0x6b, 0xaa, 0x5b, 0x53, 0x66, 0x1f, + 0xea, 0x7d, 0xb4, 0x4c, 0xd7, 0xb5, 0x40, 0xb9, 0x7c, 0x62, 0xc7, 0x54, 0x52, 0xe0, 0xe0, 0x94, + 0x6b, 0x01, 0x72, 0x7f, 0x94, 0x85, 0x5a, 0xa2, 0x45, 0x18, 0x29, 0x28, 0x36, 0x00, 0x72, 0x2c, + 0xc9, 0xf9, 0x06, 0x01, 0x92, 0x82, 0xba, 0x36, 0x4e, 0xd9, 0xc4, 0x38, 0x45, 0xc1, 0x39, 0x39, + 0x3d, 0x38, 0xe7, 0x11, 0x94, 0xe3, 0x03, 0xf6, 0xc9, 0x26, 0x89, 0xfa, 0xd4, 0xe1, 0x8d, 0x18, + 0x29, 0x0e, 0xe7, 0x29, 0xe8, 0xe1, 0x3c, 0xdf, 0xd5, 0xa2, 0x3f, 0xe6, 0xb0, 0x18, 0x23, 0x6d, + 0x44, 0x7f, 0x2e, 0xb1, 0x1f, 0xc6, 0x27, 0x50, 0xd1, 0x1a, 0xaf, 0x47, 0x79, 0x64, 0x12, 0x51, + 0x1e, 0xd1, 0x31, 0xab, 0x6c, 0x7c, 0xcc, 0xca, 0xf8, 0xeb, 0x59, 0xa8, 0x89, 0xf5, 0xe5, 0xb8, + 0xa7, 0x87, 0xde, 0xd0, 0xe9, 0xa3, 0xa3, 0x29, 0x5a, 0x61, 0x52, 0xd0, 0x52, 0xeb, 0x4c, 0x2e, + 0x31, 0x92, 0xb3, 0xf4, 0xd3, 0xa4, 0xc4, 0xa4, 0xa3, 0xd3, 0xa4, 0x06, 0xd4, 0x04, 0x63, 0x44, + 0x97, 0x51, 0x7c, 0xfc, 0xdf, 0xac, 0x9c, 0x70, 0xbe, 0x61, 0x07, 0xc4, 0x21, 0xbf, 0x01, 0x8b, + 0x02, 0x07, 0x0f, 0xd2, 0x8d, 0x9c, 0xe1, 0xd0, 0x21, 0x4c, 0x32, 0x34, 0x35, 0x4e, 0x38, 0x37, + 0xed, 0x90, 0xef, 0x89, 0x04, 0x79, 0x5b, 0x40, 0x69, 0xe0, 0x04, 0xf6, 0x71, 0x1c, 0xcf, 0x19, + 0x7d, 0xa3, 0x67, 0xd9, 0xbe, 0xd4, 0x3c, 0xcb, 0x64, 0x80, 0xa8, 0x8c, 0xec, 0xcb, 0xc8, 0xb3, + 0x3c, 0x45, 0x49, 0xc5, 0x69, 0x4a, 0x32, 0xfe, 0x4d, 0x16, 0x2a, 0x1a, 0x59, 0xbe, 0xce, 0xee, + 0x7a, 0x67, 0xc6, 0x31, 0x58, 0xd6, 0x7d, 0x80, 0x6f, 0x25, 0xab, 0xc4, 0xd8, 0x17, 0xba, 0x97, + 0x40, 0x23, 0xe0, 0x5b, 0x50, 0x16, 0xab, 0xee, 0x03, 0x34, 0xc1, 0xca, 0x5b, 0x35, 0x10, 0x70, + 0x38, 0x39, 0x56, 0x89, 0x8f, 0x31, 0xb1, 0x10, 0x27, 0x3e, 0x16, 0x89, 0x2f, 0x8b, 0xb0, 0xfe, + 0x08, 0xaa, 0xb2, 0x54, 0x9c, 0x53, 0xec, 0x6e, 0xbc, 0xea, 0x13, 0xf3, 0x6d, 0x56, 0xa8, 0x3a, + 0x9a, 0x7c, 0x99, 0xf1, 0xb1, 0xca, 0x58, 0x7a, 0x55, 0xc6, 0xc7, 0xf4, 0x61, 0x6c, 0x47, 0x41, + 0xeb, 0x18, 0x77, 0xa5, 0xf8, 0xd8, 0x43, 0x58, 0x54, 0xec, 0x6a, 0xe2, 0xda, 0xae, 0xeb, 0x4d, + 0xdc, 0x3e, 0x57, 0xe7, 0xaf, 0x98, 0x4c, 0x3a, 0x8a, 0x53, 0x8c, 0x41, 0x74, 0x40, 0x97, 0xe2, + 0xb7, 0x1e, 0x40, 0x81, 0xe4, 0x72, 0x12, 0x3e, 0xd2, 0x19, 0x17, 0xa1, 0xb0, 0xfb, 0x50, 0x20, + 0xf1, 0x3c, 0x7b, 0x2d, 0xb3, 0x21, 0x04, 0xa3, 0x05, 0x4c, 0x64, 0xdc, 0xe3, 0xa1, 0xef, 0xf4, + 0x83, 0xf8, 0x68, 0x57, 0x41, 0xe8, 0x9f, 0x54, 0x57, 0x6c, 0xb9, 0x8d, 0x31, 0x51, 0x47, 0x25, + 0x1c, 0xb1, 0x31, 0x2d, 0x26, 0xca, 0x90, 0xe2, 0xd2, 0x10, 0x56, 0x8e, 0x79, 0x78, 0xc1, 0xb9, + 0xeb, 0x0a, 0x61, 0xa8, 0xcf, 0xdd, 0xd0, 0xb7, 0x87, 0x62, 0x92, 0xa8, 0x07, 0x4f, 0x66, 0x4a, + 0x8d, 0x6d, 0x20, 0x1b, 0x71, 0xc6, 0xcd, 0x28, 0x1f, 0xf1, 0x8e, 0xe5, 0xe3, 0xb4, 0xb4, 0xb5, + 0x5f, 0x81, 0xb5, 0xeb, 0x33, 0xa5, 0x1c, 0xe0, 0xbc, 0x9f, 0xe4, 0x2a, 0x91, 0x1f, 0x70, 0xe8, + 0xd9, 0x21, 0xb5, 0x46, 0xe7, 0x2c, 0xfb, 0x50, 0xd1, 0x52, 0xe2, 0xbd, 0x3f, 0x83, 0xc2, 0x1d, + 0x7d, 0x88, 0x1d, 0xc9, 0xf5, 0xfc, 0x11, 0xfa, 0xdd, 0x06, 0x56, 0x5c, 0x7a, 0xc6, 0x9c, 0x8f, + 0xe1, 0x78, 0x62, 0xdd, 0x58, 0x87, 0x79, 0x94, 0xec, 0xb5, 0x8d, 0xee, 0x65, 0xc2, 0xa0, 0xb1, + 0x04, 0x6c, 0x9f, 0x78, 0x97, 0x1e, 0xce, 0xf9, 0x9f, 0x72, 0x50, 0xd1, 0xc0, 0x62, 0x37, 0xc2, + 0x00, 0x40, 0x6b, 0xe0, 0xd8, 0x23, 0xae, 0x9c, 0x9c, 0x35, 0xb3, 0x86, 0xd0, 0x2d, 0x09, 0x14, + 0x7b, 0xb1, 0x7d, 0x7e, 0x6a, 0x79, 0x93, 0xd0, 0x1a, 0xf0, 0x53, 0x9f, 0xab, 0x56, 0x56, 0xed, + 0xf3, 0xd3, 0x83, 0x49, 0xb8, 0x85, 0x30, 0x81, 0x25, 0x78, 0x89, 0x86, 0x25, 0x63, 0xd6, 0x46, + 0xf6, 0x65, 0x8c, 0x25, 0x03, 0x27, 0x89, 0x32, 0xf3, 0x51, 0xe0, 0x24, 0x69, 0x8b, 0xd3, 0x1b, + 0x68, 0x61, 0x76, 0x03, 0xfd, 0x16, 0xac, 0xd0, 0x06, 0x2a, 0x59, 0xb3, 0x35, 0xb5, 0x92, 0x97, + 0x30, 0x55, 0x76, 0x52, 0x13, 0x7b, 0x1b, 0xa2, 0x07, 0x8a, 0x2d, 0x05, 0xce, 0x8f, 0x88, 0x91, + 0x65, 0x4c, 0xd1, 0x33, 0x59, 0x78, 0xd7, 0xf9, 0x11, 0x17, 0x98, 0x18, 0x1d, 0xa3, 0x63, 0xca, + 0xf3, 0x13, 0x23, 0xc7, 0x9d, 0xc6, 0xb4, 0x2f, 0x93, 0x98, 0x65, 0x89, 0x69, 0x5f, 0xea, 0x98, + 0x4f, 0x60, 0x75, 0xc4, 0x07, 0x8e, 0x9d, 0x2c, 0xd6, 0x8a, 0x05, 0xb7, 0x25, 0x4a, 0xd6, 0xf2, + 0x74, 0x49, 0x71, 0x17, 0xa3, 0xf1, 0x23, 0x6f, 0x74, 0xec, 0x90, 0xcc, 0x42, 0xf1, 0x3a, 0x79, + 0xb3, 0xee, 0x4e, 0x46, 0x3f, 0x40, 0xb0, 0xc8, 0x12, 0x18, 0x35, 0xa8, 0x74, 0x43, 0x6f, 0xac, + 0xa6, 0xb9, 0x0e, 0x55, 0xfa, 0x94, 0x87, 0x1a, 0x6f, 0xc1, 0x4d, 0x64, 0x09, 0x3d, 0x6f, 0xec, + 0x0d, 0xbd, 0xd3, 0xab, 0x84, 0x1d, 0xef, 0xdf, 0x65, 0x60, 0x31, 0x91, 0x2a, 0xd9, 0xeb, 0xb7, + 0x88, 0x9f, 0x45, 0x27, 0xd3, 0x68, 0x0d, 0x2e, 0x68, 0x6b, 0x90, 0x10, 0x89, 0x99, 0xa9, 0xd3, + 0x6a, 0xad, 0xf8, 0x46, 0x05, 0x95, 0x91, 0x58, 0x4a, 0x73, 0x96, 0xa5, 0xc8, 0xfc, 0xea, 0xae, + 0x05, 0x55, 0xc4, 0x2f, 0xc8, 0x33, 0x2e, 0x03, 0xd9, 0xe5, 0x5c, 0xf2, 0xa0, 0x80, 0x6e, 0xf3, + 0x53, 0x2d, 0x88, 0x0d, 0x81, 0x81, 0xf1, 0x4f, 0x32, 0x00, 0x71, 0xeb, 0xf0, 0xa8, 0x42, 0x24, + 0xb7, 0xd0, 0x65, 0x65, 0x9a, 0x8c, 0xf2, 0x26, 0x54, 0xa3, 0x88, 0xe5, 0x58, 0x12, 0xaa, 0x28, + 0x98, 0x10, 0x87, 0xde, 0x85, 0xf9, 0xd3, 0xa1, 0x77, 0x8c, 0x12, 0xab, 0x94, 0x5b, 0x28, 0x5e, + 0xad, 0x4e, 0x60, 0x25, 0x8d, 0xc4, 0x72, 0x53, 0x3e, 0x35, 0xa8, 0x59, 0x97, 0x82, 0x8c, 0xdf, + 0xcc, 0x46, 0xa1, 0x9b, 0xf1, 0x48, 0xbc, 0x5c, 0xbd, 0xfb, 0x49, 0x62, 0x69, 0x5e, 0xe6, 0x5e, + 0xfc, 0x04, 0xea, 0x3e, 0x6d, 0x4a, 0x6a, 0xc7, 0xca, 0xbf, 0x64, 0xc7, 0xaa, 0xf9, 0x09, 0x49, + 0xe7, 0x3d, 0x68, 0xd8, 0x83, 0x73, 0xee, 0x87, 0x0e, 0x5a, 0xeb, 0x51, 0x3e, 0x96, 0xc1, 0x92, + 0x1a, 0x1c, 0x05, 0xd1, 0x77, 0x61, 0x5e, 0x1e, 0xb4, 0x8d, 0x30, 0xe5, 0xd5, 0x3d, 0x31, 0x58, + 0x20, 0x1a, 0xff, 0x5c, 0xc5, 0x8a, 0x26, 0x67, 0xf7, 0xe5, 0xa3, 0xa2, 0xf7, 0x30, 0x3b, 0xeb, + 0x40, 0x95, 0x84, 0x24, 0x9d, 0x00, 0x92, 0x1f, 0x11, 0x50, 0xba, 0x00, 0x92, 0xc3, 0x9a, 0x7f, + 0x9d, 0x61, 0x35, 0xfe, 0x43, 0x06, 0x8a, 0x3b, 0xde, 0x78, 0xc7, 0xa1, 0x60, 0x7d, 0x5c, 0x26, + 0x91, 0x8f, 0x6a, 0x4e, 0x7c, 0x62, 0xe0, 0xcf, 0x4b, 0xce, 0x93, 0xa5, 0x8a, 0x79, 0xb5, 0xa4, + 0x98, 0xf7, 0x5d, 0xb8, 0x85, 0x2e, 0x40, 0xdf, 0x1b, 0x7b, 0xbe, 0x58, 0xaa, 0xf6, 0x90, 0xc4, + 0x3d, 0xcf, 0x0d, 0xcf, 0x14, 0xef, 0xbc, 0x79, 0xc2, 0xf9, 0xa1, 0x86, 0xb1, 0x17, 0x21, 0xe0, + 0x89, 0xcd, 0x61, 0x78, 0x6e, 0x91, 0x86, 0x2e, 0xe5, 0x51, 0xe2, 0xa8, 0xf3, 0x22, 0xa1, 0x8d, + 0x70, 0x94, 0x48, 0x8d, 0x6f, 0x43, 0x39, 0x32, 0xf6, 0xb0, 0xf7, 0xa1, 0x7c, 0xe6, 0x8d, 0xa5, + 0x45, 0x28, 0x93, 0x38, 0x73, 0x27, 0x7b, 0x6d, 0x96, 0xce, 0xe8, 0x47, 0x60, 0xfc, 0x59, 0x11, + 0x8a, 0x1d, 0xf7, 0xdc, 0x73, 0xfa, 0x18, 0x6d, 0x3a, 0xe2, 0x23, 0x4f, 0x9d, 0xf6, 0x17, 0xbf, + 0x31, 0x36, 0x2b, 0xbe, 0x80, 0x27, 0x27, 0x63, 0xb3, 0xa2, 0xab, 0x77, 0x96, 0x61, 0xce, 0xd7, + 0x6f, 0xd0, 0x29, 0xf8, 0x18, 0xff, 0x1e, 0xed, 0x97, 0x05, 0xed, 0xb6, 0x04, 0x51, 0x16, 0xdd, + 0xec, 0x82, 0x43, 0x46, 0xa7, 0x2f, 0xcb, 0x08, 0xc1, 0x01, 0xbb, 0x0d, 0x45, 0x79, 0xc4, 0x8d, + 0xce, 0x24, 0x51, 0xc0, 0xba, 0x04, 0x21, 0x35, 0xf8, 0x9c, 0x5c, 0xb8, 0x91, 0x20, 0x9b, 0x33, + 0xab, 0x0a, 0xb8, 0x25, 0x68, 0xed, 0x2e, 0x54, 0x08, 0x9f, 0x50, 0x4a, 0x32, 0x48, 0x13, 0x41, + 0x88, 0x90, 0x72, 0x11, 0x55, 0x39, 0xf5, 0x22, 0x2a, 0x0c, 0x27, 0x8e, 0xb8, 0x2c, 0x75, 0x11, + 0xe8, 0xfa, 0x21, 0x0d, 0xae, 0x6e, 0x61, 0x93, 0x36, 0x15, 0x3a, 0x8c, 0xac, 0x6c, 0x2a, 0x6f, + 0x41, 0xed, 0xc4, 0x1e, 0x0e, 0x8f, 0xed, 0xfe, 0x0b, 0x32, 0x05, 0x54, 0xc9, 0xfa, 0xa9, 0x80, + 0x68, 0x0b, 0xb8, 0x0b, 0x15, 0x6d, 0x96, 0x31, 0x02, 0x33, 0x6f, 0x42, 0x3c, 0xbf, 0xd3, 0x16, + 0xbe, 0xfa, 0x6b, 0x58, 0xf8, 0xb4, 0x48, 0xd4, 0xf9, 0x64, 0x24, 0xea, 0x2d, 0xe4, 0xa6, 0x32, + 0xe4, 0xb0, 0x41, 0x77, 0xdd, 0xd8, 0x83, 0x01, 0x86, 0x1c, 0xd2, 0xc5, 0x92, 0x38, 0x78, 0x94, + 0xbe, 0x40, 0xba, 0x04, 0xc1, 0x08, 0xe5, 0x0e, 0x99, 0xa9, 0xc7, 0xb6, 0x33, 0xc0, 0x43, 0x07, + 0x64, 0x3d, 0x28, 0xda, 0xa3, 0xf0, 0xd0, 0x76, 0x06, 0xec, 0x1e, 0x54, 0x55, 0x32, 0xee, 0x8e, + 0x8b, 0x34, 0xfe, 0x32, 0x59, 0xec, 0x89, 0x06, 0xd4, 0x22, 0x8c, 0x51, 0x7c, 0xa2, 0xb8, 0x22, + 0x51, 0x90, 0x0e, 0x3e, 0xc0, 0x28, 0x9f, 0x90, 0xe3, 0xb9, 0xe1, 0xfa, 0xe3, 0x5b, 0x51, 0xf0, + 0x01, 0x52, 0xa9, 0xfa, 0x4f, 0xce, 0x31, 0xc2, 0x14, 0xc2, 0x1d, 0xf9, 0xe8, 0x56, 0x12, 0xf2, + 0xaf, 0x44, 0x45, 0x1f, 0x1d, 0x21, 0xb0, 0x6f, 0x6b, 0xfa, 0x6b, 0x13, 0x91, 0x6f, 0x4f, 0x95, + 0x7f, 0xdd, 0x99, 0xab, 0x3b, 0x00, 0x4e, 0x20, 0x76, 0x99, 0x80, 0xbb, 0x03, 0x3c, 0x02, 0x5c, + 0x32, 0xcb, 0x4e, 0xf0, 0x8c, 0x00, 0x3f, 0x5b, 0xc5, 0xb6, 0x05, 0x55, 0xbd, 0x9b, 0xac, 0x04, + 0xf9, 0x83, 0xc3, 0xf6, 0x7e, 0xe3, 0x06, 0xab, 0x40, 0xb1, 0xdb, 0xee, 0xf5, 0x76, 0xd1, 0xd3, + 0x57, 0x85, 0x52, 0x74, 0x4e, 0x31, 0x2b, 0xbe, 0x5a, 0x9b, 0x9b, 0xed, 0xc3, 0x5e, 0x7b, 0xab, + 0x91, 0xfb, 0x7e, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0x3f, 0xcf, 0x41, 0x45, 0x1b, 0x85, 0x97, 0x33, + 0xe3, 0x3b, 0x00, 0xa8, 0x49, 0xc6, 0x11, 0xa9, 0x79, 0xb3, 0x2c, 0x20, 0x34, 0xf9, 0xba, 0x8f, + 0x22, 0x47, 0x97, 0x28, 0x29, 0x1f, 0xc5, 0x5b, 0x50, 0xa3, 0xfb, 0x88, 0x74, 0x7f, 0x6d, 0xc1, + 0xac, 0x12, 0x50, 0xb2, 0x6a, 0x3c, 0xc0, 0x8c, 0x48, 0x78, 0x7a, 0x4e, 0xde, 0x4e, 0x42, 0x20, + 0x3c, 0x3f, 0x87, 0x87, 0x1f, 0x03, 0x6f, 0x78, 0xce, 0x09, 0x83, 0x24, 0xc2, 0x8a, 0x84, 0xf5, + 0xe4, 0x51, 0x6c, 0xc9, 0x0f, 0xb5, 0x13, 0xb4, 0x05, 0xb3, 0x4a, 0x40, 0x59, 0xd1, 0x37, 0x14, + 0x01, 0x51, 0xf4, 0xca, 0xea, 0x2c, 0x35, 0x24, 0x88, 0x67, 0x77, 0xc6, 0x8c, 0x58, 0x46, 0xc2, + 0xf8, 0xda, 0x6c, 0xbe, 0x57, 0x9b, 0x13, 0xd9, 0xfb, 0xc0, 0x46, 0xe3, 0xb1, 0x95, 0x62, 0xe0, + 0xcb, 0x9b, 0xf3, 0xa3, 0xf1, 0xb8, 0xa7, 0xd9, 0xbf, 0x7e, 0x06, 0xb6, 0xc7, 0x2f, 0x80, 0xb5, + 0xc4, 0x02, 0xc6, 0x26, 0x46, 0xaa, 0x58, 0xcc, 0x96, 0x33, 0x3a, 0x5b, 0x4e, 0xe1, 0x7e, 0xd9, + 0x54, 0xee, 0xf7, 0x32, 0x3e, 0x61, 0x6c, 0x43, 0xe5, 0x50, 0xbb, 0xed, 0xec, 0x9e, 0xd8, 0x21, + 0xd4, 0x3d, 0x67, 0xb4, 0x77, 0x90, 0x4d, 0xd1, 0x97, 0xd7, 0x9b, 0x69, 0xad, 0xc9, 0x6a, 0xad, + 0x31, 0xfe, 0x51, 0x86, 0x6e, 0x92, 0x89, 0x1a, 0x1f, 0x5f, 0xb0, 0xa6, 0xdc, 0x6f, 0xf1, 0x41, + 0xf7, 0x8a, 0x72, 0xbb, 0xc9, 0x33, 0xea, 0xd8, 0x34, 0xcb, 0x3b, 0x39, 0x09, 0xb8, 0x8a, 0xf1, + 0xa8, 0x20, 0xec, 0x00, 0x41, 0x4a, 0xf8, 0x16, 0x12, 0xbe, 0x43, 0xe5, 0x07, 0x32, 0xb0, 0x43, + 0x08, 0xdf, 0x7b, 0xf6, 0xa5, 0xac, 0x35, 0x10, 0x22, 0x88, 0xf4, 0x0f, 0xa8, 0xb3, 0xb0, 0xd1, + 0xb7, 0xf1, 0x0f, 0xe4, 0x59, 0xfc, 0xe9, 0xf1, 0x7d, 0x00, 0xa5, 0xa8, 0xd4, 0xe4, 0x0e, 0xab, + 0x30, 0xa3, 0x74, 0xb1, 0x8f, 0xa3, 0x31, 0x24, 0xd1, 0x62, 0x5a, 0x5c, 0xe8, 0xe3, 0xe9, 0x68, + 0xad, 0xfe, 0x3a, 0xb0, 0x13, 0xc7, 0x9f, 0x46, 0xa6, 0xc5, 0xd6, 0xc0, 0x14, 0x0d, 0xdb, 0x38, + 0x82, 0x45, 0xc5, 0x25, 0x34, 0x8d, 0x20, 0x39, 0x79, 0x99, 0x57, 0x30, 0xf9, 0xec, 0x0c, 0x93, + 0x37, 0xfe, 0x73, 0x1e, 0x8a, 0xea, 0xe6, 0xc0, 0xb4, 0xdb, 0xee, 0xca, 0xc9, 0xdb, 0xee, 0x9a, + 0x89, 0x9b, 0x91, 0x70, 0xea, 0xe5, 0x7e, 0xff, 0xee, 0xf4, 0x96, 0xad, 0xf9, 0x2a, 0x12, 0xdb, + 0xf6, 0x0a, 0xe4, 0xc7, 0x76, 0x78, 0x86, 0x76, 0x49, 0x22, 0x1e, 0xfc, 0x56, 0x3e, 0x8c, 0x42, + 0xd2, 0x87, 0x91, 0x76, 0x33, 0x20, 0x89, 0xa4, 0x33, 0x37, 0x03, 0xde, 0x02, 0x92, 0x2f, 0xb4, + 0xa0, 0xb7, 0x12, 0x02, 0xc4, 0x5e, 0x94, 0x14, 0x47, 0x4a, 0xd3, 0xe2, 0xc8, 0x6b, 0x8b, 0x0a, + 0xdf, 0x82, 0x39, 0xba, 0x55, 0x43, 0x9e, 0xf9, 0x55, 0x1b, 0x8a, 0x1c, 0x43, 0xf5, 0x9f, 0x4e, + 0x42, 0x98, 0x12, 0x57, 0xbf, 0x66, 0xab, 0x92, 0xb8, 0x66, 0x4b, 0xf7, 0xad, 0x54, 0x93, 0xbe, + 0x95, 0xfb, 0xd0, 0x88, 0x06, 0x14, 0x2d, 0x95, 0x6e, 0x20, 0x4f, 0x14, 0xd6, 0x15, 0x5c, 0x70, + 0xc9, 0xfd, 0x20, 0xde, 0x10, 0xeb, 0x89, 0x0d, 0x51, 0xf0, 0xb0, 0x56, 0x18, 0xf2, 0xd1, 0x38, + 0x54, 0x1b, 0xa2, 0x76, 0x19, 0x23, 0x51, 0xc4, 0x3c, 0x52, 0x84, 0x9a, 0x76, 0xb5, 0xe4, 0x6b, + 0x89, 0x5e, 0x88, 0x6d, 0x48, 0x1e, 0xfb, 0xa5, 0xf8, 0x93, 0xce, 0xbe, 0xb5, 0xbd, 0xdb, 0x79, + 0xba, 0xd3, 0x6b, 0x64, 0xc4, 0x67, 0xf7, 0x68, 0x73, 0xb3, 0xdd, 0xde, 0xc2, 0x6d, 0x09, 0x60, + 0x6e, 0xbb, 0xd5, 0x11, 0x5b, 0x54, 0xce, 0xf8, 0xed, 0x2c, 0x54, 0xb4, 0x36, 0xb0, 0x27, 0xd1, + 0xd0, 0xd1, 0x75, 0x4d, 0x77, 0x66, 0xdb, 0xb9, 0xae, 0xf8, 0xb5, 0x36, 0x76, 0xd1, 0x65, 0x89, + 0xd9, 0x6b, 0x2f, 0x4b, 0x64, 0xef, 0xc0, 0xbc, 0x4d, 0x25, 0x44, 0x43, 0x25, 0x4d, 0xf5, 0x12, + 0x2c, 0x47, 0x0a, 0xe3, 0x41, 0xe3, 0x4d, 0x47, 0xe0, 0xe5, 0x55, 0x08, 0x66, 0xb4, 0xef, 0xe0, + 0x88, 0x16, 0x4f, 0x6c, 0x67, 0x38, 0xf1, 0xb9, 0x74, 0xad, 0x47, 0xdb, 0x37, 0x41, 0x4d, 0x95, + 0x6c, 0x7c, 0x08, 0x10, 0xb7, 0x39, 0x39, 0x38, 0x37, 0x92, 0x83, 0x93, 0xd1, 0x06, 0x27, 0x6b, + 0xfc, 0x33, 0xc9, 0x6c, 0xe4, 0x48, 0x47, 0xc6, 0xb9, 0x6f, 0x80, 0x32, 0x17, 0x5a, 0x18, 0x96, + 0x3d, 0x1e, 0xf2, 0x50, 0xdd, 0x2e, 0xb0, 0x20, 0x53, 0x3a, 0x51, 0xc2, 0x0c, 0x73, 0xcc, 0xce, + 0x32, 0xc7, 0x37, 0xa1, 0x2a, 0x18, 0xa3, 0x9c, 0xe2, 0x40, 0x32, 0x98, 0xca, 0xc8, 0xbe, 0x54, + 0x75, 0x27, 0xb8, 0x62, 0x7e, 0x8a, 0x2b, 0xfe, 0x4e, 0x86, 0x2e, 0xfb, 0x88, 0x1b, 0x1a, 0xb3, + 0xc5, 0xa8, 0xcc, 0x24, 0x5b, 0x94, 0xa8, 0x66, 0x94, 0x7e, 0x0d, 0xab, 0xcb, 0xa6, 0xb3, 0xba, + 0x74, 0x26, 0x9a, 0x4b, 0x65, 0xa2, 0xc6, 0x1a, 0x34, 0xb7, 0xb8, 0x18, 0x8a, 0xd6, 0x70, 0x38, + 0x35, 0x96, 0xc6, 0x2d, 0xb8, 0x99, 0x92, 0x26, 0xed, 0x2c, 0x9f, 0xc2, 0x72, 0x8b, 0x6e, 0x41, + 0xf8, 0x59, 0x1d, 0x77, 0x34, 0x9a, 0xb0, 0x32, 0x5d, 0xa4, 0xac, 0x6c, 0x1b, 0x16, 0xb6, 0xf8, + 0xf1, 0xe4, 0x74, 0x97, 0x9f, 0xc7, 0x15, 0x31, 0xc8, 0x07, 0x67, 0xde, 0x85, 0x9c, 0x5c, 0xfc, + 0x8d, 0x81, 0x94, 0x02, 0xc7, 0x0a, 0xc6, 0xbc, 0xaf, 0x6c, 0xed, 0x08, 0xe9, 0x8e, 0x79, 0xdf, + 0x78, 0x02, 0x4c, 0x2f, 0x47, 0xce, 0x84, 0x50, 0x84, 0x26, 0xc7, 0x56, 0x70, 0x15, 0x84, 0x7c, + 0xa4, 0x8e, 0xf9, 0x41, 0x30, 0x39, 0xee, 0x12, 0xc4, 0x78, 0x17, 0xaa, 0x87, 0xf6, 0x95, 0xc9, + 0xbf, 0x90, 0xa7, 0xe9, 0x56, 0xa1, 0x38, 0xb6, 0xaf, 0x04, 0xa7, 0x8b, 0xdc, 0x6e, 0x98, 0x6c, + 0xfc, 0x41, 0x1e, 0xe6, 0x08, 0x93, 0xdd, 0xa3, 0xeb, 0x86, 0x1d, 0x17, 0x39, 0x8d, 0xda, 0x0b, + 0x34, 0xd0, 0xcc, 0x76, 0x91, 0x9d, 0xdd, 0x2e, 0xa4, 0x8d, 0x50, 0x5d, 0xb3, 0xa4, 0x1c, 0x24, + 0xee, 0x64, 0xa4, 0xee, 0x56, 0x4a, 0x5e, 0x05, 0x90, 0x8f, 0xaf, 0x93, 0xa6, 0x73, 0xd2, 0x49, + 0x17, 0x76, 0xac, 0x6e, 0x51, 0xeb, 0xd4, 0x2e, 0x28, 0x77, 0x04, 0x1d, 0x94, 0xaa, 0xd3, 0x15, + 0xd5, 0x11, 0xd1, 0xa4, 0x4e, 0x37, 0xa3, 0xbb, 0x95, 0x5e, 0xad, 0xbb, 0x91, 0xf1, 0xf0, 0x25, + 0xba, 0x1b, 0xbc, 0x86, 0xee, 0xf6, 0x1a, 0xee, 0xe3, 0x9b, 0x50, 0x42, 0xd1, 0x46, 0xdb, 0x20, + 0x84, 0x48, 0x23, 0x36, 0x88, 0x8f, 0x34, 0xed, 0x86, 0x62, 0x57, 0x6e, 0xc5, 0x0b, 0xd0, 0xe4, + 0x5f, 0xfc, 0x7c, 0xdc, 0x72, 0xcf, 0xa1, 0x28, 0xa1, 0x82, 0xa0, 0x5d, 0x7b, 0xa4, 0x6e, 0xaa, + 0xc3, 0xdf, 0x62, 0xd8, 0xf0, 0x7a, 0xad, 0x2f, 0x26, 0x8e, 0xcf, 0x07, 0xea, 0x0a, 0x22, 0x07, + 0xd7, 0xa8, 0x80, 0x88, 0x0e, 0x0a, 0x4d, 0xcb, 0xf5, 0x2e, 0x5c, 0xc9, 0x7b, 0x8a, 0x4e, 0xf0, + 0x4c, 0x7c, 0x1a, 0x0c, 0x1a, 0x78, 0x57, 0xe5, 0xd8, 0xf3, 0xd5, 0xfe, 0x6b, 0xfc, 0x61, 0x06, + 0x1a, 0x72, 0x75, 0x45, 0x69, 0xba, 0xa2, 0x53, 0xb8, 0x2e, 0xd4, 0xe2, 0xe5, 0x17, 0x0a, 0x19, + 0x50, 0x43, 0xfb, 0x4e, 0xb4, 0x19, 0x93, 0x7d, 0xaa, 0x22, 0x80, 0xdb, 0x72, 0x43, 0x7e, 0x03, + 0x2a, 0x2a, 0xcc, 0x7b, 0xe4, 0x0c, 0xd5, 0xcd, 0xf1, 0x14, 0xe7, 0xbd, 0xe7, 0x0c, 0xd5, 0x5e, + 0xee, 0xdb, 0xf2, 0xc8, 0x72, 0x06, 0xf7, 0x72, 0xd3, 0x0e, 0xb9, 0xf1, 0xaf, 0x32, 0xb0, 0xa0, + 0x75, 0x45, 0xae, 0xdb, 0x8f, 0xa1, 0x1a, 0x5d, 0x12, 0xcb, 0x23, 0xe1, 0x72, 0x35, 0xc9, 0x68, + 0xe2, 0x6c, 0x95, 0x7e, 0x04, 0x09, 0x44, 0x63, 0x06, 0xf6, 0x15, 0xc5, 0x22, 0x4f, 0x46, 0x4a, + 0x7f, 0x1b, 0xd8, 0x57, 0xdb, 0x9c, 0x77, 0x27, 0x23, 0xa1, 0x9d, 0x5f, 0x70, 0xfe, 0x22, 0x42, + 0x20, 0xf6, 0x09, 0x02, 0x26, 0x31, 0x0c, 0xa8, 0x8d, 0x3c, 0x37, 0x3c, 0x8b, 0x50, 0xa4, 0x60, + 0x8d, 0x40, 0xc2, 0x31, 0xfe, 0x34, 0x0b, 0x8b, 0x64, 0x45, 0x94, 0xd6, 0x5b, 0xc9, 0xba, 0x9a, + 0x30, 0x47, 0x06, 0x55, 0x62, 0x5e, 0x3b, 0x37, 0x4c, 0xf9, 0xcd, 0xbe, 0xf5, 0x9a, 0x96, 0x4f, + 0x75, 0x2a, 0xfa, 0x9a, 0xe1, 0xcf, 0xcd, 0x0e, 0xff, 0xf5, 0xc3, 0x9b, 0xe6, 0xcb, 0x2d, 0xa4, + 0xf9, 0x72, 0x5f, 0xc7, 0x83, 0x3a, 0x73, 0x7e, 0xb7, 0x28, 0x71, 0xb4, 0xf3, 0xbb, 0x4f, 0x60, + 0x35, 0x81, 0x83, 0xdc, 0xda, 0x39, 0x71, 0xb8, 0xba, 0x42, 0x66, 0x49, 0xc3, 0xee, 0xaa, 0xb4, + 0x8d, 0x22, 0x14, 0x82, 0xbe, 0x37, 0xe6, 0xc6, 0x0a, 0x2c, 0x25, 0x47, 0x55, 0x6e, 0x13, 0xbf, + 0x9b, 0x81, 0xa6, 0x8c, 0xbc, 0x71, 0xdc, 0xd3, 0x1d, 0x27, 0x08, 0x3d, 0x3f, 0xba, 0x4c, 0xf5, + 0x0e, 0x40, 0x10, 0xda, 0xbe, 0x54, 0xa8, 0xe5, 0xa5, 0x29, 0x08, 0x41, 0x65, 0xf9, 0x26, 0x94, + 0xb8, 0x3b, 0xa0, 0x44, 0xa2, 0x86, 0x22, 0x77, 0x07, 0x4a, 0xd5, 0x9e, 0xd9, 0x4a, 0x6b, 0x49, + 0x21, 0x41, 0xde, 0x61, 0x20, 0x46, 0x87, 0x9f, 0xe3, 0x96, 0x9e, 0x8f, 0xee, 0x30, 0xd8, 0xb3, + 0x2f, 0x31, 0x8e, 0x35, 0x30, 0xfe, 0x6e, 0x16, 0xe6, 0xe3, 0xf6, 0xd1, 0x05, 0x28, 0x2f, 0xbf, + 0xca, 0xe5, 0x9e, 0x24, 0x07, 0x47, 0xa8, 0x28, 0x9a, 0x6d, 0xb5, 0x44, 0x8b, 0xb3, 0xe3, 0x32, + 0x03, 0x2a, 0x0a, 0xc3, 0x9b, 0x84, 0xda, 0x9d, 0x86, 0x65, 0x42, 0x39, 0x98, 0x84, 0x42, 0xa7, + 0x14, 0xca, 0xb5, 0xe3, 0x4a, 0xad, 0xae, 0x60, 0x8f, 0xc2, 0x0e, 0x3e, 0x95, 0x20, 0xc0, 0x22, + 0x1b, 0x4d, 0xa4, 0xc0, 0x12, 0xf8, 0x0d, 0x52, 0x25, 0x68, 0xe6, 0x50, 0x8d, 0xd0, 0xe5, 0x6c, + 0xba, 0x35, 0x3a, 0x92, 0xb3, 0xdf, 0x80, 0x0a, 0x15, 0x1e, 0x1f, 0xd7, 0xce, 0x9b, 0x65, 0xac, + 0x01, 0xd3, 0xa5, 0x9d, 0xcb, 0x9b, 0x24, 0xb4, 0x7b, 0xa0, 0xaa, 0x30, 0xb0, 0xe5, 0x6f, 0x66, + 0xe0, 0x66, 0xca, 0xb4, 0xc9, 0x55, 0xbe, 0x09, 0x0b, 0x27, 0x51, 0xa2, 0x1a, 0x5d, 0x5a, 0xea, + 0x2b, 0x8a, 0xad, 0x26, 0xc7, 0xd4, 0x6c, 0x9c, 0x24, 0x01, 0xb1, 0x5e, 0x49, 0x33, 0x98, 0xb8, + 0x0c, 0x00, 0x45, 0x22, 0x9a, 0x46, 0x92, 0xdf, 0x0f, 0x61, 0xad, 0x7d, 0x29, 0x38, 0xc6, 0xa6, + 0xfe, 0xd6, 0x87, 0x22, 0xa3, 0xa4, 0x0d, 0x3d, 0xf3, 0x5a, 0x36, 0xf4, 0x01, 0x9d, 0x1e, 0x8e, + 0xca, 0xfa, 0x49, 0x0a, 0xc1, 0x0d, 0x54, 0xe4, 0xa1, 0xb7, 0x4a, 0xd4, 0xad, 0x00, 0xfd, 0xe8, + 0x8d, 0x12, 0x23, 0x80, 0xf9, 0xbd, 0xc9, 0x30, 0x74, 0xe2, 0x67, 0x4b, 0xd8, 0xb7, 0x64, 0x1e, + 0xac, 0x47, 0x8d, 0x5a, 0x6a, 0x45, 0x10, 0x55, 0x84, 0x83, 0x35, 0x12, 0x05, 0x59, 0xb3, 0xf5, + 0xcd, 0x8f, 0x92, 0x35, 0x18, 0x37, 0x61, 0x35, 0xfe, 0xa2, 0x61, 0x53, 0x5b, 0xcd, 0x3f, 0xcc, + 0x50, 0xd0, 0x7c, 0xf2, 0x09, 0x15, 0xd6, 0x86, 0xc5, 0xc0, 0x71, 0x4f, 0x87, 0x5c, 0x2f, 0x3e, + 0x90, 0x83, 0xb0, 0x9c, 0x6c, 0x9b, 0x7c, 0x66, 0xc5, 0x5c, 0xa0, 0x1c, 0x71, 0x69, 0x01, 0xdb, + 0xb8, 0xae, 0x91, 0x31, 0x59, 0x4c, 0x8d, 0xc6, 0x6c, 0xe3, 0x3b, 0x50, 0x4f, 0x56, 0xc4, 0x3e, + 0x92, 0x87, 0xee, 0xe3, 0x56, 0xe5, 0xa6, 0x4e, 0x24, 0xc7, 0x04, 0x51, 0x89, 0xc7, 0x3e, 0x30, + 0xfe, 0x76, 0x06, 0x9a, 0x26, 0x17, 0x94, 0xab, 0xb5, 0x52, 0xd1, 0xcc, 0xc7, 0x33, 0xa5, 0x5e, + 0xdf, 0x57, 0x75, 0x96, 0x5f, 0xb5, 0xe8, 0xeb, 0xd7, 0x4e, 0xc6, 0xce, 0x8d, 0x99, 0x1e, 0x6d, + 0x94, 0x60, 0x8e, 0x50, 0x8c, 0x55, 0x58, 0x96, 0xed, 0x51, 0x6d, 0x89, 0x1d, 0xa4, 0x89, 0x1a, + 0x13, 0x0e, 0xd2, 0x35, 0x68, 0xd2, 0xe9, 0x5a, 0xbd, 0x13, 0x32, 0xe3, 0x16, 0xb0, 0x3d, 0xbb, + 0x6f, 0xfb, 0x9e, 0xe7, 0x1e, 0x72, 0x5f, 0x86, 0x20, 0xa3, 0x84, 0x89, 0xfe, 0x43, 0x25, 0x0a, + 0xd3, 0x97, 0xba, 0xc9, 0xd5, 0x73, 0x55, 0xc4, 0x15, 0x7d, 0x19, 0x26, 0x2c, 0x6e, 0xd8, 0x2f, + 0xb8, 0x2a, 0x49, 0x0d, 0xd1, 0x27, 0x50, 0x19, 0x47, 0x85, 0xaa, 0x71, 0x57, 0x97, 0x82, 0xcc, + 0x56, 0x6b, 0xea, 0xd8, 0xc6, 0x63, 0x58, 0x4a, 0x96, 0x29, 0x59, 0xc7, 0x1a, 0x94, 0x46, 0x12, + 0x26, 0x5b, 0x17, 0x7d, 0x1b, 0xbf, 0x55, 0x82, 0xa2, 0xd4, 0x46, 0xd9, 0x3a, 0xe4, 0xfb, 0x2a, + 0xea, 0x2d, 0xbe, 0x6b, 0x4a, 0xa6, 0xaa, 0xff, 0x9b, 0x18, 0xfb, 0x26, 0xf0, 0xd8, 0x27, 0x50, + 0x4f, 0x3a, 0x7e, 0xa7, 0xce, 0xee, 0x27, 0x3d, 0xb6, 0xb5, 0xfe, 0x94, 0x8b, 0xaf, 0x1c, 0x6f, + 0x8e, 0x24, 0x33, 0x94, 0xce, 0xb4, 0xdd, 0xd3, 0x73, 0x85, 0xbc, 0x1d, 0x9c, 0xd9, 0xd6, 0xe3, + 0x27, 0x1f, 0xca, 0xc3, 0xfb, 0x15, 0x04, 0x76, 0xcf, 0xec, 0xc7, 0x4f, 0x3e, 0x9c, 0x96, 0xa4, + 0xe5, 0xd1, 0x7d, 0x4d, 0x92, 0x5e, 0x82, 0x02, 0x5d, 0x59, 0x4a, 0xe1, 0x4b, 0xf4, 0xc1, 0x1e, + 0xc1, 0x92, 0x54, 0xba, 0x2d, 0x19, 0x68, 0x4e, 0x5c, 0xb0, 0x44, 0x67, 0xfb, 0x64, 0x5a, 0x17, + 0x93, 0xc8, 0xfc, 0xb5, 0x02, 0x73, 0x67, 0xf1, 0xfd, 0xb3, 0x35, 0x53, 0x7e, 0x19, 0x7f, 0x5a, + 0x80, 0x8a, 0x36, 0x28, 0xac, 0x0a, 0x25, 0xb3, 0xdd, 0x6d, 0x9b, 0x9f, 0xb5, 0xb7, 0x1a, 0x37, + 0xd8, 0x7d, 0x78, 0xbb, 0xb3, 0xbf, 0x79, 0x60, 0x9a, 0xed, 0xcd, 0x9e, 0x75, 0x60, 0x5a, 0xea, + 0xc6, 0xb3, 0xc3, 0xd6, 0xf3, 0xbd, 0xf6, 0x7e, 0xcf, 0xda, 0x6a, 0xf7, 0x5a, 0x9d, 0xdd, 0x6e, + 0x23, 0xc3, 0x6e, 0x43, 0x33, 0xc6, 0x54, 0xc9, 0xad, 0xbd, 0x83, 0xa3, 0xfd, 0x5e, 0x23, 0xcb, + 0xee, 0xc2, 0xad, 0xed, 0xce, 0x7e, 0x6b, 0xd7, 0x8a, 0x71, 0x36, 0x77, 0x7b, 0x9f, 0x59, 0xed, + 0x5f, 0x3a, 0xec, 0x98, 0xcf, 0x1b, 0xb9, 0x34, 0x84, 0x9d, 0xde, 0xee, 0xa6, 0x2a, 0x21, 0xcf, + 0x6e, 0xc2, 0x32, 0x21, 0x50, 0x16, 0xab, 0x77, 0x70, 0x60, 0x75, 0x0f, 0x0e, 0xf6, 0x1b, 0x05, + 0xb6, 0x00, 0xb5, 0xce, 0xfe, 0x67, 0xad, 0xdd, 0xce, 0x96, 0x65, 0xb6, 0x5b, 0xbb, 0x7b, 0x8d, + 0x39, 0xb6, 0x08, 0xf3, 0xd3, 0x78, 0x45, 0x51, 0x84, 0xc2, 0x3b, 0xd8, 0xef, 0x1c, 0xec, 0x5b, + 0x9f, 0xb5, 0xcd, 0x6e, 0xe7, 0x60, 0xbf, 0x51, 0x62, 0x2b, 0xc0, 0x92, 0x49, 0x3b, 0x7b, 0xad, + 0xcd, 0x46, 0x99, 0x2d, 0xc3, 0x42, 0x12, 0xfe, 0xac, 0xfd, 0xbc, 0x01, 0xac, 0x09, 0x4b, 0xd4, + 0x30, 0x6b, 0xa3, 0xbd, 0x7b, 0xf0, 0xb9, 0xb5, 0xd7, 0xd9, 0xef, 0xec, 0x1d, 0xed, 0x35, 0x2a, + 0x78, 0x91, 0x62, 0xbb, 0x6d, 0x75, 0xf6, 0xbb, 0x47, 0xdb, 0xdb, 0x9d, 0xcd, 0x4e, 0x7b, 0xbf, + 0xd7, 0xa8, 0x52, 0xcd, 0x69, 0x1d, 0xaf, 0x89, 0x0c, 0xf2, 0x34, 0x8a, 0xb5, 0xd5, 0xe9, 0xb6, + 0x36, 0x76, 0xdb, 0x5b, 0x8d, 0x3a, 0xbb, 0x03, 0x37, 0x7b, 0xed, 0xbd, 0xc3, 0x03, 0xb3, 0x65, + 0x3e, 0x57, 0xa7, 0x55, 0xac, 0xed, 0x56, 0x67, 0xf7, 0xc8, 0x6c, 0x37, 0xe6, 0xd9, 0x9b, 0x70, + 0xc7, 0x6c, 0x7f, 0x7a, 0xd4, 0x31, 0xdb, 0x5b, 0xd6, 0xfe, 0xc1, 0x56, 0xdb, 0xda, 0x6e, 0xb7, + 0x7a, 0x47, 0x66, 0xdb, 0xda, 0xeb, 0x74, 0xbb, 0x9d, 0xfd, 0xa7, 0x8d, 0x06, 0x7b, 0x1b, 0xee, + 0x45, 0x28, 0x51, 0x01, 0x53, 0x58, 0x0b, 0xa2, 0x7f, 0x6a, 0x4a, 0xf7, 0xdb, 0xbf, 0xd4, 0xb3, + 0x0e, 0xdb, 0x6d, 0xb3, 0xc1, 0xd8, 0x1a, 0xac, 0xc4, 0xd5, 0x53, 0x05, 0xb2, 0xee, 0x45, 0x91, + 0x76, 0xd8, 0x36, 0xf7, 0x5a, 0xfb, 0x62, 0x82, 0x13, 0x69, 0x4b, 0xa2, 0xd9, 0x71, 0xda, 0x74, + 0xb3, 0x97, 0x19, 0x83, 0xba, 0x36, 0x2b, 0xdb, 0x2d, 0xb3, 0xb1, 0xc2, 0xe6, 0xa1, 0xb2, 0x77, + 0x78, 0x68, 0xf5, 0x3a, 0x7b, 0xed, 0x83, 0xa3, 0x5e, 0x63, 0x95, 0x2d, 0x43, 0xa3, 0xb3, 0xdf, + 0x6b, 0x9b, 0x62, 0xae, 0x55, 0xd6, 0xff, 0x51, 0x64, 0x4b, 0x30, 0xaf, 0x5a, 0xaa, 0xa0, 0x7f, + 0x51, 0x64, 0xab, 0xc0, 0x8e, 0xf6, 0xcd, 0x76, 0x6b, 0x4b, 0x0c, 0x5c, 0x94, 0xf0, 0x3f, 0x8b, + 0xd2, 0x09, 0xf4, 0x87, 0xb9, 0x68, 0xb3, 0x8e, 0xa3, 0x2a, 0x92, 0xb7, 0x91, 0x57, 0xb5, 0x5b, + 0xc4, 0x5f, 0xf5, 0x4e, 0x88, 0xa6, 0x5a, 0xe5, 0x66, 0x54, 0xab, 0x19, 0xdd, 0xbd, 0xa6, 0xcb, + 0x7e, 0x6f, 0x41, 0x6d, 0x44, 0x37, 0x93, 0xcb, 0x1b, 0x88, 0x41, 0x86, 0x18, 0x11, 0x90, 0xae, + 0x1f, 0x9e, 0x79, 0x28, 0xa3, 0x30, 0xfb, 0x50, 0x46, 0x9a, 0x7c, 0x3f, 0x97, 0x26, 0xdf, 0x3f, + 0x80, 0x05, 0x62, 0x4d, 0x8e, 0xeb, 0x8c, 0x94, 0xd6, 0x4c, 0x52, 0xe0, 0x3c, 0xb2, 0x28, 0x82, + 0x2b, 0x75, 0x42, 0xa9, 0x1c, 0x92, 0x85, 0x14, 0xa5, 0xb6, 0x91, 0xd0, 0x34, 0x88, 0x73, 0x44, + 0x9a, 0x46, 0x54, 0x83, 0x7d, 0x19, 0xd7, 0x50, 0xd1, 0x6a, 0x20, 0x38, 0xd6, 0xf0, 0x00, 0x16, + 0xf8, 0x65, 0xe8, 0xdb, 0x96, 0x37, 0xb6, 0xbf, 0x98, 0xa0, 0x97, 0xda, 0x46, 0x1d, 0xbe, 0x6a, + 0xce, 0x63, 0xc2, 0x01, 0xc2, 0xb7, 0xec, 0xd0, 0x7e, 0xf0, 0x25, 0x54, 0xb4, 0x5b, 0xeb, 0xd9, + 0x2a, 0x2c, 0x7e, 0xde, 0xe9, 0xed, 0xb7, 0xbb, 0x5d, 0xeb, 0xf0, 0x68, 0xe3, 0x59, 0xfb, 0xb9, + 0xb5, 0xd3, 0xea, 0xee, 0x34, 0x6e, 0x88, 0x45, 0xbb, 0xdf, 0xee, 0xf6, 0xda, 0x5b, 0x09, 0x78, + 0x86, 0xbd, 0x01, 0x6b, 0x47, 0xfb, 0x47, 0xdd, 0xf6, 0x96, 0x95, 0x96, 0x2f, 0x2b, 0xa8, 0x54, + 0xa6, 0xa7, 0x64, 0xcf, 0x3d, 0xf8, 0x35, 0xa8, 0x27, 0x0f, 0x6e, 0x33, 0x80, 0xb9, 0xdd, 0xf6, + 0xd3, 0xd6, 0xe6, 0x73, 0xba, 0x6a, 0xb5, 0xdb, 0x6b, 0xf5, 0x3a, 0x9b, 0x96, 0xbc, 0x5a, 0x55, + 0x70, 0x84, 0x0c, 0xab, 0x40, 0xb1, 0xb5, 0xbf, 0xb9, 0x73, 0x60, 0x76, 0x1b, 0x59, 0x76, 0x1b, + 0x56, 0x15, 0xad, 0x6e, 0x1e, 0xec, 0xed, 0x75, 0x7a, 0xc8, 0x0c, 0x7b, 0xcf, 0x0f, 0x05, 0x69, + 0x3e, 0xb0, 0xa1, 0x1c, 0xdf, 0x0d, 0x8b, 0x0c, 0xa6, 0xd3, 0xeb, 0xb4, 0x7a, 0x31, 0x77, 0x6d, + 0xdc, 0x10, 0xfc, 0x2b, 0x06, 0xe3, 0xd5, 0xae, 0x8d, 0x0c, 0x9d, 0x6d, 0x53, 0x40, 0xaa, 0xbd, + 0x91, 0x15, 0x8b, 0x2a, 0x86, 0x6e, 0x1c, 0xf4, 0x44, 0x17, 0xbe, 0x03, 0xf5, 0x64, 0x04, 0x63, + 0xd2, 0x6c, 0xbd, 0x06, 0x2b, 0x1b, 0xed, 0xde, 0xe7, 0xed, 0xf6, 0x3e, 0x8e, 0xce, 0x66, 0x7b, + 0xbf, 0x67, 0xb6, 0x76, 0x3b, 0xbd, 0xe7, 0x8d, 0xcc, 0x83, 0x4f, 0xa0, 0x31, 0xed, 0x2e, 0x4c, + 0xf8, 0x57, 0x5f, 0xe6, 0x88, 0x7d, 0xf0, 0x4f, 0x73, 0x00, 0xf1, 0x31, 0x1a, 0xc1, 0x26, 0xb7, + 0x5a, 0xbd, 0xd6, 0xee, 0x81, 0x98, 0x02, 0xf3, 0xa0, 0x27, 0xb8, 0x9f, 0xd9, 0xfe, 0xb4, 0x71, + 0x23, 0x35, 0xe5, 0xe0, 0xb0, 0xd7, 0xc8, 0x88, 0xd9, 0xa6, 0xee, 0xec, 0x5a, 0xe6, 0xc1, 0x51, + 0x67, 0xff, 0x29, 0x5d, 0x9d, 0x89, 0x3b, 0xc4, 0xd1, 0xe1, 0xb6, 0x79, 0xb0, 0xdf, 0xb3, 0xba, + 0x3b, 0x47, 0xbd, 0x2d, 0xbc, 0x78, 0x73, 0xd3, 0xec, 0x1c, 0x52, 0x99, 0xf9, 0x97, 0x21, 0x88, + 0xa2, 0x0b, 0x82, 0x5e, 0x9e, 0x1e, 0x74, 0xbb, 0x9d, 0x43, 0xeb, 0xd3, 0xa3, 0xb6, 0xd9, 0x69, + 0x77, 0x31, 0xe3, 0x5c, 0x0a, 0x5c, 0xe0, 0x17, 0xc5, 0xbe, 0xd2, 0xdb, 0xfd, 0x4c, 0x32, 0x7e, + 0x81, 0x5a, 0x4a, 0x82, 0x04, 0x56, 0x59, 0x0c, 0xa6, 0xe0, 0x9c, 0x29, 0x25, 0xc3, 0x35, 0x69, + 0x22, 0x5f, 0x45, 0xec, 0x09, 0x33, 0x84, 0x84, 0xd9, 0xaa, 0xe9, 0x49, 0x22, 0x17, 0x6e, 0x17, + 0xd1, 0xe6, 0xba, 0xb5, 0x65, 0x62, 0x86, 0xfa, 0x0c, 0x54, 0xe0, 0xce, 0x8b, 0x89, 0x12, 0xac, + 0x55, 0xa0, 0x34, 0xd4, 0x87, 0x48, 0x59, 0x78, 0xfc, 0x9b, 0x39, 0xa8, 0xd3, 0x91, 0x46, 0x7a, + 0xf0, 0x90, 0xfb, 0x6c, 0x0f, 0x8a, 0xf2, 0xe5, 0x4c, 0xb6, 0x1c, 0xdd, 0x6a, 0xa8, 0xbf, 0xd5, + 0xb9, 0xb6, 0x32, 0x0d, 0x96, 0xa2, 0xe4, 0xe2, 0x5f, 0xf9, 0x93, 0xff, 0xfe, 0x77, 0xb2, 0x35, + 0x56, 0x79, 0x78, 0xfe, 0xc1, 0xc3, 0x53, 0xee, 0x06, 0xa2, 0x8c, 0x5f, 0x01, 0x88, 0xdf, 0x83, + 0x64, 0x4d, 0xed, 0x1a, 0x85, 0xc4, 0x4b, 0x90, 0x6b, 0x37, 0x53, 0x52, 0x64, 0xb9, 0x37, 0xb1, + 0xdc, 0x45, 0xa3, 0x2e, 0xca, 0x75, 0x5c, 0x27, 0xa4, 0xb7, 0x21, 0x3f, 0xce, 0x3c, 0x60, 0x03, + 0xa8, 0xea, 0x2f, 0x35, 0x32, 0x25, 0xe5, 0xa5, 0xbc, 0x35, 0xb9, 0x76, 0x2b, 0x35, 0x4d, 0xc9, + 0xcf, 0x58, 0xc7, 0xb2, 0xd1, 0x10, 0x75, 0x4c, 0x10, 0x23, 0xae, 0x65, 0x48, 0x1a, 0x45, 0xfc, + 0x20, 0x23, 0xbb, 0xad, 0xc9, 0x84, 0x33, 0xcf, 0x41, 0xae, 0xdd, 0xb9, 0x26, 0x55, 0xd6, 0x75, + 0x07, 0xeb, 0x5a, 0x35, 0x98, 0xa8, 0xab, 0x8f, 0x38, 0xea, 0x39, 0xc8, 0x8f, 0x33, 0x0f, 0x1e, + 0xff, 0xfb, 0xf7, 0xa0, 0x1c, 0x85, 0x38, 0xb3, 0x5f, 0x87, 0x5a, 0xe2, 0xcc, 0x29, 0x53, 0xdd, + 0x48, 0x3b, 0xa2, 0xba, 0x76, 0x3b, 0x3d, 0x51, 0x56, 0xfc, 0x06, 0x56, 0xdc, 0x64, 0x2b, 0xa2, + 0x62, 0x79, 0xa6, 0xf3, 0x21, 0x9e, 0x11, 0xa7, 0x3b, 0x22, 0x5f, 0x68, 0x9a, 0x13, 0x55, 0x76, + 0x7b, 0x5a, 0x9b, 0x49, 0xd4, 0x76, 0xe7, 0x9a, 0x54, 0x59, 0xdd, 0x6d, 0xac, 0x6e, 0x85, 0x2d, + 0xe9, 0xd5, 0xa9, 0xc8, 0x58, 0xc6, 0xf1, 0x5e, 0x56, 0xfd, 0xbd, 0x42, 0x76, 0x27, 0xbe, 0x45, + 0x33, 0xe5, 0x1d, 0xc3, 0x88, 0x44, 0x66, 0x1f, 0x33, 0x34, 0x9a, 0x58, 0x15, 0x63, 0x38, 0x7d, + 0xfa, 0x73, 0x85, 0xec, 0x18, 0x2a, 0xda, 0x13, 0x3f, 0xec, 0xe6, 0xb5, 0xcf, 0x11, 0xad, 0xad, + 0xa5, 0x25, 0xa5, 0x75, 0x45, 0x2f, 0xff, 0xe1, 0x09, 0xe7, 0xec, 0x97, 0xa1, 0x1c, 0x3d, 0x1c, + 0xc3, 0x56, 0xb5, 0x87, 0x7c, 0xf4, 0x87, 0x6e, 0xd6, 0x9a, 0xb3, 0x09, 0x69, 0xc4, 0xa7, 0x97, + 0x2e, 0x88, 0xef, 0x73, 0xa8, 0x68, 0x8f, 0xc3, 0x44, 0x1d, 0x98, 0x7d, 0x80, 0x26, 0xea, 0x40, + 0xca, 0x5b, 0x32, 0xc6, 0x02, 0x56, 0x51, 0x61, 0x65, 0xa4, 0xef, 0xf0, 0xd2, 0x0b, 0xd8, 0x2e, + 0x2c, 0x4b, 0x2d, 0xf1, 0x98, 0x7f, 0x95, 0x69, 0x48, 0x79, 0x22, 0xf2, 0x51, 0x86, 0x7d, 0x02, + 0x25, 0xf5, 0x06, 0x10, 0x5b, 0x49, 0x7f, 0xcb, 0x68, 0x6d, 0x75, 0x06, 0x2e, 0x55, 0xba, 0xe7, + 0x00, 0xf1, 0x4b, 0x34, 0x11, 0x93, 0x98, 0x79, 0xd9, 0x26, 0xa2, 0x80, 0xd9, 0x67, 0x6b, 0x8c, + 0x15, 0xec, 0x60, 0x83, 0x21, 0x93, 0x70, 0xf9, 0x85, 0xba, 0x3c, 0xfb, 0x87, 0x50, 0xd1, 0x1e, + 0xa3, 0x89, 0x86, 0x6f, 0xf6, 0x21, 0x9b, 0x68, 0xf8, 0x52, 0xde, 0xae, 0x31, 0xd6, 0xb0, 0xf4, + 0x25, 0x63, 0x5e, 0x94, 0x2e, 0xc4, 0x44, 0x29, 0xae, 0x89, 0x09, 0x3a, 0x83, 0x5a, 0xe2, 0xc5, + 0x99, 0x68, 0x85, 0xa6, 0xbd, 0x67, 0x13, 0xad, 0xd0, 0xd4, 0x47, 0x6a, 0x14, 0x9d, 0x19, 0x0b, + 0xa2, 0x1e, 0xba, 0x3f, 0x4b, 0xab, 0xe9, 0x07, 0x50, 0xd1, 0x5e, 0x8f, 0x89, 0xfa, 0x32, 0xfb, + 0x50, 0x4d, 0xd4, 0x97, 0xb4, 0xc7, 0x66, 0x96, 0xb0, 0x8e, 0xba, 0x81, 0xa4, 0x80, 0xd7, 0xff, + 0x8a, 0xb2, 0x7f, 0x1d, 0xea, 0xc9, 0x07, 0x65, 0xa2, 0xb5, 0x9f, 0xfa, 0x32, 0x4d, 0xb4, 0xf6, + 0xaf, 0x79, 0x85, 0x46, 0x92, 0xf4, 0x83, 0xc5, 0xa8, 0x92, 0x87, 0x3f, 0x96, 0x87, 0xb5, 0xbe, + 0x64, 0x9f, 0x0a, 0x06, 0x27, 0x6f, 0x9f, 0x66, 0xab, 0x1a, 0xd5, 0xea, 0xd7, 0x58, 0x47, 0xeb, + 0x65, 0xe6, 0xa2, 0xea, 0x24, 0x31, 0x63, 0xe1, 0xec, 0x29, 0x2c, 0x46, 0xc4, 0x1c, 0x5d, 0x27, + 0x1d, 0x44, 0x7d, 0x48, 0xbd, 0xb4, 0x7a, 0xad, 0x31, 0x9d, 0xfa, 0x28, 0x43, 0xdb, 0x1f, 0x5e, + 0xe2, 0xab, 0x6d, 0x7f, 0xfa, 0x8d, 0xd2, 0xda, 0xf6, 0x97, 0xb8, 0xeb, 0x77, 0x7a, 0xfb, 0x0b, + 0x1d, 0x51, 0x86, 0x0b, 0xf3, 0xd3, 0x97, 0x3b, 0xdf, 0xb9, 0xee, 0x32, 0x0c, 0x2a, 0xfe, 0x8d, + 0x97, 0xdf, 0x95, 0x91, 0x64, 0x45, 0x8a, 0x9b, 0x3e, 0x94, 0xb1, 0x41, 0xec, 0x57, 0xa1, 0xaa, + 0x3f, 0x42, 0xc1, 0x74, 0x9e, 0x30, 0x5d, 0xd3, 0xad, 0xd4, 0xb4, 0x24, 0x95, 0xb0, 0xaa, 0x5e, + 0x0d, 0xfb, 0x0c, 0x56, 0xa2, 0x61, 0xd6, 0x6f, 0x73, 0x08, 0xd8, 0xdd, 0x94, 0x3b, 0x1e, 0x12, + 0x83, 0x7d, 0xf3, 0xda, 0x4b, 0x20, 0x1e, 0x65, 0x04, 0xf5, 0x25, 0x2f, 0xdc, 0x8f, 0x77, 0x9e, + 0xb4, 0x77, 0x06, 0xe2, 0x9d, 0x27, 0xf5, 0x96, 0x7e, 0x45, 0x7d, 0x6c, 0x31, 0x31, 0x46, 0x14, + 0x35, 0xcd, 0x7e, 0x00, 0xf3, 0xda, 0x55, 0x15, 0xdd, 0x2b, 0xb7, 0x1f, 0xad, 0xa4, 0xd9, 0x6b, + 0x5b, 0xd7, 0xd2, 0xec, 0xaa, 0xc6, 0x2a, 0x96, 0xbf, 0x60, 0x24, 0x06, 0x47, 0xac, 0xa2, 0x4d, + 0xa8, 0xe8, 0xd7, 0x60, 0xbc, 0xa4, 0xdc, 0x55, 0x2d, 0x49, 0xbf, 0x21, 0xf4, 0x51, 0x86, 0xed, + 0x42, 0x63, 0xfa, 0xd2, 0xba, 0x88, 0xa7, 0xa4, 0x5d, 0xf4, 0xb7, 0x36, 0x95, 0x98, 0xb8, 0xea, + 0x8e, 0x1d, 0xd2, 0xb9, 0x9b, 0xe8, 0x3d, 0x45, 0xcf, 0x9f, 0xde, 0xd5, 0x93, 0xef, 0x2c, 0x46, + 0xa5, 0xa5, 0xbd, 0xb0, 0x79, 0x3f, 0xf3, 0x28, 0xc3, 0x7e, 0x3b, 0x03, 0xd5, 0xc4, 0xa5, 0x4d, + 0x89, 0x93, 0x0d, 0x53, 0xfd, 0x6c, 0xea, 0x69, 0x7a, 0x47, 0x0d, 0x13, 0x07, 0x71, 0xf7, 0xc1, + 0xf7, 0x13, 0x93, 0xf4, 0xe3, 0x84, 0x5b, 0x72, 0x7d, 0xfa, 0xc1, 0xc5, 0x2f, 0xa7, 0x11, 0xf4, + 0x8b, 0x80, 0xbf, 0x7c, 0x94, 0x61, 0xff, 0x22, 0x03, 0xf5, 0x64, 0xbc, 0x41, 0xd4, 0xdd, 0xd4, + 0xc8, 0x86, 0x88, 0x94, 0xae, 0x09, 0x52, 0xf8, 0x01, 0xb6, 0xb2, 0xf7, 0xc0, 0x4c, 0xb4, 0x52, + 0x3e, 0x15, 0xf1, 0xd3, 0xb5, 0x96, 0xfd, 0x22, 0xbd, 0x6f, 0xac, 0x22, 0xcd, 0xd8, 0xec, 0x7b, + 0xb8, 0x11, 0xf9, 0xe9, 0xaf, 0xc7, 0x1a, 0xb9, 0xdf, 0xc8, 0x66, 0x70, 0x26, 0x7e, 0x48, 0xaf, + 0x0b, 0xaa, 0xc0, 0x24, 0x41, 0xca, 0xaf, 0x5d, 0xc8, 0xdb, 0xd8, 0xb1, 0x37, 0x8c, 0x9b, 0x89, + 0x8e, 0x4d, 0x4b, 0x1f, 0x2d, 0x6a, 0xa2, 0x7c, 0x01, 0x36, 0xde, 0x3e, 0x67, 0x5e, 0x85, 0x4d, + 0xad, 0x04, 0x1b, 0x39, 0xa2, 0x46, 0x4a, 0xf4, 0xc4, 0x7a, 0x7b, 0xcd, 0x62, 0x8c, 0x07, 0xd8, + 0xd6, 0xb7, 0x8d, 0xbb, 0xd7, 0xb6, 0xf5, 0x21, 0x06, 0x10, 0x88, 0x16, 0x1f, 0x02, 0xc4, 0xe1, + 0xa0, 0x6c, 0x2a, 0x28, 0x31, 0xe2, 0x42, 0xb3, 0x11, 0xa3, 0xc9, 0x45, 0xad, 0x62, 0x17, 0x45, + 0x89, 0xbf, 0x4c, 0x3c, 0x35, 0x0a, 0x97, 0xd4, 0x45, 0xb0, 0x64, 0xe4, 0x66, 0x42, 0x04, 0x9b, + 0x2e, 0x3f, 0xc1, 0x51, 0xa3, 0xd8, 0xc8, 0x23, 0xa8, 0xed, 0x7a, 0xde, 0x8b, 0xc9, 0x38, 0x3a, + 0x82, 0x90, 0x8c, 0x17, 0xda, 0xb1, 0x83, 0xb3, 0xb5, 0xa9, 0x5e, 0x18, 0xf7, 0xb0, 0xa8, 0x35, + 0xd6, 0xd4, 0x8a, 0x7a, 0xf8, 0xe3, 0x38, 0x06, 0xf5, 0x4b, 0x66, 0xc3, 0x42, 0xc4, 0xa8, 0xe3, + 0x38, 0xcf, 0x64, 0x31, 0x09, 0xf6, 0x3c, 0x5d, 0x45, 0x42, 0x57, 0x50, 0xad, 0x7d, 0x18, 0xa8, + 0x32, 0x1f, 0x65, 0xd8, 0x21, 0x54, 0xb7, 0x78, 0x1f, 0xef, 0xb0, 0xc0, 0xd8, 0x98, 0xc5, 0x44, + 0x9c, 0x05, 0x05, 0xd5, 0xac, 0xd5, 0x12, 0xc0, 0xe4, 0xe6, 0x35, 0xb6, 0xaf, 0x7c, 0xfe, 0xc5, + 0xc3, 0x1f, 0xcb, 0xa8, 0x9b, 0x2f, 0xd5, 0xe6, 0x15, 0x47, 0x60, 0xe9, 0x12, 0x40, 0x32, 0x8c, + 0x29, 0xb1, 0x79, 0xcd, 0x84, 0x31, 0x25, 0x86, 0x3a, 0x8a, 0xb7, 0x1a, 0xc2, 0xc2, 0x4c, 0xe4, + 0x53, 0xb4, 0x6f, 0x5d, 0x17, 0x2f, 0xb5, 0x76, 0xef, 0x7a, 0x84, 0x64, 0x6d, 0x0f, 0x92, 0xb5, + 0x75, 0xa1, 0x46, 0x57, 0xfd, 0x1e, 0x73, 0x3a, 0xcd, 0x3a, 0x75, 0x15, 0x94, 0x7e, 0x54, 0x76, + 0x7a, 0x97, 0xc1, 0xb4, 0xa4, 0x98, 0x83, 0xe7, 0x19, 0xd9, 0x09, 0xbe, 0x6f, 0xa1, 0x1d, 0x1f, + 0x8d, 0x88, 0x71, 0xf6, 0x48, 0x6b, 0x44, 0x8c, 0x29, 0xa7, 0x4d, 0x95, 0x0e, 0xca, 0x96, 0xa3, + 0xb2, 0x1f, 0xba, 0xde, 0x80, 0x8f, 0x64, 0xa9, 0xbf, 0x0c, 0x95, 0xa7, 0x3c, 0x54, 0xe7, 0x35, + 0x23, 0x81, 0x7e, 0xea, 0x00, 0xe7, 0x5a, 0xca, 0x29, 0xdb, 0x24, 0x6d, 0x52, 0xc9, 0x7c, 0x70, + 0xca, 0x89, 0x13, 0x5a, 0xce, 0xe0, 0x4b, 0xf6, 0x4b, 0x58, 0x78, 0x74, 0x3b, 0xc1, 0x8a, 0xd6, + 0x4c, 0xbd, 0xf0, 0xf9, 0x29, 0x78, 0x5a, 0xc9, 0xa2, 0xcd, 0x9a, 0x60, 0xe9, 0x42, 0x45, 0xbb, + 0xc5, 0x24, 0x1a, 0x9b, 0xd9, 0x5b, 0x6b, 0xa2, 0xb1, 0x49, 0xb9, 0xf4, 0xc4, 0xb8, 0x8f, 0xf5, + 0x18, 0xec, 0x5e, 0x5c, 0x0f, 0x5d, 0x74, 0x12, 0xd7, 0xf4, 0xf0, 0xc7, 0xf6, 0x28, 0xfc, 0x92, + 0x7d, 0x4e, 0xd3, 0xa1, 0x9d, 0x47, 0x8d, 0x35, 0x94, 0xe9, 0xa3, 0xab, 0xd1, 0x60, 0x69, 0x49, + 0x49, 0xad, 0x85, 0xaa, 0x42, 0xb1, 0xf1, 0x09, 0x40, 0x37, 0xf4, 0xc6, 0x5b, 0x36, 0x1f, 0x79, + 0x6e, 0xcc, 0xd3, 0xe3, 0x13, 0x92, 0x31, 0x9f, 0xd4, 0x8e, 0x49, 0xb2, 0xcf, 0x35, 0x95, 0x2e, + 0x71, 0x92, 0x5a, 0x11, 0xf1, 0xb5, 0x87, 0x28, 0xa3, 0x01, 0x49, 0x39, 0x48, 0xf9, 0x28, 0xc3, + 0x5a, 0x00, 0x71, 0x88, 0x5d, 0xa4, 0xa0, 0xcd, 0x44, 0xef, 0x45, 0xec, 0x35, 0x25, 0x1e, 0xef, + 0x10, 0xca, 0x71, 0x6c, 0xd2, 0x6a, 0x7c, 0x29, 0x53, 0x22, 0x92, 0x29, 0x12, 0x17, 0x66, 0xe2, + 0x82, 0x8c, 0x06, 0x0e, 0x15, 0xb0, 0x92, 0x18, 0xaa, 0x13, 0xce, 0x03, 0xe6, 0xc0, 0x22, 0x35, + 0x30, 0x92, 0xcd, 0xf0, 0x64, 0x5f, 0xf4, 0xaa, 0xcc, 0x6c, 0x88, 0x4e, 0xc4, 0x35, 0x52, 0x03, + 0x4d, 0x12, 0x76, 0x26, 0x41, 0xad, 0x74, 0xaa, 0x50, 0x6c, 0x01, 0x23, 0x58, 0x98, 0x89, 0x65, + 0x88, 0x58, 0xc7, 0x75, 0xc1, 0x29, 0x11, 0xeb, 0xb8, 0x36, 0x0c, 0xc2, 0x58, 0xc6, 0x2a, 0xe7, + 0x0d, 0x40, 0xbd, 0xf2, 0xc2, 0x09, 0xfb, 0x67, 0xa2, 0xba, 0xdf, 0xcb, 0xc0, 0x62, 0x4a, 0xb4, + 0x02, 0x7b, 0x53, 0x99, 0x28, 0xae, 0x8d, 0x64, 0x58, 0x4b, 0xf5, 0x6a, 0x1b, 0x5d, 0xac, 0x67, + 0x8f, 0x3d, 0x4b, 0x6c, 0xa0, 0xe4, 0x54, 0x96, 0x2b, 0xf3, 0xa5, 0x12, 0x4c, 0xaa, 0xf8, 0xf2, + 0x05, 0xac, 0x52, 0x43, 0x5a, 0xc3, 0xe1, 0x94, 0xc7, 0xfd, 0x0d, 0xad, 0x15, 0x29, 0x51, 0x04, + 0x09, 0x65, 0x20, 0x19, 0x49, 0x70, 0x8d, 0xec, 0x4e, 0x4d, 0x65, 0x13, 0x68, 0x4c, 0x7b, 0xb2, + 0xd9, 0xf5, 0x65, 0xad, 0xdd, 0x4d, 0x28, 0xdb, 0x29, 0xde, 0xef, 0xaf, 0x61, 0x65, 0x77, 0x8d, + 0xb5, 0xb4, 0x71, 0x21, 0xfd, 0x5b, 0xcc, 0xc7, 0xff, 0x1f, 0xb9, 0xdd, 0xa7, 0xfa, 0x79, 0x37, + 0xba, 0x47, 0x3f, 0x3d, 0x48, 0x20, 0x52, 0xf7, 0xd3, 0xbd, 0xf6, 0xef, 0x60, 0xf5, 0xf7, 0x8c, + 0x5b, 0x69, 0xd5, 0xfb, 0x94, 0x85, 0x14, 0xff, 0xd5, 0xe9, 0x75, 0xad, 0x5a, 0x70, 0x2f, 0x6d, + 0xbe, 0xaf, 0x55, 0xbc, 0xa6, 0xc6, 0xfa, 0x06, 0xca, 0x90, 0x55, 0xdd, 0xcd, 0x1e, 0x2d, 0x9f, + 0x14, 0x7f, 0x7e, 0xb4, 0x7c, 0xd2, 0xfc, 0xf2, 0x49, 0xf9, 0x49, 0x79, 0xe4, 0x3f, 0xce, 0x3c, + 0xd8, 0x78, 0xf7, 0x07, 0x5f, 0x3b, 0x75, 0xc2, 0xb3, 0xc9, 0xf1, 0x7a, 0xdf, 0x1b, 0x3d, 0x1c, + 0x2a, 0xd3, 0xa6, 0x3c, 0xfe, 0xfe, 0x70, 0xe8, 0x0e, 0x1e, 0x62, 0xb1, 0xc7, 0x73, 0x63, 0xdf, + 0x0b, 0xbd, 0x6f, 0xfe, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, 0x24, 0xba, 0xa4, 0x4f, 0x8a, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index ff86b95444..788ad9b688 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -3102,6 +3102,13 @@ message Payment { /// The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. repeated HTLCAttempt htlcs = 14; + + /** + The creation index of this payment. Each payment can be uniquely identified + by this index, which may not strictly increment by 1 for payments made in + older versions of lnd. + */ + uint64 payment_index = 15; } message HTLCAttempt { @@ -3134,14 +3141,46 @@ message ListPaymentsRequest { /** If true, then return payments that have not yet fully completed. This means that pending payments, as well as failed payments will show up if this - field is set to True. + field is set to true. This flag doesn't change the meaning of the indices, + which are tied to individual payments. */ bool include_incomplete = 1; + + /** + The index of a payment that will be used as either the start or end of a + query to determine which payments should be returned in the response. The + index_offset is exclusive. In the case of a zero index_offset, the query + will start with the oldest payment when paginating forwards, or will end + with the most recent payment when paginating backwards. + */ + uint64 index_offset = 2; + + /// The maximal number of payments returned in the response to this query. + uint64 max_payments = 3; + + /** + If set, the payments returned will result from seeking backwards from the + specified index offset. This can be used to paginate backwards. The order + of the returned payments is always oldest first (ascending index order). + */ + bool reversed = 4; } message ListPaymentsResponse { /// The list of payments repeated Payment payments = 1; + + /** + The index of the first item in the set of returned payments. This can be + used as the index_offset to continue seeking backwards in the next request. + */ + uint64 first_index_offset = 2; + + /** + The index of the last item in the set of returned payments. This can be used + as the index_offset to continue seeking forwards in the next request. + */ + uint64 last_index_offset = 3; } message DeleteAllPaymentsRequest { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 6e68328db5..4b34cfadfa 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1155,7 +1155,31 @@ "parameters": [ { "name": "include_incomplete", - "description": "*\nIf true, then return payments that have not yet fully completed. This means\nthat pending payments, as well as failed payments will show up if this\nfield is set to True.", + "description": "*\nIf true, then return payments that have not yet fully completed. This means\nthat pending payments, as well as failed payments will show up if this\nfield is set to true. This flag doesn't change the meaning of the indices,\nwhich are tied to individual payments.", + "in": "query", + "required": false, + "type": "boolean", + "format": "boolean" + }, + { + "name": "index_offset", + "description": "*\nThe index of a payment that will be used as either the start or end of a\nquery to determine which payments should be returned in the response. The\nindex_offset is exclusive. In the case of a zero index_offset, the query\nwill start with the oldest payment when paginating forwards, or will end\nwith the most recent payment when paginating backwards.", + "in": "query", + "required": false, + "type": "string", + "format": "uint64" + }, + { + "name": "max_payments", + "description": "/ The maximal number of payments returned in the response to this query.", + "in": "query", + "required": false, + "type": "string", + "format": "uint64" + }, + { + "name": "reversed", + "description": "*\nIf set, the payments returned will result from seeking backwards from the\nspecified index offset. This can be used to paginate backwards. The order\nof the returned payments is always oldest first (ascending index order).", "in": "query", "required": false, "type": "boolean", @@ -3494,6 +3518,16 @@ "$ref": "#/definitions/lnrpcPayment" }, "title": "/ The list of payments" + }, + "first_index_offset": { + "type": "string", + "format": "uint64", + "description": "*\nThe index of the first item in the set of returned payments. This can be\nused as the index_offset to continue seeking backwards in the next request." + }, + "last_index_offset": { + "type": "string", + "format": "uint64", + "description": "*\nThe index of the last item in the set of returned payments. This can be used\nas the index_offset to continue seeking forwards in the next request." } } }, @@ -3957,6 +3991,11 @@ "$ref": "#/definitions/lnrpcHTLCAttempt" }, "description": "/ The HTLCs made in attempt to settle the payment [EXPERIMENTAL]." + }, + "payment_index": { + "type": "string", + "format": "uint64", + "description": "*\nThe creation index of this payment. Each payment can be uniquely identified\nby this index, which may not strictly increment by 1 for payments made in\nolder versions of lnd." } } }, diff --git a/rpcserver.go b/rpcserver.go index 5bf7ae537f..f13cce5d0c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -5153,26 +5153,37 @@ func marshallTopologyChange(topChange *routing.TopologyChange) *lnrpc.GraphTopol } } -// ListPayments returns a list of all outgoing payments. +// ListPayments returns a list of outgoing payments determined by a paginated +// database query. func (r *rpcServer) ListPayments(ctx context.Context, req *lnrpc.ListPaymentsRequest) (*lnrpc.ListPaymentsResponse, error) { rpcsLog.Debugf("[ListPayments]") - payments, err := r.server.chanDB.FetchPayments() + query := channeldb.PaymentsQuery{ + IndexOffset: req.IndexOffset, + MaxPayments: req.MaxPayments, + Reversed: req.Reversed, + IncludeIncomplete: req.IncludeIncomplete, + } + + // If the maximum number of payments wasn't specified, then we'll + // default to return the maximal number of payments representable. + if req.MaxPayments == 0 { + query.MaxPayments = math.MaxUint64 + } + + paymentsQuerySlice, err := r.server.chanDB.QueryPayments(query) if err != nil { return nil, err } - paymentsResp := &lnrpc.ListPaymentsResponse{} - for _, payment := range payments { - // To keep compatibility with the old API, we only return - // non-suceeded payments if requested. - if payment.Status != channeldb.StatusSucceeded && - !req.IncludeIncomplete { - continue - } + paymentsResp := &lnrpc.ListPaymentsResponse{ + LastIndexOffset: paymentsQuerySlice.LastIndexOffset, + FirstIndexOffset: paymentsQuerySlice.FirstIndexOffset, + } + for _, payment := range paymentsQuerySlice.Payments { // Fetch the payment's route and preimage. If no HTLC was // successful, an empty route and preimage will be used. var ( @@ -5231,6 +5242,7 @@ func (r *rpcServer) ListPayments(ctx context.Context, PaymentRequest: string(payment.Info.PaymentRequest), Status: status, Htlcs: htlcs, + PaymentIndex: payment.SequenceNum, }) } From 97b759796d4dcb9abafb34c38a7d1699f0a71f1c Mon Sep 17 00:00:00 2001 From: bitromortac Date: Fri, 17 Jan 2020 07:49:13 +0100 Subject: [PATCH 416/562] itest: fix comment in list_outgoing_payments test --- lntest/itest/lnd_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 11edadf104..5fefcca2d7 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -4380,7 +4380,7 @@ func testListPayments(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("Can't delete payments at the end: %v", err) } - // Check that there are no payments before test. + // Check that there are no payments after test. listReq := &lnrpc.ListPaymentsRequest{} ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) paymentsResp, err = net.Alice.ListPayments(ctxt, listReq) From 4593cfa6c68dab89388ea230f2ee73d27d637451 Mon Sep 17 00:00:00 2001 From: bitromortac Date: Fri, 17 Jan 2020 07:50:50 +0100 Subject: [PATCH 417/562] lncli: modify listpayments to use queried payments and update cli docs --- cmd/lncli/commands.go | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 79313d252d..86608c5895 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -2171,10 +2171,42 @@ var listPaymentsCommand = cli.Command{ Name: "listpayments", Category: "Payments", Usage: "List all outgoing payments.", + Description: "This command enables the retrieval of payments stored " + + "in the database. Pagination is supported by the usage of " + + "index_offset in combination with the paginate_forwards flag. " + + "Reversed pagination is enabled by default to receive " + + "current payments first. Pagination can be resumed by using " + + "the returned last_index_offset (for forwards order), or " + + "first_index_offset (for reversed order) as the offset_index. ", Flags: []cli.Flag{ cli.BoolFlag{ - Name: "include_incomplete", - Usage: "if set to true, payments still in flight (or failed) will be returned as well", + Name: "include_incomplete", + Usage: "if set to true, payments still in flight (or " + + "failed) will be returned as well, keeping" + + "indices for payments the same as without " + + "the flag", + }, + cli.UintFlag{ + Name: "index_offset", + Usage: "The index of a payment that will be used as " + + "either the start (in forwards mode) or end " + + "(in reverse mode) of a query to determine " + + "which payments should be returned in the " + + "response, where the index_offset is " + + "excluded. If index_offset is set to zero in " + + "reversed mode, the query will end with the " + + "last payment made.", + }, + cli.UintFlag{ + Name: "max_payments", + Usage: "the max number of payments to return, by " + + "default, all completed payments are returned", + }, + cli.BoolFlag{ + Name: "paginate_forwards", + Usage: "if set, payments succeeding the " + + "index_offset will be returned, allowing " + + "forwards pagination", }, }, Action: actionDecorator(listPayments), @@ -2186,6 +2218,9 @@ func listPayments(ctx *cli.Context) error { req := &lnrpc.ListPaymentsRequest{ IncludeIncomplete: ctx.Bool("include_incomplete"), + IndexOffset: uint64(ctx.Uint("index_offset")), + MaxPayments: uint64(ctx.Uint("max_payments")), + Reversed: !ctx.Bool("paginate_forwards"), } payments, err := client.ListPayments(context.Background(), req) From 425b2c712fd961d4bdbb3b9b87a5dad4ecaa4bfd Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:52:50 -0700 Subject: [PATCH 418/562] htlcswitch/switch_test: increase checkHtlcEvents timeout This flakes locally for me on darwin. --- htlcswitch/switch_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index bcd98dcf87..d92a0bf3aa 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -2903,7 +2903,7 @@ func checkHtlcEvents(t *testing.T, events <-chan interface{}, event) } - case <-time.After(time.Second): + case <-time.After(5 * time.Second): t.Fatalf("expected event: %v", expected) } } From 2c3641e91520cb30896f2d7a501901ab50f5c5c5 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:53:15 -0700 Subject: [PATCH 419/562] htlcswitch/link_test: fix preimage assertion This flakes locally for me on darwin. --- htlcswitch/link_test.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 965ecdb2e5..3f86bbfe7e 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -30,6 +30,7 @@ import ( "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnpeer" + "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -4661,15 +4662,24 @@ func checkHasPreimages(t *testing.T, coreLink *channelLink, t.Helper() - for i := range htlcs { - _, ok := coreLink.cfg.PreimageCache.LookupPreimage( - htlcs[i].PaymentHash, - ) - if ok != expOk { - t.Fatalf("expected to find witness: %v, "+ + err := wait.NoError(func() error { + for i := range htlcs { + _, ok := coreLink.cfg.PreimageCache.LookupPreimage( + htlcs[i].PaymentHash, + ) + if ok == expOk { + continue + } + + return fmt.Errorf("expected to find witness: %v, "+ "got %v for hash=%x", expOk, ok, htlcs[i].PaymentHash) } + + return nil + }, 5*time.Second) + if err != nil { + t.Fatalf("unable to find preimages: %v", err) } } From 028345daeab6c305a45f1db247333dbdfdfb1952 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:53:36 -0700 Subject: [PATCH 420/562] htlcswithc/link_test: rm unused arg from generateHtlc Linter started complaining. --- htlcswitch/link_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 3f86bbfe7e..072e7f9e81 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -4504,7 +4504,7 @@ func (h *persistentLinkHarness) restartLink( // gnerateHtlc generates a simple payment from Bob to Alice. func generateHtlc(t *testing.T, coreLink *channelLink, - bobChannel *lnwallet.LightningChannel, id uint64) *lnwire.UpdateAddHTLC { + id uint64) *lnwire.UpdateAddHTLC { t.Helper() @@ -4580,8 +4580,8 @@ func TestChannelLinkNoMoreUpdates(t *testing.T) { ) // Add two HTLCs to Alice's registry, that Bob can pay. - htlc1 := generateHtlc(t, coreLink, bobChannel, 0) - htlc2 := generateHtlc(t, coreLink, bobChannel, 1) + htlc1 := generateHtlc(t, coreLink, 0) + htlc2 := generateHtlc(t, coreLink, 1) ctx := linkTestContext{ t: t, @@ -4711,7 +4711,7 @@ func TestChannelLinkWaitForRevocation(t *testing.T) { numHtlcs := 10 var htlcs []*lnwire.UpdateAddHTLC for i := 0; i < numHtlcs; i++ { - htlc := generateHtlc(t, coreLink, bobChannel, uint64(i)) + htlc := generateHtlc(t, coreLink, uint64(i)) htlcs = append(htlcs, htlc) } @@ -5054,8 +5054,8 @@ func TestChannelLinkCleanupSpuriousResponses(t *testing.T) { coreLink.cfg.HodlMask = hodl.ExitSettle.Mask() // Add two HTLCs to Alice's registry, that Bob can pay. - htlc1 := generateHtlc(t, coreLink, bobChannel, 0) - htlc2 := generateHtlc(t, coreLink, bobChannel, 1) + htlc1 := generateHtlc(t, coreLink, 0) + htlc2 := generateHtlc(t, coreLink, 1) ctx := linkTestContext{ t: t, @@ -5440,7 +5440,7 @@ func TestChannelLinkFail(t *testing.T) { func(t *testing.T, c *channelLink, remoteChannel *lnwallet.LightningChannel) { // Generate an HTLC and send to the link. - htlc1 := generateHtlc(t, c, remoteChannel, 0) + htlc1 := generateHtlc(t, c, 0) ctx := linkTestContext{ t: t, aliceLink: c, @@ -5477,7 +5477,7 @@ func TestChannelLinkFail(t *testing.T) { func(t *testing.T, c *channelLink, remoteChannel *lnwallet.LightningChannel) { // Generate an HTLC and send to the link. - htlc1 := generateHtlc(t, c, remoteChannel, 0) + htlc1 := generateHtlc(t, c, 0) ctx := linkTestContext{ t: t, aliceLink: c, From 77041c131ac4d44b0cfed7a71e3c3f57b21dcbc7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:54:02 -0700 Subject: [PATCH 421/562] htlcswitch/switch_test: add t.Helper() to assertion --- htlcswitch/switch_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index d92a0bf3aa..de9059615e 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -2895,6 +2895,8 @@ func testHtcNotifier(t *testing.T, testOpts []serverOption, iterations int, func checkHtlcEvents(t *testing.T, events <-chan interface{}, expectedEvents []interface{}) { + t.Helper() + for _, expected := range expectedEvents { select { case event := <-events: From 310e20f8b7a7ec4398afdf0affa8f6fcfc4ee197 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:54:29 -0700 Subject: [PATCH 422/562] invoices/invoiceregistry: remove debug spew --- channeldb/invoices.go | 6 ++++++ invoices/invoiceregistry.go | 8 ++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 7287910d7a..f1954bf3b4 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -203,6 +203,12 @@ type ContractTerm struct { Features *lnwire.FeatureVector } +// String returns a human-readable description of the prominent contract terms. +func (c ContractTerm) String() string { + return fmt.Sprintf("amt=%v, expiry=%v, final_cltv_delta=%v", c.Value, + c.Expiry, c.FinalCltvDelta) +} + // Invoice is a payment invoice generated by a payee in order to request // payment for some good or service. The inclusion of invoices within Lightning // creates a payment work flow for merchants very similar to that of the diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 00885edb9d..662a8a82ec 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -7,7 +7,6 @@ import ( "sync/atomic" "time" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lntypes" @@ -503,11 +502,8 @@ func (i *InvoiceRegistry) AddInvoice(invoice *channeldb.Invoice, i.Lock() - log.Debugf("Invoice(%v): added %v", paymentHash, - newLogClosure(func() string { - return spew.Sdump(invoice) - }), - ) + log.Debugf("Invoice(%v): added with terms %v", paymentHash, + invoice.Terms) addIndex, err := i.cdb.AddInvoice(invoice, paymentHash) if err != nil { From 759d7a122f80818c585f09cb3aeeceba71b7e93e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:54:56 -0700 Subject: [PATCH 423/562] htlcswitch/test_utils: add missing return This commit corrects a bug in the testing harness that could cause more than one error to be returned on the error channel. --- htlcswitch/test_utils.go | 1 + 1 file changed, 1 insertion(+) diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index f302ff01c2..0d6f3b4db6 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1365,6 +1365,7 @@ func (n *twoHopNetwork) makeHoldPayment(sendingPeer, receivingPeer lnpeer.Peer, result, ok := <-resultChan if !ok { paymentErr <- fmt.Errorf("shutting down") + return } if result.Error != nil { From e86ddf6ae7b4ade84cea8012d8e722f6a9eab007 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:55:25 -0700 Subject: [PATCH 424/562] htlcswitch/link: remove unused isReProcess argument --- htlcswitch/link.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 6eec8d382d..e12e325d6f 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1109,7 +1109,7 @@ out: l.log.Tracef("reprocessing downstream add update "+ "with payment hash(%x)", msg.PaymentHash[:]) - l.handleDownStreamPkt(packet, true) + l.handleDownstreamPkt(packet) // A message from the switch was just received. This indicates // that the link is an intermediate hop in a multi-hop HTLC @@ -1131,7 +1131,7 @@ out: continue } - l.handleDownStreamPkt(pkt, false) + l.handleDownstreamPkt(pkt) // A message from the connected peer was just received. This // indicates that we have a new incoming HTLC, either directly @@ -1275,13 +1275,13 @@ func (l *channelLink) randomFeeUpdateTimeout() time.Duration { return time.Duration(prand.Int63n(upper-lower) + lower) } -// handleDownStreamPkt processes an HTLC packet sent from the downstream HTLC +// handleDownstreamPkt processes an HTLC packet sent from the downstream HTLC // Switch. Possible messages sent by the switch include requests to forward new // HTLCs, timeout previously cleared HTLCs, and finally to settle currently // cleared HTLCs with the upstream peer. // // TODO(roasbeef): add sync ntfn to ensure switch always has consistent view? -func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) { +func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) { var isSettle bool switch htlc := pkt.htlc.(type) { case *lnwire.UpdateAddHTLC: From 5a057de5c49d59043a7bbaa932d5537c379f4f48 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:55:54 -0700 Subject: [PATCH 425/562] htlcswitch/mailbox: remove errors from AckPacket, Start, Stop A following commits will move/modify callsites of AckPacket, Start, and Stop, none of which use the return value and ultimately cause the linter to complain. However, none of these in-memory operations can fail so we just remove the returned errors altogether. --- htlcswitch/mailbox.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index 633232b91e..04c5cd6d84 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -32,7 +32,7 @@ type MailBox interface { // AckPacket removes a packet from the mailboxes in-memory replay // buffer. This will prevent a packet from being delivered after a link // restarts if the switch has remained online. - AckPacket(CircuitKey) error + AckPacket(CircuitKey) // MessageOutBox returns a channel that any new messages ready for // delivery will be sent on. @@ -50,10 +50,10 @@ type MailBox interface { // Start starts the mailbox and any goroutines it needs to operate // properly. - Start() error + Start() // Stop signals the mailbox and its goroutines for a graceful shutdown. - Stop() error + Stop() } // memoryMailBox is an implementation of the MailBox struct backed by purely @@ -120,13 +120,12 @@ const ( // Start starts the mailbox and any goroutines it needs to operate properly. // // NOTE: This method is part of the MailBox interface. -func (m *memoryMailBox) Start() error { +func (m *memoryMailBox) Start() { m.started.Do(func() { m.wg.Add(2) go m.mailCourier(wireCourier) go m.mailCourier(pktCourier) }) - return nil } // ResetMessages blocks until all buffered wire messages are cleared. @@ -180,19 +179,17 @@ func (m *memoryMailBox) signalUntilReset(cType courierType, // queue of packets to be delivered. // // NOTE: It is safe to call this method multiple times for the same circuit key. -func (m *memoryMailBox) AckPacket(inKey CircuitKey) error { +func (m *memoryMailBox) AckPacket(inKey CircuitKey) { m.pktCond.L.Lock() entry, ok := m.pktIndex[inKey] if !ok { m.pktCond.L.Unlock() - return nil + return } m.htlcPkts.Remove(entry) delete(m.pktIndex, inKey) m.pktCond.L.Unlock() - - return nil } // HasPacket queries the packets for a circuit key, this is used to drop packets @@ -208,14 +205,13 @@ func (m *memoryMailBox) HasPacket(inKey CircuitKey) bool { // Stop signals the mailbox and its goroutines for a graceful shutdown. // // NOTE: This method is part of the MailBox interface. -func (m *memoryMailBox) Stop() error { +func (m *memoryMailBox) Stop() { m.stopped.Do(func() { close(m.quit) m.wireCond.Signal() m.pktCond.Signal() }) - return nil } // mailCourier is a dedicated goroutine whose job is to reliably deliver From 68d1753dcbff3fba4a28a7eaa0660869a4e755cf Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:56:22 -0700 Subject: [PATCH 426/562] htlcswitch/test_utils: send htlcs before waiting for result This commit is preparation for the test added in the subsequent commit. We modify makeHoldPayment to return any failures direectly when trying to add an HTLC to the switch. This lets us know that the HTLC was indeed sent without failure when the method returns. --- htlcswitch/test_utils.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index 0d6f3b4db6..c997c4f905 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1345,15 +1345,13 @@ func (n *twoHopNetwork) makeHoldPayment(sendingPeer, receivingPeer lnpeer.Peer, } // Send payment and expose err channel. - go func() { - err := sender.htlcSwitch.SendHTLC( - firstHop, pid, htlc, - ) - if err != nil { - paymentErr <- err - return - } + err = sender.htlcSwitch.SendHTLC(firstHop, pid, htlc) + if err != nil { + paymentErr <- err + return paymentErr + } + go func() { resultChan, err := sender.htlcSwitch.GetPaymentResult( pid, rhash, newMockDeobfuscator(), ) From f50649d21ba76f87ee76b08af00bc2facc99ace7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 7 Apr 2020 11:56:47 -0700 Subject: [PATCH 427/562] htlcswitch/link: remove overflow queue This commit removes the overflowQueue from the link. We do so in order to promote better UX for senders, so that HTLCs are failed faster when the commitment is full. This gives the sender the opportunity to try another, more open path, rather than perceive the HTLC as being stuck. At the same time, we remove the total number of active goroutines in lnd by a factor of N where N is the number of active channels. --- htlcswitch/link.go | 228 +++++++------------ htlcswitch/link_test.go | 461 +++++++++------------------------------ htlcswitch/queue.go | 208 ------------------ htlcswitch/queue_test.go | 64 ------ lntest/itest/lnd_test.go | 45 ++-- 5 files changed, 196 insertions(+), 810 deletions(-) delete mode 100644 htlcswitch/queue.go delete mode 100644 htlcswitch/queue_test.go diff --git a/htlcswitch/link.go b/htlcswitch/link.go index e12e325d6f..b8a50eeab6 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -19,7 +19,6 @@ import ( "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch/hodl" "github.com/lightningnetwork/lnd/htlcswitch/hop" - "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lntypes" @@ -327,10 +326,6 @@ type channelLink struct { // which may affect behaviour of the service. cfg ChannelLinkConfig - // overflowQueue is used to store the htlc add updates which haven't - // been processed because of the commitment transaction overflow. - overflowQueue *packetQueue - // mailBox is the main interface between the outside world and the // link. All incoming messages will be sent over this mailBox. Messages // include new updates from our connected peer, and new packets to be @@ -395,12 +390,11 @@ func NewChannelLink(cfg ChannelLinkConfig, channel: channel, shortChanID: channel.ShortChanID(), // TODO(roasbeef): just do reserve here? - overflowQueue: newPacketQueue(input.MaxHTLCNumber / 2), - htlcUpdates: make(chan *contractcourt.ContractUpdate), - hodlMap: make(map[channeldb.CircuitKey]hodlHtlc), - hodlQueue: queue.NewConcurrentQueue(10), - log: build.NewPrefixLog(logPrefix, log), - quit: make(chan struct{}), + htlcUpdates: make(chan *contractcourt.ContractUpdate), + hodlMap: make(map[channeldb.CircuitKey]hodlHtlc), + hodlQueue: queue.NewConcurrentQueue(10), + log: build.NewPrefixLog(logPrefix, log), + quit: make(chan struct{}), } } @@ -436,7 +430,6 @@ func (l *channelLink) Start() error { } l.mailBox.ResetMessages() - l.overflowQueue.Start() l.hodlQueue.Start() // Before launching the htlcManager messages, revert any circuits that @@ -511,7 +504,6 @@ func (l *channelLink) Stop() { } l.updateFeeTimer.Stop() - l.overflowQueue.Stop() l.hodlQueue.Stop() close(l.quit) @@ -1100,37 +1092,10 @@ out: break out } - // A packet that previously overflowed the commitment - // transaction is now eligible for processing once again. So - // we'll attempt to re-process the packet in order to allow it - // to continue propagating within the network. - case packet := <-l.overflowQueue.outgoingPkts: - msg := packet.htlc.(*lnwire.UpdateAddHTLC) - l.log.Tracef("reprocessing downstream add update "+ - "with payment hash(%x)", msg.PaymentHash[:]) - - l.handleDownstreamPkt(packet) - // A message from the switch was just received. This indicates // that the link is an intermediate hop in a multi-hop HTLC // circuit. case pkt := <-l.downstream: - // If we have non empty processing queue then we'll add - // this to the overflow rather than processing it - // directly. Once an active HTLC is either settled or - // failed, then we'll free up a new slot. - htlc, ok := pkt.htlc.(*lnwire.UpdateAddHTLC) - if ok && l.overflowQueue.Length() != 0 { - l.log.Infof("downstream htlc add update with "+ - "payment hash(%x) have been added to "+ - "reprocessing queue, pend_updates=%v", - htlc.PaymentHash[:], - l.channel.PendingLocalUpdateCount()) - - l.overflowQueue.AddPkt(pkt) - continue - } - l.handleDownstreamPkt(pkt) // A message from the connected peer was just received. This @@ -1301,109 +1266,89 @@ func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) { openCircuitRef := pkt.inKey() index, err := l.channel.AddHTLC(htlc, &openCircuitRef) if err != nil { - switch err { - - // The channels spare bandwidth is fully allocated, so - // we'll put this HTLC into the overflow queue. - case lnwallet.ErrMaxHTLCNumber: - l.log.Infof("downstream htlc add update with "+ - "payment hash(%x) have been added to "+ - "reprocessing queue, pend_updates: %v", - htlc.PaymentHash[:], - l.channel.PendingLocalUpdateCount()) - - l.overflowQueue.AddPkt(pkt) - return - - // The HTLC was unable to be added to the state - // machine, as a result, we'll signal the switch to - // cancel the pending payment. - default: - l.log.Warnf("unable to handle downstream add "+ - "HTLC: %v", err) + // The HTLC was unable to be added to the state machine, + // as a result, we'll signal the switch to cancel the + // pending payment. + l.log.Warnf("Unable to handle downstream add HTLC: %v", + err) - var ( - localFailure = false - reason lnwire.OpaqueReason - ) + var ( + localFailure = false + reason lnwire.OpaqueReason + ) - // Create a temporary channel failure which we - // will send back to our peer if this is a - // forward, or report to the user if the failed - // payment was locally initiated. - failure := l.createFailureWithUpdate( - func(upd *lnwire.ChannelUpdate) lnwire.FailureMessage { - return lnwire.NewTemporaryChannelFailure( - upd, - ) - }, - ) + // Create a temporary channel failure which we will send + // back to our peer if this is a forward, or report to + // the user if the failed payment was locally initiated. + failure := l.createFailureWithUpdate( + func(upd *lnwire.ChannelUpdate) lnwire.FailureMessage { + return lnwire.NewTemporaryChannelFailure( + upd, + ) + }, + ) - // If the payment was locally initiated (which - // is indicated by a nil obfuscator), we do - // not need to encrypt it back to the sender. - if pkt.obfuscator == nil { - var b bytes.Buffer - err := lnwire.EncodeFailure(&b, failure, 0) - if err != nil { - l.log.Errorf("unable to "+ - "encode failure: %v", err) - l.mailBox.AckPacket(pkt.inKey()) - return - } - reason = lnwire.OpaqueReason(b.Bytes()) - localFailure = true - } else { - // If the packet is part of a forward, - // (identified by a non-nil obfuscator) - // we need to encrypt the error back to - // the source. - var err error - reason, err = pkt.obfuscator.EncryptFirstHop(failure) - if err != nil { - l.log.Errorf("unable to "+ - "obfuscate error: %v", err) - l.mailBox.AckPacket(pkt.inKey()) - return - } + // If the payment was locally initiated (which is + // indicated by a nil obfuscator), we do not need to + // encrypt it back to the sender. + if pkt.obfuscator == nil { + var b bytes.Buffer + err := lnwire.EncodeFailure(&b, failure, 0) + if err != nil { + l.log.Errorf("unable to encode "+ + "failure: %v", err) + l.mailBox.AckPacket(pkt.inKey()) + return } + reason = lnwire.OpaqueReason(b.Bytes()) + localFailure = true + } else { + // If the packet is part of a forward, + // (identified by a non-nil obfuscator) we need + // to encrypt the error back to the source. + var err error + reason, err = pkt.obfuscator.EncryptFirstHop(failure) + if err != nil { + l.log.Errorf("unable to "+ + "obfuscate error: %v", err) + l.mailBox.AckPacket(pkt.inKey()) + return + } + } - // Create a link error containing the temporary - // channel failure and a detail which indicates - // the we failed to add the htlc. - linkError := NewDetailedLinkError( - failure, - OutgoingFailureDownstreamHtlcAdd, - ) + // Create a link error containing the temporary channel + // failure and a detail which indicates the we failed to + // add the htlc. + linkError := NewDetailedLinkError( + failure, OutgoingFailureDownstreamHtlcAdd, + ) - failPkt := &htlcPacket{ - incomingChanID: pkt.incomingChanID, - incomingHTLCID: pkt.incomingHTLCID, - circuit: pkt.circuit, - sourceRef: pkt.sourceRef, - hasSource: true, - localFailure: localFailure, - linkFailure: linkError, - htlc: &lnwire.UpdateFailHTLC{ - Reason: reason, - }, - } + failPkt := &htlcPacket{ + incomingChanID: pkt.incomingChanID, + incomingHTLCID: pkt.incomingHTLCID, + circuit: pkt.circuit, + sourceRef: pkt.sourceRef, + hasSource: true, + localFailure: localFailure, + linkFailure: linkError, + htlc: &lnwire.UpdateFailHTLC{ + Reason: reason, + }, + } - go l.forwardBatch(failPkt) + go l.forwardBatch(failPkt) - // Remove this packet from the link's mailbox, - // this prevents it from being reprocessed if - // the link restarts and resets it mailbox. If - // this response doesn't make it back to the - // originating link, it will be rejected upon - // attempting to reforward the Add to the - // switch, since the circuit was never fully - // opened, and the forwarding package shows it - // as unacknowledged. - l.mailBox.AckPacket(pkt.inKey()) + // Remove this packet from the link's mailbox, this + // prevents it from being reprocessed if the link + // restarts and resets it mailbox. If this response + // doesn't make it back to the originating link, it will + // be rejected upon attempting to reforward the Add to + // the switch, since the circuit was never fully opened, + // and the forwarding package shows it as + // unacknowledged. + l.mailBox.AckPacket(pkt.inKey()) - return - } + return } l.log.Tracef("received downstream htlc: payment_hash=%x, "+ @@ -2179,18 +2124,7 @@ func (l *channelLink) Bandwidth() lnwire.MilliSatoshi { // Get the balance available on the channel for new HTLCs. This takes // the channel reserve into account so HTLCs up to this value won't // violate it. - channelBandwidth := l.channel.AvailableBalance() - - // To compute the total bandwidth, we'll take the current available - // bandwidth, then subtract the overflow bandwidth as we'll eventually - // also need to evaluate those HTLC's once space on the commitment - // transaction is free. - overflowBandwidth := l.overflowQueue.TotalHtlcAmount() - if channelBandwidth < overflowBandwidth { - return 0 - } - - return channelBandwidth - overflowBandwidth + return l.channel.AvailableBalance() } // AttachMailBox updates the current mailbox used by this link, and hooks up @@ -2513,7 +2447,6 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg, // notify the overflow queue that a spare spot has been // freed up within the commitment state. switchPackets = append(switchPackets, settlePacket) - l.overflowQueue.SignalFreeSlot() // A failureCode message for a previously forwarded HTLC has // been received. As a result a new slot will be freed up in @@ -2559,7 +2492,6 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg, // notify the overflow queue that a spare spot has been // freed up within the commitment state. switchPackets = append(switchPackets, failPacket) - l.overflowQueue.SignalFreeSlot() } } diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 072e7f9e81..ffd53a4752 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -7,7 +7,6 @@ import ( "encoding/binary" "fmt" "io" - "math" "net" "reflect" "runtime" @@ -263,141 +262,6 @@ func TestChannelLinkSingleHopPayment(t *testing.T) { } } -// TestChannelLinkBidirectionalOneHopPayments tests the ability of channel -// link to cope with bigger number of payment updates that commitment -// transaction may consist. -func TestChannelLinkBidirectionalOneHopPayments(t *testing.T) { - t.Parallel() - - channels, cleanUp, _, err := createClusterChannels( - btcutil.SatoshiPerBitcoin*3, - btcutil.SatoshiPerBitcoin*5) - if err != nil { - t.Fatalf("unable to create channel: %v", err) - } - defer cleanUp() - - n := newThreeHopNetwork(t, channels.aliceToBob, channels.bobToAlice, - channels.bobToCarol, channels.carolToBob, testStartingHeight) - if err := n.start(); err != nil { - t.Fatal(err) - } - defer n.stop() - bobBandwidthBefore := n.firstBobChannelLink.Bandwidth() - aliceBandwidthBefore := n.aliceChannelLink.Bandwidth() - - debug := false - if debug { - // Log message that alice receives. - n.aliceServer.intersect(createLogFunc("alice", - n.aliceChannelLink.ChanID())) - - // Log message that bob receives. - n.bobServer.intersect(createLogFunc("bob", - n.firstBobChannelLink.ChanID())) - } - - amt := lnwire.NewMSatFromSatoshis(20000) - - htlcAmt, totalTimelock, hopsForwards := generateHops(amt, - testStartingHeight, n.firstBobChannelLink) - _, _, hopsBackwards := generateHops(amt, - testStartingHeight, n.aliceChannelLink) - - type result struct { - err error - start time.Time - number int - sender string - } - - // Send max available payment number in both sides, thereby testing - // the property of channel link to cope with overflowing. - count := 2 * input.MaxHTLCNumber - resultChan := make(chan *result, count) - for i := 0; i < count/2; i++ { - go func(i int) { - r := &result{ - start: time.Now(), - number: i, - sender: "alice", - } - - firstHop := n.firstBobChannelLink.ShortChanID() - _, r.err = makePayment( - n.aliceServer, n.bobServer, firstHop, - hopsForwards, amt, htlcAmt, totalTimelock, - ).Wait(5 * time.Minute) - resultChan <- r - }(i) - } - - for i := 0; i < count/2; i++ { - go func(i int) { - r := &result{ - start: time.Now(), - number: i, - sender: "bob", - } - - firstHop := n.aliceChannelLink.ShortChanID() - _, r.err = makePayment( - n.bobServer, n.aliceServer, firstHop, - hopsBackwards, amt, htlcAmt, totalTimelock, - ).Wait(5 * time.Minute) - resultChan <- r - }(i) - } - - maxDelay := time.Duration(0) - minDelay := time.Duration(math.MaxInt64) - averageDelay := time.Duration(0) - - // Check that alice invoice was settled and bandwidth of HTLC - // links was changed. - for i := 0; i < count; i++ { - select { - case r := <-resultChan: - if r.err != nil { - t.Fatalf("unable to make payment: %v", r.err) - } - - delay := time.Since(r.start) - if delay > maxDelay { - maxDelay = delay - } - - if delay < minDelay { - minDelay = delay - } - averageDelay += delay - - case <-time.After(5 * time.Minute): - t.Fatalf("timeout: (%v/%v)", i+1, count) - } - } - - // TODO(roasbeef): should instead consume async notifications from both - // links - time.Sleep(time.Second * 2) - - // At the end Bob and Alice balances should be the same as previous, - // because they sent the equal amount of money to each other. - if aliceBandwidthBefore != n.aliceChannelLink.Bandwidth() { - t.Fatalf("alice bandwidth shouldn't have changed: expected %v, got %x", - aliceBandwidthBefore, n.aliceChannelLink.Bandwidth()) - } - - if bobBandwidthBefore != n.firstBobChannelLink.Bandwidth() { - t.Fatalf("bob bandwidth shouldn't have changed: expected %v, got %v", - bobBandwidthBefore, n.firstBobChannelLink.Bandwidth()) - } - - t.Logf("Max waiting: %v", maxDelay) - t.Logf("Min waiting: %v", minDelay) - t.Logf("Average waiting: %v", time.Duration(int(averageDelay)/count)) -} - // TestChannelLinkMultiHopPayment checks the ability to send payment over two // hops. In this test we send the payment from Carol to Alice over Bob peer. // (Carol -> Bob -> Alice) and checking that HTLC was settled properly and @@ -536,6 +400,105 @@ func testChannelLinkMultiHopPayment(t *testing.T, } } +// TestChannelLinkCancelFullCommitment tests the ability for links to cancel +// forwarded HTLCs once all of their commitment slots are full. +func TestChannelLinkCancelFullCommitment(t *testing.T) { + t.Parallel() + + channels, cleanUp, _, err := createClusterChannels( + btcutil.SatoshiPerBitcoin*3, + btcutil.SatoshiPerBitcoin*5) + if err != nil { + t.Fatalf("unable to create channel: %v", err) + } + defer cleanUp() + + n := newTwoHopNetwork( + t, channels.aliceToBob, channels.bobToAlice, testStartingHeight, + ) + if err := n.start(); err != nil { + t.Fatal(err) + } + defer n.stop() + + // Fill up the commitment from Alice's side with 20 sat payments. + count := (input.MaxHTLCNumber / 2) + amt := lnwire.NewMSatFromSatoshis(20000) + + htlcAmt, totalTimelock, hopsForwards := generateHops(amt, + testStartingHeight, n.bobChannelLink) + + firstHop := n.aliceChannelLink.ShortChanID() + + // Create channels to buffer the preimage and error channels used in + // making the preliminary payments. + preimages := make([]lntypes.Preimage, count) + aliceErrChan := make(chan chan error, count) + + var wg sync.WaitGroup + for i := 0; i < count; i++ { + preimages[i] = lntypes.Preimage{byte(i >> 8), byte(i)} + + wg.Add(1) + go func(i int) { + defer wg.Done() + + errChan := n.makeHoldPayment( + n.aliceServer, n.bobServer, firstHop, + hopsForwards, amt, htlcAmt, totalTimelock, + preimages[i], + ) + aliceErrChan <- errChan + }(i) + } + + // Wait for Alice to finish filling her commitment. + wg.Wait() + close(aliceErrChan) + + // Now make an additional payment from Alice to Bob, this should be + // canceled because the commitment in this direction is full. + err = <-makePayment( + n.aliceServer, n.bobServer, firstHop, hopsForwards, amt, + htlcAmt, totalTimelock, + ).err + if err == nil { + t.Fatalf("overflow payment should have failed") + } + lerr, ok := err.(*LinkError) + if !ok { + t.Fatalf("expected LinkError, got: %T", err) + } + + msg := lerr.WireMessage() + if _, ok := msg.(*lnwire.FailTemporaryChannelFailure); !ok { + t.Fatalf("expected TemporaryChannelFailure, got: %T", msg) + } + + // Now, settle all htlcs held by bob and clear the commitment of htlcs. + for _, preimage := range preimages { + preimage := preimage + + // It's possible that the HTLCs have not been delivered to the + // invoice registry at this point, so we poll until we are able + // to settle. + err = wait.NoError(func() error { + return n.bobServer.registry.SettleHodlInvoice(preimage) + }, time.Minute) + if err != nil { + t.Fatal(err) + } + } + + // Ensure that all of the payments sent by alice eventually succeed. + for errChan := range aliceErrChan { + err := <-errChan + if err != nil { + t.Fatalf("alice payment failed: %v", err) + } + } +} + // TestExitNodeTimelockPayloadMismatch tests that when an exit node receives an // incoming HTLC, if the time lock encoded in the payload of the forwarded HTLC // doesn't match the expected payment value, then the HTLC will be rejected @@ -2369,227 +2332,6 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth) } -// TestChannelLinkBandwidthConsistencyOverflow tests that in the case of a -// commitment overflow (no more space for new HTLC's), the bandwidth is updated -// properly as items are being added and removed from the overflow queue. -func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) { - t.Parallel() - - var mockBlob [lnwire.OnionPacketSize]byte - - const chanAmt = btcutil.SatoshiPerBitcoin * 5 - aliceLink, bobChannel, batchTick, start, cleanUp, _, err := - newSingleLinkTestHarness(chanAmt, 0) - if err != nil { - t.Fatalf("unable to create link: %v", err) - } - defer cleanUp() - - if err := start(); err != nil { - t.Fatalf("unable to start test harness: %v", err) - } - - var ( - coreLink = aliceLink.(*channelLink) - defaultCommitFee = coreLink.channel.StateSnapshot().CommitFee - aliceStartingBandwidth = aliceLink.Bandwidth() - aliceMsgs = coreLink.cfg.Peer.(*mockPeer).sentMsgs - ) - - estimator := chainfee.NewStaticEstimator(6000, 0) - feePerKw, err := estimator.EstimateFeePerKW(1) - if err != nil { - t.Fatalf("unable to query fee estimator: %v", err) - } - - var htlcID uint64 - addLinkHTLC := func(id uint64, amt lnwire.MilliSatoshi) [32]byte { - invoice, htlc, _, err := generatePayment( - amt, amt, 5, mockBlob, - ) - if err != nil { - t.Fatalf("unable to create payment: %v", err) - } - - addPkt := &htlcPacket{ - htlc: htlc, - incomingHTLCID: id, - amount: amt, - obfuscator: NewMockObfuscator(), - } - circuit := makePaymentCircuit(&htlc.PaymentHash, addPkt) - _, err = coreLink.cfg.Switch.commitCircuits(&circuit) - if err != nil { - t.Fatalf("unable to commit circuit: %v", err) - } - - addPkt.circuit = &circuit - aliceLink.HandleSwitchPacket(addPkt) - return invoice.Terms.PaymentPreimage - } - - // We'll first start by adding enough HTLC's to overflow the commitment - // transaction, checking the reported link bandwidth for proper - // consistency along the way - htlcAmt := lnwire.NewMSatFromSatoshis(100000) - totalHtlcAmt := lnwire.MilliSatoshi(0) - const numHTLCs = input.MaxHTLCNumber / 2 - var preImages [][32]byte - for i := 0; i < numHTLCs; i++ { - preImage := addLinkHTLC(htlcID, htlcAmt) - preImages = append(preImages, preImage) - - totalHtlcAmt += htlcAmt - htlcID++ - } - - // The HTLCs should all be sent to the remote. - var msg lnwire.Message - for i := 0; i < numHTLCs; i++ { - select { - case msg = <-aliceMsgs: - case <-time.After(15 * time.Second): - t.Fatalf("did not receive message %d", i) - } - - addHtlc, ok := msg.(*lnwire.UpdateAddHTLC) - if !ok { - t.Fatalf("expected UpdateAddHTLC, got %T", msg) - } - - _, err := bobChannel.ReceiveHTLC(addHtlc) - if err != nil { - t.Fatalf("bob failed receiving htlc: %v", err) - } - } - - select { - case msg = <-aliceMsgs: - t.Fatalf("unexpected message: %T", msg) - case <-time.After(20 * time.Millisecond): - } - - // TODO(roasbeef): increase sleep - time.Sleep(time.Second * 1) - commitWeight := int64(input.CommitWeight + input.HTLCWeight*numHTLCs) - htlcFee := lnwire.NewMSatFromSatoshis( - feePerKw.FeeForWeight(commitWeight), - ) - expectedBandwidth := aliceStartingBandwidth - totalHtlcAmt - htlcFee - expectedBandwidth += lnwire.NewMSatFromSatoshis(defaultCommitFee) - assertLinkBandwidth(t, aliceLink, expectedBandwidth) - - // The overflow queue should be empty at this point, as the commitment - // transaction should be full, but not yet overflown. - if coreLink.overflowQueue.Length() != 0 { - t.Fatalf("wrong overflow queue length: expected %v, got %v", 0, - coreLink.overflowQueue.Length()) - } - - // At this point, the commitment transaction should now be fully - // saturated. We'll continue adding HTLC's, and asserting that the - // bandwidth accounting is done properly. - const numOverFlowHTLCs = 20 - for i := 0; i < numOverFlowHTLCs; i++ { - preImage := addLinkHTLC(htlcID, htlcAmt) - preImages = append(preImages, preImage) - - totalHtlcAmt += htlcAmt - htlcID++ - } - - // No messages should be sent to the remote at this point. - select { - case msg = <-aliceMsgs: - t.Fatalf("unexpected message: %T", msg) - case <-time.After(20 * time.Millisecond): - } - - time.Sleep(time.Second * 2) - expectedBandwidth -= (numOverFlowHTLCs * htlcAmt) - assertLinkBandwidth(t, aliceLink, expectedBandwidth) - - // With the extra HTLC's added, the overflow queue should now be - // populated with our 20 additional HTLC's. - if coreLink.overflowQueue.Length() != numOverFlowHTLCs { - t.Fatalf("wrong overflow queue length: expected %v, got %v", - numOverFlowHTLCs, - coreLink.overflowQueue.Length()) - } - - // We trigger a state update to lock in the HTLCs. This should - // not change Alice's bandwidth. - if err := updateState(batchTick, coreLink, bobChannel, true); err != nil { - t.Fatalf("unable to update state: %v", err) - } - time.Sleep(time.Millisecond * 500) - assertLinkBandwidth(t, aliceLink, expectedBandwidth) - - // At this point, we'll now settle enough HTLCs to empty the overflow - // queue. The resulting bandwidth change should be non-existent as this - // will simply transfer over funds to the remote party. However, the - // size of the overflow queue should be decreasing - for i := 0; i < numOverFlowHTLCs; i++ { - err = bobChannel.SettleHTLC(preImages[i], uint64(i), nil, nil, nil) - if err != nil { - t.Fatalf("unable to settle htlc: %v", err) - } - - htlcSettle := &lnwire.UpdateFulfillHTLC{ - ID: uint64(i), - PaymentPreimage: preImages[i], - } - - aliceLink.HandleChannelUpdate(htlcSettle) - time.Sleep(time.Millisecond * 50) - } - time.Sleep(time.Millisecond * 500) - assertLinkBandwidth(t, aliceLink, expectedBandwidth) - - // We trigger a state update to lock in the Settles. - if err := updateState(batchTick, coreLink, bobChannel, false); err != nil { - t.Fatalf("unable to update state: %v", err) - } - - // After the state update is done, Alice should start sending - // HTLCs from the overflow queue. - for i := 0; i < numOverFlowHTLCs; i++ { - var msg lnwire.Message - select { - case msg = <-aliceMsgs: - case <-time.After(15 * time.Second): - t.Fatalf("did not receive message") - } - - addHtlc, ok := msg.(*lnwire.UpdateAddHTLC) - if !ok { - t.Fatalf("expected UpdateAddHTLC, got %T", msg) - } - - _, err := bobChannel.ReceiveHTLC(addHtlc) - if err != nil { - t.Fatalf("bob failed receiving htlc: %v", err) - } - } - - select { - case msg = <-aliceMsgs: - t.Fatalf("unexpected message: %T", msg) - case <-time.After(20 * time.Millisecond): - } - - assertLinkBandwidth(t, aliceLink, expectedBandwidth) - - // Finally, at this point, the queue itself should be fully empty. As - // enough slots have been drained from the commitment transaction to - // allocate the queue items to. - time.Sleep(time.Millisecond * 500) - if coreLink.overflowQueue.Length() != 0 { - t.Fatalf("wrong overflow queue length: expected %v, got %v", 0, - coreLink.overflowQueue.Length()) - } -} - // genAddsAndCircuits creates `numHtlcs` sequential ADD packets and there // corresponding circuits. The provided `htlc` is used in all test packets. func genAddsAndCircuits(numHtlcs int, htlc *lnwire.UpdateAddHTLC) ( @@ -5699,9 +5441,8 @@ func TestCheckHtlcForward(t *testing.T) { MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, HtlcNotifier: &mockHTLCNotifier{}, }, - log: log, - channel: testChannel.channel, - overflowQueue: newPacketQueue(input.MaxHTLCNumber / 2), + log: log, + channel: testChannel.channel, } var hash [32]byte diff --git a/htlcswitch/queue.go b/htlcswitch/queue.go deleted file mode 100644 index 420d1f9b71..0000000000 --- a/htlcswitch/queue.go +++ /dev/null @@ -1,208 +0,0 @@ -package htlcswitch - -import ( - "sync" - "sync/atomic" - "time" - - "github.com/lightningnetwork/lnd/lnwire" -) - -// packetQueue is a goroutine-safe queue of htlc packets which over flow the -// current commitment transaction. An HTLC will overflow the current commitment -// transaction if one attempts to add a new HTLC to the state machine which -// already has the max number of pending HTLC's present on the commitment -// transaction. Packets are removed from the queue by the channelLink itself -// as additional slots become available on the commitment transaction itself. -// In order to synchronize properly we use a semaphore to allow the channelLink -// to signal the number of slots available, and a condition variable to allow -// the packetQueue to know when new items have been added to the queue. -type packetQueue struct { - // totalHtlcAmt is the sum of the value of all pending HTLC's currently - // residing within the overflow queue. This value should only read or - // modified *atomically*. - totalHtlcAmt int64 // To be used atomically. - - // queueLen is an internal counter that reflects the size of the queue - // at any given instance. This value is intended to be use atomically - // as this value is used by internal methods to obtain the length of - // the queue w/o grabbing the main lock. This allows callers to avoid a - // deadlock situation where the main goroutine is attempting a send - // with the lock held. - queueLen int32 // To be used atomically. - - streamShutdown int32 // To be used atomically. - - queue []*htlcPacket - - wg sync.WaitGroup - - // freeSlots serves as a semaphore who's current value signals the - // number of available slots on the commitment transaction. - freeSlots chan struct{} - - queueCond *sync.Cond - queueMtx sync.Mutex - - // outgoingPkts is a channel that the channelLink will receive on in - // order to drain the packetQueue as new slots become available on the - // commitment transaction. - outgoingPkts chan *htlcPacket - - quit chan struct{} -} - -// newPacketQueue returns a new instance of the packetQueue. The maxFreeSlots -// value should reflect the max number of HTLC's that we're allowed to have -// outstanding within the commitment transaction. -func newPacketQueue(maxFreeSlots int) *packetQueue { - p := &packetQueue{ - outgoingPkts: make(chan *htlcPacket), - freeSlots: make(chan struct{}, maxFreeSlots), - quit: make(chan struct{}), - } - p.queueCond = sync.NewCond(&p.queueMtx) - - return p -} - -// Start starts all goroutines that packetQueue needs to perform its normal -// duties. -func (p *packetQueue) Start() { - p.wg.Add(1) - go p.packetCoordinator() -} - -// Stop signals the packetQueue for a graceful shutdown, and waits for all -// goroutines to exit. -func (p *packetQueue) Stop() { - close(p.quit) - - // Now that we've closed the channel, we'll repeatedly signal the msg - // consumer until we've detected that it has exited. - for atomic.LoadInt32(&p.streamShutdown) == 0 { - p.queueCond.Signal() - time.Sleep(time.Millisecond * 100) - } -} - -// packetCoordinator is a goroutine that handles the packet overflow queue. -// Using a synchronized queue, outside callers are able to append to the end of -// the queue, waking up the coordinator when the queue transitions from empty -// to non-empty. The packetCoordinator will then aggressively try to empty out -// the queue, passing new htlcPackets to the channelLink as slots within the -// commitment transaction become available. -// -// Future iterations of the packetCoordinator will implement congestion -// avoidance logic in the face of persistent htlcPacket back-pressure. -// -// TODO(roasbeef): later will need to add back pressure handling heuristics -// like reg congestion avoidance: -// * random dropping, RED, etc -func (p *packetQueue) packetCoordinator() { - defer atomic.StoreInt32(&p.streamShutdown, 1) - - for { - // First, we'll check our condition. If the queue of packets is - // empty, then we'll wait until a new item is added. - p.queueCond.L.Lock() - for len(p.queue) == 0 { - p.queueCond.Wait() - - // If we were woke up in order to exit, then we'll do - // so. Otherwise, we'll check the message queue for any - // new items. - select { - case <-p.quit: - p.queueCond.L.Unlock() - return - default: - } - } - - nextPkt := p.queue[0] - - p.queueCond.L.Unlock() - - // If there aren't any further messages to sent (or the link - // didn't immediately read our message), then we'll block and - // wait for a new message to be sent into the overflow queue, - // or for the link's htlcForwarder to wake up. - select { - case <-p.freeSlots: - - select { - case p.outgoingPkts <- nextPkt: - // Pop the item off the front of the queue and - // slide down the reference one to re-position - // the head pointer. This will set us up for - // the next iteration. If the queue is empty - // at this point, then we'll block at the top. - p.queueCond.L.Lock() - p.queue[0] = nil - p.queue = p.queue[1:] - atomic.AddInt32(&p.queueLen, -1) - atomic.AddInt64(&p.totalHtlcAmt, int64(-nextPkt.amount)) - p.queueCond.L.Unlock() - case <-p.quit: - return - } - - case <-p.quit: - return - - default: - } - } -} - -// AddPkt adds the referenced packet to the overflow queue, preserving ordering -// of the existing items. -func (p *packetQueue) AddPkt(pkt *htlcPacket) { - // First, we'll lock the condition, and add the message to the end of - // the message queue, and increment the internal atomic for tracking - // the queue's length. - p.queueCond.L.Lock() - p.queue = append(p.queue, pkt) - atomic.AddInt32(&p.queueLen, 1) - atomic.AddInt64(&p.totalHtlcAmt, int64(pkt.amount)) - p.queueCond.L.Unlock() - - // With the message added, we signal to the msgConsumer that there are - // additional messages to consume. - p.queueCond.Signal() -} - -// SignalFreeSlot signals to the queue that a new slot has opened up within the -// commitment transaction. The max amount of free slots has been defined when -// initially creating the packetQueue itself. This method, combined with AddPkt -// creates the following abstraction: a synchronized queue of infinite length -// which can be added to at will, which flows onto a commitment of fixed -// capacity. -func (p *packetQueue) SignalFreeSlot() { - // We'll only send over a free slot signal if the queue *is not* empty. - // Otherwise, it's possible that we attempt to overfill the free slots - // semaphore and block indefinitely below. - if atomic.LoadInt32(&p.queueLen) == 0 { - return - } - - select { - case p.freeSlots <- struct{}{}: - case <-p.quit: - return - } -} - -// Length returns the number of pending htlc packets present within the over -// flow queue. -func (p *packetQueue) Length() int32 { - return atomic.LoadInt32(&p.queueLen) -} - -// TotalHtlcAmount is the total amount (in mSAT) of all HTLC's currently -// residing within the overflow queue. -func (p *packetQueue) TotalHtlcAmount() lnwire.MilliSatoshi { - // TODO(roasbeef): also factor in fee rate? - return lnwire.MilliSatoshi(atomic.LoadInt64(&p.totalHtlcAmt)) -} diff --git a/htlcswitch/queue_test.go b/htlcswitch/queue_test.go deleted file mode 100644 index 92d3116423..0000000000 --- a/htlcswitch/queue_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package htlcswitch - -import ( - "reflect" - "testing" - "time" - - "github.com/lightningnetwork/lnd/lnwire" -) - -// TestWaitingQueueThreadSafety test the thread safety properties of the -// waiting queue, by executing methods in separate goroutines which operates -// with the same data. -func TestWaitingQueueThreadSafety(t *testing.T) { - t.Parallel() - - const numPkts = 1000 - - q := newPacketQueue(numPkts) - q.Start() - defer q.Stop() - - a := make([]uint64, numPkts) - for i := 0; i < numPkts; i++ { - a[i] = uint64(i) - q.AddPkt(&htlcPacket{ - incomingHTLCID: a[i], - htlc: &lnwire.UpdateAddHTLC{}, - }) - } - - // The reported length of the queue should be the exact number of - // packets we added above. - queueLength := q.Length() - if queueLength != numPkts { - t.Fatalf("queue has wrong length: expected %v, got %v", numPkts, - queueLength) - } - - var b []uint64 - for i := 0; i < numPkts; i++ { - q.SignalFreeSlot() - - select { - case packet := <-q.outgoingPkts: - b = append(b, packet.incomingHTLCID) - - case <-time.After(2 * time.Second): - t.Fatal("timeout") - } - } - - // The length of the queue should be zero at this point. - time.Sleep(time.Millisecond * 50) - queueLength = q.Length() - if queueLength != 0 { - t.Fatalf("queue has wrong length: expected %v, got %v", 0, - queueLength) - } - - if !reflect.DeepEqual(b, a) { - t.Fatal("wrong order of the objects") - } -} diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 11edadf104..aef7dbdf8b 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -10344,9 +10344,7 @@ func testNodeSignVerify(net *lntest.NetworkHarness, t *harnessTest) { closeChannelAndAssert(ctxt, t, net, net.Alice, aliceBobCh, false) } -// testAsyncPayments tests the performance of the async payments, and also -// checks that balances of both sides can't be become negative under stress -// payment strikes. +// testAsyncPayments tests the performance of the async payments. func testAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() @@ -10372,18 +10370,16 @@ func testAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) { t.Fatalf("unable to get alice channel info: %v", err) } - // Calculate the number of invoices. We will deplete the channel - // all the way down to the channel reserve. - chanReserve := channelCapacity / 100 - availableBalance := btcutil.Amount(info.LocalBalance) - chanReserve - numInvoices := int(availableBalance / paymentAmt) + // We'll create a number of invoices equal the max number of HTLCs that + // can be carried in one direction. The number on the commitment will + // likely be lower, but we can't guarantee that any more HTLCs will + // succeed due to the limited path diversity and inability of the router + // to retry via another path. + numInvoices := int(input.MaxHTLCNumber / 2) bobAmt := int64(numInvoices * paymentAmt) aliceAmt := info.LocalBalance - bobAmt - // Send one more payment in order to cause insufficient capacity error. - numInvoices++ - // With the channel open, we'll create invoices for Bob that Alice // will pay to in order to advance the state of the channel. bobPayReqs, _, _, err := createPayReqs( @@ -10424,28 +10420,13 @@ func testAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) { } } - // We should receive one insufficient capacity error, because we sent - // one more payment than we can actually handle with the current - // channel capacity. - errorReceived := false + // Wait until all the payments have settled. for i := 0; i < numInvoices; i++ { - if resp, err := alicePayStream.Recv(); err != nil { + if _, err := alicePayStream.Recv(); err != nil { t.Fatalf("payment stream have been closed: %v", err) - } else if resp.PaymentError != "" { - if errorReceived { - t.Fatalf("redundant payment error: %v", - resp.PaymentError) - } - - errorReceived = true - continue } } - if !errorReceived { - t.Fatalf("insufficient capacity error haven't been received") - } - // All payments have been sent, mark the finish time. timeTaken := time.Since(now) @@ -10535,8 +10516,12 @@ func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) t.Fatalf("unable to get alice channel info: %v", err) } - // Calculate the number of invoices. - numInvoices := int(info.LocalBalance / paymentAmt) + // We'll create a number of invoices equal the max number of HTLCs that + // can be carried in one direction. The number on the commitment will + // likely be lower, but we can't guarantee that any more HTLCs will + // succeed due to the limited path diversity and inability of the router + // to retry via another path. + numInvoices := int(input.MaxHTLCNumber / 2) // Nodes should exchange the same amount of money and because of this // at the end balances should remain the same. From 5d0a117162da5c1373a25b4db15b26c43e5e9f79 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Apr 2020 12:18:50 +0200 Subject: [PATCH 428/562] routing: fix log --- routing/payment_lifecycle.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 6ac79400a6..dfda814a54 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -207,7 +207,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { uint32(state.numShardsInFlight), uint32(p.currentHeight), ) if err != nil { - log.Warnf("Failed to find route for payment %x: %v", + log.Warnf("Failed to find route for payment %v: %v", p.paymentHash, err) routeErr, ok := err.(noRouteError) @@ -489,7 +489,7 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) ( // case we can safely send a new payment attempt, and wait for its // result to be available. case err == htlcswitch.ErrPaymentIDNotFound: - log.Debugf("Payment ID %v for hash %x not found in "+ + log.Debugf("Payment ID %v for hash %v not found in "+ "the Switch, retrying.", attempt.AttemptID, p.paymentHash) @@ -544,7 +544,7 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) ( } // We successfully got a payment result back from the switch. - log.Debugf("Payment %x succeeded with pid=%v", + log.Debugf("Payment %v succeeded with pid=%v", p.paymentHash, attempt.AttemptID) // Report success to mission control. @@ -637,7 +637,7 @@ func (p *shardHandler) sendPaymentAttempt( attempt *channeldb.HTLCAttemptInfo, firstHop lnwire.ShortChannelID, htlcAdd *lnwire.UpdateAddHTLC) error { - log.Tracef("Attempting to send payment %x (pid=%v), "+ + log.Tracef("Attempting to send payment %v (pid=%v), "+ "using route: %v", p.paymentHash, attempt.AttemptID, newLogClosure(func() string { return spew.Sdump(attempt.Route) @@ -653,12 +653,12 @@ func (p *shardHandler) sendPaymentAttempt( ) if err != nil { log.Errorf("Failed sending attempt %d for payment "+ - "%x to switch: %v", attempt.AttemptID, + "%v to switch: %v", attempt.AttemptID, p.paymentHash, err) return err } - log.Debugf("Payment %x (pid=%v) successfully sent to switch, route: %v", + log.Debugf("Payment %v (pid=%v) successfully sent to switch, route: %v", p.paymentHash, attempt.AttemptID, &attempt.Route) return nil @@ -678,7 +678,7 @@ func (p *shardHandler) handleSendError(attempt *channeldb.HTLCAttemptInfo, return nil } - log.Debugf("Payment %x failed: final_outcome=%v, raw_err=%v", + log.Debugf("Payment %v failed: final_outcome=%v, raw_err=%v", p.paymentHash, *reason, sendErr) err := p.router.cfg.Control.Fail(p.paymentHash, *reason) From 327634e9f7992002cf4d584717671bebf4de9c36 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 3 Apr 2020 17:01:47 +0200 Subject: [PATCH 429/562] routerrpc: move payment marshalling --- lnrpc/routerrpc/router_backend.go | 90 +++++++++++++++++++++++++++++++ rpcserver.go | 83 ++-------------------------- 2 files changed, 95 insertions(+), 78 deletions(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 6465c26863..f4aac8a4ad 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -1094,3 +1094,93 @@ func marshallChannelUpdate(update *lnwire.ChannelUpdate) *lnrpc.ChannelUpdate { ExtraOpaqueData: update.ExtraOpaqueData, } } + +// MarshallPayment marshall a payment to its rpc representation. +func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) ( + *lnrpc.Payment, error) { + + // Fetch the payment's route and preimage. If no HTLC was + // successful, an empty route and preimage will be used. + var ( + route route.Route + preimage lntypes.Preimage + ) + for _, htlc := range payment.HTLCs { + // Display the last route attempted. + route = htlc.Route + + // If any of the htlcs have settled, extract a valid + // preimage. + if htlc.Settle != nil { + preimage = htlc.Settle.Preimage + } + } + + // Encode the hops from the successful route, if any. + path := make([]string, len(route.Hops)) + for i, hop := range route.Hops { + path[i] = hex.EncodeToString(hop.PubKeyBytes[:]) + } + + msatValue := int64(payment.Info.Value) + satValue := int64(payment.Info.Value.ToSatoshis()) + + status, err := convertPaymentStatus(payment.Status) + if err != nil { + return nil, err + } + + htlcs := make([]*lnrpc.HTLCAttempt, 0, len(payment.HTLCs)) + for _, dbHTLC := range payment.HTLCs { + htlc, err := r.MarshalHTLCAttempt(dbHTLC) + if err != nil { + return nil, err + } + + htlcs = append(htlcs, htlc) + } + + paymentHash := payment.Info.PaymentHash + creationTimeNS := MarshalTimeNano(payment.Info.CreationTime) + + return &lnrpc.Payment{ + PaymentHash: hex.EncodeToString(paymentHash[:]), + Value: satValue, + ValueMsat: msatValue, + ValueSat: satValue, + CreationDate: payment.Info.CreationTime.Unix(), + CreationTimeNs: creationTimeNS, + Path: path, + Fee: int64(route.TotalFees().ToSatoshis()), + FeeSat: int64(route.TotalFees().ToSatoshis()), + FeeMsat: int64(route.TotalFees()), + PaymentPreimage: hex.EncodeToString(preimage[:]), + PaymentRequest: string(payment.Info.PaymentRequest), + Status: status, + Htlcs: htlcs, + PaymentIndex: payment.SequenceNum, + }, nil +} + +// convertPaymentStatus converts a channeldb.PaymentStatus to the type expected +// by the RPC. +func convertPaymentStatus(dbStatus channeldb.PaymentStatus) ( + lnrpc.Payment_PaymentStatus, error) { + + switch dbStatus { + case channeldb.StatusUnknown: + return lnrpc.Payment_UNKNOWN, nil + + case channeldb.StatusInFlight: + return lnrpc.Payment_IN_FLIGHT, nil + + case channeldb.StatusSucceeded: + return lnrpc.Payment_SUCCEEDED, nil + + case channeldb.StatusFailed: + return lnrpc.Payment_FAILED, nil + + default: + return 0, fmt.Errorf("unhandled payment status %v", dbStatus) + } +} diff --git a/rpcserver.go b/rpcserver.go index f13cce5d0c..4d7cc1d22f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -5184,94 +5184,21 @@ func (r *rpcServer) ListPayments(ctx context.Context, } for _, payment := range paymentsQuerySlice.Payments { - // Fetch the payment's route and preimage. If no HTLC was - // successful, an empty route and preimage will be used. - var ( - route route.Route - preimage lntypes.Preimage - ) - for _, htlc := range payment.HTLCs { - // Display the last route attempted. - route = htlc.Route - - // If any of the htlcs have settled, extract a valid - // preimage. - if htlc.Settle != nil { - preimage = htlc.Settle.Preimage - } - } - - // Encode the hops from the successful route, if any. - path := make([]string, len(route.Hops)) - for i, hop := range route.Hops { - path[i] = hex.EncodeToString(hop.PubKeyBytes[:]) - } + payment := payment - msatValue := int64(payment.Info.Value) - satValue := int64(payment.Info.Value.ToSatoshis()) - - status, err := convertPaymentStatus(payment.Status) + rpcPayment, err := r.routerBackend.MarshallPayment(&payment) if err != nil { return nil, err } - htlcs := make([]*lnrpc.HTLCAttempt, 0, len(payment.HTLCs)) - for _, dbHTLC := range payment.HTLCs { - htlc, err := r.routerBackend.MarshalHTLCAttempt(dbHTLC) - if err != nil { - return nil, err - } - - htlcs = append(htlcs, htlc) - } - - paymentHash := payment.Info.PaymentHash - creationTimeNS := routerrpc.MarshalTimeNano(payment.Info.CreationTime) - paymentsResp.Payments = append(paymentsResp.Payments, &lnrpc.Payment{ - PaymentHash: hex.EncodeToString(paymentHash[:]), - Value: satValue, - ValueMsat: msatValue, - ValueSat: satValue, - CreationDate: payment.Info.CreationTime.Unix(), - CreationTimeNs: creationTimeNS, - Path: path, - Fee: int64(route.TotalFees().ToSatoshis()), - FeeSat: int64(route.TotalFees().ToSatoshis()), - FeeMsat: int64(route.TotalFees()), - PaymentPreimage: hex.EncodeToString(preimage[:]), - PaymentRequest: string(payment.Info.PaymentRequest), - Status: status, - Htlcs: htlcs, - PaymentIndex: payment.SequenceNum, - }) + paymentsResp.Payments = append( + paymentsResp.Payments, rpcPayment, + ) } return paymentsResp, nil } -// convertPaymentStatus converts a channeldb.PaymentStatus to the type expected -// by the RPC. -func convertPaymentStatus(dbStatus channeldb.PaymentStatus) ( - lnrpc.Payment_PaymentStatus, error) { - - switch dbStatus { - case channeldb.StatusUnknown: - return lnrpc.Payment_UNKNOWN, nil - - case channeldb.StatusInFlight: - return lnrpc.Payment_IN_FLIGHT, nil - - case channeldb.StatusSucceeded: - return lnrpc.Payment_SUCCEEDED, nil - - case channeldb.StatusFailed: - return lnrpc.Payment_FAILED, nil - - default: - return 0, fmt.Errorf("unhandled payment status %v", dbStatus) - } -} - // DeleteAllPayments deletes all outgoing payments from DB. func (r *rpcServer) DeleteAllPayments(ctx context.Context, _ *lnrpc.DeleteAllPaymentsRequest) (*lnrpc.DeleteAllPaymentsResponse, error) { From 351d8e174cde786583d6475ae6d51483e0a20728 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Apr 2020 11:05:25 +0200 Subject: [PATCH 430/562] lnrpc: expose payment failure reason --- lnrpc/routerrpc/router_backend.go | 38 + lnrpc/rpc.pb.go | 1572 +++++++++++++++-------------- lnrpc/rpc.proto | 36 + lnrpc/rpc.swagger.json | 16 + 4 files changed, 909 insertions(+), 753 deletions(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index f4aac8a4ad..0a64161bb1 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -1143,6 +1143,13 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) ( paymentHash := payment.Info.PaymentHash creationTimeNS := MarshalTimeNano(payment.Info.CreationTime) + failureReason, err := marshallPaymentFailureReason( + payment.FailureReason, + ) + if err != nil { + return nil, err + } + return &lnrpc.Payment{ PaymentHash: hex.EncodeToString(paymentHash[:]), Value: satValue, @@ -1159,6 +1166,7 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) ( Status: status, Htlcs: htlcs, PaymentIndex: payment.SequenceNum, + FailureReason: failureReason, }, nil } @@ -1184,3 +1192,33 @@ func convertPaymentStatus(dbStatus channeldb.PaymentStatus) ( return 0, fmt.Errorf("unhandled payment status %v", dbStatus) } } + +// marshallPaymentFailureReason marshalls the failure reason to the corresponding rpc +// type. +func marshallPaymentFailureReason(reason *channeldb.FailureReason) ( + lnrpc.PaymentFailureReason, error) { + + if reason == nil { + return lnrpc.PaymentFailureReason_FAILURE_REASON_NONE, nil + } + + switch *reason { + + case channeldb.FailureReasonTimeout: + return lnrpc.PaymentFailureReason_FAILURE_REASON_TIMEOUT, nil + + case channeldb.FailureReasonNoRoute: + return lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE, nil + + case channeldb.FailureReasonError: + return lnrpc.PaymentFailureReason_FAILURE_REASON_ERROR, nil + + case channeldb.FailureReasonPaymentDetails: + return lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS, nil + + case channeldb.FailureReasonInsufficientBalance: + return lnrpc.PaymentFailureReason_FAILURE_REASON_INSUFFICIENT_BALANCE, nil + } + + return 0, errors.New("unknown failure reason") +} diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 2fcf8553c6..32dfc48b71 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -188,6 +188,57 @@ func (InvoiceHTLCState) EnumDescriptor() ([]byte, []int) { return fileDescriptor_77a6da22d6a3feb1, []int{4} } +type PaymentFailureReason int32 + +const ( + //* + //Payment isn't failed (yet). + PaymentFailureReason_FAILURE_REASON_NONE PaymentFailureReason = 0 + //* + //There are more routes to try, but the payment timeout was exceeded. + PaymentFailureReason_FAILURE_REASON_TIMEOUT PaymentFailureReason = 1 + //* + //All possible routes were tried and failed permanently. Or were no + //routes to the destination at all. + PaymentFailureReason_FAILURE_REASON_NO_ROUTE PaymentFailureReason = 2 + //* + //A non-recoverable error has occured. + PaymentFailureReason_FAILURE_REASON_ERROR PaymentFailureReason = 3 + //* + //Payment details incorrect (unknown hash, invalid amt or + //invalid final cltv delta) + PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS PaymentFailureReason = 4 + //* + //Insufficient local balance. + PaymentFailureReason_FAILURE_REASON_INSUFFICIENT_BALANCE PaymentFailureReason = 5 +) + +var PaymentFailureReason_name = map[int32]string{ + 0: "FAILURE_REASON_NONE", + 1: "FAILURE_REASON_TIMEOUT", + 2: "FAILURE_REASON_NO_ROUTE", + 3: "FAILURE_REASON_ERROR", + 4: "FAILURE_REASON_INCORRECT_PAYMENT_DETAILS", + 5: "FAILURE_REASON_INSUFFICIENT_BALANCE", +} + +var PaymentFailureReason_value = map[string]int32{ + "FAILURE_REASON_NONE": 0, + "FAILURE_REASON_TIMEOUT": 1, + "FAILURE_REASON_NO_ROUTE": 2, + "FAILURE_REASON_ERROR": 3, + "FAILURE_REASON_INCORRECT_PAYMENT_DETAILS": 4, + "FAILURE_REASON_INSUFFICIENT_BALANCE": 5, +} + +func (x PaymentFailureReason) String() string { + return proto.EnumName(PaymentFailureReason_name, int32(x)) +} + +func (PaymentFailureReason) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{5} +} + type FeatureBit int32 const ( @@ -255,7 +306,7 @@ func (x FeatureBit) String() string { } func (FeatureBit) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{5} + return fileDescriptor_77a6da22d6a3feb1, []int{6} } type ChannelCloseSummary_ClosureType int32 @@ -9504,10 +9555,11 @@ type Payment struct { //The creation index of this payment. Each payment can be uniquely identified //by this index, which may not strictly increment by 1 for payments made in //older versions of lnd. - PaymentIndex uint64 `protobuf:"varint,15,opt,name=payment_index,json=paymentIndex,proto3" json:"payment_index,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + PaymentIndex uint64 `protobuf:"varint,15,opt,name=payment_index,json=paymentIndex,proto3" json:"payment_index,omitempty"` + FailureReason PaymentFailureReason `protobuf:"varint,16,opt,name=failure_reason,json=failureReason,proto3,enum=lnrpc.PaymentFailureReason" json:"failure_reason,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Payment) Reset() { *m = Payment{} } @@ -9644,6 +9696,13 @@ func (m *Payment) GetPaymentIndex() uint64 { return 0 } +func (m *Payment) GetFailureReason() PaymentFailureReason { + if m != nil { + return m.FailureReason + } + return PaymentFailureReason_FAILURE_REASON_NONE +} + type HTLCAttempt struct { /// The status of the HTLC. Status HTLCAttempt_HTLCStatus `protobuf:"varint,1,opt,name=status,proto3,enum=lnrpc.HTLCAttempt_HTLCStatus" json:"status,omitempty"` @@ -11759,6 +11818,7 @@ func init() { proto.RegisterEnum("lnrpc.Initiator", Initiator_name, Initiator_value) proto.RegisterEnum("lnrpc.NodeMetricType", NodeMetricType_name, NodeMetricType_value) proto.RegisterEnum("lnrpc.InvoiceHTLCState", InvoiceHTLCState_name, InvoiceHTLCState_value) + proto.RegisterEnum("lnrpc.PaymentFailureReason", PaymentFailureReason_name, PaymentFailureReason_value) proto.RegisterEnum("lnrpc.FeatureBit", FeatureBit_name, FeatureBit_value) proto.RegisterEnum("lnrpc.ChannelCloseSummary_ClosureType", ChannelCloseSummary_ClosureType_name, ChannelCloseSummary_ClosureType_value) proto.RegisterEnum("lnrpc.Peer_SyncType", Peer_SyncType_name, Peer_SyncType_value) @@ -11948,754 +12008,760 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 11938 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x69, 0x6c, 0x24, 0x49, - 0x76, 0x18, 0xdc, 0x75, 0xb1, 0xaa, 0x5e, 0x1d, 0x2c, 0x06, 0xaf, 0x6a, 0x76, 0xf7, 0x74, 0x4f, - 0xce, 0xec, 0x4c, 0x4f, 0xcf, 0x2e, 0xbb, 0xa7, 0x77, 0x7b, 0x66, 0x77, 0xe6, 0xd3, 0x6a, 0x8b, - 0x64, 0xb1, 0x59, 0xdb, 0xbc, 0x26, 0xab, 0x38, 0xa3, 0x5e, 0x1d, 0xb9, 0xc9, 0xaa, 0x20, 0x99, - 0xea, 0xaa, 0xcc, 0x9a, 0xcc, 0x2c, 0x1e, 0xbb, 0x98, 0xef, 0x87, 0x61, 0x1b, 0x82, 0x61, 0x1b, - 0x10, 0x6c, 0x19, 0xb0, 0x2c, 0xc1, 0x87, 0x60, 0x1b, 0x86, 0x01, 0x41, 0x80, 0xe4, 0x1f, 0x06, - 0xfc, 0x5f, 0x7f, 0x7c, 0xc0, 0x90, 0x0c, 0x18, 0x86, 0x20, 0xc0, 0xb0, 0x2d, 0xff, 0x33, 0x04, - 0xf8, 0xb7, 0x01, 0x23, 0xde, 0x8b, 0xc8, 0x8c, 0xac, 0x4a, 0x76, 0xf7, 0xec, 0xae, 0xf7, 0x0f, - 0x59, 0xf9, 0xe2, 0xc5, 0xfd, 0xe2, 0xc5, 0xbb, 0x22, 0x02, 0xca, 0xfe, 0xb8, 0xbf, 0x3e, 0xf6, - 0xbd, 0xd0, 0x63, 0x85, 0xa1, 0xeb, 0x8f, 0xfb, 0x6b, 0xb7, 0x4f, 0x3d, 0xef, 0x74, 0xc8, 0x1f, - 0xda, 0x63, 0xe7, 0xa1, 0xed, 0xba, 0x5e, 0x68, 0x87, 0x8e, 0xe7, 0x06, 0x84, 0x64, 0xfc, 0x10, - 0xea, 0x4f, 0xb9, 0xdb, 0xe5, 0x7c, 0x60, 0xf2, 0x2f, 0x26, 0x3c, 0x08, 0xd9, 0xfb, 0xb0, 0x60, - 0xf3, 0x1f, 0x71, 0x3e, 0xb0, 0xc6, 0x76, 0x10, 0x8c, 0xcf, 0x7c, 0x3b, 0xe0, 0xcd, 0xcc, 0xbd, - 0xcc, 0xfd, 0xaa, 0xd9, 0xa0, 0x84, 0xc3, 0x08, 0xce, 0xde, 0x84, 0x6a, 0x20, 0x50, 0xb9, 0x1b, - 0xfa, 0xde, 0xf8, 0xaa, 0x99, 0x45, 0xbc, 0x8a, 0x80, 0xb5, 0x09, 0x64, 0x0c, 0x61, 0x3e, 0xaa, - 0x21, 0x18, 0x7b, 0x6e, 0xc0, 0xd9, 0x23, 0x58, 0xea, 0x3b, 0xe3, 0x33, 0xee, 0x5b, 0x98, 0x79, - 0xe4, 0xf2, 0x91, 0xe7, 0x3a, 0xfd, 0x66, 0xe6, 0x5e, 0xee, 0x7e, 0xd9, 0x64, 0x94, 0x26, 0x72, - 0xec, 0xc9, 0x14, 0xf6, 0x2e, 0xcc, 0x73, 0x97, 0xe0, 0x7c, 0x80, 0xb9, 0x64, 0x55, 0xf5, 0x18, - 0x2c, 0x32, 0x18, 0xbf, 0x91, 0x85, 0x85, 0x8e, 0xeb, 0x84, 0x9f, 0xdb, 0xc3, 0x21, 0x0f, 0x55, - 0x9f, 0xde, 0x85, 0xf9, 0x0b, 0x04, 0x60, 0x9f, 0x2e, 0x3c, 0x7f, 0x20, 0x7b, 0x54, 0x27, 0xf0, - 0xa1, 0x84, 0x5e, 0xdb, 0xb2, 0xec, 0xb5, 0x2d, 0x4b, 0x1d, 0xae, 0xdc, 0x35, 0xc3, 0xf5, 0x2e, - 0xcc, 0xfb, 0xbc, 0xef, 0x9d, 0x73, 0xff, 0xca, 0xba, 0x70, 0xdc, 0x81, 0x77, 0xd1, 0xcc, 0xdf, - 0xcb, 0xdc, 0x2f, 0x98, 0x75, 0x05, 0xfe, 0x1c, 0xa1, 0x6c, 0x03, 0xe6, 0xfb, 0x67, 0xb6, 0xeb, - 0xf2, 0xa1, 0x75, 0x6c, 0xf7, 0x5f, 0x4c, 0xc6, 0x41, 0xb3, 0x70, 0x2f, 0x73, 0xbf, 0xf2, 0xf8, - 0xe6, 0x3a, 0xce, 0xea, 0xfa, 0xe6, 0x99, 0xed, 0x6e, 0x60, 0x4a, 0xd7, 0xb5, 0xc7, 0xc1, 0x99, - 0x17, 0x9a, 0x75, 0x99, 0x83, 0xc0, 0x81, 0xb1, 0x04, 0x4c, 0x1f, 0x09, 0x1a, 0x7b, 0xe3, 0x5f, - 0x66, 0x60, 0xf1, 0xc8, 0x1d, 0x7a, 0xfd, 0x17, 0x3f, 0xe1, 0x10, 0xa5, 0xf4, 0x21, 0xfb, 0xba, - 0x7d, 0xc8, 0x7d, 0xd5, 0x3e, 0xac, 0xc0, 0x52, 0xb2, 0xb1, 0xb2, 0x17, 0x1c, 0x96, 0x45, 0xee, - 0x53, 0xae, 0x9a, 0xa5, 0xba, 0xf1, 0x1e, 0x34, 0xfa, 0x13, 0xdf, 0xe7, 0xee, 0x4c, 0x3f, 0xe6, - 0x25, 0x3c, 0xea, 0xc8, 0x9b, 0x50, 0x75, 0xf9, 0x45, 0x8c, 0x26, 0x69, 0xd7, 0xe5, 0x17, 0x0a, - 0xc5, 0x68, 0xc2, 0xca, 0x74, 0x35, 0xb2, 0x01, 0x7f, 0x91, 0x81, 0xfc, 0x51, 0x78, 0xe9, 0xb1, - 0x27, 0x50, 0xb5, 0x07, 0x03, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x8d, 0x69, 0xa5, 0xd4, 0x1f, 0x33, - 0xd9, 0xc5, 0x16, 0x25, 0xf5, 0xae, 0xc6, 0xdc, 0xac, 0xd8, 0xf1, 0x07, 0x6b, 0x42, 0x51, 0x7e, - 0x62, 0xbd, 0x65, 0x53, 0x7d, 0xb2, 0x3b, 0x00, 0xf6, 0xc8, 0x9b, 0xb8, 0xa1, 0x15, 0xd8, 0x21, - 0x8e, 0x58, 0xce, 0x2c, 0x13, 0xa4, 0x6b, 0x87, 0xec, 0x16, 0x94, 0xc7, 0x2f, 0xac, 0xa0, 0xef, - 0x3b, 0xe3, 0x10, 0x89, 0xa7, 0x6c, 0x96, 0xc6, 0x2f, 0xba, 0xf8, 0xcd, 0xde, 0x87, 0x92, 0x37, - 0x09, 0xc7, 0x9e, 0xe3, 0x86, 0x92, 0x5e, 0xe6, 0x65, 0x43, 0x0e, 0x26, 0xe1, 0xa1, 0x00, 0x9b, - 0x11, 0x02, 0x7b, 0x1b, 0x6a, 0x7d, 0xcf, 0x3d, 0x71, 0xfc, 0x11, 0x71, 0x84, 0xe6, 0x1c, 0xd6, - 0x95, 0x04, 0x1a, 0x7f, 0x90, 0x85, 0x4a, 0xcf, 0xb7, 0xdd, 0xc0, 0xee, 0x0b, 0x00, 0x5b, 0x85, - 0x62, 0x78, 0x69, 0x9d, 0xd9, 0xc1, 0x19, 0x76, 0xb5, 0x6c, 0xce, 0x85, 0x97, 0x3b, 0x76, 0x70, - 0xc6, 0x56, 0x60, 0x8e, 0x5a, 0x89, 0x1d, 0xca, 0x99, 0xf2, 0x4b, 0x2c, 0x10, 0x77, 0x32, 0xb2, - 0x92, 0x55, 0xe5, 0x90, 0x62, 0x1a, 0xee, 0x64, 0xb4, 0xa9, 0xc3, 0x45, 0xe7, 0x8f, 0xc5, 0x74, - 0x53, 0x05, 0xd4, 0xbd, 0x32, 0x42, 0xb0, 0x8e, 0x37, 0xa1, 0x2a, 0x93, 0xb9, 0x73, 0x7a, 0x46, - 0x7d, 0x2c, 0x98, 0x15, 0x42, 0x40, 0x90, 0x28, 0x21, 0x74, 0x46, 0xdc, 0x0a, 0x42, 0x7b, 0x34, - 0x96, 0x5d, 0x2a, 0x0b, 0x48, 0x57, 0x00, 0x30, 0xd9, 0x0b, 0xed, 0xa1, 0x75, 0xc2, 0x79, 0xd0, - 0x2c, 0xca, 0x64, 0x01, 0xd9, 0xe6, 0x3c, 0x60, 0x5f, 0x83, 0xfa, 0x80, 0x07, 0xa1, 0x25, 0x27, - 0x83, 0x07, 0xcd, 0x12, 0xae, 0xfc, 0x9a, 0x80, 0xb6, 0x14, 0x90, 0xdd, 0x06, 0xf0, 0xed, 0x0b, - 0x4b, 0x0c, 0x04, 0xbf, 0x6c, 0x96, 0x69, 0x16, 0x7c, 0xfb, 0xa2, 0x77, 0xb9, 0xc3, 0x2f, 0x05, - 0xd5, 0x3c, 0xe5, 0xa1, 0x36, 0x68, 0x81, 0xa4, 0x4e, 0x63, 0x17, 0x98, 0x06, 0xde, 0xe2, 0xa1, - 0xed, 0x0c, 0x03, 0xf6, 0x21, 0x54, 0x43, 0x0d, 0x19, 0xd9, 0x60, 0x25, 0x22, 0x21, 0x2d, 0x83, - 0x99, 0xc0, 0x33, 0xce, 0xa0, 0xb4, 0xcd, 0xf9, 0xae, 0x33, 0x72, 0x42, 0xb6, 0x02, 0x85, 0x13, - 0xe7, 0x92, 0x13, 0xb1, 0xe7, 0x76, 0x6e, 0x98, 0xf4, 0xc9, 0xee, 0x02, 0xe0, 0x0f, 0x6b, 0x14, - 0x51, 0xd3, 0xce, 0x0d, 0xb3, 0x8c, 0xb0, 0xbd, 0xc0, 0x0e, 0xd9, 0x1a, 0x14, 0xc7, 0xdc, 0xef, - 0x73, 0x35, 0x6f, 0x3b, 0x37, 0x4c, 0x05, 0xd8, 0x28, 0x42, 0x61, 0x28, 0x4a, 0x37, 0xfe, 0xb8, - 0x00, 0x95, 0x2e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, 0xcd, 0xde, - 0x82, 0x0a, 0x0e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x91, 0x6d, 0x66, 0x4c, 0x10, - 0xe0, 0x2e, 0x42, 0x59, 0x03, 0x72, 0xf6, 0x48, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x42, 0xc9, 0x1e, - 0x85, 0xd4, 0xbc, 0x2a, 0x82, 0x8b, 0xf6, 0x28, 0xc4, 0xa6, 0xbd, 0x09, 0xd5, 0xb1, 0x7d, 0x35, - 0x12, 0x6b, 0x39, 0x22, 0x87, 0xaa, 0x59, 0x91, 0x30, 0x24, 0x88, 0xc7, 0xb0, 0xa8, 0xa3, 0xa8, - 0xca, 0x0b, 0x51, 0xe5, 0x0b, 0x1a, 0xb6, 0x6c, 0xc3, 0xbb, 0x30, 0xaf, 0xf2, 0xf8, 0xd4, 0x1f, - 0x24, 0x93, 0xb2, 0x59, 0x97, 0x60, 0xd5, 0xcb, 0xfb, 0xd0, 0x38, 0x71, 0x5c, 0x7b, 0x68, 0xf5, - 0x87, 0xe1, 0xb9, 0x35, 0xe0, 0xc3, 0xd0, 0x46, 0x8a, 0x29, 0x98, 0x75, 0x84, 0x6f, 0x0e, 0xc3, - 0xf3, 0x2d, 0x01, 0x65, 0x5f, 0x87, 0xf2, 0x09, 0xe7, 0x16, 0x0e, 0x56, 0xb3, 0x94, 0x58, 0x78, - 0x6a, 0x86, 0xcc, 0xd2, 0x89, 0x9a, 0xab, 0xaf, 0x43, 0xc3, 0x9b, 0x84, 0xa7, 0x9e, 0xe3, 0x9e, - 0x5a, 0x82, 0xdf, 0x59, 0xce, 0x00, 0x69, 0x28, 0xbf, 0x91, 0x7d, 0x94, 0x31, 0xeb, 0x2a, 0x4d, - 0x70, 0x9e, 0xce, 0x80, 0xbd, 0x03, 0xf3, 0x43, 0x3b, 0x08, 0xad, 0x33, 0x6f, 0x6c, 0x8d, 0x27, - 0xc7, 0x2f, 0xf8, 0x55, 0xb3, 0x86, 0x03, 0x51, 0x13, 0xe0, 0x1d, 0x6f, 0x7c, 0x88, 0x40, 0x41, - 0xd9, 0xd8, 0x4e, 0x6a, 0x04, 0xdc, 0xcb, 0xdc, 0xaf, 0x99, 0x65, 0x01, 0xa1, 0x4a, 0x9f, 0xc3, - 0x22, 0x4e, 0x4f, 0x7f, 0x12, 0x84, 0xde, 0xc8, 0x12, 0xbc, 0xda, 0x1f, 0x04, 0xcd, 0x0a, 0xd2, - 0xda, 0x7b, 0xb2, 0xb1, 0xda, 0x1c, 0xaf, 0x6f, 0xf1, 0x20, 0xdc, 0x44, 0x64, 0x93, 0x70, 0xc5, - 0x86, 0x7e, 0x65, 0x2e, 0x0c, 0xa6, 0xe1, 0xec, 0xeb, 0xc0, 0xec, 0xe1, 0xd0, 0xbb, 0xb0, 0x02, - 0x3e, 0x3c, 0xb1, 0xe4, 0x20, 0x36, 0xeb, 0xf7, 0x32, 0xf7, 0x4b, 0x66, 0x03, 0x53, 0xba, 0x7c, - 0x78, 0x72, 0x48, 0x70, 0xf6, 0x21, 0xe0, 0x62, 0xb2, 0x4e, 0xb8, 0x1d, 0x4e, 0x7c, 0x1e, 0x34, - 0xe7, 0xef, 0xe5, 0xee, 0xd7, 0x1f, 0x2f, 0x44, 0xe3, 0x85, 0xe0, 0x0d, 0x27, 0x34, 0xab, 0x02, - 0x4f, 0x7e, 0x07, 0x6b, 0x5b, 0xb0, 0x92, 0xde, 0x24, 0x41, 0x54, 0x62, 0x54, 0x04, 0x31, 0xe6, - 0x4d, 0xf1, 0x93, 0x2d, 0x41, 0xe1, 0xdc, 0x1e, 0x4e, 0xb8, 0xe4, 0xe9, 0xf4, 0xf1, 0x71, 0xf6, - 0xdb, 0x19, 0xe3, 0x8f, 0x32, 0x50, 0xa5, 0x5e, 0x4a, 0x59, 0xe4, 0x2d, 0xa8, 0x29, 0x6a, 0xe0, - 0xbe, 0xef, 0xf9, 0x92, 0xab, 0x29, 0xca, 0x6b, 0x0b, 0x98, 0xd8, 0x55, 0x14, 0xd2, 0xd8, 0xe7, - 0xce, 0xc8, 0x3e, 0x55, 0x45, 0x2b, 0x52, 0x3a, 0x94, 0x60, 0xf6, 0x41, 0x5c, 0x9e, 0xef, 0x4d, - 0x42, 0x2e, 0xf7, 0xbc, 0xaa, 0xec, 0x9e, 0x29, 0x60, 0x51, 0xe9, 0xf8, 0xf5, 0x1a, 0x74, 0x6e, - 0xfc, 0x56, 0x06, 0x98, 0x68, 0x76, 0xcf, 0xa3, 0x02, 0x24, 0x85, 0x4e, 0xe7, 0xcc, 0xbc, 0xf6, - 0x0a, 0xc9, 0xbe, 0x6c, 0x85, 0x18, 0x50, 0xa0, 0xb6, 0xe7, 0x53, 0xda, 0x4e, 0x49, 0xdf, 0xcf, - 0x97, 0x72, 0x8d, 0xbc, 0xf1, 0x5f, 0x72, 0xb0, 0xb4, 0x49, 0x5b, 0x76, 0xab, 0xdf, 0xe7, 0xe3, - 0x68, 0xed, 0xdc, 0x85, 0x8a, 0xeb, 0x0d, 0xb8, 0xa2, 0x58, 0x6a, 0x18, 0x08, 0x90, 0x46, 0xae, - 0x67, 0xb6, 0xe3, 0x52, 0xc3, 0x69, 0x30, 0xcb, 0x08, 0xc1, 0x66, 0xbf, 0x03, 0xf3, 0x63, 0xee, - 0x0e, 0xf4, 0x25, 0x42, 0x42, 0x55, 0x4d, 0x82, 0xe5, 0xea, 0xb8, 0x0b, 0x95, 0x93, 0x09, 0xe1, - 0x09, 0xc6, 0x92, 0x47, 0x1a, 0x00, 0x09, 0x6a, 0x11, 0x7f, 0x19, 0x4f, 0x82, 0x33, 0x4c, 0x2d, - 0x60, 0x6a, 0x51, 0x7c, 0x8b, 0xa4, 0x3b, 0x00, 0x83, 0x49, 0x10, 0xca, 0x15, 0x33, 0x87, 0x89, - 0x65, 0x01, 0xa1, 0x15, 0xf3, 0x0d, 0x58, 0x1c, 0xd9, 0x97, 0x16, 0xd2, 0x8e, 0xe5, 0xb8, 0xd6, - 0xc9, 0x10, 0xf7, 0x9c, 0x22, 0xe2, 0x35, 0x46, 0xf6, 0xe5, 0x67, 0x22, 0xa5, 0xe3, 0x6e, 0x23, - 0x5c, 0xb0, 0x15, 0x25, 0xee, 0xf8, 0x3c, 0xe0, 0xfe, 0x39, 0x47, 0x4e, 0x90, 0x8f, 0x64, 0x1a, - 0x93, 0xa0, 0xa2, 0x45, 0x23, 0xd1, 0xef, 0x70, 0xd8, 0xa7, 0x65, 0x6f, 0x16, 0x47, 0x8e, 0xbb, - 0x13, 0x0e, 0xfb, 0x62, 0x5f, 0x11, 0x7c, 0x64, 0xcc, 0x7d, 0xeb, 0xc5, 0x05, 0xae, 0xe1, 0x3c, - 0xf2, 0x8d, 0x43, 0xee, 0x3f, 0xbb, 0x10, 0x5b, 0x7f, 0x3f, 0x40, 0x46, 0x64, 0x5f, 0x35, 0x2b, - 0xb8, 0xc0, 0x4b, 0xfd, 0x40, 0xb0, 0x20, 0xfb, 0x4a, 0x2c, 0x42, 0xd1, 0x5a, 0x1b, 0x67, 0x81, - 0x0f, 0xb0, 0xf8, 0x00, 0x39, 0x6a, 0x0d, 0x1b, 0xdb, 0x92, 0x09, 0xa2, 0x9e, 0x40, 0x50, 0xbd, - 0x6a, 0xec, 0xc9, 0xd0, 0x3e, 0x0d, 0x90, 0xa5, 0xd4, 0xcc, 0xaa, 0x04, 0x6e, 0x0b, 0x98, 0xf1, - 0x39, 0x09, 0x59, 0xda, 0xdc, 0xca, 0x35, 0x23, 0xb6, 0x7a, 0x84, 0xe0, 0xbc, 0x96, 0x4c, 0xf9, - 0x95, 0x36, 0x69, 0xd9, 0x94, 0x49, 0x33, 0x7e, 0x37, 0x03, 0x55, 0x59, 0x32, 0x0a, 0x25, 0x6c, - 0x1d, 0x98, 0x9a, 0xc5, 0xf0, 0xd2, 0x19, 0x58, 0xc7, 0x57, 0x21, 0x0f, 0x88, 0x68, 0x76, 0x6e, - 0x98, 0x0d, 0x99, 0xd6, 0xbb, 0x74, 0x06, 0x1b, 0x22, 0x85, 0x3d, 0x80, 0x46, 0x02, 0x3f, 0x08, - 0x7d, 0xa2, 0xe8, 0x9d, 0x1b, 0x66, 0x5d, 0xc3, 0xee, 0x86, 0xbe, 0x58, 0x23, 0x42, 0xe4, 0x99, - 0x84, 0x96, 0xe3, 0x0e, 0xf8, 0x25, 0x92, 0x51, 0xcd, 0xac, 0x10, 0xac, 0x23, 0x40, 0x1b, 0x75, - 0xa8, 0xea, 0xc5, 0x19, 0xa7, 0x50, 0x52, 0xf2, 0x12, 0x0a, 0x0c, 0x53, 0x4d, 0x32, 0xcb, 0x61, - 0xd4, 0x92, 0x9b, 0x50, 0x4a, 0xb6, 0xc0, 0x2c, 0x86, 0xaf, 0x5d, 0xb1, 0xf1, 0x5d, 0x68, 0xec, - 0x0a, 0xe2, 0x71, 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x05, 0xe6, 0xb4, 0x45, 0x53, 0x36, 0xe5, 0x97, - 0xd8, 0x73, 0xcf, 0xbc, 0x20, 0x94, 0xb5, 0xe0, 0x6f, 0xe3, 0x8f, 0x33, 0xc0, 0xda, 0x41, 0xe8, - 0x8c, 0xec, 0x90, 0x6f, 0xf3, 0x88, 0x2d, 0x1c, 0x40, 0x55, 0x94, 0xd6, 0xf3, 0x5a, 0x24, 0x90, - 0x91, 0x40, 0xf1, 0xbe, 0x5c, 0xc6, 0xb3, 0x19, 0xd6, 0x75, 0x6c, 0x62, 0xf3, 0x89, 0x02, 0xc4, - 0x2a, 0x0b, 0x6d, 0xff, 0x94, 0x87, 0x28, 0xc6, 0x49, 0x79, 0x1f, 0x08, 0x24, 0x04, 0xb8, 0xb5, - 0x5f, 0x84, 0x85, 0x99, 0x32, 0x74, 0xbe, 0x5c, 0x4e, 0xe1, 0xcb, 0x39, 0x9d, 0x2f, 0x5b, 0xb0, - 0x98, 0x68, 0x97, 0xa4, 0xb4, 0x55, 0x28, 0x8a, 0x05, 0x21, 0x84, 0x83, 0x0c, 0x49, 0x95, 0x27, - 0x9c, 0x0b, 0x31, 0xf8, 0x21, 0x2c, 0x9d, 0x70, 0xee, 0xdb, 0x21, 0x26, 0xe2, 0x8a, 0x11, 0x33, - 0x24, 0x0b, 0x5e, 0x90, 0x69, 0x5d, 0x3b, 0x3c, 0xe4, 0xbe, 0x98, 0x29, 0xe3, 0xbf, 0x65, 0x60, - 0x5e, 0x70, 0xd0, 0x3d, 0xdb, 0xbd, 0x52, 0xe3, 0xb4, 0x9b, 0x3a, 0x4e, 0xf7, 0xb5, 0xcd, 0x50, - 0xc3, 0xfe, 0xaa, 0x83, 0x94, 0x9b, 0x1e, 0x24, 0x76, 0x0f, 0xaa, 0x89, 0xb6, 0x16, 0xb0, 0xad, - 0x10, 0x44, 0x8d, 0xfc, 0xe9, 0x87, 0xf1, 0x1d, 0x68, 0xc4, 0xcd, 0x96, 0x63, 0xc8, 0x20, 0x2f, - 0x48, 0x52, 0x16, 0x80, 0xbf, 0x8d, 0xdf, 0xc9, 0x10, 0xe2, 0xa6, 0xe7, 0x44, 0xd2, 0xa9, 0x40, - 0x14, 0x72, 0xaf, 0x42, 0x14, 0xbf, 0xaf, 0x95, 0xea, 0x7f, 0xfa, 0xce, 0x8a, 0xa5, 0x13, 0x70, - 0x77, 0x60, 0xd9, 0xc3, 0x21, 0x32, 0xdf, 0x92, 0x59, 0x14, 0xdf, 0xad, 0xe1, 0xd0, 0x78, 0x17, - 0x16, 0xb4, 0xd6, 0xbd, 0xa4, 0x1f, 0xfb, 0xc0, 0x76, 0x9d, 0x20, 0x3c, 0x72, 0x83, 0xb1, 0x26, - 0xb8, 0xdd, 0x82, 0xb2, 0xe0, 0xb0, 0xa2, 0x65, 0xb4, 0x64, 0x0b, 0xa6, 0x60, 0xb9, 0xa2, 0x5d, - 0x01, 0x26, 0xda, 0x97, 0x32, 0x31, 0x2b, 0x13, 0xed, 0x4b, 0x4c, 0x34, 0xbe, 0x0d, 0x8b, 0x89, - 0xf2, 0x64, 0xd5, 0x6f, 0x42, 0x61, 0x12, 0x5e, 0x7a, 0x4a, 0x34, 0xaf, 0x48, 0x0a, 0x11, 0x0a, - 0xa0, 0x49, 0x29, 0xc6, 0x27, 0xb0, 0xb0, 0xcf, 0x2f, 0xe4, 0x22, 0x56, 0x0d, 0x79, 0x07, 0xf2, - 0xaf, 0x50, 0x0a, 0x31, 0xdd, 0x58, 0x07, 0xa6, 0x67, 0x96, 0xb5, 0x6a, 0x3a, 0x62, 0x26, 0xa1, - 0x23, 0x1a, 0xef, 0x00, 0xeb, 0x3a, 0xa7, 0xee, 0x1e, 0x0f, 0x02, 0xfb, 0x34, 0x5a, 0xf6, 0x0d, - 0xc8, 0x8d, 0x82, 0x53, 0xc9, 0xa3, 0xc4, 0x4f, 0xe3, 0x9b, 0xb0, 0x98, 0xc0, 0x93, 0x05, 0xdf, - 0x86, 0x72, 0xe0, 0x9c, 0xba, 0x28, 0x58, 0xc9, 0xa2, 0x63, 0x80, 0xb1, 0x0d, 0x4b, 0x9f, 0x71, - 0xdf, 0x39, 0xb9, 0x7a, 0x55, 0xf1, 0xc9, 0x72, 0xb2, 0xd3, 0xe5, 0xb4, 0x61, 0x79, 0xaa, 0x1c, - 0x59, 0x3d, 0x91, 0xaf, 0x9c, 0xc9, 0x92, 0x49, 0x1f, 0x1a, 0xdf, 0xcb, 0xea, 0x7c, 0xcf, 0x38, - 0x02, 0xb6, 0xe9, 0xb9, 0x2e, 0xef, 0x87, 0x87, 0x9c, 0xfb, 0xb1, 0x95, 0x2a, 0xa6, 0xd5, 0xca, - 0xe3, 0x55, 0x39, 0xb2, 0xd3, 0xcc, 0x54, 0x12, 0x31, 0x83, 0xfc, 0x98, 0xfb, 0x23, 0x2c, 0xb8, - 0x64, 0xe2, 0x6f, 0x63, 0x19, 0x16, 0x13, 0xc5, 0x4a, 0xbd, 0xfe, 0x11, 0x2c, 0x6f, 0x39, 0x41, - 0x7f, 0xb6, 0xc2, 0x55, 0x28, 0x8e, 0x27, 0xc7, 0x56, 0x92, 0x2f, 0x3f, 0xe3, 0x57, 0x42, 0xdb, - 0x9b, 0xce, 0x21, 0xcb, 0xfa, 0xab, 0x19, 0xc8, 0xef, 0xf4, 0x76, 0x37, 0xd9, 0x1a, 0x94, 0x1c, - 0xb7, 0xef, 0x8d, 0x84, 0xe0, 0x45, 0x7d, 0x8e, 0xbe, 0xaf, 0x5d, 0x60, 0xb7, 0xa0, 0x8c, 0xf2, - 0x9a, 0x50, 0x6d, 0xa5, 0xe8, 0x53, 0x12, 0x80, 0x5d, 0xaf, 0xff, 0x42, 0xe8, 0xd4, 0xfc, 0x72, - 0xec, 0xf8, 0xa8, 0x35, 0x2b, 0x65, 0x38, 0x4f, 0x7b, 0x7d, 0x9c, 0x40, 0x1a, 0xb1, 0xf1, 0xaf, - 0x4b, 0x50, 0x94, 0xbb, 0x2d, 0xed, 0xdc, 0xa1, 0x73, 0xce, 0xe3, 0x9d, 0x5b, 0x7c, 0x09, 0x79, - 0xc0, 0xe7, 0x23, 0x2f, 0x8c, 0x04, 0x36, 0x9a, 0x83, 0x2a, 0x01, 0xa5, 0xc8, 0xa6, 0x09, 0x0d, - 0x64, 0x62, 0xc8, 0x11, 0x52, 0x5f, 0xdf, 0xca, 0x6f, 0x41, 0x51, 0xed, 0xfd, 0xf9, 0x48, 0xa7, - 0x99, 0xeb, 0x93, 0xb4, 0xb6, 0x06, 0xa5, 0xbe, 0x3d, 0xb6, 0xfb, 0x4e, 0x78, 0x25, 0x19, 0x42, - 0xf4, 0x2d, 0x4a, 0x1f, 0x7a, 0x7d, 0x7b, 0x68, 0x1d, 0xdb, 0x43, 0xdb, 0xed, 0x73, 0xa9, 0xbb, - 0x57, 0x11, 0xb8, 0x41, 0x30, 0xa1, 0x9f, 0xcb, 0x76, 0x2a, 0x2c, 0x52, 0xe1, 0x65, 0xeb, 0x15, - 0x9a, 0x10, 0x2e, 0xbd, 0xd1, 0xc8, 0x11, 0x5a, 0x06, 0x89, 0x61, 0x39, 0xb3, 0x4c, 0x90, 0x6d, - 0x8e, 0xbd, 0x95, 0xc9, 0x17, 0x34, 0x74, 0x65, 0xaa, 0x8a, 0x80, 0x9f, 0x93, 0x21, 0x61, 0x56, - 0x16, 0xcb, 0x69, 0xb2, 0xd8, 0xfb, 0xb0, 0x30, 0x71, 0x03, 0x1e, 0x86, 0x43, 0x3e, 0x88, 0xda, - 0x52, 0x41, 0xa4, 0x46, 0x94, 0xa0, 0x9a, 0xb3, 0x0e, 0x8b, 0x64, 0x74, 0x08, 0xec, 0xd0, 0x0b, - 0xce, 0x9c, 0xc0, 0x0a, 0x84, 0x86, 0x44, 0xea, 0xee, 0x02, 0x26, 0x75, 0x65, 0x4a, 0x97, 0x54, - 0xa4, 0xd5, 0x29, 0x7c, 0x9f, 0xf7, 0xb9, 0x73, 0xce, 0x07, 0x28, 0xa7, 0xe5, 0xcc, 0xe5, 0x44, - 0x1e, 0x53, 0x26, 0xa2, 0xd0, 0x3d, 0x19, 0x59, 0x93, 0xf1, 0xc0, 0x16, 0xc2, 0x4a, 0x9d, 0x84, - 0x61, 0x77, 0x32, 0x3a, 0x22, 0x08, 0x7b, 0x04, 0x4a, 0x12, 0x93, 0xf2, 0xe1, 0x7c, 0x82, 0x9f, - 0x09, 0x62, 0x35, 0xab, 0x12, 0x83, 0x04, 0xc5, 0x84, 0xcc, 0xd9, 0x98, 0x92, 0x39, 0x9b, 0x50, - 0x1c, 0xfb, 0xce, 0xb9, 0x1d, 0xf2, 0xe6, 0x02, 0x31, 0x70, 0xf9, 0x29, 0x38, 0x83, 0xe3, 0x3a, - 0xa1, 0x63, 0x87, 0x9e, 0xdf, 0x64, 0x98, 0x16, 0x03, 0xd8, 0x03, 0x58, 0x40, 0x1a, 0x09, 0x42, - 0x3b, 0x9c, 0x04, 0x52, 0x02, 0x5d, 0x44, 0x62, 0x42, 0x19, 0xba, 0x8b, 0x70, 0x14, 0x42, 0xd9, - 0x37, 0x61, 0x85, 0xc8, 0x02, 0x73, 0x48, 0xc9, 0x1a, 0x05, 0x82, 0x25, 0x1c, 0x8a, 0x45, 0x4c, - 0x15, 0xf4, 0x2d, 0xe5, 0x6b, 0x21, 0x1d, 0x3c, 0x81, 0x55, 0x49, 0x26, 0x33, 0xb9, 0x96, 0x31, - 0xd7, 0x12, 0x25, 0x4f, 0x65, 0x5b, 0x87, 0x05, 0xd1, 0x24, 0xa7, 0x6f, 0xc9, 0xdc, 0x62, 0x25, - 0xac, 0x88, 0xd6, 0xa3, 0xa6, 0x34, 0x4f, 0x89, 0x26, 0xa6, 0x3d, 0xe3, 0x57, 0xec, 0xbb, 0x30, - 0x4f, 0x24, 0x83, 0xea, 0x15, 0x72, 0xfa, 0x35, 0xe4, 0xf4, 0xcb, 0xca, 0xc2, 0x19, 0xa5, 0x22, - 0xb3, 0xaf, 0xf7, 0x13, 0xdf, 0x62, 0x39, 0x0c, 0x9d, 0x13, 0x1e, 0x3a, 0x23, 0xde, 0x5c, 0x25, - 0x02, 0x53, 0xdf, 0x62, 0xa5, 0x4e, 0xc6, 0x98, 0xd2, 0x24, 0xbe, 0x40, 0x5f, 0x48, 0xbb, 0x43, - 0x2f, 0xe0, 0xca, 0x44, 0xd5, 0xbc, 0x29, 0x17, 0xa1, 0x00, 0x2a, 0x19, 0x52, 0x08, 0xe2, 0xa4, - 0xf4, 0x44, 0x86, 0xc4, 0x5b, 0x48, 0x0c, 0x35, 0xd2, 0x7d, 0x94, 0x31, 0x51, 0xec, 0xe2, 0x67, - 0xf6, 0x85, 0xe2, 0x20, 0xb7, 0x71, 0x7e, 0x41, 0x80, 0x24, 0xef, 0xf8, 0xc3, 0x0c, 0x6d, 0x88, - 0x92, 0x7f, 0x04, 0x9a, 0x7a, 0x47, 0x9c, 0xc3, 0xf2, 0xdc, 0xe1, 0x95, 0x64, 0x26, 0x40, 0xa0, - 0x03, 0x77, 0x88, 0xab, 0xd9, 0x71, 0x75, 0x14, 0xe2, 0xbd, 0x55, 0x05, 0x44, 0xa4, 0xbb, 0x50, - 0x19, 0x4f, 0x8e, 0x87, 0x4e, 0x9f, 0x50, 0x72, 0x54, 0x0a, 0x81, 0x10, 0x41, 0xe8, 0xb7, 0x44, - 0x51, 0x84, 0x91, 0x47, 0x8c, 0x8a, 0x84, 0x21, 0x0a, 0xf2, 0x76, 0xee, 0x23, 0x3b, 0xa9, 0x9a, - 0xf8, 0xdb, 0xd8, 0x80, 0xa5, 0x64, 0xa3, 0xe5, 0xc6, 0xf3, 0x00, 0x4a, 0x92, 0x57, 0x29, 0xc3, - 0x47, 0x5d, 0x33, 0x45, 0x0b, 0x15, 0x2d, 0x4a, 0x37, 0x7e, 0xaf, 0x00, 0x8b, 0x12, 0xba, 0x29, - 0x86, 0xb6, 0x3b, 0x19, 0x8d, 0x6c, 0x3f, 0x85, 0x09, 0x66, 0x5e, 0xce, 0x04, 0xb3, 0x33, 0x4c, - 0x30, 0xa9, 0xf9, 0x12, 0x0f, 0x4d, 0x6a, 0xbe, 0x62, 0x2e, 0x49, 0x19, 0xd1, 0xed, 0xa0, 0x35, - 0x09, 0xee, 0x91, 0xbd, 0x75, 0x86, 0x65, 0x17, 0x52, 0x58, 0xb6, 0xce, 0x70, 0xe7, 0xa6, 0x18, - 0xee, 0x9b, 0x40, 0x44, 0xa3, 0x66, 0xbf, 0x48, 0xfa, 0x09, 0xc2, 0xa4, 0x31, 0xf5, 0x5d, 0x98, - 0x9f, 0xe6, 0x71, 0xc4, 0x4c, 0xeb, 0x29, 0x1c, 0xce, 0x19, 0x71, 0xdc, 0xad, 0x34, 0xe4, 0xb2, - 0xe4, 0x70, 0xce, 0x88, 0xef, 0x62, 0x8a, 0xc2, 0x6f, 0x03, 0x50, 0xdd, 0xb8, 0x68, 0x00, 0x17, - 0xcd, 0x3b, 0xc9, 0xb9, 0xd0, 0x47, 0x7d, 0x5d, 0x7c, 0x4c, 0x7c, 0x8e, 0xab, 0xa8, 0x8c, 0x39, - 0x71, 0x01, 0x7d, 0x04, 0x75, 0x6f, 0xcc, 0x5d, 0x2b, 0xe6, 0x35, 0x15, 0x2c, 0xaa, 0x21, 0x8b, - 0xea, 0x28, 0xb8, 0x59, 0x13, 0x78, 0xd1, 0x27, 0xfb, 0x0e, 0x0d, 0x32, 0xd7, 0x72, 0x56, 0xaf, - 0xc9, 0x59, 0x47, 0xc4, 0xe8, 0xdb, 0xf8, 0x1b, 0x19, 0xa8, 0x68, 0xcd, 0x61, 0xcb, 0xb0, 0xb0, - 0x79, 0x70, 0x70, 0xd8, 0x36, 0x5b, 0xbd, 0xce, 0x67, 0x6d, 0x6b, 0x73, 0xf7, 0xa0, 0xdb, 0x6e, - 0xdc, 0x10, 0xe0, 0xdd, 0x83, 0xcd, 0xd6, 0xae, 0xb5, 0x7d, 0x60, 0x6e, 0x2a, 0x70, 0x86, 0xad, - 0x00, 0x33, 0xdb, 0x7b, 0x07, 0xbd, 0x76, 0x02, 0x9e, 0x65, 0x0d, 0xa8, 0x6e, 0x98, 0xed, 0xd6, - 0xe6, 0x8e, 0x84, 0xe4, 0xd8, 0x12, 0x34, 0xb6, 0x8f, 0xf6, 0xb7, 0x3a, 0xfb, 0x4f, 0xad, 0xcd, - 0xd6, 0xfe, 0x66, 0x7b, 0xb7, 0xbd, 0xd5, 0xc8, 0xb3, 0x1a, 0x94, 0x5b, 0x1b, 0xad, 0xfd, 0xad, - 0x83, 0xfd, 0xf6, 0x56, 0xa3, 0x60, 0xfc, 0x79, 0x06, 0x96, 0x71, 0xa0, 0x06, 0xd3, 0x2b, 0xf4, - 0x1e, 0x54, 0xfa, 0x9e, 0x37, 0x16, 0x6a, 0x50, 0xbc, 0xdd, 0xeb, 0x20, 0xb1, 0xfa, 0x88, 0xb3, - 0x9e, 0x78, 0x7e, 0x9f, 0xcb, 0x05, 0x0a, 0x08, 0xda, 0x16, 0x10, 0x41, 0x20, 0x92, 0xc2, 0x08, - 0x83, 0xd6, 0x67, 0x85, 0x60, 0x84, 0xb2, 0x02, 0x73, 0xc7, 0x3e, 0xb7, 0xfb, 0x67, 0x72, 0x69, - 0xca, 0x2f, 0xf6, 0x5e, 0xac, 0xa0, 0xf7, 0xc5, 0x84, 0x0f, 0xf9, 0x00, 0xe9, 0xb3, 0x64, 0xce, - 0x4b, 0xf8, 0xa6, 0x04, 0x8b, 0xad, 0xc2, 0x3e, 0xb6, 0xdd, 0x81, 0xe7, 0xf2, 0x81, 0xd4, 0x03, - 0x62, 0x80, 0x71, 0x08, 0x2b, 0xd3, 0xfd, 0x93, 0x8b, 0xf9, 0x43, 0x6d, 0x31, 0x93, 0x58, 0xbe, - 0x76, 0x3d, 0x01, 0x69, 0x0b, 0xfb, 0x6f, 0xe5, 0x21, 0x2f, 0xc4, 0xb4, 0x6b, 0x25, 0x3a, 0x5d, - 0xee, 0xce, 0xcd, 0xf8, 0x66, 0xd0, 0x0e, 0x40, 0xfb, 0x37, 0x19, 0x9b, 0xca, 0x08, 0xc1, 0x7d, - 0x3b, 0x4a, 0xf6, 0x79, 0xff, 0x5c, 0x5a, 0x9b, 0x28, 0xd9, 0xe4, 0xfd, 0x73, 0x54, 0x78, 0xec, - 0x90, 0xf2, 0xd2, 0x62, 0x2c, 0x06, 0x76, 0x88, 0x39, 0x65, 0x12, 0xe6, 0x2b, 0x46, 0x49, 0x98, - 0xab, 0x09, 0x45, 0xc7, 0x3d, 0xf6, 0x26, 0xee, 0x00, 0xd7, 0x5e, 0xc9, 0x54, 0x9f, 0xe8, 0x0a, - 0x42, 0x36, 0x21, 0x76, 0x09, 0x5a, 0x6a, 0x25, 0x01, 0xe8, 0x89, 0x7d, 0xe2, 0x03, 0x28, 0x07, - 0x57, 0x6e, 0x5f, 0x5f, 0x60, 0x4b, 0x72, 0x7c, 0x44, 0xef, 0xd7, 0xbb, 0x57, 0x6e, 0x1f, 0x97, - 0x53, 0x29, 0x90, 0xbf, 0xd8, 0x13, 0x28, 0x45, 0x46, 0x59, 0x62, 0x8f, 0x37, 0xf5, 0x1c, 0xca, - 0x12, 0x4b, 0xba, 0x6f, 0x84, 0xca, 0x1e, 0xc2, 0x1c, 0x5a, 0x4e, 0x83, 0x66, 0x15, 0x33, 0x29, - 0x61, 0x5c, 0x34, 0x03, 0xbd, 0x30, 0x7c, 0x80, 0x56, 0x54, 0x53, 0xa2, 0xad, 0x3d, 0x83, 0x5a, - 0xa2, 0x2c, 0x5d, 0xc3, 0xad, 0x91, 0x86, 0xfb, 0xb6, 0xae, 0xe1, 0xc6, 0x6c, 0x5a, 0x66, 0xd3, - 0x35, 0xde, 0x5f, 0x84, 0x92, 0xea, 0x8a, 0x58, 0x44, 0x47, 0xfb, 0xcf, 0xf6, 0x0f, 0x3e, 0xdf, - 0xb7, 0xba, 0xcf, 0xf7, 0x37, 0x1b, 0x37, 0xd8, 0x3c, 0x54, 0x5a, 0x9b, 0xb8, 0x2e, 0x11, 0x90, - 0x11, 0x28, 0x87, 0xad, 0x6e, 0x37, 0x82, 0x64, 0x8d, 0x6d, 0x68, 0x4c, 0xb7, 0x54, 0xd0, 0x64, - 0xa8, 0x60, 0xd2, 0xae, 0x1c, 0x03, 0x84, 0xfe, 0x42, 0xa6, 0x62, 0x12, 0x92, 0xe9, 0xc3, 0x78, - 0x02, 0x0d, 0xb1, 0xe9, 0x88, 0xa1, 0x0a, 0x34, 0xfb, 0xec, 0x50, 0x08, 0x5e, 0xba, 0x6d, 0xb9, - 0x64, 0x56, 0x08, 0x86, 0x55, 0x19, 0x1f, 0xc2, 0x82, 0x96, 0x2d, 0xd6, 0x37, 0xc5, 0x46, 0x36, - 0xad, 0x6f, 0xa2, 0x76, 0x41, 0x29, 0xc6, 0x2a, 0x2c, 0x8b, 0xcf, 0xf6, 0x39, 0x77, 0xc3, 0xee, - 0xe4, 0x98, 0x1c, 0x82, 0x8e, 0xe7, 0x0a, 0xad, 0xa3, 0x1c, 0xa5, 0x5c, 0x4f, 0xe4, 0xeb, 0x52, - 0x35, 0xcd, 0x22, 0x69, 0xac, 0x69, 0x35, 0x60, 0xc6, 0x75, 0xfc, 0x9b, 0x50, 0x51, 0xcb, 0x11, - 0x48, 0x0c, 0xeb, 0x61, 0xbb, 0x6d, 0x5a, 0x07, 0xfb, 0xbb, 0x9d, 0x7d, 0xc1, 0xed, 0xc4, 0xb0, - 0x22, 0x60, 0x7b, 0x1b, 0x21, 0x19, 0xa3, 0x01, 0xf5, 0xa7, 0x3c, 0xec, 0xb8, 0x27, 0x9e, 0x72, - 0x7e, 0xfd, 0x45, 0x01, 0xe6, 0x23, 0x50, 0xac, 0xe2, 0x9e, 0x73, 0x3f, 0x70, 0x3c, 0x17, 0xa5, - 0xd5, 0xb2, 0xa9, 0x3e, 0xc5, 0xd6, 0xe3, 0x0c, 0xb8, 0x1b, 0x3a, 0xe1, 0x95, 0x95, 0xb0, 0x87, - 0xd5, 0x15, 0x58, 0x6e, 0x71, 0x4b, 0x50, 0xb0, 0x87, 0x8e, 0xad, 0xfc, 0xa8, 0xf4, 0x21, 0xa0, - 0x7d, 0x6f, 0xe8, 0xf9, 0x28, 0x98, 0x96, 0x4d, 0xfa, 0x60, 0x8f, 0x60, 0x49, 0x08, 0xc8, 0xba, - 0x91, 0x12, 0xf9, 0x07, 0x99, 0xe6, 0x98, 0x3b, 0x19, 0x1d, 0xc6, 0x86, 0x4a, 0x91, 0x22, 0x36, - 0x36, 0x91, 0x43, 0x4a, 0x32, 0x51, 0x06, 0xd2, 0xb5, 0x16, 0xdc, 0xc9, 0xa8, 0x85, 0x29, 0x11, - 0xfe, 0x63, 0x58, 0x16, 0xf8, 0x91, 0xec, 0x13, 0xe5, 0x98, 0xc7, 0x1c, 0xa2, 0xb0, 0x8e, 0x4c, - 0x8b, 0xf2, 0xdc, 0x82, 0x32, 0xb5, 0x4a, 0xcc, 0x78, 0x81, 0x64, 0x6c, 0x6c, 0x0a, 0xf7, 0x83, - 0x19, 0x97, 0xe7, 0x1c, 0xed, 0xd2, 0x53, 0x2e, 0x4f, 0xcd, 0x69, 0x5a, 0x9a, 0x76, 0x9a, 0x3e, - 0x86, 0xe5, 0x63, 0x41, 0x82, 0x67, 0xdc, 0x1e, 0x70, 0xdf, 0x8a, 0x09, 0x9b, 0x74, 0x89, 0x45, - 0x91, 0xb8, 0x83, 0x69, 0xd1, 0x3a, 0x10, 0x42, 0x88, 0x60, 0x0b, 0x7c, 0x60, 0x85, 0x9e, 0x85, - 0xb2, 0x09, 0x32, 0x98, 0x92, 0x59, 0x23, 0x70, 0xcf, 0xdb, 0x14, 0xc0, 0x24, 0xde, 0xa9, 0x6f, - 0x8f, 0xcf, 0xa4, 0xb4, 0x1f, 0xe1, 0x3d, 0x15, 0x40, 0x76, 0x1b, 0x8a, 0x82, 0xe4, 0x5d, 0x4e, - 0x9e, 0x29, 0x92, 0xa7, 0x15, 0x88, 0xbd, 0x0d, 0x73, 0x58, 0x47, 0xd0, 0x6c, 0x20, 0xbd, 0x57, - 0x63, 0x46, 0xee, 0xb8, 0xa6, 0x4c, 0x13, 0x92, 0xde, 0xc4, 0x77, 0x88, 0xcb, 0x94, 0x4d, 0xfc, - 0xcd, 0xbe, 0xa7, 0xb1, 0xac, 0x45, 0xcc, 0xfb, 0xb6, 0xcc, 0x3b, 0x45, 0x69, 0xd7, 0x71, 0xaf, - 0x9f, 0x29, 0x33, 0xfa, 0x7e, 0xbe, 0x54, 0x69, 0x54, 0x8d, 0x8f, 0xa0, 0x40, 0xa3, 0x23, 0x88, - 0x10, 0xc7, 0x2e, 0x23, 0x89, 0x10, 0xa1, 0x4d, 0x28, 0xba, 0x3c, 0xbc, 0xf0, 0xfc, 0x17, 0xca, - 0x62, 0x2c, 0x3f, 0x8d, 0x1f, 0xa1, 0xa9, 0x23, 0x72, 0x87, 0x93, 0xd6, 0x26, 0xc8, 0x83, 0xa6, - 0x37, 0x38, 0xb3, 0xa5, 0xf5, 0xa5, 0x84, 0x80, 0xee, 0x99, 0x3d, 0x43, 0x1e, 0xd9, 0x59, 0x8f, - 0xf8, 0xdb, 0x50, 0x57, 0x0e, 0xf8, 0xc0, 0x1a, 0xf2, 0x93, 0x50, 0x92, 0x7b, 0x55, 0x7a, 0xdf, - 0x83, 0x5d, 0x7e, 0x12, 0x1a, 0x7b, 0xb0, 0x20, 0x09, 0xf2, 0x60, 0xcc, 0x55, 0xd5, 0xdf, 0x4e, - 0x13, 0x76, 0x2b, 0x8f, 0x17, 0x93, 0x1b, 0x2d, 0x05, 0x16, 0x24, 0x24, 0x60, 0xe3, 0x53, 0x60, - 0xfa, 0x36, 0x2c, 0xcb, 0x93, 0x22, 0xa7, 0x32, 0xb4, 0x2b, 0x7f, 0x55, 0x24, 0xd8, 0x3a, 0x03, - 0x31, 0x3a, 0xc1, 0xa4, 0xdf, 0x57, 0x81, 0x11, 0x25, 0x53, 0x7d, 0x1a, 0x7f, 0x92, 0x81, 0x45, - 0x2c, 0x4c, 0x09, 0xeb, 0x92, 0xc9, 0xfe, 0xc4, 0x8d, 0x14, 0xf3, 0xa3, 0xcb, 0x3e, 0xf4, 0xf1, - 0xd5, 0x4d, 0x9b, 0xf9, 0x19, 0xd3, 0xe6, 0x7b, 0xd0, 0x18, 0xf0, 0xa1, 0x83, 0x31, 0x32, 0x4a, - 0x94, 0x20, 0xf1, 0x7c, 0x5e, 0xc1, 0xa5, 0xaa, 0x66, 0xfc, 0xbd, 0x0c, 0x2c, 0x90, 0xa4, 0x82, - 0x4a, 0xaf, 0x1c, 0xa8, 0x4f, 0x94, 0x96, 0x27, 0x59, 0x95, 0xec, 0x53, 0xbc, 0x83, 0x23, 0x94, - 0x90, 0x77, 0x6e, 0x48, 0xed, 0x4f, 0x42, 0xd9, 0xc7, 0xa8, 0x60, 0xb8, 0x16, 0x02, 0x53, 0x62, - 0x6e, 0x92, 0x93, 0xb2, 0x73, 0x03, 0xb5, 0x0f, 0x17, 0x41, 0x1b, 0x25, 0xa1, 0x76, 0x0a, 0xb0, - 0xb1, 0x0d, 0xb5, 0x44, 0x35, 0x09, 0xfb, 0x6b, 0x95, 0xec, 0xaf, 0x33, 0x3e, 0x8e, 0xec, 0xac, - 0x8f, 0xe3, 0x0a, 0x16, 0x4d, 0x6e, 0x0f, 0xae, 0xb6, 0x3d, 0xff, 0x30, 0x38, 0x0e, 0xb7, 0x49, - 0xfc, 0x13, 0xfc, 0x3d, 0x72, 0xdc, 0x25, 0x8c, 0x9c, 0xca, 0x7f, 0xa3, 0x74, 0xd9, 0xaf, 0x41, - 0x3d, 0xf6, 0xf0, 0x69, 0x86, 0xb2, 0x5a, 0xe4, 0xe4, 0x43, 0x7b, 0x99, 0xd0, 0x03, 0x83, 0xe3, - 0x50, 0x9a, 0xca, 0xf0, 0xb7, 0xf1, 0xd7, 0xf2, 0xc0, 0x04, 0x35, 0x4f, 0x11, 0xcc, 0x94, 0x6f, - 0x32, 0x3b, 0xe3, 0x9b, 0x7c, 0x04, 0x4c, 0x43, 0x50, 0x2e, 0xd3, 0x5c, 0xe4, 0x32, 0x6d, 0xc4, - 0xb8, 0xd2, 0x63, 0xfa, 0x08, 0x96, 0xa4, 0x2c, 0x9d, 0x6c, 0x2a, 0x91, 0x06, 0x23, 0xa1, 0x3a, - 0xd1, 0x5e, 0xe5, 0x97, 0x14, 0xba, 0x39, 0x99, 0xc2, 0xd0, 0x2f, 0xa9, 0xb4, 0x72, 0x8d, 0x00, - 0xe7, 0x5e, 0x49, 0x80, 0xc5, 0x19, 0x02, 0xd4, 0x2c, 0x33, 0xa5, 0xa4, 0x65, 0xc6, 0x80, 0x9a, - 0xf2, 0x3e, 0x52, 0xd0, 0x05, 0x09, 0x8e, 0x15, 0xe9, 0x82, 0xc4, 0xc0, 0x8b, 0xfb, 0xd0, 0x50, - 0xe6, 0x93, 0xc8, 0xf6, 0x43, 0x01, 0x05, 0xd2, 0xfa, 0xb6, 0xa9, 0x2c, 0x40, 0x09, 0x4b, 0x7b, - 0x65, 0xca, 0xd2, 0xfe, 0x3e, 0x2c, 0x04, 0x82, 0x7e, 0xad, 0x89, 0x2b, 0xa3, 0x7f, 0xf8, 0x00, - 0xd5, 0xac, 0x92, 0xd9, 0xc0, 0x84, 0xa3, 0x18, 0x3e, 0x6b, 0xd7, 0xa8, 0xa5, 0xd8, 0x35, 0x9e, - 0xc4, 0x8e, 0xba, 0xe0, 0xcc, 0x19, 0xa1, 0xcc, 0x10, 0x47, 0xca, 0xc8, 0x01, 0xee, 0x9e, 0x39, - 0x23, 0x53, 0x79, 0x85, 0xc5, 0x87, 0xf1, 0xbf, 0x33, 0xd0, 0x10, 0x74, 0x90, 0x58, 0x62, 0xdf, - 0x01, 0x64, 0x06, 0xaf, 0xb9, 0xc2, 0x2a, 0x02, 0x57, 0x2d, 0xb0, 0x8f, 0x00, 0x57, 0x8c, 0x25, - 0x74, 0x4a, 0xb9, 0xbe, 0x9a, 0xc9, 0xf5, 0x15, 0xf3, 0xd0, 0x9d, 0x1b, 0xa4, 0x7b, 0x08, 0x08, - 0xfb, 0x0e, 0x94, 0x05, 0x61, 0x22, 0x95, 0xc8, 0x00, 0x2d, 0x25, 0x79, 0xa5, 0xac, 0x11, 0x91, - 0x75, 0x2c, 0x3f, 0xd3, 0x7c, 0xab, 0xf9, 0x14, 0xdf, 0xaa, 0xb6, 0x80, 0x77, 0x00, 0x9e, 0xf1, - 0xab, 0x5d, 0xaf, 0x8f, 0x1a, 0xef, 0x1d, 0x00, 0x41, 0xcb, 0x27, 0xf6, 0xc8, 0x91, 0x06, 0x9b, - 0x82, 0x59, 0x7e, 0xc1, 0xaf, 0xb6, 0x11, 0x20, 0x26, 0x52, 0x24, 0xc7, 0xab, 0xb8, 0x60, 0x96, - 0x5e, 0xf0, 0x2b, 0x5a, 0xc2, 0x16, 0xd4, 0x9e, 0xf1, 0xab, 0x2d, 0x4e, 0x42, 0xa6, 0xe7, 0x0b, - 0x22, 0xf2, 0xed, 0x0b, 0x21, 0x55, 0x26, 0xfc, 0xa2, 0x15, 0xdf, 0xbe, 0x78, 0xc6, 0xaf, 0x94, - 0x8f, 0xb6, 0x28, 0xd2, 0x87, 0x5e, 0x5f, 0xee, 0x9b, 0x2a, 0xc2, 0x23, 0x6e, 0x94, 0x39, 0xf7, - 0x02, 0x7f, 0x1b, 0x7f, 0x99, 0x81, 0x9a, 0x68, 0x3f, 0xb2, 0x65, 0x31, 0x65, 0x2a, 0x50, 0x28, - 0x13, 0x07, 0x0a, 0x3d, 0x96, 0x5c, 0x8d, 0x78, 0x7c, 0xf6, 0x7a, 0x1e, 0x8f, 0x73, 0x43, 0x0c, - 0xfe, 0x03, 0x28, 0xd3, 0xb2, 0x14, 0xeb, 0x3c, 0x97, 0x98, 0xe0, 0x44, 0x87, 0xcc, 0x12, 0xa2, - 0x3d, 0xa3, 0xb8, 0x04, 0xcd, 0xf8, 0x47, 0x43, 0x5c, 0xf6, 0x23, 0x93, 0x5f, 0xca, 0x34, 0x14, - 0xae, 0x89, 0x4b, 0xd0, 0x2d, 0x6b, 0x73, 0x33, 0x96, 0xb5, 0x03, 0x28, 0x89, 0xa9, 0xc6, 0xce, - 0xa6, 0x14, 0x9a, 0x49, 0x2b, 0x54, 0x48, 0x02, 0xb6, 0xd8, 0x14, 0x04, 0xa3, 0xcb, 0x4a, 0x49, - 0xc0, 0x0e, 0xf8, 0x21, 0x32, 0xbb, 0x0c, 0x54, 0xb4, 0x15, 0x80, 0xc6, 0xc9, 0x68, 0xbc, 0x68, - 0xb9, 0x24, 0x49, 0x3c, 0x31, 0xe0, 0x3b, 0x37, 0xcc, 0x5a, 0x3f, 0x31, 0x03, 0xeb, 0x92, 0x56, - 0x31, 0x67, 0x36, 0x11, 0xd3, 0xa4, 0x1a, 0xae, 0x08, 0x54, 0xfc, 0xde, 0x98, 0x83, 0xbc, 0x40, - 0x35, 0x3e, 0x81, 0x05, 0xad, 0x19, 0xa4, 0xe6, 0xbf, 0x6e, 0x0f, 0x8d, 0x5f, 0x89, 0x32, 0x8b, - 0x3a, 0xc8, 0x7d, 0xa4, 0x62, 0x3c, 0xf8, 0x80, 0x3a, 0x2e, 0x63, 0x49, 0x08, 0x24, 0xd0, 0x5e, - 0x3b, 0xee, 0xe0, 0xd7, 0x60, 0x51, 0x2b, 0x7d, 0xdb, 0x71, 0xed, 0xa1, 0xf3, 0x23, 0xdc, 0xf0, - 0x03, 0xe7, 0xd4, 0x9d, 0x2a, 0x9f, 0x40, 0x5f, 0xa9, 0xfc, 0xbf, 0x9f, 0x85, 0x25, 0x59, 0x01, - 0x46, 0xed, 0x39, 0x42, 0x8a, 0xdb, 0x0b, 0x4e, 0xd9, 0x77, 0xa0, 0x26, 0xc6, 0xc6, 0xf2, 0xf9, - 0xa9, 0x13, 0x84, 0x5c, 0xb9, 0xad, 0x52, 0x18, 0x97, 0xd8, 0xcc, 0x05, 0xaa, 0x29, 0x31, 0xd9, - 0x27, 0x50, 0xc1, 0xac, 0x64, 0x46, 0x91, 0x13, 0xd1, 0x9c, 0xcd, 0x48, 0x03, 0xbd, 0x73, 0xc3, - 0x84, 0x20, 0x1e, 0xf6, 0x4f, 0xa0, 0x82, 0x73, 0x78, 0x8e, 0x03, 0x39, 0xc5, 0xaa, 0x66, 0x06, - 0x5a, 0x64, 0x1e, 0xc7, 0xc3, 0xde, 0x82, 0x1a, 0x31, 0x2b, 0x39, 0x4e, 0x32, 0x1a, 0x68, 0x6d, - 0x36, 0xbb, 0x1a, 0x49, 0xd1, 0xf8, 0xb1, 0xf6, 0xbd, 0x51, 0x86, 0x62, 0xe8, 0x3b, 0xa7, 0xa7, - 0xdc, 0x37, 0x56, 0xa2, 0xa1, 0x11, 0x5c, 0x98, 0x77, 0x43, 0x3e, 0x16, 0xb2, 0xb9, 0xf1, 0x6f, - 0x33, 0x50, 0x91, 0x7c, 0xf5, 0x27, 0xf6, 0x95, 0xad, 0x69, 0x61, 0xaf, 0x64, 0xb1, 0x89, 0xa3, - 0x5c, 0xdf, 0x85, 0xf9, 0x91, 0x90, 0xd3, 0x85, 0x1e, 0x99, 0x70, 0x94, 0xd5, 0x15, 0x58, 0x8a, - 0xc9, 0xeb, 0xb0, 0x88, 0x52, 0x73, 0x60, 0x85, 0xce, 0xd0, 0x52, 0x89, 0x32, 0xc4, 0x74, 0x81, - 0x92, 0x7a, 0xce, 0x70, 0x4f, 0x26, 0x08, 0xe1, 0x31, 0x08, 0xed, 0x53, 0x2e, 0xd7, 0x36, 0x7d, - 0x18, 0x4d, 0x58, 0x99, 0x52, 0x21, 0x95, 0xfa, 0xfb, 0x7f, 0x16, 0x60, 0x75, 0x26, 0x49, 0xaa, - 0xc1, 0x91, 0x83, 0x68, 0xe8, 0x8c, 0x8e, 0xbd, 0xc8, 0x7c, 0x9a, 0xd1, 0x1c, 0x44, 0xbb, 0x22, - 0x45, 0x99, 0x4f, 0x39, 0x2c, 0x2b, 0x82, 0x44, 0xfb, 0x67, 0xa4, 0x65, 0x66, 0x51, 0x07, 0xfa, - 0x20, 0xb9, 0x89, 0x4d, 0x57, 0xa7, 0xe0, 0xba, 0x68, 0xb4, 0x38, 0x9e, 0x81, 0x05, 0xec, 0xd7, - 0xa1, 0x19, 0xd1, 0xbd, 0x14, 0xdb, 0x35, 0x95, 0x59, 0xd4, 0xf4, 0xf5, 0x57, 0xd4, 0x94, 0xb0, - 0xdd, 0xa1, 0xec, 0xb4, 0xa2, 0x96, 0x0c, 0x15, 0x18, 0xd5, 0x75, 0x0e, 0x6f, 0xa8, 0xba, 0x50, - 0x0c, 0x9f, 0xad, 0x31, 0xff, 0x5a, 0x7d, 0x43, 0xbb, 0x64, 0xa2, 0x5a, 0xf3, 0x96, 0x2c, 0x38, - 0x4a, 0xd2, 0xeb, 0x3d, 0x83, 0x95, 0x0b, 0xdb, 0x09, 0x55, 0x1f, 0x35, 0x8d, 0xbd, 0x80, 0xf5, - 0x3d, 0x7e, 0x45, 0x7d, 0x9f, 0x53, 0xe6, 0x84, 0x62, 0xb2, 0x74, 0x31, 0x0b, 0x0c, 0xd6, 0xfe, - 0x71, 0x0e, 0xea, 0xc9, 0x52, 0x04, 0x63, 0x91, 0x9b, 0x8d, 0x92, 0x37, 0xa5, 0x10, 0x2c, 0x4d, - 0xfb, 0xfb, 0x24, 0x67, 0xce, 0x3a, 0x1d, 0xb2, 0x29, 0x4e, 0x07, 0xdd, 0xd6, 0x9f, 0x7b, 0x95, - 0x73, 0x35, 0xff, 0x5a, 0xce, 0xd5, 0x42, 0x9a, 0x73, 0xf5, 0x7a, 0x8f, 0xdc, 0xdc, 0x4f, 0xe4, - 0x91, 0x2b, 0xbe, 0xd4, 0x23, 0xa7, 0xf9, 0x11, 0x4b, 0xd7, 0x58, 0xe8, 0x35, 0xcf, 0x62, 0x8a, - 0x47, 0xae, 0xfc, 0x15, 0x3c, 0x72, 0x6b, 0x7f, 0x99, 0x01, 0x36, 0xbb, 0x3a, 0xd8, 0x53, 0xf2, - 0xe7, 0xb8, 0x7c, 0x28, 0x39, 0xf7, 0x37, 0x5e, 0x6f, 0x85, 0x29, 0x82, 0x50, 0xb9, 0xd9, 0x43, - 0x58, 0xd4, 0x03, 0xe1, 0x75, 0xad, 0xbd, 0x66, 0x32, 0x3d, 0x29, 0xb6, 0xed, 0x68, 0x9e, 0xec, - 0xfc, 0x2b, 0x3d, 0xd9, 0x85, 0x57, 0x7a, 0xb2, 0xe7, 0x92, 0x9e, 0xec, 0xb5, 0xff, 0x98, 0x81, - 0xc5, 0x14, 0x22, 0xfe, 0xd9, 0xf5, 0x59, 0xd0, 0x5e, 0x82, 0xad, 0x65, 0x25, 0xed, 0xe9, 0x1c, - 0x6d, 0x17, 0x2a, 0xf1, 0x54, 0xa8, 0x83, 0x22, 0x0f, 0x5e, 0xc5, 0x5d, 0xe2, 0x1c, 0xa6, 0x9e, - 0x7d, 0xed, 0xf7, 0xb2, 0x50, 0xd1, 0x12, 0xc5, 0x28, 0x12, 0xc9, 0x6a, 0x01, 0x44, 0x24, 0x19, - 0xa2, 0xcd, 0xe1, 0x2e, 0x48, 0xa7, 0x06, 0xa5, 0xd3, 0xe2, 0x92, 0x62, 0x20, 0x22, 0xac, 0xc3, - 0xa2, 0xf2, 0xb5, 0xf1, 0x38, 0x4e, 0x50, 0xee, 0x35, 0x0b, 0xd2, 0xe3, 0xc6, 0xa3, 0xb0, 0x43, - 0xf6, 0x50, 0xa9, 0x83, 0xf1, 0xdc, 0x21, 0xa9, 0x93, 0xc7, 0x60, 0x81, 0x16, 0x88, 0x9a, 0x44, - 0x41, 0xe7, 0x1f, 0xc0, 0xb2, 0x5a, 0x1e, 0xc9, 0x1c, 0xe4, 0x44, 0x60, 0x72, 0x71, 0xe8, 0x59, - 0xbe, 0x07, 0x77, 0xa6, 0xda, 0x34, 0x95, 0x95, 0x02, 0x5a, 0x6f, 0x26, 0x5a, 0xa7, 0x97, 0xb0, - 0xf6, 0x63, 0xa8, 0x25, 0x18, 0xe5, 0xcf, 0x6e, 0xca, 0xa7, 0xed, 0x3c, 0x34, 0xa2, 0xba, 0x9d, - 0x67, 0xed, 0x7f, 0xe5, 0x80, 0xcd, 0xf2, 0xea, 0x9f, 0x67, 0x13, 0x66, 0x09, 0x33, 0x97, 0x42, - 0x98, 0xff, 0xcf, 0xe4, 0x87, 0xf7, 0x61, 0x41, 0x1e, 0x98, 0xd2, 0x1c, 0xa6, 0xb4, 0x38, 0x1b, - 0x51, 0x82, 0x6a, 0xc5, 0x47, 0xd3, 0x81, 0x1b, 0xa5, 0xc4, 0x19, 0x11, 0x4d, 0x80, 0x9a, 0x8a, - 0xdf, 0x38, 0x82, 0x39, 0xdb, 0xed, 0x9f, 0x79, 0xbe, 0xe4, 0x83, 0xbf, 0xf0, 0x95, 0xb7, 0xcf, - 0xf5, 0x16, 0xe6, 0x47, 0xa9, 0xcd, 0x94, 0x85, 0x19, 0x1f, 0x40, 0x45, 0x03, 0xb3, 0x32, 0x14, - 0x76, 0x3b, 0x7b, 0x1b, 0x07, 0x8d, 0x1b, 0xac, 0x06, 0x65, 0xb3, 0xbd, 0x79, 0xf0, 0x59, 0xdb, - 0x6c, 0x6f, 0x35, 0x32, 0xac, 0x04, 0xf9, 0xdd, 0x83, 0x6e, 0xaf, 0x91, 0x35, 0xd6, 0xa0, 0x29, - 0x4b, 0x9c, 0xf5, 0x59, 0xfc, 0x56, 0x3e, 0x32, 0x17, 0x62, 0xa2, 0x54, 0xd1, 0xbf, 0x09, 0x55, - 0x5d, 0xbc, 0x91, 0x14, 0x31, 0xe5, 0xb3, 0x17, 0xca, 0xb9, 0xa7, 0xf1, 0xea, 0x4d, 0x20, 0x8f, - 0xed, 0x20, 0xca, 0x96, 0x4d, 0xc8, 0xad, 0x29, 0xde, 0x41, 0x54, 0x7e, 0x12, 0x64, 0xf8, 0xff, - 0x41, 0x3d, 0x69, 0xc0, 0x97, 0x1c, 0x29, 0x4d, 0xe1, 0x14, 0xb9, 0x13, 0x16, 0x7d, 0xf6, 0x3d, - 0x68, 0x4c, 0x3b, 0x00, 0xa4, 0xf0, 0x7c, 0x4d, 0xfe, 0x79, 0x27, 0xe9, 0x13, 0x60, 0x3b, 0xb0, - 0x94, 0x26, 0xe0, 0x21, 0x7d, 0x5c, 0x6f, 0xa4, 0x60, 0xb3, 0x42, 0x1c, 0xfb, 0xb6, 0xf4, 0xf3, - 0x14, 0x70, 0xfa, 0xdf, 0x4e, 0xd6, 0xaf, 0x0d, 0xf6, 0x3a, 0xfd, 0xd3, 0x3c, 0x3e, 0xe7, 0x00, - 0x31, 0x8c, 0x35, 0xa0, 0x7a, 0x70, 0xd8, 0xde, 0xb7, 0x36, 0x77, 0x5a, 0xfb, 0xfb, 0xed, 0xdd, - 0xc6, 0x0d, 0xc6, 0xa0, 0x8e, 0xbe, 0xea, 0xad, 0x08, 0x96, 0x11, 0x30, 0xe9, 0x6f, 0x53, 0xb0, - 0x2c, 0x5b, 0x82, 0x46, 0x67, 0x7f, 0x0a, 0x9a, 0x63, 0x4d, 0x58, 0x3a, 0x6c, 0x93, 0x7b, 0x3b, - 0x51, 0x6e, 0x5e, 0x28, 0x0d, 0xb2, 0xbb, 0x42, 0x69, 0xa0, 0x83, 0x7f, 0x72, 0x1d, 0x28, 0x59, - 0xfa, 0xb7, 0x33, 0xb0, 0x3c, 0x95, 0x10, 0x1f, 0xe7, 0x20, 0x49, 0x3a, 0x29, 0x43, 0x57, 0x11, - 0xa8, 0x56, 0xd3, 0xfb, 0xb0, 0x10, 0x19, 0x9e, 0xa6, 0x76, 0xa5, 0x46, 0x94, 0xa0, 0x90, 0x1f, - 0xc2, 0xa2, 0x66, 0xbf, 0x9a, 0xe2, 0x15, 0x4c, 0x4b, 0x92, 0x19, 0x8c, 0xd5, 0x28, 0x6c, 0x7e, - 0xaa, 0xd5, 0x03, 0x3a, 0x4d, 0xa8, 0x27, 0xc4, 0x6e, 0xb0, 0x64, 0x7b, 0xd5, 0x27, 0x7b, 0x34, - 0x45, 0x08, 0xc9, 0xd6, 0xea, 0x13, 0xae, 0xaa, 0xff, 0xfd, 0x39, 0x60, 0x9f, 0x4e, 0xb8, 0x7f, - 0x85, 0xc7, 0x35, 0x82, 0x57, 0xc5, 0x2f, 0x2a, 0x4b, 0x4b, 0xf6, 0xb5, 0x8e, 0x64, 0xa5, 0x1d, - 0x89, 0xca, 0xbf, 0xfa, 0x48, 0x54, 0xe1, 0x55, 0x47, 0xa2, 0xde, 0x82, 0x9a, 0x73, 0xea, 0x7a, - 0x82, 0x15, 0x0a, 0x49, 0x38, 0x68, 0xce, 0xdd, 0xcb, 0xdd, 0xaf, 0x9a, 0x55, 0x09, 0x14, 0x72, - 0x70, 0xc0, 0x3e, 0x89, 0x91, 0xf8, 0xe0, 0x14, 0x8f, 0xef, 0xe9, 0x4c, 0xb0, 0x3d, 0x38, 0xe5, - 0xd2, 0xb0, 0x84, 0x9a, 0x86, 0xca, 0x2c, 0xe0, 0x01, 0x7b, 0x1b, 0xea, 0x81, 0x37, 0x11, 0x8a, - 0x85, 0x1a, 0x06, 0x72, 0x94, 0x55, 0x09, 0x7a, 0xa8, 0xbc, 0xa2, 0x8b, 0x93, 0x80, 0x5b, 0x23, - 0x27, 0x08, 0x84, 0x78, 0xd6, 0xf7, 0xdc, 0xd0, 0xf7, 0x86, 0xd2, 0xf7, 0xb5, 0x30, 0x09, 0xf8, - 0x1e, 0xa5, 0x6c, 0x52, 0x02, 0xfb, 0x56, 0xdc, 0xa4, 0xb1, 0xed, 0xf8, 0x41, 0x13, 0xb0, 0x49, - 0xaa, 0xa7, 0x28, 0xbf, 0xdb, 0x8e, 0x1f, 0xb5, 0x45, 0x7c, 0x04, 0x53, 0x47, 0xb5, 0x2a, 0xd3, - 0x47, 0xb5, 0x7e, 0x98, 0x7e, 0x54, 0xab, 0x86, 0x45, 0x3f, 0x92, 0x45, 0xcf, 0x4e, 0xf1, 0x57, - 0x3a, 0xb1, 0x35, 0x7b, 0x02, 0xad, 0xfe, 0x55, 0x4e, 0xa0, 0xcd, 0xa7, 0x9d, 0x40, 0xfb, 0x00, - 0x2a, 0x78, 0x36, 0xc8, 0x3a, 0x73, 0x84, 0x0c, 0x47, 0xbe, 0xbc, 0x86, 0x7e, 0x78, 0x68, 0xc7, - 0x71, 0x43, 0x13, 0x7c, 0xf5, 0x33, 0x98, 0x3d, 0x0c, 0xb6, 0xf0, 0x73, 0x3c, 0x0c, 0x26, 0xcf, - 0x30, 0xad, 0x43, 0x49, 0xcd, 0x13, 0x63, 0x90, 0x3f, 0xf1, 0xbd, 0x91, 0xf2, 0x71, 0x88, 0xdf, - 0xac, 0x0e, 0xd9, 0xd0, 0x93, 0x99, 0xb3, 0xa1, 0x67, 0xfc, 0x2a, 0x54, 0x34, 0x52, 0x63, 0x6f, - 0x92, 0x5d, 0x52, 0xe8, 0x66, 0x52, 0xb6, 0xa4, 0x51, 0x2c, 0x4b, 0x68, 0x67, 0x20, 0xf8, 0xcd, - 0xc0, 0xf1, 0x39, 0x1e, 0xdb, 0xb4, 0x7c, 0x7e, 0xce, 0xfd, 0x40, 0xf9, 0x9c, 0x1a, 0x51, 0x82, - 0x49, 0x70, 0xe3, 0xd7, 0x60, 0x31, 0x31, 0xb7, 0x92, 0x45, 0xbc, 0x0d, 0x73, 0x38, 0x6e, 0x2a, - 0x26, 0x20, 0x79, 0x28, 0x4b, 0xa6, 0xe1, 0x79, 0x7c, 0x72, 0x97, 0x59, 0x63, 0xdf, 0x3b, 0xc6, - 0x4a, 0x32, 0x66, 0x45, 0xc2, 0x0e, 0x7d, 0xef, 0xd8, 0xf8, 0xb3, 0x1c, 0xe4, 0x76, 0xbc, 0xb1, - 0x1e, 0xa3, 0x96, 0x99, 0x89, 0x51, 0x93, 0x0a, 0xa7, 0x15, 0x29, 0x94, 0x52, 0x66, 0x47, 0x47, - 0x91, 0x52, 0x2a, 0xef, 0x43, 0x5d, 0xf0, 0x89, 0xd0, 0x13, 0x1a, 0xfb, 0x85, 0xed, 0x93, 0x40, - 0x9c, 0xa3, 0xc5, 0x67, 0x8f, 0xc2, 0x9e, 0xb7, 0x4d, 0x70, 0xb6, 0x04, 0xb9, 0x48, 0x7d, 0xc1, - 0x64, 0xf1, 0xc9, 0x56, 0x60, 0x0e, 0x83, 0x95, 0xaf, 0xa4, 0xd3, 0x5b, 0x7e, 0xb1, 0x6f, 0xc0, - 0x62, 0xb2, 0x5c, 0x62, 0x45, 0x52, 0x36, 0xd2, 0x0b, 0x46, 0x9e, 0x74, 0x13, 0x04, 0x1f, 0x21, - 0x1c, 0x19, 0x3b, 0x73, 0xc2, 0x39, 0x26, 0x69, 0x4c, 0xaf, 0x94, 0x60, 0x7a, 0x77, 0xa1, 0x12, - 0x0e, 0xcf, 0xad, 0xb1, 0x7d, 0x35, 0xf4, 0xec, 0x81, 0x5c, 0xdf, 0x10, 0x0e, 0xcf, 0x0f, 0x09, - 0xc2, 0x1e, 0x02, 0x8c, 0xc6, 0x63, 0xb9, 0xf6, 0xd0, 0xf9, 0x11, 0x93, 0xf2, 0xde, 0xe1, 0x21, - 0x91, 0x9c, 0x59, 0x1e, 0x8d, 0xc7, 0xf4, 0x93, 0x6d, 0x41, 0x3d, 0xf5, 0x68, 0xe5, 0x1d, 0x15, - 0x5b, 0xeb, 0x8d, 0xd7, 0x53, 0x16, 0x67, 0xad, 0xaf, 0xc3, 0xd6, 0xbe, 0x07, 0xec, 0xa7, 0x3c, - 0xe0, 0xd8, 0x83, 0x72, 0xd4, 0x3e, 0xfd, 0x7c, 0x20, 0x46, 0xcb, 0x57, 0x12, 0xe7, 0x03, 0x5b, - 0x83, 0x81, 0x2f, 0xf8, 0x22, 0x6d, 0x98, 0x11, 0xcb, 0x07, 0x6d, 0xc7, 0x6c, 0x11, 0xdf, 0x37, - 0xfe, 0x6b, 0x06, 0x0a, 0x74, 0x58, 0xf1, 0x1d, 0x98, 0x27, 0xfc, 0x28, 0xde, 0x4f, 0xba, 0xca, - 0x69, 0xdf, 0xed, 0xc9, 0x50, 0x3f, 0xb1, 0x2c, 0xb4, 0x83, 0xd6, 0xd9, 0x68, 0xe6, 0xb5, 0xc3, - 0xd6, 0x77, 0xa1, 0x1c, 0x55, 0xad, 0x91, 0x4e, 0x49, 0xd5, 0xcc, 0xde, 0x80, 0xfc, 0x99, 0x37, - 0x56, 0x96, 0x1f, 0x88, 0x47, 0xd2, 0x44, 0x78, 0xdc, 0x16, 0x51, 0x07, 0x35, 0x5e, 0x5a, 0x2c, - 0xa2, 0x4a, 0x90, 0x0c, 0x66, 0xfb, 0x38, 0x97, 0xd2, 0xc7, 0x23, 0x98, 0x17, 0x7c, 0x40, 0x0b, - 0x59, 0xb9, 0x7e, 0xd3, 0x7c, 0x4f, 0x48, 0x78, 0xfd, 0xe1, 0x64, 0xc0, 0x75, 0xdb, 0x1b, 0xc6, - 0xb7, 0x49, 0xb8, 0x92, 0xac, 0x8d, 0xdf, 0xcf, 0x10, 0x7f, 0x11, 0xe5, 0xb2, 0xfb, 0x90, 0x17, - 0xfb, 0xdb, 0x94, 0x25, 0x3e, 0x3a, 0xb6, 0x20, 0xf0, 0x4c, 0xc4, 0xc0, 0xdb, 0x09, 0x26, 0xa3, - 0x64, 0xe9, 0x35, 0xb3, 0xe2, 0x4e, 0x46, 0x91, 0xe9, 0xea, 0x6b, 0xaa, 0x5b, 0x53, 0x66, 0x1f, - 0xea, 0x7d, 0xb4, 0x4c, 0xd7, 0xb5, 0x40, 0xb9, 0x7c, 0x62, 0xc7, 0x54, 0x52, 0xe0, 0xe0, 0x94, - 0x6b, 0x01, 0x72, 0x7f, 0x94, 0x85, 0x5a, 0xa2, 0x45, 0x18, 0x29, 0x28, 0x36, 0x00, 0x72, 0x2c, - 0xc9, 0xf9, 0x06, 0x01, 0x92, 0x82, 0xba, 0x36, 0x4e, 0xd9, 0xc4, 0x38, 0x45, 0xc1, 0x39, 0x39, - 0x3d, 0x38, 0xe7, 0x11, 0x94, 0xe3, 0x03, 0xf6, 0xc9, 0x26, 0x89, 0xfa, 0xd4, 0xe1, 0x8d, 0x18, - 0x29, 0x0e, 0xe7, 0x29, 0xe8, 0xe1, 0x3c, 0xdf, 0xd5, 0xa2, 0x3f, 0xe6, 0xb0, 0x18, 0x23, 0x6d, - 0x44, 0x7f, 0x2e, 0xb1, 0x1f, 0xc6, 0x27, 0x50, 0xd1, 0x1a, 0xaf, 0x47, 0x79, 0x64, 0x12, 0x51, - 0x1e, 0xd1, 0x31, 0xab, 0x6c, 0x7c, 0xcc, 0xca, 0xf8, 0xeb, 0x59, 0xa8, 0x89, 0xf5, 0xe5, 0xb8, - 0xa7, 0x87, 0xde, 0xd0, 0xe9, 0xa3, 0xa3, 0x29, 0x5a, 0x61, 0x52, 0xd0, 0x52, 0xeb, 0x4c, 0x2e, - 0x31, 0x92, 0xb3, 0xf4, 0xd3, 0xa4, 0xc4, 0xa4, 0xa3, 0xd3, 0xa4, 0x06, 0xd4, 0x04, 0x63, 0x44, - 0x97, 0x51, 0x7c, 0xfc, 0xdf, 0xac, 0x9c, 0x70, 0xbe, 0x61, 0x07, 0xc4, 0x21, 0xbf, 0x01, 0x8b, - 0x02, 0x07, 0x0f, 0xd2, 0x8d, 0x9c, 0xe1, 0xd0, 0x21, 0x4c, 0x32, 0x34, 0x35, 0x4e, 0x38, 0x37, - 0xed, 0x90, 0xef, 0x89, 0x04, 0x79, 0x5b, 0x40, 0x69, 0xe0, 0x04, 0xf6, 0x71, 0x1c, 0xcf, 0x19, - 0x7d, 0xa3, 0x67, 0xd9, 0xbe, 0xd4, 0x3c, 0xcb, 0x64, 0x80, 0xa8, 0x8c, 0xec, 0xcb, 0xc8, 0xb3, - 0x3c, 0x45, 0x49, 0xc5, 0x69, 0x4a, 0x32, 0xfe, 0x4d, 0x16, 0x2a, 0x1a, 0x59, 0xbe, 0xce, 0xee, - 0x7a, 0x67, 0xc6, 0x31, 0x58, 0xd6, 0x7d, 0x80, 0x6f, 0x25, 0xab, 0xc4, 0xd8, 0x17, 0xba, 0x97, - 0x40, 0x23, 0xe0, 0x5b, 0x50, 0x16, 0xab, 0xee, 0x03, 0x34, 0xc1, 0xca, 0x5b, 0x35, 0x10, 0x70, - 0x38, 0x39, 0x56, 0x89, 0x8f, 0x31, 0xb1, 0x10, 0x27, 0x3e, 0x16, 0x89, 0x2f, 0x8b, 0xb0, 0xfe, - 0x08, 0xaa, 0xb2, 0x54, 0x9c, 0x53, 0xec, 0x6e, 0xbc, 0xea, 0x13, 0xf3, 0x6d, 0x56, 0xa8, 0x3a, - 0x9a, 0x7c, 0x99, 0xf1, 0xb1, 0xca, 0x58, 0x7a, 0x55, 0xc6, 0xc7, 0xf4, 0x61, 0x6c, 0x47, 0x41, - 0xeb, 0x18, 0x77, 0xa5, 0xf8, 0xd8, 0x43, 0x58, 0x54, 0xec, 0x6a, 0xe2, 0xda, 0xae, 0xeb, 0x4d, - 0xdc, 0x3e, 0x57, 0xe7, 0xaf, 0x98, 0x4c, 0x3a, 0x8a, 0x53, 0x8c, 0x41, 0x74, 0x40, 0x97, 0xe2, - 0xb7, 0x1e, 0x40, 0x81, 0xe4, 0x72, 0x12, 0x3e, 0xd2, 0x19, 0x17, 0xa1, 0xb0, 0xfb, 0x50, 0x20, - 0xf1, 0x3c, 0x7b, 0x2d, 0xb3, 0x21, 0x04, 0xa3, 0x05, 0x4c, 0x64, 0xdc, 0xe3, 0xa1, 0xef, 0xf4, - 0x83, 0xf8, 0x68, 0x57, 0x41, 0xe8, 0x9f, 0x54, 0x57, 0x6c, 0xb9, 0x8d, 0x31, 0x51, 0x47, 0x25, - 0x1c, 0xb1, 0x31, 0x2d, 0x26, 0xca, 0x90, 0xe2, 0xd2, 0x10, 0x56, 0x8e, 0x79, 0x78, 0xc1, 0xb9, - 0xeb, 0x0a, 0x61, 0xa8, 0xcf, 0xdd, 0xd0, 0xb7, 0x87, 0x62, 0x92, 0xa8, 0x07, 0x4f, 0x66, 0x4a, - 0x8d, 0x6d, 0x20, 0x1b, 0x71, 0xc6, 0xcd, 0x28, 0x1f, 0xf1, 0x8e, 0xe5, 0xe3, 0xb4, 0xb4, 0xb5, - 0x5f, 0x81, 0xb5, 0xeb, 0x33, 0xa5, 0x1c, 0xe0, 0xbc, 0x9f, 0xe4, 0x2a, 0x91, 0x1f, 0x70, 0xe8, - 0xd9, 0x21, 0xb5, 0x46, 0xe7, 0x2c, 0xfb, 0x50, 0xd1, 0x52, 0xe2, 0xbd, 0x3f, 0x83, 0xc2, 0x1d, - 0x7d, 0x88, 0x1d, 0xc9, 0xf5, 0xfc, 0x11, 0xfa, 0xdd, 0x06, 0x56, 0x5c, 0x7a, 0xc6, 0x9c, 0x8f, - 0xe1, 0x78, 0x62, 0xdd, 0x58, 0x87, 0x79, 0x94, 0xec, 0xb5, 0x8d, 0xee, 0x65, 0xc2, 0xa0, 0xb1, - 0x04, 0x6c, 0x9f, 0x78, 0x97, 0x1e, 0xce, 0xf9, 0x9f, 0x72, 0x50, 0xd1, 0xc0, 0x62, 0x37, 0xc2, - 0x00, 0x40, 0x6b, 0xe0, 0xd8, 0x23, 0xae, 0x9c, 0x9c, 0x35, 0xb3, 0x86, 0xd0, 0x2d, 0x09, 0x14, - 0x7b, 0xb1, 0x7d, 0x7e, 0x6a, 0x79, 0x93, 0xd0, 0x1a, 0xf0, 0x53, 0x9f, 0xab, 0x56, 0x56, 0xed, - 0xf3, 0xd3, 0x83, 0x49, 0xb8, 0x85, 0x30, 0x81, 0x25, 0x78, 0x89, 0x86, 0x25, 0x63, 0xd6, 0x46, - 0xf6, 0x65, 0x8c, 0x25, 0x03, 0x27, 0x89, 0x32, 0xf3, 0x51, 0xe0, 0x24, 0x69, 0x8b, 0xd3, 0x1b, - 0x68, 0x61, 0x76, 0x03, 0xfd, 0x16, 0xac, 0xd0, 0x06, 0x2a, 0x59, 0xb3, 0x35, 0xb5, 0x92, 0x97, - 0x30, 0x55, 0x76, 0x52, 0x13, 0x7b, 0x1b, 0xa2, 0x07, 0x8a, 0x2d, 0x05, 0xce, 0x8f, 0x88, 0x91, - 0x65, 0x4c, 0xd1, 0x33, 0x59, 0x78, 0xd7, 0xf9, 0x11, 0x17, 0x98, 0x18, 0x1d, 0xa3, 0x63, 0xca, - 0xf3, 0x13, 0x23, 0xc7, 0x9d, 0xc6, 0xb4, 0x2f, 0x93, 0x98, 0x65, 0x89, 0x69, 0x5f, 0xea, 0x98, - 0x4f, 0x60, 0x75, 0xc4, 0x07, 0x8e, 0x9d, 0x2c, 0xd6, 0x8a, 0x05, 0xb7, 0x25, 0x4a, 0xd6, 0xf2, - 0x74, 0x49, 0x71, 0x17, 0xa3, 0xf1, 0x23, 0x6f, 0x74, 0xec, 0x90, 0xcc, 0x42, 0xf1, 0x3a, 0x79, - 0xb3, 0xee, 0x4e, 0x46, 0x3f, 0x40, 0xb0, 0xc8, 0x12, 0x18, 0x35, 0xa8, 0x74, 0x43, 0x6f, 0xac, - 0xa6, 0xb9, 0x0e, 0x55, 0xfa, 0x94, 0x87, 0x1a, 0x6f, 0xc1, 0x4d, 0x64, 0x09, 0x3d, 0x6f, 0xec, - 0x0d, 0xbd, 0xd3, 0xab, 0x84, 0x1d, 0xef, 0xdf, 0x65, 0x60, 0x31, 0x91, 0x2a, 0xd9, 0xeb, 0xb7, - 0x88, 0x9f, 0x45, 0x27, 0xd3, 0x68, 0x0d, 0x2e, 0x68, 0x6b, 0x90, 0x10, 0x89, 0x99, 0xa9, 0xd3, - 0x6a, 0xad, 0xf8, 0x46, 0x05, 0x95, 0x91, 0x58, 0x4a, 0x73, 0x96, 0xa5, 0xc8, 0xfc, 0xea, 0xae, - 0x05, 0x55, 0xc4, 0x2f, 0xc8, 0x33, 0x2e, 0x03, 0xd9, 0xe5, 0x5c, 0xf2, 0xa0, 0x80, 0x6e, 0xf3, - 0x53, 0x2d, 0x88, 0x0d, 0x81, 0x81, 0xf1, 0x4f, 0x32, 0x00, 0x71, 0xeb, 0xf0, 0xa8, 0x42, 0x24, - 0xb7, 0xd0, 0x65, 0x65, 0x9a, 0x8c, 0xf2, 0x26, 0x54, 0xa3, 0x88, 0xe5, 0x58, 0x12, 0xaa, 0x28, - 0x98, 0x10, 0x87, 0xde, 0x85, 0xf9, 0xd3, 0xa1, 0x77, 0x8c, 0x12, 0xab, 0x94, 0x5b, 0x28, 0x5e, - 0xad, 0x4e, 0x60, 0x25, 0x8d, 0xc4, 0x72, 0x53, 0x3e, 0x35, 0xa8, 0x59, 0x97, 0x82, 0x8c, 0xdf, - 0xcc, 0x46, 0xa1, 0x9b, 0xf1, 0x48, 0xbc, 0x5c, 0xbd, 0xfb, 0x49, 0x62, 0x69, 0x5e, 0xe6, 0x5e, - 0xfc, 0x04, 0xea, 0x3e, 0x6d, 0x4a, 0x6a, 0xc7, 0xca, 0xbf, 0x64, 0xc7, 0xaa, 0xf9, 0x09, 0x49, - 0xe7, 0x3d, 0x68, 0xd8, 0x83, 0x73, 0xee, 0x87, 0x0e, 0x5a, 0xeb, 0x51, 0x3e, 0x96, 0xc1, 0x92, - 0x1a, 0x1c, 0x05, 0xd1, 0x77, 0x61, 0x5e, 0x1e, 0xb4, 0x8d, 0x30, 0xe5, 0xd5, 0x3d, 0x31, 0x58, - 0x20, 0x1a, 0xff, 0x5c, 0xc5, 0x8a, 0x26, 0x67, 0xf7, 0xe5, 0xa3, 0xa2, 0xf7, 0x30, 0x3b, 0xeb, - 0x40, 0x95, 0x84, 0x24, 0x9d, 0x00, 0x92, 0x1f, 0x11, 0x50, 0xba, 0x00, 0x92, 0xc3, 0x9a, 0x7f, - 0x9d, 0x61, 0x35, 0xfe, 0x43, 0x06, 0x8a, 0x3b, 0xde, 0x78, 0xc7, 0xa1, 0x60, 0x7d, 0x5c, 0x26, - 0x91, 0x8f, 0x6a, 0x4e, 0x7c, 0x62, 0xe0, 0xcf, 0x4b, 0xce, 0x93, 0xa5, 0x8a, 0x79, 0xb5, 0xa4, - 0x98, 0xf7, 0x5d, 0xb8, 0x85, 0x2e, 0x40, 0xdf, 0x1b, 0x7b, 0xbe, 0x58, 0xaa, 0xf6, 0x90, 0xc4, - 0x3d, 0xcf, 0x0d, 0xcf, 0x14, 0xef, 0xbc, 0x79, 0xc2, 0xf9, 0xa1, 0x86, 0xb1, 0x17, 0x21, 0xe0, - 0x89, 0xcd, 0x61, 0x78, 0x6e, 0x91, 0x86, 0x2e, 0xe5, 0x51, 0xe2, 0xa8, 0xf3, 0x22, 0xa1, 0x8d, - 0x70, 0x94, 0x48, 0x8d, 0x6f, 0x43, 0x39, 0x32, 0xf6, 0xb0, 0xf7, 0xa1, 0x7c, 0xe6, 0x8d, 0xa5, - 0x45, 0x28, 0x93, 0x38, 0x73, 0x27, 0x7b, 0x6d, 0x96, 0xce, 0xe8, 0x47, 0x60, 0xfc, 0x59, 0x11, - 0x8a, 0x1d, 0xf7, 0xdc, 0x73, 0xfa, 0x18, 0x6d, 0x3a, 0xe2, 0x23, 0x4f, 0x9d, 0xf6, 0x17, 0xbf, - 0x31, 0x36, 0x2b, 0xbe, 0x80, 0x27, 0x27, 0x63, 0xb3, 0xa2, 0xab, 0x77, 0x96, 0x61, 0xce, 0xd7, - 0x6f, 0xd0, 0x29, 0xf8, 0x18, 0xff, 0x1e, 0xed, 0x97, 0x05, 0xed, 0xb6, 0x04, 0x51, 0x16, 0xdd, - 0xec, 0x82, 0x43, 0x46, 0xa7, 0x2f, 0xcb, 0x08, 0xc1, 0x01, 0xbb, 0x0d, 0x45, 0x79, 0xc4, 0x8d, - 0xce, 0x24, 0x51, 0xc0, 0xba, 0x04, 0x21, 0x35, 0xf8, 0x9c, 0x5c, 0xb8, 0x91, 0x20, 0x9b, 0x33, - 0xab, 0x0a, 0xb8, 0x25, 0x68, 0xed, 0x2e, 0x54, 0x08, 0x9f, 0x50, 0x4a, 0x32, 0x48, 0x13, 0x41, - 0x88, 0x90, 0x72, 0x11, 0x55, 0x39, 0xf5, 0x22, 0x2a, 0x0c, 0x27, 0x8e, 0xb8, 0x2c, 0x75, 0x11, - 0xe8, 0xfa, 0x21, 0x0d, 0xae, 0x6e, 0x61, 0x93, 0x36, 0x15, 0x3a, 0x8c, 0xac, 0x6c, 0x2a, 0x6f, - 0x41, 0xed, 0xc4, 0x1e, 0x0e, 0x8f, 0xed, 0xfe, 0x0b, 0x32, 0x05, 0x54, 0xc9, 0xfa, 0xa9, 0x80, - 0x68, 0x0b, 0xb8, 0x0b, 0x15, 0x6d, 0x96, 0x31, 0x02, 0x33, 0x6f, 0x42, 0x3c, 0xbf, 0xd3, 0x16, - 0xbe, 0xfa, 0x6b, 0x58, 0xf8, 0xb4, 0x48, 0xd4, 0xf9, 0x64, 0x24, 0xea, 0x2d, 0xe4, 0xa6, 0x32, - 0xe4, 0xb0, 0x41, 0x77, 0xdd, 0xd8, 0x83, 0x01, 0x86, 0x1c, 0xd2, 0xc5, 0x92, 0x38, 0x78, 0x94, - 0xbe, 0x40, 0xba, 0x04, 0xc1, 0x08, 0xe5, 0x0e, 0x99, 0xa9, 0xc7, 0xb6, 0x33, 0xc0, 0x43, 0x07, - 0x64, 0x3d, 0x28, 0xda, 0xa3, 0xf0, 0xd0, 0x76, 0x06, 0xec, 0x1e, 0x54, 0x55, 0x32, 0xee, 0x8e, - 0x8b, 0x34, 0xfe, 0x32, 0x59, 0xec, 0x89, 0x06, 0xd4, 0x22, 0x8c, 0x51, 0x7c, 0xa2, 0xb8, 0x22, - 0x51, 0x90, 0x0e, 0x3e, 0xc0, 0x28, 0x9f, 0x90, 0xe3, 0xb9, 0xe1, 0xfa, 0xe3, 0x5b, 0x51, 0xf0, - 0x01, 0x52, 0xa9, 0xfa, 0x4f, 0xce, 0x31, 0xc2, 0x14, 0xc2, 0x1d, 0xf9, 0xe8, 0x56, 0x12, 0xf2, - 0xaf, 0x44, 0x45, 0x1f, 0x1d, 0x21, 0xb0, 0x6f, 0x6b, 0xfa, 0x6b, 0x13, 0x91, 0x6f, 0x4f, 0x95, - 0x7f, 0xdd, 0x99, 0xab, 0x3b, 0x00, 0x4e, 0x20, 0x76, 0x99, 0x80, 0xbb, 0x03, 0x3c, 0x02, 0x5c, - 0x32, 0xcb, 0x4e, 0xf0, 0x8c, 0x00, 0x3f, 0x5b, 0xc5, 0xb6, 0x05, 0x55, 0xbd, 0x9b, 0xac, 0x04, - 0xf9, 0x83, 0xc3, 0xf6, 0x7e, 0xe3, 0x06, 0xab, 0x40, 0xb1, 0xdb, 0xee, 0xf5, 0x76, 0xd1, 0xd3, - 0x57, 0x85, 0x52, 0x74, 0x4e, 0x31, 0x2b, 0xbe, 0x5a, 0x9b, 0x9b, 0xed, 0xc3, 0x5e, 0x7b, 0xab, - 0x91, 0xfb, 0x7e, 0xbe, 0x94, 0x6d, 0xe4, 0x8c, 0x3f, 0xcf, 0x41, 0x45, 0x1b, 0x85, 0x97, 0x33, - 0xe3, 0x3b, 0x00, 0xa8, 0x49, 0xc6, 0x11, 0xa9, 0x79, 0xb3, 0x2c, 0x20, 0x34, 0xf9, 0xba, 0x8f, - 0x22, 0x47, 0x97, 0x28, 0x29, 0x1f, 0xc5, 0x5b, 0x50, 0xa3, 0xfb, 0x88, 0x74, 0x7f, 0x6d, 0xc1, - 0xac, 0x12, 0x50, 0xb2, 0x6a, 0x3c, 0xc0, 0x8c, 0x48, 0x78, 0x7a, 0x4e, 0xde, 0x4e, 0x42, 0x20, - 0x3c, 0x3f, 0x87, 0x87, 0x1f, 0x03, 0x6f, 0x78, 0xce, 0x09, 0x83, 0x24, 0xc2, 0x8a, 0x84, 0xf5, - 0xe4, 0x51, 0x6c, 0xc9, 0x0f, 0xb5, 0x13, 0xb4, 0x05, 0xb3, 0x4a, 0x40, 0x59, 0xd1, 0x37, 0x14, - 0x01, 0x51, 0xf4, 0xca, 0xea, 0x2c, 0x35, 0x24, 0x88, 0x67, 0x77, 0xc6, 0x8c, 0x58, 0x46, 0xc2, - 0xf8, 0xda, 0x6c, 0xbe, 0x57, 0x9b, 0x13, 0xd9, 0xfb, 0xc0, 0x46, 0xe3, 0xb1, 0x95, 0x62, 0xe0, - 0xcb, 0x9b, 0xf3, 0xa3, 0xf1, 0xb8, 0xa7, 0xd9, 0xbf, 0x7e, 0x06, 0xb6, 0xc7, 0x2f, 0x80, 0xb5, - 0xc4, 0x02, 0xc6, 0x26, 0x46, 0xaa, 0x58, 0xcc, 0x96, 0x33, 0x3a, 0x5b, 0x4e, 0xe1, 0x7e, 0xd9, - 0x54, 0xee, 0xf7, 0x32, 0x3e, 0x61, 0x6c, 0x43, 0xe5, 0x50, 0xbb, 0xed, 0xec, 0x9e, 0xd8, 0x21, - 0xd4, 0x3d, 0x67, 0xb4, 0x77, 0x90, 0x4d, 0xd1, 0x97, 0xd7, 0x9b, 0x69, 0xad, 0xc9, 0x6a, 0xad, - 0x31, 0xfe, 0x51, 0x86, 0x6e, 0x92, 0x89, 0x1a, 0x1f, 0x5f, 0xb0, 0xa6, 0xdc, 0x6f, 0xf1, 0x41, - 0xf7, 0x8a, 0x72, 0xbb, 0xc9, 0x33, 0xea, 0xd8, 0x34, 0xcb, 0x3b, 0x39, 0x09, 0xb8, 0x8a, 0xf1, - 0xa8, 0x20, 0xec, 0x00, 0x41, 0x4a, 0xf8, 0x16, 0x12, 0xbe, 0x43, 0xe5, 0x07, 0x32, 0xb0, 0x43, - 0x08, 0xdf, 0x7b, 0xf6, 0xa5, 0xac, 0x35, 0x10, 0x22, 0x88, 0xf4, 0x0f, 0xa8, 0xb3, 0xb0, 0xd1, - 0xb7, 0xf1, 0x0f, 0xe4, 0x59, 0xfc, 0xe9, 0xf1, 0x7d, 0x00, 0xa5, 0xa8, 0xd4, 0xe4, 0x0e, 0xab, - 0x30, 0xa3, 0x74, 0xb1, 0x8f, 0xa3, 0x31, 0x24, 0xd1, 0x62, 0x5a, 0x5c, 0xe8, 0xe3, 0xe9, 0x68, - 0xad, 0xfe, 0x3a, 0xb0, 0x13, 0xc7, 0x9f, 0x46, 0xa6, 0xc5, 0xd6, 0xc0, 0x14, 0x0d, 0xdb, 0x38, - 0x82, 0x45, 0xc5, 0x25, 0x34, 0x8d, 0x20, 0x39, 0x79, 0x99, 0x57, 0x30, 0xf9, 0xec, 0x0c, 0x93, - 0x37, 0xfe, 0x73, 0x1e, 0x8a, 0xea, 0xe6, 0xc0, 0xb4, 0xdb, 0xee, 0xca, 0xc9, 0xdb, 0xee, 0x9a, - 0x89, 0x9b, 0x91, 0x70, 0xea, 0xe5, 0x7e, 0xff, 0xee, 0xf4, 0x96, 0xad, 0xf9, 0x2a, 0x12, 0xdb, - 0xf6, 0x0a, 0xe4, 0xc7, 0x76, 0x78, 0x86, 0x76, 0x49, 0x22, 0x1e, 0xfc, 0x56, 0x3e, 0x8c, 0x42, - 0xd2, 0x87, 0x91, 0x76, 0x33, 0x20, 0x89, 0xa4, 0x33, 0x37, 0x03, 0xde, 0x02, 0x92, 0x2f, 0xb4, - 0xa0, 0xb7, 0x12, 0x02, 0xc4, 0x5e, 0x94, 0x14, 0x47, 0x4a, 0xd3, 0xe2, 0xc8, 0x6b, 0x8b, 0x0a, - 0xdf, 0x82, 0x39, 0xba, 0x55, 0x43, 0x9e, 0xf9, 0x55, 0x1b, 0x8a, 0x1c, 0x43, 0xf5, 0x9f, 0x4e, - 0x42, 0x98, 0x12, 0x57, 0xbf, 0x66, 0xab, 0x92, 0xb8, 0x66, 0x4b, 0xf7, 0xad, 0x54, 0x93, 0xbe, - 0x95, 0xfb, 0xd0, 0x88, 0x06, 0x14, 0x2d, 0x95, 0x6e, 0x20, 0x4f, 0x14, 0xd6, 0x15, 0x5c, 0x70, - 0xc9, 0xfd, 0x20, 0xde, 0x10, 0xeb, 0x89, 0x0d, 0x51, 0xf0, 0xb0, 0x56, 0x18, 0xf2, 0xd1, 0x38, - 0x54, 0x1b, 0xa2, 0x76, 0x19, 0x23, 0x51, 0xc4, 0x3c, 0x52, 0x84, 0x9a, 0x76, 0xb5, 0xe4, 0x6b, - 0x89, 0x5e, 0x88, 0x6d, 0x48, 0x1e, 0xfb, 0xa5, 0xf8, 0x93, 0xce, 0xbe, 0xb5, 0xbd, 0xdb, 0x79, - 0xba, 0xd3, 0x6b, 0x64, 0xc4, 0x67, 0xf7, 0x68, 0x73, 0xb3, 0xdd, 0xde, 0xc2, 0x6d, 0x09, 0x60, - 0x6e, 0xbb, 0xd5, 0x11, 0x5b, 0x54, 0xce, 0xf8, 0xed, 0x2c, 0x54, 0xb4, 0x36, 0xb0, 0x27, 0xd1, - 0xd0, 0xd1, 0x75, 0x4d, 0x77, 0x66, 0xdb, 0xb9, 0xae, 0xf8, 0xb5, 0x36, 0x76, 0xd1, 0x65, 0x89, - 0xd9, 0x6b, 0x2f, 0x4b, 0x64, 0xef, 0xc0, 0xbc, 0x4d, 0x25, 0x44, 0x43, 0x25, 0x4d, 0xf5, 0x12, - 0x2c, 0x47, 0x0a, 0xe3, 0x41, 0xe3, 0x4d, 0x47, 0xe0, 0xe5, 0x55, 0x08, 0x66, 0xb4, 0xef, 0xe0, - 0x88, 0x16, 0x4f, 0x6c, 0x67, 0x38, 0xf1, 0xb9, 0x74, 0xad, 0x47, 0xdb, 0x37, 0x41, 0x4d, 0x95, - 0x6c, 0x7c, 0x08, 0x10, 0xb7, 0x39, 0x39, 0x38, 0x37, 0x92, 0x83, 0x93, 0xd1, 0x06, 0x27, 0x6b, - 0xfc, 0x33, 0xc9, 0x6c, 0xe4, 0x48, 0x47, 0xc6, 0xb9, 0x6f, 0x80, 0x32, 0x17, 0x5a, 0x18, 0x96, - 0x3d, 0x1e, 0xf2, 0x50, 0xdd, 0x2e, 0xb0, 0x20, 0x53, 0x3a, 0x51, 0xc2, 0x0c, 0x73, 0xcc, 0xce, - 0x32, 0xc7, 0x37, 0xa1, 0x2a, 0x18, 0xa3, 0x9c, 0xe2, 0x40, 0x32, 0x98, 0xca, 0xc8, 0xbe, 0x54, - 0x75, 0x27, 0xb8, 0x62, 0x7e, 0x8a, 0x2b, 0xfe, 0x4e, 0x86, 0x2e, 0xfb, 0x88, 0x1b, 0x1a, 0xb3, - 0xc5, 0xa8, 0xcc, 0x24, 0x5b, 0x94, 0xa8, 0x66, 0x94, 0x7e, 0x0d, 0xab, 0xcb, 0xa6, 0xb3, 0xba, - 0x74, 0x26, 0x9a, 0x4b, 0x65, 0xa2, 0xc6, 0x1a, 0x34, 0xb7, 0xb8, 0x18, 0x8a, 0xd6, 0x70, 0x38, - 0x35, 0x96, 0xc6, 0x2d, 0xb8, 0x99, 0x92, 0x26, 0xed, 0x2c, 0x9f, 0xc2, 0x72, 0x8b, 0x6e, 0x41, - 0xf8, 0x59, 0x1d, 0x77, 0x34, 0x9a, 0xb0, 0x32, 0x5d, 0xa4, 0xac, 0x6c, 0x1b, 0x16, 0xb6, 0xf8, - 0xf1, 0xe4, 0x74, 0x97, 0x9f, 0xc7, 0x15, 0x31, 0xc8, 0x07, 0x67, 0xde, 0x85, 0x9c, 0x5c, 0xfc, - 0x8d, 0x81, 0x94, 0x02, 0xc7, 0x0a, 0xc6, 0xbc, 0xaf, 0x6c, 0xed, 0x08, 0xe9, 0x8e, 0x79, 0xdf, - 0x78, 0x02, 0x4c, 0x2f, 0x47, 0xce, 0x84, 0x50, 0x84, 0x26, 0xc7, 0x56, 0x70, 0x15, 0x84, 0x7c, - 0xa4, 0x8e, 0xf9, 0x41, 0x30, 0x39, 0xee, 0x12, 0xc4, 0x78, 0x17, 0xaa, 0x87, 0xf6, 0x95, 0xc9, - 0xbf, 0x90, 0xa7, 0xe9, 0x56, 0xa1, 0x38, 0xb6, 0xaf, 0x04, 0xa7, 0x8b, 0xdc, 0x6e, 0x98, 0x6c, - 0xfc, 0x41, 0x1e, 0xe6, 0x08, 0x93, 0xdd, 0xa3, 0xeb, 0x86, 0x1d, 0x17, 0x39, 0x8d, 0xda, 0x0b, - 0x34, 0xd0, 0xcc, 0x76, 0x91, 0x9d, 0xdd, 0x2e, 0xa4, 0x8d, 0x50, 0x5d, 0xb3, 0xa4, 0x1c, 0x24, - 0xee, 0x64, 0xa4, 0xee, 0x56, 0x4a, 0x5e, 0x05, 0x90, 0x8f, 0xaf, 0x93, 0xa6, 0x73, 0xd2, 0x49, - 0x17, 0x76, 0xac, 0x6e, 0x51, 0xeb, 0xd4, 0x2e, 0x28, 0x77, 0x04, 0x1d, 0x94, 0xaa, 0xd3, 0x15, - 0xd5, 0x11, 0xd1, 0xa4, 0x4e, 0x37, 0xa3, 0xbb, 0x95, 0x5e, 0xad, 0xbb, 0x91, 0xf1, 0xf0, 0x25, - 0xba, 0x1b, 0xbc, 0x86, 0xee, 0xf6, 0x1a, 0xee, 0xe3, 0x9b, 0x50, 0x42, 0xd1, 0x46, 0xdb, 0x20, - 0x84, 0x48, 0x23, 0x36, 0x88, 0x8f, 0x34, 0xed, 0x86, 0x62, 0x57, 0x6e, 0xc5, 0x0b, 0xd0, 0xe4, - 0x5f, 0xfc, 0x7c, 0xdc, 0x72, 0xcf, 0xa1, 0x28, 0xa1, 0x82, 0xa0, 0x5d, 0x7b, 0xa4, 0x6e, 0xaa, - 0xc3, 0xdf, 0x62, 0xd8, 0xf0, 0x7a, 0xad, 0x2f, 0x26, 0x8e, 0xcf, 0x07, 0xea, 0x0a, 0x22, 0x07, - 0xd7, 0xa8, 0x80, 0x88, 0x0e, 0x0a, 0x4d, 0xcb, 0xf5, 0x2e, 0x5c, 0xc9, 0x7b, 0x8a, 0x4e, 0xf0, - 0x4c, 0x7c, 0x1a, 0x0c, 0x1a, 0x78, 0x57, 0xe5, 0xd8, 0xf3, 0xd5, 0xfe, 0x6b, 0xfc, 0x61, 0x06, - 0x1a, 0x72, 0x75, 0x45, 0x69, 0xba, 0xa2, 0x53, 0xb8, 0x2e, 0xd4, 0xe2, 0xe5, 0x17, 0x0a, 0x19, - 0x50, 0x43, 0xfb, 0x4e, 0xb4, 0x19, 0x93, 0x7d, 0xaa, 0x22, 0x80, 0xdb, 0x72, 0x43, 0x7e, 0x03, - 0x2a, 0x2a, 0xcc, 0x7b, 0xe4, 0x0c, 0xd5, 0xcd, 0xf1, 0x14, 0xe7, 0xbd, 0xe7, 0x0c, 0xd5, 0x5e, - 0xee, 0xdb, 0xf2, 0xc8, 0x72, 0x06, 0xf7, 0x72, 0xd3, 0x0e, 0xb9, 0xf1, 0xaf, 0x32, 0xb0, 0xa0, - 0x75, 0x45, 0xae, 0xdb, 0x8f, 0xa1, 0x1a, 0x5d, 0x12, 0xcb, 0x23, 0xe1, 0x72, 0x35, 0xc9, 0x68, - 0xe2, 0x6c, 0x95, 0x7e, 0x04, 0x09, 0x44, 0x63, 0x06, 0xf6, 0x15, 0xc5, 0x22, 0x4f, 0x46, 0x4a, - 0x7f, 0x1b, 0xd8, 0x57, 0xdb, 0x9c, 0x77, 0x27, 0x23, 0xa1, 0x9d, 0x5f, 0x70, 0xfe, 0x22, 0x42, - 0x20, 0xf6, 0x09, 0x02, 0x26, 0x31, 0x0c, 0xa8, 0x8d, 0x3c, 0x37, 0x3c, 0x8b, 0x50, 0xa4, 0x60, - 0x8d, 0x40, 0xc2, 0x31, 0xfe, 0x34, 0x0b, 0x8b, 0x64, 0x45, 0x94, 0xd6, 0x5b, 0xc9, 0xba, 0x9a, - 0x30, 0x47, 0x06, 0x55, 0x62, 0x5e, 0x3b, 0x37, 0x4c, 0xf9, 0xcd, 0xbe, 0xf5, 0x9a, 0x96, 0x4f, - 0x75, 0x2a, 0xfa, 0x9a, 0xe1, 0xcf, 0xcd, 0x0e, 0xff, 0xf5, 0xc3, 0x9b, 0xe6, 0xcb, 0x2d, 0xa4, - 0xf9, 0x72, 0x5f, 0xc7, 0x83, 0x3a, 0x73, 0x7e, 0xb7, 0x28, 0x71, 0xb4, 0xf3, 0xbb, 0x4f, 0x60, - 0x35, 0x81, 0x83, 0xdc, 0xda, 0x39, 0x71, 0xb8, 0xba, 0x42, 0x66, 0x49, 0xc3, 0xee, 0xaa, 0xb4, - 0x8d, 0x22, 0x14, 0x82, 0xbe, 0x37, 0xe6, 0xc6, 0x0a, 0x2c, 0x25, 0x47, 0x55, 0x6e, 0x13, 0xbf, - 0x9b, 0x81, 0xa6, 0x8c, 0xbc, 0x71, 0xdc, 0xd3, 0x1d, 0x27, 0x08, 0x3d, 0x3f, 0xba, 0x4c, 0xf5, - 0x0e, 0x40, 0x10, 0xda, 0xbe, 0x54, 0xa8, 0xe5, 0xa5, 0x29, 0x08, 0x41, 0x65, 0xf9, 0x26, 0x94, - 0xb8, 0x3b, 0xa0, 0x44, 0xa2, 0x86, 0x22, 0x77, 0x07, 0x4a, 0xd5, 0x9e, 0xd9, 0x4a, 0x6b, 0x49, - 0x21, 0x41, 0xde, 0x61, 0x20, 0x46, 0x87, 0x9f, 0xe3, 0x96, 0x9e, 0x8f, 0xee, 0x30, 0xd8, 0xb3, - 0x2f, 0x31, 0x8e, 0x35, 0x30, 0xfe, 0x6e, 0x16, 0xe6, 0xe3, 0xf6, 0xd1, 0x05, 0x28, 0x2f, 0xbf, - 0xca, 0xe5, 0x9e, 0x24, 0x07, 0x47, 0xa8, 0x28, 0x9a, 0x6d, 0xb5, 0x44, 0x8b, 0xb3, 0xe3, 0x32, - 0x03, 0x2a, 0x0a, 0xc3, 0x9b, 0x84, 0xda, 0x9d, 0x86, 0x65, 0x42, 0x39, 0x98, 0x84, 0x42, 0xa7, - 0x14, 0xca, 0xb5, 0xe3, 0x4a, 0xad, 0xae, 0x60, 0x8f, 0xc2, 0x0e, 0x3e, 0x95, 0x20, 0xc0, 0x22, - 0x1b, 0x4d, 0xa4, 0xc0, 0x12, 0xf8, 0x0d, 0x52, 0x25, 0x68, 0xe6, 0x50, 0x8d, 0xd0, 0xe5, 0x6c, - 0xba, 0x35, 0x3a, 0x92, 0xb3, 0xdf, 0x80, 0x0a, 0x15, 0x1e, 0x1f, 0xd7, 0xce, 0x9b, 0x65, 0xac, - 0x01, 0xd3, 0xa5, 0x9d, 0xcb, 0x9b, 0x24, 0xb4, 0x7b, 0xa0, 0xaa, 0x30, 0xb0, 0xe5, 0x6f, 0x66, - 0xe0, 0x66, 0xca, 0xb4, 0xc9, 0x55, 0xbe, 0x09, 0x0b, 0x27, 0x51, 0xa2, 0x1a, 0x5d, 0x5a, 0xea, - 0x2b, 0x8a, 0xad, 0x26, 0xc7, 0xd4, 0x6c, 0x9c, 0x24, 0x01, 0xb1, 0x5e, 0x49, 0x33, 0x98, 0xb8, - 0x0c, 0x00, 0x45, 0x22, 0x9a, 0x46, 0x92, 0xdf, 0x0f, 0x61, 0xad, 0x7d, 0x29, 0x38, 0xc6, 0xa6, - 0xfe, 0xd6, 0x87, 0x22, 0xa3, 0xa4, 0x0d, 0x3d, 0xf3, 0x5a, 0x36, 0xf4, 0x01, 0x9d, 0x1e, 0x8e, - 0xca, 0xfa, 0x49, 0x0a, 0xc1, 0x0d, 0x54, 0xe4, 0xa1, 0xb7, 0x4a, 0xd4, 0xad, 0x00, 0xfd, 0xe8, - 0x8d, 0x12, 0x23, 0x80, 0xf9, 0xbd, 0xc9, 0x30, 0x74, 0xe2, 0x67, 0x4b, 0xd8, 0xb7, 0x64, 0x1e, - 0xac, 0x47, 0x8d, 0x5a, 0x6a, 0x45, 0x10, 0x55, 0x84, 0x83, 0x35, 0x12, 0x05, 0x59, 0xb3, 0xf5, - 0xcd, 0x8f, 0x92, 0x35, 0x18, 0x37, 0x61, 0x35, 0xfe, 0xa2, 0x61, 0x53, 0x5b, 0xcd, 0x3f, 0xcc, - 0x50, 0xd0, 0x7c, 0xf2, 0x09, 0x15, 0xd6, 0x86, 0xc5, 0xc0, 0x71, 0x4f, 0x87, 0x5c, 0x2f, 0x3e, - 0x90, 0x83, 0xb0, 0x9c, 0x6c, 0x9b, 0x7c, 0x66, 0xc5, 0x5c, 0xa0, 0x1c, 0x71, 0x69, 0x01, 0xdb, - 0xb8, 0xae, 0x91, 0x31, 0x59, 0x4c, 0x8d, 0xc6, 0x6c, 0xe3, 0x3b, 0x50, 0x4f, 0x56, 0xc4, 0x3e, - 0x92, 0x87, 0xee, 0xe3, 0x56, 0xe5, 0xa6, 0x4e, 0x24, 0xc7, 0x04, 0x51, 0x89, 0xc7, 0x3e, 0x30, - 0xfe, 0x76, 0x06, 0x9a, 0x26, 0x17, 0x94, 0xab, 0xb5, 0x52, 0xd1, 0xcc, 0xc7, 0x33, 0xa5, 0x5e, - 0xdf, 0x57, 0x75, 0x96, 0x5f, 0xb5, 0xe8, 0xeb, 0xd7, 0x4e, 0xc6, 0xce, 0x8d, 0x99, 0x1e, 0x6d, - 0x94, 0x60, 0x8e, 0x50, 0x8c, 0x55, 0x58, 0x96, 0xed, 0x51, 0x6d, 0x89, 0x1d, 0xa4, 0x89, 0x1a, - 0x13, 0x0e, 0xd2, 0x35, 0x68, 0xd2, 0xe9, 0x5a, 0xbd, 0x13, 0x32, 0xe3, 0x16, 0xb0, 0x3d, 0xbb, - 0x6f, 0xfb, 0x9e, 0xe7, 0x1e, 0x72, 0x5f, 0x86, 0x20, 0xa3, 0x84, 0x89, 0xfe, 0x43, 0x25, 0x0a, - 0xd3, 0x97, 0xba, 0xc9, 0xd5, 0x73, 0x55, 0xc4, 0x15, 0x7d, 0x19, 0x26, 0x2c, 0x6e, 0xd8, 0x2f, - 0xb8, 0x2a, 0x49, 0x0d, 0xd1, 0x27, 0x50, 0x19, 0x47, 0x85, 0xaa, 0x71, 0x57, 0x97, 0x82, 0xcc, - 0x56, 0x6b, 0xea, 0xd8, 0xc6, 0x63, 0x58, 0x4a, 0x96, 0x29, 0x59, 0xc7, 0x1a, 0x94, 0x46, 0x12, - 0x26, 0x5b, 0x17, 0x7d, 0x1b, 0xbf, 0x55, 0x82, 0xa2, 0xd4, 0x46, 0xd9, 0x3a, 0xe4, 0xfb, 0x2a, - 0xea, 0x2d, 0xbe, 0x6b, 0x4a, 0xa6, 0xaa, 0xff, 0x9b, 0x18, 0xfb, 0x26, 0xf0, 0xd8, 0x27, 0x50, - 0x4f, 0x3a, 0x7e, 0xa7, 0xce, 0xee, 0x27, 0x3d, 0xb6, 0xb5, 0xfe, 0x94, 0x8b, 0xaf, 0x1c, 0x6f, - 0x8e, 0x24, 0x33, 0x94, 0xce, 0xb4, 0xdd, 0xd3, 0x73, 0x85, 0xbc, 0x1d, 0x9c, 0xd9, 0xd6, 0xe3, - 0x27, 0x1f, 0xca, 0xc3, 0xfb, 0x15, 0x04, 0x76, 0xcf, 0xec, 0xc7, 0x4f, 0x3e, 0x9c, 0x96, 0xa4, - 0xe5, 0xd1, 0x7d, 0x4d, 0x92, 0x5e, 0x82, 0x02, 0x5d, 0x59, 0x4a, 0xe1, 0x4b, 0xf4, 0xc1, 0x1e, - 0xc1, 0x92, 0x54, 0xba, 0x2d, 0x19, 0x68, 0x4e, 0x5c, 0xb0, 0x44, 0x67, 0xfb, 0x64, 0x5a, 0x17, - 0x93, 0xc8, 0xfc, 0xb5, 0x02, 0x73, 0x67, 0xf1, 0xfd, 0xb3, 0x35, 0x53, 0x7e, 0x19, 0x7f, 0x5a, - 0x80, 0x8a, 0x36, 0x28, 0xac, 0x0a, 0x25, 0xb3, 0xdd, 0x6d, 0x9b, 0x9f, 0xb5, 0xb7, 0x1a, 0x37, - 0xd8, 0x7d, 0x78, 0xbb, 0xb3, 0xbf, 0x79, 0x60, 0x9a, 0xed, 0xcd, 0x9e, 0x75, 0x60, 0x5a, 0xea, - 0xc6, 0xb3, 0xc3, 0xd6, 0xf3, 0xbd, 0xf6, 0x7e, 0xcf, 0xda, 0x6a, 0xf7, 0x5a, 0x9d, 0xdd, 0x6e, - 0x23, 0xc3, 0x6e, 0x43, 0x33, 0xc6, 0x54, 0xc9, 0xad, 0xbd, 0x83, 0xa3, 0xfd, 0x5e, 0x23, 0xcb, - 0xee, 0xc2, 0xad, 0xed, 0xce, 0x7e, 0x6b, 0xd7, 0x8a, 0x71, 0x36, 0x77, 0x7b, 0x9f, 0x59, 0xed, - 0x5f, 0x3a, 0xec, 0x98, 0xcf, 0x1b, 0xb9, 0x34, 0x84, 0x9d, 0xde, 0xee, 0xa6, 0x2a, 0x21, 0xcf, - 0x6e, 0xc2, 0x32, 0x21, 0x50, 0x16, 0xab, 0x77, 0x70, 0x60, 0x75, 0x0f, 0x0e, 0xf6, 0x1b, 0x05, - 0xb6, 0x00, 0xb5, 0xce, 0xfe, 0x67, 0xad, 0xdd, 0xce, 0x96, 0x65, 0xb6, 0x5b, 0xbb, 0x7b, 0x8d, - 0x39, 0xb6, 0x08, 0xf3, 0xd3, 0x78, 0x45, 0x51, 0x84, 0xc2, 0x3b, 0xd8, 0xef, 0x1c, 0xec, 0x5b, - 0x9f, 0xb5, 0xcd, 0x6e, 0xe7, 0x60, 0xbf, 0x51, 0x62, 0x2b, 0xc0, 0x92, 0x49, 0x3b, 0x7b, 0xad, - 0xcd, 0x46, 0x99, 0x2d, 0xc3, 0x42, 0x12, 0xfe, 0xac, 0xfd, 0xbc, 0x01, 0xac, 0x09, 0x4b, 0xd4, - 0x30, 0x6b, 0xa3, 0xbd, 0x7b, 0xf0, 0xb9, 0xb5, 0xd7, 0xd9, 0xef, 0xec, 0x1d, 0xed, 0x35, 0x2a, - 0x78, 0x91, 0x62, 0xbb, 0x6d, 0x75, 0xf6, 0xbb, 0x47, 0xdb, 0xdb, 0x9d, 0xcd, 0x4e, 0x7b, 0xbf, - 0xd7, 0xa8, 0x52, 0xcd, 0x69, 0x1d, 0xaf, 0x89, 0x0c, 0xf2, 0x34, 0x8a, 0xb5, 0xd5, 0xe9, 0xb6, - 0x36, 0x76, 0xdb, 0x5b, 0x8d, 0x3a, 0xbb, 0x03, 0x37, 0x7b, 0xed, 0xbd, 0xc3, 0x03, 0xb3, 0x65, - 0x3e, 0x57, 0xa7, 0x55, 0xac, 0xed, 0x56, 0x67, 0xf7, 0xc8, 0x6c, 0x37, 0xe6, 0xd9, 0x9b, 0x70, - 0xc7, 0x6c, 0x7f, 0x7a, 0xd4, 0x31, 0xdb, 0x5b, 0xd6, 0xfe, 0xc1, 0x56, 0xdb, 0xda, 0x6e, 0xb7, - 0x7a, 0x47, 0x66, 0xdb, 0xda, 0xeb, 0x74, 0xbb, 0x9d, 0xfd, 0xa7, 0x8d, 0x06, 0x7b, 0x1b, 0xee, - 0x45, 0x28, 0x51, 0x01, 0x53, 0x58, 0x0b, 0xa2, 0x7f, 0x6a, 0x4a, 0xf7, 0xdb, 0xbf, 0xd4, 0xb3, - 0x0e, 0xdb, 0x6d, 0xb3, 0xc1, 0xd8, 0x1a, 0xac, 0xc4, 0xd5, 0x53, 0x05, 0xb2, 0xee, 0x45, 0x91, - 0x76, 0xd8, 0x36, 0xf7, 0x5a, 0xfb, 0x62, 0x82, 0x13, 0x69, 0x4b, 0xa2, 0xd9, 0x71, 0xda, 0x74, - 0xb3, 0x97, 0x19, 0x83, 0xba, 0x36, 0x2b, 0xdb, 0x2d, 0xb3, 0xb1, 0xc2, 0xe6, 0xa1, 0xb2, 0x77, - 0x78, 0x68, 0xf5, 0x3a, 0x7b, 0xed, 0x83, 0xa3, 0x5e, 0x63, 0x95, 0x2d, 0x43, 0xa3, 0xb3, 0xdf, - 0x6b, 0x9b, 0x62, 0xae, 0x55, 0xd6, 0xff, 0x51, 0x64, 0x4b, 0x30, 0xaf, 0x5a, 0xaa, 0xa0, 0x7f, - 0x51, 0x64, 0xab, 0xc0, 0x8e, 0xf6, 0xcd, 0x76, 0x6b, 0x4b, 0x0c, 0x5c, 0x94, 0xf0, 0x3f, 0x8b, - 0xd2, 0x09, 0xf4, 0x87, 0xb9, 0x68, 0xb3, 0x8e, 0xa3, 0x2a, 0x92, 0xb7, 0x91, 0x57, 0xb5, 0x5b, - 0xc4, 0x5f, 0xf5, 0x4e, 0x88, 0xa6, 0x5a, 0xe5, 0x66, 0x54, 0xab, 0x19, 0xdd, 0xbd, 0xa6, 0xcb, - 0x7e, 0x6f, 0x41, 0x6d, 0x44, 0x37, 0x93, 0xcb, 0x1b, 0x88, 0x41, 0x86, 0x18, 0x11, 0x90, 0xae, - 0x1f, 0x9e, 0x79, 0x28, 0xa3, 0x30, 0xfb, 0x50, 0x46, 0x9a, 0x7c, 0x3f, 0x97, 0x26, 0xdf, 0x3f, - 0x80, 0x05, 0x62, 0x4d, 0x8e, 0xeb, 0x8c, 0x94, 0xd6, 0x4c, 0x52, 0xe0, 0x3c, 0xb2, 0x28, 0x82, - 0x2b, 0x75, 0x42, 0xa9, 0x1c, 0x92, 0x85, 0x14, 0xa5, 0xb6, 0x91, 0xd0, 0x34, 0x88, 0x73, 0x44, - 0x9a, 0x46, 0x54, 0x83, 0x7d, 0x19, 0xd7, 0x50, 0xd1, 0x6a, 0x20, 0x38, 0xd6, 0xf0, 0x00, 0x16, - 0xf8, 0x65, 0xe8, 0xdb, 0x96, 0x37, 0xb6, 0xbf, 0x98, 0xa0, 0x97, 0xda, 0x46, 0x1d, 0xbe, 0x6a, - 0xce, 0x63, 0xc2, 0x01, 0xc2, 0xb7, 0xec, 0xd0, 0x7e, 0xf0, 0x25, 0x54, 0xb4, 0x5b, 0xeb, 0xd9, - 0x2a, 0x2c, 0x7e, 0xde, 0xe9, 0xed, 0xb7, 0xbb, 0x5d, 0xeb, 0xf0, 0x68, 0xe3, 0x59, 0xfb, 0xb9, - 0xb5, 0xd3, 0xea, 0xee, 0x34, 0x6e, 0x88, 0x45, 0xbb, 0xdf, 0xee, 0xf6, 0xda, 0x5b, 0x09, 0x78, - 0x86, 0xbd, 0x01, 0x6b, 0x47, 0xfb, 0x47, 0xdd, 0xf6, 0x96, 0x95, 0x96, 0x2f, 0x2b, 0xa8, 0x54, - 0xa6, 0xa7, 0x64, 0xcf, 0x3d, 0xf8, 0x35, 0xa8, 0x27, 0x0f, 0x6e, 0x33, 0x80, 0xb9, 0xdd, 0xf6, - 0xd3, 0xd6, 0xe6, 0x73, 0xba, 0x6a, 0xb5, 0xdb, 0x6b, 0xf5, 0x3a, 0x9b, 0x96, 0xbc, 0x5a, 0x55, - 0x70, 0x84, 0x0c, 0xab, 0x40, 0xb1, 0xb5, 0xbf, 0xb9, 0x73, 0x60, 0x76, 0x1b, 0x59, 0x76, 0x1b, - 0x56, 0x15, 0xad, 0x6e, 0x1e, 0xec, 0xed, 0x75, 0x7a, 0xc8, 0x0c, 0x7b, 0xcf, 0x0f, 0x05, 0x69, - 0x3e, 0xb0, 0xa1, 0x1c, 0xdf, 0x0d, 0x8b, 0x0c, 0xa6, 0xd3, 0xeb, 0xb4, 0x7a, 0x31, 0x77, 0x6d, - 0xdc, 0x10, 0xfc, 0x2b, 0x06, 0xe3, 0xd5, 0xae, 0x8d, 0x0c, 0x9d, 0x6d, 0x53, 0x40, 0xaa, 0xbd, - 0x91, 0x15, 0x8b, 0x2a, 0x86, 0x6e, 0x1c, 0xf4, 0x44, 0x17, 0xbe, 0x03, 0xf5, 0x64, 0x04, 0x63, - 0xd2, 0x6c, 0xbd, 0x06, 0x2b, 0x1b, 0xed, 0xde, 0xe7, 0xed, 0xf6, 0x3e, 0x8e, 0xce, 0x66, 0x7b, - 0xbf, 0x67, 0xb6, 0x76, 0x3b, 0xbd, 0xe7, 0x8d, 0xcc, 0x83, 0x4f, 0xa0, 0x31, 0xed, 0x2e, 0x4c, - 0xf8, 0x57, 0x5f, 0xe6, 0x88, 0x7d, 0xf0, 0x4f, 0x73, 0x00, 0xf1, 0x31, 0x1a, 0xc1, 0x26, 0xb7, - 0x5a, 0xbd, 0xd6, 0xee, 0x81, 0x98, 0x02, 0xf3, 0xa0, 0x27, 0xb8, 0x9f, 0xd9, 0xfe, 0xb4, 0x71, - 0x23, 0x35, 0xe5, 0xe0, 0xb0, 0xd7, 0xc8, 0x88, 0xd9, 0xa6, 0xee, 0xec, 0x5a, 0xe6, 0xc1, 0x51, - 0x67, 0xff, 0x29, 0x5d, 0x9d, 0x89, 0x3b, 0xc4, 0xd1, 0xe1, 0xb6, 0x79, 0xb0, 0xdf, 0xb3, 0xba, - 0x3b, 0x47, 0xbd, 0x2d, 0xbc, 0x78, 0x73, 0xd3, 0xec, 0x1c, 0x52, 0x99, 0xf9, 0x97, 0x21, 0x88, - 0xa2, 0x0b, 0x82, 0x5e, 0x9e, 0x1e, 0x74, 0xbb, 0x9d, 0x43, 0xeb, 0xd3, 0xa3, 0xb6, 0xd9, 0x69, - 0x77, 0x31, 0xe3, 0x5c, 0x0a, 0x5c, 0xe0, 0x17, 0xc5, 0xbe, 0xd2, 0xdb, 0xfd, 0x4c, 0x32, 0x7e, - 0x81, 0x5a, 0x4a, 0x82, 0x04, 0x56, 0x59, 0x0c, 0xa6, 0xe0, 0x9c, 0x29, 0x25, 0xc3, 0x35, 0x69, - 0x22, 0x5f, 0x45, 0xec, 0x09, 0x33, 0x84, 0x84, 0xd9, 0xaa, 0xe9, 0x49, 0x22, 0x17, 0x6e, 0x17, - 0xd1, 0xe6, 0xba, 0xb5, 0x65, 0x62, 0x86, 0xfa, 0x0c, 0x54, 0xe0, 0xce, 0x8b, 0x89, 0x12, 0xac, - 0x55, 0xa0, 0x34, 0xd4, 0x87, 0x48, 0x59, 0x78, 0xfc, 0x9b, 0x39, 0xa8, 0xd3, 0x91, 0x46, 0x7a, - 0xf0, 0x90, 0xfb, 0x6c, 0x0f, 0x8a, 0xf2, 0xe5, 0x4c, 0xb6, 0x1c, 0xdd, 0x6a, 0xa8, 0xbf, 0xd5, - 0xb9, 0xb6, 0x32, 0x0d, 0x96, 0xa2, 0xe4, 0xe2, 0x5f, 0xf9, 0x93, 0xff, 0xfe, 0x77, 0xb2, 0x35, - 0x56, 0x79, 0x78, 0xfe, 0xc1, 0xc3, 0x53, 0xee, 0x06, 0xa2, 0x8c, 0x5f, 0x01, 0x88, 0xdf, 0x83, - 0x64, 0x4d, 0xed, 0x1a, 0x85, 0xc4, 0x4b, 0x90, 0x6b, 0x37, 0x53, 0x52, 0x64, 0xb9, 0x37, 0xb1, - 0xdc, 0x45, 0xa3, 0x2e, 0xca, 0x75, 0x5c, 0x27, 0xa4, 0xb7, 0x21, 0x3f, 0xce, 0x3c, 0x60, 0x03, - 0xa8, 0xea, 0x2f, 0x35, 0x32, 0x25, 0xe5, 0xa5, 0xbc, 0x35, 0xb9, 0x76, 0x2b, 0x35, 0x4d, 0xc9, - 0xcf, 0x58, 0xc7, 0xb2, 0xd1, 0x10, 0x75, 0x4c, 0x10, 0x23, 0xae, 0x65, 0x48, 0x1a, 0x45, 0xfc, - 0x20, 0x23, 0xbb, 0xad, 0xc9, 0x84, 0x33, 0xcf, 0x41, 0xae, 0xdd, 0xb9, 0x26, 0x55, 0xd6, 0x75, - 0x07, 0xeb, 0x5a, 0x35, 0x98, 0xa8, 0xab, 0x8f, 0x38, 0xea, 0x39, 0xc8, 0x8f, 0x33, 0x0f, 0x1e, - 0xff, 0xfb, 0xf7, 0xa0, 0x1c, 0x85, 0x38, 0xb3, 0x5f, 0x87, 0x5a, 0xe2, 0xcc, 0x29, 0x53, 0xdd, - 0x48, 0x3b, 0xa2, 0xba, 0x76, 0x3b, 0x3d, 0x51, 0x56, 0xfc, 0x06, 0x56, 0xdc, 0x64, 0x2b, 0xa2, - 0x62, 0x79, 0xa6, 0xf3, 0x21, 0x9e, 0x11, 0xa7, 0x3b, 0x22, 0x5f, 0x68, 0x9a, 0x13, 0x55, 0x76, - 0x7b, 0x5a, 0x9b, 0x49, 0xd4, 0x76, 0xe7, 0x9a, 0x54, 0x59, 0xdd, 0x6d, 0xac, 0x6e, 0x85, 0x2d, - 0xe9, 0xd5, 0xa9, 0xc8, 0x58, 0xc6, 0xf1, 0x5e, 0x56, 0xfd, 0xbd, 0x42, 0x76, 0x27, 0xbe, 0x45, - 0x33, 0xe5, 0x1d, 0xc3, 0x88, 0x44, 0x66, 0x1f, 0x33, 0x34, 0x9a, 0x58, 0x15, 0x63, 0x38, 0x7d, - 0xfa, 0x73, 0x85, 0xec, 0x18, 0x2a, 0xda, 0x13, 0x3f, 0xec, 0xe6, 0xb5, 0xcf, 0x11, 0xad, 0xad, - 0xa5, 0x25, 0xa5, 0x75, 0x45, 0x2f, 0xff, 0xe1, 0x09, 0xe7, 0xec, 0x97, 0xa1, 0x1c, 0x3d, 0x1c, - 0xc3, 0x56, 0xb5, 0x87, 0x7c, 0xf4, 0x87, 0x6e, 0xd6, 0x9a, 0xb3, 0x09, 0x69, 0xc4, 0xa7, 0x97, - 0x2e, 0x88, 0xef, 0x73, 0xa8, 0x68, 0x8f, 0xc3, 0x44, 0x1d, 0x98, 0x7d, 0x80, 0x26, 0xea, 0x40, - 0xca, 0x5b, 0x32, 0xc6, 0x02, 0x56, 0x51, 0x61, 0x65, 0xa4, 0xef, 0xf0, 0xd2, 0x0b, 0xd8, 0x2e, - 0x2c, 0x4b, 0x2d, 0xf1, 0x98, 0x7f, 0x95, 0x69, 0x48, 0x79, 0x22, 0xf2, 0x51, 0x86, 0x7d, 0x02, - 0x25, 0xf5, 0x06, 0x10, 0x5b, 0x49, 0x7f, 0xcb, 0x68, 0x6d, 0x75, 0x06, 0x2e, 0x55, 0xba, 0xe7, - 0x00, 0xf1, 0x4b, 0x34, 0x11, 0x93, 0x98, 0x79, 0xd9, 0x26, 0xa2, 0x80, 0xd9, 0x67, 0x6b, 0x8c, - 0x15, 0xec, 0x60, 0x83, 0x21, 0x93, 0x70, 0xf9, 0x85, 0xba, 0x3c, 0xfb, 0x87, 0x50, 0xd1, 0x1e, - 0xa3, 0x89, 0x86, 0x6f, 0xf6, 0x21, 0x9b, 0x68, 0xf8, 0x52, 0xde, 0xae, 0x31, 0xd6, 0xb0, 0xf4, - 0x25, 0x63, 0x5e, 0x94, 0x2e, 0xc4, 0x44, 0x29, 0xae, 0x89, 0x09, 0x3a, 0x83, 0x5a, 0xe2, 0xc5, - 0x99, 0x68, 0x85, 0xa6, 0xbd, 0x67, 0x13, 0xad, 0xd0, 0xd4, 0x47, 0x6a, 0x14, 0x9d, 0x19, 0x0b, - 0xa2, 0x1e, 0xba, 0x3f, 0x4b, 0xab, 0xe9, 0x07, 0x50, 0xd1, 0x5e, 0x8f, 0x89, 0xfa, 0x32, 0xfb, - 0x50, 0x4d, 0xd4, 0x97, 0xb4, 0xc7, 0x66, 0x96, 0xb0, 0x8e, 0xba, 0x81, 0xa4, 0x80, 0xd7, 0xff, - 0x8a, 0xb2, 0x7f, 0x1d, 0xea, 0xc9, 0x07, 0x65, 0xa2, 0xb5, 0x9f, 0xfa, 0x32, 0x4d, 0xb4, 0xf6, - 0xaf, 0x79, 0x85, 0x46, 0x92, 0xf4, 0x83, 0xc5, 0xa8, 0x92, 0x87, 0x3f, 0x96, 0x87, 0xb5, 0xbe, - 0x64, 0x9f, 0x0a, 0x06, 0x27, 0x6f, 0x9f, 0x66, 0xab, 0x1a, 0xd5, 0xea, 0xd7, 0x58, 0x47, 0xeb, - 0x65, 0xe6, 0xa2, 0xea, 0x24, 0x31, 0x63, 0xe1, 0xec, 0x29, 0x2c, 0x46, 0xc4, 0x1c, 0x5d, 0x27, - 0x1d, 0x44, 0x7d, 0x48, 0xbd, 0xb4, 0x7a, 0xad, 0x31, 0x9d, 0xfa, 0x28, 0x43, 0xdb, 0x1f, 0x5e, - 0xe2, 0xab, 0x6d, 0x7f, 0xfa, 0x8d, 0xd2, 0xda, 0xf6, 0x97, 0xb8, 0xeb, 0x77, 0x7a, 0xfb, 0x0b, - 0x1d, 0x51, 0x86, 0x0b, 0xf3, 0xd3, 0x97, 0x3b, 0xdf, 0xb9, 0xee, 0x32, 0x0c, 0x2a, 0xfe, 0x8d, - 0x97, 0xdf, 0x95, 0x91, 0x64, 0x45, 0x8a, 0x9b, 0x3e, 0x94, 0xb1, 0x41, 0xec, 0x57, 0xa1, 0xaa, - 0x3f, 0x42, 0xc1, 0x74, 0x9e, 0x30, 0x5d, 0xd3, 0xad, 0xd4, 0xb4, 0x24, 0x95, 0xb0, 0xaa, 0x5e, - 0x0d, 0xfb, 0x0c, 0x56, 0xa2, 0x61, 0xd6, 0x6f, 0x73, 0x08, 0xd8, 0xdd, 0x94, 0x3b, 0x1e, 0x12, - 0x83, 0x7d, 0xf3, 0xda, 0x4b, 0x20, 0x1e, 0x65, 0x04, 0xf5, 0x25, 0x2f, 0xdc, 0x8f, 0x77, 0x9e, - 0xb4, 0x77, 0x06, 0xe2, 0x9d, 0x27, 0xf5, 0x96, 0x7e, 0x45, 0x7d, 0x6c, 0x31, 0x31, 0x46, 0x14, - 0x35, 0xcd, 0x7e, 0x00, 0xf3, 0xda, 0x55, 0x15, 0xdd, 0x2b, 0xb7, 0x1f, 0xad, 0xa4, 0xd9, 0x6b, - 0x5b, 0xd7, 0xd2, 0xec, 0xaa, 0xc6, 0x2a, 0x96, 0xbf, 0x60, 0x24, 0x06, 0x47, 0xac, 0xa2, 0x4d, - 0xa8, 0xe8, 0xd7, 0x60, 0xbc, 0xa4, 0xdc, 0x55, 0x2d, 0x49, 0xbf, 0x21, 0xf4, 0x51, 0x86, 0xed, - 0x42, 0x63, 0xfa, 0xd2, 0xba, 0x88, 0xa7, 0xa4, 0x5d, 0xf4, 0xb7, 0x36, 0x95, 0x98, 0xb8, 0xea, - 0x8e, 0x1d, 0xd2, 0xb9, 0x9b, 0xe8, 0x3d, 0x45, 0xcf, 0x9f, 0xde, 0xd5, 0x93, 0xef, 0x2c, 0x46, - 0xa5, 0xa5, 0xbd, 0xb0, 0x79, 0x3f, 0xf3, 0x28, 0xc3, 0x7e, 0x3b, 0x03, 0xd5, 0xc4, 0xa5, 0x4d, - 0x89, 0x93, 0x0d, 0x53, 0xfd, 0x6c, 0xea, 0x69, 0x7a, 0x47, 0x0d, 0x13, 0x07, 0x71, 0xf7, 0xc1, - 0xf7, 0x13, 0x93, 0xf4, 0xe3, 0x84, 0x5b, 0x72, 0x7d, 0xfa, 0xc1, 0xc5, 0x2f, 0xa7, 0x11, 0xf4, - 0x8b, 0x80, 0xbf, 0x7c, 0x94, 0x61, 0xff, 0x22, 0x03, 0xf5, 0x64, 0xbc, 0x41, 0xd4, 0xdd, 0xd4, - 0xc8, 0x86, 0x88, 0x94, 0xae, 0x09, 0x52, 0xf8, 0x01, 0xb6, 0xb2, 0xf7, 0xc0, 0x4c, 0xb4, 0x52, - 0x3e, 0x15, 0xf1, 0xd3, 0xb5, 0x96, 0xfd, 0x22, 0xbd, 0x6f, 0xac, 0x22, 0xcd, 0xd8, 0xec, 0x7b, - 0xb8, 0x11, 0xf9, 0xe9, 0xaf, 0xc7, 0x1a, 0xb9, 0xdf, 0xc8, 0x66, 0x70, 0x26, 0x7e, 0x48, 0xaf, - 0x0b, 0xaa, 0xc0, 0x24, 0x41, 0xca, 0xaf, 0x5d, 0xc8, 0xdb, 0xd8, 0xb1, 0x37, 0x8c, 0x9b, 0x89, - 0x8e, 0x4d, 0x4b, 0x1f, 0x2d, 0x6a, 0xa2, 0x7c, 0x01, 0x36, 0xde, 0x3e, 0x67, 0x5e, 0x85, 0x4d, - 0xad, 0x04, 0x1b, 0x39, 0xa2, 0x46, 0x4a, 0xf4, 0xc4, 0x7a, 0x7b, 0xcd, 0x62, 0x8c, 0x07, 0xd8, - 0xd6, 0xb7, 0x8d, 0xbb, 0xd7, 0xb6, 0xf5, 0x21, 0x06, 0x10, 0x88, 0x16, 0x1f, 0x02, 0xc4, 0xe1, - 0xa0, 0x6c, 0x2a, 0x28, 0x31, 0xe2, 0x42, 0xb3, 0x11, 0xa3, 0xc9, 0x45, 0xad, 0x62, 0x17, 0x45, - 0x89, 0xbf, 0x4c, 0x3c, 0x35, 0x0a, 0x97, 0xd4, 0x45, 0xb0, 0x64, 0xe4, 0x66, 0x42, 0x04, 0x9b, - 0x2e, 0x3f, 0xc1, 0x51, 0xa3, 0xd8, 0xc8, 0x23, 0xa8, 0xed, 0x7a, 0xde, 0x8b, 0xc9, 0x38, 0x3a, - 0x82, 0x90, 0x8c, 0x17, 0xda, 0xb1, 0x83, 0xb3, 0xb5, 0xa9, 0x5e, 0x18, 0xf7, 0xb0, 0xa8, 0x35, - 0xd6, 0xd4, 0x8a, 0x7a, 0xf8, 0xe3, 0x38, 0x06, 0xf5, 0x4b, 0x66, 0xc3, 0x42, 0xc4, 0xa8, 0xe3, - 0x38, 0xcf, 0x64, 0x31, 0x09, 0xf6, 0x3c, 0x5d, 0x45, 0x42, 0x57, 0x50, 0xad, 0x7d, 0x18, 0xa8, - 0x32, 0x1f, 0x65, 0xd8, 0x21, 0x54, 0xb7, 0x78, 0x1f, 0xef, 0xb0, 0xc0, 0xd8, 0x98, 0xc5, 0x44, - 0x9c, 0x05, 0x05, 0xd5, 0xac, 0xd5, 0x12, 0xc0, 0xe4, 0xe6, 0x35, 0xb6, 0xaf, 0x7c, 0xfe, 0xc5, - 0xc3, 0x1f, 0xcb, 0xa8, 0x9b, 0x2f, 0xd5, 0xe6, 0x15, 0x47, 0x60, 0xe9, 0x12, 0x40, 0x32, 0x8c, - 0x29, 0xb1, 0x79, 0xcd, 0x84, 0x31, 0x25, 0x86, 0x3a, 0x8a, 0xb7, 0x1a, 0xc2, 0xc2, 0x4c, 0xe4, - 0x53, 0xb4, 0x6f, 0x5d, 0x17, 0x2f, 0xb5, 0x76, 0xef, 0x7a, 0x84, 0x64, 0x6d, 0x0f, 0x92, 0xb5, - 0x75, 0xa1, 0x46, 0x57, 0xfd, 0x1e, 0x73, 0x3a, 0xcd, 0x3a, 0x75, 0x15, 0x94, 0x7e, 0x54, 0x76, - 0x7a, 0x97, 0xc1, 0xb4, 0xa4, 0x98, 0x83, 0xe7, 0x19, 0xd9, 0x09, 0xbe, 0x6f, 0xa1, 0x1d, 0x1f, - 0x8d, 0x88, 0x71, 0xf6, 0x48, 0x6b, 0x44, 0x8c, 0x29, 0xa7, 0x4d, 0x95, 0x0e, 0xca, 0x96, 0xa3, - 0xb2, 0x1f, 0xba, 0xde, 0x80, 0x8f, 0x64, 0xa9, 0xbf, 0x0c, 0x95, 0xa7, 0x3c, 0x54, 0xe7, 0x35, - 0x23, 0x81, 0x7e, 0xea, 0x00, 0xe7, 0x5a, 0xca, 0x29, 0xdb, 0x24, 0x6d, 0x52, 0xc9, 0x7c, 0x70, - 0xca, 0x89, 0x13, 0x5a, 0xce, 0xe0, 0x4b, 0xf6, 0x4b, 0x58, 0x78, 0x74, 0x3b, 0xc1, 0x8a, 0xd6, - 0x4c, 0xbd, 0xf0, 0xf9, 0x29, 0x78, 0x5a, 0xc9, 0xa2, 0xcd, 0x9a, 0x60, 0xe9, 0x42, 0x45, 0xbb, - 0xc5, 0x24, 0x1a, 0x9b, 0xd9, 0x5b, 0x6b, 0xa2, 0xb1, 0x49, 0xb9, 0xf4, 0xc4, 0xb8, 0x8f, 0xf5, - 0x18, 0xec, 0x5e, 0x5c, 0x0f, 0x5d, 0x74, 0x12, 0xd7, 0xf4, 0xf0, 0xc7, 0xf6, 0x28, 0xfc, 0x92, - 0x7d, 0x4e, 0xd3, 0xa1, 0x9d, 0x47, 0x8d, 0x35, 0x94, 0xe9, 0xa3, 0xab, 0xd1, 0x60, 0x69, 0x49, - 0x49, 0xad, 0x85, 0xaa, 0x42, 0xb1, 0xf1, 0x09, 0x40, 0x37, 0xf4, 0xc6, 0x5b, 0x36, 0x1f, 0x79, - 0x6e, 0xcc, 0xd3, 0xe3, 0x13, 0x92, 0x31, 0x9f, 0xd4, 0x8e, 0x49, 0xb2, 0xcf, 0x35, 0x95, 0x2e, - 0x71, 0x92, 0x5a, 0x11, 0xf1, 0xb5, 0x87, 0x28, 0xa3, 0x01, 0x49, 0x39, 0x48, 0xf9, 0x28, 0xc3, - 0x5a, 0x00, 0x71, 0x88, 0x5d, 0xa4, 0xa0, 0xcd, 0x44, 0xef, 0x45, 0xec, 0x35, 0x25, 0x1e, 0xef, - 0x10, 0xca, 0x71, 0x6c, 0xd2, 0x6a, 0x7c, 0x29, 0x53, 0x22, 0x92, 0x29, 0x12, 0x17, 0x66, 0xe2, - 0x82, 0x8c, 0x06, 0x0e, 0x15, 0xb0, 0x92, 0x18, 0xaa, 0x13, 0xce, 0x03, 0xe6, 0xc0, 0x22, 0x35, - 0x30, 0x92, 0xcd, 0xf0, 0x64, 0x5f, 0xf4, 0xaa, 0xcc, 0x6c, 0x88, 0x4e, 0xc4, 0x35, 0x52, 0x03, - 0x4d, 0x12, 0x76, 0x26, 0x41, 0xad, 0x74, 0xaa, 0x50, 0x6c, 0x01, 0x23, 0x58, 0x98, 0x89, 0x65, - 0x88, 0x58, 0xc7, 0x75, 0xc1, 0x29, 0x11, 0xeb, 0xb8, 0x36, 0x0c, 0xc2, 0x58, 0xc6, 0x2a, 0xe7, - 0x0d, 0x40, 0xbd, 0xf2, 0xc2, 0x09, 0xfb, 0x67, 0xa2, 0xba, 0xdf, 0xcb, 0xc0, 0x62, 0x4a, 0xb4, - 0x02, 0x7b, 0x53, 0x99, 0x28, 0xae, 0x8d, 0x64, 0x58, 0x4b, 0xf5, 0x6a, 0x1b, 0x5d, 0xac, 0x67, - 0x8f, 0x3d, 0x4b, 0x6c, 0xa0, 0xe4, 0x54, 0x96, 0x2b, 0xf3, 0xa5, 0x12, 0x4c, 0xaa, 0xf8, 0xf2, - 0x05, 0xac, 0x52, 0x43, 0x5a, 0xc3, 0xe1, 0x94, 0xc7, 0xfd, 0x0d, 0xad, 0x15, 0x29, 0x51, 0x04, - 0x09, 0x65, 0x20, 0x19, 0x49, 0x70, 0x8d, 0xec, 0x4e, 0x4d, 0x65, 0x13, 0x68, 0x4c, 0x7b, 0xb2, - 0xd9, 0xf5, 0x65, 0xad, 0xdd, 0x4d, 0x28, 0xdb, 0x29, 0xde, 0xef, 0xaf, 0x61, 0x65, 0x77, 0x8d, - 0xb5, 0xb4, 0x71, 0x21, 0xfd, 0x5b, 0xcc, 0xc7, 0xff, 0x1f, 0xb9, 0xdd, 0xa7, 0xfa, 0x79, 0x37, - 0xba, 0x47, 0x3f, 0x3d, 0x48, 0x20, 0x52, 0xf7, 0xd3, 0xbd, 0xf6, 0xef, 0x60, 0xf5, 0xf7, 0x8c, - 0x5b, 0x69, 0xd5, 0xfb, 0x94, 0x85, 0x14, 0xff, 0xd5, 0xe9, 0x75, 0xad, 0x5a, 0x70, 0x2f, 0x6d, - 0xbe, 0xaf, 0x55, 0xbc, 0xa6, 0xc6, 0xfa, 0x06, 0xca, 0x90, 0x55, 0xdd, 0xcd, 0x1e, 0x2d, 0x9f, - 0x14, 0x7f, 0x7e, 0xb4, 0x7c, 0xd2, 0xfc, 0xf2, 0x49, 0xf9, 0x49, 0x79, 0xe4, 0x3f, 0xce, 0x3c, - 0xd8, 0x78, 0xf7, 0x07, 0x5f, 0x3b, 0x75, 0xc2, 0xb3, 0xc9, 0xf1, 0x7a, 0xdf, 0x1b, 0x3d, 0x1c, - 0x2a, 0xd3, 0xa6, 0x3c, 0xfe, 0xfe, 0x70, 0xe8, 0x0e, 0x1e, 0x62, 0xb1, 0xc7, 0x73, 0x63, 0xdf, - 0x0b, 0xbd, 0x6f, 0xfe, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, 0x24, 0xba, 0xa4, 0x4f, 0x8a, - 0x00, 0x00, + // 12041 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x6c, 0x24, 0x49, + 0x76, 0x18, 0xda, 0xf5, 0x22, 0xab, 0x4e, 0x3d, 0x58, 0x0c, 0xbe, 0xaa, 0xd9, 0xdd, 0xd3, 0x3d, + 0x39, 0xb3, 0xd3, 0xbd, 0x3d, 0xb3, 0xec, 0x9e, 0xde, 0xed, 0x99, 0xdd, 0x99, 0xab, 0xd5, 0x16, + 0xc9, 0x62, 0xb3, 0xb6, 0xc9, 0x22, 0x27, 0xab, 0x38, 0xa3, 0x59, 0x3d, 0x72, 0x93, 0x55, 0x41, + 0x32, 0xd5, 0x55, 0x99, 0x35, 0x99, 0x59, 0x7c, 0xec, 0x62, 0xee, 0x87, 0x61, 0x1b, 0x82, 0x61, + 0x1b, 0x10, 0x6c, 0x19, 0xb0, 0x2c, 0xc1, 0x0f, 0xc1, 0x36, 0x0c, 0x03, 0x82, 0x00, 0xc9, 0x1f, + 0x06, 0xfc, 0xaf, 0x1f, 0x3f, 0x60, 0x48, 0xfe, 0xb0, 0x21, 0x08, 0x30, 0x6c, 0xcb, 0x7f, 0x86, + 0x00, 0x7f, 0x1b, 0x30, 0xe2, 0x9c, 0x88, 0xcc, 0xc8, 0xaa, 0x64, 0x77, 0xcf, 0xee, 0x7a, 0x7f, + 0xc8, 0xca, 0x13, 0x27, 0xde, 0x27, 0x4e, 0x9c, 0x57, 0x44, 0x40, 0xc9, 0x1f, 0xf7, 0x37, 0xc6, + 0xbe, 0x17, 0x7a, 0xac, 0x30, 0x74, 0xfd, 0x71, 0x7f, 0xfd, 0xf6, 0xa9, 0xe7, 0x9d, 0x0e, 0xf9, + 0x23, 0x7b, 0xec, 0x3c, 0xb2, 0x5d, 0xd7, 0x0b, 0xed, 0xd0, 0xf1, 0xdc, 0x80, 0x90, 0x8c, 0x1f, + 0x42, 0xed, 0x19, 0x77, 0xbb, 0x9c, 0x0f, 0x4c, 0xfe, 0xc5, 0x84, 0x07, 0x21, 0x7b, 0x17, 0x16, + 0x6d, 0xfe, 0x23, 0xce, 0x07, 0xd6, 0xd8, 0x0e, 0x82, 0xf1, 0x99, 0x6f, 0x07, 0xbc, 0x91, 0xb9, + 0x97, 0x79, 0x50, 0x31, 0xeb, 0x94, 0x70, 0x18, 0xc1, 0xd9, 0x9b, 0x50, 0x09, 0x04, 0x2a, 0x77, + 0x43, 0xdf, 0x1b, 0x5f, 0x35, 0xb2, 0x88, 0x57, 0x16, 0xb0, 0x16, 0x81, 0x8c, 0x21, 0x2c, 0x44, + 0x35, 0x04, 0x63, 0xcf, 0x0d, 0x38, 0x7b, 0x0c, 0xcb, 0x7d, 0x67, 0x7c, 0xc6, 0x7d, 0x0b, 0x33, + 0x8f, 0x5c, 0x3e, 0xf2, 0x5c, 0xa7, 0xdf, 0xc8, 0xdc, 0xcb, 0x3d, 0x28, 0x99, 0x8c, 0xd2, 0x44, + 0x8e, 0x7d, 0x99, 0xc2, 0xee, 0xc3, 0x02, 0x77, 0x09, 0xce, 0x07, 0x98, 0x4b, 0x56, 0x55, 0x8b, + 0xc1, 0x22, 0x83, 0xf1, 0x1b, 0x59, 0x58, 0x6c, 0xbb, 0x4e, 0xf8, 0x99, 0x3d, 0x1c, 0xf2, 0x50, + 0xf5, 0xe9, 0x3e, 0x2c, 0x5c, 0x20, 0x00, 0xfb, 0x74, 0xe1, 0xf9, 0x03, 0xd9, 0xa3, 0x1a, 0x81, + 0x0f, 0x25, 0xf4, 0xda, 0x96, 0x65, 0xaf, 0x6d, 0x59, 0xea, 0x70, 0xe5, 0xae, 0x19, 0xae, 0xfb, + 0xb0, 0xe0, 0xf3, 0xbe, 0x77, 0xce, 0xfd, 0x2b, 0xeb, 0xc2, 0x71, 0x07, 0xde, 0x45, 0x23, 0x7f, + 0x2f, 0xf3, 0xa0, 0x60, 0xd6, 0x14, 0xf8, 0x33, 0x84, 0xb2, 0x4d, 0x58, 0xe8, 0x9f, 0xd9, 0xae, + 0xcb, 0x87, 0xd6, 0xb1, 0xdd, 0x7f, 0x31, 0x19, 0x07, 0x8d, 0xc2, 0xbd, 0xcc, 0x83, 0xf2, 0x93, + 0x9b, 0x1b, 0x38, 0xab, 0x1b, 0x5b, 0x67, 0xb6, 0xbb, 0x89, 0x29, 0x5d, 0xd7, 0x1e, 0x07, 0x67, + 0x5e, 0x68, 0xd6, 0x64, 0x0e, 0x02, 0x07, 0xc6, 0x32, 0x30, 0x7d, 0x24, 0x68, 0xec, 0x8d, 0x7f, + 0x99, 0x81, 0xa5, 0x23, 0x77, 0xe8, 0xf5, 0x5f, 0xfc, 0x84, 0x43, 0x94, 0xd2, 0x87, 0xec, 0xeb, + 0xf6, 0x21, 0xf7, 0x55, 0xfb, 0xb0, 0x0a, 0xcb, 0xc9, 0xc6, 0xca, 0x5e, 0x70, 0x58, 0x11, 0xb9, + 0x4f, 0xb9, 0x6a, 0x96, 0xea, 0xc6, 0xd7, 0xa1, 0xde, 0x9f, 0xf8, 0x3e, 0x77, 0x67, 0xfa, 0xb1, + 0x20, 0xe1, 0x51, 0x47, 0xde, 0x84, 0x8a, 0xcb, 0x2f, 0x62, 0x34, 0x49, 0xbb, 0x2e, 0xbf, 0x50, + 0x28, 0x46, 0x03, 0x56, 0xa7, 0xab, 0x91, 0x0d, 0xf8, 0x8b, 0x0c, 0xe4, 0x8f, 0xc2, 0x4b, 0x8f, + 0x3d, 0x85, 0x8a, 0x3d, 0x18, 0xf8, 0x3c, 0x08, 0xac, 0xf0, 0x6a, 0x4c, 0x2b, 0xa5, 0xf6, 0x84, + 0xc9, 0x2e, 0x36, 0x29, 0xa9, 0x77, 0x35, 0xe6, 0x66, 0xd9, 0x8e, 0x3f, 0x58, 0x03, 0xe6, 0xe5, + 0x27, 0xd6, 0x5b, 0x32, 0xd5, 0x27, 0xbb, 0x03, 0x60, 0x8f, 0xbc, 0x89, 0x1b, 0x5a, 0x81, 0x1d, + 0xe2, 0x88, 0xe5, 0xcc, 0x12, 0x41, 0xba, 0x76, 0xc8, 0x6e, 0x41, 0x69, 0xfc, 0xc2, 0x0a, 0xfa, + 0xbe, 0x33, 0x0e, 0x91, 0x78, 0x4a, 0x66, 0x71, 0xfc, 0xa2, 0x8b, 0xdf, 0xec, 0x5d, 0x28, 0x7a, + 0x93, 0x70, 0xec, 0x39, 0x6e, 0x28, 0xe9, 0x65, 0x41, 0x36, 0xe4, 0x60, 0x12, 0x1e, 0x0a, 0xb0, + 0x19, 0x21, 0xb0, 0xb7, 0xa1, 0xda, 0xf7, 0xdc, 0x13, 0xc7, 0x1f, 0x11, 0x47, 0x68, 0xcc, 0x61, + 0x5d, 0x49, 0xa0, 0xf1, 0x07, 0x59, 0x28, 0xf7, 0x7c, 0xdb, 0x0d, 0xec, 0xbe, 0x00, 0xb0, 0x35, + 0x98, 0x0f, 0x2f, 0xad, 0x33, 0x3b, 0x38, 0xc3, 0xae, 0x96, 0xcc, 0xb9, 0xf0, 0x72, 0xd7, 0x0e, + 0xce, 0xd8, 0x2a, 0xcc, 0x51, 0x2b, 0xb1, 0x43, 0x39, 0x53, 0x7e, 0x89, 0x05, 0xe2, 0x4e, 0x46, + 0x56, 0xb2, 0xaa, 0x1c, 0x52, 0x4c, 0xdd, 0x9d, 0x8c, 0xb6, 0x74, 0xb8, 0xe8, 0xfc, 0xb1, 0x98, + 0x6e, 0xaa, 0x80, 0xba, 0x57, 0x42, 0x08, 0xd6, 0xf1, 0x26, 0x54, 0x64, 0x32, 0x77, 0x4e, 0xcf, + 0xa8, 0x8f, 0x05, 0xb3, 0x4c, 0x08, 0x08, 0x12, 0x25, 0x84, 0xce, 0x88, 0x5b, 0x41, 0x68, 0x8f, + 0xc6, 0xb2, 0x4b, 0x25, 0x01, 0xe9, 0x0a, 0x00, 0x26, 0x7b, 0xa1, 0x3d, 0xb4, 0x4e, 0x38, 0x0f, + 0x1a, 0xf3, 0x32, 0x59, 0x40, 0x76, 0x38, 0x0f, 0xd8, 0xd7, 0xa0, 0x36, 0xe0, 0x41, 0x68, 0xc9, + 0xc9, 0xe0, 0x41, 0xa3, 0x88, 0x2b, 0xbf, 0x2a, 0xa0, 0x4d, 0x05, 0x64, 0xb7, 0x01, 0x7c, 0xfb, + 0xc2, 0x12, 0x03, 0xc1, 0x2f, 0x1b, 0x25, 0x9a, 0x05, 0xdf, 0xbe, 0xe8, 0x5d, 0xee, 0xf2, 0x4b, + 0x41, 0x35, 0xcf, 0x78, 0xa8, 0x0d, 0x5a, 0x20, 0xa9, 0xd3, 0xd8, 0x03, 0xa6, 0x81, 0xb7, 0x79, + 0x68, 0x3b, 0xc3, 0x80, 0x7d, 0x00, 0x95, 0x50, 0x43, 0x46, 0x36, 0x58, 0x8e, 0x48, 0x48, 0xcb, + 0x60, 0x26, 0xf0, 0x8c, 0x33, 0x28, 0xee, 0x70, 0xbe, 0xe7, 0x8c, 0x9c, 0x90, 0xad, 0x42, 0xe1, + 0xc4, 0xb9, 0xe4, 0x44, 0xec, 0xb9, 0xdd, 0x1b, 0x26, 0x7d, 0xb2, 0xbb, 0x00, 0xf8, 0xc3, 0x1a, + 0x45, 0xd4, 0xb4, 0x7b, 0xc3, 0x2c, 0x21, 0x6c, 0x3f, 0xb0, 0x43, 0xb6, 0x0e, 0xf3, 0x63, 0xee, + 0xf7, 0xb9, 0x9a, 0xb7, 0xdd, 0x1b, 0xa6, 0x02, 0x6c, 0xce, 0x43, 0x61, 0x28, 0x4a, 0x37, 0xfe, + 0xb8, 0x00, 0xe5, 0x2e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, 0xcd, + 0xde, 0x82, 0x32, 0x0e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x99, 0x6d, 0x64, 0x4c, + 0x10, 0xe0, 0x2e, 0x42, 0x59, 0x1d, 0x72, 0xf6, 0x48, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x42, 0xd1, + 0x1e, 0x85, 0xd4, 0xbc, 0x0a, 0x82, 0xe7, 0xed, 0x51, 0x88, 0x4d, 0x7b, 0x13, 0x2a, 0x63, 0xfb, + 0x6a, 0x24, 0xd6, 0x72, 0x44, 0x0e, 0x15, 0xb3, 0x2c, 0x61, 0x48, 0x10, 0x4f, 0x60, 0x49, 0x47, + 0x51, 0x95, 0x17, 0xa2, 0xca, 0x17, 0x35, 0x6c, 0xd9, 0x86, 0xfb, 0xb0, 0xa0, 0xf2, 0xf8, 0xd4, + 0x1f, 0x24, 0x93, 0x92, 0x59, 0x93, 0x60, 0xd5, 0xcb, 0x07, 0x50, 0x3f, 0x71, 0x5c, 0x7b, 0x68, + 0xf5, 0x87, 0xe1, 0xb9, 0x35, 0xe0, 0xc3, 0xd0, 0x46, 0x8a, 0x29, 0x98, 0x35, 0x84, 0x6f, 0x0d, + 0xc3, 0xf3, 0x6d, 0x01, 0x65, 0xef, 0x41, 0xe9, 0x84, 0x73, 0x0b, 0x07, 0xab, 0x51, 0x4c, 0x2c, + 0x3c, 0x35, 0x43, 0x66, 0xf1, 0x44, 0xcd, 0xd5, 0x7b, 0x50, 0xf7, 0x26, 0xe1, 0xa9, 0xe7, 0xb8, + 0xa7, 0x96, 0xe0, 0x77, 0x96, 0x33, 0x40, 0x1a, 0xca, 0x6f, 0x66, 0x1f, 0x67, 0xcc, 0x9a, 0x4a, + 0x13, 0x9c, 0xa7, 0x3d, 0x60, 0xef, 0xc0, 0xc2, 0xd0, 0x0e, 0x42, 0xeb, 0xcc, 0x1b, 0x5b, 0xe3, + 0xc9, 0xf1, 0x0b, 0x7e, 0xd5, 0xa8, 0xe2, 0x40, 0x54, 0x05, 0x78, 0xd7, 0x1b, 0x1f, 0x22, 0x50, + 0x50, 0x36, 0xb6, 0x93, 0x1a, 0x01, 0xf7, 0x32, 0x0f, 0xaa, 0x66, 0x49, 0x40, 0xa8, 0xd2, 0xcf, + 0x61, 0x09, 0xa7, 0xa7, 0x3f, 0x09, 0x42, 0x6f, 0x64, 0x09, 0x5e, 0xed, 0x0f, 0x82, 0x46, 0x19, + 0x69, 0xed, 0xeb, 0xb2, 0xb1, 0xda, 0x1c, 0x6f, 0x6c, 0xf3, 0x20, 0xdc, 0x42, 0x64, 0x93, 0x70, + 0xc5, 0x86, 0x7e, 0x65, 0x2e, 0x0e, 0xa6, 0xe1, 0xec, 0x3d, 0x60, 0xf6, 0x70, 0xe8, 0x5d, 0x58, + 0x01, 0x1f, 0x9e, 0x58, 0x72, 0x10, 0x1b, 0xb5, 0x7b, 0x99, 0x07, 0x45, 0xb3, 0x8e, 0x29, 0x5d, + 0x3e, 0x3c, 0x39, 0x24, 0x38, 0xfb, 0x00, 0x70, 0x31, 0x59, 0x27, 0xdc, 0x0e, 0x27, 0x3e, 0x0f, + 0x1a, 0x0b, 0xf7, 0x72, 0x0f, 0x6a, 0x4f, 0x16, 0xa3, 0xf1, 0x42, 0xf0, 0xa6, 0x13, 0x9a, 0x15, + 0x81, 0x27, 0xbf, 0x83, 0xf5, 0x6d, 0x58, 0x4d, 0x6f, 0x92, 0x20, 0x2a, 0x31, 0x2a, 0x82, 0x18, + 0xf3, 0xa6, 0xf8, 0xc9, 0x96, 0xa1, 0x70, 0x6e, 0x0f, 0x27, 0x5c, 0xf2, 0x74, 0xfa, 0xf8, 0x28, + 0xfb, 0xed, 0x8c, 0xf1, 0x47, 0x19, 0xa8, 0x50, 0x2f, 0xa5, 0x2c, 0xf2, 0x16, 0x54, 0x15, 0x35, + 0x70, 0xdf, 0xf7, 0x7c, 0xc9, 0xd5, 0x14, 0xe5, 0xb5, 0x04, 0x4c, 0xec, 0x2a, 0x0a, 0x69, 0xec, + 0x73, 0x67, 0x64, 0x9f, 0xaa, 0xa2, 0x15, 0x29, 0x1d, 0x4a, 0x30, 0x7b, 0x3f, 0x2e, 0xcf, 0xf7, + 0x26, 0x21, 0x97, 0x7b, 0x5e, 0x45, 0x76, 0xcf, 0x14, 0xb0, 0xa8, 0x74, 0xfc, 0x7a, 0x0d, 0x3a, + 0x37, 0x7e, 0x2b, 0x03, 0x4c, 0x34, 0xbb, 0xe7, 0x51, 0x01, 0x92, 0x42, 0xa7, 0x73, 0x66, 0x5e, + 0x7b, 0x85, 0x64, 0x5f, 0xb6, 0x42, 0x0c, 0x28, 0x50, 0xdb, 0xf3, 0x29, 0x6d, 0xa7, 0xa4, 0xef, + 0xe7, 0x8b, 0xb9, 0x7a, 0xde, 0xf8, 0x2f, 0x39, 0x58, 0xde, 0xa2, 0x2d, 0xbb, 0xd9, 0xef, 0xf3, + 0x71, 0xb4, 0x76, 0xee, 0x42, 0xd9, 0xf5, 0x06, 0x5c, 0x51, 0x2c, 0x35, 0x0c, 0x04, 0x48, 0x23, + 0xd7, 0x33, 0xdb, 0x71, 0xa9, 0xe1, 0x34, 0x98, 0x25, 0x84, 0x60, 0xb3, 0xdf, 0x81, 0x85, 0x31, + 0x77, 0x07, 0xfa, 0x12, 0x21, 0xa1, 0xaa, 0x2a, 0xc1, 0x72, 0x75, 0xdc, 0x85, 0xf2, 0xc9, 0x84, + 0xf0, 0x04, 0x63, 0xc9, 0x23, 0x0d, 0x80, 0x04, 0x35, 0x89, 0xbf, 0x8c, 0x27, 0xc1, 0x19, 0xa6, + 0x16, 0x30, 0x75, 0x5e, 0x7c, 0x8b, 0xa4, 0x3b, 0x00, 0x83, 0x49, 0x10, 0xca, 0x15, 0x33, 0x87, + 0x89, 0x25, 0x01, 0xa1, 0x15, 0xf3, 0x0d, 0x58, 0x1a, 0xd9, 0x97, 0x16, 0xd2, 0x8e, 0xe5, 0xb8, + 0xd6, 0xc9, 0x10, 0xf7, 0x9c, 0x79, 0xc4, 0xab, 0x8f, 0xec, 0xcb, 0x4f, 0x45, 0x4a, 0xdb, 0xdd, + 0x41, 0xb8, 0x60, 0x2b, 0x4a, 0xdc, 0xf1, 0x79, 0xc0, 0xfd, 0x73, 0x8e, 0x9c, 0x20, 0x1f, 0xc9, + 0x34, 0x26, 0x41, 0x45, 0x8b, 0x46, 0xa2, 0xdf, 0xe1, 0xb0, 0x4f, 0xcb, 0xde, 0x9c, 0x1f, 0x39, + 0xee, 0x6e, 0x38, 0xec, 0x8b, 0x7d, 0x45, 0xf0, 0x91, 0x31, 0xf7, 0xad, 0x17, 0x17, 0xb8, 0x86, + 0xf3, 0xc8, 0x37, 0x0e, 0xb9, 0xff, 0xfc, 0x42, 0x6c, 0xfd, 0xfd, 0x00, 0x19, 0x91, 0x7d, 0xd5, + 0x28, 0xe3, 0x02, 0x2f, 0xf6, 0x03, 0xc1, 0x82, 0xec, 0x2b, 0xb1, 0x08, 0x45, 0x6b, 0x6d, 0x9c, + 0x05, 0x3e, 0xc0, 0xe2, 0x03, 0xe4, 0xa8, 0x55, 0x6c, 0x6c, 0x53, 0x26, 0x88, 0x7a, 0x02, 0x41, + 0xf5, 0xaa, 0xb1, 0x27, 0x43, 0xfb, 0x34, 0x40, 0x96, 0x52, 0x35, 0x2b, 0x12, 0xb8, 0x23, 0x60, + 0xc6, 0x67, 0x24, 0x64, 0x69, 0x73, 0x2b, 0xd7, 0x8c, 0xd8, 0xea, 0x11, 0x82, 0xf3, 0x5a, 0x34, + 0xe5, 0x57, 0xda, 0xa4, 0x65, 0x53, 0x26, 0xcd, 0xf8, 0xdd, 0x0c, 0x54, 0x64, 0xc9, 0x28, 0x94, + 0xb0, 0x0d, 0x60, 0x6a, 0x16, 0xc3, 0x4b, 0x67, 0x60, 0x1d, 0x5f, 0x85, 0x3c, 0x20, 0xa2, 0xd9, + 0xbd, 0x61, 0xd6, 0x65, 0x5a, 0xef, 0xd2, 0x19, 0x6c, 0x8a, 0x14, 0xf6, 0x10, 0xea, 0x09, 0xfc, + 0x20, 0xf4, 0x89, 0xa2, 0x77, 0x6f, 0x98, 0x35, 0x0d, 0xbb, 0x1b, 0xfa, 0x62, 0x8d, 0x08, 0x91, + 0x67, 0x12, 0x5a, 0x8e, 0x3b, 0xe0, 0x97, 0x48, 0x46, 0x55, 0xb3, 0x4c, 0xb0, 0xb6, 0x00, 0x6d, + 0xd6, 0xa0, 0xa2, 0x17, 0x67, 0x9c, 0x42, 0x51, 0xc9, 0x4b, 0x28, 0x30, 0x4c, 0x35, 0xc9, 0x2c, + 0x85, 0x51, 0x4b, 0x6e, 0x42, 0x31, 0xd9, 0x02, 0x73, 0x3e, 0x7c, 0xed, 0x8a, 0x8d, 0xef, 0x42, + 0x7d, 0x4f, 0x10, 0x8f, 0x2b, 0x88, 0x55, 0xca, 0x7f, 0xab, 0x30, 0xa7, 0x2d, 0x9a, 0x92, 0x29, + 0xbf, 0xc4, 0x9e, 0x7b, 0xe6, 0x05, 0xa1, 0xac, 0x05, 0x7f, 0x1b, 0x7f, 0x9c, 0x01, 0xd6, 0x0a, + 0x42, 0x67, 0x64, 0x87, 0x7c, 0x87, 0x47, 0x6c, 0xe1, 0x00, 0x2a, 0xa2, 0xb4, 0x9e, 0xd7, 0x24, + 0x81, 0x8c, 0x04, 0x8a, 0x77, 0xe5, 0x32, 0x9e, 0xcd, 0xb0, 0xa1, 0x63, 0x13, 0x9b, 0x4f, 0x14, + 0x20, 0x56, 0x59, 0x68, 0xfb, 0xa7, 0x3c, 0x44, 0x31, 0x4e, 0xca, 0xfb, 0x40, 0x20, 0x21, 0xc0, + 0xad, 0xff, 0x22, 0x2c, 0xce, 0x94, 0xa1, 0xf3, 0xe5, 0x52, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, + 0x82, 0xa5, 0x44, 0xbb, 0x24, 0xa5, 0xad, 0xc1, 0xbc, 0x58, 0x10, 0x42, 0x38, 0xc8, 0x90, 0x54, + 0x79, 0xc2, 0xb9, 0x10, 0x83, 0x1f, 0xc1, 0xf2, 0x09, 0xe7, 0xbe, 0x1d, 0x62, 0x22, 0xae, 0x18, + 0x31, 0x43, 0xb2, 0xe0, 0x45, 0x99, 0xd6, 0xb5, 0xc3, 0x43, 0xee, 0x8b, 0x99, 0x32, 0xfe, 0x5b, + 0x06, 0x16, 0x04, 0x07, 0xdd, 0xb7, 0xdd, 0x2b, 0x35, 0x4e, 0x7b, 0xa9, 0xe3, 0xf4, 0x40, 0xdb, + 0x0c, 0x35, 0xec, 0xaf, 0x3a, 0x48, 0xb9, 0xe9, 0x41, 0x62, 0xf7, 0xa0, 0x92, 0x68, 0x6b, 0x01, + 0xdb, 0x0a, 0x41, 0xd4, 0xc8, 0x9f, 0x7e, 0x18, 0xdf, 0x81, 0x7a, 0xdc, 0x6c, 0x39, 0x86, 0x0c, + 0xf2, 0x82, 0x24, 0x65, 0x01, 0xf8, 0xdb, 0xf8, 0x9d, 0x0c, 0x21, 0x6e, 0x79, 0x4e, 0x24, 0x9d, + 0x0a, 0x44, 0x21, 0xf7, 0x2a, 0x44, 0xf1, 0xfb, 0x5a, 0xa9, 0xfe, 0xa7, 0xef, 0xac, 0x58, 0x3a, + 0x01, 0x77, 0x07, 0x96, 0x3d, 0x1c, 0x22, 0xf3, 0x2d, 0x9a, 0xf3, 0xe2, 0xbb, 0x39, 0x1c, 0x1a, + 0xf7, 0x61, 0x51, 0x6b, 0xdd, 0x4b, 0xfa, 0xd1, 0x01, 0xb6, 0xe7, 0x04, 0xe1, 0x91, 0x1b, 0x8c, + 0x35, 0xc1, 0xed, 0x16, 0x94, 0x04, 0x87, 0x15, 0x2d, 0xa3, 0x25, 0x5b, 0x30, 0x05, 0xcb, 0x15, + 0xed, 0x0a, 0x30, 0xd1, 0xbe, 0x94, 0x89, 0x59, 0x99, 0x68, 0x5f, 0x62, 0xa2, 0xf1, 0x6d, 0x58, + 0x4a, 0x94, 0x27, 0xab, 0x7e, 0x13, 0x0a, 0x93, 0xf0, 0xd2, 0x53, 0xa2, 0x79, 0x59, 0x52, 0x88, + 0x50, 0x00, 0x4d, 0x4a, 0x31, 0x3e, 0x86, 0xc5, 0x0e, 0xbf, 0x90, 0x8b, 0x58, 0x35, 0xe4, 0x1d, + 0xc8, 0xbf, 0x42, 0x29, 0xc4, 0x74, 0x63, 0x03, 0x98, 0x9e, 0x59, 0xd6, 0xaa, 0xe9, 0x88, 0x99, + 0x84, 0x8e, 0x68, 0xbc, 0x03, 0xac, 0xeb, 0x9c, 0xba, 0xfb, 0x3c, 0x08, 0xec, 0xd3, 0x68, 0xd9, + 0xd7, 0x21, 0x37, 0x0a, 0x4e, 0x25, 0x8f, 0x12, 0x3f, 0x8d, 0x6f, 0xc2, 0x52, 0x02, 0x4f, 0x16, + 0x7c, 0x1b, 0x4a, 0x81, 0x73, 0xea, 0xa2, 0x60, 0x25, 0x8b, 0x8e, 0x01, 0xc6, 0x0e, 0x2c, 0x7f, + 0xca, 0x7d, 0xe7, 0xe4, 0xea, 0x55, 0xc5, 0x27, 0xcb, 0xc9, 0x4e, 0x97, 0xd3, 0x82, 0x95, 0xa9, + 0x72, 0x64, 0xf5, 0x44, 0xbe, 0x72, 0x26, 0x8b, 0x26, 0x7d, 0x68, 0x7c, 0x2f, 0xab, 0xf3, 0x3d, + 0xe3, 0x08, 0xd8, 0x96, 0xe7, 0xba, 0xbc, 0x1f, 0x1e, 0x72, 0xee, 0xc7, 0x56, 0xaa, 0x98, 0x56, + 0xcb, 0x4f, 0xd6, 0xe4, 0xc8, 0x4e, 0x33, 0x53, 0x49, 0xc4, 0x0c, 0xf2, 0x63, 0xee, 0x8f, 0xb0, + 0xe0, 0xa2, 0x89, 0xbf, 0x8d, 0x15, 0x58, 0x4a, 0x14, 0x2b, 0xf5, 0xfa, 0xc7, 0xb0, 0xb2, 0xed, + 0x04, 0xfd, 0xd9, 0x0a, 0xd7, 0x60, 0x7e, 0x3c, 0x39, 0xb6, 0x92, 0x7c, 0xf9, 0x39, 0xbf, 0x12, + 0xda, 0xde, 0x74, 0x0e, 0x59, 0xd6, 0x5f, 0xcd, 0x40, 0x7e, 0xb7, 0xb7, 0xb7, 0xc5, 0xd6, 0xa1, + 0xe8, 0xb8, 0x7d, 0x6f, 0x24, 0x04, 0x2f, 0xea, 0x73, 0xf4, 0x7d, 0xed, 0x02, 0xbb, 0x05, 0x25, + 0x94, 0xd7, 0x84, 0x6a, 0x2b, 0x45, 0x9f, 0xa2, 0x00, 0xec, 0x79, 0xfd, 0x17, 0x42, 0xa7, 0xe6, + 0x97, 0x63, 0xc7, 0x47, 0xad, 0x59, 0x29, 0xc3, 0x79, 0xda, 0xeb, 0xe3, 0x04, 0xd2, 0x88, 0x8d, + 0x7f, 0x5d, 0x84, 0x79, 0xb9, 0xdb, 0xd2, 0xce, 0x1d, 0x3a, 0xe7, 0x3c, 0xde, 0xb9, 0xc5, 0x97, + 0x90, 0x07, 0x7c, 0x3e, 0xf2, 0xc2, 0x48, 0x60, 0xa3, 0x39, 0xa8, 0x10, 0x50, 0x8a, 0x6c, 0x9a, + 0xd0, 0x40, 0x26, 0x86, 0x1c, 0x21, 0xf5, 0xf5, 0xad, 0xfc, 0x16, 0xcc, 0xab, 0xbd, 0x3f, 0x1f, + 0xe9, 0x34, 0x73, 0x7d, 0x92, 0xd6, 0xd6, 0xa1, 0xd8, 0xb7, 0xc7, 0x76, 0xdf, 0x09, 0xaf, 0x24, + 0x43, 0x88, 0xbe, 0x45, 0xe9, 0x43, 0xaf, 0x6f, 0x0f, 0xad, 0x63, 0x7b, 0x68, 0xbb, 0x7d, 0x2e, + 0x75, 0xf7, 0x0a, 0x02, 0x37, 0x09, 0x26, 0xf4, 0x73, 0xd9, 0x4e, 0x85, 0x45, 0x2a, 0xbc, 0x6c, + 0xbd, 0x42, 0x13, 0xc2, 0xa5, 0x37, 0x1a, 0x39, 0x42, 0xcb, 0x20, 0x31, 0x2c, 0x67, 0x96, 0x08, + 0xb2, 0xc3, 0xb1, 0xb7, 0x32, 0xf9, 0x82, 0x86, 0xae, 0x44, 0x55, 0x11, 0xf0, 0x33, 0x32, 0x24, + 0xcc, 0xca, 0x62, 0x39, 0x4d, 0x16, 0x7b, 0x17, 0x16, 0x27, 0x6e, 0xc0, 0xc3, 0x70, 0xc8, 0x07, + 0x51, 0x5b, 0xca, 0x88, 0x54, 0x8f, 0x12, 0x54, 0x73, 0x36, 0x60, 0x89, 0x8c, 0x0e, 0x81, 0x1d, + 0x7a, 0xc1, 0x99, 0x13, 0x58, 0x81, 0xd0, 0x90, 0x48, 0xdd, 0x5d, 0xc4, 0xa4, 0xae, 0x4c, 0xe9, + 0x92, 0x8a, 0xb4, 0x36, 0x85, 0xef, 0xf3, 0x3e, 0x77, 0xce, 0xf9, 0x00, 0xe5, 0xb4, 0x9c, 0xb9, + 0x92, 0xc8, 0x63, 0xca, 0x44, 0x14, 0xba, 0x27, 0x23, 0x6b, 0x32, 0x1e, 0xd8, 0x42, 0x58, 0xa9, + 0x91, 0x30, 0xec, 0x4e, 0x46, 0x47, 0x04, 0x61, 0x8f, 0x41, 0x49, 0x62, 0x52, 0x3e, 0x5c, 0x48, + 0xf0, 0x33, 0x41, 0xac, 0x66, 0x45, 0x62, 0x90, 0xa0, 0x98, 0x90, 0x39, 0xeb, 0x53, 0x32, 0x67, + 0x03, 0xe6, 0xc7, 0xbe, 0x73, 0x6e, 0x87, 0xbc, 0xb1, 0x48, 0x0c, 0x5c, 0x7e, 0x0a, 0xce, 0xe0, + 0xb8, 0x4e, 0xe8, 0xd8, 0xa1, 0xe7, 0x37, 0x18, 0xa6, 0xc5, 0x00, 0xf6, 0x10, 0x16, 0x91, 0x46, + 0x82, 0xd0, 0x0e, 0x27, 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x22, 0x1c, 0x85, + 0x50, 0xf6, 0x4d, 0x58, 0x25, 0xb2, 0xc0, 0x1c, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x87, 0x62, + 0x09, 0x53, 0x05, 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0x4f, 0x61, 0x4d, 0x92, 0xc9, 0x4c, 0xae, + 0x15, 0xcc, 0xb5, 0x4c, 0xc9, 0x53, 0xd9, 0x36, 0x60, 0x51, 0x34, 0xc9, 0xe9, 0x5b, 0x32, 0xb7, + 0x58, 0x09, 0xab, 0xa2, 0xf5, 0xa8, 0x29, 0x2d, 0x50, 0xa2, 0x89, 0x69, 0xcf, 0xf9, 0x15, 0xfb, + 0x2e, 0x2c, 0x10, 0xc9, 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, + 0xa9, 0xc8, 0xec, 0x6b, 0xfd, 0xc4, 0xb7, 0x58, 0x0e, 0x43, 0xe7, 0x84, 0x87, 0xce, 0x88, 0x37, + 0xd6, 0x88, 0xc0, 0xd4, 0xb7, 0x58, 0xa9, 0x93, 0x31, 0xa6, 0x34, 0x88, 0x2f, 0xd0, 0x17, 0xd2, + 0xee, 0xd0, 0x0b, 0xb8, 0x32, 0x51, 0x35, 0x6e, 0xca, 0x45, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, + 0x38, 0x29, 0x3d, 0x91, 0x21, 0xf1, 0x16, 0x12, 0x43, 0x95, 0x74, 0x1f, 0x65, 0x4c, 0x14, 0xbb, + 0xf8, 0x99, 0x7d, 0xa1, 0x38, 0xc8, 0x6d, 0x9c, 0x5f, 0x10, 0x20, 0xc9, 0x3b, 0xfe, 0x30, 0x43, + 0x1b, 0xa2, 0xe4, 0x1f, 0x81, 0xa6, 0xde, 0x11, 0xe7, 0xb0, 0x3c, 0x77, 0x78, 0x25, 0x99, 0x09, + 0x10, 0xe8, 0xc0, 0x1d, 0xe2, 0x6a, 0x76, 0x5c, 0x1d, 0x85, 0x78, 0x6f, 0x45, 0x01, 0x11, 0xe9, + 0x2e, 0x94, 0xc7, 0x93, 0xe3, 0xa1, 0xd3, 0x27, 0x94, 0x1c, 0x95, 0x42, 0x20, 0x44, 0x10, 0xfa, + 0x2d, 0x51, 0x14, 0x61, 0xe4, 0x11, 0xa3, 0x2c, 0x61, 0x88, 0x82, 0xbc, 0x9d, 0xfb, 0xc8, 0x4e, + 0x2a, 0x26, 0xfe, 0x36, 0x36, 0x61, 0x39, 0xd9, 0x68, 0xb9, 0xf1, 0x3c, 0x84, 0xa2, 0xe4, 0x55, + 0xca, 0xf0, 0x51, 0xd3, 0x4c, 0xd1, 0x42, 0x45, 0x8b, 0xd2, 0x8d, 0xdf, 0x2b, 0xc0, 0x92, 0x84, + 0x6e, 0x89, 0xa1, 0xed, 0x4e, 0x46, 0x23, 0xdb, 0x4f, 0x61, 0x82, 0x99, 0x97, 0x33, 0xc1, 0xec, + 0x0c, 0x13, 0x4c, 0x6a, 0xbe, 0xc4, 0x43, 0x93, 0x9a, 0xaf, 0x98, 0x4b, 0x52, 0x46, 0x74, 0x3b, + 0x68, 0x55, 0x82, 0x7b, 0x64, 0x6f, 0x9d, 0x61, 0xd9, 0x85, 0x14, 0x96, 0xad, 0x33, 0xdc, 0xb9, + 0x29, 0x86, 0xfb, 0x26, 0x10, 0xd1, 0xa8, 0xd9, 0x9f, 0x27, 0xfd, 0x04, 0x61, 0xd2, 0x98, 0x7a, + 0x1f, 0x16, 0xa6, 0x79, 0x1c, 0x31, 0xd3, 0x5a, 0x0a, 0x87, 0x73, 0x46, 0x1c, 0x77, 0x2b, 0x0d, + 0xb9, 0x24, 0x39, 0x9c, 0x33, 0xe2, 0x7b, 0x98, 0xa2, 0xf0, 0x5b, 0x00, 0x54, 0x37, 0x2e, 0x1a, + 0xc0, 0x45, 0xf3, 0x4e, 0x72, 0x2e, 0xf4, 0x51, 0xdf, 0x10, 0x1f, 0x13, 0x9f, 0xe3, 0x2a, 0x2a, + 0x61, 0x4e, 0x5c, 0x40, 0x1f, 0x42, 0xcd, 0x1b, 0x73, 0xd7, 0x8a, 0x79, 0x4d, 0x19, 0x8b, 0xaa, + 0xcb, 0xa2, 0xda, 0x0a, 0x6e, 0x56, 0x05, 0x5e, 0xf4, 0xc9, 0xbe, 0x43, 0x83, 0xcc, 0xb5, 0x9c, + 0x95, 0x6b, 0x72, 0xd6, 0x10, 0x31, 0xfa, 0x36, 0xfe, 0x46, 0x06, 0xca, 0x5a, 0x73, 0xd8, 0x0a, + 0x2c, 0x6e, 0x1d, 0x1c, 0x1c, 0xb6, 0xcc, 0x66, 0xaf, 0xfd, 0x69, 0xcb, 0xda, 0xda, 0x3b, 0xe8, + 0xb6, 0xea, 0x37, 0x04, 0x78, 0xef, 0x60, 0xab, 0xb9, 0x67, 0xed, 0x1c, 0x98, 0x5b, 0x0a, 0x9c, + 0x61, 0xab, 0xc0, 0xcc, 0xd6, 0xfe, 0x41, 0xaf, 0x95, 0x80, 0x67, 0x59, 0x1d, 0x2a, 0x9b, 0x66, + 0xab, 0xb9, 0xb5, 0x2b, 0x21, 0x39, 0xb6, 0x0c, 0xf5, 0x9d, 0xa3, 0xce, 0x76, 0xbb, 0xf3, 0xcc, + 0xda, 0x6a, 0x76, 0xb6, 0x5a, 0x7b, 0xad, 0xed, 0x7a, 0x9e, 0x55, 0xa1, 0xd4, 0xdc, 0x6c, 0x76, + 0xb6, 0x0f, 0x3a, 0xad, 0xed, 0x7a, 0xc1, 0xf8, 0xf3, 0x0c, 0xac, 0xe0, 0x40, 0x0d, 0xa6, 0x57, + 0xe8, 0x3d, 0x28, 0xf7, 0x3d, 0x6f, 0x2c, 0xd4, 0xa0, 0x78, 0xbb, 0xd7, 0x41, 0x62, 0xf5, 0x11, + 0x67, 0x3d, 0xf1, 0xfc, 0x3e, 0x97, 0x0b, 0x14, 0x10, 0xb4, 0x23, 0x20, 0x82, 0x40, 0x24, 0x85, + 0x11, 0x06, 0xad, 0xcf, 0x32, 0xc1, 0x08, 0x65, 0x15, 0xe6, 0x8e, 0x7d, 0x6e, 0xf7, 0xcf, 0xe4, + 0xd2, 0x94, 0x5f, 0xec, 0xeb, 0xb1, 0x82, 0xde, 0x17, 0x13, 0x3e, 0xe4, 0x03, 0xa4, 0xcf, 0xa2, + 0xb9, 0x20, 0xe1, 0x5b, 0x12, 0x2c, 0xb6, 0x0a, 0xfb, 0xd8, 0x76, 0x07, 0x9e, 0xcb, 0x07, 0x52, + 0x0f, 0x88, 0x01, 0xc6, 0x21, 0xac, 0x4e, 0xf7, 0x4f, 0x2e, 0xe6, 0x0f, 0xb4, 0xc5, 0x4c, 0x62, + 0xf9, 0xfa, 0xf5, 0x04, 0xa4, 0x2d, 0xec, 0xbf, 0x95, 0x87, 0xbc, 0x10, 0xd3, 0xae, 0x95, 0xe8, + 0x74, 0xb9, 0x3b, 0x37, 0xe3, 0x9b, 0x41, 0x3b, 0x00, 0xed, 0xdf, 0x64, 0x6c, 0x2a, 0x21, 0x04, + 0xf7, 0xed, 0x28, 0xd9, 0xe7, 0xfd, 0x73, 0x69, 0x6d, 0xa2, 0x64, 0x93, 0xf7, 0xcf, 0x51, 0xe1, + 0xb1, 0x43, 0xca, 0x4b, 0x8b, 0x71, 0x3e, 0xb0, 0x43, 0xcc, 0x29, 0x93, 0x30, 0xdf, 0x7c, 0x94, + 0x84, 0xb9, 0x1a, 0x30, 0xef, 0xb8, 0xc7, 0xde, 0xc4, 0x1d, 0xe0, 0xda, 0x2b, 0x9a, 0xea, 0x13, + 0x5d, 0x41, 0xc8, 0x26, 0xc4, 0x2e, 0x41, 0x4b, 0xad, 0x28, 0x00, 0x3d, 0xb1, 0x4f, 0xbc, 0x0f, + 0xa5, 0xe0, 0xca, 0xed, 0xeb, 0x0b, 0x6c, 0x59, 0x8e, 0x8f, 0xe8, 0xfd, 0x46, 0xf7, 0xca, 0xed, + 0xe3, 0x72, 0x2a, 0x06, 0xf2, 0x17, 0x7b, 0x0a, 0xc5, 0xc8, 0x28, 0x4b, 0xec, 0xf1, 0xa6, 0x9e, + 0x43, 0x59, 0x62, 0x49, 0xf7, 0x8d, 0x50, 0xd9, 0x23, 0x98, 0x43, 0xcb, 0x69, 0xd0, 0xa8, 0x60, + 0x26, 0x25, 0x8c, 0x8b, 0x66, 0xa0, 0x17, 0x86, 0x0f, 0xd0, 0x8a, 0x6a, 0x4a, 0xb4, 0xf5, 0xe7, + 0x50, 0x4d, 0x94, 0xa5, 0x6b, 0xb8, 0x55, 0xd2, 0x70, 0xdf, 0xd6, 0x35, 0xdc, 0x98, 0x4d, 0xcb, + 0x6c, 0xba, 0xc6, 0xfb, 0x8b, 0x50, 0x54, 0x5d, 0x11, 0x8b, 0xe8, 0xa8, 0xf3, 0xbc, 0x73, 0xf0, + 0x59, 0xc7, 0xea, 0x7e, 0xde, 0xd9, 0xaa, 0xdf, 0x60, 0x0b, 0x50, 0x6e, 0x6e, 0xe1, 0xba, 0x44, + 0x40, 0x46, 0xa0, 0x1c, 0x36, 0xbb, 0xdd, 0x08, 0x92, 0x35, 0x76, 0xa0, 0x3e, 0xdd, 0x52, 0x41, + 0x93, 0xa1, 0x82, 0x49, 0xbb, 0x72, 0x0c, 0x10, 0xfa, 0x0b, 0x99, 0x8a, 0x49, 0x48, 0xa6, 0x0f, + 0xe3, 0x29, 0xd4, 0xc5, 0xa6, 0x23, 0x86, 0x2a, 0xd0, 0xec, 0xb3, 0x43, 0x21, 0x78, 0xe9, 0xb6, + 0xe5, 0xa2, 0x59, 0x26, 0x18, 0x56, 0x65, 0x7c, 0x00, 0x8b, 0x5a, 0xb6, 0x58, 0xdf, 0x14, 0x1b, + 0xd9, 0xb4, 0xbe, 0x89, 0xda, 0x05, 0xa5, 0x18, 0x6b, 0xb0, 0x22, 0x3e, 0x5b, 0xe7, 0xdc, 0x0d, + 0xbb, 0x93, 0x63, 0x72, 0x08, 0x3a, 0x9e, 0x2b, 0xb4, 0x8e, 0x52, 0x94, 0x72, 0x3d, 0x91, 0x6f, + 0x48, 0xd5, 0x34, 0x8b, 0xa4, 0xb1, 0xae, 0xd5, 0x80, 0x19, 0x37, 0xf0, 0x6f, 0x42, 0x45, 0x2d, + 0x45, 0x20, 0x31, 0xac, 0x87, 0xad, 0x96, 0x69, 0x1d, 0x74, 0xf6, 0xda, 0x1d, 0xc1, 0xed, 0xc4, + 0xb0, 0x22, 0x60, 0x67, 0x07, 0x21, 0x19, 0xa3, 0x0e, 0xb5, 0x67, 0x3c, 0x6c, 0xbb, 0x27, 0x9e, + 0x72, 0x7e, 0xfd, 0x45, 0x01, 0x16, 0x22, 0x50, 0xac, 0xe2, 0x9e, 0x73, 0x3f, 0x70, 0x3c, 0x17, + 0xa5, 0xd5, 0x92, 0xa9, 0x3e, 0xc5, 0xd6, 0xe3, 0x0c, 0xb8, 0x1b, 0x3a, 0xe1, 0x95, 0x95, 0xb0, + 0x87, 0xd5, 0x14, 0x58, 0x6e, 0x71, 0xcb, 0x50, 0xb0, 0x87, 0x8e, 0xad, 0xfc, 0xa8, 0xf4, 0x21, + 0xa0, 0x7d, 0x6f, 0xe8, 0xf9, 0x28, 0x98, 0x96, 0x4c, 0xfa, 0x60, 0x8f, 0x61, 0x59, 0x08, 0xc8, + 0xba, 0x91, 0x12, 0xf9, 0x07, 0x99, 0xe6, 0x98, 0x3b, 0x19, 0x1d, 0xc6, 0x86, 0x4a, 0x91, 0x22, + 0x36, 0x36, 0x91, 0x43, 0x4a, 0x32, 0x51, 0x06, 0xd2, 0xb5, 0x16, 0xdd, 0xc9, 0xa8, 0x89, 0x29, + 0x11, 0xfe, 0x13, 0x58, 0x11, 0xf8, 0x91, 0xec, 0x13, 0xe5, 0x58, 0xc0, 0x1c, 0xa2, 0xb0, 0xb6, + 0x4c, 0x8b, 0xf2, 0xdc, 0x82, 0x12, 0xb5, 0x4a, 0xcc, 0x78, 0x81, 0x64, 0x6c, 0x6c, 0x0a, 0xf7, + 0x83, 0x19, 0x97, 0xe7, 0x1c, 0xed, 0xd2, 0x53, 0x2e, 0x4f, 0xcd, 0x69, 0x5a, 0x9c, 0x76, 0x9a, + 0x3e, 0x81, 0x95, 0x63, 0x41, 0x82, 0x67, 0xdc, 0x1e, 0x70, 0xdf, 0x8a, 0x09, 0x9b, 0x74, 0x89, + 0x25, 0x91, 0xb8, 0x8b, 0x69, 0xd1, 0x3a, 0x10, 0x42, 0x88, 0x60, 0x0b, 0x7c, 0x60, 0x85, 0x9e, + 0x85, 0xb2, 0x09, 0x32, 0x98, 0xa2, 0x59, 0x25, 0x70, 0xcf, 0xdb, 0x12, 0xc0, 0x24, 0xde, 0xa9, + 0x6f, 0x8f, 0xcf, 0xa4, 0xb4, 0x1f, 0xe1, 0x3d, 0x13, 0x40, 0x76, 0x1b, 0xe6, 0x05, 0xc9, 0xbb, + 0x9c, 0x3c, 0x53, 0x24, 0x4f, 0x2b, 0x10, 0x7b, 0x1b, 0xe6, 0xb0, 0x8e, 0xa0, 0x51, 0x47, 0x7a, + 0xaf, 0xc4, 0x8c, 0xdc, 0x71, 0x4d, 0x99, 0x26, 0x24, 0xbd, 0x89, 0xef, 0x10, 0x97, 0x29, 0x99, + 0xf8, 0x9b, 0x7d, 0x4f, 0x63, 0x59, 0x4b, 0x98, 0xf7, 0x6d, 0x99, 0x77, 0x8a, 0xd2, 0xae, 0xe3, + 0x5e, 0x3f, 0x53, 0x66, 0xf4, 0xfd, 0x7c, 0xb1, 0x5c, 0xaf, 0x18, 0x1f, 0x42, 0x81, 0x46, 0x47, + 0x10, 0x21, 0x8e, 0x5d, 0x46, 0x12, 0x21, 0x42, 0x1b, 0x30, 0xef, 0xf2, 0xf0, 0xc2, 0xf3, 0x5f, + 0x28, 0x8b, 0xb1, 0xfc, 0x34, 0x7e, 0x84, 0xa6, 0x8e, 0xc8, 0x1d, 0x4e, 0x5a, 0x9b, 0x20, 0x0f, + 0x9a, 0xde, 0xe0, 0xcc, 0x96, 0xd6, 0x97, 0x22, 0x02, 0xba, 0x67, 0xf6, 0x0c, 0x79, 0x64, 0x67, + 0x3d, 0xe2, 0x6f, 0x43, 0x4d, 0x39, 0xe0, 0x03, 0x6b, 0xc8, 0x4f, 0x42, 0x49, 0xee, 0x15, 0xe9, + 0x7d, 0x0f, 0xf6, 0xf8, 0x49, 0x68, 0xec, 0xc3, 0xa2, 0x24, 0xc8, 0x83, 0x31, 0x57, 0x55, 0x7f, + 0x3b, 0x4d, 0xd8, 0x2d, 0x3f, 0x59, 0x4a, 0x6e, 0xb4, 0x14, 0x58, 0x90, 0x90, 0x80, 0x8d, 0x4f, + 0x80, 0xe9, 0xdb, 0xb0, 0x2c, 0x4f, 0x8a, 0x9c, 0xca, 0xd0, 0xae, 0xfc, 0x55, 0x91, 0x60, 0xeb, + 0x0c, 0xc4, 0xe8, 0x04, 0x93, 0x7e, 0x5f, 0x05, 0x46, 0x14, 0x4d, 0xf5, 0x69, 0xfc, 0x49, 0x06, + 0x96, 0xb0, 0x30, 0x25, 0xac, 0x4b, 0x26, 0xfb, 0x13, 0x37, 0x52, 0xcc, 0x8f, 0x2e, 0xfb, 0xd0, + 0xc7, 0x57, 0x37, 0x6d, 0xe6, 0x67, 0x4c, 0x9b, 0x5f, 0x87, 0xfa, 0x80, 0x0f, 0x1d, 0x8c, 0x91, + 0x51, 0xa2, 0x04, 0x89, 0xe7, 0x0b, 0x0a, 0x2e, 0x55, 0x35, 0xe3, 0xef, 0x65, 0x60, 0x91, 0x24, + 0x15, 0x54, 0x7a, 0xe5, 0x40, 0x7d, 0xac, 0xb4, 0x3c, 0xc9, 0xaa, 0x64, 0x9f, 0xe2, 0x1d, 0x1c, + 0xa1, 0x84, 0xbc, 0x7b, 0x43, 0x6a, 0x7f, 0x12, 0xca, 0x3e, 0x42, 0x05, 0xc3, 0xb5, 0x10, 0x98, + 0x12, 0x73, 0x93, 0x9c, 0x94, 0xdd, 0x1b, 0xa8, 0x7d, 0xb8, 0x08, 0xda, 0x2c, 0x0a, 0xb5, 0x53, + 0x80, 0x8d, 0x1d, 0xa8, 0x26, 0xaa, 0x49, 0xd8, 0x5f, 0x2b, 0x64, 0x7f, 0x9d, 0xf1, 0x71, 0x64, + 0x67, 0x7d, 0x1c, 0x57, 0xb0, 0x64, 0x72, 0x7b, 0x70, 0xb5, 0xe3, 0xf9, 0x87, 0xc1, 0x71, 0xb8, + 0x43, 0xe2, 0x9f, 0xe0, 0xef, 0x91, 0xe3, 0x2e, 0x61, 0xe4, 0x54, 0xfe, 0x1b, 0xa5, 0xcb, 0x7e, + 0x0d, 0x6a, 0xb1, 0x87, 0x4f, 0x33, 0x94, 0x55, 0x23, 0x27, 0x1f, 0xda, 0xcb, 0x84, 0x1e, 0x18, + 0x1c, 0x87, 0xd2, 0x54, 0x86, 0xbf, 0x8d, 0xbf, 0x96, 0x07, 0x26, 0xa8, 0x79, 0x8a, 0x60, 0xa6, + 0x7c, 0x93, 0xd9, 0x19, 0xdf, 0xe4, 0x63, 0x60, 0x1a, 0x82, 0x72, 0x99, 0xe6, 0x22, 0x97, 0x69, + 0x3d, 0xc6, 0x95, 0x1e, 0xd3, 0xc7, 0xb0, 0x2c, 0x65, 0xe9, 0x64, 0x53, 0x89, 0x34, 0x18, 0x09, + 0xd5, 0x89, 0xf6, 0x2a, 0xbf, 0xa4, 0xd0, 0xcd, 0xc9, 0x14, 0x86, 0x7e, 0x49, 0xa5, 0x95, 0x6b, + 0x04, 0x38, 0xf7, 0x4a, 0x02, 0x9c, 0x9f, 0x21, 0x40, 0xcd, 0x32, 0x53, 0x4c, 0x5a, 0x66, 0x0c, + 0xa8, 0x2a, 0xef, 0x23, 0x05, 0x5d, 0x90, 0xe0, 0x58, 0x96, 0x2e, 0x48, 0x0c, 0xbc, 0x78, 0x00, + 0x75, 0x65, 0x3e, 0x89, 0x6c, 0x3f, 0x14, 0x50, 0x20, 0xad, 0x6f, 0x5b, 0xca, 0x02, 0x94, 0xb0, + 0xb4, 0x97, 0xa7, 0x2c, 0xed, 0xef, 0xc2, 0x62, 0x20, 0xe8, 0xd7, 0x9a, 0xb8, 0x32, 0xfa, 0x87, + 0x0f, 0x50, 0xcd, 0x2a, 0x9a, 0x75, 0x4c, 0x38, 0x8a, 0xe1, 0xb3, 0x76, 0x8d, 0x6a, 0x8a, 0x5d, + 0xe3, 0x69, 0xec, 0xa8, 0x0b, 0xce, 0x9c, 0x11, 0xca, 0x0c, 0x71, 0xa4, 0x8c, 0x1c, 0xe0, 0xee, + 0x99, 0x33, 0x32, 0x95, 0x57, 0x58, 0x7c, 0x18, 0xff, 0x3b, 0x03, 0x75, 0x41, 0x07, 0x89, 0x25, + 0xf6, 0x1d, 0x40, 0x66, 0xf0, 0x9a, 0x2b, 0xac, 0x2c, 0x70, 0xd5, 0x02, 0xfb, 0x10, 0x70, 0xc5, + 0x58, 0x42, 0xa7, 0x94, 0xeb, 0xab, 0x91, 0x5c, 0x5f, 0x31, 0x0f, 0xdd, 0xbd, 0x41, 0xba, 0x87, + 0x80, 0xb0, 0xef, 0x40, 0x49, 0x10, 0x26, 0x52, 0x89, 0x0c, 0xd0, 0x52, 0x92, 0x57, 0xca, 0x1a, + 0x11, 0x59, 0xc7, 0xf2, 0x33, 0xcd, 0xb7, 0x9a, 0x4f, 0xf1, 0xad, 0x6a, 0x0b, 0x78, 0x17, 0xe0, + 0x39, 0xbf, 0xda, 0xf3, 0xfa, 0xa8, 0xf1, 0xde, 0x01, 0x10, 0xb4, 0x7c, 0x62, 0x8f, 0x1c, 0x69, + 0xb0, 0x29, 0x98, 0xa5, 0x17, 0xfc, 0x6a, 0x07, 0x01, 0x62, 0x22, 0x45, 0x72, 0xbc, 0x8a, 0x0b, + 0x66, 0xf1, 0x05, 0xbf, 0xa2, 0x25, 0x6c, 0x41, 0xf5, 0x39, 0xbf, 0xda, 0xe6, 0x24, 0x64, 0x7a, + 0xbe, 0x20, 0x22, 0xdf, 0xbe, 0x10, 0x52, 0x65, 0xc2, 0x2f, 0x5a, 0xf6, 0xed, 0x8b, 0xe7, 0xfc, + 0x4a, 0xf9, 0x68, 0xe7, 0x45, 0xfa, 0xd0, 0xeb, 0xcb, 0x7d, 0x53, 0x45, 0x78, 0xc4, 0x8d, 0x32, + 0xe7, 0x5e, 0xe0, 0x6f, 0xe3, 0x2f, 0x33, 0x50, 0x15, 0xed, 0x47, 0xb6, 0x2c, 0xa6, 0x4c, 0x05, + 0x0a, 0x65, 0xe2, 0x40, 0xa1, 0x27, 0x92, 0xab, 0x11, 0x8f, 0xcf, 0x5e, 0xcf, 0xe3, 0x71, 0x6e, + 0x88, 0xc1, 0xbf, 0x0f, 0x25, 0x5a, 0x96, 0x62, 0x9d, 0xe7, 0x12, 0x13, 0x9c, 0xe8, 0x90, 0x59, + 0x44, 0xb4, 0xe7, 0x14, 0x97, 0xa0, 0x19, 0xff, 0x68, 0x88, 0x4b, 0x7e, 0x64, 0xf2, 0x4b, 0x99, + 0x86, 0xc2, 0x35, 0x71, 0x09, 0xba, 0x65, 0x6d, 0x6e, 0xc6, 0xb2, 0x76, 0x00, 0x45, 0x31, 0xd5, + 0xd8, 0xd9, 0x94, 0x42, 0x33, 0x69, 0x85, 0x0a, 0x49, 0xc0, 0x16, 0x9b, 0x82, 0x60, 0x74, 0x59, + 0x29, 0x09, 0xd8, 0x01, 0x3f, 0x44, 0x66, 0x97, 0x81, 0xb2, 0xb6, 0x02, 0xd0, 0x38, 0x19, 0x8d, + 0x17, 0x2d, 0x97, 0x24, 0x89, 0x27, 0x06, 0x7c, 0xf7, 0x86, 0x59, 0xed, 0x27, 0x66, 0x60, 0x43, + 0xd2, 0x2a, 0xe6, 0xcc, 0x26, 0x62, 0x9a, 0x54, 0xc3, 0x15, 0x81, 0x8a, 0xdf, 0x9b, 0x73, 0x90, + 0x17, 0xa8, 0xc6, 0xc7, 0xb0, 0xa8, 0x35, 0x83, 0xd4, 0xfc, 0xd7, 0xed, 0xa1, 0xf1, 0x2b, 0x51, + 0x66, 0x51, 0x07, 0xb9, 0x8f, 0x54, 0x8c, 0x07, 0x1f, 0x50, 0xc7, 0x65, 0x2c, 0x09, 0x81, 0x04, + 0xda, 0x6b, 0xc7, 0x1d, 0xfc, 0x1a, 0x2c, 0x69, 0xa5, 0xef, 0x38, 0xae, 0x3d, 0x74, 0x7e, 0x84, + 0x1b, 0x7e, 0xe0, 0x9c, 0xba, 0x53, 0xe5, 0x13, 0xe8, 0x2b, 0x95, 0xff, 0xf7, 0xb3, 0xb0, 0x2c, + 0x2b, 0xc0, 0xa8, 0x3d, 0x47, 0x48, 0x71, 0xfb, 0xc1, 0x29, 0xfb, 0x0e, 0x54, 0xc5, 0xd8, 0x58, + 0x3e, 0x3f, 0x75, 0x82, 0x90, 0x2b, 0xb7, 0x55, 0x0a, 0xe3, 0x12, 0x9b, 0xb9, 0x40, 0x35, 0x25, + 0x26, 0xfb, 0x18, 0xca, 0x98, 0x95, 0xcc, 0x28, 0x72, 0x22, 0x1a, 0xb3, 0x19, 0x69, 0xa0, 0x77, + 0x6f, 0x98, 0x10, 0xc4, 0xc3, 0xfe, 0x31, 0x94, 0x71, 0x0e, 0xcf, 0x71, 0x20, 0xa7, 0x58, 0xd5, + 0xcc, 0x40, 0x8b, 0xcc, 0xe3, 0x78, 0xd8, 0x9b, 0x50, 0x25, 0x66, 0x25, 0xc7, 0x49, 0x46, 0x03, + 0xad, 0xcf, 0x66, 0x57, 0x23, 0x29, 0x1a, 0x3f, 0xd6, 0xbe, 0x37, 0x4b, 0x30, 0x1f, 0xfa, 0xce, + 0xe9, 0x29, 0xf7, 0x8d, 0xd5, 0x68, 0x68, 0x04, 0x17, 0xe6, 0xdd, 0x90, 0x8f, 0x85, 0x6c, 0x6e, + 0xfc, 0xdb, 0x0c, 0x94, 0x25, 0x5f, 0xfd, 0x89, 0x7d, 0x65, 0xeb, 0x5a, 0xd8, 0x2b, 0x59, 0x6c, + 0xe2, 0x28, 0xd7, 0xfb, 0xb0, 0x30, 0x12, 0x72, 0xba, 0xd0, 0x23, 0x13, 0x8e, 0xb2, 0x9a, 0x02, + 0x4b, 0x31, 0x79, 0x03, 0x96, 0x50, 0x6a, 0x0e, 0xac, 0xd0, 0x19, 0x5a, 0x2a, 0x51, 0x86, 0x98, + 0x2e, 0x52, 0x52, 0xcf, 0x19, 0xee, 0xcb, 0x04, 0x21, 0x3c, 0x06, 0xa1, 0x7d, 0xca, 0xe5, 0xda, + 0xa6, 0x0f, 0xa3, 0x01, 0xab, 0x53, 0x2a, 0xa4, 0x52, 0x7f, 0xff, 0xcf, 0x22, 0xac, 0xcd, 0x24, + 0x49, 0x35, 0x38, 0x72, 0x10, 0x0d, 0x9d, 0xd1, 0xb1, 0x17, 0x99, 0x4f, 0x33, 0x9a, 0x83, 0x68, + 0x4f, 0xa4, 0x28, 0xf3, 0x29, 0x87, 0x15, 0x45, 0x90, 0x68, 0xff, 0x8c, 0xb4, 0xcc, 0x2c, 0xea, + 0x40, 0xef, 0x27, 0x37, 0xb1, 0xe9, 0xea, 0x14, 0x5c, 0x17, 0x8d, 0x96, 0xc6, 0x33, 0xb0, 0x80, + 0xfd, 0x3a, 0x34, 0x22, 0xba, 0x97, 0x62, 0xbb, 0xa6, 0x32, 0x8b, 0x9a, 0xde, 0x7b, 0x45, 0x4d, + 0x09, 0xdb, 0x1d, 0xca, 0x4e, 0xab, 0x6a, 0xc9, 0x50, 0x81, 0x51, 0x5d, 0xe7, 0xf0, 0x86, 0xaa, + 0x0b, 0xc5, 0xf0, 0xd9, 0x1a, 0xf3, 0xaf, 0xd5, 0x37, 0xb4, 0x4b, 0x26, 0xaa, 0x35, 0x6f, 0xc9, + 0x82, 0xa3, 0x24, 0xbd, 0xde, 0x33, 0x58, 0xbd, 0xb0, 0x9d, 0x50, 0xf5, 0x51, 0xd3, 0xd8, 0x0b, + 0x58, 0xdf, 0x93, 0x57, 0xd4, 0xf7, 0x19, 0x65, 0x4e, 0x28, 0x26, 0xcb, 0x17, 0xb3, 0xc0, 0x60, + 0xfd, 0x1f, 0xe7, 0xa0, 0x96, 0x2c, 0x45, 0x30, 0x16, 0xb9, 0xd9, 0x28, 0x79, 0x53, 0x0a, 0xc1, + 0xd2, 0xb4, 0xdf, 0x21, 0x39, 0x73, 0xd6, 0xe9, 0x90, 0x4d, 0x71, 0x3a, 0xe8, 0xb6, 0xfe, 0xdc, + 0xab, 0x9c, 0xab, 0xf9, 0xd7, 0x72, 0xae, 0x16, 0xd2, 0x9c, 0xab, 0xd7, 0x7b, 0xe4, 0xe6, 0x7e, + 0x22, 0x8f, 0xdc, 0xfc, 0x4b, 0x3d, 0x72, 0x9a, 0x1f, 0xb1, 0x78, 0x8d, 0x85, 0x5e, 0xf3, 0x2c, + 0xa6, 0x78, 0xe4, 0x4a, 0x5f, 0xc1, 0x23, 0xb7, 0xfe, 0x97, 0x19, 0x60, 0xb3, 0xab, 0x83, 0x3d, + 0x23, 0x7f, 0x8e, 0xcb, 0x87, 0x92, 0x73, 0x7f, 0xe3, 0xf5, 0x56, 0x98, 0x22, 0x08, 0x95, 0x9b, + 0x3d, 0x82, 0x25, 0x3d, 0x10, 0x5e, 0xd7, 0xda, 0xab, 0x26, 0xd3, 0x93, 0x62, 0xdb, 0x8e, 0xe6, + 0xc9, 0xce, 0xbf, 0xd2, 0x93, 0x5d, 0x78, 0xa5, 0x27, 0x7b, 0x2e, 0xe9, 0xc9, 0x5e, 0xff, 0x8f, + 0x19, 0x58, 0x4a, 0x21, 0xe2, 0x9f, 0x5d, 0x9f, 0x05, 0xed, 0x25, 0xd8, 0x5a, 0x56, 0xd2, 0x9e, + 0xce, 0xd1, 0xf6, 0xa0, 0x1c, 0x4f, 0x85, 0x3a, 0x28, 0xf2, 0xf0, 0x55, 0xdc, 0x25, 0xce, 0x61, + 0xea, 0xd9, 0xd7, 0x7f, 0x2f, 0x0b, 0x65, 0x2d, 0x51, 0x8c, 0x22, 0x91, 0xac, 0x16, 0x40, 0x44, + 0x92, 0x21, 0xda, 0x1c, 0xee, 0x82, 0x74, 0x6a, 0x50, 0x3a, 0x2d, 0x2e, 0x29, 0x06, 0x22, 0xc2, + 0x06, 0x2c, 0x29, 0x5f, 0x1b, 0x8f, 0xe3, 0x04, 0xe5, 0x5e, 0xb3, 0x28, 0x3d, 0x6e, 0x3c, 0x0a, + 0x3b, 0x64, 0x8f, 0x94, 0x3a, 0x18, 0xcf, 0x1d, 0x92, 0x3a, 0x79, 0x0c, 0x16, 0x69, 0x81, 0xa8, + 0x49, 0x14, 0x74, 0xfe, 0x3e, 0xac, 0xa8, 0xe5, 0x91, 0xcc, 0x41, 0x4e, 0x04, 0x26, 0x17, 0x87, + 0x9e, 0xe5, 0x7b, 0x70, 0x67, 0xaa, 0x4d, 0x53, 0x59, 0x29, 0xa0, 0xf5, 0x66, 0xa2, 0x75, 0x7a, + 0x09, 0xeb, 0x3f, 0x86, 0x6a, 0x82, 0x51, 0xfe, 0xec, 0xa6, 0x7c, 0xda, 0xce, 0x43, 0x23, 0xaa, + 0xdb, 0x79, 0xd6, 0xff, 0x57, 0x0e, 0xd8, 0x2c, 0xaf, 0xfe, 0x79, 0x36, 0x61, 0x96, 0x30, 0x73, + 0x29, 0x84, 0xf9, 0xff, 0x4c, 0x7e, 0x78, 0x17, 0x16, 0xe5, 0x81, 0x29, 0xcd, 0x61, 0x4a, 0x8b, + 0xb3, 0x1e, 0x25, 0xa8, 0x56, 0x7c, 0x38, 0x1d, 0xb8, 0x51, 0x4c, 0x9c, 0x11, 0xd1, 0x04, 0xa8, + 0xa9, 0xf8, 0x8d, 0x23, 0x98, 0xb3, 0xdd, 0xfe, 0x99, 0xe7, 0x4b, 0x3e, 0xf8, 0x0b, 0x5f, 0x79, + 0xfb, 0xdc, 0x68, 0x62, 0x7e, 0x94, 0xda, 0x4c, 0x59, 0x98, 0xf1, 0x3e, 0x94, 0x35, 0x30, 0x2b, + 0x41, 0x61, 0xaf, 0xbd, 0xbf, 0x79, 0x50, 0xbf, 0xc1, 0xaa, 0x50, 0x32, 0x5b, 0x5b, 0x07, 0x9f, + 0xb6, 0xcc, 0xd6, 0x76, 0x3d, 0xc3, 0x8a, 0x90, 0xdf, 0x3b, 0xe8, 0xf6, 0xea, 0x59, 0x63, 0x1d, + 0x1a, 0xb2, 0xc4, 0x59, 0x9f, 0xc5, 0x6f, 0xe5, 0x23, 0x73, 0x21, 0x26, 0x4a, 0x15, 0xfd, 0x9b, + 0x50, 0xd1, 0xc5, 0x1b, 0x49, 0x11, 0x53, 0x3e, 0x7b, 0xa1, 0x9c, 0x7b, 0x1a, 0xaf, 0xde, 0x02, + 0xf2, 0xd8, 0x0e, 0xa2, 0x6c, 0xd9, 0x84, 0xdc, 0x9a, 0xe2, 0x1d, 0x44, 0xe5, 0x27, 0x41, 0x86, + 0xff, 0x1f, 0xd4, 0x92, 0x06, 0x7c, 0xc9, 0x91, 0xd2, 0x14, 0x4e, 0x91, 0x3b, 0x61, 0xd1, 0x67, + 0xdf, 0x83, 0xfa, 0xb4, 0x03, 0x40, 0x0a, 0xcf, 0xd7, 0xe4, 0x5f, 0x70, 0x92, 0x3e, 0x01, 0xb6, + 0x0b, 0xcb, 0x69, 0x02, 0x1e, 0xd2, 0xc7, 0xf5, 0x46, 0x0a, 0x36, 0x2b, 0xc4, 0xb1, 0x6f, 0x4b, + 0x3f, 0x4f, 0x01, 0xa7, 0xff, 0xed, 0x64, 0xfd, 0xda, 0x60, 0x6f, 0xd0, 0x3f, 0xcd, 0xe3, 0x73, + 0x0e, 0x10, 0xc3, 0x58, 0x1d, 0x2a, 0x07, 0x87, 0xad, 0x8e, 0xb5, 0xb5, 0xdb, 0xec, 0x74, 0x5a, + 0x7b, 0xf5, 0x1b, 0x8c, 0x41, 0x0d, 0x7d, 0xd5, 0xdb, 0x11, 0x2c, 0x23, 0x60, 0xd2, 0xdf, 0xa6, + 0x60, 0x59, 0xb6, 0x0c, 0xf5, 0x76, 0x67, 0x0a, 0x9a, 0x63, 0x0d, 0x58, 0x3e, 0x6c, 0x91, 0x7b, + 0x3b, 0x51, 0x6e, 0x5e, 0x28, 0x0d, 0xb2, 0xbb, 0x42, 0x69, 0xa0, 0x83, 0x7f, 0x72, 0x1d, 0x28, + 0x59, 0xfa, 0xb7, 0x33, 0xb0, 0x32, 0x95, 0x10, 0x1f, 0xe7, 0x20, 0x49, 0x3a, 0x29, 0x43, 0x57, + 0x10, 0xa8, 0x56, 0xd3, 0xbb, 0xb0, 0x18, 0x19, 0x9e, 0xa6, 0x76, 0xa5, 0x7a, 0x94, 0xa0, 0x90, + 0x1f, 0xc1, 0x92, 0x66, 0xbf, 0x9a, 0xe2, 0x15, 0x4c, 0x4b, 0x92, 0x19, 0x8c, 0xb5, 0x28, 0x6c, + 0x7e, 0xaa, 0xd5, 0x03, 0x3a, 0x4d, 0xa8, 0x27, 0xc4, 0x6e, 0xb0, 0x64, 0x7b, 0xd5, 0x27, 0x7b, + 0x3c, 0x45, 0x08, 0xc9, 0xd6, 0xea, 0x13, 0xae, 0xaa, 0xff, 0xfd, 0x39, 0x60, 0x9f, 0x4c, 0xb8, + 0x7f, 0x85, 0xc7, 0x35, 0x82, 0x57, 0xc5, 0x2f, 0x2a, 0x4b, 0x4b, 0xf6, 0xb5, 0x8e, 0x64, 0xa5, + 0x1d, 0x89, 0xca, 0xbf, 0xfa, 0x48, 0x54, 0xe1, 0x55, 0x47, 0xa2, 0xde, 0x82, 0xaa, 0x73, 0xea, + 0x7a, 0x82, 0x15, 0x0a, 0x49, 0x38, 0x68, 0xcc, 0xdd, 0xcb, 0x3d, 0xa8, 0x98, 0x15, 0x09, 0x14, + 0x72, 0x70, 0xc0, 0x3e, 0x8e, 0x91, 0xf8, 0xe0, 0x14, 0x8f, 0xef, 0xe9, 0x4c, 0xb0, 0x35, 0x38, + 0xe5, 0xd2, 0xb0, 0x84, 0x9a, 0x86, 0xca, 0x2c, 0xe0, 0x01, 0x7b, 0x1b, 0x6a, 0x81, 0x37, 0x11, + 0x8a, 0x85, 0x1a, 0x06, 0x72, 0x94, 0x55, 0x08, 0x7a, 0xa8, 0xbc, 0xa2, 0x4b, 0x93, 0x80, 0x5b, + 0x23, 0x27, 0x08, 0x84, 0x78, 0xd6, 0xf7, 0xdc, 0xd0, 0xf7, 0x86, 0xd2, 0xf7, 0xb5, 0x38, 0x09, + 0xf8, 0x3e, 0xa5, 0x6c, 0x51, 0x02, 0xfb, 0x56, 0xdc, 0xa4, 0xb1, 0xed, 0xf8, 0x41, 0x03, 0xb0, + 0x49, 0xaa, 0xa7, 0x28, 0xbf, 0xdb, 0x8e, 0x1f, 0xb5, 0x45, 0x7c, 0x04, 0x53, 0x47, 0xb5, 0xca, + 0xd3, 0x47, 0xb5, 0x7e, 0x98, 0x7e, 0x54, 0xab, 0x8a, 0x45, 0x3f, 0x96, 0x45, 0xcf, 0x4e, 0xf1, + 0x57, 0x3a, 0xb1, 0x35, 0x7b, 0x02, 0xad, 0xf6, 0x55, 0x4e, 0xa0, 0x2d, 0xa4, 0x9d, 0x40, 0x7b, + 0x1f, 0xca, 0x78, 0x36, 0xc8, 0x3a, 0x73, 0x84, 0x0c, 0x47, 0xbe, 0xbc, 0xba, 0x7e, 0x78, 0x68, + 0xd7, 0x71, 0x43, 0x13, 0x7c, 0xf5, 0x33, 0x98, 0x3d, 0x0c, 0xb6, 0xf8, 0x73, 0x3c, 0x0c, 0x26, + 0xcf, 0x30, 0x6d, 0x40, 0x51, 0xcd, 0x13, 0x63, 0x90, 0x3f, 0xf1, 0xbd, 0x91, 0xf2, 0x71, 0x88, + 0xdf, 0xac, 0x06, 0xd9, 0xd0, 0x93, 0x99, 0xb3, 0xa1, 0x67, 0xfc, 0x2a, 0x94, 0x35, 0x52, 0x63, + 0x6f, 0x92, 0x5d, 0x52, 0xe8, 0x66, 0x52, 0xb6, 0xa4, 0x51, 0x2c, 0x49, 0x68, 0x7b, 0x20, 0xf8, + 0xcd, 0xc0, 0xf1, 0x39, 0x1e, 0xdb, 0xb4, 0x7c, 0x7e, 0xce, 0xfd, 0x40, 0xf9, 0x9c, 0xea, 0x51, + 0x82, 0x49, 0x70, 0xe3, 0xd7, 0x60, 0x29, 0x31, 0xb7, 0x92, 0x45, 0xbc, 0x0d, 0x73, 0x38, 0x6e, + 0x2a, 0x26, 0x20, 0x79, 0x28, 0x4b, 0xa6, 0xe1, 0x79, 0x7c, 0x72, 0x97, 0x59, 0x63, 0xdf, 0x3b, + 0xc6, 0x4a, 0x32, 0x66, 0x59, 0xc2, 0x0e, 0x7d, 0xef, 0xd8, 0xf8, 0xb3, 0x1c, 0xe4, 0x76, 0xbd, + 0xb1, 0x1e, 0xa3, 0x96, 0x99, 0x89, 0x51, 0x93, 0x0a, 0xa7, 0x15, 0x29, 0x94, 0x52, 0x66, 0x47, + 0x47, 0x91, 0x52, 0x2a, 0x1f, 0x40, 0x4d, 0xf0, 0x89, 0xd0, 0x13, 0x1a, 0xfb, 0x85, 0xed, 0x93, + 0x40, 0x9c, 0xa3, 0xc5, 0x67, 0x8f, 0xc2, 0x9e, 0xb7, 0x43, 0x70, 0xb6, 0x0c, 0xb9, 0x48, 0x7d, + 0xc1, 0x64, 0xf1, 0xc9, 0x56, 0x61, 0x0e, 0x83, 0x95, 0xaf, 0xa4, 0xd3, 0x5b, 0x7e, 0xb1, 0x6f, + 0xc0, 0x52, 0xb2, 0x5c, 0x62, 0x45, 0x52, 0x36, 0xd2, 0x0b, 0x46, 0x9e, 0x74, 0x13, 0x04, 0x1f, + 0x21, 0x1c, 0x19, 0x3b, 0x73, 0xc2, 0x39, 0x26, 0x69, 0x4c, 0xaf, 0x98, 0x60, 0x7a, 0x77, 0xa1, + 0x1c, 0x0e, 0xcf, 0xad, 0xb1, 0x7d, 0x35, 0xf4, 0xec, 0x81, 0x5c, 0xdf, 0x10, 0x0e, 0xcf, 0x0f, + 0x09, 0xc2, 0x1e, 0x01, 0x8c, 0xc6, 0x63, 0xb9, 0xf6, 0xd0, 0xf9, 0x11, 0x93, 0xf2, 0xfe, 0xe1, + 0x21, 0x91, 0x9c, 0x59, 0x1a, 0x8d, 0xc7, 0xf4, 0x93, 0x6d, 0x43, 0x2d, 0xf5, 0x68, 0xe5, 0x1d, + 0x15, 0x5b, 0xeb, 0x8d, 0x37, 0x52, 0x16, 0x67, 0xb5, 0xaf, 0xc3, 0xd6, 0xbf, 0x07, 0xec, 0xa7, + 0x3c, 0xe0, 0xd8, 0x83, 0x52, 0xd4, 0x3e, 0xfd, 0x7c, 0x20, 0x46, 0xcb, 0x97, 0x13, 0xe7, 0x03, + 0x9b, 0x83, 0x81, 0x2f, 0xf8, 0x22, 0x6d, 0x98, 0x11, 0xcb, 0x07, 0x6d, 0xc7, 0x6c, 0x12, 0xdf, + 0x37, 0xfe, 0x6b, 0x06, 0x0a, 0x74, 0x58, 0xf1, 0x1d, 0x58, 0x20, 0xfc, 0x28, 0xde, 0x4f, 0xba, + 0xca, 0x69, 0xdf, 0xed, 0xc9, 0x50, 0x3f, 0xb1, 0x2c, 0xb4, 0x83, 0xd6, 0xd9, 0x68, 0xe6, 0xb5, + 0xc3, 0xd6, 0x77, 0xa1, 0x14, 0x55, 0xad, 0x91, 0x4e, 0x51, 0xd5, 0xcc, 0xde, 0x80, 0xfc, 0x99, + 0x37, 0x56, 0x96, 0x1f, 0x88, 0x47, 0xd2, 0x44, 0x78, 0xdc, 0x16, 0x51, 0x07, 0x35, 0x5e, 0x5a, + 0x2c, 0xa2, 0x4a, 0x90, 0x0c, 0x66, 0xfb, 0x38, 0x97, 0xd2, 0xc7, 0x23, 0x58, 0x10, 0x7c, 0x40, + 0x0b, 0x59, 0xb9, 0x7e, 0xd3, 0xfc, 0xba, 0x90, 0xf0, 0xfa, 0xc3, 0xc9, 0x80, 0xeb, 0xb6, 0x37, + 0x8c, 0x6f, 0x93, 0x70, 0x25, 0x59, 0x1b, 0xbf, 0x9f, 0x21, 0xfe, 0x22, 0xca, 0x65, 0x0f, 0x20, + 0x2f, 0xf6, 0xb7, 0x29, 0x4b, 0x7c, 0x74, 0x6c, 0x41, 0xe0, 0x99, 0x88, 0x81, 0xb7, 0x13, 0x4c, + 0x46, 0xc9, 0xd2, 0xab, 0x66, 0xd9, 0x9d, 0x8c, 0x22, 0xd3, 0xd5, 0xd7, 0x54, 0xb7, 0xa6, 0xcc, + 0x3e, 0xd4, 0xfb, 0x68, 0x99, 0x6e, 0x68, 0x81, 0x72, 0xf9, 0xc4, 0x8e, 0xa9, 0xa4, 0xc0, 0xc1, + 0x29, 0xd7, 0x02, 0xe4, 0xfe, 0x28, 0x0b, 0xd5, 0x44, 0x8b, 0x30, 0x52, 0x50, 0x6c, 0x00, 0xe4, + 0x58, 0x92, 0xf3, 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9c, 0xb2, 0x89, 0x71, 0x8a, 0x82, 0x73, + 0x72, 0x7a, 0x70, 0xce, 0x63, 0x28, 0xc5, 0x07, 0xec, 0x93, 0x4d, 0x12, 0xf5, 0xa9, 0xc3, 0x1b, + 0x31, 0x52, 0x1c, 0xce, 0x53, 0xd0, 0xc3, 0x79, 0xbe, 0xab, 0x45, 0x7f, 0xcc, 0x61, 0x31, 0x46, + 0xda, 0x88, 0xfe, 0x5c, 0x62, 0x3f, 0x8c, 0x8f, 0xa1, 0xac, 0x35, 0x5e, 0x8f, 0xf2, 0xc8, 0x24, + 0xa2, 0x3c, 0xa2, 0x63, 0x56, 0xd9, 0xf8, 0x98, 0x95, 0xf1, 0xd7, 0xb3, 0x50, 0x15, 0xeb, 0xcb, + 0x71, 0x4f, 0x0f, 0xbd, 0xa1, 0xd3, 0x47, 0x47, 0x53, 0xb4, 0xc2, 0xa4, 0xa0, 0xa5, 0xd6, 0x99, + 0x5c, 0x62, 0x24, 0x67, 0xe9, 0xa7, 0x49, 0x89, 0x49, 0x47, 0xa7, 0x49, 0x0d, 0xa8, 0x0a, 0xc6, + 0x88, 0x2e, 0xa3, 0xf8, 0xf8, 0xbf, 0x59, 0x3e, 0xe1, 0x7c, 0xd3, 0x0e, 0x88, 0x43, 0x7e, 0x03, + 0x96, 0x04, 0x0e, 0x1e, 0xa4, 0x1b, 0x39, 0xc3, 0xa1, 0x43, 0x98, 0x64, 0x68, 0xaa, 0x9f, 0x70, + 0x6e, 0xda, 0x21, 0xdf, 0x17, 0x09, 0xf2, 0xb6, 0x80, 0xe2, 0xc0, 0x09, 0xec, 0xe3, 0x38, 0x9e, + 0x33, 0xfa, 0x46, 0xcf, 0xb2, 0x7d, 0xa9, 0x79, 0x96, 0xc9, 0x00, 0x51, 0x1e, 0xd9, 0x97, 0x91, + 0x67, 0x79, 0x8a, 0x92, 0xe6, 0xa7, 0x29, 0xc9, 0xf8, 0x37, 0x59, 0x28, 0x6b, 0x64, 0xf9, 0x3a, + 0xbb, 0xeb, 0x9d, 0x19, 0xc7, 0x60, 0x49, 0xf7, 0x01, 0xbe, 0x95, 0xac, 0x12, 0x63, 0x5f, 0xe8, + 0x5e, 0x02, 0x8d, 0x80, 0x6f, 0x41, 0x49, 0xac, 0xba, 0xf7, 0xd1, 0x04, 0x2b, 0x6f, 0xd5, 0x40, + 0xc0, 0xe1, 0xe4, 0x58, 0x25, 0x3e, 0xc1, 0xc4, 0x42, 0x9c, 0xf8, 0x44, 0x24, 0xbe, 0x2c, 0xc2, + 0xfa, 0x43, 0xa8, 0xc8, 0x52, 0x71, 0x4e, 0xb1, 0xbb, 0xf1, 0xaa, 0x4f, 0xcc, 0xb7, 0x59, 0xa6, + 0xea, 0x68, 0xf2, 0x65, 0xc6, 0x27, 0x2a, 0x63, 0xf1, 0x55, 0x19, 0x9f, 0xd0, 0x87, 0xb1, 0x13, + 0x05, 0xad, 0x63, 0xdc, 0x95, 0xe2, 0x63, 0x8f, 0x60, 0x49, 0xb1, 0xab, 0x89, 0x6b, 0xbb, 0xae, + 0x37, 0x71, 0xfb, 0x5c, 0x9d, 0xbf, 0x62, 0x32, 0xe9, 0x28, 0x4e, 0x31, 0x06, 0xd1, 0x01, 0x5d, + 0x8a, 0xdf, 0x7a, 0x08, 0x05, 0x92, 0xcb, 0x49, 0xf8, 0x48, 0x67, 0x5c, 0x84, 0xc2, 0x1e, 0x40, + 0x81, 0xc4, 0xf3, 0xec, 0xb5, 0xcc, 0x86, 0x10, 0x8c, 0x26, 0x30, 0x91, 0x71, 0x9f, 0x87, 0xbe, + 0xd3, 0x0f, 0xe2, 0xa3, 0x5d, 0x05, 0xa1, 0x7f, 0x52, 0x5d, 0xb1, 0xe5, 0x36, 0xc6, 0x44, 0x1d, + 0x95, 0x70, 0xc4, 0xc6, 0xb4, 0x94, 0x28, 0x43, 0x8a, 0x4b, 0x43, 0x58, 0x3d, 0xe6, 0xe1, 0x05, + 0xe7, 0xae, 0x2b, 0x84, 0xa1, 0x3e, 0x77, 0x43, 0xdf, 0x1e, 0x8a, 0x49, 0xa2, 0x1e, 0x3c, 0x9d, + 0x29, 0x35, 0xb6, 0x81, 0x6c, 0xc6, 0x19, 0xb7, 0xa2, 0x7c, 0xc4, 0x3b, 0x56, 0x8e, 0xd3, 0xd2, + 0xd6, 0x7f, 0x05, 0xd6, 0xaf, 0xcf, 0x94, 0x72, 0x80, 0xf3, 0x41, 0x92, 0xab, 0x44, 0x7e, 0xc0, + 0xa1, 0x67, 0x87, 0xd4, 0x1a, 0x9d, 0xb3, 0x74, 0xa0, 0xac, 0xa5, 0xc4, 0x7b, 0x7f, 0x06, 0x85, + 0x3b, 0xfa, 0x10, 0x3b, 0x92, 0xeb, 0xf9, 0x23, 0xf4, 0xbb, 0x0d, 0xac, 0xb8, 0xf4, 0x8c, 0xb9, + 0x10, 0xc3, 0xf1, 0xc4, 0xba, 0xb1, 0x01, 0x0b, 0x28, 0xd9, 0x6b, 0x1b, 0xdd, 0xcb, 0x84, 0x41, + 0x63, 0x19, 0x58, 0x87, 0x78, 0x97, 0x1e, 0xce, 0xf9, 0x9f, 0x72, 0x50, 0xd6, 0xc0, 0x62, 0x37, + 0xc2, 0x00, 0x40, 0x6b, 0xe0, 0xd8, 0x23, 0xae, 0x9c, 0x9c, 0x55, 0xb3, 0x8a, 0xd0, 0x6d, 0x09, + 0x14, 0x7b, 0xb1, 0x7d, 0x7e, 0x6a, 0x79, 0x93, 0xd0, 0x1a, 0xf0, 0x53, 0x9f, 0xab, 0x56, 0x56, + 0xec, 0xf3, 0xd3, 0x83, 0x49, 0xb8, 0x8d, 0x30, 0x81, 0x25, 0x78, 0x89, 0x86, 0x25, 0x63, 0xd6, + 0x46, 0xf6, 0x65, 0x8c, 0x25, 0x03, 0x27, 0x89, 0x32, 0xf3, 0x51, 0xe0, 0x24, 0x69, 0x8b, 0xd3, + 0x1b, 0x68, 0x61, 0x76, 0x03, 0xfd, 0x16, 0xac, 0xd2, 0x06, 0x2a, 0x59, 0xb3, 0x35, 0xb5, 0x92, + 0x97, 0x31, 0x55, 0x76, 0x52, 0x13, 0x7b, 0xeb, 0xa2, 0x07, 0x8a, 0x2d, 0x05, 0xce, 0x8f, 0x88, + 0x91, 0x65, 0x4c, 0xd1, 0x33, 0x59, 0x78, 0xd7, 0xf9, 0x11, 0x17, 0x98, 0x18, 0x1d, 0xa3, 0x63, + 0xca, 0xf3, 0x13, 0x23, 0xc7, 0x9d, 0xc6, 0xb4, 0x2f, 0x93, 0x98, 0x25, 0x89, 0x69, 0x5f, 0xea, + 0x98, 0x4f, 0x61, 0x6d, 0xc4, 0x07, 0x8e, 0x9d, 0x2c, 0xd6, 0x8a, 0x05, 0xb7, 0x65, 0x4a, 0xd6, + 0xf2, 0x74, 0x49, 0x71, 0x17, 0xa3, 0xf1, 0x23, 0x6f, 0x74, 0xec, 0x90, 0xcc, 0x42, 0xf1, 0x3a, + 0x79, 0xb3, 0xe6, 0x4e, 0x46, 0x3f, 0x40, 0xb0, 0xc8, 0x12, 0x18, 0x55, 0x28, 0x77, 0x43, 0x6f, + 0xac, 0xa6, 0xb9, 0x06, 0x15, 0xfa, 0x94, 0x87, 0x1a, 0x6f, 0xc1, 0x4d, 0x64, 0x09, 0x3d, 0x6f, + 0xec, 0x0d, 0xbd, 0xd3, 0xab, 0x84, 0x1d, 0xef, 0xdf, 0x65, 0x60, 0x29, 0x91, 0x2a, 0xd9, 0xeb, + 0xb7, 0x88, 0x9f, 0x45, 0x27, 0xd3, 0x68, 0x0d, 0x2e, 0x6a, 0x6b, 0x90, 0x10, 0x89, 0x99, 0xa9, + 0xd3, 0x6a, 0xcd, 0xf8, 0x46, 0x05, 0x95, 0x91, 0x58, 0x4a, 0x63, 0x96, 0xa5, 0xc8, 0xfc, 0xea, + 0xae, 0x05, 0x55, 0xc4, 0x2f, 0xc8, 0x33, 0x2e, 0x03, 0xd9, 0xe5, 0x5c, 0xf2, 0xa0, 0x80, 0x6e, + 0xf3, 0x53, 0x2d, 0x88, 0x0d, 0x81, 0x81, 0xf1, 0x4f, 0x32, 0x00, 0x71, 0xeb, 0xf0, 0xa8, 0x42, + 0x24, 0xb7, 0xd0, 0x65, 0x65, 0x9a, 0x8c, 0xf2, 0x26, 0x54, 0xa2, 0x88, 0xe5, 0x58, 0x12, 0x2a, + 0x2b, 0x98, 0x10, 0x87, 0xee, 0xc3, 0xc2, 0xe9, 0xd0, 0x3b, 0x46, 0x89, 0x55, 0xca, 0x2d, 0x14, + 0xaf, 0x56, 0x23, 0xb0, 0x92, 0x46, 0x62, 0xb9, 0x29, 0x9f, 0x1a, 0xd4, 0xac, 0x4b, 0x41, 0xc6, + 0x6f, 0x66, 0xa3, 0xd0, 0xcd, 0x78, 0x24, 0x5e, 0xae, 0xde, 0xfd, 0x24, 0xb1, 0x34, 0x2f, 0x73, + 0x2f, 0x7e, 0x0c, 0x35, 0x9f, 0x36, 0x25, 0xb5, 0x63, 0xe5, 0x5f, 0xb2, 0x63, 0x55, 0xfd, 0x84, + 0xa4, 0xf3, 0x75, 0xa8, 0xdb, 0x83, 0x73, 0xee, 0x87, 0x0e, 0x5a, 0xeb, 0x51, 0x3e, 0x96, 0xc1, + 0x92, 0x1a, 0x1c, 0x05, 0xd1, 0xfb, 0xb0, 0x20, 0x0f, 0xda, 0x46, 0x98, 0xf2, 0xea, 0x9e, 0x18, + 0x2c, 0x10, 0x8d, 0x7f, 0xae, 0x62, 0x45, 0x93, 0xb3, 0xfb, 0xf2, 0x51, 0xd1, 0x7b, 0x98, 0x9d, + 0x75, 0xa0, 0x4a, 0x42, 0x92, 0x4e, 0x00, 0xc9, 0x8f, 0x08, 0x28, 0x5d, 0x00, 0xc9, 0x61, 0xcd, + 0xbf, 0xce, 0xb0, 0x1a, 0xff, 0x21, 0x03, 0xf3, 0xbb, 0xde, 0x78, 0xd7, 0xa1, 0x60, 0x7d, 0x5c, + 0x26, 0x91, 0x8f, 0x6a, 0x4e, 0x7c, 0x62, 0xe0, 0xcf, 0x4b, 0xce, 0x93, 0xa5, 0x8a, 0x79, 0xd5, + 0xa4, 0x98, 0xf7, 0x5d, 0xb8, 0x85, 0x2e, 0x40, 0xdf, 0x1b, 0x7b, 0xbe, 0x58, 0xaa, 0xf6, 0x90, + 0xc4, 0x3d, 0xcf, 0x0d, 0xcf, 0x14, 0xef, 0xbc, 0x79, 0xc2, 0xf9, 0xa1, 0x86, 0xb1, 0x1f, 0x21, + 0xe0, 0x89, 0xcd, 0x61, 0x78, 0x6e, 0x91, 0x86, 0x2e, 0xe5, 0x51, 0xe2, 0xa8, 0x0b, 0x22, 0xa1, + 0x85, 0x70, 0x94, 0x48, 0x8d, 0x6f, 0x43, 0x29, 0x32, 0xf6, 0xb0, 0x77, 0xa1, 0x74, 0xe6, 0x8d, + 0xa5, 0x45, 0x28, 0x93, 0x38, 0x73, 0x27, 0x7b, 0x6d, 0x16, 0xcf, 0xe8, 0x47, 0x60, 0xfc, 0xd9, + 0x3c, 0xcc, 0xb7, 0xdd, 0x73, 0xcf, 0xe9, 0x63, 0xb4, 0xe9, 0x88, 0x8f, 0x3c, 0x75, 0xda, 0x5f, + 0xfc, 0xc6, 0xd8, 0xac, 0xf8, 0x02, 0x9e, 0x9c, 0x8c, 0xcd, 0x8a, 0xae, 0xde, 0x59, 0x81, 0x39, + 0x5f, 0xbf, 0x41, 0xa7, 0xe0, 0x63, 0xfc, 0x7b, 0xb4, 0x5f, 0x16, 0xb4, 0xdb, 0x12, 0x44, 0x59, + 0x74, 0xb3, 0x0b, 0x0e, 0x19, 0x9d, 0xbe, 0x2c, 0x21, 0x04, 0x07, 0xec, 0x36, 0xcc, 0xcb, 0x23, + 0x6e, 0x74, 0x26, 0x89, 0x02, 0xd6, 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0xe4, 0xc2, 0x8d, 0x04, 0xd9, + 0x9c, 0x59, 0x51, 0xc0, 0x6d, 0x41, 0x6b, 0x77, 0xa1, 0x4c, 0xf8, 0x84, 0x52, 0x94, 0x41, 0x9a, + 0x08, 0x42, 0x84, 0x94, 0x8b, 0xa8, 0x4a, 0xa9, 0x17, 0x51, 0x61, 0x38, 0x71, 0xc4, 0x65, 0xa9, + 0x8b, 0x40, 0xd7, 0x0f, 0x69, 0x70, 0x75, 0x0b, 0x9b, 0xb4, 0xa9, 0xd0, 0x61, 0x64, 0x65, 0x53, + 0x79, 0x0b, 0xaa, 0x27, 0xf6, 0x70, 0x78, 0x6c, 0xf7, 0x5f, 0x90, 0x29, 0xa0, 0x42, 0xd6, 0x4f, + 0x05, 0x44, 0x5b, 0xc0, 0x5d, 0x28, 0x6b, 0xb3, 0x8c, 0x11, 0x98, 0x79, 0x13, 0xe2, 0xf9, 0x9d, + 0xb6, 0xf0, 0xd5, 0x5e, 0xc3, 0xc2, 0xa7, 0x45, 0xa2, 0x2e, 0x24, 0x23, 0x51, 0x6f, 0x21, 0x37, + 0x95, 0x21, 0x87, 0x75, 0xba, 0xeb, 0xc6, 0x1e, 0x0c, 0x30, 0xe4, 0x90, 0x2e, 0x96, 0xc4, 0xc1, + 0xa3, 0xf4, 0x45, 0xd2, 0x25, 0x08, 0x46, 0x28, 0x77, 0xc8, 0x4c, 0x3d, 0xb6, 0x9d, 0x01, 0x1e, + 0x3a, 0x20, 0xeb, 0xc1, 0xbc, 0x3d, 0x0a, 0x0f, 0x6d, 0x67, 0xc0, 0xee, 0x41, 0x45, 0x25, 0xe3, + 0xee, 0xb8, 0x44, 0xe3, 0x2f, 0x93, 0xc5, 0x9e, 0x68, 0x40, 0x35, 0xc2, 0x18, 0xc5, 0x27, 0x8a, + 0xcb, 0x12, 0x05, 0xe9, 0xe0, 0x7d, 0x8c, 0xf2, 0x09, 0x39, 0x9e, 0x1b, 0xae, 0x3d, 0xb9, 0x15, + 0x05, 0x1f, 0x20, 0x95, 0xaa, 0xff, 0xe4, 0x1c, 0x23, 0x4c, 0x21, 0xdc, 0x91, 0x8f, 0x6e, 0x35, + 0x21, 0xff, 0x4a, 0x54, 0xf4, 0xd1, 0x11, 0x02, 0xfb, 0xb6, 0xa6, 0xbf, 0x36, 0x10, 0xf9, 0xf6, + 0x54, 0xf9, 0xd7, 0x9d, 0xb9, 0xba, 0x03, 0xe0, 0x04, 0x62, 0x97, 0x09, 0xb8, 0x3b, 0xc0, 0x23, + 0xc0, 0x45, 0xb3, 0xe4, 0x04, 0xcf, 0x09, 0xf0, 0xb3, 0x55, 0x6c, 0x9b, 0x50, 0xd1, 0xbb, 0xc9, + 0x8a, 0x90, 0x3f, 0x38, 0x6c, 0x75, 0xea, 0x37, 0x58, 0x19, 0xe6, 0xbb, 0xad, 0x5e, 0x6f, 0x0f, + 0x3d, 0x7d, 0x15, 0x28, 0x46, 0xe7, 0x14, 0xb3, 0xe2, 0xab, 0xb9, 0xb5, 0xd5, 0x3a, 0xec, 0xb5, + 0xb6, 0xeb, 0xb9, 0xef, 0xe7, 0x8b, 0xd9, 0x7a, 0xce, 0xf8, 0xf3, 0x1c, 0x94, 0xb5, 0x51, 0x78, + 0x39, 0x33, 0xbe, 0x03, 0x80, 0x9a, 0x64, 0x1c, 0x91, 0x9a, 0x37, 0x4b, 0x02, 0x42, 0x93, 0xaf, + 0xfb, 0x28, 0x72, 0x74, 0x89, 0x92, 0xf2, 0x51, 0xbc, 0x05, 0x55, 0xba, 0x8f, 0x48, 0xf7, 0xd7, + 0x16, 0xcc, 0x0a, 0x01, 0x25, 0xab, 0xc6, 0x03, 0xcc, 0x88, 0x84, 0xa7, 0xe7, 0xe4, 0xed, 0x24, + 0x04, 0xc2, 0xf3, 0x73, 0x78, 0xf8, 0x31, 0xf0, 0x86, 0xe7, 0x9c, 0x30, 0x48, 0x22, 0x2c, 0x4b, + 0x58, 0x4f, 0x1e, 0xc5, 0x96, 0xfc, 0x50, 0x3b, 0x41, 0x5b, 0x30, 0x2b, 0x04, 0x94, 0x15, 0x7d, + 0x43, 0x11, 0x10, 0x45, 0xaf, 0xac, 0xcd, 0x52, 0x43, 0x82, 0x78, 0xf6, 0x66, 0xcc, 0x88, 0x25, + 0x24, 0x8c, 0xaf, 0xcd, 0xe6, 0x7b, 0xb5, 0x39, 0x91, 0xbd, 0x0b, 0x6c, 0x34, 0x1e, 0x5b, 0x29, + 0x06, 0xbe, 0xbc, 0xb9, 0x30, 0x1a, 0x8f, 0x7b, 0x9a, 0xfd, 0xeb, 0x67, 0x60, 0x7b, 0xfc, 0x02, + 0x58, 0x53, 0x2c, 0x60, 0x6c, 0x62, 0xa4, 0x8a, 0xc5, 0x6c, 0x39, 0xa3, 0xb3, 0xe5, 0x14, 0xee, + 0x97, 0x4d, 0xe5, 0x7e, 0x2f, 0xe3, 0x13, 0xc6, 0x0e, 0x94, 0x0f, 0xb5, 0xdb, 0xce, 0xee, 0x89, + 0x1d, 0x42, 0xdd, 0x73, 0x46, 0x7b, 0x07, 0xd9, 0x14, 0x7d, 0x79, 0xbd, 0x99, 0xd6, 0x9a, 0xac, + 0xd6, 0x1a, 0xe3, 0x1f, 0x65, 0xe8, 0x26, 0x99, 0xa8, 0xf1, 0xf1, 0x05, 0x6b, 0xca, 0xfd, 0x16, + 0x1f, 0x74, 0x2f, 0x2b, 0xb7, 0x9b, 0x3c, 0xa3, 0x8e, 0x4d, 0xb3, 0xbc, 0x93, 0x93, 0x80, 0xab, + 0x18, 0x8f, 0x32, 0xc2, 0x0e, 0x10, 0xa4, 0x84, 0x6f, 0x21, 0xe1, 0x3b, 0x54, 0x7e, 0x20, 0x03, + 0x3b, 0x84, 0xf0, 0xbd, 0x6f, 0x5f, 0xca, 0x5a, 0x03, 0x21, 0x82, 0x48, 0xff, 0x80, 0x3a, 0x0b, + 0x1b, 0x7d, 0x1b, 0xff, 0x40, 0x9e, 0xc5, 0x9f, 0x1e, 0xdf, 0x87, 0x50, 0x8c, 0x4a, 0x4d, 0xee, + 0xb0, 0x0a, 0x33, 0x4a, 0x17, 0xfb, 0x38, 0x1a, 0x43, 0x12, 0x2d, 0xa6, 0xc5, 0x85, 0x3e, 0x9e, + 0xb6, 0xd6, 0xea, 0xf7, 0x80, 0x9d, 0x38, 0xfe, 0x34, 0x32, 0x2d, 0xb6, 0x3a, 0xa6, 0x68, 0xd8, + 0xc6, 0x11, 0x2c, 0x29, 0x2e, 0xa1, 0x69, 0x04, 0xc9, 0xc9, 0xcb, 0xbc, 0x82, 0xc9, 0x67, 0x67, + 0x98, 0xbc, 0xf1, 0x3b, 0x05, 0x98, 0x57, 0x37, 0x07, 0xa6, 0xdd, 0x76, 0x57, 0x4a, 0xde, 0x76, + 0xd7, 0x48, 0xdc, 0x8c, 0x84, 0x53, 0x2f, 0xf7, 0xfb, 0xfb, 0xd3, 0x5b, 0xb6, 0xe6, 0xab, 0x48, + 0x6c, 0xdb, 0xab, 0x90, 0x1f, 0xdb, 0xe1, 0x19, 0xda, 0x25, 0x89, 0x78, 0xf0, 0x5b, 0xf9, 0x30, + 0x0a, 0x49, 0x1f, 0x46, 0xda, 0xcd, 0x80, 0x24, 0x92, 0xce, 0xdc, 0x0c, 0x78, 0x0b, 0x48, 0xbe, + 0xd0, 0x82, 0xde, 0x8a, 0x08, 0x10, 0x7b, 0x51, 0x52, 0x1c, 0x29, 0x4e, 0x8b, 0x23, 0xaf, 0x2d, + 0x2a, 0x7c, 0x0b, 0xe6, 0xe8, 0x56, 0x0d, 0x79, 0xe6, 0x57, 0x6d, 0x28, 0x72, 0x0c, 0xd5, 0x7f, + 0x3a, 0x09, 0x61, 0x4a, 0x5c, 0xfd, 0x9a, 0xad, 0x72, 0xe2, 0x9a, 0x2d, 0xdd, 0xb7, 0x52, 0x49, + 0xfa, 0x56, 0x1e, 0x40, 0x3d, 0x1a, 0x50, 0xb4, 0x54, 0xba, 0x81, 0x3c, 0x51, 0x58, 0x53, 0x70, + 0xc1, 0x25, 0x3b, 0x41, 0xbc, 0x21, 0xd6, 0x12, 0x1b, 0xa2, 0xe0, 0x61, 0xcd, 0x30, 0xe4, 0xa3, + 0x71, 0xa8, 0x36, 0x44, 0xed, 0x32, 0x46, 0xa2, 0x88, 0x05, 0xa4, 0x08, 0x35, 0xed, 0x44, 0x35, + 0x9b, 0x50, 0x3b, 0xb1, 0x9d, 0xe1, 0xc4, 0xe7, 0x96, 0xcf, 0xed, 0xc0, 0x73, 0x91, 0x29, 0xc4, + 0x7b, 0xb3, 0xec, 0xe2, 0x0e, 0xe1, 0x98, 0x88, 0x62, 0x56, 0x4f, 0xf4, 0x4f, 0x3c, 0xdc, 0xa4, + 0x8f, 0x84, 0xd8, 0xca, 0xe4, 0xd1, 0x61, 0x8a, 0x61, 0x69, 0x77, 0xac, 0x9d, 0xbd, 0xf6, 0xb3, + 0xdd, 0x5e, 0x3d, 0x23, 0x3e, 0xbb, 0x47, 0x5b, 0x5b, 0xad, 0xd6, 0x36, 0x6e, 0x6d, 0x00, 0x73, + 0x3b, 0xcd, 0xb6, 0xd8, 0xe6, 0x72, 0xc6, 0x6f, 0x67, 0xa1, 0xac, 0xf5, 0x83, 0x3d, 0x8d, 0x86, + 0x9f, 0xae, 0x7c, 0xba, 0x33, 0xdb, 0xd7, 0x0d, 0xc5, 0xf3, 0xb5, 0xf1, 0x8f, 0x2e, 0x5c, 0xcc, + 0x5e, 0x7b, 0xe1, 0x22, 0x7b, 0x07, 0x16, 0x6c, 0x2a, 0x21, 0x1a, 0x6e, 0x69, 0xee, 0x97, 0x60, + 0x39, 0xda, 0x18, 0x53, 0x1a, 0x6f, 0x5c, 0x02, 0x2f, 0xaf, 0xc2, 0x38, 0xa3, 0xbd, 0x0b, 0x67, + 0x65, 0x5e, 0x8e, 0x89, 0x74, 0xcf, 0x47, 0x22, 0x80, 0x1c, 0x29, 0x95, 0x6c, 0x7c, 0x00, 0x10, + 0xb7, 0x39, 0x39, 0x38, 0x37, 0x92, 0x83, 0x93, 0xd1, 0x06, 0x27, 0x6b, 0xfc, 0x33, 0xc9, 0xb0, + 0xe4, 0x48, 0x47, 0x06, 0xbe, 0x6f, 0x80, 0x32, 0x39, 0x5a, 0x18, 0xda, 0x3d, 0x1e, 0xf2, 0x50, + 0xdd, 0x50, 0xb0, 0x28, 0x53, 0xda, 0x51, 0xc2, 0x0c, 0x83, 0xcd, 0xce, 0x32, 0xd8, 0x37, 0xa1, + 0x22, 0x98, 0xab, 0x24, 0x93, 0x40, 0x32, 0xa9, 0xf2, 0xc8, 0xbe, 0x54, 0x75, 0x27, 0x38, 0x6b, + 0x7e, 0x8a, 0xb3, 0xfe, 0x4e, 0x86, 0x2e, 0x0c, 0x89, 0x1b, 0x1a, 0xb3, 0xd6, 0xa8, 0xcc, 0x24, + 0x6b, 0x95, 0xa8, 0x66, 0x94, 0x7e, 0x0d, 0xbb, 0xcc, 0xa6, 0xb3, 0xcb, 0x74, 0x46, 0x9c, 0x4b, + 0x65, 0xc4, 0xc6, 0x3a, 0x34, 0xb6, 0xb9, 0x18, 0x8a, 0xe6, 0x70, 0x38, 0x35, 0x96, 0xc6, 0x2d, + 0xb8, 0x99, 0x92, 0x26, 0x6d, 0x35, 0x9f, 0xc0, 0x4a, 0x93, 0x6e, 0x52, 0xf8, 0x59, 0x1d, 0x99, + 0x34, 0x1a, 0xb0, 0x3a, 0x5d, 0xa4, 0xac, 0x6c, 0x07, 0x16, 0xb7, 0xf9, 0xf1, 0xe4, 0x74, 0x8f, + 0x9f, 0xc7, 0x15, 0x31, 0xc8, 0x07, 0x67, 0xde, 0x85, 0x9c, 0x5c, 0xfc, 0x8d, 0xc1, 0x98, 0x02, + 0xc7, 0x0a, 0xc6, 0xbc, 0xaf, 0xec, 0xf5, 0x08, 0xe9, 0x8e, 0x79, 0xdf, 0x78, 0x0a, 0x4c, 0x2f, + 0x47, 0xce, 0x84, 0x50, 0xa6, 0x26, 0xc7, 0x56, 0x70, 0x15, 0x84, 0x7c, 0xa4, 0x8e, 0x0a, 0x42, + 0x30, 0x39, 0xee, 0x12, 0xc4, 0xb8, 0x0f, 0x95, 0x43, 0xfb, 0xca, 0xe4, 0x5f, 0xc8, 0x13, 0x79, + 0x6b, 0x30, 0x3f, 0xb6, 0xaf, 0x04, 0xb7, 0x8c, 0x5c, 0x77, 0x98, 0x6c, 0xfc, 0x41, 0x1e, 0xe6, + 0x08, 0x93, 0xdd, 0xa3, 0x2b, 0x8b, 0x1d, 0x17, 0xb9, 0x95, 0xda, 0x4f, 0x34, 0xd0, 0xcc, 0x96, + 0x93, 0x9d, 0xdd, 0x72, 0xa4, 0x9d, 0x51, 0x5d, 0xd5, 0xa4, 0x9c, 0x2c, 0xee, 0x64, 0xa4, 0xee, + 0x67, 0x4a, 0x5e, 0x27, 0x90, 0x8f, 0xaf, 0xa4, 0xa6, 0xb3, 0xd6, 0x49, 0x37, 0x78, 0xac, 0xb2, + 0x51, 0xeb, 0xd4, 0x4e, 0x2a, 0x77, 0x15, 0x1d, 0x94, 0xaa, 0x17, 0xce, 0xab, 0x63, 0xa6, 0x49, + 0xbd, 0x70, 0x46, 0xff, 0x2b, 0xbe, 0x5a, 0xff, 0x23, 0x03, 0xe4, 0x4b, 0xf4, 0x3f, 0x78, 0x0d, + 0xfd, 0xef, 0x35, 0x5c, 0xd0, 0x37, 0xa1, 0x88, 0xe2, 0x91, 0xb6, 0xc9, 0x08, 0xb1, 0x48, 0x6c, + 0x32, 0x1f, 0x6a, 0x1a, 0x12, 0xc5, 0xbf, 0x68, 0x5c, 0xde, 0xe4, 0x5f, 0xfc, 0x7c, 0x5c, 0x7b, + 0x9f, 0xc3, 0xbc, 0x84, 0x0a, 0x82, 0x76, 0xed, 0x91, 0xba, 0xed, 0x0e, 0x7f, 0x8b, 0x61, 0xc3, + 0x2b, 0xba, 0xbe, 0x98, 0x38, 0x3e, 0x1f, 0xa8, 0x6b, 0x8c, 0x1c, 0x5c, 0xa3, 0x02, 0x22, 0x3a, + 0x28, 0xb4, 0x35, 0xd7, 0xbb, 0x70, 0x25, 0xef, 0x99, 0x77, 0x82, 0xe7, 0xe2, 0xd3, 0x60, 0x50, + 0xc7, 0xfb, 0x2e, 0xc7, 0x9e, 0xaf, 0xf6, 0x70, 0xe3, 0x0f, 0x33, 0x50, 0x97, 0xab, 0x2b, 0x4a, + 0xd3, 0x95, 0xa5, 0xc2, 0x75, 0xe1, 0x1a, 0x2f, 0xbf, 0x94, 0xc8, 0x80, 0x2a, 0xda, 0x88, 0xa2, + 0x0d, 0x9d, 0x6c, 0x5c, 0x65, 0x01, 0xdc, 0x91, 0x9b, 0xfa, 0x1b, 0x50, 0x56, 0xa1, 0xe2, 0x23, + 0x67, 0xa8, 0x6e, 0x9f, 0xa7, 0x58, 0xf1, 0x7d, 0x67, 0xa8, 0xe4, 0x01, 0xdf, 0x96, 0xc7, 0x9e, + 0x33, 0x28, 0x0f, 0x98, 0x76, 0xc8, 0x8d, 0x7f, 0x95, 0x81, 0x45, 0xad, 0x2b, 0x72, 0xdd, 0x7e, + 0x04, 0x95, 0xe8, 0xa2, 0x59, 0x1e, 0x09, 0xa8, 0x6b, 0x49, 0x46, 0x13, 0x67, 0x2b, 0xf7, 0x23, + 0x48, 0x20, 0x1a, 0x33, 0xb0, 0xaf, 0x28, 0x9e, 0x79, 0x32, 0x52, 0x3a, 0xe0, 0xc0, 0xbe, 0xda, + 0xe1, 0xbc, 0x3b, 0x19, 0x09, 0x0d, 0xff, 0x82, 0xf3, 0x17, 0x11, 0x02, 0xb1, 0x4f, 0x10, 0x30, + 0x89, 0x61, 0x40, 0x75, 0xe4, 0xb9, 0xe1, 0x59, 0x84, 0x22, 0x85, 0x73, 0x04, 0x12, 0x8e, 0xf1, + 0xa7, 0x59, 0x58, 0x22, 0x4b, 0xa4, 0xb4, 0x00, 0x4b, 0xd6, 0xd5, 0x80, 0x39, 0x32, 0xca, 0x12, + 0xf3, 0xda, 0xbd, 0x61, 0xca, 0x6f, 0xf6, 0xad, 0xd7, 0xb4, 0x9e, 0xaa, 0x93, 0xd5, 0xd7, 0x0c, + 0x7f, 0x6e, 0x76, 0xf8, 0xaf, 0x1f, 0xde, 0x34, 0x7f, 0x70, 0x21, 0xcd, 0x1f, 0xfc, 0x3a, 0x5e, + 0xd8, 0x99, 0x33, 0xc0, 0xf3, 0x12, 0x47, 0x3b, 0x03, 0xfc, 0x14, 0xd6, 0x12, 0x38, 0xc8, 0xad, + 0x9d, 0x13, 0x87, 0xab, 0x6b, 0x68, 0x96, 0x35, 0xec, 0xae, 0x4a, 0xdb, 0x9c, 0x87, 0x42, 0xd0, + 0xf7, 0xc6, 0xdc, 0x58, 0x85, 0xe5, 0xe4, 0xa8, 0xca, 0x6d, 0xe2, 0x77, 0x33, 0xd0, 0x90, 0xd1, + 0x3b, 0x8e, 0x7b, 0xba, 0xeb, 0x04, 0xa1, 0xe7, 0x47, 0x17, 0xb2, 0xde, 0x01, 0x08, 0x42, 0xdb, + 0x97, 0x4a, 0xb9, 0xbc, 0x78, 0x05, 0x21, 0xa8, 0x70, 0xdf, 0x84, 0x22, 0x77, 0x07, 0x94, 0x48, + 0xd4, 0x30, 0xcf, 0xdd, 0x81, 0x52, 0xd7, 0x67, 0xb6, 0xd2, 0x6a, 0x52, 0x48, 0x90, 0xf7, 0x20, + 0x88, 0xd1, 0xe1, 0xe7, 0xb8, 0xa5, 0xe7, 0xa3, 0x7b, 0x10, 0xf6, 0xed, 0x4b, 0x8c, 0x85, 0x0d, + 0x8c, 0xbf, 0x9b, 0x85, 0x85, 0xb8, 0x7d, 0x74, 0x89, 0xca, 0xcb, 0xaf, 0x83, 0xb9, 0x27, 0xc9, + 0xc1, 0x11, 0x6a, 0x8e, 0x66, 0x9f, 0x2d, 0xd2, 0xe2, 0x6c, 0xbb, 0xcc, 0x80, 0xb2, 0xc2, 0xf0, + 0x26, 0xa1, 0x76, 0x2f, 0x62, 0x89, 0x50, 0x0e, 0x26, 0xa1, 0xd0, 0x4b, 0x85, 0x82, 0xee, 0xb8, + 0x52, 0x33, 0x2c, 0xd8, 0xa3, 0xb0, 0x8d, 0xcf, 0x2d, 0x08, 0xb0, 0xc8, 0x46, 0x13, 0x29, 0xb0, + 0x04, 0x7e, 0x9d, 0xd4, 0x11, 0x9a, 0x39, 0x54, 0x45, 0x74, 0x59, 0x9d, 0x6e, 0x9e, 0x8e, 0x64, + 0xf5, 0x37, 0xa0, 0x4c, 0x85, 0xc7, 0x47, 0xbe, 0xf3, 0x66, 0x09, 0x6b, 0xc0, 0x74, 0x69, 0x2b, + 0xf3, 0x26, 0x09, 0x0b, 0x01, 0x50, 0x55, 0x18, 0x1c, 0xf3, 0x37, 0x33, 0x70, 0x33, 0x65, 0xda, + 0xe4, 0x2a, 0xdf, 0x82, 0xc5, 0x93, 0x28, 0x51, 0x8d, 0x2e, 0x2d, 0xf5, 0x55, 0xc5, 0x56, 0x93, + 0x63, 0x6a, 0xd6, 0x4f, 0x92, 0x80, 0x58, 0x37, 0xa5, 0x19, 0x4c, 0x5c, 0x28, 0x80, 0x22, 0x11, + 0x4d, 0x23, 0xa9, 0x85, 0x87, 0xb0, 0xde, 0xba, 0x14, 0x1c, 0x63, 0x4b, 0x7f, 0x2f, 0x44, 0x91, + 0x51, 0xd2, 0x0e, 0x9f, 0x79, 0x2d, 0x3b, 0xfc, 0x80, 0x4e, 0x20, 0x47, 0x65, 0xfd, 0x24, 0x85, + 0xe0, 0x06, 0x2a, 0xf2, 0xd0, 0x7b, 0x27, 0xea, 0x66, 0x81, 0x7e, 0xf4, 0xce, 0x89, 0x11, 0xc0, + 0xc2, 0xfe, 0x64, 0x18, 0x3a, 0xf1, 0xd3, 0x27, 0xec, 0x5b, 0x32, 0x0f, 0xd6, 0xa3, 0x46, 0x2d, + 0xb5, 0x22, 0x88, 0x2a, 0xc2, 0xc1, 0x1a, 0x89, 0x82, 0xac, 0xd9, 0xfa, 0x16, 0x46, 0xc9, 0x1a, + 0x8c, 0x9b, 0xb0, 0x16, 0x7f, 0xd1, 0xb0, 0xa9, 0xad, 0xe6, 0x1f, 0x66, 0x28, 0xf0, 0x3e, 0xf9, + 0x0c, 0x0b, 0x6b, 0xc1, 0x52, 0xe0, 0xb8, 0xa7, 0x43, 0xae, 0x17, 0x1f, 0xc8, 0x41, 0x58, 0x49, + 0xb6, 0x4d, 0x3e, 0xd5, 0x62, 0x2e, 0x52, 0x8e, 0xb8, 0xb4, 0x80, 0x6d, 0x5e, 0xd7, 0xc8, 0x98, + 0x2c, 0xa6, 0x46, 0x63, 0xb6, 0xf1, 0x6d, 0xa8, 0x25, 0x2b, 0x62, 0x1f, 0xca, 0x83, 0xfb, 0x71, + 0xab, 0x72, 0x53, 0xa7, 0x9a, 0x63, 0x82, 0x28, 0xc7, 0x63, 0x1f, 0x18, 0x7f, 0x3b, 0x03, 0x0d, + 0x93, 0x0b, 0xca, 0xd5, 0x5a, 0xa9, 0x68, 0xe6, 0xa3, 0x99, 0x52, 0xaf, 0xef, 0xab, 0xba, 0x0f, + 0x40, 0xb5, 0xe8, 0xbd, 0x6b, 0x27, 0x63, 0xf7, 0xc6, 0x4c, 0x8f, 0x36, 0x8b, 0x30, 0x47, 0x28, + 0xc6, 0x1a, 0xac, 0xc8, 0xf6, 0xa8, 0xb6, 0xc4, 0x4e, 0xd6, 0x44, 0x8d, 0x09, 0x27, 0xeb, 0x3a, + 0x34, 0xe8, 0x84, 0xae, 0xde, 0x09, 0x99, 0x71, 0x1b, 0xd8, 0xbe, 0xdd, 0xb7, 0x7d, 0xcf, 0x73, + 0x0f, 0xb9, 0x2f, 0xc3, 0x98, 0x51, 0xc2, 0x44, 0x1f, 0xa4, 0x12, 0x85, 0xe9, 0x4b, 0xdd, 0x06, + 0xeb, 0xb9, 0x2a, 0x6a, 0x8b, 0xbe, 0x0c, 0x13, 0x96, 0x36, 0xed, 0x17, 0x5c, 0x95, 0xa4, 0x86, + 0xe8, 0x63, 0x28, 0x8f, 0xa3, 0x42, 0xd5, 0xb8, 0xab, 0x8b, 0x45, 0x66, 0xab, 0x35, 0x75, 0x6c, + 0xe3, 0x09, 0x2c, 0x27, 0xcb, 0x94, 0xac, 0x63, 0x1d, 0x8a, 0x23, 0x09, 0x93, 0xad, 0x8b, 0xbe, + 0x8d, 0xdf, 0x2a, 0xc2, 0xbc, 0xd4, 0x46, 0xd9, 0x06, 0xe4, 0xfb, 0x2a, 0x72, 0x2e, 0xbe, 0xaf, + 0x4a, 0xa6, 0xaa, 0xff, 0x5b, 0x18, 0x3f, 0x27, 0xf0, 0xd8, 0xc7, 0x50, 0x4b, 0x3a, 0x8f, 0xa7, + 0xce, 0xff, 0x27, 0xbd, 0xbe, 0xd5, 0xfe, 0x94, 0x9b, 0xb0, 0x14, 0x6f, 0x8e, 0x24, 0x33, 0x14, + 0xcf, 0xb4, 0xdd, 0xd3, 0x73, 0x85, 0xbc, 0x1d, 0x9c, 0xd9, 0xd6, 0x93, 0xa7, 0x1f, 0xc8, 0x0b, + 0x00, 0xca, 0x08, 0xec, 0x9e, 0xd9, 0x4f, 0x9e, 0x7e, 0x30, 0x2d, 0x49, 0xcb, 0xe3, 0xff, 0x9a, + 0x24, 0xbd, 0x0c, 0x05, 0xba, 0xf6, 0x94, 0x42, 0xa0, 0xe8, 0x83, 0x3d, 0x86, 0x65, 0x65, 0xda, + 0x90, 0xc1, 0xea, 0xc4, 0x05, 0x8b, 0x74, 0x3e, 0x50, 0xa6, 0x75, 0x31, 0x89, 0x8c, 0x21, 0xab, + 0x30, 0x77, 0x16, 0xdf, 0x61, 0x5b, 0x35, 0xe5, 0x97, 0xf1, 0xa7, 0x05, 0x28, 0x6b, 0x83, 0xc2, + 0x2a, 0x50, 0x34, 0x5b, 0xdd, 0x96, 0xf9, 0x69, 0x6b, 0xbb, 0x7e, 0x83, 0x3d, 0x80, 0xb7, 0xdb, + 0x9d, 0xad, 0x03, 0xd3, 0x6c, 0x6d, 0xf5, 0xac, 0x03, 0xd3, 0x52, 0xb7, 0xa6, 0x1d, 0x36, 0x3f, + 0xdf, 0x6f, 0x75, 0x7a, 0xd6, 0x76, 0xab, 0xd7, 0x6c, 0xef, 0x75, 0xeb, 0x19, 0x76, 0x1b, 0x1a, + 0x31, 0xa6, 0x4a, 0x6e, 0xee, 0x1f, 0x1c, 0x75, 0x7a, 0xf5, 0x2c, 0xbb, 0x0b, 0xb7, 0x76, 0xda, + 0x9d, 0xe6, 0x9e, 0x15, 0xe3, 0x6c, 0xed, 0xf5, 0x3e, 0xb5, 0x5a, 0xbf, 0x74, 0xd8, 0x36, 0x3f, + 0xaf, 0xe7, 0xd2, 0x10, 0x76, 0x7b, 0x7b, 0x5b, 0xaa, 0x84, 0x3c, 0xbb, 0x09, 0x2b, 0x84, 0x40, + 0x59, 0xac, 0xde, 0xc1, 0x81, 0xd5, 0x3d, 0x38, 0xe8, 0xd4, 0x0b, 0x6c, 0x11, 0xaa, 0xed, 0xce, + 0xa7, 0xcd, 0xbd, 0xf6, 0xb6, 0x65, 0xb6, 0x9a, 0x7b, 0xfb, 0xf5, 0x39, 0xb6, 0x04, 0x0b, 0xd3, + 0x78, 0xf3, 0xa2, 0x08, 0x85, 0x77, 0xd0, 0x69, 0x1f, 0x74, 0xac, 0x4f, 0x5b, 0x66, 0xb7, 0x7d, + 0xd0, 0xa9, 0x17, 0xd9, 0x2a, 0xb0, 0x64, 0xd2, 0xee, 0x7e, 0x73, 0xab, 0x5e, 0x62, 0x2b, 0xb0, + 0x98, 0x84, 0x3f, 0x6f, 0x7d, 0x5e, 0x07, 0xd6, 0x80, 0x65, 0x6a, 0x98, 0xb5, 0xd9, 0xda, 0x3b, + 0xf8, 0xcc, 0xda, 0x6f, 0x77, 0xda, 0xfb, 0x47, 0xfb, 0xf5, 0x32, 0x5e, 0xc6, 0xd8, 0x6a, 0x59, + 0xed, 0x4e, 0xf7, 0x68, 0x67, 0xa7, 0xbd, 0xd5, 0x6e, 0x75, 0x7a, 0xf5, 0x0a, 0xd5, 0x9c, 0xd6, + 0xf1, 0xaa, 0xc8, 0x20, 0x4f, 0xb4, 0x58, 0xdb, 0xed, 0x6e, 0x73, 0x73, 0xaf, 0xb5, 0x5d, 0xaf, + 0xb1, 0x3b, 0x70, 0xb3, 0xd7, 0xda, 0x3f, 0x3c, 0x30, 0x9b, 0xe6, 0xe7, 0xea, 0xc4, 0x8b, 0xb5, + 0xd3, 0x6c, 0xef, 0x1d, 0x99, 0xad, 0xfa, 0x02, 0x7b, 0x13, 0xee, 0x98, 0xad, 0x4f, 0x8e, 0xda, + 0x66, 0x6b, 0xdb, 0xea, 0x1c, 0x6c, 0xb7, 0xac, 0x9d, 0x56, 0xb3, 0x77, 0x64, 0xb6, 0xac, 0xfd, + 0x76, 0xb7, 0xdb, 0xee, 0x3c, 0xab, 0xd7, 0xd9, 0xdb, 0x70, 0x2f, 0x42, 0x89, 0x0a, 0x98, 0xc2, + 0x5a, 0x14, 0xfd, 0x53, 0x53, 0xda, 0x69, 0xfd, 0x52, 0xcf, 0x3a, 0x6c, 0xb5, 0xcc, 0x3a, 0x63, + 0xeb, 0xb0, 0x1a, 0x57, 0x4f, 0x15, 0xc8, 0xba, 0x97, 0x44, 0xda, 0x61, 0xcb, 0xdc, 0x6f, 0x76, + 0xc4, 0x04, 0x27, 0xd2, 0x96, 0x45, 0xb3, 0xe3, 0xb4, 0xe9, 0x66, 0xaf, 0x30, 0x06, 0x35, 0x6d, + 0x56, 0x76, 0x9a, 0x66, 0x7d, 0x95, 0x2d, 0x40, 0x79, 0xff, 0xf0, 0xd0, 0xea, 0xb5, 0xf7, 0x5b, + 0x07, 0x47, 0xbd, 0xfa, 0x1a, 0x5b, 0x81, 0x7a, 0xbb, 0xd3, 0x6b, 0x99, 0x62, 0xae, 0x55, 0xd6, + 0xff, 0x31, 0xcf, 0x96, 0x61, 0x41, 0xb5, 0x54, 0x41, 0xff, 0x62, 0x9e, 0xad, 0x01, 0x3b, 0xea, + 0x98, 0xad, 0xe6, 0xb6, 0x18, 0xb8, 0x28, 0xe1, 0x7f, 0xce, 0x4b, 0x47, 0xd2, 0x1f, 0xe6, 0xa2, + 0xcd, 0x3a, 0x8e, 0xcc, 0x48, 0xde, 0x68, 0x5e, 0xd1, 0x6e, 0x22, 0x7f, 0xd5, 0x5b, 0x23, 0x9a, + 0x6a, 0x95, 0x9b, 0x51, 0xad, 0x66, 0x74, 0xf7, 0xaa, 0x2e, 0xfb, 0xbd, 0x05, 0xd5, 0x11, 0xdd, + 0x6e, 0x2e, 0x6f, 0x31, 0x06, 0x19, 0xa6, 0x44, 0x40, 0xba, 0xc2, 0x78, 0xe6, 0xb1, 0x8d, 0xc2, + 0xec, 0x63, 0x1b, 0x69, 0xf2, 0xfd, 0x5c, 0x9a, 0x7c, 0xff, 0x10, 0x16, 0x89, 0x35, 0x39, 0xae, + 0x33, 0x52, 0x5a, 0x33, 0x49, 0x81, 0x0b, 0xc8, 0xa2, 0x08, 0xae, 0xd4, 0x09, 0xa5, 0x72, 0x48, + 0x16, 0x32, 0x2f, 0xb5, 0x8d, 0x84, 0xa6, 0x41, 0x9c, 0x23, 0xd2, 0x34, 0xa2, 0x1a, 0xec, 0xcb, + 0xb8, 0x86, 0xb2, 0x56, 0x03, 0xc1, 0xb1, 0x86, 0x87, 0xb0, 0xc8, 0x2f, 0x43, 0xdf, 0xb6, 0xbc, + 0xb1, 0xfd, 0xc5, 0x04, 0x3d, 0xdd, 0x36, 0xea, 0xf0, 0x15, 0x73, 0x01, 0x13, 0x0e, 0x10, 0xbe, + 0x6d, 0x87, 0xf6, 0xc3, 0x2f, 0xa1, 0xac, 0xdd, 0x7c, 0xcf, 0xd6, 0x60, 0xe9, 0xb3, 0x76, 0xaf, + 0xd3, 0xea, 0x76, 0xad, 0xc3, 0xa3, 0xcd, 0xe7, 0xad, 0xcf, 0xad, 0xdd, 0x66, 0x77, 0xb7, 0x7e, + 0x43, 0x2c, 0xda, 0x4e, 0xab, 0xdb, 0x6b, 0x6d, 0x27, 0xe0, 0x19, 0xf6, 0x06, 0xac, 0x1f, 0x75, + 0x8e, 0xba, 0xad, 0x6d, 0x2b, 0x2d, 0x5f, 0x56, 0x50, 0xa9, 0x4c, 0x4f, 0xc9, 0x9e, 0x7b, 0xf8, + 0x6b, 0x50, 0x4b, 0x1e, 0xfe, 0x66, 0x00, 0x73, 0x7b, 0xad, 0x67, 0xcd, 0xad, 0xcf, 0xe9, 0xba, + 0xd6, 0x6e, 0xaf, 0xd9, 0x6b, 0x6f, 0x59, 0xf2, 0x7a, 0x56, 0xc1, 0x11, 0x32, 0xac, 0x0c, 0xf3, + 0xcd, 0xce, 0xd6, 0xee, 0x81, 0xd9, 0xad, 0x67, 0xd9, 0x6d, 0x58, 0x53, 0xb4, 0xba, 0x75, 0xb0, + 0xbf, 0xdf, 0xee, 0x21, 0x33, 0xec, 0x7d, 0x7e, 0x28, 0x48, 0xf3, 0xa1, 0x0d, 0xa5, 0xf8, 0x7e, + 0x59, 0x64, 0x30, 0xed, 0x5e, 0xbb, 0xd9, 0x8b, 0xb9, 0x6b, 0xfd, 0x86, 0xe0, 0x5f, 0x31, 0x18, + 0xaf, 0x87, 0xad, 0x67, 0xe8, 0x7c, 0x9c, 0x02, 0x52, 0xed, 0xf5, 0xac, 0x58, 0x54, 0x31, 0x74, + 0xf3, 0xa0, 0x27, 0xba, 0xf0, 0x1d, 0xa8, 0x25, 0xa3, 0x20, 0x93, 0x66, 0xeb, 0x75, 0x58, 0xdd, + 0x6c, 0xf5, 0x3e, 0x6b, 0xb5, 0x3a, 0x38, 0x3a, 0x5b, 0xad, 0x4e, 0xcf, 0x6c, 0xee, 0xb5, 0x7b, + 0x9f, 0xd7, 0x33, 0x0f, 0x3f, 0x86, 0xfa, 0xb4, 0xcb, 0x31, 0xe1, 0xa3, 0x7d, 0x99, 0x33, 0xf7, + 0xe1, 0x7f, 0xce, 0xc0, 0x72, 0x9a, 0x55, 0x5d, 0xcc, 0xa1, 0x5c, 0x9c, 0x82, 0x45, 0x77, 0x0f, + 0x3a, 0x56, 0xe7, 0x00, 0xef, 0x83, 0x5c, 0x87, 0xd5, 0xa9, 0x04, 0xc5, 0x09, 0x32, 0xec, 0x16, + 0xac, 0xcd, 0x64, 0xb2, 0xcc, 0x83, 0x23, 0xec, 0x76, 0x03, 0x96, 0xa7, 0x12, 0x5b, 0xa6, 0x79, + 0x60, 0xd6, 0x73, 0xec, 0x3d, 0x78, 0x30, 0x95, 0x32, 0xbb, 0x31, 0xa9, 0x7d, 0x2b, 0xcf, 0xee, + 0xc3, 0x5b, 0x33, 0xd8, 0x31, 0xef, 0xb6, 0x36, 0x9b, 0x7b, 0xa2, 0x7b, 0xf5, 0xc2, 0xc3, 0x7f, + 0x9a, 0x03, 0x88, 0x8f, 0x19, 0x89, 0xfa, 0xb7, 0x9b, 0xbd, 0xe6, 0xde, 0x81, 0x20, 0x2f, 0xf3, + 0xa0, 0x27, 0x4a, 0x37, 0x5b, 0x9f, 0xd4, 0x6f, 0xa4, 0xa6, 0x1c, 0x1c, 0x8a, 0x0e, 0xad, 0xc1, + 0x12, 0x4d, 0xd5, 0x9e, 0xe8, 0x46, 0xbb, 0xf3, 0x8c, 0xae, 0x16, 0xc5, 0xdd, 0xef, 0xe8, 0x70, + 0xc7, 0x3c, 0xe8, 0xf4, 0xac, 0xee, 0xee, 0x51, 0x6f, 0x1b, 0x2f, 0x26, 0xdd, 0x32, 0xdb, 0x87, + 0x54, 0x66, 0xfe, 0x65, 0x08, 0xa2, 0xe8, 0x82, 0x58, 0x0b, 0xcf, 0x0e, 0xba, 0xdd, 0xf6, 0xa1, + 0xf5, 0xc9, 0x51, 0xcb, 0x6c, 0xb7, 0xba, 0x98, 0x71, 0x2e, 0x05, 0x2e, 0xf0, 0xe7, 0xc5, 0x9e, + 0xd9, 0xdb, 0xfb, 0x54, 0x6e, 0x6a, 0x02, 0xb5, 0x98, 0x04, 0x09, 0xac, 0x92, 0x98, 0x1d, 0xb1, + 0x2b, 0xa4, 0x94, 0x0c, 0xd7, 0xa4, 0x89, 0x7c, 0x65, 0xb1, 0xdf, 0xcd, 0x2c, 0x12, 0xcc, 0x56, + 0x49, 0x4f, 0x12, 0xb9, 0x70, 0x2b, 0x8c, 0x04, 0x87, 0xed, 0x6d, 0x13, 0x33, 0xd4, 0x66, 0xa0, + 0x02, 0x77, 0x41, 0x10, 0xa1, 0xd8, 0x36, 0x04, 0x4a, 0x5d, 0x7d, 0x88, 0x94, 0xc5, 0x27, 0xbf, + 0x99, 0x83, 0x1a, 0x1d, 0xf9, 0xa4, 0x07, 0x21, 0xb9, 0xcf, 0xf6, 0x61, 0x5e, 0xbe, 0x2c, 0xca, + 0x56, 0xa2, 0x5b, 0x1f, 0xf5, 0xb7, 0x4c, 0xd7, 0x57, 0xa7, 0xc1, 0x52, 0x4c, 0x5e, 0xfa, 0x2b, + 0x7f, 0xf2, 0xdf, 0xff, 0x4e, 0xb6, 0xca, 0xca, 0x8f, 0xce, 0xdf, 0x7f, 0x74, 0xca, 0xdd, 0x40, + 0x94, 0xf1, 0x2b, 0x00, 0xf1, 0x7b, 0x99, 0xac, 0xa1, 0x5d, 0x33, 0x91, 0x78, 0x29, 0x73, 0xfd, + 0x66, 0x4a, 0x8a, 0x2c, 0xf7, 0x26, 0x96, 0xbb, 0x64, 0xd4, 0x44, 0xb9, 0x8e, 0xeb, 0x84, 0xf4, + 0x76, 0xe6, 0x47, 0x99, 0x87, 0x6c, 0x00, 0x15, 0xfd, 0x25, 0x4b, 0xa6, 0x24, 0xd8, 0x94, 0xb7, + 0x38, 0xd7, 0x6f, 0xa5, 0xa6, 0x29, 0xdd, 0x00, 0xeb, 0x58, 0x31, 0xea, 0xa2, 0x8e, 0x09, 0x62, + 0xc4, 0xb5, 0x0c, 0x49, 0x5b, 0x8a, 0x1f, 0xac, 0x64, 0xb7, 0x35, 0x79, 0x77, 0xe6, 0xb9, 0xcc, + 0xf5, 0x3b, 0xd7, 0xa4, 0xca, 0xba, 0xee, 0x60, 0x5d, 0x6b, 0x06, 0x13, 0x75, 0xf5, 0x11, 0x47, + 0x3d, 0x97, 0xf9, 0x51, 0xe6, 0xe1, 0x93, 0x7f, 0xff, 0x75, 0x28, 0x45, 0x21, 0xe0, 0xec, 0xd7, + 0xa1, 0x9a, 0x38, 0x93, 0xcb, 0x54, 0x37, 0xd2, 0x8e, 0xf0, 0xae, 0xdf, 0x4e, 0x4f, 0x94, 0x15, + 0xbf, 0x81, 0x15, 0x37, 0xd8, 0xaa, 0xa8, 0x58, 0x9e, 0x79, 0x7d, 0x84, 0x67, 0xe8, 0xe9, 0x0e, + 0xcd, 0x17, 0x9a, 0x56, 0x48, 0x95, 0xdd, 0x9e, 0xd6, 0xd4, 0x12, 0xb5, 0xdd, 0xb9, 0x26, 0x55, + 0x56, 0x77, 0x1b, 0xab, 0x5b, 0x65, 0xcb, 0x7a, 0x75, 0x2a, 0x72, 0x98, 0x71, 0xbc, 0xb7, 0x56, + 0x7f, 0xcf, 0x91, 0xdd, 0x89, 0x6f, 0x19, 0x4d, 0x79, 0xe7, 0x31, 0x22, 0x91, 0xd9, 0xc7, 0x1e, + 0x8d, 0x06, 0x56, 0xc5, 0x18, 0x4e, 0x9f, 0xfe, 0x9c, 0x23, 0x3b, 0x86, 0xb2, 0xf6, 0x04, 0x12, + 0xbb, 0x79, 0xed, 0x73, 0x4d, 0xeb, 0xeb, 0x69, 0x49, 0x69, 0x5d, 0xd1, 0xcb, 0x7f, 0x74, 0xc2, + 0x39, 0xfb, 0x65, 0x28, 0x45, 0x0f, 0xeb, 0xb0, 0x35, 0xed, 0xa1, 0x23, 0xfd, 0x21, 0xa0, 0xf5, + 0xc6, 0x6c, 0x42, 0x1a, 0xf1, 0xe9, 0xa5, 0x0b, 0xe2, 0xfb, 0x0c, 0xca, 0xda, 0xe3, 0x39, 0x51, + 0x07, 0x66, 0x1f, 0xe8, 0x89, 0x3a, 0x90, 0xf2, 0xd6, 0x8e, 0xb1, 0x88, 0x55, 0x94, 0x59, 0x09, + 0xe9, 0x3b, 0xbc, 0xf4, 0x02, 0xb6, 0x07, 0x2b, 0x52, 0x03, 0x3e, 0xe6, 0x5f, 0x65, 0x1a, 0x52, + 0x9e, 0xd0, 0x7c, 0x9c, 0x61, 0x1f, 0x43, 0x51, 0xbd, 0x91, 0xc4, 0x56, 0xd3, 0xdf, 0x7a, 0x5a, + 0x5f, 0x9b, 0x81, 0x4b, 0x75, 0xf5, 0x73, 0x80, 0xf8, 0xa5, 0x9e, 0x88, 0x49, 0xcc, 0xbc, 0xfc, + 0x13, 0x51, 0xc0, 0xec, 0xb3, 0x3e, 0xc6, 0x2a, 0x76, 0xb0, 0xce, 0x90, 0x49, 0xb8, 0xfc, 0x42, + 0x5d, 0x2e, 0xfe, 0x43, 0x28, 0x6b, 0x8f, 0xf5, 0x44, 0xc3, 0x37, 0xfb, 0xd0, 0x4f, 0x34, 0x7c, + 0x29, 0x6f, 0xfb, 0x18, 0xeb, 0x58, 0xfa, 0xb2, 0xb1, 0x20, 0x4a, 0x17, 0x22, 0xb0, 0x14, 0x45, + 0xc5, 0x04, 0x9d, 0x41, 0x35, 0xf1, 0x22, 0x4f, 0xb4, 0x42, 0xd3, 0xde, 0xfb, 0x89, 0x56, 0x68, + 0xea, 0x23, 0x3e, 0x8a, 0xce, 0x8c, 0x45, 0x51, 0x0f, 0xdd, 0x2f, 0xa6, 0xd5, 0xf4, 0x03, 0x28, + 0x6b, 0xaf, 0xeb, 0x44, 0x7d, 0x99, 0x7d, 0xc8, 0x27, 0xea, 0x4b, 0xda, 0x63, 0x3c, 0xcb, 0x58, + 0x47, 0xcd, 0x40, 0x52, 0xc0, 0xeb, 0x91, 0x45, 0xd9, 0xbf, 0x0e, 0xb5, 0xe4, 0x83, 0x3b, 0xd1, + 0xda, 0x4f, 0x7d, 0xb9, 0x27, 0x5a, 0xfb, 0xd7, 0xbc, 0xd2, 0x23, 0x49, 0xfa, 0xe1, 0x52, 0x54, + 0xc9, 0xa3, 0x1f, 0xcb, 0xc3, 0x6c, 0x5f, 0xb2, 0x4f, 0x04, 0x83, 0x93, 0xb7, 0x73, 0xb3, 0x35, + 0x8d, 0x6a, 0xf5, 0x6b, 0xbe, 0xa3, 0xf5, 0x32, 0x73, 0x91, 0x77, 0x92, 0x98, 0xb1, 0x70, 0xf6, + 0x0c, 0x96, 0x22, 0x62, 0x8e, 0xae, 0xdb, 0x0e, 0xa2, 0x3e, 0xa4, 0x5e, 0xea, 0xbd, 0x5e, 0x9f, + 0x4e, 0x7d, 0x9c, 0xa1, 0xed, 0x0f, 0x2f, 0x39, 0xd6, 0xb6, 0x3f, 0xfd, 0xc6, 0x6d, 0x6d, 0xfb, + 0x4b, 0xdc, 0x85, 0x3c, 0xbd, 0xfd, 0x85, 0x8e, 0x28, 0xc3, 0x85, 0x85, 0xe9, 0xcb, 0xaf, 0xef, + 0x5c, 0x77, 0x59, 0x08, 0x15, 0xff, 0xc6, 0xcb, 0xef, 0x12, 0x49, 0xb2, 0x22, 0xc5, 0x4d, 0x1f, + 0xc9, 0xd8, 0x29, 0xf6, 0xab, 0x50, 0xd1, 0x1f, 0xe9, 0x60, 0x3a, 0x4f, 0x98, 0xae, 0xe9, 0x56, + 0x6a, 0x5a, 0x92, 0x4a, 0x58, 0x45, 0xaf, 0x86, 0x7d, 0x0a, 0xab, 0xd1, 0x30, 0xeb, 0xb7, 0x5d, + 0x04, 0xec, 0x6e, 0xca, 0x1d, 0x18, 0x89, 0xc1, 0xbe, 0x79, 0xed, 0x25, 0x19, 0x8f, 0x33, 0x82, + 0xfa, 0x92, 0x0f, 0x12, 0xc4, 0x3b, 0x4f, 0xda, 0x3b, 0x0c, 0xf1, 0xce, 0x93, 0xfa, 0x8a, 0x81, + 0xa2, 0x3e, 0xb6, 0x94, 0x18, 0x23, 0x8a, 0x2a, 0x67, 0x3f, 0x80, 0x05, 0xed, 0x2a, 0x8f, 0xee, + 0x95, 0xdb, 0x8f, 0x56, 0xd2, 0xec, 0xb5, 0xb6, 0xeb, 0x69, 0x36, 0x63, 0x63, 0x0d, 0xcb, 0x5f, + 0x34, 0x12, 0x83, 0x23, 0x56, 0xd1, 0x16, 0x94, 0xf5, 0x6b, 0x42, 0x5e, 0x52, 0xee, 0x9a, 0x96, + 0xa4, 0xdf, 0xa0, 0xfa, 0x38, 0xc3, 0xf6, 0xa0, 0x3e, 0x7d, 0xa9, 0x5f, 0xc4, 0x53, 0xd2, 0x2e, + 0x42, 0x5c, 0x9f, 0x4a, 0x4c, 0x5c, 0x05, 0xc8, 0x0e, 0xe9, 0x5c, 0x52, 0xf4, 0xde, 0xa4, 0xe7, + 0x4f, 0xef, 0xea, 0xc9, 0x77, 0x28, 0xa3, 0xd2, 0xd2, 0x5e, 0x20, 0x7d, 0x90, 0x79, 0x9c, 0x61, + 0xbf, 0x9d, 0x81, 0x4a, 0xe2, 0x52, 0xab, 0xc4, 0xc9, 0x8f, 0xa9, 0x7e, 0x36, 0xf4, 0x34, 0xbd, + 0xa3, 0x86, 0x89, 0x83, 0xb8, 0xf7, 0xf0, 0xfb, 0x89, 0x49, 0xfa, 0x71, 0xc2, 0xe5, 0xba, 0x31, + 0xfd, 0x20, 0xe5, 0x97, 0xd3, 0x08, 0xfa, 0x45, 0xc9, 0x5f, 0x3e, 0xce, 0xb0, 0x7f, 0x91, 0x81, + 0x5a, 0x32, 0x96, 0x22, 0xea, 0x6e, 0x6a, 0xd4, 0x46, 0x44, 0x4a, 0xd7, 0x04, 0x60, 0xfc, 0x00, + 0x5b, 0xd9, 0x7b, 0x68, 0x26, 0x5a, 0x29, 0x9f, 0xd2, 0xf8, 0xe9, 0x5a, 0xcb, 0x7e, 0x91, 0xde, + 0x7f, 0x56, 0x91, 0x78, 0x6c, 0xf6, 0xbd, 0xe0, 0x88, 0xfc, 0xf4, 0xd7, 0x75, 0x8d, 0xdc, 0x6f, + 0x64, 0x33, 0x38, 0x13, 0x3f, 0xa4, 0xd7, 0x17, 0x55, 0xd0, 0x95, 0x20, 0xe5, 0xd7, 0x2e, 0xe4, + 0x6d, 0xec, 0xd8, 0x1b, 0xc6, 0xcd, 0x44, 0xc7, 0xa6, 0xa5, 0x8f, 0x26, 0x35, 0x51, 0xbe, 0x90, + 0x1b, 0x6f, 0x9f, 0x33, 0xaf, 0xe6, 0xa6, 0x56, 0x82, 0x8d, 0x1c, 0x51, 0x23, 0x25, 0x7a, 0x62, + 0xbd, 0xbd, 0x66, 0x31, 0xc6, 0x43, 0x6c, 0xeb, 0xdb, 0xc6, 0xdd, 0x6b, 0xdb, 0xfa, 0x08, 0x83, + 0x23, 0x44, 0x8b, 0x0f, 0x01, 0xe2, 0x70, 0x59, 0x36, 0x15, 0xb4, 0x19, 0x71, 0xa1, 0xd9, 0x88, + 0xda, 0xe4, 0xa2, 0x56, 0xb1, 0x9d, 0xa2, 0xc4, 0x5f, 0x26, 0x9e, 0x1a, 0x85, 0x93, 0xea, 0x22, + 0x58, 0x32, 0xb2, 0x35, 0x21, 0x82, 0x4d, 0x97, 0x9f, 0xe0, 0xa8, 0x51, 0xec, 0xe8, 0x11, 0x54, + 0xf7, 0x3c, 0xef, 0xc5, 0x64, 0x1c, 0x1d, 0xd1, 0x48, 0xc6, 0x42, 0xed, 0xda, 0xc1, 0xd9, 0xfa, + 0x54, 0x2f, 0x8c, 0x7b, 0x58, 0xd4, 0x3a, 0x6b, 0x68, 0x45, 0x3d, 0xfa, 0x71, 0x1c, 0xa3, 0xfb, + 0x25, 0xb3, 0x61, 0x31, 0x62, 0xd4, 0x71, 0x1c, 0x6c, 0xb2, 0x98, 0x04, 0x7b, 0x9e, 0xae, 0x22, + 0xa1, 0x2b, 0xa8, 0xd6, 0x3e, 0x0a, 0x54, 0x99, 0x8f, 0x33, 0xec, 0x10, 0x2a, 0xdb, 0xbc, 0x8f, + 0x77, 0x7c, 0x60, 0xdc, 0xcf, 0x52, 0x22, 0x86, 0x84, 0x02, 0x86, 0xd6, 0xab, 0x09, 0x60, 0x72, + 0xf3, 0x1a, 0xdb, 0x57, 0x3e, 0xff, 0xe2, 0xd1, 0x8f, 0x65, 0x44, 0xd1, 0x97, 0x6a, 0xf3, 0x8a, + 0xa3, 0xcb, 0x74, 0x09, 0x20, 0x19, 0xa2, 0x95, 0xd8, 0xbc, 0x66, 0x42, 0xb4, 0x12, 0x43, 0x1d, + 0xc5, 0x92, 0x0d, 0x61, 0x71, 0x26, 0xaa, 0x2b, 0xda, 0xb7, 0xae, 0x8b, 0x05, 0x5b, 0xbf, 0x77, + 0x3d, 0x42, 0xb2, 0xb6, 0x87, 0xc9, 0xda, 0xba, 0x50, 0xa5, 0xab, 0x90, 0x8f, 0x39, 0x9d, 0xf6, + 0x9d, 0xba, 0x2a, 0x4b, 0x3f, 0x4a, 0x3c, 0xbd, 0xcb, 0x60, 0x5a, 0x52, 0xcc, 0xc1, 0xf3, 0x9e, + 0xec, 0x04, 0xdf, 0xff, 0xd0, 0x8e, 0xd7, 0x46, 0xc4, 0x38, 0x7b, 0xe4, 0x37, 0x22, 0xc6, 0x94, + 0xd3, 0xb8, 0x4a, 0x07, 0x65, 0x2b, 0x51, 0xd9, 0x8f, 0x5c, 0x6f, 0xc0, 0x47, 0xb2, 0xd4, 0x5f, + 0x86, 0xf2, 0x33, 0x1e, 0xaa, 0xf3, 0xac, 0x91, 0x40, 0x3f, 0x75, 0xc0, 0x75, 0x3d, 0xe5, 0x14, + 0x72, 0x92, 0x36, 0xa9, 0x64, 0x3e, 0x38, 0xe5, 0xc4, 0x09, 0x2d, 0x67, 0xf0, 0x25, 0xfb, 0x25, + 0x2c, 0x3c, 0xba, 0xbd, 0x61, 0x55, 0x6b, 0xa6, 0x5e, 0xf8, 0xc2, 0x14, 0x3c, 0xad, 0x64, 0xd1, + 0x66, 0x4d, 0xb0, 0x74, 0xa1, 0xac, 0xdd, 0xf2, 0x12, 0x8d, 0xcd, 0xec, 0xad, 0x3e, 0xd1, 0xd8, + 0xa4, 0x5c, 0x0a, 0x63, 0x3c, 0xc0, 0x7a, 0x0c, 0x76, 0x2f, 0xae, 0x87, 0x2e, 0x82, 0x89, 0x6b, + 0x7a, 0xf4, 0x63, 0x7b, 0x14, 0x7e, 0xc9, 0x3e, 0xa3, 0xe9, 0xd0, 0xce, 0xeb, 0xc6, 0x1a, 0xca, + 0xf4, 0xd1, 0xde, 0x68, 0xb0, 0xb4, 0xa4, 0xa4, 0xd6, 0x42, 0x55, 0xa1, 0xd8, 0xf8, 0x14, 0xa0, + 0x1b, 0x7a, 0xe3, 0x6d, 0x9b, 0x8f, 0x3c, 0x37, 0xe6, 0xe9, 0xf1, 0x09, 0xd2, 0x98, 0x4f, 0x6a, + 0xc7, 0x48, 0xd9, 0x67, 0x9a, 0x4a, 0x97, 0x38, 0x69, 0xae, 0x88, 0xf8, 0xda, 0x43, 0xa6, 0xd1, + 0x80, 0xa4, 0x1c, 0x34, 0x7d, 0x9c, 0x61, 0x4d, 0x80, 0x38, 0x7c, 0x30, 0x52, 0xd0, 0x66, 0x22, + 0x13, 0x23, 0xf6, 0x9a, 0x12, 0x6b, 0x78, 0x08, 0xa5, 0x38, 0xee, 0x6a, 0x2d, 0xbe, 0xb4, 0x2a, + 0x11, 0xa5, 0x15, 0x89, 0x0b, 0x33, 0x31, 0x4f, 0x46, 0x1d, 0x87, 0x0a, 0x58, 0x51, 0x0c, 0xd5, + 0x09, 0xe7, 0x01, 0x73, 0x60, 0x89, 0x1a, 0x18, 0xc9, 0x66, 0x78, 0xf2, 0x31, 0x7a, 0x75, 0x67, + 0x36, 0xfc, 0x28, 0xe2, 0x1a, 0xa9, 0x41, 0x34, 0x09, 0x3b, 0x93, 0xa0, 0x56, 0x3a, 0x75, 0x29, + 0xb6, 0x80, 0x11, 0x2c, 0xce, 0xc4, 0x69, 0x44, 0xac, 0xe3, 0xba, 0xc0, 0x9b, 0x88, 0x75, 0x5c, + 0x1b, 0xe2, 0x61, 0xac, 0x60, 0x95, 0x0b, 0x06, 0xa0, 0x5e, 0x79, 0xe1, 0x84, 0xfd, 0x33, 0x51, + 0xdd, 0xef, 0x65, 0x60, 0x29, 0x25, 0x12, 0x83, 0xbd, 0xa9, 0x4c, 0x14, 0xd7, 0x46, 0x69, 0xac, + 0xa7, 0x7a, 0xec, 0x8d, 0x2e, 0xd6, 0xb3, 0xcf, 0x9e, 0x27, 0x36, 0x50, 0x72, 0x98, 0xcb, 0x95, + 0xf9, 0x52, 0x09, 0x26, 0x55, 0x7c, 0xf9, 0x02, 0xd6, 0xa8, 0x21, 0xcd, 0xe1, 0x70, 0x2a, 0x9a, + 0xe0, 0x0d, 0xad, 0x15, 0x29, 0x11, 0x12, 0x09, 0x65, 0x20, 0x19, 0x25, 0x71, 0x8d, 0xec, 0x4e, + 0x4d, 0x65, 0x13, 0xa8, 0x4f, 0x7b, 0xe9, 0xd9, 0xf5, 0x65, 0xad, 0xdf, 0x4d, 0x28, 0xdb, 0x29, + 0x9e, 0xfd, 0xaf, 0x61, 0x65, 0x77, 0x8d, 0xf5, 0xb4, 0x71, 0x21, 0xfd, 0x5b, 0xcc, 0xc7, 0xff, + 0x1f, 0x85, 0x14, 0x4c, 0xf5, 0xf3, 0x6e, 0xf4, 0xce, 0x40, 0x7a, 0x00, 0x44, 0xa4, 0xee, 0xa7, + 0x47, 0x24, 0xbc, 0x83, 0xd5, 0xdf, 0x33, 0x6e, 0xa5, 0x55, 0xef, 0x53, 0x16, 0x52, 0xfc, 0xd7, + 0xa6, 0xd7, 0xb5, 0x6a, 0xc1, 0xbd, 0xb4, 0xf9, 0xbe, 0x56, 0xf1, 0x9a, 0x1a, 0xeb, 0x1b, 0x28, + 0x43, 0x56, 0xf4, 0x10, 0x82, 0x68, 0xf9, 0xa4, 0xc4, 0x2a, 0x44, 0xcb, 0x27, 0x2d, 0xe6, 0x20, + 0x29, 0x3f, 0xa9, 0x68, 0x83, 0x8f, 0x32, 0x0f, 0x37, 0xef, 0xff, 0xe0, 0x6b, 0xa7, 0x4e, 0x78, + 0x36, 0x39, 0xde, 0xe8, 0x7b, 0xa3, 0x47, 0x43, 0x65, 0xda, 0x94, 0xd7, 0x03, 0x3c, 0x1a, 0xba, + 0x83, 0x47, 0x58, 0xec, 0xf1, 0xdc, 0xd8, 0xf7, 0x42, 0xef, 0x9b, 0xff, 0x37, 0x00, 0x00, 0xff, + 0xff, 0x40, 0x26, 0x50, 0x15, 0x6f, 0x8b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 788ad9b688..ca45b3f1bc 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -3053,6 +3053,40 @@ message InvoiceSubscription { uint64 settle_index = 2; } +enum PaymentFailureReason { + /** + Payment isn't failed (yet). + */ + FAILURE_REASON_NONE = 0; + + /** + There are more routes to try, but the payment timeout was exceeded. + */ + FAILURE_REASON_TIMEOUT = 1; + + /** + All possible routes were tried and failed permanently. Or were no + routes to the destination at all. + */ + FAILURE_REASON_NO_ROUTE = 2; + + /** + A non-recoverable error has occured. + */ + FAILURE_REASON_ERROR = 3; + + /** + Payment details incorrect (unknown hash, invalid amt or + invalid final cltv delta) + */ + FAILURE_REASON_INCORRECT_PAYMENT_DETAILS = 4; + + /** + Insufficient local balance. + */ + FAILURE_REASON_INSUFFICIENT_BALANCE = 5; +} + message Payment { /// The payment hash string payment_hash = 1; @@ -3109,6 +3143,8 @@ message Payment { older versions of lnd. */ uint64 payment_index = 15; + + PaymentFailureReason failure_reason = 16; } message HTLCAttempt { diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 4b34cfadfa..f28f5276b7 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -3996,9 +3996,25 @@ "type": "string", "format": "uint64", "description": "*\nThe creation index of this payment. Each payment can be uniquely identified\nby this index, which may not strictly increment by 1 for payments made in\nolder versions of lnd." + }, + "failure_reason": { + "$ref": "#/definitions/lnrpcPaymentFailureReason" } } }, + "lnrpcPaymentFailureReason": { + "type": "string", + "enum": [ + "FAILURE_REASON_NONE", + "FAILURE_REASON_TIMEOUT", + "FAILURE_REASON_NO_ROUTE", + "FAILURE_REASON_ERROR", + "FAILURE_REASON_INCORRECT_PAYMENT_DETAILS", + "FAILURE_REASON_INSUFFICIENT_BALANCE" + ], + "default": "FAILURE_REASON_NONE", + "description": " - FAILURE_REASON_NONE: *\nPayment isn't failed (yet).\n - FAILURE_REASON_TIMEOUT: *\nThere are more routes to try, but the payment timeout was exceeded.\n - FAILURE_REASON_NO_ROUTE: *\nAll possible routes were tried and failed permanently. Or were no\nroutes to the destination at all.\n - FAILURE_REASON_ERROR: *\nA non-recoverable error has occured.\n - FAILURE_REASON_INCORRECT_PAYMENT_DETAILS: *\nPayment details incorrect (unknown hash, invalid amt or\ninvalid final cltv delta)\n - FAILURE_REASON_INSUFFICIENT_BALANCE: *\nInsufficient local balance." + }, "lnrpcPeer": { "type": "object", "properties": { From 278915e598b030638e763c541b71839743cb16cc Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Apr 2020 09:26:52 +0200 Subject: [PATCH 431/562] channeldb: return updated payment on attempt update Similar to what is done for SettleAttempt. Co-authored-by: Johan T. Halseth --- channeldb/payment_control.go | 42 ++++++++++++++++++++----------- channeldb/payment_control_test.go | 38 ++++++++++++++-------------- routing/control_tower.go | 6 +++-- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index ca5b6998b1..1ba8466877 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -186,38 +186,39 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, // RegisterAttempt atomically records the provided HTLCAttemptInfo to the // DB. func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, - attempt *HTLCAttemptInfo) error { + attempt *HTLCAttemptInfo) (*MPPayment, error) { // Serialize the information before opening the db transaction. var a bytes.Buffer err := serializeHTLCAttemptInfo(&a, attempt) if err != nil { - return err + return nil, err } htlcInfoBytes := a.Bytes() htlcIDBytes := make([]byte, 8) binary.BigEndian.PutUint64(htlcIDBytes, attempt.AttemptID) - return kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error { + var payment *MPPayment + err = kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error { bucket, err := fetchPaymentBucketUpdate(tx, paymentHash) if err != nil { return err } - payment, err := fetchPayment(bucket) + p, err := fetchPayment(bucket) if err != nil { return err } // Ensure the payment is in-flight. - if err := ensureInFlight(payment); err != nil { + if err := ensureInFlight(p); err != nil { return err } // We cannot register a new attempt if the payment already has // reached a terminal condition: - settle, fail := payment.TerminalInfo() + settle, fail := p.TerminalInfo() if settle != nil || fail != nil { return ErrPaymentTerminal } @@ -225,7 +226,7 @@ func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, // Make sure any existing shards match the new one with regards // to MPP options. mpp := attempt.Route.FinalHop().MPP - for _, h := range payment.InFlightHTLCs() { + for _, h := range p.InFlightHTLCs() { hMpp := h.Route.FinalHop().MPP switch { @@ -258,13 +259,13 @@ func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, // If this is a non-MPP attempt, it must match the total amount // exactly. amt := attempt.Route.ReceiverAmt() - if mpp == nil && amt != payment.Info.Value { + if mpp == nil && amt != p.Info.Value { return ErrValueMismatch } // Ensure we aren't sending more than the total payment amount. - sentAmt, _ := payment.SentAmt() - if sentAmt+amt > payment.Info.Value { + sentAmt, _ := p.SentAmt() + if sentAmt+amt > p.Info.Value { return ErrValueExceedsAmt } @@ -282,8 +283,20 @@ func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, return err } - return htlcBucket.Put(htlcAttemptInfoKey, htlcInfoBytes) + err = htlcBucket.Put(htlcAttemptInfoKey, htlcInfoBytes) + if err != nil { + return err + } + + // Retrieve attempt info for the notification. + payment, err = fetchPayment(bucket) + return err }) + if err != nil { + return nil, err + } + + return payment, err } // SettleAttempt marks the given attempt settled with the preimage. If this is @@ -307,16 +320,15 @@ func (p *PaymentControl) SettleAttempt(hash lntypes.Hash, // FailAttempt marks the given payment attempt failed. func (p *PaymentControl) FailAttempt(hash lntypes.Hash, - attemptID uint64, failInfo *HTLCFailInfo) error { + attemptID uint64, failInfo *HTLCFailInfo) (*MPPayment, error) { var b bytes.Buffer if err := serializeHTLCFailInfo(&b, failInfo); err != nil { - return err + return nil, err } failBytes := b.Bytes() - _, err := p.updateHtlcKey(hash, attemptID, htlcFailInfoKey, failBytes) - return err + return p.updateHtlcKey(hash, attemptID, htlcFailInfoKey, failBytes) } // updateHtlcKey updates a database key for the specified htlc. diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index abd2722a57..95862f5e29 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -117,13 +117,13 @@ func TestPaymentControlSwitchFail(t *testing.T) { // Record a new attempt. In this test scenario, the attempt fails. // However, this is not communicated to control tower in the current // implementation. It only registers the initiation of the attempt. - err = pControl.RegisterAttempt(info.PaymentHash, attempt) + _, err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to register attempt: %v", err) } htlcReason := HTLCFailUnreadable - err = pControl.FailAttempt( + _, err = pControl.FailAttempt( info.PaymentHash, attempt.AttemptID, &HTLCFailInfo{ Reason: htlcReason, @@ -143,7 +143,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { // Record another attempt. attempt.AttemptID = 1 - err = pControl.RegisterAttempt(info.PaymentHash, attempt) + _, err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) } @@ -236,7 +236,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) { } // Record an attempt. - err = pControl.RegisterAttempt(info.PaymentHash, attempt) + _, err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) } @@ -375,7 +375,7 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { if err != nil { t.Fatalf("unable to send htlc message: %v", err) } - err = pControl.RegisterAttempt(info.PaymentHash, attempt) + _, err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) } @@ -387,7 +387,7 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) { if p.failed { // Fail the payment attempt. htlcFailure := HTLCFailUnreadable - err := pControl.FailAttempt( + _, err := pControl.FailAttempt( info.PaymentHash, attempt.AttemptID, &HTLCFailInfo{ Reason: htlcFailure, @@ -520,7 +520,7 @@ func TestPaymentControlMultiShard(t *testing.T) { a.AttemptID = i attempts = append(attempts, &a) - err = pControl.RegisterAttempt(info.PaymentHash, &a) + _, err = pControl.RegisterAttempt(info.PaymentHash, &a) if err != nil { t.Fatalf("unable to send htlc message: %v", err) } @@ -541,7 +541,7 @@ func TestPaymentControlMultiShard(t *testing.T) { // will be too large. b := *attempt b.AttemptID = 3 - err = pControl.RegisterAttempt(info.PaymentHash, &b) + _, err = pControl.RegisterAttempt(info.PaymentHash, &b) if err != ErrValueExceedsAmt { t.Fatalf("expected ErrValueExceedsAmt, got: %v", err) @@ -550,7 +550,7 @@ func TestPaymentControlMultiShard(t *testing.T) { // Fail the second attempt. a := attempts[1] htlcFail := HTLCFailUnreadable - err = pControl.FailAttempt( + _, err = pControl.FailAttempt( info.PaymentHash, a.AttemptID, &HTLCFailInfo{ Reason: htlcFail, @@ -596,7 +596,7 @@ func TestPaymentControlMultiShard(t *testing.T) { t, pControl, info.PaymentHash, info, nil, htlc, ) } else { - err := pControl.FailAttempt( + _, err := pControl.FailAttempt( info.PaymentHash, a.AttemptID, &HTLCFailInfo{ Reason: htlcFail, @@ -634,7 +634,7 @@ func TestPaymentControlMultiShard(t *testing.T) { // that the payment has reached a terminal condition. b = *attempt b.AttemptID = 3 - err = pControl.RegisterAttempt(info.PaymentHash, &b) + _, err = pControl.RegisterAttempt(info.PaymentHash, &b) if err != ErrPaymentTerminal { t.Fatalf("expected ErrPaymentTerminal, got: %v", err) } @@ -666,7 +666,7 @@ func TestPaymentControlMultiShard(t *testing.T) { ) } else { // Fail the attempt. - err := pControl.FailAttempt( + _, err := pControl.FailAttempt( info.PaymentHash, a.AttemptID, &HTLCFailInfo{ Reason: htlcFail, @@ -708,7 +708,7 @@ func TestPaymentControlMultiShard(t *testing.T) { assertPaymentStatus(t, pControl, info.PaymentHash, finalStatus) // Finally assert we cannot register more attempts. - err = pControl.RegisterAttempt(info.PaymentHash, &b) + _, err = pControl.RegisterAttempt(info.PaymentHash, &b) if err != expRegErr { t.Fatalf("expected error %v, got: %v", expRegErr, err) } @@ -756,7 +756,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) { info.Value, [32]byte{1}, ) - err = pControl.RegisterAttempt(info.PaymentHash, attempt) + _, err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) } @@ -765,7 +765,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) { b := *attempt b.AttemptID = 1 b.Route.FinalHop().MPP = nil - err = pControl.RegisterAttempt(info.PaymentHash, &b) + _, err = pControl.RegisterAttempt(info.PaymentHash, &b) if err != ErrMPPayment { t.Fatalf("expected ErrMPPayment, got: %v", err) } @@ -774,7 +774,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) { b.Route.FinalHop().MPP = record.NewMPP( info.Value, [32]byte{2}, ) - err = pControl.RegisterAttempt(info.PaymentHash, &b) + _, err = pControl.RegisterAttempt(info.PaymentHash, &b) if err != ErrMPPPaymentAddrMismatch { t.Fatalf("expected ErrMPPPaymentAddrMismatch, got: %v", err) } @@ -783,7 +783,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) { b.Route.FinalHop().MPP = record.NewMPP( info.Value/2, [32]byte{1}, ) - err = pControl.RegisterAttempt(info.PaymentHash, &b) + _, err = pControl.RegisterAttempt(info.PaymentHash, &b) if err != ErrMPPTotalAmountMismatch { t.Fatalf("expected ErrMPPTotalAmountMismatch, got: %v", err) } @@ -801,7 +801,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) { } attempt.Route.FinalHop().MPP = nil - err = pControl.RegisterAttempt(info.PaymentHash, attempt) + _, err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) } @@ -813,7 +813,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) { info.Value, [32]byte{1}, ) - err = pControl.RegisterAttempt(info.PaymentHash, &b) + _, err = pControl.RegisterAttempt(info.PaymentHash, &b) if err != ErrNonMPPayment { t.Fatalf("expected ErrNonMPPayment, got: %v", err) } diff --git a/routing/control_tower.go b/routing/control_tower.go index da7d4d2bc2..5702eb92e5 100644 --- a/routing/control_tower.go +++ b/routing/control_tower.go @@ -107,7 +107,8 @@ func (p *controlTower) InitPayment(paymentHash lntypes.Hash, func (p *controlTower) RegisterAttempt(paymentHash lntypes.Hash, attempt *channeldb.HTLCAttemptInfo) error { - return p.db.RegisterAttempt(paymentHash, attempt) + _, err := p.db.RegisterAttempt(paymentHash, attempt) + return err } // SettleAttempt marks the given attempt settled with the preimage. If @@ -133,7 +134,8 @@ func (p *controlTower) SettleAttempt(paymentHash lntypes.Hash, func (p *controlTower) FailAttempt(paymentHash lntypes.Hash, attemptID uint64, failInfo *channeldb.HTLCFailInfo) error { - return p.db.FailAttempt(paymentHash, attemptID, failInfo) + _, err := p.db.FailAttempt(paymentHash, attemptID, failInfo) + return err } // FetchPayment fetches the payment corresponding to the given payment hash. From f907fbcadc1339486ebc50176cc9a9e96a1e30d0 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Apr 2020 14:47:49 +0200 Subject: [PATCH 432/562] queue: detect close of incoming channel --- queue/queue.go | 27 +++++++++++++++++++++++++-- queue/queue_test.go | 22 ++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/queue/queue.go b/queue/queue.go index e3b01b2656..3c0702052e 100644 --- a/queue/queue.go +++ b/queue/queue.go @@ -58,6 +58,7 @@ func (cq *ConcurrentQueue) start() { go func() { defer cq.wg.Done() + readLoop: for { nextElement := cq.overflow.Front() if nextElement == nil { @@ -65,7 +66,10 @@ func (cq *ConcurrentQueue) start() { // directly to the output channel. If output channel is full // though, push to overflow. select { - case item := <-cq.chanIn: + case item, ok := <-cq.chanIn: + if !ok { + break readLoop + } select { case cq.chanOut <- item: // Optimistically push directly to chanOut @@ -79,7 +83,10 @@ func (cq *ConcurrentQueue) start() { // Overflow queue is not empty, so any new items get pushed to // the back to preserve order. select { - case item := <-cq.chanIn: + case item, ok := <-cq.chanIn: + if !ok { + break readLoop + } cq.overflow.PushBack(item) case cq.chanOut <- nextElement.Value: cq.overflow.Remove(nextElement) @@ -88,6 +95,22 @@ func (cq *ConcurrentQueue) start() { } } } + + // Incoming channel has been closed. Empty overflow queue into + // the outgoing channel. + nextElement := cq.overflow.Front() + for nextElement != nil { + select { + case cq.chanOut <- nextElement.Value: + cq.overflow.Remove(nextElement) + case <-cq.quit: + return + } + nextElement = cq.overflow.Front() + } + + // Close outgoing channel. + close(cq.chanOut) }() } diff --git a/queue/queue_test.go b/queue/queue_test.go index 9aee0cfb73..bd74dcc025 100644 --- a/queue/queue_test.go +++ b/queue/queue_test.go @@ -63,3 +63,25 @@ func TestConcurrentQueueIdempotentStop(t *testing.T) { testQueueAddDrain(t, 100, 1, 10, 1000, 1000) } + +// TestQueueCloseIncoming tests that the queue properly handles an incoming +// channel that is closed. +func TestQueueCloseIncoming(t *testing.T) { + t.Parallel() + + queue := queue.NewConcurrentQueue(10) + queue.Start() + + queue.ChanIn() <- 1 + close(queue.ChanIn()) + + item := <-queue.ChanOut() + if item.(int) != 1 { + t.Fatalf("unexpected item") + } + + _, ok := <-queue.ChanOut() + if ok { + t.Fatalf("expected outgoing channel being closed") + } +} From 5bebda8c5df7ae41c38b89e32224fb83579abd43 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Apr 2020 16:27:45 +0200 Subject: [PATCH 433/562] multimutex: add hash mutex --- multimutex/hash_mutex.go | 90 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 multimutex/hash_mutex.go diff --git a/multimutex/hash_mutex.go b/multimutex/hash_mutex.go new file mode 100644 index 0000000000..4a65394d1c --- /dev/null +++ b/multimutex/hash_mutex.go @@ -0,0 +1,90 @@ +package multimutex + +import ( + "fmt" + "sync" + + "github.com/lightningnetwork/lnd/lntypes" +) + +// HashMutex is a struct that keeps track of a set of mutexes with a given hash. +// It can be used for making sure only one goroutine gets given the mutex per +// hash. +type HashMutex struct { + // mutexes is a map of hashes to a cntMutex. The cntMutex for + // a given hash will hold the mutex to be used by all + // callers requesting access for the hash, in addition to + // the count of callers. + mutexes map[lntypes.Hash]*cntMutex + + // mapMtx is used to give synchronize concurrent access + // to the mutexes map. + mapMtx sync.Mutex +} + +// NewHashMutex creates a new Mutex. +func NewHashMutex() *HashMutex { + return &HashMutex{ + mutexes: make(map[lntypes.Hash]*cntMutex), + } +} + +// Lock locks the mutex by the given hash. If the mutex is already +// locked by this hash, Lock blocks until the mutex is available. +func (c *HashMutex) Lock(hash lntypes.Hash) { + c.mapMtx.Lock() + mtx, ok := c.mutexes[hash] + if ok { + // If the mutex already existed in the map, we + // increment its counter, to indicate that there + // now is one more goroutine waiting for it. + mtx.cnt++ + } else { + // If it was not in the map, it means no other + // goroutine has locked the mutex for this hash, + // and we can create a new mutex with count 1 + // and add it to the map. + mtx = &cntMutex{ + cnt: 1, + } + c.mutexes[hash] = mtx + } + c.mapMtx.Unlock() + + // Acquire the mutex for this hash. + mtx.Lock() +} + +// Unlock unlocks the mutex by the given hash. It is a run-time +// error if the mutex is not locked by the hash on entry to Unlock. +func (c *HashMutex) Unlock(hash lntypes.Hash) { + // Since we are done with all the work for this + // update, we update the map to reflect that. + c.mapMtx.Lock() + + mtx, ok := c.mutexes[hash] + if !ok { + // The mutex not existing in the map means + // an unlock for an hash not currently locked + // was attempted. + panic(fmt.Sprintf("double unlock for hash %v", + hash)) + } + + // Decrement the counter. If the count goes to + // zero, it means this caller was the last one + // to wait for the mutex, and we can delete it + // from the map. We can do this safely since we + // are under the mapMtx, meaning that all other + // goroutines waiting for the mutex already + // have incremented it, or will create a new + // mutex when they get the mapMtx. + mtx.cnt-- + if mtx.cnt == 0 { + delete(c.mutexes, hash) + } + c.mapMtx.Unlock() + + // Unlock the mutex for this hash. + mtx.Unlock() +} From af4abe7d58831cfdb342a04e9500611ec7a9ff25 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 3 Apr 2020 17:05:05 +0200 Subject: [PATCH 434/562] routing+routerrpc: notify full payment structures This commit fixes the inconsistency between the payment state as reported by routerrpc.SendPayment/routerrpc.TrackPayment and the main rpc ListPayments call. In addition to that, payment state changes are now sent out for every state change. This opens the door to user interfaces giving more feedback to the user about the payment process. This is especially interesting for multi-part payments. --- cmd/lncli/cmd_pay.go | 8 +- lnrpc/routerrpc/router.pb.go | 452 +++++++++++-------------------- lnrpc/routerrpc/router.proto | 62 +---- lnrpc/routerrpc/router_server.go | 98 ++----- lntest/itest/lnd_test.go | 69 +++-- routing/control_tower.go | 241 ++++++++-------- routing/control_tower_test.go | 67 +++-- routing/mock_test.go | 4 +- 8 files changed, 388 insertions(+), 613 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 3923bee7ea..b251072852 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -393,14 +393,14 @@ func sendPaymentRequest(ctx *cli.Context, return err } - if status.State != routerrpc.PaymentState_IN_FLIGHT { + if status.Status != lnrpc.Payment_IN_FLIGHT { printRespJSON(status) // If we get a payment error back, we pass an error up // to main which eventually calls fatal() and returns // with a non-zero exit code. - if status.State != routerrpc.PaymentState_SUCCEEDED { - return errors.New(status.State.String()) + if status.Status != lnrpc.Payment_SUCCEEDED { + return errors.New(status.Status.String()) } return nil @@ -454,7 +454,7 @@ func trackPayment(ctx *cli.Context) error { printRespJSON(status) - if status.State != routerrpc.PaymentState_IN_FLIGHT { + if status.Status != lnrpc.Payment_IN_FLIGHT { return nil } } diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index c9254c2848..60f70e5e97 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -23,62 +23,6 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package -type PaymentState int32 - -const ( - //* - //Payment is still in flight. - PaymentState_IN_FLIGHT PaymentState = 0 - //* - //Payment completed successfully. - PaymentState_SUCCEEDED PaymentState = 1 - //* - //There are more routes to try, but the payment timeout was exceeded. - PaymentState_FAILED_TIMEOUT PaymentState = 2 - //* - //All possible routes were tried and failed permanently. Or were no - //routes to the destination at all. - PaymentState_FAILED_NO_ROUTE PaymentState = 3 - //* - //A non-recoverable error has occured. - PaymentState_FAILED_ERROR PaymentState = 4 - //* - //Payment details incorrect (unknown hash, invalid amt or - //invalid final cltv delta) - PaymentState_FAILED_INCORRECT_PAYMENT_DETAILS PaymentState = 5 - //* - //Insufficient local balance. - PaymentState_FAILED_INSUFFICIENT_BALANCE PaymentState = 6 -) - -var PaymentState_name = map[int32]string{ - 0: "IN_FLIGHT", - 1: "SUCCEEDED", - 2: "FAILED_TIMEOUT", - 3: "FAILED_NO_ROUTE", - 4: "FAILED_ERROR", - 5: "FAILED_INCORRECT_PAYMENT_DETAILS", - 6: "FAILED_INSUFFICIENT_BALANCE", -} - -var PaymentState_value = map[string]int32{ - "IN_FLIGHT": 0, - "SUCCEEDED": 1, - "FAILED_TIMEOUT": 2, - "FAILED_NO_ROUTE": 3, - "FAILED_ERROR": 4, - "FAILED_INCORRECT_PAYMENT_DETAILS": 5, - "FAILED_INSUFFICIENT_BALANCE": 6, -} - -func (x PaymentState) String() string { - return proto.EnumName(PaymentState_name, int32(x)) -} - -func (PaymentState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{0} -} - type FailureDetail int32 const ( @@ -164,7 +108,7 @@ func (x FailureDetail) String() string { } func (FailureDetail) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{1} + return fileDescriptor_7a0613f69d37b0a5, []int{0} } type HtlcEvent_EventType int32 @@ -195,7 +139,7 @@ func (x HtlcEvent_EventType) String() string { } func (HtlcEvent_EventType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{18, 0} + return fileDescriptor_7a0613f69d37b0a5, []int{17, 0} } type SendPaymentRequest struct { @@ -460,66 +404,6 @@ func (m *TrackPaymentRequest) GetPaymentHash() []byte { return nil } -type PaymentStatus struct { - /// Current state the payment is in. - State PaymentState `protobuf:"varint,1,opt,name=state,proto3,enum=routerrpc.PaymentState" json:"state,omitempty"` - //* - //The pre-image of the payment when state is SUCCEEDED. - Preimage []byte `protobuf:"bytes,2,opt,name=preimage,proto3" json:"preimage,omitempty"` - //* - //The HTLCs made in attempt to settle the payment. - Htlcs []*lnrpc.HTLCAttempt `protobuf:"bytes,4,rep,name=htlcs,proto3" json:"htlcs,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PaymentStatus) Reset() { *m = PaymentStatus{} } -func (m *PaymentStatus) String() string { return proto.CompactTextString(m) } -func (*PaymentStatus) ProtoMessage() {} -func (*PaymentStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{2} -} - -func (m *PaymentStatus) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PaymentStatus.Unmarshal(m, b) -} -func (m *PaymentStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PaymentStatus.Marshal(b, m, deterministic) -} -func (m *PaymentStatus) XXX_Merge(src proto.Message) { - xxx_messageInfo_PaymentStatus.Merge(m, src) -} -func (m *PaymentStatus) XXX_Size() int { - return xxx_messageInfo_PaymentStatus.Size(m) -} -func (m *PaymentStatus) XXX_DiscardUnknown() { - xxx_messageInfo_PaymentStatus.DiscardUnknown(m) -} - -var xxx_messageInfo_PaymentStatus proto.InternalMessageInfo - -func (m *PaymentStatus) GetState() PaymentState { - if m != nil { - return m.State - } - return PaymentState_IN_FLIGHT -} - -func (m *PaymentStatus) GetPreimage() []byte { - if m != nil { - return m.Preimage - } - return nil -} - -func (m *PaymentStatus) GetHtlcs() []*lnrpc.HTLCAttempt { - if m != nil { - return m.Htlcs - } - return nil -} - type RouteFeeRequest struct { //* //The destination once wishes to obtain a routing fee quote to. @@ -536,7 +420,7 @@ func (m *RouteFeeRequest) Reset() { *m = RouteFeeRequest{} } func (m *RouteFeeRequest) String() string { return proto.CompactTextString(m) } func (*RouteFeeRequest) ProtoMessage() {} func (*RouteFeeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{3} + return fileDescriptor_7a0613f69d37b0a5, []int{2} } func (m *RouteFeeRequest) XXX_Unmarshal(b []byte) error { @@ -590,7 +474,7 @@ func (m *RouteFeeResponse) Reset() { *m = RouteFeeResponse{} } func (m *RouteFeeResponse) String() string { return proto.CompactTextString(m) } func (*RouteFeeResponse) ProtoMessage() {} func (*RouteFeeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{4} + return fileDescriptor_7a0613f69d37b0a5, []int{3} } func (m *RouteFeeResponse) XXX_Unmarshal(b []byte) error { @@ -639,7 +523,7 @@ func (m *SendToRouteRequest) Reset() { *m = SendToRouteRequest{} } func (m *SendToRouteRequest) String() string { return proto.CompactTextString(m) } func (*SendToRouteRequest) ProtoMessage() {} func (*SendToRouteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{5} + return fileDescriptor_7a0613f69d37b0a5, []int{4} } func (m *SendToRouteRequest) XXX_Unmarshal(b []byte) error { @@ -688,7 +572,7 @@ func (m *SendToRouteResponse) Reset() { *m = SendToRouteResponse{} } func (m *SendToRouteResponse) String() string { return proto.CompactTextString(m) } func (*SendToRouteResponse) ProtoMessage() {} func (*SendToRouteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{6} + return fileDescriptor_7a0613f69d37b0a5, []int{5} } func (m *SendToRouteResponse) XXX_Unmarshal(b []byte) error { @@ -733,7 +617,7 @@ func (m *ResetMissionControlRequest) Reset() { *m = ResetMissionControlR func (m *ResetMissionControlRequest) String() string { return proto.CompactTextString(m) } func (*ResetMissionControlRequest) ProtoMessage() {} func (*ResetMissionControlRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{7} + return fileDescriptor_7a0613f69d37b0a5, []int{6} } func (m *ResetMissionControlRequest) XXX_Unmarshal(b []byte) error { @@ -764,7 +648,7 @@ func (m *ResetMissionControlResponse) Reset() { *m = ResetMissionControl func (m *ResetMissionControlResponse) String() string { return proto.CompactTextString(m) } func (*ResetMissionControlResponse) ProtoMessage() {} func (*ResetMissionControlResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{8} + return fileDescriptor_7a0613f69d37b0a5, []int{7} } func (m *ResetMissionControlResponse) XXX_Unmarshal(b []byte) error { @@ -795,7 +679,7 @@ func (m *QueryMissionControlRequest) Reset() { *m = QueryMissionControlR func (m *QueryMissionControlRequest) String() string { return proto.CompactTextString(m) } func (*QueryMissionControlRequest) ProtoMessage() {} func (*QueryMissionControlRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{9} + return fileDescriptor_7a0613f69d37b0a5, []int{8} } func (m *QueryMissionControlRequest) XXX_Unmarshal(b []byte) error { @@ -829,7 +713,7 @@ func (m *QueryMissionControlResponse) Reset() { *m = QueryMissionControl func (m *QueryMissionControlResponse) String() string { return proto.CompactTextString(m) } func (*QueryMissionControlResponse) ProtoMessage() {} func (*QueryMissionControlResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{10} + return fileDescriptor_7a0613f69d37b0a5, []int{9} } func (m *QueryMissionControlResponse) XXX_Unmarshal(b []byte) error { @@ -873,7 +757,7 @@ func (m *PairHistory) Reset() { *m = PairHistory{} } func (m *PairHistory) String() string { return proto.CompactTextString(m) } func (*PairHistory) ProtoMessage() {} func (*PairHistory) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{11} + return fileDescriptor_7a0613f69d37b0a5, []int{10} } func (m *PairHistory) XXX_Unmarshal(b []byte) error { @@ -941,7 +825,7 @@ func (m *PairData) Reset() { *m = PairData{} } func (m *PairData) String() string { return proto.CompactTextString(m) } func (*PairData) ProtoMessage() {} func (*PairData) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{12} + return fileDescriptor_7a0613f69d37b0a5, []int{11} } func (m *PairData) XXX_Unmarshal(b []byte) error { @@ -1020,7 +904,7 @@ func (m *QueryProbabilityRequest) Reset() { *m = QueryProbabilityRequest func (m *QueryProbabilityRequest) String() string { return proto.CompactTextString(m) } func (*QueryProbabilityRequest) ProtoMessage() {} func (*QueryProbabilityRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{13} + return fileDescriptor_7a0613f69d37b0a5, []int{12} } func (m *QueryProbabilityRequest) XXX_Unmarshal(b []byte) error { @@ -1076,7 +960,7 @@ func (m *QueryProbabilityResponse) Reset() { *m = QueryProbabilityRespon func (m *QueryProbabilityResponse) String() string { return proto.CompactTextString(m) } func (*QueryProbabilityResponse) ProtoMessage() {} func (*QueryProbabilityResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{14} + return fileDescriptor_7a0613f69d37b0a5, []int{13} } func (m *QueryProbabilityResponse) XXX_Unmarshal(b []byte) error { @@ -1137,7 +1021,7 @@ func (m *BuildRouteRequest) Reset() { *m = BuildRouteRequest{} } func (m *BuildRouteRequest) String() string { return proto.CompactTextString(m) } func (*BuildRouteRequest) ProtoMessage() {} func (*BuildRouteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{15} + return fileDescriptor_7a0613f69d37b0a5, []int{14} } func (m *BuildRouteRequest) XXX_Unmarshal(b []byte) error { @@ -1199,7 +1083,7 @@ func (m *BuildRouteResponse) Reset() { *m = BuildRouteResponse{} } func (m *BuildRouteResponse) String() string { return proto.CompactTextString(m) } func (*BuildRouteResponse) ProtoMessage() {} func (*BuildRouteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{16} + return fileDescriptor_7a0613f69d37b0a5, []int{15} } func (m *BuildRouteResponse) XXX_Unmarshal(b []byte) error { @@ -1237,7 +1121,7 @@ func (m *SubscribeHtlcEventsRequest) Reset() { *m = SubscribeHtlcEventsR func (m *SubscribeHtlcEventsRequest) String() string { return proto.CompactTextString(m) } func (*SubscribeHtlcEventsRequest) ProtoMessage() {} func (*SubscribeHtlcEventsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{17} + return fileDescriptor_7a0613f69d37b0a5, []int{16} } func (m *SubscribeHtlcEventsRequest) XXX_Unmarshal(b []byte) error { @@ -1304,7 +1188,7 @@ func (m *HtlcEvent) Reset() { *m = HtlcEvent{} } func (m *HtlcEvent) String() string { return proto.CompactTextString(m) } func (*HtlcEvent) ProtoMessage() {} func (*HtlcEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{18} + return fileDescriptor_7a0613f69d37b0a5, []int{17} } func (m *HtlcEvent) XXX_Unmarshal(b []byte) error { @@ -1458,7 +1342,7 @@ func (m *HtlcInfo) Reset() { *m = HtlcInfo{} } func (m *HtlcInfo) String() string { return proto.CompactTextString(m) } func (*HtlcInfo) ProtoMessage() {} func (*HtlcInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{19} + return fileDescriptor_7a0613f69d37b0a5, []int{18} } func (m *HtlcInfo) XXX_Unmarshal(b []byte) error { @@ -1519,7 +1403,7 @@ func (m *ForwardEvent) Reset() { *m = ForwardEvent{} } func (m *ForwardEvent) String() string { return proto.CompactTextString(m) } func (*ForwardEvent) ProtoMessage() {} func (*ForwardEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{20} + return fileDescriptor_7a0613f69d37b0a5, []int{19} } func (m *ForwardEvent) XXX_Unmarshal(b []byte) error { @@ -1557,7 +1441,7 @@ func (m *ForwardFailEvent) Reset() { *m = ForwardFailEvent{} } func (m *ForwardFailEvent) String() string { return proto.CompactTextString(m) } func (*ForwardFailEvent) ProtoMessage() {} func (*ForwardFailEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{21} + return fileDescriptor_7a0613f69d37b0a5, []int{20} } func (m *ForwardFailEvent) XXX_Unmarshal(b []byte) error { @@ -1588,7 +1472,7 @@ func (m *SettleEvent) Reset() { *m = SettleEvent{} } func (m *SettleEvent) String() string { return proto.CompactTextString(m) } func (*SettleEvent) ProtoMessage() {} func (*SettleEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{22} + return fileDescriptor_7a0613f69d37b0a5, []int{21} } func (m *SettleEvent) XXX_Unmarshal(b []byte) error { @@ -1630,7 +1514,7 @@ func (m *LinkFailEvent) Reset() { *m = LinkFailEvent{} } func (m *LinkFailEvent) String() string { return proto.CompactTextString(m) } func (*LinkFailEvent) ProtoMessage() {} func (*LinkFailEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_7a0613f69d37b0a5, []int{23} + return fileDescriptor_7a0613f69d37b0a5, []int{22} } func (m *LinkFailEvent) XXX_Unmarshal(b []byte) error { @@ -1680,13 +1564,11 @@ func (m *LinkFailEvent) GetFailureString() string { } func init() { - proto.RegisterEnum("routerrpc.PaymentState", PaymentState_name, PaymentState_value) proto.RegisterEnum("routerrpc.FailureDetail", FailureDetail_name, FailureDetail_value) proto.RegisterEnum("routerrpc.HtlcEvent_EventType", HtlcEvent_EventType_name, HtlcEvent_EventType_value) proto.RegisterType((*SendPaymentRequest)(nil), "routerrpc.SendPaymentRequest") proto.RegisterMapType((map[uint64][]byte)(nil), "routerrpc.SendPaymentRequest.DestCustomRecordsEntry") proto.RegisterType((*TrackPaymentRequest)(nil), "routerrpc.TrackPaymentRequest") - proto.RegisterType((*PaymentStatus)(nil), "routerrpc.PaymentStatus") proto.RegisterType((*RouteFeeRequest)(nil), "routerrpc.RouteFeeRequest") proto.RegisterType((*RouteFeeResponse)(nil), "routerrpc.RouteFeeResponse") proto.RegisterType((*SendToRouteRequest)(nil), "routerrpc.SendToRouteRequest") @@ -1713,142 +1595,134 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2150 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xdd, 0x72, 0xdb, 0xb8, - 0x15, 0x0e, 0x6d, 0xca, 0x96, 0x8e, 0x7e, 0x4c, 0x43, 0x59, 0x47, 0x95, 0x93, 0x5d, 0x2d, 0xbb, - 0x9b, 0x68, 0xd2, 0xac, 0x9d, 0x75, 0x3b, 0x6d, 0xa6, 0xed, 0x6e, 0x47, 0x96, 0xe8, 0x88, 0x8e, - 0x4c, 0x6a, 0x21, 0x3a, 0x3f, 0xcd, 0x05, 0x86, 0x96, 0x20, 0x8b, 0x35, 0x45, 0xaa, 0x24, 0x94, - 0x8c, 0x2f, 0x3b, 0xbd, 0xeb, 0x8b, 0xf4, 0xae, 0x4f, 0xd0, 0x77, 0xe9, 0x6d, 0x9f, 0xa0, 0xd3, - 0xcb, 0x1d, 0x80, 0xa0, 0x44, 0xd9, 0x72, 0x76, 0x6f, 0x12, 0xf1, 0x3b, 0x1f, 0x0e, 0xce, 0x39, - 0xf8, 0x80, 0x03, 0x18, 0xf6, 0xa2, 0x70, 0xce, 0x68, 0x14, 0xcd, 0x86, 0x87, 0xc9, 0xaf, 0x83, - 0x59, 0x14, 0xb2, 0x10, 0x15, 0x16, 0x78, 0xbd, 0x10, 0xcd, 0x86, 0x09, 0xaa, 0xff, 0x3f, 0x07, - 0x68, 0x40, 0x83, 0x51, 0xdf, 0xbd, 0x9e, 0xd2, 0x80, 0x61, 0xfa, 0xd7, 0x39, 0x8d, 0x19, 0x42, - 0xa0, 0x8e, 0x68, 0xcc, 0x6a, 0x4a, 0x43, 0x69, 0x96, 0xb0, 0xf8, 0x8d, 0x34, 0xd8, 0x74, 0xa7, - 0xac, 0xb6, 0xd1, 0x50, 0x9a, 0x9b, 0x98, 0xff, 0x44, 0xbf, 0x80, 0xbc, 0x3b, 0x65, 0x64, 0x1a, - 0xbb, 0xac, 0x56, 0x12, 0xf0, 0xb6, 0x3b, 0x65, 0x67, 0xb1, 0xcb, 0xd0, 0x97, 0x50, 0x9a, 0x25, - 0x2e, 0xc9, 0xc4, 0x8d, 0x27, 0xb5, 0x4d, 0xe1, 0xa8, 0x28, 0xb1, 0xae, 0x1b, 0x4f, 0x50, 0x13, - 0xb4, 0xb1, 0x17, 0xb8, 0x3e, 0x19, 0xfa, 0xec, 0x03, 0x19, 0x51, 0x9f, 0xb9, 0x35, 0xb5, 0xa1, - 0x34, 0x73, 0xb8, 0x22, 0xf0, 0xb6, 0xcf, 0x3e, 0x74, 0x38, 0x8a, 0x9e, 0xc0, 0x4e, 0xea, 0x2c, - 0x4a, 0x02, 0xac, 0xe5, 0x1a, 0x4a, 0xb3, 0x80, 0x2b, 0xb3, 0xd5, 0xb0, 0x9f, 0xc0, 0x0e, 0xf3, - 0xa6, 0x34, 0x9c, 0x33, 0x12, 0xd3, 0x61, 0x18, 0x8c, 0xe2, 0xda, 0x56, 0xe2, 0x51, 0xc2, 0x83, - 0x04, 0x45, 0x3a, 0x94, 0xc7, 0x94, 0x12, 0xdf, 0x9b, 0x7a, 0x8c, 0xf0, 0xf0, 0xb7, 0x45, 0xf8, - 0xc5, 0x31, 0xa5, 0x3d, 0x8e, 0x0d, 0x5c, 0x86, 0xbe, 0x82, 0xca, 0x92, 0x23, 0x72, 0x2c, 0x0b, - 0x52, 0x29, 0x25, 0x89, 0x44, 0x9f, 0x81, 0x16, 0xce, 0xd9, 0x65, 0xe8, 0x05, 0x97, 0x64, 0x38, - 0x71, 0x03, 0xe2, 0x8d, 0x6a, 0xf9, 0x86, 0xd2, 0x54, 0x8f, 0x37, 0x9e, 0x2b, 0xb8, 0x92, 0xda, - 0xda, 0x13, 0x37, 0x30, 0x47, 0xe8, 0x31, 0xec, 0xf8, 0x6e, 0xcc, 0xc8, 0x24, 0x9c, 0x91, 0xd9, - 0xfc, 0xe2, 0x8a, 0x5e, 0xd7, 0x2a, 0xa2, 0x32, 0x65, 0x0e, 0x77, 0xc3, 0x59, 0x5f, 0x80, 0xe8, - 0x11, 0x80, 0xa8, 0x8a, 0x98, 0xbc, 0x56, 0x10, 0x39, 0x14, 0x38, 0x22, 0x26, 0x46, 0xdf, 0x42, - 0x51, 0xac, 0x26, 0x99, 0x78, 0x01, 0x8b, 0x6b, 0xd0, 0xd8, 0x6c, 0x16, 0x8f, 0xb4, 0x03, 0x3f, - 0xe0, 0x0b, 0x8b, 0xb9, 0xa5, 0xeb, 0x05, 0x0c, 0x43, 0x94, 0xfe, 0x8c, 0xd1, 0x08, 0xaa, 0x7c, - 0x15, 0xc9, 0x70, 0x1e, 0xb3, 0x70, 0x4a, 0x22, 0x3a, 0x0c, 0xa3, 0x51, 0x5c, 0x2b, 0x8a, 0xa1, - 0xbf, 0x39, 0x58, 0x88, 0xe3, 0xe0, 0xb6, 0x1a, 0x0e, 0x3a, 0x34, 0x66, 0x6d, 0x31, 0x0e, 0x27, - 0xc3, 0x8c, 0x80, 0x45, 0xd7, 0x78, 0x77, 0x74, 0x13, 0x47, 0xcf, 0x00, 0xb9, 0xbe, 0x1f, 0x7e, - 0x24, 0x31, 0xf5, 0xc7, 0x44, 0xae, 0x4e, 0x6d, 0xa7, 0xa1, 0x34, 0xf3, 0x58, 0x13, 0x96, 0x01, - 0xf5, 0xc7, 0xd2, 0x3d, 0xfa, 0x2d, 0x94, 0x45, 0x4c, 0x63, 0xea, 0xb2, 0x79, 0x44, 0xe3, 0x9a, - 0xd6, 0xd8, 0x6c, 0x56, 0x8e, 0x76, 0x65, 0x22, 0x27, 0x09, 0x7c, 0xec, 0x31, 0x5c, 0xe2, 0x3c, - 0xf9, 0x1d, 0xd7, 0x3b, 0xb0, 0xb7, 0x3e, 0x24, 0xae, 0x51, 0x5e, 0x53, 0x2e, 0x5b, 0x15, 0xf3, - 0x9f, 0xe8, 0x3e, 0xe4, 0x3e, 0xb8, 0xfe, 0x9c, 0x0a, 0xdd, 0x96, 0x70, 0xf2, 0xf1, 0xfb, 0x8d, - 0x17, 0x8a, 0xfe, 0x02, 0xaa, 0x4e, 0xe4, 0x0e, 0xaf, 0x6e, 0x48, 0xff, 0xa6, 0x72, 0x95, 0x5b, - 0xca, 0xd5, 0xff, 0xa1, 0x40, 0x59, 0x8e, 0x1a, 0x30, 0x97, 0xcd, 0x63, 0xf4, 0x0d, 0xe4, 0x62, - 0xe6, 0x32, 0x2a, 0xd8, 0x95, 0xa3, 0x07, 0x99, 0x7a, 0x66, 0x88, 0x14, 0x27, 0x2c, 0x54, 0x87, - 0xfc, 0x2c, 0xa2, 0xde, 0xd4, 0xbd, 0x4c, 0xe3, 0x5a, 0x7c, 0xa3, 0x26, 0xe4, 0x26, 0xcc, 0x1f, - 0xc6, 0x35, 0x55, 0x2c, 0x0d, 0x92, 0xc5, 0xe8, 0x3a, 0xbd, 0x76, 0x8b, 0x31, 0x3a, 0x9d, 0x31, - 0x9c, 0x10, 0x4e, 0xd5, 0xfc, 0xa6, 0xa6, 0xea, 0xdf, 0xc3, 0x8e, 0x58, 0xf1, 0x13, 0x4a, 0x3f, - 0xb5, 0x7b, 0x1f, 0x00, 0xdf, 0x9b, 0x42, 0xeb, 0xc9, 0x0e, 0xde, 0x72, 0xa7, 0x5c, 0xe6, 0xfa, - 0x08, 0xb4, 0xe5, 0xf8, 0x78, 0x16, 0x06, 0x31, 0x8f, 0x41, 0xe3, 0x09, 0x70, 0x4d, 0xf3, 0x2d, - 0x20, 0xc4, 0xaf, 0x88, 0x51, 0x15, 0x89, 0x9f, 0x50, 0x2a, 0xe4, 0xff, 0x38, 0xd9, 0x71, 0xc4, - 0x0f, 0x87, 0x57, 0x7c, 0x0f, 0xbb, 0xd7, 0xd2, 0x7d, 0x99, 0xc3, 0xbd, 0x70, 0x78, 0xd5, 0xe1, - 0xa0, 0xfe, 0x3e, 0x39, 0x66, 0x9c, 0x50, 0xcc, 0xf5, 0xf3, 0x6b, 0x8d, 0x74, 0xc8, 0x89, 0x5a, - 0x0a, 0xb7, 0xc5, 0xa3, 0x52, 0x56, 0xe4, 0x38, 0x31, 0xe9, 0xef, 0xa1, 0xba, 0xe2, 0x5c, 0x66, - 0x91, 0xad, 0xb2, 0x72, 0xab, 0xca, 0xdb, 0x63, 0xd7, 0xf3, 0xe7, 0x51, 0xea, 0xb8, 0x92, 0x8a, - 0x2e, 0x41, 0x71, 0x6a, 0xd6, 0x1f, 0x42, 0x1d, 0xd3, 0x98, 0xb2, 0x33, 0x2f, 0x8e, 0xbd, 0x30, - 0x68, 0x87, 0x01, 0x8b, 0x42, 0x5f, 0x66, 0xa0, 0x3f, 0x82, 0xfd, 0xb5, 0xd6, 0x24, 0x04, 0x3e, - 0xf8, 0x87, 0x39, 0x8d, 0xae, 0xd7, 0x0f, 0xfe, 0x01, 0xf6, 0xd7, 0x5a, 0x65, 0xfc, 0xcf, 0x20, - 0x37, 0x73, 0xbd, 0x28, 0xae, 0x6d, 0x08, 0x25, 0xec, 0xad, 0x88, 0xca, 0x8b, 0xba, 0x5e, 0xcc, - 0xc2, 0xe8, 0x1a, 0x27, 0xa4, 0x53, 0x35, 0xaf, 0x68, 0x1b, 0x5c, 0x9a, 0xc5, 0x8c, 0x11, 0xed, - 0x43, 0x21, 0x08, 0x47, 0x94, 0x8c, 0xa3, 0x70, 0x9a, 0x16, 0x81, 0x03, 0x27, 0x51, 0x38, 0xe5, - 0x9a, 0x10, 0x46, 0x16, 0x4a, 0x15, 0x6e, 0xf1, 0x4f, 0x27, 0x44, 0xdf, 0xc0, 0xf6, 0x24, 0x71, - 0x20, 0x0e, 0xc6, 0xe2, 0x51, 0xf5, 0xc6, 0xdc, 0x1d, 0x97, 0xb9, 0x38, 0xe5, 0x24, 0x42, 0x3c, - 0x55, 0xf3, 0xaa, 0x96, 0x3b, 0x55, 0xf3, 0x39, 0x6d, 0xeb, 0x54, 0xcd, 0x6f, 0x69, 0xdb, 0xfa, - 0x7f, 0x15, 0xc8, 0xa7, 0x6c, 0x1e, 0x09, 0x2f, 0x29, 0xe1, 0xba, 0x90, 0x62, 0xca, 0x73, 0xc0, - 0xf1, 0xa6, 0x14, 0x35, 0xa0, 0x24, 0x8c, 0xab, 0x12, 0x05, 0x8e, 0xb5, 0x84, 0x4c, 0xc5, 0x89, - 0x9d, 0x32, 0x84, 0x1e, 0x55, 0x79, 0x62, 0x27, 0x94, 0xb4, 0xe9, 0xc4, 0xf3, 0xe1, 0x90, 0xc6, - 0x71, 0x32, 0x4b, 0x2e, 0xa1, 0x48, 0x4c, 0x4c, 0xf4, 0x18, 0x76, 0x52, 0x4a, 0x3a, 0xd7, 0x56, - 0xa2, 0x57, 0x09, 0xcb, 0xe9, 0x9a, 0xa0, 0x65, 0x79, 0xd3, 0x65, 0x8f, 0xa8, 0x2c, 0x89, 0x7c, - 0x52, 0xb9, 0x0b, 0xff, 0x02, 0x0f, 0xc4, 0x52, 0xf6, 0xa3, 0xf0, 0xc2, 0xbd, 0xf0, 0x7c, 0x8f, - 0x5d, 0xa7, 0x22, 0xe7, 0x89, 0x47, 0xe1, 0x94, 0xf0, 0xda, 0xa6, 0x4b, 0xc0, 0x01, 0x2b, 0x1c, - 0x51, 0xbe, 0x04, 0x2c, 0x4c, 0x4c, 0x72, 0x09, 0x58, 0x28, 0x0c, 0xd9, 0xde, 0xba, 0xb9, 0xd2, - 0x5b, 0xf5, 0x2b, 0xa8, 0xdd, 0x9e, 0x4b, 0x6a, 0xa6, 0x01, 0xc5, 0xd9, 0x12, 0x16, 0xd3, 0x29, - 0x38, 0x0b, 0x65, 0xd7, 0x76, 0xe3, 0xa7, 0xd7, 0x56, 0xff, 0xa7, 0x02, 0xbb, 0xc7, 0x73, 0xcf, - 0x1f, 0xad, 0x6c, 0xdc, 0x6c, 0x74, 0xca, 0x6a, 0xe7, 0x5f, 0xd7, 0xd6, 0x37, 0xd6, 0xb6, 0xf5, - 0x75, 0xad, 0x73, 0xf3, 0xce, 0xd6, 0xf9, 0x05, 0x14, 0x97, 0x5d, 0x33, 0x39, 0x1d, 0x4b, 0x18, - 0x26, 0x69, 0xcb, 0x8c, 0xf5, 0x17, 0x80, 0xb2, 0x81, 0xca, 0x82, 0x2c, 0xce, 0x0f, 0xe5, 0xee, - 0xf3, 0xe3, 0x21, 0xd4, 0x07, 0xf3, 0x8b, 0x78, 0x18, 0x79, 0x17, 0xb4, 0xcb, 0xfc, 0xa1, 0xf1, - 0x81, 0x06, 0x2c, 0x4e, 0x77, 0xe9, 0xff, 0x54, 0x28, 0x2c, 0x50, 0x74, 0x00, 0x55, 0x2f, 0x18, - 0x86, 0xd3, 0x34, 0xe8, 0x80, 0xfa, 0x3c, 0xee, 0xa4, 0xe3, 0xec, 0xa6, 0xa6, 0x76, 0x62, 0x31, - 0x47, 0x9c, 0xbf, 0x92, 0xa4, 0xe4, 0x6f, 0x24, 0xfc, 0x6c, 0x8e, 0x09, 0xbf, 0x09, 0xda, 0xc2, - 0x3f, 0x3f, 0xe6, 0x17, 0x45, 0xc1, 0x95, 0x14, 0xe7, 0xc1, 0x24, 0xcc, 0x85, 0xe7, 0x94, 0xa9, - 0x26, 0xcc, 0x14, 0x97, 0xcc, 0x2f, 0xa1, 0xc4, 0xf7, 0x43, 0xcc, 0xdc, 0xe9, 0x8c, 0x04, 0xb1, - 0xd8, 0x17, 0x2a, 0x2e, 0x2e, 0x30, 0x2b, 0x46, 0xdf, 0x01, 0x50, 0x9e, 0x1f, 0x61, 0xd7, 0x33, - 0x2a, 0xb6, 0x44, 0xe5, 0xe8, 0xf3, 0x8c, 0x30, 0x16, 0x05, 0x38, 0x10, 0xff, 0x3a, 0xd7, 0x33, - 0x8a, 0x0b, 0x34, 0xfd, 0x89, 0xbe, 0x87, 0xf2, 0x38, 0x8c, 0x3e, 0xba, 0xd1, 0x88, 0x08, 0x50, - 0x1e, 0x1b, 0xd9, 0x3e, 0x78, 0x92, 0xd8, 0xc5, 0xf0, 0xee, 0x3d, 0x5c, 0x1a, 0x67, 0xbe, 0xd1, - 0x2b, 0x40, 0xe9, 0x78, 0xb1, 0xcb, 0x13, 0x27, 0x79, 0xe1, 0x64, 0xff, 0xb6, 0x13, 0x7e, 0x48, - 0xa7, 0x8e, 0xb4, 0xf1, 0x0d, 0x0c, 0xfd, 0x01, 0x4a, 0x31, 0x65, 0xcc, 0xa7, 0xd2, 0x4d, 0x41, - 0xb8, 0xd9, 0x5b, 0xb9, 0xe3, 0x70, 0x73, 0xea, 0xa1, 0x18, 0x2f, 0x3f, 0xd1, 0x31, 0xec, 0xf8, - 0x5e, 0x70, 0x95, 0x0d, 0x03, 0xc4, 0xf8, 0x5a, 0x66, 0x7c, 0xcf, 0x0b, 0xae, 0xb2, 0x31, 0x94, - 0xfd, 0x2c, 0xa0, 0xff, 0x11, 0x0a, 0x8b, 0x2a, 0xa1, 0x22, 0x6c, 0x9f, 0x5b, 0xaf, 0x2c, 0xfb, - 0x8d, 0xa5, 0xdd, 0x43, 0x79, 0x50, 0x07, 0x86, 0xd5, 0xd1, 0x14, 0x0e, 0x63, 0xa3, 0x6d, 0x98, - 0xaf, 0x0d, 0x6d, 0x83, 0x7f, 0x9c, 0xd8, 0xf8, 0x4d, 0x0b, 0x77, 0xb4, 0xcd, 0xe3, 0x6d, 0xc8, - 0x89, 0x79, 0xf5, 0x7f, 0x2b, 0x90, 0x17, 0x2b, 0x18, 0x8c, 0x43, 0xf4, 0x2b, 0x58, 0x88, 0x4b, - 0x1c, 0x6e, 0xbc, 0xe1, 0x0a, 0xd5, 0x95, 0xf1, 0x42, 0x30, 0x8e, 0xc4, 0x39, 0x79, 0x21, 0x8d, - 0x05, 0x79, 0x23, 0x21, 0xa7, 0x86, 0x05, 0xf9, 0x69, 0xc6, 0xf3, 0xca, 0x91, 0xa3, 0xe2, 0x9d, - 0xd4, 0x90, 0x9e, 0xb0, 0x4f, 0x33, 0x8e, 0x57, 0x4e, 0x62, 0x15, 0xef, 0xa4, 0x06, 0xc9, 0xd5, - 0x7f, 0x07, 0xa5, 0xec, 0x9a, 0xa3, 0x27, 0xa0, 0x7a, 0xc1, 0x38, 0x94, 0x1b, 0xb1, 0x7a, 0x43, - 0x5c, 0x3c, 0x49, 0x2c, 0x08, 0x3a, 0x02, 0xed, 0xe6, 0x3a, 0xeb, 0x65, 0x28, 0x66, 0x16, 0x4d, - 0xff, 0x8f, 0x02, 0xe5, 0x95, 0x45, 0xf8, 0xd9, 0xde, 0xd1, 0x77, 0x50, 0xfa, 0xe8, 0x45, 0x94, - 0x64, 0xdb, 0x7f, 0xe5, 0xa8, 0xbe, 0xda, 0xfe, 0xd3, 0xff, 0xdb, 0xe1, 0x88, 0xe2, 0x22, 0xe7, - 0x4b, 0x00, 0xfd, 0x09, 0x2a, 0x72, 0x24, 0x19, 0x51, 0xe6, 0x7a, 0xbe, 0x28, 0x55, 0x65, 0x45, - 0x1e, 0x92, 0xdb, 0x11, 0x76, 0x5c, 0x1e, 0x67, 0x3f, 0xd1, 0xd7, 0x4b, 0x07, 0x31, 0x8b, 0xbc, - 0xe0, 0x52, 0xd4, 0xaf, 0xb0, 0xa0, 0x0d, 0x04, 0xf8, 0xf4, 0x5f, 0x0a, 0x94, 0xb2, 0x57, 0x47, - 0x54, 0x86, 0x82, 0x69, 0x91, 0x93, 0x9e, 0xf9, 0xb2, 0xeb, 0x68, 0xf7, 0xf8, 0xe7, 0xe0, 0xbc, - 0xdd, 0x36, 0x8c, 0x8e, 0xc1, 0xe5, 0x84, 0xa0, 0x72, 0xd2, 0x32, 0x7b, 0x46, 0x87, 0x38, 0xe6, - 0x99, 0x61, 0x9f, 0x3b, 0xda, 0x06, 0xaa, 0xc2, 0x8e, 0xc4, 0x2c, 0x9b, 0x60, 0xfb, 0xdc, 0x31, - 0xb4, 0x4d, 0xa4, 0x41, 0x49, 0x82, 0x06, 0xc6, 0x36, 0xd6, 0x54, 0xf4, 0x15, 0x34, 0x24, 0x62, - 0x5a, 0x6d, 0x1b, 0x63, 0xa3, 0xed, 0x90, 0x7e, 0xeb, 0xdd, 0x99, 0x61, 0x39, 0xa4, 0x63, 0x38, - 0x2d, 0xb3, 0x37, 0xd0, 0x72, 0xe8, 0x0b, 0xd8, 0x5f, 0xb0, 0x06, 0xe7, 0x27, 0x27, 0x66, 0xdb, - 0xe4, 0x84, 0xe3, 0x56, 0xaf, 0x65, 0xb5, 0x0d, 0x6d, 0xeb, 0xe9, 0xdf, 0x54, 0x28, 0xaf, 0x24, - 0xbe, 0xaa, 0xfc, 0x32, 0x14, 0x2c, 0x5b, 0xfa, 0xd3, 0x14, 0x1e, 0x86, 0x6d, 0x99, 0xb6, 0x45, - 0x3a, 0x46, 0xdb, 0xee, 0xf0, 0x3d, 0xf0, 0x19, 0xec, 0xf6, 0x4c, 0xeb, 0x15, 0xb1, 0x6c, 0x87, - 0x18, 0x3d, 0xf3, 0xa5, 0x79, 0xdc, 0xe3, 0xf1, 0xde, 0x07, 0xcd, 0xb6, 0x48, 0xbb, 0xdb, 0x32, - 0xad, 0x45, 0x6a, 0x2a, 0x47, 0xf9, 0x85, 0x98, 0x18, 0x6f, 0x79, 0x05, 0x06, 0xe4, 0xac, 0xf5, - 0x56, 0xcb, 0xa1, 0x1a, 0xdc, 0x5f, 0x1f, 0x1c, 0xda, 0x03, 0xc4, 0x93, 0x3b, 0xeb, 0xf7, 0x0c, - 0xc7, 0x20, 0xe9, 0x5e, 0xdb, 0xe6, 0x25, 0x12, 0x7e, 0x5a, 0x9d, 0x0e, 0x49, 0xd2, 0xd3, 0xf2, - 0x3c, 0x12, 0xc9, 0x18, 0x90, 0x8e, 0x39, 0x68, 0x1d, 0x73, 0xb8, 0xc0, 0xe7, 0x34, 0xad, 0xd7, - 0xb6, 0xd9, 0x36, 0x48, 0x9b, 0xbb, 0xe5, 0x28, 0x70, 0x72, 0x8a, 0x9e, 0x5b, 0x1d, 0x03, 0xf7, - 0x5b, 0x66, 0x47, 0x2b, 0xa2, 0x7d, 0x78, 0x90, 0xc2, 0xc6, 0xdb, 0xbe, 0x89, 0xdf, 0x11, 0xc7, - 0xb6, 0xc9, 0xc0, 0xb6, 0x2d, 0xad, 0x94, 0xf5, 0xc4, 0xb3, 0xb5, 0xfb, 0x86, 0xa5, 0x95, 0xd1, - 0x03, 0xa8, 0x9e, 0xf5, 0xfb, 0x24, 0xb5, 0xa4, 0xc9, 0x56, 0x38, 0xbd, 0xd5, 0xe9, 0x60, 0x63, - 0x30, 0x20, 0x67, 0xe6, 0xe0, 0xac, 0xe5, 0xb4, 0xbb, 0xda, 0x0e, 0x4f, 0x69, 0x60, 0x38, 0xc4, - 0xb1, 0x9d, 0x56, 0x6f, 0x89, 0x6b, 0x3c, 0xa0, 0x25, 0xce, 0x27, 0xed, 0xd9, 0x6f, 0xb4, 0x5d, - 0x5e, 0x70, 0x0e, 0xdb, 0xaf, 0x65, 0x88, 0x88, 0xe7, 0x2e, 0x97, 0x27, 0x9d, 0x53, 0xab, 0x72, - 0xd0, 0xb4, 0x5e, 0xb7, 0x7a, 0x66, 0x87, 0xbc, 0x32, 0xde, 0x89, 0xb3, 0xea, 0x3e, 0x07, 0x93, - 0xc8, 0x48, 0x1f, 0xdb, 0x2f, 0x79, 0x20, 0xda, 0x67, 0x5c, 0x71, 0x6d, 0x13, 0xb7, 0xcf, 0x7b, - 0x2d, 0x2c, 0xc5, 0xb5, 0x77, 0xf4, 0xf7, 0x2d, 0xd8, 0x12, 0x9d, 0x35, 0x42, 0x5d, 0xbe, 0x61, - 0x17, 0x2f, 0x49, 0xf4, 0xe8, 0x93, 0x2f, 0xcc, 0x7a, 0x6d, 0xfd, 0x83, 0x69, 0x1e, 0x3f, 0x57, - 0xd0, 0x29, 0x94, 0xb2, 0xef, 0x34, 0x94, 0x6d, 0x4b, 0x6b, 0x1e, 0x70, 0x9f, 0xf4, 0xf5, 0x0a, - 0x34, 0x23, 0x66, 0xde, 0x94, 0xbf, 0xc5, 0xe4, 0xa3, 0x07, 0xd5, 0x33, 0xfc, 0x1b, 0x2f, 0xa9, - 0xfa, 0xfe, 0x5a, 0x9b, 0xbc, 0x5a, 0xf4, 0x92, 0x14, 0xe5, 0xb3, 0xe3, 0x56, 0x8a, 0xab, 0x6f, - 0x9d, 0xfa, 0xe7, 0x77, 0x99, 0xa5, 0xb7, 0x11, 0x54, 0xd7, 0xbc, 0x24, 0xd0, 0xd7, 0xd9, 0x08, - 0xee, 0x7c, 0x87, 0xd4, 0x1f, 0xff, 0x14, 0x6d, 0x39, 0xcb, 0x9a, 0x27, 0xc7, 0xca, 0x2c, 0x77, - 0x3f, 0x58, 0x56, 0x66, 0xf9, 0xd4, 0xcb, 0xe5, 0x3d, 0x68, 0x37, 0x6f, 0xa8, 0x48, 0xbf, 0x39, - 0xf6, 0xf6, 0x55, 0xb9, 0xfe, 0xcb, 0x4f, 0x72, 0xa4, 0x73, 0x13, 0x60, 0x79, 0xcf, 0x43, 0x0f, - 0x33, 0x43, 0x6e, 0xdd, 0x53, 0xeb, 0x8f, 0xee, 0xb0, 0x4a, 0x57, 0x0e, 0x54, 0xd7, 0x5c, 0xfc, - 0x56, 0xaa, 0x71, 0xf7, 0xc5, 0xb0, 0x7e, 0x7f, 0xdd, 0xfd, 0xe8, 0xb9, 0x72, 0xfc, 0xed, 0x9f, - 0x0f, 0x2f, 0x3d, 0x36, 0x99, 0x5f, 0x1c, 0x0c, 0xc3, 0xe9, 0xa1, 0xef, 0x5d, 0x4e, 0x58, 0xe0, - 0x05, 0x97, 0x01, 0x65, 0x1f, 0xc3, 0xe8, 0xea, 0xd0, 0x0f, 0x46, 0x87, 0xa2, 0xd9, 0x1c, 0x2e, - 0x86, 0x5f, 0x6c, 0x89, 0xbf, 0xc6, 0xfd, 0xfa, 0xc7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x84, - 0xd2, 0x59, 0xbd, 0x13, 0x00, 0x00, + // 2017 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0x5d, 0x77, 0xdb, 0x48, + 0x19, 0x5e, 0xc5, 0x72, 0x62, 0xbf, 0xfe, 0x52, 0xc6, 0xdd, 0xd4, 0x38, 0xed, 0xe2, 0x15, 0x6c, + 0xeb, 0x53, 0x4a, 0xd2, 0x0d, 0x1c, 0xe8, 0x01, 0xb6, 0xe0, 0x58, 0xca, 0x46, 0x8d, 0x23, 0x79, + 0xc7, 0x4e, 0xdb, 0xa5, 0x17, 0x73, 0x14, 0x7b, 0x1c, 0x8b, 0xc8, 0x92, 0x91, 0xc6, 0xed, 0xc9, + 0x25, 0xb7, 0xfc, 0x11, 0xfe, 0x04, 0xff, 0x85, 0x5b, 0xee, 0xb8, 0xe3, 0x70, 0xc9, 0x99, 0x91, + 0xc6, 0x96, 0x13, 0xa7, 0xbb, 0x37, 0x89, 0xf4, 0xbc, 0xcf, 0xbc, 0x1f, 0xf3, 0x3e, 0xf3, 0x21, + 0xc3, 0x5e, 0x14, 0x2e, 0x18, 0x8d, 0xa2, 0xf9, 0xe8, 0x30, 0x79, 0x3a, 0x98, 0x47, 0x21, 0x0b, + 0x51, 0x71, 0x89, 0x37, 0x8b, 0xd1, 0x7c, 0x94, 0xa0, 0xfa, 0xff, 0xf2, 0x80, 0x06, 0x34, 0x18, + 0xf7, 0xdd, 0x9b, 0x19, 0x0d, 0x18, 0xa6, 0x7f, 0x5d, 0xd0, 0x98, 0x21, 0x04, 0xea, 0x98, 0xc6, + 0xac, 0xa1, 0xb4, 0x94, 0x76, 0x19, 0x8b, 0x67, 0xa4, 0x41, 0xce, 0x9d, 0xb1, 0xc6, 0x56, 0x4b, + 0x69, 0xe7, 0x30, 0x7f, 0x44, 0x3f, 0x81, 0x82, 0x3b, 0x63, 0x64, 0x16, 0xbb, 0xac, 0x51, 0x16, + 0xf0, 0x8e, 0x3b, 0x63, 0xe7, 0xb1, 0xcb, 0xd0, 0x97, 0x50, 0x9e, 0x27, 0x2e, 0xc9, 0xd4, 0x8d, + 0xa7, 0x8d, 0x9c, 0x70, 0x54, 0x4a, 0xb1, 0x53, 0x37, 0x9e, 0xa2, 0x36, 0x68, 0x13, 0x2f, 0x70, + 0x7d, 0x32, 0xf2, 0xd9, 0x07, 0x32, 0xa6, 0x3e, 0x73, 0x1b, 0x6a, 0x4b, 0x69, 0xe7, 0x71, 0x55, + 0xe0, 0x5d, 0x9f, 0x7d, 0x30, 0x38, 0x8a, 0x9e, 0x42, 0x4d, 0x3a, 0x8b, 0x92, 0x04, 0x1b, 0xf9, + 0x96, 0xd2, 0x2e, 0xe2, 0xea, 0x7c, 0x3d, 0xed, 0xa7, 0x50, 0x63, 0xde, 0x8c, 0x86, 0x0b, 0x46, + 0x62, 0x3a, 0x0a, 0x83, 0x71, 0xdc, 0xd8, 0x4e, 0x3c, 0xa6, 0xf0, 0x20, 0x41, 0x91, 0x0e, 0x95, + 0x09, 0xa5, 0xc4, 0xf7, 0x66, 0x1e, 0x23, 0x3c, 0xfd, 0x1d, 0x91, 0x7e, 0x69, 0x42, 0x69, 0x8f, + 0x63, 0x03, 0x97, 0xa1, 0x9f, 0x43, 0x75, 0xc5, 0x11, 0x35, 0x56, 0x04, 0xa9, 0x2c, 0x49, 0xa2, + 0xd0, 0xe7, 0xa0, 0x85, 0x0b, 0x76, 0x15, 0x7a, 0xc1, 0x15, 0x19, 0x4d, 0xdd, 0x80, 0x78, 0xe3, + 0x46, 0xa1, 0xa5, 0xb4, 0xd5, 0xe3, 0xad, 0x17, 0x0a, 0xae, 0x4a, 0x5b, 0x77, 0xea, 0x06, 0xd6, + 0x18, 0x3d, 0x81, 0x9a, 0xef, 0xc6, 0x8c, 0x4c, 0xc3, 0x39, 0x99, 0x2f, 0x2e, 0xaf, 0xe9, 0x4d, + 0xa3, 0x2a, 0x66, 0xa6, 0xc2, 0xe1, 0xd3, 0x70, 0xde, 0x17, 0x20, 0x7a, 0x0c, 0x20, 0x66, 0x45, + 0x04, 0x6f, 0x14, 0x45, 0x0d, 0x45, 0x8e, 0x88, 0xc0, 0xe8, 0x6b, 0x28, 0x89, 0x6e, 0x92, 0xa9, + 0x17, 0xb0, 0xb8, 0x01, 0xad, 0x5c, 0xbb, 0x74, 0xa4, 0x1d, 0xf8, 0x01, 0x6f, 0x2c, 0xe6, 0x96, + 0x53, 0x2f, 0x60, 0x18, 0x22, 0xf9, 0x18, 0xa3, 0x31, 0xd4, 0x79, 0x17, 0xc9, 0x68, 0x11, 0xb3, + 0x70, 0x46, 0x22, 0x3a, 0x0a, 0xa3, 0x71, 0xdc, 0x28, 0x89, 0xa1, 0xbf, 0x3e, 0x58, 0x8a, 0xe3, + 0xe0, 0xae, 0x1a, 0x0e, 0x0c, 0x1a, 0xb3, 0xae, 0x18, 0x87, 0x93, 0x61, 0x66, 0xc0, 0xa2, 0x1b, + 0xbc, 0x3b, 0xbe, 0x8d, 0xa3, 0xe7, 0x80, 0x5c, 0xdf, 0x0f, 0x3f, 0x92, 0x98, 0xfa, 0x13, 0x92, + 0x76, 0xa7, 0x51, 0x6b, 0x29, 0xed, 0x02, 0xd6, 0x84, 0x65, 0x40, 0xfd, 0x49, 0xea, 0x1e, 0xfd, + 0x06, 0x2a, 0x22, 0xa7, 0x09, 0x75, 0xd9, 0x22, 0xa2, 0x71, 0x43, 0x6b, 0xe5, 0xda, 0xd5, 0xa3, + 0xdd, 0xb4, 0x90, 0x93, 0x04, 0x3e, 0xf6, 0x18, 0x2e, 0x73, 0x5e, 0xfa, 0x1e, 0x37, 0x0d, 0xd8, + 0xdb, 0x9c, 0x12, 0xd7, 0x28, 0x9f, 0x53, 0x2e, 0x5b, 0x15, 0xf3, 0x47, 0xf4, 0x00, 0xf2, 0x1f, + 0x5c, 0x7f, 0x41, 0x85, 0x6e, 0xcb, 0x38, 0x79, 0xf9, 0xdd, 0xd6, 0x4b, 0x45, 0x7f, 0x09, 0xf5, + 0x61, 0xe4, 0x8e, 0xae, 0x6f, 0x49, 0xff, 0xb6, 0x72, 0x95, 0x3b, 0xca, 0xd5, 0x5f, 0x41, 0x4d, + 0x4c, 0xf2, 0x09, 0xa5, 0x9f, 0x5a, 0x30, 0x0f, 0x81, 0x2f, 0x07, 0x21, 0xaf, 0x64, 0xd1, 0x6c, + 0xbb, 0x33, 0xae, 0x2c, 0x7d, 0x0c, 0xda, 0x6a, 0x7c, 0x3c, 0x0f, 0x83, 0x98, 0xf2, 0xd5, 0xc0, + 0x7b, 0xc0, 0x65, 0xc4, 0x55, 0x27, 0xf4, 0xa6, 0x88, 0x51, 0xd5, 0x14, 0x3f, 0xa1, 0x54, 0x28, + 0xee, 0x49, 0x22, 0x72, 0xe2, 0x87, 0xa3, 0x6b, 0xbe, 0x6c, 0xdc, 0x9b, 0xd4, 0x7d, 0x85, 0xc3, + 0xbd, 0x70, 0x74, 0x6d, 0x70, 0x50, 0x7f, 0x9f, 0xac, 0xec, 0x61, 0x28, 0x62, 0xfd, 0xf8, 0xf2, + 0x90, 0x0e, 0x79, 0x21, 0x07, 0xe1, 0xb6, 0x74, 0x54, 0xce, 0xea, 0x0a, 0x27, 0x26, 0xfd, 0x3d, + 0xd4, 0xd7, 0x9c, 0xa7, 0x55, 0x34, 0xa1, 0x30, 0x8f, 0xa8, 0x37, 0x73, 0xaf, 0x68, 0xea, 0x79, + 0xf9, 0x8e, 0xda, 0xb0, 0x33, 0x71, 0x3d, 0x7f, 0x11, 0x49, 0xc7, 0x55, 0xd9, 0xe7, 0x04, 0xc5, + 0xd2, 0xac, 0x3f, 0x82, 0x26, 0xa6, 0x31, 0x65, 0xe7, 0x5e, 0x1c, 0x7b, 0x61, 0xd0, 0x0d, 0x03, + 0x16, 0x85, 0x7e, 0x5a, 0x81, 0xfe, 0x18, 0xf6, 0x37, 0x5a, 0x93, 0x14, 0xf8, 0xe0, 0xef, 0x16, + 0x34, 0xba, 0xd9, 0x3c, 0xf8, 0x3b, 0xd8, 0xdf, 0x68, 0x4d, 0xf3, 0x7f, 0x0e, 0xf9, 0xb9, 0xeb, + 0x45, 0x71, 0x63, 0x4b, 0xac, 0x8b, 0xbd, 0xcc, 0xba, 0xe8, 0xbb, 0x5e, 0x74, 0xea, 0xc5, 0x2c, + 0x8c, 0x6e, 0x70, 0x42, 0x7a, 0xad, 0x16, 0x14, 0x6d, 0x4b, 0xff, 0xbb, 0x02, 0xa5, 0x8c, 0x11, + 0xed, 0x43, 0x31, 0x08, 0xc7, 0x94, 0x4c, 0xa2, 0x70, 0x26, 0x27, 0x81, 0x03, 0x27, 0x51, 0x38, + 0xe3, 0x9a, 0x10, 0x46, 0x16, 0xa6, 0x82, 0xdc, 0xe6, 0xaf, 0xc3, 0x10, 0xfd, 0x12, 0x76, 0xa6, + 0x89, 0x03, 0xb1, 0x17, 0x95, 0x8e, 0xea, 0xb7, 0x62, 0x1b, 0x2e, 0x73, 0xb1, 0xe4, 0xbc, 0x56, + 0x0b, 0x39, 0x4d, 0x7d, 0xad, 0x16, 0x54, 0x2d, 0xff, 0x5a, 0x2d, 0xe4, 0xb5, 0xed, 0xd7, 0x6a, + 0x61, 0x5b, 0xdb, 0xd1, 0xff, 0xad, 0x40, 0x41, 0xb2, 0x79, 0x26, 0x7c, 0x4a, 0x09, 0xd7, 0x45, + 0x2a, 0xa6, 0x02, 0x07, 0x86, 0xde, 0x8c, 0xa2, 0x16, 0x94, 0x85, 0x71, 0x5d, 0xa2, 0xc0, 0xb1, + 0x8e, 0x90, 0xa9, 0xd8, 0x24, 0x25, 0x43, 0xe8, 0x51, 0x4d, 0x37, 0xc9, 0x84, 0x22, 0xf7, 0xf9, + 0x78, 0x31, 0x1a, 0xd1, 0x38, 0x4e, 0xa2, 0xe4, 0x13, 0x4a, 0x8a, 0x89, 0x40, 0x4f, 0xa0, 0x26, + 0x29, 0x32, 0xd6, 0x76, 0xa2, 0xd7, 0x14, 0x4e, 0xc3, 0xb5, 0x41, 0xcb, 0xf2, 0x66, 0xab, 0x6d, + 0xb9, 0xba, 0x22, 0xf2, 0xa0, 0x49, 0xf1, 0xfa, 0x5f, 0xe0, 0xa1, 0x68, 0x65, 0x3f, 0x0a, 0x2f, + 0xdd, 0x4b, 0xcf, 0xf7, 0xd8, 0x8d, 0x14, 0x39, 0x2f, 0x3c, 0x0a, 0x67, 0x84, 0xcf, 0xad, 0x6c, + 0x01, 0x07, 0xec, 0x70, 0x4c, 0x79, 0x0b, 0x58, 0x98, 0x98, 0xd2, 0x16, 0xb0, 0x50, 0x18, 0xb2, + 0xc7, 0x59, 0x6e, 0xed, 0x38, 0xd3, 0xaf, 0xa1, 0x71, 0x37, 0x56, 0xaa, 0x99, 0x16, 0x94, 0xe6, + 0x2b, 0x58, 0x84, 0x53, 0x70, 0x16, 0xca, 0xf6, 0x76, 0xeb, 0x87, 0x7b, 0xab, 0xff, 0x43, 0x81, + 0xdd, 0xe3, 0x85, 0xe7, 0x8f, 0xd7, 0x16, 0x6e, 0x36, 0x3b, 0x65, 0xfd, 0xb0, 0xdd, 0x74, 0x92, + 0x6e, 0x6d, 0x3c, 0x49, 0x37, 0x9d, 0x56, 0xb9, 0x7b, 0x4f, 0xab, 0x9f, 0x42, 0x69, 0x75, 0x50, + 0xc5, 0x0d, 0xb5, 0x95, 0x6b, 0x97, 0x31, 0x4c, 0xe5, 0x29, 0x15, 0xeb, 0x2f, 0x01, 0x65, 0x13, + 0x4d, 0x27, 0x64, 0xb9, 0x7f, 0x28, 0xf7, 0xef, 0x1f, 0x8f, 0xa0, 0x39, 0x58, 0x5c, 0xc6, 0xa3, + 0xc8, 0xbb, 0xa4, 0xa7, 0xcc, 0x1f, 0x99, 0x1f, 0x68, 0xc0, 0x62, 0xb9, 0x4a, 0xff, 0xab, 0x42, + 0x71, 0x89, 0xa2, 0x03, 0xa8, 0x7b, 0xc1, 0x28, 0x9c, 0xc9, 0xa4, 0x03, 0xea, 0xf3, 0xbc, 0x93, + 0x4d, 0x7e, 0x57, 0x9a, 0xba, 0x89, 0xc5, 0x1a, 0x73, 0xfe, 0x5a, 0x91, 0x29, 0x7f, 0x2b, 0xe1, + 0x67, 0x6b, 0x4c, 0xf8, 0x6d, 0xd0, 0x96, 0xfe, 0xa7, 0xcc, 0x1f, 0x2d, 0x27, 0x05, 0x57, 0x25, + 0xce, 0x93, 0x49, 0x98, 0x4b, 0xcf, 0x92, 0xa9, 0x26, 0x4c, 0x89, 0xa7, 0xcc, 0x2f, 0xa1, 0xcc, + 0xd7, 0x43, 0xcc, 0xdc, 0xd9, 0x9c, 0x04, 0xb1, 0x58, 0x17, 0x2a, 0x2e, 0x2d, 0x31, 0x3b, 0x46, + 0xdf, 0x00, 0x50, 0x5e, 0x1f, 0x61, 0x37, 0x73, 0x2a, 0x96, 0x44, 0xf5, 0xe8, 0x8b, 0x8c, 0x30, + 0x96, 0x13, 0x70, 0x20, 0xfe, 0x0e, 0x6f, 0xe6, 0x14, 0x17, 0xa9, 0x7c, 0x44, 0xaf, 0xa0, 0x32, + 0x09, 0xa3, 0x8f, 0x6e, 0x34, 0x26, 0x02, 0x4c, 0xb7, 0x8d, 0x87, 0x19, 0x0f, 0x27, 0x89, 0x5d, + 0x0c, 0x3f, 0xfd, 0x0c, 0x97, 0x27, 0x99, 0x77, 0x74, 0x06, 0x48, 0x8e, 0x17, 0xab, 0x3c, 0x71, + 0x52, 0x10, 0x4e, 0xf6, 0xef, 0x3a, 0xe1, 0x9b, 0xb4, 0x74, 0xa4, 0x4d, 0x6e, 0x61, 0xe8, 0xf7, + 0x50, 0x8e, 0x29, 0x63, 0x3e, 0x4d, 0xdd, 0x14, 0x85, 0x9b, 0xbd, 0xb5, 0x6b, 0x05, 0x37, 0x4b, + 0x0f, 0xa5, 0x78, 0xf5, 0x8a, 0x8e, 0xa1, 0xe6, 0x7b, 0xc1, 0x75, 0x36, 0x0d, 0x10, 0xe3, 0x1b, + 0x99, 0xf1, 0x3d, 0x2f, 0xb8, 0xce, 0xe6, 0x50, 0xf1, 0xb3, 0x80, 0xfe, 0x07, 0x28, 0x2e, 0x67, + 0x09, 0x95, 0x60, 0xe7, 0xc2, 0x3e, 0xb3, 0x9d, 0xb7, 0xb6, 0xf6, 0x19, 0x2a, 0x80, 0x3a, 0x30, + 0x6d, 0x43, 0x53, 0x38, 0x8c, 0xcd, 0xae, 0x69, 0xbd, 0x31, 0xb5, 0x2d, 0xfe, 0x72, 0xe2, 0xe0, + 0xb7, 0x1d, 0x6c, 0x68, 0xb9, 0xe3, 0x1d, 0xc8, 0x8b, 0xb8, 0xfa, 0x3f, 0x15, 0x28, 0x88, 0x0e, + 0x06, 0x93, 0x10, 0xfd, 0x02, 0x96, 0xe2, 0x12, 0x9b, 0x1b, 0x3f, 0x70, 0x85, 0xea, 0x2a, 0x78, + 0x29, 0x98, 0x61, 0x8a, 0x73, 0xf2, 0x52, 0x1a, 0x4b, 0xf2, 0x56, 0x42, 0x96, 0x86, 0x25, 0xf9, + 0x59, 0xc6, 0xf3, 0xda, 0x96, 0xa3, 0xe2, 0x9a, 0x34, 0xc8, 0x1d, 0xf6, 0x59, 0xc6, 0xf1, 0xda, + 0x4e, 0xac, 0xe2, 0x9a, 0x34, 0xa4, 0x5c, 0xfd, 0xb7, 0x50, 0xce, 0xf6, 0x1c, 0x3d, 0x05, 0xd5, + 0x0b, 0x26, 0x61, 0xba, 0x10, 0xeb, 0xb7, 0xc4, 0xc5, 0x8b, 0xc4, 0x82, 0xa0, 0x23, 0xd0, 0x6e, + 0xf7, 0x59, 0xaf, 0x40, 0x29, 0xd3, 0x34, 0xfd, 0x5f, 0x0a, 0x54, 0xd6, 0x9a, 0xf0, 0xa3, 0xbd, + 0xa3, 0x6f, 0xa0, 0xfc, 0xd1, 0x8b, 0x28, 0xc9, 0x1e, 0xff, 0xd5, 0xa3, 0xe6, 0xfa, 0xf1, 0x2f, + 0xff, 0x77, 0xc3, 0x31, 0xc5, 0x25, 0xce, 0x4f, 0x01, 0xf4, 0x47, 0xa8, 0xa6, 0x23, 0xc9, 0x98, + 0x32, 0xd7, 0xf3, 0xc5, 0x54, 0x55, 0xd7, 0xe4, 0x91, 0x72, 0x0d, 0x61, 0xc7, 0x95, 0x49, 0xf6, + 0x15, 0x7d, 0xb5, 0x72, 0x10, 0xb3, 0xc8, 0x0b, 0xae, 0xc4, 0xfc, 0x15, 0x97, 0xb4, 0x81, 0x00, + 0x9f, 0xfd, 0x4d, 0x85, 0xca, 0x9a, 0x9f, 0x75, 0x21, 0x55, 0xa0, 0x68, 0x3b, 0xc4, 0x30, 0x87, + 0x1d, 0xab, 0xa7, 0x29, 0x48, 0x83, 0xb2, 0x63, 0x5b, 0x8e, 0x4d, 0x0c, 0xb3, 0xeb, 0x18, 0x5c, + 0x52, 0x9f, 0xc3, 0x6e, 0xcf, 0xb2, 0xcf, 0x88, 0xed, 0x0c, 0x89, 0xd9, 0xb3, 0xbe, 0xb5, 0x8e, + 0x7b, 0xa6, 0x96, 0x43, 0x0f, 0x40, 0x73, 0x6c, 0xd2, 0x3d, 0xed, 0x58, 0x36, 0x19, 0x5a, 0xe7, + 0xa6, 0x73, 0x31, 0xd4, 0x54, 0x8e, 0x9e, 0x0e, 0x7b, 0x5d, 0x62, 0xbe, 0xeb, 0x9a, 0xa6, 0x31, + 0x20, 0xe7, 0x9d, 0x77, 0x5a, 0x1e, 0x35, 0xe0, 0x81, 0x65, 0x0f, 0x2e, 0x4e, 0x4e, 0xac, 0xae, + 0x65, 0xda, 0x43, 0x72, 0xdc, 0xe9, 0x75, 0xec, 0xae, 0xa9, 0x6d, 0xa3, 0x3d, 0x40, 0x96, 0xdd, + 0x75, 0xce, 0xfb, 0x3d, 0x73, 0x68, 0x12, 0x29, 0xdd, 0x1d, 0x54, 0x87, 0x9a, 0xf0, 0xd3, 0x31, + 0x0c, 0x72, 0xd2, 0xb1, 0x7a, 0xa6, 0xa1, 0x15, 0x78, 0x26, 0x29, 0x63, 0x40, 0x0c, 0x6b, 0xd0, + 0x39, 0xe6, 0x70, 0x91, 0xc7, 0xb4, 0xec, 0x37, 0x8e, 0xd5, 0x35, 0x49, 0x97, 0xbb, 0xe5, 0x28, + 0x70, 0xb2, 0x44, 0x2f, 0x6c, 0xc3, 0xc4, 0xfd, 0x8e, 0x65, 0x68, 0x25, 0xb4, 0x0f, 0x0f, 0x25, + 0x6c, 0xbe, 0xeb, 0x5b, 0xf8, 0x7b, 0x32, 0x74, 0x1c, 0x32, 0x70, 0x1c, 0x5b, 0x2b, 0x67, 0x3d, + 0xf1, 0x6a, 0x9d, 0xbe, 0x69, 0x6b, 0x15, 0xf4, 0x10, 0xea, 0xe7, 0xfd, 0x3e, 0x91, 0x16, 0x59, + 0x6c, 0x95, 0xd3, 0x3b, 0x86, 0x81, 0xcd, 0xc1, 0x80, 0x9c, 0x5b, 0x83, 0xf3, 0xce, 0xb0, 0x7b, + 0xaa, 0xd5, 0x78, 0x49, 0x03, 0x73, 0x48, 0x86, 0xce, 0xb0, 0xd3, 0x5b, 0xe1, 0x1a, 0x4f, 0x68, + 0x85, 0xf3, 0xa0, 0x3d, 0xe7, 0xad, 0xb6, 0xcb, 0x27, 0x9c, 0xc3, 0xce, 0x9b, 0x34, 0x45, 0xc4, + 0x6b, 0x4f, 0xdb, 0x23, 0x63, 0x6a, 0x75, 0x0e, 0x5a, 0xf6, 0x9b, 0x4e, 0xcf, 0x32, 0xc8, 0x99, + 0xf9, 0xbd, 0x58, 0xfa, 0x0f, 0x38, 0x98, 0x64, 0x46, 0xfa, 0xd8, 0xf9, 0x96, 0x27, 0xa2, 0x7d, + 0x8e, 0x10, 0x54, 0xbb, 0x16, 0xee, 0x5e, 0xf4, 0x3a, 0x98, 0x60, 0xe7, 0x62, 0x68, 0x6a, 0x7b, + 0x47, 0xff, 0xc9, 0xc3, 0xb6, 0x38, 0xa8, 0x22, 0xf4, 0x8a, 0xeb, 0x7f, 0xf9, 0x2d, 0x84, 0x1e, + 0x7f, 0xf2, 0x1b, 0xa9, 0x29, 0x2f, 0xb3, 0x29, 0xfc, 0x42, 0x41, 0x7f, 0x82, 0x72, 0xf6, 0xfb, + 0x02, 0x65, 0xf7, 0xf6, 0x0d, 0x1f, 0x1e, 0x1b, 0x3c, 0x9c, 0x81, 0x66, 0xc6, 0xcc, 0x9b, 0xb9, + 0x8c, 0xca, 0xef, 0x05, 0xd4, 0xcc, 0x78, 0xb9, 0xf5, 0x11, 0xd2, 0xdc, 0xdf, 0x68, 0x4b, 0x4f, + 0xe5, 0x5e, 0x52, 0x4e, 0x7a, 0x63, 0xbf, 0x53, 0xce, 0xfa, 0x67, 0x42, 0xf3, 0x8b, 0xfb, 0xcc, + 0xa9, 0xb7, 0x31, 0xd4, 0x37, 0x5c, 0xc2, 0xd1, 0x57, 0xd9, 0x0c, 0xee, 0xbd, 0xc2, 0x37, 0x9f, + 0xfc, 0x10, 0x6d, 0x15, 0x65, 0xc3, 0x6d, 0x7d, 0x2d, 0xca, 0xfd, 0x77, 0xfd, 0xb5, 0x28, 0x9f, + 0xba, 0xf4, 0xbf, 0x07, 0xed, 0xf6, 0xe5, 0x0e, 0xe9, 0xb7, 0xc7, 0xde, 0xbd, 0x65, 0x36, 0x7f, + 0xf6, 0x49, 0x4e, 0xea, 0xdc, 0x02, 0x58, 0x5d, 0x91, 0xd0, 0xa3, 0xcc, 0x90, 0x3b, 0x57, 0xbc, + 0xe6, 0xe3, 0x7b, 0xac, 0xa9, 0xab, 0x21, 0xd4, 0x37, 0xdc, 0x99, 0xd6, 0x66, 0xe3, 0xfe, 0x3b, + 0x55, 0xf3, 0xc1, 0xa6, 0xab, 0xc5, 0x0b, 0xe5, 0xf8, 0xeb, 0x3f, 0x1f, 0x5e, 0x79, 0x6c, 0xba, + 0xb8, 0x3c, 0x18, 0x85, 0xb3, 0x43, 0xdf, 0xbb, 0x9a, 0xb2, 0xc0, 0x0b, 0xae, 0x02, 0xca, 0x3e, + 0x86, 0xd1, 0xf5, 0xa1, 0x1f, 0x8c, 0x0f, 0x85, 0x2e, 0x0f, 0x97, 0xc3, 0x2f, 0xb7, 0xc5, 0x6f, + 0x47, 0xbf, 0xfa, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x74, 0xbe, 0x98, 0x4d, 0x6b, 0x12, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1866,7 +1740,7 @@ type RouterClient interface { //* //SendPayment attempts to route a payment described by the passed //PaymentRequest to the final destination. The call returns a stream of - //payment status updates. + //payment updates. SendPayment(ctx context.Context, in *SendPaymentRequest, opts ...grpc.CallOption) (Router_SendPaymentClient, error) //* //TrackPayment returns an update stream for the payment identified by the @@ -1928,7 +1802,7 @@ func (c *routerClient) SendPayment(ctx context.Context, in *SendPaymentRequest, } type Router_SendPaymentClient interface { - Recv() (*PaymentStatus, error) + Recv() (*lnrpc.Payment, error) grpc.ClientStream } @@ -1936,8 +1810,8 @@ type routerSendPaymentClient struct { grpc.ClientStream } -func (x *routerSendPaymentClient) Recv() (*PaymentStatus, error) { - m := new(PaymentStatus) +func (x *routerSendPaymentClient) Recv() (*lnrpc.Payment, error) { + m := new(lnrpc.Payment) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } @@ -1960,7 +1834,7 @@ func (c *routerClient) TrackPayment(ctx context.Context, in *TrackPaymentRequest } type Router_TrackPaymentClient interface { - Recv() (*PaymentStatus, error) + Recv() (*lnrpc.Payment, error) grpc.ClientStream } @@ -1968,8 +1842,8 @@ type routerTrackPaymentClient struct { grpc.ClientStream } -func (x *routerTrackPaymentClient) Recv() (*PaymentStatus, error) { - m := new(PaymentStatus) +func (x *routerTrackPaymentClient) Recv() (*lnrpc.Payment, error) { + m := new(lnrpc.Payment) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } @@ -2067,7 +1941,7 @@ type RouterServer interface { //* //SendPayment attempts to route a payment described by the passed //PaymentRequest to the final destination. The call returns a stream of - //payment status updates. + //payment updates. SendPayment(*SendPaymentRequest, Router_SendPaymentServer) error //* //TrackPayment returns an update stream for the payment identified by the @@ -2118,7 +1992,7 @@ func _Router_SendPayment_Handler(srv interface{}, stream grpc.ServerStream) erro } type Router_SendPaymentServer interface { - Send(*PaymentStatus) error + Send(*lnrpc.Payment) error grpc.ServerStream } @@ -2126,7 +2000,7 @@ type routerSendPaymentServer struct { grpc.ServerStream } -func (x *routerSendPaymentServer) Send(m *PaymentStatus) error { +func (x *routerSendPaymentServer) Send(m *lnrpc.Payment) error { return x.ServerStream.SendMsg(m) } @@ -2139,7 +2013,7 @@ func _Router_TrackPayment_Handler(srv interface{}, stream grpc.ServerStream) err } type Router_TrackPaymentServer interface { - Send(*PaymentStatus) error + Send(*lnrpc.Payment) error grpc.ServerStream } @@ -2147,7 +2021,7 @@ type routerTrackPaymentServer struct { grpc.ServerStream } -func (x *routerTrackPaymentServer) Send(m *PaymentStatus) error { +func (x *routerTrackPaymentServer) Send(m *lnrpc.Payment) error { return x.ServerStream.SendMsg(m) } diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 4ff1135d9c..43cffc583f 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -121,62 +121,6 @@ message TrackPaymentRequest { bytes payment_hash = 1; } -enum PaymentState { - /** - Payment is still in flight. - */ - IN_FLIGHT = 0; - - /** - Payment completed successfully. - */ - SUCCEEDED = 1; - - /** - There are more routes to try, but the payment timeout was exceeded. - */ - FAILED_TIMEOUT = 2; - - /** - All possible routes were tried and failed permanently. Or were no - routes to the destination at all. - */ - FAILED_NO_ROUTE = 3; - - /** - A non-recoverable error has occured. - */ - FAILED_ERROR = 4; - - /** - Payment details incorrect (unknown hash, invalid amt or - invalid final cltv delta) - */ - FAILED_INCORRECT_PAYMENT_DETAILS = 5; - - /** - Insufficient local balance. - */ - FAILED_INSUFFICIENT_BALANCE = 6; -} - -message PaymentStatus { - /// Current state the payment is in. - PaymentState state = 1; - - /** - The pre-image of the payment when state is SUCCEEDED. - */ - bytes preimage = 2; - - reserved 3; - - /** - The HTLCs made in attempt to settle the payment. - */ - repeated lnrpc.HTLCAttempt htlcs = 4; -} - message RouteFeeRequest { /** The destination once wishes to obtain a routing fee quote to. @@ -465,15 +409,15 @@ service Router { /** SendPayment attempts to route a payment described by the passed PaymentRequest to the final destination. The call returns a stream of - payment status updates. + payment updates. */ - rpc SendPayment (SendPaymentRequest) returns (stream PaymentStatus); + rpc SendPayment (SendPaymentRequest) returns (stream lnrpc.Payment); /** TrackPayment returns an update stream for the payment identified by the payment hash. */ - rpc TrackPayment (TrackPaymentRequest) returns (stream PaymentStatus); + rpc TrackPayment (TrackPaymentRequest) returns (stream lnrpc.Payment); /** EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 80e4ebf450..d30ad86816 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -441,7 +441,7 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash, router := s.cfg.RouterBackend // Subscribe to the outcome of this payment. - inFlight, resultChan, err := router.Tower.SubscribePayment( + subscription, err := router.Tower.SubscribePayment( paymentHash, ) switch { @@ -450,95 +450,37 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash, case err != nil: return err } + defer subscription.Close() - // If it is in flight, send a state update to the client. Payment status - // update streams are expected to always send the current payment state - // immediately. - if inFlight { - err = stream.Send(&PaymentStatus{ - State: PaymentState_IN_FLIGHT, - }) - if err != nil { - return err - } - } - - // Wait for the outcome of the payment. For payments that have - // completed, the result should already be waiting on the channel. - select { - case result := <-resultChan: - // Marshall result to rpc type. - var status PaymentStatus - if result.Success { - log.Debugf("Payment %v successfully completed", - paymentHash) - - status.State = PaymentState_SUCCEEDED - status.Preimage = result.Preimage[:] - } else { - state, err := marshallFailureReason( - result.FailureReason, - ) + // Stream updates back to the client. The first update is always the + // current state of the payment. + for { + select { + case item, ok := <-subscription.Updates: + if !ok { + // No more payment updates. + return nil + } + result := item.(*channeldb.MPPayment) + rpcPayment, err := router.MarshallPayment(result) if err != nil { return err } - status.State = state - } - // Marshal our list of HTLCs that have been tried for this - // payment. - htlcs := make([]*lnrpc.HTLCAttempt, 0, len(result.HTLCs)) - for _, dbHtlc := range result.HTLCs { - htlc, err := router.MarshalHTLCAttempt(dbHtlc) + // Send event to the client. + err = stream.Send(rpcPayment) if err != nil { return err } - htlcs = append(htlcs, htlc) - } - status.Htlcs = htlcs + case <-s.quit: + return errServerShuttingDown - // Send event to the client. - err = stream.Send(&status) - if err != nil { - return err + case <-stream.Context().Done(): + log.Debugf("Payment status stream %v canceled", paymentHash) + return stream.Context().Err() } - - case <-s.quit: - return errServerShuttingDown - - case <-stream.Context().Done(): - log.Debugf("Payment status stream %v canceled", paymentHash) - return stream.Context().Err() - } - - return nil -} - -// marshallFailureReason marshalls the failure reason to the corresponding rpc -// type. -func marshallFailureReason(reason channeldb.FailureReason) ( - PaymentState, error) { - - switch reason { - - case channeldb.FailureReasonTimeout: - return PaymentState_FAILED_TIMEOUT, nil - - case channeldb.FailureReasonNoRoute: - return PaymentState_FAILED_NO_ROUTE, nil - - case channeldb.FailureReasonError: - return PaymentState_FAILED_ERROR, nil - - case channeldb.FailureReasonPaymentDetails: - return PaymentState_FAILED_INCORRECT_PAYMENT_DETAILS, nil - - case channeldb.FailureReasonInsufficientBalance: - return PaymentState_FAILED_INSUFFICIENT_BALANCE, nil } - - return 0, errors.New("unknown failure reason") } // BuildRoute builds a route from a list of hop addresses. diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 108ccb044f..4e2be72574 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -14271,13 +14271,13 @@ func testHoldInvoicePersistence(net *lntest.NetworkHarness, t *harnessTest) { // Wait for inlight status update. for _, payStream := range paymentStreams { - status, err := payStream.Recv() + payment, err := payStream.Recv() if err != nil { t.Fatalf("Failed receiving status update: %v", err) } - if status.State != routerrpc.PaymentState_IN_FLIGHT { - t.Fatalf("state not in flight: %v", status.State) + if payment.Status != lnrpc.Payment_IN_FLIGHT { + t.Fatalf("state not in flight: %v", payment.Status) } } @@ -14355,7 +14355,7 @@ func testHoldInvoicePersistence(net *lntest.NetworkHarness, t *harnessTest) { // Now after a restart, we must re-track the payments. We set up a // goroutine for each to track thir status updates. var ( - statusUpdates []chan *routerrpc.PaymentStatus + statusUpdates []chan *lnrpc.Payment wg sync.WaitGroup quit = make(chan struct{}) ) @@ -14377,20 +14377,20 @@ func testHoldInvoicePersistence(net *lntest.NetworkHarness, t *harnessTest) { } // We set up a channel where we'll forward any status update. - upd := make(chan *routerrpc.PaymentStatus) + upd := make(chan *lnrpc.Payment) wg.Add(1) go func() { defer wg.Done() for { - status, err := payStream.Recv() + payment, err := payStream.Recv() if err != nil { close(upd) return } select { - case upd <- status: + case upd <- payment: case <-quit: return } @@ -14400,17 +14400,17 @@ func testHoldInvoicePersistence(net *lntest.NetworkHarness, t *harnessTest) { statusUpdates = append(statusUpdates, upd) } - // Wait for the infligt status update. + // Wait for the in-flight status update. for _, upd := range statusUpdates { select { - case status, ok := <-upd: + case payment, ok := <-upd: if !ok { - t.Fatalf("failed getting status update") + t.Fatalf("failed getting payment update") } - if status.State != routerrpc.PaymentState_IN_FLIGHT { + if payment.Status != lnrpc.Payment_IN_FLIGHT { t.Fatalf("state not in in flight: %v", - status.State) + payment.Status) } case <-time.After(5 * time.Second): t.Fatalf("in flight status not recevied") @@ -14439,25 +14439,38 @@ func testHoldInvoicePersistence(net *lntest.NetworkHarness, t *harnessTest) { // Make sure we get the expected status update. for i, upd := range statusUpdates { - select { - case status, ok := <-upd: - if !ok { - t.Fatalf("failed getting status update") - } - - if i%2 == 0 { - if status.State != routerrpc.PaymentState_SUCCEEDED { - t.Fatalf("state not suceeded : %v", - status.State) + // Read until the payment is in a terminal state. + var payment *lnrpc.Payment + for payment == nil { + select { + case p, ok := <-upd: + if !ok { + t.Fatalf("failed getting payment update") } - } else { - if status.State != routerrpc.PaymentState_FAILED_INCORRECT_PAYMENT_DETAILS { - t.Fatalf("state not failed: %v", - status.State) + + if p.Status == lnrpc.Payment_IN_FLIGHT { + continue } + + payment = p + case <-time.After(5 * time.Second): + t.Fatalf("in flight status not recevied") + } + } + + // Assert terminal payment state. + if i%2 == 0 { + if payment.Status != lnrpc.Payment_SUCCEEDED { + t.Fatalf("state not suceeded : %v", + payment.Status) + } + } else { + if payment.FailureReason != + lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS { + + t.Fatalf("state not failed: %v", + payment.FailureReason) } - case <-time.After(5 * time.Second): - t.Fatalf("in flight status not recevied") } } diff --git a/routing/control_tower.go b/routing/control_tower.go index 5702eb92e5..be23c4a904 100644 --- a/routing/control_tower.go +++ b/routing/control_tower.go @@ -1,11 +1,12 @@ package routing import ( - "errors" "sync" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/multimutex" + "github.com/lightningnetwork/lnd/queue" ) // ControlTower tracks all outgoing payments made, whose primary purpose is to @@ -50,29 +51,43 @@ type ControlTower interface { FetchInFlightPayments() ([]*channeldb.InFlightPayment, error) // SubscribePayment subscribes to updates for the payment with the given - // hash. It returns a boolean indicating whether the payment is still in - // flight and a channel that provides the final outcome of the payment. - SubscribePayment(paymentHash lntypes.Hash) (bool, chan PaymentResult, + // hash. A first update with the current state of the payment is always + // sent out immediately. + SubscribePayment(paymentHash lntypes.Hash) (*ControlTowerSubscriber, error) } -// PaymentResult is the struct describing the events received by payment -// subscribers. -type PaymentResult struct { - // Success indicates whether the payment was successful. - Success bool +// ControlTowerSubscriber contains the state for a payment update subscriber. +type ControlTowerSubscriber struct { + // Updates is the channel over which *channeldb.MPPayment updates can be + // received. + Updates <-chan interface{} - // Preimage is the preimage of a successful payment. This serves as a - // proof of payment. It is only set for successful payments. - Preimage lntypes.Preimage + queue *queue.ConcurrentQueue + quit chan struct{} +} + +// newControlTowerSubscriber instantiates a new subscriber state object. +func newControlTowerSubscriber() *ControlTowerSubscriber { + // Create a queue for payment updates. + queue := queue.NewConcurrentQueue(20) + queue.Start() + + return &ControlTowerSubscriber{ + Updates: queue.ChanOut(), + queue: queue, + quit: make(chan struct{}), + } +} - // FailureReason is a failure reason code indicating the reason the - // payment failed. It is only set for failed payments. - FailureReason channeldb.FailureReason +// Close signals that the subscriber is no longer interested in updates. +func (s *ControlTowerSubscriber) Close() { + // Close quit channel so that any pending writes to the queue are + // cancelled. + close(s.quit) - // HTLCs is a list of HTLCs that have been attempted in order to settle - // the payment. - HTLCs []channeldb.HTLCAttempt + // Stop the queue goroutine so that it won't leak. + s.queue.Stop() } // controlTower is persistent implementation of ControlTower to restrict @@ -80,15 +95,21 @@ type PaymentResult struct { type controlTower struct { db *channeldb.PaymentControl - subscribers map[lntypes.Hash][]chan PaymentResult + subscribers map[lntypes.Hash][]*ControlTowerSubscriber subscribersMtx sync.Mutex + + // paymentsMtx provides synchronization on the payment level to ensure + // that no race conditions occur in between updating the database and + // sending a notification. + paymentsMtx *multimutex.HashMutex } // NewControlTower creates a new instance of the controlTower. func NewControlTower(db *channeldb.PaymentControl) ControlTower { return &controlTower{ db: db, - subscribers: make(map[lntypes.Hash][]chan PaymentResult), + subscribers: make(map[lntypes.Hash][]*ControlTowerSubscriber), + paymentsMtx: multimutex.NewHashMutex(), } } @@ -107,8 +128,18 @@ func (p *controlTower) InitPayment(paymentHash lntypes.Hash, func (p *controlTower) RegisterAttempt(paymentHash lntypes.Hash, attempt *channeldb.HTLCAttemptInfo) error { - _, err := p.db.RegisterAttempt(paymentHash, attempt) - return err + p.paymentsMtx.Lock(paymentHash) + defer p.paymentsMtx.Unlock(paymentHash) + + payment, err := p.db.RegisterAttempt(paymentHash, attempt) + if err != nil { + return err + } + + // Notify subscribers of the attempt registration. + p.notifySubscribers(paymentHash, payment) + + return nil } // SettleAttempt marks the given attempt settled with the preimage. If @@ -117,15 +148,16 @@ func (p *controlTower) RegisterAttempt(paymentHash lntypes.Hash, func (p *controlTower) SettleAttempt(paymentHash lntypes.Hash, attemptID uint64, settleInfo *channeldb.HTLCSettleInfo) error { + p.paymentsMtx.Lock(paymentHash) + defer p.paymentsMtx.Unlock(paymentHash) + payment, err := p.db.SettleAttempt(paymentHash, attemptID, settleInfo) if err != nil { return err } // Notify subscribers of success event. - p.notifyFinalEvent( - paymentHash, createSuccessResult(payment.HTLCs), - ) + p.notifySubscribers(paymentHash, payment) return nil } @@ -134,8 +166,18 @@ func (p *controlTower) SettleAttempt(paymentHash lntypes.Hash, func (p *controlTower) FailAttempt(paymentHash lntypes.Hash, attemptID uint64, failInfo *channeldb.HTLCFailInfo) error { - _, err := p.db.FailAttempt(paymentHash, attemptID, failInfo) - return err + p.paymentsMtx.Lock(paymentHash) + defer p.paymentsMtx.Unlock(paymentHash) + + payment, err := p.db.FailAttempt(paymentHash, attemptID, failInfo) + if err != nil { + return err + } + + // Notify subscribers of failed attempt. + p.notifySubscribers(paymentHash, payment) + + return nil } // FetchPayment fetches the payment corresponding to the given payment hash. @@ -145,35 +187,6 @@ func (p *controlTower) FetchPayment(paymentHash lntypes.Hash) ( return p.db.FetchPayment(paymentHash) } -// createSuccessResult creates a success result to send to subscribers. -func createSuccessResult(htlcs []channeldb.HTLCAttempt) *PaymentResult { - // Extract any preimage from the list of HTLCs. - var preimage lntypes.Preimage - for _, htlc := range htlcs { - if htlc.Settle != nil { - preimage = htlc.Settle.Preimage - break - } - } - - return &PaymentResult{ - Success: true, - Preimage: preimage, - HTLCs: htlcs, - } -} - -// createFailResult creates a failed result to send to subscribers. -func createFailedResult(htlcs []channeldb.HTLCAttempt, - reason channeldb.FailureReason) *PaymentResult { - - return &PaymentResult{ - Success: false, - FailureReason: reason, - HTLCs: htlcs, - } -} - // Fail transitions a payment into the Failed state, and records the reason the // payment failed. After invoking this method, InitPayment should return nil on // its next call for this payment hash, allowing the switch to make a @@ -181,17 +194,16 @@ func createFailedResult(htlcs []channeldb.HTLCAttempt, func (p *controlTower) Fail(paymentHash lntypes.Hash, reason channeldb.FailureReason) error { + p.paymentsMtx.Lock(paymentHash) + defer p.paymentsMtx.Unlock(paymentHash) + payment, err := p.db.Fail(paymentHash, reason) if err != nil { return err } // Notify subscribers of fail event. - p.notifyFinalEvent( - paymentHash, createFailedResult( - payment.HTLCs, reason, - ), - ) + p.notifySubscribers(paymentHash, payment) return nil } @@ -201,86 +213,81 @@ func (p *controlTower) FetchInFlightPayments() ([]*channeldb.InFlightPayment, er return p.db.FetchInFlightPayments() } -// SubscribePayment subscribes to updates for the payment with the given hash. -// It returns a boolean indicating whether the payment is still in flight and a -// channel that provides the final outcome of the payment. +// SubscribePayment subscribes to updates for the payment with the given hash. A +// first update with the current state of the payment is always sent out +// immediately. func (p *controlTower) SubscribePayment(paymentHash lntypes.Hash) ( - bool, chan PaymentResult, error) { - - // Create a channel with buffer size 1. For every payment there will be - // exactly one event sent. - c := make(chan PaymentResult, 1) + *ControlTowerSubscriber, error) { - // Take lock before querying the db to prevent this scenario: - // FetchPayment returns us an in-flight state -> payment succeeds, but - // there is no subscriber to notify yet -> we add ourselves as a - // subscriber -> ... we will never receive a notification. - p.subscribersMtx.Lock() - defer p.subscribersMtx.Unlock() + // Take lock before querying the db to prevent missing or duplicating an + // update. + p.paymentsMtx.Lock(paymentHash) + defer p.paymentsMtx.Unlock(paymentHash) payment, err := p.db.FetchPayment(paymentHash) if err != nil { - return false, nil, err + return nil, err } - var event PaymentResult + subscriber := newControlTowerSubscriber() - switch payment.Status { + // Always write current payment state to the channel. + subscriber.queue.ChanIn() <- payment - // Payment is currently in flight. Register this subscriber and - // return without writing a result to the channel yet. - case channeldb.StatusInFlight: + // Payment is currently in flight. Register this subscriber for further + // updates. Otherwise this update is the final update and the incoming + // channel can be closed. This will close the queue's outgoing channel + // when all updates have been written. + if payment.Status == channeldb.StatusInFlight { + p.subscribersMtx.Lock() p.subscribers[paymentHash] = append( - p.subscribers[paymentHash], c, - ) - - return true, c, nil - - // Payment already succeeded. It is not necessary to register as - // a subscriber, because we can send the result on the channel - // immediately. - case channeldb.StatusSucceeded: - event = *createSuccessResult(payment.HTLCs) - - // Payment already failed. It is not necessary to register as a - // subscriber, because we can send the result on the channel - // immediately. - case channeldb.StatusFailed: - event = *createFailedResult( - payment.HTLCs, *payment.FailureReason, + p.subscribers[paymentHash], subscriber, ) - - default: - return false, nil, errors.New("unknown payment status") + p.subscribersMtx.Unlock() + } else { + close(subscriber.queue.ChanIn()) } - // Write immediate result to the channel. - c <- event - close(c) - - return false, c, nil + return subscriber, nil } -// notifyFinalEvent sends a final payment event to all subscribers of this -// payment. The channel will be closed after this. -func (p *controlTower) notifyFinalEvent(paymentHash lntypes.Hash, - event *PaymentResult) { +// notifySubscribers sends a final payment event to all subscribers of this +// payment. The channel will be closed after this. Note that this function must +// be executed atomically (by means of a lock) with the database update to +// guarantuee consistency of the notifications. +func (p *controlTower) notifySubscribers(paymentHash lntypes.Hash, + event *channeldb.MPPayment) { - // Get all subscribers for this hash. As there is only a single outcome, - // the subscriber list can be cleared. + // Get all subscribers for this payment. p.subscribersMtx.Lock() list, ok := p.subscribers[paymentHash] if !ok { p.subscribersMtx.Unlock() return } - delete(p.subscribers, paymentHash) + + // If the payment reached a terminal state, the subscriber list can be + // cleared. There won't be any more updates. + terminal := event.Status != channeldb.StatusInFlight + if terminal { + delete(p.subscribers, paymentHash) + } p.subscribersMtx.Unlock() - // Notify all subscribers of the event. The subscriber channel is - // buffered, so it cannot block here. + // Notify all subscribers of the event. for _, subscriber := range list { - subscriber <- *event - close(subscriber) + select { + case subscriber.queue.ChanIn() <- event: + // If this event is the last, close the incoming channel + // of the queue. This will signal the subscriber that + // there won't be any more updates. + if terminal { + close(subscriber.queue.ChanIn()) + } + + // If subscriber disappeared, skip notification. For further + // notifications, we'll keep skipping over this subscriber. + case <-subscriber.quit: + } } } diff --git a/routing/control_tower_test.go b/routing/control_tower_test.go index 82dc2706f6..7907e37e2c 100644 --- a/routing/control_tower_test.go +++ b/routing/control_tower_test.go @@ -55,7 +55,7 @@ func TestControlTowerSubscribeUnknown(t *testing.T) { pControl := NewControlTower(channeldb.NewPaymentControl(db)) // Subscription should fail when the payment is not known. - _, _, err = pControl.SubscribePayment(lntypes.Hash{1}) + _, err = pControl.SubscribePayment(lntypes.Hash{1}) if err != channeldb.ErrPaymentNotInitiated { t.Fatal("expected subscribe to fail for unknown payment") } @@ -86,13 +86,10 @@ func TestControlTowerSubscribeSuccess(t *testing.T) { // Subscription should succeed and immediately report the InFlight // status. - inFlight, subscriber1, err := pControl.SubscribePayment(info.PaymentHash) + subscriber1, err := pControl.SubscribePayment(info.PaymentHash) if err != nil { t.Fatalf("expected subscribe to succeed, but got: %v", err) } - if !inFlight { - t.Fatalf("unexpected payment to be in flight") - } // Register an attempt. err = pControl.RegisterAttempt(info.PaymentHash, attempt) @@ -101,13 +98,10 @@ func TestControlTowerSubscribeSuccess(t *testing.T) { } // Register a second subscriber after the first attempt has started. - inFlight, subscriber2, err := pControl.SubscribePayment(info.PaymentHash) + subscriber2, err := pControl.SubscribePayment(info.PaymentHash) if err != nil { t.Fatalf("expected subscribe to succeed, but got: %v", err) } - if !inFlight { - t.Fatalf("unexpected payment to be in flight") - } // Mark the payment as successful. err = pControl.SettleAttempt( @@ -121,32 +115,33 @@ func TestControlTowerSubscribeSuccess(t *testing.T) { } // Register a third subscriber after the payment succeeded. - inFlight, subscriber3, err := pControl.SubscribePayment(info.PaymentHash) + subscriber3, err := pControl.SubscribePayment(info.PaymentHash) if err != nil { t.Fatalf("expected subscribe to succeed, but got: %v", err) } - if inFlight { - t.Fatalf("expected payment to be finished") - } // We expect all subscribers to now report the final outcome followed by // no other events. - subscribers := []chan PaymentResult{ + subscribers := []*ControlTowerSubscriber{ subscriber1, subscriber2, subscriber3, } for _, s := range subscribers { - var result PaymentResult - select { - case result = <-s: - case <-time.After(testTimeout): - t.Fatal("timeout waiting for payment result") + var result *channeldb.MPPayment + for result == nil || result.Status == channeldb.StatusInFlight { + select { + case item := <-s.Updates: + result = item.(*channeldb.MPPayment) + case <-time.After(testTimeout): + t.Fatal("timeout waiting for payment result") + } } - if !result.Success { + if result.Status != channeldb.StatusSucceeded { t.Fatal("unexpected payment state") } - if result.Preimage != preimg { + settle, _ := result.TerminalInfo() + if settle.Preimage != preimg { t.Fatal("unexpected preimage") } if len(result.HTLCs) != 1 { @@ -161,7 +156,7 @@ func TestControlTowerSubscribeSuccess(t *testing.T) { // After the final event, we expect the channel to be closed. select { - case _, ok := <-s: + case _, ok := <-s.Updates: if ok { t.Fatal("expected channel to be closed") } @@ -204,7 +199,7 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) { } // Subscription should succeed. - _, subscriber1, err := pControl.SubscribePayment(info.PaymentHash) + subscriber1, err := pControl.SubscribePayment(info.PaymentHash) if err != nil { t.Fatalf("expected subscribe to succeed, but got: %v", err) } @@ -235,29 +230,29 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) { } // Register a second subscriber after the payment failed. - inFlight, subscriber2, err := pControl.SubscribePayment(info.PaymentHash) + subscriber2, err := pControl.SubscribePayment(info.PaymentHash) if err != nil { t.Fatalf("expected subscribe to succeed, but got: %v", err) } - if inFlight { - t.Fatalf("expected payment to be finished") - } // We expect all subscribers to now report the final outcome followed by // no other events. - subscribers := []chan PaymentResult{ + subscribers := []*ControlTowerSubscriber{ subscriber1, subscriber2, } for _, s := range subscribers { - var result PaymentResult - select { - case result = <-s: - case <-time.After(testTimeout): - t.Fatal("timeout waiting for payment result") + var result *channeldb.MPPayment + for result == nil || result.Status == channeldb.StatusInFlight { + select { + case item := <-s.Updates: + result = item.(*channeldb.MPPayment) + case <-time.After(testTimeout): + t.Fatal("timeout waiting for payment result") + } } - if result.Success { + if result.Status == channeldb.StatusSucceeded { t.Fatal("unexpected payment state") } @@ -282,13 +277,13 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) { len(result.HTLCs)) } - if result.FailureReason != channeldb.FailureReasonTimeout { + if *result.FailureReason != channeldb.FailureReasonTimeout { t.Fatal("unexpected failure reason") } // After the final event, we expect the channel to be closed. select { - case _, ok := <-s: + case _, ok := <-s.Updates: if ok { t.Fatal("expected channel to be closed") } diff --git a/routing/mock_test.go b/routing/mock_test.go index 9645f73bf9..ae27bc7e7d 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -457,7 +457,7 @@ func (m *mockControlTower) FetchInFlightPayments() ( } func (m *mockControlTower) SubscribePayment(paymentHash lntypes.Hash) ( - bool, chan PaymentResult, error) { + *ControlTowerSubscriber, error) { - return false, nil, errors.New("not implemented") + return nil, errors.New("not implemented") } From 3ed3c90efe971e39e38dabda760ff221d4554e8e Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Apr 2020 12:46:05 +0200 Subject: [PATCH 435/562] lncli: add show_inflight flag --- cmd/lncli/cmd_pay.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index b251072852..34fb88e9cb 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -46,6 +46,12 @@ var ( ",.. For example: --data 3438382=0a21ff. " + "Custom record ids start from 65536.", } + + showInflightFlag = cli.BoolFlag{ + Name: "show_inflight", + Usage: "if set, intermediate payment state updates will be " + + "displayed", + } ) // paymentFlags returns common flags for sendpayment and payinvoice. @@ -82,7 +88,7 @@ func paymentFlags() []cli.Flag { Name: "allow_self_payment", Usage: "allow sending a circular payment to self", }, - dataFlag, + dataFlag, showInflightFlag, } } @@ -382,6 +388,8 @@ func sendPaymentRequest(ctx *cli.Context, req.FeeLimitSat = feeLimit + showInflight := ctx.Bool(showInflightFlag.Name) + stream, err := routerClient.SendPayment(context.Background(), req) if err != nil { return err @@ -405,6 +413,10 @@ func sendPaymentRequest(ctx *cli.Context, return nil } + + if showInflight { + printRespJSON(status) + } } } From cb4cd49dc8d3b0255afe9ff29af9c46c2dbb2c98 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 25 Mar 2020 14:59:08 +0100 Subject: [PATCH 436/562] routing: map insufficient local bandwidth error to no path With mpp it isn't possible anymore for findPath to determine that there isn't enough local bandwidth. The full payment amount isn't known at that point. In a follow-up, this payment outcome can be reintroduced on a higher level (payment lifecycle). --- channeldb/payments.go | 3 +++ routing/pathfind.go | 2 +- routing/pathfind_test.go | 31 ------------------------------- routing/payment_session.go | 10 ---------- 4 files changed, 4 insertions(+), 42 deletions(-) diff --git a/channeldb/payments.go b/channeldb/payments.go index 7c5f49a2af..16497dcdc5 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -116,6 +116,9 @@ const ( // FailureReasonInsufficientBalance indicates that we didn't have enough // balance to complete the payment. + // + // This reason isn't assigned anymore, but may still exist for older + // payments. FailureReasonInsufficientBalance FailureReason = 4 // TODO(halseth): cancel state. diff --git a/routing/pathfind.go b/routing/pathfind.go index 1365958c6a..3241fb1214 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -478,7 +478,7 @@ func findPathInternal( return nil, err } if max < amt { - return nil, errInsufficientBalance + return nil, errNoPathFound } } diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 6866211985..deaa4ea53b 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -2809,37 +2809,6 @@ func TestRouteToSelf(t *testing.T) { ctx.assertPath(path, []uint64{1, 3, 2}) } -// TestInsufficientBalance tests that a dedicated error is returned for -// insufficient local balance. -func TestInsufficientBalance(t *testing.T) { - t.Parallel() - - testChannels := []*testChannel{ - symmetricTestChannel("source", "target", 100000, &testChannelPolicy{ - Expiry: 144, - FeeBaseMsat: 500, - }, 1), - } - - ctx := newPathFindingTestContext(t, testChannels, "source") - defer ctx.cleanup() - - paymentAmt := lnwire.NewMSatFromSatoshis(100) - target := ctx.keyFromAlias("target") - - ctx.graphParams.bandwidthHints = map[uint64]lnwire.MilliSatoshi{ - 1: lnwire.NewMSatFromSatoshis(50), - } - - // Find the best path to self. We expect this to be source->a->source, - // because a charges the lowest forwarding fee. - _, err := ctx.findPath(target, paymentAmt) - if err != errInsufficientBalance { - t.Fatalf("expected insufficient balance error, but got: %v", - err) - } -} - type pathFindingTestContext struct { t *testing.T graphParams graphParams diff --git a/routing/payment_session.go b/routing/payment_session.go index 6a597ff01e..b439420fba 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -26,10 +26,6 @@ const ( // not exist in the graph. errNoPathFound - // errInsufficientLocalBalance is returned when none of the local - // channels have enough balance for the payment. - errInsufficientBalance - // errEmptyPaySession is returned when the empty payment session is // queried for a route. errEmptyPaySession @@ -50,9 +46,6 @@ func (e noRouteError) Error() string { case errEmptyPaySession: return "empty payment session" - case errInsufficientBalance: - return "insufficient local balance" - default: return "unknown no-route error" } @@ -69,9 +62,6 @@ func (e noRouteError) FailureReason() channeldb.FailureReason { return channeldb.FailureReasonNoRoute - case errInsufficientBalance: - return channeldb.FailureReasonInsufficientBalance - default: return channeldb.FailureReasonError } From 47f9c1c3fdfcd82544162b020f44b6c02ba3f7df Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 17 Mar 2020 11:32:07 +0100 Subject: [PATCH 437/562] routing: use routingGraph interface in payment session Preparation for more test coverage of payment session. The function findPath now has the call signature of the former findPathInternal function. --- routing/integrated_routing_context_test.go | 7 +- routing/pathfind.go | 46 ++------ routing/pathfind_test.go | 126 ++++++++++----------- routing/payment_session.go | 29 +++-- routing/payment_session_source.go | 25 +++- routing/payment_session_test.go | 35 +++--- routing/router.go | 18 ++- routing/router_test.go | 14 +-- server.go | 1 - 9 files changed, 155 insertions(+), 146 deletions(-) diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index db5c6fe9f3..b5fc955eea 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -111,8 +111,11 @@ func (c *integratedRoutingContext) testPayment(expectedNofAttempts int) { } // Find a route. - path, err := findPathInternal( - nil, bandwidthHints, c.graph, + path, err := findPath( + &graphParams{ + graph: c.graph, + bandwidthHints: bandwidthHints, + }, &restrictParams, &c.pathFindingCfg, c.source.pubkey, c.target.pubkey, diff --git a/routing/pathfind.go b/routing/pathfind.go index 3241fb1214..5507444a08 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -253,7 +253,7 @@ func edgeWeight(lockedAmt lnwire.MilliSatoshi, fee lnwire.MilliSatoshi, // graphParams wraps the set of graph parameters passed to findPath. type graphParams struct { // graph is the ChannelGraph to be used during path finding. - graph *channeldb.ChannelGraph + graph routingGraph // additionalEdges is an optional set of edges that should be // considered during path finding, that is not already found in the @@ -381,34 +381,8 @@ func getMaxOutgoingAmt(node route.Vertex, outgoingChan *uint64, // path and accurately check the amount to forward at every node against the // available bandwidth. func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, - source, target route.Vertex, amt lnwire.MilliSatoshi, finalHtlcExpiry int32) ( - []*channeldb.ChannelEdgePolicy, error) { - - routingTx, err := newDbRoutingTx(g.graph) - if err != nil { - return nil, err - } - defer func() { - err := routingTx.close() - if err != nil { - log.Errorf("Error closing db tx: %v", err) - } - }() - - return findPathInternal( - g.additionalEdges, g.bandwidthHints, routingTx, r, cfg, source, - target, amt, finalHtlcExpiry, - ) -} - -// findPathInternal is the internal implementation of findPath. -func findPathInternal( - additionalEdges map[route.Vertex][]*channeldb.ChannelEdgePolicy, - bandwidthHints map[uint64]lnwire.MilliSatoshi, - graph routingGraph, - r *RestrictParams, cfg *PathFindingConfig, - source, target route.Vertex, amt lnwire.MilliSatoshi, finalHtlcExpiry int32) ( - []*channeldb.ChannelEdgePolicy, error) { + source, target route.Vertex, amt lnwire.MilliSatoshi, + finalHtlcExpiry int32) ([]*channeldb.ChannelEdgePolicy, error) { // Pathfinding can be a significant portion of the total payment // latency, especially on low-powered devices. Log several metrics to @@ -427,7 +401,7 @@ func findPathInternal( features := r.DestFeatures if features == nil { var err error - features, err = graph.fetchNodeFeatures(target) + features, err = g.graph.fetchNodeFeatures(target) if err != nil { return nil, err } @@ -468,11 +442,11 @@ func findPathInternal( // If we are routing from ourselves, check that we have enough local // balance available. - self := graph.sourceNode() + self := g.graph.sourceNode() if source == self { max, err := getMaxOutgoingAmt( - self, r.OutgoingChannelID, bandwidthHints, graph, + self, r.OutgoingChannelID, g.bandwidthHints, g.graph, ) if err != nil { return nil, err @@ -491,7 +465,7 @@ func findPathInternal( distance := make(map[route.Vertex]*nodeWithDist, estimatedNodeCount) additionalEdgesWithSrc := make(map[route.Vertex][]*edgePolicyWithSource) - for vertex, outgoingEdgePolicies := range additionalEdges { + for vertex, outgoingEdgePolicies := range g.additionalEdges { // Build reverse lookup to find incoming edges. Needed because // search is taken place from target to source. for _, outgoingEdgePolicy := range outgoingEdgePolicies { @@ -739,7 +713,7 @@ func findPathInternal( } // Fetch node features fresh from the graph. - fromFeatures, err := graph.fetchNodeFeatures(node) + fromFeatures, err := g.graph.fetchNodeFeatures(node) if err != nil { return nil, err } @@ -775,7 +749,7 @@ func findPathInternal( // Create unified policies for all incoming connections. u := newUnifiedPolicies(self, pivot, r.OutgoingChannelID) - err := u.addGraphPolicies(graph) + err := u.addGraphPolicies(g.graph) if err != nil { return nil, err } @@ -806,7 +780,7 @@ func findPathInternal( } policy := unifiedPolicy.getPolicy( - amtToSend, bandwidthHints, + amtToSend, g.bandwidthHints, ) if policy == nil { diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index deaa4ea53b..193e752d93 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -811,10 +811,8 @@ func testBasicGraphPathFindingCase(t *testing.T, graphInstance *testGraphInstanc paymentAmt := lnwire.NewMSatFromSatoshis(test.paymentAmt) target := graphInstance.aliasMap[test.target] - path, err := findPath( - &graphParams{ - graph: graphInstance.graph, - }, + path, err := dbFindPath( + graphInstance.graph, nil, nil, &RestrictParams{ FeeLimit: test.feeLimit, ProbabilitySource: noProbabilitySource, @@ -1005,11 +1003,8 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) { find := func(r *RestrictParams) ( []*channeldb.ChannelEdgePolicy, error) { - return findPath( - &graphParams{ - graph: graph.graph, - additionalEdges: additionalEdges, - }, + return dbFindPath( + graph.graph, additionalEdges, nil, r, testPathFindingConfig, sourceNode.PubKeyBytes, doge.PubKeyBytes, paymentAmt, 0, @@ -1433,10 +1428,8 @@ func TestPathNotAvailable(t *testing.T) { var unknownNode route.Vertex copy(unknownNode[:], unknownNodeBytes) - _, err = findPath( - &graphParams{ - graph: graph.graph, - }, + _, err = dbFindPath( + graph.graph, nil, nil, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, unknownNode, 100, 0, ) @@ -1482,7 +1475,7 @@ func TestDestTLVGraphFallback(t *testing.T) { ctx := newPathFindingTestContext(t, testChannels, "roasbeef") defer ctx.cleanup() - sourceNode, err := ctx.graphParams.graph.SourceNode() + sourceNode, err := ctx.graph.SourceNode() if err != nil { t.Fatalf("unable to fetch source node: %v", err) @@ -1491,10 +1484,8 @@ func TestDestTLVGraphFallback(t *testing.T) { find := func(r *RestrictParams, target route.Vertex) ([]*channeldb.ChannelEdgePolicy, error) { - return findPath( - &graphParams{ - graph: ctx.graphParams.graph, - }, + return dbFindPath( + ctx.graph, nil, nil, r, testPathFindingConfig, sourceNode.PubKeyBytes, target, 100, 0, ) @@ -1765,10 +1756,8 @@ func TestPathInsufficientCapacity(t *testing.T) { target := graph.aliasMap["sophon"] payAmt := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin) - _, err = findPath( - &graphParams{ - graph: graph.graph, - }, + _, err = dbFindPath( + graph.graph, nil, nil, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -1798,10 +1787,8 @@ func TestRouteFailMinHTLC(t *testing.T) { // attempt should fail. target := graph.aliasMap["songoku"] payAmt := lnwire.MilliSatoshi(10) - _, err = findPath( - &graphParams{ - graph: graph.graph, - }, + _, err = dbFindPath( + graph.graph, nil, nil, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -1897,10 +1884,8 @@ func TestRouteFailDisabledEdge(t *testing.T) { // succeed without issue, and return a single path via phamnuwen target := graph.aliasMap["sophon"] payAmt := lnwire.NewMSatFromSatoshis(105000) - _, err = findPath( - &graphParams{ - graph: graph.graph, - }, + _, err = dbFindPath( + graph.graph, nil, nil, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -1925,10 +1910,8 @@ func TestRouteFailDisabledEdge(t *testing.T) { t.Fatalf("unable to update edge: %v", err) } - _, err = findPath( - &graphParams{ - graph: graph.graph, - }, + _, err = dbFindPath( + graph.graph, nil, nil, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -1950,10 +1933,8 @@ func TestRouteFailDisabledEdge(t *testing.T) { // If we attempt to route through that edge, we should get a failure as // it is no longer eligible. - _, err = findPath( - &graphParams{ - graph: graph.graph, - }, + _, err = dbFindPath( + graph.graph, nil, nil, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -1984,10 +1965,8 @@ func TestPathSourceEdgesBandwidth(t *testing.T) { // cheapest path. target := graph.aliasMap["sophon"] payAmt := lnwire.NewMSatFromSatoshis(50000) - path, err := findPath( - &graphParams{ - graph: graph.graph, - }, + path, err := dbFindPath( + graph.graph, nil, nil, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -2007,11 +1986,8 @@ func TestPathSourceEdgesBandwidth(t *testing.T) { // Since both these edges has a bandwidth of zero, no path should be // found. - _, err = findPath( - &graphParams{ - graph: graph.graph, - bandwidthHints: bandwidths, - }, + _, err = dbFindPath( + graph.graph, nil, bandwidths, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -2025,11 +2001,8 @@ func TestPathSourceEdgesBandwidth(t *testing.T) { // Now, if we attempt to route again, we should find the path via // phamnuven, as the other source edge won't be considered. - path, err = findPath( - &graphParams{ - graph: graph.graph, - bandwidthHints: bandwidths, - }, + path, err = dbFindPath( + graph.graph, nil, bandwidths, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -2056,11 +2029,8 @@ func TestPathSourceEdgesBandwidth(t *testing.T) { // Since we ignore disable flags for local channels, a path should // still be found. - path, err = findPath( - &graphParams{ - graph: graph.graph, - bandwidthHints: bandwidths, - }, + path, err = dbFindPath( + graph.graph, nil, bandwidths, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) @@ -2811,7 +2781,7 @@ func TestRouteToSelf(t *testing.T) { type pathFindingTestContext struct { t *testing.T - graphParams graphParams + graph *channeldb.ChannelGraph restrictParams RestrictParams pathFindingConfig PathFindingConfig testGraphInstance *testGraphInstance @@ -2838,10 +2808,8 @@ func newPathFindingTestContext(t *testing.T, testChannels []*testChannel, testGraphInstance: testGraphInstance, source: route.Vertex(sourceNode.PubKeyBytes), pathFindingConfig: *testPathFindingConfig, - graphParams: graphParams{ - graph: testGraphInstance.graph, - }, - restrictParams: *noRestrictions, + graph: testGraphInstance.graph, + restrictParams: *noRestrictions, } return ctx @@ -2868,8 +2836,8 @@ func (c *pathFindingTestContext) findPath(target route.Vertex, amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error) { - return findPath( - &c.graphParams, &c.restrictParams, &c.pathFindingConfig, + return dbFindPath( + c.graph, nil, nil, &c.restrictParams, &c.pathFindingConfig, c.source, target, amt, 0, ) } @@ -2887,3 +2855,33 @@ func (c *pathFindingTestContext) assertPath(path []*channeldb.ChannelEdgePolicy, } } } + +// dbFindPath calls findPath after getting a db transaction from the database +// graph. +func dbFindPath(graph *channeldb.ChannelGraph, + additionalEdges map[route.Vertex][]*channeldb.ChannelEdgePolicy, + bandwidthHints map[uint64]lnwire.MilliSatoshi, + r *RestrictParams, cfg *PathFindingConfig, + source, target route.Vertex, amt lnwire.MilliSatoshi, + finalHtlcExpiry int32) ([]*channeldb.ChannelEdgePolicy, error) { + + routingTx, err := newDbRoutingTx(graph) + if err != nil { + return nil, err + } + defer func() { + err := routingTx.close() + if err != nil { + log.Errorf("Error closing db tx: %v", err) + } + }() + + return findPath( + &graphParams{ + additionalEdges: additionalEdges, + bandwidthHints: bandwidthHints, + graph: routingTx, + }, + r, cfg, source, target, amt, finalHtlcExpiry, + ) +} diff --git a/routing/payment_session.go b/routing/payment_session.go index b439420fba..a28f6a6f13 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -98,13 +98,19 @@ type paymentSession struct { getBandwidthHints func() (map[uint64]lnwire.MilliSatoshi, error) - sessionSource *SessionSource - payment *LightningPayment empty bool pathFinder pathFinder + + getRoutingGraph func() (routingGraph, func(), error) + + // pathFindingConfig defines global parameters that control the + // trade-off in path finding between fees and probabiity. + pathFindingConfig PathFindingConfig + + missionControl MissionController } // RequestRoute returns a route which is likely to be capable for successfully @@ -138,10 +144,8 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, // Taking into account this prune view, we'll attempt to locate a path // to our destination, respecting the recommendations from // MissionControl. - ss := p.sessionSource - restrictions := &RestrictParams{ - ProbabilitySource: ss.MissionControl.GetProbability, + ProbabilitySource: p.missionControl.GetProbability, FeeLimit: feeLimit, OutgoingChannelID: p.payment.OutgoingChannelID, LastHop: p.payment.LastHop, @@ -164,14 +168,22 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, finalHtlcExpiry := int32(height) + int32(finalCltvDelta) + routingGraph, cleanup, err := p.getRoutingGraph() + if err != nil { + return nil, err + } + defer cleanup() + + sourceVertex := routingGraph.sourceNode() + path, err := p.pathFinder( &graphParams{ - graph: ss.Graph, additionalEdges: p.additionalEdges, bandwidthHints: bandwidthHints, + graph: routingGraph, }, - restrictions, &ss.PathFindingConfig, - ss.SelfNode.PubKeyBytes, p.payment.Target, + restrictions, &p.pathFindingConfig, + sourceVertex, p.payment.Target, maxAmt, finalHtlcExpiry, ) if err != nil { @@ -180,7 +192,6 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, // With the next candidate path found, we'll attempt to turn this into // a route by applying the time-lock and fee requirements. - sourceVertex := route.Vertex(ss.SelfNode.PubKeyBytes) route, err := newRoute( sourceVertex, path, height, finalHopParams{ diff --git a/routing/payment_session_source.go b/routing/payment_session_source.go index 3d6cfedf2b..f3b6607e11 100644 --- a/routing/payment_session_source.go +++ b/routing/payment_session_source.go @@ -26,9 +26,6 @@ type SessionSource struct { // the available bandwidth of the link should be returned. QueryBandwidth func(*channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi - // SelfNode is our own node. - SelfNode *channeldb.LightningNode - // MissionControl is a shared memory of sorts that executions of payment // path finding use in order to remember which vertexes/edges were // pruned from prior attempts. During payment execution, errors sent by @@ -43,6 +40,21 @@ type SessionSource struct { PathFindingConfig PathFindingConfig } +// getRoutingGraph returns a routing graph and a clean-up function for +// pathfinding. +func (m *SessionSource) getRoutingGraph() (routingGraph, func(), error) { + routingTx, err := newDbRoutingTx(m.Graph) + if err != nil { + return nil, nil, err + } + return routingTx, func() { + err := routingTx.close() + if err != nil { + log.Errorf("Error closing db tx: %v", err) + } + }, nil +} + // NewPaymentSession creates a new payment session backed by the latest prune // view from Mission Control. An optional set of routing hints can be provided // in order to populate additional edges to explore when finding a path to the @@ -69,9 +81,11 @@ func (m *SessionSource) NewPaymentSession(p *LightningPayment) ( return &paymentSession{ additionalEdges: edges, getBandwidthHints: getBandwidthHints, - sessionSource: m, payment: p, pathFinder: findPath, + getRoutingGraph: m.getRoutingGraph, + pathFindingConfig: m.PathFindingConfig, + missionControl: m.MissionControl, }, nil } @@ -80,8 +94,7 @@ func (m *SessionSource) NewPaymentSession(p *LightningPayment) ( // missioncontrol for resumed payment we don't want to make more attempts for. func (m *SessionSource) NewPaymentSessionEmpty() PaymentSession { return &paymentSession{ - sessionSource: m, - empty: true, + empty: true, } } diff --git a/routing/payment_session_test.go b/routing/payment_session_test.go index a916580438..60d960b87c 100644 --- a/routing/payment_session_test.go +++ b/routing/payment_session_test.go @@ -13,10 +13,11 @@ func TestRequestRoute(t *testing.T) { height = 10 ) - findPath := func(g *graphParams, r *RestrictParams, - cfg *PathFindingConfig, source, target route.Vertex, - amt lnwire.MilliSatoshi, finalHtlcExpiry int32) ( - []*channeldb.ChannelEdgePolicy, error) { + findPath := func( + g *graphParams, + r *RestrictParams, cfg *PathFindingConfig, + source, target route.Vertex, amt lnwire.MilliSatoshi, + finalHtlcExpiry int32) ([]*channeldb.ChannelEdgePolicy, error) { // We expect find path to receive a cltv limit excluding the // final cltv delta (including the block padding). @@ -37,13 +38,6 @@ func TestRequestRoute(t *testing.T) { return path, nil } - sessionSource := &SessionSource{ - SelfNode: &channeldb.LightningNode{}, - MissionControl: &MissionControl{ - cfg: &MissionControlConfig{}, - }, - } - cltvLimit := uint32(30) finalCltvDelta := uint16(8) @@ -60,9 +54,14 @@ func TestRequestRoute(t *testing.T) { return nil, nil }, - sessionSource: sessionSource, - payment: payment, - pathFinder: findPath, + payment: payment, + pathFinder: findPath, + missionControl: &MissionControl{ + cfg: &MissionControlConfig{}, + }, + getRoutingGraph: func() (routingGraph, func(), error) { + return &sessionGraph{}, func() {}, nil + }, } route, err := session.RequestRoute( @@ -79,3 +78,11 @@ func TestRequestRoute(t *testing.T) { route.TotalTimeLock) } } + +type sessionGraph struct { + routingGraph +} + +func (g *sessionGraph) sourceNode() route.Vertex { + return route.Vertex{} +} diff --git a/routing/router.go b/routing/router.go index cac3e69d46..c554ceee6e 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1426,13 +1426,25 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, // execute our path finding algorithm. finalHtlcExpiry := currentHeight + int32(finalExpiry) + routingTx, err := newDbRoutingTx(r.cfg.Graph) + if err != nil { + return nil, err + } + defer func() { + err := routingTx.close() + if err != nil { + log.Errorf("Error closing db tx: %v", err) + } + }() + path, err := findPath( &graphParams{ - graph: r.cfg.Graph, - bandwidthHints: bandwidthHints, additionalEdges: routeHints, + bandwidthHints: bandwidthHints, + graph: routingTx, }, - restrictions, &r.cfg.PathFindingConfig, + restrictions, + &r.cfg.PathFindingConfig, source, target, amt, finalHtlcExpiry, ) if err != nil { diff --git a/routing/router_test.go b/routing/router_test.go index 7ac7527c52..d8b0950f0b 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -79,11 +79,6 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr chain := newMockChain(startingHeight) chainView := newMockChainView(chain) - selfNode, err := graphInstance.graph.SourceNode() - if err != nil { - return nil, nil, err - } - pathFindingConfig := PathFindingConfig{ MinProbability: 0.01, PaymentAttemptPenalty: 100, @@ -104,8 +99,7 @@ func createTestCtxFromGraphInstance(startingHeight uint32, graphInstance *testGr } sessionSource := &SessionSource{ - Graph: graphInstance.graph, - SelfNode: selfNode, + Graph: graphInstance.graph, QueryBandwidth: func(e *channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi { return lnwire.NewMSatFromSatoshis(e.Capacity) }, @@ -2188,10 +2182,8 @@ func TestFindPathFeeWeighting(t *testing.T) { // We'll now attempt a path finding attempt using this set up. Due to // the edge weighting, we should select the direct path over the 2 hop // path even though the direct path has a higher potential time lock. - path, err := findPath( - &graphParams{ - graph: ctx.graph, - }, + path, err := dbFindPath( + ctx.graph, nil, nil, noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, amt, 0, diff --git a/server.go b/server.go index a1dce6ec0d..b56e43adc7 100644 --- a/server.go +++ b/server.go @@ -731,7 +731,6 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, Graph: chanGraph, MissionControl: s.missionControl, QueryBandwidth: queryBandwidth, - SelfNode: selfNode, PathFindingConfig: pathFindingConfig, } From b13616a593c4210e5f7baac006369dc5068aac4f Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 17 Mar 2020 11:53:29 +0100 Subject: [PATCH 438/562] routing/test: use payment session in integrated routing test Cover the payment session in the integrated routing test as a preparation for executing the upcoming mpp split logic as part of the test. --- routing/integrated_routing_context_test.go | 50 ++++++++++++---------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index b5fc955eea..eb66ac37a3 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -95,10 +95,31 @@ func (c *integratedRoutingContext) testPayment(expectedNofAttempts int) { c.t.Fatal(err) } - // Instruct pathfinding to use mission control as a probabiltiy source. - restrictParams := RestrictParams{ - ProbabilitySource: mc.GetProbability, - FeeLimit: lnwire.MaxMilliSatoshi, + getBandwidthHints := func() (map[uint64]lnwire.MilliSatoshi, error) { + // Create bandwidth hints based on local channel balances. + bandwidthHints := map[uint64]lnwire.MilliSatoshi{} + for _, ch := range c.graph.nodes[c.source.pubkey].channels { + bandwidthHints[ch.id] = ch.balance + } + + return bandwidthHints, nil + } + + payment := LightningPayment{ + FinalCLTVDelta: uint16(c.finalExpiry), + FeeLimit: lnwire.MaxMilliSatoshi, + Target: c.target.pubkey, + } + + session := &paymentSession{ + getBandwidthHints: getBandwidthHints, + payment: &payment, + pathFinder: findPath, + getRoutingGraph: func() (routingGraph, func(), error) { + return c.graph, func() {}, nil + }, + pathFindingConfig: c.pathFindingCfg, + missionControl: mc, } // Now the payment control loop starts. It will keep trying routes until @@ -111,30 +132,13 @@ func (c *integratedRoutingContext) testPayment(expectedNofAttempts int) { } // Find a route. - path, err := findPath( - &graphParams{ - graph: c.graph, - bandwidthHints: bandwidthHints, - }, - &restrictParams, - &c.pathFindingCfg, - c.source.pubkey, c.target.pubkey, - c.amt, c.finalExpiry, + route, err := session.RequestRoute( + c.amt, lnwire.MaxMilliSatoshi, 0, 0, ) if err != nil { c.t.Fatal(err) } - finalHop := finalHopParams{ - amt: c.amt, - cltvDelta: uint16(c.finalExpiry), - } - - route, err := newRoute(c.source.pubkey, path, 0, finalHop) - if err != nil { - c.t.Fatal(err) - } - // Send out the htlc on the mock graph. pid := nextPid nextPid++ From 3c6e4612ffa77c031301c480e61d55fc4db0eaaa Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 17 Mar 2020 16:51:42 +0100 Subject: [PATCH 439/562] routing/test: expose full list of htlc attempts --- routing/integrated_routing_context_test.go | 29 ++++++++++++++++------ routing/integrated_routing_test.go | 10 ++++++-- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index eb66ac37a3..96c85d5f2c 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -68,10 +68,19 @@ func newIntegratedRoutingContext(t *testing.T) *integratedRoutingContext { return &ctx } +// htlcAttempt records the route and outcome of an attempted htlc. +type htlcAttempt struct { + route *route.Route + success bool +} + // testPayment launches a test payment and asserts that it is completed after // the expected number of attempts. -func (c *integratedRoutingContext) testPayment(expectedNofAttempts int) { - var nextPid uint64 +func (c *integratedRoutingContext) testPayment() []htlcAttempt { + var ( + nextPid uint64 + attempts []htlcAttempt + ) // Create temporary database for mission control. file, err := ioutil.TempFile("", "*.db") @@ -147,8 +156,14 @@ func (c *integratedRoutingContext) testPayment(expectedNofAttempts int) { c.t.Fatal(err) } + success := htlcResult.failure == nil + attempts = append(attempts, htlcAttempt{ + route: route, + success: success, + }) + // Process the result. - if htlcResult.failure == nil { + if success { err := mc.ReportPaymentSuccess(pid, route) if err != nil { c.t.Fatal(err) @@ -177,11 +192,9 @@ func (c *integratedRoutingContext) testPayment(expectedNofAttempts int) { } } - c.t.Logf("Payment attempts: %v\n", nextPid) - if expectedNofAttempts != int(nextPid) { - c.t.Fatalf("expected %v attempts, but needed %v", - expectedNofAttempts, nextPid) - } + c.t.Logf("Payment attempts: %v\n", len(attempts)) + + return attempts } // getNodeIndex returns the zero-based index of the given node in the route. diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go index 19df17a35e..ccd2211731 100644 --- a/routing/integrated_routing_test.go +++ b/routing/integrated_routing_test.go @@ -47,11 +47,17 @@ func TestProbabilityExtrapolation(t *testing.T) { // a specific number of attempts to safe-guard against accidental // modifications anywhere in the chain of components that is involved in // this test. - ctx.testPayment(5) + attempts := ctx.testPayment() + if len(attempts) != 5 { + t.Fatalf("expected 5 attempts, but needed %v", len(attempts)) + } // If we use a static value for the node probability (no extrapolation // of data from other channels), all ten bad channels will be tried // first before switching to the paid channel. ctx.mcCfg.AprioriWeight = 1 - ctx.testPayment(11) + attempts = ctx.testPayment() + if len(attempts) != 11 { + t.Fatalf("expected 11 attempts, but needed %v", len(attempts)) + } } From 0f8eb80965340773b893e5dc1211f3d452fcdf2b Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 17 Mar 2020 17:07:52 +0100 Subject: [PATCH 440/562] routing/test: use fixed identifiers in test graph --- routing/integrated_routing_context_test.go | 9 ++++- routing/integrated_routing_test.go | 19 ++++++---- routing/mock_graph_test.go | 44 +++++++++++++--------- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index 96c85d5f2c..d421c62fcd 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -11,6 +11,11 @@ import ( "github.com/lightningnetwork/lnd/routing/route" ) +const ( + sourceNodeID = 1 + targetNodeID = 2 +) + // integratedRoutingContext defines the context in which integrated routing // tests run. type integratedRoutingContext struct { @@ -31,8 +36,8 @@ type integratedRoutingContext struct { // context with a source and a target node. func newIntegratedRoutingContext(t *testing.T) *integratedRoutingContext { // Instantiate a mock graph. - source := newMockNode() - target := newMockNode() + source := newMockNode(sourceNodeID) + target := newMockNode(targetNodeID) graph := newMockGraph(t) graph.addNode(source) diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go index ccd2211731..0362f208c9 100644 --- a/routing/integrated_routing_test.go +++ b/routing/integrated_routing_test.go @@ -15,22 +15,25 @@ func TestProbabilityExtrapolation(t *testing.T) { // source -> intermediate1 (free routing) -> intermediate(1-10) (free routing) -> target g := ctx.graph - expensiveNode := newMockNode() + const expensiveNodeID = 3 + expensiveNode := newMockNode(expensiveNodeID) expensiveNode.baseFee = 10000 g.addNode(expensiveNode) - g.addChannel(ctx.source, expensiveNode, 100000) - g.addChannel(ctx.target, expensiveNode, 100000) + g.addChannel(100, sourceNodeID, expensiveNodeID, 100000) + g.addChannel(101, targetNodeID, expensiveNodeID, 100000) - intermediate1 := newMockNode() + const intermediate1NodeID = 4 + intermediate1 := newMockNode(intermediate1NodeID) g.addNode(intermediate1) - g.addChannel(ctx.source, intermediate1, 100000) + g.addChannel(102, sourceNodeID, intermediate1NodeID, 100000) for i := 0; i < 10; i++ { - imNode := newMockNode() + imNodeID := byte(10 + i) + imNode := newMockNode(imNodeID) g.addNode(imNode) - g.addChannel(imNode, ctx.target, 100000) - g.addChannel(imNode, intermediate1, 100000) + g.addChannel(uint64(200+i), imNodeID, targetNodeID, 100000) + g.addChannel(uint64(300+i), imNodeID, intermediate1NodeID, 100000) // The channels from intermediate1 all have insufficient balance. g.nodes[intermediate1.pubkey].channels[imNode.pubkey].balance = 0 diff --git a/routing/mock_graph_test.go b/routing/mock_graph_test.go index 075a416a1a..3834d9e51a 100644 --- a/routing/mock_graph_test.go +++ b/routing/mock_graph_test.go @@ -11,14 +11,9 @@ import ( "github.com/lightningnetwork/lnd/routing/route" ) -// nextTestPubkey is global variable that is used to deterministically generate -// test keys. -var nextTestPubkey byte - // createPubkey return a new test pubkey. -func createPubkey() route.Vertex { - pubkey := route.Vertex{nextTestPubkey} - nextTestPubkey++ +func createPubkey(id byte) route.Vertex { + pubkey := route.Vertex{id} return pubkey } @@ -38,8 +33,8 @@ type mockNode struct { } // newMockNode instantiates a new mock node with a newly generated pubkey. -func newMockNode() *mockNode { - pubkey := createPubkey() +func newMockNode(id byte) *mockNode { + pubkey := createPubkey(id) return &mockNode{ channels: make(map[route.Vertex]*mockChannel), pubkey: pubkey, @@ -106,10 +101,9 @@ func (m *mockNode) fwd(from *mockNode, route *hop) (htlcResult, error) { // mockGraph contains a set of nodes that together for a mocked graph. type mockGraph struct { - t *testing.T - nodes map[route.Vertex]*mockNode - nextChanID uint64 - source *mockNode + t *testing.T + nodes map[route.Vertex]*mockNode + source *mockNode } // newMockGraph instantiates a new mock graph. @@ -122,6 +116,11 @@ func newMockGraph(t *testing.T) *mockGraph { // addNode adds the given mock node to the network. func (m *mockGraph) addNode(node *mockNode) { + m.t.Helper() + + if _, exists := m.nodes[node.pubkey]; exists { + m.t.Fatal("node already exists") + } m.nodes[node.pubkey] = node } @@ -131,16 +130,25 @@ func (m *mockGraph) addNode(node *mockNode) { // Ignore linter error because addChannel isn't yet called with different // capacities. // nolint:unparam -func (m *mockGraph) addChannel(node1, node2 *mockNode, capacity btcutil.Amount) { - id := m.nextChanID - m.nextChanID++ +func (m *mockGraph) addChannel(id uint64, node1id, node2id byte, + capacity btcutil.Amount) { + + node1pubkey := createPubkey(node1id) + node2pubkey := createPubkey(node2id) + + if _, exists := m.nodes[node1pubkey].channels[node2pubkey]; exists { + m.t.Fatal("channel already exists") + } + if _, exists := m.nodes[node2pubkey].channels[node1pubkey]; exists { + m.t.Fatal("channel already exists") + } - m.nodes[node1.pubkey].channels[node2.pubkey] = &mockChannel{ + m.nodes[node1pubkey].channels[node2pubkey] = &mockChannel{ capacity: capacity, id: id, balance: lnwire.NewMSatFromSatoshis(capacity / 2), } - m.nodes[node2.pubkey].channels[node1.pubkey] = &mockChannel{ + m.nodes[node2pubkey].channels[node1pubkey] = &mockChannel{ capacity: capacity, id: id, balance: lnwire.NewMSatFromSatoshis(capacity / 2), From e5c7e9a38c79354178ae0366c0582c9a80fb83fd Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 18 Mar 2020 10:51:07 +0100 Subject: [PATCH 441/562] routing/test: return pathfinding error --- routing/integrated_routing_context_test.go | 6 +++--- routing/integrated_routing_test.go | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index d421c62fcd..418b380caf 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -81,7 +81,7 @@ type htlcAttempt struct { // testPayment launches a test payment and asserts that it is completed after // the expected number of attempts. -func (c *integratedRoutingContext) testPayment() []htlcAttempt { +func (c *integratedRoutingContext) testPayment() ([]htlcAttempt, error) { var ( nextPid uint64 attempts []htlcAttempt @@ -150,7 +150,7 @@ func (c *integratedRoutingContext) testPayment() []htlcAttempt { c.amt, lnwire.MaxMilliSatoshi, 0, 0, ) if err != nil { - c.t.Fatal(err) + return nil, err } // Send out the htlc on the mock graph. @@ -199,7 +199,7 @@ func (c *integratedRoutingContext) testPayment() []htlcAttempt { c.t.Logf("Payment attempts: %v\n", len(attempts)) - return attempts + return attempts, nil } // getNodeIndex returns the zero-based index of the given node in the route. diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go index 0362f208c9..1e77ce8102 100644 --- a/routing/integrated_routing_test.go +++ b/routing/integrated_routing_test.go @@ -50,7 +50,10 @@ func TestProbabilityExtrapolation(t *testing.T) { // a specific number of attempts to safe-guard against accidental // modifications anywhere in the chain of components that is involved in // this test. - attempts := ctx.testPayment() + attempts, err := ctx.testPayment() + if err != nil { + t.Fatalf("payment failed: %v", err) + } if len(attempts) != 5 { t.Fatalf("expected 5 attempts, but needed %v", len(attempts)) } @@ -59,7 +62,10 @@ func TestProbabilityExtrapolation(t *testing.T) { // of data from other channels), all ten bad channels will be tried // first before switching to the paid channel. ctx.mcCfg.AprioriWeight = 1 - attempts = ctx.testPayment() + attempts, err = ctx.testPayment() + if err != nil { + t.Fatalf("payment failed: %v", err) + } if len(attempts) != 11 { t.Fatalf("expected 11 attempts, but needed %v", len(attempts)) } From 46f5fc740036a1a68ace56e46906a51c0e9892d8 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 25 Mar 2020 14:06:48 +0100 Subject: [PATCH 442/562] routing: distinguish between receiver amount and total amount in newRoute --- routing/pathfind.go | 4 +++- routing/pathfind_test.go | 1 + routing/payment_session.go | 1 + routing/router.go | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/routing/pathfind.go b/routing/pathfind.go index 5507444a08..b6879cc6d8 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -74,6 +74,7 @@ type edgePolicyWithSource struct { // custom records and payment address. type finalHopParams struct { amt lnwire.MilliSatoshi + totalAmt lnwire.MilliSatoshi cltvDelta uint16 records record.CustomSet paymentAddr *[32]byte @@ -177,7 +178,8 @@ func newRoute(sourceVertex route.Vertex, // Otherwise attach the mpp record if it exists. if finalHop.paymentAddr != nil { mpp = record.NewMPP( - finalHop.amt, *finalHop.paymentAddr, + finalHop.totalAmt, + *finalHop.paymentAddr, ) } } else { diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 193e752d93..ab54534bda 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -1327,6 +1327,7 @@ func TestNewRoute(t *testing.T) { sourceVertex, testCase.hops, startingHeight, finalHopParams{ amt: testCase.paymentAmount, + totalAmt: testCase.paymentAmount, cltvDelta: finalHopCLTV, records: nil, paymentAddr: testCase.paymentAddr, diff --git a/routing/payment_session.go b/routing/payment_session.go index a28f6a6f13..9f9c347c98 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -196,6 +196,7 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, sourceVertex, path, height, finalHopParams{ amt: maxAmt, + totalAmt: maxAmt, cltvDelta: finalCltvDelta, records: p.payment.DestCustomRecords, paymentAddr: p.payment.PaymentAddr, diff --git a/routing/router.go b/routing/router.go index c554ceee6e..7d80305b98 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1456,6 +1456,7 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, source, path, uint32(currentHeight), finalHopParams{ amt: amt, + totalAmt: amt, cltvDelta: finalExpiry, records: destCustomRecords, }, @@ -2513,6 +2514,7 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi, source, pathEdges, uint32(height), finalHopParams{ amt: receiverAmt, + totalAmt: receiverAmt, cltvDelta: uint16(finalCltvDelta), records: nil, }, From e9bd691e6a17a0c4c9ff3fd99f60d855bd3cad9b Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 28 Jan 2020 16:07:34 +0100 Subject: [PATCH 443/562] routerrpc+routing: adapt payment session for multi shard send Modifies the payment session to launch additional pathfinding attempts for lower amounts. If a single shot payment isn't possible, the goal is to try to complete the payment using multiple htlcs. In previous commits, the payment lifecycle has been prepared to deal with partial-amount routes returned from the payment session. It will query for additional shards if needed. Additionally a new rpc payment parameter is added that controls the maximum number of shards that will be used for the payment. --- lnrpc/routerrpc/router.pb.go | 276 +++++++++++---------- lnrpc/routerrpc/router.proto | 6 + lnrpc/routerrpc/router_backend.go | 8 + routing/integrated_routing_context_test.go | 53 +++- routing/integrated_routing_test.go | 215 +++++++++++++++- routing/pathfind_test.go | 6 + routing/payment_session.go | 144 +++++++---- routing/payment_session_source.go | 1 + routing/router.go | 4 + rpcserver.go | 4 + 10 files changed, 520 insertions(+), 197 deletions(-) diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 60f70e5e97..018c3d8c32 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -221,10 +221,14 @@ type SendPaymentRequest struct { //optional or remote may be set, but not both. If this field is nil or empty, //the router will try to load destination features from the graph as a //fallback. - DestFeatures []lnrpc.FeatureBit `protobuf:"varint,16,rep,packed,name=dest_features,json=destFeatures,proto3,enum=lnrpc.FeatureBit" json:"dest_features,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + DestFeatures []lnrpc.FeatureBit `protobuf:"varint,16,rep,packed,name=dest_features,json=destFeatures,proto3,enum=lnrpc.FeatureBit" json:"dest_features,omitempty"` + //* + //The maximum number of partial payments that may be use to complete the full + //amount. + MaxHtlcs uint32 `protobuf:"varint,17,opt,name=max_htlcs,json=maxHtlcs,proto3" json:"max_htlcs,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *SendPaymentRequest) Reset() { *m = SendPaymentRequest{} } @@ -364,6 +368,13 @@ func (m *SendPaymentRequest) GetDestFeatures() []lnrpc.FeatureBit { return nil } +func (m *SendPaymentRequest) GetMaxHtlcs() uint32 { + if m != nil { + return m.MaxHtlcs + } + return 0 +} + type TrackPaymentRequest struct { /// The hash of the payment to look up. PaymentHash []byte `protobuf:"bytes,1,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"` @@ -1595,134 +1606,135 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2017 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0x5d, 0x77, 0xdb, 0x48, - 0x19, 0x5e, 0xc5, 0x72, 0x62, 0xbf, 0xfe, 0x52, 0xc6, 0xdd, 0xd4, 0x38, 0xed, 0xe2, 0x15, 0x6c, - 0xeb, 0x53, 0x4a, 0xd2, 0x0d, 0x1c, 0xe8, 0x01, 0xb6, 0xe0, 0x58, 0xca, 0x46, 0x8d, 0x23, 0x79, - 0xc7, 0x4e, 0xdb, 0xa5, 0x17, 0x73, 0x14, 0x7b, 0x1c, 0x8b, 0xc8, 0x92, 0x91, 0xc6, 0xed, 0xc9, - 0x25, 0xb7, 0xfc, 0x11, 0xfe, 0x04, 0xff, 0x85, 0x5b, 0xee, 0xb8, 0xe3, 0x70, 0xc9, 0x99, 0x91, - 0xc6, 0x96, 0x13, 0xa7, 0xbb, 0x37, 0x89, 0xf4, 0xbc, 0xcf, 0xbc, 0x1f, 0xf3, 0x3e, 0xf3, 0x21, - 0xc3, 0x5e, 0x14, 0x2e, 0x18, 0x8d, 0xa2, 0xf9, 0xe8, 0x30, 0x79, 0x3a, 0x98, 0x47, 0x21, 0x0b, - 0x51, 0x71, 0x89, 0x37, 0x8b, 0xd1, 0x7c, 0x94, 0xa0, 0xfa, 0xff, 0xf2, 0x80, 0x06, 0x34, 0x18, - 0xf7, 0xdd, 0x9b, 0x19, 0x0d, 0x18, 0xa6, 0x7f, 0x5d, 0xd0, 0x98, 0x21, 0x04, 0xea, 0x98, 0xc6, - 0xac, 0xa1, 0xb4, 0x94, 0x76, 0x19, 0x8b, 0x67, 0xa4, 0x41, 0xce, 0x9d, 0xb1, 0xc6, 0x56, 0x4b, - 0x69, 0xe7, 0x30, 0x7f, 0x44, 0x3f, 0x81, 0x82, 0x3b, 0x63, 0x64, 0x16, 0xbb, 0xac, 0x51, 0x16, - 0xf0, 0x8e, 0x3b, 0x63, 0xe7, 0xb1, 0xcb, 0xd0, 0x97, 0x50, 0x9e, 0x27, 0x2e, 0xc9, 0xd4, 0x8d, - 0xa7, 0x8d, 0x9c, 0x70, 0x54, 0x4a, 0xb1, 0x53, 0x37, 0x9e, 0xa2, 0x36, 0x68, 0x13, 0x2f, 0x70, - 0x7d, 0x32, 0xf2, 0xd9, 0x07, 0x32, 0xa6, 0x3e, 0x73, 0x1b, 0x6a, 0x4b, 0x69, 0xe7, 0x71, 0x55, - 0xe0, 0x5d, 0x9f, 0x7d, 0x30, 0x38, 0x8a, 0x9e, 0x42, 0x4d, 0x3a, 0x8b, 0x92, 0x04, 0x1b, 0xf9, - 0x96, 0xd2, 0x2e, 0xe2, 0xea, 0x7c, 0x3d, 0xed, 0xa7, 0x50, 0x63, 0xde, 0x8c, 0x86, 0x0b, 0x46, - 0x62, 0x3a, 0x0a, 0x83, 0x71, 0xdc, 0xd8, 0x4e, 0x3c, 0xa6, 0xf0, 0x20, 0x41, 0x91, 0x0e, 0x95, - 0x09, 0xa5, 0xc4, 0xf7, 0x66, 0x1e, 0x23, 0x3c, 0xfd, 0x1d, 0x91, 0x7e, 0x69, 0x42, 0x69, 0x8f, - 0x63, 0x03, 0x97, 0xa1, 0x9f, 0x43, 0x75, 0xc5, 0x11, 0x35, 0x56, 0x04, 0xa9, 0x2c, 0x49, 0xa2, - 0xd0, 0xe7, 0xa0, 0x85, 0x0b, 0x76, 0x15, 0x7a, 0xc1, 0x15, 0x19, 0x4d, 0xdd, 0x80, 0x78, 0xe3, - 0x46, 0xa1, 0xa5, 0xb4, 0xd5, 0xe3, 0xad, 0x17, 0x0a, 0xae, 0x4a, 0x5b, 0x77, 0xea, 0x06, 0xd6, - 0x18, 0x3d, 0x81, 0x9a, 0xef, 0xc6, 0x8c, 0x4c, 0xc3, 0x39, 0x99, 0x2f, 0x2e, 0xaf, 0xe9, 0x4d, - 0xa3, 0x2a, 0x66, 0xa6, 0xc2, 0xe1, 0xd3, 0x70, 0xde, 0x17, 0x20, 0x7a, 0x0c, 0x20, 0x66, 0x45, - 0x04, 0x6f, 0x14, 0x45, 0x0d, 0x45, 0x8e, 0x88, 0xc0, 0xe8, 0x6b, 0x28, 0x89, 0x6e, 0x92, 0xa9, - 0x17, 0xb0, 0xb8, 0x01, 0xad, 0x5c, 0xbb, 0x74, 0xa4, 0x1d, 0xf8, 0x01, 0x6f, 0x2c, 0xe6, 0x96, - 0x53, 0x2f, 0x60, 0x18, 0x22, 0xf9, 0x18, 0xa3, 0x31, 0xd4, 0x79, 0x17, 0xc9, 0x68, 0x11, 0xb3, - 0x70, 0x46, 0x22, 0x3a, 0x0a, 0xa3, 0x71, 0xdc, 0x28, 0x89, 0xa1, 0xbf, 0x3e, 0x58, 0x8a, 0xe3, - 0xe0, 0xae, 0x1a, 0x0e, 0x0c, 0x1a, 0xb3, 0xae, 0x18, 0x87, 0x93, 0x61, 0x66, 0xc0, 0xa2, 0x1b, - 0xbc, 0x3b, 0xbe, 0x8d, 0xa3, 0xe7, 0x80, 0x5c, 0xdf, 0x0f, 0x3f, 0x92, 0x98, 0xfa, 0x13, 0x92, - 0x76, 0xa7, 0x51, 0x6b, 0x29, 0xed, 0x02, 0xd6, 0x84, 0x65, 0x40, 0xfd, 0x49, 0xea, 0x1e, 0xfd, - 0x06, 0x2a, 0x22, 0xa7, 0x09, 0x75, 0xd9, 0x22, 0xa2, 0x71, 0x43, 0x6b, 0xe5, 0xda, 0xd5, 0xa3, - 0xdd, 0xb4, 0x90, 0x93, 0x04, 0x3e, 0xf6, 0x18, 0x2e, 0x73, 0x5e, 0xfa, 0x1e, 0x37, 0x0d, 0xd8, - 0xdb, 0x9c, 0x12, 0xd7, 0x28, 0x9f, 0x53, 0x2e, 0x5b, 0x15, 0xf3, 0x47, 0xf4, 0x00, 0xf2, 0x1f, - 0x5c, 0x7f, 0x41, 0x85, 0x6e, 0xcb, 0x38, 0x79, 0xf9, 0xdd, 0xd6, 0x4b, 0x45, 0x7f, 0x09, 0xf5, - 0x61, 0xe4, 0x8e, 0xae, 0x6f, 0x49, 0xff, 0xb6, 0x72, 0x95, 0x3b, 0xca, 0xd5, 0x5f, 0x41, 0x4d, - 0x4c, 0xf2, 0x09, 0xa5, 0x9f, 0x5a, 0x30, 0x0f, 0x81, 0x2f, 0x07, 0x21, 0xaf, 0x64, 0xd1, 0x6c, - 0xbb, 0x33, 0xae, 0x2c, 0x7d, 0x0c, 0xda, 0x6a, 0x7c, 0x3c, 0x0f, 0x83, 0x98, 0xf2, 0xd5, 0xc0, - 0x7b, 0xc0, 0x65, 0xc4, 0x55, 0x27, 0xf4, 0xa6, 0x88, 0x51, 0xd5, 0x14, 0x3f, 0xa1, 0x54, 0x28, - 0xee, 0x49, 0x22, 0x72, 0xe2, 0x87, 0xa3, 0x6b, 0xbe, 0x6c, 0xdc, 0x9b, 0xd4, 0x7d, 0x85, 0xc3, - 0xbd, 0x70, 0x74, 0x6d, 0x70, 0x50, 0x7f, 0x9f, 0xac, 0xec, 0x61, 0x28, 0x62, 0xfd, 0xf8, 0xf2, - 0x90, 0x0e, 0x79, 0x21, 0x07, 0xe1, 0xb6, 0x74, 0x54, 0xce, 0xea, 0x0a, 0x27, 0x26, 0xfd, 0x3d, - 0xd4, 0xd7, 0x9c, 0xa7, 0x55, 0x34, 0xa1, 0x30, 0x8f, 0xa8, 0x37, 0x73, 0xaf, 0x68, 0xea, 0x79, - 0xf9, 0x8e, 0xda, 0xb0, 0x33, 0x71, 0x3d, 0x7f, 0x11, 0x49, 0xc7, 0x55, 0xd9, 0xe7, 0x04, 0xc5, - 0xd2, 0xac, 0x3f, 0x82, 0x26, 0xa6, 0x31, 0x65, 0xe7, 0x5e, 0x1c, 0x7b, 0x61, 0xd0, 0x0d, 0x03, - 0x16, 0x85, 0x7e, 0x5a, 0x81, 0xfe, 0x18, 0xf6, 0x37, 0x5a, 0x93, 0x14, 0xf8, 0xe0, 0xef, 0x16, - 0x34, 0xba, 0xd9, 0x3c, 0xf8, 0x3b, 0xd8, 0xdf, 0x68, 0x4d, 0xf3, 0x7f, 0x0e, 0xf9, 0xb9, 0xeb, - 0x45, 0x71, 0x63, 0x4b, 0xac, 0x8b, 0xbd, 0xcc, 0xba, 0xe8, 0xbb, 0x5e, 0x74, 0xea, 0xc5, 0x2c, - 0x8c, 0x6e, 0x70, 0x42, 0x7a, 0xad, 0x16, 0x14, 0x6d, 0x4b, 0xff, 0xbb, 0x02, 0xa5, 0x8c, 0x11, - 0xed, 0x43, 0x31, 0x08, 0xc7, 0x94, 0x4c, 0xa2, 0x70, 0x26, 0x27, 0x81, 0x03, 0x27, 0x51, 0x38, - 0xe3, 0x9a, 0x10, 0x46, 0x16, 0xa6, 0x82, 0xdc, 0xe6, 0xaf, 0xc3, 0x10, 0xfd, 0x12, 0x76, 0xa6, - 0x89, 0x03, 0xb1, 0x17, 0x95, 0x8e, 0xea, 0xb7, 0x62, 0x1b, 0x2e, 0x73, 0xb1, 0xe4, 0xbc, 0x56, - 0x0b, 0x39, 0x4d, 0x7d, 0xad, 0x16, 0x54, 0x2d, 0xff, 0x5a, 0x2d, 0xe4, 0xb5, 0xed, 0xd7, 0x6a, - 0x61, 0x5b, 0xdb, 0xd1, 0xff, 0xad, 0x40, 0x41, 0xb2, 0x79, 0x26, 0x7c, 0x4a, 0x09, 0xd7, 0x45, - 0x2a, 0xa6, 0x02, 0x07, 0x86, 0xde, 0x8c, 0xa2, 0x16, 0x94, 0x85, 0x71, 0x5d, 0xa2, 0xc0, 0xb1, - 0x8e, 0x90, 0xa9, 0xd8, 0x24, 0x25, 0x43, 0xe8, 0x51, 0x4d, 0x37, 0xc9, 0x84, 0x22, 0xf7, 0xf9, - 0x78, 0x31, 0x1a, 0xd1, 0x38, 0x4e, 0xa2, 0xe4, 0x13, 0x4a, 0x8a, 0x89, 0x40, 0x4f, 0xa0, 0x26, - 0x29, 0x32, 0xd6, 0x76, 0xa2, 0xd7, 0x14, 0x4e, 0xc3, 0xb5, 0x41, 0xcb, 0xf2, 0x66, 0xab, 0x6d, - 0xb9, 0xba, 0x22, 0xf2, 0xa0, 0x49, 0xf1, 0xfa, 0x5f, 0xe0, 0xa1, 0x68, 0x65, 0x3f, 0x0a, 0x2f, - 0xdd, 0x4b, 0xcf, 0xf7, 0xd8, 0x8d, 0x14, 0x39, 0x2f, 0x3c, 0x0a, 0x67, 0x84, 0xcf, 0xad, 0x6c, - 0x01, 0x07, 0xec, 0x70, 0x4c, 0x79, 0x0b, 0x58, 0x98, 0x98, 0xd2, 0x16, 0xb0, 0x50, 0x18, 0xb2, - 0xc7, 0x59, 0x6e, 0xed, 0x38, 0xd3, 0xaf, 0xa1, 0x71, 0x37, 0x56, 0xaa, 0x99, 0x16, 0x94, 0xe6, - 0x2b, 0x58, 0x84, 0x53, 0x70, 0x16, 0xca, 0xf6, 0x76, 0xeb, 0x87, 0x7b, 0xab, 0xff, 0x43, 0x81, - 0xdd, 0xe3, 0x85, 0xe7, 0x8f, 0xd7, 0x16, 0x6e, 0x36, 0x3b, 0x65, 0xfd, 0xb0, 0xdd, 0x74, 0x92, - 0x6e, 0x6d, 0x3c, 0x49, 0x37, 0x9d, 0x56, 0xb9, 0x7b, 0x4f, 0xab, 0x9f, 0x42, 0x69, 0x75, 0x50, - 0xc5, 0x0d, 0xb5, 0x95, 0x6b, 0x97, 0x31, 0x4c, 0xe5, 0x29, 0x15, 0xeb, 0x2f, 0x01, 0x65, 0x13, - 0x4d, 0x27, 0x64, 0xb9, 0x7f, 0x28, 0xf7, 0xef, 0x1f, 0x8f, 0xa0, 0x39, 0x58, 0x5c, 0xc6, 0xa3, - 0xc8, 0xbb, 0xa4, 0xa7, 0xcc, 0x1f, 0x99, 0x1f, 0x68, 0xc0, 0x62, 0xb9, 0x4a, 0xff, 0xab, 0x42, - 0x71, 0x89, 0xa2, 0x03, 0xa8, 0x7b, 0xc1, 0x28, 0x9c, 0xc9, 0xa4, 0x03, 0xea, 0xf3, 0xbc, 0x93, - 0x4d, 0x7e, 0x57, 0x9a, 0xba, 0x89, 0xc5, 0x1a, 0x73, 0xfe, 0x5a, 0x91, 0x29, 0x7f, 0x2b, 0xe1, - 0x67, 0x6b, 0x4c, 0xf8, 0x6d, 0xd0, 0x96, 0xfe, 0xa7, 0xcc, 0x1f, 0x2d, 0x27, 0x05, 0x57, 0x25, - 0xce, 0x93, 0x49, 0x98, 0x4b, 0xcf, 0x92, 0xa9, 0x26, 0x4c, 0x89, 0xa7, 0xcc, 0x2f, 0xa1, 0xcc, - 0xd7, 0x43, 0xcc, 0xdc, 0xd9, 0x9c, 0x04, 0xb1, 0x58, 0x17, 0x2a, 0x2e, 0x2d, 0x31, 0x3b, 0x46, - 0xdf, 0x00, 0x50, 0x5e, 0x1f, 0x61, 0x37, 0x73, 0x2a, 0x96, 0x44, 0xf5, 0xe8, 0x8b, 0x8c, 0x30, - 0x96, 0x13, 0x70, 0x20, 0xfe, 0x0e, 0x6f, 0xe6, 0x14, 0x17, 0xa9, 0x7c, 0x44, 0xaf, 0xa0, 0x32, - 0x09, 0xa3, 0x8f, 0x6e, 0x34, 0x26, 0x02, 0x4c, 0xb7, 0x8d, 0x87, 0x19, 0x0f, 0x27, 0x89, 0x5d, - 0x0c, 0x3f, 0xfd, 0x0c, 0x97, 0x27, 0x99, 0x77, 0x74, 0x06, 0x48, 0x8e, 0x17, 0xab, 0x3c, 0x71, - 0x52, 0x10, 0x4e, 0xf6, 0xef, 0x3a, 0xe1, 0x9b, 0xb4, 0x74, 0xa4, 0x4d, 0x6e, 0x61, 0xe8, 0xf7, - 0x50, 0x8e, 0x29, 0x63, 0x3e, 0x4d, 0xdd, 0x14, 0x85, 0x9b, 0xbd, 0xb5, 0x6b, 0x05, 0x37, 0x4b, - 0x0f, 0xa5, 0x78, 0xf5, 0x8a, 0x8e, 0xa1, 0xe6, 0x7b, 0xc1, 0x75, 0x36, 0x0d, 0x10, 0xe3, 0x1b, - 0x99, 0xf1, 0x3d, 0x2f, 0xb8, 0xce, 0xe6, 0x50, 0xf1, 0xb3, 0x80, 0xfe, 0x07, 0x28, 0x2e, 0x67, - 0x09, 0x95, 0x60, 0xe7, 0xc2, 0x3e, 0xb3, 0x9d, 0xb7, 0xb6, 0xf6, 0x19, 0x2a, 0x80, 0x3a, 0x30, - 0x6d, 0x43, 0x53, 0x38, 0x8c, 0xcd, 0xae, 0x69, 0xbd, 0x31, 0xb5, 0x2d, 0xfe, 0x72, 0xe2, 0xe0, - 0xb7, 0x1d, 0x6c, 0x68, 0xb9, 0xe3, 0x1d, 0xc8, 0x8b, 0xb8, 0xfa, 0x3f, 0x15, 0x28, 0x88, 0x0e, - 0x06, 0x93, 0x10, 0xfd, 0x02, 0x96, 0xe2, 0x12, 0x9b, 0x1b, 0x3f, 0x70, 0x85, 0xea, 0x2a, 0x78, - 0x29, 0x98, 0x61, 0x8a, 0x73, 0xf2, 0x52, 0x1a, 0x4b, 0xf2, 0x56, 0x42, 0x96, 0x86, 0x25, 0xf9, - 0x59, 0xc6, 0xf3, 0xda, 0x96, 0xa3, 0xe2, 0x9a, 0x34, 0xc8, 0x1d, 0xf6, 0x59, 0xc6, 0xf1, 0xda, - 0x4e, 0xac, 0xe2, 0x9a, 0x34, 0xa4, 0x5c, 0xfd, 0xb7, 0x50, 0xce, 0xf6, 0x1c, 0x3d, 0x05, 0xd5, - 0x0b, 0x26, 0x61, 0xba, 0x10, 0xeb, 0xb7, 0xc4, 0xc5, 0x8b, 0xc4, 0x82, 0xa0, 0x23, 0xd0, 0x6e, - 0xf7, 0x59, 0xaf, 0x40, 0x29, 0xd3, 0x34, 0xfd, 0x5f, 0x0a, 0x54, 0xd6, 0x9a, 0xf0, 0xa3, 0xbd, - 0xa3, 0x6f, 0xa0, 0xfc, 0xd1, 0x8b, 0x28, 0xc9, 0x1e, 0xff, 0xd5, 0xa3, 0xe6, 0xfa, 0xf1, 0x2f, - 0xff, 0x77, 0xc3, 0x31, 0xc5, 0x25, 0xce, 0x4f, 0x01, 0xf4, 0x47, 0xa8, 0xa6, 0x23, 0xc9, 0x98, - 0x32, 0xd7, 0xf3, 0xc5, 0x54, 0x55, 0xd7, 0xe4, 0x91, 0x72, 0x0d, 0x61, 0xc7, 0x95, 0x49, 0xf6, - 0x15, 0x7d, 0xb5, 0x72, 0x10, 0xb3, 0xc8, 0x0b, 0xae, 0xc4, 0xfc, 0x15, 0x97, 0xb4, 0x81, 0x00, - 0x9f, 0xfd, 0x4d, 0x85, 0xca, 0x9a, 0x9f, 0x75, 0x21, 0x55, 0xa0, 0x68, 0x3b, 0xc4, 0x30, 0x87, - 0x1d, 0xab, 0xa7, 0x29, 0x48, 0x83, 0xb2, 0x63, 0x5b, 0x8e, 0x4d, 0x0c, 0xb3, 0xeb, 0x18, 0x5c, - 0x52, 0x9f, 0xc3, 0x6e, 0xcf, 0xb2, 0xcf, 0x88, 0xed, 0x0c, 0x89, 0xd9, 0xb3, 0xbe, 0xb5, 0x8e, - 0x7b, 0xa6, 0x96, 0x43, 0x0f, 0x40, 0x73, 0x6c, 0xd2, 0x3d, 0xed, 0x58, 0x36, 0x19, 0x5a, 0xe7, - 0xa6, 0x73, 0x31, 0xd4, 0x54, 0x8e, 0x9e, 0x0e, 0x7b, 0x5d, 0x62, 0xbe, 0xeb, 0x9a, 0xa6, 0x31, - 0x20, 0xe7, 0x9d, 0x77, 0x5a, 0x1e, 0x35, 0xe0, 0x81, 0x65, 0x0f, 0x2e, 0x4e, 0x4e, 0xac, 0xae, - 0x65, 0xda, 0x43, 0x72, 0xdc, 0xe9, 0x75, 0xec, 0xae, 0xa9, 0x6d, 0xa3, 0x3d, 0x40, 0x96, 0xdd, - 0x75, 0xce, 0xfb, 0x3d, 0x73, 0x68, 0x12, 0x29, 0xdd, 0x1d, 0x54, 0x87, 0x9a, 0xf0, 0xd3, 0x31, - 0x0c, 0x72, 0xd2, 0xb1, 0x7a, 0xa6, 0xa1, 0x15, 0x78, 0x26, 0x29, 0x63, 0x40, 0x0c, 0x6b, 0xd0, - 0x39, 0xe6, 0x70, 0x91, 0xc7, 0xb4, 0xec, 0x37, 0x8e, 0xd5, 0x35, 0x49, 0x97, 0xbb, 0xe5, 0x28, - 0x70, 0xb2, 0x44, 0x2f, 0x6c, 0xc3, 0xc4, 0xfd, 0x8e, 0x65, 0x68, 0x25, 0xb4, 0x0f, 0x0f, 0x25, - 0x6c, 0xbe, 0xeb, 0x5b, 0xf8, 0x7b, 0x32, 0x74, 0x1c, 0x32, 0x70, 0x1c, 0x5b, 0x2b, 0x67, 0x3d, - 0xf1, 0x6a, 0x9d, 0xbe, 0x69, 0x6b, 0x15, 0xf4, 0x10, 0xea, 0xe7, 0xfd, 0x3e, 0x91, 0x16, 0x59, - 0x6c, 0x95, 0xd3, 0x3b, 0x86, 0x81, 0xcd, 0xc1, 0x80, 0x9c, 0x5b, 0x83, 0xf3, 0xce, 0xb0, 0x7b, - 0xaa, 0xd5, 0x78, 0x49, 0x03, 0x73, 0x48, 0x86, 0xce, 0xb0, 0xd3, 0x5b, 0xe1, 0x1a, 0x4f, 0x68, - 0x85, 0xf3, 0xa0, 0x3d, 0xe7, 0xad, 0xb6, 0xcb, 0x27, 0x9c, 0xc3, 0xce, 0x9b, 0x34, 0x45, 0xc4, - 0x6b, 0x4f, 0xdb, 0x23, 0x63, 0x6a, 0x75, 0x0e, 0x5a, 0xf6, 0x9b, 0x4e, 0xcf, 0x32, 0xc8, 0x99, - 0xf9, 0xbd, 0x58, 0xfa, 0x0f, 0x38, 0x98, 0x64, 0x46, 0xfa, 0xd8, 0xf9, 0x96, 0x27, 0xa2, 0x7d, - 0x8e, 0x10, 0x54, 0xbb, 0x16, 0xee, 0x5e, 0xf4, 0x3a, 0x98, 0x60, 0xe7, 0x62, 0x68, 0x6a, 0x7b, - 0x47, 0xff, 0xc9, 0xc3, 0xb6, 0x38, 0xa8, 0x22, 0xf4, 0x8a, 0xeb, 0x7f, 0xf9, 0x2d, 0x84, 0x1e, - 0x7f, 0xf2, 0x1b, 0xa9, 0x29, 0x2f, 0xb3, 0x29, 0xfc, 0x42, 0x41, 0x7f, 0x82, 0x72, 0xf6, 0xfb, - 0x02, 0x65, 0xf7, 0xf6, 0x0d, 0x1f, 0x1e, 0x1b, 0x3c, 0x9c, 0x81, 0x66, 0xc6, 0xcc, 0x9b, 0xb9, - 0x8c, 0xca, 0xef, 0x05, 0xd4, 0xcc, 0x78, 0xb9, 0xf5, 0x11, 0xd2, 0xdc, 0xdf, 0x68, 0x4b, 0x4f, - 0xe5, 0x5e, 0x52, 0x4e, 0x7a, 0x63, 0xbf, 0x53, 0xce, 0xfa, 0x67, 0x42, 0xf3, 0x8b, 0xfb, 0xcc, - 0xa9, 0xb7, 0x31, 0xd4, 0x37, 0x5c, 0xc2, 0xd1, 0x57, 0xd9, 0x0c, 0xee, 0xbd, 0xc2, 0x37, 0x9f, - 0xfc, 0x10, 0x6d, 0x15, 0x65, 0xc3, 0x6d, 0x7d, 0x2d, 0xca, 0xfd, 0x77, 0xfd, 0xb5, 0x28, 0x9f, - 0xba, 0xf4, 0xbf, 0x07, 0xed, 0xf6, 0xe5, 0x0e, 0xe9, 0xb7, 0xc7, 0xde, 0xbd, 0x65, 0x36, 0x7f, - 0xf6, 0x49, 0x4e, 0xea, 0xdc, 0x02, 0x58, 0x5d, 0x91, 0xd0, 0xa3, 0xcc, 0x90, 0x3b, 0x57, 0xbc, - 0xe6, 0xe3, 0x7b, 0xac, 0xa9, 0xab, 0x21, 0xd4, 0x37, 0xdc, 0x99, 0xd6, 0x66, 0xe3, 0xfe, 0x3b, - 0x55, 0xf3, 0xc1, 0xa6, 0xab, 0xc5, 0x0b, 0xe5, 0xf8, 0xeb, 0x3f, 0x1f, 0x5e, 0x79, 0x6c, 0xba, - 0xb8, 0x3c, 0x18, 0x85, 0xb3, 0x43, 0xdf, 0xbb, 0x9a, 0xb2, 0xc0, 0x0b, 0xae, 0x02, 0xca, 0x3e, - 0x86, 0xd1, 0xf5, 0xa1, 0x1f, 0x8c, 0x0f, 0x85, 0x2e, 0x0f, 0x97, 0xc3, 0x2f, 0xb7, 0xc5, 0x6f, - 0x47, 0xbf, 0xfa, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x74, 0xbe, 0x98, 0x4d, 0x6b, 0x12, 0x00, - 0x00, + // 2039 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xcd, 0x76, 0xdb, 0xc6, + 0x15, 0x0e, 0x44, 0x50, 0x22, 0x2f, 0xff, 0xa0, 0xa1, 0x23, 0xb3, 0x54, 0x9c, 0x32, 0x68, 0x63, + 0xf3, 0xb8, 0xae, 0xe4, 0xa8, 0x3d, 0xad, 0x4f, 0xdb, 0xb8, 0xa5, 0x08, 0x28, 0x82, 0x45, 0x01, + 0xcc, 0x10, 0xb2, 0x9d, 0x7a, 0x31, 0x07, 0x22, 0x87, 0x22, 0x2a, 0xfc, 0xb0, 0xc0, 0xd0, 0x8e, + 0x96, 0xdd, 0x76, 0xdf, 0x67, 0xe8, 0x4b, 0xf4, 0x5d, 0xba, 0xed, 0xae, 0xbb, 0xae, 0x7b, 0x66, + 0x00, 0x90, 0xa0, 0x44, 0x39, 0xd9, 0xd8, 0x9c, 0xef, 0x7e, 0x73, 0xe7, 0xde, 0xb9, 0xdf, 0x9d, + 0x19, 0x08, 0xf6, 0xa2, 0x70, 0xc1, 0x68, 0x14, 0xcd, 0xc7, 0x87, 0xc9, 0xaf, 0x83, 0x79, 0x14, + 0xb2, 0x10, 0x95, 0x97, 0x78, 0xbb, 0x1c, 0xcd, 0xc7, 0x09, 0xaa, 0xfe, 0x63, 0x1b, 0xd0, 0x88, + 0x06, 0x93, 0xa1, 0x73, 0xe3, 0xd3, 0x80, 0x61, 0xfa, 0xd7, 0x05, 0x8d, 0x19, 0x42, 0x20, 0x4f, + 0x68, 0xcc, 0x5a, 0x52, 0x47, 0xea, 0x56, 0xb1, 0xf8, 0x8d, 0x14, 0x28, 0x38, 0x3e, 0x6b, 0x6d, + 0x75, 0xa4, 0x6e, 0x01, 0xf3, 0x9f, 0xe8, 0x27, 0x50, 0x72, 0x7c, 0x46, 0xfc, 0xd8, 0x61, 0xad, + 0xaa, 0x80, 0x77, 0x1c, 0x9f, 0x9d, 0xc7, 0x0e, 0x43, 0x5f, 0x40, 0x75, 0x9e, 0xb8, 0x24, 0x33, + 0x27, 0x9e, 0xb5, 0x0a, 0xc2, 0x51, 0x25, 0xc5, 0x4e, 0x9d, 0x78, 0x86, 0xba, 0xa0, 0x4c, 0xdd, + 0xc0, 0xf1, 0xc8, 0xd8, 0x63, 0xef, 0xc9, 0x84, 0x7a, 0xcc, 0x69, 0xc9, 0x1d, 0xa9, 0x5b, 0xc4, + 0x75, 0x81, 0xf7, 0x3d, 0xf6, 0x5e, 0xe3, 0x28, 0x7a, 0x02, 0x8d, 0xcc, 0x59, 0x94, 0x04, 0xd8, + 0x2a, 0x76, 0xa4, 0x6e, 0x19, 0xd7, 0xe7, 0xeb, 0x61, 0x3f, 0x81, 0x06, 0x73, 0x7d, 0x1a, 0x2e, + 0x18, 0x89, 0xe9, 0x38, 0x0c, 0x26, 0x71, 0x6b, 0x3b, 0xf1, 0x98, 0xc2, 0xa3, 0x04, 0x45, 0x2a, + 0xd4, 0xa6, 0x94, 0x12, 0xcf, 0xf5, 0x5d, 0x46, 0x78, 0xf8, 0x3b, 0x22, 0xfc, 0xca, 0x94, 0xd2, + 0x01, 0xc7, 0x46, 0x0e, 0x43, 0x3f, 0x87, 0xfa, 0x8a, 0x23, 0x72, 0xac, 0x09, 0x52, 0x35, 0x23, + 0x89, 0x44, 0x9f, 0x81, 0x12, 0x2e, 0xd8, 0x55, 0xe8, 0x06, 0x57, 0x64, 0x3c, 0x73, 0x02, 0xe2, + 0x4e, 0x5a, 0xa5, 0x8e, 0xd4, 0x95, 0x8f, 0xb7, 0x9e, 0x4b, 0xb8, 0x9e, 0xd9, 0xfa, 0x33, 0x27, + 0x30, 0x26, 0xe8, 0x31, 0x34, 0x3c, 0x27, 0x66, 0x64, 0x16, 0xce, 0xc9, 0x7c, 0x71, 0x79, 0x4d, + 0x6f, 0x5a, 0x75, 0xb1, 0x33, 0x35, 0x0e, 0x9f, 0x86, 0xf3, 0xa1, 0x00, 0xd1, 0x23, 0x00, 0xb1, + 0x2b, 0x62, 0xf1, 0x56, 0x59, 0xe4, 0x50, 0xe6, 0x88, 0x58, 0x18, 0x7d, 0x05, 0x15, 0x51, 0x4d, + 0x32, 0x73, 0x03, 0x16, 0xb7, 0xa0, 0x53, 0xe8, 0x56, 0x8e, 0x94, 0x03, 0x2f, 0xe0, 0x85, 0xc5, + 0xdc, 0x72, 0xea, 0x06, 0x0c, 0x43, 0x94, 0xfd, 0x8c, 0xd1, 0x04, 0x9a, 0xbc, 0x8a, 0x64, 0xbc, + 0x88, 0x59, 0xe8, 0x93, 0x88, 0x8e, 0xc3, 0x68, 0x12, 0xb7, 0x2a, 0x62, 0xea, 0xaf, 0x0f, 0x96, + 0xe2, 0x38, 0xb8, 0xab, 0x86, 0x03, 0x8d, 0xc6, 0xac, 0x2f, 0xe6, 0xe1, 0x64, 0x9a, 0x1e, 0xb0, + 0xe8, 0x06, 0xef, 0x4e, 0x6e, 0xe3, 0xe8, 0x19, 0x20, 0xc7, 0xf3, 0xc2, 0x0f, 0x24, 0xa6, 0xde, + 0x94, 0xa4, 0xd5, 0x69, 0x35, 0x3a, 0x52, 0xb7, 0x84, 0x15, 0x61, 0x19, 0x51, 0x6f, 0x9a, 0xba, + 0x47, 0xbf, 0x81, 0x9a, 0x88, 0x69, 0x4a, 0x1d, 0xb6, 0x88, 0x68, 0xdc, 0x52, 0x3a, 0x85, 0x6e, + 0xfd, 0x68, 0x37, 0x4d, 0xe4, 0x24, 0x81, 0x8f, 0x5d, 0x86, 0xab, 0x9c, 0x97, 0x8e, 0x63, 0xb4, + 0x0f, 0x65, 0xdf, 0xf9, 0x9e, 0xcc, 0x98, 0x37, 0x8e, 0x5b, 0xbb, 0x1d, 0xa9, 0x5b, 0xc3, 0x25, + 0xdf, 0xf9, 0xfe, 0x94, 0x8f, 0xdb, 0x1a, 0xec, 0x6d, 0x8e, 0x97, 0x0b, 0x98, 0x6f, 0x38, 0xd7, + 0xb4, 0x8c, 0xf9, 0x4f, 0xf4, 0x00, 0x8a, 0xef, 0x1d, 0x6f, 0x41, 0x85, 0xa8, 0xab, 0x38, 0x19, + 0xfc, 0x6e, 0xeb, 0x85, 0xa4, 0xbe, 0x80, 0xa6, 0x1d, 0x39, 0xe3, 0xeb, 0x5b, 0x7d, 0x71, 0x5b, + 0xd6, 0xd2, 0x1d, 0x59, 0xab, 0x2f, 0xa1, 0x21, 0x2a, 0x70, 0x42, 0xe9, 0xc7, 0xba, 0xe9, 0x21, + 0xf0, 0x5e, 0x11, 0xda, 0x4b, 0x3a, 0x6a, 0xdb, 0xf1, 0xb9, 0xec, 0xd4, 0x09, 0x28, 0xab, 0xf9, + 0xf1, 0x3c, 0x0c, 0x62, 0xca, 0x5b, 0x85, 0x17, 0x88, 0x6b, 0x8c, 0x4b, 0x52, 0x88, 0x51, 0x12, + 0xb3, 0xea, 0x29, 0x7e, 0x42, 0xa9, 0x90, 0xe3, 0xe3, 0xa4, 0x03, 0x88, 0x17, 0x8e, 0xaf, 0x79, + 0x4f, 0x39, 0x37, 0xa9, 0xfb, 0x1a, 0x87, 0x07, 0xe1, 0xf8, 0x5a, 0xe3, 0xa0, 0xfa, 0x2e, 0x69, + 0x7b, 0x3b, 0x14, 0x6b, 0xfd, 0xf8, 0xf4, 0x90, 0x0a, 0x45, 0xa1, 0x15, 0xe1, 0xb6, 0x72, 0x54, + 0xcd, 0x8b, 0x0e, 0x27, 0x26, 0xf5, 0x1d, 0x34, 0xd7, 0x9c, 0xa7, 0x59, 0xb4, 0xa1, 0x34, 0x8f, + 0xa8, 0xeb, 0x3b, 0x57, 0x34, 0xf5, 0xbc, 0x1c, 0xa3, 0x2e, 0xec, 0x4c, 0x1d, 0xd7, 0x5b, 0x44, + 0x99, 0xe3, 0x7a, 0x26, 0x82, 0x04, 0xc5, 0x99, 0x59, 0xfd, 0x0c, 0xda, 0x98, 0xc6, 0x94, 0x9d, + 0xbb, 0x71, 0xec, 0x86, 0x41, 0x3f, 0x0c, 0x58, 0x14, 0x7a, 0x69, 0x06, 0xea, 0x23, 0xd8, 0xdf, + 0x68, 0x4d, 0x42, 0xe0, 0x93, 0xbf, 0x5d, 0xd0, 0xe8, 0x66, 0xf3, 0xe4, 0x6f, 0x61, 0x7f, 0xa3, + 0x35, 0x8d, 0xff, 0x19, 0x14, 0xe7, 0x8e, 0x1b, 0xc5, 0xad, 0x2d, 0xd1, 0x34, 0x7b, 0xb9, 0xa6, + 0x19, 0x3a, 0x6e, 0x74, 0xea, 0xc6, 0x2c, 0x8c, 0x6e, 0x70, 0x42, 0x7a, 0x25, 0x97, 0x24, 0x65, + 0x4b, 0xfd, 0xbb, 0x04, 0x95, 0x9c, 0x91, 0x4b, 0x37, 0x08, 0x27, 0x94, 0x4c, 0xa3, 0xd0, 0xcf, + 0x36, 0x81, 0x03, 0x27, 0x51, 0xe8, 0x73, 0x4d, 0x08, 0x23, 0x0b, 0x53, 0x41, 0x6e, 0xf3, 0xa1, + 0x1d, 0xa2, 0x5f, 0xc2, 0xce, 0x2c, 0x71, 0x20, 0x0e, 0xaa, 0xca, 0x51, 0xf3, 0xd6, 0xda, 0x9a, + 0xc3, 0x1c, 0x9c, 0x71, 0x5e, 0xc9, 0xa5, 0x82, 0x22, 0xbf, 0x92, 0x4b, 0xb2, 0x52, 0x7c, 0x25, + 0x97, 0x8a, 0xca, 0xf6, 0x2b, 0xb9, 0xb4, 0xad, 0xec, 0xa8, 0xff, 0x91, 0xa0, 0x94, 0xb1, 0x79, + 0x24, 0x7c, 0x4b, 0x09, 0xd7, 0x45, 0x2a, 0xa6, 0x12, 0x07, 0x6c, 0xd7, 0xa7, 0xa8, 0x03, 0x55, + 0x61, 0x5c, 0x97, 0x28, 0x70, 0xac, 0x27, 0x64, 0x2a, 0x4e, 0xd0, 0x8c, 0x21, 0xf4, 0x28, 0xa7, + 0x27, 0x68, 0x42, 0xc9, 0x2e, 0x81, 0x78, 0x31, 0x1e, 0xd3, 0x38, 0x4e, 0x56, 0x29, 0x26, 0x94, + 0x14, 0x13, 0x0b, 0x3d, 0x86, 0x46, 0x46, 0xc9, 0xd6, 0xda, 0x4e, 0xf4, 0x9a, 0xc2, 0xe9, 0x72, + 0x5d, 0x50, 0xf2, 0x3c, 0x7f, 0x75, 0x66, 0xd7, 0x57, 0x44, 0xbe, 0x68, 0x92, 0xbc, 0xfa, 0x17, + 0x78, 0x28, 0x4a, 0x39, 0x8c, 0xc2, 0x4b, 0xe7, 0xd2, 0xf5, 0x5c, 0x76, 0x93, 0x89, 0x9c, 0x27, + 0x1e, 0x85, 0x3e, 0xe1, 0x7b, 0x9b, 0x95, 0x80, 0x03, 0x66, 0x38, 0xa1, 0xbc, 0x04, 0x2c, 0x4c, + 0x4c, 0x69, 0x09, 0x58, 0x28, 0x0c, 0xf9, 0xbb, 0xae, 0xb0, 0x76, 0xd7, 0xa9, 0xd7, 0xd0, 0xba, + 0xbb, 0x56, 0xaa, 0x99, 0x0e, 0x54, 0xe6, 0x2b, 0x58, 0x2c, 0x27, 0xe1, 0x3c, 0x94, 0xaf, 0xed, + 0xd6, 0x0f, 0xd7, 0x56, 0xfd, 0xa7, 0x04, 0xbb, 0xc7, 0x0b, 0xd7, 0x9b, 0xac, 0x35, 0x6e, 0x3e, + 0x3a, 0x69, 0xfd, 0x26, 0xde, 0x74, 0xcd, 0x6e, 0x6d, 0xbc, 0x66, 0x37, 0x5d, 0x65, 0x85, 0x7b, + 0xaf, 0xb2, 0x9f, 0x42, 0x65, 0x75, 0x8b, 0xc5, 0x2d, 0xb9, 0x53, 0xe8, 0x56, 0x31, 0xcc, 0xb2, + 0x2b, 0x2c, 0x56, 0x5f, 0x00, 0xca, 0x07, 0x9a, 0x6e, 0xc8, 0xf2, 0xfc, 0x90, 0xee, 0x3f, 0x3f, + 0x3e, 0x83, 0xf6, 0x68, 0x71, 0x19, 0x8f, 0x23, 0xf7, 0x92, 0xf2, 0x43, 0x5d, 0x7f, 0x4f, 0x03, + 0x16, 0x67, 0x5d, 0xfa, 0x3f, 0x19, 0xca, 0x4b, 0x14, 0x1d, 0x40, 0xd3, 0x0d, 0xc6, 0xa1, 0x9f, + 0x05, 0x1d, 0x50, 0x8f, 0xc7, 0x9d, 0x1c, 0xf2, 0xbb, 0x99, 0xa9, 0x9f, 0x58, 0x8c, 0x09, 0xe7, + 0xaf, 0x25, 0x99, 0xf2, 0xb7, 0x12, 0x7e, 0x3e, 0xc7, 0x84, 0xdf, 0x05, 0x65, 0xe9, 0x9f, 0x5f, + 0x38, 0xcb, 0x4d, 0xc1, 0xf5, 0x0c, 0xe7, 0xc1, 0x24, 0xcc, 0xa5, 0xe7, 0x8c, 0x29, 0x27, 0xcc, + 0x0c, 0x4f, 0x99, 0x5f, 0x40, 0x95, 0xf7, 0x43, 0xcc, 0x1c, 0x7f, 0x4e, 0x82, 0x58, 0xf4, 0x85, + 0x8c, 0x2b, 0x4b, 0xcc, 0x8c, 0xd1, 0xd7, 0x00, 0x94, 0xe7, 0x47, 0xd8, 0xcd, 0x9c, 0x8a, 0x96, + 0xa8, 0x1f, 0x7d, 0x9e, 0x13, 0xc6, 0x72, 0x03, 0x0e, 0xc4, 0xbf, 0xf6, 0xcd, 0x9c, 0xe2, 0x32, + 0xcd, 0x7e, 0xa2, 0x97, 0x50, 0x9b, 0x86, 0xd1, 0x07, 0x27, 0x9a, 0x10, 0x01, 0xa6, 0xc7, 0xc6, + 0xc3, 0x9c, 0x87, 0x93, 0xc4, 0x2e, 0xa6, 0x9f, 0x7e, 0x82, 0xab, 0xd3, 0xdc, 0x18, 0x9d, 0x01, + 0xca, 0xe6, 0x8b, 0x2e, 0x4f, 0x9c, 0x94, 0x84, 0x93, 0xfd, 0xbb, 0x4e, 0xf8, 0x21, 0x9d, 0x39, + 0x52, 0xa6, 0xb7, 0x30, 0xf4, 0x7b, 0xa8, 0xc6, 0x94, 0x31, 0x8f, 0xa6, 0x6e, 0xca, 0xc2, 0xcd, + 0xde, 0xda, 0x9b, 0x83, 0x9b, 0x33, 0x0f, 0x95, 0x78, 0x35, 0x44, 0xc7, 0xd0, 0xf0, 0xdc, 0xe0, + 0x3a, 0x1f, 0x06, 0x88, 0xf9, 0xad, 0xdc, 0xfc, 0x81, 0x1b, 0x5c, 0xe7, 0x63, 0xa8, 0x79, 0x79, + 0x40, 0xfd, 0x03, 0x94, 0x97, 0xbb, 0x84, 0x2a, 0xb0, 0x73, 0x61, 0x9e, 0x99, 0xd6, 0x1b, 0x53, + 0xf9, 0x04, 0x95, 0x40, 0x1e, 0xe9, 0xa6, 0xa6, 0x48, 0x1c, 0xc6, 0x7a, 0x5f, 0x37, 0x5e, 0xeb, + 0xca, 0x16, 0x1f, 0x9c, 0x58, 0xf8, 0x4d, 0x0f, 0x6b, 0x4a, 0xe1, 0x78, 0x07, 0x8a, 0x62, 0x5d, + 0xf5, 0x5f, 0x12, 0x94, 0x44, 0x05, 0x83, 0x69, 0x88, 0x7e, 0x01, 0x4b, 0x71, 0x89, 0xc3, 0x8d, + 0x5f, 0xb8, 0x42, 0x75, 0x35, 0xbc, 0x14, 0x8c, 0x9d, 0xe2, 0x9c, 0xbc, 0x94, 0xc6, 0x92, 0xbc, + 0x95, 0x90, 0x33, 0xc3, 0x92, 0xfc, 0x34, 0xe7, 0x79, 0xed, 0xc8, 0x91, 0x71, 0x23, 0x33, 0x64, + 0x27, 0xec, 0xd3, 0x9c, 0xe3, 0xb5, 0x93, 0x58, 0xc6, 0x8d, 0xcc, 0x90, 0x72, 0xd5, 0xdf, 0x42, + 0x35, 0x5f, 0x73, 0xf4, 0x04, 0x64, 0x37, 0x98, 0x86, 0x69, 0x23, 0x36, 0x6f, 0x89, 0x8b, 0x27, + 0x89, 0x05, 0x41, 0x45, 0xa0, 0xdc, 0xae, 0xb3, 0x5a, 0x83, 0x4a, 0xae, 0x68, 0xea, 0xbf, 0x25, + 0xa8, 0xad, 0x15, 0xe1, 0x47, 0x7b, 0x47, 0x5f, 0x43, 0xf5, 0x83, 0x1b, 0x51, 0x92, 0xbf, 0xfe, + 0xeb, 0x47, 0xed, 0xf5, 0xeb, 0x3f, 0xfb, 0xbf, 0x1f, 0x4e, 0x28, 0xae, 0x70, 0x7e, 0x0a, 0xa0, + 0x3f, 0x42, 0x3d, 0x9d, 0x49, 0x26, 0x94, 0x39, 0xae, 0x27, 0xb6, 0xaa, 0xbe, 0x26, 0x8f, 0x94, + 0xab, 0x09, 0x3b, 0xae, 0x4d, 0xf3, 0x43, 0xf4, 0xe5, 0xca, 0x41, 0xcc, 0x22, 0x37, 0xb8, 0x12, + 0xfb, 0x57, 0x5e, 0xd2, 0x46, 0x02, 0x7c, 0xfa, 0x37, 0x19, 0x6a, 0x6b, 0x7e, 0xd6, 0x85, 0x54, + 0x83, 0xb2, 0x69, 0x11, 0x4d, 0xb7, 0x7b, 0xc6, 0x40, 0x91, 0x90, 0x02, 0x55, 0xcb, 0x34, 0x2c, + 0x93, 0x68, 0x7a, 0xdf, 0xd2, 0xb8, 0xa4, 0x3e, 0x85, 0xdd, 0x81, 0x61, 0x9e, 0x11, 0xd3, 0xb2, + 0x89, 0x3e, 0x30, 0xbe, 0x31, 0x8e, 0x07, 0xba, 0x52, 0x40, 0x0f, 0x40, 0xb1, 0x4c, 0xd2, 0x3f, + 0xed, 0x19, 0x26, 0xb1, 0x8d, 0x73, 0xdd, 0xba, 0xb0, 0x15, 0x99, 0xa3, 0xa7, 0xf6, 0xa0, 0x4f, + 0xf4, 0xb7, 0x7d, 0x5d, 0xd7, 0x46, 0xe4, 0xbc, 0xf7, 0x56, 0x29, 0xa2, 0x16, 0x3c, 0x30, 0xcc, + 0xd1, 0xc5, 0xc9, 0x89, 0xd1, 0x37, 0x74, 0xd3, 0x26, 0xc7, 0xbd, 0x41, 0xcf, 0xec, 0xeb, 0xca, + 0x36, 0xda, 0x03, 0x64, 0x98, 0x7d, 0xeb, 0x7c, 0x38, 0xd0, 0x6d, 0x9d, 0x64, 0xd2, 0xdd, 0x41, + 0x4d, 0x68, 0x08, 0x3f, 0x3d, 0x4d, 0x23, 0x27, 0x3d, 0x63, 0xa0, 0x6b, 0x4a, 0x89, 0x47, 0x92, + 0x32, 0x46, 0x44, 0x33, 0x46, 0xbd, 0x63, 0x0e, 0x97, 0xf9, 0x9a, 0x86, 0xf9, 0xda, 0x32, 0xfa, + 0x3a, 0xe9, 0x73, 0xb7, 0x1c, 0x05, 0x4e, 0xce, 0xd0, 0x0b, 0x53, 0xd3, 0xf1, 0xb0, 0x67, 0x68, + 0x4a, 0x05, 0xed, 0xc3, 0xc3, 0x0c, 0xd6, 0xdf, 0x0e, 0x0d, 0xfc, 0x1d, 0xb1, 0x2d, 0x8b, 0x8c, + 0x2c, 0xcb, 0x54, 0xaa, 0x79, 0x4f, 0x3c, 0x5b, 0x6b, 0xa8, 0x9b, 0x4a, 0x0d, 0x3d, 0x84, 0xe6, + 0xf9, 0x70, 0x48, 0x32, 0x4b, 0x96, 0x6c, 0x9d, 0xd3, 0x7b, 0x9a, 0x86, 0xf5, 0xd1, 0x88, 0x9c, + 0x1b, 0xa3, 0xf3, 0x9e, 0xdd, 0x3f, 0x55, 0x1a, 0x3c, 0xa5, 0x91, 0x6e, 0x13, 0xdb, 0xb2, 0x7b, + 0x83, 0x15, 0xae, 0xf0, 0x80, 0x56, 0x38, 0x5f, 0x74, 0x60, 0xbd, 0x51, 0x76, 0xf9, 0x86, 0x73, + 0xd8, 0x7a, 0x9d, 0x86, 0x88, 0x78, 0xee, 0x69, 0x79, 0xb2, 0x35, 0x95, 0x26, 0x07, 0x0d, 0xf3, + 0x75, 0x6f, 0x60, 0x68, 0xe4, 0x4c, 0xff, 0x4e, 0xb4, 0xfe, 0x03, 0x0e, 0x26, 0x91, 0x91, 0x21, + 0xb6, 0xbe, 0xe1, 0x81, 0x28, 0x9f, 0x22, 0x04, 0xf5, 0xbe, 0x81, 0xfb, 0x17, 0x83, 0x1e, 0x26, + 0xd8, 0xba, 0xb0, 0x75, 0x65, 0xef, 0xe8, 0xbf, 0x45, 0xd8, 0x16, 0x17, 0x55, 0x84, 0x5e, 0x72, + 0xfd, 0x2f, 0x3f, 0x94, 0xd0, 0xa3, 0x8f, 0x7e, 0x40, 0xb5, 0xb3, 0xc7, 0x6c, 0x0a, 0x3f, 0x97, + 0xd0, 0x9f, 0xa0, 0x9a, 0xff, 0xbe, 0x40, 0xf9, 0xb3, 0x7d, 0xc3, 0x87, 0xc7, 0x06, 0x0f, 0x67, + 0xa0, 0xe8, 0x31, 0x73, 0x7d, 0x87, 0xd1, 0xec, 0x7b, 0x01, 0xb5, 0x73, 0x5e, 0x6e, 0x7d, 0x84, + 0xb4, 0xf7, 0x37, 0xda, 0xd2, 0x5b, 0x79, 0x90, 0xa4, 0x93, 0xbe, 0xd8, 0xef, 0xa4, 0xb3, 0xfe, + 0x99, 0xd0, 0xfe, 0xfc, 0x3e, 0x73, 0xea, 0x6d, 0x02, 0xcd, 0x0d, 0x8f, 0x70, 0xf4, 0x65, 0x3e, + 0x82, 0x7b, 0x9f, 0xf0, 0xed, 0xc7, 0x3f, 0x44, 0x5b, 0xad, 0xb2, 0xe1, 0xb5, 0xbe, 0xb6, 0xca, + 0xfd, 0x6f, 0xfd, 0xb5, 0x55, 0x3e, 0xf6, 0xe8, 0x7f, 0x07, 0xca, 0xed, 0xc7, 0x1d, 0x52, 0x6f, + 0xcf, 0xbd, 0xfb, 0xca, 0x6c, 0xff, 0xec, 0xa3, 0x9c, 0xd4, 0xb9, 0x01, 0xb0, 0x7a, 0x22, 0xa1, + 0xcf, 0x72, 0x53, 0xee, 0x3c, 0xf1, 0xda, 0x8f, 0xee, 0xb1, 0xa6, 0xae, 0x6c, 0x68, 0x6e, 0x78, + 0x33, 0xad, 0xed, 0xc6, 0xfd, 0x6f, 0xaa, 0xf6, 0x83, 0x4d, 0x4f, 0x8b, 0xe7, 0xd2, 0xf1, 0x57, + 0x7f, 0x3e, 0xbc, 0x72, 0xd9, 0x6c, 0x71, 0x79, 0x30, 0x0e, 0xfd, 0x43, 0xcf, 0xbd, 0x9a, 0xb1, + 0xc0, 0x0d, 0xae, 0x02, 0xca, 0x3e, 0x84, 0xd1, 0xf5, 0xa1, 0x17, 0x4c, 0x0e, 0x85, 0x2e, 0x0f, + 0x97, 0xd3, 0x2f, 0xb7, 0xc5, 0x1f, 0x96, 0x7e, 0xf5, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5f, + 0x5a, 0x7c, 0x81, 0x88, 0x12, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 43cffc583f..25e47d999e 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -114,6 +114,12 @@ message SendPaymentRequest { fallback. */ repeated lnrpc.FeatureBit dest_features = 16; + + /** + The maximum number of partial payments that may be use to complete the full + amount. + */ + uint32 max_htlcs = 17; } message TrackPaymentRequest { diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 0a64161bb1..d4d75edd39 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -547,6 +547,14 @@ func (r *RouterBackend) extractIntentFromSendRequest( } payIntent.CltvLimit = cltvLimit + // Take max htlcs from the request. Map zero to one for backwards + // compatibility. + maxHtlcs := rpcPayReq.MaxHtlcs + if maxHtlcs == 0 { + maxHtlcs = 1 + } + payIntent.MaxHtlcs = maxHtlcs + // Take fee limit from request. payIntent.FeeLimit, err = lnrpc.UnmarshallAmt( rpcPayReq.FeeLimitSat, rpcPayReq.FeeLimitMsat, diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index 418b380caf..4ab395e716 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -1,7 +1,9 @@ package routing import ( + "fmt" "io/ioutil" + "math" "os" "testing" "time" @@ -64,6 +66,7 @@ func newIntegratedRoutingContext(t *testing.T) *integratedRoutingContext { pathFindingCfg: PathFindingConfig{ PaymentAttemptPenalty: 1000, + MinProbability: 0.01, }, source: source, @@ -79,9 +82,15 @@ type htlcAttempt struct { success bool } +func (h htlcAttempt) String() string { + return fmt.Sprintf("success=%v, route=%v", h.success, h.route) +} + // testPayment launches a test payment and asserts that it is completed after // the expected number of attempts. -func (c *integratedRoutingContext) testPayment() ([]htlcAttempt, error) { +func (c *integratedRoutingContext) testPayment(maxHtlcs uint32) ([]htlcAttempt, + error) { + var ( nextPid uint64 attempts []htlcAttempt @@ -119,10 +128,16 @@ func (c *integratedRoutingContext) testPayment() ([]htlcAttempt, error) { return bandwidthHints, nil } + var paymentAddr [32]byte payment := LightningPayment{ FinalCLTVDelta: uint16(c.finalExpiry), FeeLimit: lnwire.MaxMilliSatoshi, Target: c.target.pubkey, + PaymentAddr: &paymentAddr, + DestFeatures: lnwire.NewFeatureVector(mppFeatures, nil), + Amount: c.amt, + CltvLimit: math.MaxUint32, + MaxHtlcs: maxHtlcs, } session := &paymentSession{ @@ -134,10 +149,15 @@ func (c *integratedRoutingContext) testPayment() ([]htlcAttempt, error) { }, pathFindingConfig: c.pathFindingCfg, missionControl: mc, + minShardAmt: lnwire.NewMSatFromSatoshis(5000), } // Now the payment control loop starts. It will keep trying routes until // the payment succeeds. + var ( + amtRemaining = payment.Amount + inFlightHtlcs uint32 + ) for { // Create bandwidth hints based on local channel balances. bandwidthHints := map[uint64]lnwire.MilliSatoshi{} @@ -147,10 +167,10 @@ func (c *integratedRoutingContext) testPayment() ([]htlcAttempt, error) { // Find a route. route, err := session.RequestRoute( - c.amt, lnwire.MaxMilliSatoshi, 0, 0, + amtRemaining, lnwire.MaxMilliSatoshi, inFlightHtlcs, 0, ) if err != nil { - return nil, err + return attempts, err } // Send out the htlc on the mock graph. @@ -167,21 +187,33 @@ func (c *integratedRoutingContext) testPayment() ([]htlcAttempt, error) { success: success, }) - // Process the result. + // Process the result. In normal Lightning operations, the + // sender doesn't get an acknowledgement from the recipient that + // the htlc arrived. In integrated routing tests, this + // acknowledgement is available. It is a simplification of + // reality that still allows certain classes of tests to be + // performed. if success { + inFlightHtlcs++ + err := mc.ReportPaymentSuccess(pid, route) if err != nil { c.t.Fatal(err) } - // If the payment is successful, the control loop can be - // broken out of. - break + amtRemaining -= route.ReceiverAmt() + + // If the full amount has been paid, the payment is + // successful and the control loop can be terminated. + if amtRemaining == 0 { + break + } + + // Otherwise try to send the remaining amount. + continue } // Failure, update mission control and retry. - c.t.Logf("fail: %v @ %v\n", htlcResult.failure, htlcResult.failureSource) - finalResult, err := mc.ReportPaymentFail( pid, route, getNodeIndex(route, htlcResult.failureSource), @@ -192,13 +224,10 @@ func (c *integratedRoutingContext) testPayment() ([]htlcAttempt, error) { } if finalResult != nil { - c.t.Logf("final result: %v\n", finalResult) break } } - c.t.Logf("Payment attempts: %v\n", len(attempts)) - return attempts, nil } diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go index 1e77ce8102..fb5d225471 100644 --- a/routing/integrated_routing_test.go +++ b/routing/integrated_routing_test.go @@ -2,6 +2,9 @@ package routing import ( "testing" + + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/lnwire" ) // TestProbabilityExtrapolation tests that probabilities for tried channels are @@ -50,7 +53,7 @@ func TestProbabilityExtrapolation(t *testing.T) { // a specific number of attempts to safe-guard against accidental // modifications anywhere in the chain of components that is involved in // this test. - attempts, err := ctx.testPayment() + attempts, err := ctx.testPayment(1) if err != nil { t.Fatalf("payment failed: %v", err) } @@ -62,7 +65,7 @@ func TestProbabilityExtrapolation(t *testing.T) { // of data from other channels), all ten bad channels will be tried // first before switching to the paid channel. ctx.mcCfg.AprioriWeight = 1 - attempts, err = ctx.testPayment() + attempts, err = ctx.testPayment(1) if err != nil { t.Fatalf("payment failed: %v", err) } @@ -70,3 +73,211 @@ func TestProbabilityExtrapolation(t *testing.T) { t.Fatalf("expected 11 attempts, but needed %v", len(attempts)) } } + +type mppSendTestCase struct { + name string + amt btcutil.Amount + expectedAttempts int + + // expectedSuccesses is a list of htlcs that made it to the receiver, + // regardless of whether the final set became complete or not. + expectedSuccesses []expectedHtlcSuccess + + graph func(g *mockGraph) + expectedFailure bool + maxHtlcs uint32 +} + +const ( + chanSourceIm1 = 13 + chanIm1Target = 32 + chanSourceIm2 = 14 + chanIm2Target = 42 +) + +func onePathGraph(g *mockGraph) { + // Create the following network of nodes: + // source -> intermediate1 -> target + + const im1NodeID = 3 + intermediate1 := newMockNode(im1NodeID) + g.addNode(intermediate1) + + g.addChannel(chanSourceIm1, sourceNodeID, im1NodeID, 200000) + g.addChannel(chanIm1Target, targetNodeID, im1NodeID, 100000) +} + +func twoPathGraph(g *mockGraph) { + // Create the following network of nodes: + // source -> intermediate1 -> target + // source -> intermediate2 -> target + + const im1NodeID = 3 + intermediate1 := newMockNode(im1NodeID) + g.addNode(intermediate1) + + const im2NodeID = 4 + intermediate2 := newMockNode(im2NodeID) + g.addNode(intermediate2) + + g.addChannel(chanSourceIm1, sourceNodeID, im1NodeID, 200000) + g.addChannel(chanSourceIm2, sourceNodeID, im2NodeID, 200000) + g.addChannel(chanIm1Target, targetNodeID, im1NodeID, 100000) + g.addChannel(chanIm2Target, targetNodeID, im2NodeID, 100000) +} + +var mppTestCases = []mppSendTestCase{ + // Test a two-path graph with sufficient liquidity. It is expected that + // pathfinding will try first try to send the full amount via the two + // available routes. When that fails, it will half the amount to 35k sat + // and retry. That attempt reaches the target successfully. Then the + // same route is tried again. Because the channel only had 50k sat, it + // will fail. Finally the second route is tried for 35k and it succeeds + // too. Mpp payment complete. + { + + name: "sufficient inbound", + graph: twoPathGraph, + amt: 70000, + expectedAttempts: 5, + expectedSuccesses: []expectedHtlcSuccess{ + { + amt: 35000, + chans: []uint64{chanSourceIm1, chanIm1Target}, + }, + { + amt: 35000, + chans: []uint64{chanSourceIm2, chanIm2Target}, + }, + }, + maxHtlcs: 1000, + }, + + // Test that a cap on the max htlcs makes it impossible to pay. + { + name: "no splitting", + graph: twoPathGraph, + amt: 70000, + expectedAttempts: 2, + expectedSuccesses: []expectedHtlcSuccess{}, + expectedFailure: true, + maxHtlcs: 1, + }, + + // Test that an attempt is made to split the payment in multiple parts + // that all use the same route if the full amount cannot be sent in a + // single htlc. The sender is effectively probing the receiver's + // incoming channel to see if it has sufficient balance. In this test + // case, the endeavour fails. + { + + name: "one path split", + graph: onePathGraph, + amt: 70000, + expectedAttempts: 7, + expectedSuccesses: []expectedHtlcSuccess{ + { + amt: 35000, + chans: []uint64{chanSourceIm1, chanIm1Target}, + }, + { + amt: 8750, + chans: []uint64{chanSourceIm1, chanIm1Target}, + }, + }, + expectedFailure: true, + maxHtlcs: 1000, + }, +} + +// TestMppSend tests that a payment can be completed using multiple shards. +func TestMppSend(t *testing.T) { + for _, testCase := range mppTestCases { + testCase := testCase + + t.Run(testCase.name, func(t *testing.T) { + testMppSend(t, &testCase) + }) + } +} + +func testMppSend(t *testing.T, testCase *mppSendTestCase) { + ctx := newIntegratedRoutingContext(t) + + g := ctx.graph + testCase.graph(g) + + ctx.amt = lnwire.NewMSatFromSatoshis(testCase.amt) + + attempts, err := ctx.testPayment(testCase.maxHtlcs) + switch { + case err == nil && testCase.expectedFailure: + t.Fatal("expected payment to fail") + case err != nil && !testCase.expectedFailure: + t.Fatal("expected payment to succeed") + } + + if len(attempts) != testCase.expectedAttempts { + t.Fatalf("expected %v attempts, but needed %v", + testCase.expectedAttempts, len(attempts), + ) + } + + assertSuccessAttempts(t, attempts, testCase.expectedSuccesses) +} + +// expectedHtlcSuccess describes an expected successful htlc attempt. +type expectedHtlcSuccess struct { + amt btcutil.Amount + chans []uint64 +} + +// equals matches the expectation with an actual attempt. +func (e *expectedHtlcSuccess) equals(a htlcAttempt) bool { + if a.route.TotalAmount != + lnwire.NewMSatFromSatoshis(e.amt) { + + return false + } + + if len(a.route.Hops) != len(e.chans) { + return false + } + + for i, h := range a.route.Hops { + if h.ChannelID != e.chans[i] { + return false + } + } + + return true +} + +// assertSuccessAttempts asserts that the set of successful htlc attempts +// matches the given expectation. +func assertSuccessAttempts(t *testing.T, attempts []htlcAttempt, + expected []expectedHtlcSuccess) { + + successCount := 0 +loop: + for _, a := range attempts { + if !a.success { + continue + } + + successCount++ + + for _, exp := range expected { + if exp.equals(a) { + continue loop + } + } + + t.Fatalf("htlc success %v not found", a) + } + + if successCount != len(expected) { + t.Fatalf("expected %v successful htlcs, but got %v", + expected, successCount) + } +} diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index ab54534bda..0683f36ee4 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -81,6 +81,12 @@ var ( ), lnwire.Features, ) + mppFeatures = lnwire.NewRawFeatureVector( + lnwire.TLVOnionPayloadOptional, + lnwire.PaymentAddrOptional, + lnwire.MPPOptional, + ) + unknownRequiredFeatures = lnwire.NewFeatureVector( lnwire.NewRawFeatureVector(100), lnwire.Features, ) diff --git a/routing/payment_session.go b/routing/payment_session.go index 9f9c347c98..d06356e7ef 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -31,6 +31,13 @@ const ( errEmptyPaySession ) +var ( + // DefaultShardMinAmt is the default amount beyond which we won't try to + // further split the payment if no route is found. It is the minimum + // amount that we use as the shard size when splitting. + DefaultShardMinAmt = lnwire.NewMSatFromSatoshis(10000) +) + // Error returns the string representation of the noRouteError func (e noRouteError) Error() string { switch e { @@ -111,6 +118,12 @@ type paymentSession struct { pathFindingConfig PathFindingConfig missionControl MissionController + + // minShardAmt is the amount beyond which we won't try to further split + // the payment if no route is found. If the maximum number of htlcs + // specified in the payment is one, under no circumstances splitting + // will happen and this value remains unused. + minShardAmt lnwire.MilliSatoshi } // RequestRoute returns a route which is likely to be capable for successfully @@ -155,58 +168,87 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, PaymentAddr: p.payment.PaymentAddr, } - // We'll also obtain a set of bandwidthHints from the lower layer for - // each of our outbound channels. This will allow the path finding to - // skip any links that aren't active or just don't have enough bandwidth - // to carry the payment. New bandwidth hints are queried for every new - // path finding attempt, because concurrent payments may change - // balances. - bandwidthHints, err := p.getBandwidthHints() - if err != nil { - return nil, err - } - finalHtlcExpiry := int32(height) + int32(finalCltvDelta) - routingGraph, cleanup, err := p.getRoutingGraph() - if err != nil { - return nil, err + for { + // We'll also obtain a set of bandwidthHints from the lower + // layer for each of our outbound channels. This will allow the + // path finding to skip any links that aren't active or just + // don't have enough bandwidth to carry the payment. New + // bandwidth hints are queried for every new path finding + // attempt, because concurrent payments may change balances. + bandwidthHints, err := p.getBandwidthHints() + if err != nil { + return nil, err + } + + log.Debugf("PaymentSession for %x: trying pathfinding with %v", + p.payment.PaymentHash, maxAmt) + + // Get a routing graph. + routingGraph, cleanup, err := p.getRoutingGraph() + if err != nil { + return nil, err + } + + sourceVertex := routingGraph.sourceNode() + + // Find a route for the current amount. + path, err := p.pathFinder( + &graphParams{ + additionalEdges: p.additionalEdges, + bandwidthHints: bandwidthHints, + graph: routingGraph, + }, + restrictions, &p.pathFindingConfig, + sourceVertex, p.payment.Target, + maxAmt, finalHtlcExpiry, + ) + + // Close routing graph. + cleanup() + + switch { + case err == errNoPathFound: + // No splitting if this is the last shard. + isLastShard := activeShards+1 >= p.payment.MaxHtlcs + if isLastShard { + return nil, errNoPathFound + } + + // This is where the magic happens. If we can't find a + // route, try it for half the amount. + maxAmt /= 2 + + // Put a lower bound on the minimum shard size. + if maxAmt < p.minShardAmt { + return nil, errNoPathFound + } + + // Go pathfinding. + continue + + case err != nil: + return nil, err + } + + // With the next candidate path found, we'll attempt to turn + // this into a route by applying the time-lock and fee + // requirements. + route, err := newRoute( + sourceVertex, path, height, + finalHopParams{ + amt: maxAmt, + totalAmt: p.payment.Amount, + cltvDelta: finalCltvDelta, + records: p.payment.DestCustomRecords, + paymentAddr: p.payment.PaymentAddr, + }, + ) + if err != nil { + return nil, err + } + + return route, err } - defer cleanup() - - sourceVertex := routingGraph.sourceNode() - - path, err := p.pathFinder( - &graphParams{ - additionalEdges: p.additionalEdges, - bandwidthHints: bandwidthHints, - graph: routingGraph, - }, - restrictions, &p.pathFindingConfig, - sourceVertex, p.payment.Target, - maxAmt, finalHtlcExpiry, - ) - if err != nil { - return nil, err - } - - // With the next candidate path found, we'll attempt to turn this into - // a route by applying the time-lock and fee requirements. - route, err := newRoute( - sourceVertex, path, height, - finalHopParams{ - amt: maxAmt, - totalAmt: maxAmt, - cltvDelta: finalCltvDelta, - records: p.payment.DestCustomRecords, - paymentAddr: p.payment.PaymentAddr, - }, - ) - if err != nil { - // TODO(roasbeef): return which edge/vertex didn't work - // out - return nil, err - } - - return route, err } diff --git a/routing/payment_session_source.go b/routing/payment_session_source.go index f3b6607e11..a6016ab85e 100644 --- a/routing/payment_session_source.go +++ b/routing/payment_session_source.go @@ -86,6 +86,7 @@ func (m *SessionSource) NewPaymentSession(p *LightningPayment) ( getRoutingGraph: m.getRoutingGraph, pathFindingConfig: m.PathFindingConfig, missionControl: m.MissionControl, + minShardAmt: DefaultShardMinAmt, }, nil } diff --git a/routing/router.go b/routing/router.go index 7d80305b98..d93c38302c 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1624,6 +1624,10 @@ type LightningPayment struct { // understand this new onion payload format, then the payment will // fail. DestCustomRecords record.CustomSet + + // MaxHtlcs is the maximum number of partial payments that may be use to + // complete the full amount. + MaxHtlcs uint32 } // SendPayment attempts to send a payment as described within the passed diff --git a/rpcserver.go b/rpcserver.go index 4d7cc1d22f..3928eeb117 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3962,6 +3962,10 @@ func (r *rpcServer) dispatchPaymentIntent( DestCustomRecords: payIntent.destCustomRecords, DestFeatures: payIntent.destFeatures, PaymentAddr: payIntent.paymentAddr, + + // Don't enable multi-part payments on the main rpc. + // Users need to use routerrpc for that. + MaxHtlcs: 1, } preImage, route, routerErr = r.server.chanRouter.SendPayment( From f5c3f930c40f2bac2c7b635c8cc93287377f75c1 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 27 Mar 2020 14:44:44 +0100 Subject: [PATCH 444/562] lncli: expose max payment htlcs --- cmd/lncli/cmd_pay.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 34fb88e9cb..426c751666 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -52,6 +52,13 @@ var ( Usage: "if set, intermediate payment state updates will be " + "displayed", } + + maxHtlcsFlag = cli.UintFlag{ + Name: "max_htlcs", + Usage: "the maximum number of partial payments that may be " + + "used", + Value: 1, + } ) // paymentFlags returns common flags for sendpayment and payinvoice. @@ -88,7 +95,7 @@ func paymentFlags() []cli.Flag { Name: "allow_self_payment", Usage: "allow sending a circular payment to self", }, - dataFlag, showInflightFlag, + dataFlag, showInflightFlag, maxHtlcsFlag, } } @@ -318,6 +325,8 @@ func sendPaymentRequest(ctx *cli.Context, req.AllowSelfPayment = ctx.Bool("allow_self_payment") + req.MaxHtlcs = uint32(ctx.Uint(maxHtlcsFlag.Name)) + // Parse custom data records. data := ctx.String(dataFlag.Name) if data != "" { From 110c99f67699f433d3ad885fd3ffe04c3dc5492b Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 25 Mar 2020 16:21:58 +0100 Subject: [PATCH 445/562] routing: continue trying after mpp timeout It can happen that the receiver times out some htlcs of the set if it took to long to complete. But because the sender's mission control is now updated, it is worth to keep trying to send those shards again. --- routing/result_interpretation.go | 17 +++-------------- routing/result_interpretation_test.go | 10 ++++++---- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/routing/result_interpretation.go b/routing/result_interpretation.go index 660ce69cc8..70cc08f6a0 100644 --- a/routing/result_interpretation.go +++ b/routing/result_interpretation.go @@ -215,20 +215,9 @@ func (i *interpretedResult) processPaymentOutcomeFinal( i.finalFailureReason = &reasonIncorrectDetails case *lnwire.FailMPPTimeout: - // TODO(carla): decide how to penalize mpp timeout. In the - // meantime, attribute success to the hops along the route and - // do not penalize the final node. - - i.finalFailureReason = &reasonError - - // If this is a direct payment, take no action. - if n == 1 { - return - } - - // Assign all pairs a success result except the final hop, as - // the payment reached the destination correctly. - i.successPairRange(route, 0, n-2) + // Assign all pairs a success result, as the payment reached the + // destination correctly. Continue the payment process. + i.successPairRange(route, 0, n-1) default: // All other errors are considered terminal if coming from the diff --git a/routing/result_interpretation_test.go b/routing/result_interpretation_test.go index 537869f0b6..2fc0a7d90a 100644 --- a/routing/result_interpretation_test.go +++ b/routing/result_interpretation_test.go @@ -325,8 +325,10 @@ var resultTestCases = []resultTestCase{ failure: &lnwire.FailMPPTimeout{}, expectedResult: &interpretedResult{ - finalFailureReason: &reasonError, - nodeFailure: nil, + pairResults: map[DirectedNodePair]pairResult{ + getTestPair(0, 1): successPairResult(100), + }, + nodeFailure: nil, }, }, @@ -342,9 +344,9 @@ var resultTestCases = []resultTestCase{ expectedResult: &interpretedResult{ pairResults: map[DirectedNodePair]pairResult{ getTestPair(0, 1): successPairResult(100), + getTestPair(1, 2): successPairResult(99), }, - finalFailureReason: &reasonError, - nodeFailure: nil, + nodeFailure: nil, }, }, } From 35ebfcda9e9e31348c40bc41eae6575ea1da559d Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Apr 2020 17:45:31 +0200 Subject: [PATCH 446/562] itest: create mpp test context --- lntest/itest/lnd_mpp_test.go | 245 ++++++++++++++++++++--------------- 1 file changed, 143 insertions(+), 102 deletions(-) diff --git a/lntest/itest/lnd_mpp_test.go b/lntest/itest/lnd_mpp_test.go index 9b338baf05..0b015b5919 100644 --- a/lntest/itest/lnd_mpp_test.go +++ b/lntest/itest/lnd_mpp_test.go @@ -22,6 +22,9 @@ import ( func testSendToRouteMultiPath(net *lntest.NetworkHarness, t *harnessTest) { ctxb := context.Background() + ctx := newMppTestContext(t, net) + defer ctx.shutdownNodes() + // To ensure the payment goes through seperate paths, we'll set a // channel size that can only carry one shard at a time. We'll divide // the payment into 3 shards. @@ -38,113 +41,19 @@ func testSendToRouteMultiPath(net *lntest.NetworkHarness, t *harnessTest) { // \ / // \__ Dave ____/ // - // - // Create the three nodes in addition to Alice and Bob. - alice := net.Alice - bob := net.Bob - carol, err := net.NewNode("carol", nil) - if err != nil { - t.Fatalf("unable to create carol: %v", err) - } - defer shutdownAndAssert(net, t, carol) - - dave, err := net.NewNode("dave", nil) - if err != nil { - t.Fatalf("unable to create dave: %v", err) - } - defer shutdownAndAssert(net, t, dave) - - eve, err := net.NewNode("eve", nil) - if err != nil { - t.Fatalf("unable to create eve: %v", err) - } - defer shutdownAndAssert(net, t, eve) - - nodes := []*lntest.HarnessNode{alice, bob, carol, dave, eve} - - // Connect nodes to ensure propagation of channels. - for i := 0; i < len(nodes); i++ { - for j := i + 1; j < len(nodes); j++ { - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - if err := net.EnsureConnected(ctxt, nodes[i], nodes[j]); err != nil { - t.Fatalf("unable to connect nodes: %v", err) - } - } - } - - // We'll send shards along three routes from Alice. - sendRoutes := [][]*lntest.HarnessNode{ - {carol, bob}, - {dave, bob}, - {carol, eve, bob}, - } - - // Keep a list of all our active channels. - var networkChans []*lnrpc.ChannelPoint - var closeChannelFuncs []func() - - // openChannel is a helper to open a channel from->to. - openChannel := func(from, to *lntest.HarnessNode, chanSize btcutil.Amount) { - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - err := net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, from) - if err != nil { - t.Fatalf("unable to send coins : %v", err) - } - - ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - chanPoint := openChannelAndAssert( - ctxt, t, net, from, to, - lntest.OpenChannelParams{ - Amt: chanSize, - }, - ) - - closeChannelFuncs = append(closeChannelFuncs, func() { - ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert( - ctxt, t, net, from, chanPoint, false, - ) - }) - - networkChans = append(networkChans, chanPoint) - } - - // Open channels between the nodes. - openChannel(carol, bob, chanAmt) - openChannel(dave, bob, chanAmt) - openChannel(alice, dave, chanAmt) - openChannel(eve, bob, chanAmt) - openChannel(carol, eve, chanAmt) + 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. - openChannel(alice, carol, chanAmt+shardAmt) + ctx.openChannel(ctx.alice, ctx.carol, chanAmt+shardAmt) - for _, f := range closeChannelFuncs { - defer f() - } + defer ctx.closeChannels() - // Wait for all nodes to have seen all channels. - for _, chanPoint := range networkChans { - for _, node := range nodes { - txid, err := lnd.GetChanPointFundingTxid(chanPoint) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - point := wire.OutPoint{ - Hash: *txid, - Index: chanPoint.OutputIndex, - } - - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - err = node.WaitForNetworkChannelOpen(ctxt, chanPoint) - if err != nil { - t.Fatalf("(%d): timeout waiting for "+ - "channel(%s) open: %v", - node.NodeID, point, err) - } - } - } + ctx.waitForChannels() // Make Bob create an invoice for Alice to pay. payReqs, rHashes, invoices, err := createPayReqs( @@ -197,6 +106,13 @@ func testSendToRouteMultiPath(net *lntest.NetworkHarness, t *harnessTest) { return routeResp.Route, nil } + // We'll send shards along three routes from Alice. + sendRoutes := [][]*lntest.HarnessNode{ + {ctx.carol, ctx.bob}, + {ctx.dave, ctx.bob}, + {ctx.carol, ctx.eve, ctx.bob}, + } + responses := make(chan *routerrpc.SendToRouteResponse, len(sendRoutes)) for _, hops := range sendRoutes { // Build a route for the specified hops. @@ -355,3 +271,128 @@ func testSendToRouteMultiPath(net *lntest.NetworkHarness, t *harnessTest) { // ...and in Bob's list of paid invoices. assertSettledInvoice(net.Bob, rHash, 3) } + +type mppTestContext struct { + t *harnessTest + net *lntest.NetworkHarness + + // Keep a list of all our active channels. + networkChans []*lnrpc.ChannelPoint + closeChannelFuncs []func() + + alice, bob, carol, dave, eve *lntest.HarnessNode + nodes []*lntest.HarnessNode +} + +func newMppTestContext(t *harnessTest, + net *lntest.NetworkHarness) *mppTestContext { + + ctxb := context.Background() + + // Create a five-node context consisting of Alice, Bob and three new + // nodes. + carol, err := net.NewNode("carol", nil) + if err != nil { + t.Fatalf("unable to create carol: %v", err) + } + + dave, err := net.NewNode("dave", nil) + if err != nil { + t.Fatalf("unable to create dave: %v", err) + } + + eve, err := net.NewNode("eve", nil) + if err != nil { + t.Fatalf("unable to create eve: %v", err) + } + + // Connect nodes to ensure propagation of channels. + nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol, dave, eve} + for i := 0; i < len(nodes); i++ { + for j := i + 1; j < len(nodes); j++ { + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + if err := net.EnsureConnected(ctxt, nodes[i], nodes[j]); err != nil { + t.Fatalf("unable to connect nodes: %v", err) + } + } + } + + ctx := mppTestContext{ + t: t, + net: net, + alice: net.Alice, + bob: net.Bob, + carol: carol, + dave: dave, + eve: eve, + nodes: nodes, + } + + return &ctx +} + +// openChannel is a helper to open a channel from->to. +func (c *mppTestContext) openChannel(from, to *lntest.HarnessNode, chanSize btcutil.Amount) { + ctxb := context.Background() + + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + err := c.net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, from) + if err != nil { + c.t.Fatalf("unable to send coins : %v", err) + } + + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) + chanPoint := openChannelAndAssert( + ctxt, c.t, c.net, from, to, + lntest.OpenChannelParams{ + Amt: chanSize, + }, + ) + + c.closeChannelFuncs = append(c.closeChannelFuncs, func() { + ctxt, _ := context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert( + ctxt, c.t, c.net, from, chanPoint, false, + ) + }) + + c.networkChans = append(c.networkChans, chanPoint) +} + +func (c *mppTestContext) closeChannels() { + for _, f := range c.closeChannelFuncs { + f() + } +} + +func (c *mppTestContext) shutdownNodes() { + shutdownAndAssert(c.net, c.t, c.carol) + shutdownAndAssert(c.net, c.t, c.dave) + shutdownAndAssert(c.net, c.t, c.eve) +} + +func (c *mppTestContext) waitForChannels() { + ctxb := context.Background() + + // Wait for all nodes to have seen all channels. + for _, chanPoint := range c.networkChans { + for _, node := range c.nodes { + txid, err := lnd.GetChanPointFundingTxid(chanPoint) + if err != nil { + c.t.Fatalf("unable to get txid: %v", err) + } + point := wire.OutPoint{ + Hash: *txid, + Index: chanPoint.OutputIndex, + } + + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + err = node.WaitForNetworkChannelOpen(ctxt, chanPoint) + if err != nil { + c.t.Fatalf("(%d): timeout waiting for "+ + "channel(%s) open: %v", + node.NodeID, point, err) + } + } + } +} From af14f2e425c4a6f8820d98bb5c41637cb1ebaf22 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 26 Mar 2020 15:05:11 +0100 Subject: [PATCH 447/562] itest: add multi-part payment test Co-authored-by: Johan T. Halseth --- lntest/itest/lnd_send_multi_path_payment.go | 141 ++++++++++++++++++++ lntest/itest/lnd_test.go | 46 +++++++ 2 files changed, 187 insertions(+) create mode 100644 lntest/itest/lnd_send_multi_path_payment.go diff --git a/lntest/itest/lnd_send_multi_path_payment.go b/lntest/itest/lnd_send_multi_path_payment.go new file mode 100644 index 0000000000..b70564f070 --- /dev/null +++ b/lntest/itest/lnd_send_multi_path_payment.go @@ -0,0 +1,141 @@ +// +build rpctest + +package itest + +import ( + "context" + "encoding/hex" + + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/lntest" +) + +// testSendMultiPathPayment tests that we are able to successfully route a +// payment using multiple shards across different paths. +func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() + + ctx := newMppTestContext(t, net) + defer ctx.shutdownNodes() + + const paymentAmt = btcutil.Amount(300000) + + // Set up a network with three different paths Alice <-> Bob. Channel + // capacities are set such that the payment can only succeed if (at + // least) three paths are used. + // + // _ Eve _ + // / \ + // Alice -- Carol ---- Bob + // \ / + // \__ Dave ____/ + // + ctx.openChannel(ctx.carol, ctx.bob, 135000) + ctx.openChannel(ctx.alice, ctx.carol, 235000) + ctx.openChannel(ctx.dave, ctx.bob, 135000) + ctx.openChannel(ctx.alice, ctx.dave, 135000) + ctx.openChannel(ctx.eve, ctx.bob, 135000) + ctx.openChannel(ctx.carol, ctx.eve, 135000) + + defer ctx.closeChannels() + + ctx.waitForChannels() + + // Increase Dave's fee to make the test deterministic. Otherwise it + // would be unpredictable whether pathfinding would go through Charlie + // or Dave for the first shard. + _, err := ctx.dave.UpdateChannelPolicy( + context.Background(), + &lnrpc.PolicyUpdateRequest{ + Scope: &lnrpc.PolicyUpdateRequest_Global{Global: true}, + BaseFeeMsat: 500000, + FeeRate: 0.001, + TimeLockDelta: 40, + }, + ) + if err != nil { + t.Fatalf("dave policy update: %v", err) + } + // Our first test will be Alice paying Bob using a SendPayment call. + // Let Bob create an invoice for Alice to pay. + payReqs, rHashes, invoices, err := createPayReqs( + net.Bob, paymentAmt, 1, + ) + if err != nil { + t.Fatalf("unable to create pay reqs: %v", err) + } + + rHash := rHashes[0] + payReq := payReqs[0] + + payment := sendAndAssertSuccess( + t, net.Alice, + &routerrpc.SendPaymentRequest{ + PaymentRequest: payReq, + MaxHtlcs: 10, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) + + // Make sure we got the preimage. + if payment.PaymentPreimage != hex.EncodeToString(invoices[0].RPreimage) { + t.Fatalf("preimage doesn't match") + } + + // Check that Alice split the payment in at least three shards. Because + // the hand-off of the htlc to the link is asynchronous (via a mailbox), + // there is some non-determinism in the process. Depending on whether + // the new pathfinding round is started before or after the htlc is + // locked into the channel, different sharding may occur. Therefore we + // can only check if the number of shards isn't below the theoretical + // minimum. + succeeded := 0 + for _, htlc := range payment.Htlcs { + if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED { + succeeded++ + } + } + + const minExpectedShards = 3 + if succeeded < minExpectedShards { + t.Fatalf("expected at least %v shards, but got %v", + minExpectedShards, succeeded) + } + + // Make sure Bob show the invoice as settled for the full + // amount. + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + inv, err := ctx.bob.LookupInvoice( + ctxt, &lnrpc.PaymentHash{ + RHash: rHash, + }, + ) + if err != nil { + t.Fatalf("error when obtaining invoice: %v", err) + } + + if inv.AmtPaidSat != int64(paymentAmt) { + t.Fatalf("incorrect payment amt for invoice"+ + "want: %d, got %d", + paymentAmt, inv.AmtPaidSat) + } + + if inv.State != lnrpc.Invoice_SETTLED { + t.Fatalf("Invoice not settled: %v", inv.State) + } + + settled := 0 + for _, htlc := range inv.Htlcs { + if htlc.State == lnrpc.InvoiceHTLCState_SETTLED { + settled++ + } + + } + if settled != succeeded { + t.Fatalf("expected invoice to be settled "+ + "with %v HTLCs, had %v", succeeded, settled) + } +} diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 4e2be72574..d3365ab3be 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -61,6 +61,7 @@ const ( channelCloseTimeout = lntest.ChannelCloseTimeout itestLndBinary = "../../lnd-itest" anchorSize = 330 + noFeeLimitMsat = math.MaxInt64 ) // harnessTest wraps a regular testing.T providing enhanced error detection @@ -14718,6 +14719,47 @@ func testExternalFundingChanPoint(net *lntest.NetworkHarness, t *harnessTest) { closeChannelAndAssert(ctxt, t, net, dave, chanPoint, false) } +// sendAndAssertSuccess sends the given payment requests and asserts that the +// payment completes successfully. +func sendAndAssertSuccess(t *harnessTest, node *lntest.HarnessNode, + req *routerrpc.SendPaymentRequest) *lnrpc.Payment { + + ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) + defer cancel() + + stream, err := node.RouterClient.SendPayment(ctx, req) + if err != nil { + t.Fatalf("unable to send payment: %v", err) + } + + result, err := getPaymentResult(stream) + if err != nil { + t.Fatalf("unable to get payment result: %v", err) + } + + if result.Status != lnrpc.Payment_SUCCEEDED { + t.Fatalf("payment failed: %v", result.Status) + } + + return result +} + +// getPaymentResult reads a final result from the stream and returns it. +func getPaymentResult(stream routerrpc.Router_SendPaymentClient) ( + *lnrpc.Payment, error) { + + for { + payment, err := stream.Recv() + if err != nil { + return nil, err + } + + if payment.Status != lnrpc.Payment_IN_FLIGHT { + return payment, nil + } + } +} + type testCase struct { name string test func(net *lntest.NetworkHarness, t *harnessTest) @@ -14959,6 +15001,10 @@ var testsCases = []*testCase{ name: "sendtoroute multi path payment", test: testSendToRouteMultiPath, }, + { + name: "send multi path payment", + test: testSendMultiPathPayment, + }, } // TestLightningNetworkDaemon performs a series of integration tests amongst a From ef38f8f2c74019cbfba4ed2a1a3b781e98f7e1f9 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 6 Apr 2020 21:32:26 +0200 Subject: [PATCH 448/562] itest: log failure time --- lntest/itest/lnd_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index d3365ab3be..5f0c958db0 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -15145,6 +15145,10 @@ func TestLightningNetworkDaemon(t *testing.T) { // Stop at the first failure. Mimic behavior of original test // framework. if !success { + // Log failure time to help relate the lnd logs to the + // failure. + t.Logf("Failure time: %v", + time.Now().Format("2006-01-02 15:04:05.000")) break } } From 70fc9c1901c8196db5fcbd3a0dcbdcc163173f3d Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Thu, 9 Apr 2020 09:58:22 +0200 Subject: [PATCH 449/562] invoices: elminitate sleep from expiry watcher tests This commit removes sleeps from invoice expiry watcher tests in favor of a timeout guard. --- invoices/invoice_expiry_watcher_test.go | 34 ++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/invoices/invoice_expiry_watcher_test.go b/invoices/invoice_expiry_watcher_test.go index 8940063bc9..e7e28b5002 100644 --- a/invoices/invoice_expiry_watcher_test.go +++ b/invoices/invoice_expiry_watcher_test.go @@ -1,6 +1,7 @@ package invoices import ( + "sync" "testing" "time" @@ -13,6 +14,7 @@ import ( // for InvoiceExpiryWatcher tests. type invoiceExpiryWatcherTest struct { t *testing.T + wg sync.WaitGroup watcher *InvoiceExpiryWatcher testData invoiceExpiryTestData canceledInvoices []lntypes.Hash @@ -30,8 +32,11 @@ func newInvoiceExpiryWatcherTest(t *testing.T, now time.Time, ), } + test.wg.Add(numExpiredInvoices) + err := test.watcher.Start(func(paymentHash lntypes.Hash) error { test.canceledInvoices = append(test.canceledInvoices, paymentHash) + test.wg.Done() return nil }) @@ -42,6 +47,22 @@ func newInvoiceExpiryWatcherTest(t *testing.T, now time.Time, return test } +func (t *invoiceExpiryWatcherTest) waitForFinish(timeout time.Duration) { + done := make(chan struct{}) + + // Wait for all cancels. + go func() { + t.wg.Wait() + close(done) + }() + + select { + case <-done: + case <-time.After(timeout): + t.t.Fatalf("test timeout") + } +} + func (t *invoiceExpiryWatcherTest) checkExpectations() { // Check that invoices that got canceled during the test are the ones // that expired. @@ -83,9 +104,10 @@ func TestInvoiceExpiryWatcherStartStop(t *testing.T) { // Tests that no invoices will expire from an empty InvoiceExpiryWatcher. func TestInvoiceExpiryWithNoInvoices(t *testing.T) { t.Parallel() + test := newInvoiceExpiryWatcherTest(t, testTime, 0, 0) - time.Sleep(testTimeout) + test.waitForFinish(testTimeout) test.watcher.Stop() test.checkExpectations() } @@ -101,7 +123,7 @@ func TestInvoiceExpiryWithOnlyExpiredInvoices(t *testing.T) { test.watcher.AddInvoice(paymentHash, invoice) } - time.Sleep(testTimeout) + test.waitForFinish(testTimeout) test.watcher.Stop() test.checkExpectations() } @@ -110,6 +132,7 @@ func TestInvoiceExpiryWithOnlyExpiredInvoices(t *testing.T) { // will be canceled. func TestInvoiceExpiryWithPendingAndExpiredInvoices(t *testing.T) { t.Parallel() + test := newInvoiceExpiryWatcherTest(t, testTime, 5, 5) for paymentHash, invoice := range test.testData.expiredInvoices { @@ -120,7 +143,7 @@ func TestInvoiceExpiryWithPendingAndExpiredInvoices(t *testing.T) { test.watcher.AddInvoice(paymentHash, invoice) } - time.Sleep(testTimeout) + test.waitForFinish(testTimeout) test.watcher.Stop() test.checkExpectations() } @@ -128,8 +151,10 @@ func TestInvoiceExpiryWithPendingAndExpiredInvoices(t *testing.T) { // Tests adding multiple invoices at once. func TestInvoiceExpiryWhenAddingMultipleInvoices(t *testing.T) { t.Parallel() + test := newInvoiceExpiryWatcherTest(t, testTime, 5, 5) var invoices []channeldb.InvoiceWithPaymentHash + for hash, invoice := range test.testData.expiredInvoices { invoices = append(invoices, channeldb.InvoiceWithPaymentHash{ @@ -138,6 +163,7 @@ func TestInvoiceExpiryWhenAddingMultipleInvoices(t *testing.T) { }, ) } + for hash, invoice := range test.testData.pendingInvoices { invoices = append(invoices, channeldb.InvoiceWithPaymentHash{ @@ -148,7 +174,7 @@ func TestInvoiceExpiryWhenAddingMultipleInvoices(t *testing.T) { } test.watcher.AddInvoices(invoices) - time.Sleep(testTimeout) + test.waitForFinish(testTimeout) test.watcher.Stop() test.checkExpectations() } From 2b2c8b5a1090ee8672e690710ebd3dfd1520b077 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Sun, 5 Apr 2020 17:06:01 -0700 Subject: [PATCH 450/562] lnwallet/interface_test: wait for bitcoind startup Flakes locally for me on darwin. --- lnwallet/interface_test.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index 2fe3da53bf..1b6a1f28c4 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -38,6 +38,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb/kvdb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/btcwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -3062,21 +3063,25 @@ func runTests(t *testing.T, walletDriver *lnwallet.WalletDriver, defer bitcoind.Process.Kill() // Wait for the bitcoind instance to start up. - time.Sleep(time.Second) host := fmt.Sprintf("127.0.0.1:%d", rpcPort) - chainConn, err := chain.NewBitcoindConn( - netParams, host, "weks", "weks", zmqBlockHost, - zmqTxHost, 100*time.Millisecond, - ) + var chainConn *chain.BitcoindConn + err = wait.NoError(func() error { + chainConn, err = chain.NewBitcoindConn( + netParams, host, "weks", "weks", + zmqBlockHost, zmqTxHost, + 100*time.Millisecond, + ) + if err != nil { + return err + } + + return chainConn.Start() + }, 10*time.Second) if err != nil { t.Fatalf("unable to establish connection to "+ "bitcoind: %v", err) } - if err := chainConn.Start(); err != nil { - t.Fatalf("unable to establish connection to "+ - "bitcoind: %v", err) - } defer chainConn.Stop() // Create a btcwallet bitcoind client for both Alice and From 37dffb225a495af38f86bbcb8bd47ef3d74c8556 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Sun, 5 Apr 2020 17:06:14 -0700 Subject: [PATCH 451/562] input: introduce Signature iface This commit introduces the Signature interface which will be used by our witness construction methods instead of passing in raw byte slices. This will be used later to inject various kinds of mock signatures, e.g. 73-byte signatures for simulating worst-case witness weight. --- input/script_utils.go | 15 +++++++++++---- input/script_utils_test.go | 18 ++++++++++++++---- lnwallet/channel.go | 15 ++++++++++++--- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/input/script_utils.go b/input/script_utils.go index d8f80f313e..56bfbe97f1 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -23,6 +23,13 @@ var ( SequenceLockTimeSeconds = uint32(1 << 22) ) +// Signature is an interface for objects that can populate signatures during +// witness construction. +type Signature interface { + // Serialize returns a DER-encoded ECDSA signature. + Serialize() []byte +} + // WitnessScriptHash generates a pay-to-witness-script-hash public key script // paying to a version 0 witness program paying to the passed redeem script. func WitnessScriptHash(witnessScript []byte) ([]byte, error) { @@ -343,7 +350,7 @@ func SenderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor, // HTLC to activate the time locked covenant clause of a soon to be expired // HTLC. This script simply spends the multi-sig output using the // pre-generated HTLC timeout transaction. -func SenderHtlcSpendTimeout(receiverSig []byte, +func SenderHtlcSpendTimeout(receiverSig Signature, receiverSigHash txscript.SigHashType, signer Signer, signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) ( wire.TxWitness, error) { @@ -359,7 +366,7 @@ func SenderHtlcSpendTimeout(receiverSig []byte, // original OP_CHECKMULTISIG. witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack[0] = nil - witnessStack[1] = append(receiverSig, byte(receiverSigHash)) + witnessStack[1] = append(receiverSig.Serialize(), byte(receiverSigHash)) witnessStack[2] = append(sweepSig, byte(signDesc.HashType)) witnessStack[3] = nil witnessStack[4] = signDesc.WitnessScript @@ -508,7 +515,7 @@ func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey, // signed has a relative timelock delay enforced by its sequence number. This // delay give the sender of the HTLC enough time to revoke the output if this // is a breach commitment transaction. -func ReceiverHtlcSpendRedeem(senderSig []byte, +func ReceiverHtlcSpendRedeem(senderSig Signature, senderSigHash txscript.SigHashType, paymentPreimage []byte, signer Signer, signDesc *SignDescriptor, htlcSuccessTx *wire.MsgTx) ( wire.TxWitness, error) { @@ -527,7 +534,7 @@ func ReceiverHtlcSpendRedeem(senderSig []byte, // order to consume the extra pop within OP_CHECKMULTISIG. witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack[0] = nil - witnessStack[1] = append(senderSig, byte(senderSigHash)) + witnessStack[1] = append(senderSig.Serialize(), byte(senderSigHash)) witnessStack[2] = append(sweepSig, byte(signDesc.HashType)) witnessStack[3] = paymentPreimage witnessStack[4] = signDesc.WitnessScript diff --git a/input/script_utils_test.go b/input/script_utils_test.go index be1e2d0fbc..a76183dc54 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -226,7 +226,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) { htlcOutput *wire.TxOut sweepTxSigHashes *txscript.TxSigHashes senderCommitTx, sweepTx *wire.MsgTx - bobRecvrSig []byte + bobRecvrSig *btcec.Signature bobSigHash txscript.SigHashType ) @@ -303,10 +303,15 @@ func TestHTLCSenderSpendValidation(t *testing.T) { SigHashes: sweepTxSigHashes, InputIndex: 0, } - bobRecvrSig, err = bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) + bobSigBytes, err := bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) if err != nil { t.Fatalf("unable to generate alice signature: %v", err) } + + bobRecvrSig, err = btcec.ParseDERSignature(bobSigBytes, btcec.S256()) + if err != nil { + t.Fatalf("unable to parse signature: %v", err) + } } testCases := []struct { @@ -622,7 +627,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { htlcOutput *wire.TxOut receiverCommitTx, sweepTx *wire.MsgTx sweepTxSigHashes *txscript.TxSigHashes - aliceSenderSig []byte + aliceSenderSig *btcec.Signature aliceSigHash txscript.SigHashType ) @@ -695,10 +700,15 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { SigHashes: sweepTxSigHashes, InputIndex: 0, } - aliceSenderSig, err = aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) + aliceSigBytes, err := aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) if err != nil { t.Fatalf("unable to generate alice signature: %v", err) } + + aliceSenderSig, err = btcec.ParseDERSignature(aliceSigBytes, btcec.S256()) + if err != nil { + t.Fatalf("unable to parse signature: %v", err) + } } // TODO(roasbeef): modify valid to check precise script errors? diff --git a/lnwallet/channel.go b/lnwallet/channel.go index c9ca227dbc..11eb115932 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -5459,11 +5459,16 @@ func newOutgoingHtlcResolution(signer input.Signer, InputIndex: 0, } + htlcSig, err := btcec.ParseDERSignature(htlc.Signature, btcec.S256()) + if err != nil { + return nil, err + } + // With the sign desc created, we can now construct the full witness // for the timeout transaction, and populate it as well. sigHashType := HtlcSigHashType(chanType) timeoutWitness, err := input.SenderHtlcSpendTimeout( - htlc.Signature, sigHashType, signer, &timeoutSignDesc, timeoutTx, + htlcSig, sigHashType, signer, &timeoutSignDesc, timeoutTx, ) if err != nil { return nil, err @@ -5585,14 +5590,18 @@ func newIncomingHtlcResolution(signer input.Signer, InputIndex: 0, } + htlcSig, err := btcec.ParseDERSignature(htlc.Signature, btcec.S256()) + if err != nil { + return nil, err + } + // Next, we'll construct the full witness needed to satisfy the input of // the success transaction. Don't specify the preimage yet. The preimage // will be supplied by the contract resolver, either directly or when it // becomes known. sigHashType := HtlcSigHashType(chanType) successWitness, err := input.ReceiverHtlcSpendRedeem( - htlc.Signature, sigHashType, nil, signer, &successSignDesc, - successTx, + htlcSig, sigHashType, nil, signer, &successSignDesc, successTx, ) if err != nil { return nil, err From 363caa441aca977747027a6e1152b6e4d12452af Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 12 Mar 2020 18:07:09 -0700 Subject: [PATCH 452/562] rpc: allow wumbo invoices In this commit, we remove the restriction surrounding the largest invoices that we'll allow a user to create. After #3967 has landed, users will be able to send in _aggregate_ a payment larger than the current max HTLC size limit in the network. As a result, we can just treat that value as the system's MTU, and allow users to request payments it multiples of that MTU value. A follow up to this PR at a later time will also allow wumbo _channels_. However, that requires us to tweak the way we scale CSV values, as post wumbo, there is no true channel size limit, only the _local_ limit of a given node. We also need to implement a way for nodes to signal to other nodes their accepted max channel size. --- lnrpc/invoicesrpc/addinvoice.go | 12 ------------ lnrpc/invoicesrpc/config_active.go | 3 --- lnrpc/invoicesrpc/invoices_server.go | 1 - lnrpc/routerrpc/router_backend.go | 12 ------------ rpcserver.go | 1 - subrpcserver_config.go | 3 --- 6 files changed, 32 deletions(-) diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index 28b48e5479..24463ccbe4 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -37,9 +37,6 @@ type AddInvoiceConfig struct { // that's backed by the identity private key of the running lnd node. NodeSigner *netann.NodeSigner - // MaxPaymentMSat is the maximum allowed payment. - MaxPaymentMSat lnwire.MilliSatoshi - // DefaultCLTVExpiry is the default invoice expiry if no values is // specified. DefaultCLTVExpiry uint32 @@ -167,15 +164,6 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, amtMSat := invoice.Value - // The value of the invoice must also not exceed the current soft-limit - // on the largest payment within the network. - if amtMSat > cfg.MaxPaymentMSat { - return nil, nil, fmt.Errorf("payment of %v is too large, max "+ - "payment allowed is %v", invoice.Value, - cfg.MaxPaymentMSat.ToSatoshis(), - ) - } - // We also create an encoded payment request which allows the // caller to compactly send the invoice to the payer. We'll create a // list of options to be added to the encoded payment request. For now diff --git a/lnrpc/invoicesrpc/config_active.go b/lnrpc/invoicesrpc/config_active.go index b347ecd54d..9e43ccc893 100644 --- a/lnrpc/invoicesrpc/config_active.go +++ b/lnrpc/invoicesrpc/config_active.go @@ -40,9 +40,6 @@ type Config struct { // that's backed by the identity private key of the running lnd node. NodeSigner *netann.NodeSigner - // MaxPaymentMSat is the maximum allowed payment. - MaxPaymentMSat lnwire.MilliSatoshi - // DefaultCLTVExpiry is the default invoice expiry if no values is // specified. DefaultCLTVExpiry uint32 diff --git a/lnrpc/invoicesrpc/invoices_server.go b/lnrpc/invoicesrpc/invoices_server.go index 87cdc02610..e915bc1a08 100644 --- a/lnrpc/invoicesrpc/invoices_server.go +++ b/lnrpc/invoicesrpc/invoices_server.go @@ -250,7 +250,6 @@ func (s *Server) AddHoldInvoice(ctx context.Context, IsChannelActive: s.cfg.IsChannelActive, ChainParams: s.cfg.ChainParams, NodeSigner: s.cfg.NodeSigner, - MaxPaymentMSat: s.cfg.MaxPaymentMSat, DefaultCLTVExpiry: s.cfg.DefaultCLTVExpiry, ChanDB: s.cfg.ChanDB, GenInvoiceFeatures: s.cfg.GenInvoiceFeatures, diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index d4d75edd39..3ee61c97ba 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -698,18 +698,6 @@ func (r *RouterBackend) extractIntentFromSendRequest( payIntent.DestFeatures = features } - // Currently, within the bootstrap phase of the network, we limit the - // largest payment size allotted to (2^32) - 1 mSAT or 4.29 million - // satoshis. - if payIntent.Amount > r.MaxPaymentMSat { - // In this case, we'll send an error to the caller, but - // continue our loop for the next payment. - return payIntent, fmt.Errorf("payment of %v is too large, "+ - "max payment allowed is %v", payIntent.Amount, - r.MaxPaymentMSat) - - } - // Check for disallowed payments to self. if !rpcPayReq.AllowSelfPayment && payIntent.Target == r.SelfNode { return nil, errors.New("self-payments not allowed") diff --git a/rpcserver.go b/rpcserver.go index 3928eeb117..043373bfe7 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -4305,7 +4305,6 @@ func (r *rpcServer) AddInvoice(ctx context.Context, IsChannelActive: r.server.htlcSwitch.HasActiveLink, ChainParams: activeNetParams.Params, NodeSigner: r.server.nodeSigner, - MaxPaymentMSat: MaxPaymentMSat, DefaultCLTVExpiry: defaultDelta, ChanDB: r.server.chanDB, GenInvoiceFeatures: func() *lnwire.FeatureVector { diff --git a/subrpcserver_config.go b/subrpcserver_config.go index 4855911881..316320289f 100644 --- a/subrpcserver_config.go +++ b/subrpcserver_config.go @@ -202,9 +202,6 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl, subCfgValue.FieldByName("NodeSigner").Set( reflect.ValueOf(nodeSigner), ) - subCfgValue.FieldByName("MaxPaymentMSat").Set( - reflect.ValueOf(MaxPaymentMSat), - ) defaultDelta := cfg.Bitcoin.TimeLockDelta if registeredChains.PrimaryChain() == litecoinChain { defaultDelta = cfg.Litecoin.TimeLockDelta From 06f73c0a6688ae7fb220fa7a6ea41fdefd8bba4c Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 9 Apr 2020 16:28:34 +0200 Subject: [PATCH 453/562] lnrpc: remove deprecated payment path Not applicable anymore on the payment level with multi-part sends. --- lnrpc/routerrpc/router_backend.go | 7 - lnrpc/rpc.pb.go | 1517 ++++++++++++++--------------- lnrpc/rpc.proto | 3 +- lnrpc/rpc.swagger.json | 7 - lntest/itest/lnd_test.go | 13 +- 5 files changed, 759 insertions(+), 788 deletions(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 3ee61c97ba..e8493871ee 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -1112,12 +1112,6 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) ( } } - // Encode the hops from the successful route, if any. - path := make([]string, len(route.Hops)) - for i, hop := range route.Hops { - path[i] = hex.EncodeToString(hop.PubKeyBytes[:]) - } - msatValue := int64(payment.Info.Value) satValue := int64(payment.Info.Value.ToSatoshis()) @@ -1153,7 +1147,6 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) ( ValueSat: satValue, CreationDate: payment.Info.CreationTime.Unix(), CreationTimeNs: creationTimeNS, - Path: path, Fee: int64(route.TotalFees().ToSatoshis()), FeeSat: int64(route.TotalFees().ToSatoshis()), FeeMsat: int64(route.TotalFees()), diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 32dfc48b71..a17999b60c 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -9529,8 +9529,6 @@ type Payment struct { Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` // Deprecated: Do not use. /// Deprecated, use creation_time_ns CreationDate int64 `protobuf:"varint,3,opt,name=creation_date,json=creationDate,proto3" json:"creation_date,omitempty"` // Deprecated: Do not use. - /// The path this payment took. - Path []string `protobuf:"bytes,4,rep,name=path,proto3" json:"path,omitempty"` // Deprecated: Do not use. /// Deprecated, use fee_sat or fee_msat. Fee int64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` // Deprecated: Do not use. /// The payment preimage @@ -9610,14 +9608,6 @@ func (m *Payment) GetCreationDate() int64 { return 0 } -// Deprecated: Do not use. -func (m *Payment) GetPath() []string { - if m != nil { - return m.Path - } - return nil -} - // Deprecated: Do not use. func (m *Payment) GetFee() int64 { if m != nil { @@ -12008,760 +11998,759 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 12041 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x6c, 0x24, 0x49, - 0x76, 0x18, 0xda, 0xf5, 0x22, 0xab, 0x4e, 0x3d, 0x58, 0x0c, 0xbe, 0xaa, 0xd9, 0xdd, 0xd3, 0x3d, - 0x39, 0xb3, 0xd3, 0xbd, 0x3d, 0xb3, 0xec, 0x9e, 0xde, 0xed, 0x99, 0xdd, 0x99, 0xab, 0xd5, 0x16, - 0xc9, 0x62, 0xb3, 0xb6, 0xc9, 0x22, 0x27, 0xab, 0x38, 0xa3, 0x59, 0x3d, 0x72, 0x93, 0x55, 0x41, - 0x32, 0xd5, 0x55, 0x99, 0x35, 0x99, 0x59, 0x7c, 0xec, 0x62, 0xee, 0x87, 0x61, 0x1b, 0x82, 0x61, - 0x1b, 0x10, 0x6c, 0x19, 0xb0, 0x2c, 0xc1, 0x0f, 0xc1, 0x36, 0x0c, 0x03, 0x82, 0x00, 0xc9, 0x1f, - 0x06, 0xfc, 0xaf, 0x1f, 0x3f, 0x60, 0x48, 0xfe, 0xb0, 0x21, 0x08, 0x30, 0x6c, 0xcb, 0x7f, 0x86, - 0x00, 0x7f, 0x1b, 0x30, 0xe2, 0x9c, 0x88, 0xcc, 0xc8, 0xaa, 0x64, 0x77, 0xcf, 0xee, 0x7a, 0x7f, - 0xc8, 0xca, 0x13, 0x27, 0xde, 0x27, 0x4e, 0x9c, 0x57, 0x44, 0x40, 0xc9, 0x1f, 0xf7, 0x37, 0xc6, - 0xbe, 0x17, 0x7a, 0xac, 0x30, 0x74, 0xfd, 0x71, 0x7f, 0xfd, 0xf6, 0xa9, 0xe7, 0x9d, 0x0e, 0xf9, - 0x23, 0x7b, 0xec, 0x3c, 0xb2, 0x5d, 0xd7, 0x0b, 0xed, 0xd0, 0xf1, 0xdc, 0x80, 0x90, 0x8c, 0x1f, - 0x42, 0xed, 0x19, 0x77, 0xbb, 0x9c, 0x0f, 0x4c, 0xfe, 0xc5, 0x84, 0x07, 0x21, 0x7b, 0x17, 0x16, - 0x6d, 0xfe, 0x23, 0xce, 0x07, 0xd6, 0xd8, 0x0e, 0x82, 0xf1, 0x99, 0x6f, 0x07, 0xbc, 0x91, 0xb9, - 0x97, 0x79, 0x50, 0x31, 0xeb, 0x94, 0x70, 0x18, 0xc1, 0xd9, 0x9b, 0x50, 0x09, 0x04, 0x2a, 0x77, - 0x43, 0xdf, 0x1b, 0x5f, 0x35, 0xb2, 0x88, 0x57, 0x16, 0xb0, 0x16, 0x81, 0x8c, 0x21, 0x2c, 0x44, - 0x35, 0x04, 0x63, 0xcf, 0x0d, 0x38, 0x7b, 0x0c, 0xcb, 0x7d, 0x67, 0x7c, 0xc6, 0x7d, 0x0b, 0x33, - 0x8f, 0x5c, 0x3e, 0xf2, 0x5c, 0xa7, 0xdf, 0xc8, 0xdc, 0xcb, 0x3d, 0x28, 0x99, 0x8c, 0xd2, 0x44, - 0x8e, 0x7d, 0x99, 0xc2, 0xee, 0xc3, 0x02, 0x77, 0x09, 0xce, 0x07, 0x98, 0x4b, 0x56, 0x55, 0x8b, - 0xc1, 0x22, 0x83, 0xf1, 0x1b, 0x59, 0x58, 0x6c, 0xbb, 0x4e, 0xf8, 0x99, 0x3d, 0x1c, 0xf2, 0x50, - 0xf5, 0xe9, 0x3e, 0x2c, 0x5c, 0x20, 0x00, 0xfb, 0x74, 0xe1, 0xf9, 0x03, 0xd9, 0xa3, 0x1a, 0x81, - 0x0f, 0x25, 0xf4, 0xda, 0x96, 0x65, 0xaf, 0x6d, 0x59, 0xea, 0x70, 0xe5, 0xae, 0x19, 0xae, 0xfb, - 0xb0, 0xe0, 0xf3, 0xbe, 0x77, 0xce, 0xfd, 0x2b, 0xeb, 0xc2, 0x71, 0x07, 0xde, 0x45, 0x23, 0x7f, - 0x2f, 0xf3, 0xa0, 0x60, 0xd6, 0x14, 0xf8, 0x33, 0x84, 0xb2, 0x4d, 0x58, 0xe8, 0x9f, 0xd9, 0xae, - 0xcb, 0x87, 0xd6, 0xb1, 0xdd, 0x7f, 0x31, 0x19, 0x07, 0x8d, 0xc2, 0xbd, 0xcc, 0x83, 0xf2, 0x93, - 0x9b, 0x1b, 0x38, 0xab, 0x1b, 0x5b, 0x67, 0xb6, 0xbb, 0x89, 0x29, 0x5d, 0xd7, 0x1e, 0x07, 0x67, - 0x5e, 0x68, 0xd6, 0x64, 0x0e, 0x02, 0x07, 0xc6, 0x32, 0x30, 0x7d, 0x24, 0x68, 0xec, 0x8d, 0x7f, - 0x99, 0x81, 0xa5, 0x23, 0x77, 0xe8, 0xf5, 0x5f, 0xfc, 0x84, 0x43, 0x94, 0xd2, 0x87, 0xec, 0xeb, - 0xf6, 0x21, 0xf7, 0x55, 0xfb, 0xb0, 0x0a, 0xcb, 0xc9, 0xc6, 0xca, 0x5e, 0x70, 0x58, 0x11, 0xb9, - 0x4f, 0xb9, 0x6a, 0x96, 0xea, 0xc6, 0xd7, 0xa1, 0xde, 0x9f, 0xf8, 0x3e, 0x77, 0x67, 0xfa, 0xb1, - 0x20, 0xe1, 0x51, 0x47, 0xde, 0x84, 0x8a, 0xcb, 0x2f, 0x62, 0x34, 0x49, 0xbb, 0x2e, 0xbf, 0x50, - 0x28, 0x46, 0x03, 0x56, 0xa7, 0xab, 0x91, 0x0d, 0xf8, 0x8b, 0x0c, 0xe4, 0x8f, 0xc2, 0x4b, 0x8f, - 0x3d, 0x85, 0x8a, 0x3d, 0x18, 0xf8, 0x3c, 0x08, 0xac, 0xf0, 0x6a, 0x4c, 0x2b, 0xa5, 0xf6, 0x84, - 0xc9, 0x2e, 0x36, 0x29, 0xa9, 0x77, 0x35, 0xe6, 0x66, 0xd9, 0x8e, 0x3f, 0x58, 0x03, 0xe6, 0xe5, - 0x27, 0xd6, 0x5b, 0x32, 0xd5, 0x27, 0xbb, 0x03, 0x60, 0x8f, 0xbc, 0x89, 0x1b, 0x5a, 0x81, 0x1d, - 0xe2, 0x88, 0xe5, 0xcc, 0x12, 0x41, 0xba, 0x76, 0xc8, 0x6e, 0x41, 0x69, 0xfc, 0xc2, 0x0a, 0xfa, - 0xbe, 0x33, 0x0e, 0x91, 0x78, 0x4a, 0x66, 0x71, 0xfc, 0xa2, 0x8b, 0xdf, 0xec, 0x5d, 0x28, 0x7a, - 0x93, 0x70, 0xec, 0x39, 0x6e, 0x28, 0xe9, 0x65, 0x41, 0x36, 0xe4, 0x60, 0x12, 0x1e, 0x0a, 0xb0, - 0x19, 0x21, 0xb0, 0xb7, 0xa1, 0xda, 0xf7, 0xdc, 0x13, 0xc7, 0x1f, 0x11, 0x47, 0x68, 0xcc, 0x61, - 0x5d, 0x49, 0xa0, 0xf1, 0x07, 0x59, 0x28, 0xf7, 0x7c, 0xdb, 0x0d, 0xec, 0xbe, 0x00, 0xb0, 0x35, - 0x98, 0x0f, 0x2f, 0xad, 0x33, 0x3b, 0x38, 0xc3, 0xae, 0x96, 0xcc, 0xb9, 0xf0, 0x72, 0xd7, 0x0e, - 0xce, 0xd8, 0x2a, 0xcc, 0x51, 0x2b, 0xb1, 0x43, 0x39, 0x53, 0x7e, 0x89, 0x05, 0xe2, 0x4e, 0x46, - 0x56, 0xb2, 0xaa, 0x1c, 0x52, 0x4c, 0xdd, 0x9d, 0x8c, 0xb6, 0x74, 0xb8, 0xe8, 0xfc, 0xb1, 0x98, - 0x6e, 0xaa, 0x80, 0xba, 0x57, 0x42, 0x08, 0xd6, 0xf1, 0x26, 0x54, 0x64, 0x32, 0x77, 0x4e, 0xcf, - 0xa8, 0x8f, 0x05, 0xb3, 0x4c, 0x08, 0x08, 0x12, 0x25, 0x84, 0xce, 0x88, 0x5b, 0x41, 0x68, 0x8f, - 0xc6, 0xb2, 0x4b, 0x25, 0x01, 0xe9, 0x0a, 0x00, 0x26, 0x7b, 0xa1, 0x3d, 0xb4, 0x4e, 0x38, 0x0f, - 0x1a, 0xf3, 0x32, 0x59, 0x40, 0x76, 0x38, 0x0f, 0xd8, 0xd7, 0xa0, 0x36, 0xe0, 0x41, 0x68, 0xc9, - 0xc9, 0xe0, 0x41, 0xa3, 0x88, 0x2b, 0xbf, 0x2a, 0xa0, 0x4d, 0x05, 0x64, 0xb7, 0x01, 0x7c, 0xfb, - 0xc2, 0x12, 0x03, 0xc1, 0x2f, 0x1b, 0x25, 0x9a, 0x05, 0xdf, 0xbe, 0xe8, 0x5d, 0xee, 0xf2, 0x4b, - 0x41, 0x35, 0xcf, 0x78, 0xa8, 0x0d, 0x5a, 0x20, 0xa9, 0xd3, 0xd8, 0x03, 0xa6, 0x81, 0xb7, 0x79, - 0x68, 0x3b, 0xc3, 0x80, 0x7d, 0x00, 0x95, 0x50, 0x43, 0x46, 0x36, 0x58, 0x8e, 0x48, 0x48, 0xcb, - 0x60, 0x26, 0xf0, 0x8c, 0x33, 0x28, 0xee, 0x70, 0xbe, 0xe7, 0x8c, 0x9c, 0x90, 0xad, 0x42, 0xe1, - 0xc4, 0xb9, 0xe4, 0x44, 0xec, 0xb9, 0xdd, 0x1b, 0x26, 0x7d, 0xb2, 0xbb, 0x00, 0xf8, 0xc3, 0x1a, - 0x45, 0xd4, 0xb4, 0x7b, 0xc3, 0x2c, 0x21, 0x6c, 0x3f, 0xb0, 0x43, 0xb6, 0x0e, 0xf3, 0x63, 0xee, - 0xf7, 0xb9, 0x9a, 0xb7, 0xdd, 0x1b, 0xa6, 0x02, 0x6c, 0xce, 0x43, 0x61, 0x28, 0x4a, 0x37, 0xfe, - 0xb8, 0x00, 0xe5, 0x2e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, 0xcd, - 0xde, 0x82, 0x32, 0x0e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x99, 0x6d, 0x64, 0x4c, - 0x10, 0xe0, 0x2e, 0x42, 0x59, 0x1d, 0x72, 0xf6, 0x48, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x42, 0xd1, - 0x1e, 0x85, 0xd4, 0xbc, 0x0a, 0x82, 0xe7, 0xed, 0x51, 0x88, 0x4d, 0x7b, 0x13, 0x2a, 0x63, 0xfb, - 0x6a, 0x24, 0xd6, 0x72, 0x44, 0x0e, 0x15, 0xb3, 0x2c, 0x61, 0x48, 0x10, 0x4f, 0x60, 0x49, 0x47, - 0x51, 0x95, 0x17, 0xa2, 0xca, 0x17, 0x35, 0x6c, 0xd9, 0x86, 0xfb, 0xb0, 0xa0, 0xf2, 0xf8, 0xd4, - 0x1f, 0x24, 0x93, 0x92, 0x59, 0x93, 0x60, 0xd5, 0xcb, 0x07, 0x50, 0x3f, 0x71, 0x5c, 0x7b, 0x68, - 0xf5, 0x87, 0xe1, 0xb9, 0x35, 0xe0, 0xc3, 0xd0, 0x46, 0x8a, 0x29, 0x98, 0x35, 0x84, 0x6f, 0x0d, - 0xc3, 0xf3, 0x6d, 0x01, 0x65, 0xef, 0x41, 0xe9, 0x84, 0x73, 0x0b, 0x07, 0xab, 0x51, 0x4c, 0x2c, - 0x3c, 0x35, 0x43, 0x66, 0xf1, 0x44, 0xcd, 0xd5, 0x7b, 0x50, 0xf7, 0x26, 0xe1, 0xa9, 0xe7, 0xb8, - 0xa7, 0x96, 0xe0, 0x77, 0x96, 0x33, 0x40, 0x1a, 0xca, 0x6f, 0x66, 0x1f, 0x67, 0xcc, 0x9a, 0x4a, - 0x13, 0x9c, 0xa7, 0x3d, 0x60, 0xef, 0xc0, 0xc2, 0xd0, 0x0e, 0x42, 0xeb, 0xcc, 0x1b, 0x5b, 0xe3, - 0xc9, 0xf1, 0x0b, 0x7e, 0xd5, 0xa8, 0xe2, 0x40, 0x54, 0x05, 0x78, 0xd7, 0x1b, 0x1f, 0x22, 0x50, - 0x50, 0x36, 0xb6, 0x93, 0x1a, 0x01, 0xf7, 0x32, 0x0f, 0xaa, 0x66, 0x49, 0x40, 0xa8, 0xd2, 0xcf, - 0x61, 0x09, 0xa7, 0xa7, 0x3f, 0x09, 0x42, 0x6f, 0x64, 0x09, 0x5e, 0xed, 0x0f, 0x82, 0x46, 0x19, - 0x69, 0xed, 0xeb, 0xb2, 0xb1, 0xda, 0x1c, 0x6f, 0x6c, 0xf3, 0x20, 0xdc, 0x42, 0x64, 0x93, 0x70, - 0xc5, 0x86, 0x7e, 0x65, 0x2e, 0x0e, 0xa6, 0xe1, 0xec, 0x3d, 0x60, 0xf6, 0x70, 0xe8, 0x5d, 0x58, - 0x01, 0x1f, 0x9e, 0x58, 0x72, 0x10, 0x1b, 0xb5, 0x7b, 0x99, 0x07, 0x45, 0xb3, 0x8e, 0x29, 0x5d, - 0x3e, 0x3c, 0x39, 0x24, 0x38, 0xfb, 0x00, 0x70, 0x31, 0x59, 0x27, 0xdc, 0x0e, 0x27, 0x3e, 0x0f, - 0x1a, 0x0b, 0xf7, 0x72, 0x0f, 0x6a, 0x4f, 0x16, 0xa3, 0xf1, 0x42, 0xf0, 0xa6, 0x13, 0x9a, 0x15, - 0x81, 0x27, 0xbf, 0x83, 0xf5, 0x6d, 0x58, 0x4d, 0x6f, 0x92, 0x20, 0x2a, 0x31, 0x2a, 0x82, 0x18, - 0xf3, 0xa6, 0xf8, 0xc9, 0x96, 0xa1, 0x70, 0x6e, 0x0f, 0x27, 0x5c, 0xf2, 0x74, 0xfa, 0xf8, 0x28, - 0xfb, 0xed, 0x8c, 0xf1, 0x47, 0x19, 0xa8, 0x50, 0x2f, 0xa5, 0x2c, 0xf2, 0x16, 0x54, 0x15, 0x35, - 0x70, 0xdf, 0xf7, 0x7c, 0xc9, 0xd5, 0x14, 0xe5, 0xb5, 0x04, 0x4c, 0xec, 0x2a, 0x0a, 0x69, 0xec, - 0x73, 0x67, 0x64, 0x9f, 0xaa, 0xa2, 0x15, 0x29, 0x1d, 0x4a, 0x30, 0x7b, 0x3f, 0x2e, 0xcf, 0xf7, - 0x26, 0x21, 0x97, 0x7b, 0x5e, 0x45, 0x76, 0xcf, 0x14, 0xb0, 0xa8, 0x74, 0xfc, 0x7a, 0x0d, 0x3a, - 0x37, 0x7e, 0x2b, 0x03, 0x4c, 0x34, 0xbb, 0xe7, 0x51, 0x01, 0x92, 0x42, 0xa7, 0x73, 0x66, 0x5e, - 0x7b, 0x85, 0x64, 0x5f, 0xb6, 0x42, 0x0c, 0x28, 0x50, 0xdb, 0xf3, 0x29, 0x6d, 0xa7, 0xa4, 0xef, - 0xe7, 0x8b, 0xb9, 0x7a, 0xde, 0xf8, 0x2f, 0x39, 0x58, 0xde, 0xa2, 0x2d, 0xbb, 0xd9, 0xef, 0xf3, - 0x71, 0xb4, 0x76, 0xee, 0x42, 0xd9, 0xf5, 0x06, 0x5c, 0x51, 0x2c, 0x35, 0x0c, 0x04, 0x48, 0x23, - 0xd7, 0x33, 0xdb, 0x71, 0xa9, 0xe1, 0x34, 0x98, 0x25, 0x84, 0x60, 0xb3, 0xdf, 0x81, 0x85, 0x31, - 0x77, 0x07, 0xfa, 0x12, 0x21, 0xa1, 0xaa, 0x2a, 0xc1, 0x72, 0x75, 0xdc, 0x85, 0xf2, 0xc9, 0x84, - 0xf0, 0x04, 0x63, 0xc9, 0x23, 0x0d, 0x80, 0x04, 0x35, 0x89, 0xbf, 0x8c, 0x27, 0xc1, 0x19, 0xa6, - 0x16, 0x30, 0x75, 0x5e, 0x7c, 0x8b, 0xa4, 0x3b, 0x00, 0x83, 0x49, 0x10, 0xca, 0x15, 0x33, 0x87, - 0x89, 0x25, 0x01, 0xa1, 0x15, 0xf3, 0x0d, 0x58, 0x1a, 0xd9, 0x97, 0x16, 0xd2, 0x8e, 0xe5, 0xb8, - 0xd6, 0xc9, 0x10, 0xf7, 0x9c, 0x79, 0xc4, 0xab, 0x8f, 0xec, 0xcb, 0x4f, 0x45, 0x4a, 0xdb, 0xdd, - 0x41, 0xb8, 0x60, 0x2b, 0x4a, 0xdc, 0xf1, 0x79, 0xc0, 0xfd, 0x73, 0x8e, 0x9c, 0x20, 0x1f, 0xc9, - 0x34, 0x26, 0x41, 0x45, 0x8b, 0x46, 0xa2, 0xdf, 0xe1, 0xb0, 0x4f, 0xcb, 0xde, 0x9c, 0x1f, 0x39, - 0xee, 0x6e, 0x38, 0xec, 0x8b, 0x7d, 0x45, 0xf0, 0x91, 0x31, 0xf7, 0xad, 0x17, 0x17, 0xb8, 0x86, - 0xf3, 0xc8, 0x37, 0x0e, 0xb9, 0xff, 0xfc, 0x42, 0x6c, 0xfd, 0xfd, 0x00, 0x19, 0x91, 0x7d, 0xd5, - 0x28, 0xe3, 0x02, 0x2f, 0xf6, 0x03, 0xc1, 0x82, 0xec, 0x2b, 0xb1, 0x08, 0x45, 0x6b, 0x6d, 0x9c, - 0x05, 0x3e, 0xc0, 0xe2, 0x03, 0xe4, 0xa8, 0x55, 0x6c, 0x6c, 0x53, 0x26, 0x88, 0x7a, 0x02, 0x41, - 0xf5, 0xaa, 0xb1, 0x27, 0x43, 0xfb, 0x34, 0x40, 0x96, 0x52, 0x35, 0x2b, 0x12, 0xb8, 0x23, 0x60, - 0xc6, 0x67, 0x24, 0x64, 0x69, 0x73, 0x2b, 0xd7, 0x8c, 0xd8, 0xea, 0x11, 0x82, 0xf3, 0x5a, 0x34, - 0xe5, 0x57, 0xda, 0xa4, 0x65, 0x53, 0x26, 0xcd, 0xf8, 0xdd, 0x0c, 0x54, 0x64, 0xc9, 0x28, 0x94, - 0xb0, 0x0d, 0x60, 0x6a, 0x16, 0xc3, 0x4b, 0x67, 0x60, 0x1d, 0x5f, 0x85, 0x3c, 0x20, 0xa2, 0xd9, - 0xbd, 0x61, 0xd6, 0x65, 0x5a, 0xef, 0xd2, 0x19, 0x6c, 0x8a, 0x14, 0xf6, 0x10, 0xea, 0x09, 0xfc, - 0x20, 0xf4, 0x89, 0xa2, 0x77, 0x6f, 0x98, 0x35, 0x0d, 0xbb, 0x1b, 0xfa, 0x62, 0x8d, 0x08, 0x91, - 0x67, 0x12, 0x5a, 0x8e, 0x3b, 0xe0, 0x97, 0x48, 0x46, 0x55, 0xb3, 0x4c, 0xb0, 0xb6, 0x00, 0x6d, - 0xd6, 0xa0, 0xa2, 0x17, 0x67, 0x9c, 0x42, 0x51, 0xc9, 0x4b, 0x28, 0x30, 0x4c, 0x35, 0xc9, 0x2c, - 0x85, 0x51, 0x4b, 0x6e, 0x42, 0x31, 0xd9, 0x02, 0x73, 0x3e, 0x7c, 0xed, 0x8a, 0x8d, 0xef, 0x42, - 0x7d, 0x4f, 0x10, 0x8f, 0x2b, 0x88, 0x55, 0xca, 0x7f, 0xab, 0x30, 0xa7, 0x2d, 0x9a, 0x92, 0x29, - 0xbf, 0xc4, 0x9e, 0x7b, 0xe6, 0x05, 0xa1, 0xac, 0x05, 0x7f, 0x1b, 0x7f, 0x9c, 0x01, 0xd6, 0x0a, - 0x42, 0x67, 0x64, 0x87, 0x7c, 0x87, 0x47, 0x6c, 0xe1, 0x00, 0x2a, 0xa2, 0xb4, 0x9e, 0xd7, 0x24, - 0x81, 0x8c, 0x04, 0x8a, 0x77, 0xe5, 0x32, 0x9e, 0xcd, 0xb0, 0xa1, 0x63, 0x13, 0x9b, 0x4f, 0x14, - 0x20, 0x56, 0x59, 0x68, 0xfb, 0xa7, 0x3c, 0x44, 0x31, 0x4e, 0xca, 0xfb, 0x40, 0x20, 0x21, 0xc0, - 0xad, 0xff, 0x22, 0x2c, 0xce, 0x94, 0xa1, 0xf3, 0xe5, 0x52, 0x0a, 0x5f, 0xce, 0xe9, 0x7c, 0xd9, - 0x82, 0xa5, 0x44, 0xbb, 0x24, 0xa5, 0xad, 0xc1, 0xbc, 0x58, 0x10, 0x42, 0x38, 0xc8, 0x90, 0x54, - 0x79, 0xc2, 0xb9, 0x10, 0x83, 0x1f, 0xc1, 0xf2, 0x09, 0xe7, 0xbe, 0x1d, 0x62, 0x22, 0xae, 0x18, - 0x31, 0x43, 0xb2, 0xe0, 0x45, 0x99, 0xd6, 0xb5, 0xc3, 0x43, 0xee, 0x8b, 0x99, 0x32, 0xfe, 0x5b, - 0x06, 0x16, 0x04, 0x07, 0xdd, 0xb7, 0xdd, 0x2b, 0x35, 0x4e, 0x7b, 0xa9, 0xe3, 0xf4, 0x40, 0xdb, - 0x0c, 0x35, 0xec, 0xaf, 0x3a, 0x48, 0xb9, 0xe9, 0x41, 0x62, 0xf7, 0xa0, 0x92, 0x68, 0x6b, 0x01, - 0xdb, 0x0a, 0x41, 0xd4, 0xc8, 0x9f, 0x7e, 0x18, 0xdf, 0x81, 0x7a, 0xdc, 0x6c, 0x39, 0x86, 0x0c, - 0xf2, 0x82, 0x24, 0x65, 0x01, 0xf8, 0xdb, 0xf8, 0x9d, 0x0c, 0x21, 0x6e, 0x79, 0x4e, 0x24, 0x9d, - 0x0a, 0x44, 0x21, 0xf7, 0x2a, 0x44, 0xf1, 0xfb, 0x5a, 0xa9, 0xfe, 0xa7, 0xef, 0xac, 0x58, 0x3a, - 0x01, 0x77, 0x07, 0x96, 0x3d, 0x1c, 0x22, 0xf3, 0x2d, 0x9a, 0xf3, 0xe2, 0xbb, 0x39, 0x1c, 0x1a, - 0xf7, 0x61, 0x51, 0x6b, 0xdd, 0x4b, 0xfa, 0xd1, 0x01, 0xb6, 0xe7, 0x04, 0xe1, 0x91, 0x1b, 0x8c, - 0x35, 0xc1, 0xed, 0x16, 0x94, 0x04, 0x87, 0x15, 0x2d, 0xa3, 0x25, 0x5b, 0x30, 0x05, 0xcb, 0x15, - 0xed, 0x0a, 0x30, 0xd1, 0xbe, 0x94, 0x89, 0x59, 0x99, 0x68, 0x5f, 0x62, 0xa2, 0xf1, 0x6d, 0x58, - 0x4a, 0x94, 0x27, 0xab, 0x7e, 0x13, 0x0a, 0x93, 0xf0, 0xd2, 0x53, 0xa2, 0x79, 0x59, 0x52, 0x88, - 0x50, 0x00, 0x4d, 0x4a, 0x31, 0x3e, 0x86, 0xc5, 0x0e, 0xbf, 0x90, 0x8b, 0x58, 0x35, 0xe4, 0x1d, - 0xc8, 0xbf, 0x42, 0x29, 0xc4, 0x74, 0x63, 0x03, 0x98, 0x9e, 0x59, 0xd6, 0xaa, 0xe9, 0x88, 0x99, - 0x84, 0x8e, 0x68, 0xbc, 0x03, 0xac, 0xeb, 0x9c, 0xba, 0xfb, 0x3c, 0x08, 0xec, 0xd3, 0x68, 0xd9, - 0xd7, 0x21, 0x37, 0x0a, 0x4e, 0x25, 0x8f, 0x12, 0x3f, 0x8d, 0x6f, 0xc2, 0x52, 0x02, 0x4f, 0x16, - 0x7c, 0x1b, 0x4a, 0x81, 0x73, 0xea, 0xa2, 0x60, 0x25, 0x8b, 0x8e, 0x01, 0xc6, 0x0e, 0x2c, 0x7f, - 0xca, 0x7d, 0xe7, 0xe4, 0xea, 0x55, 0xc5, 0x27, 0xcb, 0xc9, 0x4e, 0x97, 0xd3, 0x82, 0x95, 0xa9, - 0x72, 0x64, 0xf5, 0x44, 0xbe, 0x72, 0x26, 0x8b, 0x26, 0x7d, 0x68, 0x7c, 0x2f, 0xab, 0xf3, 0x3d, - 0xe3, 0x08, 0xd8, 0x96, 0xe7, 0xba, 0xbc, 0x1f, 0x1e, 0x72, 0xee, 0xc7, 0x56, 0xaa, 0x98, 0x56, - 0xcb, 0x4f, 0xd6, 0xe4, 0xc8, 0x4e, 0x33, 0x53, 0x49, 0xc4, 0x0c, 0xf2, 0x63, 0xee, 0x8f, 0xb0, - 0xe0, 0xa2, 0x89, 0xbf, 0x8d, 0x15, 0x58, 0x4a, 0x14, 0x2b, 0xf5, 0xfa, 0xc7, 0xb0, 0xb2, 0xed, - 0x04, 0xfd, 0xd9, 0x0a, 0xd7, 0x60, 0x7e, 0x3c, 0x39, 0xb6, 0x92, 0x7c, 0xf9, 0x39, 0xbf, 0x12, - 0xda, 0xde, 0x74, 0x0e, 0x59, 0xd6, 0x5f, 0xcd, 0x40, 0x7e, 0xb7, 0xb7, 0xb7, 0xc5, 0xd6, 0xa1, - 0xe8, 0xb8, 0x7d, 0x6f, 0x24, 0x04, 0x2f, 0xea, 0x73, 0xf4, 0x7d, 0xed, 0x02, 0xbb, 0x05, 0x25, - 0x94, 0xd7, 0x84, 0x6a, 0x2b, 0x45, 0x9f, 0xa2, 0x00, 0xec, 0x79, 0xfd, 0x17, 0x42, 0xa7, 0xe6, - 0x97, 0x63, 0xc7, 0x47, 0xad, 0x59, 0x29, 0xc3, 0x79, 0xda, 0xeb, 0xe3, 0x04, 0xd2, 0x88, 0x8d, - 0x7f, 0x5d, 0x84, 0x79, 0xb9, 0xdb, 0xd2, 0xce, 0x1d, 0x3a, 0xe7, 0x3c, 0xde, 0xb9, 0xc5, 0x97, - 0x90, 0x07, 0x7c, 0x3e, 0xf2, 0xc2, 0x48, 0x60, 0xa3, 0x39, 0xa8, 0x10, 0x50, 0x8a, 0x6c, 0x9a, - 0xd0, 0x40, 0x26, 0x86, 0x1c, 0x21, 0xf5, 0xf5, 0xad, 0xfc, 0x16, 0xcc, 0xab, 0xbd, 0x3f, 0x1f, - 0xe9, 0x34, 0x73, 0x7d, 0x92, 0xd6, 0xd6, 0xa1, 0xd8, 0xb7, 0xc7, 0x76, 0xdf, 0x09, 0xaf, 0x24, - 0x43, 0x88, 0xbe, 0x45, 0xe9, 0x43, 0xaf, 0x6f, 0x0f, 0xad, 0x63, 0x7b, 0x68, 0xbb, 0x7d, 0x2e, - 0x75, 0xf7, 0x0a, 0x02, 0x37, 0x09, 0x26, 0xf4, 0x73, 0xd9, 0x4e, 0x85, 0x45, 0x2a, 0xbc, 0x6c, - 0xbd, 0x42, 0x13, 0xc2, 0xa5, 0x37, 0x1a, 0x39, 0x42, 0xcb, 0x20, 0x31, 0x2c, 0x67, 0x96, 0x08, - 0xb2, 0xc3, 0xb1, 0xb7, 0x32, 0xf9, 0x82, 0x86, 0xae, 0x44, 0x55, 0x11, 0xf0, 0x33, 0x32, 0x24, - 0xcc, 0xca, 0x62, 0x39, 0x4d, 0x16, 0x7b, 0x17, 0x16, 0x27, 0x6e, 0xc0, 0xc3, 0x70, 0xc8, 0x07, - 0x51, 0x5b, 0xca, 0x88, 0x54, 0x8f, 0x12, 0x54, 0x73, 0x36, 0x60, 0x89, 0x8c, 0x0e, 0x81, 0x1d, - 0x7a, 0xc1, 0x99, 0x13, 0x58, 0x81, 0xd0, 0x90, 0x48, 0xdd, 0x5d, 0xc4, 0xa4, 0xae, 0x4c, 0xe9, - 0x92, 0x8a, 0xb4, 0x36, 0x85, 0xef, 0xf3, 0x3e, 0x77, 0xce, 0xf9, 0x00, 0xe5, 0xb4, 0x9c, 0xb9, - 0x92, 0xc8, 0x63, 0xca, 0x44, 0x14, 0xba, 0x27, 0x23, 0x6b, 0x32, 0x1e, 0xd8, 0x42, 0x58, 0xa9, - 0x91, 0x30, 0xec, 0x4e, 0x46, 0x47, 0x04, 0x61, 0x8f, 0x41, 0x49, 0x62, 0x52, 0x3e, 0x5c, 0x48, - 0xf0, 0x33, 0x41, 0xac, 0x66, 0x45, 0x62, 0x90, 0xa0, 0x98, 0x90, 0x39, 0xeb, 0x53, 0x32, 0x67, - 0x03, 0xe6, 0xc7, 0xbe, 0x73, 0x6e, 0x87, 0xbc, 0xb1, 0x48, 0x0c, 0x5c, 0x7e, 0x0a, 0xce, 0xe0, - 0xb8, 0x4e, 0xe8, 0xd8, 0xa1, 0xe7, 0x37, 0x18, 0xa6, 0xc5, 0x00, 0xf6, 0x10, 0x16, 0x91, 0x46, - 0x82, 0xd0, 0x0e, 0x27, 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x22, 0x1c, 0x85, - 0x50, 0xf6, 0x4d, 0x58, 0x25, 0xb2, 0xc0, 0x1c, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x87, 0x62, - 0x09, 0x53, 0x05, 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0x4f, 0x61, 0x4d, 0x92, 0xc9, 0x4c, 0xae, - 0x15, 0xcc, 0xb5, 0x4c, 0xc9, 0x53, 0xd9, 0x36, 0x60, 0x51, 0x34, 0xc9, 0xe9, 0x5b, 0x32, 0xb7, - 0x58, 0x09, 0xab, 0xa2, 0xf5, 0xa8, 0x29, 0x2d, 0x50, 0xa2, 0x89, 0x69, 0xcf, 0xf9, 0x15, 0xfb, - 0x2e, 0x2c, 0x10, 0xc9, 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, - 0xa9, 0xc8, 0xec, 0x6b, 0xfd, 0xc4, 0xb7, 0x58, 0x0e, 0x43, 0xe7, 0x84, 0x87, 0xce, 0x88, 0x37, - 0xd6, 0x88, 0xc0, 0xd4, 0xb7, 0x58, 0xa9, 0x93, 0x31, 0xa6, 0x34, 0x88, 0x2f, 0xd0, 0x17, 0xd2, - 0xee, 0xd0, 0x0b, 0xb8, 0x32, 0x51, 0x35, 0x6e, 0xca, 0x45, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, - 0x38, 0x29, 0x3d, 0x91, 0x21, 0xf1, 0x16, 0x12, 0x43, 0x95, 0x74, 0x1f, 0x65, 0x4c, 0x14, 0xbb, - 0xf8, 0x99, 0x7d, 0xa1, 0x38, 0xc8, 0x6d, 0x9c, 0x5f, 0x10, 0x20, 0xc9, 0x3b, 0xfe, 0x30, 0x43, - 0x1b, 0xa2, 0xe4, 0x1f, 0x81, 0xa6, 0xde, 0x11, 0xe7, 0xb0, 0x3c, 0x77, 0x78, 0x25, 0x99, 0x09, - 0x10, 0xe8, 0xc0, 0x1d, 0xe2, 0x6a, 0x76, 0x5c, 0x1d, 0x85, 0x78, 0x6f, 0x45, 0x01, 0x11, 0xe9, - 0x2e, 0x94, 0xc7, 0x93, 0xe3, 0xa1, 0xd3, 0x27, 0x94, 0x1c, 0x95, 0x42, 0x20, 0x44, 0x10, 0xfa, - 0x2d, 0x51, 0x14, 0x61, 0xe4, 0x11, 0xa3, 0x2c, 0x61, 0x88, 0x82, 0xbc, 0x9d, 0xfb, 0xc8, 0x4e, - 0x2a, 0x26, 0xfe, 0x36, 0x36, 0x61, 0x39, 0xd9, 0x68, 0xb9, 0xf1, 0x3c, 0x84, 0xa2, 0xe4, 0x55, - 0xca, 0xf0, 0x51, 0xd3, 0x4c, 0xd1, 0x42, 0x45, 0x8b, 0xd2, 0x8d, 0xdf, 0x2b, 0xc0, 0x92, 0x84, - 0x6e, 0x89, 0xa1, 0xed, 0x4e, 0x46, 0x23, 0xdb, 0x4f, 0x61, 0x82, 0x99, 0x97, 0x33, 0xc1, 0xec, - 0x0c, 0x13, 0x4c, 0x6a, 0xbe, 0xc4, 0x43, 0x93, 0x9a, 0xaf, 0x98, 0x4b, 0x52, 0x46, 0x74, 0x3b, - 0x68, 0x55, 0x82, 0x7b, 0x64, 0x6f, 0x9d, 0x61, 0xd9, 0x85, 0x14, 0x96, 0xad, 0x33, 0xdc, 0xb9, - 0x29, 0x86, 0xfb, 0x26, 0x10, 0xd1, 0xa8, 0xd9, 0x9f, 0x27, 0xfd, 0x04, 0x61, 0xd2, 0x98, 0x7a, - 0x1f, 0x16, 0xa6, 0x79, 0x1c, 0x31, 0xd3, 0x5a, 0x0a, 0x87, 0x73, 0x46, 0x1c, 0x77, 0x2b, 0x0d, - 0xb9, 0x24, 0x39, 0x9c, 0x33, 0xe2, 0x7b, 0x98, 0xa2, 0xf0, 0x5b, 0x00, 0x54, 0x37, 0x2e, 0x1a, - 0xc0, 0x45, 0xf3, 0x4e, 0x72, 0x2e, 0xf4, 0x51, 0xdf, 0x10, 0x1f, 0x13, 0x9f, 0xe3, 0x2a, 0x2a, - 0x61, 0x4e, 0x5c, 0x40, 0x1f, 0x42, 0xcd, 0x1b, 0x73, 0xd7, 0x8a, 0x79, 0x4d, 0x19, 0x8b, 0xaa, - 0xcb, 0xa2, 0xda, 0x0a, 0x6e, 0x56, 0x05, 0x5e, 0xf4, 0xc9, 0xbe, 0x43, 0x83, 0xcc, 0xb5, 0x9c, - 0x95, 0x6b, 0x72, 0xd6, 0x10, 0x31, 0xfa, 0x36, 0xfe, 0x46, 0x06, 0xca, 0x5a, 0x73, 0xd8, 0x0a, - 0x2c, 0x6e, 0x1d, 0x1c, 0x1c, 0xb6, 0xcc, 0x66, 0xaf, 0xfd, 0x69, 0xcb, 0xda, 0xda, 0x3b, 0xe8, - 0xb6, 0xea, 0x37, 0x04, 0x78, 0xef, 0x60, 0xab, 0xb9, 0x67, 0xed, 0x1c, 0x98, 0x5b, 0x0a, 0x9c, - 0x61, 0xab, 0xc0, 0xcc, 0xd6, 0xfe, 0x41, 0xaf, 0x95, 0x80, 0x67, 0x59, 0x1d, 0x2a, 0x9b, 0x66, - 0xab, 0xb9, 0xb5, 0x2b, 0x21, 0x39, 0xb6, 0x0c, 0xf5, 0x9d, 0xa3, 0xce, 0x76, 0xbb, 0xf3, 0xcc, - 0xda, 0x6a, 0x76, 0xb6, 0x5a, 0x7b, 0xad, 0xed, 0x7a, 0x9e, 0x55, 0xa1, 0xd4, 0xdc, 0x6c, 0x76, - 0xb6, 0x0f, 0x3a, 0xad, 0xed, 0x7a, 0xc1, 0xf8, 0xf3, 0x0c, 0xac, 0xe0, 0x40, 0x0d, 0xa6, 0x57, - 0xe8, 0x3d, 0x28, 0xf7, 0x3d, 0x6f, 0x2c, 0xd4, 0xa0, 0x78, 0xbb, 0xd7, 0x41, 0x62, 0xf5, 0x11, - 0x67, 0x3d, 0xf1, 0xfc, 0x3e, 0x97, 0x0b, 0x14, 0x10, 0xb4, 0x23, 0x20, 0x82, 0x40, 0x24, 0x85, - 0x11, 0x06, 0xad, 0xcf, 0x32, 0xc1, 0x08, 0x65, 0x15, 0xe6, 0x8e, 0x7d, 0x6e, 0xf7, 0xcf, 0xe4, - 0xd2, 0x94, 0x5f, 0xec, 0xeb, 0xb1, 0x82, 0xde, 0x17, 0x13, 0x3e, 0xe4, 0x03, 0xa4, 0xcf, 0xa2, - 0xb9, 0x20, 0xe1, 0x5b, 0x12, 0x2c, 0xb6, 0x0a, 0xfb, 0xd8, 0x76, 0x07, 0x9e, 0xcb, 0x07, 0x52, - 0x0f, 0x88, 0x01, 0xc6, 0x21, 0xac, 0x4e, 0xf7, 0x4f, 0x2e, 0xe6, 0x0f, 0xb4, 0xc5, 0x4c, 0x62, - 0xf9, 0xfa, 0xf5, 0x04, 0xa4, 0x2d, 0xec, 0xbf, 0x95, 0x87, 0xbc, 0x10, 0xd3, 0xae, 0x95, 0xe8, - 0x74, 0xb9, 0x3b, 0x37, 0xe3, 0x9b, 0x41, 0x3b, 0x00, 0xed, 0xdf, 0x64, 0x6c, 0x2a, 0x21, 0x04, - 0xf7, 0xed, 0x28, 0xd9, 0xe7, 0xfd, 0x73, 0x69, 0x6d, 0xa2, 0x64, 0x93, 0xf7, 0xcf, 0x51, 0xe1, - 0xb1, 0x43, 0xca, 0x4b, 0x8b, 0x71, 0x3e, 0xb0, 0x43, 0xcc, 0x29, 0x93, 0x30, 0xdf, 0x7c, 0x94, - 0x84, 0xb9, 0x1a, 0x30, 0xef, 0xb8, 0xc7, 0xde, 0xc4, 0x1d, 0xe0, 0xda, 0x2b, 0x9a, 0xea, 0x13, - 0x5d, 0x41, 0xc8, 0x26, 0xc4, 0x2e, 0x41, 0x4b, 0xad, 0x28, 0x00, 0x3d, 0xb1, 0x4f, 0xbc, 0x0f, - 0xa5, 0xe0, 0xca, 0xed, 0xeb, 0x0b, 0x6c, 0x59, 0x8e, 0x8f, 0xe8, 0xfd, 0x46, 0xf7, 0xca, 0xed, - 0xe3, 0x72, 0x2a, 0x06, 0xf2, 0x17, 0x7b, 0x0a, 0xc5, 0xc8, 0x28, 0x4b, 0xec, 0xf1, 0xa6, 0x9e, - 0x43, 0x59, 0x62, 0x49, 0xf7, 0x8d, 0x50, 0xd9, 0x23, 0x98, 0x43, 0xcb, 0x69, 0xd0, 0xa8, 0x60, - 0x26, 0x25, 0x8c, 0x8b, 0x66, 0xa0, 0x17, 0x86, 0x0f, 0xd0, 0x8a, 0x6a, 0x4a, 0xb4, 0xf5, 0xe7, - 0x50, 0x4d, 0x94, 0xa5, 0x6b, 0xb8, 0x55, 0xd2, 0x70, 0xdf, 0xd6, 0x35, 0xdc, 0x98, 0x4d, 0xcb, - 0x6c, 0xba, 0xc6, 0xfb, 0x8b, 0x50, 0x54, 0x5d, 0x11, 0x8b, 0xe8, 0xa8, 0xf3, 0xbc, 0x73, 0xf0, - 0x59, 0xc7, 0xea, 0x7e, 0xde, 0xd9, 0xaa, 0xdf, 0x60, 0x0b, 0x50, 0x6e, 0x6e, 0xe1, 0xba, 0x44, - 0x40, 0x46, 0xa0, 0x1c, 0x36, 0xbb, 0xdd, 0x08, 0x92, 0x35, 0x76, 0xa0, 0x3e, 0xdd, 0x52, 0x41, - 0x93, 0xa1, 0x82, 0x49, 0xbb, 0x72, 0x0c, 0x10, 0xfa, 0x0b, 0x99, 0x8a, 0x49, 0x48, 0xa6, 0x0f, - 0xe3, 0x29, 0xd4, 0xc5, 0xa6, 0x23, 0x86, 0x2a, 0xd0, 0xec, 0xb3, 0x43, 0x21, 0x78, 0xe9, 0xb6, - 0xe5, 0xa2, 0x59, 0x26, 0x18, 0x56, 0x65, 0x7c, 0x00, 0x8b, 0x5a, 0xb6, 0x58, 0xdf, 0x14, 0x1b, - 0xd9, 0xb4, 0xbe, 0x89, 0xda, 0x05, 0xa5, 0x18, 0x6b, 0xb0, 0x22, 0x3e, 0x5b, 0xe7, 0xdc, 0x0d, - 0xbb, 0x93, 0x63, 0x72, 0x08, 0x3a, 0x9e, 0x2b, 0xb4, 0x8e, 0x52, 0x94, 0x72, 0x3d, 0x91, 0x6f, - 0x48, 0xd5, 0x34, 0x8b, 0xa4, 0xb1, 0xae, 0xd5, 0x80, 0x19, 0x37, 0xf0, 0x6f, 0x42, 0x45, 0x2d, - 0x45, 0x20, 0x31, 0xac, 0x87, 0xad, 0x96, 0x69, 0x1d, 0x74, 0xf6, 0xda, 0x1d, 0xc1, 0xed, 0xc4, - 0xb0, 0x22, 0x60, 0x67, 0x07, 0x21, 0x19, 0xa3, 0x0e, 0xb5, 0x67, 0x3c, 0x6c, 0xbb, 0x27, 0x9e, - 0x72, 0x7e, 0xfd, 0x45, 0x01, 0x16, 0x22, 0x50, 0xac, 0xe2, 0x9e, 0x73, 0x3f, 0x70, 0x3c, 0x17, - 0xa5, 0xd5, 0x92, 0xa9, 0x3e, 0xc5, 0xd6, 0xe3, 0x0c, 0xb8, 0x1b, 0x3a, 0xe1, 0x95, 0x95, 0xb0, - 0x87, 0xd5, 0x14, 0x58, 0x6e, 0x71, 0xcb, 0x50, 0xb0, 0x87, 0x8e, 0xad, 0xfc, 0xa8, 0xf4, 0x21, - 0xa0, 0x7d, 0x6f, 0xe8, 0xf9, 0x28, 0x98, 0x96, 0x4c, 0xfa, 0x60, 0x8f, 0x61, 0x59, 0x08, 0xc8, - 0xba, 0x91, 0x12, 0xf9, 0x07, 0x99, 0xe6, 0x98, 0x3b, 0x19, 0x1d, 0xc6, 0x86, 0x4a, 0x91, 0x22, - 0x36, 0x36, 0x91, 0x43, 0x4a, 0x32, 0x51, 0x06, 0xd2, 0xb5, 0x16, 0xdd, 0xc9, 0xa8, 0x89, 0x29, - 0x11, 0xfe, 0x13, 0x58, 0x11, 0xf8, 0x91, 0xec, 0x13, 0xe5, 0x58, 0xc0, 0x1c, 0xa2, 0xb0, 0xb6, - 0x4c, 0x8b, 0xf2, 0xdc, 0x82, 0x12, 0xb5, 0x4a, 0xcc, 0x78, 0x81, 0x64, 0x6c, 0x6c, 0x0a, 0xf7, - 0x83, 0x19, 0x97, 0xe7, 0x1c, 0xed, 0xd2, 0x53, 0x2e, 0x4f, 0xcd, 0x69, 0x5a, 0x9c, 0x76, 0x9a, - 0x3e, 0x81, 0x95, 0x63, 0x41, 0x82, 0x67, 0xdc, 0x1e, 0x70, 0xdf, 0x8a, 0x09, 0x9b, 0x74, 0x89, - 0x25, 0x91, 0xb8, 0x8b, 0x69, 0xd1, 0x3a, 0x10, 0x42, 0x88, 0x60, 0x0b, 0x7c, 0x60, 0x85, 0x9e, - 0x85, 0xb2, 0x09, 0x32, 0x98, 0xa2, 0x59, 0x25, 0x70, 0xcf, 0xdb, 0x12, 0xc0, 0x24, 0xde, 0xa9, - 0x6f, 0x8f, 0xcf, 0xa4, 0xb4, 0x1f, 0xe1, 0x3d, 0x13, 0x40, 0x76, 0x1b, 0xe6, 0x05, 0xc9, 0xbb, - 0x9c, 0x3c, 0x53, 0x24, 0x4f, 0x2b, 0x10, 0x7b, 0x1b, 0xe6, 0xb0, 0x8e, 0xa0, 0x51, 0x47, 0x7a, - 0xaf, 0xc4, 0x8c, 0xdc, 0x71, 0x4d, 0x99, 0x26, 0x24, 0xbd, 0x89, 0xef, 0x10, 0x97, 0x29, 0x99, - 0xf8, 0x9b, 0x7d, 0x4f, 0x63, 0x59, 0x4b, 0x98, 0xf7, 0x6d, 0x99, 0x77, 0x8a, 0xd2, 0xae, 0xe3, - 0x5e, 0x3f, 0x53, 0x66, 0xf4, 0xfd, 0x7c, 0xb1, 0x5c, 0xaf, 0x18, 0x1f, 0x42, 0x81, 0x46, 0x47, - 0x10, 0x21, 0x8e, 0x5d, 0x46, 0x12, 0x21, 0x42, 0x1b, 0x30, 0xef, 0xf2, 0xf0, 0xc2, 0xf3, 0x5f, - 0x28, 0x8b, 0xb1, 0xfc, 0x34, 0x7e, 0x84, 0xa6, 0x8e, 0xc8, 0x1d, 0x4e, 0x5a, 0x9b, 0x20, 0x0f, - 0x9a, 0xde, 0xe0, 0xcc, 0x96, 0xd6, 0x97, 0x22, 0x02, 0xba, 0x67, 0xf6, 0x0c, 0x79, 0x64, 0x67, - 0x3d, 0xe2, 0x6f, 0x43, 0x4d, 0x39, 0xe0, 0x03, 0x6b, 0xc8, 0x4f, 0x42, 0x49, 0xee, 0x15, 0xe9, - 0x7d, 0x0f, 0xf6, 0xf8, 0x49, 0x68, 0xec, 0xc3, 0xa2, 0x24, 0xc8, 0x83, 0x31, 0x57, 0x55, 0x7f, - 0x3b, 0x4d, 0xd8, 0x2d, 0x3f, 0x59, 0x4a, 0x6e, 0xb4, 0x14, 0x58, 0x90, 0x90, 0x80, 0x8d, 0x4f, - 0x80, 0xe9, 0xdb, 0xb0, 0x2c, 0x4f, 0x8a, 0x9c, 0xca, 0xd0, 0xae, 0xfc, 0x55, 0x91, 0x60, 0xeb, - 0x0c, 0xc4, 0xe8, 0x04, 0x93, 0x7e, 0x5f, 0x05, 0x46, 0x14, 0x4d, 0xf5, 0x69, 0xfc, 0x49, 0x06, - 0x96, 0xb0, 0x30, 0x25, 0xac, 0x4b, 0x26, 0xfb, 0x13, 0x37, 0x52, 0xcc, 0x8f, 0x2e, 0xfb, 0xd0, - 0xc7, 0x57, 0x37, 0x6d, 0xe6, 0x67, 0x4c, 0x9b, 0x5f, 0x87, 0xfa, 0x80, 0x0f, 0x1d, 0x8c, 0x91, - 0x51, 0xa2, 0x04, 0x89, 0xe7, 0x0b, 0x0a, 0x2e, 0x55, 0x35, 0xe3, 0xef, 0x65, 0x60, 0x91, 0x24, - 0x15, 0x54, 0x7a, 0xe5, 0x40, 0x7d, 0xac, 0xb4, 0x3c, 0xc9, 0xaa, 0x64, 0x9f, 0xe2, 0x1d, 0x1c, - 0xa1, 0x84, 0xbc, 0x7b, 0x43, 0x6a, 0x7f, 0x12, 0xca, 0x3e, 0x42, 0x05, 0xc3, 0xb5, 0x10, 0x98, - 0x12, 0x73, 0x93, 0x9c, 0x94, 0xdd, 0x1b, 0xa8, 0x7d, 0xb8, 0x08, 0xda, 0x2c, 0x0a, 0xb5, 0x53, - 0x80, 0x8d, 0x1d, 0xa8, 0x26, 0xaa, 0x49, 0xd8, 0x5f, 0x2b, 0x64, 0x7f, 0x9d, 0xf1, 0x71, 0x64, - 0x67, 0x7d, 0x1c, 0x57, 0xb0, 0x64, 0x72, 0x7b, 0x70, 0xb5, 0xe3, 0xf9, 0x87, 0xc1, 0x71, 0xb8, - 0x43, 0xe2, 0x9f, 0xe0, 0xef, 0x91, 0xe3, 0x2e, 0x61, 0xe4, 0x54, 0xfe, 0x1b, 0xa5, 0xcb, 0x7e, - 0x0d, 0x6a, 0xb1, 0x87, 0x4f, 0x33, 0x94, 0x55, 0x23, 0x27, 0x1f, 0xda, 0xcb, 0x84, 0x1e, 0x18, - 0x1c, 0x87, 0xd2, 0x54, 0x86, 0xbf, 0x8d, 0xbf, 0x96, 0x07, 0x26, 0xa8, 0x79, 0x8a, 0x60, 0xa6, - 0x7c, 0x93, 0xd9, 0x19, 0xdf, 0xe4, 0x63, 0x60, 0x1a, 0x82, 0x72, 0x99, 0xe6, 0x22, 0x97, 0x69, - 0x3d, 0xc6, 0x95, 0x1e, 0xd3, 0xc7, 0xb0, 0x2c, 0x65, 0xe9, 0x64, 0x53, 0x89, 0x34, 0x18, 0x09, - 0xd5, 0x89, 0xf6, 0x2a, 0xbf, 0xa4, 0xd0, 0xcd, 0xc9, 0x14, 0x86, 0x7e, 0x49, 0xa5, 0x95, 0x6b, - 0x04, 0x38, 0xf7, 0x4a, 0x02, 0x9c, 0x9f, 0x21, 0x40, 0xcd, 0x32, 0x53, 0x4c, 0x5a, 0x66, 0x0c, - 0xa8, 0x2a, 0xef, 0x23, 0x05, 0x5d, 0x90, 0xe0, 0x58, 0x96, 0x2e, 0x48, 0x0c, 0xbc, 0x78, 0x00, - 0x75, 0x65, 0x3e, 0x89, 0x6c, 0x3f, 0x14, 0x50, 0x20, 0xad, 0x6f, 0x5b, 0xca, 0x02, 0x94, 0xb0, - 0xb4, 0x97, 0xa7, 0x2c, 0xed, 0xef, 0xc2, 0x62, 0x20, 0xe8, 0xd7, 0x9a, 0xb8, 0x32, 0xfa, 0x87, - 0x0f, 0x50, 0xcd, 0x2a, 0x9a, 0x75, 0x4c, 0x38, 0x8a, 0xe1, 0xb3, 0x76, 0x8d, 0x6a, 0x8a, 0x5d, - 0xe3, 0x69, 0xec, 0xa8, 0x0b, 0xce, 0x9c, 0x11, 0xca, 0x0c, 0x71, 0xa4, 0x8c, 0x1c, 0xe0, 0xee, - 0x99, 0x33, 0x32, 0x95, 0x57, 0x58, 0x7c, 0x18, 0xff, 0x3b, 0x03, 0x75, 0x41, 0x07, 0x89, 0x25, - 0xf6, 0x1d, 0x40, 0x66, 0xf0, 0x9a, 0x2b, 0xac, 0x2c, 0x70, 0xd5, 0x02, 0xfb, 0x10, 0x70, 0xc5, - 0x58, 0x42, 0xa7, 0x94, 0xeb, 0xab, 0x91, 0x5c, 0x5f, 0x31, 0x0f, 0xdd, 0xbd, 0x41, 0xba, 0x87, - 0x80, 0xb0, 0xef, 0x40, 0x49, 0x10, 0x26, 0x52, 0x89, 0x0c, 0xd0, 0x52, 0x92, 0x57, 0xca, 0x1a, - 0x11, 0x59, 0xc7, 0xf2, 0x33, 0xcd, 0xb7, 0x9a, 0x4f, 0xf1, 0xad, 0x6a, 0x0b, 0x78, 0x17, 0xe0, - 0x39, 0xbf, 0xda, 0xf3, 0xfa, 0xa8, 0xf1, 0xde, 0x01, 0x10, 0xb4, 0x7c, 0x62, 0x8f, 0x1c, 0x69, - 0xb0, 0x29, 0x98, 0xa5, 0x17, 0xfc, 0x6a, 0x07, 0x01, 0x62, 0x22, 0x45, 0x72, 0xbc, 0x8a, 0x0b, - 0x66, 0xf1, 0x05, 0xbf, 0xa2, 0x25, 0x6c, 0x41, 0xf5, 0x39, 0xbf, 0xda, 0xe6, 0x24, 0x64, 0x7a, - 0xbe, 0x20, 0x22, 0xdf, 0xbe, 0x10, 0x52, 0x65, 0xc2, 0x2f, 0x5a, 0xf6, 0xed, 0x8b, 0xe7, 0xfc, - 0x4a, 0xf9, 0x68, 0xe7, 0x45, 0xfa, 0xd0, 0xeb, 0xcb, 0x7d, 0x53, 0x45, 0x78, 0xc4, 0x8d, 0x32, - 0xe7, 0x5e, 0xe0, 0x6f, 0xe3, 0x2f, 0x33, 0x50, 0x15, 0xed, 0x47, 0xb6, 0x2c, 0xa6, 0x4c, 0x05, - 0x0a, 0x65, 0xe2, 0x40, 0xa1, 0x27, 0x92, 0xab, 0x11, 0x8f, 0xcf, 0x5e, 0xcf, 0xe3, 0x71, 0x6e, - 0x88, 0xc1, 0xbf, 0x0f, 0x25, 0x5a, 0x96, 0x62, 0x9d, 0xe7, 0x12, 0x13, 0x9c, 0xe8, 0x90, 0x59, - 0x44, 0xb4, 0xe7, 0x14, 0x97, 0xa0, 0x19, 0xff, 0x68, 0x88, 0x4b, 0x7e, 0x64, 0xf2, 0x4b, 0x99, - 0x86, 0xc2, 0x35, 0x71, 0x09, 0xba, 0x65, 0x6d, 0x6e, 0xc6, 0xb2, 0x76, 0x00, 0x45, 0x31, 0xd5, - 0xd8, 0xd9, 0x94, 0x42, 0x33, 0x69, 0x85, 0x0a, 0x49, 0xc0, 0x16, 0x9b, 0x82, 0x60, 0x74, 0x59, - 0x29, 0x09, 0xd8, 0x01, 0x3f, 0x44, 0x66, 0x97, 0x81, 0xb2, 0xb6, 0x02, 0xd0, 0x38, 0x19, 0x8d, - 0x17, 0x2d, 0x97, 0x24, 0x89, 0x27, 0x06, 0x7c, 0xf7, 0x86, 0x59, 0xed, 0x27, 0x66, 0x60, 0x43, - 0xd2, 0x2a, 0xe6, 0xcc, 0x26, 0x62, 0x9a, 0x54, 0xc3, 0x15, 0x81, 0x8a, 0xdf, 0x9b, 0x73, 0x90, - 0x17, 0xa8, 0xc6, 0xc7, 0xb0, 0xa8, 0x35, 0x83, 0xd4, 0xfc, 0xd7, 0xed, 0xa1, 0xf1, 0x2b, 0x51, - 0x66, 0x51, 0x07, 0xb9, 0x8f, 0x54, 0x8c, 0x07, 0x1f, 0x50, 0xc7, 0x65, 0x2c, 0x09, 0x81, 0x04, - 0xda, 0x6b, 0xc7, 0x1d, 0xfc, 0x1a, 0x2c, 0x69, 0xa5, 0xef, 0x38, 0xae, 0x3d, 0x74, 0x7e, 0x84, - 0x1b, 0x7e, 0xe0, 0x9c, 0xba, 0x53, 0xe5, 0x13, 0xe8, 0x2b, 0x95, 0xff, 0xf7, 0xb3, 0xb0, 0x2c, - 0x2b, 0xc0, 0xa8, 0x3d, 0x47, 0x48, 0x71, 0xfb, 0xc1, 0x29, 0xfb, 0x0e, 0x54, 0xc5, 0xd8, 0x58, - 0x3e, 0x3f, 0x75, 0x82, 0x90, 0x2b, 0xb7, 0x55, 0x0a, 0xe3, 0x12, 0x9b, 0xb9, 0x40, 0x35, 0x25, - 0x26, 0xfb, 0x18, 0xca, 0x98, 0x95, 0xcc, 0x28, 0x72, 0x22, 0x1a, 0xb3, 0x19, 0x69, 0xa0, 0x77, - 0x6f, 0x98, 0x10, 0xc4, 0xc3, 0xfe, 0x31, 0x94, 0x71, 0x0e, 0xcf, 0x71, 0x20, 0xa7, 0x58, 0xd5, - 0xcc, 0x40, 0x8b, 0xcc, 0xe3, 0x78, 0xd8, 0x9b, 0x50, 0x25, 0x66, 0x25, 0xc7, 0x49, 0x46, 0x03, - 0xad, 0xcf, 0x66, 0x57, 0x23, 0x29, 0x1a, 0x3f, 0xd6, 0xbe, 0x37, 0x4b, 0x30, 0x1f, 0xfa, 0xce, - 0xe9, 0x29, 0xf7, 0x8d, 0xd5, 0x68, 0x68, 0x04, 0x17, 0xe6, 0xdd, 0x90, 0x8f, 0x85, 0x6c, 0x6e, - 0xfc, 0xdb, 0x0c, 0x94, 0x25, 0x5f, 0xfd, 0x89, 0x7d, 0x65, 0xeb, 0x5a, 0xd8, 0x2b, 0x59, 0x6c, - 0xe2, 0x28, 0xd7, 0xfb, 0xb0, 0x30, 0x12, 0x72, 0xba, 0xd0, 0x23, 0x13, 0x8e, 0xb2, 0x9a, 0x02, - 0x4b, 0x31, 0x79, 0x03, 0x96, 0x50, 0x6a, 0x0e, 0xac, 0xd0, 0x19, 0x5a, 0x2a, 0x51, 0x86, 0x98, - 0x2e, 0x52, 0x52, 0xcf, 0x19, 0xee, 0xcb, 0x04, 0x21, 0x3c, 0x06, 0xa1, 0x7d, 0xca, 0xe5, 0xda, - 0xa6, 0x0f, 0xa3, 0x01, 0xab, 0x53, 0x2a, 0xa4, 0x52, 0x7f, 0xff, 0xcf, 0x22, 0xac, 0xcd, 0x24, - 0x49, 0x35, 0x38, 0x72, 0x10, 0x0d, 0x9d, 0xd1, 0xb1, 0x17, 0x99, 0x4f, 0x33, 0x9a, 0x83, 0x68, - 0x4f, 0xa4, 0x28, 0xf3, 0x29, 0x87, 0x15, 0x45, 0x90, 0x68, 0xff, 0x8c, 0xb4, 0xcc, 0x2c, 0xea, - 0x40, 0xef, 0x27, 0x37, 0xb1, 0xe9, 0xea, 0x14, 0x5c, 0x17, 0x8d, 0x96, 0xc6, 0x33, 0xb0, 0x80, - 0xfd, 0x3a, 0x34, 0x22, 0xba, 0x97, 0x62, 0xbb, 0xa6, 0x32, 0x8b, 0x9a, 0xde, 0x7b, 0x45, 0x4d, - 0x09, 0xdb, 0x1d, 0xca, 0x4e, 0xab, 0x6a, 0xc9, 0x50, 0x81, 0x51, 0x5d, 0xe7, 0xf0, 0x86, 0xaa, - 0x0b, 0xc5, 0xf0, 0xd9, 0x1a, 0xf3, 0xaf, 0xd5, 0x37, 0xb4, 0x4b, 0x26, 0xaa, 0x35, 0x6f, 0xc9, - 0x82, 0xa3, 0x24, 0xbd, 0xde, 0x33, 0x58, 0xbd, 0xb0, 0x9d, 0x50, 0xf5, 0x51, 0xd3, 0xd8, 0x0b, - 0x58, 0xdf, 0x93, 0x57, 0xd4, 0xf7, 0x19, 0x65, 0x4e, 0x28, 0x26, 0xcb, 0x17, 0xb3, 0xc0, 0x60, - 0xfd, 0x1f, 0xe7, 0xa0, 0x96, 0x2c, 0x45, 0x30, 0x16, 0xb9, 0xd9, 0x28, 0x79, 0x53, 0x0a, 0xc1, - 0xd2, 0xb4, 0xdf, 0x21, 0x39, 0x73, 0xd6, 0xe9, 0x90, 0x4d, 0x71, 0x3a, 0xe8, 0xb6, 0xfe, 0xdc, - 0xab, 0x9c, 0xab, 0xf9, 0xd7, 0x72, 0xae, 0x16, 0xd2, 0x9c, 0xab, 0xd7, 0x7b, 0xe4, 0xe6, 0x7e, - 0x22, 0x8f, 0xdc, 0xfc, 0x4b, 0x3d, 0x72, 0x9a, 0x1f, 0xb1, 0x78, 0x8d, 0x85, 0x5e, 0xf3, 0x2c, - 0xa6, 0x78, 0xe4, 0x4a, 0x5f, 0xc1, 0x23, 0xb7, 0xfe, 0x97, 0x19, 0x60, 0xb3, 0xab, 0x83, 0x3d, - 0x23, 0x7f, 0x8e, 0xcb, 0x87, 0x92, 0x73, 0x7f, 0xe3, 0xf5, 0x56, 0x98, 0x22, 0x08, 0x95, 0x9b, - 0x3d, 0x82, 0x25, 0x3d, 0x10, 0x5e, 0xd7, 0xda, 0xab, 0x26, 0xd3, 0x93, 0x62, 0xdb, 0x8e, 0xe6, - 0xc9, 0xce, 0xbf, 0xd2, 0x93, 0x5d, 0x78, 0xa5, 0x27, 0x7b, 0x2e, 0xe9, 0xc9, 0x5e, 0xff, 0x8f, - 0x19, 0x58, 0x4a, 0x21, 0xe2, 0x9f, 0x5d, 0x9f, 0x05, 0xed, 0x25, 0xd8, 0x5a, 0x56, 0xd2, 0x9e, - 0xce, 0xd1, 0xf6, 0xa0, 0x1c, 0x4f, 0x85, 0x3a, 0x28, 0xf2, 0xf0, 0x55, 0xdc, 0x25, 0xce, 0x61, - 0xea, 0xd9, 0xd7, 0x7f, 0x2f, 0x0b, 0x65, 0x2d, 0x51, 0x8c, 0x22, 0x91, 0xac, 0x16, 0x40, 0x44, - 0x92, 0x21, 0xda, 0x1c, 0xee, 0x82, 0x74, 0x6a, 0x50, 0x3a, 0x2d, 0x2e, 0x29, 0x06, 0x22, 0xc2, - 0x06, 0x2c, 0x29, 0x5f, 0x1b, 0x8f, 0xe3, 0x04, 0xe5, 0x5e, 0xb3, 0x28, 0x3d, 0x6e, 0x3c, 0x0a, - 0x3b, 0x64, 0x8f, 0x94, 0x3a, 0x18, 0xcf, 0x1d, 0x92, 0x3a, 0x79, 0x0c, 0x16, 0x69, 0x81, 0xa8, - 0x49, 0x14, 0x74, 0xfe, 0x3e, 0xac, 0xa8, 0xe5, 0x91, 0xcc, 0x41, 0x4e, 0x04, 0x26, 0x17, 0x87, - 0x9e, 0xe5, 0x7b, 0x70, 0x67, 0xaa, 0x4d, 0x53, 0x59, 0x29, 0xa0, 0xf5, 0x66, 0xa2, 0x75, 0x7a, - 0x09, 0xeb, 0x3f, 0x86, 0x6a, 0x82, 0x51, 0xfe, 0xec, 0xa6, 0x7c, 0xda, 0xce, 0x43, 0x23, 0xaa, - 0xdb, 0x79, 0xd6, 0xff, 0x57, 0x0e, 0xd8, 0x2c, 0xaf, 0xfe, 0x79, 0x36, 0x61, 0x96, 0x30, 0x73, - 0x29, 0x84, 0xf9, 0xff, 0x4c, 0x7e, 0x78, 0x17, 0x16, 0xe5, 0x81, 0x29, 0xcd, 0x61, 0x4a, 0x8b, - 0xb3, 0x1e, 0x25, 0xa8, 0x56, 0x7c, 0x38, 0x1d, 0xb8, 0x51, 0x4c, 0x9c, 0x11, 0xd1, 0x04, 0xa8, - 0xa9, 0xf8, 0x8d, 0x23, 0x98, 0xb3, 0xdd, 0xfe, 0x99, 0xe7, 0x4b, 0x3e, 0xf8, 0x0b, 0x5f, 0x79, - 0xfb, 0xdc, 0x68, 0x62, 0x7e, 0x94, 0xda, 0x4c, 0x59, 0x98, 0xf1, 0x3e, 0x94, 0x35, 0x30, 0x2b, - 0x41, 0x61, 0xaf, 0xbd, 0xbf, 0x79, 0x50, 0xbf, 0xc1, 0xaa, 0x50, 0x32, 0x5b, 0x5b, 0x07, 0x9f, - 0xb6, 0xcc, 0xd6, 0x76, 0x3d, 0xc3, 0x8a, 0x90, 0xdf, 0x3b, 0xe8, 0xf6, 0xea, 0x59, 0x63, 0x1d, - 0x1a, 0xb2, 0xc4, 0x59, 0x9f, 0xc5, 0x6f, 0xe5, 0x23, 0x73, 0x21, 0x26, 0x4a, 0x15, 0xfd, 0x9b, - 0x50, 0xd1, 0xc5, 0x1b, 0x49, 0x11, 0x53, 0x3e, 0x7b, 0xa1, 0x9c, 0x7b, 0x1a, 0xaf, 0xde, 0x02, - 0xf2, 0xd8, 0x0e, 0xa2, 0x6c, 0xd9, 0x84, 0xdc, 0x9a, 0xe2, 0x1d, 0x44, 0xe5, 0x27, 0x41, 0x86, - 0xff, 0x1f, 0xd4, 0x92, 0x06, 0x7c, 0xc9, 0x91, 0xd2, 0x14, 0x4e, 0x91, 0x3b, 0x61, 0xd1, 0x67, - 0xdf, 0x83, 0xfa, 0xb4, 0x03, 0x40, 0x0a, 0xcf, 0xd7, 0xe4, 0x5f, 0x70, 0x92, 0x3e, 0x01, 0xb6, - 0x0b, 0xcb, 0x69, 0x02, 0x1e, 0xd2, 0xc7, 0xf5, 0x46, 0x0a, 0x36, 0x2b, 0xc4, 0xb1, 0x6f, 0x4b, - 0x3f, 0x4f, 0x01, 0xa7, 0xff, 0xed, 0x64, 0xfd, 0xda, 0x60, 0x6f, 0xd0, 0x3f, 0xcd, 0xe3, 0x73, - 0x0e, 0x10, 0xc3, 0x58, 0x1d, 0x2a, 0x07, 0x87, 0xad, 0x8e, 0xb5, 0xb5, 0xdb, 0xec, 0x74, 0x5a, - 0x7b, 0xf5, 0x1b, 0x8c, 0x41, 0x0d, 0x7d, 0xd5, 0xdb, 0x11, 0x2c, 0x23, 0x60, 0xd2, 0xdf, 0xa6, - 0x60, 0x59, 0xb6, 0x0c, 0xf5, 0x76, 0x67, 0x0a, 0x9a, 0x63, 0x0d, 0x58, 0x3e, 0x6c, 0x91, 0x7b, - 0x3b, 0x51, 0x6e, 0x5e, 0x28, 0x0d, 0xb2, 0xbb, 0x42, 0x69, 0xa0, 0x83, 0x7f, 0x72, 0x1d, 0x28, - 0x59, 0xfa, 0xb7, 0x33, 0xb0, 0x32, 0x95, 0x10, 0x1f, 0xe7, 0x20, 0x49, 0x3a, 0x29, 0x43, 0x57, - 0x10, 0xa8, 0x56, 0xd3, 0xbb, 0xb0, 0x18, 0x19, 0x9e, 0xa6, 0x76, 0xa5, 0x7a, 0x94, 0xa0, 0x90, - 0x1f, 0xc1, 0x92, 0x66, 0xbf, 0x9a, 0xe2, 0x15, 0x4c, 0x4b, 0x92, 0x19, 0x8c, 0xb5, 0x28, 0x6c, - 0x7e, 0xaa, 0xd5, 0x03, 0x3a, 0x4d, 0xa8, 0x27, 0xc4, 0x6e, 0xb0, 0x64, 0x7b, 0xd5, 0x27, 0x7b, - 0x3c, 0x45, 0x08, 0xc9, 0xd6, 0xea, 0x13, 0xae, 0xaa, 0xff, 0xfd, 0x39, 0x60, 0x9f, 0x4c, 0xb8, - 0x7f, 0x85, 0xc7, 0x35, 0x82, 0x57, 0xc5, 0x2f, 0x2a, 0x4b, 0x4b, 0xf6, 0xb5, 0x8e, 0x64, 0xa5, - 0x1d, 0x89, 0xca, 0xbf, 0xfa, 0x48, 0x54, 0xe1, 0x55, 0x47, 0xa2, 0xde, 0x82, 0xaa, 0x73, 0xea, - 0x7a, 0x82, 0x15, 0x0a, 0x49, 0x38, 0x68, 0xcc, 0xdd, 0xcb, 0x3d, 0xa8, 0x98, 0x15, 0x09, 0x14, - 0x72, 0x70, 0xc0, 0x3e, 0x8e, 0x91, 0xf8, 0xe0, 0x14, 0x8f, 0xef, 0xe9, 0x4c, 0xb0, 0x35, 0x38, - 0xe5, 0xd2, 0xb0, 0x84, 0x9a, 0x86, 0xca, 0x2c, 0xe0, 0x01, 0x7b, 0x1b, 0x6a, 0x81, 0x37, 0x11, - 0x8a, 0x85, 0x1a, 0x06, 0x72, 0x94, 0x55, 0x08, 0x7a, 0xa8, 0xbc, 0xa2, 0x4b, 0x93, 0x80, 0x5b, - 0x23, 0x27, 0x08, 0x84, 0x78, 0xd6, 0xf7, 0xdc, 0xd0, 0xf7, 0x86, 0xd2, 0xf7, 0xb5, 0x38, 0x09, - 0xf8, 0x3e, 0xa5, 0x6c, 0x51, 0x02, 0xfb, 0x56, 0xdc, 0xa4, 0xb1, 0xed, 0xf8, 0x41, 0x03, 0xb0, - 0x49, 0xaa, 0xa7, 0x28, 0xbf, 0xdb, 0x8e, 0x1f, 0xb5, 0x45, 0x7c, 0x04, 0x53, 0x47, 0xb5, 0xca, - 0xd3, 0x47, 0xb5, 0x7e, 0x98, 0x7e, 0x54, 0xab, 0x8a, 0x45, 0x3f, 0x96, 0x45, 0xcf, 0x4e, 0xf1, - 0x57, 0x3a, 0xb1, 0x35, 0x7b, 0x02, 0xad, 0xf6, 0x55, 0x4e, 0xa0, 0x2d, 0xa4, 0x9d, 0x40, 0x7b, - 0x1f, 0xca, 0x78, 0x36, 0xc8, 0x3a, 0x73, 0x84, 0x0c, 0x47, 0xbe, 0xbc, 0xba, 0x7e, 0x78, 0x68, - 0xd7, 0x71, 0x43, 0x13, 0x7c, 0xf5, 0x33, 0x98, 0x3d, 0x0c, 0xb6, 0xf8, 0x73, 0x3c, 0x0c, 0x26, - 0xcf, 0x30, 0x6d, 0x40, 0x51, 0xcd, 0x13, 0x63, 0x90, 0x3f, 0xf1, 0xbd, 0x91, 0xf2, 0x71, 0x88, - 0xdf, 0xac, 0x06, 0xd9, 0xd0, 0x93, 0x99, 0xb3, 0xa1, 0x67, 0xfc, 0x2a, 0x94, 0x35, 0x52, 0x63, - 0x6f, 0x92, 0x5d, 0x52, 0xe8, 0x66, 0x52, 0xb6, 0xa4, 0x51, 0x2c, 0x49, 0x68, 0x7b, 0x20, 0xf8, - 0xcd, 0xc0, 0xf1, 0x39, 0x1e, 0xdb, 0xb4, 0x7c, 0x7e, 0xce, 0xfd, 0x40, 0xf9, 0x9c, 0xea, 0x51, - 0x82, 0x49, 0x70, 0xe3, 0xd7, 0x60, 0x29, 0x31, 0xb7, 0x92, 0x45, 0xbc, 0x0d, 0x73, 0x38, 0x6e, - 0x2a, 0x26, 0x20, 0x79, 0x28, 0x4b, 0xa6, 0xe1, 0x79, 0x7c, 0x72, 0x97, 0x59, 0x63, 0xdf, 0x3b, - 0xc6, 0x4a, 0x32, 0x66, 0x59, 0xc2, 0x0e, 0x7d, 0xef, 0xd8, 0xf8, 0xb3, 0x1c, 0xe4, 0x76, 0xbd, - 0xb1, 0x1e, 0xa3, 0x96, 0x99, 0x89, 0x51, 0x93, 0x0a, 0xa7, 0x15, 0x29, 0x94, 0x52, 0x66, 0x47, - 0x47, 0x91, 0x52, 0x2a, 0x1f, 0x40, 0x4d, 0xf0, 0x89, 0xd0, 0x13, 0x1a, 0xfb, 0x85, 0xed, 0x93, - 0x40, 0x9c, 0xa3, 0xc5, 0x67, 0x8f, 0xc2, 0x9e, 0xb7, 0x43, 0x70, 0xb6, 0x0c, 0xb9, 0x48, 0x7d, - 0xc1, 0x64, 0xf1, 0xc9, 0x56, 0x61, 0x0e, 0x83, 0x95, 0xaf, 0xa4, 0xd3, 0x5b, 0x7e, 0xb1, 0x6f, - 0xc0, 0x52, 0xb2, 0x5c, 0x62, 0x45, 0x52, 0x36, 0xd2, 0x0b, 0x46, 0x9e, 0x74, 0x13, 0x04, 0x1f, - 0x21, 0x1c, 0x19, 0x3b, 0x73, 0xc2, 0x39, 0x26, 0x69, 0x4c, 0xaf, 0x98, 0x60, 0x7a, 0x77, 0xa1, - 0x1c, 0x0e, 0xcf, 0xad, 0xb1, 0x7d, 0x35, 0xf4, 0xec, 0x81, 0x5c, 0xdf, 0x10, 0x0e, 0xcf, 0x0f, - 0x09, 0xc2, 0x1e, 0x01, 0x8c, 0xc6, 0x63, 0xb9, 0xf6, 0xd0, 0xf9, 0x11, 0x93, 0xf2, 0xfe, 0xe1, - 0x21, 0x91, 0x9c, 0x59, 0x1a, 0x8d, 0xc7, 0xf4, 0x93, 0x6d, 0x43, 0x2d, 0xf5, 0x68, 0xe5, 0x1d, - 0x15, 0x5b, 0xeb, 0x8d, 0x37, 0x52, 0x16, 0x67, 0xb5, 0xaf, 0xc3, 0xd6, 0xbf, 0x07, 0xec, 0xa7, - 0x3c, 0xe0, 0xd8, 0x83, 0x52, 0xd4, 0x3e, 0xfd, 0x7c, 0x20, 0x46, 0xcb, 0x97, 0x13, 0xe7, 0x03, - 0x9b, 0x83, 0x81, 0x2f, 0xf8, 0x22, 0x6d, 0x98, 0x11, 0xcb, 0x07, 0x6d, 0xc7, 0x6c, 0x12, 0xdf, - 0x37, 0xfe, 0x6b, 0x06, 0x0a, 0x74, 0x58, 0xf1, 0x1d, 0x58, 0x20, 0xfc, 0x28, 0xde, 0x4f, 0xba, - 0xca, 0x69, 0xdf, 0xed, 0xc9, 0x50, 0x3f, 0xb1, 0x2c, 0xb4, 0x83, 0xd6, 0xd9, 0x68, 0xe6, 0xb5, - 0xc3, 0xd6, 0x77, 0xa1, 0x14, 0x55, 0xad, 0x91, 0x4e, 0x51, 0xd5, 0xcc, 0xde, 0x80, 0xfc, 0x99, - 0x37, 0x56, 0x96, 0x1f, 0x88, 0x47, 0xd2, 0x44, 0x78, 0xdc, 0x16, 0x51, 0x07, 0x35, 0x5e, 0x5a, - 0x2c, 0xa2, 0x4a, 0x90, 0x0c, 0x66, 0xfb, 0x38, 0x97, 0xd2, 0xc7, 0x23, 0x58, 0x10, 0x7c, 0x40, - 0x0b, 0x59, 0xb9, 0x7e, 0xd3, 0xfc, 0xba, 0x90, 0xf0, 0xfa, 0xc3, 0xc9, 0x80, 0xeb, 0xb6, 0x37, - 0x8c, 0x6f, 0x93, 0x70, 0x25, 0x59, 0x1b, 0xbf, 0x9f, 0x21, 0xfe, 0x22, 0xca, 0x65, 0x0f, 0x20, - 0x2f, 0xf6, 0xb7, 0x29, 0x4b, 0x7c, 0x74, 0x6c, 0x41, 0xe0, 0x99, 0x88, 0x81, 0xb7, 0x13, 0x4c, - 0x46, 0xc9, 0xd2, 0xab, 0x66, 0xd9, 0x9d, 0x8c, 0x22, 0xd3, 0xd5, 0xd7, 0x54, 0xb7, 0xa6, 0xcc, - 0x3e, 0xd4, 0xfb, 0x68, 0x99, 0x6e, 0x68, 0x81, 0x72, 0xf9, 0xc4, 0x8e, 0xa9, 0xa4, 0xc0, 0xc1, - 0x29, 0xd7, 0x02, 0xe4, 0xfe, 0x28, 0x0b, 0xd5, 0x44, 0x8b, 0x30, 0x52, 0x50, 0x6c, 0x00, 0xe4, - 0x58, 0x92, 0xf3, 0x0d, 0x02, 0x24, 0x05, 0x75, 0x6d, 0x9c, 0xb2, 0x89, 0x71, 0x8a, 0x82, 0x73, - 0x72, 0x7a, 0x70, 0xce, 0x63, 0x28, 0xc5, 0x07, 0xec, 0x93, 0x4d, 0x12, 0xf5, 0xa9, 0xc3, 0x1b, - 0x31, 0x52, 0x1c, 0xce, 0x53, 0xd0, 0xc3, 0x79, 0xbe, 0xab, 0x45, 0x7f, 0xcc, 0x61, 0x31, 0x46, - 0xda, 0x88, 0xfe, 0x5c, 0x62, 0x3f, 0x8c, 0x8f, 0xa1, 0xac, 0x35, 0x5e, 0x8f, 0xf2, 0xc8, 0x24, - 0xa2, 0x3c, 0xa2, 0x63, 0x56, 0xd9, 0xf8, 0x98, 0x95, 0xf1, 0xd7, 0xb3, 0x50, 0x15, 0xeb, 0xcb, - 0x71, 0x4f, 0x0f, 0xbd, 0xa1, 0xd3, 0x47, 0x47, 0x53, 0xb4, 0xc2, 0xa4, 0xa0, 0xa5, 0xd6, 0x99, - 0x5c, 0x62, 0x24, 0x67, 0xe9, 0xa7, 0x49, 0x89, 0x49, 0x47, 0xa7, 0x49, 0x0d, 0xa8, 0x0a, 0xc6, - 0x88, 0x2e, 0xa3, 0xf8, 0xf8, 0xbf, 0x59, 0x3e, 0xe1, 0x7c, 0xd3, 0x0e, 0x88, 0x43, 0x7e, 0x03, - 0x96, 0x04, 0x0e, 0x1e, 0xa4, 0x1b, 0x39, 0xc3, 0xa1, 0x43, 0x98, 0x64, 0x68, 0xaa, 0x9f, 0x70, - 0x6e, 0xda, 0x21, 0xdf, 0x17, 0x09, 0xf2, 0xb6, 0x80, 0xe2, 0xc0, 0x09, 0xec, 0xe3, 0x38, 0x9e, - 0x33, 0xfa, 0x46, 0xcf, 0xb2, 0x7d, 0xa9, 0x79, 0x96, 0xc9, 0x00, 0x51, 0x1e, 0xd9, 0x97, 0x91, - 0x67, 0x79, 0x8a, 0x92, 0xe6, 0xa7, 0x29, 0xc9, 0xf8, 0x37, 0x59, 0x28, 0x6b, 0x64, 0xf9, 0x3a, - 0xbb, 0xeb, 0x9d, 0x19, 0xc7, 0x60, 0x49, 0xf7, 0x01, 0xbe, 0x95, 0xac, 0x12, 0x63, 0x5f, 0xe8, - 0x5e, 0x02, 0x8d, 0x80, 0x6f, 0x41, 0x49, 0xac, 0xba, 0xf7, 0xd1, 0x04, 0x2b, 0x6f, 0xd5, 0x40, - 0xc0, 0xe1, 0xe4, 0x58, 0x25, 0x3e, 0xc1, 0xc4, 0x42, 0x9c, 0xf8, 0x44, 0x24, 0xbe, 0x2c, 0xc2, - 0xfa, 0x43, 0xa8, 0xc8, 0x52, 0x71, 0x4e, 0xb1, 0xbb, 0xf1, 0xaa, 0x4f, 0xcc, 0xb7, 0x59, 0xa6, - 0xea, 0x68, 0xf2, 0x65, 0xc6, 0x27, 0x2a, 0x63, 0xf1, 0x55, 0x19, 0x9f, 0xd0, 0x87, 0xb1, 0x13, - 0x05, 0xad, 0x63, 0xdc, 0x95, 0xe2, 0x63, 0x8f, 0x60, 0x49, 0xb1, 0xab, 0x89, 0x6b, 0xbb, 0xae, - 0x37, 0x71, 0xfb, 0x5c, 0x9d, 0xbf, 0x62, 0x32, 0xe9, 0x28, 0x4e, 0x31, 0x06, 0xd1, 0x01, 0x5d, - 0x8a, 0xdf, 0x7a, 0x08, 0x05, 0x92, 0xcb, 0x49, 0xf8, 0x48, 0x67, 0x5c, 0x84, 0xc2, 0x1e, 0x40, - 0x81, 0xc4, 0xf3, 0xec, 0xb5, 0xcc, 0x86, 0x10, 0x8c, 0x26, 0x30, 0x91, 0x71, 0x9f, 0x87, 0xbe, - 0xd3, 0x0f, 0xe2, 0xa3, 0x5d, 0x05, 0xa1, 0x7f, 0x52, 0x5d, 0xb1, 0xe5, 0x36, 0xc6, 0x44, 0x1d, - 0x95, 0x70, 0xc4, 0xc6, 0xb4, 0x94, 0x28, 0x43, 0x8a, 0x4b, 0x43, 0x58, 0x3d, 0xe6, 0xe1, 0x05, - 0xe7, 0xae, 0x2b, 0x84, 0xa1, 0x3e, 0x77, 0x43, 0xdf, 0x1e, 0x8a, 0x49, 0xa2, 0x1e, 0x3c, 0x9d, - 0x29, 0x35, 0xb6, 0x81, 0x6c, 0xc6, 0x19, 0xb7, 0xa2, 0x7c, 0xc4, 0x3b, 0x56, 0x8e, 0xd3, 0xd2, - 0xd6, 0x7f, 0x05, 0xd6, 0xaf, 0xcf, 0x94, 0x72, 0x80, 0xf3, 0x41, 0x92, 0xab, 0x44, 0x7e, 0xc0, - 0xa1, 0x67, 0x87, 0xd4, 0x1a, 0x9d, 0xb3, 0x74, 0xa0, 0xac, 0xa5, 0xc4, 0x7b, 0x7f, 0x06, 0x85, - 0x3b, 0xfa, 0x10, 0x3b, 0x92, 0xeb, 0xf9, 0x23, 0xf4, 0xbb, 0x0d, 0xac, 0xb8, 0xf4, 0x8c, 0xb9, - 0x10, 0xc3, 0xf1, 0xc4, 0xba, 0xb1, 0x01, 0x0b, 0x28, 0xd9, 0x6b, 0x1b, 0xdd, 0xcb, 0x84, 0x41, - 0x63, 0x19, 0x58, 0x87, 0x78, 0x97, 0x1e, 0xce, 0xf9, 0x9f, 0x72, 0x50, 0xd6, 0xc0, 0x62, 0x37, - 0xc2, 0x00, 0x40, 0x6b, 0xe0, 0xd8, 0x23, 0xae, 0x9c, 0x9c, 0x55, 0xb3, 0x8a, 0xd0, 0x6d, 0x09, - 0x14, 0x7b, 0xb1, 0x7d, 0x7e, 0x6a, 0x79, 0x93, 0xd0, 0x1a, 0xf0, 0x53, 0x9f, 0xab, 0x56, 0x56, - 0xec, 0xf3, 0xd3, 0x83, 0x49, 0xb8, 0x8d, 0x30, 0x81, 0x25, 0x78, 0x89, 0x86, 0x25, 0x63, 0xd6, - 0x46, 0xf6, 0x65, 0x8c, 0x25, 0x03, 0x27, 0x89, 0x32, 0xf3, 0x51, 0xe0, 0x24, 0x69, 0x8b, 0xd3, - 0x1b, 0x68, 0x61, 0x76, 0x03, 0xfd, 0x16, 0xac, 0xd2, 0x06, 0x2a, 0x59, 0xb3, 0x35, 0xb5, 0x92, - 0x97, 0x31, 0x55, 0x76, 0x52, 0x13, 0x7b, 0xeb, 0xa2, 0x07, 0x8a, 0x2d, 0x05, 0xce, 0x8f, 0x88, - 0x91, 0x65, 0x4c, 0xd1, 0x33, 0x59, 0x78, 0xd7, 0xf9, 0x11, 0x17, 0x98, 0x18, 0x1d, 0xa3, 0x63, - 0xca, 0xf3, 0x13, 0x23, 0xc7, 0x9d, 0xc6, 0xb4, 0x2f, 0x93, 0x98, 0x25, 0x89, 0x69, 0x5f, 0xea, - 0x98, 0x4f, 0x61, 0x6d, 0xc4, 0x07, 0x8e, 0x9d, 0x2c, 0xd6, 0x8a, 0x05, 0xb7, 0x65, 0x4a, 0xd6, - 0xf2, 0x74, 0x49, 0x71, 0x17, 0xa3, 0xf1, 0x23, 0x6f, 0x74, 0xec, 0x90, 0xcc, 0x42, 0xf1, 0x3a, - 0x79, 0xb3, 0xe6, 0x4e, 0x46, 0x3f, 0x40, 0xb0, 0xc8, 0x12, 0x18, 0x55, 0x28, 0x77, 0x43, 0x6f, - 0xac, 0xa6, 0xb9, 0x06, 0x15, 0xfa, 0x94, 0x87, 0x1a, 0x6f, 0xc1, 0x4d, 0x64, 0x09, 0x3d, 0x6f, - 0xec, 0x0d, 0xbd, 0xd3, 0xab, 0x84, 0x1d, 0xef, 0xdf, 0x65, 0x60, 0x29, 0x91, 0x2a, 0xd9, 0xeb, - 0xb7, 0x88, 0x9f, 0x45, 0x27, 0xd3, 0x68, 0x0d, 0x2e, 0x6a, 0x6b, 0x90, 0x10, 0x89, 0x99, 0xa9, - 0xd3, 0x6a, 0xcd, 0xf8, 0x46, 0x05, 0x95, 0x91, 0x58, 0x4a, 0x63, 0x96, 0xa5, 0xc8, 0xfc, 0xea, - 0xae, 0x05, 0x55, 0xc4, 0x2f, 0xc8, 0x33, 0x2e, 0x03, 0xd9, 0xe5, 0x5c, 0xf2, 0xa0, 0x80, 0x6e, - 0xf3, 0x53, 0x2d, 0x88, 0x0d, 0x81, 0x81, 0xf1, 0x4f, 0x32, 0x00, 0x71, 0xeb, 0xf0, 0xa8, 0x42, - 0x24, 0xb7, 0xd0, 0x65, 0x65, 0x9a, 0x8c, 0xf2, 0x26, 0x54, 0xa2, 0x88, 0xe5, 0x58, 0x12, 0x2a, - 0x2b, 0x98, 0x10, 0x87, 0xee, 0xc3, 0xc2, 0xe9, 0xd0, 0x3b, 0x46, 0x89, 0x55, 0xca, 0x2d, 0x14, - 0xaf, 0x56, 0x23, 0xb0, 0x92, 0x46, 0x62, 0xb9, 0x29, 0x9f, 0x1a, 0xd4, 0xac, 0x4b, 0x41, 0xc6, - 0x6f, 0x66, 0xa3, 0xd0, 0xcd, 0x78, 0x24, 0x5e, 0xae, 0xde, 0xfd, 0x24, 0xb1, 0x34, 0x2f, 0x73, - 0x2f, 0x7e, 0x0c, 0x35, 0x9f, 0x36, 0x25, 0xb5, 0x63, 0xe5, 0x5f, 0xb2, 0x63, 0x55, 0xfd, 0x84, - 0xa4, 0xf3, 0x75, 0xa8, 0xdb, 0x83, 0x73, 0xee, 0x87, 0x0e, 0x5a, 0xeb, 0x51, 0x3e, 0x96, 0xc1, - 0x92, 0x1a, 0x1c, 0x05, 0xd1, 0xfb, 0xb0, 0x20, 0x0f, 0xda, 0x46, 0x98, 0xf2, 0xea, 0x9e, 0x18, - 0x2c, 0x10, 0x8d, 0x7f, 0xae, 0x62, 0x45, 0x93, 0xb3, 0xfb, 0xf2, 0x51, 0xd1, 0x7b, 0x98, 0x9d, - 0x75, 0xa0, 0x4a, 0x42, 0x92, 0x4e, 0x00, 0xc9, 0x8f, 0x08, 0x28, 0x5d, 0x00, 0xc9, 0x61, 0xcd, - 0xbf, 0xce, 0xb0, 0x1a, 0xff, 0x21, 0x03, 0xf3, 0xbb, 0xde, 0x78, 0xd7, 0xa1, 0x60, 0x7d, 0x5c, - 0x26, 0x91, 0x8f, 0x6a, 0x4e, 0x7c, 0x62, 0xe0, 0xcf, 0x4b, 0xce, 0x93, 0xa5, 0x8a, 0x79, 0xd5, - 0xa4, 0x98, 0xf7, 0x5d, 0xb8, 0x85, 0x2e, 0x40, 0xdf, 0x1b, 0x7b, 0xbe, 0x58, 0xaa, 0xf6, 0x90, - 0xc4, 0x3d, 0xcf, 0x0d, 0xcf, 0x14, 0xef, 0xbc, 0x79, 0xc2, 0xf9, 0xa1, 0x86, 0xb1, 0x1f, 0x21, - 0xe0, 0x89, 0xcd, 0x61, 0x78, 0x6e, 0x91, 0x86, 0x2e, 0xe5, 0x51, 0xe2, 0xa8, 0x0b, 0x22, 0xa1, - 0x85, 0x70, 0x94, 0x48, 0x8d, 0x6f, 0x43, 0x29, 0x32, 0xf6, 0xb0, 0x77, 0xa1, 0x74, 0xe6, 0x8d, - 0xa5, 0x45, 0x28, 0x93, 0x38, 0x73, 0x27, 0x7b, 0x6d, 0x16, 0xcf, 0xe8, 0x47, 0x60, 0xfc, 0xd9, - 0x3c, 0xcc, 0xb7, 0xdd, 0x73, 0xcf, 0xe9, 0x63, 0xb4, 0xe9, 0x88, 0x8f, 0x3c, 0x75, 0xda, 0x5f, - 0xfc, 0xc6, 0xd8, 0xac, 0xf8, 0x02, 0x9e, 0x9c, 0x8c, 0xcd, 0x8a, 0xae, 0xde, 0x59, 0x81, 0x39, - 0x5f, 0xbf, 0x41, 0xa7, 0xe0, 0x63, 0xfc, 0x7b, 0xb4, 0x5f, 0x16, 0xb4, 0xdb, 0x12, 0x44, 0x59, - 0x74, 0xb3, 0x0b, 0x0e, 0x19, 0x9d, 0xbe, 0x2c, 0x21, 0x04, 0x07, 0xec, 0x36, 0xcc, 0xcb, 0x23, - 0x6e, 0x74, 0x26, 0x89, 0x02, 0xd6, 0x25, 0x08, 0xa9, 0xc1, 0xe7, 0xe4, 0xc2, 0x8d, 0x04, 0xd9, - 0x9c, 0x59, 0x51, 0xc0, 0x6d, 0x41, 0x6b, 0x77, 0xa1, 0x4c, 0xf8, 0x84, 0x52, 0x94, 0x41, 0x9a, - 0x08, 0x42, 0x84, 0x94, 0x8b, 0xa8, 0x4a, 0xa9, 0x17, 0x51, 0x61, 0x38, 0x71, 0xc4, 0x65, 0xa9, - 0x8b, 0x40, 0xd7, 0x0f, 0x69, 0x70, 0x75, 0x0b, 0x9b, 0xb4, 0xa9, 0xd0, 0x61, 0x64, 0x65, 0x53, - 0x79, 0x0b, 0xaa, 0x27, 0xf6, 0x70, 0x78, 0x6c, 0xf7, 0x5f, 0x90, 0x29, 0xa0, 0x42, 0xd6, 0x4f, - 0x05, 0x44, 0x5b, 0xc0, 0x5d, 0x28, 0x6b, 0xb3, 0x8c, 0x11, 0x98, 0x79, 0x13, 0xe2, 0xf9, 0x9d, - 0xb6, 0xf0, 0xd5, 0x5e, 0xc3, 0xc2, 0xa7, 0x45, 0xa2, 0x2e, 0x24, 0x23, 0x51, 0x6f, 0x21, 0x37, - 0x95, 0x21, 0x87, 0x75, 0xba, 0xeb, 0xc6, 0x1e, 0x0c, 0x30, 0xe4, 0x90, 0x2e, 0x96, 0xc4, 0xc1, - 0xa3, 0xf4, 0x45, 0xd2, 0x25, 0x08, 0x46, 0x28, 0x77, 0xc8, 0x4c, 0x3d, 0xb6, 0x9d, 0x01, 0x1e, - 0x3a, 0x20, 0xeb, 0xc1, 0xbc, 0x3d, 0x0a, 0x0f, 0x6d, 0x67, 0xc0, 0xee, 0x41, 0x45, 0x25, 0xe3, - 0xee, 0xb8, 0x44, 0xe3, 0x2f, 0x93, 0xc5, 0x9e, 0x68, 0x40, 0x35, 0xc2, 0x18, 0xc5, 0x27, 0x8a, - 0xcb, 0x12, 0x05, 0xe9, 0xe0, 0x7d, 0x8c, 0xf2, 0x09, 0x39, 0x9e, 0x1b, 0xae, 0x3d, 0xb9, 0x15, - 0x05, 0x1f, 0x20, 0x95, 0xaa, 0xff, 0xe4, 0x1c, 0x23, 0x4c, 0x21, 0xdc, 0x91, 0x8f, 0x6e, 0x35, - 0x21, 0xff, 0x4a, 0x54, 0xf4, 0xd1, 0x11, 0x02, 0xfb, 0xb6, 0xa6, 0xbf, 0x36, 0x10, 0xf9, 0xf6, - 0x54, 0xf9, 0xd7, 0x9d, 0xb9, 0xba, 0x03, 0xe0, 0x04, 0x62, 0x97, 0x09, 0xb8, 0x3b, 0xc0, 0x23, - 0xc0, 0x45, 0xb3, 0xe4, 0x04, 0xcf, 0x09, 0xf0, 0xb3, 0x55, 0x6c, 0x9b, 0x50, 0xd1, 0xbb, 0xc9, - 0x8a, 0x90, 0x3f, 0x38, 0x6c, 0x75, 0xea, 0x37, 0x58, 0x19, 0xe6, 0xbb, 0xad, 0x5e, 0x6f, 0x0f, - 0x3d, 0x7d, 0x15, 0x28, 0x46, 0xe7, 0x14, 0xb3, 0xe2, 0xab, 0xb9, 0xb5, 0xd5, 0x3a, 0xec, 0xb5, - 0xb6, 0xeb, 0xb9, 0xef, 0xe7, 0x8b, 0xd9, 0x7a, 0xce, 0xf8, 0xf3, 0x1c, 0x94, 0xb5, 0x51, 0x78, - 0x39, 0x33, 0xbe, 0x03, 0x80, 0x9a, 0x64, 0x1c, 0x91, 0x9a, 0x37, 0x4b, 0x02, 0x42, 0x93, 0xaf, - 0xfb, 0x28, 0x72, 0x74, 0x89, 0x92, 0xf2, 0x51, 0xbc, 0x05, 0x55, 0xba, 0x8f, 0x48, 0xf7, 0xd7, - 0x16, 0xcc, 0x0a, 0x01, 0x25, 0xab, 0xc6, 0x03, 0xcc, 0x88, 0x84, 0xa7, 0xe7, 0xe4, 0xed, 0x24, - 0x04, 0xc2, 0xf3, 0x73, 0x78, 0xf8, 0x31, 0xf0, 0x86, 0xe7, 0x9c, 0x30, 0x48, 0x22, 0x2c, 0x4b, - 0x58, 0x4f, 0x1e, 0xc5, 0x96, 0xfc, 0x50, 0x3b, 0x41, 0x5b, 0x30, 0x2b, 0x04, 0x94, 0x15, 0x7d, - 0x43, 0x11, 0x10, 0x45, 0xaf, 0xac, 0xcd, 0x52, 0x43, 0x82, 0x78, 0xf6, 0x66, 0xcc, 0x88, 0x25, - 0x24, 0x8c, 0xaf, 0xcd, 0xe6, 0x7b, 0xb5, 0x39, 0x91, 0xbd, 0x0b, 0x6c, 0x34, 0x1e, 0x5b, 0x29, - 0x06, 0xbe, 0xbc, 0xb9, 0x30, 0x1a, 0x8f, 0x7b, 0x9a, 0xfd, 0xeb, 0x67, 0x60, 0x7b, 0xfc, 0x02, - 0x58, 0x53, 0x2c, 0x60, 0x6c, 0x62, 0xa4, 0x8a, 0xc5, 0x6c, 0x39, 0xa3, 0xb3, 0xe5, 0x14, 0xee, - 0x97, 0x4d, 0xe5, 0x7e, 0x2f, 0xe3, 0x13, 0xc6, 0x0e, 0x94, 0x0f, 0xb5, 0xdb, 0xce, 0xee, 0x89, - 0x1d, 0x42, 0xdd, 0x73, 0x46, 0x7b, 0x07, 0xd9, 0x14, 0x7d, 0x79, 0xbd, 0x99, 0xd6, 0x9a, 0xac, - 0xd6, 0x1a, 0xe3, 0x1f, 0x65, 0xe8, 0x26, 0x99, 0xa8, 0xf1, 0xf1, 0x05, 0x6b, 0xca, 0xfd, 0x16, - 0x1f, 0x74, 0x2f, 0x2b, 0xb7, 0x9b, 0x3c, 0xa3, 0x8e, 0x4d, 0xb3, 0xbc, 0x93, 0x93, 0x80, 0xab, - 0x18, 0x8f, 0x32, 0xc2, 0x0e, 0x10, 0xa4, 0x84, 0x6f, 0x21, 0xe1, 0x3b, 0x54, 0x7e, 0x20, 0x03, - 0x3b, 0x84, 0xf0, 0xbd, 0x6f, 0x5f, 0xca, 0x5a, 0x03, 0x21, 0x82, 0x48, 0xff, 0x80, 0x3a, 0x0b, - 0x1b, 0x7d, 0x1b, 0xff, 0x40, 0x9e, 0xc5, 0x9f, 0x1e, 0xdf, 0x87, 0x50, 0x8c, 0x4a, 0x4d, 0xee, - 0xb0, 0x0a, 0x33, 0x4a, 0x17, 0xfb, 0x38, 0x1a, 0x43, 0x12, 0x2d, 0xa6, 0xc5, 0x85, 0x3e, 0x9e, - 0xb6, 0xd6, 0xea, 0xf7, 0x80, 0x9d, 0x38, 0xfe, 0x34, 0x32, 0x2d, 0xb6, 0x3a, 0xa6, 0x68, 0xd8, - 0xc6, 0x11, 0x2c, 0x29, 0x2e, 0xa1, 0x69, 0x04, 0xc9, 0xc9, 0xcb, 0xbc, 0x82, 0xc9, 0x67, 0x67, - 0x98, 0xbc, 0xf1, 0x3b, 0x05, 0x98, 0x57, 0x37, 0x07, 0xa6, 0xdd, 0x76, 0x57, 0x4a, 0xde, 0x76, - 0xd7, 0x48, 0xdc, 0x8c, 0x84, 0x53, 0x2f, 0xf7, 0xfb, 0xfb, 0xd3, 0x5b, 0xb6, 0xe6, 0xab, 0x48, - 0x6c, 0xdb, 0xab, 0x90, 0x1f, 0xdb, 0xe1, 0x19, 0xda, 0x25, 0x89, 0x78, 0xf0, 0x5b, 0xf9, 0x30, - 0x0a, 0x49, 0x1f, 0x46, 0xda, 0xcd, 0x80, 0x24, 0x92, 0xce, 0xdc, 0x0c, 0x78, 0x0b, 0x48, 0xbe, - 0xd0, 0x82, 0xde, 0x8a, 0x08, 0x10, 0x7b, 0x51, 0x52, 0x1c, 0x29, 0x4e, 0x8b, 0x23, 0xaf, 0x2d, - 0x2a, 0x7c, 0x0b, 0xe6, 0xe8, 0x56, 0x0d, 0x79, 0xe6, 0x57, 0x6d, 0x28, 0x72, 0x0c, 0xd5, 0x7f, - 0x3a, 0x09, 0x61, 0x4a, 0x5c, 0xfd, 0x9a, 0xad, 0x72, 0xe2, 0x9a, 0x2d, 0xdd, 0xb7, 0x52, 0x49, - 0xfa, 0x56, 0x1e, 0x40, 0x3d, 0x1a, 0x50, 0xb4, 0x54, 0xba, 0x81, 0x3c, 0x51, 0x58, 0x53, 0x70, - 0xc1, 0x25, 0x3b, 0x41, 0xbc, 0x21, 0xd6, 0x12, 0x1b, 0xa2, 0xe0, 0x61, 0xcd, 0x30, 0xe4, 0xa3, - 0x71, 0xa8, 0x36, 0x44, 0xed, 0x32, 0x46, 0xa2, 0x88, 0x05, 0xa4, 0x08, 0x35, 0xed, 0x44, 0x35, - 0x9b, 0x50, 0x3b, 0xb1, 0x9d, 0xe1, 0xc4, 0xe7, 0x96, 0xcf, 0xed, 0xc0, 0x73, 0x91, 0x29, 0xc4, - 0x7b, 0xb3, 0xec, 0xe2, 0x0e, 0xe1, 0x98, 0x88, 0x62, 0x56, 0x4f, 0xf4, 0x4f, 0x3c, 0xdc, 0xa4, - 0x8f, 0x84, 0xd8, 0xca, 0xe4, 0xd1, 0x61, 0x8a, 0x61, 0x69, 0x77, 0xac, 0x9d, 0xbd, 0xf6, 0xb3, - 0xdd, 0x5e, 0x3d, 0x23, 0x3e, 0xbb, 0x47, 0x5b, 0x5b, 0xad, 0xd6, 0x36, 0x6e, 0x6d, 0x00, 0x73, - 0x3b, 0xcd, 0xb6, 0xd8, 0xe6, 0x72, 0xc6, 0x6f, 0x67, 0xa1, 0xac, 0xf5, 0x83, 0x3d, 0x8d, 0x86, - 0x9f, 0xae, 0x7c, 0xba, 0x33, 0xdb, 0xd7, 0x0d, 0xc5, 0xf3, 0xb5, 0xf1, 0x8f, 0x2e, 0x5c, 0xcc, - 0x5e, 0x7b, 0xe1, 0x22, 0x7b, 0x07, 0x16, 0x6c, 0x2a, 0x21, 0x1a, 0x6e, 0x69, 0xee, 0x97, 0x60, - 0x39, 0xda, 0x18, 0x53, 0x1a, 0x6f, 0x5c, 0x02, 0x2f, 0xaf, 0xc2, 0x38, 0xa3, 0xbd, 0x0b, 0x67, - 0x65, 0x5e, 0x8e, 0x89, 0x74, 0xcf, 0x47, 0x22, 0x80, 0x1c, 0x29, 0x95, 0x6c, 0x7c, 0x00, 0x10, - 0xb7, 0x39, 0x39, 0x38, 0x37, 0x92, 0x83, 0x93, 0xd1, 0x06, 0x27, 0x6b, 0xfc, 0x33, 0xc9, 0xb0, - 0xe4, 0x48, 0x47, 0x06, 0xbe, 0x6f, 0x80, 0x32, 0x39, 0x5a, 0x18, 0xda, 0x3d, 0x1e, 0xf2, 0x50, - 0xdd, 0x50, 0xb0, 0x28, 0x53, 0xda, 0x51, 0xc2, 0x0c, 0x83, 0xcd, 0xce, 0x32, 0xd8, 0x37, 0xa1, - 0x22, 0x98, 0xab, 0x24, 0x93, 0x40, 0x32, 0xa9, 0xf2, 0xc8, 0xbe, 0x54, 0x75, 0x27, 0x38, 0x6b, - 0x7e, 0x8a, 0xb3, 0xfe, 0x4e, 0x86, 0x2e, 0x0c, 0x89, 0x1b, 0x1a, 0xb3, 0xd6, 0xa8, 0xcc, 0x24, - 0x6b, 0x95, 0xa8, 0x66, 0x94, 0x7e, 0x0d, 0xbb, 0xcc, 0xa6, 0xb3, 0xcb, 0x74, 0x46, 0x9c, 0x4b, - 0x65, 0xc4, 0xc6, 0x3a, 0x34, 0xb6, 0xb9, 0x18, 0x8a, 0xe6, 0x70, 0x38, 0x35, 0x96, 0xc6, 0x2d, - 0xb8, 0x99, 0x92, 0x26, 0x6d, 0x35, 0x9f, 0xc0, 0x4a, 0x93, 0x6e, 0x52, 0xf8, 0x59, 0x1d, 0x99, - 0x34, 0x1a, 0xb0, 0x3a, 0x5d, 0xa4, 0xac, 0x6c, 0x07, 0x16, 0xb7, 0xf9, 0xf1, 0xe4, 0x74, 0x8f, - 0x9f, 0xc7, 0x15, 0x31, 0xc8, 0x07, 0x67, 0xde, 0x85, 0x9c, 0x5c, 0xfc, 0x8d, 0xc1, 0x98, 0x02, - 0xc7, 0x0a, 0xc6, 0xbc, 0xaf, 0xec, 0xf5, 0x08, 0xe9, 0x8e, 0x79, 0xdf, 0x78, 0x0a, 0x4c, 0x2f, - 0x47, 0xce, 0x84, 0x50, 0xa6, 0x26, 0xc7, 0x56, 0x70, 0x15, 0x84, 0x7c, 0xa4, 0x8e, 0x0a, 0x42, - 0x30, 0x39, 0xee, 0x12, 0xc4, 0xb8, 0x0f, 0x95, 0x43, 0xfb, 0xca, 0xe4, 0x5f, 0xc8, 0x13, 0x79, - 0x6b, 0x30, 0x3f, 0xb6, 0xaf, 0x04, 0xb7, 0x8c, 0x5c, 0x77, 0x98, 0x6c, 0xfc, 0x41, 0x1e, 0xe6, - 0x08, 0x93, 0xdd, 0xa3, 0x2b, 0x8b, 0x1d, 0x17, 0xb9, 0x95, 0xda, 0x4f, 0x34, 0xd0, 0xcc, 0x96, - 0x93, 0x9d, 0xdd, 0x72, 0xa4, 0x9d, 0x51, 0x5d, 0xd5, 0xa4, 0x9c, 0x2c, 0xee, 0x64, 0xa4, 0xee, - 0x67, 0x4a, 0x5e, 0x27, 0x90, 0x8f, 0xaf, 0xa4, 0xa6, 0xb3, 0xd6, 0x49, 0x37, 0x78, 0xac, 0xb2, - 0x51, 0xeb, 0xd4, 0x4e, 0x2a, 0x77, 0x15, 0x1d, 0x94, 0xaa, 0x17, 0xce, 0xab, 0x63, 0xa6, 0x49, - 0xbd, 0x70, 0x46, 0xff, 0x2b, 0xbe, 0x5a, 0xff, 0x23, 0x03, 0xe4, 0x4b, 0xf4, 0x3f, 0x78, 0x0d, - 0xfd, 0xef, 0x35, 0x5c, 0xd0, 0x37, 0xa1, 0x88, 0xe2, 0x91, 0xb6, 0xc9, 0x08, 0xb1, 0x48, 0x6c, - 0x32, 0x1f, 0x6a, 0x1a, 0x12, 0xc5, 0xbf, 0x68, 0x5c, 0xde, 0xe4, 0x5f, 0xfc, 0x7c, 0x5c, 0x7b, - 0x9f, 0xc3, 0xbc, 0x84, 0x0a, 0x82, 0x76, 0xed, 0x91, 0xba, 0xed, 0x0e, 0x7f, 0x8b, 0x61, 0xc3, - 0x2b, 0xba, 0xbe, 0x98, 0x38, 0x3e, 0x1f, 0xa8, 0x6b, 0x8c, 0x1c, 0x5c, 0xa3, 0x02, 0x22, 0x3a, - 0x28, 0xb4, 0x35, 0xd7, 0xbb, 0x70, 0x25, 0xef, 0x99, 0x77, 0x82, 0xe7, 0xe2, 0xd3, 0x60, 0x50, - 0xc7, 0xfb, 0x2e, 0xc7, 0x9e, 0xaf, 0xf6, 0x70, 0xe3, 0x0f, 0x33, 0x50, 0x97, 0xab, 0x2b, 0x4a, - 0xd3, 0x95, 0xa5, 0xc2, 0x75, 0xe1, 0x1a, 0x2f, 0xbf, 0x94, 0xc8, 0x80, 0x2a, 0xda, 0x88, 0xa2, - 0x0d, 0x9d, 0x6c, 0x5c, 0x65, 0x01, 0xdc, 0x91, 0x9b, 0xfa, 0x1b, 0x50, 0x56, 0xa1, 0xe2, 0x23, - 0x67, 0xa8, 0x6e, 0x9f, 0xa7, 0x58, 0xf1, 0x7d, 0x67, 0xa8, 0xe4, 0x01, 0xdf, 0x96, 0xc7, 0x9e, - 0x33, 0x28, 0x0f, 0x98, 0x76, 0xc8, 0x8d, 0x7f, 0x95, 0x81, 0x45, 0xad, 0x2b, 0x72, 0xdd, 0x7e, - 0x04, 0x95, 0xe8, 0xa2, 0x59, 0x1e, 0x09, 0xa8, 0x6b, 0x49, 0x46, 0x13, 0x67, 0x2b, 0xf7, 0x23, - 0x48, 0x20, 0x1a, 0x33, 0xb0, 0xaf, 0x28, 0x9e, 0x79, 0x32, 0x52, 0x3a, 0xe0, 0xc0, 0xbe, 0xda, - 0xe1, 0xbc, 0x3b, 0x19, 0x09, 0x0d, 0xff, 0x82, 0xf3, 0x17, 0x11, 0x02, 0xb1, 0x4f, 0x10, 0x30, - 0x89, 0x61, 0x40, 0x75, 0xe4, 0xb9, 0xe1, 0x59, 0x84, 0x22, 0x85, 0x73, 0x04, 0x12, 0x8e, 0xf1, - 0xa7, 0x59, 0x58, 0x22, 0x4b, 0xa4, 0xb4, 0x00, 0x4b, 0xd6, 0xd5, 0x80, 0x39, 0x32, 0xca, 0x12, - 0xf3, 0xda, 0xbd, 0x61, 0xca, 0x6f, 0xf6, 0xad, 0xd7, 0xb4, 0x9e, 0xaa, 0x93, 0xd5, 0xd7, 0x0c, - 0x7f, 0x6e, 0x76, 0xf8, 0xaf, 0x1f, 0xde, 0x34, 0x7f, 0x70, 0x21, 0xcd, 0x1f, 0xfc, 0x3a, 0x5e, - 0xd8, 0x99, 0x33, 0xc0, 0xf3, 0x12, 0x47, 0x3b, 0x03, 0xfc, 0x14, 0xd6, 0x12, 0x38, 0xc8, 0xad, - 0x9d, 0x13, 0x87, 0xab, 0x6b, 0x68, 0x96, 0x35, 0xec, 0xae, 0x4a, 0xdb, 0x9c, 0x87, 0x42, 0xd0, - 0xf7, 0xc6, 0xdc, 0x58, 0x85, 0xe5, 0xe4, 0xa8, 0xca, 0x6d, 0xe2, 0x77, 0x33, 0xd0, 0x90, 0xd1, - 0x3b, 0x8e, 0x7b, 0xba, 0xeb, 0x04, 0xa1, 0xe7, 0x47, 0x17, 0xb2, 0xde, 0x01, 0x08, 0x42, 0xdb, - 0x97, 0x4a, 0xb9, 0xbc, 0x78, 0x05, 0x21, 0xa8, 0x70, 0xdf, 0x84, 0x22, 0x77, 0x07, 0x94, 0x48, - 0xd4, 0x30, 0xcf, 0xdd, 0x81, 0x52, 0xd7, 0x67, 0xb6, 0xd2, 0x6a, 0x52, 0x48, 0x90, 0xf7, 0x20, - 0x88, 0xd1, 0xe1, 0xe7, 0xb8, 0xa5, 0xe7, 0xa3, 0x7b, 0x10, 0xf6, 0xed, 0x4b, 0x8c, 0x85, 0x0d, - 0x8c, 0xbf, 0x9b, 0x85, 0x85, 0xb8, 0x7d, 0x74, 0x89, 0xca, 0xcb, 0xaf, 0x83, 0xb9, 0x27, 0xc9, - 0xc1, 0x11, 0x6a, 0x8e, 0x66, 0x9f, 0x2d, 0xd2, 0xe2, 0x6c, 0xbb, 0xcc, 0x80, 0xb2, 0xc2, 0xf0, - 0x26, 0xa1, 0x76, 0x2f, 0x62, 0x89, 0x50, 0x0e, 0x26, 0xa1, 0xd0, 0x4b, 0x85, 0x82, 0xee, 0xb8, - 0x52, 0x33, 0x2c, 0xd8, 0xa3, 0xb0, 0x8d, 0xcf, 0x2d, 0x08, 0xb0, 0xc8, 0x46, 0x13, 0x29, 0xb0, - 0x04, 0x7e, 0x9d, 0xd4, 0x11, 0x9a, 0x39, 0x54, 0x45, 0x74, 0x59, 0x9d, 0x6e, 0x9e, 0x8e, 0x64, - 0xf5, 0x37, 0xa0, 0x4c, 0x85, 0xc7, 0x47, 0xbe, 0xf3, 0x66, 0x09, 0x6b, 0xc0, 0x74, 0x69, 0x2b, - 0xf3, 0x26, 0x09, 0x0b, 0x01, 0x50, 0x55, 0x18, 0x1c, 0xf3, 0x37, 0x33, 0x70, 0x33, 0x65, 0xda, - 0xe4, 0x2a, 0xdf, 0x82, 0xc5, 0x93, 0x28, 0x51, 0x8d, 0x2e, 0x2d, 0xf5, 0x55, 0xc5, 0x56, 0x93, - 0x63, 0x6a, 0xd6, 0x4f, 0x92, 0x80, 0x58, 0x37, 0xa5, 0x19, 0x4c, 0x5c, 0x28, 0x80, 0x22, 0x11, - 0x4d, 0x23, 0xa9, 0x85, 0x87, 0xb0, 0xde, 0xba, 0x14, 0x1c, 0x63, 0x4b, 0x7f, 0x2f, 0x44, 0x91, - 0x51, 0xd2, 0x0e, 0x9f, 0x79, 0x2d, 0x3b, 0xfc, 0x80, 0x4e, 0x20, 0x47, 0x65, 0xfd, 0x24, 0x85, - 0xe0, 0x06, 0x2a, 0xf2, 0xd0, 0x7b, 0x27, 0xea, 0x66, 0x81, 0x7e, 0xf4, 0xce, 0x89, 0x11, 0xc0, - 0xc2, 0xfe, 0x64, 0x18, 0x3a, 0xf1, 0xd3, 0x27, 0xec, 0x5b, 0x32, 0x0f, 0xd6, 0xa3, 0x46, 0x2d, - 0xb5, 0x22, 0x88, 0x2a, 0xc2, 0xc1, 0x1a, 0x89, 0x82, 0xac, 0xd9, 0xfa, 0x16, 0x46, 0xc9, 0x1a, - 0x8c, 0x9b, 0xb0, 0x16, 0x7f, 0xd1, 0xb0, 0xa9, 0xad, 0xe6, 0x1f, 0x66, 0x28, 0xf0, 0x3e, 0xf9, - 0x0c, 0x0b, 0x6b, 0xc1, 0x52, 0xe0, 0xb8, 0xa7, 0x43, 0xae, 0x17, 0x1f, 0xc8, 0x41, 0x58, 0x49, - 0xb6, 0x4d, 0x3e, 0xd5, 0x62, 0x2e, 0x52, 0x8e, 0xb8, 0xb4, 0x80, 0x6d, 0x5e, 0xd7, 0xc8, 0x98, - 0x2c, 0xa6, 0x46, 0x63, 0xb6, 0xf1, 0x6d, 0xa8, 0x25, 0x2b, 0x62, 0x1f, 0xca, 0x83, 0xfb, 0x71, - 0xab, 0x72, 0x53, 0xa7, 0x9a, 0x63, 0x82, 0x28, 0xc7, 0x63, 0x1f, 0x18, 0x7f, 0x3b, 0x03, 0x0d, - 0x93, 0x0b, 0xca, 0xd5, 0x5a, 0xa9, 0x68, 0xe6, 0xa3, 0x99, 0x52, 0xaf, 0xef, 0xab, 0xba, 0x0f, - 0x40, 0xb5, 0xe8, 0xbd, 0x6b, 0x27, 0x63, 0xf7, 0xc6, 0x4c, 0x8f, 0x36, 0x8b, 0x30, 0x47, 0x28, - 0xc6, 0x1a, 0xac, 0xc8, 0xf6, 0xa8, 0xb6, 0xc4, 0x4e, 0xd6, 0x44, 0x8d, 0x09, 0x27, 0xeb, 0x3a, - 0x34, 0xe8, 0x84, 0xae, 0xde, 0x09, 0x99, 0x71, 0x1b, 0xd8, 0xbe, 0xdd, 0xb7, 0x7d, 0xcf, 0x73, - 0x0f, 0xb9, 0x2f, 0xc3, 0x98, 0x51, 0xc2, 0x44, 0x1f, 0xa4, 0x12, 0x85, 0xe9, 0x4b, 0xdd, 0x06, - 0xeb, 0xb9, 0x2a, 0x6a, 0x8b, 0xbe, 0x0c, 0x13, 0x96, 0x36, 0xed, 0x17, 0x5c, 0x95, 0xa4, 0x86, - 0xe8, 0x63, 0x28, 0x8f, 0xa3, 0x42, 0xd5, 0xb8, 0xab, 0x8b, 0x45, 0x66, 0xab, 0x35, 0x75, 0x6c, - 0xe3, 0x09, 0x2c, 0x27, 0xcb, 0x94, 0xac, 0x63, 0x1d, 0x8a, 0x23, 0x09, 0x93, 0xad, 0x8b, 0xbe, - 0x8d, 0xdf, 0x2a, 0xc2, 0xbc, 0xd4, 0x46, 0xd9, 0x06, 0xe4, 0xfb, 0x2a, 0x72, 0x2e, 0xbe, 0xaf, - 0x4a, 0xa6, 0xaa, 0xff, 0x5b, 0x18, 0x3f, 0x27, 0xf0, 0xd8, 0xc7, 0x50, 0x4b, 0x3a, 0x8f, 0xa7, - 0xce, 0xff, 0x27, 0xbd, 0xbe, 0xd5, 0xfe, 0x94, 0x9b, 0xb0, 0x14, 0x6f, 0x8e, 0x24, 0x33, 0x14, - 0xcf, 0xb4, 0xdd, 0xd3, 0x73, 0x85, 0xbc, 0x1d, 0x9c, 0xd9, 0xd6, 0x93, 0xa7, 0x1f, 0xc8, 0x0b, - 0x00, 0xca, 0x08, 0xec, 0x9e, 0xd9, 0x4f, 0x9e, 0x7e, 0x30, 0x2d, 0x49, 0xcb, 0xe3, 0xff, 0x9a, - 0x24, 0xbd, 0x0c, 0x05, 0xba, 0xf6, 0x94, 0x42, 0xa0, 0xe8, 0x83, 0x3d, 0x86, 0x65, 0x65, 0xda, - 0x90, 0xc1, 0xea, 0xc4, 0x05, 0x8b, 0x74, 0x3e, 0x50, 0xa6, 0x75, 0x31, 0x89, 0x8c, 0x21, 0xab, - 0x30, 0x77, 0x16, 0xdf, 0x61, 0x5b, 0x35, 0xe5, 0x97, 0xf1, 0xa7, 0x05, 0x28, 0x6b, 0x83, 0xc2, - 0x2a, 0x50, 0x34, 0x5b, 0xdd, 0x96, 0xf9, 0x69, 0x6b, 0xbb, 0x7e, 0x83, 0x3d, 0x80, 0xb7, 0xdb, - 0x9d, 0xad, 0x03, 0xd3, 0x6c, 0x6d, 0xf5, 0xac, 0x03, 0xd3, 0x52, 0xb7, 0xa6, 0x1d, 0x36, 0x3f, - 0xdf, 0x6f, 0x75, 0x7a, 0xd6, 0x76, 0xab, 0xd7, 0x6c, 0xef, 0x75, 0xeb, 0x19, 0x76, 0x1b, 0x1a, - 0x31, 0xa6, 0x4a, 0x6e, 0xee, 0x1f, 0x1c, 0x75, 0x7a, 0xf5, 0x2c, 0xbb, 0x0b, 0xb7, 0x76, 0xda, - 0x9d, 0xe6, 0x9e, 0x15, 0xe3, 0x6c, 0xed, 0xf5, 0x3e, 0xb5, 0x5a, 0xbf, 0x74, 0xd8, 0x36, 0x3f, - 0xaf, 0xe7, 0xd2, 0x10, 0x76, 0x7b, 0x7b, 0x5b, 0xaa, 0x84, 0x3c, 0xbb, 0x09, 0x2b, 0x84, 0x40, - 0x59, 0xac, 0xde, 0xc1, 0x81, 0xd5, 0x3d, 0x38, 0xe8, 0xd4, 0x0b, 0x6c, 0x11, 0xaa, 0xed, 0xce, - 0xa7, 0xcd, 0xbd, 0xf6, 0xb6, 0x65, 0xb6, 0x9a, 0x7b, 0xfb, 0xf5, 0x39, 0xb6, 0x04, 0x0b, 0xd3, - 0x78, 0xf3, 0xa2, 0x08, 0x85, 0x77, 0xd0, 0x69, 0x1f, 0x74, 0xac, 0x4f, 0x5b, 0x66, 0xb7, 0x7d, - 0xd0, 0xa9, 0x17, 0xd9, 0x2a, 0xb0, 0x64, 0xd2, 0xee, 0x7e, 0x73, 0xab, 0x5e, 0x62, 0x2b, 0xb0, - 0x98, 0x84, 0x3f, 0x6f, 0x7d, 0x5e, 0x07, 0xd6, 0x80, 0x65, 0x6a, 0x98, 0xb5, 0xd9, 0xda, 0x3b, - 0xf8, 0xcc, 0xda, 0x6f, 0x77, 0xda, 0xfb, 0x47, 0xfb, 0xf5, 0x32, 0x5e, 0xc6, 0xd8, 0x6a, 0x59, - 0xed, 0x4e, 0xf7, 0x68, 0x67, 0xa7, 0xbd, 0xd5, 0x6e, 0x75, 0x7a, 0xf5, 0x0a, 0xd5, 0x9c, 0xd6, - 0xf1, 0xaa, 0xc8, 0x20, 0x4f, 0xb4, 0x58, 0xdb, 0xed, 0x6e, 0x73, 0x73, 0xaf, 0xb5, 0x5d, 0xaf, - 0xb1, 0x3b, 0x70, 0xb3, 0xd7, 0xda, 0x3f, 0x3c, 0x30, 0x9b, 0xe6, 0xe7, 0xea, 0xc4, 0x8b, 0xb5, - 0xd3, 0x6c, 0xef, 0x1d, 0x99, 0xad, 0xfa, 0x02, 0x7b, 0x13, 0xee, 0x98, 0xad, 0x4f, 0x8e, 0xda, - 0x66, 0x6b, 0xdb, 0xea, 0x1c, 0x6c, 0xb7, 0xac, 0x9d, 0x56, 0xb3, 0x77, 0x64, 0xb6, 0xac, 0xfd, - 0x76, 0xb7, 0xdb, 0xee, 0x3c, 0xab, 0xd7, 0xd9, 0xdb, 0x70, 0x2f, 0x42, 0x89, 0x0a, 0x98, 0xc2, - 0x5a, 0x14, 0xfd, 0x53, 0x53, 0xda, 0x69, 0xfd, 0x52, 0xcf, 0x3a, 0x6c, 0xb5, 0xcc, 0x3a, 0x63, - 0xeb, 0xb0, 0x1a, 0x57, 0x4f, 0x15, 0xc8, 0xba, 0x97, 0x44, 0xda, 0x61, 0xcb, 0xdc, 0x6f, 0x76, - 0xc4, 0x04, 0x27, 0xd2, 0x96, 0x45, 0xb3, 0xe3, 0xb4, 0xe9, 0x66, 0xaf, 0x30, 0x06, 0x35, 0x6d, - 0x56, 0x76, 0x9a, 0x66, 0x7d, 0x95, 0x2d, 0x40, 0x79, 0xff, 0xf0, 0xd0, 0xea, 0xb5, 0xf7, 0x5b, - 0x07, 0x47, 0xbd, 0xfa, 0x1a, 0x5b, 0x81, 0x7a, 0xbb, 0xd3, 0x6b, 0x99, 0x62, 0xae, 0x55, 0xd6, - 0xff, 0x31, 0xcf, 0x96, 0x61, 0x41, 0xb5, 0x54, 0x41, 0xff, 0x62, 0x9e, 0xad, 0x01, 0x3b, 0xea, - 0x98, 0xad, 0xe6, 0xb6, 0x18, 0xb8, 0x28, 0xe1, 0x7f, 0xce, 0x4b, 0x47, 0xd2, 0x1f, 0xe6, 0xa2, - 0xcd, 0x3a, 0x8e, 0xcc, 0x48, 0xde, 0x68, 0x5e, 0xd1, 0x6e, 0x22, 0x7f, 0xd5, 0x5b, 0x23, 0x9a, - 0x6a, 0x95, 0x9b, 0x51, 0xad, 0x66, 0x74, 0xf7, 0xaa, 0x2e, 0xfb, 0xbd, 0x05, 0xd5, 0x11, 0xdd, - 0x6e, 0x2e, 0x6f, 0x31, 0x06, 0x19, 0xa6, 0x44, 0x40, 0xba, 0xc2, 0x78, 0xe6, 0xb1, 0x8d, 0xc2, - 0xec, 0x63, 0x1b, 0x69, 0xf2, 0xfd, 0x5c, 0x9a, 0x7c, 0xff, 0x10, 0x16, 0x89, 0x35, 0x39, 0xae, - 0x33, 0x52, 0x5a, 0x33, 0x49, 0x81, 0x0b, 0xc8, 0xa2, 0x08, 0xae, 0xd4, 0x09, 0xa5, 0x72, 0x48, - 0x16, 0x32, 0x2f, 0xb5, 0x8d, 0x84, 0xa6, 0x41, 0x9c, 0x23, 0xd2, 0x34, 0xa2, 0x1a, 0xec, 0xcb, - 0xb8, 0x86, 0xb2, 0x56, 0x03, 0xc1, 0xb1, 0x86, 0x87, 0xb0, 0xc8, 0x2f, 0x43, 0xdf, 0xb6, 0xbc, - 0xb1, 0xfd, 0xc5, 0x04, 0x3d, 0xdd, 0x36, 0xea, 0xf0, 0x15, 0x73, 0x01, 0x13, 0x0e, 0x10, 0xbe, - 0x6d, 0x87, 0xf6, 0xc3, 0x2f, 0xa1, 0xac, 0xdd, 0x7c, 0xcf, 0xd6, 0x60, 0xe9, 0xb3, 0x76, 0xaf, - 0xd3, 0xea, 0x76, 0xad, 0xc3, 0xa3, 0xcd, 0xe7, 0xad, 0xcf, 0xad, 0xdd, 0x66, 0x77, 0xb7, 0x7e, - 0x43, 0x2c, 0xda, 0x4e, 0xab, 0xdb, 0x6b, 0x6d, 0x27, 0xe0, 0x19, 0xf6, 0x06, 0xac, 0x1f, 0x75, - 0x8e, 0xba, 0xad, 0x6d, 0x2b, 0x2d, 0x5f, 0x56, 0x50, 0xa9, 0x4c, 0x4f, 0xc9, 0x9e, 0x7b, 0xf8, - 0x6b, 0x50, 0x4b, 0x1e, 0xfe, 0x66, 0x00, 0x73, 0x7b, 0xad, 0x67, 0xcd, 0xad, 0xcf, 0xe9, 0xba, - 0xd6, 0x6e, 0xaf, 0xd9, 0x6b, 0x6f, 0x59, 0xf2, 0x7a, 0x56, 0xc1, 0x11, 0x32, 0xac, 0x0c, 0xf3, - 0xcd, 0xce, 0xd6, 0xee, 0x81, 0xd9, 0xad, 0x67, 0xd9, 0x6d, 0x58, 0x53, 0xb4, 0xba, 0x75, 0xb0, - 0xbf, 0xdf, 0xee, 0x21, 0x33, 0xec, 0x7d, 0x7e, 0x28, 0x48, 0xf3, 0xa1, 0x0d, 0xa5, 0xf8, 0x7e, - 0x59, 0x64, 0x30, 0xed, 0x5e, 0xbb, 0xd9, 0x8b, 0xb9, 0x6b, 0xfd, 0x86, 0xe0, 0x5f, 0x31, 0x18, - 0xaf, 0x87, 0xad, 0x67, 0xe8, 0x7c, 0x9c, 0x02, 0x52, 0xed, 0xf5, 0xac, 0x58, 0x54, 0x31, 0x74, - 0xf3, 0xa0, 0x27, 0xba, 0xf0, 0x1d, 0xa8, 0x25, 0xa3, 0x20, 0x93, 0x66, 0xeb, 0x75, 0x58, 0xdd, - 0x6c, 0xf5, 0x3e, 0x6b, 0xb5, 0x3a, 0x38, 0x3a, 0x5b, 0xad, 0x4e, 0xcf, 0x6c, 0xee, 0xb5, 0x7b, - 0x9f, 0xd7, 0x33, 0x0f, 0x3f, 0x86, 0xfa, 0xb4, 0xcb, 0x31, 0xe1, 0xa3, 0x7d, 0x99, 0x33, 0xf7, - 0xe1, 0x7f, 0xce, 0xc0, 0x72, 0x9a, 0x55, 0x5d, 0xcc, 0xa1, 0x5c, 0x9c, 0x82, 0x45, 0x77, 0x0f, - 0x3a, 0x56, 0xe7, 0x00, 0xef, 0x83, 0x5c, 0x87, 0xd5, 0xa9, 0x04, 0xc5, 0x09, 0x32, 0xec, 0x16, - 0xac, 0xcd, 0x64, 0xb2, 0xcc, 0x83, 0x23, 0xec, 0x76, 0x03, 0x96, 0xa7, 0x12, 0x5b, 0xa6, 0x79, - 0x60, 0xd6, 0x73, 0xec, 0x3d, 0x78, 0x30, 0x95, 0x32, 0xbb, 0x31, 0xa9, 0x7d, 0x2b, 0xcf, 0xee, - 0xc3, 0x5b, 0x33, 0xd8, 0x31, 0xef, 0xb6, 0x36, 0x9b, 0x7b, 0xa2, 0x7b, 0xf5, 0xc2, 0xc3, 0x7f, - 0x9a, 0x03, 0x88, 0x8f, 0x19, 0x89, 0xfa, 0xb7, 0x9b, 0xbd, 0xe6, 0xde, 0x81, 0x20, 0x2f, 0xf3, - 0xa0, 0x27, 0x4a, 0x37, 0x5b, 0x9f, 0xd4, 0x6f, 0xa4, 0xa6, 0x1c, 0x1c, 0x8a, 0x0e, 0xad, 0xc1, - 0x12, 0x4d, 0xd5, 0x9e, 0xe8, 0x46, 0xbb, 0xf3, 0x8c, 0xae, 0x16, 0xc5, 0xdd, 0xef, 0xe8, 0x70, - 0xc7, 0x3c, 0xe8, 0xf4, 0xac, 0xee, 0xee, 0x51, 0x6f, 0x1b, 0x2f, 0x26, 0xdd, 0x32, 0xdb, 0x87, - 0x54, 0x66, 0xfe, 0x65, 0x08, 0xa2, 0xe8, 0x82, 0x58, 0x0b, 0xcf, 0x0e, 0xba, 0xdd, 0xf6, 0xa1, - 0xf5, 0xc9, 0x51, 0xcb, 0x6c, 0xb7, 0xba, 0x98, 0x71, 0x2e, 0x05, 0x2e, 0xf0, 0xe7, 0xc5, 0x9e, - 0xd9, 0xdb, 0xfb, 0x54, 0x6e, 0x6a, 0x02, 0xb5, 0x98, 0x04, 0x09, 0xac, 0x92, 0x98, 0x1d, 0xb1, - 0x2b, 0xa4, 0x94, 0x0c, 0xd7, 0xa4, 0x89, 0x7c, 0x65, 0xb1, 0xdf, 0xcd, 0x2c, 0x12, 0xcc, 0x56, - 0x49, 0x4f, 0x12, 0xb9, 0x70, 0x2b, 0x8c, 0x04, 0x87, 0xed, 0x6d, 0x13, 0x33, 0xd4, 0x66, 0xa0, - 0x02, 0x77, 0x41, 0x10, 0xa1, 0xd8, 0x36, 0x04, 0x4a, 0x5d, 0x7d, 0x88, 0x94, 0xc5, 0x27, 0xbf, - 0x99, 0x83, 0x1a, 0x1d, 0xf9, 0xa4, 0x07, 0x21, 0xb9, 0xcf, 0xf6, 0x61, 0x5e, 0xbe, 0x2c, 0xca, - 0x56, 0xa2, 0x5b, 0x1f, 0xf5, 0xb7, 0x4c, 0xd7, 0x57, 0xa7, 0xc1, 0x52, 0x4c, 0x5e, 0xfa, 0x2b, - 0x7f, 0xf2, 0xdf, 0xff, 0x4e, 0xb6, 0xca, 0xca, 0x8f, 0xce, 0xdf, 0x7f, 0x74, 0xca, 0xdd, 0x40, - 0x94, 0xf1, 0x2b, 0x00, 0xf1, 0x7b, 0x99, 0xac, 0xa1, 0x5d, 0x33, 0x91, 0x78, 0x29, 0x73, 0xfd, - 0x66, 0x4a, 0x8a, 0x2c, 0xf7, 0x26, 0x96, 0xbb, 0x64, 0xd4, 0x44, 0xb9, 0x8e, 0xeb, 0x84, 0xf4, - 0x76, 0xe6, 0x47, 0x99, 0x87, 0x6c, 0x00, 0x15, 0xfd, 0x25, 0x4b, 0xa6, 0x24, 0xd8, 0x94, 0xb7, - 0x38, 0xd7, 0x6f, 0xa5, 0xa6, 0x29, 0xdd, 0x00, 0xeb, 0x58, 0x31, 0xea, 0xa2, 0x8e, 0x09, 0x62, - 0xc4, 0xb5, 0x0c, 0x49, 0x5b, 0x8a, 0x1f, 0xac, 0x64, 0xb7, 0x35, 0x79, 0x77, 0xe6, 0xb9, 0xcc, - 0xf5, 0x3b, 0xd7, 0xa4, 0xca, 0xba, 0xee, 0x60, 0x5d, 0x6b, 0x06, 0x13, 0x75, 0xf5, 0x11, 0x47, - 0x3d, 0x97, 0xf9, 0x51, 0xe6, 0xe1, 0x93, 0x7f, 0xff, 0x75, 0x28, 0x45, 0x21, 0xe0, 0xec, 0xd7, - 0xa1, 0x9a, 0x38, 0x93, 0xcb, 0x54, 0x37, 0xd2, 0x8e, 0xf0, 0xae, 0xdf, 0x4e, 0x4f, 0x94, 0x15, - 0xbf, 0x81, 0x15, 0x37, 0xd8, 0xaa, 0xa8, 0x58, 0x9e, 0x79, 0x7d, 0x84, 0x67, 0xe8, 0xe9, 0x0e, - 0xcd, 0x17, 0x9a, 0x56, 0x48, 0x95, 0xdd, 0x9e, 0xd6, 0xd4, 0x12, 0xb5, 0xdd, 0xb9, 0x26, 0x55, - 0x56, 0x77, 0x1b, 0xab, 0x5b, 0x65, 0xcb, 0x7a, 0x75, 0x2a, 0x72, 0x98, 0x71, 0xbc, 0xb7, 0x56, - 0x7f, 0xcf, 0x91, 0xdd, 0x89, 0x6f, 0x19, 0x4d, 0x79, 0xe7, 0x31, 0x22, 0x91, 0xd9, 0xc7, 0x1e, - 0x8d, 0x06, 0x56, 0xc5, 0x18, 0x4e, 0x9f, 0xfe, 0x9c, 0x23, 0x3b, 0x86, 0xb2, 0xf6, 0x04, 0x12, - 0xbb, 0x79, 0xed, 0x73, 0x4d, 0xeb, 0xeb, 0x69, 0x49, 0x69, 0x5d, 0xd1, 0xcb, 0x7f, 0x74, 0xc2, - 0x39, 0xfb, 0x65, 0x28, 0x45, 0x0f, 0xeb, 0xb0, 0x35, 0xed, 0xa1, 0x23, 0xfd, 0x21, 0xa0, 0xf5, - 0xc6, 0x6c, 0x42, 0x1a, 0xf1, 0xe9, 0xa5, 0x0b, 0xe2, 0xfb, 0x0c, 0xca, 0xda, 0xe3, 0x39, 0x51, - 0x07, 0x66, 0x1f, 0xe8, 0x89, 0x3a, 0x90, 0xf2, 0xd6, 0x8e, 0xb1, 0x88, 0x55, 0x94, 0x59, 0x09, - 0xe9, 0x3b, 0xbc, 0xf4, 0x02, 0xb6, 0x07, 0x2b, 0x52, 0x03, 0x3e, 0xe6, 0x5f, 0x65, 0x1a, 0x52, - 0x9e, 0xd0, 0x7c, 0x9c, 0x61, 0x1f, 0x43, 0x51, 0xbd, 0x91, 0xc4, 0x56, 0xd3, 0xdf, 0x7a, 0x5a, - 0x5f, 0x9b, 0x81, 0x4b, 0x75, 0xf5, 0x73, 0x80, 0xf8, 0xa5, 0x9e, 0x88, 0x49, 0xcc, 0xbc, 0xfc, - 0x13, 0x51, 0xc0, 0xec, 0xb3, 0x3e, 0xc6, 0x2a, 0x76, 0xb0, 0xce, 0x90, 0x49, 0xb8, 0xfc, 0x42, - 0x5d, 0x2e, 0xfe, 0x43, 0x28, 0x6b, 0x8f, 0xf5, 0x44, 0xc3, 0x37, 0xfb, 0xd0, 0x4f, 0x34, 0x7c, - 0x29, 0x6f, 0xfb, 0x18, 0xeb, 0x58, 0xfa, 0xb2, 0xb1, 0x20, 0x4a, 0x17, 0x22, 0xb0, 0x14, 0x45, - 0xc5, 0x04, 0x9d, 0x41, 0x35, 0xf1, 0x22, 0x4f, 0xb4, 0x42, 0xd3, 0xde, 0xfb, 0x89, 0x56, 0x68, - 0xea, 0x23, 0x3e, 0x8a, 0xce, 0x8c, 0x45, 0x51, 0x0f, 0xdd, 0x2f, 0xa6, 0xd5, 0xf4, 0x03, 0x28, - 0x6b, 0xaf, 0xeb, 0x44, 0x7d, 0x99, 0x7d, 0xc8, 0x27, 0xea, 0x4b, 0xda, 0x63, 0x3c, 0xcb, 0x58, - 0x47, 0xcd, 0x40, 0x52, 0xc0, 0xeb, 0x91, 0x45, 0xd9, 0xbf, 0x0e, 0xb5, 0xe4, 0x83, 0x3b, 0xd1, - 0xda, 0x4f, 0x7d, 0xb9, 0x27, 0x5a, 0xfb, 0xd7, 0xbc, 0xd2, 0x23, 0x49, 0xfa, 0xe1, 0x52, 0x54, - 0xc9, 0xa3, 0x1f, 0xcb, 0xc3, 0x6c, 0x5f, 0xb2, 0x4f, 0x04, 0x83, 0x93, 0xb7, 0x73, 0xb3, 0x35, - 0x8d, 0x6a, 0xf5, 0x6b, 0xbe, 0xa3, 0xf5, 0x32, 0x73, 0x91, 0x77, 0x92, 0x98, 0xb1, 0x70, 0xf6, - 0x0c, 0x96, 0x22, 0x62, 0x8e, 0xae, 0xdb, 0x0e, 0xa2, 0x3e, 0xa4, 0x5e, 0xea, 0xbd, 0x5e, 0x9f, - 0x4e, 0x7d, 0x9c, 0xa1, 0xed, 0x0f, 0x2f, 0x39, 0xd6, 0xb6, 0x3f, 0xfd, 0xc6, 0x6d, 0x6d, 0xfb, - 0x4b, 0xdc, 0x85, 0x3c, 0xbd, 0xfd, 0x85, 0x8e, 0x28, 0xc3, 0x85, 0x85, 0xe9, 0xcb, 0xaf, 0xef, - 0x5c, 0x77, 0x59, 0x08, 0x15, 0xff, 0xc6, 0xcb, 0xef, 0x12, 0x49, 0xb2, 0x22, 0xc5, 0x4d, 0x1f, - 0xc9, 0xd8, 0x29, 0xf6, 0xab, 0x50, 0xd1, 0x1f, 0xe9, 0x60, 0x3a, 0x4f, 0x98, 0xae, 0xe9, 0x56, - 0x6a, 0x5a, 0x92, 0x4a, 0x58, 0x45, 0xaf, 0x86, 0x7d, 0x0a, 0xab, 0xd1, 0x30, 0xeb, 0xb7, 0x5d, - 0x04, 0xec, 0x6e, 0xca, 0x1d, 0x18, 0x89, 0xc1, 0xbe, 0x79, 0xed, 0x25, 0x19, 0x8f, 0x33, 0x82, - 0xfa, 0x92, 0x0f, 0x12, 0xc4, 0x3b, 0x4f, 0xda, 0x3b, 0x0c, 0xf1, 0xce, 0x93, 0xfa, 0x8a, 0x81, - 0xa2, 0x3e, 0xb6, 0x94, 0x18, 0x23, 0x8a, 0x2a, 0x67, 0x3f, 0x80, 0x05, 0xed, 0x2a, 0x8f, 0xee, - 0x95, 0xdb, 0x8f, 0x56, 0xd2, 0xec, 0xb5, 0xb6, 0xeb, 0x69, 0x36, 0x63, 0x63, 0x0d, 0xcb, 0x5f, - 0x34, 0x12, 0x83, 0x23, 0x56, 0xd1, 0x16, 0x94, 0xf5, 0x6b, 0x42, 0x5e, 0x52, 0xee, 0x9a, 0x96, - 0xa4, 0xdf, 0xa0, 0xfa, 0x38, 0xc3, 0xf6, 0xa0, 0x3e, 0x7d, 0xa9, 0x5f, 0xc4, 0x53, 0xd2, 0x2e, - 0x42, 0x5c, 0x9f, 0x4a, 0x4c, 0x5c, 0x05, 0xc8, 0x0e, 0xe9, 0x5c, 0x52, 0xf4, 0xde, 0xa4, 0xe7, - 0x4f, 0xef, 0xea, 0xc9, 0x77, 0x28, 0xa3, 0xd2, 0xd2, 0x5e, 0x20, 0x7d, 0x90, 0x79, 0x9c, 0x61, - 0xbf, 0x9d, 0x81, 0x4a, 0xe2, 0x52, 0xab, 0xc4, 0xc9, 0x8f, 0xa9, 0x7e, 0x36, 0xf4, 0x34, 0xbd, - 0xa3, 0x86, 0x89, 0x83, 0xb8, 0xf7, 0xf0, 0xfb, 0x89, 0x49, 0xfa, 0x71, 0xc2, 0xe5, 0xba, 0x31, - 0xfd, 0x20, 0xe5, 0x97, 0xd3, 0x08, 0xfa, 0x45, 0xc9, 0x5f, 0x3e, 0xce, 0xb0, 0x7f, 0x91, 0x81, - 0x5a, 0x32, 0x96, 0x22, 0xea, 0x6e, 0x6a, 0xd4, 0x46, 0x44, 0x4a, 0xd7, 0x04, 0x60, 0xfc, 0x00, - 0x5b, 0xd9, 0x7b, 0x68, 0x26, 0x5a, 0x29, 0x9f, 0xd2, 0xf8, 0xe9, 0x5a, 0xcb, 0x7e, 0x91, 0xde, - 0x7f, 0x56, 0x91, 0x78, 0x6c, 0xf6, 0xbd, 0xe0, 0x88, 0xfc, 0xf4, 0xd7, 0x75, 0x8d, 0xdc, 0x6f, - 0x64, 0x33, 0x38, 0x13, 0x3f, 0xa4, 0xd7, 0x17, 0x55, 0xd0, 0x95, 0x20, 0xe5, 0xd7, 0x2e, 0xe4, - 0x6d, 0xec, 0xd8, 0x1b, 0xc6, 0xcd, 0x44, 0xc7, 0xa6, 0xa5, 0x8f, 0x26, 0x35, 0x51, 0xbe, 0x90, - 0x1b, 0x6f, 0x9f, 0x33, 0xaf, 0xe6, 0xa6, 0x56, 0x82, 0x8d, 0x1c, 0x51, 0x23, 0x25, 0x7a, 0x62, - 0xbd, 0xbd, 0x66, 0x31, 0xc6, 0x43, 0x6c, 0xeb, 0xdb, 0xc6, 0xdd, 0x6b, 0xdb, 0xfa, 0x08, 0x83, - 0x23, 0x44, 0x8b, 0x0f, 0x01, 0xe2, 0x70, 0x59, 0x36, 0x15, 0xb4, 0x19, 0x71, 0xa1, 0xd9, 0x88, - 0xda, 0xe4, 0xa2, 0x56, 0xb1, 0x9d, 0xa2, 0xc4, 0x5f, 0x26, 0x9e, 0x1a, 0x85, 0x93, 0xea, 0x22, - 0x58, 0x32, 0xb2, 0x35, 0x21, 0x82, 0x4d, 0x97, 0x9f, 0xe0, 0xa8, 0x51, 0xec, 0xe8, 0x11, 0x54, - 0xf7, 0x3c, 0xef, 0xc5, 0x64, 0x1c, 0x1d, 0xd1, 0x48, 0xc6, 0x42, 0xed, 0xda, 0xc1, 0xd9, 0xfa, - 0x54, 0x2f, 0x8c, 0x7b, 0x58, 0xd4, 0x3a, 0x6b, 0x68, 0x45, 0x3d, 0xfa, 0x71, 0x1c, 0xa3, 0xfb, - 0x25, 0xb3, 0x61, 0x31, 0x62, 0xd4, 0x71, 0x1c, 0x6c, 0xb2, 0x98, 0x04, 0x7b, 0x9e, 0xae, 0x22, - 0xa1, 0x2b, 0xa8, 0xd6, 0x3e, 0x0a, 0x54, 0x99, 0x8f, 0x33, 0xec, 0x10, 0x2a, 0xdb, 0xbc, 0x8f, - 0x77, 0x7c, 0x60, 0xdc, 0xcf, 0x52, 0x22, 0x86, 0x84, 0x02, 0x86, 0xd6, 0xab, 0x09, 0x60, 0x72, - 0xf3, 0x1a, 0xdb, 0x57, 0x3e, 0xff, 0xe2, 0xd1, 0x8f, 0x65, 0x44, 0xd1, 0x97, 0x6a, 0xf3, 0x8a, - 0xa3, 0xcb, 0x74, 0x09, 0x20, 0x19, 0xa2, 0x95, 0xd8, 0xbc, 0x66, 0x42, 0xb4, 0x12, 0x43, 0x1d, - 0xc5, 0x92, 0x0d, 0x61, 0x71, 0x26, 0xaa, 0x2b, 0xda, 0xb7, 0xae, 0x8b, 0x05, 0x5b, 0xbf, 0x77, - 0x3d, 0x42, 0xb2, 0xb6, 0x87, 0xc9, 0xda, 0xba, 0x50, 0xa5, 0xab, 0x90, 0x8f, 0x39, 0x9d, 0xf6, - 0x9d, 0xba, 0x2a, 0x4b, 0x3f, 0x4a, 0x3c, 0xbd, 0xcb, 0x60, 0x5a, 0x52, 0xcc, 0xc1, 0xf3, 0x9e, - 0xec, 0x04, 0xdf, 0xff, 0xd0, 0x8e, 0xd7, 0x46, 0xc4, 0x38, 0x7b, 0xe4, 0x37, 0x22, 0xc6, 0x94, - 0xd3, 0xb8, 0x4a, 0x07, 0x65, 0x2b, 0x51, 0xd9, 0x8f, 0x5c, 0x6f, 0xc0, 0x47, 0xb2, 0xd4, 0x5f, - 0x86, 0xf2, 0x33, 0x1e, 0xaa, 0xf3, 0xac, 0x91, 0x40, 0x3f, 0x75, 0xc0, 0x75, 0x3d, 0xe5, 0x14, - 0x72, 0x92, 0x36, 0xa9, 0x64, 0x3e, 0x38, 0xe5, 0xc4, 0x09, 0x2d, 0x67, 0xf0, 0x25, 0xfb, 0x25, - 0x2c, 0x3c, 0xba, 0xbd, 0x61, 0x55, 0x6b, 0xa6, 0x5e, 0xf8, 0xc2, 0x14, 0x3c, 0xad, 0x64, 0xd1, - 0x66, 0x4d, 0xb0, 0x74, 0xa1, 0xac, 0xdd, 0xf2, 0x12, 0x8d, 0xcd, 0xec, 0xad, 0x3e, 0xd1, 0xd8, - 0xa4, 0x5c, 0x0a, 0x63, 0x3c, 0xc0, 0x7a, 0x0c, 0x76, 0x2f, 0xae, 0x87, 0x2e, 0x82, 0x89, 0x6b, - 0x7a, 0xf4, 0x63, 0x7b, 0x14, 0x7e, 0xc9, 0x3e, 0xa3, 0xe9, 0xd0, 0xce, 0xeb, 0xc6, 0x1a, 0xca, - 0xf4, 0xd1, 0xde, 0x68, 0xb0, 0xb4, 0xa4, 0xa4, 0xd6, 0x42, 0x55, 0xa1, 0xd8, 0xf8, 0x14, 0xa0, - 0x1b, 0x7a, 0xe3, 0x6d, 0x9b, 0x8f, 0x3c, 0x37, 0xe6, 0xe9, 0xf1, 0x09, 0xd2, 0x98, 0x4f, 0x6a, - 0xc7, 0x48, 0xd9, 0x67, 0x9a, 0x4a, 0x97, 0x38, 0x69, 0xae, 0x88, 0xf8, 0xda, 0x43, 0xa6, 0xd1, - 0x80, 0xa4, 0x1c, 0x34, 0x7d, 0x9c, 0x61, 0x4d, 0x80, 0x38, 0x7c, 0x30, 0x52, 0xd0, 0x66, 0x22, - 0x13, 0x23, 0xf6, 0x9a, 0x12, 0x6b, 0x78, 0x08, 0xa5, 0x38, 0xee, 0x6a, 0x2d, 0xbe, 0xb4, 0x2a, - 0x11, 0xa5, 0x15, 0x89, 0x0b, 0x33, 0x31, 0x4f, 0x46, 0x1d, 0x87, 0x0a, 0x58, 0x51, 0x0c, 0xd5, - 0x09, 0xe7, 0x01, 0x73, 0x60, 0x89, 0x1a, 0x18, 0xc9, 0x66, 0x78, 0xf2, 0x31, 0x7a, 0x75, 0x67, - 0x36, 0xfc, 0x28, 0xe2, 0x1a, 0xa9, 0x41, 0x34, 0x09, 0x3b, 0x93, 0xa0, 0x56, 0x3a, 0x75, 0x29, - 0xb6, 0x80, 0x11, 0x2c, 0xce, 0xc4, 0x69, 0x44, 0xac, 0xe3, 0xba, 0xc0, 0x9b, 0x88, 0x75, 0x5c, - 0x1b, 0xe2, 0x61, 0xac, 0x60, 0x95, 0x0b, 0x06, 0xa0, 0x5e, 0x79, 0xe1, 0x84, 0xfd, 0x33, 0x51, - 0xdd, 0xef, 0x65, 0x60, 0x29, 0x25, 0x12, 0x83, 0xbd, 0xa9, 0x4c, 0x14, 0xd7, 0x46, 0x69, 0xac, - 0xa7, 0x7a, 0xec, 0x8d, 0x2e, 0xd6, 0xb3, 0xcf, 0x9e, 0x27, 0x36, 0x50, 0x72, 0x98, 0xcb, 0x95, - 0xf9, 0x52, 0x09, 0x26, 0x55, 0x7c, 0xf9, 0x02, 0xd6, 0xa8, 0x21, 0xcd, 0xe1, 0x70, 0x2a, 0x9a, - 0xe0, 0x0d, 0xad, 0x15, 0x29, 0x11, 0x12, 0x09, 0x65, 0x20, 0x19, 0x25, 0x71, 0x8d, 0xec, 0x4e, - 0x4d, 0x65, 0x13, 0xa8, 0x4f, 0x7b, 0xe9, 0xd9, 0xf5, 0x65, 0xad, 0xdf, 0x4d, 0x28, 0xdb, 0x29, - 0x9e, 0xfd, 0xaf, 0x61, 0x65, 0x77, 0x8d, 0xf5, 0xb4, 0x71, 0x21, 0xfd, 0x5b, 0xcc, 0xc7, 0xff, - 0x1f, 0x85, 0x14, 0x4c, 0xf5, 0xf3, 0x6e, 0xf4, 0xce, 0x40, 0x7a, 0x00, 0x44, 0xa4, 0xee, 0xa7, - 0x47, 0x24, 0xbc, 0x83, 0xd5, 0xdf, 0x33, 0x6e, 0xa5, 0x55, 0xef, 0x53, 0x16, 0x52, 0xfc, 0xd7, - 0xa6, 0xd7, 0xb5, 0x6a, 0xc1, 0xbd, 0xb4, 0xf9, 0xbe, 0x56, 0xf1, 0x9a, 0x1a, 0xeb, 0x1b, 0x28, - 0x43, 0x56, 0xf4, 0x10, 0x82, 0x68, 0xf9, 0xa4, 0xc4, 0x2a, 0x44, 0xcb, 0x27, 0x2d, 0xe6, 0x20, - 0x29, 0x3f, 0xa9, 0x68, 0x83, 0x8f, 0x32, 0x0f, 0x37, 0xef, 0xff, 0xe0, 0x6b, 0xa7, 0x4e, 0x78, - 0x36, 0x39, 0xde, 0xe8, 0x7b, 0xa3, 0x47, 0x43, 0x65, 0xda, 0x94, 0xd7, 0x03, 0x3c, 0x1a, 0xba, - 0x83, 0x47, 0x58, 0xec, 0xf1, 0xdc, 0xd8, 0xf7, 0x42, 0xef, 0x9b, 0xff, 0x37, 0x00, 0x00, 0xff, - 0xff, 0x40, 0x26, 0x50, 0x15, 0x6f, 0x8b, 0x00, 0x00, + // 12030 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x59, 0x6c, 0x24, 0x49, + 0x76, 0x58, 0xd7, 0x45, 0x56, 0xbd, 0x3a, 0x58, 0x0c, 0x5e, 0xd5, 0xec, 0xe9, 0xe9, 0x9e, 0x9c, + 0xd9, 0xe9, 0x9e, 0x9e, 0x59, 0x76, 0x4f, 0xef, 0xf6, 0xcc, 0xee, 0x8c, 0xb5, 0xda, 0x22, 0x59, + 0x6c, 0xd6, 0x36, 0x59, 0xe4, 0x64, 0x15, 0x67, 0x34, 0xab, 0x23, 0x37, 0x59, 0x15, 0x24, 0x53, + 0x5d, 0x95, 0x59, 0x93, 0x99, 0xc5, 0x63, 0x17, 0xe3, 0x0f, 0xc3, 0x36, 0x04, 0xc1, 0x36, 0x20, + 0xd8, 0x32, 0x60, 0x59, 0x82, 0x0f, 0xc1, 0x36, 0x0c, 0x03, 0x82, 0x00, 0xc9, 0x1f, 0x06, 0xfc, + 0xaf, 0x1f, 0x1f, 0x30, 0x24, 0x7f, 0xd8, 0x10, 0x04, 0x18, 0xb6, 0xd7, 0x7f, 0x86, 0x00, 0x7f, + 0x1b, 0x30, 0xe2, 0xbd, 0x88, 0xcc, 0xc8, 0xaa, 0x64, 0x77, 0xcf, 0xee, 0x7a, 0x7f, 0xc8, 0xca, + 0x17, 0x2f, 0xee, 0x17, 0x2f, 0xde, 0x15, 0x11, 0x50, 0xf2, 0xc7, 0xfd, 0x8d, 0xb1, 0xef, 0x85, + 0x1e, 0x2b, 0x0c, 0x5d, 0x7f, 0xdc, 0x5f, 0x7f, 0xed, 0xd4, 0xf3, 0x4e, 0x87, 0xfc, 0xa1, 0x3d, + 0x76, 0x1e, 0xda, 0xae, 0xeb, 0x85, 0x76, 0xe8, 0x78, 0x6e, 0x40, 0x48, 0xc6, 0x0f, 0xa0, 0xf6, + 0x94, 0xbb, 0x5d, 0xce, 0x07, 0x26, 0xff, 0x62, 0xc2, 0x83, 0x90, 0xbd, 0x0b, 0x8b, 0x36, 0xff, + 0x21, 0xe7, 0x03, 0x6b, 0x6c, 0x07, 0xc1, 0xf8, 0xcc, 0xb7, 0x03, 0xde, 0xc8, 0xdc, 0xcd, 0xdc, + 0xaf, 0x98, 0x75, 0x4a, 0x38, 0x8c, 0xe0, 0xec, 0x0d, 0xa8, 0x04, 0x02, 0x95, 0xbb, 0xa1, 0xef, + 0x8d, 0xaf, 0x1a, 0x59, 0xc4, 0x2b, 0x0b, 0x58, 0x8b, 0x40, 0xc6, 0x10, 0x16, 0xa2, 0x1a, 0x82, + 0xb1, 0xe7, 0x06, 0x9c, 0x3d, 0x82, 0xe5, 0xbe, 0x33, 0x3e, 0xe3, 0xbe, 0x85, 0x99, 0x47, 0x2e, + 0x1f, 0x79, 0xae, 0xd3, 0x6f, 0x64, 0xee, 0xe6, 0xee, 0x97, 0x4c, 0x46, 0x69, 0x22, 0xc7, 0xbe, + 0x4c, 0x61, 0xf7, 0x60, 0x81, 0xbb, 0x04, 0xe7, 0x03, 0xcc, 0x25, 0xab, 0xaa, 0xc5, 0x60, 0x91, + 0xc1, 0xf8, 0x8d, 0x2c, 0x2c, 0xb6, 0x5d, 0x27, 0xfc, 0xcc, 0x1e, 0x0e, 0x79, 0xa8, 0xfa, 0x74, + 0x0f, 0x16, 0x2e, 0x10, 0x80, 0x7d, 0xba, 0xf0, 0xfc, 0x81, 0xec, 0x51, 0x8d, 0xc0, 0x87, 0x12, + 0x7a, 0x6d, 0xcb, 0xb2, 0xd7, 0xb6, 0x2c, 0x75, 0xb8, 0x72, 0xd7, 0x0c, 0xd7, 0x3d, 0x58, 0xf0, + 0x79, 0xdf, 0x3b, 0xe7, 0xfe, 0x95, 0x75, 0xe1, 0xb8, 0x03, 0xef, 0xa2, 0x91, 0xbf, 0x9b, 0xb9, + 0x5f, 0x30, 0x6b, 0x0a, 0xfc, 0x19, 0x42, 0xd9, 0x26, 0x2c, 0xf4, 0xcf, 0x6c, 0xd7, 0xe5, 0x43, + 0xeb, 0xd8, 0xee, 0x3f, 0x9f, 0x8c, 0x83, 0x46, 0xe1, 0x6e, 0xe6, 0x7e, 0xf9, 0xf1, 0xcd, 0x0d, + 0x9c, 0xd5, 0x8d, 0xad, 0x33, 0xdb, 0xdd, 0xc4, 0x94, 0xae, 0x6b, 0x8f, 0x83, 0x33, 0x2f, 0x34, + 0x6b, 0x32, 0x07, 0x81, 0x03, 0x63, 0x19, 0x98, 0x3e, 0x12, 0x34, 0xf6, 0xc6, 0xbf, 0xca, 0xc0, + 0xd2, 0x91, 0x3b, 0xf4, 0xfa, 0xcf, 0x7f, 0xc2, 0x21, 0x4a, 0xe9, 0x43, 0xf6, 0x55, 0xfb, 0x90, + 0xfb, 0xaa, 0x7d, 0x58, 0x85, 0xe5, 0x64, 0x63, 0x65, 0x2f, 0x38, 0xac, 0x88, 0xdc, 0xa7, 0x5c, + 0x35, 0x4b, 0x75, 0xe3, 0x1d, 0xa8, 0xf7, 0x27, 0xbe, 0xcf, 0xdd, 0x99, 0x7e, 0x2c, 0x48, 0x78, + 0xd4, 0x91, 0x37, 0xa0, 0xe2, 0xf2, 0x8b, 0x18, 0x4d, 0xd2, 0xae, 0xcb, 0x2f, 0x14, 0x8a, 0xd1, + 0x80, 0xd5, 0xe9, 0x6a, 0x64, 0x03, 0x7e, 0x9c, 0x81, 0xfc, 0x51, 0x78, 0xe9, 0xb1, 0x27, 0x50, + 0xb1, 0x07, 0x03, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x8d, 0x69, 0xa5, 0xd4, 0x1e, 0x33, 0xd9, 0xc5, + 0x26, 0x25, 0xf5, 0xae, 0xc6, 0xdc, 0x2c, 0xdb, 0xf1, 0x07, 0x6b, 0xc0, 0xbc, 0xfc, 0xc4, 0x7a, + 0x4b, 0xa6, 0xfa, 0x64, 0xb7, 0x01, 0xec, 0x91, 0x37, 0x71, 0x43, 0x2b, 0xb0, 0x43, 0x1c, 0xb1, + 0x9c, 0x59, 0x22, 0x48, 0xd7, 0x0e, 0xd9, 0x2d, 0x28, 0x8d, 0x9f, 0x5b, 0x41, 0xdf, 0x77, 0xc6, + 0x21, 0x12, 0x4f, 0xc9, 0x2c, 0x8e, 0x9f, 0x77, 0xf1, 0x9b, 0xbd, 0x0b, 0x45, 0x6f, 0x12, 0x8e, + 0x3d, 0xc7, 0x0d, 0x25, 0xbd, 0x2c, 0xc8, 0x86, 0x1c, 0x4c, 0xc2, 0x43, 0x01, 0x36, 0x23, 0x04, + 0xf6, 0x16, 0x54, 0xfb, 0x9e, 0x7b, 0xe2, 0xf8, 0x23, 0xe2, 0x08, 0x8d, 0x39, 0xac, 0x2b, 0x09, + 0x34, 0xfe, 0x30, 0x0b, 0xe5, 0x9e, 0x6f, 0xbb, 0x81, 0xdd, 0x17, 0x00, 0xb6, 0x06, 0xf3, 0xe1, + 0xa5, 0x75, 0x66, 0x07, 0x67, 0xd8, 0xd5, 0x92, 0x39, 0x17, 0x5e, 0xee, 0xda, 0xc1, 0x19, 0x5b, + 0x85, 0x39, 0x6a, 0x25, 0x76, 0x28, 0x67, 0xca, 0x2f, 0xb1, 0x40, 0xdc, 0xc9, 0xc8, 0x4a, 0x56, + 0x95, 0x43, 0x8a, 0xa9, 0xbb, 0x93, 0xd1, 0x96, 0x0e, 0x17, 0x9d, 0x3f, 0x16, 0xd3, 0x4d, 0x15, + 0x50, 0xf7, 0x4a, 0x08, 0xc1, 0x3a, 0xde, 0x80, 0x8a, 0x4c, 0xe6, 0xce, 0xe9, 0x19, 0xf5, 0xb1, + 0x60, 0x96, 0x09, 0x01, 0x41, 0xa2, 0x84, 0xd0, 0x19, 0x71, 0x2b, 0x08, 0xed, 0xd1, 0x58, 0x76, + 0xa9, 0x24, 0x20, 0x5d, 0x01, 0xc0, 0x64, 0x2f, 0xb4, 0x87, 0xd6, 0x09, 0xe7, 0x41, 0x63, 0x5e, + 0x26, 0x0b, 0xc8, 0x0e, 0xe7, 0x01, 0xfb, 0x1a, 0xd4, 0x06, 0x3c, 0x08, 0x2d, 0x39, 0x19, 0x3c, + 0x68, 0x14, 0x71, 0xe5, 0x57, 0x05, 0xb4, 0xa9, 0x80, 0xec, 0x35, 0x00, 0xdf, 0xbe, 0xb0, 0xc4, + 0x40, 0xf0, 0xcb, 0x46, 0x89, 0x66, 0xc1, 0xb7, 0x2f, 0x7a, 0x97, 0xbb, 0xfc, 0x52, 0x50, 0xcd, + 0x53, 0x1e, 0x6a, 0x83, 0x16, 0x48, 0xea, 0x34, 0xf6, 0x80, 0x69, 0xe0, 0x6d, 0x1e, 0xda, 0xce, + 0x30, 0x60, 0x1f, 0x40, 0x25, 0xd4, 0x90, 0x91, 0x0d, 0x96, 0x23, 0x12, 0xd2, 0x32, 0x98, 0x09, + 0x3c, 0xe3, 0x0c, 0x8a, 0x3b, 0x9c, 0xef, 0x39, 0x23, 0x27, 0x64, 0xab, 0x50, 0x38, 0x71, 0x2e, + 0x39, 0x11, 0x7b, 0x6e, 0xf7, 0x86, 0x49, 0x9f, 0xec, 0x0e, 0x00, 0xfe, 0xb0, 0x46, 0x11, 0x35, + 0xed, 0xde, 0x30, 0x4b, 0x08, 0xdb, 0x0f, 0xec, 0x90, 0xad, 0xc3, 0xfc, 0x98, 0xfb, 0x7d, 0xae, + 0xe6, 0x6d, 0xf7, 0x86, 0xa9, 0x00, 0x9b, 0xf3, 0x50, 0x18, 0x8a, 0xd2, 0x8d, 0x3f, 0x29, 0x40, + 0xb9, 0xcb, 0xdd, 0x68, 0x95, 0x31, 0xc8, 0x8b, 0x01, 0x91, 0x2b, 0x0b, 0x7f, 0xb3, 0x37, 0xa1, + 0x8c, 0x43, 0x17, 0x84, 0xbe, 0xe3, 0x9e, 0x12, 0x55, 0x6f, 0x66, 0x1b, 0x19, 0x13, 0x04, 0xb8, + 0x8b, 0x50, 0x56, 0x87, 0x9c, 0x3d, 0x52, 0x54, 0x2d, 0x7e, 0xb2, 0x9b, 0x50, 0xb4, 0x47, 0x21, + 0x35, 0xaf, 0x82, 0xe0, 0x79, 0x7b, 0x14, 0x62, 0xd3, 0xde, 0x80, 0xca, 0xd8, 0xbe, 0x1a, 0x89, + 0xb5, 0x1c, 0x91, 0x43, 0xc5, 0x2c, 0x4b, 0x18, 0x12, 0xc4, 0x63, 0x58, 0xd2, 0x51, 0x54, 0xe5, + 0x85, 0xa8, 0xf2, 0x45, 0x0d, 0x5b, 0xb6, 0xe1, 0x1e, 0x2c, 0xa8, 0x3c, 0x3e, 0xf5, 0x07, 0xc9, + 0xa4, 0x64, 0xd6, 0x24, 0x58, 0xf5, 0xf2, 0x3e, 0xd4, 0x4f, 0x1c, 0xd7, 0x1e, 0x5a, 0xfd, 0x61, + 0x78, 0x6e, 0x0d, 0xf8, 0x30, 0xb4, 0x91, 0x62, 0x0a, 0x66, 0x0d, 0xe1, 0x5b, 0xc3, 0xf0, 0x7c, + 0x5b, 0x40, 0xd9, 0x7b, 0x50, 0x3a, 0xe1, 0xdc, 0xc2, 0xc1, 0x6a, 0x14, 0x13, 0x0b, 0x4f, 0xcd, + 0x90, 0x59, 0x3c, 0x51, 0x73, 0xf5, 0x1e, 0xd4, 0xbd, 0x49, 0x78, 0xea, 0x39, 0xee, 0xa9, 0x25, + 0xf8, 0x9d, 0xe5, 0x0c, 0x90, 0x86, 0xf2, 0x9b, 0xd9, 0x47, 0x19, 0xb3, 0xa6, 0xd2, 0x04, 0xe7, + 0x69, 0x0f, 0xd8, 0xdb, 0xb0, 0x30, 0xb4, 0x83, 0xd0, 0x3a, 0xf3, 0xc6, 0xd6, 0x78, 0x72, 0xfc, + 0x9c, 0x5f, 0x35, 0xaa, 0x38, 0x10, 0x55, 0x01, 0xde, 0xf5, 0xc6, 0x87, 0x08, 0x14, 0x94, 0x8d, + 0xed, 0xa4, 0x46, 0xc0, 0xdd, 0xcc, 0xfd, 0xaa, 0x59, 0x12, 0x10, 0xaa, 0xf4, 0x73, 0x58, 0xc2, + 0xe9, 0xe9, 0x4f, 0x82, 0xd0, 0x1b, 0x59, 0x82, 0x57, 0xfb, 0x83, 0xa0, 0x51, 0x46, 0x5a, 0x7b, + 0x47, 0x36, 0x56, 0x9b, 0xe3, 0x8d, 0x6d, 0x1e, 0x84, 0x5b, 0x88, 0x6c, 0x12, 0xae, 0xd8, 0xd0, + 0xaf, 0xcc, 0xc5, 0xc1, 0x34, 0x9c, 0xbd, 0x07, 0xcc, 0x1e, 0x0e, 0xbd, 0x0b, 0x2b, 0xe0, 0xc3, + 0x13, 0x4b, 0x0e, 0x62, 0xa3, 0x76, 0x37, 0x73, 0xbf, 0x68, 0xd6, 0x31, 0xa5, 0xcb, 0x87, 0x27, + 0x87, 0x04, 0x67, 0x1f, 0x00, 0x2e, 0x26, 0xeb, 0x84, 0xdb, 0xe1, 0xc4, 0xe7, 0x41, 0x63, 0xe1, + 0x6e, 0xee, 0x7e, 0xed, 0xf1, 0x62, 0x34, 0x5e, 0x08, 0xde, 0x74, 0x42, 0xb3, 0x22, 0xf0, 0xe4, + 0x77, 0xb0, 0xbe, 0x0d, 0xab, 0xe9, 0x4d, 0x12, 0x44, 0x25, 0x46, 0x45, 0x10, 0x63, 0xde, 0x14, + 0x3f, 0xd9, 0x32, 0x14, 0xce, 0xed, 0xe1, 0x84, 0x4b, 0x9e, 0x4e, 0x1f, 0x1f, 0x65, 0xbf, 0x95, + 0x31, 0xfe, 0x38, 0x03, 0x15, 0xea, 0xa5, 0x94, 0x45, 0xde, 0x84, 0xaa, 0xa2, 0x06, 0xee, 0xfb, + 0x9e, 0x2f, 0xb9, 0x9a, 0xa2, 0xbc, 0x96, 0x80, 0x89, 0x5d, 0x45, 0x21, 0x8d, 0x7d, 0xee, 0x8c, + 0xec, 0x53, 0x55, 0xb4, 0x22, 0xa5, 0x43, 0x09, 0x66, 0xef, 0xc7, 0xe5, 0xf9, 0xde, 0x24, 0xe4, + 0x72, 0xcf, 0xab, 0xc8, 0xee, 0x99, 0x02, 0x16, 0x95, 0x8e, 0x5f, 0xaf, 0x40, 0xe7, 0xc6, 0x6f, + 0x67, 0x80, 0x89, 0x66, 0xf7, 0x3c, 0x2a, 0x40, 0x52, 0xe8, 0x74, 0xce, 0xcc, 0x2b, 0xaf, 0x90, + 0xec, 0x8b, 0x56, 0x88, 0x01, 0x05, 0x6a, 0x7b, 0x3e, 0xa5, 0xed, 0x94, 0xf4, 0xbd, 0x7c, 0x31, + 0x57, 0xcf, 0x1b, 0xff, 0x35, 0x07, 0xcb, 0x5b, 0xb4, 0x65, 0x37, 0xfb, 0x7d, 0x3e, 0x8e, 0xd6, + 0xce, 0x1d, 0x28, 0xbb, 0xde, 0x80, 0x2b, 0x8a, 0xa5, 0x86, 0x81, 0x00, 0x69, 0xe4, 0x7a, 0x66, + 0x3b, 0x2e, 0x35, 0x9c, 0x06, 0xb3, 0x84, 0x10, 0x6c, 0xf6, 0xdb, 0xb0, 0x30, 0xe6, 0xee, 0x40, + 0x5f, 0x22, 0x24, 0x54, 0x55, 0x25, 0x58, 0xae, 0x8e, 0x3b, 0x50, 0x3e, 0x99, 0x10, 0x9e, 0x60, + 0x2c, 0x79, 0xa4, 0x01, 0x90, 0xa0, 0x26, 0xf1, 0x97, 0xf1, 0x24, 0x38, 0xc3, 0xd4, 0x02, 0xa6, + 0xce, 0x8b, 0x6f, 0x91, 0x74, 0x1b, 0x60, 0x30, 0x09, 0x42, 0xb9, 0x62, 0xe6, 0x30, 0xb1, 0x24, + 0x20, 0xb4, 0x62, 0xbe, 0x0e, 0x4b, 0x23, 0xfb, 0xd2, 0x42, 0xda, 0xb1, 0x1c, 0xd7, 0x3a, 0x19, + 0xe2, 0x9e, 0x33, 0x8f, 0x78, 0xf5, 0x91, 0x7d, 0xf9, 0xa9, 0x48, 0x69, 0xbb, 0x3b, 0x08, 0x17, + 0x6c, 0x45, 0x89, 0x3b, 0x3e, 0x0f, 0xb8, 0x7f, 0xce, 0x91, 0x13, 0xe4, 0x23, 0x99, 0xc6, 0x24, + 0xa8, 0x68, 0xd1, 0x48, 0xf4, 0x3b, 0x1c, 0xf6, 0x69, 0xd9, 0x9b, 0xf3, 0x23, 0xc7, 0xdd, 0x0d, + 0x87, 0x7d, 0xb1, 0xaf, 0x08, 0x3e, 0x32, 0xe6, 0xbe, 0xf5, 0xfc, 0x02, 0xd7, 0x70, 0x1e, 0xf9, + 0xc6, 0x21, 0xf7, 0x9f, 0x5d, 0x88, 0xad, 0xbf, 0x1f, 0x20, 0x23, 0xb2, 0xaf, 0x1a, 0x65, 0x5c, + 0xe0, 0xc5, 0x7e, 0x20, 0x58, 0x90, 0x7d, 0x25, 0x16, 0xa1, 0x68, 0xad, 0x8d, 0xb3, 0xc0, 0x07, + 0x58, 0x7c, 0x80, 0x1c, 0xb5, 0x8a, 0x8d, 0x6d, 0xca, 0x04, 0x51, 0x4f, 0x20, 0xa8, 0x5e, 0x35, + 0xf6, 0x64, 0x68, 0x9f, 0x06, 0xc8, 0x52, 0xaa, 0x66, 0x45, 0x02, 0x77, 0x04, 0xcc, 0xf8, 0x8c, + 0x84, 0x2c, 0x6d, 0x6e, 0xe5, 0x9a, 0x11, 0x5b, 0x3d, 0x42, 0x70, 0x5e, 0x8b, 0xa6, 0xfc, 0x4a, + 0x9b, 0xb4, 0x6c, 0xca, 0xa4, 0x19, 0xbf, 0x97, 0x81, 0x8a, 0x2c, 0x19, 0x85, 0x12, 0xb6, 0x01, + 0x4c, 0xcd, 0x62, 0x78, 0xe9, 0x0c, 0xac, 0xe3, 0xab, 0x90, 0x07, 0x44, 0x34, 0xbb, 0x37, 0xcc, + 0xba, 0x4c, 0xeb, 0x5d, 0x3a, 0x83, 0x4d, 0x91, 0xc2, 0x1e, 0x40, 0x3d, 0x81, 0x1f, 0x84, 0x3e, + 0x51, 0xf4, 0xee, 0x0d, 0xb3, 0xa6, 0x61, 0x77, 0x43, 0x5f, 0xac, 0x11, 0x21, 0xf2, 0x4c, 0x42, + 0xcb, 0x71, 0x07, 0xfc, 0x12, 0xc9, 0xa8, 0x6a, 0x96, 0x09, 0xd6, 0x16, 0xa0, 0xcd, 0x1a, 0x54, + 0xf4, 0xe2, 0x8c, 0x53, 0x28, 0x2a, 0x79, 0x09, 0x05, 0x86, 0xa9, 0x26, 0x99, 0xa5, 0x30, 0x6a, + 0xc9, 0x4d, 0x28, 0x26, 0x5b, 0x60, 0xce, 0x87, 0xaf, 0x5c, 0xb1, 0xf1, 0x1d, 0xa8, 0xef, 0x09, + 0xe2, 0x71, 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x15, 0xe6, 0xb4, 0x45, 0x53, 0x32, 0xe5, 0x97, 0xd8, + 0x73, 0xcf, 0xbc, 0x20, 0x94, 0xb5, 0xe0, 0x6f, 0xe3, 0x4f, 0x32, 0xc0, 0x5a, 0x41, 0xe8, 0x8c, + 0xec, 0x90, 0xef, 0xf0, 0x88, 0x2d, 0x1c, 0x40, 0x45, 0x94, 0xd6, 0xf3, 0x9a, 0x24, 0x90, 0x91, + 0x40, 0xf1, 0xae, 0x5c, 0xc6, 0xb3, 0x19, 0x36, 0x74, 0x6c, 0x62, 0xf3, 0x89, 0x02, 0xc4, 0x2a, + 0x0b, 0x6d, 0xff, 0x94, 0x87, 0x28, 0xc6, 0x49, 0x79, 0x1f, 0x08, 0x24, 0x04, 0xb8, 0xf5, 0x5f, + 0x84, 0xc5, 0x99, 0x32, 0x74, 0xbe, 0x5c, 0x4a, 0xe1, 0xcb, 0x39, 0x9d, 0x2f, 0x5b, 0xb0, 0x94, + 0x68, 0x97, 0xa4, 0xb4, 0x35, 0x98, 0x17, 0x0b, 0x42, 0x08, 0x07, 0x19, 0x92, 0x2a, 0x4f, 0x38, + 0x17, 0x62, 0xf0, 0x43, 0x58, 0x3e, 0xe1, 0xdc, 0xb7, 0x43, 0x4c, 0xc4, 0x15, 0x23, 0x66, 0x48, + 0x16, 0xbc, 0x28, 0xd3, 0xba, 0x76, 0x78, 0xc8, 0x7d, 0x31, 0x53, 0xc6, 0x7f, 0xcf, 0xc0, 0x82, + 0xe0, 0xa0, 0xfb, 0xb6, 0x7b, 0xa5, 0xc6, 0x69, 0x2f, 0x75, 0x9c, 0xee, 0x6b, 0x9b, 0xa1, 0x86, + 0xfd, 0x55, 0x07, 0x29, 0x37, 0x3d, 0x48, 0xec, 0x2e, 0x54, 0x12, 0x6d, 0x2d, 0x60, 0x5b, 0x21, + 0x88, 0x1a, 0xf9, 0xd3, 0x0f, 0xe3, 0xdb, 0x50, 0x8f, 0x9b, 0x2d, 0xc7, 0x90, 0x41, 0x5e, 0x90, + 0xa4, 0x2c, 0x00, 0x7f, 0x1b, 0xbf, 0x9b, 0x21, 0xc4, 0x2d, 0xcf, 0x89, 0xa4, 0x53, 0x81, 0x28, + 0xe4, 0x5e, 0x85, 0x28, 0x7e, 0x5f, 0x2b, 0xd5, 0xff, 0xf4, 0x9d, 0x15, 0x4b, 0x27, 0xe0, 0xee, + 0xc0, 0xb2, 0x87, 0x43, 0x64, 0xbe, 0x45, 0x73, 0x5e, 0x7c, 0x37, 0x87, 0x43, 0xe3, 0x1e, 0x2c, + 0x6a, 0xad, 0x7b, 0x41, 0x3f, 0x3a, 0xc0, 0xf6, 0x9c, 0x20, 0x3c, 0x72, 0x83, 0xb1, 0x26, 0xb8, + 0xdd, 0x82, 0x92, 0xe0, 0xb0, 0xa2, 0x65, 0xb4, 0x64, 0x0b, 0xa6, 0x60, 0xb9, 0xa2, 0x5d, 0x01, + 0x26, 0xda, 0x97, 0x32, 0x31, 0x2b, 0x13, 0xed, 0x4b, 0x4c, 0x34, 0xbe, 0x05, 0x4b, 0x89, 0xf2, + 0x64, 0xd5, 0x6f, 0x40, 0x61, 0x12, 0x5e, 0x7a, 0x4a, 0x34, 0x2f, 0x4b, 0x0a, 0x11, 0x0a, 0xa0, + 0x49, 0x29, 0xc6, 0xc7, 0xb0, 0xd8, 0xe1, 0x17, 0x72, 0x11, 0xab, 0x86, 0xbc, 0x0d, 0xf9, 0x97, + 0x28, 0x85, 0x98, 0x6e, 0x6c, 0x00, 0xd3, 0x33, 0xcb, 0x5a, 0x35, 0x1d, 0x31, 0x93, 0xd0, 0x11, + 0x8d, 0xb7, 0x81, 0x75, 0x9d, 0x53, 0x77, 0x9f, 0x07, 0x81, 0x7d, 0x1a, 0x2d, 0xfb, 0x3a, 0xe4, + 0x46, 0xc1, 0xa9, 0xe4, 0x51, 0xe2, 0xa7, 0xf1, 0x0d, 0x58, 0x4a, 0xe0, 0xc9, 0x82, 0x5f, 0x83, + 0x52, 0xe0, 0x9c, 0xba, 0x28, 0x58, 0xc9, 0xa2, 0x63, 0x80, 0xb1, 0x03, 0xcb, 0x9f, 0x72, 0xdf, + 0x39, 0xb9, 0x7a, 0x59, 0xf1, 0xc9, 0x72, 0xb2, 0xd3, 0xe5, 0xb4, 0x60, 0x65, 0xaa, 0x1c, 0x59, + 0x3d, 0x91, 0xaf, 0x9c, 0xc9, 0xa2, 0x49, 0x1f, 0x1a, 0xdf, 0xcb, 0xea, 0x7c, 0xcf, 0x38, 0x02, + 0xb6, 0xe5, 0xb9, 0x2e, 0xef, 0x87, 0x87, 0x9c, 0xfb, 0xb1, 0x95, 0x2a, 0xa6, 0xd5, 0xf2, 0xe3, + 0x35, 0x39, 0xb2, 0xd3, 0xcc, 0x54, 0x12, 0x31, 0x83, 0xfc, 0x98, 0xfb, 0x23, 0x2c, 0xb8, 0x68, + 0xe2, 0x6f, 0x63, 0x05, 0x96, 0x12, 0xc5, 0x4a, 0xbd, 0xfe, 0x11, 0xac, 0x6c, 0x3b, 0x41, 0x7f, + 0xb6, 0xc2, 0x35, 0x98, 0x1f, 0x4f, 0x8e, 0xad, 0x24, 0x5f, 0x7e, 0xc6, 0xaf, 0x84, 0xb6, 0x37, + 0x9d, 0x43, 0x96, 0xf5, 0xd7, 0x33, 0x90, 0xdf, 0xed, 0xed, 0x6d, 0xb1, 0x75, 0x28, 0x3a, 0x6e, + 0xdf, 0x1b, 0x09, 0xc1, 0x8b, 0xfa, 0x1c, 0x7d, 0x5f, 0xbb, 0xc0, 0x6e, 0x41, 0x09, 0xe5, 0x35, + 0xa1, 0xda, 0x4a, 0xd1, 0xa7, 0x28, 0x00, 0x7b, 0x5e, 0xff, 0xb9, 0xd0, 0xa9, 0xf9, 0xe5, 0xd8, + 0xf1, 0x51, 0x6b, 0x56, 0xca, 0x70, 0x9e, 0xf6, 0xfa, 0x38, 0x81, 0x34, 0x62, 0xe3, 0xdf, 0x14, + 0x61, 0x5e, 0xee, 0xb6, 0xb4, 0x73, 0x87, 0xce, 0x39, 0x8f, 0x77, 0x6e, 0xf1, 0x25, 0xe4, 0x01, + 0x9f, 0x8f, 0xbc, 0x30, 0x12, 0xd8, 0x68, 0x0e, 0x2a, 0x04, 0x94, 0x22, 0x9b, 0x26, 0x34, 0x90, + 0x89, 0x21, 0x47, 0x48, 0x7d, 0x7d, 0x2b, 0xbf, 0x05, 0xf3, 0x6a, 0xef, 0xcf, 0x47, 0x3a, 0xcd, + 0x5c, 0x9f, 0xa4, 0xb5, 0x75, 0x28, 0xf6, 0xed, 0xb1, 0xdd, 0x77, 0xc2, 0x2b, 0xc9, 0x10, 0xa2, + 0x6f, 0x51, 0xfa, 0xd0, 0xeb, 0xdb, 0x43, 0xeb, 0xd8, 0x1e, 0xda, 0x6e, 0x9f, 0x4b, 0xdd, 0xbd, + 0x82, 0xc0, 0x4d, 0x82, 0x09, 0xfd, 0x5c, 0xb6, 0x53, 0x61, 0x91, 0x0a, 0x2f, 0x5b, 0xaf, 0xd0, + 0x84, 0x70, 0xe9, 0x8d, 0x46, 0x8e, 0xd0, 0x32, 0x48, 0x0c, 0xcb, 0x99, 0x25, 0x82, 0xec, 0x70, + 0xec, 0xad, 0x4c, 0xbe, 0xa0, 0xa1, 0x2b, 0x51, 0x55, 0x04, 0xfc, 0x8c, 0x0c, 0x09, 0xb3, 0xb2, + 0x58, 0x4e, 0x93, 0xc5, 0xde, 0x85, 0xc5, 0x89, 0x1b, 0xf0, 0x30, 0x1c, 0xf2, 0x41, 0xd4, 0x96, + 0x32, 0x22, 0xd5, 0xa3, 0x04, 0xd5, 0x9c, 0x0d, 0x58, 0x22, 0xa3, 0x43, 0x60, 0x87, 0x5e, 0x70, + 0xe6, 0x04, 0x56, 0x20, 0x34, 0x24, 0x52, 0x77, 0x17, 0x31, 0xa9, 0x2b, 0x53, 0xba, 0xa4, 0x22, + 0xad, 0x4d, 0xe1, 0xfb, 0xbc, 0xcf, 0x9d, 0x73, 0x3e, 0x40, 0x39, 0x2d, 0x67, 0xae, 0x24, 0xf2, + 0x98, 0x32, 0x11, 0x85, 0xee, 0xc9, 0xc8, 0x9a, 0x8c, 0x07, 0xb6, 0x10, 0x56, 0x6a, 0x24, 0x0c, + 0xbb, 0x93, 0xd1, 0x11, 0x41, 0xd8, 0x23, 0x50, 0x92, 0x98, 0x94, 0x0f, 0x17, 0x12, 0xfc, 0x4c, + 0x10, 0xab, 0x59, 0x91, 0x18, 0x24, 0x28, 0x26, 0x64, 0xce, 0xfa, 0x94, 0xcc, 0xd9, 0x80, 0xf9, + 0xb1, 0xef, 0x9c, 0xdb, 0x21, 0x6f, 0x2c, 0x12, 0x03, 0x97, 0x9f, 0x82, 0x33, 0x38, 0xae, 0x13, + 0x3a, 0x76, 0xe8, 0xf9, 0x0d, 0x86, 0x69, 0x31, 0x80, 0x3d, 0x80, 0x45, 0xa4, 0x91, 0x20, 0xb4, + 0xc3, 0x49, 0x20, 0x25, 0xd0, 0x25, 0x24, 0x26, 0x94, 0xa1, 0xbb, 0x08, 0x47, 0x21, 0x94, 0x7d, + 0x03, 0x56, 0x89, 0x2c, 0x30, 0x87, 0x94, 0xac, 0x51, 0x20, 0x58, 0xc6, 0xa1, 0x58, 0xc2, 0x54, + 0x41, 0xdf, 0x52, 0xbe, 0x16, 0xd2, 0xc1, 0x13, 0x58, 0x93, 0x64, 0x32, 0x93, 0x6b, 0x05, 0x73, + 0x2d, 0x53, 0xf2, 0x54, 0xb6, 0x0d, 0x58, 0x14, 0x4d, 0x72, 0xfa, 0x96, 0xcc, 0x2d, 0x56, 0xc2, + 0xaa, 0x68, 0x3d, 0x6a, 0x4a, 0x0b, 0x94, 0x68, 0x62, 0xda, 0x33, 0x7e, 0xc5, 0xbe, 0x03, 0x0b, + 0x44, 0x32, 0xa8, 0x5e, 0x21, 0xa7, 0x5f, 0x47, 0x4e, 0xbf, 0xa2, 0x2c, 0x9c, 0x51, 0x2a, 0x32, + 0xfb, 0x5a, 0x3f, 0xf1, 0x2d, 0x96, 0xc3, 0xd0, 0x39, 0xe1, 0xa1, 0x33, 0xe2, 0x8d, 0x35, 0x22, + 0x30, 0xf5, 0x2d, 0x56, 0xea, 0x64, 0x8c, 0x29, 0x0d, 0xe2, 0x0b, 0xf4, 0x85, 0xb4, 0x3b, 0xf4, + 0x02, 0xae, 0x4c, 0x54, 0x8d, 0x9b, 0x72, 0x11, 0x0a, 0xa0, 0x92, 0x21, 0x85, 0x20, 0x4e, 0x4a, + 0x4f, 0x64, 0x48, 0xbc, 0x85, 0xc4, 0x50, 0x25, 0xdd, 0x47, 0x19, 0x13, 0xc5, 0x2e, 0x7e, 0x66, + 0x5f, 0x28, 0x0e, 0xf2, 0x1a, 0xce, 0x2f, 0x08, 0x90, 0xe4, 0x1d, 0x7f, 0x94, 0xa1, 0x0d, 0x51, + 0xf2, 0x8f, 0x40, 0x53, 0xef, 0x88, 0x73, 0x58, 0x9e, 0x3b, 0xbc, 0x92, 0xcc, 0x04, 0x08, 0x74, + 0xe0, 0x0e, 0x71, 0x35, 0x3b, 0xae, 0x8e, 0x42, 0xbc, 0xb7, 0xa2, 0x80, 0x88, 0x74, 0x07, 0xca, + 0xe3, 0xc9, 0xf1, 0xd0, 0xe9, 0x13, 0x4a, 0x8e, 0x4a, 0x21, 0x10, 0x22, 0x08, 0xfd, 0x96, 0x28, + 0x8a, 0x30, 0xf2, 0x88, 0x51, 0x96, 0x30, 0x44, 0x41, 0xde, 0xce, 0x7d, 0x64, 0x27, 0x15, 0x13, + 0x7f, 0x1b, 0x9b, 0xb0, 0x9c, 0x6c, 0xb4, 0xdc, 0x78, 0x1e, 0x40, 0x51, 0xf2, 0x2a, 0x65, 0xf8, + 0xa8, 0x69, 0xa6, 0x68, 0xa1, 0xa2, 0x45, 0xe9, 0xc6, 0xef, 0x17, 0x60, 0x49, 0x42, 0xb7, 0xc4, + 0xd0, 0x76, 0x27, 0xa3, 0x91, 0xed, 0xa7, 0x30, 0xc1, 0xcc, 0x8b, 0x99, 0x60, 0x76, 0x86, 0x09, + 0x26, 0x35, 0x5f, 0xe2, 0xa1, 0x49, 0xcd, 0x57, 0xcc, 0x25, 0x29, 0x23, 0xba, 0x1d, 0xb4, 0x2a, + 0xc1, 0x3d, 0xb2, 0xb7, 0xce, 0xb0, 0xec, 0x42, 0x0a, 0xcb, 0xd6, 0x19, 0xee, 0xdc, 0x14, 0xc3, + 0x7d, 0x03, 0x88, 0x68, 0xd4, 0xec, 0xcf, 0x93, 0x7e, 0x82, 0x30, 0x69, 0x4c, 0xbd, 0x07, 0x0b, + 0xd3, 0x3c, 0x8e, 0x98, 0x69, 0x2d, 0x85, 0xc3, 0x39, 0x23, 0x8e, 0xbb, 0x95, 0x86, 0x5c, 0x92, + 0x1c, 0xce, 0x19, 0xf1, 0x3d, 0x4c, 0x51, 0xf8, 0x2d, 0x00, 0xaa, 0x1b, 0x17, 0x0d, 0xe0, 0xa2, + 0x79, 0x3b, 0x39, 0x17, 0xfa, 0xa8, 0x6f, 0x88, 0x8f, 0x89, 0xcf, 0x71, 0x15, 0x95, 0x30, 0x27, + 0x2e, 0xa0, 0x0f, 0xa1, 0xe6, 0x8d, 0xb9, 0x6b, 0xc5, 0xbc, 0xa6, 0x8c, 0x45, 0xd5, 0x65, 0x51, + 0x6d, 0x05, 0x37, 0xab, 0x02, 0x2f, 0xfa, 0x64, 0xdf, 0xa6, 0x41, 0xe6, 0x5a, 0xce, 0xca, 0x35, + 0x39, 0x6b, 0x88, 0x18, 0x7d, 0x1b, 0xbf, 0x99, 0x81, 0xb2, 0xd6, 0x1c, 0xb6, 0x02, 0x8b, 0x5b, + 0x07, 0x07, 0x87, 0x2d, 0xb3, 0xd9, 0x6b, 0x7f, 0xda, 0xb2, 0xb6, 0xf6, 0x0e, 0xba, 0xad, 0xfa, + 0x0d, 0x01, 0xde, 0x3b, 0xd8, 0x6a, 0xee, 0x59, 0x3b, 0x07, 0xe6, 0x96, 0x02, 0x67, 0xd8, 0x2a, + 0x30, 0xb3, 0xb5, 0x7f, 0xd0, 0x6b, 0x25, 0xe0, 0x59, 0x56, 0x87, 0xca, 0xa6, 0xd9, 0x6a, 0x6e, + 0xed, 0x4a, 0x48, 0x8e, 0x2d, 0x43, 0x7d, 0xe7, 0xa8, 0xb3, 0xdd, 0xee, 0x3c, 0xb5, 0xb6, 0x9a, + 0x9d, 0xad, 0xd6, 0x5e, 0x6b, 0xbb, 0x9e, 0x67, 0x55, 0x28, 0x35, 0x37, 0x9b, 0x9d, 0xed, 0x83, + 0x4e, 0x6b, 0xbb, 0x5e, 0x30, 0xfe, 0x22, 0x03, 0x2b, 0x38, 0x50, 0x83, 0xe9, 0x15, 0x7a, 0x17, + 0xca, 0x7d, 0xcf, 0x1b, 0x0b, 0x35, 0x28, 0xde, 0xee, 0x75, 0x90, 0x58, 0x7d, 0xc4, 0x59, 0x4f, + 0x3c, 0xbf, 0xcf, 0xe5, 0x02, 0x05, 0x04, 0xed, 0x08, 0x88, 0x20, 0x10, 0x49, 0x61, 0x84, 0x41, + 0xeb, 0xb3, 0x4c, 0x30, 0x42, 0x59, 0x85, 0xb9, 0x63, 0x9f, 0xdb, 0xfd, 0x33, 0xb9, 0x34, 0xe5, + 0x17, 0x7b, 0x27, 0x56, 0xd0, 0xfb, 0x62, 0xc2, 0x87, 0x7c, 0x80, 0xf4, 0x59, 0x34, 0x17, 0x24, + 0x7c, 0x4b, 0x82, 0xc5, 0x56, 0x61, 0x1f, 0xdb, 0xee, 0xc0, 0x73, 0xf9, 0x40, 0xea, 0x01, 0x31, + 0xc0, 0x38, 0x84, 0xd5, 0xe9, 0xfe, 0xc9, 0xc5, 0xfc, 0x81, 0xb6, 0x98, 0x49, 0x2c, 0x5f, 0xbf, + 0x9e, 0x80, 0xb4, 0x85, 0xfd, 0xb7, 0xf3, 0x90, 0x17, 0x62, 0xda, 0xb5, 0x12, 0x9d, 0x2e, 0x77, + 0xe7, 0x66, 0x7c, 0x33, 0x68, 0x07, 0xa0, 0xfd, 0x9b, 0x8c, 0x4d, 0x25, 0x84, 0xe0, 0xbe, 0x1d, + 0x25, 0xfb, 0xbc, 0x7f, 0x2e, 0xad, 0x4d, 0x94, 0x6c, 0xf2, 0xfe, 0x39, 0x2a, 0x3c, 0x76, 0x48, + 0x79, 0x69, 0x31, 0xce, 0x07, 0x76, 0x88, 0x39, 0x65, 0x12, 0xe6, 0x9b, 0x8f, 0x92, 0x30, 0x57, + 0x03, 0xe6, 0x1d, 0xf7, 0xd8, 0x9b, 0xb8, 0x03, 0x5c, 0x7b, 0x45, 0x53, 0x7d, 0xa2, 0x2b, 0x08, + 0xd9, 0x84, 0xd8, 0x25, 0x68, 0xa9, 0x15, 0x05, 0xa0, 0x27, 0xf6, 0x89, 0xf7, 0xa1, 0x14, 0x5c, + 0xb9, 0x7d, 0x7d, 0x81, 0x2d, 0xcb, 0xf1, 0x11, 0xbd, 0xdf, 0xe8, 0x5e, 0xb9, 0x7d, 0x5c, 0x4e, + 0xc5, 0x40, 0xfe, 0x62, 0x4f, 0xa0, 0x18, 0x19, 0x65, 0x89, 0x3d, 0xde, 0xd4, 0x73, 0x28, 0x4b, + 0x2c, 0xe9, 0xbe, 0x11, 0x2a, 0x7b, 0x08, 0x73, 0x68, 0x39, 0x0d, 0x1a, 0x15, 0xcc, 0xa4, 0x84, + 0x71, 0xd1, 0x0c, 0xf4, 0xc2, 0xf0, 0x01, 0x5a, 0x51, 0x4d, 0x89, 0xb6, 0xfe, 0x0c, 0xaa, 0x89, + 0xb2, 0x74, 0x0d, 0xb7, 0x4a, 0x1a, 0xee, 0x5b, 0xba, 0x86, 0x1b, 0xb3, 0x69, 0x99, 0x4d, 0xd7, + 0x78, 0x7f, 0x11, 0x8a, 0xaa, 0x2b, 0x62, 0x11, 0x1d, 0x75, 0x9e, 0x75, 0x0e, 0x3e, 0xeb, 0x58, + 0xdd, 0xcf, 0x3b, 0x5b, 0xf5, 0x1b, 0x6c, 0x01, 0xca, 0xcd, 0x2d, 0x5c, 0x97, 0x08, 0xc8, 0x08, + 0x94, 0xc3, 0x66, 0xb7, 0x1b, 0x41, 0xb2, 0xc6, 0x0e, 0xd4, 0xa7, 0x5b, 0x2a, 0x68, 0x32, 0x54, + 0x30, 0x69, 0x57, 0x8e, 0x01, 0x42, 0x7f, 0x21, 0x53, 0x31, 0x09, 0xc9, 0xf4, 0x61, 0x3c, 0x81, + 0xba, 0xd8, 0x74, 0xc4, 0x50, 0x05, 0x9a, 0x7d, 0x76, 0x28, 0x04, 0x2f, 0xdd, 0xb6, 0x5c, 0x34, + 0xcb, 0x04, 0xc3, 0xaa, 0x8c, 0x0f, 0x60, 0x51, 0xcb, 0x16, 0xeb, 0x9b, 0x62, 0x23, 0x9b, 0xd6, + 0x37, 0x51, 0xbb, 0xa0, 0x14, 0x63, 0x0d, 0x56, 0xc4, 0x67, 0xeb, 0x9c, 0xbb, 0x61, 0x77, 0x72, + 0x4c, 0x0e, 0x41, 0xc7, 0x73, 0x85, 0xd6, 0x51, 0x8a, 0x52, 0xae, 0x27, 0xf2, 0x0d, 0xa9, 0x9a, + 0x66, 0x91, 0x34, 0xd6, 0xb5, 0x1a, 0x30, 0xe3, 0x06, 0xfe, 0x4d, 0xa8, 0xa8, 0xa5, 0x08, 0x24, + 0x86, 0xf5, 0xb0, 0xd5, 0x32, 0xad, 0x83, 0xce, 0x5e, 0xbb, 0x23, 0xb8, 0x9d, 0x18, 0x56, 0x04, + 0xec, 0xec, 0x20, 0x24, 0x63, 0xd4, 0xa1, 0xf6, 0x94, 0x87, 0x6d, 0xf7, 0xc4, 0x53, 0xce, 0xaf, + 0x1f, 0x17, 0x60, 0x21, 0x02, 0xc5, 0x2a, 0xee, 0x39, 0xf7, 0x03, 0xc7, 0x73, 0x51, 0x5a, 0x2d, + 0x99, 0xea, 0x53, 0x6c, 0x3d, 0xce, 0x80, 0xbb, 0xa1, 0x13, 0x5e, 0x59, 0x09, 0x7b, 0x58, 0x4d, + 0x81, 0xe5, 0x16, 0xb7, 0x0c, 0x05, 0x7b, 0xe8, 0xd8, 0xca, 0x8f, 0x4a, 0x1f, 0x02, 0xda, 0xf7, + 0x86, 0x9e, 0x8f, 0x82, 0x69, 0xc9, 0xa4, 0x0f, 0xf6, 0x08, 0x96, 0x85, 0x80, 0xac, 0x1b, 0x29, + 0x91, 0x7f, 0x90, 0x69, 0x8e, 0xb9, 0x93, 0xd1, 0x61, 0x6c, 0xa8, 0x14, 0x29, 0x62, 0x63, 0x13, + 0x39, 0xa4, 0x24, 0x13, 0x65, 0x20, 0x5d, 0x6b, 0xd1, 0x9d, 0x8c, 0x9a, 0x98, 0x12, 0xe1, 0x3f, + 0x86, 0x15, 0x81, 0x1f, 0xc9, 0x3e, 0x51, 0x8e, 0x05, 0xcc, 0x21, 0x0a, 0x6b, 0xcb, 0xb4, 0x28, + 0xcf, 0x2d, 0x28, 0x51, 0xab, 0xc4, 0x8c, 0x17, 0x48, 0xc6, 0xc6, 0xa6, 0x70, 0x3f, 0x98, 0x71, + 0x79, 0xce, 0xd1, 0x2e, 0x3d, 0xe5, 0xf2, 0xd4, 0x9c, 0xa6, 0xc5, 0x69, 0xa7, 0xe9, 0x63, 0x58, + 0x39, 0x16, 0x24, 0x78, 0xc6, 0xed, 0x01, 0xf7, 0xad, 0x98, 0xb0, 0x49, 0x97, 0x58, 0x12, 0x89, + 0xbb, 0x98, 0x16, 0xad, 0x03, 0x21, 0x84, 0x08, 0xb6, 0xc0, 0x07, 0x56, 0xe8, 0x59, 0x28, 0x9b, + 0x20, 0x83, 0x29, 0x9a, 0x55, 0x02, 0xf7, 0xbc, 0x2d, 0x01, 0x4c, 0xe2, 0x9d, 0xfa, 0xf6, 0xf8, + 0x4c, 0x4a, 0xfb, 0x11, 0xde, 0x53, 0x01, 0x64, 0xaf, 0xc1, 0xbc, 0x20, 0x79, 0x97, 0x93, 0x67, + 0x8a, 0xe4, 0x69, 0x05, 0x62, 0x6f, 0xc1, 0x1c, 0xd6, 0x11, 0x34, 0xea, 0x48, 0xef, 0x95, 0x98, + 0x91, 0x3b, 0xae, 0x29, 0xd3, 0x84, 0xa4, 0x37, 0xf1, 0x1d, 0xe2, 0x32, 0x25, 0x13, 0x7f, 0xb3, + 0xef, 0x6a, 0x2c, 0x6b, 0x09, 0xf3, 0xbe, 0x25, 0xf3, 0x4e, 0x51, 0xda, 0x75, 0xdc, 0xeb, 0x67, + 0xca, 0x8c, 0xbe, 0x97, 0x2f, 0x96, 0xeb, 0x15, 0xe3, 0x43, 0x28, 0xd0, 0xe8, 0x08, 0x22, 0xc4, + 0xb1, 0xcb, 0x48, 0x22, 0x44, 0x68, 0x03, 0xe6, 0x5d, 0x1e, 0x5e, 0x78, 0xfe, 0x73, 0x65, 0x31, + 0x96, 0x9f, 0xc6, 0x0f, 0xd1, 0xd4, 0x11, 0xb9, 0xc3, 0x49, 0x6b, 0x13, 0xe4, 0x41, 0xd3, 0x1b, + 0x9c, 0xd9, 0xd2, 0xfa, 0x52, 0x44, 0x40, 0xf7, 0xcc, 0x9e, 0x21, 0x8f, 0xec, 0xac, 0x47, 0xfc, + 0x2d, 0xa8, 0x29, 0x07, 0x7c, 0x60, 0x0d, 0xf9, 0x49, 0x28, 0xc9, 0xbd, 0x22, 0xbd, 0xef, 0xc1, + 0x1e, 0x3f, 0x09, 0x8d, 0x7d, 0x58, 0x94, 0x04, 0x79, 0x30, 0xe6, 0xaa, 0xea, 0x6f, 0xa5, 0x09, + 0xbb, 0xe5, 0xc7, 0x4b, 0xc9, 0x8d, 0x96, 0x02, 0x0b, 0x12, 0x12, 0xb0, 0xf1, 0x09, 0x30, 0x7d, + 0x1b, 0x96, 0xe5, 0x49, 0x91, 0x53, 0x19, 0xda, 0x95, 0xbf, 0x2a, 0x12, 0x6c, 0x9d, 0x81, 0x18, + 0x9d, 0x60, 0xd2, 0xef, 0xab, 0xc0, 0x88, 0xa2, 0xa9, 0x3e, 0x8d, 0x3f, 0xcd, 0xc0, 0x12, 0x16, + 0xa6, 0x84, 0x75, 0xc9, 0x64, 0x7f, 0xe2, 0x46, 0x8a, 0xf9, 0xd1, 0x65, 0x1f, 0xfa, 0xf8, 0xea, + 0xa6, 0xcd, 0xfc, 0x8c, 0x69, 0xf3, 0x1d, 0xa8, 0x0f, 0xf8, 0xd0, 0xc1, 0x18, 0x19, 0x25, 0x4a, + 0x90, 0x78, 0xbe, 0xa0, 0xe0, 0x52, 0x55, 0x33, 0xfe, 0x7e, 0x06, 0x16, 0x49, 0x52, 0x41, 0xa5, + 0x57, 0x0e, 0xd4, 0xc7, 0x4a, 0xcb, 0x93, 0xac, 0x4a, 0xf6, 0x29, 0xde, 0xc1, 0x11, 0x4a, 0xc8, + 0xbb, 0x37, 0xa4, 0xf6, 0x27, 0xa1, 0xec, 0x23, 0x54, 0x30, 0x5c, 0x0b, 0x81, 0x29, 0x31, 0x37, + 0xc9, 0x49, 0xd9, 0xbd, 0x81, 0xda, 0x87, 0x8b, 0xa0, 0xcd, 0xa2, 0x50, 0x3b, 0x05, 0xd8, 0xd8, + 0x81, 0x6a, 0xa2, 0x9a, 0x84, 0xfd, 0xb5, 0x42, 0xf6, 0xd7, 0x19, 0x1f, 0x47, 0x76, 0xd6, 0xc7, + 0x71, 0x05, 0x4b, 0x26, 0xb7, 0x07, 0x57, 0x3b, 0x9e, 0x7f, 0x18, 0x1c, 0x87, 0x3b, 0x24, 0xfe, + 0x09, 0xfe, 0x1e, 0x39, 0xee, 0x12, 0x46, 0x4e, 0xe5, 0xbf, 0x51, 0xba, 0xec, 0xd7, 0xa0, 0x16, + 0x7b, 0xf8, 0x34, 0x43, 0x59, 0x35, 0x72, 0xf2, 0xa1, 0xbd, 0x4c, 0xe8, 0x81, 0xc1, 0x71, 0x28, + 0x4d, 0x65, 0xf8, 0xdb, 0xf8, 0x1b, 0x79, 0x60, 0x82, 0x9a, 0xa7, 0x08, 0x66, 0xca, 0x37, 0x99, + 0x9d, 0xf1, 0x4d, 0x3e, 0x02, 0xa6, 0x21, 0x28, 0x97, 0x69, 0x2e, 0x72, 0x99, 0xd6, 0x63, 0x5c, + 0xe9, 0x31, 0x7d, 0x04, 0xcb, 0x52, 0x96, 0x4e, 0x36, 0x95, 0x48, 0x83, 0x91, 0x50, 0x9d, 0x68, + 0xaf, 0xf2, 0x4b, 0x0a, 0xdd, 0x9c, 0x4c, 0x61, 0xe8, 0x97, 0x54, 0x5a, 0xb9, 0x46, 0x80, 0x73, + 0x2f, 0x25, 0xc0, 0xf9, 0x19, 0x02, 0xd4, 0x2c, 0x33, 0xc5, 0xa4, 0x65, 0xc6, 0x80, 0xaa, 0xf2, + 0x3e, 0x52, 0xd0, 0x05, 0x09, 0x8e, 0x65, 0xe9, 0x82, 0xc4, 0xc0, 0x8b, 0xfb, 0x50, 0x57, 0xe6, + 0x93, 0xc8, 0xf6, 0x43, 0x01, 0x05, 0xd2, 0xfa, 0xb6, 0xa5, 0x2c, 0x40, 0x09, 0x4b, 0x7b, 0x79, + 0xca, 0xd2, 0xfe, 0x2e, 0x2c, 0x06, 0x82, 0x7e, 0xad, 0x89, 0x2b, 0xa3, 0x7f, 0xf8, 0x00, 0xd5, + 0xac, 0xa2, 0x59, 0xc7, 0x84, 0xa3, 0x18, 0x3e, 0x6b, 0xd7, 0xa8, 0xa6, 0xd8, 0x35, 0x9e, 0xc4, + 0x8e, 0xba, 0xe0, 0xcc, 0x19, 0xa1, 0xcc, 0x10, 0x47, 0xca, 0xc8, 0x01, 0xee, 0x9e, 0x39, 0x23, + 0x53, 0x79, 0x85, 0xc5, 0x87, 0xf1, 0x7f, 0x32, 0x50, 0x17, 0x74, 0x90, 0x58, 0x62, 0xdf, 0x06, + 0x64, 0x06, 0xaf, 0xb8, 0xc2, 0xca, 0x02, 0x57, 0x2d, 0xb0, 0x0f, 0x01, 0x57, 0x8c, 0x25, 0x74, + 0x4a, 0xb9, 0xbe, 0x1a, 0xc9, 0xf5, 0x15, 0xf3, 0xd0, 0xdd, 0x1b, 0xa4, 0x7b, 0x08, 0x08, 0xfb, + 0x36, 0x94, 0x04, 0x61, 0x22, 0x95, 0xc8, 0x00, 0x2d, 0x25, 0x79, 0xa5, 0xac, 0x11, 0x91, 0x75, + 0x2c, 0x3f, 0xd3, 0x7c, 0xab, 0xf9, 0x14, 0xdf, 0xaa, 0xb6, 0x80, 0x77, 0x01, 0x9e, 0xf1, 0xab, + 0x3d, 0xaf, 0x8f, 0x1a, 0xef, 0x6d, 0x00, 0x41, 0xcb, 0x27, 0xf6, 0xc8, 0x91, 0x06, 0x9b, 0x82, + 0x59, 0x7a, 0xce, 0xaf, 0x76, 0x10, 0x20, 0x26, 0x52, 0x24, 0xc7, 0xab, 0xb8, 0x60, 0x16, 0x9f, + 0xf3, 0x2b, 0x5a, 0xc2, 0x16, 0x54, 0x9f, 0xf1, 0xab, 0x6d, 0x4e, 0x42, 0xa6, 0xe7, 0x0b, 0x22, + 0xf2, 0xed, 0x0b, 0x21, 0x55, 0x26, 0xfc, 0xa2, 0x65, 0xdf, 0xbe, 0x78, 0xc6, 0xaf, 0x94, 0x8f, + 0x76, 0x5e, 0xa4, 0x0f, 0xbd, 0xbe, 0xdc, 0x37, 0x55, 0x84, 0x47, 0xdc, 0x28, 0x73, 0xee, 0x39, + 0xfe, 0x36, 0xfe, 0x32, 0x03, 0x55, 0xd1, 0x7e, 0x64, 0xcb, 0x62, 0xca, 0x54, 0xa0, 0x50, 0x26, + 0x0e, 0x14, 0x7a, 0x2c, 0xb9, 0x1a, 0xf1, 0xf8, 0xec, 0xf5, 0x3c, 0x1e, 0xe7, 0x86, 0x18, 0xfc, + 0xfb, 0x50, 0xa2, 0x65, 0x29, 0xd6, 0x79, 0x2e, 0x31, 0xc1, 0x89, 0x0e, 0x99, 0x45, 0x44, 0x7b, + 0x46, 0x71, 0x09, 0x9a, 0xf1, 0x8f, 0x86, 0xb8, 0xe4, 0x47, 0x26, 0xbf, 0x94, 0x69, 0x28, 0x5c, + 0x13, 0x97, 0xa0, 0x5b, 0xd6, 0xe6, 0x66, 0x2c, 0x6b, 0x07, 0x50, 0x14, 0x53, 0x8d, 0x9d, 0x4d, + 0x29, 0x34, 0x93, 0x56, 0xa8, 0x90, 0x04, 0x6c, 0xb1, 0x29, 0x08, 0x46, 0x97, 0x95, 0x92, 0x80, + 0x1d, 0xf0, 0x43, 0x64, 0x76, 0x19, 0x28, 0x6b, 0x2b, 0x00, 0x8d, 0x93, 0xd1, 0x78, 0xd1, 0x72, + 0x49, 0x92, 0x78, 0x62, 0xc0, 0x77, 0x6f, 0x98, 0xd5, 0x7e, 0x62, 0x06, 0x36, 0x24, 0xad, 0x62, + 0xce, 0x6c, 0x22, 0xa6, 0x49, 0x35, 0x5c, 0x11, 0xa8, 0xf8, 0xbd, 0x39, 0x07, 0x79, 0x81, 0x6a, + 0x7c, 0x0c, 0x8b, 0x5a, 0x33, 0x48, 0xcd, 0x7f, 0xd5, 0x1e, 0x1a, 0xbf, 0x12, 0x65, 0x16, 0x75, + 0x90, 0xfb, 0x48, 0xc5, 0x78, 0xf0, 0x01, 0x75, 0x5c, 0xc6, 0x92, 0x10, 0x48, 0xa0, 0xbd, 0x72, + 0xdc, 0xc1, 0xaf, 0xc1, 0x92, 0x56, 0xfa, 0x8e, 0xe3, 0xda, 0x43, 0xe7, 0x87, 0xb8, 0xe1, 0x07, + 0xce, 0xa9, 0x3b, 0x55, 0x3e, 0x81, 0xbe, 0x52, 0xf9, 0xff, 0x20, 0x0b, 0xcb, 0xb2, 0x02, 0x8c, + 0xda, 0x73, 0x84, 0x14, 0xb7, 0x1f, 0x9c, 0xb2, 0x6f, 0x43, 0x55, 0x8c, 0x8d, 0xe5, 0xf3, 0x53, + 0x27, 0x08, 0xb9, 0x72, 0x5b, 0xa5, 0x30, 0x2e, 0xb1, 0x99, 0x0b, 0x54, 0x53, 0x62, 0xb2, 0x8f, + 0xa1, 0x8c, 0x59, 0xc9, 0x8c, 0x22, 0x27, 0xa2, 0x31, 0x9b, 0x91, 0x06, 0x7a, 0xf7, 0x86, 0x09, + 0x41, 0x3c, 0xec, 0x1f, 0x43, 0x19, 0xe7, 0xf0, 0x1c, 0x07, 0x72, 0x8a, 0x55, 0xcd, 0x0c, 0xb4, + 0xc8, 0x3c, 0x8e, 0x87, 0xbd, 0x09, 0x55, 0x62, 0x56, 0x72, 0x9c, 0x64, 0x34, 0xd0, 0xfa, 0x6c, + 0x76, 0x35, 0x92, 0xa2, 0xf1, 0x63, 0xed, 0x7b, 0xb3, 0x04, 0xf3, 0xa1, 0xef, 0x9c, 0x9e, 0x72, + 0xdf, 0x58, 0x8d, 0x86, 0x46, 0x70, 0x61, 0xde, 0x0d, 0xf9, 0x58, 0xc8, 0xe6, 0xc6, 0xbf, 0xcb, + 0x40, 0x59, 0xf2, 0xd5, 0x9f, 0xd8, 0x57, 0xb6, 0xae, 0x85, 0xbd, 0x92, 0xc5, 0x26, 0x8e, 0x72, + 0xbd, 0x07, 0x0b, 0x23, 0x21, 0xa7, 0x0b, 0x3d, 0x32, 0xe1, 0x28, 0xab, 0x29, 0xb0, 0x14, 0x93, + 0x37, 0x60, 0x09, 0xa5, 0xe6, 0xc0, 0x0a, 0x9d, 0xa1, 0xa5, 0x12, 0x65, 0x88, 0xe9, 0x22, 0x25, + 0xf5, 0x9c, 0xe1, 0xbe, 0x4c, 0x10, 0xc2, 0x63, 0x10, 0xda, 0xa7, 0x5c, 0xae, 0x6d, 0xfa, 0x30, + 0x1a, 0xb0, 0x3a, 0xa5, 0x42, 0x2a, 0xf5, 0xf7, 0xff, 0x2e, 0xc2, 0xda, 0x4c, 0x92, 0x54, 0x83, + 0x23, 0x07, 0xd1, 0xd0, 0x19, 0x1d, 0x7b, 0x91, 0xf9, 0x34, 0xa3, 0x39, 0x88, 0xf6, 0x44, 0x8a, + 0x32, 0x9f, 0x72, 0x58, 0x51, 0x04, 0x89, 0xf6, 0xcf, 0x48, 0xcb, 0xcc, 0xa2, 0x0e, 0xf4, 0x7e, + 0x72, 0x13, 0x9b, 0xae, 0x4e, 0xc1, 0x75, 0xd1, 0x68, 0x69, 0x3c, 0x03, 0x0b, 0xd8, 0xaf, 0x43, + 0x23, 0xa2, 0x7b, 0x29, 0xb6, 0x6b, 0x2a, 0xb3, 0xa8, 0xe9, 0xbd, 0x97, 0xd4, 0x94, 0xb0, 0xdd, + 0xa1, 0xec, 0xb4, 0xaa, 0x96, 0x0c, 0x15, 0x18, 0xd5, 0x75, 0x0e, 0xaf, 0xab, 0xba, 0x50, 0x0c, + 0x9f, 0xad, 0x31, 0xff, 0x4a, 0x7d, 0x43, 0xbb, 0x64, 0xa2, 0x5a, 0xf3, 0x96, 0x2c, 0x38, 0x4a, + 0xd2, 0xeb, 0x3d, 0x83, 0xd5, 0x0b, 0xdb, 0x09, 0x55, 0x1f, 0x35, 0x8d, 0xbd, 0x80, 0xf5, 0x3d, + 0x7e, 0x49, 0x7d, 0x9f, 0x51, 0xe6, 0x84, 0x62, 0xb2, 0x7c, 0x31, 0x0b, 0x0c, 0xd6, 0xff, 0x49, + 0x0e, 0x6a, 0xc9, 0x52, 0x04, 0x63, 0x91, 0x9b, 0x8d, 0x92, 0x37, 0xa5, 0x10, 0x2c, 0x4d, 0xfb, + 0x1d, 0x92, 0x33, 0x67, 0x9d, 0x0e, 0xd9, 0x14, 0xa7, 0x83, 0x6e, 0xeb, 0xcf, 0xbd, 0xcc, 0xb9, + 0x9a, 0x7f, 0x25, 0xe7, 0x6a, 0x21, 0xcd, 0xb9, 0x7a, 0xbd, 0x47, 0x6e, 0xee, 0x27, 0xf2, 0xc8, + 0xcd, 0xbf, 0xd0, 0x23, 0xa7, 0xf9, 0x11, 0x8b, 0xd7, 0x58, 0xe8, 0x35, 0xcf, 0x62, 0x8a, 0x47, + 0xae, 0xf4, 0x15, 0x3c, 0x72, 0xeb, 0x7f, 0x99, 0x01, 0x36, 0xbb, 0x3a, 0xd8, 0x53, 0xf2, 0xe7, + 0xb8, 0x7c, 0x28, 0x39, 0xf7, 0xd7, 0x5f, 0x6d, 0x85, 0x29, 0x82, 0x50, 0xb9, 0xd9, 0x43, 0x58, + 0xd2, 0x03, 0xe1, 0x75, 0xad, 0xbd, 0x6a, 0x32, 0x3d, 0x29, 0xb6, 0xed, 0x68, 0x9e, 0xec, 0xfc, + 0x4b, 0x3d, 0xd9, 0x85, 0x97, 0x7a, 0xb2, 0xe7, 0x92, 0x9e, 0xec, 0xf5, 0xff, 0x94, 0x81, 0xa5, + 0x14, 0x22, 0xfe, 0xd9, 0xf5, 0x59, 0xd0, 0x5e, 0x82, 0xad, 0x65, 0x25, 0xed, 0xe9, 0x1c, 0x6d, + 0x0f, 0xca, 0xf1, 0x54, 0xa8, 0x83, 0x22, 0x0f, 0x5e, 0xc6, 0x5d, 0xe2, 0x1c, 0xa6, 0x9e, 0x7d, + 0xfd, 0xf7, 0xb3, 0x50, 0xd6, 0x12, 0xc5, 0x28, 0x12, 0xc9, 0x6a, 0x01, 0x44, 0x24, 0x19, 0xa2, + 0xcd, 0xe1, 0x0e, 0x48, 0xa7, 0x06, 0xa5, 0xd3, 0xe2, 0x92, 0x62, 0x20, 0x22, 0x6c, 0xc0, 0x92, + 0xf2, 0xb5, 0xf1, 0x38, 0x4e, 0x50, 0xee, 0x35, 0x8b, 0xd2, 0xe3, 0xc6, 0xa3, 0xb0, 0x43, 0xf6, + 0x50, 0xa9, 0x83, 0xf1, 0xdc, 0x21, 0xa9, 0x93, 0xc7, 0x60, 0x91, 0x16, 0x88, 0x9a, 0x44, 0x41, + 0xe7, 0xef, 0xc3, 0x8a, 0x5a, 0x1e, 0xc9, 0x1c, 0xe4, 0x44, 0x60, 0x72, 0x71, 0xe8, 0x59, 0xbe, + 0x0b, 0xb7, 0xa7, 0xda, 0x34, 0x95, 0x95, 0x02, 0x5a, 0x6f, 0x26, 0x5a, 0xa7, 0x97, 0xb0, 0xfe, + 0x23, 0xa8, 0x26, 0x18, 0xe5, 0xcf, 0x6e, 0xca, 0xa7, 0xed, 0x3c, 0x34, 0xa2, 0xba, 0x9d, 0x67, + 0xfd, 0x7f, 0xe7, 0x80, 0xcd, 0xf2, 0xea, 0x9f, 0x67, 0x13, 0x66, 0x09, 0x33, 0x97, 0x42, 0x98, + 0xff, 0xdf, 0xe4, 0x87, 0x77, 0x61, 0x51, 0x1e, 0x98, 0xd2, 0x1c, 0xa6, 0xb4, 0x38, 0xeb, 0x51, + 0x82, 0x6a, 0xc5, 0x87, 0xd3, 0x81, 0x1b, 0xc5, 0xc4, 0x19, 0x11, 0x4d, 0x80, 0x9a, 0x8a, 0xdf, + 0x38, 0x82, 0x39, 0xdb, 0xed, 0x9f, 0x79, 0xbe, 0xe4, 0x83, 0xbf, 0xf0, 0x95, 0xb7, 0xcf, 0x8d, + 0x26, 0xe6, 0x47, 0xa9, 0xcd, 0x94, 0x85, 0x19, 0xef, 0x43, 0x59, 0x03, 0xb3, 0x12, 0x14, 0xf6, + 0xda, 0xfb, 0x9b, 0x07, 0xf5, 0x1b, 0xac, 0x0a, 0x25, 0xb3, 0xb5, 0x75, 0xf0, 0x69, 0xcb, 0x6c, + 0x6d, 0xd7, 0x33, 0xac, 0x08, 0xf9, 0xbd, 0x83, 0x6e, 0xaf, 0x9e, 0x35, 0xd6, 0xa1, 0x21, 0x4b, + 0x9c, 0xf5, 0x59, 0xfc, 0x76, 0x3e, 0x32, 0x17, 0x62, 0xa2, 0x54, 0xd1, 0xbf, 0x01, 0x15, 0x5d, + 0xbc, 0x91, 0x14, 0x31, 0xe5, 0xb3, 0x17, 0xca, 0xb9, 0xa7, 0xf1, 0xea, 0x2d, 0x20, 0x8f, 0xed, + 0x20, 0xca, 0x96, 0x4d, 0xc8, 0xad, 0x29, 0xde, 0x41, 0x54, 0x7e, 0x12, 0x64, 0xf8, 0x57, 0xa0, + 0x96, 0x34, 0xe0, 0x4b, 0x8e, 0x94, 0xa6, 0x70, 0x8a, 0xdc, 0x09, 0x8b, 0x3e, 0xfb, 0x2e, 0xd4, + 0xa7, 0x1d, 0x00, 0x52, 0x78, 0xbe, 0x26, 0xff, 0x82, 0x93, 0xf4, 0x09, 0xb0, 0x5d, 0x58, 0x4e, + 0x13, 0xf0, 0x90, 0x3e, 0xae, 0x37, 0x52, 0xb0, 0x59, 0x21, 0x8e, 0x7d, 0x4b, 0xfa, 0x79, 0x0a, + 0x38, 0xfd, 0x6f, 0x25, 0xeb, 0xd7, 0x06, 0x7b, 0x83, 0xfe, 0x69, 0x1e, 0x9f, 0x73, 0x80, 0x18, + 0xc6, 0xea, 0x50, 0x39, 0x38, 0x6c, 0x75, 0xac, 0xad, 0xdd, 0x66, 0xa7, 0xd3, 0xda, 0xab, 0xdf, + 0x60, 0x0c, 0x6a, 0xe8, 0xab, 0xde, 0x8e, 0x60, 0x19, 0x01, 0x93, 0xfe, 0x36, 0x05, 0xcb, 0xb2, + 0x65, 0xa8, 0xb7, 0x3b, 0x53, 0xd0, 0x1c, 0x6b, 0xc0, 0xf2, 0x61, 0x8b, 0xdc, 0xdb, 0x89, 0x72, + 0xf3, 0x42, 0x69, 0x90, 0xdd, 0x15, 0x4a, 0x03, 0x1d, 0xfc, 0x93, 0xeb, 0x40, 0xc9, 0xd2, 0xbf, + 0x93, 0x81, 0x95, 0xa9, 0x84, 0xf8, 0x38, 0x07, 0x49, 0xd2, 0x49, 0x19, 0xba, 0x82, 0x40, 0xb5, + 0x9a, 0xde, 0x85, 0xc5, 0xc8, 0xf0, 0x34, 0xb5, 0x2b, 0xd5, 0xa3, 0x04, 0x85, 0xfc, 0x10, 0x96, + 0x34, 0xfb, 0xd5, 0x14, 0xaf, 0x60, 0x5a, 0x92, 0xcc, 0x60, 0xac, 0x45, 0x61, 0xf3, 0x53, 0xad, + 0x1e, 0xd0, 0x69, 0x42, 0x3d, 0x21, 0x76, 0x83, 0x25, 0xdb, 0xab, 0x3e, 0xd9, 0xa3, 0x29, 0x42, + 0x48, 0xb6, 0x56, 0x9f, 0x70, 0x55, 0xfd, 0x1f, 0xcc, 0x01, 0xfb, 0x64, 0xc2, 0xfd, 0x2b, 0x3c, + 0xae, 0x11, 0xbc, 0x2c, 0x7e, 0x51, 0x59, 0x5a, 0xb2, 0xaf, 0x74, 0x24, 0x2b, 0xed, 0x48, 0x54, + 0xfe, 0xe5, 0x47, 0xa2, 0x0a, 0x2f, 0x3b, 0x12, 0xf5, 0x26, 0x54, 0x9d, 0x53, 0xd7, 0x13, 0xac, + 0x50, 0x48, 0xc2, 0x41, 0x63, 0xee, 0x6e, 0xee, 0x7e, 0xc5, 0xac, 0x48, 0xa0, 0x90, 0x83, 0x03, + 0xf6, 0x71, 0x8c, 0xc4, 0x07, 0xa7, 0x78, 0x7c, 0x4f, 0x67, 0x82, 0xad, 0xc1, 0x29, 0x97, 0x86, + 0x25, 0xd4, 0x34, 0x54, 0x66, 0x01, 0x0f, 0xd8, 0x5b, 0x50, 0x0b, 0xbc, 0x89, 0x50, 0x2c, 0xd4, + 0x30, 0x90, 0xa3, 0xac, 0x42, 0xd0, 0x43, 0xe5, 0x15, 0x5d, 0x9a, 0x04, 0xdc, 0x1a, 0x39, 0x41, + 0x20, 0xc4, 0xb3, 0xbe, 0xe7, 0x86, 0xbe, 0x37, 0x94, 0xbe, 0xaf, 0xc5, 0x49, 0xc0, 0xf7, 0x29, + 0x65, 0x8b, 0x12, 0xd8, 0x37, 0xe3, 0x26, 0x8d, 0x6d, 0xc7, 0x0f, 0x1a, 0x80, 0x4d, 0x52, 0x3d, + 0x45, 0xf9, 0xdd, 0x76, 0xfc, 0xa8, 0x2d, 0xe2, 0x23, 0x98, 0x3a, 0xaa, 0x55, 0x9e, 0x3e, 0xaa, + 0xf5, 0x83, 0xf4, 0xa3, 0x5a, 0x55, 0x2c, 0xfa, 0x91, 0x2c, 0x7a, 0x76, 0x8a, 0xbf, 0xd2, 0x89, + 0xad, 0xd9, 0x13, 0x68, 0xb5, 0xaf, 0x72, 0x02, 0x6d, 0x21, 0xed, 0x04, 0xda, 0xfb, 0x50, 0xc6, + 0xb3, 0x41, 0xd6, 0x99, 0x23, 0x64, 0x38, 0xf2, 0xe5, 0xd5, 0xf5, 0xc3, 0x43, 0xbb, 0x8e, 0x1b, + 0x9a, 0xe0, 0xab, 0x9f, 0xc1, 0xec, 0x61, 0xb0, 0xc5, 0x9f, 0xe3, 0x61, 0x30, 0x79, 0x86, 0x69, + 0x03, 0x8a, 0x6a, 0x9e, 0x18, 0x83, 0xfc, 0x89, 0xef, 0x8d, 0x94, 0x8f, 0x43, 0xfc, 0x66, 0x35, + 0xc8, 0x86, 0x9e, 0xcc, 0x9c, 0x0d, 0x3d, 0xe3, 0x57, 0xa1, 0xac, 0x91, 0x1a, 0x7b, 0x83, 0xec, + 0x92, 0x42, 0x37, 0x93, 0xb2, 0x25, 0x8d, 0x62, 0x49, 0x42, 0xdb, 0x03, 0xc1, 0x6f, 0x06, 0x8e, + 0xcf, 0xf1, 0xd8, 0xa6, 0xe5, 0xf3, 0x73, 0xee, 0x07, 0xca, 0xe7, 0x54, 0x8f, 0x12, 0x4c, 0x82, + 0x1b, 0xbf, 0x06, 0x4b, 0x89, 0xb9, 0x95, 0x2c, 0xe2, 0x2d, 0x98, 0xc3, 0x71, 0x53, 0x31, 0x01, + 0xc9, 0x43, 0x59, 0x32, 0x0d, 0xcf, 0xe3, 0x93, 0xbb, 0xcc, 0x1a, 0xfb, 0xde, 0x31, 0x56, 0x92, + 0x31, 0xcb, 0x12, 0x76, 0xe8, 0x7b, 0xc7, 0xc6, 0x9f, 0xe7, 0x20, 0xb7, 0xeb, 0x8d, 0xf5, 0x18, + 0xb5, 0xcc, 0x4c, 0x8c, 0x9a, 0x54, 0x38, 0xad, 0x48, 0xa1, 0x94, 0x32, 0x3b, 0x3a, 0x8a, 0x94, + 0x52, 0x79, 0x1f, 0x6a, 0x82, 0x4f, 0x84, 0x9e, 0xd0, 0xd8, 0x2f, 0x6c, 0x9f, 0x04, 0xe2, 0x1c, + 0x2d, 0x3e, 0x7b, 0x14, 0xf6, 0xbc, 0x1d, 0x82, 0xb3, 0x65, 0xc8, 0x45, 0xea, 0x0b, 0x26, 0x8b, + 0x4f, 0xb6, 0x0a, 0x73, 0x18, 0xac, 0x7c, 0x25, 0x9d, 0xde, 0xf2, 0x8b, 0x7d, 0x1d, 0x96, 0x92, + 0xe5, 0x12, 0x2b, 0x92, 0xb2, 0x91, 0x5e, 0x30, 0xf2, 0xa4, 0x9b, 0x20, 0xf8, 0x08, 0xe1, 0xc8, + 0xd8, 0x99, 0x13, 0xce, 0x31, 0x49, 0x63, 0x7a, 0xc5, 0x04, 0xd3, 0xbb, 0x03, 0xe5, 0x70, 0x78, + 0x6e, 0x8d, 0xed, 0xab, 0xa1, 0x67, 0x0f, 0xe4, 0xfa, 0x86, 0x70, 0x78, 0x7e, 0x48, 0x10, 0xf6, + 0x10, 0x60, 0x34, 0x1e, 0xcb, 0xb5, 0x87, 0xce, 0x8f, 0x98, 0x94, 0xf7, 0x0f, 0x0f, 0x89, 0xe4, + 0xcc, 0xd2, 0x68, 0x3c, 0xa6, 0x9f, 0x6c, 0x1b, 0x6a, 0xa9, 0x47, 0x2b, 0x6f, 0xab, 0xd8, 0x5a, + 0x6f, 0xbc, 0x91, 0xb2, 0x38, 0xab, 0x7d, 0x1d, 0xb6, 0xfe, 0x5d, 0x60, 0x3f, 0xe5, 0x01, 0xc7, + 0x1e, 0x94, 0xa2, 0xf6, 0xe9, 0xe7, 0x03, 0x31, 0x5a, 0xbe, 0x9c, 0x38, 0x1f, 0xd8, 0x1c, 0x0c, + 0x7c, 0xc1, 0x17, 0x69, 0xc3, 0x8c, 0x58, 0x3e, 0x68, 0x3b, 0x66, 0x93, 0xf8, 0xbe, 0xf1, 0xdf, + 0x32, 0x50, 0xa0, 0xc3, 0x8a, 0x6f, 0xc3, 0x02, 0xe1, 0x47, 0xf1, 0x7e, 0xd2, 0x55, 0x4e, 0xfb, + 0x6e, 0x4f, 0x86, 0xfa, 0x89, 0x65, 0xa1, 0x1d, 0xb4, 0xce, 0x46, 0x33, 0xaf, 0x1d, 0xb6, 0xbe, + 0x03, 0xa5, 0xa8, 0x6a, 0x8d, 0x74, 0x8a, 0xaa, 0x66, 0xf6, 0x3a, 0xe4, 0xcf, 0xbc, 0xb1, 0xb2, + 0xfc, 0x40, 0x3c, 0x92, 0x26, 0xc2, 0xe3, 0xb6, 0x88, 0x3a, 0xa8, 0xf1, 0xd2, 0x62, 0x11, 0x55, + 0x82, 0x64, 0x30, 0xdb, 0xc7, 0xb9, 0x94, 0x3e, 0x1e, 0xc1, 0x82, 0xe0, 0x03, 0x5a, 0xc8, 0xca, + 0xf5, 0x9b, 0xe6, 0x3b, 0x42, 0xc2, 0xeb, 0x0f, 0x27, 0x03, 0xae, 0xdb, 0xde, 0x30, 0xbe, 0x4d, + 0xc2, 0x95, 0x64, 0x6d, 0xfc, 0x41, 0x86, 0xf8, 0x8b, 0x28, 0x97, 0xdd, 0x87, 0xbc, 0xd8, 0xdf, + 0xa6, 0x2c, 0xf1, 0xd1, 0xb1, 0x05, 0x81, 0x67, 0x22, 0x06, 0xde, 0x4e, 0x30, 0x19, 0x25, 0x4b, + 0xaf, 0x9a, 0x65, 0x77, 0x32, 0x8a, 0x4c, 0x57, 0x5f, 0x53, 0xdd, 0x9a, 0x32, 0xfb, 0x50, 0xef, + 0xa3, 0x65, 0xba, 0xa1, 0x05, 0xca, 0xe5, 0x13, 0x3b, 0xa6, 0x92, 0x02, 0x07, 0xa7, 0x5c, 0x0b, + 0x90, 0xfb, 0xe3, 0x2c, 0x54, 0x13, 0x2d, 0xc2, 0x48, 0x41, 0xb1, 0x01, 0x90, 0x63, 0x49, 0xce, + 0x37, 0x08, 0x90, 0x14, 0xd4, 0xb5, 0x71, 0xca, 0x26, 0xc6, 0x29, 0x0a, 0xce, 0xc9, 0xe9, 0xc1, + 0x39, 0x8f, 0xa0, 0x14, 0x1f, 0xb0, 0x4f, 0x36, 0x49, 0xd4, 0xa7, 0x0e, 0x6f, 0xc4, 0x48, 0x71, + 0x38, 0x4f, 0x41, 0x0f, 0xe7, 0xf9, 0x8e, 0x16, 0xfd, 0x31, 0x87, 0xc5, 0x18, 0x69, 0x23, 0xfa, + 0x73, 0x89, 0xfd, 0x30, 0x3e, 0x86, 0xb2, 0xd6, 0x78, 0x3d, 0xca, 0x23, 0x93, 0x88, 0xf2, 0x88, + 0x8e, 0x59, 0x65, 0xe3, 0x63, 0x56, 0xc6, 0xdf, 0xcc, 0x42, 0x55, 0xac, 0x2f, 0xc7, 0x3d, 0x3d, + 0xf4, 0x86, 0x4e, 0x1f, 0x1d, 0x4d, 0xd1, 0x0a, 0x93, 0x82, 0x96, 0x5a, 0x67, 0x72, 0x89, 0x91, + 0x9c, 0xa5, 0x9f, 0x26, 0x25, 0x26, 0x1d, 0x9d, 0x26, 0x35, 0xa0, 0x2a, 0x18, 0x23, 0xba, 0x8c, + 0xe2, 0xe3, 0xff, 0x66, 0xf9, 0x84, 0xf3, 0x4d, 0x3b, 0x20, 0x0e, 0xf9, 0x75, 0x58, 0x12, 0x38, + 0x78, 0x90, 0x6e, 0xe4, 0x0c, 0x87, 0x0e, 0x61, 0x92, 0xa1, 0xa9, 0x7e, 0xc2, 0xb9, 0x69, 0x87, + 0x7c, 0x5f, 0x24, 0xc8, 0xdb, 0x02, 0x8a, 0x03, 0x27, 0xb0, 0x8f, 0xe3, 0x78, 0xce, 0xe8, 0x1b, + 0x3d, 0xcb, 0xf6, 0xa5, 0xe6, 0x59, 0x26, 0x03, 0x44, 0x79, 0x64, 0x5f, 0x46, 0x9e, 0xe5, 0x29, + 0x4a, 0x9a, 0x9f, 0xa6, 0x24, 0xe3, 0xdf, 0x66, 0xa1, 0xac, 0x91, 0xe5, 0xab, 0xec, 0xae, 0xb7, + 0x67, 0x1c, 0x83, 0x25, 0xdd, 0x07, 0xf8, 0x66, 0xb2, 0x4a, 0x8c, 0x7d, 0xa1, 0x7b, 0x09, 0x34, + 0x02, 0xbe, 0x05, 0x25, 0xb1, 0xea, 0xde, 0x47, 0x13, 0xac, 0xbc, 0x55, 0x03, 0x01, 0x87, 0x93, + 0x63, 0x95, 0xf8, 0x18, 0x13, 0x0b, 0x71, 0xe2, 0x63, 0x91, 0xf8, 0xa2, 0x08, 0xeb, 0x0f, 0xa1, + 0x22, 0x4b, 0xc5, 0x39, 0xc5, 0xee, 0xc6, 0xab, 0x3e, 0x31, 0xdf, 0x66, 0x99, 0xaa, 0xa3, 0xc9, + 0x97, 0x19, 0x1f, 0xab, 0x8c, 0xc5, 0x97, 0x65, 0x7c, 0x4c, 0x1f, 0xc6, 0x4e, 0x14, 0xb4, 0x8e, + 0x71, 0x57, 0x8a, 0x8f, 0x3d, 0x84, 0x25, 0xc5, 0xae, 0x26, 0xae, 0xed, 0xba, 0xde, 0xc4, 0xed, + 0x73, 0x75, 0xfe, 0x8a, 0xc9, 0xa4, 0xa3, 0x38, 0xc5, 0x18, 0x44, 0x07, 0x74, 0x29, 0x7e, 0xeb, + 0x01, 0x14, 0x48, 0x2e, 0x27, 0xe1, 0x23, 0x9d, 0x71, 0x11, 0x0a, 0xbb, 0x0f, 0x05, 0x12, 0xcf, + 0xb3, 0xd7, 0x32, 0x1b, 0x42, 0x30, 0x9a, 0xc0, 0x44, 0xc6, 0x7d, 0x1e, 0xfa, 0x4e, 0x3f, 0x88, + 0x8f, 0x76, 0x15, 0x84, 0xfe, 0x49, 0x75, 0xc5, 0x96, 0xdb, 0x18, 0x13, 0x75, 0x54, 0xc2, 0x11, + 0x1b, 0xd3, 0x52, 0xa2, 0x0c, 0x29, 0x2e, 0x0d, 0x61, 0xf5, 0x98, 0x87, 0x17, 0x9c, 0xbb, 0xae, + 0x10, 0x86, 0xfa, 0xdc, 0x0d, 0x7d, 0x7b, 0x28, 0x26, 0x89, 0x7a, 0xf0, 0x64, 0xa6, 0xd4, 0xd8, + 0x06, 0xb2, 0x19, 0x67, 0xdc, 0x8a, 0xf2, 0x11, 0xef, 0x58, 0x39, 0x4e, 0x4b, 0x5b, 0xff, 0x15, + 0x58, 0xbf, 0x3e, 0x53, 0xca, 0x01, 0xce, 0xfb, 0x49, 0xae, 0x12, 0xf9, 0x01, 0x87, 0x9e, 0x1d, + 0x52, 0x6b, 0x74, 0xce, 0xd2, 0x81, 0xb2, 0x96, 0x12, 0xef, 0xfd, 0x19, 0x14, 0xee, 0xe8, 0x43, + 0xec, 0x48, 0xae, 0xe7, 0x8f, 0xd0, 0xef, 0x36, 0xb0, 0xe2, 0xd2, 0x33, 0xe6, 0x42, 0x0c, 0xc7, + 0x13, 0xeb, 0xc6, 0x06, 0x2c, 0xa0, 0x64, 0xaf, 0x6d, 0x74, 0x2f, 0x12, 0x06, 0x8d, 0x65, 0x60, + 0x1d, 0xe2, 0x5d, 0x7a, 0x38, 0xe7, 0x7f, 0xce, 0x41, 0x59, 0x03, 0x8b, 0xdd, 0x08, 0x03, 0x00, + 0xad, 0x81, 0x63, 0x8f, 0xb8, 0x72, 0x72, 0x56, 0xcd, 0x2a, 0x42, 0xb7, 0x25, 0x50, 0xec, 0xc5, + 0xf6, 0xf9, 0xa9, 0xe5, 0x4d, 0x42, 0x6b, 0xc0, 0x4f, 0x7d, 0xae, 0x5a, 0x59, 0xb1, 0xcf, 0x4f, + 0x0f, 0x26, 0xe1, 0x36, 0xc2, 0x04, 0x96, 0xe0, 0x25, 0x1a, 0x96, 0x8c, 0x59, 0x1b, 0xd9, 0x97, + 0x31, 0x96, 0x0c, 0x9c, 0x24, 0xca, 0xcc, 0x47, 0x81, 0x93, 0xa4, 0x2d, 0x4e, 0x6f, 0xa0, 0x85, + 0xd9, 0x0d, 0xf4, 0x9b, 0xb0, 0x4a, 0x1b, 0xa8, 0x64, 0xcd, 0xd6, 0xd4, 0x4a, 0x5e, 0xc6, 0x54, + 0xd9, 0x49, 0x4d, 0xec, 0xad, 0x8b, 0x1e, 0x28, 0xb6, 0x14, 0x38, 0x3f, 0x24, 0x46, 0x96, 0x31, + 0x45, 0xcf, 0x64, 0xe1, 0x5d, 0xe7, 0x87, 0x5c, 0x60, 0x62, 0x74, 0x8c, 0x8e, 0x29, 0xcf, 0x4f, + 0x8c, 0x1c, 0x77, 0x1a, 0xd3, 0xbe, 0x4c, 0x62, 0x96, 0x24, 0xa6, 0x7d, 0xa9, 0x63, 0x3e, 0x81, + 0xb5, 0x11, 0x1f, 0x38, 0x76, 0xb2, 0x58, 0x2b, 0x16, 0xdc, 0x96, 0x29, 0x59, 0xcb, 0xd3, 0x25, + 0xc5, 0x5d, 0x8c, 0xc6, 0x0f, 0xbd, 0xd1, 0xb1, 0x43, 0x32, 0x0b, 0xc5, 0xeb, 0xe4, 0xcd, 0x9a, + 0x3b, 0x19, 0x7d, 0x1f, 0xc1, 0x22, 0x4b, 0x60, 0x54, 0xa1, 0xdc, 0x0d, 0xbd, 0xb1, 0x9a, 0xe6, + 0x1a, 0x54, 0xe8, 0x53, 0x1e, 0x6a, 0xbc, 0x05, 0x37, 0x91, 0x25, 0xf4, 0xbc, 0xb1, 0x37, 0xf4, + 0x4e, 0xaf, 0x12, 0x76, 0xbc, 0x7f, 0x9f, 0x81, 0xa5, 0x44, 0xaa, 0x64, 0xaf, 0xdf, 0x24, 0x7e, + 0x16, 0x9d, 0x4c, 0xa3, 0x35, 0xb8, 0xa8, 0xad, 0x41, 0x42, 0x24, 0x66, 0xa6, 0x4e, 0xab, 0x35, + 0xe3, 0x1b, 0x15, 0x54, 0x46, 0x62, 0x29, 0x8d, 0x59, 0x96, 0x22, 0xf3, 0xab, 0xbb, 0x16, 0x54, + 0x11, 0xbf, 0x20, 0xcf, 0xb8, 0x0c, 0x64, 0x97, 0x73, 0xc9, 0x83, 0x02, 0xba, 0xcd, 0x4f, 0xb5, + 0x20, 0x36, 0x04, 0x06, 0xc6, 0x3f, 0xcd, 0x00, 0xc4, 0xad, 0xc3, 0xa3, 0x0a, 0x91, 0xdc, 0x42, + 0x97, 0x95, 0x69, 0x32, 0xca, 0x1b, 0x50, 0x89, 0x22, 0x96, 0x63, 0x49, 0xa8, 0xac, 0x60, 0x42, + 0x1c, 0xba, 0x07, 0x0b, 0xa7, 0x43, 0xef, 0x18, 0x25, 0x56, 0x29, 0xb7, 0x50, 0xbc, 0x5a, 0x8d, + 0xc0, 0x4a, 0x1a, 0x89, 0xe5, 0xa6, 0x7c, 0x6a, 0x50, 0xb3, 0x2e, 0x05, 0x19, 0xbf, 0x95, 0x8d, + 0x42, 0x37, 0xe3, 0x91, 0x78, 0xb1, 0x7a, 0xf7, 0x93, 0xc4, 0xd2, 0xbc, 0xc8, 0xbd, 0xf8, 0x31, + 0xd4, 0x7c, 0xda, 0x94, 0xd4, 0x8e, 0x95, 0x7f, 0xc1, 0x8e, 0x55, 0xf5, 0x13, 0x92, 0xce, 0x3b, + 0x50, 0xb7, 0x07, 0xe7, 0xdc, 0x0f, 0x1d, 0xb4, 0xd6, 0xa3, 0x7c, 0x2c, 0x83, 0x25, 0x35, 0x38, + 0x0a, 0xa2, 0xf7, 0x60, 0x41, 0x1e, 0xb4, 0x8d, 0x30, 0xe5, 0xd5, 0x3d, 0x31, 0x58, 0x20, 0x1a, + 0xff, 0x42, 0xc5, 0x8a, 0x26, 0x67, 0xf7, 0xc5, 0xa3, 0xa2, 0xf7, 0x30, 0x3b, 0xeb, 0x40, 0x95, + 0x84, 0x24, 0x9d, 0x00, 0x92, 0x1f, 0x11, 0x50, 0xba, 0x00, 0x92, 0xc3, 0x9a, 0x7f, 0x95, 0x61, + 0x35, 0xfe, 0x63, 0x06, 0xe6, 0x77, 0xbd, 0xf1, 0xae, 0x43, 0xc1, 0xfa, 0xb8, 0x4c, 0x22, 0x1f, + 0xd5, 0x9c, 0xf8, 0xc4, 0xc0, 0x9f, 0x17, 0x9c, 0x27, 0x4b, 0x15, 0xf3, 0xaa, 0x49, 0x31, 0xef, + 0x3b, 0x70, 0x0b, 0x5d, 0x80, 0xbe, 0x37, 0xf6, 0x7c, 0xb1, 0x54, 0xed, 0x21, 0x89, 0x7b, 0x9e, + 0x1b, 0x9e, 0x29, 0xde, 0x79, 0xf3, 0x84, 0xf3, 0x43, 0x0d, 0x63, 0x3f, 0x42, 0xc0, 0x13, 0x9b, + 0xc3, 0xf0, 0xdc, 0x22, 0x0d, 0x5d, 0xca, 0xa3, 0xc4, 0x51, 0x17, 0x44, 0x42, 0x0b, 0xe1, 0x28, + 0x91, 0x1a, 0xdf, 0x82, 0x52, 0x64, 0xec, 0x61, 0xef, 0x42, 0xe9, 0xcc, 0x1b, 0x4b, 0x8b, 0x50, + 0x26, 0x71, 0xe6, 0x4e, 0xf6, 0xda, 0x2c, 0x9e, 0xd1, 0x8f, 0xc0, 0xf8, 0xf3, 0x79, 0x98, 0x6f, + 0xbb, 0xe7, 0x9e, 0xd3, 0xc7, 0x68, 0xd3, 0x11, 0x1f, 0x79, 0xea, 0xb4, 0xbf, 0xf8, 0x8d, 0xb1, + 0x59, 0xf1, 0x05, 0x3c, 0x39, 0x19, 0x9b, 0x15, 0x5d, 0xbd, 0xb3, 0x02, 0x73, 0xbe, 0x7e, 0x83, + 0x4e, 0xc1, 0xc7, 0xf8, 0xf7, 0x68, 0xbf, 0x2c, 0x68, 0xb7, 0x25, 0x88, 0xb2, 0xe8, 0x66, 0x17, + 0x1c, 0x32, 0x3a, 0x7d, 0x59, 0x42, 0x08, 0x0e, 0xd8, 0x6b, 0x30, 0x2f, 0x8f, 0xb8, 0xd1, 0x99, + 0x24, 0x0a, 0x58, 0x97, 0x20, 0xa4, 0x06, 0x9f, 0x93, 0x0b, 0x37, 0x12, 0x64, 0x73, 0x66, 0x45, + 0x01, 0xb7, 0x05, 0xad, 0xdd, 0x81, 0x32, 0xe1, 0x13, 0x4a, 0x51, 0x06, 0x69, 0x22, 0x08, 0x11, + 0x52, 0x2e, 0xa2, 0x2a, 0xa5, 0x5e, 0x44, 0x85, 0xe1, 0xc4, 0x11, 0x97, 0xa5, 0x2e, 0x02, 0x5d, + 0x3f, 0xa4, 0xc1, 0xd5, 0x2d, 0x6c, 0xd2, 0xa6, 0x42, 0x87, 0x91, 0x95, 0x4d, 0xe5, 0x4d, 0xa8, + 0x9e, 0xd8, 0xc3, 0xe1, 0xb1, 0xdd, 0x7f, 0x4e, 0xa6, 0x80, 0x0a, 0x59, 0x3f, 0x15, 0x10, 0x6d, + 0x01, 0x77, 0xa0, 0xac, 0xcd, 0x32, 0x46, 0x60, 0xe6, 0x4d, 0x88, 0xe7, 0x77, 0xda, 0xc2, 0x57, + 0x7b, 0x05, 0x0b, 0x9f, 0x16, 0x89, 0xba, 0x90, 0x8c, 0x44, 0xbd, 0x85, 0xdc, 0x54, 0x86, 0x1c, + 0xd6, 0xe9, 0xae, 0x1b, 0x7b, 0x30, 0xc0, 0x90, 0x43, 0xba, 0x58, 0x12, 0x07, 0x8f, 0xd2, 0x17, + 0x49, 0x97, 0x20, 0x18, 0xa1, 0xdc, 0x26, 0x33, 0xf5, 0xd8, 0x76, 0x06, 0x78, 0xe8, 0x80, 0xac, + 0x07, 0xf3, 0xf6, 0x28, 0x3c, 0xb4, 0x9d, 0x01, 0xbb, 0x0b, 0x15, 0x95, 0x8c, 0xbb, 0xe3, 0x12, + 0x8d, 0xbf, 0x4c, 0x16, 0x7b, 0xa2, 0x01, 0xd5, 0x08, 0x63, 0x14, 0x9f, 0x28, 0x2e, 0x4b, 0x14, + 0xa4, 0x83, 0xf7, 0x31, 0xca, 0x27, 0xe4, 0x78, 0x6e, 0xb8, 0xf6, 0xf8, 0x56, 0x14, 0x7c, 0x80, + 0x54, 0xaa, 0xfe, 0x93, 0x73, 0x8c, 0x30, 0x85, 0x70, 0x47, 0x3e, 0xba, 0xd5, 0x84, 0xfc, 0x2b, + 0x51, 0xd1, 0x47, 0x47, 0x08, 0xec, 0x5b, 0x9a, 0xfe, 0xda, 0x40, 0xe4, 0xd7, 0xa6, 0xca, 0xbf, + 0xee, 0xcc, 0xd5, 0x6d, 0x00, 0x27, 0x10, 0xbb, 0x4c, 0xc0, 0xdd, 0x01, 0x1e, 0x01, 0x2e, 0x9a, + 0x25, 0x27, 0x78, 0x46, 0x80, 0x9f, 0xad, 0x62, 0xdb, 0x84, 0x8a, 0xde, 0x4d, 0x56, 0x84, 0xfc, + 0xc1, 0x61, 0xab, 0x53, 0xbf, 0xc1, 0xca, 0x30, 0xdf, 0x6d, 0xf5, 0x7a, 0x7b, 0xe8, 0xe9, 0xab, + 0x40, 0x31, 0x3a, 0xa7, 0x98, 0x15, 0x5f, 0xcd, 0xad, 0xad, 0xd6, 0x61, 0xaf, 0xb5, 0x5d, 0xcf, + 0x7d, 0x2f, 0x5f, 0xcc, 0xd6, 0x73, 0xc6, 0x5f, 0xe4, 0xa0, 0xac, 0x8d, 0xc2, 0x8b, 0x99, 0xf1, + 0x6d, 0x00, 0xd4, 0x24, 0xe3, 0x88, 0xd4, 0xbc, 0x59, 0x12, 0x10, 0x9a, 0x7c, 0xdd, 0x47, 0x91, + 0xa3, 0x4b, 0x94, 0x94, 0x8f, 0xe2, 0x4d, 0xa8, 0xd2, 0x7d, 0x44, 0xba, 0xbf, 0xb6, 0x60, 0x56, + 0x08, 0x28, 0x59, 0x35, 0x1e, 0x60, 0x46, 0x24, 0x3c, 0x3d, 0x27, 0x6f, 0x27, 0x21, 0x10, 0x9e, + 0x9f, 0xc3, 0xc3, 0x8f, 0x81, 0x37, 0x3c, 0xe7, 0x84, 0x41, 0x12, 0x61, 0x59, 0xc2, 0x7a, 0xf2, + 0x28, 0xb6, 0xe4, 0x87, 0xda, 0x09, 0xda, 0x82, 0x59, 0x21, 0xa0, 0xac, 0xe8, 0xeb, 0x8a, 0x80, + 0x28, 0x7a, 0x65, 0x6d, 0x96, 0x1a, 0x12, 0xc4, 0xb3, 0x37, 0x63, 0x46, 0x2c, 0x21, 0x61, 0x7c, + 0x6d, 0x36, 0xdf, 0xcb, 0xcd, 0x89, 0xec, 0x5d, 0x60, 0xa3, 0xf1, 0xd8, 0x4a, 0x31, 0xf0, 0xe5, + 0xcd, 0x85, 0xd1, 0x78, 0xdc, 0xd3, 0xec, 0x5f, 0x3f, 0x03, 0xdb, 0xe3, 0x17, 0xc0, 0x9a, 0x62, + 0x01, 0x63, 0x13, 0x23, 0x55, 0x2c, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, 0x70, 0xbf, 0x6c, 0x2a, + 0xf7, 0x7b, 0x11, 0x9f, 0x30, 0x76, 0xa0, 0x7c, 0xa8, 0xdd, 0x76, 0x76, 0x57, 0xec, 0x10, 0xea, + 0x9e, 0x33, 0xda, 0x3b, 0xc8, 0xa6, 0xe8, 0xcb, 0xeb, 0xcd, 0xb4, 0xd6, 0x64, 0xb5, 0xd6, 0x18, + 0xff, 0x38, 0x43, 0x37, 0xc9, 0x44, 0x8d, 0x8f, 0x2f, 0x58, 0x53, 0xee, 0xb7, 0xf8, 0xa0, 0x7b, + 0x59, 0xb9, 0xdd, 0xe4, 0x19, 0x75, 0x6c, 0x9a, 0xe5, 0x9d, 0x9c, 0x04, 0x5c, 0xc5, 0x78, 0x94, + 0x11, 0x76, 0x80, 0x20, 0x25, 0x7c, 0x0b, 0x09, 0xdf, 0xa1, 0xf2, 0x03, 0x19, 0xd8, 0x21, 0x84, + 0xef, 0x7d, 0xfb, 0x52, 0xd6, 0x1a, 0x08, 0x11, 0x44, 0xfa, 0x07, 0xd4, 0x59, 0xd8, 0xe8, 0xdb, + 0xf8, 0x87, 0xf2, 0x2c, 0xfe, 0xf4, 0xf8, 0x3e, 0x80, 0x62, 0x54, 0x6a, 0x72, 0x87, 0x55, 0x98, + 0x51, 0xba, 0xd8, 0xc7, 0xd1, 0x18, 0x92, 0x68, 0x31, 0x2d, 0x2e, 0xf4, 0xf1, 0xb4, 0xb5, 0x56, + 0xbf, 0x07, 0xec, 0xc4, 0xf1, 0xa7, 0x91, 0x69, 0xb1, 0xd5, 0x31, 0x45, 0xc3, 0x36, 0x8e, 0x60, + 0x49, 0x71, 0x09, 0x4d, 0x23, 0x48, 0x4e, 0x5e, 0xe6, 0x25, 0x4c, 0x3e, 0x3b, 0xc3, 0xe4, 0x8d, + 0xdf, 0x2c, 0xc0, 0xbc, 0xba, 0x39, 0x30, 0xed, 0xb6, 0xbb, 0x52, 0xf2, 0xb6, 0xbb, 0x46, 0xe2, + 0x66, 0x24, 0x9c, 0x7a, 0xb9, 0xdf, 0xdf, 0x9b, 0xde, 0xb2, 0x35, 0x5f, 0x45, 0x62, 0xdb, 0x96, + 0xbe, 0x8a, 0x42, 0xd2, 0x57, 0x91, 0x76, 0x03, 0x20, 0x89, 0x9e, 0x33, 0x37, 0x00, 0xde, 0x02, + 0x92, 0x23, 0xb4, 0xe0, 0xb6, 0x22, 0x02, 0xc4, 0x9e, 0x93, 0x14, 0x3b, 0x8a, 0xd3, 0x62, 0xc7, + 0x2b, 0x8b, 0x04, 0xdf, 0x84, 0x39, 0xba, 0x3d, 0x43, 0x9e, 0xed, 0x55, 0x1b, 0x87, 0x1c, 0x2b, + 0xf5, 0x9f, 0x4e, 0x3c, 0x98, 0x12, 0x57, 0xbf, 0x4e, 0xab, 0x9c, 0xb8, 0x4e, 0x4b, 0xf7, 0xa1, + 0x54, 0x92, 0x3e, 0x94, 0xfb, 0x50, 0x8f, 0x06, 0x0e, 0x2d, 0x92, 0x6e, 0x20, 0x4f, 0x0e, 0xd6, + 0x14, 0x5c, 0x70, 0xc3, 0x4e, 0x10, 0x6f, 0x7c, 0xb5, 0xc4, 0xc6, 0x27, 0x78, 0x55, 0x33, 0x0c, + 0xf9, 0x68, 0x1c, 0xaa, 0x8d, 0x4f, 0xbb, 0x74, 0x91, 0x66, 0x7e, 0x01, 0x67, 0x5e, 0x4d, 0x2f, + 0x51, 0xc7, 0x26, 0xd4, 0x4e, 0x6c, 0x67, 0x38, 0xf1, 0xb9, 0xe5, 0x73, 0x3b, 0xf0, 0x5c, 0x5c, + 0xfc, 0xf1, 0x1e, 0x2c, 0xbb, 0xb8, 0x43, 0x38, 0x26, 0xa2, 0x98, 0xd5, 0x13, 0xfd, 0x13, 0x0f, + 0x31, 0xe9, 0x23, 0x21, 0xb6, 0x2c, 0x79, 0x44, 0x98, 0x62, 0x55, 0xda, 0x1d, 0x6b, 0x67, 0xaf, + 0xfd, 0x74, 0xb7, 0x57, 0xcf, 0x88, 0xcf, 0xee, 0xd1, 0xd6, 0x56, 0xab, 0xb5, 0x8d, 0x5b, 0x18, + 0xc0, 0xdc, 0x4e, 0xb3, 0xbd, 0x27, 0x37, 0xb0, 0x7c, 0xbd, 0x60, 0xfc, 0x4e, 0x16, 0xca, 0x5a, + 0x6f, 0xd8, 0x93, 0x68, 0x12, 0xe8, 0x82, 0xa7, 0xdb, 0xb3, 0x3d, 0xde, 0x50, 0x1c, 0x5e, 0x9b, + 0x85, 0xe8, 0x7a, 0xc5, 0xec, 0xb5, 0xd7, 0x2b, 0xb2, 0xb7, 0x61, 0xc1, 0xa6, 0x12, 0xa2, 0x41, + 0x97, 0xc6, 0x7d, 0x09, 0x96, 0x63, 0x8e, 0x11, 0xa4, 0xf1, 0x36, 0x25, 0xf0, 0xf2, 0x2a, 0x68, + 0x33, 0xda, 0xa9, 0x70, 0x6e, 0xe6, 0xe5, 0xc8, 0x48, 0x67, 0x7c, 0xb4, 0xe1, 0xcb, 0xf1, 0x52, + 0xc9, 0xc6, 0x07, 0x00, 0x71, 0x9b, 0x93, 0x43, 0x74, 0x23, 0x39, 0x44, 0x19, 0x6d, 0x88, 0xb2, + 0xc6, 0x3f, 0x97, 0xec, 0x49, 0x8e, 0x77, 0x64, 0xce, 0xfb, 0x3a, 0x28, 0x03, 0xa3, 0x85, 0x81, + 0xdc, 0xe3, 0x21, 0x0f, 0xd5, 0x7d, 0x04, 0x8b, 0x32, 0xa5, 0x1d, 0x25, 0xcc, 0xb0, 0xd3, 0xec, + 0x2c, 0x3b, 0x7d, 0x03, 0x2a, 0x82, 0x95, 0x4a, 0x62, 0x09, 0x24, 0x4b, 0x2a, 0x8f, 0xec, 0x4b, + 0x55, 0x77, 0x82, 0x8f, 0xe6, 0xa7, 0xf8, 0xe8, 0xef, 0x66, 0xe8, 0x7a, 0x90, 0xb8, 0xa1, 0x31, + 0x23, 0x8d, 0xca, 0x4c, 0x32, 0x52, 0x89, 0x6a, 0x46, 0xe9, 0xd7, 0x30, 0xc7, 0x6c, 0x3a, 0x73, + 0x4c, 0x67, 0xbb, 0xb9, 0x54, 0xb6, 0x6b, 0xac, 0x43, 0x63, 0x9b, 0x8b, 0xa1, 0x68, 0x0e, 0x87, + 0x53, 0x63, 0x69, 0xdc, 0x82, 0x9b, 0x29, 0x69, 0xd2, 0x32, 0xf3, 0x09, 0xac, 0x34, 0xe9, 0xde, + 0x84, 0x9f, 0xd5, 0x01, 0x49, 0xa3, 0x01, 0xab, 0xd3, 0x45, 0xca, 0xca, 0x76, 0x60, 0x71, 0x9b, + 0x1f, 0x4f, 0x4e, 0xf7, 0xf8, 0x79, 0x5c, 0x11, 0x83, 0x7c, 0x70, 0xe6, 0x5d, 0xc8, 0xc9, 0xc5, + 0xdf, 0x18, 0x7a, 0x29, 0x70, 0xac, 0x60, 0xcc, 0xfb, 0xca, 0x3a, 0x8f, 0x90, 0xee, 0x98, 0xf7, + 0x8d, 0x27, 0xc0, 0xf4, 0x72, 0xe4, 0x4c, 0x08, 0xd5, 0x69, 0x72, 0x6c, 0x05, 0x57, 0x41, 0xc8, + 0x47, 0xea, 0x60, 0x20, 0x04, 0x93, 0xe3, 0x2e, 0x41, 0x8c, 0x7b, 0x50, 0x39, 0xb4, 0xaf, 0x4c, + 0xfe, 0x85, 0x3c, 0x7f, 0xb7, 0x06, 0xf3, 0x63, 0xfb, 0x4a, 0xf0, 0xcc, 0xc8, 0x51, 0x87, 0xc9, + 0xc6, 0x1f, 0xe6, 0x61, 0x8e, 0x30, 0xd9, 0x5d, 0xba, 0xa0, 0xd8, 0x71, 0x91, 0x67, 0xa9, 0xdd, + 0x43, 0x03, 0xcd, 0x6c, 0x30, 0xd9, 0xd9, 0x0d, 0x46, 0x5a, 0x15, 0xd5, 0xc5, 0x4c, 0xca, 0xa5, + 0xe2, 0x4e, 0x46, 0xea, 0x36, 0xa6, 0xe4, 0xe5, 0x01, 0xf9, 0xf8, 0x02, 0x6a, 0x3a, 0x59, 0x9d, + 0x74, 0x7a, 0xc7, 0x0a, 0x1a, 0xb5, 0x4e, 0xed, 0x9b, 0x72, 0x6f, 0xd1, 0x41, 0xa9, 0x5a, 0xe0, + 0xbc, 0x3a, 0x54, 0x9a, 0xd4, 0x02, 0x67, 0xb4, 0xbd, 0xe2, 0xcb, 0xb5, 0x3d, 0x32, 0x37, 0xbe, + 0x40, 0xdb, 0x83, 0x57, 0xd0, 0xf6, 0x5e, 0xc1, 0xe1, 0x7c, 0x13, 0x8a, 0x28, 0x0c, 0x69, 0x5b, + 0x8d, 0x10, 0x82, 0xc4, 0x56, 0xf3, 0xa1, 0xa6, 0x0f, 0x51, 0xb4, 0x8b, 0xc6, 0xeb, 0x4d, 0xfe, + 0xc5, 0xcf, 0xc7, 0x91, 0xf7, 0x39, 0xcc, 0x4b, 0xa8, 0x20, 0x68, 0xd7, 0x1e, 0xa9, 0xbb, 0xed, + 0xf0, 0xb7, 0x18, 0x36, 0xbc, 0x90, 0xeb, 0x8b, 0x89, 0xe3, 0xf3, 0x81, 0xba, 0xb4, 0xc8, 0xc1, + 0x35, 0x2a, 0x20, 0xa2, 0x83, 0x42, 0x37, 0x73, 0xbd, 0x0b, 0x57, 0xf2, 0x9e, 0x79, 0x27, 0x78, + 0x26, 0x3e, 0x0d, 0x06, 0x75, 0xbc, 0xdd, 0x72, 0xec, 0xf9, 0x6a, 0x27, 0x37, 0xfe, 0x28, 0x03, + 0x75, 0xb9, 0xba, 0xa2, 0x34, 0x5d, 0x35, 0x2a, 0x5c, 0x17, 0x9c, 0xf1, 0xe2, 0x2b, 0x88, 0x0c, + 0xa8, 0xa2, 0x45, 0x28, 0xda, 0xd6, 0xc9, 0xa2, 0x55, 0x16, 0xc0, 0x1d, 0xb9, 0xb5, 0xbf, 0x0e, + 0x65, 0x15, 0x18, 0x3e, 0x72, 0x86, 0xea, 0xae, 0x79, 0x8a, 0x0c, 0xdf, 0x77, 0x86, 0x4a, 0x2a, + 0xf0, 0x6d, 0x79, 0xc8, 0x39, 0x83, 0x52, 0x81, 0x69, 0x87, 0xdc, 0xf8, 0xd7, 0x19, 0x58, 0xd4, + 0xba, 0x22, 0xd7, 0xed, 0x47, 0x50, 0x89, 0xae, 0x95, 0xe5, 0x91, 0x38, 0xba, 0x96, 0x64, 0x34, + 0x71, 0xb6, 0x72, 0x3f, 0x82, 0x04, 0xa2, 0x31, 0x03, 0xfb, 0x8a, 0xa2, 0x97, 0x27, 0x23, 0xa5, + 0xf1, 0x0d, 0xec, 0xab, 0x1d, 0xce, 0xbb, 0x93, 0x91, 0xd0, 0xe7, 0x2f, 0x38, 0x7f, 0x1e, 0x21, + 0x10, 0xfb, 0x04, 0x01, 0x93, 0x18, 0x06, 0x54, 0x47, 0x9e, 0x1b, 0x9e, 0x45, 0x28, 0x52, 0x14, + 0x47, 0x20, 0xe1, 0x18, 0x7f, 0x96, 0x85, 0x25, 0xb2, 0x3b, 0x4a, 0x7b, 0xaf, 0x64, 0x5d, 0x0d, + 0x98, 0x23, 0x13, 0x2c, 0x31, 0xaf, 0xdd, 0x1b, 0xa6, 0xfc, 0x66, 0xdf, 0x7c, 0x45, 0x5b, 0xa9, + 0x3a, 0x47, 0x7d, 0xcd, 0xf0, 0xe7, 0x66, 0x87, 0xff, 0xfa, 0xe1, 0x4d, 0xf3, 0xfe, 0x16, 0xd2, + 0xbc, 0xbf, 0xaf, 0xe2, 0x73, 0x9d, 0x39, 0xf1, 0x3b, 0x2f, 0x71, 0xb4, 0x13, 0xbf, 0x4f, 0x60, + 0x2d, 0x81, 0x83, 0xdc, 0xda, 0x39, 0x71, 0xb8, 0xba, 0x74, 0x66, 0x59, 0xc3, 0xee, 0xaa, 0xb4, + 0xcd, 0x79, 0x28, 0x04, 0x7d, 0x6f, 0xcc, 0x8d, 0x55, 0x58, 0x4e, 0x8e, 0xaa, 0xdc, 0x26, 0x7e, + 0x2f, 0x03, 0x0d, 0x19, 0xab, 0xe3, 0xb8, 0xa7, 0xbb, 0x4e, 0x10, 0x7a, 0x7e, 0x74, 0xfd, 0xea, + 0x6d, 0x80, 0x20, 0xb4, 0x7d, 0xa9, 0x82, 0xcb, 0x6b, 0x56, 0x10, 0x82, 0xea, 0xf5, 0x4d, 0x28, + 0x72, 0x77, 0x40, 0x89, 0x44, 0x0d, 0xf3, 0xdc, 0x1d, 0x28, 0xe5, 0x7c, 0x66, 0x2b, 0xad, 0x26, + 0x85, 0x04, 0x79, 0xeb, 0x81, 0x18, 0x1d, 0x7e, 0x8e, 0x5b, 0x7a, 0x3e, 0xba, 0xf5, 0x60, 0xdf, + 0xbe, 0xc4, 0xc8, 0xd7, 0xc0, 0xf8, 0x7b, 0x59, 0x58, 0x88, 0xdb, 0x47, 0x57, 0xa6, 0xbc, 0xf8, + 0xf2, 0x97, 0xbb, 0x92, 0x1c, 0x1c, 0xa1, 0xd4, 0x68, 0xd6, 0xd8, 0x22, 0x2d, 0xce, 0xb6, 0xcb, + 0x0c, 0x28, 0x2b, 0x0c, 0x6f, 0x12, 0x6a, 0xb7, 0x20, 0x96, 0x08, 0xe5, 0x60, 0x12, 0x0a, 0x2d, + 0x54, 0xa8, 0xe3, 0x8e, 0x2b, 0xf5, 0xc0, 0x82, 0x3d, 0x0a, 0xdb, 0xf8, 0xb8, 0x82, 0x00, 0x8b, + 0x6c, 0x34, 0x91, 0x02, 0x4b, 0xe0, 0xd7, 0x49, 0x29, 0xa1, 0x99, 0x43, 0x85, 0x44, 0x97, 0xd8, + 0xe9, 0x9e, 0xe9, 0x48, 0x62, 0x7f, 0x1d, 0xca, 0x54, 0x78, 0x7c, 0xc0, 0x3b, 0x6f, 0x96, 0xb0, + 0x06, 0x4c, 0x97, 0x96, 0x31, 0x6f, 0x92, 0xb0, 0x07, 0x00, 0x55, 0x85, 0xa1, 0x30, 0x7f, 0x2b, + 0x03, 0x37, 0x53, 0xa6, 0x4d, 0xae, 0xf2, 0x2d, 0x58, 0x3c, 0x89, 0x12, 0xd5, 0xe8, 0xd2, 0x52, + 0x5f, 0x55, 0x6c, 0x35, 0x39, 0xa6, 0x66, 0xfd, 0x24, 0x09, 0x88, 0x35, 0x51, 0x9a, 0xc1, 0xc4, + 0xf5, 0x01, 0x28, 0x12, 0xd1, 0x34, 0x92, 0x12, 0x78, 0x08, 0xeb, 0xad, 0x4b, 0xc1, 0x31, 0xb6, + 0xf4, 0xd7, 0x41, 0x14, 0x19, 0x25, 0xad, 0xee, 0x99, 0x57, 0xb2, 0xba, 0x0f, 0xe8, 0xbc, 0x71, + 0x54, 0xd6, 0x4f, 0x52, 0x08, 0x6e, 0xa0, 0x22, 0x0f, 0xbd, 0x6e, 0xa2, 0xee, 0x11, 0xe8, 0x47, + 0xaf, 0x9a, 0x18, 0x01, 0x2c, 0xec, 0x4f, 0x86, 0xa1, 0x13, 0x3f, 0x74, 0xc2, 0xbe, 0x29, 0xf3, + 0x60, 0x3d, 0x6a, 0xd4, 0x52, 0x2b, 0x82, 0xa8, 0x22, 0x1c, 0xac, 0x91, 0x28, 0xc8, 0x9a, 0xad, + 0x6f, 0x61, 0x94, 0xac, 0xc1, 0xb8, 0x09, 0x6b, 0xf1, 0x17, 0x0d, 0x9b, 0xda, 0x6a, 0xfe, 0x51, + 0x86, 0xc2, 0xec, 0x93, 0x8f, 0xae, 0xb0, 0x16, 0x2c, 0x05, 0x8e, 0x7b, 0x3a, 0xe4, 0x7a, 0xf1, + 0x81, 0x1c, 0x84, 0x95, 0x64, 0xdb, 0xe4, 0xc3, 0x2c, 0xe6, 0x22, 0xe5, 0x88, 0x4b, 0x0b, 0xd8, + 0xe6, 0x75, 0x8d, 0x8c, 0xc9, 0x62, 0x6a, 0x34, 0x66, 0x1b, 0xdf, 0x86, 0x5a, 0xb2, 0x22, 0xf6, + 0xa1, 0x3c, 0xa6, 0x1f, 0xb7, 0x2a, 0x37, 0x75, 0x86, 0x39, 0x26, 0x88, 0x72, 0x3c, 0xf6, 0x81, + 0xf1, 0x77, 0x32, 0xd0, 0x30, 0xb9, 0xa0, 0x5c, 0xad, 0x95, 0x8a, 0x66, 0x3e, 0x9a, 0x29, 0xf5, + 0xfa, 0xbe, 0xaa, 0xd3, 0xff, 0xaa, 0x45, 0xef, 0x5d, 0x3b, 0x19, 0xbb, 0x37, 0x66, 0x7a, 0xb4, + 0x59, 0x84, 0x39, 0x42, 0x31, 0xd6, 0x60, 0x45, 0xb6, 0x47, 0xb5, 0x25, 0x76, 0xa9, 0x26, 0x6a, + 0x4c, 0xb8, 0x54, 0xd7, 0xa1, 0x41, 0xe7, 0x71, 0xf5, 0x4e, 0xc8, 0x8c, 0xdb, 0xc0, 0xf6, 0xed, + 0xbe, 0xed, 0x7b, 0x9e, 0x7b, 0xc8, 0x7d, 0x19, 0xb4, 0x8c, 0x12, 0x26, 0x7a, 0x1c, 0x95, 0x28, + 0x4c, 0x5f, 0xea, 0xee, 0x57, 0xcf, 0x55, 0x31, 0x5a, 0xf4, 0x65, 0x98, 0xb0, 0xb4, 0x69, 0x3f, + 0xe7, 0xaa, 0x24, 0x35, 0x44, 0x1f, 0x43, 0x79, 0x1c, 0x15, 0xaa, 0xc6, 0x5d, 0x5d, 0x23, 0x32, + 0x5b, 0xad, 0xa9, 0x63, 0x1b, 0x8f, 0x61, 0x39, 0x59, 0xa6, 0x64, 0x1d, 0xeb, 0x50, 0x1c, 0x49, + 0x98, 0x6c, 0x5d, 0xf4, 0x6d, 0xfc, 0x76, 0x11, 0xe6, 0xa5, 0x36, 0xca, 0x36, 0x20, 0xdf, 0x57, + 0x71, 0x72, 0xf1, 0xed, 0x54, 0x32, 0x55, 0xfd, 0xdf, 0xc2, 0x68, 0x39, 0x81, 0xc7, 0x3e, 0x86, + 0x5a, 0xd2, 0x55, 0x3c, 0x75, 0xda, 0x3f, 0xe9, 0xe3, 0xad, 0xf6, 0xa7, 0x9c, 0x82, 0xa5, 0x78, + 0x73, 0x24, 0x99, 0xa1, 0x78, 0xa6, 0xed, 0x9e, 0x9e, 0x2b, 0xe4, 0xed, 0xe0, 0xcc, 0xb6, 0x1e, + 0x3f, 0xf9, 0x40, 0x1e, 0xf7, 0x2f, 0x23, 0xb0, 0x7b, 0x66, 0x3f, 0x7e, 0xf2, 0xc1, 0xb4, 0x24, + 0x2d, 0x0f, 0xfb, 0x6b, 0x92, 0xf4, 0x32, 0x14, 0xe8, 0x92, 0x53, 0x0a, 0x78, 0xa2, 0x0f, 0xf6, + 0x08, 0x96, 0x95, 0x81, 0x43, 0x86, 0xa6, 0x13, 0x17, 0x2c, 0xd2, 0x69, 0x40, 0x99, 0xd6, 0xc5, + 0x24, 0x32, 0x89, 0xac, 0xc2, 0xdc, 0x59, 0x7c, 0x63, 0x6d, 0xd5, 0x94, 0x5f, 0xc6, 0x9f, 0x15, + 0xa0, 0xac, 0x0d, 0x0a, 0xab, 0x40, 0xd1, 0x6c, 0x75, 0x5b, 0xe6, 0xa7, 0xad, 0xed, 0xfa, 0x0d, + 0x76, 0x1f, 0xde, 0x6a, 0x77, 0xb6, 0x0e, 0x4c, 0xb3, 0xb5, 0xd5, 0xb3, 0x0e, 0x4c, 0x4b, 0xdd, + 0x91, 0x76, 0xd8, 0xfc, 0x7c, 0xbf, 0xd5, 0xe9, 0x59, 0xdb, 0xad, 0x5e, 0xb3, 0xbd, 0xd7, 0xad, + 0x67, 0xd8, 0x6b, 0xd0, 0x88, 0x31, 0x55, 0x72, 0x73, 0xff, 0xe0, 0xa8, 0xd3, 0xab, 0x67, 0xd9, + 0x1d, 0xb8, 0xb5, 0xd3, 0xee, 0x34, 0xf7, 0xac, 0x18, 0x67, 0x6b, 0xaf, 0xf7, 0xa9, 0xd5, 0xfa, + 0xa5, 0xc3, 0xb6, 0xf9, 0x79, 0x3d, 0x97, 0x86, 0xb0, 0xdb, 0xdb, 0xdb, 0x52, 0x25, 0xe4, 0xd9, + 0x4d, 0x58, 0x21, 0x04, 0xca, 0x62, 0xf5, 0x0e, 0x0e, 0xac, 0xee, 0xc1, 0x41, 0xa7, 0x5e, 0x60, + 0x8b, 0x50, 0x6d, 0x77, 0x3e, 0x6d, 0xee, 0xb5, 0xb7, 0x2d, 0xb3, 0xd5, 0xdc, 0xdb, 0xaf, 0xcf, + 0xb1, 0x25, 0x58, 0x98, 0xc6, 0x9b, 0x17, 0x45, 0x28, 0xbc, 0x83, 0x4e, 0xfb, 0xa0, 0x63, 0x7d, + 0xda, 0x32, 0xbb, 0xed, 0x83, 0x4e, 0xbd, 0xc8, 0x56, 0x81, 0x25, 0x93, 0x76, 0xf7, 0x9b, 0x5b, + 0xf5, 0x12, 0x5b, 0x81, 0xc5, 0x24, 0xfc, 0x59, 0xeb, 0xf3, 0x3a, 0xb0, 0x06, 0x2c, 0x53, 0xc3, + 0xac, 0xcd, 0xd6, 0xde, 0xc1, 0x67, 0xd6, 0x7e, 0xbb, 0xd3, 0xde, 0x3f, 0xda, 0xaf, 0x97, 0xf1, + 0xea, 0xc5, 0x56, 0xcb, 0x6a, 0x77, 0xba, 0x47, 0x3b, 0x3b, 0xed, 0xad, 0x76, 0xab, 0xd3, 0xab, + 0x57, 0xa8, 0xe6, 0xb4, 0x8e, 0x57, 0x45, 0x06, 0x79, 0x7e, 0xc5, 0xda, 0x6e, 0x77, 0x9b, 0x9b, + 0x7b, 0xad, 0xed, 0x7a, 0x8d, 0xdd, 0x86, 0x9b, 0xbd, 0xd6, 0xfe, 0xe1, 0x81, 0xd9, 0x34, 0x3f, + 0x57, 0xe7, 0x5b, 0xac, 0x9d, 0x66, 0x7b, 0xef, 0xc8, 0x6c, 0xd5, 0x17, 0xd8, 0x1b, 0x70, 0xdb, + 0x6c, 0x7d, 0x72, 0xd4, 0x36, 0x5b, 0xdb, 0x56, 0xe7, 0x60, 0xbb, 0x65, 0xed, 0xb4, 0x9a, 0xbd, + 0x23, 0xb3, 0x65, 0xed, 0xb7, 0xbb, 0xdd, 0x76, 0xe7, 0x69, 0xbd, 0xce, 0xde, 0x82, 0xbb, 0x11, + 0x4a, 0x54, 0xc0, 0x14, 0xd6, 0xa2, 0xe8, 0x9f, 0x9a, 0xd2, 0x4e, 0xeb, 0x97, 0x7a, 0xd6, 0x61, + 0xab, 0x65, 0xd6, 0x19, 0x5b, 0x87, 0xd5, 0xb8, 0x7a, 0xaa, 0x40, 0xd6, 0xbd, 0x24, 0xd2, 0x0e, + 0x5b, 0xe6, 0x7e, 0xb3, 0x23, 0x26, 0x38, 0x91, 0xb6, 0x2c, 0x9a, 0x1d, 0xa7, 0x4d, 0x37, 0x7b, + 0x85, 0x31, 0xa8, 0x69, 0xb3, 0xb2, 0xd3, 0x34, 0xeb, 0xab, 0x6c, 0x01, 0xca, 0xfb, 0x87, 0x87, + 0x56, 0xaf, 0xbd, 0xdf, 0x3a, 0x38, 0xea, 0xd5, 0xd7, 0xd8, 0x0a, 0xd4, 0xdb, 0x9d, 0x5e, 0xcb, + 0x14, 0x73, 0xad, 0xb2, 0xfe, 0xcf, 0x79, 0xb6, 0x0c, 0x0b, 0xaa, 0xa5, 0x0a, 0xfa, 0xe3, 0x79, + 0xb6, 0x06, 0xec, 0xa8, 0x63, 0xb6, 0x9a, 0xdb, 0x62, 0xe0, 0xa2, 0x84, 0xff, 0x35, 0x2f, 0xdd, + 0x46, 0x7f, 0x94, 0x8b, 0x36, 0xeb, 0x38, 0x0e, 0x23, 0x79, 0x7f, 0x79, 0x45, 0xbb, 0x77, 0xfc, + 0x65, 0x2f, 0x8b, 0x68, 0xaa, 0x55, 0x6e, 0x46, 0xb5, 0x9a, 0xd1, 0xdd, 0xab, 0xba, 0xec, 0xf7, + 0x26, 0x54, 0x47, 0x74, 0x97, 0xb9, 0xbc, 0xb3, 0x18, 0x64, 0x50, 0x12, 0x01, 0xe9, 0xc2, 0xe2, + 0x99, 0xa7, 0x35, 0x0a, 0xb3, 0x4f, 0x6b, 0xa4, 0xc9, 0xf7, 0x73, 0x69, 0xf2, 0xfd, 0x03, 0x58, + 0x24, 0xd6, 0xe4, 0xb8, 0xce, 0x48, 0x69, 0xcd, 0x24, 0x05, 0x2e, 0x20, 0x8b, 0x22, 0xb8, 0x52, + 0x27, 0x94, 0xca, 0x21, 0x59, 0xc8, 0xbc, 0xd4, 0x36, 0x12, 0x9a, 0x06, 0x71, 0x8e, 0x48, 0xd3, + 0x88, 0x6a, 0xb0, 0x2f, 0xe3, 0x1a, 0xca, 0x5a, 0x0d, 0x04, 0xc7, 0x1a, 0x1e, 0xc0, 0x22, 0xbf, + 0x0c, 0x7d, 0xdb, 0xf2, 0xc6, 0xf6, 0x17, 0x13, 0xf4, 0x6b, 0xdb, 0xa8, 0xc3, 0x57, 0xcc, 0x05, + 0x4c, 0x38, 0x40, 0xf8, 0xb6, 0x1d, 0xda, 0x0f, 0xbe, 0x84, 0xb2, 0x76, 0xcf, 0x3d, 0x5b, 0x83, + 0xa5, 0xcf, 0xda, 0xbd, 0x4e, 0xab, 0xdb, 0xb5, 0x0e, 0x8f, 0x36, 0x9f, 0xb5, 0x3e, 0xb7, 0x76, + 0x9b, 0xdd, 0xdd, 0xfa, 0x0d, 0xb1, 0x68, 0x3b, 0xad, 0x6e, 0xaf, 0xb5, 0x9d, 0x80, 0x67, 0xd8, + 0xeb, 0xb0, 0x7e, 0xd4, 0x39, 0xea, 0xb6, 0xb6, 0xad, 0xb4, 0x7c, 0x59, 0x41, 0xa5, 0x32, 0x3d, + 0x25, 0x7b, 0xee, 0xc1, 0xaf, 0x41, 0x2d, 0x79, 0xd4, 0x9b, 0x01, 0xcc, 0xed, 0xb5, 0x9e, 0x36, + 0xb7, 0x3e, 0xa7, 0xcb, 0x59, 0xbb, 0xbd, 0x66, 0xaf, 0xbd, 0x65, 0xc9, 0xcb, 0x58, 0x05, 0x47, + 0xc8, 0xb0, 0x32, 0xcc, 0x37, 0x3b, 0x5b, 0xbb, 0x07, 0x66, 0xb7, 0x9e, 0x65, 0xaf, 0xc1, 0x9a, + 0xa2, 0xd5, 0xad, 0x83, 0xfd, 0xfd, 0x76, 0x0f, 0x99, 0x61, 0xef, 0xf3, 0x43, 0x41, 0x9a, 0x0f, + 0x6c, 0x28, 0xc5, 0xb7, 0xc9, 0x22, 0x83, 0x69, 0xf7, 0xda, 0xcd, 0x5e, 0xcc, 0x5d, 0xeb, 0x37, + 0x04, 0xff, 0x8a, 0xc1, 0x78, 0x19, 0x6c, 0x3d, 0x43, 0xa7, 0xe1, 0x14, 0x90, 0x6a, 0xaf, 0x67, + 0xc5, 0xa2, 0x8a, 0xa1, 0x9b, 0x07, 0x3d, 0xd1, 0x85, 0x6f, 0x43, 0x2d, 0x19, 0xf3, 0x98, 0x34, + 0x5e, 0xaf, 0xc3, 0xea, 0x66, 0xab, 0xf7, 0x59, 0xab, 0xd5, 0xc1, 0xd1, 0xd9, 0x6a, 0x75, 0x7a, + 0x66, 0x73, 0xaf, 0xdd, 0xfb, 0xbc, 0x9e, 0x79, 0xf0, 0x31, 0xd4, 0xa7, 0x1d, 0x8c, 0x09, 0x8f, + 0xec, 0x8b, 0x5c, 0xb7, 0x0f, 0xfe, 0x4b, 0x06, 0x96, 0xd3, 0x6c, 0xeb, 0x62, 0x0e, 0xe5, 0xe2, + 0x14, 0x2c, 0xba, 0x7b, 0xd0, 0xb1, 0x3a, 0x07, 0x78, 0xfb, 0xe3, 0x3a, 0xac, 0x4e, 0x25, 0x28, + 0x4e, 0x90, 0x61, 0xb7, 0x60, 0x6d, 0x26, 0x93, 0x65, 0x1e, 0x1c, 0x61, 0xb7, 0x1b, 0xb0, 0x3c, + 0x95, 0xd8, 0x32, 0xcd, 0x03, 0xb3, 0x9e, 0x63, 0xef, 0xc1, 0xfd, 0xa9, 0x94, 0xd9, 0x8d, 0x49, + 0xed, 0x5b, 0x79, 0x76, 0x0f, 0xde, 0x9c, 0xc1, 0x8e, 0x79, 0xb7, 0xb5, 0xd9, 0xdc, 0x13, 0xdd, + 0xab, 0x17, 0x1e, 0xfc, 0xb3, 0x1c, 0x40, 0x7c, 0xa8, 0x48, 0xd4, 0xbf, 0xdd, 0xec, 0x35, 0xf7, + 0x0e, 0x04, 0x79, 0x99, 0x07, 0x3d, 0x51, 0xba, 0xd9, 0xfa, 0xa4, 0x7e, 0x23, 0x35, 0xe5, 0xe0, + 0x50, 0x74, 0x68, 0x0d, 0x96, 0x68, 0xaa, 0xf6, 0x44, 0x37, 0xda, 0x9d, 0xa7, 0x74, 0x91, 0x28, + 0xee, 0x7e, 0x47, 0x87, 0x3b, 0xe6, 0x41, 0xa7, 0x67, 0x75, 0x77, 0x8f, 0x7a, 0xdb, 0x78, 0x0d, + 0xe9, 0x96, 0xd9, 0x3e, 0xa4, 0x32, 0xf3, 0x2f, 0x42, 0x10, 0x45, 0x17, 0xc4, 0x5a, 0x78, 0x7a, + 0xd0, 0xed, 0xb6, 0x0f, 0xad, 0x4f, 0x8e, 0x5a, 0x66, 0xbb, 0xd5, 0xc5, 0x8c, 0x73, 0x29, 0x70, + 0x81, 0x3f, 0x2f, 0xf6, 0xcc, 0xde, 0xde, 0xa7, 0x72, 0x53, 0x13, 0xa8, 0xc5, 0x24, 0x48, 0x60, + 0x95, 0xc4, 0xec, 0x88, 0x5d, 0x21, 0xa5, 0x64, 0xb8, 0x26, 0x4d, 0xe4, 0x2b, 0x8b, 0xfd, 0x6e, + 0x66, 0x91, 0x60, 0xb6, 0x4a, 0x7a, 0x92, 0xc8, 0x85, 0x5b, 0x61, 0x24, 0x38, 0x6c, 0x6f, 0x9b, + 0x98, 0xa1, 0x36, 0x03, 0x15, 0xb8, 0x0b, 0x82, 0x08, 0xc5, 0xb6, 0x21, 0x50, 0xea, 0xea, 0x43, + 0xa4, 0x2c, 0x3e, 0xfe, 0xad, 0x1c, 0xd4, 0xe8, 0x80, 0x27, 0x3d, 0xff, 0xc8, 0x7d, 0xb6, 0x0f, + 0xf3, 0xf2, 0x1d, 0x51, 0xb6, 0x12, 0xdd, 0xf1, 0xa8, 0xbf, 0x5c, 0xba, 0xbe, 0x3a, 0x0d, 0x96, + 0x62, 0xf2, 0xd2, 0x5f, 0xfb, 0xd3, 0xff, 0xf1, 0x77, 0xb3, 0x55, 0x56, 0x7e, 0x78, 0xfe, 0xfe, + 0xc3, 0x53, 0xee, 0x06, 0xa2, 0x8c, 0x5f, 0x01, 0x88, 0x5f, 0xc7, 0x64, 0x0d, 0xed, 0x52, 0x89, + 0xc4, 0xbb, 0x98, 0xeb, 0x37, 0x53, 0x52, 0x64, 0xb9, 0x37, 0xb1, 0xdc, 0x25, 0xa3, 0x26, 0xca, + 0x75, 0x5c, 0x27, 0xa4, 0x97, 0x32, 0x3f, 0xca, 0x3c, 0x60, 0x03, 0xa8, 0xe8, 0xef, 0x56, 0x32, + 0x25, 0xc1, 0xa6, 0xbc, 0xbc, 0xb9, 0x7e, 0x2b, 0x35, 0x4d, 0xe9, 0x06, 0x58, 0xc7, 0x8a, 0x51, + 0x17, 0x75, 0x4c, 0x10, 0x23, 0xae, 0x65, 0x48, 0xda, 0x52, 0xfc, 0x3c, 0x25, 0x7b, 0x4d, 0x93, + 0x77, 0x67, 0x1e, 0xc7, 0x5c, 0xbf, 0x7d, 0x4d, 0xaa, 0xac, 0xeb, 0x36, 0xd6, 0xb5, 0x66, 0x30, + 0x51, 0x57, 0x1f, 0x71, 0xd4, 0xe3, 0x98, 0x1f, 0x65, 0x1e, 0x3c, 0xfe, 0x0f, 0xef, 0x40, 0x29, + 0x0a, 0xf8, 0x66, 0xbf, 0x0e, 0xd5, 0xc4, 0x09, 0x5c, 0xa6, 0xba, 0x91, 0x76, 0x60, 0x77, 0xfd, + 0xb5, 0xf4, 0x44, 0x59, 0xf1, 0xeb, 0x58, 0x71, 0x83, 0xad, 0x8a, 0x8a, 0xe5, 0x09, 0xd7, 0x87, + 0x78, 0x62, 0x9e, 0x6e, 0xcc, 0x7c, 0xae, 0x69, 0x85, 0x54, 0xd9, 0x6b, 0xd3, 0x9a, 0x5a, 0xa2, + 0xb6, 0xdb, 0xd7, 0xa4, 0xca, 0xea, 0x5e, 0xc3, 0xea, 0x56, 0xd9, 0xb2, 0x5e, 0x9d, 0x8a, 0x13, + 0x66, 0x1c, 0x6f, 0xa9, 0xd5, 0x5f, 0x6f, 0x64, 0xb7, 0xe3, 0x3b, 0x45, 0x53, 0x5e, 0x75, 0x8c, + 0x48, 0x64, 0xf6, 0x69, 0x47, 0xa3, 0x81, 0x55, 0x31, 0x86, 0xd3, 0xa7, 0x3f, 0xde, 0xc8, 0x8e, + 0xa1, 0xac, 0x3d, 0x78, 0xc4, 0x6e, 0x5e, 0xfb, 0x38, 0xd3, 0xfa, 0x7a, 0x5a, 0x52, 0x5a, 0x57, + 0xf4, 0xf2, 0x1f, 0x9e, 0x70, 0xce, 0x7e, 0x19, 0x4a, 0xd1, 0x33, 0x3a, 0x6c, 0x4d, 0x7b, 0xd6, + 0x48, 0x7f, 0xf6, 0x67, 0xbd, 0x31, 0x9b, 0x90, 0x46, 0x7c, 0x7a, 0xe9, 0x82, 0xf8, 0x3e, 0x83, + 0xb2, 0xf6, 0x54, 0x4e, 0xd4, 0x81, 0xd9, 0xe7, 0x78, 0xa2, 0x0e, 0xa4, 0xbc, 0xac, 0x63, 0x2c, + 0x62, 0x15, 0x65, 0x56, 0x42, 0xfa, 0x0e, 0x2f, 0xbd, 0x80, 0xed, 0xc1, 0x8a, 0xd4, 0x80, 0x8f, + 0xf9, 0x57, 0x99, 0x86, 0x94, 0x07, 0x33, 0x1f, 0x65, 0xd8, 0xc7, 0x50, 0x54, 0x2f, 0x22, 0xb1, + 0xd5, 0xf4, 0x97, 0x9d, 0xd6, 0xd7, 0x66, 0xe0, 0x52, 0x5d, 0xfd, 0x1c, 0x20, 0x7e, 0x97, 0x27, + 0x62, 0x12, 0x33, 0xef, 0xfc, 0x44, 0x14, 0x30, 0xfb, 0x88, 0x8f, 0xb1, 0x8a, 0x1d, 0xac, 0x33, + 0x64, 0x12, 0x2e, 0xbf, 0x50, 0x57, 0x89, 0xff, 0x00, 0xca, 0xda, 0xd3, 0x3c, 0xd1, 0xf0, 0xcd, + 0x3e, 0xeb, 0x13, 0x0d, 0x5f, 0xca, 0x4b, 0x3e, 0xc6, 0x3a, 0x96, 0xbe, 0x6c, 0x2c, 0x88, 0xd2, + 0x85, 0x08, 0x2c, 0x45, 0x51, 0x31, 0x41, 0x67, 0x50, 0x4d, 0xbc, 0xbf, 0x13, 0xad, 0xd0, 0xb4, + 0xd7, 0x7d, 0xa2, 0x15, 0x9a, 0xfa, 0x64, 0x8f, 0xa2, 0x33, 0x63, 0x51, 0xd4, 0x43, 0xb7, 0x89, + 0x69, 0x35, 0x7d, 0x1f, 0xca, 0xda, 0x5b, 0x3a, 0x51, 0x5f, 0x66, 0x9f, 0xed, 0x89, 0xfa, 0x92, + 0xf6, 0xf4, 0xce, 0x32, 0xd6, 0x51, 0x33, 0x90, 0x14, 0xf0, 0x32, 0x64, 0x51, 0xf6, 0xaf, 0x43, + 0x2d, 0xf9, 0xbc, 0x4e, 0xb4, 0xf6, 0x53, 0xdf, 0xe9, 0x89, 0xd6, 0xfe, 0x35, 0x6f, 0xf2, 0x48, + 0x92, 0x7e, 0xb0, 0x14, 0x55, 0xf2, 0xf0, 0x47, 0xf2, 0xe8, 0xda, 0x97, 0xec, 0x13, 0xc1, 0xe0, + 0xe4, 0x5d, 0xdc, 0x6c, 0x4d, 0xa3, 0x5a, 0xfd, 0x52, 0xef, 0x68, 0xbd, 0xcc, 0x5c, 0xdb, 0x9d, + 0x24, 0x66, 0x2c, 0x9c, 0x3d, 0x85, 0xa5, 0x88, 0x98, 0xa3, 0xcb, 0xb5, 0x83, 0xa8, 0x0f, 0xa9, + 0x57, 0x78, 0xaf, 0xd7, 0xa7, 0x53, 0x1f, 0x65, 0x68, 0xfb, 0xc3, 0x2b, 0x8d, 0xb5, 0xed, 0x4f, + 0xbf, 0x5f, 0x5b, 0xdb, 0xfe, 0x12, 0x37, 0x1f, 0x4f, 0x6f, 0x7f, 0xa1, 0x23, 0xca, 0x70, 0x61, + 0x61, 0xfa, 0xaa, 0xeb, 0xdb, 0xd7, 0x5d, 0x0d, 0x42, 0xc5, 0xbf, 0xfe, 0xe2, 0x9b, 0x43, 0x92, + 0xac, 0x48, 0x71, 0xd3, 0x87, 0x32, 0x52, 0x8a, 0xfd, 0x2a, 0x54, 0xf4, 0x27, 0x39, 0x98, 0xce, + 0x13, 0xa6, 0x6b, 0xba, 0x95, 0x9a, 0x96, 0xa4, 0x12, 0x56, 0xd1, 0xab, 0x61, 0x9f, 0xc2, 0x6a, + 0x34, 0xcc, 0xfa, 0xdd, 0x16, 0x01, 0xbb, 0x93, 0x72, 0xe3, 0x45, 0x62, 0xb0, 0x6f, 0x5e, 0x7b, + 0x25, 0xc6, 0xa3, 0x8c, 0xa0, 0xbe, 0xe4, 0xf3, 0x03, 0xf1, 0xce, 0x93, 0xf6, 0xea, 0x42, 0xbc, + 0xf3, 0xa4, 0xbe, 0x59, 0xa0, 0xa8, 0x8f, 0x2d, 0x25, 0xc6, 0x88, 0x62, 0xc8, 0xd9, 0xf7, 0x61, + 0x41, 0xbb, 0xb8, 0xa3, 0x7b, 0xe5, 0xf6, 0xa3, 0x95, 0x34, 0x7b, 0x89, 0xed, 0x7a, 0x9a, 0xcd, + 0xd8, 0x58, 0xc3, 0xf2, 0x17, 0x8d, 0xc4, 0xe0, 0x88, 0x55, 0xb4, 0x05, 0x65, 0xfd, 0x52, 0x90, + 0x17, 0x94, 0xbb, 0xa6, 0x25, 0xe9, 0xf7, 0xa5, 0x3e, 0xca, 0xb0, 0x3d, 0xa8, 0x4f, 0x5f, 0xe1, + 0x17, 0xf1, 0x94, 0xb4, 0x6b, 0x0f, 0xd7, 0xa7, 0x12, 0x13, 0x17, 0xff, 0xb1, 0x43, 0x3a, 0x85, + 0x14, 0xbd, 0x2e, 0xe9, 0xf9, 0xd3, 0xbb, 0x7a, 0xf2, 0xd5, 0xc9, 0xa8, 0xb4, 0xb4, 0xf7, 0x46, + 0xef, 0x67, 0x1e, 0x65, 0xd8, 0xef, 0x64, 0xa0, 0x92, 0xb8, 0xc2, 0x2a, 0x71, 0xce, 0x63, 0xaa, + 0x9f, 0x0d, 0x3d, 0x4d, 0xef, 0xa8, 0x61, 0xe2, 0x20, 0xee, 0x3d, 0xf8, 0x5e, 0x62, 0x92, 0x7e, + 0x94, 0x70, 0xb9, 0x6e, 0x4c, 0x3f, 0x3f, 0xf9, 0xe5, 0x34, 0x82, 0x7e, 0x2d, 0xf2, 0x97, 0x8f, + 0x32, 0xec, 0x5f, 0x66, 0xa0, 0x96, 0x8c, 0xa5, 0x88, 0xba, 0x9b, 0x1a, 0xb5, 0x11, 0x91, 0xd2, + 0x35, 0x01, 0x18, 0xdf, 0xc7, 0x56, 0xf6, 0x1e, 0x98, 0x89, 0x56, 0xca, 0x87, 0x33, 0x7e, 0xba, + 0xd6, 0xb2, 0x5f, 0xa4, 0xd7, 0x9e, 0x55, 0xdc, 0x1d, 0x9b, 0x7d, 0x1d, 0x38, 0x22, 0x3f, 0xfd, + 0x2d, 0x5d, 0x23, 0xf7, 0x1b, 0xd9, 0x0c, 0xce, 0xc4, 0x0f, 0xe8, 0xad, 0x45, 0x15, 0x7a, 0x25, + 0x48, 0xf9, 0x95, 0x0b, 0x79, 0x0b, 0x3b, 0xf6, 0xba, 0x71, 0x33, 0xd1, 0xb1, 0x69, 0xe9, 0xa3, + 0x49, 0x4d, 0x94, 0xef, 0xe1, 0xc6, 0xdb, 0xe7, 0xcc, 0x1b, 0xb9, 0xa9, 0x95, 0x60, 0x23, 0x47, + 0xd4, 0x48, 0x89, 0x9e, 0x58, 0x6f, 0xaf, 0x58, 0x8c, 0xf1, 0x00, 0xdb, 0xfa, 0x96, 0x71, 0xe7, + 0xda, 0xb6, 0x3e, 0xc4, 0xe0, 0x08, 0xd1, 0xe2, 0x43, 0x80, 0x38, 0x38, 0x96, 0x4d, 0x85, 0x68, + 0x46, 0x5c, 0x68, 0x36, 0x7e, 0x36, 0xb9, 0xa8, 0x55, 0x24, 0xa7, 0x28, 0xf1, 0x97, 0x89, 0xa7, + 0x46, 0xc1, 0xa3, 0xba, 0x08, 0x96, 0x8c, 0x63, 0x4d, 0x88, 0x60, 0xd3, 0xe5, 0x27, 0x38, 0x6a, + 0x14, 0x29, 0x7a, 0x04, 0xd5, 0x3d, 0xcf, 0x7b, 0x3e, 0x19, 0x47, 0x07, 0x32, 0x92, 0xb1, 0x50, + 0xbb, 0x76, 0x70, 0xb6, 0x3e, 0xd5, 0x0b, 0xe3, 0x2e, 0x16, 0xb5, 0xce, 0x1a, 0x5a, 0x51, 0x0f, + 0x7f, 0x14, 0x47, 0xe4, 0x7e, 0xc9, 0x6c, 0x58, 0x8c, 0x18, 0x75, 0x1c, 0xf5, 0x9a, 0x2c, 0x26, + 0xc1, 0x9e, 0xa7, 0xab, 0x48, 0xe8, 0x0a, 0xaa, 0xb5, 0x0f, 0x03, 0x55, 0xe6, 0xa3, 0x0c, 0x3b, + 0x84, 0xca, 0x36, 0xef, 0xe3, 0x8d, 0x1e, 0x18, 0xf7, 0xb3, 0x94, 0x88, 0x21, 0xa1, 0x80, 0xa1, + 0xf5, 0x6a, 0x02, 0x98, 0xdc, 0xbc, 0xc6, 0xf6, 0x95, 0xcf, 0xbf, 0x78, 0xf8, 0x23, 0x19, 0x51, + 0xf4, 0xa5, 0xda, 0xbc, 0xe2, 0xe8, 0x32, 0x5d, 0x02, 0x48, 0x86, 0x68, 0x25, 0x36, 0xaf, 0x99, + 0x10, 0xad, 0xc4, 0x50, 0x47, 0xb1, 0x64, 0x43, 0x58, 0x9c, 0x89, 0xea, 0x8a, 0xf6, 0xad, 0xeb, + 0x62, 0xc1, 0xd6, 0xef, 0x5e, 0x8f, 0x90, 0xac, 0xed, 0x41, 0xb2, 0xb6, 0x2e, 0x54, 0xe9, 0xe2, + 0xe3, 0x63, 0x4e, 0x67, 0x7b, 0xa7, 0x2e, 0xc6, 0xd2, 0x0f, 0x0e, 0x4f, 0xef, 0x32, 0x98, 0x96, + 0x14, 0x73, 0xf0, 0x74, 0x27, 0x3b, 0xc1, 0xd7, 0x3e, 0xb4, 0xc3, 0xb4, 0x11, 0x31, 0xce, 0x1e, + 0xf0, 0x8d, 0x88, 0x31, 0xe5, 0xec, 0xad, 0xd2, 0x41, 0xd9, 0x4a, 0x54, 0xf6, 0x43, 0xd7, 0x1b, + 0xf0, 0x91, 0x2c, 0xf5, 0x97, 0xa1, 0xfc, 0x94, 0x87, 0xea, 0xf4, 0x6a, 0x24, 0xd0, 0x4f, 0x1d, + 0x67, 0x5d, 0x4f, 0x39, 0x73, 0x9c, 0xa4, 0x4d, 0x2a, 0x99, 0x0f, 0x4e, 0x39, 0x71, 0x42, 0xcb, + 0x19, 0x7c, 0xc9, 0x7e, 0x09, 0x0b, 0x8f, 0xee, 0x6a, 0x58, 0xd5, 0x9a, 0xa9, 0x17, 0xbe, 0x30, + 0x05, 0x4f, 0x2b, 0x59, 0xb4, 0x59, 0x13, 0x2c, 0x5d, 0x28, 0x6b, 0x77, 0xba, 0x44, 0x63, 0x33, + 0x7b, 0x87, 0x4f, 0x34, 0x36, 0x29, 0x57, 0xc0, 0x18, 0xf7, 0xb1, 0x1e, 0x83, 0xdd, 0x8d, 0xeb, + 0xa1, 0x6b, 0x5f, 0xe2, 0x9a, 0x1e, 0xfe, 0xc8, 0x1e, 0x85, 0x5f, 0xb2, 0xcf, 0x68, 0x3a, 0xb4, + 0xd3, 0xb9, 0xb1, 0x86, 0x32, 0x7d, 0x90, 0x37, 0x1a, 0x2c, 0x2d, 0x29, 0xa9, 0xb5, 0x50, 0x55, + 0x28, 0x36, 0x3e, 0x01, 0xe8, 0x86, 0xde, 0x78, 0xdb, 0xe6, 0x23, 0xcf, 0x8d, 0x79, 0x7a, 0x7c, + 0x5e, 0x34, 0xe6, 0x93, 0xda, 0xa1, 0x51, 0xf6, 0x99, 0xa6, 0xd2, 0x25, 0xce, 0x95, 0x2b, 0x22, + 0xbe, 0xf6, 0x48, 0x69, 0x34, 0x20, 0x29, 0xc7, 0x4a, 0x1f, 0x65, 0x58, 0x13, 0x20, 0x0e, 0x1f, + 0x8c, 0x14, 0xb4, 0x99, 0xc8, 0xc4, 0x88, 0xbd, 0xa6, 0xc4, 0x1a, 0x1e, 0x42, 0x29, 0x8e, 0xbb, + 0x5a, 0x8b, 0xaf, 0xa8, 0x4a, 0x44, 0x69, 0x45, 0xe2, 0xc2, 0x4c, 0xcc, 0x93, 0x51, 0xc7, 0xa1, + 0x02, 0x56, 0x14, 0x43, 0x75, 0xc2, 0x79, 0xc0, 0x1c, 0x58, 0xa2, 0x06, 0x46, 0xb2, 0x19, 0x9e, + 0x73, 0x8c, 0xde, 0xd8, 0x99, 0x0d, 0x3f, 0x8a, 0xb8, 0x46, 0x6a, 0x10, 0x4d, 0xc2, 0xce, 0x24, + 0xa8, 0x95, 0xce, 0x58, 0x8a, 0x2d, 0x60, 0x04, 0x8b, 0x33, 0x71, 0x1a, 0x11, 0xeb, 0xb8, 0x2e, + 0xf0, 0x26, 0x62, 0x1d, 0xd7, 0x86, 0x78, 0x18, 0x2b, 0x58, 0xe5, 0x82, 0x01, 0xa8, 0x57, 0x5e, + 0x38, 0x61, 0xff, 0x4c, 0x54, 0xf7, 0xfb, 0x19, 0x58, 0x4a, 0x89, 0xc4, 0x60, 0x6f, 0x28, 0x13, + 0xc5, 0xb5, 0x51, 0x1a, 0xeb, 0xa9, 0x1e, 0x7b, 0xa3, 0x8b, 0xf5, 0xec, 0xb3, 0x67, 0x89, 0x0d, + 0x94, 0x1c, 0xe6, 0x72, 0x65, 0xbe, 0x50, 0x82, 0x49, 0x15, 0x5f, 0xbe, 0x80, 0x35, 0x6a, 0x48, + 0x73, 0x38, 0x9c, 0x8a, 0x26, 0x78, 0x5d, 0x6b, 0x45, 0x4a, 0x84, 0x44, 0x42, 0x19, 0x48, 0x46, + 0x49, 0x5c, 0x23, 0xbb, 0x53, 0x53, 0xd9, 0x04, 0xea, 0xd3, 0x5e, 0x7a, 0x76, 0x7d, 0x59, 0xeb, + 0x77, 0x12, 0xca, 0x76, 0x8a, 0x67, 0xff, 0x6b, 0x58, 0xd9, 0x1d, 0x63, 0x3d, 0x6d, 0x5c, 0x48, + 0xff, 0x16, 0xf3, 0xf1, 0x57, 0xa3, 0x90, 0x82, 0xa9, 0x7e, 0xde, 0x89, 0x5e, 0x15, 0x48, 0x0f, + 0x80, 0x88, 0xd4, 0xfd, 0xf4, 0x88, 0x84, 0xb7, 0xb1, 0xfa, 0xbb, 0xc6, 0xad, 0xb4, 0xea, 0x7d, + 0xca, 0x42, 0x8a, 0xff, 0xda, 0xf4, 0xba, 0x56, 0x2d, 0xb8, 0x9b, 0x36, 0xdf, 0xd7, 0x2a, 0x5e, + 0x53, 0x63, 0x7d, 0x03, 0x65, 0xc8, 0x8a, 0x1e, 0x42, 0x10, 0x2d, 0x9f, 0x94, 0x58, 0x85, 0x68, + 0xf9, 0xa4, 0xc5, 0x1c, 0x24, 0xe5, 0x27, 0x15, 0x6d, 0xf0, 0x51, 0xe6, 0xc1, 0xe6, 0xbd, 0xef, + 0x7f, 0xed, 0xd4, 0x09, 0xcf, 0x26, 0xc7, 0x1b, 0x7d, 0x6f, 0xf4, 0x70, 0xa8, 0x4c, 0x9b, 0xf2, + 0x32, 0x80, 0x87, 0x43, 0x77, 0xf0, 0x10, 0x8b, 0x3d, 0x9e, 0x1b, 0xfb, 0x5e, 0xe8, 0x7d, 0xe3, + 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xd5, 0x75, 0xf0, 0xe2, 0x5d, 0x8b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index ca45b3f1bc..d7af96a1b5 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -3097,8 +3097,7 @@ message Payment { /// Deprecated, use creation_time_ns int64 creation_date = 3 [deprecated = true]; - /// The path this payment took. - repeated string path = 4 [deprecated = true]; + reserved 4; /// Deprecated, use fee_sat or fee_msat. int64 fee = 5 [deprecated = true]; diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index f28f5276b7..28941ae288 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -3936,13 +3936,6 @@ "format": "int64", "title": "/ Deprecated, use creation_time_ns" }, - "path": { - "type": "array", - "items": { - "type": "string" - }, - "description": "/ The path this payment took." - }, "fee": { "type": "string", "format": "int64", diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 5f0c958db0..94cc274480 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -4336,15 +4336,12 @@ func testListPayments(net *lntest.NetworkHarness, t *harnessTest) { len(paymentsResp.Payments), 1) } p := paymentsResp.Payments[0] + path := p.Htlcs[len(p.Htlcs)-1].Route.Hops // Ensure that the stored path shows a direct payment to Bob with no // other nodes in-between. - expectedPath := []string{ - net.Bob.PubKeyStr, - } - if !reflect.DeepEqual(p.Path, expectedPath) { - t.Fatalf("incorrect path, got %v, want %v", - p.Path, expectedPath) + if len(path) != 1 || path[0].PubKey != net.Bob.PubKeyStr { + t.Fatalf("incorrect path") } // The payment amount should also match our previous payment directly. @@ -14317,8 +14314,8 @@ func testHoldInvoicePersistence(net *lntest.NetworkHarness, t *harnessTest) { // We wait for the payment attempt to have been // properly recorded in the DB. - if len(payment.Path) == 0 { - return fmt.Errorf("path is empty") + if len(payment.Htlcs) == 0 { + return fmt.Errorf("no attempt recorded") } delete(payHashes, payment.PaymentHash) From e61ff2202da92da9fd0ad99a60667033b152d872 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 9 Apr 2020 16:30:21 +0200 Subject: [PATCH 454/562] lnrpc: report total fees paid Fixes a bug where only the fees of the last route where reported. --- lnrpc/routerrpc/router_backend.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index e8493871ee..2d2be75b11 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -1095,20 +1095,17 @@ func marshallChannelUpdate(update *lnwire.ChannelUpdate) *lnrpc.ChannelUpdate { func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) ( *lnrpc.Payment, error) { - // Fetch the payment's route and preimage. If no HTLC was - // successful, an empty route and preimage will be used. + // Fetch the payment's preimage and the total paid in fees. var ( - route route.Route + fee lnwire.MilliSatoshi preimage lntypes.Preimage ) for _, htlc := range payment.HTLCs { - // Display the last route attempted. - route = htlc.Route - // If any of the htlcs have settled, extract a valid // preimage. if htlc.Settle != nil { preimage = htlc.Settle.Preimage + fee += htlc.Route.TotalFees() } } @@ -1147,9 +1144,9 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) ( ValueSat: satValue, CreationDate: payment.Info.CreationTime.Unix(), CreationTimeNs: creationTimeNS, - Fee: int64(route.TotalFees().ToSatoshis()), - FeeSat: int64(route.TotalFees().ToSatoshis()), - FeeMsat: int64(route.TotalFees()), + Fee: int64(fee.ToSatoshis()), + FeeSat: int64(fee.ToSatoshis()), + FeeMsat: int64(fee), PaymentPreimage: hex.EncodeToString(preimage[:]), PaymentRequest: string(payment.Info.PaymentRequest), Status: status, From 0f94b8dc624cf0e96ddc8fe1b8e3bf4b3fc4c074 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Sun, 5 Apr 2020 17:06:38 -0700 Subject: [PATCH 455/562] multi: return input.Signature from SignOutputRaw --- chancloser.go | 2 +- contractcourt/htlc_timeout_resolver_test.go | 25 +++++++++++---- discovery/gossiper_test.go | 3 +- fundingmanager.go | 26 +++++++++++---- fundingmanager_test.go | 6 ++-- htlcswitch/mock.go | 6 ++-- input/script_utils.go | 32 +++++++++++-------- input/script_utils_test.go | 12 ++++--- input/signer.go | 3 +- input/size.go | 16 +++++++--- input/test_utils.go | 6 ++-- lnwallet/btcwallet/signer.go | 6 ++-- lnwallet/channel.go | 7 ++-- lnwallet/channel_test.go | 16 +++++----- lnwallet/interface.go | 3 +- lnwallet/interface_test.go | 4 +-- lnwallet/reservation.go | 16 ++++++---- lnwallet/sigpool.go | 2 +- lnwallet/wallet.go | 26 +++++---------- lnwire/signature.go | 3 +- mock.go | 4 +-- netann/channel_update_test.go | 3 +- netann/node_signer.go | 7 ++-- netann/sign.go | 3 +- peer_test.go | 16 +++++----- server.go | 2 +- sweep/test_utils.go | 15 +++++++-- watchtower/lookout/justice_descriptor_test.go | 4 +-- watchtower/wtmock/signer.go | 4 +-- 29 files changed, 168 insertions(+), 110 deletions(-) diff --git a/chancloser.go b/chancloser.go index 4dc28d40ef..befb6ccd85 100644 --- a/chancloser.go +++ b/chancloser.go @@ -589,7 +589,7 @@ func (c *channelCloser) proposeCloseSigned(fee btcutil.Amount) (*lnwire.ClosingS // party responds we'll be able to decide if we've agreed on fees or // not. c.lastFeeProposal = fee - parsedSig, err := lnwire.NewSigFromRawSignature(rawSig) + parsedSig, err := lnwire.NewSigFromSignature(rawSig) if err != nil { return nil, err } diff --git a/contractcourt/htlc_timeout_resolver_test.go b/contractcourt/htlc_timeout_resolver_test.go index 52324698a9..923fb3eaf4 100644 --- a/contractcourt/htlc_timeout_resolver_test.go +++ b/contractcourt/htlc_timeout_resolver_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" @@ -15,12 +16,22 @@ import ( "github.com/lightningnetwork/lnd/lnwallet" ) +type dummySignature struct{} + +func (s *dummySignature) Serialize() []byte { + return []byte{} +} + +func (s *dummySignature) Verify(_ []byte, _ *btcec.PublicKey) bool { + return true +} + type mockSigner struct { } func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, - signDesc *input.SignDescriptor) ([]byte, error) { - return nil, nil + signDesc *input.SignDescriptor) (input.Signature, error) { + return &dummySignature{}, nil } func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, @@ -145,8 +156,8 @@ func TestHtlcTimeoutResolver(t *testing.T) { timeout: true, txToBroadcast: func() (*wire.MsgTx, error) { witness, err := input.SenderHtlcSpendTimeout( - nil, txscript.SigHashAll, signer, - fakeSignDesc, sweepTx, + &dummySignature{}, txscript.SigHashAll, + signer, fakeSignDesc, sweepTx, ) if err != nil { return nil, err @@ -165,9 +176,9 @@ func TestHtlcTimeoutResolver(t *testing.T) { timeout: false, txToBroadcast: func() (*wire.MsgTx, error) { witness, err := input.ReceiverHtlcSpendRedeem( - nil, txscript.SigHashAll, - fakePreimageBytes, signer, - fakeSignDesc, sweepTx, + &dummySignature{}, txscript.SigHashAll, + fakePreimageBytes, signer, fakeSignDesc, + sweepTx, ) if err != nil { return nil, err diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index f927a9609c..75d3cef67e 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -23,6 +23,7 @@ import ( "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwire" @@ -96,7 +97,7 @@ type mockSigner struct { } func (n *mockSigner) SignMessage(pubKey *btcec.PublicKey, - msg []byte) (*btcec.Signature, error) { + msg []byte) (input.Signature, error) { if !pubKey.IsEqual(n.privKey.PubKey()) { return nil, fmt.Errorf("unknown public key") diff --git a/fundingmanager.go b/fundingmanager.go index 23126c30c1..761227c93b 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -254,7 +254,8 @@ type fundingConfig struct { // // TODO(roasbeef): should instead pass on this responsibility to a // distinct sub-system? - SignMessage func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error) + SignMessage func(pubKey *btcec.PublicKey, + msg []byte) (input.Signature, error) // CurrentNodeAnnouncement should return the latest, fully signed node // announcement from the backing Lightning Network node. @@ -1726,7 +1727,7 @@ func (f *fundingManager) continueFundingAccept(resCtx *reservationWithCtx, PendingChannelID: pendingChanID, FundingPoint: *outPoint, } - fundingCreated.CommitSig, err = lnwire.NewSigFromRawSignature(sig) + fundingCreated.CommitSig, err = lnwire.NewSigFromSignature(sig) if err != nil { fndgLog.Errorf("Unable to parse signature: %v", err) f.failFundingFlow(resCtx.peer, pendingChanID, err) @@ -1775,14 +1776,21 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { fndgLog.Infof("completing pending_id(%x) with ChannelPoint(%v)", pendingChanID[:], fundingOut) + commitSig, err := fmsg.msg.CommitSig.ToSignature() + if err != nil { + fndgLog.Errorf("unable to parse signature: %v", err) + f.failFundingFlow(fmsg.peer, pendingChanID, err) + return + } + // With all the necessary data available, attempt to advance the // funding workflow to the next stage. If this succeeds then the // funding transaction will broadcast after our next message. // CompleteReservationSingle will also mark the channel as 'IsPending' // in the database. - commitSig := fmsg.msg.CommitSig.ToSignatureBytes() completeChan, err := resCtx.reservation.CompleteReservationSingle( - &fundingOut, commitSig) + &fundingOut, commitSig, + ) if err != nil { // TODO(roasbeef): better error logging: peerID, channelID, etc. fndgLog.Errorf("unable to complete single reservation: %v", err) @@ -1837,7 +1845,7 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { // With their signature for our version of the commitment transaction // verified, we can now send over our signature to the remote peer. _, sig := resCtx.reservation.OurSignatures() - ourCommitSig, err := lnwire.NewSigFromRawSignature(sig) + ourCommitSig, err := lnwire.NewSigFromSignature(sig) if err != nil { fndgLog.Errorf("unable to parse signature: %v", err) f.failFundingFlow(fmsg.peer, pendingChanID, err) @@ -1950,7 +1958,13 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) { // The remote peer has responded with a signature for our commitment // transaction. We'll verify the signature for validity, then commit // the state to disk as we can now open the channel. - commitSig := fmsg.msg.CommitSig.ToSignatureBytes() + commitSig, err := fmsg.msg.CommitSig.ToSignature() + if err != nil { + fndgLog.Errorf("Unable to parse signature: %v", err) + f.failFundingFlow(fmsg.peer, pendingChanID, err) + return + } + completeChan, err := resCtx.reservation.CompleteReservation( nil, commitSig, ) diff --git a/fundingmanager_test.go b/fundingmanager_test.go index c7247136da..b222bf94b2 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -334,7 +334,9 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, Wallet: lnw, Notifier: chainNotifier, FeeEstimator: estimator, - SignMessage: func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error) { + SignMessage: func(pubKey *btcec.PublicKey, + msg []byte) (input.Signature, error) { + return testSig, nil }, SendAnnouncement: func(msg lnwire.Message, @@ -474,7 +476,7 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) { Notifier: oldCfg.Notifier, FeeEstimator: oldCfg.FeeEstimator, SignMessage: func(pubKey *btcec.PublicKey, - msg []byte) (*btcec.Signature, error) { + msg []byte) (input.Signature, error) { return testSig, nil }, SendAnnouncement: func(msg lnwire.Message, diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index cefb673a9b..c65e5fb012 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -852,7 +852,9 @@ type mockSigner struct { key *btcec.PrivateKey } -func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *input.SignDescriptor) ([]byte, error) { +func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, + signDesc *input.SignDescriptor) (input.Signature, error) { + amt := signDesc.Output.Value witnessScript := signDesc.WitnessScript privKey := m.key @@ -877,7 +879,7 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *input.SignDescripto return nil, err } - return sig[:len(sig)-1], nil + return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256()) } func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *input.SignDescriptor) (*input.Script, error) { diff --git a/input/script_utils.go b/input/script_utils.go index 56bfbe97f1..97938ce8b4 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -28,6 +28,10 @@ var ( type Signature interface { // Serialize returns a DER-encoded ECDSA signature. Serialize() []byte + + // Verify return true if the ECDSA signature is valid for the passed + // message digest under the provided public key. + Verify([]byte, *btcec.PublicKey) bool } // WitnessScriptHash generates a pay-to-witness-script-hash public key script @@ -290,7 +294,7 @@ func SenderHtlcSpendRevokeWithKey(signer Signer, signDesc *SignDescriptor, // manner in order to encode the revocation contract into a sig+key // pair. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = revokeKey.SerializeCompressed() witnessStack[2] = signDesc.WitnessScript @@ -339,7 +343,7 @@ func SenderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor, // generated above under the receiver's public key, and the payment // pre-image. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = paymentPreimage witnessStack[2] = signDesc.WitnessScript @@ -367,7 +371,7 @@ func SenderHtlcSpendTimeout(receiverSig Signature, witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack[0] = nil witnessStack[1] = append(receiverSig.Serialize(), byte(receiverSigHash)) - witnessStack[2] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[2] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[3] = nil witnessStack[4] = signDesc.WitnessScript @@ -535,7 +539,7 @@ func ReceiverHtlcSpendRedeem(senderSig Signature, witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack[0] = nil witnessStack[1] = append(senderSig.Serialize(), byte(senderSigHash)) - witnessStack[2] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[2] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[3] = paymentPreimage witnessStack[4] = signDesc.WitnessScript @@ -562,7 +566,7 @@ func ReceiverHtlcSpendRevokeWithKey(signer Signer, signDesc *SignDescriptor, // witness stack in order to force script execution to the HTLC // revocation clause. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = revokeKey.SerializeCompressed() witnessStack[2] = signDesc.WitnessScript @@ -627,7 +631,7 @@ func ReceiverHtlcSpendTimeout(signer Signer, signDesc *SignDescriptor, } witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = nil witnessStack[2] = signDesc.WitnessScript @@ -732,7 +736,7 @@ func HtlcSpendSuccess(signer Signer, signDesc *SignDescriptor, // witness script), in order to force execution to the second portion // of the if clause. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = nil witnessStack[2] = signDesc.WitnessScript @@ -757,7 +761,7 @@ func HtlcSpendRevoke(signer Signer, signDesc *SignDescriptor, // witness script), in order to force execution to the revocation // clause in the second level HTLC script. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = []byte{1} witnessStack[2] = signDesc.WitnessScript @@ -788,7 +792,7 @@ func HtlcSecondLevelSpend(signer Signer, signDesc *SignDescriptor, // witness script), in order to force execution to the second portion // of the if clause. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(txscript.SigHashAll)) + witnessStack[0] = append(sweepSig.Serialize(), byte(txscript.SigHashAll)) witnessStack[1] = nil witnessStack[2] = signDesc.WitnessScript @@ -892,7 +896,7 @@ func CommitSpendTimeout(signer Signer, signDesc *SignDescriptor, // place an empty byte in order to ensure our script is still valid // from the PoV of nodes that are enforcing minimal OP_IF/OP_NOTIF. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = nil witnessStack[2] = signDesc.WitnessScript @@ -917,7 +921,7 @@ func CommitSpendRevoke(signer Signer, signDesc *SignDescriptor, // Place a 1 as the first item in the evaluated witness stack to // force script execution to the revocation clause. witnessStack := wire.TxWitness(make([][]byte, 3)) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = []byte{1} witnessStack[2] = signDesc.WitnessScript @@ -951,7 +955,7 @@ func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor, // exact same as a regular p2wkh witness, depending on the value of the // tweakless bool. witness := make([][]byte, 2) - witness[0] = append(sweepSig, byte(signDesc.HashType)) + witness[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) switch tweakless { // If we're tweaking the key, then we use the tweaked public key as the @@ -1028,7 +1032,7 @@ func CommitSpendToRemoteConfirmed(signer Signer, signDesc *SignDescriptor, // Finally, we'll manually craft the witness. The witness here is the // signature and the redeem script. witnessStack := make([][]byte, 2) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = signDesc.WitnessScript return witnessStack, nil @@ -1084,7 +1088,7 @@ func CommitSpendAnchor(signer Signer, signDesc *SignDescriptor, // The witness here is just a signature and the redeem script. witnessStack := make([][]byte, 2) - witnessStack[0] = append(sweepSig, byte(signDesc.HashType)) + witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType)) witnessStack[1] = signDesc.WitnessScript return witnessStack, nil diff --git a/input/script_utils_test.go b/input/script_utils_test.go index a76183dc54..5978d3eec1 100644 --- a/input/script_utils_test.go +++ b/input/script_utils_test.go @@ -303,12 +303,14 @@ func TestHTLCSenderSpendValidation(t *testing.T) { SigHashes: sweepTxSigHashes, InputIndex: 0, } - bobSigBytes, err := bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) + bobSig, err := bobSigner.SignOutputRaw(sweepTx, &bobSignDesc) if err != nil { t.Fatalf("unable to generate alice signature: %v", err) } - bobRecvrSig, err = btcec.ParseDERSignature(bobSigBytes, btcec.S256()) + bobRecvrSig, err = btcec.ParseDERSignature( + bobSig.Serialize(), btcec.S256(), + ) if err != nil { t.Fatalf("unable to parse signature: %v", err) } @@ -700,12 +702,14 @@ func TestHTLCReceiverSpendValidation(t *testing.T) { SigHashes: sweepTxSigHashes, InputIndex: 0, } - aliceSigBytes, err := aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) + aliceSig, err := aliceSigner.SignOutputRaw(sweepTx, &aliceSignDesc) if err != nil { t.Fatalf("unable to generate alice signature: %v", err) } - aliceSenderSig, err = btcec.ParseDERSignature(aliceSigBytes, btcec.S256()) + aliceSenderSig, err = btcec.ParseDERSignature( + aliceSig.Serialize(), btcec.S256(), + ) if err != nil { t.Fatalf("unable to parse signature: %v", err) } diff --git a/input/signer.go b/input/signer.go index cd32025562..86622638ea 100644 --- a/input/signer.go +++ b/input/signer.go @@ -14,7 +14,8 @@ type Signer interface { // according to the data within the passed SignDescriptor. // // NOTE: The resulting signature should be void of a sighash byte. - SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]byte, error) + SignOutputRaw(tx *wire.MsgTx, + signDesc *SignDescriptor) (Signature, error) // ComputeInputScript generates a complete InputIndex for the passed // transaction with the signature as defined within the passed diff --git a/input/size.go b/input/size.go index 32a89bcda3..74f1247d5b 100644 --- a/input/size.go +++ b/input/size.go @@ -410,6 +410,14 @@ const ( OfferedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + OfferedHtlcScriptSize ) +type dummySignature struct{} + +func (d *dummySignature) Serialize() []byte { + // Always return worst-case signature length, excluding the one byte + // sighash flag. + return make([]byte, 73-1) +} + // dummySigner is a fake signer used for size (upper bound) calculations. type dummySigner struct { Signer @@ -417,12 +425,10 @@ type dummySigner struct { // SignOutputRaw generates a signature for the passed transaction according to // the data within the passed SignDescriptor. -func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ( - []byte, error) { +func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx, + signDesc *SignDescriptor) (Signature, error) { - // Always return worst-case signature length, excluding the one byte - // sighash flag. - return make([]byte, 73-1), nil + return &dummySignature{}, nil } var ( diff --git a/input/test_utils.go b/input/test_utils.go index b9719438dc..5b00441726 100644 --- a/input/test_utils.go +++ b/input/test_utils.go @@ -50,7 +50,9 @@ type MockSigner struct { // SignOutputRaw generates a signature for the passed transaction according to // the data within the passed SignDescriptor. -func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]byte, error) { +func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx, + signDesc *SignDescriptor) (Signature, error) { + pubkey := signDesc.KeyDesc.PubKey switch { case signDesc.SingleTweak != nil: @@ -72,7 +74,7 @@ func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([] return nil, err } - return sig[:len(sig)-1], nil + return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256()) } // ComputeInputScript generates a complete InputIndex for the passed transaction diff --git a/lnwallet/btcwallet/signer.go b/lnwallet/btcwallet/signer.go index 35e158c028..a79a5fd927 100644 --- a/lnwallet/btcwallet/signer.go +++ b/lnwallet/btcwallet/signer.go @@ -225,7 +225,7 @@ func maybeTweakPrivKey(signDesc *input.SignDescriptor, // // This is a part of the WalletController interface. func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx, - signDesc *input.SignDescriptor) ([]byte, error) { + signDesc *input.SignDescriptor) (input.Signature, error) { witnessScript := signDesc.WitnessScript @@ -256,7 +256,7 @@ func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx, } // Chop off the sighash flag at the end of the signature. - return sig[:len(sig)-1], nil + return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256()) } // ComputeInputScript generates a complete InputScript for the passed @@ -358,7 +358,7 @@ var _ input.Signer = (*BtcWallet)(nil) // // NOTE: This is a part of the MessageSigner interface. func (b *BtcWallet) SignMessage(pubKey *btcec.PublicKey, - msg []byte) (*btcec.Signature, error) { + msg []byte) (input.Signature, error) { // First attempt to fetch the private key which corresponds to the // specified public key. diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 11eb115932..33380deb2d 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -3402,7 +3402,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig, []ch close(cancelChan) return sig, htlcSigs, nil, err } - sig, err = lnwire.NewSigFromRawSignature(rawSig) + sig, err = lnwire.NewSigFromSignature(rawSig) if err != nil { close(cancelChan) return sig, htlcSigs, nil, err @@ -5075,7 +5075,7 @@ func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) { return nil, err } - ourSig := append(ourSigRaw, byte(txscript.SigHashAll)) + ourSig := append(ourSigRaw.Serialize(), byte(txscript.SigHashAll)) // With the final signature generated, create the witness stack // required to spend from the multi-sig output. @@ -5950,7 +5950,8 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer input.Si // settle any in flight. func (lc *LightningChannel) CreateCloseProposal(proposedFee btcutil.Amount, localDeliveryScript []byte, - remoteDeliveryScript []byte) ([]byte, *chainhash.Hash, btcutil.Amount, error) { + remoteDeliveryScript []byte) (input.Signature, *chainhash.Hash, + btcutil.Amount, error) { lc.Lock() defer lc.Unlock() diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index c266db1c80..8a7711fea9 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -616,7 +616,7 @@ func TestCooperativeChannelClosure(t *testing.T) { if err != nil { t.Fatalf("unable to create alice coop close proposal: %v", err) } - aliceCloseSig := append(aliceSig, byte(txscript.SigHashAll)) + aliceCloseSig := append(aliceSig.Serialize(), byte(txscript.SigHashAll)) bobFee := bobChannel.CalcFee(bobFeeRate) bobSig, _, _, err := bobChannel.CreateCloseProposal( @@ -625,7 +625,7 @@ func TestCooperativeChannelClosure(t *testing.T) { if err != nil { t.Fatalf("unable to create bob coop close proposal: %v", err) } - bobCloseSig := append(bobSig, byte(txscript.SigHashAll)) + bobCloseSig := append(bobSig.Serialize(), byte(txscript.SigHashAll)) // With the proposals created, both sides should be able to properly // process the other party's signature. This indicates that the @@ -2059,7 +2059,7 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { if err != nil { t.Fatalf("unable to close channel: %v", err) } - aliceCloseSig := append(aliceSig, byte(txscript.SigHashAll)) + aliceCloseSig := append(aliceSig.Serialize(), byte(txscript.SigHashAll)) bobFee := btcutil.Amount(bobChannel.CalcFee(bobFeeRate)) + 1000 bobSig, _, _, err := bobChannel.CreateCloseProposal(bobFee, @@ -2067,7 +2067,7 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { if err != nil { t.Fatalf("unable to close channel: %v", err) } - bobCloseSig := append(bobSig, byte(txscript.SigHashAll)) + bobCloseSig := append(bobSig.Serialize(), byte(txscript.SigHashAll)) closeTx, _, err := bobChannel.CompleteCooperativeClose( bobCloseSig, aliceCloseSig, @@ -2098,14 +2098,14 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { if err != nil { t.Fatalf("unable to close channel: %v", err) } - aliceCloseSig = append(aliceSig, byte(txscript.SigHashAll)) + aliceCloseSig = append(aliceSig.Serialize(), byte(txscript.SigHashAll)) bobSig, _, _, err = bobChannel.CreateCloseProposal(bobFee, bobDeliveryScript, aliceDeliveryScript) if err != nil { t.Fatalf("unable to close channel: %v", err) } - bobCloseSig = append(bobSig, byte(txscript.SigHashAll)) + bobCloseSig = append(bobSig.Serialize(), byte(txscript.SigHashAll)) closeTx, _, err = bobChannel.CompleteCooperativeClose( bobCloseSig, aliceCloseSig, @@ -2141,7 +2141,7 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { if err != nil { t.Fatalf("unable to close channel: %v", err) } - aliceCloseSig = append(aliceSig, byte(txscript.SigHashAll)) + aliceCloseSig = append(aliceSig.Serialize(), byte(txscript.SigHashAll)) bobSig, _, _, err = bobChannel.CreateCloseProposal( bobFee, bobDeliveryScript, aliceDeliveryScript, @@ -2149,7 +2149,7 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { if err != nil { t.Fatalf("unable to close channel: %v", err) } - bobCloseSig = append(bobSig, byte(txscript.SigHashAll)) + bobCloseSig = append(bobSig.Serialize(), byte(txscript.SigHashAll)) closeTx, _, err = bobChannel.CompleteCooperativeClose( bobCloseSig, aliceCloseSig, diff --git a/lnwallet/interface.go b/lnwallet/interface.go index 1c6c2bd70e..41052503cd 100644 --- a/lnwallet/interface.go +++ b/lnwallet/interface.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwallet/wallet/txauthor" + "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -292,7 +293,7 @@ type MessageSigner interface { // that corresponds to the passed public key. If the target private key // is unable to be found, then an error will be returned. The actual // digest signed is the double SHA-256 of the passed message. - SignMessage(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error) + SignMessage(pubKey *btcec.PublicKey, msg []byte) (input.Signature, error) } // WalletDriver represents a "driver" for a particular concrete diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index 1b6a1f28c4..16fc7ce431 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -1591,7 +1591,7 @@ func txFromOutput(tx *wire.MsgTx, signer input.Signer, fromPubKey, return nil, fmt.Errorf("unable to generate signature: %v", err) } witness := make([][]byte, 2) - witness[0] = append(spendSig, byte(txscript.SigHashAll)) + witness[0] = append(spendSig.Serialize(), byte(txscript.SigHashAll)) witness[1] = fromPubKey.SerializeCompressed() tx1.TxIn[0].Witness = witness @@ -1976,7 +1976,7 @@ func testSignOutputUsingTweaks(r *rpctest.Harness, t.Fatalf("unable to generate signature: %v", err) } witness := make([][]byte, 2) - witness[0] = append(spendSig, byte(txscript.SigHashAll)) + witness[0] = append(spendSig.Serialize(), byte(txscript.SigHashAll)) witness[1] = tweakedKey.SerializeCompressed() sweepTx.TxIn[0].Witness = witness diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 1925135180..22ef08b3a9 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -134,8 +134,8 @@ type ChannelReservation struct { theirFundingInputScripts []*input.Script // Our signature for their version of the commitment transaction. - ourCommitmentSig []byte - theirCommitmentSig []byte + ourCommitmentSig input.Signature + theirCommitmentSig input.Signature ourContribution *ChannelContribution theirContribution *ChannelContribution @@ -538,7 +538,9 @@ func (r *ChannelReservation) TheirContribution() *ChannelContribution { // // NOTE: These signatures will only be populated after a call to // .ProcessContribution() -func (r *ChannelReservation) OurSignatures() ([]*input.Script, []byte) { +func (r *ChannelReservation) OurSignatures() ([]*input.Script, + input.Signature) { + r.RLock() defer r.RUnlock() return r.ourFundingInputScripts, r.ourCommitmentSig @@ -558,7 +560,7 @@ func (r *ChannelReservation) OurSignatures() ([]*input.Script, []byte) { // confirmations. Once the method unblocks, a LightningChannel instance is // returned, marking the channel available for updates. func (r *ChannelReservation) CompleteReservation(fundingInputScripts []*input.Script, - commitmentSig []byte) (*channeldb.OpenChannel, error) { + commitmentSig input.Signature) (*channeldb.OpenChannel, error) { // TODO(roasbeef): add flag for watch or not? errChan := make(chan error, 1) @@ -585,7 +587,7 @@ func (r *ChannelReservation) CompleteReservation(fundingInputScripts []*input.Sc // called as a response to a single funder channel, only a commitment signature // will be populated. func (r *ChannelReservation) CompleteReservationSingle(fundingPoint *wire.OutPoint, - commitSig []byte) (*channeldb.OpenChannel, error) { + commitSig input.Signature) (*channeldb.OpenChannel, error) { errChan := make(chan error, 1) completeChan := make(chan *channeldb.OpenChannel, 1) @@ -608,7 +610,9 @@ func (r *ChannelReservation) CompleteReservationSingle(fundingPoint *wire.OutPoi // // NOTE: These attributes will be unpopulated before a call to // .CompleteReservation(). -func (r *ChannelReservation) TheirSignatures() ([]*input.Script, []byte) { +func (r *ChannelReservation) TheirSignatures() ([]*input.Script, + input.Signature) { + r.RLock() defer r.RUnlock() return r.theirFundingInputScripts, r.theirCommitmentSig diff --git a/lnwallet/sigpool.go b/lnwallet/sigpool.go index 57b849888a..ec1d4f3462 100644 --- a/lnwallet/sigpool.go +++ b/lnwallet/sigpool.go @@ -205,7 +205,7 @@ func (s *SigPool) poolWorker() { } } - sig, err := lnwire.NewSigFromRawSignature(rawSig) + sig, err := lnwire.NewSigFromSignature(rawSig) select { case sigMsg.Resp <- SignJobResp{ Sig: sig, diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index f7d66b6bab..3349d29ecf 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -215,7 +215,7 @@ type addCounterPartySigsMsg struct { // This should be 1/2 of the signatures needed to successfully spend our // version of the commitment transaction. - theirCommitmentSig []byte + theirCommitmentSig input.Signature // This channel is used to return the completed channel after the wallet // has completed all of its stages in the funding process. @@ -240,7 +240,7 @@ type addSingleFunderSigsMsg struct { // theirCommitmentSig are the 1/2 of the signatures needed to // successfully spend our version of the commitment transaction. - theirCommitmentSig []byte + theirCommitmentSig input.Signature // This channel is used to return the completed channel after the wallet // has completed all of its stages in the funding process. @@ -1406,18 +1406,13 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs // Verify that we've received a valid signature from the remote party // for our version of the commitment transaction. - theirCommitSig := msg.theirCommitmentSig - sig, err := btcec.ParseSignature(theirCommitSig, btcec.S256()) - if err != nil { - msg.err <- err - msg.completeChan <- nil - return - } else if !sig.Verify(sigHash, theirKey.PubKey) { + if !msg.theirCommitmentSig.Verify(sigHash, theirKey.PubKey) { msg.err <- fmt.Errorf("counterparty's commitment signature is invalid") msg.completeChan <- nil return } - res.partialState.LocalCommitment.CommitSig = theirCommitSig + theirCommitSigBytes := msg.theirCommitmentSig.Serialize() + res.partialState.LocalCommitment.CommitSig = theirCommitSigBytes // Funding complete, this entry can be removed from limbo. l.limboMtx.Lock() @@ -1566,19 +1561,14 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) { // Verify that we've received a valid signature from the remote party // for our version of the commitment transaction. - sig, err := btcec.ParseSignature(req.theirCommitmentSig, btcec.S256()) - if err != nil { - req.err <- err - req.completeChan <- nil - return - } - if !sig.Verify(sigHash, theirKey.PubKey) { + if !req.theirCommitmentSig.Verify(sigHash, theirKey.PubKey) { req.err <- fmt.Errorf("counterparty's commitment signature " + "is invalid") req.completeChan <- nil return } - chanState.LocalCommitment.CommitSig = req.theirCommitmentSig + theirCommitSigBytes := req.theirCommitmentSig.Serialize() + chanState.LocalCommitment.CommitSig = theirCommitSigBytes // With their signature for our version of the commitment transactions // verified, we can now generate a signature for their version, diff --git a/lnwire/signature.go b/lnwire/signature.go index 012d5a9131..13a2f25c3a 100644 --- a/lnwire/signature.go +++ b/lnwire/signature.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/input" ) // Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized @@ -64,7 +65,7 @@ func NewSigFromRawSignature(sig []byte) (Sig, error) { // NewSigFromSignature creates a new signature as used on the wire, from an // existing btcec.Signature. -func NewSigFromSignature(e *btcec.Signature) (Sig, error) { +func NewSigFromSignature(e input.Signature) (Sig, error) { if e == nil { return Sig{}, fmt.Errorf("cannot decode empty signature") } diff --git a/mock.go b/mock.go index bf9559d747..0b71a6dc38 100644 --- a/mock.go +++ b/mock.go @@ -33,7 +33,7 @@ type mockSigner struct { } func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, - signDesc *input.SignDescriptor) ([]byte, error) { + signDesc *input.SignDescriptor) (input.Signature, error) { amt := signDesc.Output.Value witnessScript := signDesc.WitnessScript privKey := m.key @@ -58,7 +58,7 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, return nil, err } - return sig[:len(sig)-1], nil + return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256()) } func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, diff --git a/netann/channel_update_test.go b/netann/channel_update_test.go index 0bc48e5c7a..1fff1d5134 100644 --- a/netann/channel_update_test.go +++ b/netann/channel_update_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/netann" @@ -17,7 +18,7 @@ type mockSigner struct { } func (m *mockSigner) SignMessage(pk *btcec.PublicKey, - msg []byte) (*btcec.Signature, error) { + msg []byte) (input.Signature, error) { if m.err != nil { return nil, m.err diff --git a/netann/node_signer.go b/netann/node_signer.go index 8946c2c6bb..2b97c9379a 100644 --- a/netann/node_signer.go +++ b/netann/node_signer.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" ) @@ -31,7 +32,7 @@ func NewNodeSigner(key *btcec.PrivateKey) *NodeSigner { // resident node's private key. If the target public key is _not_ the node's // private key, then an error will be returned. func (n *NodeSigner) SignMessage(pubKey *btcec.PublicKey, - msg []byte) (*btcec.Signature, error) { + msg []byte) (input.Signature, error) { // If this isn't our identity public key, then we'll exit early with an // error as we can't sign with this key. @@ -41,12 +42,12 @@ func (n *NodeSigner) SignMessage(pubKey *btcec.PublicKey, // Otherwise, we'll sign the dsha256 of the target message. digest := chainhash.DoubleHashB(msg) - sign, err := n.privKey.Sign(digest) + sig, err := n.privKey.Sign(digest) if err != nil { return nil, fmt.Errorf("can't sign the message: %v", err) } - return sign, nil + return sig, nil } // SignCompact signs a double-sha256 digest of the msg parameter under the diff --git a/netann/sign.go b/netann/sign.go index 5a66962013..6e0bce9814 100644 --- a/netann/sign.go +++ b/netann/sign.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" ) @@ -11,7 +12,7 @@ import ( // SignAnnouncement signs any type of gossip message that is announced on the // network. func SignAnnouncement(signer lnwallet.MessageSigner, pubKey *btcec.PublicKey, - msg lnwire.Message) (*btcec.Signature, error) { + msg lnwire.Message) (input.Signature, error) { var ( data []byte diff --git a/peer_test.go b/peer_test.go index 14cb197983..4669168be0 100644 --- a/peer_test.go +++ b/peer_test.go @@ -96,7 +96,7 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err := lnwire.NewSigFromRawSignature(initiatorSig) + parsedSig, err := lnwire.NewSigFromSignature(initiatorSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -184,7 +184,7 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { if err != nil { t.Fatalf("unable to create close proposal: %v", err) } - parsedSig, err := lnwire.NewSigFromRawSignature(closeSig) + parsedSig, err := lnwire.NewSigFromSignature(closeSig) if err != nil { t.Fatalf("unable to parse signature: %v", err) } @@ -296,7 +296,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err := lnwire.NewSigFromRawSignature(initiatorSig) + parsedSig, err := lnwire.NewSigFromSignature(initiatorSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -340,7 +340,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err = lnwire.NewSigFromRawSignature(initiatorSig) + parsedSig, err = lnwire.NewSigFromSignature(initiatorSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -385,7 +385,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err = lnwire.NewSigFromRawSignature(initiatorSig) + parsedSig, err = lnwire.NewSigFromSignature(initiatorSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -477,7 +477,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { if err != nil { t.Fatalf("unable to create close proposal: %v", err) } - parsedSig, err := lnwire.NewSigFromRawSignature(closeSig) + parsedSig, err := lnwire.NewSigFromSignature(closeSig) if err != nil { t.Fatalf("unable to parse signature: %v", err) } @@ -543,7 +543,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err = lnwire.NewSigFromRawSignature(responderSig) + parsedSig, err = lnwire.NewSigFromSignature(responderSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -589,7 +589,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err = lnwire.NewSigFromRawSignature(responderSig) + parsedSig, err = lnwire.NewSigFromSignature(responderSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } diff --git a/server.go b/server.go index a1dce6ec0d..fba2dd6fb3 100644 --- a/server.go +++ b/server.go @@ -981,7 +981,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, Notifier: cc.chainNotifier, FeeEstimator: cc.feeEstimator, SignMessage: func(pubKey *btcec.PublicKey, - msg []byte) (*btcec.Signature, error) { + msg []byte) (input.Signature, error) { if pubKey.IsEqual(privKey.PubKey()) { return s.nodeSigner.SignMessage(pubKey, msg) diff --git a/sweep/test_utils.go b/sweep/test_utils.go index 6b9b0d7236..7c28710be5 100644 --- a/sweep/test_utils.go +++ b/sweep/test_utils.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" @@ -18,13 +19,23 @@ var ( mockChainHeight = int32(100) ) +type dummySignature struct{} + +func (s *dummySignature) Serialize() []byte { + return []byte{} +} + +func (s *dummySignature) Verify(_ []byte, _ *btcec.PublicKey) bool { + return true +} + type mockSigner struct { } func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, - signDesc *input.SignDescriptor) ([]byte, error) { + signDesc *input.SignDescriptor) (input.Signature, error) { - return []byte{}, nil + return &dummySignature{}, nil } func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, diff --git a/watchtower/lookout/justice_descriptor_test.go b/watchtower/lookout/justice_descriptor_test.go index 7fd93c8c8a..6785f1b680 100644 --- a/watchtower/lookout/justice_descriptor_test.go +++ b/watchtower/lookout/justice_descriptor_test.go @@ -262,7 +262,7 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) { toRemoteSigRaw := toRemoteWitness[0][:len(toRemoteWitness[0])-1] // Convert the DER to-local sig into a fixed-size signature. - toLocalSig, err := lnwire.NewSigFromRawSignature(toLocalSigRaw) + toLocalSig, err := lnwire.NewSigFromSignature(toLocalSigRaw) if err != nil { t.Fatalf("unable to parse to-local signature: %v", err) } @@ -310,7 +310,7 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) { // Construct the test's to-local witness. justiceTxn.TxIn[0].Witness = make([][]byte, 3) - justiceTxn.TxIn[0].Witness[0] = append(toLocalSigRaw, + justiceTxn.TxIn[0].Witness[0] = append(toLocalSigRaw.Serialize(), byte(txscript.SigHashAll)) justiceTxn.TxIn[0].Witness[1] = []byte{1} justiceTxn.TxIn[0].Witness[2] = toLocalScript diff --git a/watchtower/wtmock/signer.go b/watchtower/wtmock/signer.go index c41e4f2f44..89421d6adb 100644 --- a/watchtower/wtmock/signer.go +++ b/watchtower/wtmock/signer.go @@ -30,7 +30,7 @@ func NewMockSigner() *MockSigner { // in the sign descriptor. The returned signature is the raw DER-encoded // signature without the signhash flag. func (s *MockSigner) SignOutputRaw(tx *wire.MsgTx, - signDesc *input.SignDescriptor) ([]byte, error) { + signDesc *input.SignDescriptor) (input.Signature, error) { s.mu.Lock() defer s.mu.Unlock() @@ -50,7 +50,7 @@ func (s *MockSigner) SignOutputRaw(tx *wire.MsgTx, return nil, err } - return sig[:len(sig)-1], nil + return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256()) } // ComputeInputScript is not implemented. From f2b6e2af04724936088303d3ba3daa1edf658230 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Sun, 5 Apr 2020 17:07:01 -0700 Subject: [PATCH 456/562] input: pass input.Signature to multisig spend Modifies SpendMultiSig to accept input.Signature, so that we can ultimately assert the size of multisig witnesses. --- chancloser.go | 13 ++++--- input/script_utils.go | 12 +++--- lnwallet/channel.go | 21 +++++++---- lnwallet/channel_test.go | 51 +++++++++++++------------- lnwallet/chanvalidate/validate_test.go | 18 ++++++++- lnwallet/test_utils.go | 18 +++++++-- 6 files changed, 85 insertions(+), 48 deletions(-) diff --git a/chancloser.go b/chancloser.go index befb6ccd85..b261a36576 100644 --- a/chancloser.go +++ b/chancloser.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" - "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" @@ -510,11 +509,15 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b // transaction! We'll craft the final closing transaction so // we can broadcast it to the network. matchingSig := c.priorFeeOffers[remoteProposedFee].Signature - localSigBytes := matchingSig.ToSignatureBytes() - localSig := append(localSigBytes, byte(txscript.SigHashAll)) + localSig, err := matchingSig.ToSignature() + if err != nil { + return nil, false, err + } - remoteSigBytes := closeSignedMsg.Signature.ToSignatureBytes() - remoteSig := append(remoteSigBytes, byte(txscript.SigHashAll)) + remoteSig, err := closeSignedMsg.Signature.ToSignature() + if err != nil { + return nil, false, err + } closeTx, _, err := c.cfg.channel.CompleteCooperativeClose( localSig, remoteSig, c.localDeliveryScript, diff --git a/input/script_utils.go b/input/script_utils.go index 97938ce8b4..318d1faed6 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -96,7 +96,9 @@ func GenFundingPkScript(aPub, bPub []byte, amt int64) ([]byte, *wire.TxOut, erro // SpendMultiSig generates the witness stack required to redeem the 2-of-2 p2wsh // multi-sig output. -func SpendMultiSig(witnessScript, pubA, sigA, pubB, sigB []byte) [][]byte { +func SpendMultiSig(witnessScript, pubA []byte, sigA Signature, + pubB []byte, sigB Signature) [][]byte { + witness := make([][]byte, 4) // When spending a p2wsh multi-sig script, rather than an OP_0, we add @@ -108,11 +110,11 @@ func SpendMultiSig(witnessScript, pubA, sigA, pubB, sigB []byte) [][]byte { // ensure the signatures appear on the Script Virtual Machine stack in // the correct order. if bytes.Compare(pubA, pubB) == 1 { - witness[1] = sigB - witness[2] = sigA + witness[1] = append(sigB.Serialize(), byte(txscript.SigHashAll)) + witness[2] = append(sigA.Serialize(), byte(txscript.SigHashAll)) } else { - witness[1] = sigA - witness[2] = sigB + witness[1] = append(sigA.Serialize(), byte(txscript.SigHashAll)) + witness[2] = append(sigB.Serialize(), byte(txscript.SigHashAll)) } // Finally, add the preimage as the last witness element. diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 33380deb2d..5f6eef9225 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -5065,18 +5065,22 @@ func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) { // for the transaction. localCommit := lc.channelState.LocalCommitment commitTx := localCommit.CommitTx.Copy() - theirSig := append(localCommit.CommitSig, byte(txscript.SigHashAll)) + + theirSig, err := btcec.ParseDERSignature( + localCommit.CommitSig, btcec.S256(), + ) + if err != nil { + return nil, err + } // With this, we then generate the full witness so the caller can // broadcast a fully signed transaction. lc.signDesc.SigHashes = txscript.NewTxSigHashes(commitTx) - ourSigRaw, err := lc.Signer.SignOutputRaw(commitTx, lc.signDesc) + ourSig, err := lc.Signer.SignOutputRaw(commitTx, lc.signDesc) if err != nil { return nil, err } - ourSig := append(ourSigRaw.Serialize(), byte(txscript.SigHashAll)) - // With the final signature generated, create the witness stack // required to spend from the multi-sig output. ourKey := lc.channelState.LocalChanCfg.MultiSigKey.PubKey. @@ -6017,7 +6021,8 @@ func (lc *LightningChannel) CreateCloseProposal(proposedFee btcutil.Amount, // // NOTE: The passed local and remote sigs are expected to be fully complete // signatures including the proper sighash byte. -func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte, +func (lc *LightningChannel) CompleteCooperativeClose( + localSig, remoteSig input.Signature, localDeliveryScript, remoteDeliveryScript []byte, proposedFee btcutil.Amount) (*wire.MsgTx, btcutil.Amount, error) { @@ -6070,8 +6075,10 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte, SerializeCompressed() theirKey := lc.channelState.RemoteChanCfg.MultiSigKey.PubKey. SerializeCompressed() - witness := input.SpendMultiSig(lc.signDesc.WitnessScript, ourKey, - localSig, theirKey, remoteSig) + witness := input.SpendMultiSig( + lc.signDesc.WitnessScript, ourKey, localSig, theirKey, + remoteSig, + ) closeTx.TxIn[0].Witness = witness // Validate the finalized transaction to ensure the output script is diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 8a7711fea9..318c0b9607 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -616,7 +616,6 @@ func TestCooperativeChannelClosure(t *testing.T) { if err != nil { t.Fatalf("unable to create alice coop close proposal: %v", err) } - aliceCloseSig := append(aliceSig.Serialize(), byte(txscript.SigHashAll)) bobFee := bobChannel.CalcFee(bobFeeRate) bobSig, _, _, err := bobChannel.CreateCloseProposal( @@ -625,14 +624,13 @@ func TestCooperativeChannelClosure(t *testing.T) { if err != nil { t.Fatalf("unable to create bob coop close proposal: %v", err) } - bobCloseSig := append(bobSig.Serialize(), byte(txscript.SigHashAll)) // With the proposals created, both sides should be able to properly // process the other party's signature. This indicates that the // transaction is well formed, and the signatures verify. aliceCloseTx, _, err := bobChannel.CompleteCooperativeClose( - bobCloseSig, aliceCloseSig, bobDeliveryScript, - aliceDeliveryScript, bobFee, + bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript, + bobFee, ) if err != nil { t.Fatalf("unable to complete alice cooperative close: %v", err) @@ -640,8 +638,8 @@ func TestCooperativeChannelClosure(t *testing.T) { bobCloseSha := aliceCloseTx.TxHash() bobCloseTx, _, err := aliceChannel.CompleteCooperativeClose( - aliceCloseSig, bobCloseSig, aliceDeliveryScript, - bobDeliveryScript, aliceFee, + aliceSig, bobSig, aliceDeliveryScript, bobDeliveryScript, + aliceFee, ) if err != nil { t.Fatalf("unable to complete bob cooperative close: %v", err) @@ -2054,24 +2052,25 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { // balances. As a result, performing a cooperative closure now result // in both sides having an output within the closure transaction. aliceFee := btcutil.Amount(aliceChannel.CalcFee(aliceFeeRate)) + 1000 - aliceSig, _, _, err := aliceChannel.CreateCloseProposal(aliceFee, - aliceDeliveryScript, bobDeliveryScript) + aliceSig, _, _, err := aliceChannel.CreateCloseProposal( + aliceFee, aliceDeliveryScript, bobDeliveryScript, + ) if err != nil { t.Fatalf("unable to close channel: %v", err) } - aliceCloseSig := append(aliceSig.Serialize(), byte(txscript.SigHashAll)) bobFee := btcutil.Amount(bobChannel.CalcFee(bobFeeRate)) + 1000 - bobSig, _, _, err := bobChannel.CreateCloseProposal(bobFee, - bobDeliveryScript, aliceDeliveryScript) + bobSig, _, _, err := bobChannel.CreateCloseProposal( + bobFee, bobDeliveryScript, aliceDeliveryScript, + ) if err != nil { t.Fatalf("unable to close channel: %v", err) } - bobCloseSig := append(bobSig.Serialize(), byte(txscript.SigHashAll)) closeTx, _, err := bobChannel.CompleteCooperativeClose( - bobCloseSig, aliceCloseSig, - bobDeliveryScript, aliceDeliveryScript, bobFee) + bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript, + bobFee, + ) if err != nil { t.Fatalf("unable to accept channel close: %v", err) } @@ -2093,23 +2092,24 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { // Attempt another cooperative channel closure. It should succeed // without any issues. - aliceSig, _, _, err = aliceChannel.CreateCloseProposal(aliceFee, - aliceDeliveryScript, bobDeliveryScript) + aliceSig, _, _, err = aliceChannel.CreateCloseProposal( + aliceFee, aliceDeliveryScript, bobDeliveryScript, + ) if err != nil { t.Fatalf("unable to close channel: %v", err) } - aliceCloseSig = append(aliceSig.Serialize(), byte(txscript.SigHashAll)) - bobSig, _, _, err = bobChannel.CreateCloseProposal(bobFee, - bobDeliveryScript, aliceDeliveryScript) + bobSig, _, _, err = bobChannel.CreateCloseProposal( + bobFee, bobDeliveryScript, aliceDeliveryScript, + ) if err != nil { t.Fatalf("unable to close channel: %v", err) } - bobCloseSig = append(bobSig.Serialize(), byte(txscript.SigHashAll)) closeTx, _, err = bobChannel.CompleteCooperativeClose( - bobCloseSig, aliceCloseSig, - bobDeliveryScript, aliceDeliveryScript, bobFee) + bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript, + bobFee, + ) if err != nil { t.Fatalf("unable to accept channel close: %v", err) } @@ -2141,7 +2141,6 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { if err != nil { t.Fatalf("unable to close channel: %v", err) } - aliceCloseSig = append(aliceSig.Serialize(), byte(txscript.SigHashAll)) bobSig, _, _, err = bobChannel.CreateCloseProposal( bobFee, bobDeliveryScript, aliceDeliveryScript, @@ -2149,11 +2148,11 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { if err != nil { t.Fatalf("unable to close channel: %v", err) } - bobCloseSig = append(bobSig.Serialize(), byte(txscript.SigHashAll)) closeTx, _, err = bobChannel.CompleteCooperativeClose( - bobCloseSig, aliceCloseSig, - bobDeliveryScript, aliceDeliveryScript, bobFee) + bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript, + bobFee, + ) if err != nil { t.Fatalf("unable to accept channel close: %v", err) } diff --git a/lnwallet/chanvalidate/validate_test.go b/lnwallet/chanvalidate/validate_test.go index 12bb5c093e..e979b014b0 100644 --- a/lnwallet/chanvalidate/validate_test.go +++ b/lnwallet/chanvalidate/validate_test.go @@ -98,7 +98,7 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) { } sigHashes := txscript.NewTxSigHashes(commitTx) - aliceSig, err := txscript.RawTxInWitnessSignature( + aliceSigRaw, err := txscript.RawTxInWitnessSignature( commitTx, sigHashes, 0, chanSize, multiSigScript, txscript.SigHashAll, alicePriv, ) @@ -106,7 +106,14 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) { return nil, err } - bobSig, err := txscript.RawTxInWitnessSignature( + aliceSig, err := btcec.ParseDERSignature( + aliceSigRaw, btcec.S256(), + ) + if err != nil { + return nil, err + } + + bobSigRaw, err := txscript.RawTxInWitnessSignature( commitTx, sigHashes, 0, chanSize, multiSigScript, txscript.SigHashAll, bobPriv, ) @@ -114,6 +121,13 @@ func newChannelTestCtx(chanSize int64) (*channelTestCtx, error) { return nil, err } + bobSig, err := btcec.ParseDERSignature( + bobSigRaw, btcec.S256(), + ) + if err != nil { + return nil, err + } + commitTx.TxIn[0].Witness = input.SpendMultiSig( multiSigScript, alicePub.SerializeCompressed(), aliceSig, bobPub.SerializeCompressed(), bobSig, diff --git a/lnwallet/test_utils.go b/lnwallet/test_utils.go index cbe1b2b3e3..55d8a3420c 100644 --- a/lnwallet/test_utils.go +++ b/lnwallet/test_utils.go @@ -1,7 +1,6 @@ package lnwallet import ( - "bytes" "crypto/rand" "encoding/binary" "encoding/hex" @@ -81,6 +80,19 @@ var ( }, LockTime: 5, } + + // A valid, DER-encoded signature (taken from btcec unit tests). + testSigBytes = []byte{ + 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, + 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, + 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, + 0xe9, 0xd6, 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, + 0x5f, 0xb8, 0xcd, 0x41, 0x02, 0x20, 0x18, 0x15, + 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60, + 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, + 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, + 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, + } ) // CreateTestChannels creates to fully populated channels to be used within @@ -257,7 +269,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) ( CommitFee: commitFee, FeePerKw: btcutil.Amount(feePerKw), CommitTx: aliceCommitTx, - CommitSig: bytes.Repeat([]byte{1}, 71), + CommitSig: testSigBytes, } bobCommit := channeldb.ChannelCommitment{ CommitHeight: 0, @@ -266,7 +278,7 @@ func CreateTestChannels(chanType channeldb.ChannelType) ( CommitFee: commitFee, FeePerKw: btcutil.Amount(feePerKw), CommitTx: bobCommitTx, - CommitSig: bytes.Repeat([]byte{1}, 71), + CommitSig: testSigBytes, } var chanIDBytes [8]byte From c1b9b272cda02948a0941a04da1b58fd6d164397 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Sun, 5 Apr 2020 17:07:14 -0700 Subject: [PATCH 457/562] input/size: assert witness size constants This commit introduces a new test case that asserts all of the witness size constants currently in the codebase. We also reintroduce the AcceptedHtlcSuccessWitnessSize and OfferedHtlcTimeoutWitnessSize constants that were recently removed for the sake of completeness. In asserting the witnes sizes, there were three uncovered discrepancies: * OfferedHtlcSuccessWitnessSize overestimated by about 30% because it included an extra signature in the calculation. * ToLocalPenaltyWitnessSize was underestimated by one byte, because it was missing the length byte for the OP_TRUE. This has implications the watchtower protocol since the client and server are assumed to share the same weight estimates used for signing. This commit keeps the current behavior, with the intention of rolling out negotiation for which weight estimate to use for a given session. * AcceptedHtlcScriptSize was underestimated by one byte because it was missing a length byte for the value 32 pushed on the stack when asserting the preimage's length. This affects all AcceptedHtlc* witness sizes. --- input/size.go | 113 ++-- input/size_test.go | 573 +++++++++++++++++- lnrpc/signrpc/signer_server.go | 2 +- sweep/txgenerator_test.go | 2 +- watchtower/lookout/justice_descriptor.go | 14 +- watchtower/lookout/justice_descriptor_test.go | 8 +- watchtower/wtclient/backup_task.go | 9 +- 7 files changed, 648 insertions(+), 73 deletions(-) diff --git a/input/size.go b/input/size.go index 74f1247d5b..6cebc28241 100644 --- a/input/size.go +++ b/input/size.go @@ -1,12 +1,8 @@ package input import ( - "math/big" - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" - "github.com/lightningnetwork/lnd/keychain" ) const ( @@ -94,7 +90,7 @@ const ( // - OP_CHECKMULTISIG: 1 byte MultiSigSize = 1 + 1 + 33 + 1 + 33 + 1 + 1 - // WitnessSize 222 bytes + // MultiSigWitnessSize 222 bytes // - NumberOfWitnessElements: 1 byte // - NilLength: 1 byte // - sigAliceLength: 1 byte @@ -103,7 +99,7 @@ const ( // - sigBob: 73 bytes // - WitnessScriptLength: 1 byte // - WitnessScript (MultiSig) - WitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + MultiSigSize + MultiSigWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + MultiSigSize // InputSize 41 bytes // - PreviousOutPoint: @@ -177,7 +173,7 @@ const ( BaseCommitmentTxWeight = witnessScaleFactor * BaseCommitmentTxSize // WitnessCommitmentTxWeight 224 weight - WitnessCommitmentTxWeight = WitnessHeaderSize + WitnessSize + WitnessCommitmentTxWeight = WitnessHeaderSize + MultiSigWitnessSize // BaseAnchorCommitmentTxSize 225 + 43 * num-htlc-outputs bytes // - Version: 4 bytes @@ -264,14 +260,15 @@ const ( // - witness_script (to_local_script) ToLocalTimeoutWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize - // ToLocalPenaltyWitnessSize 156 bytes + // ToLocalPenaltyWitnessSize 157 bytes // - number_of_witness_elements: 1 byte // - revocation_sig_length: 1 byte // - revocation_sig: 73 bytes + // - OP_TRUE_length: 1 byte // - OP_TRUE: 1 byte // - witness_script_length: 1 byte // - witness_script (to_local_script) - ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + ToLocalScriptSize + ToLocalPenaltyWitnessSize = 1 + 1 + 73 + 1 + 1 + 1 + ToLocalScriptSize // ToRemoteConfirmedScriptSize 37 bytes // - OP_DATA: 1 byte @@ -289,7 +286,7 @@ const ( // - witness_script (to_remote_delayed_script) ToRemoteConfirmedWitnessSize = 1 + 1 + 73 + 1 + ToRemoteConfirmedScriptSize - // AcceptedHtlcScriptSize 142 bytes + // AcceptedHtlcScriptSize 143 bytes // - OP_DUP: 1 byte // - OP_HASH160: 1 byte // - OP_DATA: 1 byte (RIPEMD160(SHA256(revocationkey)) length) @@ -302,6 +299,7 @@ const ( // - remotekey: 33 bytes // - OP_SWAP: 1 byte // - OP_SIZE: 1 byte + // - OP_DATA: 1 byte (32 length) // - 32: 1 byte // - OP_EQUAL: 1 byte // - OP_IF: 1 byte @@ -327,7 +325,7 @@ const ( // - OP_CSV: 1 byte // HTLC script types. The size won't be correct in all cases, // - OP_DROP: 1 byte // but it is just an upper bound used for fee estimation in any case. // - OP_ENDIF: 1 byte - AcceptedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 7*1 + 20 + 4*1 + + AcceptedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 8*1 + 20 + 4*1 + 33 + 5*1 + 4 + 8*1 // AcceptedHtlcTimeoutWitnessSize 219 @@ -349,6 +347,20 @@ const ( // - witness_script (accepted_htlc_script) AcceptedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + AcceptedHtlcScriptSize + // AcceptedHtlcSuccessWitnessSize 322 bytes + // - number_of_witness_elements: 1 byte + // - nil_length: 1 byte + // - sig_alice_length: 1 byte + // - sig_alice: 73 bytes + // - sig_bob_length: 1 byte + // - sig_bob: 73 bytes + // - preimage_length: 1 byte + // - preimage: 32 bytes + // - witness_script_length: 1 byte + // - witness_script (accepted_htlc_script) + AcceptedHtlcSuccessWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 32 + 1 + + AcceptedHtlcScriptSize + // OfferedHtlcScriptSize 136 bytes // - OP_DUP: 1 byte // - OP_HASH160: 1 byte @@ -386,18 +398,27 @@ const ( // - OP_ENDIF: 1 byte OfferedHtlcScriptSize = 3*1 + 20 + 5*1 + 33 + 10*1 + 33 + 5*1 + 20 + 7*1 - // OfferedHtlcSuccessWitnessSize 320 bytes + // OfferedHtlcSuccessWitnessSize 245 bytes // - number_of_witness_elements: 1 byte - // - nil_length: 1 byte // - receiver_sig_length: 1 byte // - receiver_sig: 73 bytes - // - sender_sig_length: 1 byte - // - sender_sig: 73 bytes // - payment_preimage_length: 1 byte // - payment_preimage: 32 bytes // - witness_script_length: 1 byte // - witness_script (offered_htlc_script) - OfferedHtlcSuccessWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 32 + 1 + OfferedHtlcScriptSize + OfferedHtlcSuccessWitnessSize = 1 + 1 + 73 + 1 + 32 + 1 + OfferedHtlcScriptSize + + // OfferedHtlcTimeoutWitnessSize 285 bytes + // - number_of_witness_elements: 1 byte + // - nil_length: 1 byte + // - sig_alice_length: 1 byte + // - sig_alice: 73 bytes + // - sig_bob_length: 1 byte + // - sig_bob: 73 bytes + // - nil_length: 1 byte + // - witness_script_length: 1 byte + // - witness_script (offered_htlc_script) + OfferedHtlcTimeoutWitnessSize = 1 + 1 + 1 + 73 + 1 + 73 + 1 + 1 + OfferedHtlcScriptSize // OfferedHtlcPenaltyWitnessSize 246 bytes // - number_of_witness_elements: 1 byte @@ -408,53 +429,25 @@ const ( // - witness_script_length: 1 byte // - witness_script (offered_htlc_script) OfferedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + OfferedHtlcScriptSize -) - -type dummySignature struct{} - -func (d *dummySignature) Serialize() []byte { - // Always return worst-case signature length, excluding the one byte - // sighash flag. - return make([]byte, 73-1) -} - -// dummySigner is a fake signer used for size (upper bound) calculations. -type dummySigner struct { - Signer -} - -// SignOutputRaw generates a signature for the passed transaction according to -// the data within the passed SignDescriptor. -func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx, - signDesc *SignDescriptor) (Signature, error) { - - return &dummySignature{}, nil -} - -var ( - // dummyPubKey is a pubkey used in script size calculation. - dummyPubKey = btcec.PublicKey{ - X: &big.Int{}, - Y: &big.Int{}, - } - // dummyAnchorScript is a script used for size calculation. - dummyAnchorScript, _ = CommitScriptAnchor(&dummyPubKey) - - // dummyAnchorWitness is a witness used for size calculation. - dummyAnchorWitness, _ = CommitSpendAnchor( - &dummySigner{}, - &SignDescriptor{ - KeyDesc: keychain.KeyDescriptor{ - PubKey: &dummyPubKey, - }, - WitnessScript: dummyAnchorScript, - }, - nil, - ) + // AnchorScriptSize 40 bytes + // - pubkey_length: 1 byte + // - pubkey: 33 bytes + // - OP_CHECKSIG: 1 byte + // - OP_IFDUP: 1 byte + // - OP_NOTIF: 1 byte + // - OP_16: 1 byte + // - OP_CSV 1 byte + // - OP_ENDIF: 1 byte + AnchorScriptSize = 1 + 33 + 6*1 // AnchorWitnessSize 116 bytes - AnchorWitnessSize = dummyAnchorWitness.SerializeSize() + // - number_of_witnes_elements: 1 byte + // - signature_length: 1 byte + // - signature: 73 bytes + // - witness_script_length: 1 byte + // - witness_script (anchor_script) + AnchorWitnessSize = 1 + 1 + 73 + 1 + AnchorScriptSize ) // EstimateCommitTxWeight estimate commitment transaction weight depending on diff --git a/input/size_test.go b/input/size_test.go index fb57427c3b..c7c2dc1b3a 100644 --- a/input/size_test.go +++ b/input/size_test.go @@ -1,15 +1,45 @@ package input_test import ( + "math/big" "testing" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" +) + +const ( + testCSVDelay = (1 << 31) - 1 + + testCLTVExpiry = 500000000 + + // maxDERSignatureSize is the largest possible DER-encoded signature + // without the trailing sighash flag. + maxDERSignatureSize = 72 +) + +var ( + testPubkeyBytes = make([]byte, 33) + + testHash160 = make([]byte, 20) + testPreimage = make([]byte, 32) + + // testPubkey is a pubkey used in script size calculation. + testPubkey = &btcec.PublicKey{ + X: &big.Int{}, + Y: &big.Int{}, + } + + testPrivkey, _ = btcec.PrivKeyFromBytes(btcec.S256(), make([]byte, 32)) + + testTx = wire.NewMsgTx(2) ) // TestTxWeightEstimator tests that transaction weight estimates are calculated @@ -204,7 +234,7 @@ func TestTxWeightEstimator(t *testing.T) { for j := 0; j < test.numP2PKHInputs; j++ { weightEstimate.AddP2PKHInput() - signature := make([]byte, 73) + signature := make([]byte, maxDERSignatureSize+1) compressedPubKey := make([]byte, 33) scriptSig, err := txscript.NewScriptBuilder().AddData(signature). AddData(compressedPubKey).Script() @@ -217,7 +247,7 @@ func TestTxWeightEstimator(t *testing.T) { for j := 0; j < test.numP2WKHInputs; j++ { weightEstimate.AddP2WKHInput() - signature := make([]byte, 73) + signature := make([]byte, maxDERSignatureSize+1) compressedPubKey := make([]byte, 33) witness := wire.TxWitness{signature, compressedPubKey} tx.AddTxIn(&wire.TxIn{Witness: witness}) @@ -232,7 +262,7 @@ func TestTxWeightEstimator(t *testing.T) { for j := 0; j < test.numNestedP2WKHInputs; j++ { weightEstimate.AddNestedP2WKHInput() - signature := make([]byte, 73) + signature := make([]byte, maxDERSignatureSize+1) compressedPubKey := make([]byte, 33) witness := wire.TxWitness{signature, compressedPubKey} scriptSig, err := txscript.NewScriptBuilder().AddData(p2wkhScript). @@ -281,10 +311,537 @@ func TestTxWeightEstimator(t *testing.T) { } } -// TestSizes guards calculated constants to make sure their values remain -// unchanged. -func TestSizes(t *testing.T) { - if input.AnchorWitnessSize != 116 { - t.Fatal("unexpected anchor witness size") +type maxDERSignature struct{} + +func (s *maxDERSignature) Serialize() []byte { + // Always return worst-case signature length, excluding the one byte + // sighash flag. + return make([]byte, maxDERSignatureSize) +} + +func (s *maxDERSignature) Verify(_ []byte, _ *btcec.PublicKey) bool { + return true +} + +// dummySigner is a fake signer used for size (upper bound) calculations. +type dummySigner struct { + input.Signer +} + +// SignOutputRaw generates a signature for the passed transaction according to +// the data within the passed SignDescriptor. +func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx, + signDesc *input.SignDescriptor) (input.Signature, error) { + + return &maxDERSignature{}, nil +} + +type witnessSizeTest struct { + name string + expSize int + genWitness func(t *testing.T) wire.TxWitness +} + +var witnessSizeTests = []witnessSizeTest{ + { + name: "funding", + expSize: input.MultiSigWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witnessScript, _, err := input.GenFundingPkScript( + testPubkeyBytes, testPubkeyBytes, 1, + ) + if err != nil { + t.Fatal(err) + } + + return input.SpendMultiSig( + witnessScript, + testPubkeyBytes, &maxDERSignature{}, + testPubkeyBytes, &maxDERSignature{}, + ) + }, + }, + { + name: "to local timeout", + expSize: input.ToLocalTimeoutWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witnessScript, err := input.CommitScriptToSelf( + testCSVDelay, testPubkey, testPubkey, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witnessScript, + } + + witness, err := input.CommitSpendTimeout( + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "to local revoke", + expSize: input.ToLocalPenaltyWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witnessScript, err := input.CommitScriptToSelf( + testCSVDelay, testPubkey, testPubkey, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witnessScript, + } + + witness, err := input.CommitSpendRevoke( + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "to remote confirmed", + expSize: input.ToRemoteConfirmedWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.CommitScriptToRemoteConfirmed( + testPubkey, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + KeyDesc: keychain.KeyDescriptor{ + PubKey: testPubkey, + }, + } + + witness, err := input.CommitSpendToRemoteConfirmed( + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "anchor", + expSize: input.AnchorWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.CommitScriptAnchor( + testPubkey, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + KeyDesc: keychain.KeyDescriptor{ + PubKey: testPubkey, + }, + } + + witness, err := input.CommitSpendAnchor( + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "anchor anyone", + expSize: 43, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.CommitScriptAnchor( + testPubkey, + ) + if err != nil { + t.Fatal(err) + } + + witness, _ := input.CommitSpendAnchorAnyone(witScript) + + return witness + }, + }, + { + name: "offered htlc revoke", + expSize: input.OfferedHtlcPenaltyWitnessSize - 3, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.SenderHTLCScript( + testPubkey, testPubkey, testPubkey, + testHash160, false, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + KeyDesc: keychain.KeyDescriptor{ + PubKey: testPubkey, + }, + DoubleTweak: testPrivkey, + } + + witness, err := input.SenderHtlcSpendRevoke( + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "offered htlc revoke confirmed", + expSize: input.OfferedHtlcPenaltyWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + hash := make([]byte, 20) + + witScript, err := input.SenderHTLCScript( + testPubkey, testPubkey, testPubkey, + hash, true, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + KeyDesc: keychain.KeyDescriptor{ + PubKey: testPubkey, + }, + DoubleTweak: testPrivkey, + } + + witness, err := input.SenderHtlcSpendRevoke( + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "offered htlc timeout", + expSize: input.OfferedHtlcTimeoutWitnessSize - 3, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.SenderHTLCScript( + testPubkey, testPubkey, testPubkey, + testHash160, false, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + } + + witness, err := input.SenderHtlcSpendTimeout( + &maxDERSignature{}, txscript.SigHashAll, + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "offered htlc timeout confirmed", + expSize: input.OfferedHtlcTimeoutWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.SenderHTLCScript( + testPubkey, testPubkey, testPubkey, + testHash160, true, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + } + + witness, err := input.SenderHtlcSpendTimeout( + &maxDERSignature{}, txscript.SigHashAll, + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "offered htlc success", + expSize: input.OfferedHtlcSuccessWitnessSize - 3, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.SenderHTLCScript( + testPubkey, testPubkey, testPubkey, + testHash160, false, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + } + + witness, err := input.SenderHtlcSpendRedeem( + &dummySigner{}, signDesc, testTx, testPreimage, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "offered htlc success confirmed", + expSize: input.OfferedHtlcSuccessWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.SenderHTLCScript( + testPubkey, testPubkey, testPubkey, + testHash160, true, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + } + + witness, err := input.SenderHtlcSpendRedeem( + &dummySigner{}, signDesc, testTx, testPreimage, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "accepted htlc revoke", + expSize: input.AcceptedHtlcPenaltyWitnessSize - 3, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.ReceiverHTLCScript( + testCLTVExpiry, testPubkey, testPubkey, + testPubkey, testHash160, false, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + KeyDesc: keychain.KeyDescriptor{ + PubKey: testPubkey, + }, + DoubleTweak: testPrivkey, + } + + witness, err := input.ReceiverHtlcSpendRevoke( + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "accepted htlc revoke confirmed", + expSize: input.AcceptedHtlcPenaltyWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.ReceiverHTLCScript( + testCLTVExpiry, testPubkey, testPubkey, + testPubkey, testHash160, true, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + KeyDesc: keychain.KeyDescriptor{ + PubKey: testPubkey, + }, + DoubleTweak: testPrivkey, + } + + witness, err := input.ReceiverHtlcSpendRevoke( + &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "accepted htlc timeout", + expSize: input.AcceptedHtlcTimeoutWitnessSize - 3, + genWitness: func(t *testing.T) wire.TxWitness { + + witScript, err := input.ReceiverHTLCScript( + testCLTVExpiry, testPubkey, testPubkey, + testPubkey, testHash160, false, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + } + + witness, err := input.ReceiverHtlcSpendTimeout( + &dummySigner{}, signDesc, testTx, + testCLTVExpiry, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "accepted htlc timeout confirmed", + expSize: input.AcceptedHtlcTimeoutWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.ReceiverHTLCScript( + testCLTVExpiry, testPubkey, testPubkey, + testPubkey, testHash160, true, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + } + + witness, err := input.ReceiverHtlcSpendTimeout( + &dummySigner{}, signDesc, testTx, + testCLTVExpiry, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "accepted htlc success", + expSize: input.AcceptedHtlcSuccessWitnessSize - 3, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.ReceiverHTLCScript( + testCLTVExpiry, testPubkey, testPubkey, + testPubkey, testHash160, false, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + KeyDesc: keychain.KeyDescriptor{ + PubKey: testPubkey, + }, + } + + witness, err := input.ReceiverHtlcSpendRedeem( + &maxDERSignature{}, txscript.SigHashAll, + testPreimage, &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, + { + name: "accepted htlc success confirmed", + expSize: input.AcceptedHtlcSuccessWitnessSize, + genWitness: func(t *testing.T) wire.TxWitness { + witScript, err := input.ReceiverHTLCScript( + testCLTVExpiry, testPubkey, testPubkey, + testPubkey, testHash160, true, + ) + if err != nil { + t.Fatal(err) + } + + signDesc := &input.SignDescriptor{ + WitnessScript: witScript, + KeyDesc: keychain.KeyDescriptor{ + PubKey: testPubkey, + }, + } + + witness, err := input.ReceiverHtlcSpendRedeem( + &maxDERSignature{}, txscript.SigHashAll, + testPreimage, &dummySigner{}, signDesc, testTx, + ) + if err != nil { + t.Fatal(err) + } + + return witness + }, + }, +} + +// TestWitnessSizes asserts the correctness of our magic witness constants. +// Witnesses involving signatures will have maxDERSignatures injected so that we +// can determine upper bounds for the witness sizes. These constants are +// predominately used for fee estimation, so we want to be certain that we +// aren't under estimating or our transactions could get stuck. +func TestWitnessSizes(t *testing.T) { + for _, test := range witnessSizeTests { + test := test + t.Run(test.name, func(t *testing.T) { + size := test.genWitness(t).SerializeSize() + if size != test.expSize { + t.Fatalf("size mismatch, want: %v, got: %v", + test.expSize, size) + } + }) } } diff --git a/lnrpc/signrpc/signer_server.go b/lnrpc/signrpc/signer_server.go index e51fe5d00e..127d113e70 100644 --- a/lnrpc/signrpc/signer_server.go +++ b/lnrpc/signrpc/signer_server.go @@ -321,7 +321,7 @@ func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp, err return nil, err } - resp.RawSigs[i] = sig + resp.RawSigs[i] = sig.Serialize() } return resp, nil diff --git a/sweep/txgenerator_test.go b/sweep/txgenerator_test.go index 91641e5e59..575ae65aa3 100644 --- a/sweep/txgenerator_test.go +++ b/sweep/txgenerator_test.go @@ -15,7 +15,7 @@ var ( input.HtlcOfferedRemoteTimeout, input.WitnessKeyHash, } - expectedWeight = int64(1462) + expectedWeight = int64(1463) expectedSummary = "0000000000000000000000000000000000000000000000000000000000000000:10 (CommitmentTimeLock), " + "0000000000000000000000000000000000000000000000000000000000000001:11 (HtlcAcceptedSuccessSecondLevel), " + "0000000000000000000000000000000000000000000000000000000000000002:12 (HtlcOfferedRemoteTimeout), " + diff --git a/watchtower/lookout/justice_descriptor.go b/watchtower/lookout/justice_descriptor.go index 40e5a479e1..cea3ae0327 100644 --- a/watchtower/lookout/justice_descriptor.go +++ b/watchtower/lookout/justice_descriptor.go @@ -225,6 +225,12 @@ func (p *JusticeDescriptor) assembleJusticeTxn(txWeight int64, // CreateJusticeTxn computes the justice transaction that sweeps a breaching // commitment transaction. The justice transaction is constructed by assembling // the witnesses using data provided by the client in a prior state update. +// +// NOTE: An older version of ToLocalPenaltyWitnessSize underestimated the size +// of the witness by one byte, which could cause the signature(s) to break if +// the tower is reconstructing with the newer constant because the output values +// might differ. This method retains that original behavior to not invalidate +// historical signatures. func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) { var ( sweepInputs = make([]*breachedInput, 0, 2) @@ -256,7 +262,13 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) { if err != nil { return nil, err } - weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize) + + // An older ToLocalPenaltyWitnessSize constant used to underestimate the + // size by one byte. The diferrence in weight can cause different output + // values on the sweep transaction, so we mimic the original bug to + // avoid invalidating signatures by older clients. + weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize - 1) + sweepInputs = append(sweepInputs, toLocalInput) // If the justice kit specifies that we have to sweep the to-remote diff --git a/watchtower/lookout/justice_descriptor_test.go b/watchtower/lookout/justice_descriptor_test.go index 6785f1b680..afc4dacd6f 100644 --- a/watchtower/lookout/justice_descriptor_test.go +++ b/watchtower/lookout/justice_descriptor_test.go @@ -144,7 +144,13 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) { // Compute the weight estimate for our justice transaction. var weightEstimate input.TxWeightEstimator - weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize) + + // An older ToLocalPenaltyWitnessSize constant used to underestimate the + // size by one byte. The diferrence in weight can cause different output + // values on the sweep transaction, so we mimic the original bug and + // create signatures using the original weight estimate. + weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize - 1) + weightEstimate.AddWitnessInput(input.P2WKHWitnessSize) weightEstimate.AddP2WKHOutput() if blobType.Has(blob.FlagReward) { diff --git a/watchtower/wtclient/backup_task.go b/watchtower/wtclient/backup_task.go index c112c10163..302a6bc3bf 100644 --- a/watchtower/wtclient/backup_task.go +++ b/watchtower/wtclient/backup_task.go @@ -141,7 +141,14 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody) error { // Next, add the contribution from the inputs that are present on this // breach transaction. if t.toLocalInput != nil { - weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize) + // An older ToLocalPenaltyWitnessSize constant used to + // underestimate the size by one byte. The diferrence in weight + // can cause different output values on the sweep transaction, + // so we mimic the original bug and create signatures using the + // original weight estimate. + weightEstimate.AddWitnessInput( + input.ToLocalPenaltyWitnessSize - 1, + ) } if t.toRemoteInput != nil { weightEstimate.AddWitnessInput(input.P2WKHWitnessSize) From f71cc951fd3f22c429687e1d28b7f51cab35c47b Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 10 Apr 2020 16:01:21 -0700 Subject: [PATCH 458/562] channeldb/channel: fix HasChanStatus for ChanStatusDefault This commit resovles a lingering issue w/in the codebase wrt how the ChannelStatus flags are defined. Currently ChannelStatus is improperly used to define a bit field and the individual flags themselves. As a result, HasChanStatus accepts queries on particular status (combinations of flags) and individual flags themselves. This is an issue because the way HasChanStatus computes whether the channel has a particular status assumes the provided inputs are all flags (or at least combinations of flags). However, ChanStatusDefault is simply the absence of any other flag. Hence, HasChanStatus will always return true when querying for ChanStatusDefault because status&0 == 0 is always true. Longer term we should should consider splitting these definitions into flags and particular states, and change the way construct or operate on them, but for now I've just special-cased this one value. Fortunately, we don't query HasChannelStatus w/ ChanStatusDefault anywhere in the codebase so we dodge a bullet here, but it'd be nice to have some greater assurances moving forward. --- channeldb/channel.go | 6 ++++ channeldb/channel_test.go | 59 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/channeldb/channel.go b/channeldb/channel.go index 21468b7f32..e2e6658dd3 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -711,6 +711,12 @@ func (c *OpenChannel) HasChanStatus(status ChannelStatus) bool { } func (c *OpenChannel) hasChanStatus(status ChannelStatus) bool { + // Special case ChanStatusDefualt since it isn't actually flag, but a + // particular combination (or lack-there-of) of flags. + if status == ChanStatusDefault { + return c.chanStatus == ChanStatusDefault + } + return c.chanStatus&status == status } diff --git a/channeldb/channel_test.go b/channeldb/channel_test.go index eb068485e5..6b1e0ab8b1 100644 --- a/channeldb/channel_test.go +++ b/channeldb/channel_test.go @@ -1581,3 +1581,62 @@ func TestBalanceAtHeight(t *testing.T) { }) } } + +// TestHasChanStatus asserts the behavior of HasChanStatus by checking the +// behavior of various status flags in addition to the special case of +// ChanStatusDefault which is treated like a flag in the code base even though +// it isn't. +func TestHasChanStatus(t *testing.T) { + tests := []struct { + name string + status ChannelStatus + expHas map[ChannelStatus]bool + }{ + { + name: "default", + status: ChanStatusDefault, + expHas: map[ChannelStatus]bool{ + ChanStatusDefault: true, + ChanStatusBorked: false, + }, + }, + { + name: "single flag", + status: ChanStatusBorked, + expHas: map[ChannelStatus]bool{ + ChanStatusDefault: false, + ChanStatusBorked: true, + }, + }, + { + name: "multiple flags", + status: ChanStatusBorked | ChanStatusLocalDataLoss, + expHas: map[ChannelStatus]bool{ + ChanStatusDefault: false, + ChanStatusBorked: true, + ChanStatusLocalDataLoss: true, + }, + }, + } + + for _, test := range tests { + test := test + + t.Run(test.name, func(t *testing.T) { + c := &OpenChannel{ + chanStatus: test.status, + } + + for status, expHas := range test.expHas { + has := c.HasChanStatus(status) + if has == expHas { + continue + } + + t.Fatalf("expected chan status to "+ + "have %s? %t, got: %t", + status, expHas, has) + } + }) + } +} From 93089aaaf8d4ad0d5c054283fea3a07891bfec55 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 10 Apr 2020 16:10:48 -0700 Subject: [PATCH 459/562] channeldb/channel: don't print ChanStatusDefault when it's not This commit removes ChanStatusDefault from the list of orderedChanStatusFlags since it is not flag. As with the prior commit, the logic around these flags assumes everything in the list is a flag, but ChanStatusDefault is not. It turns out we properly special case that if the channel is in ChanStatusDefault that we only return ChanStatusDefault. However, if any of the bits are set we would always report ChanStatusDefault since status&0 == 0. This fixed simply by removing ChanStatusDefault from the list since we only need the list to express non-default status flags. --- channeldb/channel.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index e2e6658dd3..2031b7b337 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -475,7 +475,6 @@ var chanStatusStrings = map[ChannelStatus]string{ // orderedChanStatusFlags is an in-order list of all that channel status flags. var orderedChanStatusFlags = []ChannelStatus{ - ChanStatusDefault, ChanStatusBorked, ChanStatusCommitBroadcasted, ChanStatusLocalDataLoss, @@ -488,7 +487,7 @@ var orderedChanStatusFlags = []ChannelStatus{ // String returns a human-readable representation of the ChannelStatus. func (c ChannelStatus) String() string { // If no flags are set, then this is the default case. - if c == 0 { + if c == ChanStatusDefault { return chanStatusStrings[ChanStatusDefault] } From 06bd645e5d8f874946597423efe676a3d64396ef Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:03:27 -0700 Subject: [PATCH 460/562] build/version: fix incomplete semanticAlphabet godoc --- build/version.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index af068c441f..ad6fdebcc6 100644 --- a/build/version.go +++ b/build/version.go @@ -15,7 +15,8 @@ import ( // the -ldflags during compilation. var Commit string -// semanticAlphabet +// semanticAlphabet is the set of characters that are permitted for use in an +// AppPreRelease. const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-" // These constants define the application version and follow the semantic From 640aadb61a353e33669e18eab70327b25e557c16 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:03:57 -0700 Subject: [PATCH 461/562] build/version: expose AppMajor, AppMinor, AppPatch, etc. --- build/version.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/build/version.go b/build/version.go index ad6fdebcc6..855d9127c8 100644 --- a/build/version.go +++ b/build/version.go @@ -22,26 +22,31 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // These constants define the application version and follow the semantic // versioning 2.0.0 spec (http://semver.org/). const ( - appMajor uint = 0 - appMinor uint = 9 - appPatch uint = 0 + // AppMajor defines the major version of this binary. + AppMajor uint = 0 - // appPreRelease MUST only contain characters from semanticAlphabet + // AppMinor defines the minor version of this binary. + AppMinor uint = 9 + + // AppPatch defines the application patch for this binary. + AppPatch uint = 0 + + // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - appPreRelease = "beta" + AppPreRelease = "beta" ) // Version returns the application version as a properly formed string per the // semantic versioning 2.0.0 spec (http://semver.org/). func Version() string { // Start with the major, minor, and patch versions. - version := fmt.Sprintf("%d.%d.%d", appMajor, appMinor, appPatch) + version := fmt.Sprintf("%d.%d.%d", AppMajor, AppMinor, AppPatch) // Append pre-release version if there is one. The hyphen called for // by the semantic versioning spec is automatically appended and should // not be contained in the pre-release string. The pre-release version // is not appended if it contains invalid characters. - preRelease := normalizeVerString(appPreRelease) + preRelease := normalizeVerString(AppPreRelease) if preRelease != "" { version = fmt.Sprintf("%s-%s", version, preRelease) } From b68764f86c4c14056e2e8aa3763d32307e88cff3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:04:11 -0700 Subject: [PATCH 462/562] build/version: check AppPreRelease semantics in init() We'll do the validation during construction of the runtime so that we can safely use the AppPreRelease field externally without needing to normalize it. --- build/version.go | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/build/version.go b/build/version.go index 855d9127c8..4985ed6cc4 100644 --- a/build/version.go +++ b/build/version.go @@ -6,7 +6,6 @@ package build import ( - "bytes" "fmt" "strings" ) @@ -36,19 +35,30 @@ const ( AppPreRelease = "beta" ) +func init() { + // Assert that AppPreRelease is valid according to the semantic + // versioning guidelines for pre-release version and build metadata + // strings. In particular it MUST only contain characters in + // semanticAlphabet. + for _, r := range AppPreRelease { + if !strings.ContainsRune(semanticAlphabet, r) { + panic(fmt.Errorf("rune: %v is not in the semantic "+ + "alphabet", r)) + } + } +} + // Version returns the application version as a properly formed string per the // semantic versioning 2.0.0 spec (http://semver.org/). func Version() string { // Start with the major, minor, and patch versions. version := fmt.Sprintf("%d.%d.%d", AppMajor, AppMinor, AppPatch) - // Append pre-release version if there is one. The hyphen called for - // by the semantic versioning spec is automatically appended and should - // not be contained in the pre-release string. The pre-release version - // is not appended if it contains invalid characters. - preRelease := normalizeVerString(AppPreRelease) - if preRelease != "" { - version = fmt.Sprintf("%s-%s", version, preRelease) + // Append pre-release version if there is one. The hyphen called for by + // the semantic versioning spec is automatically appended and should not + // be contained in the pre-release string. + if AppPreRelease != "" { + version = fmt.Sprintf("%s-%s", version, AppPreRelease) } // Append commit hash of current build to version. @@ -56,17 +66,3 @@ func Version() string { return version } - -// normalizeVerString returns the passed string stripped of all characters which -// are not valid according to the semantic versioning guidelines for pre-release -// version and build metadata strings. In particular they MUST only contain -// characters in semanticAlphabet. -func normalizeVerString(str string) string { - var result bytes.Buffer - for _, r := range str { - if strings.ContainsRune(semanticAlphabet, r) { - result.WriteRune(r) - } - } - return result.String() -} From 75a1a1fbab31f42856a87ff8c06514876bbbf0f0 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:04:25 -0700 Subject: [PATCH 463/562] make+build: compile SHA1 commit hash into binary --- Makefile | 4 +++- build/version.go | 14 +++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 5ecd492911..d9b0551917 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,9 @@ ANDROID_BUILD_DIR := $(MOBILE_BUILD_DIR)/android ANDROID_BUILD := $(ANDROID_BUILD_DIR)/Lndmobile.aar COMMIT := $(shell git describe --abbrev=40 --dirty) -LDFLAGS := -ldflags "-X $(PKG)/build.Commit=$(COMMIT)" +COMMIT_HASH := $(shell git rev-parse HEAD) +LDFLAGS := -ldflags "-X $(PKG)/build.Commit=$(COMMIT) \ + -X $(PKG)/build.CommitHash=$(COMMIT_HASH)" BTCD_COMMIT := $(shell cat go.mod | \ grep $(BTCD_PKG) | \ diff --git a/build/version.go b/build/version.go index 4985ed6cc4..3e3a147f87 100644 --- a/build/version.go +++ b/build/version.go @@ -10,9 +10,17 @@ import ( "strings" ) -// Commit stores the current commit hash of this build, this should be set using -// the -ldflags during compilation. -var Commit string +var ( + // Commit stores the current commit of this build, which includes the + // most recent tag, the number of commits since that tag (if non-zero), + // the commit hash, and a dirty marker. This should be set using the + // -ldflags during compilation. + Commit string + + // CommitHash stores the current commit hash of this build, this should + // be set using the -ldflags during compilation. + CommitHash string +) // semanticAlphabet is the set of characters that are permitted for use in an // AppPreRelease. From 07420835d0a4e1220b686e0b7d64394e974fb89b Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:04:55 -0700 Subject: [PATCH 464/562] make+build: compile build tags into binary --- Makefile | 18 ++++++++++++------ build/version.go | 13 +++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index d9b0551917..9d480601b8 100644 --- a/Makefile +++ b/Makefile @@ -23,8 +23,6 @@ ANDROID_BUILD := $(ANDROID_BUILD_DIR)/Lndmobile.aar COMMIT := $(shell git describe --abbrev=40 --dirty) COMMIT_HASH := $(shell git rev-parse HEAD) -LDFLAGS := -ldflags "-X $(PKG)/build.Commit=$(COMMIT) \ - -X $(PKG)/build.CommitHash=$(COMMIT_HASH)" BTCD_COMMIT := $(shell cat go.mod | \ grep $(BTCD_PKG) | \ @@ -53,6 +51,14 @@ include make/testing_flags.mk DEV_TAGS := $(if ${tags},$(DEV_TAGS) ${tags},$(DEV_TAGS)) +make_ldflags = $(shell echo -ldflags \"-X $(PKG)/build.Commit=$(COMMIT) \ + -X $(PKG)/build.CommitHash=$(COMMIT_HASH) \ + -X $(PKG)/build.RawTags=$(shell echo $(1) | sed -e 's/ /,/g')\") + +LDFLAGS := $(call make_ldflags, ${tags}) +DEV_LDFLAGS := $(call make_ldflags, $(DEV_TAGS)) +ITEST_LDFLAGS := $(call make_ldflags, $(ITEST_TAGS)) + # Linting uses a lot of memory, so keep it under control by limiting the number # of workers if requested. ifneq ($(workers),) @@ -97,13 +103,13 @@ btcd: build: @$(call print, "Building debug lnd and lncli.") - $(GOBUILD) -tags="$(DEV_TAGS)" -o lnd-debug $(LDFLAGS) $(PKG)/cmd/lnd - $(GOBUILD) -tags="$(DEV_TAGS)" -o lncli-debug $(LDFLAGS) $(PKG)/cmd/lncli + $(GOBUILD) -tags="$(DEV_TAGS)" -o lnd-debug $(DEV_LDFLAGS) $(PKG)/cmd/lnd + $(GOBUILD) -tags="$(DEV_TAGS)" -o lncli-debug $(DEV_LDFLAGS) $(PKG)/cmd/lncli build-itest: @$(call print, "Building itest lnd and lncli.") - $(GOBUILD) -tags="$(ITEST_TAGS)" -o lnd-itest $(LDFLAGS) $(PKG)/cmd/lnd - $(GOBUILD) -tags="$(ITEST_TAGS)" -o lncli-itest $(LDFLAGS) $(PKG)/cmd/lncli + $(GOBUILD) -tags="$(ITEST_TAGS)" -o lnd-itest $(ITEST_LDFLAGS) $(PKG)/cmd/lnd + $(GOBUILD) -tags="$(ITEST_TAGS)" -o lncli-itest $(ITEST_LDFLAGS) $(PKG)/cmd/lncli install: @$(call print, "Installing lnd and lncli.") diff --git a/build/version.go b/build/version.go index 3e3a147f87..d863adab32 100644 --- a/build/version.go +++ b/build/version.go @@ -20,6 +20,10 @@ var ( // CommitHash stores the current commit hash of this build, this should // be set using the -ldflags during compilation. CommitHash string + + // RawTags contains the raw set of build tags, separated by commas. This + // should be set using -ldflags during compilation. + RawTags string ) // semanticAlphabet is the set of characters that are permitted for use in an @@ -74,3 +78,12 @@ func Version() string { return version } + +// Tags returns the list of build tags that were compiled into the executable. +func Tags() []string { + if len(RawTags) == 0 { + return nil + } + + return strings.Split(RawTags, ",") +} From d66f15d01f876bc388c7319bbc89fc295c6a6c18 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:05:24 -0700 Subject: [PATCH 465/562] make+build: compile go version into binary --- Makefile | 2 ++ build/version.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 9d480601b8..4f3ddbba79 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,7 @@ GOBUILD := GO111MODULE=on go build -v GOINSTALL := GO111MODULE=on go install -v GOTEST := GO111MODULE=on go test +GOVERSION := $(shell go version | awk '{print $$3}') GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*") GOLIST := go list -deps $(PKG)/... | grep '$(PKG)'| grep -v '/vendor/' GOLISTCOVER := $(shell go list -deps -f '{{.ImportPath}}' ./... | grep '$(PKG)' | sed -e 's/^$(ESCPKG)/./') @@ -53,6 +54,7 @@ DEV_TAGS := $(if ${tags},$(DEV_TAGS) ${tags},$(DEV_TAGS)) make_ldflags = $(shell echo -ldflags \"-X $(PKG)/build.Commit=$(COMMIT) \ -X $(PKG)/build.CommitHash=$(COMMIT_HASH) \ + -X $(PKG)/build.GoVersion=$(GOVERSION) \ -X $(PKG)/build.RawTags=$(shell echo $(1) | sed -e 's/ /,/g')\") LDFLAGS := $(call make_ldflags, ${tags}) diff --git a/build/version.go b/build/version.go index d863adab32..2895f60cec 100644 --- a/build/version.go +++ b/build/version.go @@ -24,6 +24,10 @@ var ( // RawTags contains the raw set of build tags, separated by commas. This // should be set using -ldflags during compilation. RawTags string + + // GoVersion stores the go version that the executable was compiled + // with. This hsould be set using -ldflags during compilation. + GoVersion string ) // semanticAlphabet is the set of characters that are permitted for use in an From a25269c4d304eddccbade278d56aae082d4c0272 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:05:46 -0700 Subject: [PATCH 466/562] lnrpc/verrpc: add Versioner RPC server --- lnrpc/verrpc/driver.go | 25 ++++ lnrpc/verrpc/log.go | 32 +++++ lnrpc/verrpc/server.go | 75 +++++++++++ lnrpc/verrpc/verrpc.pb.go | 268 ++++++++++++++++++++++++++++++++++++++ lnrpc/verrpc/verrpc.proto | 41 ++++++ log.go | 2 + 6 files changed, 443 insertions(+) create mode 100644 lnrpc/verrpc/driver.go create mode 100644 lnrpc/verrpc/log.go create mode 100644 lnrpc/verrpc/server.go create mode 100644 lnrpc/verrpc/verrpc.pb.go create mode 100644 lnrpc/verrpc/verrpc.proto diff --git a/lnrpc/verrpc/driver.go b/lnrpc/verrpc/driver.go new file mode 100644 index 0000000000..db250f7d0d --- /dev/null +++ b/lnrpc/verrpc/driver.go @@ -0,0 +1,25 @@ +package verrpc + +import ( + "fmt" + + "github.com/lightningnetwork/lnd/lnrpc" +) + +func init() { + subServer := &lnrpc.SubServerDriver{ + SubServerName: subServerName, + New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, + lnrpc.MacaroonPerms, error) { + + return &Server{}, macPermissions, nil + }, + } + + // We'll register ourselves as a sub-RPC server within the global lnrpc + // package namespace. + if err := lnrpc.RegisterSubServer(subServer); err != nil { + panic(fmt.Sprintf("failed to register sub server driver '%s': %v", + subServerName, err)) + } +} diff --git a/lnrpc/verrpc/log.go b/lnrpc/verrpc/log.go new file mode 100644 index 0000000000..fb57daa212 --- /dev/null +++ b/lnrpc/verrpc/log.go @@ -0,0 +1,32 @@ +package verrpc + +import ( + "github.com/btcsuite/btclog" + "github.com/lightningnetwork/lnd/build" +) + +// log is a logger that is initialized with no output filters. This +// means the package will not perform any logging by default until the caller +// requests it. +var log btclog.Logger + +// Subsystem defines the logging code for this subsystem. +const Subsystem = "VRPC" + +// The default amount of logging is none. +func init() { + UseLogger(build.NewSubLogger(Subsystem, nil)) +} + +// DisableLog disables all library log output. Logging output is disabled +// by default until UseLogger is called. +func DisableLog() { + UseLogger(btclog.Disabled) +} + +// UseLogger uses a specified Logger to output package logging info. +// This should be used in preference to SetLogWriter if the caller is also +// using btclog. +func UseLogger(logger btclog.Logger) { + log = logger +} diff --git a/lnrpc/verrpc/server.go b/lnrpc/verrpc/server.go new file mode 100644 index 0000000000..d11c61d1f7 --- /dev/null +++ b/lnrpc/verrpc/server.go @@ -0,0 +1,75 @@ +package verrpc + +import ( + "context" + + "github.com/lightningnetwork/lnd/build" + "google.golang.org/grpc" + "gopkg.in/macaroon-bakery.v2/bakery" +) + +const subServerName = "VersionRPC" + +var macPermissions = map[string][]bakery.Op{ + "/verrpc.Versioner/GetVersion": {{ + Entity: "info", + Action: "read", + }}, +} + +// Server is an rpc server that supports querying for information about the +// running binary. +type Server struct{} + +// Start launches any helper goroutines required for the rpcServer to function. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) Start() error { + return nil +} + +// Stop signals any active goroutines for a graceful closure. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) Stop() error { + return nil +} + +// Name returns a unique string representation of the sub-server. This can be +// used to identify the sub-server and also de-duplicate them. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) Name() string { + return subServerName +} + +// RegisterWithRootServer will be called by the root gRPC server to direct a +// sub RPC server to register itself with the main gRPC root server. Until this +// is called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { + RegisterVersionerServer(grpcServer, s) + + log.Debugf("Versioner RPC server successfully registered with root " + + "gRPC server") + + return nil +} + +// GetVersion returns information about the compiled binary. +func (s *Server) GetVersion(_ context.Context, + _ *VersionRequest) (*Version, error) { + + return &Version{ + Commit: build.Commit, + CommitHash: build.CommitHash, + Version: build.Version(), + AppMajor: uint32(build.AppMajor), + AppMinor: uint32(build.AppMinor), + AppPatch: uint32(build.AppPatch), + AppPreRelease: build.AppPreRelease, + BuildTags: build.Tags(), + GoVersion: build.GoVersion, + }, nil +} diff --git a/lnrpc/verrpc/verrpc.pb.go b/lnrpc/verrpc/verrpc.pb.go new file mode 100644 index 0000000000..a3bd4994be --- /dev/null +++ b/lnrpc/verrpc/verrpc.pb.go @@ -0,0 +1,268 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: verrpc/verrpc.proto + +package verrpc + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type VersionRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VersionRequest) Reset() { *m = VersionRequest{} } +func (m *VersionRequest) String() string { return proto.CompactTextString(m) } +func (*VersionRequest) ProtoMessage() {} +func (*VersionRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_494312204cefa0e6, []int{0} +} + +func (m *VersionRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VersionRequest.Unmarshal(m, b) +} +func (m *VersionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VersionRequest.Marshal(b, m, deterministic) +} +func (m *VersionRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_VersionRequest.Merge(m, src) +} +func (m *VersionRequest) XXX_Size() int { + return xxx_messageInfo_VersionRequest.Size(m) +} +func (m *VersionRequest) XXX_DiscardUnknown() { + xxx_messageInfo_VersionRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_VersionRequest proto.InternalMessageInfo + +type Version struct { + /// A verbose description of the daemon's commit. + Commit string `protobuf:"bytes,1,opt,name=commit,proto3" json:"commit,omitempty"` + /// The SHA1 commit hash that the daemon is compiled with. + CommitHash string `protobuf:"bytes,2,opt,name=commit_hash,json=commitHash,proto3" json:"commit_hash,omitempty"` + /// The semantic version. + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + /// The major application version. + AppMajor uint32 `protobuf:"varint,4,opt,name=app_major,json=appMajor,proto3" json:"app_major,omitempty"` + /// The minor application version. + AppMinor uint32 `protobuf:"varint,5,opt,name=app_minor,json=appMinor,proto3" json:"app_minor,omitempty"` + /// The application patch number. + AppPatch uint32 `protobuf:"varint,6,opt,name=app_patch,json=appPatch,proto3" json:"app_patch,omitempty"` + /// The application pre-release modifier, possibly empty. + AppPreRelease string `protobuf:"bytes,7,opt,name=app_pre_release,json=appPreRelease,proto3" json:"app_pre_release,omitempty"` + /// The list of build tags that were supplied during comilation. + BuildTags []string `protobuf:"bytes,8,rep,name=build_tags,json=buildTags,proto3" json:"build_tags,omitempty"` + /// The version of go that compiled the executable. + GoVersion string `protobuf:"bytes,9,opt,name=go_version,json=goVersion,proto3" json:"go_version,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Version) Reset() { *m = Version{} } +func (m *Version) String() string { return proto.CompactTextString(m) } +func (*Version) ProtoMessage() {} +func (*Version) Descriptor() ([]byte, []int) { + return fileDescriptor_494312204cefa0e6, []int{1} +} + +func (m *Version) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Version.Unmarshal(m, b) +} +func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Version.Marshal(b, m, deterministic) +} +func (m *Version) XXX_Merge(src proto.Message) { + xxx_messageInfo_Version.Merge(m, src) +} +func (m *Version) XXX_Size() int { + return xxx_messageInfo_Version.Size(m) +} +func (m *Version) XXX_DiscardUnknown() { + xxx_messageInfo_Version.DiscardUnknown(m) +} + +var xxx_messageInfo_Version proto.InternalMessageInfo + +func (m *Version) GetCommit() string { + if m != nil { + return m.Commit + } + return "" +} + +func (m *Version) GetCommitHash() string { + if m != nil { + return m.CommitHash + } + return "" +} + +func (m *Version) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +func (m *Version) GetAppMajor() uint32 { + if m != nil { + return m.AppMajor + } + return 0 +} + +func (m *Version) GetAppMinor() uint32 { + if m != nil { + return m.AppMinor + } + return 0 +} + +func (m *Version) GetAppPatch() uint32 { + if m != nil { + return m.AppPatch + } + return 0 +} + +func (m *Version) GetAppPreRelease() string { + if m != nil { + return m.AppPreRelease + } + return "" +} + +func (m *Version) GetBuildTags() []string { + if m != nil { + return m.BuildTags + } + return nil +} + +func (m *Version) GetGoVersion() string { + if m != nil { + return m.GoVersion + } + return "" +} + +func init() { + proto.RegisterType((*VersionRequest)(nil), "verrpc.VersionRequest") + proto.RegisterType((*Version)(nil), "verrpc.Version") +} + +func init() { proto.RegisterFile("verrpc/verrpc.proto", fileDescriptor_494312204cefa0e6) } + +var fileDescriptor_494312204cefa0e6 = []byte{ + // 300 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x91, 0x51, 0x4b, 0xf3, 0x30, + 0x14, 0x86, 0xd9, 0xf6, 0x7d, 0xdd, 0x72, 0x64, 0x4e, 0x22, 0x48, 0x50, 0xc4, 0xb1, 0x0b, 0xd9, + 0x85, 0xb4, 0xa0, 0xf8, 0x07, 0x76, 0xa3, 0x37, 0x82, 0x14, 0xf1, 0xc2, 0x9b, 0x92, 0x75, 0x87, + 0x34, 0xda, 0x26, 0x31, 0xc9, 0xe6, 0x6f, 0xf1, 0xdf, 0x4a, 0x93, 0xae, 0x43, 0xaf, 0x7a, 0x9e, + 0xf7, 0x29, 0xa7, 0xe5, 0x3d, 0x70, 0xba, 0x43, 0x6b, 0x4d, 0x99, 0xc5, 0x47, 0x6a, 0xac, 0xf6, + 0x9a, 0x26, 0x91, 0x16, 0x27, 0x70, 0xfc, 0x8a, 0xd6, 0x49, 0xad, 0x72, 0xfc, 0xdc, 0xa2, 0xf3, + 0x8b, 0xef, 0x21, 0x8c, 0xbb, 0x88, 0x9e, 0x41, 0x52, 0xea, 0xa6, 0x91, 0x9e, 0x0d, 0xe6, 0x83, + 0x25, 0xc9, 0x3b, 0xa2, 0x57, 0x70, 0x14, 0xa7, 0xa2, 0xe2, 0xae, 0x62, 0xc3, 0x20, 0x21, 0x46, + 0x8f, 0xdc, 0x55, 0x94, 0xc1, 0x78, 0x17, 0x77, 0xb0, 0x51, 0x90, 0x7b, 0xa4, 0x17, 0x40, 0xb8, + 0x31, 0x45, 0xc3, 0xdf, 0xb5, 0x65, 0xff, 0xe6, 0x83, 0xe5, 0x34, 0x9f, 0x70, 0x63, 0x9e, 0x5a, + 0xee, 0xa5, 0x54, 0xda, 0xb2, 0xff, 0x07, 0xd9, 0xf2, 0x5e, 0x1a, 0xee, 0xcb, 0x8a, 0x25, 0xbd, + 0x7c, 0x6e, 0x99, 0x5e, 0xc3, 0x2c, 0x48, 0x8b, 0x85, 0xc5, 0x1a, 0xb9, 0x43, 0x36, 0x0e, 0x1f, + 0x9e, 0xb6, 0xaf, 0x58, 0xcc, 0x63, 0x48, 0x2f, 0x01, 0xd6, 0x5b, 0x59, 0x6f, 0x0a, 0xcf, 0x85, + 0x63, 0x93, 0xf9, 0x68, 0x49, 0x72, 0x12, 0x92, 0x17, 0x2e, 0x5c, 0xab, 0x85, 0x2e, 0xf6, 0xbf, + 0x4e, 0xc2, 0x06, 0x22, 0x74, 0xd7, 0xc7, 0xed, 0x0a, 0x48, 0x37, 0xa2, 0xa5, 0xf7, 0x00, 0x0f, + 0xe8, 0xfb, 0xaa, 0xd2, 0xae, 0xdf, 0xdf, 0x75, 0x9e, 0xcf, 0xfe, 0xe4, 0xab, 0xf4, 0xed, 0x46, + 0x48, 0x5f, 0x6d, 0xd7, 0x69, 0xa9, 0x9b, 0xac, 0x96, 0xa2, 0xf2, 0x4a, 0x2a, 0xa1, 0xd0, 0x7f, + 0x69, 0xfb, 0x91, 0xd5, 0x6a, 0x93, 0xd5, 0xea, 0x70, 0xaf, 0x75, 0x12, 0x0e, 0x76, 0xf7, 0x13, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0xb5, 0x81, 0xc7, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// VersionerClient is the client API for Versioner service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type VersionerClient interface { + GetVersion(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*Version, error) +} + +type versionerClient struct { + cc *grpc.ClientConn +} + +func NewVersionerClient(cc *grpc.ClientConn) VersionerClient { + return &versionerClient{cc} +} + +func (c *versionerClient) GetVersion(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*Version, error) { + out := new(Version) + err := c.cc.Invoke(ctx, "/verrpc.Versioner/GetVersion", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// VersionerServer is the server API for Versioner service. +type VersionerServer interface { + GetVersion(context.Context, *VersionRequest) (*Version, error) +} + +func RegisterVersionerServer(s *grpc.Server, srv VersionerServer) { + s.RegisterService(&_Versioner_serviceDesc, srv) +} + +func _Versioner_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VersionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VersionerServer).GetVersion(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/verrpc.Versioner/GetVersion", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VersionerServer).GetVersion(ctx, req.(*VersionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Versioner_serviceDesc = grpc.ServiceDesc{ + ServiceName: "verrpc.Versioner", + HandlerType: (*VersionerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetVersion", + Handler: _Versioner_GetVersion_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "verrpc/verrpc.proto", +} diff --git a/lnrpc/verrpc/verrpc.proto b/lnrpc/verrpc/verrpc.proto new file mode 100644 index 0000000000..9e139a710d --- /dev/null +++ b/lnrpc/verrpc/verrpc.proto @@ -0,0 +1,41 @@ +syntax = "proto3"; + +package verrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/verrpc"; + +service Versioner { + rpc GetVersion (VersionRequest) returns (Version); +}; + +message VersionRequest { +}; + +message Version { + /// A verbose description of the daemon's commit. + string commit = 1; + + /// The SHA1 commit hash that the daemon is compiled with. + string commit_hash = 2; + + /// The semantic version. + string version = 3; + + /// The major application version. + uint32 app_major = 4; + + /// The minor application version. + uint32 app_minor = 5; + + /// The application patch number. + uint32 app_patch = 6; + + /// The application pre-release modifier, possibly empty. + string app_pre_release = 7; + + /// The list of build tags that were supplied during comilation. + repeated string build_tags = 8; + + /// The version of go that compiled the executable. + string go_version = 9; +}; diff --git a/log.go b/log.go index 92d99dfde1..51754cca54 100644 --- a/log.go +++ b/log.go @@ -23,6 +23,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lnrpc/signrpc" + "github.com/lightningnetwork/lnd/lnrpc/verrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lnrpc/wtclientrpc" "github.com/lightningnetwork/lnd/lnwallet" @@ -103,6 +104,7 @@ func init() { addSubLogger(routerrpc.Subsystem, routerrpc.UseLogger) addSubLogger(wtclientrpc.Subsystem, wtclientrpc.UseLogger) addSubLogger(chanfitness.Subsystem, chanfitness.UseLogger) + addSubLogger(verrpc.Subsystem, verrpc.UseLogger) } // addSubLogger is a helper method to conveniently create and register the From 5c04038c180b33250a11e350d9b728a00e87de67 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:06:12 -0700 Subject: [PATCH 467/562] bulid: only return semantic version from Version() The version field in getinfo is kept the same for backwards compatibility. --- build/version.go | 3 --- rpcserver.go | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build/version.go b/build/version.go index 2895f60cec..6049735ce5 100644 --- a/build/version.go +++ b/build/version.go @@ -77,9 +77,6 @@ func Version() string { version = fmt.Sprintf("%s-%s", version, AppPreRelease) } - // Append commit hash of current build to version. - version = fmt.Sprintf("%s commit=%s", version, Commit) - return version } diff --git a/rpcserver.go b/rpcserver.go index 043373bfe7..337cc2a1a0 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2407,7 +2407,7 @@ func (r *rpcServer) GetInfo(ctx context.Context, Alias: nodeAnn.Alias.String(), Color: routing.EncodeHexColor(nodeAnn.RGBColor), BestHeaderTimestamp: int64(bestHeaderTimestamp), - Version: build.Version(), + Version: build.Version() + " commit=" + build.Commit, SyncedToGraph: isGraphSynced, Features: features, }, nil From 91cd7e633ac29ac6b4321a2ed10f5c72b1227ff7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:06:37 -0700 Subject: [PATCH 468/562] lnrpc+rpcserver: expose git commit hash in getinfo --- lnrpc/rpc.pb.go | 1517 ++++++++++++++++++++-------------------- lnrpc/rpc.proto | 3 + lnrpc/rpc.swagger.json | 4 + rpcserver.go | 1 + 4 files changed, 772 insertions(+), 753 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index a17999b60c..28195cd61d 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -4161,6 +4161,8 @@ var xxx_messageInfo_GetInfoRequest proto.InternalMessageInfo type GetInfoResponse struct { /// The version of the LND software that the node is running. Version string `protobuf:"bytes,14,opt,name=version,proto3" json:"version,omitempty"` + /// The SHA1 commit hash that the daemon is compiled with. + CommitHash string `protobuf:"bytes,20,opt,name=commit_hash,json=commitHash,proto3" json:"commit_hash,omitempty"` /// The identity pubkey of the current node. IdentityPubkey string `protobuf:"bytes,1,opt,name=identity_pubkey,json=identityPubkey,proto3" json:"identity_pubkey,omitempty"` /// If applicable, the alias of the current node, e.g. "bob" @@ -4234,6 +4236,13 @@ func (m *GetInfoResponse) GetVersion() string { return "" } +func (m *GetInfoResponse) GetCommitHash() string { + if m != nil { + return m.CommitHash + } + return "" +} + func (m *GetInfoResponse) GetIdentityPubkey() string { if m != nil { return m.IdentityPubkey @@ -11998,759 +12007,761 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 12030 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x59, 0x6c, 0x24, 0x49, - 0x76, 0x58, 0xd7, 0x45, 0x56, 0xbd, 0x3a, 0x58, 0x0c, 0x5e, 0xd5, 0xec, 0xe9, 0xe9, 0x9e, 0x9c, - 0xd9, 0xe9, 0x9e, 0x9e, 0x59, 0x76, 0x4f, 0xef, 0xf6, 0xcc, 0xee, 0x8c, 0xb5, 0xda, 0x22, 0x59, - 0x6c, 0xd6, 0x36, 0x59, 0xe4, 0x64, 0x15, 0x67, 0x34, 0xab, 0x23, 0x37, 0x59, 0x15, 0x24, 0x53, - 0x5d, 0x95, 0x59, 0x93, 0x99, 0xc5, 0x63, 0x17, 0xe3, 0x0f, 0xc3, 0x36, 0x04, 0xc1, 0x36, 0x20, - 0xd8, 0x32, 0x60, 0x59, 0x82, 0x0f, 0xc1, 0x36, 0x0c, 0x03, 0x82, 0x00, 0xc9, 0x1f, 0x06, 0xfc, - 0xaf, 0x1f, 0x1f, 0x30, 0x24, 0x7f, 0xd8, 0x10, 0x04, 0x18, 0xb6, 0xd7, 0x7f, 0x86, 0x00, 0x7f, - 0x1b, 0x30, 0xe2, 0xbd, 0x88, 0xcc, 0xc8, 0xaa, 0x64, 0x77, 0xcf, 0xee, 0x7a, 0x7f, 0xc8, 0xca, - 0x17, 0x2f, 0xee, 0x17, 0x2f, 0xde, 0x15, 0x11, 0x50, 0xf2, 0xc7, 0xfd, 0x8d, 0xb1, 0xef, 0x85, - 0x1e, 0x2b, 0x0c, 0x5d, 0x7f, 0xdc, 0x5f, 0x7f, 0xed, 0xd4, 0xf3, 0x4e, 0x87, 0xfc, 0xa1, 0x3d, - 0x76, 0x1e, 0xda, 0xae, 0xeb, 0x85, 0x76, 0xe8, 0x78, 0x6e, 0x40, 0x48, 0xc6, 0x0f, 0xa0, 0xf6, - 0x94, 0xbb, 0x5d, 0xce, 0x07, 0x26, 0xff, 0x62, 0xc2, 0x83, 0x90, 0xbd, 0x0b, 0x8b, 0x36, 0xff, - 0x21, 0xe7, 0x03, 0x6b, 0x6c, 0x07, 0xc1, 0xf8, 0xcc, 0xb7, 0x03, 0xde, 0xc8, 0xdc, 0xcd, 0xdc, - 0xaf, 0x98, 0x75, 0x4a, 0x38, 0x8c, 0xe0, 0xec, 0x0d, 0xa8, 0x04, 0x02, 0x95, 0xbb, 0xa1, 0xef, - 0x8d, 0xaf, 0x1a, 0x59, 0xc4, 0x2b, 0x0b, 0x58, 0x8b, 0x40, 0xc6, 0x10, 0x16, 0xa2, 0x1a, 0x82, - 0xb1, 0xe7, 0x06, 0x9c, 0x3d, 0x82, 0xe5, 0xbe, 0x33, 0x3e, 0xe3, 0xbe, 0x85, 0x99, 0x47, 0x2e, - 0x1f, 0x79, 0xae, 0xd3, 0x6f, 0x64, 0xee, 0xe6, 0xee, 0x97, 0x4c, 0x46, 0x69, 0x22, 0xc7, 0xbe, - 0x4c, 0x61, 0xf7, 0x60, 0x81, 0xbb, 0x04, 0xe7, 0x03, 0xcc, 0x25, 0xab, 0xaa, 0xc5, 0x60, 0x91, - 0xc1, 0xf8, 0x8d, 0x2c, 0x2c, 0xb6, 0x5d, 0x27, 0xfc, 0xcc, 0x1e, 0x0e, 0x79, 0xa8, 0xfa, 0x74, - 0x0f, 0x16, 0x2e, 0x10, 0x80, 0x7d, 0xba, 0xf0, 0xfc, 0x81, 0xec, 0x51, 0x8d, 0xc0, 0x87, 0x12, - 0x7a, 0x6d, 0xcb, 0xb2, 0xd7, 0xb6, 0x2c, 0x75, 0xb8, 0x72, 0xd7, 0x0c, 0xd7, 0x3d, 0x58, 0xf0, - 0x79, 0xdf, 0x3b, 0xe7, 0xfe, 0x95, 0x75, 0xe1, 0xb8, 0x03, 0xef, 0xa2, 0x91, 0xbf, 0x9b, 0xb9, - 0x5f, 0x30, 0x6b, 0x0a, 0xfc, 0x19, 0x42, 0xd9, 0x26, 0x2c, 0xf4, 0xcf, 0x6c, 0xd7, 0xe5, 0x43, - 0xeb, 0xd8, 0xee, 0x3f, 0x9f, 0x8c, 0x83, 0x46, 0xe1, 0x6e, 0xe6, 0x7e, 0xf9, 0xf1, 0xcd, 0x0d, - 0x9c, 0xd5, 0x8d, 0xad, 0x33, 0xdb, 0xdd, 0xc4, 0x94, 0xae, 0x6b, 0x8f, 0x83, 0x33, 0x2f, 0x34, - 0x6b, 0x32, 0x07, 0x81, 0x03, 0x63, 0x19, 0x98, 0x3e, 0x12, 0x34, 0xf6, 0xc6, 0xbf, 0xca, 0xc0, - 0xd2, 0x91, 0x3b, 0xf4, 0xfa, 0xcf, 0x7f, 0xc2, 0x21, 0x4a, 0xe9, 0x43, 0xf6, 0x55, 0xfb, 0x90, - 0xfb, 0xaa, 0x7d, 0x58, 0x85, 0xe5, 0x64, 0x63, 0x65, 0x2f, 0x38, 0xac, 0x88, 0xdc, 0xa7, 0x5c, - 0x35, 0x4b, 0x75, 0xe3, 0x1d, 0xa8, 0xf7, 0x27, 0xbe, 0xcf, 0xdd, 0x99, 0x7e, 0x2c, 0x48, 0x78, - 0xd4, 0x91, 0x37, 0xa0, 0xe2, 0xf2, 0x8b, 0x18, 0x4d, 0xd2, 0xae, 0xcb, 0x2f, 0x14, 0x8a, 0xd1, - 0x80, 0xd5, 0xe9, 0x6a, 0x64, 0x03, 0x7e, 0x9c, 0x81, 0xfc, 0x51, 0x78, 0xe9, 0xb1, 0x27, 0x50, - 0xb1, 0x07, 0x03, 0x9f, 0x07, 0x81, 0x15, 0x5e, 0x8d, 0x69, 0xa5, 0xd4, 0x1e, 0x33, 0xd9, 0xc5, - 0x26, 0x25, 0xf5, 0xae, 0xc6, 0xdc, 0x2c, 0xdb, 0xf1, 0x07, 0x6b, 0xc0, 0xbc, 0xfc, 0xc4, 0x7a, - 0x4b, 0xa6, 0xfa, 0x64, 0xb7, 0x01, 0xec, 0x91, 0x37, 0x71, 0x43, 0x2b, 0xb0, 0x43, 0x1c, 0xb1, - 0x9c, 0x59, 0x22, 0x48, 0xd7, 0x0e, 0xd9, 0x2d, 0x28, 0x8d, 0x9f, 0x5b, 0x41, 0xdf, 0x77, 0xc6, - 0x21, 0x12, 0x4f, 0xc9, 0x2c, 0x8e, 0x9f, 0x77, 0xf1, 0x9b, 0xbd, 0x0b, 0x45, 0x6f, 0x12, 0x8e, - 0x3d, 0xc7, 0x0d, 0x25, 0xbd, 0x2c, 0xc8, 0x86, 0x1c, 0x4c, 0xc2, 0x43, 0x01, 0x36, 0x23, 0x04, - 0xf6, 0x16, 0x54, 0xfb, 0x9e, 0x7b, 0xe2, 0xf8, 0x23, 0xe2, 0x08, 0x8d, 0x39, 0xac, 0x2b, 0x09, - 0x34, 0xfe, 0x30, 0x0b, 0xe5, 0x9e, 0x6f, 0xbb, 0x81, 0xdd, 0x17, 0x00, 0xb6, 0x06, 0xf3, 0xe1, - 0xa5, 0x75, 0x66, 0x07, 0x67, 0xd8, 0xd5, 0x92, 0x39, 0x17, 0x5e, 0xee, 0xda, 0xc1, 0x19, 0x5b, - 0x85, 0x39, 0x6a, 0x25, 0x76, 0x28, 0x67, 0xca, 0x2f, 0xb1, 0x40, 0xdc, 0xc9, 0xc8, 0x4a, 0x56, - 0x95, 0x43, 0x8a, 0xa9, 0xbb, 0x93, 0xd1, 0x96, 0x0e, 0x17, 0x9d, 0x3f, 0x16, 0xd3, 0x4d, 0x15, - 0x50, 0xf7, 0x4a, 0x08, 0xc1, 0x3a, 0xde, 0x80, 0x8a, 0x4c, 0xe6, 0xce, 0xe9, 0x19, 0xf5, 0xb1, - 0x60, 0x96, 0x09, 0x01, 0x41, 0xa2, 0x84, 0xd0, 0x19, 0x71, 0x2b, 0x08, 0xed, 0xd1, 0x58, 0x76, - 0xa9, 0x24, 0x20, 0x5d, 0x01, 0xc0, 0x64, 0x2f, 0xb4, 0x87, 0xd6, 0x09, 0xe7, 0x41, 0x63, 0x5e, - 0x26, 0x0b, 0xc8, 0x0e, 0xe7, 0x01, 0xfb, 0x1a, 0xd4, 0x06, 0x3c, 0x08, 0x2d, 0x39, 0x19, 0x3c, - 0x68, 0x14, 0x71, 0xe5, 0x57, 0x05, 0xb4, 0xa9, 0x80, 0xec, 0x35, 0x00, 0xdf, 0xbe, 0xb0, 0xc4, - 0x40, 0xf0, 0xcb, 0x46, 0x89, 0x66, 0xc1, 0xb7, 0x2f, 0x7a, 0x97, 0xbb, 0xfc, 0x52, 0x50, 0xcd, - 0x53, 0x1e, 0x6a, 0x83, 0x16, 0x48, 0xea, 0x34, 0xf6, 0x80, 0x69, 0xe0, 0x6d, 0x1e, 0xda, 0xce, - 0x30, 0x60, 0x1f, 0x40, 0x25, 0xd4, 0x90, 0x91, 0x0d, 0x96, 0x23, 0x12, 0xd2, 0x32, 0x98, 0x09, - 0x3c, 0xe3, 0x0c, 0x8a, 0x3b, 0x9c, 0xef, 0x39, 0x23, 0x27, 0x64, 0xab, 0x50, 0x38, 0x71, 0x2e, - 0x39, 0x11, 0x7b, 0x6e, 0xf7, 0x86, 0x49, 0x9f, 0xec, 0x0e, 0x00, 0xfe, 0xb0, 0x46, 0x11, 0x35, - 0xed, 0xde, 0x30, 0x4b, 0x08, 0xdb, 0x0f, 0xec, 0x90, 0xad, 0xc3, 0xfc, 0x98, 0xfb, 0x7d, 0xae, - 0xe6, 0x6d, 0xf7, 0x86, 0xa9, 0x00, 0x9b, 0xf3, 0x50, 0x18, 0x8a, 0xd2, 0x8d, 0x3f, 0x29, 0x40, - 0xb9, 0xcb, 0xdd, 0x68, 0x95, 0x31, 0xc8, 0x8b, 0x01, 0x91, 0x2b, 0x0b, 0x7f, 0xb3, 0x37, 0xa1, - 0x8c, 0x43, 0x17, 0x84, 0xbe, 0xe3, 0x9e, 0x12, 0x55, 0x6f, 0x66, 0x1b, 0x19, 0x13, 0x04, 0xb8, - 0x8b, 0x50, 0x56, 0x87, 0x9c, 0x3d, 0x52, 0x54, 0x2d, 0x7e, 0xb2, 0x9b, 0x50, 0xb4, 0x47, 0x21, - 0x35, 0xaf, 0x82, 0xe0, 0x79, 0x7b, 0x14, 0x62, 0xd3, 0xde, 0x80, 0xca, 0xd8, 0xbe, 0x1a, 0x89, - 0xb5, 0x1c, 0x91, 0x43, 0xc5, 0x2c, 0x4b, 0x18, 0x12, 0xc4, 0x63, 0x58, 0xd2, 0x51, 0x54, 0xe5, - 0x85, 0xa8, 0xf2, 0x45, 0x0d, 0x5b, 0xb6, 0xe1, 0x1e, 0x2c, 0xa8, 0x3c, 0x3e, 0xf5, 0x07, 0xc9, - 0xa4, 0x64, 0xd6, 0x24, 0x58, 0xf5, 0xf2, 0x3e, 0xd4, 0x4f, 0x1c, 0xd7, 0x1e, 0x5a, 0xfd, 0x61, - 0x78, 0x6e, 0x0d, 0xf8, 0x30, 0xb4, 0x91, 0x62, 0x0a, 0x66, 0x0d, 0xe1, 0x5b, 0xc3, 0xf0, 0x7c, - 0x5b, 0x40, 0xd9, 0x7b, 0x50, 0x3a, 0xe1, 0xdc, 0xc2, 0xc1, 0x6a, 0x14, 0x13, 0x0b, 0x4f, 0xcd, - 0x90, 0x59, 0x3c, 0x51, 0x73, 0xf5, 0x1e, 0xd4, 0xbd, 0x49, 0x78, 0xea, 0x39, 0xee, 0xa9, 0x25, - 0xf8, 0x9d, 0xe5, 0x0c, 0x90, 0x86, 0xf2, 0x9b, 0xd9, 0x47, 0x19, 0xb3, 0xa6, 0xd2, 0x04, 0xe7, - 0x69, 0x0f, 0xd8, 0xdb, 0xb0, 0x30, 0xb4, 0x83, 0xd0, 0x3a, 0xf3, 0xc6, 0xd6, 0x78, 0x72, 0xfc, - 0x9c, 0x5f, 0x35, 0xaa, 0x38, 0x10, 0x55, 0x01, 0xde, 0xf5, 0xc6, 0x87, 0x08, 0x14, 0x94, 0x8d, - 0xed, 0xa4, 0x46, 0xc0, 0xdd, 0xcc, 0xfd, 0xaa, 0x59, 0x12, 0x10, 0xaa, 0xf4, 0x73, 0x58, 0xc2, - 0xe9, 0xe9, 0x4f, 0x82, 0xd0, 0x1b, 0x59, 0x82, 0x57, 0xfb, 0x83, 0xa0, 0x51, 0x46, 0x5a, 0x7b, - 0x47, 0x36, 0x56, 0x9b, 0xe3, 0x8d, 0x6d, 0x1e, 0x84, 0x5b, 0x88, 0x6c, 0x12, 0xae, 0xd8, 0xd0, - 0xaf, 0xcc, 0xc5, 0xc1, 0x34, 0x9c, 0xbd, 0x07, 0xcc, 0x1e, 0x0e, 0xbd, 0x0b, 0x2b, 0xe0, 0xc3, - 0x13, 0x4b, 0x0e, 0x62, 0xa3, 0x76, 0x37, 0x73, 0xbf, 0x68, 0xd6, 0x31, 0xa5, 0xcb, 0x87, 0x27, - 0x87, 0x04, 0x67, 0x1f, 0x00, 0x2e, 0x26, 0xeb, 0x84, 0xdb, 0xe1, 0xc4, 0xe7, 0x41, 0x63, 0xe1, - 0x6e, 0xee, 0x7e, 0xed, 0xf1, 0x62, 0x34, 0x5e, 0x08, 0xde, 0x74, 0x42, 0xb3, 0x22, 0xf0, 0xe4, - 0x77, 0xb0, 0xbe, 0x0d, 0xab, 0xe9, 0x4d, 0x12, 0x44, 0x25, 0x46, 0x45, 0x10, 0x63, 0xde, 0x14, - 0x3f, 0xd9, 0x32, 0x14, 0xce, 0xed, 0xe1, 0x84, 0x4b, 0x9e, 0x4e, 0x1f, 0x1f, 0x65, 0xbf, 0x95, - 0x31, 0xfe, 0x38, 0x03, 0x15, 0xea, 0xa5, 0x94, 0x45, 0xde, 0x84, 0xaa, 0xa2, 0x06, 0xee, 0xfb, - 0x9e, 0x2f, 0xb9, 0x9a, 0xa2, 0xbc, 0x96, 0x80, 0x89, 0x5d, 0x45, 0x21, 0x8d, 0x7d, 0xee, 0x8c, - 0xec, 0x53, 0x55, 0xb4, 0x22, 0xa5, 0x43, 0x09, 0x66, 0xef, 0xc7, 0xe5, 0xf9, 0xde, 0x24, 0xe4, - 0x72, 0xcf, 0xab, 0xc8, 0xee, 0x99, 0x02, 0x16, 0x95, 0x8e, 0x5f, 0xaf, 0x40, 0xe7, 0xc6, 0x6f, - 0x67, 0x80, 0x89, 0x66, 0xf7, 0x3c, 0x2a, 0x40, 0x52, 0xe8, 0x74, 0xce, 0xcc, 0x2b, 0xaf, 0x90, - 0xec, 0x8b, 0x56, 0x88, 0x01, 0x05, 0x6a, 0x7b, 0x3e, 0xa5, 0xed, 0x94, 0xf4, 0xbd, 0x7c, 0x31, - 0x57, 0xcf, 0x1b, 0xff, 0x35, 0x07, 0xcb, 0x5b, 0xb4, 0x65, 0x37, 0xfb, 0x7d, 0x3e, 0x8e, 0xd6, - 0xce, 0x1d, 0x28, 0xbb, 0xde, 0x80, 0x2b, 0x8a, 0xa5, 0x86, 0x81, 0x00, 0x69, 0xe4, 0x7a, 0x66, - 0x3b, 0x2e, 0x35, 0x9c, 0x06, 0xb3, 0x84, 0x10, 0x6c, 0xf6, 0xdb, 0xb0, 0x30, 0xe6, 0xee, 0x40, - 0x5f, 0x22, 0x24, 0x54, 0x55, 0x25, 0x58, 0xae, 0x8e, 0x3b, 0x50, 0x3e, 0x99, 0x10, 0x9e, 0x60, - 0x2c, 0x79, 0xa4, 0x01, 0x90, 0xa0, 0x26, 0xf1, 0x97, 0xf1, 0x24, 0x38, 0xc3, 0xd4, 0x02, 0xa6, - 0xce, 0x8b, 0x6f, 0x91, 0x74, 0x1b, 0x60, 0x30, 0x09, 0x42, 0xb9, 0x62, 0xe6, 0x30, 0xb1, 0x24, - 0x20, 0xb4, 0x62, 0xbe, 0x0e, 0x4b, 0x23, 0xfb, 0xd2, 0x42, 0xda, 0xb1, 0x1c, 0xd7, 0x3a, 0x19, - 0xe2, 0x9e, 0x33, 0x8f, 0x78, 0xf5, 0x91, 0x7d, 0xf9, 0xa9, 0x48, 0x69, 0xbb, 0x3b, 0x08, 0x17, - 0x6c, 0x45, 0x89, 0x3b, 0x3e, 0x0f, 0xb8, 0x7f, 0xce, 0x91, 0x13, 0xe4, 0x23, 0x99, 0xc6, 0x24, - 0xa8, 0x68, 0xd1, 0x48, 0xf4, 0x3b, 0x1c, 0xf6, 0x69, 0xd9, 0x9b, 0xf3, 0x23, 0xc7, 0xdd, 0x0d, - 0x87, 0x7d, 0xb1, 0xaf, 0x08, 0x3e, 0x32, 0xe6, 0xbe, 0xf5, 0xfc, 0x02, 0xd7, 0x70, 0x1e, 0xf9, - 0xc6, 0x21, 0xf7, 0x9f, 0x5d, 0x88, 0xad, 0xbf, 0x1f, 0x20, 0x23, 0xb2, 0xaf, 0x1a, 0x65, 0x5c, - 0xe0, 0xc5, 0x7e, 0x20, 0x58, 0x90, 0x7d, 0x25, 0x16, 0xa1, 0x68, 0xad, 0x8d, 0xb3, 0xc0, 0x07, - 0x58, 0x7c, 0x80, 0x1c, 0xb5, 0x8a, 0x8d, 0x6d, 0xca, 0x04, 0x51, 0x4f, 0x20, 0xa8, 0x5e, 0x35, - 0xf6, 0x64, 0x68, 0x9f, 0x06, 0xc8, 0x52, 0xaa, 0x66, 0x45, 0x02, 0x77, 0x04, 0xcc, 0xf8, 0x8c, - 0x84, 0x2c, 0x6d, 0x6e, 0xe5, 0x9a, 0x11, 0x5b, 0x3d, 0x42, 0x70, 0x5e, 0x8b, 0xa6, 0xfc, 0x4a, - 0x9b, 0xb4, 0x6c, 0xca, 0xa4, 0x19, 0xbf, 0x97, 0x81, 0x8a, 0x2c, 0x19, 0x85, 0x12, 0xb6, 0x01, - 0x4c, 0xcd, 0x62, 0x78, 0xe9, 0x0c, 0xac, 0xe3, 0xab, 0x90, 0x07, 0x44, 0x34, 0xbb, 0x37, 0xcc, - 0xba, 0x4c, 0xeb, 0x5d, 0x3a, 0x83, 0x4d, 0x91, 0xc2, 0x1e, 0x40, 0x3d, 0x81, 0x1f, 0x84, 0x3e, - 0x51, 0xf4, 0xee, 0x0d, 0xb3, 0xa6, 0x61, 0x77, 0x43, 0x5f, 0xac, 0x11, 0x21, 0xf2, 0x4c, 0x42, - 0xcb, 0x71, 0x07, 0xfc, 0x12, 0xc9, 0xa8, 0x6a, 0x96, 0x09, 0xd6, 0x16, 0xa0, 0xcd, 0x1a, 0x54, - 0xf4, 0xe2, 0x8c, 0x53, 0x28, 0x2a, 0x79, 0x09, 0x05, 0x86, 0xa9, 0x26, 0x99, 0xa5, 0x30, 0x6a, - 0xc9, 0x4d, 0x28, 0x26, 0x5b, 0x60, 0xce, 0x87, 0xaf, 0x5c, 0xb1, 0xf1, 0x1d, 0xa8, 0xef, 0x09, - 0xe2, 0x71, 0x05, 0xb1, 0x4a, 0xf9, 0x6f, 0x15, 0xe6, 0xb4, 0x45, 0x53, 0x32, 0xe5, 0x97, 0xd8, - 0x73, 0xcf, 0xbc, 0x20, 0x94, 0xb5, 0xe0, 0x6f, 0xe3, 0x4f, 0x32, 0xc0, 0x5a, 0x41, 0xe8, 0x8c, - 0xec, 0x90, 0xef, 0xf0, 0x88, 0x2d, 0x1c, 0x40, 0x45, 0x94, 0xd6, 0xf3, 0x9a, 0x24, 0x90, 0x91, - 0x40, 0xf1, 0xae, 0x5c, 0xc6, 0xb3, 0x19, 0x36, 0x74, 0x6c, 0x62, 0xf3, 0x89, 0x02, 0xc4, 0x2a, - 0x0b, 0x6d, 0xff, 0x94, 0x87, 0x28, 0xc6, 0x49, 0x79, 0x1f, 0x08, 0x24, 0x04, 0xb8, 0xf5, 0x5f, - 0x84, 0xc5, 0x99, 0x32, 0x74, 0xbe, 0x5c, 0x4a, 0xe1, 0xcb, 0x39, 0x9d, 0x2f, 0x5b, 0xb0, 0x94, - 0x68, 0x97, 0xa4, 0xb4, 0x35, 0x98, 0x17, 0x0b, 0x42, 0x08, 0x07, 0x19, 0x92, 0x2a, 0x4f, 0x38, - 0x17, 0x62, 0xf0, 0x43, 0x58, 0x3e, 0xe1, 0xdc, 0xb7, 0x43, 0x4c, 0xc4, 0x15, 0x23, 0x66, 0x48, - 0x16, 0xbc, 0x28, 0xd3, 0xba, 0x76, 0x78, 0xc8, 0x7d, 0x31, 0x53, 0xc6, 0x7f, 0xcf, 0xc0, 0x82, - 0xe0, 0xa0, 0xfb, 0xb6, 0x7b, 0xa5, 0xc6, 0x69, 0x2f, 0x75, 0x9c, 0xee, 0x6b, 0x9b, 0xa1, 0x86, - 0xfd, 0x55, 0x07, 0x29, 0x37, 0x3d, 0x48, 0xec, 0x2e, 0x54, 0x12, 0x6d, 0x2d, 0x60, 0x5b, 0x21, - 0x88, 0x1a, 0xf9, 0xd3, 0x0f, 0xe3, 0xdb, 0x50, 0x8f, 0x9b, 0x2d, 0xc7, 0x90, 0x41, 0x5e, 0x90, - 0xa4, 0x2c, 0x00, 0x7f, 0x1b, 0xbf, 0x9b, 0x21, 0xc4, 0x2d, 0xcf, 0x89, 0xa4, 0x53, 0x81, 0x28, - 0xe4, 0x5e, 0x85, 0x28, 0x7e, 0x5f, 0x2b, 0xd5, 0xff, 0xf4, 0x9d, 0x15, 0x4b, 0x27, 0xe0, 0xee, - 0xc0, 0xb2, 0x87, 0x43, 0x64, 0xbe, 0x45, 0x73, 0x5e, 0x7c, 0x37, 0x87, 0x43, 0xe3, 0x1e, 0x2c, - 0x6a, 0xad, 0x7b, 0x41, 0x3f, 0x3a, 0xc0, 0xf6, 0x9c, 0x20, 0x3c, 0x72, 0x83, 0xb1, 0x26, 0xb8, - 0xdd, 0x82, 0x92, 0xe0, 0xb0, 0xa2, 0x65, 0xb4, 0x64, 0x0b, 0xa6, 0x60, 0xb9, 0xa2, 0x5d, 0x01, - 0x26, 0xda, 0x97, 0x32, 0x31, 0x2b, 0x13, 0xed, 0x4b, 0x4c, 0x34, 0xbe, 0x05, 0x4b, 0x89, 0xf2, - 0x64, 0xd5, 0x6f, 0x40, 0x61, 0x12, 0x5e, 0x7a, 0x4a, 0x34, 0x2f, 0x4b, 0x0a, 0x11, 0x0a, 0xa0, - 0x49, 0x29, 0xc6, 0xc7, 0xb0, 0xd8, 0xe1, 0x17, 0x72, 0x11, 0xab, 0x86, 0xbc, 0x0d, 0xf9, 0x97, - 0x28, 0x85, 0x98, 0x6e, 0x6c, 0x00, 0xd3, 0x33, 0xcb, 0x5a, 0x35, 0x1d, 0x31, 0x93, 0xd0, 0x11, - 0x8d, 0xb7, 0x81, 0x75, 0x9d, 0x53, 0x77, 0x9f, 0x07, 0x81, 0x7d, 0x1a, 0x2d, 0xfb, 0x3a, 0xe4, - 0x46, 0xc1, 0xa9, 0xe4, 0x51, 0xe2, 0xa7, 0xf1, 0x0d, 0x58, 0x4a, 0xe0, 0xc9, 0x82, 0x5f, 0x83, - 0x52, 0xe0, 0x9c, 0xba, 0x28, 0x58, 0xc9, 0xa2, 0x63, 0x80, 0xb1, 0x03, 0xcb, 0x9f, 0x72, 0xdf, - 0x39, 0xb9, 0x7a, 0x59, 0xf1, 0xc9, 0x72, 0xb2, 0xd3, 0xe5, 0xb4, 0x60, 0x65, 0xaa, 0x1c, 0x59, - 0x3d, 0x91, 0xaf, 0x9c, 0xc9, 0xa2, 0x49, 0x1f, 0x1a, 0xdf, 0xcb, 0xea, 0x7c, 0xcf, 0x38, 0x02, - 0xb6, 0xe5, 0xb9, 0x2e, 0xef, 0x87, 0x87, 0x9c, 0xfb, 0xb1, 0x95, 0x2a, 0xa6, 0xd5, 0xf2, 0xe3, - 0x35, 0x39, 0xb2, 0xd3, 0xcc, 0x54, 0x12, 0x31, 0x83, 0xfc, 0x98, 0xfb, 0x23, 0x2c, 0xb8, 0x68, - 0xe2, 0x6f, 0x63, 0x05, 0x96, 0x12, 0xc5, 0x4a, 0xbd, 0xfe, 0x11, 0xac, 0x6c, 0x3b, 0x41, 0x7f, - 0xb6, 0xc2, 0x35, 0x98, 0x1f, 0x4f, 0x8e, 0xad, 0x24, 0x5f, 0x7e, 0xc6, 0xaf, 0x84, 0xb6, 0x37, - 0x9d, 0x43, 0x96, 0xf5, 0xd7, 0x33, 0x90, 0xdf, 0xed, 0xed, 0x6d, 0xb1, 0x75, 0x28, 0x3a, 0x6e, - 0xdf, 0x1b, 0x09, 0xc1, 0x8b, 0xfa, 0x1c, 0x7d, 0x5f, 0xbb, 0xc0, 0x6e, 0x41, 0x09, 0xe5, 0x35, - 0xa1, 0xda, 0x4a, 0xd1, 0xa7, 0x28, 0x00, 0x7b, 0x5e, 0xff, 0xb9, 0xd0, 0xa9, 0xf9, 0xe5, 0xd8, - 0xf1, 0x51, 0x6b, 0x56, 0xca, 0x70, 0x9e, 0xf6, 0xfa, 0x38, 0x81, 0x34, 0x62, 0xe3, 0xdf, 0x14, - 0x61, 0x5e, 0xee, 0xb6, 0xb4, 0x73, 0x87, 0xce, 0x39, 0x8f, 0x77, 0x6e, 0xf1, 0x25, 0xe4, 0x01, - 0x9f, 0x8f, 0xbc, 0x30, 0x12, 0xd8, 0x68, 0x0e, 0x2a, 0x04, 0x94, 0x22, 0x9b, 0x26, 0x34, 0x90, - 0x89, 0x21, 0x47, 0x48, 0x7d, 0x7d, 0x2b, 0xbf, 0x05, 0xf3, 0x6a, 0xef, 0xcf, 0x47, 0x3a, 0xcd, - 0x5c, 0x9f, 0xa4, 0xb5, 0x75, 0x28, 0xf6, 0xed, 0xb1, 0xdd, 0x77, 0xc2, 0x2b, 0xc9, 0x10, 0xa2, - 0x6f, 0x51, 0xfa, 0xd0, 0xeb, 0xdb, 0x43, 0xeb, 0xd8, 0x1e, 0xda, 0x6e, 0x9f, 0x4b, 0xdd, 0xbd, - 0x82, 0xc0, 0x4d, 0x82, 0x09, 0xfd, 0x5c, 0xb6, 0x53, 0x61, 0x91, 0x0a, 0x2f, 0x5b, 0xaf, 0xd0, - 0x84, 0x70, 0xe9, 0x8d, 0x46, 0x8e, 0xd0, 0x32, 0x48, 0x0c, 0xcb, 0x99, 0x25, 0x82, 0xec, 0x70, - 0xec, 0xad, 0x4c, 0xbe, 0xa0, 0xa1, 0x2b, 0x51, 0x55, 0x04, 0xfc, 0x8c, 0x0c, 0x09, 0xb3, 0xb2, - 0x58, 0x4e, 0x93, 0xc5, 0xde, 0x85, 0xc5, 0x89, 0x1b, 0xf0, 0x30, 0x1c, 0xf2, 0x41, 0xd4, 0x96, - 0x32, 0x22, 0xd5, 0xa3, 0x04, 0xd5, 0x9c, 0x0d, 0x58, 0x22, 0xa3, 0x43, 0x60, 0x87, 0x5e, 0x70, - 0xe6, 0x04, 0x56, 0x20, 0x34, 0x24, 0x52, 0x77, 0x17, 0x31, 0xa9, 0x2b, 0x53, 0xba, 0xa4, 0x22, - 0xad, 0x4d, 0xe1, 0xfb, 0xbc, 0xcf, 0x9d, 0x73, 0x3e, 0x40, 0x39, 0x2d, 0x67, 0xae, 0x24, 0xf2, - 0x98, 0x32, 0x11, 0x85, 0xee, 0xc9, 0xc8, 0x9a, 0x8c, 0x07, 0xb6, 0x10, 0x56, 0x6a, 0x24, 0x0c, - 0xbb, 0x93, 0xd1, 0x11, 0x41, 0xd8, 0x23, 0x50, 0x92, 0x98, 0x94, 0x0f, 0x17, 0x12, 0xfc, 0x4c, - 0x10, 0xab, 0x59, 0x91, 0x18, 0x24, 0x28, 0x26, 0x64, 0xce, 0xfa, 0x94, 0xcc, 0xd9, 0x80, 0xf9, - 0xb1, 0xef, 0x9c, 0xdb, 0x21, 0x6f, 0x2c, 0x12, 0x03, 0x97, 0x9f, 0x82, 0x33, 0x38, 0xae, 0x13, - 0x3a, 0x76, 0xe8, 0xf9, 0x0d, 0x86, 0x69, 0x31, 0x80, 0x3d, 0x80, 0x45, 0xa4, 0x91, 0x20, 0xb4, - 0xc3, 0x49, 0x20, 0x25, 0xd0, 0x25, 0x24, 0x26, 0x94, 0xa1, 0xbb, 0x08, 0x47, 0x21, 0x94, 0x7d, - 0x03, 0x56, 0x89, 0x2c, 0x30, 0x87, 0x94, 0xac, 0x51, 0x20, 0x58, 0xc6, 0xa1, 0x58, 0xc2, 0x54, - 0x41, 0xdf, 0x52, 0xbe, 0x16, 0xd2, 0xc1, 0x13, 0x58, 0x93, 0x64, 0x32, 0x93, 0x6b, 0x05, 0x73, - 0x2d, 0x53, 0xf2, 0x54, 0xb6, 0x0d, 0x58, 0x14, 0x4d, 0x72, 0xfa, 0x96, 0xcc, 0x2d, 0x56, 0xc2, - 0xaa, 0x68, 0x3d, 0x6a, 0x4a, 0x0b, 0x94, 0x68, 0x62, 0xda, 0x33, 0x7e, 0xc5, 0xbe, 0x03, 0x0b, - 0x44, 0x32, 0xa8, 0x5e, 0x21, 0xa7, 0x5f, 0x47, 0x4e, 0xbf, 0xa2, 0x2c, 0x9c, 0x51, 0x2a, 0x32, - 0xfb, 0x5a, 0x3f, 0xf1, 0x2d, 0x96, 0xc3, 0xd0, 0x39, 0xe1, 0xa1, 0x33, 0xe2, 0x8d, 0x35, 0x22, - 0x30, 0xf5, 0x2d, 0x56, 0xea, 0x64, 0x8c, 0x29, 0x0d, 0xe2, 0x0b, 0xf4, 0x85, 0xb4, 0x3b, 0xf4, - 0x02, 0xae, 0x4c, 0x54, 0x8d, 0x9b, 0x72, 0x11, 0x0a, 0xa0, 0x92, 0x21, 0x85, 0x20, 0x4e, 0x4a, - 0x4f, 0x64, 0x48, 0xbc, 0x85, 0xc4, 0x50, 0x25, 0xdd, 0x47, 0x19, 0x13, 0xc5, 0x2e, 0x7e, 0x66, - 0x5f, 0x28, 0x0e, 0xf2, 0x1a, 0xce, 0x2f, 0x08, 0x90, 0xe4, 0x1d, 0x7f, 0x94, 0xa1, 0x0d, 0x51, - 0xf2, 0x8f, 0x40, 0x53, 0xef, 0x88, 0x73, 0x58, 0x9e, 0x3b, 0xbc, 0x92, 0xcc, 0x04, 0x08, 0x74, - 0xe0, 0x0e, 0x71, 0x35, 0x3b, 0xae, 0x8e, 0x42, 0xbc, 0xb7, 0xa2, 0x80, 0x88, 0x74, 0x07, 0xca, - 0xe3, 0xc9, 0xf1, 0xd0, 0xe9, 0x13, 0x4a, 0x8e, 0x4a, 0x21, 0x10, 0x22, 0x08, 0xfd, 0x96, 0x28, - 0x8a, 0x30, 0xf2, 0x88, 0x51, 0x96, 0x30, 0x44, 0x41, 0xde, 0xce, 0x7d, 0x64, 0x27, 0x15, 0x13, - 0x7f, 0x1b, 0x9b, 0xb0, 0x9c, 0x6c, 0xb4, 0xdc, 0x78, 0x1e, 0x40, 0x51, 0xf2, 0x2a, 0x65, 0xf8, - 0xa8, 0x69, 0xa6, 0x68, 0xa1, 0xa2, 0x45, 0xe9, 0xc6, 0xef, 0x17, 0x60, 0x49, 0x42, 0xb7, 0xc4, - 0xd0, 0x76, 0x27, 0xa3, 0x91, 0xed, 0xa7, 0x30, 0xc1, 0xcc, 0x8b, 0x99, 0x60, 0x76, 0x86, 0x09, - 0x26, 0x35, 0x5f, 0xe2, 0xa1, 0x49, 0xcd, 0x57, 0xcc, 0x25, 0x29, 0x23, 0xba, 0x1d, 0xb4, 0x2a, - 0xc1, 0x3d, 0xb2, 0xb7, 0xce, 0xb0, 0xec, 0x42, 0x0a, 0xcb, 0xd6, 0x19, 0xee, 0xdc, 0x14, 0xc3, - 0x7d, 0x03, 0x88, 0x68, 0xd4, 0xec, 0xcf, 0x93, 0x7e, 0x82, 0x30, 0x69, 0x4c, 0xbd, 0x07, 0x0b, - 0xd3, 0x3c, 0x8e, 0x98, 0x69, 0x2d, 0x85, 0xc3, 0x39, 0x23, 0x8e, 0xbb, 0x95, 0x86, 0x5c, 0x92, - 0x1c, 0xce, 0x19, 0xf1, 0x3d, 0x4c, 0x51, 0xf8, 0x2d, 0x00, 0xaa, 0x1b, 0x17, 0x0d, 0xe0, 0xa2, - 0x79, 0x3b, 0x39, 0x17, 0xfa, 0xa8, 0x6f, 0x88, 0x8f, 0x89, 0xcf, 0x71, 0x15, 0x95, 0x30, 0x27, - 0x2e, 0xa0, 0x0f, 0xa1, 0xe6, 0x8d, 0xb9, 0x6b, 0xc5, 0xbc, 0xa6, 0x8c, 0x45, 0xd5, 0x65, 0x51, - 0x6d, 0x05, 0x37, 0xab, 0x02, 0x2f, 0xfa, 0x64, 0xdf, 0xa6, 0x41, 0xe6, 0x5a, 0xce, 0xca, 0x35, - 0x39, 0x6b, 0x88, 0x18, 0x7d, 0x1b, 0xbf, 0x99, 0x81, 0xb2, 0xd6, 0x1c, 0xb6, 0x02, 0x8b, 0x5b, - 0x07, 0x07, 0x87, 0x2d, 0xb3, 0xd9, 0x6b, 0x7f, 0xda, 0xb2, 0xb6, 0xf6, 0x0e, 0xba, 0xad, 0xfa, - 0x0d, 0x01, 0xde, 0x3b, 0xd8, 0x6a, 0xee, 0x59, 0x3b, 0x07, 0xe6, 0x96, 0x02, 0x67, 0xd8, 0x2a, - 0x30, 0xb3, 0xb5, 0x7f, 0xd0, 0x6b, 0x25, 0xe0, 0x59, 0x56, 0x87, 0xca, 0xa6, 0xd9, 0x6a, 0x6e, - 0xed, 0x4a, 0x48, 0x8e, 0x2d, 0x43, 0x7d, 0xe7, 0xa8, 0xb3, 0xdd, 0xee, 0x3c, 0xb5, 0xb6, 0x9a, - 0x9d, 0xad, 0xd6, 0x5e, 0x6b, 0xbb, 0x9e, 0x67, 0x55, 0x28, 0x35, 0x37, 0x9b, 0x9d, 0xed, 0x83, - 0x4e, 0x6b, 0xbb, 0x5e, 0x30, 0xfe, 0x22, 0x03, 0x2b, 0x38, 0x50, 0x83, 0xe9, 0x15, 0x7a, 0x17, - 0xca, 0x7d, 0xcf, 0x1b, 0x0b, 0x35, 0x28, 0xde, 0xee, 0x75, 0x90, 0x58, 0x7d, 0xc4, 0x59, 0x4f, - 0x3c, 0xbf, 0xcf, 0xe5, 0x02, 0x05, 0x04, 0xed, 0x08, 0x88, 0x20, 0x10, 0x49, 0x61, 0x84, 0x41, - 0xeb, 0xb3, 0x4c, 0x30, 0x42, 0x59, 0x85, 0xb9, 0x63, 0x9f, 0xdb, 0xfd, 0x33, 0xb9, 0x34, 0xe5, - 0x17, 0x7b, 0x27, 0x56, 0xd0, 0xfb, 0x62, 0xc2, 0x87, 0x7c, 0x80, 0xf4, 0x59, 0x34, 0x17, 0x24, - 0x7c, 0x4b, 0x82, 0xc5, 0x56, 0x61, 0x1f, 0xdb, 0xee, 0xc0, 0x73, 0xf9, 0x40, 0xea, 0x01, 0x31, - 0xc0, 0x38, 0x84, 0xd5, 0xe9, 0xfe, 0xc9, 0xc5, 0xfc, 0x81, 0xb6, 0x98, 0x49, 0x2c, 0x5f, 0xbf, - 0x9e, 0x80, 0xb4, 0x85, 0xfd, 0xb7, 0xf3, 0x90, 0x17, 0x62, 0xda, 0xb5, 0x12, 0x9d, 0x2e, 0x77, - 0xe7, 0x66, 0x7c, 0x33, 0x68, 0x07, 0xa0, 0xfd, 0x9b, 0x8c, 0x4d, 0x25, 0x84, 0xe0, 0xbe, 0x1d, - 0x25, 0xfb, 0xbc, 0x7f, 0x2e, 0xad, 0x4d, 0x94, 0x6c, 0xf2, 0xfe, 0x39, 0x2a, 0x3c, 0x76, 0x48, - 0x79, 0x69, 0x31, 0xce, 0x07, 0x76, 0x88, 0x39, 0x65, 0x12, 0xe6, 0x9b, 0x8f, 0x92, 0x30, 0x57, - 0x03, 0xe6, 0x1d, 0xf7, 0xd8, 0x9b, 0xb8, 0x03, 0x5c, 0x7b, 0x45, 0x53, 0x7d, 0xa2, 0x2b, 0x08, - 0xd9, 0x84, 0xd8, 0x25, 0x68, 0xa9, 0x15, 0x05, 0xa0, 0x27, 0xf6, 0x89, 0xf7, 0xa1, 0x14, 0x5c, - 0xb9, 0x7d, 0x7d, 0x81, 0x2d, 0xcb, 0xf1, 0x11, 0xbd, 0xdf, 0xe8, 0x5e, 0xb9, 0x7d, 0x5c, 0x4e, - 0xc5, 0x40, 0xfe, 0x62, 0x4f, 0xa0, 0x18, 0x19, 0x65, 0x89, 0x3d, 0xde, 0xd4, 0x73, 0x28, 0x4b, - 0x2c, 0xe9, 0xbe, 0x11, 0x2a, 0x7b, 0x08, 0x73, 0x68, 0x39, 0x0d, 0x1a, 0x15, 0xcc, 0xa4, 0x84, - 0x71, 0xd1, 0x0c, 0xf4, 0xc2, 0xf0, 0x01, 0x5a, 0x51, 0x4d, 0x89, 0xb6, 0xfe, 0x0c, 0xaa, 0x89, - 0xb2, 0x74, 0x0d, 0xb7, 0x4a, 0x1a, 0xee, 0x5b, 0xba, 0x86, 0x1b, 0xb3, 0x69, 0x99, 0x4d, 0xd7, - 0x78, 0x7f, 0x11, 0x8a, 0xaa, 0x2b, 0x62, 0x11, 0x1d, 0x75, 0x9e, 0x75, 0x0e, 0x3e, 0xeb, 0x58, - 0xdd, 0xcf, 0x3b, 0x5b, 0xf5, 0x1b, 0x6c, 0x01, 0xca, 0xcd, 0x2d, 0x5c, 0x97, 0x08, 0xc8, 0x08, - 0x94, 0xc3, 0x66, 0xb7, 0x1b, 0x41, 0xb2, 0xc6, 0x0e, 0xd4, 0xa7, 0x5b, 0x2a, 0x68, 0x32, 0x54, - 0x30, 0x69, 0x57, 0x8e, 0x01, 0x42, 0x7f, 0x21, 0x53, 0x31, 0x09, 0xc9, 0xf4, 0x61, 0x3c, 0x81, - 0xba, 0xd8, 0x74, 0xc4, 0x50, 0x05, 0x9a, 0x7d, 0x76, 0x28, 0x04, 0x2f, 0xdd, 0xb6, 0x5c, 0x34, - 0xcb, 0x04, 0xc3, 0xaa, 0x8c, 0x0f, 0x60, 0x51, 0xcb, 0x16, 0xeb, 0x9b, 0x62, 0x23, 0x9b, 0xd6, - 0x37, 0x51, 0xbb, 0xa0, 0x14, 0x63, 0x0d, 0x56, 0xc4, 0x67, 0xeb, 0x9c, 0xbb, 0x61, 0x77, 0x72, - 0x4c, 0x0e, 0x41, 0xc7, 0x73, 0x85, 0xd6, 0x51, 0x8a, 0x52, 0xae, 0x27, 0xf2, 0x0d, 0xa9, 0x9a, - 0x66, 0x91, 0x34, 0xd6, 0xb5, 0x1a, 0x30, 0xe3, 0x06, 0xfe, 0x4d, 0xa8, 0xa8, 0xa5, 0x08, 0x24, - 0x86, 0xf5, 0xb0, 0xd5, 0x32, 0xad, 0x83, 0xce, 0x5e, 0xbb, 0x23, 0xb8, 0x9d, 0x18, 0x56, 0x04, - 0xec, 0xec, 0x20, 0x24, 0x63, 0xd4, 0xa1, 0xf6, 0x94, 0x87, 0x6d, 0xf7, 0xc4, 0x53, 0xce, 0xaf, - 0x1f, 0x17, 0x60, 0x21, 0x02, 0xc5, 0x2a, 0xee, 0x39, 0xf7, 0x03, 0xc7, 0x73, 0x51, 0x5a, 0x2d, - 0x99, 0xea, 0x53, 0x6c, 0x3d, 0xce, 0x80, 0xbb, 0xa1, 0x13, 0x5e, 0x59, 0x09, 0x7b, 0x58, 0x4d, - 0x81, 0xe5, 0x16, 0xb7, 0x0c, 0x05, 0x7b, 0xe8, 0xd8, 0xca, 0x8f, 0x4a, 0x1f, 0x02, 0xda, 0xf7, - 0x86, 0x9e, 0x8f, 0x82, 0x69, 0xc9, 0xa4, 0x0f, 0xf6, 0x08, 0x96, 0x85, 0x80, 0xac, 0x1b, 0x29, - 0x91, 0x7f, 0x90, 0x69, 0x8e, 0xb9, 0x93, 0xd1, 0x61, 0x6c, 0xa8, 0x14, 0x29, 0x62, 0x63, 0x13, - 0x39, 0xa4, 0x24, 0x13, 0x65, 0x20, 0x5d, 0x6b, 0xd1, 0x9d, 0x8c, 0x9a, 0x98, 0x12, 0xe1, 0x3f, - 0x86, 0x15, 0x81, 0x1f, 0xc9, 0x3e, 0x51, 0x8e, 0x05, 0xcc, 0x21, 0x0a, 0x6b, 0xcb, 0xb4, 0x28, - 0xcf, 0x2d, 0x28, 0x51, 0xab, 0xc4, 0x8c, 0x17, 0x48, 0xc6, 0xc6, 0xa6, 0x70, 0x3f, 0x98, 0x71, - 0x79, 0xce, 0xd1, 0x2e, 0x3d, 0xe5, 0xf2, 0xd4, 0x9c, 0xa6, 0xc5, 0x69, 0xa7, 0xe9, 0x63, 0x58, - 0x39, 0x16, 0x24, 0x78, 0xc6, 0xed, 0x01, 0xf7, 0xad, 0x98, 0xb0, 0x49, 0x97, 0x58, 0x12, 0x89, - 0xbb, 0x98, 0x16, 0xad, 0x03, 0x21, 0x84, 0x08, 0xb6, 0xc0, 0x07, 0x56, 0xe8, 0x59, 0x28, 0x9b, - 0x20, 0x83, 0x29, 0x9a, 0x55, 0x02, 0xf7, 0xbc, 0x2d, 0x01, 0x4c, 0xe2, 0x9d, 0xfa, 0xf6, 0xf8, - 0x4c, 0x4a, 0xfb, 0x11, 0xde, 0x53, 0x01, 0x64, 0xaf, 0xc1, 0xbc, 0x20, 0x79, 0x97, 0x93, 0x67, - 0x8a, 0xe4, 0x69, 0x05, 0x62, 0x6f, 0xc1, 0x1c, 0xd6, 0x11, 0x34, 0xea, 0x48, 0xef, 0x95, 0x98, - 0x91, 0x3b, 0xae, 0x29, 0xd3, 0x84, 0xa4, 0x37, 0xf1, 0x1d, 0xe2, 0x32, 0x25, 0x13, 0x7f, 0xb3, - 0xef, 0x6a, 0x2c, 0x6b, 0x09, 0xf3, 0xbe, 0x25, 0xf3, 0x4e, 0x51, 0xda, 0x75, 0xdc, 0xeb, 0x67, - 0xca, 0x8c, 0xbe, 0x97, 0x2f, 0x96, 0xeb, 0x15, 0xe3, 0x43, 0x28, 0xd0, 0xe8, 0x08, 0x22, 0xc4, - 0xb1, 0xcb, 0x48, 0x22, 0x44, 0x68, 0x03, 0xe6, 0x5d, 0x1e, 0x5e, 0x78, 0xfe, 0x73, 0x65, 0x31, - 0x96, 0x9f, 0xc6, 0x0f, 0xd1, 0xd4, 0x11, 0xb9, 0xc3, 0x49, 0x6b, 0x13, 0xe4, 0x41, 0xd3, 0x1b, - 0x9c, 0xd9, 0xd2, 0xfa, 0x52, 0x44, 0x40, 0xf7, 0xcc, 0x9e, 0x21, 0x8f, 0xec, 0xac, 0x47, 0xfc, - 0x2d, 0xa8, 0x29, 0x07, 0x7c, 0x60, 0x0d, 0xf9, 0x49, 0x28, 0xc9, 0xbd, 0x22, 0xbd, 0xef, 0xc1, - 0x1e, 0x3f, 0x09, 0x8d, 0x7d, 0x58, 0x94, 0x04, 0x79, 0x30, 0xe6, 0xaa, 0xea, 0x6f, 0xa5, 0x09, - 0xbb, 0xe5, 0xc7, 0x4b, 0xc9, 0x8d, 0x96, 0x02, 0x0b, 0x12, 0x12, 0xb0, 0xf1, 0x09, 0x30, 0x7d, - 0x1b, 0x96, 0xe5, 0x49, 0x91, 0x53, 0x19, 0xda, 0x95, 0xbf, 0x2a, 0x12, 0x6c, 0x9d, 0x81, 0x18, - 0x9d, 0x60, 0xd2, 0xef, 0xab, 0xc0, 0x88, 0xa2, 0xa9, 0x3e, 0x8d, 0x3f, 0xcd, 0xc0, 0x12, 0x16, - 0xa6, 0x84, 0x75, 0xc9, 0x64, 0x7f, 0xe2, 0x46, 0x8a, 0xf9, 0xd1, 0x65, 0x1f, 0xfa, 0xf8, 0xea, - 0xa6, 0xcd, 0xfc, 0x8c, 0x69, 0xf3, 0x1d, 0xa8, 0x0f, 0xf8, 0xd0, 0xc1, 0x18, 0x19, 0x25, 0x4a, - 0x90, 0x78, 0xbe, 0xa0, 0xe0, 0x52, 0x55, 0x33, 0xfe, 0x7e, 0x06, 0x16, 0x49, 0x52, 0x41, 0xa5, - 0x57, 0x0e, 0xd4, 0xc7, 0x4a, 0xcb, 0x93, 0xac, 0x4a, 0xf6, 0x29, 0xde, 0xc1, 0x11, 0x4a, 0xc8, - 0xbb, 0x37, 0xa4, 0xf6, 0x27, 0xa1, 0xec, 0x23, 0x54, 0x30, 0x5c, 0x0b, 0x81, 0x29, 0x31, 0x37, - 0xc9, 0x49, 0xd9, 0xbd, 0x81, 0xda, 0x87, 0x8b, 0xa0, 0xcd, 0xa2, 0x50, 0x3b, 0x05, 0xd8, 0xd8, - 0x81, 0x6a, 0xa2, 0x9a, 0x84, 0xfd, 0xb5, 0x42, 0xf6, 0xd7, 0x19, 0x1f, 0x47, 0x76, 0xd6, 0xc7, - 0x71, 0x05, 0x4b, 0x26, 0xb7, 0x07, 0x57, 0x3b, 0x9e, 0x7f, 0x18, 0x1c, 0x87, 0x3b, 0x24, 0xfe, - 0x09, 0xfe, 0x1e, 0x39, 0xee, 0x12, 0x46, 0x4e, 0xe5, 0xbf, 0x51, 0xba, 0xec, 0xd7, 0xa0, 0x16, - 0x7b, 0xf8, 0x34, 0x43, 0x59, 0x35, 0x72, 0xf2, 0xa1, 0xbd, 0x4c, 0xe8, 0x81, 0xc1, 0x71, 0x28, - 0x4d, 0x65, 0xf8, 0xdb, 0xf8, 0x1b, 0x79, 0x60, 0x82, 0x9a, 0xa7, 0x08, 0x66, 0xca, 0x37, 0x99, - 0x9d, 0xf1, 0x4d, 0x3e, 0x02, 0xa6, 0x21, 0x28, 0x97, 0x69, 0x2e, 0x72, 0x99, 0xd6, 0x63, 0x5c, - 0xe9, 0x31, 0x7d, 0x04, 0xcb, 0x52, 0x96, 0x4e, 0x36, 0x95, 0x48, 0x83, 0x91, 0x50, 0x9d, 0x68, - 0xaf, 0xf2, 0x4b, 0x0a, 0xdd, 0x9c, 0x4c, 0x61, 0xe8, 0x97, 0x54, 0x5a, 0xb9, 0x46, 0x80, 0x73, - 0x2f, 0x25, 0xc0, 0xf9, 0x19, 0x02, 0xd4, 0x2c, 0x33, 0xc5, 0xa4, 0x65, 0xc6, 0x80, 0xaa, 0xf2, - 0x3e, 0x52, 0xd0, 0x05, 0x09, 0x8e, 0x65, 0xe9, 0x82, 0xc4, 0xc0, 0x8b, 0xfb, 0x50, 0x57, 0xe6, - 0x93, 0xc8, 0xf6, 0x43, 0x01, 0x05, 0xd2, 0xfa, 0xb6, 0xa5, 0x2c, 0x40, 0x09, 0x4b, 0x7b, 0x79, - 0xca, 0xd2, 0xfe, 0x2e, 0x2c, 0x06, 0x82, 0x7e, 0xad, 0x89, 0x2b, 0xa3, 0x7f, 0xf8, 0x00, 0xd5, - 0xac, 0xa2, 0x59, 0xc7, 0x84, 0xa3, 0x18, 0x3e, 0x6b, 0xd7, 0xa8, 0xa6, 0xd8, 0x35, 0x9e, 0xc4, - 0x8e, 0xba, 0xe0, 0xcc, 0x19, 0xa1, 0xcc, 0x10, 0x47, 0xca, 0xc8, 0x01, 0xee, 0x9e, 0x39, 0x23, - 0x53, 0x79, 0x85, 0xc5, 0x87, 0xf1, 0x7f, 0x32, 0x50, 0x17, 0x74, 0x90, 0x58, 0x62, 0xdf, 0x06, - 0x64, 0x06, 0xaf, 0xb8, 0xc2, 0xca, 0x02, 0x57, 0x2d, 0xb0, 0x0f, 0x01, 0x57, 0x8c, 0x25, 0x74, - 0x4a, 0xb9, 0xbe, 0x1a, 0xc9, 0xf5, 0x15, 0xf3, 0xd0, 0xdd, 0x1b, 0xa4, 0x7b, 0x08, 0x08, 0xfb, - 0x36, 0x94, 0x04, 0x61, 0x22, 0x95, 0xc8, 0x00, 0x2d, 0x25, 0x79, 0xa5, 0xac, 0x11, 0x91, 0x75, - 0x2c, 0x3f, 0xd3, 0x7c, 0xab, 0xf9, 0x14, 0xdf, 0xaa, 0xb6, 0x80, 0x77, 0x01, 0x9e, 0xf1, 0xab, - 0x3d, 0xaf, 0x8f, 0x1a, 0xef, 0x6d, 0x00, 0x41, 0xcb, 0x27, 0xf6, 0xc8, 0x91, 0x06, 0x9b, 0x82, - 0x59, 0x7a, 0xce, 0xaf, 0x76, 0x10, 0x20, 0x26, 0x52, 0x24, 0xc7, 0xab, 0xb8, 0x60, 0x16, 0x9f, - 0xf3, 0x2b, 0x5a, 0xc2, 0x16, 0x54, 0x9f, 0xf1, 0xab, 0x6d, 0x4e, 0x42, 0xa6, 0xe7, 0x0b, 0x22, - 0xf2, 0xed, 0x0b, 0x21, 0x55, 0x26, 0xfc, 0xa2, 0x65, 0xdf, 0xbe, 0x78, 0xc6, 0xaf, 0x94, 0x8f, - 0x76, 0x5e, 0xa4, 0x0f, 0xbd, 0xbe, 0xdc, 0x37, 0x55, 0x84, 0x47, 0xdc, 0x28, 0x73, 0xee, 0x39, - 0xfe, 0x36, 0xfe, 0x32, 0x03, 0x55, 0xd1, 0x7e, 0x64, 0xcb, 0x62, 0xca, 0x54, 0xa0, 0x50, 0x26, - 0x0e, 0x14, 0x7a, 0x2c, 0xb9, 0x1a, 0xf1, 0xf8, 0xec, 0xf5, 0x3c, 0x1e, 0xe7, 0x86, 0x18, 0xfc, - 0xfb, 0x50, 0xa2, 0x65, 0x29, 0xd6, 0x79, 0x2e, 0x31, 0xc1, 0x89, 0x0e, 0x99, 0x45, 0x44, 0x7b, - 0x46, 0x71, 0x09, 0x9a, 0xf1, 0x8f, 0x86, 0xb8, 0xe4, 0x47, 0x26, 0xbf, 0x94, 0x69, 0x28, 0x5c, - 0x13, 0x97, 0xa0, 0x5b, 0xd6, 0xe6, 0x66, 0x2c, 0x6b, 0x07, 0x50, 0x14, 0x53, 0x8d, 0x9d, 0x4d, - 0x29, 0x34, 0x93, 0x56, 0xa8, 0x90, 0x04, 0x6c, 0xb1, 0x29, 0x08, 0x46, 0x97, 0x95, 0x92, 0x80, - 0x1d, 0xf0, 0x43, 0x64, 0x76, 0x19, 0x28, 0x6b, 0x2b, 0x00, 0x8d, 0x93, 0xd1, 0x78, 0xd1, 0x72, - 0x49, 0x92, 0x78, 0x62, 0xc0, 0x77, 0x6f, 0x98, 0xd5, 0x7e, 0x62, 0x06, 0x36, 0x24, 0xad, 0x62, - 0xce, 0x6c, 0x22, 0xa6, 0x49, 0x35, 0x5c, 0x11, 0xa8, 0xf8, 0xbd, 0x39, 0x07, 0x79, 0x81, 0x6a, - 0x7c, 0x0c, 0x8b, 0x5a, 0x33, 0x48, 0xcd, 0x7f, 0xd5, 0x1e, 0x1a, 0xbf, 0x12, 0x65, 0x16, 0x75, - 0x90, 0xfb, 0x48, 0xc5, 0x78, 0xf0, 0x01, 0x75, 0x5c, 0xc6, 0x92, 0x10, 0x48, 0xa0, 0xbd, 0x72, - 0xdc, 0xc1, 0xaf, 0xc1, 0x92, 0x56, 0xfa, 0x8e, 0xe3, 0xda, 0x43, 0xe7, 0x87, 0xb8, 0xe1, 0x07, - 0xce, 0xa9, 0x3b, 0x55, 0x3e, 0x81, 0xbe, 0x52, 0xf9, 0xff, 0x20, 0x0b, 0xcb, 0xb2, 0x02, 0x8c, - 0xda, 0x73, 0x84, 0x14, 0xb7, 0x1f, 0x9c, 0xb2, 0x6f, 0x43, 0x55, 0x8c, 0x8d, 0xe5, 0xf3, 0x53, - 0x27, 0x08, 0xb9, 0x72, 0x5b, 0xa5, 0x30, 0x2e, 0xb1, 0x99, 0x0b, 0x54, 0x53, 0x62, 0xb2, 0x8f, - 0xa1, 0x8c, 0x59, 0xc9, 0x8c, 0x22, 0x27, 0xa2, 0x31, 0x9b, 0x91, 0x06, 0x7a, 0xf7, 0x86, 0x09, - 0x41, 0x3c, 0xec, 0x1f, 0x43, 0x19, 0xe7, 0xf0, 0x1c, 0x07, 0x72, 0x8a, 0x55, 0xcd, 0x0c, 0xb4, - 0xc8, 0x3c, 0x8e, 0x87, 0xbd, 0x09, 0x55, 0x62, 0x56, 0x72, 0x9c, 0x64, 0x34, 0xd0, 0xfa, 0x6c, - 0x76, 0x35, 0x92, 0xa2, 0xf1, 0x63, 0xed, 0x7b, 0xb3, 0x04, 0xf3, 0xa1, 0xef, 0x9c, 0x9e, 0x72, - 0xdf, 0x58, 0x8d, 0x86, 0x46, 0x70, 0x61, 0xde, 0x0d, 0xf9, 0x58, 0xc8, 0xe6, 0xc6, 0xbf, 0xcb, - 0x40, 0x59, 0xf2, 0xd5, 0x9f, 0xd8, 0x57, 0xb6, 0xae, 0x85, 0xbd, 0x92, 0xc5, 0x26, 0x8e, 0x72, - 0xbd, 0x07, 0x0b, 0x23, 0x21, 0xa7, 0x0b, 0x3d, 0x32, 0xe1, 0x28, 0xab, 0x29, 0xb0, 0x14, 0x93, - 0x37, 0x60, 0x09, 0xa5, 0xe6, 0xc0, 0x0a, 0x9d, 0xa1, 0xa5, 0x12, 0x65, 0x88, 0xe9, 0x22, 0x25, - 0xf5, 0x9c, 0xe1, 0xbe, 0x4c, 0x10, 0xc2, 0x63, 0x10, 0xda, 0xa7, 0x5c, 0xae, 0x6d, 0xfa, 0x30, - 0x1a, 0xb0, 0x3a, 0xa5, 0x42, 0x2a, 0xf5, 0xf7, 0xff, 0x2e, 0xc2, 0xda, 0x4c, 0x92, 0x54, 0x83, - 0x23, 0x07, 0xd1, 0xd0, 0x19, 0x1d, 0x7b, 0x91, 0xf9, 0x34, 0xa3, 0x39, 0x88, 0xf6, 0x44, 0x8a, - 0x32, 0x9f, 0x72, 0x58, 0x51, 0x04, 0x89, 0xf6, 0xcf, 0x48, 0xcb, 0xcc, 0xa2, 0x0e, 0xf4, 0x7e, - 0x72, 0x13, 0x9b, 0xae, 0x4e, 0xc1, 0x75, 0xd1, 0x68, 0x69, 0x3c, 0x03, 0x0b, 0xd8, 0xaf, 0x43, - 0x23, 0xa2, 0x7b, 0x29, 0xb6, 0x6b, 0x2a, 0xb3, 0xa8, 0xe9, 0xbd, 0x97, 0xd4, 0x94, 0xb0, 0xdd, - 0xa1, 0xec, 0xb4, 0xaa, 0x96, 0x0c, 0x15, 0x18, 0xd5, 0x75, 0x0e, 0xaf, 0xab, 0xba, 0x50, 0x0c, - 0x9f, 0xad, 0x31, 0xff, 0x4a, 0x7d, 0x43, 0xbb, 0x64, 0xa2, 0x5a, 0xf3, 0x96, 0x2c, 0x38, 0x4a, - 0xd2, 0xeb, 0x3d, 0x83, 0xd5, 0x0b, 0xdb, 0x09, 0x55, 0x1f, 0x35, 0x8d, 0xbd, 0x80, 0xf5, 0x3d, - 0x7e, 0x49, 0x7d, 0x9f, 0x51, 0xe6, 0x84, 0x62, 0xb2, 0x7c, 0x31, 0x0b, 0x0c, 0xd6, 0xff, 0x49, - 0x0e, 0x6a, 0xc9, 0x52, 0x04, 0x63, 0x91, 0x9b, 0x8d, 0x92, 0x37, 0xa5, 0x10, 0x2c, 0x4d, 0xfb, - 0x1d, 0x92, 0x33, 0x67, 0x9d, 0x0e, 0xd9, 0x14, 0xa7, 0x83, 0x6e, 0xeb, 0xcf, 0xbd, 0xcc, 0xb9, - 0x9a, 0x7f, 0x25, 0xe7, 0x6a, 0x21, 0xcd, 0xb9, 0x7a, 0xbd, 0x47, 0x6e, 0xee, 0x27, 0xf2, 0xc8, - 0xcd, 0xbf, 0xd0, 0x23, 0xa7, 0xf9, 0x11, 0x8b, 0xd7, 0x58, 0xe8, 0x35, 0xcf, 0x62, 0x8a, 0x47, - 0xae, 0xf4, 0x15, 0x3c, 0x72, 0xeb, 0x7f, 0x99, 0x01, 0x36, 0xbb, 0x3a, 0xd8, 0x53, 0xf2, 0xe7, - 0xb8, 0x7c, 0x28, 0x39, 0xf7, 0xd7, 0x5f, 0x6d, 0x85, 0x29, 0x82, 0x50, 0xb9, 0xd9, 0x43, 0x58, - 0xd2, 0x03, 0xe1, 0x75, 0xad, 0xbd, 0x6a, 0x32, 0x3d, 0x29, 0xb6, 0xed, 0x68, 0x9e, 0xec, 0xfc, - 0x4b, 0x3d, 0xd9, 0x85, 0x97, 0x7a, 0xb2, 0xe7, 0x92, 0x9e, 0xec, 0xf5, 0xff, 0x94, 0x81, 0xa5, - 0x14, 0x22, 0xfe, 0xd9, 0xf5, 0x59, 0xd0, 0x5e, 0x82, 0xad, 0x65, 0x25, 0xed, 0xe9, 0x1c, 0x6d, - 0x0f, 0xca, 0xf1, 0x54, 0xa8, 0x83, 0x22, 0x0f, 0x5e, 0xc6, 0x5d, 0xe2, 0x1c, 0xa6, 0x9e, 0x7d, - 0xfd, 0xf7, 0xb3, 0x50, 0xd6, 0x12, 0xc5, 0x28, 0x12, 0xc9, 0x6a, 0x01, 0x44, 0x24, 0x19, 0xa2, - 0xcd, 0xe1, 0x0e, 0x48, 0xa7, 0x06, 0xa5, 0xd3, 0xe2, 0x92, 0x62, 0x20, 0x22, 0x6c, 0xc0, 0x92, - 0xf2, 0xb5, 0xf1, 0x38, 0x4e, 0x50, 0xee, 0x35, 0x8b, 0xd2, 0xe3, 0xc6, 0xa3, 0xb0, 0x43, 0xf6, - 0x50, 0xa9, 0x83, 0xf1, 0xdc, 0x21, 0xa9, 0x93, 0xc7, 0x60, 0x91, 0x16, 0x88, 0x9a, 0x44, 0x41, - 0xe7, 0xef, 0xc3, 0x8a, 0x5a, 0x1e, 0xc9, 0x1c, 0xe4, 0x44, 0x60, 0x72, 0x71, 0xe8, 0x59, 0xbe, - 0x0b, 0xb7, 0xa7, 0xda, 0x34, 0x95, 0x95, 0x02, 0x5a, 0x6f, 0x26, 0x5a, 0xa7, 0x97, 0xb0, 0xfe, - 0x23, 0xa8, 0x26, 0x18, 0xe5, 0xcf, 0x6e, 0xca, 0xa7, 0xed, 0x3c, 0x34, 0xa2, 0xba, 0x9d, 0x67, - 0xfd, 0x7f, 0xe7, 0x80, 0xcd, 0xf2, 0xea, 0x9f, 0x67, 0x13, 0x66, 0x09, 0x33, 0x97, 0x42, 0x98, - 0xff, 0xdf, 0xe4, 0x87, 0x77, 0x61, 0x51, 0x1e, 0x98, 0xd2, 0x1c, 0xa6, 0xb4, 0x38, 0xeb, 0x51, - 0x82, 0x6a, 0xc5, 0x87, 0xd3, 0x81, 0x1b, 0xc5, 0xc4, 0x19, 0x11, 0x4d, 0x80, 0x9a, 0x8a, 0xdf, - 0x38, 0x82, 0x39, 0xdb, 0xed, 0x9f, 0x79, 0xbe, 0xe4, 0x83, 0xbf, 0xf0, 0x95, 0xb7, 0xcf, 0x8d, - 0x26, 0xe6, 0x47, 0xa9, 0xcd, 0x94, 0x85, 0x19, 0xef, 0x43, 0x59, 0x03, 0xb3, 0x12, 0x14, 0xf6, - 0xda, 0xfb, 0x9b, 0x07, 0xf5, 0x1b, 0xac, 0x0a, 0x25, 0xb3, 0xb5, 0x75, 0xf0, 0x69, 0xcb, 0x6c, - 0x6d, 0xd7, 0x33, 0xac, 0x08, 0xf9, 0xbd, 0x83, 0x6e, 0xaf, 0x9e, 0x35, 0xd6, 0xa1, 0x21, 0x4b, - 0x9c, 0xf5, 0x59, 0xfc, 0x76, 0x3e, 0x32, 0x17, 0x62, 0xa2, 0x54, 0xd1, 0xbf, 0x01, 0x15, 0x5d, - 0xbc, 0x91, 0x14, 0x31, 0xe5, 0xb3, 0x17, 0xca, 0xb9, 0xa7, 0xf1, 0xea, 0x2d, 0x20, 0x8f, 0xed, - 0x20, 0xca, 0x96, 0x4d, 0xc8, 0xad, 0x29, 0xde, 0x41, 0x54, 0x7e, 0x12, 0x64, 0xf8, 0x57, 0xa0, - 0x96, 0x34, 0xe0, 0x4b, 0x8e, 0x94, 0xa6, 0x70, 0x8a, 0xdc, 0x09, 0x8b, 0x3e, 0xfb, 0x2e, 0xd4, - 0xa7, 0x1d, 0x00, 0x52, 0x78, 0xbe, 0x26, 0xff, 0x82, 0x93, 0xf4, 0x09, 0xb0, 0x5d, 0x58, 0x4e, - 0x13, 0xf0, 0x90, 0x3e, 0xae, 0x37, 0x52, 0xb0, 0x59, 0x21, 0x8e, 0x7d, 0x4b, 0xfa, 0x79, 0x0a, - 0x38, 0xfd, 0x6f, 0x25, 0xeb, 0xd7, 0x06, 0x7b, 0x83, 0xfe, 0x69, 0x1e, 0x9f, 0x73, 0x80, 0x18, - 0xc6, 0xea, 0x50, 0x39, 0x38, 0x6c, 0x75, 0xac, 0xad, 0xdd, 0x66, 0xa7, 0xd3, 0xda, 0xab, 0xdf, - 0x60, 0x0c, 0x6a, 0xe8, 0xab, 0xde, 0x8e, 0x60, 0x19, 0x01, 0x93, 0xfe, 0x36, 0x05, 0xcb, 0xb2, - 0x65, 0xa8, 0xb7, 0x3b, 0x53, 0xd0, 0x1c, 0x6b, 0xc0, 0xf2, 0x61, 0x8b, 0xdc, 0xdb, 0x89, 0x72, - 0xf3, 0x42, 0x69, 0x90, 0xdd, 0x15, 0x4a, 0x03, 0x1d, 0xfc, 0x93, 0xeb, 0x40, 0xc9, 0xd2, 0xbf, - 0x93, 0x81, 0x95, 0xa9, 0x84, 0xf8, 0x38, 0x07, 0x49, 0xd2, 0x49, 0x19, 0xba, 0x82, 0x40, 0xb5, - 0x9a, 0xde, 0x85, 0xc5, 0xc8, 0xf0, 0x34, 0xb5, 0x2b, 0xd5, 0xa3, 0x04, 0x85, 0xfc, 0x10, 0x96, - 0x34, 0xfb, 0xd5, 0x14, 0xaf, 0x60, 0x5a, 0x92, 0xcc, 0x60, 0xac, 0x45, 0x61, 0xf3, 0x53, 0xad, - 0x1e, 0xd0, 0x69, 0x42, 0x3d, 0x21, 0x76, 0x83, 0x25, 0xdb, 0xab, 0x3e, 0xd9, 0xa3, 0x29, 0x42, - 0x48, 0xb6, 0x56, 0x9f, 0x70, 0x55, 0xfd, 0x1f, 0xcc, 0x01, 0xfb, 0x64, 0xc2, 0xfd, 0x2b, 0x3c, - 0xae, 0x11, 0xbc, 0x2c, 0x7e, 0x51, 0x59, 0x5a, 0xb2, 0xaf, 0x74, 0x24, 0x2b, 0xed, 0x48, 0x54, - 0xfe, 0xe5, 0x47, 0xa2, 0x0a, 0x2f, 0x3b, 0x12, 0xf5, 0x26, 0x54, 0x9d, 0x53, 0xd7, 0x13, 0xac, - 0x50, 0x48, 0xc2, 0x41, 0x63, 0xee, 0x6e, 0xee, 0x7e, 0xc5, 0xac, 0x48, 0xa0, 0x90, 0x83, 0x03, - 0xf6, 0x71, 0x8c, 0xc4, 0x07, 0xa7, 0x78, 0x7c, 0x4f, 0x67, 0x82, 0xad, 0xc1, 0x29, 0x97, 0x86, - 0x25, 0xd4, 0x34, 0x54, 0x66, 0x01, 0x0f, 0xd8, 0x5b, 0x50, 0x0b, 0xbc, 0x89, 0x50, 0x2c, 0xd4, - 0x30, 0x90, 0xa3, 0xac, 0x42, 0xd0, 0x43, 0xe5, 0x15, 0x5d, 0x9a, 0x04, 0xdc, 0x1a, 0x39, 0x41, - 0x20, 0xc4, 0xb3, 0xbe, 0xe7, 0x86, 0xbe, 0x37, 0x94, 0xbe, 0xaf, 0xc5, 0x49, 0xc0, 0xf7, 0x29, - 0x65, 0x8b, 0x12, 0xd8, 0x37, 0xe3, 0x26, 0x8d, 0x6d, 0xc7, 0x0f, 0x1a, 0x80, 0x4d, 0x52, 0x3d, - 0x45, 0xf9, 0xdd, 0x76, 0xfc, 0xa8, 0x2d, 0xe2, 0x23, 0x98, 0x3a, 0xaa, 0x55, 0x9e, 0x3e, 0xaa, - 0xf5, 0x83, 0xf4, 0xa3, 0x5a, 0x55, 0x2c, 0xfa, 0x91, 0x2c, 0x7a, 0x76, 0x8a, 0xbf, 0xd2, 0x89, - 0xad, 0xd9, 0x13, 0x68, 0xb5, 0xaf, 0x72, 0x02, 0x6d, 0x21, 0xed, 0x04, 0xda, 0xfb, 0x50, 0xc6, - 0xb3, 0x41, 0xd6, 0x99, 0x23, 0x64, 0x38, 0xf2, 0xe5, 0xd5, 0xf5, 0xc3, 0x43, 0xbb, 0x8e, 0x1b, - 0x9a, 0xe0, 0xab, 0x9f, 0xc1, 0xec, 0x61, 0xb0, 0xc5, 0x9f, 0xe3, 0x61, 0x30, 0x79, 0x86, 0x69, - 0x03, 0x8a, 0x6a, 0x9e, 0x18, 0x83, 0xfc, 0x89, 0xef, 0x8d, 0x94, 0x8f, 0x43, 0xfc, 0x66, 0x35, - 0xc8, 0x86, 0x9e, 0xcc, 0x9c, 0x0d, 0x3d, 0xe3, 0x57, 0xa1, 0xac, 0x91, 0x1a, 0x7b, 0x83, 0xec, - 0x92, 0x42, 0x37, 0x93, 0xb2, 0x25, 0x8d, 0x62, 0x49, 0x42, 0xdb, 0x03, 0xc1, 0x6f, 0x06, 0x8e, - 0xcf, 0xf1, 0xd8, 0xa6, 0xe5, 0xf3, 0x73, 0xee, 0x07, 0xca, 0xe7, 0x54, 0x8f, 0x12, 0x4c, 0x82, - 0x1b, 0xbf, 0x06, 0x4b, 0x89, 0xb9, 0x95, 0x2c, 0xe2, 0x2d, 0x98, 0xc3, 0x71, 0x53, 0x31, 0x01, - 0xc9, 0x43, 0x59, 0x32, 0x0d, 0xcf, 0xe3, 0x93, 0xbb, 0xcc, 0x1a, 0xfb, 0xde, 0x31, 0x56, 0x92, - 0x31, 0xcb, 0x12, 0x76, 0xe8, 0x7b, 0xc7, 0xc6, 0x9f, 0xe7, 0x20, 0xb7, 0xeb, 0x8d, 0xf5, 0x18, - 0xb5, 0xcc, 0x4c, 0x8c, 0x9a, 0x54, 0x38, 0xad, 0x48, 0xa1, 0x94, 0x32, 0x3b, 0x3a, 0x8a, 0x94, - 0x52, 0x79, 0x1f, 0x6a, 0x82, 0x4f, 0x84, 0x9e, 0xd0, 0xd8, 0x2f, 0x6c, 0x9f, 0x04, 0xe2, 0x1c, - 0x2d, 0x3e, 0x7b, 0x14, 0xf6, 0xbc, 0x1d, 0x82, 0xb3, 0x65, 0xc8, 0x45, 0xea, 0x0b, 0x26, 0x8b, - 0x4f, 0xb6, 0x0a, 0x73, 0x18, 0xac, 0x7c, 0x25, 0x9d, 0xde, 0xf2, 0x8b, 0x7d, 0x1d, 0x96, 0x92, - 0xe5, 0x12, 0x2b, 0x92, 0xb2, 0x91, 0x5e, 0x30, 0xf2, 0xa4, 0x9b, 0x20, 0xf8, 0x08, 0xe1, 0xc8, - 0xd8, 0x99, 0x13, 0xce, 0x31, 0x49, 0x63, 0x7a, 0xc5, 0x04, 0xd3, 0xbb, 0x03, 0xe5, 0x70, 0x78, - 0x6e, 0x8d, 0xed, 0xab, 0xa1, 0x67, 0x0f, 0xe4, 0xfa, 0x86, 0x70, 0x78, 0x7e, 0x48, 0x10, 0xf6, - 0x10, 0x60, 0x34, 0x1e, 0xcb, 0xb5, 0x87, 0xce, 0x8f, 0x98, 0x94, 0xf7, 0x0f, 0x0f, 0x89, 0xe4, - 0xcc, 0xd2, 0x68, 0x3c, 0xa6, 0x9f, 0x6c, 0x1b, 0x6a, 0xa9, 0x47, 0x2b, 0x6f, 0xab, 0xd8, 0x5a, - 0x6f, 0xbc, 0x91, 0xb2, 0x38, 0xab, 0x7d, 0x1d, 0xb6, 0xfe, 0x5d, 0x60, 0x3f, 0xe5, 0x01, 0xc7, - 0x1e, 0x94, 0xa2, 0xf6, 0xe9, 0xe7, 0x03, 0x31, 0x5a, 0xbe, 0x9c, 0x38, 0x1f, 0xd8, 0x1c, 0x0c, - 0x7c, 0xc1, 0x17, 0x69, 0xc3, 0x8c, 0x58, 0x3e, 0x68, 0x3b, 0x66, 0x93, 0xf8, 0xbe, 0xf1, 0xdf, - 0x32, 0x50, 0xa0, 0xc3, 0x8a, 0x6f, 0xc3, 0x02, 0xe1, 0x47, 0xf1, 0x7e, 0xd2, 0x55, 0x4e, 0xfb, - 0x6e, 0x4f, 0x86, 0xfa, 0x89, 0x65, 0xa1, 0x1d, 0xb4, 0xce, 0x46, 0x33, 0xaf, 0x1d, 0xb6, 0xbe, - 0x03, 0xa5, 0xa8, 0x6a, 0x8d, 0x74, 0x8a, 0xaa, 0x66, 0xf6, 0x3a, 0xe4, 0xcf, 0xbc, 0xb1, 0xb2, - 0xfc, 0x40, 0x3c, 0x92, 0x26, 0xc2, 0xe3, 0xb6, 0x88, 0x3a, 0xa8, 0xf1, 0xd2, 0x62, 0x11, 0x55, - 0x82, 0x64, 0x30, 0xdb, 0xc7, 0xb9, 0x94, 0x3e, 0x1e, 0xc1, 0x82, 0xe0, 0x03, 0x5a, 0xc8, 0xca, - 0xf5, 0x9b, 0xe6, 0x3b, 0x42, 0xc2, 0xeb, 0x0f, 0x27, 0x03, 0xae, 0xdb, 0xde, 0x30, 0xbe, 0x4d, - 0xc2, 0x95, 0x64, 0x6d, 0xfc, 0x41, 0x86, 0xf8, 0x8b, 0x28, 0x97, 0xdd, 0x87, 0xbc, 0xd8, 0xdf, - 0xa6, 0x2c, 0xf1, 0xd1, 0xb1, 0x05, 0x81, 0x67, 0x22, 0x06, 0xde, 0x4e, 0x30, 0x19, 0x25, 0x4b, - 0xaf, 0x9a, 0x65, 0x77, 0x32, 0x8a, 0x4c, 0x57, 0x5f, 0x53, 0xdd, 0x9a, 0x32, 0xfb, 0x50, 0xef, - 0xa3, 0x65, 0xba, 0xa1, 0x05, 0xca, 0xe5, 0x13, 0x3b, 0xa6, 0x92, 0x02, 0x07, 0xa7, 0x5c, 0x0b, - 0x90, 0xfb, 0xe3, 0x2c, 0x54, 0x13, 0x2d, 0xc2, 0x48, 0x41, 0xb1, 0x01, 0x90, 0x63, 0x49, 0xce, - 0x37, 0x08, 0x90, 0x14, 0xd4, 0xb5, 0x71, 0xca, 0x26, 0xc6, 0x29, 0x0a, 0xce, 0xc9, 0xe9, 0xc1, - 0x39, 0x8f, 0xa0, 0x14, 0x1f, 0xb0, 0x4f, 0x36, 0x49, 0xd4, 0xa7, 0x0e, 0x6f, 0xc4, 0x48, 0x71, - 0x38, 0x4f, 0x41, 0x0f, 0xe7, 0xf9, 0x8e, 0x16, 0xfd, 0x31, 0x87, 0xc5, 0x18, 0x69, 0x23, 0xfa, - 0x73, 0x89, 0xfd, 0x30, 0x3e, 0x86, 0xb2, 0xd6, 0x78, 0x3d, 0xca, 0x23, 0x93, 0x88, 0xf2, 0x88, - 0x8e, 0x59, 0x65, 0xe3, 0x63, 0x56, 0xc6, 0xdf, 0xcc, 0x42, 0x55, 0xac, 0x2f, 0xc7, 0x3d, 0x3d, - 0xf4, 0x86, 0x4e, 0x1f, 0x1d, 0x4d, 0xd1, 0x0a, 0x93, 0x82, 0x96, 0x5a, 0x67, 0x72, 0x89, 0x91, - 0x9c, 0xa5, 0x9f, 0x26, 0x25, 0x26, 0x1d, 0x9d, 0x26, 0x35, 0xa0, 0x2a, 0x18, 0x23, 0xba, 0x8c, - 0xe2, 0xe3, 0xff, 0x66, 0xf9, 0x84, 0xf3, 0x4d, 0x3b, 0x20, 0x0e, 0xf9, 0x75, 0x58, 0x12, 0x38, - 0x78, 0x90, 0x6e, 0xe4, 0x0c, 0x87, 0x0e, 0x61, 0x92, 0xa1, 0xa9, 0x7e, 0xc2, 0xb9, 0x69, 0x87, - 0x7c, 0x5f, 0x24, 0xc8, 0xdb, 0x02, 0x8a, 0x03, 0x27, 0xb0, 0x8f, 0xe3, 0x78, 0xce, 0xe8, 0x1b, - 0x3d, 0xcb, 0xf6, 0xa5, 0xe6, 0x59, 0x26, 0x03, 0x44, 0x79, 0x64, 0x5f, 0x46, 0x9e, 0xe5, 0x29, - 0x4a, 0x9a, 0x9f, 0xa6, 0x24, 0xe3, 0xdf, 0x66, 0xa1, 0xac, 0x91, 0xe5, 0xab, 0xec, 0xae, 0xb7, - 0x67, 0x1c, 0x83, 0x25, 0xdd, 0x07, 0xf8, 0x66, 0xb2, 0x4a, 0x8c, 0x7d, 0xa1, 0x7b, 0x09, 0x34, - 0x02, 0xbe, 0x05, 0x25, 0xb1, 0xea, 0xde, 0x47, 0x13, 0xac, 0xbc, 0x55, 0x03, 0x01, 0x87, 0x93, - 0x63, 0x95, 0xf8, 0x18, 0x13, 0x0b, 0x71, 0xe2, 0x63, 0x91, 0xf8, 0xa2, 0x08, 0xeb, 0x0f, 0xa1, - 0x22, 0x4b, 0xc5, 0x39, 0xc5, 0xee, 0xc6, 0xab, 0x3e, 0x31, 0xdf, 0x66, 0x99, 0xaa, 0xa3, 0xc9, - 0x97, 0x19, 0x1f, 0xab, 0x8c, 0xc5, 0x97, 0x65, 0x7c, 0x4c, 0x1f, 0xc6, 0x4e, 0x14, 0xb4, 0x8e, - 0x71, 0x57, 0x8a, 0x8f, 0x3d, 0x84, 0x25, 0xc5, 0xae, 0x26, 0xae, 0xed, 0xba, 0xde, 0xc4, 0xed, - 0x73, 0x75, 0xfe, 0x8a, 0xc9, 0xa4, 0xa3, 0x38, 0xc5, 0x18, 0x44, 0x07, 0x74, 0x29, 0x7e, 0xeb, - 0x01, 0x14, 0x48, 0x2e, 0x27, 0xe1, 0x23, 0x9d, 0x71, 0x11, 0x0a, 0xbb, 0x0f, 0x05, 0x12, 0xcf, - 0xb3, 0xd7, 0x32, 0x1b, 0x42, 0x30, 0x9a, 0xc0, 0x44, 0xc6, 0x7d, 0x1e, 0xfa, 0x4e, 0x3f, 0x88, - 0x8f, 0x76, 0x15, 0x84, 0xfe, 0x49, 0x75, 0xc5, 0x96, 0xdb, 0x18, 0x13, 0x75, 0x54, 0xc2, 0x11, - 0x1b, 0xd3, 0x52, 0xa2, 0x0c, 0x29, 0x2e, 0x0d, 0x61, 0xf5, 0x98, 0x87, 0x17, 0x9c, 0xbb, 0xae, - 0x10, 0x86, 0xfa, 0xdc, 0x0d, 0x7d, 0x7b, 0x28, 0x26, 0x89, 0x7a, 0xf0, 0x64, 0xa6, 0xd4, 0xd8, - 0x06, 0xb2, 0x19, 0x67, 0xdc, 0x8a, 0xf2, 0x11, 0xef, 0x58, 0x39, 0x4e, 0x4b, 0x5b, 0xff, 0x15, - 0x58, 0xbf, 0x3e, 0x53, 0xca, 0x01, 0xce, 0xfb, 0x49, 0xae, 0x12, 0xf9, 0x01, 0x87, 0x9e, 0x1d, - 0x52, 0x6b, 0x74, 0xce, 0xd2, 0x81, 0xb2, 0x96, 0x12, 0xef, 0xfd, 0x19, 0x14, 0xee, 0xe8, 0x43, - 0xec, 0x48, 0xae, 0xe7, 0x8f, 0xd0, 0xef, 0x36, 0xb0, 0xe2, 0xd2, 0x33, 0xe6, 0x42, 0x0c, 0xc7, - 0x13, 0xeb, 0xc6, 0x06, 0x2c, 0xa0, 0x64, 0xaf, 0x6d, 0x74, 0x2f, 0x12, 0x06, 0x8d, 0x65, 0x60, - 0x1d, 0xe2, 0x5d, 0x7a, 0x38, 0xe7, 0x7f, 0xce, 0x41, 0x59, 0x03, 0x8b, 0xdd, 0x08, 0x03, 0x00, - 0xad, 0x81, 0x63, 0x8f, 0xb8, 0x72, 0x72, 0x56, 0xcd, 0x2a, 0x42, 0xb7, 0x25, 0x50, 0xec, 0xc5, - 0xf6, 0xf9, 0xa9, 0xe5, 0x4d, 0x42, 0x6b, 0xc0, 0x4f, 0x7d, 0xae, 0x5a, 0x59, 0xb1, 0xcf, 0x4f, - 0x0f, 0x26, 0xe1, 0x36, 0xc2, 0x04, 0x96, 0xe0, 0x25, 0x1a, 0x96, 0x8c, 0x59, 0x1b, 0xd9, 0x97, - 0x31, 0x96, 0x0c, 0x9c, 0x24, 0xca, 0xcc, 0x47, 0x81, 0x93, 0xa4, 0x2d, 0x4e, 0x6f, 0xa0, 0x85, - 0xd9, 0x0d, 0xf4, 0x9b, 0xb0, 0x4a, 0x1b, 0xa8, 0x64, 0xcd, 0xd6, 0xd4, 0x4a, 0x5e, 0xc6, 0x54, - 0xd9, 0x49, 0x4d, 0xec, 0xad, 0x8b, 0x1e, 0x28, 0xb6, 0x14, 0x38, 0x3f, 0x24, 0x46, 0x96, 0x31, - 0x45, 0xcf, 0x64, 0xe1, 0x5d, 0xe7, 0x87, 0x5c, 0x60, 0x62, 0x74, 0x8c, 0x8e, 0x29, 0xcf, 0x4f, - 0x8c, 0x1c, 0x77, 0x1a, 0xd3, 0xbe, 0x4c, 0x62, 0x96, 0x24, 0xa6, 0x7d, 0xa9, 0x63, 0x3e, 0x81, - 0xb5, 0x11, 0x1f, 0x38, 0x76, 0xb2, 0x58, 0x2b, 0x16, 0xdc, 0x96, 0x29, 0x59, 0xcb, 0xd3, 0x25, - 0xc5, 0x5d, 0x8c, 0xc6, 0x0f, 0xbd, 0xd1, 0xb1, 0x43, 0x32, 0x0b, 0xc5, 0xeb, 0xe4, 0xcd, 0x9a, - 0x3b, 0x19, 0x7d, 0x1f, 0xc1, 0x22, 0x4b, 0x60, 0x54, 0xa1, 0xdc, 0x0d, 0xbd, 0xb1, 0x9a, 0xe6, - 0x1a, 0x54, 0xe8, 0x53, 0x1e, 0x6a, 0xbc, 0x05, 0x37, 0x91, 0x25, 0xf4, 0xbc, 0xb1, 0x37, 0xf4, - 0x4e, 0xaf, 0x12, 0x76, 0xbc, 0x7f, 0x9f, 0x81, 0xa5, 0x44, 0xaa, 0x64, 0xaf, 0xdf, 0x24, 0x7e, - 0x16, 0x9d, 0x4c, 0xa3, 0x35, 0xb8, 0xa8, 0xad, 0x41, 0x42, 0x24, 0x66, 0xa6, 0x4e, 0xab, 0x35, - 0xe3, 0x1b, 0x15, 0x54, 0x46, 0x62, 0x29, 0x8d, 0x59, 0x96, 0x22, 0xf3, 0xab, 0xbb, 0x16, 0x54, - 0x11, 0xbf, 0x20, 0xcf, 0xb8, 0x0c, 0x64, 0x97, 0x73, 0xc9, 0x83, 0x02, 0xba, 0xcd, 0x4f, 0xb5, - 0x20, 0x36, 0x04, 0x06, 0xc6, 0x3f, 0xcd, 0x00, 0xc4, 0xad, 0xc3, 0xa3, 0x0a, 0x91, 0xdc, 0x42, - 0x97, 0x95, 0x69, 0x32, 0xca, 0x1b, 0x50, 0x89, 0x22, 0x96, 0x63, 0x49, 0xa8, 0xac, 0x60, 0x42, - 0x1c, 0xba, 0x07, 0x0b, 0xa7, 0x43, 0xef, 0x18, 0x25, 0x56, 0x29, 0xb7, 0x50, 0xbc, 0x5a, 0x8d, - 0xc0, 0x4a, 0x1a, 0x89, 0xe5, 0xa6, 0x7c, 0x6a, 0x50, 0xb3, 0x2e, 0x05, 0x19, 0xbf, 0x95, 0x8d, - 0x42, 0x37, 0xe3, 0x91, 0x78, 0xb1, 0x7a, 0xf7, 0x93, 0xc4, 0xd2, 0xbc, 0xc8, 0xbd, 0xf8, 0x31, - 0xd4, 0x7c, 0xda, 0x94, 0xd4, 0x8e, 0x95, 0x7f, 0xc1, 0x8e, 0x55, 0xf5, 0x13, 0x92, 0xce, 0x3b, - 0x50, 0xb7, 0x07, 0xe7, 0xdc, 0x0f, 0x1d, 0xb4, 0xd6, 0xa3, 0x7c, 0x2c, 0x83, 0x25, 0x35, 0x38, - 0x0a, 0xa2, 0xf7, 0x60, 0x41, 0x1e, 0xb4, 0x8d, 0x30, 0xe5, 0xd5, 0x3d, 0x31, 0x58, 0x20, 0x1a, - 0xff, 0x42, 0xc5, 0x8a, 0x26, 0x67, 0xf7, 0xc5, 0xa3, 0xa2, 0xf7, 0x30, 0x3b, 0xeb, 0x40, 0x95, - 0x84, 0x24, 0x9d, 0x00, 0x92, 0x1f, 0x11, 0x50, 0xba, 0x00, 0x92, 0xc3, 0x9a, 0x7f, 0x95, 0x61, - 0x35, 0xfe, 0x63, 0x06, 0xe6, 0x77, 0xbd, 0xf1, 0xae, 0x43, 0xc1, 0xfa, 0xb8, 0x4c, 0x22, 0x1f, - 0xd5, 0x9c, 0xf8, 0xc4, 0xc0, 0x9f, 0x17, 0x9c, 0x27, 0x4b, 0x15, 0xf3, 0xaa, 0x49, 0x31, 0xef, - 0x3b, 0x70, 0x0b, 0x5d, 0x80, 0xbe, 0x37, 0xf6, 0x7c, 0xb1, 0x54, 0xed, 0x21, 0x89, 0x7b, 0x9e, - 0x1b, 0x9e, 0x29, 0xde, 0x79, 0xf3, 0x84, 0xf3, 0x43, 0x0d, 0x63, 0x3f, 0x42, 0xc0, 0x13, 0x9b, - 0xc3, 0xf0, 0xdc, 0x22, 0x0d, 0x5d, 0xca, 0xa3, 0xc4, 0x51, 0x17, 0x44, 0x42, 0x0b, 0xe1, 0x28, - 0x91, 0x1a, 0xdf, 0x82, 0x52, 0x64, 0xec, 0x61, 0xef, 0x42, 0xe9, 0xcc, 0x1b, 0x4b, 0x8b, 0x50, - 0x26, 0x71, 0xe6, 0x4e, 0xf6, 0xda, 0x2c, 0x9e, 0xd1, 0x8f, 0xc0, 0xf8, 0xf3, 0x79, 0x98, 0x6f, - 0xbb, 0xe7, 0x9e, 0xd3, 0xc7, 0x68, 0xd3, 0x11, 0x1f, 0x79, 0xea, 0xb4, 0xbf, 0xf8, 0x8d, 0xb1, - 0x59, 0xf1, 0x05, 0x3c, 0x39, 0x19, 0x9b, 0x15, 0x5d, 0xbd, 0xb3, 0x02, 0x73, 0xbe, 0x7e, 0x83, - 0x4e, 0xc1, 0xc7, 0xf8, 0xf7, 0x68, 0xbf, 0x2c, 0x68, 0xb7, 0x25, 0x88, 0xb2, 0xe8, 0x66, 0x17, - 0x1c, 0x32, 0x3a, 0x7d, 0x59, 0x42, 0x08, 0x0e, 0xd8, 0x6b, 0x30, 0x2f, 0x8f, 0xb8, 0xd1, 0x99, - 0x24, 0x0a, 0x58, 0x97, 0x20, 0xa4, 0x06, 0x9f, 0x93, 0x0b, 0x37, 0x12, 0x64, 0x73, 0x66, 0x45, - 0x01, 0xb7, 0x05, 0xad, 0xdd, 0x81, 0x32, 0xe1, 0x13, 0x4a, 0x51, 0x06, 0x69, 0x22, 0x08, 0x11, - 0x52, 0x2e, 0xa2, 0x2a, 0xa5, 0x5e, 0x44, 0x85, 0xe1, 0xc4, 0x11, 0x97, 0xa5, 0x2e, 0x02, 0x5d, - 0x3f, 0xa4, 0xc1, 0xd5, 0x2d, 0x6c, 0xd2, 0xa6, 0x42, 0x87, 0x91, 0x95, 0x4d, 0xe5, 0x4d, 0xa8, - 0x9e, 0xd8, 0xc3, 0xe1, 0xb1, 0xdd, 0x7f, 0x4e, 0xa6, 0x80, 0x0a, 0x59, 0x3f, 0x15, 0x10, 0x6d, - 0x01, 0x77, 0xa0, 0xac, 0xcd, 0x32, 0x46, 0x60, 0xe6, 0x4d, 0x88, 0xe7, 0x77, 0xda, 0xc2, 0x57, - 0x7b, 0x05, 0x0b, 0x9f, 0x16, 0x89, 0xba, 0x90, 0x8c, 0x44, 0xbd, 0x85, 0xdc, 0x54, 0x86, 0x1c, - 0xd6, 0xe9, 0xae, 0x1b, 0x7b, 0x30, 0xc0, 0x90, 0x43, 0xba, 0x58, 0x12, 0x07, 0x8f, 0xd2, 0x17, - 0x49, 0x97, 0x20, 0x18, 0xa1, 0xdc, 0x26, 0x33, 0xf5, 0xd8, 0x76, 0x06, 0x78, 0xe8, 0x80, 0xac, - 0x07, 0xf3, 0xf6, 0x28, 0x3c, 0xb4, 0x9d, 0x01, 0xbb, 0x0b, 0x15, 0x95, 0x8c, 0xbb, 0xe3, 0x12, - 0x8d, 0xbf, 0x4c, 0x16, 0x7b, 0xa2, 0x01, 0xd5, 0x08, 0x63, 0x14, 0x9f, 0x28, 0x2e, 0x4b, 0x14, - 0xa4, 0x83, 0xf7, 0x31, 0xca, 0x27, 0xe4, 0x78, 0x6e, 0xb8, 0xf6, 0xf8, 0x56, 0x14, 0x7c, 0x80, - 0x54, 0xaa, 0xfe, 0x93, 0x73, 0x8c, 0x30, 0x85, 0x70, 0x47, 0x3e, 0xba, 0xd5, 0x84, 0xfc, 0x2b, - 0x51, 0xd1, 0x47, 0x47, 0x08, 0xec, 0x5b, 0x9a, 0xfe, 0xda, 0x40, 0xe4, 0xd7, 0xa6, 0xca, 0xbf, - 0xee, 0xcc, 0xd5, 0x6d, 0x00, 0x27, 0x10, 0xbb, 0x4c, 0xc0, 0xdd, 0x01, 0x1e, 0x01, 0x2e, 0x9a, - 0x25, 0x27, 0x78, 0x46, 0x80, 0x9f, 0xad, 0x62, 0xdb, 0x84, 0x8a, 0xde, 0x4d, 0x56, 0x84, 0xfc, - 0xc1, 0x61, 0xab, 0x53, 0xbf, 0xc1, 0xca, 0x30, 0xdf, 0x6d, 0xf5, 0x7a, 0x7b, 0xe8, 0xe9, 0xab, - 0x40, 0x31, 0x3a, 0xa7, 0x98, 0x15, 0x5f, 0xcd, 0xad, 0xad, 0xd6, 0x61, 0xaf, 0xb5, 0x5d, 0xcf, - 0x7d, 0x2f, 0x5f, 0xcc, 0xd6, 0x73, 0xc6, 0x5f, 0xe4, 0xa0, 0xac, 0x8d, 0xc2, 0x8b, 0x99, 0xf1, - 0x6d, 0x00, 0xd4, 0x24, 0xe3, 0x88, 0xd4, 0xbc, 0x59, 0x12, 0x10, 0x9a, 0x7c, 0xdd, 0x47, 0x91, - 0xa3, 0x4b, 0x94, 0x94, 0x8f, 0xe2, 0x4d, 0xa8, 0xd2, 0x7d, 0x44, 0xba, 0xbf, 0xb6, 0x60, 0x56, - 0x08, 0x28, 0x59, 0x35, 0x1e, 0x60, 0x46, 0x24, 0x3c, 0x3d, 0x27, 0x6f, 0x27, 0x21, 0x10, 0x9e, - 0x9f, 0xc3, 0xc3, 0x8f, 0x81, 0x37, 0x3c, 0xe7, 0x84, 0x41, 0x12, 0x61, 0x59, 0xc2, 0x7a, 0xf2, - 0x28, 0xb6, 0xe4, 0x87, 0xda, 0x09, 0xda, 0x82, 0x59, 0x21, 0xa0, 0xac, 0xe8, 0xeb, 0x8a, 0x80, - 0x28, 0x7a, 0x65, 0x6d, 0x96, 0x1a, 0x12, 0xc4, 0xb3, 0x37, 0x63, 0x46, 0x2c, 0x21, 0x61, 0x7c, - 0x6d, 0x36, 0xdf, 0xcb, 0xcd, 0x89, 0xec, 0x5d, 0x60, 0xa3, 0xf1, 0xd8, 0x4a, 0x31, 0xf0, 0xe5, - 0xcd, 0x85, 0xd1, 0x78, 0xdc, 0xd3, 0xec, 0x5f, 0x3f, 0x03, 0xdb, 0xe3, 0x17, 0xc0, 0x9a, 0x62, - 0x01, 0x63, 0x13, 0x23, 0x55, 0x2c, 0x66, 0xcb, 0x19, 0x9d, 0x2d, 0xa7, 0x70, 0xbf, 0x6c, 0x2a, - 0xf7, 0x7b, 0x11, 0x9f, 0x30, 0x76, 0xa0, 0x7c, 0xa8, 0xdd, 0x76, 0x76, 0x57, 0xec, 0x10, 0xea, - 0x9e, 0x33, 0xda, 0x3b, 0xc8, 0xa6, 0xe8, 0xcb, 0xeb, 0xcd, 0xb4, 0xd6, 0x64, 0xb5, 0xd6, 0x18, - 0xff, 0x38, 0x43, 0x37, 0xc9, 0x44, 0x8d, 0x8f, 0x2f, 0x58, 0x53, 0xee, 0xb7, 0xf8, 0xa0, 0x7b, - 0x59, 0xb9, 0xdd, 0xe4, 0x19, 0x75, 0x6c, 0x9a, 0xe5, 0x9d, 0x9c, 0x04, 0x5c, 0xc5, 0x78, 0x94, - 0x11, 0x76, 0x80, 0x20, 0x25, 0x7c, 0x0b, 0x09, 0xdf, 0xa1, 0xf2, 0x03, 0x19, 0xd8, 0x21, 0x84, - 0xef, 0x7d, 0xfb, 0x52, 0xd6, 0x1a, 0x08, 0x11, 0x44, 0xfa, 0x07, 0xd4, 0x59, 0xd8, 0xe8, 0xdb, - 0xf8, 0x87, 0xf2, 0x2c, 0xfe, 0xf4, 0xf8, 0x3e, 0x80, 0x62, 0x54, 0x6a, 0x72, 0x87, 0x55, 0x98, - 0x51, 0xba, 0xd8, 0xc7, 0xd1, 0x18, 0x92, 0x68, 0x31, 0x2d, 0x2e, 0xf4, 0xf1, 0xb4, 0xb5, 0x56, - 0xbf, 0x07, 0xec, 0xc4, 0xf1, 0xa7, 0x91, 0x69, 0xb1, 0xd5, 0x31, 0x45, 0xc3, 0x36, 0x8e, 0x60, - 0x49, 0x71, 0x09, 0x4d, 0x23, 0x48, 0x4e, 0x5e, 0xe6, 0x25, 0x4c, 0x3e, 0x3b, 0xc3, 0xe4, 0x8d, - 0xdf, 0x2c, 0xc0, 0xbc, 0xba, 0x39, 0x30, 0xed, 0xb6, 0xbb, 0x52, 0xf2, 0xb6, 0xbb, 0x46, 0xe2, - 0x66, 0x24, 0x9c, 0x7a, 0xb9, 0xdf, 0xdf, 0x9b, 0xde, 0xb2, 0x35, 0x5f, 0x45, 0x62, 0xdb, 0x96, - 0xbe, 0x8a, 0x42, 0xd2, 0x57, 0x91, 0x76, 0x03, 0x20, 0x89, 0x9e, 0x33, 0x37, 0x00, 0xde, 0x02, - 0x92, 0x23, 0xb4, 0xe0, 0xb6, 0x22, 0x02, 0xc4, 0x9e, 0x93, 0x14, 0x3b, 0x8a, 0xd3, 0x62, 0xc7, - 0x2b, 0x8b, 0x04, 0xdf, 0x84, 0x39, 0xba, 0x3d, 0x43, 0x9e, 0xed, 0x55, 0x1b, 0x87, 0x1c, 0x2b, - 0xf5, 0x9f, 0x4e, 0x3c, 0x98, 0x12, 0x57, 0xbf, 0x4e, 0xab, 0x9c, 0xb8, 0x4e, 0x4b, 0xf7, 0xa1, - 0x54, 0x92, 0x3e, 0x94, 0xfb, 0x50, 0x8f, 0x06, 0x0e, 0x2d, 0x92, 0x6e, 0x20, 0x4f, 0x0e, 0xd6, - 0x14, 0x5c, 0x70, 0xc3, 0x4e, 0x10, 0x6f, 0x7c, 0xb5, 0xc4, 0xc6, 0x27, 0x78, 0x55, 0x33, 0x0c, - 0xf9, 0x68, 0x1c, 0xaa, 0x8d, 0x4f, 0xbb, 0x74, 0x91, 0x66, 0x7e, 0x01, 0x67, 0x5e, 0x4d, 0x2f, - 0x51, 0xc7, 0x26, 0xd4, 0x4e, 0x6c, 0x67, 0x38, 0xf1, 0xb9, 0xe5, 0x73, 0x3b, 0xf0, 0x5c, 0x5c, - 0xfc, 0xf1, 0x1e, 0x2c, 0xbb, 0xb8, 0x43, 0x38, 0x26, 0xa2, 0x98, 0xd5, 0x13, 0xfd, 0x13, 0x0f, - 0x31, 0xe9, 0x23, 0x21, 0xb6, 0x2c, 0x79, 0x44, 0x98, 0x62, 0x55, 0xda, 0x1d, 0x6b, 0x67, 0xaf, - 0xfd, 0x74, 0xb7, 0x57, 0xcf, 0x88, 0xcf, 0xee, 0xd1, 0xd6, 0x56, 0xab, 0xb5, 0x8d, 0x5b, 0x18, - 0xc0, 0xdc, 0x4e, 0xb3, 0xbd, 0x27, 0x37, 0xb0, 0x7c, 0xbd, 0x60, 0xfc, 0x4e, 0x16, 0xca, 0x5a, - 0x6f, 0xd8, 0x93, 0x68, 0x12, 0xe8, 0x82, 0xa7, 0xdb, 0xb3, 0x3d, 0xde, 0x50, 0x1c, 0x5e, 0x9b, - 0x85, 0xe8, 0x7a, 0xc5, 0xec, 0xb5, 0xd7, 0x2b, 0xb2, 0xb7, 0x61, 0xc1, 0xa6, 0x12, 0xa2, 0x41, - 0x97, 0xc6, 0x7d, 0x09, 0x96, 0x63, 0x8e, 0x11, 0xa4, 0xf1, 0x36, 0x25, 0xf0, 0xf2, 0x2a, 0x68, - 0x33, 0xda, 0xa9, 0x70, 0x6e, 0xe6, 0xe5, 0xc8, 0x48, 0x67, 0x7c, 0xb4, 0xe1, 0xcb, 0xf1, 0x52, - 0xc9, 0xc6, 0x07, 0x00, 0x71, 0x9b, 0x93, 0x43, 0x74, 0x23, 0x39, 0x44, 0x19, 0x6d, 0x88, 0xb2, - 0xc6, 0x3f, 0x97, 0xec, 0x49, 0x8e, 0x77, 0x64, 0xce, 0xfb, 0x3a, 0x28, 0x03, 0xa3, 0x85, 0x81, - 0xdc, 0xe3, 0x21, 0x0f, 0xd5, 0x7d, 0x04, 0x8b, 0x32, 0xa5, 0x1d, 0x25, 0xcc, 0xb0, 0xd3, 0xec, - 0x2c, 0x3b, 0x7d, 0x03, 0x2a, 0x82, 0x95, 0x4a, 0x62, 0x09, 0x24, 0x4b, 0x2a, 0x8f, 0xec, 0x4b, - 0x55, 0x77, 0x82, 0x8f, 0xe6, 0xa7, 0xf8, 0xe8, 0xef, 0x66, 0xe8, 0x7a, 0x90, 0xb8, 0xa1, 0x31, - 0x23, 0x8d, 0xca, 0x4c, 0x32, 0x52, 0x89, 0x6a, 0x46, 0xe9, 0xd7, 0x30, 0xc7, 0x6c, 0x3a, 0x73, - 0x4c, 0x67, 0xbb, 0xb9, 0x54, 0xb6, 0x6b, 0xac, 0x43, 0x63, 0x9b, 0x8b, 0xa1, 0x68, 0x0e, 0x87, - 0x53, 0x63, 0x69, 0xdc, 0x82, 0x9b, 0x29, 0x69, 0xd2, 0x32, 0xf3, 0x09, 0xac, 0x34, 0xe9, 0xde, - 0x84, 0x9f, 0xd5, 0x01, 0x49, 0xa3, 0x01, 0xab, 0xd3, 0x45, 0xca, 0xca, 0x76, 0x60, 0x71, 0x9b, - 0x1f, 0x4f, 0x4e, 0xf7, 0xf8, 0x79, 0x5c, 0x11, 0x83, 0x7c, 0x70, 0xe6, 0x5d, 0xc8, 0xc9, 0xc5, - 0xdf, 0x18, 0x7a, 0x29, 0x70, 0xac, 0x60, 0xcc, 0xfb, 0xca, 0x3a, 0x8f, 0x90, 0xee, 0x98, 0xf7, - 0x8d, 0x27, 0xc0, 0xf4, 0x72, 0xe4, 0x4c, 0x08, 0xd5, 0x69, 0x72, 0x6c, 0x05, 0x57, 0x41, 0xc8, - 0x47, 0xea, 0x60, 0x20, 0x04, 0x93, 0xe3, 0x2e, 0x41, 0x8c, 0x7b, 0x50, 0x39, 0xb4, 0xaf, 0x4c, - 0xfe, 0x85, 0x3c, 0x7f, 0xb7, 0x06, 0xf3, 0x63, 0xfb, 0x4a, 0xf0, 0xcc, 0xc8, 0x51, 0x87, 0xc9, - 0xc6, 0x1f, 0xe6, 0x61, 0x8e, 0x30, 0xd9, 0x5d, 0xba, 0xa0, 0xd8, 0x71, 0x91, 0x67, 0xa9, 0xdd, - 0x43, 0x03, 0xcd, 0x6c, 0x30, 0xd9, 0xd9, 0x0d, 0x46, 0x5a, 0x15, 0xd5, 0xc5, 0x4c, 0xca, 0xa5, - 0xe2, 0x4e, 0x46, 0xea, 0x36, 0xa6, 0xe4, 0xe5, 0x01, 0xf9, 0xf8, 0x02, 0x6a, 0x3a, 0x59, 0x9d, - 0x74, 0x7a, 0xc7, 0x0a, 0x1a, 0xb5, 0x4e, 0xed, 0x9b, 0x72, 0x6f, 0xd1, 0x41, 0xa9, 0x5a, 0xe0, - 0xbc, 0x3a, 0x54, 0x9a, 0xd4, 0x02, 0x67, 0xb4, 0xbd, 0xe2, 0xcb, 0xb5, 0x3d, 0x32, 0x37, 0xbe, - 0x40, 0xdb, 0x83, 0x57, 0xd0, 0xf6, 0x5e, 0xc1, 0xe1, 0x7c, 0x13, 0x8a, 0x28, 0x0c, 0x69, 0x5b, - 0x8d, 0x10, 0x82, 0xc4, 0x56, 0xf3, 0xa1, 0xa6, 0x0f, 0x51, 0xb4, 0x8b, 0xc6, 0xeb, 0x4d, 0xfe, - 0xc5, 0xcf, 0xc7, 0x91, 0xf7, 0x39, 0xcc, 0x4b, 0xa8, 0x20, 0x68, 0xd7, 0x1e, 0xa9, 0xbb, 0xed, - 0xf0, 0xb7, 0x18, 0x36, 0xbc, 0x90, 0xeb, 0x8b, 0x89, 0xe3, 0xf3, 0x81, 0xba, 0xb4, 0xc8, 0xc1, - 0x35, 0x2a, 0x20, 0xa2, 0x83, 0x42, 0x37, 0x73, 0xbd, 0x0b, 0x57, 0xf2, 0x9e, 0x79, 0x27, 0x78, - 0x26, 0x3e, 0x0d, 0x06, 0x75, 0xbc, 0xdd, 0x72, 0xec, 0xf9, 0x6a, 0x27, 0x37, 0xfe, 0x28, 0x03, - 0x75, 0xb9, 0xba, 0xa2, 0x34, 0x5d, 0x35, 0x2a, 0x5c, 0x17, 0x9c, 0xf1, 0xe2, 0x2b, 0x88, 0x0c, - 0xa8, 0xa2, 0x45, 0x28, 0xda, 0xd6, 0xc9, 0xa2, 0x55, 0x16, 0xc0, 0x1d, 0xb9, 0xb5, 0xbf, 0x0e, - 0x65, 0x15, 0x18, 0x3e, 0x72, 0x86, 0xea, 0xae, 0x79, 0x8a, 0x0c, 0xdf, 0x77, 0x86, 0x4a, 0x2a, - 0xf0, 0x6d, 0x79, 0xc8, 0x39, 0x83, 0x52, 0x81, 0x69, 0x87, 0xdc, 0xf8, 0xd7, 0x19, 0x58, 0xd4, - 0xba, 0x22, 0xd7, 0xed, 0x47, 0x50, 0x89, 0xae, 0x95, 0xe5, 0x91, 0x38, 0xba, 0x96, 0x64, 0x34, - 0x71, 0xb6, 0x72, 0x3f, 0x82, 0x04, 0xa2, 0x31, 0x03, 0xfb, 0x8a, 0xa2, 0x97, 0x27, 0x23, 0xa5, - 0xf1, 0x0d, 0xec, 0xab, 0x1d, 0xce, 0xbb, 0x93, 0x91, 0xd0, 0xe7, 0x2f, 0x38, 0x7f, 0x1e, 0x21, - 0x10, 0xfb, 0x04, 0x01, 0x93, 0x18, 0x06, 0x54, 0x47, 0x9e, 0x1b, 0x9e, 0x45, 0x28, 0x52, 0x14, - 0x47, 0x20, 0xe1, 0x18, 0x7f, 0x96, 0x85, 0x25, 0xb2, 0x3b, 0x4a, 0x7b, 0xaf, 0x64, 0x5d, 0x0d, - 0x98, 0x23, 0x13, 0x2c, 0x31, 0xaf, 0xdd, 0x1b, 0xa6, 0xfc, 0x66, 0xdf, 0x7c, 0x45, 0x5b, 0xa9, - 0x3a, 0x47, 0x7d, 0xcd, 0xf0, 0xe7, 0x66, 0x87, 0xff, 0xfa, 0xe1, 0x4d, 0xf3, 0xfe, 0x16, 0xd2, - 0xbc, 0xbf, 0xaf, 0xe2, 0x73, 0x9d, 0x39, 0xf1, 0x3b, 0x2f, 0x71, 0xb4, 0x13, 0xbf, 0x4f, 0x60, - 0x2d, 0x81, 0x83, 0xdc, 0xda, 0x39, 0x71, 0xb8, 0xba, 0x74, 0x66, 0x59, 0xc3, 0xee, 0xaa, 0xb4, - 0xcd, 0x79, 0x28, 0x04, 0x7d, 0x6f, 0xcc, 0x8d, 0x55, 0x58, 0x4e, 0x8e, 0xaa, 0xdc, 0x26, 0x7e, - 0x2f, 0x03, 0x0d, 0x19, 0xab, 0xe3, 0xb8, 0xa7, 0xbb, 0x4e, 0x10, 0x7a, 0x7e, 0x74, 0xfd, 0xea, - 0x6d, 0x80, 0x20, 0xb4, 0x7d, 0xa9, 0x82, 0xcb, 0x6b, 0x56, 0x10, 0x82, 0xea, 0xf5, 0x4d, 0x28, - 0x72, 0x77, 0x40, 0x89, 0x44, 0x0d, 0xf3, 0xdc, 0x1d, 0x28, 0xe5, 0x7c, 0x66, 0x2b, 0xad, 0x26, - 0x85, 0x04, 0x79, 0xeb, 0x81, 0x18, 0x1d, 0x7e, 0x8e, 0x5b, 0x7a, 0x3e, 0xba, 0xf5, 0x60, 0xdf, - 0xbe, 0xc4, 0xc8, 0xd7, 0xc0, 0xf8, 0x7b, 0x59, 0x58, 0x88, 0xdb, 0x47, 0x57, 0xa6, 0xbc, 0xf8, - 0xf2, 0x97, 0xbb, 0x92, 0x1c, 0x1c, 0xa1, 0xd4, 0x68, 0xd6, 0xd8, 0x22, 0x2d, 0xce, 0xb6, 0xcb, - 0x0c, 0x28, 0x2b, 0x0c, 0x6f, 0x12, 0x6a, 0xb7, 0x20, 0x96, 0x08, 0xe5, 0x60, 0x12, 0x0a, 0x2d, - 0x54, 0xa8, 0xe3, 0x8e, 0x2b, 0xf5, 0xc0, 0x82, 0x3d, 0x0a, 0xdb, 0xf8, 0xb8, 0x82, 0x00, 0x8b, - 0x6c, 0x34, 0x91, 0x02, 0x4b, 0xe0, 0xd7, 0x49, 0x29, 0xa1, 0x99, 0x43, 0x85, 0x44, 0x97, 0xd8, - 0xe9, 0x9e, 0xe9, 0x48, 0x62, 0x7f, 0x1d, 0xca, 0x54, 0x78, 0x7c, 0xc0, 0x3b, 0x6f, 0x96, 0xb0, - 0x06, 0x4c, 0x97, 0x96, 0x31, 0x6f, 0x92, 0xb0, 0x07, 0x00, 0x55, 0x85, 0xa1, 0x30, 0x7f, 0x2b, - 0x03, 0x37, 0x53, 0xa6, 0x4d, 0xae, 0xf2, 0x2d, 0x58, 0x3c, 0x89, 0x12, 0xd5, 0xe8, 0xd2, 0x52, - 0x5f, 0x55, 0x6c, 0x35, 0x39, 0xa6, 0x66, 0xfd, 0x24, 0x09, 0x88, 0x35, 0x51, 0x9a, 0xc1, 0xc4, - 0xf5, 0x01, 0x28, 0x12, 0xd1, 0x34, 0x92, 0x12, 0x78, 0x08, 0xeb, 0xad, 0x4b, 0xc1, 0x31, 0xb6, - 0xf4, 0xd7, 0x41, 0x14, 0x19, 0x25, 0xad, 0xee, 0x99, 0x57, 0xb2, 0xba, 0x0f, 0xe8, 0xbc, 0x71, - 0x54, 0xd6, 0x4f, 0x52, 0x08, 0x6e, 0xa0, 0x22, 0x0f, 0xbd, 0x6e, 0xa2, 0xee, 0x11, 0xe8, 0x47, - 0xaf, 0x9a, 0x18, 0x01, 0x2c, 0xec, 0x4f, 0x86, 0xa1, 0x13, 0x3f, 0x74, 0xc2, 0xbe, 0x29, 0xf3, - 0x60, 0x3d, 0x6a, 0xd4, 0x52, 0x2b, 0x82, 0xa8, 0x22, 0x1c, 0xac, 0x91, 0x28, 0xc8, 0x9a, 0xad, - 0x6f, 0x61, 0x94, 0xac, 0xc1, 0xb8, 0x09, 0x6b, 0xf1, 0x17, 0x0d, 0x9b, 0xda, 0x6a, 0xfe, 0x51, - 0x86, 0xc2, 0xec, 0x93, 0x8f, 0xae, 0xb0, 0x16, 0x2c, 0x05, 0x8e, 0x7b, 0x3a, 0xe4, 0x7a, 0xf1, - 0x81, 0x1c, 0x84, 0x95, 0x64, 0xdb, 0xe4, 0xc3, 0x2c, 0xe6, 0x22, 0xe5, 0x88, 0x4b, 0x0b, 0xd8, - 0xe6, 0x75, 0x8d, 0x8c, 0xc9, 0x62, 0x6a, 0x34, 0x66, 0x1b, 0xdf, 0x86, 0x5a, 0xb2, 0x22, 0xf6, - 0xa1, 0x3c, 0xa6, 0x1f, 0xb7, 0x2a, 0x37, 0x75, 0x86, 0x39, 0x26, 0x88, 0x72, 0x3c, 0xf6, 0x81, - 0xf1, 0x77, 0x32, 0xd0, 0x30, 0xb9, 0xa0, 0x5c, 0xad, 0x95, 0x8a, 0x66, 0x3e, 0x9a, 0x29, 0xf5, - 0xfa, 0xbe, 0xaa, 0xd3, 0xff, 0xaa, 0x45, 0xef, 0x5d, 0x3b, 0x19, 0xbb, 0x37, 0x66, 0x7a, 0xb4, - 0x59, 0x84, 0x39, 0x42, 0x31, 0xd6, 0x60, 0x45, 0xb6, 0x47, 0xb5, 0x25, 0x76, 0xa9, 0x26, 0x6a, - 0x4c, 0xb8, 0x54, 0xd7, 0xa1, 0x41, 0xe7, 0x71, 0xf5, 0x4e, 0xc8, 0x8c, 0xdb, 0xc0, 0xf6, 0xed, - 0xbe, 0xed, 0x7b, 0x9e, 0x7b, 0xc8, 0x7d, 0x19, 0xb4, 0x8c, 0x12, 0x26, 0x7a, 0x1c, 0x95, 0x28, - 0x4c, 0x5f, 0xea, 0xee, 0x57, 0xcf, 0x55, 0x31, 0x5a, 0xf4, 0x65, 0x98, 0xb0, 0xb4, 0x69, 0x3f, - 0xe7, 0xaa, 0x24, 0x35, 0x44, 0x1f, 0x43, 0x79, 0x1c, 0x15, 0xaa, 0xc6, 0x5d, 0x5d, 0x23, 0x32, - 0x5b, 0xad, 0xa9, 0x63, 0x1b, 0x8f, 0x61, 0x39, 0x59, 0xa6, 0x64, 0x1d, 0xeb, 0x50, 0x1c, 0x49, - 0x98, 0x6c, 0x5d, 0xf4, 0x6d, 0xfc, 0x76, 0x11, 0xe6, 0xa5, 0x36, 0xca, 0x36, 0x20, 0xdf, 0x57, - 0x71, 0x72, 0xf1, 0xed, 0x54, 0x32, 0x55, 0xfd, 0xdf, 0xc2, 0x68, 0x39, 0x81, 0xc7, 0x3e, 0x86, - 0x5a, 0xd2, 0x55, 0x3c, 0x75, 0xda, 0x3f, 0xe9, 0xe3, 0xad, 0xf6, 0xa7, 0x9c, 0x82, 0xa5, 0x78, - 0x73, 0x24, 0x99, 0xa1, 0x78, 0xa6, 0xed, 0x9e, 0x9e, 0x2b, 0xe4, 0xed, 0xe0, 0xcc, 0xb6, 0x1e, - 0x3f, 0xf9, 0x40, 0x1e, 0xf7, 0x2f, 0x23, 0xb0, 0x7b, 0x66, 0x3f, 0x7e, 0xf2, 0xc1, 0xb4, 0x24, - 0x2d, 0x0f, 0xfb, 0x6b, 0x92, 0xf4, 0x32, 0x14, 0xe8, 0x92, 0x53, 0x0a, 0x78, 0xa2, 0x0f, 0xf6, - 0x08, 0x96, 0x95, 0x81, 0x43, 0x86, 0xa6, 0x13, 0x17, 0x2c, 0xd2, 0x69, 0x40, 0x99, 0xd6, 0xc5, - 0x24, 0x32, 0x89, 0xac, 0xc2, 0xdc, 0x59, 0x7c, 0x63, 0x6d, 0xd5, 0x94, 0x5f, 0xc6, 0x9f, 0x15, - 0xa0, 0xac, 0x0d, 0x0a, 0xab, 0x40, 0xd1, 0x6c, 0x75, 0x5b, 0xe6, 0xa7, 0xad, 0xed, 0xfa, 0x0d, - 0x76, 0x1f, 0xde, 0x6a, 0x77, 0xb6, 0x0e, 0x4c, 0xb3, 0xb5, 0xd5, 0xb3, 0x0e, 0x4c, 0x4b, 0xdd, - 0x91, 0x76, 0xd8, 0xfc, 0x7c, 0xbf, 0xd5, 0xe9, 0x59, 0xdb, 0xad, 0x5e, 0xb3, 0xbd, 0xd7, 0xad, - 0x67, 0xd8, 0x6b, 0xd0, 0x88, 0x31, 0x55, 0x72, 0x73, 0xff, 0xe0, 0xa8, 0xd3, 0xab, 0x67, 0xd9, - 0x1d, 0xb8, 0xb5, 0xd3, 0xee, 0x34, 0xf7, 0xac, 0x18, 0x67, 0x6b, 0xaf, 0xf7, 0xa9, 0xd5, 0xfa, - 0xa5, 0xc3, 0xb6, 0xf9, 0x79, 0x3d, 0x97, 0x86, 0xb0, 0xdb, 0xdb, 0xdb, 0x52, 0x25, 0xe4, 0xd9, - 0x4d, 0x58, 0x21, 0x04, 0xca, 0x62, 0xf5, 0x0e, 0x0e, 0xac, 0xee, 0xc1, 0x41, 0xa7, 0x5e, 0x60, - 0x8b, 0x50, 0x6d, 0x77, 0x3e, 0x6d, 0xee, 0xb5, 0xb7, 0x2d, 0xb3, 0xd5, 0xdc, 0xdb, 0xaf, 0xcf, - 0xb1, 0x25, 0x58, 0x98, 0xc6, 0x9b, 0x17, 0x45, 0x28, 0xbc, 0x83, 0x4e, 0xfb, 0xa0, 0x63, 0x7d, - 0xda, 0x32, 0xbb, 0xed, 0x83, 0x4e, 0xbd, 0xc8, 0x56, 0x81, 0x25, 0x93, 0x76, 0xf7, 0x9b, 0x5b, - 0xf5, 0x12, 0x5b, 0x81, 0xc5, 0x24, 0xfc, 0x59, 0xeb, 0xf3, 0x3a, 0xb0, 0x06, 0x2c, 0x53, 0xc3, - 0xac, 0xcd, 0xd6, 0xde, 0xc1, 0x67, 0xd6, 0x7e, 0xbb, 0xd3, 0xde, 0x3f, 0xda, 0xaf, 0x97, 0xf1, - 0xea, 0xc5, 0x56, 0xcb, 0x6a, 0x77, 0xba, 0x47, 0x3b, 0x3b, 0xed, 0xad, 0x76, 0xab, 0xd3, 0xab, - 0x57, 0xa8, 0xe6, 0xb4, 0x8e, 0x57, 0x45, 0x06, 0x79, 0x7e, 0xc5, 0xda, 0x6e, 0x77, 0x9b, 0x9b, - 0x7b, 0xad, 0xed, 0x7a, 0x8d, 0xdd, 0x86, 0x9b, 0xbd, 0xd6, 0xfe, 0xe1, 0x81, 0xd9, 0x34, 0x3f, - 0x57, 0xe7, 0x5b, 0xac, 0x9d, 0x66, 0x7b, 0xef, 0xc8, 0x6c, 0xd5, 0x17, 0xd8, 0x1b, 0x70, 0xdb, - 0x6c, 0x7d, 0x72, 0xd4, 0x36, 0x5b, 0xdb, 0x56, 0xe7, 0x60, 0xbb, 0x65, 0xed, 0xb4, 0x9a, 0xbd, - 0x23, 0xb3, 0x65, 0xed, 0xb7, 0xbb, 0xdd, 0x76, 0xe7, 0x69, 0xbd, 0xce, 0xde, 0x82, 0xbb, 0x11, - 0x4a, 0x54, 0xc0, 0x14, 0xd6, 0xa2, 0xe8, 0x9f, 0x9a, 0xd2, 0x4e, 0xeb, 0x97, 0x7a, 0xd6, 0x61, - 0xab, 0x65, 0xd6, 0x19, 0x5b, 0x87, 0xd5, 0xb8, 0x7a, 0xaa, 0x40, 0xd6, 0xbd, 0x24, 0xd2, 0x0e, - 0x5b, 0xe6, 0x7e, 0xb3, 0x23, 0x26, 0x38, 0x91, 0xb6, 0x2c, 0x9a, 0x1d, 0xa7, 0x4d, 0x37, 0x7b, - 0x85, 0x31, 0xa8, 0x69, 0xb3, 0xb2, 0xd3, 0x34, 0xeb, 0xab, 0x6c, 0x01, 0xca, 0xfb, 0x87, 0x87, - 0x56, 0xaf, 0xbd, 0xdf, 0x3a, 0x38, 0xea, 0xd5, 0xd7, 0xd8, 0x0a, 0xd4, 0xdb, 0x9d, 0x5e, 0xcb, - 0x14, 0x73, 0xad, 0xb2, 0xfe, 0xcf, 0x79, 0xb6, 0x0c, 0x0b, 0xaa, 0xa5, 0x0a, 0xfa, 0xe3, 0x79, - 0xb6, 0x06, 0xec, 0xa8, 0x63, 0xb6, 0x9a, 0xdb, 0x62, 0xe0, 0xa2, 0x84, 0xff, 0x35, 0x2f, 0xdd, - 0x46, 0x7f, 0x94, 0x8b, 0x36, 0xeb, 0x38, 0x0e, 0x23, 0x79, 0x7f, 0x79, 0x45, 0xbb, 0x77, 0xfc, - 0x65, 0x2f, 0x8b, 0x68, 0xaa, 0x55, 0x6e, 0x46, 0xb5, 0x9a, 0xd1, 0xdd, 0xab, 0xba, 0xec, 0xf7, - 0x26, 0x54, 0x47, 0x74, 0x97, 0xb9, 0xbc, 0xb3, 0x18, 0x64, 0x50, 0x12, 0x01, 0xe9, 0xc2, 0xe2, - 0x99, 0xa7, 0x35, 0x0a, 0xb3, 0x4f, 0x6b, 0xa4, 0xc9, 0xf7, 0x73, 0x69, 0xf2, 0xfd, 0x03, 0x58, - 0x24, 0xd6, 0xe4, 0xb8, 0xce, 0x48, 0x69, 0xcd, 0x24, 0x05, 0x2e, 0x20, 0x8b, 0x22, 0xb8, 0x52, - 0x27, 0x94, 0xca, 0x21, 0x59, 0xc8, 0xbc, 0xd4, 0x36, 0x12, 0x9a, 0x06, 0x71, 0x8e, 0x48, 0xd3, - 0x88, 0x6a, 0xb0, 0x2f, 0xe3, 0x1a, 0xca, 0x5a, 0x0d, 0x04, 0xc7, 0x1a, 0x1e, 0xc0, 0x22, 0xbf, - 0x0c, 0x7d, 0xdb, 0xf2, 0xc6, 0xf6, 0x17, 0x13, 0xf4, 0x6b, 0xdb, 0xa8, 0xc3, 0x57, 0xcc, 0x05, - 0x4c, 0x38, 0x40, 0xf8, 0xb6, 0x1d, 0xda, 0x0f, 0xbe, 0x84, 0xb2, 0x76, 0xcf, 0x3d, 0x5b, 0x83, - 0xa5, 0xcf, 0xda, 0xbd, 0x4e, 0xab, 0xdb, 0xb5, 0x0e, 0x8f, 0x36, 0x9f, 0xb5, 0x3e, 0xb7, 0x76, - 0x9b, 0xdd, 0xdd, 0xfa, 0x0d, 0xb1, 0x68, 0x3b, 0xad, 0x6e, 0xaf, 0xb5, 0x9d, 0x80, 0x67, 0xd8, - 0xeb, 0xb0, 0x7e, 0xd4, 0x39, 0xea, 0xb6, 0xb6, 0xad, 0xb4, 0x7c, 0x59, 0x41, 0xa5, 0x32, 0x3d, - 0x25, 0x7b, 0xee, 0xc1, 0xaf, 0x41, 0x2d, 0x79, 0xd4, 0x9b, 0x01, 0xcc, 0xed, 0xb5, 0x9e, 0x36, - 0xb7, 0x3e, 0xa7, 0xcb, 0x59, 0xbb, 0xbd, 0x66, 0xaf, 0xbd, 0x65, 0xc9, 0xcb, 0x58, 0x05, 0x47, - 0xc8, 0xb0, 0x32, 0xcc, 0x37, 0x3b, 0x5b, 0xbb, 0x07, 0x66, 0xb7, 0x9e, 0x65, 0xaf, 0xc1, 0x9a, - 0xa2, 0xd5, 0xad, 0x83, 0xfd, 0xfd, 0x76, 0x0f, 0x99, 0x61, 0xef, 0xf3, 0x43, 0x41, 0x9a, 0x0f, - 0x6c, 0x28, 0xc5, 0xb7, 0xc9, 0x22, 0x83, 0x69, 0xf7, 0xda, 0xcd, 0x5e, 0xcc, 0x5d, 0xeb, 0x37, - 0x04, 0xff, 0x8a, 0xc1, 0x78, 0x19, 0x6c, 0x3d, 0x43, 0xa7, 0xe1, 0x14, 0x90, 0x6a, 0xaf, 0x67, - 0xc5, 0xa2, 0x8a, 0xa1, 0x9b, 0x07, 0x3d, 0xd1, 0x85, 0x6f, 0x43, 0x2d, 0x19, 0xf3, 0x98, 0x34, - 0x5e, 0xaf, 0xc3, 0xea, 0x66, 0xab, 0xf7, 0x59, 0xab, 0xd5, 0xc1, 0xd1, 0xd9, 0x6a, 0x75, 0x7a, - 0x66, 0x73, 0xaf, 0xdd, 0xfb, 0xbc, 0x9e, 0x79, 0xf0, 0x31, 0xd4, 0xa7, 0x1d, 0x8c, 0x09, 0x8f, - 0xec, 0x8b, 0x5c, 0xb7, 0x0f, 0xfe, 0x4b, 0x06, 0x96, 0xd3, 0x6c, 0xeb, 0x62, 0x0e, 0xe5, 0xe2, - 0x14, 0x2c, 0xba, 0x7b, 0xd0, 0xb1, 0x3a, 0x07, 0x78, 0xfb, 0xe3, 0x3a, 0xac, 0x4e, 0x25, 0x28, - 0x4e, 0x90, 0x61, 0xb7, 0x60, 0x6d, 0x26, 0x93, 0x65, 0x1e, 0x1c, 0x61, 0xb7, 0x1b, 0xb0, 0x3c, - 0x95, 0xd8, 0x32, 0xcd, 0x03, 0xb3, 0x9e, 0x63, 0xef, 0xc1, 0xfd, 0xa9, 0x94, 0xd9, 0x8d, 0x49, - 0xed, 0x5b, 0x79, 0x76, 0x0f, 0xde, 0x9c, 0xc1, 0x8e, 0x79, 0xb7, 0xb5, 0xd9, 0xdc, 0x13, 0xdd, - 0xab, 0x17, 0x1e, 0xfc, 0xb3, 0x1c, 0x40, 0x7c, 0xa8, 0x48, 0xd4, 0xbf, 0xdd, 0xec, 0x35, 0xf7, - 0x0e, 0x04, 0x79, 0x99, 0x07, 0x3d, 0x51, 0xba, 0xd9, 0xfa, 0xa4, 0x7e, 0x23, 0x35, 0xe5, 0xe0, - 0x50, 0x74, 0x68, 0x0d, 0x96, 0x68, 0xaa, 0xf6, 0x44, 0x37, 0xda, 0x9d, 0xa7, 0x74, 0x91, 0x28, - 0xee, 0x7e, 0x47, 0x87, 0x3b, 0xe6, 0x41, 0xa7, 0x67, 0x75, 0x77, 0x8f, 0x7a, 0xdb, 0x78, 0x0d, - 0xe9, 0x96, 0xd9, 0x3e, 0xa4, 0x32, 0xf3, 0x2f, 0x42, 0x10, 0x45, 0x17, 0xc4, 0x5a, 0x78, 0x7a, - 0xd0, 0xed, 0xb6, 0x0f, 0xad, 0x4f, 0x8e, 0x5a, 0x66, 0xbb, 0xd5, 0xc5, 0x8c, 0x73, 0x29, 0x70, - 0x81, 0x3f, 0x2f, 0xf6, 0xcc, 0xde, 0xde, 0xa7, 0x72, 0x53, 0x13, 0xa8, 0xc5, 0x24, 0x48, 0x60, - 0x95, 0xc4, 0xec, 0x88, 0x5d, 0x21, 0xa5, 0x64, 0xb8, 0x26, 0x4d, 0xe4, 0x2b, 0x8b, 0xfd, 0x6e, - 0x66, 0x91, 0x60, 0xb6, 0x4a, 0x7a, 0x92, 0xc8, 0x85, 0x5b, 0x61, 0x24, 0x38, 0x6c, 0x6f, 0x9b, - 0x98, 0xa1, 0x36, 0x03, 0x15, 0xb8, 0x0b, 0x82, 0x08, 0xc5, 0xb6, 0x21, 0x50, 0xea, 0xea, 0x43, - 0xa4, 0x2c, 0x3e, 0xfe, 0xad, 0x1c, 0xd4, 0xe8, 0x80, 0x27, 0x3d, 0xff, 0xc8, 0x7d, 0xb6, 0x0f, - 0xf3, 0xf2, 0x1d, 0x51, 0xb6, 0x12, 0xdd, 0xf1, 0xa8, 0xbf, 0x5c, 0xba, 0xbe, 0x3a, 0x0d, 0x96, - 0x62, 0xf2, 0xd2, 0x5f, 0xfb, 0xd3, 0xff, 0xf1, 0x77, 0xb3, 0x55, 0x56, 0x7e, 0x78, 0xfe, 0xfe, - 0xc3, 0x53, 0xee, 0x06, 0xa2, 0x8c, 0x5f, 0x01, 0x88, 0x5f, 0xc7, 0x64, 0x0d, 0xed, 0x52, 0x89, - 0xc4, 0xbb, 0x98, 0xeb, 0x37, 0x53, 0x52, 0x64, 0xb9, 0x37, 0xb1, 0xdc, 0x25, 0xa3, 0x26, 0xca, - 0x75, 0x5c, 0x27, 0xa4, 0x97, 0x32, 0x3f, 0xca, 0x3c, 0x60, 0x03, 0xa8, 0xe8, 0xef, 0x56, 0x32, - 0x25, 0xc1, 0xa6, 0xbc, 0xbc, 0xb9, 0x7e, 0x2b, 0x35, 0x4d, 0xe9, 0x06, 0x58, 0xc7, 0x8a, 0x51, - 0x17, 0x75, 0x4c, 0x10, 0x23, 0xae, 0x65, 0x48, 0xda, 0x52, 0xfc, 0x3c, 0x25, 0x7b, 0x4d, 0x93, - 0x77, 0x67, 0x1e, 0xc7, 0x5c, 0xbf, 0x7d, 0x4d, 0xaa, 0xac, 0xeb, 0x36, 0xd6, 0xb5, 0x66, 0x30, - 0x51, 0x57, 0x1f, 0x71, 0xd4, 0xe3, 0x98, 0x1f, 0x65, 0x1e, 0x3c, 0xfe, 0x0f, 0xef, 0x40, 0x29, - 0x0a, 0xf8, 0x66, 0xbf, 0x0e, 0xd5, 0xc4, 0x09, 0x5c, 0xa6, 0xba, 0x91, 0x76, 0x60, 0x77, 0xfd, - 0xb5, 0xf4, 0x44, 0x59, 0xf1, 0xeb, 0x58, 0x71, 0x83, 0xad, 0x8a, 0x8a, 0xe5, 0x09, 0xd7, 0x87, - 0x78, 0x62, 0x9e, 0x6e, 0xcc, 0x7c, 0xae, 0x69, 0x85, 0x54, 0xd9, 0x6b, 0xd3, 0x9a, 0x5a, 0xa2, - 0xb6, 0xdb, 0xd7, 0xa4, 0xca, 0xea, 0x5e, 0xc3, 0xea, 0x56, 0xd9, 0xb2, 0x5e, 0x9d, 0x8a, 0x13, - 0x66, 0x1c, 0x6f, 0xa9, 0xd5, 0x5f, 0x6f, 0x64, 0xb7, 0xe3, 0x3b, 0x45, 0x53, 0x5e, 0x75, 0x8c, - 0x48, 0x64, 0xf6, 0x69, 0x47, 0xa3, 0x81, 0x55, 0x31, 0x86, 0xd3, 0xa7, 0x3f, 0xde, 0xc8, 0x8e, - 0xa1, 0xac, 0x3d, 0x78, 0xc4, 0x6e, 0x5e, 0xfb, 0x38, 0xd3, 0xfa, 0x7a, 0x5a, 0x52, 0x5a, 0x57, - 0xf4, 0xf2, 0x1f, 0x9e, 0x70, 0xce, 0x7e, 0x19, 0x4a, 0xd1, 0x33, 0x3a, 0x6c, 0x4d, 0x7b, 0xd6, - 0x48, 0x7f, 0xf6, 0x67, 0xbd, 0x31, 0x9b, 0x90, 0x46, 0x7c, 0x7a, 0xe9, 0x82, 0xf8, 0x3e, 0x83, - 0xb2, 0xf6, 0x54, 0x4e, 0xd4, 0x81, 0xd9, 0xe7, 0x78, 0xa2, 0x0e, 0xa4, 0xbc, 0xac, 0x63, 0x2c, - 0x62, 0x15, 0x65, 0x56, 0x42, 0xfa, 0x0e, 0x2f, 0xbd, 0x80, 0xed, 0xc1, 0x8a, 0xd4, 0x80, 0x8f, - 0xf9, 0x57, 0x99, 0x86, 0x94, 0x07, 0x33, 0x1f, 0x65, 0xd8, 0xc7, 0x50, 0x54, 0x2f, 0x22, 0xb1, - 0xd5, 0xf4, 0x97, 0x9d, 0xd6, 0xd7, 0x66, 0xe0, 0x52, 0x5d, 0xfd, 0x1c, 0x20, 0x7e, 0x97, 0x27, - 0x62, 0x12, 0x33, 0xef, 0xfc, 0x44, 0x14, 0x30, 0xfb, 0x88, 0x8f, 0xb1, 0x8a, 0x1d, 0xac, 0x33, - 0x64, 0x12, 0x2e, 0xbf, 0x50, 0x57, 0x89, 0xff, 0x00, 0xca, 0xda, 0xd3, 0x3c, 0xd1, 0xf0, 0xcd, - 0x3e, 0xeb, 0x13, 0x0d, 0x5f, 0xca, 0x4b, 0x3e, 0xc6, 0x3a, 0x96, 0xbe, 0x6c, 0x2c, 0x88, 0xd2, - 0x85, 0x08, 0x2c, 0x45, 0x51, 0x31, 0x41, 0x67, 0x50, 0x4d, 0xbc, 0xbf, 0x13, 0xad, 0xd0, 0xb4, - 0xd7, 0x7d, 0xa2, 0x15, 0x9a, 0xfa, 0x64, 0x8f, 0xa2, 0x33, 0x63, 0x51, 0xd4, 0x43, 0xb7, 0x89, - 0x69, 0x35, 0x7d, 0x1f, 0xca, 0xda, 0x5b, 0x3a, 0x51, 0x5f, 0x66, 0x9f, 0xed, 0x89, 0xfa, 0x92, - 0xf6, 0xf4, 0xce, 0x32, 0xd6, 0x51, 0x33, 0x90, 0x14, 0xf0, 0x32, 0x64, 0x51, 0xf6, 0xaf, 0x43, - 0x2d, 0xf9, 0xbc, 0x4e, 0xb4, 0xf6, 0x53, 0xdf, 0xe9, 0x89, 0xd6, 0xfe, 0x35, 0x6f, 0xf2, 0x48, - 0x92, 0x7e, 0xb0, 0x14, 0x55, 0xf2, 0xf0, 0x47, 0xf2, 0xe8, 0xda, 0x97, 0xec, 0x13, 0xc1, 0xe0, - 0xe4, 0x5d, 0xdc, 0x6c, 0x4d, 0xa3, 0x5a, 0xfd, 0x52, 0xef, 0x68, 0xbd, 0xcc, 0x5c, 0xdb, 0x9d, - 0x24, 0x66, 0x2c, 0x9c, 0x3d, 0x85, 0xa5, 0x88, 0x98, 0xa3, 0xcb, 0xb5, 0x83, 0xa8, 0x0f, 0xa9, - 0x57, 0x78, 0xaf, 0xd7, 0xa7, 0x53, 0x1f, 0x65, 0x68, 0xfb, 0xc3, 0x2b, 0x8d, 0xb5, 0xed, 0x4f, - 0xbf, 0x5f, 0x5b, 0xdb, 0xfe, 0x12, 0x37, 0x1f, 0x4f, 0x6f, 0x7f, 0xa1, 0x23, 0xca, 0x70, 0x61, - 0x61, 0xfa, 0xaa, 0xeb, 0xdb, 0xd7, 0x5d, 0x0d, 0x42, 0xc5, 0xbf, 0xfe, 0xe2, 0x9b, 0x43, 0x92, - 0xac, 0x48, 0x71, 0xd3, 0x87, 0x32, 0x52, 0x8a, 0xfd, 0x2a, 0x54, 0xf4, 0x27, 0x39, 0x98, 0xce, - 0x13, 0xa6, 0x6b, 0xba, 0x95, 0x9a, 0x96, 0xa4, 0x12, 0x56, 0xd1, 0xab, 0x61, 0x9f, 0xc2, 0x6a, - 0x34, 0xcc, 0xfa, 0xdd, 0x16, 0x01, 0xbb, 0x93, 0x72, 0xe3, 0x45, 0x62, 0xb0, 0x6f, 0x5e, 0x7b, - 0x25, 0xc6, 0xa3, 0x8c, 0xa0, 0xbe, 0xe4, 0xf3, 0x03, 0xf1, 0xce, 0x93, 0xf6, 0xea, 0x42, 0xbc, - 0xf3, 0xa4, 0xbe, 0x59, 0xa0, 0xa8, 0x8f, 0x2d, 0x25, 0xc6, 0x88, 0x62, 0xc8, 0xd9, 0xf7, 0x61, - 0x41, 0xbb, 0xb8, 0xa3, 0x7b, 0xe5, 0xf6, 0xa3, 0x95, 0x34, 0x7b, 0x89, 0xed, 0x7a, 0x9a, 0xcd, - 0xd8, 0x58, 0xc3, 0xf2, 0x17, 0x8d, 0xc4, 0xe0, 0x88, 0x55, 0xb4, 0x05, 0x65, 0xfd, 0x52, 0x90, - 0x17, 0x94, 0xbb, 0xa6, 0x25, 0xe9, 0xf7, 0xa5, 0x3e, 0xca, 0xb0, 0x3d, 0xa8, 0x4f, 0x5f, 0xe1, - 0x17, 0xf1, 0x94, 0xb4, 0x6b, 0x0f, 0xd7, 0xa7, 0x12, 0x13, 0x17, 0xff, 0xb1, 0x43, 0x3a, 0x85, - 0x14, 0xbd, 0x2e, 0xe9, 0xf9, 0xd3, 0xbb, 0x7a, 0xf2, 0xd5, 0xc9, 0xa8, 0xb4, 0xb4, 0xf7, 0x46, - 0xef, 0x67, 0x1e, 0x65, 0xd8, 0xef, 0x64, 0xa0, 0x92, 0xb8, 0xc2, 0x2a, 0x71, 0xce, 0x63, 0xaa, - 0x9f, 0x0d, 0x3d, 0x4d, 0xef, 0xa8, 0x61, 0xe2, 0x20, 0xee, 0x3d, 0xf8, 0x5e, 0x62, 0x92, 0x7e, - 0x94, 0x70, 0xb9, 0x6e, 0x4c, 0x3f, 0x3f, 0xf9, 0xe5, 0x34, 0x82, 0x7e, 0x2d, 0xf2, 0x97, 0x8f, - 0x32, 0xec, 0x5f, 0x66, 0xa0, 0x96, 0x8c, 0xa5, 0x88, 0xba, 0x9b, 0x1a, 0xb5, 0x11, 0x91, 0xd2, - 0x35, 0x01, 0x18, 0xdf, 0xc7, 0x56, 0xf6, 0x1e, 0x98, 0x89, 0x56, 0xca, 0x87, 0x33, 0x7e, 0xba, - 0xd6, 0xb2, 0x5f, 0xa4, 0xd7, 0x9e, 0x55, 0xdc, 0x1d, 0x9b, 0x7d, 0x1d, 0x38, 0x22, 0x3f, 0xfd, - 0x2d, 0x5d, 0x23, 0xf7, 0x1b, 0xd9, 0x0c, 0xce, 0xc4, 0x0f, 0xe8, 0xad, 0x45, 0x15, 0x7a, 0x25, - 0x48, 0xf9, 0x95, 0x0b, 0x79, 0x0b, 0x3b, 0xf6, 0xba, 0x71, 0x33, 0xd1, 0xb1, 0x69, 0xe9, 0xa3, - 0x49, 0x4d, 0x94, 0xef, 0xe1, 0xc6, 0xdb, 0xe7, 0xcc, 0x1b, 0xb9, 0xa9, 0x95, 0x60, 0x23, 0x47, - 0xd4, 0x48, 0x89, 0x9e, 0x58, 0x6f, 0xaf, 0x58, 0x8c, 0xf1, 0x00, 0xdb, 0xfa, 0x96, 0x71, 0xe7, - 0xda, 0xb6, 0x3e, 0xc4, 0xe0, 0x08, 0xd1, 0xe2, 0x43, 0x80, 0x38, 0x38, 0x96, 0x4d, 0x85, 0x68, - 0x46, 0x5c, 0x68, 0x36, 0x7e, 0x36, 0xb9, 0xa8, 0x55, 0x24, 0xa7, 0x28, 0xf1, 0x97, 0x89, 0xa7, - 0x46, 0xc1, 0xa3, 0xba, 0x08, 0x96, 0x8c, 0x63, 0x4d, 0x88, 0x60, 0xd3, 0xe5, 0x27, 0x38, 0x6a, - 0x14, 0x29, 0x7a, 0x04, 0xd5, 0x3d, 0xcf, 0x7b, 0x3e, 0x19, 0x47, 0x07, 0x32, 0x92, 0xb1, 0x50, - 0xbb, 0x76, 0x70, 0xb6, 0x3e, 0xd5, 0x0b, 0xe3, 0x2e, 0x16, 0xb5, 0xce, 0x1a, 0x5a, 0x51, 0x0f, - 0x7f, 0x14, 0x47, 0xe4, 0x7e, 0xc9, 0x6c, 0x58, 0x8c, 0x18, 0x75, 0x1c, 0xf5, 0x9a, 0x2c, 0x26, - 0xc1, 0x9e, 0xa7, 0xab, 0x48, 0xe8, 0x0a, 0xaa, 0xb5, 0x0f, 0x03, 0x55, 0xe6, 0xa3, 0x0c, 0x3b, - 0x84, 0xca, 0x36, 0xef, 0xe3, 0x8d, 0x1e, 0x18, 0xf7, 0xb3, 0x94, 0x88, 0x21, 0xa1, 0x80, 0xa1, - 0xf5, 0x6a, 0x02, 0x98, 0xdc, 0xbc, 0xc6, 0xf6, 0x95, 0xcf, 0xbf, 0x78, 0xf8, 0x23, 0x19, 0x51, - 0xf4, 0xa5, 0xda, 0xbc, 0xe2, 0xe8, 0x32, 0x5d, 0x02, 0x48, 0x86, 0x68, 0x25, 0x36, 0xaf, 0x99, - 0x10, 0xad, 0xc4, 0x50, 0x47, 0xb1, 0x64, 0x43, 0x58, 0x9c, 0x89, 0xea, 0x8a, 0xf6, 0xad, 0xeb, - 0x62, 0xc1, 0xd6, 0xef, 0x5e, 0x8f, 0x90, 0xac, 0xed, 0x41, 0xb2, 0xb6, 0x2e, 0x54, 0xe9, 0xe2, - 0xe3, 0x63, 0x4e, 0x67, 0x7b, 0xa7, 0x2e, 0xc6, 0xd2, 0x0f, 0x0e, 0x4f, 0xef, 0x32, 0x98, 0x96, - 0x14, 0x73, 0xf0, 0x74, 0x27, 0x3b, 0xc1, 0xd7, 0x3e, 0xb4, 0xc3, 0xb4, 0x11, 0x31, 0xce, 0x1e, - 0xf0, 0x8d, 0x88, 0x31, 0xe5, 0xec, 0xad, 0xd2, 0x41, 0xd9, 0x4a, 0x54, 0xf6, 0x43, 0xd7, 0x1b, - 0xf0, 0x91, 0x2c, 0xf5, 0x97, 0xa1, 0xfc, 0x94, 0x87, 0xea, 0xf4, 0x6a, 0x24, 0xd0, 0x4f, 0x1d, - 0x67, 0x5d, 0x4f, 0x39, 0x73, 0x9c, 0xa4, 0x4d, 0x2a, 0x99, 0x0f, 0x4e, 0x39, 0x71, 0x42, 0xcb, - 0x19, 0x7c, 0xc9, 0x7e, 0x09, 0x0b, 0x8f, 0xee, 0x6a, 0x58, 0xd5, 0x9a, 0xa9, 0x17, 0xbe, 0x30, - 0x05, 0x4f, 0x2b, 0x59, 0xb4, 0x59, 0x13, 0x2c, 0x5d, 0x28, 0x6b, 0x77, 0xba, 0x44, 0x63, 0x33, - 0x7b, 0x87, 0x4f, 0x34, 0x36, 0x29, 0x57, 0xc0, 0x18, 0xf7, 0xb1, 0x1e, 0x83, 0xdd, 0x8d, 0xeb, - 0xa1, 0x6b, 0x5f, 0xe2, 0x9a, 0x1e, 0xfe, 0xc8, 0x1e, 0x85, 0x5f, 0xb2, 0xcf, 0x68, 0x3a, 0xb4, - 0xd3, 0xb9, 0xb1, 0x86, 0x32, 0x7d, 0x90, 0x37, 0x1a, 0x2c, 0x2d, 0x29, 0xa9, 0xb5, 0x50, 0x55, - 0x28, 0x36, 0x3e, 0x01, 0xe8, 0x86, 0xde, 0x78, 0xdb, 0xe6, 0x23, 0xcf, 0x8d, 0x79, 0x7a, 0x7c, - 0x5e, 0x34, 0xe6, 0x93, 0xda, 0xa1, 0x51, 0xf6, 0x99, 0xa6, 0xd2, 0x25, 0xce, 0x95, 0x2b, 0x22, - 0xbe, 0xf6, 0x48, 0x69, 0x34, 0x20, 0x29, 0xc7, 0x4a, 0x1f, 0x65, 0x58, 0x13, 0x20, 0x0e, 0x1f, - 0x8c, 0x14, 0xb4, 0x99, 0xc8, 0xc4, 0x88, 0xbd, 0xa6, 0xc4, 0x1a, 0x1e, 0x42, 0x29, 0x8e, 0xbb, - 0x5a, 0x8b, 0xaf, 0xa8, 0x4a, 0x44, 0x69, 0x45, 0xe2, 0xc2, 0x4c, 0xcc, 0x93, 0x51, 0xc7, 0xa1, - 0x02, 0x56, 0x14, 0x43, 0x75, 0xc2, 0x79, 0xc0, 0x1c, 0x58, 0xa2, 0x06, 0x46, 0xb2, 0x19, 0x9e, - 0x73, 0x8c, 0xde, 0xd8, 0x99, 0x0d, 0x3f, 0x8a, 0xb8, 0x46, 0x6a, 0x10, 0x4d, 0xc2, 0xce, 0x24, - 0xa8, 0x95, 0xce, 0x58, 0x8a, 0x2d, 0x60, 0x04, 0x8b, 0x33, 0x71, 0x1a, 0x11, 0xeb, 0xb8, 0x2e, - 0xf0, 0x26, 0x62, 0x1d, 0xd7, 0x86, 0x78, 0x18, 0x2b, 0x58, 0xe5, 0x82, 0x01, 0xa8, 0x57, 0x5e, - 0x38, 0x61, 0xff, 0x4c, 0x54, 0xf7, 0xfb, 0x19, 0x58, 0x4a, 0x89, 0xc4, 0x60, 0x6f, 0x28, 0x13, - 0xc5, 0xb5, 0x51, 0x1a, 0xeb, 0xa9, 0x1e, 0x7b, 0xa3, 0x8b, 0xf5, 0xec, 0xb3, 0x67, 0x89, 0x0d, - 0x94, 0x1c, 0xe6, 0x72, 0x65, 0xbe, 0x50, 0x82, 0x49, 0x15, 0x5f, 0xbe, 0x80, 0x35, 0x6a, 0x48, - 0x73, 0x38, 0x9c, 0x8a, 0x26, 0x78, 0x5d, 0x6b, 0x45, 0x4a, 0x84, 0x44, 0x42, 0x19, 0x48, 0x46, - 0x49, 0x5c, 0x23, 0xbb, 0x53, 0x53, 0xd9, 0x04, 0xea, 0xd3, 0x5e, 0x7a, 0x76, 0x7d, 0x59, 0xeb, - 0x77, 0x12, 0xca, 0x76, 0x8a, 0x67, 0xff, 0x6b, 0x58, 0xd9, 0x1d, 0x63, 0x3d, 0x6d, 0x5c, 0x48, - 0xff, 0x16, 0xf3, 0xf1, 0x57, 0xa3, 0x90, 0x82, 0xa9, 0x7e, 0xde, 0x89, 0x5e, 0x15, 0x48, 0x0f, - 0x80, 0x88, 0xd4, 0xfd, 0xf4, 0x88, 0x84, 0xb7, 0xb1, 0xfa, 0xbb, 0xc6, 0xad, 0xb4, 0xea, 0x7d, - 0xca, 0x42, 0x8a, 0xff, 0xda, 0xf4, 0xba, 0x56, 0x2d, 0xb8, 0x9b, 0x36, 0xdf, 0xd7, 0x2a, 0x5e, - 0x53, 0x63, 0x7d, 0x03, 0x65, 0xc8, 0x8a, 0x1e, 0x42, 0x10, 0x2d, 0x9f, 0x94, 0x58, 0x85, 0x68, - 0xf9, 0xa4, 0xc5, 0x1c, 0x24, 0xe5, 0x27, 0x15, 0x6d, 0xf0, 0x51, 0xe6, 0xc1, 0xe6, 0xbd, 0xef, - 0x7f, 0xed, 0xd4, 0x09, 0xcf, 0x26, 0xc7, 0x1b, 0x7d, 0x6f, 0xf4, 0x70, 0xa8, 0x4c, 0x9b, 0xf2, - 0x32, 0x80, 0x87, 0x43, 0x77, 0xf0, 0x10, 0x8b, 0x3d, 0x9e, 0x1b, 0xfb, 0x5e, 0xe8, 0x7d, 0xe3, - 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xd5, 0x75, 0xf0, 0xe2, 0x5d, 0x8b, 0x00, 0x00, + // 12049 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x59, 0x6c, 0x24, 0x49, + 0x7a, 0x18, 0xdc, 0x75, 0x91, 0x55, 0x5f, 0x1d, 0x2c, 0x06, 0xaf, 0x6a, 0xf6, 0xf4, 0x74, 0x4f, + 0xce, 0xec, 0x74, 0x4f, 0xcf, 0x2c, 0xbb, 0xa7, 0x77, 0x7b, 0x66, 0x77, 0xe6, 0xd7, 0x6a, 0x8b, + 0x64, 0xb1, 0x59, 0xdb, 0x64, 0x91, 0x93, 0x55, 0x9c, 0xd1, 0xac, 0x8e, 0xdc, 0x64, 0x55, 0x90, + 0x4c, 0x75, 0x55, 0x66, 0x4d, 0x66, 0x16, 0x8f, 0x5d, 0xcc, 0xff, 0x60, 0xf8, 0x10, 0x04, 0xdb, + 0x80, 0x60, 0xcb, 0x80, 0x65, 0x09, 0x3e, 0x04, 0xdb, 0x30, 0x0c, 0x08, 0x02, 0x56, 0x7e, 0x30, + 0xe0, 0x77, 0xbd, 0xf8, 0x80, 0x21, 0xf9, 0xc1, 0x86, 0x20, 0xc0, 0xb0, 0x2d, 0xbf, 0x19, 0x02, + 0xfc, 0x6c, 0xc0, 0x88, 0xef, 0x8b, 0xc8, 0x8c, 0xac, 0x4a, 0x76, 0xf7, 0xec, 0xae, 0xf7, 0x85, + 0xac, 0xfc, 0xe2, 0x8b, 0xfb, 0x8b, 0x2f, 0xbe, 0x2b, 0x22, 0xa0, 0xe4, 0x8f, 0xfb, 0x1b, 0x63, + 0xdf, 0x0b, 0x3d, 0x56, 0x18, 0xba, 0xfe, 0xb8, 0xbf, 0xfe, 0xda, 0xa9, 0xe7, 0x9d, 0x0e, 0xf9, + 0x43, 0x7b, 0xec, 0x3c, 0xb4, 0x5d, 0xd7, 0x0b, 0xed, 0xd0, 0xf1, 0xdc, 0x80, 0x90, 0x8c, 0x1f, + 0x40, 0xed, 0x29, 0x77, 0xbb, 0x9c, 0x0f, 0x4c, 0xfe, 0xc5, 0x84, 0x07, 0x21, 0x7b, 0x17, 0x16, + 0x6d, 0xfe, 0x43, 0xce, 0x07, 0xd6, 0xd8, 0x0e, 0x82, 0xf1, 0x99, 0x6f, 0x07, 0xbc, 0x91, 0xb9, + 0x9b, 0xb9, 0x5f, 0x31, 0xeb, 0x94, 0x70, 0x18, 0xc1, 0xd9, 0x1b, 0x50, 0x09, 0x04, 0x2a, 0x77, + 0x43, 0xdf, 0x1b, 0x5f, 0x35, 0xb2, 0x88, 0x57, 0x16, 0xb0, 0x16, 0x81, 0x8c, 0x21, 0x2c, 0x44, + 0x35, 0x04, 0x63, 0xcf, 0x0d, 0x38, 0x7b, 0x04, 0xcb, 0x7d, 0x67, 0x7c, 0xc6, 0x7d, 0x0b, 0x33, + 0x8f, 0x5c, 0x3e, 0xf2, 0x5c, 0xa7, 0xdf, 0xc8, 0xdc, 0xcd, 0xdd, 0x2f, 0x99, 0x8c, 0xd2, 0x44, + 0x8e, 0x7d, 0x99, 0xc2, 0xee, 0xc1, 0x02, 0x77, 0x09, 0xce, 0x07, 0x98, 0x4b, 0x56, 0x55, 0x8b, + 0xc1, 0x22, 0x83, 0xf1, 0x1b, 0x59, 0x58, 0x6c, 0xbb, 0x4e, 0xf8, 0x99, 0x3d, 0x1c, 0xf2, 0x50, + 0xf5, 0xe9, 0x1e, 0x2c, 0x5c, 0x20, 0x00, 0xfb, 0x74, 0xe1, 0xf9, 0x03, 0xd9, 0xa3, 0x1a, 0x81, + 0x0f, 0x25, 0xf4, 0xda, 0x96, 0x65, 0xaf, 0x6d, 0x59, 0xea, 0x70, 0xe5, 0xae, 0x19, 0xae, 0x7b, + 0xb0, 0xe0, 0xf3, 0xbe, 0x77, 0xce, 0xfd, 0x2b, 0xeb, 0xc2, 0x71, 0x07, 0xde, 0x45, 0x23, 0x7f, + 0x37, 0x73, 0xbf, 0x60, 0xd6, 0x14, 0xf8, 0x33, 0x84, 0xb2, 0x4d, 0x58, 0xe8, 0x9f, 0xd9, 0xae, + 0xcb, 0x87, 0xd6, 0xb1, 0xdd, 0x7f, 0x3e, 0x19, 0x07, 0x8d, 0xc2, 0xdd, 0xcc, 0xfd, 0xf2, 0xe3, + 0x9b, 0x1b, 0x38, 0xab, 0x1b, 0x5b, 0x67, 0xb6, 0xbb, 0x89, 0x29, 0x5d, 0xd7, 0x1e, 0x07, 0x67, + 0x5e, 0x68, 0xd6, 0x64, 0x0e, 0x02, 0x07, 0xc6, 0x32, 0x30, 0x7d, 0x24, 0x68, 0xec, 0x8d, 0x7f, + 0x99, 0x81, 0xa5, 0x23, 0x77, 0xe8, 0xf5, 0x9f, 0xff, 0x84, 0x43, 0x94, 0xd2, 0x87, 0xec, 0xab, + 0xf6, 0x21, 0xf7, 0x55, 0xfb, 0xb0, 0x0a, 0xcb, 0xc9, 0xc6, 0xca, 0x5e, 0x70, 0x58, 0x11, 0xb9, + 0x4f, 0xb9, 0x6a, 0x96, 0xea, 0xc6, 0x3b, 0x50, 0xef, 0x4f, 0x7c, 0x9f, 0xbb, 0x33, 0xfd, 0x58, + 0x90, 0xf0, 0xa8, 0x23, 0x6f, 0x40, 0xc5, 0xe5, 0x17, 0x31, 0x9a, 0xa4, 0x5d, 0x97, 0x5f, 0x28, + 0x14, 0xa3, 0x01, 0xab, 0xd3, 0xd5, 0xc8, 0x06, 0xfc, 0x45, 0x06, 0xf2, 0x47, 0xe1, 0xa5, 0xc7, + 0x9e, 0x40, 0xc5, 0x1e, 0x0c, 0x7c, 0x1e, 0x04, 0x56, 0x78, 0x35, 0xa6, 0x95, 0x52, 0x7b, 0xcc, + 0x64, 0x17, 0x9b, 0x94, 0xd4, 0xbb, 0x1a, 0x73, 0xb3, 0x6c, 0xc7, 0x1f, 0xac, 0x01, 0xf3, 0xf2, + 0x13, 0xeb, 0x2d, 0x99, 0xea, 0x93, 0xdd, 0x06, 0xb0, 0x47, 0xde, 0xc4, 0x0d, 0xad, 0xc0, 0x0e, + 0x71, 0xc4, 0x72, 0x66, 0x89, 0x20, 0x5d, 0x3b, 0x64, 0xb7, 0xa0, 0x34, 0x7e, 0x6e, 0x05, 0x7d, + 0xdf, 0x19, 0x87, 0x48, 0x3c, 0x25, 0xb3, 0x38, 0x7e, 0xde, 0xc5, 0x6f, 0xf6, 0x2e, 0x14, 0xbd, + 0x49, 0x38, 0xf6, 0x1c, 0x37, 0x94, 0xf4, 0xb2, 0x20, 0x1b, 0x72, 0x30, 0x09, 0x0f, 0x05, 0xd8, + 0x8c, 0x10, 0xd8, 0x5b, 0x50, 0xed, 0x7b, 0xee, 0x89, 0xe3, 0x8f, 0x88, 0x23, 0x34, 0xe6, 0xb0, + 0xae, 0x24, 0xd0, 0xf8, 0xc3, 0x2c, 0x94, 0x7b, 0xbe, 0xed, 0x06, 0x76, 0x5f, 0x00, 0xd8, 0x1a, + 0xcc, 0x87, 0x97, 0xd6, 0x99, 0x1d, 0x9c, 0x61, 0x57, 0x4b, 0xe6, 0x5c, 0x78, 0xb9, 0x6b, 0x07, + 0x67, 0x6c, 0x15, 0xe6, 0xa8, 0x95, 0xd8, 0xa1, 0x9c, 0x29, 0xbf, 0xc4, 0x02, 0x71, 0x27, 0x23, + 0x2b, 0x59, 0x55, 0x0e, 0x29, 0xa6, 0xee, 0x4e, 0x46, 0x5b, 0x3a, 0x5c, 0x74, 0xfe, 0x58, 0x4c, + 0x37, 0x55, 0x40, 0xdd, 0x2b, 0x21, 0x04, 0xeb, 0x78, 0x03, 0x2a, 0x32, 0x99, 0x3b, 0xa7, 0x67, + 0xd4, 0xc7, 0x82, 0x59, 0x26, 0x04, 0x04, 0x89, 0x12, 0x42, 0x67, 0xc4, 0xad, 0x20, 0xb4, 0x47, + 0x63, 0xd9, 0xa5, 0x92, 0x80, 0x74, 0x05, 0x00, 0x93, 0xbd, 0xd0, 0x1e, 0x5a, 0x27, 0x9c, 0x07, + 0x8d, 0x79, 0x99, 0x2c, 0x20, 0x3b, 0x9c, 0x07, 0xec, 0x6b, 0x50, 0x1b, 0xf0, 0x20, 0xb4, 0xe4, + 0x64, 0xf0, 0xa0, 0x51, 0xc4, 0x95, 0x5f, 0x15, 0xd0, 0xa6, 0x02, 0xb2, 0xd7, 0x00, 0x7c, 0xfb, + 0xc2, 0x12, 0x03, 0xc1, 0x2f, 0x1b, 0x25, 0x9a, 0x05, 0xdf, 0xbe, 0xe8, 0x5d, 0xee, 0xf2, 0x4b, + 0x41, 0x35, 0x4f, 0x79, 0xa8, 0x0d, 0x5a, 0x20, 0xa9, 0xd3, 0xd8, 0x03, 0xa6, 0x81, 0xb7, 0x79, + 0x68, 0x3b, 0xc3, 0x80, 0x7d, 0x00, 0x95, 0x50, 0x43, 0x46, 0x36, 0x58, 0x8e, 0x48, 0x48, 0xcb, + 0x60, 0x26, 0xf0, 0x8c, 0x33, 0x28, 0xee, 0x70, 0xbe, 0xe7, 0x8c, 0x9c, 0x90, 0xad, 0x42, 0xe1, + 0xc4, 0xb9, 0xe4, 0x44, 0xec, 0xb9, 0xdd, 0x1b, 0x26, 0x7d, 0xb2, 0x3b, 0x00, 0xf8, 0xc3, 0x1a, + 0x45, 0xd4, 0xb4, 0x7b, 0xc3, 0x2c, 0x21, 0x6c, 0x3f, 0xb0, 0x43, 0xb6, 0x0e, 0xf3, 0x63, 0xee, + 0xf7, 0xb9, 0x9a, 0xb7, 0xdd, 0x1b, 0xa6, 0x02, 0x6c, 0xce, 0x43, 0x61, 0x28, 0x4a, 0x37, 0xfe, + 0xb8, 0x00, 0xe5, 0x2e, 0x77, 0xa3, 0x55, 0xc6, 0x20, 0x2f, 0x06, 0x44, 0xae, 0x2c, 0xfc, 0xcd, + 0xde, 0x84, 0x32, 0x0e, 0x5d, 0x10, 0xfa, 0x8e, 0x7b, 0x4a, 0x54, 0xbd, 0x99, 0x6d, 0x64, 0x4c, + 0x10, 0xe0, 0x2e, 0x42, 0x59, 0x1d, 0x72, 0xf6, 0x48, 0x51, 0xb5, 0xf8, 0xc9, 0x6e, 0x42, 0xd1, + 0x1e, 0x85, 0xd4, 0xbc, 0x0a, 0x82, 0xe7, 0xed, 0x51, 0x88, 0x4d, 0x7b, 0x03, 0x2a, 0x63, 0xfb, + 0x6a, 0x24, 0xd6, 0x72, 0x44, 0x0e, 0x15, 0xb3, 0x2c, 0x61, 0x48, 0x10, 0x8f, 0x61, 0x49, 0x47, + 0x51, 0x95, 0x17, 0xa2, 0xca, 0x17, 0x35, 0x6c, 0xd9, 0x86, 0x7b, 0xb0, 0xa0, 0xf2, 0xf8, 0xd4, + 0x1f, 0x24, 0x93, 0x92, 0x59, 0x93, 0x60, 0xd5, 0xcb, 0xfb, 0x50, 0x3f, 0x71, 0x5c, 0x7b, 0x68, + 0xf5, 0x87, 0xe1, 0xb9, 0x35, 0xe0, 0xc3, 0xd0, 0x46, 0x8a, 0x29, 0x98, 0x35, 0x84, 0x6f, 0x0d, + 0xc3, 0xf3, 0x6d, 0x01, 0x65, 0xef, 0x41, 0xe9, 0x84, 0x73, 0x0b, 0x07, 0xab, 0x51, 0x4c, 0x2c, + 0x3c, 0x35, 0x43, 0x66, 0xf1, 0x44, 0xcd, 0xd5, 0x7b, 0x50, 0xf7, 0x26, 0xe1, 0xa9, 0xe7, 0xb8, + 0xa7, 0x96, 0xe0, 0x77, 0x96, 0x33, 0x40, 0x1a, 0xca, 0x6f, 0x66, 0x1f, 0x65, 0xcc, 0x9a, 0x4a, + 0x13, 0x9c, 0xa7, 0x3d, 0x60, 0x6f, 0xc3, 0xc2, 0xd0, 0x0e, 0x42, 0xeb, 0xcc, 0x1b, 0x5b, 0xe3, + 0xc9, 0xf1, 0x73, 0x7e, 0xd5, 0xa8, 0xe2, 0x40, 0x54, 0x05, 0x78, 0xd7, 0x1b, 0x1f, 0x22, 0x50, + 0x50, 0x36, 0xb6, 0x93, 0x1a, 0x01, 0x77, 0x33, 0xf7, 0xab, 0x66, 0x49, 0x40, 0xa8, 0xd2, 0xcf, + 0x61, 0x09, 0xa7, 0xa7, 0x3f, 0x09, 0x42, 0x6f, 0x64, 0x09, 0x5e, 0xed, 0x0f, 0x82, 0x46, 0x19, + 0x69, 0xed, 0x1d, 0xd9, 0x58, 0x6d, 0x8e, 0x37, 0xb6, 0x79, 0x10, 0x6e, 0x21, 0xb2, 0x49, 0xb8, + 0x62, 0x43, 0xbf, 0x32, 0x17, 0x07, 0xd3, 0x70, 0xf6, 0x1e, 0x30, 0x7b, 0x38, 0xf4, 0x2e, 0xac, + 0x80, 0x0f, 0x4f, 0x2c, 0x39, 0x88, 0x8d, 0xda, 0xdd, 0xcc, 0xfd, 0xa2, 0x59, 0xc7, 0x94, 0x2e, + 0x1f, 0x9e, 0x1c, 0x12, 0x9c, 0x7d, 0x00, 0xb8, 0x98, 0xac, 0x13, 0x6e, 0x87, 0x13, 0x9f, 0x07, + 0x8d, 0x85, 0xbb, 0xb9, 0xfb, 0xb5, 0xc7, 0x8b, 0xd1, 0x78, 0x21, 0x78, 0xd3, 0x09, 0xcd, 0x8a, + 0xc0, 0x93, 0xdf, 0xc1, 0xfa, 0x36, 0xac, 0xa6, 0x37, 0x49, 0x10, 0x95, 0x18, 0x15, 0x41, 0x8c, + 0x79, 0x53, 0xfc, 0x64, 0xcb, 0x50, 0x38, 0xb7, 0x87, 0x13, 0x2e, 0x79, 0x3a, 0x7d, 0x7c, 0x94, + 0xfd, 0x56, 0xc6, 0xf8, 0xa3, 0x0c, 0x54, 0xa8, 0x97, 0x52, 0x16, 0x79, 0x13, 0xaa, 0x8a, 0x1a, + 0xb8, 0xef, 0x7b, 0xbe, 0xe4, 0x6a, 0x8a, 0xf2, 0x5a, 0x02, 0x26, 0x76, 0x15, 0x85, 0x34, 0xf6, + 0xb9, 0x33, 0xb2, 0x4f, 0x55, 0xd1, 0x8a, 0x94, 0x0e, 0x25, 0x98, 0xbd, 0x1f, 0x97, 0xe7, 0x7b, + 0x93, 0x90, 0xcb, 0x3d, 0xaf, 0x22, 0xbb, 0x67, 0x0a, 0x58, 0x54, 0x3a, 0x7e, 0xbd, 0x02, 0x9d, + 0x1b, 0xbf, 0x9d, 0x01, 0x26, 0x9a, 0xdd, 0xf3, 0xa8, 0x00, 0x49, 0xa1, 0xd3, 0x39, 0x33, 0xaf, + 0xbc, 0x42, 0xb2, 0x2f, 0x5a, 0x21, 0x06, 0x14, 0xa8, 0xed, 0xf9, 0x94, 0xb6, 0x53, 0xd2, 0xf7, + 0xf2, 0xc5, 0x5c, 0x3d, 0x6f, 0xfc, 0x97, 0x1c, 0x2c, 0x6f, 0xd1, 0x96, 0xdd, 0xec, 0xf7, 0xf9, + 0x38, 0x5a, 0x3b, 0x77, 0xa0, 0xec, 0x7a, 0x03, 0xae, 0x28, 0x96, 0x1a, 0x06, 0x02, 0xa4, 0x91, + 0xeb, 0x99, 0xed, 0xb8, 0xd4, 0x70, 0x1a, 0xcc, 0x12, 0x42, 0xb0, 0xd9, 0x6f, 0xc3, 0xc2, 0x98, + 0xbb, 0x03, 0x7d, 0x89, 0x90, 0x50, 0x55, 0x95, 0x60, 0xb9, 0x3a, 0xee, 0x40, 0xf9, 0x64, 0x42, + 0x78, 0x82, 0xb1, 0xe4, 0x91, 0x06, 0x40, 0x82, 0x9a, 0xc4, 0x5f, 0xc6, 0x93, 0xe0, 0x0c, 0x53, + 0x0b, 0x98, 0x3a, 0x2f, 0xbe, 0x45, 0xd2, 0x6d, 0x80, 0xc1, 0x24, 0x08, 0xe5, 0x8a, 0x99, 0xc3, + 0xc4, 0x92, 0x80, 0xd0, 0x8a, 0xf9, 0x3a, 0x2c, 0x8d, 0xec, 0x4b, 0x0b, 0x69, 0xc7, 0x72, 0x5c, + 0xeb, 0x64, 0x88, 0x7b, 0xce, 0x3c, 0xe2, 0xd5, 0x47, 0xf6, 0xe5, 0xa7, 0x22, 0xa5, 0xed, 0xee, + 0x20, 0x5c, 0xb0, 0x15, 0x25, 0xee, 0xf8, 0x3c, 0xe0, 0xfe, 0x39, 0x47, 0x4e, 0x90, 0x8f, 0x64, + 0x1a, 0x93, 0xa0, 0xa2, 0x45, 0x23, 0xd1, 0xef, 0x70, 0xd8, 0xa7, 0x65, 0x6f, 0xce, 0x8f, 0x1c, + 0x77, 0x37, 0x1c, 0xf6, 0xc5, 0xbe, 0x22, 0xf8, 0xc8, 0x98, 0xfb, 0xd6, 0xf3, 0x0b, 0x5c, 0xc3, + 0x79, 0xe4, 0x1b, 0x87, 0xdc, 0x7f, 0x76, 0x21, 0xb6, 0xfe, 0x7e, 0x80, 0x8c, 0xc8, 0xbe, 0x6a, + 0x94, 0x71, 0x81, 0x17, 0xfb, 0x81, 0x60, 0x41, 0xf6, 0x95, 0x58, 0x84, 0xa2, 0xb5, 0x36, 0xce, + 0x02, 0x1f, 0x60, 0xf1, 0x01, 0x72, 0xd4, 0x2a, 0x36, 0xb6, 0x29, 0x13, 0x44, 0x3d, 0x81, 0xa0, + 0x7a, 0xd5, 0xd8, 0x93, 0xa1, 0x7d, 0x1a, 0x20, 0x4b, 0xa9, 0x9a, 0x15, 0x09, 0xdc, 0x11, 0x30, + 0xe3, 0x33, 0x12, 0xb2, 0xb4, 0xb9, 0x95, 0x6b, 0x46, 0x6c, 0xf5, 0x08, 0xc1, 0x79, 0x2d, 0x9a, + 0xf2, 0x2b, 0x6d, 0xd2, 0xb2, 0x29, 0x93, 0x66, 0xfc, 0x5e, 0x06, 0x2a, 0xb2, 0x64, 0x14, 0x4a, + 0xd8, 0x06, 0x30, 0x35, 0x8b, 0xe1, 0xa5, 0x33, 0xb0, 0x8e, 0xaf, 0x42, 0x1e, 0x10, 0xd1, 0xec, + 0xde, 0x30, 0xeb, 0x32, 0xad, 0x77, 0xe9, 0x0c, 0x36, 0x45, 0x0a, 0x7b, 0x00, 0xf5, 0x04, 0x7e, + 0x10, 0xfa, 0x44, 0xd1, 0xbb, 0x37, 0xcc, 0x9a, 0x86, 0xdd, 0x0d, 0x7d, 0xb1, 0x46, 0x84, 0xc8, + 0x33, 0x09, 0x2d, 0xc7, 0x1d, 0xf0, 0x4b, 0x24, 0xa3, 0xaa, 0x59, 0x26, 0x58, 0x5b, 0x80, 0x36, + 0x6b, 0x50, 0xd1, 0x8b, 0x33, 0x4e, 0xa1, 0xa8, 0xe4, 0x25, 0x14, 0x18, 0xa6, 0x9a, 0x64, 0x96, + 0xc2, 0xa8, 0x25, 0x37, 0xa1, 0x98, 0x6c, 0x81, 0x39, 0x1f, 0xbe, 0x72, 0xc5, 0xc6, 0x77, 0xa0, + 0xbe, 0x27, 0x88, 0xc7, 0x15, 0xc4, 0x2a, 0xe5, 0xbf, 0x55, 0x98, 0xd3, 0x16, 0x4d, 0xc9, 0x94, + 0x5f, 0x62, 0xcf, 0x3d, 0xf3, 0x82, 0x50, 0xd6, 0x82, 0xbf, 0x8d, 0x3f, 0xce, 0x00, 0x6b, 0x05, + 0xa1, 0x33, 0xb2, 0x43, 0xbe, 0xc3, 0x23, 0xb6, 0x70, 0x00, 0x15, 0x51, 0x5a, 0xcf, 0x6b, 0x92, + 0x40, 0x46, 0x02, 0xc5, 0xbb, 0x72, 0x19, 0xcf, 0x66, 0xd8, 0xd0, 0xb1, 0x89, 0xcd, 0x27, 0x0a, + 0x10, 0xab, 0x2c, 0xb4, 0xfd, 0x53, 0x1e, 0xa2, 0x18, 0x27, 0xe5, 0x7d, 0x20, 0x90, 0x10, 0xe0, + 0xd6, 0x7f, 0x11, 0x16, 0x67, 0xca, 0xd0, 0xf9, 0x72, 0x29, 0x85, 0x2f, 0xe7, 0x74, 0xbe, 0x6c, + 0xc1, 0x52, 0xa2, 0x5d, 0x92, 0xd2, 0xd6, 0x60, 0x5e, 0x2c, 0x08, 0x21, 0x1c, 0x64, 0x48, 0xaa, + 0x3c, 0xe1, 0x5c, 0x88, 0xc1, 0x0f, 0x61, 0xf9, 0x84, 0x73, 0xdf, 0x0e, 0x31, 0x11, 0x57, 0x8c, + 0x98, 0x21, 0x59, 0xf0, 0xa2, 0x4c, 0xeb, 0xda, 0xe1, 0x21, 0xf7, 0xc5, 0x4c, 0x19, 0xff, 0x2d, + 0x03, 0x0b, 0x82, 0x83, 0xee, 0xdb, 0xee, 0x95, 0x1a, 0xa7, 0xbd, 0xd4, 0x71, 0xba, 0xaf, 0x6d, + 0x86, 0x1a, 0xf6, 0x57, 0x1d, 0xa4, 0xdc, 0xf4, 0x20, 0xb1, 0xbb, 0x50, 0x49, 0xb4, 0xb5, 0x80, + 0x6d, 0x85, 0x20, 0x6a, 0xe4, 0x4f, 0x3f, 0x8c, 0x6f, 0x43, 0x3d, 0x6e, 0xb6, 0x1c, 0x43, 0x06, + 0x79, 0x41, 0x92, 0xb2, 0x00, 0xfc, 0x6d, 0xfc, 0x6e, 0x86, 0x10, 0xb7, 0x3c, 0x27, 0x92, 0x4e, + 0x05, 0xa2, 0x90, 0x7b, 0x15, 0xa2, 0xf8, 0x7d, 0xad, 0x54, 0xff, 0xd3, 0x77, 0x56, 0x2c, 0x9d, + 0x80, 0xbb, 0x03, 0xcb, 0x1e, 0x0e, 0x91, 0xf9, 0x16, 0xcd, 0x79, 0xf1, 0xdd, 0x1c, 0x0e, 0x8d, + 0x7b, 0xb0, 0xa8, 0xb5, 0xee, 0x05, 0xfd, 0xe8, 0x00, 0xdb, 0x73, 0x82, 0xf0, 0xc8, 0x0d, 0xc6, + 0x9a, 0xe0, 0x76, 0x0b, 0x4a, 0x82, 0xc3, 0x8a, 0x96, 0xd1, 0x92, 0x2d, 0x98, 0x82, 0xe5, 0x8a, + 0x76, 0x05, 0x98, 0x68, 0x5f, 0xca, 0xc4, 0xac, 0x4c, 0xb4, 0x2f, 0x31, 0xd1, 0xf8, 0x16, 0x2c, + 0x25, 0xca, 0x93, 0x55, 0xbf, 0x01, 0x85, 0x49, 0x78, 0xe9, 0x29, 0xd1, 0xbc, 0x2c, 0x29, 0x44, + 0x28, 0x80, 0x26, 0xa5, 0x18, 0x1f, 0xc3, 0x62, 0x87, 0x5f, 0xc8, 0x45, 0xac, 0x1a, 0xf2, 0x36, + 0xe4, 0x5f, 0xa2, 0x14, 0x62, 0xba, 0xb1, 0x01, 0x4c, 0xcf, 0x2c, 0x6b, 0xd5, 0x74, 0xc4, 0x4c, + 0x42, 0x47, 0x34, 0xde, 0x06, 0xd6, 0x75, 0x4e, 0xdd, 0x7d, 0x1e, 0x04, 0xf6, 0x69, 0xb4, 0xec, + 0xeb, 0x90, 0x1b, 0x05, 0xa7, 0x92, 0x47, 0x89, 0x9f, 0xc6, 0x37, 0x60, 0x29, 0x81, 0x27, 0x0b, + 0x7e, 0x0d, 0x4a, 0x81, 0x73, 0xea, 0xa2, 0x60, 0x25, 0x8b, 0x8e, 0x01, 0xc6, 0x0e, 0x2c, 0x7f, + 0xca, 0x7d, 0xe7, 0xe4, 0xea, 0x65, 0xc5, 0x27, 0xcb, 0xc9, 0x4e, 0x97, 0xd3, 0x82, 0x95, 0xa9, + 0x72, 0x64, 0xf5, 0x44, 0xbe, 0x72, 0x26, 0x8b, 0x26, 0x7d, 0x68, 0x7c, 0x2f, 0xab, 0xf3, 0x3d, + 0xe3, 0x08, 0xd8, 0x96, 0xe7, 0xba, 0xbc, 0x1f, 0x1e, 0x72, 0xee, 0xc7, 0x56, 0xaa, 0x98, 0x56, + 0xcb, 0x8f, 0xd7, 0xe4, 0xc8, 0x4e, 0x33, 0x53, 0x49, 0xc4, 0x0c, 0xf2, 0x63, 0xee, 0x8f, 0xb0, + 0xe0, 0xa2, 0x89, 0xbf, 0x8d, 0x15, 0x58, 0x4a, 0x14, 0x2b, 0xf5, 0xfa, 0x47, 0xb0, 0xb2, 0xed, + 0x04, 0xfd, 0xd9, 0x0a, 0xd7, 0x60, 0x7e, 0x3c, 0x39, 0xb6, 0x92, 0x7c, 0xf9, 0x19, 0xbf, 0x12, + 0xda, 0xde, 0x74, 0x0e, 0x59, 0xd6, 0x5f, 0xcd, 0x40, 0x7e, 0xb7, 0xb7, 0xb7, 0xc5, 0xd6, 0xa1, + 0xe8, 0xb8, 0x7d, 0x6f, 0x24, 0x04, 0x2f, 0xea, 0x73, 0xf4, 0x7d, 0xed, 0x02, 0xbb, 0x05, 0x25, + 0x94, 0xd7, 0x84, 0x6a, 0x2b, 0x45, 0x9f, 0xa2, 0x00, 0xec, 0x79, 0xfd, 0xe7, 0x42, 0xa7, 0xe6, + 0x97, 0x63, 0xc7, 0x47, 0xad, 0x59, 0x29, 0xc3, 0x79, 0xda, 0xeb, 0xe3, 0x04, 0xd2, 0x88, 0x8d, + 0x7f, 0x5d, 0x84, 0x79, 0xb9, 0xdb, 0xd2, 0xce, 0x1d, 0x3a, 0xe7, 0x3c, 0xde, 0xb9, 0xc5, 0x97, + 0x90, 0x07, 0x7c, 0x3e, 0xf2, 0xc2, 0x48, 0x60, 0xa3, 0x39, 0xa8, 0x10, 0x50, 0x8a, 0x6c, 0x9a, + 0xd0, 0x40, 0x26, 0x86, 0x1c, 0x21, 0xf5, 0xf5, 0xad, 0xfc, 0x16, 0xcc, 0xab, 0xbd, 0x3f, 0x1f, + 0xe9, 0x34, 0x73, 0x7d, 0x92, 0xd6, 0xd6, 0xa1, 0xd8, 0xb7, 0xc7, 0x76, 0xdf, 0x09, 0xaf, 0x24, + 0x43, 0x88, 0xbe, 0x45, 0xe9, 0x43, 0xaf, 0x6f, 0x0f, 0xad, 0x63, 0x7b, 0x68, 0xbb, 0x7d, 0x2e, + 0x75, 0xf7, 0x0a, 0x02, 0x37, 0x09, 0x26, 0xf4, 0x73, 0xd9, 0x4e, 0x85, 0x45, 0x2a, 0xbc, 0x6c, + 0xbd, 0x42, 0x13, 0xc2, 0xa5, 0x37, 0x1a, 0x39, 0x42, 0xcb, 0x20, 0x31, 0x2c, 0x67, 0x96, 0x08, + 0xb2, 0xc3, 0xb1, 0xb7, 0x32, 0xf9, 0x82, 0x86, 0xae, 0x44, 0x55, 0x11, 0xf0, 0x33, 0x32, 0x24, + 0xcc, 0xca, 0x62, 0x39, 0x4d, 0x16, 0x7b, 0x17, 0x16, 0x27, 0x6e, 0xc0, 0xc3, 0x70, 0xc8, 0x07, + 0x51, 0x5b, 0xca, 0x88, 0x54, 0x8f, 0x12, 0x54, 0x73, 0x36, 0x60, 0x89, 0x8c, 0x0e, 0x81, 0x1d, + 0x7a, 0xc1, 0x99, 0x13, 0x58, 0x81, 0xd0, 0x90, 0x48, 0xdd, 0x5d, 0xc4, 0xa4, 0xae, 0x4c, 0xe9, + 0x92, 0x8a, 0xb4, 0x36, 0x85, 0xef, 0xf3, 0x3e, 0x77, 0xce, 0xf9, 0x00, 0xe5, 0xb4, 0x9c, 0xb9, + 0x92, 0xc8, 0x63, 0xca, 0x44, 0x14, 0xba, 0x27, 0x23, 0x6b, 0x32, 0x1e, 0xd8, 0x42, 0x58, 0xa9, + 0x91, 0x30, 0xec, 0x4e, 0x46, 0x47, 0x04, 0x61, 0x8f, 0x40, 0x49, 0x62, 0x52, 0x3e, 0x5c, 0x48, + 0xf0, 0x33, 0x41, 0xac, 0x66, 0x45, 0x62, 0x90, 0xa0, 0x98, 0x90, 0x39, 0xeb, 0x53, 0x32, 0x67, + 0x03, 0xe6, 0xc7, 0xbe, 0x73, 0x6e, 0x87, 0xbc, 0xb1, 0x48, 0x0c, 0x5c, 0x7e, 0x0a, 0xce, 0xe0, + 0xb8, 0x4e, 0xe8, 0xd8, 0xa1, 0xe7, 0x37, 0x18, 0xa6, 0xc5, 0x00, 0xf6, 0x00, 0x16, 0x91, 0x46, + 0x82, 0xd0, 0x0e, 0x27, 0x81, 0x94, 0x40, 0x97, 0x90, 0x98, 0x50, 0x86, 0xee, 0x22, 0x1c, 0x85, + 0x50, 0xf6, 0x0d, 0x58, 0x25, 0xb2, 0xc0, 0x1c, 0x52, 0xb2, 0x46, 0x81, 0x60, 0x19, 0x87, 0x62, + 0x09, 0x53, 0x05, 0x7d, 0x4b, 0xf9, 0x5a, 0x48, 0x07, 0x4f, 0x60, 0x4d, 0x92, 0xc9, 0x4c, 0xae, + 0x15, 0xcc, 0xb5, 0x4c, 0xc9, 0x53, 0xd9, 0x36, 0x60, 0x51, 0x34, 0xc9, 0xe9, 0x5b, 0x32, 0xb7, + 0x58, 0x09, 0xab, 0xa2, 0xf5, 0xa8, 0x29, 0x2d, 0x50, 0xa2, 0x89, 0x69, 0xcf, 0xf8, 0x15, 0xfb, + 0x0e, 0x2c, 0x10, 0xc9, 0xa0, 0x7a, 0x85, 0x9c, 0x7e, 0x1d, 0x39, 0xfd, 0x8a, 0xb2, 0x70, 0x46, + 0xa9, 0xc8, 0xec, 0x6b, 0xfd, 0xc4, 0xb7, 0x58, 0x0e, 0x43, 0xe7, 0x84, 0x87, 0xce, 0x88, 0x37, + 0xd6, 0x88, 0xc0, 0xd4, 0xb7, 0x58, 0xa9, 0x93, 0x31, 0xa6, 0x34, 0x88, 0x2f, 0xd0, 0x17, 0xd2, + 0xee, 0xd0, 0x0b, 0xb8, 0x32, 0x51, 0x35, 0x6e, 0xca, 0x45, 0x28, 0x80, 0x4a, 0x86, 0x14, 0x82, + 0x38, 0x29, 0x3d, 0x91, 0x21, 0xf1, 0x16, 0x12, 0x43, 0x95, 0x74, 0x1f, 0x65, 0x4c, 0x14, 0xbb, + 0xf8, 0x99, 0x7d, 0xa1, 0x38, 0xc8, 0x6b, 0x38, 0xbf, 0x20, 0x40, 0x92, 0x77, 0xfc, 0x38, 0x43, + 0x1b, 0xa2, 0xe4, 0x1f, 0x81, 0xa6, 0xde, 0x11, 0xe7, 0xb0, 0x3c, 0x77, 0x78, 0x25, 0x99, 0x09, + 0x10, 0xe8, 0xc0, 0x1d, 0xe2, 0x6a, 0x76, 0x5c, 0x1d, 0x85, 0x78, 0x6f, 0x45, 0x01, 0x11, 0xe9, + 0x0e, 0x94, 0xc7, 0x93, 0xe3, 0xa1, 0xd3, 0x27, 0x94, 0x1c, 0x95, 0x42, 0x20, 0x44, 0x10, 0xfa, + 0x2d, 0x51, 0x14, 0x61, 0xe4, 0x11, 0xa3, 0x2c, 0x61, 0x88, 0x82, 0xbc, 0x9d, 0xfb, 0xc8, 0x4e, + 0x2a, 0x26, 0xfe, 0x36, 0x36, 0x61, 0x39, 0xd9, 0x68, 0xb9, 0xf1, 0x3c, 0x80, 0xa2, 0xe4, 0x55, + 0xca, 0xf0, 0x51, 0xd3, 0x4c, 0xd1, 0x42, 0x45, 0x8b, 0xd2, 0x8d, 0xdf, 0x2f, 0xc0, 0x92, 0x84, + 0x6e, 0x89, 0xa1, 0xed, 0x4e, 0x46, 0x23, 0xdb, 0x4f, 0x61, 0x82, 0x99, 0x17, 0x33, 0xc1, 0xec, + 0x0c, 0x13, 0x4c, 0x6a, 0xbe, 0xc4, 0x43, 0x93, 0x9a, 0xaf, 0x98, 0x4b, 0x52, 0x46, 0x74, 0x3b, + 0x68, 0x55, 0x82, 0x7b, 0x64, 0x6f, 0x9d, 0x61, 0xd9, 0x85, 0x14, 0x96, 0xad, 0x33, 0xdc, 0xb9, + 0x29, 0x86, 0xfb, 0x06, 0x10, 0xd1, 0xa8, 0xd9, 0x9f, 0x27, 0xfd, 0x04, 0x61, 0xd2, 0x98, 0x7a, + 0x0f, 0x16, 0xa6, 0x79, 0x1c, 0x31, 0xd3, 0x5a, 0x0a, 0x87, 0x73, 0x46, 0x1c, 0x77, 0x2b, 0x0d, + 0xb9, 0x24, 0x39, 0x9c, 0x33, 0xe2, 0x7b, 0x98, 0xa2, 0xf0, 0x5b, 0x00, 0x54, 0x37, 0x2e, 0x1a, + 0xc0, 0x45, 0xf3, 0x76, 0x72, 0x2e, 0xf4, 0x51, 0xdf, 0x10, 0x1f, 0x13, 0x9f, 0xe3, 0x2a, 0x2a, + 0x61, 0x4e, 0x5c, 0x40, 0x1f, 0x42, 0xcd, 0x1b, 0x73, 0xd7, 0x8a, 0x79, 0x4d, 0x19, 0x8b, 0xaa, + 0xcb, 0xa2, 0xda, 0x0a, 0x6e, 0x56, 0x05, 0x5e, 0xf4, 0xc9, 0xbe, 0x4d, 0x83, 0xcc, 0xb5, 0x9c, + 0x95, 0x6b, 0x72, 0xd6, 0x10, 0x31, 0xfa, 0x36, 0x7e, 0x33, 0x03, 0x65, 0xad, 0x39, 0x6c, 0x05, + 0x16, 0xb7, 0x0e, 0x0e, 0x0e, 0x5b, 0x66, 0xb3, 0xd7, 0xfe, 0xb4, 0x65, 0x6d, 0xed, 0x1d, 0x74, + 0x5b, 0xf5, 0x1b, 0x02, 0xbc, 0x77, 0xb0, 0xd5, 0xdc, 0xb3, 0x76, 0x0e, 0xcc, 0x2d, 0x05, 0xce, + 0xb0, 0x55, 0x60, 0x66, 0x6b, 0xff, 0xa0, 0xd7, 0x4a, 0xc0, 0xb3, 0xac, 0x0e, 0x95, 0x4d, 0xb3, + 0xd5, 0xdc, 0xda, 0x95, 0x90, 0x1c, 0x5b, 0x86, 0xfa, 0xce, 0x51, 0x67, 0xbb, 0xdd, 0x79, 0x6a, + 0x6d, 0x35, 0x3b, 0x5b, 0xad, 0xbd, 0xd6, 0x76, 0x3d, 0xcf, 0xaa, 0x50, 0x6a, 0x6e, 0x36, 0x3b, + 0xdb, 0x07, 0x9d, 0xd6, 0x76, 0xbd, 0x60, 0xfc, 0x79, 0x06, 0x56, 0x70, 0xa0, 0x06, 0xd3, 0x2b, + 0xf4, 0x2e, 0x94, 0xfb, 0x9e, 0x37, 0x16, 0x6a, 0x50, 0xbc, 0xdd, 0xeb, 0x20, 0xb1, 0xfa, 0x88, + 0xb3, 0x9e, 0x78, 0x7e, 0x9f, 0xcb, 0x05, 0x0a, 0x08, 0xda, 0x11, 0x10, 0x41, 0x20, 0x92, 0xc2, + 0x08, 0x83, 0xd6, 0x67, 0x99, 0x60, 0x84, 0xb2, 0x0a, 0x73, 0xc7, 0x3e, 0xb7, 0xfb, 0x67, 0x72, + 0x69, 0xca, 0x2f, 0xf6, 0x4e, 0xac, 0xa0, 0xf7, 0xc5, 0x84, 0x0f, 0xf9, 0x00, 0xe9, 0xb3, 0x68, + 0x2e, 0x48, 0xf8, 0x96, 0x04, 0x8b, 0xad, 0xc2, 0x3e, 0xb6, 0xdd, 0x81, 0xe7, 0xf2, 0x81, 0xd4, + 0x03, 0x62, 0x80, 0x71, 0x08, 0xab, 0xd3, 0xfd, 0x93, 0x8b, 0xf9, 0x03, 0x6d, 0x31, 0x93, 0x58, + 0xbe, 0x7e, 0x3d, 0x01, 0x69, 0x0b, 0xfb, 0x6f, 0xe5, 0x21, 0x2f, 0xc4, 0xb4, 0x6b, 0x25, 0x3a, + 0x5d, 0xee, 0xce, 0xcd, 0xf8, 0x66, 0xd0, 0x0e, 0x40, 0xfb, 0x37, 0x19, 0x9b, 0x4a, 0x08, 0xc1, + 0x7d, 0x3b, 0x4a, 0xf6, 0x79, 0xff, 0x5c, 0x5a, 0x9b, 0x28, 0xd9, 0xe4, 0xfd, 0x73, 0x54, 0x78, + 0xec, 0x90, 0xf2, 0xd2, 0x62, 0x9c, 0x0f, 0xec, 0x10, 0x73, 0xca, 0x24, 0xcc, 0x37, 0x1f, 0x25, + 0x61, 0xae, 0x06, 0xcc, 0x3b, 0xee, 0xb1, 0x37, 0x71, 0x07, 0xb8, 0xf6, 0x8a, 0xa6, 0xfa, 0x44, + 0x57, 0x10, 0xb2, 0x09, 0xb1, 0x4b, 0xd0, 0x52, 0x2b, 0x0a, 0x40, 0x4f, 0xec, 0x13, 0xef, 0x43, + 0x29, 0xb8, 0x72, 0xfb, 0xfa, 0x02, 0x5b, 0x96, 0xe3, 0x23, 0x7a, 0xbf, 0xd1, 0xbd, 0x72, 0xfb, + 0xb8, 0x9c, 0x8a, 0x81, 0xfc, 0xc5, 0x9e, 0x40, 0x31, 0x32, 0xca, 0x12, 0x7b, 0xbc, 0xa9, 0xe7, + 0x50, 0x96, 0x58, 0xd2, 0x7d, 0x23, 0x54, 0xf6, 0x10, 0xe6, 0xd0, 0x72, 0x1a, 0x34, 0x2a, 0x98, + 0x49, 0x09, 0xe3, 0xa2, 0x19, 0xe8, 0x85, 0xe1, 0x03, 0xb4, 0xa2, 0x9a, 0x12, 0x6d, 0xfd, 0x19, + 0x54, 0x13, 0x65, 0xe9, 0x1a, 0x6e, 0x95, 0x34, 0xdc, 0xb7, 0x74, 0x0d, 0x37, 0x66, 0xd3, 0x32, + 0x9b, 0xae, 0xf1, 0xfe, 0x22, 0x14, 0x55, 0x57, 0xc4, 0x22, 0x3a, 0xea, 0x3c, 0xeb, 0x1c, 0x7c, + 0xd6, 0xb1, 0xba, 0x9f, 0x77, 0xb6, 0xea, 0x37, 0xd8, 0x02, 0x94, 0x9b, 0x5b, 0xb8, 0x2e, 0x11, + 0x90, 0x11, 0x28, 0x87, 0xcd, 0x6e, 0x37, 0x82, 0x64, 0x8d, 0x1d, 0xa8, 0x4f, 0xb7, 0x54, 0xd0, + 0x64, 0xa8, 0x60, 0xd2, 0xae, 0x1c, 0x03, 0x84, 0xfe, 0x42, 0xa6, 0x62, 0x12, 0x92, 0xe9, 0xc3, + 0x78, 0x02, 0x75, 0xb1, 0xe9, 0x88, 0xa1, 0x0a, 0x34, 0xfb, 0xec, 0x50, 0x08, 0x5e, 0xba, 0x6d, + 0xb9, 0x68, 0x96, 0x09, 0x86, 0x55, 0x19, 0x1f, 0xc0, 0xa2, 0x96, 0x2d, 0xd6, 0x37, 0xc5, 0x46, + 0x36, 0xad, 0x6f, 0xa2, 0x76, 0x41, 0x29, 0xc6, 0x1a, 0xac, 0x88, 0xcf, 0xd6, 0x39, 0x77, 0xc3, + 0xee, 0xe4, 0x98, 0x1c, 0x82, 0x8e, 0xe7, 0x0a, 0xad, 0xa3, 0x14, 0xa5, 0x5c, 0x4f, 0xe4, 0x1b, + 0x52, 0x35, 0xcd, 0x22, 0x69, 0xac, 0x6b, 0x35, 0x60, 0xc6, 0x0d, 0xfc, 0x9b, 0x50, 0x51, 0x4b, + 0x11, 0x48, 0x0c, 0xeb, 0x61, 0xab, 0x65, 0x5a, 0x07, 0x9d, 0xbd, 0x76, 0x47, 0x70, 0x3b, 0x31, + 0xac, 0x08, 0xd8, 0xd9, 0x41, 0x48, 0xc6, 0xa8, 0x43, 0xed, 0x29, 0x0f, 0xdb, 0xee, 0x89, 0xa7, + 0x9c, 0x5f, 0x7f, 0x63, 0x0e, 0x16, 0x22, 0x50, 0xac, 0xe2, 0x9e, 0x73, 0x3f, 0x70, 0x3c, 0x17, + 0xa5, 0xd5, 0x92, 0xa9, 0x3e, 0x05, 0x77, 0x92, 0x32, 0x3a, 0x6e, 0x81, 0xcb, 0x98, 0x2a, 0xa5, + 0x7a, 0xdc, 0xff, 0xee, 0xc1, 0x82, 0x33, 0xe0, 0x6e, 0xe8, 0x84, 0x57, 0x56, 0xc2, 0x60, 0x56, + 0x53, 0x60, 0xb9, 0x07, 0x2e, 0x43, 0xc1, 0x1e, 0x3a, 0xb6, 0x72, 0xb4, 0xd2, 0x87, 0x80, 0xf6, + 0xbd, 0xa1, 0xe7, 0xa3, 0xe4, 0x5a, 0x32, 0xe9, 0x83, 0x3d, 0x82, 0x65, 0x21, 0x41, 0xeb, 0x56, + 0x4c, 0x64, 0x30, 0x64, 0xbb, 0x63, 0xee, 0x64, 0x74, 0x18, 0x5b, 0x32, 0x45, 0x8a, 0xd8, 0xf9, + 0x44, 0x0e, 0x29, 0xea, 0x44, 0x19, 0x48, 0x19, 0x5b, 0x74, 0x27, 0xa3, 0x26, 0xa6, 0x44, 0xf8, + 0x8f, 0x61, 0x45, 0xe0, 0x47, 0xc2, 0x51, 0x94, 0x63, 0x01, 0x73, 0x88, 0xc2, 0xda, 0x32, 0x2d, + 0xca, 0x73, 0x0b, 0x4a, 0xd4, 0x2a, 0x41, 0x12, 0x05, 0x12, 0xc2, 0xb1, 0x29, 0xdc, 0x0f, 0x66, + 0x7c, 0xa2, 0x73, 0xb4, 0x8d, 0x4f, 0xf9, 0x44, 0x35, 0xaf, 0x6a, 0x71, 0xda, 0xab, 0xfa, 0x18, + 0x56, 0x8e, 0x05, 0x8d, 0x9e, 0x71, 0x7b, 0xc0, 0x7d, 0x2b, 0xa6, 0x7c, 0x52, 0x36, 0x96, 0x44, + 0xe2, 0x2e, 0xa6, 0x45, 0x0b, 0x45, 0x48, 0x29, 0x82, 0x6f, 0xf0, 0x81, 0x15, 0x7a, 0x16, 0x0a, + 0x2f, 0xc8, 0x81, 0x8a, 0x66, 0x95, 0xc0, 0x3d, 0x6f, 0x4b, 0x00, 0x93, 0x78, 0xa7, 0xbe, 0x3d, + 0x3e, 0x93, 0xea, 0x40, 0x84, 0xf7, 0x54, 0x00, 0xd9, 0x6b, 0x30, 0x2f, 0xd6, 0x84, 0xcb, 0xc9, + 0x75, 0x45, 0x02, 0xb7, 0x02, 0xb1, 0xb7, 0x60, 0x0e, 0xeb, 0x08, 0x1a, 0x75, 0x5c, 0x10, 0x95, + 0x98, 0xd3, 0x3b, 0xae, 0x29, 0xd3, 0x84, 0x28, 0x38, 0xf1, 0x1d, 0x62, 0x43, 0x25, 0x13, 0x7f, + 0xb3, 0xef, 0x6a, 0x3c, 0x6d, 0x09, 0xf3, 0xbe, 0x25, 0xf3, 0x4e, 0x91, 0xe2, 0x75, 0xec, 0xed, + 0x67, 0xca, 0xad, 0xbe, 0x97, 0x2f, 0x96, 0xeb, 0x15, 0xe3, 0x43, 0x28, 0xd0, 0xe8, 0x08, 0x22, + 0xc4, 0xb1, 0xcb, 0x48, 0x22, 0x44, 0x68, 0x03, 0xe6, 0x5d, 0x1e, 0x5e, 0x78, 0xfe, 0x73, 0x65, + 0x52, 0x96, 0x9f, 0xc6, 0x0f, 0xd1, 0x16, 0x12, 0xf9, 0xcb, 0x49, 0xad, 0x13, 0xe4, 0x41, 0xd3, + 0x1b, 0x9c, 0xd9, 0xd2, 0x3c, 0x53, 0x44, 0x40, 0xf7, 0xcc, 0x9e, 0x21, 0x8f, 0xec, 0xac, 0xcb, + 0xfc, 0x2d, 0xa8, 0x29, 0x0f, 0x7d, 0x60, 0x0d, 0xf9, 0x49, 0x28, 0xc9, 0xbd, 0x22, 0xdd, 0xf3, + 0xc1, 0x1e, 0x3f, 0x09, 0x8d, 0x7d, 0x58, 0x94, 0x04, 0x79, 0x30, 0xe6, 0xaa, 0xea, 0x6f, 0xa5, + 0x49, 0xc3, 0xe5, 0xc7, 0x4b, 0xc9, 0x9d, 0x98, 0x22, 0x0f, 0x12, 0x22, 0xb2, 0xf1, 0x09, 0x30, + 0x7d, 0x9f, 0x96, 0xe5, 0x49, 0x99, 0x54, 0x59, 0xe2, 0x95, 0x43, 0x2b, 0x92, 0x7c, 0x9d, 0x81, + 0x18, 0x9d, 0x60, 0xd2, 0xef, 0xab, 0xc8, 0x89, 0xa2, 0xa9, 0x3e, 0x8d, 0x3f, 0xc9, 0xc0, 0x12, + 0x16, 0xa6, 0xa4, 0x79, 0xc9, 0x85, 0x7f, 0xe2, 0x46, 0x8a, 0xf9, 0xd1, 0x85, 0x23, 0xfa, 0xf8, + 0xea, 0xb6, 0xcf, 0xfc, 0x8c, 0xed, 0xf3, 0x1d, 0xa8, 0x0f, 0xf8, 0xd0, 0xc1, 0x20, 0x1a, 0x25, + 0x6b, 0x90, 0xfc, 0xbe, 0xa0, 0xe0, 0x52, 0x97, 0x33, 0xfe, 0x5e, 0x06, 0x16, 0x49, 0x94, 0x41, + 0xad, 0x58, 0x0e, 0xd4, 0xc7, 0x4a, 0x0d, 0x94, 0xac, 0x4a, 0xf6, 0x29, 0xde, 0xe2, 0x11, 0x4a, + 0xc8, 0xbb, 0x37, 0xa4, 0x7a, 0x28, 0xa1, 0xec, 0x23, 0xd4, 0x40, 0x5c, 0x0b, 0x81, 0x29, 0x41, + 0x39, 0xc9, 0x49, 0xd9, 0xbd, 0x81, 0xea, 0x89, 0x8b, 0xa0, 0xcd, 0xa2, 0xd0, 0x4b, 0x05, 0xd8, + 0xd8, 0x81, 0x6a, 0xa2, 0x9a, 0x84, 0x81, 0xb6, 0x42, 0x06, 0xda, 0x19, 0x27, 0x48, 0x76, 0xd6, + 0x09, 0x72, 0x05, 0x4b, 0x26, 0xb7, 0x07, 0x57, 0x3b, 0x9e, 0x7f, 0x18, 0x1c, 0x87, 0x3b, 0x24, + 0x1f, 0x0a, 0xfe, 0x1e, 0x79, 0xf6, 0x12, 0x56, 0x50, 0xe5, 0xe0, 0x51, 0xca, 0xee, 0xd7, 0xa0, + 0x16, 0xbb, 0x00, 0x35, 0x4b, 0x5a, 0x35, 0xf2, 0x02, 0xa2, 0x41, 0x4d, 0x28, 0x8a, 0xc1, 0x71, + 0x28, 0x6d, 0x69, 0xf8, 0xdb, 0xf8, 0x6b, 0x79, 0x60, 0x82, 0x9a, 0xa7, 0x08, 0x66, 0xca, 0x79, + 0x99, 0x9d, 0x71, 0x5e, 0x3e, 0x02, 0xa6, 0x21, 0x28, 0x9f, 0x6a, 0x2e, 0xf2, 0xa9, 0xd6, 0x63, + 0x5c, 0xe9, 0x52, 0x7d, 0x04, 0xcb, 0x52, 0xd8, 0x4e, 0x36, 0x95, 0x48, 0x83, 0x91, 0xd4, 0x9d, + 0x68, 0xaf, 0x72, 0x5c, 0x0a, 0xe5, 0x9d, 0x6c, 0x65, 0xe8, 0xb8, 0x54, 0x6a, 0xbb, 0x46, 0x80, + 0x73, 0x2f, 0x25, 0xc0, 0xf9, 0x19, 0x02, 0xd4, 0x4c, 0x37, 0xc5, 0xa4, 0xe9, 0xc6, 0x80, 0xaa, + 0x72, 0x4f, 0x52, 0x54, 0x06, 0x49, 0x96, 0x65, 0xe9, 0xa3, 0xc4, 0xc8, 0x8c, 0xfb, 0x50, 0x57, + 0xf6, 0x95, 0xc8, 0x38, 0x44, 0x11, 0x07, 0xd2, 0x3c, 0xb7, 0xa5, 0x4c, 0x44, 0x09, 0x53, 0x7c, + 0x79, 0xca, 0x14, 0xff, 0x2e, 0x2c, 0x06, 0x82, 0x7e, 0xad, 0x89, 0x2b, 0xc3, 0x83, 0xf8, 0x00, + 0xf5, 0xb0, 0xa2, 0x59, 0xc7, 0x84, 0xa3, 0x18, 0x3e, 0x6b, 0xf8, 0xa8, 0xa6, 0x18, 0x3e, 0x9e, + 0xc4, 0x9e, 0xbc, 0xe0, 0xcc, 0x19, 0xa1, 0x50, 0x11, 0x87, 0xd2, 0xc8, 0x01, 0xee, 0x9e, 0x39, + 0x23, 0x53, 0xb9, 0x8d, 0xc5, 0x87, 0xf1, 0xbf, 0x33, 0x50, 0x17, 0x74, 0x90, 0x58, 0x62, 0xdf, + 0x06, 0x64, 0x06, 0xaf, 0xb8, 0xc2, 0xca, 0x02, 0x57, 0x2d, 0xb0, 0x0f, 0x01, 0x57, 0x8c, 0x25, + 0x94, 0x4e, 0xb9, 0xbe, 0x1a, 0xc9, 0xf5, 0x15, 0xf3, 0xd0, 0xdd, 0x1b, 0xa4, 0x9c, 0x08, 0x08, + 0xfb, 0x36, 0x94, 0x04, 0x61, 0x22, 0x95, 0xc8, 0x08, 0x2e, 0x25, 0x9a, 0xa5, 0xac, 0x11, 0x91, + 0x75, 0x2c, 0x3f, 0xd3, 0x9c, 0xaf, 0xf9, 0x14, 0xe7, 0xab, 0xb6, 0x80, 0x77, 0x01, 0x9e, 0xf1, + 0xab, 0x3d, 0xaf, 0x8f, 0x2a, 0xf1, 0x6d, 0x00, 0x41, 0xcb, 0x27, 0xf6, 0xc8, 0x91, 0x16, 0x9d, + 0x82, 0x59, 0x7a, 0xce, 0xaf, 0x76, 0x10, 0x20, 0x26, 0x52, 0x24, 0xc7, 0xab, 0xb8, 0x60, 0x16, + 0x9f, 0xf3, 0x2b, 0x5a, 0xc2, 0x16, 0x54, 0x9f, 0xf1, 0xab, 0x6d, 0x4e, 0x52, 0xa8, 0xe7, 0x0b, + 0x22, 0xf2, 0xed, 0x0b, 0x21, 0x76, 0x26, 0x1c, 0xa7, 0x65, 0xdf, 0xbe, 0x78, 0xc6, 0xaf, 0x94, + 0x13, 0x77, 0x5e, 0xa4, 0x0f, 0xbd, 0xbe, 0xdc, 0x37, 0x55, 0x08, 0x48, 0xdc, 0x28, 0x73, 0xee, + 0x39, 0xfe, 0x36, 0xfe, 0x32, 0x03, 0x55, 0xd1, 0x7e, 0x64, 0xcb, 0x62, 0xca, 0x54, 0x24, 0x51, + 0x26, 0x8e, 0x24, 0x7a, 0x2c, 0xb9, 0x1a, 0xf1, 0xf8, 0xec, 0xf5, 0x3c, 0x1e, 0xe7, 0x86, 0x18, + 0xfc, 0xfb, 0x50, 0xa2, 0x65, 0x29, 0xd6, 0x79, 0x2e, 0x31, 0xc1, 0x89, 0x0e, 0x99, 0x45, 0x44, + 0x7b, 0x46, 0x81, 0x0b, 0x9a, 0x75, 0x90, 0x86, 0xb8, 0xe4, 0x47, 0x36, 0xc1, 0x94, 0x69, 0x28, + 0x5c, 0x13, 0xb8, 0xa0, 0x9b, 0xde, 0xe6, 0x66, 0x4c, 0x6f, 0x07, 0x50, 0x14, 0x53, 0x8d, 0x9d, + 0x4d, 0x29, 0x34, 0x93, 0x56, 0xa8, 0x90, 0x04, 0x6c, 0xb1, 0x29, 0x08, 0x46, 0x97, 0x95, 0x92, + 0x80, 0x1d, 0xf0, 0x43, 0x64, 0x76, 0x19, 0x28, 0x6b, 0x2b, 0x00, 0xad, 0x97, 0xd1, 0x78, 0xd1, + 0x72, 0x49, 0x92, 0x78, 0x62, 0xc0, 0x77, 0x6f, 0x98, 0xd5, 0x7e, 0x62, 0x06, 0x36, 0x24, 0xad, + 0x62, 0xce, 0x6c, 0x22, 0xe8, 0x49, 0x35, 0x5c, 0x11, 0xa8, 0xf8, 0xbd, 0x39, 0x07, 0x79, 0x81, + 0x6a, 0x7c, 0x0c, 0x8b, 0x5a, 0x33, 0xc8, 0x0e, 0xf0, 0xaa, 0x3d, 0x34, 0x7e, 0x25, 0xca, 0x2c, + 0xea, 0x20, 0xff, 0x92, 0x0a, 0x02, 0xe1, 0x03, 0xea, 0xb8, 0x0c, 0x36, 0x21, 0x90, 0x40, 0x7b, + 0xe5, 0xc0, 0x84, 0x5f, 0x83, 0x25, 0xad, 0xf4, 0x1d, 0xc7, 0xb5, 0x87, 0xce, 0x0f, 0x71, 0xc3, + 0x0f, 0x9c, 0x53, 0x77, 0xaa, 0x7c, 0x02, 0x7d, 0xa5, 0xf2, 0xff, 0x7e, 0x16, 0x96, 0x65, 0x05, + 0x18, 0xd6, 0xe7, 0x08, 0x29, 0x6e, 0x3f, 0x38, 0x65, 0xdf, 0x86, 0xaa, 0x18, 0x1b, 0xcb, 0xe7, + 0xa7, 0x4e, 0x10, 0x72, 0xe5, 0xd7, 0x4a, 0x61, 0x5c, 0x62, 0x33, 0x17, 0xa8, 0xa6, 0xc4, 0x64, + 0x1f, 0x43, 0x19, 0xb3, 0x92, 0x9d, 0x45, 0x4e, 0x44, 0x63, 0x36, 0x23, 0x0d, 0xf4, 0xee, 0x0d, + 0x13, 0x82, 0x78, 0xd8, 0x3f, 0x86, 0x32, 0xce, 0xe1, 0x39, 0x0e, 0xe4, 0x14, 0xab, 0x9a, 0x19, + 0x68, 0x91, 0x79, 0x1c, 0x0f, 0x7b, 0x13, 0xaa, 0xc4, 0xac, 0xe4, 0x38, 0xc9, 0x70, 0xa1, 0xf5, + 0xd9, 0xec, 0x6a, 0x24, 0x45, 0xe3, 0xc7, 0xda, 0xf7, 0x66, 0x09, 0xe6, 0x43, 0xdf, 0x39, 0x3d, + 0xe5, 0xbe, 0xb1, 0x1a, 0x0d, 0x8d, 0xe0, 0xc2, 0xbc, 0x1b, 0xf2, 0xb1, 0x90, 0xcd, 0x8d, 0x7f, + 0x9b, 0x81, 0xb2, 0xe4, 0xab, 0x3f, 0xb1, 0x33, 0x6d, 0x5d, 0x8b, 0x8b, 0x25, 0x93, 0x4e, 0x1c, + 0x06, 0x7b, 0x0f, 0x16, 0x46, 0x42, 0x4e, 0x17, 0x7a, 0x64, 0xc2, 0x93, 0x56, 0x53, 0x60, 0x29, + 0x26, 0x6f, 0xc0, 0x12, 0x4a, 0xcd, 0x81, 0x15, 0x3a, 0x43, 0x4b, 0x25, 0xca, 0x18, 0xd4, 0x45, + 0x4a, 0xea, 0x39, 0xc3, 0x7d, 0x99, 0x20, 0x84, 0xc7, 0x20, 0xb4, 0x4f, 0xb9, 0x5c, 0xdb, 0xf4, + 0x61, 0x34, 0x60, 0x75, 0x4a, 0x85, 0x54, 0xfa, 0xf1, 0xff, 0x59, 0x84, 0xb5, 0x99, 0x24, 0xa9, + 0x27, 0x47, 0x1e, 0xa4, 0xa1, 0x33, 0x3a, 0xf6, 0x22, 0xfb, 0x6a, 0x46, 0xf3, 0x20, 0xed, 0x89, + 0x14, 0x65, 0x5f, 0xe5, 0xb0, 0xa2, 0x08, 0x12, 0x0d, 0xa4, 0x91, 0x96, 0x99, 0x45, 0x1d, 0xe8, + 0xfd, 0xe4, 0x26, 0x36, 0x5d, 0x9d, 0x82, 0xeb, 0xa2, 0xd1, 0xd2, 0x78, 0x06, 0x16, 0xb0, 0x5f, + 0x87, 0x46, 0x44, 0xf7, 0x52, 0x6c, 0xd7, 0x54, 0x66, 0x51, 0xd3, 0x7b, 0x2f, 0xa9, 0x29, 0x61, + 0xdc, 0x43, 0xd9, 0x69, 0x55, 0x2d, 0x19, 0x2a, 0x30, 0xaa, 0xeb, 0x1c, 0x5e, 0x57, 0x75, 0xa1, + 0x18, 0x3e, 0x5b, 0x63, 0xfe, 0x95, 0xfa, 0x86, 0x86, 0xcb, 0x44, 0xb5, 0xe6, 0x2d, 0x59, 0x70, + 0x94, 0xa4, 0xd7, 0x7b, 0x06, 0xab, 0x17, 0xb6, 0x13, 0xaa, 0x3e, 0x6a, 0x1a, 0x7b, 0x01, 0xeb, + 0x7b, 0xfc, 0x92, 0xfa, 0x3e, 0xa3, 0xcc, 0x09, 0xc5, 0x64, 0xf9, 0x62, 0x16, 0x18, 0xac, 0xff, + 0xe3, 0x1c, 0xd4, 0x92, 0xa5, 0x08, 0xc6, 0x22, 0x37, 0x1b, 0x25, 0x6f, 0x4a, 0x21, 0x58, 0xda, + 0xfe, 0x3b, 0x24, 0x67, 0xce, 0x7a, 0x25, 0xb2, 0x29, 0x5e, 0x09, 0xdd, 0x19, 0x90, 0x7b, 0x99, + 0xf7, 0x35, 0xff, 0x4a, 0xde, 0xd7, 0x42, 0x9a, 0xf7, 0xf5, 0x7a, 0x97, 0xdd, 0xdc, 0x4f, 0xe4, + 0xb2, 0x9b, 0x7f, 0xa1, 0xcb, 0x4e, 0x73, 0x34, 0x16, 0xaf, 0x31, 0xe1, 0x6b, 0xae, 0xc7, 0x14, + 0x97, 0x5d, 0xe9, 0x2b, 0xb8, 0xec, 0xd6, 0xff, 0x32, 0x03, 0x6c, 0x76, 0x75, 0xb0, 0xa7, 0xe4, + 0xf0, 0x71, 0xf9, 0x50, 0x72, 0xee, 0xaf, 0xbf, 0xda, 0x0a, 0x53, 0x04, 0xa1, 0x72, 0xb3, 0x87, + 0xb0, 0xa4, 0x47, 0xca, 0xeb, 0x5a, 0x7b, 0xd5, 0x64, 0x7a, 0x52, 0x6c, 0xdb, 0xd1, 0x5c, 0xdd, + 0xf9, 0x97, 0xba, 0xba, 0x0b, 0x2f, 0x75, 0x75, 0xcf, 0x25, 0x5d, 0xdd, 0xeb, 0xff, 0x31, 0x03, + 0x4b, 0x29, 0x44, 0xfc, 0xb3, 0xeb, 0xb3, 0xa0, 0xbd, 0x04, 0x5b, 0xcb, 0x4a, 0xda, 0xd3, 0x39, + 0xda, 0x9e, 0xb2, 0x07, 0x8a, 0xa9, 0x50, 0x27, 0x49, 0x1e, 0xbc, 0x8c, 0xbb, 0xc4, 0x39, 0x4c, + 0x3d, 0xfb, 0xfa, 0xef, 0x67, 0xa1, 0xac, 0x25, 0x8a, 0x51, 0x24, 0x92, 0xd5, 0x22, 0x8c, 0x48, + 0x32, 0x44, 0x9b, 0xc3, 0x1d, 0x90, 0x5e, 0x0f, 0x4a, 0xa7, 0xc5, 0x25, 0xc5, 0x40, 0x44, 0xd8, + 0x80, 0x25, 0xe5, 0x8c, 0xe3, 0x71, 0x20, 0xa1, 0xdc, 0x6b, 0x16, 0xa5, 0x4b, 0x8e, 0x47, 0x71, + 0x89, 0xec, 0xa1, 0x52, 0x07, 0xe3, 0xb9, 0x43, 0x52, 0x27, 0x97, 0xc2, 0x22, 0x2d, 0x10, 0x35, + 0x89, 0x82, 0xce, 0xdf, 0x87, 0x15, 0xb5, 0x3c, 0x92, 0x39, 0xc8, 0xcb, 0xc0, 0xe4, 0xe2, 0xd0, + 0xb3, 0x7c, 0x17, 0x6e, 0x4f, 0xb5, 0x69, 0x2a, 0x2b, 0x45, 0xbc, 0xde, 0x4c, 0xb4, 0x4e, 0x2f, + 0x61, 0xfd, 0x47, 0x50, 0x4d, 0x30, 0xca, 0x9f, 0xdd, 0x94, 0x4f, 0xdb, 0x79, 0x68, 0x44, 0x75, + 0x3b, 0xcf, 0xfa, 0xff, 0xca, 0x01, 0x9b, 0xe5, 0xd5, 0x3f, 0xcf, 0x26, 0xcc, 0x12, 0x66, 0x2e, + 0x85, 0x30, 0xff, 0x9f, 0xc9, 0x0f, 0xef, 0xc2, 0xa2, 0x3c, 0x51, 0xa5, 0x79, 0x54, 0x69, 0x71, + 0xd6, 0xa3, 0x04, 0xd5, 0x8a, 0x0f, 0xa7, 0x23, 0x3b, 0x8a, 0x89, 0x43, 0x24, 0x9a, 0x00, 0x35, + 0x15, 0xe0, 0x71, 0x04, 0x73, 0xb6, 0xdb, 0x3f, 0xf3, 0x7c, 0xc9, 0x07, 0x7f, 0xe1, 0x2b, 0x6f, + 0x9f, 0x1b, 0x4d, 0xcc, 0x8f, 0x52, 0x9b, 0x29, 0x0b, 0x33, 0xde, 0x87, 0xb2, 0x06, 0x66, 0x25, + 0x28, 0xec, 0xb5, 0xf7, 0x37, 0x0f, 0xea, 0x37, 0x58, 0x15, 0x4a, 0x66, 0x6b, 0xeb, 0xe0, 0xd3, + 0x96, 0xd9, 0xda, 0xae, 0x67, 0x58, 0x11, 0xf2, 0x7b, 0x07, 0xdd, 0x5e, 0x3d, 0x6b, 0xac, 0x43, + 0x43, 0x96, 0x38, 0xeb, 0xd4, 0xf8, 0xed, 0x7c, 0x64, 0x2e, 0xc4, 0x44, 0xa9, 0xa2, 0x7f, 0x03, + 0x2a, 0xba, 0x78, 0x23, 0x29, 0x62, 0xca, 0xa9, 0x2f, 0x94, 0x73, 0x4f, 0xe3, 0xd5, 0x5b, 0x40, + 0x2e, 0xdd, 0x41, 0x94, 0x2d, 0x9b, 0x90, 0x5b, 0x53, 0xdc, 0x87, 0xa8, 0xfc, 0x24, 0xc8, 0xf0, + 0xff, 0x83, 0x5a, 0xd2, 0x80, 0x2f, 0x39, 0x52, 0x9a, 0xc2, 0x29, 0x72, 0x27, 0x2c, 0xfa, 0xec, + 0xbb, 0x50, 0x9f, 0x76, 0x00, 0x48, 0xe1, 0xf9, 0x9a, 0xfc, 0x0b, 0x4e, 0xd2, 0x27, 0xc0, 0x76, + 0x61, 0x39, 0x4d, 0xc0, 0x43, 0xfa, 0xb8, 0xde, 0x48, 0xc1, 0x66, 0x85, 0x38, 0xf6, 0x2d, 0xe9, + 0x08, 0x2a, 0xe0, 0xf4, 0xbf, 0x95, 0xac, 0x5f, 0x1b, 0xec, 0x0d, 0xfa, 0xa7, 0xb9, 0x84, 0xce, + 0x01, 0x62, 0x18, 0xab, 0x43, 0xe5, 0xe0, 0xb0, 0xd5, 0xb1, 0xb6, 0x76, 0x9b, 0x9d, 0x4e, 0x6b, + 0xaf, 0x7e, 0x83, 0x31, 0xa8, 0xa1, 0x33, 0x7b, 0x3b, 0x82, 0x65, 0x04, 0x4c, 0x3a, 0xe4, 0x14, + 0x2c, 0xcb, 0x96, 0xa1, 0xde, 0xee, 0x4c, 0x41, 0x73, 0xac, 0x01, 0xcb, 0x87, 0x2d, 0xf2, 0x7f, + 0x27, 0xca, 0xcd, 0x0b, 0xa5, 0x41, 0x76, 0x57, 0x28, 0x0d, 0x74, 0x32, 0x50, 0xae, 0x03, 0x25, + 0x4b, 0xff, 0x4e, 0x06, 0x56, 0xa6, 0x12, 0xe2, 0xf3, 0x1e, 0x24, 0x49, 0x27, 0x65, 0xe8, 0x0a, + 0x02, 0xd5, 0x6a, 0x7a, 0x17, 0x16, 0x23, 0xc3, 0xd3, 0xd4, 0xae, 0x54, 0x8f, 0x12, 0x14, 0xf2, + 0x43, 0x58, 0xd2, 0xec, 0x57, 0x53, 0xbc, 0x82, 0x69, 0x49, 0x32, 0x83, 0xb1, 0x16, 0xc5, 0xd5, + 0x4f, 0xb5, 0x7a, 0x40, 0xc7, 0x0d, 0xf5, 0x84, 0xd8, 0x4f, 0x96, 0x6c, 0xaf, 0xfa, 0x64, 0x8f, + 0xa6, 0x08, 0x21, 0xd9, 0x5a, 0x7d, 0xc2, 0x55, 0xf5, 0x7f, 0x30, 0x07, 0xec, 0x93, 0x09, 0xf7, + 0xaf, 0xf0, 0x3c, 0x47, 0xf0, 0xb2, 0x00, 0x47, 0x65, 0x69, 0xc9, 0xbe, 0xd2, 0x99, 0xad, 0xb4, + 0x33, 0x53, 0xf9, 0x97, 0x9f, 0x99, 0x2a, 0xbc, 0xec, 0xcc, 0xd4, 0x9b, 0x50, 0x75, 0x4e, 0x5d, + 0x4f, 0xb0, 0x42, 0x21, 0x09, 0x07, 0x8d, 0xb9, 0xbb, 0xb9, 0xfb, 0x15, 0xb3, 0x22, 0x81, 0x42, + 0x0e, 0x0e, 0xd8, 0xc7, 0x31, 0x12, 0x1f, 0x9c, 0xe2, 0xf9, 0x3e, 0x9d, 0x09, 0xb6, 0x06, 0xa7, + 0x5c, 0x1a, 0x96, 0x50, 0xd3, 0x50, 0x99, 0x05, 0x3c, 0x60, 0x6f, 0x41, 0x2d, 0xf0, 0x26, 0x42, + 0xb1, 0x50, 0xc3, 0x40, 0x8e, 0xb2, 0x0a, 0x41, 0x0f, 0x95, 0xdb, 0x74, 0x69, 0x12, 0x70, 0x6b, + 0xe4, 0x04, 0x81, 0x10, 0xcf, 0xfa, 0x9e, 0x1b, 0xfa, 0xde, 0x50, 0xfa, 0xbe, 0x16, 0x27, 0x01, + 0xdf, 0xa7, 0x94, 0x2d, 0x4a, 0x60, 0xdf, 0x8c, 0x9b, 0x34, 0xb6, 0x1d, 0x3f, 0x68, 0x00, 0x36, + 0x49, 0xf5, 0x14, 0xe5, 0x77, 0xdb, 0xf1, 0xa3, 0xb6, 0x88, 0x8f, 0x60, 0xea, 0x2c, 0x57, 0x79, + 0xfa, 0x2c, 0xd7, 0x0f, 0xd2, 0xcf, 0x72, 0x55, 0xb1, 0xe8, 0x47, 0xb2, 0xe8, 0xd9, 0x29, 0xfe, + 0x4a, 0x47, 0xba, 0x66, 0x8f, 0xa8, 0xd5, 0xbe, 0xca, 0x11, 0xb5, 0x85, 0xb4, 0x23, 0x6a, 0xef, + 0x43, 0x19, 0x0f, 0x0f, 0x59, 0x67, 0x8e, 0x90, 0xe1, 0xc8, 0x97, 0x57, 0xd7, 0x4f, 0x17, 0xed, + 0x3a, 0x6e, 0x68, 0x82, 0xaf, 0x7e, 0x06, 0xb3, 0xa7, 0xc5, 0x16, 0x7f, 0x8e, 0xa7, 0xc5, 0xe4, + 0x21, 0xa7, 0x0d, 0x28, 0xaa, 0x79, 0x62, 0x0c, 0xf2, 0x27, 0xbe, 0x37, 0x52, 0x3e, 0x0e, 0xf1, + 0x9b, 0xd5, 0x20, 0x1b, 0x7a, 0x32, 0x73, 0x36, 0xf4, 0x8c, 0x5f, 0x85, 0xb2, 0x46, 0x6a, 0xec, + 0x0d, 0xb2, 0x4b, 0x0a, 0xdd, 0x4c, 0xca, 0x96, 0x34, 0x8a, 0x25, 0x09, 0x6d, 0x0f, 0x04, 0xbf, + 0x19, 0x38, 0x3e, 0xc7, 0x73, 0x9d, 0x96, 0xcf, 0xcf, 0xb9, 0x1f, 0x28, 0x9f, 0x53, 0x3d, 0x4a, + 0x30, 0x09, 0x6e, 0xfc, 0x1a, 0x2c, 0x25, 0xe6, 0x56, 0xb2, 0x88, 0xb7, 0x60, 0x0e, 0xc7, 0x4d, + 0x05, 0x0d, 0x24, 0x4f, 0x6d, 0xc9, 0x34, 0x3c, 0xb0, 0x4f, 0xee, 0x32, 0x6b, 0xec, 0x7b, 0xc7, + 0x58, 0x49, 0xc6, 0x2c, 0x4b, 0xd8, 0xa1, 0xef, 0x1d, 0x1b, 0x7f, 0x96, 0x83, 0xdc, 0xae, 0x37, + 0xd6, 0x83, 0xd8, 0x32, 0x33, 0x41, 0x6c, 0x52, 0xe1, 0xb4, 0x22, 0x85, 0x52, 0xca, 0xec, 0xe8, + 0x28, 0x52, 0x4a, 0xe5, 0x7d, 0xa8, 0x09, 0x3e, 0x11, 0x7a, 0x42, 0x63, 0xbf, 0xb0, 0x7d, 0x12, + 0x88, 0x73, 0xb4, 0xf8, 0xec, 0x51, 0xd8, 0xf3, 0x76, 0x08, 0xce, 0x96, 0x21, 0x17, 0xa9, 0x2f, + 0x98, 0x2c, 0x3e, 0xd9, 0x2a, 0xcc, 0x61, 0x34, 0xf3, 0x95, 0x74, 0x7a, 0xcb, 0x2f, 0xf6, 0x75, + 0x58, 0x4a, 0x96, 0x4b, 0xac, 0x48, 0xca, 0x46, 0x7a, 0xc1, 0xc8, 0x93, 0x6e, 0x82, 0xe0, 0x23, + 0x84, 0x23, 0x83, 0x6b, 0x4e, 0x38, 0xc7, 0x24, 0x8d, 0xe9, 0x15, 0x13, 0x4c, 0xef, 0x0e, 0x94, + 0xc3, 0xe1, 0xb9, 0x35, 0xb6, 0xaf, 0x86, 0x9e, 0x3d, 0x90, 0xeb, 0x1b, 0xc2, 0xe1, 0xf9, 0x21, + 0x41, 0xd8, 0x43, 0x80, 0xd1, 0x78, 0x2c, 0xd7, 0x1e, 0x3a, 0x3f, 0x62, 0x52, 0xde, 0x3f, 0x3c, + 0x24, 0x92, 0x33, 0x4b, 0xa3, 0xf1, 0x98, 0x7e, 0xb2, 0x6d, 0xa8, 0xa5, 0x9e, 0xbd, 0xbc, 0xad, + 0x82, 0x6f, 0xbd, 0xf1, 0x46, 0xca, 0xe2, 0xac, 0xf6, 0x75, 0xd8, 0xfa, 0x77, 0x81, 0xfd, 0x94, + 0x27, 0x20, 0x7b, 0x50, 0x8a, 0xda, 0xa7, 0x1f, 0x20, 0xc4, 0x70, 0xfa, 0x72, 0xe2, 0x00, 0x61, + 0x73, 0x30, 0xf0, 0x05, 0x5f, 0xa4, 0x0d, 0x33, 0x62, 0xf9, 0xa0, 0xed, 0x98, 0x4d, 0xe2, 0xfb, + 0xc6, 0x7f, 0xcd, 0x40, 0x81, 0x4e, 0x33, 0xbe, 0x0d, 0x0b, 0x84, 0x1f, 0x05, 0x04, 0x4a, 0x57, + 0x39, 0xed, 0xbb, 0x3d, 0x19, 0x0b, 0x28, 0x96, 0x85, 0x76, 0x12, 0x3b, 0x1b, 0xcd, 0xbc, 0x76, + 0x1a, 0xfb, 0x0e, 0x94, 0xa2, 0xaa, 0x35, 0xd2, 0x29, 0xaa, 0x9a, 0xd9, 0xeb, 0x90, 0x3f, 0xf3, + 0xc6, 0xca, 0xf2, 0x03, 0xf1, 0x48, 0x9a, 0x08, 0x8f, 0xdb, 0x22, 0xea, 0xa0, 0xc6, 0x4b, 0x8b, + 0x45, 0x54, 0x09, 0x92, 0xc1, 0x6c, 0x1f, 0xe7, 0x52, 0xfa, 0x78, 0x04, 0x0b, 0x82, 0x0f, 0x68, + 0x31, 0x2d, 0xd7, 0x6f, 0x9a, 0xef, 0x08, 0x09, 0xaf, 0x3f, 0x9c, 0x0c, 0xb8, 0x6e, 0x7b, 0xc3, + 0x00, 0x38, 0x09, 0x57, 0x92, 0xb5, 0xf1, 0x07, 0x19, 0xe2, 0x2f, 0xa2, 0x5c, 0x76, 0x1f, 0xf2, + 0x62, 0x7f, 0x9b, 0xb2, 0xc4, 0x47, 0xe7, 0x1a, 0x04, 0x9e, 0x89, 0x18, 0x78, 0x7d, 0xc1, 0x64, + 0x94, 0x2c, 0xbd, 0x6a, 0x96, 0xdd, 0xc9, 0x28, 0x32, 0x5d, 0x7d, 0x4d, 0x75, 0x6b, 0xca, 0xec, + 0x43, 0xbd, 0x8f, 0x96, 0xe9, 0x86, 0x16, 0x49, 0x97, 0x4f, 0xec, 0x98, 0x4a, 0x0a, 0x1c, 0x9c, + 0x72, 0x2d, 0x82, 0xee, 0x8f, 0xb2, 0x50, 0x4d, 0xb4, 0x08, 0x43, 0x09, 0xc5, 0x06, 0x40, 0x8e, + 0x25, 0x39, 0xdf, 0x20, 0x40, 0x52, 0x50, 0xd7, 0xc6, 0x29, 0x9b, 0x18, 0xa7, 0x28, 0x38, 0x27, + 0xa7, 0x07, 0xe7, 0x3c, 0x82, 0x52, 0x7c, 0x02, 0x3f, 0xd9, 0x24, 0x51, 0x9f, 0x3a, 0xdd, 0x11, + 0x23, 0xc5, 0xe1, 0x3c, 0x05, 0x3d, 0x9c, 0xe7, 0x3b, 0x5a, 0xf4, 0xc7, 0x1c, 0x16, 0x63, 0xa4, + 0x8d, 0xe8, 0xcf, 0x25, 0xf6, 0xc3, 0xf8, 0x18, 0xca, 0x5a, 0xe3, 0xf5, 0x28, 0x8f, 0x4c, 0x22, + 0xca, 0x23, 0x3a, 0x87, 0x95, 0x8d, 0xcf, 0x61, 0x19, 0x7f, 0x3d, 0x0b, 0x55, 0xb1, 0xbe, 0x1c, + 0xf7, 0xf4, 0xd0, 0x1b, 0x3a, 0x7d, 0x74, 0x34, 0x45, 0x2b, 0x4c, 0x0a, 0x5a, 0x6a, 0x9d, 0xc9, + 0x25, 0x46, 0x72, 0x96, 0x7e, 0xdc, 0x94, 0x98, 0x74, 0x74, 0xdc, 0xd4, 0x80, 0xaa, 0x60, 0x8c, + 0xe8, 0x32, 0x8a, 0xef, 0x07, 0x30, 0xcb, 0x27, 0x9c, 0x6f, 0xda, 0x01, 0x71, 0xc8, 0xaf, 0xc3, + 0x92, 0xc0, 0xc1, 0x93, 0x76, 0x23, 0x67, 0x38, 0x74, 0x08, 0x93, 0x0c, 0x4d, 0xf5, 0x13, 0xce, + 0x4d, 0x3b, 0xe4, 0xfb, 0x22, 0x41, 0x5e, 0x27, 0x50, 0x1c, 0x38, 0x81, 0x7d, 0x1c, 0x07, 0x7c, + 0x46, 0xdf, 0xe8, 0x59, 0xb6, 0x2f, 0x35, 0xcf, 0x32, 0x19, 0x20, 0xca, 0x23, 0xfb, 0x32, 0xf2, + 0x2c, 0x4f, 0x51, 0xd2, 0xfc, 0x34, 0x25, 0x19, 0xff, 0x26, 0x0b, 0x65, 0x8d, 0x2c, 0x5f, 0x65, + 0x77, 0xbd, 0x3d, 0xe3, 0x18, 0x2c, 0xe9, 0x3e, 0xc0, 0x37, 0x93, 0x55, 0x62, 0xec, 0x0b, 0x5d, + 0x5c, 0xa0, 0x11, 0xf0, 0x2d, 0x28, 0x89, 0x55, 0xf7, 0x3e, 0x9a, 0x60, 0xe5, 0xb5, 0x1b, 0x08, + 0x38, 0x9c, 0x1c, 0xab, 0xc4, 0xc7, 0x98, 0x58, 0x88, 0x13, 0x1f, 0x8b, 0xc4, 0x17, 0x85, 0x60, + 0x7f, 0x08, 0x15, 0x59, 0x2a, 0xce, 0x29, 0x76, 0x37, 0x5e, 0xf5, 0x89, 0xf9, 0x36, 0xcb, 0x54, + 0x1d, 0x4d, 0xbe, 0xcc, 0xf8, 0x58, 0x65, 0x2c, 0xbe, 0x2c, 0xe3, 0x63, 0xfa, 0x30, 0x76, 0xa2, + 0xa8, 0x76, 0x8c, 0xbb, 0x52, 0x7c, 0xec, 0x21, 0x2c, 0x29, 0x76, 0x35, 0x71, 0x6d, 0xd7, 0xf5, + 0x26, 0x6e, 0x9f, 0xab, 0x03, 0x5a, 0x4c, 0x26, 0x1d, 0xc5, 0x29, 0xc6, 0x20, 0x3a, 0xc1, 0x4b, + 0xf1, 0x5b, 0x0f, 0xa0, 0x40, 0x72, 0x39, 0x09, 0x1f, 0xe9, 0x8c, 0x8b, 0x50, 0xd8, 0x7d, 0x28, + 0x90, 0x78, 0x9e, 0xbd, 0x96, 0xd9, 0x10, 0x82, 0xd1, 0x04, 0x26, 0x32, 0xee, 0xf3, 0xd0, 0x77, + 0xfa, 0x41, 0x7c, 0xf6, 0xab, 0x20, 0xf4, 0x4f, 0xaa, 0x2b, 0xb6, 0xdc, 0xc6, 0x98, 0xa8, 0xa3, + 0x12, 0x8e, 0xd8, 0x98, 0x96, 0x12, 0x65, 0x48, 0x71, 0x69, 0x08, 0xab, 0xc7, 0x3c, 0xbc, 0xe0, + 0xdc, 0x75, 0x85, 0x30, 0xd4, 0xe7, 0x6e, 0xe8, 0xdb, 0x43, 0x31, 0x49, 0xd4, 0x83, 0x27, 0x33, + 0xa5, 0xc6, 0x36, 0x90, 0xcd, 0x38, 0xe3, 0x56, 0x94, 0x8f, 0x78, 0xc7, 0xca, 0x71, 0x5a, 0xda, + 0xfa, 0xaf, 0xc0, 0xfa, 0xf5, 0x99, 0x52, 0x4e, 0x78, 0xde, 0x4f, 0x72, 0x95, 0xc8, 0x0f, 0x38, + 0xf4, 0xec, 0x90, 0x5a, 0xa3, 0x73, 0x96, 0x0e, 0x94, 0xb5, 0x94, 0x78, 0xef, 0xcf, 0xa0, 0x70, + 0x47, 0x1f, 0x62, 0x47, 0x72, 0x3d, 0x7f, 0x84, 0x7e, 0xb7, 0x81, 0x15, 0x97, 0x9e, 0x31, 0x17, + 0x62, 0x38, 0x1e, 0x69, 0x37, 0x36, 0x60, 0x01, 0x25, 0x7b, 0x6d, 0xa3, 0x7b, 0x91, 0x30, 0x68, + 0x2c, 0x03, 0xeb, 0x10, 0xef, 0xd2, 0xe3, 0x3d, 0xff, 0x53, 0x0e, 0xca, 0x1a, 0x58, 0xec, 0x46, + 0x18, 0x00, 0x68, 0x0d, 0x1c, 0x7b, 0xc4, 0x95, 0x93, 0xb3, 0x6a, 0x56, 0x11, 0xba, 0x2d, 0x81, + 0x62, 0x2f, 0xb6, 0xcf, 0x4f, 0x2d, 0x6f, 0x12, 0x5a, 0x03, 0x7e, 0xea, 0x73, 0xd5, 0xca, 0x8a, + 0x7d, 0x7e, 0x7a, 0x30, 0x09, 0xb7, 0x11, 0x26, 0xb0, 0x04, 0x2f, 0xd1, 0xb0, 0x64, 0xcc, 0xda, + 0xc8, 0xbe, 0x8c, 0xb1, 0x64, 0xe0, 0x24, 0x51, 0x66, 0x3e, 0x0a, 0x9c, 0x24, 0x6d, 0x71, 0x7a, + 0x03, 0x2d, 0xcc, 0x6e, 0xa0, 0xdf, 0x84, 0x55, 0xda, 0x40, 0x25, 0x6b, 0xb6, 0xa6, 0x56, 0xf2, + 0x32, 0xa6, 0xca, 0x4e, 0x6a, 0x62, 0x6f, 0x5d, 0xf4, 0x40, 0xb1, 0xa5, 0xc0, 0xf9, 0x21, 0x31, + 0xb2, 0x8c, 0x29, 0x7a, 0x26, 0x0b, 0xef, 0x3a, 0x3f, 0xe4, 0x02, 0x13, 0xa3, 0x63, 0x74, 0x4c, + 0x79, 0xc0, 0x62, 0xe4, 0xb8, 0xd3, 0x98, 0xf6, 0x65, 0x12, 0xb3, 0x24, 0x31, 0xed, 0x4b, 0x1d, + 0xf3, 0x09, 0xac, 0x8d, 0xf8, 0xc0, 0xb1, 0x93, 0xc5, 0x5a, 0xb1, 0xe0, 0xb6, 0x4c, 0xc9, 0x5a, + 0x9e, 0x2e, 0x29, 0xee, 0x62, 0x34, 0x7e, 0xe8, 0x8d, 0x8e, 0x1d, 0x92, 0x59, 0x28, 0x5e, 0x27, + 0x6f, 0xd6, 0xdc, 0xc9, 0xe8, 0xfb, 0x08, 0x16, 0x59, 0x02, 0xa3, 0x0a, 0xe5, 0x6e, 0xe8, 0x8d, + 0xd5, 0x34, 0xd7, 0xa0, 0x42, 0x9f, 0xf2, 0xd4, 0xe3, 0x2d, 0xb8, 0x89, 0x2c, 0xa1, 0xe7, 0x8d, + 0xbd, 0xa1, 0x77, 0x7a, 0x95, 0xb0, 0xe3, 0xfd, 0xbb, 0x0c, 0x2c, 0x25, 0x52, 0x25, 0x7b, 0xfd, + 0x26, 0xf1, 0xb3, 0xe8, 0xe8, 0x1a, 0xad, 0xc1, 0x45, 0x6d, 0x0d, 0x12, 0x22, 0x31, 0x33, 0x75, + 0x9c, 0xad, 0x19, 0x5f, 0xb9, 0xa0, 0x32, 0x12, 0x4b, 0x69, 0xcc, 0xb2, 0x14, 0x99, 0x5f, 0x5d, + 0xc6, 0xa0, 0x8a, 0xf8, 0x05, 0x79, 0x08, 0x66, 0x20, 0xbb, 0x9c, 0x4b, 0x9e, 0x24, 0xd0, 0x6d, + 0x7e, 0xaa, 0x05, 0xb1, 0x21, 0x30, 0x30, 0xfe, 0x49, 0x06, 0x20, 0x6e, 0x1d, 0x9e, 0x65, 0x88, + 0xe4, 0x16, 0xba, 0xcd, 0x4c, 0x93, 0x51, 0xde, 0x80, 0x4a, 0x14, 0xb1, 0x1c, 0x4b, 0x42, 0x65, + 0x05, 0x13, 0xe2, 0xd0, 0x3d, 0x58, 0x38, 0x1d, 0x7a, 0xc7, 0x28, 0xb1, 0x4a, 0xb9, 0x85, 0xe2, + 0xd5, 0x6a, 0x04, 0x56, 0xd2, 0x48, 0x2c, 0x37, 0xe5, 0x53, 0x83, 0x9a, 0x75, 0x29, 0xc8, 0xf8, + 0xad, 0x6c, 0x14, 0xba, 0x19, 0x8f, 0xc4, 0x8b, 0xd5, 0xbb, 0x9f, 0x24, 0x96, 0xe6, 0x45, 0xee, + 0xc5, 0x8f, 0xa1, 0xe6, 0xd3, 0xa6, 0xa4, 0x76, 0xac, 0xfc, 0x0b, 0x76, 0xac, 0xaa, 0x9f, 0x90, + 0x74, 0xde, 0x81, 0xba, 0x3d, 0x38, 0xe7, 0x7e, 0xe8, 0xa0, 0xb5, 0x1e, 0xe5, 0x63, 0x19, 0x2c, + 0xa9, 0xc1, 0x51, 0x10, 0xbd, 0x07, 0x0b, 0xf2, 0x24, 0x6e, 0x84, 0x29, 0xef, 0xf6, 0x89, 0xc1, + 0x02, 0xd1, 0xf8, 0xe7, 0x2a, 0x56, 0x34, 0x39, 0xbb, 0x2f, 0x1e, 0x15, 0xbd, 0x87, 0xd9, 0x59, + 0x07, 0xaa, 0x24, 0x24, 0xe9, 0x04, 0x90, 0xfc, 0x88, 0x80, 0xd2, 0x05, 0x90, 0x1c, 0xd6, 0xfc, + 0xab, 0x0c, 0xab, 0xf1, 0x1f, 0x32, 0x30, 0xbf, 0xeb, 0x8d, 0x77, 0x1d, 0x8a, 0xe6, 0xc7, 0x65, + 0x12, 0xf9, 0xa8, 0xe6, 0xc4, 0x27, 0x06, 0xfe, 0xbc, 0xe0, 0xc0, 0x59, 0xaa, 0x98, 0x57, 0x4d, + 0x8a, 0x79, 0xdf, 0x81, 0x5b, 0xe8, 0x02, 0xf4, 0xbd, 0xb1, 0xe7, 0x8b, 0xa5, 0x6a, 0x0f, 0x49, + 0xdc, 0xf3, 0xdc, 0xf0, 0x4c, 0xf1, 0xce, 0x9b, 0x27, 0x9c, 0x1f, 0x6a, 0x18, 0xfb, 0x11, 0x02, + 0x1e, 0xe9, 0x1c, 0x86, 0xe7, 0x16, 0x69, 0xe8, 0x52, 0x1e, 0x25, 0x8e, 0xba, 0x20, 0x12, 0x5a, + 0x08, 0x47, 0x89, 0xd4, 0xf8, 0x16, 0x94, 0x22, 0x63, 0x0f, 0x7b, 0x17, 0x4a, 0x67, 0xde, 0x58, + 0x5a, 0x84, 0x32, 0x89, 0x43, 0x79, 0xb2, 0xd7, 0x66, 0xf1, 0x8c, 0x7e, 0x04, 0xc6, 0x9f, 0xcd, + 0xc3, 0x7c, 0xdb, 0x3d, 0xf7, 0x9c, 0x3e, 0x46, 0x9b, 0x8e, 0xf8, 0xc8, 0x53, 0xd7, 0x01, 0x88, + 0xdf, 0x18, 0x9b, 0x15, 0xdf, 0xd0, 0x93, 0x93, 0xb1, 0x59, 0xd1, 0xdd, 0x3c, 0x2b, 0x30, 0xe7, + 0xeb, 0x57, 0xec, 0x14, 0x7c, 0x8c, 0x7f, 0x8f, 0xf6, 0xcb, 0x82, 0x76, 0x9d, 0x82, 0x28, 0x8b, + 0xae, 0x7e, 0xc1, 0x21, 0xa3, 0xe3, 0x99, 0x25, 0x84, 0xe0, 0x80, 0xbd, 0x06, 0xf3, 0xf2, 0x0c, + 0x1c, 0x1d, 0x5a, 0xa2, 0x80, 0x75, 0x09, 0x42, 0x6a, 0xf0, 0x39, 0xb9, 0x70, 0x23, 0x41, 0x36, + 0x67, 0x56, 0x14, 0x70, 0x5b, 0xd0, 0xda, 0x1d, 0x28, 0x13, 0x3e, 0xa1, 0x14, 0x65, 0x90, 0x26, + 0x82, 0x10, 0x21, 0xe5, 0xa6, 0xaa, 0x52, 0xea, 0x4d, 0x55, 0x18, 0x4e, 0x1c, 0x71, 0x59, 0xea, + 0x22, 0xd0, 0xfd, 0x44, 0x1a, 0x5c, 0x5d, 0xd3, 0x26, 0x6d, 0x2a, 0x74, 0x5a, 0x59, 0xd9, 0x54, + 0xde, 0x84, 0xea, 0x89, 0x3d, 0x1c, 0x1e, 0xdb, 0xfd, 0xe7, 0x64, 0x0a, 0xa8, 0x90, 0xf5, 0x53, + 0x01, 0xd1, 0x16, 0x70, 0x07, 0xca, 0xda, 0x2c, 0x63, 0x04, 0x66, 0xde, 0x84, 0x78, 0x7e, 0xa7, + 0x2d, 0x7c, 0xb5, 0x57, 0xb0, 0xf0, 0x69, 0x91, 0xa8, 0x0b, 0xc9, 0x48, 0xd4, 0x5b, 0xc8, 0x4d, + 0x65, 0xc8, 0x61, 0x9d, 0x2e, 0xc3, 0xb1, 0x07, 0x03, 0x0c, 0x39, 0xa4, 0x9b, 0x27, 0x71, 0xf0, + 0x28, 0x7d, 0x91, 0x74, 0x09, 0x82, 0x11, 0xca, 0x6d, 0x32, 0x53, 0x8f, 0x6d, 0x67, 0x80, 0x87, + 0x0e, 0xc8, 0x7a, 0x30, 0x6f, 0x8f, 0xc2, 0x43, 0xdb, 0x19, 0xb0, 0xbb, 0x50, 0x51, 0xc9, 0xb8, + 0x3b, 0x2e, 0xd1, 0xf8, 0xcb, 0x64, 0xb1, 0x27, 0x1a, 0x50, 0x8d, 0x30, 0x46, 0xf1, 0x91, 0xe3, + 0xb2, 0x44, 0x41, 0x3a, 0x78, 0x1f, 0xa3, 0x7c, 0x42, 0x8e, 0x07, 0x8b, 0x6b, 0x8f, 0x6f, 0x45, + 0xc1, 0x07, 0x48, 0xa5, 0xea, 0x3f, 0x39, 0xc7, 0x08, 0x53, 0x08, 0x77, 0xe4, 0xa3, 0x5b, 0x4d, + 0xc8, 0xbf, 0x12, 0x15, 0x7d, 0x74, 0x84, 0xc0, 0xbe, 0xa5, 0xe9, 0xaf, 0x0d, 0x44, 0x7e, 0x6d, + 0xaa, 0xfc, 0xeb, 0x0e, 0x65, 0xdd, 0x06, 0x70, 0x02, 0xb1, 0xcb, 0x04, 0xdc, 0x1d, 0xe0, 0x19, + 0xe1, 0xa2, 0x59, 0x72, 0x82, 0x67, 0x04, 0xf8, 0xd9, 0x2a, 0xb6, 0x4d, 0xa8, 0xe8, 0xdd, 0x64, + 0x45, 0xc8, 0x1f, 0x1c, 0xb6, 0x3a, 0xf5, 0x1b, 0xac, 0x0c, 0xf3, 0xdd, 0x56, 0xaf, 0xb7, 0x87, + 0x9e, 0xbe, 0x0a, 0x14, 0xa3, 0x83, 0x8c, 0x59, 0xf1, 0xd5, 0xdc, 0xda, 0x6a, 0x1d, 0xf6, 0x5a, + 0xdb, 0xf5, 0xdc, 0xf7, 0xf2, 0xc5, 0x6c, 0x3d, 0x67, 0xfc, 0x79, 0x0e, 0xca, 0xda, 0x28, 0xbc, + 0x98, 0x19, 0xdf, 0x06, 0x40, 0x4d, 0x32, 0x8e, 0x48, 0xcd, 0x9b, 0x25, 0x01, 0xa1, 0xc9, 0xd7, + 0x7d, 0x14, 0x39, 0xba, 0x65, 0x49, 0xf9, 0x28, 0xde, 0x84, 0x2a, 0x5d, 0x58, 0xa4, 0xfb, 0x6b, + 0x0b, 0x66, 0x85, 0x80, 0x92, 0x55, 0xe3, 0x09, 0x67, 0x44, 0xc2, 0xe3, 0x75, 0xf2, 0xfa, 0x12, + 0x02, 0xe1, 0x01, 0x3b, 0x3c, 0x1d, 0x19, 0x78, 0xc3, 0x73, 0x4e, 0x18, 0x24, 0x11, 0x96, 0x25, + 0xac, 0x27, 0xcf, 0x6a, 0x4b, 0x7e, 0xa8, 0x1d, 0xb1, 0x2d, 0x98, 0x15, 0x02, 0xca, 0x8a, 0xbe, + 0xae, 0x08, 0x88, 0xa2, 0x57, 0xd6, 0x66, 0xa9, 0x21, 0x41, 0x3c, 0x7b, 0x33, 0x66, 0xc4, 0x12, + 0x12, 0xc6, 0xd7, 0x66, 0xf3, 0xbd, 0xdc, 0x9c, 0xc8, 0xde, 0x05, 0x36, 0x1a, 0x8f, 0xad, 0x14, + 0x03, 0x5f, 0xde, 0x5c, 0x18, 0x8d, 0xc7, 0x3d, 0xcd, 0xfe, 0xf5, 0x33, 0xb0, 0x3d, 0x7e, 0x01, + 0xac, 0x29, 0x16, 0x30, 0x36, 0x31, 0x52, 0xc5, 0x62, 0xb6, 0x9c, 0xd1, 0xd9, 0x72, 0x0a, 0xf7, + 0xcb, 0xa6, 0x72, 0xbf, 0x17, 0xf1, 0x09, 0x63, 0x07, 0xca, 0x87, 0xda, 0x75, 0x68, 0x77, 0xc5, + 0x0e, 0xa1, 0x2e, 0x42, 0xa3, 0xbd, 0x83, 0x6c, 0x8a, 0xbe, 0xbc, 0xff, 0x4c, 0x6b, 0x4d, 0x56, + 0x6b, 0x8d, 0xf1, 0x8f, 0x32, 0x74, 0xd5, 0x4c, 0xd4, 0xf8, 0xf8, 0x06, 0x36, 0xe5, 0x7e, 0x8b, + 0x4f, 0xc2, 0x97, 0x95, 0xdb, 0x4d, 0x1e, 0x62, 0xc7, 0xa6, 0x59, 0xde, 0xc9, 0x49, 0xc0, 0x55, + 0x8c, 0x47, 0x19, 0x61, 0x07, 0x08, 0x52, 0xc2, 0xb7, 0x90, 0xf0, 0x1d, 0x2a, 0x3f, 0x90, 0x81, + 0x1d, 0x42, 0xf8, 0xde, 0xb7, 0x2f, 0x65, 0xad, 0x81, 0x10, 0x41, 0xa4, 0x7f, 0x40, 0x1d, 0x96, + 0x8d, 0xbe, 0x8d, 0x7f, 0x20, 0x0f, 0xeb, 0x4f, 0x8f, 0xef, 0x03, 0x28, 0x46, 0xa5, 0x26, 0x77, + 0x58, 0x85, 0x19, 0xa5, 0x8b, 0x7d, 0x1c, 0x8d, 0x21, 0x89, 0x16, 0xd3, 0xe2, 0x42, 0x1f, 0x4f, + 0x5b, 0x6b, 0xf5, 0x7b, 0xc0, 0x4e, 0x1c, 0x7f, 0x1a, 0x99, 0x16, 0x5b, 0x1d, 0x53, 0x34, 0x6c, + 0xe3, 0x08, 0x96, 0x14, 0x97, 0xd0, 0x34, 0x82, 0xe4, 0xe4, 0x65, 0x5e, 0xc2, 0xe4, 0xb3, 0x33, + 0x4c, 0xde, 0xf8, 0xcd, 0x02, 0xcc, 0xab, 0xab, 0x05, 0xd3, 0xae, 0xc3, 0x2b, 0x25, 0xaf, 0xc3, + 0x6b, 0x24, 0xae, 0x4e, 0xc2, 0xa9, 0x97, 0xfb, 0xfd, 0xbd, 0xe9, 0x2d, 0x5b, 0xf3, 0x55, 0x24, + 0xb6, 0x6d, 0xe9, 0xab, 0x28, 0x24, 0x7d, 0x15, 0x69, 0x57, 0x04, 0x92, 0xe8, 0x39, 0x73, 0x45, + 0xe0, 0x2d, 0x20, 0x39, 0x42, 0x0b, 0x6e, 0x2b, 0x22, 0x40, 0xec, 0x39, 0x49, 0xb1, 0xa3, 0x38, + 0x2d, 0x76, 0xbc, 0xb2, 0x48, 0xf0, 0x4d, 0x98, 0xa3, 0xeb, 0x35, 0xe4, 0xe1, 0x5f, 0xb5, 0x71, + 0xc8, 0xb1, 0x52, 0xff, 0xe9, 0xc4, 0x83, 0x29, 0x71, 0xf5, 0xfb, 0xb6, 0xca, 0x89, 0xfb, 0xb6, + 0x74, 0x1f, 0x4a, 0x25, 0xe9, 0x43, 0xb9, 0x0f, 0xf5, 0x68, 0xe0, 0xd0, 0x22, 0xe9, 0x06, 0xf2, + 0xe4, 0x60, 0x4d, 0xc1, 0x05, 0x37, 0xec, 0x04, 0xf1, 0xc6, 0x57, 0x4b, 0x6c, 0x7c, 0x82, 0x57, + 0x35, 0xc3, 0x90, 0x8f, 0xc6, 0xa1, 0xda, 0xf8, 0xb4, 0x5b, 0x19, 0x69, 0xe6, 0x17, 0x70, 0xe6, + 0xd5, 0xf4, 0x12, 0x75, 0x6c, 0x42, 0xed, 0xc4, 0x76, 0x86, 0x13, 0x9f, 0x5b, 0x3e, 0xb7, 0x03, + 0xcf, 0xc5, 0xc5, 0x1f, 0xef, 0xc1, 0xb2, 0x8b, 0x3b, 0x84, 0x63, 0x22, 0x8a, 0x59, 0x3d, 0xd1, + 0x3f, 0xf1, 0x10, 0x93, 0x3e, 0x12, 0x62, 0xcb, 0x92, 0x67, 0x88, 0x29, 0x56, 0xa5, 0xdd, 0xb1, + 0x76, 0xf6, 0xda, 0x4f, 0x77, 0x7b, 0xf5, 0x8c, 0xf8, 0xec, 0x1e, 0x6d, 0x6d, 0xb5, 0x5a, 0xdb, + 0xb8, 0x85, 0x01, 0xcc, 0xed, 0x34, 0xdb, 0x7b, 0x72, 0x03, 0xcb, 0xd7, 0x0b, 0xc6, 0xef, 0x64, + 0xa1, 0xac, 0xf5, 0x86, 0x3d, 0x89, 0x26, 0x81, 0x6e, 0x80, 0xba, 0x3d, 0xdb, 0xe3, 0x0d, 0xc5, + 0xe1, 0xb5, 0x59, 0x88, 0xee, 0x5f, 0xcc, 0x5e, 0x7b, 0xff, 0x22, 0x7b, 0x1b, 0x16, 0x6c, 0x2a, + 0x21, 0x1a, 0x74, 0x69, 0xdc, 0x97, 0x60, 0x39, 0xe6, 0x18, 0x41, 0x1a, 0x6f, 0x53, 0x02, 0x2f, + 0xaf, 0x82, 0x36, 0xa3, 0x9d, 0x0a, 0xe7, 0x66, 0x5e, 0x8e, 0x8c, 0x74, 0xc6, 0x47, 0x1b, 0xbe, + 0x1c, 0x2f, 0x95, 0x6c, 0x7c, 0x00, 0x10, 0xb7, 0x39, 0x39, 0x44, 0x37, 0x92, 0x43, 0x94, 0xd1, + 0x86, 0x28, 0x6b, 0xfc, 0x33, 0xc9, 0x9e, 0xe4, 0x78, 0x47, 0xe6, 0xbc, 0xaf, 0x83, 0x32, 0x30, + 0x5a, 0x18, 0xc8, 0x3d, 0x1e, 0xf2, 0x50, 0x5d, 0x58, 0xb0, 0x28, 0x53, 0xda, 0x51, 0xc2, 0x0c, + 0x3b, 0xcd, 0xce, 0xb2, 0xd3, 0x37, 0xa0, 0x22, 0x58, 0xa9, 0x24, 0x96, 0x40, 0xb2, 0xa4, 0xf2, + 0xc8, 0xbe, 0x54, 0x75, 0x27, 0xf8, 0x68, 0x7e, 0x8a, 0x8f, 0xfe, 0x6e, 0x86, 0xee, 0x0f, 0x89, + 0x1b, 0x1a, 0x33, 0xd2, 0xa8, 0xcc, 0x24, 0x23, 0x95, 0xa8, 0x66, 0x94, 0x7e, 0x0d, 0x73, 0xcc, + 0xa6, 0x33, 0xc7, 0x74, 0xb6, 0x9b, 0x4b, 0x65, 0xbb, 0xc6, 0x3a, 0x34, 0xb6, 0xb9, 0x18, 0x8a, + 0xe6, 0x70, 0x38, 0x35, 0x96, 0xc6, 0x2d, 0xb8, 0x99, 0x92, 0x26, 0x2d, 0x33, 0x9f, 0xc0, 0x4a, + 0x93, 0x2e, 0x56, 0xf8, 0x59, 0x1d, 0x90, 0x34, 0x1a, 0xb0, 0x3a, 0x5d, 0xa4, 0xac, 0x6c, 0x07, + 0x16, 0xb7, 0xf9, 0xf1, 0xe4, 0x74, 0x8f, 0x9f, 0xc7, 0x15, 0x31, 0xc8, 0x07, 0x67, 0xde, 0x85, + 0x9c, 0x5c, 0xfc, 0x8d, 0xa1, 0x97, 0x02, 0xc7, 0x0a, 0xc6, 0xbc, 0xaf, 0xac, 0xf3, 0x08, 0xe9, + 0x8e, 0x79, 0xdf, 0x78, 0x02, 0x4c, 0x2f, 0x47, 0xce, 0x84, 0x50, 0x9d, 0x26, 0xc7, 0x56, 0x70, + 0x15, 0x84, 0x7c, 0xa4, 0x0e, 0x06, 0x42, 0x30, 0x39, 0xee, 0x12, 0xc4, 0xb8, 0x07, 0x95, 0x43, + 0xfb, 0xca, 0xe4, 0x5f, 0xc8, 0xf3, 0x77, 0x6b, 0x30, 0x3f, 0xb6, 0xaf, 0x04, 0xcf, 0x8c, 0x1c, + 0x75, 0x98, 0x6c, 0xfc, 0x61, 0x1e, 0xe6, 0x08, 0x93, 0xdd, 0xa5, 0x1b, 0x8c, 0x1d, 0x17, 0x79, + 0x96, 0xda, 0x3d, 0x34, 0xd0, 0xcc, 0x06, 0x93, 0x9d, 0xdd, 0x60, 0xa4, 0x55, 0x51, 0xdd, 0xdc, + 0xa4, 0x5c, 0x2a, 0xee, 0x64, 0xa4, 0xae, 0x6b, 0x4a, 0xde, 0x2e, 0x90, 0x8f, 0x6f, 0xa8, 0xa6, + 0x93, 0xd5, 0x49, 0xa7, 0x77, 0xac, 0xa0, 0x51, 0xeb, 0xd4, 0xbe, 0x29, 0xf7, 0x16, 0x1d, 0x94, + 0xaa, 0x05, 0xce, 0xab, 0x43, 0xa5, 0x49, 0x2d, 0x70, 0x46, 0xdb, 0x2b, 0xbe, 0x5c, 0xdb, 0x23, + 0x73, 0xe3, 0x0b, 0xb4, 0x3d, 0x78, 0x05, 0x6d, 0xef, 0x15, 0x1c, 0xce, 0x37, 0xa1, 0x88, 0xc2, + 0x90, 0xb6, 0xd5, 0x08, 0x21, 0x48, 0x6c, 0x35, 0x1f, 0x6a, 0xfa, 0x10, 0x45, 0xbb, 0x68, 0xbc, + 0xde, 0xe4, 0x5f, 0xfc, 0x7c, 0x1c, 0x79, 0x9f, 0xc3, 0xbc, 0x84, 0x0a, 0x82, 0x76, 0xed, 0x91, + 0xba, 0xfc, 0x0e, 0x7f, 0x8b, 0x61, 0xc3, 0x1b, 0xbb, 0xbe, 0x98, 0x38, 0x3e, 0x1f, 0xa8, 0x5b, + 0x8d, 0x1c, 0x5c, 0xa3, 0x02, 0x22, 0x3a, 0x28, 0x74, 0x33, 0xd7, 0xbb, 0x70, 0x25, 0xef, 0x99, + 0x77, 0x82, 0x67, 0xe2, 0xd3, 0x60, 0x50, 0xc7, 0xeb, 0x2f, 0xc7, 0x9e, 0xaf, 0x76, 0x72, 0xe3, + 0xc7, 0x19, 0xa8, 0xcb, 0xd5, 0x15, 0xa5, 0xe9, 0xaa, 0x51, 0xe1, 0xba, 0xe0, 0x8c, 0x17, 0xdf, + 0x51, 0x64, 0x40, 0x15, 0x2d, 0x42, 0xd1, 0xb6, 0x4e, 0x16, 0xad, 0xb2, 0x00, 0xee, 0xc8, 0xad, + 0xfd, 0x75, 0x28, 0xab, 0xc0, 0xf0, 0x91, 0x33, 0x54, 0x97, 0xd1, 0x53, 0x64, 0xf8, 0xbe, 0x33, + 0x54, 0x52, 0x81, 0x6f, 0xcb, 0x43, 0xce, 0x19, 0x94, 0x0a, 0x4c, 0x3b, 0xe4, 0xc6, 0xbf, 0xca, + 0xc0, 0xa2, 0xd6, 0x15, 0xb9, 0x6e, 0x3f, 0x82, 0x4a, 0x74, 0xef, 0x2c, 0x8f, 0xc4, 0xd1, 0xb5, + 0x24, 0xa3, 0x89, 0xb3, 0x95, 0xfb, 0x11, 0x24, 0x10, 0x8d, 0x19, 0xd8, 0x57, 0x14, 0xbd, 0x3c, + 0x19, 0x29, 0x8d, 0x6f, 0x60, 0x5f, 0xed, 0x70, 0xde, 0x9d, 0x8c, 0x84, 0x3e, 0x7f, 0xc1, 0xf9, + 0xf3, 0x08, 0x81, 0xd8, 0x27, 0x08, 0x98, 0xc4, 0x30, 0xa0, 0x3a, 0xf2, 0xdc, 0xf0, 0x2c, 0x42, + 0x91, 0xa2, 0x38, 0x02, 0x09, 0xc7, 0xf8, 0xd3, 0x2c, 0x2c, 0x91, 0xdd, 0x51, 0xda, 0x7b, 0x25, + 0xeb, 0x6a, 0xc0, 0x1c, 0x99, 0x60, 0x89, 0x79, 0xed, 0xde, 0x30, 0xe5, 0x37, 0xfb, 0xe6, 0x2b, + 0xda, 0x4a, 0xd5, 0x39, 0xea, 0x6b, 0x86, 0x3f, 0x37, 0x3b, 0xfc, 0xd7, 0x0f, 0x6f, 0x9a, 0xf7, + 0xb7, 0x90, 0xe6, 0xfd, 0x7d, 0x15, 0x9f, 0xeb, 0xcc, 0x89, 0xdf, 0x79, 0x89, 0xa3, 0x9d, 0xf8, + 0x7d, 0x02, 0x6b, 0x09, 0x1c, 0xe4, 0xd6, 0xce, 0x89, 0xc3, 0xd5, 0xad, 0x34, 0xcb, 0x1a, 0x76, + 0x57, 0xa5, 0x6d, 0xce, 0x43, 0x21, 0xe8, 0x7b, 0x63, 0x6e, 0xac, 0xc2, 0x72, 0x72, 0x54, 0xe5, + 0x36, 0xf1, 0x7b, 0x19, 0x68, 0xc8, 0x58, 0x1d, 0xc7, 0x3d, 0xdd, 0x75, 0x82, 0xd0, 0xf3, 0xa3, + 0xfb, 0x59, 0x6f, 0x03, 0x04, 0xa1, 0xed, 0x4b, 0x15, 0x5c, 0xde, 0xc3, 0x82, 0x10, 0x54, 0xaf, + 0x6f, 0x42, 0x91, 0xbb, 0x03, 0x4a, 0x24, 0x6a, 0x98, 0xe7, 0xee, 0x40, 0x29, 0xe7, 0x33, 0x5b, + 0x69, 0x35, 0x29, 0x24, 0xc8, 0x5b, 0x0f, 0xc4, 0xe8, 0xf0, 0x73, 0xdc, 0xd2, 0xf3, 0xd1, 0xad, + 0x07, 0xfb, 0xf6, 0x25, 0x46, 0xbe, 0x06, 0xc6, 0xdf, 0xcd, 0xc2, 0x42, 0xdc, 0x3e, 0xba, 0x53, + 0xe5, 0xc5, 0xb7, 0xc3, 0xdc, 0x95, 0xe4, 0xe0, 0x08, 0xa5, 0x46, 0xb3, 0xc6, 0x16, 0x69, 0x71, + 0xb6, 0x5d, 0x66, 0x40, 0x59, 0x61, 0x78, 0x93, 0x50, 0xbb, 0x26, 0xb1, 0x44, 0x28, 0x07, 0x93, + 0x50, 0x68, 0xa1, 0x42, 0x1d, 0x77, 0x5c, 0xa9, 0x07, 0x16, 0xec, 0x51, 0xd8, 0xc6, 0xd7, 0x17, + 0x04, 0x58, 0x64, 0xa3, 0x89, 0x14, 0x58, 0x02, 0xbf, 0x4e, 0x4a, 0x09, 0xcd, 0x1c, 0x2a, 0x24, + 0xba, 0xc4, 0x4e, 0x17, 0x51, 0x47, 0x12, 0xfb, 0xeb, 0x50, 0xa6, 0xc2, 0xe3, 0x03, 0xde, 0x79, + 0xb3, 0x84, 0x35, 0x60, 0xba, 0xb4, 0x8c, 0x79, 0x93, 0x84, 0x3d, 0x00, 0xa8, 0x2a, 0x0c, 0x85, + 0xf9, 0x9b, 0x19, 0xb8, 0x99, 0x32, 0x6d, 0x72, 0x95, 0x6f, 0xc1, 0xe2, 0x49, 0x94, 0xa8, 0x46, + 0x97, 0x96, 0xfa, 0xaa, 0x62, 0xab, 0xc9, 0x31, 0x35, 0xeb, 0x27, 0x49, 0x40, 0xac, 0x89, 0xd2, + 0x0c, 0x26, 0xae, 0x0f, 0x40, 0x91, 0x88, 0xa6, 0x91, 0x94, 0xc0, 0x43, 0x58, 0x6f, 0x5d, 0x0a, + 0x8e, 0xb1, 0xa5, 0x3f, 0x1f, 0xa2, 0xc8, 0x28, 0x69, 0x75, 0xcf, 0xbc, 0x92, 0xd5, 0x7d, 0x40, + 0xe7, 0x8d, 0xa3, 0xb2, 0x7e, 0x92, 0x42, 0x70, 0x03, 0x15, 0x79, 0xe8, 0xf9, 0x13, 0x75, 0x8f, + 0x40, 0x3f, 0x7a, 0xf6, 0xc4, 0x08, 0x60, 0x61, 0x7f, 0x32, 0x0c, 0x9d, 0xf8, 0x25, 0x14, 0xf6, + 0x4d, 0x99, 0x07, 0xeb, 0x51, 0xa3, 0x96, 0x5a, 0x11, 0x44, 0x15, 0xe1, 0x60, 0x8d, 0x44, 0x41, + 0xd6, 0x6c, 0x7d, 0x0b, 0xa3, 0x64, 0x0d, 0xc6, 0x4d, 0x58, 0x8b, 0xbf, 0x68, 0xd8, 0xd4, 0x56, + 0xf3, 0x0f, 0x33, 0x14, 0x66, 0x9f, 0x7c, 0x95, 0x85, 0xb5, 0x60, 0x29, 0x70, 0xdc, 0xd3, 0x21, + 0xd7, 0x8b, 0x0f, 0xe4, 0x20, 0xac, 0x24, 0xdb, 0x26, 0x5f, 0x6e, 0x31, 0x17, 0x29, 0x47, 0x5c, + 0x5a, 0xc0, 0x36, 0xaf, 0x6b, 0x64, 0x4c, 0x16, 0x53, 0xa3, 0x31, 0xdb, 0xf8, 0x36, 0xd4, 0x92, + 0x15, 0xb1, 0x0f, 0xe5, 0x31, 0xfd, 0xb8, 0x55, 0xb9, 0xa9, 0x33, 0xcc, 0x31, 0x41, 0x94, 0xe3, + 0xb1, 0x0f, 0x8c, 0xbf, 0x9d, 0x81, 0x86, 0xc9, 0x05, 0xe5, 0x6a, 0xad, 0x54, 0x34, 0xf3, 0xd1, + 0x4c, 0xa9, 0xd7, 0xf7, 0x55, 0x9d, 0xfe, 0x57, 0x2d, 0x7a, 0xef, 0xda, 0xc9, 0xd8, 0xbd, 0x31, + 0xd3, 0xa3, 0xcd, 0x22, 0xcc, 0x11, 0x8a, 0xb1, 0x06, 0x2b, 0xb2, 0x3d, 0xaa, 0x2d, 0xb1, 0x4b, + 0x35, 0x51, 0x63, 0xc2, 0xa5, 0xba, 0x0e, 0x0d, 0x3a, 0x8f, 0xab, 0x77, 0x42, 0x66, 0xdc, 0x06, + 0xb6, 0x6f, 0xf7, 0x6d, 0xdf, 0xf3, 0xdc, 0x43, 0xee, 0xcb, 0xa0, 0x65, 0x94, 0x30, 0xd1, 0xe3, + 0xa8, 0x44, 0x61, 0xfa, 0x52, 0x97, 0xc3, 0x7a, 0xae, 0x8a, 0xd1, 0xa2, 0x2f, 0xc3, 0x84, 0xa5, + 0x4d, 0xfb, 0x39, 0x57, 0x25, 0xa9, 0x21, 0xfa, 0x18, 0xca, 0xe3, 0xa8, 0x50, 0x35, 0xee, 0xea, + 0x1a, 0x91, 0xd9, 0x6a, 0x4d, 0x1d, 0xdb, 0x78, 0x0c, 0xcb, 0xc9, 0x32, 0x25, 0xeb, 0x58, 0x87, + 0xe2, 0x48, 0xc2, 0x64, 0xeb, 0xa2, 0x6f, 0xe3, 0xb7, 0x8b, 0x30, 0x2f, 0xb5, 0x51, 0xb6, 0x01, + 0xf9, 0xbe, 0x8a, 0x93, 0x8b, 0xaf, 0xaf, 0x92, 0xa9, 0xea, 0xff, 0x16, 0x46, 0xcb, 0x09, 0x3c, + 0xf6, 0x31, 0xd4, 0x92, 0xae, 0xe2, 0xa9, 0xd3, 0xfe, 0x49, 0x1f, 0x6f, 0xb5, 0x3f, 0xe5, 0x14, + 0x2c, 0xc5, 0x9b, 0x23, 0xc9, 0x0c, 0xc5, 0x33, 0x6d, 0xf7, 0xf4, 0x5c, 0x21, 0x6f, 0x07, 0x67, + 0xb6, 0xf5, 0xf8, 0xc9, 0x07, 0xf2, 0xb8, 0x7f, 0x19, 0x81, 0xdd, 0x33, 0xfb, 0xf1, 0x93, 0x0f, + 0xa6, 0x25, 0x69, 0x79, 0xd8, 0x5f, 0x93, 0xa4, 0x97, 0xa1, 0x40, 0xb7, 0xa0, 0x52, 0xc0, 0x13, + 0x7d, 0xb0, 0x47, 0xb0, 0xac, 0x0c, 0x1c, 0x32, 0x34, 0x9d, 0xb8, 0x60, 0x91, 0x4e, 0x03, 0xca, + 0xb4, 0x2e, 0x26, 0x91, 0x49, 0x64, 0x15, 0xe6, 0xce, 0xe2, 0x2b, 0x6d, 0xab, 0xa6, 0xfc, 0x32, + 0xfe, 0xb4, 0x00, 0x65, 0x6d, 0x50, 0x58, 0x05, 0x8a, 0x66, 0xab, 0xdb, 0x32, 0x3f, 0x6d, 0x6d, + 0xd7, 0x6f, 0xb0, 0xfb, 0xf0, 0x56, 0xbb, 0xb3, 0x75, 0x60, 0x9a, 0xad, 0xad, 0x9e, 0x75, 0x60, + 0x5a, 0xea, 0x12, 0xb5, 0xc3, 0xe6, 0xe7, 0xfb, 0xad, 0x4e, 0xcf, 0xda, 0x6e, 0xf5, 0x9a, 0xed, + 0xbd, 0x6e, 0x3d, 0xc3, 0x5e, 0x83, 0x46, 0x8c, 0xa9, 0x92, 0x9b, 0xfb, 0x07, 0x47, 0x9d, 0x5e, + 0x3d, 0xcb, 0xee, 0xc0, 0xad, 0x9d, 0x76, 0xa7, 0xb9, 0x67, 0xc5, 0x38, 0x5b, 0x7b, 0xbd, 0x4f, + 0xad, 0xd6, 0x2f, 0x1d, 0xb6, 0xcd, 0xcf, 0xeb, 0xb9, 0x34, 0x84, 0xdd, 0xde, 0xde, 0x96, 0x2a, + 0x21, 0xcf, 0x6e, 0xc2, 0x0a, 0x21, 0x50, 0x16, 0xab, 0x77, 0x70, 0x60, 0x75, 0x0f, 0x0e, 0x3a, + 0xf5, 0x02, 0x5b, 0x84, 0x6a, 0xbb, 0xf3, 0x69, 0x73, 0xaf, 0xbd, 0x6d, 0x99, 0xad, 0xe6, 0xde, + 0x7e, 0x7d, 0x8e, 0x2d, 0xc1, 0xc2, 0x34, 0xde, 0xbc, 0x28, 0x42, 0xe1, 0x1d, 0x74, 0xda, 0x07, + 0x1d, 0xeb, 0xd3, 0x96, 0xd9, 0x6d, 0x1f, 0x74, 0xea, 0x45, 0xb6, 0x0a, 0x2c, 0x99, 0xb4, 0xbb, + 0xdf, 0xdc, 0xaa, 0x97, 0xd8, 0x0a, 0x2c, 0x26, 0xe1, 0xcf, 0x5a, 0x9f, 0xd7, 0x81, 0x35, 0x60, + 0x99, 0x1a, 0x66, 0x6d, 0xb6, 0xf6, 0x0e, 0x3e, 0xb3, 0xf6, 0xdb, 0x9d, 0xf6, 0xfe, 0xd1, 0x7e, + 0xbd, 0x8c, 0x77, 0x33, 0xb6, 0x5a, 0x56, 0xbb, 0xd3, 0x3d, 0xda, 0xd9, 0x69, 0x6f, 0xb5, 0x5b, + 0x9d, 0x5e, 0xbd, 0x42, 0x35, 0xa7, 0x75, 0xbc, 0x2a, 0x32, 0xc8, 0xf3, 0x2b, 0xd6, 0x76, 0xbb, + 0xdb, 0xdc, 0xdc, 0x6b, 0x6d, 0xd7, 0x6b, 0xec, 0x36, 0xdc, 0xec, 0xb5, 0xf6, 0x0f, 0x0f, 0xcc, + 0xa6, 0xf9, 0xb9, 0x3a, 0xdf, 0x62, 0xed, 0x34, 0xdb, 0x7b, 0x47, 0x66, 0xab, 0xbe, 0xc0, 0xde, + 0x80, 0xdb, 0x66, 0xeb, 0x93, 0xa3, 0xb6, 0xd9, 0xda, 0xb6, 0x3a, 0x07, 0xdb, 0x2d, 0x6b, 0xa7, + 0xd5, 0xec, 0x1d, 0x99, 0x2d, 0x6b, 0xbf, 0xdd, 0xed, 0xb6, 0x3b, 0x4f, 0xeb, 0x75, 0xf6, 0x16, + 0xdc, 0x8d, 0x50, 0xa2, 0x02, 0xa6, 0xb0, 0x16, 0x45, 0xff, 0xd4, 0x94, 0x76, 0x5a, 0xbf, 0xd4, + 0xb3, 0x0e, 0x5b, 0x2d, 0xb3, 0xce, 0xd8, 0x3a, 0xac, 0xc6, 0xd5, 0x53, 0x05, 0xb2, 0xee, 0x25, + 0x91, 0x76, 0xd8, 0x32, 0xf7, 0x9b, 0x1d, 0x31, 0xc1, 0x89, 0xb4, 0x65, 0xd1, 0xec, 0x38, 0x6d, + 0xba, 0xd9, 0x2b, 0x8c, 0x41, 0x4d, 0x9b, 0x95, 0x9d, 0xa6, 0x59, 0x5f, 0x65, 0x0b, 0x50, 0xde, + 0x3f, 0x3c, 0xb4, 0x7a, 0xed, 0xfd, 0xd6, 0xc1, 0x51, 0xaf, 0xbe, 0xc6, 0x56, 0xa0, 0xde, 0xee, + 0xf4, 0x5a, 0xa6, 0x98, 0x6b, 0x95, 0xf5, 0x7f, 0xcc, 0xb3, 0x65, 0x58, 0x50, 0x2d, 0x55, 0xd0, + 0xbf, 0x98, 0x67, 0x6b, 0xc0, 0x8e, 0x3a, 0x66, 0xab, 0xb9, 0x2d, 0x06, 0x2e, 0x4a, 0xf8, 0x9f, + 0xf3, 0xd2, 0x6d, 0xf4, 0xe3, 0x5c, 0xb4, 0x59, 0xc7, 0x71, 0x18, 0xc9, 0x0b, 0xce, 0x2b, 0xda, + 0xc5, 0xe4, 0x2f, 0x7b, 0x7a, 0x44, 0x53, 0xad, 0x72, 0x33, 0xaa, 0xd5, 0x8c, 0xee, 0x5e, 0xd5, + 0x65, 0xbf, 0x37, 0xa1, 0x3a, 0xa2, 0xcb, 0xce, 0xe5, 0xa5, 0xc6, 0x20, 0x83, 0x92, 0x08, 0x48, + 0x37, 0x1a, 0xcf, 0xbc, 0xbd, 0x51, 0x98, 0x7d, 0x7b, 0x23, 0x4d, 0xbe, 0x9f, 0x4b, 0x93, 0xef, + 0x1f, 0xc0, 0x22, 0xb1, 0x26, 0xc7, 0x75, 0x46, 0x4a, 0x6b, 0x26, 0x29, 0x70, 0x01, 0x59, 0x14, + 0xc1, 0x95, 0x3a, 0xa1, 0x54, 0x0e, 0xc9, 0x42, 0xe6, 0xa5, 0xb6, 0x91, 0xd0, 0x34, 0x88, 0x73, + 0x44, 0x9a, 0x46, 0x54, 0x83, 0x7d, 0x19, 0xd7, 0x50, 0xd6, 0x6a, 0x20, 0x38, 0xd6, 0xf0, 0x00, + 0x16, 0xf9, 0x65, 0xe8, 0xdb, 0x96, 0x37, 0xb6, 0xbf, 0x98, 0xa0, 0x5f, 0xdb, 0x46, 0x1d, 0xbe, + 0x62, 0x2e, 0x60, 0xc2, 0x01, 0xc2, 0xb7, 0xed, 0xd0, 0x7e, 0xf0, 0x25, 0x94, 0xb5, 0x8b, 0xf0, + 0xd9, 0x1a, 0x2c, 0x7d, 0xd6, 0xee, 0x75, 0x5a, 0xdd, 0xae, 0x75, 0x78, 0xb4, 0xf9, 0xac, 0xf5, + 0xb9, 0xb5, 0xdb, 0xec, 0xee, 0xd6, 0x6f, 0x88, 0x45, 0xdb, 0x69, 0x75, 0x7b, 0xad, 0xed, 0x04, + 0x3c, 0xc3, 0x5e, 0x87, 0xf5, 0xa3, 0xce, 0x51, 0xb7, 0xb5, 0x6d, 0xa5, 0xe5, 0xcb, 0x0a, 0x2a, + 0x95, 0xe9, 0x29, 0xd9, 0x73, 0x0f, 0x7e, 0x0d, 0x6a, 0xc9, 0xa3, 0xde, 0x0c, 0x60, 0x6e, 0xaf, + 0xf5, 0xb4, 0xb9, 0xf5, 0x39, 0xdd, 0xde, 0xda, 0xed, 0x35, 0x7b, 0xed, 0x2d, 0x4b, 0xde, 0xd6, + 0x2a, 0x38, 0x42, 0x86, 0x95, 0x61, 0xbe, 0xd9, 0xd9, 0xda, 0x3d, 0x30, 0xbb, 0xf5, 0x2c, 0x7b, + 0x0d, 0xd6, 0x14, 0xad, 0x6e, 0x1d, 0xec, 0xef, 0xb7, 0x7b, 0xc8, 0x0c, 0x7b, 0x9f, 0x1f, 0x0a, + 0xd2, 0x7c, 0x60, 0x43, 0x29, 0xbe, 0x6e, 0x16, 0x19, 0x4c, 0xbb, 0xd7, 0x6e, 0xf6, 0x62, 0xee, + 0x5a, 0xbf, 0x21, 0xf8, 0x57, 0x0c, 0xc6, 0xdb, 0x62, 0xeb, 0x19, 0x3a, 0x0d, 0xa7, 0x80, 0x54, + 0x7b, 0x3d, 0x2b, 0x16, 0x55, 0x0c, 0xdd, 0x3c, 0xe8, 0x89, 0x2e, 0x7c, 0x1b, 0x6a, 0xc9, 0x98, + 0xc7, 0xa4, 0xf1, 0x7a, 0x1d, 0x56, 0x37, 0x5b, 0xbd, 0xcf, 0x5a, 0xad, 0x0e, 0x8e, 0xce, 0x56, + 0xab, 0xd3, 0x33, 0x9b, 0x7b, 0xed, 0xde, 0xe7, 0xf5, 0xcc, 0x83, 0x8f, 0xa1, 0x3e, 0xed, 0x60, + 0x4c, 0x78, 0x64, 0x5f, 0xe4, 0xba, 0x7d, 0xf0, 0x9f, 0x33, 0xb0, 0x9c, 0x66, 0x5b, 0x17, 0x73, + 0x28, 0x17, 0xa7, 0x60, 0xd1, 0xdd, 0x83, 0x8e, 0xd5, 0x39, 0xc0, 0xeb, 0x21, 0xd7, 0x61, 0x75, + 0x2a, 0x41, 0x71, 0x82, 0x0c, 0xbb, 0x05, 0x6b, 0x33, 0x99, 0x2c, 0xf3, 0xe0, 0x08, 0xbb, 0xdd, + 0x80, 0xe5, 0xa9, 0xc4, 0x96, 0x69, 0x1e, 0x98, 0xf5, 0x1c, 0x7b, 0x0f, 0xee, 0x4f, 0xa5, 0xcc, + 0x6e, 0x4c, 0x6a, 0xdf, 0xca, 0xb3, 0x7b, 0xf0, 0xe6, 0x0c, 0x76, 0xcc, 0xbb, 0xad, 0xcd, 0xe6, + 0x9e, 0xe8, 0x5e, 0xbd, 0xf0, 0xe0, 0x9f, 0xe6, 0x00, 0xe2, 0x43, 0x45, 0xa2, 0xfe, 0xed, 0x66, + 0xaf, 0xb9, 0x77, 0x20, 0xc8, 0xcb, 0x3c, 0xe8, 0x89, 0xd2, 0xcd, 0xd6, 0x27, 0xf5, 0x1b, 0xa9, + 0x29, 0x07, 0x87, 0xa2, 0x43, 0x6b, 0xb0, 0x44, 0x53, 0xb5, 0x27, 0xba, 0xd1, 0xee, 0x3c, 0xa5, + 0x9b, 0x46, 0x71, 0xf7, 0x3b, 0x3a, 0xdc, 0x31, 0x0f, 0x3a, 0x3d, 0xab, 0xbb, 0x7b, 0xd4, 0xdb, + 0xc6, 0x7b, 0x4a, 0xb7, 0xcc, 0xf6, 0x21, 0x95, 0x99, 0x7f, 0x11, 0x82, 0x28, 0xba, 0x20, 0xd6, + 0xc2, 0xd3, 0x83, 0x6e, 0xb7, 0x7d, 0x68, 0x7d, 0x72, 0xd4, 0x32, 0xdb, 0xad, 0x2e, 0x66, 0x9c, + 0x4b, 0x81, 0x0b, 0xfc, 0x79, 0xb1, 0x67, 0xf6, 0xf6, 0x3e, 0x95, 0x9b, 0x9a, 0x40, 0x2d, 0x26, + 0x41, 0x02, 0xab, 0x24, 0x66, 0x47, 0xec, 0x0a, 0x29, 0x25, 0xc3, 0x35, 0x69, 0x22, 0x5f, 0x59, + 0xec, 0x77, 0x33, 0x8b, 0x04, 0xb3, 0x55, 0xd2, 0x93, 0x44, 0x2e, 0xdc, 0x0a, 0x23, 0xc1, 0x61, + 0x7b, 0xdb, 0xc4, 0x0c, 0xb5, 0x19, 0xa8, 0xc0, 0x5d, 0x10, 0x44, 0x28, 0xb6, 0x0d, 0x81, 0x52, + 0x57, 0x1f, 0x22, 0x65, 0xf1, 0xf1, 0x6f, 0xe5, 0xa0, 0x46, 0x07, 0x3c, 0xe9, 0x7d, 0x48, 0xee, + 0xb3, 0x7d, 0x98, 0x97, 0x0f, 0x8d, 0xb2, 0x95, 0xe8, 0x8e, 0x47, 0xfd, 0x69, 0xd3, 0xf5, 0xd5, + 0x69, 0xb0, 0x14, 0x93, 0x97, 0xfe, 0xca, 0x9f, 0xfc, 0xf7, 0xbf, 0x93, 0xad, 0xb2, 0xf2, 0xc3, + 0xf3, 0xf7, 0x1f, 0x9e, 0x72, 0x37, 0x10, 0x65, 0xfc, 0x0a, 0x40, 0xfc, 0x7c, 0x26, 0x6b, 0x68, + 0x97, 0x4a, 0x24, 0x1e, 0xce, 0x5c, 0xbf, 0x99, 0x92, 0x22, 0xcb, 0xbd, 0x89, 0xe5, 0x2e, 0x19, + 0x35, 0x51, 0xae, 0xe3, 0x3a, 0x21, 0x3d, 0xa5, 0xf9, 0x51, 0xe6, 0x01, 0x1b, 0x40, 0x45, 0x7f, + 0xd8, 0x92, 0x29, 0x09, 0x36, 0xe5, 0x69, 0xce, 0xf5, 0x5b, 0xa9, 0x69, 0x4a, 0x37, 0xc0, 0x3a, + 0x56, 0x8c, 0xba, 0xa8, 0x63, 0x82, 0x18, 0x71, 0x2d, 0x43, 0xd2, 0x96, 0xe2, 0xf7, 0x2b, 0xd9, + 0x6b, 0x9a, 0xbc, 0x3b, 0xf3, 0x7a, 0xe6, 0xfa, 0xed, 0x6b, 0x52, 0x65, 0x5d, 0xb7, 0xb1, 0xae, + 0x35, 0x83, 0x89, 0xba, 0xfa, 0x88, 0xa3, 0x5e, 0xcf, 0xfc, 0x28, 0xf3, 0xe0, 0xf1, 0xbf, 0x7f, + 0x07, 0x4a, 0x51, 0xc0, 0x37, 0xfb, 0x75, 0xa8, 0x26, 0x4e, 0xe0, 0x32, 0xd5, 0x8d, 0xb4, 0x03, + 0xbb, 0xeb, 0xaf, 0xa5, 0x27, 0xca, 0x8a, 0x5f, 0xc7, 0x8a, 0x1b, 0x6c, 0x55, 0x54, 0x2c, 0x4f, + 0xb8, 0x3e, 0xc4, 0x13, 0xf3, 0x74, 0x63, 0xe6, 0x73, 0x4d, 0x2b, 0xa4, 0xca, 0x5e, 0x9b, 0xd6, + 0xd4, 0x12, 0xb5, 0xdd, 0xbe, 0x26, 0x55, 0x56, 0xf7, 0x1a, 0x56, 0xb7, 0xca, 0x96, 0xf5, 0xea, + 0x54, 0x9c, 0x30, 0xe3, 0x78, 0x8d, 0xad, 0xfe, 0xbc, 0x23, 0xbb, 0x1d, 0xdf, 0x29, 0x9a, 0xf2, + 0xec, 0x63, 0x44, 0x22, 0xb3, 0x6f, 0x3f, 0x1a, 0x0d, 0xac, 0x8a, 0x31, 0x9c, 0x3e, 0xfd, 0x75, + 0x47, 0x76, 0x0c, 0x65, 0xed, 0x45, 0x24, 0x76, 0xf3, 0xda, 0xd7, 0x9b, 0xd6, 0xd7, 0xd3, 0x92, + 0xd2, 0xba, 0xa2, 0x97, 0xff, 0xf0, 0x84, 0x73, 0xf6, 0xcb, 0x50, 0x8a, 0xde, 0xd9, 0x61, 0x6b, + 0xda, 0xbb, 0x47, 0xfa, 0xbb, 0x40, 0xeb, 0x8d, 0xd9, 0x84, 0x34, 0xe2, 0xd3, 0x4b, 0x17, 0xc4, + 0xf7, 0x19, 0x94, 0xb5, 0xb7, 0x74, 0xa2, 0x0e, 0xcc, 0xbe, 0xd7, 0x13, 0x75, 0x20, 0xe5, 0xe9, + 0x1d, 0x63, 0x11, 0xab, 0x28, 0xb3, 0x12, 0xd2, 0x77, 0x78, 0xe9, 0x05, 0x6c, 0x0f, 0x56, 0xa4, + 0x06, 0x7c, 0xcc, 0xbf, 0xca, 0x34, 0xa4, 0xbc, 0xa8, 0xf9, 0x28, 0xc3, 0x3e, 0x86, 0xa2, 0x7a, + 0x32, 0x89, 0xad, 0xa6, 0x3f, 0xfd, 0xb4, 0xbe, 0x36, 0x03, 0x97, 0xea, 0xea, 0xe7, 0x00, 0xf1, + 0xc3, 0x3d, 0x11, 0x93, 0x98, 0x79, 0x08, 0x28, 0xa2, 0x80, 0xd9, 0x57, 0x7e, 0x8c, 0x55, 0xec, + 0x60, 0x9d, 0x21, 0x93, 0x70, 0xf9, 0x85, 0xba, 0x6b, 0xfc, 0x07, 0x50, 0xd6, 0xde, 0xee, 0x89, + 0x86, 0x6f, 0xf6, 0xdd, 0x9f, 0x68, 0xf8, 0x52, 0x9e, 0xfa, 0x31, 0xd6, 0xb1, 0xf4, 0x65, 0x63, + 0x41, 0x94, 0x2e, 0x44, 0x60, 0x29, 0x8a, 0x8a, 0x09, 0x3a, 0x83, 0x6a, 0xe2, 0x81, 0x9e, 0x68, + 0x85, 0xa6, 0x3d, 0xff, 0x13, 0xad, 0xd0, 0xd4, 0x37, 0x7d, 0x14, 0x9d, 0x19, 0x8b, 0xa2, 0x1e, + 0xba, 0x4d, 0x4c, 0xab, 0xe9, 0xfb, 0x50, 0xd6, 0x1e, 0xdb, 0x89, 0xfa, 0x32, 0xfb, 0xae, 0x4f, + 0xd4, 0x97, 0xb4, 0xb7, 0x79, 0x96, 0xb1, 0x8e, 0x9a, 0x81, 0xa4, 0x80, 0x97, 0x21, 0x8b, 0xb2, + 0x7f, 0x1d, 0x6a, 0xc9, 0xf7, 0x77, 0xa2, 0xb5, 0x9f, 0xfa, 0x90, 0x4f, 0xb4, 0xf6, 0xaf, 0x79, + 0xb4, 0x47, 0x92, 0xf4, 0x83, 0xa5, 0xa8, 0x92, 0x87, 0x3f, 0x92, 0x47, 0xd7, 0xbe, 0x64, 0x9f, + 0x08, 0x06, 0x27, 0x2f, 0xeb, 0x66, 0x6b, 0x1a, 0xd5, 0xea, 0xb7, 0x7e, 0x47, 0xeb, 0x65, 0xe6, + 0x5e, 0xef, 0x24, 0x31, 0x63, 0xe1, 0xec, 0x29, 0x2c, 0x45, 0xc4, 0x1c, 0xdd, 0xbe, 0x1d, 0x44, + 0x7d, 0x48, 0xbd, 0xe3, 0x7b, 0xbd, 0x3e, 0x9d, 0xfa, 0x28, 0x43, 0xdb, 0x1f, 0x5e, 0x69, 0xac, + 0x6d, 0x7f, 0xfa, 0x05, 0xdc, 0xda, 0xf6, 0x97, 0xb8, 0xf9, 0x78, 0x7a, 0xfb, 0x0b, 0x1d, 0x51, + 0x86, 0x0b, 0x0b, 0xd3, 0x57, 0x5d, 0xdf, 0xbe, 0xee, 0x6a, 0x10, 0x2a, 0xfe, 0xf5, 0x17, 0xdf, + 0x1c, 0x92, 0x64, 0x45, 0x8a, 0x9b, 0x3e, 0x94, 0x91, 0x52, 0xec, 0x57, 0xa1, 0xa2, 0xbf, 0xd9, + 0xc1, 0x74, 0x9e, 0x30, 0x5d, 0xd3, 0xad, 0xd4, 0xb4, 0x24, 0x95, 0xb0, 0x8a, 0x5e, 0x0d, 0xfb, + 0x14, 0x56, 0xa3, 0x61, 0xd6, 0xef, 0xb6, 0x08, 0xd8, 0x9d, 0x94, 0x1b, 0x2f, 0x12, 0x83, 0x7d, + 0xf3, 0xda, 0x2b, 0x31, 0x1e, 0x65, 0x04, 0xf5, 0x25, 0xdf, 0x27, 0x88, 0x77, 0x9e, 0xb4, 0x67, + 0x19, 0xe2, 0x9d, 0x27, 0xf5, 0x51, 0x03, 0x45, 0x7d, 0x6c, 0x29, 0x31, 0x46, 0x14, 0x43, 0xce, + 0xbe, 0x0f, 0x0b, 0xda, 0xc5, 0x1d, 0xdd, 0x2b, 0xb7, 0x1f, 0xad, 0xa4, 0xd9, 0x4b, 0x6c, 0xd7, + 0xd3, 0x6c, 0xc6, 0xc6, 0x1a, 0x96, 0xbf, 0x68, 0x24, 0x06, 0x47, 0xac, 0xa2, 0x2d, 0x28, 0xeb, + 0x97, 0x82, 0xbc, 0xa0, 0xdc, 0x35, 0x2d, 0x49, 0xbf, 0x2f, 0xf5, 0x51, 0x86, 0xed, 0x41, 0x7d, + 0xfa, 0x0a, 0xbf, 0x88, 0xa7, 0xa4, 0x5d, 0x7b, 0xb8, 0x3e, 0x95, 0x98, 0xb8, 0xf8, 0x8f, 0x1d, + 0xd2, 0x29, 0xa4, 0xe8, 0xf9, 0x49, 0xcf, 0x9f, 0xde, 0xd5, 0x93, 0xcf, 0x52, 0x46, 0xa5, 0xa5, + 0x3d, 0x48, 0x7a, 0x3f, 0xf3, 0x28, 0xc3, 0x7e, 0x27, 0x03, 0x95, 0xc4, 0x15, 0x56, 0x89, 0x73, + 0x1e, 0x53, 0xfd, 0x6c, 0xe8, 0x69, 0x7a, 0x47, 0x0d, 0x13, 0x07, 0x71, 0xef, 0xc1, 0xf7, 0x12, + 0x93, 0xf4, 0xa3, 0x84, 0xcb, 0x75, 0x63, 0xfa, 0x7d, 0xca, 0x2f, 0xa7, 0x11, 0xf4, 0x6b, 0x91, + 0xbf, 0x7c, 0x94, 0x61, 0xff, 0x22, 0x03, 0xb5, 0x64, 0x2c, 0x45, 0xd4, 0xdd, 0xd4, 0xa8, 0x8d, + 0x88, 0x94, 0xae, 0x09, 0xc0, 0xf8, 0x3e, 0xb6, 0xb2, 0xf7, 0xc0, 0x4c, 0xb4, 0x52, 0xbe, 0xac, + 0xf1, 0xd3, 0xb5, 0x96, 0xfd, 0x22, 0x3d, 0x07, 0xad, 0xe2, 0xee, 0xd8, 0xec, 0xf3, 0xc1, 0x11, + 0xf9, 0xe9, 0x8f, 0xed, 0x1a, 0xb9, 0xdf, 0xc8, 0x66, 0x70, 0x26, 0x7e, 0x40, 0x8f, 0x31, 0xaa, + 0xd0, 0x2b, 0x41, 0xca, 0xaf, 0x5c, 0xc8, 0x5b, 0xd8, 0xb1, 0xd7, 0x8d, 0x9b, 0x89, 0x8e, 0x4d, + 0x4b, 0x1f, 0x4d, 0x6a, 0xa2, 0x7c, 0x30, 0x37, 0xde, 0x3e, 0x67, 0x1e, 0xd1, 0x4d, 0xad, 0x04, + 0x1b, 0x39, 0xa2, 0x46, 0x4a, 0xf4, 0xc4, 0x7a, 0x7b, 0xc5, 0x62, 0x8c, 0x07, 0xd8, 0xd6, 0xb7, + 0x8c, 0x3b, 0xd7, 0xb6, 0xf5, 0x21, 0x06, 0x47, 0x88, 0x16, 0x1f, 0x02, 0xc4, 0xc1, 0xb1, 0x6c, + 0x2a, 0x44, 0x33, 0xe2, 0x42, 0xb3, 0xf1, 0xb3, 0xc9, 0x45, 0xad, 0x22, 0x39, 0x45, 0x89, 0xbf, + 0x4c, 0x3c, 0x35, 0x0a, 0x1e, 0xd5, 0x45, 0xb0, 0x64, 0x1c, 0x6b, 0x42, 0x04, 0x9b, 0x2e, 0x3f, + 0xc1, 0x51, 0xa3, 0x48, 0xd1, 0x23, 0xa8, 0xee, 0x79, 0xde, 0xf3, 0xc9, 0x38, 0x3a, 0x90, 0x91, + 0x8c, 0x85, 0xda, 0xb5, 0x83, 0xb3, 0xf5, 0xa9, 0x5e, 0x18, 0x77, 0xb1, 0xa8, 0x75, 0xd6, 0xd0, + 0x8a, 0x7a, 0xf8, 0xa3, 0x38, 0x22, 0xf7, 0x4b, 0x66, 0xc3, 0x62, 0xc4, 0xa8, 0xe3, 0xa8, 0xd7, + 0x64, 0x31, 0x09, 0xf6, 0x3c, 0x5d, 0x45, 0x42, 0x57, 0x50, 0xad, 0x7d, 0x18, 0xa8, 0x32, 0x1f, + 0x65, 0xd8, 0x21, 0x54, 0xb6, 0x79, 0x1f, 0x6f, 0xf4, 0xc0, 0xb8, 0x9f, 0xa5, 0x44, 0x0c, 0x09, + 0x05, 0x0c, 0xad, 0x57, 0x13, 0xc0, 0xe4, 0xe6, 0x35, 0xb6, 0xaf, 0x7c, 0xfe, 0xc5, 0xc3, 0x1f, + 0xc9, 0x88, 0xa2, 0x2f, 0xd5, 0xe6, 0x15, 0x47, 0x97, 0xe9, 0x12, 0x40, 0x32, 0x44, 0x2b, 0xb1, + 0x79, 0xcd, 0x84, 0x68, 0x25, 0x86, 0x3a, 0x8a, 0x25, 0x1b, 0xc2, 0xe2, 0x4c, 0x54, 0x57, 0xb4, + 0x6f, 0x5d, 0x17, 0x0b, 0xb6, 0x7e, 0xf7, 0x7a, 0x84, 0x64, 0x6d, 0x0f, 0x92, 0xb5, 0x75, 0xa1, + 0x4a, 0x17, 0x1f, 0x1f, 0x73, 0x3a, 0xdb, 0x3b, 0x75, 0x31, 0x96, 0x7e, 0x70, 0x78, 0x7a, 0x97, + 0xc1, 0xb4, 0xa4, 0x98, 0x83, 0xa7, 0x3b, 0xd9, 0x09, 0x3e, 0x07, 0xa2, 0x1d, 0xa6, 0x8d, 0x88, + 0x71, 0xf6, 0x80, 0x6f, 0x44, 0x8c, 0x29, 0x67, 0x6f, 0x95, 0x0e, 0xca, 0x56, 0xa2, 0xb2, 0x1f, + 0xba, 0xde, 0x80, 0x8f, 0x64, 0xa9, 0xbf, 0x0c, 0xe5, 0xa7, 0x3c, 0x54, 0xa7, 0x57, 0x23, 0x81, + 0x7e, 0xea, 0x38, 0xeb, 0x7a, 0xca, 0x99, 0xe3, 0x24, 0x6d, 0x52, 0xc9, 0x7c, 0x70, 0xca, 0x89, + 0x13, 0x5a, 0xce, 0xe0, 0x4b, 0xf6, 0x4b, 0x58, 0x78, 0x74, 0x57, 0xc3, 0xaa, 0xd6, 0x4c, 0xbd, + 0xf0, 0x85, 0x29, 0x78, 0x5a, 0xc9, 0xa2, 0xcd, 0x9a, 0x60, 0xe9, 0x42, 0x59, 0xbb, 0xd3, 0x25, + 0x1a, 0x9b, 0xd9, 0x3b, 0x7c, 0xa2, 0xb1, 0x49, 0xb9, 0x02, 0xc6, 0xb8, 0x8f, 0xf5, 0x18, 0xec, + 0x6e, 0x5c, 0x0f, 0x5d, 0xfb, 0x12, 0xd7, 0xf4, 0xf0, 0x47, 0xf6, 0x28, 0xfc, 0x92, 0x7d, 0x46, + 0xd3, 0xa1, 0x9d, 0xce, 0x8d, 0x35, 0x94, 0xe9, 0x83, 0xbc, 0xd1, 0x60, 0x69, 0x49, 0x49, 0xad, + 0x85, 0xaa, 0x42, 0xb1, 0xf1, 0x09, 0x40, 0x37, 0xf4, 0xc6, 0xdb, 0x36, 0x1f, 0x79, 0x6e, 0xcc, + 0xd3, 0xe3, 0xf3, 0xa2, 0x31, 0x9f, 0xd4, 0x0e, 0x8d, 0xb2, 0xcf, 0x34, 0x95, 0x2e, 0x71, 0xae, + 0x5c, 0x11, 0xf1, 0xb5, 0x47, 0x4a, 0xa3, 0x01, 0x49, 0x39, 0x56, 0xfa, 0x28, 0xc3, 0x9a, 0x00, + 0x71, 0xf8, 0x60, 0xa4, 0xa0, 0xcd, 0x44, 0x26, 0x46, 0xec, 0x35, 0x25, 0xd6, 0xf0, 0x10, 0x4a, + 0x71, 0xdc, 0xd5, 0x5a, 0x7c, 0x45, 0x55, 0x22, 0x4a, 0x2b, 0x12, 0x17, 0x66, 0x62, 0x9e, 0x8c, + 0x3a, 0x0e, 0x15, 0xb0, 0xa2, 0x18, 0xaa, 0x13, 0xce, 0x03, 0xe6, 0xc0, 0x12, 0x35, 0x30, 0x92, + 0xcd, 0xf0, 0x9c, 0x63, 0xf4, 0x08, 0xcf, 0x6c, 0xf8, 0x51, 0xc4, 0x35, 0x52, 0x83, 0x68, 0x12, + 0x76, 0x26, 0x41, 0xad, 0x74, 0xc6, 0x52, 0x6c, 0x01, 0x23, 0x58, 0x9c, 0x89, 0xd3, 0x88, 0x58, + 0xc7, 0x75, 0x81, 0x37, 0x11, 0xeb, 0xb8, 0x36, 0xc4, 0xc3, 0x58, 0xc1, 0x2a, 0x17, 0x0c, 0x40, + 0xbd, 0xf2, 0xc2, 0x09, 0xfb, 0x67, 0xa2, 0xba, 0xdf, 0xcf, 0xc0, 0x52, 0x4a, 0x24, 0x06, 0x7b, + 0x43, 0x99, 0x28, 0xae, 0x8d, 0xd2, 0x58, 0x4f, 0xf5, 0xd8, 0x1b, 0x5d, 0xac, 0x67, 0x9f, 0x3d, + 0x4b, 0x6c, 0xa0, 0xe4, 0x30, 0x97, 0x2b, 0xf3, 0x85, 0x12, 0x4c, 0xaa, 0xf8, 0xf2, 0x05, 0xac, + 0x51, 0x43, 0x9a, 0xc3, 0xe1, 0x54, 0x34, 0xc1, 0xeb, 0x5a, 0x2b, 0x52, 0x22, 0x24, 0x12, 0xca, + 0x40, 0x32, 0x4a, 0xe2, 0x1a, 0xd9, 0x9d, 0x9a, 0xca, 0x26, 0x50, 0x9f, 0xf6, 0xd2, 0xb3, 0xeb, + 0xcb, 0x5a, 0xbf, 0x93, 0x50, 0xb6, 0x53, 0x3c, 0xfb, 0x5f, 0xc3, 0xca, 0xee, 0x18, 0xeb, 0x69, + 0xe3, 0x42, 0xfa, 0xb7, 0x98, 0x8f, 0xff, 0x3f, 0x0a, 0x29, 0x98, 0xea, 0xe7, 0x9d, 0xe8, 0x55, + 0x81, 0xf4, 0x00, 0x88, 0x48, 0xdd, 0x4f, 0x8f, 0x48, 0x78, 0x1b, 0xab, 0xbf, 0x6b, 0xdc, 0x4a, + 0xab, 0xde, 0xa7, 0x2c, 0xa4, 0xf8, 0xaf, 0x4d, 0xaf, 0x6b, 0xd5, 0x82, 0xbb, 0x69, 0xf3, 0x7d, + 0xad, 0xe2, 0x35, 0x35, 0xd6, 0x37, 0x50, 0x86, 0xac, 0xe8, 0x21, 0x04, 0xd1, 0xf2, 0x49, 0x89, + 0x55, 0x88, 0x96, 0x4f, 0x5a, 0xcc, 0x41, 0x52, 0x7e, 0x52, 0xd1, 0x06, 0x1f, 0x65, 0x1e, 0x6c, + 0xde, 0xfb, 0xfe, 0xd7, 0x4e, 0x9d, 0xf0, 0x6c, 0x72, 0xbc, 0xd1, 0xf7, 0x46, 0x0f, 0x87, 0xca, + 0xb4, 0x29, 0x2f, 0x03, 0x78, 0x38, 0x74, 0x07, 0x0f, 0xb1, 0xd8, 0xe3, 0xb9, 0xb1, 0xef, 0x85, + 0xde, 0x37, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x63, 0x6c, 0x5d, 0x30, 0x7e, 0x8b, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index d7af96a1b5..fdfd1857f0 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1660,6 +1660,9 @@ message GetInfoResponse { /// The version of the LND software that the node is running. string version = 14; + /// The SHA1 commit hash that the daemon is compiled with. + string commit_hash = 20; + /// The identity pubkey of the current node. string identity_pubkey = 1; diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 28941ae288..c588125da8 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -2923,6 +2923,10 @@ "type": "string", "description": "/ The version of the LND software that the node is running." }, + "commit_hash": { + "type": "string", + "description": "/ The SHA1 commit hash that the daemon is compiled with." + }, "identity_pubkey": { "type": "string", "description": "/ The identity pubkey of the current node." diff --git a/rpcserver.go b/rpcserver.go index 337cc2a1a0..666a5fb224 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2408,6 +2408,7 @@ func (r *rpcServer) GetInfo(ctx context.Context, Color: routing.EncodeHexColor(nodeAnn.RGBColor), BestHeaderTimestamp: int64(bestHeaderTimestamp), Version: build.Version() + " commit=" + build.Commit, + CommitHash: build.CommitHash, SyncedToGraph: isGraphSynced, Features: features, }, nil From f93a8ab7d085d7216e20f8a4c71749d281750b24 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 9 Apr 2020 17:07:05 -0700 Subject: [PATCH 469/562] cmd/lncli: add version command that reads verrpc.GetVersion --- cmd/lncli/cmd_version.go | 54 +++++++++++++++++++++++ cmd/lncli/main.go | 1 + lnrpc/lnclipb/lncli.pb.go | 91 +++++++++++++++++++++++++++++++++++++++ lnrpc/lnclipb/lncli.proto | 15 +++++++ 4 files changed, 161 insertions(+) create mode 100644 cmd/lncli/cmd_version.go create mode 100644 lnrpc/lnclipb/lncli.pb.go create mode 100644 lnrpc/lnclipb/lncli.proto diff --git a/cmd/lncli/cmd_version.go b/cmd/lncli/cmd_version.go new file mode 100644 index 0000000000..578129ed9a --- /dev/null +++ b/cmd/lncli/cmd_version.go @@ -0,0 +1,54 @@ +package main + +import ( + "context" + "fmt" + + "github.com/lightningnetwork/lnd/build" + "github.com/lightningnetwork/lnd/lnrpc/lnclipb" + "github.com/lightningnetwork/lnd/lnrpc/verrpc" + "github.com/urfave/cli" +) + +var versionCommand = cli.Command{ + Name: "version", + Usage: "Display lncli and lnd version info.", + Description: ` + Returns version information about both lncli and lnd. If lncli is unable + to connect to lnd, the command fails but still prints the lncli version. + `, + Action: actionDecorator(version), +} + +func version(ctx *cli.Context) error { + conn := getClientConn(ctx, false) + defer conn.Close() + + versions := &lnclipb.VersionResponse{ + Lncli: &verrpc.Version{ + Commit: build.Commit, + CommitHash: build.CommitHash, + Version: build.Version(), + AppMajor: uint32(build.AppMajor), + AppMinor: uint32(build.AppMinor), + AppPatch: uint32(build.AppPatch), + AppPreRelease: build.AppPreRelease, + BuildTags: build.Tags(), + GoVersion: build.GoVersion, + }, + } + + client := verrpc.NewVersionerClient(conn) + + ctxb := context.Background() + lndVersion, err := client.GetVersion(ctxb, &verrpc.VersionRequest{}) + if err != nil { + printRespJSON(versions) + return fmt.Errorf("unable fetch version from lnd: %v", err) + } + versions.Lnd = lndVersion + + printRespJSON(versions) + + return nil +} diff --git a/cmd/lncli/main.go b/cmd/lncli/main.go index 6f0640802f..a88fc926de 100644 --- a/cmd/lncli/main.go +++ b/cmd/lncli/main.go @@ -301,6 +301,7 @@ func main() { restoreChanBackupCommand, bakeMacaroonCommand, trackPaymentCommand, + versionCommand, } // Add any extra commands determined by build flags. diff --git a/lnrpc/lnclipb/lncli.pb.go b/lnrpc/lnclipb/lncli.pb.go new file mode 100644 index 0000000000..f6174d3d2d --- /dev/null +++ b/lnrpc/lnclipb/lncli.pb.go @@ -0,0 +1,91 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: lnclipb/lncli.proto + +package lnclipb + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + verrpc "github.com/lightningnetwork/lnd/lnrpc/verrpc" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type VersionResponse struct { + /// The version information for lncli. + Lncli *verrpc.Version `protobuf:"bytes,1,opt,name=lncli,proto3" json:"lncli,omitempty"` + /// The version information for lnd. + Lnd *verrpc.Version `protobuf:"bytes,2,opt,name=lnd,proto3" json:"lnd,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VersionResponse) Reset() { *m = VersionResponse{} } +func (m *VersionResponse) String() string { return proto.CompactTextString(m) } +func (*VersionResponse) ProtoMessage() {} +func (*VersionResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_88b54c9c61b986c4, []int{0} +} + +func (m *VersionResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VersionResponse.Unmarshal(m, b) +} +func (m *VersionResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VersionResponse.Marshal(b, m, deterministic) +} +func (m *VersionResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_VersionResponse.Merge(m, src) +} +func (m *VersionResponse) XXX_Size() int { + return xxx_messageInfo_VersionResponse.Size(m) +} +func (m *VersionResponse) XXX_DiscardUnknown() { + xxx_messageInfo_VersionResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_VersionResponse proto.InternalMessageInfo + +func (m *VersionResponse) GetLncli() *verrpc.Version { + if m != nil { + return m.Lncli + } + return nil +} + +func (m *VersionResponse) GetLnd() *verrpc.Version { + if m != nil { + return m.Lnd + } + return nil +} + +func init() { + proto.RegisterType((*VersionResponse)(nil), "lnclipb.VersionResponse") +} + +func init() { proto.RegisterFile("lnclipb/lncli.proto", fileDescriptor_88b54c9c61b986c4) } + +var fileDescriptor_88b54c9c61b986c4 = []byte{ + // 159 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xce, 0xc9, 0x4b, 0xce, + 0xc9, 0x2c, 0x48, 0xd2, 0x07, 0xd3, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xec, 0x50, 0x41, + 0x29, 0xe1, 0xb2, 0xd4, 0xa2, 0xa2, 0x82, 0x64, 0x7d, 0x08, 0x05, 0x91, 0x55, 0x8a, 0xe6, 0xe2, + 0x0f, 0x4b, 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0x0b, 0x4a, 0x2d, 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x15, + 0x52, 0xe5, 0x62, 0x05, 0x6b, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x36, 0xe2, 0xd7, 0x83, 0x6a, + 0x80, 0xa9, 0x83, 0xc8, 0x0a, 0x29, 0x72, 0x31, 0xe7, 0xe4, 0xa5, 0x48, 0x30, 0x61, 0x57, 0x04, + 0x92, 0x73, 0xd2, 0x8f, 0xd2, 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, + 0xcf, 0xc9, 0x4c, 0xcf, 0x28, 0xc9, 0xcb, 0xcc, 0x4b, 0xcf, 0x4b, 0x2d, 0x29, 0xcf, 0x2f, 0xca, + 0xd6, 0xcf, 0xc9, 0x4b, 0xd1, 0xcf, 0xc9, 0x03, 0x39, 0x09, 0xea, 0xc4, 0x24, 0x36, 0xb0, 0xa3, + 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x4d, 0xfc, 0x5e, 0x89, 0xc9, 0x00, 0x00, 0x00, +} diff --git a/lnrpc/lnclipb/lncli.proto b/lnrpc/lnclipb/lncli.proto new file mode 100644 index 0000000000..37286fd98b --- /dev/null +++ b/lnrpc/lnclipb/lncli.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +import "verrpc/verrpc.proto"; + +package lnclipb; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/lnclipb"; + +message VersionResponse { + /// The version information for lncli. + verrpc.Version lncli = 1; + + /// The version information for lnd. + verrpc.Version lnd = 2; +}; From f48c4cae3784092a7015709816319f49c17ac6dc Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 13 Apr 2020 11:45:02 -0700 Subject: [PATCH 470/562] fundingmanager: check remote peer upfront shutdown support before reservation This addresses a bug in which a funding reservation wasn't cleaned up properly if the remote peer didn't support upfront shutdown. Alternatively, we could just cancel the reservation on error, but instead we move the check above so that we don't attempt coin selection in the first place. --- fundingmanager.go | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index 761227c93b..95e6464ea5 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -3078,6 +3078,27 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { } } + // Check whether the peer supports upfront shutdown, and get an address + // which should be used (either a user specified address or a new + // address from the wallet if our node is configured to set shutdown + // address by default). + shutdown, err := getUpfrontShutdownScript( + msg.peer, msg.openChanReq.shutdownScript, + func() (lnwire.DeliveryAddress, error) { + addr, err := f.cfg.Wallet.NewAddress( + lnwallet.WitnessPubKey, false, + ) + if err != nil { + return nil, err + } + return txscript.PayToAddrScript(addr) + }, + ) + if err != nil { + msg.err <- err + return + } + // Initialize a funding reservation with the local wallet. If the // wallet doesn't have enough funds to commit to this channel, then the // request will fail, and be aborted. @@ -3112,24 +3133,6 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { return } - // Check whether the peer supports upfront shutdown, and get an address which - // should be used (either a user specified address or a new address from the - // wallet if our node is configured to set shutdown address by default). - shutdown, err := getUpfrontShutdownScript( - msg.peer, msg.openChanReq.shutdownScript, - func() (lnwire.DeliveryAddress, error) { - addr, err := f.cfg.Wallet.NewAddress(lnwallet.WitnessPubKey, false) - if err != nil { - return nil, err - } - return txscript.PayToAddrScript(addr) - }, - ) - if err != nil { - msg.err <- err - return - } - // Set our upfront shutdown address in the existing reservation. reservation.SetOurUpfrontShutdown(shutdown) From d6fa2f90925b543df22503e1edaf75b5c3bb1e77 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 10 Apr 2020 16:23:49 -0700 Subject: [PATCH 471/562] peer: filter channels loaded into switch via whitelist This is less brittle than blacklisting states since it may not be clear that new states needs to be added. Now that HasChanStatus is fixed for ChanStatusDefault, we can safely implement this. --- peer.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/peer.go b/peer.go index 492c8f04a1..c6e2ae0251 100644 --- a/peer.go +++ b/peer.go @@ -504,13 +504,9 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) ( // Skip adding any permanently irreconcilable channels to the // htlcswitch. switch { - case dbChan.HasChanStatus(channeldb.ChanStatusBorked): - fallthrough - case dbChan.HasChanStatus(channeldb.ChanStatusCommitBroadcasted): - fallthrough - case dbChan.HasChanStatus(channeldb.ChanStatusCoopBroadcasted): - fallthrough - case dbChan.HasChanStatus(channeldb.ChanStatusLocalDataLoss): + case !dbChan.HasChanStatus(channeldb.ChanStatusDefault) && + !dbChan.HasChanStatus(channeldb.ChanStatusRestored): + peerLog.Warnf("ChannelPoint(%v) has status %v, won't "+ "start.", chanPoint, dbChan.ChanStatus()) From 84e577af450dffdfcecbf7b5957d0efffd3273e2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 13 Apr 2020 17:02:32 -0700 Subject: [PATCH 472/562] build: update to latest btcutil and psbt versions The latest versions of the `psbt` package includes some decoding bug fixes. --- go.mod | 4 ++-- go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 27824c1b8d..54f57f80ff 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2 github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d - github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059 + github.com/btcsuite/btcutil v1.0.2 + github.com/btcsuite/btcutil/psbt v1.0.2 github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 diff --git a/go.sum b/go.sum index 09469ecf0d..c58f8025ad 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,10 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059 h1:RU+MRFz83kf5hgJrGryakeYv/Xj2wZ7pwu9Eb7tna30= -github.com/btcsuite/btcutil/psbt v1.0.2-0.20200323233600-8bf941f57059/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil/psbt v1.0.2 h1:gCVY3KxdoEVU7Q6TjusPO+GANIwVgr9yTLqM+a6CZr8= +github.com/btcsuite/btcutil/psbt v1.0.2/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb h1:kkq2SSCy+OrC7GVZLIqutoHVR2yW4SJQdX70jtmuLDI= github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb/go.mod h1:9fJNm1aXi4q9P5Nk23mmqppCy1Le3f2/JMWj9UXKkCc= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= From d4823161d8612202136b48b2ba16ee31408967f9 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 13 Apr 2020 23:45:02 -0700 Subject: [PATCH 473/562] lnrpc/verrpc: correct mispelling of compilation --- lnrpc/verrpc/verrpc.pb.go | 2 +- lnrpc/verrpc/verrpc.proto | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lnrpc/verrpc/verrpc.pb.go b/lnrpc/verrpc/verrpc.pb.go index a3bd4994be..00cb36427c 100644 --- a/lnrpc/verrpc/verrpc.pb.go +++ b/lnrpc/verrpc/verrpc.pb.go @@ -68,7 +68,7 @@ type Version struct { AppPatch uint32 `protobuf:"varint,6,opt,name=app_patch,json=appPatch,proto3" json:"app_patch,omitempty"` /// The application pre-release modifier, possibly empty. AppPreRelease string `protobuf:"bytes,7,opt,name=app_pre_release,json=appPreRelease,proto3" json:"app_pre_release,omitempty"` - /// The list of build tags that were supplied during comilation. + /// The list of build tags that were supplied during compilation. BuildTags []string `protobuf:"bytes,8,rep,name=build_tags,json=buildTags,proto3" json:"build_tags,omitempty"` /// The version of go that compiled the executable. GoVersion string `protobuf:"bytes,9,opt,name=go_version,json=goVersion,proto3" json:"go_version,omitempty"` diff --git a/lnrpc/verrpc/verrpc.proto b/lnrpc/verrpc/verrpc.proto index 9e139a710d..1ec3a24119 100644 --- a/lnrpc/verrpc/verrpc.proto +++ b/lnrpc/verrpc/verrpc.proto @@ -33,7 +33,7 @@ message Version { /// The application pre-release modifier, possibly empty. string app_pre_release = 7; - /// The list of build tags that were supplied during comilation. + /// The list of build tags that were supplied during compilation. repeated string build_tags = 8; /// The version of go that compiled the executable. From 969eecc7d289b5cb811b12c2c40e068d54262e50 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 14 Apr 2020 10:10:12 +0200 Subject: [PATCH 474/562] routing+routerrpc+lncli: rename MaxHtlcs to MaxShards --- cmd/lncli/cmd_pay.go | 8 +- lnrpc/routerrpc/router.pb.go | 250 ++++++++++---------- lnrpc/routerrpc/router.proto | 2 +- lnrpc/routerrpc/router_backend.go | 8 +- lntest/itest/lnd_send_multi_path_payment.go | 2 +- routing/integrated_routing_context_test.go | 4 +- routing/integrated_routing_test.go | 10 +- routing/payment_session.go | 2 +- routing/router.go | 6 +- rpcserver.go | 2 +- 10 files changed, 147 insertions(+), 147 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 426c751666..78f5167e1a 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -53,8 +53,8 @@ var ( "displayed", } - maxHtlcsFlag = cli.UintFlag{ - Name: "max_htlcs", + maxShardsFlag = cli.UintFlag{ + Name: "max_shards", Usage: "the maximum number of partial payments that may be " + "used", Value: 1, @@ -95,7 +95,7 @@ func paymentFlags() []cli.Flag { Name: "allow_self_payment", Usage: "allow sending a circular payment to self", }, - dataFlag, showInflightFlag, maxHtlcsFlag, + dataFlag, showInflightFlag, maxShardsFlag, } } @@ -325,7 +325,7 @@ func sendPaymentRequest(ctx *cli.Context, req.AllowSelfPayment = ctx.Bool("allow_self_payment") - req.MaxHtlcs = uint32(ctx.Uint(maxHtlcsFlag.Name)) + req.MaxShards = uint32(ctx.Uint(maxShardsFlag.Name)) // Parse custom data records. data := ctx.String(dataFlag.Name) diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 018c3d8c32..c5d8feae38 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -225,7 +225,7 @@ type SendPaymentRequest struct { //* //The maximum number of partial payments that may be use to complete the full //amount. - MaxHtlcs uint32 `protobuf:"varint,17,opt,name=max_htlcs,json=maxHtlcs,proto3" json:"max_htlcs,omitempty"` + MaxShards uint32 `protobuf:"varint,17,opt,name=max_shards,json=maxShards,proto3" json:"max_shards,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -368,9 +368,9 @@ func (m *SendPaymentRequest) GetDestFeatures() []lnrpc.FeatureBit { return nil } -func (m *SendPaymentRequest) GetMaxHtlcs() uint32 { +func (m *SendPaymentRequest) GetMaxShards() uint32 { if m != nil { - return m.MaxHtlcs + return m.MaxShards } return 0 } @@ -1606,135 +1606,135 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2039 bytes of a gzipped FileDescriptorProto + // 2040 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xcd, 0x76, 0xdb, 0xc6, 0x15, 0x0e, 0x44, 0x50, 0x22, 0x2f, 0xff, 0xa0, 0xa1, 0x23, 0xb3, 0x54, 0x9c, 0x32, 0x68, 0x63, 0xf3, 0xb8, 0xae, 0xe4, 0xa8, 0x3d, 0xad, 0x4f, 0xdb, 0xb8, 0xa5, 0x08, 0x28, 0x82, 0x45, 0x01, 0xcc, 0x10, 0xb2, 0x9d, 0x7a, 0x31, 0x07, 0x22, 0x87, 0x22, 0x2a, 0xfc, 0xb0, 0xc0, 0xd0, 0x8e, - 0x96, 0xdd, 0x76, 0xdf, 0x67, 0xe8, 0x4b, 0xf4, 0x5d, 0xba, 0xed, 0xae, 0xbb, 0xae, 0x7b, 0x66, - 0x00, 0x90, 0xa0, 0x44, 0x39, 0xd9, 0xd8, 0x9c, 0xef, 0x7e, 0x73, 0xe7, 0xde, 0xb9, 0xdf, 0x9d, - 0x19, 0x08, 0xf6, 0xa2, 0x70, 0xc1, 0x68, 0x14, 0xcd, 0xc7, 0x87, 0xc9, 0xaf, 0x83, 0x79, 0x14, - 0xb2, 0x10, 0x95, 0x97, 0x78, 0xbb, 0x1c, 0xcd, 0xc7, 0x09, 0xaa, 0xfe, 0x63, 0x1b, 0xd0, 0x88, - 0x06, 0x93, 0xa1, 0x73, 0xe3, 0xd3, 0x80, 0x61, 0xfa, 0xd7, 0x05, 0x8d, 0x19, 0x42, 0x20, 0x4f, - 0x68, 0xcc, 0x5a, 0x52, 0x47, 0xea, 0x56, 0xb1, 0xf8, 0x8d, 0x14, 0x28, 0x38, 0x3e, 0x6b, 0x6d, - 0x75, 0xa4, 0x6e, 0x01, 0xf3, 0x9f, 0xe8, 0x27, 0x50, 0x72, 0x7c, 0x46, 0xfc, 0xd8, 0x61, 0xad, - 0xaa, 0x80, 0x77, 0x1c, 0x9f, 0x9d, 0xc7, 0x0e, 0x43, 0x5f, 0x40, 0x75, 0x9e, 0xb8, 0x24, 0x33, - 0x27, 0x9e, 0xb5, 0x0a, 0xc2, 0x51, 0x25, 0xc5, 0x4e, 0x9d, 0x78, 0x86, 0xba, 0xa0, 0x4c, 0xdd, - 0xc0, 0xf1, 0xc8, 0xd8, 0x63, 0xef, 0xc9, 0x84, 0x7a, 0xcc, 0x69, 0xc9, 0x1d, 0xa9, 0x5b, 0xc4, - 0x75, 0x81, 0xf7, 0x3d, 0xf6, 0x5e, 0xe3, 0x28, 0x7a, 0x02, 0x8d, 0xcc, 0x59, 0x94, 0x04, 0xd8, - 0x2a, 0x76, 0xa4, 0x6e, 0x19, 0xd7, 0xe7, 0xeb, 0x61, 0x3f, 0x81, 0x06, 0x73, 0x7d, 0x1a, 0x2e, - 0x18, 0x89, 0xe9, 0x38, 0x0c, 0x26, 0x71, 0x6b, 0x3b, 0xf1, 0x98, 0xc2, 0xa3, 0x04, 0x45, 0x2a, - 0xd4, 0xa6, 0x94, 0x12, 0xcf, 0xf5, 0x5d, 0x46, 0x78, 0xf8, 0x3b, 0x22, 0xfc, 0xca, 0x94, 0xd2, - 0x01, 0xc7, 0x46, 0x0e, 0x43, 0x3f, 0x87, 0xfa, 0x8a, 0x23, 0x72, 0xac, 0x09, 0x52, 0x35, 0x23, - 0x89, 0x44, 0x9f, 0x81, 0x12, 0x2e, 0xd8, 0x55, 0xe8, 0x06, 0x57, 0x64, 0x3c, 0x73, 0x02, 0xe2, - 0x4e, 0x5a, 0xa5, 0x8e, 0xd4, 0x95, 0x8f, 0xb7, 0x9e, 0x4b, 0xb8, 0x9e, 0xd9, 0xfa, 0x33, 0x27, - 0x30, 0x26, 0xe8, 0x31, 0x34, 0x3c, 0x27, 0x66, 0x64, 0x16, 0xce, 0xc9, 0x7c, 0x71, 0x79, 0x4d, - 0x6f, 0x5a, 0x75, 0xb1, 0x33, 0x35, 0x0e, 0x9f, 0x86, 0xf3, 0xa1, 0x00, 0xd1, 0x23, 0x00, 0xb1, - 0x2b, 0x62, 0xf1, 0x56, 0x59, 0xe4, 0x50, 0xe6, 0x88, 0x58, 0x18, 0x7d, 0x05, 0x15, 0x51, 0x4d, - 0x32, 0x73, 0x03, 0x16, 0xb7, 0xa0, 0x53, 0xe8, 0x56, 0x8e, 0x94, 0x03, 0x2f, 0xe0, 0x85, 0xc5, - 0xdc, 0x72, 0xea, 0x06, 0x0c, 0x43, 0x94, 0xfd, 0x8c, 0xd1, 0x04, 0x9a, 0xbc, 0x8a, 0x64, 0xbc, - 0x88, 0x59, 0xe8, 0x93, 0x88, 0x8e, 0xc3, 0x68, 0x12, 0xb7, 0x2a, 0x62, 0xea, 0xaf, 0x0f, 0x96, - 0xe2, 0x38, 0xb8, 0xab, 0x86, 0x03, 0x8d, 0xc6, 0xac, 0x2f, 0xe6, 0xe1, 0x64, 0x9a, 0x1e, 0xb0, + 0x96, 0xdd, 0xf6, 0x05, 0xfa, 0x08, 0x7d, 0x89, 0xbe, 0x4b, 0xb7, 0xdd, 0x75, 0xd7, 0x75, 0xcf, + 0x0c, 0x00, 0x12, 0x94, 0x28, 0x27, 0x1b, 0x09, 0xf8, 0xee, 0x37, 0x77, 0xee, 0x9d, 0xfb, 0xdd, + 0x99, 0x01, 0x61, 0x2f, 0x0a, 0x17, 0x8c, 0x46, 0xd1, 0x7c, 0x7c, 0x98, 0x3c, 0x1d, 0xcc, 0xa3, + 0x90, 0x85, 0xa8, 0xbc, 0xc4, 0xdb, 0xe5, 0x68, 0x3e, 0x4e, 0x50, 0xf5, 0x1f, 0xdb, 0x80, 0x46, + 0x34, 0x98, 0x0c, 0x9d, 0x1b, 0x9f, 0x06, 0x0c, 0xd3, 0xbf, 0x2e, 0x68, 0xcc, 0x10, 0x02, 0x79, + 0x42, 0x63, 0xd6, 0x92, 0x3a, 0x52, 0xb7, 0x8a, 0xc5, 0x33, 0x52, 0xa0, 0xe0, 0xf8, 0xac, 0xb5, + 0xd5, 0x91, 0xba, 0x05, 0xcc, 0x1f, 0xd1, 0x4f, 0xa0, 0xe4, 0xf8, 0x8c, 0xf8, 0xb1, 0xc3, 0x5a, + 0x55, 0x01, 0xef, 0x38, 0x3e, 0x3b, 0x8f, 0x1d, 0x86, 0xbe, 0x80, 0xea, 0x3c, 0x71, 0x49, 0x66, + 0x4e, 0x3c, 0x6b, 0x15, 0x84, 0xa3, 0x4a, 0x8a, 0x9d, 0x3a, 0xf1, 0x0c, 0x75, 0x41, 0x99, 0xba, + 0x81, 0xe3, 0x91, 0xb1, 0xc7, 0xde, 0x93, 0x09, 0xf5, 0x98, 0xd3, 0x92, 0x3b, 0x52, 0xb7, 0x88, + 0xeb, 0x02, 0xef, 0x7b, 0xec, 0xbd, 0xc6, 0x51, 0xf4, 0x04, 0x1a, 0x99, 0xb3, 0x28, 0x09, 0xb0, + 0x55, 0xec, 0x48, 0xdd, 0x32, 0xae, 0xcf, 0xd7, 0xc3, 0x7e, 0x02, 0x0d, 0xe6, 0xfa, 0x34, 0x5c, + 0x30, 0x12, 0xd3, 0x71, 0x18, 0x4c, 0xe2, 0xd6, 0x76, 0xe2, 0x31, 0x85, 0x47, 0x09, 0x8a, 0x54, + 0xa8, 0x4d, 0x29, 0x25, 0x9e, 0xeb, 0xbb, 0x8c, 0xf0, 0xf0, 0x77, 0x44, 0xf8, 0x95, 0x29, 0xa5, + 0x03, 0x8e, 0x8d, 0x1c, 0x86, 0x7e, 0x0e, 0xf5, 0x15, 0x47, 0xe4, 0x58, 0x13, 0xa4, 0x6a, 0x46, + 0x12, 0x89, 0x3e, 0x03, 0x25, 0x5c, 0xb0, 0xab, 0xd0, 0x0d, 0xae, 0xc8, 0x78, 0xe6, 0x04, 0xc4, + 0x9d, 0xb4, 0x4a, 0x1d, 0xa9, 0x2b, 0x1f, 0x6f, 0x3d, 0x97, 0x70, 0x3d, 0xb3, 0xf5, 0x67, 0x4e, + 0x60, 0x4c, 0xd0, 0x63, 0x68, 0x78, 0x4e, 0xcc, 0xc8, 0x2c, 0x9c, 0x93, 0xf9, 0xe2, 0xf2, 0x9a, + 0xde, 0xb4, 0xea, 0x62, 0x65, 0x6a, 0x1c, 0x3e, 0x0d, 0xe7, 0x43, 0x01, 0xa2, 0x47, 0x00, 0x62, + 0x55, 0xc4, 0xe4, 0xad, 0xb2, 0xc8, 0xa1, 0xcc, 0x11, 0x31, 0x31, 0xfa, 0x0a, 0x2a, 0xa2, 0x9a, + 0x64, 0xe6, 0x06, 0x2c, 0x6e, 0x41, 0xa7, 0xd0, 0xad, 0x1c, 0x29, 0x07, 0x5e, 0xc0, 0x0b, 0x8b, + 0xb9, 0xe5, 0xd4, 0x0d, 0x18, 0x86, 0x28, 0x7b, 0x8c, 0xd1, 0x04, 0x9a, 0xbc, 0x8a, 0x64, 0xbc, + 0x88, 0x59, 0xe8, 0x93, 0x88, 0x8e, 0xc3, 0x68, 0x12, 0xb7, 0x2a, 0x62, 0xe8, 0xaf, 0x0f, 0x96, + 0xe2, 0x38, 0xb8, 0xab, 0x86, 0x03, 0x8d, 0xc6, 0xac, 0x2f, 0xc6, 0xe1, 0x64, 0x98, 0x1e, 0xb0, 0xe8, 0x06, 0xef, 0x4e, 0x6e, 0xe3, 0xe8, 0x19, 0x20, 0xc7, 0xf3, 0xc2, 0x0f, 0x24, 0xa6, 0xde, 0x94, 0xa4, 0xd5, 0x69, 0x35, 0x3a, 0x52, 0xb7, 0x84, 0x15, 0x61, 0x19, 0x51, 0x6f, 0x9a, 0xba, 0x47, 0xbf, 0x81, 0x9a, 0x88, 0x69, 0x4a, 0x1d, 0xb6, 0x88, 0x68, 0xdc, 0x52, 0x3a, 0x85, 0x6e, - 0xfd, 0x68, 0x37, 0x4d, 0xe4, 0x24, 0x81, 0x8f, 0x5d, 0x86, 0xab, 0x9c, 0x97, 0x8e, 0x63, 0xb4, - 0x0f, 0x65, 0xdf, 0xf9, 0x9e, 0xcc, 0x98, 0x37, 0x8e, 0x5b, 0xbb, 0x1d, 0xa9, 0x5b, 0xc3, 0x25, - 0xdf, 0xf9, 0xfe, 0x94, 0x8f, 0xdb, 0x1a, 0xec, 0x6d, 0x8e, 0x97, 0x0b, 0x98, 0x6f, 0x38, 0xd7, - 0xb4, 0x8c, 0xf9, 0x4f, 0xf4, 0x00, 0x8a, 0xef, 0x1d, 0x6f, 0x41, 0x85, 0xa8, 0xab, 0x38, 0x19, - 0xfc, 0x6e, 0xeb, 0x85, 0xa4, 0xbe, 0x80, 0xa6, 0x1d, 0x39, 0xe3, 0xeb, 0x5b, 0x7d, 0x71, 0x5b, - 0xd6, 0xd2, 0x1d, 0x59, 0xab, 0x2f, 0xa1, 0x21, 0x2a, 0x70, 0x42, 0xe9, 0xc7, 0xba, 0xe9, 0x21, - 0xf0, 0x5e, 0x11, 0xda, 0x4b, 0x3a, 0x6a, 0xdb, 0xf1, 0xb9, 0xec, 0xd4, 0x09, 0x28, 0xab, 0xf9, - 0xf1, 0x3c, 0x0c, 0x62, 0xca, 0x5b, 0x85, 0x17, 0x88, 0x6b, 0x8c, 0x4b, 0x52, 0x88, 0x51, 0x12, - 0xb3, 0xea, 0x29, 0x7e, 0x42, 0xa9, 0x90, 0xe3, 0xe3, 0xa4, 0x03, 0x88, 0x17, 0x8e, 0xaf, 0x79, - 0x4f, 0x39, 0x37, 0xa9, 0xfb, 0x1a, 0x87, 0x07, 0xe1, 0xf8, 0x5a, 0xe3, 0xa0, 0xfa, 0x2e, 0x69, - 0x7b, 0x3b, 0x14, 0x6b, 0xfd, 0xf8, 0xf4, 0x90, 0x0a, 0x45, 0xa1, 0x15, 0xe1, 0xb6, 0x72, 0x54, - 0xcd, 0x8b, 0x0e, 0x27, 0x26, 0xf5, 0x1d, 0x34, 0xd7, 0x9c, 0xa7, 0x59, 0xb4, 0xa1, 0x34, 0x8f, - 0xa8, 0xeb, 0x3b, 0x57, 0x34, 0xf5, 0xbc, 0x1c, 0xa3, 0x2e, 0xec, 0x4c, 0x1d, 0xd7, 0x5b, 0x44, - 0x99, 0xe3, 0x7a, 0x26, 0x82, 0x04, 0xc5, 0x99, 0x59, 0xfd, 0x0c, 0xda, 0x98, 0xc6, 0x94, 0x9d, - 0xbb, 0x71, 0xec, 0x86, 0x41, 0x3f, 0x0c, 0x58, 0x14, 0x7a, 0x69, 0x06, 0xea, 0x23, 0xd8, 0xdf, - 0x68, 0x4d, 0x42, 0xe0, 0x93, 0xbf, 0x5d, 0xd0, 0xe8, 0x66, 0xf3, 0xe4, 0x6f, 0x61, 0x7f, 0xa3, - 0x35, 0x8d, 0xff, 0x19, 0x14, 0xe7, 0x8e, 0x1b, 0xc5, 0xad, 0x2d, 0xd1, 0x34, 0x7b, 0xb9, 0xa6, - 0x19, 0x3a, 0x6e, 0x74, 0xea, 0xc6, 0x2c, 0x8c, 0x6e, 0x70, 0x42, 0x7a, 0x25, 0x97, 0x24, 0x65, - 0x4b, 0xfd, 0xbb, 0x04, 0x95, 0x9c, 0x91, 0x4b, 0x37, 0x08, 0x27, 0x94, 0x4c, 0xa3, 0xd0, 0xcf, - 0x36, 0x81, 0x03, 0x27, 0x51, 0xe8, 0x73, 0x4d, 0x08, 0x23, 0x0b, 0x53, 0x41, 0x6e, 0xf3, 0xa1, - 0x1d, 0xa2, 0x5f, 0xc2, 0xce, 0x2c, 0x71, 0x20, 0x0e, 0xaa, 0xca, 0x51, 0xf3, 0xd6, 0xda, 0x9a, - 0xc3, 0x1c, 0x9c, 0x71, 0x5e, 0xc9, 0xa5, 0x82, 0x22, 0xbf, 0x92, 0x4b, 0xb2, 0x52, 0x7c, 0x25, - 0x97, 0x8a, 0xca, 0xf6, 0x2b, 0xb9, 0xb4, 0xad, 0xec, 0xa8, 0xff, 0x91, 0xa0, 0x94, 0xb1, 0x79, - 0x24, 0x7c, 0x4b, 0x09, 0xd7, 0x45, 0x2a, 0xa6, 0x12, 0x07, 0x6c, 0xd7, 0xa7, 0xa8, 0x03, 0x55, - 0x61, 0x5c, 0x97, 0x28, 0x70, 0xac, 0x27, 0x64, 0x2a, 0x4e, 0xd0, 0x8c, 0x21, 0xf4, 0x28, 0xa7, - 0x27, 0x68, 0x42, 0xc9, 0x2e, 0x81, 0x78, 0x31, 0x1e, 0xd3, 0x38, 0x4e, 0x56, 0x29, 0x26, 0x94, - 0x14, 0x13, 0x0b, 0x3d, 0x86, 0x46, 0x46, 0xc9, 0xd6, 0xda, 0x4e, 0xf4, 0x9a, 0xc2, 0xe9, 0x72, - 0x5d, 0x50, 0xf2, 0x3c, 0x7f, 0x75, 0x66, 0xd7, 0x57, 0x44, 0xbe, 0x68, 0x92, 0xbc, 0xfa, 0x17, - 0x78, 0x28, 0x4a, 0x39, 0x8c, 0xc2, 0x4b, 0xe7, 0xd2, 0xf5, 0x5c, 0x76, 0x93, 0x89, 0x9c, 0x27, - 0x1e, 0x85, 0x3e, 0xe1, 0x7b, 0x9b, 0x95, 0x80, 0x03, 0x66, 0x38, 0xa1, 0xbc, 0x04, 0x2c, 0x4c, - 0x4c, 0x69, 0x09, 0x58, 0x28, 0x0c, 0xf9, 0xbb, 0xae, 0xb0, 0x76, 0xd7, 0xa9, 0xd7, 0xd0, 0xba, - 0xbb, 0x56, 0xaa, 0x99, 0x0e, 0x54, 0xe6, 0x2b, 0x58, 0x2c, 0x27, 0xe1, 0x3c, 0x94, 0xaf, 0xed, - 0xd6, 0x0f, 0xd7, 0x56, 0xfd, 0xa7, 0x04, 0xbb, 0xc7, 0x0b, 0xd7, 0x9b, 0xac, 0x35, 0x6e, 0x3e, - 0x3a, 0x69, 0xfd, 0x26, 0xde, 0x74, 0xcd, 0x6e, 0x6d, 0xbc, 0x66, 0x37, 0x5d, 0x65, 0x85, 0x7b, - 0xaf, 0xb2, 0x9f, 0x42, 0x65, 0x75, 0x8b, 0xc5, 0x2d, 0xb9, 0x53, 0xe8, 0x56, 0x31, 0xcc, 0xb2, - 0x2b, 0x2c, 0x56, 0x5f, 0x00, 0xca, 0x07, 0x9a, 0x6e, 0xc8, 0xf2, 0xfc, 0x90, 0xee, 0x3f, 0x3f, - 0x3e, 0x83, 0xf6, 0x68, 0x71, 0x19, 0x8f, 0x23, 0xf7, 0x92, 0xf2, 0x43, 0x5d, 0x7f, 0x4f, 0x03, - 0x16, 0x67, 0x5d, 0xfa, 0x3f, 0x19, 0xca, 0x4b, 0x14, 0x1d, 0x40, 0xd3, 0x0d, 0xc6, 0xa1, 0x9f, - 0x05, 0x1d, 0x50, 0x8f, 0xc7, 0x9d, 0x1c, 0xf2, 0xbb, 0x99, 0xa9, 0x9f, 0x58, 0x8c, 0x09, 0xe7, - 0xaf, 0x25, 0x99, 0xf2, 0xb7, 0x12, 0x7e, 0x3e, 0xc7, 0x84, 0xdf, 0x05, 0x65, 0xe9, 0x9f, 0x5f, - 0x38, 0xcb, 0x4d, 0xc1, 0xf5, 0x0c, 0xe7, 0xc1, 0x24, 0xcc, 0xa5, 0xe7, 0x8c, 0x29, 0x27, 0xcc, - 0x0c, 0x4f, 0x99, 0x5f, 0x40, 0x95, 0xf7, 0x43, 0xcc, 0x1c, 0x7f, 0x4e, 0x82, 0x58, 0xf4, 0x85, - 0x8c, 0x2b, 0x4b, 0xcc, 0x8c, 0xd1, 0xd7, 0x00, 0x94, 0xe7, 0x47, 0xd8, 0xcd, 0x9c, 0x8a, 0x96, - 0xa8, 0x1f, 0x7d, 0x9e, 0x13, 0xc6, 0x72, 0x03, 0x0e, 0xc4, 0xbf, 0xf6, 0xcd, 0x9c, 0xe2, 0x32, - 0xcd, 0x7e, 0xa2, 0x97, 0x50, 0x9b, 0x86, 0xd1, 0x07, 0x27, 0x9a, 0x10, 0x01, 0xa6, 0xc7, 0xc6, - 0xc3, 0x9c, 0x87, 0x93, 0xc4, 0x2e, 0xa6, 0x9f, 0x7e, 0x82, 0xab, 0xd3, 0xdc, 0x18, 0x9d, 0x01, - 0xca, 0xe6, 0x8b, 0x2e, 0x4f, 0x9c, 0x94, 0x84, 0x93, 0xfd, 0xbb, 0x4e, 0xf8, 0x21, 0x9d, 0x39, - 0x52, 0xa6, 0xb7, 0x30, 0xf4, 0x7b, 0xa8, 0xc6, 0x94, 0x31, 0x8f, 0xa6, 0x6e, 0xca, 0xc2, 0xcd, - 0xde, 0xda, 0x9b, 0x83, 0x9b, 0x33, 0x0f, 0x95, 0x78, 0x35, 0x44, 0xc7, 0xd0, 0xf0, 0xdc, 0xe0, - 0x3a, 0x1f, 0x06, 0x88, 0xf9, 0xad, 0xdc, 0xfc, 0x81, 0x1b, 0x5c, 0xe7, 0x63, 0xa8, 0x79, 0x79, - 0x40, 0xfd, 0x03, 0x94, 0x97, 0xbb, 0x84, 0x2a, 0xb0, 0x73, 0x61, 0x9e, 0x99, 0xd6, 0x1b, 0x53, - 0xf9, 0x04, 0x95, 0x40, 0x1e, 0xe9, 0xa6, 0xa6, 0x48, 0x1c, 0xc6, 0x7a, 0x5f, 0x37, 0x5e, 0xeb, - 0xca, 0x16, 0x1f, 0x9c, 0x58, 0xf8, 0x4d, 0x0f, 0x6b, 0x4a, 0xe1, 0x78, 0x07, 0x8a, 0x62, 0x5d, - 0xf5, 0x5f, 0x12, 0x94, 0x44, 0x05, 0x83, 0x69, 0x88, 0x7e, 0x01, 0x4b, 0x71, 0x89, 0xc3, 0x8d, - 0x5f, 0xb8, 0x42, 0x75, 0x35, 0xbc, 0x14, 0x8c, 0x9d, 0xe2, 0x9c, 0xbc, 0x94, 0xc6, 0x92, 0xbc, - 0x95, 0x90, 0x33, 0xc3, 0x92, 0xfc, 0x34, 0xe7, 0x79, 0xed, 0xc8, 0x91, 0x71, 0x23, 0x33, 0x64, - 0x27, 0xec, 0xd3, 0x9c, 0xe3, 0xb5, 0x93, 0x58, 0xc6, 0x8d, 0xcc, 0x90, 0x72, 0xd5, 0xdf, 0x42, - 0x35, 0x5f, 0x73, 0xf4, 0x04, 0x64, 0x37, 0x98, 0x86, 0x69, 0x23, 0x36, 0x6f, 0x89, 0x8b, 0x27, - 0x89, 0x05, 0x41, 0x45, 0xa0, 0xdc, 0xae, 0xb3, 0x5a, 0x83, 0x4a, 0xae, 0x68, 0xea, 0xbf, 0x25, - 0xa8, 0xad, 0x15, 0xe1, 0x47, 0x7b, 0x47, 0x5f, 0x43, 0xf5, 0x83, 0x1b, 0x51, 0x92, 0xbf, 0xfe, - 0xeb, 0x47, 0xed, 0xf5, 0xeb, 0x3f, 0xfb, 0xbf, 0x1f, 0x4e, 0x28, 0xae, 0x70, 0x7e, 0x0a, 0xa0, - 0x3f, 0x42, 0x3d, 0x9d, 0x49, 0x26, 0x94, 0x39, 0xae, 0x27, 0xb6, 0xaa, 0xbe, 0x26, 0x8f, 0x94, - 0xab, 0x09, 0x3b, 0xae, 0x4d, 0xf3, 0x43, 0xf4, 0xe5, 0xca, 0x41, 0xcc, 0x22, 0x37, 0xb8, 0x12, - 0xfb, 0x57, 0x5e, 0xd2, 0x46, 0x02, 0x7c, 0xfa, 0x37, 0x19, 0x6a, 0x6b, 0x7e, 0xd6, 0x85, 0x54, - 0x83, 0xb2, 0x69, 0x11, 0x4d, 0xb7, 0x7b, 0xc6, 0x40, 0x91, 0x90, 0x02, 0x55, 0xcb, 0x34, 0x2c, - 0x93, 0x68, 0x7a, 0xdf, 0xd2, 0xb8, 0xa4, 0x3e, 0x85, 0xdd, 0x81, 0x61, 0x9e, 0x11, 0xd3, 0xb2, - 0x89, 0x3e, 0x30, 0xbe, 0x31, 0x8e, 0x07, 0xba, 0x52, 0x40, 0x0f, 0x40, 0xb1, 0x4c, 0xd2, 0x3f, - 0xed, 0x19, 0x26, 0xb1, 0x8d, 0x73, 0xdd, 0xba, 0xb0, 0x15, 0x99, 0xa3, 0xa7, 0xf6, 0xa0, 0x4f, - 0xf4, 0xb7, 0x7d, 0x5d, 0xd7, 0x46, 0xe4, 0xbc, 0xf7, 0x56, 0x29, 0xa2, 0x16, 0x3c, 0x30, 0xcc, - 0xd1, 0xc5, 0xc9, 0x89, 0xd1, 0x37, 0x74, 0xd3, 0x26, 0xc7, 0xbd, 0x41, 0xcf, 0xec, 0xeb, 0xca, - 0x36, 0xda, 0x03, 0x64, 0x98, 0x7d, 0xeb, 0x7c, 0x38, 0xd0, 0x6d, 0x9d, 0x64, 0xd2, 0xdd, 0x41, - 0x4d, 0x68, 0x08, 0x3f, 0x3d, 0x4d, 0x23, 0x27, 0x3d, 0x63, 0xa0, 0x6b, 0x4a, 0x89, 0x47, 0x92, - 0x32, 0x46, 0x44, 0x33, 0x46, 0xbd, 0x63, 0x0e, 0x97, 0xf9, 0x9a, 0x86, 0xf9, 0xda, 0x32, 0xfa, - 0x3a, 0xe9, 0x73, 0xb7, 0x1c, 0x05, 0x4e, 0xce, 0xd0, 0x0b, 0x53, 0xd3, 0xf1, 0xb0, 0x67, 0x68, - 0x4a, 0x05, 0xed, 0xc3, 0xc3, 0x0c, 0xd6, 0xdf, 0x0e, 0x0d, 0xfc, 0x1d, 0xb1, 0x2d, 0x8b, 0x8c, - 0x2c, 0xcb, 0x54, 0xaa, 0x79, 0x4f, 0x3c, 0x5b, 0x6b, 0xa8, 0x9b, 0x4a, 0x0d, 0x3d, 0x84, 0xe6, - 0xf9, 0x70, 0x48, 0x32, 0x4b, 0x96, 0x6c, 0x9d, 0xd3, 0x7b, 0x9a, 0x86, 0xf5, 0xd1, 0x88, 0x9c, - 0x1b, 0xa3, 0xf3, 0x9e, 0xdd, 0x3f, 0x55, 0x1a, 0x3c, 0xa5, 0x91, 0x6e, 0x13, 0xdb, 0xb2, 0x7b, - 0x83, 0x15, 0xae, 0xf0, 0x80, 0x56, 0x38, 0x5f, 0x74, 0x60, 0xbd, 0x51, 0x76, 0xf9, 0x86, 0x73, - 0xd8, 0x7a, 0x9d, 0x86, 0x88, 0x78, 0xee, 0x69, 0x79, 0xb2, 0x35, 0x95, 0x26, 0x07, 0x0d, 0xf3, - 0x75, 0x6f, 0x60, 0x68, 0xe4, 0x4c, 0xff, 0x4e, 0xb4, 0xfe, 0x03, 0x0e, 0x26, 0x91, 0x91, 0x21, - 0xb6, 0xbe, 0xe1, 0x81, 0x28, 0x9f, 0x22, 0x04, 0xf5, 0xbe, 0x81, 0xfb, 0x17, 0x83, 0x1e, 0x26, - 0xd8, 0xba, 0xb0, 0x75, 0x65, 0xef, 0xe8, 0xbf, 0x45, 0xd8, 0x16, 0x17, 0x55, 0x84, 0x5e, 0x72, - 0xfd, 0x2f, 0x3f, 0x94, 0xd0, 0xa3, 0x8f, 0x7e, 0x40, 0xb5, 0xb3, 0xc7, 0x6c, 0x0a, 0x3f, 0x97, - 0xd0, 0x9f, 0xa0, 0x9a, 0xff, 0xbe, 0x40, 0xf9, 0xb3, 0x7d, 0xc3, 0x87, 0xc7, 0x06, 0x0f, 0x67, - 0xa0, 0xe8, 0x31, 0x73, 0x7d, 0x87, 0xd1, 0xec, 0x7b, 0x01, 0xb5, 0x73, 0x5e, 0x6e, 0x7d, 0x84, - 0xb4, 0xf7, 0x37, 0xda, 0xd2, 0x5b, 0x79, 0x90, 0xa4, 0x93, 0xbe, 0xd8, 0xef, 0xa4, 0xb3, 0xfe, - 0x99, 0xd0, 0xfe, 0xfc, 0x3e, 0x73, 0xea, 0x6d, 0x02, 0xcd, 0x0d, 0x8f, 0x70, 0xf4, 0x65, 0x3e, - 0x82, 0x7b, 0x9f, 0xf0, 0xed, 0xc7, 0x3f, 0x44, 0x5b, 0xad, 0xb2, 0xe1, 0xb5, 0xbe, 0xb6, 0xca, - 0xfd, 0x6f, 0xfd, 0xb5, 0x55, 0x3e, 0xf6, 0xe8, 0x7f, 0x07, 0xca, 0xed, 0xc7, 0x1d, 0x52, 0x6f, - 0xcf, 0xbd, 0xfb, 0xca, 0x6c, 0xff, 0xec, 0xa3, 0x9c, 0xd4, 0xb9, 0x01, 0xb0, 0x7a, 0x22, 0xa1, - 0xcf, 0x72, 0x53, 0xee, 0x3c, 0xf1, 0xda, 0x8f, 0xee, 0xb1, 0xa6, 0xae, 0x6c, 0x68, 0x6e, 0x78, - 0x33, 0xad, 0xed, 0xc6, 0xfd, 0x6f, 0xaa, 0xf6, 0x83, 0x4d, 0x4f, 0x8b, 0xe7, 0xd2, 0xf1, 0x57, - 0x7f, 0x3e, 0xbc, 0x72, 0xd9, 0x6c, 0x71, 0x79, 0x30, 0x0e, 0xfd, 0x43, 0xcf, 0xbd, 0x9a, 0xb1, - 0xc0, 0x0d, 0xae, 0x02, 0xca, 0x3e, 0x84, 0xd1, 0xf5, 0xa1, 0x17, 0x4c, 0x0e, 0x85, 0x2e, 0x0f, - 0x97, 0xd3, 0x2f, 0xb7, 0xc5, 0x1f, 0x96, 0x7e, 0xf5, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5f, - 0x5a, 0x7c, 0x81, 0x88, 0x12, 0x00, 0x00, + 0xfd, 0x68, 0x37, 0x4d, 0xe4, 0x24, 0x81, 0x8f, 0x5d, 0x86, 0xab, 0x9c, 0x97, 0xbe, 0xc7, 0x7c, + 0x75, 0x7c, 0xe7, 0x7b, 0x12, 0xcf, 0x1c, 0x9e, 0xc2, 0x6e, 0x47, 0xea, 0xd6, 0x70, 0xd9, 0x77, + 0xbe, 0x1f, 0x09, 0xa0, 0xad, 0xc1, 0xde, 0xe6, 0x88, 0xb9, 0x84, 0xf9, 0x92, 0x73, 0x55, 0xcb, + 0x98, 0x3f, 0xa2, 0x07, 0x50, 0x7c, 0xef, 0x78, 0x0b, 0x2a, 0x64, 0x5d, 0xc5, 0xc9, 0xcb, 0xef, + 0xb6, 0x5e, 0x48, 0xea, 0x0b, 0x68, 0xda, 0x91, 0x33, 0xbe, 0xbe, 0xd5, 0x19, 0xb7, 0x85, 0x2d, + 0xdd, 0x11, 0xb6, 0xfa, 0x12, 0x1a, 0xa2, 0x06, 0x27, 0x94, 0x7e, 0xac, 0x9f, 0x1e, 0x02, 0xef, + 0x16, 0xa1, 0xbe, 0xa4, 0xa7, 0xb6, 0x1d, 0x9f, 0x0b, 0x4f, 0x9d, 0x80, 0xb2, 0x1a, 0x1f, 0xcf, + 0xc3, 0x20, 0xa6, 0xbc, 0x59, 0x78, 0x89, 0xb8, 0xca, 0xb8, 0x28, 0x85, 0x1c, 0x25, 0x31, 0xaa, + 0x9e, 0xe2, 0x27, 0x94, 0x0a, 0x41, 0x3e, 0x4e, 0x7a, 0x80, 0x78, 0xe1, 0xf8, 0x9a, 0x77, 0x95, + 0x73, 0x93, 0xba, 0xaf, 0x71, 0x78, 0x10, 0x8e, 0xaf, 0x35, 0x0e, 0xaa, 0xef, 0x92, 0xc6, 0xb7, + 0x43, 0x31, 0xd7, 0x8f, 0x4f, 0x0f, 0xa9, 0x50, 0x14, 0x6a, 0x11, 0x6e, 0x2b, 0x47, 0xd5, 0xbc, + 0xec, 0x70, 0x62, 0x52, 0xdf, 0x41, 0x73, 0xcd, 0x79, 0x9a, 0x45, 0x1b, 0x4a, 0xf3, 0x88, 0xba, + 0xbe, 0x73, 0x45, 0x53, 0xcf, 0xcb, 0x77, 0xd4, 0x85, 0x9d, 0xa9, 0xe3, 0x7a, 0x8b, 0x28, 0x73, + 0x5c, 0xcf, 0x64, 0x90, 0xa0, 0x38, 0x33, 0xab, 0x9f, 0x41, 0x1b, 0xd3, 0x98, 0xb2, 0x73, 0x37, + 0x8e, 0xdd, 0x30, 0xe8, 0x87, 0x01, 0x8b, 0x42, 0x2f, 0xcd, 0x40, 0x7d, 0x04, 0xfb, 0x1b, 0xad, + 0x49, 0x08, 0x7c, 0xf0, 0xb7, 0x0b, 0x1a, 0xdd, 0x6c, 0x1e, 0xfc, 0x2d, 0xec, 0x6f, 0xb4, 0xa6, + 0xf1, 0x3f, 0x83, 0xe2, 0xdc, 0x71, 0xa3, 0xb8, 0xb5, 0x25, 0xda, 0x66, 0x2f, 0xd7, 0x36, 0x43, + 0xc7, 0x8d, 0x4e, 0xdd, 0x98, 0x85, 0xd1, 0x0d, 0x4e, 0x48, 0xaf, 0xe4, 0x92, 0xa4, 0x6c, 0xa9, + 0x7f, 0x97, 0xa0, 0x92, 0x33, 0xa2, 0x7d, 0x28, 0x07, 0xe1, 0x84, 0x92, 0x69, 0x14, 0xfa, 0xd9, + 0x22, 0x70, 0xe0, 0x24, 0x0a, 0x7d, 0xae, 0x09, 0x61, 0x64, 0x61, 0x2a, 0xc8, 0x6d, 0xfe, 0x6a, + 0x87, 0xe8, 0x97, 0xb0, 0x33, 0x4b, 0x1c, 0x88, 0xad, 0xaa, 0x72, 0xd4, 0xbc, 0x35, 0xb7, 0xe6, + 0x30, 0x07, 0x67, 0x9c, 0x57, 0x72, 0xa9, 0xa0, 0xc8, 0xaf, 0xe4, 0x92, 0xac, 0x14, 0x5f, 0xc9, + 0xa5, 0xa2, 0xb2, 0xfd, 0x4a, 0x2e, 0x6d, 0x2b, 0x3b, 0xea, 0x7f, 0x24, 0x28, 0x65, 0x6c, 0x1e, + 0x09, 0x5f, 0x52, 0xc2, 0x75, 0x91, 0x8a, 0xa9, 0xc4, 0x01, 0xdb, 0xf5, 0x29, 0xea, 0x40, 0x55, + 0x18, 0xd7, 0x25, 0x0a, 0x1c, 0xeb, 0x09, 0x99, 0x8a, 0x3d, 0x34, 0x63, 0x08, 0x3d, 0xca, 0xe9, + 0x1e, 0x9a, 0x50, 0xb2, 0x63, 0x20, 0x5e, 0x8c, 0xc7, 0x34, 0x8e, 0x93, 0x59, 0x8a, 0x09, 0x25, + 0xc5, 0xc4, 0x44, 0x8f, 0xa1, 0x91, 0x51, 0xb2, 0xb9, 0xb6, 0x13, 0xbd, 0xa6, 0x70, 0x3a, 0x5d, + 0x17, 0x94, 0x3c, 0xcf, 0x5f, 0xed, 0xda, 0xf5, 0x15, 0x91, 0x4f, 0x9a, 0x24, 0xaf, 0xfe, 0x05, + 0x1e, 0x8a, 0x52, 0x0e, 0xa3, 0xf0, 0xd2, 0xb9, 0x74, 0x3d, 0x97, 0xdd, 0x64, 0x22, 0xe7, 0x89, + 0x47, 0xa1, 0x4f, 0xf8, 0xda, 0x66, 0x25, 0xe0, 0x80, 0x19, 0x4e, 0x28, 0x2f, 0x01, 0x0b, 0x13, + 0x53, 0x5a, 0x02, 0x16, 0x0a, 0x43, 0xfe, 0xb4, 0x2b, 0xac, 0x9d, 0x76, 0xea, 0x35, 0xb4, 0xee, + 0xce, 0x95, 0x6a, 0xa6, 0x03, 0x95, 0xf9, 0x0a, 0x16, 0xd3, 0x49, 0x38, 0x0f, 0xe5, 0x6b, 0xbb, + 0xf5, 0xc3, 0xb5, 0x55, 0xff, 0x29, 0xc1, 0xee, 0xf1, 0xc2, 0xf5, 0x26, 0x6b, 0x8d, 0x9b, 0x8f, + 0x4e, 0x5a, 0x3f, 0x8b, 0x37, 0x1d, 0xb4, 0x5b, 0x1b, 0x0f, 0xda, 0x4d, 0x87, 0x59, 0xe1, 0xde, + 0xc3, 0xec, 0xa7, 0x50, 0x59, 0x9d, 0x63, 0x71, 0x4b, 0xee, 0x14, 0xba, 0x55, 0x0c, 0xb3, 0xec, + 0x10, 0x8b, 0xd5, 0x17, 0x80, 0xf2, 0x81, 0xa6, 0x0b, 0xb2, 0xdc, 0x3f, 0xa4, 0xfb, 0xf7, 0x8f, + 0xcf, 0xa0, 0x3d, 0x5a, 0x5c, 0xc6, 0xe3, 0xc8, 0xbd, 0xa4, 0xa7, 0xcc, 0x1b, 0xeb, 0xef, 0x69, + 0xc0, 0xe2, 0xac, 0x4b, 0xff, 0x27, 0x43, 0x79, 0x89, 0xa2, 0x03, 0x68, 0xba, 0xc1, 0x38, 0xf4, + 0xb3, 0xa0, 0x03, 0xea, 0xf1, 0xb8, 0x93, 0x4d, 0x7e, 0x37, 0x33, 0xf5, 0x13, 0x8b, 0x31, 0xe1, + 0xfc, 0xb5, 0x24, 0x53, 0xfe, 0x56, 0xc2, 0xcf, 0xe7, 0x98, 0xf0, 0xbb, 0xa0, 0x2c, 0xfd, 0xcf, + 0x98, 0x37, 0x5e, 0x2e, 0x0a, 0xae, 0x67, 0x38, 0x0f, 0x26, 0x61, 0x2e, 0x3d, 0x67, 0x4c, 0x39, + 0x61, 0x66, 0x78, 0xca, 0xfc, 0x02, 0xaa, 0xbc, 0x1f, 0x62, 0xe6, 0xf8, 0x73, 0x12, 0xc4, 0xa2, + 0x2f, 0x64, 0x5c, 0x59, 0x62, 0x66, 0x8c, 0xbe, 0x06, 0xa0, 0x3c, 0x3f, 0xc2, 0x6e, 0xe6, 0x54, + 0xb4, 0x44, 0xfd, 0xe8, 0xf3, 0x9c, 0x30, 0x96, 0x0b, 0x70, 0x20, 0xfe, 0xda, 0x37, 0x73, 0x8a, + 0xcb, 0x34, 0x7b, 0x44, 0x2f, 0xa1, 0x36, 0x0d, 0xa3, 0x0f, 0x4e, 0x34, 0x21, 0x02, 0x4c, 0xb7, + 0x8d, 0x87, 0x39, 0x0f, 0x27, 0x89, 0x5d, 0x0c, 0x3f, 0xfd, 0x04, 0x57, 0xa7, 0xb9, 0x77, 0x74, + 0x06, 0x28, 0x1b, 0x2f, 0xba, 0x3c, 0x71, 0x52, 0x12, 0x4e, 0xf6, 0xef, 0x3a, 0xe1, 0x9b, 0x74, + 0xe6, 0x48, 0x99, 0xde, 0xc2, 0xd0, 0xef, 0xa1, 0x1a, 0x53, 0xc6, 0x3c, 0x9a, 0xba, 0x29, 0x0b, + 0x37, 0x7b, 0x6b, 0xb7, 0x0e, 0x6e, 0xce, 0x3c, 0x54, 0xe2, 0xd5, 0x2b, 0x3a, 0x86, 0x86, 0xe7, + 0x06, 0xd7, 0xf9, 0x30, 0x40, 0x8c, 0x6f, 0xe5, 0xc6, 0x0f, 0xdc, 0xe0, 0x3a, 0x1f, 0x43, 0xcd, + 0xcb, 0x03, 0xea, 0x1f, 0xa0, 0xbc, 0x5c, 0x25, 0x54, 0x81, 0x9d, 0x0b, 0xf3, 0xcc, 0xb4, 0xde, + 0x98, 0xca, 0x27, 0xa8, 0x04, 0xf2, 0x48, 0x37, 0x35, 0x45, 0xe2, 0x30, 0xd6, 0xfb, 0xba, 0xf1, + 0x5a, 0x57, 0xb6, 0xf8, 0xcb, 0x89, 0x85, 0xdf, 0xf4, 0xb0, 0xa6, 0x14, 0x8e, 0x77, 0xa0, 0x28, + 0xe6, 0x55, 0xff, 0x25, 0x41, 0x49, 0x54, 0x30, 0x98, 0x86, 0xe8, 0x17, 0xb0, 0x14, 0x97, 0xd8, + 0xdc, 0xf8, 0x81, 0x2b, 0x54, 0x57, 0xc3, 0x4b, 0xc1, 0xd8, 0x29, 0xce, 0xc9, 0x4b, 0x69, 0x2c, + 0xc9, 0x5b, 0x09, 0x39, 0x33, 0x2c, 0xc9, 0x4f, 0x73, 0x9e, 0xd7, 0xb6, 0x1c, 0x19, 0x37, 0x32, + 0x43, 0xb6, 0xc3, 0x3e, 0xcd, 0x39, 0x5e, 0xdb, 0x89, 0x65, 0xdc, 0xc8, 0x0c, 0x29, 0x57, 0xfd, + 0x2d, 0x54, 0xf3, 0x35, 0x47, 0x4f, 0x40, 0x76, 0x83, 0x69, 0x98, 0x36, 0x62, 0xf3, 0x96, 0xb8, + 0x78, 0x92, 0x58, 0x10, 0x54, 0x04, 0xca, 0xed, 0x3a, 0xab, 0x35, 0xa8, 0xe4, 0x8a, 0xa6, 0xfe, + 0x5b, 0x82, 0xda, 0x5a, 0x11, 0x7e, 0xb4, 0x77, 0xf4, 0x35, 0x54, 0x3f, 0xb8, 0x11, 0x25, 0xf9, + 0xe3, 0xbf, 0x7e, 0xd4, 0x5e, 0x3f, 0xfe, 0xb3, 0xff, 0xfd, 0x70, 0x42, 0x71, 0x85, 0xf3, 0x53, + 0x00, 0xfd, 0x11, 0xea, 0xe9, 0x48, 0x32, 0xa1, 0xcc, 0x71, 0x3d, 0xb1, 0x54, 0xf5, 0x35, 0x79, + 0xa4, 0x5c, 0x4d, 0xd8, 0x71, 0x6d, 0x9a, 0x7f, 0x45, 0x5f, 0xae, 0x1c, 0xc4, 0x2c, 0x72, 0x83, + 0x2b, 0xb1, 0x7e, 0xe5, 0x25, 0x6d, 0x24, 0xc0, 0xa7, 0x7f, 0x93, 0xa1, 0xb6, 0xe6, 0x67, 0x5d, + 0x48, 0x35, 0x28, 0x9b, 0x16, 0xd1, 0x74, 0xbb, 0x67, 0x0c, 0x14, 0x09, 0x29, 0x50, 0xb5, 0x4c, + 0xc3, 0x32, 0x89, 0xa6, 0xf7, 0x2d, 0x8d, 0x4b, 0xea, 0x53, 0xd8, 0x1d, 0x18, 0xe6, 0x19, 0x31, + 0x2d, 0x9b, 0xe8, 0x03, 0xe3, 0x1b, 0xe3, 0x78, 0xa0, 0x2b, 0x05, 0xf4, 0x00, 0x14, 0xcb, 0x24, + 0xfd, 0xd3, 0x9e, 0x61, 0x12, 0xdb, 0x38, 0xd7, 0xad, 0x0b, 0x5b, 0x91, 0x39, 0x7a, 0x6a, 0x0f, + 0xfa, 0x44, 0x7f, 0xdb, 0xd7, 0x75, 0x6d, 0x44, 0xce, 0x7b, 0x6f, 0x95, 0x22, 0x6a, 0xc1, 0x03, + 0xc3, 0x1c, 0x5d, 0x9c, 0x9c, 0x18, 0x7d, 0x43, 0x37, 0x6d, 0x72, 0xdc, 0x1b, 0xf4, 0xcc, 0xbe, + 0xae, 0x6c, 0xa3, 0x3d, 0x40, 0x86, 0xd9, 0xb7, 0xce, 0x87, 0x03, 0xdd, 0xd6, 0x49, 0x26, 0xdd, + 0x1d, 0xd4, 0x84, 0x86, 0xf0, 0xd3, 0xd3, 0x34, 0x72, 0xd2, 0x33, 0x06, 0xba, 0xa6, 0x94, 0x78, + 0x24, 0x29, 0x63, 0x44, 0x34, 0x63, 0xd4, 0x3b, 0xe6, 0x70, 0x99, 0xcf, 0x69, 0x98, 0xaf, 0x2d, + 0xa3, 0xaf, 0x93, 0x3e, 0x77, 0xcb, 0x51, 0xe0, 0xe4, 0x0c, 0xbd, 0x30, 0x35, 0x1d, 0x0f, 0x7b, + 0x86, 0xa6, 0x54, 0xd0, 0x3e, 0x3c, 0xcc, 0x60, 0xfd, 0xed, 0xd0, 0xc0, 0xdf, 0x11, 0xdb, 0xb2, + 0xc8, 0xc8, 0xb2, 0x4c, 0xa5, 0x9a, 0xf7, 0xc4, 0xb3, 0xb5, 0x86, 0xba, 0xa9, 0xd4, 0xd0, 0x43, + 0x68, 0x9e, 0x0f, 0x87, 0x24, 0xb3, 0x64, 0xc9, 0xd6, 0x39, 0xbd, 0xa7, 0x69, 0x58, 0x1f, 0x8d, + 0xc8, 0xb9, 0x31, 0x3a, 0xef, 0xd9, 0xfd, 0x53, 0xa5, 0xc1, 0x53, 0x1a, 0xe9, 0x36, 0xb1, 0x2d, + 0xbb, 0x37, 0x58, 0xe1, 0x0a, 0x0f, 0x68, 0x85, 0xf3, 0x49, 0x07, 0xd6, 0x1b, 0x65, 0x97, 0x2f, + 0x38, 0x87, 0xad, 0xd7, 0x69, 0x88, 0x88, 0xe7, 0x9e, 0x96, 0x27, 0x9b, 0x53, 0x69, 0x72, 0xd0, + 0x30, 0x5f, 0xf7, 0x06, 0x86, 0x46, 0xce, 0xf4, 0xef, 0x44, 0xeb, 0x3f, 0xe0, 0x60, 0x12, 0x19, + 0x19, 0x62, 0xeb, 0x1b, 0x1e, 0x88, 0xf2, 0x29, 0x42, 0x50, 0xef, 0x1b, 0xb8, 0x7f, 0x31, 0xe8, + 0x61, 0x82, 0xad, 0x0b, 0x5b, 0x57, 0xf6, 0x8e, 0xfe, 0x5b, 0x84, 0x6d, 0x71, 0x50, 0x45, 0xe8, + 0x25, 0xd7, 0xff, 0xf2, 0x53, 0x09, 0x3d, 0xfa, 0xe8, 0x27, 0x54, 0x3b, 0xbb, 0xcc, 0xa6, 0xf0, + 0x73, 0x09, 0xfd, 0x09, 0xaa, 0xf9, 0xef, 0x0b, 0x94, 0xdf, 0xdb, 0x37, 0x7c, 0x78, 0x6c, 0xf0, + 0x70, 0x06, 0x8a, 0x1e, 0x33, 0xd7, 0x77, 0x18, 0xcd, 0xbe, 0x17, 0x50, 0x3b, 0xe7, 0xe5, 0xd6, + 0x47, 0x48, 0x7b, 0x7f, 0xa3, 0x2d, 0x3d, 0x95, 0x07, 0x49, 0x3a, 0xe9, 0x8d, 0xfd, 0x4e, 0x3a, + 0xeb, 0x9f, 0x09, 0xed, 0xcf, 0xef, 0x33, 0xa7, 0xde, 0x26, 0xd0, 0xdc, 0x70, 0x09, 0x47, 0x5f, + 0xe6, 0x23, 0xb8, 0xf7, 0x0a, 0xdf, 0x7e, 0xfc, 0x43, 0xb4, 0xd5, 0x2c, 0x1b, 0x6e, 0xeb, 0x6b, + 0xb3, 0xdc, 0x7f, 0xd7, 0x5f, 0x9b, 0xe5, 0x63, 0x97, 0xfe, 0x77, 0xa0, 0xdc, 0xbe, 0xdc, 0x21, + 0xf5, 0xf6, 0xd8, 0xbb, 0xb7, 0xcc, 0xf6, 0xcf, 0x3e, 0xca, 0x49, 0x9d, 0x1b, 0x00, 0xab, 0x2b, + 0x12, 0xfa, 0x2c, 0x37, 0xe4, 0xce, 0x15, 0xaf, 0xfd, 0xe8, 0x1e, 0x6b, 0xea, 0xca, 0x86, 0xe6, + 0x86, 0x3b, 0xd3, 0xda, 0x6a, 0xdc, 0x7f, 0xa7, 0x6a, 0x3f, 0xd8, 0x74, 0xb5, 0x78, 0x2e, 0x1d, + 0x7f, 0xf5, 0xe7, 0xc3, 0x2b, 0x97, 0xcd, 0x16, 0x97, 0x07, 0xe3, 0xd0, 0x3f, 0xf4, 0xdc, 0xab, + 0x19, 0x0b, 0xdc, 0xe0, 0x2a, 0xa0, 0xec, 0x43, 0x18, 0x5d, 0x1f, 0x7a, 0xc1, 0xe4, 0x50, 0xe8, + 0xf2, 0x70, 0x39, 0xfc, 0x72, 0x5b, 0xfc, 0xb4, 0xf4, 0xab, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, + 0x27, 0x10, 0x6c, 0xe6, 0x8a, 0x12, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 25e47d999e..5bf947ade0 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -119,7 +119,7 @@ message SendPaymentRequest { The maximum number of partial payments that may be use to complete the full amount. */ - uint32 max_htlcs = 17; + uint32 max_shards = 17; } message TrackPaymentRequest { diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 2d2be75b11..2803f4472b 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -549,11 +549,11 @@ func (r *RouterBackend) extractIntentFromSendRequest( // Take max htlcs from the request. Map zero to one for backwards // compatibility. - maxHtlcs := rpcPayReq.MaxHtlcs - if maxHtlcs == 0 { - maxHtlcs = 1 + maxShards := rpcPayReq.MaxShards + if maxShards == 0 { + maxShards = 1 } - payIntent.MaxHtlcs = maxHtlcs + payIntent.MaxShards = maxShards // Take fee limit from request. payIntent.FeeLimit, err = lnrpc.UnmarshallAmt( diff --git a/lntest/itest/lnd_send_multi_path_payment.go b/lntest/itest/lnd_send_multi_path_payment.go index b70564f070..318f255688 100644 --- a/lntest/itest/lnd_send_multi_path_payment.go +++ b/lntest/itest/lnd_send_multi_path_payment.go @@ -74,7 +74,7 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) { t, net.Alice, &routerrpc.SendPaymentRequest{ PaymentRequest: payReq, - MaxHtlcs: 10, + MaxShards: 10, TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat, }, diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index 4ab395e716..457ed4f467 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -88,7 +88,7 @@ func (h htlcAttempt) String() string { // testPayment launches a test payment and asserts that it is completed after // the expected number of attempts. -func (c *integratedRoutingContext) testPayment(maxHtlcs uint32) ([]htlcAttempt, +func (c *integratedRoutingContext) testPayment(maxShards uint32) ([]htlcAttempt, error) { var ( @@ -137,7 +137,7 @@ func (c *integratedRoutingContext) testPayment(maxHtlcs uint32) ([]htlcAttempt, DestFeatures: lnwire.NewFeatureVector(mppFeatures, nil), Amount: c.amt, CltvLimit: math.MaxUint32, - MaxHtlcs: maxHtlcs, + MaxShards: maxShards, } session := &paymentSession{ diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go index fb5d225471..2fdf7136e9 100644 --- a/routing/integrated_routing_test.go +++ b/routing/integrated_routing_test.go @@ -85,7 +85,7 @@ type mppSendTestCase struct { graph func(g *mockGraph) expectedFailure bool - maxHtlcs uint32 + maxShards uint32 } const ( @@ -150,7 +150,7 @@ var mppTestCases = []mppSendTestCase{ chans: []uint64{chanSourceIm2, chanIm2Target}, }, }, - maxHtlcs: 1000, + maxShards: 1000, }, // Test that a cap on the max htlcs makes it impossible to pay. @@ -161,7 +161,7 @@ var mppTestCases = []mppSendTestCase{ expectedAttempts: 2, expectedSuccesses: []expectedHtlcSuccess{}, expectedFailure: true, - maxHtlcs: 1, + maxShards: 1, }, // Test that an attempt is made to split the payment in multiple parts @@ -186,7 +186,7 @@ var mppTestCases = []mppSendTestCase{ }, }, expectedFailure: true, - maxHtlcs: 1000, + maxShards: 1000, }, } @@ -209,7 +209,7 @@ func testMppSend(t *testing.T, testCase *mppSendTestCase) { ctx.amt = lnwire.NewMSatFromSatoshis(testCase.amt) - attempts, err := ctx.testPayment(testCase.maxHtlcs) + attempts, err := ctx.testPayment(testCase.maxShards) switch { case err == nil && testCase.expectedFailure: t.Fatal("expected payment to fail") diff --git a/routing/payment_session.go b/routing/payment_session.go index d06356e7ef..c5a20f7a1a 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -211,7 +211,7 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, switch { case err == errNoPathFound: // No splitting if this is the last shard. - isLastShard := activeShards+1 >= p.payment.MaxHtlcs + isLastShard := activeShards+1 >= p.payment.MaxShards if isLastShard { return nil, errNoPathFound } diff --git a/routing/router.go b/routing/router.go index d93c38302c..2d286ce533 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1625,9 +1625,9 @@ type LightningPayment struct { // fail. DestCustomRecords record.CustomSet - // MaxHtlcs is the maximum number of partial payments that may be use to - // complete the full amount. - MaxHtlcs uint32 + // MaxShards is the maximum number of partial payments that may be used + // to complete the full amount. + MaxShards uint32 } // SendPayment attempts to send a payment as described within the passed diff --git a/rpcserver.go b/rpcserver.go index 666a5fb224..29f40d7a70 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3966,7 +3966,7 @@ func (r *rpcServer) dispatchPaymentIntent( // Don't enable multi-part payments on the main rpc. // Users need to use routerrpc for that. - MaxHtlcs: 1, + MaxShards: 1, } preImage, route, routerErr = r.server.chanRouter.SendPayment( From ec5bfd3df706f48d73fa94e141dfc90b208ac084 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 14 Apr 2020 10:37:56 +0200 Subject: [PATCH 475/562] make: move escaped double quote to fix windows build --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4f3ddbba79..5df705078b 100644 --- a/Makefile +++ b/Makefile @@ -52,10 +52,10 @@ include make/testing_flags.mk DEV_TAGS := $(if ${tags},$(DEV_TAGS) ${tags},$(DEV_TAGS)) -make_ldflags = $(shell echo -ldflags \"-X $(PKG)/build.Commit=$(COMMIT) \ +make_ldflags = -ldflags "$(shell echo -X $(PKG)/build.Commit=$(COMMIT) \ -X $(PKG)/build.CommitHash=$(COMMIT_HASH) \ -X $(PKG)/build.GoVersion=$(GOVERSION) \ - -X $(PKG)/build.RawTags=$(shell echo $(1) | sed -e 's/ /,/g')\") + -X $(PKG)/build.RawTags=$(shell echo $(1) | sed -e 's/ /,/g'))" LDFLAGS := $(call make_ldflags, ${tags}) DEV_LDFLAGS := $(call make_ldflags, $(DEV_TAGS)) From 1e3b0672d7fbe68b8abd618ec99da48c089c050c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 14 Apr 2020 11:13:11 +0200 Subject: [PATCH 476/562] config+lnd+lncli: add commit back to version string --- cmd/lncli/main.go | 2 +- config.go | 3 ++- lnd.go | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cmd/lncli/main.go b/cmd/lncli/main.go index a88fc926de..52d64ada7a 100644 --- a/cmd/lncli/main.go +++ b/cmd/lncli/main.go @@ -205,7 +205,7 @@ func extractPathArgs(ctx *cli.Context) (string, string, error) { func main() { app := cli.NewApp() app.Name = "lncli" - app.Version = build.Version() + app.Version = build.Version() + " commit=" + build.Commit app.Usage = "control plane for your Lightning Network Daemon (lnd)" app.Flags = []cli.Flag{ cli.StringFlag{ diff --git a/config.go b/config.go index 773c5d00b9..6816b0e81d 100644 --- a/config.go +++ b/config.go @@ -478,7 +478,8 @@ func loadConfig() (*config, error) { appName = strings.TrimSuffix(appName, filepath.Ext(appName)) usageMessage := fmt.Sprintf("Use %s -h to show usage", appName) if preCfg.ShowVersion { - fmt.Println(appName, "version", build.Version()) + fmt.Println(appName, "version", build.Version(), + "commit="+build.Commit) os.Exit(0) } diff --git a/lnd.go b/lnd.go index 875f0e7377..faffac1f1a 100644 --- a/lnd.go +++ b/lnd.go @@ -170,8 +170,9 @@ func Main(lisCfg ListenerCfg) error { }() // Show version at startup. - ltndLog.Infof("Version: %s, build=%s, logging=%s", - build.Version(), build.Deployment, build.LoggingType) + ltndLog.Infof("Version: %s commit=%s, build=%s, logging=%s", + build.Version(), build.Commit, build.Deployment, + build.LoggingType) var network string switch { From 5b38ed0b3e769fc3bbbd703ab159ba0171d53835 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:47:47 -0700 Subject: [PATCH 477/562] htlcswitch/link: correct link log statement --- htlcswitch/link.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index b8a50eeab6..bee3e6be88 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1179,7 +1179,7 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution, // Settle htlcs that returned a settle resolution using the preimage // in the resolution. case *invoices.HtlcSettleResolution: - l.log.Debugf("received settle resolution for %v"+ + l.log.Debugf("received settle resolution for %v "+ "with outcome: %v", circuitKey, res.Outcome) return l.settleHTLC(res.Preimage, htlc.pd) From f3051efeb308958920d4de9a32679a9bf28247fb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:48:06 -0700 Subject: [PATCH 478/562] htlcswitch/mailbox: block until mailbox shutdown Fixes a bug where Stop() wouldn't actually wait for the mailbox to exit. --- htlcswitch/mailbox.go | 47 +++++++++++++++++++++++++++++++++----- htlcswitch/mailbox_test.go | 22 ++++++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index 04c5cd6d84..e32d75a785 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -78,8 +78,9 @@ type memoryMailBox struct { pktOutbox chan *htlcPacket pktReset chan chan struct{} - wg sync.WaitGroup - quit chan struct{} + wireShutdown chan struct{} + pktShutdown chan struct{} + quit chan struct{} } // newMemoryMailBox creates a new instance of the memoryMailBox. @@ -92,6 +93,8 @@ func newMemoryMailBox() *memoryMailBox { msgReset: make(chan chan struct{}, 1), pktReset: make(chan chan struct{}, 1), pktIndex: make(map[CircuitKey]*list.Element), + wireShutdown: make(chan struct{}), + pktShutdown: make(chan struct{}), quit: make(chan struct{}), } box.wireCond = sync.NewCond(&box.wireMtx) @@ -122,7 +125,6 @@ const ( // NOTE: This method is part of the MailBox interface. func (m *memoryMailBox) Start() { m.started.Do(func() { - m.wg.Add(2) go m.mailCourier(wireCourier) go m.mailCourier(pktCourier) }) @@ -157,6 +159,7 @@ func (m *memoryMailBox) signalUntilReset(cType courierType, done chan struct{}) error { for { + switch cType { case wireCourier: m.wireCond.Signal() @@ -209,17 +212,49 @@ func (m *memoryMailBox) Stop() { m.stopped.Do(func() { close(m.quit) - m.wireCond.Signal() - m.pktCond.Signal() + m.signalUntilShutdown(wireCourier) + m.signalUntilShutdown(pktCourier) }) } +// signalUntilShutdown strobes the condition variable of the passed courier +// type, blocking until the worker has exited. +func (m *memoryMailBox) signalUntilShutdown(cType courierType) { + var ( + cond *sync.Cond + shutdown chan struct{} + ) + + switch cType { + case wireCourier: + cond = m.wireCond + shutdown = m.wireShutdown + case pktCourier: + cond = m.pktCond + shutdown = m.pktShutdown + } + + for { + select { + case <-time.After(time.Millisecond): + cond.Signal() + case <-shutdown: + return + } + } +} + // mailCourier is a dedicated goroutine whose job is to reliably deliver // messages of a particular type. There are two types of couriers: wire // couriers, and mail couriers. Depending on the passed courierType, this // goroutine will assume one of two roles. func (m *memoryMailBox) mailCourier(cType courierType) { - defer m.wg.Done() + switch cType { + case wireCourier: + defer close(m.wireShutdown) + case pktCourier: + defer close(m.pktShutdown) + } // TODO(roasbeef): refactor... diff --git a/htlcswitch/mailbox_test.go b/htlcswitch/mailbox_test.go index e8356c97d8..83dfc282ef 100644 --- a/htlcswitch/mailbox_test.go +++ b/htlcswitch/mailbox_test.go @@ -148,6 +148,28 @@ func TestMailBoxCouriers(t *testing.T) { } } +// TestMailBoxResetAfterShutdown tests that ResetMessages and ResetPackets +// return ErrMailBoxShuttingDown after the mailbox has been stopped. +func TestMailBoxResetAfterShutdown(t *testing.T) { + t.Parallel() + + m := newMemoryMailBox() + m.Start() + + // Stop the mailbox, then try to reset the message and packet couriers. + m.Stop() + + err := m.ResetMessages() + if err != ErrMailBoxShuttingDown { + t.Fatalf("expected ErrMailBoxShuttingDown, got: %v", err) + } + + err = m.ResetPackets() + if err != ErrMailBoxShuttingDown { + t.Fatalf("expected ErrMailBoxShuttingDown, got: %v", err) + } +} + // TestMailOrchestrator asserts that the orchestrator properly buffers packets // for channels that haven't been made live, such that they are delivered // immediately after BindLiveShortChanID. It also tests that packets are delivered From 12bbf28e651d9854f755eaa306708f608e3088b6 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:48:23 -0700 Subject: [PATCH 479/562] htlcswitch: make handleBatchFwdErrors a pure function --- htlcswitch/link.go | 22 +--------------------- htlcswitch/switch.go | 7 ++++--- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index bee3e6be88..9298ceb158 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -2948,27 +2948,7 @@ func (l *channelLink) forwardBatch(packets ...*htlcPacket) { } errChan := l.cfg.ForwardPackets(l.quit, filteredPkts...) - go l.handleBatchFwdErrs(errChan) -} - -// handleBatchFwdErrs waits on the given errChan until it is closed, logging -// the errors returned from any unsuccessful forwarding attempts. -func (l *channelLink) handleBatchFwdErrs(errChan chan error) { - for { - err, ok := <-errChan - if !ok { - // Err chan has been drained or switch is shutting - // down. Either way, return. - return - } - - if err == nil { - continue - } - - l.log.Errorf("unhandled error while forwarding htlc packet over "+ - "htlcswitch: %v", err) - } + go handleBatchFwdErrs(errChan, l.log) } // sendHTLCError functions cancels HTLC and send cancel message back to the diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 52d05be8b4..78ff100502 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -9,6 +9,7 @@ import ( "time" "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btclog" "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/chainntnfs" @@ -1972,13 +1973,13 @@ func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) { // link quit channel, meaning the send will fail only if the // switch receives a shutdown request. errChan := s.ForwardPackets(nil, switchPackets...) - go handleBatchFwdErrs(errChan) + go handleBatchFwdErrs(errChan, log) } } // handleBatchFwdErrs waits on the given errChan until it is closed, logging the // errors returned from any unsuccessful forwarding attempts. -func handleBatchFwdErrs(errChan chan error) { +func handleBatchFwdErrs(errChan chan error, l btclog.Logger) { for { err, ok := <-errChan if !ok { @@ -1991,7 +1992,7 @@ func handleBatchFwdErrs(errChan chan error) { continue } - log.Errorf("unhandled error while reforwarding htlc "+ + l.Errorf("Unhandled error while reforwarding htlc "+ "settle/fail over htlcswitch: %v", err) } } From 564534c829b230ed58fbcab25d84fd9306ff0da7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:48:40 -0700 Subject: [PATCH 480/562] htlcswitch: move packet failure to mailbox This commit moves the current logic for sending failures out of the link and into the mailbox in preparation for our failing delayed htlcs. We do so because the mailbox may need to fail packets while the link is offline, and needs to be able to complete the task without member methods on the link. --- htlcswitch/link.go | 68 +---------------- htlcswitch/mailbox.go | 149 ++++++++++++++++++++++++++++++++++--- htlcswitch/mailbox_test.go | 148 ++++++++++++++++++++++++++++++++++-- htlcswitch/switch.go | 18 +++-- 4 files changed, 293 insertions(+), 90 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 9298ceb158..afdd50cc02 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1272,72 +1272,6 @@ func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) { l.log.Warnf("Unable to handle downstream add HTLC: %v", err) - var ( - localFailure = false - reason lnwire.OpaqueReason - ) - - // Create a temporary channel failure which we will send - // back to our peer if this is a forward, or report to - // the user if the failed payment was locally initiated. - failure := l.createFailureWithUpdate( - func(upd *lnwire.ChannelUpdate) lnwire.FailureMessage { - return lnwire.NewTemporaryChannelFailure( - upd, - ) - }, - ) - - // If the payment was locally initiated (which is - // indicated by a nil obfuscator), we do not need to - // encrypt it back to the sender. - if pkt.obfuscator == nil { - var b bytes.Buffer - err := lnwire.EncodeFailure(&b, failure, 0) - if err != nil { - l.log.Errorf("unable to encode "+ - "failure: %v", err) - l.mailBox.AckPacket(pkt.inKey()) - return - } - reason = lnwire.OpaqueReason(b.Bytes()) - localFailure = true - } else { - // If the packet is part of a forward, - // (identified by a non-nil obfuscator) we need - // to encrypt the error back to the source. - var err error - reason, err = pkt.obfuscator.EncryptFirstHop(failure) - if err != nil { - l.log.Errorf("unable to "+ - "obfuscate error: %v", err) - l.mailBox.AckPacket(pkt.inKey()) - return - } - } - - // Create a link error containing the temporary channel - // failure and a detail which indicates the we failed to - // add the htlc. - linkError := NewDetailedLinkError( - failure, OutgoingFailureDownstreamHtlcAdd, - ) - - failPkt := &htlcPacket{ - incomingChanID: pkt.incomingChanID, - incomingHTLCID: pkt.incomingHTLCID, - circuit: pkt.circuit, - sourceRef: pkt.sourceRef, - hasSource: true, - localFailure: localFailure, - linkFailure: linkError, - htlc: &lnwire.UpdateFailHTLC{ - Reason: reason, - }, - } - - go l.forwardBatch(failPkt) - // Remove this packet from the link's mailbox, this // prevents it from being reprocessed if the link // restarts and resets it mailbox. If this response @@ -1346,7 +1280,7 @@ func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) { // the switch, since the circuit was never fully opened, // and the forwarding package shows it as // unacknowledged. - l.mailBox.AckPacket(pkt.inKey()) + l.mailBox.FailAdd(pkt) return } diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index e32d75a785..54c918b85a 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -1,6 +1,7 @@ package htlcswitch import ( + "bytes" "container/list" "errors" "sync" @@ -31,8 +32,17 @@ type MailBox interface { // AckPacket removes a packet from the mailboxes in-memory replay // buffer. This will prevent a packet from being delivered after a link - // restarts if the switch has remained online. - AckPacket(CircuitKey) + // restarts if the switch has remained online. The returned boolean + // indicates whether or not a packet with the passed incoming circuit + // key was removed. + AckPacket(CircuitKey) bool + + // FailAdd fails an UpdateAddHTLC that exists within the mailbox, + // removing it from the in-memory replay buffer. This will prevent the + // packet from being delivered after the link restarts if the switch has + // remained online. The generated LinkError will show an + // OutgoingFailureDownstreamHtlcAdd FailureDetail. + FailAdd(pkt *htlcPacket) // MessageOutBox returns a channel that any new messages ready for // delivery will be sent on. @@ -56,12 +66,29 @@ type MailBox interface { Stop() } +type mailBoxConfig struct { + // shortChanID is the short channel id of the channel this mailbox + // belongs to. + shortChanID lnwire.ShortChannelID + + // fetchUpdate retreives the most recent channel update for the channel + // this mailbox belongs to. + fetchUpdate func(lnwire.ShortChannelID) (*lnwire.ChannelUpdate, error) + + // forwardPackets send a varidic number of htlcPackets to the switch to + // be routed. A quit channel should be provided so that the call can + // properly exit during shutdown. + forwardPackets func(chan struct{}, ...*htlcPacket) chan error +} + // memoryMailBox is an implementation of the MailBox struct backed by purely // in-memory queues. type memoryMailBox struct { started sync.Once stopped sync.Once + cfg *mailBoxConfig + wireMessages *list.List wireMtx sync.Mutex wireCond *sync.Cond @@ -84,8 +111,9 @@ type memoryMailBox struct { } // newMemoryMailBox creates a new instance of the memoryMailBox. -func newMemoryMailBox() *memoryMailBox { +func newMemoryMailBox(cfg *mailBoxConfig) *memoryMailBox { box := &memoryMailBox{ + cfg: cfg, wireMessages: list.New(), htlcPkts: list.New(), messageOutbox: make(chan lnwire.Message), @@ -179,20 +207,23 @@ func (m *memoryMailBox) signalUntilReset(cType courierType, } // AckPacket removes the packet identified by it's incoming circuit key from the -// queue of packets to be delivered. +// queue of packets to be delivered. The returned boolean indicates whether or +// not a packet with the passed incoming circuit key was removed. // // NOTE: It is safe to call this method multiple times for the same circuit key. -func (m *memoryMailBox) AckPacket(inKey CircuitKey) { +func (m *memoryMailBox) AckPacket(inKey CircuitKey) bool { m.pktCond.L.Lock() entry, ok := m.pktIndex[inKey] if !ok { m.pktCond.L.Unlock() - return + return false } m.htlcPkts.Remove(entry) delete(m.pktIndex, inKey) m.pktCond.L.Unlock() + + return true } // HasPacket queries the packets for a circuit key, this is used to drop packets @@ -410,6 +441,80 @@ func (m *memoryMailBox) AddPacket(pkt *htlcPacket) error { return nil } +// FailAdd fails an UpdateAddHTLC that exists within the mailbox, removing it +// from the in-memory replay buffer. This will prevent the packet from being +// delivered after the link restarts if the switch has remained online. The +// generated LinkError will show an OutgoingFailureDownstreamHtlcAdd +// FailureDetail. +func (m *memoryMailBox) FailAdd(pkt *htlcPacket) { + // First, remove the packet from mailbox. If we didn't find the packet + // because it has already been acked, we'll exit early to avoid sending + // a duplicate fail message through the switch. + if !m.AckPacket(pkt.inKey()) { + return + } + + var ( + localFailure = false + reason lnwire.OpaqueReason + ) + + // Create a temporary channel failure which we will send back to our + // peer if this is a forward, or report to the user if the failed + // payment was locally initiated. + var failure lnwire.FailureMessage + update, err := m.cfg.fetchUpdate(m.cfg.shortChanID) + if err != nil { + failure = &lnwire.FailTemporaryNodeFailure{} + } else { + failure = lnwire.NewTemporaryChannelFailure(update) + } + + // If the payment was locally initiated (which is indicated by a nil + // obfuscator), we do not need to encrypt it back to the sender. + if pkt.obfuscator == nil { + var b bytes.Buffer + err := lnwire.EncodeFailure(&b, failure, 0) + if err != nil { + log.Errorf("Unable to encode failure: %v", err) + return + } + reason = lnwire.OpaqueReason(b.Bytes()) + localFailure = true + } else { + // If the packet is part of a forward, (identified by a non-nil + // obfuscator) we need to encrypt the error back to the source. + var err error + reason, err = pkt.obfuscator.EncryptFirstHop(failure) + if err != nil { + log.Errorf("Unable to obfuscate error: %v", err) + return + } + } + + // Create a link error containing the temporary channel failure and a + // detail which indicates the we failed to add the htlc. + linkError := NewDetailedLinkError( + failure, OutgoingFailureDownstreamHtlcAdd, + ) + + failPkt := &htlcPacket{ + incomingChanID: pkt.incomingChanID, + incomingHTLCID: pkt.incomingHTLCID, + circuit: pkt.circuit, + sourceRef: pkt.sourceRef, + hasSource: true, + localFailure: localFailure, + linkFailure: linkError, + htlc: &lnwire.UpdateFailHTLC{ + Reason: reason, + }, + } + + errChan := m.cfg.forwardPackets(m.quit, failPkt) + go handleBatchFwdErrs(errChan, log) +} + // MessageOutBox returns a channel that any new messages ready for delivery // will be sent on. // @@ -434,6 +539,8 @@ func (m *memoryMailBox) PacketOutBox() chan *htlcPacket { type mailOrchestrator struct { mu sync.RWMutex + cfg *mailOrchConfig + // mailboxes caches exactly one mailbox for all known channels. mailboxes map[lnwire.ChannelID]MailBox @@ -454,9 +561,21 @@ type mailOrchestrator struct { unclaimedPackets map[lnwire.ShortChannelID][]*htlcPacket } +type mailOrchConfig struct { + // forwardPackets send a varidic number of htlcPackets to the switch to + // be routed. A quit channel should be provided so that the call can + // properly exit during shutdown. + forwardPackets func(chan struct{}, ...*htlcPacket) chan error + + // fetchUpdate retreives the most recent channel update for the channel + // this mailbox belongs to. + fetchUpdate func(lnwire.ShortChannelID) (*lnwire.ChannelUpdate, error) +} + // newMailOrchestrator initializes a fresh mailOrchestrator. -func newMailOrchestrator() *mailOrchestrator { +func newMailOrchestrator(cfg *mailOrchConfig) *mailOrchestrator { return &mailOrchestrator{ + cfg: cfg, mailboxes: make(map[lnwire.ChannelID]MailBox), liveIndex: make(map[lnwire.ShortChannelID]lnwire.ChannelID), unclaimedPackets: make(map[lnwire.ShortChannelID][]*htlcPacket), @@ -472,7 +591,9 @@ func (mo *mailOrchestrator) Stop() { // GetOrCreateMailBox returns an existing mailbox belonging to `chanID`, or // creates and returns a new mailbox if none is found. -func (mo *mailOrchestrator) GetOrCreateMailBox(chanID lnwire.ChannelID) MailBox { +func (mo *mailOrchestrator) GetOrCreateMailBox(chanID lnwire.ChannelID, + shortChanID lnwire.ShortChannelID) MailBox { + // First, try lookup the mailbox directly using only the shared mutex. mo.mu.RLock() mailbox, ok := mo.mailboxes[chanID] @@ -485,7 +606,7 @@ func (mo *mailOrchestrator) GetOrCreateMailBox(chanID lnwire.ChannelID) MailBox // Otherwise, we will try again with exclusive lock, creating a mailbox // if one still has not been created. mo.mu.Lock() - mailbox = mo.exclusiveGetOrCreateMailBox(chanID) + mailbox = mo.exclusiveGetOrCreateMailBox(chanID, shortChanID) mo.mu.Unlock() return mailbox @@ -497,11 +618,15 @@ func (mo *mailOrchestrator) GetOrCreateMailBox(chanID lnwire.ChannelID) MailBox // // NOTE: This method MUST be invoked with the mailOrchestrator's exclusive lock. func (mo *mailOrchestrator) exclusiveGetOrCreateMailBox( - chanID lnwire.ChannelID) MailBox { + chanID lnwire.ChannelID, shortChanID lnwire.ShortChannelID) MailBox { mailbox, ok := mo.mailboxes[chanID] if !ok { - mailbox = newMemoryMailBox() + mailbox = newMemoryMailBox(&mailBoxConfig{ + shortChanID: shortChanID, + fetchUpdate: mo.cfg.fetchUpdate, + forwardPackets: mo.cfg.forwardPackets, + }) mailbox.Start() mo.mailboxes[chanID] = mailbox } @@ -581,7 +706,7 @@ func (mo *mailOrchestrator) Deliver( // index should only be set if the mailbox had been initialized // beforehand. However, this does ensure that this case is // handled properly in the event that it could happen. - mailbox = mo.exclusiveGetOrCreateMailBox(chanID) + mailbox = mo.exclusiveGetOrCreateMailBox(chanID, sid) mo.mu.Unlock() // Deliver the packet to the mailbox if it was found or created. diff --git a/htlcswitch/mailbox_test.go b/htlcswitch/mailbox_test.go index 83dfc282ef..ccf35e8798 100644 --- a/htlcswitch/mailbox_test.go +++ b/htlcswitch/mailbox_test.go @@ -19,7 +19,7 @@ func TestMailBoxCouriers(t *testing.T) { // First, we'll create new instance of the current default mailbox // type. - mailBox := newMemoryMailBox() + mailBox := newMemoryMailBox(&mailBoxConfig{}) mailBox.Start() defer mailBox.Stop() @@ -153,7 +153,7 @@ func TestMailBoxCouriers(t *testing.T) { func TestMailBoxResetAfterShutdown(t *testing.T) { t.Parallel() - m := newMemoryMailBox() + m := newMemoryMailBox(&mailBoxConfig{}) m.Start() // Stop the mailbox, then try to reset the message and packet couriers. @@ -170,6 +170,144 @@ func TestMailBoxResetAfterShutdown(t *testing.T) { } } +type mailboxContext struct { + t *testing.T + mailbox MailBox + forwards chan *htlcPacket +} + +func newMailboxContext(t *testing.T) *mailboxContext { + + ctx := &mailboxContext{ + t: t, + forwards: make(chan *htlcPacket, 1), + } + ctx.mailbox = newMemoryMailBox(&mailBoxConfig{ + fetchUpdate: func(sid lnwire.ShortChannelID) ( + *lnwire.ChannelUpdate, error) { + return &lnwire.ChannelUpdate{ + ShortChannelID: sid, + }, nil + }, + forwardPackets: ctx.forward, + }) + ctx.mailbox.Start() + + return ctx +} + +func (c *mailboxContext) forward(_ chan struct{}, + pkts ...*htlcPacket) chan error { + + for _, pkt := range pkts { + c.forwards <- pkt + } + + errChan := make(chan error) + close(errChan) + + return errChan +} + +func (c *mailboxContext) sendAdds(start, num int) []*htlcPacket { + c.t.Helper() + + sentPackets := make([]*htlcPacket, num) + for i := 0; i < num; i++ { + pkt := &htlcPacket{ + outgoingChanID: lnwire.NewShortChanIDFromInt( + uint64(prand.Int63())), + incomingChanID: lnwire.NewShortChanIDFromInt( + uint64(prand.Int63())), + incomingHTLCID: uint64(start + i), + amount: lnwire.MilliSatoshi(prand.Int63()), + htlc: &lnwire.UpdateAddHTLC{ + ID: uint64(start + i), + }, + } + sentPackets[i] = pkt + + err := c.mailbox.AddPacket(pkt) + if err != nil { + c.t.Fatalf("unable to add packet: %v", err) + } + } + + return sentPackets +} + +func (c *mailboxContext) receivePkts(pkts []*htlcPacket) { + c.t.Helper() + + for i, expPkt := range pkts { + select { + case pkt := <-c.mailbox.PacketOutBox(): + if reflect.DeepEqual(expPkt, pkt) { + continue + } + + c.t.Fatalf("inkey mismatch #%d, want: %v vs "+ + "got: %v", i, expPkt.inKey(), pkt.inKey()) + + case <-time.After(50 * time.Millisecond): + c.t.Fatalf("did not receive fail for index %d", i) + } + } +} + +func (c *mailboxContext) checkFails(adds []*htlcPacket) { + c.t.Helper() + + for i, add := range adds { + select { + case fail := <-c.forwards: + if add.inKey() == fail.inKey() { + continue + } + c.t.Fatalf("inkey mismatch #%d, add: %v vs fail: %v", + i, add.inKey(), fail.inKey()) + + case <-time.After(50 * time.Millisecond): + c.t.Fatalf("did not receive fail for index %d", i) + } + } + + select { + case pkt := <-c.forwards: + c.t.Fatalf("unexpected forward: %v", pkt) + case <-time.After(50 * time.Millisecond): + } +} + +// TestMailBoxFailAdd asserts that FailAdd returns a response to the switch +// under various interleavings with other operations on the mailbox. +func TestMailBoxFailAdd(t *testing.T) { + ctx := newMailboxContext(t) + defer ctx.mailbox.Stop() + + failAdds := func(adds []*htlcPacket) { + for _, add := range adds { + ctx.mailbox.FailAdd(add) + } + } + + const numBatchPackets = 5 + + // Send 10 adds, and pull them from the mailbox. + adds := ctx.sendAdds(0, numBatchPackets) + ctx.receivePkts(adds) + + // Fail all of these adds, simulating an error adding the HTLCs to the + // commitment. We should see a failure message for each. + go failAdds(adds) + ctx.checkFails(adds) + + // As a sanity check, Fail all of them again and assert that no + // duplicate fails are sent. + go failAdds(adds) + ctx.checkFails(nil) +} + // TestMailOrchestrator asserts that the orchestrator properly buffers packets // for channels that haven't been made live, such that they are delivered // immediately after BindLiveShortChanID. It also tests that packets are delivered @@ -178,7 +316,7 @@ func TestMailOrchestrator(t *testing.T) { t.Parallel() // First, we'll create a new instance of our orchestrator. - mo := newMailOrchestrator() + mo := newMailOrchestrator(&mailOrchConfig{}) defer mo.Stop() // We'll be delivering 10 htlc packets via the orchestrator. @@ -203,7 +341,7 @@ func TestMailOrchestrator(t *testing.T) { } // Now, initialize a new mailbox for Alice's chanid. - mailbox := mo.GetOrCreateMailBox(chanID1) + mailbox := mo.GetOrCreateMailBox(chanID1, aliceChanID) // Verify that no messages are received, since Alice's mailbox has not // been made live. @@ -248,7 +386,7 @@ func TestMailOrchestrator(t *testing.T) { // For the second half of the test, create a new mailbox for Bob and // immediately make it live with an assigned short chan id. - mailbox = mo.GetOrCreateMailBox(chanID2) + mailbox = mo.GetOrCreateMailBox(chanID2, bobChanID) mo.BindLiveShortChanID(mailbox, chanID2, bobChanID) // Create the second half of our htlcs, and deliver them via the diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 78ff100502..ba57ed11f6 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -283,12 +283,11 @@ func New(cfg Config, currentHeight uint32) (*Switch, error) { return nil, err } - return &Switch{ + s := &Switch{ bestHeight: currentHeight, cfg: &cfg, circuits: circuitMap, linkIndex: make(map[lnwire.ChannelID]ChannelLink), - mailOrchestrator: newMailOrchestrator(), forwardingIndex: make(map[lnwire.ShortChannelID]ChannelLink), interfaceIndex: make(map[[33]byte]map[lnwire.ChannelID]ChannelLink), pendingLinkIndex: make(map[lnwire.ChannelID]ChannelLink), @@ -297,7 +296,14 @@ func New(cfg Config, currentHeight uint32) (*Switch, error) { chanCloseRequests: make(chan *ChanClose), resolutionMsgs: make(chan *resolutionMsg), quit: make(chan struct{}), - }, nil + } + + s.mailOrchestrator = newMailOrchestrator(&mailOrchConfig{ + fetchUpdate: s.cfg.FetchLastChannelUpdate, + forwardPackets: s.ForwardPackets, + }) + + return s, nil } // resolutionMsg is a struct that wraps an existing ResolutionMsg with a done @@ -2037,7 +2043,8 @@ func (s *Switch) AddLink(link ChannelLink) error { // Get and attach the mailbox for this link, which buffers packets in // case there packets that we tried to deliver while this link was // offline. - mailbox := s.mailOrchestrator.GetOrCreateMailBox(chanID) + shortChanID := link.ShortChanID() + mailbox := s.mailOrchestrator.GetOrCreateMailBox(chanID, shortChanID) link.AttachMailBox(mailbox) if err := link.Start(); err != nil { @@ -2045,7 +2052,6 @@ func (s *Switch) AddLink(link ChannelLink) error { return err } - shortChanID := link.ShortChanID() if shortChanID == hop.Source { log.Infof("Adding pending link chan_id=%v, short_chan_id=%v", chanID, shortChanID) @@ -2217,7 +2223,7 @@ func (s *Switch) UpdateShortChanID(chanID lnwire.ChannelID) error { // Finally, alert the mail orchestrator to the change of short channel // ID, and deliver any unclaimed packets to the link. - mailbox := s.mailOrchestrator.GetOrCreateMailBox(chanID) + mailbox := s.mailOrchestrator.GetOrCreateMailBox(chanID, shortChanID) s.mailOrchestrator.BindLiveShortChanID( mailbox, chanID, shortChanID, ) From 63f3d0b0120c7684eeb87ea998561bc1fe2ba4eb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:48:58 -0700 Subject: [PATCH 481/562] htlcswitch/mailbox: advance packet head after delivery This commit delays the advancement of the pktHead until after the message has been delivered. This is a prepatory step, as in the future we may fail to deliver the packet due to a deadline expiring. --- htlcswitch/mailbox.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index 54c918b85a..d0b509d56e 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -219,6 +219,13 @@ func (m *memoryMailBox) AckPacket(inKey CircuitKey) bool { return false } + // Check whether we are removing the head of the queue. If so, we must + // advance the head to the next packet before removing. It's possible + // that the courier has already adanced the pktHead, so this check + // prevents the pktHead from getting desynchronized. + if entry == m.pktHead { + m.pktHead = entry.Next() + } m.htlcPkts.Remove(entry) delete(m.pktIndex, inKey) m.pktCond.L.Unlock() @@ -333,8 +340,9 @@ func (m *memoryMailBox) mailCourier(cType courierType) { } var ( - nextPkt *htlcPacket - nextMsg lnwire.Message + nextPkt *htlcPacket + nextPktEl *list.Element + nextMsg lnwire.Message ) switch cType { // Grab the datum off the front of the queue, shifting the @@ -350,7 +358,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { // re-delivered once the link comes back online. case pktCourier: nextPkt = m.pktHead.Value.(*htlcPacket) - m.pktHead = m.pktHead.Next() + nextPktEl = m.pktHead } // Now that we're done with the condition, we can unlock it to @@ -382,6 +390,14 @@ func (m *memoryMailBox) mailCourier(cType courierType) { case pktCourier: select { case m.pktOutbox <- nextPkt: + m.pktCond.L.Lock() + // Only advance the pktHead if this packet + // is still at the head of the queue. + if m.pktHead != nil && m.pktHead == nextPktEl { + m.pktHead = m.pktHead.Next() + } + m.pktCond.L.Unlock() + case pktDone := <-m.pktReset: m.pktCond.L.Lock() m.pktHead = m.htlcPkts.Front() From 37dca27a3d51b10844a6831124e659bf06264a08 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:49:26 -0700 Subject: [PATCH 482/562] htlcswitch: thread clock from switch to mailbox --- htlcswitch/mailbox.go | 19 +++++++++++++++++++ htlcswitch/mailbox_test.go | 20 ++++++++++++++++---- htlcswitch/mock.go | 2 ++ htlcswitch/switch.go | 16 ++++++++++++++++ server.go | 2 ++ 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index d0b509d56e..1c1ad5c403 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lnwire" ) @@ -79,6 +80,14 @@ type mailBoxConfig struct { // be routed. A quit channel should be provided so that the call can // properly exit during shutdown. forwardPackets func(chan struct{}, ...*htlcPacket) chan error + + // clock is a time source for the mailbox. + clock clock.Clock + + // expiry is the interval after which Adds will be cancelled if they + // have not been yet been delivered. The computed deadline will expiry + // this long after the Adds are added via AddPacket. + expiry time.Duration } // memoryMailBox is an implementation of the MailBox struct backed by purely @@ -586,6 +595,14 @@ type mailOrchConfig struct { // fetchUpdate retreives the most recent channel update for the channel // this mailbox belongs to. fetchUpdate func(lnwire.ShortChannelID) (*lnwire.ChannelUpdate, error) + + // clock is a time source for the generated mailboxes. + clock clock.Clock + + // expiry is the interval after which Adds will be cancelled if they + // have not been yet been delivered. The computed deadline will expiry + // this long after the Adds are added to a mailbox via AddPacket. + expiry time.Duration } // newMailOrchestrator initializes a fresh mailOrchestrator. @@ -642,6 +659,8 @@ func (mo *mailOrchestrator) exclusiveGetOrCreateMailBox( shortChanID: shortChanID, fetchUpdate: mo.cfg.fetchUpdate, forwardPackets: mo.cfg.forwardPackets, + clock: mo.cfg.clock, + expiry: mo.cfg.expiry, }) mailbox.Start() mo.mailboxes[chanID] = mailbox diff --git a/htlcswitch/mailbox_test.go b/htlcswitch/mailbox_test.go index ccf35e8798..040f2d3436 100644 --- a/htlcswitch/mailbox_test.go +++ b/htlcswitch/mailbox_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/davecgh/go-spew/spew" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lnwire" ) @@ -19,7 +20,10 @@ func TestMailBoxCouriers(t *testing.T) { // First, we'll create new instance of the current default mailbox // type. - mailBox := newMemoryMailBox(&mailBoxConfig{}) + mailBox := newMemoryMailBox(&mailBoxConfig{ + clock: clock.NewDefaultClock(), + expiry: time.Minute, + }) mailBox.Start() defer mailBox.Stop() @@ -172,14 +176,17 @@ func TestMailBoxResetAfterShutdown(t *testing.T) { type mailboxContext struct { t *testing.T + clock *clock.TestClock mailbox MailBox forwards chan *htlcPacket } -func newMailboxContext(t *testing.T) *mailboxContext { +func newMailboxContext(t *testing.T, startTime time.Time, + expiry time.Duration) *mailboxContext { ctx := &mailboxContext{ t: t, + clock: clock.NewTestClock(startTime), forwards: make(chan *htlcPacket, 1), } ctx.mailbox = newMemoryMailBox(&mailBoxConfig{ @@ -190,6 +197,8 @@ func newMailboxContext(t *testing.T) *mailboxContext { }, nil }, forwardPackets: ctx.forward, + clock: ctx.clock, + expiry: expiry, }) ctx.mailbox.Start() @@ -282,7 +291,7 @@ func (c *mailboxContext) checkFails(adds []*htlcPacket) { // TestMailBoxFailAdd asserts that FailAdd returns a response to the switch // under various interleavings with other operations on the mailbox. func TestMailBoxFailAdd(t *testing.T) { - ctx := newMailboxContext(t) + ctx := newMailboxContext(t, time.Now(), time.Minute) defer ctx.mailbox.Stop() failAdds := func(adds []*htlcPacket) { @@ -316,7 +325,10 @@ func TestMailOrchestrator(t *testing.T) { t.Parallel() // First, we'll create a new instance of our orchestrator. - mo := newMailOrchestrator(&mailOrchConfig{}) + mo := newMailOrchestrator(&mailOrchConfig{ + clock: clock.NewDefaultClock(), + expiry: time.Minute, + }) defer mo.Stop() // We'll be delivering 10 htlc packets via the orchestrator. diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index c65e5fb012..e9a2a1efab 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -177,6 +177,8 @@ func initSwitchWithDB(startingHeight uint32, db *channeldb.DB) (*Switch, error) LogEventTicker: ticker.NewForce(DefaultLogInterval), AckEventTicker: ticker.NewForce(DefaultAckInterval), HtlcNotifier: &mockHTLCNotifier{}, + Clock: clock.NewDefaultClock(), + HTLCExpiry: time.Hour, } return New(cfg, startingHeight) diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index ba57ed11f6..06c597bf60 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -15,6 +15,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/kvdb" + "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lntypes" @@ -36,6 +37,10 @@ const ( // DefaultAckInterval is the duration between attempts to ack any settle // fails in a forwarding package. DefaultAckInterval = 15 * time.Second + + // DefaultHTLCExpiry is the duration after which Adds will be cancelled + // if they could not get added to an outgoing commitment. + DefaultHTLCExpiry = time.Minute ) var ( @@ -174,6 +179,15 @@ type Config struct { // RejectHTLC is a flag that instructs the htlcswitch to reject any // HTLCs that are not from the source hop. RejectHTLC bool + + // Clock is a time source for the switch. + Clock clock.Clock + + // HTLCExpiry is the interval after which Adds will be cancelled if they + // have not been yet been delivered to a link. The computed deadline + // will expiry this long after the Adds are added to a mailbox via + // AddPacket. + HTLCExpiry time.Duration } // Switch is the central messaging bus for all incoming/outgoing HTLCs. @@ -301,6 +315,8 @@ func New(cfg Config, currentHeight uint32) (*Switch, error) { s.mailOrchestrator = newMailOrchestrator(&mailOrchConfig{ fetchUpdate: s.cfg.FetchLastChannelUpdate, forwardPackets: s.ForwardPackets, + clock: s.cfg.Clock, + expiry: s.cfg.HTLCExpiry, }) return s, nil diff --git a/server.go b/server.go index f8c36b306a..3fdffb2c31 100644 --- a/server.go +++ b/server.go @@ -496,6 +496,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, AckEventTicker: ticker.New(htlcswitch.DefaultAckInterval), AllowCircularRoute: cfg.AllowCircularRoute, RejectHTLC: cfg.RejectHTLC, + Clock: clock.NewDefaultClock(), + HTLCExpiry: htlcswitch.DefaultHTLCExpiry, }, uint32(currentHeight)) if err != nil { return nil, err From 1aa2dde4a43651645d0ada6b791a0e7c10a4e4f8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:49:48 -0700 Subject: [PATCH 483/562] htlcswithc/mailbox: prioritize settles/fails over adds This commit splits the packet courier internally into two distinct queues, one for adds and one for settles+fails. This allows us to prioritize HTLCs that will clear the commitment transaction and make space for adds. Previously this responsibility was handled by the overflow queue. --- htlcswitch/mailbox.go | 151 +++++++++++++++++++++++++++++-------- htlcswitch/mailbox_test.go | 109 ++++++++++++++++++++++++++ 2 files changed, 228 insertions(+), 32 deletions(-) diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index 1c1ad5c403..4eff702608 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -4,6 +4,7 @@ import ( "bytes" "container/list" "errors" + "fmt" "sync" "time" @@ -108,8 +109,13 @@ type memoryMailBox struct { htlcPkts *list.List pktIndex map[CircuitKey]*list.Element pktHead *list.Element - pktMtx sync.Mutex - pktCond *sync.Cond + + addPkts *list.List + addIndex map[CircuitKey]*list.Element + addHead *list.Element + + pktMtx sync.Mutex + pktCond *sync.Cond pktOutbox chan *htlcPacket pktReset chan chan struct{} @@ -125,11 +131,13 @@ func newMemoryMailBox(cfg *mailBoxConfig) *memoryMailBox { cfg: cfg, wireMessages: list.New(), htlcPkts: list.New(), + addPkts: list.New(), messageOutbox: make(chan lnwire.Message), pktOutbox: make(chan *htlcPacket), msgReset: make(chan chan struct{}, 1), pktReset: make(chan chan struct{}, 1), pktIndex: make(map[CircuitKey]*list.Element), + addIndex: make(map[CircuitKey]*list.Element), wireShutdown: make(chan struct{}), pktShutdown: make(chan struct{}), quit: make(chan struct{}), @@ -222,24 +230,39 @@ func (m *memoryMailBox) signalUntilReset(cType courierType, // NOTE: It is safe to call this method multiple times for the same circuit key. func (m *memoryMailBox) AckPacket(inKey CircuitKey) bool { m.pktCond.L.Lock() - entry, ok := m.pktIndex[inKey] - if !ok { - m.pktCond.L.Unlock() - return false + defer m.pktCond.L.Unlock() + + if entry, ok := m.pktIndex[inKey]; ok { + // Check whether we are removing the head of the queue. If so, + // we must advance the head to the next packet before removing. + // It's possible that the courier has already advanced the + // pktHead, so this check prevents the pktHead from getting + // desynchronized. + if entry == m.pktHead { + m.pktHead = entry.Next() + } + m.htlcPkts.Remove(entry) + delete(m.pktIndex, inKey) + + return true } - // Check whether we are removing the head of the queue. If so, we must - // advance the head to the next packet before removing. It's possible - // that the courier has already adanced the pktHead, so this check - // prevents the pktHead from getting desynchronized. - if entry == m.pktHead { - m.pktHead = entry.Next() + if entry, ok := m.addIndex[inKey]; ok { + // Check whether we are removing the head of the queue. If so, + // we must advance the head to the next add before removing. + // It's possible that the courier has already advanced the + // addHead, so this check prevents the addHead from getting + // desynchronized. + if entry == m.addHead { + m.addHead = entry.Next() + } + m.addPkts.Remove(entry) + delete(m.addIndex, inKey) + + return true } - m.htlcPkts.Remove(entry) - delete(m.pktIndex, inKey) - m.pktCond.L.Unlock() - return true + return false } // HasPacket queries the packets for a circuit key, this is used to drop packets @@ -328,7 +351,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { case pktCourier: m.pktCond.L.Lock() - for m.pktHead == nil { + for m.pktHead == nil && m.addHead == nil { m.pktCond.Wait() select { @@ -338,6 +361,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { // reconnect. case pktDone := <-m.pktReset: m.pktHead = m.htlcPkts.Front() + m.addHead = m.addPkts.Front() close(pktDone) case <-m.quit: @@ -351,6 +375,8 @@ func (m *memoryMailBox) mailCourier(cType courierType) { var ( nextPkt *htlcPacket nextPktEl *list.Element + nextAdd *htlcPacket + nextAddEl *list.Element nextMsg lnwire.Message ) switch cType { @@ -366,8 +392,15 @@ func (m *memoryMailBox) mailCourier(cType courierType) { // doesn't make it into a commitment, then it'll be // re-delivered once the link comes back online. case pktCourier: - nextPkt = m.pktHead.Value.(*htlcPacket) - nextPktEl = m.pktHead + // Peek at the next item to deliver, prioritizing + // Settle/Fail packets over Adds. + if m.pktHead != nil { + nextPkt = m.pktHead.Value.(*htlcPacket) + nextPktEl = m.pktHead + } else { + nextAdd = m.addHead.Value.(*htlcPacket) + nextAddEl = m.addHead + } } // Now that we're done with the condition, we can unlock it to @@ -397,22 +430,56 @@ func (m *memoryMailBox) mailCourier(cType courierType) { } case pktCourier: + var ( + pktOutbox chan *htlcPacket + addOutbox chan *htlcPacket + ) + + // Prioritize delivery of Settle/Fail packets over Adds. + // This ensures that we actively clear the commitment of + // existing HTLCs before trying to add new ones. This + // can help to improve forwarding performance since the + // time to sign a commitment is linear in the number of + // HTLCs manifested on the commitments. + // + // NOTE: Both types are eventually delivered over the + // same channel, but we can control which is delivered + // by exclusively making one nil and the other non-nil. + // We know from our loop condition that at least one + // nextPkt and nextAdd are non-nil. + if nextPkt != nil { + pktOutbox = m.pktOutbox + } else { + addOutbox = m.pktOutbox + } + select { - case m.pktOutbox <- nextPkt: + case pktOutbox <- nextPkt: m.pktCond.L.Lock() - // Only advance the pktHead if this packet - // is still at the head of the queue. + // Only advance the pktHead if this Settle or + // Fail is still at the head of the queue. if m.pktHead != nil && m.pktHead == nextPktEl { m.pktHead = m.pktHead.Next() } m.pktCond.L.Unlock() + case addOutbox <- nextAdd: + m.pktCond.L.Lock() + // Only advance the addHead if this Add is still + // at the head of the queue. + if m.addHead != nil && m.addHead == nextAddEl { + m.addHead = m.addHead.Next() + } + m.pktCond.L.Unlock() + case pktDone := <-m.pktReset: m.pktCond.L.Lock() m.pktHead = m.htlcPkts.Front() + m.addHead = m.addPkts.Front() m.pktCond.L.Unlock() close(pktDone) + case <-m.quit: return } @@ -444,18 +511,38 @@ func (m *memoryMailBox) AddMessage(msg lnwire.Message) error { // NOTE: This method is safe for concrete use and part of the MailBox // interface. func (m *memoryMailBox) AddPacket(pkt *htlcPacket) error { - // First, we'll lock the condition, and add the packet to the end of - // the htlc packet inbox. m.pktCond.L.Lock() - if _, ok := m.pktIndex[pkt.inKey()]; ok { - m.pktCond.L.Unlock() - return nil - } + switch htlc := pkt.htlc.(type) { + + // Split off Settle/Fail packets into the htlcPkts queue. + case *lnwire.UpdateFulfillHTLC, *lnwire.UpdateFailHTLC: + if _, ok := m.pktIndex[pkt.inKey()]; ok { + m.pktCond.L.Unlock() + return nil + } + + entry := m.htlcPkts.PushBack(pkt) + m.pktIndex[pkt.inKey()] = entry + if m.pktHead == nil { + m.pktHead = entry + } + + // Split off Add packets into the addPkts queue. + case *lnwire.UpdateAddHTLC: + if _, ok := m.addIndex[pkt.inKey()]; ok { + m.pktCond.L.Unlock() + return nil + } + + entry := m.addPkts.PushBack(pkt) + m.addIndex[pkt.inKey()] = entry + if m.addHead == nil { + m.addHead = entry + } - entry := m.htlcPkts.PushBack(pkt) - m.pktIndex[pkt.inKey()] = entry - if m.pktHead == nil { - m.pktHead = entry + default: + m.pktCond.L.Unlock() + return fmt.Errorf("unknown htlc type: %T", htlc) } m.pktCond.L.Unlock() diff --git a/htlcswitch/mailbox_test.go b/htlcswitch/mailbox_test.go index 040f2d3436..6a7cf026d6 100644 --- a/htlcswitch/mailbox_test.go +++ b/htlcswitch/mailbox_test.go @@ -38,6 +38,9 @@ func TestMailBoxCouriers(t *testing.T) { outgoingChanID: lnwire.NewShortChanIDFromInt(uint64(prand.Int63())), incomingChanID: lnwire.NewShortChanIDFromInt(uint64(prand.Int63())), amount: lnwire.MilliSatoshi(prand.Int63()), + htlc: &lnwire.UpdateAddHTLC{ + ID: uint64(i), + }, } sentPackets[i] = pkt @@ -315,6 +318,106 @@ func TestMailBoxFailAdd(t *testing.T) { // duplicate fails are sent. go failAdds(adds) ctx.checkFails(nil) + +} + +// TestMailBoxPacketPrioritization asserts that the mailbox will prioritize +// delivering Settle and Fail packets over Adds if both are available for +// delivery at the same time. +func TestMailBoxPacketPrioritization(t *testing.T) { + t.Parallel() + + // First, we'll create new instance of the current default mailbox + // type. + mailBox := newMemoryMailBox(&mailBoxConfig{ + clock: clock.NewDefaultClock(), + expiry: time.Minute, + }) + mailBox.Start() + defer mailBox.Stop() + + const numPackets = 5 + + _, _, aliceChanID, bobChanID := genIDs() + + // Next we'll send the following sequence of packets: + // - Settle1 + // - Add1 + // - Add2 + // - Fail + // - Settle2 + sentPackets := make([]*htlcPacket, numPackets) + for i := 0; i < numPackets; i++ { + pkt := &htlcPacket{ + outgoingChanID: aliceChanID, + outgoingHTLCID: uint64(i), + incomingChanID: bobChanID, + incomingHTLCID: uint64(i), + amount: lnwire.MilliSatoshi(prand.Int63()), + } + + switch i { + case 0, 4: + // First and last packets are a Settle. A non-Add is + // sent first to make the test deterministic w/o needing + // to sleep. + pkt.htlc = &lnwire.UpdateFulfillHTLC{ID: uint64(i)} + case 1, 2: + // Next two packets are Adds. + pkt.htlc = &lnwire.UpdateAddHTLC{ID: uint64(i)} + case 3: + // Last packet is a Fail. + pkt.htlc = &lnwire.UpdateFailHTLC{ID: uint64(i)} + } + + sentPackets[i] = pkt + + err := mailBox.AddPacket(pkt) + if err != nil { + t.Fatalf("failed to add packet: %v", err) + } + } + + // When dequeueing the packets, we expect the following sequence: + // - Settle1 + // - Fail + // - Settle2 + // - Add1 + // - Add2 + // + // We expect to see Fail and Settle2 to be delivered before either Add1 + // or Add2 due to the prioritization between the split queue. + for i := 0; i < numPackets; i++ { + select { + case pkt := <-mailBox.PacketOutBox(): + var expPkt *htlcPacket + switch i { + case 0: + // First packet should be Settle1. + expPkt = sentPackets[0] + case 1: + // Second packet should be Fail. + expPkt = sentPackets[3] + case 2: + // Third packet should be Settle2. + expPkt = sentPackets[4] + case 3: + // Fourth packet should be Add1. + expPkt = sentPackets[1] + case 4: + // Last packet should be Add2. + expPkt = sentPackets[2] + } + + if !reflect.DeepEqual(expPkt, pkt) { + t.Fatalf("recvd packet mismatch %d, want: %v, got: %v", + i, spew.Sdump(expPkt), spew.Sdump(pkt)) + } + + case <-time.After(50 * time.Millisecond): + t.Fatalf("didn't receive packet %d before timeout", i) + } + } } // TestMailOrchestrator asserts that the orchestrator properly buffers packets @@ -346,6 +449,9 @@ func TestMailOrchestrator(t *testing.T) { incomingChanID: bobChanID, incomingHTLCID: uint64(i), amount: lnwire.MilliSatoshi(prand.Int63()), + htlc: &lnwire.UpdateAddHTLC{ + ID: uint64(i), + }, } sentPackets[i] = pkt @@ -411,6 +517,9 @@ func TestMailOrchestrator(t *testing.T) { incomingChanID: bobChanID, incomingHTLCID: uint64(halfPackets + i), amount: lnwire.MilliSatoshi(prand.Int63()), + htlc: &lnwire.UpdateAddHTLC{ + ID: uint64(halfPackets + i), + }, } sentPackets[i] = pkt From e7ece11c29ff2e1cb9fef54e7850f80c2f45c828 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:50:07 -0700 Subject: [PATCH 484/562] htlcswitch/mailbox: fail htlcs when delayed for 1 minute Now that packet failure is handled by the mailbox, we can now enforce a delivery deadline and fail the packet if it the deadilne is exceeded. This gives senders quicker feedback about tried routes, and allows them to try alternative paths to the destination in the meantime. --- htlcswitch/link.go | 7 +++ htlcswitch/mailbox.go | 63 ++++++++++++++++++++++++--- htlcswitch/mailbox_test.go | 89 +++++++++++++++++++++++++++++++++++--- 3 files changed, 145 insertions(+), 14 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index afdd50cc02..27102d5506 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -509,6 +509,13 @@ func (l *channelLink) Stop() { close(l.quit) l.wg.Wait() + // Now that the htlcManager has completely exited, reset the packet + // courier. This allows the mailbox to revaluate any lingering Adds that + // were delivered but didn't make it on a commitment to be failed back + // if the link is offline for an extended period of time. The error is + // ignored since it can only fail when the daemon is exiting. + _ = l.mailBox.ResetPackets() + // As a final precaution, we will attempt to flush any uncommitted // preimages to the preimage cache. The preimages should be re-delivered // after channel reestablishment, however this adds an extra layer of diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index 4eff702608..dd5b4a641f 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -253,9 +253,16 @@ func (m *memoryMailBox) AckPacket(inKey CircuitKey) bool { // It's possible that the courier has already advanced the // addHead, so this check prevents the addHead from getting // desynchronized. + // + // NOTE: While this event is rare for Settles or Fails, it could + // be very common for Adds since the mailbox has the ability to + // cancel Adds before they are delivered. When that occurs, the + // head of addPkts has only been peeked and we expect to be + // removing the head of the queue. if entry == m.addHead { m.addHead = entry.Next() } + m.addPkts.Remove(entry) delete(m.addIndex, inKey) @@ -314,6 +321,18 @@ func (m *memoryMailBox) signalUntilShutdown(cType courierType) { } } +// pktWithExpiry wraps an incoming packet and records the time at which it it +// should be canceled from the mailbox. This will be used to detect if it gets +// stuck in the mailbox and inform when to cancel back. +type pktWithExpiry struct { + pkt *htlcPacket + expiry time.Time +} + +func (p *pktWithExpiry) deadline(clock clock.Clock) <-chan time.Time { + return clock.TickAfter(p.expiry.Sub(clock.Now())) +} + // mailCourier is a dedicated goroutine whose job is to reliably deliver // messages of a particular type. There are two types of couriers: wire // couriers, and mail couriers. Depending on the passed courierType, this @@ -364,6 +383,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { m.addHead = m.addPkts.Front() close(pktDone) + case <-m.quit: m.pktCond.L.Unlock() return @@ -375,7 +395,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { var ( nextPkt *htlcPacket nextPktEl *list.Element - nextAdd *htlcPacket + nextAdd *pktWithExpiry nextAddEl *list.Element nextMsg lnwire.Message ) @@ -392,13 +412,18 @@ func (m *memoryMailBox) mailCourier(cType courierType) { // doesn't make it into a commitment, then it'll be // re-delivered once the link comes back online. case pktCourier: - // Peek at the next item to deliver, prioritizing - // Settle/Fail packets over Adds. + // Peek at the head of the Settle/Fails and Add queues. + // We peak both even if there is a Settle/Fail present + // because we need to set a deadline for the next + // pending Add if it's present. Due to clock + // monotonicity, we know that the head of the Adds is + // the next to expire. if m.pktHead != nil { nextPkt = m.pktHead.Value.(*htlcPacket) nextPktEl = m.pktHead - } else { - nextAdd = m.addHead.Value.(*htlcPacket) + } + if m.addHead != nil { + nextAdd = m.addHead.Value.(*pktWithExpiry) nextAddEl = m.addHead } } @@ -433,6 +458,8 @@ func (m *memoryMailBox) mailCourier(cType courierType) { var ( pktOutbox chan *htlcPacket addOutbox chan *htlcPacket + add *htlcPacket + deadline <-chan time.Time ) // Prioritize delivery of Settle/Fail packets over Adds. @@ -453,6 +480,22 @@ func (m *memoryMailBox) mailCourier(cType courierType) { addOutbox = m.pktOutbox } + // If we have a pending Add, we'll also construct the + // deadline so we can fail it back if we are unable to + // deliver any message in time. We also dereference the + // nextAdd's packet, since we will need access to it in + // the case we are delivering it and/or if the deadline + // expires. + // + // NOTE: It's possible after this point for add to be + // nil, but this can only occur when addOutbox is also + // nil, hence we won't accidentally deliver a nil + // packet. + if nextAdd != nil { + add = nextAdd.pkt + deadline = nextAdd.deadline(m.cfg.clock) + } + select { case pktOutbox <- nextPkt: m.pktCond.L.Lock() @@ -463,7 +506,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { } m.pktCond.L.Unlock() - case addOutbox <- nextAdd: + case addOutbox <- add: m.pktCond.L.Lock() // Only advance the addHead if this Add is still // at the head of the queue. @@ -472,6 +515,9 @@ func (m *memoryMailBox) mailCourier(cType courierType) { } m.pktCond.L.Unlock() + case <-deadline: + m.FailAdd(add) + case pktDone := <-m.pktReset: m.pktCond.L.Lock() m.pktHead = m.htlcPkts.Front() @@ -534,7 +580,10 @@ func (m *memoryMailBox) AddPacket(pkt *htlcPacket) error { return nil } - entry := m.addPkts.PushBack(pkt) + entry := m.addPkts.PushBack(&pktWithExpiry{ + pkt: pkt, + expiry: m.cfg.clock.Now().Add(m.cfg.expiry), + }) m.addIndex[pkt.inKey()] = entry if m.addHead == nil { m.addHead = entry diff --git a/htlcswitch/mailbox_test.go b/htlcswitch/mailbox_test.go index 6a7cf026d6..999468dce7 100644 --- a/htlcswitch/mailbox_test.go +++ b/htlcswitch/mailbox_test.go @@ -179,8 +179,8 @@ func TestMailBoxResetAfterShutdown(t *testing.T) { type mailboxContext struct { t *testing.T - clock *clock.TestClock mailbox MailBox + clock *clock.TestClock forwards chan *htlcPacket } @@ -294,7 +294,15 @@ func (c *mailboxContext) checkFails(adds []*htlcPacket) { // TestMailBoxFailAdd asserts that FailAdd returns a response to the switch // under various interleavings with other operations on the mailbox. func TestMailBoxFailAdd(t *testing.T) { - ctx := newMailboxContext(t, time.Now(), time.Minute) + var ( + batchDelay = time.Second + expiry = time.Minute + firstBatchStart = time.Now() + secondBatchStart = time.Now().Add(batchDelay) + thirdBatchStart = time.Now().Add(2 * batchDelay) + thirdBatchExpiry = thirdBatchStart.Add(expiry) + ) + ctx := newMailboxContext(t, firstBatchStart, expiry) defer ctx.mailbox.Stop() failAdds := func(adds []*htlcPacket) { @@ -306,19 +314,54 @@ func TestMailBoxFailAdd(t *testing.T) { const numBatchPackets = 5 // Send 10 adds, and pull them from the mailbox. - adds := ctx.sendAdds(0, numBatchPackets) - ctx.receivePkts(adds) + firstBatch := ctx.sendAdds(0, numBatchPackets) + ctx.receivePkts(firstBatch) // Fail all of these adds, simulating an error adding the HTLCs to the // commitment. We should see a failure message for each. - go failAdds(adds) - ctx.checkFails(adds) + go failAdds(firstBatch) + ctx.checkFails(firstBatch) // As a sanity check, Fail all of them again and assert that no // duplicate fails are sent. - go failAdds(adds) + go failAdds(firstBatch) + ctx.checkFails(nil) + + // Now, send a second batch of adds after a short delay and deliver them + // to the link. + ctx.clock.SetTime(secondBatchStart) + secondBatch := ctx.sendAdds(numBatchPackets, numBatchPackets) + ctx.receivePkts(secondBatch) + + // Reset the packet queue w/o changing the current time. This simulates + // the link flapping and coming back up before the second batch's + // expiries have elapsed. We should see no failures sent back. + err := ctx.mailbox.ResetPackets() + if err != nil { + t.Fatalf("unable to reset packets: %v", err) + } ctx.checkFails(nil) + // Redeliver the second batch to the link and hold them there. + ctx.receivePkts(secondBatch) + + // Send a third batch of adds shortly after the second batch. + ctx.clock.SetTime(thirdBatchStart) + thirdBatch := ctx.sendAdds(2*numBatchPackets, numBatchPackets) + + // Advance the clock so that the third batch expires. We expect to only + // see fails for the third batch, since the second batch is still being + // held by the link. + ctx.clock.SetTime(thirdBatchExpiry) + ctx.checkFails(thirdBatch) + + // Finally, reset the link which should cause the second batch to be + // cancelled immediately. + err = ctx.mailbox.ResetPackets() + if err != nil { + t.Fatalf("unable to reset packets: %v", err) + } + ctx.checkFails(secondBatch) } // TestMailBoxPacketPrioritization asserts that the mailbox will prioritize @@ -420,6 +463,38 @@ func TestMailBoxPacketPrioritization(t *testing.T) { } } +// TestMailBoxAddExpiry asserts that the mailbox will cancel back Adds that have +// reached their expiry time. +func TestMailBoxAddExpiry(t *testing.T) { + var ( + expiry = time.Minute + batchDelay = time.Second + firstBatchStart = time.Now() + firstBatchExpiry = firstBatchStart.Add(expiry) + secondBatchStart = firstBatchStart.Add(batchDelay) + secondBatchExpiry = secondBatchStart.Add(expiry) + ) + + ctx := newMailboxContext(t, firstBatchStart, expiry) + defer ctx.mailbox.Stop() + + // Each batch will consist of 10 messages. + const numBatchPackets = 10 + + firstBatch := ctx.sendAdds(0, numBatchPackets) + + ctx.clock.SetTime(secondBatchStart) + ctx.checkFails(nil) + + secondBatch := ctx.sendAdds(numBatchPackets, numBatchPackets) + + ctx.clock.SetTime(firstBatchExpiry) + ctx.checkFails(firstBatch) + + ctx.clock.SetTime(secondBatchExpiry) + ctx.checkFails(secondBatch) +} + // TestMailOrchestrator asserts that the orchestrator properly buffers packets // for channels that haven't been made live, such that they are delivered // immediately after BindLiveShortChanID. It also tests that packets are delivered From 16ad0274c932f1db8c7da9db4ed853630ad7b690 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:50:25 -0700 Subject: [PATCH 485/562] htlcswitch/mailbox: fail on duplicate adds --- htlcswitch/mailbox.go | 16 ++++++++----- htlcswitch/mailbox_test.go | 46 +++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index dd5b4a641f..66398e291e 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -12,9 +12,15 @@ import ( "github.com/lightningnetwork/lnd/lnwire" ) -// ErrMailBoxShuttingDown is returned when the mailbox is interrupted by a -// shutdown request. -var ErrMailBoxShuttingDown = errors.New("mailbox is shutting down") +var ( + // ErrMailBoxShuttingDown is returned when the mailbox is interrupted by + // a shutdown request. + ErrMailBoxShuttingDown = errors.New("mailbox is shutting down") + + // ErrPacketAlreadyExists signals that an attempt to add a packet failed + // because it already exists in the mailbox. + ErrPacketAlreadyExists = errors.New("mailbox already has packet") +) // MailBox is an interface which represents a concurrent-safe, in-order // delivery queue for messages from the network and also from the main switch. @@ -564,7 +570,7 @@ func (m *memoryMailBox) AddPacket(pkt *htlcPacket) error { case *lnwire.UpdateFulfillHTLC, *lnwire.UpdateFailHTLC: if _, ok := m.pktIndex[pkt.inKey()]; ok { m.pktCond.L.Unlock() - return nil + return ErrPacketAlreadyExists } entry := m.htlcPkts.PushBack(pkt) @@ -577,7 +583,7 @@ func (m *memoryMailBox) AddPacket(pkt *htlcPacket) error { case *lnwire.UpdateAddHTLC: if _, ok := m.addIndex[pkt.inKey()]; ok { m.pktCond.L.Unlock() - return nil + return ErrPacketAlreadyExists } entry := m.addPkts.PushBack(&pktWithExpiry{ diff --git a/htlcswitch/mailbox_test.go b/htlcswitch/mailbox_test.go index 999468dce7..655caaffe7 100644 --- a/htlcswitch/mailbox_test.go +++ b/htlcswitch/mailbox_test.go @@ -44,7 +44,10 @@ func TestMailBoxCouriers(t *testing.T) { } sentPackets[i] = pkt - mailBox.AddPacket(pkt) + err := mailBox.AddPacket(pkt) + if err != nil { + t.Fatalf("unable to add packet: %v", err) + } } // Next, we'll do the same, but this time adding wire messages. @@ -495,6 +498,47 @@ func TestMailBoxAddExpiry(t *testing.T) { ctx.checkFails(secondBatch) } +// TestMailBoxDuplicateAddPacket asserts that the mailbox returns an +// ErrPacketAlreadyExists failure when two htlcPackets are added with identical +// incoming circuit keys. +func TestMailBoxDuplicateAddPacket(t *testing.T) { + t.Parallel() + + mailBox := newMemoryMailBox(&mailBoxConfig{ + clock: clock.NewDefaultClock(), + }) + mailBox.Start() + defer mailBox.Stop() + + addTwice := func(t *testing.T, pkt *htlcPacket) { + // The first add should succeed. + err := mailBox.AddPacket(pkt) + if err != nil { + t.Fatalf("unable to add packet: %v", err) + } + + // Adding again with the same incoming circuit key should fail. + err = mailBox.AddPacket(pkt) + if err != ErrPacketAlreadyExists { + t.Fatalf("expected ErrPacketAlreadyExists, got: %v", err) + } + } + + // Assert duplicate AddPacket calls fail for all types of HTLCs. + addTwice(t, &htlcPacket{ + incomingHTLCID: 0, + htlc: &lnwire.UpdateAddHTLC{}, + }) + addTwice(t, &htlcPacket{ + incomingHTLCID: 1, + htlc: &lnwire.UpdateFulfillHTLC{}, + }) + addTwice(t, &htlcPacket{ + incomingHTLCID: 2, + htlc: &lnwire.UpdateFailHTLC{}, + }) +} + // TestMailOrchestrator asserts that the orchestrator properly buffers packets // for channels that haven't been made live, such that they are delivered // immediately after BindLiveShortChanID. It also tests that packets are delivered From 6fca22be2b19f216e830f084ee1b4a65527072b5 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:50:45 -0700 Subject: [PATCH 486/562] htlcswitch/link: use return instead of break out There is no clean up logic after the loop, done purely to improve clarity. --- htlcswitch/link.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 27102d5506..f474303ec5 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1010,13 +1010,12 @@ func (l *channelLink) htlcManager() { go l.fwdPkgGarbager() } -out: for { // We must always check if we failed at some point processing // the last update before processing the next. if l.failed { l.log.Errorf("link failed, exiting htlcManager") - break out + return } // If the previous event resulted in a non-empty batch, resume @@ -1086,7 +1085,7 @@ out: l.cfg.Peer.WipeChannel(chanPoint) }() - break out + return case <-l.cfg.BatchTicker.Ticks(): // Attempt to extend the remote commitment chain @@ -1096,7 +1095,7 @@ out: if err := l.updateCommitTx(); err != nil { l.fail(LinkFailureError{code: ErrInternalError}, "unable to update commitment: %v", err) - break out + return } // A message from the switch was just received. This indicates @@ -1121,11 +1120,11 @@ out: fmt.Sprintf("process hodl queue: %v", err.Error()), ) - break out + return } case <-l.quit: - break out + return } } } From a8977651ccb44f5ab47a75e7321c9a09a73810a1 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:51:06 -0700 Subject: [PATCH 487/562] htlcswitch/linkfailure: use whitelist for ShouldSendToPeer --- htlcswitch/linkfailure.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/htlcswitch/linkfailure.go b/htlcswitch/linkfailure.go index c806c4b269..b9ec7596fa 100644 --- a/htlcswitch/linkfailure.go +++ b/htlcswitch/linkfailure.go @@ -90,13 +90,23 @@ func (e LinkFailureError) Error() string { // the link fails with this LinkFailureError. func (e LinkFailureError) ShouldSendToPeer() bool { switch e.code { - // If the failure is a result of the peer sending us an error, we don't - // have to respond with one. - case ErrRemoteError: - return false - // In all other cases we will attempt to send our peer an error message. - default: + // Since sending an error can lead some nodes to force close the + // channel, create a whitelist of the failures we want to send so that + // newly added error codes aren't automatically sent to the remote peer. + case + ErrInternalError, + ErrRemoteError, + ErrSyncError, + ErrInvalidUpdate, + ErrInvalidCommitment, + ErrInvalidRevocation, + ErrRecoveryError: + return true + + // In all other cases we will not attempt to send our peer an error. + default: + return false } } From ec1b8d874d41472ca710fc4de89c09931d154556 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:51:30 -0700 Subject: [PATCH 488/562] htlcswitch/link: add pending commit ticker for stall detection This commit adds a PendingCommitTicker to the link config, which allows us to control how quickly we fail the link if the commitment dance stalls. Now that the mailbox has the ability to cancel packets, when the link fails it will reset the mailbox packets on exit, forcing a reevaluation of the HTLCs against their mailbox expiries. --- htlcswitch/link.go | 14 ++++++ htlcswitch/link_test.go | 103 +++++++++++++++++++++++++++++++++++--- htlcswitch/linkfailure.go | 6 +++ htlcswitch/test_utils.go | 1 + peer.go | 1 + 5 files changed, 117 insertions(+), 8 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index f474303ec5..c7a86c1e0c 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -223,6 +223,11 @@ type ChannelLinkConfig struct { // syncing. FwdPkgGCTicker ticker.Ticker + // PendingCommitTicker is a ticker that allows the link to determine if + // a locally initiated commitment dance gets stuck waiting for the + // remote party to revoke. + PendingCommitTicker ticker.Ticker + // BatchSize is the max size of a batch of updates done to the link // before we do a state update. BatchSize uint32 @@ -1098,6 +1103,11 @@ func (l *channelLink) htlcManager() { return } + case <-l.cfg.PendingCommitTicker.Ticks(): + l.fail(LinkFailureError{code: ErrRemoteUnresponsive}, + "unable to complete dance") + return + // A message from the switch was just received. This indicates // that the link is an intermediate hop in a multi-hop HTLC // circuit. @@ -1934,6 +1944,8 @@ func (l *channelLink) updateCommitTx() error { theirCommitSig, htlcSigs, pendingHTLCs, err := l.channel.SignNextCommitment() if err == lnwallet.ErrNoWindow { + l.cfg.PendingCommitTicker.Resume() + l.log.Tracef("revocation window exhausted, unable to send: "+ "%v, pend_updates=%v, dangling_closes%v", l.channel.PendingLocalUpdateCount(), @@ -1953,6 +1965,8 @@ func (l *channelLink) updateCommitTx() error { return err } + l.cfg.PendingCommitTicker.Pause() + // The remote party now has a new pending commitment, so we'll update // the contract court to be aware of this new set (the prior old remote // pending). diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index ffd53a4752..935ccde3db 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -1699,10 +1699,11 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) ( UpdateContractSignals: func(*contractcourt.ContractSignals) error { return nil }, - Registry: invoiceRegistry, - ChainEvents: &contractcourt.ChainEventSubscription{}, - BatchTicker: bticker, - FwdPkgGCTicker: ticker.NewForce(15 * time.Second), + Registry: invoiceRegistry, + ChainEvents: &contractcourt.ChainEventSubscription{}, + BatchTicker: bticker, + FwdPkgGCTicker: ticker.NewForce(15 * time.Second), + PendingCommitTicker: ticker.New(time.Minute), // Make the BatchSize and Min/MaxFeeUpdateTimeout large enough // to not trigger commit updates automatically during tests. BatchSize: 10000, @@ -4203,10 +4204,11 @@ func (h *persistentLinkHarness) restartLink( UpdateContractSignals: func(*contractcourt.ContractSignals) error { return nil }, - Registry: h.coreLink.cfg.Registry, - ChainEvents: &contractcourt.ChainEventSubscription{}, - BatchTicker: bticker, - FwdPkgGCTicker: ticker.New(5 * time.Second), + Registry: h.coreLink.cfg.Registry, + ChainEvents: &contractcourt.ChainEventSubscription{}, + BatchTicker: bticker, + FwdPkgGCTicker: ticker.New(5 * time.Second), + PendingCommitTicker: ticker.New(time.Minute), // Make the BatchSize and Min/MaxFeeUpdateTimeout large enough // to not trigger commit updates automatically during tests. BatchSize: 10000, @@ -6134,6 +6136,91 @@ func TestChannelLinkReceiveEmptySig(t *testing.T) { aliceLink.Stop() } +// TestPendingCommitTicker tests that a link will fail itself after a timeout if +// the commitment dance stalls out. +func TestPendingCommitTicker(t *testing.T) { + t.Parallel() + + const chanAmt = btcutil.SatoshiPerBitcoin * 5 + const chanReserve = btcutil.SatoshiPerBitcoin * 1 + aliceLink, bobChannel, batchTicker, start, cleanUp, _, err := + newSingleLinkTestHarness(chanAmt, chanReserve) + if err != nil { + t.Fatalf("unable to create link: %v", err) + } + + var ( + coreLink = aliceLink.(*channelLink) + aliceMsgs = coreLink.cfg.Peer.(*mockPeer).sentMsgs + ) + + coreLink.cfg.PendingCommitTicker = ticker.NewForce(time.Millisecond) + + linkErrs := make(chan LinkFailureError) + coreLink.cfg.OnChannelFailure = func(_ lnwire.ChannelID, + _ lnwire.ShortChannelID, linkErr LinkFailureError) { + + linkErrs <- linkErr + } + + if err := start(); err != nil { + t.Fatalf("unable to start test harness: %v", err) + } + defer cleanUp() + + ctx := linkTestContext{ + t: t, + aliceLink: aliceLink, + bobChannel: bobChannel, + aliceMsgs: aliceMsgs, + } + + // Send an HTLC from Alice to Bob, and signal the batch ticker to signa + // a commitment. + htlc, _ := generateHtlcAndInvoice(t, 0) + ctx.sendHtlcAliceToBob(0, htlc) + ctx.receiveHtlcAliceToBob() + batchTicker <- time.Now() + + select { + case msg := <-aliceMsgs: + if _, ok := msg.(*lnwire.CommitSig); !ok { + t.Fatalf("expected CommitSig, got: %T", msg) + } + case <-time.After(time.Second): + t.Fatalf("alice did not send commit sig") + } + + // Check that Alice hasn't failed. + select { + case linkErr := <-linkErrs: + t.Fatalf("link failed unexpectedly: %v", linkErr) + case <-time.After(50 * time.Millisecond): + } + + // Without completing the dance, send another HTLC from Alice to Bob. + // Since the revocation window has been exhausted, we should see the + // link fail itself immediately due to the low pending commit timeout. + // In production this would be much longer, e.g. a minute. + htlc, _ = generateHtlcAndInvoice(t, 1) + ctx.sendHtlcAliceToBob(1, htlc) + ctx.receiveHtlcAliceToBob() + batchTicker <- time.Now() + + // Assert that we get the expected link failure from Alice. + select { + case linkErr := <-linkErrs: + if linkErr.code != ErrRemoteUnresponsive { + t.Fatalf("error code mismatch, "+ + "want: ErrRemoteUnresponsive, got: %v", + linkErr.code) + } + + case <-time.After(time.Second): + t.Fatalf("did not receive failure") + } +} + // assertFailureCode asserts that an error is of type ClearTextError and that // the failure code is as expected. func assertFailureCode(t *testing.T, err error, code lnwire.FailCode) { diff --git a/htlcswitch/linkfailure.go b/htlcswitch/linkfailure.go index b9ec7596fa..840a4d8dad 100644 --- a/htlcswitch/linkfailure.go +++ b/htlcswitch/linkfailure.go @@ -20,6 +20,10 @@ const ( // to fail the link. ErrRemoteError + // ErrRemoteUnresponsive indicates that our peer took too long to + // complete a commitment dance. + ErrRemoteUnresponsive + // ErrSyncError indicates that we failed synchronizing the state of the // channel with our peer. ErrSyncError @@ -71,6 +75,8 @@ func (e LinkFailureError) Error() string { return "internal error" case ErrRemoteError: return "remote error" + case ErrRemoteUnresponsive: + return "remote unresponsive" case ErrSyncError: return "sync error" case ErrInvalidUpdate: diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index c997c4f905..c591e65bc7 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1167,6 +1167,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer, BatchSize: 10, BatchTicker: ticker.NewForce(testBatchTimeout), FwdPkgGCTicker: ticker.NewForce(fwdPkgTimeout), + PendingCommitTicker: ticker.NewForce(time.Minute), MinFeeUpdateTimeout: minFeeUpdateTimeout, MaxFeeUpdateTimeout: maxFeeUpdateTimeout, OnChannelFailure: func(lnwire.ChannelID, lnwire.ShortChannelID, LinkFailureError) {}, diff --git a/peer.go b/peer.go index c6e2ae0251..3ae9977781 100644 --- a/peer.go +++ b/peer.go @@ -669,6 +669,7 @@ func (p *peer) addLink(chanPoint *wire.OutPoint, SyncStates: syncStates, BatchTicker: ticker.New(50 * time.Millisecond), FwdPkgGCTicker: ticker.New(time.Minute), + PendingCommitTicker: ticker.New(time.Minute), BatchSize: 10, UnsafeReplay: cfg.UnsafeReplay, MinFeeUpdateTimeout: htlcswitch.DefaultMinLinkFeeUpdateTimeout, From 55f90be2a57c74e498ace45cff2bf4aa2890551d Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 10:51:48 -0700 Subject: [PATCH 489/562] htlcswitch/mailbox: rename Settle/Fail queue to indicate replies This commit renames the variables associated with processing the Settle/Fail packets to indicate that they are replies. --- htlcswitch/mailbox.go | 66 ++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index 66398e291e..95d88763e1 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -112,10 +112,12 @@ type memoryMailBox struct { messageOutbox chan lnwire.Message msgReset chan chan struct{} - htlcPkts *list.List - pktIndex map[CircuitKey]*list.Element - pktHead *list.Element + // repPkts is a queue for reply packets, e.g. Settles and Fails. + repPkts *list.List + repIndex map[CircuitKey]*list.Element + repHead *list.Element + // addPkts is a dedicated queue for Adds. addPkts *list.List addIndex map[CircuitKey]*list.Element addHead *list.Element @@ -136,13 +138,13 @@ func newMemoryMailBox(cfg *mailBoxConfig) *memoryMailBox { box := &memoryMailBox{ cfg: cfg, wireMessages: list.New(), - htlcPkts: list.New(), + repPkts: list.New(), addPkts: list.New(), messageOutbox: make(chan lnwire.Message), pktOutbox: make(chan *htlcPacket), msgReset: make(chan chan struct{}, 1), pktReset: make(chan chan struct{}, 1), - pktIndex: make(map[CircuitKey]*list.Element), + repIndex: make(map[CircuitKey]*list.Element), addIndex: make(map[CircuitKey]*list.Element), wireShutdown: make(chan struct{}), pktShutdown: make(chan struct{}), @@ -238,17 +240,17 @@ func (m *memoryMailBox) AckPacket(inKey CircuitKey) bool { m.pktCond.L.Lock() defer m.pktCond.L.Unlock() - if entry, ok := m.pktIndex[inKey]; ok { + if entry, ok := m.repIndex[inKey]; ok { // Check whether we are removing the head of the queue. If so, // we must advance the head to the next packet before removing. // It's possible that the courier has already advanced the - // pktHead, so this check prevents the pktHead from getting + // repHead, so this check prevents the repHead from getting // desynchronized. - if entry == m.pktHead { - m.pktHead = entry.Next() + if entry == m.repHead { + m.repHead = entry.Next() } - m.htlcPkts.Remove(entry) - delete(m.pktIndex, inKey) + m.repPkts.Remove(entry) + delete(m.repIndex, inKey) return true } @@ -282,7 +284,7 @@ func (m *memoryMailBox) AckPacket(inKey CircuitKey) bool { // bound for the switch that already have a queued response. func (m *memoryMailBox) HasPacket(inKey CircuitKey) bool { m.pktCond.L.Lock() - _, ok := m.pktIndex[inKey] + _, ok := m.repIndex[inKey] m.pktCond.L.Unlock() return ok @@ -376,7 +378,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { case pktCourier: m.pktCond.L.Lock() - for m.pktHead == nil && m.addHead == nil { + for m.repHead == nil && m.addHead == nil { m.pktCond.Wait() select { @@ -385,7 +387,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { // any un-ACK'd messages are re-delivered upon // reconnect. case pktDone := <-m.pktReset: - m.pktHead = m.htlcPkts.Front() + m.repHead = m.repPkts.Front() m.addHead = m.addPkts.Front() close(pktDone) @@ -399,8 +401,8 @@ func (m *memoryMailBox) mailCourier(cType courierType) { } var ( - nextPkt *htlcPacket - nextPktEl *list.Element + nextRep *htlcPacket + nextRepEl *list.Element nextAdd *pktWithExpiry nextAddEl *list.Element nextMsg lnwire.Message @@ -424,9 +426,9 @@ func (m *memoryMailBox) mailCourier(cType courierType) { // pending Add if it's present. Due to clock // monotonicity, we know that the head of the Adds is // the next to expire. - if m.pktHead != nil { - nextPkt = m.pktHead.Value.(*htlcPacket) - nextPktEl = m.pktHead + if m.repHead != nil { + nextRep = m.repHead.Value.(*htlcPacket) + nextRepEl = m.repHead } if m.addHead != nil { nextAdd = m.addHead.Value.(*pktWithExpiry) @@ -479,8 +481,8 @@ func (m *memoryMailBox) mailCourier(cType courierType) { // same channel, but we can control which is delivered // by exclusively making one nil and the other non-nil. // We know from our loop condition that at least one - // nextPkt and nextAdd are non-nil. - if nextPkt != nil { + // nextRep and nextAdd are non-nil. + if nextRep != nil { pktOutbox = m.pktOutbox } else { addOutbox = m.pktOutbox @@ -503,12 +505,12 @@ func (m *memoryMailBox) mailCourier(cType courierType) { } select { - case pktOutbox <- nextPkt: + case pktOutbox <- nextRep: m.pktCond.L.Lock() - // Only advance the pktHead if this Settle or + // Only advance the repHead if this Settle or // Fail is still at the head of the queue. - if m.pktHead != nil && m.pktHead == nextPktEl { - m.pktHead = m.pktHead.Next() + if m.repHead != nil && m.repHead == nextRepEl { + m.repHead = m.repHead.Next() } m.pktCond.L.Unlock() @@ -526,7 +528,7 @@ func (m *memoryMailBox) mailCourier(cType courierType) { case pktDone := <-m.pktReset: m.pktCond.L.Lock() - m.pktHead = m.htlcPkts.Front() + m.repHead = m.repPkts.Front() m.addHead = m.addPkts.Front() m.pktCond.L.Unlock() @@ -566,17 +568,17 @@ func (m *memoryMailBox) AddPacket(pkt *htlcPacket) error { m.pktCond.L.Lock() switch htlc := pkt.htlc.(type) { - // Split off Settle/Fail packets into the htlcPkts queue. + // Split off Settle/Fail packets into the repPkts queue. case *lnwire.UpdateFulfillHTLC, *lnwire.UpdateFailHTLC: - if _, ok := m.pktIndex[pkt.inKey()]; ok { + if _, ok := m.repIndex[pkt.inKey()]; ok { m.pktCond.L.Unlock() return ErrPacketAlreadyExists } - entry := m.htlcPkts.PushBack(pkt) - m.pktIndex[pkt.inKey()] = entry - if m.pktHead == nil { - m.pktHead = entry + entry := m.repPkts.PushBack(pkt) + m.repIndex[pkt.inKey()] = entry + if m.repHead == nil { + m.repHead = entry } // Split off Add packets into the addPkts queue. From 95e2809ba3e40bcb5c74a7b1ac71804a423180f6 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 14 Apr 2020 20:08:36 -0700 Subject: [PATCH 490/562] build: bump version to v0.10.0-beta.rc1 We also add '.' to the semantic versioning alphabet to ensure it isn't stripped out. --- build/version.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/version.go b/build/version.go index 6049735ce5..c22b8390c8 100644 --- a/build/version.go +++ b/build/version.go @@ -32,7 +32,7 @@ var ( // semanticAlphabet is the set of characters that are permitted for use in an // AppPreRelease. -const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-" +const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-." // These constants define the application version and follow the semantic // versioning 2.0.0 spec (http://semver.org/). @@ -41,14 +41,14 @@ const ( AppMajor uint = 0 // AppMinor defines the minor version of this binary. - AppMinor uint = 9 + AppMinor uint = 10 // AppPatch defines the application patch for this binary. AppPatch uint = 0 // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta" + AppPreRelease = "beta.rc1" ) func init() { From 0a3fdf0271f8b3dc6795aa01e4deb2386e56a59e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 22:34:16 -0700 Subject: [PATCH 491/562] htlcswitch/test_utils: extend PendingCommit timeout Flakes locally on darwin. --- htlcswitch/test_utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index c591e65bc7..614abce695 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1167,7 +1167,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer, BatchSize: 10, BatchTicker: ticker.NewForce(testBatchTimeout), FwdPkgGCTicker: ticker.NewForce(fwdPkgTimeout), - PendingCommitTicker: ticker.NewForce(time.Minute), + PendingCommitTicker: ticker.NewForce(2 * time.Minute), MinFeeUpdateTimeout: minFeeUpdateTimeout, MaxFeeUpdateTimeout: maxFeeUpdateTimeout, OnChannelFailure: func(lnwire.ChannelID, lnwire.ShortChannelID, LinkFailureError) {}, From b467f549b72105eae214b4e799f437cc219819e0 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 Apr 2020 22:33:53 -0700 Subject: [PATCH 492/562] htlcswitch/link: return error from AddPacket --- htlcswitch/link.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index c7a86c1e0c..3290573a24 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -2309,8 +2309,7 @@ func (l *channelLink) HandleSwitchPacket(pkt *htlcPacket) error { l.log.Tracef("received switch packet inkey=%v, outkey=%v", pkt.inKey(), pkt.outKey()) - l.mailBox.AddPacket(pkt) - return nil + return l.mailBox.AddPacket(pkt) } // HandleChannelUpdate handles the htlc requests as settle/add/fail which sent From eec3799da9cb7931ae0b36d757b2621dbc8fd60f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 15 Apr 2020 12:32:02 -0700 Subject: [PATCH 493/562] build: bump version to bump version to v0.10.0-beta.rc2 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index c22b8390c8..774e781207 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc1" + AppPreRelease = "beta.rc2" ) func init() { From 6e8442b3339bdae89f048f1dca8474310a4f1573 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 16 Apr 2020 15:20:23 +0200 Subject: [PATCH 494/562] routing: move payment session constructor --- routing/integrated_routing_context_test.go | 18 ++++--- routing/payment_session.go | 24 +++++++++ routing/payment_session_source.go | 24 ++++----- routing/payment_session_test.go | 59 +++++++++++----------- 4 files changed, 73 insertions(+), 52 deletions(-) diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index 457ed4f467..cc71560d8b 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -140,18 +140,20 @@ func (c *integratedRoutingContext) testPayment(maxShards uint32) ([]htlcAttempt, MaxShards: maxShards, } - session := &paymentSession{ - getBandwidthHints: getBandwidthHints, - payment: &payment, - pathFinder: findPath, - getRoutingGraph: func() (routingGraph, func(), error) { + session, err := newPaymentSession( + &payment, getBandwidthHints, + func() (routingGraph, func(), error) { return c.graph, func() {}, nil }, - pathFindingConfig: c.pathFindingCfg, - missionControl: mc, - minShardAmt: lnwire.NewMSatFromSatoshis(5000), + mc, c.pathFindingCfg, + ) + if err != nil { + c.t.Fatal(err) } + // Override default minimum shard amount. + session.minShardAmt = lnwire.NewMSatFromSatoshis(5000) + // Now the payment control loop starts. It will keep trying routes until // the payment succeeds. var ( diff --git a/routing/payment_session.go b/routing/payment_session.go index c5a20f7a1a..2eef929e2e 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -126,6 +126,30 @@ type paymentSession struct { minShardAmt lnwire.MilliSatoshi } +// newPaymentSession instantiates a new payment session. +func newPaymentSession(p *LightningPayment, + getBandwidthHints func() (map[uint64]lnwire.MilliSatoshi, error), + getRoutingGraph func() (routingGraph, func(), error), + missionControl MissionController, pathFindingConfig PathFindingConfig) ( + *paymentSession, error) { + + edges, err := RouteHintsToEdges(p.RouteHints, p.Target) + if err != nil { + return nil, err + } + + return &paymentSession{ + additionalEdges: edges, + getBandwidthHints: getBandwidthHints, + payment: p, + pathFinder: findPath, + getRoutingGraph: getRoutingGraph, + pathFindingConfig: pathFindingConfig, + missionControl: missionControl, + minShardAmt: DefaultShardMinAmt, + }, nil +} + // RequestRoute returns a route which is likely to be capable for successfully // routing the specified HTLC payment to the target node. Initially the first // set of paths returned from this method may encounter routing failure along diff --git a/routing/payment_session_source.go b/routing/payment_session_source.go index a6016ab85e..8122ff7117 100644 --- a/routing/payment_session_source.go +++ b/routing/payment_session_source.go @@ -62,11 +62,6 @@ func (m *SessionSource) getRoutingGraph() (routingGraph, func(), error) { func (m *SessionSource) NewPaymentSession(p *LightningPayment) ( PaymentSession, error) { - edges, err := RouteHintsToEdges(p.RouteHints, p.Target) - if err != nil { - return nil, err - } - sourceNode, err := m.Graph.SourceNode() if err != nil { return nil, err @@ -78,16 +73,15 @@ func (m *SessionSource) NewPaymentSession(p *LightningPayment) ( return generateBandwidthHints(sourceNode, m.QueryBandwidth) } - return &paymentSession{ - additionalEdges: edges, - getBandwidthHints: getBandwidthHints, - payment: p, - pathFinder: findPath, - getRoutingGraph: m.getRoutingGraph, - pathFindingConfig: m.PathFindingConfig, - missionControl: m.MissionControl, - minShardAmt: DefaultShardMinAmt, - }, nil + session, err := newPaymentSession( + p, getBandwidthHints, m.getRoutingGraph, + m.MissionControl, m.PathFindingConfig, + ) + if err != nil { + return nil, err + } + + return session, nil } // NewPaymentSessionEmpty creates a new paymentSession instance that is empty, diff --git a/routing/payment_session_test.go b/routing/payment_session_test.go index 60d960b87c..ba55fcea6e 100644 --- a/routing/payment_session_test.go +++ b/routing/payment_session_test.go @@ -13,9 +13,36 @@ func TestRequestRoute(t *testing.T) { height = 10 ) - findPath := func( - g *graphParams, - r *RestrictParams, cfg *PathFindingConfig, + cltvLimit := uint32(30) + finalCltvDelta := uint16(8) + + payment := &LightningPayment{ + CltvLimit: cltvLimit, + FinalCLTVDelta: finalCltvDelta, + Amount: 1000, + FeeLimit: 1000, + } + + session, err := newPaymentSession( + payment, + func() (map[uint64]lnwire.MilliSatoshi, + error) { + + return nil, nil + }, + func() (routingGraph, func(), error) { + return &sessionGraph{}, func() {}, nil + }, + &MissionControl{cfg: &MissionControlConfig{}}, + PathFindingConfig{}, + ) + if err != nil { + t.Fatal(err) + } + + // Override pathfinder with a mock. + session.pathFinder = func( + g *graphParams, r *RestrictParams, cfg *PathFindingConfig, source, target route.Vertex, amt lnwire.MilliSatoshi, finalHtlcExpiry int32) ([]*channeldb.ChannelEdgePolicy, error) { @@ -38,32 +65,6 @@ func TestRequestRoute(t *testing.T) { return path, nil } - cltvLimit := uint32(30) - finalCltvDelta := uint16(8) - - payment := &LightningPayment{ - CltvLimit: cltvLimit, - FinalCLTVDelta: finalCltvDelta, - Amount: 1000, - FeeLimit: 1000, - } - - session := &paymentSession{ - getBandwidthHints: func() (map[uint64]lnwire.MilliSatoshi, - error) { - - return nil, nil - }, - payment: payment, - pathFinder: findPath, - missionControl: &MissionControl{ - cfg: &MissionControlConfig{}, - }, - getRoutingGraph: func() (routingGraph, func(), error) { - return &sessionGraph{}, func() {}, nil - }, - } - route, err := session.RequestRoute( payment.Amount, payment.FeeLimit, 0, height, ) From 8920e20cf7e5f72a4abefeb7791343ba03b499e8 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 17 Apr 2020 09:22:32 +0200 Subject: [PATCH 495/562] cert: define ExtendedKeyUsage as required by macOS 10.15 --- cert/selfsigned.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cert/selfsigned.go b/cert/selfsigned.go index f67e8cd8ae..244d64b798 100644 --- a/cert/selfsigned.go +++ b/cert/selfsigned.go @@ -228,6 +228,7 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, IsCA: true, // so can sign self. BasicConstraintsValid: true, From 9bd7eb74b68504d683a5310b406a1e68c4f3bef6 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 16 Apr 2020 15:22:44 +0200 Subject: [PATCH 496/562] routing: add prefix logger for payment session --- routing/payment_session.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/routing/payment_session.go b/routing/payment_session.go index 2eef929e2e..6c4677686d 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -1,6 +1,10 @@ package routing import ( + "fmt" + + "github.com/btcsuite/btclog" + "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" @@ -124,6 +128,9 @@ type paymentSession struct { // specified in the payment is one, under no circumstances splitting // will happen and this value remains unused. minShardAmt lnwire.MilliSatoshi + + // log is a payment session-specific logger. + log btclog.Logger } // newPaymentSession instantiates a new payment session. @@ -138,6 +145,8 @@ func newPaymentSession(p *LightningPayment, return nil, err } + logPrefix := fmt.Sprintf("PaymentSession(%x):", p.PaymentHash) + return &paymentSession{ additionalEdges: edges, getBandwidthHints: getBandwidthHints, @@ -147,6 +156,7 @@ func newPaymentSession(p *LightningPayment, pathFindingConfig: pathFindingConfig, missionControl: missionControl, minShardAmt: DefaultShardMinAmt, + log: build.NewPrefixLog(logPrefix, log), }, nil } @@ -206,8 +216,7 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, return nil, err } - log.Debugf("PaymentSession for %x: trying pathfinding with %v", - p.payment.PaymentHash, maxAmt) + p.log.Debugf("pathfinding for amt=%v", maxAmt) // Get a routing graph. routingGraph, cleanup, err := p.getRoutingGraph() @@ -237,6 +246,10 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, // No splitting if this is the last shard. isLastShard := activeShards+1 >= p.payment.MaxShards if isLastShard { + p.log.Debugf("not splitting because shard "+ + "limit %v has been reached", + p.payment.MaxShards) + return nil, errNoPathFound } @@ -246,6 +259,10 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, // Put a lower bound on the minimum shard size. if maxAmt < p.minShardAmt { + p.log.Debugf("not splitting because minimum "+ + "shard amount %v has been reached", + p.minShardAmt) + return nil, errNoPathFound } From 805641adf5e771e4f29375da547bdd988ccf8c24 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 16 Apr 2020 15:08:07 +0200 Subject: [PATCH 497/562] routing: do not split payment if destination does not support mpp --- routing/payment_session.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/routing/payment_session.go b/routing/payment_session.go index 6c4677686d..f5a49eff04 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -243,6 +243,15 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, switch { case err == errNoPathFound: + // Don't split if this is a legacy payment without mpp + // record. + if p.payment.PaymentAddr == nil { + p.log.Debugf("not splitting because payment " + + "address is unspecified") + + return nil, errNoPathFound + } + // No splitting if this is the last shard. isLastShard := activeShards+1 >= p.payment.MaxShards if isLastShard { From f44a9e1d4cb7a1a6951a9664856c7c4bae030a87 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 16 Apr 2020 10:36:58 +0200 Subject: [PATCH 498/562] routing/test: make test channel capacities configurable --- routing/integrated_routing_test.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go index 2fdf7136e9..d0aa4d084f 100644 --- a/routing/integrated_routing_test.go +++ b/routing/integrated_routing_test.go @@ -107,7 +107,7 @@ func onePathGraph(g *mockGraph) { g.addChannel(chanIm1Target, targetNodeID, im1NodeID, 100000) } -func twoPathGraph(g *mockGraph) { +func twoPathGraph(g *mockGraph, capacityOut, capacityIn btcutil.Amount) { // Create the following network of nodes: // source -> intermediate1 -> target // source -> intermediate2 -> target @@ -120,10 +120,10 @@ func twoPathGraph(g *mockGraph) { intermediate2 := newMockNode(im2NodeID) g.addNode(intermediate2) - g.addChannel(chanSourceIm1, sourceNodeID, im1NodeID, 200000) - g.addChannel(chanSourceIm2, sourceNodeID, im2NodeID, 200000) - g.addChannel(chanIm1Target, targetNodeID, im1NodeID, 100000) - g.addChannel(chanIm2Target, targetNodeID, im2NodeID, 100000) + g.addChannel(chanSourceIm1, sourceNodeID, im1NodeID, capacityOut) + g.addChannel(chanSourceIm2, sourceNodeID, im2NodeID, capacityOut) + g.addChannel(chanIm1Target, targetNodeID, im1NodeID, capacityIn) + g.addChannel(chanIm2Target, targetNodeID, im2NodeID, capacityIn) } var mppTestCases = []mppSendTestCase{ @@ -136,8 +136,10 @@ var mppTestCases = []mppSendTestCase{ // too. Mpp payment complete. { - name: "sufficient inbound", - graph: twoPathGraph, + name: "sufficient inbound", + graph: func(g *mockGraph) { + twoPathGraph(g, 200000, 100000) + }, amt: 70000, expectedAttempts: 5, expectedSuccesses: []expectedHtlcSuccess{ @@ -155,8 +157,10 @@ var mppTestCases = []mppSendTestCase{ // Test that a cap on the max htlcs makes it impossible to pay. { - name: "no splitting", - graph: twoPathGraph, + name: "no splitting", + graph: func(g *mockGraph) { + twoPathGraph(g, 200000, 100000) + }, amt: 70000, expectedAttempts: 2, expectedSuccesses: []expectedHtlcSuccess{}, From 7fc1938f10bc5e00163286441b4b96bb03548447 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 16 Apr 2020 10:45:00 +0200 Subject: [PATCH 499/562] routing: payment splitting pre-check This commit reverts cb4cd49dc8d3b0255afe9ff29af9c46c2dbb2c98 to bring back the insufficient local balance failure. Distinguishing betweeen this failure and a regular "no route" failure prevents meaningless htlcs from being sent out. --- channeldb/payments.go | 3 --- routing/integrated_routing_test.go | 13 ++++++++++ routing/pathfind.go | 38 ++++++++++++++++++++---------- routing/pathfind_test.go | 7 +++--- routing/payment_session.go | 20 ++++++++++++++++ 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/channeldb/payments.go b/channeldb/payments.go index 16497dcdc5..7c5f49a2af 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -116,9 +116,6 @@ const ( // FailureReasonInsufficientBalance indicates that we didn't have enough // balance to complete the payment. - // - // This reason isn't assigned anymore, but may still exist for older - // payments. FailureReasonInsufficientBalance FailureReason = 4 // TODO(halseth): cancel state. diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go index d0aa4d084f..1d897d8a86 100644 --- a/routing/integrated_routing_test.go +++ b/routing/integrated_routing_test.go @@ -192,6 +192,19 @@ var mppTestCases = []mppSendTestCase{ expectedFailure: true, maxShards: 1000, }, + + // Test that no attempts are made if the total local balance is + // insufficient. + { + name: "insufficient total balance", + graph: func(g *mockGraph) { + twoPathGraph(g, 100000, 500000) + }, + amt: 300000, + expectedAttempts: 0, + expectedFailure: true, + maxShards: 10, + }, } // TestMppSend tests that a payment can be completed using multiple shards. diff --git a/routing/pathfind.go b/routing/pathfind.go index b6879cc6d8..e5def09b53 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -326,13 +326,14 @@ type PathFindingConfig struct { MinProbability float64 } -// getMaxOutgoingAmt returns the maximum available balance in any of the -// channels of the given node. -func getMaxOutgoingAmt(node route.Vertex, outgoingChan *uint64, +// getOutgoingBalance returns the maximum available balance in any of the +// channels of the given node. The second return parameters is the total +// available balance. +func getOutgoingBalance(node route.Vertex, outgoingChan *uint64, bandwidthHints map[uint64]lnwire.MilliSatoshi, - g routingGraph) (lnwire.MilliSatoshi, error) { + g routingGraph) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, error) { - var max lnwire.MilliSatoshi + var max, total lnwire.MilliSatoshi cb := func(edgeInfo *channeldb.ChannelEdgeInfo, outEdge, _ *channeldb.ChannelEdgePolicy) error { @@ -349,26 +350,30 @@ func getMaxOutgoingAmt(node route.Vertex, outgoingChan *uint64, bandwidth, ok := bandwidthHints[chanID] - // If the bandwidth is not available for whatever reason, don't - // fail the pathfinding early. + // If the bandwidth is not available, use the channel capacity. + // This can happen when a channel is added to the graph after + // we've already queried the bandwidth hints. if !ok { - max = lnwire.MaxMilliSatoshi - return nil + bandwidth = lnwire.NewMSatFromSatoshis( + edgeInfo.Capacity, + ) } if bandwidth > max { max = bandwidth } + total += bandwidth + return nil } // Iterate over all channels of the to node. err := g.forEachNodeChannel(node, cb) if err != nil { - return 0, err + return 0, 0, err } - return max, err + return max, total, err } // findPath attempts to find a path from the source node within the ChannelGraph @@ -447,12 +452,21 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, self := g.graph.sourceNode() if source == self { - max, err := getMaxOutgoingAmt( + max, total, err := getOutgoingBalance( self, r.OutgoingChannelID, g.bandwidthHints, g.graph, ) if err != nil { return nil, err } + + // If the total outgoing balance isn't sufficient, it will be + // impossible to complete the payment. + if total < amt { + return nil, errInsufficientBalance + } + + // If there is only not enough capacity on a single route, it + // may still be possible to complete the payment by splitting. if max < amt { return nil, errNoPathFound } diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 0683f36ee4..deaccb2898 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -1768,7 +1768,7 @@ func TestPathInsufficientCapacity(t *testing.T) { noRestrictions, testPathFindingConfig, sourceNode.PubKeyBytes, target, payAmt, 0, ) - if err != errNoPathFound { + if err != errInsufficientBalance { t.Fatalf("graph shouldn't be able to support payment: %v", err) } } @@ -2790,6 +2790,7 @@ type pathFindingTestContext struct { t *testing.T graph *channeldb.ChannelGraph restrictParams RestrictParams + bandwidthHints map[uint64]lnwire.MilliSatoshi pathFindingConfig PathFindingConfig testGraphInstance *testGraphInstance source route.Vertex @@ -2844,8 +2845,8 @@ func (c *pathFindingTestContext) findPath(target route.Vertex, error) { return dbFindPath( - c.graph, nil, nil, &c.restrictParams, &c.pathFindingConfig, - c.source, target, amt, 0, + c.graph, nil, c.bandwidthHints, &c.restrictParams, + &c.pathFindingConfig, c.source, target, amt, 0, ) } diff --git a/routing/payment_session.go b/routing/payment_session.go index f5a49eff04..5cd8d9f7d7 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -30,6 +30,10 @@ const ( // not exist in the graph. errNoPathFound + // errInsufficientLocalBalance is returned when none of the local + // channels have enough balance for the payment. + errInsufficientBalance + // errEmptyPaySession is returned when the empty payment session is // queried for a route. errEmptyPaySession @@ -57,6 +61,9 @@ func (e noRouteError) Error() string { case errEmptyPaySession: return "empty payment session" + case errInsufficientBalance: + return "insufficient local balance" + default: return "unknown no-route error" } @@ -73,6 +80,9 @@ func (e noRouteError) FailureReason() channeldb.FailureReason { return channeldb.FailureReasonNoRoute + case errInsufficientBalance: + return channeldb.FailureReasonInsufficientBalance + default: return channeldb.FailureReasonError } @@ -278,6 +288,16 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, // Go pathfinding. continue + // If there isn't enough local bandwidth, there is no point in + // splitting. It won't be possible to create a complete set in + // any case, but the sent out partial payments would be held by + // the receiver until the mpp timeout. + case err == errInsufficientBalance: + p.log.Debug("not splitting because local balance " + + "is insufficient") + + return nil, err + case err != nil: return nil, err } From 7785d1691904ad81c05d98ad91459b8fcec8e365 Mon Sep 17 00:00:00 2001 From: Carsten Otto Date: Sat, 18 Apr 2020 11:12:18 +0100 Subject: [PATCH 500/562] fix typos --- lnrpc/rpc.pb.go | 2 +- lnrpc/rpc.proto | 2 +- lnrpc/rpc.swagger.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 28195cd61d..10f9a7cde9 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -7161,7 +7161,7 @@ type Hop struct { //this field MUST be set to true for them to be encoded properly. TlvPayload bool `protobuf:"varint,9,opt,name=tlv_payload,json=tlvPayload,proto3" json:"tlv_payload,omitempty"` //* - //An optional TLV record tha singals the use of an MPP payment. If present, + //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. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index fdfd1857f0..1317b96409 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2458,7 +2458,7 @@ message Hop { bool tlv_payload = 9; /** - An optional TLV record tha singals the use of an MPP payment. If present, + 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. diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index c588125da8..90859472dc 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -3125,7 +3125,7 @@ }, "mpp_record": { "$ref": "#/definitions/lnrpcMPPRecord", - "description": "*\nAn optional TLV record tha singals 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": "*\nAn 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." }, "custom_records": { "type": "object", From 4ed0a35b109507db4c5c571fcc474f18af47e993 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 20 Apr 2020 14:17:53 -0700 Subject: [PATCH 501/562] build: bump dep to cert v1.0.2 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 54f57f80ff..a4943762af 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200 github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d github.com/lightningnetwork/lightning-onion v1.0.1 - github.com/lightningnetwork/lnd/cert v1.0.1 + github.com/lightningnetwork/lnd/cert v1.0.2 github.com/lightningnetwork/lnd/queue v1.0.3 github.com/lightningnetwork/lnd/ticker v1.0.0 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 From 6ec2cc566964ee2178006866350a7838b2442036 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 17 Apr 2020 15:21:38 -0700 Subject: [PATCH 502/562] htlcswitch/mailbox_test: use mailboxContext everywhere Modifies some of the older mailbox tests that were left untouched as of PR #4174 to use the new mailbox test context. This ensures that the config members of each mailbox's config are properly initialized. In certain instances where travis is slow, this would cause test panics. --- htlcswitch/mailbox_test.go | 88 ++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/htlcswitch/mailbox_test.go b/htlcswitch/mailbox_test.go index 655caaffe7..7e15eb040f 100644 --- a/htlcswitch/mailbox_test.go +++ b/htlcswitch/mailbox_test.go @@ -11,6 +11,8 @@ import ( "github.com/lightningnetwork/lnd/lnwire" ) +const testExpiry = time.Minute + // TestMailBoxCouriers tests that both aspects of the mailBox struct works // properly. Both packets and messages should be able to added to each // respective mailbox concurrently, and also messages/packets should also be @@ -20,12 +22,8 @@ func TestMailBoxCouriers(t *testing.T) { // First, we'll create new instance of the current default mailbox // type. - mailBox := newMemoryMailBox(&mailBoxConfig{ - clock: clock.NewDefaultClock(), - expiry: time.Minute, - }) - mailBox.Start() - defer mailBox.Stop() + ctx := newMailboxContext(t, time.Now(), testExpiry) + defer ctx.mailbox.Stop() // We'll be adding 10 message of both types to the mailbox. const numPackets = 10 @@ -44,7 +42,7 @@ func TestMailBoxCouriers(t *testing.T) { } sentPackets[i] = pkt - err := mailBox.AddPacket(pkt) + err := ctx.mailbox.AddPacket(pkt) if err != nil { t.Fatalf("unable to add packet: %v", err) } @@ -59,7 +57,10 @@ func TestMailBoxCouriers(t *testing.T) { } sentMessages[i] = msg - mailBox.AddMessage(msg) + err := ctx.mailbox.AddMessage(msg) + if err != nil { + t.Fatalf("unable to add message: %v", err) + } } // Now we'll attempt to read back the packets/messages we added to the @@ -73,14 +74,14 @@ func TestMailBoxCouriers(t *testing.T) { select { case <-timeout: t.Fatalf("didn't recv pkt after timeout") - case pkt := <-mailBox.PacketOutBox(): + case pkt := <-ctx.mailbox.PacketOutBox(): recvdPackets = append(recvdPackets, pkt) } } else { select { case <-timeout: t.Fatalf("didn't recv message after timeout") - case msg := <-mailBox.MessageOutBox(): + case msg := <-ctx.mailbox.MessageOutBox(): recvdMessages = append(recvdMessages, msg) } } @@ -111,13 +112,19 @@ func TestMailBoxCouriers(t *testing.T) { // Now that we've received all of the intended msgs/pkts, ack back half // of the packets. for _, recvdPkt := range recvdPackets[:halfPackets] { - mailBox.AckPacket(recvdPkt.inKey()) + ctx.mailbox.AckPacket(recvdPkt.inKey()) } // With the packets drained and partially acked, we reset the mailbox, // simulating a link shutting down and then coming back up. - mailBox.ResetMessages() - mailBox.ResetPackets() + err := ctx.mailbox.ResetMessages() + if err != nil { + t.Fatalf("unable to reset messages: %v", err) + } + err = ctx.mailbox.ResetPackets() + if err != nil { + t.Fatalf("unable to reset packets: %v", err) + } // Now, we'll use the same alternating strategy to read from our // mailbox. All wire messages are dropped on startup, but any unacked @@ -130,12 +137,12 @@ func TestMailBoxCouriers(t *testing.T) { select { case <-timeout: t.Fatalf("didn't recv pkt after timeout") - case pkt := <-mailBox.PacketOutBox(): + case pkt := <-ctx.mailbox.PacketOutBox(): recvdPackets2 = append(recvdPackets2, pkt) } } else { select { - case <-mailBox.MessageOutBox(): + case <-ctx.mailbox.MessageOutBox(): t.Fatalf("should not receive wire msg after reset") default: } @@ -163,18 +170,17 @@ func TestMailBoxCouriers(t *testing.T) { func TestMailBoxResetAfterShutdown(t *testing.T) { t.Parallel() - m := newMemoryMailBox(&mailBoxConfig{}) - m.Start() + ctx := newMailboxContext(t, time.Now(), time.Second) // Stop the mailbox, then try to reset the message and packet couriers. - m.Stop() + ctx.mailbox.Stop() - err := m.ResetMessages() + err := ctx.mailbox.ResetMessages() if err != ErrMailBoxShuttingDown { t.Fatalf("expected ErrMailBoxShuttingDown, got: %v", err) } - err = m.ResetPackets() + err = ctx.mailbox.ResetPackets() if err != ErrMailBoxShuttingDown { t.Fatalf("expected ErrMailBoxShuttingDown, got: %v", err) } @@ -375,12 +381,8 @@ func TestMailBoxPacketPrioritization(t *testing.T) { // First, we'll create new instance of the current default mailbox // type. - mailBox := newMemoryMailBox(&mailBoxConfig{ - clock: clock.NewDefaultClock(), - expiry: time.Minute, - }) - mailBox.Start() - defer mailBox.Stop() + ctx := newMailboxContext(t, time.Now(), testExpiry) + defer ctx.mailbox.Stop() const numPackets = 5 @@ -418,7 +420,7 @@ func TestMailBoxPacketPrioritization(t *testing.T) { sentPackets[i] = pkt - err := mailBox.AddPacket(pkt) + err := ctx.mailbox.AddPacket(pkt) if err != nil { t.Fatalf("failed to add packet: %v", err) } @@ -435,7 +437,7 @@ func TestMailBoxPacketPrioritization(t *testing.T) { // or Add2 due to the prioritization between the split queue. for i := 0; i < numPackets; i++ { select { - case pkt := <-mailBox.PacketOutBox(): + case pkt := <-ctx.mailbox.PacketOutBox(): var expPkt *htlcPacket switch i { case 0: @@ -504,21 +506,19 @@ func TestMailBoxAddExpiry(t *testing.T) { func TestMailBoxDuplicateAddPacket(t *testing.T) { t.Parallel() - mailBox := newMemoryMailBox(&mailBoxConfig{ - clock: clock.NewDefaultClock(), - }) - mailBox.Start() - defer mailBox.Stop() + ctx := newMailboxContext(t, time.Now(), testExpiry) + ctx.mailbox.Start() + defer ctx.mailbox.Stop() addTwice := func(t *testing.T, pkt *htlcPacket) { // The first add should succeed. - err := mailBox.AddPacket(pkt) + err := ctx.mailbox.AddPacket(pkt) if err != nil { t.Fatalf("unable to add packet: %v", err) } // Adding again with the same incoming circuit key should fail. - err = mailBox.AddPacket(pkt) + err = ctx.mailbox.AddPacket(pkt) if err != ErrPacketAlreadyExists { t.Fatalf("expected ErrPacketAlreadyExists, got: %v", err) } @@ -548,8 +548,22 @@ func TestMailOrchestrator(t *testing.T) { // First, we'll create a new instance of our orchestrator. mo := newMailOrchestrator(&mailOrchConfig{ - clock: clock.NewDefaultClock(), - expiry: time.Minute, + fetchUpdate: func(sid lnwire.ShortChannelID) ( + *lnwire.ChannelUpdate, error) { + return &lnwire.ChannelUpdate{ + ShortChannelID: sid, + }, nil + }, + forwardPackets: func(_ chan struct{}, + pkts ...*htlcPacket) chan error { + // Close the channel immediately so the goroutine + // logging errors can exit. + errChan := make(chan error) + close(errChan) + return errChan + }, + clock: clock.NewTestClock(time.Now()), + expiry: testExpiry, }) defer mo.Stop() From 3ab5899853ec0a891f103ea08f90de63f4953032 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 20 Apr 2020 22:12:49 -0700 Subject: [PATCH 503/562] lnwallet/channel: fix log typo --- lnwallet/channel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 5f6eef9225..4cf75c0a20 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2414,7 +2414,7 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool, chainfee.SatPerKWeight(weight) if effFeeRate < chainfee.FeePerKwFloor { return nil, fmt.Errorf("height=%v, for ChannelPoint(%v) "+ - "attempts to create commitment wigh feerate %v: %v", + "attempts to create commitment with feerate %v: %v", nextHeight, lc.channelState.FundingOutpoint, effFeeRate, spew.Sdump(commitTx)) } From ce00f52ca2c028375c0b06c1730097a9d0e88a37 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 21 Apr 2020 10:18:57 +0200 Subject: [PATCH 504/562] make: add new release flags --- make/release_flags.mk | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 make/release_flags.mk diff --git a/make/release_flags.mk b/make/release_flags.mk new file mode 100644 index 0000000000..7b64d3fd0a --- /dev/null +++ b/make/release_flags.mk @@ -0,0 +1,55 @@ +VERSION_TAG = $(shell date +%Y%m%d)-01 +VERSION_CHECK = @$(call print, "Building master with date version tag") + +BUILD_SYSTEM = darwin-386 \ +darwin-amd64 \ +dragonfly-amd64 \ +freebsd-386 \ +freebsd-amd64 \ +freebsd-arm \ +illumos-amd64 \ +linux-386 \ +linux-amd64 \ +linux-armv6 \ +linux-armv7 \ +linux-arm64 \ +linux-ppc64 \ +linux-ppc64le \ +linux-mips \ +linux-mipsle \ +linux-mips64 \ +linux-mips64le \ +linux-s390x \ +netbsd-386 \ +netbsd-amd64 \ +netbsd-arm \ +netbsd-arm64 \ +openbsd-386 \ +openbsd-amd64 \ +openbsd-arm \ +openbsd-arm64 \ +solaris-amd64 \ +windows-386 \ +windows-amd64 \ +windows-arm + +RELEASE_TAGS = autopilotrpc signrpc walletrpc chainrpc invoicesrpc watchtowerrpc + +# One can either specify a git tag as the version suffix or one is generated +# from the current date. +ifneq ($(tag),) +VERSION_TAG = $(tag) +VERSION_CHECK = ./build/release/release.sh check-tag "$(VERSION_TAG)" +endif + +# By default we will build all systems. But with the 'sys' tag, a specific +# system can be specified. This is useful to release for a subset of +# systems/architectures. +ifneq ($(sys),) +BUILD_SYSTEM = $(sys) +endif + +# Use all build tags by default but allow them to be overwritten. +ifneq ($(tags),) +RELEASE_TAGS = $(tags) +endif From 317ccb2cc99635dfd6f1203771c88d50cdd0cf89 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 21 Apr 2020 10:19:58 +0200 Subject: [PATCH 505/562] make+build: call release script from makefile --- Makefile | 23 +++- build/release/release.sh | 262 +++++++++++++++++++++------------------ 2 files changed, 156 insertions(+), 129 deletions(-) diff --git a/Makefile b/Makefile index 5df705078b..a36999c3dd 100644 --- a/Makefile +++ b/Makefile @@ -49,17 +49,25 @@ MAKE := make XARGS := xargs -L 1 include make/testing_flags.mk +include make/release_flags.mk DEV_TAGS := $(if ${tags},$(DEV_TAGS) ${tags},$(DEV_TAGS)) -make_ldflags = -ldflags "$(shell echo -X $(PKG)/build.Commit=$(COMMIT) \ +# We only return the part inside the double quote here to avoid escape issues +# when calling the external release script. The second parameter can be used to +# add additional ldflags if needed (currently only used for the release). +make_ldflags = $(2) -X $(PKG)/build.Commit=$(COMMIT) \ -X $(PKG)/build.CommitHash=$(COMMIT_HASH) \ -X $(PKG)/build.GoVersion=$(GOVERSION) \ - -X $(PKG)/build.RawTags=$(shell echo $(1) | sed -e 's/ /,/g'))" + -X $(PKG)/build.RawTags=$(shell echo $(1) | sed -e 's/ /,/g') -LDFLAGS := $(call make_ldflags, ${tags}) -DEV_LDFLAGS := $(call make_ldflags, $(DEV_TAGS)) -ITEST_LDFLAGS := $(call make_ldflags, $(ITEST_TAGS)) +LDFLAGS := -ldflags "$(call make_ldflags, ${tags})" +DEV_LDFLAGS := -ldflags "$(call make_ldflags, $(DEV_TAGS))" +ITEST_LDFLAGS := -ldflags "$(call make_ldflags, $(ITEST_TAGS))" + +# For the release, we want to remove the symbol table and debug information (-s) +# and omit the DWARF symbol table (-w). Also we clear the build ID. +RELEASE_LDFLAGS := $(call make_ldflags, $(RELEASE_TAGS), -s -w -buildid=) # Linting uses a lot of memory, so keep it under control by limiting the number # of workers if requested. @@ -118,6 +126,11 @@ install: $(GOINSTALL) -tags="${tags}" $(LDFLAGS) $(PKG)/cmd/lnd $(GOINSTALL) -tags="${tags}" $(LDFLAGS) $(PKG)/cmd/lncli +release: + @$(call print, "Releasing lnd and lncli binaries.") + $(VERSION_CHECK) + ./build/release/release.sh build-release "$(VERSION_TAG)" "$(BUILD_SYSTEM)" "$(RELEASE_TAGS)" "$(RELEASE_LDFLAGS)" + scratch: build diff --git a/build/release/release.sh b/build/release/release.sh index 46ce14a8c6..ca650180ed 100755 --- a/build/release/release.sh +++ b/build/release/release.sh @@ -9,138 +9,152 @@ set -e -# If no tag specified, use date + version otherwise use tag. -if [[ $1x = x ]]; then - DATE=`date +%Y%m%d` - VERSION="01" - TAG=$DATE-$VERSION -else - TAG=$1 - - # If a tag is specified, ensure that that tag is present and checked out. - if [[ $TAG != $(git describe) ]]; then - echo "tag $TAG not checked out" - exit 1 - fi +LND_VERSION_REGEX="lnd version (.+) commit" +PKG="github.com/lightningnetwork/lnd" +PACKAGE=lnd - # Build lnd to extract version. - go build github.com/lightningnetwork/lnd/cmd/lnd - - # Extract version command output. - LND_VERSION_OUTPUT=`./lnd --version` - - # Use a regex to isolate the version string. - LND_VERSION_REGEX="lnd version (.+) commit" - if [[ $LND_VERSION_OUTPUT =~ $LND_VERSION_REGEX ]]; then - # Prepend 'v' to match git tag naming scheme. - LND_VERSION="v${BASH_REMATCH[1]}" - echo "version: $LND_VERSION" - - # If tag contains a release candidate suffix, append this suffix to the - # lnd reported version before we compare. - RC_REGEX="-rc[0-9]+$" - if [[ $TAG =~ $RC_REGEX ]]; then - LND_VERSION+=${BASH_REMATCH[0]} - fi - - # Match git tag with lnd version. - if [[ $TAG != $LND_VERSION ]]; then - echo "lnd version $LND_VERSION does not match tag $TAG" - exit 1 - fi - else - echo "malformed lnd version output" - exit 1 +# green prints one line of green text (if the terminal supports it). +function green() { + echo -e "\e[0;32m${1}\e[0m" +} + +# red prints one line of red text (if the terminal supports it). +function red() { + echo -e "\e[0;31m${1}\e[0m" +} + +# check_tag_correct makes sure the given git tag is checked out and the git tree +# is not dirty. +# arguments: +function check_tag_correct() { + local tag=$1 + + # If a tag is specified, ensure that that tag is present and checked out. + if [[ $tag != $(git describe) ]]; then + red "tag $tag not checked out" + exit 1 + fi + + # Build lnd to extract version. + go build ${PKG}/cmd/lnd + + # Extract version command output. + lnd_version_output=$(./lnd --version) + + # Use a regex to isolate the version string. + if [[ $lnd_version_output =~ $LND_VERSION_REGEX ]]; then + # Prepend 'v' to match git tag naming scheme. + lnd_version="v${BASH_REMATCH[1]}" + green "version: $lnd_version" + + # If tag contains a release candidate suffix, append this suffix to the + # lnd reported version before we compare. + RC_REGEX="-rc[0-9]+$" + if [[ $tag =~ $RC_REGEX ]]; then + lnd_version+=${BASH_REMATCH[0]} fi -fi - -go mod vendor -tar -cvzf vendor.tar.gz vendor -PACKAGE=lnd -MAINDIR=$PACKAGE-$TAG -mkdir -p $MAINDIR - -cp vendor.tar.gz $MAINDIR/ -rm vendor.tar.gz -rm -r vendor - -PACKAGESRC="$MAINDIR/$PACKAGE-source-$TAG.tar" -git archive -o $PACKAGESRC HEAD -gzip -f $PACKAGESRC > "$PACKAGESRC.gz" - -cd $MAINDIR - -# If LNDBUILDSYS is set the default list is ignored. Useful to release -# for a subset of systems/architectures. -SYS=${LNDBUILDSYS:-" - darwin-386 - darwin-amd64 - dragonfly-amd64 - freebsd-386 - freebsd-amd64 - freebsd-arm - illumos-amd64 - linux-386 - linux-amd64 - linux-armv6 - linux-armv7 - linux-arm64 - linux-ppc64 - linux-ppc64le - linux-mips - linux-mipsle - linux-mips64 - linux-mips64le - linux-s390x - netbsd-386 - netbsd-amd64 - netbsd-arm - netbsd-arm64 - openbsd-386 - openbsd-amd64 - openbsd-arm - openbsd-arm64 - solaris-amd64 - windows-386 - windows-amd64 - windows-arm -"} - -# Use the first element of $GOPATH in the case where GOPATH is a list -# (something that is totally allowed). -PKG="github.com/lightningnetwork/lnd" -COMMIT=$(git describe --abbrev=40 --dirty) -COMMITFLAGS="-X $PKG/build.Commit=$COMMIT" - -for i in $SYS; do - OS=$(echo $i | cut -f1 -d-) - ARCH=$(echo $i | cut -f2 -d-) - ARM= - - if [[ $ARCH = "armv6" ]]; then - ARCH=arm - ARM=6 - elif [[ $ARCH = "armv7" ]]; then - ARCH=arm - ARM=7 + # Match git tag with lnd version. + if [[ $tag != "${lnd_version}" ]]; then + red "lnd version $lnd_version does not match tag $tag" + exit 1 + fi + else + red "malformed lnd version output" + exit 1 + fi +} + +# build_release builds the actual release binaries. +# arguments: +function build_release() { + local tag=$1 + local sys=$2 + local buildtags=$3 + local ldflags=$4 + + green " - Packaging vendor" + go mod vendor + tar -czf vendor.tar.gz vendor + + maindir=$PACKAGE-$tag + mkdir -p $maindir + + cp vendor.tar.gz $maindir/ + rm vendor.tar.gz + rm -r vendor + + package_source="${maindir}/${PACKAGE}-source-${tag}.tar" + git archive -o "${package_source}" HEAD + gzip -f "${package_source}" >"${package_source}.gz" + + cd "${maindir}" + + for i in $sys; do + os=$(echo $i | cut -f1 -d-) + arch=$(echo $i | cut -f2 -d-) + arm= + + if [[ $arch == "armv6" ]]; then + arch=arm + arm=6 + elif [[ $arch == "armv7" ]]; then + arch=arm + arm=7 fi - mkdir $PACKAGE-$i-$TAG - cd $PACKAGE-$i-$TAG + dir="${PACKAGE}-${i}-${tag}" + mkdir "${dir}" + pushd "${dir}" - echo "Building:" $OS $ARCH $ARM - env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -trimpath -ldflags="-s -w -buildid= $COMMITFLAGS" -tags="autopilotrpc signrpc walletrpc chainrpc invoicesrpc watchtowerrpc" github.com/lightningnetwork/lnd/cmd/lnd - env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -trimpath -ldflags="-s -w -buildid= $COMMITFLAGS" -tags="autopilotrpc invoicesrpc walletrpc watchtowerrpc" github.com/lightningnetwork/lnd/cmd/lncli - cd .. + green " - Building: ${os} ${arch} ${arm} with build tags '${buildtags}'" + env CGO_ENABLED=0 GOOS=$os GOARCH=$arch GOARM=$arm go build -v -trimpath -ldflags="${ldflags}" -tags="${buildtags}" ${PKG}/cmd/lnd + env CGO_ENABLED=0 GOOS=$os GOARCH=$arch GOARM=$arm go build -v -trimpath -ldflags="${ldflags}" -tags="${buildtags}" ${PKG}/cmd/lncli + popd - if [[ $OS = "windows" ]]; then - zip -r $PACKAGE-$i-$TAG.zip $PACKAGE-$i-$TAG + if [[ $os == "windows" ]]; then + zip -r "${dir}.zip" "${dir}" else - tar -cvzf $PACKAGE-$i-$TAG.tar.gz $PACKAGE-$i-$TAG + tar -cvzf "${dir}.tar.gz" "${dir}" fi - rm -r $PACKAGE-$i-$TAG -done + rm -r "${dir}" + done + + shasum -a 256 * >manifest-$tag.txt +} + +# usage prints the usage of the whole script. +function usage() { + red "Usage: " + red "release.sh check-tag " + red "release.sh build-release " +} + +# Whatever sub command is passed in, we need at least 2 arguments. +if [ "$#" -lt 2 ]; then + usage + exit 1 +fi -shasum -a 256 * > manifest-$TAG.txt +# Extract the sub command and remove it from the list of parameters by shifting +# them to the left. +SUBCOMMAND=$1 +shift + +# Call the function corresponding to the specified sub command or print the +# usage if the sub command was not found. +case $SUBCOMMAND in +check-tag) + green "Checking if version tag exists" + check_tag_correct "$@" + ;; +build-release) + green "Building release" + build_release "$@" + ;; +*) + usage + exit 1 + ;; +esac From c08ddad22ee51adc8bfca321d9cfe39052bc9027 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 21 Apr 2020 10:20:29 +0200 Subject: [PATCH 506/562] build/README: describe how to use make release --- build/release/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build/release/README.md b/build/release/README.md index 68b9597449..e6591ea471 100644 --- a/build/release/README.md +++ b/build/release/README.md @@ -19,8 +19,7 @@ the release binaries following these steps: 1. `git clone https://github.com/lightningnetwork/lnd.git` 2. `cd lnd` -3. `./build/release/release.sh # is the name of the next - release/tag` +3. `make release tag= # is the name of the next release/tag` This will then create a directory of the form `lnd-` containing archives of the release binaries for each supported operating system and architecture, @@ -64,7 +63,7 @@ and `go` (matching the same version used in the release): release with `git checkout `. 7. Proceed to verify the tag with `git verify-tag ` and compile the binaries from source for the intended operating system and architecture with - `LNDBUILDSYS=OS-ARCH ./build/release/release.sh `. + `make release sys=OS-ARCH tag=`. 8. Extract the archive found in the `lnd-` directory created by the release script and recompute the `SHA256` hash of the release binaries (lnd and lncli) with `shasum -a 256 `. These should match __exactly__ From 4384319b4a066bcd85e1abdb6309a0ac421e8b23 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 21 Apr 2020 10:48:07 +0200 Subject: [PATCH 507/562] travis: use make command for windows build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 138d0b2bc3..79e007e9d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,7 +43,7 @@ jobs: - make unit pkg=... case=_NONE_ - make lint workers=1 - make btcd - - LNDBUILDSYS=windows-amd64 bash ./build/release/release.sh + - make release sys=windows-amd64 - stage: Test script: make travis-cover name: Unit Cover From d451ef4ee101f324426812283e0c285ac6fc1e8a Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 13 Apr 2020 10:07:53 +0200 Subject: [PATCH 508/562] routerrpc: rename rpcs to SendPaymentV2 and TrackPaymentV2 The message in the response stream changed. Rename the calls themselves, to prevent older applications from getting decode errors. Especially troublesome is the case where the request is executed (send payment), but the application can't read the outcome (payment sent or not?) --- cmd/lncli/cmd_pay.go | 4 +- lnrpc/routerrpc/router.pb.go | 324 +++++++++++++++---------------- lnrpc/routerrpc/router.proto | 8 +- lnrpc/routerrpc/router_server.go | 18 +- lntest/itest/lnd_test.go | 10 +- 5 files changed, 182 insertions(+), 182 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 78f5167e1a..26e3c9efed 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -399,7 +399,7 @@ func sendPaymentRequest(ctx *cli.Context, showInflight := ctx.Bool(showInflightFlag.Name) - stream, err := routerClient.SendPayment(context.Background(), req) + stream, err := routerClient.SendPaymentV2(context.Background(), req) if err != nil { return err } @@ -462,7 +462,7 @@ func trackPayment(ctx *cli.Context) error { PaymentHash: hash, } - stream, err := client.TrackPayment(context.Background(), req) + stream, err := client.TrackPaymentV2(context.Background(), req) if err != nil { return err } diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index c5d8feae38..7b0b18d090 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -1606,135 +1606,135 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2040 bytes of a gzipped FileDescriptorProto + // 2044 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xcd, 0x76, 0xdb, 0xc6, - 0x15, 0x0e, 0x44, 0x50, 0x22, 0x2f, 0xff, 0xa0, 0xa1, 0x23, 0xb3, 0x54, 0x9c, 0x32, 0x68, 0x63, - 0xf3, 0xb8, 0xae, 0xe4, 0xa8, 0x3d, 0xad, 0x4f, 0xdb, 0xb8, 0xa5, 0x08, 0x28, 0x82, 0x45, 0x01, - 0xcc, 0x10, 0xb2, 0x9d, 0x7a, 0x31, 0x07, 0x22, 0x87, 0x22, 0x2a, 0xfc, 0xb0, 0xc0, 0xd0, 0x8e, - 0x96, 0xdd, 0xf6, 0x05, 0xfa, 0x08, 0x7d, 0x89, 0xbe, 0x4b, 0xb7, 0xdd, 0x75, 0xd7, 0x75, 0xcf, - 0x0c, 0x00, 0x12, 0x94, 0x28, 0x27, 0x1b, 0x09, 0xf8, 0xee, 0x37, 0x77, 0xee, 0x9d, 0xfb, 0xdd, - 0x99, 0x01, 0x61, 0x2f, 0x0a, 0x17, 0x8c, 0x46, 0xd1, 0x7c, 0x7c, 0x98, 0x3c, 0x1d, 0xcc, 0xa3, - 0x90, 0x85, 0xa8, 0xbc, 0xc4, 0xdb, 0xe5, 0x68, 0x3e, 0x4e, 0x50, 0xf5, 0x1f, 0xdb, 0x80, 0x46, - 0x34, 0x98, 0x0c, 0x9d, 0x1b, 0x9f, 0x06, 0x0c, 0xd3, 0xbf, 0x2e, 0x68, 0xcc, 0x10, 0x02, 0x79, - 0x42, 0x63, 0xd6, 0x92, 0x3a, 0x52, 0xb7, 0x8a, 0xc5, 0x33, 0x52, 0xa0, 0xe0, 0xf8, 0xac, 0xb5, - 0xd5, 0x91, 0xba, 0x05, 0xcc, 0x1f, 0xd1, 0x4f, 0xa0, 0xe4, 0xf8, 0x8c, 0xf8, 0xb1, 0xc3, 0x5a, - 0x55, 0x01, 0xef, 0x38, 0x3e, 0x3b, 0x8f, 0x1d, 0x86, 0xbe, 0x80, 0xea, 0x3c, 0x71, 0x49, 0x66, - 0x4e, 0x3c, 0x6b, 0x15, 0x84, 0xa3, 0x4a, 0x8a, 0x9d, 0x3a, 0xf1, 0x0c, 0x75, 0x41, 0x99, 0xba, - 0x81, 0xe3, 0x91, 0xb1, 0xc7, 0xde, 0x93, 0x09, 0xf5, 0x98, 0xd3, 0x92, 0x3b, 0x52, 0xb7, 0x88, - 0xeb, 0x02, 0xef, 0x7b, 0xec, 0xbd, 0xc6, 0x51, 0xf4, 0x04, 0x1a, 0x99, 0xb3, 0x28, 0x09, 0xb0, - 0x55, 0xec, 0x48, 0xdd, 0x32, 0xae, 0xcf, 0xd7, 0xc3, 0x7e, 0x02, 0x0d, 0xe6, 0xfa, 0x34, 0x5c, - 0x30, 0x12, 0xd3, 0x71, 0x18, 0x4c, 0xe2, 0xd6, 0x76, 0xe2, 0x31, 0x85, 0x47, 0x09, 0x8a, 0x54, - 0xa8, 0x4d, 0x29, 0x25, 0x9e, 0xeb, 0xbb, 0x8c, 0xf0, 0xf0, 0x77, 0x44, 0xf8, 0x95, 0x29, 0xa5, - 0x03, 0x8e, 0x8d, 0x1c, 0x86, 0x7e, 0x0e, 0xf5, 0x15, 0x47, 0xe4, 0x58, 0x13, 0xa4, 0x6a, 0x46, - 0x12, 0x89, 0x3e, 0x03, 0x25, 0x5c, 0xb0, 0xab, 0xd0, 0x0d, 0xae, 0xc8, 0x78, 0xe6, 0x04, 0xc4, - 0x9d, 0xb4, 0x4a, 0x1d, 0xa9, 0x2b, 0x1f, 0x6f, 0x3d, 0x97, 0x70, 0x3d, 0xb3, 0xf5, 0x67, 0x4e, - 0x60, 0x4c, 0xd0, 0x63, 0x68, 0x78, 0x4e, 0xcc, 0xc8, 0x2c, 0x9c, 0x93, 0xf9, 0xe2, 0xf2, 0x9a, - 0xde, 0xb4, 0xea, 0x62, 0x65, 0x6a, 0x1c, 0x3e, 0x0d, 0xe7, 0x43, 0x01, 0xa2, 0x47, 0x00, 0x62, - 0x55, 0xc4, 0xe4, 0xad, 0xb2, 0xc8, 0xa1, 0xcc, 0x11, 0x31, 0x31, 0xfa, 0x0a, 0x2a, 0xa2, 0x9a, - 0x64, 0xe6, 0x06, 0x2c, 0x6e, 0x41, 0xa7, 0xd0, 0xad, 0x1c, 0x29, 0x07, 0x5e, 0xc0, 0x0b, 0x8b, - 0xb9, 0xe5, 0xd4, 0x0d, 0x18, 0x86, 0x28, 0x7b, 0x8c, 0xd1, 0x04, 0x9a, 0xbc, 0x8a, 0x64, 0xbc, - 0x88, 0x59, 0xe8, 0x93, 0x88, 0x8e, 0xc3, 0x68, 0x12, 0xb7, 0x2a, 0x62, 0xe8, 0xaf, 0x0f, 0x96, - 0xe2, 0x38, 0xb8, 0xab, 0x86, 0x03, 0x8d, 0xc6, 0xac, 0x2f, 0xc6, 0xe1, 0x64, 0x98, 0x1e, 0xb0, - 0xe8, 0x06, 0xef, 0x4e, 0x6e, 0xe3, 0xe8, 0x19, 0x20, 0xc7, 0xf3, 0xc2, 0x0f, 0x24, 0xa6, 0xde, - 0x94, 0xa4, 0xd5, 0x69, 0x35, 0x3a, 0x52, 0xb7, 0x84, 0x15, 0x61, 0x19, 0x51, 0x6f, 0x9a, 0xba, - 0x47, 0xbf, 0x81, 0x9a, 0x88, 0x69, 0x4a, 0x1d, 0xb6, 0x88, 0x68, 0xdc, 0x52, 0x3a, 0x85, 0x6e, - 0xfd, 0x68, 0x37, 0x4d, 0xe4, 0x24, 0x81, 0x8f, 0x5d, 0x86, 0xab, 0x9c, 0x97, 0xbe, 0xc7, 0x7c, - 0x75, 0x7c, 0xe7, 0x7b, 0x12, 0xcf, 0x1c, 0x9e, 0xc2, 0x6e, 0x47, 0xea, 0xd6, 0x70, 0xd9, 0x77, - 0xbe, 0x1f, 0x09, 0xa0, 0xad, 0xc1, 0xde, 0xe6, 0x88, 0xb9, 0x84, 0xf9, 0x92, 0x73, 0x55, 0xcb, - 0x98, 0x3f, 0xa2, 0x07, 0x50, 0x7c, 0xef, 0x78, 0x0b, 0x2a, 0x64, 0x5d, 0xc5, 0xc9, 0xcb, 0xef, - 0xb6, 0x5e, 0x48, 0xea, 0x0b, 0x68, 0xda, 0x91, 0x33, 0xbe, 0xbe, 0xd5, 0x19, 0xb7, 0x85, 0x2d, - 0xdd, 0x11, 0xb6, 0xfa, 0x12, 0x1a, 0xa2, 0x06, 0x27, 0x94, 0x7e, 0xac, 0x9f, 0x1e, 0x02, 0xef, - 0x16, 0xa1, 0xbe, 0xa4, 0xa7, 0xb6, 0x1d, 0x9f, 0x0b, 0x4f, 0x9d, 0x80, 0xb2, 0x1a, 0x1f, 0xcf, - 0xc3, 0x20, 0xa6, 0xbc, 0x59, 0x78, 0x89, 0xb8, 0xca, 0xb8, 0x28, 0x85, 0x1c, 0x25, 0x31, 0xaa, - 0x9e, 0xe2, 0x27, 0x94, 0x0a, 0x41, 0x3e, 0x4e, 0x7a, 0x80, 0x78, 0xe1, 0xf8, 0x9a, 0x77, 0x95, - 0x73, 0x93, 0xba, 0xaf, 0x71, 0x78, 0x10, 0x8e, 0xaf, 0x35, 0x0e, 0xaa, 0xef, 0x92, 0xc6, 0xb7, - 0x43, 0x31, 0xd7, 0x8f, 0x4f, 0x0f, 0xa9, 0x50, 0x14, 0x6a, 0x11, 0x6e, 0x2b, 0x47, 0xd5, 0xbc, - 0xec, 0x70, 0x62, 0x52, 0xdf, 0x41, 0x73, 0xcd, 0x79, 0x9a, 0x45, 0x1b, 0x4a, 0xf3, 0x88, 0xba, - 0xbe, 0x73, 0x45, 0x53, 0xcf, 0xcb, 0x77, 0xd4, 0x85, 0x9d, 0xa9, 0xe3, 0x7a, 0x8b, 0x28, 0x73, - 0x5c, 0xcf, 0x64, 0x90, 0xa0, 0x38, 0x33, 0xab, 0x9f, 0x41, 0x1b, 0xd3, 0x98, 0xb2, 0x73, 0x37, - 0x8e, 0xdd, 0x30, 0xe8, 0x87, 0x01, 0x8b, 0x42, 0x2f, 0xcd, 0x40, 0x7d, 0x04, 0xfb, 0x1b, 0xad, - 0x49, 0x08, 0x7c, 0xf0, 0xb7, 0x0b, 0x1a, 0xdd, 0x6c, 0x1e, 0xfc, 0x2d, 0xec, 0x6f, 0xb4, 0xa6, - 0xf1, 0x3f, 0x83, 0xe2, 0xdc, 0x71, 0xa3, 0xb8, 0xb5, 0x25, 0xda, 0x66, 0x2f, 0xd7, 0x36, 0x43, - 0xc7, 0x8d, 0x4e, 0xdd, 0x98, 0x85, 0xd1, 0x0d, 0x4e, 0x48, 0xaf, 0xe4, 0x92, 0xa4, 0x6c, 0xa9, - 0x7f, 0x97, 0xa0, 0x92, 0x33, 0xa2, 0x7d, 0x28, 0x07, 0xe1, 0x84, 0x92, 0x69, 0x14, 0xfa, 0xd9, - 0x22, 0x70, 0xe0, 0x24, 0x0a, 0x7d, 0xae, 0x09, 0x61, 0x64, 0x61, 0x2a, 0xc8, 0x6d, 0xfe, 0x6a, - 0x87, 0xe8, 0x97, 0xb0, 0x33, 0x4b, 0x1c, 0x88, 0xad, 0xaa, 0x72, 0xd4, 0xbc, 0x35, 0xb7, 0xe6, - 0x30, 0x07, 0x67, 0x9c, 0x57, 0x72, 0xa9, 0xa0, 0xc8, 0xaf, 0xe4, 0x92, 0xac, 0x14, 0x5f, 0xc9, - 0xa5, 0xa2, 0xb2, 0xfd, 0x4a, 0x2e, 0x6d, 0x2b, 0x3b, 0xea, 0x7f, 0x24, 0x28, 0x65, 0x6c, 0x1e, - 0x09, 0x5f, 0x52, 0xc2, 0x75, 0x91, 0x8a, 0xa9, 0xc4, 0x01, 0xdb, 0xf5, 0x29, 0xea, 0x40, 0x55, - 0x18, 0xd7, 0x25, 0x0a, 0x1c, 0xeb, 0x09, 0x99, 0x8a, 0x3d, 0x34, 0x63, 0x08, 0x3d, 0xca, 0xe9, - 0x1e, 0x9a, 0x50, 0xb2, 0x63, 0x20, 0x5e, 0x8c, 0xc7, 0x34, 0x8e, 0x93, 0x59, 0x8a, 0x09, 0x25, - 0xc5, 0xc4, 0x44, 0x8f, 0xa1, 0x91, 0x51, 0xb2, 0xb9, 0xb6, 0x13, 0xbd, 0xa6, 0x70, 0x3a, 0x5d, - 0x17, 0x94, 0x3c, 0xcf, 0x5f, 0xed, 0xda, 0xf5, 0x15, 0x91, 0x4f, 0x9a, 0x24, 0xaf, 0xfe, 0x05, - 0x1e, 0x8a, 0x52, 0x0e, 0xa3, 0xf0, 0xd2, 0xb9, 0x74, 0x3d, 0x97, 0xdd, 0x64, 0x22, 0xe7, 0x89, - 0x47, 0xa1, 0x4f, 0xf8, 0xda, 0x66, 0x25, 0xe0, 0x80, 0x19, 0x4e, 0x28, 0x2f, 0x01, 0x0b, 0x13, - 0x53, 0x5a, 0x02, 0x16, 0x0a, 0x43, 0xfe, 0xb4, 0x2b, 0xac, 0x9d, 0x76, 0xea, 0x35, 0xb4, 0xee, - 0xce, 0x95, 0x6a, 0xa6, 0x03, 0x95, 0xf9, 0x0a, 0x16, 0xd3, 0x49, 0x38, 0x0f, 0xe5, 0x6b, 0xbb, - 0xf5, 0xc3, 0xb5, 0x55, 0xff, 0x29, 0xc1, 0xee, 0xf1, 0xc2, 0xf5, 0x26, 0x6b, 0x8d, 0x9b, 0x8f, - 0x4e, 0x5a, 0x3f, 0x8b, 0x37, 0x1d, 0xb4, 0x5b, 0x1b, 0x0f, 0xda, 0x4d, 0x87, 0x59, 0xe1, 0xde, - 0xc3, 0xec, 0xa7, 0x50, 0x59, 0x9d, 0x63, 0x71, 0x4b, 0xee, 0x14, 0xba, 0x55, 0x0c, 0xb3, 0xec, - 0x10, 0x8b, 0xd5, 0x17, 0x80, 0xf2, 0x81, 0xa6, 0x0b, 0xb2, 0xdc, 0x3f, 0xa4, 0xfb, 0xf7, 0x8f, - 0xcf, 0xa0, 0x3d, 0x5a, 0x5c, 0xc6, 0xe3, 0xc8, 0xbd, 0xa4, 0xa7, 0xcc, 0x1b, 0xeb, 0xef, 0x69, - 0xc0, 0xe2, 0xac, 0x4b, 0xff, 0x27, 0x43, 0x79, 0x89, 0xa2, 0x03, 0x68, 0xba, 0xc1, 0x38, 0xf4, - 0xb3, 0xa0, 0x03, 0xea, 0xf1, 0xb8, 0x93, 0x4d, 0x7e, 0x37, 0x33, 0xf5, 0x13, 0x8b, 0x31, 0xe1, - 0xfc, 0xb5, 0x24, 0x53, 0xfe, 0x56, 0xc2, 0xcf, 0xe7, 0x98, 0xf0, 0xbb, 0xa0, 0x2c, 0xfd, 0xcf, - 0x98, 0x37, 0x5e, 0x2e, 0x0a, 0xae, 0x67, 0x38, 0x0f, 0x26, 0x61, 0x2e, 0x3d, 0x67, 0x4c, 0x39, - 0x61, 0x66, 0x78, 0xca, 0xfc, 0x02, 0xaa, 0xbc, 0x1f, 0x62, 0xe6, 0xf8, 0x73, 0x12, 0xc4, 0xa2, - 0x2f, 0x64, 0x5c, 0x59, 0x62, 0x66, 0x8c, 0xbe, 0x06, 0xa0, 0x3c, 0x3f, 0xc2, 0x6e, 0xe6, 0x54, - 0xb4, 0x44, 0xfd, 0xe8, 0xf3, 0x9c, 0x30, 0x96, 0x0b, 0x70, 0x20, 0xfe, 0xda, 0x37, 0x73, 0x8a, - 0xcb, 0x34, 0x7b, 0x44, 0x2f, 0xa1, 0x36, 0x0d, 0xa3, 0x0f, 0x4e, 0x34, 0x21, 0x02, 0x4c, 0xb7, - 0x8d, 0x87, 0x39, 0x0f, 0x27, 0x89, 0x5d, 0x0c, 0x3f, 0xfd, 0x04, 0x57, 0xa7, 0xb9, 0x77, 0x74, - 0x06, 0x28, 0x1b, 0x2f, 0xba, 0x3c, 0x71, 0x52, 0x12, 0x4e, 0xf6, 0xef, 0x3a, 0xe1, 0x9b, 0x74, - 0xe6, 0x48, 0x99, 0xde, 0xc2, 0xd0, 0xef, 0xa1, 0x1a, 0x53, 0xc6, 0x3c, 0x9a, 0xba, 0x29, 0x0b, - 0x37, 0x7b, 0x6b, 0xb7, 0x0e, 0x6e, 0xce, 0x3c, 0x54, 0xe2, 0xd5, 0x2b, 0x3a, 0x86, 0x86, 0xe7, - 0x06, 0xd7, 0xf9, 0x30, 0x40, 0x8c, 0x6f, 0xe5, 0xc6, 0x0f, 0xdc, 0xe0, 0x3a, 0x1f, 0x43, 0xcd, - 0xcb, 0x03, 0xea, 0x1f, 0xa0, 0xbc, 0x5c, 0x25, 0x54, 0x81, 0x9d, 0x0b, 0xf3, 0xcc, 0xb4, 0xde, - 0x98, 0xca, 0x27, 0xa8, 0x04, 0xf2, 0x48, 0x37, 0x35, 0x45, 0xe2, 0x30, 0xd6, 0xfb, 0xba, 0xf1, - 0x5a, 0x57, 0xb6, 0xf8, 0xcb, 0x89, 0x85, 0xdf, 0xf4, 0xb0, 0xa6, 0x14, 0x8e, 0x77, 0xa0, 0x28, - 0xe6, 0x55, 0xff, 0x25, 0x41, 0x49, 0x54, 0x30, 0x98, 0x86, 0xe8, 0x17, 0xb0, 0x14, 0x97, 0xd8, - 0xdc, 0xf8, 0x81, 0x2b, 0x54, 0x57, 0xc3, 0x4b, 0xc1, 0xd8, 0x29, 0xce, 0xc9, 0x4b, 0x69, 0x2c, - 0xc9, 0x5b, 0x09, 0x39, 0x33, 0x2c, 0xc9, 0x4f, 0x73, 0x9e, 0xd7, 0xb6, 0x1c, 0x19, 0x37, 0x32, - 0x43, 0xb6, 0xc3, 0x3e, 0xcd, 0x39, 0x5e, 0xdb, 0x89, 0x65, 0xdc, 0xc8, 0x0c, 0x29, 0x57, 0xfd, - 0x2d, 0x54, 0xf3, 0x35, 0x47, 0x4f, 0x40, 0x76, 0x83, 0x69, 0x98, 0x36, 0x62, 0xf3, 0x96, 0xb8, - 0x78, 0x92, 0x58, 0x10, 0x54, 0x04, 0xca, 0xed, 0x3a, 0xab, 0x35, 0xa8, 0xe4, 0x8a, 0xa6, 0xfe, - 0x5b, 0x82, 0xda, 0x5a, 0x11, 0x7e, 0xb4, 0x77, 0xf4, 0x35, 0x54, 0x3f, 0xb8, 0x11, 0x25, 0xf9, - 0xe3, 0xbf, 0x7e, 0xd4, 0x5e, 0x3f, 0xfe, 0xb3, 0xff, 0xfd, 0x70, 0x42, 0x71, 0x85, 0xf3, 0x53, - 0x00, 0xfd, 0x11, 0xea, 0xe9, 0x48, 0x32, 0xa1, 0xcc, 0x71, 0x3d, 0xb1, 0x54, 0xf5, 0x35, 0x79, - 0xa4, 0x5c, 0x4d, 0xd8, 0x71, 0x6d, 0x9a, 0x7f, 0x45, 0x5f, 0xae, 0x1c, 0xc4, 0x2c, 0x72, 0x83, - 0x2b, 0xb1, 0x7e, 0xe5, 0x25, 0x6d, 0x24, 0xc0, 0xa7, 0x7f, 0x93, 0xa1, 0xb6, 0xe6, 0x67, 0x5d, - 0x48, 0x35, 0x28, 0x9b, 0x16, 0xd1, 0x74, 0xbb, 0x67, 0x0c, 0x14, 0x09, 0x29, 0x50, 0xb5, 0x4c, - 0xc3, 0x32, 0x89, 0xa6, 0xf7, 0x2d, 0x8d, 0x4b, 0xea, 0x53, 0xd8, 0x1d, 0x18, 0xe6, 0x19, 0x31, - 0x2d, 0x9b, 0xe8, 0x03, 0xe3, 0x1b, 0xe3, 0x78, 0xa0, 0x2b, 0x05, 0xf4, 0x00, 0x14, 0xcb, 0x24, - 0xfd, 0xd3, 0x9e, 0x61, 0x12, 0xdb, 0x38, 0xd7, 0xad, 0x0b, 0x5b, 0x91, 0x39, 0x7a, 0x6a, 0x0f, - 0xfa, 0x44, 0x7f, 0xdb, 0xd7, 0x75, 0x6d, 0x44, 0xce, 0x7b, 0x6f, 0x95, 0x22, 0x6a, 0xc1, 0x03, - 0xc3, 0x1c, 0x5d, 0x9c, 0x9c, 0x18, 0x7d, 0x43, 0x37, 0x6d, 0x72, 0xdc, 0x1b, 0xf4, 0xcc, 0xbe, - 0xae, 0x6c, 0xa3, 0x3d, 0x40, 0x86, 0xd9, 0xb7, 0xce, 0x87, 0x03, 0xdd, 0xd6, 0x49, 0x26, 0xdd, - 0x1d, 0xd4, 0x84, 0x86, 0xf0, 0xd3, 0xd3, 0x34, 0x72, 0xd2, 0x33, 0x06, 0xba, 0xa6, 0x94, 0x78, - 0x24, 0x29, 0x63, 0x44, 0x34, 0x63, 0xd4, 0x3b, 0xe6, 0x70, 0x99, 0xcf, 0x69, 0x98, 0xaf, 0x2d, - 0xa3, 0xaf, 0x93, 0x3e, 0x77, 0xcb, 0x51, 0xe0, 0xe4, 0x0c, 0xbd, 0x30, 0x35, 0x1d, 0x0f, 0x7b, - 0x86, 0xa6, 0x54, 0xd0, 0x3e, 0x3c, 0xcc, 0x60, 0xfd, 0xed, 0xd0, 0xc0, 0xdf, 0x11, 0xdb, 0xb2, - 0xc8, 0xc8, 0xb2, 0x4c, 0xa5, 0x9a, 0xf7, 0xc4, 0xb3, 0xb5, 0x86, 0xba, 0xa9, 0xd4, 0xd0, 0x43, - 0x68, 0x9e, 0x0f, 0x87, 0x24, 0xb3, 0x64, 0xc9, 0xd6, 0x39, 0xbd, 0xa7, 0x69, 0x58, 0x1f, 0x8d, - 0xc8, 0xb9, 0x31, 0x3a, 0xef, 0xd9, 0xfd, 0x53, 0xa5, 0xc1, 0x53, 0x1a, 0xe9, 0x36, 0xb1, 0x2d, - 0xbb, 0x37, 0x58, 0xe1, 0x0a, 0x0f, 0x68, 0x85, 0xf3, 0x49, 0x07, 0xd6, 0x1b, 0x65, 0x97, 0x2f, - 0x38, 0x87, 0xad, 0xd7, 0x69, 0x88, 0x88, 0xe7, 0x9e, 0x96, 0x27, 0x9b, 0x53, 0x69, 0x72, 0xd0, - 0x30, 0x5f, 0xf7, 0x06, 0x86, 0x46, 0xce, 0xf4, 0xef, 0x44, 0xeb, 0x3f, 0xe0, 0x60, 0x12, 0x19, - 0x19, 0x62, 0xeb, 0x1b, 0x1e, 0x88, 0xf2, 0x29, 0x42, 0x50, 0xef, 0x1b, 0xb8, 0x7f, 0x31, 0xe8, - 0x61, 0x82, 0xad, 0x0b, 0x5b, 0x57, 0xf6, 0x8e, 0xfe, 0x5b, 0x84, 0x6d, 0x71, 0x50, 0x45, 0xe8, - 0x25, 0xd7, 0xff, 0xf2, 0x53, 0x09, 0x3d, 0xfa, 0xe8, 0x27, 0x54, 0x3b, 0xbb, 0xcc, 0xa6, 0xf0, - 0x73, 0x09, 0xfd, 0x09, 0xaa, 0xf9, 0xef, 0x0b, 0x94, 0xdf, 0xdb, 0x37, 0x7c, 0x78, 0x6c, 0xf0, - 0x70, 0x06, 0x8a, 0x1e, 0x33, 0xd7, 0x77, 0x18, 0xcd, 0xbe, 0x17, 0x50, 0x3b, 0xe7, 0xe5, 0xd6, - 0x47, 0x48, 0x7b, 0x7f, 0xa3, 0x2d, 0x3d, 0x95, 0x07, 0x49, 0x3a, 0xe9, 0x8d, 0xfd, 0x4e, 0x3a, - 0xeb, 0x9f, 0x09, 0xed, 0xcf, 0xef, 0x33, 0xa7, 0xde, 0x26, 0xd0, 0xdc, 0x70, 0x09, 0x47, 0x5f, - 0xe6, 0x23, 0xb8, 0xf7, 0x0a, 0xdf, 0x7e, 0xfc, 0x43, 0xb4, 0xd5, 0x2c, 0x1b, 0x6e, 0xeb, 0x6b, - 0xb3, 0xdc, 0x7f, 0xd7, 0x5f, 0x9b, 0xe5, 0x63, 0x97, 0xfe, 0x77, 0xa0, 0xdc, 0xbe, 0xdc, 0x21, - 0xf5, 0xf6, 0xd8, 0xbb, 0xb7, 0xcc, 0xf6, 0xcf, 0x3e, 0xca, 0x49, 0x9d, 0x1b, 0x00, 0xab, 0x2b, - 0x12, 0xfa, 0x2c, 0x37, 0xe4, 0xce, 0x15, 0xaf, 0xfd, 0xe8, 0x1e, 0x6b, 0xea, 0xca, 0x86, 0xe6, - 0x86, 0x3b, 0xd3, 0xda, 0x6a, 0xdc, 0x7f, 0xa7, 0x6a, 0x3f, 0xd8, 0x74, 0xb5, 0x78, 0x2e, 0x1d, - 0x7f, 0xf5, 0xe7, 0xc3, 0x2b, 0x97, 0xcd, 0x16, 0x97, 0x07, 0xe3, 0xd0, 0x3f, 0xf4, 0xdc, 0xab, - 0x19, 0x0b, 0xdc, 0xe0, 0x2a, 0xa0, 0xec, 0x43, 0x18, 0x5d, 0x1f, 0x7a, 0xc1, 0xe4, 0x50, 0xe8, - 0xf2, 0x70, 0x39, 0xfc, 0x72, 0x5b, 0xfc, 0xb4, 0xf4, 0xab, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, - 0x27, 0x10, 0x6c, 0xe6, 0x8a, 0x12, 0x00, 0x00, + 0x15, 0x0e, 0x44, 0x50, 0x22, 0x2f, 0xff, 0xa0, 0xa1, 0x23, 0xb3, 0x94, 0x9d, 0x32, 0x68, 0x63, + 0xf3, 0xb8, 0xae, 0xe4, 0xa8, 0x3d, 0xad, 0x4f, 0xdb, 0xa4, 0xa5, 0x08, 0x28, 0x82, 0x4d, 0x01, + 0xcc, 0x10, 0x92, 0x9d, 0x7a, 0x31, 0x07, 0x22, 0x87, 0x22, 0x2a, 0xfc, 0xb0, 0xc0, 0xd0, 0x8e, + 0x96, 0xdd, 0xf6, 0x05, 0xfa, 0x08, 0x7d, 0x89, 0xbe, 0x4b, 0xb7, 0xdd, 0xf7, 0x9c, 0xae, 0x7b, + 0x66, 0x00, 0x90, 0xa0, 0x44, 0x39, 0xd9, 0x48, 0xc0, 0x77, 0xbf, 0xb9, 0x73, 0xef, 0xdc, 0xef, + 0xce, 0x0c, 0x08, 0x7b, 0x51, 0xb8, 0x60, 0x34, 0x8a, 0xe6, 0xe3, 0xc3, 0xe4, 0xe9, 0x60, 0x1e, + 0x85, 0x2c, 0x44, 0xe5, 0x25, 0xde, 0x2e, 0x47, 0xf3, 0x71, 0x82, 0xaa, 0xff, 0xd8, 0x06, 0x34, + 0xa2, 0xc1, 0x64, 0xe8, 0xdc, 0xf8, 0x34, 0x60, 0x98, 0xfe, 0x75, 0x41, 0x63, 0x86, 0x10, 0xc8, + 0x13, 0x1a, 0xb3, 0x96, 0xd4, 0x91, 0xba, 0x55, 0x2c, 0x9e, 0x91, 0x02, 0x05, 0xc7, 0x67, 0xad, + 0xad, 0x8e, 0xd4, 0x2d, 0x60, 0xfe, 0x88, 0x7e, 0x02, 0x25, 0xc7, 0x67, 0xc4, 0x8f, 0x1d, 0xd6, + 0xaa, 0x0a, 0x78, 0xc7, 0xf1, 0xd9, 0x59, 0xec, 0x30, 0xf4, 0x39, 0x54, 0xe7, 0x89, 0x4b, 0x32, + 0x73, 0xe2, 0x59, 0xab, 0x20, 0x1c, 0x55, 0x52, 0xec, 0xd4, 0x89, 0x67, 0xa8, 0x0b, 0xca, 0xd4, + 0x0d, 0x1c, 0x8f, 0x8c, 0x3d, 0xf6, 0x9e, 0x4c, 0xa8, 0xc7, 0x9c, 0x96, 0xdc, 0x91, 0xba, 0x45, + 0x5c, 0x17, 0x78, 0xdf, 0x63, 0xef, 0x35, 0x8e, 0xa2, 0xa7, 0xd0, 0xc8, 0x9c, 0x45, 0x49, 0x80, + 0xad, 0x62, 0x47, 0xea, 0x96, 0x71, 0x7d, 0xbe, 0x1e, 0xf6, 0x53, 0x68, 0x30, 0xd7, 0xa7, 0xe1, + 0x82, 0x91, 0x98, 0x8e, 0xc3, 0x60, 0x12, 0xb7, 0xb6, 0x13, 0x8f, 0x29, 0x3c, 0x4a, 0x50, 0xa4, + 0x42, 0x6d, 0x4a, 0x29, 0xf1, 0x5c, 0xdf, 0x65, 0x84, 0x87, 0xbf, 0x23, 0xc2, 0xaf, 0x4c, 0x29, + 0x1d, 0x70, 0x6c, 0xe4, 0x30, 0xf4, 0x73, 0xa8, 0xaf, 0x38, 0x22, 0xc7, 0x9a, 0x20, 0x55, 0x33, + 0x92, 0x48, 0xf4, 0x39, 0x28, 0xe1, 0x82, 0x5d, 0x85, 0x6e, 0x70, 0x45, 0xc6, 0x33, 0x27, 0x20, + 0xee, 0xa4, 0x55, 0xea, 0x48, 0x5d, 0xf9, 0x78, 0xeb, 0x85, 0x84, 0xeb, 0x99, 0xad, 0x3f, 0x73, + 0x02, 0x63, 0x82, 0x9e, 0x40, 0xc3, 0x73, 0x62, 0x46, 0x66, 0xe1, 0x9c, 0xcc, 0x17, 0x97, 0xd7, + 0xf4, 0xa6, 0x55, 0x17, 0x2b, 0x53, 0xe3, 0xf0, 0x69, 0x38, 0x1f, 0x0a, 0x10, 0x3d, 0x06, 0x10, + 0xab, 0x22, 0x26, 0x6f, 0x95, 0x45, 0x0e, 0x65, 0x8e, 0x88, 0x89, 0xd1, 0x97, 0x50, 0x11, 0xd5, + 0x24, 0x33, 0x37, 0x60, 0x71, 0x0b, 0x3a, 0x85, 0x6e, 0xe5, 0x48, 0x39, 0xf0, 0x02, 0x5e, 0x58, + 0xcc, 0x2d, 0xa7, 0x6e, 0xc0, 0x30, 0x44, 0xd9, 0x63, 0x8c, 0x26, 0xd0, 0xe4, 0x55, 0x24, 0xe3, + 0x45, 0xcc, 0x42, 0x9f, 0x44, 0x74, 0x1c, 0x46, 0x93, 0xb8, 0x55, 0x11, 0x43, 0x7f, 0x7d, 0xb0, + 0x14, 0xc7, 0xc1, 0x5d, 0x35, 0x1c, 0x68, 0x34, 0x66, 0x7d, 0x31, 0x0e, 0x27, 0xc3, 0xf4, 0x80, + 0x45, 0x37, 0x78, 0x77, 0x72, 0x1b, 0x47, 0xcf, 0x01, 0x39, 0x9e, 0x17, 0x7e, 0x20, 0x31, 0xf5, + 0xa6, 0x24, 0xad, 0x4e, 0xab, 0xd1, 0x91, 0xba, 0x25, 0xac, 0x08, 0xcb, 0x88, 0x7a, 0xd3, 0xd4, + 0x3d, 0xfa, 0x0d, 0xd4, 0x44, 0x4c, 0x53, 0xea, 0xb0, 0x45, 0x44, 0xe3, 0x96, 0xd2, 0x29, 0x74, + 0xeb, 0x47, 0xbb, 0x69, 0x22, 0x27, 0x09, 0x7c, 0xec, 0x32, 0x5c, 0xe5, 0xbc, 0xf4, 0x3d, 0xe6, + 0xab, 0xe3, 0x3b, 0xdf, 0x93, 0x78, 0xe6, 0xf0, 0x14, 0x76, 0x3b, 0x52, 0xb7, 0x86, 0xcb, 0xbe, + 0xf3, 0xfd, 0x48, 0x00, 0x6d, 0x0d, 0xf6, 0x36, 0x47, 0xcc, 0x25, 0xcc, 0x97, 0x9c, 0xab, 0x5a, + 0xc6, 0xfc, 0x11, 0x3d, 0x80, 0xe2, 0x7b, 0xc7, 0x5b, 0x50, 0x21, 0xeb, 0x2a, 0x4e, 0x5e, 0x7e, + 0xb7, 0xf5, 0x52, 0x52, 0x5f, 0x42, 0xd3, 0x8e, 0x9c, 0xf1, 0xf5, 0xad, 0xce, 0xb8, 0x2d, 0x6c, + 0xe9, 0x8e, 0xb0, 0xd5, 0xaf, 0xa1, 0x21, 0x6a, 0x70, 0x42, 0xe9, 0xc7, 0xfa, 0xe9, 0x21, 0xf0, + 0x6e, 0x11, 0xea, 0x4b, 0x7a, 0x6a, 0xdb, 0xf1, 0xb9, 0xf0, 0xd4, 0x09, 0x28, 0xab, 0xf1, 0xf1, + 0x3c, 0x0c, 0x62, 0xca, 0x9b, 0x85, 0x97, 0x88, 0xab, 0x8c, 0x8b, 0x52, 0xc8, 0x51, 0x12, 0xa3, + 0xea, 0x29, 0x7e, 0x42, 0xa9, 0x10, 0xe4, 0x93, 0xa4, 0x07, 0x88, 0x17, 0x8e, 0xaf, 0x79, 0x57, + 0x39, 0x37, 0xa9, 0xfb, 0x1a, 0x87, 0x07, 0xe1, 0xf8, 0x5a, 0xe3, 0xa0, 0xfa, 0x2e, 0x69, 0x7c, + 0x3b, 0x14, 0x73, 0xfd, 0xf8, 0xf4, 0x90, 0x0a, 0x45, 0xa1, 0x16, 0xe1, 0xb6, 0x72, 0x54, 0xcd, + 0xcb, 0x0e, 0x27, 0x26, 0xf5, 0x1d, 0x34, 0xd7, 0x9c, 0xa7, 0x59, 0xb4, 0xa1, 0x34, 0x8f, 0xa8, + 0xeb, 0x3b, 0x57, 0x34, 0xf5, 0xbc, 0x7c, 0x47, 0x5d, 0xd8, 0x99, 0x3a, 0xae, 0xb7, 0x88, 0x32, + 0xc7, 0xf5, 0x4c, 0x06, 0x09, 0x8a, 0x33, 0xb3, 0xfa, 0x08, 0xda, 0x98, 0xc6, 0x94, 0x9d, 0xb9, + 0x71, 0xec, 0x86, 0x41, 0x3f, 0x0c, 0x58, 0x14, 0x7a, 0x69, 0x06, 0xea, 0x63, 0xd8, 0xdf, 0x68, + 0x4d, 0x42, 0xe0, 0x83, 0xbf, 0x5d, 0xd0, 0xe8, 0x66, 0xf3, 0xe0, 0x6f, 0x61, 0x7f, 0xa3, 0x35, + 0x8d, 0xff, 0x39, 0x14, 0xe7, 0x8e, 0x1b, 0xc5, 0xad, 0x2d, 0xd1, 0x36, 0x7b, 0xb9, 0xb6, 0x19, + 0x3a, 0x6e, 0x74, 0xea, 0xc6, 0x2c, 0x8c, 0x6e, 0x70, 0x42, 0x7a, 0x25, 0x97, 0x24, 0x65, 0x4b, + 0xfd, 0xbb, 0x04, 0x95, 0x9c, 0x11, 0xed, 0x43, 0x39, 0x08, 0x27, 0x94, 0x4c, 0xa3, 0xd0, 0xcf, + 0x16, 0x81, 0x03, 0x27, 0x51, 0xe8, 0x73, 0x4d, 0x08, 0x23, 0x0b, 0x53, 0x41, 0x6e, 0xf3, 0x57, + 0x3b, 0x44, 0xbf, 0x84, 0x9d, 0x59, 0xe2, 0x40, 0x6c, 0x55, 0x95, 0xa3, 0xe6, 0xad, 0xb9, 0x35, + 0x87, 0x39, 0x38, 0xe3, 0xbc, 0x92, 0x4b, 0x05, 0x45, 0x7e, 0x25, 0x97, 0x64, 0xa5, 0xf8, 0x4a, + 0x2e, 0x15, 0x95, 0xed, 0x57, 0x72, 0x69, 0x5b, 0xd9, 0x51, 0xff, 0x23, 0x41, 0x29, 0x63, 0xf3, + 0x48, 0xf8, 0x92, 0x12, 0xae, 0x8b, 0x54, 0x4c, 0x25, 0x0e, 0xd8, 0xae, 0x4f, 0x51, 0x07, 0xaa, + 0xc2, 0xb8, 0x2e, 0x51, 0xe0, 0x58, 0x4f, 0xc8, 0x54, 0xec, 0xa1, 0x19, 0x43, 0xe8, 0x51, 0x4e, + 0xf7, 0xd0, 0x84, 0x92, 0x1d, 0x03, 0xf1, 0x62, 0x3c, 0xa6, 0x71, 0x9c, 0xcc, 0x52, 0x4c, 0x28, + 0x29, 0x26, 0x26, 0x7a, 0x02, 0x8d, 0x8c, 0x92, 0xcd, 0xb5, 0x9d, 0xe8, 0x35, 0x85, 0xd3, 0xe9, + 0xba, 0xa0, 0xe4, 0x79, 0xfe, 0x6a, 0xd7, 0xae, 0xaf, 0x88, 0x7c, 0xd2, 0x24, 0x79, 0xf5, 0x2f, + 0xf0, 0x50, 0x94, 0x72, 0x18, 0x85, 0x97, 0xce, 0xa5, 0xeb, 0xb9, 0xec, 0x26, 0x13, 0x39, 0x4f, + 0x3c, 0x0a, 0x7d, 0xc2, 0xd7, 0x36, 0x2b, 0x01, 0x07, 0xcc, 0x70, 0x42, 0x79, 0x09, 0x58, 0x98, + 0x98, 0xd2, 0x12, 0xb0, 0x50, 0x18, 0xf2, 0xa7, 0x5d, 0x61, 0xed, 0xb4, 0x53, 0xaf, 0xa1, 0x75, + 0x77, 0xae, 0x54, 0x33, 0x1d, 0xa8, 0xcc, 0x57, 0xb0, 0x98, 0x4e, 0xc2, 0x79, 0x28, 0x5f, 0xdb, + 0xad, 0x1f, 0xae, 0xad, 0xfa, 0x4f, 0x09, 0x76, 0x8f, 0x17, 0xae, 0x37, 0x59, 0x6b, 0xdc, 0x7c, + 0x74, 0xd2, 0xfa, 0x59, 0xbc, 0xe9, 0xa0, 0xdd, 0xda, 0x78, 0xd0, 0x6e, 0x3a, 0xcc, 0x0a, 0xf7, + 0x1e, 0x66, 0x3f, 0x85, 0xca, 0xea, 0x1c, 0x8b, 0x5b, 0x72, 0xa7, 0xd0, 0xad, 0x62, 0x98, 0x65, + 0x87, 0x58, 0xac, 0xbe, 0x04, 0x94, 0x0f, 0x34, 0x5d, 0x90, 0xe5, 0xfe, 0x21, 0xdd, 0xbf, 0x7f, + 0x3c, 0x82, 0xf6, 0x68, 0x71, 0x19, 0x8f, 0x23, 0xf7, 0x92, 0x9e, 0x32, 0x6f, 0xac, 0xbf, 0xa7, + 0x01, 0x8b, 0xb3, 0x2e, 0xfd, 0x9f, 0x0c, 0xe5, 0x25, 0x8a, 0x0e, 0xa0, 0xe9, 0x06, 0xe3, 0xd0, + 0xcf, 0x82, 0x0e, 0xa8, 0xc7, 0xe3, 0x4e, 0x36, 0xf9, 0xdd, 0xcc, 0xd4, 0x4f, 0x2c, 0xc6, 0x84, + 0xf3, 0xd7, 0x92, 0x4c, 0xf9, 0x5b, 0x09, 0x3f, 0x9f, 0x63, 0xc2, 0xef, 0x82, 0xb2, 0xf4, 0x3f, + 0x63, 0xde, 0x78, 0xb9, 0x28, 0xb8, 0x9e, 0xe1, 0x3c, 0x98, 0x84, 0xb9, 0xf4, 0x9c, 0x31, 0xe5, + 0x84, 0x99, 0xe1, 0x29, 0xf3, 0x73, 0xa8, 0xf2, 0x7e, 0x88, 0x99, 0xe3, 0xcf, 0x49, 0x10, 0x8b, + 0xbe, 0x90, 0x71, 0x65, 0x89, 0x99, 0x31, 0xfa, 0x0a, 0x80, 0xf2, 0xfc, 0x08, 0xbb, 0x99, 0x53, + 0xd1, 0x12, 0xf5, 0xa3, 0xcf, 0x72, 0xc2, 0x58, 0x2e, 0xc0, 0x81, 0xf8, 0x6b, 0xdf, 0xcc, 0x29, + 0x2e, 0xd3, 0xec, 0x11, 0x7d, 0x0d, 0xb5, 0x69, 0x18, 0x7d, 0x70, 0xa2, 0x09, 0x11, 0x60, 0xba, + 0x6d, 0x3c, 0xcc, 0x79, 0x38, 0x49, 0xec, 0x62, 0xf8, 0xe9, 0x27, 0xb8, 0x3a, 0xcd, 0xbd, 0xa3, + 0xd7, 0x80, 0xb2, 0xf1, 0xa2, 0xcb, 0x13, 0x27, 0x25, 0xe1, 0x64, 0xff, 0xae, 0x13, 0xbe, 0x49, + 0x67, 0x8e, 0x94, 0xe9, 0x2d, 0x0c, 0xfd, 0x1e, 0xaa, 0x31, 0x65, 0xcc, 0xa3, 0xa9, 0x9b, 0xb2, + 0x70, 0xb3, 0xb7, 0x76, 0xeb, 0xe0, 0xe6, 0xcc, 0x43, 0x25, 0x5e, 0xbd, 0xa2, 0x63, 0x68, 0x78, + 0x6e, 0x70, 0x9d, 0x0f, 0x03, 0xc4, 0xf8, 0x56, 0x6e, 0xfc, 0xc0, 0x0d, 0xae, 0xf3, 0x31, 0xd4, + 0xbc, 0x3c, 0xa0, 0xfe, 0x01, 0xca, 0xcb, 0x55, 0x42, 0x15, 0xd8, 0x39, 0x37, 0x5f, 0x9b, 0xd6, + 0x1b, 0x53, 0xf9, 0x04, 0x95, 0x40, 0x1e, 0xe9, 0xa6, 0xa6, 0x48, 0x1c, 0xc6, 0x7a, 0x5f, 0x37, + 0x2e, 0x74, 0x65, 0x8b, 0xbf, 0x9c, 0x58, 0xf8, 0x4d, 0x0f, 0x6b, 0x4a, 0xe1, 0x78, 0x07, 0x8a, + 0x62, 0x5e, 0xf5, 0x5f, 0x12, 0x94, 0x44, 0x05, 0x83, 0x69, 0x88, 0x7e, 0x01, 0x4b, 0x71, 0x89, + 0xcd, 0x8d, 0x1f, 0xb8, 0x42, 0x75, 0x35, 0xbc, 0x14, 0x8c, 0x9d, 0xe2, 0x9c, 0xbc, 0x94, 0xc6, + 0x92, 0xbc, 0x95, 0x90, 0x33, 0xc3, 0x92, 0xfc, 0x2c, 0xe7, 0x79, 0x6d, 0xcb, 0x91, 0x71, 0x23, + 0x33, 0x64, 0x3b, 0xec, 0xb3, 0x9c, 0xe3, 0xb5, 0x9d, 0x58, 0xc6, 0x8d, 0xcc, 0x90, 0x72, 0xd5, + 0xdf, 0x42, 0x35, 0x5f, 0x73, 0xf4, 0x14, 0x64, 0x37, 0x98, 0x86, 0x69, 0x23, 0x36, 0x6f, 0x89, + 0x8b, 0x27, 0x89, 0x05, 0x41, 0x45, 0xa0, 0xdc, 0xae, 0xb3, 0x5a, 0x83, 0x4a, 0xae, 0x68, 0xea, + 0xbf, 0x25, 0xa8, 0xad, 0x15, 0xe1, 0x47, 0x7b, 0x47, 0x5f, 0x41, 0xf5, 0x83, 0x1b, 0x51, 0x92, + 0x3f, 0xfe, 0xeb, 0x47, 0xed, 0xf5, 0xe3, 0x3f, 0xfb, 0xdf, 0x0f, 0x27, 0x14, 0x57, 0x38, 0x3f, + 0x05, 0xd0, 0x1f, 0xa1, 0x9e, 0x8e, 0x24, 0x13, 0xca, 0x1c, 0xd7, 0x13, 0x4b, 0x55, 0x5f, 0x93, + 0x47, 0xca, 0xd5, 0x84, 0x1d, 0xd7, 0xa6, 0xf9, 0x57, 0xf4, 0xc5, 0xca, 0x41, 0xcc, 0x22, 0x37, + 0xb8, 0x12, 0xeb, 0x57, 0x5e, 0xd2, 0x46, 0x02, 0x7c, 0xf6, 0x37, 0x19, 0x6a, 0x6b, 0x7e, 0xd6, + 0x85, 0x54, 0x83, 0xb2, 0x69, 0x11, 0x4d, 0xb7, 0x7b, 0xc6, 0x40, 0x91, 0x90, 0x02, 0x55, 0xcb, + 0x34, 0x2c, 0x93, 0x68, 0x7a, 0xdf, 0xd2, 0xb8, 0xa4, 0x3e, 0x85, 0xdd, 0x81, 0x61, 0xbe, 0x26, + 0xa6, 0x65, 0x13, 0x7d, 0x60, 0x7c, 0x63, 0x1c, 0x0f, 0x74, 0xa5, 0x80, 0x1e, 0x80, 0x62, 0x99, + 0xa4, 0x7f, 0xda, 0x33, 0x4c, 0x62, 0x1b, 0x67, 0xba, 0x75, 0x6e, 0x2b, 0x32, 0x47, 0x4f, 0xed, + 0x41, 0x9f, 0xe8, 0x6f, 0xfb, 0xba, 0xae, 0x8d, 0xc8, 0x59, 0xef, 0xad, 0x52, 0x44, 0x2d, 0x78, + 0x60, 0x98, 0xa3, 0xf3, 0x93, 0x13, 0xa3, 0x6f, 0xe8, 0xa6, 0x4d, 0x8e, 0x7b, 0x83, 0x9e, 0xd9, + 0xd7, 0x95, 0x6d, 0xb4, 0x07, 0xc8, 0x30, 0xfb, 0xd6, 0xd9, 0x70, 0xa0, 0xdb, 0x3a, 0xc9, 0xa4, + 0xbb, 0x83, 0x9a, 0xd0, 0x10, 0x7e, 0x7a, 0x9a, 0x46, 0x4e, 0x7a, 0xc6, 0x40, 0xd7, 0x94, 0x12, + 0x8f, 0x24, 0x65, 0x8c, 0x88, 0x66, 0x8c, 0x7a, 0xc7, 0x1c, 0x2e, 0xf3, 0x39, 0x0d, 0xf3, 0xc2, + 0x32, 0xfa, 0x3a, 0xe9, 0x73, 0xb7, 0x1c, 0x05, 0x4e, 0xce, 0xd0, 0x73, 0x53, 0xd3, 0xf1, 0xb0, + 0x67, 0x68, 0x4a, 0x05, 0xed, 0xc3, 0xc3, 0x0c, 0xd6, 0xdf, 0x0e, 0x0d, 0xfc, 0x1d, 0xb1, 0x2d, + 0x8b, 0x8c, 0x2c, 0xcb, 0x54, 0xaa, 0x79, 0x4f, 0x3c, 0x5b, 0x6b, 0xa8, 0x9b, 0x4a, 0x0d, 0x3d, + 0x84, 0xe6, 0xd9, 0x70, 0x48, 0x32, 0x4b, 0x96, 0x6c, 0x9d, 0xd3, 0x7b, 0x9a, 0x86, 0xf5, 0xd1, + 0x88, 0x9c, 0x19, 0xa3, 0xb3, 0x9e, 0xdd, 0x3f, 0x55, 0x1a, 0x3c, 0xa5, 0x91, 0x6e, 0x13, 0xdb, + 0xb2, 0x7b, 0x83, 0x15, 0xae, 0xf0, 0x80, 0x56, 0x38, 0x9f, 0x74, 0x60, 0xbd, 0x51, 0x76, 0xf9, + 0x82, 0x73, 0xd8, 0xba, 0x48, 0x43, 0x44, 0x3c, 0xf7, 0xb4, 0x3c, 0xd9, 0x9c, 0x4a, 0x93, 0x83, + 0x86, 0x79, 0xd1, 0x1b, 0x18, 0x1a, 0x79, 0xad, 0x7f, 0x27, 0x5a, 0xff, 0x01, 0x07, 0x93, 0xc8, + 0xc8, 0x10, 0x5b, 0xdf, 0xf0, 0x40, 0x94, 0x4f, 0x11, 0x82, 0x7a, 0xdf, 0xc0, 0xfd, 0xf3, 0x41, + 0x0f, 0x13, 0x6c, 0x9d, 0xdb, 0xba, 0xb2, 0x77, 0xf4, 0xdf, 0x22, 0x6c, 0x8b, 0x83, 0x2a, 0x42, + 0x7f, 0x82, 0x5a, 0xee, 0x53, 0xe9, 0xe2, 0x08, 0x3d, 0xfe, 0xe8, 0x47, 0x54, 0x3b, 0xbb, 0xce, + 0xa6, 0xf0, 0x0b, 0x09, 0x1d, 0x43, 0x3d, 0xff, 0x85, 0x71, 0x71, 0x84, 0xf2, 0xfb, 0xfb, 0x86, + 0x8f, 0x8f, 0x0d, 0x3e, 0x5e, 0x83, 0xa2, 0xc7, 0xcc, 0xf5, 0x1d, 0x46, 0xb3, 0x6f, 0x06, 0xd4, + 0xce, 0x79, 0xb9, 0xf5, 0x21, 0xd2, 0xde, 0xdf, 0x68, 0x4b, 0x4f, 0xe6, 0x01, 0x6f, 0xe9, 0xe5, + 0xad, 0xfd, 0x4e, 0x42, 0xeb, 0x9f, 0x0a, 0xed, 0xcf, 0xee, 0x33, 0xa7, 0xde, 0x26, 0xd0, 0xdc, + 0x70, 0x11, 0x47, 0x5f, 0xe4, 0x23, 0xb8, 0xf7, 0x1a, 0xdf, 0x7e, 0xf2, 0x43, 0xb4, 0xd5, 0x2c, + 0x1b, 0x6e, 0xec, 0x6b, 0xb3, 0xdc, 0x7f, 0xdf, 0x5f, 0x9b, 0xe5, 0x63, 0x17, 0xff, 0x77, 0xa0, + 0xdc, 0xbe, 0xe0, 0x21, 0xf5, 0xf6, 0xd8, 0xbb, 0x37, 0xcd, 0xf6, 0xcf, 0x3e, 0xca, 0x49, 0x9d, + 0x1b, 0x00, 0xab, 0x6b, 0x12, 0x7a, 0x94, 0x1b, 0x72, 0xe7, 0x9a, 0xd7, 0x7e, 0x7c, 0x8f, 0x35, + 0x75, 0x65, 0x43, 0x73, 0xc3, 0xbd, 0x69, 0x6d, 0x35, 0xee, 0xbf, 0x57, 0xb5, 0x1f, 0x6c, 0xba, + 0x5e, 0xbc, 0x90, 0x8e, 0xbf, 0xfc, 0xf3, 0xe1, 0x95, 0xcb, 0x66, 0x8b, 0xcb, 0x83, 0x71, 0xe8, + 0x1f, 0x7a, 0xee, 0xd5, 0x8c, 0x05, 0x6e, 0x70, 0x15, 0x50, 0xf6, 0x21, 0x8c, 0xae, 0x0f, 0xbd, + 0x60, 0x72, 0x28, 0x74, 0x79, 0xb8, 0x1c, 0x7e, 0xb9, 0x2d, 0x7e, 0x5e, 0xfa, 0xd5, 0xff, 0x03, + 0x00, 0x00, 0xff, 0xff, 0x40, 0x4b, 0x61, 0x91, 0x8e, 0x12, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1750,14 +1750,14 @@ const _ = grpc.SupportPackageIsVersion4 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type RouterClient interface { //* - //SendPayment attempts to route a payment described by the passed + //SendPaymentV2 attempts to route a payment described by the passed //PaymentRequest to the final destination. The call returns a stream of //payment updates. - SendPayment(ctx context.Context, in *SendPaymentRequest, opts ...grpc.CallOption) (Router_SendPaymentClient, error) + SendPaymentV2(ctx context.Context, in *SendPaymentRequest, opts ...grpc.CallOption) (Router_SendPaymentV2Client, error) //* - //TrackPayment returns an update stream for the payment identified by the + //TrackPaymentV2 returns an update stream for the payment identified by the //payment hash. - TrackPayment(ctx context.Context, in *TrackPaymentRequest, opts ...grpc.CallOption) (Router_TrackPaymentClient, error) + TrackPaymentV2(ctx context.Context, in *TrackPaymentRequest, opts ...grpc.CallOption) (Router_TrackPaymentV2Client, error) //* //EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it //may cost to send an HTLC to the target end destination. @@ -1798,12 +1798,12 @@ func NewRouterClient(cc *grpc.ClientConn) RouterClient { return &routerClient{cc} } -func (c *routerClient) SendPayment(ctx context.Context, in *SendPaymentRequest, opts ...grpc.CallOption) (Router_SendPaymentClient, error) { - stream, err := c.cc.NewStream(ctx, &_Router_serviceDesc.Streams[0], "/routerrpc.Router/SendPayment", opts...) +func (c *routerClient) SendPaymentV2(ctx context.Context, in *SendPaymentRequest, opts ...grpc.CallOption) (Router_SendPaymentV2Client, error) { + stream, err := c.cc.NewStream(ctx, &_Router_serviceDesc.Streams[0], "/routerrpc.Router/SendPaymentV2", opts...) if err != nil { return nil, err } - x := &routerSendPaymentClient{stream} + x := &routerSendPaymentV2Client{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -1813,16 +1813,16 @@ func (c *routerClient) SendPayment(ctx context.Context, in *SendPaymentRequest, return x, nil } -type Router_SendPaymentClient interface { +type Router_SendPaymentV2Client interface { Recv() (*lnrpc.Payment, error) grpc.ClientStream } -type routerSendPaymentClient struct { +type routerSendPaymentV2Client struct { grpc.ClientStream } -func (x *routerSendPaymentClient) Recv() (*lnrpc.Payment, error) { +func (x *routerSendPaymentV2Client) Recv() (*lnrpc.Payment, error) { m := new(lnrpc.Payment) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err @@ -1830,12 +1830,12 @@ func (x *routerSendPaymentClient) Recv() (*lnrpc.Payment, error) { return m, nil } -func (c *routerClient) TrackPayment(ctx context.Context, in *TrackPaymentRequest, opts ...grpc.CallOption) (Router_TrackPaymentClient, error) { - stream, err := c.cc.NewStream(ctx, &_Router_serviceDesc.Streams[1], "/routerrpc.Router/TrackPayment", opts...) +func (c *routerClient) TrackPaymentV2(ctx context.Context, in *TrackPaymentRequest, opts ...grpc.CallOption) (Router_TrackPaymentV2Client, error) { + stream, err := c.cc.NewStream(ctx, &_Router_serviceDesc.Streams[1], "/routerrpc.Router/TrackPaymentV2", opts...) if err != nil { return nil, err } - x := &routerTrackPaymentClient{stream} + x := &routerTrackPaymentV2Client{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -1845,16 +1845,16 @@ func (c *routerClient) TrackPayment(ctx context.Context, in *TrackPaymentRequest return x, nil } -type Router_TrackPaymentClient interface { +type Router_TrackPaymentV2Client interface { Recv() (*lnrpc.Payment, error) grpc.ClientStream } -type routerTrackPaymentClient struct { +type routerTrackPaymentV2Client struct { grpc.ClientStream } -func (x *routerTrackPaymentClient) Recv() (*lnrpc.Payment, error) { +func (x *routerTrackPaymentV2Client) Recv() (*lnrpc.Payment, error) { m := new(lnrpc.Payment) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err @@ -1951,14 +1951,14 @@ func (x *routerSubscribeHtlcEventsClient) Recv() (*HtlcEvent, error) { // RouterServer is the server API for Router service. type RouterServer interface { //* - //SendPayment attempts to route a payment described by the passed + //SendPaymentV2 attempts to route a payment described by the passed //PaymentRequest to the final destination. The call returns a stream of //payment updates. - SendPayment(*SendPaymentRequest, Router_SendPaymentServer) error + SendPaymentV2(*SendPaymentRequest, Router_SendPaymentV2Server) error //* - //TrackPayment returns an update stream for the payment identified by the + //TrackPaymentV2 returns an update stream for the payment identified by the //payment hash. - TrackPayment(*TrackPaymentRequest, Router_TrackPaymentServer) error + TrackPaymentV2(*TrackPaymentRequest, Router_TrackPaymentV2Server) error //* //EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it //may cost to send an HTLC to the target end destination. @@ -1995,45 +1995,45 @@ func RegisterRouterServer(s *grpc.Server, srv RouterServer) { s.RegisterService(&_Router_serviceDesc, srv) } -func _Router_SendPayment_Handler(srv interface{}, stream grpc.ServerStream) error { +func _Router_SendPaymentV2_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(SendPaymentRequest) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(RouterServer).SendPayment(m, &routerSendPaymentServer{stream}) + return srv.(RouterServer).SendPaymentV2(m, &routerSendPaymentV2Server{stream}) } -type Router_SendPaymentServer interface { +type Router_SendPaymentV2Server interface { Send(*lnrpc.Payment) error grpc.ServerStream } -type routerSendPaymentServer struct { +type routerSendPaymentV2Server struct { grpc.ServerStream } -func (x *routerSendPaymentServer) Send(m *lnrpc.Payment) error { +func (x *routerSendPaymentV2Server) Send(m *lnrpc.Payment) error { return x.ServerStream.SendMsg(m) } -func _Router_TrackPayment_Handler(srv interface{}, stream grpc.ServerStream) error { +func _Router_TrackPaymentV2_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(TrackPaymentRequest) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(RouterServer).TrackPayment(m, &routerTrackPaymentServer{stream}) + return srv.(RouterServer).TrackPaymentV2(m, &routerTrackPaymentV2Server{stream}) } -type Router_TrackPaymentServer interface { +type Router_TrackPaymentV2Server interface { Send(*lnrpc.Payment) error grpc.ServerStream } -type routerTrackPaymentServer struct { +type routerTrackPaymentV2Server struct { grpc.ServerStream } -func (x *routerTrackPaymentServer) Send(m *lnrpc.Payment) error { +func (x *routerTrackPaymentV2Server) Send(m *lnrpc.Payment) error { return x.ServerStream.SendMsg(m) } @@ -2197,13 +2197,13 @@ var _Router_serviceDesc = grpc.ServiceDesc{ }, Streams: []grpc.StreamDesc{ { - StreamName: "SendPayment", - Handler: _Router_SendPayment_Handler, + StreamName: "SendPaymentV2", + Handler: _Router_SendPaymentV2_Handler, ServerStreams: true, }, { - StreamName: "TrackPayment", - Handler: _Router_TrackPayment_Handler, + StreamName: "TrackPaymentV2", + Handler: _Router_TrackPaymentV2_Handler, ServerStreams: true, }, { diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 5bf947ade0..62980527b3 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -413,17 +413,17 @@ enum FailureDetail { service Router { /** - SendPayment attempts to route a payment described by the passed + SendPaymentV2 attempts to route a payment described by the passed PaymentRequest to the final destination. The call returns a stream of payment updates. */ - rpc SendPayment (SendPaymentRequest) returns (stream lnrpc.Payment); + rpc SendPaymentV2 (SendPaymentRequest) returns (stream lnrpc.Payment); /** - TrackPayment returns an update stream for the payment identified by the + TrackPaymentV2 returns an update stream for the payment identified by the payment hash. */ - rpc TrackPayment (TrackPaymentRequest) returns (stream lnrpc.Payment); + rpc TrackPaymentV2 (TrackPaymentRequest) returns (stream lnrpc.Payment); /** EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index d30ad86816..b380174511 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -48,7 +48,7 @@ var ( // macPermissions maps RPC calls to the permissions they require. macPermissions = map[string][]bakery.Op{ - "/routerrpc.Router/SendPayment": {{ + "/routerrpc.Router/SendPaymentV2": {{ Entity: "offchain", Action: "write", }}, @@ -56,7 +56,7 @@ var ( Entity: "offchain", Action: "write", }}, - "/routerrpc.Router/TrackPayment": {{ + "/routerrpc.Router/TrackPaymentV2": {{ Entity: "offchain", Action: "read", }}, @@ -214,13 +214,13 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } -// SendPayment attempts to route a payment described by the passed +// SendPaymentV2 attempts to route a payment described by the passed // PaymentRequest to the final destination. If we are unable to route the // payment, or cannot find a route that satisfies the constraints in the // PaymentRequest, then an error will be returned. Otherwise, the payment // pre-image, along with the final route will be returned. -func (s *Server) SendPayment(req *SendPaymentRequest, - stream Router_SendPaymentServer) error { +func (s *Server) SendPaymentV2(req *SendPaymentRequest, + stream Router_SendPaymentV2Server) error { payment, err := s.cfg.RouterBackend.extractIntentFromSendRequest(req) if err != nil { @@ -419,10 +419,10 @@ func (s *Server) QueryProbability(ctx context.Context, }, nil } -// TrackPayment returns a stream of payment state updates. The stream is +// TrackPaymentV2 returns a stream of payment state updates. The stream is // closed when the payment completes. -func (s *Server) TrackPayment(request *TrackPaymentRequest, - stream Router_TrackPaymentServer) error { +func (s *Server) TrackPaymentV2(request *TrackPaymentRequest, + stream Router_TrackPaymentV2Server) error { paymentHash, err := lntypes.MakeHash(request.PaymentHash) if err != nil { @@ -436,7 +436,7 @@ func (s *Server) TrackPayment(request *TrackPaymentRequest, // trackPayment writes payment status updates to the provided stream. func (s *Server) trackPayment(paymentHash lntypes.Hash, - stream Router_TrackPaymentServer) error { + stream Router_TrackPaymentV2Server) error { router := s.cfg.RouterBackend diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 94cc274480..b5e1eade46 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -14248,12 +14248,12 @@ func testHoldInvoicePersistence(net *lntest.NetworkHarness, t *harnessTest) { } // Let Alice initiate payments for all the created invoices. - var paymentStreams []routerrpc.Router_SendPaymentClient + var paymentStreams []routerrpc.Router_SendPaymentV2Client for _, payReq := range payReqs { ctx, cancel := context.WithCancel(ctxb) defer cancel() - payStream, err := net.Alice.RouterClient.SendPayment( + payStream, err := net.Alice.RouterClient.SendPaymentV2( ctx, &routerrpc.SendPaymentRequest{ PaymentRequest: payReq, TimeoutSeconds: 60, @@ -14365,7 +14365,7 @@ func testHoldInvoicePersistence(net *lntest.NetworkHarness, t *harnessTest) { ctx, cancel := context.WithCancel(ctxb) defer cancel() - payStream, err := net.Alice.RouterClient.TrackPayment( + payStream, err := net.Alice.RouterClient.TrackPaymentV2( ctx, &routerrpc.TrackPaymentRequest{ PaymentHash: hash[:], }, @@ -14724,7 +14724,7 @@ func sendAndAssertSuccess(t *harnessTest, node *lntest.HarnessNode, ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() - stream, err := node.RouterClient.SendPayment(ctx, req) + stream, err := node.RouterClient.SendPaymentV2(ctx, req) if err != nil { t.Fatalf("unable to send payment: %v", err) } @@ -14742,7 +14742,7 @@ func sendAndAssertSuccess(t *harnessTest, node *lntest.HarnessNode, } // getPaymentResult reads a final result from the stream and returns it. -func getPaymentResult(stream routerrpc.Router_SendPaymentClient) ( +func getPaymentResult(stream routerrpc.Router_SendPaymentV2Client) ( *lnrpc.Payment, error) { for { From ad5f1404cb5ae177ed5b689660e39020cff1429c Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 13 Apr 2020 10:20:22 +0200 Subject: [PATCH 509/562] lnrpc: remove experimental tag from payment htlcs --- lnrpc/rpc.pb.go | 2 +- lnrpc/rpc.proto | 2 +- lnrpc/rpc.swagger.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 10f9a7cde9..2c55f6b0f4 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -9556,7 +9556,7 @@ type Payment struct { FeeMsat int64 `protobuf:"varint,12,opt,name=fee_msat,json=feeMsat,proto3" json:"fee_msat,omitempty"` /// The time in UNIX nanoseconds at which the payment was created. CreationTimeNs int64 `protobuf:"varint,13,opt,name=creation_time_ns,json=creationTimeNs,proto3" json:"creation_time_ns,omitempty"` - /// The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. + /// The HTLCs made in attempt to settle the payment. Htlcs []*HTLCAttempt `protobuf:"bytes,14,rep,name=htlcs,proto3" json:"htlcs,omitempty"` //* //The creation index of this payment. Each payment can be uniquely identified diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 1317b96409..7f58e59e99 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -3136,7 +3136,7 @@ message Payment { /// The time in UNIX nanoseconds at which the payment was created. int64 creation_time_ns = 13; - /// The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. + /// The HTLCs made in attempt to settle the payment. repeated HTLCAttempt htlcs = 14; /** diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 90859472dc..189fb6f0e3 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -3987,7 +3987,7 @@ "items": { "$ref": "#/definitions/lnrpcHTLCAttempt" }, - "description": "/ The HTLCs made in attempt to settle the payment [EXPERIMENTAL]." + "description": "/ The HTLCs made in attempt to settle the payment." }, "payment_index": { "type": "string", From 7fe100bcfb04834fc71d61e49cbe013837892da7 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 13 Apr 2020 12:16:55 +0200 Subject: [PATCH 510/562] routerrpc: bring back legacy track and send rpcs To soften the transition for routerrpc users to the V2 messages. --- lnrpc/routerrpc/router.pb.go | 523 +++++++++++++++----- lnrpc/routerrpc/router.proto | 73 +++ lnrpc/routerrpc/router_server.go | 8 + lnrpc/routerrpc/router_server_deprecated.go | 95 ++++ 4 files changed, 570 insertions(+), 129 deletions(-) create mode 100644 lnrpc/routerrpc/router_server_deprecated.go diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 7b0b18d090..4f6dd0fc4e 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -111,6 +111,62 @@ func (FailureDetail) EnumDescriptor() ([]byte, []int) { return fileDescriptor_7a0613f69d37b0a5, []int{0} } +type PaymentState int32 + +const ( + //* + //Payment is still in flight. + PaymentState_IN_FLIGHT PaymentState = 0 + //* + //Payment completed successfully. + PaymentState_SUCCEEDED PaymentState = 1 + //* + //There are more routes to try, but the payment timeout was exceeded. + PaymentState_FAILED_TIMEOUT PaymentState = 2 + //* + //All possible routes were tried and failed permanently. Or were no + //routes to the destination at all. + PaymentState_FAILED_NO_ROUTE PaymentState = 3 + //* + //A non-recoverable error has occured. + PaymentState_FAILED_ERROR PaymentState = 4 + //* + //Payment details incorrect (unknown hash, invalid amt or + //invalid final cltv delta) + PaymentState_FAILED_INCORRECT_PAYMENT_DETAILS PaymentState = 5 + //* + //Insufficient local balance. + PaymentState_FAILED_INSUFFICIENT_BALANCE PaymentState = 6 +) + +var PaymentState_name = map[int32]string{ + 0: "IN_FLIGHT", + 1: "SUCCEEDED", + 2: "FAILED_TIMEOUT", + 3: "FAILED_NO_ROUTE", + 4: "FAILED_ERROR", + 5: "FAILED_INCORRECT_PAYMENT_DETAILS", + 6: "FAILED_INSUFFICIENT_BALANCE", +} + +var PaymentState_value = map[string]int32{ + "IN_FLIGHT": 0, + "SUCCEEDED": 1, + "FAILED_TIMEOUT": 2, + "FAILED_NO_ROUTE": 3, + "FAILED_ERROR": 4, + "FAILED_INCORRECT_PAYMENT_DETAILS": 5, + "FAILED_INSUFFICIENT_BALANCE": 6, +} + +func (x PaymentState) String() string { + return proto.EnumName(PaymentState_name, int32(x)) +} + +func (PaymentState) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{1} +} + type HtlcEvent_EventType int32 const ( @@ -1574,8 +1630,69 @@ func (m *LinkFailEvent) GetFailureString() string { return "" } +type PaymentStatus struct { + /// Current state the payment is in. + State PaymentState `protobuf:"varint,1,opt,name=state,proto3,enum=routerrpc.PaymentState" json:"state,omitempty"` + //* + //The pre-image of the payment when state is SUCCEEDED. + Preimage []byte `protobuf:"bytes,2,opt,name=preimage,proto3" json:"preimage,omitempty"` + //* + //The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. + Htlcs []*lnrpc.HTLCAttempt `protobuf:"bytes,4,rep,name=htlcs,proto3" json:"htlcs,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PaymentStatus) Reset() { *m = PaymentStatus{} } +func (m *PaymentStatus) String() string { return proto.CompactTextString(m) } +func (*PaymentStatus) ProtoMessage() {} +func (*PaymentStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{23} +} + +func (m *PaymentStatus) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PaymentStatus.Unmarshal(m, b) +} +func (m *PaymentStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PaymentStatus.Marshal(b, m, deterministic) +} +func (m *PaymentStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_PaymentStatus.Merge(m, src) +} +func (m *PaymentStatus) XXX_Size() int { + return xxx_messageInfo_PaymentStatus.Size(m) +} +func (m *PaymentStatus) XXX_DiscardUnknown() { + xxx_messageInfo_PaymentStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_PaymentStatus proto.InternalMessageInfo + +func (m *PaymentStatus) GetState() PaymentState { + if m != nil { + return m.State + } + return PaymentState_IN_FLIGHT +} + +func (m *PaymentStatus) GetPreimage() []byte { + if m != nil { + return m.Preimage + } + return nil +} + +func (m *PaymentStatus) GetHtlcs() []*lnrpc.HTLCAttempt { + if m != nil { + return m.Htlcs + } + return nil +} + func init() { proto.RegisterEnum("routerrpc.FailureDetail", FailureDetail_name, FailureDetail_value) + proto.RegisterEnum("routerrpc.PaymentState", PaymentState_name, PaymentState_value) proto.RegisterEnum("routerrpc.HtlcEvent_EventType", HtlcEvent_EventType_name, HtlcEvent_EventType_value) proto.RegisterType((*SendPaymentRequest)(nil), "routerrpc.SendPaymentRequest") proto.RegisterMapType((map[uint64][]byte)(nil), "routerrpc.SendPaymentRequest.DestCustomRecordsEntry") @@ -1601,140 +1718,152 @@ func init() { proto.RegisterType((*ForwardFailEvent)(nil), "routerrpc.ForwardFailEvent") proto.RegisterType((*SettleEvent)(nil), "routerrpc.SettleEvent") proto.RegisterType((*LinkFailEvent)(nil), "routerrpc.LinkFailEvent") + proto.RegisterType((*PaymentStatus)(nil), "routerrpc.PaymentStatus") } func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2044 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xcd, 0x76, 0xdb, 0xc6, - 0x15, 0x0e, 0x44, 0x50, 0x22, 0x2f, 0xff, 0xa0, 0xa1, 0x23, 0xb3, 0x94, 0x9d, 0x32, 0x68, 0x63, - 0xf3, 0xb8, 0xae, 0xe4, 0xa8, 0x3d, 0xad, 0x4f, 0xdb, 0xa4, 0xa5, 0x08, 0x28, 0x82, 0x4d, 0x01, - 0xcc, 0x10, 0x92, 0x9d, 0x7a, 0x31, 0x07, 0x22, 0x87, 0x22, 0x2a, 0xfc, 0xb0, 0xc0, 0xd0, 0x8e, - 0x96, 0xdd, 0xf6, 0x05, 0xfa, 0x08, 0x7d, 0x89, 0xbe, 0x4b, 0xb7, 0xdd, 0xf7, 0x9c, 0xae, 0x7b, - 0x66, 0x00, 0x90, 0xa0, 0x44, 0x39, 0xd9, 0x48, 0xc0, 0x77, 0xbf, 0xb9, 0x73, 0xef, 0xdc, 0xef, - 0xce, 0x0c, 0x08, 0x7b, 0x51, 0xb8, 0x60, 0x34, 0x8a, 0xe6, 0xe3, 0xc3, 0xe4, 0xe9, 0x60, 0x1e, - 0x85, 0x2c, 0x44, 0xe5, 0x25, 0xde, 0x2e, 0x47, 0xf3, 0x71, 0x82, 0xaa, 0xff, 0xd8, 0x06, 0x34, - 0xa2, 0xc1, 0x64, 0xe8, 0xdc, 0xf8, 0x34, 0x60, 0x98, 0xfe, 0x75, 0x41, 0x63, 0x86, 0x10, 0xc8, - 0x13, 0x1a, 0xb3, 0x96, 0xd4, 0x91, 0xba, 0x55, 0x2c, 0x9e, 0x91, 0x02, 0x05, 0xc7, 0x67, 0xad, - 0xad, 0x8e, 0xd4, 0x2d, 0x60, 0xfe, 0x88, 0x7e, 0x02, 0x25, 0xc7, 0x67, 0xc4, 0x8f, 0x1d, 0xd6, - 0xaa, 0x0a, 0x78, 0xc7, 0xf1, 0xd9, 0x59, 0xec, 0x30, 0xf4, 0x39, 0x54, 0xe7, 0x89, 0x4b, 0x32, - 0x73, 0xe2, 0x59, 0xab, 0x20, 0x1c, 0x55, 0x52, 0xec, 0xd4, 0x89, 0x67, 0xa8, 0x0b, 0xca, 0xd4, - 0x0d, 0x1c, 0x8f, 0x8c, 0x3d, 0xf6, 0x9e, 0x4c, 0xa8, 0xc7, 0x9c, 0x96, 0xdc, 0x91, 0xba, 0x45, - 0x5c, 0x17, 0x78, 0xdf, 0x63, 0xef, 0x35, 0x8e, 0xa2, 0xa7, 0xd0, 0xc8, 0x9c, 0x45, 0x49, 0x80, - 0xad, 0x62, 0x47, 0xea, 0x96, 0x71, 0x7d, 0xbe, 0x1e, 0xf6, 0x53, 0x68, 0x30, 0xd7, 0xa7, 0xe1, - 0x82, 0x91, 0x98, 0x8e, 0xc3, 0x60, 0x12, 0xb7, 0xb6, 0x13, 0x8f, 0x29, 0x3c, 0x4a, 0x50, 0xa4, - 0x42, 0x6d, 0x4a, 0x29, 0xf1, 0x5c, 0xdf, 0x65, 0x84, 0x87, 0xbf, 0x23, 0xc2, 0xaf, 0x4c, 0x29, - 0x1d, 0x70, 0x6c, 0xe4, 0x30, 0xf4, 0x73, 0xa8, 0xaf, 0x38, 0x22, 0xc7, 0x9a, 0x20, 0x55, 0x33, - 0x92, 0x48, 0xf4, 0x39, 0x28, 0xe1, 0x82, 0x5d, 0x85, 0x6e, 0x70, 0x45, 0xc6, 0x33, 0x27, 0x20, - 0xee, 0xa4, 0x55, 0xea, 0x48, 0x5d, 0xf9, 0x78, 0xeb, 0x85, 0x84, 0xeb, 0x99, 0xad, 0x3f, 0x73, - 0x02, 0x63, 0x82, 0x9e, 0x40, 0xc3, 0x73, 0x62, 0x46, 0x66, 0xe1, 0x9c, 0xcc, 0x17, 0x97, 0xd7, - 0xf4, 0xa6, 0x55, 0x17, 0x2b, 0x53, 0xe3, 0xf0, 0x69, 0x38, 0x1f, 0x0a, 0x10, 0x3d, 0x06, 0x10, - 0xab, 0x22, 0x26, 0x6f, 0x95, 0x45, 0x0e, 0x65, 0x8e, 0x88, 0x89, 0xd1, 0x97, 0x50, 0x11, 0xd5, - 0x24, 0x33, 0x37, 0x60, 0x71, 0x0b, 0x3a, 0x85, 0x6e, 0xe5, 0x48, 0x39, 0xf0, 0x02, 0x5e, 0x58, - 0xcc, 0x2d, 0xa7, 0x6e, 0xc0, 0x30, 0x44, 0xd9, 0x63, 0x8c, 0x26, 0xd0, 0xe4, 0x55, 0x24, 0xe3, - 0x45, 0xcc, 0x42, 0x9f, 0x44, 0x74, 0x1c, 0x46, 0x93, 0xb8, 0x55, 0x11, 0x43, 0x7f, 0x7d, 0xb0, - 0x14, 0xc7, 0xc1, 0x5d, 0x35, 0x1c, 0x68, 0x34, 0x66, 0x7d, 0x31, 0x0e, 0x27, 0xc3, 0xf4, 0x80, - 0x45, 0x37, 0x78, 0x77, 0x72, 0x1b, 0x47, 0xcf, 0x01, 0x39, 0x9e, 0x17, 0x7e, 0x20, 0x31, 0xf5, - 0xa6, 0x24, 0xad, 0x4e, 0xab, 0xd1, 0x91, 0xba, 0x25, 0xac, 0x08, 0xcb, 0x88, 0x7a, 0xd3, 0xd4, - 0x3d, 0xfa, 0x0d, 0xd4, 0x44, 0x4c, 0x53, 0xea, 0xb0, 0x45, 0x44, 0xe3, 0x96, 0xd2, 0x29, 0x74, - 0xeb, 0x47, 0xbb, 0x69, 0x22, 0x27, 0x09, 0x7c, 0xec, 0x32, 0x5c, 0xe5, 0xbc, 0xf4, 0x3d, 0xe6, - 0xab, 0xe3, 0x3b, 0xdf, 0x93, 0x78, 0xe6, 0xf0, 0x14, 0x76, 0x3b, 0x52, 0xb7, 0x86, 0xcb, 0xbe, - 0xf3, 0xfd, 0x48, 0x00, 0x6d, 0x0d, 0xf6, 0x36, 0x47, 0xcc, 0x25, 0xcc, 0x97, 0x9c, 0xab, 0x5a, - 0xc6, 0xfc, 0x11, 0x3d, 0x80, 0xe2, 0x7b, 0xc7, 0x5b, 0x50, 0x21, 0xeb, 0x2a, 0x4e, 0x5e, 0x7e, - 0xb7, 0xf5, 0x52, 0x52, 0x5f, 0x42, 0xd3, 0x8e, 0x9c, 0xf1, 0xf5, 0xad, 0xce, 0xb8, 0x2d, 0x6c, - 0xe9, 0x8e, 0xb0, 0xd5, 0xaf, 0xa1, 0x21, 0x6a, 0x70, 0x42, 0xe9, 0xc7, 0xfa, 0xe9, 0x21, 0xf0, - 0x6e, 0x11, 0xea, 0x4b, 0x7a, 0x6a, 0xdb, 0xf1, 0xb9, 0xf0, 0xd4, 0x09, 0x28, 0xab, 0xf1, 0xf1, - 0x3c, 0x0c, 0x62, 0xca, 0x9b, 0x85, 0x97, 0x88, 0xab, 0x8c, 0x8b, 0x52, 0xc8, 0x51, 0x12, 0xa3, - 0xea, 0x29, 0x7e, 0x42, 0xa9, 0x10, 0xe4, 0x93, 0xa4, 0x07, 0x88, 0x17, 0x8e, 0xaf, 0x79, 0x57, - 0x39, 0x37, 0xa9, 0xfb, 0x1a, 0x87, 0x07, 0xe1, 0xf8, 0x5a, 0xe3, 0xa0, 0xfa, 0x2e, 0x69, 0x7c, - 0x3b, 0x14, 0x73, 0xfd, 0xf8, 0xf4, 0x90, 0x0a, 0x45, 0xa1, 0x16, 0xe1, 0xb6, 0x72, 0x54, 0xcd, - 0xcb, 0x0e, 0x27, 0x26, 0xf5, 0x1d, 0x34, 0xd7, 0x9c, 0xa7, 0x59, 0xb4, 0xa1, 0x34, 0x8f, 0xa8, - 0xeb, 0x3b, 0x57, 0x34, 0xf5, 0xbc, 0x7c, 0x47, 0x5d, 0xd8, 0x99, 0x3a, 0xae, 0xb7, 0x88, 0x32, - 0xc7, 0xf5, 0x4c, 0x06, 0x09, 0x8a, 0x33, 0xb3, 0xfa, 0x08, 0xda, 0x98, 0xc6, 0x94, 0x9d, 0xb9, - 0x71, 0xec, 0x86, 0x41, 0x3f, 0x0c, 0x58, 0x14, 0x7a, 0x69, 0x06, 0xea, 0x63, 0xd8, 0xdf, 0x68, - 0x4d, 0x42, 0xe0, 0x83, 0xbf, 0x5d, 0xd0, 0xe8, 0x66, 0xf3, 0xe0, 0x6f, 0x61, 0x7f, 0xa3, 0x35, - 0x8d, 0xff, 0x39, 0x14, 0xe7, 0x8e, 0x1b, 0xc5, 0xad, 0x2d, 0xd1, 0x36, 0x7b, 0xb9, 0xb6, 0x19, - 0x3a, 0x6e, 0x74, 0xea, 0xc6, 0x2c, 0x8c, 0x6e, 0x70, 0x42, 0x7a, 0x25, 0x97, 0x24, 0x65, 0x4b, - 0xfd, 0xbb, 0x04, 0x95, 0x9c, 0x11, 0xed, 0x43, 0x39, 0x08, 0x27, 0x94, 0x4c, 0xa3, 0xd0, 0xcf, - 0x16, 0x81, 0x03, 0x27, 0x51, 0xe8, 0x73, 0x4d, 0x08, 0x23, 0x0b, 0x53, 0x41, 0x6e, 0xf3, 0x57, - 0x3b, 0x44, 0xbf, 0x84, 0x9d, 0x59, 0xe2, 0x40, 0x6c, 0x55, 0x95, 0xa3, 0xe6, 0xad, 0xb9, 0x35, - 0x87, 0x39, 0x38, 0xe3, 0xbc, 0x92, 0x4b, 0x05, 0x45, 0x7e, 0x25, 0x97, 0x64, 0xa5, 0xf8, 0x4a, - 0x2e, 0x15, 0x95, 0xed, 0x57, 0x72, 0x69, 0x5b, 0xd9, 0x51, 0xff, 0x23, 0x41, 0x29, 0x63, 0xf3, - 0x48, 0xf8, 0x92, 0x12, 0xae, 0x8b, 0x54, 0x4c, 0x25, 0x0e, 0xd8, 0xae, 0x4f, 0x51, 0x07, 0xaa, - 0xc2, 0xb8, 0x2e, 0x51, 0xe0, 0x58, 0x4f, 0xc8, 0x54, 0xec, 0xa1, 0x19, 0x43, 0xe8, 0x51, 0x4e, - 0xf7, 0xd0, 0x84, 0x92, 0x1d, 0x03, 0xf1, 0x62, 0x3c, 0xa6, 0x71, 0x9c, 0xcc, 0x52, 0x4c, 0x28, - 0x29, 0x26, 0x26, 0x7a, 0x02, 0x8d, 0x8c, 0x92, 0xcd, 0xb5, 0x9d, 0xe8, 0x35, 0x85, 0xd3, 0xe9, - 0xba, 0xa0, 0xe4, 0x79, 0xfe, 0x6a, 0xd7, 0xae, 0xaf, 0x88, 0x7c, 0xd2, 0x24, 0x79, 0xf5, 0x2f, - 0xf0, 0x50, 0x94, 0x72, 0x18, 0x85, 0x97, 0xce, 0xa5, 0xeb, 0xb9, 0xec, 0x26, 0x13, 0x39, 0x4f, - 0x3c, 0x0a, 0x7d, 0xc2, 0xd7, 0x36, 0x2b, 0x01, 0x07, 0xcc, 0x70, 0x42, 0x79, 0x09, 0x58, 0x98, - 0x98, 0xd2, 0x12, 0xb0, 0x50, 0x18, 0xf2, 0xa7, 0x5d, 0x61, 0xed, 0xb4, 0x53, 0xaf, 0xa1, 0x75, - 0x77, 0xae, 0x54, 0x33, 0x1d, 0xa8, 0xcc, 0x57, 0xb0, 0x98, 0x4e, 0xc2, 0x79, 0x28, 0x5f, 0xdb, - 0xad, 0x1f, 0xae, 0xad, 0xfa, 0x4f, 0x09, 0x76, 0x8f, 0x17, 0xae, 0x37, 0x59, 0x6b, 0xdc, 0x7c, - 0x74, 0xd2, 0xfa, 0x59, 0xbc, 0xe9, 0xa0, 0xdd, 0xda, 0x78, 0xd0, 0x6e, 0x3a, 0xcc, 0x0a, 0xf7, - 0x1e, 0x66, 0x3f, 0x85, 0xca, 0xea, 0x1c, 0x8b, 0x5b, 0x72, 0xa7, 0xd0, 0xad, 0x62, 0x98, 0x65, - 0x87, 0x58, 0xac, 0xbe, 0x04, 0x94, 0x0f, 0x34, 0x5d, 0x90, 0xe5, 0xfe, 0x21, 0xdd, 0xbf, 0x7f, - 0x3c, 0x82, 0xf6, 0x68, 0x71, 0x19, 0x8f, 0x23, 0xf7, 0x92, 0x9e, 0x32, 0x6f, 0xac, 0xbf, 0xa7, - 0x01, 0x8b, 0xb3, 0x2e, 0xfd, 0x9f, 0x0c, 0xe5, 0x25, 0x8a, 0x0e, 0xa0, 0xe9, 0x06, 0xe3, 0xd0, - 0xcf, 0x82, 0x0e, 0xa8, 0xc7, 0xe3, 0x4e, 0x36, 0xf9, 0xdd, 0xcc, 0xd4, 0x4f, 0x2c, 0xc6, 0x84, - 0xf3, 0xd7, 0x92, 0x4c, 0xf9, 0x5b, 0x09, 0x3f, 0x9f, 0x63, 0xc2, 0xef, 0x82, 0xb2, 0xf4, 0x3f, - 0x63, 0xde, 0x78, 0xb9, 0x28, 0xb8, 0x9e, 0xe1, 0x3c, 0x98, 0x84, 0xb9, 0xf4, 0x9c, 0x31, 0xe5, - 0x84, 0x99, 0xe1, 0x29, 0xf3, 0x73, 0xa8, 0xf2, 0x7e, 0x88, 0x99, 0xe3, 0xcf, 0x49, 0x10, 0x8b, - 0xbe, 0x90, 0x71, 0x65, 0x89, 0x99, 0x31, 0xfa, 0x0a, 0x80, 0xf2, 0xfc, 0x08, 0xbb, 0x99, 0x53, - 0xd1, 0x12, 0xf5, 0xa3, 0xcf, 0x72, 0xc2, 0x58, 0x2e, 0xc0, 0x81, 0xf8, 0x6b, 0xdf, 0xcc, 0x29, - 0x2e, 0xd3, 0xec, 0x11, 0x7d, 0x0d, 0xb5, 0x69, 0x18, 0x7d, 0x70, 0xa2, 0x09, 0x11, 0x60, 0xba, - 0x6d, 0x3c, 0xcc, 0x79, 0x38, 0x49, 0xec, 0x62, 0xf8, 0xe9, 0x27, 0xb8, 0x3a, 0xcd, 0xbd, 0xa3, - 0xd7, 0x80, 0xb2, 0xf1, 0xa2, 0xcb, 0x13, 0x27, 0x25, 0xe1, 0x64, 0xff, 0xae, 0x13, 0xbe, 0x49, - 0x67, 0x8e, 0x94, 0xe9, 0x2d, 0x0c, 0xfd, 0x1e, 0xaa, 0x31, 0x65, 0xcc, 0xa3, 0xa9, 0x9b, 0xb2, - 0x70, 0xb3, 0xb7, 0x76, 0xeb, 0xe0, 0xe6, 0xcc, 0x43, 0x25, 0x5e, 0xbd, 0xa2, 0x63, 0x68, 0x78, - 0x6e, 0x70, 0x9d, 0x0f, 0x03, 0xc4, 0xf8, 0x56, 0x6e, 0xfc, 0xc0, 0x0d, 0xae, 0xf3, 0x31, 0xd4, - 0xbc, 0x3c, 0xa0, 0xfe, 0x01, 0xca, 0xcb, 0x55, 0x42, 0x15, 0xd8, 0x39, 0x37, 0x5f, 0x9b, 0xd6, - 0x1b, 0x53, 0xf9, 0x04, 0x95, 0x40, 0x1e, 0xe9, 0xa6, 0xa6, 0x48, 0x1c, 0xc6, 0x7a, 0x5f, 0x37, - 0x2e, 0x74, 0x65, 0x8b, 0xbf, 0x9c, 0x58, 0xf8, 0x4d, 0x0f, 0x6b, 0x4a, 0xe1, 0x78, 0x07, 0x8a, - 0x62, 0x5e, 0xf5, 0x5f, 0x12, 0x94, 0x44, 0x05, 0x83, 0x69, 0x88, 0x7e, 0x01, 0x4b, 0x71, 0x89, - 0xcd, 0x8d, 0x1f, 0xb8, 0x42, 0x75, 0x35, 0xbc, 0x14, 0x8c, 0x9d, 0xe2, 0x9c, 0xbc, 0x94, 0xc6, - 0x92, 0xbc, 0x95, 0x90, 0x33, 0xc3, 0x92, 0xfc, 0x2c, 0xe7, 0x79, 0x6d, 0xcb, 0x91, 0x71, 0x23, - 0x33, 0x64, 0x3b, 0xec, 0xb3, 0x9c, 0xe3, 0xb5, 0x9d, 0x58, 0xc6, 0x8d, 0xcc, 0x90, 0x72, 0xd5, - 0xdf, 0x42, 0x35, 0x5f, 0x73, 0xf4, 0x14, 0x64, 0x37, 0x98, 0x86, 0x69, 0x23, 0x36, 0x6f, 0x89, - 0x8b, 0x27, 0x89, 0x05, 0x41, 0x45, 0xa0, 0xdc, 0xae, 0xb3, 0x5a, 0x83, 0x4a, 0xae, 0x68, 0xea, - 0xbf, 0x25, 0xa8, 0xad, 0x15, 0xe1, 0x47, 0x7b, 0x47, 0x5f, 0x41, 0xf5, 0x83, 0x1b, 0x51, 0x92, - 0x3f, 0xfe, 0xeb, 0x47, 0xed, 0xf5, 0xe3, 0x3f, 0xfb, 0xdf, 0x0f, 0x27, 0x14, 0x57, 0x38, 0x3f, - 0x05, 0xd0, 0x1f, 0xa1, 0x9e, 0x8e, 0x24, 0x13, 0xca, 0x1c, 0xd7, 0x13, 0x4b, 0x55, 0x5f, 0x93, - 0x47, 0xca, 0xd5, 0x84, 0x1d, 0xd7, 0xa6, 0xf9, 0x57, 0xf4, 0xc5, 0xca, 0x41, 0xcc, 0x22, 0x37, - 0xb8, 0x12, 0xeb, 0x57, 0x5e, 0xd2, 0x46, 0x02, 0x7c, 0xf6, 0x37, 0x19, 0x6a, 0x6b, 0x7e, 0xd6, - 0x85, 0x54, 0x83, 0xb2, 0x69, 0x11, 0x4d, 0xb7, 0x7b, 0xc6, 0x40, 0x91, 0x90, 0x02, 0x55, 0xcb, - 0x34, 0x2c, 0x93, 0x68, 0x7a, 0xdf, 0xd2, 0xb8, 0xa4, 0x3e, 0x85, 0xdd, 0x81, 0x61, 0xbe, 0x26, - 0xa6, 0x65, 0x13, 0x7d, 0x60, 0x7c, 0x63, 0x1c, 0x0f, 0x74, 0xa5, 0x80, 0x1e, 0x80, 0x62, 0x99, - 0xa4, 0x7f, 0xda, 0x33, 0x4c, 0x62, 0x1b, 0x67, 0xba, 0x75, 0x6e, 0x2b, 0x32, 0x47, 0x4f, 0xed, - 0x41, 0x9f, 0xe8, 0x6f, 0xfb, 0xba, 0xae, 0x8d, 0xc8, 0x59, 0xef, 0xad, 0x52, 0x44, 0x2d, 0x78, - 0x60, 0x98, 0xa3, 0xf3, 0x93, 0x13, 0xa3, 0x6f, 0xe8, 0xa6, 0x4d, 0x8e, 0x7b, 0x83, 0x9e, 0xd9, - 0xd7, 0x95, 0x6d, 0xb4, 0x07, 0xc8, 0x30, 0xfb, 0xd6, 0xd9, 0x70, 0xa0, 0xdb, 0x3a, 0xc9, 0xa4, - 0xbb, 0x83, 0x9a, 0xd0, 0x10, 0x7e, 0x7a, 0x9a, 0x46, 0x4e, 0x7a, 0xc6, 0x40, 0xd7, 0x94, 0x12, - 0x8f, 0x24, 0x65, 0x8c, 0x88, 0x66, 0x8c, 0x7a, 0xc7, 0x1c, 0x2e, 0xf3, 0x39, 0x0d, 0xf3, 0xc2, - 0x32, 0xfa, 0x3a, 0xe9, 0x73, 0xb7, 0x1c, 0x05, 0x4e, 0xce, 0xd0, 0x73, 0x53, 0xd3, 0xf1, 0xb0, - 0x67, 0x68, 0x4a, 0x05, 0xed, 0xc3, 0xc3, 0x0c, 0xd6, 0xdf, 0x0e, 0x0d, 0xfc, 0x1d, 0xb1, 0x2d, - 0x8b, 0x8c, 0x2c, 0xcb, 0x54, 0xaa, 0x79, 0x4f, 0x3c, 0x5b, 0x6b, 0xa8, 0x9b, 0x4a, 0x0d, 0x3d, - 0x84, 0xe6, 0xd9, 0x70, 0x48, 0x32, 0x4b, 0x96, 0x6c, 0x9d, 0xd3, 0x7b, 0x9a, 0x86, 0xf5, 0xd1, - 0x88, 0x9c, 0x19, 0xa3, 0xb3, 0x9e, 0xdd, 0x3f, 0x55, 0x1a, 0x3c, 0xa5, 0x91, 0x6e, 0x13, 0xdb, - 0xb2, 0x7b, 0x83, 0x15, 0xae, 0xf0, 0x80, 0x56, 0x38, 0x9f, 0x74, 0x60, 0xbd, 0x51, 0x76, 0xf9, - 0x82, 0x73, 0xd8, 0xba, 0x48, 0x43, 0x44, 0x3c, 0xf7, 0xb4, 0x3c, 0xd9, 0x9c, 0x4a, 0x93, 0x83, - 0x86, 0x79, 0xd1, 0x1b, 0x18, 0x1a, 0x79, 0xad, 0x7f, 0x27, 0x5a, 0xff, 0x01, 0x07, 0x93, 0xc8, - 0xc8, 0x10, 0x5b, 0xdf, 0xf0, 0x40, 0x94, 0x4f, 0x11, 0x82, 0x7a, 0xdf, 0xc0, 0xfd, 0xf3, 0x41, - 0x0f, 0x13, 0x6c, 0x9d, 0xdb, 0xba, 0xb2, 0x77, 0xf4, 0xdf, 0x22, 0x6c, 0x8b, 0x83, 0x2a, 0x42, - 0x7f, 0x82, 0x5a, 0xee, 0x53, 0xe9, 0xe2, 0x08, 0x3d, 0xfe, 0xe8, 0x47, 0x54, 0x3b, 0xbb, 0xce, - 0xa6, 0xf0, 0x0b, 0x09, 0x1d, 0x43, 0x3d, 0xff, 0x85, 0x71, 0x71, 0x84, 0xf2, 0xfb, 0xfb, 0x86, - 0x8f, 0x8f, 0x0d, 0x3e, 0x5e, 0x83, 0xa2, 0xc7, 0xcc, 0xf5, 0x1d, 0x46, 0xb3, 0x6f, 0x06, 0xd4, - 0xce, 0x79, 0xb9, 0xf5, 0x21, 0xd2, 0xde, 0xdf, 0x68, 0x4b, 0x4f, 0xe6, 0x01, 0x6f, 0xe9, 0xe5, - 0xad, 0xfd, 0x4e, 0x42, 0xeb, 0x9f, 0x0a, 0xed, 0xcf, 0xee, 0x33, 0xa7, 0xde, 0x26, 0xd0, 0xdc, - 0x70, 0x11, 0x47, 0x5f, 0xe4, 0x23, 0xb8, 0xf7, 0x1a, 0xdf, 0x7e, 0xf2, 0x43, 0xb4, 0xd5, 0x2c, - 0x1b, 0x6e, 0xec, 0x6b, 0xb3, 0xdc, 0x7f, 0xdf, 0x5f, 0x9b, 0xe5, 0x63, 0x17, 0xff, 0x77, 0xa0, - 0xdc, 0xbe, 0xe0, 0x21, 0xf5, 0xf6, 0xd8, 0xbb, 0x37, 0xcd, 0xf6, 0xcf, 0x3e, 0xca, 0x49, 0x9d, - 0x1b, 0x00, 0xab, 0x6b, 0x12, 0x7a, 0x94, 0x1b, 0x72, 0xe7, 0x9a, 0xd7, 0x7e, 0x7c, 0x8f, 0x35, - 0x75, 0x65, 0x43, 0x73, 0xc3, 0xbd, 0x69, 0x6d, 0x35, 0xee, 0xbf, 0x57, 0xb5, 0x1f, 0x6c, 0xba, - 0x5e, 0xbc, 0x90, 0x8e, 0xbf, 0xfc, 0xf3, 0xe1, 0x95, 0xcb, 0x66, 0x8b, 0xcb, 0x83, 0x71, 0xe8, - 0x1f, 0x7a, 0xee, 0xd5, 0x8c, 0x05, 0x6e, 0x70, 0x15, 0x50, 0xf6, 0x21, 0x8c, 0xae, 0x0f, 0xbd, - 0x60, 0x72, 0x28, 0x74, 0x79, 0xb8, 0x1c, 0x7e, 0xb9, 0x2d, 0x7e, 0x5e, 0xfa, 0xd5, 0xff, 0x03, - 0x00, 0x00, 0xff, 0xff, 0x40, 0x4b, 0x61, 0x91, 0x8e, 0x12, 0x00, 0x00, + // 2215 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0x4d, 0x77, 0xdb, 0xc6, + 0xd5, 0x0e, 0x48, 0x50, 0x22, 0x2f, 0x3f, 0x04, 0x8d, 0x1c, 0x99, 0x2f, 0x15, 0x27, 0x0c, 0xde, + 0xc4, 0xe6, 0x71, 0x1d, 0xc9, 0x51, 0x7b, 0x5a, 0x9f, 0xb6, 0x49, 0x4b, 0x91, 0x90, 0x05, 0x9b, + 0x02, 0x98, 0x21, 0x25, 0xdb, 0xf5, 0x62, 0x0e, 0x44, 0x0e, 0x45, 0x54, 0xf8, 0x60, 0x81, 0xa1, + 0x1d, 0x2d, 0xbb, 0xeb, 0xe9, 0xb6, 0x8b, 0xfe, 0x84, 0xee, 0xfa, 0x0b, 0xfa, 0x5f, 0xba, 0xed, + 0x2f, 0xe8, 0xba, 0x67, 0x06, 0x03, 0x12, 0x94, 0x28, 0x3b, 0x1b, 0x9b, 0x78, 0xee, 0x33, 0x77, + 0xee, 0x9d, 0xfb, 0xdc, 0xf9, 0x10, 0xec, 0x46, 0xe1, 0x9c, 0xd1, 0x28, 0x9a, 0x8d, 0x0e, 0x92, + 0x5f, 0xfb, 0xb3, 0x28, 0x64, 0x21, 0x2a, 0x2d, 0xf0, 0x46, 0x29, 0x9a, 0x8d, 0x12, 0x54, 0xff, + 0xfb, 0x06, 0xa0, 0x01, 0x0d, 0xc6, 0x7d, 0xe7, 0xda, 0xa7, 0x01, 0xc3, 0xf4, 0x4f, 0x73, 0x1a, + 0x33, 0x84, 0x40, 0x1d, 0xd3, 0x98, 0xd5, 0x95, 0xa6, 0xd2, 0xaa, 0x60, 0xf1, 0x1b, 0x69, 0x90, + 0x77, 0x7c, 0x56, 0xcf, 0x35, 0x95, 0x56, 0x1e, 0xf3, 0x9f, 0xe8, 0xff, 0xa0, 0xe8, 0xf8, 0x8c, + 0xf8, 0xb1, 0xc3, 0xea, 0x15, 0x01, 0x6f, 0x3a, 0x3e, 0x3b, 0x8d, 0x1d, 0x86, 0xbe, 0x84, 0xca, + 0x2c, 0x71, 0x49, 0xa6, 0x4e, 0x3c, 0xad, 0xe7, 0x85, 0xa3, 0xb2, 0xc4, 0x4e, 0x9c, 0x78, 0x8a, + 0x5a, 0xa0, 0x4d, 0xdc, 0xc0, 0xf1, 0xc8, 0xc8, 0x63, 0xef, 0xc8, 0x98, 0x7a, 0xcc, 0xa9, 0xab, + 0x4d, 0xa5, 0x55, 0xc0, 0x35, 0x81, 0x77, 0x3c, 0xf6, 0xae, 0xcb, 0x51, 0xf4, 0x08, 0xb6, 0x52, + 0x67, 0x51, 0x12, 0x60, 0xbd, 0xd0, 0x54, 0x5a, 0x25, 0x5c, 0x9b, 0xad, 0x86, 0xfd, 0x08, 0xb6, + 0x98, 0xeb, 0xd3, 0x70, 0xce, 0x48, 0x4c, 0x47, 0x61, 0x30, 0x8e, 0xeb, 0x1b, 0x89, 0x47, 0x09, + 0x0f, 0x12, 0x14, 0xe9, 0x50, 0x9d, 0x50, 0x4a, 0x3c, 0xd7, 0x77, 0x19, 0xe1, 0xe1, 0x6f, 0x8a, + 0xf0, 0xcb, 0x13, 0x4a, 0x7b, 0x1c, 0x1b, 0x38, 0x0c, 0x7d, 0x05, 0xb5, 0x25, 0x47, 0xe4, 0x58, + 0x15, 0xa4, 0x4a, 0x4a, 0x12, 0x89, 0x3e, 0x01, 0x2d, 0x9c, 0xb3, 0xcb, 0xd0, 0x0d, 0x2e, 0xc9, + 0x68, 0xea, 0x04, 0xc4, 0x1d, 0xd7, 0x8b, 0x4d, 0xa5, 0xa5, 0x1e, 0xe5, 0x9e, 0x2a, 0xb8, 0x96, + 0xda, 0x3a, 0x53, 0x27, 0x30, 0xc7, 0xe8, 0x21, 0x6c, 0x79, 0x4e, 0xcc, 0xc8, 0x34, 0x9c, 0x91, + 0xd9, 0xfc, 0xe2, 0x8a, 0x5e, 0xd7, 0x6b, 0x62, 0x65, 0xaa, 0x1c, 0x3e, 0x09, 0x67, 0x7d, 0x01, + 0xa2, 0x07, 0x00, 0x62, 0x55, 0xc4, 0xe4, 0xf5, 0x92, 0xc8, 0xa1, 0xc4, 0x11, 0x31, 0x31, 0xfa, + 0x16, 0xca, 0xa2, 0x9a, 0x64, 0xea, 0x06, 0x2c, 0xae, 0x43, 0x33, 0xdf, 0x2a, 0x1f, 0x6a, 0xfb, + 0x5e, 0xc0, 0x0b, 0x8b, 0xb9, 0xe5, 0xc4, 0x0d, 0x18, 0x86, 0x28, 0xfd, 0x19, 0xa3, 0x31, 0xec, + 0xf0, 0x2a, 0x92, 0xd1, 0x3c, 0x66, 0xa1, 0x4f, 0x22, 0x3a, 0x0a, 0xa3, 0x71, 0x5c, 0x2f, 0x8b, + 0xa1, 0xbf, 0xd8, 0x5f, 0x88, 0x63, 0xff, 0xb6, 0x1a, 0xf6, 0xbb, 0x34, 0x66, 0x1d, 0x31, 0x0e, + 0x27, 0xc3, 0x8c, 0x80, 0x45, 0xd7, 0x78, 0x7b, 0x7c, 0x13, 0x47, 0x4f, 0x00, 0x39, 0x9e, 0x17, + 0xbe, 0x27, 0x31, 0xf5, 0x26, 0x44, 0x56, 0xa7, 0xbe, 0xd5, 0x54, 0x5a, 0x45, 0xac, 0x09, 0xcb, + 0x80, 0x7a, 0x13, 0xe9, 0x1e, 0xfd, 0x12, 0xaa, 0x22, 0xa6, 0x09, 0x75, 0xd8, 0x3c, 0xa2, 0x71, + 0x5d, 0x6b, 0xe6, 0x5b, 0xb5, 0xc3, 0x6d, 0x99, 0xc8, 0x71, 0x02, 0x1f, 0xb9, 0x0c, 0x57, 0x38, + 0x4f, 0x7e, 0xc7, 0x7c, 0x75, 0x7c, 0xe7, 0x47, 0x12, 0x4f, 0x1d, 0x9e, 0xc2, 0x76, 0x53, 0x69, + 0x55, 0x71, 0xc9, 0x77, 0x7e, 0x1c, 0x08, 0xa0, 0xd1, 0x85, 0xdd, 0xf5, 0x11, 0x73, 0x09, 0xf3, + 0x25, 0xe7, 0xaa, 0x56, 0x31, 0xff, 0x89, 0xee, 0x41, 0xe1, 0x9d, 0xe3, 0xcd, 0xa9, 0x90, 0x75, + 0x05, 0x27, 0x1f, 0xbf, 0xce, 0x3d, 0x53, 0xf4, 0x67, 0xb0, 0x33, 0x8c, 0x9c, 0xd1, 0xd5, 0x8d, + 0xce, 0xb8, 0x29, 0x6c, 0xe5, 0x96, 0xb0, 0xf5, 0xef, 0x61, 0x4b, 0xd4, 0xe0, 0x98, 0xd2, 0x0f, + 0xf5, 0xd3, 0x7d, 0xe0, 0xdd, 0x22, 0xd4, 0x97, 0xf4, 0xd4, 0x86, 0xe3, 0x73, 0xe1, 0xe9, 0x63, + 0xd0, 0x96, 0xe3, 0xe3, 0x59, 0x18, 0xc4, 0x94, 0x37, 0x0b, 0x2f, 0x11, 0x57, 0x19, 0x17, 0xa5, + 0x90, 0xa3, 0x22, 0x46, 0xd5, 0x24, 0x7e, 0x4c, 0xa9, 0x10, 0xe4, 0xc3, 0xa4, 0x07, 0x88, 0x17, + 0x8e, 0xae, 0x78, 0x57, 0x39, 0xd7, 0xd2, 0x7d, 0x95, 0xc3, 0xbd, 0x70, 0x74, 0xd5, 0xe5, 0xa0, + 0xfe, 0x36, 0x69, 0xfc, 0x61, 0x28, 0xe6, 0xfa, 0xe9, 0xe9, 0x21, 0x1d, 0x0a, 0x42, 0x2d, 0xc2, + 0x6d, 0xf9, 0xb0, 0x92, 0x95, 0x1d, 0x4e, 0x4c, 0xfa, 0x5b, 0xd8, 0x59, 0x71, 0x2e, 0xb3, 0x68, + 0x40, 0x71, 0x16, 0x51, 0xd7, 0x77, 0x2e, 0xa9, 0xf4, 0xbc, 0xf8, 0x46, 0x2d, 0xd8, 0x9c, 0x38, + 0xae, 0x37, 0x8f, 0x52, 0xc7, 0xb5, 0x54, 0x06, 0x09, 0x8a, 0x53, 0xb3, 0xfe, 0x19, 0x34, 0x30, + 0x8d, 0x29, 0x3b, 0x75, 0xe3, 0xd8, 0x0d, 0x83, 0x4e, 0x18, 0xb0, 0x28, 0xf4, 0x64, 0x06, 0xfa, + 0x03, 0xd8, 0x5b, 0x6b, 0x4d, 0x42, 0xe0, 0x83, 0x7f, 0x98, 0xd3, 0xe8, 0x7a, 0xfd, 0xe0, 0x1f, + 0x60, 0x6f, 0xad, 0x55, 0xc6, 0xff, 0x04, 0x0a, 0x33, 0xc7, 0x8d, 0xe2, 0x7a, 0x4e, 0xb4, 0xcd, + 0x6e, 0xa6, 0x6d, 0xfa, 0x8e, 0x1b, 0x9d, 0xb8, 0x31, 0x0b, 0xa3, 0x6b, 0x9c, 0x90, 0x5e, 0xa8, + 0x45, 0x45, 0xcb, 0xe9, 0x7f, 0x55, 0xa0, 0x9c, 0x31, 0xa2, 0x3d, 0x28, 0x05, 0xe1, 0x98, 0x92, + 0x49, 0x14, 0xfa, 0xe9, 0x22, 0x70, 0xe0, 0x38, 0x0a, 0x7d, 0xae, 0x09, 0x61, 0x64, 0xa1, 0x14, + 0xe4, 0x06, 0xff, 0x1c, 0x86, 0xe8, 0x1b, 0xd8, 0x9c, 0x26, 0x0e, 0xc4, 0x56, 0x55, 0x3e, 0xdc, + 0xb9, 0x31, 0x77, 0xd7, 0x61, 0x0e, 0x4e, 0x39, 0x2f, 0xd4, 0x62, 0x5e, 0x53, 0x5f, 0xa8, 0x45, + 0x55, 0x2b, 0xbc, 0x50, 0x8b, 0x05, 0x6d, 0xe3, 0x85, 0x5a, 0xdc, 0xd0, 0x36, 0xf5, 0xff, 0x28, + 0x50, 0x4c, 0xd9, 0x3c, 0x12, 0xbe, 0xa4, 0x84, 0xeb, 0x42, 0x8a, 0xa9, 0xc8, 0x81, 0xa1, 0xeb, + 0x53, 0xd4, 0x84, 0x8a, 0x30, 0xae, 0x4a, 0x14, 0x38, 0xd6, 0x16, 0x32, 0x15, 0x7b, 0x68, 0xca, + 0x10, 0x7a, 0x54, 0xe5, 0x1e, 0x9a, 0x50, 0xd2, 0x63, 0x20, 0x9e, 0x8f, 0x46, 0x34, 0x8e, 0x93, + 0x59, 0x0a, 0x09, 0x45, 0x62, 0x62, 0xa2, 0x87, 0xb0, 0x95, 0x52, 0xd2, 0xb9, 0x36, 0x12, 0xbd, + 0x4a, 0x58, 0x4e, 0xd7, 0x02, 0x2d, 0xcb, 0xf3, 0x97, 0xbb, 0x76, 0x6d, 0x49, 0xe4, 0x93, 0x26, + 0xc9, 0xeb, 0x7f, 0x84, 0xfb, 0xa2, 0x94, 0xfd, 0x28, 0xbc, 0x70, 0x2e, 0x5c, 0xcf, 0x65, 0xd7, + 0xa9, 0xc8, 0x79, 0xe2, 0x51, 0xe8, 0x13, 0xbe, 0xb6, 0x69, 0x09, 0x38, 0x60, 0x85, 0x63, 0xca, + 0x4b, 0xc0, 0xc2, 0xc4, 0x24, 0x4b, 0xc0, 0x42, 0x61, 0xc8, 0x9e, 0x76, 0xf9, 0x95, 0xd3, 0x4e, + 0xbf, 0x82, 0xfa, 0xed, 0xb9, 0xa4, 0x66, 0x9a, 0x50, 0x9e, 0x2d, 0x61, 0x31, 0x9d, 0x82, 0xb3, + 0x50, 0xb6, 0xb6, 0xb9, 0x8f, 0xd7, 0x56, 0xff, 0x87, 0x02, 0xdb, 0x47, 0x73, 0xd7, 0x1b, 0xaf, + 0x34, 0x6e, 0x36, 0x3a, 0x65, 0xf5, 0x2c, 0x5e, 0x77, 0xd0, 0xe6, 0xd6, 0x1e, 0xb4, 0xeb, 0x0e, + 0xb3, 0xfc, 0x9d, 0x87, 0xd9, 0x17, 0x50, 0x5e, 0x9e, 0x63, 0x71, 0x5d, 0x6d, 0xe6, 0x5b, 0x15, + 0x0c, 0xd3, 0xf4, 0x10, 0x8b, 0xf5, 0x67, 0x80, 0xb2, 0x81, 0xca, 0x05, 0x59, 0xec, 0x1f, 0xca, + 0xdd, 0xfb, 0xc7, 0x67, 0xd0, 0x18, 0xcc, 0x2f, 0xe2, 0x51, 0xe4, 0x5e, 0xd0, 0x13, 0xe6, 0x8d, + 0x8c, 0x77, 0x34, 0x60, 0x71, 0xda, 0xa5, 0xff, 0x55, 0xa1, 0xb4, 0x40, 0xd1, 0x3e, 0xec, 0xb8, + 0xc1, 0x28, 0xf4, 0xd3, 0xa0, 0x03, 0xea, 0xf1, 0xb8, 0x93, 0x4d, 0x7e, 0x3b, 0x35, 0x75, 0x12, + 0x8b, 0x39, 0xe6, 0xfc, 0x95, 0x24, 0x25, 0x3f, 0x97, 0xf0, 0xb3, 0x39, 0x26, 0xfc, 0x16, 0x68, + 0x0b, 0xff, 0x53, 0xe6, 0x8d, 0x16, 0x8b, 0x82, 0x6b, 0x29, 0xce, 0x83, 0x49, 0x98, 0x0b, 0xcf, + 0x29, 0x53, 0x4d, 0x98, 0x29, 0x2e, 0x99, 0x5f, 0x42, 0x85, 0xf7, 0x43, 0xcc, 0x1c, 0x7f, 0x46, + 0x82, 0x58, 0xf4, 0x85, 0x8a, 0xcb, 0x0b, 0xcc, 0x8a, 0xd1, 0x77, 0x00, 0x94, 0xe7, 0x47, 0xd8, + 0xf5, 0x8c, 0x8a, 0x96, 0xa8, 0x1d, 0x7e, 0x9e, 0x11, 0xc6, 0x62, 0x01, 0xf6, 0xc5, 0xbf, 0xc3, + 0xeb, 0x19, 0xc5, 0x25, 0x9a, 0xfe, 0x44, 0xdf, 0x43, 0x75, 0x12, 0x46, 0xef, 0x9d, 0x68, 0x4c, + 0x04, 0x28, 0xb7, 0x8d, 0xfb, 0x19, 0x0f, 0xc7, 0x89, 0x5d, 0x0c, 0x3f, 0xf9, 0x04, 0x57, 0x26, + 0x99, 0x6f, 0xf4, 0x12, 0x50, 0x3a, 0x5e, 0x74, 0x79, 0xe2, 0xa4, 0x28, 0x9c, 0xec, 0xdd, 0x76, + 0xc2, 0x37, 0xe9, 0xd4, 0x91, 0x36, 0xb9, 0x81, 0xa1, 0xdf, 0x40, 0x25, 0xa6, 0x8c, 0x79, 0x54, + 0xba, 0x29, 0x09, 0x37, 0xbb, 0x2b, 0xb7, 0x0e, 0x6e, 0x4e, 0x3d, 0x94, 0xe3, 0xe5, 0x27, 0x3a, + 0x82, 0x2d, 0xcf, 0x0d, 0xae, 0xb2, 0x61, 0x80, 0x18, 0x5f, 0xcf, 0x8c, 0xef, 0xb9, 0xc1, 0x55, + 0x36, 0x86, 0xaa, 0x97, 0x05, 0xf4, 0xdf, 0x42, 0x69, 0xb1, 0x4a, 0xa8, 0x0c, 0x9b, 0x67, 0xd6, + 0x4b, 0xcb, 0x7e, 0x65, 0x69, 0x9f, 0xa0, 0x22, 0xa8, 0x03, 0xc3, 0xea, 0x6a, 0x0a, 0x87, 0xb1, + 0xd1, 0x31, 0xcc, 0x73, 0x43, 0xcb, 0xf1, 0x8f, 0x63, 0x1b, 0xbf, 0x6a, 0xe3, 0xae, 0x96, 0x3f, + 0xda, 0x84, 0x82, 0x98, 0x57, 0xff, 0x97, 0x02, 0x45, 0x51, 0xc1, 0x60, 0x12, 0xa2, 0x9f, 0xc1, + 0x42, 0x5c, 0x62, 0x73, 0xe3, 0x07, 0xae, 0x50, 0x5d, 0x15, 0x2f, 0x04, 0x33, 0x94, 0x38, 0x27, + 0x2f, 0xa4, 0xb1, 0x20, 0xe7, 0x12, 0x72, 0x6a, 0x58, 0x90, 0x1f, 0x67, 0x3c, 0xaf, 0x6c, 0x39, + 0x2a, 0xde, 0x4a, 0x0d, 0xe9, 0x0e, 0xfb, 0x38, 0xe3, 0x78, 0x65, 0x27, 0x56, 0xf1, 0x56, 0x6a, + 0x90, 0x5c, 0xfd, 0x57, 0x50, 0xc9, 0xd6, 0x1c, 0x3d, 0x02, 0xd5, 0x0d, 0x26, 0xa1, 0x6c, 0xc4, + 0x9d, 0x1b, 0xe2, 0xe2, 0x49, 0x62, 0x41, 0xd0, 0x11, 0x68, 0x37, 0xeb, 0xac, 0x57, 0xa1, 0x9c, + 0x29, 0x9a, 0xfe, 0x6f, 0x05, 0xaa, 0x2b, 0x45, 0xf8, 0xc9, 0xde, 0xd1, 0x77, 0x50, 0x79, 0xef, + 0x46, 0x94, 0x64, 0x8f, 0xff, 0xda, 0x61, 0x63, 0xf5, 0xf8, 0x4f, 0xff, 0xef, 0x84, 0x63, 0x8a, + 0xcb, 0x9c, 0x2f, 0x01, 0xf4, 0x3b, 0xa8, 0xc9, 0x91, 0x64, 0x4c, 0x99, 0xe3, 0x7a, 0x62, 0xa9, + 0x6a, 0x2b, 0xf2, 0x90, 0xdc, 0xae, 0xb0, 0xe3, 0xea, 0x24, 0xfb, 0x89, 0xbe, 0x5e, 0x3a, 0x88, + 0x59, 0xe4, 0x06, 0x97, 0x62, 0xfd, 0x4a, 0x0b, 0xda, 0x40, 0x80, 0xfc, 0x20, 0xaf, 0xca, 0xcb, + 0xe0, 0x80, 0x39, 0x6c, 0x1e, 0xa3, 0x6f, 0xa0, 0x10, 0x33, 0x47, 0xee, 0x64, 0xb5, 0x95, 0xde, + 0xca, 0x10, 0x29, 0x4e, 0x58, 0x2b, 0xb7, 0x9f, 0xdc, 0xad, 0xdb, 0x4f, 0x81, 0xef, 0x18, 0xc9, + 0x2e, 0x5a, 0x3e, 0x44, 0x32, 0xf9, 0x93, 0x61, 0xaf, 0xd3, 0x66, 0x8c, 0xfa, 0x33, 0x86, 0x13, + 0x42, 0x72, 0xba, 0x3d, 0xfe, 0xb3, 0x0a, 0xd5, 0x95, 0xa4, 0x56, 0x55, 0x5d, 0x85, 0x92, 0x65, + 0x93, 0xae, 0x31, 0x6c, 0x9b, 0x3d, 0x4d, 0x41, 0x1a, 0x54, 0x6c, 0xcb, 0xb4, 0x2d, 0xd2, 0x35, + 0x3a, 0x76, 0x97, 0xeb, 0xfb, 0x53, 0xd8, 0xee, 0x99, 0xd6, 0x4b, 0x62, 0xd9, 0x43, 0x62, 0xf4, + 0xcc, 0xe7, 0xe6, 0x51, 0xcf, 0xd0, 0xf2, 0xe8, 0x1e, 0x68, 0xb6, 0x45, 0x3a, 0x27, 0x6d, 0xd3, + 0x22, 0x43, 0xf3, 0xd4, 0xb0, 0xcf, 0x86, 0x9a, 0xca, 0x51, 0x1e, 0x08, 0x31, 0x5e, 0x77, 0x0c, + 0xa3, 0x3b, 0x20, 0xa7, 0xed, 0xd7, 0x5a, 0x01, 0xd5, 0xe1, 0x9e, 0x69, 0x0d, 0xce, 0x8e, 0x8f, + 0xcd, 0x8e, 0x69, 0x58, 0x43, 0x72, 0xd4, 0xee, 0xb5, 0xad, 0x8e, 0xa1, 0x6d, 0xa0, 0x5d, 0x40, + 0xa6, 0xd5, 0xb1, 0x4f, 0xfb, 0x3d, 0x63, 0x68, 0x90, 0xb4, 0x8f, 0x36, 0xd1, 0x0e, 0x6c, 0x09, + 0x3f, 0xed, 0x6e, 0x97, 0x1c, 0xb7, 0xcd, 0x9e, 0xd1, 0xd5, 0x8a, 0x3c, 0x12, 0xc9, 0x18, 0x90, + 0xae, 0x39, 0x68, 0x1f, 0x71, 0xb8, 0xc4, 0xe7, 0x34, 0xad, 0x73, 0xdb, 0xec, 0x18, 0xa4, 0xc3, + 0xdd, 0x72, 0x14, 0x38, 0x39, 0x45, 0xcf, 0xac, 0xae, 0x81, 0xfb, 0x6d, 0xb3, 0xab, 0x95, 0xd1, + 0x1e, 0xdc, 0x4f, 0x61, 0xe3, 0x75, 0xdf, 0xc4, 0x6f, 0xc8, 0xd0, 0xb6, 0xc9, 0xc0, 0xb6, 0x2d, + 0xad, 0x92, 0xf5, 0xc4, 0xb3, 0xb5, 0xfb, 0x86, 0xa5, 0x55, 0xd1, 0x7d, 0xd8, 0x39, 0xed, 0xf7, + 0x49, 0x6a, 0x49, 0x93, 0xad, 0x71, 0x7a, 0xbb, 0xdb, 0xc5, 0xc6, 0x60, 0x40, 0x4e, 0xcd, 0xc1, + 0x69, 0x7b, 0xd8, 0x39, 0xd1, 0xb6, 0x78, 0x4a, 0x03, 0x63, 0x48, 0x86, 0xf6, 0xb0, 0xdd, 0x5b, + 0xe2, 0x1a, 0x0f, 0x68, 0x89, 0xf3, 0x49, 0x7b, 0xf6, 0x2b, 0x6d, 0x9b, 0x2f, 0x38, 0x87, 0xed, + 0x73, 0x19, 0x22, 0xe2, 0xb9, 0xcb, 0xf2, 0xa4, 0x73, 0x6a, 0x3b, 0x1c, 0x34, 0xad, 0xf3, 0x76, + 0xcf, 0xec, 0x92, 0x97, 0xc6, 0x1b, 0xb1, 0x0f, 0xdd, 0xe3, 0x60, 0x12, 0x19, 0xe9, 0x63, 0xfb, + 0x39, 0x0f, 0x44, 0xfb, 0x14, 0x21, 0xa8, 0x75, 0x4c, 0xdc, 0x39, 0xeb, 0xb5, 0x31, 0xc1, 0xf6, + 0xd9, 0xd0, 0xd0, 0x76, 0x1f, 0xff, 0x53, 0x81, 0x4a, 0x56, 0x67, 0xbc, 0xea, 0xa6, 0x45, 0x8e, + 0x7b, 0xe6, 0xf3, 0x93, 0x61, 0x22, 0x82, 0xc1, 0x59, 0x87, 0x97, 0xcc, 0xe0, 0xfb, 0x1b, 0x82, + 0x5a, 0xb2, 0xe8, 0x8b, 0x64, 0x73, 0x7c, 0x2e, 0x89, 0x59, 0xb6, 0xf4, 0x9b, 0xe7, 0xc1, 0x4b, + 0xd0, 0xc0, 0xd8, 0xc6, 0x9a, 0x8a, 0xbe, 0x82, 0xa6, 0x44, 0x78, 0x5d, 0x31, 0x36, 0x3a, 0x43, + 0xd2, 0x6f, 0xbf, 0x39, 0xe5, 0x65, 0x4f, 0x44, 0x36, 0xd0, 0x0a, 0xe8, 0x0b, 0xd8, 0x5b, 0xb0, + 0xd6, 0xe9, 0xe2, 0xf0, 0x6f, 0x9b, 0xb0, 0x21, 0x8e, 0xf9, 0x08, 0xfd, 0x1e, 0xaa, 0x99, 0x87, + 0xe6, 0xf9, 0x21, 0x7a, 0xf0, 0xc1, 0x27, 0x68, 0x23, 0x7d, 0x0c, 0x48, 0xf8, 0xa9, 0x82, 0x8e, + 0xa0, 0x96, 0x7d, 0x9f, 0x9d, 0x1f, 0xa2, 0xec, 0xe9, 0xb8, 0xe6, 0xe9, 0xb6, 0xc6, 0xc7, 0x4b, + 0xd0, 0x8c, 0x98, 0xb9, 0x3e, 0x6f, 0x52, 0xf9, 0xe2, 0x42, 0x8d, 0x8c, 0x97, 0x1b, 0xcf, 0xb8, + 0xc6, 0xde, 0x5a, 0x9b, 0xbc, 0xd7, 0xf4, 0xf8, 0x86, 0xb8, 0x78, 0xf3, 0xdc, 0x4a, 0x68, 0xf5, + 0xa1, 0xd5, 0xf8, 0xfc, 0x2e, 0xb3, 0xf4, 0x36, 0x86, 0x9d, 0x35, 0xcf, 0x18, 0xf4, 0x75, 0x36, + 0x82, 0x3b, 0x1f, 0x41, 0x8d, 0x87, 0x1f, 0xa3, 0x2d, 0x67, 0x59, 0xf3, 0xde, 0x59, 0x99, 0xe5, + 0xee, 0xd7, 0xd2, 0xca, 0x2c, 0x1f, 0x7a, 0x36, 0xbd, 0x05, 0xed, 0xe6, 0xf5, 0x18, 0xe9, 0x37, + 0xc7, 0xde, 0xbe, 0xa7, 0x37, 0xfe, 0xff, 0x83, 0x1c, 0xe9, 0xdc, 0x04, 0x58, 0x5e, 0x32, 0xd1, + 0x67, 0x99, 0x21, 0xb7, 0x2e, 0xc9, 0x8d, 0x07, 0x77, 0x58, 0xa5, 0xab, 0x21, 0xec, 0xac, 0xb9, + 0x75, 0xae, 0xac, 0xc6, 0xdd, 0xb7, 0xd2, 0xc6, 0xbd, 0x75, 0x97, 0xb3, 0xa7, 0x0a, 0x3a, 0x4d, + 0x74, 0x91, 0xfe, 0xd1, 0xe3, 0x23, 0x42, 0xaf, 0xaf, 0x3f, 0x44, 0xe6, 0xb1, 0x9e, 0xff, 0x4b, + 0x4e, 0x79, 0xaa, 0x20, 0x1b, 0x2a, 0x59, 0x71, 0x7f, 0x54, 0xf5, 0x1f, 0x73, 0x78, 0xf4, 0xed, + 0x1f, 0x0e, 0x2e, 0x5d, 0x36, 0x9d, 0x5f, 0xec, 0x8f, 0x42, 0xff, 0xc0, 0x73, 0x2f, 0xa7, 0x2c, + 0x70, 0x83, 0xcb, 0x80, 0xb2, 0xf7, 0x61, 0x74, 0x75, 0xe0, 0x05, 0xe3, 0x03, 0xd1, 0x37, 0x07, + 0x0b, 0x3f, 0x17, 0x1b, 0xe2, 0x8f, 0x87, 0x3f, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x09, + 0xc8, 0xdd, 0x00, 0x6c, 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1788,6 +1917,15 @@ type RouterClient interface { //SubscribeHtlcEvents creates a uni-directional stream from the server to //the client which delivers a stream of htlc events. SubscribeHtlcEvents(ctx context.Context, in *SubscribeHtlcEventsRequest, opts ...grpc.CallOption) (Router_SubscribeHtlcEventsClient, error) + //* + //Deprecated, use SendPaymentV2. SendPayment attempts to route a payment + //described by the passed PaymentRequest to the final destination. The call + //returns a stream of payment status updates. + SendPayment(ctx context.Context, in *SendPaymentRequest, opts ...grpc.CallOption) (Router_SendPaymentClient, error) + //* + //Deprecated, use TrackPaymentV2. TrackPayment returns an update stream for + //the payment identified by the payment hash. + TrackPayment(ctx context.Context, in *TrackPaymentRequest, opts ...grpc.CallOption) (Router_TrackPaymentClient, error) } type routerClient struct { @@ -1948,6 +2086,72 @@ func (x *routerSubscribeHtlcEventsClient) Recv() (*HtlcEvent, error) { return m, nil } +// Deprecated: Do not use. +func (c *routerClient) SendPayment(ctx context.Context, in *SendPaymentRequest, opts ...grpc.CallOption) (Router_SendPaymentClient, error) { + stream, err := c.cc.NewStream(ctx, &_Router_serviceDesc.Streams[3], "/routerrpc.Router/SendPayment", opts...) + if err != nil { + return nil, err + } + x := &routerSendPaymentClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Router_SendPaymentClient interface { + Recv() (*PaymentStatus, error) + grpc.ClientStream +} + +type routerSendPaymentClient struct { + grpc.ClientStream +} + +func (x *routerSendPaymentClient) Recv() (*PaymentStatus, error) { + m := new(PaymentStatus) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Deprecated: Do not use. +func (c *routerClient) TrackPayment(ctx context.Context, in *TrackPaymentRequest, opts ...grpc.CallOption) (Router_TrackPaymentClient, error) { + stream, err := c.cc.NewStream(ctx, &_Router_serviceDesc.Streams[4], "/routerrpc.Router/TrackPayment", opts...) + if err != nil { + return nil, err + } + x := &routerTrackPaymentClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Router_TrackPaymentClient interface { + Recv() (*PaymentStatus, error) + grpc.ClientStream +} + +type routerTrackPaymentClient struct { + grpc.ClientStream +} + +func (x *routerTrackPaymentClient) Recv() (*PaymentStatus, error) { + m := new(PaymentStatus) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // RouterServer is the server API for Router service. type RouterServer interface { //* @@ -1989,6 +2193,15 @@ type RouterServer interface { //SubscribeHtlcEvents creates a uni-directional stream from the server to //the client which delivers a stream of htlc events. SubscribeHtlcEvents(*SubscribeHtlcEventsRequest, Router_SubscribeHtlcEventsServer) error + //* + //Deprecated, use SendPaymentV2. SendPayment attempts to route a payment + //described by the passed PaymentRequest to the final destination. The call + //returns a stream of payment status updates. + SendPayment(*SendPaymentRequest, Router_SendPaymentServer) error + //* + //Deprecated, use TrackPaymentV2. TrackPayment returns an update stream for + //the payment identified by the payment hash. + TrackPayment(*TrackPaymentRequest, Router_TrackPaymentServer) error } func RegisterRouterServer(s *grpc.Server, srv RouterServer) { @@ -2166,6 +2379,48 @@ func (x *routerSubscribeHtlcEventsServer) Send(m *HtlcEvent) error { return x.ServerStream.SendMsg(m) } +func _Router_SendPayment_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SendPaymentRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(RouterServer).SendPayment(m, &routerSendPaymentServer{stream}) +} + +type Router_SendPaymentServer interface { + Send(*PaymentStatus) error + grpc.ServerStream +} + +type routerSendPaymentServer struct { + grpc.ServerStream +} + +func (x *routerSendPaymentServer) Send(m *PaymentStatus) error { + return x.ServerStream.SendMsg(m) +} + +func _Router_TrackPayment_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(TrackPaymentRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(RouterServer).TrackPayment(m, &routerTrackPaymentServer{stream}) +} + +type Router_TrackPaymentServer interface { + Send(*PaymentStatus) error + grpc.ServerStream +} + +type routerTrackPaymentServer struct { + grpc.ServerStream +} + +func (x *routerTrackPaymentServer) Send(m *PaymentStatus) error { + return x.ServerStream.SendMsg(m) +} + var _Router_serviceDesc = grpc.ServiceDesc{ ServiceName: "routerrpc.Router", HandlerType: (*RouterServer)(nil), @@ -2211,6 +2466,16 @@ var _Router_serviceDesc = grpc.ServiceDesc{ Handler: _Router_SubscribeHtlcEvents_Handler, ServerStreams: true, }, + { + StreamName: "SendPayment", + Handler: _Router_SendPayment_Handler, + ServerStreams: true, + }, + { + StreamName: "TrackPayment", + Handler: _Router_TrackPayment_Handler, + ServerStreams: true, + }, }, Metadata: "routerrpc/router.proto", } diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 62980527b3..d0a33cc7b8 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -411,6 +411,62 @@ enum FailureDetail { CIRCULAR_ROUTE = 22; } +enum PaymentState { + /** + Payment is still in flight. + */ + IN_FLIGHT = 0; + + /** + Payment completed successfully. + */ + SUCCEEDED = 1; + + /** + There are more routes to try, but the payment timeout was exceeded. + */ + FAILED_TIMEOUT = 2; + + /** + All possible routes were tried and failed permanently. Or were no + routes to the destination at all. + */ + FAILED_NO_ROUTE = 3; + + /** + A non-recoverable error has occured. + */ + FAILED_ERROR = 4; + + /** + Payment details incorrect (unknown hash, invalid amt or + invalid final cltv delta) + */ + FAILED_INCORRECT_PAYMENT_DETAILS = 5; + + /** + Insufficient local balance. + */ + FAILED_INSUFFICIENT_BALANCE = 6; +} + +message PaymentStatus { + /// Current state the payment is in. + PaymentState state = 1; + + /** + The pre-image of the payment when state is SUCCEEDED. + */ + bytes preimage = 2; + + reserved 3; + + /** + The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. + */ + repeated lnrpc.HTLCAttempt htlcs = 4; +} + service Router { /** SendPaymentV2 attempts to route a payment described by the passed @@ -472,4 +528,21 @@ service Router { */ rpc SubscribeHtlcEvents (SubscribeHtlcEventsRequest) returns (stream HtlcEvent); + + /** + Deprecated, use SendPaymentV2. SendPayment attempts to route a payment + described by the passed PaymentRequest to the final destination. The call + returns a stream of payment status updates. + */ + rpc SendPayment(SendPaymentRequest) returns (stream PaymentStatus) { + option deprecated = true; + } + + /** + Deprecated, use TrackPaymentV2. TrackPayment returns an update stream for + the payment identified by the payment hash. + */ + rpc TrackPayment(TrackPaymentRequest) returns (stream PaymentStatus) { + option deprecated = true; + } } diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index b380174511..5a98f21234 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -84,6 +84,14 @@ var ( Entity: "offchain", Action: "read", }}, + "/routerrpc.Router/SendPayment": {{ + Entity: "offchain", + Action: "write", + }}, + "/routerrpc.Router/TrackPayment": {{ + Entity: "offchain", + Action: "read", + }}, } // DefaultRouterMacFilename is the default name of the router macaroon diff --git a/lnrpc/routerrpc/router_server_deprecated.go b/lnrpc/routerrpc/router_server_deprecated.go new file mode 100644 index 0000000000..199ec841ca --- /dev/null +++ b/lnrpc/routerrpc/router_server_deprecated.go @@ -0,0 +1,95 @@ +package routerrpc + +import ( + "encoding/hex" + "errors" + "fmt" + + "github.com/lightningnetwork/lnd/lnrpc" +) + +// legacyTrackPaymentServer is a wrapper struct that transforms a stream of main +// rpc payment structs into the legacy PaymentStatus format. +type legacyTrackPaymentServer struct { + Router_TrackPaymentServer +} + +// Send converts a Payment object and sends it as a PaymentStatus object on the +// embedded stream. +func (i *legacyTrackPaymentServer) Send(p *lnrpc.Payment) error { + var state PaymentState + switch p.Status { + case lnrpc.Payment_IN_FLIGHT: + state = PaymentState_IN_FLIGHT + case lnrpc.Payment_SUCCEEDED: + state = PaymentState_SUCCEEDED + case lnrpc.Payment_FAILED: + switch p.FailureReason { + case lnrpc.PaymentFailureReason_FAILURE_REASON_NONE: + return fmt.Errorf("expected fail reason") + + case lnrpc.PaymentFailureReason_FAILURE_REASON_TIMEOUT: + state = PaymentState_FAILED_TIMEOUT + + case lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE: + state = PaymentState_FAILED_NO_ROUTE + + case lnrpc.PaymentFailureReason_FAILURE_REASON_ERROR: + state = PaymentState_FAILED_ERROR + + case lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS: + state = PaymentState_FAILED_INCORRECT_PAYMENT_DETAILS + + case lnrpc.PaymentFailureReason_FAILURE_REASON_INSUFFICIENT_BALANCE: + state = PaymentState_FAILED_INSUFFICIENT_BALANCE + + default: + return fmt.Errorf("unknown failure reason %v", + p.FailureReason) + } + default: + return fmt.Errorf("unknown state %v", p.Status) + } + + preimage, err := hex.DecodeString(p.PaymentPreimage) + if err != nil { + return err + } + + legacyState := PaymentStatus{ + State: state, + Preimage: preimage, + Htlcs: p.Htlcs, + } + + return i.Router_TrackPaymentServer.Send(&legacyState) +} + +// TrackPayment returns a stream of payment state updates. The stream is +// closed when the payment completes. +func (s *Server) TrackPayment(request *TrackPaymentRequest, + stream Router_TrackPaymentServer) error { + + legacyStream := legacyTrackPaymentServer{ + Router_TrackPaymentServer: stream, + } + return s.TrackPaymentV2(request, &legacyStream) +} + +// SendPayment attempts to route a payment described by the passed +// PaymentRequest to the final destination. If we are unable to route the +// payment, or cannot find a route that satisfies the constraints in the +// PaymentRequest, then an error will be returned. Otherwise, the payment +// pre-image, along with the final route will be returned. +func (s *Server) SendPayment(request *SendPaymentRequest, + stream Router_SendPaymentServer) error { + + if request.MaxShards > 1 { + return errors.New("for multi-part payments, use SendPaymentV2") + } + + legacyStream := legacyTrackPaymentServer{ + Router_TrackPaymentServer: stream, + } + return s.SendPaymentV2(request, &legacyStream) +} From 89bd58786ecb7fe6fcd5bd9ac5767a797cc09ed7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 20 Apr 2020 23:37:34 -0700 Subject: [PATCH 511/562] lnwallet/channel: enforce absolute fee floor of 250 sat/kw This enforces the _actualized_ fee rate of the commitment transaction, rather than the fee floor used for estimation. The new value of 250 sat/kw corresponds to 1 sat/byte, rather than 253 which is only rounded up during estimation to account for the fact that BOLT 3 rounds down to the nearest satoshi and that the vbyte fee estimation is lossy. Previously we would incorrectly fail to sign the next commitment even though the fee was technically high enough. Restarting with this commit should solve the issue as long as the channel hasn't already gone to chain. --- lnwallet/chainfee/rates.go | 7 ++++++- lnwallet/channel.go | 2 +- lnwallet/channel_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lnwallet/chainfee/rates.go b/lnwallet/chainfee/rates.go index 48c3d7dfe6..69c458a4a0 100644 --- a/lnwallet/chainfee/rates.go +++ b/lnwallet/chainfee/rates.go @@ -9,8 +9,13 @@ import ( const ( // FeePerKwFloor is the lowest fee rate in sat/kw that we should use for - // determining transaction fees. + // estimating transaction fees before signing. FeePerKwFloor SatPerKWeight = 253 + + // AbsoluteFeePerKwFloor is the lowest fee rate in sat/kw of a + // transaction that we should ever _create_. This is the the equivalent + // of 1 sat/byte in sat/kw. + AbsoluteFeePerKwFloor SatPerKWeight = 250 ) // SatPerKVByte represents a fee rate in sat/kb. diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 4cf75c0a20..600820f2cb 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2412,7 +2412,7 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool, effFeeRate := chainfee.SatPerKWeight(fee) * 1000 / chainfee.SatPerKWeight(weight) - if effFeeRate < chainfee.FeePerKwFloor { + if effFeeRate < chainfee.AbsoluteFeePerKwFloor { return nil, fmt.Errorf("height=%v, for ChannelPoint(%v) "+ "attempts to create commitment with feerate %v: %v", nextHeight, lc.channelState.FundingOutpoint, diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 318c0b9607..9f10be1603 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -7638,3 +7638,41 @@ func TestChannelMaxFeeRate(t *testing.T) { assertMaxFeeRate(0.000001, 690) assertMaxFeeRate(0.0000001, chainfee.FeePerKwFloor) } + +// TestChannelFeeRateFloor asserts that valid commitments can be proposed and +// received using chainfee.FeePerKwFloor as the initiator's fee rate. +func TestChannelFeeRateFloor(t *testing.T) { + t.Parallel() + + alice, bob, cleanUp, err := CreateTestChannels( + channeldb.SingleFunderTweaklessBit, + ) + if err != nil { + t.Fatalf("unable to create test channels: %v", err) + } + defer cleanUp() + + // Set the fee rate to the proposing fee rate floor. + minFee := chainfee.FeePerKwFloor + + // Alice is the initiator, so only she can propose fee updates. + if err := alice.UpdateFee(minFee); err != nil { + t.Fatalf("unable to send fee update") + } + if err := bob.ReceiveUpdateFee(minFee); err != nil { + t.Fatalf("unable to receive fee update") + } + + // Check that alice can still sign commitments. + sig, htlcSigs, _, err := alice.SignNextCommitment() + if err != nil { + t.Fatalf("alice unable to sign commitment: %v", err) + } + + // Check that bob can still receive commitments. + err = bob.ReceiveNewCommitment(sig, htlcSigs) + if err != nil { + t.Fatalf("bob unable to process alice's new commitment: %v", + err) + } +} From 1e51ec0a2db723e4d94a20743d2b2942b3dbacdc Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 21 Apr 2020 16:42:52 -0700 Subject: [PATCH 512/562] lnrpc/invoicesrpc: clamp down on max invoice size In this commit, we move to clamp down somewhat on the max invoice size after the limit was removed as part of the mpp changes. In #4210, it was reported that a value of -1, would underflow and end up as 18 million BTC, which would trip checks w.r.t the max expressible value in mSAT. In this commit, we clamp things down to 100k BTC, which should be more than enough for anybody. Fixes #4210. --- lnrpc/invoicesrpc/addinvoice.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index 24463ccbe4..c027208a6c 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -156,10 +156,22 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, len(invoice.DescriptionHash)) } + // We set the max invoice amount to 100k BTC, which itself is several + // multiples off the current block reward. + maxInvoiceAmt := btcutil.Amount(btcutil.SatoshiPerBitcoin * 100000) + + switch { // The value of the invoice must not be negative. - if invoice.Value < 0 { + case invoice.Value < 0: return nil, nil, fmt.Errorf("payments of negative value "+ "are not allowed, value is %v", invoice.Value) + + // Also ensure that the invoice is actually realistic, while preventing + // any issues due to underflow. + case invoice.Value.ToSatoshis() > maxInvoiceAmt: + return nil, nil, fmt.Errorf("invoice amount %v is "+ + "too large, max is %v", invoice.Value.ToSatoshis(), + maxInvoiceAmt) } amtMSat := invoice.Value From d51bb65536b5f2509014667d731a7db5efa6f6b3 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 20 Apr 2020 08:06:35 +0200 Subject: [PATCH 513/562] routerrpc+lncli: add flag to suppress in-flight updates This is a preparation for enabling the REST interface on routerrpc. It provides REST clients that don't support server-side streaming via keep-alive connections to use the streaming endpoint in the typical request/response pattern. The url just needs to contain ?no_inflight_updates=true and only the terminal response is sent back before the connection is closed. --- cmd/lncli/cmd_pay.go | 10 +- lnrpc/routerrpc/router.pb.go | 306 +++++++++++++++++-------------- lnrpc/routerrpc/router.proto | 12 ++ lnrpc/routerrpc/router_server.go | 14 +- 4 files changed, 191 insertions(+), 151 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 26e3c9efed..11abacbfa1 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -397,7 +397,7 @@ func sendPaymentRequest(ctx *cli.Context, req.FeeLimitSat = feeLimit - showInflight := ctx.Bool(showInflightFlag.Name) + req.NoInflightUpdates = !ctx.Bool(showInflightFlag.Name) stream, err := routerClient.SendPaymentV2(context.Background(), req) if err != nil { @@ -410,9 +410,9 @@ func sendPaymentRequest(ctx *cli.Context, return err } - if status.Status != lnrpc.Payment_IN_FLIGHT { - printRespJSON(status) + printRespJSON(status) + if status.Status != lnrpc.Payment_IN_FLIGHT { // If we get a payment error back, we pass an error up // to main which eventually calls fatal() and returns // with a non-zero exit code. @@ -422,10 +422,6 @@ func sendPaymentRequest(ctx *cli.Context, return nil } - - if showInflight { - printRespJSON(status) - } } } diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 4f6dd0fc4e..2b2ed2d846 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -281,7 +281,11 @@ type SendPaymentRequest struct { //* //The maximum number of partial payments that may be use to complete the full //amount. - MaxShards uint32 `protobuf:"varint,17,opt,name=max_shards,json=maxShards,proto3" json:"max_shards,omitempty"` + MaxShards uint32 `protobuf:"varint,17,opt,name=max_shards,json=maxShards,proto3" json:"max_shards,omitempty"` + //* + //If set, only the final payment update is streamed back. Intermediate updates + //that show which htlcs are still in flight are suppressed. + NoInflightUpdates bool `protobuf:"varint,18,opt,name=no_inflight_updates,json=noInflightUpdates,proto3" json:"no_inflight_updates,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -431,9 +435,20 @@ func (m *SendPaymentRequest) GetMaxShards() uint32 { return 0 } +func (m *SendPaymentRequest) GetNoInflightUpdates() bool { + if m != nil { + return m.NoInflightUpdates + } + return false +} + type TrackPaymentRequest struct { /// The hash of the payment to look up. - PaymentHash []byte `protobuf:"bytes,1,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"` + PaymentHash []byte `protobuf:"bytes,1,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"` + //* + //If set, only the final payment update is streamed back. Intermediate updates + //that show which htlcs are still in flight are suppressed. + NoInflightUpdates bool `protobuf:"varint,2,opt,name=no_inflight_updates,json=noInflightUpdates,proto3" json:"no_inflight_updates,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -471,6 +486,13 @@ func (m *TrackPaymentRequest) GetPaymentHash() []byte { return nil } +func (m *TrackPaymentRequest) GetNoInflightUpdates() bool { + if m != nil { + return m.NoInflightUpdates + } + return false +} + type RouteFeeRequest struct { //* //The destination once wishes to obtain a routing fee quote to. @@ -1724,146 +1746,148 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2215 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0x4d, 0x77, 0xdb, 0xc6, - 0xd5, 0x0e, 0x48, 0x50, 0x22, 0x2f, 0x3f, 0x04, 0x8d, 0x1c, 0x99, 0x2f, 0x15, 0x27, 0x0c, 0xde, - 0xc4, 0xe6, 0x71, 0x1d, 0xc9, 0x51, 0x7b, 0x5a, 0x9f, 0xb6, 0x49, 0x4b, 0x91, 0x90, 0x05, 0x9b, + // 2247 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0x4d, 0x77, 0xdb, 0xc6, + 0xd5, 0x0e, 0x48, 0x50, 0x22, 0x2f, 0x3f, 0x04, 0x8d, 0x1c, 0x99, 0x2f, 0x65, 0x27, 0x0c, 0xde, + 0xc4, 0xe6, 0x71, 0x1d, 0xc9, 0x51, 0x7b, 0xda, 0x9c, 0xb6, 0x49, 0x4b, 0x91, 0x90, 0x05, 0x9b, 0x02, 0x98, 0x21, 0x25, 0xdb, 0xf5, 0x62, 0x0e, 0x44, 0x0e, 0x45, 0x54, 0xf8, 0x60, 0x81, 0xa1, - 0x1d, 0x2d, 0xbb, 0xeb, 0xe9, 0xb6, 0x8b, 0xfe, 0x84, 0xee, 0xfa, 0x0b, 0xfa, 0x5f, 0xba, 0xed, - 0x2f, 0xe8, 0xba, 0x67, 0x06, 0x03, 0x12, 0x94, 0x28, 0x3b, 0x1b, 0x9b, 0x78, 0xee, 0x33, 0x77, - 0xee, 0x9d, 0xfb, 0xdc, 0xf9, 0x10, 0xec, 0x46, 0xe1, 0x9c, 0xd1, 0x28, 0x9a, 0x8d, 0x0e, 0x92, - 0x5f, 0xfb, 0xb3, 0x28, 0x64, 0x21, 0x2a, 0x2d, 0xf0, 0x46, 0x29, 0x9a, 0x8d, 0x12, 0x54, 0xff, - 0xfb, 0x06, 0xa0, 0x01, 0x0d, 0xc6, 0x7d, 0xe7, 0xda, 0xa7, 0x01, 0xc3, 0xf4, 0x4f, 0x73, 0x1a, - 0x33, 0x84, 0x40, 0x1d, 0xd3, 0x98, 0xd5, 0x95, 0xa6, 0xd2, 0xaa, 0x60, 0xf1, 0x1b, 0x69, 0x90, - 0x77, 0x7c, 0x56, 0xcf, 0x35, 0x95, 0x56, 0x1e, 0xf3, 0x9f, 0xe8, 0xff, 0xa0, 0xe8, 0xf8, 0x8c, - 0xf8, 0xb1, 0xc3, 0xea, 0x15, 0x01, 0x6f, 0x3a, 0x3e, 0x3b, 0x8d, 0x1d, 0x86, 0xbe, 0x84, 0xca, - 0x2c, 0x71, 0x49, 0xa6, 0x4e, 0x3c, 0xad, 0xe7, 0x85, 0xa3, 0xb2, 0xc4, 0x4e, 0x9c, 0x78, 0x8a, - 0x5a, 0xa0, 0x4d, 0xdc, 0xc0, 0xf1, 0xc8, 0xc8, 0x63, 0xef, 0xc8, 0x98, 0x7a, 0xcc, 0xa9, 0xab, - 0x4d, 0xa5, 0x55, 0xc0, 0x35, 0x81, 0x77, 0x3c, 0xf6, 0xae, 0xcb, 0x51, 0xf4, 0x08, 0xb6, 0x52, - 0x67, 0x51, 0x12, 0x60, 0xbd, 0xd0, 0x54, 0x5a, 0x25, 0x5c, 0x9b, 0xad, 0x86, 0xfd, 0x08, 0xb6, - 0x98, 0xeb, 0xd3, 0x70, 0xce, 0x48, 0x4c, 0x47, 0x61, 0x30, 0x8e, 0xeb, 0x1b, 0x89, 0x47, 0x09, - 0x0f, 0x12, 0x14, 0xe9, 0x50, 0x9d, 0x50, 0x4a, 0x3c, 0xd7, 0x77, 0x19, 0xe1, 0xe1, 0x6f, 0x8a, - 0xf0, 0xcb, 0x13, 0x4a, 0x7b, 0x1c, 0x1b, 0x38, 0x0c, 0x7d, 0x05, 0xb5, 0x25, 0x47, 0xe4, 0x58, - 0x15, 0xa4, 0x4a, 0x4a, 0x12, 0x89, 0x3e, 0x01, 0x2d, 0x9c, 0xb3, 0xcb, 0xd0, 0x0d, 0x2e, 0xc9, - 0x68, 0xea, 0x04, 0xc4, 0x1d, 0xd7, 0x8b, 0x4d, 0xa5, 0xa5, 0x1e, 0xe5, 0x9e, 0x2a, 0xb8, 0x96, - 0xda, 0x3a, 0x53, 0x27, 0x30, 0xc7, 0xe8, 0x21, 0x6c, 0x79, 0x4e, 0xcc, 0xc8, 0x34, 0x9c, 0x91, - 0xd9, 0xfc, 0xe2, 0x8a, 0x5e, 0xd7, 0x6b, 0x62, 0x65, 0xaa, 0x1c, 0x3e, 0x09, 0x67, 0x7d, 0x01, - 0xa2, 0x07, 0x00, 0x62, 0x55, 0xc4, 0xe4, 0xf5, 0x92, 0xc8, 0xa1, 0xc4, 0x11, 0x31, 0x31, 0xfa, - 0x16, 0xca, 0xa2, 0x9a, 0x64, 0xea, 0x06, 0x2c, 0xae, 0x43, 0x33, 0xdf, 0x2a, 0x1f, 0x6a, 0xfb, - 0x5e, 0xc0, 0x0b, 0x8b, 0xb9, 0xe5, 0xc4, 0x0d, 0x18, 0x86, 0x28, 0xfd, 0x19, 0xa3, 0x31, 0xec, - 0xf0, 0x2a, 0x92, 0xd1, 0x3c, 0x66, 0xa1, 0x4f, 0x22, 0x3a, 0x0a, 0xa3, 0x71, 0x5c, 0x2f, 0x8b, - 0xa1, 0xbf, 0xd8, 0x5f, 0x88, 0x63, 0xff, 0xb6, 0x1a, 0xf6, 0xbb, 0x34, 0x66, 0x1d, 0x31, 0x0e, - 0x27, 0xc3, 0x8c, 0x80, 0x45, 0xd7, 0x78, 0x7b, 0x7c, 0x13, 0x47, 0x4f, 0x00, 0x39, 0x9e, 0x17, - 0xbe, 0x27, 0x31, 0xf5, 0x26, 0x44, 0x56, 0xa7, 0xbe, 0xd5, 0x54, 0x5a, 0x45, 0xac, 0x09, 0xcb, - 0x80, 0x7a, 0x13, 0xe9, 0x1e, 0xfd, 0x12, 0xaa, 0x22, 0xa6, 0x09, 0x75, 0xd8, 0x3c, 0xa2, 0x71, - 0x5d, 0x6b, 0xe6, 0x5b, 0xb5, 0xc3, 0x6d, 0x99, 0xc8, 0x71, 0x02, 0x1f, 0xb9, 0x0c, 0x57, 0x38, - 0x4f, 0x7e, 0xc7, 0x7c, 0x75, 0x7c, 0xe7, 0x47, 0x12, 0x4f, 0x1d, 0x9e, 0xc2, 0x76, 0x53, 0x69, - 0x55, 0x71, 0xc9, 0x77, 0x7e, 0x1c, 0x08, 0xa0, 0xd1, 0x85, 0xdd, 0xf5, 0x11, 0x73, 0x09, 0xf3, - 0x25, 0xe7, 0xaa, 0x56, 0x31, 0xff, 0x89, 0xee, 0x41, 0xe1, 0x9d, 0xe3, 0xcd, 0xa9, 0x90, 0x75, - 0x05, 0x27, 0x1f, 0xbf, 0xce, 0x3d, 0x53, 0xf4, 0x67, 0xb0, 0x33, 0x8c, 0x9c, 0xd1, 0xd5, 0x8d, - 0xce, 0xb8, 0x29, 0x6c, 0xe5, 0x96, 0xb0, 0xf5, 0xef, 0x61, 0x4b, 0xd4, 0xe0, 0x98, 0xd2, 0x0f, - 0xf5, 0xd3, 0x7d, 0xe0, 0xdd, 0x22, 0xd4, 0x97, 0xf4, 0xd4, 0x86, 0xe3, 0x73, 0xe1, 0xe9, 0x63, - 0xd0, 0x96, 0xe3, 0xe3, 0x59, 0x18, 0xc4, 0x94, 0x37, 0x0b, 0x2f, 0x11, 0x57, 0x19, 0x17, 0xa5, - 0x90, 0xa3, 0x22, 0x46, 0xd5, 0x24, 0x7e, 0x4c, 0xa9, 0x10, 0xe4, 0xc3, 0xa4, 0x07, 0x88, 0x17, - 0x8e, 0xae, 0x78, 0x57, 0x39, 0xd7, 0xd2, 0x7d, 0x95, 0xc3, 0xbd, 0x70, 0x74, 0xd5, 0xe5, 0xa0, - 0xfe, 0x36, 0x69, 0xfc, 0x61, 0x28, 0xe6, 0xfa, 0xe9, 0xe9, 0x21, 0x1d, 0x0a, 0x42, 0x2d, 0xc2, - 0x6d, 0xf9, 0xb0, 0x92, 0x95, 0x1d, 0x4e, 0x4c, 0xfa, 0x5b, 0xd8, 0x59, 0x71, 0x2e, 0xb3, 0x68, - 0x40, 0x71, 0x16, 0x51, 0xd7, 0x77, 0x2e, 0xa9, 0xf4, 0xbc, 0xf8, 0x46, 0x2d, 0xd8, 0x9c, 0x38, - 0xae, 0x37, 0x8f, 0x52, 0xc7, 0xb5, 0x54, 0x06, 0x09, 0x8a, 0x53, 0xb3, 0xfe, 0x19, 0x34, 0x30, - 0x8d, 0x29, 0x3b, 0x75, 0xe3, 0xd8, 0x0d, 0x83, 0x4e, 0x18, 0xb0, 0x28, 0xf4, 0x64, 0x06, 0xfa, - 0x03, 0xd8, 0x5b, 0x6b, 0x4d, 0x42, 0xe0, 0x83, 0x7f, 0x98, 0xd3, 0xe8, 0x7a, 0xfd, 0xe0, 0x1f, - 0x60, 0x6f, 0xad, 0x55, 0xc6, 0xff, 0x04, 0x0a, 0x33, 0xc7, 0x8d, 0xe2, 0x7a, 0x4e, 0xb4, 0xcd, - 0x6e, 0xa6, 0x6d, 0xfa, 0x8e, 0x1b, 0x9d, 0xb8, 0x31, 0x0b, 0xa3, 0x6b, 0x9c, 0x90, 0x5e, 0xa8, - 0x45, 0x45, 0xcb, 0xe9, 0x7f, 0x55, 0xa0, 0x9c, 0x31, 0xa2, 0x3d, 0x28, 0x05, 0xe1, 0x98, 0x92, - 0x49, 0x14, 0xfa, 0xe9, 0x22, 0x70, 0xe0, 0x38, 0x0a, 0x7d, 0xae, 0x09, 0x61, 0x64, 0xa1, 0x14, - 0xe4, 0x06, 0xff, 0x1c, 0x86, 0xe8, 0x1b, 0xd8, 0x9c, 0x26, 0x0e, 0xc4, 0x56, 0x55, 0x3e, 0xdc, - 0xb9, 0x31, 0x77, 0xd7, 0x61, 0x0e, 0x4e, 0x39, 0x2f, 0xd4, 0x62, 0x5e, 0x53, 0x5f, 0xa8, 0x45, - 0x55, 0x2b, 0xbc, 0x50, 0x8b, 0x05, 0x6d, 0xe3, 0x85, 0x5a, 0xdc, 0xd0, 0x36, 0xf5, 0xff, 0x28, - 0x50, 0x4c, 0xd9, 0x3c, 0x12, 0xbe, 0xa4, 0x84, 0xeb, 0x42, 0x8a, 0xa9, 0xc8, 0x81, 0xa1, 0xeb, - 0x53, 0xd4, 0x84, 0x8a, 0x30, 0xae, 0x4a, 0x14, 0x38, 0xd6, 0x16, 0x32, 0x15, 0x7b, 0x68, 0xca, - 0x10, 0x7a, 0x54, 0xe5, 0x1e, 0x9a, 0x50, 0xd2, 0x63, 0x20, 0x9e, 0x8f, 0x46, 0x34, 0x8e, 0x93, - 0x59, 0x0a, 0x09, 0x45, 0x62, 0x62, 0xa2, 0x87, 0xb0, 0x95, 0x52, 0xd2, 0xb9, 0x36, 0x12, 0xbd, - 0x4a, 0x58, 0x4e, 0xd7, 0x02, 0x2d, 0xcb, 0xf3, 0x97, 0xbb, 0x76, 0x6d, 0x49, 0xe4, 0x93, 0x26, - 0xc9, 0xeb, 0x7f, 0x84, 0xfb, 0xa2, 0x94, 0xfd, 0x28, 0xbc, 0x70, 0x2e, 0x5c, 0xcf, 0x65, 0xd7, - 0xa9, 0xc8, 0x79, 0xe2, 0x51, 0xe8, 0x13, 0xbe, 0xb6, 0x69, 0x09, 0x38, 0x60, 0x85, 0x63, 0xca, - 0x4b, 0xc0, 0xc2, 0xc4, 0x24, 0x4b, 0xc0, 0x42, 0x61, 0xc8, 0x9e, 0x76, 0xf9, 0x95, 0xd3, 0x4e, - 0xbf, 0x82, 0xfa, 0xed, 0xb9, 0xa4, 0x66, 0x9a, 0x50, 0x9e, 0x2d, 0x61, 0x31, 0x9d, 0x82, 0xb3, - 0x50, 0xb6, 0xb6, 0xb9, 0x8f, 0xd7, 0x56, 0xff, 0x87, 0x02, 0xdb, 0x47, 0x73, 0xd7, 0x1b, 0xaf, - 0x34, 0x6e, 0x36, 0x3a, 0x65, 0xf5, 0x2c, 0x5e, 0x77, 0xd0, 0xe6, 0xd6, 0x1e, 0xb4, 0xeb, 0x0e, - 0xb3, 0xfc, 0x9d, 0x87, 0xd9, 0x17, 0x50, 0x5e, 0x9e, 0x63, 0x71, 0x5d, 0x6d, 0xe6, 0x5b, 0x15, - 0x0c, 0xd3, 0xf4, 0x10, 0x8b, 0xf5, 0x67, 0x80, 0xb2, 0x81, 0xca, 0x05, 0x59, 0xec, 0x1f, 0xca, - 0xdd, 0xfb, 0xc7, 0x67, 0xd0, 0x18, 0xcc, 0x2f, 0xe2, 0x51, 0xe4, 0x5e, 0xd0, 0x13, 0xe6, 0x8d, - 0x8c, 0x77, 0x34, 0x60, 0x71, 0xda, 0xa5, 0xff, 0x55, 0xa1, 0xb4, 0x40, 0xd1, 0x3e, 0xec, 0xb8, - 0xc1, 0x28, 0xf4, 0xd3, 0xa0, 0x03, 0xea, 0xf1, 0xb8, 0x93, 0x4d, 0x7e, 0x3b, 0x35, 0x75, 0x12, - 0x8b, 0x39, 0xe6, 0xfc, 0x95, 0x24, 0x25, 0x3f, 0x97, 0xf0, 0xb3, 0x39, 0x26, 0xfc, 0x16, 0x68, - 0x0b, 0xff, 0x53, 0xe6, 0x8d, 0x16, 0x8b, 0x82, 0x6b, 0x29, 0xce, 0x83, 0x49, 0x98, 0x0b, 0xcf, - 0x29, 0x53, 0x4d, 0x98, 0x29, 0x2e, 0x99, 0x5f, 0x42, 0x85, 0xf7, 0x43, 0xcc, 0x1c, 0x7f, 0x46, - 0x82, 0x58, 0xf4, 0x85, 0x8a, 0xcb, 0x0b, 0xcc, 0x8a, 0xd1, 0x77, 0x00, 0x94, 0xe7, 0x47, 0xd8, - 0xf5, 0x8c, 0x8a, 0x96, 0xa8, 0x1d, 0x7e, 0x9e, 0x11, 0xc6, 0x62, 0x01, 0xf6, 0xc5, 0xbf, 0xc3, - 0xeb, 0x19, 0xc5, 0x25, 0x9a, 0xfe, 0x44, 0xdf, 0x43, 0x75, 0x12, 0x46, 0xef, 0x9d, 0x68, 0x4c, - 0x04, 0x28, 0xb7, 0x8d, 0xfb, 0x19, 0x0f, 0xc7, 0x89, 0x5d, 0x0c, 0x3f, 0xf9, 0x04, 0x57, 0x26, - 0x99, 0x6f, 0xf4, 0x12, 0x50, 0x3a, 0x5e, 0x74, 0x79, 0xe2, 0xa4, 0x28, 0x9c, 0xec, 0xdd, 0x76, - 0xc2, 0x37, 0xe9, 0xd4, 0x91, 0x36, 0xb9, 0x81, 0xa1, 0xdf, 0x40, 0x25, 0xa6, 0x8c, 0x79, 0x54, - 0xba, 0x29, 0x09, 0x37, 0xbb, 0x2b, 0xb7, 0x0e, 0x6e, 0x4e, 0x3d, 0x94, 0xe3, 0xe5, 0x27, 0x3a, - 0x82, 0x2d, 0xcf, 0x0d, 0xae, 0xb2, 0x61, 0x80, 0x18, 0x5f, 0xcf, 0x8c, 0xef, 0xb9, 0xc1, 0x55, - 0x36, 0x86, 0xaa, 0x97, 0x05, 0xf4, 0xdf, 0x42, 0x69, 0xb1, 0x4a, 0xa8, 0x0c, 0x9b, 0x67, 0xd6, - 0x4b, 0xcb, 0x7e, 0x65, 0x69, 0x9f, 0xa0, 0x22, 0xa8, 0x03, 0xc3, 0xea, 0x6a, 0x0a, 0x87, 0xb1, - 0xd1, 0x31, 0xcc, 0x73, 0x43, 0xcb, 0xf1, 0x8f, 0x63, 0x1b, 0xbf, 0x6a, 0xe3, 0xae, 0x96, 0x3f, - 0xda, 0x84, 0x82, 0x98, 0x57, 0xff, 0x97, 0x02, 0x45, 0x51, 0xc1, 0x60, 0x12, 0xa2, 0x9f, 0xc1, - 0x42, 0x5c, 0x62, 0x73, 0xe3, 0x07, 0xae, 0x50, 0x5d, 0x15, 0x2f, 0x04, 0x33, 0x94, 0x38, 0x27, - 0x2f, 0xa4, 0xb1, 0x20, 0xe7, 0x12, 0x72, 0x6a, 0x58, 0x90, 0x1f, 0x67, 0x3c, 0xaf, 0x6c, 0x39, - 0x2a, 0xde, 0x4a, 0x0d, 0xe9, 0x0e, 0xfb, 0x38, 0xe3, 0x78, 0x65, 0x27, 0x56, 0xf1, 0x56, 0x6a, - 0x90, 0x5c, 0xfd, 0x57, 0x50, 0xc9, 0xd6, 0x1c, 0x3d, 0x02, 0xd5, 0x0d, 0x26, 0xa1, 0x6c, 0xc4, - 0x9d, 0x1b, 0xe2, 0xe2, 0x49, 0x62, 0x41, 0xd0, 0x11, 0x68, 0x37, 0xeb, 0xac, 0x57, 0xa1, 0x9c, - 0x29, 0x9a, 0xfe, 0x6f, 0x05, 0xaa, 0x2b, 0x45, 0xf8, 0xc9, 0xde, 0xd1, 0x77, 0x50, 0x79, 0xef, - 0x46, 0x94, 0x64, 0x8f, 0xff, 0xda, 0x61, 0x63, 0xf5, 0xf8, 0x4f, 0xff, 0xef, 0x84, 0x63, 0x8a, - 0xcb, 0x9c, 0x2f, 0x01, 0xf4, 0x3b, 0xa8, 0xc9, 0x91, 0x64, 0x4c, 0x99, 0xe3, 0x7a, 0x62, 0xa9, - 0x6a, 0x2b, 0xf2, 0x90, 0xdc, 0xae, 0xb0, 0xe3, 0xea, 0x24, 0xfb, 0x89, 0xbe, 0x5e, 0x3a, 0x88, - 0x59, 0xe4, 0x06, 0x97, 0x62, 0xfd, 0x4a, 0x0b, 0xda, 0x40, 0x80, 0xfc, 0x20, 0xaf, 0xca, 0xcb, - 0xe0, 0x80, 0x39, 0x6c, 0x1e, 0xa3, 0x6f, 0xa0, 0x10, 0x33, 0x47, 0xee, 0x64, 0xb5, 0x95, 0xde, - 0xca, 0x10, 0x29, 0x4e, 0x58, 0x2b, 0xb7, 0x9f, 0xdc, 0xad, 0xdb, 0x4f, 0x81, 0xef, 0x18, 0xc9, - 0x2e, 0x5a, 0x3e, 0x44, 0x32, 0xf9, 0x93, 0x61, 0xaf, 0xd3, 0x66, 0x8c, 0xfa, 0x33, 0x86, 0x13, - 0x42, 0x72, 0xba, 0x3d, 0xfe, 0xb3, 0x0a, 0xd5, 0x95, 0xa4, 0x56, 0x55, 0x5d, 0x85, 0x92, 0x65, - 0x93, 0xae, 0x31, 0x6c, 0x9b, 0x3d, 0x4d, 0x41, 0x1a, 0x54, 0x6c, 0xcb, 0xb4, 0x2d, 0xd2, 0x35, - 0x3a, 0x76, 0x97, 0xeb, 0xfb, 0x53, 0xd8, 0xee, 0x99, 0xd6, 0x4b, 0x62, 0xd9, 0x43, 0x62, 0xf4, - 0xcc, 0xe7, 0xe6, 0x51, 0xcf, 0xd0, 0xf2, 0xe8, 0x1e, 0x68, 0xb6, 0x45, 0x3a, 0x27, 0x6d, 0xd3, - 0x22, 0x43, 0xf3, 0xd4, 0xb0, 0xcf, 0x86, 0x9a, 0xca, 0x51, 0x1e, 0x08, 0x31, 0x5e, 0x77, 0x0c, - 0xa3, 0x3b, 0x20, 0xa7, 0xed, 0xd7, 0x5a, 0x01, 0xd5, 0xe1, 0x9e, 0x69, 0x0d, 0xce, 0x8e, 0x8f, - 0xcd, 0x8e, 0x69, 0x58, 0x43, 0x72, 0xd4, 0xee, 0xb5, 0xad, 0x8e, 0xa1, 0x6d, 0xa0, 0x5d, 0x40, - 0xa6, 0xd5, 0xb1, 0x4f, 0xfb, 0x3d, 0x63, 0x68, 0x90, 0xb4, 0x8f, 0x36, 0xd1, 0x0e, 0x6c, 0x09, - 0x3f, 0xed, 0x6e, 0x97, 0x1c, 0xb7, 0xcd, 0x9e, 0xd1, 0xd5, 0x8a, 0x3c, 0x12, 0xc9, 0x18, 0x90, - 0xae, 0x39, 0x68, 0x1f, 0x71, 0xb8, 0xc4, 0xe7, 0x34, 0xad, 0x73, 0xdb, 0xec, 0x18, 0xa4, 0xc3, - 0xdd, 0x72, 0x14, 0x38, 0x39, 0x45, 0xcf, 0xac, 0xae, 0x81, 0xfb, 0x6d, 0xb3, 0xab, 0x95, 0xd1, - 0x1e, 0xdc, 0x4f, 0x61, 0xe3, 0x75, 0xdf, 0xc4, 0x6f, 0xc8, 0xd0, 0xb6, 0xc9, 0xc0, 0xb6, 0x2d, - 0xad, 0x92, 0xf5, 0xc4, 0xb3, 0xb5, 0xfb, 0x86, 0xa5, 0x55, 0xd1, 0x7d, 0xd8, 0x39, 0xed, 0xf7, - 0x49, 0x6a, 0x49, 0x93, 0xad, 0x71, 0x7a, 0xbb, 0xdb, 0xc5, 0xc6, 0x60, 0x40, 0x4e, 0xcd, 0xc1, - 0x69, 0x7b, 0xd8, 0x39, 0xd1, 0xb6, 0x78, 0x4a, 0x03, 0x63, 0x48, 0x86, 0xf6, 0xb0, 0xdd, 0x5b, - 0xe2, 0x1a, 0x0f, 0x68, 0x89, 0xf3, 0x49, 0x7b, 0xf6, 0x2b, 0x6d, 0x9b, 0x2f, 0x38, 0x87, 0xed, - 0x73, 0x19, 0x22, 0xe2, 0xb9, 0xcb, 0xf2, 0xa4, 0x73, 0x6a, 0x3b, 0x1c, 0x34, 0xad, 0xf3, 0x76, - 0xcf, 0xec, 0x92, 0x97, 0xc6, 0x1b, 0xb1, 0x0f, 0xdd, 0xe3, 0x60, 0x12, 0x19, 0xe9, 0x63, 0xfb, - 0x39, 0x0f, 0x44, 0xfb, 0x14, 0x21, 0xa8, 0x75, 0x4c, 0xdc, 0x39, 0xeb, 0xb5, 0x31, 0xc1, 0xf6, - 0xd9, 0xd0, 0xd0, 0x76, 0x1f, 0xff, 0x53, 0x81, 0x4a, 0x56, 0x67, 0xbc, 0xea, 0xa6, 0x45, 0x8e, - 0x7b, 0xe6, 0xf3, 0x93, 0x61, 0x22, 0x82, 0xc1, 0x59, 0x87, 0x97, 0xcc, 0xe0, 0xfb, 0x1b, 0x82, - 0x5a, 0xb2, 0xe8, 0x8b, 0x64, 0x73, 0x7c, 0x2e, 0x89, 0x59, 0xb6, 0xf4, 0x9b, 0xe7, 0xc1, 0x4b, - 0xd0, 0xc0, 0xd8, 0xc6, 0x9a, 0x8a, 0xbe, 0x82, 0xa6, 0x44, 0x78, 0x5d, 0x31, 0x36, 0x3a, 0x43, - 0xd2, 0x6f, 0xbf, 0x39, 0xe5, 0x65, 0x4f, 0x44, 0x36, 0xd0, 0x0a, 0xe8, 0x0b, 0xd8, 0x5b, 0xb0, - 0xd6, 0xe9, 0xe2, 0xf0, 0x6f, 0x9b, 0xb0, 0x21, 0x8e, 0xf9, 0x08, 0xfd, 0x1e, 0xaa, 0x99, 0x87, - 0xe6, 0xf9, 0x21, 0x7a, 0xf0, 0xc1, 0x27, 0x68, 0x23, 0x7d, 0x0c, 0x48, 0xf8, 0xa9, 0x82, 0x8e, - 0xa0, 0x96, 0x7d, 0x9f, 0x9d, 0x1f, 0xa2, 0xec, 0xe9, 0xb8, 0xe6, 0xe9, 0xb6, 0xc6, 0xc7, 0x4b, - 0xd0, 0x8c, 0x98, 0xb9, 0x3e, 0x6f, 0x52, 0xf9, 0xe2, 0x42, 0x8d, 0x8c, 0x97, 0x1b, 0xcf, 0xb8, - 0xc6, 0xde, 0x5a, 0x9b, 0xbc, 0xd7, 0xf4, 0xf8, 0x86, 0xb8, 0x78, 0xf3, 0xdc, 0x4a, 0x68, 0xf5, - 0xa1, 0xd5, 0xf8, 0xfc, 0x2e, 0xb3, 0xf4, 0x36, 0x86, 0x9d, 0x35, 0xcf, 0x18, 0xf4, 0x75, 0x36, - 0x82, 0x3b, 0x1f, 0x41, 0x8d, 0x87, 0x1f, 0xa3, 0x2d, 0x67, 0x59, 0xf3, 0xde, 0x59, 0x99, 0xe5, - 0xee, 0xd7, 0xd2, 0xca, 0x2c, 0x1f, 0x7a, 0x36, 0xbd, 0x05, 0xed, 0xe6, 0xf5, 0x18, 0xe9, 0x37, - 0xc7, 0xde, 0xbe, 0xa7, 0x37, 0xfe, 0xff, 0x83, 0x1c, 0xe9, 0xdc, 0x04, 0x58, 0x5e, 0x32, 0xd1, - 0x67, 0x99, 0x21, 0xb7, 0x2e, 0xc9, 0x8d, 0x07, 0x77, 0x58, 0xa5, 0xab, 0x21, 0xec, 0xac, 0xb9, - 0x75, 0xae, 0xac, 0xc6, 0xdd, 0xb7, 0xd2, 0xc6, 0xbd, 0x75, 0x97, 0xb3, 0xa7, 0x0a, 0x3a, 0x4d, - 0x74, 0x91, 0xfe, 0xd1, 0xe3, 0x23, 0x42, 0xaf, 0xaf, 0x3f, 0x44, 0xe6, 0xb1, 0x9e, 0xff, 0x4b, - 0x4e, 0x79, 0xaa, 0x20, 0x1b, 0x2a, 0x59, 0x71, 0x7f, 0x54, 0xf5, 0x1f, 0x73, 0x78, 0xf4, 0xed, - 0x1f, 0x0e, 0x2e, 0x5d, 0x36, 0x9d, 0x5f, 0xec, 0x8f, 0x42, 0xff, 0xc0, 0x73, 0x2f, 0xa7, 0x2c, - 0x70, 0x83, 0xcb, 0x80, 0xb2, 0xf7, 0x61, 0x74, 0x75, 0xe0, 0x05, 0xe3, 0x03, 0xd1, 0x37, 0x07, - 0x0b, 0x3f, 0x17, 0x1b, 0xe2, 0x8f, 0x87, 0x3f, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x09, - 0xc8, 0xdd, 0x00, 0x6c, 0x14, 0x00, 0x00, + 0x1d, 0x2d, 0xbb, 0xeb, 0xe9, 0xb6, 0x3f, 0xa2, 0xbb, 0xfe, 0x82, 0xee, 0xfb, 0x33, 0xba, 0xed, + 0x2f, 0xe8, 0xba, 0x67, 0x06, 0x03, 0x12, 0x94, 0x28, 0xbb, 0xdd, 0xd8, 0xc4, 0x73, 0x9f, 0xb9, + 0x73, 0xef, 0xdc, 0xe7, 0xce, 0x87, 0x60, 0x37, 0x0a, 0xe7, 0x8c, 0x46, 0xd1, 0x6c, 0x74, 0x90, + 0xfc, 0xda, 0x9f, 0x45, 0x21, 0x0b, 0x51, 0x69, 0x81, 0x37, 0x4a, 0xd1, 0x6c, 0x94, 0xa0, 0xfa, + 0x3f, 0x36, 0x00, 0x0d, 0x68, 0x30, 0xee, 0x3b, 0xd7, 0x3e, 0x0d, 0x18, 0xa6, 0x7f, 0x98, 0xd3, + 0x98, 0x21, 0x04, 0xea, 0x98, 0xc6, 0xac, 0xae, 0x34, 0x95, 0x56, 0x05, 0x8b, 0xdf, 0x48, 0x83, + 0xbc, 0xe3, 0xb3, 0x7a, 0xae, 0xa9, 0xb4, 0xf2, 0x98, 0xff, 0x44, 0xff, 0x07, 0x45, 0xc7, 0x67, + 0xc4, 0x8f, 0x1d, 0x56, 0xaf, 0x08, 0x78, 0xd3, 0xf1, 0xd9, 0x69, 0xec, 0x30, 0xf4, 0x05, 0x54, + 0x66, 0x89, 0x4b, 0x32, 0x75, 0xe2, 0x69, 0x3d, 0x2f, 0x1c, 0x95, 0x25, 0x76, 0xe2, 0xc4, 0x53, + 0xd4, 0x02, 0x6d, 0xe2, 0x06, 0x8e, 0x47, 0x46, 0x1e, 0x7b, 0x47, 0xc6, 0xd4, 0x63, 0x4e, 0x5d, + 0x6d, 0x2a, 0xad, 0x02, 0xae, 0x09, 0xbc, 0xe3, 0xb1, 0x77, 0x5d, 0x8e, 0xa2, 0xc7, 0xb0, 0x95, + 0x3a, 0x8b, 0x92, 0x00, 0xeb, 0x85, 0xa6, 0xd2, 0x2a, 0xe1, 0xda, 0x6c, 0x35, 0xec, 0xc7, 0xb0, + 0xc5, 0x5c, 0x9f, 0x86, 0x73, 0x46, 0x62, 0x3a, 0x0a, 0x83, 0x71, 0x5c, 0xdf, 0x48, 0x3c, 0x4a, + 0x78, 0x90, 0xa0, 0x48, 0x87, 0xea, 0x84, 0x52, 0xe2, 0xb9, 0xbe, 0xcb, 0x08, 0x0f, 0x7f, 0x53, + 0x84, 0x5f, 0x9e, 0x50, 0xda, 0xe3, 0xd8, 0xc0, 0x61, 0xe8, 0x4b, 0xa8, 0x2d, 0x39, 0x22, 0xc7, + 0xaa, 0x20, 0x55, 0x52, 0x92, 0x48, 0xf4, 0x29, 0x68, 0xe1, 0x9c, 0x5d, 0x86, 0x6e, 0x70, 0x49, + 0x46, 0x53, 0x27, 0x20, 0xee, 0xb8, 0x5e, 0x6c, 0x2a, 0x2d, 0xf5, 0x28, 0xf7, 0x4c, 0xc1, 0xb5, + 0xd4, 0xd6, 0x99, 0x3a, 0x81, 0x39, 0x46, 0x8f, 0x60, 0xcb, 0x73, 0x62, 0x46, 0xa6, 0xe1, 0x8c, + 0xcc, 0xe6, 0x17, 0x57, 0xf4, 0xba, 0x5e, 0x13, 0x2b, 0x53, 0xe5, 0xf0, 0x49, 0x38, 0xeb, 0x0b, + 0x10, 0x3d, 0x04, 0x10, 0xab, 0x22, 0x26, 0xaf, 0x97, 0x44, 0x0e, 0x25, 0x8e, 0x88, 0x89, 0xd1, + 0x37, 0x50, 0x16, 0xd5, 0x24, 0x53, 0x37, 0x60, 0x71, 0x1d, 0x9a, 0xf9, 0x56, 0xf9, 0x50, 0xdb, + 0xf7, 0x02, 0x5e, 0x58, 0xcc, 0x2d, 0x27, 0x6e, 0xc0, 0x30, 0x44, 0xe9, 0xcf, 0x18, 0x8d, 0x61, + 0x87, 0x57, 0x91, 0x8c, 0xe6, 0x31, 0x0b, 0x7d, 0x12, 0xd1, 0x51, 0x18, 0x8d, 0xe3, 0x7a, 0x59, + 0x0c, 0xfd, 0xd9, 0xfe, 0x42, 0x1c, 0xfb, 0xb7, 0xd5, 0xb0, 0xdf, 0xa5, 0x31, 0xeb, 0x88, 0x71, + 0x38, 0x19, 0x66, 0x04, 0x2c, 0xba, 0xc6, 0xdb, 0xe3, 0x9b, 0x38, 0x7a, 0x0a, 0xc8, 0xf1, 0xbc, + 0xf0, 0x3d, 0x89, 0xa9, 0x37, 0x21, 0xb2, 0x3a, 0xf5, 0xad, 0xa6, 0xd2, 0x2a, 0x62, 0x4d, 0x58, + 0x06, 0xd4, 0x9b, 0x48, 0xf7, 0xe8, 0xe7, 0x50, 0x15, 0x31, 0x4d, 0xa8, 0xc3, 0xe6, 0x11, 0x8d, + 0xeb, 0x5a, 0x33, 0xdf, 0xaa, 0x1d, 0x6e, 0xcb, 0x44, 0x8e, 0x13, 0xf8, 0xc8, 0x65, 0xb8, 0xc2, + 0x79, 0xf2, 0x3b, 0xe6, 0xab, 0xe3, 0x3b, 0x3f, 0x92, 0x78, 0xea, 0xf0, 0x14, 0xb6, 0x9b, 0x4a, + 0xab, 0x8a, 0x4b, 0xbe, 0xf3, 0xe3, 0x40, 0x00, 0x68, 0x1f, 0x76, 0x82, 0x90, 0xb8, 0xc1, 0xc4, + 0x73, 0x2f, 0xa7, 0x8c, 0xcc, 0x67, 0x63, 0x87, 0xd1, 0xb8, 0x8e, 0x44, 0x14, 0xdb, 0x41, 0x68, + 0x4a, 0xcb, 0x59, 0x62, 0x68, 0x74, 0x61, 0x77, 0x7d, 0x86, 0x5c, 0xf2, 0xbc, 0x44, 0xbc, 0x0b, + 0x54, 0xcc, 0x7f, 0xa2, 0x7b, 0x50, 0x78, 0xe7, 0x78, 0x73, 0x2a, 0xda, 0xa0, 0x82, 0x93, 0x8f, + 0x5f, 0xe6, 0xbe, 0x55, 0xf4, 0x29, 0xec, 0x0c, 0x23, 0x67, 0x74, 0x75, 0xa3, 0x93, 0x6e, 0x36, + 0x82, 0x72, 0xbb, 0x11, 0xee, 0x88, 0x37, 0x77, 0x47, 0xbc, 0xfa, 0xf7, 0xb0, 0x25, 0x6a, 0x7c, + 0x4c, 0xe9, 0x87, 0xfa, 0xf5, 0x3e, 0xf0, 0x6e, 0x14, 0xea, 0x4e, 0x7a, 0x76, 0xc3, 0xf1, 0xb9, + 0xb0, 0xf5, 0x31, 0x68, 0xcb, 0xf1, 0xf1, 0x2c, 0x0c, 0x62, 0xca, 0x9b, 0x91, 0x4b, 0x80, 0xab, + 0x98, 0x8b, 0x5e, 0xc8, 0x5d, 0x11, 0xa3, 0x6a, 0x12, 0x3f, 0xa6, 0x54, 0x08, 0xfe, 0x51, 0xd2, + 0x63, 0xc4, 0x0b, 0x47, 0x57, 0xbc, 0x6b, 0x9d, 0x6b, 0xe9, 0xbe, 0xca, 0xe1, 0x5e, 0x38, 0xba, + 0xea, 0x72, 0x50, 0x7f, 0x9b, 0x6c, 0x2c, 0xc3, 0x50, 0xcc, 0xf5, 0x3f, 0x2c, 0x87, 0x0e, 0x05, + 0xa1, 0x46, 0xe1, 0xb6, 0x7c, 0x58, 0xc9, 0xca, 0x1a, 0x27, 0x26, 0xfd, 0x2d, 0xec, 0xac, 0x38, + 0x97, 0x59, 0x34, 0xa0, 0x38, 0x8b, 0xa8, 0xeb, 0x3b, 0x97, 0x54, 0x7a, 0x5e, 0x7c, 0xa3, 0x16, + 0x6c, 0x4e, 0x1c, 0xd7, 0x9b, 0x47, 0xa9, 0xe3, 0x5a, 0x2a, 0xb3, 0x04, 0xc5, 0xa9, 0x59, 0x7f, + 0x00, 0x0d, 0x4c, 0x63, 0xca, 0x4e, 0xdd, 0x38, 0x76, 0xc3, 0xa0, 0x13, 0x06, 0x2c, 0x0a, 0x3d, + 0x99, 0x81, 0xfe, 0x10, 0xf6, 0xd6, 0x5a, 0x93, 0x10, 0xf8, 0xe0, 0x1f, 0xe6, 0x34, 0xba, 0x5e, + 0x3f, 0xf8, 0x07, 0xd8, 0x5b, 0x6b, 0x95, 0xf1, 0x3f, 0x85, 0xc2, 0xcc, 0x71, 0x23, 0x5e, 0x7b, + 0xde, 0x96, 0xbb, 0x99, 0xb6, 0xec, 0x3b, 0x6e, 0x74, 0xe2, 0xc6, 0x2c, 0x8c, 0xae, 0x71, 0x42, + 0x7a, 0xa1, 0x16, 0x15, 0x2d, 0xa7, 0xff, 0x59, 0x81, 0x72, 0xc6, 0x88, 0xf6, 0xa0, 0x14, 0x84, + 0x63, 0x4a, 0x26, 0x51, 0xe8, 0xa7, 0x8b, 0xc0, 0x81, 0xe3, 0x28, 0xf4, 0xb9, 0x26, 0x84, 0x91, + 0x85, 0x52, 0xc0, 0x1b, 0xfc, 0x73, 0x18, 0xa2, 0xaf, 0x61, 0x73, 0x9a, 0x38, 0x10, 0x5b, 0x61, + 0xf9, 0x70, 0xe7, 0xc6, 0xdc, 0x5d, 0x87, 0x39, 0x38, 0xe5, 0xbc, 0x50, 0x8b, 0x79, 0x4d, 0x7d, + 0xa1, 0x16, 0x55, 0xad, 0xf0, 0x42, 0x2d, 0x16, 0xb4, 0x8d, 0x17, 0x6a, 0x71, 0x43, 0xdb, 0xd4, + 0xff, 0xa5, 0x40, 0x31, 0x65, 0xf3, 0x48, 0xf8, 0x92, 0x12, 0xae, 0x0b, 0x29, 0xa6, 0x22, 0x07, + 0x86, 0xae, 0x4f, 0x51, 0x13, 0x2a, 0xc2, 0xb8, 0x2a, 0x51, 0xe0, 0x58, 0x5b, 0xc8, 0x54, 0xec, + 0xd1, 0x29, 0x43, 0xe8, 0x51, 0x95, 0x7b, 0x74, 0x42, 0x49, 0x8f, 0x99, 0x78, 0x3e, 0x1a, 0xd1, + 0x38, 0x4e, 0x66, 0x29, 0x24, 0x14, 0x89, 0x89, 0x89, 0x1e, 0xc1, 0x56, 0x4a, 0x49, 0xe7, 0xda, + 0x48, 0xf4, 0x2a, 0x61, 0x39, 0x5d, 0x0b, 0xb4, 0x2c, 0xcf, 0x5f, 0x9e, 0x0a, 0xb5, 0x25, 0x91, + 0x4f, 0x9a, 0x24, 0xaf, 0xff, 0x1e, 0xee, 0x8b, 0x52, 0xf6, 0xa3, 0xf0, 0xc2, 0xb9, 0x70, 0x3d, + 0x97, 0x5d, 0xa7, 0x22, 0xe7, 0x89, 0x47, 0xa1, 0x4f, 0xf8, 0xda, 0xa6, 0x25, 0xe0, 0x80, 0x15, + 0x8e, 0x29, 0x2f, 0x01, 0x0b, 0x13, 0x93, 0x2c, 0x01, 0x0b, 0x85, 0x21, 0x7b, 0x9a, 0xe6, 0x57, + 0x4e, 0x53, 0xfd, 0x0a, 0xea, 0xb7, 0xe7, 0x92, 0x9a, 0x69, 0x42, 0x79, 0xb6, 0x84, 0xc5, 0x74, + 0x0a, 0xce, 0x42, 0xd9, 0xda, 0xe6, 0x3e, 0x5e, 0x5b, 0xfd, 0xaf, 0x0a, 0x6c, 0x1f, 0xcd, 0x5d, + 0x6f, 0xbc, 0xd2, 0xb8, 0xd9, 0xe8, 0x94, 0xd5, 0xb3, 0x7e, 0xdd, 0x41, 0x9e, 0x5b, 0x7b, 0x90, + 0xaf, 0x3b, 0x2c, 0xf3, 0x77, 0x1e, 0x96, 0x9f, 0x43, 0x79, 0x79, 0x4e, 0xc6, 0x75, 0xb5, 0x99, + 0x6f, 0x55, 0x30, 0x4c, 0xd3, 0x43, 0x32, 0xd6, 0xbf, 0x05, 0x94, 0x0d, 0x54, 0x2e, 0xc8, 0x62, + 0xff, 0x50, 0xee, 0xde, 0x3f, 0x1e, 0x40, 0x63, 0x30, 0xbf, 0x88, 0x47, 0x91, 0x7b, 0x41, 0x4f, + 0x98, 0x37, 0x32, 0xde, 0xd1, 0x80, 0xc5, 0x69, 0x97, 0xfe, 0x5b, 0x85, 0xd2, 0x02, 0xe5, 0xdb, + 0xb3, 0x1b, 0x8c, 0x42, 0x3f, 0x0d, 0x3a, 0xa0, 0x1e, 0x8f, 0x3b, 0x39, 0x14, 0xb6, 0x53, 0x53, + 0x27, 0xb1, 0x98, 0x63, 0xce, 0x5f, 0x49, 0x52, 0xf2, 0x73, 0x09, 0x3f, 0x9b, 0x63, 0xc2, 0x6f, + 0x81, 0xb6, 0xf0, 0x3f, 0x65, 0xde, 0x68, 0xb1, 0x28, 0xb8, 0x96, 0xe2, 0x3c, 0x98, 0x84, 0xb9, + 0xf0, 0x9c, 0x32, 0xd5, 0x84, 0x99, 0xe2, 0x92, 0xf9, 0x05, 0x54, 0x78, 0x3f, 0xc4, 0xcc, 0xf1, + 0x67, 0x24, 0x88, 0x45, 0x5f, 0xa8, 0xb8, 0xbc, 0xc0, 0xac, 0x18, 0x7d, 0x07, 0x40, 0x79, 0x7e, + 0x84, 0x5d, 0xcf, 0xa8, 0x68, 0x89, 0xda, 0xe1, 0x67, 0x19, 0x61, 0x2c, 0x16, 0x60, 0x5f, 0xfc, + 0x3b, 0xbc, 0x9e, 0x51, 0x5c, 0xa2, 0xe9, 0x4f, 0xf4, 0x3d, 0x54, 0x27, 0x61, 0xf4, 0xde, 0x89, + 0xc6, 0x44, 0x80, 0x72, 0xdb, 0xb8, 0x9f, 0xf1, 0x70, 0x9c, 0xd8, 0xc5, 0xf0, 0x93, 0x4f, 0x70, + 0x65, 0x92, 0xf9, 0x46, 0x2f, 0x01, 0xa5, 0xe3, 0x45, 0x97, 0x27, 0x4e, 0x8a, 0xc2, 0xc9, 0xde, + 0x6d, 0x27, 0x7c, 0x93, 0x4e, 0x1d, 0x69, 0x93, 0x1b, 0x18, 0xfa, 0x15, 0x54, 0x62, 0xca, 0x98, + 0x47, 0xa5, 0x9b, 0x92, 0x70, 0xb3, 0xbb, 0x72, 0xab, 0xe1, 0xe6, 0xd4, 0x43, 0x39, 0x5e, 0x7e, + 0xa2, 0x23, 0xd8, 0xf2, 0xdc, 0xe0, 0x2a, 0x1b, 0x06, 0x88, 0xf1, 0xf5, 0xcc, 0xf8, 0x9e, 0x1b, + 0x5c, 0x65, 0x63, 0xa8, 0x7a, 0x59, 0x40, 0xff, 0x35, 0x94, 0x16, 0xab, 0x84, 0xca, 0xb0, 0x79, + 0x66, 0xbd, 0xb4, 0xec, 0x57, 0x96, 0xf6, 0x09, 0x2a, 0x82, 0x3a, 0x30, 0xac, 0xae, 0xa6, 0x70, + 0x18, 0x1b, 0x1d, 0xc3, 0x3c, 0x37, 0xb4, 0x1c, 0xff, 0x38, 0xb6, 0xf1, 0xab, 0x36, 0xee, 0x6a, + 0xf9, 0xa3, 0x4d, 0x28, 0x88, 0x79, 0xf5, 0xbf, 0x2b, 0x50, 0x14, 0x15, 0x0c, 0x26, 0x21, 0xfa, + 0x09, 0x2c, 0xc4, 0x25, 0x36, 0x37, 0x7e, 0xe0, 0x0a, 0xd5, 0x55, 0xf1, 0x42, 0x30, 0x43, 0x89, + 0x73, 0xf2, 0x42, 0x1a, 0x0b, 0x72, 0x2e, 0x21, 0xa7, 0x86, 0x05, 0xf9, 0x49, 0xc6, 0xf3, 0xca, + 0x96, 0xa3, 0xe2, 0xad, 0xd4, 0x90, 0xee, 0xb0, 0x4f, 0x32, 0x8e, 0x57, 0x76, 0x62, 0x15, 0x6f, + 0xa5, 0x06, 0xc9, 0xd5, 0x7f, 0x01, 0x95, 0x6c, 0xcd, 0xd1, 0x63, 0x50, 0xdd, 0x60, 0x12, 0xca, + 0x46, 0xdc, 0xb9, 0x21, 0x2e, 0x9e, 0x24, 0x16, 0x04, 0x1d, 0x81, 0x76, 0xb3, 0xce, 0x7a, 0x15, + 0xca, 0x99, 0xa2, 0xe9, 0xff, 0x54, 0xa0, 0xba, 0x52, 0x84, 0xff, 0xda, 0x3b, 0xfa, 0x0e, 0x2a, + 0xef, 0xdd, 0x88, 0x92, 0xec, 0xf1, 0x5f, 0x3b, 0x6c, 0xac, 0x1e, 0xff, 0xe9, 0xff, 0x9d, 0x70, + 0x4c, 0x71, 0x99, 0xf3, 0x25, 0x80, 0x7e, 0x03, 0x35, 0x39, 0x92, 0x8c, 0x29, 0x73, 0x5c, 0x4f, + 0x2c, 0x55, 0x6d, 0x45, 0x1e, 0x92, 0xdb, 0x15, 0x76, 0x5c, 0x9d, 0x64, 0x3f, 0xd1, 0x57, 0x4b, + 0x07, 0x31, 0x8b, 0xdc, 0xe0, 0x52, 0xac, 0x5f, 0x69, 0x41, 0x1b, 0x08, 0x90, 0x1f, 0xe4, 0x55, + 0x79, 0x79, 0x1c, 0x30, 0x87, 0xcd, 0x63, 0xf4, 0x35, 0x14, 0x62, 0xe6, 0xc8, 0x9d, 0xac, 0xb6, + 0xd2, 0x5b, 0x19, 0x22, 0xc5, 0x09, 0x6b, 0xe5, 0xf6, 0x93, 0xbb, 0x75, 0xfb, 0x29, 0xf0, 0x1d, + 0x23, 0xd9, 0x45, 0xcb, 0x87, 0x48, 0x26, 0x7f, 0x32, 0xec, 0x75, 0xda, 0x8c, 0x51, 0x7f, 0xc6, + 0x70, 0x42, 0x48, 0x4e, 0xb7, 0x27, 0x7f, 0x54, 0xa1, 0xba, 0x92, 0xd4, 0xaa, 0xaa, 0xab, 0x50, + 0xb2, 0x6c, 0xd2, 0x35, 0x86, 0x6d, 0xb3, 0xa7, 0x29, 0x48, 0x83, 0x8a, 0x6d, 0x99, 0xb6, 0x45, + 0xba, 0x46, 0xc7, 0xee, 0x72, 0x7d, 0x7f, 0x0a, 0xdb, 0x3d, 0xd3, 0x7a, 0x49, 0x2c, 0x7b, 0x48, + 0x8c, 0x9e, 0xf9, 0xdc, 0x3c, 0xea, 0x19, 0x5a, 0x1e, 0xdd, 0x03, 0xcd, 0xb6, 0x48, 0xe7, 0xa4, + 0x6d, 0x5a, 0x64, 0x68, 0x9e, 0x1a, 0xf6, 0xd9, 0x50, 0x53, 0x39, 0xca, 0x03, 0x21, 0xc6, 0xeb, + 0x8e, 0x61, 0x74, 0x07, 0xe4, 0xb4, 0xfd, 0x5a, 0x2b, 0xa0, 0x3a, 0xdc, 0x33, 0xad, 0xc1, 0xd9, + 0xf1, 0xb1, 0xd9, 0x31, 0x0d, 0x6b, 0x48, 0x8e, 0xda, 0xbd, 0xb6, 0xd5, 0x31, 0xb4, 0x0d, 0xb4, + 0x0b, 0xc8, 0xb4, 0x3a, 0xf6, 0x69, 0xbf, 0x67, 0x0c, 0x0d, 0x92, 0xf6, 0xd1, 0x26, 0xda, 0x81, + 0x2d, 0xe1, 0xa7, 0xdd, 0xed, 0x92, 0xe3, 0xb6, 0xd9, 0x33, 0xba, 0x5a, 0x91, 0x47, 0x22, 0x19, + 0x03, 0xd2, 0x35, 0x07, 0xed, 0x23, 0x0e, 0x97, 0xf8, 0x9c, 0xa6, 0x75, 0x6e, 0x9b, 0x1d, 0x83, + 0x74, 0xb8, 0x5b, 0x8e, 0x02, 0x27, 0xa7, 0xe8, 0x99, 0xd5, 0x35, 0x70, 0xbf, 0x6d, 0x76, 0xb5, + 0x32, 0xda, 0x83, 0xfb, 0x29, 0x6c, 0xbc, 0xee, 0x9b, 0xf8, 0x0d, 0x19, 0xda, 0x36, 0x19, 0xd8, + 0xb6, 0xa5, 0x55, 0xb2, 0x9e, 0x78, 0xb6, 0x76, 0xdf, 0xb0, 0xb4, 0x2a, 0xba, 0x0f, 0x3b, 0xa7, + 0xfd, 0x3e, 0x49, 0x2d, 0x69, 0xb2, 0x35, 0x4e, 0x6f, 0x77, 0xbb, 0xd8, 0x18, 0x0c, 0xc8, 0xa9, + 0x39, 0x38, 0x6d, 0x0f, 0x3b, 0x27, 0xda, 0x16, 0x4f, 0x69, 0x60, 0x0c, 0xc9, 0xd0, 0x1e, 0xb6, + 0x7b, 0x4b, 0x5c, 0xe3, 0x01, 0x2d, 0x71, 0x3e, 0x69, 0xcf, 0x7e, 0xa5, 0x6d, 0xf3, 0x05, 0xe7, + 0xb0, 0x7d, 0x2e, 0x43, 0x44, 0x3c, 0x77, 0x59, 0x9e, 0x74, 0x4e, 0x6d, 0x87, 0x83, 0xa6, 0x75, + 0xde, 0xee, 0x99, 0x5d, 0xf2, 0xd2, 0x78, 0x23, 0xf6, 0xa1, 0x7b, 0x1c, 0x4c, 0x22, 0x23, 0x7d, + 0x6c, 0x3f, 0xe7, 0x81, 0x68, 0x9f, 0x22, 0x04, 0xb5, 0x8e, 0x89, 0x3b, 0x67, 0xbd, 0x36, 0x26, + 0xd8, 0x3e, 0x1b, 0x1a, 0xda, 0xee, 0x93, 0xbf, 0x29, 0x50, 0xc9, 0xea, 0x8c, 0x57, 0xdd, 0xb4, + 0xc8, 0x71, 0xcf, 0x7c, 0x7e, 0x32, 0x4c, 0x44, 0x30, 0x38, 0xeb, 0xf0, 0x92, 0x19, 0x7c, 0x7f, + 0x43, 0x50, 0x4b, 0x16, 0x7d, 0x91, 0x6c, 0x8e, 0xcf, 0x25, 0x31, 0xcb, 0x96, 0x7e, 0xf3, 0x3c, + 0x78, 0x09, 0x1a, 0x18, 0xdb, 0x58, 0x53, 0xd1, 0x97, 0xd0, 0x94, 0x08, 0xaf, 0x2b, 0xc6, 0x46, + 0x67, 0x48, 0xfa, 0xed, 0x37, 0xa7, 0xbc, 0xec, 0x89, 0xc8, 0x06, 0x5a, 0x01, 0x7d, 0x0e, 0x7b, + 0x0b, 0xd6, 0x3a, 0x5d, 0x1c, 0xfe, 0x65, 0x13, 0x36, 0xc4, 0x31, 0x1f, 0xa1, 0xdf, 0x42, 0x35, + 0xf3, 0x90, 0x3d, 0x3f, 0x44, 0x0f, 0x3f, 0xf8, 0xc4, 0x6d, 0xa4, 0x8f, 0x01, 0x09, 0x3f, 0x53, + 0xd0, 0x11, 0xd4, 0xb2, 0xef, 0xb9, 0xf3, 0x43, 0x94, 0x3d, 0x1d, 0xd7, 0x3c, 0xf5, 0xd6, 0xf8, + 0x78, 0x09, 0x9a, 0x11, 0x33, 0xd7, 0xe7, 0x4d, 0x2a, 0x5f, 0x5c, 0xa8, 0x91, 0xf1, 0x72, 0xe3, + 0x19, 0xd7, 0xd8, 0x5b, 0x6b, 0x93, 0xf7, 0x9a, 0x1e, 0xdf, 0x10, 0x17, 0x6f, 0x9e, 0x5b, 0x09, + 0xad, 0x3e, 0xb4, 0x1a, 0x9f, 0xdd, 0x65, 0x96, 0xde, 0xc6, 0xb0, 0xb3, 0xe6, 0x19, 0x83, 0xbe, + 0xca, 0x46, 0x70, 0xe7, 0x23, 0xa8, 0xf1, 0xe8, 0x63, 0xb4, 0xe5, 0x2c, 0x6b, 0xde, 0x3b, 0x2b, + 0xb3, 0xdc, 0xfd, 0x5a, 0x5a, 0x99, 0xe5, 0x43, 0xcf, 0xa6, 0xb7, 0xa0, 0xdd, 0xbc, 0x1e, 0x23, + 0xfd, 0xe6, 0xd8, 0xdb, 0xf7, 0xf4, 0xc6, 0xff, 0x7f, 0x90, 0x23, 0x9d, 0x9b, 0x00, 0xcb, 0x4b, + 0x26, 0x7a, 0x90, 0x19, 0x72, 0xeb, 0x92, 0xdc, 0x78, 0x78, 0x87, 0x55, 0xba, 0x1a, 0xc2, 0xce, + 0x9a, 0x5b, 0xe7, 0xca, 0x6a, 0xdc, 0x7d, 0x2b, 0x6d, 0xdc, 0x5b, 0x77, 0x39, 0x7b, 0xa6, 0xa0, + 0xd3, 0x44, 0x17, 0xe9, 0x1f, 0x55, 0x3e, 0x22, 0xf4, 0xfa, 0xfa, 0x43, 0x64, 0x1e, 0xeb, 0xf9, + 0x3f, 0xe5, 0x94, 0x67, 0x0a, 0xb2, 0xa1, 0x92, 0x15, 0xf7, 0x47, 0x55, 0xff, 0x31, 0x87, 0x47, + 0xdf, 0xfc, 0xee, 0xe0, 0xd2, 0x65, 0xd3, 0xf9, 0xc5, 0xfe, 0x28, 0xf4, 0x0f, 0xc4, 0x5f, 0x32, + 0x02, 0x37, 0xb8, 0x0c, 0x28, 0x7b, 0x1f, 0x46, 0x57, 0x07, 0x5e, 0x30, 0x3e, 0x10, 0x7d, 0x73, + 0xb0, 0xf0, 0x73, 0xb1, 0x21, 0xfe, 0x38, 0xf9, 0xd3, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8d, + 0x86, 0x7a, 0x49, 0xcc, 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index d0a33cc7b8..9065715af1 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -120,11 +120,23 @@ message SendPaymentRequest { amount. */ uint32 max_shards = 17; + + /** + If set, only the final payment update is streamed back. Intermediate updates + that show which htlcs are still in flight are suppressed. + */ + bool no_inflight_updates = 18; } message TrackPaymentRequest { /// The hash of the payment to look up. bytes payment_hash = 1; + + /** + If set, only the final payment update is streamed back. Intermediate updates + that show which htlcs are still in flight are suppressed. + */ + bool no_inflight_updates = 2; } message RouteFeeRequest { diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 5a98f21234..e38c648b57 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -255,7 +255,7 @@ func (s *Server) SendPaymentV2(req *SendPaymentRequest, return err } - return s.trackPayment(payment.PaymentHash, stream) + return s.trackPayment(payment.PaymentHash, stream, req.NoInflightUpdates) } // EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it @@ -439,12 +439,12 @@ func (s *Server) TrackPaymentV2(request *TrackPaymentRequest, log.Debugf("TrackPayment called for payment %v", paymentHash) - return s.trackPayment(paymentHash, stream) + return s.trackPayment(paymentHash, stream, request.NoInflightUpdates) } // trackPayment writes payment status updates to the provided stream. func (s *Server) trackPayment(paymentHash lntypes.Hash, - stream Router_TrackPaymentV2Server) error { + stream Router_TrackPaymentV2Server, noInflightUpdates bool) error { router := s.cfg.RouterBackend @@ -470,6 +470,14 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash, return nil } result := item.(*channeldb.MPPayment) + + // Skip in-flight updates unless requested. + if noInflightUpdates && + result.Status == channeldb.StatusInFlight { + + continue + } + rpcPayment, err := router.MarshallPayment(result) if err != nil { return err From 6ffdf7ef1fa080844af9fced3a57e54d0ee22729 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 15 Apr 2020 15:59:40 +0200 Subject: [PATCH 514/562] lncli: live table-based payment updates --- cmd/lncli/cmd_pay.go | 232 ++++++++++++++++++++++++++++++++++++++----- go.mod | 5 + go.sum | 32 ++++++ 3 files changed, 244 insertions(+), 25 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 11abacbfa1..acb8f5edbc 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "context" "crypto/rand" "encoding/hex" @@ -10,7 +11,11 @@ import ( "os" "strconv" "strings" + "time" + "github.com/gosuri/uilive" + "github.com/jedib0t/go-pretty/table" + "github.com/jedib0t/go-pretty/text" "github.com/lightninglabs/protobuf-hex-display/jsonpb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" @@ -59,6 +64,11 @@ var ( "used", Value: 1, } + + jsonFlag = cli.BoolFlag{ + Name: "json", + Usage: "if set, payment updates are printed as json messages", + } ) // paymentFlags returns common flags for sendpayment and payinvoice. @@ -95,7 +105,7 @@ func paymentFlags() []cli.Flag { Name: "allow_self_payment", Usage: "allow sending a circular payment to self", }, - dataFlag, showInflightFlag, maxShardsFlag, + dataFlag, showInflightFlag, maxShardsFlag, jsonFlag, } } @@ -404,25 +414,21 @@ func sendPaymentRequest(ctx *cli.Context, return err } - for { - status, err := stream.Recv() - if err != nil { - return err - } - - printRespJSON(status) - - if status.Status != lnrpc.Payment_IN_FLIGHT { - // If we get a payment error back, we pass an error up - // to main which eventually calls fatal() and returns - // with a non-zero exit code. - if status.Status != lnrpc.Payment_SUCCEEDED { - return errors.New(status.Status.String()) - } + finalState, err := printLivePayment( + stream, client, ctx.Bool(jsonFlag.Name), + ) + if err != nil { + return err + } - return nil - } + // If we get a payment error back, we pass an error up + // to main which eventually calls fatal() and returns + // with a non-zero exit code. + if finalState.Status != lnrpc.Payment_SUCCEEDED { + return errors.New(finalState.Status.String()) } + + return nil } var trackPaymentCommand = cli.Command{ @@ -443,7 +449,7 @@ func trackPayment(ctx *cli.Context) error { conn := getClientConn(ctx, false) defer conn.Close() - client := routerrpc.NewRouterClient(conn) + routerClient := routerrpc.NewRouterClient(conn) if !args.Present() { return fmt.Errorf("hash argument missing") @@ -458,23 +464,199 @@ func trackPayment(ctx *cli.Context) error { PaymentHash: hash, } - stream, err := client.TrackPaymentV2(context.Background(), req) + stream, err := routerClient.TrackPaymentV2(context.Background(), req) if err != nil { return err } + client := lnrpc.NewLightningClient(conn) + _, err = printLivePayment(stream, client, ctx.Bool(jsonFlag.Name)) + return err +} + +// printLivePayment receives payment updates from the given stream and either +// outputs them as json or as a more user-friendly formatted table. The table +// option uses terminal control codes to rewrite the output. This call +// terminates when the payment reaches a final state. +func printLivePayment(stream routerrpc.Router_TrackPaymentV2Client, + client lnrpc.LightningClient, json bool) (*lnrpc.Payment, error) { + + // Initialize terminal (re)writer if formatted output is requested. + var writer *uilive.Writer + if !json { + writer = uilive.New() + writer.Start() + defer writer.Stop() + } + + aliases := newAliasCache(client) + + first := true for { - status, err := stream.Recv() + payment, err := stream.Recv() if err != nil { - return err + return nil, err + } + + if json { + // Delimit json messages by newlines (inspired by + // grpc over rest chunking). + if first { + first = false + } else { + fmt.Println() + } + + // Write raw json to stdout. + printRespJSON(payment) + } else { + // Write formatted table to writer. This writer will + // erase the previously written output in the terminal + // first. + table := formatPayment(payment, aliases) + _, err := writer.Write([]byte(table)) + if err != nil { + return nil, err + } + } + + // Terminate loop if payments state is final. + if payment.Status != lnrpc.Payment_IN_FLIGHT { + return payment, nil } + } +} - printRespJSON(status) +// aliasCache allows cached retrieval of node aliases. +type aliasCache struct { + cache map[string]string + client lnrpc.LightningClient +} - if status.Status != lnrpc.Payment_IN_FLIGHT { - return nil +func newAliasCache(client lnrpc.LightningClient) *aliasCache { + return &aliasCache{ + client: client, + cache: make(map[string]string), + } +} + +// get returns a node alias either from cache or freshly requested from lnd. +func (a *aliasCache) get(pubkey string) string { + alias, ok := a.cache[pubkey] + if ok { + return alias + } + + // Request node info. + resp, err := a.client.GetNodeInfo( + context.Background(), + &lnrpc.NodeInfoRequest{ + PubKey: pubkey, + }, + ) + if err != nil { + // If no info is available, use the + // pubkey as identifier. + alias = pubkey[:6] + } else { + alias = resp.Node.Alias + } + a.cache[pubkey] = alias + + return alias +} + +// formatMsat formats msat amounts as fractional sats. +func formatMsat(amt int64) string { + return strconv.FormatFloat(float64(amt)/1000.0, 'f', -1, 64) +} + +// formatPayment formats the payment state as an ascii table. +func formatPayment(payment *lnrpc.Payment, aliases *aliasCache) string { + t := table.NewWriter() + + // Build table header. + t.AppendHeader(table.Row{ + "HTLC_STATE", "ATTEMPT_TIME", "RESOLVE_TIME", "RECEIVER_AMT", + "FEE", "TIMELOCK", "CHAN_OUT", "ROUTE", + }) + t.SetColumnConfigs([]table.ColumnConfig{ + {Name: "ATTEMPT_TIME", Align: text.AlignRight}, + {Name: "RESOLVE_TIME", Align: text.AlignRight}, + {Name: "CHAN_OUT", Align: text.AlignLeft, + AlignHeader: text.AlignLeft}, + }) + + // Add all htlcs as rows. + createTime := time.Unix(0, payment.CreationTimeNs) + var totalPaid, totalFees int64 + for _, htlc := range payment.Htlcs { + formatTime := func(timeNs int64) string { + if timeNs == 0 { + return "-" + } + resolveTime := time.Unix(0, timeNs) + resolveTimeMs := resolveTime.Sub(createTime). + Milliseconds() + return fmt.Sprintf( + "%.3f", float64(resolveTimeMs)/1000.0, + ) + } + + attemptTime := formatTime(htlc.AttemptTimeNs) + resolveTime := formatTime(htlc.ResolveTimeNs) + + route := htlc.Route + lastHop := route.Hops[len(route.Hops)-1] + + hops := []string{} + for _, h := range route.Hops { + alias := aliases.get(h.PubKey) + hops = append(hops, alias) + } + + state := htlc.Status.String() + if htlc.Failure != nil { + state = fmt.Sprintf( + "%v @ %v", + htlc.Failure.Code, + htlc.Failure.FailureSourceIndex, + ) + } + + t.AppendRow([]interface{}{ + state, attemptTime, resolveTime, + formatMsat(lastHop.AmtToForwardMsat), + formatMsat(route.TotalFeesMsat), + route.TotalTimeLock, route.Hops[0].ChanId, + strings.Join(hops, "->")}, + ) + + if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED { + totalPaid += lastHop.AmtToForwardMsat + totalFees += route.TotalFeesMsat } } + + // Render table. + b := &bytes.Buffer{} + t.SetOutputMirror(b) + t.Render() + + // Add additional payment-level data. + fmt.Fprintf(b, "Amount + fee: %v + %v sat\n", + formatMsat(totalPaid), formatMsat(totalFees)) + fmt.Fprintf(b, "Payment hash: %v\n", payment.PaymentHash) + fmt.Fprintf(b, "Payment status: %v", payment.Status) + switch payment.Status { + case lnrpc.Payment_SUCCEEDED: + fmt.Fprintf(b, ", preimage: %v", payment.PaymentPreimage) + case lnrpc.Payment_FAILED: + fmt.Fprintf(b, ", reason: %v", payment.FailureReason) + } + fmt.Fprintf(b, "\n") + + return b.String() } var payInvoiceCommand = cli.Command{ diff --git a/go.mod b/go.mod index a4943762af..f5768758fb 100644 --- a/go.mod +++ b/go.mod @@ -17,12 +17,15 @@ require ( github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 github.com/davecgh/go-spew v1.1.1 github.com/go-errors/errors v1.0.1 + github.com/go-openapi/strfmt v0.19.5 // indirect github.com/golang/protobuf v1.3.1 + github.com/gosuri/uilive v0.0.4 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.8.6 github.com/jackpal/gateway v1.0.5 github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad + github.com/jedib0t/go-pretty v4.3.0+incompatible github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c // indirect @@ -40,6 +43,8 @@ require ( github.com/lightningnetwork/lnd/queue v1.0.3 github.com/lightningnetwork/lnd/ticker v1.0.0 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 github.com/prometheus/client_golang v0.9.3 github.com/rogpeppe/fastuuid v1.2.0 // indirect diff --git a/go.sum b/go.sum index c58f8025ad..9f9a86c795 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,8 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -66,6 +68,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -79,6 +82,11 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/strfmt v0.19.5 h1:0utjKrw+BAh8s57XE9Xz8DUBsVvPmRUB6styvl9wWIM= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -90,6 +98,12 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42 h1:q3pnF5JFBNRz8sRD+IRj7Y6DMyYGTNqnZ9axTbSfoNI= github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gosuri/uilive v0.0.4 h1:hUEBpQDj8D8jXgtCdBu7sWsy5sbW/5GhuO8KBwJ2jyY= +github.com/gosuri/uilive v0.0.4/go.mod h1:V/epo5LjjlDE5RJUcqx8dbw+zc93y5Ya3yg8tfZ74VI= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= @@ -102,6 +116,8 @@ github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad h1:heFfj7z0pGsNCekUlsFhO2jstxO4b5iQ665LjwM5mDc= github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo= +github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -145,10 +161,16 @@ github.com/lightningnetwork/lightning-onion v1.0.1/go.mod h1:rigfi6Af/KqsF7Za0hO github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 h1:PRMAcldsl4mXKJeRNB/KVNz6TlbS6hk2Rs42PqgU3Ws= github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -178,15 +200,23 @@ github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 h1:tcJ6OjwOMvExLlzrAVZute09ocAGa7KqOON60++Gz4E= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= github.com/urfave/cli v1.18.0 h1:m9MfmZWX7bwr9kUcs/Asr95j0IVXzGNNc+/5ku2m26Q= github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -214,6 +244,8 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7v golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 6591408a9ef7ff354b34810cfd30562482ee8df3 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 21 Apr 2020 17:30:28 -0700 Subject: [PATCH 515/562] build: bump version to bump version to v0.10.0-beta.rc3 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index 774e781207..8a55435e62 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc2" + AppPreRelease = "beta.rc3" ) func init() { From cd9c1c7746961548c6d9f1b62181199f626dc8b8 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 21 Apr 2020 18:03:57 -0700 Subject: [PATCH 516/562] Revert "lncli: live table-based payment updates" This reverts commit 6ffdf7ef1fa080844af9fced3a57e54d0ee22729. --- cmd/lncli/cmd_pay.go | 232 +++++-------------------------------------- go.mod | 5 - go.sum | 32 ------ 3 files changed, 25 insertions(+), 244 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index acb8f5edbc..11abacbfa1 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "context" "crypto/rand" "encoding/hex" @@ -11,11 +10,7 @@ import ( "os" "strconv" "strings" - "time" - "github.com/gosuri/uilive" - "github.com/jedib0t/go-pretty/table" - "github.com/jedib0t/go-pretty/text" "github.com/lightninglabs/protobuf-hex-display/jsonpb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" @@ -64,11 +59,6 @@ var ( "used", Value: 1, } - - jsonFlag = cli.BoolFlag{ - Name: "json", - Usage: "if set, payment updates are printed as json messages", - } ) // paymentFlags returns common flags for sendpayment and payinvoice. @@ -105,7 +95,7 @@ func paymentFlags() []cli.Flag { Name: "allow_self_payment", Usage: "allow sending a circular payment to self", }, - dataFlag, showInflightFlag, maxShardsFlag, jsonFlag, + dataFlag, showInflightFlag, maxShardsFlag, } } @@ -414,21 +404,25 @@ func sendPaymentRequest(ctx *cli.Context, return err } - finalState, err := printLivePayment( - stream, client, ctx.Bool(jsonFlag.Name), - ) - if err != nil { - return err - } + for { + status, err := stream.Recv() + if err != nil { + return err + } - // If we get a payment error back, we pass an error up - // to main which eventually calls fatal() and returns - // with a non-zero exit code. - if finalState.Status != lnrpc.Payment_SUCCEEDED { - return errors.New(finalState.Status.String()) - } + printRespJSON(status) - return nil + if status.Status != lnrpc.Payment_IN_FLIGHT { + // If we get a payment error back, we pass an error up + // to main which eventually calls fatal() and returns + // with a non-zero exit code. + if status.Status != lnrpc.Payment_SUCCEEDED { + return errors.New(status.Status.String()) + } + + return nil + } + } } var trackPaymentCommand = cli.Command{ @@ -449,7 +443,7 @@ func trackPayment(ctx *cli.Context) error { conn := getClientConn(ctx, false) defer conn.Close() - routerClient := routerrpc.NewRouterClient(conn) + client := routerrpc.NewRouterClient(conn) if !args.Present() { return fmt.Errorf("hash argument missing") @@ -464,199 +458,23 @@ func trackPayment(ctx *cli.Context) error { PaymentHash: hash, } - stream, err := routerClient.TrackPaymentV2(context.Background(), req) + stream, err := client.TrackPaymentV2(context.Background(), req) if err != nil { return err } - client := lnrpc.NewLightningClient(conn) - _, err = printLivePayment(stream, client, ctx.Bool(jsonFlag.Name)) - return err -} - -// printLivePayment receives payment updates from the given stream and either -// outputs them as json or as a more user-friendly formatted table. The table -// option uses terminal control codes to rewrite the output. This call -// terminates when the payment reaches a final state. -func printLivePayment(stream routerrpc.Router_TrackPaymentV2Client, - client lnrpc.LightningClient, json bool) (*lnrpc.Payment, error) { - - // Initialize terminal (re)writer if formatted output is requested. - var writer *uilive.Writer - if !json { - writer = uilive.New() - writer.Start() - defer writer.Stop() - } - - aliases := newAliasCache(client) - - first := true for { - payment, err := stream.Recv() + status, err := stream.Recv() if err != nil { - return nil, err - } - - if json { - // Delimit json messages by newlines (inspired by - // grpc over rest chunking). - if first { - first = false - } else { - fmt.Println() - } - - // Write raw json to stdout. - printRespJSON(payment) - } else { - // Write formatted table to writer. This writer will - // erase the previously written output in the terminal - // first. - table := formatPayment(payment, aliases) - _, err := writer.Write([]byte(table)) - if err != nil { - return nil, err - } - } - - // Terminate loop if payments state is final. - if payment.Status != lnrpc.Payment_IN_FLIGHT { - return payment, nil - } - } -} - -// aliasCache allows cached retrieval of node aliases. -type aliasCache struct { - cache map[string]string - client lnrpc.LightningClient -} - -func newAliasCache(client lnrpc.LightningClient) *aliasCache { - return &aliasCache{ - client: client, - cache: make(map[string]string), - } -} - -// get returns a node alias either from cache or freshly requested from lnd. -func (a *aliasCache) get(pubkey string) string { - alias, ok := a.cache[pubkey] - if ok { - return alias - } - - // Request node info. - resp, err := a.client.GetNodeInfo( - context.Background(), - &lnrpc.NodeInfoRequest{ - PubKey: pubkey, - }, - ) - if err != nil { - // If no info is available, use the - // pubkey as identifier. - alias = pubkey[:6] - } else { - alias = resp.Node.Alias - } - a.cache[pubkey] = alias - - return alias -} - -// formatMsat formats msat amounts as fractional sats. -func formatMsat(amt int64) string { - return strconv.FormatFloat(float64(amt)/1000.0, 'f', -1, 64) -} - -// formatPayment formats the payment state as an ascii table. -func formatPayment(payment *lnrpc.Payment, aliases *aliasCache) string { - t := table.NewWriter() - - // Build table header. - t.AppendHeader(table.Row{ - "HTLC_STATE", "ATTEMPT_TIME", "RESOLVE_TIME", "RECEIVER_AMT", - "FEE", "TIMELOCK", "CHAN_OUT", "ROUTE", - }) - t.SetColumnConfigs([]table.ColumnConfig{ - {Name: "ATTEMPT_TIME", Align: text.AlignRight}, - {Name: "RESOLVE_TIME", Align: text.AlignRight}, - {Name: "CHAN_OUT", Align: text.AlignLeft, - AlignHeader: text.AlignLeft}, - }) - - // Add all htlcs as rows. - createTime := time.Unix(0, payment.CreationTimeNs) - var totalPaid, totalFees int64 - for _, htlc := range payment.Htlcs { - formatTime := func(timeNs int64) string { - if timeNs == 0 { - return "-" - } - resolveTime := time.Unix(0, timeNs) - resolveTimeMs := resolveTime.Sub(createTime). - Milliseconds() - return fmt.Sprintf( - "%.3f", float64(resolveTimeMs)/1000.0, - ) - } - - attemptTime := formatTime(htlc.AttemptTimeNs) - resolveTime := formatTime(htlc.ResolveTimeNs) - - route := htlc.Route - lastHop := route.Hops[len(route.Hops)-1] - - hops := []string{} - for _, h := range route.Hops { - alias := aliases.get(h.PubKey) - hops = append(hops, alias) - } - - state := htlc.Status.String() - if htlc.Failure != nil { - state = fmt.Sprintf( - "%v @ %v", - htlc.Failure.Code, - htlc.Failure.FailureSourceIndex, - ) + return err } - t.AppendRow([]interface{}{ - state, attemptTime, resolveTime, - formatMsat(lastHop.AmtToForwardMsat), - formatMsat(route.TotalFeesMsat), - route.TotalTimeLock, route.Hops[0].ChanId, - strings.Join(hops, "->")}, - ) + printRespJSON(status) - if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED { - totalPaid += lastHop.AmtToForwardMsat - totalFees += route.TotalFeesMsat + if status.Status != lnrpc.Payment_IN_FLIGHT { + return nil } } - - // Render table. - b := &bytes.Buffer{} - t.SetOutputMirror(b) - t.Render() - - // Add additional payment-level data. - fmt.Fprintf(b, "Amount + fee: %v + %v sat\n", - formatMsat(totalPaid), formatMsat(totalFees)) - fmt.Fprintf(b, "Payment hash: %v\n", payment.PaymentHash) - fmt.Fprintf(b, "Payment status: %v", payment.Status) - switch payment.Status { - case lnrpc.Payment_SUCCEEDED: - fmt.Fprintf(b, ", preimage: %v", payment.PaymentPreimage) - case lnrpc.Payment_FAILED: - fmt.Fprintf(b, ", reason: %v", payment.FailureReason) - } - fmt.Fprintf(b, "\n") - - return b.String() } var payInvoiceCommand = cli.Command{ diff --git a/go.mod b/go.mod index f5768758fb..a4943762af 100644 --- a/go.mod +++ b/go.mod @@ -17,15 +17,12 @@ require ( github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 github.com/davecgh/go-spew v1.1.1 github.com/go-errors/errors v1.0.1 - github.com/go-openapi/strfmt v0.19.5 // indirect github.com/golang/protobuf v1.3.1 - github.com/gosuri/uilive v0.0.4 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.8.6 github.com/jackpal/gateway v1.0.5 github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad - github.com/jedib0t/go-pretty v4.3.0+incompatible github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c // indirect @@ -43,8 +40,6 @@ require ( github.com/lightningnetwork/lnd/queue v1.0.3 github.com/lightningnetwork/lnd/ticker v1.0.0 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 - github.com/mattn/go-isatty v0.0.12 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 github.com/prometheus/client_golang v0.9.3 github.com/rogpeppe/fastuuid v1.2.0 // indirect diff --git a/go.sum b/go.sum index 9f9a86c795..c58f8025ad 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,6 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -68,7 +66,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -82,11 +79,6 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY= -github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/strfmt v0.19.5 h1:0utjKrw+BAh8s57XE9Xz8DUBsVvPmRUB6styvl9wWIM= -github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -98,12 +90,6 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42 h1:q3pnF5JFBNRz8sRD+IRj7Y6DMyYGTNqnZ9axTbSfoNI= github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gosuri/uilive v0.0.4 h1:hUEBpQDj8D8jXgtCdBu7sWsy5sbW/5GhuO8KBwJ2jyY= -github.com/gosuri/uilive v0.0.4/go.mod h1:V/epo5LjjlDE5RJUcqx8dbw+zc93y5Ya3yg8tfZ74VI= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= @@ -116,8 +102,6 @@ github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad h1:heFfj7z0pGsNCekUlsFhO2jstxO4b5iQ665LjwM5mDc= github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo= -github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -161,16 +145,10 @@ github.com/lightningnetwork/lightning-onion v1.0.1/go.mod h1:rigfi6Af/KqsF7Za0hO github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 h1:PRMAcldsl4mXKJeRNB/KVNz6TlbS6hk2Rs42PqgU3Ws= github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -200,23 +178,15 @@ github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 h1:tcJ6OjwOMvExLlzrAVZute09ocAGa7KqOON60++Gz4E= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= github.com/urfave/cli v1.18.0 h1:m9MfmZWX7bwr9kUcs/Asr95j0IVXzGNNc+/5ku2m26Q= github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU= -go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -244,8 +214,6 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7v golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 0bc05f9d6552c82bb1347f735f5a0c801ec5c551 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 21 Apr 2020 18:12:46 -0700 Subject: [PATCH 517/562] build: bump version to bump version to v0.10.0-beta.rc4 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index 8a55435e62..c3bb8603e8 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc3" + AppPreRelease = "beta.rc4" ) func init() { From ce0a61abeb20ed0bd257fe3ea210434771d7dff2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 21 Apr 2020 22:16:05 -0700 Subject: [PATCH 518/562] lnrpc/invoicesrpc: linter fix --- lnrpc/invoicesrpc/addinvoice.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index c027208a6c..171e85b7b1 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -162,9 +162,9 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, switch { // The value of the invoice must not be negative. - case invoice.Value < 0: + case int64(invoice.Value) < 0: return nil, nil, fmt.Errorf("payments of negative value "+ - "are not allowed, value is %v", invoice.Value) + "are not allowed, value is %v", int64(invoice.Value)) // Also ensure that the invoice is actually realistic, while preventing // any issues due to underflow. From 8d7e07d96be5c38ccf1e158935902366cb3f8cc3 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 15 Apr 2020 15:59:40 +0200 Subject: [PATCH 519/562] lncli: live table-based payment updates --- cmd/lncli/cmd_pay.go | 261 ++++++++++++++++++++++++++++++++++++++----- go.mod | 4 + go.sum | 28 +++++ 3 files changed, 264 insertions(+), 29 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 11abacbfa1..3388a4b9ec 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "context" "crypto/rand" "encoding/hex" @@ -8,9 +9,13 @@ import ( "fmt" "io/ioutil" "os" + "runtime" "strconv" "strings" + "time" + "github.com/jedib0t/go-pretty/table" + "github.com/jedib0t/go-pretty/text" "github.com/lightninglabs/protobuf-hex-display/jsonpb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" @@ -47,10 +52,10 @@ var ( "Custom record ids start from 65536.", } - showInflightFlag = cli.BoolFlag{ - Name: "show_inflight", + inflightUpdatesFlag = cli.BoolFlag{ + Name: "inflight_updates", Usage: "if set, intermediate payment state updates will be " + - "displayed", + "displayed. Only valid in combination with --json.", } maxShardsFlag = cli.UintFlag{ @@ -59,6 +64,13 @@ var ( "used", Value: 1, } + + jsonFlag = cli.BoolFlag{ + Name: "json", + Usage: "if set, payment updates are printed as json " + + "messages. Set by default on Windows because table " + + "formatting is unsupported.", + } ) // paymentFlags returns common flags for sendpayment and payinvoice. @@ -95,7 +107,7 @@ func paymentFlags() []cli.Flag { Name: "allow_self_payment", Usage: "allow sending a circular payment to self", }, - dataFlag, showInflightFlag, maxShardsFlag, + dataFlag, inflightUpdatesFlag, maxShardsFlag, jsonFlag, } } @@ -397,32 +409,30 @@ func sendPaymentRequest(ctx *cli.Context, req.FeeLimitSat = feeLimit - req.NoInflightUpdates = !ctx.Bool(showInflightFlag.Name) + // Always print in-flight updates for the table output. + printJSON := ctx.Bool(jsonFlag.Name) + req.NoInflightUpdates = !ctx.Bool(inflightUpdatesFlag.Name) && printJSON stream, err := routerClient.SendPaymentV2(context.Background(), req) if err != nil { return err } - for { - status, err := stream.Recv() - if err != nil { - return err - } - - printRespJSON(status) - - if status.Status != lnrpc.Payment_IN_FLIGHT { - // If we get a payment error back, we pass an error up - // to main which eventually calls fatal() and returns - // with a non-zero exit code. - if status.Status != lnrpc.Payment_SUCCEEDED { - return errors.New(status.Status.String()) - } + finalState, err := printLivePayment( + stream, client, printJSON, + ) + if err != nil { + return err + } - return nil - } + // If we get a payment error back, we pass an error up + // to main which eventually calls fatal() and returns + // with a non-zero exit code. + if finalState.Status != lnrpc.Payment_SUCCEEDED { + return errors.New(finalState.Status.String()) } + + return nil } var trackPaymentCommand = cli.Command{ @@ -443,7 +453,7 @@ func trackPayment(ctx *cli.Context) error { conn := getClientConn(ctx, false) defer conn.Close() - client := routerrpc.NewRouterClient(conn) + routerClient := routerrpc.NewRouterClient(conn) if !args.Present() { return fmt.Errorf("hash argument missing") @@ -458,25 +468,206 @@ func trackPayment(ctx *cli.Context) error { PaymentHash: hash, } - stream, err := client.TrackPaymentV2(context.Background(), req) + stream, err := routerClient.TrackPaymentV2(context.Background(), req) if err != nil { return err } + client := lnrpc.NewLightningClient(conn) + _, err = printLivePayment(stream, client, ctx.Bool(jsonFlag.Name)) + return err +} + +// printLivePayment receives payment updates from the given stream and either +// outputs them as json or as a more user-friendly formatted table. The table +// option uses terminal control codes to rewrite the output. This call +// terminates when the payment reaches a final state. +func printLivePayment(stream routerrpc.Router_TrackPaymentV2Client, + client lnrpc.LightningClient, json bool) (*lnrpc.Payment, error) { + + // Terminal escape codes aren't supported on Windows, fall back to json. + if !json && runtime.GOOS == "windows" { + json = true + } + + aliases := newAliasCache(client) + + first := true + var lastLineCount int for { - status, err := stream.Recv() + payment, err := stream.Recv() if err != nil { - return err + return nil, err } - printRespJSON(status) + if json { + // Delimit json messages by newlines (inspired by + // grpc over rest chunking). + if first { + first = false + } else { + fmt.Println() + } - if status.Status != lnrpc.Payment_IN_FLIGHT { - return nil + // Write raw json to stdout. + printRespJSON(payment) + } else { + table := formatPayment(payment, aliases) + + // Clear all previously written lines and print the + // updated table. + clearLines(lastLineCount) + fmt.Print(table) + + // Store the number of lines written for the next update + // pass. + lastLineCount = 0 + for _, b := range table { + if b == '\n' { + lastLineCount++ + } + } } + + // Terminate loop if payments state is final. + if payment.Status != lnrpc.Payment_IN_FLIGHT { + return payment, nil + } + } +} + +// aliasCache allows cached retrieval of node aliases. +type aliasCache struct { + cache map[string]string + client lnrpc.LightningClient +} + +func newAliasCache(client lnrpc.LightningClient) *aliasCache { + return &aliasCache{ + client: client, + cache: make(map[string]string), } } +// get returns a node alias either from cache or freshly requested from lnd. +func (a *aliasCache) get(pubkey string) string { + alias, ok := a.cache[pubkey] + if ok { + return alias + } + + // Request node info. + resp, err := a.client.GetNodeInfo( + context.Background(), + &lnrpc.NodeInfoRequest{ + PubKey: pubkey, + }, + ) + if err != nil { + // If no info is available, use the + // pubkey as identifier. + alias = pubkey[:6] + } else { + alias = resp.Node.Alias + } + a.cache[pubkey] = alias + + return alias +} + +// formatMsat formats msat amounts as fractional sats. +func formatMsat(amt int64) string { + return strconv.FormatFloat(float64(amt)/1000.0, 'f', -1, 64) +} + +// formatPayment formats the payment state as an ascii table. +func formatPayment(payment *lnrpc.Payment, aliases *aliasCache) string { + t := table.NewWriter() + + // Build table header. + t.AppendHeader(table.Row{ + "HTLC_STATE", "ATTEMPT_TIME", "RESOLVE_TIME", "RECEIVER_AMT", + "FEE", "TIMELOCK", "CHAN_OUT", "ROUTE", + }) + t.SetColumnConfigs([]table.ColumnConfig{ + {Name: "ATTEMPT_TIME", Align: text.AlignRight}, + {Name: "RESOLVE_TIME", Align: text.AlignRight}, + {Name: "CHAN_OUT", Align: text.AlignLeft, + AlignHeader: text.AlignLeft}, + }) + + // Add all htlcs as rows. + createTime := time.Unix(0, payment.CreationTimeNs) + var totalPaid, totalFees int64 + for _, htlc := range payment.Htlcs { + formatTime := func(timeNs int64) string { + if timeNs == 0 { + return "-" + } + resolveTime := time.Unix(0, timeNs) + resolveTimeMs := resolveTime.Sub(createTime). + Milliseconds() + return fmt.Sprintf( + "%.3f", float64(resolveTimeMs)/1000.0, + ) + } + + attemptTime := formatTime(htlc.AttemptTimeNs) + resolveTime := formatTime(htlc.ResolveTimeNs) + + route := htlc.Route + lastHop := route.Hops[len(route.Hops)-1] + + hops := []string{} + for _, h := range route.Hops { + alias := aliases.get(h.PubKey) + hops = append(hops, alias) + } + + state := htlc.Status.String() + if htlc.Failure != nil { + state = fmt.Sprintf( + "%v @ %v", + htlc.Failure.Code, + htlc.Failure.FailureSourceIndex, + ) + } + + t.AppendRow([]interface{}{ + state, attemptTime, resolveTime, + formatMsat(lastHop.AmtToForwardMsat), + formatMsat(route.TotalFeesMsat), + route.TotalTimeLock, route.Hops[0].ChanId, + strings.Join(hops, "->")}, + ) + + if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED { + totalPaid += lastHop.AmtToForwardMsat + totalFees += route.TotalFeesMsat + } + } + + // Render table. + b := &bytes.Buffer{} + t.SetOutputMirror(b) + t.Render() + + // Add additional payment-level data. + fmt.Fprintf(b, "Amount + fee: %v + %v sat\n", + formatMsat(totalPaid), formatMsat(totalFees)) + fmt.Fprintf(b, "Payment hash: %v\n", payment.PaymentHash) + fmt.Fprintf(b, "Payment status: %v", payment.Status) + switch payment.Status { + case lnrpc.Payment_SUCCEEDED: + fmt.Fprintf(b, ", preimage: %v", payment.PaymentPreimage) + case lnrpc.Payment_FAILED: + fmt.Fprintf(b, ", reason: %v", payment.FailureReason) + } + fmt.Fprintf(b, "\n") + + return b.String() +} + var payInvoiceCommand = cli.Command{ Name: "payinvoice", Category: "Payments", @@ -672,3 +863,15 @@ func sendToRouteRequest(ctx *cli.Context, req *lnrpc.SendToRouteRequest) error { return nil } + +// ESC is the ASCII code for escape character +const ESC = 27 + +// clearCode defines a terminal escape code to clear the currently line and move +// the cursor up. +var clearCode = fmt.Sprintf("%c[%dA%c[2K", ESC, 1, ESC) + +// clearLines erases the last count lines in the terminal window. +func clearLines(count int) { + _, _ = fmt.Print(strings.Repeat(clearCode, count)) +} diff --git a/go.mod b/go.mod index a4943762af..e5f42da921 100644 --- a/go.mod +++ b/go.mod @@ -17,12 +17,14 @@ require ( github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 github.com/davecgh/go-spew v1.1.1 github.com/go-errors/errors v1.0.1 + github.com/go-openapi/strfmt v0.19.5 // indirect github.com/golang/protobuf v1.3.1 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.8.6 github.com/jackpal/gateway v1.0.5 github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad + github.com/jedib0t/go-pretty v4.3.0+incompatible github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c // indirect @@ -40,6 +42,7 @@ require ( github.com/lightningnetwork/lnd/queue v1.0.3 github.com/lightningnetwork/lnd/ticker v1.0.0 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 github.com/prometheus/client_golang v0.9.3 github.com/rogpeppe/fastuuid v1.2.0 // indirect @@ -47,6 +50,7 @@ require ( github.com/urfave/cli v1.18.0 golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 + golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 google.golang.org/grpc v1.19.0 diff --git a/go.sum b/go.sum index c58f8025ad..85a5e1559a 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,8 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -66,6 +68,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -79,6 +82,11 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/strfmt v0.19.5 h1:0utjKrw+BAh8s57XE9Xz8DUBsVvPmRUB6styvl9wWIM= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -90,6 +98,10 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42 h1:q3pnF5JFBNRz8sRD+IRj7Y6DMyYGTNqnZ9axTbSfoNI= github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= @@ -102,6 +114,8 @@ github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad h1:heFfj7z0pGsNCekUlsFhO2jstxO4b5iQ665LjwM5mDc= github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo= +github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -145,10 +159,14 @@ github.com/lightningnetwork/lightning-onion v1.0.1/go.mod h1:rigfi6Af/KqsF7Za0hO github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 h1:PRMAcldsl4mXKJeRNB/KVNz6TlbS6hk2Rs42PqgU3Ws= github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -178,15 +196,23 @@ github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 h1:tcJ6OjwOMvExLlzrAVZute09ocAGa7KqOON60++Gz4E= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= github.com/urfave/cli v1.18.0 h1:m9MfmZWX7bwr9kUcs/Asr95j0IVXzGNNc+/5ku2m26Q= github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -214,6 +240,8 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7v golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From f6b2410011359f6c38b23b7c51962e2c20b94fed Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 22 Apr 2020 09:19:11 +0200 Subject: [PATCH 520/562] routing+routerrpc: rename max_shards to max_parts Don't introduce a new term and align with the P in MPP. --- cmd/lncli/cmd_pay.go | 8 +- lnrpc/routerrpc/router.pb.go | 290 ++++++++++---------- lnrpc/routerrpc/router.proto | 2 +- lnrpc/routerrpc/router_backend.go | 8 +- lnrpc/routerrpc/router_server_deprecated.go | 2 +- lntest/itest/lnd_send_multi_path_payment.go | 2 +- routing/integrated_routing_context_test.go | 4 +- routing/integrated_routing_test.go | 12 +- routing/payment_session.go | 4 +- routing/router.go | 4 +- rpcserver.go | 2 +- 11 files changed, 169 insertions(+), 169 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 3388a4b9ec..a90330b558 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -58,8 +58,8 @@ var ( "displayed. Only valid in combination with --json.", } - maxShardsFlag = cli.UintFlag{ - Name: "max_shards", + maxPartsFlag = cli.UintFlag{ + Name: "max_parts", Usage: "the maximum number of partial payments that may be " + "used", Value: 1, @@ -107,7 +107,7 @@ func paymentFlags() []cli.Flag { Name: "allow_self_payment", Usage: "allow sending a circular payment to self", }, - dataFlag, inflightUpdatesFlag, maxShardsFlag, jsonFlag, + dataFlag, inflightUpdatesFlag, maxPartsFlag, jsonFlag, } } @@ -337,7 +337,7 @@ func sendPaymentRequest(ctx *cli.Context, req.AllowSelfPayment = ctx.Bool("allow_self_payment") - req.MaxShards = uint32(ctx.Uint(maxShardsFlag.Name)) + req.MaxParts = uint32(ctx.Uint(maxPartsFlag.Name)) // Parse custom data records. data := ctx.String(dataFlag.Name) diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 2b2ed2d846..ae57eacdf9 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -281,7 +281,7 @@ type SendPaymentRequest struct { //* //The maximum number of partial payments that may be use to complete the full //amount. - MaxShards uint32 `protobuf:"varint,17,opt,name=max_shards,json=maxShards,proto3" json:"max_shards,omitempty"` + MaxParts uint32 `protobuf:"varint,17,opt,name=max_parts,json=maxParts,proto3" json:"max_parts,omitempty"` //* //If set, only the final payment update is streamed back. Intermediate updates //that show which htlcs are still in flight are suppressed. @@ -428,9 +428,9 @@ func (m *SendPaymentRequest) GetDestFeatures() []lnrpc.FeatureBit { return nil } -func (m *SendPaymentRequest) GetMaxShards() uint32 { +func (m *SendPaymentRequest) GetMaxParts() uint32 { if m != nil { - return m.MaxShards + return m.MaxParts } return 0 } @@ -1746,148 +1746,148 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2247 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0x4d, 0x77, 0xdb, 0xc6, - 0xd5, 0x0e, 0x48, 0x50, 0x22, 0x2f, 0x3f, 0x04, 0x8d, 0x1c, 0x99, 0x2f, 0x65, 0x27, 0x0c, 0xde, - 0xc4, 0xe6, 0x71, 0x1d, 0xc9, 0x51, 0x7b, 0xda, 0x9c, 0xb6, 0x49, 0x4b, 0x91, 0x90, 0x05, 0x9b, - 0x02, 0x98, 0x21, 0x25, 0xdb, 0xf5, 0x62, 0x0e, 0x44, 0x0e, 0x45, 0x54, 0xf8, 0x60, 0x81, 0xa1, - 0x1d, 0x2d, 0xbb, 0xeb, 0xe9, 0xb6, 0x3f, 0xa2, 0xbb, 0xfe, 0x82, 0xee, 0xfb, 0x33, 0xba, 0xed, - 0x2f, 0xe8, 0xba, 0x67, 0x06, 0x03, 0x12, 0x94, 0x28, 0xbb, 0xdd, 0xd8, 0xc4, 0x73, 0x9f, 0xb9, - 0x73, 0xef, 0xdc, 0xe7, 0xce, 0x87, 0x60, 0x37, 0x0a, 0xe7, 0x8c, 0x46, 0xd1, 0x6c, 0x74, 0x90, - 0xfc, 0xda, 0x9f, 0x45, 0x21, 0x0b, 0x51, 0x69, 0x81, 0x37, 0x4a, 0xd1, 0x6c, 0x94, 0xa0, 0xfa, - 0x3f, 0x36, 0x00, 0x0d, 0x68, 0x30, 0xee, 0x3b, 0xd7, 0x3e, 0x0d, 0x18, 0xa6, 0x7f, 0x98, 0xd3, - 0x98, 0x21, 0x04, 0xea, 0x98, 0xc6, 0xac, 0xae, 0x34, 0x95, 0x56, 0x05, 0x8b, 0xdf, 0x48, 0x83, - 0xbc, 0xe3, 0xb3, 0x7a, 0xae, 0xa9, 0xb4, 0xf2, 0x98, 0xff, 0x44, 0xff, 0x07, 0x45, 0xc7, 0x67, - 0xc4, 0x8f, 0x1d, 0x56, 0xaf, 0x08, 0x78, 0xd3, 0xf1, 0xd9, 0x69, 0xec, 0x30, 0xf4, 0x05, 0x54, - 0x66, 0x89, 0x4b, 0x32, 0x75, 0xe2, 0x69, 0x3d, 0x2f, 0x1c, 0x95, 0x25, 0x76, 0xe2, 0xc4, 0x53, - 0xd4, 0x02, 0x6d, 0xe2, 0x06, 0x8e, 0x47, 0x46, 0x1e, 0x7b, 0x47, 0xc6, 0xd4, 0x63, 0x4e, 0x5d, - 0x6d, 0x2a, 0xad, 0x02, 0xae, 0x09, 0xbc, 0xe3, 0xb1, 0x77, 0x5d, 0x8e, 0xa2, 0xc7, 0xb0, 0x95, - 0x3a, 0x8b, 0x92, 0x00, 0xeb, 0x85, 0xa6, 0xd2, 0x2a, 0xe1, 0xda, 0x6c, 0x35, 0xec, 0xc7, 0xb0, - 0xc5, 0x5c, 0x9f, 0x86, 0x73, 0x46, 0x62, 0x3a, 0x0a, 0x83, 0x71, 0x5c, 0xdf, 0x48, 0x3c, 0x4a, - 0x78, 0x90, 0xa0, 0x48, 0x87, 0xea, 0x84, 0x52, 0xe2, 0xb9, 0xbe, 0xcb, 0x08, 0x0f, 0x7f, 0x53, - 0x84, 0x5f, 0x9e, 0x50, 0xda, 0xe3, 0xd8, 0xc0, 0x61, 0xe8, 0x4b, 0xa8, 0x2d, 0x39, 0x22, 0xc7, - 0xaa, 0x20, 0x55, 0x52, 0x92, 0x48, 0xf4, 0x29, 0x68, 0xe1, 0x9c, 0x5d, 0x86, 0x6e, 0x70, 0x49, - 0x46, 0x53, 0x27, 0x20, 0xee, 0xb8, 0x5e, 0x6c, 0x2a, 0x2d, 0xf5, 0x28, 0xf7, 0x4c, 0xc1, 0xb5, - 0xd4, 0xd6, 0x99, 0x3a, 0x81, 0x39, 0x46, 0x8f, 0x60, 0xcb, 0x73, 0x62, 0x46, 0xa6, 0xe1, 0x8c, - 0xcc, 0xe6, 0x17, 0x57, 0xf4, 0xba, 0x5e, 0x13, 0x2b, 0x53, 0xe5, 0xf0, 0x49, 0x38, 0xeb, 0x0b, - 0x10, 0x3d, 0x04, 0x10, 0xab, 0x22, 0x26, 0xaf, 0x97, 0x44, 0x0e, 0x25, 0x8e, 0x88, 0x89, 0xd1, - 0x37, 0x50, 0x16, 0xd5, 0x24, 0x53, 0x37, 0x60, 0x71, 0x1d, 0x9a, 0xf9, 0x56, 0xf9, 0x50, 0xdb, - 0xf7, 0x02, 0x5e, 0x58, 0xcc, 0x2d, 0x27, 0x6e, 0xc0, 0x30, 0x44, 0xe9, 0xcf, 0x18, 0x8d, 0x61, - 0x87, 0x57, 0x91, 0x8c, 0xe6, 0x31, 0x0b, 0x7d, 0x12, 0xd1, 0x51, 0x18, 0x8d, 0xe3, 0x7a, 0x59, - 0x0c, 0xfd, 0xd9, 0xfe, 0x42, 0x1c, 0xfb, 0xb7, 0xd5, 0xb0, 0xdf, 0xa5, 0x31, 0xeb, 0x88, 0x71, - 0x38, 0x19, 0x66, 0x04, 0x2c, 0xba, 0xc6, 0xdb, 0xe3, 0x9b, 0x38, 0x7a, 0x0a, 0xc8, 0xf1, 0xbc, - 0xf0, 0x3d, 0x89, 0xa9, 0x37, 0x21, 0xb2, 0x3a, 0xf5, 0xad, 0xa6, 0xd2, 0x2a, 0x62, 0x4d, 0x58, - 0x06, 0xd4, 0x9b, 0x48, 0xf7, 0xe8, 0xe7, 0x50, 0x15, 0x31, 0x4d, 0xa8, 0xc3, 0xe6, 0x11, 0x8d, - 0xeb, 0x5a, 0x33, 0xdf, 0xaa, 0x1d, 0x6e, 0xcb, 0x44, 0x8e, 0x13, 0xf8, 0xc8, 0x65, 0xb8, 0xc2, - 0x79, 0xf2, 0x3b, 0xe6, 0xab, 0xe3, 0x3b, 0x3f, 0x92, 0x78, 0xea, 0xf0, 0x14, 0xb6, 0x9b, 0x4a, - 0xab, 0x8a, 0x4b, 0xbe, 0xf3, 0xe3, 0x40, 0x00, 0x68, 0x1f, 0x76, 0x82, 0x90, 0xb8, 0xc1, 0xc4, - 0x73, 0x2f, 0xa7, 0x8c, 0xcc, 0x67, 0x63, 0x87, 0xd1, 0xb8, 0x8e, 0x44, 0x14, 0xdb, 0x41, 0x68, - 0x4a, 0xcb, 0x59, 0x62, 0x68, 0x74, 0x61, 0x77, 0x7d, 0x86, 0x5c, 0xf2, 0xbc, 0x44, 0xbc, 0x0b, - 0x54, 0xcc, 0x7f, 0xa2, 0x7b, 0x50, 0x78, 0xe7, 0x78, 0x73, 0x2a, 0xda, 0xa0, 0x82, 0x93, 0x8f, - 0x5f, 0xe6, 0xbe, 0x55, 0xf4, 0x29, 0xec, 0x0c, 0x23, 0x67, 0x74, 0x75, 0xa3, 0x93, 0x6e, 0x36, - 0x82, 0x72, 0xbb, 0x11, 0xee, 0x88, 0x37, 0x77, 0x47, 0xbc, 0xfa, 0xf7, 0xb0, 0x25, 0x6a, 0x7c, - 0x4c, 0xe9, 0x87, 0xfa, 0xf5, 0x3e, 0xf0, 0x6e, 0x14, 0xea, 0x4e, 0x7a, 0x76, 0xc3, 0xf1, 0xb9, - 0xb0, 0xf5, 0x31, 0x68, 0xcb, 0xf1, 0xf1, 0x2c, 0x0c, 0x62, 0xca, 0x9b, 0x91, 0x4b, 0x80, 0xab, - 0x98, 0x8b, 0x5e, 0xc8, 0x5d, 0x11, 0xa3, 0x6a, 0x12, 0x3f, 0xa6, 0x54, 0x08, 0xfe, 0x51, 0xd2, - 0x63, 0xc4, 0x0b, 0x47, 0x57, 0xbc, 0x6b, 0x9d, 0x6b, 0xe9, 0xbe, 0xca, 0xe1, 0x5e, 0x38, 0xba, - 0xea, 0x72, 0x50, 0x7f, 0x9b, 0x6c, 0x2c, 0xc3, 0x50, 0xcc, 0xf5, 0x3f, 0x2c, 0x87, 0x0e, 0x05, - 0xa1, 0x46, 0xe1, 0xb6, 0x7c, 0x58, 0xc9, 0xca, 0x1a, 0x27, 0x26, 0xfd, 0x2d, 0xec, 0xac, 0x38, - 0x97, 0x59, 0x34, 0xa0, 0x38, 0x8b, 0xa8, 0xeb, 0x3b, 0x97, 0x54, 0x7a, 0x5e, 0x7c, 0xa3, 0x16, - 0x6c, 0x4e, 0x1c, 0xd7, 0x9b, 0x47, 0xa9, 0xe3, 0x5a, 0x2a, 0xb3, 0x04, 0xc5, 0xa9, 0x59, 0x7f, - 0x00, 0x0d, 0x4c, 0x63, 0xca, 0x4e, 0xdd, 0x38, 0x76, 0xc3, 0xa0, 0x13, 0x06, 0x2c, 0x0a, 0x3d, - 0x99, 0x81, 0xfe, 0x10, 0xf6, 0xd6, 0x5a, 0x93, 0x10, 0xf8, 0xe0, 0x1f, 0xe6, 0x34, 0xba, 0x5e, - 0x3f, 0xf8, 0x07, 0xd8, 0x5b, 0x6b, 0x95, 0xf1, 0x3f, 0x85, 0xc2, 0xcc, 0x71, 0x23, 0x5e, 0x7b, - 0xde, 0x96, 0xbb, 0x99, 0xb6, 0xec, 0x3b, 0x6e, 0x74, 0xe2, 0xc6, 0x2c, 0x8c, 0xae, 0x71, 0x42, - 0x7a, 0xa1, 0x16, 0x15, 0x2d, 0xa7, 0xff, 0x59, 0x81, 0x72, 0xc6, 0x88, 0xf6, 0xa0, 0x14, 0x84, - 0x63, 0x4a, 0x26, 0x51, 0xe8, 0xa7, 0x8b, 0xc0, 0x81, 0xe3, 0x28, 0xf4, 0xb9, 0x26, 0x84, 0x91, - 0x85, 0x52, 0xc0, 0x1b, 0xfc, 0x73, 0x18, 0xa2, 0xaf, 0x61, 0x73, 0x9a, 0x38, 0x10, 0x5b, 0x61, - 0xf9, 0x70, 0xe7, 0xc6, 0xdc, 0x5d, 0x87, 0x39, 0x38, 0xe5, 0xbc, 0x50, 0x8b, 0x79, 0x4d, 0x7d, - 0xa1, 0x16, 0x55, 0xad, 0xf0, 0x42, 0x2d, 0x16, 0xb4, 0x8d, 0x17, 0x6a, 0x71, 0x43, 0xdb, 0xd4, - 0xff, 0xa5, 0x40, 0x31, 0x65, 0xf3, 0x48, 0xf8, 0x92, 0x12, 0xae, 0x0b, 0x29, 0xa6, 0x22, 0x07, - 0x86, 0xae, 0x4f, 0x51, 0x13, 0x2a, 0xc2, 0xb8, 0x2a, 0x51, 0xe0, 0x58, 0x5b, 0xc8, 0x54, 0xec, - 0xd1, 0x29, 0x43, 0xe8, 0x51, 0x95, 0x7b, 0x74, 0x42, 0x49, 0x8f, 0x99, 0x78, 0x3e, 0x1a, 0xd1, - 0x38, 0x4e, 0x66, 0x29, 0x24, 0x14, 0x89, 0x89, 0x89, 0x1e, 0xc1, 0x56, 0x4a, 0x49, 0xe7, 0xda, - 0x48, 0xf4, 0x2a, 0x61, 0x39, 0x5d, 0x0b, 0xb4, 0x2c, 0xcf, 0x5f, 0x9e, 0x0a, 0xb5, 0x25, 0x91, - 0x4f, 0x9a, 0x24, 0xaf, 0xff, 0x1e, 0xee, 0x8b, 0x52, 0xf6, 0xa3, 0xf0, 0xc2, 0xb9, 0x70, 0x3d, - 0x97, 0x5d, 0xa7, 0x22, 0xe7, 0x89, 0x47, 0xa1, 0x4f, 0xf8, 0xda, 0xa6, 0x25, 0xe0, 0x80, 0x15, - 0x8e, 0x29, 0x2f, 0x01, 0x0b, 0x13, 0x93, 0x2c, 0x01, 0x0b, 0x85, 0x21, 0x7b, 0x9a, 0xe6, 0x57, - 0x4e, 0x53, 0xfd, 0x0a, 0xea, 0xb7, 0xe7, 0x92, 0x9a, 0x69, 0x42, 0x79, 0xb6, 0x84, 0xc5, 0x74, - 0x0a, 0xce, 0x42, 0xd9, 0xda, 0xe6, 0x3e, 0x5e, 0x5b, 0xfd, 0xaf, 0x0a, 0x6c, 0x1f, 0xcd, 0x5d, - 0x6f, 0xbc, 0xd2, 0xb8, 0xd9, 0xe8, 0x94, 0xd5, 0xb3, 0x7e, 0xdd, 0x41, 0x9e, 0x5b, 0x7b, 0x90, - 0xaf, 0x3b, 0x2c, 0xf3, 0x77, 0x1e, 0x96, 0x9f, 0x43, 0x79, 0x79, 0x4e, 0xc6, 0x75, 0xb5, 0x99, - 0x6f, 0x55, 0x30, 0x4c, 0xd3, 0x43, 0x32, 0xd6, 0xbf, 0x05, 0x94, 0x0d, 0x54, 0x2e, 0xc8, 0x62, - 0xff, 0x50, 0xee, 0xde, 0x3f, 0x1e, 0x40, 0x63, 0x30, 0xbf, 0x88, 0x47, 0x91, 0x7b, 0x41, 0x4f, - 0x98, 0x37, 0x32, 0xde, 0xd1, 0x80, 0xc5, 0x69, 0x97, 0xfe, 0x5b, 0x85, 0xd2, 0x02, 0xe5, 0xdb, - 0xb3, 0x1b, 0x8c, 0x42, 0x3f, 0x0d, 0x3a, 0xa0, 0x1e, 0x8f, 0x3b, 0x39, 0x14, 0xb6, 0x53, 0x53, - 0x27, 0xb1, 0x98, 0x63, 0xce, 0x5f, 0x49, 0x52, 0xf2, 0x73, 0x09, 0x3f, 0x9b, 0x63, 0xc2, 0x6f, - 0x81, 0xb6, 0xf0, 0x3f, 0x65, 0xde, 0x68, 0xb1, 0x28, 0xb8, 0x96, 0xe2, 0x3c, 0x98, 0x84, 0xb9, - 0xf0, 0x9c, 0x32, 0xd5, 0x84, 0x99, 0xe2, 0x92, 0xf9, 0x05, 0x54, 0x78, 0x3f, 0xc4, 0xcc, 0xf1, - 0x67, 0x24, 0x88, 0x45, 0x5f, 0xa8, 0xb8, 0xbc, 0xc0, 0xac, 0x18, 0x7d, 0x07, 0x40, 0x79, 0x7e, - 0x84, 0x5d, 0xcf, 0xa8, 0x68, 0x89, 0xda, 0xe1, 0x67, 0x19, 0x61, 0x2c, 0x16, 0x60, 0x5f, 0xfc, - 0x3b, 0xbc, 0x9e, 0x51, 0x5c, 0xa2, 0xe9, 0x4f, 0xf4, 0x3d, 0x54, 0x27, 0x61, 0xf4, 0xde, 0x89, - 0xc6, 0x44, 0x80, 0x72, 0xdb, 0xb8, 0x9f, 0xf1, 0x70, 0x9c, 0xd8, 0xc5, 0xf0, 0x93, 0x4f, 0x70, - 0x65, 0x92, 0xf9, 0x46, 0x2f, 0x01, 0xa5, 0xe3, 0x45, 0x97, 0x27, 0x4e, 0x8a, 0xc2, 0xc9, 0xde, - 0x6d, 0x27, 0x7c, 0x93, 0x4e, 0x1d, 0x69, 0x93, 0x1b, 0x18, 0xfa, 0x15, 0x54, 0x62, 0xca, 0x98, - 0x47, 0xa5, 0x9b, 0x92, 0x70, 0xb3, 0xbb, 0x72, 0xab, 0xe1, 0xe6, 0xd4, 0x43, 0x39, 0x5e, 0x7e, - 0xa2, 0x23, 0xd8, 0xf2, 0xdc, 0xe0, 0x2a, 0x1b, 0x06, 0x88, 0xf1, 0xf5, 0xcc, 0xf8, 0x9e, 0x1b, - 0x5c, 0x65, 0x63, 0xa8, 0x7a, 0x59, 0x40, 0xff, 0x35, 0x94, 0x16, 0xab, 0x84, 0xca, 0xb0, 0x79, - 0x66, 0xbd, 0xb4, 0xec, 0x57, 0x96, 0xf6, 0x09, 0x2a, 0x82, 0x3a, 0x30, 0xac, 0xae, 0xa6, 0x70, - 0x18, 0x1b, 0x1d, 0xc3, 0x3c, 0x37, 0xb4, 0x1c, 0xff, 0x38, 0xb6, 0xf1, 0xab, 0x36, 0xee, 0x6a, - 0xf9, 0xa3, 0x4d, 0x28, 0x88, 0x79, 0xf5, 0xbf, 0x2b, 0x50, 0x14, 0x15, 0x0c, 0x26, 0x21, 0xfa, - 0x09, 0x2c, 0xc4, 0x25, 0x36, 0x37, 0x7e, 0xe0, 0x0a, 0xd5, 0x55, 0xf1, 0x42, 0x30, 0x43, 0x89, - 0x73, 0xf2, 0x42, 0x1a, 0x0b, 0x72, 0x2e, 0x21, 0xa7, 0x86, 0x05, 0xf9, 0x49, 0xc6, 0xf3, 0xca, - 0x96, 0xa3, 0xe2, 0xad, 0xd4, 0x90, 0xee, 0xb0, 0x4f, 0x32, 0x8e, 0x57, 0x76, 0x62, 0x15, 0x6f, - 0xa5, 0x06, 0xc9, 0xd5, 0x7f, 0x01, 0x95, 0x6c, 0xcd, 0xd1, 0x63, 0x50, 0xdd, 0x60, 0x12, 0xca, - 0x46, 0xdc, 0xb9, 0x21, 0x2e, 0x9e, 0x24, 0x16, 0x04, 0x1d, 0x81, 0x76, 0xb3, 0xce, 0x7a, 0x15, - 0xca, 0x99, 0xa2, 0xe9, 0xff, 0x54, 0xa0, 0xba, 0x52, 0x84, 0xff, 0xda, 0x3b, 0xfa, 0x0e, 0x2a, - 0xef, 0xdd, 0x88, 0x92, 0xec, 0xf1, 0x5f, 0x3b, 0x6c, 0xac, 0x1e, 0xff, 0xe9, 0xff, 0x9d, 0x70, - 0x4c, 0x71, 0x99, 0xf3, 0x25, 0x80, 0x7e, 0x03, 0x35, 0x39, 0x92, 0x8c, 0x29, 0x73, 0x5c, 0x4f, - 0x2c, 0x55, 0x6d, 0x45, 0x1e, 0x92, 0xdb, 0x15, 0x76, 0x5c, 0x9d, 0x64, 0x3f, 0xd1, 0x57, 0x4b, - 0x07, 0x31, 0x8b, 0xdc, 0xe0, 0x52, 0xac, 0x5f, 0x69, 0x41, 0x1b, 0x08, 0x90, 0x1f, 0xe4, 0x55, - 0x79, 0x79, 0x1c, 0x30, 0x87, 0xcd, 0x63, 0xf4, 0x35, 0x14, 0x62, 0xe6, 0xc8, 0x9d, 0xac, 0xb6, - 0xd2, 0x5b, 0x19, 0x22, 0xc5, 0x09, 0x6b, 0xe5, 0xf6, 0x93, 0xbb, 0x75, 0xfb, 0x29, 0xf0, 0x1d, - 0x23, 0xd9, 0x45, 0xcb, 0x87, 0x48, 0x26, 0x7f, 0x32, 0xec, 0x75, 0xda, 0x8c, 0x51, 0x7f, 0xc6, - 0x70, 0x42, 0x48, 0x4e, 0xb7, 0x27, 0x7f, 0x54, 0xa1, 0xba, 0x92, 0xd4, 0xaa, 0xaa, 0xab, 0x50, - 0xb2, 0x6c, 0xd2, 0x35, 0x86, 0x6d, 0xb3, 0xa7, 0x29, 0x48, 0x83, 0x8a, 0x6d, 0x99, 0xb6, 0x45, - 0xba, 0x46, 0xc7, 0xee, 0x72, 0x7d, 0x7f, 0x0a, 0xdb, 0x3d, 0xd3, 0x7a, 0x49, 0x2c, 0x7b, 0x48, - 0x8c, 0x9e, 0xf9, 0xdc, 0x3c, 0xea, 0x19, 0x5a, 0x1e, 0xdd, 0x03, 0xcd, 0xb6, 0x48, 0xe7, 0xa4, - 0x6d, 0x5a, 0x64, 0x68, 0x9e, 0x1a, 0xf6, 0xd9, 0x50, 0x53, 0x39, 0xca, 0x03, 0x21, 0xc6, 0xeb, - 0x8e, 0x61, 0x74, 0x07, 0xe4, 0xb4, 0xfd, 0x5a, 0x2b, 0xa0, 0x3a, 0xdc, 0x33, 0xad, 0xc1, 0xd9, - 0xf1, 0xb1, 0xd9, 0x31, 0x0d, 0x6b, 0x48, 0x8e, 0xda, 0xbd, 0xb6, 0xd5, 0x31, 0xb4, 0x0d, 0xb4, - 0x0b, 0xc8, 0xb4, 0x3a, 0xf6, 0x69, 0xbf, 0x67, 0x0c, 0x0d, 0x92, 0xf6, 0xd1, 0x26, 0xda, 0x81, - 0x2d, 0xe1, 0xa7, 0xdd, 0xed, 0x92, 0xe3, 0xb6, 0xd9, 0x33, 0xba, 0x5a, 0x91, 0x47, 0x22, 0x19, - 0x03, 0xd2, 0x35, 0x07, 0xed, 0x23, 0x0e, 0x97, 0xf8, 0x9c, 0xa6, 0x75, 0x6e, 0x9b, 0x1d, 0x83, - 0x74, 0xb8, 0x5b, 0x8e, 0x02, 0x27, 0xa7, 0xe8, 0x99, 0xd5, 0x35, 0x70, 0xbf, 0x6d, 0x76, 0xb5, - 0x32, 0xda, 0x83, 0xfb, 0x29, 0x6c, 0xbc, 0xee, 0x9b, 0xf8, 0x0d, 0x19, 0xda, 0x36, 0x19, 0xd8, - 0xb6, 0xa5, 0x55, 0xb2, 0x9e, 0x78, 0xb6, 0x76, 0xdf, 0xb0, 0xb4, 0x2a, 0xba, 0x0f, 0x3b, 0xa7, - 0xfd, 0x3e, 0x49, 0x2d, 0x69, 0xb2, 0x35, 0x4e, 0x6f, 0x77, 0xbb, 0xd8, 0x18, 0x0c, 0xc8, 0xa9, - 0x39, 0x38, 0x6d, 0x0f, 0x3b, 0x27, 0xda, 0x16, 0x4f, 0x69, 0x60, 0x0c, 0xc9, 0xd0, 0x1e, 0xb6, - 0x7b, 0x4b, 0x5c, 0xe3, 0x01, 0x2d, 0x71, 0x3e, 0x69, 0xcf, 0x7e, 0xa5, 0x6d, 0xf3, 0x05, 0xe7, - 0xb0, 0x7d, 0x2e, 0x43, 0x44, 0x3c, 0x77, 0x59, 0x9e, 0x74, 0x4e, 0x6d, 0x87, 0x83, 0xa6, 0x75, - 0xde, 0xee, 0x99, 0x5d, 0xf2, 0xd2, 0x78, 0x23, 0xf6, 0xa1, 0x7b, 0x1c, 0x4c, 0x22, 0x23, 0x7d, - 0x6c, 0x3f, 0xe7, 0x81, 0x68, 0x9f, 0x22, 0x04, 0xb5, 0x8e, 0x89, 0x3b, 0x67, 0xbd, 0x36, 0x26, - 0xd8, 0x3e, 0x1b, 0x1a, 0xda, 0xee, 0x93, 0xbf, 0x29, 0x50, 0xc9, 0xea, 0x8c, 0x57, 0xdd, 0xb4, - 0xc8, 0x71, 0xcf, 0x7c, 0x7e, 0x32, 0x4c, 0x44, 0x30, 0x38, 0xeb, 0xf0, 0x92, 0x19, 0x7c, 0x7f, - 0x43, 0x50, 0x4b, 0x16, 0x7d, 0x91, 0x6c, 0x8e, 0xcf, 0x25, 0x31, 0xcb, 0x96, 0x7e, 0xf3, 0x3c, - 0x78, 0x09, 0x1a, 0x18, 0xdb, 0x58, 0x53, 0xd1, 0x97, 0xd0, 0x94, 0x08, 0xaf, 0x2b, 0xc6, 0x46, - 0x67, 0x48, 0xfa, 0xed, 0x37, 0xa7, 0xbc, 0xec, 0x89, 0xc8, 0x06, 0x5a, 0x01, 0x7d, 0x0e, 0x7b, - 0x0b, 0xd6, 0x3a, 0x5d, 0x1c, 0xfe, 0x65, 0x13, 0x36, 0xc4, 0x31, 0x1f, 0xa1, 0xdf, 0x42, 0x35, - 0xf3, 0x90, 0x3d, 0x3f, 0x44, 0x0f, 0x3f, 0xf8, 0xc4, 0x6d, 0xa4, 0x8f, 0x01, 0x09, 0x3f, 0x53, - 0xd0, 0x11, 0xd4, 0xb2, 0xef, 0xb9, 0xf3, 0x43, 0x94, 0x3d, 0x1d, 0xd7, 0x3c, 0xf5, 0xd6, 0xf8, - 0x78, 0x09, 0x9a, 0x11, 0x33, 0xd7, 0xe7, 0x4d, 0x2a, 0x5f, 0x5c, 0xa8, 0x91, 0xf1, 0x72, 0xe3, - 0x19, 0xd7, 0xd8, 0x5b, 0x6b, 0x93, 0xf7, 0x9a, 0x1e, 0xdf, 0x10, 0x17, 0x6f, 0x9e, 0x5b, 0x09, - 0xad, 0x3e, 0xb4, 0x1a, 0x9f, 0xdd, 0x65, 0x96, 0xde, 0xc6, 0xb0, 0xb3, 0xe6, 0x19, 0x83, 0xbe, - 0xca, 0x46, 0x70, 0xe7, 0x23, 0xa8, 0xf1, 0xe8, 0x63, 0xb4, 0xe5, 0x2c, 0x6b, 0xde, 0x3b, 0x2b, - 0xb3, 0xdc, 0xfd, 0x5a, 0x5a, 0x99, 0xe5, 0x43, 0xcf, 0xa6, 0xb7, 0xa0, 0xdd, 0xbc, 0x1e, 0x23, - 0xfd, 0xe6, 0xd8, 0xdb, 0xf7, 0xf4, 0xc6, 0xff, 0x7f, 0x90, 0x23, 0x9d, 0x9b, 0x00, 0xcb, 0x4b, - 0x26, 0x7a, 0x90, 0x19, 0x72, 0xeb, 0x92, 0xdc, 0x78, 0x78, 0x87, 0x55, 0xba, 0x1a, 0xc2, 0xce, - 0x9a, 0x5b, 0xe7, 0xca, 0x6a, 0xdc, 0x7d, 0x2b, 0x6d, 0xdc, 0x5b, 0x77, 0x39, 0x7b, 0xa6, 0xa0, - 0xd3, 0x44, 0x17, 0xe9, 0x1f, 0x55, 0x3e, 0x22, 0xf4, 0xfa, 0xfa, 0x43, 0x64, 0x1e, 0xeb, 0xf9, - 0x3f, 0xe5, 0x94, 0x67, 0x0a, 0xb2, 0xa1, 0x92, 0x15, 0xf7, 0x47, 0x55, 0xff, 0x31, 0x87, 0x47, - 0xdf, 0xfc, 0xee, 0xe0, 0xd2, 0x65, 0xd3, 0xf9, 0xc5, 0xfe, 0x28, 0xf4, 0x0f, 0xc4, 0x5f, 0x32, - 0x02, 0x37, 0xb8, 0x0c, 0x28, 0x7b, 0x1f, 0x46, 0x57, 0x07, 0x5e, 0x30, 0x3e, 0x10, 0x7d, 0x73, - 0xb0, 0xf0, 0x73, 0xb1, 0x21, 0xfe, 0x38, 0xf9, 0xd3, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8d, - 0x86, 0x7a, 0x49, 0xcc, 0x14, 0x00, 0x00, + // 2248 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0xcd, 0x76, 0xdb, 0xb8, + 0xf5, 0x1f, 0x4a, 0x94, 0x2d, 0x5d, 0x7d, 0x98, 0x86, 0x33, 0x8e, 0xfe, 0x72, 0x32, 0xa3, 0xe1, + 0x7f, 0x26, 0xd1, 0x49, 0x33, 0x76, 0xc6, 0xed, 0x69, 0xe7, 0xb4, 0x9d, 0x69, 0x65, 0x89, 0x8e, + 0x99, 0xc8, 0xa4, 0x06, 0x92, 0x9d, 0xa4, 0x59, 0xe0, 0xd0, 0x12, 0x64, 0xb1, 0xe6, 0x87, 0x4a, + 0x42, 0xc9, 0x78, 0xd9, 0x5d, 0x4f, 0xb7, 0x7d, 0x88, 0xee, 0xfa, 0x04, 0xdd, 0xf6, 0x39, 0xba, + 0xed, 0x13, 0x74, 0xdd, 0x03, 0x10, 0x94, 0x28, 0x5b, 0x4e, 0xda, 0x8d, 0x4d, 0xfc, 0xee, 0xc5, + 0xc5, 0xbd, 0xb8, 0xbf, 0x8b, 0x0b, 0x08, 0x76, 0xa3, 0x70, 0xce, 0x68, 0x14, 0xcd, 0x46, 0x07, + 0xc9, 0xd7, 0xfe, 0x2c, 0x0a, 0x59, 0x88, 0x4a, 0x0b, 0xbc, 0x51, 0x8a, 0x66, 0xa3, 0x04, 0xd5, + 0xff, 0xb1, 0x01, 0x68, 0x40, 0x83, 0x71, 0xdf, 0xb9, 0xf6, 0x69, 0xc0, 0x30, 0xfd, 0xc3, 0x9c, + 0xc6, 0x0c, 0x21, 0x50, 0xc7, 0x34, 0x66, 0x75, 0xa5, 0xa9, 0xb4, 0x2a, 0x58, 0x7c, 0x23, 0x0d, + 0xf2, 0x8e, 0xcf, 0xea, 0xb9, 0xa6, 0xd2, 0xca, 0x63, 0xfe, 0x89, 0xfe, 0x0f, 0x8a, 0x8e, 0xcf, + 0x88, 0x1f, 0x3b, 0xac, 0x5e, 0x11, 0xf0, 0xa6, 0xe3, 0xb3, 0xd3, 0xd8, 0x61, 0xe8, 0x0b, 0xa8, + 0xcc, 0x12, 0x93, 0x64, 0xea, 0xc4, 0xd3, 0x7a, 0x5e, 0x18, 0x2a, 0x4b, 0xec, 0xc4, 0x89, 0xa7, + 0xa8, 0x05, 0xda, 0xc4, 0x0d, 0x1c, 0x8f, 0x8c, 0x3c, 0xf6, 0x8e, 0x8c, 0xa9, 0xc7, 0x9c, 0xba, + 0xda, 0x54, 0x5a, 0x05, 0x5c, 0x13, 0x78, 0xc7, 0x63, 0xef, 0xba, 0x1c, 0x45, 0x8f, 0x61, 0x2b, + 0x35, 0x16, 0x25, 0x0e, 0xd6, 0x0b, 0x4d, 0xa5, 0x55, 0xc2, 0xb5, 0xd9, 0xaa, 0xdb, 0x8f, 0x61, + 0x8b, 0xb9, 0x3e, 0x0d, 0xe7, 0x8c, 0xc4, 0x74, 0x14, 0x06, 0xe3, 0xb8, 0xbe, 0x91, 0x58, 0x94, + 0xf0, 0x20, 0x41, 0x91, 0x0e, 0xd5, 0x09, 0xa5, 0xc4, 0x73, 0x7d, 0x97, 0x11, 0xee, 0xfe, 0xa6, + 0x70, 0xbf, 0x3c, 0xa1, 0xb4, 0xc7, 0xb1, 0x81, 0xc3, 0xd0, 0x97, 0x50, 0x5b, 0xea, 0x88, 0x18, + 0xab, 0x42, 0xa9, 0x92, 0x2a, 0x89, 0x40, 0x9f, 0x82, 0x16, 0xce, 0xd9, 0x65, 0xe8, 0x06, 0x97, + 0x64, 0x34, 0x75, 0x02, 0xe2, 0x8e, 0xeb, 0xc5, 0xa6, 0xd2, 0x52, 0x8f, 0x72, 0xcf, 0x14, 0x5c, + 0x4b, 0x65, 0x9d, 0xa9, 0x13, 0x98, 0x63, 0xf4, 0x08, 0xb6, 0x3c, 0x27, 0x66, 0x64, 0x1a, 0xce, + 0xc8, 0x6c, 0x7e, 0x71, 0x45, 0xaf, 0xeb, 0x35, 0xb1, 0x33, 0x55, 0x0e, 0x9f, 0x84, 0xb3, 0xbe, + 0x00, 0xd1, 0x43, 0x00, 0xb1, 0x2b, 0x62, 0xf1, 0x7a, 0x49, 0xc4, 0x50, 0xe2, 0x88, 0x58, 0x18, + 0x7d, 0x03, 0x65, 0x91, 0x4d, 0x32, 0x75, 0x03, 0x16, 0xd7, 0xa1, 0x99, 0x6f, 0x95, 0x0f, 0xb5, + 0x7d, 0x2f, 0xe0, 0x89, 0xc5, 0x5c, 0x72, 0xe2, 0x06, 0x0c, 0x43, 0x94, 0x7e, 0xc6, 0x68, 0x0c, + 0x3b, 0x3c, 0x8b, 0x64, 0x34, 0x8f, 0x59, 0xe8, 0x93, 0x88, 0x8e, 0xc2, 0x68, 0x1c, 0xd7, 0xcb, + 0x62, 0xea, 0xcf, 0xf6, 0x17, 0xe4, 0xd8, 0xbf, 0xcd, 0x86, 0xfd, 0x2e, 0x8d, 0x59, 0x47, 0xcc, + 0xc3, 0xc9, 0x34, 0x23, 0x60, 0xd1, 0x35, 0xde, 0x1e, 0xdf, 0xc4, 0xd1, 0x53, 0x40, 0x8e, 0xe7, + 0x85, 0xef, 0x49, 0x4c, 0xbd, 0x09, 0x91, 0xd9, 0xa9, 0x6f, 0x35, 0x95, 0x56, 0x11, 0x6b, 0x42, + 0x32, 0xa0, 0xde, 0x44, 0x9a, 0x47, 0x3f, 0x87, 0xaa, 0xf0, 0x69, 0x42, 0x1d, 0x36, 0x8f, 0x68, + 0x5c, 0xd7, 0x9a, 0xf9, 0x56, 0xed, 0x70, 0x5b, 0x06, 0x72, 0x9c, 0xc0, 0x47, 0x2e, 0xc3, 0x15, + 0xae, 0x27, 0xc7, 0x31, 0xda, 0x83, 0x92, 0xef, 0xfc, 0x48, 0x66, 0x4e, 0xc4, 0xe2, 0xfa, 0x76, + 0x53, 0x69, 0x55, 0x71, 0xd1, 0x77, 0x7e, 0xec, 0xf3, 0x31, 0xda, 0x87, 0x9d, 0x20, 0x24, 0x6e, + 0x30, 0xf1, 0xdc, 0xcb, 0x29, 0x23, 0xf3, 0xd9, 0xd8, 0x61, 0x34, 0xae, 0x23, 0xe1, 0xc3, 0x76, + 0x10, 0x9a, 0x52, 0x72, 0x96, 0x08, 0x1a, 0x5d, 0xd8, 0x5d, 0x1f, 0x1f, 0x27, 0x3c, 0x4f, 0x10, + 0xaf, 0x01, 0x15, 0xf3, 0x4f, 0x74, 0x0f, 0x0a, 0xef, 0x1c, 0x6f, 0x4e, 0x45, 0x11, 0x54, 0x70, + 0x32, 0xf8, 0x65, 0xee, 0x5b, 0x45, 0x9f, 0xc2, 0xce, 0x30, 0x72, 0x46, 0x57, 0x37, 0xea, 0xe8, + 0x66, 0x19, 0x28, 0xb7, 0xcb, 0xe0, 0x0e, 0x7f, 0x73, 0x77, 0xf8, 0xab, 0x7f, 0x0f, 0x5b, 0x22, + 0xc3, 0xc7, 0x94, 0x7e, 0xa8, 0x5a, 0xef, 0x03, 0xaf, 0x45, 0xc1, 0xed, 0xa4, 0x62, 0x37, 0x1c, + 0x9f, 0xd3, 0x5a, 0x1f, 0x83, 0xb6, 0x9c, 0x1f, 0xcf, 0xc2, 0x20, 0xa6, 0xbc, 0x14, 0x39, 0x01, + 0x38, 0x87, 0x39, 0xe5, 0x05, 0xd9, 0x15, 0x31, 0xab, 0x26, 0xf1, 0x63, 0x4a, 0x05, 0xdd, 0x1f, + 0x25, 0x15, 0x46, 0xbc, 0x70, 0x74, 0xc5, 0x6b, 0xd6, 0xb9, 0x96, 0xe6, 0xab, 0x1c, 0xee, 0x85, + 0xa3, 0xab, 0x2e, 0x07, 0xf5, 0xb7, 0xc9, 0xb1, 0x32, 0x0c, 0xc5, 0x5a, 0xff, 0xc3, 0x76, 0xe8, + 0x50, 0x10, 0x5c, 0x14, 0x66, 0xcb, 0x87, 0x95, 0x2c, 0xa9, 0x71, 0x22, 0xd2, 0xdf, 0xc2, 0xce, + 0x8a, 0x71, 0x19, 0x45, 0x03, 0x8a, 0xb3, 0x88, 0xba, 0xbe, 0x73, 0x49, 0xa5, 0xe5, 0xc5, 0x18, + 0xb5, 0x60, 0x73, 0xe2, 0xb8, 0xde, 0x3c, 0x4a, 0x0d, 0xd7, 0x52, 0x92, 0x25, 0x28, 0x4e, 0xc5, + 0xfa, 0x03, 0x68, 0x60, 0x1a, 0x53, 0x76, 0xea, 0xc6, 0xb1, 0x1b, 0x06, 0x9d, 0x30, 0x60, 0x51, + 0xe8, 0xc9, 0x08, 0xf4, 0x87, 0xb0, 0xb7, 0x56, 0x9a, 0xb8, 0xc0, 0x27, 0xff, 0x30, 0xa7, 0xd1, + 0xf5, 0xfa, 0xc9, 0x3f, 0xc0, 0xde, 0x5a, 0xa9, 0xf4, 0xff, 0x29, 0x14, 0x66, 0x8e, 0x1b, 0xf1, + 0xdc, 0xf3, 0xa2, 0xdc, 0xcd, 0x14, 0x65, 0xdf, 0x71, 0xa3, 0x13, 0x37, 0x66, 0x61, 0x74, 0x8d, + 0x13, 0xa5, 0x17, 0x6a, 0x51, 0xd1, 0x72, 0xfa, 0x9f, 0x15, 0x28, 0x67, 0x84, 0xbc, 0x34, 0x82, + 0x70, 0x4c, 0xc9, 0x24, 0x0a, 0xfd, 0x74, 0x13, 0x38, 0x70, 0x1c, 0x85, 0x3e, 0xe7, 0x84, 0x10, + 0xb2, 0x50, 0x12, 0x78, 0x83, 0x0f, 0x87, 0x21, 0xfa, 0x1a, 0x36, 0xa7, 0x89, 0x01, 0x71, 0x10, + 0x96, 0x0f, 0x77, 0x6e, 0xac, 0xdd, 0x75, 0x98, 0x83, 0x53, 0x9d, 0x17, 0x6a, 0x31, 0xaf, 0xa9, + 0x2f, 0xd4, 0xa2, 0xaa, 0x15, 0x5e, 0xa8, 0xc5, 0x82, 0xb6, 0xf1, 0x42, 0x2d, 0x6e, 0x68, 0x9b, + 0xfa, 0xbf, 0x14, 0x28, 0xa6, 0xda, 0xdc, 0x13, 0xbe, 0xa5, 0x84, 0xf3, 0x42, 0x92, 0xa9, 0xc8, + 0x81, 0xa1, 0xeb, 0x53, 0xd4, 0x84, 0x8a, 0x10, 0xae, 0x52, 0x14, 0x38, 0xd6, 0x16, 0x34, 0x15, + 0x27, 0x74, 0xaa, 0x21, 0xf8, 0xa8, 0xca, 0x13, 0x3a, 0x51, 0x49, 0x9b, 0x4c, 0x3c, 0x1f, 0x8d, + 0x68, 0x1c, 0x27, 0xab, 0x14, 0x12, 0x15, 0x89, 0x89, 0x85, 0x1e, 0xc1, 0x56, 0xaa, 0x92, 0xae, + 0xb5, 0x91, 0xf0, 0x55, 0xc2, 0x72, 0xb9, 0x16, 0x68, 0x59, 0x3d, 0x7f, 0xd9, 0x13, 0x6a, 0x4b, + 0x45, 0xbe, 0x68, 0x12, 0xbc, 0xfe, 0x7b, 0xb8, 0x2f, 0x52, 0xd9, 0x8f, 0xc2, 0x0b, 0xe7, 0xc2, + 0xf5, 0x5c, 0x76, 0x9d, 0x92, 0x9c, 0x07, 0x1e, 0x85, 0x3e, 0xe1, 0x7b, 0x9b, 0xa6, 0x80, 0x03, + 0x56, 0x38, 0xa6, 0x3c, 0x05, 0x2c, 0x4c, 0x44, 0x32, 0x05, 0x2c, 0x14, 0x82, 0x6c, 0x2f, 0xcd, + 0xaf, 0xf4, 0x52, 0xfd, 0x0a, 0xea, 0xb7, 0xd7, 0x92, 0x9c, 0x69, 0x42, 0x79, 0xb6, 0x84, 0xc5, + 0x72, 0x0a, 0xce, 0x42, 0xd9, 0xdc, 0xe6, 0x3e, 0x9e, 0x5b, 0xfd, 0xaf, 0x0a, 0x6c, 0x1f, 0xcd, + 0x5d, 0x6f, 0xbc, 0x52, 0xb8, 0x59, 0xef, 0x94, 0xd5, 0x4e, 0xbf, 0xae, 0x8d, 0xe7, 0xd6, 0xb6, + 0xf1, 0x75, 0xad, 0x32, 0x7f, 0x67, 0xab, 0xfc, 0x1c, 0xca, 0xcb, 0x2e, 0x19, 0xd7, 0xd5, 0x66, + 0xbe, 0x55, 0xc1, 0x30, 0x4d, 0x5b, 0x64, 0xac, 0x7f, 0x0b, 0x28, 0xeb, 0xa8, 0xdc, 0x90, 0xc5, + 0xf9, 0xa1, 0xdc, 0x7d, 0x7e, 0x3c, 0x80, 0xc6, 0x60, 0x7e, 0x11, 0x8f, 0x22, 0xf7, 0x82, 0x9e, + 0x30, 0x6f, 0x64, 0xbc, 0xa3, 0x01, 0x8b, 0xd3, 0x2a, 0xfd, 0xb7, 0x0a, 0xa5, 0x05, 0xca, 0x8f, + 0x67, 0x37, 0x18, 0x85, 0x7e, 0xea, 0x74, 0x40, 0x3d, 0xee, 0x77, 0xd2, 0x14, 0xb6, 0x53, 0x51, + 0x27, 0x91, 0x98, 0x63, 0xae, 0xbf, 0x12, 0xa4, 0xd4, 0xcf, 0x25, 0xfa, 0xd9, 0x18, 0x13, 0xfd, + 0x16, 0x68, 0x0b, 0xfb, 0x53, 0xe6, 0x8d, 0x16, 0x9b, 0x82, 0x6b, 0x29, 0xce, 0x9d, 0x49, 0x34, + 0x17, 0x96, 0x53, 0x4d, 0x35, 0xd1, 0x4c, 0x71, 0xa9, 0xf9, 0x05, 0x54, 0x78, 0x3d, 0xc4, 0xcc, + 0xf1, 0x67, 0x24, 0x88, 0x45, 0x5d, 0xa8, 0xb8, 0xbc, 0xc0, 0xac, 0x18, 0x7d, 0x07, 0x40, 0x79, + 0x7c, 0x84, 0x5d, 0xcf, 0xa8, 0x28, 0x89, 0xda, 0xe1, 0x67, 0x19, 0x62, 0x2c, 0x36, 0x60, 0x5f, + 0xfc, 0x1d, 0x5e, 0xcf, 0x28, 0x2e, 0xd1, 0xf4, 0x13, 0x7d, 0x0f, 0xd5, 0x49, 0x18, 0xbd, 0x77, + 0xa2, 0x31, 0x11, 0xa0, 0x3c, 0x36, 0xee, 0x67, 0x2c, 0x1c, 0x27, 0x72, 0x31, 0xfd, 0xe4, 0x13, + 0x5c, 0x99, 0x64, 0xc6, 0xe8, 0x25, 0xa0, 0x74, 0xbe, 0xa8, 0xf2, 0xc4, 0x48, 0x51, 0x18, 0xd9, + 0xbb, 0x6d, 0x84, 0x1f, 0xd2, 0xa9, 0x21, 0x6d, 0x72, 0x03, 0x43, 0xbf, 0x82, 0x4a, 0x4c, 0x19, + 0xf3, 0xa8, 0x34, 0x53, 0x12, 0x66, 0x76, 0x57, 0xee, 0x34, 0x5c, 0x9c, 0x5a, 0x28, 0xc7, 0xcb, + 0x21, 0x3a, 0x82, 0x2d, 0xcf, 0x0d, 0xae, 0xb2, 0x6e, 0x80, 0x98, 0x5f, 0xcf, 0xcc, 0xef, 0xb9, + 0xc1, 0x55, 0xd6, 0x87, 0xaa, 0x97, 0x05, 0xf4, 0x5f, 0x43, 0x69, 0xb1, 0x4b, 0xa8, 0x0c, 0x9b, + 0x67, 0xd6, 0x4b, 0xcb, 0x7e, 0x65, 0x69, 0x9f, 0xa0, 0x22, 0xa8, 0x03, 0xc3, 0xea, 0x6a, 0x0a, + 0x87, 0xb1, 0xd1, 0x31, 0xcc, 0x73, 0x43, 0xcb, 0xf1, 0xc1, 0xb1, 0x8d, 0x5f, 0xb5, 0x71, 0x57, + 0xcb, 0x1f, 0x6d, 0x42, 0x41, 0xac, 0xab, 0xff, 0x5d, 0x81, 0xa2, 0xc8, 0x60, 0x30, 0x09, 0xd1, + 0x4f, 0x60, 0x41, 0x2e, 0x71, 0xb8, 0xf1, 0x86, 0x2b, 0x58, 0x57, 0xc5, 0x0b, 0xc2, 0x0c, 0x25, + 0xce, 0x95, 0x17, 0xd4, 0x58, 0x28, 0xe7, 0x12, 0xe5, 0x54, 0xb0, 0x50, 0x7e, 0x92, 0xb1, 0xbc, + 0x72, 0xe4, 0xa8, 0x78, 0x2b, 0x15, 0xa4, 0x27, 0xec, 0x93, 0x8c, 0xe1, 0x95, 0x93, 0x58, 0xc5, + 0x5b, 0xa9, 0x40, 0xea, 0xea, 0xbf, 0x80, 0x4a, 0x36, 0xe7, 0xe8, 0x31, 0xa8, 0x6e, 0x30, 0x09, + 0x65, 0x21, 0xee, 0xdc, 0x20, 0x17, 0x0f, 0x12, 0x0b, 0x05, 0x1d, 0x81, 0x76, 0x33, 0xcf, 0x7a, + 0x15, 0xca, 0x99, 0xa4, 0xe9, 0xff, 0x54, 0xa0, 0xba, 0x92, 0x84, 0xff, 0xda, 0x3a, 0xfa, 0x0e, + 0x2a, 0xef, 0xdd, 0x88, 0x92, 0x6c, 0xfb, 0xaf, 0x1d, 0x36, 0x56, 0xdb, 0x7f, 0xfa, 0xbf, 0x13, + 0x8e, 0x29, 0x2e, 0x73, 0x7d, 0x09, 0xa0, 0xdf, 0x40, 0x4d, 0xce, 0x24, 0x63, 0xca, 0x1c, 0xd7, + 0x13, 0x5b, 0x55, 0x5b, 0xa1, 0x87, 0xd4, 0xed, 0x0a, 0x39, 0xae, 0x4e, 0xb2, 0x43, 0xf4, 0xd5, + 0xd2, 0x40, 0xcc, 0x22, 0x37, 0xb8, 0x14, 0xfb, 0x57, 0x5a, 0xa8, 0x0d, 0x04, 0xc8, 0x1b, 0x79, + 0x55, 0x5e, 0x1e, 0x07, 0xcc, 0x61, 0xf3, 0x18, 0x7d, 0x0d, 0x85, 0x98, 0x39, 0xf2, 0x24, 0xab, + 0xad, 0xd4, 0x56, 0x46, 0x91, 0xe2, 0x44, 0x6b, 0xe5, 0xf6, 0x93, 0xbb, 0x75, 0xfb, 0x29, 0xf0, + 0x13, 0x23, 0x39, 0x45, 0xcb, 0x87, 0x48, 0x06, 0x7f, 0x32, 0xec, 0x75, 0xda, 0x8c, 0x51, 0x7f, + 0xc6, 0x70, 0xa2, 0x90, 0x74, 0xb7, 0x27, 0x7f, 0x54, 0xa1, 0xba, 0x12, 0xd4, 0x2a, 0xab, 0xab, + 0x50, 0xb2, 0x6c, 0xd2, 0x35, 0x86, 0x6d, 0xb3, 0xa7, 0x29, 0x48, 0x83, 0x8a, 0x6d, 0x99, 0xb6, + 0x45, 0xba, 0x46, 0xc7, 0xee, 0x72, 0x7e, 0x7f, 0x0a, 0xdb, 0x3d, 0xd3, 0x7a, 0x49, 0x2c, 0x7b, + 0x48, 0x8c, 0x9e, 0xf9, 0xdc, 0x3c, 0xea, 0x19, 0x5a, 0x1e, 0xdd, 0x03, 0xcd, 0xb6, 0x48, 0xe7, + 0xa4, 0x6d, 0x5a, 0x64, 0x68, 0x9e, 0x1a, 0xf6, 0xd9, 0x50, 0x53, 0x39, 0xca, 0x1d, 0x21, 0xc6, + 0xeb, 0x8e, 0x61, 0x74, 0x07, 0xe4, 0xb4, 0xfd, 0x5a, 0x2b, 0xa0, 0x3a, 0xdc, 0x33, 0xad, 0xc1, + 0xd9, 0xf1, 0xb1, 0xd9, 0x31, 0x0d, 0x6b, 0x48, 0x8e, 0xda, 0xbd, 0xb6, 0xd5, 0x31, 0xb4, 0x0d, + 0xb4, 0x0b, 0xc8, 0xb4, 0x3a, 0xf6, 0x69, 0xbf, 0x67, 0x0c, 0x0d, 0x92, 0xd6, 0xd1, 0x26, 0xda, + 0x81, 0x2d, 0x61, 0xa7, 0xdd, 0xed, 0x92, 0xe3, 0xb6, 0xd9, 0x33, 0xba, 0x5a, 0x91, 0x7b, 0x22, + 0x35, 0x06, 0xa4, 0x6b, 0x0e, 0xda, 0x47, 0x1c, 0x2e, 0xf1, 0x35, 0x4d, 0xeb, 0xdc, 0x36, 0x3b, + 0x06, 0xe9, 0x70, 0xb3, 0x1c, 0x05, 0xae, 0x9c, 0xa2, 0x67, 0x56, 0xd7, 0xc0, 0xfd, 0xb6, 0xd9, + 0xd5, 0xca, 0x68, 0x0f, 0xee, 0xa7, 0xb0, 0xf1, 0xba, 0x6f, 0xe2, 0x37, 0x64, 0x68, 0xdb, 0x64, + 0x60, 0xdb, 0x96, 0x56, 0xc9, 0x5a, 0xe2, 0xd1, 0xda, 0x7d, 0xc3, 0xd2, 0xaa, 0xe8, 0x3e, 0xec, + 0x9c, 0xf6, 0xfb, 0x24, 0x95, 0xa4, 0xc1, 0xd6, 0xb8, 0x7a, 0xbb, 0xdb, 0xc5, 0xc6, 0x60, 0x40, + 0x4e, 0xcd, 0xc1, 0x69, 0x7b, 0xd8, 0x39, 0xd1, 0xb6, 0x78, 0x48, 0x03, 0x63, 0x48, 0x86, 0xf6, + 0xb0, 0xdd, 0x5b, 0xe2, 0x1a, 0x77, 0x68, 0x89, 0xf3, 0x45, 0x7b, 0xf6, 0x2b, 0x6d, 0x9b, 0x6f, + 0x38, 0x87, 0xed, 0x73, 0xe9, 0x22, 0xe2, 0xb1, 0xcb, 0xf4, 0xa4, 0x6b, 0x6a, 0x3b, 0x1c, 0x34, + 0xad, 0xf3, 0x76, 0xcf, 0xec, 0x92, 0x97, 0xc6, 0x1b, 0x71, 0x0e, 0xdd, 0xe3, 0x60, 0xe2, 0x19, + 0xe9, 0x63, 0xfb, 0x39, 0x77, 0x44, 0xfb, 0x14, 0x21, 0xa8, 0x75, 0x4c, 0xdc, 0x39, 0xeb, 0xb5, + 0x31, 0xc1, 0xf6, 0xd9, 0xd0, 0xd0, 0x76, 0x9f, 0xfc, 0x4d, 0x81, 0x4a, 0x96, 0x67, 0x3c, 0xeb, + 0xa6, 0x45, 0x8e, 0x7b, 0xe6, 0xf3, 0x93, 0x61, 0x42, 0x82, 0xc1, 0x59, 0x87, 0xa7, 0xcc, 0xe0, + 0xe7, 0x1b, 0x82, 0x5a, 0xb2, 0xe9, 0x8b, 0x60, 0x73, 0x7c, 0x2d, 0x89, 0x59, 0xb6, 0xb4, 0x9b, + 0xe7, 0xce, 0x4b, 0xd0, 0xc0, 0xd8, 0xc6, 0x9a, 0x8a, 0xbe, 0x84, 0xa6, 0x44, 0x78, 0x5e, 0x31, + 0x36, 0x3a, 0x43, 0xd2, 0x6f, 0xbf, 0x39, 0xe5, 0x69, 0x4f, 0x48, 0x36, 0xd0, 0x0a, 0xe8, 0x73, + 0xd8, 0x5b, 0x68, 0xad, 0xe3, 0xc5, 0xe1, 0x5f, 0x36, 0x61, 0x43, 0xb4, 0xf9, 0x08, 0xfd, 0x16, + 0xaa, 0x99, 0x67, 0xec, 0xf9, 0x21, 0x7a, 0xf8, 0xc1, 0x07, 0x6e, 0x23, 0x7d, 0x0c, 0x48, 0xf8, + 0x99, 0x82, 0x8e, 0xa0, 0x96, 0x7d, 0xcf, 0x9d, 0x1f, 0xa2, 0x6c, 0x77, 0x5c, 0xf3, 0xd4, 0x5b, + 0x63, 0xe3, 0x25, 0x68, 0x46, 0xcc, 0x5c, 0x9f, 0x17, 0xa9, 0x7c, 0x71, 0xa1, 0x46, 0xc6, 0xca, + 0x8d, 0x67, 0x5c, 0x63, 0x6f, 0xad, 0x4c, 0xde, 0x6b, 0x7a, 0xfc, 0x40, 0x5c, 0xbc, 0x79, 0x6e, + 0x05, 0xb4, 0xfa, 0xd0, 0x6a, 0x7c, 0x76, 0x97, 0x58, 0x5a, 0x1b, 0xc3, 0xce, 0x9a, 0x67, 0x0c, + 0xfa, 0x2a, 0xeb, 0xc1, 0x9d, 0x8f, 0xa0, 0xc6, 0xa3, 0x8f, 0xa9, 0x2d, 0x57, 0x59, 0xf3, 0xde, + 0x59, 0x59, 0xe5, 0xee, 0xd7, 0xd2, 0xca, 0x2a, 0x1f, 0x7a, 0x36, 0xbd, 0x05, 0xed, 0xe6, 0xf5, + 0x18, 0xe9, 0x37, 0xe7, 0xde, 0xbe, 0xa7, 0x37, 0xfe, 0xff, 0x83, 0x3a, 0xd2, 0xb8, 0x09, 0xb0, + 0xbc, 0x64, 0xa2, 0x07, 0x99, 0x29, 0xb7, 0x2e, 0xc9, 0x8d, 0x87, 0x77, 0x48, 0xa5, 0xa9, 0x21, + 0xec, 0xac, 0xb9, 0x75, 0xae, 0xec, 0xc6, 0xdd, 0xb7, 0xd2, 0xc6, 0xbd, 0x75, 0x97, 0xb3, 0x67, + 0x0a, 0x3a, 0x4d, 0x78, 0x91, 0xfe, 0xa4, 0xf2, 0x11, 0xa2, 0xd7, 0xd7, 0x37, 0x91, 0x79, 0xac, + 0xe7, 0xff, 0x94, 0x53, 0x9e, 0x29, 0xc8, 0x86, 0x4a, 0x96, 0xdc, 0x1f, 0x65, 0xfd, 0xc7, 0x0c, + 0x1e, 0x7d, 0xf3, 0xbb, 0x83, 0x4b, 0x97, 0x4d, 0xe7, 0x17, 0xfb, 0xa3, 0xd0, 0x3f, 0x10, 0xbf, + 0x64, 0x04, 0x6e, 0x70, 0x19, 0x50, 0xf6, 0x3e, 0x8c, 0xae, 0x0e, 0xbc, 0x60, 0x7c, 0x20, 0xea, + 0xe6, 0x60, 0x61, 0xe7, 0x62, 0x43, 0xfc, 0x34, 0xf9, 0xd3, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, + 0x16, 0x00, 0xbc, 0x19, 0xca, 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 9065715af1..673ffb986b 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -119,7 +119,7 @@ message SendPaymentRequest { The maximum number of partial payments that may be use to complete the full amount. */ - uint32 max_shards = 17; + uint32 max_parts = 17; /** If set, only the final payment update is streamed back. Intermediate updates diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 2803f4472b..354e5e29d3 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -549,11 +549,11 @@ func (r *RouterBackend) extractIntentFromSendRequest( // Take max htlcs from the request. Map zero to one for backwards // compatibility. - maxShards := rpcPayReq.MaxShards - if maxShards == 0 { - maxShards = 1 + maxParts := rpcPayReq.MaxParts + if maxParts == 0 { + maxParts = 1 } - payIntent.MaxShards = maxShards + payIntent.MaxParts = maxParts // Take fee limit from request. payIntent.FeeLimit, err = lnrpc.UnmarshallAmt( diff --git a/lnrpc/routerrpc/router_server_deprecated.go b/lnrpc/routerrpc/router_server_deprecated.go index 199ec841ca..66f3d3689c 100644 --- a/lnrpc/routerrpc/router_server_deprecated.go +++ b/lnrpc/routerrpc/router_server_deprecated.go @@ -84,7 +84,7 @@ func (s *Server) TrackPayment(request *TrackPaymentRequest, func (s *Server) SendPayment(request *SendPaymentRequest, stream Router_SendPaymentServer) error { - if request.MaxShards > 1 { + if request.MaxParts > 1 { return errors.New("for multi-part payments, use SendPaymentV2") } diff --git a/lntest/itest/lnd_send_multi_path_payment.go b/lntest/itest/lnd_send_multi_path_payment.go index 318f255688..227320001b 100644 --- a/lntest/itest/lnd_send_multi_path_payment.go +++ b/lntest/itest/lnd_send_multi_path_payment.go @@ -74,7 +74,7 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) { t, net.Alice, &routerrpc.SendPaymentRequest{ PaymentRequest: payReq, - MaxShards: 10, + MaxParts: 10, TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat, }, diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go index cc71560d8b..b223668e63 100644 --- a/routing/integrated_routing_context_test.go +++ b/routing/integrated_routing_context_test.go @@ -88,7 +88,7 @@ func (h htlcAttempt) String() string { // testPayment launches a test payment and asserts that it is completed after // the expected number of attempts. -func (c *integratedRoutingContext) testPayment(maxShards uint32) ([]htlcAttempt, +func (c *integratedRoutingContext) testPayment(maxParts uint32) ([]htlcAttempt, error) { var ( @@ -137,7 +137,7 @@ func (c *integratedRoutingContext) testPayment(maxShards uint32) ([]htlcAttempt, DestFeatures: lnwire.NewFeatureVector(mppFeatures, nil), Amount: c.amt, CltvLimit: math.MaxUint32, - MaxShards: maxShards, + MaxParts: maxParts, } session, err := newPaymentSession( diff --git a/routing/integrated_routing_test.go b/routing/integrated_routing_test.go index 1d897d8a86..4f044d8e00 100644 --- a/routing/integrated_routing_test.go +++ b/routing/integrated_routing_test.go @@ -85,7 +85,7 @@ type mppSendTestCase struct { graph func(g *mockGraph) expectedFailure bool - maxShards uint32 + maxParts uint32 } const ( @@ -152,7 +152,7 @@ var mppTestCases = []mppSendTestCase{ chans: []uint64{chanSourceIm2, chanIm2Target}, }, }, - maxShards: 1000, + maxParts: 1000, }, // Test that a cap on the max htlcs makes it impossible to pay. @@ -165,7 +165,7 @@ var mppTestCases = []mppSendTestCase{ expectedAttempts: 2, expectedSuccesses: []expectedHtlcSuccess{}, expectedFailure: true, - maxShards: 1, + maxParts: 1, }, // Test that an attempt is made to split the payment in multiple parts @@ -190,7 +190,7 @@ var mppTestCases = []mppSendTestCase{ }, }, expectedFailure: true, - maxShards: 1000, + maxParts: 1000, }, // Test that no attempts are made if the total local balance is @@ -203,7 +203,7 @@ var mppTestCases = []mppSendTestCase{ amt: 300000, expectedAttempts: 0, expectedFailure: true, - maxShards: 10, + maxParts: 10, }, } @@ -226,7 +226,7 @@ func testMppSend(t *testing.T, testCase *mppSendTestCase) { ctx.amt = lnwire.NewMSatFromSatoshis(testCase.amt) - attempts, err := ctx.testPayment(testCase.maxShards) + attempts, err := ctx.testPayment(testCase.maxParts) switch { case err == nil && testCase.expectedFailure: t.Fatal("expected payment to fail") diff --git a/routing/payment_session.go b/routing/payment_session.go index 5cd8d9f7d7..ed22b8c631 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -263,11 +263,11 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, } // No splitting if this is the last shard. - isLastShard := activeShards+1 >= p.payment.MaxShards + isLastShard := activeShards+1 >= p.payment.MaxParts if isLastShard { p.log.Debugf("not splitting because shard "+ "limit %v has been reached", - p.payment.MaxShards) + p.payment.MaxParts) return nil, errNoPathFound } diff --git a/routing/router.go b/routing/router.go index 2d286ce533..c3773fe6a6 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1625,9 +1625,9 @@ type LightningPayment struct { // fail. DestCustomRecords record.CustomSet - // MaxShards is the maximum number of partial payments that may be used + // MaxParts is the maximum number of partial payments that may be used // to complete the full amount. - MaxShards uint32 + MaxParts uint32 } // SendPayment attempts to send a payment as described within the passed diff --git a/rpcserver.go b/rpcserver.go index 29f40d7a70..2f824de89c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3966,7 +3966,7 @@ func (r *rpcServer) dispatchPaymentIntent( // Don't enable multi-part payments on the main rpc. // Users need to use routerrpc for that. - MaxShards: 1, + MaxParts: 1, } preImage, route, routerErr = r.server.chanRouter.SendPayment( From 0cf63ae8981a1041dd7b9f217dcc2158a28247d3 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 23 Apr 2020 18:13:24 -0700 Subject: [PATCH 521/562] build: bump version to 0.10.0-beta.rc5 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index c3bb8603e8..627b8ee4e8 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc4" + AppPreRelease = "beta.rc5" ) func init() { From d765e73e5778391ec9b9be8fbee946485bf77a0d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Sun, 26 Apr 2020 21:05:13 +0200 Subject: [PATCH 522/562] lncli: add PSBT publish warning --- cmd/lncli/cmd_open_channel.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/lncli/cmd_open_channel.go b/cmd/lncli/cmd_open_channel.go index d86b65cf08..27b275364d 100644 --- a/cmd/lncli/cmd_open_channel.go +++ b/cmd/lncli/cmd_open_channel.go @@ -33,6 +33,10 @@ If you are using a wallet that can fund a PSBT directly (currently not possible with bitcoind), you can use this PSBT that contains the same address and amount: %s +!!! WARNING !!! +DO NOT PUBLISH the finished transaction by yourself or with another tool. +lnd MUST publish it in the proper funding flow order OR THE FUNDS CAN BE LOST! + Paste the funded PSBT here to continue the funding flow. Base64 encoded PSBT: ` From fb17e9b863109669369773365ce409afd435f66b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Sun, 26 Apr 2020 21:05:24 +0200 Subject: [PATCH 523/562] docs: add PSBT publish warning --- docs/psbt.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/psbt.md b/docs/psbt.md index 3d51dbc7fb..17a44ca851 100644 --- a/docs/psbt.md +++ b/docs/psbt.md @@ -34,6 +34,15 @@ about the pending channel. If the remote node is an `lnd` node, we know it's after 10 minutes. **So as long as the whole process takes less than 10 minutes, everything should work fine.** +### Safety warning + +**DO NOT PUBLISH** the finished transaction by yourself or with another tool. +lnd MUST publish it in the proper funding flow order **OR THE FUNDS CAN BE +LOST**! + +This is very important to remember when using wallets like `Wasabi` for +instance, where the "publish" button is very easy to hit by accident. + ### 1. Use the new `--psbt` flag in `lncli openchannel` The new `--psbt` flag in the `openchannel` command starts an interactive dialog @@ -201,7 +210,15 @@ $ bitcoin-cli walletprocesspsbt cHNidP8BAH0CAAAAAbxLLf9+AYfqfF69QAQuETnL6cas7GDi ``` Interpreting the output, we now have a complete, final, and signed transaction -inside the PSBT. Let's give it to `lncli` to continue: +inside the PSBT. + +**!!! WARNING !!!** + +**DO NOT PUBLISH** the finished transaction by yourself or with another tool. +lnd MUST publish it in the proper funding flow order **OR THE FUNDS CAN BE +LOST**! + +Let's give it to `lncli` to continue: ```bash ... From c039aee0590866d0d6b4cb0fa7d7c6ff4ee551ed Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 28 Apr 2020 11:15:44 -0700 Subject: [PATCH 524/562] chainregistry: increase zmq connection timeout with bitcoind backend There seems to be a misinterpretation of a variable between the btcwallet and gozmq libraries. When establish a ZMQ connection, it expects a timeout, which is used to set read deadlines and determine how long we should wait before attempting a reconnection. Within btcwallet and lnd however, this is is interpreted as a polling duration, explaining the current value of 100ms. Under load, especially on less-capable hardware, this leads to high resource usage as we get into a constant reconnection loop. To remedy this, we use a timeout of 5s instead, which is a much more reasonable value for read timeouts, and is also what's used for LN peers. --- chainregistry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainregistry.go b/chainregistry.go index b5df1cf1d2..cd5a378777 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -314,7 +314,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, activeNetParams.Params, bitcoindHost, bitcoindMode.RPCUser, bitcoindMode.RPCPass, bitcoindMode.ZMQPubRawBlock, bitcoindMode.ZMQPubRawTx, - 100*time.Millisecond, + 5*time.Second, ) if err != nil { return nil, err From 1d548684e2b2bbbbf342ac3dd7076371550301ff Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 28 Apr 2020 19:53:28 -0700 Subject: [PATCH 525/562] build: bump version to v0.10.0-beta.rc6 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index 627b8ee4e8..c2f240d5b9 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc5" + AppPreRelease = "beta.rc6" ) func init() { From 1a3194d302f33bb52823297d9d7f75cd37516053 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 29 Apr 2020 10:21:45 -0700 Subject: [PATCH 526/562] build: bump version to v0.10.0-beta --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index c2f240d5b9..33646021c9 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc6" + AppPreRelease = "beta" ) func init() { From 08f25bb5bfae1b8ae0358debd9de005927a6eb14 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 10 Apr 2020 18:26:31 -0700 Subject: [PATCH 527/562] rpcserver: include upfront shutdown script in ListChannels response This field could be omitted from the response if we were unable to calculate the channel's uptime. --- rpcserver.go | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 2f824de89c..a6a42eae00 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3300,6 +3300,25 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, channel.PushAmountSat = uint64(localBalance.ToSatoshis()) } + if len(dbChannel.LocalShutdownScript) > 0 { + _, addresses, _, err := txscript.ExtractPkScriptAddrs( + dbChannel.LocalShutdownScript, activeNetParams.Params, + ) + if err != nil { + return nil, err + } + + // We only expect one upfront shutdown address for a channel. If + // LocalShutdownScript is non-zero, there should be one payout + // address set. + if len(addresses) != 1 { + return nil, fmt.Errorf("expected one upfront shutdown "+ + "address, got: %v", len(addresses)) + } + + channel.CloseAddress = addresses[0].String() + } + outpoint := dbChannel.FundingOutpoint // Get the lifespan observed by the channel event store. If the channel is @@ -3337,25 +3356,6 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, } channel.Uptime = int64(uptime.Seconds()) - if len(dbChannel.LocalShutdownScript) > 0 { - _, addresses, _, err := txscript.ExtractPkScriptAddrs( - dbChannel.LocalShutdownScript, activeNetParams.Params, - ) - if err != nil { - return nil, err - } - - // We only expect one upfront shutdown address for a channel. If - // LocalShutdownScript is non-zero, there should be one payout address - // set. - if len(addresses) != 1 { - return nil, fmt.Errorf("expected one upfront shutdown address, "+ - "got: %v", len(addresses)) - } - - channel.CloseAddress = addresses[0].String() - } - return channel, nil } From 97e5763601edeeb4d20bf65425a87ff4dce99a53 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 10 Apr 2020 18:31:46 -0700 Subject: [PATCH 528/562] rpcserver: omit uptime in ListChannels response if server not started If the server hasn't fully started yet, it's possible that the channel event store hasn't either, so it won't be able to consume any requests until then. To prevent blocking, we'll just omit the uptime related fields for now. --- rpcserver.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index a6a42eae00..196f8b51dc 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3319,11 +3319,18 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph, channel.CloseAddress = addresses[0].String() } - outpoint := dbChannel.FundingOutpoint + // If the server hasn't fully started yet, it's possible that the + // channel event store hasn't either, so it won't be able to consume any + // requests until then. To prevent blocking, we'll just omit the uptime + // related fields for now. + if !r.server.Started() { + return channel, nil + } // Get the lifespan observed by the channel event store. If the channel is // not known to the channel event store, return early because we cannot // calculate any further uptime information. + outpoint := dbChannel.FundingOutpoint startTime, endTime, err := r.server.chanEventStore.GetLifespan(outpoint) switch err { case chanfitness.ErrChannelNotFound: From f8b85eaf1268603855768403f8e2a30faf097ba3 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 4 May 2020 12:13:47 -0700 Subject: [PATCH 529/562] channeldb: eliminate extra copy in QueryPayments In this commit, we eliminate an extraneous copy in the `QueryPayments` method. Before this commit, we would copy each payment from the initial FetchPayments call into a new slice. However, pointers to payments are return from `FetchPayments`, so we can just maintain that same reference rather than copying again when we want to limit our response. --- channeldb/payments.go | 4 ++-- rpcserver.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/channeldb/payments.go b/channeldb/payments.go index 7c5f49a2af..3956dd784b 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -460,7 +460,7 @@ type PaymentsQuery struct { type PaymentsResponse struct { // Payments is the set of payments returned from the database for the // PaymentsQuery. - Payments []MPPayment + Payments []*MPPayment // FirstIndexOffset is the index of the first element in the set of // returned MPPayments. Callers can use this to resume their query @@ -536,7 +536,7 @@ func (db *DB) QueryPayments(query PaymentsQuery) (PaymentsResponse, error) { continue } - resp.Payments = append(resp.Payments, *payment) + resp.Payments = append(resp.Payments, payment) } // Need to swap the payments slice order if reversed order. diff --git a/rpcserver.go b/rpcserver.go index 196f8b51dc..2db89ea66c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -5197,7 +5197,7 @@ func (r *rpcServer) ListPayments(ctx context.Context, for _, payment := range paymentsQuerySlice.Payments { payment := payment - rpcPayment, err := r.routerBackend.MarshallPayment(&payment) + rpcPayment, err := r.routerBackend.MarshallPayment(payment) if err != nil { return nil, err } From 08da73731608d281320244f26ac81469d431a97c Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 4 May 2020 09:33:25 +0200 Subject: [PATCH 530/562] lnrpc: add failure detail none to link event rpc --- lnrpc/routerrpc/subscribe_events.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lnrpc/routerrpc/subscribe_events.go b/lnrpc/routerrpc/subscribe_events.go index 4454dbda2f..d44b54a773 100644 --- a/lnrpc/routerrpc/subscribe_events.go +++ b/lnrpc/routerrpc/subscribe_events.go @@ -120,15 +120,21 @@ func rpcFailReason(linkErr *htlcswitch.LinkError) (lnrpc.Failure_FailureCode, if err != nil { return 0, 0, err } + wireCode := wireErr.GetCode() + + // If the link has no failure detail, return with failure detail none. + if linkErr.FailureDetail == nil { + return wireCode, FailureDetail_NO_DETAIL, nil + } switch failureDetail := linkErr.FailureDetail.(type) { case invoices.FailResolutionResult: fd, err := rpcFailureResolution(failureDetail) - return wireErr.GetCode(), fd, err + return wireCode, fd, err case htlcswitch.OutgoingFailure: fd, err := rpcOutgoingFailure(failureDetail) - return wireErr.GetCode(), fd, err + return wireCode, fd, err default: return 0, 0, fmt.Errorf("unknown failure "+ From d70f77efaf8930669f12865e355b122d7a51a88a Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 4 May 2020 09:47:01 +0200 Subject: [PATCH 531/562] lntest/test: move multi-hop payments test into own file --- lntest/itest/lnd_multi-hop-payments.go | 289 +++++++++++++++++++++++++ lntest/itest/lnd_test.go | 275 ----------------------- 2 files changed, 289 insertions(+), 275 deletions(-) create mode 100644 lntest/itest/lnd_multi-hop-payments.go diff --git a/lntest/itest/lnd_multi-hop-payments.go b/lntest/itest/lnd_multi-hop-payments.go new file mode 100644 index 0000000000..fde4c8c900 --- /dev/null +++ b/lntest/itest/lnd_multi-hop-payments.go @@ -0,0 +1,289 @@ +// +build rpctest + +package itest + +import ( + "context" + "time" + + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lntest" +) + +func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() + + const chanAmt = btcutil.Amount(100000) + var networkChans []*lnrpc.ChannelPoint + + // Open a channel with 100k satoshis between Alice and Bob with Alice + // being the sole funder of the channel. + ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) + chanPointAlice := openChannelAndAssert( + ctxt, t, net, net.Alice, net.Bob, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + networkChans = append(networkChans, chanPointAlice) + + aliceChanTXID, err := lnd.GetChanPointFundingTxid(chanPointAlice) + if err != nil { + t.Fatalf("unable to get txid: %v", err) + } + aliceFundPoint := wire.OutPoint{ + Hash: *aliceChanTXID, + Index: chanPointAlice.OutputIndex, + } + + // As preliminary setup, we'll create two new nodes: Carol and Dave, + // such that we now have a 4 node, 3 channel topology. Dave will make a + // channel with Alice, and Carol with Dave. After this setup, the + // network topology should now look like: + // Carol -> Dave -> Alice -> Bob + // + // First, we'll create Dave and establish a channel to Alice. Dave will + // be running an older node that requires the legacy onion payload. + daveArgs := []string{"--protocol.legacyonion"} + dave, err := net.NewNode("Dave", daveArgs) + if err != nil { + t.Fatalf("unable to create new nodes: %v", err) + } + defer shutdownAndAssert(net, t, dave) + + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + if err := net.ConnectNodes(ctxt, dave, net.Alice); err != nil { + t.Fatalf("unable to connect dave to alice: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, dave) + if err != nil { + t.Fatalf("unable to send coins to dave: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) + chanPointDave := openChannelAndAssert( + ctxt, t, net, dave, net.Alice, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + networkChans = append(networkChans, chanPointDave) + daveChanTXID, err := lnd.GetChanPointFundingTxid(chanPointDave) + if err != nil { + t.Fatalf("unable to get txid: %v", err) + } + daveFundPoint := wire.OutPoint{ + Hash: *daveChanTXID, + Index: chanPointDave.OutputIndex, + } + + // Next, we'll create Carol and establish a channel to from her to + // Dave. + carol, err := net.NewNode("Carol", nil) + if err != nil { + t.Fatalf("unable to create new nodes: %v", err) + } + defer shutdownAndAssert(net, t, carol) + + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + if err := net.ConnectNodes(ctxt, carol, dave); err != nil { + t.Fatalf("unable to connect carol to dave: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, carol) + if err != nil { + t.Fatalf("unable to send coins to carol: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) + chanPointCarol := openChannelAndAssert( + ctxt, t, net, carol, dave, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + networkChans = append(networkChans, chanPointCarol) + + carolChanTXID, err := lnd.GetChanPointFundingTxid(chanPointCarol) + if err != nil { + t.Fatalf("unable to get txid: %v", err) + } + carolFundPoint := wire.OutPoint{ + Hash: *carolChanTXID, + Index: chanPointCarol.OutputIndex, + } + + // Wait for all nodes to have seen all channels. + nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol, dave} + nodeNames := []string{"Alice", "Bob", "Carol", "Dave"} + for _, chanPoint := range networkChans { + for i, node := range nodes { + txid, err := lnd.GetChanPointFundingTxid(chanPoint) + if err != nil { + t.Fatalf("unable to get txid: %v", err) + } + point := wire.OutPoint{ + Hash: *txid, + Index: chanPoint.OutputIndex, + } + + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = node.WaitForNetworkChannelOpen(ctxt, chanPoint) + if err != nil { + t.Fatalf("%s(%d): timeout waiting for "+ + "channel(%s) open: %v", nodeNames[i], + node.NodeID, point, err) + } + } + } + + // Create 5 invoices for Bob, which expect a payment from Carol for 1k + // satoshis with a different preimage each time. + const numPayments = 5 + const paymentAmt = 1000 + payReqs, _, _, err := createPayReqs( + net.Bob, paymentAmt, numPayments, + ) + if err != nil { + t.Fatalf("unable to create pay reqs: %v", err) + } + + // We'll wait for all parties to recognize the new channels within the + // network. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = dave.WaitForNetworkChannelOpen(ctxt, chanPointDave) + if err != nil { + t.Fatalf("dave didn't advertise his channel: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = carol.WaitForNetworkChannelOpen(ctxt, chanPointCarol) + if err != nil { + t.Fatalf("carol didn't advertise her channel in time: %v", + err) + } + + time.Sleep(time.Millisecond * 50) + + // Set the fee policies of the Alice -> Bob and the Dave -> Alice + // channel edges to relatively large non default values. This makes it + // possible to pick up more subtle fee calculation errors. + maxHtlc := uint64(calculateMaxHtlc(chanAmt)) + updateChannelPolicy( + t, net.Alice, chanPointAlice, 1000, 100000, + lnd.DefaultBitcoinTimeLockDelta, maxHtlc, carol, + ) + + updateChannelPolicy( + t, dave, chanPointDave, 5000, 150000, + lnd.DefaultBitcoinTimeLockDelta, maxHtlc, carol, + ) + + // Using Carol as the source, pay to the 5 invoices from Bob created + // above. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = completePaymentRequests(ctxt, carol, payReqs, true) + if err != nil { + t.Fatalf("unable to send payments: %v", err) + } + + // When asserting the amount of satoshis moved, we'll factor in the + // default base fee, as we didn't modify the fee structure when + // creating the seed nodes in the network. + const baseFee = 1 + + // At this point all the channels within our proto network should be + // shifted by 5k satoshis in the direction of Bob, the sink within the + // payment flow generated above. The order of asserts corresponds to + // increasing of time is needed to embed the HTLC in commitment + // transaction, in channel Carol->David->Alice->Bob, order is Bob, + // Alice, David, Carol. + + // The final node bob expects to get paid five times 1000 sat. + expectedAmountPaidAtoB := int64(5 * 1000) + + assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Bob, + aliceFundPoint, int64(0), expectedAmountPaidAtoB) + assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Alice, + aliceFundPoint, expectedAmountPaidAtoB, int64(0)) + + // To forward a payment of 1000 sat, Alice is charging a fee of + // 1 sat + 10% = 101 sat. + const expectedFeeAlice = 5 * 101 + + // Dave needs to pay what Alice pays plus Alice's fee. + expectedAmountPaidDtoA := expectedAmountPaidAtoB + expectedFeeAlice + + assertAmountPaid(t, "Dave(local) => Alice(remote)", net.Alice, + daveFundPoint, int64(0), expectedAmountPaidDtoA) + assertAmountPaid(t, "Dave(local) => Alice(remote)", dave, + daveFundPoint, expectedAmountPaidDtoA, int64(0)) + + // To forward a payment of 1101 sat, Dave is charging a fee of + // 5 sat + 15% = 170.15 sat. This is rounded down in rpcserver to 170. + const expectedFeeDave = 5 * 170 + + // Carol needs to pay what Dave pays plus Dave's fee. + expectedAmountPaidCtoD := expectedAmountPaidDtoA + expectedFeeDave + + assertAmountPaid(t, "Carol(local) => Dave(remote)", dave, + carolFundPoint, int64(0), expectedAmountPaidCtoD) + assertAmountPaid(t, "Carol(local) => Dave(remote)", carol, + carolFundPoint, expectedAmountPaidCtoD, int64(0)) + + // Now that we know all the balances have been settled out properly, + // we'll ensure that our internal record keeping for completed circuits + // was properly updated. + + // First, check that the FeeReport response shows the proper fees + // accrued over each time range. Dave should've earned 170 satoshi for + // each of the forwarded payments. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + feeReport, err := dave.FeeReport(ctxt, &lnrpc.FeeReportRequest{}) + if err != nil { + t.Fatalf("unable to query for fee report: %v", err) + } + + if feeReport.DayFeeSum != uint64(expectedFeeDave) { + t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, + feeReport.DayFeeSum) + } + if feeReport.WeekFeeSum != uint64(expectedFeeDave) { + t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, + feeReport.WeekFeeSum) + } + if feeReport.MonthFeeSum != uint64(expectedFeeDave) { + t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, + feeReport.MonthFeeSum) + } + + // Next, ensure that if we issue the vanilla query for the forwarding + // history, it returns 5 values, and each entry is formatted properly. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + fwdingHistory, err := dave.ForwardingHistory( + ctxt, &lnrpc.ForwardingHistoryRequest{}, + ) + if err != nil { + t.Fatalf("unable to query for fee report: %v", err) + } + if len(fwdingHistory.ForwardingEvents) != 5 { + t.Fatalf("wrong number of forwarding event: expected %v, "+ + "got %v", 5, len(fwdingHistory.ForwardingEvents)) + } + expectedForwardingFee := uint64(expectedFeeDave / numPayments) + for _, event := range fwdingHistory.ForwardingEvents { + // Each event should show a fee of 170 satoshi. + if event.Fee != expectedForwardingFee { + t.Fatalf("fee mismatch: expected %v, got %v", + expectedForwardingFee, event.Fee) + } + } + + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false) + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, dave, chanPointDave, false) + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, carol, chanPointCarol, false) +} diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index b5e1eade46..9d56f108f6 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -4504,281 +4504,6 @@ func updateChannelPolicy(t *harnessTest, node *lntest.HarnessNode, ) } -func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { - ctxb := context.Background() - - const chanAmt = btcutil.Amount(100000) - var networkChans []*lnrpc.ChannelPoint - - // Open a channel with 100k satoshis between Alice and Bob with Alice - // being the sole funder of the channel. - ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) - chanPointAlice := openChannelAndAssert( - ctxt, t, net, net.Alice, net.Bob, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - networkChans = append(networkChans, chanPointAlice) - - aliceChanTXID, err := lnd.GetChanPointFundingTxid(chanPointAlice) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - aliceFundPoint := wire.OutPoint{ - Hash: *aliceChanTXID, - Index: chanPointAlice.OutputIndex, - } - - // As preliminary setup, we'll create two new nodes: Carol and Dave, - // such that we now have a 4 node, 3 channel topology. Dave will make a - // channel with Alice, and Carol with Dave. After this setup, the - // network topology should now look like: - // Carol -> Dave -> Alice -> Bob - // - // First, we'll create Dave and establish a channel to Alice. Dave will - // be running an older node that requires the legacy onion payload. - daveArgs := []string{"--protocol.legacyonion"} - dave, err := net.NewNode("Dave", daveArgs) - if err != nil { - t.Fatalf("unable to create new nodes: %v", err) - } - defer shutdownAndAssert(net, t, dave) - - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, dave, net.Alice); err != nil { - t.Fatalf("unable to connect dave to alice: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, dave) - if err != nil { - t.Fatalf("unable to send coins to dave: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - chanPointDave := openChannelAndAssert( - ctxt, t, net, dave, net.Alice, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - networkChans = append(networkChans, chanPointDave) - daveChanTXID, err := lnd.GetChanPointFundingTxid(chanPointDave) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - daveFundPoint := wire.OutPoint{ - Hash: *daveChanTXID, - Index: chanPointDave.OutputIndex, - } - - // Next, we'll create Carol and establish a channel to from her to - // Dave. - carol, err := net.NewNode("Carol", nil) - if err != nil { - t.Fatalf("unable to create new nodes: %v", err) - } - defer shutdownAndAssert(net, t, carol) - - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, carol, dave); err != nil { - t.Fatalf("unable to connect carol to dave: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, carol) - if err != nil { - t.Fatalf("unable to send coins to carol: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - chanPointCarol := openChannelAndAssert( - ctxt, t, net, carol, dave, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - networkChans = append(networkChans, chanPointCarol) - - carolChanTXID, err := lnd.GetChanPointFundingTxid(chanPointCarol) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - carolFundPoint := wire.OutPoint{ - Hash: *carolChanTXID, - Index: chanPointCarol.OutputIndex, - } - - // Wait for all nodes to have seen all channels. - nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol, dave} - nodeNames := []string{"Alice", "Bob", "Carol", "Dave"} - for _, chanPoint := range networkChans { - for i, node := range nodes { - txid, err := lnd.GetChanPointFundingTxid(chanPoint) - if err != nil { - t.Fatalf("unable to get txid: %v", err) - } - point := wire.OutPoint{ - Hash: *txid, - Index: chanPoint.OutputIndex, - } - - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = node.WaitForNetworkChannelOpen(ctxt, chanPoint) - if err != nil { - t.Fatalf("%s(%d): timeout waiting for "+ - "channel(%s) open: %v", nodeNames[i], - node.NodeID, point, err) - } - } - } - - // Create 5 invoices for Bob, which expect a payment from Carol for 1k - // satoshis with a different preimage each time. - const numPayments = 5 - const paymentAmt = 1000 - payReqs, _, _, err := createPayReqs( - net.Bob, paymentAmt, numPayments, - ) - if err != nil { - t.Fatalf("unable to create pay reqs: %v", err) - } - - // We'll wait for all parties to recognize the new channels within the - // network. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = dave.WaitForNetworkChannelOpen(ctxt, chanPointDave) - if err != nil { - t.Fatalf("dave didn't advertise his channel: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = carol.WaitForNetworkChannelOpen(ctxt, chanPointCarol) - if err != nil { - t.Fatalf("carol didn't advertise her channel in time: %v", - err) - } - - time.Sleep(time.Millisecond * 50) - - // Set the fee policies of the Alice -> Bob and the Dave -> Alice - // channel edges to relatively large non default values. This makes it - // possible to pick up more subtle fee calculation errors. - maxHtlc := uint64(calculateMaxHtlc(chanAmt)) - updateChannelPolicy( - t, net.Alice, chanPointAlice, 1000, 100000, - lnd.DefaultBitcoinTimeLockDelta, maxHtlc, carol, - ) - - updateChannelPolicy( - t, dave, chanPointDave, 5000, 150000, - lnd.DefaultBitcoinTimeLockDelta, maxHtlc, carol, - ) - - // Using Carol as the source, pay to the 5 invoices from Bob created - // above. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = completePaymentRequests(ctxt, carol, payReqs, true) - if err != nil { - t.Fatalf("unable to send payments: %v", err) - } - - // When asserting the amount of satoshis moved, we'll factor in the - // default base fee, as we didn't modify the fee structure when - // creating the seed nodes in the network. - const baseFee = 1 - - // At this point all the channels within our proto network should be - // shifted by 5k satoshis in the direction of Bob, the sink within the - // payment flow generated above. The order of asserts corresponds to - // increasing of time is needed to embed the HTLC in commitment - // transaction, in channel Carol->David->Alice->Bob, order is Bob, - // Alice, David, Carol. - - // The final node bob expects to get paid five times 1000 sat. - expectedAmountPaidAtoB := int64(5 * 1000) - - assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Bob, - aliceFundPoint, int64(0), expectedAmountPaidAtoB) - assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Alice, - aliceFundPoint, expectedAmountPaidAtoB, int64(0)) - - // To forward a payment of 1000 sat, Alice is charging a fee of - // 1 sat + 10% = 101 sat. - const expectedFeeAlice = 5 * 101 - - // Dave needs to pay what Alice pays plus Alice's fee. - expectedAmountPaidDtoA := expectedAmountPaidAtoB + expectedFeeAlice - - assertAmountPaid(t, "Dave(local) => Alice(remote)", net.Alice, - daveFundPoint, int64(0), expectedAmountPaidDtoA) - assertAmountPaid(t, "Dave(local) => Alice(remote)", dave, - daveFundPoint, expectedAmountPaidDtoA, int64(0)) - - // To forward a payment of 1101 sat, Dave is charging a fee of - // 5 sat + 15% = 170.15 sat. This is rounded down in rpcserver to 170. - const expectedFeeDave = 5 * 170 - - // Carol needs to pay what Dave pays plus Dave's fee. - expectedAmountPaidCtoD := expectedAmountPaidDtoA + expectedFeeDave - - assertAmountPaid(t, "Carol(local) => Dave(remote)", dave, - carolFundPoint, int64(0), expectedAmountPaidCtoD) - assertAmountPaid(t, "Carol(local) => Dave(remote)", carol, - carolFundPoint, expectedAmountPaidCtoD, int64(0)) - - // Now that we know all the balances have been settled out properly, - // we'll ensure that our internal record keeping for completed circuits - // was properly updated. - - // First, check that the FeeReport response shows the proper fees - // accrued over each time range. Dave should've earned 170 satoshi for - // each of the forwarded payments. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - feeReport, err := dave.FeeReport(ctxt, &lnrpc.FeeReportRequest{}) - if err != nil { - t.Fatalf("unable to query for fee report: %v", err) - } - - if feeReport.DayFeeSum != uint64(expectedFeeDave) { - t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, - feeReport.DayFeeSum) - } - if feeReport.WeekFeeSum != uint64(expectedFeeDave) { - t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, - feeReport.WeekFeeSum) - } - if feeReport.MonthFeeSum != uint64(expectedFeeDave) { - t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, - feeReport.MonthFeeSum) - } - - // Next, ensure that if we issue the vanilla query for the forwarding - // history, it returns 5 values, and each entry is formatted properly. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - fwdingHistory, err := dave.ForwardingHistory( - ctxt, &lnrpc.ForwardingHistoryRequest{}, - ) - if err != nil { - t.Fatalf("unable to query for fee report: %v", err) - } - if len(fwdingHistory.ForwardingEvents) != 5 { - t.Fatalf("wrong number of forwarding event: expected %v, "+ - "got %v", 5, len(fwdingHistory.ForwardingEvents)) - } - expectedForwardingFee := uint64(expectedFeeDave / numPayments) - for _, event := range fwdingHistory.ForwardingEvents { - // Each event should show a fee of 170 satoshi. - if event.Fee != expectedForwardingFee { - t.Fatalf("fee mismatch: expected %v, got %v", - expectedForwardingFee, event.Fee) - } - } - - ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false) - ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, dave, chanPointDave, false) - ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, carol, chanPointCarol, false) -} - type singleHopSendToRouteCase struct { name string From 926892c906a4acbb525361b38443dec1b05ac3c9 Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 4 May 2020 09:52:15 +0200 Subject: [PATCH 532/562] lntest/test: test htlcnotifier stream for successful multi-hop payments --- lntest/itest/lnd_multi-hop-payments.go | 118 +++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/lntest/itest/lnd_multi-hop-payments.go b/lntest/itest/lnd_multi-hop-payments.go index fde4c8c900..39a48a0858 100644 --- a/lntest/itest/lnd_multi-hop-payments.go +++ b/lntest/itest/lnd_multi-hop-payments.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" ) @@ -180,6 +181,39 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { lnd.DefaultBitcoinTimeLockDelta, maxHtlc, carol, ) + // Before we start sending payments, subscribe to htlc events for each + // node. + ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + + aliceEvents, err := net.Alice.RouterClient.SubscribeHtlcEvents( + ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, + ) + if err != nil { + t.Fatalf("could not subscribe events: %v", err) + } + + bobEvents, err := net.Bob.RouterClient.SubscribeHtlcEvents( + ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, + ) + if err != nil { + t.Fatalf("could not subscribe events: %v", err) + } + + carolEvents, err := carol.RouterClient.SubscribeHtlcEvents( + ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, + ) + if err != nil { + t.Fatalf("could not subscribe events: %v", err) + } + + daveEvents, err := dave.RouterClient.SubscribeHtlcEvents( + ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, + ) + if err != nil { + t.Fatalf("could not subscribe events: %v", err) + } + // Using Carol as the source, pay to the 5 invoices from Bob created // above. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) @@ -280,6 +314,29 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { } } + // We expect Carol to have successful forwards and settles for + // her sends. + assertHtlcEvents( + t, numPayments, 0, numPayments, routerrpc.HtlcEvent_SEND, + carolEvents, + ) + + // Dave and Alice should both have forwards and settles for + // their role as forwarding nodes. + assertHtlcEvents( + t, numPayments, 0, numPayments, routerrpc.HtlcEvent_FORWARD, + daveEvents, + ) + assertHtlcEvents( + t, numPayments, 0, numPayments, routerrpc.HtlcEvent_FORWARD, + aliceEvents, + ) + + // Bob should only have settle events for his receives. + assertHtlcEvents( + t, 0, 0, numPayments, routerrpc.HtlcEvent_RECEIVE, bobEvents, + ) + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false) ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) @@ -287,3 +344,64 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) closeChannelAndAssert(ctxt, t, net, carol, chanPointCarol, false) } + +// assertHtlcEvents consumes events from a client and ensures that they are of +// the expected type and contain the expected number of forwards, forward +// failures and settles. +func assertHtlcEvents(t *harnessTest, fwdCount, fwdFailCount, settleCount int, + userType routerrpc.HtlcEvent_EventType, + client routerrpc.Router_SubscribeHtlcEventsClient) { + + var forwards, forwardFails, settles int + + numEvents := fwdCount + fwdFailCount + settleCount + for i := 0; i < numEvents; i++ { + event := assertEventAndType(t, userType, client) + + switch event.Event.(type) { + case *routerrpc.HtlcEvent_ForwardEvent: + forwards++ + + case *routerrpc.HtlcEvent_ForwardFailEvent: + forwardFails++ + + case *routerrpc.HtlcEvent_SettleEvent: + settles++ + + default: + t.Fatalf("unexpected event: %T", event.Event) + } + } + + if forwards != fwdCount { + t.Fatalf("expected: %v forwards, got: %v", fwdCount, forwards) + } + + if forwardFails != fwdFailCount { + t.Fatalf("expected: %v forward fails, got: %v", fwdFailCount, + forwardFails) + } + + if settles != settleCount { + t.Fatalf("expected: %v settles, got: %v", settleCount, settles) + } +} + +// assertEventAndType reads an event from the stream provided and ensures that +// it is associated with the correct user related type - a user initiated send, +// a receive to our node or a forward through our node. Note that this event +// type is different from the htlc event type (forward, link failure etc). +func assertEventAndType(t *harnessTest, eventType routerrpc.HtlcEvent_EventType, + client routerrpc.Router_SubscribeHtlcEventsClient) *routerrpc.HtlcEvent { + event, err := client.Recv() + if err != nil { + t.Fatalf("could not get event") + } + + if event.EventType != eventType { + t.Fatalf("expected: %v, got: %v", eventType, + event.EventType) + } + + return event +} From a80c69982d44173df756fc85edecf515960d561a Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 4 May 2020 09:55:35 +0200 Subject: [PATCH 533/562] lntest/test: move multi-hop error propagation into its own file --- .../itest/lnd_multi-hop-error-propagation.go | 342 ++++++++++++++++++ lntest/itest/lnd_test.go | 326 ----------------- 2 files changed, 342 insertions(+), 326 deletions(-) create mode 100644 lntest/itest/lnd_multi-hop-error-propagation.go diff --git a/lntest/itest/lnd_multi-hop-error-propagation.go b/lntest/itest/lnd_multi-hop-error-propagation.go new file mode 100644 index 0000000000..9e567b1e9f --- /dev/null +++ b/lntest/itest/lnd_multi-hop-error-propagation.go @@ -0,0 +1,342 @@ +// +build rpctest + +package itest + +import ( + "context" + "encoding/hex" + "strings" + "time" + + "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/lntest" + "github.com/lightningnetwork/lnd/lnwire" +) + +func testHtlcErrorPropagation(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() + + // In this test we wish to exercise the daemon's correct parsing, + // handling, and propagation of errors that occur while processing a + // multi-hop payment. + const chanAmt = lnd.MaxBtcFundingAmount + + // First establish a channel with a capacity of 0.5 BTC between Alice + // and Bob. + ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) + chanPointAlice := openChannelAndAssert( + ctxt, t, net, net.Alice, net.Bob, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + if err := net.Alice.WaitForNetworkChannelOpen(ctxt, chanPointAlice); err != nil { + t.Fatalf("channel not seen by alice before timeout: %v", err) + } + + cType, err := channelCommitType(net.Alice, chanPointAlice) + if err != nil { + t.Fatalf("unable to get channel type: %v", err) + } + + commitFee := cType.calcStaticFee(0) + assertBaseBalance := func() { + balReq := &lnrpc.ChannelBalanceRequest{} + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + aliceBal, err := net.Alice.ChannelBalance(ctxt, balReq) + if err != nil { + t.Fatalf("unable to get channel balance: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + bobBal, err := net.Bob.ChannelBalance(ctxt, balReq) + if err != nil { + t.Fatalf("unable to get channel balance: %v", err) + } + if aliceBal.Balance != int64(chanAmt-commitFee) { + t.Fatalf("alice has an incorrect balance: expected %v got %v", + int64(chanAmt-commitFee), aliceBal) + } + if bobBal.Balance != int64(chanAmt-commitFee) { + t.Fatalf("bob has an incorrect balance: expected %v got %v", + int64(chanAmt-commitFee), bobBal) + } + } + + // Since we'd like to test some multi-hop failure scenarios, we'll + // introduce another node into our test network: Carol. + carol, err := net.NewNode("Carol", nil) + if err != nil { + t.Fatalf("unable to create new nodes: %v", err) + } + + // Next, we'll create a connection from Bob to Carol, and open a + // channel between them so we have the topology: Alice -> Bob -> Carol. + // The channel created will be of lower capacity that the one created + // above. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + if err := net.ConnectNodes(ctxt, net.Bob, carol); err != nil { + t.Fatalf("unable to connect bob to carol: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) + const bobChanAmt = lnd.MaxBtcFundingAmount + chanPointBob := openChannelAndAssert( + ctxt, t, net, net.Bob, carol, + lntest.OpenChannelParams{ + Amt: chanAmt, + }, + ) + + // Ensure that Alice has Carol in her routing table before proceeding. + nodeInfoReq := &lnrpc.NodeInfoRequest{ + PubKey: carol.PubKeyStr, + } + checkTableTimeout := time.After(time.Second * 10) + checkTableTicker := time.NewTicker(100 * time.Millisecond) + defer checkTableTicker.Stop() + +out: + // TODO(roasbeef): make into async hook for node announcements + for { + select { + case <-checkTableTicker.C: + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + _, err := net.Alice.GetNodeInfo(ctxt, nodeInfoReq) + if err != nil && strings.Contains(err.Error(), + "unable to find") { + + continue + } + + break out + case <-checkTableTimeout: + t.Fatalf("carol's node announcement didn't propagate within " + + "the timeout period") + } + } + + // With the channels, open we can now start to test our multi-hop error + // scenarios. First, we'll generate an invoice from carol that we'll + // use to test some error cases. + const payAmt = 10000 + invoiceReq := &lnrpc.Invoice{ + Memo: "kek99", + Value: payAmt, + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + carolInvoice, err := carol.AddInvoice(ctxt, invoiceReq) + if err != nil { + t.Fatalf("unable to generate carol invoice: %v", err) + } + + carolPayReq, err := carol.DecodePayReq(ctxb, + &lnrpc.PayReqString{ + PayReq: carolInvoice.PaymentRequest, + }) + if err != nil { + t.Fatalf("unable to decode generated payment request: %v", err) + } + + // Before we send the payment, ensure that the announcement of the new + // channel has been processed by Alice. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + if err := net.Alice.WaitForNetworkChannelOpen(ctxt, chanPointBob); err != nil { + t.Fatalf("channel not seen by alice before timeout: %v", err) + } + + // For the first scenario, we'll test the cancellation of an HTLC with + // an unknown payment hash. + // TODO(roasbeef): return failure response rather than failing entire + // stream on payment error. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + sendReq := &lnrpc.SendRequest{ + PaymentHashString: hex.EncodeToString(makeFakePayHash(t)), + DestString: hex.EncodeToString(carol.PubKey[:]), + Amt: payAmt, + FinalCltvDelta: int32(carolPayReq.CltvExpiry), + } + resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) + if err != nil { + t.Fatalf("unable to send payment: %v", err) + } + + // The payment should have resulted in an error since we sent it with the + // wrong payment hash. + if resp.PaymentError == "" { + t.Fatalf("payment should have been rejected due to invalid " + + "payment hash") + } + + assertLastHTLCError( + t, net.Alice, + lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, + ) + + // The balances of all parties should be the same as initially since + // the HTLC was canceled. + assertBaseBalance() + + // Next, we'll test the case of a recognized payHash but, an incorrect + // value on the extended HTLC. + htlcAmt := lnwire.NewMSatFromSatoshis(1000) + sendReq = &lnrpc.SendRequest{ + PaymentHashString: hex.EncodeToString(carolInvoice.RHash), + DestString: hex.EncodeToString(carol.PubKey[:]), + Amt: int64(htlcAmt.ToSatoshis()), // 10k satoshis are expected. + FinalCltvDelta: int32(carolPayReq.CltvExpiry), + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) + if err != nil { + t.Fatalf("unable to send payment: %v", err) + } + + // The payment should fail with an error since we sent 1k satoshis isn't of + // 10k as was requested. + if resp.PaymentError == "" { + t.Fatalf("payment should have been rejected due to wrong " + + "HTLC amount") + } + + assertLastHTLCError( + t, net.Alice, + lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, + ) + + // The balances of all parties should be the same as initially since + // the HTLC was canceled. + assertBaseBalance() + + // Next we'll test an error that occurs mid-route due to an outgoing + // link having insufficient capacity. In order to do so, we'll first + // need to unbalance the link connecting Bob<->Carol. + ctx, cancel := context.WithCancel(ctxb) + defer cancel() + + bobPayStream, err := net.Bob.SendPayment(ctx) + if err != nil { + t.Fatalf("unable to create payment stream: %v", err) + } + + // To do so, we'll push most of the funds in the channel over to + // Alice's side, leaving on 10k satoshis of available balance for bob. + // There's a max payment amount, so we'll have to do this + // incrementally. + chanReserve := int64(chanAmt / 100) + amtToSend := int64(chanAmt) - chanReserve - 20000 + amtSent := int64(0) + for amtSent != amtToSend { + // We'll send in chunks of the max payment amount. If we're + // about to send too much, then we'll only send the amount + // remaining. + toSend := int64(lnd.MaxPaymentMSat.ToSatoshis()) + if toSend+amtSent > amtToSend { + toSend = amtToSend - amtSent + } + + invoiceReq = &lnrpc.Invoice{ + Value: toSend, + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + carolInvoice2, err := carol.AddInvoice(ctxt, invoiceReq) + if err != nil { + t.Fatalf("unable to generate carol invoice: %v", err) + } + if err := bobPayStream.Send(&lnrpc.SendRequest{ + PaymentRequest: carolInvoice2.PaymentRequest, + }); err != nil { + t.Fatalf("unable to send payment: %v", err) + } + + if resp, err := bobPayStream.Recv(); err != nil { + t.Fatalf("payment stream has been closed: %v", err) + } else if resp.PaymentError != "" { + t.Fatalf("bob's payment failed: %v", resp.PaymentError) + } + + amtSent += toSend + } + + // At this point, Alice has 50mil satoshis on her side of the channel, + // but Bob only has 10k available on his side of the channel. So a + // payment from Alice to Carol worth 100k satoshis should fail. + invoiceReq = &lnrpc.Invoice{ + Value: 100000, + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + carolInvoice3, err := carol.AddInvoice(ctxt, invoiceReq) + if err != nil { + t.Fatalf("unable to generate carol invoice: %v", err) + } + + sendReq = &lnrpc.SendRequest{ + PaymentRequest: carolInvoice3.PaymentRequest, + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) + if err != nil { + t.Fatalf("unable to send payment: %v", err) + } + if resp.PaymentError == "" { + t.Fatalf("payment should fail due to insufficient "+ + "capacity: %v", err) + } + + assertLastHTLCError( + t, net.Alice, lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE, + ) + + // Generate new invoice to not pay same invoice twice. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + carolInvoice, err = carol.AddInvoice(ctxt, invoiceReq) + if err != nil { + t.Fatalf("unable to generate carol invoice: %v", err) + } + + // For our final test, we'll ensure that if a target link isn't + // available for what ever reason then the payment fails accordingly. + // + // We'll attempt to complete the original invoice we created with Carol + // above, but before we do so, Carol will go offline, resulting in a + // failed payment. + shutdownAndAssert(net, t, carol) + + // Reset mission control to forget the temporary channel failure above. + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + _, err = net.Alice.RouterClient.ResetMissionControl( + ctxt, &routerrpc.ResetMissionControlRequest{}, + ) + if err != nil { + t.Fatalf("unable to reset mission control: %v", err) + } + + sendReq = &lnrpc.SendRequest{ + PaymentRequest: carolInvoice.PaymentRequest, + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) + if err != nil { + t.Fatalf("unable to send payment: %v", err) + } + + if resp.PaymentError == "" { + t.Fatalf("payment should have failed") + } + + assertLastHTLCError(t, net.Alice, lnrpc.Failure_UNKNOWN_NEXT_PEER) + + // Finally, immediately close the channel. This function will also + // block until the channel is closed and will additionally assert the + // relevant channel closing post conditions. + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false) + + // Force close Bob's final channel. + ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) + closeChannelAndAssert(ctxt, t, net, net.Bob, chanPointBob, true) + + // Cleanup by mining the force close and sweep transaction. + cleanupForceClose(t, net, net.Bob, chanPointBob) +} diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 9d56f108f6..d6f93474c6 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -9106,332 +9106,6 @@ func assertNodeNumChannels(t *harnessTest, node *lntest.HarnessNode, } } -func testHtlcErrorPropagation(net *lntest.NetworkHarness, t *harnessTest) { - ctxb := context.Background() - - // In this test we wish to exercise the daemon's correct parsing, - // handling, and propagation of errors that occur while processing a - // multi-hop payment. - const chanAmt = lnd.MaxBtcFundingAmount - - // First establish a channel with a capacity of 0.5 BTC between Alice - // and Bob. - ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) - chanPointAlice := openChannelAndAssert( - ctxt, t, net, net.Alice, net.Bob, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - if err := net.Alice.WaitForNetworkChannelOpen(ctxt, chanPointAlice); err != nil { - t.Fatalf("channel not seen by alice before timeout: %v", err) - } - - cType, err := channelCommitType(net.Alice, chanPointAlice) - if err != nil { - t.Fatalf("unable to get channel type: %v", err) - } - - commitFee := cType.calcStaticFee(0) - assertBaseBalance := func() { - balReq := &lnrpc.ChannelBalanceRequest{} - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - aliceBal, err := net.Alice.ChannelBalance(ctxt, balReq) - if err != nil { - t.Fatalf("unable to get channel balance: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - bobBal, err := net.Bob.ChannelBalance(ctxt, balReq) - if err != nil { - t.Fatalf("unable to get channel balance: %v", err) - } - if aliceBal.Balance != int64(chanAmt-commitFee) { - t.Fatalf("alice has an incorrect balance: expected %v got %v", - int64(chanAmt-commitFee), aliceBal) - } - if bobBal.Balance != int64(chanAmt-commitFee) { - t.Fatalf("bob has an incorrect balance: expected %v got %v", - int64(chanAmt-commitFee), bobBal) - } - } - - // Since we'd like to test some multi-hop failure scenarios, we'll - // introduce another node into our test network: Carol. - carol, err := net.NewNode("Carol", nil) - if err != nil { - t.Fatalf("unable to create new nodes: %v", err) - } - - // Next, we'll create a connection from Bob to Carol, and open a - // channel between them so we have the topology: Alice -> Bob -> Carol. - // The channel created will be of lower capacity that the one created - // above. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - if err := net.ConnectNodes(ctxt, net.Bob, carol); err != nil { - t.Fatalf("unable to connect bob to carol: %v", err) - } - ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout) - const bobChanAmt = lnd.MaxBtcFundingAmount - chanPointBob := openChannelAndAssert( - ctxt, t, net, net.Bob, carol, - lntest.OpenChannelParams{ - Amt: chanAmt, - }, - ) - - // Ensure that Alice has Carol in her routing table before proceeding. - nodeInfoReq := &lnrpc.NodeInfoRequest{ - PubKey: carol.PubKeyStr, - } - checkTableTimeout := time.After(time.Second * 10) - checkTableTicker := time.NewTicker(100 * time.Millisecond) - defer checkTableTicker.Stop() - -out: - // TODO(roasbeef): make into async hook for node announcements - for { - select { - case <-checkTableTicker.C: - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - _, err := net.Alice.GetNodeInfo(ctxt, nodeInfoReq) - if err != nil && strings.Contains(err.Error(), - "unable to find") { - - continue - } - - break out - case <-checkTableTimeout: - t.Fatalf("carol's node announcement didn't propagate within " + - "the timeout period") - } - } - - // With the channels, open we can now start to test our multi-hop error - // scenarios. First, we'll generate an invoice from carol that we'll - // use to test some error cases. - const payAmt = 10000 - invoiceReq := &lnrpc.Invoice{ - Memo: "kek99", - Value: payAmt, - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - carolInvoice, err := carol.AddInvoice(ctxt, invoiceReq) - if err != nil { - t.Fatalf("unable to generate carol invoice: %v", err) - } - - carolPayReq, err := carol.DecodePayReq(ctxb, - &lnrpc.PayReqString{ - PayReq: carolInvoice.PaymentRequest, - }) - if err != nil { - t.Fatalf("unable to decode generated payment request: %v", err) - } - - // Before we send the payment, ensure that the announcement of the new - // channel has been processed by Alice. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - if err := net.Alice.WaitForNetworkChannelOpen(ctxt, chanPointBob); err != nil { - t.Fatalf("channel not seen by alice before timeout: %v", err) - } - - // For the first scenario, we'll test the cancellation of an HTLC with - // an unknown payment hash. - // TODO(roasbeef): return failure response rather than failing entire - // stream on payment error. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - sendReq := &lnrpc.SendRequest{ - PaymentHashString: hex.EncodeToString(makeFakePayHash(t)), - DestString: hex.EncodeToString(carol.PubKey[:]), - Amt: payAmt, - FinalCltvDelta: int32(carolPayReq.CltvExpiry), - } - resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) - if err != nil { - t.Fatalf("unable to send payment: %v", err) - } - - // The payment should have resulted in an error since we sent it with the - // wrong payment hash. - if resp.PaymentError == "" { - t.Fatalf("payment should have been rejected due to invalid " + - "payment hash") - } - - assertLastHTLCError( - t, net.Alice, - lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, - ) - - // The balances of all parties should be the same as initially since - // the HTLC was canceled. - assertBaseBalance() - - // Next, we'll test the case of a recognized payHash but, an incorrect - // value on the extended HTLC. - htlcAmt := lnwire.NewMSatFromSatoshis(1000) - sendReq = &lnrpc.SendRequest{ - PaymentHashString: hex.EncodeToString(carolInvoice.RHash), - DestString: hex.EncodeToString(carol.PubKey[:]), - Amt: int64(htlcAmt.ToSatoshis()), // 10k satoshis are expected. - FinalCltvDelta: int32(carolPayReq.CltvExpiry), - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) - if err != nil { - t.Fatalf("unable to send payment: %v", err) - } - - // The payment should fail with an error since we sent 1k satoshis isn't of - // 10k as was requested. - if resp.PaymentError == "" { - t.Fatalf("payment should have been rejected due to wrong " + - "HTLC amount") - } - - assertLastHTLCError( - t, net.Alice, - lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, - ) - - // The balances of all parties should be the same as initially since - // the HTLC was canceled. - assertBaseBalance() - - // Next we'll test an error that occurs mid-route due to an outgoing - // link having insufficient capacity. In order to do so, we'll first - // need to unbalance the link connecting Bob<->Carol. - ctx, cancel := context.WithCancel(ctxb) - defer cancel() - - bobPayStream, err := net.Bob.SendPayment(ctx) - if err != nil { - t.Fatalf("unable to create payment stream: %v", err) - } - - // To do so, we'll push most of the funds in the channel over to - // Alice's side, leaving on 10k satoshis of available balance for bob. - // There's a max payment amount, so we'll have to do this - // incrementally. - chanReserve := int64(chanAmt / 100) - amtToSend := int64(chanAmt) - chanReserve - 20000 - amtSent := int64(0) - for amtSent != amtToSend { - // We'll send in chunks of the max payment amount. If we're - // about to send too much, then we'll only send the amount - // remaining. - toSend := int64(lnd.MaxPaymentMSat.ToSatoshis()) - if toSend+amtSent > amtToSend { - toSend = amtToSend - amtSent - } - - invoiceReq = &lnrpc.Invoice{ - Value: toSend, - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - carolInvoice2, err := carol.AddInvoice(ctxt, invoiceReq) - if err != nil { - t.Fatalf("unable to generate carol invoice: %v", err) - } - if err := bobPayStream.Send(&lnrpc.SendRequest{ - PaymentRequest: carolInvoice2.PaymentRequest, - }); err != nil { - t.Fatalf("unable to send payment: %v", err) - } - - if resp, err := bobPayStream.Recv(); err != nil { - t.Fatalf("payment stream has been closed: %v", err) - } else if resp.PaymentError != "" { - t.Fatalf("bob's payment failed: %v", resp.PaymentError) - } - - amtSent += toSend - } - - // At this point, Alice has 50mil satoshis on her side of the channel, - // but Bob only has 10k available on his side of the channel. So a - // payment from Alice to Carol worth 100k satoshis should fail. - invoiceReq = &lnrpc.Invoice{ - Value: 100000, - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - carolInvoice3, err := carol.AddInvoice(ctxt, invoiceReq) - if err != nil { - t.Fatalf("unable to generate carol invoice: %v", err) - } - - sendReq = &lnrpc.SendRequest{ - PaymentRequest: carolInvoice3.PaymentRequest, - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) - if err != nil { - t.Fatalf("unable to send payment: %v", err) - } - if resp.PaymentError == "" { - t.Fatalf("payment should fail due to insufficient "+ - "capacity: %v", err) - } - - assertLastHTLCError( - t, net.Alice, lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE, - ) - - // Generate new invoice to not pay same invoice twice. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - carolInvoice, err = carol.AddInvoice(ctxt, invoiceReq) - if err != nil { - t.Fatalf("unable to generate carol invoice: %v", err) - } - - // For our final test, we'll ensure that if a target link isn't - // available for what ever reason then the payment fails accordingly. - // - // We'll attempt to complete the original invoice we created with Carol - // above, but before we do so, Carol will go offline, resulting in a - // failed payment. - shutdownAndAssert(net, t, carol) - - // Reset mission control to forget the temporary channel failure above. - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - _, err = net.Alice.RouterClient.ResetMissionControl( - ctxt, &routerrpc.ResetMissionControlRequest{}, - ) - if err != nil { - t.Fatalf("unable to reset mission control: %v", err) - } - - sendReq = &lnrpc.SendRequest{ - PaymentRequest: carolInvoice.PaymentRequest, - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) - if err != nil { - t.Fatalf("unable to send payment: %v", err) - } - - if resp.PaymentError == "" { - t.Fatalf("payment should have failed") - } - - assertLastHTLCError(t, net.Alice, lnrpc.Failure_UNKNOWN_NEXT_PEER) - - // Finally, immediately close the channel. This function will also - // block until the channel is closed and will additionally assert the - // relevant channel closing post conditions. - ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false) - - // Force close Bob's final channel. - ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) - closeChannelAndAssert(ctxt, t, net, net.Bob, chanPointBob, true) - - // Cleanup by mining the force close and sweep transaction. - cleanupForceClose(t, net, net.Bob, chanPointBob) -} - // testRejectHTLC tests that a node can be created with the flag --rejecthtlc. // This means that the node will reject all forwarded HTLCs but can still // accept direct HTLCs as well as send HTLCs. From 3289b31b09e0634b99f28874db5cbf9479a71279 Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 4 May 2020 10:12:55 +0200 Subject: [PATCH 534/562] lntest/test: add htlc events test to multi-hop error propagation --- .../itest/lnd_multi-hop-error-propagation.go | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/lntest/itest/lnd_multi-hop-error-propagation.go b/lntest/itest/lnd_multi-hop-error-propagation.go index 9e567b1e9f..d1689a99cb 100644 --- a/lntest/itest/lnd_multi-hop-error-propagation.go +++ b/lntest/itest/lnd_multi-hop-error-propagation.go @@ -146,6 +146,32 @@ out: t.Fatalf("channel not seen by alice before timeout: %v", err) } + // Before we start sending payments, subscribe to htlc events for each + // node. + ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + + aliceEvents, err := net.Alice.RouterClient.SubscribeHtlcEvents( + ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, + ) + if err != nil { + t.Fatalf("could not subscribe events: %v", err) + } + + bobEvents, err := net.Bob.RouterClient.SubscribeHtlcEvents( + ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, + ) + if err != nil { + t.Fatalf("could not subscribe events: %v", err) + } + + carolEvents, err := carol.RouterClient.SubscribeHtlcEvents( + ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, + ) + if err != nil { + t.Fatalf("could not subscribe events: %v", err) + } + // For the first scenario, we'll test the cancellation of an HTLC with // an unknown payment hash. // TODO(roasbeef): return failure response rather than failing entire @@ -174,6 +200,18 @@ out: lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, ) + // We expect alice and bob to each have one forward and one forward + // fail event at this stage. + assertHtlcEvents(t, 1, 1, 0, routerrpc.HtlcEvent_SEND, aliceEvents) + assertHtlcEvents(t, 1, 1, 0, routerrpc.HtlcEvent_FORWARD, bobEvents) + + // Carol should have a link failure because the htlc failed on her + // incoming link. + assertLinkFailure( + t, routerrpc.HtlcEvent_RECEIVE, + routerrpc.FailureDetail_UNKNOWN_INVOICE, carolEvents, + ) + // The balances of all parties should be the same as initially since // the HTLC was canceled. assertBaseBalance() @@ -205,6 +243,18 @@ out: lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, ) + // We expect alice and bob to each have one forward and one forward + // fail event at this stage. + assertHtlcEvents(t, 1, 1, 0, routerrpc.HtlcEvent_SEND, aliceEvents) + assertHtlcEvents(t, 1, 1, 0, routerrpc.HtlcEvent_FORWARD, bobEvents) + + // Carol should have a link failure because the htlc failed on her + // incoming link. + assertLinkFailure( + t, routerrpc.HtlcEvent_RECEIVE, + routerrpc.FailureDetail_INVOICE_UNDERPAID, carolEvents, + ) + // The balances of all parties should be the same as initially since // the HTLC was canceled. assertBaseBalance() @@ -256,6 +306,16 @@ out: t.Fatalf("bob's payment failed: %v", resp.PaymentError) } + // For each send bob makes, we need to check that bob has a + // forward and settle event for his send, and carol has a + // settle event for her receive. + assertHtlcEvents( + t, 1, 0, 1, routerrpc.HtlcEvent_SEND, bobEvents, + ) + assertHtlcEvents( + t, 0, 0, 1, routerrpc.HtlcEvent_RECEIVE, carolEvents, + ) + amtSent += toSend } @@ -288,6 +348,16 @@ out: t, net.Alice, lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE, ) + // Alice should have a forwarding event and a forwarding failure. + assertHtlcEvents(t, 1, 1, 0, routerrpc.HtlcEvent_SEND, aliceEvents) + + // Bob should have a link failure because the htlc failed on his + // outgoing link. + assertLinkFailure( + t, routerrpc.HtlcEvent_FORWARD, + routerrpc.FailureDetail_INSUFFICIENT_BALANCE, bobEvents, + ) + // Generate new invoice to not pay same invoice twice. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) carolInvoice, err = carol.AddInvoice(ctxt, invoiceReq) @@ -327,6 +397,16 @@ out: assertLastHTLCError(t, net.Alice, lnrpc.Failure_UNKNOWN_NEXT_PEER) + // Alice should have a forwarding event and subsequent fail. + assertHtlcEvents(t, 1, 1, 0, routerrpc.HtlcEvent_SEND, aliceEvents) + + // Bob should have a link failure because he could not find the next + // peer. + assertLinkFailure( + t, routerrpc.HtlcEvent_FORWARD, + routerrpc.FailureDetail_NO_DETAIL, bobEvents, + ) + // Finally, immediately close the channel. This function will also // block until the channel is closed and will additionally assert the // relevant channel closing post conditions. @@ -340,3 +420,23 @@ out: // Cleanup by mining the force close and sweep transaction. cleanupForceClose(t, net, net.Bob, chanPointBob) } + +// assertLinkFailure checks that the stream provided has a single link failure +// the the failure detail provided. +func assertLinkFailure(t *harnessTest, + eventType routerrpc.HtlcEvent_EventType, + failureDetail routerrpc.FailureDetail, + client routerrpc.Router_SubscribeHtlcEventsClient) { + + event := assertEventAndType(t, eventType, client) + + linkFail, ok := event.Event.(*routerrpc.HtlcEvent_LinkFailEvent) + if !ok { + t.Fatalf("expected forwarding failure, got: %T", linkFail) + } + + if linkFail.LinkFailEvent.FailureDetail != failureDetail { + t.Fatalf("expected: %v, got: %v", failureDetail, + linkFail.LinkFailEvent.FailureDetail) + } +} From 3c0b438f16b47fce87e8934c0d51b3babbc9de4e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 6 May 2020 16:22:47 -0700 Subject: [PATCH 535/562] cmd/lncli: remove usage of Millisecond() for Go 1.12 The new table format for the pay command started to use the `Millisecond()` method on `time.Duration`. However, this method was only added in Go 1.13, so this breaks the build for Go 1.12. We replace this by manual division. `time.Duration` "natively" is in nanoseconds, so we covert to milli seconds by dividing my `time.Millisecond`, which is 1,000,000. --- cmd/lncli/cmd_pay.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index a90330b558..0f99a1fab3 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -605,8 +605,8 @@ func formatPayment(payment *lnrpc.Payment, aliases *aliasCache) string { return "-" } resolveTime := time.Unix(0, timeNs) - resolveTimeMs := resolveTime.Sub(createTime). - Milliseconds() + resolveTimeDiff := resolveTime.Sub(createTime) + resolveTimeMs := resolveTimeDiff / time.Millisecond return fmt.Sprintf( "%.3f", float64(resolveTimeMs)/1000.0, ) From 4b7e8669ac217a6d50b33ba077329035321eeb27 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 11 May 2020 15:38:45 -0700 Subject: [PATCH 536/562] channeldb/db: adds optional dry-run abort for migrations --- channeldb/db.go | 21 +++++++++++++++++- channeldb/db_test.go | 10 +++++++++ channeldb/meta_test.go | 48 +++++++++++++++++++++++++++++++++++++++--- channeldb/options.go | 12 +++++++++++ 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/channeldb/db.go b/channeldb/db.go index c2842b1815..43ad6cde41 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -25,6 +25,12 @@ const ( dbFilePermission = 0600 ) +var ( + // ErrDryRunMigrationOK signals that a migration executed successful, + // but we intentionally did not commit the result. + ErrDryRunMigrationOK = errors.New("Dry run migration successful") +) + // migration is a function which takes a prior outdated version of the database // instances and mutates the key/bucket structure to arrive at a more // up-to-date version of the database. @@ -145,6 +151,7 @@ type DB struct { dbPath string graph *ChannelGraph clock clock.Clock + dryRun bool } // Open opens an existing channeldb. Any necessary schemas migrations due to @@ -174,6 +181,7 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) { Backend: bdb, dbPath: dbPath, clock: opts.clock, + dryRun: opts.dryRun, } chanDB.graph = newChannelGraph( chanDB, opts.RejectCacheSize, opts.ChannelCacheSize, @@ -1227,7 +1235,18 @@ func (d *DB) syncVersions(versions []version) error { } meta.DbVersionNumber = latestVersion - return putMeta(meta, tx) + err := putMeta(meta, tx) + if err != nil { + return err + } + + // In dry-run mode, return an error to prevent the transaction + // from committing. + if d.dryRun { + return ErrDryRunMigrationOK + } + + return nil }) } diff --git a/channeldb/db_test.go b/channeldb/db_test.go index e678d2a504..242b70ca4d 100644 --- a/channeldb/db_test.go +++ b/channeldb/db_test.go @@ -45,6 +45,16 @@ func TestOpenWithCreate(t *testing.T) { if !fileExists(dbPath) { t.Fatalf("channeldb failed to create data directory") } + + // Now, reopen the same db in dry run migration mode. Since we have not + // applied any migrations, this should ignore the flag and not fail. + cdb, err = Open(dbPath, OptionDryRunMigration(true)) + if err != nil { + t.Fatalf("unable to create channeldb: %v", err) + } + if err := cdb.Close(); err != nil { + t.Fatalf("unable to close channeldb: %v", err) + } } // TestWipe tests that the database wipe operation completes successfully diff --git a/channeldb/meta_test.go b/channeldb/meta_test.go index 1933c0e161..a18932f477 100644 --- a/channeldb/meta_test.go +++ b/channeldb/meta_test.go @@ -12,13 +12,14 @@ import ( // applyMigration is a helper test function that encapsulates the general steps // which are needed to properly check the result of applying migration function. func applyMigration(t *testing.T, beforeMigration, afterMigration func(d *DB), - migrationFunc migration, shouldFail bool) { + migrationFunc migration, shouldFail bool, dryRun bool) { cdb, cleanUp, err := makeTestDB() defer cleanUp() if err != nil { t.Fatal(err) } + cdb.dryRun = dryRun // Create a test node that will be our source node. testNode, err := createTestVertex(cdb) @@ -54,6 +55,9 @@ func applyMigration(t *testing.T, beforeMigration, afterMigration func(d *DB), defer func() { if r := recover(); r != nil { + if dryRun && r != ErrDryRunMigrationOK { + t.Fatalf("expected dry run migration OK") + } err = errors.New(r) } @@ -256,7 +260,8 @@ func TestMigrationWithPanic(t *testing.T) { beforeMigrationFunc, afterMigrationFunc, migrationWithPanic, - true) + true, + false) } // TestMigrationWithFatal asserts that migrations which fail do not modify the @@ -330,7 +335,8 @@ func TestMigrationWithFatal(t *testing.T) { beforeMigrationFunc, afterMigrationFunc, migrationWithFatal, - true) + true, + false) } // TestMigrationWithoutErrors asserts that a successful migration has its @@ -404,6 +410,7 @@ func TestMigrationWithoutErrors(t *testing.T) { beforeMigrationFunc, afterMigrationFunc, migrationWithoutErrors, + false, false) } @@ -446,3 +453,38 @@ func TestMigrationReversion(t *testing.T) { "want: %v, got: %v", ErrDBReversion, err) } } + +// TestMigrationDryRun ensures that opening the database in dry run migration +// mode will fail and not commit the migration. +func TestMigrationDryRun(t *testing.T) { + t.Parallel() + + // Nothing to do, will inspect version number. + beforeMigrationFunc := func(d *DB) {} + + // Check that version of database version is not modified. + afterMigrationFunc := func(d *DB) { + err := kvdb.View(d, func(tx kvdb.ReadTx) error { + meta, err := d.FetchMeta(nil) + if err != nil { + t.Fatal(err) + } + + if meta.DbVersionNumber != 0 { + t.Fatal("dry run migration was not aborted") + } + + return nil + }) + if err != nil { + t.Fatalf("unable to apply after func: %v", err) + } + } + + applyMigration(t, + beforeMigrationFunc, + afterMigrationFunc, + func(kvdb.RwTx) error { return nil }, + true, + true) +} diff --git a/channeldb/options.go b/channeldb/options.go index 90185f2cd0..b84dd199d5 100644 --- a/channeldb/options.go +++ b/channeldb/options.go @@ -31,6 +31,10 @@ type Options struct { // clock is the time source used by the database. clock clock.Clock + + // dryRun will fail to commit a successful migration when opening the + // database if set to true. + dryRun bool } // DefaultOptions returns an Options populated with default values. @@ -73,3 +77,11 @@ func OptionClock(clock clock.Clock) OptionModifier { o.clock = clock } } + +// OptionDryRunMigration controls whether or not to intentially fail to commit a +// successful migration that occurs when opening the database. +func OptionDryRunMigration(dryRun bool) OptionModifier { + return func(o *Options) { + o.dryRun = dryRun + } +} From 412d7f5c38688eb5252524d0d39ed3cf2deeb0b5 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 11 May 2020 15:38:56 -0700 Subject: [PATCH 537/562] config: adds cli configurable --migration-dry-run --- config.go | 2 ++ lnd.go | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index 6816b0e81d..df3cf6ea98 100644 --- a/config.go +++ b/config.go @@ -335,6 +335,8 @@ type config struct { MaxChannelFeeAllocation float64 `long:"max-channel-fee-allocation" description:"The maximum percentage of total funds that can be allocated to a channel's commitment fee. This only applies for the initiator of the channel. Valid values are within [0.1, 1]."` + DryRunMigration bool `long:"dry-run-migration" description:"If true, lnd will abort committing a migration if it would otherwise have been successful. This leaves the database unmodified, and still compatible with the previously active version of lnd."` + net tor.Net EnableUpfrontShutdown bool `long:"enable-upfront-shutdown" description:"If true, option upfront shutdown script will be enabled. If peers that we open channels with support this feature, we will automatically set the script to which cooperative closes should be paid out to on channel open. This offers the partial protection of a channel peer disconnecting from us if cooperative close is attempted with a different script."` diff --git a/lnd.go b/lnd.go index faffac1f1a..f8dd44e014 100644 --- a/lnd.go +++ b/lnd.go @@ -235,10 +235,15 @@ func Main(lisCfg ListenerCfg) error { channeldb.OptionSetRejectCacheSize(cfg.Caches.RejectCacheSize), channeldb.OptionSetChannelCacheSize(cfg.Caches.ChannelCacheSize), channeldb.OptionSetSyncFreelist(cfg.SyncFreelist), + channeldb.OptionDryRunMigration(cfg.DryRunMigration), ) - if err != nil { - err := fmt.Errorf("Unable to open channeldb: %v", err) - ltndLog.Error(err) + switch { + case err == channeldb.ErrDryRunMigrationOK: + ltndLog.Info("%v, exiting", err) + return nil + + case err != nil: + ltndLog.Errorf("Unable to open channeldb: %v", err) return err } defer chanDB.Close() From 389b715f15921c3705035d8bf1ab04738b5d6013 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 8 May 2020 13:53:22 +0200 Subject: [PATCH 538/562] routing/test: add channel id constants --- routing/pathfind_test.go | 49 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index deaccb2898..f524c348be 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -2254,26 +2254,35 @@ func TestNewRouteFromEmptyHops(t *testing.T) { func TestRestrictOutgoingChannel(t *testing.T) { t.Parallel() + // Define channel id constants + const ( + chanSourceA = 1 + chanATarget = 4 + chanSourceB1 = 2 + chanSourceB2 = 3 + chanBTarget = 5 + ) + // Set up a test graph with three possible paths from roasbeef to - // target. The path through channel 2 is the highest cost path. + // target. The path through chanSourceB1 is the highest cost path. testChannels := []*testChannel{ symmetricTestChannel("roasbeef", "a", 100000, &testChannelPolicy{ Expiry: 144, - }, 1), + }, chanSourceA), symmetricTestChannel("a", "target", 100000, &testChannelPolicy{ Expiry: 144, FeeRate: 400, - }, 4), + }, chanATarget), symmetricTestChannel("roasbeef", "b", 100000, &testChannelPolicy{ Expiry: 144, - }, 2), + }, chanSourceB1), symmetricTestChannel("roasbeef", "b", 100000, &testChannelPolicy{ Expiry: 144, - }, 3), + }, chanSourceB2), symmetricTestChannel("b", "target", 100000, &testChannelPolicy{ Expiry: 144, FeeRate: 800, - }, 5), + }, chanBTarget), } ctx := newPathFindingTestContext(t, testChannels, "roasbeef") @@ -2286,32 +2295,22 @@ func TestRestrictOutgoingChannel(t *testing.T) { paymentAmt := lnwire.NewMSatFromSatoshis(100) target := ctx.keyFromAlias("target") - outgoingChannelID := uint64(2) + outgoingChannelID := uint64(chanSourceB1) - // Find the best path given the restriction to only use channel 2 as the - // outgoing channel. + // Find the best path given the restriction to only use chanSourceB1 as + // the outgoing channel. ctx.restrictParams.OutgoingChannelID = &outgoingChannelID path, err := ctx.findPath(target, paymentAmt) if err != nil { t.Fatalf("unable to find path: %v", err) } - route, err := newRoute( - ctx.source, path, startingHeight, - finalHopParams{ - amt: paymentAmt, - cltvDelta: finalHopCLTV, - records: nil, - }, - ) - if err != nil { - t.Fatalf("unable to create path: %v", err) - } - // Assert that the route starts with channel 2, in line with the - // specified restriction. - if route.Hops[0].ChannelID != 2 { - t.Fatalf("expected route to pass through channel 2, "+ - "but channel %v was selected instead", route.Hops[0].ChannelID) + // Assert that the route starts with channel chanSourceB1, in line with + // the specified restriction. + if path[0].ChannelID != chanSourceB1 { + t.Fatalf("expected route to pass through channel %v, "+ + "but channel %v was selected instead", chanSourceB1, + path[0].ChannelID) } } From 5e83ed9d891d8d482c77268ee514299e09c16b04 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 7 May 2020 11:48:39 +0200 Subject: [PATCH 539/562] routing+routerrpc: add multiple outgoing channel restriction --- cmd/lncli/cmd_pay.go | 5 +- lnrpc/routerrpc/router.pb.go | 304 +++++++++++++------------ lnrpc/routerrpc/router.proto | 13 +- lnrpc/routerrpc/router_backend.go | 16 +- lnrpc/routerrpc/router_backend_test.go | 2 +- routing/pathfind.go | 27 ++- routing/pathfind_test.go | 36 ++- routing/payment_session.go | 16 +- routing/router.go | 15 +- routing/unified_policies.go | 12 +- rpcserver.go | 59 ++--- 11 files changed, 289 insertions(+), 216 deletions(-) diff --git a/cmd/lncli/cmd_pay.go b/cmd/lncli/cmd_pay.go index 0f99a1fab3..fbd4a51088 100644 --- a/cmd/lncli/cmd_pay.go +++ b/cmd/lncli/cmd_pay.go @@ -321,7 +321,10 @@ func sendPaymentRequest(ctx *cli.Context, client := lnrpc.NewLightningClient(conn) routerClient := routerrpc.NewRouterClient(conn) - req.OutgoingChanId = ctx.Uint64("outgoing_chan_id") + outChan := ctx.Uint64("outgoing_chan_id") + if outChan != 0 { + req.OutgoingChanIds = []uint64{outChan} + } if ctx.IsSet(lastHopFlag.Name) { lastHop, err := route.NewVertexFromStr( ctx.String(lastHopFlag.Name), diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index ae57eacdf9..14787b5a32 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -247,10 +247,15 @@ type SendPaymentRequest struct { // //The fields fee_limit_sat and fee_limit_msat are mutually exclusive. FeeLimitMsat int64 `protobuf:"varint,13,opt,name=fee_limit_msat,json=feeLimitMsat,proto3" json:"fee_limit_msat,omitempty"` - //* - //The channel id of the channel that must be taken to the first hop. If zero, + // + //Deprecated, use outgoing_chan_ids. The channel id of the channel that must + //be taken to the first hop. If zero, any channel may be used (unless + //outgoing_chan_ids are set). + OutgoingChanId uint64 `protobuf:"varint,8,opt,name=outgoing_chan_id,json=outgoingChanId,proto3" json:"outgoing_chan_id,omitempty"` // Deprecated: Do not use. + // + //The channel ids of the channels are allowed for the first hop. If empty, //any channel may be used. - OutgoingChanId uint64 `protobuf:"varint,8,opt,name=outgoing_chan_id,json=outgoingChanId,proto3" json:"outgoing_chan_id,omitempty"` + OutgoingChanIds []uint64 `protobuf:"varint,19,rep,packed,name=outgoing_chan_ids,json=outgoingChanIds,proto3" json:"outgoing_chan_ids,omitempty"` //* //The pubkey of the last hop of the route. If empty, any hop may be used. LastHopPubkey []byte `protobuf:"bytes,14,opt,name=last_hop_pubkey,json=lastHopPubkey,proto3" json:"last_hop_pubkey,omitempty"` @@ -379,6 +384,7 @@ func (m *SendPaymentRequest) GetFeeLimitMsat() int64 { return 0 } +// Deprecated: Do not use. func (m *SendPaymentRequest) GetOutgoingChanId() uint64 { if m != nil { return m.OutgoingChanId @@ -386,6 +392,13 @@ func (m *SendPaymentRequest) GetOutgoingChanId() uint64 { return 0 } +func (m *SendPaymentRequest) GetOutgoingChanIds() []uint64 { + if m != nil { + return m.OutgoingChanIds + } + return nil +} + func (m *SendPaymentRequest) GetLastHopPubkey() []byte { if m != nil { return m.LastHopPubkey @@ -1746,148 +1759,149 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 2248 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0xcd, 0x76, 0xdb, 0xb8, - 0xf5, 0x1f, 0x4a, 0x94, 0x2d, 0x5d, 0x7d, 0x98, 0x86, 0x33, 0x8e, 0xfe, 0x72, 0x32, 0xa3, 0xe1, - 0x7f, 0x26, 0xd1, 0x49, 0x33, 0x76, 0xc6, 0xed, 0x69, 0xe7, 0xb4, 0x9d, 0x69, 0x65, 0x89, 0x8e, - 0x99, 0xc8, 0xa4, 0x06, 0x92, 0x9d, 0xa4, 0x59, 0xe0, 0xd0, 0x12, 0x64, 0xb1, 0xe6, 0x87, 0x4a, - 0x42, 0xc9, 0x78, 0xd9, 0x5d, 0x4f, 0xb7, 0x7d, 0x88, 0xee, 0xfa, 0x04, 0xdd, 0xf6, 0x39, 0xba, - 0xed, 0x13, 0x74, 0xdd, 0x03, 0x10, 0x94, 0x28, 0x5b, 0x4e, 0xda, 0x8d, 0x4d, 0xfc, 0xee, 0xc5, - 0xc5, 0xbd, 0xb8, 0xbf, 0x8b, 0x0b, 0x08, 0x76, 0xa3, 0x70, 0xce, 0x68, 0x14, 0xcd, 0x46, 0x07, - 0xc9, 0xd7, 0xfe, 0x2c, 0x0a, 0x59, 0x88, 0x4a, 0x0b, 0xbc, 0x51, 0x8a, 0x66, 0xa3, 0x04, 0xd5, - 0xff, 0xb1, 0x01, 0x68, 0x40, 0x83, 0x71, 0xdf, 0xb9, 0xf6, 0x69, 0xc0, 0x30, 0xfd, 0xc3, 0x9c, - 0xc6, 0x0c, 0x21, 0x50, 0xc7, 0x34, 0x66, 0x75, 0xa5, 0xa9, 0xb4, 0x2a, 0x58, 0x7c, 0x23, 0x0d, - 0xf2, 0x8e, 0xcf, 0xea, 0xb9, 0xa6, 0xd2, 0xca, 0x63, 0xfe, 0x89, 0xfe, 0x0f, 0x8a, 0x8e, 0xcf, - 0x88, 0x1f, 0x3b, 0xac, 0x5e, 0x11, 0xf0, 0xa6, 0xe3, 0xb3, 0xd3, 0xd8, 0x61, 0xe8, 0x0b, 0xa8, - 0xcc, 0x12, 0x93, 0x64, 0xea, 0xc4, 0xd3, 0x7a, 0x5e, 0x18, 0x2a, 0x4b, 0xec, 0xc4, 0x89, 0xa7, - 0xa8, 0x05, 0xda, 0xc4, 0x0d, 0x1c, 0x8f, 0x8c, 0x3c, 0xf6, 0x8e, 0x8c, 0xa9, 0xc7, 0x9c, 0xba, - 0xda, 0x54, 0x5a, 0x05, 0x5c, 0x13, 0x78, 0xc7, 0x63, 0xef, 0xba, 0x1c, 0x45, 0x8f, 0x61, 0x2b, - 0x35, 0x16, 0x25, 0x0e, 0xd6, 0x0b, 0x4d, 0xa5, 0x55, 0xc2, 0xb5, 0xd9, 0xaa, 0xdb, 0x8f, 0x61, - 0x8b, 0xb9, 0x3e, 0x0d, 0xe7, 0x8c, 0xc4, 0x74, 0x14, 0x06, 0xe3, 0xb8, 0xbe, 0x91, 0x58, 0x94, - 0xf0, 0x20, 0x41, 0x91, 0x0e, 0xd5, 0x09, 0xa5, 0xc4, 0x73, 0x7d, 0x97, 0x11, 0xee, 0xfe, 0xa6, - 0x70, 0xbf, 0x3c, 0xa1, 0xb4, 0xc7, 0xb1, 0x81, 0xc3, 0xd0, 0x97, 0x50, 0x5b, 0xea, 0x88, 0x18, - 0xab, 0x42, 0xa9, 0x92, 0x2a, 0x89, 0x40, 0x9f, 0x82, 0x16, 0xce, 0xd9, 0x65, 0xe8, 0x06, 0x97, - 0x64, 0x34, 0x75, 0x02, 0xe2, 0x8e, 0xeb, 0xc5, 0xa6, 0xd2, 0x52, 0x8f, 0x72, 0xcf, 0x14, 0x5c, - 0x4b, 0x65, 0x9d, 0xa9, 0x13, 0x98, 0x63, 0xf4, 0x08, 0xb6, 0x3c, 0x27, 0x66, 0x64, 0x1a, 0xce, - 0xc8, 0x6c, 0x7e, 0x71, 0x45, 0xaf, 0xeb, 0x35, 0xb1, 0x33, 0x55, 0x0e, 0x9f, 0x84, 0xb3, 0xbe, - 0x00, 0xd1, 0x43, 0x00, 0xb1, 0x2b, 0x62, 0xf1, 0x7a, 0x49, 0xc4, 0x50, 0xe2, 0x88, 0x58, 0x18, - 0x7d, 0x03, 0x65, 0x91, 0x4d, 0x32, 0x75, 0x03, 0x16, 0xd7, 0xa1, 0x99, 0x6f, 0x95, 0x0f, 0xb5, - 0x7d, 0x2f, 0xe0, 0x89, 0xc5, 0x5c, 0x72, 0xe2, 0x06, 0x0c, 0x43, 0x94, 0x7e, 0xc6, 0x68, 0x0c, - 0x3b, 0x3c, 0x8b, 0x64, 0x34, 0x8f, 0x59, 0xe8, 0x93, 0x88, 0x8e, 0xc2, 0x68, 0x1c, 0xd7, 0xcb, - 0x62, 0xea, 0xcf, 0xf6, 0x17, 0xe4, 0xd8, 0xbf, 0xcd, 0x86, 0xfd, 0x2e, 0x8d, 0x59, 0x47, 0xcc, - 0xc3, 0xc9, 0x34, 0x23, 0x60, 0xd1, 0x35, 0xde, 0x1e, 0xdf, 0xc4, 0xd1, 0x53, 0x40, 0x8e, 0xe7, - 0x85, 0xef, 0x49, 0x4c, 0xbd, 0x09, 0x91, 0xd9, 0xa9, 0x6f, 0x35, 0x95, 0x56, 0x11, 0x6b, 0x42, - 0x32, 0xa0, 0xde, 0x44, 0x9a, 0x47, 0x3f, 0x87, 0xaa, 0xf0, 0x69, 0x42, 0x1d, 0x36, 0x8f, 0x68, - 0x5c, 0xd7, 0x9a, 0xf9, 0x56, 0xed, 0x70, 0x5b, 0x06, 0x72, 0x9c, 0xc0, 0x47, 0x2e, 0xc3, 0x15, - 0xae, 0x27, 0xc7, 0x31, 0xda, 0x83, 0x92, 0xef, 0xfc, 0x48, 0x66, 0x4e, 0xc4, 0xe2, 0xfa, 0x76, - 0x53, 0x69, 0x55, 0x71, 0xd1, 0x77, 0x7e, 0xec, 0xf3, 0x31, 0xda, 0x87, 0x9d, 0x20, 0x24, 0x6e, - 0x30, 0xf1, 0xdc, 0xcb, 0x29, 0x23, 0xf3, 0xd9, 0xd8, 0x61, 0x34, 0xae, 0x23, 0xe1, 0xc3, 0x76, - 0x10, 0x9a, 0x52, 0x72, 0x96, 0x08, 0x1a, 0x5d, 0xd8, 0x5d, 0x1f, 0x1f, 0x27, 0x3c, 0x4f, 0x10, - 0xaf, 0x01, 0x15, 0xf3, 0x4f, 0x74, 0x0f, 0x0a, 0xef, 0x1c, 0x6f, 0x4e, 0x45, 0x11, 0x54, 0x70, - 0x32, 0xf8, 0x65, 0xee, 0x5b, 0x45, 0x9f, 0xc2, 0xce, 0x30, 0x72, 0x46, 0x57, 0x37, 0xea, 0xe8, - 0x66, 0x19, 0x28, 0xb7, 0xcb, 0xe0, 0x0e, 0x7f, 0x73, 0x77, 0xf8, 0xab, 0x7f, 0x0f, 0x5b, 0x22, - 0xc3, 0xc7, 0x94, 0x7e, 0xa8, 0x5a, 0xef, 0x03, 0xaf, 0x45, 0xc1, 0xed, 0xa4, 0x62, 0x37, 0x1c, - 0x9f, 0xd3, 0x5a, 0x1f, 0x83, 0xb6, 0x9c, 0x1f, 0xcf, 0xc2, 0x20, 0xa6, 0xbc, 0x14, 0x39, 0x01, - 0x38, 0x87, 0x39, 0xe5, 0x05, 0xd9, 0x15, 0x31, 0xab, 0x26, 0xf1, 0x63, 0x4a, 0x05, 0xdd, 0x1f, - 0x25, 0x15, 0x46, 0xbc, 0x70, 0x74, 0xc5, 0x6b, 0xd6, 0xb9, 0x96, 0xe6, 0xab, 0x1c, 0xee, 0x85, - 0xa3, 0xab, 0x2e, 0x07, 0xf5, 0xb7, 0xc9, 0xb1, 0x32, 0x0c, 0xc5, 0x5a, 0xff, 0xc3, 0x76, 0xe8, - 0x50, 0x10, 0x5c, 0x14, 0x66, 0xcb, 0x87, 0x95, 0x2c, 0xa9, 0x71, 0x22, 0xd2, 0xdf, 0xc2, 0xce, - 0x8a, 0x71, 0x19, 0x45, 0x03, 0x8a, 0xb3, 0x88, 0xba, 0xbe, 0x73, 0x49, 0xa5, 0xe5, 0xc5, 0x18, - 0xb5, 0x60, 0x73, 0xe2, 0xb8, 0xde, 0x3c, 0x4a, 0x0d, 0xd7, 0x52, 0x92, 0x25, 0x28, 0x4e, 0xc5, - 0xfa, 0x03, 0x68, 0x60, 0x1a, 0x53, 0x76, 0xea, 0xc6, 0xb1, 0x1b, 0x06, 0x9d, 0x30, 0x60, 0x51, - 0xe8, 0xc9, 0x08, 0xf4, 0x87, 0xb0, 0xb7, 0x56, 0x9a, 0xb8, 0xc0, 0x27, 0xff, 0x30, 0xa7, 0xd1, - 0xf5, 0xfa, 0xc9, 0x3f, 0xc0, 0xde, 0x5a, 0xa9, 0xf4, 0xff, 0x29, 0x14, 0x66, 0x8e, 0x1b, 0xf1, - 0xdc, 0xf3, 0xa2, 0xdc, 0xcd, 0x14, 0x65, 0xdf, 0x71, 0xa3, 0x13, 0x37, 0x66, 0x61, 0x74, 0x8d, - 0x13, 0xa5, 0x17, 0x6a, 0x51, 0xd1, 0x72, 0xfa, 0x9f, 0x15, 0x28, 0x67, 0x84, 0xbc, 0x34, 0x82, - 0x70, 0x4c, 0xc9, 0x24, 0x0a, 0xfd, 0x74, 0x13, 0x38, 0x70, 0x1c, 0x85, 0x3e, 0xe7, 0x84, 0x10, - 0xb2, 0x50, 0x12, 0x78, 0x83, 0x0f, 0x87, 0x21, 0xfa, 0x1a, 0x36, 0xa7, 0x89, 0x01, 0x71, 0x10, - 0x96, 0x0f, 0x77, 0x6e, 0xac, 0xdd, 0x75, 0x98, 0x83, 0x53, 0x9d, 0x17, 0x6a, 0x31, 0xaf, 0xa9, - 0x2f, 0xd4, 0xa2, 0xaa, 0x15, 0x5e, 0xa8, 0xc5, 0x82, 0xb6, 0xf1, 0x42, 0x2d, 0x6e, 0x68, 0x9b, - 0xfa, 0xbf, 0x14, 0x28, 0xa6, 0xda, 0xdc, 0x13, 0xbe, 0xa5, 0x84, 0xf3, 0x42, 0x92, 0xa9, 0xc8, - 0x81, 0xa1, 0xeb, 0x53, 0xd4, 0x84, 0x8a, 0x10, 0xae, 0x52, 0x14, 0x38, 0xd6, 0x16, 0x34, 0x15, - 0x27, 0x74, 0xaa, 0x21, 0xf8, 0xa8, 0xca, 0x13, 0x3a, 0x51, 0x49, 0x9b, 0x4c, 0x3c, 0x1f, 0x8d, - 0x68, 0x1c, 0x27, 0xab, 0x14, 0x12, 0x15, 0x89, 0x89, 0x85, 0x1e, 0xc1, 0x56, 0xaa, 0x92, 0xae, - 0xb5, 0x91, 0xf0, 0x55, 0xc2, 0x72, 0xb9, 0x16, 0x68, 0x59, 0x3d, 0x7f, 0xd9, 0x13, 0x6a, 0x4b, - 0x45, 0xbe, 0x68, 0x12, 0xbc, 0xfe, 0x7b, 0xb8, 0x2f, 0x52, 0xd9, 0x8f, 0xc2, 0x0b, 0xe7, 0xc2, - 0xf5, 0x5c, 0x76, 0x9d, 0x92, 0x9c, 0x07, 0x1e, 0x85, 0x3e, 0xe1, 0x7b, 0x9b, 0xa6, 0x80, 0x03, - 0x56, 0x38, 0xa6, 0x3c, 0x05, 0x2c, 0x4c, 0x44, 0x32, 0x05, 0x2c, 0x14, 0x82, 0x6c, 0x2f, 0xcd, - 0xaf, 0xf4, 0x52, 0xfd, 0x0a, 0xea, 0xb7, 0xd7, 0x92, 0x9c, 0x69, 0x42, 0x79, 0xb6, 0x84, 0xc5, - 0x72, 0x0a, 0xce, 0x42, 0xd9, 0xdc, 0xe6, 0x3e, 0x9e, 0x5b, 0xfd, 0xaf, 0x0a, 0x6c, 0x1f, 0xcd, - 0x5d, 0x6f, 0xbc, 0x52, 0xb8, 0x59, 0xef, 0x94, 0xd5, 0x4e, 0xbf, 0xae, 0x8d, 0xe7, 0xd6, 0xb6, - 0xf1, 0x75, 0xad, 0x32, 0x7f, 0x67, 0xab, 0xfc, 0x1c, 0xca, 0xcb, 0x2e, 0x19, 0xd7, 0xd5, 0x66, - 0xbe, 0x55, 0xc1, 0x30, 0x4d, 0x5b, 0x64, 0xac, 0x7f, 0x0b, 0x28, 0xeb, 0xa8, 0xdc, 0x90, 0xc5, - 0xf9, 0xa1, 0xdc, 0x7d, 0x7e, 0x3c, 0x80, 0xc6, 0x60, 0x7e, 0x11, 0x8f, 0x22, 0xf7, 0x82, 0x9e, - 0x30, 0x6f, 0x64, 0xbc, 0xa3, 0x01, 0x8b, 0xd3, 0x2a, 0xfd, 0xb7, 0x0a, 0xa5, 0x05, 0xca, 0x8f, - 0x67, 0x37, 0x18, 0x85, 0x7e, 0xea, 0x74, 0x40, 0x3d, 0xee, 0x77, 0xd2, 0x14, 0xb6, 0x53, 0x51, - 0x27, 0x91, 0x98, 0x63, 0xae, 0xbf, 0x12, 0xa4, 0xd4, 0xcf, 0x25, 0xfa, 0xd9, 0x18, 0x13, 0xfd, - 0x16, 0x68, 0x0b, 0xfb, 0x53, 0xe6, 0x8d, 0x16, 0x9b, 0x82, 0x6b, 0x29, 0xce, 0x9d, 0x49, 0x34, - 0x17, 0x96, 0x53, 0x4d, 0x35, 0xd1, 0x4c, 0x71, 0xa9, 0xf9, 0x05, 0x54, 0x78, 0x3d, 0xc4, 0xcc, - 0xf1, 0x67, 0x24, 0x88, 0x45, 0x5d, 0xa8, 0xb8, 0xbc, 0xc0, 0xac, 0x18, 0x7d, 0x07, 0x40, 0x79, - 0x7c, 0x84, 0x5d, 0xcf, 0xa8, 0x28, 0x89, 0xda, 0xe1, 0x67, 0x19, 0x62, 0x2c, 0x36, 0x60, 0x5f, - 0xfc, 0x1d, 0x5e, 0xcf, 0x28, 0x2e, 0xd1, 0xf4, 0x13, 0x7d, 0x0f, 0xd5, 0x49, 0x18, 0xbd, 0x77, - 0xa2, 0x31, 0x11, 0xa0, 0x3c, 0x36, 0xee, 0x67, 0x2c, 0x1c, 0x27, 0x72, 0x31, 0xfd, 0xe4, 0x13, - 0x5c, 0x99, 0x64, 0xc6, 0xe8, 0x25, 0xa0, 0x74, 0xbe, 0xa8, 0xf2, 0xc4, 0x48, 0x51, 0x18, 0xd9, - 0xbb, 0x6d, 0x84, 0x1f, 0xd2, 0xa9, 0x21, 0x6d, 0x72, 0x03, 0x43, 0xbf, 0x82, 0x4a, 0x4c, 0x19, - 0xf3, 0xa8, 0x34, 0x53, 0x12, 0x66, 0x76, 0x57, 0xee, 0x34, 0x5c, 0x9c, 0x5a, 0x28, 0xc7, 0xcb, - 0x21, 0x3a, 0x82, 0x2d, 0xcf, 0x0d, 0xae, 0xb2, 0x6e, 0x80, 0x98, 0x5f, 0xcf, 0xcc, 0xef, 0xb9, - 0xc1, 0x55, 0xd6, 0x87, 0xaa, 0x97, 0x05, 0xf4, 0x5f, 0x43, 0x69, 0xb1, 0x4b, 0xa8, 0x0c, 0x9b, - 0x67, 0xd6, 0x4b, 0xcb, 0x7e, 0x65, 0x69, 0x9f, 0xa0, 0x22, 0xa8, 0x03, 0xc3, 0xea, 0x6a, 0x0a, - 0x87, 0xb1, 0xd1, 0x31, 0xcc, 0x73, 0x43, 0xcb, 0xf1, 0xc1, 0xb1, 0x8d, 0x5f, 0xb5, 0x71, 0x57, - 0xcb, 0x1f, 0x6d, 0x42, 0x41, 0xac, 0xab, 0xff, 0x5d, 0x81, 0xa2, 0xc8, 0x60, 0x30, 0x09, 0xd1, - 0x4f, 0x60, 0x41, 0x2e, 0x71, 0xb8, 0xf1, 0x86, 0x2b, 0x58, 0x57, 0xc5, 0x0b, 0xc2, 0x0c, 0x25, - 0xce, 0x95, 0x17, 0xd4, 0x58, 0x28, 0xe7, 0x12, 0xe5, 0x54, 0xb0, 0x50, 0x7e, 0x92, 0xb1, 0xbc, - 0x72, 0xe4, 0xa8, 0x78, 0x2b, 0x15, 0xa4, 0x27, 0xec, 0x93, 0x8c, 0xe1, 0x95, 0x93, 0x58, 0xc5, - 0x5b, 0xa9, 0x40, 0xea, 0xea, 0xbf, 0x80, 0x4a, 0x36, 0xe7, 0xe8, 0x31, 0xa8, 0x6e, 0x30, 0x09, - 0x65, 0x21, 0xee, 0xdc, 0x20, 0x17, 0x0f, 0x12, 0x0b, 0x05, 0x1d, 0x81, 0x76, 0x33, 0xcf, 0x7a, - 0x15, 0xca, 0x99, 0xa4, 0xe9, 0xff, 0x54, 0xa0, 0xba, 0x92, 0x84, 0xff, 0xda, 0x3a, 0xfa, 0x0e, - 0x2a, 0xef, 0xdd, 0x88, 0x92, 0x6c, 0xfb, 0xaf, 0x1d, 0x36, 0x56, 0xdb, 0x7f, 0xfa, 0xbf, 0x13, - 0x8e, 0x29, 0x2e, 0x73, 0x7d, 0x09, 0xa0, 0xdf, 0x40, 0x4d, 0xce, 0x24, 0x63, 0xca, 0x1c, 0xd7, - 0x13, 0x5b, 0x55, 0x5b, 0xa1, 0x87, 0xd4, 0xed, 0x0a, 0x39, 0xae, 0x4e, 0xb2, 0x43, 0xf4, 0xd5, - 0xd2, 0x40, 0xcc, 0x22, 0x37, 0xb8, 0x14, 0xfb, 0x57, 0x5a, 0xa8, 0x0d, 0x04, 0xc8, 0x1b, 0x79, - 0x55, 0x5e, 0x1e, 0x07, 0xcc, 0x61, 0xf3, 0x18, 0x7d, 0x0d, 0x85, 0x98, 0x39, 0xf2, 0x24, 0xab, - 0xad, 0xd4, 0x56, 0x46, 0x91, 0xe2, 0x44, 0x6b, 0xe5, 0xf6, 0x93, 0xbb, 0x75, 0xfb, 0x29, 0xf0, - 0x13, 0x23, 0x39, 0x45, 0xcb, 0x87, 0x48, 0x06, 0x7f, 0x32, 0xec, 0x75, 0xda, 0x8c, 0x51, 0x7f, - 0xc6, 0x70, 0xa2, 0x90, 0x74, 0xb7, 0x27, 0x7f, 0x54, 0xa1, 0xba, 0x12, 0xd4, 0x2a, 0xab, 0xab, - 0x50, 0xb2, 0x6c, 0xd2, 0x35, 0x86, 0x6d, 0xb3, 0xa7, 0x29, 0x48, 0x83, 0x8a, 0x6d, 0x99, 0xb6, - 0x45, 0xba, 0x46, 0xc7, 0xee, 0x72, 0x7e, 0x7f, 0x0a, 0xdb, 0x3d, 0xd3, 0x7a, 0x49, 0x2c, 0x7b, - 0x48, 0x8c, 0x9e, 0xf9, 0xdc, 0x3c, 0xea, 0x19, 0x5a, 0x1e, 0xdd, 0x03, 0xcd, 0xb6, 0x48, 0xe7, - 0xa4, 0x6d, 0x5a, 0x64, 0x68, 0x9e, 0x1a, 0xf6, 0xd9, 0x50, 0x53, 0x39, 0xca, 0x1d, 0x21, 0xc6, - 0xeb, 0x8e, 0x61, 0x74, 0x07, 0xe4, 0xb4, 0xfd, 0x5a, 0x2b, 0xa0, 0x3a, 0xdc, 0x33, 0xad, 0xc1, - 0xd9, 0xf1, 0xb1, 0xd9, 0x31, 0x0d, 0x6b, 0x48, 0x8e, 0xda, 0xbd, 0xb6, 0xd5, 0x31, 0xb4, 0x0d, - 0xb4, 0x0b, 0xc8, 0xb4, 0x3a, 0xf6, 0x69, 0xbf, 0x67, 0x0c, 0x0d, 0x92, 0xd6, 0xd1, 0x26, 0xda, - 0x81, 0x2d, 0x61, 0xa7, 0xdd, 0xed, 0x92, 0xe3, 0xb6, 0xd9, 0x33, 0xba, 0x5a, 0x91, 0x7b, 0x22, - 0x35, 0x06, 0xa4, 0x6b, 0x0e, 0xda, 0x47, 0x1c, 0x2e, 0xf1, 0x35, 0x4d, 0xeb, 0xdc, 0x36, 0x3b, - 0x06, 0xe9, 0x70, 0xb3, 0x1c, 0x05, 0xae, 0x9c, 0xa2, 0x67, 0x56, 0xd7, 0xc0, 0xfd, 0xb6, 0xd9, - 0xd5, 0xca, 0x68, 0x0f, 0xee, 0xa7, 0xb0, 0xf1, 0xba, 0x6f, 0xe2, 0x37, 0x64, 0x68, 0xdb, 0x64, - 0x60, 0xdb, 0x96, 0x56, 0xc9, 0x5a, 0xe2, 0xd1, 0xda, 0x7d, 0xc3, 0xd2, 0xaa, 0xe8, 0x3e, 0xec, - 0x9c, 0xf6, 0xfb, 0x24, 0x95, 0xa4, 0xc1, 0xd6, 0xb8, 0x7a, 0xbb, 0xdb, 0xc5, 0xc6, 0x60, 0x40, - 0x4e, 0xcd, 0xc1, 0x69, 0x7b, 0xd8, 0x39, 0xd1, 0xb6, 0x78, 0x48, 0x03, 0x63, 0x48, 0x86, 0xf6, - 0xb0, 0xdd, 0x5b, 0xe2, 0x1a, 0x77, 0x68, 0x89, 0xf3, 0x45, 0x7b, 0xf6, 0x2b, 0x6d, 0x9b, 0x6f, - 0x38, 0x87, 0xed, 0x73, 0xe9, 0x22, 0xe2, 0xb1, 0xcb, 0xf4, 0xa4, 0x6b, 0x6a, 0x3b, 0x1c, 0x34, - 0xad, 0xf3, 0x76, 0xcf, 0xec, 0x92, 0x97, 0xc6, 0x1b, 0x71, 0x0e, 0xdd, 0xe3, 0x60, 0xe2, 0x19, - 0xe9, 0x63, 0xfb, 0x39, 0x77, 0x44, 0xfb, 0x14, 0x21, 0xa8, 0x75, 0x4c, 0xdc, 0x39, 0xeb, 0xb5, - 0x31, 0xc1, 0xf6, 0xd9, 0xd0, 0xd0, 0x76, 0x9f, 0xfc, 0x4d, 0x81, 0x4a, 0x96, 0x67, 0x3c, 0xeb, - 0xa6, 0x45, 0x8e, 0x7b, 0xe6, 0xf3, 0x93, 0x61, 0x42, 0x82, 0xc1, 0x59, 0x87, 0xa7, 0xcc, 0xe0, - 0xe7, 0x1b, 0x82, 0x5a, 0xb2, 0xe9, 0x8b, 0x60, 0x73, 0x7c, 0x2d, 0x89, 0x59, 0xb6, 0xb4, 0x9b, - 0xe7, 0xce, 0x4b, 0xd0, 0xc0, 0xd8, 0xc6, 0x9a, 0x8a, 0xbe, 0x84, 0xa6, 0x44, 0x78, 0x5e, 0x31, - 0x36, 0x3a, 0x43, 0xd2, 0x6f, 0xbf, 0x39, 0xe5, 0x69, 0x4f, 0x48, 0x36, 0xd0, 0x0a, 0xe8, 0x73, - 0xd8, 0x5b, 0x68, 0xad, 0xe3, 0xc5, 0xe1, 0x5f, 0x36, 0x61, 0x43, 0xb4, 0xf9, 0x08, 0xfd, 0x16, - 0xaa, 0x99, 0x67, 0xec, 0xf9, 0x21, 0x7a, 0xf8, 0xc1, 0x07, 0x6e, 0x23, 0x7d, 0x0c, 0x48, 0xf8, - 0x99, 0x82, 0x8e, 0xa0, 0x96, 0x7d, 0xcf, 0x9d, 0x1f, 0xa2, 0x6c, 0x77, 0x5c, 0xf3, 0xd4, 0x5b, - 0x63, 0xe3, 0x25, 0x68, 0x46, 0xcc, 0x5c, 0x9f, 0x17, 0xa9, 0x7c, 0x71, 0xa1, 0x46, 0xc6, 0xca, - 0x8d, 0x67, 0x5c, 0x63, 0x6f, 0xad, 0x4c, 0xde, 0x6b, 0x7a, 0xfc, 0x40, 0x5c, 0xbc, 0x79, 0x6e, - 0x05, 0xb4, 0xfa, 0xd0, 0x6a, 0x7c, 0x76, 0x97, 0x58, 0x5a, 0x1b, 0xc3, 0xce, 0x9a, 0x67, 0x0c, - 0xfa, 0x2a, 0xeb, 0xc1, 0x9d, 0x8f, 0xa0, 0xc6, 0xa3, 0x8f, 0xa9, 0x2d, 0x57, 0x59, 0xf3, 0xde, - 0x59, 0x59, 0xe5, 0xee, 0xd7, 0xd2, 0xca, 0x2a, 0x1f, 0x7a, 0x36, 0xbd, 0x05, 0xed, 0xe6, 0xf5, - 0x18, 0xe9, 0x37, 0xe7, 0xde, 0xbe, 0xa7, 0x37, 0xfe, 0xff, 0x83, 0x3a, 0xd2, 0xb8, 0x09, 0xb0, - 0xbc, 0x64, 0xa2, 0x07, 0x99, 0x29, 0xb7, 0x2e, 0xc9, 0x8d, 0x87, 0x77, 0x48, 0xa5, 0xa9, 0x21, - 0xec, 0xac, 0xb9, 0x75, 0xae, 0xec, 0xc6, 0xdd, 0xb7, 0xd2, 0xc6, 0xbd, 0x75, 0x97, 0xb3, 0x67, - 0x0a, 0x3a, 0x4d, 0x78, 0x91, 0xfe, 0xa4, 0xf2, 0x11, 0xa2, 0xd7, 0xd7, 0x37, 0x91, 0x79, 0xac, - 0xe7, 0xff, 0x94, 0x53, 0x9e, 0x29, 0xc8, 0x86, 0x4a, 0x96, 0xdc, 0x1f, 0x65, 0xfd, 0xc7, 0x0c, - 0x1e, 0x7d, 0xf3, 0xbb, 0x83, 0x4b, 0x97, 0x4d, 0xe7, 0x17, 0xfb, 0xa3, 0xd0, 0x3f, 0x10, 0xbf, - 0x64, 0x04, 0x6e, 0x70, 0x19, 0x50, 0xf6, 0x3e, 0x8c, 0xae, 0x0e, 0xbc, 0x60, 0x7c, 0x20, 0xea, - 0xe6, 0x60, 0x61, 0xe7, 0x62, 0x43, 0xfc, 0x34, 0xf9, 0xd3, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, - 0x16, 0x00, 0xbc, 0x19, 0xca, 0x14, 0x00, 0x00, + // 2268 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0xcf, 0x77, 0xdb, 0xc6, + 0xf1, 0x0f, 0x48, 0x50, 0x22, 0x87, 0x3f, 0x04, 0x2d, 0x1d, 0x19, 0x5f, 0x2a, 0x4e, 0x18, 0x7c, + 0x13, 0x87, 0xcf, 0x4d, 0x24, 0x47, 0xed, 0x6b, 0xf3, 0xda, 0x26, 0x2d, 0x45, 0x42, 0x11, 0x6c, + 0x0a, 0x60, 0x96, 0x94, 0x6c, 0xd7, 0x87, 0x7d, 0x10, 0xb9, 0x14, 0x51, 0x81, 0x00, 0x0b, 0x2c, + 0xed, 0xe8, 0xd8, 0x5b, 0x5f, 0xaf, 0xfd, 0x23, 0x7a, 0xeb, 0x5f, 0xd0, 0xff, 0xa5, 0xd7, 0xde, + 0xfb, 0x5e, 0xcf, 0x7d, 0xbb, 0x58, 0x90, 0xa0, 0x44, 0xd9, 0xed, 0x45, 0xc2, 0x7e, 0xe6, 0xb3, + 0xb3, 0x33, 0x3b, 0x33, 0x3b, 0xbb, 0x84, 0xbd, 0x28, 0x5c, 0x30, 0x1a, 0x45, 0xf3, 0xd1, 0x61, + 0xf2, 0x75, 0x30, 0x8f, 0x42, 0x16, 0xa2, 0xd2, 0x12, 0x6f, 0x94, 0xa2, 0xf9, 0x28, 0x41, 0x8d, + 0x7f, 0x6d, 0x01, 0x1a, 0xd0, 0x60, 0xdc, 0x77, 0x6f, 0x66, 0x34, 0x60, 0x98, 0xfe, 0x61, 0x41, + 0x63, 0x86, 0x10, 0xa8, 0x63, 0x1a, 0x33, 0x5d, 0x69, 0x2a, 0xad, 0x0a, 0x16, 0xdf, 0x48, 0x83, + 0xbc, 0x3b, 0x63, 0x7a, 0xae, 0xa9, 0xb4, 0xf2, 0x98, 0x7f, 0xa2, 0xff, 0x83, 0xa2, 0x3b, 0x63, + 0x64, 0x16, 0xbb, 0x4c, 0xaf, 0x08, 0x78, 0xdb, 0x9d, 0xb1, 0xb3, 0xd8, 0x65, 0xe8, 0x53, 0xa8, + 0xcc, 0x13, 0x95, 0x64, 0xea, 0xc6, 0x53, 0x3d, 0x2f, 0x14, 0x95, 0x25, 0x76, 0xea, 0xc6, 0x53, + 0xd4, 0x02, 0x6d, 0xe2, 0x05, 0xae, 0x4f, 0x46, 0x3e, 0x7b, 0x43, 0xc6, 0xd4, 0x67, 0xae, 0xae, + 0x36, 0x95, 0x56, 0x01, 0xd7, 0x04, 0xde, 0xf1, 0xd9, 0x9b, 0x2e, 0x47, 0xd1, 0x17, 0xb0, 0x93, + 0x2a, 0x8b, 0x12, 0x03, 0xf5, 0x42, 0x53, 0x69, 0x95, 0x70, 0x6d, 0xbe, 0x6e, 0xf6, 0x17, 0xb0, + 0xc3, 0xbc, 0x19, 0x0d, 0x17, 0x8c, 0xc4, 0x74, 0x14, 0x06, 0xe3, 0x58, 0xdf, 0x4a, 0x34, 0x4a, + 0x78, 0x90, 0xa0, 0xc8, 0x80, 0xea, 0x84, 0x52, 0xe2, 0x7b, 0x33, 0x8f, 0x11, 0x6e, 0xfe, 0xb6, + 0x30, 0xbf, 0x3c, 0xa1, 0xb4, 0xc7, 0xb1, 0x81, 0xcb, 0xd0, 0x67, 0x50, 0x5b, 0x71, 0x84, 0x8f, + 0x55, 0x41, 0xaa, 0xa4, 0x24, 0xe1, 0xe8, 0x01, 0x68, 0xe1, 0x82, 0x5d, 0x85, 0x5e, 0x70, 0x45, + 0x46, 0x53, 0x37, 0x20, 0xde, 0x58, 0x2f, 0x36, 0x95, 0x96, 0x7a, 0xac, 0xea, 0xca, 0x53, 0x05, + 0xd7, 0x52, 0x69, 0x67, 0xea, 0x06, 0xd6, 0x18, 0x3d, 0x81, 0xdd, 0xdb, 0xfc, 0x58, 0xaf, 0x37, + 0xf3, 0x2d, 0x15, 0xef, 0xac, 0x53, 0x63, 0xf4, 0x18, 0x76, 0x7c, 0x37, 0x66, 0x64, 0x1a, 0xce, + 0xc9, 0x7c, 0x71, 0x79, 0x4d, 0x6f, 0xf4, 0x9a, 0xd8, 0xc7, 0x2a, 0x87, 0x4f, 0xc3, 0x79, 0x5f, + 0x80, 0xe8, 0x11, 0x80, 0xd8, 0x43, 0x61, 0xaa, 0x5e, 0x12, 0x1e, 0x97, 0x38, 0x22, 0xcc, 0x44, + 0x5f, 0x43, 0x59, 0xc4, 0x9e, 0x4c, 0xbd, 0x80, 0xc5, 0x3a, 0x34, 0xf3, 0xad, 0xf2, 0x91, 0x76, + 0xe0, 0x07, 0x3c, 0x0d, 0x30, 0x97, 0x9c, 0x7a, 0x01, 0xc3, 0x10, 0xa5, 0x9f, 0x31, 0x1a, 0x43, + 0x9d, 0xc7, 0x9c, 0x8c, 0x16, 0x31, 0x0b, 0x67, 0x24, 0xa2, 0xa3, 0x30, 0x1a, 0xc7, 0x7a, 0x59, + 0x4c, 0xfd, 0xd9, 0xc1, 0x32, 0x95, 0x0e, 0xee, 0xe6, 0xce, 0x41, 0x97, 0xc6, 0xac, 0x23, 0xe6, + 0xe1, 0x64, 0x9a, 0x19, 0xb0, 0xe8, 0x06, 0xef, 0x8e, 0x6f, 0xe3, 0xe8, 0x4b, 0x40, 0xae, 0xef, + 0x87, 0x6f, 0x49, 0x4c, 0xfd, 0x09, 0x91, 0xb1, 0xd4, 0x77, 0x9a, 0x4a, 0xab, 0x88, 0x35, 0x21, + 0x19, 0x50, 0x7f, 0x22, 0xd5, 0xa3, 0x9f, 0x43, 0x55, 0xd8, 0x34, 0xa1, 0x2e, 0x5b, 0x44, 0x34, + 0xd6, 0xb5, 0x66, 0xbe, 0x55, 0x3b, 0xda, 0x95, 0x8e, 0x9c, 0x24, 0xf0, 0xb1, 0xc7, 0x70, 0x85, + 0xf3, 0xe4, 0x38, 0x46, 0xfb, 0x50, 0x9a, 0xb9, 0x3f, 0x92, 0xb9, 0x1b, 0xb1, 0x58, 0xdf, 0x6d, + 0x2a, 0xad, 0x2a, 0x2e, 0xce, 0xdc, 0x1f, 0xfb, 0x7c, 0x8c, 0x0e, 0xa0, 0x1e, 0x84, 0xc4, 0x0b, + 0x26, 0xbe, 0x77, 0x35, 0x65, 0x64, 0x31, 0x1f, 0xbb, 0x8c, 0xc6, 0x3a, 0x12, 0x36, 0xec, 0x06, + 0xa1, 0x25, 0x25, 0xe7, 0x89, 0xa0, 0xd1, 0x85, 0xbd, 0xcd, 0xfe, 0xf1, 0xf2, 0xe0, 0x01, 0xe2, + 0x15, 0xa3, 0x62, 0xfe, 0x89, 0x1e, 0x40, 0xe1, 0x8d, 0xeb, 0x2f, 0xa8, 0x28, 0x99, 0x0a, 0x4e, + 0x06, 0xbf, 0xcc, 0x7d, 0xa3, 0x18, 0x53, 0xa8, 0x0f, 0x23, 0x77, 0x74, 0x7d, 0xab, 0xea, 0x6e, + 0x17, 0x8d, 0x72, 0xb7, 0x68, 0xee, 0xb1, 0x37, 0x77, 0x8f, 0xbd, 0xc6, 0x77, 0xb0, 0x23, 0x22, + 0x7c, 0x42, 0xe9, 0xbb, 0x6a, 0xfb, 0x21, 0xf0, 0xca, 0x15, 0x95, 0x90, 0xd4, 0xf7, 0x96, 0x3b, + 0xe3, 0x45, 0x60, 0x8c, 0x41, 0x5b, 0xcd, 0x8f, 0xe7, 0x61, 0x10, 0x53, 0x5e, 0xb8, 0x3c, 0x01, + 0x78, 0x06, 0xf3, 0x02, 0x11, 0xa5, 0xa1, 0x88, 0x59, 0x35, 0x89, 0x9f, 0x50, 0x2a, 0x8a, 0xe3, + 0x71, 0x52, 0x8f, 0xc4, 0x0f, 0x47, 0xd7, 0xbc, 0xc2, 0xdd, 0x1b, 0xa9, 0xbe, 0xca, 0xe1, 0x5e, + 0x38, 0xba, 0xee, 0x72, 0xd0, 0x78, 0x9d, 0x1c, 0x42, 0xc3, 0x50, 0xac, 0xf5, 0x3f, 0x6c, 0x87, + 0x01, 0x05, 0x91, 0x8b, 0x42, 0x6d, 0xf9, 0xa8, 0x92, 0x4d, 0x6a, 0x9c, 0x88, 0x8c, 0xd7, 0x50, + 0x5f, 0x53, 0x2e, 0xbd, 0x68, 0x40, 0x71, 0x1e, 0x51, 0x6f, 0xe6, 0x5e, 0x51, 0xa9, 0x79, 0x39, + 0x46, 0x2d, 0xd8, 0x9e, 0xb8, 0x9e, 0xbf, 0x88, 0x52, 0xc5, 0xb5, 0x34, 0xc9, 0x12, 0x14, 0xa7, + 0x62, 0xe3, 0x23, 0x68, 0x60, 0x1a, 0x53, 0x76, 0xe6, 0xc5, 0xb1, 0x17, 0x06, 0x9d, 0x30, 0x60, + 0x51, 0xe8, 0x4b, 0x0f, 0x8c, 0x47, 0xb0, 0xbf, 0x51, 0x9a, 0x98, 0xc0, 0x27, 0xff, 0xb0, 0xa0, + 0xd1, 0xcd, 0xe6, 0xc9, 0x3f, 0xc0, 0xfe, 0x46, 0xa9, 0xb4, 0xff, 0x4b, 0x28, 0xcc, 0x5d, 0x2f, + 0xe2, 0xb1, 0xe7, 0x45, 0xb9, 0x97, 0x29, 0xca, 0xbe, 0xeb, 0x45, 0xa7, 0x5e, 0xcc, 0xc2, 0xe8, + 0x06, 0x27, 0xa4, 0x67, 0x6a, 0x51, 0xd1, 0x72, 0xc6, 0x9f, 0x15, 0x28, 0x67, 0x84, 0xbc, 0x34, + 0x82, 0x70, 0x4c, 0xc9, 0x24, 0x0a, 0x67, 0xe9, 0x26, 0x70, 0xe0, 0x24, 0x0a, 0x67, 0x3c, 0x27, + 0x84, 0x90, 0x85, 0x32, 0x81, 0xb7, 0xf8, 0x70, 0x18, 0xa2, 0xaf, 0x60, 0x7b, 0x9a, 0x28, 0x10, + 0xc7, 0x66, 0xf9, 0xa8, 0x7e, 0x6b, 0xed, 0xae, 0xcb, 0x5c, 0x9c, 0x72, 0x9e, 0xa9, 0xc5, 0xbc, + 0xa6, 0x3e, 0x53, 0x8b, 0xaa, 0x56, 0x78, 0xa6, 0x16, 0x0b, 0xda, 0xd6, 0x33, 0xb5, 0xb8, 0xa5, + 0x6d, 0x1b, 0xff, 0x54, 0xa0, 0x98, 0xb2, 0xb9, 0x25, 0x7c, 0x4b, 0x09, 0xcf, 0x0b, 0x99, 0x4c, + 0x45, 0x0e, 0x0c, 0xbd, 0x19, 0x45, 0x4d, 0xa8, 0x08, 0xe1, 0x7a, 0x8a, 0x02, 0xc7, 0xda, 0x22, + 0x4d, 0xc5, 0x79, 0x9e, 0x32, 0x44, 0x3e, 0xaa, 0xf2, 0x3c, 0x4f, 0x28, 0x69, 0x4b, 0x8a, 0x17, + 0xa3, 0x11, 0x8d, 0xe3, 0x64, 0x95, 0x42, 0x42, 0x91, 0x98, 0x58, 0xe8, 0x31, 0xec, 0xa4, 0x94, + 0x74, 0xad, 0xad, 0x24, 0x5f, 0x25, 0x2c, 0x97, 0x6b, 0x81, 0x96, 0xe5, 0xcd, 0x56, 0x1d, 0xa4, + 0xb6, 0x22, 0xf2, 0x45, 0x13, 0xe7, 0x8d, 0xdf, 0xc3, 0x43, 0x11, 0xca, 0x7e, 0x14, 0x5e, 0xba, + 0x97, 0x9e, 0xef, 0xb1, 0x9b, 0x34, 0xc9, 0xb9, 0xe3, 0x51, 0x38, 0x23, 0x7c, 0x6f, 0xd3, 0x10, + 0x70, 0xc0, 0x0e, 0xc7, 0x94, 0x87, 0x80, 0x85, 0x89, 0x48, 0x86, 0x80, 0x85, 0x42, 0x90, 0xed, + 0xbc, 0xf9, 0xb5, 0xce, 0x6b, 0x5c, 0x83, 0x7e, 0x77, 0x2d, 0x99, 0x33, 0x4d, 0x28, 0xcf, 0x57, + 0xb0, 0x58, 0x4e, 0xc1, 0x59, 0x28, 0x1b, 0xdb, 0xdc, 0xfb, 0x63, 0x6b, 0xfc, 0x55, 0x81, 0xdd, + 0xe3, 0x85, 0xe7, 0x8f, 0xd7, 0x0a, 0x37, 0x6b, 0x9d, 0xb2, 0x7e, 0x2f, 0xd8, 0xd4, 0xf4, 0x73, + 0x1b, 0x9b, 0xfe, 0x97, 0x1b, 0x1a, 0x6b, 0x5e, 0x34, 0xd6, 0xdc, 0x86, 0xb6, 0xfa, 0x09, 0x94, + 0x57, 0x5d, 0x32, 0xd6, 0xd5, 0x66, 0xbe, 0x55, 0xc1, 0x30, 0x4d, 0x5b, 0x64, 0x6c, 0x7c, 0x03, + 0x28, 0x6b, 0xa8, 0xdc, 0x90, 0xe5, 0xf9, 0xa1, 0xdc, 0x7f, 0x7e, 0x7c, 0x04, 0x8d, 0xc1, 0xe2, + 0x32, 0x1e, 0x45, 0xde, 0x25, 0x3d, 0x65, 0xfe, 0xc8, 0x7c, 0x43, 0x03, 0x16, 0xa7, 0x55, 0xfa, + 0x6f, 0x15, 0x4a, 0x4b, 0x94, 0x1f, 0xcf, 0x5e, 0x30, 0x0a, 0x67, 0xa9, 0xd1, 0x01, 0xf5, 0xb9, + 0xdd, 0x49, 0x53, 0xd8, 0x4d, 0x45, 0x9d, 0x44, 0x62, 0x8d, 0x39, 0x7f, 0xcd, 0x49, 0xc9, 0xcf, + 0x25, 0xfc, 0xac, 0x8f, 0x09, 0xbf, 0x05, 0xda, 0x52, 0xff, 0x94, 0xf9, 0xa3, 0xe5, 0xa6, 0xe0, + 0x5a, 0x8a, 0x73, 0x63, 0x12, 0xe6, 0x52, 0x73, 0xca, 0x54, 0x13, 0x66, 0x8a, 0x4b, 0xe6, 0xa7, + 0x50, 0xe1, 0xf5, 0x10, 0x33, 0x77, 0x36, 0x27, 0x41, 0x2c, 0xea, 0x42, 0xc5, 0xe5, 0x25, 0x66, + 0xc7, 0xe8, 0x5b, 0x00, 0xca, 0xfd, 0x23, 0xec, 0x66, 0x4e, 0x45, 0x49, 0xd4, 0x8e, 0x3e, 0xce, + 0x24, 0xc6, 0x72, 0x03, 0x0e, 0xc4, 0xdf, 0xe1, 0xcd, 0x9c, 0xe2, 0x12, 0x4d, 0x3f, 0xd1, 0x77, + 0x50, 0x9d, 0x84, 0xd1, 0x5b, 0x37, 0x1a, 0x13, 0x01, 0xca, 0x63, 0xe3, 0x61, 0x46, 0xc3, 0x49, + 0x22, 0x17, 0xd3, 0x4f, 0x3f, 0xc0, 0x95, 0x49, 0x66, 0x8c, 0x9e, 0x03, 0x4a, 0xe7, 0x8b, 0x2a, + 0x4f, 0x94, 0x14, 0x85, 0x92, 0xfd, 0xbb, 0x4a, 0xf8, 0x21, 0x9d, 0x2a, 0xd2, 0x26, 0xb7, 0x30, + 0xf4, 0x2b, 0xa8, 0xc4, 0x94, 0x31, 0x9f, 0x4a, 0x35, 0x25, 0xa1, 0x66, 0x6f, 0xed, 0x4e, 0xc3, + 0xc5, 0xa9, 0x86, 0x72, 0xbc, 0x1a, 0xa2, 0x63, 0xd8, 0xf1, 0xbd, 0xe0, 0x3a, 0x6b, 0x06, 0x88, + 0xf9, 0x7a, 0x66, 0x7e, 0xcf, 0x0b, 0xae, 0xb3, 0x36, 0x54, 0xfd, 0x2c, 0x60, 0xfc, 0x1a, 0x4a, + 0xcb, 0x5d, 0x42, 0x65, 0xd8, 0x3e, 0xb7, 0x9f, 0xdb, 0xce, 0x0b, 0x5b, 0xfb, 0x00, 0x15, 0x41, + 0x1d, 0x98, 0x76, 0x57, 0x53, 0x38, 0x8c, 0xcd, 0x8e, 0x69, 0x5d, 0x98, 0x5a, 0x8e, 0x0f, 0x4e, + 0x1c, 0xfc, 0xa2, 0x8d, 0xbb, 0x5a, 0xfe, 0x78, 0x1b, 0x0a, 0x62, 0x5d, 0xe3, 0xef, 0x0a, 0x14, + 0x45, 0x04, 0x83, 0x49, 0x88, 0x7e, 0x02, 0xcb, 0xe4, 0x12, 0x87, 0x1b, 0x6f, 0xb8, 0x22, 0xeb, + 0xaa, 0x78, 0x99, 0x30, 0x43, 0x89, 0x73, 0xf2, 0x32, 0x35, 0x96, 0xe4, 0x5c, 0x42, 0x4e, 0x05, + 0x4b, 0xf2, 0x93, 0x8c, 0xe6, 0xb5, 0x23, 0x47, 0xc5, 0x3b, 0xa9, 0x20, 0x3d, 0x61, 0xb3, 0x77, + 0xdb, 0xb5, 0x93, 0x38, 0x73, 0xb7, 0x95, 0x5c, 0xe3, 0x17, 0x50, 0xc9, 0xc6, 0x1c, 0x7d, 0x01, + 0xaa, 0x17, 0x4c, 0x42, 0x59, 0x88, 0xf5, 0x5b, 0xc9, 0xc5, 0x9d, 0xc4, 0x82, 0x60, 0x20, 0xd0, + 0x6e, 0xc7, 0xd9, 0xa8, 0x42, 0x39, 0x13, 0x34, 0xe3, 0x1f, 0x0a, 0x54, 0xd7, 0x82, 0xf0, 0x5f, + 0x6b, 0x47, 0xdf, 0x42, 0xe5, 0xad, 0x17, 0x51, 0x92, 0x6d, 0xff, 0xb5, 0xa3, 0xc6, 0x7a, 0xfb, + 0x4f, 0xff, 0x77, 0xc2, 0x31, 0xc5, 0x65, 0xce, 0x97, 0x00, 0xfa, 0x0d, 0xd4, 0xe4, 0x4c, 0x32, + 0xa6, 0xcc, 0xf5, 0x7c, 0xb1, 0x55, 0xb5, 0xb5, 0xf4, 0x90, 0xdc, 0xae, 0x90, 0xe3, 0xea, 0x24, + 0x3b, 0x44, 0x9f, 0xaf, 0x14, 0xc4, 0x2c, 0xf2, 0x82, 0x2b, 0xb1, 0x7f, 0xa5, 0x25, 0x6d, 0x20, + 0x40, 0xde, 0xc8, 0xab, 0xf2, 0xf2, 0x38, 0x60, 0x2e, 0x5b, 0xc4, 0xe8, 0x2b, 0x28, 0xc4, 0xcc, + 0x95, 0x27, 0x59, 0x6d, 0xad, 0xb6, 0x32, 0x44, 0x8a, 0x13, 0xd6, 0xda, 0xed, 0x27, 0x77, 0xe7, + 0xf6, 0x53, 0xe0, 0x27, 0x46, 0x72, 0x8a, 0x96, 0x8f, 0x90, 0x74, 0xfe, 0x74, 0xd8, 0xeb, 0xb4, + 0x19, 0xa3, 0xb3, 0x39, 0xc3, 0x09, 0x21, 0xe9, 0x6e, 0x4f, 0xfe, 0xa8, 0x42, 0x75, 0xcd, 0xa9, + 0xf5, 0xac, 0xae, 0x42, 0xc9, 0x76, 0x48, 0xd7, 0x1c, 0xb6, 0xad, 0x9e, 0xa6, 0x20, 0x0d, 0x2a, + 0x8e, 0x6d, 0x39, 0x36, 0xe9, 0x9a, 0x1d, 0xa7, 0xcb, 0xf3, 0xfb, 0x43, 0xd8, 0xed, 0x59, 0xf6, + 0x73, 0x62, 0x3b, 0x43, 0x62, 0xf6, 0xac, 0xef, 0xad, 0xe3, 0x9e, 0xa9, 0xe5, 0xd1, 0x03, 0xd0, + 0x1c, 0x9b, 0x74, 0x4e, 0xdb, 0x96, 0x4d, 0x86, 0xd6, 0x99, 0xe9, 0x9c, 0x0f, 0x35, 0x95, 0xa3, + 0xdc, 0x10, 0x62, 0xbe, 0xec, 0x98, 0x66, 0x77, 0x40, 0xce, 0xda, 0x2f, 0xb5, 0x02, 0xd2, 0xe1, + 0x81, 0x65, 0x0f, 0xce, 0x4f, 0x4e, 0xac, 0x8e, 0x65, 0xda, 0x43, 0x72, 0xdc, 0xee, 0xb5, 0xed, + 0x8e, 0xa9, 0x6d, 0xa1, 0x3d, 0x40, 0x96, 0xdd, 0x71, 0xce, 0xfa, 0x3d, 0x73, 0x68, 0x92, 0xb4, + 0x8e, 0xb6, 0x51, 0x1d, 0x76, 0x84, 0x9e, 0x76, 0xb7, 0x4b, 0x4e, 0xda, 0x56, 0xcf, 0xec, 0x6a, + 0x45, 0x6e, 0x89, 0x64, 0x0c, 0x48, 0xd7, 0x1a, 0xb4, 0x8f, 0x39, 0x5c, 0xe2, 0x6b, 0x5a, 0xf6, + 0x85, 0x63, 0x75, 0x4c, 0xd2, 0xe1, 0x6a, 0x39, 0x0a, 0x9c, 0x9c, 0xa2, 0xe7, 0x76, 0xd7, 0xc4, + 0xfd, 0xb6, 0xd5, 0xd5, 0xca, 0x68, 0x1f, 0x1e, 0xa6, 0xb0, 0xf9, 0xb2, 0x6f, 0xe1, 0x57, 0x64, + 0xe8, 0x38, 0x64, 0xe0, 0x38, 0xb6, 0x56, 0xc9, 0x6a, 0xe2, 0xde, 0x3a, 0x7d, 0xd3, 0xd6, 0xaa, + 0xe8, 0x21, 0xd4, 0xcf, 0xfa, 0x7d, 0x92, 0x4a, 0x52, 0x67, 0x6b, 0x9c, 0xde, 0xee, 0x76, 0xb1, + 0x39, 0x18, 0x90, 0x33, 0x6b, 0x70, 0xd6, 0x1e, 0x76, 0x4e, 0xb5, 0x1d, 0xee, 0xd2, 0xc0, 0x1c, + 0x92, 0xa1, 0x33, 0x6c, 0xf7, 0x56, 0xb8, 0xc6, 0x0d, 0x5a, 0xe1, 0x7c, 0xd1, 0x9e, 0xf3, 0x42, + 0xdb, 0xe5, 0x1b, 0xce, 0x61, 0xe7, 0x42, 0x9a, 0x88, 0xb8, 0xef, 0x32, 0x3c, 0xe9, 0x9a, 0x5a, + 0x9d, 0x83, 0x96, 0x7d, 0xd1, 0xee, 0x59, 0x5d, 0xf2, 0xdc, 0x7c, 0x25, 0xce, 0xa1, 0x07, 0x1c, + 0x4c, 0x2c, 0x23, 0x7d, 0xec, 0x7c, 0xcf, 0x0d, 0xd1, 0x3e, 0x44, 0x08, 0x6a, 0x1d, 0x0b, 0x77, + 0xce, 0x7b, 0x6d, 0x4c, 0xb0, 0x73, 0x3e, 0x34, 0xb5, 0xbd, 0x27, 0x7f, 0x53, 0xa0, 0x92, 0xcd, + 0x33, 0x1e, 0x75, 0xcb, 0x26, 0x27, 0x3d, 0xeb, 0xfb, 0xd3, 0x61, 0x92, 0x04, 0x83, 0xf3, 0x0e, + 0x0f, 0x99, 0xc9, 0xcf, 0x37, 0x04, 0xb5, 0x64, 0xd3, 0x97, 0xce, 0xe6, 0xf8, 0x5a, 0x12, 0xb3, + 0x1d, 0xa9, 0x37, 0xcf, 0x8d, 0x97, 0xa0, 0x89, 0xb1, 0x83, 0x35, 0x15, 0x7d, 0x06, 0x4d, 0x89, + 0xf0, 0xb8, 0x62, 0x6c, 0x76, 0x86, 0xa4, 0xdf, 0x7e, 0x75, 0xc6, 0xc3, 0x9e, 0x24, 0xd9, 0x40, + 0x2b, 0xa0, 0x4f, 0x60, 0x7f, 0xc9, 0xda, 0x94, 0x17, 0x47, 0x7f, 0xd9, 0x86, 0x2d, 0xd1, 0xe6, + 0x23, 0xf4, 0x5b, 0xa8, 0x66, 0x9e, 0xb1, 0x17, 0x47, 0xe8, 0xd1, 0x3b, 0x1f, 0xb8, 0x8d, 0xf4, + 0x31, 0x20, 0xe1, 0xa7, 0x0a, 0x3a, 0x86, 0x5a, 0xf6, 0x3d, 0x77, 0x71, 0x84, 0xb2, 0xdd, 0x71, + 0xc3, 0x53, 0x6f, 0x83, 0x8e, 0xe7, 0xa0, 0x99, 0x31, 0xf3, 0x66, 0xbc, 0x48, 0xe5, 0x8b, 0x0b, + 0x35, 0x32, 0x5a, 0x6e, 0x3d, 0xe3, 0x1a, 0xfb, 0x1b, 0x65, 0xf2, 0x5e, 0xd3, 0xe3, 0x07, 0xe2, + 0xf2, 0xcd, 0x73, 0xc7, 0xa1, 0xf5, 0x87, 0x56, 0xe3, 0xe3, 0xfb, 0xc4, 0x52, 0xdb, 0x18, 0xea, + 0x1b, 0x9e, 0x31, 0xe8, 0xf3, 0xac, 0x05, 0xf7, 0x3e, 0x82, 0x1a, 0x8f, 0xdf, 0x47, 0x5b, 0xad, + 0xb2, 0xe1, 0xbd, 0xb3, 0xb6, 0xca, 0xfd, 0xaf, 0xa5, 0xb5, 0x55, 0xde, 0xf5, 0x6c, 0x7a, 0x0d, + 0xda, 0xed, 0xeb, 0x31, 0x32, 0x6e, 0xcf, 0xbd, 0x7b, 0x4f, 0x6f, 0xfc, 0xff, 0x3b, 0x39, 0x52, + 0xb9, 0x05, 0xb0, 0xba, 0x64, 0xa2, 0x8f, 0x32, 0x53, 0xee, 0x5c, 0x92, 0x1b, 0x8f, 0xee, 0x91, + 0x4a, 0x55, 0x43, 0xa8, 0x6f, 0xb8, 0x75, 0xae, 0xed, 0xc6, 0xfd, 0xb7, 0xd2, 0xc6, 0x83, 0x4d, + 0x97, 0xb3, 0xa7, 0x0a, 0x3a, 0x4b, 0xf2, 0x22, 0xfd, 0x49, 0xe5, 0x3d, 0x89, 0xae, 0x6f, 0x6e, + 0x22, 0x8b, 0xd8, 0xc8, 0xff, 0x29, 0xa7, 0x3c, 0x55, 0x90, 0x03, 0x95, 0x6c, 0x72, 0xbf, 0x37, + 0xeb, 0xdf, 0xa7, 0xf0, 0xf8, 0xeb, 0xdf, 0x1d, 0x5e, 0x79, 0x6c, 0xba, 0xb8, 0x3c, 0x18, 0x85, + 0xb3, 0x43, 0xf1, 0x4b, 0x46, 0xe0, 0x05, 0x57, 0x01, 0x65, 0x6f, 0xc3, 0xe8, 0xfa, 0xd0, 0x0f, + 0xc6, 0x87, 0xa2, 0x6e, 0x0e, 0x97, 0x7a, 0x2e, 0xb7, 0xc4, 0x0f, 0x99, 0x3f, 0xfd, 0x4f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x61, 0x45, 0xd3, 0x59, 0xf8, 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 673ffb986b..f515af2684 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -71,11 +71,18 @@ message SendPaymentRequest { */ int64 fee_limit_msat = 13; - /** - The channel id of the channel that must be taken to the first hop. If zero, + /* + Deprecated, use outgoing_chan_ids. The channel id of the channel that must + be taken to the first hop. If zero, any channel may be used (unless + outgoing_chan_ids are set). + */ + uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true]; + + /* + The channel ids of the channels are allowed for the first hop. If empty, any channel may be used. */ - uint64 outgoing_chan_id = 8 [jstype = JS_STRING]; + repeated uint64 outgoing_chan_ids = 19; /** The pubkey of the last hop of the route. If empty, any hop may be used. diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 354e5e29d3..4292ee6549 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -248,7 +248,7 @@ func (r *RouterBackend) QueryRoutes(ctx context.Context, // Pass along an outgoing channel restriction if specified. if in.OutgoingChanId != 0 { - restrictions.OutgoingChannelID = &in.OutgoingChanId + restrictions.OutgoingChannelIDs = []uint64{in.OutgoingChanId} } // Pass along a last hop restriction if specified. @@ -522,9 +522,19 @@ func (r *RouterBackend) extractIntentFromSendRequest( payIntent := &routing.LightningPayment{} - // Pass along an outgoing channel restriction if specified. + // Pass along restrictions on the outgoing channels that may be used. + payIntent.OutgoingChannelIDs = rpcPayReq.OutgoingChanIds + + // Add the deprecated single outgoing channel restriction if present. if rpcPayReq.OutgoingChanId != 0 { - payIntent.OutgoingChannelID = &rpcPayReq.OutgoingChanId + if payIntent.OutgoingChannelIDs != nil { + return nil, errors.New("outgoing_chan_id and " + + "outgoing_chan_ids are mutually exclusive") + } + + payIntent.OutgoingChannelIDs = append( + payIntent.OutgoingChannelIDs, rpcPayReq.OutgoingChanId, + ) } // Pass along a last hop restriction if specified. diff --git a/lnrpc/routerrpc/router_backend_test.go b/lnrpc/routerrpc/router_backend_test.go index 33a0ccfba3..3e2bd91669 100644 --- a/lnrpc/routerrpc/router_backend_test.go +++ b/lnrpc/routerrpc/router_backend_test.go @@ -159,7 +159,7 @@ func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool) { t.Fatal("unexpected last hop") } - if *restrictions.OutgoingChannelID != outgoingChan { + if restrictions.OutgoingChannelIDs[0] != outgoingChan { t.Fatal("unexpected outgoing channel id") } diff --git a/routing/pathfind.go b/routing/pathfind.go index e5def09b53..70efb1c2dd 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -284,9 +284,9 @@ type RestrictParams struct { // the source to the target. FeeLimit lnwire.MilliSatoshi - // OutgoingChannelID is the channel that needs to be taken to the first - // hop. If nil, any channel may be used. - OutgoingChannelID *uint64 + // OutgoingChannelIDs is the list of channels that are allowed for the + // first hop. If nil, any channel may be used. + OutgoingChannelIDs []uint64 // LastHop is the pubkey of the last node before the final destination // is reached. If nil, any node may be used. @@ -329,7 +329,7 @@ type PathFindingConfig struct { // getOutgoingBalance returns the maximum available balance in any of the // channels of the given node. The second return parameters is the total // available balance. -func getOutgoingBalance(node route.Vertex, outgoingChan *uint64, +func getOutgoingBalance(node route.Vertex, outgoingChans map[uint64]struct{}, bandwidthHints map[uint64]lnwire.MilliSatoshi, g routingGraph) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, error) { @@ -344,8 +344,10 @@ func getOutgoingBalance(node route.Vertex, outgoingChan *uint64, chanID := outEdge.ChannelID // Enforce outgoing channel restriction. - if outgoingChan != nil && chanID != *outgoingChan { - return nil + if outgoingChans != nil { + if _, ok := outgoingChans[chanID]; !ok { + return nil + } } bandwidth, ok := bandwidthHints[chanID] @@ -447,13 +449,22 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, return nil, errNoPaymentAddr } + // Set up outgoing channel map for quicker access. + var outgoingChanMap map[uint64]struct{} + if len(r.OutgoingChannelIDs) > 0 { + outgoingChanMap = make(map[uint64]struct{}) + for _, outChan := range r.OutgoingChannelIDs { + outgoingChanMap[outChan] = struct{}{} + } + } + // If we are routing from ourselves, check that we have enough local // balance available. self := g.graph.sourceNode() if source == self { max, total, err := getOutgoingBalance( - self, r.OutgoingChannelID, g.bandwidthHints, g.graph, + self, outgoingChanMap, g.bandwidthHints, g.graph, ) if err != nil { return nil, err @@ -763,7 +774,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, pivot := partialPath.node // Create unified policies for all incoming connections. - u := newUnifiedPolicies(self, pivot, r.OutgoingChannelID) + u := newUnifiedPolicies(self, pivot, outgoingChanMap) err := u.addGraphPolicies(g.graph) if err != nil { diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index f524c348be..043ca2cd58 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -2256,11 +2256,12 @@ func TestRestrictOutgoingChannel(t *testing.T) { // Define channel id constants const ( - chanSourceA = 1 - chanATarget = 4 - chanSourceB1 = 2 - chanSourceB2 = 3 - chanBTarget = 5 + chanSourceA = 1 + chanATarget = 4 + chanSourceB1 = 2 + chanSourceB2 = 3 + chanBTarget = 5 + chanSourceTarget = 6 ) // Set up a test graph with three possible paths from roasbeef to @@ -2283,6 +2284,9 @@ func TestRestrictOutgoingChannel(t *testing.T) { Expiry: 144, FeeRate: 800, }, chanBTarget), + symmetricTestChannel("roasbeef", "target", 100000, &testChannelPolicy{ + Expiry: 144, + }, chanSourceTarget), } ctx := newPathFindingTestContext(t, testChannels, "roasbeef") @@ -2297,9 +2301,9 @@ func TestRestrictOutgoingChannel(t *testing.T) { target := ctx.keyFromAlias("target") outgoingChannelID := uint64(chanSourceB1) - // Find the best path given the restriction to only use chanSourceB1 as - // the outgoing channel. - ctx.restrictParams.OutgoingChannelID = &outgoingChannelID + // Find the best path given the restriction to only use channel 2 as the + // outgoing channel. + ctx.restrictParams.OutgoingChannelIDs = []uint64{outgoingChannelID} path, err := ctx.findPath(target, paymentAmt) if err != nil { t.Fatalf("unable to find path: %v", err) @@ -2312,6 +2316,20 @@ func TestRestrictOutgoingChannel(t *testing.T) { "but channel %v was selected instead", chanSourceB1, path[0].ChannelID) } + + // If a direct channel to target is allowed as well, that channel is + // expected to be selected because the routing fees are zero. + ctx.restrictParams.OutgoingChannelIDs = []uint64{ + chanSourceB1, chanSourceTarget, + } + path, err = ctx.findPath(target, paymentAmt) + if err != nil { + t.Fatalf("unable to find path: %v", err) + } + if path[0].ChannelID != chanSourceTarget { + t.Fatalf("expected route to pass through channel %v", + chanSourceTarget) + } } // TestRestrictLastHop asserts that a last hop restriction is obeyed by the path @@ -2773,7 +2791,7 @@ func TestRouteToSelf(t *testing.T) { outgoingChanID := uint64(1) lastHop := ctx.keyFromAlias("b") - ctx.restrictParams.OutgoingChannelID = &outgoingChanID + ctx.restrictParams.OutgoingChannelIDs = []uint64{outgoingChanID} ctx.restrictParams.LastHop = &lastHop // Find the best path to self given that we want to go out via channel 1 diff --git a/routing/payment_session.go b/routing/payment_session.go index ed22b8c631..b4aac5aad1 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -202,14 +202,14 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi, // to our destination, respecting the recommendations from // MissionControl. restrictions := &RestrictParams{ - ProbabilitySource: p.missionControl.GetProbability, - FeeLimit: feeLimit, - OutgoingChannelID: p.payment.OutgoingChannelID, - LastHop: p.payment.LastHop, - CltvLimit: cltvLimit, - DestCustomRecords: p.payment.DestCustomRecords, - DestFeatures: p.payment.DestFeatures, - PaymentAddr: p.payment.PaymentAddr, + ProbabilitySource: p.missionControl.GetProbability, + FeeLimit: feeLimit, + OutgoingChannelIDs: p.payment.OutgoingChannelIDs, + LastHop: p.payment.LastHop, + CltvLimit: cltvLimit, + DestCustomRecords: p.payment.DestCustomRecords, + DestFeatures: p.payment.DestFeatures, + PaymentAddr: p.payment.PaymentAddr, } finalHtlcExpiry := int32(height) + int32(finalCltvDelta) diff --git a/routing/router.go b/routing/router.go index c3773fe6a6..2c73465c65 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1594,9 +1594,9 @@ type LightningPayment struct { // destination successfully. RouteHints [][]zpay32.HopHint - // OutgoingChannelID is the channel that needs to be taken to the first - // hop. If nil, any channel may be used. - OutgoingChannelID *uint64 + // OutgoingChannelIDs is the list of channels that are allowed for the + // first hop. If nil, any channel may be used. + OutgoingChannelIDs []uint64 // LastHop is the pubkey of the last node before the final destination // is reached. If nil, any node may be used. @@ -2379,6 +2379,13 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi, log.Tracef("BuildRoute called: hopsCount=%v, amt=%v", len(hops), amt) + var outgoingChans map[uint64]struct{} + if outgoingChan != nil { + outgoingChans = map[uint64]struct{}{ + *outgoingChan: {}, + } + } + // If no amount is specified, we need to build a route for the minimum // amount that this route can carry. useMinAmt := amt == nil @@ -2444,7 +2451,7 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi, // Build unified policies for this hop based on the channels // known in the graph. - u := newUnifiedPolicies(source, toNode, outgoingChan) + u := newUnifiedPolicies(source, toNode, outgoingChans) err := u.addGraphPolicies(routingTx) if err != nil { diff --git a/routing/unified_policies.go b/routing/unified_policies.go index 3759175a6e..0ff509382e 100644 --- a/routing/unified_policies.go +++ b/routing/unified_policies.go @@ -21,13 +21,13 @@ type unifiedPolicies struct { // outChanRestr is an optional outgoing channel restriction for the // local channel to use. - outChanRestr *uint64 + outChanRestr map[uint64]struct{} } // newUnifiedPolicies instantiates a new unifiedPolicies object. Channel // policies can be added to this object. func newUnifiedPolicies(sourceNode, toNode route.Vertex, - outChanRestr *uint64) *unifiedPolicies { + outChanRestr map[uint64]struct{}) *unifiedPolicies { return &unifiedPolicies{ policies: make(map[route.Vertex]*unifiedPolicy), @@ -45,10 +45,10 @@ func (u *unifiedPolicies) addPolicy(fromNode route.Vertex, localChan := fromNode == u.sourceNode // Skip channels if there is an outgoing channel restriction. - if localChan && u.outChanRestr != nil && - *u.outChanRestr != edge.ChannelID { - - return + if localChan && u.outChanRestr != nil { + if _, ok := u.outChanRestr[edge.ChannelID]; !ok { + return + } } // Update the policies map. diff --git a/rpcserver.go b/rpcserver.go index 2db89ea66c..359d5d183a 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3692,18 +3692,18 @@ func (r *rpcServer) unmarshallSendToRouteRequest( // hints), or we'll get a fully populated route from the user that we'll pass // directly to the channel router for dispatching. type rpcPaymentIntent struct { - msat lnwire.MilliSatoshi - feeLimit lnwire.MilliSatoshi - cltvLimit uint32 - dest route.Vertex - rHash [32]byte - cltvDelta uint16 - routeHints [][]zpay32.HopHint - outgoingChannelID *uint64 - lastHop *route.Vertex - destFeatures *lnwire.FeatureVector - paymentAddr *[32]byte - payReq []byte + msat lnwire.MilliSatoshi + feeLimit lnwire.MilliSatoshi + cltvLimit uint32 + dest route.Vertex + rHash [32]byte + cltvDelta uint16 + routeHints [][]zpay32.HopHint + outgoingChannelIDs []uint64 + lastHop *route.Vertex + destFeatures *lnwire.FeatureVector + paymentAddr *[32]byte + payReq []byte destCustomRecords record.CustomSet @@ -3739,9 +3739,12 @@ func (r *rpcServer) extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPayme } // If there are no routes specified, pass along a outgoing channel - // restriction if specified. + // restriction if specified. The main server rpc does not support + // multiple channel restrictions. if rpcPayReq.OutgoingChanId != 0 { - payIntent.outgoingChannelID = &rpcPayReq.OutgoingChanId + payIntent.outgoingChannelIDs = []uint64{ + rpcPayReq.OutgoingChanId, + } } // Pass along a last hop restriction if specified. @@ -3956,20 +3959,20 @@ func (r *rpcServer) dispatchPaymentIntent( // router, otherwise we'll create a payment session to execute it. if payIntent.route == nil { payment := &routing.LightningPayment{ - Target: payIntent.dest, - Amount: payIntent.msat, - FinalCLTVDelta: payIntent.cltvDelta, - FeeLimit: payIntent.feeLimit, - CltvLimit: payIntent.cltvLimit, - PaymentHash: payIntent.rHash, - RouteHints: payIntent.routeHints, - OutgoingChannelID: payIntent.outgoingChannelID, - LastHop: payIntent.lastHop, - PaymentRequest: payIntent.payReq, - PayAttemptTimeout: routing.DefaultPayAttemptTimeout, - DestCustomRecords: payIntent.destCustomRecords, - DestFeatures: payIntent.destFeatures, - PaymentAddr: payIntent.paymentAddr, + Target: payIntent.dest, + Amount: payIntent.msat, + FinalCLTVDelta: payIntent.cltvDelta, + FeeLimit: payIntent.feeLimit, + CltvLimit: payIntent.cltvLimit, + PaymentHash: payIntent.rHash, + RouteHints: payIntent.routeHints, + OutgoingChannelIDs: payIntent.outgoingChannelIDs, + LastHop: payIntent.lastHop, + PaymentRequest: payIntent.payReq, + PayAttemptTimeout: routing.DefaultPayAttemptTimeout, + DestCustomRecords: payIntent.destCustomRecords, + DestFeatures: payIntent.destFeatures, + PaymentAddr: payIntent.paymentAddr, // Don't enable multi-part payments on the main rpc. // Users need to use routerrpc for that. From 4a914724699ea57dda30ad1953b83a378b6331ad Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 11 May 2020 15:23:43 -0700 Subject: [PATCH 540/562] wtclient: refactor existing candidate session filtering into method --- watchtower/wtclient/client.go | 95 +++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/watchtower/wtclient/client.go b/watchtower/wtclient/client.go index 76aa2a4bc6..8a37abe545 100644 --- a/watchtower/wtclient/client.go +++ b/watchtower/wtclient/client.go @@ -38,6 +38,14 @@ const ( DefaultForceQuitDelay = 10 * time.Second ) +var ( + // activeSessionFilter is a filter that ignored any sessions which are + // not active. + activeSessionFilter = func(s *wtdb.ClientSession) bool { + return s.Status == wtdb.CSessionActive + } +) + // RegisteredTower encompasses information about a registered watchtower with // the client. type RegisteredTower struct { @@ -268,49 +276,18 @@ func New(config *Config) (*TowerClient, error) { // the client. We will use any of these session if their policies match // the current policy of the client, otherwise they will be ignored and // new sessions will be requested. - sessions, err := cfg.DB.ListClientSessions(nil) + candidateSessions, err := getClientSessions( + cfg.DB, cfg.SecretKeyRing, nil, activeSessionFilter, + ) if err != nil { return nil, err } - candidateSessions := make(map[wtdb.SessionID]*wtdb.ClientSession) - sessionTowers := make(map[wtdb.TowerID]*wtdb.Tower) - for _, s := range sessions { - // Candidate sessions must be in an active state. - if s.Status != wtdb.CSessionActive { - continue - } - - // Reload the tower from disk using the tower ID contained in - // each candidate session. We will also rederive any session - // keys needed to be able to communicate with the towers and - // authenticate session requests. This prevents us from having - // to store the private keys on disk. - tower, ok := sessionTowers[s.TowerID] - if !ok { - var err error - tower, err = cfg.DB.LoadTowerByID(s.TowerID) - if err != nil { - return nil, err - } - } - s.Tower = tower - - sessionKey, err := DeriveSessionKey(cfg.SecretKeyRing, s.KeyIndex) - if err != nil { - return nil, err - } - s.SessionPrivKey = sessionKey - - candidateSessions[s.ID] = s - sessionTowers[tower.ID] = tower - } - var candidateTowers []*wtdb.Tower - for _, tower := range sessionTowers { + for _, s := range candidateSessions { log.Infof("Using private watchtower %s, offering policy %s", - tower, cfg.Policy) - candidateTowers = append(candidateTowers, tower) + s.Tower, cfg.Policy) + candidateTowers = append(candidateTowers, s.Tower) } // Load the sweep pkscripts that have been generated for all previously @@ -353,6 +330,50 @@ func New(config *Config) (*TowerClient, error) { return c, nil } +// getClientSessions retrieves the client sessions for a particular tower if +// specified, otherwise all client sessions for all towers are retrieved. An +// optional filter can be provided to filter out any undesired client sessions. +// +// NOTE: This method should only be used when deserialization of a +// ClientSession's Tower and SessionPrivKey fields is desired, otherwise, the +// existing ListClientSessions method should be used. +func getClientSessions(db DB, keyRing SecretKeyRing, forTower *wtdb.TowerID, + passesFilter func(*wtdb.ClientSession) bool) ( + map[wtdb.SessionID]*wtdb.ClientSession, error) { + + sessions, err := db.ListClientSessions(forTower) + if err != nil { + return nil, err + } + + // Reload the tower from disk using the tower ID contained in each + // candidate session. We will also rederive any session keys needed to + // be able to communicate with the towers and authenticate session + // requests. This prevents us from having to store the private keys on + // disk. + for _, s := range sessions { + tower, err := db.LoadTowerByID(s.TowerID) + if err != nil { + return nil, err + } + s.Tower = tower + + sessionKey, err := DeriveSessionKey(keyRing, s.KeyIndex) + if err != nil { + return nil, err + } + s.SessionPrivKey = sessionKey + + // If an optional filter was provided, use it to filter out any + // undesired sessions. + if passesFilter != nil && !passesFilter(s) { + delete(sessions, s.ID) + } + } + + return sessions, nil +} + // buildHighestCommitHeights inspects the full set of candidate client sessions // loaded from disk, and determines the highest known commit height for each // channel. This allows the client to reject backups that it has already From 2de2f28d230e2b993141d833534ae02ec44b0b14 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 11 May 2020 15:26:12 -0700 Subject: [PATCH 541/562] wtclient: load missing info into client sessions upon new tower This addresses a potential panic in where we relied on this missing info being populated. --- watchtower/wtclient/client.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/watchtower/wtclient/client.go b/watchtower/wtclient/client.go index 8a37abe545..6827cdca8f 100644 --- a/watchtower/wtclient/client.go +++ b/watchtower/wtclient/client.go @@ -1060,7 +1060,9 @@ func (c *TowerClient) handleNewTower(msg *newTowerMsg) error { c.candidateTowers.AddCandidate(tower) // Include all of its corresponding sessions to our set of candidates. - sessions, err := c.cfg.DB.ListClientSessions(&tower.ID) + sessions, err := getClientSessions( + c.cfg.DB, c.cfg.SecretKeyRing, &tower.ID, nil, + ) if err != nil { return fmt.Errorf("unable to determine sessions for tower %x: "+ "%v", tower.IdentityKey.SerializeCompressed(), err) From 1cbb5743333ac69252a3242b56121f031518acee Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 11 May 2020 15:26:36 -0700 Subject: [PATCH 542/562] wtclient: filter out inactive sessions upon adding existing/new tower --- watchtower/wtclient/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watchtower/wtclient/client.go b/watchtower/wtclient/client.go index 6827cdca8f..1f3c1c3cd3 100644 --- a/watchtower/wtclient/client.go +++ b/watchtower/wtclient/client.go @@ -1061,7 +1061,7 @@ func (c *TowerClient) handleNewTower(msg *newTowerMsg) error { // Include all of its corresponding sessions to our set of candidates. sessions, err := getClientSessions( - c.cfg.DB, c.cfg.SecretKeyRing, &tower.ID, nil, + c.cfg.DB, c.cfg.SecretKeyRing, &tower.ID, activeSessionFilter, ) if err != nil { return fmt.Errorf("unable to determine sessions for tower %x: "+ From badbc5a491f7fc39d1880a56dc4f35f11c885856 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 11 May 2020 16:05:04 -0700 Subject: [PATCH 543/562] rpc: use existing rpc logger for wtclientrpc The logger string used to identify the wtclient and wtclientrpc loggers was the same, leading to being unable to modify the log level of the wtclient logger as it would be overwritten with the wtclientrpc's one. To simplify things, we decide to use the existing RPC logger for wtclientrpc. --- lnrpc/wtclientrpc/config.go | 4 +++ lnrpc/wtclientrpc/log.go | 48 ----------------------------------- lnrpc/wtclientrpc/wtclient.go | 4 +-- log.go | 2 -- rpcserver.go | 1 + subrpcserver_config.go | 7 ++++- 6 files changed, 13 insertions(+), 53 deletions(-) delete mode 100644 lnrpc/wtclientrpc/log.go diff --git a/lnrpc/wtclientrpc/config.go b/lnrpc/wtclientrpc/config.go index a008ca0d38..8796bd0569 100644 --- a/lnrpc/wtclientrpc/config.go +++ b/lnrpc/wtclientrpc/config.go @@ -1,6 +1,7 @@ package wtclientrpc import ( + "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/watchtower/wtclient" ) @@ -22,4 +23,7 @@ type Config struct { // addresses to ensure we don't leak any information when running over // non-clear networks, e.g. Tor, etc. Resolver lncfg.TCPResolver + + // Log is the logger instance we should log output to. + Log btclog.Logger } diff --git a/lnrpc/wtclientrpc/log.go b/lnrpc/wtclientrpc/log.go deleted file mode 100644 index eaa847d647..0000000000 --- a/lnrpc/wtclientrpc/log.go +++ /dev/null @@ -1,48 +0,0 @@ -package wtclientrpc - -import ( - "github.com/btcsuite/btclog" - "github.com/lightningnetwork/lnd/build" -) - -// Subsystem defines the logging code for this subsystem. -const Subsystem = "WTCL" - -// log is a logger that is initialized with no output filters. This means the -// package will not perform any logging by default until the caller requests -// it. -var log btclog.Logger - -// The default amount of logging is none. -func init() { - UseLogger(build.NewSubLogger(Subsystem, nil)) -} - -// DisableLog disables all library log output. Logging output is disabled by -// by default until UseLogger is called. -func DisableLog() { - UseLogger(btclog.Disabled) -} - -// UseLogger uses a specified Logger to output package logging info. This -// should be used in preference to SetLogWriter if the caller is also using -// btclog. -func UseLogger(logger btclog.Logger) { - log = logger -} - -// logClosure is used to provide a closure over expensive logging operations so -// don't have to be performed when the logging level doesn't warrant it. -type logClosure func() string // nolint:unused - -// String invokes the underlying function and returns the result. -func (c logClosure) String() string { - return c() -} - -// newLogClosure returns a new closure over a function that returns a string -// which itself provides a Stringer interface so that it can be used with the -// logging system. -func newLogClosure(c func() string) logClosure { // nolint:unused - return logClosure(c) -} diff --git a/lnrpc/wtclientrpc/wtclient.go b/lnrpc/wtclientrpc/wtclient.go index 8cbdc9bfa9..b6f1fa2a8f 100644 --- a/lnrpc/wtclientrpc/wtclient.go +++ b/lnrpc/wtclientrpc/wtclient.go @@ -115,8 +115,8 @@ func (c *WatchtowerClient) RegisterWithRootServer(grpcServer *grpc.Server) error // all our methods are routed properly. RegisterWatchtowerClientServer(grpcServer, c) - log.Debugf("WatchtowerClient RPC server successfully registered with " + - "root gRPC server") + c.cfg.Log.Debugf("WatchtowerClient RPC server successfully registered " + + "with root gRPC server") return nil } diff --git a/log.go b/log.go index 51754cca54..abd1672690 100644 --- a/log.go +++ b/log.go @@ -25,7 +25,6 @@ import ( "github.com/lightningnetwork/lnd/lnrpc/signrpc" "github.com/lightningnetwork/lnd/lnrpc/verrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" - "github.com/lightningnetwork/lnd/lnrpc/wtclientrpc" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chanfunding" "github.com/lightningnetwork/lnd/monitoring" @@ -102,7 +101,6 @@ func init() { addSubLogger(routing.Subsystem, routing.UseLogger, localchans.UseLogger) addSubLogger(routerrpc.Subsystem, routerrpc.UseLogger) - addSubLogger(wtclientrpc.Subsystem, wtclientrpc.UseLogger) addSubLogger(chanfitness.Subsystem, chanfitness.UseLogger) addSubLogger(verrpc.Subsystem, verrpc.UseLogger) } diff --git a/rpcserver.go b/rpcserver.go index 359d5d183a..02825dd87b 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -594,6 +594,7 @@ func newRPCServer(s *server, macService *macaroons.Service, s.htlcSwitch, activeNetParams.Params, s.chanRouter, routerBackend, s.nodeSigner, s.chanDB, s.sweeper, tower, s.towerClient, cfg.net.ResolveTCPAddr, genInvoiceFeatures, + rpcsLog, ) if err != nil { return nil, err diff --git a/subrpcserver_config.go b/subrpcserver_config.go index 316320289f..5c87f3abd3 100644 --- a/subrpcserver_config.go +++ b/subrpcserver_config.go @@ -5,6 +5,7 @@ import ( "reflect" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/autopilot" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/htlcswitch" @@ -94,7 +95,8 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl, tower *watchtower.Standalone, towerClient wtclient.Client, tcpResolver lncfg.TCPResolver, - genInvoiceFeatures func() *lnwire.FeatureVector) error { + genInvoiceFeatures func() *lnwire.FeatureVector, + rpcLogger btclog.Logger) error { // First, we'll use reflect to obtain a version of the config struct // that allows us to programmatically inspect its fields. @@ -244,6 +246,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl, subCfgValue.FieldByName("Resolver").Set( reflect.ValueOf(tcpResolver), ) + subCfgValue.FieldByName("Log").Set( + reflect.ValueOf(rpcLogger), + ) default: return fmt.Errorf("unknown field: %v, %T", fieldName, From 3afa4178bae166fd321f5d1e6fe2519eeac62cd7 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 14 May 2020 11:48:06 -0700 Subject: [PATCH 544/562] wtclient: test case re-add removed tower --- watchtower/wtclient/client_test.go | 121 +++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 23 deletions(-) diff --git a/watchtower/wtclient/client_test.go b/watchtower/wtclient/client_test.go index ea681d5751..577d33f931 100644 --- a/watchtower/wtclient/client_test.go +++ b/watchtower/wtclient/client_test.go @@ -366,17 +366,18 @@ func (c *mockChannel) getState(i uint64) (*wire.MsgTx, *lnwallet.BreachRetributi } type testHarness struct { - t *testing.T - cfg harnessCfg - signer *wtmock.MockSigner - capacity lnwire.MilliSatoshi - clientDB *wtmock.ClientDB - clientCfg *wtclient.Config - client wtclient.Client - serverDB *wtmock.TowerDB - serverCfg *wtserver.Config - server *wtserver.Server - net *mockNet + t *testing.T + cfg harnessCfg + signer *wtmock.MockSigner + capacity lnwire.MilliSatoshi + clientDB *wtmock.ClientDB + clientCfg *wtclient.Config + client wtclient.Client + serverAddr *lnwire.NetAddress + serverDB *wtmock.TowerDB + serverCfg *wtserver.Config + server *wtserver.Server + net *mockNet mu sync.Mutex channels map[lnwire.ChannelID]*mockChannel @@ -467,18 +468,19 @@ func newHarness(t *testing.T, cfg harnessCfg) *testHarness { } h := &testHarness{ - t: t, - cfg: cfg, - signer: signer, - capacity: cfg.localBalance + cfg.remoteBalance, - clientDB: clientDB, - clientCfg: clientCfg, - client: client, - serverDB: serverDB, - serverCfg: serverCfg, - server: server, - net: mockNet, - channels: make(map[lnwire.ChannelID]*mockChannel), + t: t, + cfg: cfg, + signer: signer, + capacity: cfg.localBalance + cfg.remoteBalance, + clientDB: clientDB, + clientCfg: clientCfg, + client: client, + serverAddr: towerAddr, + serverDB: serverDB, + serverCfg: serverCfg, + server: server, + net: mockNet, + channels: make(map[lnwire.ChannelID]*mockChannel), } h.makeChannel(0, h.cfg.localBalance, h.cfg.remoteBalance) @@ -782,6 +784,25 @@ func (h *testHarness) assertUpdatesForPolicy(hints []blob.BreachHint, } } +// addTower adds a tower found at `addr` to the client. +func (h *testHarness) addTower(addr *lnwire.NetAddress) { + h.t.Helper() + + if err := h.client.AddTower(addr); err != nil { + h.t.Fatalf("unable to add tower: %v", err) + } +} + +// removeTower removes a tower from the client. If `addr` is specified, then the +// only said address is removed from the tower. +func (h *testHarness) removeTower(pubKey *btcec.PublicKey, addr net.Addr) { + h.t.Helper() + + if err := h.client.RemoveTower(pubKey, addr); err != nil { + h.t.Fatalf("unable to remove tower: %v", err) + } +} + const ( localBalance = lnwire.MilliSatoshi(100000000) remoteBalance = lnwire.MilliSatoshi(200000000) @@ -1396,6 +1417,60 @@ var clientTests = []clientTest{ h.waitServerUpdates(hints, 5*time.Second) }, }, + { + // Asserts that the client can continue making backups to a + // tower that's been re-added after it's been removed. + name: "re-add removed tower", + cfg: harnessCfg{ + localBalance: localBalance, + remoteBalance: remoteBalance, + policy: wtpolicy.Policy{ + TxPolicy: wtpolicy.TxPolicy{ + BlobType: blob.TypeAltruistCommit, + SweepFeeRate: wtpolicy.DefaultSweepFeeRate, + }, + MaxUpdates: 5, + }, + }, + fn: func(h *testHarness) { + const ( + chanID = 0 + numUpdates = 4 + ) + + // Create four channel updates and only back up the + // first two. + hints := h.advanceChannelN(chanID, numUpdates) + h.backupStates(chanID, 0, numUpdates/2, nil) + h.waitServerUpdates(hints[:numUpdates/2], 5*time.Second) + + // Fully remove the tower, causing its existing sessions + // to be marked inactive. + h.removeTower(h.serverAddr.IdentityKey, nil) + + // Back up the remaining states. Since the tower has + // been removed, it shouldn't receive any updates. + h.backupStates(chanID, numUpdates/2, numUpdates, nil) + h.waitServerUpdates(nil, time.Second) + + // Re-add the tower. We prevent the tower from acking + // session creation to ensure the inactive sessions are + // not used. + h.server.Stop() + h.serverCfg.NoAckCreateSession = true + h.startServer() + h.addTower(h.serverAddr) + h.waitServerUpdates(nil, time.Second) + + // Finally, allow the tower to ack session creation, + // allowing the state updates to be sent through the new + // session. + h.server.Stop() + h.serverCfg.NoAckCreateSession = false + h.startServer() + h.waitServerUpdates(hints[numUpdates/2:], 5*time.Second) + }, + }, } // TestClient executes the client test suite, asserting the ability to backup From 0c13b29a0e1545cc7161082b1ecdf81ecef624b6 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 14 May 2020 15:28:49 -0700 Subject: [PATCH 545/562] wtmock: prevent race conditions by not using ClientSession pointers These race conditions originate from the mock database storing and returning pointers, rather than returning a copy. Observed on Travis: WARNING: DATA RACE Read at 0x00c0003222b8 by goroutine 149: github.com/lightningnetwork/lnd/watchtower/wtclient.(*sessionQueue).drainBackups() /home/runner/work/lnd/lnd/watchtower/wtclient/session_queue.go:288 +0xed github.com/lightningnetwork/lnd/watchtower/wtclient.(*sessionQueue).sessionManager() /home/runner/work/lnd/lnd/watchtower/wtclient/session_queue.go:281 +0x450 Previous write at 0x00c0003222b8 by goroutine 93: github.com/lightningnetwork/lnd/watchtower/wtclient.getClientSessions() /home/runner/work/lnd/lnd/watchtower/wtclient/client.go:365 +0x24f github.com/lightningnetwork/lnd/watchtower/wtclient.(*TowerClient).handleNewTower() /home/runner/work/lnd/lnd/watchtower/wtclient/client.go:1063 +0x23e github.com/lightningnetwork/lnd/watchtower/wtclient.(*TowerClient).backupDispatcher() /home/runner/work/lnd/lnd/watchtower/wtclient/client.go:784 +0x10b9 --- watchtower/wtmock/client_db.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/watchtower/wtmock/client_db.go b/watchtower/wtmock/client_db.go index 395f16a40b..1f66e24564 100644 --- a/watchtower/wtmock/client_db.go +++ b/watchtower/wtmock/client_db.go @@ -19,7 +19,7 @@ type ClientDB struct { mu sync.Mutex summaries map[lnwire.ChannelID]wtdb.ClientChanSummary - activeSessions map[wtdb.SessionID]*wtdb.ClientSession + activeSessions map[wtdb.SessionID]wtdb.ClientSession towerIndex map[towerPK]wtdb.TowerID towers map[wtdb.TowerID]*wtdb.Tower @@ -31,7 +31,7 @@ type ClientDB struct { func NewClientDB() *ClientDB { return &ClientDB{ summaries: make(map[lnwire.ChannelID]wtdb.ClientChanSummary), - activeSessions: make(map[wtdb.SessionID]*wtdb.ClientSession), + activeSessions: make(map[wtdb.SessionID]wtdb.ClientSession), towerIndex: make(map[towerPK]wtdb.TowerID), towers: make(map[wtdb.TowerID]*wtdb.Tower), indexes: make(map[wtdb.TowerID]uint32), @@ -62,7 +62,7 @@ func (m *ClientDB) CreateTower(lnAddr *lnwire.NetAddress) (*wtdb.Tower, error) { } for id, session := range towerSessions { session.Status = wtdb.CSessionActive - m.activeSessions[id] = session + m.activeSessions[id] = *session } } else { towerID = wtdb.TowerID(atomic.AddUint64(&m.nextTowerID, 1)) @@ -122,7 +122,7 @@ func (m *ClientDB) RemoveTower(pubKey *btcec.PublicKey, addr net.Addr) error { return wtdb.ErrTowerUnackedUpdates } session.Status = wtdb.CSessionInactive - m.activeSessions[id] = session + m.activeSessions[id] = *session } return nil @@ -205,10 +205,11 @@ func (m *ClientDB) listClientSessions( sessions := make(map[wtdb.SessionID]*wtdb.ClientSession) for _, session := range m.activeSessions { + session := session if tower != nil && *tower != session.TowerID { continue } - sessions[session.ID] = session + sessions[session.ID] = &session } return sessions, nil @@ -240,7 +241,7 @@ func (m *ClientDB) CreateClientSession(session *wtdb.ClientSession) error { // permits us to create another session with this tower. delete(m.indexes, session.TowerID) - m.activeSessions[session.ID] = &wtdb.ClientSession{ + m.activeSessions[session.ID] = wtdb.ClientSession{ ID: session.ID, ClientSessionBody: wtdb.ClientSessionBody{ SeqNum: session.SeqNum, @@ -313,6 +314,7 @@ func (m *ClientDB) CommitUpdate(id *wtdb.SessionID, // Save the update and increment the sequence number. session.CommittedUpdates = append(session.CommittedUpdates, *update) session.SeqNum++ + m.activeSessions[*id] = session return session.TowerLastApplied, nil } @@ -360,6 +362,7 @@ func (m *ClientDB) AckUpdate(id *wtdb.SessionID, seqNum, lastApplied uint16) err session.AckedUpdates[seqNum] = update.BackupID session.TowerLastApplied = lastApplied + m.activeSessions[*id] = session return nil } From d914f55e2ca4a8e7c7ed913be31dbc5da9df89e6 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 12 May 2020 13:33:45 +0200 Subject: [PATCH 546/562] lnwallet: return signer error --- lnwallet/channel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 600820f2cb..4463540447 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -3425,7 +3425,7 @@ func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig, []ch // jobs. if jobResp.Err != nil { close(cancelChan) - return sig, htlcSigs, nil, err + return sig, htlcSigs, nil, jobResp.Err } htlcSigs = append(htlcSigs, jobResp.Sig) From 470537ec3a9bb11b44f931db8667d6611bf53553 Mon Sep 17 00:00:00 2001 From: Roei Erez Date: Thu, 30 Apr 2020 12:34:47 +0300 Subject: [PATCH 547/562] chainntnfs: use sync.Once to start notifiers. --- chainntnfs/bitcoindnotify/bitcoind.go | 63 ++++++++++++------------ chainntnfs/btcdnotify/btcd.go | 69 ++++++++++++++------------- chainntnfs/neutrinonotify/neutrino.go | 61 ++++++++++++----------- 3 files changed, 101 insertions(+), 92 deletions(-) diff --git a/chainntnfs/bitcoindnotify/bitcoind.go b/chainntnfs/bitcoindnotify/bitcoind.go index 5956a0fb7c..bb96a7ec5d 100644 --- a/chainntnfs/bitcoindnotify/bitcoind.go +++ b/chainntnfs/bitcoindnotify/bitcoind.go @@ -34,7 +34,7 @@ const ( type BitcoindNotifier struct { epochClientCounter uint64 // To be used atomically. - started int32 // To be used atomically. + start sync.Once stopped int32 // To be used atomically. chainConn *chain.BitcoindClient @@ -96,11 +96,41 @@ func New(chainConn *chain.BitcoindConn, chainParams *chaincfg.Params, // Start connects to the running bitcoind node over websockets, registers for // block notifications, and finally launches all related helper goroutines. func (b *BitcoindNotifier) Start() error { - // Already started? - if atomic.AddInt32(&b.started, 1) != 1 { + var startErr error + b.start.Do(func() { + startErr = b.startNotifier() + }) + return startErr +} + +// Stop shutsdown the BitcoindNotifier. +func (b *BitcoindNotifier) Stop() error { + // Already shutting down? + if atomic.AddInt32(&b.stopped, 1) != 1 { return nil } + // Shutdown the rpc client, this gracefully disconnects from bitcoind, + // and cleans up all related resources. + b.chainConn.Stop() + + close(b.quit) + b.wg.Wait() + + // Notify all pending clients of our shutdown by closing the related + // notification channels. + for _, epochClient := range b.blockEpochClients { + close(epochClient.cancelChan) + epochClient.wg.Wait() + + close(epochClient.epochChan) + } + b.txNotifier.TearDown() + + return nil +} + +func (b *BitcoindNotifier) startNotifier() error { // Connect to bitcoind, and register for notifications on connected, // and disconnected blocks. if err := b.chainConn.Start(); err != nil { @@ -131,33 +161,6 @@ func (b *BitcoindNotifier) Start() error { return nil } -// Stop shutsdown the BitcoindNotifier. -func (b *BitcoindNotifier) Stop() error { - // Already shutting down? - if atomic.AddInt32(&b.stopped, 1) != 1 { - return nil - } - - // Shutdown the rpc client, this gracefully disconnects from bitcoind, - // and cleans up all related resources. - b.chainConn.Stop() - - close(b.quit) - b.wg.Wait() - - // Notify all pending clients of our shutdown by closing the related - // notification channels. - for _, epochClient := range b.blockEpochClients { - close(epochClient.cancelChan) - epochClient.wg.Wait() - - close(epochClient.epochChan) - } - b.txNotifier.TearDown() - - return nil -} - // notificationDispatcher is the primary goroutine which handles client // notification registrations, as well as notification dispatches. func (b *BitcoindNotifier) notificationDispatcher() { diff --git a/chainntnfs/btcdnotify/btcd.go b/chainntnfs/btcdnotify/btcd.go index 7b17920952..1ce8c63059 100644 --- a/chainntnfs/btcdnotify/btcd.go +++ b/chainntnfs/btcdnotify/btcd.go @@ -53,7 +53,7 @@ type txUpdate struct { type BtcdNotifier struct { epochClientCounter uint64 // To be used atomically. - started int32 // To be used atomically. + start sync.Once stopped int32 // To be used atomically. chainConn *rpcclient.Client @@ -134,11 +134,44 @@ func New(config *rpcclient.ConnConfig, chainParams *chaincfg.Params, // Start connects to the running btcd node over websockets, registers for block // notifications, and finally launches all related helper goroutines. func (b *BtcdNotifier) Start() error { - // Already started? - if atomic.AddInt32(&b.started, 1) != 1 { + var startErr error + b.start.Do(func() { + startErr = b.startNotifier() + }) + return startErr +} + +// Stop shutsdown the BtcdNotifier. +func (b *BtcdNotifier) Stop() error { + // Already shutting down? + if atomic.AddInt32(&b.stopped, 1) != 1 { return nil } + // Shutdown the rpc client, this gracefully disconnects from btcd, and + // cleans up all related resources. + b.chainConn.Shutdown() + + close(b.quit) + b.wg.Wait() + + b.chainUpdates.Stop() + b.txUpdates.Stop() + + // Notify all pending clients of our shutdown by closing the related + // notification channels. + for _, epochClient := range b.blockEpochClients { + close(epochClient.cancelChan) + epochClient.wg.Wait() + + close(epochClient.epochChan) + } + b.txNotifier.TearDown() + + return nil +} + +func (b *BtcdNotifier) startNotifier() error { // Start our concurrent queues before starting the chain connection, to // ensure onBlockConnected and onRedeemingTx callbacks won't be // blocked. @@ -182,36 +215,6 @@ func (b *BtcdNotifier) Start() error { return nil } -// Stop shutsdown the BtcdNotifier. -func (b *BtcdNotifier) Stop() error { - // Already shutting down? - if atomic.AddInt32(&b.stopped, 1) != 1 { - return nil - } - - // Shutdown the rpc client, this gracefully disconnects from btcd, and - // cleans up all related resources. - b.chainConn.Shutdown() - - close(b.quit) - b.wg.Wait() - - b.chainUpdates.Stop() - b.txUpdates.Stop() - - // Notify all pending clients of our shutdown by closing the related - // notification channels. - for _, epochClient := range b.blockEpochClients { - close(epochClient.cancelChan) - epochClient.wg.Wait() - - close(epochClient.epochChan) - } - b.txNotifier.TearDown() - - return nil -} - // onBlockConnected implements on OnBlockConnected callback for rpcclient. // Ingesting a block updates the wallet's internal utxo state based on the // outputs created and destroyed within each block. diff --git a/chainntnfs/neutrinonotify/neutrino.go b/chainntnfs/neutrinonotify/neutrino.go index 771c4b8627..be1e8f8066 100644 --- a/chainntnfs/neutrinonotify/neutrino.go +++ b/chainntnfs/neutrinonotify/neutrino.go @@ -39,7 +39,7 @@ const ( type NeutrinoNotifier struct { epochClientCounter uint64 // To be used atomically. - started int32 // To be used atomically. + start sync.Once stopped int32 // To be used atomically. bestBlockMtx sync.RWMutex @@ -111,11 +111,40 @@ func New(node *neutrino.ChainService, spendHintCache chainntnfs.SpendHintCache, // Start contacts the running neutrino light client and kicks off an initial // empty rescan. func (n *NeutrinoNotifier) Start() error { - // Already started? - if atomic.AddInt32(&n.started, 1) != 1 { + var startErr error + n.start.Do(func() { + startErr = n.startNotifier() + }) + return startErr +} + +// Stop shuts down the NeutrinoNotifier. +func (n *NeutrinoNotifier) Stop() error { + // Already shutting down? + if atomic.AddInt32(&n.stopped, 1) != 1 { return nil } + close(n.quit) + n.wg.Wait() + + n.chainUpdates.Stop() + n.txUpdates.Stop() + + // Notify all pending clients of our shutdown by closing the related + // notification channels. + for _, epochClient := range n.blockEpochClients { + close(epochClient.cancelChan) + epochClient.wg.Wait() + + close(epochClient.epochChan) + } + n.txNotifier.TearDown() + + return nil +} + +func (n *NeutrinoNotifier) startNotifier() error { // Start our concurrent queues before starting the rescan, to ensure // onFilteredBlockConnected and onRelavantTx callbacks won't be // blocked. @@ -174,32 +203,6 @@ func (n *NeutrinoNotifier) Start() error { return nil } -// Stop shuts down the NeutrinoNotifier. -func (n *NeutrinoNotifier) Stop() error { - // Already shutting down? - if atomic.AddInt32(&n.stopped, 1) != 1 { - return nil - } - - close(n.quit) - n.wg.Wait() - - n.chainUpdates.Stop() - n.txUpdates.Stop() - - // Notify all pending clients of our shutdown by closing the related - // notification channels. - for _, epochClient := range n.blockEpochClients { - close(epochClient.cancelChan) - epochClient.wg.Wait() - - close(epochClient.epochChan) - } - n.txNotifier.TearDown() - - return nil -} - // filteredBlock represents a new block which has been connected to the main // chain. The slice of transactions will only be populated if the block // includes a transaction that confirmed one of our watched txids, or spends From e52982fd0be8dd143832791e18d68be180fdc456 Mon Sep 17 00:00:00 2001 From: Roei Erez Date: Thu, 30 Apr 2020 12:54:33 +0300 Subject: [PATCH 548/562] Ensure chain notifier is started before accessed. The use case comes from the RPC layer that is ready before the chain notifier which is used in the sub server. --- chainntnfs/bitcoindnotify/bitcoind.go | 10 ++++++++++ chainntnfs/btcdnotify/btcd.go | 10 ++++++++++ chainntnfs/interface.go | 3 +++ chainntnfs/neutrinonotify/neutrino.go | 10 ++++++++++ contractcourt/chain_watcher_test.go | 4 ++++ discovery/gossiper_test.go | 4 ++++ fundingmanager_test.go | 4 ++++ htlcswitch/mock.go | 4 ++++ lnrpc/chainrpc/chainnotifier_server.go | 17 +++++++++++++++++ mock.go | 4 ++++ sweep/test_utils.go | 5 +++++ 11 files changed, 75 insertions(+) diff --git a/chainntnfs/bitcoindnotify/bitcoind.go b/chainntnfs/bitcoindnotify/bitcoind.go index bb96a7ec5d..b39f78a435 100644 --- a/chainntnfs/bitcoindnotify/bitcoind.go +++ b/chainntnfs/bitcoindnotify/bitcoind.go @@ -35,6 +35,7 @@ type BitcoindNotifier struct { epochClientCounter uint64 // To be used atomically. start sync.Once + active int32 // To be used atomically. stopped int32 // To be used atomically. chainConn *chain.BitcoindClient @@ -130,6 +131,11 @@ func (b *BitcoindNotifier) Stop() error { return nil } +// Started returns true if this instance has been started, and false otherwise. +func (b *BitcoindNotifier) Started() bool { + return atomic.LoadInt32(&b.active) != 0 +} + func (b *BitcoindNotifier) startNotifier() error { // Connect to bitcoind, and register for notifications on connected, // and disconnected blocks. @@ -158,6 +164,10 @@ func (b *BitcoindNotifier) startNotifier() error { b.wg.Add(1) go b.notificationDispatcher() + // Set the active flag now that we've completed the full + // startup. + atomic.StoreInt32(&b.active, 1) + return nil } diff --git a/chainntnfs/btcdnotify/btcd.go b/chainntnfs/btcdnotify/btcd.go index 1ce8c63059..d23a30599e 100644 --- a/chainntnfs/btcdnotify/btcd.go +++ b/chainntnfs/btcdnotify/btcd.go @@ -54,6 +54,7 @@ type BtcdNotifier struct { epochClientCounter uint64 // To be used atomically. start sync.Once + active int32 // To be used atomically. stopped int32 // To be used atomically. chainConn *rpcclient.Client @@ -141,6 +142,11 @@ func (b *BtcdNotifier) Start() error { return startErr } +// Started returns true if this instance has been started, and false otherwise. +func (b *BtcdNotifier) Started() bool { + return atomic.LoadInt32(&b.active) != 0 +} + // Stop shutsdown the BtcdNotifier. func (b *BtcdNotifier) Stop() error { // Already shutting down? @@ -212,6 +218,10 @@ func (b *BtcdNotifier) startNotifier() error { b.wg.Add(1) go b.notificationDispatcher() + // Set the active flag now that we've completed the full + // startup. + atomic.StoreInt32(&b.active, 1) + return nil } diff --git a/chainntnfs/interface.go b/chainntnfs/interface.go index ace86e777d..c224181c8b 100644 --- a/chainntnfs/interface.go +++ b/chainntnfs/interface.go @@ -139,6 +139,9 @@ type ChainNotifier interface { // ready, and able to receive notification registrations from clients. Start() error + // Started returns true if this instance has been started, and false otherwise. + Started() bool + // Stops the concrete ChainNotifier. Once stopped, the ChainNotifier // should disallow any future requests from potential clients. // Additionally, all pending client notifications will be canceled diff --git a/chainntnfs/neutrinonotify/neutrino.go b/chainntnfs/neutrinonotify/neutrino.go index be1e8f8066..567fa520ff 100644 --- a/chainntnfs/neutrinonotify/neutrino.go +++ b/chainntnfs/neutrinonotify/neutrino.go @@ -40,6 +40,7 @@ type NeutrinoNotifier struct { epochClientCounter uint64 // To be used atomically. start sync.Once + active int32 // To be used atomically. stopped int32 // To be used atomically. bestBlockMtx sync.RWMutex @@ -144,6 +145,11 @@ func (n *NeutrinoNotifier) Stop() error { return nil } +// Started returns true if this instance has been started, and false otherwise. +func (n *NeutrinoNotifier) Started() bool { + return atomic.LoadInt32(&n.active) != 0 +} + func (n *NeutrinoNotifier) startNotifier() error { // Start our concurrent queues before starting the rescan, to ensure // onFilteredBlockConnected and onRelavantTx callbacks won't be @@ -200,6 +206,10 @@ func (n *NeutrinoNotifier) startNotifier() error { n.wg.Add(1) go n.notificationDispatcher() + // Set the active flag now that we've completed the full + // startup. + atomic.StoreInt32(&n.active, 1) + return nil } diff --git a/contractcourt/chain_watcher_test.go b/contractcourt/chain_watcher_test.go index 6dc47f530f..62c7687177 100644 --- a/contractcourt/chain_watcher_test.go +++ b/contractcourt/chain_watcher_test.go @@ -43,6 +43,10 @@ func (m *mockNotifier) Start() error { return nil } +func (m *mockNotifier) Started() bool { + return true +} + func (m *mockNotifier) Stop() error { return nil } diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index 75d3cef67e..5281d4aa0f 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -453,6 +453,10 @@ func (m *mockNotifier) Start() error { return nil } +func (m *mockNotifier) Started() bool { + return true +} + func (m *mockNotifier) Stop() error { return nil } diff --git a/fundingmanager_test.go b/fundingmanager_test.go index b222bf94b2..0fa5831f14 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -131,6 +131,10 @@ func (m *mockNotifier) Start() error { return nil } +func (m *mockNotifier) Started() bool { + return true +} + func (m *mockNotifier) Stop() error { return nil } diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index e9a2a1efab..0ce5adf61e 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -931,6 +931,10 @@ func (m *mockNotifier) Start() error { return nil } +func (m *mockNotifier) Started() bool { + return true +} + func (m *mockNotifier) Stop() error { return nil } diff --git a/lnrpc/chainrpc/chainnotifier_server.go b/lnrpc/chainrpc/chainnotifier_server.go index 2d662c8e75..261f760515 100644 --- a/lnrpc/chainrpc/chainnotifier_server.go +++ b/lnrpc/chainrpc/chainnotifier_server.go @@ -63,6 +63,11 @@ var ( // has been shut down. ErrChainNotifierServerShuttingDown = errors.New("chain notifier RPC " + "subserver shutting down") + + // ErrChainNotifierServerNotActive indicates that the chain notifier hasn't + // finished the startup process. + ErrChainNotifierServerNotActive = errors.New("chain notifier RPC is" + + "still in the process of starting") ) // fileExists reports whether the named file or directory exists. @@ -196,6 +201,10 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { func (s *Server) RegisterConfirmationsNtfn(in *ConfRequest, confStream ChainNotifier_RegisterConfirmationsNtfnServer) error { + if !s.cfg.ChainNotifier.Started() { + return ErrChainNotifierServerNotActive + } + // We'll start by reconstructing the RPC request into what the // underlying ChainNotifier expects. var txid chainhash.Hash @@ -292,6 +301,10 @@ func (s *Server) RegisterConfirmationsNtfn(in *ConfRequest, func (s *Server) RegisterSpendNtfn(in *SpendRequest, spendStream ChainNotifier_RegisterSpendNtfnServer) error { + if !s.cfg.ChainNotifier.Started() { + return ErrChainNotifierServerNotActive + } + // We'll start by reconstructing the RPC request into what the // underlying ChainNotifier expects. var op *wire.OutPoint @@ -399,6 +412,10 @@ func (s *Server) RegisterSpendNtfn(in *SpendRequest, func (s *Server) RegisterBlockEpochNtfn(in *BlockEpoch, epochStream ChainNotifier_RegisterBlockEpochNtfnServer) error { + if !s.cfg.ChainNotifier.Started() { + return ErrChainNotifierServerNotActive + } + // We'll start by reconstructing the RPC request into what the // underlying ChainNotifier expects. var hash chainhash.Hash diff --git a/mock.go b/mock.go index 0b71a6dc38..34e466d9e6 100644 --- a/mock.go +++ b/mock.go @@ -112,6 +112,10 @@ func (m *mockNotfier) Start() error { return nil } +func (m *mockNotfier) Started() bool { + return true +} + func (m *mockNotfier) Stop() error { return nil } diff --git a/sweep/test_utils.go b/sweep/test_utils.go index 7c28710be5..5b83d730e0 100644 --- a/sweep/test_utils.go +++ b/sweep/test_utils.go @@ -200,6 +200,11 @@ func (m *MockNotifier) Start() error { return nil } +// Started checks if started +func (m *MockNotifier) Started() bool { + return true +} + // Stop the notifier. func (m *MockNotifier) Stop() error { return nil From adbbde6f31b994757735e2a2c895beb5015695ce Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 15 May 2020 17:00:16 -0700 Subject: [PATCH 549/562] build: update to latest btcd and btcwallet versions This update introduces backwards compatibility for btcd nodes running versions prior to v0.20.1-beta. --- go.mod | 8 ++++---- go.sum | 9 +++++++-- lnwallet/btcwallet/btcwallet.go | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index e5f42da921..0cbd31af9a 100644 --- a/go.mod +++ b/go.mod @@ -5,15 +5,15 @@ require ( github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e // indirect github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82 github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2 - github.com/btcsuite/btcd v0.20.1-beta + github.com/btcsuite/btcd v0.20.1-beta.0.20200515232429-9f0179fd2c46 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcutil v1.0.2 github.com/btcsuite/btcutil/psbt v1.0.2 - github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb + github.com/btcsuite/btcwallet v0.11.1-0.20200515224913-e0e62245ecbe github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 github.com/btcsuite/btcwallet/walletdb v1.3.1 - github.com/btcsuite/btcwallet/wtxmgr v1.0.0 + github.com/btcsuite/btcwallet/wtxmgr v1.1.1-0.20200515224913-e0e62245ecbe github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 github.com/davecgh/go-spew v1.1.1 github.com/go-errors/errors v1.0.1 @@ -48,7 +48,7 @@ require ( github.com/rogpeppe/fastuuid v1.2.0 // indirect github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 github.com/urfave/cli v1.18.0 - golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d + golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 diff --git a/go.sum b/go.sum index 85a5e1559a..ec887b754e 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,9 @@ github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcug github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.20.1-beta.0.20200513120220-b470eee47728/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.20.1-beta.0.20200515232429-9f0179fd2c46 h1:QyTpiR5nQe94vza2qkvf7Ns8XX2Rjh/vdIhO3RzGj4o= +github.com/btcsuite/btcd v0.20.1-beta.0.20200515232429-9f0179fd2c46/go.mod h1:Yktc19YNjh/Iz2//CX0vfRTS4IJKM/RKO5YZ9Fn+Pgo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= @@ -32,8 +35,8 @@ github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2ut github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/btcutil/psbt v1.0.2 h1:gCVY3KxdoEVU7Q6TjusPO+GANIwVgr9yTLqM+a6CZr8= github.com/btcsuite/btcutil/psbt v1.0.2/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= -github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb h1:kkq2SSCy+OrC7GVZLIqutoHVR2yW4SJQdX70jtmuLDI= -github.com/btcsuite/btcwallet v0.11.1-0.20200403222202-ada7ca077ebb/go.mod h1:9fJNm1aXi4q9P5Nk23mmqppCy1Le3f2/JMWj9UXKkCc= +github.com/btcsuite/btcwallet v0.11.1-0.20200515224913-e0e62245ecbe h1:0m9uXDcnUc3Fv72635O/MfLbhbW+0hfSVgRiWezpkHU= +github.com/btcsuite/btcwallet v0.11.1-0.20200515224913-e0e62245ecbe/go.mod h1:9+AH3V5mcTtNXTKe+fe63fDLKGOwQbZqmvOVUef+JFE= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= @@ -47,6 +50,8 @@ github.com/btcsuite/btcwallet/walletdb v1.3.1 h1:lW1Ac3F1jJY4K11P+YQtRNcP5jFk27A github.com/btcsuite/btcwallet/walletdb v1.3.1/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= github.com/btcsuite/btcwallet/wtxmgr v1.0.0 h1:aIHgViEmZmZfe0tQQqF1xyd2qBqFWxX5vZXkkbjtbeA= github.com/btcsuite/btcwallet/wtxmgr v1.0.0/go.mod h1:vc4gBprll6BP0UJ+AIGDaySoc7MdAmZf8kelfNb8CFY= +github.com/btcsuite/btcwallet/wtxmgr v1.1.1-0.20200515224913-e0e62245ecbe h1:yQbJVYfsKbdqDQNLxd4hhiLSiMkIygefW5mSHMsdKpc= +github.com/btcsuite/btcwallet/wtxmgr v1.1.1-0.20200515224913-e0e62245ecbe/go.mod h1:OwC0W0HhUszbWdvJvH6xvgabKSJ0lXl11YbmmqF9YXQ= github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 h1:kij1x2aL7VE6gtx8KMIt8PGPgI5GV9LgtHFG5KaEMPY= github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:QcFA8DZHtuIAdYKCq/BzELOaznRsCvwf4zTPmaYwaig= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= diff --git a/lnwallet/btcwallet/btcwallet.go b/lnwallet/btcwallet/btcwallet.go index 3e51605a50..beec057f32 100644 --- a/lnwallet/btcwallet/btcwallet.go +++ b/lnwallet/btcwallet/btcwallet.go @@ -300,7 +300,7 @@ func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut, if len(outputs) < 1 { return nil, lnwallet.ErrNoOutputs } - return b.wallet.SendOutputs(outputs, defaultAccount, 1, feeSatPerKB) + return b.wallet.SendOutputs(outputs, defaultAccount, 1, feeSatPerKB, "") } // CreateSimpleTx creates a Bitcoin transaction paying to the specified @@ -430,7 +430,7 @@ func (b *BtcWallet) ListUnspentWitness(minConfs, maxConfs int32) ( // (currently ErrDoubleSpend). If the transaction is already published to the // network (either in the mempool or chain) no error will be returned. func (b *BtcWallet) PublishTransaction(tx *wire.MsgTx) error { - if err := b.wallet.PublishTransaction(tx); err != nil { + if err := b.wallet.PublishTransaction(tx, ""); err != nil { // If we failed to publish the transaction, check whether we // got an error of known type. From e8833042799d71dba209fe305ce3ae105c154cfe Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 18 May 2020 19:28:34 -0700 Subject: [PATCH 550/562] build: bump version to v0.10.1-beta.rc1 --- build/version.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/version.go b/build/version.go index 33646021c9..9c52ce474c 100644 --- a/build/version.go +++ b/build/version.go @@ -44,11 +44,11 @@ const ( AppMinor uint = 10 // AppPatch defines the application patch for this binary. - AppPatch uint = 0 + AppPatch uint = 1 // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta" + AppPreRelease = "beta.rc1" ) func init() { From c45b2387c2653a9fcabf73b2da7bf475f3b0bf3c Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Wed, 20 May 2020 11:42:12 -0700 Subject: [PATCH 551/562] btcwallet: add transaction outputs bounds check to FetchInputInfo This prevents a panic when providing an incompatible output index for the transaction. --- lnwallet/btcwallet/signer.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lnwallet/btcwallet/signer.go b/lnwallet/btcwallet/signer.go index a79a5fd927..6332f85f89 100644 --- a/lnwallet/btcwallet/signer.go +++ b/lnwallet/btcwallet/signer.go @@ -37,6 +37,11 @@ func (b *BtcWallet) FetchInputInfo(prevOut *wire.OutPoint) (*lnwallet.Utxo, erro // we actually have control of this output. We do this because the check // above only guarantees that the transaction is somehow relevant to us, // like in the event of us being the sender of the transaction. + numOutputs := uint32(len(txDetail.TxRecord.MsgTx.TxOut)) + if prevOut.Index >= numOutputs { + return nil, fmt.Errorf("invalid output index %v for "+ + "transaction with %v outputs", prevOut.Index, numOutputs) + } pkScript := txDetail.TxRecord.MsgTx.TxOut[prevOut.Index].PkScript if _, err := b.fetchOutputAddr(pkScript); err != nil { return nil, err From ae6e84ddfd3c4d2366e151a04aca3f78b4078ed5 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 21 May 2020 17:26:15 -0700 Subject: [PATCH 552/562] build: bump version to v0.10.1-beta.rc2 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index 9c52ce474c..c34752d9eb 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc1" + AppPreRelease = "beta.rc2" ) func init() { From 2edda573a584037a586a9325a3042bc17c96bf15 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 19 May 2020 20:31:26 -0700 Subject: [PATCH 553/562] channeldb/invoices: ignore error when no settles exist This fixes a bug that would cause no backlog to be delivered at all. --- channeldb/invoice_test.go | 7 +++++++ channeldb/invoices.go | 15 +++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index 2680789445..a35c9fae43 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -11,6 +11,7 @@ import ( "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" + "github.com/stretchr/testify/assert" ) var ( @@ -305,6 +306,9 @@ func TestInvoiceAddTimeSeries(t *testing.T) { t.Fatalf("unable to make test db: %v", err) } + _, err = db.InvoicesAddedSince(0) + assert.Nil(t, err) + // We'll start off by creating 20 random invoices, and inserting them // into the database. const numInvoices = 20 @@ -372,6 +376,9 @@ func TestInvoiceAddTimeSeries(t *testing.T) { } } + _, err = db.InvoicesSettledSince(0) + assert.Nil(t, err) + var settledInvoices []Invoice var settleIndex uint64 = 1 // We'll now only settle the latter half of each of those invoices. diff --git a/channeldb/invoices.go b/channeldb/invoices.go index f1954bf3b4..46b1b7c5c1 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -488,12 +488,12 @@ func (d *DB) InvoicesAddedSince(sinceAddIndex uint64) ([]Invoice, error) { err := kvdb.View(d, func(tx kvdb.ReadTx) error { invoices := tx.ReadBucket(invoiceBucket) if invoices == nil { - return ErrNoInvoicesCreated + return nil } addIndex := invoices.NestedReadBucket(addIndexBucket) if addIndex == nil { - return ErrNoInvoicesCreated + return nil } // We'll now run through each entry in the add index starting @@ -520,12 +520,7 @@ func (d *DB) InvoicesAddedSince(sinceAddIndex uint64) ([]Invoice, error) { return nil }) - switch { - // If no invoices have been created, then we'll return the empty set of - // invoices. - case err == ErrNoInvoicesCreated: - - case err != nil: + if err != nil { return nil, err } @@ -886,12 +881,12 @@ func (d *DB) InvoicesSettledSince(sinceSettleIndex uint64) ([]Invoice, error) { err := kvdb.View(d, func(tx kvdb.ReadTx) error { invoices := tx.ReadBucket(invoiceBucket) if invoices == nil { - return ErrNoInvoicesCreated + return nil } settleIndex := invoices.NestedReadBucket(settleIndexBucket) if settleIndex == nil { - return ErrNoInvoicesCreated + return nil } // We'll now run through each entry in the add index starting From 544e606e2cbf69b305c53d805f616f0040fb59a9 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 19 May 2020 20:31:38 -0700 Subject: [PATCH 554/562] invoices: return error from SubscribeNotifications on shutdown --- invoices/invoiceregistry.go | 7 +++++-- invoices/invoiceregistry_test.go | 15 ++++++++++----- rpcserver.go | 5 ++++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 662a8a82ec..b0e06a16b6 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -1182,7 +1182,9 @@ func (i *invoiceSubscriptionKit) notify(event *invoiceEvent) error { // added. The invoiceIndex parameter is a streaming "checkpoint". We'll start // by first sending out all new events with an invoice index _greater_ than // this value. Afterwards, we'll send out real-time notifications. -func (i *InvoiceRegistry) SubscribeNotifications(addIndex, settleIndex uint64) *InvoiceSubscription { +func (i *InvoiceRegistry) SubscribeNotifications( + addIndex, settleIndex uint64) (*InvoiceSubscription, error) { + client := &InvoiceSubscription{ NewInvoices: make(chan *channeldb.Invoice), SettledInvoices: make(chan *channeldb.Invoice), @@ -1254,9 +1256,10 @@ func (i *InvoiceRegistry) SubscribeNotifications(addIndex, settleIndex uint64) * select { case i.newSubscriptions <- client: case <-i.quit: + return nil, ErrShuttingDown } - return client + return client, nil } // SubscribeSingleInvoice returns an SingleInvoiceSubscription which allows the diff --git a/invoices/invoiceregistry_test.go b/invoices/invoiceregistry_test.go index 319c30cf05..aeb5212508 100644 --- a/invoices/invoiceregistry_test.go +++ b/invoices/invoiceregistry_test.go @@ -9,6 +9,7 @@ import ( "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" + "github.com/stretchr/testify/assert" ) // TestSettleInvoice tests settling of an invoice and related notifications. @@ -16,7 +17,8 @@ func TestSettleInvoice(t *testing.T) { ctx := newTestContext(t) defer ctx.cleanup() - allSubscriptions := ctx.registry.SubscribeNotifications(0, 0) + allSubscriptions, err := ctx.registry.SubscribeNotifications(0, 0) + assert.Nil(t, err) defer allSubscriptions.Cancel() // Subscribe to the not yet existing invoice. @@ -221,11 +223,12 @@ func TestCancelInvoice(t *testing.T) { ctx := newTestContext(t) defer ctx.cleanup() - allSubscriptions := ctx.registry.SubscribeNotifications(0, 0) + allSubscriptions, err := ctx.registry.SubscribeNotifications(0, 0) + assert.Nil(t, err) defer allSubscriptions.Cancel() // Try to cancel the not yet existing invoice. This should fail. - err := ctx.registry.CancelInvoice(testInvoicePaymentHash) + err = ctx.registry.CancelInvoice(testInvoicePaymentHash) if err != channeldb.ErrInvoiceNotFound { t.Fatalf("expected ErrInvoiceNotFound, but got %v", err) } @@ -352,7 +355,8 @@ func TestSettleHoldInvoice(t *testing.T) { } defer registry.Stop() - allSubscriptions := registry.SubscribeNotifications(0, 0) + allSubscriptions, err := registry.SubscribeNotifications(0, 0) + assert.Nil(t, err) defer allSubscriptions.Cancel() // Subscribe to the not yet existing invoice. @@ -651,7 +655,8 @@ func testKeySend(t *testing.T, keySendEnabled bool) { ctx.registry.cfg.AcceptKeySend = keySendEnabled - allSubscriptions := ctx.registry.SubscribeNotifications(0, 0) + allSubscriptions, err := ctx.registry.SubscribeNotifications(0, 0) + assert.Nil(t, err) defer allSubscriptions.Cancel() hodlChan := make(chan interface{}, 1) diff --git a/rpcserver.go b/rpcserver.go index 02825dd87b..dd16b414ab 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -4461,9 +4461,12 @@ func (r *rpcServer) ListInvoices(ctx context.Context, func (r *rpcServer) SubscribeInvoices(req *lnrpc.InvoiceSubscription, updateStream lnrpc.Lightning_SubscribeInvoicesServer) error { - invoiceClient := r.server.invoices.SubscribeNotifications( + invoiceClient, err := r.server.invoices.SubscribeNotifications( req.AddIndex, req.SettleIndex, ) + if err != nil { + return err + } defer invoiceClient.Cancel() for { From 5cb7ca6bf46931164e690f842542e142b809877d Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 19 May 2020 20:31:52 -0700 Subject: [PATCH 555/562] invoices/invoiceregistry: properly synchronize backlog This commit moves the db calls for retrieving add and settle backlogs outide of the main event loop. All other db operations are performed outside of the event loop and synchronized via the invoice registry's mutex, which also synchronizes the order in which events submitted to be processed. This resolves various concurrency issues where notifications can be missed of inconsistent reads against the databse. This is especially important in this case because we are actually making two separate database calls. --- invoices/invoiceregistry.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index b0e06a16b6..520e758231 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -234,15 +234,6 @@ func (i *InvoiceRegistry) invoiceEventLoop() { // We'll query for any backlog notifications, then add it to the // set of clients. case newClient := <-i.newSubscriptions: - // Before we add the client to our set of active - // clients, we'll first attempt to deliver any backlog - // invoice events. - err := i.deliverBacklogEvents(newClient) - if err != nil { - log.Errorf("unable to deliver backlog invoice "+ - "notifications: %v", err) - } - log.Infof("New invoice subscription "+ "client: id=%v", newClient.id) @@ -410,9 +401,6 @@ func (i *InvoiceRegistry) dispatchToClients(event *invoiceEvent) { // deliverBacklogEvents will attempts to query the invoice database for any // notifications that the client has missed since it reconnected last. func (i *InvoiceRegistry) deliverBacklogEvents(client *InvoiceSubscription) error { - // First, we'll query the database to see if based on the provided - // addIndex and settledIndex we need to deliver any backlog - // notifications. addEvents, err := i.cdb.InvoicesAddedSince(client.addIndex) if err != nil { return err @@ -1253,6 +1241,16 @@ func (i *InvoiceRegistry) SubscribeNotifications( } }() + i.Lock() + defer i.Unlock() + + // Query the database to see if based on the provided addIndex and + // settledIndex we need to deliver any backlog notifications. + err := i.deliverBacklogEvents(client) + if err != nil { + return nil, err + } + select { case i.newSubscriptions <- client: case <-i.quit: From 6cd4cc47c1c46fbd5379915af06ff1a1688bd4b9 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 28 May 2020 19:28:34 +0200 Subject: [PATCH 556/562] rpcserver+routerrpc: remove payment limit --- config.go | 1 - go.mod | 1 + lnrpc/routerrpc/router_backend.go | 14 --------- lnrpc/routerrpc/router_backend_test.go | 5 ++- .../itest/lnd_multi-hop-error-propagation.go | 3 +- rpcserver.go | 31 +------------------ 6 files changed, 6 insertions(+), 49 deletions(-) diff --git a/config.go b/config.go index df3cf6ea98..76e0d6af5b 100644 --- a/config.go +++ b/config.go @@ -817,7 +817,6 @@ func loadConfig() (*config, error) { // primary chain. registeredChains.RegisterPrimaryChain(litecoinChain) MaxFundingAmount = maxLtcFundingAmount - MaxPaymentMSat = maxLtcPaymentMSat case cfg.Bitcoin.Active: // Multiple networks can't be selected simultaneously. Count diff --git a/go.mod b/go.mod index 0cbd31af9a..e2da683686 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,7 @@ require ( github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 github.com/prometheus/client_golang v0.9.3 github.com/rogpeppe/fastuuid v1.2.0 // indirect + github.com/stretchr/testify v1.3.0 github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 github.com/urfave/cli v1.18.0 golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 4292ee6549..aec39942c6 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -27,9 +27,6 @@ import ( // RouterBackend contains the backend implementation of the router rpc sub // server calls. type RouterBackend struct { - // MaxPaymentMSat is the largest payment permitted by the backend. - MaxPaymentMSat lnwire.MilliSatoshi - // SelfNode is the vertex of the node sending the payment. SelfNode route.Vertex @@ -143,10 +140,6 @@ func (r *RouterBackend) QueryRoutes(ctx context.Context, if err != nil { return nil, err } - if amt > r.MaxPaymentMSat { - return nil, fmt.Errorf("payment of %v is too large, max payment "+ - "allowed is %v", amt, r.MaxPaymentMSat.ToSatoshis()) - } // Unmarshall restrictions from request. feeLimit := lnrpc.CalculateFeeLimit(in.FeeLimit, amt) @@ -489,13 +482,6 @@ func (r *RouterBackend) UnmarshallRoute(rpcroute *lnrpc.Route) ( return nil, err } - if routeHop.AmtToForward > r.MaxPaymentMSat { - return nil, fmt.Errorf("payment of %v is too large, "+ - "max payment allowed is %v", - routeHop.AmtToForward, - r.MaxPaymentMSat.ToSatoshis()) - } - hops[i] = routeHop prevNodePubKey = routeHop.PubKeyBytes diff --git a/lnrpc/routerrpc/router_backend_test.go b/lnrpc/routerrpc/router_backend_test.go index 3e2bd91669..bd9fee3751 100644 --- a/lnrpc/routerrpc/router_backend_test.go +++ b/lnrpc/routerrpc/router_backend_test.go @@ -186,9 +186,8 @@ func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool) { } backend := &RouterBackend{ - MaxPaymentMSat: lnwire.NewMSatFromSatoshis(1000000), - FindRoute: findRoute, - SelfNode: route.Vertex{1, 2, 3}, + FindRoute: findRoute, + SelfNode: route.Vertex{1, 2, 3}, FetchChannelCapacity: func(chanID uint64) ( btcutil.Amount, error) { diff --git a/lntest/itest/lnd_multi-hop-error-propagation.go b/lntest/itest/lnd_multi-hop-error-propagation.go index d1689a99cb..9280aafc65 100644 --- a/lntest/itest/lnd_multi-hop-error-propagation.go +++ b/lntest/itest/lnd_multi-hop-error-propagation.go @@ -5,6 +5,7 @@ package itest import ( "context" "encoding/hex" + "math" "strings" "time" @@ -281,7 +282,7 @@ out: // We'll send in chunks of the max payment amount. If we're // about to send too much, then we'll only send the amount // remaining. - toSend := int64(lnd.MaxPaymentMSat.ToSatoshis()) + toSend := int64(math.MaxUint32) if toSend+amtSent > amtToSend { toSend = amtToSend - amtSent } diff --git a/rpcserver.go b/rpcserver.go index dd16b414ab..c5bcf33e99 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -68,23 +68,7 @@ import ( "gopkg.in/macaroon-bakery.v2/bakery" ) -const ( - // maxBtcPaymentMSat is the maximum allowed Bitcoin payment currently - // permitted as defined in BOLT-0002. - maxBtcPaymentMSat = lnwire.MilliSatoshi(math.MaxUint32) - - // maxLtcPaymentMSat is the maximum allowed Litecoin payment currently - // permitted. - maxLtcPaymentMSat = lnwire.MilliSatoshi(math.MaxUint32) * - btcToLtcConversionRate -) - var ( - // MaxPaymentMSat is the maximum allowed payment currently permitted as - // defined in BOLT-002. This value depends on which chain is active. - // It is set to the value under the Bitcoin chain as default. - MaxPaymentMSat = maxBtcPaymentMSat - // defaultAcceptorTimeout is the time after which an RPCAcceptor will time // out and return false if it hasn't yet received a response. // @@ -542,8 +526,7 @@ func newRPCServer(s *server, macService *macaroons.Service, } graph := s.chanDB.ChannelGraph() routerBackend := &routerrpc.RouterBackend{ - MaxPaymentMSat: MaxPaymentMSat, - SelfNode: selfNode.PubKeyBytes, + SelfNode: selfNode.PubKeyBytes, FetchChannelCapacity: func(chanID uint64) (btcutil.Amount, error) { @@ -3918,18 +3901,6 @@ func (r *rpcServer) extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPayme return payIntent, err } - // Currently, within the bootstrap phase of the network, we limit the - // largest payment size allotted to (2^32) - 1 mSAT or 4.29 million - // satoshis. - if payIntent.msat > MaxPaymentMSat { - // In this case, we'll send an error to the caller, but - // continue our loop for the next payment. - return payIntent, fmt.Errorf("payment of %v is too large, "+ - "max payment allowed is %v", payIntent.msat, - MaxPaymentMSat) - - } - return payIntent, nil } From 745bf0a6c91fb374d8dc695eb6176ff14feac0bc Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 27 May 2020 22:42:22 -0700 Subject: [PATCH 557/562] channeldb/db: lower-case ErrDryRunMigrationOk message --- channeldb/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channeldb/db.go b/channeldb/db.go index 43ad6cde41..ffbec7539a 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -28,7 +28,7 @@ const ( var ( // ErrDryRunMigrationOK signals that a migration executed successful, // but we intentionally did not commit the result. - ErrDryRunMigrationOK = errors.New("Dry run migration successful") + ErrDryRunMigrationOK = errors.New("dry run migration successful") ) // migration is a function which takes a prior outdated version of the database From 564217213cabb16fb36da2c90c8693d43e42bd20 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 27 May 2020 22:42:46 -0700 Subject: [PATCH 558/562] lnd: use Infof to format errors on channeldb open --- lnd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnd.go b/lnd.go index f8dd44e014..a577c8d48a 100644 --- a/lnd.go +++ b/lnd.go @@ -239,7 +239,7 @@ func Main(lisCfg ListenerCfg) error { ) switch { case err == channeldb.ErrDryRunMigrationOK: - ltndLog.Info("%v, exiting", err) + ltndLog.Infof("%v, exiting", err) return nil case err != nil: From bca3bb4d33b8e49a555b8149a39e92ac8a1379c6 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 27 May 2020 12:14:52 +0200 Subject: [PATCH 559/562] routing: don't treat bad features as an unexpected error Previous behavior led to the payment loop being abandoned immediately, resulting in a payment stuck in state in_flight. --- routing/pathfind.go | 6 ++++-- routing/pathfind_test.go | 8 ++------ routing/payment_session.go | 18 +++++++++++++++++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/routing/pathfind.go b/routing/pathfind.go index 70efb1c2dd..6d5e9abd56 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -420,13 +420,15 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, // required features. err := feature.ValidateRequired(features) if err != nil { - return nil, err + log.Warnf("Pathfinding destination node features: %v", err) + return nil, errUnknownRequiredFeature } // Ensure that all transitive dependencies are set. err = feature.ValidateDeps(features) if err != nil { - return nil, err + log.Warnf("Pathfinding destination node features: %v", err) + return nil, errMissingDependentFeature } // Now that we know the feature vector is well formed, we'll proceed in diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 043ca2cd58..6be9b272bd 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -23,7 +23,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/feature" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing/route" @@ -1597,9 +1596,7 @@ func TestMissingFeatureDep(t *testing.T) { joost := ctx.keyFromAlias("joost") _, err := ctx.findPath(conner, 100) - if err != feature.NewErrMissingFeatureDep( - lnwire.TLVOnionPayloadOptional, - ) { + if err != errMissingDependentFeature { t.Fatalf("path shouldn't have been found: %v", err) } @@ -1674,9 +1671,8 @@ func TestUnknownRequiredFeatures(t *testing.T) { // Conner's node in the graph has an unknown required feature (100). // Pathfinding should fail since we check the destination's features for // unknown required features before beginning pathfinding. - expErr := feature.NewErrUnknownRequired([]lnwire.FeatureBit{100}) _, err := ctx.findPath(conner, 100) - if !reflect.DeepEqual(err, expErr) { + if !reflect.DeepEqual(err, errUnknownRequiredFeature) { t.Fatalf("path shouldn't have been found: %v", err) } diff --git a/routing/payment_session.go b/routing/payment_session.go index b4aac5aad1..2d7ef8bf89 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -37,6 +37,14 @@ const ( // errEmptyPaySession is returned when the empty payment session is // queried for a route. errEmptyPaySession + + // errUnknownRequiredFeature is returned when the destination node + // requires an unknown feature. + errUnknownRequiredFeature + + // errMissingDependentFeature is returned when the destination node + // misses a feature that a feature that we require depends on. + errMissingDependentFeature ) var ( @@ -64,6 +72,12 @@ func (e noRouteError) Error() string { case errInsufficientBalance: return "insufficient local balance" + case errUnknownRequiredFeature: + return "unknown required feature" + + case errMissingDependentFeature: + return "missing dependent feature" + default: return "unknown no-route error" } @@ -76,7 +90,9 @@ func (e noRouteError) FailureReason() channeldb.FailureReason { errNoTlvPayload, errNoPaymentAddr, errNoPathFound, - errEmptyPaySession: + errEmptyPaySession, + errUnknownRequiredFeature, + errMissingDependentFeature: return channeldb.FailureReasonNoRoute From 4f2221d56c8212ddc4f48a4e6a6ee57255e61195 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 28 May 2020 15:56:19 -0700 Subject: [PATCH 560/562] build: bump version to v0.10.1-beta.rc3 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index c34752d9eb..1cb71ac4f2 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc2" + AppPreRelease = "beta.rc3" ) func init() { From 52bb3f33707b81972c67937c7a89addcdf00991c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 3 Jun 2020 11:18:49 -0700 Subject: [PATCH 561/562] build: bump version to 0.10.1-beta --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index 1cb71ac4f2..c4f5eedb1b 100644 --- a/build/version.go +++ b/build/version.go @@ -48,7 +48,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - AppPreRelease = "beta.rc3" + AppPreRelease = "beta" ) func init() { From f517f4a94b872fe096137a0814dc158a742b2861 Mon Sep 17 00:00:00 2001 From: losh11 Date: Thu, 18 Jun 2020 18:31:30 +0100 Subject: [PATCH 562/562] litecoin: 0.10.1 changes --- chainregistry.go | 28 ++--- config.go | 1 - discovery/utils.go | 154 ------------------------ go.mod | 28 +---- go.sum | 21 ++++ lnd.go | 3 +- lnrpc/routerrpc/config_active.go | 71 ----------- lnrpc/routerrpc/config_default.go | 28 ----- lnwallet/btcwallet/blockchain.go | 4 +- lnwallet/btcwallet/btcwallet.go | 8 +- lnwallet/btcwallet/btcwallet_rpctest.go | 4 +- lnwallet/btcwallet/config.go | 2 +- lnwallet/btcwallet/driver.go | 4 +- lnwallet/btcwallet/signer.go | 10 +- walletunlocker/service.go | 12 +- 15 files changed, 65 insertions(+), 313 deletions(-) delete mode 100644 discovery/utils.go delete mode 100644 lnrpc/routerrpc/config_active.go delete mode 100644 lnrpc/routerrpc/config_default.go diff --git a/chainregistry.go b/chainregistry.go index 799d5cd7cb..cc2f94cb7c 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -12,17 +12,9 @@ import ( "sync" "time" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/rpcclient" - "github.com/ltcsuite/ltcutil" - "github.com/ltcsuite/ltcwallet/chain" - "github.com/ltcsuite/ltcwallet/wallet" - "github.com/ltcsuite/ltcwallet/walletdb" - "github.com/ltcsuite/neutrino" - "github.com/ltcsuite/neutrino/headerfs" "github.com/ltcsuite/lnd/chainntnfs" "github.com/ltcsuite/lnd/chainntnfs/bitcoindnotify" - "github.com/ltcsuite/lnd/chainntnfs/btcdnotify" + ltcdnotify "github.com/ltcsuite/lnd/chainntnfs/btcdnotify" "github.com/ltcsuite/lnd/chainntnfs/neutrinonotify" "github.com/ltcsuite/lnd/channeldb" "github.com/ltcsuite/lnd/htlcswitch" @@ -33,6 +25,14 @@ import ( "github.com/ltcsuite/lnd/lnwallet/chainfee" "github.com/ltcsuite/lnd/lnwire" "github.com/ltcsuite/lnd/routing/chainview" + "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcsuite/ltcd/rpcclient" + "github.com/ltcsuite/ltcutil" + "github.com/ltcsuite/ltcwallet/chain" + "github.com/ltcsuite/ltcwallet/wallet" + "github.com/ltcsuite/ltcwallet/walletdb" + "github.com/ltcsuite/neutrino" + "github.com/ltcsuite/neutrino/headerfs" ) const ( @@ -205,7 +205,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, "unknown", registeredChains.PrimaryChain()) } - walletConfig := <cwallet.Config{ + walletConfig := &btcwallet.Config{ PrivatePass: privateWalletPw, PublicPass: publicWalletPw, Birthday: birthday, @@ -280,9 +280,9 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, bitcoindHost = bitcoindMode.RPCHost } else { // The RPC ports specified in chainparams.go assume - // ltcd, which picks a different port so that ltcwallet + // ltcd, which picks a different port so that btcwallet // can use the same RPC port as bitcoind. We convert - // this back to the ltcwallet/bitcoind port. + // this back to the btcwallet/bitcoind port. rpcPort, err := strconv.Atoi(activeNetParams.rpcPort) if err != nil { return nil, err @@ -491,7 +491,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, homeChainConfig.Node) } - wc, err := ltcwallet.New(*walletConfig) + wc, err := btcwallet.New(*walletConfig) if err != nil { fmt.Printf("unable to create wallet controller: %v\n", err) return nil, err @@ -721,7 +721,7 @@ func (c *chainRegistry) NumActiveChains() uint32 { func initNeutrinoBackend(chainDir string) (*neutrino.ChainService, func(), error) { // First we'll open the database file for neutrino, creating the // database if needed. We append the normalized network name here to - // match the behavior of ltcwallet. + // match the behavior of btcwallet. dbPath := filepath.Join( chainDir, normalizeNetwork(activeNetParams.Name), diff --git a/config.go b/config.go index 6fa01c473a..94caaa9770 100644 --- a/config.go +++ b/config.go @@ -817,7 +817,6 @@ func loadConfig() (*config, error) { // primary chain. registeredChains.RegisterPrimaryChain(litecoinChain) MaxFundingAmount = maxLtcFundingAmount - MaxPaymentMSat = maxLtcPaymentMSat } // Ensure that the user didn't attempt to specify negative values for diff --git a/discovery/utils.go b/discovery/utils.go deleted file mode 100644 index 2a253ebb74..0000000000 --- a/discovery/utils.go +++ /dev/null @@ -1,154 +0,0 @@ -package discovery - -import ( - "github.com/ltcsuite/ltcd/btcec" - "github.com/go-errors/errors" - "github.com/ltcsuite/lnd/channeldb" - "github.com/ltcsuite/lnd/lnwallet" - "github.com/ltcsuite/lnd/lnwire" -) - -// CreateChanAnnouncement is a helper function which creates all channel -// announcements given the necessary channel related database items. This -// function is used to transform out database structs into the corresponding wire -// structs for announcing new channels to other peers, or simply syncing up a -// peer's initial routing table upon connect. -func CreateChanAnnouncement(chanProof *channeldb.ChannelAuthProof, - chanInfo *channeldb.ChannelEdgeInfo, - e1, e2 *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, - *lnwire.ChannelUpdate, *lnwire.ChannelUpdate, error) { - - // First, using the parameters of the channel, along with the channel - // authentication chanProof, we'll create re-create the original - // authenticated channel announcement. - chanID := lnwire.NewShortChanIDFromInt(chanInfo.ChannelID) - chanAnn := &lnwire.ChannelAnnouncement{ - ShortChannelID: chanID, - NodeID1: chanInfo.NodeKey1Bytes, - NodeID2: chanInfo.NodeKey2Bytes, - ChainHash: chanInfo.ChainHash, - BitcoinKey1: chanInfo.BitcoinKey1Bytes, - BitcoinKey2: chanInfo.BitcoinKey2Bytes, - Features: lnwire.NewRawFeatureVector(), - ExtraOpaqueData: chanInfo.ExtraOpaqueData, - } - - var err error - chanAnn.BitcoinSig1, err = lnwire.NewSigFromRawSignature( - chanProof.BitcoinSig1Bytes, - ) - if err != nil { - return nil, nil, nil, err - } - chanAnn.BitcoinSig2, err = lnwire.NewSigFromRawSignature( - chanProof.BitcoinSig2Bytes, - ) - if err != nil { - return nil, nil, nil, err - } - chanAnn.NodeSig1, err = lnwire.NewSigFromRawSignature( - chanProof.NodeSig1Bytes, - ) - if err != nil { - return nil, nil, nil, err - } - chanAnn.NodeSig2, err = lnwire.NewSigFromRawSignature( - chanProof.NodeSig2Bytes, - ) - if err != nil { - return nil, nil, nil, err - } - - // We'll unconditionally queue the channel's existence chanProof as it - // will need to be processed before either of the channel update - // networkMsgs. - - // Since it's up to a node's policy as to whether they advertise the - // edge in a direction, we don't create an advertisement if the edge is - // nil. - var edge1Ann, edge2Ann *lnwire.ChannelUpdate - if e1 != nil { - edge1Ann = &lnwire.ChannelUpdate{ - ChainHash: chanInfo.ChainHash, - ShortChannelID: chanID, - Timestamp: uint32(e1.LastUpdate.Unix()), - MessageFlags: e1.MessageFlags, - ChannelFlags: e1.ChannelFlags, - TimeLockDelta: e1.TimeLockDelta, - HtlcMinimumMsat: e1.MinHTLC, - HtlcMaximumMsat: e1.MaxHTLC, - BaseFee: uint32(e1.FeeBaseMSat), - FeeRate: uint32(e1.FeeProportionalMillionths), - ExtraOpaqueData: e1.ExtraOpaqueData, - } - edge1Ann.Signature, err = lnwire.NewSigFromRawSignature(e1.SigBytes) - if err != nil { - return nil, nil, nil, err - } - } - if e2 != nil { - edge2Ann = &lnwire.ChannelUpdate{ - ChainHash: chanInfo.ChainHash, - ShortChannelID: chanID, - Timestamp: uint32(e2.LastUpdate.Unix()), - MessageFlags: e2.MessageFlags, - ChannelFlags: e2.ChannelFlags, - TimeLockDelta: e2.TimeLockDelta, - HtlcMinimumMsat: e2.MinHTLC, - HtlcMaximumMsat: e2.MaxHTLC, - BaseFee: uint32(e2.FeeBaseMSat), - FeeRate: uint32(e2.FeeProportionalMillionths), - ExtraOpaqueData: e2.ExtraOpaqueData, - } - edge2Ann.Signature, err = lnwire.NewSigFromRawSignature(e2.SigBytes) - if err != nil { - return nil, nil, nil, err - } - } - - return chanAnn, edge1Ann, edge2Ann, nil -} - -// SignAnnouncement is a helper function which is used to sign any outgoing -// channel node node announcement messages. -func SignAnnouncement(signer lnwallet.MessageSigner, pubKey *btcec.PublicKey, - msg lnwire.Message) (*btcec.Signature, error) { - - var ( - data []byte - err error - ) - - switch m := msg.(type) { - case *lnwire.ChannelAnnouncement: - data, err = m.DataToSign() - case *lnwire.ChannelUpdate: - data, err = m.DataToSign() - case *lnwire.NodeAnnouncement: - data, err = m.DataToSign() - default: - return nil, errors.New("can't sign message " + - "of this format") - } - if err != nil { - return nil, errors.Errorf("unable to get data to sign: %v", err) - } - - return signer.SignMessage(pubKey, data) -} - -// remotePubFromChanInfo returns the public key of the remote peer given a -// ChannelEdgeInfo that describe a channel we have with them. -func remotePubFromChanInfo(chanInfo *channeldb.ChannelEdgeInfo, - chanFlags lnwire.ChanUpdateChanFlags) [33]byte { - - var remotePubKey [33]byte - switch { - case chanFlags&lnwire.ChanUpdateDirection == 0: - remotePubKey = chanInfo.NodeKey2Bytes - case chanFlags&lnwire.ChanUpdateDirection == 1: - remotePubKey = chanInfo.NodeKey1Bytes - } - - return remotePubKey -} diff --git a/go.mod b/go.mod index 7f696aa661..6e0f12c997 100644 --- a/go.mod +++ b/go.mod @@ -34,15 +34,15 @@ require ( github.com/ltcsuite/lnd/cert v0.0.0-00010101000000-000000000000 github.com/ltcsuite/lnd/queue v1.0.3 github.com/ltcsuite/lnd/ticker v1.0.1 - github.com/ltcsuite/ltcd v0.20.1-beta - github.com/ltcsuite/ltcutil v1.0.2 + github.com/ltcsuite/ltcd v0.20.1-beta.0.20200617222819-81094527da29 + github.com/ltcsuite/ltcutil v1.0.2-beta github.com/ltcsuite/ltcutil/psbt v1.0.2 - github.com/ltcsuite/ltcwallet v0.11.1-beta + github.com/ltcsuite/ltcwallet v0.11.1-beta.0.20200617223724-8fab723115a2 github.com/ltcsuite/ltcwallet/wallet/txauthor v1.0.0 github.com/ltcsuite/ltcwallet/wallet/txrules v1.0.0 github.com/ltcsuite/ltcwallet/walletdb v1.3.1 - github.com/ltcsuite/ltcwallet/wtxmgr v1.0.0 - github.com/ltcsuite/neutrino v0.11.0 + github.com/ltcsuite/ltcwallet/wtxmgr v1.1.0 + github.com/ltcsuite/neutrino v0.11.1-0.20200618172823-18e554fc0b01 github.com/mattn/go-runewidth v0.0.9 // indirect github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 github.com/prometheus/client_golang v0.9.3 @@ -50,7 +50,7 @@ require ( github.com/stretchr/testify v1.3.0 github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 github.com/urfave/cli v1.18.0 - golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 + golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 @@ -71,20 +71,4 @@ replace git.schwanenlied.me/yawning/bsaes.git => github.com/Yawning/bsaes v0.0.0 // btcsuite/btcutil package requests a newer version. replace golang.org/x/crypto => golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 -//temp - -replace github.com/ltcsuite/ltcutil => ../ltcutil - -replace github.com/ltcsuite/ltcd => ../ltcd - -replace github.com/ltcsuite/neutrino => ../neutrino - -replace github.com/ltcsuite/ltcwallet => ../ltcwallet - -replace github.com/ltcsuite/ltcwallet/walletdb => ../ltcwallet/walletdb - -replace github.com/ltcsuite/ltcwallet/wtxmgr => ../ltcwallet/wtxmgr - -replace github.com/ltcsuite/ltcutil/psbt => ../ltcutil/psbt - go 1.12 diff --git a/go.sum b/go.sum index 4bd4c17359..135c35cac6 100644 --- a/go.sum +++ b/go.sum @@ -60,6 +60,7 @@ github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -168,15 +169,35 @@ github.com/ltcsuite/lnd/queue v1.0.3 h1:c3lV2VVknh6tUNBgSHrIUiyaaFfWWdt+s2q0Oz4f github.com/ltcsuite/lnd/queue v1.0.3/go.mod h1:L0MMGRrsJFPHhTInek8YgW2v7NyB6pXrAh6Bbg2D7u8= github.com/ltcsuite/lnd/ticker v1.0.1 h1:+0KvqE4HYO+fFPgNo+42hhyEjK0DwBp//IPmkLhCMcI= github.com/ltcsuite/lnd/ticker v1.0.1/go.mod h1:WZKpekfDVAVv7Gsrr0GAWC/U1XURfGesFg9sQYJbeL4= +github.com/ltcsuite/ltcd v0.20.1-beta/go.mod h1:ZFQaYdYULIuTQiWqs7AUiHD2XhDFeeHW1IH+UYMdABU= +github.com/ltcsuite/ltcd v0.20.1-beta.0.20200617222819-81094527da29 h1:k7X+QeOhE8u/DttC5eUAqaYhhEEd74DrZYxrJEb4D1k= +github.com/ltcsuite/ltcd v0.20.1-beta.0.20200617222819-81094527da29/go.mod h1:k4GH6YHNIenJnZY4zAETuiyiYdWKd00kIc6M2lXt/4g= github.com/ltcsuite/ltclog v0.0.0-20160817181405-73889fb79bd6/go.mod h1:0vobaAoyUrwaVFd11+PtAx4afDrzzyFopOaky5ytLBw= +github.com/ltcsuite/ltcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= +github.com/ltcsuite/ltcutil v0.0.0-20191227053721-6bec450ea6ad/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= +github.com/ltcsuite/ltcutil v1.0.2-beta h1:IS86frABIvbpw9ilpQ/zt8t30pFog6DD4tBcgbjdj8g= +github.com/ltcsuite/ltcutil v1.0.2-beta/go.mod h1:G1JGpaqtMm0mPtheTryXnDd9a4KAFuGevdQirlJO1Nw= +github.com/ltcsuite/ltcutil/psbt v1.0.2 h1:gv2tsFI6wC9xwSOKIsMvbx4dAZx9jIe09OmyGT5byuA= +github.com/ltcsuite/ltcutil/psbt v1.0.2/go.mod h1:qMxeWKeZ9pN6BUM9lh4E4DrWq1lFnVSdQMl/Sv4IxGA= +github.com/ltcsuite/ltcwallet v0.11.1-beta/go.mod h1:NDOrqKG1Wo5f9WbKzEW0oQFRcFrA6znu+zFYgmFvyJE= +github.com/ltcsuite/ltcwallet v0.11.1-beta.0.20200617223724-8fab723115a2 h1:spjO8mJY+Xq4BR+PTCWgpDQDls4a3gbCCPbtbEPt1Gk= +github.com/ltcsuite/ltcwallet v0.11.1-beta.0.20200617223724-8fab723115a2/go.mod h1:1XqgFL7DJ+LEZ1Ky4pdgtw0YCo+FRVzUcVomimaob3I= github.com/ltcsuite/ltcwallet/wallet/txauthor v1.0.0 h1:V5iIFayENLKYw63swa3HsHEHvW8oKHzrVaqqhn48Xgc= github.com/ltcsuite/ltcwallet/wallet/txauthor v1.0.0/go.mod h1:4kj4pIFY9uVuroAn6rjLaFdMTxxXrwQwvU3iw8qurOg= github.com/ltcsuite/ltcwallet/wallet/txrules v1.0.0 h1:WDrodrBVO5EbaAT5//i2YOg7DH+FnWSm/kjTvMNT/EY= github.com/ltcsuite/ltcwallet/wallet/txrules v1.0.0/go.mod h1:H/FiHbbfd9+TPn9ao1Ier7rBosT5j2ejIbHvZqHSEVU= github.com/ltcsuite/ltcwallet/wallet/txsizes v1.0.0 h1:V6WkKCtE0YfJq+spvFk39y/pl33tsc6DbyWGCLWQcds= github.com/ltcsuite/ltcwallet/wallet/txsizes v1.0.0/go.mod h1:BVSZSGrQP4MXD7Y3vVVZ1TiabQmzmkeYngSfz7DD34o= +github.com/ltcsuite/ltcwallet/walletdb v1.2.0/go.mod h1:C4GeXkLjUw1zkKiUwTvqSKE0eJmFjM7FZBjjw6TglJw= +github.com/ltcsuite/ltcwallet/walletdb v1.3.1 h1:Qm93cp6zh7qQs3ujiwQ/Jo+JTU/QNyi/9vCqUoq18oQ= +github.com/ltcsuite/ltcwallet/walletdb v1.3.1/go.mod h1:C4GeXkLjUw1zkKiUwTvqSKE0eJmFjM7FZBjjw6TglJw= github.com/ltcsuite/ltcwallet/wtxmgr v1.0.0 h1:nTzmath9QTVL9esn4/luLDnjQ1VFtih7FI7klQDZze4= github.com/ltcsuite/ltcwallet/wtxmgr v1.0.0/go.mod h1:mEc+C10DLTHG6iaDnBUlulZGADd1QMe+gZOiCNo/qcg= +github.com/ltcsuite/ltcwallet/wtxmgr v1.1.0 h1:qgaaioOX5osqTsTnseHm8tSTFF3Rlv3LSo6T42xovFw= +github.com/ltcsuite/ltcwallet/wtxmgr v1.1.0/go.mod h1:mEc+C10DLTHG6iaDnBUlulZGADd1QMe+gZOiCNo/qcg= +github.com/ltcsuite/neutrino v0.11.0/go.mod h1:22zulMl4XMtJJb/7Z8YR3oud1EqfbQ2oSYE4gMnNVfM= +github.com/ltcsuite/neutrino v0.11.1-0.20200618172823-18e554fc0b01 h1:LRVt00FI60JZIhQa9AHxRPDyfyU7Rj+tUlAJw2whB4g= +github.com/ltcsuite/neutrino v0.11.1-0.20200618172823-18e554fc0b01/go.mod h1:Q4OQw7sBl70saf3lVvwDT+Oc43oey7ftdkdcvTUVln0= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= diff --git a/lnd.go b/lnd.go index 663778e1d6..c9a62794eb 100644 --- a/lnd.go +++ b/lnd.go @@ -42,6 +42,7 @@ import ( "github.com/ltcsuite/lnd/lncfg" "github.com/ltcsuite/lnd/lnrpc" "github.com/ltcsuite/lnd/lnwallet" + "github.com/ltcsuite/lnd/lnwallet/btcwallet" "github.com/ltcsuite/lnd/macaroons" "github.com/ltcsuite/lnd/signal" "github.com/ltcsuite/lnd/tor" @@ -1059,7 +1060,7 @@ func waitForWalletPassword(restEndpoints []net.Addr, keychain.KeyDerivationVersion) } - netDir := ltcwallet.NetworkDir( + netDir := btcwallet.NetworkDir( chainConfig.ChainDir, activeNetParams.Params, ) loader := wallet.NewLoader( diff --git a/lnrpc/routerrpc/config_active.go b/lnrpc/routerrpc/config_active.go deleted file mode 100644 index 86deb415be..0000000000 --- a/lnrpc/routerrpc/config_active.go +++ /dev/null @@ -1,71 +0,0 @@ -// +build routerrpc - -package routerrpc - -import ( - "github.com/ltcsuite/lnd/macaroons" - "github.com/ltcsuite/lnd/routing" -) - -// Config is the main configuration file for the router RPC server. It contains -// all the items required for the router RPC server to carry out its duties. -// The fields with struct tags are meant to be parsed as normal configuration -// options, while if able to be populated, the latter fields MUST also be -// specified. -type Config struct { - RoutingConfig - - // RouterMacPath is the path for the router macaroon. If unspecified - // then we assume that the macaroon will be found under the network - // directory, named DefaultRouterMacFilename. - RouterMacPath string `long:"routermacaroonpath" description:"Path to the router macaroon"` - - // NetworkDir is the main network directory wherein the router rpc - // server will find the macaroon named DefaultRouterMacFilename. - NetworkDir string - - // MacService is the main macaroon service that we'll use to handle - // authentication for the Router rpc server. - MacService *macaroons.Service - - // Router is the main channel router instance that backs this RPC - // server. - // - // TODO(roasbeef): make into pkg lvl interface? - // - // TODO(roasbeef): assumes router handles saving payment state - Router *routing.ChannelRouter - - // RouterBackend contains shared logic between this sub server and the - // main rpc server. - RouterBackend *RouterBackend -} - -// DefaultConfig defines the config defaults. -func DefaultConfig() *Config { - defaultRoutingConfig := RoutingConfig{ - AprioriHopProbability: routing.DefaultAprioriHopProbability, - AprioriWeight: routing.DefaultAprioriWeight, - MinRouteProbability: routing.DefaultMinRouteProbability, - PenaltyHalfLife: routing.DefaultPenaltyHalfLife, - AttemptCost: routing.DefaultPaymentAttemptPenalty. - ToSatoshis(), - MaxMcHistory: routing.DefaultMaxMcHistory, - } - - return &Config{ - RoutingConfig: defaultRoutingConfig, - } -} - -// GetRoutingConfig returns the routing config based on this sub server config. -func GetRoutingConfig(cfg *Config) *RoutingConfig { - return &RoutingConfig{ - AprioriHopProbability: cfg.AprioriHopProbability, - AprioriWeight: cfg.AprioriWeight, - MinRouteProbability: cfg.MinRouteProbability, - AttemptCost: cfg.AttemptCost, - PenaltyHalfLife: cfg.PenaltyHalfLife, - MaxMcHistory: cfg.MaxMcHistory, - } -} diff --git a/lnrpc/routerrpc/config_default.go b/lnrpc/routerrpc/config_default.go deleted file mode 100644 index d01b529472..0000000000 --- a/lnrpc/routerrpc/config_default.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build !routerrpc - -package routerrpc - -import "github.com/ltcsuite/lnd/routing" - -// Config is the default config struct for the package. When the build tag isn't -// specified, then we output a blank config. -type Config struct{} - -// DefaultConfig defines the config defaults. Without the sub server enabled, -// there are no defaults to set. -func DefaultConfig() *Config { - return &Config{} -} - -// GetRoutingConfig returns the routing config based on this sub server config. -func GetRoutingConfig(cfg *Config) *RoutingConfig { - return &RoutingConfig{ - AprioriHopProbability: routing.DefaultAprioriHopProbability, - AprioriWeight: routing.DefaultAprioriWeight, - MinRouteProbability: routing.DefaultMinRouteProbability, - AttemptCost: routing.DefaultPaymentAttemptPenalty. - ToSatoshis(), - PenaltyHalfLife: routing.DefaultPenaltyHalfLife, - MaxMcHistory: routing.DefaultMaxMcHistory, - } -} diff --git a/lnwallet/btcwallet/blockchain.go b/lnwallet/btcwallet/blockchain.go index b54bc839a2..d5e8232754 100644 --- a/lnwallet/btcwallet/blockchain.go +++ b/lnwallet/btcwallet/blockchain.go @@ -1,4 +1,4 @@ -package ltcwallet +package btcwallet import ( "encoding/hex" @@ -9,10 +9,10 @@ import ( "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/ltcutil" + "github.com/ltcsuite/lnd/lnwallet" "github.com/ltcsuite/ltcwallet/chain" "github.com/ltcsuite/neutrino" "github.com/ltcsuite/neutrino/headerfs" - "github.com/ltcsuite/lnd/lnwallet" ) var ( diff --git a/lnwallet/btcwallet/btcwallet.go b/lnwallet/btcwallet/btcwallet.go index 6f1a5db999..7a266b980d 100644 --- a/lnwallet/btcwallet/btcwallet.go +++ b/lnwallet/btcwallet/btcwallet.go @@ -1,4 +1,4 @@ -package ltcwallet +package btcwallet import ( "bytes" @@ -8,6 +8,9 @@ import ( "sync" "time" + "github.com/ltcsuite/lnd/keychain" + "github.com/ltcsuite/lnd/lnwallet" + "github.com/ltcsuite/lnd/lnwallet/chainfee" "github.com/ltcsuite/ltcd/chaincfg" "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/txscript" @@ -19,9 +22,6 @@ import ( "github.com/ltcsuite/ltcwallet/wallet/txauthor" "github.com/ltcsuite/ltcwallet/wallet/txrules" "github.com/ltcsuite/ltcwallet/walletdb" - "github.com/ltcsuite/lnd/keychain" - "github.com/ltcsuite/lnd/lnwallet" - "github.com/ltcsuite/lnd/lnwallet/chainfee" ) const ( diff --git a/lnwallet/btcwallet/btcwallet_rpctest.go b/lnwallet/btcwallet/btcwallet_rpctest.go index 7139e4cc17..b31affdfaf 100644 --- a/lnwallet/btcwallet/btcwallet_rpctest.go +++ b/lnwallet/btcwallet/btcwallet_rpctest.go @@ -3,8 +3,8 @@ package btcwallet import ( - "github.com/btcsuite/btcwallet/snacl" - "github.com/btcsuite/btcwallet/waddrmgr" + "github.com/ltcsuite/ltcwallet/snacl" + "github.com/ltcsuite/ltcwallet/waddrmgr" ) func init() { diff --git a/lnwallet/btcwallet/config.go b/lnwallet/btcwallet/config.go index 514f0c1306..5c9e7dd606 100644 --- a/lnwallet/btcwallet/config.go +++ b/lnwallet/btcwallet/config.go @@ -1,4 +1,4 @@ -package ltcwallet +package btcwallet import ( "path/filepath" diff --git a/lnwallet/btcwallet/driver.go b/lnwallet/btcwallet/driver.go index 7b5b8a7d03..d9c0613ea4 100644 --- a/lnwallet/btcwallet/driver.go +++ b/lnwallet/btcwallet/driver.go @@ -1,10 +1,10 @@ -package ltcwallet +package btcwallet import ( "fmt" - "github.com/ltcsuite/ltcwallet/chain" "github.com/ltcsuite/lnd/lnwallet" + "github.com/ltcsuite/ltcwallet/chain" ) const ( diff --git a/lnwallet/btcwallet/signer.go b/lnwallet/btcwallet/signer.go index 0025b08edc..5fb641dd2f 100644 --- a/lnwallet/btcwallet/signer.go +++ b/lnwallet/btcwallet/signer.go @@ -1,8 +1,12 @@ -package ltcwallet +package btcwallet import ( "fmt" + "github.com/go-errors/errors" + "github.com/ltcsuite/lnd/input" + "github.com/ltcsuite/lnd/keychain" + "github.com/ltcsuite/lnd/lnwallet" "github.com/ltcsuite/ltcd/btcec" "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/txscript" @@ -11,10 +15,6 @@ import ( "github.com/ltcsuite/ltcwallet/waddrmgr" base "github.com/ltcsuite/ltcwallet/wallet" "github.com/ltcsuite/ltcwallet/walletdb" - "github.com/go-errors/errors" - "github.com/ltcsuite/lnd/input" - "github.com/ltcsuite/lnd/keychain" - "github.com/ltcsuite/lnd/lnwallet" ) // FetchInputInfo queries for the WalletController's knowledge of the passed diff --git a/walletunlocker/service.go b/walletunlocker/service.go index 14eed6a87e..99b9a92ee8 100644 --- a/walletunlocker/service.go +++ b/walletunlocker/service.go @@ -8,14 +8,14 @@ import ( "os" "time" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcwallet/wallet" "github.com/ltcsuite/lnd/aezeed" "github.com/ltcsuite/lnd/chanbackup" "github.com/ltcsuite/lnd/keychain" "github.com/ltcsuite/lnd/lnrpc" "github.com/ltcsuite/lnd/lnwallet" "github.com/ltcsuite/lnd/lnwallet/btcwallet" + "github.com/ltcsuite/ltcd/chaincfg" + "github.com/ltcsuite/ltcwallet/wallet" ) // ChannelsToRecover wraps any set of packed (serialized+encrypted) channel @@ -128,7 +128,7 @@ func (u *UnlockerService) GenSeed(ctx context.Context, // Before we start, we'll ensure that the wallet hasn't already created // so we don't show a *new* seed to the user if one already exists. - netDir := ltcwallet.NetworkDir(u.chainDir, u.netParams) + netDir := btcwallet.NetworkDir(u.chainDir, u.netParams) loader := wallet.NewLoader(u.netParams, netDir, u.noFreelistSync, 0) walletExists, err := loader.WalletExists() if err != nil { @@ -257,7 +257,7 @@ func (u *UnlockerService) InitWallet(ctx context.Context, // We'll then open up the directory that will be used to store the // wallet's files so we can check if the wallet already exists. - netDir := ltcwallet.NetworkDir(u.chainDir, u.netParams) + netDir := btcwallet.NetworkDir(u.chainDir, u.netParams) loader := wallet.NewLoader( u.netParams, netDir, u.noFreelistSync, uint32(recoveryWindow), ) @@ -316,7 +316,7 @@ func (u *UnlockerService) UnlockWallet(ctx context.Context, password := in.WalletPassword recoveryWindow := uint32(in.RecoveryWindow) - netDir := ltcwallet.NetworkDir(u.chainDir, u.netParams) + netDir := btcwallet.NetworkDir(u.chainDir, u.netParams) loader := wallet.NewLoader( u.netParams, netDir, u.noFreelistSync, recoveryWindow, ) @@ -369,7 +369,7 @@ func (u *UnlockerService) UnlockWallet(ctx context.Context, func (u *UnlockerService) ChangePassword(ctx context.Context, in *lnrpc.ChangePasswordRequest) (*lnrpc.ChangePasswordResponse, error) { - netDir := ltcwallet.NetworkDir(u.chainDir, u.netParams) + netDir := btcwallet.NetworkDir(u.chainDir, u.netParams) loader := wallet.NewLoader(u.netParams, netDir, u.noFreelistSync, 0) // First, we'll make sure the wallet exists for the specific chain and