Merge pull request #2022 from joostjager/holdinvoice
htlcswitch: hodl invoice
This commit is contained in:
commit
aa1cd04dbf
@ -2,7 +2,6 @@ package channeldb
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@ -67,17 +66,18 @@ func TestInvoiceWorkflow(t *testing.T) {
|
||||
copy(fakeInvoice.Terms.PaymentPreimage[:], rev[:])
|
||||
fakeInvoice.Terms.Value = lnwire.NewMSatFromSatoshis(10000)
|
||||
|
||||
paymentHash := fakeInvoice.Terms.PaymentPreimage.Hash()
|
||||
|
||||
// Add the invoice to the database, this should succeed as there aren't
|
||||
// any existing invoices within the database with the same payment
|
||||
// hash.
|
||||
if _, err := db.AddInvoice(fakeInvoice); err != nil {
|
||||
if _, err := db.AddInvoice(fakeInvoice, paymentHash); err != nil {
|
||||
t.Fatalf("unable to find invoice: %v", err)
|
||||
}
|
||||
|
||||
// Attempt to retrieve the invoice which was just added to the
|
||||
// database. It should be found, and the invoice returned should be
|
||||
// identical to the one created above.
|
||||
paymentHash := sha256.Sum256(fakeInvoice.Terms.PaymentPreimage[:])
|
||||
dbInvoice, err := db.LookupInvoice(paymentHash)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find invoice: %v", err)
|
||||
@ -99,7 +99,7 @@ func TestInvoiceWorkflow(t *testing.T) {
|
||||
// now have the settled bit toggle to true and a non-default
|
||||
// SettledDate
|
||||
payAmt := fakeInvoice.Terms.Value * 2
|
||||
if _, err := db.SettleInvoice(paymentHash, payAmt); err != nil {
|
||||
if _, err := db.AcceptOrSettleInvoice(paymentHash, payAmt); err != nil {
|
||||
t.Fatalf("unable to settle invoice: %v", err)
|
||||
}
|
||||
dbInvoice2, err := db.LookupInvoice(paymentHash)
|
||||
@ -126,7 +126,7 @@ func TestInvoiceWorkflow(t *testing.T) {
|
||||
|
||||
// Attempt to insert generated above again, this should fail as
|
||||
// duplicates are rejected by the processing logic.
|
||||
if _, err := db.AddInvoice(fakeInvoice); err != ErrDuplicateInvoice {
|
||||
if _, err := db.AddInvoice(fakeInvoice, paymentHash); err != ErrDuplicateInvoice {
|
||||
t.Fatalf("invoice insertion should fail due to duplication, "+
|
||||
"instead %v", err)
|
||||
}
|
||||
@ -149,7 +149,8 @@ func TestInvoiceWorkflow(t *testing.T) {
|
||||
t.Fatalf("unable to create invoice: %v", err)
|
||||
}
|
||||
|
||||
if _, err := db.AddInvoice(invoice); err != nil {
|
||||
hash := invoice.Terms.PaymentPreimage.Hash()
|
||||
if _, err := db.AddInvoice(invoice, hash); err != nil {
|
||||
t.Fatalf("unable to add invoice %v", err)
|
||||
}
|
||||
|
||||
@ -198,7 +199,9 @@ func TestInvoiceAddTimeSeries(t *testing.T) {
|
||||
t.Fatalf("unable to create invoice: %v", err)
|
||||
}
|
||||
|
||||
if _, err := db.AddInvoice(invoice); err != nil {
|
||||
paymentHash := invoice.Terms.PaymentPreimage.Hash()
|
||||
|
||||
if _, err := db.AddInvoice(invoice, paymentHash); err != nil {
|
||||
t.Fatalf("unable to add invoice %v", err)
|
||||
}
|
||||
|
||||
@ -256,11 +259,9 @@ func TestInvoiceAddTimeSeries(t *testing.T) {
|
||||
for i := 10; i < len(invoices); i++ {
|
||||
invoice := &invoices[i]
|
||||
|
||||
paymentHash := sha256.Sum256(
|
||||
invoice.Terms.PaymentPreimage[:],
|
||||
)
|
||||
paymentHash := invoice.Terms.PaymentPreimage.Hash()
|
||||
|
||||
_, err := db.SettleInvoice(paymentHash, 0)
|
||||
_, err := db.AcceptOrSettleInvoice(paymentHash, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to settle invoice: %v", err)
|
||||
}
|
||||
@ -334,13 +335,14 @@ func TestDuplicateSettleInvoice(t *testing.T) {
|
||||
t.Fatalf("unable to create invoice: %v", err)
|
||||
}
|
||||
|
||||
if _, err := db.AddInvoice(invoice); err != nil {
|
||||
payHash := invoice.Terms.PaymentPreimage.Hash()
|
||||
|
||||
if _, err := db.AddInvoice(invoice, payHash); err != nil {
|
||||
t.Fatalf("unable to add invoice %v", err)
|
||||
}
|
||||
|
||||
// With the invoice in the DB, we'll now attempt to settle the invoice.
|
||||
payHash := sha256.Sum256(invoice.Terms.PaymentPreimage[:])
|
||||
dbInvoice, err := db.SettleInvoice(payHash, amt)
|
||||
dbInvoice, err := db.AcceptOrSettleInvoice(payHash, amt)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to settle invoice: %v", err)
|
||||
}
|
||||
@ -360,7 +362,7 @@ func TestDuplicateSettleInvoice(t *testing.T) {
|
||||
|
||||
// If we try to settle the invoice again, then we should get the very
|
||||
// same invoice back, but with an error this time.
|
||||
dbInvoice, err = db.SettleInvoice(payHash, amt)
|
||||
dbInvoice, err = db.AcceptOrSettleInvoice(payHash, amt)
|
||||
if err != ErrInvoiceAlreadySettled {
|
||||
t.Fatalf("expected ErrInvoiceAlreadySettled")
|
||||
}
|
||||
@ -397,14 +399,15 @@ func TestQueryInvoices(t *testing.T) {
|
||||
t.Fatalf("unable to create invoice: %v", err)
|
||||
}
|
||||
|
||||
if _, err := db.AddInvoice(invoice); err != nil {
|
||||
paymentHash := invoice.Terms.PaymentPreimage.Hash()
|
||||
|
||||
if _, err := db.AddInvoice(invoice, paymentHash); err != nil {
|
||||
t.Fatalf("unable to add invoice: %v", err)
|
||||
}
|
||||
|
||||
// We'll only settle half of all invoices created.
|
||||
if i%2 == 0 {
|
||||
paymentHash := sha256.Sum256(invoice.Terms.PaymentPreimage[:])
|
||||
if _, err := db.SettleInvoice(paymentHash, i); err != nil {
|
||||
if _, err := db.AcceptOrSettleInvoice(paymentHash, i); err != nil {
|
||||
t.Fatalf("unable to settle invoice: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package channeldb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -16,6 +15,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// UnknownPreimage is an all-zeroes preimage that indicates that the
|
||||
// preimage for this invoice is not yet known.
|
||||
UnknownPreimage lntypes.Preimage
|
||||
|
||||
// invoiceBucket is the name of the bucket within the database that
|
||||
// stores all data related to invoices no matter their final state.
|
||||
// Within the invoice bucket, each invoice is keyed by its invoice ID
|
||||
@ -66,6 +69,13 @@ var (
|
||||
// ErrInvoiceAlreadyCanceled is returned when the invoice is already
|
||||
// canceled.
|
||||
ErrInvoiceAlreadyCanceled = errors.New("invoice already canceled")
|
||||
|
||||
// ErrInvoiceAlreadyAccepted is returned when the invoice is already
|
||||
// accepted.
|
||||
ErrInvoiceAlreadyAccepted = errors.New("invoice already accepted")
|
||||
|
||||
// ErrInvoiceStillOpen is returned when the invoice is still open.
|
||||
ErrInvoiceStillOpen = errors.New("invoice still open")
|
||||
)
|
||||
|
||||
const (
|
||||
@ -97,6 +107,10 @@ const (
|
||||
|
||||
// ContractCanceled means the invoice has been canceled.
|
||||
ContractCanceled ContractState = 2
|
||||
|
||||
// ContractAccepted means the HTLC has been accepted but not settled
|
||||
// yet.
|
||||
ContractAccepted ContractState = 3
|
||||
)
|
||||
|
||||
// String returns a human readable identifier for the ContractState type.
|
||||
@ -108,6 +122,8 @@ func (c ContractState) String() string {
|
||||
return "Settled"
|
||||
case ContractCanceled:
|
||||
return "Canceled"
|
||||
case ContractAccepted:
|
||||
return "Accepted"
|
||||
}
|
||||
|
||||
return "Unknown"
|
||||
@ -213,11 +229,14 @@ func validateInvoice(i *Invoice) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddInvoice inserts the targeted invoice into the database. If the invoice
|
||||
// has *any* payment hashes which already exists within the database, then the
|
||||
// AddInvoice inserts the targeted invoice into the database. If the invoice has
|
||||
// *any* payment hashes which already exists within the database, then the
|
||||
// insertion will be aborted and rejected due to the strict policy banning any
|
||||
// duplicate payment hashes.
|
||||
func (d *DB) AddInvoice(newInvoice *Invoice) (uint64, error) {
|
||||
// duplicate payment hashes. A side effect of this function is that it sets
|
||||
// AddIndex on newInvoice.
|
||||
func (d *DB) AddInvoice(newInvoice *Invoice, paymentHash lntypes.Hash) (
|
||||
uint64, error) {
|
||||
|
||||
if err := validateInvoice(newInvoice); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -244,9 +263,6 @@ func (d *DB) AddInvoice(newInvoice *Invoice) (uint64, error) {
|
||||
|
||||
// Ensure that an invoice an identical payment hash doesn't
|
||||
// already exist within the index.
|
||||
paymentHash := sha256.Sum256(
|
||||
newInvoice.Terms.PaymentPreimage[:],
|
||||
)
|
||||
if invoiceIndex.Get(paymentHash[:]) != nil {
|
||||
return ErrDuplicateInvoice
|
||||
}
|
||||
@ -268,6 +284,7 @@ func (d *DB) AddInvoice(newInvoice *Invoice) (uint64, error) {
|
||||
|
||||
newIndex, err := putInvoice(
|
||||
invoices, invoiceIndex, addIndex, newInvoice, invoiceNum,
|
||||
paymentHash,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -607,11 +624,14 @@ func (d *DB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error) {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// SettleInvoice attempts to mark an invoice corresponding to the passed
|
||||
// payment hash as fully settled. If an invoice matching the passed payment
|
||||
// hash doesn't existing within the database, then the action will fail with a
|
||||
// "not found" error.
|
||||
func (d *DB) SettleInvoice(paymentHash [32]byte,
|
||||
// AcceptOrSettleInvoice attempts to mark an invoice corresponding to the passed
|
||||
// payment hash as settled. If an invoice matching the passed payment hash
|
||||
// doesn't existing within the database, then the action will fail with a "not
|
||||
// found" error.
|
||||
//
|
||||
// When the preimage for the invoice is unknown (hold invoice), the invoice is
|
||||
// marked as accepted.
|
||||
func (d *DB) AcceptOrSettleInvoice(paymentHash [32]byte,
|
||||
amtPaid lnwire.MilliSatoshi) (*Invoice, error) {
|
||||
|
||||
var settledInvoice *Invoice
|
||||
@ -640,7 +660,7 @@ func (d *DB) SettleInvoice(paymentHash [32]byte,
|
||||
return ErrInvoiceNotFound
|
||||
}
|
||||
|
||||
settledInvoice, err = settleInvoice(
|
||||
settledInvoice, err = acceptOrSettleInvoice(
|
||||
invoices, settleIndex, invoiceNum, amtPaid,
|
||||
)
|
||||
|
||||
@ -650,6 +670,46 @@ func (d *DB) SettleInvoice(paymentHash [32]byte,
|
||||
return settledInvoice, err
|
||||
}
|
||||
|
||||
// SettleHoldInvoice sets the preimage of a hodl invoice and marks the invoice
|
||||
// as settled.
|
||||
func (d *DB) SettleHoldInvoice(preimage lntypes.Preimage) (*Invoice, error) {
|
||||
var updatedInvoice *Invoice
|
||||
hash := preimage.Hash()
|
||||
err := d.Update(func(tx *bbolt.Tx) error {
|
||||
invoices, err := tx.CreateBucketIfNotExists(invoiceBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
invoiceIndex, err := invoices.CreateBucketIfNotExists(
|
||||
invoiceIndexBucket,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
settleIndex, err := invoices.CreateBucketIfNotExists(
|
||||
settleIndexBucket,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check the invoice index to see if an invoice paying to this
|
||||
// hash exists within the DB.
|
||||
invoiceNum := invoiceIndex.Get(hash[:])
|
||||
if invoiceNum == nil {
|
||||
return ErrInvoiceNotFound
|
||||
}
|
||||
|
||||
updatedInvoice, err = settleHoldInvoice(
|
||||
invoices, settleIndex, invoiceNum, preimage,
|
||||
)
|
||||
|
||||
return err
|
||||
})
|
||||
|
||||
return updatedInvoice, err
|
||||
}
|
||||
|
||||
// CancelInvoice attempts to cancel the invoice corresponding to the passed
|
||||
// payment hash.
|
||||
func (d *DB) CancelInvoice(paymentHash lntypes.Hash) (*Invoice, error) {
|
||||
@ -743,7 +803,8 @@ func (d *DB) InvoicesSettledSince(sinceSettleIndex uint64) ([]Invoice, error) {
|
||||
}
|
||||
|
||||
func putInvoice(invoices, invoiceIndex, addIndex *bbolt.Bucket,
|
||||
i *Invoice, invoiceNum uint32) (uint64, error) {
|
||||
i *Invoice, invoiceNum uint32, paymentHash lntypes.Hash) (
|
||||
uint64, error) {
|
||||
|
||||
// Create the invoice key which is just the big-endian representation
|
||||
// of the invoice number.
|
||||
@ -762,7 +823,6 @@ func putInvoice(invoices, invoiceIndex, addIndex *bbolt.Bucket,
|
||||
// Add the payment hash to the invoice index. This will let us quickly
|
||||
// identify if we can settle an incoming payment, and also to possibly
|
||||
// allow a single invoice to have multiple payment installations.
|
||||
paymentHash := sha256.Sum256(i.Terms.PaymentPreimage[:])
|
||||
err := invoiceIndex.Put(paymentHash[:], invoiceKey[:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -928,7 +988,7 @@ func deserializeInvoice(r io.Reader) (Invoice, error) {
|
||||
return invoice, nil
|
||||
}
|
||||
|
||||
func settleInvoice(invoices, settleIndex *bbolt.Bucket, invoiceNum []byte,
|
||||
func acceptOrSettleInvoice(invoices, settleIndex *bbolt.Bucket, invoiceNum []byte,
|
||||
amtPaid lnwire.MilliSatoshi) (*Invoice, error) {
|
||||
|
||||
invoice, err := fetchInvoice(invoiceNum, invoices)
|
||||
@ -936,32 +996,90 @@ func settleInvoice(invoices, settleIndex *bbolt.Bucket, invoiceNum []byte,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch invoice.Terms.State {
|
||||
case ContractSettled:
|
||||
state := invoice.Terms.State
|
||||
|
||||
switch {
|
||||
case state == ContractAccepted:
|
||||
return &invoice, ErrInvoiceAlreadyAccepted
|
||||
case state == ContractSettled:
|
||||
return &invoice, ErrInvoiceAlreadySettled
|
||||
case ContractCanceled:
|
||||
case state == ContractCanceled:
|
||||
return &invoice, ErrInvoiceAlreadyCanceled
|
||||
}
|
||||
|
||||
holdInvoice := invoice.Terms.PaymentPreimage == UnknownPreimage
|
||||
if holdInvoice {
|
||||
invoice.Terms.State = ContractAccepted
|
||||
} else {
|
||||
err := setSettleFields(settleIndex, invoiceNum, &invoice)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
invoice.AmtPaid = amtPaid
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := serializeInvoice(&buf, &invoice); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := invoices.Put(invoiceNum[:], buf.Bytes()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &invoice, nil
|
||||
}
|
||||
|
||||
func setSettleFields(settleIndex *bbolt.Bucket, invoiceNum []byte,
|
||||
invoice *Invoice) error {
|
||||
|
||||
// Now that we know the invoice hasn't already been settled, we'll
|
||||
// update the settle index so we can place this settle event in the
|
||||
// proper location within our time series.
|
||||
nextSettleSeqNo, err := settleIndex.NextSequence()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
var seqNoBytes [8]byte
|
||||
byteOrder.PutUint64(seqNoBytes[:], nextSettleSeqNo)
|
||||
if err := settleIndex.Put(seqNoBytes[:], invoiceNum); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
invoice.AmtPaid = amtPaid
|
||||
invoice.Terms.State = ContractSettled
|
||||
invoice.SettleDate = time.Now()
|
||||
invoice.SettleIndex = nextSettleSeqNo
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func settleHoldInvoice(invoices, settleIndex *bbolt.Bucket,
|
||||
invoiceNum []byte, preimage lntypes.Preimage) (*Invoice,
|
||||
error) {
|
||||
|
||||
invoice, err := fetchInvoice(invoiceNum, invoices)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch invoice.Terms.State {
|
||||
case ContractOpen:
|
||||
return &invoice, ErrInvoiceStillOpen
|
||||
case ContractCanceled:
|
||||
return &invoice, ErrInvoiceAlreadyCanceled
|
||||
case ContractSettled:
|
||||
return &invoice, ErrInvoiceAlreadySettled
|
||||
}
|
||||
|
||||
invoice.Terms.PaymentPreimage = preimage
|
||||
|
||||
err = setSettleFields(settleIndex, invoiceNum, &invoice)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := serializeInvoice(&buf, &invoice); err != nil {
|
||||
return nil, err
|
||||
@ -991,6 +1109,9 @@ func cancelInvoice(invoices *bbolt.Bucket, invoiceNum []byte) (
|
||||
|
||||
invoice.Terms.State = ContractCanceled
|
||||
|
||||
// Set AmtPaid back to 0, in case the invoice was already accepted.
|
||||
invoice.AmtPaid = 0
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := serializeInvoice(&buf, &invoice); err != nil {
|
||||
return nil, err
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"strconv"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@ -15,6 +17,8 @@ import (
|
||||
func invoicesCommands() []cli.Command {
|
||||
return []cli.Command{
|
||||
cancelInvoiceCommand,
|
||||
addHoldInvoiceCommand,
|
||||
settleInvoiceCommand,
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +32,60 @@ func getInvoicesClient(ctx *cli.Context) (invoicesrpc.InvoicesClient, func()) {
|
||||
return invoicesrpc.NewInvoicesClient(conn), cleanUp
|
||||
}
|
||||
|
||||
var settleInvoiceCommand = cli.Command{
|
||||
Name: "settleinvoice",
|
||||
Category: "Payments",
|
||||
Usage: "Reveal a preimage and use it to settle the corresponding invoice.",
|
||||
Description: `
|
||||
Todo.`,
|
||||
ArgsUsage: "preimage",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "preimage",
|
||||
Usage: "the hex-encoded preimage (32 byte) which will " +
|
||||
"allow settling an incoming HTLC payable to this " +
|
||||
"preimage.",
|
||||
},
|
||||
},
|
||||
Action: actionDecorator(settleInvoice),
|
||||
}
|
||||
|
||||
func settleInvoice(ctx *cli.Context) error {
|
||||
var (
|
||||
preimage []byte
|
||||
err error
|
||||
)
|
||||
|
||||
client, cleanUp := getInvoicesClient(ctx)
|
||||
defer cleanUp()
|
||||
|
||||
args := ctx.Args()
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("preimage"):
|
||||
preimage, err = hex.DecodeString(ctx.String("preimage"))
|
||||
case args.Present():
|
||||
preimage, err = hex.DecodeString(args.First())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse preimage: %v", err)
|
||||
}
|
||||
|
||||
invoice := &invoicesrpc.SettleInvoiceMsg{
|
||||
Preimage: preimage,
|
||||
}
|
||||
|
||||
resp, err := client.SettleInvoice(context.Background(), invoice)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printJSON(resp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var cancelInvoiceCommand = cli.Command{
|
||||
Name: "cancelinvoice",
|
||||
Category: "Payments",
|
||||
@ -80,3 +138,120 @@ func cancelInvoice(ctx *cli.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var addHoldInvoiceCommand = cli.Command{
|
||||
Name: "addholdinvoice",
|
||||
Category: "Payments",
|
||||
Usage: "Add a new hold invoice.",
|
||||
Description: `
|
||||
Add a new invoice, expressing intent for a future payment.
|
||||
|
||||
Invoices without an amount can be created by not supplying any
|
||||
parameters or providing an amount of 0. These invoices allow the payee
|
||||
to specify the amount of satoshis they wish to send.`,
|
||||
ArgsUsage: "hash [amt]",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "memo",
|
||||
Usage: "a description of the payment to attach along " +
|
||||
"with the invoice (default=\"\")",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "amt",
|
||||
Usage: "the amt of satoshis in this invoice",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "description_hash",
|
||||
Usage: "SHA-256 hash of the description of the payment. " +
|
||||
"Used if the purpose of payment cannot naturally " +
|
||||
"fit within the memo. If provided this will be " +
|
||||
"used instead of the description(memo) field in " +
|
||||
"the encoded invoice.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "fallback_addr",
|
||||
Usage: "fallback on-chain address that can be used in " +
|
||||
"case the lightning payment fails",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "expiry",
|
||||
Usage: "the invoice's expiry time in seconds. If not " +
|
||||
"specified, an expiry of 3600 seconds (1 hour) " +
|
||||
"is implied.",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "private",
|
||||
Usage: "encode routing hints in the invoice with " +
|
||||
"private channels in order to assist the " +
|
||||
"payer in reaching you",
|
||||
},
|
||||
},
|
||||
Action: actionDecorator(addHoldInvoice),
|
||||
}
|
||||
|
||||
func addHoldInvoice(ctx *cli.Context) error {
|
||||
var (
|
||||
descHash []byte
|
||||
amt int64
|
||||
err error
|
||||
)
|
||||
|
||||
client, cleanUp := getInvoicesClient(ctx)
|
||||
defer cleanUp()
|
||||
|
||||
args := ctx.Args()
|
||||
if ctx.NArg() == 0 {
|
||||
cli.ShowCommandHelp(ctx, "addholdinvoice")
|
||||
return nil
|
||||
}
|
||||
|
||||
hash, err := hex.DecodeString(args.First())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse hash: %v", err)
|
||||
}
|
||||
|
||||
args = args.Tail()
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("amt"):
|
||||
amt = ctx.Int64("amt")
|
||||
case args.Present():
|
||||
amt, err = strconv.ParseInt(args.First(), 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to decode amt argument: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse preimage: %v", err)
|
||||
}
|
||||
|
||||
descHash, err = hex.DecodeString(ctx.String("description_hash"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse description_hash: %v", err)
|
||||
}
|
||||
|
||||
invoice := &invoicesrpc.AddHoldInvoiceRequest{
|
||||
Memo: ctx.String("memo"),
|
||||
Hash: hash,
|
||||
Value: amt,
|
||||
DescriptionHash: descHash,
|
||||
FallbackAddr: ctx.String("fallback_addr"),
|
||||
Expiry: ctx.Int64("expiry"),
|
||||
Private: ctx.Bool("private"),
|
||||
}
|
||||
|
||||
resp, err := client.AddHoldInvoice(context.Background(), invoice)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printJSON(struct {
|
||||
PayReq string `json:"pay_req"`
|
||||
}{
|
||||
PayReq: resp.PaymentRequest,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/sweep"
|
||||
@ -137,10 +137,9 @@ type ChainArbitratorConfig struct {
|
||||
// Sweeper allows resolvers to sweep their final outputs.
|
||||
Sweeper *sweep.UtxoSweeper
|
||||
|
||||
// SettleInvoice attempts to settle an existing invoice on-chain with
|
||||
// the given payment hash. ErrInvoiceNotFound is returned if an invoice
|
||||
// is not found.
|
||||
SettleInvoice func(lntypes.Hash, lnwire.MilliSatoshi) error
|
||||
// Registry is the invoice database that is used by resolvers to lookup
|
||||
// preimages and settle invoices.
|
||||
Registry *invoices.InvoiceRegistry
|
||||
|
||||
// NotifyClosedChannel is a function closure that the ChainArbitrator
|
||||
// will use to notify the ChannelNotifier about a newly closed channel.
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
@ -177,9 +176,6 @@ func createTestChannelArbitrator(log ArbitratorLog) (*ChannelArbitrator,
|
||||
*lnwallet.IncomingHtlcResolution, uint32) error {
|
||||
return nil
|
||||
},
|
||||
SettleInvoice: func(lntypes.Hash, lnwire.MilliSatoshi) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// We'll use the resolvedChan to synchronize on call to
|
||||
|
@ -1,11 +1,13 @@
|
||||
package contractcourt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
)
|
||||
@ -70,11 +72,18 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
||||
return nil, h.Checkpoint(h)
|
||||
}
|
||||
|
||||
// applyPreimage is a helper function that will populate our internal
|
||||
// tryApplyPreimage is a helper function that will populate our internal
|
||||
// resolver with the preimage we learn of. This should be called once
|
||||
// the preimage is revealed so the inner resolver can properly complete
|
||||
// its duties.
|
||||
applyPreimage := func(preimage lntypes.Preimage) {
|
||||
// its duties. The boolean return value indicates whether the preimage
|
||||
// was properly applied.
|
||||
tryApplyPreimage := func(preimage lntypes.Preimage) bool {
|
||||
// Check to see if this preimage matches our htlc.
|
||||
if !preimage.Matches(h.payHash) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Update htlcResolution with the matching preimage.
|
||||
h.htlcResolution.Preimage = preimage
|
||||
|
||||
log.Infof("%T(%v): extracted preimage=%v from beacon!", h,
|
||||
@ -93,6 +102,8 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
||||
// preimage.
|
||||
h.htlcResolution.SignedSuccessTx.TxIn[0].Witness[3] = preimage[:]
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// If the HTLC hasn't expired yet, then we may still be able to claim
|
||||
@ -112,6 +123,26 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
||||
blockEpochs.Cancel()
|
||||
}()
|
||||
|
||||
// Create a buffered hodl chan to prevent deadlock.
|
||||
hodlChan := make(chan interface{}, 1)
|
||||
|
||||
// Notify registry that we are potentially settling as exit hop
|
||||
// on-chain, so that we will get a hodl event when a corresponding hodl
|
||||
// invoice is settled.
|
||||
event, err := h.Registry.NotifyExitHopHtlc(h.payHash, h.htlcAmt, hodlChan)
|
||||
if err != nil && err != channeldb.ErrInvoiceNotFound {
|
||||
return nil, err
|
||||
}
|
||||
defer h.Registry.HodlUnsubscribeAll(hodlChan)
|
||||
|
||||
// If the htlc can be settled directly, we can progress to the inner
|
||||
// resolver immediately.
|
||||
if event != nil && event.Preimage != nil {
|
||||
if tryApplyPreimage(*event.Preimage) {
|
||||
return &h.htlcSuccessResolver, nil
|
||||
}
|
||||
}
|
||||
|
||||
// With the epochs and preimage subscriptions initialized, we'll query
|
||||
// to see if we already know the preimage.
|
||||
preimage, ok := h.PreimageDB.LookupPreimage(h.payHash)
|
||||
@ -119,26 +150,35 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
||||
// If we do, then this means we can claim the HTLC! However,
|
||||
// we don't know how to ourselves, so we'll return our inner
|
||||
// resolver which has the knowledge to do so.
|
||||
applyPreimage(preimage)
|
||||
return &h.htlcSuccessResolver, nil
|
||||
if tryApplyPreimage(preimage) {
|
||||
return &h.htlcSuccessResolver, nil
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
|
||||
select {
|
||||
case preimage := <-preimageSubscription.WitnessUpdates:
|
||||
// If this isn't our preimage, then we'll continue
|
||||
// onwards.
|
||||
hash := preimage.Hash()
|
||||
preimageMatches := bytes.Equal(hash[:], h.payHash[:])
|
||||
if !preimageMatches {
|
||||
if !tryApplyPreimage(preimage) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Otherwise, we've learned of the preimage! We'll add
|
||||
// this information to our inner resolver, then return
|
||||
// it so it can continue contract resolution.
|
||||
applyPreimage(preimage)
|
||||
// We've learned of the preimage and this information
|
||||
// has been added to our inner resolver. We return it so
|
||||
// it can continue contract resolution.
|
||||
return &h.htlcSuccessResolver, nil
|
||||
|
||||
case hodlItem := <-hodlChan:
|
||||
hodlEvent := hodlItem.(invoices.HodlEvent)
|
||||
|
||||
// Only process settle events.
|
||||
if hodlEvent.Preimage == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if !tryApplyPreimage(*hodlEvent.Preimage) {
|
||||
continue
|
||||
}
|
||||
return &h.htlcSuccessResolver, nil
|
||||
|
||||
case newBlock, ok := <-blockEpochs.Epochs:
|
||||
|
@ -178,8 +178,13 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
|
||||
}
|
||||
|
||||
// With the HTLC claimed, we can attempt to settle its
|
||||
// corresponding invoice if we were the original destination.
|
||||
err = h.SettleInvoice(h.payHash, h.htlcAmt)
|
||||
// corresponding invoice if we were the original destination. As
|
||||
// the htlc is already settled at this point, we don't need to
|
||||
// read on the hodl channel.
|
||||
hodlChan := make(chan interface{}, 1)
|
||||
_, err = h.Registry.NotifyExitHopHtlc(
|
||||
h.payHash, h.htlcAmt, hodlChan,
|
||||
)
|
||||
if err != nil && err != channeldb.ErrInvoiceNotFound {
|
||||
log.Errorf("Unable to settle invoice with payment "+
|
||||
"hash %x: %v", h.payHash, err)
|
||||
@ -251,8 +256,11 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
|
||||
}
|
||||
|
||||
// With the HTLC claimed, we can attempt to settle its corresponding
|
||||
// invoice if we were the original destination.
|
||||
err = h.SettleInvoice(h.payHash, h.htlcAmt)
|
||||
// invoice if we were the original destination. As the htlc is already
|
||||
// settled at this point, we don't need to read on the hodl
|
||||
// channel.
|
||||
hodlChan := make(chan interface{}, 1)
|
||||
_, err = h.Registry.NotifyExitHopHtlc(h.payHash, h.htlcAmt, hodlChan)
|
||||
if err != nil && err != channeldb.ErrInvoiceNotFound {
|
||||
log.Errorf("Unable to settle invoice with payment "+
|
||||
"hash %x: %v", h.payHash, err)
|
||||
|
@ -3,6 +3,7 @@ package htlcswitch
|
||||
import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
@ -17,13 +18,23 @@ type InvoiceDatabase interface {
|
||||
// extended to us gives us enough time to settle as we prescribe.
|
||||
LookupInvoice(lntypes.Hash) (channeldb.Invoice, uint32, error)
|
||||
|
||||
// SettleInvoice attempts to mark an invoice corresponding to the
|
||||
// passed payment hash as fully settled.
|
||||
SettleInvoice(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi) error
|
||||
// NotifyExitHopHtlc attempts to mark an invoice as settled. If the
|
||||
// invoice is a debug invoice, then this method is a noop as debug
|
||||
// invoices are never fully settled. The return value describes how the
|
||||
// htlc should be resolved. If the htlc cannot be resolved immediately,
|
||||
// the resolution is sent on the passed in hodlChan later.
|
||||
NotifyExitHopHtlc(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi,
|
||||
hodlChan chan<- interface{}) (*invoices.HodlEvent, error)
|
||||
|
||||
// CancelInvoice attempts to cancel the invoice corresponding to the
|
||||
// passed payment hash.
|
||||
CancelInvoice(payHash lntypes.Hash) error
|
||||
|
||||
// SettleHodlInvoice settles a hold invoice.
|
||||
SettleHodlInvoice(preimage lntypes.Preimage) error
|
||||
|
||||
// HodlUnsubscribeAll unsubscribes from all hodl events.
|
||||
HodlUnsubscribeAll(subscriber chan<- interface{})
|
||||
}
|
||||
|
||||
// ChannelLink is an interface which represents the subsystem for managing the
|
||||
|
@ -16,10 +16,12 @@ import (
|
||||
"github.com/lightningnetwork/lnd/contractcourt"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/queue"
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
)
|
||||
|
||||
@ -344,10 +346,24 @@ type channelLink struct {
|
||||
|
||||
sync.RWMutex
|
||||
|
||||
// hodlQueue is used to receive exit hop htlc resolutions from invoice
|
||||
// registry.
|
||||
hodlQueue *queue.ConcurrentQueue
|
||||
|
||||
// hodlMap stores a list of htlc data structs per hash. It allows
|
||||
// resolving those htlcs when we receive a message on hodlQueue.
|
||||
hodlMap map[lntypes.Hash][]hodlHtlc
|
||||
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
}
|
||||
|
||||
// hodlHtlc contains htlc data that is required for resolution.
|
||||
type hodlHtlc struct {
|
||||
pd *lnwallet.PaymentDescriptor
|
||||
obfuscator ErrorEncrypter
|
||||
}
|
||||
|
||||
// NewChannelLink creates a new instance of a ChannelLink given a configuration
|
||||
// and active channel that will be used to verify/apply updates to.
|
||||
func NewChannelLink(cfg ChannelLinkConfig,
|
||||
@ -361,6 +377,8 @@ func NewChannelLink(cfg ChannelLinkConfig,
|
||||
logCommitTimer: time.NewTimer(300 * time.Millisecond),
|
||||
overflowQueue: newPacketQueue(input.MaxHTLCNumber / 2),
|
||||
htlcUpdates: make(chan []channeldb.HTLC),
|
||||
hodlMap: make(map[lntypes.Hash][]hodlHtlc),
|
||||
hodlQueue: queue.NewConcurrentQueue(10),
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
@ -384,6 +402,7 @@ func (l *channelLink) Start() error {
|
||||
|
||||
l.mailBox.ResetMessages()
|
||||
l.overflowQueue.Start()
|
||||
l.hodlQueue.Start()
|
||||
|
||||
// Before launching the htlcManager messages, revert any circuits that
|
||||
// were marked open in the switch's circuit map, but did not make it
|
||||
@ -449,12 +468,17 @@ func (l *channelLink) Stop() {
|
||||
|
||||
log.Infof("ChannelLink(%v) is stopping", l)
|
||||
|
||||
// As the link is stopping, we are no longer interested in hodl events
|
||||
// coming from the invoice registry.
|
||||
l.cfg.Registry.HodlUnsubscribeAll(l.hodlQueue.ChanIn())
|
||||
|
||||
if l.cfg.ChainEvents.Cancel != nil {
|
||||
l.cfg.ChainEvents.Cancel()
|
||||
}
|
||||
|
||||
l.updateFeeTimer.Stop()
|
||||
l.overflowQueue.Stop()
|
||||
l.hodlQueue.Stop()
|
||||
|
||||
close(l.quit)
|
||||
l.wg.Wait()
|
||||
@ -1058,12 +1082,119 @@ out:
|
||||
case msg := <-l.upstream:
|
||||
l.handleUpstreamMsg(msg)
|
||||
|
||||
// A hodl event is received. This means that we now have a
|
||||
// resolution for a previously accepted htlc.
|
||||
case hodlItem := <-l.hodlQueue.ChanOut():
|
||||
hodlEvent := hodlItem.(invoices.HodlEvent)
|
||||
err := l.processHodlQueue(hodlEvent)
|
||||
if err != nil {
|
||||
l.fail(LinkFailureError{code: ErrInternalError},
|
||||
fmt.Sprintf("process hodl queue: %v",
|
||||
err.Error()),
|
||||
)
|
||||
break out
|
||||
}
|
||||
|
||||
case <-l.quit:
|
||||
break out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// processHodlQueue processes a received hodl event and continues reading from
|
||||
// the hodl queue until no more events remain. When this function returns
|
||||
// without an error, the commit tx should be updated.
|
||||
func (l *channelLink) processHodlQueue(firstHodlEvent invoices.HodlEvent) error {
|
||||
// Try to read all waiting resolution messages, so that they can all be
|
||||
// processed in a single commitment tx update.
|
||||
hodlEvent := firstHodlEvent
|
||||
loop:
|
||||
for {
|
||||
if err := l.processHodlMapEvent(hodlEvent); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
select {
|
||||
case item := <-l.hodlQueue.ChanOut():
|
||||
hodlEvent = item.(invoices.HodlEvent)
|
||||
default:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
// Update the commitment tx.
|
||||
if err := l.updateCommitTx(); err != nil {
|
||||
return fmt.Errorf("unable to update commitment: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// processHodlMapEvent resolves stored hodl htlcs based using the information in
|
||||
// hodlEvent.
|
||||
func (l *channelLink) processHodlMapEvent(hodlEvent invoices.HodlEvent) error {
|
||||
// Lookup all hodl htlcs that can be failed or settled with this event.
|
||||
// The hodl htlc must be present in the map.
|
||||
hash := hodlEvent.Hash
|
||||
hodlHtlcs, ok := l.hodlMap[hash]
|
||||
if !ok {
|
||||
return fmt.Errorf("hodl htlc not found: %v", hash)
|
||||
}
|
||||
|
||||
if err := l.processHodlEvent(hodlEvent, hodlHtlcs...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Clean up hodl map.
|
||||
delete(l.hodlMap, hash)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// processHodlEvent applies a received hodl event to the provided htlc. When
|
||||
// this function returns without an error, the commit tx should be updated.
|
||||
func (l *channelLink) processHodlEvent(hodlEvent invoices.HodlEvent,
|
||||
htlcs ...hodlHtlc) error {
|
||||
|
||||
hash := hodlEvent.Hash
|
||||
if hodlEvent.Preimage == nil {
|
||||
l.debugf("Received hodl cancel event for %v", hash)
|
||||
} else {
|
||||
l.debugf("Received hodl settle event for %v", hash)
|
||||
}
|
||||
|
||||
// Determine required action for the resolution.
|
||||
var hodlAction func(htlc hodlHtlc) error
|
||||
if hodlEvent.Preimage != nil {
|
||||
hodlAction = func(htlc hodlHtlc) error {
|
||||
return l.settleHTLC(
|
||||
*hodlEvent.Preimage, htlc.pd.HtlcIndex,
|
||||
htlc.pd.SourceRef,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
hodlAction = func(htlc hodlHtlc) error {
|
||||
failure := lnwire.NewFailUnknownPaymentHash(
|
||||
htlc.pd.Amount,
|
||||
)
|
||||
l.sendHTLCError(
|
||||
htlc.pd.HtlcIndex, failure, htlc.obfuscator,
|
||||
htlc.pd.SourceRef,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Apply action for all htlcs matching this hash.
|
||||
for _, htlc := range htlcs {
|
||||
if err := hodlAction(htlc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// randomFeeUpdateTimeout returns a random timeout between the bounds defined
|
||||
// within the link's configuration that will be used to determine when the link
|
||||
// should propose an update to its commitment fee rate.
|
||||
@ -2354,228 +2485,20 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
|
||||
fwdInfo := chanIterator.ForwardingInstructions()
|
||||
switch fwdInfo.NextHop {
|
||||
case exitHop:
|
||||
// If hodl.ExitSettle is requested, we will not validate
|
||||
// the final hop's ADD, nor will we settle the
|
||||
// corresponding invoice or respond with the preimage.
|
||||
if l.cfg.DebugHTLC &&
|
||||
l.cfg.HodlMask.Active(hodl.ExitSettle) {
|
||||
l.warnf(hodl.ExitSettle.Warning())
|
||||
continue
|
||||
}
|
||||
|
||||
// First, we'll check the expiry of the HTLC itself
|
||||
// against, the current block height. If the timeout is
|
||||
// too soon, then we'll reject the HTLC.
|
||||
if pd.Timeout-expiryGraceDelta <= heightNow {
|
||||
log.Errorf("htlc(%x) has an expiry that's too "+
|
||||
"soon: expiry=%v, best_height=%v",
|
||||
pd.RHash[:], pd.Timeout, heightNow)
|
||||
|
||||
failure := lnwire.FailFinalExpiryTooSoon{}
|
||||
l.sendHTLCError(
|
||||
pd.HtlcIndex, &failure, obfuscator, pd.SourceRef,
|
||||
)
|
||||
needUpdate = true
|
||||
continue
|
||||
}
|
||||
|
||||
// We're the designated payment destination. Therefore
|
||||
// we attempt to see if we have an invoice locally
|
||||
// which'll allow us to settle this htlc.
|
||||
invoiceHash := lntypes.Hash(pd.RHash)
|
||||
invoice, minCltvDelta, err := l.cfg.Registry.LookupInvoice(
|
||||
invoiceHash,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("unable to query invoice registry: "+
|
||||
" %v", err)
|
||||
failure := lnwire.NewFailUnknownPaymentHash(
|
||||
pd.Amount,
|
||||
)
|
||||
l.sendHTLCError(
|
||||
pd.HtlcIndex, failure, obfuscator, pd.SourceRef,
|
||||
)
|
||||
|
||||
needUpdate = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Reject htlcs for canceled invoices.
|
||||
if invoice.Terms.State == channeldb.ContractCanceled {
|
||||
l.errorf("Rejecting htlc due to canceled " +
|
||||
"invoice")
|
||||
|
||||
failure := lnwire.NewFailUnknownPaymentHash(
|
||||
pd.Amount,
|
||||
)
|
||||
l.sendHTLCError(
|
||||
pd.HtlcIndex, failure, obfuscator,
|
||||
pd.SourceRef,
|
||||
)
|
||||
|
||||
needUpdate = true
|
||||
continue
|
||||
}
|
||||
|
||||
// If the invoice is already settled, we choose to
|
||||
// accept the payment to simplify failure recovery.
|
||||
//
|
||||
// NOTE: Though our recovery and forwarding logic is
|
||||
// predominately batched, settling invoices happens
|
||||
// iteratively. We may reject one of two payments
|
||||
// for the same rhash at first, but then restart and
|
||||
// reject both after seeing that the invoice has been
|
||||
// settled. Without any record of which one settles
|
||||
// first, it is ambiguous as to which one actually
|
||||
// settled the invoice. Thus, by accepting all
|
||||
// payments, we eliminate the race condition that can
|
||||
// lead to this inconsistency.
|
||||
//
|
||||
// TODO(conner): track ownership of settlements to
|
||||
// properly recover from failures? or add batch invoice
|
||||
// settlement
|
||||
if invoice.Terms.State != channeldb.ContractOpen {
|
||||
log.Warnf("Accepting duplicate payment for "+
|
||||
"hash=%x", pd.RHash[:])
|
||||
}
|
||||
|
||||
// If we're not currently in debug mode, and the
|
||||
// extended htlc doesn't meet the value requested, then
|
||||
// we'll fail the htlc. Otherwise, we settle this htlc
|
||||
// within our local state update log, then send the
|
||||
// update entry to the remote party.
|
||||
//
|
||||
// NOTE: We make an exception when the value requested
|
||||
// by the invoice is zero. This means the invoice
|
||||
// allows the payee to specify the amount of satoshis
|
||||
// they wish to send. So since we expect the htlc to
|
||||
// have a different amount, we should not fail.
|
||||
if !l.cfg.DebugHTLC && invoice.Terms.Value > 0 &&
|
||||
pd.Amount < invoice.Terms.Value {
|
||||
|
||||
log.Errorf("rejecting htlc due to incorrect "+
|
||||
"amount: expected %v, received %v",
|
||||
invoice.Terms.Value, pd.Amount)
|
||||
|
||||
failure := lnwire.NewFailUnknownPaymentHash(
|
||||
pd.Amount,
|
||||
)
|
||||
l.sendHTLCError(
|
||||
pd.HtlcIndex, failure, obfuscator, pd.SourceRef,
|
||||
)
|
||||
|
||||
needUpdate = true
|
||||
continue
|
||||
}
|
||||
|
||||
// As we're the exit hop, we'll double check the
|
||||
// hop-payload included in the HTLC to ensure that it
|
||||
// was crafted correctly by the sender and matches the
|
||||
// HTLC we were extended.
|
||||
//
|
||||
// NOTE: We make an exception when the value requested
|
||||
// by the invoice is zero. This means the invoice
|
||||
// allows the payee to specify the amount of satoshis
|
||||
// they wish to send. So since we expect the htlc to
|
||||
// have a different amount, we should not fail.
|
||||
if !l.cfg.DebugHTLC && invoice.Terms.Value > 0 &&
|
||||
fwdInfo.AmountToForward < invoice.Terms.Value {
|
||||
|
||||
log.Errorf("Onion payload of incoming htlc(%x) "+
|
||||
"has incorrect value: expected %v, "+
|
||||
"got %v", pd.RHash, invoice.Terms.Value,
|
||||
fwdInfo.AmountToForward)
|
||||
|
||||
failure := lnwire.NewFailUnknownPaymentHash(
|
||||
pd.Amount,
|
||||
)
|
||||
l.sendHTLCError(
|
||||
pd.HtlcIndex, failure, obfuscator, pd.SourceRef,
|
||||
)
|
||||
|
||||
needUpdate = true
|
||||
continue
|
||||
}
|
||||
|
||||
// We'll also ensure that our time-lock value has been
|
||||
// computed correctly.
|
||||
expectedHeight := heightNow + minCltvDelta
|
||||
switch {
|
||||
case !l.cfg.DebugHTLC && pd.Timeout < expectedHeight:
|
||||
log.Errorf("Incoming htlc(%x) has an "+
|
||||
"expiration that is too soon: "+
|
||||
"expected at least %v, got %v",
|
||||
pd.RHash[:], expectedHeight, pd.Timeout)
|
||||
|
||||
failure := lnwire.FailFinalExpiryTooSoon{}
|
||||
l.sendHTLCError(
|
||||
pd.HtlcIndex, failure, obfuscator,
|
||||
pd.SourceRef,
|
||||
)
|
||||
|
||||
needUpdate = true
|
||||
continue
|
||||
|
||||
case !l.cfg.DebugHTLC && pd.Timeout != fwdInfo.OutgoingCTLV:
|
||||
log.Errorf("HTLC(%x) has incorrect "+
|
||||
"time-lock: expected %v, got %v",
|
||||
pd.RHash[:], pd.Timeout,
|
||||
fwdInfo.OutgoingCTLV)
|
||||
|
||||
failure := lnwire.NewFinalIncorrectCltvExpiry(
|
||||
fwdInfo.OutgoingCTLV,
|
||||
)
|
||||
l.sendHTLCError(
|
||||
pd.HtlcIndex, failure, obfuscator, pd.SourceRef,
|
||||
)
|
||||
|
||||
needUpdate = true
|
||||
continue
|
||||
}
|
||||
|
||||
preimage := invoice.Terms.PaymentPreimage
|
||||
err = l.channel.SettleHTLC(
|
||||
preimage, pd.HtlcIndex, pd.SourceRef, nil, nil,
|
||||
updated, err := l.processExitHop(
|
||||
pd, obfuscator, fwdInfo, heightNow,
|
||||
)
|
||||
if err != nil {
|
||||
l.fail(LinkFailureError{code: ErrInternalError},
|
||||
"unable to settle htlc: %v", err)
|
||||
err.Error(),
|
||||
)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Notify the invoiceRegistry of the invoices we just
|
||||
// settled (with the amount accepted at settle time)
|
||||
// with this latest commitment update.
|
||||
err = l.cfg.Registry.SettleInvoice(
|
||||
invoiceHash, pd.Amount,
|
||||
)
|
||||
if err != nil {
|
||||
l.fail(LinkFailureError{code: ErrInternalError},
|
||||
"unable to settle invoice: %v", err)
|
||||
return false
|
||||
if updated {
|
||||
needUpdate = true
|
||||
}
|
||||
|
||||
l.infof("settling %x as exit hop", pd.RHash)
|
||||
|
||||
// If the link is in hodl.BogusSettle mode, replace the
|
||||
// preimage with a fake one before sending it to the
|
||||
// peer.
|
||||
if l.cfg.DebugHTLC &&
|
||||
l.cfg.HodlMask.Active(hodl.BogusSettle) {
|
||||
l.warnf(hodl.BogusSettle.Warning())
|
||||
preimage = [32]byte{}
|
||||
copy(preimage[:], bytes.Repeat([]byte{2}, 32))
|
||||
}
|
||||
|
||||
// HTLC was successfully settled locally send
|
||||
// notification about it remote peer.
|
||||
l.cfg.Peer.SendMessage(false, &lnwire.UpdateFulfillHTLC{
|
||||
ChanID: l.ChanID(),
|
||||
ID: pd.HtlcIndex,
|
||||
PaymentPreimage: preimage,
|
||||
})
|
||||
needUpdate = true
|
||||
|
||||
// There are additional channels left within this route. So
|
||||
// we'll simply do some forwarding package book-keeping.
|
||||
default:
|
||||
@ -2733,6 +2656,208 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
|
||||
return needUpdate
|
||||
}
|
||||
|
||||
// processExitHop handles an htlc for which this link is the exit hop. It
|
||||
// returns a boolean indicating whether the commitment tx needs an update.
|
||||
func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
|
||||
obfuscator ErrorEncrypter, fwdInfo ForwardingInfo, heightNow uint32) (
|
||||
bool, error) {
|
||||
|
||||
// If hodl.ExitSettle is requested, we will not validate the final hop's
|
||||
// ADD, nor will we settle the corresponding invoice or respond with the
|
||||
// preimage.
|
||||
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.ExitSettle) {
|
||||
l.warnf(hodl.ExitSettle.Warning())
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// First, we'll check the expiry of the HTLC itself against, the current
|
||||
// block height. If the timeout is too soon, then we'll reject the HTLC.
|
||||
if pd.Timeout-expiryGraceDelta <= heightNow {
|
||||
log.Errorf("htlc(%x) has an expiry that's too soon: expiry=%v"+
|
||||
", best_height=%v", pd.RHash[:], pd.Timeout, heightNow)
|
||||
|
||||
failure := lnwire.NewFinalExpiryTooSoon()
|
||||
l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// We're the designated payment destination. Therefore we attempt to
|
||||
// see if we have an invoice locally which'll allow us to settle this
|
||||
// htlc.
|
||||
//
|
||||
// Only the immutable data from LookupInvoice is used, because otherwise
|
||||
// a race condition may be created with concurrent writes to the invoice
|
||||
// registry. For example: cancelation of an invoice.
|
||||
invoiceHash := lntypes.Hash(pd.RHash)
|
||||
invoice, minCltvDelta, err := l.cfg.Registry.LookupInvoice(invoiceHash)
|
||||
if err != nil {
|
||||
log.Errorf("unable to query invoice registry: %v", err)
|
||||
failure := lnwire.NewFailUnknownPaymentHash(pd.Amount)
|
||||
l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// If the invoice is already settled, we choose to accept the payment to
|
||||
// simplify failure recovery.
|
||||
//
|
||||
// NOTE: Though our recovery and forwarding logic is predominately
|
||||
// batched, settling invoices happens iteratively. We may reject one of
|
||||
// two payments for the same rhash at first, but then restart and reject
|
||||
// both after seeing that the invoice has been settled. Without any
|
||||
// record of which one settles first, it is ambiguous as to which one
|
||||
// actually settled the invoice. Thus, by accepting all payments, we
|
||||
// eliminate the race condition that can lead to this inconsistency.
|
||||
//
|
||||
// TODO(conner): track ownership of settlements to properly recover from
|
||||
// failures? or add batch invoice settlement
|
||||
//
|
||||
// TODO(joostjager): The log statement below is not always accurate, as
|
||||
// the invoice may have been canceled after the LookupInvoice call.
|
||||
// Leaving it as is for now, because fixing this would involve changing
|
||||
// the signature of InvoiceRegistry.SettleInvoice just because of this
|
||||
// log statement.
|
||||
if invoice.Terms.State == channeldb.ContractSettled {
|
||||
log.Warnf("Accepting duplicate payment for hash=%x",
|
||||
pd.RHash[:])
|
||||
}
|
||||
|
||||
// If we're not currently in debug mode, and the extended htlc doesn't
|
||||
// meet the value requested, then we'll fail the htlc. Otherwise, we
|
||||
// settle this htlc within our local state update log, then send the
|
||||
// update entry to the remote party.
|
||||
//
|
||||
// NOTE: We make an exception when the value requested by the invoice is
|
||||
// zero. This means the invoice allows the payee to specify the amount
|
||||
// of satoshis they wish to send. So since we expect the htlc to have a
|
||||
// different amount, we should not fail.
|
||||
if !l.cfg.DebugHTLC && invoice.Terms.Value > 0 &&
|
||||
pd.Amount < invoice.Terms.Value {
|
||||
|
||||
log.Errorf("rejecting htlc due to incorrect amount: expected "+
|
||||
"%v, received %v", invoice.Terms.Value, pd.Amount)
|
||||
|
||||
failure := lnwire.NewFailUnknownPaymentHash(pd.Amount)
|
||||
l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// As we're the exit hop, we'll double check the hop-payload included in
|
||||
// the HTLC to ensure that it was crafted correctly by the sender and
|
||||
// matches the HTLC we were extended.
|
||||
//
|
||||
// NOTE: We make an exception when the value requested by the invoice is
|
||||
// zero. This means the invoice allows the payee to specify the amount
|
||||
// of satoshis they wish to send. So since we expect the htlc to have a
|
||||
// different amount, we should not fail.
|
||||
if !l.cfg.DebugHTLC && invoice.Terms.Value > 0 &&
|
||||
fwdInfo.AmountToForward < invoice.Terms.Value {
|
||||
|
||||
log.Errorf("Onion payload of incoming htlc(%x) has incorrect "+
|
||||
"value: expected %v, got %v", pd.RHash,
|
||||
invoice.Terms.Value, fwdInfo.AmountToForward)
|
||||
|
||||
failure := lnwire.NewFailUnknownPaymentHash(pd.Amount)
|
||||
l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// We'll also ensure that our time-lock value has been computed
|
||||
// correctly.
|
||||
expectedHeight := heightNow + minCltvDelta
|
||||
switch {
|
||||
case !l.cfg.DebugHTLC && pd.Timeout < expectedHeight:
|
||||
log.Errorf("Incoming htlc(%x) has an expiration that is too "+
|
||||
"soon: expected at least %v, got %v",
|
||||
pd.RHash[:], expectedHeight, pd.Timeout)
|
||||
|
||||
failure := lnwire.FailFinalExpiryTooSoon{}
|
||||
l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef)
|
||||
|
||||
return true, nil
|
||||
|
||||
case !l.cfg.DebugHTLC && pd.Timeout != fwdInfo.OutgoingCTLV:
|
||||
log.Errorf("HTLC(%x) has incorrect time-lock: expected %v, "+
|
||||
"got %v", pd.RHash[:], pd.Timeout, fwdInfo.OutgoingCTLV)
|
||||
|
||||
failure := lnwire.NewFinalIncorrectCltvExpiry(
|
||||
fwdInfo.OutgoingCTLV,
|
||||
)
|
||||
l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Notify the invoiceRegistry of the exit hop htlc. If we crash right
|
||||
// after this, this code will be re-executed after restart. We will
|
||||
// receive back a resolution event.
|
||||
event, err := l.cfg.Registry.NotifyExitHopHtlc(
|
||||
invoiceHash, pd.Amount, l.hodlQueue.ChanIn(),
|
||||
)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Create a hodlHtlc struct and decide either resolved now or later.
|
||||
htlc := hodlHtlc{
|
||||
pd: pd,
|
||||
obfuscator: obfuscator,
|
||||
}
|
||||
|
||||
if event == nil {
|
||||
// Save payment descriptor for future reference.
|
||||
hodlHtlcs := l.hodlMap[invoiceHash]
|
||||
l.hodlMap[invoiceHash] = append(hodlHtlcs, htlc)
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Process the received resolution.
|
||||
err = l.processHodlEvent(*event, htlc)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// settleHTLC settles the HTLC on the channel.
|
||||
func (l *channelLink) settleHTLC(preimage lntypes.Preimage, htlcIndex uint64,
|
||||
sourceRef *channeldb.AddRef) error {
|
||||
|
||||
hash := preimage.Hash()
|
||||
|
||||
l.infof("settling htlc %v as exit hop", hash)
|
||||
|
||||
err := l.channel.SettleHTLC(
|
||||
preimage, htlcIndex, sourceRef, nil, nil,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to settle htlc: %v", err)
|
||||
}
|
||||
|
||||
// If the link is in hodl.BogusSettle mode, replace the preimage with a
|
||||
// fake one before sending it to the peer.
|
||||
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.BogusSettle) {
|
||||
l.warnf(hodl.BogusSettle.Warning())
|
||||
preimage = [32]byte{}
|
||||
copy(preimage[:], bytes.Repeat([]byte{2}, 32))
|
||||
}
|
||||
|
||||
// HTLC was successfully settled locally send notification about it
|
||||
// remote peer.
|
||||
l.cfg.Peer.SendMessage(false, &lnwire.UpdateFulfillHTLC{
|
||||
ChanID: l.ChanID(),
|
||||
ID: htlcIndex,
|
||||
PaymentPreimage: preimage,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// forwardBatch forwards the given htlcPackets to the switch, and waits on the
|
||||
// err chan for the individual responses. This method is intended to be spawned
|
||||
// as a goroutine so the responses can be handled in the background.
|
||||
|
@ -1066,22 +1066,15 @@ func TestChannelLinkMultiHopUnknownPaymentHash(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Generate payment: invoice and htlc.
|
||||
invoice, htlc, err := generatePayment(amount, htlcAmt, totalTimelock,
|
||||
// Generate payment invoice and htlc, but don't add this invoice to the
|
||||
// receiver registry. This should trigger an unknown payment hash
|
||||
// failure.
|
||||
_, htlc, err := generatePayment(amount, htlcAmt, totalTimelock,
|
||||
blob)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// We need to have wrong rhash for that reason we should change the
|
||||
// preimage. Inverse first byte by xoring with 0xff.
|
||||
invoice.Terms.PaymentPreimage[0] ^= byte(255)
|
||||
|
||||
// Check who is last in the route and add invoice to server registry.
|
||||
if err := n.carolServer.registry.AddInvoice(*invoice); err != nil {
|
||||
t.Fatalf("unable to add invoice in carol registry: %v", err)
|
||||
}
|
||||
|
||||
// Send payment and expose err channel.
|
||||
_, err = n.aliceServer.htlcSwitch.SendHTLC(
|
||||
n.firstBobChannelLink.ShortChanID(), htlc,
|
||||
@ -1095,12 +1088,6 @@ func TestChannelLinkMultiHopUnknownPaymentHash(t *testing.T) {
|
||||
// Wait for Alice to receive the revocation.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Check that alice invoice wasn't settled and bandwidth of htlc
|
||||
// links hasn't been changed.
|
||||
if invoice.Terms.State == channeldb.ContractSettled {
|
||||
t.Fatal("alice invoice was settled")
|
||||
}
|
||||
|
||||
if n.aliceChannelLink.Bandwidth() != aliceBandwidthBefore {
|
||||
t.Fatal("the bandwidth of alice channel link which handles " +
|
||||
"alice->bob channel should be the same")
|
||||
@ -2059,7 +2046,9 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
|
||||
|
||||
// We must add the invoice to the registry, such that Alice expects
|
||||
// this payment.
|
||||
err = coreLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(*invoice)
|
||||
err = coreLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(
|
||||
*invoice, htlc.PaymentHash,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to add invoice to registry: %v", err)
|
||||
}
|
||||
@ -2161,7 +2150,9 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create payment: %v", err)
|
||||
}
|
||||
err = coreLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(*invoice)
|
||||
err = coreLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(
|
||||
*invoice, htlc.PaymentHash,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to add invoice to registry: %v", err)
|
||||
}
|
||||
@ -3817,7 +3808,9 @@ func TestChannelLinkAcceptDuplicatePayment(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := n.carolServer.registry.AddInvoice(*invoice); err != nil {
|
||||
|
||||
err = n.carolServer.registry.AddInvoice(*invoice, htlc.PaymentHash)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to add invoice in carol registry: %v", err)
|
||||
}
|
||||
|
||||
@ -4195,7 +4188,8 @@ func generateHtlc(t *testing.T, coreLink *channelLink,
|
||||
// We must add the invoice to the registry, such that Alice
|
||||
// expects this payment.
|
||||
err := coreLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(
|
||||
*invoice)
|
||||
*invoice, htlc.PaymentHash,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to add invoice to registry: %v", err)
|
||||
}
|
||||
@ -5595,3 +5589,169 @@ func TestChannelLinkCanceledInvoice(t *testing.T) {
|
||||
t.Fatalf("expected unknown payment hash, but got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type hodlInvoiceTestCtx struct {
|
||||
n *twoHopNetwork
|
||||
startBandwidthAlice lnwire.MilliSatoshi
|
||||
startBandwidthBob lnwire.MilliSatoshi
|
||||
hash lntypes.Hash
|
||||
preimage lntypes.Preimage
|
||||
amount lnwire.MilliSatoshi
|
||||
errChan chan error
|
||||
|
||||
cleanUp func()
|
||||
}
|
||||
|
||||
func newHodlInvoiceTestCtx(t *testing.T) (*hodlInvoiceTestCtx, error) {
|
||||
// Setup a alice-bob network.
|
||||
aliceChannel, bobChannel, cleanUp, err := createTwoClusterChannels(
|
||||
btcutil.SatoshiPerBitcoin*3,
|
||||
btcutil.SatoshiPerBitcoin*5,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create channel: %v", err)
|
||||
}
|
||||
|
||||
n := newTwoHopNetwork(t, aliceChannel, bobChannel, testStartingHeight)
|
||||
if err := n.start(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
aliceBandwidthBefore := n.aliceChannelLink.Bandwidth()
|
||||
bobBandwidthBefore := n.bobChannelLink.Bandwidth()
|
||||
|
||||
debug := false
|
||||
if debug {
|
||||
// Log message that alice receives.
|
||||
n.aliceServer.intersect(
|
||||
createLogFunc("alice", n.aliceChannelLink.ChanID()),
|
||||
)
|
||||
|
||||
// Log message that bob receives.
|
||||
n.bobServer.intersect(
|
||||
createLogFunc("bob", n.bobChannelLink.ChanID()),
|
||||
)
|
||||
}
|
||||
|
||||
amount := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin)
|
||||
htlcAmt, totalTimelock, hops := generateHops(
|
||||
amount, testStartingHeight, n.bobChannelLink,
|
||||
)
|
||||
|
||||
// Generate hold invoice preimage.
|
||||
r, err := generateRandomBytes(sha256.Size)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
preimage, err := lntypes.MakePreimage(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hash := preimage.Hash()
|
||||
|
||||
// Have alice pay the hodl invoice, wait for bob's commitment state to
|
||||
// be updated and the invoice state to be updated.
|
||||
receiver := n.bobServer
|
||||
receiver.registry.settleChan = make(chan lntypes.Hash)
|
||||
firstHop := n.bobChannelLink.ShortChanID()
|
||||
errChan := n.makeHoldPayment(
|
||||
n.aliceServer, receiver, firstHop, hops, amount, htlcAmt,
|
||||
totalTimelock, preimage,
|
||||
)
|
||||
|
||||
select {
|
||||
case err := <-errChan:
|
||||
t.Fatalf("no payment result expected: %v", err)
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("timeout")
|
||||
case h := <-receiver.registry.settleChan:
|
||||
if hash != h {
|
||||
t.Fatal("unexpect invoice settled")
|
||||
}
|
||||
}
|
||||
|
||||
return &hodlInvoiceTestCtx{
|
||||
n: n,
|
||||
startBandwidthAlice: aliceBandwidthBefore,
|
||||
startBandwidthBob: bobBandwidthBefore,
|
||||
preimage: preimage,
|
||||
hash: hash,
|
||||
amount: amount,
|
||||
errChan: errChan,
|
||||
|
||||
cleanUp: func() {
|
||||
cleanUp()
|
||||
n.stop()
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TestChannelLinkHoldInvoiceSettle asserts that a hodl invoice can be settled.
|
||||
func TestChannelLinkHoldInvoiceSettle(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx, err := newHodlInvoiceTestCtx(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ctx.cleanUp()
|
||||
|
||||
err = ctx.n.bobServer.registry.SettleHodlInvoice(ctx.preimage)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Wait for payment to succeed.
|
||||
select {
|
||||
case err := <-ctx.errChan:
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("timeout")
|
||||
}
|
||||
|
||||
// Wait for Bob to receive the revocation.
|
||||
if ctx.startBandwidthAlice-ctx.amount !=
|
||||
ctx.n.aliceChannelLink.Bandwidth() {
|
||||
|
||||
t.Fatal("alice bandwidth should have decrease on payment " +
|
||||
"amount")
|
||||
}
|
||||
|
||||
if ctx.startBandwidthBob+ctx.amount !=
|
||||
ctx.n.bobChannelLink.Bandwidth() {
|
||||
|
||||
t.Fatalf("bob bandwidth isn't match: expected %v, got %v",
|
||||
ctx.startBandwidthBob+ctx.amount,
|
||||
ctx.n.bobChannelLink.Bandwidth())
|
||||
}
|
||||
}
|
||||
|
||||
// TestChannelLinkHoldInvoiceSettle asserts that a hodl invoice can be canceled.
|
||||
func TestChannelLinkHoldInvoiceCancel(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx, err := newHodlInvoiceTestCtx(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ctx.cleanUp()
|
||||
|
||||
err = ctx.n.bobServer.registry.CancelInvoice(ctx.hash)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Wait for payment to succeed.
|
||||
select {
|
||||
case err := <-ctx.errChan:
|
||||
if !strings.Contains(err.Error(),
|
||||
lnwire.CodeUnknownPaymentHash.String()) {
|
||||
|
||||
t.Fatal("expected unknown payment hash")
|
||||
}
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("timeout")
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
@ -23,6 +24,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/contractcourt"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
@ -131,6 +133,7 @@ type mockServer struct {
|
||||
htlcSwitch *Switch
|
||||
|
||||
registry *mockInvoiceRegistry
|
||||
pCache *mockPreimageCache
|
||||
interceptorFuncs []messageInterceptor
|
||||
}
|
||||
|
||||
@ -186,19 +189,24 @@ func newMockServer(t testing.TB, name string, startingHeight uint32,
|
||||
h := sha256.Sum256([]byte(name))
|
||||
copy(id[:], h[:])
|
||||
|
||||
pCache := newMockPreimageCache()
|
||||
|
||||
htlcSwitch, err := initSwitchWithDB(startingHeight, db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
registry := newMockRegistry(defaultDelta)
|
||||
|
||||
return &mockServer{
|
||||
t: t,
|
||||
id: id,
|
||||
name: name,
|
||||
messages: make(chan lnwire.Message, 3000),
|
||||
quit: make(chan struct{}),
|
||||
registry: newMockRegistry(defaultDelta),
|
||||
registry: registry,
|
||||
htlcSwitch: htlcSwitch,
|
||||
pCache: pCache,
|
||||
interceptorFuncs: make([]messageInterceptor, 0),
|
||||
}, nil
|
||||
}
|
||||
@ -697,82 +705,92 @@ func (f *mockChannelLink) UpdateShortChanID() (lnwire.ShortChannelID, error) {
|
||||
|
||||
var _ ChannelLink = (*mockChannelLink)(nil)
|
||||
|
||||
type mockInvoiceRegistry struct {
|
||||
sync.Mutex
|
||||
func newDB() (*channeldb.DB, func(), error) {
|
||||
// First, create a temporary directory to be used for the duration of
|
||||
// this test.
|
||||
tempDirName, err := ioutil.TempDir("", "channeldb")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
invoices map[lntypes.Hash]channeldb.Invoice
|
||||
finalDelta uint32
|
||||
// Next, create channeldb for the first time.
|
||||
cdb, err := channeldb.Open(tempDirName)
|
||||
if err != nil {
|
||||
os.RemoveAll(tempDirName)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
cleanUp := func() {
|
||||
cdb.Close()
|
||||
os.RemoveAll(tempDirName)
|
||||
}
|
||||
|
||||
return cdb, cleanUp, nil
|
||||
}
|
||||
|
||||
type mockInvoiceRegistry struct {
|
||||
settleChan chan lntypes.Hash
|
||||
|
||||
registry *invoices.InvoiceRegistry
|
||||
|
||||
cleanup func()
|
||||
}
|
||||
|
||||
func newMockRegistry(minDelta uint32) *mockInvoiceRegistry {
|
||||
cdb, cleanup, err := newDB()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
decodeExpiry := func(invoice string) (uint32, error) {
|
||||
return 3, nil
|
||||
}
|
||||
|
||||
registry := invoices.NewRegistry(cdb, decodeExpiry)
|
||||
registry.Start()
|
||||
|
||||
return &mockInvoiceRegistry{
|
||||
finalDelta: minDelta,
|
||||
invoices: make(map[lntypes.Hash]channeldb.Invoice),
|
||||
registry: registry,
|
||||
cleanup: cleanup,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *mockInvoiceRegistry) LookupInvoice(rHash lntypes.Hash) (channeldb.Invoice, uint32, error) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
invoice, ok := i.invoices[rHash]
|
||||
if !ok {
|
||||
return channeldb.Invoice{}, 0, fmt.Errorf("can't find mock "+
|
||||
"invoice: %x", rHash[:])
|
||||
}
|
||||
|
||||
return invoice, i.finalDelta, nil
|
||||
return i.registry.LookupInvoice(rHash)
|
||||
}
|
||||
|
||||
func (i *mockInvoiceRegistry) SettleInvoice(rhash lntypes.Hash,
|
||||
amt lnwire.MilliSatoshi) error {
|
||||
func (i *mockInvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error {
|
||||
return i.registry.SettleHodlInvoice(preimage)
|
||||
}
|
||||
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
func (i *mockInvoiceRegistry) NotifyExitHopHtlc(rhash lntypes.Hash,
|
||||
amt lnwire.MilliSatoshi, hodlChan chan<- interface{}) (
|
||||
*invoices.HodlEvent, error) {
|
||||
|
||||
invoice, ok := i.invoices[rhash]
|
||||
if !ok {
|
||||
return fmt.Errorf("can't find mock invoice: %x", rhash[:])
|
||||
event, err := i.registry.NotifyExitHopHtlc(rhash, amt, hodlChan)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if i.settleChan != nil {
|
||||
i.settleChan <- rhash
|
||||
}
|
||||
|
||||
if invoice.Terms.State == channeldb.ContractSettled {
|
||||
return nil
|
||||
}
|
||||
|
||||
invoice.Terms.State = channeldb.ContractSettled
|
||||
invoice.AmtPaid = amt
|
||||
i.invoices[rhash] = invoice
|
||||
|
||||
return nil
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (i *mockInvoiceRegistry) CancelInvoice(payHash lntypes.Hash) error {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
invoice, ok := i.invoices[payHash]
|
||||
if !ok {
|
||||
return channeldb.ErrInvoiceNotFound
|
||||
}
|
||||
|
||||
if invoice.Terms.State == channeldb.ContractCanceled {
|
||||
return nil
|
||||
}
|
||||
|
||||
invoice.Terms.State = channeldb.ContractCanceled
|
||||
i.invoices[payHash] = invoice
|
||||
|
||||
return nil
|
||||
return i.registry.CancelInvoice(payHash)
|
||||
}
|
||||
|
||||
func (i *mockInvoiceRegistry) AddInvoice(invoice channeldb.Invoice) error {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
func (i *mockInvoiceRegistry) AddInvoice(invoice channeldb.Invoice,
|
||||
paymentHash lntypes.Hash) error {
|
||||
|
||||
rhash := invoice.Terms.PaymentPreimage.Hash()
|
||||
i.invoices[rhash] = invoice
|
||||
_, err := i.registry.AddInvoice(&invoice, paymentHash)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
func (i *mockInvoiceRegistry) HodlUnsubscribeAll(subscriber chan<- interface{}) {
|
||||
i.registry.HodlUnsubscribeAll(subscriber)
|
||||
}
|
||||
|
||||
var _ InvoiceDatabase = (*mockInvoiceRegistry)(nil)
|
||||
|
@ -520,19 +520,12 @@ func getChanID(msg lnwire.Message) (lnwire.ChannelID, error) {
|
||||
return chanID, nil
|
||||
}
|
||||
|
||||
// generatePayment generates the htlc add request by given path blob and
|
||||
// generateHoldPayment generates the htlc add request by given path blob and
|
||||
// invoice which should be added by destination peer.
|
||||
func generatePayment(invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32,
|
||||
blob [lnwire.OnionPacketSize]byte) (*channeldb.Invoice, *lnwire.UpdateAddHTLC, error) {
|
||||
|
||||
var preimage [sha256.Size]byte
|
||||
r, err := generateRandomBytes(sha256.Size)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
copy(preimage[:], r)
|
||||
|
||||
rhash := fastsha256.Sum256(preimage[:])
|
||||
func generatePaymentWithPreimage(invoiceAmt, htlcAmt lnwire.MilliSatoshi,
|
||||
timelock uint32, blob [lnwire.OnionPacketSize]byte,
|
||||
preimage, rhash [32]byte) (*channeldb.Invoice, *lnwire.UpdateAddHTLC,
|
||||
error) {
|
||||
|
||||
invoice := &channeldb.Invoice{
|
||||
CreationDate: time.Now(),
|
||||
@ -552,6 +545,24 @@ func generatePayment(invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32,
|
||||
return invoice, htlc, nil
|
||||
}
|
||||
|
||||
// generatePayment generates the htlc add request by given path blob and
|
||||
// invoice which should be added by destination peer.
|
||||
func generatePayment(invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32,
|
||||
blob [lnwire.OnionPacketSize]byte) (*channeldb.Invoice, *lnwire.UpdateAddHTLC, error) {
|
||||
|
||||
var preimage [sha256.Size]byte
|
||||
r, err := generateRandomBytes(sha256.Size)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
copy(preimage[:], r)
|
||||
|
||||
rhash := fastsha256.Sum256(preimage[:])
|
||||
return generatePaymentWithPreimage(
|
||||
invoiceAmt, htlcAmt, timelock, blob, preimage, rhash,
|
||||
)
|
||||
}
|
||||
|
||||
// generateRoute generates the path blob by given array of peers.
|
||||
func generateRoute(hops ...ForwardingInfo) ([lnwire.OnionPacketSize]byte, error) {
|
||||
var blob [lnwire.OnionPacketSize]byte
|
||||
@ -742,7 +753,8 @@ func preparePayment(sendingPeer, receivingPeer lnpeer.Peer,
|
||||
}
|
||||
|
||||
// Check who is last in the route and add invoice to server registry.
|
||||
if err := receiver.registry.AddInvoice(*invoice); err != nil {
|
||||
hash := invoice.Terms.PaymentPreimage.Hash()
|
||||
if err := receiver.registry.AddInvoice(*invoice, hash); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@ -971,7 +983,6 @@ type hopNetwork struct {
|
||||
feeEstimator *mockFeeEstimator
|
||||
globalPolicy ForwardingPolicy
|
||||
obfuscator ErrorEncrypter
|
||||
pCache *mockPreimageCache
|
||||
|
||||
defaultDelta uint32
|
||||
}
|
||||
@ -979,8 +990,6 @@ type hopNetwork struct {
|
||||
func newHopNetwork() *hopNetwork {
|
||||
defaultDelta := uint32(6)
|
||||
|
||||
pCache := newMockPreimageCache()
|
||||
|
||||
globalPolicy := ForwardingPolicy{
|
||||
MinHTLC: lnwire.NewMSatFromSatoshis(5),
|
||||
BaseFee: lnwire.NewMSatFromSatoshis(1),
|
||||
@ -997,7 +1006,6 @@ func newHopNetwork() *hopNetwork {
|
||||
feeEstimator: feeEstimator,
|
||||
globalPolicy: globalPolicy,
|
||||
obfuscator: obfuscator,
|
||||
pCache: pCache,
|
||||
defaultDelta: defaultDelta,
|
||||
}
|
||||
}
|
||||
@ -1028,7 +1036,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer,
|
||||
FetchLastChannelUpdate: mockGetChanUpdateMessage,
|
||||
Registry: server.registry,
|
||||
FeeEstimator: h.feeEstimator,
|
||||
PreimageCache: h.pCache,
|
||||
PreimageCache: server.pCache,
|
||||
UpdateContractSignals: func(*contractcourt.ContractSignals) error {
|
||||
return nil
|
||||
},
|
||||
@ -1136,7 +1144,7 @@ func newTwoHopNetwork(t testing.TB,
|
||||
}
|
||||
}
|
||||
|
||||
// start starts the three hop network alice,bob,carol servers.
|
||||
// start starts the two hop network alice,bob servers.
|
||||
func (n *twoHopNetwork) start() error {
|
||||
if err := n.aliceServer.Start(); err != nil {
|
||||
return err
|
||||
@ -1166,3 +1174,48 @@ func (n *twoHopNetwork) stop() {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
func (n *twoHopNetwork) makeHoldPayment(sendingPeer, receivingPeer lnpeer.Peer,
|
||||
firstHop lnwire.ShortChannelID, hops []ForwardingInfo,
|
||||
invoiceAmt, htlcAmt lnwire.MilliSatoshi,
|
||||
timelock uint32, preimage lntypes.Preimage) chan error {
|
||||
|
||||
paymentErr := make(chan error, 1)
|
||||
|
||||
sender := sendingPeer.(*mockServer)
|
||||
receiver := receivingPeer.(*mockServer)
|
||||
|
||||
// Generate route convert it to blob, and return next destination for
|
||||
// htlc add request.
|
||||
blob, err := generateRoute(hops...)
|
||||
if err != nil {
|
||||
paymentErr <- err
|
||||
return paymentErr
|
||||
}
|
||||
|
||||
rhash := preimage.Hash()
|
||||
|
||||
// Generate payment: invoice and htlc.
|
||||
invoice, htlc, err := generatePaymentWithPreimage(invoiceAmt, htlcAmt, timelock, blob,
|
||||
channeldb.UnknownPreimage, rhash)
|
||||
if err != nil {
|
||||
paymentErr <- err
|
||||
return paymentErr
|
||||
}
|
||||
|
||||
// Check who is last in the route and add invoice to server registry.
|
||||
if err := receiver.registry.AddInvoice(*invoice, rhash); err != nil {
|
||||
paymentErr <- err
|
||||
return paymentErr
|
||||
}
|
||||
|
||||
// Send payment and expose err channel.
|
||||
go func() {
|
||||
_, err := sender.htlcSwitch.SendHTLC(
|
||||
firstHop, htlc, newMockDeobfuscator(),
|
||||
)
|
||||
paymentErr <- err
|
||||
}()
|
||||
|
||||
return paymentErr
|
||||
}
|
||||
|
@ -7,14 +7,12 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/queue"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -29,6 +27,14 @@ var (
|
||||
DebugHash = DebugPre.Hash()
|
||||
)
|
||||
|
||||
// HodlEvent describes how an htlc should be resolved. If HodlEvent.Preimage is
|
||||
// set, the event indicates a settle event. If Preimage is nil, it is a cancel
|
||||
// event.
|
||||
type HodlEvent struct {
|
||||
Preimage *lntypes.Preimage
|
||||
Hash lntypes.Hash
|
||||
}
|
||||
|
||||
// InvoiceRegistry is a central registry of all the outstanding invoices
|
||||
// created by the daemon. The registry is a thin wrapper around a map in order
|
||||
// to ensure that all updates/reads are thread safe.
|
||||
@ -52,7 +58,17 @@ type InvoiceRegistry struct {
|
||||
// that *all* nodes are able to fully settle.
|
||||
debugInvoices map[lntypes.Hash]*channeldb.Invoice
|
||||
|
||||
activeNetParams *chaincfg.Params
|
||||
// decodeFinalCltvExpiry is a function used to decode the final expiry
|
||||
// value from the payment request.
|
||||
decodeFinalCltvExpiry func(invoice string) (uint32, error)
|
||||
|
||||
// subscriptions is a map from a payment hash to a list of subscribers.
|
||||
// It is used for efficient notification of links.
|
||||
hodlSubscriptions map[lntypes.Hash]map[chan<- interface{}]struct{}
|
||||
|
||||
// reverseSubscriptions tracks hashes subscribed to per subscriber. This
|
||||
// is used to unsubscribe from all hashes efficiently.
|
||||
hodlReverseSubscriptions map[chan<- interface{}]map[lntypes.Hash]struct{}
|
||||
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
@ -62,8 +78,8 @@ type InvoiceRegistry struct {
|
||||
// wraps the persistent on-disk invoice storage with an additional in-memory
|
||||
// layer. The in-memory layer is in place such that debug invoices can be added
|
||||
// which are volatile yet available system wide within the daemon.
|
||||
func NewRegistry(cdb *channeldb.DB,
|
||||
activeNetParams *chaincfg.Params) *InvoiceRegistry {
|
||||
func NewRegistry(cdb *channeldb.DB, decodeFinalCltvExpiry func(invoice string) (
|
||||
uint32, error)) *InvoiceRegistry {
|
||||
|
||||
return &InvoiceRegistry{
|
||||
cdb: cdb,
|
||||
@ -74,7 +90,9 @@ func NewRegistry(cdb *channeldb.DB,
|
||||
newSingleSubscriptions: make(chan *SingleInvoiceSubscription),
|
||||
subscriptionCancels: make(chan uint32),
|
||||
invoiceEvents: make(chan *invoiceEvent, 100),
|
||||
activeNetParams: activeNetParams,
|
||||
hodlSubscriptions: make(map[lntypes.Hash]map[chan<- interface{}]struct{}),
|
||||
hodlReverseSubscriptions: make(map[chan<- interface{}]map[lntypes.Hash]struct{}),
|
||||
decodeFinalCltvExpiry: decodeFinalCltvExpiry,
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
@ -163,8 +181,10 @@ func (i *InvoiceRegistry) invoiceEventNotifier() {
|
||||
// dispatch notifications to all registered clients.
|
||||
case event := <-i.invoiceEvents:
|
||||
// For backwards compatibility, do not notify all
|
||||
// invoice subscribers of cancel events
|
||||
if event.state != channeldb.ContractCanceled {
|
||||
// invoice subscribers of cancel and accept events.
|
||||
if event.state != channeldb.ContractCanceled &&
|
||||
event.state != channeldb.ContractAccepted {
|
||||
|
||||
i.dispatchToClients(event)
|
||||
}
|
||||
i.dispatchToSingleClients(event)
|
||||
@ -380,7 +400,8 @@ func (i *InvoiceRegistry) AddDebugInvoice(amt btcutil.Amount,
|
||||
// daemon add/forward HTLCs are able to obtain the proper preimage required for
|
||||
// redemption in the case that we're the final destination. We also return the
|
||||
// addIndex of the newly created invoice which monotonically increases for each
|
||||
// new invoice added.
|
||||
// new invoice added. A side effect of this function is that it also sets
|
||||
// AddIndex on the invoice argument.
|
||||
func (i *InvoiceRegistry) AddInvoice(invoice *channeldb.Invoice,
|
||||
paymentHash lntypes.Hash) (uint64, error) {
|
||||
|
||||
@ -391,7 +412,7 @@ func (i *InvoiceRegistry) AddInvoice(invoice *channeldb.Invoice,
|
||||
return spew.Sdump(invoice)
|
||||
}))
|
||||
|
||||
addIndex, err := i.cdb.AddInvoice(invoice)
|
||||
addIndex, err := i.cdb.AddInvoice(invoice, paymentHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -429,53 +450,110 @@ func (i *InvoiceRegistry) LookupInvoice(rHash lntypes.Hash) (channeldb.Invoice,
|
||||
return channeldb.Invoice{}, 0, err
|
||||
}
|
||||
|
||||
payReq, err := zpay32.Decode(
|
||||
string(invoice.PaymentRequest), i.activeNetParams,
|
||||
)
|
||||
expiry, err := i.decodeFinalCltvExpiry(string(invoice.PaymentRequest))
|
||||
if err != nil {
|
||||
return channeldb.Invoice{}, 0, err
|
||||
}
|
||||
|
||||
return invoice, uint32(payReq.MinFinalCLTVExpiry()), nil
|
||||
return invoice, expiry, nil
|
||||
}
|
||||
|
||||
// SettleInvoice attempts to mark an invoice as settled. If the invoice is a
|
||||
// NotifyExitHopHtlc attempts to mark an invoice as settled. If the invoice is a
|
||||
// debug invoice, then this method is a noop as debug invoices are never fully
|
||||
// settled.
|
||||
func (i *InvoiceRegistry) SettleInvoice(rHash lntypes.Hash,
|
||||
amtPaid lnwire.MilliSatoshi) error {
|
||||
// settled. The return value describes how the htlc should be resolved.
|
||||
//
|
||||
// When the preimage of the invoice is not yet known (hodl invoice), this
|
||||
// function moves the invoice to the accepted state. When SettleHoldInvoice is
|
||||
// called later, a resolution message will be send back to the caller via the
|
||||
// provided hodlChan. Invoice registry sends on this channel what action needs
|
||||
// to be taken on the htlc (settle or cancel). The caller needs to ensure that
|
||||
// the channel is either buffered or received on from another goroutine to
|
||||
// prevent deadlock.
|
||||
func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
|
||||
amtPaid lnwire.MilliSatoshi, hodlChan chan<- interface{}) (
|
||||
*HodlEvent, error) {
|
||||
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
log.Debugf("Settling invoice %x", rHash[:])
|
||||
|
||||
createEvent := func(preimage *lntypes.Preimage) *HodlEvent {
|
||||
return &HodlEvent{
|
||||
Hash: rHash,
|
||||
Preimage: preimage,
|
||||
}
|
||||
}
|
||||
|
||||
// First check the in-memory debug invoice index to see if this is an
|
||||
// existing invoice added for debugging.
|
||||
if _, ok := i.debugInvoices[rHash]; ok {
|
||||
// Debug invoices are never fully settled, so we simply return
|
||||
// immediately in this case.
|
||||
return nil
|
||||
if invoice, ok := i.debugInvoices[rHash]; ok {
|
||||
// Debug invoices are never fully settled, so we just settle the
|
||||
// htlc in this case.
|
||||
return createEvent(&invoice.Terms.PaymentPreimage), nil
|
||||
}
|
||||
|
||||
// If this isn't a debug invoice, then we'll attempt to settle an
|
||||
// invoice matching this rHash on disk (if one exists).
|
||||
invoice, err := i.cdb.SettleInvoice(rHash, amtPaid)
|
||||
invoice, err := i.cdb.AcceptOrSettleInvoice(rHash, amtPaid)
|
||||
switch err {
|
||||
|
||||
// Implement idempotency by returning success if the invoice was already
|
||||
// settled.
|
||||
if err == channeldb.ErrInvoiceAlreadySettled {
|
||||
log.Debugf("Invoice %v already settled", rHash)
|
||||
return nil
|
||||
// If invoice is already settled, settle htlc. This means we accept more
|
||||
// payments to the same invoice hash.
|
||||
case channeldb.ErrInvoiceAlreadySettled:
|
||||
return createEvent(&invoice.Terms.PaymentPreimage), nil
|
||||
|
||||
// If invoice is already canceled, cancel htlc.
|
||||
case channeldb.ErrInvoiceAlreadyCanceled:
|
||||
return createEvent(nil), nil
|
||||
|
||||
// If invoice is already accepted, add this htlc to the list of
|
||||
// subscribers.
|
||||
case channeldb.ErrInvoiceAlreadyAccepted:
|
||||
i.hodlSubscribe(hodlChan, rHash)
|
||||
return nil, nil
|
||||
|
||||
// If this call settled the invoice, settle the htlc. Otherwise
|
||||
// subscribe for a future hodl event.
|
||||
case nil:
|
||||
i.notifyClients(rHash, invoice, invoice.Terms.State)
|
||||
switch invoice.Terms.State {
|
||||
case channeldb.ContractSettled:
|
||||
return createEvent(&invoice.Terms.PaymentPreimage), nil
|
||||
case channeldb.ContractAccepted:
|
||||
// Subscribe to updates to this invoice.
|
||||
i.hodlSubscribe(hodlChan, rHash)
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected invoice state %v",
|
||||
invoice.Terms.State)
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// SettleHodlInvoice sets the preimage of a hodl invoice.
|
||||
func (i *InvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
invoice, err := i.cdb.SettleHoldInvoice(preimage)
|
||||
if err != nil {
|
||||
log.Errorf("Invoice SetPreimage %v: %v", preimage, err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Payment received: %v", spew.Sdump(invoice))
|
||||
hash := preimage.Hash()
|
||||
log.Infof("Notifying clients of set preimage to %v",
|
||||
invoice.Terms.PaymentPreimage)
|
||||
|
||||
i.notifyClients(rHash, invoice, channeldb.ContractSettled)
|
||||
i.notifyHodlSubscribers(HodlEvent{
|
||||
Hash: hash,
|
||||
Preimage: &preimage,
|
||||
})
|
||||
i.notifyClients(hash, invoice, invoice.Terms.State)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -496,13 +574,14 @@ func (i *InvoiceRegistry) CancelInvoice(payHash lntypes.Hash) error {
|
||||
log.Debugf("Invoice %v already canceled", payHash)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Invoice %v canceled", payHash)
|
||||
|
||||
i.notifyHodlSubscribers(HodlEvent{
|
||||
Hash: payHash,
|
||||
})
|
||||
i.notifyClients(payHash, invoice, channeldb.ContractCanceled)
|
||||
|
||||
return nil
|
||||
@ -754,3 +833,60 @@ func (i *InvoiceRegistry) SubscribeSingleInvoice(
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// notifyHodlSubscribers sends out the hodl event to all current subscribers.
|
||||
func (i *InvoiceRegistry) notifyHodlSubscribers(hodlEvent HodlEvent) {
|
||||
subscribers, ok := i.hodlSubscriptions[hodlEvent.Hash]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Notify all interested subscribers and remove subscription from both
|
||||
// maps. The subscription can be removed as there only ever will be a
|
||||
// single resolution for each hash.
|
||||
for subscriber := range subscribers {
|
||||
select {
|
||||
case subscriber <- hodlEvent:
|
||||
case <-i.quit:
|
||||
return
|
||||
}
|
||||
|
||||
delete(i.hodlReverseSubscriptions[subscriber], hodlEvent.Hash)
|
||||
}
|
||||
|
||||
delete(i.hodlSubscriptions, hodlEvent.Hash)
|
||||
}
|
||||
|
||||
// hodlSubscribe adds a new invoice subscription.
|
||||
func (i *InvoiceRegistry) hodlSubscribe(subscriber chan<- interface{},
|
||||
hash lntypes.Hash) {
|
||||
|
||||
log.Debugf("Hodl subscribe for %v", hash)
|
||||
|
||||
subscriptions, ok := i.hodlSubscriptions[hash]
|
||||
if !ok {
|
||||
subscriptions = make(map[chan<- interface{}]struct{})
|
||||
i.hodlSubscriptions[hash] = subscriptions
|
||||
}
|
||||
subscriptions[subscriber] = struct{}{}
|
||||
|
||||
reverseSubscriptions, ok := i.hodlReverseSubscriptions[subscriber]
|
||||
if !ok {
|
||||
reverseSubscriptions = make(map[lntypes.Hash]struct{})
|
||||
i.hodlReverseSubscriptions[subscriber] = reverseSubscriptions
|
||||
}
|
||||
reverseSubscriptions[hash] = struct{}{}
|
||||
}
|
||||
|
||||
// HodlUnsubscribeAll cancels the subscription.
|
||||
func (i *InvoiceRegistry) HodlUnsubscribeAll(subscriber chan<- interface{}) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
hashes := i.hodlReverseSubscriptions[subscriber]
|
||||
for hash := range hashes {
|
||||
delete(i.hodlSubscriptions[hash], subscriber)
|
||||
}
|
||||
|
||||
delete(i.hodlReverseSubscriptions, subscriber)
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -28,22 +29,49 @@ var (
|
||||
testPayReq = "lnbc500u1pwywxzwpp5nd2u9xzq02t0tuf2654as7vma42lwkcjptx4yzfq0umq4swpa7cqdqqcqzysmlpc9ewnydr8rr8dnltyxphdyf6mcqrsd6dml8zajtyhwe6a45d807kxtmzayuf0hh2d9tn478ecxkecdg7c5g85pntupug5kakm7xcpn63zqk"
|
||||
)
|
||||
|
||||
// TestSettleInvoice tests settling of an invoice and related notifications.
|
||||
func TestSettleInvoice(t *testing.T) {
|
||||
func decodeExpiry(payReq string) (uint32, error) {
|
||||
invoice, err := zpay32.Decode(payReq, &chaincfg.MainNetParams)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(invoice.MinFinalCLTVExpiry()), nil
|
||||
}
|
||||
|
||||
var (
|
||||
testInvoice = &channeldb.Invoice{
|
||||
Terms: channeldb.ContractTerm{
|
||||
PaymentPreimage: preimage,
|
||||
Value: lnwire.MilliSatoshi(100000),
|
||||
},
|
||||
PaymentRequest: []byte(testPayReq),
|
||||
}
|
||||
)
|
||||
|
||||
func newTestContext(t *testing.T) (*InvoiceRegistry, func()) {
|
||||
cdb, cleanup, err := newDB()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
// Instantiate and start the invoice registry.
|
||||
registry := NewRegistry(cdb, &chaincfg.MainNetParams)
|
||||
registry := NewRegistry(cdb, decodeExpiry)
|
||||
|
||||
err = registry.Start()
|
||||
if err != nil {
|
||||
cleanup()
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer registry.Stop()
|
||||
|
||||
return registry, func() {
|
||||
registry.Stop()
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
// TestSettleInvoice tests settling of an invoice and related notifications.
|
||||
func TestSettleInvoice(t *testing.T) {
|
||||
registry, cleanup := newTestContext(t)
|
||||
defer cleanup()
|
||||
|
||||
allSubscriptions := registry.SubscribeNotifications(0, 0)
|
||||
defer allSubscriptions.Cancel()
|
||||
@ -57,15 +85,7 @@ func TestSettleInvoice(t *testing.T) {
|
||||
}
|
||||
|
||||
// Add the invoice.
|
||||
invoice := &channeldb.Invoice{
|
||||
Terms: channeldb.ContractTerm{
|
||||
PaymentPreimage: preimage,
|
||||
Value: lnwire.MilliSatoshi(100000),
|
||||
},
|
||||
PaymentRequest: []byte(testPayReq),
|
||||
}
|
||||
|
||||
addIdx, err := registry.AddInvoice(invoice, hash)
|
||||
addIdx, err := registry.AddInvoice(testInvoice, hash)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -97,9 +117,11 @@ func TestSettleInvoice(t *testing.T) {
|
||||
t.Fatal("no update received")
|
||||
}
|
||||
|
||||
hodlChan := make(chan interface{}, 1)
|
||||
|
||||
// Settle invoice with a slightly higher amount.
|
||||
amtPaid := lnwire.MilliSatoshi(100500)
|
||||
err = registry.SettleInvoice(hash, amtPaid)
|
||||
_, err = registry.NotifyExitHopHtlc(hash, amtPaid, hodlChan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -131,13 +153,13 @@ func TestSettleInvoice(t *testing.T) {
|
||||
}
|
||||
|
||||
// Try to settle again.
|
||||
err = registry.SettleInvoice(hash, amtPaid)
|
||||
_, err = registry.NotifyExitHopHtlc(hash, amtPaid, hodlChan)
|
||||
if err != nil {
|
||||
t.Fatal("expected duplicate settle to succeed")
|
||||
}
|
||||
|
||||
// Try to settle again with a different amount.
|
||||
err = registry.SettleInvoice(hash, amtPaid+600)
|
||||
_, err = registry.NotifyExitHopHtlc(hash, amtPaid+600, hodlChan)
|
||||
if err != nil {
|
||||
t.Fatal("expected duplicate settle to succeed")
|
||||
}
|
||||
@ -156,30 +178,25 @@ func TestSettleInvoice(t *testing.T) {
|
||||
if err != channeldb.ErrInvoiceAlreadySettled {
|
||||
t.Fatal("expected cancelation of a settled invoice to fail")
|
||||
}
|
||||
|
||||
// As this is a direct sette, we expect nothing on the hodl chan.
|
||||
select {
|
||||
case <-hodlChan:
|
||||
t.Fatal("unexpected event")
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// TestCancelInvoice tests cancelation of an invoice and related notifications.
|
||||
func TestCancelInvoice(t *testing.T) {
|
||||
cdb, cleanup, err := newDB()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
registry, cleanup := newTestContext(t)
|
||||
defer cleanup()
|
||||
|
||||
// Instantiate and start the invoice registry.
|
||||
registry := NewRegistry(cdb, &chaincfg.MainNetParams)
|
||||
|
||||
err = registry.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer registry.Stop()
|
||||
|
||||
allSubscriptions := registry.SubscribeNotifications(0, 0)
|
||||
defer allSubscriptions.Cancel()
|
||||
|
||||
// Try to cancel the not yet existing invoice. This should fail.
|
||||
err = registry.CancelInvoice(hash)
|
||||
err := registry.CancelInvoice(hash)
|
||||
if err != channeldb.ErrInvoiceNotFound {
|
||||
t.Fatalf("expected ErrInvoiceNotFound, but got %v", err)
|
||||
}
|
||||
@ -194,14 +211,7 @@ func TestCancelInvoice(t *testing.T) {
|
||||
|
||||
// Add the invoice.
|
||||
amt := lnwire.MilliSatoshi(100000)
|
||||
invoice := &channeldb.Invoice{
|
||||
Terms: channeldb.ContractTerm{
|
||||
PaymentPreimage: preimage,
|
||||
Value: amt,
|
||||
},
|
||||
}
|
||||
|
||||
_, err = registry.AddInvoice(invoice, hash)
|
||||
_, err = registry.AddInvoice(testInvoice, hash)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -261,10 +271,144 @@ func TestCancelInvoice(t *testing.T) {
|
||||
t.Fatal("expected cancelation of a canceled invoice to succeed")
|
||||
}
|
||||
|
||||
// Try to settle. This should not be possible.
|
||||
err = registry.SettleInvoice(hash, amt)
|
||||
if err != channeldb.ErrInvoiceAlreadyCanceled {
|
||||
t.Fatal("expected settlement of a canceled invoice to fail")
|
||||
// Notify arrival of a new htlc paying to this invoice. This should
|
||||
// succeed.
|
||||
hodlChan := make(chan interface{})
|
||||
event, err := registry.NotifyExitHopHtlc(hash, amt, hodlChan)
|
||||
if err != nil {
|
||||
t.Fatal("expected settlement of a canceled invoice to succeed")
|
||||
}
|
||||
|
||||
if event.Preimage != nil {
|
||||
t.Fatal("expected cancel hodl event")
|
||||
}
|
||||
}
|
||||
|
||||
// TestHoldInvoice tests settling of a hold invoice and related notifications.
|
||||
func TestHoldInvoice(t *testing.T) {
|
||||
defer timeout(t)()
|
||||
|
||||
cdb, cleanup, err := newDB()
|
||||
defer cleanup()
|
||||
|
||||
// Instantiate and start the invoice registry.
|
||||
registry := NewRegistry(cdb, decodeExpiry)
|
||||
|
||||
err = registry.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer registry.Stop()
|
||||
|
||||
allSubscriptions := registry.SubscribeNotifications(0, 0)
|
||||
defer allSubscriptions.Cancel()
|
||||
|
||||
// Subscribe to the not yet existing invoice.
|
||||
subscription := registry.SubscribeSingleInvoice(hash)
|
||||
defer subscription.Cancel()
|
||||
|
||||
if subscription.hash != hash {
|
||||
t.Fatalf("expected subscription for provided hash")
|
||||
}
|
||||
|
||||
// Add the invoice.
|
||||
invoice := &channeldb.Invoice{
|
||||
Terms: channeldb.ContractTerm{
|
||||
PaymentPreimage: channeldb.UnknownPreimage,
|
||||
Value: lnwire.MilliSatoshi(100000),
|
||||
},
|
||||
}
|
||||
|
||||
_, err = registry.AddInvoice(invoice, hash)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// We expect the open state to be sent to the single invoice subscriber.
|
||||
update := <-subscription.Updates
|
||||
if update.Terms.State != channeldb.ContractOpen {
|
||||
t.Fatalf("expected state ContractOpen, but got %v",
|
||||
update.Terms.State)
|
||||
}
|
||||
|
||||
// We expect a new invoice notification to be sent out.
|
||||
newInvoice := <-allSubscriptions.NewInvoices
|
||||
if newInvoice.Terms.State != channeldb.ContractOpen {
|
||||
t.Fatalf("expected state ContractOpen, but got %v",
|
||||
newInvoice.Terms.State)
|
||||
}
|
||||
|
||||
// Use slightly higher amount for accept/settle.
|
||||
amtPaid := lnwire.MilliSatoshi(100500)
|
||||
|
||||
hodlChan := make(chan interface{}, 1)
|
||||
|
||||
// NotifyExitHopHtlc without a preimage present in the invoice registry
|
||||
// should be possible.
|
||||
event, err := registry.NotifyExitHopHtlc(hash, amtPaid, hodlChan)
|
||||
if err != nil {
|
||||
t.Fatalf("expected settle to succeed but got %v", err)
|
||||
}
|
||||
if event != nil {
|
||||
t.Fatalf("unexpect direct settle")
|
||||
}
|
||||
|
||||
// Test idempotency.
|
||||
event, err = registry.NotifyExitHopHtlc(hash, amtPaid, hodlChan)
|
||||
if err != nil {
|
||||
t.Fatalf("expected settle to succeed but got %v", err)
|
||||
}
|
||||
if event != nil {
|
||||
t.Fatalf("unexpect direct settle")
|
||||
}
|
||||
|
||||
// We expect the accepted state to be sent to the single invoice
|
||||
// subscriber. For all invoice subscribers, we don't expect an update.
|
||||
// Those only get notified on settle.
|
||||
update = <-subscription.Updates
|
||||
if update.Terms.State != channeldb.ContractAccepted {
|
||||
t.Fatalf("expected state ContractAccepted, but got %v",
|
||||
update.Terms.State)
|
||||
}
|
||||
if update.AmtPaid != amtPaid {
|
||||
t.Fatal("invoice AmtPaid incorrect")
|
||||
}
|
||||
|
||||
// Settling with preimage should succeed.
|
||||
err = registry.SettleHodlInvoice(preimage)
|
||||
if err != nil {
|
||||
t.Fatal("expected set preimage to succeed")
|
||||
}
|
||||
|
||||
hodlEvent := (<-hodlChan).(HodlEvent)
|
||||
if *hodlEvent.Preimage != preimage {
|
||||
t.Fatal("unexpected preimage in hodl event")
|
||||
}
|
||||
|
||||
// We expect a settled notification to be sent out for both all and
|
||||
// single invoice subscribers.
|
||||
settledInvoice := <-allSubscriptions.SettledInvoices
|
||||
if settledInvoice.Terms.State != channeldb.ContractSettled {
|
||||
t.Fatalf("expected state ContractSettled, but got %v",
|
||||
settledInvoice.Terms.State)
|
||||
}
|
||||
|
||||
update = <-subscription.Updates
|
||||
if update.Terms.State != channeldb.ContractSettled {
|
||||
t.Fatalf("expected state ContractSettled, but got %v",
|
||||
update.Terms.State)
|
||||
}
|
||||
|
||||
// Idempotency.
|
||||
err = registry.SettleHodlInvoice(preimage)
|
||||
if err != channeldb.ErrInvoiceAlreadySettled {
|
||||
t.Fatalf("expected ErrInvoiceAlreadySettled but got %v", err)
|
||||
}
|
||||
|
||||
// Try to cancel.
|
||||
err = registry.CancelInvoice(hash)
|
||||
if err == nil {
|
||||
t.Fatal("expected cancelation of a settled invoice to fail")
|
||||
}
|
||||
}
|
||||
|
||||
|
26
invoices/utils_test.go
Normal file
26
invoices/utils_test.go
Normal file
@ -0,0 +1,26 @@
|
||||
package invoices
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// timeout implements a test level timeout.
|
||||
func timeout(t *testing.T) func() {
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
|
||||
|
||||
panic("test timeout")
|
||||
case <-done:
|
||||
}
|
||||
}()
|
||||
|
||||
return func() {
|
||||
close(done)
|
||||
}
|
||||
}
|
416
lnrpc/invoicesrpc/addinvoice.go
Normal file
416
lnrpc/invoicesrpc/addinvoice.go
Normal file
@ -0,0 +1,416 @@
|
||||
package invoicesrpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/netann"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
// AddInvoiceConfig contains dependencies for invoice creation.
|
||||
type AddInvoiceConfig struct {
|
||||
// AddInvoice is called to add the invoice to the registry.
|
||||
AddInvoice func(invoice *channeldb.Invoice, paymentHash lntypes.Hash) (
|
||||
uint64, error)
|
||||
|
||||
// IsChannelActive is used to generate valid hop hints.
|
||||
IsChannelActive func(chanID lnwire.ChannelID) bool
|
||||
|
||||
// ChainParams are required to properly decode invoice payment requests
|
||||
// that are marshalled over rpc.
|
||||
ChainParams *chaincfg.Params
|
||||
|
||||
// NodeSigner is an implementation of the MessageSigner implementation
|
||||
// that's backed by the identity private key of the running lnd node.
|
||||
NodeSigner *netann.NodeSigner
|
||||
|
||||
// MaxPaymentMSat is the maximum allowed payment.
|
||||
MaxPaymentMSat lnwire.MilliSatoshi
|
||||
|
||||
// DefaultCLTVExpiry is the default invoice expiry if no values is
|
||||
// specified.
|
||||
DefaultCLTVExpiry uint32
|
||||
|
||||
// ChanDB is a global boltdb instance which is needed to access the
|
||||
// channel graph.
|
||||
ChanDB *channeldb.DB
|
||||
}
|
||||
|
||||
// AddInvoiceData contains the required data to create a new invoice.
|
||||
type AddInvoiceData struct {
|
||||
// An optional memo to attach along with the invoice. Used for record
|
||||
// keeping purposes for the invoice's creator, and will also be set in
|
||||
// the description field of the encoded payment request if the
|
||||
// description_hash field is not being used.
|
||||
Memo string
|
||||
|
||||
// Deprecated. An optional cryptographic receipt of payment which is not
|
||||
// implemented.
|
||||
Receipt []byte
|
||||
|
||||
// The preimage which will allow settling an incoming HTLC payable to
|
||||
// this preimage. If Preimage is set, Hash should be nil. If both
|
||||
// Preimage and Hash are nil, a random preimage is generated.
|
||||
Preimage *lntypes.Preimage
|
||||
|
||||
// The hash of the preimage. If Hash is set, Preimage should be nil.
|
||||
// This condition indicates that we have a 'hold invoice' for which the
|
||||
// htlc will be accepted and held until the preimage becomes known.
|
||||
Hash *lntypes.Hash
|
||||
|
||||
// The value of this invoice in satoshis.
|
||||
Value btcutil.Amount
|
||||
|
||||
// Hash (SHA-256) of a description of the payment. Used if the
|
||||
// description of payment (memo) is too long to naturally fit within the
|
||||
// description field of an encoded payment request.
|
||||
DescriptionHash []byte
|
||||
|
||||
// Payment request expiry time in seconds. Default is 3600 (1 hour).
|
||||
Expiry int64
|
||||
|
||||
// Fallback on-chain address.
|
||||
FallbackAddr string
|
||||
|
||||
// Delta to use for the time-lock of the CLTV extended to the final hop.
|
||||
CltvExpiry uint64
|
||||
|
||||
// Whether this invoice should include routing hints for private
|
||||
// channels.
|
||||
Private bool
|
||||
}
|
||||
|
||||
// AddInvoice attempts to add a new invoice to the invoice database. Any
|
||||
// duplicated invoices are rejected, therefore all invoices *must* have a
|
||||
// unique payment preimage.
|
||||
func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
|
||||
invoice *AddInvoiceData) (*lntypes.Hash, *channeldb.Invoice, error) {
|
||||
|
||||
var (
|
||||
paymentPreimage lntypes.Preimage
|
||||
paymentHash lntypes.Hash
|
||||
)
|
||||
|
||||
switch {
|
||||
|
||||
// Only either preimage or hash can be set.
|
||||
case invoice.Preimage != nil && invoice.Hash != nil:
|
||||
return nil, nil,
|
||||
errors.New("preimage and hash both set")
|
||||
|
||||
// Prevent the unknown preimage magic value from being used for a
|
||||
// regular invoice. This would cause the invoice the be handled as if it
|
||||
// was a hold invoice.
|
||||
case invoice.Preimage != nil &&
|
||||
*invoice.Preimage == channeldb.UnknownPreimage:
|
||||
|
||||
return nil, nil,
|
||||
fmt.Errorf("cannot use all zeroes as a preimage")
|
||||
|
||||
// Prevent the hash of the unknown preimage magic value to be used for a
|
||||
// hold invoice. This would make it impossible to settle the invoice,
|
||||
// because it would still be interpreted as not having a preimage.
|
||||
case invoice.Hash != nil &&
|
||||
*invoice.Hash == channeldb.UnknownPreimage.Hash():
|
||||
|
||||
return nil, nil,
|
||||
fmt.Errorf("cannot use hash of all zeroes preimage")
|
||||
|
||||
// If no hash or preimage is given, generate a random preimage.
|
||||
case invoice.Preimage == nil && invoice.Hash == nil:
|
||||
if _, err := rand.Read(paymentPreimage[:]); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
paymentHash = paymentPreimage.Hash()
|
||||
|
||||
// If just a hash is given, we create a hold invoice by setting the
|
||||
// preimage to unknown.
|
||||
case invoice.Preimage == nil && invoice.Hash != nil:
|
||||
paymentPreimage = channeldb.UnknownPreimage
|
||||
paymentHash = *invoice.Hash
|
||||
|
||||
// A specific preimage was supplied. Use that for the invoice.
|
||||
case invoice.Preimage != nil && invoice.Hash == nil:
|
||||
paymentPreimage = *invoice.Preimage
|
||||
paymentHash = invoice.Preimage.Hash()
|
||||
}
|
||||
|
||||
// The size of the memo, receipt and description hash attached must not
|
||||
// exceed the maximum values for either of the fields.
|
||||
if len(invoice.Memo) > channeldb.MaxMemoSize {
|
||||
return nil, nil, fmt.Errorf("memo too large: %v bytes "+
|
||||
"(maxsize=%v)", len(invoice.Memo), channeldb.MaxMemoSize)
|
||||
}
|
||||
if len(invoice.Receipt) > channeldb.MaxReceiptSize {
|
||||
return nil, nil, fmt.Errorf("receipt too large: %v bytes "+
|
||||
"(maxsize=%v)", len(invoice.Receipt), channeldb.MaxReceiptSize)
|
||||
}
|
||||
if len(invoice.DescriptionHash) > 0 && len(invoice.DescriptionHash) != 32 {
|
||||
return nil, nil, fmt.Errorf("description hash is %v bytes, must be %v",
|
||||
len(invoice.DescriptionHash), channeldb.MaxPaymentRequestSize)
|
||||
}
|
||||
|
||||
// The value of the invoice must not be negative.
|
||||
if invoice.Value < 0 {
|
||||
return nil, nil, fmt.Errorf("payments of negative value "+
|
||||
"are not allowed, value is %v", invoice.Value)
|
||||
}
|
||||
|
||||
amtMSat := lnwire.NewMSatFromSatoshis(invoice.Value)
|
||||
|
||||
// The value of the invoice must also not exceed the current soft-limit
|
||||
// on the largest payment within the network.
|
||||
if amtMSat > cfg.MaxPaymentMSat {
|
||||
return nil, nil, fmt.Errorf("payment of %v is too large, max "+
|
||||
"payment allowed is %v", invoice.Value,
|
||||
cfg.MaxPaymentMSat.ToSatoshis(),
|
||||
)
|
||||
}
|
||||
|
||||
// We also create an encoded payment request which allows the
|
||||
// caller to compactly send the invoice to the payer. We'll create a
|
||||
// list of options to be added to the encoded payment request. For now
|
||||
// we only support the required fields description/description_hash,
|
||||
// expiry, fallback address, and the amount field.
|
||||
var options []func(*zpay32.Invoice)
|
||||
|
||||
// We only include the amount in the invoice if it is greater than 0.
|
||||
// By not including the amount, we enable the creation of invoices that
|
||||
// allow the payee to specify the amount of satoshis they wish to send.
|
||||
if amtMSat > 0 {
|
||||
options = append(options, zpay32.Amount(amtMSat))
|
||||
}
|
||||
|
||||
// If specified, add a fallback address to the payment request.
|
||||
if len(invoice.FallbackAddr) > 0 {
|
||||
addr, err := btcutil.DecodeAddress(invoice.FallbackAddr,
|
||||
cfg.ChainParams)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("invalid fallback address: %v",
|
||||
err)
|
||||
}
|
||||
options = append(options, zpay32.FallbackAddr(addr))
|
||||
}
|
||||
|
||||
// If expiry is set, specify it. If it is not provided, no expiry time
|
||||
// will be explicitly added to this payment request, which will imply
|
||||
// the default 3600 seconds.
|
||||
if invoice.Expiry > 0 {
|
||||
|
||||
// We'll ensure that the specified expiry is restricted to sane
|
||||
// number of seconds. As a result, we'll reject an invoice with
|
||||
// an expiry greater than 1 year.
|
||||
maxExpiry := time.Hour * 24 * 365
|
||||
expSeconds := invoice.Expiry
|
||||
|
||||
if float64(expSeconds) > maxExpiry.Seconds() {
|
||||
return nil, nil, fmt.Errorf("expiry of %v seconds "+
|
||||
"greater than max expiry of %v seconds",
|
||||
float64(expSeconds), maxExpiry.Seconds())
|
||||
}
|
||||
|
||||
expiry := time.Duration(invoice.Expiry) * time.Second
|
||||
options = append(options, zpay32.Expiry(expiry))
|
||||
}
|
||||
|
||||
// If the description hash is set, then we add it do the list of options.
|
||||
// If not, use the memo field as the payment request description.
|
||||
if len(invoice.DescriptionHash) > 0 {
|
||||
var descHash [32]byte
|
||||
copy(descHash[:], invoice.DescriptionHash[:])
|
||||
options = append(options, zpay32.DescriptionHash(descHash))
|
||||
} else {
|
||||
// Use the memo field as the description. If this is not set
|
||||
// this will just be an empty string.
|
||||
options = append(options, zpay32.Description(invoice.Memo))
|
||||
}
|
||||
|
||||
// We'll use our current default CLTV value unless one was specified as
|
||||
// an option on the command line when creating an invoice.
|
||||
switch {
|
||||
case invoice.CltvExpiry > math.MaxUint16:
|
||||
return nil, nil, fmt.Errorf("CLTV delta of %v is too large, max "+
|
||||
"accepted is: %v", invoice.CltvExpiry, math.MaxUint16)
|
||||
case invoice.CltvExpiry != 0:
|
||||
options = append(options,
|
||||
zpay32.CLTVExpiry(invoice.CltvExpiry))
|
||||
default:
|
||||
// TODO(roasbeef): assumes set delta between versions
|
||||
defaultDelta := cfg.DefaultCLTVExpiry
|
||||
options = append(options, zpay32.CLTVExpiry(uint64(defaultDelta)))
|
||||
}
|
||||
|
||||
// If we were requested to include routing hints in the invoice, then
|
||||
// we'll fetch all of our available private channels and create routing
|
||||
// hints for them.
|
||||
if invoice.Private {
|
||||
openChannels, err := cfg.ChanDB.FetchAllChannels()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("could not fetch all channels")
|
||||
}
|
||||
|
||||
graph := cfg.ChanDB.ChannelGraph()
|
||||
|
||||
numHints := 0
|
||||
for _, channel := range openChannels {
|
||||
// We'll restrict the number of individual route hints
|
||||
// to 20 to avoid creating overly large invoices.
|
||||
if numHints > 20 {
|
||||
break
|
||||
}
|
||||
|
||||
// Since we're only interested in our private channels,
|
||||
// we'll skip public ones.
|
||||
isPublic := channel.ChannelFlags&lnwire.FFAnnounceChannel != 0
|
||||
if isPublic {
|
||||
continue
|
||||
}
|
||||
|
||||
// Make sure the counterparty has enough balance in the
|
||||
// channel for our amount. We do this in order to reduce
|
||||
// payment errors when attempting to use this channel
|
||||
// as a hint.
|
||||
chanPoint := lnwire.NewChanIDFromOutPoint(
|
||||
&channel.FundingOutpoint,
|
||||
)
|
||||
if amtMSat >= channel.LocalCommitment.RemoteBalance {
|
||||
log.Debugf("Skipping channel %v due to "+
|
||||
"not having enough remote balance",
|
||||
chanPoint)
|
||||
continue
|
||||
}
|
||||
|
||||
// Make sure the channel is active.
|
||||
if !cfg.IsChannelActive(chanPoint) {
|
||||
log.Debugf("Skipping channel %v due to not "+
|
||||
"being eligible to forward payments",
|
||||
chanPoint)
|
||||
continue
|
||||
}
|
||||
|
||||
// To ensure we don't leak unadvertised nodes, we'll
|
||||
// make sure our counterparty is publicly advertised
|
||||
// within the network. Otherwise, we'll end up leaking
|
||||
// information about nodes that intend to stay
|
||||
// unadvertised, like in the case of a node only having
|
||||
// private channels.
|
||||
var remotePub [33]byte
|
||||
copy(remotePub[:], channel.IdentityPub.SerializeCompressed())
|
||||
isRemoteNodePublic, err := graph.IsPublicNode(remotePub)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to determine if node %x "+
|
||||
"is advertised: %v", remotePub, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !isRemoteNodePublic {
|
||||
log.Debugf("Skipping channel %v due to "+
|
||||
"counterparty %x being unadvertised",
|
||||
chanPoint, remotePub)
|
||||
continue
|
||||
}
|
||||
|
||||
// Fetch the policies for each end of the channel.
|
||||
chanID := channel.ShortChanID().ToUint64()
|
||||
info, p1, p2, err := graph.FetchChannelEdgesByID(chanID)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to fetch the routing "+
|
||||
"policies for the edges of the channel "+
|
||||
"%v: %v", chanPoint, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Now, we'll need to determine which is the correct
|
||||
// policy for HTLCs being sent from the remote node.
|
||||
var remotePolicy *channeldb.ChannelEdgePolicy
|
||||
if bytes.Equal(remotePub[:], info.NodeKey1Bytes[:]) {
|
||||
remotePolicy = p1
|
||||
} else {
|
||||
remotePolicy = p2
|
||||
}
|
||||
|
||||
// If for some reason we don't yet have the edge for
|
||||
// the remote party, then we'll just skip adding this
|
||||
// channel as a routing hint.
|
||||
if remotePolicy == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Finally, create the routing hint for this channel and
|
||||
// add it to our list of route hints.
|
||||
hint := zpay32.HopHint{
|
||||
NodeID: channel.IdentityPub,
|
||||
ChannelID: chanID,
|
||||
FeeBaseMSat: uint32(remotePolicy.FeeBaseMSat),
|
||||
FeeProportionalMillionths: uint32(
|
||||
remotePolicy.FeeProportionalMillionths,
|
||||
),
|
||||
CLTVExpiryDelta: remotePolicy.TimeLockDelta,
|
||||
}
|
||||
|
||||
// Include the route hint in our set of options that
|
||||
// will be used when creating the invoice.
|
||||
routeHint := []zpay32.HopHint{hint}
|
||||
options = append(options, zpay32.RouteHint(routeHint))
|
||||
|
||||
numHints++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create and encode the payment request as a bech32 (zpay32) string.
|
||||
creationDate := time.Now()
|
||||
payReq, err := zpay32.NewInvoice(
|
||||
cfg.ChainParams, paymentHash, creationDate, options...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
payReqString, err := payReq.Encode(
|
||||
zpay32.MessageSigner{
|
||||
SignCompact: cfg.NodeSigner.SignDigestCompact,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
newInvoice := &channeldb.Invoice{
|
||||
CreationDate: creationDate,
|
||||
Memo: []byte(invoice.Memo),
|
||||
Receipt: invoice.Receipt,
|
||||
PaymentRequest: []byte(payReqString),
|
||||
Terms: channeldb.ContractTerm{
|
||||
Value: amtMSat,
|
||||
PaymentPreimage: paymentPreimage,
|
||||
},
|
||||
}
|
||||
|
||||
log.Tracef("[addinvoice] adding new invoice %v",
|
||||
newLogClosure(func() string {
|
||||
return spew.Sdump(newInvoice)
|
||||
}),
|
||||
)
|
||||
|
||||
// With all sanity checks passed, write the invoice to the database.
|
||||
_, err = cfg.AddInvoice(newInvoice, paymentHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &paymentHash, newInvoice, nil
|
||||
}
|
@ -4,8 +4,11 @@ package invoicesrpc
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"github.com/lightningnetwork/lnd/netann"
|
||||
)
|
||||
|
||||
// Config is the primary configuration struct for the invoices RPC server. It
|
||||
@ -26,7 +29,25 @@ type Config struct {
|
||||
// created by the daemon.
|
||||
InvoiceRegistry *invoices.InvoiceRegistry
|
||||
|
||||
// IsChannelActive is used to generate valid hop hints.
|
||||
IsChannelActive func(chanID lnwire.ChannelID) bool
|
||||
|
||||
// ChainParams are required to properly decode invoice payment requests
|
||||
// that are marshalled over rpc.
|
||||
ChainParams *chaincfg.Params
|
||||
|
||||
// NodeSigner is an implementation of the MessageSigner implementation
|
||||
// that's backed by the identity private key of the running lnd node.
|
||||
NodeSigner *netann.NodeSigner
|
||||
|
||||
// MaxPaymentMSat is the maximum allowed payment.
|
||||
MaxPaymentMSat lnwire.MilliSatoshi
|
||||
|
||||
// DefaultCLTVExpiry is the default invoice expiry if no values is
|
||||
// specified.
|
||||
DefaultCLTVExpiry uint32
|
||||
|
||||
// ChanDB is a global boltdb instance which is needed to access the
|
||||
// channel graph.
|
||||
ChanDB *channeldb.DB
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ var _ = math.Inf
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type CancelInvoiceMsg struct {
|
||||
// / Hash corresponding to the invoice to cancel.
|
||||
// / Hash corresponding to the (hold) invoice to cancel.
|
||||
PaymentHash []byte `protobuf:"bytes,1,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
@ -37,7 +37,7 @@ func (m *CancelInvoiceMsg) Reset() { *m = CancelInvoiceMsg{} }
|
||||
func (m *CancelInvoiceMsg) String() string { return proto.CompactTextString(m) }
|
||||
func (*CancelInvoiceMsg) ProtoMessage() {}
|
||||
func (*CancelInvoiceMsg) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_invoices_1b708c9c030aea0e, []int{0}
|
||||
return fileDescriptor_invoices_faecc7e411e82f9d, []int{0}
|
||||
}
|
||||
func (m *CancelInvoiceMsg) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CancelInvoiceMsg.Unmarshal(m, b)
|
||||
@ -74,7 +74,7 @@ func (m *CancelInvoiceResp) Reset() { *m = CancelInvoiceResp{} }
|
||||
func (m *CancelInvoiceResp) String() string { return proto.CompactTextString(m) }
|
||||
func (*CancelInvoiceResp) ProtoMessage() {}
|
||||
func (*CancelInvoiceResp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_invoices_1b708c9c030aea0e, []int{1}
|
||||
return fileDescriptor_invoices_faecc7e411e82f9d, []int{1}
|
||||
}
|
||||
func (m *CancelInvoiceResp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CancelInvoiceResp.Unmarshal(m, b)
|
||||
@ -94,9 +94,244 @@ func (m *CancelInvoiceResp) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_CancelInvoiceResp proto.InternalMessageInfo
|
||||
|
||||
type AddHoldInvoiceRequest struct {
|
||||
// *
|
||||
// An optional memo to attach along with the invoice. Used for record keeping
|
||||
// purposes for the invoice's creator, and will also be set in the description
|
||||
// field of the encoded payment request if the description_hash field is not
|
||||
// being used.
|
||||
Memo string `protobuf:"bytes,1,opt,name=memo,proto3" json:"memo,omitempty"`
|
||||
// / The hash of the preimage
|
||||
Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"`
|
||||
// / The value of this invoice in satoshis
|
||||
Value int64 `protobuf:"varint,3,opt,name=value,proto3" json:"value,omitempty"`
|
||||
// *
|
||||
// Hash (SHA-256) of a description of the payment. Used if the description of
|
||||
// payment (memo) is too long to naturally fit within the description field
|
||||
// of an encoded payment request.
|
||||
DescriptionHash []byte `protobuf:"bytes,4,opt,name=description_hash,proto3" json:"description_hash,omitempty"`
|
||||
// / Payment request expiry time in seconds. Default is 3600 (1 hour).
|
||||
Expiry int64 `protobuf:"varint,5,opt,name=expiry,proto3" json:"expiry,omitempty"`
|
||||
// / Fallback on-chain address.
|
||||
FallbackAddr string `protobuf:"bytes,6,opt,name=fallback_addr,proto3" json:"fallback_addr,omitempty"`
|
||||
// / Delta to use for the time-lock of the CLTV extended to the final hop.
|
||||
CltvExpiry uint64 `protobuf:"varint,7,opt,name=cltv_expiry,proto3" json:"cltv_expiry,omitempty"`
|
||||
// *
|
||||
// Route hints that can each be individually used to assist in reaching the
|
||||
// invoice's destination.
|
||||
RouteHints []*lnrpc.RouteHint `protobuf:"bytes,8,rep,name=route_hints,proto3" json:"route_hints,omitempty"`
|
||||
// / Whether this invoice should include routing hints for private channels.
|
||||
Private bool `protobuf:"varint,9,opt,name=private,proto3" json:"private,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) Reset() { *m = AddHoldInvoiceRequest{} }
|
||||
func (m *AddHoldInvoiceRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*AddHoldInvoiceRequest) ProtoMessage() {}
|
||||
func (*AddHoldInvoiceRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_invoices_faecc7e411e82f9d, []int{2}
|
||||
}
|
||||
func (m *AddHoldInvoiceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AddHoldInvoiceRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *AddHoldInvoiceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_AddHoldInvoiceRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *AddHoldInvoiceRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AddHoldInvoiceRequest.Merge(dst, src)
|
||||
}
|
||||
func (m *AddHoldInvoiceRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_AddHoldInvoiceRequest.Size(m)
|
||||
}
|
||||
func (m *AddHoldInvoiceRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AddHoldInvoiceRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AddHoldInvoiceRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetMemo() string {
|
||||
if m != nil {
|
||||
return m.Memo
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetHash() []byte {
|
||||
if m != nil {
|
||||
return m.Hash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetValue() int64 {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetDescriptionHash() []byte {
|
||||
if m != nil {
|
||||
return m.DescriptionHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetExpiry() int64 {
|
||||
if m != nil {
|
||||
return m.Expiry
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetFallbackAddr() string {
|
||||
if m != nil {
|
||||
return m.FallbackAddr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetCltvExpiry() uint64 {
|
||||
if m != nil {
|
||||
return m.CltvExpiry
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetRouteHints() []*lnrpc.RouteHint {
|
||||
if m != nil {
|
||||
return m.RouteHints
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceRequest) GetPrivate() bool {
|
||||
if m != nil {
|
||||
return m.Private
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type AddHoldInvoiceResp struct {
|
||||
// *
|
||||
// A bare-bones invoice for a payment within the Lightning Network. With the
|
||||
// details of the invoice, the sender has all the data necessary to send a
|
||||
// payment to the recipient.
|
||||
PaymentRequest string `protobuf:"bytes,1,opt,name=payment_request,proto3" json:"payment_request,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *AddHoldInvoiceResp) Reset() { *m = AddHoldInvoiceResp{} }
|
||||
func (m *AddHoldInvoiceResp) String() string { return proto.CompactTextString(m) }
|
||||
func (*AddHoldInvoiceResp) ProtoMessage() {}
|
||||
func (*AddHoldInvoiceResp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_invoices_faecc7e411e82f9d, []int{3}
|
||||
}
|
||||
func (m *AddHoldInvoiceResp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AddHoldInvoiceResp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *AddHoldInvoiceResp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_AddHoldInvoiceResp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *AddHoldInvoiceResp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AddHoldInvoiceResp.Merge(dst, src)
|
||||
}
|
||||
func (m *AddHoldInvoiceResp) XXX_Size() int {
|
||||
return xxx_messageInfo_AddHoldInvoiceResp.Size(m)
|
||||
}
|
||||
func (m *AddHoldInvoiceResp) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AddHoldInvoiceResp.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AddHoldInvoiceResp proto.InternalMessageInfo
|
||||
|
||||
func (m *AddHoldInvoiceResp) GetPaymentRequest() string {
|
||||
if m != nil {
|
||||
return m.PaymentRequest
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type SettleInvoiceMsg struct {
|
||||
// / Externally discovered pre-image that should be used to settle the hold invoice.
|
||||
Preimage []byte `protobuf:"bytes,1,opt,name=preimage,proto3" json:"preimage,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SettleInvoiceMsg) Reset() { *m = SettleInvoiceMsg{} }
|
||||
func (m *SettleInvoiceMsg) String() string { return proto.CompactTextString(m) }
|
||||
func (*SettleInvoiceMsg) ProtoMessage() {}
|
||||
func (*SettleInvoiceMsg) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_invoices_faecc7e411e82f9d, []int{4}
|
||||
}
|
||||
func (m *SettleInvoiceMsg) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SettleInvoiceMsg.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SettleInvoiceMsg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SettleInvoiceMsg.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *SettleInvoiceMsg) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SettleInvoiceMsg.Merge(dst, src)
|
||||
}
|
||||
func (m *SettleInvoiceMsg) XXX_Size() int {
|
||||
return xxx_messageInfo_SettleInvoiceMsg.Size(m)
|
||||
}
|
||||
func (m *SettleInvoiceMsg) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SettleInvoiceMsg.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SettleInvoiceMsg proto.InternalMessageInfo
|
||||
|
||||
func (m *SettleInvoiceMsg) GetPreimage() []byte {
|
||||
if m != nil {
|
||||
return m.Preimage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SettleInvoiceResp struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SettleInvoiceResp) Reset() { *m = SettleInvoiceResp{} }
|
||||
func (m *SettleInvoiceResp) String() string { return proto.CompactTextString(m) }
|
||||
func (*SettleInvoiceResp) ProtoMessage() {}
|
||||
func (*SettleInvoiceResp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_invoices_faecc7e411e82f9d, []int{5}
|
||||
}
|
||||
func (m *SettleInvoiceResp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SettleInvoiceResp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SettleInvoiceResp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SettleInvoiceResp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *SettleInvoiceResp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SettleInvoiceResp.Merge(dst, src)
|
||||
}
|
||||
func (m *SettleInvoiceResp) XXX_Size() int {
|
||||
return xxx_messageInfo_SettleInvoiceResp.Size(m)
|
||||
}
|
||||
func (m *SettleInvoiceResp) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SettleInvoiceResp.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SettleInvoiceResp proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*CancelInvoiceMsg)(nil), "invoicesrpc.CancelInvoiceMsg")
|
||||
proto.RegisterType((*CancelInvoiceResp)(nil), "invoicesrpc.CancelInvoiceResp")
|
||||
proto.RegisterType((*AddHoldInvoiceRequest)(nil), "invoicesrpc.AddHoldInvoiceRequest")
|
||||
proto.RegisterType((*AddHoldInvoiceResp)(nil), "invoicesrpc.AddHoldInvoiceResp")
|
||||
proto.RegisterType((*SettleInvoiceMsg)(nil), "invoicesrpc.SettleInvoiceMsg")
|
||||
proto.RegisterType((*SettleInvoiceResp)(nil), "invoicesrpc.SettleInvoiceResp")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@ -121,6 +356,14 @@ type InvoicesClient interface {
|
||||
// canceled, this call will succeed. If the invoice is already settled, it will
|
||||
// fail.
|
||||
CancelInvoice(ctx context.Context, in *CancelInvoiceMsg, opts ...grpc.CallOption) (*CancelInvoiceResp, error)
|
||||
// *
|
||||
// AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
||||
// supplied in the request.
|
||||
AddHoldInvoice(ctx context.Context, in *AddHoldInvoiceRequest, opts ...grpc.CallOption) (*AddHoldInvoiceResp, error)
|
||||
// *
|
||||
// SettleInvoice settles an accepted invoice. If the invoice is already
|
||||
// settled, this call will succeed.
|
||||
SettleInvoice(ctx context.Context, in *SettleInvoiceMsg, opts ...grpc.CallOption) (*SettleInvoiceResp, error)
|
||||
}
|
||||
|
||||
type invoicesClient struct {
|
||||
@ -172,6 +415,24 @@ func (c *invoicesClient) CancelInvoice(ctx context.Context, in *CancelInvoiceMsg
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *invoicesClient) AddHoldInvoice(ctx context.Context, in *AddHoldInvoiceRequest, opts ...grpc.CallOption) (*AddHoldInvoiceResp, error) {
|
||||
out := new(AddHoldInvoiceResp)
|
||||
err := c.cc.Invoke(ctx, "/invoicesrpc.Invoices/AddHoldInvoice", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *invoicesClient) SettleInvoice(ctx context.Context, in *SettleInvoiceMsg, opts ...grpc.CallOption) (*SettleInvoiceResp, error) {
|
||||
out := new(SettleInvoiceResp)
|
||||
err := c.cc.Invoke(ctx, "/invoicesrpc.Invoices/SettleInvoice", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// InvoicesServer is the server API for Invoices service.
|
||||
type InvoicesServer interface {
|
||||
// *
|
||||
@ -184,6 +445,14 @@ type InvoicesServer interface {
|
||||
// canceled, this call will succeed. If the invoice is already settled, it will
|
||||
// fail.
|
||||
CancelInvoice(context.Context, *CancelInvoiceMsg) (*CancelInvoiceResp, error)
|
||||
// *
|
||||
// AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
||||
// supplied in the request.
|
||||
AddHoldInvoice(context.Context, *AddHoldInvoiceRequest) (*AddHoldInvoiceResp, error)
|
||||
// *
|
||||
// SettleInvoice settles an accepted invoice. If the invoice is already
|
||||
// settled, this call will succeed.
|
||||
SettleInvoice(context.Context, *SettleInvoiceMsg) (*SettleInvoiceResp, error)
|
||||
}
|
||||
|
||||
func RegisterInvoicesServer(s *grpc.Server, srv InvoicesServer) {
|
||||
@ -229,6 +498,42 @@ func _Invoices_CancelInvoice_Handler(srv interface{}, ctx context.Context, dec f
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Invoices_AddHoldInvoice_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AddHoldInvoiceRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(InvoicesServer).AddHoldInvoice(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/invoicesrpc.Invoices/AddHoldInvoice",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(InvoicesServer).AddHoldInvoice(ctx, req.(*AddHoldInvoiceRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Invoices_SettleInvoice_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SettleInvoiceMsg)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(InvoicesServer).SettleInvoice(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/invoicesrpc.Invoices/SettleInvoice",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(InvoicesServer).SettleInvoice(ctx, req.(*SettleInvoiceMsg))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Invoices_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "invoicesrpc.Invoices",
|
||||
HandlerType: (*InvoicesServer)(nil),
|
||||
@ -237,6 +542,14 @@ var _Invoices_serviceDesc = grpc.ServiceDesc{
|
||||
MethodName: "CancelInvoice",
|
||||
Handler: _Invoices_CancelInvoice_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AddHoldInvoice",
|
||||
Handler: _Invoices_AddHoldInvoice_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SettleInvoice",
|
||||
Handler: _Invoices_SettleInvoice_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
@ -249,25 +562,40 @@ var _Invoices_serviceDesc = grpc.ServiceDesc{
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("invoicesrpc/invoices.proto", fileDescriptor_invoices_1b708c9c030aea0e)
|
||||
proto.RegisterFile("invoicesrpc/invoices.proto", fileDescriptor_invoices_faecc7e411e82f9d)
|
||||
}
|
||||
|
||||
var fileDescriptor_invoices_1b708c9c030aea0e = []byte{
|
||||
// 246 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0xbf, 0x4b, 0x43, 0x31,
|
||||
0x10, 0xc7, 0x79, 0x8b, 0x68, 0x5a, 0x45, 0x23, 0x88, 0x04, 0x15, 0xed, 0xe4, 0x94, 0xa8, 0xc5,
|
||||
0xd5, 0x41, 0x17, 0x1d, 0x14, 0x69, 0x37, 0x17, 0xc9, 0x8b, 0x21, 0x39, 0x4c, 0xef, 0x42, 0x92,
|
||||
0x2a, 0xfe, 0x2b, 0xfe, 0xb5, 0xd2, 0x36, 0xe2, 0x7b, 0x42, 0xb7, 0xcb, 0x7d, 0x7f, 0xe4, 0x93,
|
||||
0x30, 0x01, 0xf8, 0x41, 0x60, 0x6c, 0x4e, 0xd1, 0xa8, 0xdf, 0x59, 0xc6, 0x44, 0x85, 0xf8, 0xa0,
|
||||
0xa3, 0x89, 0x23, 0x47, 0xe4, 0x82, 0x55, 0x3a, 0x82, 0xd2, 0x88, 0x54, 0x74, 0x01, 0xc2, 0x6a,
|
||||
0x15, 0x5b, 0x29, 0x9a, 0xd5, 0x38, 0xba, 0x66, 0xbb, 0x77, 0x1a, 0x8d, 0x0d, 0x0f, 0xab, 0xf4,
|
||||
0x63, 0x76, 0xfc, 0x8c, 0x0d, 0xa3, 0xfe, 0x9a, 0x59, 0x2c, 0xaf, 0x5e, 0x67, 0x7f, 0xd8, 0x9c,
|
||||
0x36, 0xe7, 0xc3, 0xc9, 0xa0, 0xee, 0xee, 0x75, 0xf6, 0xa3, 0x7d, 0xb6, 0xd7, 0x8b, 0x4d, 0x6c,
|
||||
0x8e, 0x57, 0xdf, 0x0d, 0xdb, 0xac, 0xe7, 0xcc, 0x6f, 0xd8, 0xc1, 0x74, 0xde, 0x66, 0x93, 0xa0,
|
||||
0xb5, 0x53, 0x40, 0x17, 0x6c, 0x95, 0x38, 0x97, 0x01, 0x17, 0x00, 0xcf, 0x7f, 0x7d, 0x62, 0xa7,
|
||||
0xee, 0xaa, 0xe7, 0xa2, 0xe1, 0x4f, 0x6c, 0xbb, 0x77, 0x03, 0x3f, 0x96, 0x9d, 0x07, 0xca, 0xff,
|
||||
0xd0, 0xe2, 0x64, 0xbd, 0xbc, 0x80, 0xbb, 0x1d, 0xbf, 0x5c, 0x3a, 0x28, 0x7e, 0xde, 0x4a, 0x43,
|
||||
0x33, 0x15, 0xc0, 0xf9, 0x82, 0x80, 0x0e, 0x6d, 0xf9, 0xa4, 0xf4, 0xae, 0x02, 0xbe, 0xa9, 0x25,
|
||||
0x82, 0xea, 0xd4, 0xb4, 0x1b, 0xcb, 0x4f, 0x1a, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xd2, 0xc3,
|
||||
0x7e, 0x3a, 0x78, 0x01, 0x00, 0x00,
|
||||
var fileDescriptor_invoices_faecc7e411e82f9d = []byte{
|
||||
// 490 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x93, 0x4f, 0x8f, 0xd3, 0x3c,
|
||||
0x10, 0xc6, 0x95, 0xb6, 0xdb, 0x6d, 0xa7, 0xbb, 0xfb, 0xf6, 0x35, 0xb0, 0x8a, 0x22, 0xfe, 0x84,
|
||||
0x88, 0x43, 0xc4, 0x21, 0x81, 0xae, 0xb8, 0xae, 0x04, 0x5c, 0xca, 0x01, 0x84, 0x52, 0x71, 0xe1,
|
||||
0x52, 0xb9, 0x89, 0x49, 0xac, 0x75, 0x6d, 0x63, 0xbb, 0x85, 0xfd, 0x54, 0x7c, 0x06, 0xbe, 0x19,
|
||||
0x8a, 0xe3, 0x96, 0x24, 0x0b, 0xdc, 0x66, 0x1e, 0xcf, 0x3c, 0x19, 0xff, 0x3c, 0x81, 0x80, 0xf2,
|
||||
0xbd, 0xa0, 0x39, 0xd1, 0x4a, 0xe6, 0xe9, 0x21, 0x4e, 0xa4, 0x12, 0x46, 0xa0, 0x59, 0xeb, 0x2c,
|
||||
0x78, 0x58, 0x0a, 0x51, 0x32, 0x92, 0x62, 0x49, 0x53, 0xcc, 0xb9, 0x30, 0xd8, 0x50, 0xc1, 0x5d,
|
||||
0x69, 0x30, 0x55, 0x32, 0x6f, 0xc2, 0xe8, 0x15, 0xcc, 0xdf, 0x62, 0x9e, 0x13, 0xf6, 0xae, 0xe9,
|
||||
0x7e, 0xaf, 0x4b, 0xf4, 0x14, 0xce, 0x24, 0xbe, 0xdd, 0x12, 0x6e, 0xd6, 0x15, 0xd6, 0x95, 0xef,
|
||||
0x85, 0x5e, 0x7c, 0x96, 0xcd, 0x9c, 0xb6, 0xc4, 0xba, 0x8a, 0xee, 0xc1, 0xff, 0x9d, 0xb6, 0x8c,
|
||||
0x68, 0x19, 0xfd, 0x18, 0xc0, 0x83, 0xd7, 0x45, 0xb1, 0x14, 0xac, 0x38, 0xca, 0x5f, 0x77, 0x44,
|
||||
0x1b, 0x84, 0x60, 0xb4, 0x25, 0x5b, 0x61, 0x9d, 0xa6, 0x99, 0x8d, 0x6b, 0xcd, 0xba, 0x0f, 0xac,
|
||||
0xbb, 0x8d, 0xd1, 0x7d, 0x38, 0xd9, 0x63, 0xb6, 0x23, 0xfe, 0x30, 0xf4, 0xe2, 0x61, 0xd6, 0x24,
|
||||
0xe8, 0x39, 0xcc, 0x0b, 0xa2, 0x73, 0x45, 0x65, 0x7d, 0x89, 0x66, 0xa6, 0x91, 0xed, 0xba, 0xa3,
|
||||
0xa3, 0x4b, 0x18, 0x93, 0xef, 0x92, 0xaa, 0x5b, 0xff, 0xc4, 0x5a, 0xb8, 0x0c, 0x3d, 0x83, 0xf3,
|
||||
0x2f, 0x98, 0xb1, 0x0d, 0xce, 0x6f, 0xd6, 0xb8, 0x28, 0x94, 0x3f, 0xb6, 0xa3, 0x74, 0x45, 0x14,
|
||||
0xc2, 0x2c, 0x67, 0x66, 0xbf, 0x76, 0x16, 0xa7, 0xa1, 0x17, 0x8f, 0xb2, 0xb6, 0x84, 0x16, 0x30,
|
||||
0x53, 0x62, 0x67, 0xc8, 0xba, 0xa2, 0xdc, 0x68, 0x7f, 0x12, 0x0e, 0xe3, 0xd9, 0x62, 0x9e, 0x30,
|
||||
0x5e, 0x23, 0xcd, 0xea, 0x93, 0x25, 0xe5, 0x26, 0x6b, 0x17, 0x21, 0x1f, 0x4e, 0xa5, 0xa2, 0x7b,
|
||||
0x6c, 0x88, 0x3f, 0x0d, 0xbd, 0x78, 0x92, 0x1d, 0xd2, 0xe8, 0x1a, 0x50, 0x1f, 0x98, 0x96, 0x28,
|
||||
0x86, 0xff, 0x0e, 0xfc, 0x55, 0x03, 0xd0, 0x81, 0xeb, 0xcb, 0x51, 0x02, 0xf3, 0x15, 0x31, 0x86,
|
||||
0x91, 0xd6, 0xeb, 0x05, 0x30, 0x91, 0x8a, 0xd0, 0x2d, 0x2e, 0x89, 0x7b, 0xb9, 0x63, 0x5e, 0x3f,
|
||||
0x5b, 0xa7, 0xbe, 0xfe, 0xdc, 0xe2, 0xe7, 0x00, 0x26, 0x2e, 0xd7, 0xe8, 0x1a, 0x2e, 0x57, 0xbb,
|
||||
0x4d, 0x0d, 0x75, 0x43, 0x56, 0x94, 0x97, 0xc7, 0x52, 0x84, 0xdc, 0x25, 0x3f, 0xfe, 0x5e, 0x83,
|
||||
0xe0, 0xc2, 0x69, 0xae, 0xe6, 0x85, 0x87, 0x3e, 0xc0, 0x79, 0x67, 0x31, 0xd0, 0xa3, 0xa4, 0xb5,
|
||||
0x97, 0x49, 0x7f, 0xd7, 0x82, 0xc7, 0x7f, 0x3f, 0xb6, 0x2c, 0x3e, 0xc1, 0x45, 0x97, 0x10, 0x8a,
|
||||
0x3a, 0x1d, 0x7f, 0xdc, 0xb7, 0xe0, 0xc9, 0x3f, 0x6b, 0xb4, 0xac, 0xc7, 0xec, 0x80, 0xe8, 0x8d,
|
||||
0xd9, 0x87, 0xda, 0x1b, 0xf3, 0x0e, 0xc3, 0x37, 0x57, 0x9f, 0x5f, 0x96, 0xd4, 0x54, 0xbb, 0x4d,
|
||||
0x92, 0x8b, 0x6d, 0xca, 0x68, 0x59, 0x19, 0x4e, 0x79, 0xc9, 0x89, 0xf9, 0x26, 0xd4, 0x4d, 0xca,
|
||||
0x78, 0x91, 0x5a, 0x52, 0x69, 0xcb, 0x66, 0x33, 0xb6, 0xbf, 0xe0, 0xd5, 0xaf, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0x89, 0x60, 0x5e, 0x11, 0xd6, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
@ -23,10 +23,79 @@ service Invoices {
|
||||
fail.
|
||||
*/
|
||||
rpc CancelInvoice(CancelInvoiceMsg) returns (CancelInvoiceResp);
|
||||
|
||||
/**
|
||||
AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
|
||||
supplied in the request.
|
||||
*/
|
||||
rpc AddHoldInvoice(AddHoldInvoiceRequest) returns (AddHoldInvoiceResp);
|
||||
|
||||
/**
|
||||
SettleInvoice settles an accepted invoice. If the invoice is already
|
||||
settled, this call will succeed.
|
||||
*/
|
||||
rpc SettleInvoice(SettleInvoiceMsg) returns (SettleInvoiceResp);
|
||||
}
|
||||
|
||||
message CancelInvoiceMsg {
|
||||
/// Hash corresponding to the invoice to cancel.
|
||||
/// Hash corresponding to the (hold) invoice to cancel.
|
||||
bytes payment_hash = 1;
|
||||
}
|
||||
message CancelInvoiceResp {}
|
||||
|
||||
message AddHoldInvoiceRequest {
|
||||
/**
|
||||
An optional memo to attach along with the invoice. Used for record keeping
|
||||
purposes for the invoice's creator, and will also be set in the description
|
||||
field of the encoded payment request if the description_hash field is not
|
||||
being used.
|
||||
*/
|
||||
string memo = 1 [json_name = "memo"];
|
||||
|
||||
/// The hash of the preimage
|
||||
bytes hash = 2 [json_name = "hash"];
|
||||
|
||||
/// The value of this invoice in satoshis
|
||||
int64 value = 3 [json_name = "value"];
|
||||
|
||||
/**
|
||||
Hash (SHA-256) of a description of the payment. Used if the description of
|
||||
payment (memo) is too long to naturally fit within the description field
|
||||
of an encoded payment request.
|
||||
*/
|
||||
bytes description_hash = 4 [json_name = "description_hash"];
|
||||
|
||||
/// Payment request expiry time in seconds. Default is 3600 (1 hour).
|
||||
int64 expiry = 5 [json_name = "expiry"];
|
||||
|
||||
/// Fallback on-chain address.
|
||||
string fallback_addr = 6 [json_name = "fallback_addr"];
|
||||
|
||||
/// Delta to use for the time-lock of the CLTV extended to the final hop.
|
||||
uint64 cltv_expiry = 7 [json_name = "cltv_expiry"];
|
||||
|
||||
/**
|
||||
Route hints that can each be individually used to assist in reaching the
|
||||
invoice's destination.
|
||||
*/
|
||||
repeated lnrpc.RouteHint route_hints = 8 [json_name = "route_hints"];
|
||||
|
||||
/// Whether this invoice should include routing hints for private channels.
|
||||
bool private = 9 [json_name = "private"];
|
||||
}
|
||||
|
||||
message AddHoldInvoiceResp {
|
||||
/**
|
||||
A bare-bones invoice for a payment within the Lightning Network. With the
|
||||
details of the invoice, the sender has all the data necessary to send a
|
||||
payment to the recipient.
|
||||
*/
|
||||
string payment_request = 1 [json_name = "payment_request"];
|
||||
}
|
||||
|
||||
message SettleInvoiceMsg {
|
||||
/// Externally discovered pre-image that should be used to settle the hold invoice.
|
||||
bytes preimage = 1;
|
||||
}
|
||||
|
||||
message SettleInvoiceResp {}
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
)
|
||||
@ -43,10 +45,18 @@ var (
|
||||
Entity: "invoices",
|
||||
Action: "read",
|
||||
}},
|
||||
"/invoicesrpc.Invoices/SettleInvoice": {{
|
||||
Entity: "invoices",
|
||||
Action: "write",
|
||||
}},
|
||||
"/invoicesrpc.Invoices/CancelInvoice": {{
|
||||
Entity: "invoices",
|
||||
Action: "write",
|
||||
}},
|
||||
"/invoicesrpc.Invoices/AddHoldInvoice": {{
|
||||
Entity: "invoices",
|
||||
Action: "write",
|
||||
}},
|
||||
}
|
||||
|
||||
// DefaultInvoicesMacFilename is the default name of the invoices
|
||||
@ -163,12 +173,12 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error {
|
||||
func (s *Server) SubscribeSingleInvoice(req *lnrpc.PaymentHash,
|
||||
updateStream Invoices_SubscribeSingleInvoiceServer) error {
|
||||
|
||||
hash, err := lntypes.NewHash(req.RHash)
|
||||
hash, err := lntypes.MakeHash(req.RHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
invoiceClient := s.cfg.InvoiceRegistry.SubscribeSingleInvoice(*hash)
|
||||
invoiceClient := s.cfg.InvoiceRegistry.SubscribeSingleInvoice(hash)
|
||||
defer invoiceClient.Cancel()
|
||||
|
||||
for {
|
||||
@ -191,18 +201,36 @@ func (s *Server) SubscribeSingleInvoice(req *lnrpc.PaymentHash,
|
||||
}
|
||||
}
|
||||
|
||||
// SettleInvoice settles an accepted invoice. If the invoice is already settled,
|
||||
// this call will succeed.
|
||||
func (s *Server) SettleInvoice(ctx context.Context,
|
||||
in *SettleInvoiceMsg) (*SettleInvoiceResp, error) {
|
||||
|
||||
preimage, err := lntypes.MakePreimage(in.Preimage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = s.cfg.InvoiceRegistry.SettleHodlInvoice(preimage)
|
||||
if err != nil && err != channeldb.ErrInvoiceAlreadySettled {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SettleInvoiceResp{}, nil
|
||||
}
|
||||
|
||||
// CancelInvoice cancels a currently open invoice. If the invoice is already
|
||||
// canceled, this call will succeed. If the invoice is already settled, it will
|
||||
// fail.
|
||||
func (s *Server) CancelInvoice(ctx context.Context,
|
||||
in *CancelInvoiceMsg) (*CancelInvoiceResp, error) {
|
||||
|
||||
paymentHash, err := lntypes.NewHash(in.PaymentHash)
|
||||
paymentHash, err := lntypes.MakeHash(in.PaymentHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = s.cfg.InvoiceRegistry.CancelInvoice(*paymentHash)
|
||||
err = s.cfg.InvoiceRegistry.CancelInvoice(paymentHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -211,3 +239,45 @@ func (s *Server) CancelInvoice(ctx context.Context,
|
||||
|
||||
return &CancelInvoiceResp{}, nil
|
||||
}
|
||||
|
||||
// AddHoldInvoice attempts to add a new hold invoice to the invoice database.
|
||||
// Any duplicated invoices are rejected, therefore all invoices *must* have a
|
||||
// unique payment hash.
|
||||
func (s *Server) AddHoldInvoice(ctx context.Context,
|
||||
invoice *AddHoldInvoiceRequest) (*AddHoldInvoiceResp, error) {
|
||||
|
||||
addInvoiceCfg := &AddInvoiceConfig{
|
||||
AddInvoice: s.cfg.InvoiceRegistry.AddInvoice,
|
||||
IsChannelActive: s.cfg.IsChannelActive,
|
||||
ChainParams: s.cfg.ChainParams,
|
||||
NodeSigner: s.cfg.NodeSigner,
|
||||
MaxPaymentMSat: s.cfg.MaxPaymentMSat,
|
||||
DefaultCLTVExpiry: s.cfg.DefaultCLTVExpiry,
|
||||
ChanDB: s.cfg.ChanDB,
|
||||
}
|
||||
|
||||
hash, err := lntypes.MakeHash(invoice.Hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addInvoiceData := &AddInvoiceData{
|
||||
Memo: invoice.Memo,
|
||||
Hash: &hash,
|
||||
Value: btcutil.Amount(invoice.Value),
|
||||
DescriptionHash: invoice.DescriptionHash,
|
||||
Expiry: invoice.Expiry,
|
||||
FallbackAddr: invoice.FallbackAddr,
|
||||
CltvExpiry: invoice.CltvExpiry,
|
||||
Private: invoice.Private,
|
||||
}
|
||||
|
||||
_, dbInvoice, err := AddInvoice(ctx, addInvoiceCfg, addInvoiceData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &AddHoldInvoiceResp{
|
||||
PaymentRequest: string(dbInvoice.PaymentRequest),
|
||||
}, nil
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
@ -61,16 +60,17 @@ func CreateRPCInvoice(invoice *channeldb.Invoice,
|
||||
state = lnrpc.Invoice_SETTLED
|
||||
case channeldb.ContractCanceled:
|
||||
state = lnrpc.Invoice_CANCELED
|
||||
case channeldb.ContractAccepted:
|
||||
state = lnrpc.Invoice_ACCEPTED
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown invoice state %v",
|
||||
invoice.Terms.State)
|
||||
}
|
||||
|
||||
return &lnrpc.Invoice{
|
||||
rpcInvoice := &lnrpc.Invoice{
|
||||
Memo: string(invoice.Memo[:]),
|
||||
Receipt: invoice.Receipt[:],
|
||||
RHash: decoded.PaymentHash[:],
|
||||
RPreimage: preimage[:],
|
||||
Value: int64(satAmt),
|
||||
CreationDate: invoice.CreationDate.Unix(),
|
||||
SettleDate: settleDate,
|
||||
@ -88,12 +88,18 @@ func CreateRPCInvoice(invoice *channeldb.Invoice,
|
||||
AmtPaidMsat: int64(invoice.AmtPaid),
|
||||
AmtPaid: int64(invoice.AmtPaid),
|
||||
State: state,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if preimage != channeldb.UnknownPreimage {
|
||||
rpcInvoice.RPreimage = preimage[:]
|
||||
}
|
||||
|
||||
return rpcInvoice, nil
|
||||
}
|
||||
|
||||
// CreateRPCRouteHints takes in the decoded form of an invoice's route hints
|
||||
// and converts them into the lnrpc type.
|
||||
func CreateRPCRouteHints(routeHints [][]routing.HopHint) []*lnrpc.RouteHint {
|
||||
func CreateRPCRouteHints(routeHints [][]zpay32.HopHint) []*lnrpc.RouteHint {
|
||||
var res []*lnrpc.RouteHint
|
||||
|
||||
for _, route := range routeHints {
|
||||
|
1144
lnrpc/rpc.pb.go
1144
lnrpc/rpc.pb.go
@ -55,7 +55,7 @@ func (x AddressType) String() string {
|
||||
return proto.EnumName(AddressType_name, int32(x))
|
||||
}
|
||||
func (AddressType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{0}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{0}
|
||||
}
|
||||
|
||||
type ChannelCloseSummary_ClosureType int32
|
||||
@ -90,7 +90,7 @@ func (x ChannelCloseSummary_ClosureType) String() string {
|
||||
return proto.EnumName(ChannelCloseSummary_ClosureType_name, int32(x))
|
||||
}
|
||||
func (ChannelCloseSummary_ClosureType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{39, 0}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{39, 0}
|
||||
}
|
||||
|
||||
type ChannelEventUpdate_UpdateType int32
|
||||
@ -119,7 +119,7 @@ func (x ChannelEventUpdate_UpdateType) String() string {
|
||||
return proto.EnumName(ChannelEventUpdate_UpdateType_name, int32(x))
|
||||
}
|
||||
func (ChannelEventUpdate_UpdateType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{60, 0}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{60, 0}
|
||||
}
|
||||
|
||||
type Invoice_InvoiceState int32
|
||||
@ -128,24 +128,27 @@ const (
|
||||
Invoice_OPEN Invoice_InvoiceState = 0
|
||||
Invoice_SETTLED Invoice_InvoiceState = 1
|
||||
Invoice_CANCELED Invoice_InvoiceState = 2
|
||||
Invoice_ACCEPTED Invoice_InvoiceState = 3
|
||||
)
|
||||
|
||||
var Invoice_InvoiceState_name = map[int32]string{
|
||||
0: "OPEN",
|
||||
1: "SETTLED",
|
||||
2: "CANCELED",
|
||||
3: "ACCEPTED",
|
||||
}
|
||||
var Invoice_InvoiceState_value = map[string]int32{
|
||||
"OPEN": 0,
|
||||
"SETTLED": 1,
|
||||
"CANCELED": 2,
|
||||
"ACCEPTED": 3,
|
||||
}
|
||||
|
||||
func (x Invoice_InvoiceState) String() string {
|
||||
return proto.EnumName(Invoice_InvoiceState_name, int32(x))
|
||||
}
|
||||
func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{90, 0}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{90, 0}
|
||||
}
|
||||
|
||||
type GenSeedRequest struct {
|
||||
@ -166,7 +169,7 @@ func (m *GenSeedRequest) Reset() { *m = GenSeedRequest{} }
|
||||
func (m *GenSeedRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenSeedRequest) ProtoMessage() {}
|
||||
func (*GenSeedRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{0}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{0}
|
||||
}
|
||||
func (m *GenSeedRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GenSeedRequest.Unmarshal(m, b)
|
||||
@ -221,7 +224,7 @@ func (m *GenSeedResponse) Reset() { *m = GenSeedResponse{} }
|
||||
func (m *GenSeedResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenSeedResponse) ProtoMessage() {}
|
||||
func (*GenSeedResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{1}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{1}
|
||||
}
|
||||
func (m *GenSeedResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GenSeedResponse.Unmarshal(m, b)
|
||||
@ -286,7 +289,7 @@ func (m *InitWalletRequest) Reset() { *m = InitWalletRequest{} }
|
||||
func (m *InitWalletRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*InitWalletRequest) ProtoMessage() {}
|
||||
func (*InitWalletRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{2}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{2}
|
||||
}
|
||||
func (m *InitWalletRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InitWalletRequest.Unmarshal(m, b)
|
||||
@ -344,7 +347,7 @@ func (m *InitWalletResponse) Reset() { *m = InitWalletResponse{} }
|
||||
func (m *InitWalletResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*InitWalletResponse) ProtoMessage() {}
|
||||
func (*InitWalletResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{3}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{3}
|
||||
}
|
||||
func (m *InitWalletResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InitWalletResponse.Unmarshal(m, b)
|
||||
@ -386,7 +389,7 @@ func (m *UnlockWalletRequest) Reset() { *m = UnlockWalletRequest{} }
|
||||
func (m *UnlockWalletRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*UnlockWalletRequest) ProtoMessage() {}
|
||||
func (*UnlockWalletRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{4}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{4}
|
||||
}
|
||||
func (m *UnlockWalletRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UnlockWalletRequest.Unmarshal(m, b)
|
||||
@ -430,7 +433,7 @@ func (m *UnlockWalletResponse) Reset() { *m = UnlockWalletResponse{} }
|
||||
func (m *UnlockWalletResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*UnlockWalletResponse) ProtoMessage() {}
|
||||
func (*UnlockWalletResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{5}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{5}
|
||||
}
|
||||
func (m *UnlockWalletResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UnlockWalletResponse.Unmarshal(m, b)
|
||||
@ -468,7 +471,7 @@ func (m *ChangePasswordRequest) Reset() { *m = ChangePasswordRequest{} }
|
||||
func (m *ChangePasswordRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChangePasswordRequest) ProtoMessage() {}
|
||||
func (*ChangePasswordRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{6}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{6}
|
||||
}
|
||||
func (m *ChangePasswordRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChangePasswordRequest.Unmarshal(m, b)
|
||||
@ -512,7 +515,7 @@ func (m *ChangePasswordResponse) Reset() { *m = ChangePasswordResponse{}
|
||||
func (m *ChangePasswordResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChangePasswordResponse) ProtoMessage() {}
|
||||
func (*ChangePasswordResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{7}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{7}
|
||||
}
|
||||
func (m *ChangePasswordResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChangePasswordResponse.Unmarshal(m, b)
|
||||
@ -554,7 +557,7 @@ func (m *Utxo) Reset() { *m = Utxo{} }
|
||||
func (m *Utxo) String() string { return proto.CompactTextString(m) }
|
||||
func (*Utxo) ProtoMessage() {}
|
||||
func (*Utxo) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{8}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{8}
|
||||
}
|
||||
func (m *Utxo) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Utxo.Unmarshal(m, b)
|
||||
@ -642,7 +645,7 @@ func (m *Transaction) Reset() { *m = Transaction{} }
|
||||
func (m *Transaction) String() string { return proto.CompactTextString(m) }
|
||||
func (*Transaction) ProtoMessage() {}
|
||||
func (*Transaction) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{9}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{9}
|
||||
}
|
||||
func (m *Transaction) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Transaction.Unmarshal(m, b)
|
||||
@ -728,7 +731,7 @@ func (m *GetTransactionsRequest) Reset() { *m = GetTransactionsRequest{}
|
||||
func (m *GetTransactionsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetTransactionsRequest) ProtoMessage() {}
|
||||
func (*GetTransactionsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{10}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{10}
|
||||
}
|
||||
func (m *GetTransactionsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetTransactionsRequest.Unmarshal(m, b)
|
||||
@ -760,7 +763,7 @@ func (m *TransactionDetails) Reset() { *m = TransactionDetails{} }
|
||||
func (m *TransactionDetails) String() string { return proto.CompactTextString(m) }
|
||||
func (*TransactionDetails) ProtoMessage() {}
|
||||
func (*TransactionDetails) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{11}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{11}
|
||||
}
|
||||
func (m *TransactionDetails) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_TransactionDetails.Unmarshal(m, b)
|
||||
@ -801,7 +804,7 @@ func (m *FeeLimit) Reset() { *m = FeeLimit{} }
|
||||
func (m *FeeLimit) String() string { return proto.CompactTextString(m) }
|
||||
func (*FeeLimit) ProtoMessage() {}
|
||||
func (*FeeLimit) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{12}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{12}
|
||||
}
|
||||
func (m *FeeLimit) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FeeLimit.Unmarshal(m, b)
|
||||
@ -961,7 +964,7 @@ func (m *SendRequest) Reset() { *m = SendRequest{} }
|
||||
func (m *SendRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendRequest) ProtoMessage() {}
|
||||
func (*SendRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{13}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{13}
|
||||
}
|
||||
func (m *SendRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendRequest.Unmarshal(m, b)
|
||||
@ -1058,7 +1061,7 @@ func (m *SendResponse) Reset() { *m = SendResponse{} }
|
||||
func (m *SendResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendResponse) ProtoMessage() {}
|
||||
func (*SendResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{14}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{14}
|
||||
}
|
||||
func (m *SendResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendResponse.Unmarshal(m, b)
|
||||
@ -1128,7 +1131,7 @@ func (m *SendToRouteRequest) Reset() { *m = SendToRouteRequest{} }
|
||||
func (m *SendToRouteRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendToRouteRequest) ProtoMessage() {}
|
||||
func (*SendToRouteRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{15}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{15}
|
||||
}
|
||||
func (m *SendToRouteRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendToRouteRequest.Unmarshal(m, b)
|
||||
@ -1193,7 +1196,7 @@ func (m *ChannelPoint) Reset() { *m = ChannelPoint{} }
|
||||
func (m *ChannelPoint) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelPoint) ProtoMessage() {}
|
||||
func (*ChannelPoint) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{16}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{16}
|
||||
}
|
||||
func (m *ChannelPoint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelPoint.Unmarshal(m, b)
|
||||
@ -1339,7 +1342,7 @@ func (m *OutPoint) Reset() { *m = OutPoint{} }
|
||||
func (m *OutPoint) String() string { return proto.CompactTextString(m) }
|
||||
func (*OutPoint) ProtoMessage() {}
|
||||
func (*OutPoint) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{17}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{17}
|
||||
}
|
||||
func (m *OutPoint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_OutPoint.Unmarshal(m, b)
|
||||
@ -1394,7 +1397,7 @@ func (m *LightningAddress) Reset() { *m = LightningAddress{} }
|
||||
func (m *LightningAddress) String() string { return proto.CompactTextString(m) }
|
||||
func (*LightningAddress) ProtoMessage() {}
|
||||
func (*LightningAddress) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{18}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{18}
|
||||
}
|
||||
func (m *LightningAddress) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_LightningAddress.Unmarshal(m, b)
|
||||
@ -1444,7 +1447,7 @@ func (m *SendManyRequest) Reset() { *m = SendManyRequest{} }
|
||||
func (m *SendManyRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendManyRequest) ProtoMessage() {}
|
||||
func (*SendManyRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{19}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{19}
|
||||
}
|
||||
func (m *SendManyRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendManyRequest.Unmarshal(m, b)
|
||||
@ -1497,7 +1500,7 @@ func (m *SendManyResponse) Reset() { *m = SendManyResponse{} }
|
||||
func (m *SendManyResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendManyResponse) ProtoMessage() {}
|
||||
func (*SendManyResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{20}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{20}
|
||||
}
|
||||
func (m *SendManyResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendManyResponse.Unmarshal(m, b)
|
||||
@ -1547,7 +1550,7 @@ func (m *SendCoinsRequest) Reset() { *m = SendCoinsRequest{} }
|
||||
func (m *SendCoinsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendCoinsRequest) ProtoMessage() {}
|
||||
func (*SendCoinsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{21}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{21}
|
||||
}
|
||||
func (m *SendCoinsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendCoinsRequest.Unmarshal(m, b)
|
||||
@ -1614,7 +1617,7 @@ func (m *SendCoinsResponse) Reset() { *m = SendCoinsResponse{} }
|
||||
func (m *SendCoinsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendCoinsResponse) ProtoMessage() {}
|
||||
func (*SendCoinsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{22}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{22}
|
||||
}
|
||||
func (m *SendCoinsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendCoinsResponse.Unmarshal(m, b)
|
||||
@ -1655,7 +1658,7 @@ func (m *ListUnspentRequest) Reset() { *m = ListUnspentRequest{} }
|
||||
func (m *ListUnspentRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListUnspentRequest) ProtoMessage() {}
|
||||
func (*ListUnspentRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{23}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{23}
|
||||
}
|
||||
func (m *ListUnspentRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListUnspentRequest.Unmarshal(m, b)
|
||||
@ -1701,7 +1704,7 @@ func (m *ListUnspentResponse) Reset() { *m = ListUnspentResponse{} }
|
||||
func (m *ListUnspentResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListUnspentResponse) ProtoMessage() {}
|
||||
func (*ListUnspentResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{24}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{24}
|
||||
}
|
||||
func (m *ListUnspentResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListUnspentResponse.Unmarshal(m, b)
|
||||
@ -1740,7 +1743,7 @@ func (m *NewAddressRequest) Reset() { *m = NewAddressRequest{} }
|
||||
func (m *NewAddressRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*NewAddressRequest) ProtoMessage() {}
|
||||
func (*NewAddressRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{25}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{25}
|
||||
}
|
||||
func (m *NewAddressRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NewAddressRequest.Unmarshal(m, b)
|
||||
@ -1779,7 +1782,7 @@ func (m *NewAddressResponse) Reset() { *m = NewAddressResponse{} }
|
||||
func (m *NewAddressResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*NewAddressResponse) ProtoMessage() {}
|
||||
func (*NewAddressResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{26}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{26}
|
||||
}
|
||||
func (m *NewAddressResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NewAddressResponse.Unmarshal(m, b)
|
||||
@ -1818,7 +1821,7 @@ func (m *SignMessageRequest) Reset() { *m = SignMessageRequest{} }
|
||||
func (m *SignMessageRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SignMessageRequest) ProtoMessage() {}
|
||||
func (*SignMessageRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{27}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{27}
|
||||
}
|
||||
func (m *SignMessageRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SignMessageRequest.Unmarshal(m, b)
|
||||
@ -1857,7 +1860,7 @@ func (m *SignMessageResponse) Reset() { *m = SignMessageResponse{} }
|
||||
func (m *SignMessageResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SignMessageResponse) ProtoMessage() {}
|
||||
func (*SignMessageResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{28}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{28}
|
||||
}
|
||||
func (m *SignMessageResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SignMessageResponse.Unmarshal(m, b)
|
||||
@ -1898,7 +1901,7 @@ func (m *VerifyMessageRequest) Reset() { *m = VerifyMessageRequest{} }
|
||||
func (m *VerifyMessageRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*VerifyMessageRequest) ProtoMessage() {}
|
||||
func (*VerifyMessageRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{29}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{29}
|
||||
}
|
||||
func (m *VerifyMessageRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VerifyMessageRequest.Unmarshal(m, b)
|
||||
@ -1946,7 +1949,7 @@ func (m *VerifyMessageResponse) Reset() { *m = VerifyMessageResponse{} }
|
||||
func (m *VerifyMessageResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*VerifyMessageResponse) ProtoMessage() {}
|
||||
func (*VerifyMessageResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{30}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{30}
|
||||
}
|
||||
func (m *VerifyMessageResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VerifyMessageResponse.Unmarshal(m, b)
|
||||
@ -1995,7 +1998,7 @@ func (m *ConnectPeerRequest) Reset() { *m = ConnectPeerRequest{} }
|
||||
func (m *ConnectPeerRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConnectPeerRequest) ProtoMessage() {}
|
||||
func (*ConnectPeerRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{31}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{31}
|
||||
}
|
||||
func (m *ConnectPeerRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ConnectPeerRequest.Unmarshal(m, b)
|
||||
@ -2039,7 +2042,7 @@ func (m *ConnectPeerResponse) Reset() { *m = ConnectPeerResponse{} }
|
||||
func (m *ConnectPeerResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConnectPeerResponse) ProtoMessage() {}
|
||||
func (*ConnectPeerResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{32}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{32}
|
||||
}
|
||||
func (m *ConnectPeerResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ConnectPeerResponse.Unmarshal(m, b)
|
||||
@ -2071,7 +2074,7 @@ func (m *DisconnectPeerRequest) Reset() { *m = DisconnectPeerRequest{} }
|
||||
func (m *DisconnectPeerRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*DisconnectPeerRequest) ProtoMessage() {}
|
||||
func (*DisconnectPeerRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{33}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{33}
|
||||
}
|
||||
func (m *DisconnectPeerRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DisconnectPeerRequest.Unmarshal(m, b)
|
||||
@ -2108,7 +2111,7 @@ func (m *DisconnectPeerResponse) Reset() { *m = DisconnectPeerResponse{}
|
||||
func (m *DisconnectPeerResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*DisconnectPeerResponse) ProtoMessage() {}
|
||||
func (*DisconnectPeerResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{34}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{34}
|
||||
}
|
||||
func (m *DisconnectPeerResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DisconnectPeerResponse.Unmarshal(m, b)
|
||||
@ -2142,7 +2145,7 @@ func (m *HTLC) Reset() { *m = HTLC{} }
|
||||
func (m *HTLC) String() string { return proto.CompactTextString(m) }
|
||||
func (*HTLC) ProtoMessage() {}
|
||||
func (*HTLC) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{35}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{35}
|
||||
}
|
||||
func (m *HTLC) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_HTLC.Unmarshal(m, b)
|
||||
@ -2256,7 +2259,7 @@ func (m *Channel) Reset() { *m = Channel{} }
|
||||
func (m *Channel) String() string { return proto.CompactTextString(m) }
|
||||
func (*Channel) ProtoMessage() {}
|
||||
func (*Channel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{36}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{36}
|
||||
}
|
||||
func (m *Channel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Channel.Unmarshal(m, b)
|
||||
@ -2416,7 +2419,7 @@ func (m *ListChannelsRequest) Reset() { *m = ListChannelsRequest{} }
|
||||
func (m *ListChannelsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListChannelsRequest) ProtoMessage() {}
|
||||
func (*ListChannelsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{37}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{37}
|
||||
}
|
||||
func (m *ListChannelsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListChannelsRequest.Unmarshal(m, b)
|
||||
@ -2476,7 +2479,7 @@ func (m *ListChannelsResponse) Reset() { *m = ListChannelsResponse{} }
|
||||
func (m *ListChannelsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListChannelsResponse) ProtoMessage() {}
|
||||
func (*ListChannelsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{38}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{38}
|
||||
}
|
||||
func (m *ListChannelsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListChannelsResponse.Unmarshal(m, b)
|
||||
@ -2533,7 +2536,7 @@ func (m *ChannelCloseSummary) Reset() { *m = ChannelCloseSummary{} }
|
||||
func (m *ChannelCloseSummary) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelCloseSummary) ProtoMessage() {}
|
||||
func (*ChannelCloseSummary) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{39}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{39}
|
||||
}
|
||||
func (m *ChannelCloseSummary) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelCloseSummary.Unmarshal(m, b)
|
||||
@ -2639,7 +2642,7 @@ func (m *ClosedChannelsRequest) Reset() { *m = ClosedChannelsRequest{} }
|
||||
func (m *ClosedChannelsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ClosedChannelsRequest) ProtoMessage() {}
|
||||
func (*ClosedChannelsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{40}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{40}
|
||||
}
|
||||
func (m *ClosedChannelsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ClosedChannelsRequest.Unmarshal(m, b)
|
||||
@ -2712,7 +2715,7 @@ func (m *ClosedChannelsResponse) Reset() { *m = ClosedChannelsResponse{}
|
||||
func (m *ClosedChannelsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ClosedChannelsResponse) ProtoMessage() {}
|
||||
func (*ClosedChannelsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{41}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{41}
|
||||
}
|
||||
func (m *ClosedChannelsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ClosedChannelsResponse.Unmarshal(m, b)
|
||||
@ -2765,7 +2768,7 @@ func (m *Peer) Reset() { *m = Peer{} }
|
||||
func (m *Peer) String() string { return proto.CompactTextString(m) }
|
||||
func (*Peer) ProtoMessage() {}
|
||||
func (*Peer) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{42}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{42}
|
||||
}
|
||||
func (m *Peer) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Peer.Unmarshal(m, b)
|
||||
@ -2851,7 +2854,7 @@ func (m *ListPeersRequest) Reset() { *m = ListPeersRequest{} }
|
||||
func (m *ListPeersRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListPeersRequest) ProtoMessage() {}
|
||||
func (*ListPeersRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{43}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{43}
|
||||
}
|
||||
func (m *ListPeersRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListPeersRequest.Unmarshal(m, b)
|
||||
@ -2883,7 +2886,7 @@ func (m *ListPeersResponse) Reset() { *m = ListPeersResponse{} }
|
||||
func (m *ListPeersResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListPeersResponse) ProtoMessage() {}
|
||||
func (*ListPeersResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{44}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{44}
|
||||
}
|
||||
func (m *ListPeersResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListPeersResponse.Unmarshal(m, b)
|
||||
@ -2920,7 +2923,7 @@ func (m *GetInfoRequest) Reset() { *m = GetInfoRequest{} }
|
||||
func (m *GetInfoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetInfoRequest) ProtoMessage() {}
|
||||
func (*GetInfoRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{45}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{45}
|
||||
}
|
||||
func (m *GetInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetInfoRequest.Unmarshal(m, b)
|
||||
@ -2980,7 +2983,7 @@ func (m *GetInfoResponse) Reset() { *m = GetInfoResponse{} }
|
||||
func (m *GetInfoResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetInfoResponse) ProtoMessage() {}
|
||||
func (*GetInfoResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{46}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{46}
|
||||
}
|
||||
func (m *GetInfoResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetInfoResponse.Unmarshal(m, b)
|
||||
@ -3113,7 +3116,7 @@ func (m *Chain) Reset() { *m = Chain{} }
|
||||
func (m *Chain) String() string { return proto.CompactTextString(m) }
|
||||
func (*Chain) ProtoMessage() {}
|
||||
func (*Chain) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{47}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{47}
|
||||
}
|
||||
func (m *Chain) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Chain.Unmarshal(m, b)
|
||||
@ -3160,7 +3163,7 @@ func (m *ConfirmationUpdate) Reset() { *m = ConfirmationUpdate{} }
|
||||
func (m *ConfirmationUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConfirmationUpdate) ProtoMessage() {}
|
||||
func (*ConfirmationUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{48}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{48}
|
||||
}
|
||||
func (m *ConfirmationUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ConfirmationUpdate.Unmarshal(m, b)
|
||||
@ -3212,7 +3215,7 @@ func (m *ChannelOpenUpdate) Reset() { *m = ChannelOpenUpdate{} }
|
||||
func (m *ChannelOpenUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelOpenUpdate) ProtoMessage() {}
|
||||
func (*ChannelOpenUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{49}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{49}
|
||||
}
|
||||
func (m *ChannelOpenUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelOpenUpdate.Unmarshal(m, b)
|
||||
@ -3251,7 +3254,7 @@ func (m *ChannelCloseUpdate) Reset() { *m = ChannelCloseUpdate{} }
|
||||
func (m *ChannelCloseUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelCloseUpdate) ProtoMessage() {}
|
||||
func (*ChannelCloseUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{50}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{50}
|
||||
}
|
||||
func (m *ChannelCloseUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelCloseUpdate.Unmarshal(m, b)
|
||||
@ -3306,7 +3309,7 @@ func (m *CloseChannelRequest) Reset() { *m = CloseChannelRequest{} }
|
||||
func (m *CloseChannelRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*CloseChannelRequest) ProtoMessage() {}
|
||||
func (*CloseChannelRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{51}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{51}
|
||||
}
|
||||
func (m *CloseChannelRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CloseChannelRequest.Unmarshal(m, b)
|
||||
@ -3368,7 +3371,7 @@ func (m *CloseStatusUpdate) Reset() { *m = CloseStatusUpdate{} }
|
||||
func (m *CloseStatusUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*CloseStatusUpdate) ProtoMessage() {}
|
||||
func (*CloseStatusUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{52}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{52}
|
||||
}
|
||||
func (m *CloseStatusUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CloseStatusUpdate.Unmarshal(m, b)
|
||||
@ -3511,7 +3514,7 @@ func (m *PendingUpdate) Reset() { *m = PendingUpdate{} }
|
||||
func (m *PendingUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*PendingUpdate) ProtoMessage() {}
|
||||
func (*PendingUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{53}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{53}
|
||||
}
|
||||
func (m *PendingUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingUpdate.Unmarshal(m, b)
|
||||
@ -3577,7 +3580,7 @@ func (m *OpenChannelRequest) Reset() { *m = OpenChannelRequest{} }
|
||||
func (m *OpenChannelRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*OpenChannelRequest) ProtoMessage() {}
|
||||
func (*OpenChannelRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{54}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{54}
|
||||
}
|
||||
func (m *OpenChannelRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_OpenChannelRequest.Unmarshal(m, b)
|
||||
@ -3688,7 +3691,7 @@ func (m *OpenStatusUpdate) Reset() { *m = OpenStatusUpdate{} }
|
||||
func (m *OpenStatusUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*OpenStatusUpdate) ProtoMessage() {}
|
||||
func (*OpenStatusUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{55}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{55}
|
||||
}
|
||||
func (m *OpenStatusUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_OpenStatusUpdate.Unmarshal(m, b)
|
||||
@ -3844,7 +3847,7 @@ func (m *PendingHTLC) Reset() { *m = PendingHTLC{} }
|
||||
func (m *PendingHTLC) String() string { return proto.CompactTextString(m) }
|
||||
func (*PendingHTLC) ProtoMessage() {}
|
||||
func (*PendingHTLC) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{56}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{56}
|
||||
}
|
||||
func (m *PendingHTLC) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingHTLC.Unmarshal(m, b)
|
||||
@ -3916,7 +3919,7 @@ func (m *PendingChannelsRequest) Reset() { *m = PendingChannelsRequest{}
|
||||
func (m *PendingChannelsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PendingChannelsRequest) ProtoMessage() {}
|
||||
func (*PendingChannelsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{57}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{57}
|
||||
}
|
||||
func (m *PendingChannelsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsRequest.Unmarshal(m, b)
|
||||
@ -3956,7 +3959,7 @@ func (m *PendingChannelsResponse) Reset() { *m = PendingChannelsResponse
|
||||
func (m *PendingChannelsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*PendingChannelsResponse) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{58}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{58}
|
||||
}
|
||||
func (m *PendingChannelsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse.Unmarshal(m, b)
|
||||
@ -4028,7 +4031,7 @@ func (m *PendingChannelsResponse_PendingChannel) Reset() {
|
||||
func (m *PendingChannelsResponse_PendingChannel) String() string { return proto.CompactTextString(m) }
|
||||
func (*PendingChannelsResponse_PendingChannel) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse_PendingChannel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{58, 0}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{58, 0}
|
||||
}
|
||||
func (m *PendingChannelsResponse_PendingChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_PendingChannel.Unmarshal(m, b)
|
||||
@ -4115,7 +4118,7 @@ func (m *PendingChannelsResponse_PendingOpenChannel) String() string {
|
||||
}
|
||||
func (*PendingChannelsResponse_PendingOpenChannel) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse_PendingOpenChannel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{58, 1}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{58, 1}
|
||||
}
|
||||
func (m *PendingChannelsResponse_PendingOpenChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_PendingOpenChannel.Unmarshal(m, b)
|
||||
@ -4188,7 +4191,7 @@ func (m *PendingChannelsResponse_WaitingCloseChannel) String() string {
|
||||
}
|
||||
func (*PendingChannelsResponse_WaitingCloseChannel) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse_WaitingCloseChannel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{58, 2}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{58, 2}
|
||||
}
|
||||
func (m *PendingChannelsResponse_WaitingCloseChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_WaitingCloseChannel.Unmarshal(m, b)
|
||||
@ -4236,7 +4239,7 @@ func (m *PendingChannelsResponse_ClosedChannel) Reset() { *m = PendingCh
|
||||
func (m *PendingChannelsResponse_ClosedChannel) String() string { return proto.CompactTextString(m) }
|
||||
func (*PendingChannelsResponse_ClosedChannel) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse_ClosedChannel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{58, 3}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{58, 3}
|
||||
}
|
||||
func (m *PendingChannelsResponse_ClosedChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_ClosedChannel.Unmarshal(m, b)
|
||||
@ -4300,7 +4303,7 @@ func (m *PendingChannelsResponse_ForceClosedChannel) String() string {
|
||||
}
|
||||
func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {}
|
||||
func (*PendingChannelsResponse_ForceClosedChannel) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{58, 4}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{58, 4}
|
||||
}
|
||||
func (m *PendingChannelsResponse_ForceClosedChannel) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PendingChannelsResponse_ForceClosedChannel.Unmarshal(m, b)
|
||||
@ -4379,7 +4382,7 @@ func (m *ChannelEventSubscription) Reset() { *m = ChannelEventSubscripti
|
||||
func (m *ChannelEventSubscription) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelEventSubscription) ProtoMessage() {}
|
||||
func (*ChannelEventSubscription) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{59}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{59}
|
||||
}
|
||||
func (m *ChannelEventSubscription) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelEventSubscription.Unmarshal(m, b)
|
||||
@ -4416,7 +4419,7 @@ func (m *ChannelEventUpdate) Reset() { *m = ChannelEventUpdate{} }
|
||||
func (m *ChannelEventUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelEventUpdate) ProtoMessage() {}
|
||||
func (*ChannelEventUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{60}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{60}
|
||||
}
|
||||
func (m *ChannelEventUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelEventUpdate.Unmarshal(m, b)
|
||||
@ -4628,7 +4631,7 @@ func (m *WalletBalanceRequest) Reset() { *m = WalletBalanceRequest{} }
|
||||
func (m *WalletBalanceRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*WalletBalanceRequest) ProtoMessage() {}
|
||||
func (*WalletBalanceRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{61}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{61}
|
||||
}
|
||||
func (m *WalletBalanceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_WalletBalanceRequest.Unmarshal(m, b)
|
||||
@ -4664,7 +4667,7 @@ func (m *WalletBalanceResponse) Reset() { *m = WalletBalanceResponse{} }
|
||||
func (m *WalletBalanceResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*WalletBalanceResponse) ProtoMessage() {}
|
||||
func (*WalletBalanceResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{62}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{62}
|
||||
}
|
||||
func (m *WalletBalanceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_WalletBalanceResponse.Unmarshal(m, b)
|
||||
@ -4715,7 +4718,7 @@ func (m *ChannelBalanceRequest) Reset() { *m = ChannelBalanceRequest{} }
|
||||
func (m *ChannelBalanceRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelBalanceRequest) ProtoMessage() {}
|
||||
func (*ChannelBalanceRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{63}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{63}
|
||||
}
|
||||
func (m *ChannelBalanceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelBalanceRequest.Unmarshal(m, b)
|
||||
@ -4749,7 +4752,7 @@ func (m *ChannelBalanceResponse) Reset() { *m = ChannelBalanceResponse{}
|
||||
func (m *ChannelBalanceResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelBalanceResponse) ProtoMessage() {}
|
||||
func (*ChannelBalanceResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{64}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{64}
|
||||
}
|
||||
func (m *ChannelBalanceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelBalanceResponse.Unmarshal(m, b)
|
||||
@ -4819,7 +4822,7 @@ func (m *QueryRoutesRequest) Reset() { *m = QueryRoutesRequest{} }
|
||||
func (m *QueryRoutesRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*QueryRoutesRequest) ProtoMessage() {}
|
||||
func (*QueryRoutesRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{65}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{65}
|
||||
}
|
||||
func (m *QueryRoutesRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_QueryRoutesRequest.Unmarshal(m, b)
|
||||
@ -4914,7 +4917,7 @@ func (m *EdgeLocator) Reset() { *m = EdgeLocator{} }
|
||||
func (m *EdgeLocator) String() string { return proto.CompactTextString(m) }
|
||||
func (*EdgeLocator) ProtoMessage() {}
|
||||
func (*EdgeLocator) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{66}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{66}
|
||||
}
|
||||
func (m *EdgeLocator) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EdgeLocator.Unmarshal(m, b)
|
||||
@ -4959,7 +4962,7 @@ func (m *QueryRoutesResponse) Reset() { *m = QueryRoutesResponse{} }
|
||||
func (m *QueryRoutesResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*QueryRoutesResponse) ProtoMessage() {}
|
||||
func (*QueryRoutesResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{67}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{67}
|
||||
}
|
||||
func (m *QueryRoutesResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_QueryRoutesResponse.Unmarshal(m, b)
|
||||
@ -5011,7 +5014,7 @@ func (m *Hop) Reset() { *m = Hop{} }
|
||||
func (m *Hop) String() string { return proto.CompactTextString(m) }
|
||||
func (*Hop) ProtoMessage() {}
|
||||
func (*Hop) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{68}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{68}
|
||||
}
|
||||
func (m *Hop) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Hop.Unmarshal(m, b)
|
||||
@ -5132,7 +5135,7 @@ func (m *Route) Reset() { *m = Route{} }
|
||||
func (m *Route) String() string { return proto.CompactTextString(m) }
|
||||
func (*Route) ProtoMessage() {}
|
||||
func (*Route) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{69}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{69}
|
||||
}
|
||||
func (m *Route) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Route.Unmarshal(m, b)
|
||||
@ -5208,7 +5211,7 @@ func (m *NodeInfoRequest) Reset() { *m = NodeInfoRequest{} }
|
||||
func (m *NodeInfoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*NodeInfoRequest) ProtoMessage() {}
|
||||
func (*NodeInfoRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{70}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{70}
|
||||
}
|
||||
func (m *NodeInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NodeInfoRequest.Unmarshal(m, b)
|
||||
@ -5253,7 +5256,7 @@ func (m *NodeInfo) Reset() { *m = NodeInfo{} }
|
||||
func (m *NodeInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*NodeInfo) ProtoMessage() {}
|
||||
func (*NodeInfo) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{71}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{71}
|
||||
}
|
||||
func (m *NodeInfo) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NodeInfo.Unmarshal(m, b)
|
||||
@ -5314,7 +5317,7 @@ func (m *LightningNode) Reset() { *m = LightningNode{} }
|
||||
func (m *LightningNode) String() string { return proto.CompactTextString(m) }
|
||||
func (*LightningNode) ProtoMessage() {}
|
||||
func (*LightningNode) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{72}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{72}
|
||||
}
|
||||
func (m *LightningNode) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_LightningNode.Unmarshal(m, b)
|
||||
@ -5381,7 +5384,7 @@ func (m *NodeAddress) Reset() { *m = NodeAddress{} }
|
||||
func (m *NodeAddress) String() string { return proto.CompactTextString(m) }
|
||||
func (*NodeAddress) ProtoMessage() {}
|
||||
func (*NodeAddress) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{73}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{73}
|
||||
}
|
||||
func (m *NodeAddress) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NodeAddress.Unmarshal(m, b)
|
||||
@ -5431,7 +5434,7 @@ func (m *RoutingPolicy) Reset() { *m = RoutingPolicy{} }
|
||||
func (m *RoutingPolicy) String() string { return proto.CompactTextString(m) }
|
||||
func (*RoutingPolicy) ProtoMessage() {}
|
||||
func (*RoutingPolicy) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{74}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{74}
|
||||
}
|
||||
func (m *RoutingPolicy) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RoutingPolicy.Unmarshal(m, b)
|
||||
@ -5521,7 +5524,7 @@ func (m *ChannelEdge) Reset() { *m = ChannelEdge{} }
|
||||
func (m *ChannelEdge) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelEdge) ProtoMessage() {}
|
||||
func (*ChannelEdge) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{75}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{75}
|
||||
}
|
||||
func (m *ChannelEdge) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelEdge.Unmarshal(m, b)
|
||||
@ -5612,7 +5615,7 @@ func (m *ChannelGraphRequest) Reset() { *m = ChannelGraphRequest{} }
|
||||
func (m *ChannelGraphRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelGraphRequest) ProtoMessage() {}
|
||||
func (*ChannelGraphRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{76}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{76}
|
||||
}
|
||||
func (m *ChannelGraphRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelGraphRequest.Unmarshal(m, b)
|
||||
@ -5654,7 +5657,7 @@ func (m *ChannelGraph) Reset() { *m = ChannelGraph{} }
|
||||
func (m *ChannelGraph) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelGraph) ProtoMessage() {}
|
||||
func (*ChannelGraph) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{77}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{77}
|
||||
}
|
||||
func (m *ChannelGraph) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelGraph.Unmarshal(m, b)
|
||||
@ -5703,7 +5706,7 @@ func (m *ChanInfoRequest) Reset() { *m = ChanInfoRequest{} }
|
||||
func (m *ChanInfoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChanInfoRequest) ProtoMessage() {}
|
||||
func (*ChanInfoRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{78}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{78}
|
||||
}
|
||||
func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChanInfoRequest.Unmarshal(m, b)
|
||||
@ -5740,7 +5743,7 @@ func (m *NetworkInfoRequest) Reset() { *m = NetworkInfoRequest{} }
|
||||
func (m *NetworkInfoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*NetworkInfoRequest) ProtoMessage() {}
|
||||
func (*NetworkInfoRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{79}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{79}
|
||||
}
|
||||
func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NetworkInfoRequest.Unmarshal(m, b)
|
||||
@ -5779,7 +5782,7 @@ func (m *NetworkInfo) Reset() { *m = NetworkInfo{} }
|
||||
func (m *NetworkInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*NetworkInfo) ProtoMessage() {}
|
||||
func (*NetworkInfo) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{80}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{80}
|
||||
}
|
||||
func (m *NetworkInfo) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NetworkInfo.Unmarshal(m, b)
|
||||
@ -5872,7 +5875,7 @@ func (m *StopRequest) Reset() { *m = StopRequest{} }
|
||||
func (m *StopRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*StopRequest) ProtoMessage() {}
|
||||
func (*StopRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{81}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{81}
|
||||
}
|
||||
func (m *StopRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_StopRequest.Unmarshal(m, b)
|
||||
@ -5902,7 +5905,7 @@ func (m *StopResponse) Reset() { *m = StopResponse{} }
|
||||
func (m *StopResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*StopResponse) ProtoMessage() {}
|
||||
func (*StopResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{82}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{82}
|
||||
}
|
||||
func (m *StopResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_StopResponse.Unmarshal(m, b)
|
||||
@ -5932,7 +5935,7 @@ func (m *GraphTopologySubscription) Reset() { *m = GraphTopologySubscrip
|
||||
func (m *GraphTopologySubscription) String() string { return proto.CompactTextString(m) }
|
||||
func (*GraphTopologySubscription) ProtoMessage() {}
|
||||
func (*GraphTopologySubscription) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{83}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{83}
|
||||
}
|
||||
func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GraphTopologySubscription.Unmarshal(m, b)
|
||||
@ -5965,7 +5968,7 @@ func (m *GraphTopologyUpdate) Reset() { *m = GraphTopologyUpdate{} }
|
||||
func (m *GraphTopologyUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*GraphTopologyUpdate) ProtoMessage() {}
|
||||
func (*GraphTopologyUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{84}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{84}
|
||||
}
|
||||
func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GraphTopologyUpdate.Unmarshal(m, b)
|
||||
@ -6020,7 +6023,7 @@ func (m *NodeUpdate) Reset() { *m = NodeUpdate{} }
|
||||
func (m *NodeUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*NodeUpdate) ProtoMessage() {}
|
||||
func (*NodeUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{85}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{85}
|
||||
}
|
||||
func (m *NodeUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NodeUpdate.Unmarshal(m, b)
|
||||
@ -6088,7 +6091,7 @@ func (m *ChannelEdgeUpdate) Reset() { *m = ChannelEdgeUpdate{} }
|
||||
func (m *ChannelEdgeUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelEdgeUpdate) ProtoMessage() {}
|
||||
func (*ChannelEdgeUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{86}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{86}
|
||||
}
|
||||
func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelEdgeUpdate.Unmarshal(m, b)
|
||||
@ -6168,7 +6171,7 @@ func (m *ClosedChannelUpdate) Reset() { *m = ClosedChannelUpdate{} }
|
||||
func (m *ClosedChannelUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*ClosedChannelUpdate) ProtoMessage() {}
|
||||
func (*ClosedChannelUpdate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{87}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{87}
|
||||
}
|
||||
func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ClosedChannelUpdate.Unmarshal(m, b)
|
||||
@ -6238,7 +6241,7 @@ func (m *HopHint) Reset() { *m = HopHint{} }
|
||||
func (m *HopHint) String() string { return proto.CompactTextString(m) }
|
||||
func (*HopHint) ProtoMessage() {}
|
||||
func (*HopHint) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{88}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{88}
|
||||
}
|
||||
func (m *HopHint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_HopHint.Unmarshal(m, b)
|
||||
@ -6307,7 +6310,7 @@ func (m *RouteHint) Reset() { *m = RouteHint{} }
|
||||
func (m *RouteHint) String() string { return proto.CompactTextString(m) }
|
||||
func (*RouteHint) ProtoMessage() {}
|
||||
func (*RouteHint) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{89}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{89}
|
||||
}
|
||||
func (m *RouteHint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RouteHint.Unmarshal(m, b)
|
||||
@ -6422,7 +6425,7 @@ func (m *Invoice) Reset() { *m = Invoice{} }
|
||||
func (m *Invoice) String() string { return proto.CompactTextString(m) }
|
||||
func (*Invoice) ProtoMessage() {}
|
||||
func (*Invoice) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{90}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{90}
|
||||
}
|
||||
func (m *Invoice) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Invoice.Unmarshal(m, b)
|
||||
@ -6614,7 +6617,7 @@ func (m *AddInvoiceResponse) Reset() { *m = AddInvoiceResponse{} }
|
||||
func (m *AddInvoiceResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*AddInvoiceResponse) ProtoMessage() {}
|
||||
func (*AddInvoiceResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{91}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{91}
|
||||
}
|
||||
func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AddInvoiceResponse.Unmarshal(m, b)
|
||||
@ -6671,7 +6674,7 @@ func (m *PaymentHash) Reset() { *m = PaymentHash{} }
|
||||
func (m *PaymentHash) String() string { return proto.CompactTextString(m) }
|
||||
func (*PaymentHash) ProtoMessage() {}
|
||||
func (*PaymentHash) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{92}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{92}
|
||||
}
|
||||
func (m *PaymentHash) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PaymentHash.Unmarshal(m, b)
|
||||
@ -6727,7 +6730,7 @@ func (m *ListInvoiceRequest) Reset() { *m = ListInvoiceRequest{} }
|
||||
func (m *ListInvoiceRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListInvoiceRequest) ProtoMessage() {}
|
||||
func (*ListInvoiceRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{93}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{93}
|
||||
}
|
||||
func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListInvoiceRequest.Unmarshal(m, b)
|
||||
@ -6797,7 +6800,7 @@ func (m *ListInvoiceResponse) Reset() { *m = ListInvoiceResponse{} }
|
||||
func (m *ListInvoiceResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListInvoiceResponse) ProtoMessage() {}
|
||||
func (*ListInvoiceResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{94}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{94}
|
||||
}
|
||||
func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListInvoiceResponse.Unmarshal(m, b)
|
||||
@ -6860,7 +6863,7 @@ func (m *InvoiceSubscription) Reset() { *m = InvoiceSubscription{} }
|
||||
func (m *InvoiceSubscription) String() string { return proto.CompactTextString(m) }
|
||||
func (*InvoiceSubscription) ProtoMessage() {}
|
||||
func (*InvoiceSubscription) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{95}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{95}
|
||||
}
|
||||
func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InvoiceSubscription.Unmarshal(m, b)
|
||||
@ -6920,7 +6923,7 @@ func (m *Payment) Reset() { *m = Payment{} }
|
||||
func (m *Payment) String() string { return proto.CompactTextString(m) }
|
||||
func (*Payment) ProtoMessage() {}
|
||||
func (*Payment) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{96}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{96}
|
||||
}
|
||||
func (m *Payment) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Payment.Unmarshal(m, b)
|
||||
@ -7007,7 +7010,7 @@ func (m *ListPaymentsRequest) Reset() { *m = ListPaymentsRequest{} }
|
||||
func (m *ListPaymentsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListPaymentsRequest) ProtoMessage() {}
|
||||
func (*ListPaymentsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{97}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{97}
|
||||
}
|
||||
func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListPaymentsRequest.Unmarshal(m, b)
|
||||
@ -7039,7 +7042,7 @@ func (m *ListPaymentsResponse) Reset() { *m = ListPaymentsResponse{} }
|
||||
func (m *ListPaymentsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListPaymentsResponse) ProtoMessage() {}
|
||||
func (*ListPaymentsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{98}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{98}
|
||||
}
|
||||
func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ListPaymentsResponse.Unmarshal(m, b)
|
||||
@ -7076,7 +7079,7 @@ func (m *DeleteAllPaymentsRequest) Reset() { *m = DeleteAllPaymentsReque
|
||||
func (m *DeleteAllPaymentsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteAllPaymentsRequest) ProtoMessage() {}
|
||||
func (*DeleteAllPaymentsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{99}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{99}
|
||||
}
|
||||
func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DeleteAllPaymentsRequest.Unmarshal(m, b)
|
||||
@ -7106,7 +7109,7 @@ func (m *DeleteAllPaymentsResponse) Reset() { *m = DeleteAllPaymentsResp
|
||||
func (m *DeleteAllPaymentsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteAllPaymentsResponse) ProtoMessage() {}
|
||||
func (*DeleteAllPaymentsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{100}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{100}
|
||||
}
|
||||
func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DeleteAllPaymentsResponse.Unmarshal(m, b)
|
||||
@ -7137,7 +7140,7 @@ func (m *AbandonChannelRequest) Reset() { *m = AbandonChannelRequest{} }
|
||||
func (m *AbandonChannelRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*AbandonChannelRequest) ProtoMessage() {}
|
||||
func (*AbandonChannelRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{101}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{101}
|
||||
}
|
||||
func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AbandonChannelRequest.Unmarshal(m, b)
|
||||
@ -7174,7 +7177,7 @@ func (m *AbandonChannelResponse) Reset() { *m = AbandonChannelResponse{}
|
||||
func (m *AbandonChannelResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*AbandonChannelResponse) ProtoMessage() {}
|
||||
func (*AbandonChannelResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{102}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{102}
|
||||
}
|
||||
func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AbandonChannelResponse.Unmarshal(m, b)
|
||||
@ -7206,7 +7209,7 @@ func (m *DebugLevelRequest) Reset() { *m = DebugLevelRequest{} }
|
||||
func (m *DebugLevelRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*DebugLevelRequest) ProtoMessage() {}
|
||||
func (*DebugLevelRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{103}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{103}
|
||||
}
|
||||
func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DebugLevelRequest.Unmarshal(m, b)
|
||||
@ -7251,7 +7254,7 @@ func (m *DebugLevelResponse) Reset() { *m = DebugLevelResponse{} }
|
||||
func (m *DebugLevelResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*DebugLevelResponse) ProtoMessage() {}
|
||||
func (*DebugLevelResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{104}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{104}
|
||||
}
|
||||
func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DebugLevelResponse.Unmarshal(m, b)
|
||||
@ -7290,7 +7293,7 @@ func (m *PayReqString) Reset() { *m = PayReqString{} }
|
||||
func (m *PayReqString) String() string { return proto.CompactTextString(m) }
|
||||
func (*PayReqString) ProtoMessage() {}
|
||||
func (*PayReqString) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{105}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{105}
|
||||
}
|
||||
func (m *PayReqString) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PayReqString.Unmarshal(m, b)
|
||||
@ -7337,7 +7340,7 @@ func (m *PayReq) Reset() { *m = PayReq{} }
|
||||
func (m *PayReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*PayReq) ProtoMessage() {}
|
||||
func (*PayReq) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{106}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{106}
|
||||
}
|
||||
func (m *PayReq) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PayReq.Unmarshal(m, b)
|
||||
@ -7437,7 +7440,7 @@ func (m *FeeReportRequest) Reset() { *m = FeeReportRequest{} }
|
||||
func (m *FeeReportRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*FeeReportRequest) ProtoMessage() {}
|
||||
func (*FeeReportRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{107}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{107}
|
||||
}
|
||||
func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FeeReportRequest.Unmarshal(m, b)
|
||||
@ -7475,7 +7478,7 @@ func (m *ChannelFeeReport) Reset() { *m = ChannelFeeReport{} }
|
||||
func (m *ChannelFeeReport) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChannelFeeReport) ProtoMessage() {}
|
||||
func (*ChannelFeeReport) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{108}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{108}
|
||||
}
|
||||
func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ChannelFeeReport.Unmarshal(m, b)
|
||||
@ -7541,7 +7544,7 @@ func (m *FeeReportResponse) Reset() { *m = FeeReportResponse{} }
|
||||
func (m *FeeReportResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*FeeReportResponse) ProtoMessage() {}
|
||||
func (*FeeReportResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{109}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{109}
|
||||
}
|
||||
func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FeeReportResponse.Unmarshal(m, b)
|
||||
@ -7609,7 +7612,7 @@ func (m *PolicyUpdateRequest) Reset() { *m = PolicyUpdateRequest{} }
|
||||
func (m *PolicyUpdateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PolicyUpdateRequest) ProtoMessage() {}
|
||||
func (*PolicyUpdateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{110}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{110}
|
||||
}
|
||||
func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PolicyUpdateRequest.Unmarshal(m, b)
|
||||
@ -7770,7 +7773,7 @@ func (m *PolicyUpdateResponse) Reset() { *m = PolicyUpdateResponse{} }
|
||||
func (m *PolicyUpdateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*PolicyUpdateResponse) ProtoMessage() {}
|
||||
func (*PolicyUpdateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{111}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{111}
|
||||
}
|
||||
func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PolicyUpdateResponse.Unmarshal(m, b)
|
||||
@ -7808,7 +7811,7 @@ func (m *ForwardingHistoryRequest) Reset() { *m = ForwardingHistoryReque
|
||||
func (m *ForwardingHistoryRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ForwardingHistoryRequest) ProtoMessage() {}
|
||||
func (*ForwardingHistoryRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{112}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{112}
|
||||
}
|
||||
func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ForwardingHistoryRequest.Unmarshal(m, b)
|
||||
@ -7880,7 +7883,7 @@ func (m *ForwardingEvent) Reset() { *m = ForwardingEvent{} }
|
||||
func (m *ForwardingEvent) String() string { return proto.CompactTextString(m) }
|
||||
func (*ForwardingEvent) ProtoMessage() {}
|
||||
func (*ForwardingEvent) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{113}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{113}
|
||||
}
|
||||
func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ForwardingEvent.Unmarshal(m, b)
|
||||
@ -7963,7 +7966,7 @@ func (m *ForwardingHistoryResponse) Reset() { *m = ForwardingHistoryResp
|
||||
func (m *ForwardingHistoryResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ForwardingHistoryResponse) ProtoMessage() {}
|
||||
func (*ForwardingHistoryResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_rpc_3ef4d8a7aac1a994, []int{114}
|
||||
return fileDescriptor_rpc_1d2b968b4af573ab, []int{114}
|
||||
}
|
||||
func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ForwardingHistoryResponse.Unmarshal(m, b)
|
||||
@ -10464,455 +10467,456 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{
|
||||
Metadata: "rpc.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_3ef4d8a7aac1a994) }
|
||||
func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_1d2b968b4af573ab) }
|
||||
|
||||
var fileDescriptor_rpc_3ef4d8a7aac1a994 = []byte{
|
||||
// 7142 bytes of a gzipped FileDescriptorProto
|
||||
var fileDescriptor_rpc_1d2b968b4af573ab = []byte{
|
||||
// 7154 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7c, 0x5d, 0x6c, 0x24, 0xd9,
|
||||
0x5d, 0xef, 0x54, 0x7f, 0xd8, 0xdd, 0xff, 0x6e, 0xb7, 0xdb, 0xc7, 0x5f, 0x3d, 0xbd, 0xb3, 0xb3,
|
||||
0xde, 0xca, 0xdc, 0x1d, 0xc7, 0xd9, 0x3b, 0x9e, 0x9d, 0x24, 0x9b, 0xcd, 0xee, 0xcd, 0xbd, 0xd7,
|
||||
0x63, 0x7b, 0xc6, 0x93, 0x78, 0x3d, 0x4e, 0x79, 0x26, 0x73, 0xb3, 0xc9, 0x55, 0xa7, 0xdc, 0x7d,
|
||||
0xdc, 0xae, 0x9d, 0xea, 0xaa, 0x4e, 0x55, 0xb5, 0x3d, 0xce, 0x32, 0x12, 0x02, 0x44, 0x24, 0x04,
|
||||
0x42, 0xc0, 0x0b, 0x41, 0x41, 0x48, 0x01, 0x09, 0xf2, 0xc8, 0x43, 0x10, 0x12, 0x1f, 0x4f, 0x88,
|
||||
0x07, 0x24, 0x84, 0x20, 0x8f, 0x48, 0x48, 0x08, 0x5e, 0x80, 0x07, 0x24, 0x24, 0x1e, 0x91, 0xd0,
|
||||
0xf9, 0x9f, 0x8f, 0x3a, 0xa7, 0xaa, 0x7a, 0x3c, 0x9b, 0x04, 0x9e, 0xec, 0xf3, 0x3b, 0xff, 0x3a,
|
||||
0x9f, 0xff, 0xaf, 0xf3, 0x3f, 0xff, 0xd3, 0x50, 0x8f, 0xc6, 0xfd, 0x5b, 0xe3, 0x28, 0x4c, 0x42,
|
||||
0x52, 0xf5, 0x83, 0x68, 0xdc, 0xef, 0x5e, 0x1b, 0x86, 0xe1, 0xd0, 0xa7, 0x9b, 0xee, 0xd8, 0xdb,
|
||||
0x74, 0x83, 0x20, 0x4c, 0xdc, 0xc4, 0x0b, 0x83, 0x98, 0x13, 0xd9, 0xdf, 0x80, 0xd6, 0x7d, 0x1a,
|
||||
0x1c, 0x51, 0x3a, 0x70, 0xe8, 0x37, 0x27, 0x34, 0x4e, 0xc8, 0xa7, 0x60, 0xc1, 0xa5, 0xdf, 0xa2,
|
||||
0x74, 0xd0, 0x1b, 0xbb, 0x71, 0x3c, 0x3e, 0x8d, 0xdc, 0x98, 0x76, 0xac, 0x35, 0x6b, 0xbd, 0xe9,
|
||||
0xb4, 0x79, 0xc5, 0xa1, 0xc2, 0xc9, 0xeb, 0xd0, 0x8c, 0x19, 0x29, 0x0d, 0x92, 0x28, 0x1c, 0x5f,
|
||||
0x74, 0x4a, 0x48, 0xd7, 0x60, 0xd8, 0x2e, 0x87, 0x6c, 0x1f, 0xe6, 0x55, 0x0f, 0xf1, 0x38, 0x0c,
|
||||
0x62, 0x4a, 0x6e, 0xc3, 0x52, 0xdf, 0x1b, 0x9f, 0xd2, 0xa8, 0x87, 0x1f, 0x8f, 0x02, 0x3a, 0x0a,
|
||||
0x03, 0xaf, 0xdf, 0xb1, 0xd6, 0xca, 0xeb, 0x75, 0x87, 0xf0, 0x3a, 0xf6, 0xc5, 0xfb, 0xa2, 0x86,
|
||||
0xdc, 0x84, 0x79, 0x1a, 0x70, 0x9c, 0x0e, 0xf0, 0x2b, 0xd1, 0x55, 0x2b, 0x85, 0xd9, 0x07, 0xf6,
|
||||
0x9f, 0x59, 0xb0, 0xf0, 0x20, 0xf0, 0x92, 0x27, 0xae, 0xef, 0xd3, 0x44, 0xce, 0xe9, 0x26, 0xcc,
|
||||
0x9f, 0x23, 0x80, 0x73, 0x3a, 0x0f, 0xa3, 0x81, 0x98, 0x51, 0x8b, 0xc3, 0x87, 0x02, 0x9d, 0x3a,
|
||||
0xb2, 0xd2, 0xd4, 0x91, 0x15, 0x2e, 0x57, 0x79, 0xca, 0x72, 0xdd, 0x84, 0xf9, 0x88, 0xf6, 0xc3,
|
||||
0x33, 0x1a, 0x5d, 0xf4, 0xce, 0xbd, 0x60, 0x10, 0x9e, 0x77, 0x2a, 0x6b, 0xd6, 0x7a, 0xd5, 0x69,
|
||||
0x49, 0xf8, 0x09, 0xa2, 0xf6, 0x12, 0x10, 0x7d, 0x16, 0x7c, 0xdd, 0xec, 0x21, 0x2c, 0x3e, 0x0e,
|
||||
0xfc, 0xb0, 0xff, 0xf4, 0x47, 0x9c, 0x5d, 0x41, 0xf7, 0xa5, 0xc2, 0xee, 0x57, 0x60, 0xc9, 0xec,
|
||||
0x48, 0x0c, 0x80, 0xc2, 0xf2, 0xf6, 0xa9, 0x1b, 0x0c, 0xa9, 0x6c, 0x52, 0x0e, 0xe1, 0x93, 0xd0,
|
||||
0xee, 0x4f, 0xa2, 0x88, 0x06, 0xb9, 0x31, 0xcc, 0x0b, 0x5c, 0x0d, 0xe2, 0x75, 0x68, 0x06, 0xf4,
|
||||
0x3c, 0x25, 0x13, 0x2c, 0x13, 0xd0, 0x73, 0x49, 0x62, 0x77, 0x60, 0x25, 0xdb, 0x8d, 0x18, 0xc0,
|
||||
0xdf, 0x5b, 0x50, 0x79, 0x9c, 0x3c, 0x0b, 0xc9, 0x2d, 0xa8, 0x24, 0x17, 0x63, 0xce, 0x98, 0xad,
|
||||
0x3b, 0xe4, 0x16, 0xf2, 0xfa, 0xad, 0xad, 0xc1, 0x20, 0xa2, 0x71, 0xfc, 0xe8, 0x62, 0x4c, 0x9d,
|
||||
0xa6, 0xcb, 0x0b, 0x3d, 0x46, 0x47, 0x3a, 0x30, 0x2b, 0xca, 0xd8, 0x61, 0xdd, 0x91, 0x45, 0x72,
|
||||
0x1d, 0xc0, 0x1d, 0x85, 0x93, 0x20, 0xe9, 0xc5, 0x6e, 0x82, 0x3b, 0x57, 0x76, 0x34, 0x84, 0x5c,
|
||||
0x83, 0xfa, 0xf8, 0x69, 0x2f, 0xee, 0x47, 0xde, 0x38, 0xc1, 0xdd, 0xaa, 0x3b, 0x29, 0x40, 0x3e,
|
||||
0x05, 0xb5, 0x70, 0x92, 0x8c, 0x43, 0x2f, 0x48, 0x3a, 0xd5, 0x35, 0x6b, 0xbd, 0x71, 0x67, 0x5e,
|
||||
0x8c, 0xe5, 0xe1, 0x24, 0x39, 0x64, 0xb0, 0xa3, 0x08, 0xc8, 0x0d, 0x98, 0xeb, 0x87, 0xc1, 0x89,
|
||||
0x17, 0x8d, 0xb8, 0x0c, 0x76, 0x66, 0xb0, 0x37, 0x13, 0xb4, 0xbf, 0x53, 0x82, 0xc6, 0xa3, 0xc8,
|
||||
0x0d, 0x62, 0xb7, 0xcf, 0x00, 0x36, 0xf4, 0xe4, 0x59, 0xef, 0xd4, 0x8d, 0x4f, 0x71, 0xb6, 0x75,
|
||||
0x47, 0x16, 0xc9, 0x0a, 0xcc, 0xf0, 0x81, 0xe2, 0x9c, 0xca, 0x8e, 0x28, 0x91, 0x37, 0x61, 0x21,
|
||||
0x98, 0x8c, 0x7a, 0x66, 0x5f, 0x65, 0xdc, 0xe9, 0x7c, 0x05, 0x5b, 0x80, 0x63, 0xb6, 0xd7, 0xbc,
|
||||
0x0b, 0x3e, 0x43, 0x0d, 0x21, 0x36, 0x34, 0x45, 0x89, 0x7a, 0xc3, 0x53, 0x3e, 0xcd, 0xaa, 0x63,
|
||||
0x60, 0xac, 0x8d, 0xc4, 0x1b, 0xd1, 0x5e, 0x9c, 0xb8, 0xa3, 0xb1, 0x98, 0x96, 0x86, 0x60, 0x7d,
|
||||
0x98, 0xb8, 0x7e, 0xef, 0x84, 0xd2, 0xb8, 0x33, 0x2b, 0xea, 0x15, 0x42, 0xde, 0x80, 0xd6, 0x80,
|
||||
0xc6, 0x49, 0x4f, 0x6c, 0x0a, 0x8d, 0x3b, 0x35, 0x94, 0xb8, 0x0c, 0xca, 0x38, 0xe3, 0x3e, 0x4d,
|
||||
0xb4, 0xd5, 0x89, 0x05, 0x07, 0xda, 0xfb, 0x40, 0x34, 0x78, 0x87, 0x26, 0xae, 0xe7, 0xc7, 0xe4,
|
||||
0x6d, 0x68, 0x26, 0x1a, 0x31, 0x6a, 0x98, 0x86, 0x62, 0x17, 0xed, 0x03, 0xc7, 0xa0, 0xb3, 0xef,
|
||||
0x43, 0xed, 0x1e, 0xa5, 0xfb, 0xde, 0xc8, 0x4b, 0xc8, 0x0a, 0x54, 0x4f, 0xbc, 0x67, 0x94, 0x33,
|
||||
0x74, 0x79, 0xef, 0x8a, 0xc3, 0x8b, 0xa4, 0x0b, 0xb3, 0x63, 0x1a, 0xf5, 0xa9, 0x5c, 0xfe, 0xbd,
|
||||
0x2b, 0x8e, 0x04, 0xee, 0xce, 0x42, 0xd5, 0x67, 0x1f, 0xdb, 0x7f, 0x53, 0x82, 0xc6, 0x11, 0x0d,
|
||||
0x94, 0xa0, 0x10, 0xa8, 0xb0, 0x29, 0x09, 0xe1, 0xc0, 0xff, 0xc9, 0x6b, 0xd0, 0xc0, 0x69, 0xc6,
|
||||
0x49, 0xe4, 0x05, 0x43, 0xc1, 0x9f, 0xc0, 0xa0, 0x23, 0x44, 0x48, 0x1b, 0xca, 0xee, 0x48, 0xf2,
|
||||
0x26, 0xfb, 0x97, 0x09, 0xd1, 0xd8, 0xbd, 0x18, 0x31, 0x79, 0x53, 0xbb, 0xd6, 0x74, 0x1a, 0x02,
|
||||
0xdb, 0x63, 0xdb, 0x76, 0x0b, 0x16, 0x75, 0x12, 0xd9, 0x7a, 0x15, 0x5b, 0x5f, 0xd0, 0x28, 0x45,
|
||||
0x27, 0x37, 0x61, 0x5e, 0xd2, 0x47, 0x7c, 0xb0, 0xb8, 0x8f, 0x75, 0xa7, 0x25, 0x60, 0x39, 0x85,
|
||||
0x75, 0x68, 0x9f, 0x78, 0x81, 0xeb, 0xf7, 0xfa, 0x7e, 0x72, 0xd6, 0x1b, 0x50, 0x3f, 0x71, 0x71,
|
||||
0x47, 0xab, 0x4e, 0x0b, 0xf1, 0x6d, 0x3f, 0x39, 0xdb, 0x61, 0x28, 0x79, 0x13, 0xea, 0x27, 0x94,
|
||||
0xf6, 0x70, 0x25, 0x3a, 0x35, 0x43, 0x3a, 0xe4, 0xea, 0x3a, 0xb5, 0x13, 0xb9, 0xce, 0xeb, 0xd0,
|
||||
0x0e, 0x27, 0xc9, 0x30, 0xf4, 0x82, 0x61, 0xaf, 0x7f, 0xea, 0x06, 0x3d, 0x6f, 0xd0, 0xa9, 0xaf,
|
||||
0x59, 0xeb, 0x15, 0xa7, 0x25, 0x71, 0xa6, 0x15, 0x1e, 0x0c, 0xec, 0x3f, 0xb4, 0xa0, 0xc9, 0x17,
|
||||
0x55, 0x18, 0x94, 0x1b, 0x30, 0x27, 0xc7, 0x4e, 0xa3, 0x28, 0x8c, 0x84, 0xa0, 0x98, 0x20, 0xd9,
|
||||
0x80, 0xb6, 0x04, 0xc6, 0x11, 0xf5, 0x46, 0xee, 0x90, 0x0a, 0xed, 0x93, 0xc3, 0xc9, 0x9d, 0xb4,
|
||||
0xc5, 0x28, 0x9c, 0x24, 0x5c, 0xa5, 0x37, 0xee, 0x34, 0xc5, 0xf0, 0x1d, 0x86, 0x39, 0x26, 0x09,
|
||||
0x13, 0x94, 0x82, 0x4d, 0x31, 0x30, 0xfb, 0x07, 0x16, 0x10, 0x36, 0xf4, 0x47, 0x21, 0x6f, 0x42,
|
||||
0xac, 0x69, 0x76, 0x3f, 0xad, 0x97, 0xde, 0xcf, 0xd2, 0xb4, 0xfd, 0x5c, 0x87, 0x19, 0x1c, 0x16,
|
||||
0x93, 0xfc, 0x72, 0x76, 0xe8, 0x77, 0x4b, 0x1d, 0xcb, 0x11, 0xf5, 0xc4, 0x86, 0x2a, 0x9f, 0x63,
|
||||
0xa5, 0x60, 0x8e, 0xbc, 0xca, 0xfe, 0x9e, 0x05, 0x4d, 0xb6, 0xfa, 0x01, 0xf5, 0x51, 0xab, 0x91,
|
||||
0xdb, 0x40, 0x4e, 0x26, 0xc1, 0x80, 0x6d, 0x56, 0xf2, 0xcc, 0x1b, 0xf4, 0x8e, 0x2f, 0x58, 0x57,
|
||||
0x38, 0xee, 0xbd, 0x2b, 0x4e, 0x41, 0x1d, 0x79, 0x13, 0xda, 0x06, 0x1a, 0x27, 0x11, 0x1f, 0xfd,
|
||||
0xde, 0x15, 0x27, 0x57, 0xc3, 0x16, 0x93, 0xe9, 0xcd, 0x49, 0xd2, 0xf3, 0x82, 0x01, 0x7d, 0x86,
|
||||
0xeb, 0x3f, 0xe7, 0x18, 0xd8, 0xdd, 0x16, 0x34, 0xf5, 0xef, 0xec, 0x0f, 0xa1, 0x26, 0xb5, 0x2e,
|
||||
0x6a, 0x9c, 0xcc, 0xb8, 0x1c, 0x0d, 0x21, 0x5d, 0xa8, 0x99, 0xa3, 0x70, 0x6a, 0x1f, 0xa7, 0x6f,
|
||||
0xfb, 0x7f, 0x43, 0x7b, 0x9f, 0xa9, 0xbe, 0xc0, 0x0b, 0x86, 0xc2, 0xec, 0x30, 0x7d, 0x3c, 0x9e,
|
||||
0x1c, 0x3f, 0xa5, 0x17, 0x82, 0xff, 0x44, 0x89, 0x09, 0xfd, 0x69, 0x18, 0x27, 0xa2, 0x1f, 0xfc,
|
||||
0xdf, 0xfe, 0x07, 0x0b, 0xe6, 0x19, 0x23, 0xbc, 0xef, 0x06, 0x17, 0x92, 0x0b, 0xf6, 0xa1, 0xc9,
|
||||
0x9a, 0x7a, 0x14, 0x6e, 0x71, 0xad, 0xce, 0xb5, 0xd5, 0xba, 0xd8, 0x8f, 0x0c, 0xf5, 0x2d, 0x9d,
|
||||
0x94, 0x39, 0x5b, 0x17, 0x8e, 0xf1, 0x35, 0x53, 0x2b, 0x89, 0x1b, 0x0d, 0x69, 0x82, 0xfa, 0x5e,
|
||||
0xe8, 0x7f, 0xe0, 0xd0, 0x76, 0x18, 0x9c, 0x90, 0x35, 0x68, 0xc6, 0x6e, 0xd2, 0x1b, 0xd3, 0x08,
|
||||
0xd7, 0x04, 0x55, 0x43, 0xd9, 0x81, 0xd8, 0x4d, 0x0e, 0x69, 0x74, 0xf7, 0x22, 0xa1, 0xdd, 0xff,
|
||||
0x03, 0x0b, 0xb9, 0x5e, 0x98, 0x36, 0x4a, 0xa7, 0xc8, 0xfe, 0x25, 0x4b, 0x50, 0x3d, 0x73, 0xfd,
|
||||
0x09, 0x15, 0x66, 0x88, 0x17, 0xde, 0x2d, 0xbd, 0x63, 0xd9, 0x6f, 0x40, 0x3b, 0x1d, 0xb6, 0x10,
|
||||
0x56, 0x02, 0x15, 0xb6, 0xd2, 0xa2, 0x01, 0xfc, 0xdf, 0xfe, 0xae, 0xc5, 0x09, 0xb7, 0x43, 0x4f,
|
||||
0xa9, 0x74, 0x46, 0xc8, 0x34, 0xbf, 0x24, 0x64, 0xff, 0x4f, 0x35, 0x79, 0x3f, 0xfe, 0x64, 0xc9,
|
||||
0x55, 0xa8, 0xc5, 0x34, 0x18, 0xf4, 0x5c, 0xdf, 0x47, 0xcd, 0x57, 0x73, 0x66, 0x59, 0x79, 0xcb,
|
||||
0xf7, 0xed, 0x9b, 0xb0, 0xa0, 0x8d, 0xee, 0x05, 0xf3, 0x38, 0x00, 0xb2, 0xef, 0xc5, 0xc9, 0xe3,
|
||||
0x20, 0x1e, 0x6b, 0x1a, 0xf3, 0x15, 0xa8, 0x8f, 0xbc, 0x00, 0x47, 0xc6, 0x59, 0xb1, 0xea, 0xd4,
|
||||
0x46, 0x5e, 0xc0, 0xc6, 0x15, 0x63, 0xa5, 0xfb, 0x4c, 0x54, 0x96, 0x44, 0xa5, 0xfb, 0x0c, 0x2b,
|
||||
0xed, 0x77, 0x60, 0xd1, 0x68, 0x4f, 0x74, 0xfd, 0x3a, 0x54, 0x27, 0xc9, 0xb3, 0x50, 0xda, 0xb3,
|
||||
0x86, 0xe0, 0x10, 0xe6, 0x19, 0x39, 0xbc, 0xc6, 0x7e, 0x0f, 0x16, 0x0e, 0xe8, 0xb9, 0xe0, 0x4c,
|
||||
0x39, 0x90, 0x37, 0x2e, 0xf5, 0x9a, 0xb0, 0xde, 0xbe, 0x05, 0x44, 0xff, 0x58, 0xf4, 0xaa, 0xf9,
|
||||
0x50, 0x96, 0xe1, 0x43, 0xd9, 0x6f, 0x00, 0x39, 0xf2, 0x86, 0xc1, 0xfb, 0x34, 0x8e, 0xdd, 0xa1,
|
||||
0x52, 0x6a, 0x6d, 0x28, 0x8f, 0xe2, 0xa1, 0x90, 0x3d, 0xf6, 0xaf, 0xfd, 0x69, 0x58, 0x34, 0xe8,
|
||||
0x44, 0xc3, 0xd7, 0xa0, 0x1e, 0x7b, 0xc3, 0xc0, 0x4d, 0x26, 0x11, 0x15, 0x4d, 0xa7, 0x80, 0x7d,
|
||||
0x0f, 0x96, 0xbe, 0x42, 0x23, 0xef, 0xe4, 0xe2, 0xb2, 0xe6, 0xcd, 0x76, 0x4a, 0xd9, 0x76, 0x76,
|
||||
0x61, 0x39, 0xd3, 0x8e, 0xe8, 0x9e, 0xb3, 0xaf, 0xd8, 0xc9, 0x9a, 0xc3, 0x0b, 0x9a, 0x30, 0x97,
|
||||
0x74, 0x61, 0xb6, 0x1f, 0x03, 0xd9, 0x0e, 0x83, 0x80, 0xf6, 0x93, 0x43, 0x4a, 0xa3, 0xf4, 0xd4,
|
||||
0x94, 0xf2, 0x6a, 0xe3, 0xce, 0xaa, 0x58, 0xd9, 0xac, 0x86, 0x10, 0x4c, 0x4c, 0xa0, 0x32, 0xa6,
|
||||
0xd1, 0x08, 0x1b, 0xae, 0x39, 0xf8, 0xbf, 0xbd, 0x0c, 0x8b, 0x46, 0xb3, 0xc2, 0xe1, 0x7d, 0x0b,
|
||||
0x96, 0x77, 0xbc, 0xb8, 0x9f, 0xef, 0xb0, 0x03, 0xb3, 0xe3, 0xc9, 0x71, 0x2f, 0x95, 0x44, 0x59,
|
||||
0x64, 0x3e, 0x52, 0xf6, 0x13, 0xd1, 0xd8, 0xcf, 0x5b, 0x50, 0xd9, 0x7b, 0xb4, 0xbf, 0xcd, 0x94,
|
||||
0x9f, 0x17, 0xf4, 0xc3, 0x11, 0x33, 0x20, 0x7c, 0xd2, 0xaa, 0x3c, 0x55, 0xc2, 0xae, 0x41, 0x1d,
|
||||
0xed, 0x0e, 0x73, 0xfb, 0xc4, 0x01, 0x27, 0x05, 0x98, 0xcb, 0x49, 0x9f, 0x8d, 0xbd, 0x08, 0x7d,
|
||||
0x4a, 0xe9, 0x29, 0x56, 0x50, 0x6f, 0xe6, 0x2b, 0xec, 0xef, 0x56, 0x61, 0x56, 0x58, 0x13, 0xec,
|
||||
0xaf, 0x9f, 0x78, 0x67, 0x54, 0x8c, 0x44, 0x94, 0x98, 0x4d, 0x8f, 0xe8, 0x28, 0x4c, 0x68, 0xcf,
|
||||
0xd8, 0x06, 0x13, 0x44, 0x97, 0x9a, 0x37, 0xd4, 0xe3, 0x4e, 0x78, 0x99, 0x53, 0x19, 0x20, 0x5b,
|
||||
0x2c, 0xe9, 0x51, 0x54, 0xd0, 0xa3, 0x90, 0x45, 0xb6, 0x12, 0x7d, 0x77, 0xec, 0xf6, 0xbd, 0xe4,
|
||||
0x42, 0xa8, 0x04, 0x55, 0x66, 0x6d, 0xfb, 0x61, 0xdf, 0xf5, 0x7b, 0xc7, 0xae, 0xef, 0x06, 0x7d,
|
||||
0x2a, 0xdd, 0x75, 0x03, 0x64, 0xae, 0xab, 0x18, 0x92, 0x24, 0xe3, 0xee, 0x6d, 0x06, 0x65, 0x06,
|
||||
0xa9, 0x1f, 0x8e, 0x46, 0x5e, 0xc2, 0x3c, 0x5e, 0xf4, 0x86, 0xca, 0x8e, 0x86, 0xf0, 0xc3, 0x01,
|
||||
0x96, 0xce, 0xf9, 0xea, 0xd5, 0xe5, 0xe1, 0x40, 0x03, 0x59, 0x2b, 0xcc, 0xa5, 0x62, 0x6a, 0xec,
|
||||
0xe9, 0x79, 0x07, 0x78, 0x2b, 0x29, 0xc2, 0xf6, 0x61, 0x12, 0xc4, 0x34, 0x49, 0x7c, 0x3a, 0x50,
|
||||
0x03, 0x6a, 0x20, 0x59, 0xbe, 0x82, 0xdc, 0x86, 0x45, 0xee, 0x84, 0xc7, 0x6e, 0x12, 0xc6, 0xa7,
|
||||
0x5e, 0xdc, 0x8b, 0x99, 0x3b, 0xdb, 0x44, 0xfa, 0xa2, 0x2a, 0xf2, 0x0e, 0xac, 0x66, 0xe0, 0x88,
|
||||
0xf6, 0xa9, 0x77, 0x46, 0x07, 0x9d, 0x39, 0xfc, 0x6a, 0x5a, 0x35, 0x59, 0x83, 0x06, 0x3b, 0x7b,
|
||||
0x4c, 0xc6, 0x03, 0x97, 0x59, 0xe4, 0x16, 0xee, 0x83, 0x0e, 0x91, 0xb7, 0x60, 0x6e, 0x4c, 0xb9,
|
||||
0x39, 0x3f, 0x4d, 0xfc, 0x7e, 0xdc, 0x99, 0x37, 0xb4, 0x1b, 0xe3, 0x5c, 0xc7, 0xa4, 0x60, 0x4c,
|
||||
0xd9, 0x8f, 0xd1, 0x09, 0x75, 0x2f, 0x3a, 0x6d, 0x64, 0xb7, 0x14, 0x40, 0x19, 0x89, 0xbc, 0x33,
|
||||
0x37, 0xa1, 0x9d, 0x05, 0xae, 0xd0, 0x45, 0x91, 0x7d, 0xe7, 0x05, 0x5e, 0xe2, 0xb9, 0x49, 0x18,
|
||||
0x75, 0x08, 0xd6, 0xa5, 0x80, 0xfd, 0x5b, 0x16, 0x57, 0xbb, 0x82, 0x45, 0x95, 0xfa, 0x7c, 0x0d,
|
||||
0x1a, 0x9c, 0x39, 0x7b, 0x61, 0xe0, 0x5f, 0x08, 0x7e, 0x05, 0x0e, 0x3d, 0x0c, 0xfc, 0x0b, 0xf2,
|
||||
0x09, 0x98, 0xf3, 0x02, 0x9d, 0x84, 0x4b, 0x78, 0x53, 0x82, 0x48, 0xf4, 0x1a, 0x34, 0xc6, 0x93,
|
||||
0x63, 0xdf, 0xeb, 0x73, 0x92, 0x32, 0x6f, 0x85, 0x43, 0x48, 0xc0, 0x9c, 0x41, 0x3e, 0x4e, 0x4e,
|
||||
0x51, 0x41, 0x8a, 0x86, 0xc0, 0x18, 0x89, 0x7d, 0x17, 0x96, 0xcc, 0x01, 0x0a, 0x55, 0xb6, 0x01,
|
||||
0x35, 0xc1, 0xf9, 0x71, 0xa7, 0x81, 0xab, 0xd7, 0x12, 0xab, 0x27, 0x48, 0x1d, 0x55, 0x6f, 0xff,
|
||||
0x41, 0x05, 0x16, 0x05, 0xba, 0xed, 0x87, 0x31, 0x3d, 0x9a, 0x8c, 0x46, 0x6e, 0x54, 0x20, 0x52,
|
||||
0xd6, 0x25, 0x22, 0x55, 0x32, 0x45, 0x8a, 0x31, 0xfa, 0xa9, 0xeb, 0x05, 0xdc, 0x93, 0xe5, 0xf2,
|
||||
0xa8, 0x21, 0x64, 0x1d, 0xe6, 0xfb, 0x7e, 0x18, 0x73, 0xaf, 0x4d, 0x3f, 0x74, 0x66, 0xe1, 0xbc,
|
||||
0x0a, 0xa8, 0x16, 0xa9, 0x00, 0x5d, 0x84, 0x67, 0x32, 0x22, 0x6c, 0x43, 0x93, 0x35, 0x4a, 0xa5,
|
||||
0x46, 0x9a, 0xe5, 0x9e, 0x9c, 0x8e, 0xb1, 0xf1, 0x64, 0x05, 0x86, 0x4b, 0xe7, 0x7c, 0x91, 0xb8,
|
||||
0xb0, 0x33, 0x2d, 0xd3, 0x78, 0x1a, 0x75, 0x5d, 0x88, 0x4b, 0xbe, 0x8a, 0xdc, 0x03, 0xe0, 0x7d,
|
||||
0xa1, 0xd9, 0x05, 0x34, 0xbb, 0x6f, 0x98, 0x3b, 0xa2, 0xaf, 0xfd, 0x2d, 0x56, 0x98, 0x44, 0x14,
|
||||
0x4d, 0xb1, 0xf6, 0xa5, 0xfd, 0x0b, 0x16, 0x34, 0xb4, 0x3a, 0xb2, 0x0c, 0x0b, 0xdb, 0x0f, 0x1f,
|
||||
0x1e, 0xee, 0x3a, 0x5b, 0x8f, 0x1e, 0x7c, 0x65, 0xb7, 0xb7, 0xbd, 0xff, 0xf0, 0x68, 0xb7, 0x7d,
|
||||
0x85, 0xc1, 0xfb, 0x0f, 0xb7, 0xb7, 0xf6, 0x7b, 0xf7, 0x1e, 0x3a, 0xdb, 0x12, 0xb6, 0xc8, 0x0a,
|
||||
0x10, 0x67, 0xf7, 0xfd, 0x87, 0x8f, 0x76, 0x0d, 0xbc, 0x44, 0xda, 0xd0, 0xbc, 0xeb, 0xec, 0x6e,
|
||||
0x6d, 0xef, 0x09, 0xa4, 0x4c, 0x96, 0xa0, 0x7d, 0xef, 0xf1, 0xc1, 0xce, 0x83, 0x83, 0xfb, 0xbd,
|
||||
0xed, 0xad, 0x83, 0xed, 0xdd, 0xfd, 0xdd, 0x9d, 0x76, 0x85, 0xcc, 0x41, 0x7d, 0xeb, 0xee, 0xd6,
|
||||
0xc1, 0xce, 0xc3, 0x83, 0xdd, 0x9d, 0x76, 0xd5, 0xfe, 0x3b, 0x0b, 0x96, 0x71, 0xd4, 0x83, 0xac,
|
||||
0x80, 0xac, 0x41, 0xa3, 0x1f, 0x86, 0x63, 0xca, 0xb4, 0xbd, 0x52, 0xe8, 0x3a, 0xc4, 0x98, 0x9f,
|
||||
0xab, 0xcf, 0x93, 0x30, 0xea, 0x53, 0x21, 0x1f, 0x80, 0xd0, 0x3d, 0x86, 0x30, 0xe6, 0x17, 0xdb,
|
||||
0xcb, 0x29, 0xb8, 0x78, 0x34, 0x38, 0xc6, 0x49, 0x56, 0x60, 0xe6, 0x38, 0xa2, 0x6e, 0xff, 0x54,
|
||||
0x48, 0x86, 0x28, 0x91, 0x4f, 0xa6, 0x07, 0x8c, 0x3e, 0x5b, 0x7d, 0x9f, 0x0e, 0x90, 0x63, 0x6a,
|
||||
0xce, 0xbc, 0xc0, 0xb7, 0x05, 0xcc, 0xe4, 0xdf, 0x3d, 0x76, 0x83, 0x41, 0x18, 0xd0, 0x81, 0x70,
|
||||
0xf6, 0x52, 0xc0, 0x3e, 0x84, 0x95, 0xec, 0xfc, 0x84, 0x7c, 0xbd, 0xad, 0xc9, 0x17, 0xf7, 0xbd,
|
||||
0xba, 0xd3, 0x77, 0x53, 0x93, 0xb5, 0x7f, 0xb6, 0xa0, 0xc2, 0x4c, 0xf1, 0x74, 0xb3, 0xad, 0x7b,
|
||||
0x57, 0xe5, 0x5c, 0x84, 0x0a, 0xcf, 0x2c, 0x5c, 0x39, 0x73, 0x03, 0xa6, 0x21, 0x69, 0x7d, 0x44,
|
||||
0xfb, 0x67, 0x38, 0x63, 0x55, 0xcf, 0x10, 0x26, 0x20, 0xcc, 0xf5, 0xc5, 0xaf, 0x85, 0x80, 0xc8,
|
||||
0xb2, 0xac, 0xc3, 0x2f, 0x67, 0xd3, 0x3a, 0xfc, 0xae, 0x03, 0xb3, 0x5e, 0x70, 0x1c, 0x4e, 0x82,
|
||||
0x01, 0x0a, 0x44, 0xcd, 0x91, 0x45, 0x8c, 0x89, 0xa1, 0xa0, 0x7a, 0x23, 0xc9, 0xfe, 0x29, 0x60,
|
||||
0x13, 0x76, 0x34, 0x8a, 0xd1, 0xf5, 0x50, 0xe1, 0x99, 0xb7, 0x61, 0x41, 0xc3, 0x52, 0x37, 0x76,
|
||||
0xcc, 0x80, 0x8c, 0x1b, 0x8b, 0x3e, 0x0b, 0xaf, 0xb1, 0xdb, 0xd0, 0xba, 0x4f, 0x93, 0x07, 0xc1,
|
||||
0x49, 0x28, 0x5b, 0xfa, 0xdd, 0x0a, 0xcc, 0x2b, 0x48, 0x34, 0xb4, 0x0e, 0xf3, 0xde, 0x80, 0x06,
|
||||
0x89, 0x97, 0x5c, 0xf4, 0x8c, 0x13, 0x58, 0x16, 0x66, 0xbe, 0x9e, 0xeb, 0x7b, 0xae, 0x8c, 0x02,
|
||||
0xf2, 0x02, 0xb9, 0x03, 0x4b, 0xcc, 0x10, 0x49, 0xdb, 0xa2, 0xb6, 0x98, 0x1f, 0xfc, 0x0a, 0xeb,
|
||||
0x98, 0x32, 0x60, 0xb8, 0xd0, 0xf6, 0xea, 0x13, 0xee, 0xf3, 0x14, 0x55, 0xb1, 0x55, 0xe3, 0x2d,
|
||||
0xb1, 0x29, 0x57, 0xb9, 0xb1, 0x52, 0x40, 0x2e, 0xcc, 0x36, 0xc3, 0x55, 0x55, 0x36, 0xcc, 0xa6,
|
||||
0x85, 0xea, 0x6a, 0xb9, 0x50, 0x1d, 0x53, 0x65, 0x17, 0x41, 0x9f, 0x0e, 0x7a, 0x49, 0xd8, 0x43,
|
||||
0x95, 0x8b, 0xbb, 0x53, 0x73, 0xb2, 0x30, 0xb9, 0x06, 0xb3, 0x09, 0x8d, 0x93, 0x80, 0x26, 0xa8,
|
||||
0x95, 0x6a, 0x18, 0x10, 0x90, 0x10, 0x73, 0x50, 0x27, 0x91, 0x17, 0x77, 0x9a, 0x18, 0x84, 0xc3,
|
||||
0xff, 0xc9, 0x67, 0x60, 0xf9, 0x98, 0xc6, 0x49, 0xef, 0x94, 0xba, 0x03, 0x1a, 0xe1, 0x4e, 0xf3,
|
||||
0x68, 0x1f, 0xb7, 0xfb, 0xc5, 0x95, 0x8c, 0x87, 0xce, 0x68, 0x14, 0x7b, 0x61, 0x80, 0x16, 0xbf,
|
||||
0xee, 0xc8, 0x22, 0x6b, 0x8f, 0x4d, 0x5e, 0xd9, 0x4b, 0xb5, 0x82, 0xf3, 0x38, 0xf1, 0xe2, 0x4a,
|
||||
0x72, 0x03, 0x66, 0x70, 0x02, 0x71, 0xa7, 0x6d, 0x44, 0x35, 0xb6, 0x19, 0xe8, 0x88, 0xba, 0x2f,
|
||||
0x56, 0x6a, 0x8d, 0x76, 0xd3, 0xfe, 0x1c, 0x54, 0x11, 0x66, 0x9b, 0xce, 0x17, 0x83, 0x33, 0x05,
|
||||
0x2f, 0xb0, 0xa1, 0x05, 0x34, 0x39, 0x0f, 0xa3, 0xa7, 0x32, 0x24, 0x2c, 0x8a, 0xf6, 0xb7, 0xd0,
|
||||
0xc5, 0x57, 0x21, 0xd2, 0xc7, 0xe8, 0x9f, 0xb0, 0x83, 0x1a, 0x5f, 0xea, 0xf8, 0xd4, 0x15, 0xa7,
|
||||
0x8e, 0x1a, 0x02, 0x47, 0xa7, 0x2e, 0x53, 0x5b, 0xc6, 0xee, 0xf1, 0x83, 0x5c, 0x03, 0xb1, 0x3d,
|
||||
0xbe, 0x79, 0x37, 0xa0, 0x25, 0x83, 0xaf, 0x71, 0xcf, 0xa7, 0x27, 0x89, 0x8c, 0x2b, 0x04, 0x93,
|
||||
0x11, 0x9e, 0xf6, 0xf6, 0xe9, 0x49, 0x62, 0x1f, 0xc0, 0x82, 0x50, 0x25, 0x0f, 0xc7, 0x54, 0x76,
|
||||
0xfd, 0xf9, 0x22, 0x93, 0xdc, 0xb8, 0xb3, 0x68, 0xea, 0x1e, 0x1e, 0x6e, 0x36, 0x29, 0x6d, 0x07,
|
||||
0x88, 0xae, 0x9a, 0x44, 0x83, 0xc2, 0x2e, 0xca, 0xc8, 0x89, 0x98, 0x8e, 0x81, 0xb1, 0xf5, 0x89,
|
||||
0x27, 0xfd, 0xbe, 0x0c, 0x99, 0xb3, 0xe3, 0x30, 0x2f, 0xda, 0xbf, 0x67, 0xc1, 0x22, 0xb6, 0x26,
|
||||
0x9d, 0x0a, 0xa1, 0xfe, 0xdf, 0xf9, 0x18, 0xc3, 0x6c, 0xf6, 0xf5, 0x68, 0xd2, 0x12, 0x54, 0x75,
|
||||
0x83, 0xc0, 0x0b, 0x1f, 0xff, 0x50, 0x5f, 0xc9, 0x1e, 0xea, 0xed, 0x5f, 0xb7, 0x60, 0x81, 0xeb,
|
||||
0xe4, 0xc4, 0x4d, 0x26, 0xb1, 0x98, 0xfe, 0xff, 0x82, 0x39, 0x6e, 0x5c, 0x85, 0x54, 0x8b, 0x81,
|
||||
0x2e, 0x29, 0x05, 0x84, 0x28, 0x27, 0xde, 0xbb, 0xe2, 0x98, 0xc4, 0xe4, 0x3d, 0x74, 0x70, 0x82,
|
||||
0x1e, 0xa2, 0x22, 0x30, 0x78, 0xb5, 0xc0, 0x0c, 0xa8, 0xef, 0x35, 0xf2, 0xbb, 0x35, 0x98, 0xe1,
|
||||
0xfe, 0xae, 0x7d, 0x1f, 0xe6, 0x8c, 0x8e, 0x8c, 0x80, 0x42, 0x93, 0x07, 0x14, 0x72, 0xa1, 0xa8,
|
||||
0x52, 0x41, 0x28, 0xea, 0xf7, 0xcb, 0x40, 0x18, 0xb3, 0x64, 0x76, 0x83, 0x39, 0xdc, 0xe1, 0xc0,
|
||||
0x38, 0x3e, 0x35, 0x1d, 0x1d, 0x22, 0xb7, 0x80, 0x68, 0x45, 0x19, 0x51, 0xe4, 0xd6, 0xa7, 0xa0,
|
||||
0x86, 0xa9, 0x49, 0x61, 0xbc, 0x85, 0x99, 0x15, 0x07, 0x45, 0xbe, 0xec, 0x85, 0x75, 0xcc, 0xc0,
|
||||
0x8c, 0x27, 0xf1, 0x29, 0x5e, 0xae, 0x88, 0x03, 0x96, 0x2c, 0x67, 0xf7, 0x77, 0xe6, 0xd2, 0xfd,
|
||||
0x9d, 0xcd, 0x05, 0x6d, 0x34, 0x17, 0xbf, 0x66, 0xba, 0xf8, 0x37, 0x60, 0x6e, 0xc4, 0x5c, 0xce,
|
||||
0xc4, 0xef, 0xf7, 0x46, 0xac, 0x77, 0x71, 0x9e, 0x32, 0x40, 0xb2, 0x01, 0x6d, 0xe1, 0x6e, 0xa4,
|
||||
0xe7, 0x08, 0xc0, 0x35, 0xce, 0xe1, 0x4c, 0x7f, 0xa7, 0x61, 0x9c, 0x06, 0x0e, 0x36, 0x05, 0xd8,
|
||||
0xc9, 0x2b, 0x66, 0x1c, 0xd2, 0x9b, 0x04, 0xe2, 0x7e, 0x85, 0x0e, 0xf0, 0x24, 0x55, 0x73, 0xf2,
|
||||
0x15, 0xf6, 0xaf, 0x5a, 0xd0, 0x66, 0x7b, 0x66, 0xb0, 0xe5, 0xbb, 0x80, 0x52, 0xf1, 0x92, 0x5c,
|
||||
0x69, 0xd0, 0x92, 0x77, 0xa0, 0x8e, 0xe5, 0x70, 0x4c, 0x03, 0xc1, 0x93, 0x1d, 0x93, 0x27, 0x53,
|
||||
0x7d, 0xb2, 0x77, 0xc5, 0x49, 0x89, 0x35, 0x8e, 0xfc, 0x2b, 0x0b, 0x1a, 0xa2, 0x97, 0x1f, 0x39,
|
||||
0x4c, 0xd0, 0xd5, 0x2e, 0xc4, 0x38, 0x27, 0xa5, 0xf7, 0x5f, 0xeb, 0x30, 0x3f, 0x72, 0x93, 0x49,
|
||||
0xc4, 0xec, 0xb1, 0x11, 0x22, 0xc8, 0xc2, 0xcc, 0xb8, 0xa2, 0xea, 0x8c, 0x7b, 0x89, 0xe7, 0xf7,
|
||||
0x64, 0xad, 0xb8, 0x7a, 0x2a, 0xaa, 0x62, 0x1a, 0x24, 0x4e, 0xdc, 0x21, 0x15, 0x76, 0x93, 0x17,
|
||||
0xec, 0x0e, 0xac, 0x88, 0x09, 0x65, 0x5c, 0x55, 0xfb, 0x4f, 0x9a, 0xb0, 0x9a, 0xab, 0x52, 0xf7,
|
||||
0xd3, 0xe2, 0xec, 0xeb, 0x7b, 0xa3, 0xe3, 0x50, 0xf9, 0xf9, 0x96, 0x7e, 0x2c, 0x36, 0xaa, 0xc8,
|
||||
0x10, 0x96, 0xa5, 0x83, 0xc0, 0xd6, 0x34, 0x35, 0x66, 0x25, 0xb4, 0x52, 0x6f, 0x99, 0x5b, 0x98,
|
||||
0xed, 0x50, 0xe2, 0xba, 0x10, 0x17, 0xb7, 0x47, 0x4e, 0xa1, 0xa3, 0x3c, 0x11, 0xa1, 0xac, 0x35,
|
||||
0x6f, 0x85, 0xf5, 0xf5, 0xe6, 0x25, 0x7d, 0x19, 0x9e, 0xad, 0x33, 0xb5, 0x35, 0x72, 0x01, 0xd7,
|
||||
0x65, 0x1d, 0x6a, 0xe3, 0x7c, 0x7f, 0x95, 0x97, 0x9a, 0x1b, 0xfa, 0xec, 0x66, 0xa7, 0x97, 0x34,
|
||||
0x4c, 0x3e, 0x84, 0x95, 0x73, 0xd7, 0x4b, 0xe4, 0xb0, 0x34, 0xdf, 0xa0, 0x8a, 0x5d, 0xde, 0xb9,
|
||||
0xa4, 0xcb, 0x27, 0xfc, 0x63, 0xc3, 0x44, 0x4d, 0x69, 0xb1, 0xfb, 0x17, 0x16, 0xb4, 0xcc, 0x76,
|
||||
0x18, 0x9b, 0x0a, 0xd9, 0x97, 0x3a, 0x50, 0x7a, 0x93, 0x19, 0x38, 0x7f, 0x54, 0x2e, 0x15, 0x1d,
|
||||
0x95, 0xf5, 0x03, 0x6a, 0xf9, 0xb2, 0x18, 0x53, 0xe5, 0xe5, 0x62, 0x4c, 0xd5, 0xa2, 0x18, 0x53,
|
||||
0xf7, 0xdf, 0x2d, 0x20, 0x79, 0x5e, 0x22, 0xf7, 0xf9, 0x59, 0x3d, 0xa0, 0xbe, 0x50, 0x29, 0xff,
|
||||
0xf3, 0xe5, 0xf8, 0x51, 0xae, 0x9d, 0xfc, 0x9a, 0x09, 0x86, 0x7e, 0x77, 0xac, 0x3b, 0x3b, 0x73,
|
||||
0x4e, 0x51, 0x55, 0x26, 0xea, 0x55, 0xb9, 0x3c, 0xea, 0x55, 0xbd, 0x3c, 0xea, 0x35, 0x93, 0x8d,
|
||||
0x7a, 0x75, 0x7f, 0xce, 0x82, 0xc5, 0x82, 0x4d, 0xff, 0xc9, 0x4d, 0x9c, 0x6d, 0x93, 0xa1, 0x0b,
|
||||
0x4a, 0x62, 0x9b, 0x74, 0xb0, 0xfb, 0x53, 0x30, 0x67, 0x30, 0xfa, 0x4f, 0xae, 0xff, 0xac, 0xbf,
|
||||
0xc6, 0xf9, 0xcc, 0xc0, 0xba, 0xff, 0x52, 0x02, 0x92, 0x17, 0xb6, 0xff, 0xd6, 0x31, 0xe4, 0xd7,
|
||||
0xa9, 0x5c, 0xb0, 0x4e, 0xff, 0xa5, 0x76, 0xe0, 0x4d, 0x58, 0x10, 0xc9, 0x2c, 0x5a, 0x84, 0x86,
|
||||
0x73, 0x4c, 0xbe, 0x82, 0x79, 0xac, 0x66, 0xc8, 0xb1, 0x66, 0x24, 0x08, 0x68, 0xc6, 0x30, 0x13,
|
||||
0x79, 0xb4, 0xbb, 0xd0, 0x11, 0x2b, 0xb4, 0x7b, 0x46, 0x83, 0xe4, 0x68, 0x72, 0xcc, 0x33, 0x42,
|
||||
0xbc, 0x30, 0xb0, 0x7f, 0x50, 0x56, 0x4e, 0x37, 0x56, 0x0a, 0xf3, 0xfe, 0x19, 0x68, 0xea, 0xca,
|
||||
0x5c, 0x6c, 0x47, 0x26, 0x40, 0xc7, 0x0c, 0xbb, 0x4e, 0x45, 0x76, 0xa0, 0x85, 0x2a, 0x6b, 0xa0,
|
||||
0xbe, 0x2b, 0xe1, 0x77, 0x2f, 0x08, 0x3c, 0xec, 0x5d, 0x71, 0x32, 0xdf, 0x90, 0x2f, 0x40, 0xcb,
|
||||
0x3c, 0x4a, 0x09, 0x1f, 0xa1, 0xc8, 0x37, 0x67, 0x9f, 0x9b, 0xc4, 0x64, 0x0b, 0xda, 0xd9, 0xb3,
|
||||
0x98, 0xb8, 0x2d, 0x9e, 0xd2, 0x40, 0x8e, 0x9c, 0xbc, 0x23, 0xee, 0x9e, 0xaa, 0x18, 0x04, 0xbb,
|
||||
0x61, 0x7e, 0xa6, 0x2d, 0xd3, 0x2d, 0xfe, 0x47, 0xbb, 0x8d, 0xfa, 0x3a, 0x40, 0x8a, 0x91, 0x36,
|
||||
0x34, 0x1f, 0x1e, 0xee, 0x1e, 0xf4, 0xb6, 0xf7, 0xb6, 0x0e, 0x0e, 0x76, 0xf7, 0xdb, 0x57, 0x08,
|
||||
0x81, 0x16, 0xc6, 0xaf, 0x76, 0x14, 0x66, 0x31, 0x6c, 0x6b, 0x9b, 0xc7, 0xc6, 0x04, 0x56, 0x22,
|
||||
0x4b, 0xd0, 0x7e, 0x70, 0x90, 0x41, 0xcb, 0x77, 0xeb, 0x4a, 0x3e, 0xec, 0x15, 0x58, 0xe2, 0x09,
|
||||
0x4f, 0x77, 0x39, 0x7b, 0x48, 0x5f, 0xe1, 0x37, 0x2d, 0x58, 0xce, 0x54, 0xa4, 0x89, 0x07, 0xdc,
|
||||
0x1d, 0x30, 0x7d, 0x04, 0x13, 0x64, 0x3c, 0xa9, 0x3c, 0xbf, 0x8c, 0x06, 0xc9, 0x57, 0x30, 0x9e,
|
||||
0xd7, 0x3c, 0xc5, 0x8c, 0x24, 0x15, 0x55, 0xd9, 0xab, 0x3c, 0x2d, 0x2b, 0xa0, 0x7e, 0x66, 0xe0,
|
||||
0x27, 0x3c, 0x91, 0x4a, 0xaf, 0x48, 0xef, 0xf2, 0xcc, 0x21, 0xcb, 0x22, 0x73, 0xf2, 0x0d, 0xd7,
|
||||
0xc3, 0x1c, 0x6f, 0x61, 0x9d, 0xfd, 0xa7, 0x25, 0x20, 0x5f, 0x9e, 0xd0, 0xe8, 0x02, 0x73, 0x06,
|
||||
0x54, 0x38, 0x70, 0x35, 0x1b, 0xec, 0x9a, 0x19, 0x4f, 0x8e, 0xbf, 0x44, 0x2f, 0x64, 0x42, 0x4b,
|
||||
0x49, 0x4f, 0x68, 0x01, 0x76, 0x38, 0x56, 0x19, 0x0b, 0xd6, 0x7a, 0x15, 0x43, 0x12, 0xf5, 0x60,
|
||||
0x32, 0xe2, 0x8d, 0x16, 0xe6, 0x9d, 0x54, 0x2e, 0xcf, 0x3b, 0xa9, 0x5e, 0x96, 0x77, 0xf2, 0x09,
|
||||
0x98, 0xf3, 0x86, 0x41, 0xc8, 0xd4, 0x02, 0x33, 0xec, 0x71, 0x67, 0x66, 0xad, 0xcc, 0x0e, 0xc3,
|
||||
0x02, 0x3c, 0x60, 0x18, 0xf9, 0x5c, 0x4a, 0x44, 0x07, 0x43, 0xcc, 0x61, 0xd2, 0x15, 0xc5, 0xee,
|
||||
0x60, 0x48, 0xf7, 0xc3, 0xbe, 0x9b, 0x84, 0x91, 0xfa, 0x90, 0x61, 0x31, 0x3b, 0xf5, 0xc7, 0xe1,
|
||||
0x84, 0xb9, 0x39, 0x72, 0x29, 0x78, 0xd8, 0xa6, 0xc9, 0xd1, 0x43, 0x5c, 0x10, 0xfb, 0xab, 0xd0,
|
||||
0xd0, 0x9a, 0x20, 0xaf, 0xf2, 0x13, 0x26, 0x73, 0x21, 0xc4, 0x79, 0xb0, 0xc2, 0x3d, 0xf6, 0x80,
|
||||
0xfa, 0x0f, 0x06, 0xe4, 0x53, 0xb0, 0x30, 0xf0, 0x22, 0x8a, 0xb9, 0x4a, 0xbd, 0x88, 0x9e, 0xd1,
|
||||
0x28, 0x96, 0x27, 0xe7, 0xb6, 0xaa, 0x70, 0x38, 0x6e, 0xbf, 0x07, 0x8b, 0xc6, 0xd6, 0x28, 0xce,
|
||||
0x95, 0xe9, 0x21, 0x56, 0x3e, 0x3d, 0x44, 0xa6, 0x86, 0xd8, 0xdf, 0x2e, 0x41, 0x79, 0x2f, 0x1c,
|
||||
0xeb, 0xd1, 0x7e, 0xcb, 0x8c, 0xf6, 0x0b, 0x17, 0xa8, 0xa7, 0x3c, 0x1c, 0x61, 0x19, 0x0d, 0x90,
|
||||
0x6c, 0x40, 0xcb, 0x1d, 0x25, 0xbd, 0x24, 0x64, 0x2e, 0xdf, 0xb9, 0x1b, 0x0d, 0x38, 0x3b, 0xe3,
|
||||
0x16, 0x67, 0x6a, 0xc8, 0x12, 0x94, 0x95, 0xaf, 0x80, 0x04, 0xac, 0xc8, 0xce, 0x1b, 0x78, 0x8f,
|
||||
0x78, 0x21, 0x22, 0x67, 0xa2, 0xc4, 0xa4, 0xc5, 0xfc, 0x9e, 0x1f, 0xf6, 0xb8, 0xc6, 0x2f, 0xaa,
|
||||
0x62, 0xee, 0x18, 0xe3, 0x0e, 0x24, 0x13, 0x21, 0x4f, 0x59, 0xd6, 0xc3, 0xb3, 0x35, 0xf3, 0x56,
|
||||
0xf5, 0x9f, 0x2c, 0xa8, 0xe2, 0xda, 0x30, 0xeb, 0xc5, 0xc5, 0x5b, 0x05, 0xfc, 0x71, 0x4d, 0xe6,
|
||||
0x9c, 0x2c, 0x4c, 0x6c, 0x23, 0xeb, 0xad, 0xa4, 0x26, 0xa4, 0x67, 0xbe, 0xad, 0x41, 0x9d, 0x97,
|
||||
0x54, 0x86, 0x17, 0xe7, 0x7b, 0x05, 0x92, 0xeb, 0x50, 0x39, 0x0d, 0xc7, 0xd2, 0xdd, 0x06, 0x79,
|
||||
0x1b, 0x16, 0x8e, 0x1d, 0xc4, 0xd3, 0xf1, 0xb0, 0xf6, 0xf8, 0xb4, 0xb8, 0x13, 0x95, 0x85, 0x99,
|
||||
0x1b, 0xa9, 0x9a, 0xd5, 0x97, 0x29, 0x83, 0xda, 0x1b, 0x30, 0xcf, 0xb8, 0x5e, 0x8b, 0xba, 0x4e,
|
||||
0x15, 0x65, 0xfb, 0xa7, 0x2d, 0xa8, 0x49, 0x62, 0xb2, 0x0e, 0x15, 0x26, 0x42, 0x99, 0x83, 0xab,
|
||||
0xba, 0x05, 0x67, 0x74, 0x0e, 0x52, 0x30, 0x67, 0x02, 0x83, 0x61, 0xe9, 0x39, 0x49, 0x86, 0xc2,
|
||||
0xd2, 0x63, 0x80, 0x1a, 0x6e, 0xc6, 0x7b, 0xce, 0xa0, 0xf6, 0xf7, 0x2d, 0x98, 0x33, 0xfa, 0x20,
|
||||
0x6b, 0xd0, 0xf0, 0xdd, 0x38, 0x11, 0x37, 0x8b, 0x62, 0x7b, 0x74, 0x48, 0xdf, 0xe8, 0x92, 0x19,
|
||||
0x87, 0x57, 0x11, 0xe2, 0xb2, 0x1e, 0x21, 0xbe, 0x0d, 0xf5, 0x34, 0x37, 0xb1, 0x62, 0xc8, 0x3e,
|
||||
0xeb, 0x51, 0xde, 0xef, 0xa7, 0x44, 0x18, 0x74, 0x0c, 0xfd, 0x30, 0x12, 0x97, 0x56, 0xbc, 0x60,
|
||||
0xbf, 0x07, 0x0d, 0x8d, 0x5e, 0x8f, 0x41, 0x5a, 0x46, 0x0c, 0x52, 0x25, 0xbf, 0x94, 0xd2, 0xe4,
|
||||
0x17, 0xfb, 0x5f, 0x2d, 0x98, 0x63, 0x3c, 0xe8, 0x05, 0xc3, 0xc3, 0xd0, 0xf7, 0xfa, 0x17, 0xb8,
|
||||
0xf7, 0x92, 0xdd, 0x84, 0x4a, 0x94, 0xbc, 0x68, 0xc2, 0x8c, 0xeb, 0x65, 0xe4, 0x43, 0x88, 0xa8,
|
||||
0x2a, 0x33, 0x19, 0x66, 0x12, 0x70, 0xec, 0xc6, 0x42, 0x2c, 0x84, 0xd7, 0x66, 0x80, 0x4c, 0xd2,
|
||||
0x18, 0x10, 0xb9, 0x09, 0xed, 0x8d, 0x3c, 0xdf, 0xf7, 0x38, 0x2d, 0xf7, 0xe9, 0x8b, 0xaa, 0x58,
|
||||
0x9f, 0x03, 0x2f, 0x76, 0x8f, 0xd3, 0x8b, 0x18, 0x55, 0xc6, 0xf0, 0x8c, 0xfb, 0x4c, 0x0b, 0xcf,
|
||||
0xcc, 0xa0, 0x5e, 0x31, 0x41, 0xfb, 0x8f, 0x4a, 0xd0, 0x90, 0x2e, 0xc2, 0x60, 0x48, 0xc5, 0xdd,
|
||||
0xa2, 0xa9, 0x18, 0x35, 0x44, 0xd6, 0x1b, 0xa7, 0x31, 0x0d, 0xc9, 0x32, 0x46, 0x39, 0xcf, 0x18,
|
||||
0xd7, 0xa0, 0xce, 0x18, 0xf4, 0x2d, 0x3c, 0xf6, 0x89, 0x74, 0x5f, 0x05, 0xc8, 0xda, 0x3b, 0x58,
|
||||
0x5b, 0x4d, 0x6b, 0x11, 0x78, 0xe1, 0x4d, 0xe4, 0x3b, 0xd0, 0x14, 0xcd, 0xe0, 0xce, 0xa1, 0xe6,
|
||||
0x49, 0x45, 0xc4, 0xd8, 0x55, 0xc7, 0xa0, 0x94, 0x5f, 0xde, 0x91, 0x5f, 0xd6, 0x2e, 0xfb, 0x52,
|
||||
0x52, 0xda, 0xf7, 0xd5, 0x05, 0xef, 0xfd, 0xc8, 0x1d, 0x9f, 0x4a, 0x59, 0xbe, 0x0d, 0x8b, 0x5e,
|
||||
0xd0, 0xf7, 0x27, 0x03, 0xda, 0x9b, 0x04, 0x6e, 0x10, 0x84, 0x93, 0xa0, 0x4f, 0x65, 0xf6, 0x4b,
|
||||
0x51, 0x95, 0x3d, 0x50, 0xc9, 0x7f, 0xd8, 0x10, 0xd9, 0x80, 0x2a, 0x37, 0x95, 0xdc, 0x76, 0x14,
|
||||
0x0b, 0x3a, 0x27, 0x21, 0xeb, 0x50, 0xe5, 0x16, 0xb3, 0x64, 0x48, 0x8d, 0xb6, 0xab, 0x0e, 0x27,
|
||||
0x60, 0x6a, 0x07, 0x13, 0x3c, 0x4d, 0xb5, 0x63, 0xda, 0x9d, 0x99, 0x3e, 0x4f, 0x01, 0x5d, 0x02,
|
||||
0x72, 0xc0, 0x25, 0x45, 0xbf, 0x1b, 0xfa, 0xd9, 0x32, 0x34, 0x34, 0x98, 0x69, 0x90, 0x21, 0x1b,
|
||||
0x70, 0x6f, 0xe0, 0xb9, 0x23, 0x9a, 0xd0, 0x48, 0x48, 0x47, 0x06, 0x65, 0x74, 0xee, 0xd9, 0xb0,
|
||||
0x17, 0x4e, 0x92, 0xde, 0x80, 0x0e, 0x23, 0xca, 0xad, 0x29, 0x33, 0x4d, 0x06, 0xca, 0xe8, 0x18,
|
||||
0x7f, 0x6a, 0x74, 0x9c, 0x83, 0x32, 0xa8, 0xbc, 0xe9, 0xe1, 0x6b, 0x54, 0x49, 0x6f, 0x7a, 0xf8,
|
||||
0x8a, 0x64, 0x75, 0x5f, 0xb5, 0x40, 0xf7, 0xbd, 0x0d, 0x2b, 0x5c, 0xcb, 0x09, 0x7d, 0xd0, 0xcb,
|
||||
0x30, 0xd6, 0x94, 0x5a, 0xb2, 0x01, 0x6d, 0x36, 0x66, 0x29, 0x12, 0xb1, 0xf7, 0x2d, 0x1e, 0x35,
|
||||
0xb5, 0x9c, 0x1c, 0xce, 0x68, 0x31, 0x7c, 0xa9, 0xd3, 0xf2, 0x9b, 0xef, 0x1c, 0x8e, 0xb4, 0xee,
|
||||
0x33, 0x93, 0xb6, 0x2e, 0x68, 0x33, 0xb8, 0x3d, 0x07, 0x8d, 0xa3, 0x24, 0x1c, 0xcb, 0x4d, 0x69,
|
||||
0x41, 0x93, 0x17, 0x45, 0x16, 0xd2, 0x2b, 0x70, 0x15, 0xb9, 0xe8, 0x51, 0x38, 0x0e, 0xfd, 0x70,
|
||||
0x78, 0x61, 0x1c, 0x9d, 0xfe, 0xd2, 0x82, 0x45, 0xa3, 0x36, 0x3d, 0x3b, 0x61, 0xd4, 0x45, 0xa6,
|
||||
0x8f, 0x70, 0xc6, 0x5b, 0xd0, 0x54, 0x30, 0x27, 0xe4, 0x01, 0xee, 0xc7, 0x22, 0xa3, 0x64, 0x0b,
|
||||
0xe6, 0xe5, 0xc8, 0xe4, 0x87, 0x9c, 0x0b, 0x3b, 0x79, 0x2e, 0x14, 0xdf, 0xb7, 0xc4, 0x07, 0xb2,
|
||||
0x89, 0x2f, 0x88, 0x0c, 0x02, 0x7e, 0x94, 0x92, 0x41, 0x36, 0x75, 0xf8, 0xd2, 0x8f, 0xda, 0x72,
|
||||
0x04, 0x7d, 0x05, 0xc6, 0xf6, 0x2f, 0x5a, 0x00, 0xe9, 0xe8, 0xf0, 0xde, 0x59, 0x99, 0x11, 0xfe,
|
||||
0xdc, 0x45, 0x33, 0x19, 0xaf, 0x43, 0x53, 0xdd, 0x57, 0xa6, 0x96, 0xa9, 0x21, 0x31, 0xe6, 0x39,
|
||||
0xdf, 0x84, 0xf9, 0xa1, 0x1f, 0x1e, 0xa3, 0x59, 0xc7, 0xb4, 0xb6, 0x58, 0xe4, 0x62, 0xb5, 0x38,
|
||||
0x7c, 0x4f, 0xa0, 0xa9, 0x19, 0xab, 0x68, 0x66, 0xcc, 0xfe, 0xa5, 0x92, 0xba, 0x5e, 0x4a, 0xe7,
|
||||
0x3c, 0x55, 0xca, 0xc8, 0x9d, 0x9c, 0x3a, 0x9d, 0x72, 0x9b, 0x83, 0xce, 0xe9, 0xe1, 0xa5, 0xd1,
|
||||
0xae, 0xf7, 0xa0, 0x15, 0x71, 0x7d, 0x25, 0x95, 0x59, 0xe5, 0x05, 0xca, 0x6c, 0x2e, 0x32, 0x6c,
|
||||
0xdd, 0x27, 0xa1, 0xed, 0x0e, 0xce, 0x68, 0x94, 0x78, 0x18, 0x6f, 0x40, 0x47, 0x83, 0xab, 0xe0,
|
||||
0x79, 0x0d, 0x47, 0xfb, 0x7f, 0x13, 0xe6, 0x45, 0xfe, 0x9b, 0xa2, 0x14, 0xb9, 0xec, 0x29, 0xcc,
|
||||
0x08, 0xed, 0xdf, 0x96, 0x37, 0x59, 0xe6, 0x1e, 0x4e, 0x5f, 0x11, 0x7d, 0x76, 0xa5, 0xcc, 0xec,
|
||||
0x3e, 0x21, 0x6e, 0x95, 0x06, 0x32, 0xa8, 0x51, 0xd6, 0xb2, 0x4d, 0x06, 0xe2, 0x16, 0xd0, 0x5c,
|
||||
0xd2, 0xca, 0xcb, 0x2c, 0xa9, 0xfd, 0x43, 0x0b, 0x66, 0xf7, 0xc2, 0xf1, 0x9e, 0xc8, 0xbb, 0x41,
|
||||
0x41, 0x50, 0x89, 0xa7, 0xb2, 0xf8, 0x82, 0x8c, 0x9c, 0x42, 0xfb, 0x3e, 0x97, 0xb5, 0xef, 0xff,
|
||||
0x17, 0x5e, 0xc1, 0x90, 0x5a, 0x14, 0x8e, 0xc3, 0x88, 0x09, 0xa3, 0xeb, 0x73, 0x63, 0x1e, 0x06,
|
||||
0xc9, 0xa9, 0x54, 0x63, 0x2f, 0x22, 0xc1, 0x73, 0x2e, 0x3b, 0x9b, 0x71, 0xd7, 0x5c, 0xf8, 0x23,
|
||||
0x5c, 0xbb, 0xe5, 0x2b, 0xec, 0xcf, 0x43, 0x1d, 0x1d, 0x6a, 0x9c, 0xd6, 0x9b, 0x50, 0x3f, 0x0d,
|
||||
0xc7, 0xbd, 0x53, 0x2f, 0x48, 0xa4, 0x70, 0xb7, 0x52, 0x4f, 0x77, 0x0f, 0x17, 0x44, 0x11, 0xd8,
|
||||
0xdf, 0x9e, 0x81, 0xd9, 0x07, 0xc1, 0x59, 0xe8, 0xf5, 0xf1, 0xd6, 0x6c, 0x44, 0x47, 0xa1, 0x4c,
|
||||
0xc3, 0x65, 0xff, 0x93, 0x6b, 0x30, 0x8b, 0x79, 0x67, 0x63, 0xce, 0xb4, 0x4d, 0x7e, 0xbb, 0x2d,
|
||||
0x20, 0xe6, 0x24, 0x44, 0xe9, 0x0b, 0x00, 0x2e, 0x3e, 0x1a, 0xc2, 0x8e, 0x1a, 0x91, 0x9e, 0xc1,
|
||||
0x2f, 0x4a, 0x69, 0x9a, 0x73, 0x55, 0x4b, 0x73, 0x66, 0x7d, 0x89, 0x3c, 0x21, 0x9e, 0x48, 0xc2,
|
||||
0xfb, 0x12, 0x10, 0x1e, 0x8f, 0x22, 0xca, 0x43, 0xa2, 0xe8, 0x72, 0xcc, 0x8a, 0xe3, 0x91, 0x0e,
|
||||
0x32, 0xb7, 0x84, 0x7f, 0xc0, 0x69, 0xb8, 0x12, 0xd6, 0x21, 0xe6, 0xe8, 0x65, 0x5f, 0x67, 0xd4,
|
||||
0x39, 0xef, 0x67, 0x60, 0xa6, 0xa9, 0x07, 0x54, 0x29, 0x54, 0x3e, 0x0f, 0xe0, 0xaf, 0x1c, 0xb2,
|
||||
0xb8, 0x76, 0xa8, 0xe2, 0x29, 0x82, 0xf2, 0x50, 0xc5, 0x18, 0xc6, 0xf5, 0xfd, 0x63, 0xb7, 0xff,
|
||||
0x14, 0x1f, 0xdf, 0xe0, 0x3d, 0x56, 0xdd, 0x31, 0x41, 0xcc, 0xf6, 0x49, 0x77, 0x15, 0xf3, 0x00,
|
||||
0x2a, 0x8e, 0x0e, 0x91, 0x3b, 0xd0, 0xc0, 0x83, 0xa4, 0xd8, 0xd7, 0x16, 0xee, 0x6b, 0x5b, 0x3f,
|
||||
0x69, 0xe2, 0xce, 0xea, 0x44, 0xfa, 0x8d, 0xde, 0x7c, 0x2e, 0x69, 0xcf, 0x1d, 0x0c, 0xc4, 0x45,
|
||||
0x68, 0x9b, 0x1f, 0x8a, 0x15, 0xc0, 0xac, 0xaa, 0x58, 0x30, 0x4e, 0xb0, 0x80, 0x04, 0x06, 0x46,
|
||||
0xae, 0x43, 0x8d, 0x1d, 0x72, 0xc6, 0xae, 0x37, 0xc0, 0xac, 0x3f, 0x7e, 0xd6, 0x52, 0x18, 0x6b,
|
||||
0x43, 0xfe, 0x8f, 0x17, 0x96, 0x8b, 0xb8, 0x2a, 0x06, 0xc6, 0xd6, 0x46, 0x95, 0x51, 0x98, 0x96,
|
||||
0xf8, 0x8e, 0x1a, 0x20, 0x79, 0x0b, 0xaf, 0xa3, 0x12, 0xda, 0x59, 0xc6, 0x70, 0xd7, 0x2b, 0x62,
|
||||
0xce, 0x82, 0x69, 0xe5, 0xdf, 0x23, 0x46, 0xe2, 0x70, 0x4a, 0xfb, 0xd3, 0xd0, 0xd4, 0x61, 0x52,
|
||||
0x83, 0xca, 0xc3, 0xc3, 0xdd, 0x83, 0xf6, 0x15, 0xd2, 0x80, 0xd9, 0xa3, 0xdd, 0x47, 0x8f, 0xf6,
|
||||
0x77, 0x77, 0xda, 0x16, 0x69, 0x42, 0x4d, 0xa5, 0x66, 0x95, 0xec, 0x04, 0xc8, 0xd6, 0x60, 0x20,
|
||||
0xbe, 0x53, 0x87, 0xfb, 0x94, 0x83, 0x2d, 0x83, 0x83, 0x0b, 0xb8, 0xa8, 0x54, 0xcc, 0x45, 0x2f,
|
||||
0x5c, 0x6b, 0x7b, 0x17, 0x1a, 0x87, 0xda, 0xd3, 0x14, 0x14, 0x28, 0xf9, 0x28, 0x45, 0x08, 0xa2,
|
||||
0x86, 0x68, 0xc3, 0x29, 0xe9, 0xc3, 0xb1, 0x7f, 0xc7, 0xe2, 0xe9, 0xf2, 0x6a, 0xf8, 0xbc, 0x6f,
|
||||
0x1b, 0x9a, 0x2a, 0xca, 0x94, 0xe6, 0x59, 0x1a, 0x18, 0xa3, 0xc1, 0xa1, 0xf4, 0xc2, 0x93, 0x93,
|
||||
0x98, 0xca, 0xac, 0x28, 0x03, 0x63, 0x92, 0xc0, 0x7c, 0x2a, 0xe6, 0x9f, 0x78, 0xbc, 0x87, 0x58,
|
||||
0x64, 0x47, 0xe5, 0x70, 0xa6, 0xd7, 0x45, 0x20, 0x45, 0xe6, 0x83, 0xa9, 0xb2, 0x4a, 0x07, 0xcd,
|
||||
0xae, 0xf2, 0x06, 0xd4, 0x54, 0xbb, 0xa6, 0xca, 0x92, 0x94, 0xaa, 0x9e, 0xa9, 0x46, 0x3c, 0x65,
|
||||
0x18, 0x83, 0xe6, 0x6a, 0x3a, 0x5f, 0x41, 0x6e, 0x01, 0x39, 0xf1, 0xa2, 0x2c, 0x79, 0x19, 0xc9,
|
||||
0x0b, 0x6a, 0xec, 0x27, 0xb0, 0x28, 0x59, 0x47, 0x73, 0xa6, 0xcc, 0x4d, 0xb4, 0x2e, 0x13, 0x98,
|
||||
0x52, 0x5e, 0x60, 0xec, 0xff, 0xb0, 0x60, 0x56, 0xec, 0x74, 0xee, 0x79, 0x13, 0xdf, 0x67, 0x03,
|
||||
0x23, 0x1d, 0xe3, 0x25, 0x08, 0x4a, 0x97, 0x50, 0x93, 0x39, 0x45, 0x58, 0x2e, 0x52, 0x84, 0x04,
|
||||
0x2a, 0x63, 0x37, 0x39, 0xc5, 0x13, 0x76, 0xdd, 0xc1, 0xff, 0x49, 0x9b, 0xc7, 0x83, 0xb8, 0xd2,
|
||||
0xc5, 0x58, 0x50, 0xd1, 0x43, 0x2e, 0x6e, 0xdf, 0xf3, 0x0f, 0xb9, 0xae, 0x41, 0x1d, 0x07, 0xd0,
|
||||
0x4b, 0xc3, 0x3d, 0x29, 0xc0, 0x38, 0x97, 0x17, 0x50, 0x92, 0x45, 0x52, 0x76, 0x8a, 0xd8, 0xcb,
|
||||
0x7c, 0xe7, 0xc5, 0x12, 0xa8, 0xcb, 0x63, 0x91, 0x7e, 0x9b, 0xc2, 0x29, 0x47, 0x88, 0x01, 0x64,
|
||||
0x39, 0x42, 0x90, 0x3a, 0xaa, 0xde, 0xee, 0x42, 0x67, 0x87, 0xfa, 0x34, 0xa1, 0x5b, 0xbe, 0x9f,
|
||||
0x6d, 0xff, 0x15, 0xb8, 0x5a, 0x50, 0x27, 0xfc, 0xe7, 0x2f, 0xc3, 0xf2, 0x16, 0x4f, 0x55, 0xfc,
|
||||
0x49, 0xa5, 0xdf, 0xd8, 0x1d, 0x58, 0xc9, 0x36, 0x29, 0x3a, 0xbb, 0x07, 0x0b, 0x3b, 0xf4, 0x78,
|
||||
0x32, 0xdc, 0xa7, 0x67, 0x69, 0x47, 0x04, 0x2a, 0xf1, 0x69, 0x78, 0x2e, 0x04, 0x13, 0xff, 0x27,
|
||||
0xaf, 0x02, 0xf8, 0x8c, 0xa6, 0x17, 0x8f, 0x69, 0x5f, 0x3e, 0xbe, 0x40, 0xe4, 0x68, 0x4c, 0xfb,
|
||||
0xf6, 0xdb, 0x40, 0xf4, 0x76, 0xc4, 0x7a, 0x31, 0xbb, 0x37, 0x39, 0xee, 0xc5, 0x17, 0x71, 0x42,
|
||||
0x47, 0xf2, 0x55, 0x89, 0x0e, 0xd9, 0x37, 0xa1, 0x79, 0xe8, 0x5e, 0x38, 0xf4, 0x9b, 0xe2, 0x55,
|
||||
0xdb, 0x2a, 0xcc, 0x8e, 0xdd, 0x0b, 0xa6, 0xa6, 0x54, 0x1c, 0x0a, 0xab, 0xed, 0x7f, 0x2b, 0xc1,
|
||||
0x0c, 0xa7, 0x64, 0xad, 0x0e, 0x68, 0x9c, 0x78, 0x01, 0x32, 0x96, 0x6c, 0x55, 0x83, 0x72, 0xac,
|
||||
0x5c, 0x2a, 0x60, 0x65, 0x71, 0x4a, 0x93, 0x89, 0xec, 0x82, 0x5f, 0x0d, 0x8c, 0x31, 0x57, 0x9a,
|
||||
0x07, 0xc7, 0x03, 0x21, 0x29, 0x90, 0x09, 0x59, 0xa6, 0xd6, 0x95, 0x8f, 0x4f, 0x4a, 0xa9, 0xe0,
|
||||
0x5c, 0x1d, 0x2a, 0xb4, 0xe1, 0xb3, 0x9c, 0xc1, 0x73, 0x36, 0x3c, 0x67, 0xab, 0x6b, 0x2f, 0x61,
|
||||
0xab, 0xf9, 0xd1, 0xed, 0x45, 0xb6, 0x1a, 0x5e, 0xc2, 0x56, 0xdb, 0x04, 0xda, 0xf7, 0x28, 0x75,
|
||||
0x28, 0xf3, 0x06, 0x25, 0xef, 0x7e, 0xc7, 0x82, 0xb6, 0xe0, 0x22, 0x55, 0x47, 0x5e, 0x37, 0xbc,
|
||||
0xde, 0xc2, 0x84, 0xf2, 0x1b, 0x30, 0x87, 0xbe, 0xa8, 0x8a, 0xcd, 0x8a, 0x40, 0xb2, 0x01, 0xb2,
|
||||
0x79, 0xc8, 0x7b, 0xdf, 0x91, 0xe7, 0x8b, 0x4d, 0xd1, 0x21, 0x19, 0xde, 0x8d, 0x5c, 0x91, 0x0f,
|
||||
0x66, 0x39, 0xaa, 0x6c, 0xff, 0xb1, 0x05, 0x0b, 0xda, 0x80, 0x05, 0x17, 0xbe, 0x07, 0x52, 0x1a,
|
||||
0x78, 0xa0, 0x96, 0x4b, 0xee, 0xaa, 0x29, 0x36, 0xe9, 0x67, 0x06, 0x31, 0x6e, 0xa6, 0x7b, 0x81,
|
||||
0x03, 0x8c, 0x27, 0x23, 0xa1, 0x44, 0x75, 0x88, 0x31, 0xd2, 0x39, 0xa5, 0x4f, 0x15, 0x09, 0x57,
|
||||
0xe3, 0x06, 0x86, 0xd1, 0x30, 0xe6, 0x43, 0x2b, 0xa2, 0x8a, 0x88, 0x86, 0xe9, 0xa0, 0xfd, 0xb7,
|
||||
0x16, 0x2c, 0xf2, 0xc3, 0x90, 0x38, 0x6a, 0xaa, 0xb7, 0x40, 0x33, 0xfc, 0xf4, 0xc7, 0x25, 0x72,
|
||||
0xef, 0x8a, 0x23, 0xca, 0xe4, 0xb3, 0x2f, 0x79, 0x80, 0x53, 0x49, 0x6a, 0x53, 0xf6, 0xa2, 0x5c,
|
||||
0xb4, 0x17, 0x2f, 0x58, 0xe9, 0xa2, 0xc0, 0x64, 0xb5, 0x30, 0x30, 0x79, 0x77, 0x16, 0xaa, 0x71,
|
||||
0x3f, 0x1c, 0x53, 0x7b, 0x05, 0x96, 0xcc, 0xc9, 0x09, 0x15, 0xf4, 0x3d, 0x0b, 0x3a, 0xf7, 0x78,
|
||||
0x00, 0xdf, 0x0b, 0x86, 0x7b, 0x5e, 0x9c, 0x84, 0x91, 0x7a, 0x32, 0x79, 0x1d, 0x20, 0x4e, 0xdc,
|
||||
0x28, 0xe1, 0xa9, 0xc8, 0x22, 0x20, 0x98, 0x22, 0x6c, 0x8c, 0x34, 0x18, 0xf0, 0x5a, 0xbe, 0x37,
|
||||
0xaa, 0x9c, 0xf3, 0x21, 0xc4, 0x71, 0xcd, 0xb0, 0xc4, 0x6f, 0xf0, 0xa4, 0x4d, 0xe6, 0x2b, 0xd0,
|
||||
0x33, 0xd4, 0xeb, 0xfc, 0x1c, 0x94, 0x41, 0xed, 0xbf, 0xb6, 0x60, 0x3e, 0x1d, 0x24, 0x5e, 0x67,
|
||||
0x9a, 0xda, 0x41, 0x98, 0xdf, 0x54, 0x3b, 0xc8, 0x50, 0xa5, 0xc7, 0xec, 0xb1, 0x18, 0x9b, 0x86,
|
||||
0xa0, 0xc4, 0x8a, 0x52, 0x38, 0x91, 0x0e, 0x8e, 0x0e, 0xf1, 0x14, 0x2c, 0xe6, 0x09, 0x08, 0xaf,
|
||||
0x46, 0x94, 0x30, 0x93, 0x7c, 0x94, 0xe0, 0x57, 0x3c, 0xa8, 0x2a, 0x8b, 0xd2, 0x94, 0xce, 0x22,
|
||||
0x8a, 0xa6, 0x54, 0xbf, 0x0c, 0xa9, 0xf1, 0xf5, 0x91, 0x65, 0xfb, 0x97, 0x2d, 0xb8, 0x5a, 0xb0,
|
||||
0xf0, 0x42, 0x6a, 0x76, 0x60, 0xe1, 0x44, 0x55, 0xca, 0xc5, 0xe1, 0xa2, 0xb3, 0x22, 0x2f, 0xdb,
|
||||
0xcc, 0x05, 0x71, 0xf2, 0x1f, 0x28, 0xbf, 0x88, 0x2f, 0xb7, 0x91, 0xe4, 0x98, 0xaf, 0xd8, 0x78,
|
||||
0x0e, 0x0d, 0xed, 0xb1, 0x22, 0x59, 0x85, 0xc5, 0x27, 0x0f, 0x1e, 0x1d, 0xec, 0x1e, 0x1d, 0xf5,
|
||||
0x0e, 0x1f, 0xdf, 0xfd, 0xd2, 0xee, 0x57, 0x7b, 0x7b, 0x5b, 0x47, 0x7b, 0xed, 0x2b, 0x64, 0x05,
|
||||
0xc8, 0xc1, 0xee, 0xd1, 0xa3, 0xdd, 0x1d, 0x03, 0xb7, 0xc8, 0x75, 0xe8, 0x3e, 0x3e, 0x78, 0x7c,
|
||||
0xb4, 0xbb, 0xd3, 0x2b, 0xfa, 0xae, 0x44, 0x5e, 0x85, 0xab, 0xa2, 0xbe, 0xe0, 0xf3, 0xf2, 0x9d,
|
||||
0x5f, 0x29, 0x43, 0x8b, 0xdf, 0x03, 0xf3, 0x5f, 0xc7, 0xa0, 0x11, 0x79, 0x1f, 0x66, 0xc5, 0xaf,
|
||||
0x9b, 0x90, 0x65, 0x31, 0x6b, 0xf3, 0xf7, 0x54, 0xba, 0x2b, 0x59, 0x58, 0xb0, 0xf5, 0xe2, 0xcf,
|
||||
0xfc, 0xf0, 0x1f, 0x7f, 0xad, 0x34, 0x47, 0x1a, 0x9b, 0x67, 0x6f, 0x6d, 0x0e, 0x69, 0x10, 0xb3,
|
||||
0x36, 0xbe, 0x0e, 0x90, 0xfe, 0xee, 0x07, 0xe9, 0x28, 0x77, 0x32, 0xf3, 0x83, 0x26, 0xdd, 0xab,
|
||||
0x05, 0x35, 0xa2, 0xdd, 0xab, 0xd8, 0xee, 0xa2, 0xdd, 0x62, 0xed, 0x7a, 0x81, 0x97, 0xf0, 0x1f,
|
||||
0x01, 0x79, 0xd7, 0xda, 0x20, 0x03, 0x68, 0xea, 0x3f, 0xeb, 0x41, 0x64, 0x14, 0xab, 0xe0, 0x47,
|
||||
0x45, 0xba, 0xaf, 0x14, 0xd6, 0xc9, 0x10, 0x1e, 0xf6, 0xb1, 0x6c, 0xb7, 0x59, 0x1f, 0x13, 0xa4,
|
||||
0x48, 0x7b, 0xf1, 0xa1, 0x65, 0xfe, 0x7a, 0x07, 0xb9, 0xa6, 0x69, 0x9c, 0xdc, 0x6f, 0x87, 0x74,
|
||||
0x5f, 0x9d, 0x52, 0x2b, 0xfa, 0x7a, 0x15, 0xfb, 0x5a, 0xb5, 0x09, 0xeb, 0xab, 0x8f, 0x34, 0xf2,
|
||||
0xb7, 0x43, 0xde, 0xb5, 0x36, 0xee, 0xfc, 0xf9, 0x1a, 0xd4, 0x55, 0xdc, 0x99, 0x7c, 0x08, 0x73,
|
||||
0xc6, 0x45, 0x3d, 0x91, 0xd3, 0x28, 0xba, 0xd7, 0xef, 0x5e, 0x2b, 0xae, 0x14, 0x1d, 0x5f, 0xc7,
|
||||
0x8e, 0x3b, 0x64, 0x85, 0x75, 0x2c, 0x6e, 0xba, 0x37, 0x31, 0xe5, 0x84, 0xe7, 0x8f, 0x3f, 0xe5,
|
||||
0xf3, 0x4c, 0x2f, 0xd7, 0x8d, 0x79, 0xe6, 0x2e, 0xe3, 0x8d, 0x79, 0xe6, 0x6f, 0xe4, 0xed, 0x6b,
|
||||
0xd8, 0xdd, 0x0a, 0x59, 0xd2, 0xbb, 0x53, 0xf1, 0x60, 0x8a, 0x8f, 0x1e, 0xf4, 0x1f, 0xbe, 0x20,
|
||||
0xaf, 0x2a, 0xc6, 0x2a, 0xfa, 0x41, 0x0c, 0xc5, 0x22, 0xf9, 0x5f, 0xc5, 0xb0, 0x3b, 0xd8, 0x15,
|
||||
0x21, 0xb8, 0x7d, 0xfa, 0xef, 0x5e, 0x90, 0xaf, 0x41, 0x5d, 0x3d, 0x74, 0x26, 0xab, 0xda, 0xc3,
|
||||
0x73, 0xfd, 0x61, 0x76, 0xb7, 0x93, 0xaf, 0x28, 0x62, 0x0c, 0xbd, 0x65, 0xc6, 0x18, 0x4f, 0xa0,
|
||||
0xa1, 0x3d, 0x66, 0x26, 0x57, 0xd5, 0xad, 0x41, 0xf6, 0xc1, 0x74, 0xb7, 0x5b, 0x54, 0x25, 0xba,
|
||||
0x58, 0xc0, 0x2e, 0x1a, 0xa4, 0x8e, 0xbc, 0x97, 0x3c, 0x0b, 0x63, 0xb2, 0x0f, 0xcb, 0xe2, 0xdc,
|
||||
0x73, 0x4c, 0x3f, 0xce, 0x12, 0x15, 0xfc, 0x0e, 0xc8, 0x6d, 0x8b, 0xbc, 0x07, 0x35, 0xf9, 0x66,
|
||||
0x9d, 0xac, 0x14, 0xbf, 0xbd, 0xef, 0xae, 0xe6, 0x70, 0xa1, 0x15, 0xbf, 0x0a, 0x90, 0xbe, 0x9c,
|
||||
0x56, 0x02, 0x9c, 0x7b, 0x89, 0xad, 0x76, 0x27, 0xff, 0xcc, 0xda, 0x5e, 0xc1, 0x09, 0xb6, 0x09,
|
||||
0x0a, 0x70, 0x40, 0xcf, 0xe5, 0x33, 0xa0, 0x6f, 0x40, 0x43, 0x7b, 0x3c, 0xad, 0x96, 0x2f, 0xff,
|
||||
0xf0, 0x5a, 0x2d, 0x5f, 0xc1, 0x5b, 0x6b, 0xbb, 0x8b, 0xad, 0x2f, 0xd9, 0xf3, 0xac, 0xf5, 0xd8,
|
||||
0x1b, 0x06, 0x23, 0x4e, 0xc0, 0x36, 0xe8, 0x14, 0xe6, 0x8c, 0x17, 0xd2, 0x4a, 0x7a, 0x8a, 0xde,
|
||||
0x5f, 0x2b, 0xe9, 0x29, 0x7c, 0x54, 0x2d, 0xd9, 0xd9, 0x5e, 0x60, 0xfd, 0x9c, 0x21, 0x89, 0xd6,
|
||||
0xd3, 0x07, 0xd0, 0xd0, 0x5e, 0x3b, 0xab, 0xb9, 0xe4, 0x1f, 0x56, 0xab, 0xb9, 0x14, 0x3d, 0x8e,
|
||||
0x5e, 0xc2, 0x3e, 0x5a, 0x36, 0xb2, 0x02, 0xbe, 0xa2, 0x61, 0x6d, 0x7f, 0x08, 0x2d, 0xf3, 0xfd,
|
||||
0xb3, 0x92, 0xcb, 0xc2, 0x97, 0xd4, 0x4a, 0x2e, 0xa7, 0x3c, 0x9a, 0x16, 0x2c, 0xbd, 0xb1, 0xa8,
|
||||
0x3a, 0xd9, 0xfc, 0x48, 0xdc, 0x15, 0x3f, 0x27, 0x5f, 0x66, 0xca, 0x47, 0x3c, 0x6b, 0x22, 0xab,
|
||||
0x1a, 0xd7, 0xea, 0x8f, 0x9f, 0x94, 0xbc, 0xe4, 0x5e, 0x40, 0x99, 0xcc, 0xcc, 0xdf, 0x01, 0xa1,
|
||||
0x45, 0xc1, 0xe7, 0x4d, 0x9a, 0x45, 0xd1, 0x5f, 0x40, 0x69, 0x16, 0xc5, 0x78, 0x05, 0x95, 0xb5,
|
||||
0x28, 0x89, 0xc7, 0xda, 0x08, 0x60, 0x3e, 0x93, 0xe8, 0xa7, 0xa4, 0xa2, 0x38, 0x33, 0xba, 0x7b,
|
||||
0xfd, 0xc5, 0xf9, 0x81, 0xa6, 0xa2, 0x92, 0x0a, 0x6a, 0x53, 0xe6, 0xa1, 0xff, 0x7f, 0x68, 0xea,
|
||||
0x2f, 0x53, 0x89, 0x2e, 0xca, 0xd9, 0x9e, 0x5e, 0x29, 0xac, 0x33, 0x37, 0x97, 0x34, 0xf5, 0x6e,
|
||||
0xc8, 0x57, 0x60, 0x45, 0x89, 0xba, 0x9e, 0x3b, 0x16, 0x93, 0xd7, 0x0a, 0x32, 0xca, 0xf4, 0x68,
|
||||
0x48, 0xf7, 0xea, 0xd4, 0x94, 0xb3, 0xdb, 0x16, 0x63, 0x1a, 0xf3, 0xc9, 0x5f, 0xaa, 0xcc, 0x8b,
|
||||
0x5e, 0x3a, 0xa6, 0xca, 0xbc, 0xf0, 0x9d, 0xa0, 0x64, 0x1a, 0xb2, 0x68, 0xac, 0x11, 0xbf, 0x08,
|
||||
0x20, 0x1f, 0xc0, 0xbc, 0x96, 0x9d, 0x7b, 0x74, 0x11, 0xf4, 0x95, 0x00, 0xe4, 0x9f, 0x71, 0x74,
|
||||
0x8b, 0xdc, 0x75, 0x7b, 0x15, 0xdb, 0x5f, 0xb0, 0x8d, 0xc5, 0x61, 0xcc, 0xbf, 0x0d, 0x0d, 0x3d,
|
||||
0xf3, 0xf7, 0x05, 0xed, 0xae, 0x6a, 0x55, 0xfa, 0x2b, 0x84, 0xdb, 0x16, 0xf9, 0x0d, 0x0b, 0x9a,
|
||||
0x46, 0x1e, 0xad, 0x71, 0xdd, 0x95, 0x69, 0xa7, 0xa3, 0xd7, 0xe9, 0x0d, 0xd9, 0x0e, 0x0e, 0x72,
|
||||
0x7f, 0xe3, 0x8b, 0xc6, 0x22, 0x7c, 0x64, 0x1c, 0xfb, 0x6e, 0x65, 0x7f, 0xf8, 0xe5, 0x79, 0x96,
|
||||
0x40, 0x7f, 0xea, 0xf2, 0xfc, 0xb6, 0x45, 0xbe, 0x6f, 0x41, 0xcb, 0x0c, 0x56, 0xa8, 0xad, 0x2a,
|
||||
0x0c, 0x8b, 0xa8, 0xad, 0x9a, 0x12, 0xe1, 0xf8, 0x00, 0x47, 0xf9, 0x68, 0xc3, 0x31, 0x46, 0x29,
|
||||
0x1e, 0x83, 0xfe, 0x78, 0xa3, 0x25, 0xef, 0xf2, 0x1f, 0x7f, 0x92, 0x11, 0x34, 0xa2, 0x59, 0x8d,
|
||||
0xec, 0xf6, 0xea, 0xbf, 0x67, 0xb4, 0x6e, 0xdd, 0xb6, 0xc8, 0x37, 0xf8, 0xef, 0xc3, 0x88, 0x6f,
|
||||
0x91, 0x4b, 0x5e, 0xf6, 0x7b, 0xfb, 0x06, 0xce, 0xe9, 0xba, 0x7d, 0xd5, 0x98, 0x53, 0xd6, 0x1e,
|
||||
0x6f, 0xf1, 0xd1, 0x89, 0x9f, 0x22, 0x4a, 0x0d, 0x4a, 0xee, 0xe7, 0x89, 0xa6, 0x0f, 0x72, 0xc4,
|
||||
0x07, 0x29, 0xc8, 0x0d, 0x56, 0x7e, 0xc9, 0x66, 0xec, 0x0d, 0x1c, 0xeb, 0x0d, 0xfb, 0xb5, 0xa9,
|
||||
0x63, 0xdd, 0xc4, 0x90, 0x03, 0x1b, 0xf1, 0x21, 0x40, 0x1a, 0xed, 0x26, 0x99, 0x68, 0xab, 0x12,
|
||||
0xf0, 0x7c, 0x40, 0xdc, 0x94, 0x17, 0x19, 0x94, 0x65, 0x2d, 0x7e, 0x8d, 0xab, 0xab, 0x07, 0x32,
|
||||
0x4e, 0xab, 0x3b, 0x25, 0x66, 0x58, 0xda, 0x70, 0x4a, 0xb2, 0xed, 0x1b, 0xca, 0x4a, 0x05, 0x7d,
|
||||
0x1f, 0xc3, 0xdc, 0x7e, 0x18, 0x3e, 0x9d, 0x8c, 0xd5, 0x5d, 0x95, 0x19, 0x0d, 0xdc, 0x73, 0xe3,
|
||||
0xd3, 0x6e, 0x66, 0x16, 0xf6, 0x1a, 0x36, 0xd5, 0x25, 0x1d, 0xad, 0xa9, 0xcd, 0x8f, 0xd2, 0x68,
|
||||
0xfa, 0x73, 0xe2, 0xc2, 0x82, 0xd2, 0x81, 0x6a, 0xe0, 0x5d, 0xb3, 0x19, 0x43, 0xf3, 0x65, 0xbb,
|
||||
0x30, 0x3c, 0x5b, 0x39, 0xda, 0xcd, 0x58, 0xb6, 0x79, 0xdb, 0x22, 0x87, 0xd0, 0xdc, 0xa1, 0xfd,
|
||||
0x70, 0x40, 0x45, 0x48, 0x6d, 0x31, 0x1d, 0xb8, 0x8a, 0xc5, 0x75, 0xe7, 0x0c, 0xd0, 0xb4, 0x0b,
|
||||
0x63, 0xf7, 0x22, 0xa2, 0xdf, 0xdc, 0xfc, 0x48, 0x04, 0xeb, 0x9e, 0x4b, 0xbb, 0x20, 0xa3, 0x99,
|
||||
0x86, 0x5d, 0xc8, 0x84, 0x3f, 0x0d, 0xbb, 0x90, 0x0b, 0x7f, 0x1a, 0x4b, 0x2d, 0xa3, 0xa9, 0xc4,
|
||||
0x87, 0x85, 0x5c, 0xc4, 0x54, 0x99, 0x84, 0x69, 0x71, 0xd6, 0xee, 0xda, 0x74, 0x02, 0xb3, 0xb7,
|
||||
0x0d, 0xb3, 0xb7, 0x23, 0x98, 0xdb, 0xa1, 0x7c, 0xb1, 0x78, 0x42, 0x4c, 0x26, 0x19, 0x5b, 0x4f,
|
||||
0xb7, 0xc9, 0x2a, 0x70, 0xac, 0x33, 0x0d, 0x3f, 0x66, 0xa3, 0x90, 0xaf, 0x41, 0xe3, 0x3e, 0x4d,
|
||||
0x64, 0x06, 0x8c, 0x72, 0x3d, 0x33, 0x29, 0x31, 0xdd, 0x82, 0x04, 0x1a, 0x93, 0x67, 0xb0, 0xb5,
|
||||
0x4d, 0x3a, 0x18, 0x52, 0xae, 0x9c, 0x7a, 0xde, 0xe0, 0x39, 0xf9, 0x7f, 0xd8, 0xb8, 0x4a, 0xd4,
|
||||
0x5b, 0xd1, 0x12, 0x27, 0xf4, 0xc6, 0xe7, 0x33, 0x78, 0x51, 0xcb, 0x41, 0x38, 0xa0, 0x9a, 0x0b,
|
||||
0x14, 0x40, 0x43, 0xcb, 0x2f, 0x55, 0x02, 0x94, 0x4f, 0x07, 0x56, 0x02, 0x54, 0x90, 0x8e, 0x6a,
|
||||
0xaf, 0x63, 0x3f, 0x36, 0x59, 0x4b, 0xfb, 0xe1, 0x29, 0xa8, 0x69, 0x4f, 0x9b, 0x1f, 0xb9, 0xa3,
|
||||
0xe4, 0x39, 0x79, 0x82, 0x2f, 0xc2, 0xf5, 0x2c, 0x9f, 0xd4, 0x97, 0xce, 0x26, 0x04, 0xa9, 0xc5,
|
||||
0xd2, 0xaa, 0x4c, 0xff, 0x9a, 0x77, 0x85, 0x9e, 0xd2, 0x67, 0x01, 0x8e, 0x92, 0x70, 0xbc, 0xe3,
|
||||
0xd2, 0x51, 0x18, 0xa4, 0xba, 0x36, 0xcd, 0x64, 0x49, 0xf5, 0x97, 0x96, 0xce, 0x42, 0x9e, 0x68,
|
||||
0x87, 0x0f, 0x23, 0x49, 0x4a, 0x32, 0xd7, 0xd4, 0x64, 0x17, 0xb5, 0x20, 0x05, 0x09, 0x2f, 0xb7,
|
||||
0x2d, 0xb2, 0x05, 0x90, 0x86, 0xcc, 0xd5, 0x51, 0x22, 0x17, 0x8d, 0x57, 0x6a, 0xaf, 0x20, 0xbe,
|
||||
0x7e, 0x08, 0xf5, 0x34, 0x06, 0xbb, 0x9a, 0xa6, 0x40, 0x1b, 0x11, 0x5b, 0x65, 0xc1, 0x73, 0x91,
|
||||
0x51, 0xbb, 0x8d, 0x4b, 0x05, 0xa4, 0xc6, 0x96, 0x0a, 0xc3, 0x9d, 0x1e, 0x2c, 0xf2, 0x01, 0x2a,
|
||||
0x77, 0x04, 0x73, 0x33, 0xe4, 0x4c, 0x0a, 0xa2, 0x93, 0x4a, 0x9a, 0x0b, 0x83, 0x7b, 0x46, 0xb4,
|
||||
0x82, 0x71, 0x2b, 0xcf, 0x0b, 0x61, 0xaa, 0x79, 0x04, 0x0b, 0xb9, 0xe8, 0x93, 0x12, 0xe9, 0x69,
|
||||
0x01, 0x41, 0x25, 0xd2, 0x53, 0x03, 0x57, 0xf6, 0x32, 0x76, 0x39, 0x6f, 0x03, 0x9e, 0x80, 0xce,
|
||||
0xbd, 0xa4, 0x7f, 0xfa, 0xae, 0xb5, 0x71, 0xf7, 0xe6, 0x07, 0xff, 0x63, 0xe8, 0x25, 0xa7, 0x93,
|
||||
0xe3, 0x5b, 0xfd, 0x70, 0xb4, 0xe9, 0xcb, 0x90, 0x82, 0xc8, 0xb0, 0xda, 0xf4, 0x83, 0xc1, 0x26,
|
||||
0xb6, 0x7c, 0x3c, 0x83, 0xbf, 0x9c, 0xfb, 0xe9, 0xff, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x58, 0x14,
|
||||
0xcd, 0xde, 0x6b, 0x57, 0x00, 0x00,
|
||||
0xdc, 0xae, 0x9d, 0xea, 0xaa, 0x4e, 0x55, 0xb5, 0x3d, 0xce, 0x32, 0x12, 0x02, 0x04, 0x12, 0x02,
|
||||
0x21, 0x40, 0x48, 0x04, 0x05, 0x21, 0x05, 0x24, 0xc8, 0x23, 0x0f, 0x41, 0x48, 0x7c, 0x3c, 0x21,
|
||||
0x1e, 0x90, 0x10, 0x82, 0x3c, 0x22, 0x21, 0x21, 0x78, 0x01, 0x1e, 0x90, 0x90, 0x78, 0x44, 0x42,
|
||||
0xe7, 0x7f, 0x3e, 0xea, 0x9c, 0xaa, 0xea, 0xf1, 0x6c, 0x12, 0x78, 0xb2, 0xcf, 0xef, 0xfc, 0xeb,
|
||||
0x7c, 0xfe, 0xbf, 0xce, 0xff, 0xfc, 0x4f, 0x43, 0x3d, 0x1a, 0xf7, 0x6f, 0x8d, 0xa3, 0x30, 0x09,
|
||||
0x49, 0xd5, 0x0f, 0xa2, 0x71, 0xbf, 0x7b, 0x6d, 0x18, 0x86, 0x43, 0x9f, 0x6e, 0xba, 0x63, 0x6f,
|
||||
0xd3, 0x0d, 0x82, 0x30, 0x71, 0x13, 0x2f, 0x0c, 0x62, 0x4e, 0x64, 0x7f, 0x03, 0x5a, 0xf7, 0x69,
|
||||
0x70, 0x44, 0xe9, 0xc0, 0xa1, 0xdf, 0x9c, 0xd0, 0x38, 0x21, 0x9f, 0x82, 0x05, 0x97, 0x7e, 0x8b,
|
||||
0xd2, 0x41, 0x6f, 0xec, 0xc6, 0xf1, 0xf8, 0x34, 0x72, 0x63, 0xda, 0xb1, 0xd6, 0xac, 0xf5, 0xa6,
|
||||
0xd3, 0xe6, 0x15, 0x87, 0x0a, 0x27, 0xaf, 0x43, 0x33, 0x66, 0xa4, 0x34, 0x48, 0xa2, 0x70, 0x7c,
|
||||
0xd1, 0x29, 0x21, 0x5d, 0x83, 0x61, 0xbb, 0x1c, 0xb2, 0x7d, 0x98, 0x57, 0x3d, 0xc4, 0xe3, 0x30,
|
||||
0x88, 0x29, 0xb9, 0x0d, 0x4b, 0x7d, 0x6f, 0x7c, 0x4a, 0xa3, 0x1e, 0x7e, 0x3c, 0x0a, 0xe8, 0x28,
|
||||
0x0c, 0xbc, 0x7e, 0xc7, 0x5a, 0x2b, 0xaf, 0xd7, 0x1d, 0xc2, 0xeb, 0xd8, 0x17, 0xef, 0x8b, 0x1a,
|
||||
0x72, 0x13, 0xe6, 0x69, 0xc0, 0x71, 0x3a, 0xc0, 0xaf, 0x44, 0x57, 0xad, 0x14, 0x66, 0x1f, 0xd8,
|
||||
0x7f, 0x66, 0xc1, 0xc2, 0x83, 0xc0, 0x4b, 0x9e, 0xb8, 0xbe, 0x4f, 0x13, 0x39, 0xa7, 0x9b, 0x30,
|
||||
0x7f, 0x8e, 0x00, 0xce, 0xe9, 0x3c, 0x8c, 0x06, 0x62, 0x46, 0x2d, 0x0e, 0x1f, 0x0a, 0x74, 0xea,
|
||||
0xc8, 0x4a, 0x53, 0x47, 0x56, 0xb8, 0x5c, 0xe5, 0x29, 0xcb, 0x75, 0x13, 0xe6, 0x23, 0xda, 0x0f,
|
||||
0xcf, 0x68, 0x74, 0xd1, 0x3b, 0xf7, 0x82, 0x41, 0x78, 0xde, 0xa9, 0xac, 0x59, 0xeb, 0x55, 0xa7,
|
||||
0x25, 0xe1, 0x27, 0x88, 0xda, 0x4b, 0x40, 0xf4, 0x59, 0xf0, 0x75, 0xb3, 0x87, 0xb0, 0xf8, 0x38,
|
||||
0xf0, 0xc3, 0xfe, 0xd3, 0x1f, 0x72, 0x76, 0x05, 0xdd, 0x97, 0x0a, 0xbb, 0x5f, 0x81, 0x25, 0xb3,
|
||||
0x23, 0x31, 0x00, 0x0a, 0xcb, 0xdb, 0xa7, 0x6e, 0x30, 0xa4, 0xb2, 0x49, 0x39, 0x84, 0x4f, 0x42,
|
||||
0xbb, 0x3f, 0x89, 0x22, 0x1a, 0xe4, 0xc6, 0x30, 0x2f, 0x70, 0x35, 0x88, 0xd7, 0xa1, 0x19, 0xd0,
|
||||
0xf3, 0x94, 0x4c, 0xb0, 0x4c, 0x40, 0xcf, 0x25, 0x89, 0xdd, 0x81, 0x95, 0x6c, 0x37, 0x62, 0x00,
|
||||
0x7f, 0x6f, 0x41, 0xe5, 0x71, 0xf2, 0x2c, 0x24, 0xb7, 0xa0, 0x92, 0x5c, 0x8c, 0x39, 0x63, 0xb6,
|
||||
0xee, 0x90, 0x5b, 0xc8, 0xeb, 0xb7, 0xb6, 0x06, 0x83, 0x88, 0xc6, 0xf1, 0xa3, 0x8b, 0x31, 0x75,
|
||||
0x9a, 0x2e, 0x2f, 0xf4, 0x18, 0x1d, 0xe9, 0xc0, 0xac, 0x28, 0x63, 0x87, 0x75, 0x47, 0x16, 0xc9,
|
||||
0x75, 0x00, 0x77, 0x14, 0x4e, 0x82, 0xa4, 0x17, 0xbb, 0x09, 0xee, 0x5c, 0xd9, 0xd1, 0x10, 0x72,
|
||||
0x0d, 0xea, 0xe3, 0xa7, 0xbd, 0xb8, 0x1f, 0x79, 0xe3, 0x04, 0x77, 0xab, 0xee, 0xa4, 0x00, 0xf9,
|
||||
0x14, 0xd4, 0xc2, 0x49, 0x32, 0x0e, 0xbd, 0x20, 0xe9, 0x54, 0xd7, 0xac, 0xf5, 0xc6, 0x9d, 0x79,
|
||||
0x31, 0x96, 0x87, 0x93, 0xe4, 0x90, 0xc1, 0x8e, 0x22, 0x20, 0x37, 0x60, 0xae, 0x1f, 0x06, 0x27,
|
||||
0x5e, 0x34, 0xe2, 0x32, 0xd8, 0x99, 0xc1, 0xde, 0x4c, 0xd0, 0xfe, 0x76, 0x09, 0x1a, 0x8f, 0x22,
|
||||
0x37, 0x88, 0xdd, 0x3e, 0x03, 0xd8, 0xd0, 0x93, 0x67, 0xbd, 0x53, 0x37, 0x3e, 0xc5, 0xd9, 0xd6,
|
||||
0x1d, 0x59, 0x24, 0x2b, 0x30, 0xc3, 0x07, 0x8a, 0x73, 0x2a, 0x3b, 0xa2, 0x44, 0xde, 0x84, 0x85,
|
||||
0x60, 0x32, 0xea, 0x99, 0x7d, 0x95, 0x71, 0xa7, 0xf3, 0x15, 0x6c, 0x01, 0x8e, 0xd9, 0x5e, 0xf3,
|
||||
0x2e, 0xf8, 0x0c, 0x35, 0x84, 0xd8, 0xd0, 0x14, 0x25, 0xea, 0x0d, 0x4f, 0xf9, 0x34, 0xab, 0x8e,
|
||||
0x81, 0xb1, 0x36, 0x12, 0x6f, 0x44, 0x7b, 0x71, 0xe2, 0x8e, 0xc6, 0x62, 0x5a, 0x1a, 0x82, 0xf5,
|
||||
0x61, 0xe2, 0xfa, 0xbd, 0x13, 0x4a, 0xe3, 0xce, 0xac, 0xa8, 0x57, 0x08, 0x79, 0x03, 0x5a, 0x03,
|
||||
0x1a, 0x27, 0x3d, 0xb1, 0x29, 0x34, 0xee, 0xd4, 0x50, 0xe2, 0x32, 0x28, 0xe3, 0x8c, 0xfb, 0x34,
|
||||
0xd1, 0x56, 0x27, 0x16, 0x1c, 0x68, 0xef, 0x03, 0xd1, 0xe0, 0x1d, 0x9a, 0xb8, 0x9e, 0x1f, 0x93,
|
||||
0xb7, 0xa1, 0x99, 0x68, 0xc4, 0xa8, 0x61, 0x1a, 0x8a, 0x5d, 0xb4, 0x0f, 0x1c, 0x83, 0xce, 0xbe,
|
||||
0x0f, 0xb5, 0x7b, 0x94, 0xee, 0x7b, 0x23, 0x2f, 0x21, 0x2b, 0x50, 0x3d, 0xf1, 0x9e, 0x51, 0xce,
|
||||
0xd0, 0xe5, 0xbd, 0x2b, 0x0e, 0x2f, 0x92, 0x2e, 0xcc, 0x8e, 0x69, 0xd4, 0xa7, 0x72, 0xf9, 0xf7,
|
||||
0xae, 0x38, 0x12, 0xb8, 0x3b, 0x0b, 0x55, 0x9f, 0x7d, 0x6c, 0xff, 0x4d, 0x09, 0x1a, 0x47, 0x34,
|
||||
0x50, 0x82, 0x42, 0xa0, 0xc2, 0xa6, 0x24, 0x84, 0x03, 0xff, 0x27, 0xaf, 0x41, 0x03, 0xa7, 0x19,
|
||||
0x27, 0x91, 0x17, 0x0c, 0x05, 0x7f, 0x02, 0x83, 0x8e, 0x10, 0x21, 0x6d, 0x28, 0xbb, 0x23, 0xc9,
|
||||
0x9b, 0xec, 0x5f, 0x26, 0x44, 0x63, 0xf7, 0x62, 0xc4, 0xe4, 0x4d, 0xed, 0x5a, 0xd3, 0x69, 0x08,
|
||||
0x6c, 0x8f, 0x6d, 0xdb, 0x2d, 0x58, 0xd4, 0x49, 0x64, 0xeb, 0x55, 0x6c, 0x7d, 0x41, 0xa3, 0x14,
|
||||
0x9d, 0xdc, 0x84, 0x79, 0x49, 0x1f, 0xf1, 0xc1, 0xe2, 0x3e, 0xd6, 0x9d, 0x96, 0x80, 0xe5, 0x14,
|
||||
0xd6, 0xa1, 0x7d, 0xe2, 0x05, 0xae, 0xdf, 0xeb, 0xfb, 0xc9, 0x59, 0x6f, 0x40, 0xfd, 0xc4, 0xc5,
|
||||
0x1d, 0xad, 0x3a, 0x2d, 0xc4, 0xb7, 0xfd, 0xe4, 0x6c, 0x87, 0xa1, 0xe4, 0x4d, 0xa8, 0x9f, 0x50,
|
||||
0xda, 0xc3, 0x95, 0xe8, 0xd4, 0x0c, 0xe9, 0x90, 0xab, 0xeb, 0xd4, 0x4e, 0xe4, 0x3a, 0xaf, 0x43,
|
||||
0x3b, 0x9c, 0x24, 0xc3, 0xd0, 0x0b, 0x86, 0xbd, 0xfe, 0xa9, 0x1b, 0xf4, 0xbc, 0x41, 0xa7, 0xbe,
|
||||
0x66, 0xad, 0x57, 0x9c, 0x96, 0xc4, 0x99, 0x56, 0x78, 0x30, 0xb0, 0xff, 0xd0, 0x82, 0x26, 0x5f,
|
||||
0x54, 0x61, 0x50, 0x6e, 0xc0, 0x9c, 0x1c, 0x3b, 0x8d, 0xa2, 0x30, 0x12, 0x82, 0x62, 0x82, 0x64,
|
||||
0x03, 0xda, 0x12, 0x18, 0x47, 0xd4, 0x1b, 0xb9, 0x43, 0x2a, 0xb4, 0x4f, 0x0e, 0x27, 0x77, 0xd2,
|
||||
0x16, 0xa3, 0x70, 0x92, 0x70, 0x95, 0xde, 0xb8, 0xd3, 0x14, 0xc3, 0x77, 0x18, 0xe6, 0x98, 0x24,
|
||||
0x4c, 0x50, 0x0a, 0x36, 0xc5, 0xc0, 0xec, 0xef, 0x5b, 0x40, 0xd8, 0xd0, 0x1f, 0x85, 0xbc, 0x09,
|
||||
0xb1, 0xa6, 0xd9, 0xfd, 0xb4, 0x5e, 0x7a, 0x3f, 0x4b, 0xd3, 0xf6, 0x73, 0x1d, 0x66, 0x70, 0x58,
|
||||
0x4c, 0xf2, 0xcb, 0xd9, 0xa1, 0xdf, 0x2d, 0x75, 0x2c, 0x47, 0xd4, 0x13, 0x1b, 0xaa, 0x7c, 0x8e,
|
||||
0x95, 0x82, 0x39, 0xf2, 0x2a, 0xfb, 0xbb, 0x16, 0x34, 0xd9, 0xea, 0x07, 0xd4, 0x47, 0xad, 0x46,
|
||||
0x6e, 0x03, 0x39, 0x99, 0x04, 0x03, 0xb6, 0x59, 0xc9, 0x33, 0x6f, 0xd0, 0x3b, 0xbe, 0x60, 0x5d,
|
||||
0xe1, 0xb8, 0xf7, 0xae, 0x38, 0x05, 0x75, 0xe4, 0x4d, 0x68, 0x1b, 0x68, 0x9c, 0x44, 0x7c, 0xf4,
|
||||
0x7b, 0x57, 0x9c, 0x5c, 0x0d, 0x5b, 0x4c, 0xa6, 0x37, 0x27, 0x49, 0xcf, 0x0b, 0x06, 0xf4, 0x19,
|
||||
0xae, 0xff, 0x9c, 0x63, 0x60, 0x77, 0x5b, 0xd0, 0xd4, 0xbf, 0xb3, 0x3f, 0x84, 0x9a, 0xd4, 0xba,
|
||||
0xa8, 0x71, 0x32, 0xe3, 0x72, 0x34, 0x84, 0x74, 0xa1, 0x66, 0x8e, 0xc2, 0xa9, 0x7d, 0x9c, 0xbe,
|
||||
0xed, 0xff, 0x0d, 0xed, 0x7d, 0xa6, 0xfa, 0x02, 0x2f, 0x18, 0x0a, 0xb3, 0xc3, 0xf4, 0xf1, 0x78,
|
||||
0x72, 0xfc, 0x94, 0x5e, 0x08, 0xfe, 0x13, 0x25, 0x26, 0xf4, 0xa7, 0x61, 0x9c, 0x88, 0x7e, 0xf0,
|
||||
0x7f, 0xfb, 0x1f, 0x2c, 0x98, 0x67, 0x8c, 0xf0, 0xbe, 0x1b, 0x5c, 0x48, 0x2e, 0xd8, 0x87, 0x26,
|
||||
0x6b, 0xea, 0x51, 0xb8, 0xc5, 0xb5, 0x3a, 0xd7, 0x56, 0xeb, 0x62, 0x3f, 0x32, 0xd4, 0xb7, 0x74,
|
||||
0x52, 0xe6, 0x6c, 0x5d, 0x38, 0xc6, 0xd7, 0x4c, 0xad, 0x24, 0x6e, 0x34, 0xa4, 0x09, 0xea, 0x7b,
|
||||
0xa1, 0xff, 0x81, 0x43, 0xdb, 0x61, 0x70, 0x42, 0xd6, 0xa0, 0x19, 0xbb, 0x49, 0x6f, 0x4c, 0x23,
|
||||
0x5c, 0x13, 0x54, 0x0d, 0x65, 0x07, 0x62, 0x37, 0x39, 0xa4, 0xd1, 0xdd, 0x8b, 0x84, 0x76, 0xff,
|
||||
0x0f, 0x2c, 0xe4, 0x7a, 0x61, 0xda, 0x28, 0x9d, 0x22, 0xfb, 0x97, 0x2c, 0x41, 0xf5, 0xcc, 0xf5,
|
||||
0x27, 0x54, 0x98, 0x21, 0x5e, 0x78, 0xb7, 0xf4, 0x8e, 0x65, 0xbf, 0x01, 0xed, 0x74, 0xd8, 0x42,
|
||||
0x58, 0x09, 0x54, 0xd8, 0x4a, 0x8b, 0x06, 0xf0, 0x7f, 0xfb, 0x3b, 0x16, 0x27, 0xdc, 0x0e, 0x3d,
|
||||
0xa5, 0xd2, 0x19, 0x21, 0xd3, 0xfc, 0x92, 0x90, 0xfd, 0x3f, 0xd5, 0xe4, 0xfd, 0xe8, 0x93, 0x25,
|
||||
0x57, 0xa1, 0x16, 0xd3, 0x60, 0xd0, 0x73, 0x7d, 0x1f, 0x35, 0x5f, 0xcd, 0x99, 0x65, 0xe5, 0x2d,
|
||||
0xdf, 0xb7, 0x6f, 0xc2, 0x82, 0x36, 0xba, 0x17, 0xcc, 0xe3, 0x00, 0xc8, 0xbe, 0x17, 0x27, 0x8f,
|
||||
0x83, 0x78, 0xac, 0x69, 0xcc, 0x57, 0xa0, 0x3e, 0xf2, 0x02, 0x1c, 0x19, 0x67, 0xc5, 0xaa, 0x53,
|
||||
0x1b, 0x79, 0x01, 0x1b, 0x57, 0x8c, 0x95, 0xee, 0x33, 0x51, 0x59, 0x12, 0x95, 0xee, 0x33, 0xac,
|
||||
0xb4, 0xdf, 0x81, 0x45, 0xa3, 0x3d, 0xd1, 0xf5, 0xeb, 0x50, 0x9d, 0x24, 0xcf, 0x42, 0x69, 0xcf,
|
||||
0x1a, 0x82, 0x43, 0x98, 0x67, 0xe4, 0xf0, 0x1a, 0xfb, 0x3d, 0x58, 0x38, 0xa0, 0xe7, 0x82, 0x33,
|
||||
0xe5, 0x40, 0xde, 0xb8, 0xd4, 0x6b, 0xc2, 0x7a, 0xfb, 0x16, 0x10, 0xfd, 0x63, 0xd1, 0xab, 0xe6,
|
||||
0x43, 0x59, 0x86, 0x0f, 0x65, 0xbf, 0x01, 0xe4, 0xc8, 0x1b, 0x06, 0xef, 0xd3, 0x38, 0x76, 0x87,
|
||||
0x4a, 0xa9, 0xb5, 0xa1, 0x3c, 0x8a, 0x87, 0x42, 0xf6, 0xd8, 0xbf, 0xf6, 0xa7, 0x61, 0xd1, 0xa0,
|
||||
0x13, 0x0d, 0x5f, 0x83, 0x7a, 0xec, 0x0d, 0x03, 0x37, 0x99, 0x44, 0x54, 0x34, 0x9d, 0x02, 0xf6,
|
||||
0x3d, 0x58, 0xfa, 0x0a, 0x8d, 0xbc, 0x93, 0x8b, 0xcb, 0x9a, 0x37, 0xdb, 0x29, 0x65, 0xdb, 0xd9,
|
||||
0x85, 0xe5, 0x4c, 0x3b, 0xa2, 0x7b, 0xce, 0xbe, 0x62, 0x27, 0x6b, 0x0e, 0x2f, 0x68, 0xc2, 0x5c,
|
||||
0xd2, 0x85, 0xd9, 0x7e, 0x0c, 0x64, 0x3b, 0x0c, 0x02, 0xda, 0x4f, 0x0e, 0x29, 0x8d, 0xd2, 0x53,
|
||||
0x53, 0xca, 0xab, 0x8d, 0x3b, 0xab, 0x62, 0x65, 0xb3, 0x1a, 0x42, 0x30, 0x31, 0x81, 0xca, 0x98,
|
||||
0x46, 0x23, 0x6c, 0xb8, 0xe6, 0xe0, 0xff, 0xf6, 0x32, 0x2c, 0x1a, 0xcd, 0x0a, 0x87, 0xf7, 0x2d,
|
||||
0x58, 0xde, 0xf1, 0xe2, 0x7e, 0xbe, 0xc3, 0x0e, 0xcc, 0x8e, 0x27, 0xc7, 0xbd, 0x54, 0x12, 0x65,
|
||||
0x91, 0xf9, 0x48, 0xd9, 0x4f, 0x44, 0x63, 0x3f, 0x6b, 0x41, 0x65, 0xef, 0xd1, 0xfe, 0x36, 0x53,
|
||||
0x7e, 0x5e, 0xd0, 0x0f, 0x47, 0xcc, 0x80, 0xf0, 0x49, 0xab, 0xf2, 0x54, 0x09, 0xbb, 0x06, 0x75,
|
||||
0xb4, 0x3b, 0xcc, 0xed, 0x13, 0x07, 0x9c, 0x14, 0x60, 0x2e, 0x27, 0x7d, 0x36, 0xf6, 0x22, 0xf4,
|
||||
0x29, 0xa5, 0xa7, 0x58, 0x41, 0xbd, 0x99, 0xaf, 0xb0, 0xbf, 0x53, 0x85, 0x59, 0x61, 0x4d, 0xb0,
|
||||
0xbf, 0x7e, 0xe2, 0x9d, 0x51, 0x31, 0x12, 0x51, 0x62, 0x36, 0x3d, 0xa2, 0xa3, 0x30, 0xa1, 0x3d,
|
||||
0x63, 0x1b, 0x4c, 0x10, 0x5d, 0x6a, 0xde, 0x50, 0x8f, 0x3b, 0xe1, 0x65, 0x4e, 0x65, 0x80, 0x6c,
|
||||
0xb1, 0xa4, 0x47, 0x51, 0x41, 0x8f, 0x42, 0x16, 0xd9, 0x4a, 0xf4, 0xdd, 0xb1, 0xdb, 0xf7, 0x92,
|
||||
0x0b, 0xa1, 0x12, 0x54, 0x99, 0xb5, 0xed, 0x87, 0x7d, 0xd7, 0xef, 0x1d, 0xbb, 0xbe, 0x1b, 0xf4,
|
||||
0xa9, 0x74, 0xd7, 0x0d, 0x90, 0xb9, 0xae, 0x62, 0x48, 0x92, 0x8c, 0xbb, 0xb7, 0x19, 0x94, 0x19,
|
||||
0xa4, 0x7e, 0x38, 0x1a, 0x79, 0x09, 0xf3, 0x78, 0xd1, 0x1b, 0x2a, 0x3b, 0x1a, 0xc2, 0x0f, 0x07,
|
||||
0x58, 0x3a, 0xe7, 0xab, 0x57, 0x97, 0x87, 0x03, 0x0d, 0x64, 0xad, 0x30, 0x97, 0x8a, 0xa9, 0xb1,
|
||||
0xa7, 0xe7, 0x1d, 0xe0, 0xad, 0xa4, 0x08, 0xdb, 0x87, 0x49, 0x10, 0xd3, 0x24, 0xf1, 0xe9, 0x40,
|
||||
0x0d, 0xa8, 0x81, 0x64, 0xf9, 0x0a, 0x72, 0x1b, 0x16, 0xb9, 0x13, 0x1e, 0xbb, 0x49, 0x18, 0x9f,
|
||||
0x7a, 0x71, 0x2f, 0x66, 0xee, 0x6c, 0x13, 0xe9, 0x8b, 0xaa, 0xc8, 0x3b, 0xb0, 0x9a, 0x81, 0x23,
|
||||
0xda, 0xa7, 0xde, 0x19, 0x1d, 0x74, 0xe6, 0xf0, 0xab, 0x69, 0xd5, 0x64, 0x0d, 0x1a, 0xec, 0xec,
|
||||
0x31, 0x19, 0x0f, 0x5c, 0x66, 0x91, 0x5b, 0xb8, 0x0f, 0x3a, 0x44, 0xde, 0x82, 0xb9, 0x31, 0xe5,
|
||||
0xe6, 0xfc, 0x34, 0xf1, 0xfb, 0x71, 0x67, 0xde, 0xd0, 0x6e, 0x8c, 0x73, 0x1d, 0x93, 0x82, 0x31,
|
||||
0x65, 0x3f, 0x46, 0x27, 0xd4, 0xbd, 0xe8, 0xb4, 0x91, 0xdd, 0x52, 0x00, 0x65, 0x24, 0xf2, 0xce,
|
||||
0xdc, 0x84, 0x76, 0x16, 0xb8, 0x42, 0x17, 0x45, 0xf6, 0x9d, 0x17, 0x78, 0x89, 0xe7, 0x26, 0x61,
|
||||
0xd4, 0x21, 0x58, 0x97, 0x02, 0xf6, 0x6f, 0x59, 0x5c, 0xed, 0x0a, 0x16, 0x55, 0xea, 0xf3, 0x35,
|
||||
0x68, 0x70, 0xe6, 0xec, 0x85, 0x81, 0x7f, 0x21, 0xf8, 0x15, 0x38, 0xf4, 0x30, 0xf0, 0x2f, 0xc8,
|
||||
0x27, 0x60, 0xce, 0x0b, 0x74, 0x12, 0x2e, 0xe1, 0x4d, 0x09, 0x22, 0xd1, 0x6b, 0xd0, 0x18, 0x4f,
|
||||
0x8e, 0x7d, 0xaf, 0xcf, 0x49, 0xca, 0xbc, 0x15, 0x0e, 0x21, 0x01, 0x73, 0x06, 0xf9, 0x38, 0x39,
|
||||
0x45, 0x05, 0x29, 0x1a, 0x02, 0x63, 0x24, 0xf6, 0x5d, 0x58, 0x32, 0x07, 0x28, 0x54, 0xd9, 0x06,
|
||||
0xd4, 0x04, 0xe7, 0xc7, 0x9d, 0x06, 0xae, 0x5e, 0x4b, 0xac, 0x9e, 0x20, 0x75, 0x54, 0xbd, 0xfd,
|
||||
0x07, 0x15, 0x58, 0x14, 0xe8, 0xb6, 0x1f, 0xc6, 0xf4, 0x68, 0x32, 0x1a, 0xb9, 0x51, 0x81, 0x48,
|
||||
0x59, 0x97, 0x88, 0x54, 0xc9, 0x14, 0x29, 0xc6, 0xe8, 0xa7, 0xae, 0x17, 0x70, 0x4f, 0x96, 0xcb,
|
||||
0xa3, 0x86, 0x90, 0x75, 0x98, 0xef, 0xfb, 0x61, 0xcc, 0xbd, 0x36, 0xfd, 0xd0, 0x99, 0x85, 0xf3,
|
||||
0x2a, 0xa0, 0x5a, 0xa4, 0x02, 0x74, 0x11, 0x9e, 0xc9, 0x88, 0xb0, 0x0d, 0x4d, 0xd6, 0x28, 0x95,
|
||||
0x1a, 0x69, 0x96, 0x7b, 0x72, 0x3a, 0xc6, 0xc6, 0x93, 0x15, 0x18, 0x2e, 0x9d, 0xf3, 0x45, 0xe2,
|
||||
0xc2, 0xce, 0xb4, 0x4c, 0xe3, 0x69, 0xd4, 0x75, 0x21, 0x2e, 0xf9, 0x2a, 0x72, 0x0f, 0x80, 0xf7,
|
||||
0x85, 0x66, 0x17, 0xd0, 0xec, 0xbe, 0x61, 0xee, 0x88, 0xbe, 0xf6, 0xb7, 0x58, 0x61, 0x12, 0x51,
|
||||
0x34, 0xc5, 0xda, 0x97, 0xf6, 0xcf, 0x5b, 0xd0, 0xd0, 0xea, 0xc8, 0x32, 0x2c, 0x6c, 0x3f, 0x7c,
|
||||
0x78, 0xb8, 0xeb, 0x6c, 0x3d, 0x7a, 0xf0, 0x95, 0xdd, 0xde, 0xf6, 0xfe, 0xc3, 0xa3, 0xdd, 0xf6,
|
||||
0x15, 0x06, 0xef, 0x3f, 0xdc, 0xde, 0xda, 0xef, 0xdd, 0x7b, 0xe8, 0x6c, 0x4b, 0xd8, 0x22, 0x2b,
|
||||
0x40, 0x9c, 0xdd, 0xf7, 0x1f, 0x3e, 0xda, 0x35, 0xf0, 0x12, 0x69, 0x43, 0xf3, 0xae, 0xb3, 0xbb,
|
||||
0xb5, 0xbd, 0x27, 0x90, 0x32, 0x59, 0x82, 0xf6, 0xbd, 0xc7, 0x07, 0x3b, 0x0f, 0x0e, 0xee, 0xf7,
|
||||
0xb6, 0xb7, 0x0e, 0xb6, 0x77, 0xf7, 0x77, 0x77, 0xda, 0x15, 0x32, 0x07, 0xf5, 0xad, 0xbb, 0x5b,
|
||||
0x07, 0x3b, 0x0f, 0x0f, 0x76, 0x77, 0xda, 0x55, 0xfb, 0xef, 0x2c, 0x58, 0xc6, 0x51, 0x0f, 0xb2,
|
||||
0x02, 0xb2, 0x06, 0x8d, 0x7e, 0x18, 0x8e, 0x29, 0xd3, 0xf6, 0x4a, 0xa1, 0xeb, 0x10, 0x63, 0x7e,
|
||||
0xae, 0x3e, 0x4f, 0xc2, 0xa8, 0x4f, 0x85, 0x7c, 0x00, 0x42, 0xf7, 0x18, 0xc2, 0x98, 0x5f, 0x6c,
|
||||
0x2f, 0xa7, 0xe0, 0xe2, 0xd1, 0xe0, 0x18, 0x27, 0x59, 0x81, 0x99, 0xe3, 0x88, 0xba, 0xfd, 0x53,
|
||||
0x21, 0x19, 0xa2, 0x44, 0x3e, 0x99, 0x1e, 0x30, 0xfa, 0x6c, 0xf5, 0x7d, 0x3a, 0x40, 0x8e, 0xa9,
|
||||
0x39, 0xf3, 0x02, 0xdf, 0x16, 0x30, 0x93, 0x7f, 0xf7, 0xd8, 0x0d, 0x06, 0x61, 0x40, 0x07, 0xc2,
|
||||
0xd9, 0x4b, 0x01, 0xfb, 0x10, 0x56, 0xb2, 0xf3, 0x13, 0xf2, 0xf5, 0xb6, 0x26, 0x5f, 0xdc, 0xf7,
|
||||
0xea, 0x4e, 0xdf, 0x4d, 0x4d, 0xd6, 0xfe, 0xd9, 0x82, 0x0a, 0x33, 0xc5, 0xd3, 0xcd, 0xb6, 0xee,
|
||||
0x5d, 0x95, 0x73, 0x11, 0x2a, 0x3c, 0xb3, 0x70, 0xe5, 0xcc, 0x0d, 0x98, 0x86, 0xa4, 0xf5, 0x11,
|
||||
0xed, 0x9f, 0xe1, 0x8c, 0x55, 0x3d, 0x43, 0x98, 0x80, 0x30, 0xd7, 0x17, 0xbf, 0x16, 0x02, 0x22,
|
||||
0xcb, 0xb2, 0x0e, 0xbf, 0x9c, 0x4d, 0xeb, 0xf0, 0xbb, 0x0e, 0xcc, 0x7a, 0xc1, 0x71, 0x38, 0x09,
|
||||
0x06, 0x28, 0x10, 0x35, 0x47, 0x16, 0x31, 0x26, 0x86, 0x82, 0xea, 0x8d, 0x24, 0xfb, 0xa7, 0x80,
|
||||
0x4d, 0xd8, 0xd1, 0x28, 0x46, 0xd7, 0x43, 0x85, 0x67, 0xde, 0x86, 0x05, 0x0d, 0x4b, 0xdd, 0xd8,
|
||||
0x31, 0x03, 0x32, 0x6e, 0x2c, 0xfa, 0x2c, 0xbc, 0xc6, 0x6e, 0x43, 0xeb, 0x3e, 0x4d, 0x1e, 0x04,
|
||||
0x27, 0xa1, 0x6c, 0xe9, 0x77, 0x2b, 0x30, 0xaf, 0x20, 0xd1, 0xd0, 0x3a, 0xcc, 0x7b, 0x03, 0x1a,
|
||||
0x24, 0x5e, 0x72, 0xd1, 0x33, 0x4e, 0x60, 0x59, 0x98, 0xf9, 0x7a, 0xae, 0xef, 0xb9, 0x32, 0x0a,
|
||||
0xc8, 0x0b, 0xe4, 0x0e, 0x2c, 0x31, 0x43, 0x24, 0x6d, 0x8b, 0xda, 0x62, 0x7e, 0xf0, 0x2b, 0xac,
|
||||
0x63, 0xca, 0x80, 0xe1, 0x42, 0xdb, 0xab, 0x4f, 0xb8, 0xcf, 0x53, 0x54, 0xc5, 0x56, 0x8d, 0xb7,
|
||||
0xc4, 0xa6, 0x5c, 0xe5, 0xc6, 0x4a, 0x01, 0xb9, 0x30, 0xdb, 0x0c, 0x57, 0x55, 0xd9, 0x30, 0x9b,
|
||||
0x16, 0xaa, 0xab, 0xe5, 0x42, 0x75, 0x4c, 0x95, 0x5d, 0x04, 0x7d, 0x3a, 0xe8, 0x25, 0x61, 0x0f,
|
||||
0x55, 0x2e, 0xee, 0x4e, 0xcd, 0xc9, 0xc2, 0xe4, 0x1a, 0xcc, 0x26, 0x34, 0x4e, 0x02, 0x9a, 0xa0,
|
||||
0x56, 0xaa, 0x61, 0x40, 0x40, 0x42, 0xcc, 0x41, 0x9d, 0x44, 0x5e, 0xdc, 0x69, 0x62, 0x10, 0x0e,
|
||||
0xff, 0x27, 0x9f, 0x81, 0xe5, 0x63, 0x1a, 0x27, 0xbd, 0x53, 0xea, 0x0e, 0x68, 0x84, 0x3b, 0xcd,
|
||||
0xa3, 0x7d, 0xdc, 0xee, 0x17, 0x57, 0x32, 0x1e, 0x3a, 0xa3, 0x51, 0xec, 0x85, 0x01, 0x5a, 0xfc,
|
||||
0xba, 0x23, 0x8b, 0xac, 0x3d, 0x36, 0x79, 0x65, 0x2f, 0xd5, 0x0a, 0xce, 0xe3, 0xc4, 0x8b, 0x2b,
|
||||
0xc9, 0x0d, 0x98, 0xc1, 0x09, 0xc4, 0x9d, 0xb6, 0x11, 0xd5, 0xd8, 0x66, 0xa0, 0x23, 0xea, 0xbe,
|
||||
0x58, 0xa9, 0x35, 0xda, 0x4d, 0xfb, 0x73, 0x50, 0x45, 0x98, 0x6d, 0x3a, 0x5f, 0x0c, 0xce, 0x14,
|
||||
0xbc, 0xc0, 0x86, 0x16, 0xd0, 0xe4, 0x3c, 0x8c, 0x9e, 0xca, 0x90, 0xb0, 0x28, 0xda, 0xdf, 0x42,
|
||||
0x17, 0x5f, 0x85, 0x48, 0x1f, 0xa3, 0x7f, 0xc2, 0x0e, 0x6a, 0x7c, 0xa9, 0xe3, 0x53, 0x57, 0x9c,
|
||||
0x3a, 0x6a, 0x08, 0x1c, 0x9d, 0xba, 0x4c, 0x6d, 0x19, 0xbb, 0xc7, 0x0f, 0x72, 0x0d, 0xc4, 0xf6,
|
||||
0xf8, 0xe6, 0xdd, 0x80, 0x96, 0x0c, 0xbe, 0xc6, 0x3d, 0x9f, 0x9e, 0x24, 0x32, 0xae, 0x10, 0x4c,
|
||||
0x46, 0x78, 0xda, 0xdb, 0xa7, 0x27, 0x89, 0x7d, 0x00, 0x0b, 0x42, 0x95, 0x3c, 0x1c, 0x53, 0xd9,
|
||||
0xf5, 0xe7, 0x8b, 0x4c, 0x72, 0xe3, 0xce, 0xa2, 0xa9, 0x7b, 0x78, 0xb8, 0xd9, 0xa4, 0xb4, 0x1d,
|
||||
0x20, 0xba, 0x6a, 0x12, 0x0d, 0x0a, 0xbb, 0x28, 0x23, 0x27, 0x62, 0x3a, 0x06, 0xc6, 0xd6, 0x27,
|
||||
0x9e, 0xf4, 0xfb, 0x32, 0x64, 0xce, 0x8e, 0xc3, 0xbc, 0x68, 0xff, 0x9e, 0x05, 0x8b, 0xd8, 0x9a,
|
||||
0x74, 0x2a, 0x84, 0xfa, 0x7f, 0xe7, 0x63, 0x0c, 0xb3, 0xd9, 0xd7, 0xa3, 0x49, 0x4b, 0x50, 0xd5,
|
||||
0x0d, 0x02, 0x2f, 0x7c, 0xfc, 0x43, 0x7d, 0x25, 0x7b, 0xa8, 0xb7, 0x7f, 0xdd, 0x82, 0x05, 0xae,
|
||||
0x93, 0x13, 0x37, 0x99, 0xc4, 0x62, 0xfa, 0xff, 0x0b, 0xe6, 0xb8, 0x71, 0x15, 0x52, 0x2d, 0x06,
|
||||
0xba, 0xa4, 0x14, 0x10, 0xa2, 0x9c, 0x78, 0xef, 0x8a, 0x63, 0x12, 0x93, 0xf7, 0xd0, 0xc1, 0x09,
|
||||
0x7a, 0x88, 0x8a, 0xc0, 0xe0, 0xd5, 0x02, 0x33, 0xa0, 0xbe, 0xd7, 0xc8, 0xef, 0xd6, 0x60, 0x86,
|
||||
0xfb, 0xbb, 0xf6, 0x7d, 0x98, 0x33, 0x3a, 0x32, 0x02, 0x0a, 0x4d, 0x1e, 0x50, 0xc8, 0x85, 0xa2,
|
||||
0x4a, 0x05, 0xa1, 0xa8, 0xdf, 0x2f, 0x03, 0x61, 0xcc, 0x92, 0xd9, 0x0d, 0xe6, 0x70, 0x87, 0x03,
|
||||
0xe3, 0xf8, 0xd4, 0x74, 0x74, 0x88, 0xdc, 0x02, 0xa2, 0x15, 0x65, 0x44, 0x91, 0x5b, 0x9f, 0x82,
|
||||
0x1a, 0xa6, 0x26, 0x85, 0xf1, 0x16, 0x66, 0x56, 0x1c, 0x14, 0xf9, 0xb2, 0x17, 0xd6, 0x31, 0x03,
|
||||
0x33, 0x9e, 0xc4, 0xa7, 0x78, 0xb9, 0x22, 0x0e, 0x58, 0xb2, 0x9c, 0xdd, 0xdf, 0x99, 0x4b, 0xf7,
|
||||
0x77, 0x36, 0x17, 0xb4, 0xd1, 0x5c, 0xfc, 0x9a, 0xe9, 0xe2, 0xdf, 0x80, 0xb9, 0x11, 0x73, 0x39,
|
||||
0x13, 0xbf, 0xdf, 0x1b, 0xb1, 0xde, 0xc5, 0x79, 0xca, 0x00, 0xc9, 0x06, 0xb4, 0x85, 0xbb, 0x91,
|
||||
0x9e, 0x23, 0x00, 0xd7, 0x38, 0x87, 0x33, 0xfd, 0x9d, 0x86, 0x71, 0x1a, 0x38, 0xd8, 0x14, 0x60,
|
||||
0x27, 0xaf, 0x98, 0x71, 0x48, 0x6f, 0x12, 0x88, 0xfb, 0x15, 0x3a, 0xc0, 0x93, 0x54, 0xcd, 0xc9,
|
||||
0x57, 0xd8, 0xbf, 0x62, 0x41, 0x9b, 0xed, 0x99, 0xc1, 0x96, 0xef, 0x02, 0x4a, 0xc5, 0x4b, 0x72,
|
||||
0xa5, 0x41, 0x4b, 0xde, 0x81, 0x3a, 0x96, 0xc3, 0x31, 0x0d, 0x04, 0x4f, 0x76, 0x4c, 0x9e, 0x4c,
|
||||
0xf5, 0xc9, 0xde, 0x15, 0x27, 0x25, 0xd6, 0x38, 0xf2, 0xaf, 0x2c, 0x68, 0x88, 0x5e, 0x7e, 0xe8,
|
||||
0x30, 0x41, 0x57, 0xbb, 0x10, 0xe3, 0x9c, 0x94, 0xde, 0x7f, 0xad, 0xc3, 0xfc, 0xc8, 0x4d, 0x26,
|
||||
0x11, 0xb3, 0xc7, 0x46, 0x88, 0x20, 0x0b, 0x33, 0xe3, 0x8a, 0xaa, 0x33, 0xee, 0x25, 0x9e, 0xdf,
|
||||
0x93, 0xb5, 0xe2, 0xea, 0xa9, 0xa8, 0x8a, 0x69, 0x90, 0x38, 0x71, 0x87, 0x54, 0xd8, 0x4d, 0x5e,
|
||||
0xb0, 0x3b, 0xb0, 0x22, 0x26, 0x94, 0x71, 0x55, 0xed, 0x3f, 0x69, 0xc2, 0x6a, 0xae, 0x4a, 0xdd,
|
||||
0x4f, 0x8b, 0xb3, 0xaf, 0xef, 0x8d, 0x8e, 0x43, 0xe5, 0xe7, 0x5b, 0xfa, 0xb1, 0xd8, 0xa8, 0x22,
|
||||
0x43, 0x58, 0x96, 0x0e, 0x02, 0x5b, 0xd3, 0xd4, 0x98, 0x95, 0xd0, 0x4a, 0xbd, 0x65, 0x6e, 0x61,
|
||||
0xb6, 0x43, 0x89, 0xeb, 0x42, 0x5c, 0xdc, 0x1e, 0x39, 0x85, 0x8e, 0xf2, 0x44, 0x84, 0xb2, 0xd6,
|
||||
0xbc, 0x15, 0xd6, 0xd7, 0x9b, 0x97, 0xf4, 0x65, 0x78, 0xb6, 0xce, 0xd4, 0xd6, 0xc8, 0x05, 0x5c,
|
||||
0x97, 0x75, 0xa8, 0x8d, 0xf3, 0xfd, 0x55, 0x5e, 0x6a, 0x6e, 0xe8, 0xb3, 0x9b, 0x9d, 0x5e, 0xd2,
|
||||
0x30, 0xf9, 0x10, 0x56, 0xce, 0x5d, 0x2f, 0x91, 0xc3, 0xd2, 0x7c, 0x83, 0x2a, 0x76, 0x79, 0xe7,
|
||||
0x92, 0x2e, 0x9f, 0xf0, 0x8f, 0x0d, 0x13, 0x35, 0xa5, 0xc5, 0xee, 0x5f, 0x58, 0xd0, 0x32, 0xdb,
|
||||
0x61, 0x6c, 0x2a, 0x64, 0x5f, 0xea, 0x40, 0xe9, 0x4d, 0x66, 0xe0, 0xfc, 0x51, 0xb9, 0x54, 0x74,
|
||||
0x54, 0xd6, 0x0f, 0xa8, 0xe5, 0xcb, 0x62, 0x4c, 0x95, 0x97, 0x8b, 0x31, 0x55, 0x8b, 0x62, 0x4c,
|
||||
0xdd, 0x7f, 0xb7, 0x80, 0xe4, 0x79, 0x89, 0xdc, 0xe7, 0x67, 0xf5, 0x80, 0xfa, 0x42, 0xa5, 0xfc,
|
||||
0xcf, 0x97, 0xe3, 0x47, 0xb9, 0x76, 0xf2, 0x6b, 0x26, 0x18, 0xfa, 0xdd, 0xb1, 0xee, 0xec, 0xcc,
|
||||
0x39, 0x45, 0x55, 0x99, 0xa8, 0x57, 0xe5, 0xf2, 0xa8, 0x57, 0xf5, 0xf2, 0xa8, 0xd7, 0x4c, 0x36,
|
||||
0xea, 0xd5, 0xfd, 0x19, 0x0b, 0x16, 0x0b, 0x36, 0xfd, 0xc7, 0x37, 0x71, 0xb6, 0x4d, 0x86, 0x2e,
|
||||
0x28, 0x89, 0x6d, 0xd2, 0xc1, 0xee, 0x4f, 0xc0, 0x9c, 0xc1, 0xe8, 0x3f, 0xbe, 0xfe, 0xb3, 0xfe,
|
||||
0x1a, 0xe7, 0x33, 0x03, 0xeb, 0xfe, 0x4b, 0x09, 0x48, 0x5e, 0xd8, 0xfe, 0x5b, 0xc7, 0x90, 0x5f,
|
||||
0xa7, 0x72, 0xc1, 0x3a, 0xfd, 0x97, 0xda, 0x81, 0x37, 0x61, 0x41, 0x24, 0xb3, 0x68, 0x11, 0x1a,
|
||||
0xce, 0x31, 0xf9, 0x0a, 0xe6, 0xb1, 0x9a, 0x21, 0xc7, 0x9a, 0x91, 0x20, 0xa0, 0x19, 0xc3, 0x4c,
|
||||
0xe4, 0xd1, 0xee, 0x42, 0x47, 0xac, 0xd0, 0xee, 0x19, 0x0d, 0x92, 0xa3, 0xc9, 0x31, 0xcf, 0x08,
|
||||
0xf1, 0xc2, 0xc0, 0xfe, 0x7e, 0x59, 0x39, 0xdd, 0x58, 0x29, 0xcc, 0xfb, 0x67, 0xa0, 0xa9, 0x2b,
|
||||
0x73, 0xb1, 0x1d, 0x99, 0x00, 0x1d, 0x33, 0xec, 0x3a, 0x15, 0xd9, 0x81, 0x16, 0xaa, 0xac, 0x81,
|
||||
0xfa, 0xae, 0x84, 0xdf, 0xbd, 0x20, 0xf0, 0xb0, 0x77, 0xc5, 0xc9, 0x7c, 0x43, 0xbe, 0x00, 0x2d,
|
||||
0xf3, 0x28, 0x25, 0x7c, 0x84, 0x22, 0xdf, 0x9c, 0x7d, 0x6e, 0x12, 0x93, 0x2d, 0x68, 0x67, 0xcf,
|
||||
0x62, 0xe2, 0xb6, 0x78, 0x4a, 0x03, 0x39, 0x72, 0xf2, 0x8e, 0xb8, 0x7b, 0xaa, 0x62, 0x10, 0xec,
|
||||
0x86, 0xf9, 0x99, 0xb6, 0x4c, 0xb7, 0xf8, 0x1f, 0xed, 0x36, 0xea, 0xeb, 0x00, 0x29, 0x46, 0xda,
|
||||
0xd0, 0x7c, 0x78, 0xb8, 0x7b, 0xd0, 0xdb, 0xde, 0xdb, 0x3a, 0x38, 0xd8, 0xdd, 0x6f, 0x5f, 0x21,
|
||||
0x04, 0x5a, 0x18, 0xbf, 0xda, 0x51, 0x98, 0xc5, 0xb0, 0xad, 0x6d, 0x1e, 0x1b, 0x13, 0x58, 0x89,
|
||||
0x2c, 0x41, 0xfb, 0xc1, 0x41, 0x06, 0x2d, 0xdf, 0xad, 0x2b, 0xf9, 0xb0, 0x57, 0x60, 0x89, 0x27,
|
||||
0x3c, 0xdd, 0xe5, 0xec, 0x21, 0x7d, 0x85, 0xdf, 0xb4, 0x60, 0x39, 0x53, 0x91, 0x26, 0x1e, 0x70,
|
||||
0x77, 0xc0, 0xf4, 0x11, 0x4c, 0x90, 0xf1, 0xa4, 0xf2, 0xfc, 0x32, 0x1a, 0x24, 0x5f, 0xc1, 0x78,
|
||||
0x5e, 0xf3, 0x14, 0x33, 0x92, 0x54, 0x54, 0x65, 0xaf, 0xf2, 0xb4, 0xac, 0x80, 0xfa, 0x99, 0x81,
|
||||
0x9f, 0xf0, 0x44, 0x2a, 0xbd, 0x22, 0xbd, 0xcb, 0x33, 0x87, 0x2c, 0x8b, 0xcc, 0xc9, 0x37, 0x5c,
|
||||
0x0f, 0x73, 0xbc, 0x85, 0x75, 0xf6, 0x9f, 0x96, 0x80, 0x7c, 0x79, 0x42, 0xa3, 0x0b, 0xcc, 0x19,
|
||||
0x50, 0xe1, 0xc0, 0xd5, 0x6c, 0xb0, 0x6b, 0x66, 0x3c, 0x39, 0xfe, 0x12, 0xbd, 0x90, 0x09, 0x2d,
|
||||
0x25, 0x3d, 0xa1, 0x05, 0xd8, 0xe1, 0x58, 0x65, 0x2c, 0x58, 0xeb, 0x55, 0x0c, 0x49, 0xd4, 0x83,
|
||||
0xc9, 0x88, 0x37, 0x5a, 0x98, 0x77, 0x52, 0xb9, 0x3c, 0xef, 0xa4, 0x7a, 0x59, 0xde, 0xc9, 0x27,
|
||||
0x60, 0xce, 0x1b, 0x06, 0x21, 0x53, 0x0b, 0xcc, 0xb0, 0xc7, 0x9d, 0x99, 0xb5, 0x32, 0x3b, 0x0c,
|
||||
0x0b, 0xf0, 0x80, 0x61, 0xe4, 0x73, 0x29, 0x11, 0x1d, 0x0c, 0x31, 0x87, 0x49, 0x57, 0x14, 0xbb,
|
||||
0x83, 0x21, 0xdd, 0x0f, 0xfb, 0x6e, 0x12, 0x46, 0xea, 0x43, 0x86, 0xc5, 0xec, 0xd4, 0x1f, 0x87,
|
||||
0x13, 0xe6, 0xe6, 0xc8, 0xa5, 0xe0, 0x61, 0x9b, 0x26, 0x47, 0x0f, 0x71, 0x41, 0xec, 0xaf, 0x42,
|
||||
0x43, 0x6b, 0x82, 0xbc, 0xca, 0x4f, 0x98, 0xcc, 0x85, 0x10, 0xe7, 0xc1, 0x0a, 0xf7, 0xd8, 0x03,
|
||||
0xea, 0x3f, 0x18, 0x90, 0x4f, 0xc1, 0xc2, 0xc0, 0x8b, 0x28, 0xe6, 0x2a, 0xf5, 0x22, 0x7a, 0x46,
|
||||
0xa3, 0x58, 0x9e, 0x9c, 0xdb, 0xaa, 0xc2, 0xe1, 0xb8, 0xfd, 0x1e, 0x2c, 0x1a, 0x5b, 0xa3, 0x38,
|
||||
0x57, 0xa6, 0x87, 0x58, 0xf9, 0xf4, 0x10, 0x99, 0x1a, 0x62, 0xff, 0x5c, 0x09, 0xca, 0x7b, 0xe1,
|
||||
0x58, 0x8f, 0xf6, 0x5b, 0x66, 0xb4, 0x5f, 0xb8, 0x40, 0x3d, 0xe5, 0xe1, 0x08, 0xcb, 0x68, 0x80,
|
||||
0x64, 0x03, 0x5a, 0xee, 0x28, 0xe9, 0x25, 0x21, 0x73, 0xf9, 0xce, 0xdd, 0x68, 0xc0, 0xd9, 0x19,
|
||||
0xb7, 0x38, 0x53, 0x43, 0x96, 0xa0, 0xac, 0x7c, 0x05, 0x24, 0x60, 0x45, 0x76, 0xde, 0xc0, 0x7b,
|
||||
0xc4, 0x0b, 0x11, 0x39, 0x13, 0x25, 0x26, 0x2d, 0xe6, 0xf7, 0xfc, 0xb0, 0xc7, 0x35, 0x7e, 0x51,
|
||||
0x15, 0x73, 0xc7, 0x18, 0x77, 0x20, 0x99, 0x08, 0x79, 0xca, 0xb2, 0x1e, 0x9e, 0xad, 0x99, 0xb7,
|
||||
0xaa, 0xff, 0x64, 0x41, 0x15, 0xd7, 0x86, 0x59, 0x2f, 0x2e, 0xde, 0x2a, 0xe0, 0x8f, 0x6b, 0x32,
|
||||
0xe7, 0x64, 0x61, 0x62, 0x1b, 0x59, 0x6f, 0x25, 0x35, 0x21, 0x3d, 0xf3, 0x6d, 0x0d, 0xea, 0xbc,
|
||||
0xa4, 0x32, 0xbc, 0x38, 0xdf, 0x2b, 0x90, 0x5c, 0x87, 0xca, 0x69, 0x38, 0x96, 0xee, 0x36, 0xc8,
|
||||
0xdb, 0xb0, 0x70, 0xec, 0x20, 0x9e, 0x8e, 0x87, 0xb5, 0xc7, 0xa7, 0xc5, 0x9d, 0xa8, 0x2c, 0xcc,
|
||||
0xdc, 0x48, 0xd5, 0xac, 0xbe, 0x4c, 0x19, 0xd4, 0xde, 0x80, 0x79, 0xc6, 0xf5, 0x5a, 0xd4, 0x75,
|
||||
0xaa, 0x28, 0xdb, 0x3f, 0x69, 0x41, 0x4d, 0x12, 0x93, 0x75, 0xa8, 0x30, 0x11, 0xca, 0x1c, 0x5c,
|
||||
0xd5, 0x2d, 0x38, 0xa3, 0x73, 0x90, 0x82, 0x39, 0x13, 0x18, 0x0c, 0x4b, 0xcf, 0x49, 0x32, 0x14,
|
||||
0x96, 0x1e, 0x03, 0xd4, 0x70, 0x33, 0xde, 0x73, 0x06, 0xb5, 0xbf, 0x67, 0xc1, 0x9c, 0xd1, 0x07,
|
||||
0x59, 0x83, 0x86, 0xef, 0xc6, 0x89, 0xb8, 0x59, 0x14, 0xdb, 0xa3, 0x43, 0xfa, 0x46, 0x97, 0xcc,
|
||||
0x38, 0xbc, 0x8a, 0x10, 0x97, 0xf5, 0x08, 0xf1, 0x6d, 0xa8, 0xa7, 0xb9, 0x89, 0x15, 0x43, 0xf6,
|
||||
0x59, 0x8f, 0xf2, 0x7e, 0x3f, 0x25, 0xc2, 0xa0, 0x63, 0xe8, 0x87, 0x91, 0xb8, 0xb4, 0xe2, 0x05,
|
||||
0xfb, 0x3d, 0x68, 0x68, 0xf4, 0x7a, 0x0c, 0xd2, 0x32, 0x62, 0x90, 0x2a, 0xf9, 0xa5, 0x94, 0x26,
|
||||
0xbf, 0xd8, 0xff, 0x6a, 0xc1, 0x1c, 0xe3, 0x41, 0x2f, 0x18, 0x1e, 0x86, 0xbe, 0xd7, 0xbf, 0xc0,
|
||||
0xbd, 0x97, 0xec, 0x26, 0x54, 0xa2, 0xe4, 0x45, 0x13, 0x66, 0x5c, 0x2f, 0x23, 0x1f, 0x42, 0x44,
|
||||
0x55, 0x99, 0xc9, 0x30, 0x93, 0x80, 0x63, 0x37, 0x16, 0x62, 0x21, 0xbc, 0x36, 0x03, 0x64, 0x92,
|
||||
0xc6, 0x80, 0xc8, 0x4d, 0x68, 0x6f, 0xe4, 0xf9, 0xbe, 0xc7, 0x69, 0xb9, 0x4f, 0x5f, 0x54, 0xc5,
|
||||
0xfa, 0x1c, 0x78, 0xb1, 0x7b, 0x9c, 0x5e, 0xc4, 0xa8, 0x32, 0x86, 0x67, 0xdc, 0x67, 0x5a, 0x78,
|
||||
0x66, 0x06, 0xf5, 0x8a, 0x09, 0xda, 0x7f, 0x54, 0x82, 0x86, 0x74, 0x11, 0x06, 0x43, 0x2a, 0xee,
|
||||
0x16, 0x4d, 0xc5, 0xa8, 0x21, 0xb2, 0xde, 0x38, 0x8d, 0x69, 0x48, 0x96, 0x31, 0xca, 0x79, 0xc6,
|
||||
0xb8, 0x06, 0x75, 0xc6, 0xa0, 0x6f, 0xe1, 0xb1, 0x4f, 0xa4, 0xfb, 0x2a, 0x40, 0xd6, 0xde, 0xc1,
|
||||
0xda, 0x6a, 0x5a, 0x8b, 0xc0, 0x0b, 0x6f, 0x22, 0xdf, 0x81, 0xa6, 0x68, 0x06, 0x77, 0x0e, 0x35,
|
||||
0x4f, 0x2a, 0x22, 0xc6, 0xae, 0x3a, 0x06, 0xa5, 0xfc, 0xf2, 0x8e, 0xfc, 0xb2, 0x76, 0xd9, 0x97,
|
||||
0x92, 0xd2, 0xbe, 0xaf, 0x2e, 0x78, 0xef, 0x47, 0xee, 0xf8, 0x54, 0xca, 0xf2, 0x6d, 0x58, 0xf4,
|
||||
0x82, 0xbe, 0x3f, 0x19, 0xd0, 0xde, 0x24, 0x70, 0x83, 0x20, 0x9c, 0x04, 0x7d, 0x2a, 0xb3, 0x5f,
|
||||
0x8a, 0xaa, 0xec, 0x81, 0x4a, 0xfe, 0xc3, 0x86, 0xc8, 0x06, 0x54, 0xb9, 0xa9, 0xe4, 0xb6, 0xa3,
|
||||
0x58, 0xd0, 0x39, 0x09, 0x59, 0x87, 0x2a, 0xb7, 0x98, 0x25, 0x43, 0x6a, 0xb4, 0x5d, 0x75, 0x38,
|
||||
0x01, 0x53, 0x3b, 0x98, 0xe0, 0x69, 0xaa, 0x1d, 0xd3, 0xee, 0xcc, 0xf4, 0x79, 0x0a, 0xe8, 0x12,
|
||||
0x90, 0x03, 0x2e, 0x29, 0xfa, 0xdd, 0xd0, 0x4f, 0x97, 0xa1, 0xa1, 0xc1, 0x4c, 0x83, 0x0c, 0xd9,
|
||||
0x80, 0x7b, 0x03, 0xcf, 0x1d, 0xd1, 0x84, 0x46, 0x42, 0x3a, 0x32, 0x28, 0xa3, 0x73, 0xcf, 0x86,
|
||||
0xbd, 0x70, 0x92, 0xf4, 0x06, 0x74, 0x18, 0x51, 0x6e, 0x4d, 0x99, 0x69, 0x32, 0x50, 0x46, 0xc7,
|
||||
0xf8, 0x53, 0xa3, 0xe3, 0x1c, 0x94, 0x41, 0xe5, 0x4d, 0x0f, 0x5f, 0xa3, 0x4a, 0x7a, 0xd3, 0xc3,
|
||||
0x57, 0x24, 0xab, 0xfb, 0xaa, 0x05, 0xba, 0xef, 0x6d, 0x58, 0xe1, 0x5a, 0x4e, 0xe8, 0x83, 0x5e,
|
||||
0x86, 0xb1, 0xa6, 0xd4, 0x92, 0x0d, 0x68, 0xb3, 0x31, 0x4b, 0x91, 0x88, 0xbd, 0x6f, 0xf1, 0xa8,
|
||||
0xa9, 0xe5, 0xe4, 0x70, 0x46, 0x8b, 0xe1, 0x4b, 0x9d, 0x96, 0xdf, 0x7c, 0xe7, 0x70, 0xa4, 0x75,
|
||||
0x9f, 0x99, 0xb4, 0x75, 0x41, 0x9b, 0xc1, 0xed, 0x39, 0x68, 0x1c, 0x25, 0xe1, 0x58, 0x6e, 0x4a,
|
||||
0x0b, 0x9a, 0xbc, 0x28, 0xb2, 0x90, 0x5e, 0x81, 0xab, 0xc8, 0x45, 0x8f, 0xc2, 0x71, 0xe8, 0x87,
|
||||
0xc3, 0x0b, 0xe3, 0xe8, 0xf4, 0x97, 0x16, 0x2c, 0x1a, 0xb5, 0xe9, 0xd9, 0x09, 0xa3, 0x2e, 0x32,
|
||||
0x7d, 0x84, 0x33, 0xde, 0x82, 0xa6, 0x82, 0x39, 0x21, 0x0f, 0x70, 0x3f, 0x16, 0x19, 0x25, 0x5b,
|
||||
0x30, 0x2f, 0x47, 0x26, 0x3f, 0xe4, 0x5c, 0xd8, 0xc9, 0x73, 0xa1, 0xf8, 0xbe, 0x25, 0x3e, 0x90,
|
||||
0x4d, 0x7c, 0x41, 0x64, 0x10, 0xf0, 0xa3, 0x94, 0x0c, 0xb2, 0xa9, 0xc3, 0x97, 0x7e, 0xd4, 0x96,
|
||||
0x23, 0xe8, 0x2b, 0x30, 0xb6, 0x7f, 0xc1, 0x02, 0x48, 0x47, 0x87, 0xf7, 0xce, 0xca, 0x8c, 0xf0,
|
||||
0xe7, 0x2e, 0x9a, 0xc9, 0x78, 0x1d, 0x9a, 0xea, 0xbe, 0x32, 0xb5, 0x4c, 0x0d, 0x89, 0x31, 0xcf,
|
||||
0xf9, 0x26, 0xcc, 0x0f, 0xfd, 0xf0, 0x18, 0xcd, 0x3a, 0xa6, 0xb5, 0xc5, 0x22, 0x17, 0xab, 0xc5,
|
||||
0xe1, 0x7b, 0x02, 0x4d, 0xcd, 0x58, 0x45, 0x33, 0x63, 0xf6, 0x2f, 0x96, 0xd4, 0xf5, 0x52, 0x3a,
|
||||
0xe7, 0xa9, 0x52, 0x46, 0xee, 0xe4, 0xd4, 0xe9, 0x94, 0xdb, 0x1c, 0x74, 0x4e, 0x0f, 0x2f, 0x8d,
|
||||
0x76, 0xbd, 0x07, 0xad, 0x88, 0xeb, 0x2b, 0xa9, 0xcc, 0x2a, 0x2f, 0x50, 0x66, 0x73, 0x91, 0x61,
|
||||
0xeb, 0x3e, 0x09, 0x6d, 0x77, 0x70, 0x46, 0xa3, 0xc4, 0xc3, 0x78, 0x03, 0x3a, 0x1a, 0x5c, 0x05,
|
||||
0xcf, 0x6b, 0x38, 0xda, 0xff, 0x9b, 0x30, 0x2f, 0xf2, 0xdf, 0x14, 0xa5, 0xc8, 0x65, 0x4f, 0x61,
|
||||
0x46, 0x68, 0xff, 0xb6, 0xbc, 0xc9, 0x32, 0xf7, 0x70, 0xfa, 0x8a, 0xe8, 0xb3, 0x2b, 0x65, 0x66,
|
||||
0xf7, 0x09, 0x71, 0xab, 0x34, 0x90, 0x41, 0x8d, 0xb2, 0x96, 0x6d, 0x32, 0x10, 0xb7, 0x80, 0xe6,
|
||||
0x92, 0x56, 0x5e, 0x66, 0x49, 0xed, 0x1f, 0x58, 0x30, 0xbb, 0x17, 0x8e, 0xf7, 0x44, 0xde, 0x0d,
|
||||
0x0a, 0x82, 0x4a, 0x3c, 0x95, 0xc5, 0x17, 0x64, 0xe4, 0x14, 0xda, 0xf7, 0xb9, 0xac, 0x7d, 0xff,
|
||||
0xbf, 0xf0, 0x0a, 0x86, 0xd4, 0xa2, 0x70, 0x1c, 0x46, 0x4c, 0x18, 0x5d, 0x9f, 0x1b, 0xf3, 0x30,
|
||||
0x48, 0x4e, 0xa5, 0x1a, 0x7b, 0x11, 0x09, 0x9e, 0x73, 0xd9, 0xd9, 0x8c, 0xbb, 0xe6, 0xc2, 0x1f,
|
||||
0xe1, 0xda, 0x2d, 0x5f, 0x61, 0x7f, 0x1e, 0xea, 0xe8, 0x50, 0xe3, 0xb4, 0xde, 0x84, 0xfa, 0x69,
|
||||
0x38, 0xee, 0x9d, 0x7a, 0x41, 0x22, 0x85, 0xbb, 0x95, 0x7a, 0xba, 0x7b, 0xb8, 0x20, 0x8a, 0xc0,
|
||||
0xfe, 0xb5, 0x19, 0x98, 0x7d, 0x10, 0x9c, 0x85, 0x5e, 0x1f, 0x6f, 0xcd, 0x46, 0x74, 0x14, 0xca,
|
||||
0x34, 0x5c, 0xf6, 0x3f, 0xb9, 0x06, 0xb3, 0x98, 0x77, 0x36, 0xe6, 0x4c, 0xdb, 0xe4, 0xb7, 0xdb,
|
||||
0x02, 0x62, 0x4e, 0x42, 0x94, 0xbe, 0x00, 0xe0, 0xe2, 0xa3, 0x21, 0xec, 0xa8, 0x11, 0xe9, 0x19,
|
||||
0xfc, 0xa2, 0x94, 0xa6, 0x39, 0x57, 0xb5, 0x34, 0x67, 0xd6, 0x97, 0xc8, 0x13, 0xe2, 0x89, 0x24,
|
||||
0xbc, 0x2f, 0x01, 0xe1, 0xf1, 0x28, 0xa2, 0x3c, 0x24, 0x8a, 0x2e, 0xc7, 0xac, 0x38, 0x1e, 0xe9,
|
||||
0x20, 0x73, 0x4b, 0xf8, 0x07, 0x9c, 0x86, 0x2b, 0x61, 0x1d, 0x62, 0x8e, 0x5e, 0xf6, 0x75, 0x46,
|
||||
0x9d, 0xf3, 0x7e, 0x06, 0x66, 0x9a, 0x7a, 0x40, 0x95, 0x42, 0xe5, 0xf3, 0x00, 0xfe, 0xca, 0x21,
|
||||
0x8b, 0x6b, 0x87, 0x2a, 0x9e, 0x22, 0x28, 0x0f, 0x55, 0x8c, 0x61, 0x5c, 0xdf, 0x3f, 0x76, 0xfb,
|
||||
0x4f, 0xf1, 0xf1, 0x0d, 0xde, 0x63, 0xd5, 0x1d, 0x13, 0xc4, 0x6c, 0x9f, 0x74, 0x57, 0x31, 0x0f,
|
||||
0xa0, 0xe2, 0xe8, 0x10, 0xb9, 0x03, 0x0d, 0x3c, 0x48, 0x8a, 0x7d, 0x6d, 0xe1, 0xbe, 0xb6, 0xf5,
|
||||
0x93, 0x26, 0xee, 0xac, 0x4e, 0xa4, 0xdf, 0xe8, 0xcd, 0xe7, 0x92, 0xf6, 0xdc, 0xc1, 0x40, 0x5c,
|
||||
0x84, 0xb6, 0xf9, 0xa1, 0x58, 0x01, 0xcc, 0xaa, 0x8a, 0x05, 0xe3, 0x04, 0x0b, 0x48, 0x60, 0x60,
|
||||
0xe4, 0x3a, 0xd4, 0xd8, 0x21, 0x67, 0xec, 0x7a, 0x03, 0xcc, 0xfa, 0xe3, 0x67, 0x2d, 0x85, 0xb1,
|
||||
0x36, 0xe4, 0xff, 0x78, 0x61, 0xb9, 0x88, 0xab, 0x62, 0x60, 0x6c, 0x6d, 0x54, 0x19, 0x85, 0x69,
|
||||
0x89, 0xef, 0xa8, 0x01, 0x92, 0xb7, 0xf0, 0x3a, 0x2a, 0xa1, 0x9d, 0x65, 0x0c, 0x77, 0xbd, 0x22,
|
||||
0xe6, 0x2c, 0x98, 0x56, 0xfe, 0x3d, 0x62, 0x24, 0x0e, 0xa7, 0xb4, 0xb7, 0xa0, 0xa9, 0xc3, 0xa4,
|
||||
0x06, 0x95, 0x87, 0x87, 0xbb, 0x07, 0xed, 0x2b, 0xa4, 0x01, 0xb3, 0x47, 0xbb, 0x8f, 0x1e, 0xed,
|
||||
0xef, 0xee, 0xb4, 0x2d, 0xd2, 0x84, 0x9a, 0x4a, 0xcd, 0x2a, 0xb1, 0xd2, 0xd6, 0xf6, 0xf6, 0xee,
|
||||
0xe1, 0xa3, 0xdd, 0x9d, 0x76, 0xd9, 0x4e, 0x80, 0x6c, 0x0d, 0x06, 0xa2, 0x15, 0x75, 0xd4, 0x4f,
|
||||
0xf9, 0xd9, 0x32, 0xf8, 0xb9, 0x80, 0xa7, 0x4a, 0xc5, 0x3c, 0xf5, 0xc2, 0x95, 0xb7, 0x77, 0xa1,
|
||||
0x71, 0xa8, 0x3d, 0x54, 0x41, 0xf1, 0x92, 0x4f, 0x54, 0x84, 0x58, 0x6a, 0x88, 0x36, 0x9c, 0x92,
|
||||
0x3e, 0x1c, 0xfb, 0x77, 0x2c, 0x9e, 0x3c, 0xaf, 0x86, 0xcf, 0xfb, 0xb6, 0xa1, 0xa9, 0x62, 0x4e,
|
||||
0x69, 0xd6, 0xa5, 0x81, 0x31, 0x1a, 0x1c, 0x4a, 0x2f, 0x3c, 0x39, 0x89, 0xa9, 0xcc, 0x91, 0x32,
|
||||
0x30, 0x26, 0x17, 0xcc, 0xc3, 0x62, 0xde, 0x8a, 0xc7, 0x7b, 0x88, 0x45, 0xae, 0x54, 0x0e, 0x67,
|
||||
0x5a, 0x5e, 0x84, 0x55, 0x64, 0x76, 0x98, 0x2a, 0xab, 0xe4, 0xd0, 0xec, 0x2a, 0x6f, 0x40, 0x4d,
|
||||
0xb5, 0x6b, 0x2a, 0x30, 0x49, 0xa9, 0xea, 0x99, 0xa2, 0xc4, 0x33, 0x87, 0x31, 0x68, 0xae, 0xb4,
|
||||
0xf3, 0x15, 0xe4, 0x16, 0x90, 0x13, 0x2f, 0xca, 0x92, 0x97, 0x91, 0xbc, 0xa0, 0xc6, 0x7e, 0x02,
|
||||
0x8b, 0x92, 0x91, 0x34, 0xd7, 0xca, 0xdc, 0x44, 0xeb, 0x32, 0xf1, 0x29, 0xe5, 0xc5, 0xc7, 0xfe,
|
||||
0x0f, 0x0b, 0x66, 0xc5, 0x4e, 0xe7, 0x1e, 0x3b, 0xf1, 0x7d, 0x36, 0x30, 0xd2, 0x31, 0xde, 0x85,
|
||||
0xa0, 0xac, 0x09, 0xa5, 0x99, 0x53, 0x8b, 0xe5, 0x22, 0xb5, 0x48, 0xa0, 0x32, 0x76, 0x93, 0x53,
|
||||
0x3c, 0x6f, 0xd7, 0x1d, 0xfc, 0x9f, 0xb4, 0x79, 0x74, 0x88, 0xab, 0x60, 0x8c, 0x0c, 0x15, 0x3d,
|
||||
0xeb, 0xe2, 0xd6, 0x3e, 0xff, 0xac, 0xeb, 0x1a, 0xd4, 0x71, 0x00, 0xbd, 0x34, 0xf8, 0x93, 0x02,
|
||||
0x8c, 0x73, 0x79, 0x01, 0xe5, 0x5a, 0xa4, 0x68, 0xa7, 0x88, 0xbd, 0xcc, 0x77, 0x5e, 0x2c, 0x81,
|
||||
0xba, 0x4a, 0x16, 0xc9, 0xb8, 0x29, 0x9c, 0x72, 0x84, 0x18, 0x40, 0x96, 0x23, 0x04, 0xa9, 0xa3,
|
||||
0xea, 0xed, 0x2e, 0x74, 0x76, 0xa8, 0x4f, 0x13, 0xba, 0xe5, 0xfb, 0xd9, 0xf6, 0x5f, 0x81, 0xab,
|
||||
0x05, 0x75, 0xc2, 0x9b, 0xfe, 0x32, 0x2c, 0x6f, 0xf1, 0xc4, 0xc5, 0x1f, 0x57, 0x32, 0x8e, 0xdd,
|
||||
0x81, 0x95, 0x6c, 0x93, 0xa2, 0xb3, 0x7b, 0xb0, 0xb0, 0x43, 0x8f, 0x27, 0xc3, 0x7d, 0x7a, 0x96,
|
||||
0x76, 0x44, 0xa0, 0x12, 0x9f, 0x86, 0xe7, 0x42, 0x30, 0xf1, 0x7f, 0xf2, 0x2a, 0x80, 0xcf, 0x68,
|
||||
0x7a, 0xf1, 0x98, 0xf6, 0xe5, 0x53, 0x0c, 0x44, 0x8e, 0xc6, 0xb4, 0x6f, 0xbf, 0x0d, 0x44, 0x6f,
|
||||
0x47, 0xac, 0x17, 0xb3, 0x82, 0x93, 0xe3, 0x5e, 0x7c, 0x11, 0x27, 0x74, 0x24, 0xdf, 0x98, 0xe8,
|
||||
0x90, 0x7d, 0x13, 0x9a, 0x87, 0xee, 0x85, 0x43, 0xbf, 0x29, 0xde, 0xb8, 0xad, 0xc2, 0xec, 0xd8,
|
||||
0xbd, 0x60, 0x6a, 0x4a, 0x45, 0xa5, 0xb0, 0xda, 0xfe, 0xb7, 0x12, 0xcc, 0x70, 0x4a, 0xd6, 0xea,
|
||||
0x80, 0xc6, 0x89, 0x17, 0x20, 0x63, 0xc9, 0x56, 0x35, 0x28, 0xc7, 0xca, 0xa5, 0x02, 0x56, 0x16,
|
||||
0x67, 0x36, 0x99, 0xd6, 0x2e, 0xf8, 0xd5, 0xc0, 0x18, 0x73, 0xa5, 0x59, 0x71, 0x3c, 0x2c, 0x92,
|
||||
0x02, 0x99, 0x00, 0x66, 0x6a, 0x6b, 0xf9, 0xf8, 0xa4, 0x94, 0x0a, 0xce, 0xd5, 0xa1, 0x42, 0x8b,
|
||||
0x3e, 0xcb, 0x19, 0x3c, 0x67, 0xd1, 0x73, 0x96, 0xbb, 0xf6, 0x12, 0x96, 0x9b, 0x1f, 0xe4, 0x5e,
|
||||
0x64, 0xb9, 0xe1, 0x25, 0x2c, 0xb7, 0x4d, 0xa0, 0x7d, 0x8f, 0x52, 0x87, 0x32, 0xdf, 0x50, 0xf2,
|
||||
0xee, 0xb7, 0x2d, 0x68, 0x0b, 0x2e, 0x52, 0x75, 0xe4, 0x75, 0xc3, 0x07, 0x2e, 0x4c, 0x2f, 0xbf,
|
||||
0x01, 0x73, 0xe8, 0x99, 0xaa, 0x48, 0xad, 0x08, 0x2b, 0x1b, 0x20, 0x9b, 0x87, 0xbc, 0x05, 0x1e,
|
||||
0x79, 0xbe, 0xd8, 0x14, 0x1d, 0x92, 0xc1, 0xde, 0xc8, 0x15, 0xd9, 0x61, 0x96, 0xa3, 0xca, 0xf6,
|
||||
0x1f, 0x5b, 0xb0, 0xa0, 0x0d, 0x58, 0x70, 0xe1, 0x7b, 0x20, 0xa5, 0x81, 0x87, 0x6d, 0xb9, 0xe4,
|
||||
0xae, 0x9a, 0x62, 0x93, 0x7e, 0x66, 0x10, 0xe3, 0x66, 0xba, 0x17, 0x38, 0xc0, 0x78, 0x32, 0x12,
|
||||
0x4a, 0x54, 0x87, 0x18, 0x23, 0x9d, 0x53, 0xfa, 0x54, 0x91, 0x70, 0x35, 0x6e, 0x60, 0x18, 0x1b,
|
||||
0x63, 0x1e, 0xb5, 0x22, 0xaa, 0x88, 0xd8, 0x98, 0x0e, 0xda, 0x7f, 0x6b, 0xc1, 0x22, 0x3f, 0x1a,
|
||||
0x89, 0x83, 0xa7, 0x7a, 0x19, 0x34, 0xc3, 0xcf, 0x82, 0x5c, 0x22, 0xf7, 0xae, 0x38, 0xa2, 0x4c,
|
||||
0x3e, 0xfb, 0x92, 0xc7, 0x39, 0x95, 0xb2, 0x36, 0x65, 0x2f, 0xca, 0x45, 0x7b, 0xf1, 0x82, 0x95,
|
||||
0x2e, 0x0a, 0x53, 0x56, 0x0b, 0xc3, 0x94, 0x77, 0x67, 0xa1, 0x1a, 0xf7, 0xc3, 0x31, 0xb5, 0x57,
|
||||
0x60, 0xc9, 0x9c, 0x9c, 0x50, 0x41, 0xdf, 0xb5, 0xa0, 0x73, 0x8f, 0x87, 0xf3, 0xbd, 0x60, 0xb8,
|
||||
0xe7, 0xc5, 0x49, 0x18, 0xa9, 0x07, 0x94, 0xd7, 0x01, 0xe2, 0xc4, 0x8d, 0x12, 0x9e, 0x98, 0x2c,
|
||||
0xc2, 0x83, 0x29, 0xc2, 0xc6, 0x48, 0x83, 0x01, 0xaf, 0xe5, 0x7b, 0xa3, 0xca, 0x39, 0x1f, 0x42,
|
||||
0x1c, 0xde, 0x0c, 0x4b, 0xfc, 0x06, 0x4f, 0xe1, 0x64, 0xbe, 0x02, 0x3d, 0x43, 0xbd, 0xce, 0x4f,
|
||||
0x45, 0x19, 0xd4, 0xfe, 0x6b, 0x0b, 0xe6, 0xd3, 0x41, 0xe2, 0xe5, 0xa6, 0xa9, 0x1d, 0x84, 0xf9,
|
||||
0x4d, 0xb5, 0x83, 0x0c, 0x5c, 0x7a, 0xcc, 0x1e, 0x8b, 0xb1, 0x69, 0x08, 0x4a, 0xac, 0x28, 0x85,
|
||||
0x13, 0xe9, 0xe0, 0xe8, 0x10, 0x4f, 0xc8, 0x62, 0x9e, 0x80, 0xf0, 0x6a, 0x44, 0x09, 0xf3, 0xca,
|
||||
0x47, 0x09, 0x7e, 0xc5, 0x43, 0xac, 0xb2, 0x28, 0x4d, 0xe9, 0x2c, 0xa2, 0x68, 0x4a, 0xf5, 0xab,
|
||||
0x91, 0x1a, 0x5f, 0x1f, 0x59, 0xb6, 0x7f, 0xc9, 0x82, 0xab, 0x05, 0x0b, 0x2f, 0xa4, 0x66, 0x07,
|
||||
0x16, 0x4e, 0x54, 0xa5, 0x5c, 0x1c, 0x2e, 0x3a, 0x2b, 0xf2, 0xea, 0xcd, 0x5c, 0x10, 0x27, 0xff,
|
||||
0x81, 0xf2, 0x8b, 0xf8, 0x72, 0x1b, 0x29, 0x8f, 0xf9, 0x8a, 0x8d, 0xe7, 0xd0, 0xd0, 0x9e, 0x2e,
|
||||
0x92, 0x55, 0x58, 0x7c, 0xf2, 0xe0, 0xd1, 0xc1, 0xee, 0xd1, 0x51, 0xef, 0xf0, 0xf1, 0xdd, 0x2f,
|
||||
0xed, 0x7e, 0xb5, 0xb7, 0xb7, 0x75, 0xb4, 0xd7, 0xbe, 0x42, 0x56, 0x80, 0x1c, 0xec, 0x1e, 0x3d,
|
||||
0xda, 0xdd, 0x31, 0x70, 0x8b, 0x5c, 0x87, 0xee, 0xe3, 0x83, 0xc7, 0x47, 0xbb, 0x3b, 0xbd, 0xa2,
|
||||
0xef, 0x4a, 0xe4, 0x55, 0xb8, 0x2a, 0xea, 0x0b, 0x3e, 0x2f, 0xdf, 0xf9, 0xe5, 0x32, 0xb4, 0xf8,
|
||||
0xad, 0x30, 0xff, 0xad, 0x0c, 0x1a, 0x91, 0xf7, 0x61, 0x56, 0xfc, 0xd6, 0x09, 0x59, 0x16, 0xb3,
|
||||
0x36, 0x7f, 0x5d, 0xa5, 0xbb, 0x92, 0x85, 0x05, 0x5b, 0x2f, 0xfe, 0xd4, 0x0f, 0xfe, 0xf1, 0x57,
|
||||
0x4b, 0x73, 0xa4, 0xb1, 0x79, 0xf6, 0xd6, 0xe6, 0x90, 0x06, 0x31, 0x6b, 0xe3, 0xeb, 0x00, 0xe9,
|
||||
0xaf, 0x80, 0x90, 0x8e, 0x72, 0x27, 0x33, 0x3f, 0x6f, 0xd2, 0xbd, 0x5a, 0x50, 0x23, 0xda, 0xbd,
|
||||
0x8a, 0xed, 0x2e, 0xda, 0x2d, 0xd6, 0xae, 0x17, 0x78, 0x09, 0xff, 0x49, 0x90, 0x77, 0xad, 0x0d,
|
||||
0x32, 0x80, 0xa6, 0xfe, 0x23, 0x1f, 0x44, 0xc6, 0xb4, 0x0a, 0x7e, 0x62, 0xa4, 0xfb, 0x4a, 0x61,
|
||||
0x9d, 0x0c, 0xe8, 0x61, 0x1f, 0xcb, 0x76, 0x9b, 0xf5, 0x31, 0x41, 0x8a, 0xb4, 0x17, 0x1f, 0x5a,
|
||||
0xe6, 0x6f, 0x79, 0x90, 0x6b, 0x9a, 0xc6, 0xc9, 0xfd, 0x92, 0x48, 0xf7, 0xd5, 0x29, 0xb5, 0xa2,
|
||||
0xaf, 0x57, 0xb1, 0xaf, 0x55, 0x9b, 0xb0, 0xbe, 0xfa, 0x48, 0x23, 0x7f, 0x49, 0xe4, 0x5d, 0x6b,
|
||||
0xe3, 0xce, 0x9f, 0xaf, 0x41, 0x5d, 0x45, 0xa1, 0xc9, 0x87, 0x30, 0x67, 0x5c, 0xdb, 0x13, 0x39,
|
||||
0x8d, 0xa2, 0x5b, 0xfe, 0xee, 0xb5, 0xe2, 0x4a, 0xd1, 0xf1, 0x75, 0xec, 0xb8, 0x43, 0x56, 0x58,
|
||||
0xc7, 0xe2, 0xde, 0x7b, 0x13, 0x13, 0x50, 0x78, 0x36, 0xf9, 0x53, 0x3e, 0xcf, 0xf4, 0xaa, 0xdd,
|
||||
0x98, 0x67, 0xee, 0x6a, 0xde, 0x98, 0x67, 0xfe, 0x7e, 0xde, 0xbe, 0x86, 0xdd, 0xad, 0x90, 0x25,
|
||||
0xbd, 0x3b, 0x15, 0x1d, 0xa6, 0xf8, 0x04, 0x42, 0xff, 0x19, 0x0c, 0xf2, 0xaa, 0x62, 0xac, 0xa2,
|
||||
0x9f, 0xc7, 0x50, 0x2c, 0x92, 0xff, 0x8d, 0x0c, 0xbb, 0x83, 0x5d, 0x11, 0x82, 0xdb, 0xa7, 0xff,
|
||||
0x0a, 0x06, 0xf9, 0x1a, 0xd4, 0xd5, 0xb3, 0x67, 0xb2, 0xaa, 0x3d, 0x43, 0xd7, 0x9f, 0x69, 0x77,
|
||||
0x3b, 0xf9, 0x8a, 0x22, 0xc6, 0xd0, 0x5b, 0x66, 0x8c, 0xf1, 0x04, 0x1a, 0xda, 0xd3, 0x66, 0x72,
|
||||
0x55, 0xdd, 0x21, 0x64, 0x9f, 0x4f, 0x77, 0xbb, 0x45, 0x55, 0xa2, 0x8b, 0x05, 0xec, 0xa2, 0x41,
|
||||
0xea, 0xc8, 0x7b, 0xc9, 0xb3, 0x30, 0x26, 0xfb, 0xb0, 0x2c, 0xce, 0x3d, 0xc7, 0xf4, 0xe3, 0x2c,
|
||||
0x51, 0xc1, 0xaf, 0x82, 0xdc, 0xb6, 0xc8, 0x7b, 0x50, 0x93, 0x2f, 0xd8, 0xc9, 0x4a, 0xf1, 0x4b,
|
||||
0xfc, 0xee, 0x6a, 0x0e, 0x17, 0x5a, 0xf1, 0xab, 0x00, 0xe9, 0x3b, 0x6a, 0x25, 0xc0, 0xb9, 0x77,
|
||||
0xd9, 0x6a, 0x77, 0xf2, 0x8f, 0xae, 0xed, 0x15, 0x9c, 0x60, 0x9b, 0xa0, 0x00, 0x07, 0xf4, 0x5c,
|
||||
0x3e, 0x0a, 0xfa, 0x06, 0x34, 0xb4, 0xa7, 0xd4, 0x6a, 0xf9, 0xf2, 0xcf, 0xb0, 0xd5, 0xf2, 0x15,
|
||||
0xbc, 0xbc, 0xb6, 0xbb, 0xd8, 0xfa, 0x92, 0x3d, 0xcf, 0x5a, 0x8f, 0xbd, 0x61, 0x30, 0xe2, 0x04,
|
||||
0x6c, 0x83, 0x4e, 0x61, 0xce, 0x78, 0x2f, 0xad, 0xa4, 0xa7, 0xe8, 0x35, 0xb6, 0x92, 0x9e, 0xc2,
|
||||
0x27, 0xd6, 0x92, 0x9d, 0xed, 0x05, 0xd6, 0xcf, 0x19, 0x92, 0x68, 0x3d, 0x7d, 0x00, 0x0d, 0xed,
|
||||
0xed, 0xb3, 0x9a, 0x4b, 0xfe, 0x99, 0xb5, 0x9a, 0x4b, 0xd1, 0x53, 0xe9, 0x25, 0xec, 0xa3, 0x65,
|
||||
0x23, 0x2b, 0xe0, 0x9b, 0x1a, 0xd6, 0xf6, 0x87, 0xd0, 0x32, 0x5f, 0x43, 0x2b, 0xb9, 0x2c, 0x7c,
|
||||
0x57, 0xad, 0xe4, 0x72, 0xca, 0x13, 0x6a, 0xc1, 0xd2, 0x1b, 0x8b, 0xaa, 0x93, 0xcd, 0x8f, 0xc4,
|
||||
0xcd, 0xf1, 0x73, 0xf2, 0x65, 0xa6, 0x7c, 0xc4, 0x23, 0x27, 0xb2, 0xaa, 0x71, 0xad, 0xfe, 0x14,
|
||||
0x4a, 0xc9, 0x4b, 0xee, 0x3d, 0x94, 0xc9, 0xcc, 0xfc, 0x55, 0x10, 0x5a, 0x14, 0x7c, 0xec, 0xa4,
|
||||
0x59, 0x14, 0xfd, 0x3d, 0x94, 0x66, 0x51, 0x8c, 0x37, 0x51, 0x59, 0x8b, 0x92, 0x78, 0xac, 0x8d,
|
||||
0x00, 0xe6, 0x33, 0x69, 0x7f, 0x4a, 0x2a, 0x8a, 0xf3, 0xa4, 0xbb, 0xd7, 0x5f, 0x9c, 0x2d, 0x68,
|
||||
0x2a, 0x2a, 0xa9, 0xa0, 0x36, 0x65, 0x56, 0xfa, 0xff, 0x87, 0xa6, 0xfe, 0x4e, 0x95, 0xe8, 0xa2,
|
||||
0x9c, 0xed, 0xe9, 0x95, 0xc2, 0x3a, 0x73, 0x73, 0x49, 0x53, 0xef, 0x86, 0x7c, 0x05, 0x56, 0x94,
|
||||
0xa8, 0xeb, 0x99, 0x64, 0x31, 0x79, 0xad, 0x20, 0xbf, 0x4c, 0x8f, 0x86, 0x74, 0xaf, 0x4e, 0x4d,
|
||||
0x40, 0xbb, 0x6d, 0x31, 0xa6, 0x31, 0x1f, 0x00, 0xa6, 0xca, 0xbc, 0xe8, 0xdd, 0x63, 0xaa, 0xcc,
|
||||
0x0b, 0x5f, 0x0d, 0x4a, 0xa6, 0x21, 0x8b, 0xc6, 0x1a, 0xf1, 0x6b, 0x01, 0xf2, 0x01, 0xcc, 0x6b,
|
||||
0xb9, 0xba, 0x47, 0x17, 0x41, 0x5f, 0x09, 0x40, 0xfe, 0x51, 0x47, 0xb7, 0xc8, 0x5d, 0xb7, 0x57,
|
||||
0xb1, 0xfd, 0x05, 0xdb, 0x58, 0x1c, 0xc6, 0xfc, 0xdb, 0xd0, 0xd0, 0xf3, 0x80, 0x5f, 0xd0, 0xee,
|
||||
0xaa, 0x56, 0xa5, 0xbf, 0x49, 0xb8, 0x6d, 0x91, 0xdf, 0xb0, 0xa0, 0x69, 0x64, 0xd5, 0x1a, 0x97,
|
||||
0x5f, 0x99, 0x76, 0x3a, 0x7a, 0x9d, 0xde, 0x90, 0xed, 0xe0, 0x20, 0xf7, 0x37, 0xbe, 0x68, 0x2c,
|
||||
0xc2, 0x47, 0xc6, 0xb1, 0xef, 0x56, 0xf6, 0x67, 0x60, 0x9e, 0x67, 0x09, 0xf4, 0x87, 0x2f, 0xcf,
|
||||
0x6f, 0x5b, 0xe4, 0x7b, 0x16, 0xb4, 0xcc, 0x60, 0x85, 0xda, 0xaa, 0xc2, 0xb0, 0x88, 0xda, 0xaa,
|
||||
0x29, 0x11, 0x8e, 0x0f, 0x70, 0x94, 0x8f, 0x36, 0x1c, 0x63, 0x94, 0xe2, 0x69, 0xe8, 0x8f, 0x36,
|
||||
0x5a, 0xf2, 0x2e, 0xff, 0x29, 0x28, 0x19, 0x41, 0x23, 0x9a, 0xd5, 0xc8, 0x6e, 0xaf, 0xfe, 0xeb,
|
||||
0x46, 0xeb, 0xd6, 0x6d, 0x8b, 0x7c, 0x83, 0xff, 0x5a, 0x8c, 0xf8, 0x16, 0xb9, 0xe4, 0x65, 0xbf,
|
||||
0xb7, 0x6f, 0xe0, 0x9c, 0xae, 0xdb, 0x57, 0x8d, 0x39, 0x65, 0xed, 0xf1, 0x16, 0x1f, 0x9d, 0xf8,
|
||||
0x61, 0xa2, 0xd4, 0xa0, 0xe4, 0x7e, 0xac, 0x68, 0xfa, 0x20, 0x47, 0x7c, 0x90, 0x82, 0xdc, 0x60,
|
||||
0xe5, 0x97, 0x6c, 0xc6, 0xde, 0xc0, 0xb1, 0xde, 0xb0, 0x5f, 0x9b, 0x3a, 0xd6, 0x4d, 0x0c, 0x39,
|
||||
0xb0, 0x11, 0x1f, 0x02, 0xa4, 0xd1, 0x6e, 0x92, 0x89, 0xb6, 0x2a, 0x01, 0xcf, 0x07, 0xc4, 0x4d,
|
||||
0x79, 0x91, 0x41, 0x59, 0xd6, 0xe2, 0xd7, 0xb8, 0xba, 0x7a, 0x20, 0xe3, 0xb4, 0xba, 0x53, 0x62,
|
||||
0x86, 0xa5, 0x0d, 0xa7, 0x24, 0xdb, 0xbe, 0xa1, 0xac, 0x54, 0xd0, 0xf7, 0x31, 0xcc, 0xed, 0x87,
|
||||
0xe1, 0xd3, 0xc9, 0x58, 0xdd, 0x5c, 0x99, 0xd1, 0xc0, 0x3d, 0x37, 0x3e, 0xed, 0x66, 0x66, 0x61,
|
||||
0xaf, 0x61, 0x53, 0x5d, 0xd2, 0xd1, 0x9a, 0xda, 0xfc, 0x28, 0x8d, 0xa6, 0x3f, 0x27, 0x2e, 0x2c,
|
||||
0x28, 0x1d, 0xa8, 0x06, 0xde, 0x35, 0x9b, 0x31, 0x34, 0x5f, 0xb6, 0x0b, 0xc3, 0xb3, 0x95, 0xa3,
|
||||
0xdd, 0x8c, 0x65, 0x9b, 0xb7, 0x2d, 0x72, 0x08, 0xcd, 0x1d, 0xda, 0x0f, 0x07, 0x54, 0x84, 0xd4,
|
||||
0x16, 0xd3, 0x81, 0xab, 0x58, 0x5c, 0x77, 0xce, 0x00, 0x4d, 0xbb, 0x30, 0x76, 0x2f, 0x22, 0xfa,
|
||||
0xcd, 0xcd, 0x8f, 0x44, 0xb0, 0xee, 0xb9, 0xb4, 0x0b, 0x32, 0x9a, 0x69, 0xd8, 0x85, 0x4c, 0xf8,
|
||||
0xd3, 0xb0, 0x0b, 0xb9, 0xf0, 0xa7, 0xb1, 0xd4, 0x32, 0x9a, 0x4a, 0x7c, 0x58, 0xc8, 0x45, 0x4c,
|
||||
0x95, 0x49, 0x98, 0x16, 0x67, 0xed, 0xae, 0x4d, 0x27, 0x30, 0x7b, 0xdb, 0x30, 0x7b, 0x3b, 0x82,
|
||||
0xb9, 0x1d, 0xca, 0x17, 0x8b, 0xa7, 0xc7, 0x64, 0x52, 0xb3, 0xf5, 0xe4, 0x9b, 0xac, 0x02, 0xc7,
|
||||
0x3a, 0xd3, 0xf0, 0x63, 0x6e, 0x0a, 0xf9, 0x1a, 0x34, 0xee, 0xd3, 0x44, 0xe6, 0xc3, 0x28, 0xd7,
|
||||
0x33, 0x93, 0x20, 0xd3, 0x2d, 0x48, 0xa7, 0x31, 0x79, 0x06, 0x5b, 0xdb, 0xa4, 0x83, 0x21, 0xe5,
|
||||
0xca, 0xa9, 0xe7, 0x0d, 0x9e, 0x93, 0xff, 0x87, 0x8d, 0xab, 0xb4, 0xbd, 0x15, 0x2d, 0x8d, 0x42,
|
||||
0x6f, 0x7c, 0x3e, 0x83, 0x17, 0xb5, 0x1c, 0x84, 0x03, 0xaa, 0xb9, 0x40, 0x01, 0x34, 0xb4, 0x6c,
|
||||
0x53, 0x25, 0x40, 0xf9, 0xe4, 0x60, 0x25, 0x40, 0x05, 0xc9, 0xa9, 0xf6, 0x3a, 0xf6, 0x63, 0x93,
|
||||
0xb5, 0xb4, 0x1f, 0x9e, 0x90, 0x9a, 0xf6, 0xb4, 0xf9, 0x91, 0x3b, 0x4a, 0x9e, 0x93, 0x27, 0xf8,
|
||||
0x3e, 0x5c, 0xcf, 0xf9, 0x49, 0x7d, 0xe9, 0x6c, 0x7a, 0x90, 0x5a, 0x2c, 0xad, 0xca, 0xf4, 0xaf,
|
||||
0x79, 0x57, 0xe8, 0x29, 0x7d, 0x16, 0xe0, 0x28, 0x09, 0xc7, 0x3b, 0x2e, 0x1d, 0x85, 0x41, 0xaa,
|
||||
0x6b, 0xd3, 0xbc, 0x96, 0x54, 0x7f, 0x69, 0xc9, 0x2d, 0xe4, 0x89, 0x76, 0xf8, 0x30, 0x52, 0xa6,
|
||||
0x24, 0x73, 0x4d, 0x4d, 0x7d, 0x51, 0x0b, 0x52, 0x90, 0xfe, 0x72, 0xdb, 0x22, 0x5b, 0x00, 0x69,
|
||||
0xc8, 0x5c, 0x1d, 0x25, 0x72, 0xd1, 0x78, 0xa5, 0xf6, 0x0a, 0xe2, 0xeb, 0x87, 0x50, 0x4f, 0x63,
|
||||
0xb0, 0xab, 0x69, 0x42, 0xb4, 0x11, 0xb1, 0x55, 0x16, 0x3c, 0x17, 0x19, 0xb5, 0xdb, 0xb8, 0x54,
|
||||
0x40, 0x6a, 0x6c, 0xa9, 0x30, 0xdc, 0xe9, 0xc1, 0x22, 0x1f, 0xa0, 0x72, 0x47, 0x30, 0x53, 0x43,
|
||||
0xce, 0xa4, 0x20, 0x3a, 0xa9, 0xa4, 0xb9, 0x30, 0xb8, 0x67, 0x44, 0x2b, 0x18, 0xb7, 0xf2, 0x2c,
|
||||
0x11, 0xa6, 0x9a, 0x47, 0xb0, 0x90, 0x8b, 0x3e, 0x29, 0x91, 0x9e, 0x16, 0x10, 0x54, 0x22, 0x3d,
|
||||
0x35, 0x70, 0x65, 0x2f, 0x63, 0x97, 0xf3, 0x36, 0xe0, 0x09, 0xe8, 0xdc, 0x4b, 0xfa, 0xa7, 0xef,
|
||||
0x5a, 0x1b, 0x77, 0x6f, 0x7e, 0xf0, 0x3f, 0x86, 0x5e, 0x72, 0x3a, 0x39, 0xbe, 0xd5, 0x0f, 0x47,
|
||||
0x9b, 0xbe, 0x0c, 0x29, 0x88, 0x7c, 0xab, 0x4d, 0x3f, 0x18, 0x6c, 0x62, 0xcb, 0xc7, 0x33, 0xf8,
|
||||
0x3b, 0xba, 0x9f, 0xfe, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xc6, 0x71, 0x9a, 0x79, 0x57,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
@ -1892,6 +1892,7 @@ message Invoice {
|
||||
OPEN = 0;
|
||||
SETTLED = 1;
|
||||
CANCELED = 2;
|
||||
ACCEPTED = 3;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1162,7 +1162,8 @@
|
||||
"enum": [
|
||||
"OPEN",
|
||||
"SETTLED",
|
||||
"CANCELED"
|
||||
"CANCELED",
|
||||
"ACCEPTED"
|
||||
],
|
||||
"default": "OPEN"
|
||||
},
|
||||
|
@ -17,33 +17,33 @@ func (hash Hash) String() string {
|
||||
return hex.EncodeToString(hash[:])
|
||||
}
|
||||
|
||||
// NewHash returns a new Hash from a byte slice. An error is returned if
|
||||
// MakeHash returns a new Hash from a byte slice. An error is returned if
|
||||
// the number of bytes passed in is not HashSize.
|
||||
func NewHash(newHash []byte) (*Hash, error) {
|
||||
func MakeHash(newHash []byte) (Hash, error) {
|
||||
nhlen := len(newHash)
|
||||
if nhlen != HashSize {
|
||||
return nil, fmt.Errorf("invalid hash length of %v, want %v",
|
||||
return Hash{}, fmt.Errorf("invalid hash length of %v, want %v",
|
||||
nhlen, HashSize)
|
||||
}
|
||||
|
||||
var hash Hash
|
||||
copy(hash[:], newHash)
|
||||
|
||||
return &hash, nil
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
// NewHashFromStr creates a Hash from a hex hash string.
|
||||
func NewHashFromStr(newHash string) (*Hash, error) {
|
||||
// MakeHashFromStr creates a Hash from a hex hash string.
|
||||
func MakeHashFromStr(newHash string) (Hash, error) {
|
||||
// Return error if hash string is of incorrect length.
|
||||
if len(newHash) != HashSize*2 {
|
||||
return nil, fmt.Errorf("invalid hash string length of %v, "+
|
||||
return Hash{}, fmt.Errorf("invalid hash string length of %v, "+
|
||||
"want %v", len(newHash), HashSize*2)
|
||||
}
|
||||
|
||||
hash, err := hex.DecodeString(newHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Hash{}, err
|
||||
}
|
||||
|
||||
return NewHash(hash)
|
||||
return MakeHash(hash)
|
||||
}
|
||||
|
@ -53,3 +53,8 @@ func MakePreimageFromStr(newPreimage string) (Preimage, error) {
|
||||
func (p *Preimage) Hash() Hash {
|
||||
return Hash(sha256.Sum256(p[:]))
|
||||
}
|
||||
|
||||
// Matches returns whether this preimage is the preimage of the given hash.
|
||||
func (p *Preimage) Matches(h Hash) bool {
|
||||
return h == p.Hash()
|
||||
}
|
||||
|
@ -409,6 +409,11 @@ func (f FailFinalExpiryTooSoon) Error() string {
|
||||
return f.Code().String()
|
||||
}
|
||||
|
||||
// NewFinalExpiryTooSoon creates new instance of the FailFinalExpiryTooSoon.
|
||||
func NewFinalExpiryTooSoon() *FailFinalExpiryTooSoon {
|
||||
return &FailFinalExpiryTooSoon{}
|
||||
}
|
||||
|
||||
// FailInvalidOnionVersion is returned if the onion version byte is unknown.
|
||||
//
|
||||
// NOTE: May be returned only by intermediate nodes.
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/coreos/bbolt"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -152,7 +153,7 @@ func (m *missionControl) GraphPruneView() graphPruneView {
|
||||
// view from Mission Control. An optional set of routing hints can be provided
|
||||
// in order to populate additional edges to explore when finding a path to the
|
||||
// payment's destination.
|
||||
func (m *missionControl) NewPaymentSession(routeHints [][]HopHint,
|
||||
func (m *missionControl) NewPaymentSession(routeHints [][]zpay32.HopHint,
|
||||
target Vertex) (*paymentSession, error) {
|
||||
|
||||
viewSnapshot := m.GraphPruneView()
|
||||
|
@ -39,28 +39,6 @@ const (
|
||||
RiskFactorBillionths = 15
|
||||
)
|
||||
|
||||
// HopHint is a routing hint that contains the minimum information of a channel
|
||||
// required for an intermediate hop in a route to forward the payment to the
|
||||
// next. This should be ideally used for private channels, since they are not
|
||||
// publicly advertised to the network for routing.
|
||||
type HopHint struct {
|
||||
// NodeID is the public key of the node at the start of the channel.
|
||||
NodeID *btcec.PublicKey
|
||||
|
||||
// ChannelID is the unique identifier of the channel.
|
||||
ChannelID uint64
|
||||
|
||||
// FeeBaseMSat is the base fee of the channel in millisatoshis.
|
||||
FeeBaseMSat uint32
|
||||
|
||||
// FeeProportionalMillionths is the fee rate, in millionths of a
|
||||
// satoshi, for every satoshi sent through the channel.
|
||||
FeeProportionalMillionths uint32
|
||||
|
||||
// CLTVExpiryDelta is the time-lock delta of the channel.
|
||||
CLTVExpiryDelta uint16
|
||||
}
|
||||
|
||||
// Hop represents an intermediate or final node of the route. This naming
|
||||
// is in line with the definition given in BOLT #4: Onion Routing Protocol.
|
||||
// The struct houses the channel along which this hop can be reached and
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -1746,11 +1747,11 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
// The CLTV expiry should be the current height plus 9 (the expiry for
|
||||
// the B -> C channel.
|
||||
if firstRoute.TotalTimeLock !=
|
||||
startingHeight+DefaultFinalCLTVDelta {
|
||||
startingHeight+zpay32.DefaultFinalCLTVDelta {
|
||||
|
||||
t.Fatalf("wrong total time lock: got %v, expecting %v",
|
||||
firstRoute.TotalTimeLock,
|
||||
startingHeight+DefaultFinalCLTVDelta)
|
||||
startingHeight+zpay32.DefaultFinalCLTVDelta)
|
||||
}
|
||||
|
||||
// Next, we'll set A as the source node so we can assert that we create
|
||||
@ -1845,11 +1846,11 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
// The outgoing CLTV value itself should be the current height plus 30
|
||||
// to meet Carol's requirements.
|
||||
if routes[0].Hops[0].OutgoingTimeLock !=
|
||||
startingHeight+DefaultFinalCLTVDelta {
|
||||
startingHeight+zpay32.DefaultFinalCLTVDelta {
|
||||
|
||||
t.Fatalf("wrong total time lock: got %v, expecting %v",
|
||||
routes[0].Hops[0].OutgoingTimeLock,
|
||||
startingHeight+DefaultFinalCLTVDelta)
|
||||
startingHeight+zpay32.DefaultFinalCLTVDelta)
|
||||
}
|
||||
|
||||
// For B -> C, we assert that the final hop also has the proper
|
||||
@ -1860,11 +1861,11 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
lastHop.AmtToForward, amt)
|
||||
}
|
||||
if lastHop.OutgoingTimeLock !=
|
||||
startingHeight+DefaultFinalCLTVDelta {
|
||||
startingHeight+zpay32.DefaultFinalCLTVDelta {
|
||||
|
||||
t.Fatalf("wrong total time lock: got %v, expecting %v",
|
||||
lastHop.OutgoingTimeLock,
|
||||
startingHeight+DefaultFinalCLTVDelta)
|
||||
startingHeight+zpay32.DefaultFinalCLTVDelta)
|
||||
}
|
||||
|
||||
// We'll also make similar assertions for the second route from A to C
|
||||
@ -1875,7 +1876,7 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
t.Fatalf("wrong amount: got %v, expected %v",
|
||||
secondRoute.TotalAmount, expectedAmt)
|
||||
}
|
||||
expectedTimeLock := startingHeight + daveFinalCLTV + DefaultFinalCLTVDelta
|
||||
expectedTimeLock := startingHeight + daveFinalCLTV + zpay32.DefaultFinalCLTVDelta
|
||||
if secondRoute.TotalTimeLock != uint32(expectedTimeLock) {
|
||||
t.Fatalf("wrong total time lock: got %v, expecting %v",
|
||||
secondRoute.TotalTimeLock, expectedTimeLock)
|
||||
@ -1885,7 +1886,7 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
t.Fatalf("wrong forward amount: got %v, expected %v",
|
||||
onionPayload.AmtToForward, amt)
|
||||
}
|
||||
expectedTimeLock = startingHeight + DefaultFinalCLTVDelta
|
||||
expectedTimeLock = startingHeight + zpay32.DefaultFinalCLTVDelta
|
||||
if onionPayload.OutgoingTimeLock != uint32(expectedTimeLock) {
|
||||
t.Fatalf("wrong outgoing time lock: got %v, expecting %v",
|
||||
onionPayload.OutgoingTimeLock,
|
||||
@ -1899,11 +1900,11 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
lastHop.AmtToForward, amt)
|
||||
}
|
||||
if lastHop.OutgoingTimeLock !=
|
||||
startingHeight+DefaultFinalCLTVDelta {
|
||||
startingHeight+zpay32.DefaultFinalCLTVDelta {
|
||||
|
||||
t.Fatalf("wrong total time lock: got %v, expecting %v",
|
||||
lastHop.OutgoingTimeLock,
|
||||
startingHeight+DefaultFinalCLTVDelta)
|
||||
startingHeight+zpay32.DefaultFinalCLTVDelta)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,13 +25,10 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/multimutex"
|
||||
"github.com/lightningnetwork/lnd/routing/chainview"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultFinalCLTVDelta is the default value to be used as the final
|
||||
// CLTV delta for a route if one is unspecified.
|
||||
DefaultFinalCLTVDelta = 9
|
||||
|
||||
// defaultPayAttemptTimeout is a duration that we'll use to determine
|
||||
// if we should give up on a payment attempt. This will be used if a
|
||||
// value isn't specified in the LightningNode struct.
|
||||
@ -1331,7 +1328,7 @@ func (r *ChannelRouter) FindRoutes(source, target Vertex,
|
||||
|
||||
var finalCLTVDelta uint16
|
||||
if len(finalExpiry) == 0 {
|
||||
finalCLTVDelta = DefaultFinalCLTVDelta
|
||||
finalCLTVDelta = zpay32.DefaultFinalCLTVDelta
|
||||
} else {
|
||||
finalCLTVDelta = finalExpiry[0]
|
||||
}
|
||||
@ -1551,7 +1548,7 @@ type LightningPayment struct {
|
||||
// multiple routes, ensure the hop hints within each route are chained
|
||||
// together and sorted in forward order in order to reach the
|
||||
// destination successfully.
|
||||
RouteHints [][]HopHint
|
||||
RouteHints [][]zpay32.HopHint
|
||||
|
||||
// OutgoingChannelID is the channel that needs to be taken to the first
|
||||
// hop. If nil, any channel may be used.
|
||||
@ -1628,7 +1625,7 @@ func (r *ChannelRouter) sendPayment(payment *LightningPayment,
|
||||
|
||||
var finalCLTVDelta uint16
|
||||
if payment.FinalCLTVDelta == nil {
|
||||
finalCLTVDelta = DefaultFinalCLTVDelta
|
||||
finalCLTVDelta = zpay32.DefaultFinalCLTVDelta
|
||||
} else {
|
||||
finalCLTVDelta = *payment.FinalCLTVDelta
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
// defaultNumRoutes is the default value for the maximum number of routes to
|
||||
@ -186,7 +187,7 @@ func TestFindRoutesFeeSorting(t *testing.T) {
|
||||
routes, err := ctx.router.FindRoutes(
|
||||
ctx.router.selfNode.PubKeyBytes,
|
||||
target, paymentAmt, noRestrictions, defaultNumRoutes,
|
||||
DefaultFinalCLTVDelta,
|
||||
zpay32.DefaultFinalCLTVDelta,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find any routes: %v", err)
|
||||
@ -248,7 +249,7 @@ func TestFindRoutesWithFeeLimit(t *testing.T) {
|
||||
routes, err := ctx.router.FindRoutes(
|
||||
ctx.router.selfNode.PubKeyBytes,
|
||||
target, paymentAmt, restrictions, defaultNumRoutes,
|
||||
DefaultFinalCLTVDelta,
|
||||
zpay32.DefaultFinalCLTVDelta,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find any routes: %v", err)
|
||||
@ -1345,7 +1346,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
||||
routes, err := ctx.router.FindRoutes(
|
||||
ctx.router.selfNode.PubKeyBytes,
|
||||
targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes,
|
||||
DefaultFinalCLTVDelta,
|
||||
zpay32.DefaultFinalCLTVDelta,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find any routes: %v", err)
|
||||
@ -1391,7 +1392,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
||||
routes, err = ctx.router.FindRoutes(
|
||||
ctx.router.selfNode.PubKeyBytes,
|
||||
targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes,
|
||||
DefaultFinalCLTVDelta,
|
||||
zpay32.DefaultFinalCLTVDelta,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find any routes: %v", err)
|
||||
|
333
rpcserver.go
333
rpcserver.go
@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"encoding/hex"
|
||||
@ -39,6 +38,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lncfg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
@ -422,7 +422,8 @@ func newRPCServer(s *server, macService *macaroons.Service,
|
||||
// server configuration struct.
|
||||
err := subServerCgs.PopulateDependencies(
|
||||
s.cc, networkDir, macService, atpl, invoiceRegistry,
|
||||
activeNetParams.Params, s.chanRouter,
|
||||
s.htlcSwitch, activeNetParams.Params, s.chanRouter,
|
||||
s.nodeSigner, s.chanDB,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -2796,7 +2797,7 @@ type rpcPaymentIntent struct {
|
||||
dest routing.Vertex
|
||||
rHash [32]byte
|
||||
cltvDelta uint16
|
||||
routeHints [][]routing.HopHint
|
||||
routeHints [][]zpay32.HopHint
|
||||
outgoingChannelID *uint64
|
||||
|
||||
routes []*routing.Route
|
||||
@ -3277,309 +3278,51 @@ func (r *rpcServer) sendPaymentSync(ctx context.Context,
|
||||
func (r *rpcServer) AddInvoice(ctx context.Context,
|
||||
invoice *lnrpc.Invoice) (*lnrpc.AddInvoiceResponse, error) {
|
||||
|
||||
var paymentPreimage [32]byte
|
||||
defaultDelta := cfg.Bitcoin.TimeLockDelta
|
||||
if registeredChains.PrimaryChain() == litecoinChain {
|
||||
defaultDelta = cfg.Litecoin.TimeLockDelta
|
||||
}
|
||||
|
||||
switch {
|
||||
// If a preimage wasn't specified, then we'll generate a new preimage
|
||||
// from fresh cryptographic randomness.
|
||||
case len(invoice.RPreimage) == 0:
|
||||
if _, err := rand.Read(paymentPreimage[:]); err != nil {
|
||||
addInvoiceCfg := &invoicesrpc.AddInvoiceConfig{
|
||||
AddInvoice: r.server.invoices.AddInvoice,
|
||||
IsChannelActive: r.server.htlcSwitch.HasActiveLink,
|
||||
ChainParams: activeNetParams.Params,
|
||||
NodeSigner: r.server.nodeSigner,
|
||||
MaxPaymentMSat: maxPaymentMSat,
|
||||
DefaultCLTVExpiry: defaultDelta,
|
||||
ChanDB: r.server.chanDB,
|
||||
}
|
||||
|
||||
addInvoiceData := &invoicesrpc.AddInvoiceData{
|
||||
Memo: invoice.Memo,
|
||||
Receipt: invoice.Receipt,
|
||||
Value: btcutil.Amount(invoice.Value),
|
||||
DescriptionHash: invoice.DescriptionHash,
|
||||
Expiry: invoice.Expiry,
|
||||
FallbackAddr: invoice.FallbackAddr,
|
||||
CltvExpiry: invoice.CltvExpiry,
|
||||
Private: invoice.Private,
|
||||
}
|
||||
|
||||
if invoice.RPreimage != nil {
|
||||
preimage, err := lntypes.MakePreimage(invoice.RPreimage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Otherwise, if a preimage was specified, then it MUST be exactly
|
||||
// 32-bytes.
|
||||
case len(invoice.RPreimage) > 0 && len(invoice.RPreimage) != 32:
|
||||
return nil, fmt.Errorf("payment preimage must be exactly "+
|
||||
"32 bytes, is instead %v", len(invoice.RPreimage))
|
||||
|
||||
// If the preimage meets the size specifications, then it can be used
|
||||
// as is.
|
||||
default:
|
||||
copy(paymentPreimage[:], invoice.RPreimage[:])
|
||||
addInvoiceData.Preimage = &preimage
|
||||
}
|
||||
|
||||
// The size of the memo, receipt and description hash attached must not
|
||||
// exceed the maximum values for either of the fields.
|
||||
if len(invoice.Memo) > channeldb.MaxMemoSize {
|
||||
return nil, fmt.Errorf("memo too large: %v bytes "+
|
||||
"(maxsize=%v)", len(invoice.Memo), channeldb.MaxMemoSize)
|
||||
}
|
||||
if len(invoice.Receipt) > channeldb.MaxReceiptSize {
|
||||
return nil, fmt.Errorf("receipt too large: %v bytes "+
|
||||
"(maxsize=%v)", len(invoice.Receipt), channeldb.MaxReceiptSize)
|
||||
}
|
||||
if len(invoice.DescriptionHash) > 0 && len(invoice.DescriptionHash) != 32 {
|
||||
return nil, fmt.Errorf("description hash is %v bytes, must be %v",
|
||||
len(invoice.DescriptionHash), channeldb.MaxPaymentRequestSize)
|
||||
}
|
||||
|
||||
// The value of the invoice must not be negative.
|
||||
if invoice.Value < 0 {
|
||||
return nil, fmt.Errorf("payments of negative value "+
|
||||
"are not allowed, value is %v", invoice.Value)
|
||||
}
|
||||
|
||||
amt := btcutil.Amount(invoice.Value)
|
||||
amtMSat := lnwire.NewMSatFromSatoshis(amt)
|
||||
|
||||
// The value of the invoice must also not exceed the current soft-limit
|
||||
// on the largest payment within the network.
|
||||
if amtMSat > maxPaymentMSat {
|
||||
return nil, fmt.Errorf("payment of %v is too large, max "+
|
||||
"payment allowed is %v", amt, maxPaymentMSat.ToSatoshis())
|
||||
}
|
||||
|
||||
// Next, generate the payment hash itself from the preimage. This will
|
||||
// be used by clients to query for the state of a particular invoice.
|
||||
rHash := sha256.Sum256(paymentPreimage[:])
|
||||
|
||||
// We also create an encoded payment request which allows the
|
||||
// caller to compactly send the invoice to the payer. We'll create a
|
||||
// list of options to be added to the encoded payment request. For now
|
||||
// we only support the required fields description/description_hash,
|
||||
// expiry, fallback address, and the amount field.
|
||||
var options []func(*zpay32.Invoice)
|
||||
|
||||
// We only include the amount in the invoice if it is greater than 0.
|
||||
// By not including the amount, we enable the creation of invoices that
|
||||
// allow the payee to specify the amount of satoshis they wish to send.
|
||||
if amtMSat > 0 {
|
||||
options = append(options, zpay32.Amount(amtMSat))
|
||||
}
|
||||
|
||||
// If specified, add a fallback address to the payment request.
|
||||
if len(invoice.FallbackAddr) > 0 {
|
||||
addr, err := btcutil.DecodeAddress(invoice.FallbackAddr,
|
||||
activeNetParams.Params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid fallback address: %v",
|
||||
err)
|
||||
}
|
||||
options = append(options, zpay32.FallbackAddr(addr))
|
||||
}
|
||||
|
||||
// If expiry is set, specify it. If it is not provided, no expiry time
|
||||
// will be explicitly added to this payment request, which will imply
|
||||
// the default 3600 seconds.
|
||||
if invoice.Expiry > 0 {
|
||||
|
||||
// We'll ensure that the specified expiry is restricted to sane
|
||||
// number of seconds. As a result, we'll reject an invoice with
|
||||
// an expiry greater than 1 year.
|
||||
maxExpiry := time.Hour * 24 * 365
|
||||
expSeconds := invoice.Expiry
|
||||
|
||||
if float64(expSeconds) > maxExpiry.Seconds() {
|
||||
return nil, fmt.Errorf("expiry of %v seconds "+
|
||||
"greater than max expiry of %v seconds",
|
||||
float64(expSeconds), maxExpiry.Seconds())
|
||||
}
|
||||
|
||||
expiry := time.Duration(invoice.Expiry) * time.Second
|
||||
options = append(options, zpay32.Expiry(expiry))
|
||||
}
|
||||
|
||||
// If the description hash is set, then we add it do the list of options.
|
||||
// If not, use the memo field as the payment request description.
|
||||
if len(invoice.DescriptionHash) > 0 {
|
||||
var descHash [32]byte
|
||||
copy(descHash[:], invoice.DescriptionHash[:])
|
||||
options = append(options, zpay32.DescriptionHash(descHash))
|
||||
} else {
|
||||
// Use the memo field as the description. If this is not set
|
||||
// this will just be an empty string.
|
||||
options = append(options, zpay32.Description(invoice.Memo))
|
||||
}
|
||||
|
||||
// We'll use our current default CLTV value unless one was specified as
|
||||
// an option on the command line when creating an invoice.
|
||||
switch {
|
||||
case invoice.CltvExpiry > math.MaxUint16:
|
||||
return nil, fmt.Errorf("CLTV delta of %v is too large, max "+
|
||||
"accepted is: %v", invoice.CltvExpiry, math.MaxUint16)
|
||||
case invoice.CltvExpiry != 0:
|
||||
options = append(options,
|
||||
zpay32.CLTVExpiry(invoice.CltvExpiry))
|
||||
default:
|
||||
// TODO(roasbeef): assumes set delta between versions
|
||||
defaultDelta := cfg.Bitcoin.TimeLockDelta
|
||||
if registeredChains.PrimaryChain() == litecoinChain {
|
||||
defaultDelta = cfg.Litecoin.TimeLockDelta
|
||||
}
|
||||
options = append(options, zpay32.CLTVExpiry(uint64(defaultDelta)))
|
||||
}
|
||||
|
||||
// If we were requested to include routing hints in the invoice, then
|
||||
// we'll fetch all of our available private channels and create routing
|
||||
// hints for them.
|
||||
if invoice.Private {
|
||||
openChannels, err := r.server.chanDB.FetchAllChannels()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not fetch all channels")
|
||||
}
|
||||
|
||||
graph := r.server.chanDB.ChannelGraph()
|
||||
|
||||
numHints := 0
|
||||
for _, channel := range openChannels {
|
||||
// We'll restrict the number of individual route hints
|
||||
// to 20 to avoid creating overly large invoices.
|
||||
if numHints > 20 {
|
||||
break
|
||||
}
|
||||
|
||||
// Since we're only interested in our private channels,
|
||||
// we'll skip public ones.
|
||||
isPublic := channel.ChannelFlags&lnwire.FFAnnounceChannel != 0
|
||||
if isPublic {
|
||||
continue
|
||||
}
|
||||
|
||||
// Make sure the counterparty has enough balance in the
|
||||
// channel for our amount. We do this in order to reduce
|
||||
// payment errors when attempting to use this channel
|
||||
// as a hint.
|
||||
chanPoint := lnwire.NewChanIDFromOutPoint(
|
||||
&channel.FundingOutpoint,
|
||||
)
|
||||
if amtMSat >= channel.LocalCommitment.RemoteBalance {
|
||||
rpcsLog.Debugf("Skipping channel %v due to "+
|
||||
"not having enough remote balance",
|
||||
chanPoint)
|
||||
continue
|
||||
}
|
||||
|
||||
// Make sure the channel is active.
|
||||
link, err := r.server.htlcSwitch.GetLink(chanPoint)
|
||||
if err != nil {
|
||||
rpcsLog.Errorf("Unable to get link for "+
|
||||
"channel %v: %v", chanPoint, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !link.EligibleToForward() {
|
||||
rpcsLog.Debugf("Skipping channel %v due to not "+
|
||||
"being eligible to forward payments",
|
||||
chanPoint)
|
||||
continue
|
||||
}
|
||||
|
||||
// To ensure we don't leak unadvertised nodes, we'll
|
||||
// make sure our counterparty is publicly advertised
|
||||
// within the network. Otherwise, we'll end up leaking
|
||||
// information about nodes that intend to stay
|
||||
// unadvertised, like in the case of a node only having
|
||||
// private channels.
|
||||
var remotePub [33]byte
|
||||
copy(remotePub[:], channel.IdentityPub.SerializeCompressed())
|
||||
isRemoteNodePublic, err := graph.IsPublicNode(remotePub)
|
||||
if err != nil {
|
||||
rpcsLog.Errorf("Unable to determine if node %x "+
|
||||
"is advertised: %v", remotePub, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !isRemoteNodePublic {
|
||||
rpcsLog.Debugf("Skipping channel %v due to "+
|
||||
"counterparty %x being unadvertised",
|
||||
chanPoint, remotePub)
|
||||
continue
|
||||
}
|
||||
|
||||
// Fetch the policies for each end of the channel.
|
||||
chanID := channel.ShortChanID().ToUint64()
|
||||
info, p1, p2, err := graph.FetchChannelEdgesByID(chanID)
|
||||
if err != nil {
|
||||
rpcsLog.Errorf("Unable to fetch the routing "+
|
||||
"policies for the edges of the channel "+
|
||||
"%v: %v", chanPoint, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Now, we'll need to determine which is the correct
|
||||
// policy for HTLCs being sent from the remote node.
|
||||
var remotePolicy *channeldb.ChannelEdgePolicy
|
||||
if bytes.Equal(remotePub[:], info.NodeKey1Bytes[:]) {
|
||||
remotePolicy = p1
|
||||
} else {
|
||||
remotePolicy = p2
|
||||
}
|
||||
|
||||
// If for some reason we don't yet have the edge for
|
||||
// the remote party, then we'll just skip adding this
|
||||
// channel as a routing hint.
|
||||
if remotePolicy == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Finally, create the routing hint for this channel and
|
||||
// add it to our list of route hints.
|
||||
hint := routing.HopHint{
|
||||
NodeID: channel.IdentityPub,
|
||||
ChannelID: chanID,
|
||||
FeeBaseMSat: uint32(remotePolicy.FeeBaseMSat),
|
||||
FeeProportionalMillionths: uint32(
|
||||
remotePolicy.FeeProportionalMillionths,
|
||||
),
|
||||
CLTVExpiryDelta: remotePolicy.TimeLockDelta,
|
||||
}
|
||||
|
||||
// Include the route hint in our set of options that
|
||||
// will be used when creating the invoice.
|
||||
routeHint := []routing.HopHint{hint}
|
||||
options = append(options, zpay32.RouteHint(routeHint))
|
||||
|
||||
numHints++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create and encode the payment request as a bech32 (zpay32) string.
|
||||
creationDate := time.Now()
|
||||
payReq, err := zpay32.NewInvoice(
|
||||
activeNetParams.Params, rHash, creationDate, options...,
|
||||
hash, dbInvoice, err := invoicesrpc.AddInvoice(
|
||||
ctx, addInvoiceCfg, addInvoiceData,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payReqString, err := payReq.Encode(
|
||||
zpay32.MessageSigner{
|
||||
SignCompact: r.server.nodeSigner.SignDigestCompact,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newInvoice := &channeldb.Invoice{
|
||||
CreationDate: creationDate,
|
||||
Memo: []byte(invoice.Memo),
|
||||
Receipt: invoice.Receipt,
|
||||
PaymentRequest: []byte(payReqString),
|
||||
Terms: channeldb.ContractTerm{
|
||||
Value: amtMSat,
|
||||
},
|
||||
}
|
||||
copy(newInvoice.Terms.PaymentPreimage[:], paymentPreimage[:])
|
||||
|
||||
rpcsLog.Tracef("[addinvoice] adding new invoice %v",
|
||||
newLogClosure(func() string {
|
||||
return spew.Sdump(newInvoice)
|
||||
}),
|
||||
)
|
||||
|
||||
// With all sanity checks passed, write the invoice to the database.
|
||||
addIndex, err := r.server.invoices.AddInvoice(newInvoice, rHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &lnrpc.AddInvoiceResponse{
|
||||
RHash: rHash[:],
|
||||
PaymentRequest: payReqString,
|
||||
AddIndex: addIndex,
|
||||
AddIndex: dbInvoice.AddIndex,
|
||||
PaymentRequest: string(dbInvoice.PaymentRequest),
|
||||
RHash: hash[:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
13
server.go
13
server.go
@ -46,6 +46,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/sweep"
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
"github.com/lightningnetwork/lnd/tor"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -284,6 +285,14 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
|
||||
readBufferPool, runtime.NumCPU(), pool.DefaultWorkerTimeout,
|
||||
)
|
||||
|
||||
decodeFinalCltvExpiry := func(payReq string) (uint32, error) {
|
||||
invoice, err := zpay32.Decode(payReq, activeNetParams.Params)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(invoice.MinFinalCLTVExpiry()), nil
|
||||
}
|
||||
|
||||
s := &server{
|
||||
chanDB: chanDB,
|
||||
cc: cc,
|
||||
@ -291,7 +300,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
|
||||
writePool: writePool,
|
||||
readPool: readPool,
|
||||
|
||||
invoices: invoices.NewRegistry(chanDB, activeNetParams.Params),
|
||||
invoices: invoices.NewRegistry(chanDB, decodeFinalCltvExpiry),
|
||||
|
||||
channelNotifier: channelnotifier.New(chanDB),
|
||||
|
||||
@ -778,7 +787,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
|
||||
},
|
||||
DisableChannel: s.chanStatusMgr.RequestDisable,
|
||||
Sweeper: s.sweeper,
|
||||
SettleInvoice: s.invoices.SettleInvoice,
|
||||
Registry: s.invoices,
|
||||
NotifyClosedChannel: s.channelNotifier.NotifyClosedChannelEvent,
|
||||
}, chanDB)
|
||||
|
||||
|
@ -6,6 +6,8 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/lightningnetwork/lnd/autopilot"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/autopilotrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
||||
@ -14,6 +16,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"github.com/lightningnetwork/lnd/netann"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
)
|
||||
|
||||
@ -64,8 +67,11 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
|
||||
networkDir string, macService *macaroons.Service,
|
||||
atpl *autopilot.Manager,
|
||||
invoiceRegistry *invoices.InvoiceRegistry,
|
||||
htlcSwitch *htlcswitch.Switch,
|
||||
activeNetParams *chaincfg.Params,
|
||||
chanRouter *routing.ChannelRouter) error {
|
||||
chanRouter *routing.ChannelRouter,
|
||||
nodeSigner *netann.NodeSigner,
|
||||
chanDB *channeldb.DB) error {
|
||||
|
||||
// First, we'll use reflect to obtain a version of the config struct
|
||||
// that allows us to programmatically inspect its fields.
|
||||
@ -90,9 +96,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
|
||||
continue
|
||||
}
|
||||
|
||||
switch cfg := field.Interface().(type) {
|
||||
switch subCfg := field.Interface().(type) {
|
||||
case *signrpc.Config:
|
||||
subCfgValue := extractReflectValue(cfg)
|
||||
subCfgValue := extractReflectValue(subCfg)
|
||||
|
||||
subCfgValue.FieldByName("MacService").Set(
|
||||
reflect.ValueOf(macService),
|
||||
@ -105,7 +111,7 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
|
||||
)
|
||||
|
||||
case *walletrpc.Config:
|
||||
subCfgValue := extractReflectValue(cfg)
|
||||
subCfgValue := extractReflectValue(subCfg)
|
||||
|
||||
subCfgValue.FieldByName("NetworkDir").Set(
|
||||
reflect.ValueOf(networkDir),
|
||||
@ -124,14 +130,14 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
|
||||
)
|
||||
|
||||
case *autopilotrpc.Config:
|
||||
subCfgValue := extractReflectValue(cfg)
|
||||
subCfgValue := extractReflectValue(subCfg)
|
||||
|
||||
subCfgValue.FieldByName("Manager").Set(
|
||||
reflect.ValueOf(atpl),
|
||||
)
|
||||
|
||||
case *chainrpc.Config:
|
||||
subCfgValue := extractReflectValue(cfg)
|
||||
subCfgValue := extractReflectValue(subCfg)
|
||||
|
||||
subCfgValue.FieldByName("NetworkDir").Set(
|
||||
reflect.ValueOf(networkDir),
|
||||
@ -144,7 +150,7 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
|
||||
)
|
||||
|
||||
case *invoicesrpc.Config:
|
||||
subCfgValue := extractReflectValue(cfg)
|
||||
subCfgValue := extractReflectValue(subCfg)
|
||||
|
||||
subCfgValue.FieldByName("NetworkDir").Set(
|
||||
reflect.ValueOf(networkDir),
|
||||
@ -155,9 +161,28 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
|
||||
subCfgValue.FieldByName("InvoiceRegistry").Set(
|
||||
reflect.ValueOf(invoiceRegistry),
|
||||
)
|
||||
subCfgValue.FieldByName("IsChannelActive").Set(
|
||||
reflect.ValueOf(htlcSwitch.HasActiveLink),
|
||||
)
|
||||
subCfgValue.FieldByName("ChainParams").Set(
|
||||
reflect.ValueOf(activeNetParams),
|
||||
)
|
||||
subCfgValue.FieldByName("NodeSigner").Set(
|
||||
reflect.ValueOf(nodeSigner),
|
||||
)
|
||||
subCfgValue.FieldByName("MaxPaymentMSat").Set(
|
||||
reflect.ValueOf(maxPaymentMSat),
|
||||
)
|
||||
defaultDelta := cfg.Bitcoin.TimeLockDelta
|
||||
if registeredChains.PrimaryChain() == litecoinChain {
|
||||
defaultDelta = cfg.Litecoin.TimeLockDelta
|
||||
}
|
||||
subCfgValue.FieldByName("DefaultCLTVExpiry").Set(
|
||||
reflect.ValueOf(defaultDelta),
|
||||
)
|
||||
subCfgValue.FieldByName("ChanDB").Set(
|
||||
reflect.ValueOf(chanDB),
|
||||
)
|
||||
|
||||
case *routerrpc.Config:
|
||||
subCfgValue := extractReflectValue(cfg)
|
||||
|
@ -85,7 +85,9 @@ func (p *preimageBeacon) LookupPreimage(
|
||||
|
||||
// If we've found the invoice, then we can return the preimage
|
||||
// directly.
|
||||
if err != channeldb.ErrInvoiceNotFound {
|
||||
if err != channeldb.ErrInvoiceNotFound &&
|
||||
invoice.Terms.PaymentPreimage != channeldb.UnknownPreimage {
|
||||
|
||||
return invoice.Terms.PaymentPreimage, true
|
||||
}
|
||||
|
||||
|
31
zpay32/hophint.go
Normal file
31
zpay32/hophint.go
Normal file
@ -0,0 +1,31 @@
|
||||
package zpay32
|
||||
|
||||
import "github.com/btcsuite/btcd/btcec"
|
||||
|
||||
const (
|
||||
// DefaultFinalCLTVDelta is the default value to be used as the final
|
||||
// CLTV delta for a route if one is unspecified.
|
||||
DefaultFinalCLTVDelta = 9
|
||||
)
|
||||
|
||||
// HopHint is a routing hint that contains the minimum information of a channel
|
||||
// required for an intermediate hop in a route to forward the payment to the
|
||||
// next. This should be ideally used for private channels, since they are not
|
||||
// publicly advertised to the network for routing.
|
||||
type HopHint struct {
|
||||
// NodeID is the public key of the node at the start of the channel.
|
||||
NodeID *btcec.PublicKey
|
||||
|
||||
// ChannelID is the unique identifier of the channel.
|
||||
ChannelID uint64
|
||||
|
||||
// FeeBaseMSat is the base fee of the channel in millisatoshis.
|
||||
FeeBaseMSat uint32
|
||||
|
||||
// FeeProportionalMillionths is the fee rate, in millionths of a
|
||||
// satoshi, for every satoshi sent through the channel.
|
||||
FeeProportionalMillionths uint32
|
||||
|
||||
// CLTVExpiryDelta is the time-lock delta of the channel.
|
||||
CLTVExpiryDelta uint16
|
||||
}
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/bech32"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -146,7 +145,7 @@ type Invoice struct {
|
||||
// represent private routes.
|
||||
//
|
||||
// NOTE: This is optional.
|
||||
RouteHints [][]routing.HopHint
|
||||
RouteHints [][]HopHint
|
||||
}
|
||||
|
||||
// Amount is a functional option that allows callers of NewInvoice to set the
|
||||
@ -214,7 +213,7 @@ func FallbackAddr(fallbackAddr btcutil.Address) func(*Invoice) {
|
||||
|
||||
// RouteHint is a functional option that allows callers of NewInvoice to add
|
||||
// one or more hop hints that represent a private route to the destination.
|
||||
func RouteHint(routeHint []routing.HopHint) func(*Invoice) {
|
||||
func RouteHint(routeHint []HopHint) func(*Invoice) {
|
||||
return func(i *Invoice) {
|
||||
i.RouteHints = append(i.RouteHints, routeHint)
|
||||
}
|
||||
@ -476,7 +475,7 @@ func (invoice *Invoice) MinFinalCLTVExpiry() uint64 {
|
||||
return *invoice.minFinalCLTVExpiry
|
||||
}
|
||||
|
||||
return routing.DefaultFinalCLTVDelta
|
||||
return DefaultFinalCLTVDelta
|
||||
}
|
||||
|
||||
// validateInvoice does a sanity check of the provided Invoice, making sure it
|
||||
@ -843,7 +842,7 @@ func parseFallbackAddr(data []byte, net *chaincfg.Params) (btcutil.Address, erro
|
||||
|
||||
// parseRouteHint converts the data (encoded in base32) into an array containing
|
||||
// one or more routing hop hints that represent a single route hint.
|
||||
func parseRouteHint(data []byte) ([]routing.HopHint, error) {
|
||||
func parseRouteHint(data []byte) ([]HopHint, error) {
|
||||
base256Data, err := bech32.ConvertBits(data, 5, 8, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -854,10 +853,10 @@ func parseRouteHint(data []byte) ([]routing.HopHint, error) {
|
||||
"got %d", hopHintLen, len(base256Data))
|
||||
}
|
||||
|
||||
var routeHint []routing.HopHint
|
||||
var routeHint []HopHint
|
||||
|
||||
for len(base256Data) > 0 {
|
||||
hopHint := routing.HopHint{}
|
||||
hopHint := HopHint{}
|
||||
hopHint.NodeID, err = btcec.ParsePubKey(base256Data[:33], btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/bech32"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
)
|
||||
|
||||
// TestDecodeAmount ensures that the amount string in the hrp of the Invoice
|
||||
@ -738,7 +737,7 @@ func TestParseRouteHint(t *testing.T) {
|
||||
tests := []struct {
|
||||
data []byte
|
||||
valid bool
|
||||
result []routing.HopHint
|
||||
result []HopHint
|
||||
}{
|
||||
{
|
||||
data: []byte{0x0, 0x0, 0x0, 0x0},
|
||||
@ -747,7 +746,7 @@ func TestParseRouteHint(t *testing.T) {
|
||||
{
|
||||
data: []byte{},
|
||||
valid: true,
|
||||
result: []routing.HopHint{},
|
||||
result: []HopHint{},
|
||||
},
|
||||
{
|
||||
data: testSingleHopData,
|
||||
|
@ -17,7 +17,6 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
|
||||
litecoinCfg "github.com/ltcsuite/ltcd/chaincfg"
|
||||
)
|
||||
@ -53,7 +52,7 @@ var (
|
||||
testHopHintPubkeyBytes2, _ = hex.DecodeString("039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255")
|
||||
testHopHintPubkey2, _ = btcec.ParsePubKey(testHopHintPubkeyBytes2, btcec.S256())
|
||||
|
||||
testSingleHop = []routing.HopHint{
|
||||
testSingleHop = []HopHint{
|
||||
{
|
||||
NodeID: testHopHintPubkey1,
|
||||
ChannelID: 0x0102030405060708,
|
||||
@ -62,7 +61,7 @@ var (
|
||||
CLTVExpiryDelta: 3,
|
||||
},
|
||||
}
|
||||
testDoubleHop = []routing.HopHint{
|
||||
testDoubleHop = []HopHint{
|
||||
{
|
||||
NodeID: testHopHintPubkey1,
|
||||
ChannelID: 0x0102030405060708,
|
||||
@ -414,7 +413,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
DescriptionHash: &testDescriptionHash,
|
||||
Destination: testPubKey,
|
||||
FallbackAddr: testRustyAddr,
|
||||
RouteHints: [][]routing.HopHint{testSingleHop},
|
||||
RouteHints: [][]HopHint{testSingleHop},
|
||||
}
|
||||
},
|
||||
beforeEncoding: func(i *Invoice) {
|
||||
@ -437,7 +436,7 @@ func TestDecodeEncode(t *testing.T) {
|
||||
DescriptionHash: &testDescriptionHash,
|
||||
Destination: testPubKey,
|
||||
FallbackAddr: testRustyAddr,
|
||||
RouteHints: [][]routing.HopHint{testDoubleHop},
|
||||
RouteHints: [][]HopHint{testDoubleHop},
|
||||
}
|
||||
},
|
||||
beforeEncoding: func(i *Invoice) {
|
||||
@ -844,7 +843,7 @@ func compareHashes(a, b *[32]byte) bool {
|
||||
return bytes.Equal(a[:], b[:])
|
||||
}
|
||||
|
||||
func compareRouteHints(a, b []routing.HopHint) error {
|
||||
func compareRouteHints(a, b []HopHint) error {
|
||||
if len(a) != len(b) {
|
||||
return fmt.Errorf("expected len routingInfo %d, got %d",
|
||||
len(a), len(b))
|
||||
|
Loading…
Reference in New Issue
Block a user