diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 031f0143..f9d0f433 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -566,42 +566,63 @@ func (m *Failure) GetFlags() uint32 { } type ChannelUpdate struct { - // Signature is used to validate the announced data and prove the - // ownership of node id. + //* + //The signature that validates the announced data and proves the ownership + //of node id. Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` - // ChainHash denotes the target chain that this channel was opened - // within. This value should be the genesis hash of the target chain. - // Along with the short channel ID, this uniquely identifies the - // channel globally in a blockchain. + //* + //The target chain that this channel was opened within. This value + //should be the genesis hash of the target chain. Along with the short + //channel ID, this uniquely identifies the channel globally in a + //blockchain. ChainHash []byte `protobuf:"bytes,2,opt,name=chain_hash,json=chainHash,proto3" json:"chain_hash,omitempty"` - // ShortChannelID is the unique description of the funding transaction. + //* + //The unique description of the funding transaction. ChanId uint64 `protobuf:"varint,3,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` - // Timestamp allows ordering in the case of multiple announcements. We - // should ignore the message if timestamp is not greater than - // the last-received. + //* + //A timestamp that allows ordering in the case of multiple announcements. + //We should ignore the message if timestamp is not greater than the + //last-received. Timestamp uint32 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - // Flags is a bitfield that describes additional meta-data concerning - // how the update is to be interpreted. Currently, the - // least-significant bit must be set to 0 if the creating node - // corresponds to the first node in the previously sent channel - // announcement and 1 otherwise. If the second bit is set, then the - // channel is set to be disabled. + //* + //The bitfield that describes whether optional fields are present in this + //update. Currently, the least-significant bit must be set to 1 if the + //optional field MaxHtlc is present. + MessageFlags uint32 `protobuf:"varint,10,opt,name=message_flags,json=messageFlags,proto3" json:"message_flags,omitempty"` + //* + //The bitfield that describes additional meta-data concerning how the + //update is to be interpreted. Currently, the least-significant bit must be + //set to 0 if the creating node corresponds to the first node in the + //previously sent channel announcement and 1 otherwise. If the second bit + //is set, then the channel is set to be disabled. ChannelFlags uint32 `protobuf:"varint,5,opt,name=channel_flags,json=channelFlags,proto3" json:"channel_flags,omitempty"` - // TimeLockDelta is the minimum number of blocks this node requires to - // be added to the expiry of HTLCs. This is a security parameter - // determined by the node operator. This value represents the required - // gap between the time locks of the incoming and outgoing HTLC's set - // to this node. + //* + //The minimum number of blocks this node requires to be added to the expiry + //of HTLCs. This is a security parameter determined by the node operator. + //This value represents the required gap between the time locks of the + //incoming and outgoing HTLC's set to this node. TimeLockDelta uint32 `protobuf:"varint,6,opt,name=time_lock_delta,json=timeLockDelta,proto3" json:"time_lock_delta,omitempty"` - // HtlcMinimumMsat is the minimum HTLC value which will be accepted. + //* + //The minimum HTLC value which will be accepted. HtlcMinimumMsat uint64 `protobuf:"varint,7,opt,name=htlc_minimum_msat,json=htlcMinimumMsat,proto3" json:"htlc_minimum_msat,omitempty"` - // BaseFee is the base fee that must be used for incoming HTLC's to - // this particular channel. This value will be tacked onto the required - // for a payment independent of the size of the payment. + //* + //The base fee that must be used for incoming HTLC's to this particular + //channel. This value will be tacked onto the required for a payment + //independent of the size of the payment. BaseFee uint32 `protobuf:"varint,8,opt,name=base_fee,json=baseFee,proto3" json:"base_fee,omitempty"` - // FeeRate is the fee rate that will be charged per millionth of a - // satoshi. - FeeRate uint32 `protobuf:"varint,9,opt,name=fee_rate,json=feeRate,proto3" json:"fee_rate,omitempty"` + //* + //The fee rate that will be charged per millionth of a satoshi. + FeeRate uint32 `protobuf:"varint,9,opt,name=fee_rate,json=feeRate,proto3" json:"fee_rate,omitempty"` + //* + //The maximum HTLC value which will be accepted. + HtlcMaximumMsat uint64 `protobuf:"varint,11,opt,name=htlc_maximum_msat,json=htlcMaximumMsat,proto3" json:"htlc_maximum_msat,omitempty"` + //* + //The set of data that was appended to this message, some of which we may + //not actually know how to iterate or parse. By holding onto this data, we + //ensure that we're able to properly validate the set of signatures that + //cover these new fields, and ensure we're able to make upgrades to the + //network in a forwards compatible manner. + ExtraOpaqueData []byte `protobuf:"bytes,12,opt,name=extra_opaque_data,json=extraOpaqueData,proto3" json:"extra_opaque_data,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -660,6 +681,13 @@ func (m *ChannelUpdate) GetTimestamp() uint32 { return 0 } +func (m *ChannelUpdate) GetMessageFlags() uint32 { + if m != nil { + return m.MessageFlags + } + return 0 +} + func (m *ChannelUpdate) GetChannelFlags() uint32 { if m != nil { return m.ChannelFlags @@ -695,6 +723,20 @@ func (m *ChannelUpdate) GetFeeRate() uint32 { return 0 } +func (m *ChannelUpdate) GetHtlcMaximumMsat() uint64 { + if m != nil { + return m.HtlcMaximumMsat + } + return 0 +} + +func (m *ChannelUpdate) GetExtraOpaqueData() []byte { + if m != nil { + return m.ExtraOpaqueData + } + return nil +} + func init() { proto.RegisterEnum("routerrpc.Failure_FailureCode", Failure_FailureCode_name, Failure_FailureCode_value) proto.RegisterType((*PaymentRequest)(nil), "routerrpc.PaymentRequest") @@ -710,81 +752,84 @@ func init() { func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 1172 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x56, 0xdd, 0x72, 0x1a, 0x37, - 0x14, 0x2e, 0xb1, 0xcd, 0xcf, 0x01, 0xec, 0xb5, 0x6c, 0x27, 0x98, 0xc4, 0x89, 0x43, 0x3b, 0xad, - 0xa7, 0xd3, 0xb1, 0xa7, 0x74, 0x92, 0xcb, 0x76, 0x36, 0x20, 0xea, 0x9d, 0xc0, 0x2e, 0xd5, 0x82, - 0x13, 0xb7, 0x17, 0x1a, 0x99, 0x95, 0x61, 0x6b, 0xf6, 0x27, 0xbb, 0xa2, 0xad, 0x5f, 0xa0, 0x0f, - 0xd4, 0x77, 0xe8, 0x43, 0xf4, 0x11, 0xfa, 0x16, 0x1d, 0x49, 0xbb, 0x18, 0x6c, 0xf7, 0x8a, 0xd5, - 0xf7, 0x1d, 0x7d, 0xd2, 0x39, 0x3a, 0x3f, 0xc0, 0xd3, 0x24, 0x5a, 0x08, 0x9e, 0x24, 0xf1, 0xe4, - 0x4c, 0x7f, 0x9d, 0xc6, 0x49, 0x24, 0x22, 0x54, 0x59, 0xe2, 0xcd, 0x4a, 0x12, 0x4f, 0x34, 0xda, - 0xfa, 0xbb, 0x00, 0xdb, 0x43, 0x76, 0x1b, 0xf0, 0x50, 0x10, 0xfe, 0x69, 0xc1, 0x53, 0x81, 0x9e, - 0x41, 0x29, 0x66, 0xb7, 0x34, 0xe1, 0x9f, 0x1a, 0x85, 0xe3, 0xc2, 0x49, 0x85, 0x14, 0x63, 0x76, - 0x4b, 0xf8, 0x27, 0xd4, 0x82, 0xfa, 0x35, 0xe7, 0x74, 0xee, 0x07, 0xbe, 0xa0, 0x29, 0x13, 0x8d, - 0x27, 0xc7, 0x85, 0x93, 0x0d, 0x52, 0xbd, 0xe6, 0xbc, 0x2f, 0x31, 0x97, 0x09, 0x74, 0x04, 0x30, - 0x99, 0x8b, 0xdf, 0xb4, 0x51, 0x63, 0xe3, 0xb8, 0x70, 0xb2, 0x45, 0x2a, 0x12, 0x51, 0x16, 0xe8, - 0x2b, 0xd8, 0x11, 0x7e, 0xc0, 0xa3, 0x85, 0xa0, 0x29, 0x9f, 0x44, 0xa1, 0x97, 0x36, 0x36, 0x95, - 0xcd, 0x76, 0x06, 0xbb, 0x1a, 0x45, 0xa7, 0xb0, 0x17, 0x2d, 0xc4, 0x34, 0xf2, 0xc3, 0x29, 0x9d, - 0xcc, 0x58, 0x18, 0xf2, 0x39, 0xf5, 0xbd, 0xc6, 0x96, 0x3a, 0x71, 0x37, 0xa7, 0x3a, 0x9a, 0xb1, - 0xbc, 0xd6, 0xaf, 0xb0, 0xb3, 0x74, 0x23, 0x8d, 0xa3, 0x30, 0xe5, 0xe8, 0x10, 0xca, 0xd2, 0x8f, - 0x19, 0x4b, 0x67, 0xca, 0x91, 0x1a, 0x91, 0x7e, 0x9d, 0xb3, 0x74, 0x86, 0x9e, 0x43, 0x25, 0x4e, - 0x38, 0xf5, 0x03, 0x36, 0xe5, 0xca, 0x8b, 0x1a, 0x29, 0xc7, 0x09, 0xb7, 0xe4, 0x1a, 0xbd, 0x82, - 0x6a, 0xac, 0xa5, 0x28, 0x4f, 0x12, 0xe5, 0x43, 0x85, 0x40, 0x06, 0xe1, 0x24, 0x69, 0x7d, 0x0f, - 0x3b, 0x44, 0xc6, 0xb2, 0xc7, 0x79, 0x1e, 0x33, 0x04, 0x9b, 0x1e, 0x4f, 0x45, 0x76, 0x8e, 0xfa, - 0x96, 0x71, 0x64, 0xc1, 0x6a, 0xa0, 0x8a, 0x2c, 0x90, 0x31, 0x6a, 0x79, 0x60, 0xdc, 0xed, 0xcf, - 0x2e, 0x7b, 0x02, 0x86, 0x7c, 0x1f, 0xe9, 0xae, 0x8c, 0x71, 0x20, 0x77, 0x15, 0xd4, 0xae, 0xed, - 0x0c, 0xef, 0x71, 0x3e, 0x48, 0x99, 0x40, 0x5f, 0xea, 0x10, 0xd2, 0x79, 0x34, 0xb9, 0xa1, 0x1e, - 0x9f, 0xb3, 0xdb, 0x4c, 0xbe, 0x2e, 0xe1, 0x7e, 0x34, 0xb9, 0xe9, 0x4a, 0xb0, 0xf5, 0x0b, 0x20, - 0x97, 0x87, 0xde, 0x28, 0x52, 0x67, 0xe5, 0x17, 0x7d, 0x0d, 0xb5, 0xdc, 0xb9, 0x95, 0xc0, 0xe4, - 0x0e, 0xab, 0xe0, 0xb4, 0x60, 0x4b, 0xa5, 0x8a, 0x92, 0xad, 0xb6, 0x6b, 0xa7, 0xf3, 0x50, 0xe6, - 0x8b, 0x96, 0xd1, 0x54, 0x8b, 0xc2, 0xde, 0x9a, 0x78, 0xe6, 0x45, 0x13, 0x64, 0x18, 0x75, 0x58, - 0x0b, 0xcb, 0xb0, 0xaa, 0x35, 0xfa, 0x06, 0x4a, 0xd7, 0xcc, 0x9f, 0x2f, 0x92, 0x5c, 0x18, 0x9d, - 0x2e, 0x33, 0xf2, 0xb4, 0xa7, 0x19, 0x92, 0x9b, 0xb4, 0xfe, 0x2c, 0x41, 0x29, 0x03, 0x51, 0x1b, - 0x36, 0x27, 0x91, 0xa7, 0x15, 0xb7, 0xdb, 0x2f, 0x1f, 0x6e, 0xcb, 0x7f, 0x3b, 0x91, 0xc7, 0x89, - 0xb2, 0x45, 0x6d, 0x38, 0xc8, 0xa4, 0x68, 0x1a, 0x2d, 0x92, 0x09, 0xa7, 0xf1, 0xe2, 0xea, 0x86, - 0xdf, 0x66, 0xaf, 0xbd, 0x97, 0x91, 0xae, 0xe2, 0x86, 0x8a, 0x42, 0x3f, 0xc0, 0x76, 0x9e, 0x6a, - 0x8b, 0xd8, 0x63, 0x82, 0xab, 0xb7, 0xaf, 0xb6, 0x1b, 0x2b, 0x27, 0x66, 0x19, 0x37, 0x56, 0x3c, - 0xa9, 0x4f, 0x56, 0x97, 0x32, 0xad, 0x66, 0x62, 0x3e, 0xd1, 0xaf, 0x27, 0xf3, 0x7a, 0x93, 0x94, - 0x25, 0xa0, 0xde, 0xad, 0x05, 0xf5, 0x28, 0xf4, 0xa3, 0x90, 0xa6, 0x33, 0x46, 0xdb, 0x6f, 0xde, - 0xaa, 0x5c, 0xae, 0x91, 0xaa, 0x02, 0xdd, 0x19, 0x6b, 0xbf, 0x79, 0x2b, 0x53, 0x4f, 0x55, 0x0f, - 0xff, 0x23, 0xf6, 0x93, 0xdb, 0x46, 0xf1, 0xb8, 0x70, 0x52, 0x27, 0xaa, 0xa0, 0xb0, 0x42, 0xd0, - 0x3e, 0x6c, 0x5d, 0xcf, 0xd9, 0x34, 0x6d, 0x94, 0x14, 0xa5, 0x17, 0xad, 0x7f, 0x36, 0xa1, 0xba, - 0x12, 0x02, 0x54, 0x83, 0x32, 0xc1, 0x2e, 0x26, 0x17, 0xb8, 0x6b, 0x7c, 0x86, 0x1a, 0xb0, 0x3f, - 0xb6, 0xdf, 0xdb, 0xce, 0x07, 0x9b, 0x0e, 0xcd, 0xcb, 0x01, 0xb6, 0x47, 0xf4, 0xdc, 0x74, 0xcf, - 0x8d, 0x02, 0x7a, 0x01, 0x0d, 0xcb, 0xee, 0x38, 0x84, 0xe0, 0xce, 0x68, 0xc9, 0x99, 0x03, 0x67, - 0x6c, 0x8f, 0x8c, 0x27, 0xe8, 0x15, 0x3c, 0xef, 0x59, 0xb6, 0xd9, 0xa7, 0x77, 0x36, 0x9d, 0xfe, - 0xe8, 0x82, 0xe2, 0x8f, 0x43, 0x8b, 0x5c, 0x1a, 0x1b, 0x8f, 0x19, 0x9c, 0x8f, 0xfa, 0x9d, 0x5c, - 0x61, 0x13, 0x1d, 0xc2, 0x81, 0x36, 0xd0, 0x5b, 0xe8, 0xc8, 0x71, 0xa8, 0xeb, 0x38, 0xb6, 0xb1, - 0x85, 0x76, 0xa1, 0x6e, 0xd9, 0x17, 0x66, 0xdf, 0xea, 0x52, 0x82, 0xcd, 0xfe, 0xc0, 0x28, 0xa2, - 0x3d, 0xd8, 0xb9, 0x6f, 0x57, 0x92, 0x12, 0xb9, 0x9d, 0x63, 0x5b, 0x8e, 0x4d, 0x2f, 0x30, 0x71, - 0x2d, 0xc7, 0x36, 0xca, 0xe8, 0x29, 0xa0, 0x75, 0xea, 0x7c, 0x60, 0x76, 0x8c, 0x0a, 0x3a, 0x80, - 0xdd, 0x75, 0xfc, 0x3d, 0xbe, 0x34, 0x40, 0x86, 0x41, 0x5f, 0x8c, 0xbe, 0xc3, 0x7d, 0xe7, 0x03, - 0x1d, 0x58, 0xb6, 0x35, 0x18, 0x0f, 0x8c, 0x2a, 0xda, 0x07, 0xa3, 0x87, 0x31, 0xb5, 0x6c, 0x77, - 0xdc, 0xeb, 0x59, 0x1d, 0x0b, 0xdb, 0x23, 0xa3, 0xa6, 0x4f, 0x7e, 0xcc, 0xf1, 0xba, 0xdc, 0xd0, - 0x39, 0x37, 0x6d, 0x1b, 0xf7, 0x69, 0xd7, 0x72, 0xcd, 0x77, 0x7d, 0xdc, 0x35, 0xb6, 0xd1, 0x11, - 0x1c, 0x8e, 0xf0, 0x60, 0xe8, 0x10, 0x93, 0x5c, 0xd2, 0x9c, 0xef, 0x99, 0x56, 0x7f, 0x4c, 0xb0, - 0xb1, 0x83, 0x5e, 0xc3, 0x11, 0xc1, 0x3f, 0x8d, 0x2d, 0x82, 0xbb, 0xd4, 0x76, 0xba, 0x98, 0xf6, - 0xb0, 0x39, 0x1a, 0x13, 0x4c, 0x07, 0x96, 0xeb, 0x5a, 0xf6, 0x8f, 0x86, 0x81, 0xbe, 0x80, 0xe3, - 0xa5, 0xc9, 0x52, 0xe0, 0x9e, 0xd5, 0xae, 0xf4, 0x2f, 0x7f, 0x4f, 0x1b, 0x7f, 0x1c, 0xd1, 0x21, - 0xc6, 0xc4, 0x40, 0xa8, 0x09, 0x4f, 0xef, 0x8e, 0xd7, 0x07, 0x64, 0x67, 0xef, 0x49, 0x6e, 0x88, - 0xc9, 0xc0, 0xb4, 0xe5, 0x03, 0xaf, 0x71, 0xfb, 0xf2, 0xda, 0x77, 0xdc, 0xfd, 0x6b, 0x1f, 0xb4, - 0xfe, 0x7a, 0x02, 0xf5, 0xb5, 0xa4, 0x47, 0x2f, 0xa0, 0x92, 0xfa, 0xd3, 0x90, 0x09, 0x59, 0xca, - 0xba, 0xca, 0xef, 0x00, 0x35, 0x00, 0x66, 0xcc, 0x0f, 0x75, 0x7b, 0xd1, 0xd5, 0x56, 0x51, 0x88, - 0x6a, 0x2e, 0xcf, 0xa0, 0x24, 0x6b, 0x46, 0xf6, 0xf2, 0x0d, 0x55, 0x20, 0x45, 0xb9, 0xb4, 0x3c, - 0xa9, 0x2a, 0xfb, 0x57, 0x2a, 0x58, 0x10, 0xab, 0xda, 0xa9, 0x93, 0x3b, 0x00, 0x7d, 0x0e, 0x79, - 0xa9, 0x51, 0x9d, 0xff, 0x5b, 0xca, 0xa2, 0x96, 0x81, 0x3d, 0x89, 0x3d, 0xe8, 0x8c, 0x82, 0x65, - 0x15, 0xb4, 0xda, 0x19, 0x05, 0x43, 0x5f, 0xc3, 0xae, 0x2e, 0x53, 0x3f, 0xf4, 0x83, 0x45, 0xa0, - 0xcb, 0xb5, 0xa4, 0x6e, 0xb3, 0xa3, 0xca, 0x55, 0xe3, 0xaa, 0x6a, 0x0f, 0xa1, 0x7c, 0xc5, 0x52, - 0x2e, 0x9b, 0x72, 0xa3, 0xac, 0xc4, 0x4a, 0x72, 0xdd, 0xe3, 0x6a, 0xbe, 0xc8, 0x56, 0x9d, 0xc8, - 0x46, 0x51, 0xd1, 0xd4, 0x35, 0xe7, 0x84, 0x09, 0xde, 0xfe, 0xb7, 0x00, 0x45, 0xd5, 0x19, 0x13, - 0xd4, 0x85, 0xaa, 0xec, 0x94, 0xd9, 0x70, 0x42, 0x87, 0x2b, 0xbd, 0x64, 0x7d, 0xee, 0x36, 0x9b, - 0x8f, 0x51, 0x59, 0x63, 0x7d, 0x0f, 0x06, 0x4e, 0x85, 0x1f, 0xc8, 0xa6, 0x93, 0x8d, 0x0e, 0xb4, - 0x6a, 0x7f, 0x6f, 0x1e, 0x35, 0x9f, 0x3f, 0xca, 0x65, 0x62, 0x7d, 0x7d, 0xa5, 0xac, 0x79, 0xa3, - 0xa3, 0x15, 0xdb, 0x87, 0x13, 0xa3, 0xf9, 0xf2, 0xff, 0x68, 0xad, 0xf6, 0xee, 0xdb, 0x9f, 0xcf, - 0xa6, 0xbe, 0x98, 0x2d, 0xae, 0x4e, 0x27, 0x51, 0x70, 0x36, 0xf7, 0xa7, 0x33, 0x11, 0xfa, 0xe1, - 0x34, 0xe4, 0xe2, 0xf7, 0x28, 0xb9, 0x39, 0x9b, 0x87, 0xde, 0x99, 0x1a, 0x20, 0x67, 0x4b, 0x99, - 0xab, 0xa2, 0xfa, 0xef, 0xf1, 0xdd, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x7d, 0x2a, 0xf5, - 0xab, 0x08, 0x00, 0x00, + // 1224 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x56, 0xef, 0x72, 0x1a, 0x37, + 0x10, 0x2f, 0xb1, 0xcd, 0x9f, 0x05, 0xcc, 0x59, 0xb6, 0x13, 0x4c, 0xe2, 0xc4, 0xa1, 0x9d, 0xd6, + 0x93, 0xe9, 0xd8, 0x53, 0x3a, 0xc9, 0xc7, 0x76, 0x08, 0x88, 0xfa, 0x26, 0x70, 0x47, 0x75, 0xe0, + 0xc4, 0xed, 0x07, 0x8d, 0xcc, 0xc9, 0x70, 0x35, 0xf7, 0xc7, 0x77, 0xa2, 0xb5, 0x5f, 0xa0, 0xaf, + 0xd3, 0xa7, 0xe8, 0x43, 0xf4, 0x11, 0xfa, 0x16, 0x1d, 0x49, 0x77, 0x80, 0x1d, 0xf7, 0x13, 0xa7, + 0xdf, 0xef, 0xa7, 0x5d, 0xed, 0x6a, 0x77, 0x05, 0x3c, 0x8d, 0xc3, 0x85, 0xe0, 0x71, 0x1c, 0x4d, + 0x4e, 0xf5, 0xd7, 0x49, 0x14, 0x87, 0x22, 0x44, 0xa5, 0x25, 0xde, 0x28, 0xc5, 0xd1, 0x44, 0xa3, + 0xcd, 0xbf, 0x73, 0xb0, 0x3d, 0x64, 0x77, 0x3e, 0x0f, 0x04, 0xe1, 0x37, 0x0b, 0x9e, 0x08, 0xf4, + 0x0c, 0x0a, 0x11, 0xbb, 0xa3, 0x31, 0xbf, 0xa9, 0xe7, 0x8e, 0x72, 0xc7, 0x25, 0x92, 0x8f, 0xd8, + 0x1d, 0xe1, 0x37, 0xa8, 0x09, 0xd5, 0x2b, 0xce, 0xe9, 0xdc, 0xf3, 0x3d, 0x41, 0x13, 0x26, 0xea, + 0x4f, 0x8e, 0x72, 0xc7, 0x1b, 0xa4, 0x7c, 0xc5, 0x79, 0x5f, 0x62, 0x0e, 0x13, 0xe8, 0x10, 0x60, + 0x32, 0x17, 0xbf, 0x6b, 0x51, 0x7d, 0xe3, 0x28, 0x77, 0xbc, 0x45, 0x4a, 0x12, 0x51, 0x0a, 0xf4, + 0x0d, 0xd4, 0x84, 0xe7, 0xf3, 0x70, 0x21, 0x68, 0xc2, 0x27, 0x61, 0xe0, 0x26, 0xf5, 0x4d, 0xa5, + 0xd9, 0x4e, 0x61, 0x47, 0xa3, 0xe8, 0x04, 0x76, 0xc3, 0x85, 0x98, 0x86, 0x5e, 0x30, 0xa5, 0x93, + 0x19, 0x0b, 0x02, 0x3e, 0xa7, 0x9e, 0x5b, 0xdf, 0x52, 0x1e, 0x77, 0x32, 0xaa, 0xa3, 0x19, 0xd3, + 0x6d, 0xfe, 0x06, 0xb5, 0x65, 0x18, 0x49, 0x14, 0x06, 0x09, 0x47, 0x07, 0x50, 0x94, 0x71, 0xcc, + 0x58, 0x32, 0x53, 0x81, 0x54, 0x88, 0x8c, 0xeb, 0x8c, 0x25, 0x33, 0xf4, 0x1c, 0x4a, 0x51, 0xcc, + 0xa9, 0xe7, 0xb3, 0x29, 0x57, 0x51, 0x54, 0x48, 0x31, 0x8a, 0xb9, 0x29, 0xd7, 0xe8, 0x15, 0x94, + 0x23, 0x6d, 0x8a, 0xf2, 0x38, 0x56, 0x31, 0x94, 0x08, 0xa4, 0x10, 0x8e, 0xe3, 0xe6, 0x0f, 0x50, + 0x23, 0x32, 0x97, 0x3d, 0xce, 0xb3, 0x9c, 0x21, 0xd8, 0x74, 0x79, 0x22, 0x52, 0x3f, 0xea, 0x5b, + 0xe6, 0x91, 0xf9, 0xeb, 0x89, 0xca, 0x33, 0x5f, 0xe6, 0xa8, 0xe9, 0x82, 0xb1, 0xda, 0x9f, 0x1e, + 0xf6, 0x18, 0x0c, 0x79, 0x3f, 0x32, 0x5c, 0x99, 0x63, 0x5f, 0xee, 0xca, 0xa9, 0x5d, 0xdb, 0x29, + 0xde, 0xe3, 0x7c, 0x90, 0x30, 0x81, 0xbe, 0xd6, 0x29, 0xa4, 0xf3, 0x70, 0x72, 0x4d, 0x5d, 0x3e, + 0x67, 0x77, 0xa9, 0xf9, 0xaa, 0x84, 0xfb, 0xe1, 0xe4, 0xba, 0x2b, 0xc1, 0xe6, 0xaf, 0x80, 0x1c, + 0x1e, 0xb8, 0xa3, 0x50, 0xf9, 0xca, 0x0e, 0xfa, 0x1a, 0x2a, 0x59, 0x70, 0x6b, 0x89, 0xc9, 0x02, + 0x56, 0xc9, 0x69, 0xc2, 0x96, 0x2a, 0x15, 0x65, 0xb6, 0xdc, 0xaa, 0x9c, 0xcc, 0x03, 0x59, 0x2f, + 0xda, 0x8c, 0xa6, 0x9a, 0x14, 0x76, 0xef, 0x19, 0x4f, 0xa3, 0x68, 0x80, 0x4c, 0xa3, 0x4e, 0x6b, + 0x6e, 0x99, 0x56, 0xb5, 0x46, 0xdf, 0x42, 0xe1, 0x8a, 0x79, 0xf3, 0x45, 0x9c, 0x19, 0x46, 0x27, + 0xcb, 0x8a, 0x3c, 0xe9, 0x69, 0x86, 0x64, 0x92, 0xe6, 0x9f, 0x05, 0x28, 0xa4, 0x20, 0x6a, 0xc1, + 0xe6, 0x24, 0x74, 0xb5, 0xc5, 0xed, 0xd6, 0xcb, 0xcf, 0xb7, 0x65, 0xbf, 0x9d, 0xd0, 0xe5, 0x44, + 0x69, 0x51, 0x0b, 0xf6, 0x53, 0x53, 0x34, 0x09, 0x17, 0xf1, 0x84, 0xd3, 0x68, 0x71, 0x79, 0xcd, + 0xef, 0xd2, 0xdb, 0xde, 0x4d, 0x49, 0x47, 0x71, 0x43, 0x45, 0xa1, 0x1f, 0x61, 0x3b, 0x2b, 0xb5, + 0x45, 0xe4, 0x32, 0xc1, 0xd5, 0xdd, 0x97, 0x5b, 0xf5, 0x35, 0x8f, 0x69, 0xc5, 0x8d, 0x15, 0x4f, + 0xaa, 0x93, 0xf5, 0xa5, 0x2c, 0xab, 0x99, 0x98, 0x4f, 0xf4, 0xed, 0xc9, 0xba, 0xde, 0x24, 0x45, + 0x09, 0xa8, 0x7b, 0x6b, 0x42, 0x35, 0x0c, 0xbc, 0x30, 0xa0, 0xc9, 0x8c, 0xd1, 0xd6, 0xdb, 0x77, + 0xaa, 0x96, 0x2b, 0xa4, 0xac, 0x40, 0x67, 0xc6, 0x5a, 0x6f, 0xdf, 0xc9, 0xd2, 0x53, 0xdd, 0xc3, + 0x6f, 0x23, 0x2f, 0xbe, 0xab, 0xe7, 0x8f, 0x72, 0xc7, 0x55, 0xa2, 0x1a, 0x0a, 0x2b, 0x04, 0xed, + 0xc1, 0xd6, 0xd5, 0x9c, 0x4d, 0x93, 0x7a, 0x41, 0x51, 0x7a, 0xd1, 0xfc, 0x67, 0x13, 0xca, 0x6b, + 0x29, 0x40, 0x15, 0x28, 0x12, 0xec, 0x60, 0x72, 0x8e, 0xbb, 0xc6, 0x17, 0xa8, 0x0e, 0x7b, 0x63, + 0xeb, 0x83, 0x65, 0x7f, 0xb4, 0xe8, 0xb0, 0x7d, 0x31, 0xc0, 0xd6, 0x88, 0x9e, 0xb5, 0x9d, 0x33, + 0x23, 0x87, 0x5e, 0x40, 0xdd, 0xb4, 0x3a, 0x36, 0x21, 0xb8, 0x33, 0x5a, 0x72, 0xed, 0x81, 0x3d, + 0xb6, 0x46, 0xc6, 0x13, 0xf4, 0x0a, 0x9e, 0xf7, 0x4c, 0xab, 0xdd, 0xa7, 0x2b, 0x4d, 0xa7, 0x3f, + 0x3a, 0xa7, 0xf8, 0xd3, 0xd0, 0x24, 0x17, 0xc6, 0xc6, 0x63, 0x82, 0xb3, 0x51, 0xbf, 0x93, 0x59, + 0xd8, 0x44, 0x07, 0xb0, 0xaf, 0x05, 0x7a, 0x0b, 0x1d, 0xd9, 0x36, 0x75, 0x6c, 0xdb, 0x32, 0xb6, + 0xd0, 0x0e, 0x54, 0x4d, 0xeb, 0xbc, 0xdd, 0x37, 0xbb, 0x94, 0xe0, 0x76, 0x7f, 0x60, 0xe4, 0xd1, + 0x2e, 0xd4, 0x1e, 0xea, 0x0a, 0xd2, 0x44, 0xa6, 0xb3, 0x2d, 0xd3, 0xb6, 0xe8, 0x39, 0x26, 0x8e, + 0x69, 0x5b, 0x46, 0x11, 0x3d, 0x05, 0x74, 0x9f, 0x3a, 0x1b, 0xb4, 0x3b, 0x46, 0x09, 0xed, 0xc3, + 0xce, 0x7d, 0xfc, 0x03, 0xbe, 0x30, 0x40, 0xa6, 0x41, 0x1f, 0x8c, 0xbe, 0xc7, 0x7d, 0xfb, 0x23, + 0x1d, 0x98, 0x96, 0x39, 0x18, 0x0f, 0x8c, 0x32, 0xda, 0x03, 0xa3, 0x87, 0x31, 0x35, 0x2d, 0x67, + 0xdc, 0xeb, 0x99, 0x1d, 0x13, 0x5b, 0x23, 0xa3, 0xa2, 0x3d, 0x3f, 0x16, 0x78, 0x55, 0x6e, 0xe8, + 0x9c, 0xb5, 0x2d, 0x0b, 0xf7, 0x69, 0xd7, 0x74, 0xda, 0xef, 0xfb, 0xb8, 0x6b, 0x6c, 0xa3, 0x43, + 0x38, 0x18, 0xe1, 0xc1, 0xd0, 0x26, 0x6d, 0x72, 0x41, 0x33, 0xbe, 0xd7, 0x36, 0xfb, 0x63, 0x82, + 0x8d, 0x1a, 0x7a, 0x0d, 0x87, 0x04, 0xff, 0x3c, 0x36, 0x09, 0xee, 0x52, 0xcb, 0xee, 0x62, 0xda, + 0xc3, 0xed, 0xd1, 0x98, 0x60, 0x3a, 0x30, 0x1d, 0xc7, 0xb4, 0x7e, 0x32, 0x0c, 0xf4, 0x15, 0x1c, + 0x2d, 0x25, 0x4b, 0x03, 0x0f, 0x54, 0x3b, 0x32, 0xbe, 0xec, 0x3e, 0x2d, 0xfc, 0x69, 0x44, 0x87, + 0x18, 0x13, 0x03, 0xa1, 0x06, 0x3c, 0x5d, 0xb9, 0xd7, 0x0e, 0x52, 0xdf, 0xbb, 0x92, 0x1b, 0x62, + 0x32, 0x68, 0x5b, 0xf2, 0x82, 0xef, 0x71, 0x7b, 0xf2, 0xd8, 0x2b, 0xee, 0xe1, 0xb1, 0xf7, 0x9b, + 0x7f, 0x6d, 0x40, 0xf5, 0x5e, 0xd1, 0xa3, 0x17, 0x50, 0x4a, 0xbc, 0x69, 0xc0, 0x84, 0x6c, 0x65, + 0xdd, 0xe5, 0x2b, 0x40, 0x3d, 0x00, 0x33, 0xe6, 0x05, 0x7a, 0xbc, 0xe8, 0x6e, 0x2b, 0x29, 0x44, + 0x0d, 0x97, 0x67, 0x50, 0x90, 0x3d, 0x23, 0x67, 0xf9, 0x86, 0x6a, 0x90, 0xbc, 0x5c, 0x9a, 0xae, + 0xb4, 0x2a, 0xe7, 0x57, 0x22, 0x98, 0x1f, 0xa9, 0xde, 0xa9, 0x92, 0x15, 0x80, 0xbe, 0x84, 0xaa, + 0xcf, 0x93, 0x84, 0x4d, 0x39, 0xd5, 0xf5, 0x0f, 0x4a, 0x51, 0x49, 0xc1, 0x9e, 0xc4, 0xa4, 0x28, + 0xeb, 0x5f, 0x2d, 0xda, 0xd2, 0xa2, 0x14, 0xd4, 0xa2, 0x87, 0xe3, 0x53, 0xb0, 0xb4, 0xcd, 0xd6, + 0xc7, 0xa7, 0x60, 0xe8, 0x0d, 0xec, 0xe8, 0x5e, 0xf6, 0x02, 0xcf, 0x5f, 0xf8, 0xba, 0xa7, 0x0b, + 0xea, 0xc8, 0x35, 0xd5, 0xd3, 0x1a, 0x57, 0xad, 0x7d, 0x00, 0xc5, 0x4b, 0x96, 0x70, 0x39, 0xb9, + 0xeb, 0x45, 0x65, 0xac, 0x20, 0xd7, 0x3d, 0xae, 0x1e, 0x21, 0x39, 0xcf, 0x63, 0x39, 0x4d, 0x4a, + 0x9a, 0xba, 0xe2, 0x9c, 0xc8, 0x3c, 0x2e, 0x3d, 0xb0, 0xdb, 0x95, 0x87, 0xf2, 0x9a, 0x07, 0x8d, + 0x2b, 0x0f, 0x6f, 0x60, 0x87, 0xdf, 0x8a, 0x98, 0xd1, 0x30, 0x62, 0x37, 0x0b, 0x4e, 0x5d, 0x26, + 0x58, 0xbd, 0xa2, 0x92, 0x5b, 0x53, 0x84, 0xad, 0xf0, 0x2e, 0x13, 0xac, 0xf5, 0x6f, 0x0e, 0xf2, + 0x6a, 0x2c, 0xc7, 0xa8, 0x0b, 0x65, 0x39, 0xa6, 0xd3, 0x97, 0x11, 0x1d, 0xac, 0x0d, 0xb2, 0xfb, + 0x8f, 0x7e, 0xa3, 0xf1, 0x18, 0x95, 0x4e, 0xf5, 0x0f, 0x60, 0xe0, 0x44, 0x78, 0xbe, 0x9c, 0x78, + 0xe9, 0xbb, 0x85, 0xd6, 0xf5, 0x0f, 0x1e, 0xc3, 0xc6, 0xf3, 0x47, 0xb9, 0xd4, 0x58, 0x5f, 0x1f, + 0x29, 0x7d, 0x39, 0xd0, 0xe1, 0x9a, 0xf6, 0xf3, 0xe7, 0xaa, 0xf1, 0xf2, 0xff, 0x68, 0x6d, 0xed, + 0xfd, 0x77, 0xbf, 0x9c, 0x4e, 0x3d, 0x31, 0x5b, 0x5c, 0x9e, 0x4c, 0x42, 0xff, 0x74, 0xee, 0x4d, + 0x67, 0x22, 0xf0, 0x82, 0x69, 0xc0, 0xc5, 0x1f, 0x61, 0x7c, 0x7d, 0x3a, 0x0f, 0xdc, 0x53, 0xf5, + 0x7a, 0x9d, 0x2e, 0xcd, 0x5c, 0xe6, 0xd5, 0x1f, 0x9f, 0xef, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, + 0x89, 0x21, 0x7b, 0xbd, 0x28, 0x09, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 94992269..dc875d68 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -164,50 +164,86 @@ message Failure { message ChannelUpdate { - // Signature is used to validate the announced data and prove the - // ownership of node id. - bytes signature = 1; + /** + The signature that validates the announced data and proves the ownership + of node id. + */ + bytes signature = 1; - // ChainHash denotes the target chain that this channel was opened - // within. This value should be the genesis hash of the target chain. - // Along with the short channel ID, this uniquely identifies the - // channel globally in a blockchain. - bytes chain_hash = 2; + /** + The target chain that this channel was opened within. This value + should be the genesis hash of the target chain. Along with the short + channel ID, this uniquely identifies the channel globally in a + blockchain. + */ + bytes chain_hash = 2; - // ShortChannelID is the unique description of the funding transaction. - uint64 chan_id = 3; + /** + The unique description of the funding transaction. + */ + uint64 chan_id = 3; - // Timestamp allows ordering in the case of multiple announcements. We - // should ignore the message if timestamp is not greater than - // the last-received. - uint32 timestamp = 4; + /** + A timestamp that allows ordering in the case of multiple announcements. + We should ignore the message if timestamp is not greater than the + last-received. + */ + uint32 timestamp = 4; - // Flags is a bitfield that describes additional meta-data concerning - // how the update is to be interpreted. Currently, the - // least-significant bit must be set to 0 if the creating node - // corresponds to the first node in the previously sent channel - // announcement and 1 otherwise. If the second bit is set, then the - // channel is set to be disabled. - uint32 channel_flags = 5; + /** + The bitfield that describes whether optional fields are present in this + update. Currently, the least-significant bit must be set to 1 if the + optional field MaxHtlc is present. + */ + uint32 message_flags = 10; - // TimeLockDelta is the minimum number of blocks this node requires to - // be added to the expiry of HTLCs. This is a security parameter - // determined by the node operator. This value represents the required - // gap between the time locks of the incoming and outgoing HTLC's set - // to this node. - uint32 time_lock_delta = 6; + /** + The bitfield that describes additional meta-data concerning how the + update is to be interpreted. Currently, the least-significant bit must be + set to 0 if the creating node corresponds to the first node in the + previously sent channel announcement and 1 otherwise. If the second bit + is set, then the channel is set to be disabled. + */ + uint32 channel_flags = 5; - // HtlcMinimumMsat is the minimum HTLC value which will be accepted. - uint64 htlc_minimum_msat = 7; + /** + The minimum number of blocks this node requires to be added to the expiry + of HTLCs. This is a security parameter determined by the node operator. + This value represents the required gap between the time locks of the + incoming and outgoing HTLC's set to this node. + */ + uint32 time_lock_delta = 6; - // BaseFee is the base fee that must be used for incoming HTLC's to - // this particular channel. This value will be tacked onto the required - // for a payment independent of the size of the payment. - uint32 base_fee = 8; + /** + The minimum HTLC value which will be accepted. + */ + uint64 htlc_minimum_msat = 7; - // FeeRate is the fee rate that will be charged per millionth of a - // satoshi. - uint32 fee_rate = 9; + /** + The base fee that must be used for incoming HTLC's to this particular + channel. This value will be tacked onto the required for a payment + independent of the size of the payment. + */ + uint32 base_fee = 8; + + /** + The fee rate that will be charged per millionth of a satoshi. + */ + uint32 fee_rate = 9; + + /** + The maximum HTLC value which will be accepted. + */ + uint64 htlc_maximum_msat = 11; + + /** + The set of data that was appended to this message, some of which we may + not actually know how to iterate or parse. By holding onto this data, we + ensure that we're able to properly validate the set of signatures that + cover these new fields, and ensure we're able to make upgrades to the + network in a forwards compatible manner. + */ + bytes extra_opaque_data = 12; } service Router { diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 1f63cefd..9f08237a 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -429,10 +429,13 @@ func marshallChannelUpdate(update *lnwire.ChannelUpdate) *ChannelUpdate { ChainHash: update.ChainHash[:], ChanId: update.ShortChannelID.ToUint64(), Timestamp: update.Timestamp, + MessageFlags: uint32(update.MessageFlags), ChannelFlags: uint32(update.ChannelFlags), TimeLockDelta: uint32(update.TimeLockDelta), HtlcMinimumMsat: uint64(update.HtlcMinimumMsat), BaseFee: update.BaseFee, FeeRate: update.FeeRate, + HtlcMaximumMsat: uint64(update.HtlcMaximumMsat), + ExtraOpaqueData: update.ExtraOpaqueData, } } diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 38883ca8..46993d2a 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -12,6 +12,20 @@ import ( "github.com/lightningnetwork/lnd/routing/route" ) +// errNoRoute is returned when all routes from the payment session have been +// attempted. +type errNoRoute struct { + // lastError is the error encountered during the last payment attempt, + // if at least one attempt has been made. + lastError *htlcswitch.ForwardingError +} + +// Error returns a string representation of the error. +func (e errNoRoute) Error() string { + return fmt.Sprintf("unable to route payment to destination: %v", + e.lastError) +} + // paymentLifecycle holds all information about the current state of a payment // needed to resume if from any point. type paymentLifecycle struct { @@ -23,7 +37,7 @@ type paymentLifecycle struct { finalCLTVDelta uint16 attempt *channeldb.PaymentAttemptInfo circuit *sphinx.Circuit - lastError error + lastError *htlcswitch.ForwardingError } // resumePayment resumes the paymentLifecycle from the current state. @@ -218,10 +232,8 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, // payment, we'll return that. if p.lastError != nil { return lnwire.ShortChannelID{}, nil, - fmt.Errorf("unable to route payment to "+ - "destination: %v", p.lastError) + errNoRoute{lastError: p.lastError} } - // Terminal state, return. return lnwire.ShortChannelID{}, nil, err } @@ -326,9 +338,21 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, // handleSendError inspects the given error from the Switch and determines // whether we should make another payment attempt. func (p *paymentLifecycle) handleSendError(sendErr error) error { - finalOutcome := p.router.processSendError( - p.paySession, &p.attempt.Route, sendErr, - ) + var finalOutcome bool + + // If an internal, non-forwarding error occurred, we can stop trying. + fErr, ok := sendErr.(*htlcswitch.ForwardingError) + if !ok { + finalOutcome = true + } else { + finalOutcome = p.router.processSendError( + p.paySession, &p.attempt.Route, fErr, + ) + + // Save the forwarding error so it can be returned if this turns + // out to be the last attempt. + p.lastError = fErr + } if finalOutcome { log.Errorf("Payment %x failed with final outcome: %v", @@ -348,7 +372,5 @@ func (p *paymentLifecycle) handleSendError(sendErr error) error { return sendErr } - // We get ready to make another payment attempt. - p.lastError = sendErr return nil } diff --git a/routing/router.go b/routing/router.go index 6e85a096..8b1fd987 100644 --- a/routing/router.go +++ b/routing/router.go @@ -40,11 +40,6 @@ const ( ) var ( - // ErrNoRouteHopsProvided is returned when a caller attempts to - // construct a new sphinx packet, but provides an empty set of hops for - // each route. - ErrNoRouteHopsProvided = fmt.Errorf("empty route hops provided") - // ErrRouterShuttingDown is returned if the router is in the process of // shutting down. ErrRouterShuttingDown = fmt.Errorf("router shutting down") @@ -1436,6 +1431,9 @@ func (r *ChannelRouter) FindRoute(source, target route.Vertex, }, restrictions, source, target, amt, ) + if err != nil { + return nil, err + } // We'll fetch the current block height so we can properly calculate the // required HTLC time locks within the route. @@ -1658,7 +1656,23 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( // Since this is the first time this payment is being made, we pass nil // for the existing attempt. preimage, _, err := r.sendPayment(nil, payment, paySession) - return preimage, err + if err != nil { + // SendToRoute should return a structured error. In case the + // provided route fails, payment lifecycle will return a + // noRouteError with the structured error embedded. + if noRouteError, ok := err.(errNoRoute); ok { + if noRouteError.lastError == nil { + return lntypes.Preimage{}, + errors.New("failure message missing") + } + + return lntypes.Preimage{}, noRouteError.lastError + } + + return lntypes.Preimage{}, err + } + + return preimage, nil } // sendPayment attempts to send a payment as described within the passed @@ -1740,12 +1754,7 @@ func (r *ChannelRouter) sendPayment( // to continue with an alternative route. This is indicated by the boolean // return value. func (r *ChannelRouter) processSendError(paySession PaymentSession, - rt *route.Route, err error) bool { - - fErr, ok := err.(*htlcswitch.ForwardingError) - if !ok { - return true - } + rt *route.Route, fErr *htlcswitch.ForwardingError) bool { errSource := fErr.ErrorSource errVertex := route.NewVertex(errSource) diff --git a/routing/router_test.go b/routing/router_test.go index 9dd2e85e..f90dbd8c 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -3136,3 +3136,107 @@ func TestRouterPaymentStateMachine(t *testing.T) { } } } + +// TestSendToRouteStructuredError asserts that SendToRoute returns a structured +// error. +func TestSendToRouteStructuredError(t *testing.T) { + t.Parallel() + + // Setup a three node network. + chanCapSat := btcutil.Amount(100000) + testChannels := []*testChannel{ + symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{ + Expiry: 144, + FeeRate: 400, + MinHTLC: 1, + MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat), + }, 1), + symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{ + Expiry: 144, + FeeRate: 400, + MinHTLC: 1, + MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat), + }, 2), + } + + testGraph, err := createTestGraphFromChannels(testChannels) + if err != nil { + t.Fatalf("unable to create graph: %v", err) + } + defer testGraph.cleanUp() + + const startingBlockHeight = 101 + + ctx, cleanUp, err := createTestCtxFromGraphInstance( + startingBlockHeight, testGraph, + ) + if err != nil { + t.Fatalf("unable to create router: %v", err) + } + defer cleanUp() + + // Setup a route from source a to destination c. The route will be used + // in a call to SendToRoute. SendToRoute also applies channel updates, + // but it saves us from including RequestRoute in the test scope too. + hop1 := ctx.aliases["b"] + hop2 := ctx.aliases["c"] + + hops := []*route.Hop{ + { + ChannelID: 1, + PubKeyBytes: hop1, + }, + { + ChannelID: 2, + PubKeyBytes: hop2, + }, + } + + rt, err := route.NewRouteFromHops( + lnwire.MilliSatoshi(10000), 100, + ctx.aliases["a"], hops, + ) + if err != nil { + t.Fatalf("unable to create route: %v", err) + } + + // We'll modify the SendToSwitch method so that it simulates a failed + // payment with an error originating from the first hop of the route. + // The unsigned channel update is attached to the failure message. + ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult( + func(firstHop lnwire.ShortChannelID) ([32]byte, error) { + + v := ctx.aliases["b"] + source, err := btcec.ParsePubKey( + v[:], btcec.S256(), + ) + if err != nil { + t.Fatal(err) + } + + return [32]byte{}, &htlcswitch.ForwardingError{ + ErrorSource: source, + FailureMessage: &lnwire.FailFeeInsufficient{ + Update: lnwire.ChannelUpdate{}, + }, + } + }) + + // The payment parameter is mostly redundant in SendToRoute. Can be left + // empty for this test. + var payment lntypes.Hash + + // Send off the payment request to the router. The specified route + // should be attempted and the channel update should be received by + // router and ignored because it is missing a valid signature. + _, err = ctx.router.SendToRoute(payment, rt) + + fErr, ok := err.(*htlcswitch.ForwardingError) + if !ok { + t.Fatalf("expected forwarding error") + } + + if _, ok := fErr.FailureMessage.(*lnwire.FailFeeInsufficient); !ok { + t.Fatalf("expected fee insufficient error") + } +}