htlcswitch+routing+routerrpc: return error source as index
This commit is contained in:
parent
55bef96cf3
commit
2b47632b26
2
go.mod
2
go.mod
@ -30,7 +30,7 @@ require (
|
|||||||
github.com/juju/version v0.0.0-20180108022336-b64dbd566305 // indirect
|
github.com/juju/version v0.0.0-20180108022336-b64dbd566305 // indirect
|
||||||
github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec
|
github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec
|
||||||
github.com/lightninglabs/neutrino v0.0.0-20190629001446-52dd89dd1aaa
|
github.com/lightninglabs/neutrino v0.0.0-20190629001446-52dd89dd1aaa
|
||||||
github.com/lightningnetwork/lightning-onion v0.0.0-20190430041606-751fb4dd8b72
|
github.com/lightningnetwork/lightning-onion v0.0.0-20190703000913-ecc936dc56c9
|
||||||
github.com/lightningnetwork/lnd/queue v1.0.1
|
github.com/lightningnetwork/lnd/queue v1.0.1
|
||||||
github.com/lightningnetwork/lnd/ticker v1.0.0
|
github.com/lightningnetwork/lnd/ticker v1.0.0
|
||||||
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796
|
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796
|
||||||
|
4
go.sum
4
go.sum
@ -137,8 +137,8 @@ github.com/lightninglabs/neutrino v0.0.0-20190313035638-e1ad4c33fb18 h1:lxD7RgKY
|
|||||||
github.com/lightninglabs/neutrino v0.0.0-20190313035638-e1ad4c33fb18/go.mod h1:v6tz6jbuAubTrRpX8ke2KH9sJxml8KlPQTKgo9mAp1Q=
|
github.com/lightninglabs/neutrino v0.0.0-20190313035638-e1ad4c33fb18/go.mod h1:v6tz6jbuAubTrRpX8ke2KH9sJxml8KlPQTKgo9mAp1Q=
|
||||||
github.com/lightninglabs/neutrino v0.0.0-20190629001446-52dd89dd1aaa h1:vLsdHrqHKNDShoSRkrFEM0FsNt5waIKS87IgP1YLz+g=
|
github.com/lightninglabs/neutrino v0.0.0-20190629001446-52dd89dd1aaa h1:vLsdHrqHKNDShoSRkrFEM0FsNt5waIKS87IgP1YLz+g=
|
||||||
github.com/lightninglabs/neutrino v0.0.0-20190629001446-52dd89dd1aaa/go.mod h1:vzLU75ll8qbRJIzW5dvK/UXtR9c2FecJ6VNOM8chyVM=
|
github.com/lightninglabs/neutrino v0.0.0-20190629001446-52dd89dd1aaa/go.mod h1:vzLU75ll8qbRJIzW5dvK/UXtR9c2FecJ6VNOM8chyVM=
|
||||||
github.com/lightningnetwork/lightning-onion v0.0.0-20190430041606-751fb4dd8b72 h1:KgmypyQfJnEf2vhwboKCtTp4mHxIcLeXPBPWDbPuzFQ=
|
github.com/lightningnetwork/lightning-onion v0.0.0-20190703000913-ecc936dc56c9 h1:u6dbtgPtilk/HWg9GwA8GniHqzCW/7an3ZSpZARfHx4=
|
||||||
github.com/lightningnetwork/lightning-onion v0.0.0-20190430041606-751fb4dd8b72/go.mod h1:Sooe/CoCqa85JxqHV+IBR2HW+6t2Cv+36awSmoccswM=
|
github.com/lightningnetwork/lightning-onion v0.0.0-20190703000913-ecc936dc56c9/go.mod h1:Sooe/CoCqa85JxqHV+IBR2HW+6t2Cv+36awSmoccswM=
|
||||||
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw=
|
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw=
|
||||||
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY=
|
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY=
|
||||||
github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA=
|
github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA=
|
||||||
|
@ -6,17 +6,18 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
sphinx "github.com/lightningnetwork/lightning-onion"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ForwardingError wraps an lnwire.FailureMessage in a struct that also
|
// ForwardingError wraps an lnwire.FailureMessage in a struct that also
|
||||||
// includes the source of the error.
|
// includes the source of the error.
|
||||||
type ForwardingError struct {
|
type ForwardingError struct {
|
||||||
// ErrorSource is the public key of the node that sent the error. With
|
// FailureSourceIdx is the index of the node that sent the failure. With
|
||||||
// this information, the dispatcher of a payment can modify their set
|
// this information, the dispatcher of a payment can modify their set of
|
||||||
// of candidate routes in response to the type of error extracted.
|
// candidate routes in response to the type of failure extracted. Index
|
||||||
ErrorSource *btcec.PublicKey
|
// zero is the self node.
|
||||||
|
FailureSourceIdx int
|
||||||
|
|
||||||
// ExtraMsg is an additional error message that callers can provide in
|
// ExtraMsg is an additional error message that callers can provide in
|
||||||
// order to provide context specific error details.
|
// order to provide context specific error details.
|
||||||
@ -256,20 +257,20 @@ type SphinxErrorDecrypter struct {
|
|||||||
// NOTE: Part of the ErrorDecrypter interface.
|
// NOTE: Part of the ErrorDecrypter interface.
|
||||||
func (s *SphinxErrorDecrypter) DecryptError(reason lnwire.OpaqueReason) (*ForwardingError, error) {
|
func (s *SphinxErrorDecrypter) DecryptError(reason lnwire.OpaqueReason) (*ForwardingError, error) {
|
||||||
|
|
||||||
source, failureData, err := s.OnionErrorDecrypter.DecryptError(reason)
|
failure, err := s.OnionErrorDecrypter.DecryptError(reason)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
r := bytes.NewReader(failureData)
|
r := bytes.NewReader(failure.Message)
|
||||||
failureMsg, err := lnwire.DecodeFailure(r, 0)
|
failureMsg, err := lnwire.DecodeFailure(r, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ForwardingError{
|
return &ForwardingError{
|
||||||
ErrorSource: source,
|
FailureSourceIdx: failure.SenderIdx,
|
||||||
FailureMessage: failureMsg,
|
FailureMessage: failureMsg,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,10 +163,7 @@ func initSwitchWithDB(startingHeight uint32, db *channeldb.DB) (*Switch, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv, _ := btcec.NewPrivateKey(btcec.S256())
|
|
||||||
pubkey := priv.PubKey()
|
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
SelfKey: pubkey,
|
|
||||||
DB: db,
|
DB: db,
|
||||||
SwitchPackager: channeldb.NewSwitchPackager(),
|
SwitchPackager: channeldb.NewSwitchPackager(),
|
||||||
FwdingLog: &mockForwardingLog{
|
FwdingLog: &mockForwardingLog{
|
||||||
@ -393,12 +390,9 @@ func (o *mockDeobfuscator) DecryptError(reason lnwire.OpaqueReason) (*Forwarding
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
priv, _ := btcec.NewPrivateKey(btcec.S256())
|
|
||||||
pubkey := priv.PubKey()
|
|
||||||
|
|
||||||
return &ForwardingError{
|
return &ForwardingError{
|
||||||
ErrorSource: pubkey,
|
FailureSourceIdx: 1,
|
||||||
FailureMessage: failure,
|
FailureMessage: failure,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/coreos/bbolt"
|
"github.com/coreos/bbolt"
|
||||||
@ -112,11 +111,6 @@ type ChanClose struct {
|
|||||||
// Config defines the configuration for the service. ALL elements within the
|
// Config defines the configuration for the service. ALL elements within the
|
||||||
// configuration MUST be non-nil for the service to carry out its duties.
|
// configuration MUST be non-nil for the service to carry out its duties.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// SelfKey is the key of the backing Lightning node. This key is used
|
|
||||||
// to properly craft failure messages, such that the Layer 3 router can
|
|
||||||
// properly route around link./vertex failures.
|
|
||||||
SelfKey *btcec.PublicKey
|
|
||||||
|
|
||||||
// FwdingLog is an interface that will be used by the switch to log
|
// FwdingLog is an interface that will be used by the switch to log
|
||||||
// forwarding events. A forwarding event happens each time a payment
|
// forwarding events. A forwarding event happens each time a payment
|
||||||
// circuit is successfully completed. So when we forward an HTLC, and a
|
// circuit is successfully completed. So when we forward an HTLC, and a
|
||||||
@ -776,8 +770,8 @@ func (s *Switch) handleLocalDispatch(pkt *htlcPacket) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Link %v not found", pkt.outgoingChanID)
|
log.Errorf("Link %v not found", pkt.outgoingChanID)
|
||||||
return &ForwardingError{
|
return &ForwardingError{
|
||||||
ErrorSource: s.cfg.SelfKey,
|
FailureSourceIdx: 0,
|
||||||
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,9 +784,9 @@ func (s *Switch) handleLocalDispatch(pkt *htlcPacket) error {
|
|||||||
// will be returned back to the router.
|
// will be returned back to the router.
|
||||||
htlcErr := lnwire.NewTemporaryChannelFailure(nil)
|
htlcErr := lnwire.NewTemporaryChannelFailure(nil)
|
||||||
return &ForwardingError{
|
return &ForwardingError{
|
||||||
ErrorSource: s.cfg.SelfKey,
|
FailureSourceIdx: 0,
|
||||||
ExtraMsg: err.Error(),
|
ExtraMsg: err.Error(),
|
||||||
FailureMessage: htlcErr,
|
FailureMessage: htlcErr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -808,8 +802,8 @@ func (s *Switch) handleLocalDispatch(pkt *htlcPacket) error {
|
|||||||
"satisfied", pkt.outgoingChanID)
|
"satisfied", pkt.outgoingChanID)
|
||||||
|
|
||||||
return &ForwardingError{
|
return &ForwardingError{
|
||||||
ErrorSource: s.cfg.SelfKey,
|
FailureSourceIdx: 0,
|
||||||
FailureMessage: htlcErr,
|
FailureMessage: htlcErr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -823,9 +817,9 @@ func (s *Switch) handleLocalDispatch(pkt *htlcPacket) error {
|
|||||||
// will be returned back to the router.
|
// will be returned back to the router.
|
||||||
htlcErr := lnwire.NewTemporaryChannelFailure(nil)
|
htlcErr := lnwire.NewTemporaryChannelFailure(nil)
|
||||||
return &ForwardingError{
|
return &ForwardingError{
|
||||||
ErrorSource: s.cfg.SelfKey,
|
FailureSourceIdx: 0,
|
||||||
ExtraMsg: err.Error(),
|
ExtraMsg: err.Error(),
|
||||||
FailureMessage: htlcErr,
|
FailureMessage: htlcErr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -967,9 +961,9 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter,
|
|||||||
failureMsg = lnwire.NewTemporaryChannelFailure(nil)
|
failureMsg = lnwire.NewTemporaryChannelFailure(nil)
|
||||||
}
|
}
|
||||||
failure = &ForwardingError{
|
failure = &ForwardingError{
|
||||||
ErrorSource: s.cfg.SelfKey,
|
FailureSourceIdx: 0,
|
||||||
ExtraMsg: userErr,
|
ExtraMsg: userErr,
|
||||||
FailureMessage: failureMsg,
|
FailureMessage: failureMsg,
|
||||||
}
|
}
|
||||||
|
|
||||||
// A payment had to be timed out on chain before it got past
|
// A payment had to be timed out on chain before it got past
|
||||||
@ -981,9 +975,9 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter,
|
|||||||
"on-chain, then cancelled back (hash=%v, pid=%d)",
|
"on-chain, then cancelled back (hash=%v, pid=%d)",
|
||||||
paymentHash, paymentID)
|
paymentHash, paymentID)
|
||||||
failure = &ForwardingError{
|
failure = &ForwardingError{
|
||||||
ErrorSource: s.cfg.SelfKey,
|
FailureSourceIdx: 0,
|
||||||
ExtraMsg: userErr,
|
ExtraMsg: userErr,
|
||||||
FailureMessage: lnwire.FailPermanentChannelFailure{},
|
FailureMessage: lnwire.FailPermanentChannelFailure{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// A regular multi-hop payment error that we'll need to
|
// A regular multi-hop payment error that we'll need to
|
||||||
@ -999,9 +993,9 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter,
|
|||||||
paymentHash, paymentID, err)
|
paymentHash, paymentID, err)
|
||||||
log.Error(userErr)
|
log.Error(userErr)
|
||||||
failure = &ForwardingError{
|
failure = &ForwardingError{
|
||||||
ErrorSource: s.cfg.SelfKey,
|
FailureSourceIdx: 0,
|
||||||
ExtraMsg: userErr,
|
ExtraMsg: userErr,
|
||||||
FailureMessage: lnwire.NewTemporaryChannelFailure(nil),
|
FailureMessage: lnwire.NewTemporaryChannelFailure(nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -610,10 +610,6 @@ func (m *SendToRouteResponse) GetFailure() *Failure {
|
|||||||
type Failure struct {
|
type Failure struct {
|
||||||
/// Failure code as defined in the Lightning spec
|
/// Failure code as defined in the Lightning spec
|
||||||
Code Failure_FailureCode `protobuf:"varint,1,opt,name=code,proto3,enum=routerrpc.Failure_FailureCode" json:"code,omitempty"`
|
Code Failure_FailureCode `protobuf:"varint,1,opt,name=code,proto3,enum=routerrpc.Failure_FailureCode" json:"code,omitempty"`
|
||||||
//*
|
|
||||||
//The node pubkey of the intermediate or final node that generated the failure
|
|
||||||
//message.
|
|
||||||
FailureSourcePubkey []byte `protobuf:"bytes,2,opt,name=failure_source_pubkey,json=failureSourcePubkey,proto3" json:"failure_source_pubkey,omitempty"`
|
|
||||||
/// An optional channel update message.
|
/// An optional channel update message.
|
||||||
ChannelUpdate *ChannelUpdate `protobuf:"bytes,3,opt,name=channel_update,json=channelUpdate,proto3" json:"channel_update,omitempty"`
|
ChannelUpdate *ChannelUpdate `protobuf:"bytes,3,opt,name=channel_update,json=channelUpdate,proto3" json:"channel_update,omitempty"`
|
||||||
/// A failure type-dependent htlc value.
|
/// A failure type-dependent htlc value.
|
||||||
@ -623,7 +619,11 @@ type Failure struct {
|
|||||||
/// A failure type-dependent cltv expiry value.
|
/// A failure type-dependent cltv expiry value.
|
||||||
CltvExpiry uint32 `protobuf:"varint,6,opt,name=cltv_expiry,json=cltvExpiry,proto3" json:"cltv_expiry,omitempty"`
|
CltvExpiry uint32 `protobuf:"varint,6,opt,name=cltv_expiry,json=cltvExpiry,proto3" json:"cltv_expiry,omitempty"`
|
||||||
/// A failure type-dependent flags value.
|
/// A failure type-dependent flags value.
|
||||||
Flags uint32 `protobuf:"varint,7,opt,name=flags,proto3" json:"flags,omitempty"`
|
Flags uint32 `protobuf:"varint,7,opt,name=flags,proto3" json:"flags,omitempty"`
|
||||||
|
//*
|
||||||
|
//The position in the path of the intermediate or final node that generated
|
||||||
|
//the failure message. Position zero is the sender node.
|
||||||
|
FailureSourceIndex uint32 `protobuf:"varint,8,opt,name=failure_source_index,json=failureSourceIndex,proto3" json:"failure_source_index,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
XXX_sizecache int32 `json:"-"`
|
XXX_sizecache int32 `json:"-"`
|
||||||
@ -661,13 +661,6 @@ func (m *Failure) GetCode() Failure_FailureCode {
|
|||||||
return Failure_RESERVED
|
return Failure_RESERVED
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Failure) GetFailureSourcePubkey() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.FailureSourcePubkey
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Failure) GetChannelUpdate() *ChannelUpdate {
|
func (m *Failure) GetChannelUpdate() *ChannelUpdate {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.ChannelUpdate
|
return m.ChannelUpdate
|
||||||
@ -703,6 +696,13 @@ func (m *Failure) GetFlags() uint32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Failure) GetFailureSourceIndex() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.FailureSourceIndex
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type ChannelUpdate struct {
|
type ChannelUpdate struct {
|
||||||
//*
|
//*
|
||||||
//The signature that validates the announced data and proves the ownership
|
//The signature that validates the announced data and proves the ownership
|
||||||
@ -1167,109 +1167,110 @@ func init() {
|
|||||||
func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) }
|
func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) }
|
||||||
|
|
||||||
var fileDescriptor_7a0613f69d37b0a5 = []byte{
|
var fileDescriptor_7a0613f69d37b0a5 = []byte{
|
||||||
// 1623 bytes of a gzipped FileDescriptorProto
|
// 1635 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdd, 0x72, 0x1a, 0xc9,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0x5f, 0x73, 0x22, 0xc7,
|
||||||
0x15, 0x5e, 0x04, 0x08, 0x71, 0xf8, 0x1b, 0xb5, 0x64, 0x79, 0x8c, 0x2c, 0xaf, 0x76, 0x92, 0x78,
|
0x11, 0x37, 0x02, 0x09, 0xd1, 0xfc, 0xd1, 0x6a, 0xa4, 0xd3, 0xed, 0xa1, 0xd3, 0x59, 0x5e, 0x27,
|
||||||
0x55, 0xae, 0x8d, 0x94, 0x90, 0xf2, 0xd6, 0x5e, 0x25, 0x85, 0xa1, 0x59, 0x26, 0x86, 0x19, 0x6d,
|
0x67, 0xd5, 0x95, 0x23, 0x39, 0xa4, 0xce, 0xe5, 0xa7, 0xa4, 0x38, 0x18, 0xcc, 0xfa, 0x60, 0x57,
|
||||||
0x03, 0xde, 0x75, 0x72, 0xd1, 0xd5, 0x82, 0x16, 0x4c, 0x09, 0x66, 0xd8, 0x99, 0x66, 0x63, 0xe5,
|
0x1e, 0xe0, 0xec, 0x4b, 0x1e, 0xa6, 0x46, 0xec, 0x08, 0xb6, 0x04, 0xbb, 0x78, 0x77, 0x70, 0x4e,
|
||||||
0x22, 0x77, 0xc9, 0x5d, 0x9e, 0x25, 0x79, 0x82, 0xbc, 0x47, 0x5e, 0x25, 0x57, 0xa9, 0xee, 0x1e,
|
0x79, 0xc8, 0x5b, 0x5e, 0x52, 0x95, 0xcf, 0x92, 0x7c, 0x82, 0x7c, 0x8f, 0x7c, 0x95, 0x3c, 0xa5,
|
||||||
0x60, 0x40, 0xc8, 0xeb, 0x2b, 0x31, 0xdf, 0xf9, 0xfa, 0x9c, 0xd3, 0xe7, 0xaf, 0x8f, 0xe0, 0x24,
|
0x66, 0x66, 0x81, 0x05, 0xa1, 0x8b, 0x9f, 0xc4, 0xfe, 0xfa, 0xd7, 0x7f, 0xa6, 0x7b, 0xba, 0xa7,
|
||||||
0x0c, 0x16, 0x82, 0x87, 0xe1, 0x7c, 0x78, 0xa5, 0x7f, 0x5d, 0xce, 0xc3, 0x40, 0x04, 0x28, 0xbf,
|
0x05, 0x27, 0x51, 0x38, 0x17, 0x3c, 0x8a, 0x66, 0xc3, 0x2b, 0xfd, 0xeb, 0x72, 0x16, 0x85, 0x22,
|
||||||
0xc2, 0xab, 0xf9, 0x70, 0x3e, 0xd4, 0xa8, 0xf5, 0xbf, 0x3d, 0x40, 0x3d, 0xee, 0x8f, 0xae, 0xd9,
|
0x44, 0x85, 0x25, 0x5e, 0x2d, 0x44, 0xb3, 0xa1, 0x46, 0xad, 0xff, 0xee, 0x00, 0xea, 0xf1, 0xc0,
|
||||||
0xfd, 0x8c, 0xfb, 0x82, 0xf0, 0x1f, 0x17, 0x3c, 0x12, 0x08, 0x41, 0x66, 0xc4, 0x23, 0x61, 0xa6,
|
0xbb, 0x66, 0xf7, 0x53, 0x1e, 0x08, 0xc2, 0x7f, 0x9a, 0xf3, 0x58, 0x20, 0x04, 0x39, 0x8f, 0xc7,
|
||||||
0xce, 0x53, 0x17, 0x45, 0xa2, 0x7e, 0x23, 0x03, 0xd2, 0x6c, 0x26, 0xcc, 0xbd, 0xf3, 0xd4, 0x45,
|
0xc2, 0xcc, 0x9c, 0x67, 0x2e, 0x4a, 0x44, 0xfd, 0x46, 0x06, 0x64, 0xd9, 0x54, 0x98, 0x3b, 0xe7,
|
||||||
0x9a, 0xc8, 0x9f, 0xe8, 0x0b, 0x28, 0xce, 0xf5, 0x39, 0x3a, 0x61, 0xd1, 0xc4, 0x4c, 0x2b, 0x76,
|
0x99, 0x8b, 0x2c, 0x91, 0x3f, 0xd1, 0x67, 0x50, 0x9a, 0x69, 0x3d, 0x3a, 0x66, 0xf1, 0xd8, 0xcc,
|
||||||
0x21, 0xc6, 0xda, 0x2c, 0x9a, 0xa0, 0x0b, 0x30, 0x6e, 0x3d, 0x9f, 0x4d, 0xe9, 0x70, 0x2a, 0x7e,
|
0x2a, 0x76, 0x31, 0xc1, 0xda, 0x2c, 0x1e, 0xa3, 0x0b, 0x30, 0x6e, 0xfd, 0x80, 0x4d, 0xe8, 0x70,
|
||||||
0xa2, 0x23, 0x3e, 0x15, 0xcc, 0xcc, 0x9c, 0xa7, 0x2e, 0xb2, 0xa4, 0xac, 0xf0, 0xc6, 0x54, 0xfc,
|
0x22, 0x7e, 0xa6, 0x1e, 0x9f, 0x08, 0x66, 0xe6, 0xce, 0x33, 0x17, 0xbb, 0xa4, 0xa2, 0xf0, 0xc6,
|
||||||
0xd4, 0x94, 0x28, 0xfa, 0x12, 0x2a, 0x4b, 0x65, 0xa1, 0xf6, 0xc2, 0xcc, 0x9e, 0xa7, 0x2e, 0xf2,
|
0x44, 0xfc, 0xdc, 0x94, 0x28, 0xfa, 0x02, 0x0e, 0x16, 0xc6, 0x22, 0x1d, 0x85, 0xb9, 0x7b, 0x9e,
|
||||||
0xa4, 0x3c, 0xdf, 0xf4, 0xed, 0x4b, 0xa8, 0x08, 0x6f, 0xc6, 0x83, 0x85, 0xa0, 0x11, 0x1f, 0x06,
|
0xb9, 0x28, 0x90, 0xca, 0x6c, 0x3d, 0xb6, 0x2f, 0xe0, 0x40, 0xf8, 0x53, 0x1e, 0xce, 0x05, 0x8d,
|
||||||
0xfe, 0x28, 0x32, 0xf7, 0xb5, 0xc6, 0x18, 0xee, 0x69, 0x14, 0x59, 0x50, 0xba, 0xe5, 0x9c, 0x4e,
|
0xf9, 0x30, 0x0c, 0xbc, 0xd8, 0xdc, 0xd3, 0x16, 0x13, 0xb8, 0xa7, 0x51, 0x64, 0x41, 0xf9, 0x96,
|
||||||
0xbd, 0x99, 0x27, 0x68, 0xc4, 0x84, 0x99, 0x53, 0xae, 0x17, 0x6e, 0x39, 0xef, 0x48, 0xac, 0xc7,
|
0x73, 0x3a, 0xf1, 0xa7, 0xbe, 0xa0, 0x31, 0x13, 0x66, 0x5e, 0x85, 0x5e, 0xbc, 0xe5, 0xbc, 0x23,
|
||||||
0x84, 0xf4, 0x2f, 0x58, 0x88, 0x71, 0xe0, 0xf9, 0x63, 0x3a, 0x9c, 0x30, 0x9f, 0x7a, 0x23, 0xf3,
|
0xb1, 0x1e, 0x13, 0x32, 0xbe, 0x70, 0x2e, 0x46, 0xa1, 0x1f, 0x8c, 0xe8, 0x70, 0xcc, 0x02, 0xea,
|
||||||
0xe0, 0x3c, 0x75, 0x91, 0x21, 0xe5, 0x25, 0xde, 0x98, 0x30, 0xdf, 0x1e, 0xa1, 0x33, 0x00, 0x75,
|
0x7b, 0xe6, 0xfe, 0x79, 0xe6, 0x22, 0x47, 0x2a, 0x0b, 0xbc, 0x31, 0x66, 0x81, 0xed, 0xa1, 0x33,
|
||||||
0x07, 0xa5, 0xce, 0xcc, 0x2b, 0x8b, 0x79, 0x89, 0x28, 0x5d, 0xa8, 0x06, 0x05, 0x15, 0x60, 0x3a,
|
0x00, 0x75, 0x06, 0x65, 0xce, 0x2c, 0x28, 0x8f, 0x05, 0x89, 0x28, 0x5b, 0xa8, 0x06, 0x45, 0x95,
|
||||||
0xf1, 0x7c, 0x11, 0x99, 0x70, 0x9e, 0xbe, 0x28, 0xd4, 0x8c, 0xcb, 0xa9, 0x2f, 0x63, 0x4d, 0xa4,
|
0x60, 0x3a, 0xf6, 0x03, 0x11, 0x9b, 0x70, 0x9e, 0xbd, 0x28, 0xd6, 0x8c, 0xcb, 0x49, 0x20, 0x73,
|
||||||
0xa4, 0xed, 0xf9, 0x82, 0x24, 0x49, 0xd6, 0x37, 0x70, 0xd4, 0x0f, 0xd9, 0xf0, 0x6e, 0x2b, 0xf8,
|
0x4d, 0xa4, 0xa4, 0xed, 0x07, 0x82, 0xa4, 0x49, 0xd6, 0x37, 0x70, 0xd4, 0x8f, 0xd8, 0xf0, 0x6e,
|
||||||
0xdb, 0x61, 0x4d, 0x3d, 0x08, 0xab, 0xf5, 0x37, 0x28, 0xc5, 0x87, 0x7a, 0x82, 0x89, 0x45, 0x84,
|
0x23, 0xf9, 0x9b, 0x69, 0xcd, 0x3c, 0x48, 0xab, 0xf5, 0x57, 0x28, 0x27, 0x4a, 0x3d, 0xc1, 0xc4,
|
||||||
0x7e, 0x0d, 0xd9, 0x48, 0x30, 0xc1, 0x15, 0xb9, 0x5c, 0x7b, 0x7a, 0xb9, 0xca, 0xf6, 0x65, 0x82,
|
0x3c, 0x46, 0xbf, 0x81, 0xdd, 0x58, 0x30, 0xc1, 0x15, 0xb9, 0x52, 0x7b, 0x7a, 0xb9, 0xac, 0xf6,
|
||||||
0xc8, 0x89, 0x66, 0xa1, 0x2a, 0x1c, 0xcc, 0x43, 0xee, 0xcd, 0xd8, 0x98, 0xab, 0x84, 0x16, 0xc9,
|
0x65, 0x8a, 0xc8, 0x89, 0x66, 0xa1, 0x2a, 0xec, 0xcf, 0x22, 0xee, 0x4f, 0xd9, 0x88, 0xab, 0x82,
|
||||||
0xea, 0x1b, 0x59, 0x90, 0x55, 0x87, 0x55, 0x3a, 0x0b, 0xb5, 0x62, 0xf2, 0x0e, 0x44, 0x8b, 0xac,
|
0x96, 0xc8, 0xf2, 0x1b, 0x59, 0xb0, 0xab, 0x94, 0x55, 0x39, 0x8b, 0xb5, 0x52, 0xfa, 0x0c, 0x44,
|
||||||
0xdf, 0x43, 0x45, 0x7d, 0xb7, 0x38, 0xff, 0x58, 0xc9, 0x3c, 0x85, 0x1c, 0x9b, 0xe9, 0xd8, 0xeb,
|
0x8b, 0xac, 0xdf, 0xc3, 0x81, 0xfa, 0x6e, 0x71, 0xfe, 0xb1, 0x2b, 0xf3, 0x14, 0xf2, 0x6c, 0xaa,
|
||||||
0xb2, 0xd9, 0x67, 0x33, 0x19, 0x76, 0x6b, 0x04, 0xc6, 0xfa, 0x7c, 0x34, 0x0f, 0xfc, 0x88, 0xcb,
|
0x73, 0xaf, 0xaf, 0xcd, 0x1e, 0x9b, 0xca, 0xb4, 0x5b, 0x1e, 0x18, 0x2b, 0xfd, 0x78, 0x16, 0x06,
|
||||||
0x54, 0x48, 0xe5, 0x32, 0x13, 0x32, 0x6d, 0x33, 0x79, 0x2a, 0xa5, 0x4e, 0x95, 0x63, 0xbc, 0xc5,
|
0x31, 0x97, 0xa5, 0x90, 0xc6, 0x65, 0x25, 0x64, 0xd9, 0xa6, 0x52, 0x2b, 0xa3, 0xb4, 0x2a, 0x09,
|
||||||
0x79, 0x37, 0x62, 0x02, 0xbd, 0xd4, 0x15, 0x40, 0xa7, 0xc1, 0xf0, 0x4e, 0xd6, 0x14, 0xbb, 0x8f,
|
0xde, 0xe2, 0xbc, 0x1b, 0x33, 0x81, 0x5e, 0xea, 0x1b, 0x40, 0x27, 0xe1, 0xf0, 0x4e, 0xde, 0x29,
|
||||||
0xd5, 0x97, 0x24, 0xdc, 0x09, 0x86, 0x77, 0x4d, 0x09, 0x5a, 0x7f, 0xd6, 0xb5, 0xdd, 0x0f, 0xb4,
|
0x76, 0x9f, 0x98, 0x2f, 0x4b, 0xb8, 0x13, 0x0e, 0xef, 0x9a, 0x12, 0xb4, 0xfe, 0xa4, 0xef, 0x76,
|
||||||
0xef, 0x9f, 0x1c, 0xde, 0x75, 0x08, 0xf6, 0x1e, 0x0f, 0x01, 0x85, 0xa3, 0x0d, 0xe5, 0xf1, 0x2d,
|
0x3f, 0xd4, 0xb1, 0xff, 0xe2, 0xf4, 0xae, 0x52, 0xb0, 0xf3, 0x78, 0x0a, 0x28, 0x1c, 0xad, 0x19,
|
||||||
0x92, 0x91, 0x4d, 0x6d, 0x45, 0xf6, 0x2b, 0xc8, 0xdd, 0x32, 0x6f, 0xba, 0x08, 0x97, 0x8a, 0x51,
|
0x4f, 0x4e, 0x91, 0xce, 0x6c, 0x66, 0x23, 0xb3, 0x5f, 0x42, 0xfe, 0x96, 0xf9, 0x93, 0x79, 0xb4,
|
||||||
0x22, 0x4d, 0x2d, 0x2d, 0x21, 0x4b, 0x8a, 0xf5, 0x8f, 0x1c, 0xe4, 0x62, 0x10, 0xd5, 0x20, 0x33,
|
0x30, 0x8c, 0x52, 0x65, 0x6a, 0x69, 0x09, 0x59, 0x50, 0xac, 0xbf, 0xe7, 0x21, 0x9f, 0x80, 0xa8,
|
||||||
0x0c, 0x46, 0xcb, 0xec, 0xbe, 0x78, 0x78, 0x6c, 0xf9, 0xb7, 0x11, 0x8c, 0x38, 0x51, 0x5c, 0x54,
|
0x06, 0xb9, 0x61, 0xe8, 0x2d, 0xaa, 0xfb, 0xe2, 0xa1, 0xda, 0xe2, 0x6f, 0x23, 0xf4, 0x38, 0x51,
|
||||||
0x83, 0x27, 0xb1, 0x2a, 0x1a, 0x05, 0x8b, 0x70, 0xc8, 0xe9, 0x7c, 0x71, 0x73, 0xc7, 0xef, 0xe3,
|
0x5c, 0xf4, 0x07, 0xa8, 0xc8, 0x1b, 0x1d, 0xf0, 0x09, 0x9d, 0xcf, 0x3c, 0xb6, 0x2c, 0xa8, 0x99,
|
||||||
0x84, 0x1f, 0xc5, 0xc2, 0x9e, 0x92, 0x5d, 0x2b, 0x11, 0xfa, 0x03, 0x94, 0x65, 0x17, 0xf8, 0x7c,
|
0xd2, 0x6e, 0x68, 0xc2, 0x40, 0xc9, 0x49, 0x79, 0x98, 0xfe, 0x44, 0xa7, 0x50, 0x18, 0x8b, 0xc9,
|
||||||
0x4a, 0x17, 0xf3, 0x11, 0x5b, 0x15, 0x81, 0x99, 0xb0, 0xd8, 0xd0, 0x84, 0x81, 0x92, 0x93, 0xd2,
|
0x50, 0x57, 0x22, 0xa7, 0x9a, 0x62, 0x5f, 0x02, 0xaa, 0x06, 0x16, 0x94, 0xc3, 0xc0, 0x0f, 0x03,
|
||||||
0x30, 0xf9, 0x89, 0x4e, 0x21, 0x3f, 0x11, 0xd3, 0xa1, 0xce, 0x5e, 0x46, 0x35, 0xd2, 0x81, 0x04,
|
0x1a, 0x8f, 0x19, 0xad, 0xbd, 0xfe, 0x5a, 0x35, 0x6b, 0x89, 0x14, 0x15, 0xd8, 0x1b, 0xb3, 0xda,
|
||||||
0x54, 0xde, 0x2c, 0x28, 0x05, 0xbe, 0x17, 0xf8, 0x34, 0x9a, 0x30, 0x5a, 0x7b, 0xfd, 0xb5, 0x6a,
|
0xeb, 0xaf, 0xd1, 0xa7, 0x50, 0x54, 0x2d, 0xc3, 0x3f, 0xcc, 0xfc, 0xe8, 0x5e, 0x75, 0x69, 0x99,
|
||||||
0xf0, 0x22, 0x29, 0x28, 0xb0, 0x37, 0x61, 0xb5, 0xd7, 0x5f, 0xa3, 0xcf, 0xa1, 0xa0, 0xda, 0x8c,
|
0xa8, 0x2e, 0xc2, 0x0a, 0x41, 0xc7, 0xb0, 0x7b, 0x3b, 0x61, 0xa3, 0x58, 0x75, 0x66, 0x99, 0xe8,
|
||||||
0x7f, 0x98, 0x7b, 0xe1, 0xbd, 0xea, 0xec, 0x12, 0x51, 0x9d, 0x87, 0x15, 0x82, 0x8e, 0x21, 0x7b,
|
0x0f, 0xf4, 0x15, 0x1c, 0x27, 0x39, 0xa0, 0x71, 0x38, 0x8f, 0x86, 0x9c, 0xfa, 0x81, 0xc7, 0x3f,
|
||||||
0x3b, 0x65, 0xe3, 0x48, 0x75, 0x73, 0x89, 0xe8, 0x0f, 0xeb, 0xbf, 0x19, 0x28, 0x24, 0x42, 0x80,
|
0xa8, 0xbe, 0x2c, 0x13, 0x94, 0xc8, 0x7a, 0x4a, 0x64, 0x4b, 0x89, 0xf5, 0x9f, 0x1c, 0x14, 0x53,
|
||||||
0x8a, 0x70, 0x40, 0x70, 0x0f, 0x93, 0x77, 0xb8, 0x69, 0x7c, 0x86, 0x4c, 0x38, 0x1e, 0x38, 0x6f,
|
0x09, 0x40, 0x25, 0xd8, 0x27, 0xb8, 0x87, 0xc9, 0x3b, 0xdc, 0x34, 0x3e, 0x41, 0x26, 0x1c, 0x0f,
|
||||||
0x1d, 0xf7, 0x7b, 0x87, 0x5e, 0xd7, 0xdf, 0x77, 0xb1, 0xd3, 0xa7, 0xed, 0x7a, 0xaf, 0x6d, 0xa4,
|
0x9c, 0xb7, 0x8e, 0xfb, 0x83, 0x43, 0xaf, 0xeb, 0xef, 0xbb, 0xd8, 0xe9, 0xd3, 0x76, 0xbd, 0xd7,
|
||||||
0xd0, 0x73, 0x30, 0x6d, 0xa7, 0xe1, 0x12, 0x82, 0x1b, 0xfd, 0x95, 0xac, 0xde, 0x75, 0x07, 0x4e,
|
0x36, 0x32, 0xe8, 0x39, 0x98, 0xb6, 0xd3, 0x70, 0x09, 0xc1, 0x8d, 0xfe, 0x52, 0x56, 0xef, 0xba,
|
||||||
0xdf, 0xd8, 0x43, 0x9f, 0xc3, 0x69, 0xcb, 0x76, 0xea, 0x1d, 0xba, 0xe6, 0x34, 0x3a, 0xfd, 0x77,
|
0x03, 0xa7, 0x6f, 0xec, 0xa0, 0x4f, 0xe1, 0xb4, 0x65, 0x3b, 0xf5, 0x0e, 0x5d, 0x71, 0x1a, 0x9d,
|
||||||
0x14, 0xff, 0x70, 0x6d, 0x93, 0xf7, 0x46, 0x7a, 0x17, 0xa1, 0xdd, 0xef, 0x34, 0x96, 0x1a, 0x32,
|
0xfe, 0x3b, 0x8a, 0x7f, 0xbc, 0xb6, 0xc9, 0x7b, 0x23, 0xbb, 0x8d, 0xd0, 0xee, 0x77, 0x1a, 0x0b,
|
||||||
0xe8, 0x19, 0x3c, 0xd1, 0x04, 0x7d, 0x84, 0xf6, 0x5d, 0x97, 0xf6, 0x5c, 0xd7, 0x31, 0xb2, 0xe8,
|
0x0b, 0x39, 0xf4, 0x0c, 0x9e, 0x68, 0x82, 0x56, 0xa1, 0x7d, 0xd7, 0xa5, 0x3d, 0xd7, 0x75, 0x8c,
|
||||||
0x10, 0x4a, 0xb6, 0xf3, 0xae, 0xde, 0xb1, 0x9b, 0x94, 0xe0, 0x7a, 0xa7, 0x6b, 0xec, 0xa3, 0x23,
|
0x5d, 0x74, 0x08, 0x65, 0xdb, 0x79, 0x57, 0xef, 0xd8, 0x4d, 0x4a, 0x70, 0xbd, 0xd3, 0x35, 0xf6,
|
||||||
0xa8, 0x6c, 0xf3, 0x72, 0x52, 0xc5, 0x92, 0xe7, 0x3a, 0xb6, 0xeb, 0xd0, 0x77, 0x98, 0xf4, 0x6c,
|
0xd0, 0x11, 0x1c, 0x6c, 0xf2, 0xf2, 0xd2, 0xc4, 0x82, 0xe7, 0x3a, 0xb6, 0xeb, 0xd0, 0x77, 0x98,
|
||||||
0xd7, 0x31, 0x0e, 0xd0, 0x09, 0xa0, 0x4d, 0x51, 0xbb, 0x5b, 0x6f, 0x18, 0x79, 0xf4, 0x04, 0x0e,
|
0xf4, 0x6c, 0xd7, 0x31, 0xf6, 0xd1, 0x09, 0xa0, 0x75, 0x51, 0xbb, 0x5b, 0x6f, 0x18, 0x05, 0xf4,
|
||||||
0x37, 0xf1, 0xb7, 0xf8, 0xbd, 0x01, 0x32, 0x0c, 0xda, 0x31, 0xfa, 0x06, 0x77, 0xdc, 0xef, 0x69,
|
0x04, 0x0e, 0xd7, 0xf1, 0xb7, 0xf8, 0xbd, 0x01, 0x32, 0x0d, 0x3a, 0x30, 0xfa, 0x06, 0x77, 0xdc,
|
||||||
0xd7, 0x76, 0xec, 0xee, 0xa0, 0x6b, 0x14, 0xd0, 0x31, 0x18, 0x2d, 0x8c, 0xa9, 0xed, 0xf4, 0x06,
|
0x1f, 0x68, 0xd7, 0x76, 0xec, 0xee, 0xa0, 0x6b, 0x14, 0xd1, 0x31, 0x18, 0x2d, 0x8c, 0xa9, 0xed,
|
||||||
0xad, 0x96, 0xdd, 0xb0, 0xb1, 0xd3, 0x37, 0x8a, 0xda, 0xf2, 0xae, 0x8b, 0x97, 0xe4, 0x81, 0x46,
|
0xf4, 0x06, 0xad, 0x96, 0xdd, 0xb0, 0xb1, 0xd3, 0x37, 0x4a, 0xda, 0xf3, 0xb6, 0x83, 0x97, 0xa5,
|
||||||
0xbb, 0xee, 0x38, 0xb8, 0x43, 0x9b, 0x76, 0xaf, 0xfe, 0xa6, 0x83, 0x9b, 0x46, 0x19, 0x9d, 0xc1,
|
0x42, 0xa3, 0x5d, 0x77, 0x1c, 0xdc, 0xa1, 0x4d, 0xbb, 0x57, 0x7f, 0xd3, 0xc1, 0x4d, 0xa3, 0x82,
|
||||||
0xb3, 0x3e, 0xee, 0x5e, 0xbb, 0xa4, 0x4e, 0xde, 0xd3, 0xa5, 0xbc, 0x55, 0xb7, 0x3b, 0x03, 0x82,
|
0xce, 0xe0, 0x59, 0x1f, 0x77, 0xaf, 0x5d, 0x52, 0x27, 0xef, 0xe9, 0x42, 0xde, 0xaa, 0xdb, 0x9d,
|
||||||
0x8d, 0x0a, 0xfa, 0x02, 0xce, 0x08, 0xfe, 0x6e, 0x60, 0x13, 0xdc, 0xa4, 0x8e, 0xdb, 0xc4, 0xb4,
|
0x01, 0xc1, 0xc6, 0x01, 0xfa, 0x0c, 0xce, 0x08, 0xfe, 0x7e, 0x60, 0x13, 0xdc, 0xa4, 0x8e, 0xdb,
|
||||||
0x85, 0xeb, 0xfd, 0x01, 0xc1, 0xb4, 0x6b, 0xf7, 0x7a, 0xb6, 0xf3, 0xad, 0x61, 0xa0, 0x5f, 0xc2,
|
0xc4, 0xb4, 0x85, 0xeb, 0xfd, 0x01, 0xc1, 0xb4, 0x6b, 0xf7, 0x7a, 0xb6, 0xf3, 0xad, 0x61, 0xa0,
|
||||||
0xf9, 0x8a, 0xb2, 0x52, 0xb0, 0xc5, 0x3a, 0x94, 0xf7, 0x5b, 0xe6, 0xd3, 0xc1, 0x3f, 0xf4, 0xe9,
|
0x5f, 0xc1, 0xf9, 0x92, 0xb2, 0x34, 0xb0, 0xc1, 0x3a, 0x94, 0xe7, 0x5b, 0xd4, 0xd3, 0xc1, 0x3f,
|
||||||
0x35, 0xc6, 0xc4, 0x40, 0xa8, 0x0a, 0x27, 0x6b, 0xf3, 0xda, 0x40, 0x6c, 0xfb, 0x48, 0xca, 0xae,
|
0xf6, 0xe9, 0x35, 0xc6, 0xc4, 0x40, 0xa8, 0x0a, 0x27, 0x2b, 0xf7, 0xda, 0x41, 0xe2, 0xfb, 0x48,
|
||||||
0x31, 0xe9, 0xd6, 0x1d, 0x99, 0xe0, 0x0d, 0xd9, 0xb1, 0x74, 0x7b, 0x2d, 0xdb, 0x76, 0xfb, 0x89,
|
0xca, 0xae, 0x31, 0xe9, 0xd6, 0x1d, 0x59, 0xe0, 0x35, 0xd9, 0xb1, 0x0c, 0x7b, 0x25, 0xdb, 0x0c,
|
||||||
0xf5, 0xaf, 0x34, 0x94, 0x36, 0x8a, 0x1e, 0x3d, 0x87, 0x7c, 0xe4, 0x8d, 0x7d, 0x26, 0x64, 0x2b,
|
0xfb, 0xc9, 0x77, 0xb9, 0xfd, 0x1d, 0x23, 0x6b, 0xfd, 0x33, 0x0b, 0xe5, 0xb5, 0x66, 0x41, 0xcf,
|
||||||
0xeb, 0x2e, 0x5f, 0x03, 0xea, 0xa5, 0x98, 0x30, 0xcf, 0xd7, 0xe3, 0x45, 0x77, 0x5b, 0x5e, 0x21,
|
0xa1, 0x10, 0xfb, 0xa3, 0x80, 0x09, 0xd9, 0xce, 0xba, 0xd3, 0x57, 0x80, 0x7a, 0x2d, 0xc6, 0xcc,
|
||||||
0x6a, 0xb8, 0x3c, 0x85, 0xdc, 0xf2, 0xa5, 0x49, 0xab, 0x06, 0xd9, 0x1f, 0xea, 0x17, 0xe6, 0x39,
|
0x0f, 0xf4, 0x88, 0xd1, 0x23, 0xb6, 0xa0, 0x10, 0x35, 0x60, 0x9e, 0x42, 0x7e, 0xf1, 0xda, 0x64,
|
||||||
0xe4, 0xe5, 0xfc, 0x8a, 0x04, 0x9b, 0xcd, 0x55, 0xef, 0x94, 0xc8, 0x1a, 0x40, 0xbf, 0x80, 0xd2,
|
0x55, 0x63, 0xed, 0x0d, 0xf5, 0x2b, 0xf3, 0x1c, 0x0a, 0x72, 0x86, 0xc5, 0x82, 0x4d, 0x67, 0xaa,
|
||||||
0x8c, 0x47, 0x11, 0x1b, 0x73, 0xaa, 0xeb, 0x1f, 0x14, 0xa3, 0x18, 0x83, 0x2d, 0x89, 0x49, 0xd2,
|
0xe7, 0xca, 0x64, 0x05, 0xa0, 0xcf, 0xa1, 0x3c, 0xe5, 0x71, 0xcc, 0x46, 0x9c, 0xea, 0xbe, 0x01,
|
||||||
0xb2, 0x7f, 0x35, 0x29, 0xab, 0x49, 0x31, 0xa8, 0x49, 0xdb, 0xe3, 0x53, 0xb0, 0xb8, 0xcd, 0x92,
|
0xc5, 0x28, 0x25, 0x60, 0x4b, 0xb5, 0xcf, 0xe7, 0xb0, 0xe8, 0xe3, 0x84, 0xb4, 0xab, 0x49, 0x09,
|
||||||
0xe3, 0x53, 0x30, 0xf4, 0x0a, 0x0e, 0x75, 0x2f, 0x7b, 0xbe, 0x37, 0x5b, 0xcc, 0x74, 0x4f, 0xe7,
|
0xa8, 0x49, 0x9b, 0x23, 0x54, 0xb0, 0xa4, 0x3d, 0xd3, 0x23, 0x54, 0x30, 0xf4, 0x0a, 0x0e, 0xf5,
|
||||||
0x94, 0xcb, 0x15, 0xd5, 0xd3, 0x1a, 0x57, 0xad, 0xfd, 0x0c, 0x0e, 0x6e, 0x58, 0xc4, 0xe5, 0xe4,
|
0x0c, 0xf0, 0x03, 0x7f, 0x3a, 0x9f, 0xea, 0x59, 0x90, 0x57, 0x21, 0x1f, 0xa8, 0x59, 0xa0, 0x71,
|
||||||
0x56, 0xef, 0x67, 0x89, 0xe4, 0xe4, 0x77, 0x8b, 0x73, 0x29, 0x92, 0xf3, 0x3c, 0x94, 0xd3, 0x24,
|
0x35, 0x12, 0x9e, 0xc1, 0xfe, 0x0d, 0x8b, 0xb9, 0x9c, 0xde, 0x49, 0xaf, 0xe6, 0xe5, 0x77, 0x8b,
|
||||||
0xaf, 0x45, 0xb7, 0x9c, 0x13, 0x19, 0xc7, 0x95, 0x05, 0xf6, 0x61, 0x6d, 0xa1, 0x90, 0xb0, 0xa0,
|
0x73, 0x29, 0x92, 0x33, 0x3d, 0x92, 0x53, 0xa8, 0xa0, 0x45, 0xb7, 0x9c, 0x13, 0x99, 0xc7, 0xa5,
|
||||||
0x71, 0x65, 0xe1, 0x15, 0x1c, 0xf2, 0x0f, 0x22, 0x64, 0x34, 0x98, 0xb3, 0x1f, 0x17, 0x9c, 0x8e,
|
0x07, 0xf6, 0x61, 0xe5, 0xa1, 0x98, 0xf2, 0xa0, 0x71, 0xe5, 0xe1, 0x15, 0x1c, 0xf2, 0x0f, 0x22,
|
||||||
0x98, 0x60, 0x66, 0x51, 0x05, 0xb7, 0xa2, 0x04, 0xae, 0xc2, 0x9b, 0x4c, 0x30, 0xeb, 0x39, 0x54,
|
0x62, 0x34, 0x9c, 0xb1, 0x9f, 0xe6, 0x9c, 0x7a, 0x4c, 0x30, 0xb3, 0xa4, 0x92, 0x7b, 0xa0, 0x04,
|
||||||
0x09, 0x8f, 0xb8, 0xe8, 0x7a, 0x51, 0xe4, 0x05, 0x7e, 0x23, 0xf0, 0x45, 0x18, 0x4c, 0xe3, 0x07,
|
0xae, 0xc2, 0x9b, 0x4c, 0x30, 0xeb, 0x39, 0x54, 0x09, 0x8f, 0xb9, 0xe8, 0xfa, 0x71, 0xec, 0x87,
|
||||||
0xc0, 0x3a, 0x83, 0xd3, 0x9d, 0x52, 0x3d, 0xc1, 0xe5, 0xe1, 0xef, 0x16, 0x3c, 0xbc, 0xdf, 0x7d,
|
0x41, 0x23, 0x0c, 0x44, 0x14, 0x4e, 0x92, 0x47, 0xc0, 0x3a, 0x83, 0xd3, 0xad, 0x52, 0x3d, 0xc5,
|
||||||
0xf8, 0x2d, 0x9c, 0xee, 0x94, 0xc6, 0xe3, 0xff, 0x2b, 0xc8, 0xfa, 0xc1, 0x88, 0x47, 0x66, 0x4a,
|
0xa5, 0xf2, 0xf7, 0x73, 0x1e, 0xdd, 0x6f, 0x57, 0x7e, 0x0b, 0xa7, 0x5b, 0xa5, 0xc9, 0x13, 0xf0,
|
||||||
0x2d, 0x00, 0x27, 0x89, 0xb9, 0xe9, 0x04, 0x23, 0xde, 0xf6, 0x22, 0x11, 0x84, 0xf7, 0x44, 0x93,
|
0x25, 0xec, 0x06, 0xa1, 0xc7, 0x63, 0x33, 0xa3, 0x96, 0x80, 0x93, 0xd4, 0xbc, 0x75, 0x42, 0x8f,
|
||||||
0xac, 0xff, 0xa4, 0xa0, 0x90, 0x80, 0xd1, 0x09, 0xec, 0xc7, 0x33, 0x5a, 0x17, 0x55, 0xfc, 0x85,
|
0xb7, 0xfd, 0x58, 0x84, 0xd1, 0x3d, 0xd1, 0x24, 0xeb, 0xdf, 0x19, 0x28, 0xa6, 0x60, 0x74, 0x02,
|
||||||
0x5e, 0x42, 0x79, 0xca, 0x22, 0x41, 0xe5, 0xc8, 0xa6, 0x32, 0x49, 0xf1, 0x7b, 0xb7, 0x85, 0xa2,
|
0x7b, 0xb3, 0xf9, 0xcd, 0x1d, 0xbf, 0x4f, 0x2e, 0x55, 0xf2, 0x85, 0x5e, 0x42, 0x65, 0xc2, 0x62,
|
||||||
0x6f, 0xe0, 0x69, 0x20, 0x26, 0x3c, 0xd4, 0xab, 0x4c, 0xb4, 0x18, 0x0e, 0x79, 0x14, 0xd1, 0x79,
|
0x41, 0xe5, 0xf8, 0xa3, 0xb2, 0x48, 0xc9, 0x9b, 0xb7, 0x81, 0xa2, 0x6f, 0xe0, 0x69, 0x28, 0xc6,
|
||||||
0x18, 0xdc, 0xa8, 0x52, 0xdb, 0x23, 0x8f, 0x89, 0xd1, 0x6b, 0x38, 0x88, 0x6b, 0x24, 0x32, 0x33,
|
0x3c, 0xd2, 0xeb, 0x4c, 0x3c, 0x1f, 0x0e, 0x79, 0x1c, 0xd3, 0x59, 0x14, 0xde, 0xa8, 0xab, 0xb6,
|
||||||
0xca, 0xf5, 0x67, 0x0f, 0x47, 0xfe, 0xd2, 0xfb, 0x15, 0xd5, 0xfa, 0x77, 0x0a, 0xca, 0x9b, 0x42,
|
0x43, 0x1e, 0x13, 0xa3, 0xd7, 0xb0, 0x9f, 0xdc, 0x91, 0xd8, 0xcc, 0xa9, 0xd0, 0x9f, 0x3d, 0x7c,
|
||||||
0xf4, 0x42, 0x55, 0xbf, 0x2a, 0x41, 0x6f, 0xa4, 0xee, 0x91, 0x21, 0x09, 0xe4, 0x93, 0xef, 0x52,
|
0x2a, 0x16, 0xd1, 0x2f, 0xa9, 0xd6, 0xbf, 0x32, 0x50, 0x59, 0x17, 0xa2, 0x17, 0xea, 0xf6, 0xab,
|
||||||
0x83, 0xe3, 0x99, 0xe7, 0xd3, 0x39, 0xf7, 0xd9, 0xd4, 0xfb, 0x2b, 0xa7, 0xcb, 0x45, 0x22, 0xad,
|
0x2b, 0xe8, 0x7b, 0xea, 0x1c, 0x39, 0x92, 0x42, 0x7e, 0xf1, 0x59, 0x6a, 0x70, 0x3c, 0xf5, 0x03,
|
||||||
0xd8, 0x3b, 0x65, 0xc8, 0x82, 0xe2, 0xc6, 0xa5, 0x33, 0xea, 0xd2, 0x1b, 0xd8, 0xab, 0x7f, 0xa6,
|
0x3a, 0xe3, 0x01, 0x9b, 0xf8, 0x7f, 0xe1, 0x74, 0xb1, 0x4c, 0x64, 0x15, 0x7b, 0xab, 0x0c, 0x59,
|
||||||
0xa0, 0x98, 0x5c, 0x89, 0x50, 0x09, 0xf2, 0xb6, 0x43, 0x5b, 0x1d, 0xfb, 0xdb, 0x76, 0xdf, 0xf8,
|
0x50, 0x5a, 0x3b, 0x74, 0x4e, 0x1d, 0x7a, 0x0d, 0x7b, 0xf5, 0x8f, 0x0c, 0x94, 0xd2, 0x6b, 0x11,
|
||||||
0x4c, 0x7e, 0xf6, 0x06, 0x8d, 0x06, 0xc6, 0x4d, 0xdc, 0x34, 0x52, 0x08, 0x41, 0x59, 0x4e, 0x02,
|
0x2a, 0x43, 0xc1, 0x76, 0x68, 0xab, 0x63, 0x7f, 0xdb, 0xee, 0x1b, 0x9f, 0xc8, 0xcf, 0xde, 0xa0,
|
||||||
0xdc, 0xa4, 0x7d, 0xbb, 0x8b, 0xdd, 0x81, 0x7c, 0x16, 0x8e, 0xa0, 0x12, 0x63, 0x8e, 0x4b, 0x89,
|
0xd1, 0xc0, 0xb8, 0x89, 0x9b, 0x46, 0x06, 0x21, 0xa8, 0xc8, 0x79, 0x80, 0x9b, 0xb4, 0x6f, 0x77,
|
||||||
0x3b, 0xe8, 0x63, 0x23, 0x8d, 0x0c, 0x28, 0xc6, 0x20, 0x26, 0xc4, 0x25, 0x46, 0x46, 0xce, 0xb2,
|
0xb1, 0x3b, 0x90, 0x8f, 0xc3, 0x11, 0x1c, 0x24, 0x98, 0xe3, 0x52, 0xe2, 0x0e, 0xfa, 0xd8, 0xc8,
|
||||||
0x18, 0x79, 0xf8, 0xc4, 0x34, 0x71, 0xbf, 0x6e, 0x77, 0x7a, 0x46, 0xb6, 0xf6, 0xf7, 0x0c, 0xec,
|
0x22, 0x03, 0x4a, 0x09, 0x88, 0x09, 0x71, 0x89, 0x91, 0x93, 0x13, 0x2d, 0x41, 0x1e, 0x3e, 0x34,
|
||||||
0xab, 0x15, 0x22, 0x44, 0x6d, 0x28, 0x24, 0x76, 0x71, 0x74, 0x96, 0xc8, 0xc0, 0xc3, 0x1d, 0xbd,
|
0x4d, 0xdc, 0xaf, 0xdb, 0x9d, 0x9e, 0xb1, 0x5b, 0xfb, 0x5b, 0x0e, 0xf6, 0xd4, 0x1a, 0x11, 0xa1,
|
||||||
0x6a, 0xee, 0xde, 0xf1, 0x16, 0xd1, 0x6f, 0x52, 0xe8, 0x8f, 0x50, 0x4c, 0x6e, 0x96, 0x28, 0xb9,
|
0x36, 0x14, 0x53, 0xfb, 0x38, 0x3a, 0x4b, 0x55, 0xe0, 0xe1, 0x9e, 0x5e, 0x35, 0xb7, 0xef, 0x79,
|
||||||
0x31, 0xec, 0x58, 0x39, 0x3f, 0xaa, 0xeb, 0x2d, 0x18, 0x38, 0x12, 0xde, 0x4c, 0xbe, 0xf6, 0xf1,
|
0xf3, 0xf8, 0xab, 0x0c, 0xfa, 0x0e, 0x4a, 0xe9, 0xed, 0x12, 0xa5, 0xb7, 0x86, 0x2d, 0x6b, 0xe7,
|
||||||
0xce, 0x86, 0xaa, 0x09, 0xfe, 0xd6, 0x22, 0x58, 0x3d, 0xdd, 0x29, 0x8b, 0xfb, 0xa3, 0xa3, 0xaf,
|
0x47, 0x6d, 0xbd, 0x05, 0x03, 0xc7, 0xc2, 0x9f, 0xca, 0x2d, 0x21, 0xd9, 0xdb, 0x50, 0x35, 0xc5,
|
||||||
0x18, 0x6f, 0x4d, 0x0f, 0xae, 0xb8, 0xb9, 0xaa, 0x55, 0x5f, 0x3c, 0x26, 0x8e, 0xb5, 0x8d, 0xe0,
|
0xdf, 0x58, 0x06, 0xab, 0xa7, 0x5b, 0x65, 0x49, 0x7f, 0x74, 0xf4, 0x11, 0x93, 0xcd, 0xe9, 0xc1,
|
||||||
0x68, 0x47, 0x27, 0xa3, 0x5f, 0x25, 0x3d, 0x78, 0x74, 0x0e, 0x54, 0x5f, 0xfe, 0x1c, 0x6d, 0x6d,
|
0x11, 0xd7, 0xd7, 0xb5, 0xea, 0x8b, 0xc7, 0xc4, 0x89, 0x35, 0x0f, 0x8e, 0xb6, 0x74, 0x32, 0xfa,
|
||||||
0x65, 0x47, 0xcb, 0x6f, 0x58, 0x79, 0x7c, 0x60, 0x6c, 0x58, 0xf9, 0xc8, 0xe4, 0x78, 0xf3, 0xdb,
|
0x75, 0x3a, 0x82, 0x47, 0xe7, 0x40, 0xf5, 0xe5, 0xff, 0xa3, 0xad, 0xbc, 0x6c, 0x69, 0xf9, 0x35,
|
||||||
0x3f, 0x5d, 0x8d, 0x3d, 0x31, 0x59, 0xdc, 0x5c, 0x0e, 0x83, 0xd9, 0xd5, 0xd4, 0x1b, 0x4f, 0x84,
|
0x2f, 0x8f, 0x0f, 0x8c, 0x35, 0x2f, 0x1f, 0x99, 0x1c, 0x6f, 0x7e, 0xfb, 0xc7, 0xab, 0x91, 0x2f,
|
||||||
0xef, 0xf9, 0x63, 0x9f, 0x8b, 0xbf, 0x04, 0xe1, 0xdd, 0xd5, 0xd4, 0x1f, 0x5d, 0xa9, 0x2d, 0xf4,
|
0xc6, 0xf3, 0x9b, 0xcb, 0x61, 0x38, 0xbd, 0x9a, 0xf8, 0xa3, 0xb1, 0x08, 0xfc, 0x60, 0x14, 0x70,
|
||||||
0x6a, 0xa5, 0xee, 0x66, 0x5f, 0xfd, 0x0f, 0xf7, 0xbb, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xb7,
|
0xf1, 0xe7, 0x30, 0xba, 0xbb, 0x9a, 0x04, 0xde, 0x95, 0xda, 0x44, 0xaf, 0x96, 0xe6, 0x6e, 0xf6,
|
||||||
0x0c, 0x44, 0x60, 0xf3, 0x0d, 0x00, 0x00,
|
0xd4, 0xff, 0x71, 0xbf, 0xfb, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2f, 0xaa, 0x9f, 0x4e, 0xf7,
|
||||||
|
0x0d, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
@ -199,11 +199,7 @@ message Failure {
|
|||||||
/// Failure code as defined in the Lightning spec
|
/// Failure code as defined in the Lightning spec
|
||||||
FailureCode code = 1;
|
FailureCode code = 1;
|
||||||
|
|
||||||
/**
|
reserved 2;
|
||||||
The node pubkey of the intermediate or final node that generated the failure
|
|
||||||
message.
|
|
||||||
**/
|
|
||||||
bytes failure_source_pubkey = 2;
|
|
||||||
|
|
||||||
/// An optional channel update message.
|
/// An optional channel update message.
|
||||||
ChannelUpdate channel_update = 3;
|
ChannelUpdate channel_update = 3;
|
||||||
@ -219,6 +215,12 @@ message Failure {
|
|||||||
|
|
||||||
/// A failure type-dependent flags value.
|
/// A failure type-dependent flags value.
|
||||||
uint32 flags = 7;
|
uint32 flags = 7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The position in the path of the intermediate or final node that generated
|
||||||
|
the failure message. Position zero is the sender node.
|
||||||
|
**/
|
||||||
|
uint32 failure_source_index = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -399,7 +399,7 @@ func marshallError(sendError error) (*Failure, error) {
|
|||||||
return nil, errors.New("unknown wire error")
|
return nil, errors.New("unknown wire error")
|
||||||
}
|
}
|
||||||
|
|
||||||
response.FailureSourcePubkey = fErr.ErrorSource.SerializeCompressed()
|
response.FailureSourceIndex = uint32(fErr.FailureSourceIdx)
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
@ -1815,19 +1815,39 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
rt *route.Route, fErr *htlcswitch.ForwardingError) (
|
rt *route.Route, fErr *htlcswitch.ForwardingError) (
|
||||||
bool, channeldb.FailureReason) {
|
bool, channeldb.FailureReason) {
|
||||||
|
|
||||||
errSource := fErr.ErrorSource
|
var (
|
||||||
errVertex := route.NewVertex(errSource)
|
failureSourceIdx = fErr.FailureSourceIdx
|
||||||
|
|
||||||
log.Tracef("node=%x reported failure when sending htlc", errVertex)
|
failureVertex route.Vertex
|
||||||
|
failureSource *btcec.PublicKey
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
// For any non-self failure, look up the source pub key in the hops
|
||||||
|
// slice. Otherwise return the self node pubkey.
|
||||||
|
if failureSourceIdx > 0 {
|
||||||
|
failureVertex = rt.Hops[failureSourceIdx-1].PubKeyBytes
|
||||||
|
failureSource, err = btcec.ParsePubKey(failureVertex[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Cannot parse pubkey %v: %v",
|
||||||
|
failureVertex, err)
|
||||||
|
|
||||||
|
return true, channeldb.FailureReasonError
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
failureVertex = r.selfNode.PubKeyBytes
|
||||||
|
failureSource, err = r.selfNode.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Cannot parse self pubkey: %v", err)
|
||||||
|
return true, channeldb.FailureReasonError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Tracef("Node %x (index %v) reported failure when sending htlc",
|
||||||
|
failureVertex, failureSourceIdx)
|
||||||
|
|
||||||
// Always determine chan id ourselves, because a channel
|
// Always determine chan id ourselves, because a channel
|
||||||
// update with id may not be available.
|
// update with id may not be available.
|
||||||
failedEdge, failedAmt, err := getFailedEdge(
|
failedEdge, failedAmt := getFailedEdge(rt, failureSourceIdx)
|
||||||
rt, route.Vertex(errVertex),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return true, channeldb.FailureReasonError
|
|
||||||
}
|
|
||||||
|
|
||||||
// processChannelUpdateAndRetry is a closure that
|
// processChannelUpdateAndRetry is a closure that
|
||||||
// handles a failure message containing a channel
|
// handles a failure message containing a channel
|
||||||
@ -1919,8 +1939,8 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// that sent us this error, as it doesn't now what the
|
// that sent us this error, as it doesn't now what the
|
||||||
// correct block height is.
|
// correct block height is.
|
||||||
case *lnwire.FailExpiryTooSoon:
|
case *lnwire.FailExpiryTooSoon:
|
||||||
r.applyChannelUpdate(&onionErr.Update, errSource)
|
r.applyChannelUpdate(&onionErr.Update, failureSource)
|
||||||
paySession.ReportVertexFailure(errVertex)
|
paySession.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If we hit an instance of onion payload corruption or an invalid
|
// If we hit an instance of onion payload corruption or an invalid
|
||||||
@ -1941,7 +1961,7 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// routing.
|
// routing.
|
||||||
case *lnwire.FailAmountBelowMinimum:
|
case *lnwire.FailAmountBelowMinimum:
|
||||||
processChannelUpdateAndRetry(
|
processChannelUpdateAndRetry(
|
||||||
&onionErr.Update, errSource,
|
&onionErr.Update, failureSource,
|
||||||
)
|
)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
@ -1950,7 +1970,7 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// newly updated fees.
|
// newly updated fees.
|
||||||
case *lnwire.FailFeeInsufficient:
|
case *lnwire.FailFeeInsufficient:
|
||||||
processChannelUpdateAndRetry(
|
processChannelUpdateAndRetry(
|
||||||
&onionErr.Update, errSource,
|
&onionErr.Update, failureSource,
|
||||||
)
|
)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
@ -1959,7 +1979,7 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// apply the new delta value and try it once more.
|
// apply the new delta value and try it once more.
|
||||||
case *lnwire.FailIncorrectCltvExpiry:
|
case *lnwire.FailIncorrectCltvExpiry:
|
||||||
processChannelUpdateAndRetry(
|
processChannelUpdateAndRetry(
|
||||||
&onionErr.Update, errSource,
|
&onionErr.Update, failureSource,
|
||||||
)
|
)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
@ -1967,7 +1987,7 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// forward one is currently disabled, so we'll apply
|
// forward one is currently disabled, so we'll apply
|
||||||
// the update and continue.
|
// the update and continue.
|
||||||
case *lnwire.FailChannelDisabled:
|
case *lnwire.FailChannelDisabled:
|
||||||
r.applyChannelUpdate(&onionErr.Update, errSource)
|
r.applyChannelUpdate(&onionErr.Update, failureSource)
|
||||||
paySession.ReportEdgeFailure(failedEdge, 0)
|
paySession.ReportEdgeFailure(failedEdge, 0)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
@ -1975,7 +1995,7 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// sufficient capacity, so we'll prune this edge for
|
// sufficient capacity, so we'll prune this edge for
|
||||||
// now, and continue onwards with our path finding.
|
// now, and continue onwards with our path finding.
|
||||||
case *lnwire.FailTemporaryChannelFailure:
|
case *lnwire.FailTemporaryChannelFailure:
|
||||||
r.applyChannelUpdate(onionErr.Update, errSource)
|
r.applyChannelUpdate(onionErr.Update, failureSource)
|
||||||
paySession.ReportEdgeFailure(failedEdge, failedAmt)
|
paySession.ReportEdgeFailure(failedEdge, failedAmt)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
@ -1983,14 +2003,14 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// required features, then we'll note this error and
|
// required features, then we'll note this error and
|
||||||
// continue.
|
// continue.
|
||||||
case *lnwire.FailRequiredNodeFeatureMissing:
|
case *lnwire.FailRequiredNodeFeatureMissing:
|
||||||
paySession.ReportVertexFailure(errVertex)
|
paySession.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If the send fail due to a node not having the
|
// If the send fail due to a node not having the
|
||||||
// required features, then we'll note this error and
|
// required features, then we'll note this error and
|
||||||
// continue.
|
// continue.
|
||||||
case *lnwire.FailRequiredChannelFeatureMissing:
|
case *lnwire.FailRequiredChannelFeatureMissing:
|
||||||
paySession.ReportVertexFailure(errVertex)
|
paySession.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If the next hop in the route wasn't known or
|
// If the next hop in the route wasn't known or
|
||||||
@ -2008,11 +2028,11 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// reason, then we'll note this and continue with the
|
// reason, then we'll note this and continue with the
|
||||||
// routes.
|
// routes.
|
||||||
case *lnwire.FailTemporaryNodeFailure:
|
case *lnwire.FailTemporaryNodeFailure:
|
||||||
paySession.ReportVertexFailure(errVertex)
|
paySession.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
case *lnwire.FailPermanentNodeFailure:
|
case *lnwire.FailPermanentNodeFailure:
|
||||||
paySession.ReportVertexFailure(errVertex)
|
paySession.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If we crafted a route that contains a too long time
|
// If we crafted a route that contains a too long time
|
||||||
@ -2025,7 +2045,7 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
// that as a hint during future path finding through
|
// that as a hint during future path finding through
|
||||||
// that node.
|
// that node.
|
||||||
case *lnwire.FailExpiryTooFar:
|
case *lnwire.FailExpiryTooFar:
|
||||||
paySession.ReportVertexFailure(errVertex)
|
paySession.ReportVertexFailure(failureVertex)
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|
||||||
// If we get a permanent channel or node failure, then
|
// If we get a permanent channel or node failure, then
|
||||||
@ -2046,45 +2066,43 @@ func (r *ChannelRouter) processSendError(paySession PaymentSession,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getFailedEdge tries to locate the failing channel given a route and the
|
// getFailedEdge tries to locate the failing channel given a route and the
|
||||||
// pubkey of the node that sent the error. It will assume that the error is
|
// pubkey of the node that sent the failure. It will assume that the failure is
|
||||||
// associated with the outgoing channel of the error node. As a second result,
|
// associated with the outgoing channel of the failing node. As a second result,
|
||||||
// it returns the amount sent over the edge.
|
// it returns the amount sent over the edge.
|
||||||
func getFailedEdge(route *route.Route, errSource route.Vertex) (edge,
|
func getFailedEdge(route *route.Route, failureSource int) (edge,
|
||||||
lnwire.MilliSatoshi, error) {
|
lnwire.MilliSatoshi) {
|
||||||
|
|
||||||
hopCount := len(route.Hops)
|
// Determine if we have a failure from the final hop. If it is, we
|
||||||
fromNode := route.SourcePubKey
|
// assume that the failing channel is the incoming channel. In this
|
||||||
amt := route.TotalAmount
|
// function the outgoing channel of the hop indicated by failureSource
|
||||||
for i, hop := range route.Hops {
|
// is returned, where index zero is the self node. By decrementing
|
||||||
toNode := hop.PubKeyBytes
|
// failureSource by one, the outgoing channel of the penultimate hop is
|
||||||
|
// returned, which is the same as the incoming channel of the final
|
||||||
// Determine if we have a failure from the final hop.
|
// node.
|
||||||
//
|
//
|
||||||
// TODO(joostjager): In this case, certain types of errors are
|
// TODO(joostjager): In this case, certain types of failures are not
|
||||||
// not expected. For example FailUnknownNextPeer. This could be
|
// expected. For example FailUnknownNextPeer. This could be a reason to
|
||||||
// a reason to prune the node?
|
// prune the node?
|
||||||
finalHopFailing := i == hopCount-1 && errSource == toNode
|
if failureSource == len(route.Hops) {
|
||||||
|
failureSource--
|
||||||
// As this error indicates that the target channel was unable to
|
|
||||||
// carry this HTLC (for w/e reason), we'll return the _outgoing_
|
|
||||||
// channel that the source of the error was meant to pass the
|
|
||||||
// HTLC along to.
|
|
||||||
//
|
|
||||||
// If the errSource is the final hop, we assume that the failing
|
|
||||||
// channel is the incoming channel.
|
|
||||||
if errSource == fromNode || finalHopFailing {
|
|
||||||
return edge{
|
|
||||||
from: fromNode,
|
|
||||||
to: toNode,
|
|
||||||
channel: hop.ChannelID,
|
|
||||||
}, amt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
fromNode = toNode
|
|
||||||
amt = hop.AmtToForward
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return edge{}, 0, fmt.Errorf("cannot find error source node in route")
|
// As this failure indicates that the target channel was unable to carry
|
||||||
|
// this HTLC (for w/e reason), we'll return the _outgoing_ channel that
|
||||||
|
// the source of the failure was meant to pass the HTLC along to.
|
||||||
|
if failureSource == 0 {
|
||||||
|
return edge{
|
||||||
|
from: route.SourcePubKey,
|
||||||
|
to: route.Hops[0].PubKeyBytes,
|
||||||
|
channel: route.Hops[0].ChannelID,
|
||||||
|
}, route.TotalAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
return edge{
|
||||||
|
from: route.Hops[failureSource-1].PubKeyBytes,
|
||||||
|
to: route.Hops[failureSource].PubKeyBytes,
|
||||||
|
channel: route.Hops[failureSource].ChannelID,
|
||||||
|
}, route.Hops[failureSource-1].AmtToForward
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyChannelUpdate validates a channel update and if valid, applies it to the
|
// applyChannelUpdate validates a channel update and if valid, applies it to the
|
||||||
|
@ -265,8 +265,6 @@ func TestSendPaymentRouteFailureFallback(t *testing.T) {
|
|||||||
var preImage [32]byte
|
var preImage [32]byte
|
||||||
copy(preImage[:], bytes.Repeat([]byte{9}, 32))
|
copy(preImage[:], bytes.Repeat([]byte{9}, 32))
|
||||||
|
|
||||||
sourceNode := ctx.router.selfNode
|
|
||||||
|
|
||||||
// We'll modify the SendToSwitch method that's been set within the
|
// We'll modify the SendToSwitch method that's been set within the
|
||||||
// router's configuration to ignore the path that has luo ji as the
|
// router's configuration to ignore the path that has luo ji as the
|
||||||
// first hop. This should force the router to instead take the
|
// first hop. This should force the router to instead take the
|
||||||
@ -276,12 +274,8 @@ func TestSendPaymentRouteFailureFallback(t *testing.T) {
|
|||||||
|
|
||||||
roasbeefLuoji := lnwire.NewShortChanIDFromInt(689530843)
|
roasbeefLuoji := lnwire.NewShortChanIDFromInt(689530843)
|
||||||
if firstHop == roasbeefLuoji {
|
if firstHop == roasbeefLuoji {
|
||||||
pub, err := sourceNode.PubKey()
|
|
||||||
if err != nil {
|
|
||||||
return preImage, err
|
|
||||||
}
|
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: pub,
|
FailureSourceIdx: 0,
|
||||||
// TODO(roasbeef): temp node failure should be?
|
// TODO(roasbeef): temp node failure should be?
|
||||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||||
}
|
}
|
||||||
@ -410,17 +404,8 @@ func TestChannelUpdateValidation(t *testing.T) {
|
|||||||
// The unsigned channel update is attached to the failure message.
|
// The unsigned channel update is attached to the failure message.
|
||||||
ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult(
|
ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult(
|
||||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
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{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: source,
|
FailureSourceIdx: 1,
|
||||||
FailureMessage: &lnwire.FailFeeInsufficient{
|
FailureMessage: &lnwire.FailFeeInsufficient{
|
||||||
Update: errChanUpdate,
|
Update: errChanUpdate,
|
||||||
},
|
},
|
||||||
@ -533,9 +518,6 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
|||||||
FeeRate: uint32(edgeUpdateToFail.FeeProportionalMillionths),
|
FeeRate: uint32(edgeUpdateToFail.FeeProportionalMillionths),
|
||||||
}
|
}
|
||||||
|
|
||||||
// The error will be returned by Son Goku.
|
|
||||||
sourceNode := ctx.aliases["songoku"]
|
|
||||||
|
|
||||||
// We'll now modify the SendToSwitch method to return an error for the
|
// We'll now modify the SendToSwitch method to return an error for the
|
||||||
// outgoing channel to Son goku. This will be a fee related error, so
|
// outgoing channel to Son goku. This will be a fee related error, so
|
||||||
// it should only cause the edge to be pruned after the second attempt.
|
// it should only cause the edge to be pruned after the second attempt.
|
||||||
@ -544,15 +526,8 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
|||||||
|
|
||||||
roasbeefSongoku := lnwire.NewShortChanIDFromInt(chanID)
|
roasbeefSongoku := lnwire.NewShortChanIDFromInt(chanID)
|
||||||
if firstHop == roasbeefSongoku {
|
if firstHop == roasbeefSongoku {
|
||||||
sourceKey, err := btcec.ParsePubKey(
|
|
||||||
sourceNode[:], btcec.S256(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourceKey,
|
FailureSourceIdx: 1,
|
||||||
|
|
||||||
// Within our error, we'll add a channel update
|
// Within our error, we'll add a channel update
|
||||||
// which is meant to reflect he new fee
|
// which is meant to reflect he new fee
|
||||||
@ -647,9 +622,6 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
|
|||||||
FeeRate: uint32(edgeUpdateToFail.FeeProportionalMillionths),
|
FeeRate: uint32(edgeUpdateToFail.FeeProportionalMillionths),
|
||||||
}
|
}
|
||||||
|
|
||||||
// The error will be returned by Son Goku.
|
|
||||||
sourceNode := ctx.aliases["songoku"]
|
|
||||||
|
|
||||||
// We'll now modify the SendToSwitch method to return an error for the
|
// We'll now modify the SendToSwitch method to return an error for the
|
||||||
// outgoing channel to son goku. Since this is a time lock related
|
// outgoing channel to son goku. Since this is a time lock related
|
||||||
// error, we should fail the payment flow all together, as Goku is the
|
// error, we should fail the payment flow all together, as Goku is the
|
||||||
@ -658,15 +630,8 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
|
|||||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
||||||
|
|
||||||
if firstHop == roasbeefSongoku {
|
if firstHop == roasbeefSongoku {
|
||||||
sourceKey, err := btcec.ParsePubKey(
|
|
||||||
sourceNode[:], btcec.S256(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourceKey,
|
FailureSourceIdx: 1,
|
||||||
FailureMessage: &lnwire.FailExpiryTooSoon{
|
FailureMessage: &lnwire.FailExpiryTooSoon{
|
||||||
Update: errChanUpdate,
|
Update: errChanUpdate,
|
||||||
},
|
},
|
||||||
@ -719,15 +684,8 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
|
|||||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
||||||
|
|
||||||
if firstHop == roasbeefSongoku {
|
if firstHop == roasbeefSongoku {
|
||||||
sourceKey, err := btcec.ParsePubKey(
|
|
||||||
sourceNode[:], btcec.S256(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourceKey,
|
FailureSourceIdx: 1,
|
||||||
FailureMessage: &lnwire.FailIncorrectCltvExpiry{
|
FailureMessage: &lnwire.FailIncorrectCltvExpiry{
|
||||||
Update: errChanUpdate,
|
Update: errChanUpdate,
|
||||||
},
|
},
|
||||||
@ -776,16 +734,6 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
var preImage [32]byte
|
var preImage [32]byte
|
||||||
copy(preImage[:], bytes.Repeat([]byte{9}, 32))
|
copy(preImage[:], bytes.Repeat([]byte{9}, 32))
|
||||||
|
|
||||||
sourceNode, err := ctx.graph.SourceNode()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to fetch source node: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sourcePub, err := sourceNode.PubKey()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to fetch source node pub: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
roasbeefLuoji := lnwire.NewShortChanIDFromInt(689530843)
|
roasbeefLuoji := lnwire.NewShortChanIDFromInt(689530843)
|
||||||
|
|
||||||
// First, we'll modify the SendToSwitch method to return an error
|
// First, we'll modify the SendToSwitch method to return an error
|
||||||
@ -802,7 +750,7 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
// outgoing link to simulate the channel from luo ji to
|
// outgoing link to simulate the channel from luo ji to
|
||||||
// roasbeef not having enough capacity.
|
// roasbeef not having enough capacity.
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourcePub,
|
FailureSourceIdx: 0,
|
||||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -812,16 +760,8 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
// prune out the rest of the routes.
|
// prune out the rest of the routes.
|
||||||
roasbeefSatoshi := lnwire.NewShortChanIDFromInt(2340213491)
|
roasbeefSatoshi := lnwire.NewShortChanIDFromInt(2340213491)
|
||||||
if firstHop == roasbeefSatoshi {
|
if firstHop == roasbeefSatoshi {
|
||||||
vertex := ctx.aliases["satoshi"]
|
|
||||||
key, err := btcec.ParsePubKey(
|
|
||||||
vertex[:], btcec.S256(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: key,
|
FailureSourceIdx: 1,
|
||||||
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -854,7 +794,7 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
|
|
||||||
if firstHop == roasbeefLuoji {
|
if firstHop == roasbeefLuoji {
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourcePub,
|
FailureSourceIdx: 0,
|
||||||
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -900,7 +840,7 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
// outgoing link to simulate the channel from luo ji to
|
// outgoing link to simulate the channel from luo ji to
|
||||||
// roasbeef not having enough capacity.
|
// roasbeef not having enough capacity.
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourcePub,
|
FailureSourceIdx: 0,
|
||||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2948,11 +2888,6 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
PaymentHash: payHash,
|
PaymentHash: payHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
errSource, err := btcec.ParsePubKey(hop1[:], btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to fetch source node pub: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(preImage[:], bytes.Repeat([]byte{9}, 32))
|
copy(preImage[:], bytes.Repeat([]byte{9}, 32))
|
||||||
|
|
||||||
router.cfg.MissionControl = &mockPaymentSessionSource{
|
router.cfg.MissionControl = &mockPaymentSessionSource{
|
||||||
@ -3030,7 +2965,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
case sendToSwitchResultFailure:
|
case sendToSwitchResultFailure:
|
||||||
select {
|
select {
|
||||||
case sendResult <- &htlcswitch.ForwardingError{
|
case sendResult <- &htlcswitch.ForwardingError{
|
||||||
ErrorSource: errSource,
|
FailureSourceIdx: 1,
|
||||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||||
}:
|
}:
|
||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1 * time.Second):
|
||||||
@ -3056,7 +2991,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
select {
|
select {
|
||||||
case getPaymentResult <- &htlcswitch.PaymentResult{
|
case getPaymentResult <- &htlcswitch.PaymentResult{
|
||||||
Error: &htlcswitch.ForwardingError{
|
Error: &htlcswitch.ForwardingError{
|
||||||
ErrorSource: errSource,
|
FailureSourceIdx: 1,
|
||||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||||
},
|
},
|
||||||
}:
|
}:
|
||||||
@ -3224,17 +3159,8 @@ func TestSendToRouteStructuredError(t *testing.T) {
|
|||||||
// The unsigned channel update is attached to the failure message.
|
// The unsigned channel update is attached to the failure message.
|
||||||
ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult(
|
ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcher).setPaymentResult(
|
||||||
func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
|
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{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: source,
|
FailureSourceIdx: 1,
|
||||||
FailureMessage: &lnwire.FailFeeInsufficient{
|
FailureMessage: &lnwire.FailFeeInsufficient{
|
||||||
Update: lnwire.ChannelUpdate{},
|
Update: lnwire.ChannelUpdate{},
|
||||||
},
|
},
|
||||||
|
@ -409,8 +409,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.htlcSwitch, err = htlcswitch.New(htlcswitch.Config{
|
s.htlcSwitch, err = htlcswitch.New(htlcswitch.Config{
|
||||||
DB: chanDB,
|
DB: chanDB,
|
||||||
SelfKey: s.identityPriv.PubKey(),
|
|
||||||
LocalChannelClose: func(pubKey []byte,
|
LocalChannelClose: func(pubKey []byte,
|
||||||
request *htlcswitch.ChanClose) {
|
request *htlcswitch.ChanClose) {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user