mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 14:22:37 +01:00
Merge pull request #8485 from carlaKC/7298-3-forwardblindedroutes
[3/3]: Blinded Route Error Handling
This commit is contained in:
commit
add2691954
29 changed files with 1323 additions and 522 deletions
|
@ -627,9 +627,8 @@ func DefaultConfig() Config {
|
||||||
RejectCacheSize: channeldb.DefaultRejectCacheSize,
|
RejectCacheSize: channeldb.DefaultRejectCacheSize,
|
||||||
ChannelCacheSize: channeldb.DefaultChannelCacheSize,
|
ChannelCacheSize: channeldb.DefaultChannelCacheSize,
|
||||||
},
|
},
|
||||||
Prometheus: lncfg.DefaultPrometheus(),
|
Prometheus: lncfg.DefaultPrometheus(),
|
||||||
Watchtower: lncfg.DefaultWatchtowerCfg(defaultTowerDir),
|
Watchtower: lncfg.DefaultWatchtowerCfg(defaultTowerDir),
|
||||||
ProtocolOptions: lncfg.DefaultProtocol(),
|
|
||||||
HealthChecks: &lncfg.HealthCheckConfig{
|
HealthChecks: &lncfg.HealthCheckConfig{
|
||||||
ChainCheck: &lncfg.CheckConfig{
|
ChainCheck: &lncfg.CheckConfig{
|
||||||
Interval: defaultChainInterval,
|
Interval: defaultChainInterval,
|
||||||
|
|
|
@ -543,7 +543,7 @@ func (h *htlcIncomingContestResolver) decodePayload() (*hop.Payload,
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
payload, err := iterator.HopPayload()
|
payload, _, err := iterator.HopPayload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,7 +263,7 @@ type mockHopIterator struct {
|
||||||
hop.Iterator
|
hop.Iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *mockHopIterator) HopPayload() (*hop.Payload, error) {
|
func (h *mockHopIterator) HopPayload() (*hop.Payload, hop.RouteRole, error) {
|
||||||
var nextAddress [8]byte
|
var nextAddress [8]byte
|
||||||
if !h.isExit {
|
if !h.isExit {
|
||||||
nextAddress = [8]byte{0x01}
|
nextAddress = [8]byte{0x01}
|
||||||
|
@ -275,7 +275,7 @@ func (h *mockHopIterator) HopPayload() (*hop.Payload, error) {
|
||||||
ForwardAmount: 100,
|
ForwardAmount: 100,
|
||||||
OutgoingCltv: 40,
|
OutgoingCltv: 40,
|
||||||
ExtraBytes: [12]byte{},
|
ExtraBytes: [12]byte{},
|
||||||
}), nil
|
}), hop.RouteRoleCleartext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *mockHopIterator) EncodeNextHop(w io.Writer) error {
|
func (h *mockHopIterator) EncodeNextHop(w io.Writer) error {
|
||||||
|
|
|
@ -215,8 +215,11 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor
|
||||||
|
|
||||||
* [Preparatory work](https://github.com/lightningnetwork/lnd/pull/8159) for
|
* [Preparatory work](https://github.com/lightningnetwork/lnd/pull/8159) for
|
||||||
forwarding of blinded routes was added, along with [support](https://github.com/lightningnetwork/lnd/pull/8160)
|
forwarding of blinded routes was added, along with [support](https://github.com/lightningnetwork/lnd/pull/8160)
|
||||||
for forwarding blinded payments. Forwarding of blinded payments is disabled
|
for forwarding blinded payments and [error handling](https://github.com/lightningnetwork/lnd/pull/8485).
|
||||||
by default, and the feature is not yet advertised to the network.
|
With this change, LND is now eligible to be selected as part of a blinded
|
||||||
|
route and can forward payments on behalf of nodes that have support for
|
||||||
|
receiving to blinded paths. This upgrade provides a meaningful improvement
|
||||||
|
to the anonymity set and usability of blinded paths in the Lightning Network.
|
||||||
|
|
||||||
* Introduced [fee bumper](https://github.com/lightningnetwork/lnd/pull/8424) to
|
* Introduced [fee bumper](https://github.com/lightningnetwork/lnd/pull/8424) to
|
||||||
handle bumping the fees of sweeping transactions properly. A
|
handle bumping the fees of sweeping transactions properly. A
|
||||||
|
|
|
@ -79,6 +79,11 @@ var defaultSetDesc = setDesc{
|
||||||
SetInit: {}, // I
|
SetInit: {}, // I
|
||||||
SetNodeAnn: {}, // N
|
SetNodeAnn: {}, // N
|
||||||
},
|
},
|
||||||
|
lnwire.RouteBlindingOptional: {
|
||||||
|
SetInit: {}, // I
|
||||||
|
SetNodeAnn: {}, // N
|
||||||
|
SetInvoice: {}, // 9
|
||||||
|
},
|
||||||
lnwire.ShutdownAnySegwitOptional: {
|
lnwire.ShutdownAnySegwitOptional: {
|
||||||
SetInit: {}, // I
|
SetInit: {}, // I
|
||||||
SetNodeAnn: {}, // N
|
SetNodeAnn: {}, // N
|
||||||
|
|
|
@ -79,6 +79,12 @@ var deps = depDesc{
|
||||||
lnwire.AnchorsZeroFeeHtlcTxOptional: {},
|
lnwire.AnchorsZeroFeeHtlcTxOptional: {},
|
||||||
lnwire.ExplicitChannelTypeOptional: {},
|
lnwire.ExplicitChannelTypeOptional: {},
|
||||||
},
|
},
|
||||||
|
lnwire.RouteBlindingOptional: {
|
||||||
|
lnwire.TLVOnionPayloadOptional: {},
|
||||||
|
},
|
||||||
|
lnwire.RouteBlindingRequired: {
|
||||||
|
lnwire.TLVOnionPayloadRequired: {},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateDeps asserts that a feature vector sets all features and their
|
// ValidateDeps asserts that a feature vector sets all features and their
|
||||||
|
|
|
@ -60,6 +60,9 @@ type Config struct {
|
||||||
// segwit witness versions for co-op closes.
|
// segwit witness versions for co-op closes.
|
||||||
NoAnySegwit bool
|
NoAnySegwit bool
|
||||||
|
|
||||||
|
// NoRouteBlinding unsets route blinding feature bits.
|
||||||
|
NoRouteBlinding bool
|
||||||
|
|
||||||
// CustomFeatures is a set of custom features to advertise in each
|
// CustomFeatures is a set of custom features to advertise in each
|
||||||
// set.
|
// set.
|
||||||
CustomFeatures map[Set][]lnwire.FeatureBit
|
CustomFeatures map[Set][]lnwire.FeatureBit
|
||||||
|
@ -123,6 +126,8 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) {
|
||||||
raw.Unset(lnwire.PaymentAddrRequired)
|
raw.Unset(lnwire.PaymentAddrRequired)
|
||||||
raw.Unset(lnwire.MPPOptional)
|
raw.Unset(lnwire.MPPOptional)
|
||||||
raw.Unset(lnwire.MPPRequired)
|
raw.Unset(lnwire.MPPRequired)
|
||||||
|
raw.Unset(lnwire.RouteBlindingOptional)
|
||||||
|
raw.Unset(lnwire.RouteBlindingRequired)
|
||||||
raw.Unset(lnwire.AMPOptional)
|
raw.Unset(lnwire.AMPOptional)
|
||||||
raw.Unset(lnwire.AMPRequired)
|
raw.Unset(lnwire.AMPRequired)
|
||||||
raw.Unset(lnwire.KeysendOptional)
|
raw.Unset(lnwire.KeysendOptional)
|
||||||
|
@ -179,7 +184,10 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) {
|
||||||
raw.Unset(lnwire.SimpleTaprootChannelsOptionalStaging)
|
raw.Unset(lnwire.SimpleTaprootChannelsOptionalStaging)
|
||||||
raw.Unset(lnwire.SimpleTaprootChannelsRequiredStaging)
|
raw.Unset(lnwire.SimpleTaprootChannelsRequiredStaging)
|
||||||
}
|
}
|
||||||
|
if cfg.NoRouteBlinding {
|
||||||
|
raw.Unset(lnwire.RouteBlindingOptional)
|
||||||
|
raw.Unset(lnwire.RouteBlindingRequired)
|
||||||
|
}
|
||||||
for _, custom := range cfg.CustomFeatures[set] {
|
for _, custom := range cfg.CustomFeatures[set] {
|
||||||
if custom > set.Maximum() {
|
if custom > set.Maximum() {
|
||||||
return nil, fmt.Errorf("feature bit: %v "+
|
return nil, fmt.Errorf("feature bit: %v "+
|
||||||
|
|
|
@ -205,6 +205,12 @@ func (c *PaymentCircuit) Decode(r io.Reader) error {
|
||||||
// Test encrypter.
|
// Test encrypter.
|
||||||
c.ErrorEncrypter = NewMockObfuscator()
|
c.ErrorEncrypter = NewMockObfuscator()
|
||||||
|
|
||||||
|
case hop.EncrypterTypeIntroduction:
|
||||||
|
c.ErrorEncrypter = hop.NewIntroductionErrorEncrypter()
|
||||||
|
|
||||||
|
case hop.EncrypterTypeRelaying:
|
||||||
|
c.ErrorEncrypter = hop.NewRelayingErrorEncrypter()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return UnknownEncrypterType(encrypterType)
|
return UnknownEncrypterType(encrypterType)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,26 @@ const (
|
||||||
|
|
||||||
// EncrypterTypeMock is used to identify a mock obfuscator instance.
|
// EncrypterTypeMock is used to identify a mock obfuscator instance.
|
||||||
EncrypterTypeMock = 2
|
EncrypterTypeMock = 2
|
||||||
|
|
||||||
|
// EncrypterTypeIntroduction is used to identify a sphinx onion error
|
||||||
|
// encrypter where we are the introduction node in a blinded route. It
|
||||||
|
// has the same functionality as EncrypterTypeSphinx, but is used to
|
||||||
|
// mark our special-case error handling.
|
||||||
|
EncrypterTypeIntroduction = 3
|
||||||
|
|
||||||
|
// EncrypterTypeRelaying is used to identify a sphinx onion error
|
||||||
|
// encryper where we are a relaying node in a blinded route. It has
|
||||||
|
// the same functionality as a EncrypterTypeSphinx, but is used to mark
|
||||||
|
// our special-case error handling.
|
||||||
|
EncrypterTypeRelaying = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// IsBlinded returns a boolean indicating whether the error encrypter belongs
|
||||||
|
// to a blinded route.
|
||||||
|
func (e EncrypterType) IsBlinded() bool {
|
||||||
|
return e == EncrypterTypeIntroduction || e == EncrypterTypeRelaying
|
||||||
|
}
|
||||||
|
|
||||||
// ErrorEncrypterExtracter defines a function signature that extracts an
|
// ErrorEncrypterExtracter defines a function signature that extracts an
|
||||||
// ErrorEncrypter from an sphinx OnionPacket.
|
// ErrorEncrypter from an sphinx OnionPacket.
|
||||||
type ErrorEncrypterExtracter func(*btcec.PublicKey) (ErrorEncrypter,
|
type ErrorEncrypterExtracter func(*btcec.PublicKey) (ErrorEncrypter,
|
||||||
|
@ -197,9 +215,72 @@ func (s *SphinxErrorEncrypter) Reextract(
|
||||||
s.OnionErrorEncrypter = sphinxEncrypter.OnionErrorEncrypter
|
s.OnionErrorEncrypter = sphinxEncrypter.OnionErrorEncrypter
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time check to ensure SphinxErrorEncrypter implements the
|
// A compile time check to ensure SphinxErrorEncrypter implements the
|
||||||
// ErrorEncrypter interface.
|
// ErrorEncrypter interface.
|
||||||
var _ ErrorEncrypter = (*SphinxErrorEncrypter)(nil)
|
var _ ErrorEncrypter = (*SphinxErrorEncrypter)(nil)
|
||||||
|
|
||||||
|
// A compile time check to ensure that IntroductionErrorEncrypter implements
|
||||||
|
// the ErrorEncrypter interface.
|
||||||
|
var _ ErrorEncrypter = (*IntroductionErrorEncrypter)(nil)
|
||||||
|
|
||||||
|
// IntroductionErrorEncrypter is a wrapper type on SphinxErrorEncrypter which
|
||||||
|
// is used to signal that we have special HTLC error handling for this hop.
|
||||||
|
type IntroductionErrorEncrypter struct {
|
||||||
|
// ErrorEncrypter is the underlying error encrypter, embedded
|
||||||
|
// directly in the struct so that we don't have to re-implement the
|
||||||
|
// ErrorEncrypter interface.
|
||||||
|
ErrorEncrypter
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIntroductionErrorEncrypter returns a blank IntroductionErrorEncrypter.
|
||||||
|
func NewIntroductionErrorEncrypter() *IntroductionErrorEncrypter {
|
||||||
|
return &IntroductionErrorEncrypter{
|
||||||
|
ErrorEncrypter: NewSphinxErrorEncrypter(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the identifier for an introduction error encrypter.
|
||||||
|
func (i *IntroductionErrorEncrypter) Type() EncrypterType {
|
||||||
|
return EncrypterTypeIntroduction
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reextract rederives the error encrypter from the currently held EphemeralKey,
|
||||||
|
// relying on the logic in the underlying SphinxErrorEncrypter.
|
||||||
|
func (i *IntroductionErrorEncrypter) Reextract(
|
||||||
|
extract ErrorEncrypterExtracter) error {
|
||||||
|
|
||||||
|
return i.ErrorEncrypter.Reextract(extract)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A compile time check to ensure that RelayingErrorEncrypte implements
|
||||||
|
// the ErrorEncrypter interface.
|
||||||
|
var _ ErrorEncrypter = (*RelayingErrorEncrypter)(nil)
|
||||||
|
|
||||||
|
// RelayingErrorEncrypter is a wrapper type on SphinxErrorEncrypter which
|
||||||
|
// is used to signal that we have special HTLC error handling for this hop.
|
||||||
|
type RelayingErrorEncrypter struct {
|
||||||
|
ErrorEncrypter
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRelayingErrorEncrypter returns a blank RelayingErrorEncrypter with
|
||||||
|
// an underlying SphinxErrorEncrypter.
|
||||||
|
func NewRelayingErrorEncrypter() *RelayingErrorEncrypter {
|
||||||
|
return &RelayingErrorEncrypter{
|
||||||
|
ErrorEncrypter: NewSphinxErrorEncrypter(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the identifier for a relaying error encrypter.
|
||||||
|
func (r *RelayingErrorEncrypter) Type() EncrypterType {
|
||||||
|
return EncrypterTypeRelaying
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reextract rederives the error encrypter from the currently held EphemeralKey,
|
||||||
|
// relying on the logic in the underlying SphinxErrorEncrypter.
|
||||||
|
func (r *RelayingErrorEncrypter) Reextract(
|
||||||
|
extract ErrorEncrypterExtracter) error {
|
||||||
|
|
||||||
|
return r.ErrorEncrypter.Reextract(extract)
|
||||||
|
}
|
||||||
|
|
|
@ -97,19 +97,37 @@ func hopFromPayload(p *Payload) (*route.Hop, uint64) {
|
||||||
|
|
||||||
// FuzzPayloadFinal fuzzes final hop payloads, providing the additional context
|
// FuzzPayloadFinal fuzzes final hop payloads, providing the additional context
|
||||||
// that the hop should be final (which is usually obtained by the structure
|
// that the hop should be final (which is usually obtained by the structure
|
||||||
// of the sphinx packet).
|
// of the sphinx packet) for the case where a blinding point was provided in
|
||||||
func FuzzPayloadFinal(f *testing.F) {
|
// UpdateAddHtlc.
|
||||||
fuzzPayload(f, true)
|
func FuzzPayloadFinalBlinding(f *testing.F) {
|
||||||
|
fuzzPayload(f, true, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuzzPayloadFinal fuzzes final hop payloads, providing the additional context
|
||||||
|
// that the hop should be final (which is usually obtained by the structure
|
||||||
|
// of the sphinx packet) for the case where no blinding point was provided in
|
||||||
|
// UpdateAddHtlc.
|
||||||
|
func FuzzPayloadFinalNoBlinding(f *testing.F) {
|
||||||
|
fuzzPayload(f, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuzzPayloadIntermediate fuzzes intermediate hop payloads, providing the
|
// FuzzPayloadIntermediate fuzzes intermediate hop payloads, providing the
|
||||||
// additional context that a hop should be intermediate (which is usually
|
// additional context that a hop should be intermediate (which is usually
|
||||||
// obtained by the structure of the sphinx packet).
|
// obtained by the structure of the sphinx packet) for the case where a
|
||||||
func FuzzPayloadIntermediate(f *testing.F) {
|
// blinding point was provided in UpdateAddHtlc.
|
||||||
fuzzPayload(f, false)
|
func FuzzPayloadIntermediateBlinding(f *testing.F) {
|
||||||
|
fuzzPayload(f, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fuzzPayload(f *testing.F, finalPayload bool) {
|
// FuzzPayloadIntermediate fuzzes intermediate hop payloads, providing the
|
||||||
|
// additional context that a hop should be intermediate (which is usually
|
||||||
|
// obtained by the structure of the sphinx packet) for the case where no
|
||||||
|
// blinding point was provided in UpdateAddHtlc.
|
||||||
|
func FuzzPayloadIntermediateNoBlinding(f *testing.F) {
|
||||||
|
fuzzPayload(f, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fuzzPayload(f *testing.F, finalPayload, updateAddBlinded bool) {
|
||||||
f.Fuzz(func(t *testing.T, data []byte) {
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
if len(data) > sphinx.MaxPayloadSize {
|
if len(data) > sphinx.MaxPayloadSize {
|
||||||
return
|
return
|
||||||
|
@ -117,17 +135,23 @@ func fuzzPayload(f *testing.F, finalPayload bool) {
|
||||||
|
|
||||||
r := bytes.NewReader(data)
|
r := bytes.NewReader(data)
|
||||||
|
|
||||||
payload1, _, err := NewPayloadFromReader(r, finalPayload)
|
payload1, parsed, err := ParseTLVPayload(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = ValidateParsedPayloadTypes(
|
||||||
|
parsed, finalPayload, updateAddBlinded,
|
||||||
|
); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
hop, nextChanID := hopFromPayload(payload1)
|
hop, nextChanID := hopFromPayload(payload1)
|
||||||
err = hop.PackHopPayload(&b, nextChanID, finalPayload)
|
err = hop.PackHopPayload(&b, nextChanID, finalPayload)
|
||||||
switch {
|
switch {
|
||||||
// PackHopPayload refuses to encode an AMP record
|
// PackHopPayload refuses to encode an AMP record
|
||||||
// without an MPP record. However, NewPayloadFromReader
|
// without an MPP record. However, ValidateParsedPayloadTypes
|
||||||
// does allow decoding an AMP record without an MPP
|
// does allow decoding an AMP record without an MPP
|
||||||
// record, since validation is done at a later stage. Do
|
// record, since validation is done at a later stage. Do
|
||||||
// not report a bug for this case.
|
// not report a bug for this case.
|
||||||
|
@ -136,9 +160,9 @@ func fuzzPayload(f *testing.F, finalPayload bool) {
|
||||||
|
|
||||||
// PackHopPayload will not encode regular payloads or final
|
// PackHopPayload will not encode regular payloads or final
|
||||||
// hops in blinded routes that do not have an amount or expiry
|
// hops in blinded routes that do not have an amount or expiry
|
||||||
// TLV set. However, NewPayloadFromReader will allow creation
|
// TLV set. However, ValidateParsedPayloadTypes will allow
|
||||||
// of payloads where these TLVs are present, but they have
|
// creation of payloads where these TLVs are present, but they
|
||||||
// zero values because validation is done at a later stage.
|
// have zero values because validation is done at a later stage.
|
||||||
case errors.Is(err, route.ErrMissingField):
|
case errors.Is(err, route.ErrMissingField):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -146,7 +170,12 @@ func fuzzPayload(f *testing.F, finalPayload bool) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
payload2, _, err := NewPayloadFromReader(&b, finalPayload)
|
payload2, parsed, err := ParseTLVPayload(&b)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = ValidateParsedPayloadTypes(
|
||||||
|
parsed, finalPayload, updateAddBlinded,
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, payload1, payload2)
|
require.Equal(t, payload1, payload2)
|
||||||
|
|
|
@ -17,8 +17,69 @@ import (
|
||||||
var (
|
var (
|
||||||
// ErrDecodeFailed is returned when we can't decode blinded data.
|
// ErrDecodeFailed is returned when we can't decode blinded data.
|
||||||
ErrDecodeFailed = errors.New("could not decode blinded data")
|
ErrDecodeFailed = errors.New("could not decode blinded data")
|
||||||
|
|
||||||
|
// ErrNoBlindingPoint is returned when we have not provided a blinding
|
||||||
|
// point for a validated payload with encrypted data set.
|
||||||
|
ErrNoBlindingPoint = errors.New("no blinding point set for validated " +
|
||||||
|
"blinded hop")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RouteRole represents the different types of roles a node can have as a
|
||||||
|
// recipient of a HTLC.
|
||||||
|
type RouteRole uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RouteRoleCleartext represents a regular route hop.
|
||||||
|
RouteRoleCleartext RouteRole = iota
|
||||||
|
|
||||||
|
// RouteRoleIntroduction represents an introduction node in a blinded
|
||||||
|
// path, characterized by a blinding point in the onion payload.
|
||||||
|
RouteRoleIntroduction
|
||||||
|
|
||||||
|
// RouteRoleRelaying represents a relaying node in a blinded path,
|
||||||
|
// characterized by a blinding point in update_add_htlc.
|
||||||
|
RouteRoleRelaying
|
||||||
|
)
|
||||||
|
|
||||||
|
// String representation of a role in a route.
|
||||||
|
func (h RouteRole) String() string {
|
||||||
|
switch h {
|
||||||
|
case RouteRoleCleartext:
|
||||||
|
return "cleartext"
|
||||||
|
|
||||||
|
case RouteRoleRelaying:
|
||||||
|
return "blinded relay"
|
||||||
|
|
||||||
|
case RouteRoleIntroduction:
|
||||||
|
return "introduction node"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown route role: %d", h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRouteRole returns the role we're playing in a route depending on the
|
||||||
|
// blinding points set (or not). If we are in the situation where we received
|
||||||
|
// blinding points in both the update add message and the payload:
|
||||||
|
// - We must have had a valid update add blinding point, because we were able
|
||||||
|
// to decrypt our onion to get the payload blinding point.
|
||||||
|
// - We return a relaying node role, because an introduction node (by
|
||||||
|
// definition) does not receive a blinding point in update add.
|
||||||
|
// - We assume the sending node to be buggy (including a payload blinding
|
||||||
|
// where it shouldn't), and rely on validation elsewhere to handle this.
|
||||||
|
func NewRouteRole(updateAddBlinding, payloadBlinding bool) RouteRole {
|
||||||
|
switch {
|
||||||
|
case updateAddBlinding:
|
||||||
|
return RouteRoleRelaying
|
||||||
|
|
||||||
|
case payloadBlinding:
|
||||||
|
return RouteRoleIntroduction
|
||||||
|
|
||||||
|
default:
|
||||||
|
return RouteRoleCleartext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Iterator is an interface that abstracts away the routing information
|
// Iterator is an interface that abstracts away the routing information
|
||||||
// included in HTLC's which includes the entirety of the payment path of an
|
// included in HTLC's which includes the entirety of the payment path of an
|
||||||
// HTLC. This interface provides two basic method which carry out: how to
|
// HTLC. This interface provides two basic method which carry out: how to
|
||||||
|
@ -30,8 +91,11 @@ type Iterator interface {
|
||||||
// information encoded within the returned ForwardingInfo is to be used
|
// information encoded within the returned ForwardingInfo is to be used
|
||||||
// by each hop to authenticate the information given to it by the prior
|
// by each hop to authenticate the information given to it by the prior
|
||||||
// hop. The payload will also contain any additional TLV fields provided
|
// hop. The payload will also contain any additional TLV fields provided
|
||||||
// by the sender.
|
// by the sender. The role that this hop plays in the context of
|
||||||
HopPayload() (*Payload, error)
|
// route blinding (regular, introduction or relaying) is returned
|
||||||
|
// whenever the payload is successfully parsed, even if we subsequently
|
||||||
|
// face a validation error.
|
||||||
|
HopPayload() (*Payload, RouteRole, error)
|
||||||
|
|
||||||
// EncodeNextHop encodes the onion packet destined for the next hop
|
// EncodeNextHop encodes the onion packet destined for the next hop
|
||||||
// into the passed io.Writer.
|
// into the passed io.Writer.
|
||||||
|
@ -39,8 +103,8 @@ type Iterator interface {
|
||||||
|
|
||||||
// ExtractErrorEncrypter returns the ErrorEncrypter needed for this hop,
|
// ExtractErrorEncrypter returns the ErrorEncrypter needed for this hop,
|
||||||
// along with a failure code to signal if the decoding was successful.
|
// along with a failure code to signal if the decoding was successful.
|
||||||
ExtractErrorEncrypter(ErrorEncrypterExtracter) (ErrorEncrypter,
|
ExtractErrorEncrypter(extractor ErrorEncrypterExtracter,
|
||||||
lnwire.FailCode)
|
introductionNode bool) (ErrorEncrypter, lnwire.FailCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sphinxHopIterator is the Sphinx implementation of hop iterator which uses
|
// sphinxHopIterator is the Sphinx implementation of hop iterator which uses
|
||||||
|
@ -90,29 +154,56 @@ func (r *sphinxHopIterator) EncodeNextHop(w io.Writer) error {
|
||||||
// HopPayload returns the set of fields that detail exactly _how_ this hop
|
// HopPayload returns the set of fields that detail exactly _how_ this hop
|
||||||
// should forward the HTLC to the next hop. Additionally, the information
|
// should forward the HTLC to the next hop. Additionally, the information
|
||||||
// encoded within the returned ForwardingInfo is to be used by each hop to
|
// encoded within the returned ForwardingInfo is to be used by each hop to
|
||||||
// authenticate the information given to it by the prior hop. The payload will
|
// authenticate the information given to it by the prior hop. The role that
|
||||||
// also contain any additional TLV fields provided by the sender.
|
// this hop plays in the context of route blinding (regular, introduction or
|
||||||
|
// relaying) is returned whenever the payload is successfully parsed, even if
|
||||||
|
// we subsequently face a validation error. The payload will also contain any
|
||||||
|
// additional TLV fields provided by the sender.
|
||||||
//
|
//
|
||||||
// NOTE: Part of the HopIterator interface.
|
// NOTE: Part of the HopIterator interface.
|
||||||
func (r *sphinxHopIterator) HopPayload() (*Payload, error) {
|
func (r *sphinxHopIterator) HopPayload() (*Payload, RouteRole, error) {
|
||||||
switch r.processedPacket.Payload.Type {
|
switch r.processedPacket.Payload.Type {
|
||||||
|
|
||||||
// If this is the legacy payload, then we'll extract the information
|
// If this is the legacy payload, then we'll extract the information
|
||||||
// directly from the pre-populated ForwardingInstructions field.
|
// directly from the pre-populated ForwardingInstructions field.
|
||||||
case sphinx.PayloadLegacy:
|
case sphinx.PayloadLegacy:
|
||||||
fwdInst := r.processedPacket.ForwardingInstructions
|
fwdInst := r.processedPacket.ForwardingInstructions
|
||||||
return NewLegacyPayload(fwdInst), nil
|
return NewLegacyPayload(fwdInst), RouteRoleCleartext, nil
|
||||||
|
|
||||||
// Otherwise, if this is the TLV payload, then we'll make a new stream
|
// Otherwise, if this is the TLV payload, then we'll make a new stream
|
||||||
// to decode only what we need to make routing decisions.
|
// to decode only what we need to make routing decisions.
|
||||||
case sphinx.PayloadTLV:
|
case sphinx.PayloadTLV:
|
||||||
isFinal := r.processedPacket.Action == sphinx.ExitNode
|
isFinal := r.processedPacket.Action == sphinx.ExitNode
|
||||||
payload, parsed, err := NewPayloadFromReader(
|
payload, parsed, err := ParseTLVPayload(
|
||||||
bytes.NewReader(r.processedPacket.Payload.Payload),
|
bytes.NewReader(r.processedPacket.Payload.Payload),
|
||||||
isFinal,
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
// If we couldn't even parse our payload then we do
|
||||||
|
// a best-effort of determining our role in a blinded
|
||||||
|
// route, accepting that we can't know whether we
|
||||||
|
// were the introduction node (as the payload
|
||||||
|
// is not parseable).
|
||||||
|
routeRole := RouteRoleCleartext
|
||||||
|
if r.blindingKit.UpdateAddBlinding.IsSome() {
|
||||||
|
routeRole = RouteRoleRelaying
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, routeRole, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we've parsed our payload we can determine which
|
||||||
|
// role we're playing in the route.
|
||||||
|
_, payloadBlinding := parsed[record.BlindingPointOnionType]
|
||||||
|
routeRole := NewRouteRole(
|
||||||
|
r.blindingKit.UpdateAddBlinding.IsSome(),
|
||||||
|
payloadBlinding,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := ValidateTLVPayload(
|
||||||
|
parsed, isFinal,
|
||||||
|
r.blindingKit.UpdateAddBlinding.IsSome(),
|
||||||
|
); err != nil {
|
||||||
|
return nil, routeRole, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we had an encrypted data payload present, pull out our
|
// If we had an encrypted data payload present, pull out our
|
||||||
|
@ -122,17 +213,18 @@ func (r *sphinxHopIterator) HopPayload() (*Payload, error) {
|
||||||
payload, isFinal, parsed,
|
payload, isFinal, parsed,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, routeRole, err
|
||||||
}
|
}
|
||||||
|
|
||||||
payload.FwdInfo = *fwdInfo
|
payload.FwdInfo = *fwdInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
return payload, err
|
return payload, routeRole, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown sphinx payload type: %v",
|
return nil, RouteRoleCleartext,
|
||||||
r.processedPacket.Payload.Type)
|
fmt.Errorf("unknown sphinx payload type: %v",
|
||||||
|
r.processedPacket.Payload.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,9 +235,31 @@ func (r *sphinxHopIterator) HopPayload() (*Payload, error) {
|
||||||
//
|
//
|
||||||
// NOTE: Part of the HopIterator interface.
|
// NOTE: Part of the HopIterator interface.
|
||||||
func (r *sphinxHopIterator) ExtractErrorEncrypter(
|
func (r *sphinxHopIterator) ExtractErrorEncrypter(
|
||||||
extracter ErrorEncrypterExtracter) (ErrorEncrypter, lnwire.FailCode) {
|
extracter ErrorEncrypterExtracter, introductionNode bool) (
|
||||||
|
ErrorEncrypter, lnwire.FailCode) {
|
||||||
|
|
||||||
return extracter(r.ogPacket.EphemeralKey)
|
encrypter, errCode := extracter(r.ogPacket.EphemeralKey)
|
||||||
|
if errCode != lnwire.CodeNone {
|
||||||
|
return nil, errCode
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're in a blinded path, wrap the error encrypter that we just
|
||||||
|
// derived in a "marker" type which we'll use to know what type of
|
||||||
|
// error we're handling.
|
||||||
|
switch {
|
||||||
|
case introductionNode:
|
||||||
|
return &IntroductionErrorEncrypter{
|
||||||
|
ErrorEncrypter: encrypter,
|
||||||
|
}, errCode
|
||||||
|
|
||||||
|
case r.blindingKit.UpdateAddBlinding.IsSome():
|
||||||
|
return &RelayingErrorEncrypter{
|
||||||
|
ErrorEncrypter: encrypter,
|
||||||
|
}, errCode
|
||||||
|
|
||||||
|
default:
|
||||||
|
return encrypter, errCode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlindingProcessor is an interface that provides the cryptographic operations
|
// BlindingProcessor is an interface that provides the cryptographic operations
|
||||||
|
@ -182,35 +296,16 @@ type BlindingKit struct {
|
||||||
IncomingAmount lnwire.MilliSatoshi
|
IncomingAmount lnwire.MilliSatoshi
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateBlindingPoint validates that only one blinding point is present for
|
// getBlindingPoint returns either the payload or updateAddHtlc blinding point,
|
||||||
// the hop and returns the relevant one.
|
// assuming that validation that these values are appropriately set has already
|
||||||
func (b *BlindingKit) validateBlindingPoint(payloadBlinding *btcec.PublicKey,
|
// been handled elsewhere.
|
||||||
isFinalHop bool) (*btcec.PublicKey, error) {
|
func (b *BlindingKit) getBlindingPoint(payloadBlinding *btcec.PublicKey) (
|
||||||
|
*btcec.PublicKey, error) {
|
||||||
|
|
||||||
// Bolt 04: if encrypted_recipient_data is present:
|
|
||||||
// - if blinding_point (in update add) is set:
|
|
||||||
// - MUST error if current_blinding_point is set (in payload)
|
|
||||||
// - otherwise:
|
|
||||||
// - MUST return an error if current_blinding_point is not present
|
|
||||||
// (in payload)
|
|
||||||
payloadBlindingSet := payloadBlinding != nil
|
payloadBlindingSet := payloadBlinding != nil
|
||||||
updateBlindingSet := b.UpdateAddBlinding.IsSome()
|
updateBlindingSet := b.UpdateAddBlinding.IsSome()
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case !(payloadBlindingSet || updateBlindingSet):
|
|
||||||
return nil, ErrInvalidPayload{
|
|
||||||
Type: record.BlindingPointOnionType,
|
|
||||||
Violation: OmittedViolation,
|
|
||||||
FinalHop: isFinalHop,
|
|
||||||
}
|
|
||||||
|
|
||||||
case payloadBlindingSet && updateBlindingSet:
|
|
||||||
return nil, ErrInvalidPayload{
|
|
||||||
Type: record.BlindingPointOnionType,
|
|
||||||
Violation: IncludedViolation,
|
|
||||||
FinalHop: isFinalHop,
|
|
||||||
}
|
|
||||||
|
|
||||||
case payloadBlindingSet:
|
case payloadBlindingSet:
|
||||||
return payloadBlinding, nil
|
return payloadBlinding, nil
|
||||||
|
|
||||||
|
@ -223,9 +318,10 @@ func (b *BlindingKit) validateBlindingPoint(payloadBlinding *btcec.PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
return pk.Val, nil
|
return pk.Val, nil
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("expected blinded point set")
|
default:
|
||||||
|
return nil, ErrNoBlindingPoint
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptAndValidateFwdInfo performs all operations required to decrypt and
|
// DecryptAndValidateFwdInfo performs all operations required to decrypt and
|
||||||
|
@ -235,11 +331,10 @@ func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload,
|
||||||
*ForwardingInfo, error) {
|
*ForwardingInfo, error) {
|
||||||
|
|
||||||
// We expect this function to be called when we have encrypted data
|
// We expect this function to be called when we have encrypted data
|
||||||
// present, and a blinding key is set either in the payload or the
|
// present, and expect validation to already have ensured that a
|
||||||
|
// blinding key is set either in the payload or the
|
||||||
// update_add_htlc message.
|
// update_add_htlc message.
|
||||||
blindingPoint, err := b.validateBlindingPoint(
|
blindingPoint, err := b.getBlindingPoint(payload.blindingPoint)
|
||||||
payload.blindingPoint, isFinalHop,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,10 +88,10 @@ func TestSphinxHopIteratorForwardingInstructions(t *testing.T) {
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
iterator.processedPacket = testCase.sphinxPacket
|
iterator.processedPacket = testCase.sphinxPacket
|
||||||
|
|
||||||
pld, err := iterator.HopPayload()
|
pld, _, pldErr := iterator.HopPayload()
|
||||||
if err != nil {
|
if pldErr != nil {
|
||||||
t.Fatalf("#%v: unable to extract forwarding "+
|
t.Fatalf("#%v: unable to extract forwarding "+
|
||||||
"instructions: %v", i, err)
|
"instructions: %v", i, pldErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fwdInfo := pld.ForwardingInfo()
|
fwdInfo := pld.ForwardingInfo()
|
||||||
|
@ -216,24 +216,10 @@ func TestDecryptAndValidateFwdInfo(t *testing.T) {
|
||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no blinding point",
|
name: "no blinding point",
|
||||||
data: validData,
|
data: validData,
|
||||||
processor: &mockProcessor{},
|
processor: &mockProcessor{},
|
||||||
expectedErr: ErrInvalidPayload{
|
expectedErr: ErrNoBlindingPoint,
|
||||||
Type: record.BlindingPointOnionType,
|
|
||||||
Violation: OmittedViolation,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "both blinding points",
|
|
||||||
data: validData,
|
|
||||||
updateAddBlinding: &btcec.PublicKey{},
|
|
||||||
payloadBlinding: &btcec.PublicKey{},
|
|
||||||
processor: &mockProcessor{},
|
|
||||||
expectedErr: ErrInvalidPayload{
|
|
||||||
Type: record.BlindingPointOnionType,
|
|
||||||
Violation: IncludedViolation,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "decryption failed",
|
name: "decryption failed",
|
||||||
|
@ -265,12 +251,19 @@ func TestDecryptAndValidateFwdInfo(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "valid",
|
name: "valid using update add",
|
||||||
updateAddBlinding: &btcec.PublicKey{},
|
updateAddBlinding: &btcec.PublicKey{},
|
||||||
data: validData,
|
data: validData,
|
||||||
processor: &mockProcessor{},
|
processor: &mockProcessor{},
|
||||||
expectedErr: nil,
|
expectedErr: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "valid using payload",
|
||||||
|
payloadBlinding: &btcec.PublicKey{},
|
||||||
|
data: validData,
|
||||||
|
processor: &mockProcessor{},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range tests {
|
for _, testCase := range tests {
|
||||||
|
|
|
@ -133,14 +133,10 @@ func NewLegacyPayload(f *sphinx.HopData) *Payload {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPayloadFromReader builds a new Hop from the passed io.Reader and returns
|
// ParseTLVPayload builds a new Hop from the passed io.Reader and returns
|
||||||
// a map of all the types that were found in the payload. The reader
|
// a map of all the types that were found in the payload. This function
|
||||||
// should correspond to the bytes encapsulated in a TLV onion payload. The
|
// does not perform validation of TLV types included in the payload.
|
||||||
// final hop bool signals that this payload was the final packet parsed by
|
func ParseTLVPayload(r io.Reader) (*Payload, map[tlv.Type][]byte, error) {
|
||||||
// sphinx.
|
|
||||||
func NewPayloadFromReader(r io.Reader, finalHop bool) (*Payload,
|
|
||||||
map[tlv.Type][]byte, error) {
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cid uint64
|
cid uint64
|
||||||
amt uint64
|
amt uint64
|
||||||
|
@ -175,23 +171,6 @@ func NewPayloadFromReader(r io.Reader, finalHop bool) (*Payload,
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate whether the sender properly included or omitted tlv records
|
|
||||||
// in accordance with BOLT 04.
|
|
||||||
err = ValidateParsedPayloadTypes(parsedTypes, finalHop)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for violation of the rules for mandatory fields.
|
|
||||||
violatingType := getMinRequiredViolation(parsedTypes)
|
|
||||||
if violatingType != nil {
|
|
||||||
return nil, nil, ErrInvalidPayload{
|
|
||||||
Type: *violatingType,
|
|
||||||
Violation: RequiredViolation,
|
|
||||||
FinalHop: finalHop,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no MPP field was parsed, set the MPP field on the resulting
|
// If no MPP field was parsed, set the MPP field on the resulting
|
||||||
// payload to nil.
|
// payload to nil.
|
||||||
if _, ok := parsedTypes[record.MPPOnionType]; !ok {
|
if _, ok := parsedTypes[record.MPPOnionType]; !ok {
|
||||||
|
@ -232,7 +211,34 @@ func NewPayloadFromReader(r io.Reader, finalHop bool) (*Payload,
|
||||||
blindingPoint: blindingPoint,
|
blindingPoint: blindingPoint,
|
||||||
customRecords: customRecords,
|
customRecords: customRecords,
|
||||||
totalAmtMsat: lnwire.MilliSatoshi(totalAmtMsat),
|
totalAmtMsat: lnwire.MilliSatoshi(totalAmtMsat),
|
||||||
}, nil, nil
|
}, parsedTypes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateTLVPayload validates the TLV fields that were included in a TLV
|
||||||
|
// payload.
|
||||||
|
func ValidateTLVPayload(parsedTypes map[tlv.Type][]byte,
|
||||||
|
finalHop bool, updateAddBlinding bool) error {
|
||||||
|
|
||||||
|
// Validate whether the sender properly included or omitted tlv records
|
||||||
|
// in accordance with BOLT 04.
|
||||||
|
err := ValidateParsedPayloadTypes(
|
||||||
|
parsedTypes, finalHop, updateAddBlinding,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for violation of the rules for mandatory fields.
|
||||||
|
violatingType := getMinRequiredViolation(parsedTypes)
|
||||||
|
if violatingType != nil {
|
||||||
|
return ErrInvalidPayload{
|
||||||
|
Type: *violatingType,
|
||||||
|
Violation: RequiredViolation,
|
||||||
|
FinalHop: finalHop,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForwardingInfo returns the basic parameters required for HTLC forwarding,
|
// ForwardingInfo returns the basic parameters required for HTLC forwarding,
|
||||||
|
@ -259,7 +265,7 @@ func NewCustomRecords(parsedTypes tlv.TypeMap) record.CustomSet {
|
||||||
// boolean should be true if the payload was parsed for an exit hop. The
|
// boolean should be true if the payload was parsed for an exit hop. The
|
||||||
// requirements for this method are described in BOLT 04.
|
// requirements for this method are described in BOLT 04.
|
||||||
func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap,
|
func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap,
|
||||||
isFinalHop bool) error {
|
isFinalHop, updateAddBlinding bool) error {
|
||||||
|
|
||||||
_, hasAmt := parsedTypes[record.AmtOnionType]
|
_, hasAmt := parsedTypes[record.AmtOnionType]
|
||||||
_, hasLockTime := parsedTypes[record.LockTimeOnionType]
|
_, hasLockTime := parsedTypes[record.LockTimeOnionType]
|
||||||
|
@ -267,6 +273,7 @@ func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap,
|
||||||
_, hasMPP := parsedTypes[record.MPPOnionType]
|
_, hasMPP := parsedTypes[record.MPPOnionType]
|
||||||
_, hasAMP := parsedTypes[record.AMPOnionType]
|
_, hasAMP := parsedTypes[record.AMPOnionType]
|
||||||
_, hasEncryptedData := parsedTypes[record.EncryptedDataOnionType]
|
_, hasEncryptedData := parsedTypes[record.EncryptedDataOnionType]
|
||||||
|
_, hasBlinding := parsedTypes[record.BlindingPointOnionType]
|
||||||
|
|
||||||
// All cleartext hops (including final hop) and the final hop in a
|
// All cleartext hops (including final hop) and the final hop in a
|
||||||
// blinded path require the forwading amount and expiry TLVs to be set.
|
// blinded path require the forwading amount and expiry TLVs to be set.
|
||||||
|
@ -277,6 +284,32 @@ func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap,
|
||||||
needNextHop := !(hasEncryptedData || isFinalHop)
|
needNextHop := !(hasEncryptedData || isFinalHop)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
// Both blinding point being set is invalid.
|
||||||
|
case hasBlinding && updateAddBlinding:
|
||||||
|
return ErrInvalidPayload{
|
||||||
|
Type: record.BlindingPointOnionType,
|
||||||
|
Violation: IncludedViolation,
|
||||||
|
FinalHop: isFinalHop,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If encrypted data is not provided, blinding points should not be
|
||||||
|
// set.
|
||||||
|
case !hasEncryptedData && (hasBlinding || updateAddBlinding):
|
||||||
|
return ErrInvalidPayload{
|
||||||
|
Type: record.EncryptedDataOnionType,
|
||||||
|
Violation: OmittedViolation,
|
||||||
|
FinalHop: isFinalHop,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If encrypted data is present, we require that one blinding point
|
||||||
|
// is set.
|
||||||
|
case hasEncryptedData && !(hasBlinding || updateAddBlinding):
|
||||||
|
return ErrInvalidPayload{
|
||||||
|
Type: record.EncryptedDataOnionType,
|
||||||
|
Violation: IncludedViolation,
|
||||||
|
FinalHop: isFinalHop,
|
||||||
|
}
|
||||||
|
|
||||||
// Hops that need forwarding info must include an amount to forward.
|
// Hops that need forwarding info must include an amount to forward.
|
||||||
case needFwdInfo && !hasAmt:
|
case needFwdInfo && !hasAmt:
|
||||||
return ErrInvalidPayload{
|
return ErrInvalidPayload{
|
||||||
|
|
|
@ -26,6 +26,7 @@ type decodePayloadTest struct {
|
||||||
name string
|
name string
|
||||||
payload []byte
|
payload []byte
|
||||||
isFinalHop bool
|
isFinalHop bool
|
||||||
|
updateAddBlinded bool
|
||||||
expErr error
|
expErr error
|
||||||
expCustomRecords map[uint64][]byte
|
expCustomRecords map[uint64][]byte
|
||||||
shouldHaveMPP bool
|
shouldHaveMPP bool
|
||||||
|
@ -271,8 +272,9 @@ var decodePayloadTests = []decodePayloadTest{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "intermediate hop with encrypted data",
|
name: "intermediate hop with encrypted data",
|
||||||
isFinalHop: false,
|
isFinalHop: false,
|
||||||
|
updateAddBlinded: true,
|
||||||
payload: []byte{
|
payload: []byte{
|
||||||
// encrypted data
|
// encrypted data
|
||||||
0x0a, 0x03, 0x03, 0x02, 0x01,
|
0x0a, 0x03, 0x03, 0x02, 0x01,
|
||||||
|
@ -365,8 +367,9 @@ var decodePayloadTests = []decodePayloadTest{
|
||||||
shouldHaveTotalAmt: true,
|
shouldHaveTotalAmt: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "final blinded hop with total amount",
|
name: "final blinded hop with total amount",
|
||||||
isFinalHop: true,
|
isFinalHop: true,
|
||||||
|
updateAddBlinded: true,
|
||||||
payload: []byte{
|
payload: []byte{
|
||||||
// amount
|
// amount
|
||||||
0x02, 0x00,
|
0x02, 0x00,
|
||||||
|
@ -378,8 +381,9 @@ var decodePayloadTests = []decodePayloadTest{
|
||||||
shouldHaveEncData: true,
|
shouldHaveEncData: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "final blinded missing amt",
|
name: "final blinded missing amt",
|
||||||
isFinalHop: true,
|
isFinalHop: true,
|
||||||
|
updateAddBlinded: true,
|
||||||
payload: []byte{
|
payload: []byte{
|
||||||
// cltv
|
// cltv
|
||||||
0x04, 0x00,
|
0x04, 0x00,
|
||||||
|
@ -394,8 +398,9 @@ var decodePayloadTests = []decodePayloadTest{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "final blinded missing cltv",
|
name: "final blinded missing cltv",
|
||||||
isFinalHop: true,
|
isFinalHop: true,
|
||||||
|
updateAddBlinded: true,
|
||||||
payload: []byte{
|
payload: []byte{
|
||||||
// amount
|
// amount
|
||||||
0x02, 0x00,
|
0x02, 0x00,
|
||||||
|
@ -410,8 +415,9 @@ var decodePayloadTests = []decodePayloadTest{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "intermediate blinded has amount",
|
name: "intermediate blinded has amount",
|
||||||
isFinalHop: false,
|
isFinalHop: false,
|
||||||
|
updateAddBlinded: true,
|
||||||
payload: []byte{
|
payload: []byte{
|
||||||
// amount
|
// amount
|
||||||
0x02, 0x00,
|
0x02, 0x00,
|
||||||
|
@ -425,8 +431,9 @@ var decodePayloadTests = []decodePayloadTest{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "intermediate blinded has expiry",
|
name: "intermediate blinded has expiry",
|
||||||
isFinalHop: false,
|
isFinalHop: false,
|
||||||
|
updateAddBlinded: true,
|
||||||
payload: []byte{
|
payload: []byte{
|
||||||
// cltv
|
// cltv
|
||||||
0x04, 0x00,
|
0x04, 0x00,
|
||||||
|
@ -439,6 +446,67 @@ var decodePayloadTests = []decodePayloadTest{
|
||||||
FinalHop: false,
|
FinalHop: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "update add blinding no data",
|
||||||
|
isFinalHop: false,
|
||||||
|
payload: []byte{
|
||||||
|
// cltv
|
||||||
|
0x04, 0x00,
|
||||||
|
},
|
||||||
|
updateAddBlinded: true,
|
||||||
|
expErr: hop.ErrInvalidPayload{
|
||||||
|
Type: record.EncryptedDataOnionType,
|
||||||
|
Violation: hop.OmittedViolation,
|
||||||
|
FinalHop: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "onion blinding point no data",
|
||||||
|
isFinalHop: false,
|
||||||
|
payload: append([]byte{
|
||||||
|
// blinding point (type / length)
|
||||||
|
0x0c, 0x21,
|
||||||
|
},
|
||||||
|
// blinding point (value)
|
||||||
|
testPubKey.SerializeCompressed()...,
|
||||||
|
),
|
||||||
|
expErr: hop.ErrInvalidPayload{
|
||||||
|
Type: record.EncryptedDataOnionType,
|
||||||
|
Violation: hop.OmittedViolation,
|
||||||
|
FinalHop: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "encrypted data no blinding",
|
||||||
|
isFinalHop: false,
|
||||||
|
payload: []byte{
|
||||||
|
// encrypted data
|
||||||
|
0x0a, 0x03, 0x03, 0x02, 0x01,
|
||||||
|
},
|
||||||
|
expErr: hop.ErrInvalidPayload{
|
||||||
|
Type: record.EncryptedDataOnionType,
|
||||||
|
Violation: hop.IncludedViolation,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "both blinding points",
|
||||||
|
isFinalHop: false,
|
||||||
|
updateAddBlinded: true,
|
||||||
|
payload: append([]byte{
|
||||||
|
// encrypted data
|
||||||
|
0x0a, 0x03, 0x03, 0x02, 0x01,
|
||||||
|
// blinding point (type / length)
|
||||||
|
0x0c, 0x21,
|
||||||
|
},
|
||||||
|
// blinding point (value)
|
||||||
|
testPubKey.SerializeCompressed()...,
|
||||||
|
),
|
||||||
|
expErr: hop.ErrInvalidPayload{
|
||||||
|
Type: record.BlindingPointOnionType,
|
||||||
|
Violation: hop.IncludedViolation,
|
||||||
|
FinalHop: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestDecodeHopPayloadRecordValidation asserts that parsing the payloads in the
|
// TestDecodeHopPayloadRecordValidation asserts that parsing the payloads in the
|
||||||
|
@ -479,8 +547,13 @@ func testDecodeHopPayloadValidation(t *testing.T, test decodePayloadTest) {
|
||||||
testChildIndex = uint32(9)
|
testChildIndex = uint32(9)
|
||||||
)
|
)
|
||||||
|
|
||||||
p, _, err := hop.NewPayloadFromReader(
|
p, parsedTypes, err := hop.ParseTLVPayload(
|
||||||
bytes.NewReader(test.payload), test.isFinalHop,
|
bytes.NewReader(test.payload),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = hop.ValidateTLVPayload(
|
||||||
|
parsedTypes, test.isFinalHop, test.updateAddBlinded,
|
||||||
)
|
)
|
||||||
if !reflect.DeepEqual(test.expErr, err) {
|
if !reflect.DeepEqual(test.expErr, err) {
|
||||||
t.Fatalf("expected error mismatch, want: %v, got: %v",
|
t.Fatalf("expected error mismatch, want: %v, got: %v",
|
||||||
|
|
|
@ -1793,8 +1793,20 @@ func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) {
|
||||||
htlc.ID = pkt.incomingHTLCID
|
htlc.ID = pkt.incomingHTLCID
|
||||||
|
|
||||||
// We send the HTLC message to the peer which initially created
|
// We send the HTLC message to the peer which initially created
|
||||||
// the HTLC.
|
// the HTLC. If the incoming blinding point is non-nil, we
|
||||||
l.cfg.Peer.SendMessage(false, htlc)
|
// know that we are a relaying node in a blinded path.
|
||||||
|
// Otherwise, we're either an introduction node or not part of
|
||||||
|
// a blinded path at all.
|
||||||
|
if err := l.sendIncomingHTLCFailureMsg(
|
||||||
|
htlc.ID,
|
||||||
|
pkt.obfuscator,
|
||||||
|
htlc.Reason,
|
||||||
|
); err != nil {
|
||||||
|
l.log.Errorf("unable to send HTLC failure: %v",
|
||||||
|
err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// If the packet does not have a link failure set, it failed
|
// If the packet does not have a link failure set, it failed
|
||||||
// further down the route so we notify a forwarding failure.
|
// further down the route so we notify a forwarding failure.
|
||||||
|
@ -2030,6 +2042,19 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
|
||||||
failure = &lnwire.FailInvalidOnionKey{
|
failure = &lnwire.FailInvalidOnionKey{
|
||||||
OnionSHA256: msg.ShaOnionBlob,
|
OnionSHA256: msg.ShaOnionBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle malformed errors that are part of a blinded route.
|
||||||
|
// This case is slightly different, because we expect every
|
||||||
|
// relaying node in the blinded portion of the route to send
|
||||||
|
// malformed errors. If we're also a relaying node, we're
|
||||||
|
// likely going to switch this error out anyway for our own
|
||||||
|
// malformed error, but we handle the case here for
|
||||||
|
// completeness.
|
||||||
|
case lnwire.CodeInvalidBlinding:
|
||||||
|
failure = &lnwire.FailInvalidBlinding{
|
||||||
|
OnionSHA256: msg.ShaOnionBlob,
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
l.log.Warnf("unexpected failure code received in "+
|
l.log.Warnf("unexpected failure code received in "+
|
||||||
"UpdateFailMailformedHTLC: %v", msg.FailureCode)
|
"UpdateFailMailformedHTLC: %v", msg.FailureCode)
|
||||||
|
@ -3249,7 +3274,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
|
||||||
// DecodeHopIterator function which process the Sphinx packet.
|
// DecodeHopIterator function which process the Sphinx packet.
|
||||||
chanIterator, failureCode := decodeResps[i].Result()
|
chanIterator, failureCode := decodeResps[i].Result()
|
||||||
if failureCode != lnwire.CodeNone {
|
if failureCode != lnwire.CodeNone {
|
||||||
// If we're unable to process the onion blob than we
|
// If we're unable to process the onion blob then we
|
||||||
// should send the malformed htlc error to payment
|
// should send the malformed htlc error to payment
|
||||||
// sender.
|
// sender.
|
||||||
l.sendMalformedHTLCError(pd.HtlcIndex, failureCode,
|
l.sendMalformedHTLCError(pd.HtlcIndex, failureCode,
|
||||||
|
@ -3260,37 +3285,50 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve onion obfuscator from onion blob in order to
|
|
||||||
// produce initial obfuscation of the onion failureCode.
|
|
||||||
obfuscator, failureCode := chanIterator.ExtractErrorEncrypter(
|
|
||||||
l.cfg.ExtractErrorEncrypter,
|
|
||||||
)
|
|
||||||
if failureCode != lnwire.CodeNone {
|
|
||||||
// If we're unable to process the onion blob than we
|
|
||||||
// should send the malformed htlc error to payment
|
|
||||||
// sender.
|
|
||||||
l.sendMalformedHTLCError(
|
|
||||||
pd.HtlcIndex, failureCode, onionBlob[:], pd.SourceRef,
|
|
||||||
)
|
|
||||||
|
|
||||||
l.log.Errorf("unable to decode onion "+
|
|
||||||
"obfuscator: %v", failureCode)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
heightNow := l.cfg.BestHeight()
|
heightNow := l.cfg.BestHeight()
|
||||||
|
|
||||||
pld, err := chanIterator.HopPayload()
|
pld, routeRole, pldErr := chanIterator.HopPayload()
|
||||||
if err != nil {
|
if pldErr != nil {
|
||||||
// If we're unable to process the onion payload, or we
|
// If we're unable to process the onion payload, or we
|
||||||
// received invalid onion payload failure, then we
|
// received invalid onion payload failure, then we
|
||||||
// should send an error back to the caller so the HTLC
|
// should send an error back to the caller so the HTLC
|
||||||
// can be canceled.
|
// can be canceled.
|
||||||
var failedType uint64
|
var failedType uint64
|
||||||
if e, ok := err.(hop.ErrInvalidPayload); ok {
|
|
||||||
|
// We need to get the underlying error value, so we
|
||||||
|
// can't use errors.As as suggested by the linter.
|
||||||
|
//nolint:errorlint
|
||||||
|
if e, ok := pldErr.(hop.ErrInvalidPayload); ok {
|
||||||
failedType = uint64(e.Type)
|
failedType = uint64(e.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we couldn't parse the payload, make our best
|
||||||
|
// effort at creating an error encrypter that knows
|
||||||
|
// what blinding type we were, but if we couldn't
|
||||||
|
// parse the payload we have no way of knowing whether
|
||||||
|
// we were the introduction node or not.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
|
obfuscator, failCode := chanIterator.ExtractErrorEncrypter(
|
||||||
|
l.cfg.ExtractErrorEncrypter,
|
||||||
|
// We need our route role here because we
|
||||||
|
// couldn't parse or validate the payload.
|
||||||
|
routeRole == hop.RouteRoleIntroduction,
|
||||||
|
)
|
||||||
|
if failCode != lnwire.CodeNone {
|
||||||
|
l.log.Errorf("could not extract error "+
|
||||||
|
"encrypter: %v", pldErr)
|
||||||
|
|
||||||
|
// We can't process this htlc, send back
|
||||||
|
// malformed.
|
||||||
|
l.sendMalformedHTLCError(
|
||||||
|
pd.HtlcIndex, failureCode,
|
||||||
|
onionBlob[:], pd.SourceRef,
|
||||||
|
)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: currently none of the test unit infrastructure
|
// TODO: currently none of the test unit infrastructure
|
||||||
// is setup to handle TLV payloads, so testing this
|
// is setup to handle TLV payloads, so testing this
|
||||||
// would require implementing a separate mock iterator
|
// would require implementing a separate mock iterator
|
||||||
|
@ -3303,7 +3341,29 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
|
||||||
)
|
)
|
||||||
|
|
||||||
l.log.Errorf("unable to decode forwarding "+
|
l.log.Errorf("unable to decode forwarding "+
|
||||||
"instructions: %v", err)
|
"instructions: %v", pldErr)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve onion obfuscator from onion blob in order to
|
||||||
|
// produce initial obfuscation of the onion failureCode.
|
||||||
|
obfuscator, failureCode := chanIterator.ExtractErrorEncrypter(
|
||||||
|
l.cfg.ExtractErrorEncrypter,
|
||||||
|
routeRole == hop.RouteRoleIntroduction,
|
||||||
|
)
|
||||||
|
if failureCode != lnwire.CodeNone {
|
||||||
|
// If we're unable to process the onion blob than we
|
||||||
|
// should send the malformed htlc error to payment
|
||||||
|
// sender.
|
||||||
|
l.sendMalformedHTLCError(
|
||||||
|
pd.HtlcIndex, failureCode, onionBlob[:],
|
||||||
|
pd.SourceRef,
|
||||||
|
)
|
||||||
|
|
||||||
|
l.log.Errorf("unable to decode onion "+
|
||||||
|
"obfuscator: %v", failureCode)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3672,11 +3732,14 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l.cfg.Peer.SendMessage(false, &lnwire.UpdateFailHTLC{
|
// Send the appropriate failure message depending on whether we're
|
||||||
ChanID: l.ChanID(),
|
// in a blinded route or not.
|
||||||
ID: pd.HtlcIndex,
|
if err := l.sendIncomingHTLCFailureMsg(
|
||||||
Reason: reason,
|
pd.HtlcIndex, e, reason,
|
||||||
})
|
); err != nil {
|
||||||
|
l.log.Errorf("unable to send HTLC failure: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Notify a link failure on our incoming link. Outgoing htlc information
|
// Notify a link failure on our incoming link. Outgoing htlc information
|
||||||
// is not available at this point, because we have not decrypted the
|
// is not available at this point, because we have not decrypted the
|
||||||
|
@ -3705,6 +3768,95 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sendPeerHTLCFailure handles sending a HTLC failure message back to the
|
||||||
|
// peer from which the HTLC was received. This function is primarily used to
|
||||||
|
// handle the special requirements of route blinding, specifically:
|
||||||
|
// - Forwarding nodes must switch out any errors with MalformedFailHTLC
|
||||||
|
// - Introduction nodes should return regular HTLC failure messages.
|
||||||
|
//
|
||||||
|
// It accepts the original opaque failure, which will be used in the case
|
||||||
|
// that we're not part of a blinded route and an error encrypter that'll be
|
||||||
|
// used if we are the introduction node and need to present an error as if
|
||||||
|
// we're the failing party.
|
||||||
|
//
|
||||||
|
// Note: this function does not yet handle special error cases for receiving
|
||||||
|
// nodes in blinded paths, as LND does not support blinded receives.
|
||||||
|
func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
|
||||||
|
e hop.ErrorEncrypter,
|
||||||
|
originalFailure lnwire.OpaqueReason) error {
|
||||||
|
|
||||||
|
var msg lnwire.Message
|
||||||
|
switch {
|
||||||
|
// Our circuit's error encrypter will be nil if this was a locally
|
||||||
|
// initiated payment. We can only hit a blinded error for a locally
|
||||||
|
// initiated payment if we allow ourselves to be picked as the
|
||||||
|
// introduction node for our own payments and in that case we
|
||||||
|
// shouldn't reach this code. To prevent the HTLC getting stuck,
|
||||||
|
// we fail it back and log an error.
|
||||||
|
// code.
|
||||||
|
case e == nil:
|
||||||
|
msg = &lnwire.UpdateFailHTLC{
|
||||||
|
ChanID: l.ChanID(),
|
||||||
|
ID: htlcIndex,
|
||||||
|
Reason: originalFailure,
|
||||||
|
}
|
||||||
|
|
||||||
|
l.log.Errorf("Unexpected blinded failure when "+
|
||||||
|
"we are the sending node, incoming htlc: %v(%v)",
|
||||||
|
l.ShortChanID(), htlcIndex)
|
||||||
|
|
||||||
|
// For cleartext hops (ie, non-blinded/normal) we don't need any
|
||||||
|
// transformation on the error message and can just send the original.
|
||||||
|
case !e.Type().IsBlinded():
|
||||||
|
msg = &lnwire.UpdateFailHTLC{
|
||||||
|
ChanID: l.ChanID(),
|
||||||
|
ID: htlcIndex,
|
||||||
|
Reason: originalFailure,
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we're the introduction node, we need to convert the error to
|
||||||
|
// a UpdateFailHTLC.
|
||||||
|
case e.Type() == hop.EncrypterTypeIntroduction:
|
||||||
|
l.log.Debugf("Introduction blinded node switching out failure "+
|
||||||
|
"error: %v", htlcIndex)
|
||||||
|
|
||||||
|
// The specification does not require that we set the onion
|
||||||
|
// blob.
|
||||||
|
failureMsg := lnwire.NewInvalidBlinding(nil)
|
||||||
|
reason, err := e.EncryptFirstHop(failureMsg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = &lnwire.UpdateFailHTLC{
|
||||||
|
ChanID: l.ChanID(),
|
||||||
|
ID: htlcIndex,
|
||||||
|
Reason: reason,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are a relaying node, we need to switch out any error that
|
||||||
|
// we've received to a malformed HTLC error.
|
||||||
|
case e.Type() == hop.EncrypterTypeRelaying:
|
||||||
|
l.log.Debugf("Relaying blinded node switching out malformed "+
|
||||||
|
"error: %v", htlcIndex)
|
||||||
|
|
||||||
|
msg = &lnwire.UpdateFailMalformedHTLC{
|
||||||
|
ChanID: l.ChanID(),
|
||||||
|
ID: htlcIndex,
|
||||||
|
FailureCode: lnwire.CodeInvalidBlinding,
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected encrypter: %d", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := l.cfg.Peer.SendMessage(false, msg); err != nil {
|
||||||
|
l.log.Warnf("Send update fail failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// sendMalformedHTLCError helper function which sends the malformed HTLC update
|
// sendMalformedHTLCError helper function which sends the malformed HTLC update
|
||||||
// to the payment sender.
|
// to the payment sender.
|
||||||
func (l *channelLink) sendMalformedHTLCError(htlcIndex uint64,
|
func (l *channelLink) sendMalformedHTLCError(htlcIndex uint64,
|
||||||
|
|
|
@ -738,6 +738,7 @@ func (m *memoryMailBox) FailAdd(pkt *htlcPacket) {
|
||||||
sourceRef: pkt.sourceRef,
|
sourceRef: pkt.sourceRef,
|
||||||
hasSource: true,
|
hasSource: true,
|
||||||
localFailure: localFailure,
|
localFailure: localFailure,
|
||||||
|
obfuscator: pkt.obfuscator,
|
||||||
linkFailure: linkError,
|
linkFailure: linkError,
|
||||||
htlc: &lnwire.UpdateFailHTLC{
|
htlc: &lnwire.UpdateFailHTLC{
|
||||||
Reason: reason,
|
Reason: reason,
|
||||||
|
|
|
@ -330,10 +330,10 @@ func newMockHopIterator(hops ...*hop.Payload) hop.Iterator {
|
||||||
return &mockHopIterator{hops: hops}
|
return &mockHopIterator{hops: hops}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *mockHopIterator) HopPayload() (*hop.Payload, error) {
|
func (r *mockHopIterator) HopPayload() (*hop.Payload, hop.RouteRole, error) {
|
||||||
h := r.hops[0]
|
h := r.hops[0]
|
||||||
r.hops = r.hops[1:]
|
r.hops = r.hops[1:]
|
||||||
return h, nil
|
return h, hop.RouteRoleCleartext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *mockHopIterator) ExtraOnionBlob() []byte {
|
func (r *mockHopIterator) ExtraOnionBlob() []byte {
|
||||||
|
@ -341,7 +341,7 @@ func (r *mockHopIterator) ExtraOnionBlob() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *mockHopIterator) ExtractErrorEncrypter(
|
func (r *mockHopIterator) ExtractErrorEncrypter(
|
||||||
extracter hop.ErrorEncrypterExtracter) (hop.ErrorEncrypter,
|
extracter hop.ErrorEncrypterExtracter, _ bool) (hop.ErrorEncrypter,
|
||||||
lnwire.FailCode) {
|
lnwire.FailCode) {
|
||||||
|
|
||||||
return extracter(nil)
|
return extracter(nil)
|
||||||
|
|
|
@ -1297,6 +1297,11 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error {
|
||||||
|
|
||||||
fail, isFail := htlc.(*lnwire.UpdateFailHTLC)
|
fail, isFail := htlc.(*lnwire.UpdateFailHTLC)
|
||||||
if isFail && !packet.hasSource {
|
if isFail && !packet.hasSource {
|
||||||
|
// HTLC resolutions and messages restored from disk
|
||||||
|
// don't have the obfuscator set from the original htlc
|
||||||
|
// add packet - set it here for use in blinded errors.
|
||||||
|
packet.obfuscator = circuit.ErrorEncrypter
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
// No message to encrypt, locally sourced payment.
|
// No message to encrypt, locally sourced payment.
|
||||||
case circuit.ErrorEncrypter == nil:
|
case circuit.ErrorEncrypter == nil:
|
||||||
|
@ -1485,6 +1490,7 @@ func (s *Switch) failAddPacket(packet *htlcPacket, failure *LinkError) error {
|
||||||
incomingTimeout: packet.incomingTimeout,
|
incomingTimeout: packet.incomingTimeout,
|
||||||
outgoingTimeout: packet.outgoingTimeout,
|
outgoingTimeout: packet.outgoingTimeout,
|
||||||
circuit: packet.circuit,
|
circuit: packet.circuit,
|
||||||
|
obfuscator: packet.obfuscator,
|
||||||
linkFailure: failure,
|
linkFailure: failure,
|
||||||
htlc: &lnwire.UpdateFailHTLC{
|
htlc: &lnwire.UpdateFailHTLC{
|
||||||
Reason: reason,
|
Reason: reason,
|
||||||
|
@ -1841,6 +1847,10 @@ out:
|
||||||
// resolution message on restart.
|
// resolution message on restart.
|
||||||
resolutionMsg.errChan <- nil
|
resolutionMsg.errChan <- nil
|
||||||
|
|
||||||
|
// Create a htlc packet for this resolution. We do
|
||||||
|
// not have some of the information that we'll need
|
||||||
|
// for blinded error handling here , so we'll rely on
|
||||||
|
// our forwarding logic to fill it in later.
|
||||||
pkt := &htlcPacket{
|
pkt := &htlcPacket{
|
||||||
outgoingChanID: resolutionMsg.SourceChan,
|
outgoingChanID: resolutionMsg.SourceChan,
|
||||||
outgoingHTLCID: resolutionMsg.HtlcIndex,
|
outgoingHTLCID: resolutionMsg.HtlcIndex,
|
||||||
|
@ -2065,6 +2075,8 @@ func (s *Switch) reforwardResolutions() error {
|
||||||
|
|
||||||
// The circuit is still open, so we can assume that the link or
|
// The circuit is still open, so we can assume that the link or
|
||||||
// switch (if we are the source) hasn't cleaned it up yet.
|
// switch (if we are the source) hasn't cleaned it up yet.
|
||||||
|
// We rely on our forwarding logic to fill in details that
|
||||||
|
// are not currently available to us.
|
||||||
resPkt := &htlcPacket{
|
resPkt := &htlcPacket{
|
||||||
outgoingChanID: resMsg.SourceChan,
|
outgoingChanID: resMsg.SourceChan,
|
||||||
outgoingHTLCID: resMsg.HtlcIndex,
|
outgoingHTLCID: resMsg.HtlcIndex,
|
||||||
|
@ -2214,7 +2226,8 @@ func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) {
|
||||||
// we can continue to propagate it. This
|
// we can continue to propagate it. This
|
||||||
// failure originated from another node, so
|
// failure originated from another node, so
|
||||||
// the linkFailure field is not set on this
|
// the linkFailure field is not set on this
|
||||||
// packet.
|
// packet. We rely on the link to fill in
|
||||||
|
// additional circuit information for us.
|
||||||
failPacket := &htlcPacket{
|
failPacket := &htlcPacket{
|
||||||
outgoingChanID: fwdPkg.Source,
|
outgoingChanID: fwdPkg.Source,
|
||||||
outgoingHTLCID: pd.ParentIndex,
|
outgoingHTLCID: pd.ParentIndex,
|
||||||
|
|
|
@ -566,6 +566,26 @@ var allTestCases = []*lntest.TestCase{
|
||||||
Name: "forward blinded",
|
Name: "forward blinded",
|
||||||
TestFunc: testForwardBlindedRoute,
|
TestFunc: testForwardBlindedRoute,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "receiver blinded error",
|
||||||
|
TestFunc: testReceiverBlindedError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "relayer blinded error",
|
||||||
|
TestFunc: testRelayingBlindedError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "introduction blinded error",
|
||||||
|
TestFunc: testIntroductionNodeError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "disable introduction node",
|
||||||
|
TestFunc: testDisableIntroductionNode,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "on chain to blinded",
|
||||||
|
TestFunc: testErrorHandlingOnChainFailure,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "removetx",
|
Name: "removetx",
|
||||||
TestFunc: testRemoveTx,
|
TestFunc: testRemoveTx,
|
||||||
|
|
|
@ -355,14 +355,16 @@ func (b *blindedForwardTest) setup(
|
||||||
ctx context.Context) *routing.BlindedPayment {
|
ctx context.Context) *routing.BlindedPayment {
|
||||||
|
|
||||||
b.carol = b.ht.NewNode("Carol", []string{
|
b.carol = b.ht.NewNode("Carol", []string{
|
||||||
"requireinterceptor",
|
"--requireinterceptor", "--bitcoin.timelockdelta=18",
|
||||||
})
|
})
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
b.carolInterceptor, err = b.carol.RPC.Router.HtlcInterceptor(ctx)
|
b.carolInterceptor, err = b.carol.RPC.Router.HtlcInterceptor(ctx)
|
||||||
require.NoError(b.ht, err, "interceptor")
|
require.NoError(b.ht, err, "interceptor")
|
||||||
|
|
||||||
b.dave = b.ht.NewNode("Dave", nil)
|
b.dave = b.ht.NewNode("Dave", []string{
|
||||||
|
"--bitcoin.timelockdelta=18",
|
||||||
|
})
|
||||||
|
|
||||||
b.channels = setupFourHopNetwork(b.ht, b.carol, b.dave)
|
b.channels = setupFourHopNetwork(b.ht, b.carol, b.dave)
|
||||||
|
|
||||||
|
@ -448,9 +450,11 @@ func (b *blindedForwardTest) createRouteToBlinded(paymentAmt int64,
|
||||||
return resp.Routes[0]
|
return resp.Routes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendBlindedPayment dispatches a payment to the route provided.
|
// sendBlindedPayment dispatches a payment to the route provided, returning a
|
||||||
|
// cancel function for the payment. Timeout is set for very long to allow
|
||||||
|
// time for on-chain resolution.
|
||||||
func (b *blindedForwardTest) sendBlindedPayment(ctx context.Context,
|
func (b *blindedForwardTest) sendBlindedPayment(ctx context.Context,
|
||||||
route *lnrpc.Route) {
|
route *lnrpc.Route) func() {
|
||||||
|
|
||||||
hash := sha256.Sum256(b.preimage[:])
|
hash := sha256.Sum256(b.preimage[:])
|
||||||
sendReq := &routerrpc.SendToRouteRequest{
|
sendReq := &routerrpc.SendToRouteRequest{
|
||||||
|
@ -458,11 +462,13 @@ func (b *blindedForwardTest) sendBlindedPayment(ctx context.Context,
|
||||||
Route: route,
|
Route: route,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch in a goroutine because this call is blocking - we assume
|
ctx, cancel := context.WithTimeout(ctx, time.Hour)
|
||||||
// that we'll have assertions that this payment is sent by the caller.
|
|
||||||
go func() {
|
go func() {
|
||||||
b.ht.Alice.RPC.SendToRouteV2(sendReq)
|
_, err := b.ht.Alice.RPC.Router.SendToRouteV2(ctx, sendReq)
|
||||||
|
require.NoError(b.ht, err)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
// interceptFinalHop launches a goroutine to intercept Carol's htlcs and
|
// interceptFinalHop launches a goroutine to intercept Carol's htlcs and
|
||||||
|
@ -524,6 +530,43 @@ func (b *blindedForwardTest) interceptFinalHop() func(routerrpc.ResolveHoldForwa
|
||||||
return resolve
|
return resolve
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drainCarolLiquidity will drain all of the liquidity in Carol's channel in
|
||||||
|
// the direction requested:
|
||||||
|
// - incoming: Carol has no incoming liquidity from Bob
|
||||||
|
// - outgoing: Carol has no outgoing liquidity to Dave.
|
||||||
|
func (b *blindedForwardTest) drainCarolLiquidity(incoming bool) {
|
||||||
|
sendingNode := b.carol
|
||||||
|
receivingNode := b.dave
|
||||||
|
|
||||||
|
if incoming {
|
||||||
|
sendingNode = b.ht.Bob
|
||||||
|
receivingNode = b.carol
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := sendingNode.RPC.ListChannels(&lnrpc.ListChannelsRequest{
|
||||||
|
Peer: receivingNode.PubKey[:],
|
||||||
|
})
|
||||||
|
require.Len(b.ht, resp.Channels, 1)
|
||||||
|
|
||||||
|
// We can't send our channel reserve, and leave some buffer for fees.
|
||||||
|
paymentAmt := resp.Channels[0].LocalBalance -
|
||||||
|
int64(resp.Channels[0].RemoteConstraints.ChanReserveSat) - 25000
|
||||||
|
|
||||||
|
invoice := receivingNode.RPC.AddInvoice(&lnrpc.Invoice{
|
||||||
|
// Leave some leeway for fees for the HTLC.
|
||||||
|
Value: paymentAmt,
|
||||||
|
})
|
||||||
|
|
||||||
|
pmtClient := sendingNode.RPC.SendPayment(
|
||||||
|
&routerrpc.SendPaymentRequest{
|
||||||
|
PaymentRequest: invoice.PaymentRequest,
|
||||||
|
TimeoutSeconds: 60,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
b.ht.AssertPaymentStatusFromStream(pmtClient, lnrpc.Payment_SUCCEEDED)
|
||||||
|
}
|
||||||
|
|
||||||
// setupFourHopNetwork creates a network with the following topology and
|
// setupFourHopNetwork creates a network with the following topology and
|
||||||
// liquidity:
|
// liquidity:
|
||||||
// Alice (100k)----- Bob (100k) ----- Carol (100k) ----- Dave
|
// Alice (100k)----- Bob (100k) ----- Carol (100k) ----- Dave
|
||||||
|
@ -768,7 +811,8 @@ func testForwardBlindedRoute(ht *lntest.HarnessTest) {
|
||||||
resolveHTLC := testCase.interceptFinalHop()
|
resolveHTLC := testCase.interceptFinalHop()
|
||||||
|
|
||||||
// Once our interceptor is set up, we can send the blinded payment.
|
// Once our interceptor is set up, we can send the blinded payment.
|
||||||
testCase.sendBlindedPayment(ctx, blindedRoute)
|
cancelPmt := testCase.sendBlindedPayment(ctx, blindedRoute)
|
||||||
|
defer cancelPmt()
|
||||||
|
|
||||||
// Wait for the HTLC to be active on Alice's channel.
|
// Wait for the HTLC to be active on Alice's channel.
|
||||||
hash := sha256.Sum256(testCase.preimage[:])
|
hash := sha256.Sum256(testCase.preimage[:])
|
||||||
|
@ -788,3 +832,227 @@ func testForwardBlindedRoute(ht *lntest.HarnessTest) {
|
||||||
ht.AssertHTLCNotActive(ht.Bob, testCase.channels[1], hash[:])
|
ht.AssertHTLCNotActive(ht.Bob, testCase.channels[1], hash[:])
|
||||||
ht.AssertHTLCNotActive(ht.Alice, testCase.channels[0], hash[:])
|
ht.AssertHTLCNotActive(ht.Alice, testCase.channels[0], hash[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests handling of errors from the receiving node in a blinded route, testing
|
||||||
|
// a payment over: Alice -- Bob -- Carol -- Dave, where Bob is the introduction
|
||||||
|
// node.
|
||||||
|
//
|
||||||
|
// Note that at present the payment fails at Dave because we do not yet support
|
||||||
|
// receiving to blinded routes. In future, we can substitute this test out to
|
||||||
|
// trigger an IncorrectPaymentDetails failure. In the meantime, this test
|
||||||
|
// provides valuable coverage for the case where a node in the route is not
|
||||||
|
// spec compliant (ie, does not return the blinded failure and just uses a
|
||||||
|
// normal one) because Dave will not appropriately convert the error.
|
||||||
|
func testReceiverBlindedError(ht *lntest.HarnessTest) {
|
||||||
|
ctx, testCase := newBlindedForwardTest(ht)
|
||||||
|
defer testCase.cleanup()
|
||||||
|
route := testCase.setup(ctx)
|
||||||
|
|
||||||
|
sendAndResumeBlindedPayment(ctx, ht, testCase, route, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testRelayingBlindedError tests handling of errors from relaying nodes in a
|
||||||
|
// blinded route, testing a failure over on Carol's outgoing link in the
|
||||||
|
// following topology: Alice -- Bob -- Carol -- Dave, where Bob is the
|
||||||
|
// introduction node.
|
||||||
|
func testRelayingBlindedError(ht *lntest.HarnessTest) {
|
||||||
|
ctx, testCase := newBlindedForwardTest(ht)
|
||||||
|
defer testCase.cleanup()
|
||||||
|
route := testCase.setup(ctx)
|
||||||
|
|
||||||
|
// Before we send our payment, drain all of Carol's liquidity
|
||||||
|
// so that she can't forward the payment to Dave.
|
||||||
|
testCase.drainCarolLiquidity(false)
|
||||||
|
|
||||||
|
// Then dispatch the payment through Carol which will fail due to
|
||||||
|
// a lack of liquidity. This check only happens _after_ the interceptor
|
||||||
|
// has given the instruction to resume so we can use test
|
||||||
|
// infrastructure that will go ahead and intercept the payment.
|
||||||
|
sendAndResumeBlindedPayment(ctx, ht, testCase, route, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendAndResumeBlindedPayment sends a blinded payment through the test
|
||||||
|
// network provided, intercepting the payment at Carol and allowing it to
|
||||||
|
// resume. This utility function allows us to ensure that payments at least
|
||||||
|
// reach Carol and asserts that all errors appear to originate from the
|
||||||
|
// introduction node.
|
||||||
|
func sendAndResumeBlindedPayment(ctx context.Context, ht *lntest.HarnessTest,
|
||||||
|
testCase *blindedForwardTest, route *routing.BlindedPayment,
|
||||||
|
interceptAtCarol bool) {
|
||||||
|
|
||||||
|
blindedRoute := testCase.createRouteToBlinded(10_000_000, route)
|
||||||
|
|
||||||
|
// Before we dispatch the payment, spin up a goroutine that will
|
||||||
|
// intercept the HTLC on Carol's forward. This allows us to ensure
|
||||||
|
// that the HTLC actually reaches the location we expect it to.
|
||||||
|
var resolveHTLC func(routerrpc.ResolveHoldForwardAction)
|
||||||
|
if interceptAtCarol {
|
||||||
|
resolveHTLC = testCase.interceptFinalHop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, test sending the payment all the way through to Dave. We
|
||||||
|
// expect this payment to fail, because he does not know how to
|
||||||
|
// process payments to a blinded route (not yet supported).
|
||||||
|
cancelPmt := testCase.sendBlindedPayment(ctx, blindedRoute)
|
||||||
|
defer cancelPmt()
|
||||||
|
|
||||||
|
// When Carol intercepts the HTLC, instruct her to resume the payment
|
||||||
|
// so that it'll reach Dave and fail.
|
||||||
|
if interceptAtCarol {
|
||||||
|
resolveHTLC(routerrpc.ResolveHoldForwardAction_RESUME)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the HTLC to reflect as failed for Alice.
|
||||||
|
preimage, err := lntypes.MakePreimage(testCase.preimage[:])
|
||||||
|
require.NoError(ht, err)
|
||||||
|
pmt := ht.AssertPaymentStatus(ht.Alice, preimage, lnrpc.Payment_FAILED)
|
||||||
|
require.Len(ht, pmt.Htlcs, 1)
|
||||||
|
require.EqualValues(
|
||||||
|
ht, 1, pmt.Htlcs[0].Failure.FailureSourceIndex,
|
||||||
|
)
|
||||||
|
require.Equal(
|
||||||
|
ht, lnrpc.Failure_INVALID_ONION_BLINDING,
|
||||||
|
pmt.Htlcs[0].Failure.Code,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testIntroductionNodeError tests handling of errors in a blinded route when
|
||||||
|
// the introduction node is the source of the error. This test sends a payment
|
||||||
|
// over Alice -- Bob -- Carol -- Dave, where Bob is the introduction node and
|
||||||
|
// has insufficient outgoing liquidity to forward on to carol.
|
||||||
|
func testIntroductionNodeError(ht *lntest.HarnessTest) {
|
||||||
|
ctx, testCase := newBlindedForwardTest(ht)
|
||||||
|
defer testCase.cleanup()
|
||||||
|
route := testCase.setup(ctx)
|
||||||
|
|
||||||
|
// Before we send our payment, drain all of Carol's incoming liquidity
|
||||||
|
// so that she can't receive the forward from Bob, causing a failure
|
||||||
|
// at the introduction node.
|
||||||
|
testCase.drainCarolLiquidity(true)
|
||||||
|
|
||||||
|
// Send the payment, but do not expect it to reach Carol at all.
|
||||||
|
sendAndResumeBlindedPayment(ctx, ht, testCase, route, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testDisableIntroductionNode tests disabling of blinded forwards for the
|
||||||
|
// introduction node.
|
||||||
|
func testDisableIntroductionNode(ht *lntest.HarnessTest) {
|
||||||
|
// Disable route blinding for Bob, then re-connect to Alice.
|
||||||
|
ht.RestartNodeWithExtraArgs(ht.Bob, []string{
|
||||||
|
"--protocol.no-route-blinding",
|
||||||
|
})
|
||||||
|
ht.EnsureConnected(ht.Alice, ht.Bob)
|
||||||
|
|
||||||
|
ctx, testCase := newBlindedForwardTest(ht)
|
||||||
|
defer testCase.cleanup()
|
||||||
|
route := testCase.setup(ctx)
|
||||||
|
// We always expect failures to look like they originated at Bob
|
||||||
|
// because blinded errors are converted. However, our tests intercepts
|
||||||
|
// all of Carol's forwards and we're not providing it any interceptor
|
||||||
|
// instructions. This means that the test will hang/timeout at Carol
|
||||||
|
// if Bob _doesn't_ fail the HTLC back as expected.
|
||||||
|
sendAndResumeBlindedPayment(ctx, ht, testCase, route, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testErrorHandlingOnChainFailure tests handling of blinded errors when we're
|
||||||
|
// resolving from an on-chain resolution. This test also tests that we're able
|
||||||
|
// to resolve blinded HTLCs on chain between restarts, as we've got all the
|
||||||
|
// infrastructure in place already for error testing.
|
||||||
|
func testErrorHandlingOnChainFailure(ht *lntest.HarnessTest) {
|
||||||
|
// Setup a test case, note that we don't use its built in clean up
|
||||||
|
// because we're going to close a channel so we'll close out the
|
||||||
|
// rest manually.
|
||||||
|
ctx, testCase := newBlindedForwardTest(ht)
|
||||||
|
|
||||||
|
// Note that we send a larger amount here do it'll be worthwhile for
|
||||||
|
// the sweeper to claim.
|
||||||
|
route := testCase.setup(ctx)
|
||||||
|
blindedRoute := testCase.createRouteToBlinded(50_000_000, route)
|
||||||
|
|
||||||
|
// Once our interceptor is set up, we can send the blinded payment.
|
||||||
|
cancelPmt := testCase.sendBlindedPayment(ctx, blindedRoute)
|
||||||
|
defer cancelPmt()
|
||||||
|
|
||||||
|
// Wait for the HTLC to be active on Alice and Bob's channels.
|
||||||
|
hash := sha256.Sum256(testCase.preimage[:])
|
||||||
|
ht.AssertOutgoingHTLCActive(ht.Alice, testCase.channels[0], hash[:])
|
||||||
|
ht.AssertOutgoingHTLCActive(ht.Bob, testCase.channels[1], hash[:])
|
||||||
|
|
||||||
|
// Intercept the forward on Carol's link, but do not take any action
|
||||||
|
// so that we have the chance to force close with this HTLC in flight.
|
||||||
|
carolHTLC, err := testCase.carolInterceptor.Recv()
|
||||||
|
require.NoError(ht, err)
|
||||||
|
|
||||||
|
// Force close Bob <-> Carol.
|
||||||
|
closeStream, _ := ht.CloseChannelAssertPending(
|
||||||
|
ht.Bob, testCase.channels[1], true,
|
||||||
|
)
|
||||||
|
|
||||||
|
ht.AssertStreamChannelForceClosed(
|
||||||
|
ht.Bob, testCase.channels[1], false, closeStream,
|
||||||
|
)
|
||||||
|
|
||||||
|
// SuspendCarol so that she can't interfere with the resolution of the
|
||||||
|
// HTLC from now on.
|
||||||
|
restartCarol := ht.SuspendNode(testCase.carol)
|
||||||
|
|
||||||
|
// Mine blocks so that Bob will claim his CSV delayed local commitment,
|
||||||
|
// we've already mined 1 block so we need one less than our CSV.
|
||||||
|
ht.MineBlocks(node.DefaultCSV - 1)
|
||||||
|
ht.AssertNumPendingSweeps(ht.Bob, 1)
|
||||||
|
ht.MineEmptyBlocks(1)
|
||||||
|
ht.Miner.MineBlocksAndAssertNumTxes(1, 1)
|
||||||
|
|
||||||
|
// Restart bob so that we can test that he's able to recover everything
|
||||||
|
// he needs to claim a blinded HTLC.
|
||||||
|
ht.RestartNode(ht.Bob)
|
||||||
|
|
||||||
|
// Mine enough blocks for Bob to trigger timeout of his outgoing HTLC.
|
||||||
|
// Carol's incoming expiry height is Bob's outgoing so we can use this
|
||||||
|
// value.
|
||||||
|
info := ht.Bob.RPC.GetInfo()
|
||||||
|
target := carolHTLC.IncomingExpiry - info.BlockHeight
|
||||||
|
ht.MineBlocks(target)
|
||||||
|
|
||||||
|
// Wait for Bob's timeout transaction in the mempool, since we've
|
||||||
|
// suspended Carol we don't need to account for her commitment output
|
||||||
|
// claim.
|
||||||
|
ht.Miner.MineBlocksAndAssertNumTxes(1, 1)
|
||||||
|
|
||||||
|
// Assert that the HTLC has cleared.
|
||||||
|
ht.AssertHTLCNotActive(ht.Alice, testCase.channels[0], hash[:])
|
||||||
|
ht.AssertHTLCNotActive(ht.Bob, testCase.channels[0], hash[:])
|
||||||
|
|
||||||
|
// Wait for the HTLC to reflect as failed for Alice.
|
||||||
|
paymentStream := ht.Alice.RPC.TrackPaymentV2(hash[:])
|
||||||
|
htlcs := ht.ReceiveTrackPayment(paymentStream).Htlcs
|
||||||
|
require.Len(ht, htlcs, 1)
|
||||||
|
require.NotNil(ht, htlcs[0].Failure)
|
||||||
|
require.Equal(
|
||||||
|
ht, htlcs[0].Failure.Code,
|
||||||
|
lnrpc.Failure_INVALID_ONION_BLINDING,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Clean up the rest of our force close: mine blocks so that Bob's CSV
|
||||||
|
// expires plus one block to trigger his sweep and then mine it.
|
||||||
|
ht.MineBlocks(node.DefaultCSV + 1)
|
||||||
|
ht.Miner.MineBlocksAndAssertNumTxes(1, 1)
|
||||||
|
|
||||||
|
// Bring carol back up so that we can close out the rest of our
|
||||||
|
// channels cooperatively. She requires an interceptor to start up
|
||||||
|
// so we just re-register our interceptor.
|
||||||
|
require.NoError(ht, restartCarol())
|
||||||
|
_, err = testCase.carol.RPC.Router.HtlcInterceptor(ctx)
|
||||||
|
require.NoError(ht, err, "interceptor")
|
||||||
|
|
||||||
|
// Assert that Carol has started up and reconnected to dave so that
|
||||||
|
// we can close out channels cooperatively.
|
||||||
|
ht.EnsureConnected(testCase.carol, testCase.dave)
|
||||||
|
|
||||||
|
// Manually close out the rest of our channels and cancel (don't use
|
||||||
|
// built in cleanup which will try close the already-force-closed
|
||||||
|
// channel).
|
||||||
|
ht.CloseChannel(ht.Alice, testCase.channels[0])
|
||||||
|
ht.CloseChannel(testCase.carol, testCase.channels[2])
|
||||||
|
testCase.cancel()
|
||||||
|
}
|
||||||
|
|
|
@ -59,14 +59,6 @@ type ProtocolOptions struct {
|
||||||
NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"`
|
NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultProtocol returns a protocol config with route blinding turned off,
|
|
||||||
// temporarily in place until full handling of blinded route errors is merged.
|
|
||||||
func DefaultProtocol() *ProtocolOptions {
|
|
||||||
return &ProtocolOptions{
|
|
||||||
NoRouteBlindingOption: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wumbo returns true if lnd should permit the creation and acceptance of wumbo
|
// Wumbo returns true if lnd should permit the creation and acceptance of wumbo
|
||||||
// channels.
|
// channels.
|
||||||
func (l *ProtocolOptions) Wumbo() bool {
|
func (l *ProtocolOptions) Wumbo() bool {
|
||||||
|
|
|
@ -62,13 +62,6 @@ type ProtocolOptions struct {
|
||||||
NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"`
|
NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultProtocol returns a protocol config with route blinding turned on,
|
|
||||||
// so that itests can run against route blinding features even while we've
|
|
||||||
// got it turned off for the daemon (pending completion of error handling).
|
|
||||||
func DefaultProtocol() *ProtocolOptions {
|
|
||||||
return &ProtocolOptions{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wumbo returns true if lnd should permit the creation and acceptance of wumbo
|
// Wumbo returns true if lnd should permit the creation and acceptance of wumbo
|
||||||
// channels.
|
// channels.
|
||||||
func (l *ProtocolOptions) Wumbo() bool {
|
func (l *ProtocolOptions) Wumbo() bool {
|
||||||
|
|
|
@ -651,6 +651,8 @@ const (
|
||||||
FeatureBit_ANCHORS_OPT FeatureBit = 21
|
FeatureBit_ANCHORS_OPT FeatureBit = 21
|
||||||
FeatureBit_ANCHORS_ZERO_FEE_HTLC_REQ FeatureBit = 22
|
FeatureBit_ANCHORS_ZERO_FEE_HTLC_REQ FeatureBit = 22
|
||||||
FeatureBit_ANCHORS_ZERO_FEE_HTLC_OPT FeatureBit = 23
|
FeatureBit_ANCHORS_ZERO_FEE_HTLC_OPT FeatureBit = 23
|
||||||
|
FeatureBit_ROUTE_BLINDING_REQUIRED FeatureBit = 24
|
||||||
|
FeatureBit_ROUTE_BLINDING_OPTIONAL FeatureBit = 25
|
||||||
FeatureBit_AMP_REQ FeatureBit = 30
|
FeatureBit_AMP_REQ FeatureBit = 30
|
||||||
FeatureBit_AMP_OPT FeatureBit = 31
|
FeatureBit_AMP_OPT FeatureBit = 31
|
||||||
)
|
)
|
||||||
|
@ -681,6 +683,8 @@ var (
|
||||||
21: "ANCHORS_OPT",
|
21: "ANCHORS_OPT",
|
||||||
22: "ANCHORS_ZERO_FEE_HTLC_REQ",
|
22: "ANCHORS_ZERO_FEE_HTLC_REQ",
|
||||||
23: "ANCHORS_ZERO_FEE_HTLC_OPT",
|
23: "ANCHORS_ZERO_FEE_HTLC_OPT",
|
||||||
|
24: "ROUTE_BLINDING_REQUIRED",
|
||||||
|
25: "ROUTE_BLINDING_OPTIONAL",
|
||||||
30: "AMP_REQ",
|
30: "AMP_REQ",
|
||||||
31: "AMP_OPT",
|
31: "AMP_OPT",
|
||||||
}
|
}
|
||||||
|
@ -708,6 +712,8 @@ var (
|
||||||
"ANCHORS_OPT": 21,
|
"ANCHORS_OPT": 21,
|
||||||
"ANCHORS_ZERO_FEE_HTLC_REQ": 22,
|
"ANCHORS_ZERO_FEE_HTLC_REQ": 22,
|
||||||
"ANCHORS_ZERO_FEE_HTLC_OPT": 23,
|
"ANCHORS_ZERO_FEE_HTLC_OPT": 23,
|
||||||
|
"ROUTE_BLINDING_REQUIRED": 24,
|
||||||
|
"ROUTE_BLINDING_OPTIONAL": 25,
|
||||||
"AMP_REQ": 30,
|
"AMP_REQ": 30,
|
||||||
"AMP_OPT": 31,
|
"AMP_OPT": 31,
|
||||||
}
|
}
|
||||||
|
@ -20669,7 +20675,7 @@ var file_lightning_proto_rawDesc = []byte{
|
||||||
0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x04,
|
0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x04,
|
||||||
0x12, 0x27, 0x0a, 0x23, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53,
|
0x12, 0x27, 0x0a, 0x23, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53,
|
||||||
0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f,
|
0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f,
|
||||||
0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x05, 0x2a, 0xcf, 0x04, 0x0a, 0x0a, 0x46, 0x65,
|
0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x05, 0x2a, 0x89, 0x05, 0x0a, 0x0a, 0x46, 0x65,
|
||||||
0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41,
|
0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41,
|
||||||
0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51,
|
0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51,
|
||||||
0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50,
|
0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50,
|
||||||
|
@ -20705,338 +20711,342 @@ var file_lightning_proto_rawDesc = []byte{
|
||||||
0x45, 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x52, 0x45, 0x51,
|
0x45, 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x52, 0x45, 0x51,
|
||||||
0x10, 0x16, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, 0x45,
|
0x10, 0x16, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, 0x45,
|
||||||
0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x4f, 0x50, 0x54, 0x10,
|
0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x4f, 0x50, 0x54, 0x10,
|
||||||
0x17, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x1e, 0x12, 0x0b,
|
0x17, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44,
|
||||||
0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x1f, 0x2a, 0xac, 0x01, 0x0a, 0x0d,
|
0x49, 0x4e, 0x47, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x18, 0x12, 0x1b,
|
||||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a,
|
0x0a, 0x17, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47,
|
||||||
0x16, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f,
|
0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x19, 0x12, 0x0b, 0x0a, 0x07, 0x41,
|
||||||
0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44,
|
0x4d, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x1e, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f,
|
||||||
0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44,
|
0x4f, 0x50, 0x54, 0x10, 0x1f, 0x2a, 0xac, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||||
0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f,
|
0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, 0x41, 0x54,
|
||||||
0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e,
|
0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
|
||||||
0x44, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41,
|
0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41,
|
||||||
0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45,
|
0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12,
|
||||||
0x52, 0x52, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46,
|
0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52,
|
||||||
0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x50,
|
0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1f, 0x0a,
|
||||||
0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x10, 0x04, 0x32, 0xb9, 0x27, 0x0a, 0x09, 0x4c,
|
0x1b, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f,
|
||||||
0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c,
|
0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x10, 0x03, 0x12, 0x24,
|
||||||
0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45,
|
||||||
0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52,
|
0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57,
|
0x45, 0x52, 0x10, 0x04, 0x32, 0xb9, 0x27, 0x0a, 0x09, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69,
|
||||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70,
|
0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61,
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42,
|
0x6e, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c,
|
||||||
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43,
|
0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71,
|
0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61,
|
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d,
|
||||||
0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
|
||||||
0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
|
0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
||||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47,
|
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d,
|
||||||
0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72,
|
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a,
|
||||||
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
|
0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||||
0x12, 0x44, 0x0a, 0x0b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x12,
|
0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e,
|
||||||
0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
|
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
0x46, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72,
|
0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
|
||||||
0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65,
|
0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x44, 0x0a, 0x0b, 0x45, 0x73,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f,
|
0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
||||||
0x69, 0x6e, 0x73, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64,
|
0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x71,
|
||||||
0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c,
|
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74,
|
||||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65,
|
0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e,
|
0x12, 0x3e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x17, 0x2e,
|
||||||
0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52,
|
||||||
0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53,
|
||||||
0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73,
|
0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15,
|
0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12,
|
||||||
0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65,
|
0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71,
|
0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
|
||||||
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x65,
|
0x69, 0x62, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
|
||||||
0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53,
|
0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73,
|
||||||
0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17,
|
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64,
|
0x6f, 0x6e, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79,
|
||||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65,
|
0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e,
|
||||||
0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65,
|
0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||||
0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x69,
|
0x65, 0x12, 0x41, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12,
|
||||||
0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65,
|
||||||
0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71,
|
0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67,
|
0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||||
0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73,
|
||||||
0x12, 0x4a, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e,
|
||||||
0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79,
|
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a,
|
||||||
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73,
|
0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, 0x56, 0x65,
|
||||||
0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b,
|
0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e,
|
||||||
0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x6c, 0x6e,
|
0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||||
0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52,
|
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43,
|
0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65,
|
||||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||||
0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
|
0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f,
|
||||||
0x50, 0x65, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73,
|
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
|
||||||
0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f,
|
0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e,
|
||||||
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1c,
|
||||||
0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x17,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73,
|
0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50,
|
||||||
0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4c,
|
||||||
0x65, 0x12, 0x47, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x65,
|
0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
|
0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65,
|
||||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50,
|
0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x13, 0x53,
|
||||||
0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65,
|
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e,
|
||||||
0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65,
|
0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45,
|
||||||
0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c,
|
0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70,
|
0x1a, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65,
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67,
|
0x6e, 0x74, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12,
|
||||||
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
|
0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
||||||
0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47,
|
||||||
0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75,
|
0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47,
|
||||||
0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a,
|
0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a,
|
||||||
0x0f, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49,
|
||||||
0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f,
|
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
||||||
0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x65,
|
||||||
0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x50, 0x0a, 0x0f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e,
|
||||||
0x6c, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69,
|
0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
||||||
0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66,
|
||||||
0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e,
|
0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x50, 0x65, 0x6e,
|
||||||
0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1d, 0x2e, 0x6c,
|
||||||
0x65, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e,
|
||||||
0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68,
|
0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e,
|
||||||
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e,
|
0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x4c,
|
||||||
0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75,
|
0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e,
|
||||||
0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76,
|
0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73,
|
||||||
0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
|
0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68,
|
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62,
|
||||||
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f,
|
||||||
0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76,
|
||||||
0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f,
|
0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a,
|
||||||
0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45,
|
||||||
0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65,
|
0x76, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e,
|
||||||
0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1c,
|
||||||
0x65, 0x12, 0x41, 0x0a, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61,
|
||||||
0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65,
|
0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c,
|
||||||
0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e,
|
||||||
0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50,
|
0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0f, 0x4f,
|
||||||
0x6f, 0x69, 0x6e, 0x74, 0x12, 0x43, 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e,
|
0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19,
|
||||||
0x6e, 0x65, 0x6c, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e,
|
||||||
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17,
|
0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75,
|
0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x43,
|
||||||
0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x10, 0x42, 0x61, 0x74,
|
0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x19, 0x2e,
|
||||||
0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1e, 0x2e,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43,
|
0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e,
|
0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43,
|
0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x10, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e,
|
||||||
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c,
|
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x0a, 0x10, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74,
|
0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
||||||
0x65, 0x70, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x6e, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x1a,
|
0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
||||||
0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x46, 0x75, 0x6e, 0x64,
|
||||||
0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x52, 0x65, 0x73, 0x70, 0x12, 0x50, 0x0a, 0x0f,
|
0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x12, 0x1b, 0x2e, 0x6c,
|
||||||
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12,
|
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x61, 0x6e,
|
||||||
0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41,
|
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
||||||
0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e,
|
0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63,
|
0x65, 0x70, 0x52, 0x65, 0x73, 0x70, 0x12, 0x50, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
||||||
0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x46,
|
0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
||||||
0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a,
|
0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72,
|
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71,
|
||||||
0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70,
|
0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73,
|
||||||
0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f,
|
0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71,
|
||||||
0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52,
|
0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41,
|
0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01,
|
||||||
0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73,
|
0x12, 0x4d, 0x0a, 0x0e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79,
|
0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64,
|
||||||
0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e,
|
0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e,
|
||||||
0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88,
|
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||||
0x02, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61,
|
0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12,
|
||||||
0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e,
|
0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x28, 0x01, 0x30, 0x01,
|
||||||
0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74,
|
0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53,
|
||||||
0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f,
|
0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64,
|
||||||
0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b,
|
||||||
0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x65,
|
0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e,
|
||||||
0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e,
|
0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53,
|
||||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01,
|
||||||
0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a,
|
0x28, 0x01, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f,
|
||||||
0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x2e, 0x6c, 0x6e,
|
0x75, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x6c, 0x6e,
|
0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65,
|
0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e,
|
||||||
0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c,
|
0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e,
|
||||||
0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x76, 0x6f, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64,
|
||||||
0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e,
|
0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a,
|
0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73,
|
||||||
0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x12,
|
0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61,
|
0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e,
|
||||||
0x73, 0x68, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69,
|
0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52,
|
||||||
0x63, 0x65, 0x12, 0x41, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x49,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75,
|
||||||
0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x0e, 0x2e, 0x6c,
|
||||||
0x69, 0x6f, 0x6e, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f,
|
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x11,
|
||||||
0x69, 0x63, 0x65, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x0c, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50,
|
0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65,
|
||||||
0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61,
|
0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63,
|
||||||
0x79, 0x52, 0x65, 0x71, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0d, 0x2e, 0x6c, 0x6e, 0x72,
|
0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x0e, 0x2e,
|
||||||
0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x30, 0x01, 0x12,
|
||||||
0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
0x32, 0x0a, 0x0c, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12,
|
||||||
0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65,
|
0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x53, 0x74,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69,
|
0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79,
|
||||||
0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x52, 0x65, 0x71, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65,
|
||||||
0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d,
|
0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74,
|
||||||
0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65,
|
0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d,
|
||||||
0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50,
|
0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d,
|
||||||
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56,
|
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e,
|
||||||
0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d,
|
||||||
0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65,
|
0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71,
|
0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65,
|
||||||
0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65,
|
0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50,
|
||||||
0x62, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20,
|
||||||
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e,
|
0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x47, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e,
|
0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x47, 0x72, 0x61, 0x70,
|
||||||
0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72,
|
0x68, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
||||||
0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65,
|
0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61,
|
||||||
0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x70, 0x68, 0x12, 0x47, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74,
|
||||||
0x65, 0x12, 0x39, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f,
|
0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64,
|
||||||
0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66,
|
0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72,
|
||||||
0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x0b,
|
0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x47,
|
||||||
0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e,
|
0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75,
|
0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65,
|
0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e,
|
||||||
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75,
|
0x65, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64,
|
||||||
0x74, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72,
|
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f,
|
||||||
0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a,
|
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44,
|
||||||
0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x65,
|
0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x19, 0x2e,
|
||||||
0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x6c,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
||||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f,
|
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||||
0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x0a, 0x53,
|
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f,
|
||||||
0x74, 0x6f, 0x70, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e,
|
||||||
0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e,
|
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72,
|
||||||
0x73, 0x65, 0x12, 0x57, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43,
|
0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x61, 0x65,
|
||||||
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x20, 0x2e, 0x6c, 0x6e,
|
0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70,
|
||||||
0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x79, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1a, 0x2e,
|
0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x15,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c,
|
0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
||||||
0x6f, 0x67, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44,
|
0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72,
|
||||||
0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x75, 0x62, 0x73, 0x63,
|
||||||
0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75,
|
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75,
|
0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x55, 0x70, 0x64,
|
||||||
0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e,
|
0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65,
|
||||||
0x0a, 0x09, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6e,
|
0x76, 0x65, 0x6c, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75,
|
||||||
0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71,
|
0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c,
|
||||||
0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x46, 0x65, 0x65, 0x52,
|
||||||
0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50,
|
0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65,
|
||||||
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f,
|
0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18,
|
||||||
0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74,
|
||||||
0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61,
|
||||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56,
|
0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12,
|
||||||
0x0a, 0x11, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74,
|
0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70,
|
||||||
0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77,
|
0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e,
|
||||||
0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71,
|
0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x46, 0x6f, 0x72, 0x77,
|
||||||
0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65,
|
0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67,
|
||||||
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x21, 0x2e,
|
0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e,
|
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e,
|
||||||
0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
0x12, 0x4e, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
||||||
0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x54, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74,
|
0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x21, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70,
|
0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63,
|
||||||
0x73, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61,
|
0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x63, 0x6b, 0x75, 0x70, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70,
|
||||||
0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61,
|
0x12, 0x54, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61,
|
||||||
0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a, 0x10,
|
0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1e, 0x2e, 0x6c, 0x6e,
|
||||||
0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70,
|
0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x45, 0x78,
|
||||||
0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63,
|
0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e,
|
||||||
0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e,
|
0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e,
|
||||||
0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61,
|
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79,
|
||||||
0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15,
|
0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61,
|
0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61,
|
||||||
0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65,
|
0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65,
|
||||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52,
|
0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72,
|
||||||
0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70,
|
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62,
|
|
||||||
0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12,
|
0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12,
|
||||||
0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42,
|
0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43,
|
||||||
0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61,
|
0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||||
0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x30, 0x01, 0x12, 0x47,
|
0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58,
|
||||||
0x0a, 0x0c, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x1a,
|
0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72,
|
0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
||||||
0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72,
|
0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53,
|
||||||
0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52,
|
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d,
|
0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e,
|
||||||
0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72,
|
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x30, 0x01, 0x12, 0x47, 0x0a, 0x0c, 0x42, 0x61, 0x6b, 0x65,
|
||||||
0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49,
|
0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71,
|
||||||
0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44,
|
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b,
|
||||||
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x6c,
|
0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||||
0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1e, 0x2e,
|
0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61,
|
0x6e, 0x49, 0x44, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73,
|
||||||
0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e,
|
0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61,
|
0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74,
|
||||||
0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50,
|
0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63,
|
||||||
0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65,
|
0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44,
|
||||||
0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44,
|
||||||
0x12, 0x53, 0x0a, 0x18, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74,
|
||||||
0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x6c,
|
0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e,
|
||||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72,
|
0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69,
|
||||||
0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73,
|
0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x18, 0x43, 0x68,
|
||||||
0x72, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x12, 0x1c,
|
0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65,
|
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43,
|
||||||
0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c,
|
0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61,
|
0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b,
|
||||||
0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x56, 0x0a,
|
0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||||
0x11, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
0x56, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x50, 0x43, 0x4d, 0x69,
|
||||||
0x67, 0x65, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43,
|
0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75,
|
0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52,
|
||||||
0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73,
|
0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
|
0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x43,
|
||||||
0x62, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x6c,
|
||||||
0x12, 0x25, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
|
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d,
|
||||||
0x62, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d,
|
||||||
0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12,
|
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||||
0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x19,
|
0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x75, 0x73, 0x74,
|
||||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73,
|
0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x6c, 0x6e, 0x72,
|
||||||
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x75, 0x73, 0x74,
|
||||||
0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73,
|
0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x14, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48,
|
0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d,
|
||||||
0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e,
|
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73,
|
||||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63,
|
0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||||
0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||||
0x74, 0x1a, 0x23, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70,
|
0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74,
|
||||||
0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
|
0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
0x5f, 0x0a, 0x14, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73,
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65,
|
0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x62,
|
0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75,
|
||||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6c, 0x6e,
|
||||||
|
0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65,
|
||||||
|
0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
|
0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c,
|
||||||
|
0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f,
|
||||||
|
0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
|
0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -4311,6 +4311,8 @@ enum FeatureBit {
|
||||||
ANCHORS_OPT = 21;
|
ANCHORS_OPT = 21;
|
||||||
ANCHORS_ZERO_FEE_HTLC_REQ = 22;
|
ANCHORS_ZERO_FEE_HTLC_REQ = 22;
|
||||||
ANCHORS_ZERO_FEE_HTLC_OPT = 23;
|
ANCHORS_ZERO_FEE_HTLC_OPT = 23;
|
||||||
|
ROUTE_BLINDING_REQUIRED = 24;
|
||||||
|
ROUTE_BLINDING_OPTIONAL = 25;
|
||||||
AMP_REQ = 30;
|
AMP_REQ = 30;
|
||||||
AMP_OPT = 31;
|
AMP_OPT = 31;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1470,6 +1470,8 @@
|
||||||
"ANCHORS_OPT",
|
"ANCHORS_OPT",
|
||||||
"ANCHORS_ZERO_FEE_HTLC_REQ",
|
"ANCHORS_ZERO_FEE_HTLC_REQ",
|
||||||
"ANCHORS_ZERO_FEE_HTLC_OPT",
|
"ANCHORS_ZERO_FEE_HTLC_OPT",
|
||||||
|
"ROUTE_BLINDING_REQUIRED",
|
||||||
|
"ROUTE_BLINDING_OPTIONAL",
|
||||||
"AMP_REQ",
|
"AMP_REQ",
|
||||||
"AMP_OPT"
|
"AMP_OPT"
|
||||||
]
|
]
|
||||||
|
@ -4694,6 +4696,8 @@
|
||||||
"ANCHORS_OPT",
|
"ANCHORS_OPT",
|
||||||
"ANCHORS_ZERO_FEE_HTLC_REQ",
|
"ANCHORS_ZERO_FEE_HTLC_REQ",
|
||||||
"ANCHORS_ZERO_FEE_HTLC_OPT",
|
"ANCHORS_ZERO_FEE_HTLC_OPT",
|
||||||
|
"ROUTE_BLINDING_REQUIRED",
|
||||||
|
"ROUTE_BLINDING_OPTIONAL",
|
||||||
"AMP_REQ",
|
"AMP_REQ",
|
||||||
"AMP_OPT"
|
"AMP_OPT"
|
||||||
],
|
],
|
||||||
|
|
|
@ -77,6 +77,8 @@
|
||||||
"ANCHORS_OPT",
|
"ANCHORS_OPT",
|
||||||
"ANCHORS_ZERO_FEE_HTLC_REQ",
|
"ANCHORS_ZERO_FEE_HTLC_REQ",
|
||||||
"ANCHORS_ZERO_FEE_HTLC_OPT",
|
"ANCHORS_ZERO_FEE_HTLC_OPT",
|
||||||
|
"ROUTE_BLINDING_REQUIRED",
|
||||||
|
"ROUTE_BLINDING_OPTIONAL",
|
||||||
"AMP_REQ",
|
"AMP_REQ",
|
||||||
"AMP_OPT"
|
"AMP_OPT"
|
||||||
],
|
],
|
||||||
|
|
|
@ -772,6 +772,8 @@
|
||||||
"ANCHORS_OPT",
|
"ANCHORS_OPT",
|
||||||
"ANCHORS_ZERO_FEE_HTLC_REQ",
|
"ANCHORS_ZERO_FEE_HTLC_REQ",
|
||||||
"ANCHORS_ZERO_FEE_HTLC_OPT",
|
"ANCHORS_ZERO_FEE_HTLC_OPT",
|
||||||
|
"ROUTE_BLINDING_REQUIRED",
|
||||||
|
"ROUTE_BLINDING_OPTIONAL",
|
||||||
"AMP_REQ",
|
"AMP_REQ",
|
||||||
"AMP_OPT"
|
"AMP_OPT"
|
||||||
],
|
],
|
||||||
|
|
|
@ -141,6 +141,14 @@ const (
|
||||||
// transactions, which also imply anchor commitments.
|
// transactions, which also imply anchor commitments.
|
||||||
AnchorsZeroFeeHtlcTxOptional FeatureBit = 23
|
AnchorsZeroFeeHtlcTxOptional FeatureBit = 23
|
||||||
|
|
||||||
|
// RouteBlindingRequired is a required feature bit that signals that
|
||||||
|
// the node supports blinded payments.
|
||||||
|
RouteBlindingRequired FeatureBit = 24
|
||||||
|
|
||||||
|
// RouteBlindingOptional is an optional feature bit that signals that
|
||||||
|
// the node supports blinded payments.
|
||||||
|
RouteBlindingOptional FeatureBit = 25
|
||||||
|
|
||||||
// ShutdownAnySegwitRequired is an required feature bit that signals
|
// ShutdownAnySegwitRequired is an required feature bit that signals
|
||||||
// that the sender is able to properly handle/parse segwit witness
|
// that the sender is able to properly handle/parse segwit witness
|
||||||
// programs up to version 16. This enables utilization of Taproot
|
// programs up to version 16. This enables utilization of Taproot
|
||||||
|
@ -315,6 +323,8 @@ var Features = map[FeatureBit]string{
|
||||||
ScidAliasOptional: "scid-alias",
|
ScidAliasOptional: "scid-alias",
|
||||||
ZeroConfRequired: "zero-conf",
|
ZeroConfRequired: "zero-conf",
|
||||||
ZeroConfOptional: "zero-conf",
|
ZeroConfOptional: "zero-conf",
|
||||||
|
RouteBlindingRequired: "route-blinding",
|
||||||
|
RouteBlindingOptional: "route-blinding",
|
||||||
ShutdownAnySegwitRequired: "shutdown-any-segwit",
|
ShutdownAnySegwitRequired: "shutdown-any-segwit",
|
||||||
ShutdownAnySegwitOptional: "shutdown-any-segwit",
|
ShutdownAnySegwitOptional: "shutdown-any-segwit",
|
||||||
SimpleTaprootChannelsRequiredFinal: "simple-taproot-chans",
|
SimpleTaprootChannelsRequiredFinal: "simple-taproot-chans",
|
||||||
|
|
|
@ -549,6 +549,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
|
||||||
NoAnySegwit: cfg.ProtocolOptions.NoAnySegwit(),
|
NoAnySegwit: cfg.ProtocolOptions.NoAnySegwit(),
|
||||||
CustomFeatures: cfg.ProtocolOptions.ExperimentalProtocol.CustomFeatures(),
|
CustomFeatures: cfg.ProtocolOptions.ExperimentalProtocol.CustomFeatures(),
|
||||||
NoTaprootChans: !cfg.ProtocolOptions.TaprootChans,
|
NoTaprootChans: !cfg.ProtocolOptions.TaprootChans,
|
||||||
|
NoRouteBlinding: cfg.ProtocolOptions.NoRouteBlinding(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Add table
Reference in a new issue