Merge pull request #4405 from joostjager/interceptor-out

htlcswitch: expose additional data for intercepted packets
This commit is contained in:
Conner Fromknecht 2020-06-29 11:35:20 -07:00 committed by GitHub
commit eeea441c3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 358 additions and 200 deletions

View File

@ -115,15 +115,19 @@ type interceptedForward struct {
}
// Packet returns the intercepted htlc packet.
func (f *interceptedForward) Packet() lnwire.UpdateAddHTLC {
return *f.htlc
}
// CircuitKey returns the circuit key for the intercepted htlc.
func (f *interceptedForward) CircuitKey() channeldb.CircuitKey {
return channeldb.CircuitKey{
ChanID: f.packet.incomingChanID,
HtlcID: f.packet.incomingHTLCID,
func (f *interceptedForward) Packet() InterceptedPacket {
return InterceptedPacket{
IncomingCircuit: channeldb.CircuitKey{
ChanID: f.packet.incomingChanID,
HtlcID: f.packet.incomingHTLCID,
},
OutgoingChanID: f.packet.outgoingChanID,
Hash: f.htlc.PaymentHash,
OutgoingExpiry: f.htlc.Expiry,
OutgoingAmount: f.htlc.Amount,
IncomingAmount: f.packet.incomingAmount,
IncomingExpiry: f.packet.incomingTimeout,
CustomRecords: f.packet.customRecords,
}
}

View File

@ -8,6 +8,7 @@ import (
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record"
)
// InvoiceDatabase is an interface which represents the persistent subsystem
@ -200,17 +201,46 @@ type InterceptableHtlcForwarder interface {
// and resolve it later or let the switch execute its default behavior.
type ForwardInterceptor func(InterceptedForward) bool
// InterceptedPacket contains the relevant information for the interceptor about
// an htlc.
type InterceptedPacket struct {
// IncomingCircuit contains the incoming channel and htlc id of the
// packet.
IncomingCircuit channeldb.CircuitKey
// OutgoingChanID is the destination channel for this packet.
OutgoingChanID lnwire.ShortChannelID
// Hash is the payment hash of the htlc.
Hash lntypes.Hash
// OutgoingExpiry is the absolute block height at which the outgoing
// htlc expires.
OutgoingExpiry uint32
// OutgoingAmount is the amount to forward.
OutgoingAmount lnwire.MilliSatoshi
// IncomingExpiry is the absolute block height at which the incoming
// htlc expires.
IncomingExpiry uint32
// IncomingAmount is the amount of the accepted htlc.
IncomingAmount lnwire.MilliSatoshi
// CustomRecords are user-defined records in the custom type range that
// were included in the payload.
CustomRecords record.CustomSet
}
// InterceptedForward is passed to the ForwardInterceptor for every forwarded
// htlc. It contains all the information about the packet which accordingly
// the interceptor decides if to hold or not.
// In addition this interface allows a later resolution by calling either
// Resume, Settle or Fail.
type InterceptedForward interface {
// CircuitKey returns the intercepted packet.
CircuitKey() channeldb.CircuitKey
// Packet returns the intercepted packet.
Packet() lnwire.UpdateAddHTLC
Packet() InterceptedPacket
// Resume notifies the intention to resume an existing hold forward. This
// basically means the caller wants to resume with the default behavior for

View File

@ -2731,6 +2731,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
obfuscator: obfuscator,
incomingTimeout: pd.Timeout,
outgoingTimeout: fwdInfo.OutgoingCTLV,
customRecords: pld.CustomRecords(),
}
switchPackets = append(
switchPackets, updatePacket,
@ -2794,6 +2795,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
obfuscator: obfuscator,
incomingTimeout: pd.Timeout,
outgoingTimeout: fwdInfo.OutgoingCTLV,
customRecords: pld.CustomRecords(),
}
fwdPkg.FwdFilter.Set(idx)

View File

@ -4,6 +4,7 @@ import (
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/htlcswitch/hop"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record"
)
// htlcPacket is a wrapper around htlc lnwire update, which adds additional
@ -91,6 +92,10 @@ type htlcPacket struct {
// will be extraced from the hop payload recevived by the incoming
// link.
outgoingTimeout uint32
// customRecords are user-defined records in the custom type range that
// were included in the payload.
customRecords record.CustomSet
}
// inKey returns the circuit key used to identify the incoming htlc.

View File

@ -148,18 +148,22 @@ func (r *forwardInterceptor) holdAndForwardToClient(
forward htlcswitch.InterceptedForward) error {
htlc := forward.Packet()
inKey := forward.CircuitKey()
inKey := htlc.IncomingCircuit
// First hold the forward, then send to client.
r.holdForwards[forward.CircuitKey()] = forward
r.holdForwards[inKey] = forward
interceptionRequest := &ForwardHtlcInterceptRequest{
IncomingCircuitKey: &CircuitKey{
ChanId: inKey.ChanID.ToUint64(),
HtlcId: inKey.HtlcID,
},
HtlcPaymentHash: htlc.PaymentHash[:],
AmountMsat: uint64(htlc.Amount),
Expiry: htlc.Expiry,
OutgoingRequestedChanId: htlc.OutgoingChanID.ToUint64(),
PaymentHash: htlc.Hash[:],
OutgoingAmountMsat: uint64(htlc.OutgoingAmount),
OutgoingExpiry: htlc.OutgoingExpiry,
IncomingAmountMsat: uint64(htlc.IncomingAmount),
IncomingExpiry: htlc.IncomingExpiry,
CustomRecords: htlc.CustomRecords,
}
return r.stream.Send(interceptionRequest)

View File

@ -1809,17 +1809,28 @@ type ForwardHtlcInterceptRequest struct {
//The key of this forwarded htlc. It defines the incoming channel id and
//the index in this channel.
IncomingCircuitKey *CircuitKey `protobuf:"bytes,1,opt,name=incoming_circuit_key,json=incomingCircuitKey,proto3" json:"incoming_circuit_key,omitempty"`
// The incoming htlc amount.
IncomingAmountMsat uint64 `protobuf:"varint,5,opt,name=incoming_amount_msat,json=incomingAmountMsat,proto3" json:"incoming_amount_msat,omitempty"`
// The incoming htlc expiry.
IncomingExpiry uint32 `protobuf:"varint,6,opt,name=incoming_expiry,json=incomingExpiry,proto3" json:"incoming_expiry,omitempty"`
//
//The htlc payment hash. This value is not guaranteed to be unique per
//request.
HtlcPaymentHash []byte `protobuf:"bytes,2,opt,name=htlc_payment_hash,json=htlcPaymentHash,proto3" json:"htlc_payment_hash,omitempty"`
/// The htlc amount.
AmountMsat uint64 `protobuf:"varint,3,opt,name=amount_msat,json=amountMsat,proto3" json:"amount_msat,omitempty"`
/// The htlc expiry.
Expiry uint32 `protobuf:"varint,4,opt,name=expiry,proto3" json:"expiry,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
PaymentHash []byte `protobuf:"bytes,2,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"`
// The requested outgoing channel id for this forwarded htlc. Because of
// non-strict forwarding, this isn't necessarily the channel over which the
// packet will be forwarded eventually. A different channel to the same peer
// may be selected as well.
OutgoingRequestedChanId uint64 `protobuf:"varint,7,opt,name=outgoing_requested_chan_id,json=outgoingRequestedChanId,proto3" json:"outgoing_requested_chan_id,omitempty"`
// The outgoing htlc amount.
OutgoingAmountMsat uint64 `protobuf:"varint,3,opt,name=outgoing_amount_msat,json=outgoingAmountMsat,proto3" json:"outgoing_amount_msat,omitempty"`
// The outgoing htlc expiry.
OutgoingExpiry uint32 `protobuf:"varint,4,opt,name=outgoing_expiry,json=outgoingExpiry,proto3" json:"outgoing_expiry,omitempty"`
// Any custom records that were present in the payload.
CustomRecords map[uint64][]byte `protobuf:"bytes,8,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:"-"`
}
func (m *ForwardHtlcInterceptRequest) Reset() { *m = ForwardHtlcInterceptRequest{} }
@ -1854,27 +1865,55 @@ func (m *ForwardHtlcInterceptRequest) GetIncomingCircuitKey() *CircuitKey {
return nil
}
func (m *ForwardHtlcInterceptRequest) GetHtlcPaymentHash() []byte {
func (m *ForwardHtlcInterceptRequest) GetIncomingAmountMsat() uint64 {
if m != nil {
return m.HtlcPaymentHash
return m.IncomingAmountMsat
}
return 0
}
func (m *ForwardHtlcInterceptRequest) GetIncomingExpiry() uint32 {
if m != nil {
return m.IncomingExpiry
}
return 0
}
func (m *ForwardHtlcInterceptRequest) GetPaymentHash() []byte {
if m != nil {
return m.PaymentHash
}
return nil
}
func (m *ForwardHtlcInterceptRequest) GetAmountMsat() uint64 {
func (m *ForwardHtlcInterceptRequest) GetOutgoingRequestedChanId() uint64 {
if m != nil {
return m.AmountMsat
return m.OutgoingRequestedChanId
}
return 0
}
func (m *ForwardHtlcInterceptRequest) GetExpiry() uint32 {
func (m *ForwardHtlcInterceptRequest) GetOutgoingAmountMsat() uint64 {
if m != nil {
return m.Expiry
return m.OutgoingAmountMsat
}
return 0
}
func (m *ForwardHtlcInterceptRequest) GetOutgoingExpiry() uint32 {
if m != nil {
return m.OutgoingExpiry
}
return 0
}
func (m *ForwardHtlcInterceptRequest) GetCustomRecords() map[uint64][]byte {
if m != nil {
return m.CustomRecords
}
return nil
}
//*
//ForwardHtlcInterceptResponse enables the caller to resolve a previously hold
//forward. The caller can choose either to:
@ -1973,170 +2012,176 @@ func init() {
proto.RegisterType((*PaymentStatus)(nil), "routerrpc.PaymentStatus")
proto.RegisterType((*CircuitKey)(nil), "routerrpc.CircuitKey")
proto.RegisterType((*ForwardHtlcInterceptRequest)(nil), "routerrpc.ForwardHtlcInterceptRequest")
proto.RegisterMapType((map[uint64][]byte)(nil), "routerrpc.ForwardHtlcInterceptRequest.CustomRecordsEntry")
proto.RegisterType((*ForwardHtlcInterceptResponse)(nil), "routerrpc.ForwardHtlcInterceptResponse")
}
func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) }
var fileDescriptor_7a0613f69d37b0a5 = []byte{
// 2499 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x4b, 0x73, 0x1b, 0xc7,
0xf1, 0xf7, 0xe2, 0x45, 0xa0, 0xf1, 0x5a, 0x0e, 0x64, 0x0a, 0x7f, 0x50, 0xb2, 0xe1, 0xb5, 0x2d,
0xa1, 0xf4, 0xb7, 0x29, 0x99, 0x49, 0x25, 0xae, 0xf8, 0x91, 0x80, 0xc0, 0x52, 0x5c, 0x09, 0x04,
0xe0, 0x01, 0x48, 0xdb, 0xf1, 0x61, 0x6a, 0x09, 0x0c, 0x88, 0x0d, 0x17, 0xbb, 0xc8, 0xee, 0x40,
0x32, 0x8f, 0xb9, 0xa5, 0xf2, 0x45, 0x72, 0xcb, 0x27, 0xc8, 0x21, 0x87, 0xdc, 0xf2, 0x21, 0x72,
0xcd, 0x3d, 0x55, 0x39, 0xa7, 0xe6, 0xb1, 0xc0, 0x2e, 0x09, 0x4a, 0x49, 0x55, 0x2e, 0xe4, 0xce,
0xaf, 0x7b, 0x7a, 0xba, 0xa7, 0x5f, 0xd3, 0x80, 0xbd, 0xc0, 0x5f, 0x31, 0x1a, 0x04, 0xcb, 0xc9,
0x53, 0xf9, 0x75, 0xb0, 0x0c, 0x7c, 0xe6, 0xa3, 0xc2, 0x1a, 0x6f, 0x14, 0x82, 0xe5, 0x44, 0xa2,
0xc6, 0x3f, 0x73, 0x80, 0x46, 0xd4, 0x9b, 0x0e, 0xed, 0xeb, 0x05, 0xf5, 0x18, 0xa6, 0xbf, 0x5d,
0xd1, 0x90, 0x21, 0x04, 0x99, 0x29, 0x0d, 0x59, 0x5d, 0x6b, 0x6a, 0xad, 0x12, 0x16, 0xdf, 0x48,
0x87, 0xb4, 0xbd, 0x60, 0xf5, 0x54, 0x53, 0x6b, 0xa5, 0x31, 0xff, 0x44, 0xff, 0x07, 0x79, 0x7b,
0xc1, 0xc8, 0x22, 0xb4, 0x59, 0xbd, 0x24, 0xe0, 0x1d, 0x7b, 0xc1, 0x4e, 0x43, 0x9b, 0xa1, 0x0f,
0xa0, 0xb4, 0x94, 0x22, 0xc9, 0xdc, 0x0e, 0xe7, 0xf5, 0xb4, 0x10, 0x54, 0x54, 0xd8, 0x89, 0x1d,
0xce, 0x51, 0x0b, 0xf4, 0x99, 0xe3, 0xd9, 0x2e, 0x99, 0xb8, 0xec, 0x15, 0x99, 0x52, 0x97, 0xd9,
0xf5, 0x4c, 0x53, 0x6b, 0x65, 0x71, 0x45, 0xe0, 0x1d, 0x97, 0xbd, 0xea, 0x72, 0x14, 0x3d, 0x86,
0x6a, 0x24, 0x2c, 0x90, 0x0a, 0xd6, 0xb3, 0x4d, 0xad, 0x55, 0xc0, 0x95, 0x65, 0x52, 0xed, 0xc7,
0x50, 0x65, 0xce, 0x82, 0xfa, 0x2b, 0x46, 0x42, 0x3a, 0xf1, 0xbd, 0x69, 0x58, 0xcf, 0x49, 0x89,
0x0a, 0x1e, 0x49, 0x14, 0x19, 0x50, 0x9e, 0x51, 0x4a, 0x5c, 0x67, 0xe1, 0x30, 0xc2, 0xd5, 0xdf,
0x11, 0xea, 0x17, 0x67, 0x94, 0xf6, 0x38, 0x36, 0xb2, 0x19, 0xfa, 0x08, 0x2a, 0x1b, 0x1e, 0x61,
0x63, 0x59, 0x30, 0x95, 0x22, 0x26, 0x61, 0xe8, 0x01, 0xe8, 0xfe, 0x8a, 0x5d, 0xfa, 0x8e, 0x77,
0x49, 0x26, 0x73, 0xdb, 0x23, 0xce, 0xb4, 0x9e, 0x6f, 0x6a, 0xad, 0xcc, 0x51, 0xa6, 0xae, 0x3d,
0xd3, 0x70, 0x25, 0xa2, 0x76, 0xe6, 0xb6, 0x67, 0x4d, 0xd1, 0x13, 0xd8, 0xbd, 0xc9, 0x1f, 0xd6,
0x6b, 0xcd, 0x74, 0x2b, 0x83, 0xab, 0x49, 0xd6, 0x10, 0x3d, 0x82, 0xaa, 0x6b, 0x87, 0x8c, 0xcc,
0xfd, 0x25, 0x59, 0xae, 0x2e, 0xae, 0xe8, 0x75, 0xbd, 0x22, 0xee, 0xb1, 0xcc, 0xe1, 0x13, 0x7f,
0x39, 0x14, 0x20, 0x7a, 0x08, 0x20, 0xee, 0x50, 0xa8, 0x5a, 0x2f, 0x08, 0x8b, 0x0b, 0x1c, 0x11,
0x6a, 0xa2, 0xcf, 0xa0, 0x28, 0x7c, 0x4f, 0xe6, 0x8e, 0xc7, 0xc2, 0x3a, 0x34, 0xd3, 0xad, 0xe2,
0xa1, 0x7e, 0xe0, 0x7a, 0x3c, 0x0c, 0x30, 0xa7, 0x9c, 0x38, 0x1e, 0xc3, 0x10, 0x44, 0x9f, 0x21,
0x9a, 0x42, 0x8d, 0xfb, 0x9c, 0x4c, 0x56, 0x21, 0xf3, 0x17, 0x24, 0xa0, 0x13, 0x3f, 0x98, 0x86,
0xf5, 0xa2, 0xd8, 0xfa, 0xd3, 0x83, 0x75, 0x28, 0x1d, 0xdc, 0x8e, 0x9d, 0x83, 0x2e, 0x0d, 0x59,
0x47, 0xec, 0xc3, 0x72, 0x9b, 0xe9, 0xb1, 0xe0, 0x1a, 0xef, 0x4e, 0x6f, 0xe2, 0xe8, 0x13, 0x40,
0xb6, 0xeb, 0xfa, 0xaf, 0x49, 0x48, 0xdd, 0x19, 0x51, 0xbe, 0xac, 0x57, 0x9b, 0x5a, 0x2b, 0x8f,
0x75, 0x41, 0x19, 0x51, 0x77, 0xa6, 0xc4, 0xa3, 0x9f, 0x41, 0x59, 0xe8, 0x34, 0xa3, 0x36, 0x5b,
0x05, 0x34, 0xac, 0xeb, 0xcd, 0x74, 0xab, 0x72, 0xb8, 0xab, 0x0c, 0x39, 0x96, 0xf0, 0x91, 0xc3,
0x70, 0x89, 0xf3, 0xa9, 0x75, 0x88, 0xf6, 0xa1, 0xb0, 0xb0, 0x7f, 0x24, 0x4b, 0x3b, 0x60, 0x61,
0x7d, 0xb7, 0xa9, 0xb5, 0xca, 0x38, 0xbf, 0xb0, 0x7f, 0x1c, 0xf2, 0x35, 0x3a, 0x80, 0x9a, 0xe7,
0x13, 0xc7, 0x9b, 0xb9, 0xce, 0xe5, 0x9c, 0x91, 0xd5, 0x72, 0x6a, 0x33, 0x1a, 0xd6, 0x91, 0xd0,
0x61, 0xd7, 0xf3, 0x2d, 0x45, 0x39, 0x93, 0x84, 0x46, 0x17, 0xf6, 0xb6, 0xdb, 0xc7, 0xd3, 0x83,
0x3b, 0x88, 0x67, 0x4c, 0x06, 0xf3, 0x4f, 0x74, 0x0f, 0xb2, 0xaf, 0x6c, 0x77, 0x45, 0x45, 0xca,
0x94, 0xb0, 0x5c, 0xfc, 0x22, 0xf5, 0xb9, 0x66, 0xcc, 0xa1, 0x36, 0x0e, 0xec, 0xc9, 0xd5, 0x8d,
0xac, 0xbb, 0x99, 0x34, 0xda, 0xed, 0xa4, 0xb9, 0x43, 0xdf, 0xd4, 0x1d, 0xfa, 0x1a, 0x5f, 0x43,
0x55, 0x78, 0xf8, 0x98, 0xd2, 0x37, 0xe5, 0xf6, 0x7d, 0xe0, 0x99, 0x2b, 0x32, 0x41, 0xe6, 0x77,
0xce, 0x5e, 0xf0, 0x24, 0x30, 0xa6, 0xa0, 0x6f, 0xf6, 0x87, 0x4b, 0xdf, 0x0b, 0x29, 0x4f, 0x5c,
0x1e, 0x00, 0x3c, 0x82, 0x79, 0x82, 0x88, 0xd4, 0xd0, 0xc4, 0xae, 0x8a, 0xc2, 0x8f, 0x29, 0x15,
0xc9, 0xf1, 0x48, 0xe6, 0x23, 0x71, 0xfd, 0xc9, 0x15, 0xcf, 0x70, 0xfb, 0x5a, 0x89, 0x2f, 0x73,
0xb8, 0xe7, 0x4f, 0xae, 0xba, 0x1c, 0x34, 0x7e, 0x90, 0x45, 0x68, 0xec, 0x8b, 0xb3, 0xfe, 0x8b,
0xeb, 0x30, 0x20, 0x2b, 0x62, 0x51, 0x88, 0x2d, 0x1e, 0x96, 0xe2, 0x41, 0x8d, 0x25, 0xc9, 0xf8,
0x01, 0x6a, 0x09, 0xe1, 0xca, 0x8a, 0x06, 0xe4, 0x97, 0x01, 0x75, 0x16, 0xf6, 0x25, 0x55, 0x92,
0xd7, 0x6b, 0xd4, 0x82, 0x9d, 0x99, 0xed, 0xb8, 0xab, 0x20, 0x12, 0x5c, 0x89, 0x82, 0x4c, 0xa2,
0x38, 0x22, 0x1b, 0x0f, 0xa0, 0x81, 0x69, 0x48, 0xd9, 0xa9, 0x13, 0x86, 0x8e, 0xef, 0x75, 0x7c,
0x8f, 0x05, 0xbe, 0xab, 0x2c, 0x30, 0x1e, 0xc2, 0xfe, 0x56, 0xaa, 0x54, 0x81, 0x6f, 0xfe, 0x66,
0x45, 0x83, 0xeb, 0xed, 0x9b, 0xbf, 0x81, 0xfd, 0xad, 0x54, 0xa5, 0xff, 0x27, 0x90, 0x5d, 0xda,
0x4e, 0xc0, 0x7d, 0xcf, 0x93, 0x72, 0x2f, 0x96, 0x94, 0x43, 0xdb, 0x09, 0x4e, 0x9c, 0x90, 0xf9,
0xc1, 0x35, 0x96, 0x4c, 0x2f, 0x32, 0x79, 0x4d, 0x4f, 0x19, 0x7f, 0xd0, 0xa0, 0x18, 0x23, 0xf2,
0xd4, 0xf0, 0xfc, 0x29, 0x25, 0xb3, 0xc0, 0x5f, 0x44, 0x97, 0xc0, 0x81, 0xe3, 0xc0, 0x5f, 0xf0,
0x98, 0x10, 0x44, 0xe6, 0xab, 0x00, 0xce, 0xf1, 0xe5, 0xd8, 0x47, 0x9f, 0xc2, 0xce, 0x5c, 0x0a,
0x10, 0x65, 0xb3, 0x78, 0x58, 0xbb, 0x71, 0x76, 0xd7, 0x66, 0x36, 0x8e, 0x78, 0x5e, 0x64, 0xf2,
0x69, 0x3d, 0xf3, 0x22, 0x93, 0xcf, 0xe8, 0xd9, 0x17, 0x99, 0x7c, 0x56, 0xcf, 0xbd, 0xc8, 0xe4,
0x73, 0xfa, 0x8e, 0xf1, 0x0f, 0x0d, 0xf2, 0x11, 0x37, 0xd7, 0x84, 0x5f, 0x29, 0xe1, 0x71, 0xa1,
0x82, 0x29, 0xcf, 0x81, 0xb1, 0xb3, 0xa0, 0xa8, 0x09, 0x25, 0x41, 0x4c, 0x86, 0x28, 0x70, 0xac,
0x2d, 0xc2, 0x54, 0xd4, 0xf3, 0x88, 0x43, 0xc4, 0x63, 0x46, 0xd5, 0x73, 0xc9, 0x12, 0xb5, 0xa4,
0x70, 0x35, 0x99, 0xd0, 0x30, 0x94, 0xa7, 0x64, 0x25, 0x8b, 0xc2, 0xc4, 0x41, 0x8f, 0xa0, 0x1a,
0xb1, 0x44, 0x67, 0xe5, 0x64, 0xbc, 0x2a, 0x58, 0x1d, 0xd7, 0x02, 0x3d, 0xce, 0xb7, 0xd8, 0x74,
0x90, 0xca, 0x86, 0x91, 0x1f, 0x2a, 0x8d, 0x37, 0x7e, 0x03, 0xf7, 0x85, 0x2b, 0x87, 0x81, 0x7f,
0x61, 0x5f, 0x38, 0xae, 0xc3, 0xae, 0xa3, 0x20, 0xe7, 0x86, 0x07, 0xfe, 0x82, 0xf0, 0xbb, 0x8d,
0x5c, 0xc0, 0x81, 0xbe, 0x3f, 0xa5, 0xdc, 0x05, 0xcc, 0x97, 0x24, 0xe5, 0x02, 0xe6, 0x0b, 0x42,
0xbc, 0xf3, 0xa6, 0x13, 0x9d, 0xd7, 0xb8, 0x82, 0xfa, 0xed, 0xb3, 0x54, 0xcc, 0x34, 0xa1, 0xb8,
0xdc, 0xc0, 0xe2, 0x38, 0x0d, 0xc7, 0xa1, 0xb8, 0x6f, 0x53, 0x6f, 0xf7, 0xad, 0xf1, 0x47, 0x0d,
0x76, 0x8f, 0x56, 0x8e, 0x3b, 0x4d, 0x24, 0x6e, 0x5c, 0x3b, 0x2d, 0xf9, 0x2e, 0xd8, 0xd6, 0xf4,
0x53, 0x5b, 0x9b, 0xfe, 0x27, 0x5b, 0x1a, 0x6b, 0x5a, 0x34, 0xd6, 0xd4, 0x96, 0xb6, 0xfa, 0x3e,
0x14, 0x37, 0x5d, 0x32, 0xac, 0x67, 0x9a, 0xe9, 0x56, 0x09, 0xc3, 0x3c, 0x6a, 0x91, 0xa1, 0xf1,
0x39, 0xa0, 0xb8, 0xa2, 0xea, 0x42, 0xd6, 0xf5, 0x43, 0xbb, 0xbb, 0x7e, 0x3c, 0x80, 0xc6, 0x68,
0x75, 0x11, 0x4e, 0x02, 0xe7, 0x82, 0x9e, 0x30, 0x77, 0x62, 0xbe, 0xa2, 0x1e, 0x0b, 0xa3, 0x2c,
0xfd, 0x57, 0x06, 0x0a, 0x6b, 0x94, 0x97, 0x67, 0xc7, 0x9b, 0xf8, 0x8b, 0x48, 0x69, 0x8f, 0xba,
0x5c, 0x6f, 0xd9, 0x14, 0x76, 0x23, 0x52, 0x47, 0x52, 0xac, 0x29, 0xe7, 0x4f, 0x18, 0xa9, 0xf8,
0x53, 0x92, 0x3f, 0x6e, 0xa3, 0xe4, 0x6f, 0x81, 0xbe, 0x96, 0x3f, 0x67, 0xee, 0x64, 0x7d, 0x29,
0xb8, 0x12, 0xe1, 0x5c, 0x19, 0xc9, 0xb9, 0x96, 0x1c, 0x71, 0x66, 0x24, 0x67, 0x84, 0x2b, 0xce,
0x0f, 0xa0, 0xc4, 0xf3, 0x21, 0x64, 0xf6, 0x62, 0x49, 0xbc, 0x50, 0xe4, 0x45, 0x06, 0x17, 0xd7,
0x58, 0x3f, 0x44, 0x5f, 0x01, 0x50, 0x6e, 0x1f, 0x61, 0xd7, 0x4b, 0x2a, 0x52, 0xa2, 0x72, 0xf8,
0x5e, 0x2c, 0x30, 0xd6, 0x17, 0x70, 0x20, 0xfe, 0x8e, 0xaf, 0x97, 0x14, 0x17, 0x68, 0xf4, 0x89,
0xbe, 0x86, 0xf2, 0xcc, 0x0f, 0x5e, 0xdb, 0xc1, 0x94, 0x08, 0x50, 0x95, 0x8d, 0xfb, 0x31, 0x09,
0xc7, 0x92, 0x2e, 0xb6, 0x9f, 0xbc, 0x83, 0x4b, 0xb3, 0xd8, 0x1a, 0xbd, 0x04, 0x14, 0xed, 0x17,
0x59, 0x2e, 0x85, 0xe4, 0x85, 0x90, 0xfd, 0xdb, 0x42, 0x78, 0x91, 0x8e, 0x04, 0xe9, 0xb3, 0x1b,
0x18, 0xfa, 0x02, 0x4a, 0x21, 0x65, 0xcc, 0xa5, 0x4a, 0x4c, 0x41, 0x88, 0xd9, 0x4b, 0xbc, 0x69,
0x38, 0x39, 0x92, 0x50, 0x0c, 0x37, 0x4b, 0x74, 0x04, 0x55, 0xd7, 0xf1, 0xae, 0xe2, 0x6a, 0x80,
0xd8, 0x5f, 0x8f, 0xed, 0xef, 0x39, 0xde, 0x55, 0x5c, 0x87, 0xb2, 0x1b, 0x07, 0x8c, 0x2f, 0xa1,
0xb0, 0xbe, 0x25, 0x54, 0x84, 0x9d, 0xb3, 0xfe, 0xcb, 0xfe, 0xe0, 0xdb, 0xbe, 0xfe, 0x0e, 0xca,
0x43, 0x66, 0x64, 0xf6, 0xbb, 0xba, 0xc6, 0x61, 0x6c, 0x76, 0x4c, 0xeb, 0xdc, 0xd4, 0x53, 0x7c,
0x71, 0x3c, 0xc0, 0xdf, 0xb6, 0x71, 0x57, 0x4f, 0x1f, 0xed, 0x40, 0x56, 0x9c, 0x6b, 0xfc, 0x59,
0x83, 0xbc, 0xf0, 0xa0, 0x37, 0xf3, 0xd1, 0xff, 0xc3, 0x3a, 0xb8, 0x44, 0x71, 0xe3, 0x0d, 0x57,
0x44, 0x5d, 0x19, 0xaf, 0x03, 0x66, 0xac, 0x70, 0xce, 0xbc, 0x0e, 0x8d, 0x35, 0x73, 0x4a, 0x32,
0x47, 0x84, 0x35, 0xf3, 0x93, 0x98, 0xe4, 0x44, 0xc9, 0xc9, 0xe0, 0x6a, 0x44, 0x88, 0x2a, 0x6c,
0xfc, 0x6d, 0x9b, 0xa8, 0xc4, 0xb1, 0xb7, 0xad, 0xe2, 0x35, 0x7e, 0x0e, 0xa5, 0xb8, 0xcf, 0xd1,
0x63, 0xc8, 0x38, 0xde, 0xcc, 0x57, 0x89, 0x58, 0xbb, 0x11, 0x5c, 0xdc, 0x48, 0x2c, 0x18, 0x0c,
0x04, 0xfa, 0x4d, 0x3f, 0x1b, 0x65, 0x28, 0xc6, 0x9c, 0x66, 0xfc, 0x5d, 0x83, 0x72, 0xc2, 0x09,
0xff, 0xb1, 0x74, 0xf4, 0x15, 0x94, 0x5e, 0x3b, 0x01, 0x25, 0xf1, 0xf6, 0x5f, 0x39, 0x6c, 0x24,
0xdb, 0x7f, 0xf4, 0xbf, 0xe3, 0x4f, 0x29, 0x2e, 0x72, 0x7e, 0x05, 0xa0, 0x5f, 0x42, 0x45, 0xed,
0x24, 0x53, 0xca, 0x6c, 0xc7, 0x15, 0x57, 0x55, 0x49, 0x84, 0x87, 0xe2, 0xed, 0x0a, 0x3a, 0x2e,
0xcf, 0xe2, 0x4b, 0xf4, 0xf1, 0x46, 0x40, 0xc8, 0x02, 0xc7, 0xbb, 0x14, 0xf7, 0x57, 0x58, 0xb3,
0x8d, 0x04, 0xc8, 0x1b, 0x79, 0x59, 0x3d, 0x1e, 0x47, 0xcc, 0x66, 0xab, 0x10, 0x7d, 0x0a, 0xd9,
0x90, 0xd9, 0xaa, 0x92, 0x55, 0x12, 0xb9, 0x15, 0x63, 0xa4, 0x58, 0x72, 0x25, 0x5e, 0x3f, 0xa9,
0x5b, 0xaf, 0x9f, 0x2c, 0xaf, 0x18, 0xb2, 0x8a, 0x16, 0x0f, 0x91, 0x32, 0xfe, 0x64, 0xdc, 0xeb,
0xb4, 0x19, 0xa3, 0x8b, 0x25, 0xc3, 0x92, 0x41, 0x75, 0xb7, 0xaf, 0x01, 0x3a, 0x4e, 0x30, 0x59,
0x39, 0xec, 0x25, 0xbd, 0xe6, 0x3d, 0x2b, 0x2a, 0xd7, 0xb2, 0xec, 0xe5, 0x26, 0xb2, 0x44, 0xdf,
0x87, 0x9d, 0xa8, 0x10, 0xc9, 0xfa, 0x96, 0x9b, 0x8b, 0x02, 0x64, 0xfc, 0x4d, 0x83, 0x7d, 0xe5,
0x52, 0xe9, 0x0d, 0x46, 0x83, 0x09, 0x5d, 0xae, 0x9f, 0xc5, 0xcf, 0xe1, 0xde, 0xa6, 0xa8, 0xca,
0x83, 0x48, 0xf4, 0xd4, 0x2e, 0x1e, 0xbe, 0x1b, 0xb3, 0x74, 0xa3, 0x06, 0x46, 0xeb, 0x62, 0xbb,
0x51, 0xed, 0x09, 0xec, 0x0a, 0x0d, 0x12, 0xaf, 0x4a, 0x69, 0x7d, 0x95, 0x13, 0x86, 0xb1, 0x97,
0xe5, 0xfb, 0x50, 0xb4, 0x17, 0xfe, 0xca, 0x4b, 0x44, 0x3c, 0x48, 0x48, 0x04, 0xfb, 0x1e, 0xe4,
0xe8, 0x8f, 0x4b, 0x27, 0xb8, 0x16, 0x1e, 0x2a, 0x63, 0xb5, 0x32, 0xfe, 0xa2, 0xc1, 0x83, 0xed,
0xd6, 0xa8, 0x9e, 0xf3, 0x3f, 0x33, 0xe7, 0x0b, 0xc8, 0xd9, 0x13, 0xe6, 0xf8, 0x9e, 0x8a, 0xd2,
0x0f, 0x63, 0x5b, 0x31, 0x0d, 0x7d, 0xf7, 0x15, 0x3d, 0xf1, 0xdd, 0xa9, 0x52, 0xa6, 0x2d, 0x58,
0xb1, 0xda, 0x92, 0x08, 0x80, 0x74, 0x32, 0x00, 0x9e, 0xfc, 0x2e, 0x03, 0xe5, 0x44, 0x94, 0x26,
0xcb, 0x54, 0x19, 0x0a, 0xfd, 0x01, 0xe9, 0x9a, 0xe3, 0xb6, 0xd5, 0xd3, 0x35, 0xa4, 0x43, 0x69,
0xd0, 0xb7, 0x06, 0x7d, 0xd2, 0x35, 0x3b, 0x83, 0x2e, 0x2f, 0x58, 0xef, 0xc2, 0x6e, 0xcf, 0xea,
0xbf, 0x24, 0xfd, 0xc1, 0x98, 0x98, 0x3d, 0xeb, 0xb9, 0x75, 0xd4, 0x33, 0xf5, 0x34, 0xba, 0x07,
0xfa, 0xa0, 0x4f, 0x3a, 0x27, 0x6d, 0xab, 0x4f, 0xc6, 0xd6, 0xa9, 0x39, 0x38, 0x1b, 0xeb, 0x19,
0x8e, 0xf2, 0xc8, 0x22, 0xe6, 0x77, 0x1d, 0xd3, 0xec, 0x8e, 0xc8, 0x69, 0xfb, 0x3b, 0x3d, 0x8b,
0xea, 0x70, 0xcf, 0xea, 0x8f, 0xce, 0x8e, 0x8f, 0xad, 0x8e, 0x65, 0xf6, 0xc7, 0xe4, 0xa8, 0xdd,
0x6b, 0xf7, 0x3b, 0xa6, 0x9e, 0x43, 0x7b, 0x80, 0xac, 0x7e, 0x67, 0x70, 0x3a, 0xec, 0x99, 0x63,
0x93, 0x44, 0x85, 0x71, 0x07, 0xd5, 0xa0, 0x2a, 0xe4, 0xb4, 0xbb, 0x5d, 0x72, 0xdc, 0xb6, 0x7a,
0x66, 0x57, 0xcf, 0x73, 0x4d, 0x14, 0xc7, 0x88, 0x74, 0xad, 0x51, 0xfb, 0x88, 0xc3, 0x05, 0x7e,
0xa6, 0xd5, 0x3f, 0x1f, 0x58, 0x1d, 0x93, 0x74, 0xb8, 0x58, 0x8e, 0x02, 0x67, 0x8e, 0xd0, 0xb3,
0x7e, 0xd7, 0xc4, 0xc3, 0xb6, 0xd5, 0xd5, 0x8b, 0x68, 0x1f, 0xee, 0x47, 0xb0, 0xf9, 0xdd, 0xd0,
0xc2, 0xdf, 0x93, 0xf1, 0x60, 0x40, 0x46, 0x83, 0x41, 0x5f, 0x2f, 0xc5, 0x25, 0x71, 0x6b, 0x07,
0x43, 0xb3, 0xaf, 0x97, 0xd1, 0x7d, 0xa8, 0x9d, 0x0e, 0x87, 0x24, 0xa2, 0x44, 0xc6, 0x56, 0x38,
0x7b, 0xbb, 0xdb, 0xc5, 0xe6, 0x68, 0x44, 0x4e, 0xad, 0xd1, 0x69, 0x7b, 0xdc, 0x39, 0xd1, 0xab,
0xdc, 0xa4, 0x91, 0x39, 0x26, 0xe3, 0xc1, 0xb8, 0xdd, 0xdb, 0xe0, 0x3a, 0x57, 0x68, 0x83, 0xf3,
0x43, 0x7b, 0x83, 0x6f, 0xf5, 0x5d, 0x7e, 0xe1, 0x1c, 0x1e, 0x9c, 0x2b, 0x15, 0x11, 0xb7, 0x5d,
0xb9, 0x27, 0x3a, 0x53, 0xaf, 0x71, 0xd0, 0xea, 0x9f, 0xb7, 0x7b, 0x56, 0x97, 0xbc, 0x34, 0xbf,
0x17, 0x8d, 0xe5, 0x1e, 0x07, 0xa5, 0x66, 0x64, 0x88, 0x07, 0xcf, 0xb9, 0x22, 0xfa, 0xbb, 0x08,
0x41, 0xa5, 0x63, 0xe1, 0xce, 0x59, 0xaf, 0x8d, 0x09, 0x1e, 0x9c, 0x8d, 0x4d, 0x7d, 0xef, 0xc9,
0x9f, 0x34, 0x28, 0xc5, 0x0b, 0x07, 0xf7, 0xba, 0xd5, 0x27, 0xc7, 0x3d, 0xeb, 0xf9, 0xc9, 0x58,
0x06, 0xc1, 0xe8, 0xac, 0xc3, 0x5d, 0x66, 0xf2, 0x86, 0x85, 0xa0, 0x22, 0x2f, 0x7d, 0x6d, 0x6c,
0x8a, 0x9f, 0xa5, 0xb0, 0xfe, 0x40, 0xc9, 0x4d, 0x73, 0xe5, 0x15, 0x68, 0x62, 0x3c, 0xc0, 0x7a,
0x06, 0x7d, 0x04, 0x4d, 0x85, 0x70, 0xbf, 0x62, 0x6c, 0x76, 0xc6, 0x64, 0xd8, 0xfe, 0xfe, 0x94,
0xbb, 0x5d, 0x06, 0xd9, 0x48, 0xcf, 0xa2, 0xf7, 0x61, 0x7f, 0xcd, 0xb5, 0x2d, 0x2e, 0x9e, 0x7c,
0x09, 0xf5, 0xbb, 0x82, 0x1e, 0x01, 0xe4, 0x46, 0xe6, 0x78, 0xdc, 0x33, 0x65, 0x93, 0x3d, 0x96,
0x81, 0x0b, 0x90, 0xc3, 0xe6, 0xe8, 0xec, 0xd4, 0xd4, 0x53, 0x87, 0x7f, 0xcd, 0x43, 0x4e, 0xbc,
0xfa, 0x02, 0xf4, 0x2b, 0x28, 0xc7, 0x7e, 0xd5, 0x38, 0x3f, 0x44, 0x0f, 0xdf, 0xf8, 0x7b, 0x47,
0x23, 0x9a, 0x0d, 0x15, 0xfc, 0x4c, 0x43, 0x47, 0x50, 0x89, 0x8f, 0xf7, 0xe7, 0x87, 0x28, 0xfe,
0x58, 0xda, 0x32, 0xf9, 0x6f, 0x91, 0xf1, 0x12, 0x74, 0x33, 0x64, 0xce, 0x82, 0xd7, 0x6c, 0x35,
0x80, 0xa3, 0x46, 0x3c, 0xc1, 0x93, 0x53, 0x7d, 0x63, 0x7f, 0x2b, 0x4d, 0x95, 0x9c, 0x6f, 0x78,
0x7f, 0x5c, 0x8f, 0xc0, 0xb7, 0x0c, 0x4a, 0xce, 0xdd, 0x8d, 0xf7, 0xee, 0x22, 0xab, 0xb1, 0x35,
0xfd, 0xfb, 0x14, 0xb7, 0xb1, 0x1c, 0xa3, 0x6d, 0xb9, 0xa5, 0x1b, 0x42, 0xb7, 0x74, 0x11, 0x34,
0x85, 0xda, 0x96, 0xf1, 0x18, 0x7d, 0x9c, 0xac, 0x63, 0x77, 0x0c, 0xd7, 0x8d, 0x47, 0x6f, 0x63,
0x53, 0xc6, 0x4f, 0xa1, 0xb6, 0x65, 0x8e, 0x4e, 0x9c, 0x72, 0xf7, 0x14, 0x9e, 0x38, 0xe5, 0x4d,
0xe3, 0xf8, 0x0f, 0xa0, 0xdf, 0x1c, 0xbb, 0x90, 0x71, 0x73, 0xef, 0xed, 0xf9, 0xaf, 0xf1, 0xe1,
0x1b, 0x79, 0x94, 0x70, 0x0b, 0x60, 0x33, 0xbc, 0xa0, 0x07, 0xb1, 0x2d, 0xb7, 0x86, 0xaf, 0xc6,
0xc3, 0x3b, 0xa8, 0x4a, 0xd4, 0x18, 0x6a, 0x5b, 0xa6, 0x99, 0xc4, 0x6d, 0xdc, 0x3d, 0xed, 0x34,
0xee, 0x6d, 0x7b, 0xf4, 0x3f, 0xd3, 0xd0, 0xa9, 0x0c, 0xb0, 0xe8, 0xa7, 0xba, 0xb7, 0x64, 0x4c,
0x7d, 0xfb, 0xe3, 0x64, 0x15, 0x8a, 0xd0, 0x7a, 0xa6, 0xa1, 0x01, 0x94, 0xe2, 0x59, 0xf2, 0xd6,
0xf4, 0x79, 0xab, 0xc0, 0x19, 0x54, 0x13, 0xcd, 0xd8, 0x0f, 0xd0, 0xe3, 0xdb, 0x83, 0xc3, 0xd6,
0x7e, 0x9d, 0x88, 0x80, 0x37, 0x3c, 0x53, 0x5a, 0xda, 0x33, 0xed, 0xe8, 0xb3, 0x5f, 0x3f, 0xbd,
0x74, 0xd8, 0x7c, 0x75, 0x71, 0x30, 0xf1, 0x17, 0x4f, 0xc5, 0x2f, 0x71, 0x9e, 0xe3, 0x5d, 0x7a,
0x94, 0xbd, 0xf6, 0x83, 0xab, 0xa7, 0xae, 0x37, 0x7d, 0x2a, 0xd2, 0xe0, 0xe9, 0x5a, 0xe4, 0x45,
0x4e, 0xfc, 0x10, 0xff, 0x93, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0x33, 0x56, 0x83, 0xe8, 0xb8,
0x17, 0x00, 0x00,
// 2580 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x59, 0x4b, 0x77, 0xdb, 0xc6,
0xf5, 0x0f, 0x48, 0x88, 0xa2, 0x2e, 0x1f, 0x82, 0x86, 0x8a, 0xc5, 0x3f, 0x65, 0x27, 0x0c, 0x93,
0xd8, 0x3c, 0xfe, 0x27, 0xb2, 0xa2, 0xf6, 0xb4, 0x69, 0xf3, 0x68, 0x28, 0x12, 0xb2, 0x60, 0x53,
0x24, 0x33, 0xa4, 0x9c, 0xa4, 0x59, 0x4c, 0x21, 0x72, 0x28, 0xa2, 0x02, 0x01, 0x16, 0x18, 0xda,
0xd1, 0xb2, 0xbb, 0x9e, 0x7e, 0x8a, 0xee, 0xba, 0xeb, 0x27, 0xe8, 0xa2, 0x8b, 0x7e, 0x8f, 0x6e,
0xbb, 0xef, 0x39, 0x5d, 0xf7, 0xcc, 0x03, 0x20, 0x20, 0x51, 0x76, 0x7b, 0xda, 0x8d, 0x4d, 0xfc,
0xee, 0x6f, 0xee, 0xdc, 0x99, 0xfb, 0x9a, 0x19, 0xc1, 0xbd, 0xc0, 0x5f, 0x32, 0x1a, 0x04, 0x8b,
0xf1, 0x13, 0xf9, 0xeb, 0x60, 0x11, 0xf8, 0xcc, 0x47, 0x5b, 0x31, 0x5e, 0xdb, 0x0a, 0x16, 0x63,
0x89, 0x36, 0xfe, 0x91, 0x03, 0x34, 0xa4, 0xde, 0x64, 0x60, 0x5f, 0xcf, 0xa9, 0xc7, 0x30, 0xfd,
0xcd, 0x92, 0x86, 0x0c, 0x21, 0xd0, 0x27, 0x34, 0x64, 0x55, 0xad, 0xae, 0x35, 0x8b, 0x58, 0xfc,
0x46, 0x06, 0x64, 0xed, 0x39, 0xab, 0x66, 0xea, 0x5a, 0x33, 0x8b, 0xf9, 0x4f, 0xf4, 0x7f, 0x90,
0xb7, 0xe7, 0x8c, 0xcc, 0x43, 0x9b, 0x55, 0x8b, 0x02, 0xde, 0xb4, 0xe7, 0xec, 0x2c, 0xb4, 0x19,
0x7a, 0x0f, 0x8a, 0x0b, 0xa9, 0x92, 0xcc, 0xec, 0x70, 0x56, 0xcd, 0x0a, 0x45, 0x05, 0x85, 0x9d,
0xda, 0xe1, 0x0c, 0x35, 0xc1, 0x98, 0x3a, 0x9e, 0xed, 0x92, 0xb1, 0xcb, 0x5e, 0x92, 0x09, 0x75,
0x99, 0x5d, 0xd5, 0xeb, 0x5a, 0x73, 0x03, 0x97, 0x05, 0xde, 0x76, 0xd9, 0xcb, 0x0e, 0x47, 0xd1,
0x23, 0xd8, 0x8e, 0x94, 0x05, 0xd2, 0xc0, 0xea, 0x46, 0x5d, 0x6b, 0x6e, 0xe1, 0xf2, 0x22, 0x6d,
0xf6, 0x23, 0xd8, 0x66, 0xce, 0x9c, 0xfa, 0x4b, 0x46, 0x42, 0x3a, 0xf6, 0xbd, 0x49, 0x58, 0xcd,
0x49, 0x8d, 0x0a, 0x1e, 0x4a, 0x14, 0x35, 0xa0, 0x34, 0xa5, 0x94, 0xb8, 0xce, 0xdc, 0x61, 0x84,
0x9b, 0xbf, 0x29, 0xcc, 0x2f, 0x4c, 0x29, 0xed, 0x72, 0x6c, 0x68, 0x33, 0xf4, 0x01, 0x94, 0x57,
0x1c, 0xb1, 0xc6, 0x92, 0x20, 0x15, 0x23, 0x92, 0x58, 0xe8, 0x01, 0x18, 0xfe, 0x92, 0x5d, 0xfa,
0x8e, 0x77, 0x49, 0xc6, 0x33, 0xdb, 0x23, 0xce, 0xa4, 0x9a, 0xaf, 0x6b, 0x4d, 0xfd, 0x58, 0xaf,
0x6a, 0x87, 0x1a, 0x2e, 0x47, 0xd2, 0xf6, 0xcc, 0xf6, 0xac, 0x09, 0x7a, 0x0c, 0x3b, 0x37, 0xf9,
0x61, 0xb5, 0x52, 0xcf, 0x36, 0x75, 0xbc, 0x9d, 0xa6, 0x86, 0xe8, 0x21, 0x6c, 0xbb, 0x76, 0xc8,
0xc8, 0xcc, 0x5f, 0x90, 0xc5, 0xf2, 0xe2, 0x8a, 0x5e, 0x57, 0xcb, 0x62, 0x1f, 0x4b, 0x1c, 0x3e,
0xf5, 0x17, 0x03, 0x01, 0xa2, 0x07, 0x00, 0x62, 0x0f, 0x85, 0xa9, 0xd5, 0x2d, 0xb1, 0xe2, 0x2d,
0x8e, 0x08, 0x33, 0xd1, 0x27, 0x50, 0x10, 0xbe, 0x27, 0x33, 0xc7, 0x63, 0x61, 0x15, 0xea, 0xd9,
0x66, 0xe1, 0xc8, 0x38, 0x70, 0x3d, 0x1e, 0x06, 0x98, 0x4b, 0x4e, 0x1d, 0x8f, 0x61, 0x08, 0xa2,
0x9f, 0x21, 0x9a, 0x40, 0x85, 0xfb, 0x9c, 0x8c, 0x97, 0x21, 0xf3, 0xe7, 0x24, 0xa0, 0x63, 0x3f,
0x98, 0x84, 0xd5, 0x82, 0x18, 0xfa, 0xe3, 0x83, 0x38, 0x94, 0x0e, 0x6e, 0xc7, 0xce, 0x41, 0x87,
0x86, 0xac, 0x2d, 0xc6, 0x61, 0x39, 0xcc, 0xf4, 0x58, 0x70, 0x8d, 0x77, 0x26, 0x37, 0x71, 0xf4,
0x11, 0x20, 0xdb, 0x75, 0xfd, 0x57, 0x24, 0xa4, 0xee, 0x94, 0x28, 0x5f, 0x56, 0xb7, 0xeb, 0x5a,
0x33, 0x8f, 0x0d, 0x21, 0x19, 0x52, 0x77, 0xaa, 0xd4, 0xa3, 0x9f, 0x40, 0x49, 0xd8, 0x34, 0xa5,
0x36, 0x5b, 0x06, 0x34, 0xac, 0x1a, 0xf5, 0x6c, 0xb3, 0x7c, 0xb4, 0xa3, 0x16, 0x72, 0x22, 0xe1,
0x63, 0x87, 0xe1, 0x22, 0xe7, 0xa9, 0xef, 0x10, 0xed, 0xc3, 0xd6, 0xdc, 0xfe, 0x81, 0x2c, 0xec,
0x80, 0x85, 0xd5, 0x9d, 0xba, 0xd6, 0x2c, 0xe1, 0xfc, 0xdc, 0xfe, 0x61, 0xc0, 0xbf, 0xd1, 0x01,
0x54, 0x3c, 0x9f, 0x38, 0xde, 0xd4, 0x75, 0x2e, 0x67, 0x8c, 0x2c, 0x17, 0x13, 0x9b, 0xd1, 0xb0,
0x8a, 0x84, 0x0d, 0x3b, 0x9e, 0x6f, 0x29, 0xc9, 0xb9, 0x14, 0xd4, 0x3a, 0x70, 0x6f, 0xfd, 0xfa,
0x78, 0x7a, 0x70, 0x07, 0xf1, 0x8c, 0xd1, 0x31, 0xff, 0x89, 0x76, 0x61, 0xe3, 0xa5, 0xed, 0x2e,
0xa9, 0x48, 0x99, 0x22, 0x96, 0x1f, 0x3f, 0xcf, 0x7c, 0xaa, 0x35, 0x66, 0x50, 0x19, 0x05, 0xf6,
0xf8, 0xea, 0x46, 0xd6, 0xdd, 0x4c, 0x1a, 0xed, 0x76, 0xd2, 0xdc, 0x61, 0x6f, 0xe6, 0x0e, 0x7b,
0x1b, 0x5f, 0xc2, 0xb6, 0xf0, 0xf0, 0x09, 0xa5, 0xaf, 0xcb, 0xed, 0x3d, 0xe0, 0x99, 0x2b, 0x32,
0x41, 0xe6, 0x77, 0xce, 0x9e, 0xf3, 0x24, 0x68, 0x4c, 0xc0, 0x58, 0x8d, 0x0f, 0x17, 0xbe, 0x17,
0x52, 0x9e, 0xb8, 0x3c, 0x00, 0x78, 0x04, 0xf3, 0x04, 0x11, 0xa9, 0xa1, 0x89, 0x51, 0x65, 0x85,
0x9f, 0x50, 0x2a, 0x92, 0xe3, 0xa1, 0xcc, 0x47, 0xe2, 0xfa, 0xe3, 0x2b, 0x9e, 0xe1, 0xf6, 0xb5,
0x52, 0x5f, 0xe2, 0x70, 0xd7, 0x1f, 0x5f, 0x75, 0x38, 0xd8, 0xf8, 0x5e, 0x16, 0xa1, 0x91, 0x2f,
0xe6, 0xfa, 0x0f, 0xb6, 0xa3, 0x01, 0x1b, 0x22, 0x16, 0x85, 0xda, 0xc2, 0x51, 0x31, 0x19, 0xd4,
0x58, 0x8a, 0x1a, 0xdf, 0x43, 0x25, 0xa5, 0x5c, 0xad, 0xa2, 0x06, 0xf9, 0x45, 0x40, 0x9d, 0xb9,
0x7d, 0x49, 0x95, 0xe6, 0xf8, 0x1b, 0x35, 0x61, 0x73, 0x6a, 0x3b, 0xee, 0x32, 0x88, 0x14, 0x97,
0xa3, 0x20, 0x93, 0x28, 0x8e, 0xc4, 0x8d, 0xfb, 0x50, 0xc3, 0x34, 0xa4, 0xec, 0xcc, 0x09, 0x43,
0xc7, 0xf7, 0xda, 0xbe, 0xc7, 0x02, 0xdf, 0x55, 0x2b, 0x68, 0x3c, 0x80, 0xfd, 0xb5, 0x52, 0x69,
0x02, 0x1f, 0xfc, 0xf5, 0x92, 0x06, 0xd7, 0xeb, 0x07, 0x7f, 0x0d, 0xfb, 0x6b, 0xa5, 0xca, 0xfe,
0x8f, 0x60, 0x63, 0x61, 0x3b, 0x01, 0xf7, 0x3d, 0x4f, 0xca, 0x7b, 0x89, 0xa4, 0x1c, 0xd8, 0x4e,
0x70, 0xea, 0x84, 0xcc, 0x0f, 0xae, 0xb1, 0x24, 0x3d, 0xd3, 0xf3, 0x9a, 0x91, 0x69, 0xfc, 0x5e,
0x83, 0x42, 0x42, 0xc8, 0x53, 0xc3, 0xf3, 0x27, 0x94, 0x4c, 0x03, 0x7f, 0x1e, 0x6d, 0x02, 0x07,
0x4e, 0x02, 0x7f, 0xce, 0x63, 0x42, 0x08, 0x99, 0xaf, 0x02, 0x38, 0xc7, 0x3f, 0x47, 0x3e, 0xfa,
0x18, 0x36, 0x67, 0x52, 0x81, 0x28, 0x9b, 0x85, 0xa3, 0xca, 0x8d, 0xb9, 0x3b, 0x36, 0xb3, 0x71,
0xc4, 0x79, 0xa6, 0xe7, 0xb3, 0x86, 0xfe, 0x4c, 0xcf, 0xeb, 0xc6, 0xc6, 0x33, 0x3d, 0xbf, 0x61,
0xe4, 0x9e, 0xe9, 0xf9, 0x9c, 0xb1, 0xd9, 0xf8, 0xbb, 0x06, 0xf9, 0x88, 0xcd, 0x2d, 0xe1, 0x5b,
0x4a, 0x78, 0x5c, 0xa8, 0x60, 0xca, 0x73, 0x60, 0xe4, 0xcc, 0x29, 0xaa, 0x43, 0x51, 0x08, 0xd3,
0x21, 0x0a, 0x1c, 0x6b, 0x89, 0x30, 0x15, 0xf5, 0x3c, 0x62, 0x88, 0x78, 0xd4, 0x55, 0x3d, 0x97,
0x94, 0xa8, 0x25, 0x85, 0xcb, 0xf1, 0x98, 0x86, 0xa1, 0x9c, 0x65, 0x43, 0x52, 0x14, 0x26, 0x26,
0x7a, 0x08, 0xdb, 0x11, 0x25, 0x9a, 0x2b, 0x27, 0xe3, 0x55, 0xc1, 0x6a, 0xba, 0x26, 0x18, 0x49,
0xde, 0x7c, 0xd5, 0x41, 0xca, 0x2b, 0x22, 0x9f, 0x54, 0x2e, 0xbe, 0xf1, 0x6b, 0xd8, 0x13, 0xae,
0x1c, 0x04, 0xfe, 0x85, 0x7d, 0xe1, 0xb8, 0x0e, 0xbb, 0x8e, 0x82, 0x9c, 0x2f, 0x3c, 0xf0, 0xe7,
0x84, 0xef, 0x6d, 0xe4, 0x02, 0x0e, 0xf4, 0xfc, 0x09, 0xe5, 0x2e, 0x60, 0xbe, 0x14, 0x29, 0x17,
0x30, 0x5f, 0x08, 0x92, 0x9d, 0x37, 0x9b, 0xea, 0xbc, 0x8d, 0x2b, 0xa8, 0xde, 0x9e, 0x4b, 0xc5,
0x4c, 0x1d, 0x0a, 0x8b, 0x15, 0x2c, 0xa6, 0xd3, 0x70, 0x12, 0x4a, 0xfa, 0x36, 0xf3, 0x66, 0xdf,
0x36, 0xfe, 0xa8, 0xc1, 0xce, 0xf1, 0xd2, 0x71, 0x27, 0xa9, 0xc4, 0x4d, 0x5a, 0xa7, 0xa5, 0xcf,
0x05, 0xeb, 0x9a, 0x7e, 0x66, 0x6d, 0xd3, 0xff, 0x68, 0x4d, 0x63, 0xcd, 0x8a, 0xc6, 0x9a, 0x59,
0xd3, 0x56, 0xdf, 0x85, 0xc2, 0xaa, 0x4b, 0x86, 0x55, 0xbd, 0x9e, 0x6d, 0x16, 0x31, 0xcc, 0xa2,
0x16, 0x19, 0x36, 0x3e, 0x05, 0x94, 0x34, 0x54, 0x6d, 0x48, 0x5c, 0x3f, 0xb4, 0xbb, 0xeb, 0xc7,
0x7d, 0xa8, 0x0d, 0x97, 0x17, 0xe1, 0x38, 0x70, 0x2e, 0xe8, 0x29, 0x73, 0xc7, 0xe6, 0x4b, 0xea,
0xb1, 0x30, 0xca, 0xd2, 0x7f, 0xea, 0xb0, 0x15, 0xa3, 0xbc, 0x3c, 0x3b, 0xde, 0xd8, 0x9f, 0x47,
0x46, 0x7b, 0xd4, 0xe5, 0x76, 0xcb, 0xa6, 0xb0, 0x13, 0x89, 0xda, 0x52, 0x62, 0x4d, 0x38, 0x3f,
0xb5, 0x48, 0xc5, 0xcf, 0x48, 0x7e, 0x72, 0x8d, 0x92, 0xdf, 0x04, 0x23, 0xd6, 0x3f, 0x63, 0xee,
0x38, 0xde, 0x14, 0x5c, 0x8e, 0x70, 0x6e, 0x8c, 0x64, 0xc6, 0x9a, 0x23, 0xa6, 0x2e, 0x99, 0x11,
0xae, 0x98, 0xef, 0x41, 0x91, 0xe7, 0x43, 0xc8, 0xec, 0xf9, 0x82, 0x78, 0xa1, 0xc8, 0x0b, 0x1d,
0x17, 0x62, 0xac, 0x17, 0xa2, 0x2f, 0x00, 0x28, 0x5f, 0x1f, 0x61, 0xd7, 0x0b, 0x2a, 0x52, 0xa2,
0x7c, 0xf4, 0x4e, 0x22, 0x30, 0xe2, 0x0d, 0x38, 0x10, 0xff, 0x8e, 0xae, 0x17, 0x14, 0x6f, 0xd1,
0xe8, 0x27, 0xfa, 0x12, 0x4a, 0x53, 0x3f, 0x78, 0x65, 0x07, 0x13, 0x22, 0x40, 0x55, 0x36, 0xf6,
0x12, 0x1a, 0x4e, 0xa4, 0x5c, 0x0c, 0x3f, 0x7d, 0x0b, 0x17, 0xa7, 0x89, 0x6f, 0xf4, 0x1c, 0x50,
0x34, 0x5e, 0x64, 0xb9, 0x54, 0x92, 0x17, 0x4a, 0xf6, 0x6f, 0x2b, 0xe1, 0x45, 0x3a, 0x52, 0x64,
0x4c, 0x6f, 0x60, 0xe8, 0x33, 0x28, 0x86, 0x94, 0x31, 0x97, 0x2a, 0x35, 0x5b, 0x42, 0xcd, 0xbd,
0xd4, 0x99, 0x86, 0x8b, 0x23, 0x0d, 0x85, 0x70, 0xf5, 0x89, 0x8e, 0x61, 0xdb, 0x75, 0xbc, 0xab,
0xa4, 0x19, 0x20, 0xc6, 0x57, 0x13, 0xe3, 0xbb, 0x8e, 0x77, 0x95, 0xb4, 0xa1, 0xe4, 0x26, 0x81,
0xc6, 0xe7, 0xb0, 0x15, 0xef, 0x12, 0x2a, 0xc0, 0xe6, 0x79, 0xef, 0x79, 0xaf, 0xff, 0x4d, 0xcf,
0x78, 0x0b, 0xe5, 0x41, 0x1f, 0x9a, 0xbd, 0x8e, 0xa1, 0x71, 0x18, 0x9b, 0x6d, 0xd3, 0x7a, 0x61,
0x1a, 0x19, 0xfe, 0x71, 0xd2, 0xc7, 0xdf, 0xb4, 0x70, 0xc7, 0xc8, 0x1e, 0x6f, 0xc2, 0x86, 0x98,
0xb7, 0xf1, 0x67, 0x0d, 0xf2, 0xc2, 0x83, 0xde, 0xd4, 0x47, 0xff, 0x0f, 0x71, 0x70, 0x89, 0xe2,
0xc6, 0x1b, 0xae, 0x88, 0xba, 0x12, 0x8e, 0x03, 0x66, 0xa4, 0x70, 0x4e, 0x8e, 0x43, 0x23, 0x26,
0x67, 0x24, 0x39, 0x12, 0xc4, 0xe4, 0xc7, 0x09, 0xcd, 0xa9, 0x92, 0xa3, 0xe3, 0xed, 0x48, 0x10,
0x55, 0xd8, 0xe4, 0xd9, 0x36, 0x55, 0x89, 0x13, 0x67, 0x5b, 0xc5, 0x6d, 0xfc, 0x14, 0x8a, 0x49,
0x9f, 0xa3, 0x47, 0xa0, 0x3b, 0xde, 0xd4, 0x57, 0x89, 0x58, 0xb9, 0x11, 0x5c, 0x7c, 0x91, 0x58,
0x10, 0x1a, 0x08, 0x8c, 0x9b, 0x7e, 0x6e, 0x94, 0xa0, 0x90, 0x70, 0x5a, 0xe3, 0x6f, 0x1a, 0x94,
0x52, 0x4e, 0xf8, 0xb7, 0xb5, 0xa3, 0x2f, 0xa0, 0xf8, 0xca, 0x09, 0x28, 0x49, 0xb6, 0xff, 0xf2,
0x51, 0x2d, 0xdd, 0xfe, 0xa3, 0xff, 0xdb, 0xfe, 0x84, 0xe2, 0x02, 0xe7, 0x2b, 0x00, 0xfd, 0x02,
0xca, 0x6a, 0x24, 0x99, 0x50, 0x66, 0x3b, 0xae, 0xd8, 0xaa, 0x72, 0x2a, 0x3c, 0x14, 0xb7, 0x23,
0xe4, 0xb8, 0x34, 0x4d, 0x7e, 0xa2, 0x0f, 0x57, 0x0a, 0x42, 0x16, 0x38, 0xde, 0xa5, 0xd8, 0xbf,
0xad, 0x98, 0x36, 0x14, 0x20, 0x6f, 0xe4, 0x25, 0x75, 0x78, 0x1c, 0x32, 0x9b, 0x2d, 0x43, 0xf4,
0x31, 0x6c, 0x84, 0xcc, 0x56, 0x95, 0xac, 0x9c, 0xca, 0xad, 0x04, 0x91, 0x62, 0xc9, 0x4a, 0x9d,
0x7e, 0x32, 0xb7, 0x4e, 0x3f, 0x1b, 0xbc, 0x62, 0xc8, 0x2a, 0x5a, 0x38, 0x42, 0x6a, 0xf1, 0xa7,
0xa3, 0x6e, 0xbb, 0xc5, 0x18, 0x9d, 0x2f, 0x18, 0x96, 0x04, 0xd5, 0xdd, 0xbe, 0x04, 0x68, 0x3b,
0xc1, 0x78, 0xe9, 0xb0, 0xe7, 0xf4, 0x9a, 0xf7, 0xac, 0xa8, 0x5c, 0xcb, 0xb2, 0x97, 0x1b, 0xcb,
0x12, 0xbd, 0x07, 0x9b, 0x51, 0x21, 0x92, 0xf5, 0x2d, 0x37, 0x13, 0x05, 0xa8, 0xf1, 0x07, 0x1d,
0xf6, 0x95, 0x4b, 0xa5, 0x37, 0x18, 0x0d, 0xc6, 0x74, 0x11, 0x1f, 0x8b, 0x9f, 0xc2, 0xee, 0xaa,
0xa8, 0xca, 0x89, 0x48, 0x74, 0xd4, 0x2e, 0x1c, 0xbd, 0x9d, 0x58, 0xe9, 0xca, 0x0c, 0x8c, 0xe2,
0x62, 0xbb, 0x32, 0xed, 0x30, 0xa1, 0xc8, 0x9e, 0xfb, 0x4b, 0x4f, 0x85, 0xa8, 0xac, 0x78, 0x68,
0x15, 0xce, 0x5c, 0x24, 0x22, 0xfa, 0x11, 0xc4, 0x41, 0x4e, 0xe8, 0x0f, 0x0b, 0x27, 0xb8, 0x16,
0xd5, 0xaf, 0xb4, 0x2a, 0xb7, 0xa6, 0x40, 0x6f, 0x9d, 0x55, 0x33, 0xb7, 0xcf, 0xaa, 0x9f, 0x41,
0x2d, 0xce, 0x0e, 0x75, 0x8d, 0xa5, 0x93, 0xb8, 0xb5, 0x6d, 0x0a, 0x1b, 0xf6, 0x22, 0x06, 0x8e,
0x08, 0xaa, 0xbf, 0x1d, 0xc2, 0x6e, 0x22, 0xb5, 0x56, 0xa6, 0xcb, 0x4c, 0x44, 0xab, 0xec, 0x4a,
0x9a, 0x1e, 0x8f, 0x50, 0xa6, 0xeb, 0xd2, 0xf4, 0x08, 0x56, 0xa6, 0xff, 0x0a, 0xca, 0x37, 0xae,
0x79, 0x79, 0xe1, 0xf7, 0x9f, 0xdd, 0xae, 0xac, 0xeb, 0xdc, 0x73, 0xb0, 0xe6, 0xae, 0x57, 0x1a,
0x27, 0xb1, 0xda, 0x57, 0x80, 0xfe, 0xcb, 0x0b, 0xd3, 0x5f, 0x34, 0xb8, 0xbf, 0xde, 0x06, 0xd5,
0xc8, 0xff, 0x67, 0x31, 0xf2, 0x19, 0xe4, 0xec, 0x31, 0x73, 0x7c, 0x4f, 0xa5, 0xfe, 0xfb, 0x89,
0xa1, 0x98, 0x86, 0xbe, 0xfb, 0x92, 0x9e, 0xfa, 0xee, 0x44, 0x19, 0xd3, 0x12, 0x54, 0xac, 0x86,
0xa4, 0xb2, 0x2a, 0x9b, 0xce, 0xaa, 0xc7, 0xbf, 0xd5, 0xa1, 0x94, 0x4a, 0xfd, 0x74, 0xed, 0x2f,
0xc1, 0x56, 0xaf, 0x4f, 0x3a, 0xe6, 0xa8, 0x65, 0x75, 0x0d, 0x0d, 0x19, 0x50, 0xec, 0xf7, 0xac,
0x7e, 0x8f, 0x74, 0xcc, 0x76, 0xbf, 0xc3, 0xbb, 0xc0, 0xdb, 0xb0, 0xd3, 0xb5, 0x7a, 0xcf, 0x49,
0xaf, 0x3f, 0x22, 0x66, 0xd7, 0x7a, 0x6a, 0x1d, 0x77, 0x4d, 0x23, 0x8b, 0x76, 0xc1, 0xe8, 0xf7,
0x48, 0xfb, 0xb4, 0x65, 0xf5, 0xc8, 0xc8, 0x3a, 0x33, 0xfb, 0xe7, 0x23, 0x43, 0xe7, 0x28, 0x4f,
0x57, 0x62, 0x7e, 0xdb, 0x36, 0xcd, 0xce, 0x90, 0x9c, 0xb5, 0xbe, 0x35, 0x36, 0x50, 0x15, 0x76,
0xad, 0xde, 0xf0, 0xfc, 0xe4, 0xc4, 0x6a, 0x5b, 0x66, 0x6f, 0x44, 0x8e, 0x5b, 0xdd, 0x56, 0xaf,
0x6d, 0x1a, 0x39, 0x74, 0x0f, 0x90, 0xd5, 0x6b, 0xf7, 0xcf, 0x06, 0x5d, 0x73, 0x64, 0x92, 0xa8,
0xdb, 0x6c, 0xa2, 0x0a, 0x6c, 0x0b, 0x3d, 0xad, 0x4e, 0x87, 0x9c, 0xb4, 0xac, 0xae, 0xd9, 0x31,
0xf2, 0xdc, 0x12, 0xc5, 0x18, 0x92, 0x8e, 0x35, 0x6c, 0x1d, 0x73, 0x78, 0x8b, 0xcf, 0x69, 0xf5,
0x5e, 0xf4, 0xad, 0xb6, 0x49, 0xda, 0x5c, 0x2d, 0x47, 0x81, 0x93, 0x23, 0xf4, 0xbc, 0xd7, 0x31,
0xf1, 0xa0, 0x65, 0x75, 0x8c, 0x02, 0xda, 0x87, 0xbd, 0x08, 0x36, 0xbf, 0x1d, 0x58, 0xf8, 0x3b,
0x32, 0xea, 0xf7, 0xc9, 0xb0, 0xdf, 0xef, 0x19, 0xc5, 0xa4, 0x26, 0xbe, 0xda, 0xfe, 0xc0, 0xec,
0x19, 0x25, 0xb4, 0x07, 0x95, 0xb3, 0xc1, 0x80, 0x44, 0x92, 0x68, 0xb1, 0x65, 0x4e, 0x6f, 0x75,
0x3a, 0xd8, 0x1c, 0x0e, 0xc9, 0x99, 0x35, 0x3c, 0x6b, 0x8d, 0xda, 0xa7, 0xc6, 0x36, 0x5f, 0xd2,
0xd0, 0x1c, 0x91, 0x51, 0x7f, 0xd4, 0xea, 0xae, 0x70, 0x83, 0x1b, 0xb4, 0xc2, 0xf9, 0xa4, 0xdd,
0xfe, 0x37, 0xc6, 0x0e, 0xdf, 0x70, 0x0e, 0xf7, 0x5f, 0x28, 0x13, 0x11, 0x5f, 0xbb, 0x72, 0x4f,
0x34, 0xa7, 0x51, 0xe1, 0xa0, 0xd5, 0x7b, 0xd1, 0xea, 0x5a, 0x1d, 0xf2, 0xdc, 0xfc, 0x4e, 0x74,
0xeb, 0x5d, 0x0e, 0x4a, 0xcb, 0xc8, 0x00, 0xf7, 0x9f, 0x72, 0x43, 0x8c, 0xb7, 0x11, 0x82, 0x72,
0xdb, 0xc2, 0xed, 0xf3, 0x6e, 0x0b, 0x13, 0xdc, 0x3f, 0x1f, 0x99, 0xc6, 0xbd, 0xc7, 0x7f, 0xd2,
0xa0, 0x98, 0xac, 0xc6, 0xdc, 0xeb, 0x56, 0x8f, 0x9c, 0x74, 0xad, 0xa7, 0xa7, 0x23, 0x19, 0x04,
0xc3, 0xf3, 0x36, 0x77, 0x99, 0xc9, 0x4f, 0x01, 0x08, 0xca, 0x72, 0xd3, 0xe3, 0xc5, 0x66, 0xf8,
0x5c, 0x0a, 0xeb, 0xf5, 0x95, 0xde, 0x2c, 0x37, 0x5e, 0x81, 0x26, 0xc6, 0x7d, 0x6c, 0xe8, 0xe8,
0x03, 0xa8, 0x2b, 0x84, 0xfb, 0x15, 0x63, 0xb3, 0x3d, 0x22, 0x83, 0xd6, 0x77, 0x67, 0xdc, 0xed,
0x32, 0xc8, 0x86, 0xc6, 0x06, 0x7a, 0x17, 0xf6, 0x63, 0xd6, 0xba, 0xb8, 0x78, 0xfc, 0x39, 0x54,
0xef, 0x0a, 0x7a, 0x04, 0x90, 0x1b, 0x9a, 0xa3, 0x51, 0xd7, 0x94, 0x27, 0x97, 0x13, 0x19, 0xb8,
0x00, 0x39, 0x6c, 0x0e, 0xcf, 0xcf, 0x4c, 0x23, 0x73, 0xf4, 0xd7, 0x3c, 0xe4, 0xc4, 0x51, 0x3a,
0x40, 0x5f, 0x41, 0x29, 0xf1, 0x54, 0xf4, 0xe2, 0x08, 0x3d, 0x78, 0xed, 0x23, 0x52, 0x2d, 0xba,
0x70, 0x2b, 0xf8, 0x50, 0x43, 0xc7, 0x50, 0x4e, 0xbe, 0x99, 0xbc, 0x38, 0x42, 0xc9, 0x13, 0xe8,
0x9a, 0xe7, 0x94, 0x35, 0x3a, 0x9e, 0x83, 0x61, 0x86, 0xcc, 0x99, 0xf3, 0x46, 0xa8, 0x5e, 0x35,
0x50, 0x2d, 0x99, 0xe0, 0xe9, 0xa7, 0x92, 0xda, 0xfe, 0x5a, 0x99, 0x2a, 0x39, 0x5f, 0xf3, 0x43,
0x47, 0xfc, 0xae, 0x70, 0x6b, 0x41, 0xe9, 0xc7, 0x8c, 0xda, 0x3b, 0x77, 0x89, 0xd5, 0x5b, 0x40,
0xf6, 0x77, 0x19, 0xbe, 0xc6, 0x52, 0x42, 0xb6, 0x66, 0x97, 0x6e, 0x28, 0x5d, 0xd3, 0x9a, 0xd1,
0x04, 0x2a, 0x6b, 0xde, 0x1c, 0xd0, 0x87, 0xe9, 0x3a, 0x76, 0xc7, 0x8b, 0x45, 0xed, 0xe1, 0x9b,
0x68, 0x6a, 0xf1, 0x13, 0xa8, 0xac, 0x79, 0x9c, 0x48, 0xcd, 0x72, 0xf7, 0xd3, 0x46, 0x6a, 0x96,
0xd7, 0xbd, 0x71, 0x7c, 0x0f, 0xc6, 0xcd, 0xbb, 0x2c, 0x6a, 0xdc, 0x1c, 0x7b, 0xfb, 0x52, 0x5d,
0x7b, 0xff, 0xb5, 0x1c, 0xa5, 0xdc, 0x02, 0x58, 0xdd, 0x08, 0xd1, 0xfd, 0xc4, 0x90, 0x5b, 0x37,
0xda, 0xda, 0x83, 0x3b, 0xa4, 0x4a, 0xd5, 0x08, 0x2a, 0x6b, 0xae, 0x88, 0xa9, 0xdd, 0xb8, 0xfb,
0x0a, 0x59, 0xdb, 0x5d, 0x77, 0x93, 0x3a, 0xd4, 0xd0, 0x99, 0x0c, 0xb0, 0xe8, 0xfd, 0xf3, 0x0d,
0x19, 0x53, 0x5d, 0x7f, 0xe2, 0x5b, 0x86, 0x22, 0xb4, 0x0e, 0x35, 0xd4, 0x87, 0x62, 0x32, 0x4b,
0xde, 0x98, 0x3e, 0x6f, 0x54, 0x38, 0x85, 0xed, 0x54, 0x33, 0xf6, 0x03, 0xf4, 0xe8, 0x8d, 0x67,
0x06, 0xb9, 0x63, 0xa9, 0x08, 0x78, 0xcd, 0xe1, 0xa2, 0xa9, 0x1d, 0x6a, 0xc7, 0x9f, 0xfc, 0xf2,
0xc9, 0xa5, 0xc3, 0x66, 0xcb, 0x8b, 0x83, 0xb1, 0x3f, 0x7f, 0x22, 0x9e, 0x37, 0x3d, 0xc7, 0xbb,
0xf4, 0x28, 0x7b, 0xe5, 0x07, 0x57, 0x4f, 0x5c, 0x6f, 0xf2, 0x44, 0xa4, 0xc1, 0x93, 0x58, 0xe5,
0x45, 0x4e, 0xfc, 0x75, 0xe3, 0x47, 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x4a, 0x9f, 0xe0, 0x07,
0x0d, 0x19, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -605,17 +605,32 @@ message ForwardHtlcInterceptRequest {
*/
CircuitKey incoming_circuit_key = 1;
// The incoming htlc amount.
uint64 incoming_amount_msat = 5;
// The incoming htlc expiry.
uint32 incoming_expiry = 6;
/*
The htlc payment hash. This value is not guaranteed to be unique per
request.
*/
bytes htlc_payment_hash = 2;
bytes payment_hash = 2;
/// The htlc amount.
uint64 amount_msat = 3;
// The requested outgoing channel id for this forwarded htlc. Because of
// non-strict forwarding, this isn't necessarily the channel over which the
// packet will be forwarded eventually. A different channel to the same peer
// may be selected as well.
uint64 outgoing_requested_chan_id = 7;
/// The htlc expiry.
uint32 expiry = 4;
// The outgoing htlc amount.
uint64 outgoing_amount_msat = 3;
// The outgoing htlc expiry.
uint32 outgoing_expiry = 4;
// Any custom records that were present in the payload.
map<uint64, bytes> custom_records = 8;
}
/**

View File

@ -907,20 +907,43 @@
"$ref": "#/definitions/routerrpcCircuitKey",
"description": "The key of this forwarded htlc. It defines the incoming channel id and\nthe index in this channel."
},
"htlc_payment_hash": {
"incoming_amount_msat": {
"type": "string",
"format": "uint64",
"description": "The incoming htlc amount."
},
"incoming_expiry": {
"type": "integer",
"format": "int64",
"description": "The incoming htlc expiry."
},
"payment_hash": {
"type": "string",
"format": "byte",
"description": "The htlc payment hash. This value is not guaranteed to be unique per\nrequest."
},
"amount_msat": {
"outgoing_requested_chan_id": {
"type": "string",
"format": "uint64",
"description": "/ The htlc amount."
"description": "The requested outgoing channel id for this forwarded htlc. Because of\nnon-strict forwarding, this isn't necessarily the channel over which the\npacket will be forwarded eventually. A different channel to the same peer\nmay be selected as well."
},
"expiry": {
"outgoing_amount_msat": {
"type": "string",
"format": "uint64",
"description": "The outgoing htlc amount."
},
"outgoing_expiry": {
"type": "integer",
"format": "int64",
"description": "/ The htlc expiry."
"description": "The outgoing htlc expiry."
},
"custom_records": {
"type": "object",
"additionalProperties": {
"type": "string",
"format": "byte"
},
"description": "Any custom records that were present in the payload."
}
}
},

View File

@ -16,10 +16,16 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var (
customTestKey uint64 = 394829
customTestValue = []byte{1, 3, 5}
)
type interceptorTestCase struct {
amountMsat int64
invoice *lnrpc.Invoice
@ -133,6 +139,25 @@ func testForwardInterceptor(net *lntest.NetworkHarness, t *harnessTest) {
for i := 0; i < len(testCases); i++ {
select {
case request := <-interceptedChan:
// Assert sanity of informational packet data.
require.NotZero(t.t, request.OutgoingRequestedChanId)
require.NotZero(t.t, request.IncomingExpiry)
require.NotZero(t.t, request.IncomingAmountMsat)
require.Less(
t.t,
request.OutgoingExpiry, request.IncomingExpiry,
)
require.Less(
t.t,
request.OutgoingAmountMsat,
request.IncomingAmountMsat,
)
value, ok := request.CustomRecords[customTestKey]
require.True(t.t, ok, "expected custom record")
require.Equal(t.t, customTestValue, value)
testCase := testCases[i]
// For held packets we ignore, keeping them in hold status.
@ -353,6 +378,11 @@ func (c *interceptorTestContext) sendAliceToCarolPayment(ctx context.Context,
Route: route,
}
// Send a custom record to the forwarding node.
route.Hops[0].CustomRecords = map[uint64][]byte{
customTestKey: customTestValue,
}
// Send the payment.
return c.alice.RouterClient.SendToRouteV2(ctx, sendReq)
}