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.
This commit is contained in:
parent
46f5fc7400
commit
e9bd691e6a
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +81,12 @@ var (
|
||||
), lnwire.Features,
|
||||
)
|
||||
|
||||
mppFeatures = lnwire.NewRawFeatureVector(
|
||||
lnwire.TLVOnionPayloadOptional,
|
||||
lnwire.PaymentAddrOptional,
|
||||
lnwire.MPPOptional,
|
||||
)
|
||||
|
||||
unknownRequiredFeatures = lnwire.NewFeatureVector(
|
||||
lnwire.NewRawFeatureVector(100), lnwire.Features,
|
||||
)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ func (m *SessionSource) NewPaymentSession(p *LightningPayment) (
|
||||
getRoutingGraph: m.getRoutingGraph,
|
||||
pathFindingConfig: m.PathFindingConfig,
|
||||
missionControl: m.MissionControl,
|
||||
minShardAmt: DefaultShardMinAmt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user