mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-26 09:42:05 +01:00
Merge pull request #8633 from ffranr/8619-rpc+htlcswitch-add-htlc-transformation-capabilities-to-the-interceptor
rpc+htlcswitch: add htlc transformation capabilities to the interceptor
This commit is contained in:
commit
a908c579b4
@ -8,9 +8,11 @@ import (
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/record"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -105,6 +107,10 @@ const (
|
||||
|
||||
// FwdActionFail fails the intercepted packet back to the sender.
|
||||
FwdActionFail
|
||||
|
||||
// FwdActionResumeModified forwards the intercepted packet to the switch
|
||||
// with modifications.
|
||||
FwdActionResumeModified
|
||||
)
|
||||
|
||||
// FwdResolution defines the action to be taken on an intercepted packet.
|
||||
@ -119,6 +125,18 @@ type FwdResolution struct {
|
||||
// FwdActionSettle.
|
||||
Preimage lntypes.Preimage
|
||||
|
||||
// IncomingAmountMsat is the amount that is to be used for validating if
|
||||
// Action is FwdActionResumeModified.
|
||||
IncomingAmountMsat fn.Option[lnwire.MilliSatoshi]
|
||||
|
||||
// OutgoingAmountMsat is the amount that is to be used for forwarding if
|
||||
// Action is FwdActionResumeModified.
|
||||
OutgoingAmountMsat fn.Option[lnwire.MilliSatoshi]
|
||||
|
||||
// CustomRecords is the custom records that are to be used for
|
||||
// forwarding if Action is FwdActionResumeModified.
|
||||
CustomRecords fn.Option[record.CustomSet]
|
||||
|
||||
// FailureMessage is the encrypted failure message that is to be passed
|
||||
// back to the sender if action is FwdActionFail.
|
||||
FailureMessage []byte
|
||||
@ -363,6 +381,8 @@ func (s *InterceptableSwitch) setInterceptor(interceptor ForwardInterceptor) {
|
||||
})
|
||||
}
|
||||
|
||||
// resolve processes a HTLC given the resolution type specified by the
|
||||
// intercepting client.
|
||||
func (s *InterceptableSwitch) resolve(res *FwdResolution) error {
|
||||
intercepted, err := s.heldHtlcSet.pop(res.Key)
|
||||
if err != nil {
|
||||
@ -373,6 +393,12 @@ func (s *InterceptableSwitch) resolve(res *FwdResolution) error {
|
||||
case FwdActionResume:
|
||||
return intercepted.Resume()
|
||||
|
||||
case FwdActionResumeModified:
|
||||
return intercepted.ResumeModified(
|
||||
res.IncomingAmountMsat, res.OutgoingAmountMsat,
|
||||
res.CustomRecords,
|
||||
)
|
||||
|
||||
case FwdActionSettle:
|
||||
return intercepted.Settle(res.Preimage)
|
||||
|
||||
@ -615,6 +641,73 @@ func (f *interceptedForward) Resume() error {
|
||||
return f.htlcSwitch.ForwardPackets(nil, f.packet)
|
||||
}
|
||||
|
||||
// ResumeModified resumes the default behavior with field modifications.
|
||||
func (f *interceptedForward) ResumeModified(
|
||||
incomingAmountMsat fn.Option[lnwire.MilliSatoshi],
|
||||
outgoingAmountMsat fn.Option[lnwire.MilliSatoshi],
|
||||
customRecords fn.Option[record.CustomSet]) error {
|
||||
|
||||
// Set the incoming amount, if it is provided, on the packet.
|
||||
incomingAmountMsat.WhenSome(func(amount lnwire.MilliSatoshi) {
|
||||
f.packet.incomingAmount = amount
|
||||
})
|
||||
|
||||
// Modify the wire message contained in the packet.
|
||||
switch htlc := f.packet.htlc.(type) {
|
||||
case *lnwire.UpdateAddHTLC:
|
||||
outgoingAmountMsat.WhenSome(func(amount lnwire.MilliSatoshi) {
|
||||
htlc.Amount = amount
|
||||
})
|
||||
|
||||
//nolint:lll
|
||||
err := fn.MapOptionZ(customRecords, func(records record.CustomSet) error {
|
||||
if len(records) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type cast and validate custom records.
|
||||
htlc.CustomRecords = lnwire.CustomRecords(records)
|
||||
err := htlc.CustomRecords.Validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to validate custom "+
|
||||
"records: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to encode custom records: %w",
|
||||
err)
|
||||
}
|
||||
|
||||
case *lnwire.UpdateFulfillHTLC:
|
||||
//nolint:lll
|
||||
err := fn.MapOptionZ(customRecords, func(records record.CustomSet) error {
|
||||
if len(records) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type cast and validate custom records.
|
||||
htlc.CustomRecords = lnwire.CustomRecords(records)
|
||||
err := htlc.CustomRecords.Validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to validate custom "+
|
||||
"records: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to encode custom records: %w",
|
||||
err)
|
||||
}
|
||||
}
|
||||
|
||||
// Forward to the switch. A link quit channel isn't needed, because we
|
||||
// are on a different thread now.
|
||||
return f.htlcSwitch.ForwardPackets(nil, f.packet)
|
||||
}
|
||||
|
||||
// Fail notifies the intention to Fail an existing hold forward with an
|
||||
// encrypted failure reason.
|
||||
func (f *interceptedForward) Fail(reason []byte) error {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
@ -323,7 +324,7 @@ type InterceptableHtlcForwarder interface {
|
||||
type ForwardInterceptor func(InterceptedPacket) error
|
||||
|
||||
// InterceptedPacket contains the relevant information for the interceptor about
|
||||
// an htlc.
|
||||
// an HTLC.
|
||||
type InterceptedPacket struct {
|
||||
// IncomingCircuit contains the incoming channel and htlc id of the
|
||||
// packet.
|
||||
@ -375,6 +376,12 @@ type InterceptedForward interface {
|
||||
// this htlc which usually means forward it.
|
||||
Resume() error
|
||||
|
||||
// ResumeModified notifies the intention to resume an existing hold
|
||||
// forward with modified fields.
|
||||
ResumeModified(incomingAmountMsat,
|
||||
outgoingAmountMsat fn.Option[lnwire.MilliSatoshi],
|
||||
customRecords fn.Option[record.CustomSet]) error
|
||||
|
||||
// Settle notifies the intention to settle an existing hold
|
||||
// forward with a given preimage.
|
||||
Settle(lntypes.Preimage) error
|
||||
|
@ -38,7 +38,6 @@ func TestNetworkResultSerialization(t *testing.T) {
|
||||
ChanID: chanID,
|
||||
ID: 2,
|
||||
PaymentPreimage: preimage,
|
||||
ExtraData: make([]byte, 0),
|
||||
}
|
||||
|
||||
fail := &lnwire.UpdateFailHTLC{
|
||||
|
@ -3,9 +3,11 @@ package lnd
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/record"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -51,6 +53,14 @@ func (f *interceptedForward) Resume() error {
|
||||
return ErrCannotResume
|
||||
}
|
||||
|
||||
// ResumeModified notifies the intention to resume an existing hold forward with
|
||||
// a modified htlc.
|
||||
func (f *interceptedForward) ResumeModified(_, _ fn.Option[lnwire.MilliSatoshi],
|
||||
_ fn.Option[record.CustomSet]) error {
|
||||
|
||||
return ErrCannotResume
|
||||
}
|
||||
|
||||
// Fail notifies the intention to fail an existing hold forward with an
|
||||
// encrypted failure reason.
|
||||
func (f *interceptedForward) Fail(_ []byte) error {
|
||||
|
@ -422,6 +422,10 @@ var allTestCases = []*lntest.TestCase{
|
||||
Name: "forward interceptor",
|
||||
TestFunc: testForwardInterceptorBasic,
|
||||
},
|
||||
{
|
||||
Name: "forward interceptor modified htlc",
|
||||
TestFunc: testForwardInterceptorModifiedHtlc,
|
||||
},
|
||||
{
|
||||
Name: "zero conf channel open",
|
||||
TestFunc: testZeroConfChannelOpen,
|
||||
|
@ -1,6 +1,7 @@
|
||||
package itest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -344,6 +345,140 @@ func testForwardInterceptorBasic(ht *lntest.HarnessTest) {
|
||||
ht.CloseChannel(bob, cpBC)
|
||||
}
|
||||
|
||||
// testForwardInterceptorModifiedHtlc tests that the interceptor can modify the
|
||||
// amount and custom records of an intercepted HTLC and resume it.
|
||||
func testForwardInterceptorModifiedHtlc(ht *lntest.HarnessTest) {
|
||||
// Initialize the test context with 3 connected nodes.
|
||||
ts := newInterceptorTestScenario(ht)
|
||||
|
||||
alice, bob, carol := ts.alice, ts.bob, ts.carol
|
||||
|
||||
// Open and wait for channels.
|
||||
const chanAmt = btcutil.Amount(300000)
|
||||
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntest.OpenChannelRequest{
|
||||
{Local: alice, Remote: bob, Param: p},
|
||||
{Local: bob, Remote: carol, Param: p},
|
||||
}
|
||||
resp := ht.OpenMultiChannelsAsync(reqs)
|
||||
cpAB, cpBC := resp[0], resp[1]
|
||||
|
||||
// Make sure Alice is aware of channel Bob=>Carol.
|
||||
ht.AssertTopologyChannelOpen(alice, cpBC)
|
||||
|
||||
// Connect an interceptor to Bob's node.
|
||||
bobInterceptor, cancelBobInterceptor := bob.RPC.HtlcInterceptor()
|
||||
|
||||
// Prepare the test cases.
|
||||
invoiceValueAmtMsat := int64(1000)
|
||||
req := &lnrpc.Invoice{ValueMsat: invoiceValueAmtMsat}
|
||||
addResponse := carol.RPC.AddInvoice(req)
|
||||
invoice := carol.RPC.LookupInvoice(addResponse.RHash)
|
||||
tc := &interceptorTestCase{
|
||||
amountMsat: invoiceValueAmtMsat,
|
||||
invoice: invoice,
|
||||
payAddr: invoice.PaymentAddr,
|
||||
}
|
||||
|
||||
// We initiate a payment from Alice.
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
// Signal that all the payments have been sent.
|
||||
defer close(done)
|
||||
|
||||
ts.sendPaymentAndAssertAction(tc)
|
||||
}()
|
||||
|
||||
// We start the htlc interceptor with a simple implementation that saves
|
||||
// all intercepted packets. These packets are held to simulate a
|
||||
// pending payment.
|
||||
packet := ht.ReceiveHtlcInterceptor(bobInterceptor)
|
||||
|
||||
// Resume the intercepted HTLC with a modified amount and custom
|
||||
// records.
|
||||
if packet.CustomRecords == nil {
|
||||
packet.CustomRecords = make(map[uint64][]byte)
|
||||
}
|
||||
customRecords := packet.CustomRecords
|
||||
|
||||
// Add custom records entry.
|
||||
crKey := uint64(65537)
|
||||
crValue := []byte("custom-records-test-value")
|
||||
customRecords[crKey] = crValue
|
||||
|
||||
action := routerrpc.ResolveHoldForwardAction_RESUME_MODIFIED
|
||||
newOutgoingAmountMsat := packet.OutgoingAmountMsat + 4000
|
||||
|
||||
err := bobInterceptor.Send(&routerrpc.ForwardHtlcInterceptResponse{
|
||||
IncomingCircuitKey: packet.IncomingCircuitKey,
|
||||
OutgoingAmountMsat: newOutgoingAmountMsat,
|
||||
CustomRecords: customRecords,
|
||||
Action: action,
|
||||
})
|
||||
require.NoError(ht, err, "failed to send request")
|
||||
|
||||
// Check that the modified UpdateAddHTLC message fields were reported in
|
||||
// Carol's log.
|
||||
targetLogPrefixStr := "Received UpdateAddHTLC("
|
||||
targetOutgoingAmountMsatStr := fmt.Sprintf(
|
||||
"amt=%d", newOutgoingAmountMsat,
|
||||
)
|
||||
|
||||
// Formulate custom records target log string.
|
||||
var asciiValues []string
|
||||
for _, b := range crValue {
|
||||
asciiValues = append(asciiValues, fmt.Sprintf("%d", b))
|
||||
}
|
||||
|
||||
targetCustomRecordsStr := fmt.Sprintf(
|
||||
"%d:[%s]", crKey, strings.Join(asciiValues, " "),
|
||||
)
|
||||
|
||||
// logEntryCheck is a helper function that checks if the log entry
|
||||
// contains the expected strings.
|
||||
logEntryCheck := func(logEntry string) bool {
|
||||
return strings.Contains(logEntry, targetLogPrefixStr) &&
|
||||
strings.Contains(logEntry, targetCustomRecordsStr) &&
|
||||
strings.Contains(logEntry, targetOutgoingAmountMsatStr)
|
||||
}
|
||||
|
||||
// Wait for the log entry to appear in Carol's log.
|
||||
require.Eventually(ht, func() bool {
|
||||
ctx := context.Background()
|
||||
dbgInfo, err := carol.RPC.LN.GetDebugInfo(
|
||||
ctx, &lnrpc.GetDebugInfoRequest{},
|
||||
)
|
||||
require.NoError(ht, err, "failed to get Carol node debug info")
|
||||
|
||||
for _, logEntry := range dbgInfo.Log {
|
||||
if logEntryCheck(logEntry) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}, defaultTimeout, time.Second)
|
||||
|
||||
// Cancel the context, which will disconnect Bob's interceptor.
|
||||
cancelBobInterceptor()
|
||||
|
||||
// Make sure all goroutines are finished.
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(defaultTimeout):
|
||||
require.Fail(ht, "timeout waiting for sending payment")
|
||||
}
|
||||
|
||||
// Assert that the payment was successful.
|
||||
var preimage lntypes.Preimage
|
||||
copy(preimage[:], invoice.RPreimage)
|
||||
ht.AssertPaymentStatus(alice, preimage, lnrpc.Payment_SUCCEEDED)
|
||||
|
||||
// Finally, close channels.
|
||||
ht.CloseChannel(alice, cpAB)
|
||||
ht.CloseChannel(bob, cpBC)
|
||||
}
|
||||
|
||||
// interceptorTestScenario is a helper struct to hold the test context and
|
||||
// provide the needed functionality.
|
||||
type interceptorTestScenario struct {
|
||||
|
@ -4,10 +4,12 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/record"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@ -22,7 +24,7 @@ var (
|
||||
ErrMissingPreimage = errors.New("missing preimage")
|
||||
)
|
||||
|
||||
// forwardInterceptor is a helper struct that handles the lifecycle of an rpc
|
||||
// forwardInterceptor is a helper struct that handles the lifecycle of an RPC
|
||||
// interceptor streaming session.
|
||||
// It is created when the stream opens and disconnects when the stream closes.
|
||||
type forwardInterceptor struct {
|
||||
@ -43,7 +45,7 @@ func newForwardInterceptor(htlcSwitch htlcswitch.InterceptableHtlcForwarder,
|
||||
}
|
||||
|
||||
// run sends the intercepted packets to the client and receives the
|
||||
// corersponding responses. On one hand it registered itself as an interceptor
|
||||
// corresponding responses. On one hand it registered itself as an interceptor
|
||||
// that receives the switch packets and on the other hand launches a go routine
|
||||
// to read from the client stream.
|
||||
// To coordinate all this and make sure it is safe for concurrent access all
|
||||
@ -119,6 +121,45 @@ func (r *forwardInterceptor) resolveFromClient(
|
||||
Action: htlcswitch.FwdActionResume,
|
||||
})
|
||||
|
||||
case ResolveHoldForwardAction_RESUME_MODIFIED:
|
||||
// Modify HTLC and resume forward.
|
||||
incomingAmtMsat := fn.None[lnwire.MilliSatoshi]()
|
||||
if in.IncomingAmountMsat > 0 {
|
||||
incomingAmtMsat = fn.Some[lnwire.MilliSatoshi](
|
||||
lnwire.MilliSatoshi(in.IncomingAmountMsat),
|
||||
)
|
||||
}
|
||||
|
||||
outgoingAmtMsat := fn.None[lnwire.MilliSatoshi]()
|
||||
if in.OutgoingAmountMsat > 0 {
|
||||
outgoingAmtMsat = fn.Some[lnwire.MilliSatoshi](
|
||||
lnwire.MilliSatoshi(in.OutgoingAmountMsat),
|
||||
)
|
||||
}
|
||||
|
||||
customRecords := fn.None[record.CustomSet]()
|
||||
if len(in.CustomRecords) > 0 {
|
||||
// Validate custom records.
|
||||
cr := record.CustomSet(in.CustomRecords)
|
||||
if err := cr.Validate(); err != nil {
|
||||
return status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
"failed to validate custom records: %v",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
customRecords = fn.Some[record.CustomSet](cr)
|
||||
}
|
||||
|
||||
return r.htlcSwitch.Resolve(&htlcswitch.FwdResolution{
|
||||
Key: circuitKey,
|
||||
Action: htlcswitch.FwdActionResumeModified,
|
||||
IncomingAmountMsat: incomingAmtMsat,
|
||||
OutgoingAmountMsat: outgoingAmtMsat,
|
||||
CustomRecords: customRecords,
|
||||
})
|
||||
|
||||
case ResolveHoldForwardAction_FAIL:
|
||||
// Fail with an encrypted reason.
|
||||
if in.FailureMessage != nil {
|
||||
|
@ -206,6 +206,9 @@ const (
|
||||
ResolveHoldForwardAction_SETTLE ResolveHoldForwardAction = 0
|
||||
ResolveHoldForwardAction_FAIL ResolveHoldForwardAction = 1
|
||||
ResolveHoldForwardAction_RESUME ResolveHoldForwardAction = 2
|
||||
// RESUME_MODIFIED is an action that is used to resume a hold forward HTLC
|
||||
// with modifications specified during interception.
|
||||
ResolveHoldForwardAction_RESUME_MODIFIED ResolveHoldForwardAction = 3
|
||||
)
|
||||
|
||||
// Enum value maps for ResolveHoldForwardAction.
|
||||
@ -214,11 +217,13 @@ var (
|
||||
0: "SETTLE",
|
||||
1: "FAIL",
|
||||
2: "RESUME",
|
||||
3: "RESUME_MODIFIED",
|
||||
}
|
||||
ResolveHoldForwardAction_value = map[string]int32{
|
||||
"SETTLE": 0,
|
||||
"FAIL": 1,
|
||||
"RESUME": 2,
|
||||
"SETTLE": 0,
|
||||
"FAIL": 1,
|
||||
"RESUME": 2,
|
||||
"RESUME_MODIFIED": 3,
|
||||
}
|
||||
)
|
||||
|
||||
@ -3143,6 +3148,8 @@ func (x *ForwardHtlcInterceptRequest) GetAutoFailHeight() int32 {
|
||||
// ForwardHtlcInterceptResponse enables the caller to resolve a previously hold
|
||||
// forward. The caller can choose either to:
|
||||
// - `Resume`: Execute the default behavior (usually forward).
|
||||
// - `ResumeModified`: Execute the default behavior (usually forward) with HTLC
|
||||
// field modifications.
|
||||
// - `Reject`: Fail the htlc backwards.
|
||||
// - `Settle`: Settle this htlc with a given preimage.
|
||||
type ForwardHtlcInterceptResponse struct {
|
||||
@ -3171,6 +3178,15 @@ type ForwardHtlcInterceptResponse struct {
|
||||
// For backwards-compatibility reasons, TEMPORARY_CHANNEL_FAILURE is the
|
||||
// default value for this field.
|
||||
FailureCode lnrpc.Failure_FailureCode `protobuf:"varint,5,opt,name=failure_code,json=failureCode,proto3,enum=lnrpc.Failure_FailureCode" json:"failure_code,omitempty"`
|
||||
// incoming_amount_msat is used to set the p2p message incoming amount field
|
||||
// for validating an incoming HTLC.
|
||||
IncomingAmountMsat uint64 `protobuf:"varint,6,opt,name=incoming_amount_msat,json=incomingAmountMsat,proto3" json:"incoming_amount_msat,omitempty"`
|
||||
// outgoing_amount_msat is used to set the p2p message outgoing amount field
|
||||
// for resuming a HTLC.
|
||||
OutgoingAmountMsat uint64 `protobuf:"varint,7,opt,name=outgoing_amount_msat,json=outgoingAmountMsat,proto3" json:"outgoing_amount_msat,omitempty"`
|
||||
// custom_records is used to set the p2p message custom records field for
|
||||
// resuming a HTLC.
|
||||
CustomRecords map[uint64][]byte `protobuf:"bytes,8,rep,name=custom_records,json=customRecords,proto3" json:"custom_records,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (x *ForwardHtlcInterceptResponse) Reset() {
|
||||
@ -3240,6 +3256,27 @@ func (x *ForwardHtlcInterceptResponse) GetFailureCode() lnrpc.Failure_FailureCod
|
||||
return lnrpc.Failure_FailureCode(0)
|
||||
}
|
||||
|
||||
func (x *ForwardHtlcInterceptResponse) GetIncomingAmountMsat() uint64 {
|
||||
if x != nil {
|
||||
return x.IncomingAmountMsat
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ForwardHtlcInterceptResponse) GetOutgoingAmountMsat() uint64 {
|
||||
if x != nil {
|
||||
return x.OutgoingAmountMsat
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ForwardHtlcInterceptResponse) GetCustomRecords() map[uint64][]byte {
|
||||
if x != nil {
|
||||
return x.CustomRecords
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateChanStatusRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -3727,7 +3764,7 @@ var file_routerrpc_router_proto_rawDesc = []byte{
|
||||
0x6f, 0x72, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa8, 0x02, 0x0a, 0x1c, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72,
|
||||
0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb1, 0x04, 0x0a, 0x1c, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72,
|
||||
0x64, 0x48, 0x74, 0x6c, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x14, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69,
|
||||
0x6e, 0x67, 0x5f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01,
|
||||
@ -3746,170 +3783,188 @@ var file_routerrpc_router_proto_rawDesc = []byte{
|
||||
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x43,
|
||||
0x6f, 0x64, 0x65, 0x52, 0x0b, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65,
|
||||
0x22, 0x82, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0a,
|
||||
0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
||||
0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x12, 0x33, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
|
||||
0x32, 0x1b, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61,
|
||||
0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43,
|
||||
0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x2a, 0x81, 0x04, 0x0a, 0x0d, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x44, 0x65, 0x74,
|
||||
0x61, 0x69, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00,
|
||||
0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x10, 0x01, 0x12,
|
||||
0x10, 0x0a, 0x0c, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x43, 0x4f, 0x44, 0x45, 0x10,
|
||||
0x02, 0x12, 0x15, 0x0a, 0x11, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x4c,
|
||||
0x49, 0x47, 0x49, 0x42, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x4e, 0x5f, 0x43,
|
||||
0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x14,
|
||||
0x0a, 0x10, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, 0x44, 0x53, 0x5f, 0x4d,
|
||||
0x41, 0x58, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43,
|
||||
0x49, 0x45, 0x4e, 0x54, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x06, 0x12, 0x16,
|
||||
0x0a, 0x12, 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x46, 0x4f, 0x52,
|
||||
0x57, 0x41, 0x52, 0x44, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x41,
|
||||
0x44, 0x44, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x08, 0x12, 0x15, 0x0a, 0x11, 0x46,
|
||||
0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x53, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44,
|
||||
0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f, 0x43, 0x41,
|
||||
0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, 0x56, 0x4f,
|
||||
0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x52, 0x50, 0x41, 0x49, 0x44, 0x10, 0x0b, 0x12,
|
||||
0x1b, 0x0a, 0x17, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52,
|
||||
0x59, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x0c, 0x12, 0x14, 0x0a, 0x10,
|
||||
0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x45, 0x4e,
|
||||
0x10, 0x0d, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x50, 0x50, 0x5f, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43,
|
||||
0x45, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x0e, 0x12, 0x14, 0x0a, 0x10, 0x41,
|
||||
0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x4d, 0x49, 0x53, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x10,
|
||||
0x0f, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x45, 0x54, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x5f, 0x4d,
|
||||
0x49, 0x53, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x10, 0x10, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x45, 0x54,
|
||||
0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x4f, 0x57, 0x10, 0x11,
|
||||
0x12, 0x10, 0x0a, 0x0c, 0x53, 0x45, 0x54, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x50, 0x41, 0x49, 0x44,
|
||||
0x10, 0x12, 0x12, 0x13, 0x0a, 0x0f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x49, 0x4e,
|
||||
0x56, 0x4f, 0x49, 0x43, 0x45, 0x10, 0x13, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x41, 0x4c,
|
||||
0x49, 0x44, 0x5f, 0x4b, 0x45, 0x59, 0x53, 0x45, 0x4e, 0x44, 0x10, 0x14, 0x12, 0x13, 0x0a, 0x0f,
|
||||
0x4d, 0x50, 0x50, 0x5f, 0x49, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10,
|
||||
0x15, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x49, 0x52, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x5f, 0x52, 0x4f,
|
||||
0x55, 0x54, 0x45, 0x10, 0x16, 0x2a, 0xae, 0x01, 0x0a, 0x0c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x49, 0x4e, 0x5f, 0x46, 0x4c, 0x49,
|
||||
0x47, 0x48, 0x54, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44,
|
||||
0x45, 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x54,
|
||||
0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x41, 0x49, 0x4c,
|
||||
0x45, 0x44, 0x5f, 0x4e, 0x4f, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x10, 0x03, 0x12, 0x10, 0x0a,
|
||||
0x0c, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12,
|
||||
0x24, 0x0a, 0x20, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52,
|
||||
0x45, 0x43, 0x54, 0x5f, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41,
|
||||
0x49, 0x4c, 0x53, 0x10, 0x05, 0x12, 0x1f, 0x0a, 0x1b, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f,
|
||||
0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x42, 0x41, 0x4c,
|
||||
0x41, 0x4e, 0x43, 0x45, 0x10, 0x06, 0x2a, 0x3c, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76,
|
||||
0x65, 0x48, 0x6f, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x41, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x08,
|
||||
0x0a, 0x04, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x53, 0x55,
|
||||
0x4d, 0x45, 0x10, 0x02, 0x2a, 0x35, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x4e, 0x41, 0x42,
|
||||
0x4c, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x10,
|
||||
0x01, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x02, 0x32, 0xb5, 0x0c, 0x0a, 0x06,
|
||||
0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61,
|
||||
0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x32, 0x12, 0x1d, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50,
|
||||
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x63,
|
||||
0x6b, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x32, 0x12, 0x1e, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50, 0x61, 0x79, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0d,
|
||||
0x54, 0x72, 0x61, 0x63, 0x6b, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50,
|
||||
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e,
|
||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x30, 0x01,
|
||||
0x12, 0x4b, 0x0a, 0x10, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x46, 0x65, 0x65, 0x12, 0x1a, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x1b, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a,
|
||||
0x0b, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01,
|
||||
0x12, 0x42, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x56,
|
||||
0x32, 0x12, 0x1d, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65,
|
||||
0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x54, 0x4c, 0x43, 0x41, 0x74, 0x74,
|
||||
0x65, 0x6d, 0x70, 0x74, 0x12, 0x64, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x65, 0x74, 0x4d, 0x69, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x25, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x4d, 0x69, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x52,
|
||||
0x65, 0x73, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x13, 0x51, 0x75,
|
||||
0x65, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x12, 0x25, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75,
|
||||
0x65, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x6a, 0x0a, 0x15, 0x58, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x27, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x58, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x69, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x28, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x58,
|
||||
0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x17,
|
||||
0x47, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x47,
|
||||
0x12, 0x30, 0x0a, 0x14, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6d, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12,
|
||||
0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x73,
|
||||
0x61, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x61,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x12, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x4d, 0x73, 0x61, 0x74, 0x12, 0x61, 0x0a, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x72,
|
||||
0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64,
|
||||
0x48, 0x74, 0x6c, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x63, 0x6f,
|
||||
0x72, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
|
||||
0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x43, 0x75, 0x73, 0x74, 0x6f,
|
||||
0x6d, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x82, 0x01, 0x0a, 0x17, 0x55, 0x70,
|
||||
0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09,
|
||||
0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x33, 0x0a, 0x06, 0x61, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1a,
|
||||
0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x81, 0x04, 0x0a, 0x0d, 0x46,
|
||||
0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x0b, 0x0a, 0x07,
|
||||
0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f,
|
||||
0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x4e, 0x49, 0x4f,
|
||||
0x4e, 0x5f, 0x44, 0x45, 0x43, 0x4f, 0x44, 0x45, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4c, 0x49,
|
||||
0x4e, 0x4b, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x4c, 0x49, 0x47, 0x49, 0x42, 0x4c, 0x45, 0x10,
|
||||
0x03, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x4e, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x49,
|
||||
0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x14, 0x0a, 0x10, 0x48, 0x54, 0x4c, 0x43, 0x5f,
|
||||
0x45, 0x58, 0x43, 0x45, 0x45, 0x44, 0x53, 0x5f, 0x4d, 0x41, 0x58, 0x10, 0x05, 0x12, 0x18, 0x0a,
|
||||
0x14, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x42, 0x41,
|
||||
0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x43, 0x4f, 0x4d,
|
||||
0x50, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x10, 0x07, 0x12,
|
||||
0x13, 0x0a, 0x0f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x41, 0x44, 0x44, 0x5f, 0x46, 0x41, 0x49, 0x4c,
|
||||
0x45, 0x44, 0x10, 0x08, 0x12, 0x15, 0x0a, 0x11, 0x46, 0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x53,
|
||||
0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x49,
|
||||
0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10,
|
||||
0x0a, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x44,
|
||||
0x45, 0x52, 0x50, 0x41, 0x49, 0x44, 0x10, 0x0b, 0x12, 0x1b, 0x0a, 0x17, 0x49, 0x4e, 0x56, 0x4f,
|
||||
0x49, 0x43, 0x45, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x53,
|
||||
0x4f, 0x4f, 0x4e, 0x10, 0x0c, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45,
|
||||
0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x10, 0x0d, 0x12, 0x17, 0x0a, 0x13, 0x4d,
|
||||
0x50, 0x50, 0x5f, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f,
|
||||
0x55, 0x54, 0x10, 0x0e, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f,
|
||||
0x4d, 0x49, 0x53, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x10, 0x0f, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x45,
|
||||
0x54, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x5f, 0x4d, 0x49, 0x53, 0x4d, 0x41, 0x54, 0x43, 0x48,
|
||||
0x10, 0x10, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x45, 0x54, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x5f,
|
||||
0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x4f, 0x57, 0x10, 0x11, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x45, 0x54,
|
||||
0x5f, 0x4f, 0x56, 0x45, 0x52, 0x50, 0x41, 0x49, 0x44, 0x10, 0x12, 0x12, 0x13, 0x0a, 0x0f, 0x55,
|
||||
0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x10, 0x13,
|
||||
0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4b, 0x45, 0x59, 0x53,
|
||||
0x45, 0x4e, 0x44, 0x10, 0x14, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x50, 0x50, 0x5f, 0x49, 0x4e, 0x5f,
|
||||
0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x15, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x49,
|
||||
0x52, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x10, 0x16, 0x2a, 0xae,
|
||||
0x01, 0x0a, 0x0c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
|
||||
0x0d, 0x0a, 0x09, 0x49, 0x4e, 0x5f, 0x46, 0x4c, 0x49, 0x47, 0x48, 0x54, 0x10, 0x00, 0x12, 0x0d,
|
||||
0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a,
|
||||
0x0e, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10,
|
||||
0x02, 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x4e, 0x4f, 0x5f, 0x52,
|
||||
0x4f, 0x55, 0x54, 0x45, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44,
|
||||
0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, 0x24, 0x0a, 0x20, 0x46, 0x41, 0x49, 0x4c,
|
||||
0x45, 0x44, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x41, 0x59,
|
||||
0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x05, 0x12, 0x1f,
|
||||
0x0a, 0x1b, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49,
|
||||
0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x06, 0x2a,
|
||||
0x51, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x48, 0x6f, 0x6c, 0x64, 0x46, 0x6f,
|
||||
0x72, 0x77, 0x61, 0x72, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x53,
|
||||
0x45, 0x54, 0x54, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x41, 0x49, 0x4c, 0x10,
|
||||
0x01, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x13, 0x0a,
|
||||
0x0f, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44,
|
||||
0x10, 0x03, 0x2a, 0x35, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45,
|
||||
0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12,
|
||||
0x08, 0x0a, 0x04, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x02, 0x32, 0xb5, 0x0c, 0x0a, 0x06, 0x52, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x56, 0x32, 0x12, 0x1d, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50,
|
||||
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x32, 0x12, 0x1e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0d, 0x54, 0x72,
|
||||
0x61, 0x63, 0x6b, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50, 0x61, 0x79,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x6c,
|
||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x4b,
|
||||
0x0a, 0x10, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46,
|
||||
0x65, 0x65, 0x12, 0x1a, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x52,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0b, 0x53,
|
||||
0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x42,
|
||||
0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x56, 0x32, 0x12,
|
||||
0x1d, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64,
|
||||
0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12,
|
||||
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x54, 0x4c, 0x43, 0x41, 0x74, 0x74, 0x65, 0x6d,
|
||||
0x70, 0x74, 0x12, 0x64, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x25, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x26, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73,
|
||||
0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70,
|
||||
0x0a, 0x17, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x5b, 0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69,
|
||||
0x6c, 0x69, 0x74, 0x79, 0x12, 0x22, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74,
|
||||
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x61, 0x62,
|
||||
0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a,
|
||||
0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72,
|
||||
0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12,
|
||||
0x25, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72,
|
||||
0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a,
|
||||
0x0a, 0x15, 0x58, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x27, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x58, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x28, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x58, 0x49, 0x6d,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x17, 0x47, 0x65,
|
||||
0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x2a, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
|
||||
0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x17,
|
||||
0x53, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53,
|
||||
0x65, 0x74, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b,
|
||||
0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c, 0x69,
|
||||
0x74, 0x79, 0x12, 0x22, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x51,
|
||||
0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c,
|
||||
0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x42,
|
||||
0x75, 0x69, 0x6c, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x73,
|
||||
0x63, 0x72, 0x69, 0x62, 0x65, 0x48, 0x74, 0x6c, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12,
|
||||
0x25, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73,
|
||||
0x63, 0x72, 0x69, 0x62, 0x65, 0x48, 0x74, 0x6c, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x48, 0x74, 0x6c, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x4d,
|
||||
0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61,
|
||||
0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x03, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x4f, 0x0a,
|
||||
0x0c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50,
|
||||
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x03, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x66,
|
||||
0x0a, 0x0f, 0x48, 0x74, 0x6c, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f,
|
||||
0x72, 0x12, 0x27, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f,
|
||||
0x72, 0x77, 0x61, 0x72, 0x64, 0x48, 0x74, 0x6c, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65,
|
||||
0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x26, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x48, 0x74,
|
||||
0x6c, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x43, 0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x22, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61,
|
||||
0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x43, 0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x42, 0x31, 0x5a, 0x2f, 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, 0x2f, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
|
||||
0x69, 0x62, 0x65, 0x48, 0x74, 0x6c, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x25, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
|
||||
0x69, 0x62, 0x65, 0x48, 0x74, 0x6c, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x48, 0x74, 0x6c, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0b,
|
||||
0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74,
|
||||
0x61, 0x74, 0x75, 0x73, 0x22, 0x03, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x4f, 0x0a, 0x0c, 0x54,
|
||||
0x72, 0x61, 0x63, 0x6b, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50, 0x61, 0x79,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x03, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x66, 0x0a, 0x0f,
|
||||
0x48, 0x74, 0x6c, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12,
|
||||
0x27, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77,
|
||||
0x61, 0x72, 0x64, 0x48, 0x74, 0x6c, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x26, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x48, 0x74, 0x6c, 0x63,
|
||||
0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x28, 0x01, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68,
|
||||
0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x22, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43,
|
||||
0x68, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x42, 0x31, 0x5a, 0x2f, 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, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -3925,7 +3980,7 @@ func file_routerrpc_router_proto_rawDescGZIP() []byte {
|
||||
}
|
||||
|
||||
var file_routerrpc_router_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
|
||||
var file_routerrpc_router_proto_msgTypes = make([]protoimpl.MessageInfo, 43)
|
||||
var file_routerrpc_router_proto_msgTypes = make([]protoimpl.MessageInfo, 44)
|
||||
var file_routerrpc_router_proto_goTypes = []interface{}{
|
||||
(FailureDetail)(0), // 0: routerrpc.FailureDetail
|
||||
(PaymentState)(0), // 1: routerrpc.PaymentState
|
||||
@ -3976,23 +4031,24 @@ var file_routerrpc_router_proto_goTypes = []interface{}{
|
||||
(*UpdateChanStatusResponse)(nil), // 46: routerrpc.UpdateChanStatusResponse
|
||||
nil, // 47: routerrpc.SendPaymentRequest.DestCustomRecordsEntry
|
||||
nil, // 48: routerrpc.ForwardHtlcInterceptRequest.CustomRecordsEntry
|
||||
(*lnrpc.RouteHint)(nil), // 49: lnrpc.RouteHint
|
||||
(lnrpc.FeatureBit)(0), // 50: lnrpc.FeatureBit
|
||||
(lnrpc.PaymentFailureReason)(0), // 51: lnrpc.PaymentFailureReason
|
||||
(*lnrpc.Route)(nil), // 52: lnrpc.Route
|
||||
(*lnrpc.Failure)(nil), // 53: lnrpc.Failure
|
||||
(lnrpc.Failure_FailureCode)(0), // 54: lnrpc.Failure.FailureCode
|
||||
(*lnrpc.HTLCAttempt)(nil), // 55: lnrpc.HTLCAttempt
|
||||
(*lnrpc.ChannelPoint)(nil), // 56: lnrpc.ChannelPoint
|
||||
(*lnrpc.Payment)(nil), // 57: lnrpc.Payment
|
||||
nil, // 49: routerrpc.ForwardHtlcInterceptResponse.CustomRecordsEntry
|
||||
(*lnrpc.RouteHint)(nil), // 50: lnrpc.RouteHint
|
||||
(lnrpc.FeatureBit)(0), // 51: lnrpc.FeatureBit
|
||||
(lnrpc.PaymentFailureReason)(0), // 52: lnrpc.PaymentFailureReason
|
||||
(*lnrpc.Route)(nil), // 53: lnrpc.Route
|
||||
(*lnrpc.Failure)(nil), // 54: lnrpc.Failure
|
||||
(lnrpc.Failure_FailureCode)(0), // 55: lnrpc.Failure.FailureCode
|
||||
(*lnrpc.HTLCAttempt)(nil), // 56: lnrpc.HTLCAttempt
|
||||
(*lnrpc.ChannelPoint)(nil), // 57: lnrpc.ChannelPoint
|
||||
(*lnrpc.Payment)(nil), // 58: lnrpc.Payment
|
||||
}
|
||||
var file_routerrpc_router_proto_depIdxs = []int32{
|
||||
49, // 0: routerrpc.SendPaymentRequest.route_hints:type_name -> lnrpc.RouteHint
|
||||
50, // 0: routerrpc.SendPaymentRequest.route_hints:type_name -> lnrpc.RouteHint
|
||||
47, // 1: routerrpc.SendPaymentRequest.dest_custom_records:type_name -> routerrpc.SendPaymentRequest.DestCustomRecordsEntry
|
||||
50, // 2: routerrpc.SendPaymentRequest.dest_features:type_name -> lnrpc.FeatureBit
|
||||
51, // 3: routerrpc.RouteFeeResponse.failure_reason:type_name -> lnrpc.PaymentFailureReason
|
||||
52, // 4: routerrpc.SendToRouteRequest.route:type_name -> lnrpc.Route
|
||||
53, // 5: routerrpc.SendToRouteResponse.failure:type_name -> lnrpc.Failure
|
||||
51, // 2: routerrpc.SendPaymentRequest.dest_features:type_name -> lnrpc.FeatureBit
|
||||
52, // 3: routerrpc.RouteFeeResponse.failure_reason:type_name -> lnrpc.PaymentFailureReason
|
||||
53, // 4: routerrpc.SendToRouteRequest.route:type_name -> lnrpc.Route
|
||||
54, // 5: routerrpc.SendToRouteResponse.failure:type_name -> lnrpc.Failure
|
||||
19, // 6: routerrpc.QueryMissionControlResponse.pairs:type_name -> routerrpc.PairHistory
|
||||
19, // 7: routerrpc.XImportMissionControlRequest.pairs:type_name -> routerrpc.PairHistory
|
||||
20, // 8: routerrpc.PairHistory.history:type_name -> routerrpc.PairData
|
||||
@ -4002,7 +4058,7 @@ var file_routerrpc_router_proto_depIdxs = []int32{
|
||||
27, // 12: routerrpc.MissionControlConfig.apriori:type_name -> routerrpc.AprioriParameters
|
||||
26, // 13: routerrpc.MissionControlConfig.bimodal:type_name -> routerrpc.BimodalParameters
|
||||
20, // 14: routerrpc.QueryProbabilityResponse.history:type_name -> routerrpc.PairData
|
||||
52, // 15: routerrpc.BuildRouteResponse.route:type_name -> lnrpc.Route
|
||||
53, // 15: routerrpc.BuildRouteResponse.route:type_name -> lnrpc.Route
|
||||
5, // 16: routerrpc.HtlcEvent.event_type:type_name -> routerrpc.HtlcEvent.EventType
|
||||
35, // 17: routerrpc.HtlcEvent.forward_event:type_name -> routerrpc.ForwardEvent
|
||||
36, // 18: routerrpc.HtlcEvent.forward_fail_event:type_name -> routerrpc.ForwardFailEvent
|
||||
@ -4012,58 +4068,59 @@ var file_routerrpc_router_proto_depIdxs = []int32{
|
||||
38, // 22: routerrpc.HtlcEvent.final_htlc_event:type_name -> routerrpc.FinalHtlcEvent
|
||||
34, // 23: routerrpc.ForwardEvent.info:type_name -> routerrpc.HtlcInfo
|
||||
34, // 24: routerrpc.LinkFailEvent.info:type_name -> routerrpc.HtlcInfo
|
||||
54, // 25: routerrpc.LinkFailEvent.wire_failure:type_name -> lnrpc.Failure.FailureCode
|
||||
55, // 25: routerrpc.LinkFailEvent.wire_failure:type_name -> lnrpc.Failure.FailureCode
|
||||
0, // 26: routerrpc.LinkFailEvent.failure_detail:type_name -> routerrpc.FailureDetail
|
||||
1, // 27: routerrpc.PaymentStatus.state:type_name -> routerrpc.PaymentState
|
||||
55, // 28: routerrpc.PaymentStatus.htlcs:type_name -> lnrpc.HTLCAttempt
|
||||
56, // 28: routerrpc.PaymentStatus.htlcs:type_name -> lnrpc.HTLCAttempt
|
||||
42, // 29: routerrpc.ForwardHtlcInterceptRequest.incoming_circuit_key:type_name -> routerrpc.CircuitKey
|
||||
48, // 30: routerrpc.ForwardHtlcInterceptRequest.custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.CustomRecordsEntry
|
||||
42, // 31: routerrpc.ForwardHtlcInterceptResponse.incoming_circuit_key:type_name -> routerrpc.CircuitKey
|
||||
2, // 32: routerrpc.ForwardHtlcInterceptResponse.action:type_name -> routerrpc.ResolveHoldForwardAction
|
||||
54, // 33: routerrpc.ForwardHtlcInterceptResponse.failure_code:type_name -> lnrpc.Failure.FailureCode
|
||||
56, // 34: routerrpc.UpdateChanStatusRequest.chan_point:type_name -> lnrpc.ChannelPoint
|
||||
3, // 35: routerrpc.UpdateChanStatusRequest.action:type_name -> routerrpc.ChanStatusAction
|
||||
6, // 36: routerrpc.Router.SendPaymentV2:input_type -> routerrpc.SendPaymentRequest
|
||||
7, // 37: routerrpc.Router.TrackPaymentV2:input_type -> routerrpc.TrackPaymentRequest
|
||||
8, // 38: routerrpc.Router.TrackPayments:input_type -> routerrpc.TrackPaymentsRequest
|
||||
9, // 39: routerrpc.Router.EstimateRouteFee:input_type -> routerrpc.RouteFeeRequest
|
||||
11, // 40: routerrpc.Router.SendToRoute:input_type -> routerrpc.SendToRouteRequest
|
||||
11, // 41: routerrpc.Router.SendToRouteV2:input_type -> routerrpc.SendToRouteRequest
|
||||
13, // 42: routerrpc.Router.ResetMissionControl:input_type -> routerrpc.ResetMissionControlRequest
|
||||
15, // 43: routerrpc.Router.QueryMissionControl:input_type -> routerrpc.QueryMissionControlRequest
|
||||
17, // 44: routerrpc.Router.XImportMissionControl:input_type -> routerrpc.XImportMissionControlRequest
|
||||
21, // 45: routerrpc.Router.GetMissionControlConfig:input_type -> routerrpc.GetMissionControlConfigRequest
|
||||
23, // 46: routerrpc.Router.SetMissionControlConfig:input_type -> routerrpc.SetMissionControlConfigRequest
|
||||
28, // 47: routerrpc.Router.QueryProbability:input_type -> routerrpc.QueryProbabilityRequest
|
||||
30, // 48: routerrpc.Router.BuildRoute:input_type -> routerrpc.BuildRouteRequest
|
||||
32, // 49: routerrpc.Router.SubscribeHtlcEvents:input_type -> routerrpc.SubscribeHtlcEventsRequest
|
||||
6, // 50: routerrpc.Router.SendPayment:input_type -> routerrpc.SendPaymentRequest
|
||||
7, // 51: routerrpc.Router.TrackPayment:input_type -> routerrpc.TrackPaymentRequest
|
||||
44, // 52: routerrpc.Router.HtlcInterceptor:input_type -> routerrpc.ForwardHtlcInterceptResponse
|
||||
45, // 53: routerrpc.Router.UpdateChanStatus:input_type -> routerrpc.UpdateChanStatusRequest
|
||||
57, // 54: routerrpc.Router.SendPaymentV2:output_type -> lnrpc.Payment
|
||||
57, // 55: routerrpc.Router.TrackPaymentV2:output_type -> lnrpc.Payment
|
||||
57, // 56: routerrpc.Router.TrackPayments:output_type -> lnrpc.Payment
|
||||
10, // 57: routerrpc.Router.EstimateRouteFee:output_type -> routerrpc.RouteFeeResponse
|
||||
12, // 58: routerrpc.Router.SendToRoute:output_type -> routerrpc.SendToRouteResponse
|
||||
55, // 59: routerrpc.Router.SendToRouteV2:output_type -> lnrpc.HTLCAttempt
|
||||
14, // 60: routerrpc.Router.ResetMissionControl:output_type -> routerrpc.ResetMissionControlResponse
|
||||
16, // 61: routerrpc.Router.QueryMissionControl:output_type -> routerrpc.QueryMissionControlResponse
|
||||
18, // 62: routerrpc.Router.XImportMissionControl:output_type -> routerrpc.XImportMissionControlResponse
|
||||
22, // 63: routerrpc.Router.GetMissionControlConfig:output_type -> routerrpc.GetMissionControlConfigResponse
|
||||
24, // 64: routerrpc.Router.SetMissionControlConfig:output_type -> routerrpc.SetMissionControlConfigResponse
|
||||
29, // 65: routerrpc.Router.QueryProbability:output_type -> routerrpc.QueryProbabilityResponse
|
||||
31, // 66: routerrpc.Router.BuildRoute:output_type -> routerrpc.BuildRouteResponse
|
||||
33, // 67: routerrpc.Router.SubscribeHtlcEvents:output_type -> routerrpc.HtlcEvent
|
||||
41, // 68: routerrpc.Router.SendPayment:output_type -> routerrpc.PaymentStatus
|
||||
41, // 69: routerrpc.Router.TrackPayment:output_type -> routerrpc.PaymentStatus
|
||||
43, // 70: routerrpc.Router.HtlcInterceptor:output_type -> routerrpc.ForwardHtlcInterceptRequest
|
||||
46, // 71: routerrpc.Router.UpdateChanStatus:output_type -> routerrpc.UpdateChanStatusResponse
|
||||
54, // [54:72] is the sub-list for method output_type
|
||||
36, // [36:54] is the sub-list for method input_type
|
||||
36, // [36:36] is the sub-list for extension type_name
|
||||
36, // [36:36] is the sub-list for extension extendee
|
||||
0, // [0:36] is the sub-list for field type_name
|
||||
55, // 33: routerrpc.ForwardHtlcInterceptResponse.failure_code:type_name -> lnrpc.Failure.FailureCode
|
||||
49, // 34: routerrpc.ForwardHtlcInterceptResponse.custom_records:type_name -> routerrpc.ForwardHtlcInterceptResponse.CustomRecordsEntry
|
||||
57, // 35: routerrpc.UpdateChanStatusRequest.chan_point:type_name -> lnrpc.ChannelPoint
|
||||
3, // 36: routerrpc.UpdateChanStatusRequest.action:type_name -> routerrpc.ChanStatusAction
|
||||
6, // 37: routerrpc.Router.SendPaymentV2:input_type -> routerrpc.SendPaymentRequest
|
||||
7, // 38: routerrpc.Router.TrackPaymentV2:input_type -> routerrpc.TrackPaymentRequest
|
||||
8, // 39: routerrpc.Router.TrackPayments:input_type -> routerrpc.TrackPaymentsRequest
|
||||
9, // 40: routerrpc.Router.EstimateRouteFee:input_type -> routerrpc.RouteFeeRequest
|
||||
11, // 41: routerrpc.Router.SendToRoute:input_type -> routerrpc.SendToRouteRequest
|
||||
11, // 42: routerrpc.Router.SendToRouteV2:input_type -> routerrpc.SendToRouteRequest
|
||||
13, // 43: routerrpc.Router.ResetMissionControl:input_type -> routerrpc.ResetMissionControlRequest
|
||||
15, // 44: routerrpc.Router.QueryMissionControl:input_type -> routerrpc.QueryMissionControlRequest
|
||||
17, // 45: routerrpc.Router.XImportMissionControl:input_type -> routerrpc.XImportMissionControlRequest
|
||||
21, // 46: routerrpc.Router.GetMissionControlConfig:input_type -> routerrpc.GetMissionControlConfigRequest
|
||||
23, // 47: routerrpc.Router.SetMissionControlConfig:input_type -> routerrpc.SetMissionControlConfigRequest
|
||||
28, // 48: routerrpc.Router.QueryProbability:input_type -> routerrpc.QueryProbabilityRequest
|
||||
30, // 49: routerrpc.Router.BuildRoute:input_type -> routerrpc.BuildRouteRequest
|
||||
32, // 50: routerrpc.Router.SubscribeHtlcEvents:input_type -> routerrpc.SubscribeHtlcEventsRequest
|
||||
6, // 51: routerrpc.Router.SendPayment:input_type -> routerrpc.SendPaymentRequest
|
||||
7, // 52: routerrpc.Router.TrackPayment:input_type -> routerrpc.TrackPaymentRequest
|
||||
44, // 53: routerrpc.Router.HtlcInterceptor:input_type -> routerrpc.ForwardHtlcInterceptResponse
|
||||
45, // 54: routerrpc.Router.UpdateChanStatus:input_type -> routerrpc.UpdateChanStatusRequest
|
||||
58, // 55: routerrpc.Router.SendPaymentV2:output_type -> lnrpc.Payment
|
||||
58, // 56: routerrpc.Router.TrackPaymentV2:output_type -> lnrpc.Payment
|
||||
58, // 57: routerrpc.Router.TrackPayments:output_type -> lnrpc.Payment
|
||||
10, // 58: routerrpc.Router.EstimateRouteFee:output_type -> routerrpc.RouteFeeResponse
|
||||
12, // 59: routerrpc.Router.SendToRoute:output_type -> routerrpc.SendToRouteResponse
|
||||
56, // 60: routerrpc.Router.SendToRouteV2:output_type -> lnrpc.HTLCAttempt
|
||||
14, // 61: routerrpc.Router.ResetMissionControl:output_type -> routerrpc.ResetMissionControlResponse
|
||||
16, // 62: routerrpc.Router.QueryMissionControl:output_type -> routerrpc.QueryMissionControlResponse
|
||||
18, // 63: routerrpc.Router.XImportMissionControl:output_type -> routerrpc.XImportMissionControlResponse
|
||||
22, // 64: routerrpc.Router.GetMissionControlConfig:output_type -> routerrpc.GetMissionControlConfigResponse
|
||||
24, // 65: routerrpc.Router.SetMissionControlConfig:output_type -> routerrpc.SetMissionControlConfigResponse
|
||||
29, // 66: routerrpc.Router.QueryProbability:output_type -> routerrpc.QueryProbabilityResponse
|
||||
31, // 67: routerrpc.Router.BuildRoute:output_type -> routerrpc.BuildRouteResponse
|
||||
33, // 68: routerrpc.Router.SubscribeHtlcEvents:output_type -> routerrpc.HtlcEvent
|
||||
41, // 69: routerrpc.Router.SendPayment:output_type -> routerrpc.PaymentStatus
|
||||
41, // 70: routerrpc.Router.TrackPayment:output_type -> routerrpc.PaymentStatus
|
||||
43, // 71: routerrpc.Router.HtlcInterceptor:output_type -> routerrpc.ForwardHtlcInterceptRequest
|
||||
46, // 72: routerrpc.Router.UpdateChanStatus:output_type -> routerrpc.UpdateChanStatusResponse
|
||||
55, // [55:73] is the sub-list for method output_type
|
||||
37, // [37:55] is the sub-list for method input_type
|
||||
37, // [37:37] is the sub-list for extension type_name
|
||||
37, // [37:37] is the sub-list for extension extendee
|
||||
0, // [0:37] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_routerrpc_router_proto_init() }
|
||||
@ -4583,7 +4640,7 @@ func file_routerrpc_router_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_routerrpc_router_proto_rawDesc,
|
||||
NumEnums: 6,
|
||||
NumMessages: 43,
|
||||
NumMessages: 44,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
@ -960,6 +960,8 @@ message ForwardHtlcInterceptRequest {
|
||||
ForwardHtlcInterceptResponse enables the caller to resolve a previously hold
|
||||
forward. The caller can choose either to:
|
||||
- `Resume`: Execute the default behavior (usually forward).
|
||||
- `ResumeModified`: Execute the default behavior (usually forward) with HTLC
|
||||
field modifications.
|
||||
- `Reject`: Fail the htlc backwards.
|
||||
- `Settle`: Settle this htlc with a given preimage.
|
||||
*/
|
||||
@ -990,12 +992,28 @@ message ForwardHtlcInterceptResponse {
|
||||
// For backwards-compatibility reasons, TEMPORARY_CHANNEL_FAILURE is the
|
||||
// default value for this field.
|
||||
lnrpc.Failure.FailureCode failure_code = 5;
|
||||
|
||||
// incoming_amount_msat is used to set the p2p message incoming amount field
|
||||
// for validating an incoming HTLC.
|
||||
uint64 incoming_amount_msat = 6;
|
||||
|
||||
// outgoing_amount_msat is used to set the p2p message outgoing amount field
|
||||
// for resuming a HTLC.
|
||||
uint64 outgoing_amount_msat = 7;
|
||||
|
||||
// custom_records is used to set the p2p message custom records field for
|
||||
// resuming a HTLC.
|
||||
map<uint64, bytes> custom_records = 8;
|
||||
}
|
||||
|
||||
enum ResolveHoldForwardAction {
|
||||
SETTLE = 0;
|
||||
FAIL = 1;
|
||||
RESUME = 2;
|
||||
|
||||
// RESUME_MODIFIED is an action that is used to resume a hold forward HTLC
|
||||
// with modifications specified during interception.
|
||||
RESUME_MODIFIED = 3;
|
||||
}
|
||||
|
||||
message UpdateChanStatusRequest {
|
||||
|
@ -1343,9 +1343,27 @@
|
||||
"failure_code": {
|
||||
"$ref": "#/definitions/FailureFailureCode",
|
||||
"description": "Return the specified failure code in case the resolve action is Fail. The\nmessage data fields are populated automatically.\n\nIf a non-zero failure_code is specified, failure_message must not be set.\n\nFor backwards-compatibility reasons, TEMPORARY_CHANNEL_FAILURE is the\ndefault value for this field."
|
||||
},
|
||||
"incoming_amount_msat": {
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "incoming_amount_msat is used to set the p2p message incoming amount field\nfor validating an incoming HTLC."
|
||||
},
|
||||
"outgoing_amount_msat": {
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "outgoing_amount_msat is used to set the p2p message outgoing amount field\nfor resuming a HTLC."
|
||||
},
|
||||
"custom_records": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
"description": "custom_records is used to set the p2p message custom records field for\nresuming a HTLC."
|
||||
}
|
||||
},
|
||||
"description": "*\nForwardHtlcInterceptResponse enables the caller to resolve a previously hold\nforward. The caller can choose either to:\n- `Resume`: Execute the default behavior (usually forward).\n- `Reject`: Fail the htlc backwards.\n- `Settle`: Settle this htlc with a given preimage."
|
||||
"description": "*\nForwardHtlcInterceptResponse enables the caller to resolve a previously hold\nforward. The caller can choose either to:\n- `Resume`: Execute the default behavior (usually forward).\n- `ResumeModified`: Execute the default behavior (usually forward) with HTLC\nfield modifications.\n- `Reject`: Fail the htlc backwards.\n- `Settle`: Settle this htlc with a given preimage."
|
||||
},
|
||||
"routerrpcGetMissionControlConfigResponse": {
|
||||
"type": "object",
|
||||
@ -1632,9 +1650,11 @@
|
||||
"enum": [
|
||||
"SETTLE",
|
||||
"FAIL",
|
||||
"RESUME"
|
||||
"RESUME",
|
||||
"RESUME_MODIFIED"
|
||||
],
|
||||
"default": "SETTLE"
|
||||
"default": "SETTLE",
|
||||
"description": " - RESUME_MODIFIED: RESUME_MODIFIED is an action that is used to resume a hold forward HTLC\nwith modifications specified during interception."
|
||||
},
|
||||
"routerrpcRouteFeeRequest": {
|
||||
"type": "object",
|
||||
|
@ -1487,7 +1487,7 @@ func (s *Server) SubscribeHtlcEvents(req *SubscribeHtlcEventsRequest,
|
||||
|
||||
// HtlcInterceptor is a bidirectional stream for streaming interception
|
||||
// requests to the caller.
|
||||
// Upon connection it does the following:
|
||||
// Upon connection, it does the following:
|
||||
// 1. Check if there is already a live stream, if yes it rejects the request.
|
||||
// 2. Registered a ForwardInterceptor
|
||||
// 3. Delivers to the caller every √√ and detect his answer.
|
||||
@ -1500,7 +1500,7 @@ func (s *Server) HtlcInterceptor(stream Router_HtlcInterceptorServer) error {
|
||||
}
|
||||
defer atomic.CompareAndSwapInt32(&s.forwardInterceptorActive, 1, 0)
|
||||
|
||||
// run the forward interceptor.
|
||||
// Run the forward interceptor.
|
||||
return newForwardInterceptor(
|
||||
s.cfg.RouterBackend.InterceptableForwarder, stream,
|
||||
).run()
|
||||
|
169
lnwire/custom_records.go
Normal file
169
lnwire/custom_records.go
Normal file
@ -0,0 +1,169 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
|
||||
const (
|
||||
// MinCustomRecordsTlvType is the minimum custom records TLV type as
|
||||
// defined in BOLT 01.
|
||||
MinCustomRecordsTlvType = 65536
|
||||
)
|
||||
|
||||
// CustomRecords stores a set of custom key/value pairs. Map keys are TLV types
|
||||
// which must be greater than or equal to MinCustomRecordsTlvType.
|
||||
type CustomRecords map[uint64][]byte
|
||||
|
||||
// NewCustomRecordsFromTlvTypeMap creates a new CustomRecords instance from a
|
||||
// tlv.TypeMap.
|
||||
func NewCustomRecordsFromTlvTypeMap(tlvMap tlv.TypeMap) (CustomRecords,
|
||||
error) {
|
||||
|
||||
customRecords := make(CustomRecords, len(tlvMap))
|
||||
for k, v := range tlvMap {
|
||||
customRecords[uint64(k)] = v
|
||||
}
|
||||
|
||||
// Validate the custom records.
|
||||
err := customRecords.Validate()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("custom records from tlv map "+
|
||||
"validation error: %v", err)
|
||||
}
|
||||
|
||||
return customRecords, nil
|
||||
}
|
||||
|
||||
// NewCustomRecordsFromTlvBlob creates a new CustomRecords instance from a
|
||||
// tlv.Blob.
|
||||
func NewCustomRecordsFromTlvBlob(b tlv.Blob) (CustomRecords, error) {
|
||||
stream, err := tlv.NewStream()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating stream: %w", err)
|
||||
}
|
||||
|
||||
typeMap, err := stream.DecodeWithParsedTypes(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding HTLC record: %w", err)
|
||||
}
|
||||
|
||||
return NewCustomRecordsFromTlvTypeMap(typeMap)
|
||||
}
|
||||
|
||||
// Validate checks that all custom records are in the custom type range.
|
||||
func (c CustomRecords) Validate() error {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for key := range c {
|
||||
if key < MinCustomRecordsTlvType {
|
||||
return fmt.Errorf("custom records entry with TLV "+
|
||||
"type below min: %d", MinCustomRecordsTlvType)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Copy returns a copy of the custom records.
|
||||
func (c CustomRecords) Copy() CustomRecords {
|
||||
customRecords := make(CustomRecords, len(c))
|
||||
for k, v := range c {
|
||||
customRecords[k] = v
|
||||
}
|
||||
|
||||
return customRecords
|
||||
}
|
||||
|
||||
// ExtendRecordProducers extends the given records slice with the custom
|
||||
// records. The resultant records slice will be sorted if the given records
|
||||
// slice contains TLV types greater than or equal to MinCustomRecordsTlvType.
|
||||
func (c CustomRecords) ExtendRecordProducers(
|
||||
producers []tlv.RecordProducer) ([]tlv.RecordProducer, error) {
|
||||
|
||||
// If the custom records are nil or empty, there is nothing to do.
|
||||
if len(c) == 0 {
|
||||
return producers, nil
|
||||
}
|
||||
|
||||
// Validate the custom records.
|
||||
err := c.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure that the existing records slice TLV types are not also present
|
||||
// in the custom records. If they are, the resultant extended records
|
||||
// slice would erroneously contain duplicate TLV types.
|
||||
for _, rp := range producers {
|
||||
record := rp.Record()
|
||||
recordTlvType := uint64(record.Type())
|
||||
|
||||
_, foundDuplicateTlvType := c[recordTlvType]
|
||||
if foundDuplicateTlvType {
|
||||
return nil, fmt.Errorf("custom records contains a TLV "+
|
||||
"type that is already present in the "+
|
||||
"existing records: %d", recordTlvType)
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the custom records map to a TLV record producer slice and
|
||||
// append them to the exiting records slice.
|
||||
crRecords := tlv.MapToRecords(c)
|
||||
for _, record := range crRecords {
|
||||
r := recordProducer{record}
|
||||
producers = append(producers, &r)
|
||||
}
|
||||
|
||||
// If the records slice which was given as an argument included TLV
|
||||
// values greater than or equal to the minimum custom records TLV type
|
||||
// we will sort the extended records slice to ensure that it is ordered
|
||||
// correctly.
|
||||
sort.Slice(producers, func(i, j int) bool {
|
||||
recordI := producers[i].Record()
|
||||
recordJ := producers[j].Record()
|
||||
return recordI.Type() < recordJ.Type()
|
||||
})
|
||||
|
||||
return producers, nil
|
||||
}
|
||||
|
||||
// RecordProducers returns a slice of record producers for the custom records.
|
||||
func (c CustomRecords) RecordProducers() []tlv.RecordProducer {
|
||||
// If the custom records are nil or empty, return an empty slice.
|
||||
if len(c) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert the custom records map to a TLV record producer slice.
|
||||
records := tlv.MapToRecords(c)
|
||||
|
||||
// Convert the records to record producers.
|
||||
producers := make([]tlv.RecordProducer, len(records))
|
||||
for i, record := range records {
|
||||
producers[i] = &recordProducer{record}
|
||||
}
|
||||
|
||||
return producers
|
||||
}
|
||||
|
||||
// Serialize serializes the custom records into a byte slice.
|
||||
func (c CustomRecords) Serialize() ([]byte, error) {
|
||||
records := tlv.MapToRecords(c)
|
||||
stream, err := tlv.NewStream(records...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating stream: %w", err)
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
if err := stream.Encode(&b); err != nil {
|
||||
return nil, fmt.Errorf("error encoding custom records: %w", err)
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import "github.com/lightningnetwork/lnd/tlv"
|
||||
|
||||
// QueryEncoding is an enum-like type that represents exactly how a set data is
|
||||
// encoded on the wire.
|
||||
type QueryEncoding uint8
|
||||
@ -15,3 +17,17 @@ const (
|
||||
// NOTE: this should no longer be used or accepted.
|
||||
EncodingSortedZlib QueryEncoding = 1
|
||||
)
|
||||
|
||||
// recordProducer is a simple helper struct that implements the
|
||||
// tlv.RecordProducer interface.
|
||||
type recordProducer struct {
|
||||
record tlv.Record
|
||||
}
|
||||
|
||||
// Record returns the underlying record.
|
||||
func (r *recordProducer) Record() tlv.Record {
|
||||
return r.record
|
||||
}
|
||||
|
||||
// Ensure that recordProducer implements the tlv.RecordProducer interface.
|
||||
var _ tlv.RecordProducer = (*recordProducer)(nil)
|
||||
|
@ -15,6 +15,41 @@ import (
|
||||
// upgrades to the network in a forwards compatible manner.
|
||||
type ExtraOpaqueData []byte
|
||||
|
||||
// NewExtraOpaqueDataFromTlvTypeMap creates a new ExtraOpaqueData instance from
|
||||
// a tlv.TypeMap.
|
||||
func NewExtraOpaqueDataFromTlvTypeMap(tlvMap tlv.TypeMap) (ExtraOpaqueData,
|
||||
error) {
|
||||
|
||||
extraData := ExtraOpaqueData{}
|
||||
|
||||
// If the tlv map is empty, return an empty extra data instance.
|
||||
if len(tlvMap) == 0 {
|
||||
return extraData, nil
|
||||
}
|
||||
|
||||
// Convert the tlv map to a generic type map.
|
||||
tlvMapGeneric := make(map[uint64][]byte)
|
||||
for k, v := range tlvMap {
|
||||
tlvMapGeneric[uint64(k)] = v
|
||||
}
|
||||
|
||||
// Convert the generic type map to a slice of records.
|
||||
records := tlv.MapToRecords(tlvMapGeneric)
|
||||
|
||||
// Encode the records into the extra data byte slice.
|
||||
tlvStream, err := tlv.NewStream(records...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var bytesWriter bytes.Buffer
|
||||
if err := tlvStream.Encode(&bytesWriter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytesWriter.Bytes(), nil
|
||||
}
|
||||
|
||||
// Encode attempts to encode the raw extra bytes into the passed io.Writer.
|
||||
func (e *ExtraOpaqueData) Encode(w *bytes.Buffer) error {
|
||||
eBytes := []byte((*e)[:])
|
||||
@ -105,6 +140,45 @@ func (e *ExtraOpaqueData) ExtractRecords(recordProducers ...tlv.RecordProducer)
|
||||
return tlvStream.DecodeWithParsedTypesP2P(extraBytesReader)
|
||||
}
|
||||
|
||||
// RecordProducers parses ExtraOpaqueData into a slice of TLV record producers
|
||||
// by interpreting it as a TLV map.
|
||||
func (e *ExtraOpaqueData) RecordProducers() ([]tlv.RecordProducer, error) {
|
||||
var recordProducers []tlv.RecordProducer
|
||||
|
||||
// If the instance is nil or empty, return an empty slice.
|
||||
if e == nil || len(*e) == 0 {
|
||||
return recordProducers, nil
|
||||
}
|
||||
|
||||
// Parse the extra opaque data as a TLV map.
|
||||
tlvMap, err := e.ExtractRecords()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert the TLV map into a slice of records.
|
||||
tlvMapGeneric := make(map[uint64][]byte)
|
||||
for k, v := range tlvMap {
|
||||
tlvMapGeneric[uint64(k)] = v
|
||||
}
|
||||
records := tlv.MapToRecords(tlvMapGeneric)
|
||||
|
||||
// Convert the records to record producers.
|
||||
recordProducers = make([]tlv.RecordProducer, len(records))
|
||||
for i, record := range records {
|
||||
recordProducers[i] = &recordProducer{record}
|
||||
}
|
||||
|
||||
return recordProducers, nil
|
||||
}
|
||||
|
||||
// Copy returns a copy of the target ExtraOpaqueData instance.
|
||||
func (e *ExtraOpaqueData) Copy() ExtraOpaqueData {
|
||||
copyData := make([]byte, len(*e))
|
||||
copy(copyData, *e)
|
||||
return copyData
|
||||
}
|
||||
|
||||
// EncodeMessageExtraData encodes the given recordProducers into the given
|
||||
// extraData.
|
||||
func EncodeMessageExtraData(extraData *ExtraOpaqueData,
|
||||
|
@ -86,14 +86,6 @@ func TestExtraOpaqueDataEncodeDecode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type recordProducer struct {
|
||||
record tlv.Record
|
||||
}
|
||||
|
||||
func (r *recordProducer) Record() tlv.Record {
|
||||
return r.record
|
||||
}
|
||||
|
||||
// TestExtraOpaqueDataPackUnpackRecords tests that we're able to pack a set of
|
||||
// tlv.Records into a stream, and unpack them on the other side to obtain the
|
||||
// same set of records.
|
||||
@ -151,3 +143,66 @@ func TestExtraOpaqueDataPackUnpackRecords(t *testing.T) {
|
||||
t.Fatalf("type2 not found in typeMap")
|
||||
}
|
||||
}
|
||||
|
||||
// TestPackRecords tests that we're able to pack a set of records into an
|
||||
// ExtraOpaqueData instance, and then extract them back out. Crucially, we'll
|
||||
// ensure that records can be packed in any order, and we'll ensure that the
|
||||
// unpacked records are valid.
|
||||
func TestPackRecords(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create an empty ExtraOpaqueData instance.
|
||||
extraBytes := ExtraOpaqueData{}
|
||||
|
||||
var (
|
||||
// Record type 1.
|
||||
tlvType1 tlv.TlvType1
|
||||
recordBytes1 = []byte("recordBytes1")
|
||||
tlvRecord1 = tlv.NewPrimitiveRecord[tlv.TlvType1](
|
||||
recordBytes1,
|
||||
)
|
||||
|
||||
// Record type 2.
|
||||
tlvType2 tlv.TlvType2
|
||||
recordBytes2 = []byte("recordBytes2")
|
||||
tlvRecord2 = tlv.NewPrimitiveRecord[tlv.TlvType2](
|
||||
recordBytes2,
|
||||
)
|
||||
|
||||
// Record type 3.
|
||||
tlvType3 tlv.TlvType3
|
||||
recordBytes3 = []byte("recordBytes3")
|
||||
tlvRecord3 = tlv.NewPrimitiveRecord[tlv.TlvType3](
|
||||
recordBytes3,
|
||||
)
|
||||
)
|
||||
|
||||
// Pack records 1 and 2 into the ExtraOpaqueData instance.
|
||||
err := extraBytes.PackRecords(
|
||||
[]tlv.RecordProducer{&tlvRecord1, &tlvRecord2}...,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Examine the records that were packed into the ExtraOpaqueData.
|
||||
extractedRecords, err := extraBytes.ExtractRecords()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, 2, len(extractedRecords))
|
||||
require.Equal(t, recordBytes1, extractedRecords[tlvType1.TypeVal()])
|
||||
require.Equal(t, recordBytes2, extractedRecords[tlvType2.TypeVal()])
|
||||
|
||||
// Pack records 1, 2, and 3 into the ExtraOpaqueData instance.
|
||||
err = extraBytes.PackRecords(
|
||||
[]tlv.RecordProducer{&tlvRecord3, &tlvRecord1, &tlvRecord2}...,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Examine the records that were packed into the ExtraOpaqueData.
|
||||
extractedRecords, err = extraBytes.ExtractRecords()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, 3, len(extractedRecords))
|
||||
require.Equal(t, recordBytes1, extractedRecords[tlvType1.TypeVal()])
|
||||
require.Equal(t, recordBytes2, extractedRecords[tlvType2.TypeVal()])
|
||||
require.Equal(t, recordBytes3, extractedRecords[tlvType3.TypeVal()])
|
||||
}
|
||||
|
@ -389,6 +389,45 @@ func TestEmptyMessageUnknownType(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// randCustomRecords generates a random set of custom records for testing.
|
||||
func randCustomRecords(t *testing.T, r *rand.Rand) CustomRecords {
|
||||
var (
|
||||
customRecords = CustomRecords{}
|
||||
|
||||
// We'll generate a random number of records,
|
||||
// between 0 and 10.
|
||||
numRecords = r.Intn(10)
|
||||
)
|
||||
|
||||
// For each record, we'll generate a random key and
|
||||
// value.
|
||||
for i := 0; i < numRecords; i++ {
|
||||
// Keys must be equal to or greater than
|
||||
// MinCustomRecordsTlvType.
|
||||
keyOffset := uint64(r.Intn(100))
|
||||
key := MinCustomRecordsTlvType + keyOffset
|
||||
|
||||
// Values are byte slices of any length.
|
||||
value := make([]byte, r.Intn(100))
|
||||
_, err := r.Read(value)
|
||||
require.NoError(t, err)
|
||||
|
||||
customRecords[key] = value
|
||||
}
|
||||
|
||||
// Validate the custom records as a sanity check.
|
||||
err := customRecords.Validate()
|
||||
require.NoError(t, err)
|
||||
|
||||
// If by chance we end up with an empty set of custom records, we'll
|
||||
// set it to nil to simplify test comparisons.
|
||||
if len(customRecords) == 0 {
|
||||
customRecords = nil
|
||||
}
|
||||
|
||||
return customRecords
|
||||
}
|
||||
|
||||
// TestLightningWireProtocol uses the testing/quick package to create a series
|
||||
// of fuzz tests to attempt to break a primary scenario which is implemented as
|
||||
// property based testing scenario.
|
||||
@ -1353,6 +1392,8 @@ func TestLightningWireProtocol(t *testing.T) {
|
||||
_, err = r.Read(req.OnionBlob[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
req.CustomRecords = randCustomRecords(t, r)
|
||||
|
||||
// Generate a blinding point 50% of the time, since not
|
||||
// all update adds will use route blinding.
|
||||
if r.Int31()%2 == 0 {
|
||||
@ -1373,6 +1414,21 @@ func TestLightningWireProtocol(t *testing.T) {
|
||||
|
||||
v[0] = reflect.ValueOf(*req)
|
||||
},
|
||||
MsgUpdateFulfillHTLC: func(v []reflect.Value, r *rand.Rand) {
|
||||
req := UpdateFulfillHTLC{
|
||||
ID: r.Uint64(),
|
||||
}
|
||||
|
||||
_, err := r.Read(req.ChanID[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.Read(req.PaymentPreimage[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
req.CustomRecords = randCustomRecords(t, r)
|
||||
|
||||
v[0] = reflect.ValueOf(req)
|
||||
},
|
||||
}
|
||||
|
||||
// With the above types defined, we'll now generate a slice of
|
||||
|
29
lnwire/test_utils.go
Normal file
29
lnwire/test_utils.go
Normal file
@ -0,0 +1,29 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
)
|
||||
|
||||
// pubkeyFromHex parses a Bitcoin public key from a hex encoded string.
|
||||
func pubkeyFromHex(keyHex string) (*btcec.PublicKey, error) {
|
||||
bytes, err := hex.DecodeString(keyHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcec.ParsePubKey(bytes)
|
||||
}
|
||||
|
||||
// generateRandomBytes returns a slice of n random bytes.
|
||||
func generateRandomBytes(n int) ([]byte, error) {
|
||||
b := make([]byte, n)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
@ -2,6 +2,7 @@ package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
@ -72,6 +73,11 @@ type UpdateAddHTLC struct {
|
||||
// next hop for this htlc.
|
||||
BlindingPoint BlindingPointRecord
|
||||
|
||||
// CustomRecords maps TLV types to byte slices, storing arbitrary data
|
||||
// intended for inclusion in the ExtraData field of the UpdateAddHTLC
|
||||
// message.
|
||||
CustomRecords CustomRecords
|
||||
|
||||
// ExtraData is the set of data that was appended to this message to
|
||||
// fill out the full maximum transport message size. These fields can
|
||||
// be used to specify optional data such as custom TLV fields.
|
||||
@ -92,6 +98,10 @@ var _ Message = (*UpdateAddHTLC)(nil)
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateAddHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
// msgExtraData is a temporary variable used to read the message extra
|
||||
// data field from the reader.
|
||||
var msgExtraData ExtraOpaqueData
|
||||
|
||||
if err := ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.ID,
|
||||
@ -99,25 +109,76 @@ func (c *UpdateAddHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
c.PaymentHash[:],
|
||||
&c.Expiry,
|
||||
c.OnionBlob[:],
|
||||
&c.ExtraData,
|
||||
&msgExtraData,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Extract TLV records from the extra data field.
|
||||
blindingRecord := c.BlindingPoint.Zero()
|
||||
tlvMap, err := c.ExtraData.ExtractRecords(&blindingRecord)
|
||||
|
||||
extraDataTlvMap, err := msgExtraData.ExtractRecords(&blindingRecord)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if val, ok := tlvMap[c.BlindingPoint.TlvType()]; ok && val == nil {
|
||||
val, ok := extraDataTlvMap[c.BlindingPoint.TlvType()]
|
||||
if ok && val == nil {
|
||||
c.BlindingPoint = tlv.SomeRecordT(blindingRecord)
|
||||
|
||||
// Remove the entry from the TLV map. Anything left in the map
|
||||
// will be included in the custom records field.
|
||||
delete(extraDataTlvMap, c.BlindingPoint.TlvType())
|
||||
}
|
||||
|
||||
// Any records from the extra data TLV map which are in the custom
|
||||
// records TLV type range will be included in the custom records field
|
||||
// and removed from the extra data field.
|
||||
customRecordsTlvMap := make(tlv.TypeMap, len(extraDataTlvMap))
|
||||
for k, v := range extraDataTlvMap {
|
||||
// Skip records that are not in the custom records TLV type
|
||||
// range.
|
||||
if k < MinCustomRecordsTlvType {
|
||||
continue
|
||||
}
|
||||
|
||||
// Include the record in the custom records map.
|
||||
customRecordsTlvMap[k] = v
|
||||
|
||||
// Now that the record is included in the custom records map,
|
||||
// we can remove it from the extra data TLV map.
|
||||
delete(extraDataTlvMap, k)
|
||||
}
|
||||
|
||||
// Set the custom records field to the custom records specific TLV
|
||||
// record map.
|
||||
customRecords, err := NewCustomRecordsFromTlvTypeMap(
|
||||
customRecordsTlvMap,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.CustomRecords = customRecords
|
||||
|
||||
// Set custom records to nil if we didn't parse anything out of it so
|
||||
// that we can use assert.Equal in tests.
|
||||
if len(customRecordsTlvMap) == 0 {
|
||||
c.CustomRecords = nil
|
||||
}
|
||||
|
||||
// Set extra data to nil if we didn't parse anything out of it so that
|
||||
// we can use assert.Equal in tests.
|
||||
if len(tlvMap) == 0 {
|
||||
if len(extraDataTlvMap) == 0 {
|
||||
c.ExtraData = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode the remaining records back into the extra data field. These
|
||||
// records are not in the custom records TLV type range and do not
|
||||
// have associated fields in the UpdateAddHTLC struct.
|
||||
c.ExtraData, err = NewExtraOpaqueDataFromTlvTypeMap(extraDataTlvMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -152,21 +213,41 @@ func (c *UpdateAddHTLC) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Only include blinding point in extra data if present.
|
||||
var records []tlv.RecordProducer
|
||||
|
||||
c.BlindingPoint.WhenSome(func(b tlv.RecordT[BlindingPointTlvType,
|
||||
*btcec.PublicKey]) {
|
||||
|
||||
records = append(records, &b)
|
||||
})
|
||||
|
||||
err := EncodeMessageExtraData(&c.ExtraData, records...)
|
||||
// Construct a slice of all the records that we should include in the
|
||||
// message extra data field. We will start by including any records from
|
||||
// the extra data field.
|
||||
msgExtraDataRecords, err := c.ExtraData.RecordProducers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
// Include blinding point in extra data if specified.
|
||||
c.BlindingPoint.WhenSome(func(b tlv.RecordT[BlindingPointTlvType,
|
||||
*btcec.PublicKey]) {
|
||||
|
||||
msgExtraDataRecords = append(msgExtraDataRecords, &b)
|
||||
})
|
||||
|
||||
// Include custom records in the extra data wire field if they are
|
||||
// present. Ensure that the custom records are validated before encoding
|
||||
// them.
|
||||
if err := c.CustomRecords.Validate(); err != nil {
|
||||
return fmt.Errorf("custom records validation error: %w", err)
|
||||
}
|
||||
|
||||
// Extend the message extra data records slice with TLV records from the
|
||||
// custom records field.
|
||||
customTlvRecords := c.CustomRecords.RecordProducers()
|
||||
msgExtraDataRecords = append(msgExtraDataRecords, customTlvRecords...)
|
||||
|
||||
// We will now construct the message extra data field that will be
|
||||
// encoded into the byte writer.
|
||||
var msgExtraData ExtraOpaqueData
|
||||
if err := msgExtraData.PackRecords(msgExtraDataRecords...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, msgExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
216
lnwire/update_add_htlc_test.go
Normal file
216
lnwire/update_add_htlc_test.go
Normal file
@ -0,0 +1,216 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testCase is a test case for the UpdateAddHTLC message.
|
||||
type testCase struct {
|
||||
// Msg is the message to be encoded and decoded.
|
||||
Msg UpdateAddHTLC
|
||||
|
||||
// ExpectEncodeError is a flag that indicates whether we expect the
|
||||
// encoding of the message to fail.
|
||||
ExpectEncodeError bool
|
||||
}
|
||||
|
||||
// generateTestCases generates a set of UpdateAddHTLC message test cases.
|
||||
func generateTestCases(t *testing.T) []testCase {
|
||||
// Firstly, we'll set basic values for the message fields.
|
||||
//
|
||||
// Generate random channel ID.
|
||||
chanIDBytes, err := generateRandomBytes(32)
|
||||
require.NoError(t, err)
|
||||
|
||||
var chanID ChannelID
|
||||
copy(chanID[:], chanIDBytes)
|
||||
|
||||
// Generate random payment hash.
|
||||
paymentHashBytes, err := generateRandomBytes(32)
|
||||
require.NoError(t, err)
|
||||
|
||||
var paymentHash [32]byte
|
||||
copy(paymentHash[:], paymentHashBytes)
|
||||
|
||||
// Generate random onion blob.
|
||||
onionBlobBytes, err := generateRandomBytes(OnionPacketSize)
|
||||
require.NoError(t, err)
|
||||
|
||||
var onionBlob [OnionPacketSize]byte
|
||||
copy(onionBlob[:], onionBlobBytes)
|
||||
|
||||
// Define the blinding point.
|
||||
blinding, err := pubkeyFromHex(
|
||||
"0228f2af0abe322403480fb3ee172f7f1601e67d1da6cad40b54c4468d4" +
|
||||
"8236c39",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
blindingPoint := tlv.SomeRecordT(
|
||||
tlv.NewPrimitiveRecord[BlindingPointTlvType](blinding),
|
||||
)
|
||||
|
||||
// Define custom records.
|
||||
recordKey1 := uint64(MinCustomRecordsTlvType + 1)
|
||||
recordValue1, err := generateRandomBytes(10)
|
||||
require.NoError(t, err)
|
||||
|
||||
recordKey2 := uint64(MinCustomRecordsTlvType + 2)
|
||||
recordValue2, err := generateRandomBytes(10)
|
||||
require.NoError(t, err)
|
||||
|
||||
customRecords := CustomRecords{
|
||||
recordKey1: recordValue1,
|
||||
recordKey2: recordValue2,
|
||||
}
|
||||
|
||||
// Construct an instance of extra data that contains records with TLV
|
||||
// types below the minimum custom records threshold and that lack
|
||||
// corresponding fields in the message struct. Content should persist in
|
||||
// the extra data field after encoding and decoding.
|
||||
var (
|
||||
recordBytes45 = []byte("recordBytes45")
|
||||
tlvRecord45 = tlv.NewPrimitiveRecord[tlv.TlvType45](
|
||||
recordBytes45,
|
||||
)
|
||||
|
||||
recordBytes55 = []byte("recordBytes55")
|
||||
tlvRecord55 = tlv.NewPrimitiveRecord[tlv.TlvType55](
|
||||
recordBytes55,
|
||||
)
|
||||
)
|
||||
|
||||
var extraData ExtraOpaqueData
|
||||
err = extraData.PackRecords(
|
||||
[]tlv.RecordProducer{&tlvRecord45, &tlvRecord55}...,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Define test cases.
|
||||
testCases := make([]testCase, 0)
|
||||
|
||||
testCases = append(testCases, testCase{
|
||||
Msg: UpdateAddHTLC{
|
||||
ChanID: chanID,
|
||||
ID: 42,
|
||||
Amount: MilliSatoshi(1000),
|
||||
PaymentHash: paymentHash,
|
||||
Expiry: 43,
|
||||
OnionBlob: onionBlob,
|
||||
BlindingPoint: blindingPoint,
|
||||
CustomRecords: customRecords,
|
||||
ExtraData: extraData,
|
||||
},
|
||||
})
|
||||
|
||||
// Add a test case where the blinding point field is not populated.
|
||||
testCases = append(testCases, testCase{
|
||||
Msg: UpdateAddHTLC{
|
||||
ChanID: chanID,
|
||||
ID: 42,
|
||||
Amount: MilliSatoshi(1000),
|
||||
PaymentHash: paymentHash,
|
||||
Expiry: 43,
|
||||
OnionBlob: onionBlob,
|
||||
CustomRecords: customRecords,
|
||||
},
|
||||
})
|
||||
|
||||
// Add a test case where the custom records field is not populated.
|
||||
testCases = append(testCases, testCase{
|
||||
Msg: UpdateAddHTLC{
|
||||
ChanID: chanID,
|
||||
ID: 42,
|
||||
Amount: MilliSatoshi(1000),
|
||||
PaymentHash: paymentHash,
|
||||
Expiry: 43,
|
||||
OnionBlob: onionBlob,
|
||||
BlindingPoint: blindingPoint,
|
||||
},
|
||||
})
|
||||
|
||||
// Add a case where the custom records are invlaid.
|
||||
invalidCustomRecords := CustomRecords{
|
||||
MinCustomRecordsTlvType - 1: recordValue1,
|
||||
}
|
||||
|
||||
testCases = append(testCases, testCase{
|
||||
Msg: UpdateAddHTLC{
|
||||
ChanID: chanID,
|
||||
ID: 42,
|
||||
Amount: MilliSatoshi(1000),
|
||||
PaymentHash: paymentHash,
|
||||
Expiry: 43,
|
||||
OnionBlob: onionBlob,
|
||||
BlindingPoint: blindingPoint,
|
||||
CustomRecords: invalidCustomRecords,
|
||||
},
|
||||
ExpectEncodeError: true,
|
||||
})
|
||||
|
||||
return testCases
|
||||
}
|
||||
|
||||
// TestUpdateAddHtlcEncodeDecode tests UpdateAddHTLC message encoding and
|
||||
// decoding for all supported field values.
|
||||
func TestUpdateAddHtlcEncodeDecode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Generate test cases.
|
||||
testCases := generateTestCases(t)
|
||||
|
||||
// Execute test cases.
|
||||
for tcIdx, tc := range testCases {
|
||||
t.Log("Running test case", tcIdx)
|
||||
|
||||
// Encode test case message.
|
||||
var buf bytes.Buffer
|
||||
err := tc.Msg.Encode(&buf, 0)
|
||||
|
||||
// Check if we expect an encoding error.
|
||||
if tc.ExpectEncodeError {
|
||||
require.Error(t, err)
|
||||
continue
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
// Decode the encoded message bytes message.
|
||||
var actualMsg UpdateAddHTLC
|
||||
decodeReader := bytes.NewReader(buf.Bytes())
|
||||
err = actualMsg.Decode(decodeReader, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Compare the two messages to ensure equality one field at a
|
||||
// time.
|
||||
require.Equal(t, tc.Msg.ChanID, actualMsg.ChanID)
|
||||
require.Equal(t, tc.Msg.ID, actualMsg.ID)
|
||||
require.Equal(t, tc.Msg.Amount, actualMsg.Amount)
|
||||
require.Equal(t, tc.Msg.PaymentHash, actualMsg.PaymentHash)
|
||||
require.Equal(t, tc.Msg.OnionBlob, actualMsg.OnionBlob)
|
||||
require.Equal(t, tc.Msg.BlindingPoint, actualMsg.BlindingPoint)
|
||||
|
||||
// Check that the custom records field is as expected.
|
||||
if len(tc.Msg.CustomRecords) == 0 {
|
||||
require.Len(t, actualMsg.CustomRecords, 0)
|
||||
} else {
|
||||
require.Equal(
|
||||
t, tc.Msg.CustomRecords,
|
||||
actualMsg.CustomRecords,
|
||||
)
|
||||
}
|
||||
|
||||
// Check that the extra data field is as expected.
|
||||
if len(tc.Msg.ExtraData) == 0 {
|
||||
require.Len(t, actualMsg.ExtraData, 0)
|
||||
} else {
|
||||
require.Equal(
|
||||
t, tc.Msg.ExtraData,
|
||||
actualMsg.ExtraData,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,10 @@ package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
|
||||
// UpdateFulfillHTLC is sent by Alice to Bob when she wishes to settle a
|
||||
@ -23,6 +26,10 @@ type UpdateFulfillHTLC struct {
|
||||
// HTLC.
|
||||
PaymentPreimage [32]byte
|
||||
|
||||
// CustomRecords maps TLV types to byte slices, storing arbitrary data
|
||||
// intended for inclusion in the ExtraData field.
|
||||
CustomRecords CustomRecords
|
||||
|
||||
// ExtraData is the set of data that was appended to this message to
|
||||
// fill out the full maximum transport message size. These fields can
|
||||
// be used to specify optional data such as custom TLV fields.
|
||||
@ -49,12 +56,75 @@ var _ Message = (*UpdateFulfillHTLC)(nil)
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFulfillHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
// msgExtraData is a temporary variable used to read the message extra
|
||||
// data field from the reader.
|
||||
var msgExtraData ExtraOpaqueData
|
||||
|
||||
if err := ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.ID,
|
||||
c.PaymentPreimage[:],
|
||||
&c.ExtraData,
|
||||
&msgExtraData,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Extract TLV records from the message extra data field.
|
||||
extraDataTlvMap, err := msgExtraData.ExtractRecords()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Any records from the extra data TLV map which are in the custom
|
||||
// records TLV type range will be included in the custom records field
|
||||
// and removed from the extra data field.
|
||||
customRecordsTlvMap := make(tlv.TypeMap, len(extraDataTlvMap))
|
||||
for k, v := range extraDataTlvMap {
|
||||
// Skip records that are not in the custom records TLV type
|
||||
// range.
|
||||
if k < MinCustomRecordsTlvType {
|
||||
continue
|
||||
}
|
||||
|
||||
// Include the record in the custom records map.
|
||||
customRecordsTlvMap[k] = v
|
||||
|
||||
// Now that the record is included in the custom records map,
|
||||
// we can remove it from the extra data TLV map.
|
||||
delete(extraDataTlvMap, k)
|
||||
}
|
||||
|
||||
// Set the custom records field to the TLV record map.
|
||||
customRecords, err := NewCustomRecordsFromTlvTypeMap(
|
||||
customRecordsTlvMap,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.CustomRecords = customRecords
|
||||
|
||||
// Set custom records to nil if we didn't parse anything out of it so
|
||||
// that we can use assert.Equal in tests.
|
||||
if len(customRecordsTlvMap) == 0 {
|
||||
c.CustomRecords = nil
|
||||
}
|
||||
|
||||
// Set extra data to nil if we didn't parse anything out of it so that
|
||||
// we can use assert.Equal in tests.
|
||||
if len(extraDataTlvMap) == 0 {
|
||||
c.ExtraData = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode the remaining records back into the extra data field. These
|
||||
// records are not in the custom records TLV type range and do not
|
||||
// have associated fields in the UpdateFulfillHTLC struct.
|
||||
c.ExtraData, err = NewExtraOpaqueDataFromTlvTypeMap(extraDataTlvMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode serializes the target UpdateFulfillHTLC into the passed io.Writer
|
||||
@ -74,7 +144,34 @@ func (c *UpdateFulfillHTLC) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
// Construct a slice of all the records that we should include in the
|
||||
// message extra data field. We will start by including any records from
|
||||
// the extra data field.
|
||||
msgExtraDataRecords, err := c.ExtraData.RecordProducers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Include custom records in the extra data wire field if they are
|
||||
// present. Ensure that the custom records are validated before encoding
|
||||
// them.
|
||||
if err := c.CustomRecords.Validate(); err != nil {
|
||||
return fmt.Errorf("custom records validation error: %w", err)
|
||||
}
|
||||
|
||||
// Extend the message extra data records slice with TLV records from the
|
||||
// custom records field.
|
||||
customTlvRecords := c.CustomRecords.RecordProducers()
|
||||
msgExtraDataRecords = append(msgExtraDataRecords, customTlvRecords...)
|
||||
|
||||
// We will now construct the message extra data field that will be
|
||||
// encoded into the byte writer.
|
||||
var msgExtraData ExtraOpaqueData
|
||||
if err := msgExtraData.PackRecords(msgExtraDataRecords...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, msgExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
148
lnwire/update_fulfill_htlc_test.go
Normal file
148
lnwire/update_fulfill_htlc_test.go
Normal file
@ -0,0 +1,148 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testCaseUpdateFulfill is a test case for the UpdateFulfillHTLC message.
|
||||
type testCaseUpdateFulfill struct {
|
||||
// Msg is the message to be encoded and decoded.
|
||||
Msg UpdateFulfillHTLC
|
||||
|
||||
// ExpectEncodeError is a flag that indicates whether we expect the
|
||||
// encoding of the message to fail.
|
||||
ExpectEncodeError bool
|
||||
}
|
||||
|
||||
// generateTestCases generates a set of UpdateFulfillHTLC message test cases.
|
||||
func generateUpdateFulfillTestCases(t *testing.T) []testCaseUpdateFulfill {
|
||||
// Firstly, we'll set basic values for the message fields.
|
||||
//
|
||||
// Generate random channel ID.
|
||||
chanIDBytes, err := generateRandomBytes(32)
|
||||
require.NoError(t, err)
|
||||
|
||||
var chanID ChannelID
|
||||
copy(chanID[:], chanIDBytes)
|
||||
|
||||
// Generate random payment preimage.
|
||||
paymentPreimageBytes, err := generateRandomBytes(32)
|
||||
require.NoError(t, err)
|
||||
|
||||
var paymentPreimage [32]byte
|
||||
copy(paymentPreimage[:], paymentPreimageBytes)
|
||||
|
||||
// Define custom records.
|
||||
recordKey1 := uint64(MinCustomRecordsTlvType + 1)
|
||||
recordValue1, err := generateRandomBytes(10)
|
||||
require.NoError(t, err)
|
||||
|
||||
recordKey2 := uint64(MinCustomRecordsTlvType + 2)
|
||||
recordValue2, err := generateRandomBytes(10)
|
||||
require.NoError(t, err)
|
||||
|
||||
customRecords := CustomRecords{
|
||||
recordKey1: recordValue1,
|
||||
recordKey2: recordValue2,
|
||||
}
|
||||
|
||||
// Construct an instance of extra data that contains records with TLV
|
||||
// types below the minimum custom records threshold and that lack
|
||||
// corresponding fields in the message struct. Content should persist in
|
||||
// the extra data field after encoding and decoding.
|
||||
var (
|
||||
recordBytes45 = []byte("recordBytes45")
|
||||
tlvRecord45 = tlv.NewPrimitiveRecord[tlv.TlvType45](
|
||||
recordBytes45,
|
||||
)
|
||||
|
||||
recordBytes55 = []byte("recordBytes55")
|
||||
tlvRecord55 = tlv.NewPrimitiveRecord[tlv.TlvType55](
|
||||
recordBytes55,
|
||||
)
|
||||
)
|
||||
|
||||
var extraData ExtraOpaqueData
|
||||
err = extraData.PackRecords(
|
||||
[]tlv.RecordProducer{&tlvRecord45, &tlvRecord55}...,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Define test cases.
|
||||
testCases := make([]testCaseUpdateFulfill, 0)
|
||||
|
||||
testCases = append(testCases, testCaseUpdateFulfill{
|
||||
Msg: UpdateFulfillHTLC{
|
||||
ChanID: chanID,
|
||||
ID: 42,
|
||||
PaymentPreimage: paymentPreimage,
|
||||
CustomRecords: customRecords,
|
||||
ExtraData: extraData,
|
||||
},
|
||||
})
|
||||
|
||||
return testCases
|
||||
}
|
||||
|
||||
// TestUpdateFulfillHtlcEncodeDecode tests UpdateFulfillHTLC message encoding
|
||||
// and decoding for all supported field values.
|
||||
func TestUpdateFulfillHtlcEncodeDecode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Generate test cases.
|
||||
testCases := generateUpdateFulfillTestCases(t)
|
||||
|
||||
// Execute test cases.
|
||||
for tcIdx, tc := range testCases {
|
||||
t.Log("Running test case", tcIdx)
|
||||
|
||||
// Encode test case message.
|
||||
var buf bytes.Buffer
|
||||
err := tc.Msg.Encode(&buf, 0)
|
||||
|
||||
// Check if we expect an encoding error.
|
||||
if tc.ExpectEncodeError {
|
||||
require.Error(t, err)
|
||||
continue
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
// Decode the encoded message bytes message.
|
||||
var actualMsg UpdateFulfillHTLC
|
||||
decodeReader := bytes.NewReader(buf.Bytes())
|
||||
err = actualMsg.Decode(decodeReader, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Compare the two messages to ensure equality one field at a
|
||||
// time.
|
||||
require.Equal(t, tc.Msg.ChanID, actualMsg.ChanID)
|
||||
require.Equal(t, tc.Msg.ID, actualMsg.ID)
|
||||
require.Equal(
|
||||
t, tc.Msg.PaymentPreimage, actualMsg.PaymentPreimage,
|
||||
)
|
||||
|
||||
// Check that the custom records field is as expected.
|
||||
if len(tc.Msg.CustomRecords) == 0 {
|
||||
require.Len(t, actualMsg.CustomRecords, 0)
|
||||
} else {
|
||||
require.Equal(
|
||||
t, tc.Msg.CustomRecords,
|
||||
actualMsg.CustomRecords,
|
||||
)
|
||||
}
|
||||
|
||||
// Check that the extra data field is as expected.
|
||||
if len(tc.Msg.ExtraData) == 0 {
|
||||
require.Len(t, actualMsg.ExtraData, 0)
|
||||
} else {
|
||||
require.Equal(
|
||||
t, tc.Msg.ExtraData,
|
||||
actualMsg.ExtraData,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -2024,17 +2024,18 @@ func messageSummary(msg lnwire.Message) string {
|
||||
)
|
||||
|
||||
return fmt.Sprintf("chan_id=%v, id=%v, amt=%v, expiry=%v, "+
|
||||
"hash=%x, blinding_point=%x", msg.ChanID, msg.ID,
|
||||
msg.Amount, msg.Expiry, msg.PaymentHash[:],
|
||||
blindingPoint)
|
||||
"hash=%x, blinding_point=%x, custom_records=%v",
|
||||
msg.ChanID, msg.ID, msg.Amount, msg.Expiry,
|
||||
msg.PaymentHash[:], blindingPoint, msg.CustomRecords)
|
||||
|
||||
case *lnwire.UpdateFailHTLC:
|
||||
return fmt.Sprintf("chan_id=%v, id=%v, reason=%x", msg.ChanID,
|
||||
msg.ID, msg.Reason)
|
||||
|
||||
case *lnwire.UpdateFulfillHTLC:
|
||||
return fmt.Sprintf("chan_id=%v, id=%v, pre_image=%x",
|
||||
msg.ChanID, msg.ID, msg.PaymentPreimage[:])
|
||||
return fmt.Sprintf("chan_id=%v, id=%v, pre_image=%x, "+
|
||||
"custom_records=%v", msg.ChanID, msg.ID,
|
||||
msg.PaymentPreimage[:], msg.CustomRecords)
|
||||
|
||||
case *lnwire.CommitSig:
|
||||
return fmt.Sprintf("chan_id=%v, num_htlcs=%v", msg.ChanID,
|
||||
|
Loading…
x
Reference in New Issue
Block a user