diff --git a/breacharbiter.go b/breacharbiter.go index 45c4bafc1d..269a7b1240 100644 --- a/breacharbiter.go +++ b/breacharbiter.go @@ -807,13 +807,13 @@ func (bo *breachedOutput) SignDesc() *lnwallet.SignDescriptor { return &bo.signDesc } -// BuildWitness computes a valid witness that allows us to spend from the +// CraftInputScript computes a valid witness that allows us to spend from the // breached output. It does so by first generating and memoizing the witness // generation function, which parameterized primarily by the witness type and // sign descriptor. The method then returns the witness computed by invoking // this function on the first and subsequent calls. -func (bo *breachedOutput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx, - hashCache *txscript.TxSigHashes, txinIdx int) ([][]byte, error) { +func (bo *breachedOutput) CraftInputScript(signer lnwallet.Signer, txn *wire.MsgTx, + hashCache *txscript.TxSigHashes, txinIdx int) (*lnwallet.InputScript, error) { // First, we ensure that the witness generation function has been // initialized for this breached output. @@ -1082,15 +1082,16 @@ func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64, // First, we construct a valid witness for this outpoint and // transaction using the SpendableOutput's witness generation // function. - witness, err := so.BuildWitness(b.cfg.Signer, txn, hashCache, - idx) + inputScript, err := so.CraftInputScript( + b.cfg.Signer, txn, hashCache, idx, + ) if err != nil { return err } // Then, we add the witness to the transaction at the // appropriate txin index. - txn.TxIn[idx].Witness = witness + txn.TxIn[idx].Witness = inputScript.Witness return nil } diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index e1e511b940..228ca6b48c 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -161,7 +161,13 @@ var sendCoinsCommand = cli.Command{ Name: "addr", Usage: "the BASE58 encoded bitcoin address to send coins to on-chain", }, - // TODO(roasbeef): switch to BTC on command line? int may not be sufficient + cli.BoolFlag{ + Name: "sweepall", + Usage: "if set, then the amount field will be ignored, " + + "and all the wallet will attempt to sweep all " + + "outputs within the wallet to the target " + + "address", + }, cli.Int64Flag{ Name: "amt", Usage: "the number of bitcoin denominated in satoshis to send", @@ -215,14 +221,18 @@ func sendCoins(ctx *cli.Context) error { amt = ctx.Int64("amt") case args.Present(): amt, err = strconv.ParseInt(args.First(), 10, 64) - default: + case !ctx.Bool("sweepall"): return fmt.Errorf("Amount argument missing") } - if err != nil { return fmt.Errorf("unable to decode amount: %v", err) } + if amt != 0 && ctx.Bool("sweepall") { + return fmt.Errorf("amount cannot be set if attempting to " + + "sweep all coins out of the wallet") + } + ctxb := context.Background() client, cleanUp := getClient(ctx) defer cleanUp() @@ -232,6 +242,7 @@ func sendCoins(ctx *cli.Context) error { Amount: amt, TargetConf: int32(ctx.Int64("conf_target")), SatPerByte: ctx.Int64("sat_per_byte"), + SendAll: ctx.Bool("sweepall"), } txid, err := client.SendCoins(ctxb, req) if err != nil { diff --git a/contractcourt/contract_resolvers.go b/contractcourt/contract_resolvers.go index 6d4609da40..3cc5e4a967 100644 --- a/contractcourt/contract_resolvers.go +++ b/contractcourt/contract_resolvers.go @@ -476,7 +476,10 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) { // TODO: Use time-based sweeper and result chan. var err error h.sweepTx, err = h.Sweeper.CreateSweepTx( - []sweep.Input{&input}, sweepConfTarget, 0, + []sweep.Input{&input}, + sweep.FeePreference{ + ConfTarget: sweepConfTarget, + }, 0, ) if err != nil { return nil, err @@ -1270,7 +1273,10 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) { // // TODO: Use time-based sweeper and result chan. c.sweepTx, err = c.Sweeper.CreateSweepTx( - []sweep.Input{&input}, sweepConfTarget, 0, + []sweep.Input{&input}, + sweep.FeePreference{ + ConfTarget: sweepConfTarget, + }, 0, ) if err != nil { return nil, err diff --git a/lnd_test.go b/lnd_test.go index 2abde8d51d..cb78e648ea 100644 --- a/lnd_test.go +++ b/lnd_test.go @@ -12617,12 +12617,95 @@ func testAbandonChannel(net *lntest.NetworkHarness, t *harnessTest) { cleanupForceClose(t, net, net.Bob, chanPoint) } +// testSweepAllCoins tests that we're able to properly sweep all coins from the +// wallet into a single target address at the specified fee rate. +func testSweepAllCoins(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() + + // First, we'll make a new node, ainz who'll we'll use to test wallet + // sweeping. + ainz, err := net.NewNode("Ainz", nil) + if err != nil { + t.Fatalf("unable to create new node: %v", err) + } + defer shutdownAndAssert(net, t, ainz) + + // Next, we'll give Ainz exactly 2 utxos of 1 BTC each, with one of + // them being p2wkh and the other being a n2wpkh address. + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + err = net.SendCoins(ctxt, btcutil.SatoshiPerBitcoin, ainz) + if err != nil { + t.Fatalf("unable to send coins to eve: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + err = net.SendCoinsNP2WKH(ctxt, btcutil.SatoshiPerBitcoin, ainz) + if err != nil { + t.Fatalf("unable to send coins to eve: %v", err) + } + + // With the two coins above mined, we'll now instruct ainz to sweep all + // the coins to an external address not under its control. + minerAddr, err := net.Miner.NewAddress() + if err != nil { + t.Fatalf("unable to create new miner addr: %v", err) + } + + sweepReq := &lnrpc.SendCoinsRequest{ + Addr: minerAddr.String(), + SendAll: true, + } + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + _, err = ainz.SendCoins(ctxt, sweepReq) + if err != nil { + t.Fatalf("unable to sweep coins: %v", err) + } + + // We'll mine a block wish should include the sweep transaction we + // generated above. + block := mineBlocks(t, net, 1, 1)[0] + + // The sweep transaction should have exactly two inputs as we only had + // two UTXOs in the wallet. + sweepTx := block.Transactions[1] + if len(sweepTx.TxIn) != 2 { + t.Fatalf("expected 2 inputs instead have %v", len(sweepTx.TxIn)) + } + + // Finally, Ainz should now have no coins at all within his wallet. + balReq := &lnrpc.WalletBalanceRequest{} + resp, err := ainz.WalletBalance(ctxt, balReq) + if err != nil { + t.Fatalf("unable to get ainz's balance: %v", err) + } + switch { + case resp.ConfirmedBalance != 0: + t.Fatalf("expected no confirmed balance, instead have %v", + resp.ConfirmedBalance) + + case resp.UnconfirmedBalance != 0: + t.Fatalf("expected no unconfirmed balance, instead have %v", + resp.UnconfirmedBalance) + } + + // If we try again, but this time specifying an amount, then the call + // should fail. + sweepReq.Amount = 10000 + _, err = ainz.SendCoins(ctxt, sweepReq) + if err == nil { + t.Fatalf("sweep attempt should fail") + } +} + type testCase struct { name string test func(net *lntest.NetworkHarness, t *harnessTest) } var testsCases = []*testCase{ + { + name: "sweep coins", + test: testSweepAllCoins, + }, { name: "onchain fund recovery", test: testOnchainFundRecovery, diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 3cbefc0168..54d0402dbb 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -49,7 +49,7 @@ func (x AddressType) String() string { return proto.EnumName(AddressType_name, int32(x)) } func (AddressType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_b1b9aa8c9dfaad66, []int{0} + return fileDescriptor_rpc_e66000aa8614d793, []int{0} } type ChannelCloseSummary_ClosureType int32 @@ -84,7 +84,7 @@ func (x ChannelCloseSummary_ClosureType) String() string { return proto.EnumName(ChannelCloseSummary_ClosureType_name, int32(x)) } func (ChannelCloseSummary_ClosureType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_b1b9aa8c9dfaad66, []int{38, 0} + return fileDescriptor_rpc_e66000aa8614d793, []int{38, 0} } type Invoice_InvoiceState int32 @@ -107,7 +107,7 @@ func (x Invoice_InvoiceState) String() string { return proto.EnumName(Invoice_InvoiceState_name, int32(x)) } func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_b1b9aa8c9dfaad66, []int{86, 0} + return fileDescriptor_rpc_e66000aa8614d793, []int{86, 0} } type GenSeedRequest struct { @@ -128,7 +128,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_b1b9aa8c9dfaad66, []int{0} + return fileDescriptor_rpc_e66000aa8614d793, []int{0} } func (m *GenSeedRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GenSeedRequest.Unmarshal(m, b) @@ -183,7 +183,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_b1b9aa8c9dfaad66, []int{1} + return fileDescriptor_rpc_e66000aa8614d793, []int{1} } func (m *GenSeedResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GenSeedResponse.Unmarshal(m, b) @@ -248,7 +248,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_b1b9aa8c9dfaad66, []int{2} + return fileDescriptor_rpc_e66000aa8614d793, []int{2} } func (m *InitWalletRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InitWalletRequest.Unmarshal(m, b) @@ -306,7 +306,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_b1b9aa8c9dfaad66, []int{3} + return fileDescriptor_rpc_e66000aa8614d793, []int{3} } func (m *InitWalletResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InitWalletResponse.Unmarshal(m, b) @@ -348,7 +348,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_b1b9aa8c9dfaad66, []int{4} + return fileDescriptor_rpc_e66000aa8614d793, []int{4} } func (m *UnlockWalletRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UnlockWalletRequest.Unmarshal(m, b) @@ -392,7 +392,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_b1b9aa8c9dfaad66, []int{5} + return fileDescriptor_rpc_e66000aa8614d793, []int{5} } func (m *UnlockWalletResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UnlockWalletResponse.Unmarshal(m, b) @@ -430,7 +430,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_b1b9aa8c9dfaad66, []int{6} + return fileDescriptor_rpc_e66000aa8614d793, []int{6} } func (m *ChangePasswordRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChangePasswordRequest.Unmarshal(m, b) @@ -474,7 +474,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_b1b9aa8c9dfaad66, []int{7} + return fileDescriptor_rpc_e66000aa8614d793, []int{7} } func (m *ChangePasswordResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChangePasswordResponse.Unmarshal(m, b) @@ -518,7 +518,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_b1b9aa8c9dfaad66, []int{8} + return fileDescriptor_rpc_e66000aa8614d793, []int{8} } func (m *Utxo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Utxo.Unmarshal(m, b) @@ -606,7 +606,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_b1b9aa8c9dfaad66, []int{9} + return fileDescriptor_rpc_e66000aa8614d793, []int{9} } func (m *Transaction) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Transaction.Unmarshal(m, b) @@ -692,7 +692,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_b1b9aa8c9dfaad66, []int{10} + return fileDescriptor_rpc_e66000aa8614d793, []int{10} } func (m *GetTransactionsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetTransactionsRequest.Unmarshal(m, b) @@ -724,7 +724,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_b1b9aa8c9dfaad66, []int{11} + return fileDescriptor_rpc_e66000aa8614d793, []int{11} } func (m *TransactionDetails) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TransactionDetails.Unmarshal(m, b) @@ -765,7 +765,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_b1b9aa8c9dfaad66, []int{12} + return fileDescriptor_rpc_e66000aa8614d793, []int{12} } func (m *FeeLimit) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeLimit.Unmarshal(m, b) @@ -921,7 +921,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_b1b9aa8c9dfaad66, []int{13} + return fileDescriptor_rpc_e66000aa8614d793, []int{13} } func (m *SendRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendRequest.Unmarshal(m, b) @@ -1011,7 +1011,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_b1b9aa8c9dfaad66, []int{14} + return fileDescriptor_rpc_e66000aa8614d793, []int{14} } func (m *SendResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendResponse.Unmarshal(m, b) @@ -1075,7 +1075,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_b1b9aa8c9dfaad66, []int{15} + return fileDescriptor_rpc_e66000aa8614d793, []int{15} } func (m *SendToRouteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendToRouteRequest.Unmarshal(m, b) @@ -1132,7 +1132,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_b1b9aa8c9dfaad66, []int{16} + return fileDescriptor_rpc_e66000aa8614d793, []int{16} } func (m *ChannelPoint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelPoint.Unmarshal(m, b) @@ -1276,7 +1276,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_b1b9aa8c9dfaad66, []int{17} + return fileDescriptor_rpc_e66000aa8614d793, []int{17} } func (m *LightningAddress) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_LightningAddress.Unmarshal(m, b) @@ -1326,7 +1326,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_b1b9aa8c9dfaad66, []int{18} + return fileDescriptor_rpc_e66000aa8614d793, []int{18} } func (m *SendManyRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendManyRequest.Unmarshal(m, b) @@ -1379,7 +1379,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_b1b9aa8c9dfaad66, []int{19} + return fileDescriptor_rpc_e66000aa8614d793, []int{19} } func (m *SendManyResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendManyResponse.Unmarshal(m, b) @@ -1414,7 +1414,12 @@ type SendCoinsRequest struct { // / The target number of blocks that this transaction should be confirmed by. TargetConf int32 `protobuf:"varint,3,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` // / A manual fee rate set in sat/byte that should be used when crafting the transaction. - SatPerByte int64 `protobuf:"varint,5,opt,name=sat_per_byte,json=satPerByte,proto3" json:"sat_per_byte,omitempty"` + SatPerByte int64 `protobuf:"varint,5,opt,name=sat_per_byte,json=satPerByte,proto3" json:"sat_per_byte,omitempty"` + // * + // If set, then the amount field will be ignored, and lnd will attempt to + // send all the coins under control of the internal wallet to the specified + // address. + SendAll bool `protobuf:"varint,6,opt,name=send_all,json=sendAll,proto3" json:"send_all,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1424,7 +1429,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_b1b9aa8c9dfaad66, []int{20} + return fileDescriptor_rpc_e66000aa8614d793, []int{20} } func (m *SendCoinsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendCoinsRequest.Unmarshal(m, b) @@ -1472,6 +1477,13 @@ func (m *SendCoinsRequest) GetSatPerByte() int64 { return 0 } +func (m *SendCoinsRequest) GetSendAll() bool { + if m != nil { + return m.SendAll + } + return false +} + type SendCoinsResponse struct { // / The transaction ID of the transaction Txid string `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` @@ -1484,7 +1496,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_b1b9aa8c9dfaad66, []int{21} + return fileDescriptor_rpc_e66000aa8614d793, []int{21} } func (m *SendCoinsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendCoinsResponse.Unmarshal(m, b) @@ -1525,7 +1537,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_b1b9aa8c9dfaad66, []int{22} + return fileDescriptor_rpc_e66000aa8614d793, []int{22} } func (m *ListUnspentRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListUnspentRequest.Unmarshal(m, b) @@ -1571,7 +1583,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_b1b9aa8c9dfaad66, []int{23} + return fileDescriptor_rpc_e66000aa8614d793, []int{23} } func (m *ListUnspentResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListUnspentResponse.Unmarshal(m, b) @@ -1610,7 +1622,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_b1b9aa8c9dfaad66, []int{24} + return fileDescriptor_rpc_e66000aa8614d793, []int{24} } func (m *NewAddressRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NewAddressRequest.Unmarshal(m, b) @@ -1649,7 +1661,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_b1b9aa8c9dfaad66, []int{25} + return fileDescriptor_rpc_e66000aa8614d793, []int{25} } func (m *NewAddressResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NewAddressResponse.Unmarshal(m, b) @@ -1688,7 +1700,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_b1b9aa8c9dfaad66, []int{26} + return fileDescriptor_rpc_e66000aa8614d793, []int{26} } func (m *SignMessageRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SignMessageRequest.Unmarshal(m, b) @@ -1727,7 +1739,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_b1b9aa8c9dfaad66, []int{27} + return fileDescriptor_rpc_e66000aa8614d793, []int{27} } func (m *SignMessageResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SignMessageResponse.Unmarshal(m, b) @@ -1768,7 +1780,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_b1b9aa8c9dfaad66, []int{28} + return fileDescriptor_rpc_e66000aa8614d793, []int{28} } func (m *VerifyMessageRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VerifyMessageRequest.Unmarshal(m, b) @@ -1816,7 +1828,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_b1b9aa8c9dfaad66, []int{29} + return fileDescriptor_rpc_e66000aa8614d793, []int{29} } func (m *VerifyMessageResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VerifyMessageResponse.Unmarshal(m, b) @@ -1865,7 +1877,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_b1b9aa8c9dfaad66, []int{30} + return fileDescriptor_rpc_e66000aa8614d793, []int{30} } func (m *ConnectPeerRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConnectPeerRequest.Unmarshal(m, b) @@ -1909,7 +1921,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_b1b9aa8c9dfaad66, []int{31} + return fileDescriptor_rpc_e66000aa8614d793, []int{31} } func (m *ConnectPeerResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConnectPeerResponse.Unmarshal(m, b) @@ -1941,7 +1953,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_b1b9aa8c9dfaad66, []int{32} + return fileDescriptor_rpc_e66000aa8614d793, []int{32} } func (m *DisconnectPeerRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DisconnectPeerRequest.Unmarshal(m, b) @@ -1978,7 +1990,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_b1b9aa8c9dfaad66, []int{33} + return fileDescriptor_rpc_e66000aa8614d793, []int{33} } func (m *DisconnectPeerResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DisconnectPeerResponse.Unmarshal(m, b) @@ -2012,7 +2024,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_b1b9aa8c9dfaad66, []int{34} + return fileDescriptor_rpc_e66000aa8614d793, []int{34} } func (m *HTLC) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HTLC.Unmarshal(m, b) @@ -2124,7 +2136,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_b1b9aa8c9dfaad66, []int{35} + return fileDescriptor_rpc_e66000aa8614d793, []int{35} } func (m *Channel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Channel.Unmarshal(m, b) @@ -2277,7 +2289,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_b1b9aa8c9dfaad66, []int{36} + return fileDescriptor_rpc_e66000aa8614d793, []int{36} } func (m *ListChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListChannelsRequest.Unmarshal(m, b) @@ -2337,7 +2349,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_b1b9aa8c9dfaad66, []int{37} + return fileDescriptor_rpc_e66000aa8614d793, []int{37} } func (m *ListChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListChannelsResponse.Unmarshal(m, b) @@ -2394,7 +2406,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_b1b9aa8c9dfaad66, []int{38} + return fileDescriptor_rpc_e66000aa8614d793, []int{38} } func (m *ChannelCloseSummary) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelCloseSummary.Unmarshal(m, b) @@ -2500,7 +2512,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_b1b9aa8c9dfaad66, []int{39} + return fileDescriptor_rpc_e66000aa8614d793, []int{39} } func (m *ClosedChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelsRequest.Unmarshal(m, b) @@ -2573,7 +2585,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_b1b9aa8c9dfaad66, []int{40} + return fileDescriptor_rpc_e66000aa8614d793, []int{40} } func (m *ClosedChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelsResponse.Unmarshal(m, b) @@ -2626,7 +2638,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_b1b9aa8c9dfaad66, []int{41} + return fileDescriptor_rpc_e66000aa8614d793, []int{41} } func (m *Peer) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Peer.Unmarshal(m, b) @@ -2712,7 +2724,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_b1b9aa8c9dfaad66, []int{42} + return fileDescriptor_rpc_e66000aa8614d793, []int{42} } func (m *ListPeersRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPeersRequest.Unmarshal(m, b) @@ -2744,7 +2756,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_b1b9aa8c9dfaad66, []int{43} + return fileDescriptor_rpc_e66000aa8614d793, []int{43} } func (m *ListPeersResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPeersResponse.Unmarshal(m, b) @@ -2781,7 +2793,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_b1b9aa8c9dfaad66, []int{44} + return fileDescriptor_rpc_e66000aa8614d793, []int{44} } func (m *GetInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetInfoRequest.Unmarshal(m, b) @@ -2841,7 +2853,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_b1b9aa8c9dfaad66, []int{45} + return fileDescriptor_rpc_e66000aa8614d793, []int{45} } func (m *GetInfoResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetInfoResponse.Unmarshal(m, b) @@ -2961,7 +2973,9 @@ func (m *GetInfoResponse) GetChains() []*Chain { } type Chain struct { - Chain string `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` + // / The blockchain the node is on (eg bitcoin, litecoin) + Chain string `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` + // / The network the node is on (eg regtest, testnet, mainnet) Network string `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -2972,7 +2986,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_b1b9aa8c9dfaad66, []int{46} + return fileDescriptor_rpc_e66000aa8614d793, []int{46} } func (m *Chain) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Chain.Unmarshal(m, b) @@ -3019,7 +3033,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_b1b9aa8c9dfaad66, []int{47} + return fileDescriptor_rpc_e66000aa8614d793, []int{47} } func (m *ConfirmationUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConfirmationUpdate.Unmarshal(m, b) @@ -3071,7 +3085,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_b1b9aa8c9dfaad66, []int{48} + return fileDescriptor_rpc_e66000aa8614d793, []int{48} } func (m *ChannelOpenUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelOpenUpdate.Unmarshal(m, b) @@ -3110,7 +3124,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_b1b9aa8c9dfaad66, []int{49} + return fileDescriptor_rpc_e66000aa8614d793, []int{49} } func (m *ChannelCloseUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelCloseUpdate.Unmarshal(m, b) @@ -3165,7 +3179,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_b1b9aa8c9dfaad66, []int{50} + return fileDescriptor_rpc_e66000aa8614d793, []int{50} } func (m *CloseChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CloseChannelRequest.Unmarshal(m, b) @@ -3227,7 +3241,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_b1b9aa8c9dfaad66, []int{51} + return fileDescriptor_rpc_e66000aa8614d793, []int{51} } func (m *CloseStatusUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CloseStatusUpdate.Unmarshal(m, b) @@ -3370,7 +3384,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_b1b9aa8c9dfaad66, []int{52} + return fileDescriptor_rpc_e66000aa8614d793, []int{52} } func (m *PendingUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingUpdate.Unmarshal(m, b) @@ -3436,7 +3450,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_b1b9aa8c9dfaad66, []int{53} + return fileDescriptor_rpc_e66000aa8614d793, []int{53} } func (m *OpenChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_OpenChannelRequest.Unmarshal(m, b) @@ -3547,7 +3561,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_b1b9aa8c9dfaad66, []int{54} + return fileDescriptor_rpc_e66000aa8614d793, []int{54} } func (m *OpenStatusUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_OpenStatusUpdate.Unmarshal(m, b) @@ -3703,7 +3717,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_b1b9aa8c9dfaad66, []int{55} + return fileDescriptor_rpc_e66000aa8614d793, []int{55} } func (m *PendingHTLC) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingHTLC.Unmarshal(m, b) @@ -3775,7 +3789,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_b1b9aa8c9dfaad66, []int{56} + return fileDescriptor_rpc_e66000aa8614d793, []int{56} } func (m *PendingChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsRequest.Unmarshal(m, b) @@ -3815,7 +3829,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_b1b9aa8c9dfaad66, []int{57} + return fileDescriptor_rpc_e66000aa8614d793, []int{57} } func (m *PendingChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse.Unmarshal(m, b) @@ -3887,7 +3901,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_b1b9aa8c9dfaad66, []int{57, 0} + return fileDescriptor_rpc_e66000aa8614d793, []int{57, 0} } func (m *PendingChannelsResponse_PendingChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_PendingChannel.Unmarshal(m, b) @@ -3974,7 +3988,7 @@ func (m *PendingChannelsResponse_PendingOpenChannel) String() string { } func (*PendingChannelsResponse_PendingOpenChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingOpenChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_b1b9aa8c9dfaad66, []int{57, 1} + return fileDescriptor_rpc_e66000aa8614d793, []int{57, 1} } func (m *PendingChannelsResponse_PendingOpenChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_PendingOpenChannel.Unmarshal(m, b) @@ -4047,7 +4061,7 @@ func (m *PendingChannelsResponse_WaitingCloseChannel) String() string { } func (*PendingChannelsResponse_WaitingCloseChannel) ProtoMessage() {} func (*PendingChannelsResponse_WaitingCloseChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_b1b9aa8c9dfaad66, []int{57, 2} + return fileDescriptor_rpc_e66000aa8614d793, []int{57, 2} } func (m *PendingChannelsResponse_WaitingCloseChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_WaitingCloseChannel.Unmarshal(m, b) @@ -4095,7 +4109,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_b1b9aa8c9dfaad66, []int{57, 3} + return fileDescriptor_rpc_e66000aa8614d793, []int{57, 3} } func (m *PendingChannelsResponse_ClosedChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_ClosedChannel.Unmarshal(m, b) @@ -4159,7 +4173,7 @@ func (m *PendingChannelsResponse_ForceClosedChannel) String() string { } func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ForceClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_b1b9aa8c9dfaad66, []int{57, 4} + return fileDescriptor_rpc_e66000aa8614d793, []int{57, 4} } func (m *PendingChannelsResponse_ForceClosedChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_ForceClosedChannel.Unmarshal(m, b) @@ -4238,7 +4252,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_b1b9aa8c9dfaad66, []int{58} + return fileDescriptor_rpc_e66000aa8614d793, []int{58} } func (m *WalletBalanceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WalletBalanceRequest.Unmarshal(m, b) @@ -4274,7 +4288,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_b1b9aa8c9dfaad66, []int{59} + return fileDescriptor_rpc_e66000aa8614d793, []int{59} } func (m *WalletBalanceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WalletBalanceResponse.Unmarshal(m, b) @@ -4325,7 +4339,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_b1b9aa8c9dfaad66, []int{60} + return fileDescriptor_rpc_e66000aa8614d793, []int{60} } func (m *ChannelBalanceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelBalanceRequest.Unmarshal(m, b) @@ -4359,7 +4373,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_b1b9aa8c9dfaad66, []int{61} + return fileDescriptor_rpc_e66000aa8614d793, []int{61} } func (m *ChannelBalanceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelBalanceResponse.Unmarshal(m, b) @@ -4417,7 +4431,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_b1b9aa8c9dfaad66, []int{62} + return fileDescriptor_rpc_e66000aa8614d793, []int{62} } func (m *QueryRoutesRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryRoutesRequest.Unmarshal(m, b) @@ -4483,7 +4497,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_b1b9aa8c9dfaad66, []int{63} + return fileDescriptor_rpc_e66000aa8614d793, []int{63} } func (m *QueryRoutesResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryRoutesResponse.Unmarshal(m, b) @@ -4535,7 +4549,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_b1b9aa8c9dfaad66, []int{64} + return fileDescriptor_rpc_e66000aa8614d793, []int{64} } func (m *Hop) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Hop.Unmarshal(m, b) @@ -4656,7 +4670,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_b1b9aa8c9dfaad66, []int{65} + return fileDescriptor_rpc_e66000aa8614d793, []int{65} } func (m *Route) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Route.Unmarshal(m, b) @@ -4732,7 +4746,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_b1b9aa8c9dfaad66, []int{66} + return fileDescriptor_rpc_e66000aa8614d793, []int{66} } func (m *NodeInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeInfoRequest.Unmarshal(m, b) @@ -4777,7 +4791,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_b1b9aa8c9dfaad66, []int{67} + return fileDescriptor_rpc_e66000aa8614d793, []int{67} } func (m *NodeInfo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeInfo.Unmarshal(m, b) @@ -4838,7 +4852,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_b1b9aa8c9dfaad66, []int{68} + return fileDescriptor_rpc_e66000aa8614d793, []int{68} } func (m *LightningNode) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_LightningNode.Unmarshal(m, b) @@ -4905,7 +4919,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_b1b9aa8c9dfaad66, []int{69} + return fileDescriptor_rpc_e66000aa8614d793, []int{69} } func (m *NodeAddress) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeAddress.Unmarshal(m, b) @@ -4954,7 +4968,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_b1b9aa8c9dfaad66, []int{70} + return fileDescriptor_rpc_e66000aa8614d793, []int{70} } func (m *RoutingPolicy) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RoutingPolicy.Unmarshal(m, b) @@ -5037,7 +5051,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_b1b9aa8c9dfaad66, []int{71} + return fileDescriptor_rpc_e66000aa8614d793, []int{71} } func (m *ChannelEdge) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEdge.Unmarshal(m, b) @@ -5128,7 +5142,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_b1b9aa8c9dfaad66, []int{72} + return fileDescriptor_rpc_e66000aa8614d793, []int{72} } func (m *ChannelGraphRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelGraphRequest.Unmarshal(m, b) @@ -5170,7 +5184,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_b1b9aa8c9dfaad66, []int{73} + return fileDescriptor_rpc_e66000aa8614d793, []int{73} } func (m *ChannelGraph) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelGraph.Unmarshal(m, b) @@ -5219,7 +5233,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_b1b9aa8c9dfaad66, []int{74} + return fileDescriptor_rpc_e66000aa8614d793, []int{74} } func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChanInfoRequest.Unmarshal(m, b) @@ -5256,7 +5270,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_b1b9aa8c9dfaad66, []int{75} + return fileDescriptor_rpc_e66000aa8614d793, []int{75} } func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NetworkInfoRequest.Unmarshal(m, b) @@ -5295,7 +5309,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_b1b9aa8c9dfaad66, []int{76} + return fileDescriptor_rpc_e66000aa8614d793, []int{76} } func (m *NetworkInfo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NetworkInfo.Unmarshal(m, b) @@ -5388,7 +5402,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_b1b9aa8c9dfaad66, []int{77} + return fileDescriptor_rpc_e66000aa8614d793, []int{77} } func (m *StopRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StopRequest.Unmarshal(m, b) @@ -5418,7 +5432,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_b1b9aa8c9dfaad66, []int{78} + return fileDescriptor_rpc_e66000aa8614d793, []int{78} } func (m *StopResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StopResponse.Unmarshal(m, b) @@ -5448,7 +5462,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_b1b9aa8c9dfaad66, []int{79} + return fileDescriptor_rpc_e66000aa8614d793, []int{79} } func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GraphTopologySubscription.Unmarshal(m, b) @@ -5481,7 +5495,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_b1b9aa8c9dfaad66, []int{80} + return fileDescriptor_rpc_e66000aa8614d793, []int{80} } func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GraphTopologyUpdate.Unmarshal(m, b) @@ -5536,7 +5550,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_b1b9aa8c9dfaad66, []int{81} + return fileDescriptor_rpc_e66000aa8614d793, []int{81} } func (m *NodeUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeUpdate.Unmarshal(m, b) @@ -5604,7 +5618,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_b1b9aa8c9dfaad66, []int{82} + return fileDescriptor_rpc_e66000aa8614d793, []int{82} } func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEdgeUpdate.Unmarshal(m, b) @@ -5684,7 +5698,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_b1b9aa8c9dfaad66, []int{83} + return fileDescriptor_rpc_e66000aa8614d793, []int{83} } func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelUpdate.Unmarshal(m, b) @@ -5754,7 +5768,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_b1b9aa8c9dfaad66, []int{84} + return fileDescriptor_rpc_e66000aa8614d793, []int{84} } func (m *HopHint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HopHint.Unmarshal(m, b) @@ -5823,7 +5837,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_b1b9aa8c9dfaad66, []int{85} + return fileDescriptor_rpc_e66000aa8614d793, []int{85} } func (m *RouteHint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RouteHint.Unmarshal(m, b) @@ -5938,7 +5952,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_b1b9aa8c9dfaad66, []int{86} + return fileDescriptor_rpc_e66000aa8614d793, []int{86} } func (m *Invoice) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Invoice.Unmarshal(m, b) @@ -6130,7 +6144,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_b1b9aa8c9dfaad66, []int{87} + return fileDescriptor_rpc_e66000aa8614d793, []int{87} } func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AddInvoiceResponse.Unmarshal(m, b) @@ -6187,7 +6201,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_b1b9aa8c9dfaad66, []int{88} + return fileDescriptor_rpc_e66000aa8614d793, []int{88} } func (m *PaymentHash) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PaymentHash.Unmarshal(m, b) @@ -6243,7 +6257,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_b1b9aa8c9dfaad66, []int{89} + return fileDescriptor_rpc_e66000aa8614d793, []int{89} } func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListInvoiceRequest.Unmarshal(m, b) @@ -6313,7 +6327,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_b1b9aa8c9dfaad66, []int{90} + return fileDescriptor_rpc_e66000aa8614d793, []int{90} } func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListInvoiceResponse.Unmarshal(m, b) @@ -6376,7 +6390,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_b1b9aa8c9dfaad66, []int{91} + return fileDescriptor_rpc_e66000aa8614d793, []int{91} } func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InvoiceSubscription.Unmarshal(m, b) @@ -6436,7 +6450,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_b1b9aa8c9dfaad66, []int{92} + return fileDescriptor_rpc_e66000aa8614d793, []int{92} } func (m *Payment) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Payment.Unmarshal(m, b) @@ -6523,7 +6537,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_b1b9aa8c9dfaad66, []int{93} + return fileDescriptor_rpc_e66000aa8614d793, []int{93} } func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPaymentsRequest.Unmarshal(m, b) @@ -6555,7 +6569,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_b1b9aa8c9dfaad66, []int{94} + return fileDescriptor_rpc_e66000aa8614d793, []int{94} } func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPaymentsResponse.Unmarshal(m, b) @@ -6592,7 +6606,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_b1b9aa8c9dfaad66, []int{95} + return fileDescriptor_rpc_e66000aa8614d793, []int{95} } func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DeleteAllPaymentsRequest.Unmarshal(m, b) @@ -6622,7 +6636,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_b1b9aa8c9dfaad66, []int{96} + return fileDescriptor_rpc_e66000aa8614d793, []int{96} } func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DeleteAllPaymentsResponse.Unmarshal(m, b) @@ -6653,7 +6667,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_b1b9aa8c9dfaad66, []int{97} + return fileDescriptor_rpc_e66000aa8614d793, []int{97} } func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AbandonChannelRequest.Unmarshal(m, b) @@ -6690,7 +6704,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_b1b9aa8c9dfaad66, []int{98} + return fileDescriptor_rpc_e66000aa8614d793, []int{98} } func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AbandonChannelResponse.Unmarshal(m, b) @@ -6722,7 +6736,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_b1b9aa8c9dfaad66, []int{99} + return fileDescriptor_rpc_e66000aa8614d793, []int{99} } func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DebugLevelRequest.Unmarshal(m, b) @@ -6767,7 +6781,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_b1b9aa8c9dfaad66, []int{100} + return fileDescriptor_rpc_e66000aa8614d793, []int{100} } func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DebugLevelResponse.Unmarshal(m, b) @@ -6806,7 +6820,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_b1b9aa8c9dfaad66, []int{101} + return fileDescriptor_rpc_e66000aa8614d793, []int{101} } func (m *PayReqString) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PayReqString.Unmarshal(m, b) @@ -6853,7 +6867,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_b1b9aa8c9dfaad66, []int{102} + return fileDescriptor_rpc_e66000aa8614d793, []int{102} } func (m *PayReq) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PayReq.Unmarshal(m, b) @@ -6953,7 +6967,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_b1b9aa8c9dfaad66, []int{103} + return fileDescriptor_rpc_e66000aa8614d793, []int{103} } func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeReportRequest.Unmarshal(m, b) @@ -6991,7 +7005,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_b1b9aa8c9dfaad66, []int{104} + return fileDescriptor_rpc_e66000aa8614d793, []int{104} } func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelFeeReport.Unmarshal(m, b) @@ -7057,7 +7071,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_b1b9aa8c9dfaad66, []int{105} + return fileDescriptor_rpc_e66000aa8614d793, []int{105} } func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeReportResponse.Unmarshal(m, b) @@ -7125,7 +7139,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_b1b9aa8c9dfaad66, []int{106} + return fileDescriptor_rpc_e66000aa8614d793, []int{106} } func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PolicyUpdateRequest.Unmarshal(m, b) @@ -7286,7 +7300,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_b1b9aa8c9dfaad66, []int{107} + return fileDescriptor_rpc_e66000aa8614d793, []int{107} } func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PolicyUpdateResponse.Unmarshal(m, b) @@ -7324,7 +7338,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_b1b9aa8c9dfaad66, []int{108} + return fileDescriptor_rpc_e66000aa8614d793, []int{108} } func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingHistoryRequest.Unmarshal(m, b) @@ -7396,7 +7410,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_b1b9aa8c9dfaad66, []int{109} + return fileDescriptor_rpc_e66000aa8614d793, []int{109} } func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingEvent.Unmarshal(m, b) @@ -7479,7 +7493,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_b1b9aa8c9dfaad66, []int{110} + return fileDescriptor_rpc_e66000aa8614d793, []int{110} } func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingHistoryResponse.Unmarshal(m, b) @@ -9909,428 +9923,430 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{ Metadata: "rpc.proto", } -func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_b1b9aa8c9dfaad66) } - -var fileDescriptor_rpc_b1b9aa8c9dfaad66 = []byte{ - // 6718 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7c, 0x5b, 0x6c, 0x24, 0xd9, - 0x59, 0xff, 0x54, 0xbb, 0xdb, 0xee, 0xfe, 0xba, 0xed, 0x6e, 0x1f, 0xdf, 0x7a, 0x7a, 0x67, 0x67, - 0x67, 0x4f, 0x26, 0x3b, 0x13, 0xff, 0xf7, 0x3f, 0x9e, 0x9d, 0x24, 0xcb, 0x66, 0x17, 0x02, 0x1e, - 0xdb, 0x33, 0x9e, 0xc4, 0x3b, 0xe3, 0x94, 0x67, 0x32, 0x64, 0x03, 0xea, 0x94, 0xbb, 0x8f, 0xdb, - 0x95, 0xe9, 0xae, 0xea, 0x54, 0x55, 0xdb, 0xd3, 0x59, 0x56, 0xe2, 0x26, 0x90, 0x10, 0x11, 0x02, - 0x5e, 0x08, 0x12, 0x42, 0x0a, 0x48, 0x24, 0x8f, 0xbc, 0x44, 0x48, 0xc0, 0x1b, 0x2f, 0x20, 0x21, - 0x84, 0xf2, 0x88, 0xc4, 0x0b, 0xbc, 0x00, 0x82, 0x07, 0x24, 0x1e, 0x78, 0x00, 0xa1, 0xf3, 0x9d, - 0x4b, 0x9d, 0x53, 0x55, 0x3d, 0x9e, 0x5c, 0xe0, 0xc9, 0x7d, 0x7e, 0xe7, 0xab, 0x73, 0xfd, 0x6e, - 0xe7, 0x3b, 0xdf, 0x31, 0xd4, 0xa2, 0x71, 0xef, 0xd6, 0x38, 0x0a, 0x93, 0x90, 0x54, 0x86, 0x41, - 0x34, 0xee, 0x75, 0xae, 0x0c, 0xc2, 0x70, 0x30, 0x64, 0x5b, 0xde, 0xd8, 0xdf, 0xf2, 0x82, 0x20, - 0x4c, 0xbc, 0xc4, 0x0f, 0x83, 0x58, 0x10, 0xd1, 0xaf, 0xc0, 0xd2, 0x7d, 0x16, 0x1c, 0x31, 0xd6, - 0x77, 0xd9, 0xd7, 0x26, 0x2c, 0x4e, 0xc8, 0xff, 0x83, 0x65, 0x8f, 0x7d, 0x9d, 0xb1, 0x7e, 0x77, - 0xec, 0xc5, 0xf1, 0xf8, 0x34, 0xf2, 0x62, 0xd6, 0x76, 0xae, 0x39, 0x37, 0x1b, 0x6e, 0x4b, 0x54, - 0x1c, 0x6a, 0x9c, 0xbc, 0x0e, 0x8d, 0x98, 0x93, 0xb2, 0x20, 0x89, 0xc2, 0xf1, 0xb4, 0x5d, 0x42, - 0xba, 0x3a, 0xc7, 0xf6, 0x04, 0x44, 0x87, 0xd0, 0xd4, 0x3d, 0xc4, 0xe3, 0x30, 0x88, 0x19, 0xb9, - 0x0d, 0xab, 0x3d, 0x7f, 0x7c, 0xca, 0xa2, 0x2e, 0x7e, 0x3c, 0x0a, 0xd8, 0x28, 0x0c, 0xfc, 0x5e, - 0xdb, 0xb9, 0x36, 0x77, 0xb3, 0xe6, 0x12, 0x51, 0xc7, 0xbf, 0x78, 0x5f, 0xd6, 0x90, 0x1b, 0xd0, - 0x64, 0x81, 0xc0, 0x59, 0x1f, 0xbf, 0x92, 0x5d, 0x2d, 0xa5, 0x30, 0xff, 0x80, 0xfe, 0x85, 0x03, - 0xcb, 0x0f, 0x02, 0x3f, 0x79, 0xea, 0x0d, 0x87, 0x2c, 0x51, 0x73, 0xba, 0x01, 0xcd, 0x73, 0x04, - 0x70, 0x4e, 0xe7, 0x61, 0xd4, 0x97, 0x33, 0x5a, 0x12, 0xf0, 0xa1, 0x44, 0x67, 0x8e, 0xac, 0x34, - 0x73, 0x64, 0x85, 0xcb, 0x35, 0x37, 0x63, 0xb9, 0x6e, 0x40, 0x33, 0x62, 0xbd, 0xf0, 0x8c, 0x45, - 0xd3, 0xee, 0xb9, 0x1f, 0xf4, 0xc3, 0xf3, 0x76, 0xf9, 0x9a, 0x73, 0xb3, 0xe2, 0x2e, 0x29, 0xf8, - 0x29, 0xa2, 0x74, 0x15, 0x88, 0x39, 0x0b, 0xb1, 0x6e, 0x74, 0x00, 0x2b, 0x4f, 0x82, 0x61, 0xd8, - 0x7b, 0xf6, 0x03, 0xce, 0xae, 0xa0, 0xfb, 0x52, 0x61, 0xf7, 0xeb, 0xb0, 0x6a, 0x77, 0x24, 0x07, - 0xc0, 0x60, 0x6d, 0xe7, 0xd4, 0x0b, 0x06, 0x4c, 0x35, 0xa9, 0x86, 0xf0, 0x09, 0x68, 0xf5, 0x26, - 0x51, 0xc4, 0x82, 0xdc, 0x18, 0x9a, 0x12, 0xd7, 0x83, 0x78, 0x1d, 0x1a, 0x01, 0x3b, 0x4f, 0xc9, - 0x24, 0xcb, 0x04, 0xec, 0x5c, 0x91, 0xd0, 0x36, 0xac, 0x67, 0xbb, 0x91, 0x03, 0xf8, 0x57, 0x07, - 0xca, 0x4f, 0x92, 0xe7, 0x21, 0xb9, 0x05, 0xe5, 0x64, 0x3a, 0x16, 0x8c, 0xb9, 0x74, 0x87, 0xdc, - 0x42, 0x5e, 0xbf, 0xb5, 0xdd, 0xef, 0x47, 0x2c, 0x8e, 0x1f, 0x4f, 0xc7, 0xcc, 0x6d, 0x78, 0xa2, - 0xd0, 0xe5, 0x74, 0xa4, 0x0d, 0x0b, 0xb2, 0x8c, 0x1d, 0xd6, 0x5c, 0x55, 0x24, 0x57, 0x01, 0xbc, - 0x51, 0x38, 0x09, 0x92, 0x6e, 0xec, 0x25, 0xb8, 0x73, 0x73, 0xae, 0x81, 0x90, 0xeb, 0xb0, 0x18, - 0xf7, 0x22, 0x7f, 0x9c, 0x74, 0xc7, 0x93, 0xe3, 0x67, 0x6c, 0x8a, 0x3b, 0x56, 0x73, 0x6d, 0x90, - 0x6c, 0x41, 0x35, 0x9c, 0x24, 0xe3, 0xd0, 0x0f, 0x92, 0x76, 0xe5, 0x9a, 0x73, 0xb3, 0x7e, 0x67, - 0x45, 0x8e, 0x89, 0xcf, 0x24, 0x60, 0xc3, 0x43, 0x5e, 0xe5, 0x6a, 0x22, 0xde, 0x6c, 0x2f, 0x0c, - 0x4e, 0xfc, 0x68, 0x24, 0xe4, 0xb1, 0x3d, 0x8f, 0x3d, 0xdb, 0x20, 0xfd, 0x66, 0x09, 0xea, 0x8f, - 0x23, 0x2f, 0x88, 0xbd, 0x1e, 0x07, 0xf8, 0x34, 0x92, 0xe7, 0xdd, 0x53, 0x2f, 0x3e, 0xc5, 0x99, - 0xd7, 0x5c, 0x55, 0x24, 0xeb, 0x30, 0x2f, 0x06, 0x8d, 0xf3, 0x9b, 0x73, 0x65, 0x89, 0xbc, 0x09, - 0xcb, 0xc1, 0x64, 0xd4, 0xb5, 0xfb, 0x9a, 0xc3, 0x5d, 0xcf, 0x57, 0xf0, 0xc5, 0x38, 0xe6, 0xfb, - 0x2e, 0xba, 0x10, 0x33, 0x35, 0x10, 0x42, 0xa1, 0x21, 0x4b, 0xcc, 0x1f, 0x9c, 0x8a, 0xa9, 0x56, - 0x5c, 0x0b, 0xe3, 0x6d, 0x24, 0xfe, 0x88, 0x75, 0xe3, 0xc4, 0x1b, 0x8d, 0xe5, 0xb4, 0x0c, 0x04, - 0xeb, 0xc3, 0xc4, 0x1b, 0x76, 0x4f, 0x18, 0x8b, 0xdb, 0x0b, 0xb2, 0x5e, 0x23, 0xe4, 0x0d, 0x58, - 0xea, 0xb3, 0x38, 0xe9, 0xca, 0x0d, 0x62, 0x71, 0xbb, 0x8a, 0xd2, 0x97, 0x41, 0x39, 0x97, 0xdc, - 0x67, 0x89, 0xb1, 0x3a, 0xb1, 0xe4, 0x46, 0x7a, 0x00, 0xc4, 0x80, 0x77, 0x59, 0xe2, 0xf9, 0xc3, - 0x98, 0xbc, 0x0d, 0x8d, 0xc4, 0x20, 0x46, 0x6d, 0x53, 0xd7, 0xac, 0x63, 0x7c, 0xe0, 0x5a, 0x74, - 0xf4, 0x3e, 0x54, 0xef, 0x31, 0x76, 0xe0, 0x8f, 0xfc, 0x84, 0xac, 0x43, 0xe5, 0xc4, 0x7f, 0xce, - 0x04, 0x73, 0xcf, 0xed, 0x5f, 0x72, 0x45, 0x91, 0x74, 0x60, 0x61, 0xcc, 0xa2, 0x1e, 0x53, 0xcb, - 0xbf, 0x7f, 0xc9, 0x55, 0xc0, 0xdd, 0x05, 0xa8, 0x0c, 0xf9, 0xc7, 0xf4, 0xdb, 0x25, 0xa8, 0x1f, - 0xb1, 0x40, 0x0b, 0x0d, 0x81, 0x32, 0x9f, 0x92, 0x14, 0x14, 0xfc, 0x4d, 0x5e, 0x83, 0x3a, 0x4e, - 0x33, 0x4e, 0x22, 0x3f, 0x18, 0x48, 0x5e, 0x05, 0x0e, 0x1d, 0x21, 0x42, 0x5a, 0x30, 0xe7, 0x8d, - 0x14, 0x9f, 0xf2, 0x9f, 0x5c, 0xa0, 0xc6, 0xde, 0x74, 0xc4, 0x65, 0x4f, 0xef, 0x5a, 0xc3, 0xad, - 0x4b, 0x6c, 0x9f, 0x6f, 0xdb, 0x2d, 0x58, 0x31, 0x49, 0x54, 0xeb, 0x15, 0x6c, 0x7d, 0xd9, 0xa0, - 0x94, 0x9d, 0xdc, 0x80, 0xa6, 0xa2, 0x8f, 0xc4, 0x60, 0x71, 0x1f, 0x6b, 0xee, 0x92, 0x84, 0xd5, - 0x14, 0x6e, 0x42, 0xeb, 0xc4, 0x0f, 0xbc, 0x61, 0xb7, 0x37, 0x4c, 0xce, 0xba, 0x7d, 0x36, 0x4c, - 0x3c, 0xdc, 0xd1, 0x8a, 0xbb, 0x84, 0xf8, 0xce, 0x30, 0x39, 0xdb, 0xe5, 0x28, 0x79, 0x13, 0x6a, - 0x27, 0x8c, 0x75, 0x71, 0x25, 0xda, 0x55, 0x94, 0x90, 0xa6, 0x5c, 0x7a, 0xb5, 0xba, 0x6e, 0xf5, - 0x44, 0xfe, 0xa2, 0x7f, 0xe2, 0x40, 0x43, 0x2c, 0x95, 0x34, 0x19, 0xd7, 0x61, 0x51, 0x8d, 0x88, - 0x45, 0x51, 0x18, 0x49, 0xf6, 0xb7, 0x41, 0xb2, 0x09, 0x2d, 0x05, 0x8c, 0x23, 0xe6, 0x8f, 0xbc, - 0x01, 0x93, 0xfa, 0x25, 0x87, 0x93, 0x3b, 0x69, 0x8b, 0x51, 0x38, 0x49, 0x84, 0xd2, 0xae, 0xdf, - 0x69, 0xc8, 0x41, 0xb9, 0x1c, 0x73, 0x6d, 0x12, 0xce, 0xfe, 0x05, 0x4b, 0x6d, 0x61, 0xf4, 0x1b, - 0x0e, 0x10, 0x3e, 0xf4, 0xc7, 0xa1, 0x68, 0x42, 0xae, 0x54, 0x76, 0x97, 0x9c, 0x97, 0xde, 0xa5, - 0xd2, 0xac, 0x5d, 0xba, 0x0e, 0xf3, 0x38, 0x2c, 0x2e, 0xcf, 0x73, 0xb9, 0xa1, 0xcb, 0x3a, 0xfa, - 0x2d, 0x07, 0x1a, 0xa6, 0x0e, 0x22, 0xb7, 0x81, 0x9c, 0x4c, 0x82, 0xbe, 0x1f, 0x0c, 0xba, 0xc9, - 0x73, 0xbf, 0xdf, 0x3d, 0x9e, 0xf2, 0x26, 0x70, 0x3c, 0xfb, 0x97, 0xdc, 0x82, 0x3a, 0xf2, 0x26, - 0xb4, 0x2c, 0x34, 0x4e, 0x22, 0x31, 0xaa, 0xfd, 0x4b, 0x6e, 0xae, 0x86, 0x2f, 0x12, 0xd7, 0x72, - 0x93, 0xa4, 0xeb, 0x07, 0x7d, 0xf6, 0x1c, 0xd7, 0x75, 0xd1, 0xb5, 0xb0, 0xbb, 0x4b, 0xd0, 0x30, - 0xbf, 0xa3, 0x9f, 0x85, 0xd6, 0x01, 0x57, 0x1e, 0x81, 0x1f, 0x0c, 0xa4, 0x12, 0xe7, 0x1a, 0x4d, - 0x6a, 0x5c, 0xb1, 0xd7, 0xb2, 0xc4, 0xc5, 0xe6, 0x34, 0x8c, 0x13, 0xb9, 0x2e, 0xf8, 0x9b, 0xfe, - 0x83, 0x03, 0x4d, 0xbe, 0xe8, 0xef, 0x7b, 0xc1, 0x54, 0xad, 0xf8, 0x01, 0x34, 0x78, 0x53, 0x8f, - 0xc3, 0x6d, 0xa1, 0x17, 0x85, 0xbc, 0xdf, 0x94, 0x8b, 0x94, 0xa1, 0xbe, 0x65, 0x92, 0x72, 0xd7, - 0x65, 0xea, 0x5a, 0x5f, 0x73, 0xc1, 0x4c, 0xbc, 0x68, 0xc0, 0x12, 0xd4, 0x98, 0x52, 0x83, 0x82, - 0x80, 0x76, 0xc2, 0xe0, 0x84, 0x5c, 0x83, 0x46, 0xec, 0x25, 0xdd, 0x31, 0x8b, 0x70, 0xd5, 0x50, - 0xb8, 0xe6, 0x5c, 0x88, 0xbd, 0xe4, 0x90, 0x45, 0x77, 0xa7, 0x09, 0xeb, 0xfc, 0x24, 0x2c, 0xe7, - 0x7a, 0xe1, 0xf2, 0x9c, 0x4e, 0x91, 0xff, 0x24, 0xab, 0x50, 0x39, 0xf3, 0x86, 0x13, 0x26, 0x15, - 0xb9, 0x28, 0xbc, 0x5b, 0x7a, 0xc7, 0xa1, 0x6f, 0x40, 0x2b, 0x1d, 0xb6, 0x14, 0x0c, 0x02, 0x65, - 0xbe, 0x82, 0xb2, 0x01, 0xfc, 0x4d, 0x7f, 0xc1, 0x11, 0x84, 0x3b, 0xa1, 0xaf, 0x95, 0x22, 0x27, - 0xe4, 0xba, 0x53, 0x11, 0xf2, 0xdf, 0x33, 0x8d, 0xc6, 0x0f, 0x3f, 0x59, 0x7a, 0x03, 0x96, 0x8d, - 0x21, 0xbc, 0x60, 0xb0, 0x0f, 0x81, 0x1c, 0xf8, 0x71, 0xf2, 0x24, 0x88, 0xc7, 0x86, 0x62, 0x79, - 0x05, 0x6a, 0x23, 0x3f, 0xc0, 0xee, 0x05, 0x6f, 0x56, 0xdc, 0xea, 0xc8, 0x0f, 0x78, 0xe7, 0x31, - 0x56, 0x7a, 0xcf, 0x65, 0x65, 0x49, 0x56, 0x7a, 0xcf, 0xb1, 0x92, 0xbe, 0x03, 0x2b, 0x56, 0x7b, - 0xb2, 0xeb, 0xd7, 0xa1, 0x32, 0x49, 0x9e, 0x87, 0x4a, 0xed, 0xd7, 0x25, 0x1b, 0x70, 0x67, 0xc2, - 0x15, 0x35, 0xf4, 0x3d, 0x58, 0x7e, 0xc8, 0xce, 0x25, 0xfb, 0xa9, 0x81, 0xbc, 0x71, 0xa1, 0xa3, - 0x81, 0xf5, 0xf4, 0x16, 0x10, 0xf3, 0x63, 0xd9, 0xab, 0xe1, 0x76, 0x38, 0x96, 0xdb, 0x41, 0xdf, - 0x00, 0x72, 0xe4, 0x0f, 0x82, 0xf7, 0x59, 0x1c, 0x7b, 0x03, 0xad, 0x25, 0x5a, 0x30, 0x37, 0x8a, - 0x07, 0x52, 0x39, 0xf0, 0x9f, 0xf4, 0x93, 0xb0, 0x62, 0xd1, 0xc9, 0x86, 0xaf, 0x40, 0x2d, 0xf6, - 0x07, 0x81, 0x97, 0x4c, 0x22, 0x26, 0x9b, 0x4e, 0x01, 0x7a, 0x0f, 0x56, 0xbf, 0xc8, 0x22, 0xff, - 0x64, 0x7a, 0x51, 0xf3, 0x76, 0x3b, 0xa5, 0x6c, 0x3b, 0x7b, 0xb0, 0x96, 0x69, 0x47, 0x76, 0x2f, - 0x78, 0x54, 0xee, 0x64, 0xd5, 0x15, 0x05, 0x43, 0x62, 0x4b, 0xa6, 0xc4, 0xd2, 0x27, 0x40, 0x76, - 0xc2, 0x20, 0x60, 0xbd, 0xe4, 0x90, 0xb1, 0x28, 0x3d, 0x68, 0xa4, 0x0c, 0x59, 0xbf, 0xb3, 0x21, - 0x57, 0x36, 0xab, 0x06, 0x24, 0xa7, 0x12, 0x28, 0x8f, 0x59, 0x34, 0xc2, 0x86, 0xab, 0x2e, 0xfe, - 0xa6, 0x6b, 0xb0, 0x62, 0x35, 0x2b, 0x7d, 0xc4, 0xb7, 0x60, 0x6d, 0xd7, 0x8f, 0x7b, 0xf9, 0x0e, - 0xdb, 0xb0, 0x30, 0x9e, 0x1c, 0x77, 0x53, 0x71, 0x53, 0x45, 0xee, 0x4a, 0x64, 0x3f, 0x91, 0x8d, - 0xfd, 0x8a, 0x03, 0xe5, 0xfd, 0xc7, 0x07, 0x3b, 0xa4, 0x03, 0x55, 0x3f, 0xe8, 0x85, 0x23, 0xae, - 0x91, 0xc5, 0xa4, 0x75, 0x79, 0xa6, 0x18, 0x5d, 0x81, 0x1a, 0x2a, 0x72, 0xee, 0x1d, 0xc9, 0x33, - 0x41, 0x0a, 0x70, 0xcf, 0x8c, 0x3d, 0x1f, 0xfb, 0x11, 0xba, 0x5e, 0xca, 0xa1, 0x2a, 0xa3, 0xb2, - 0xcc, 0x57, 0xd0, 0xff, 0x2e, 0xc3, 0x82, 0x54, 0xe3, 0xd8, 0x5f, 0x2f, 0xf1, 0xcf, 0x98, 0x1c, - 0x89, 0x2c, 0x71, 0x23, 0x19, 0xb1, 0x51, 0x98, 0xb0, 0xae, 0xb5, 0x0d, 0x36, 0x88, 0x9e, 0xa7, - 0x68, 0xa8, 0x2b, 0xfc, 0xd5, 0x39, 0x41, 0x65, 0x81, 0x7c, 0xb1, 0x38, 0xd0, 0xf5, 0xfb, 0x38, - 0xa6, 0xb2, 0xab, 0x8a, 0x7c, 0x25, 0x7a, 0xde, 0xd8, 0xeb, 0xf9, 0xc9, 0x54, 0xca, 0xbd, 0x2e, - 0xf3, 0xb6, 0x87, 0x61, 0xcf, 0x1b, 0x76, 0x8f, 0xbd, 0xa1, 0x17, 0xf4, 0x98, 0xf2, 0x6a, 0x2d, - 0x90, 0x7b, 0x78, 0x72, 0x48, 0x8a, 0x4c, 0x78, 0x81, 0x19, 0x94, 0x7b, 0x8a, 0xbd, 0x70, 0x34, - 0xf2, 0x13, 0xee, 0x18, 0xa2, 0xd3, 0x30, 0xe7, 0x1a, 0x88, 0xf0, 0xa1, 0xb1, 0x74, 0x2e, 0x56, - 0xaf, 0xa6, 0x7c, 0x68, 0x03, 0xe4, 0xad, 0x70, 0xcf, 0x83, 0xeb, 0xaa, 0x67, 0xe7, 0x6d, 0x10, - 0xad, 0xa4, 0x08, 0xdf, 0x87, 0x49, 0x10, 0xb3, 0x24, 0x19, 0xb2, 0xbe, 0x1e, 0x50, 0x1d, 0xc9, - 0xf2, 0x15, 0xe4, 0x36, 0xac, 0x08, 0x5f, 0x35, 0xf6, 0x92, 0x30, 0x3e, 0xf5, 0xe3, 0x6e, 0xcc, - 0xbd, 0xbe, 0x06, 0xd2, 0x17, 0x55, 0x91, 0x77, 0x60, 0x23, 0x03, 0x47, 0xac, 0xc7, 0xfc, 0x33, - 0xd6, 0x6f, 0x2f, 0xe2, 0x57, 0xb3, 0xaa, 0xc9, 0x35, 0xa8, 0x73, 0x17, 0x7d, 0x32, 0xee, 0x7b, - 0xdc, 0x44, 0x2f, 0xe1, 0x3e, 0x98, 0x10, 0x79, 0x0b, 0x16, 0xc7, 0x4c, 0xd8, 0xd1, 0xd3, 0x64, - 0xd8, 0x8b, 0xdb, 0x4d, 0x4b, 0xbb, 0x71, 0xce, 0x75, 0x6d, 0x0a, 0xce, 0x94, 0xbd, 0x18, 0x7d, - 0x35, 0x6f, 0xda, 0x6e, 0x21, 0xbb, 0xa5, 0x00, 0xca, 0x48, 0xe4, 0x9f, 0x79, 0x09, 0x6b, 0x2f, - 0x23, 0x6f, 0xa9, 0x22, 0xfd, 0x7d, 0x47, 0x28, 0x56, 0xc9, 0x84, 0x5a, 0x41, 0xbe, 0x06, 0x75, - 0xc1, 0x7e, 0xdd, 0x30, 0x18, 0x4e, 0x25, 0x47, 0x82, 0x80, 0x1e, 0x05, 0xc3, 0x29, 0xf9, 0x18, - 0x2c, 0xfa, 0x81, 0x49, 0x22, 0x64, 0xb8, 0xa1, 0x40, 0x24, 0x7a, 0x0d, 0xea, 0xe3, 0xc9, 0xf1, - 0xd0, 0xef, 0x09, 0x92, 0x39, 0xd1, 0x8a, 0x80, 0x90, 0x80, 0xfb, 0x4f, 0x62, 0x24, 0x82, 0xa2, - 0x8c, 0x14, 0x75, 0x89, 0x71, 0x12, 0x7a, 0x17, 0x56, 0xed, 0x01, 0x4a, 0x65, 0xb5, 0x09, 0x55, - 0xc9, 0xdb, 0x71, 0xbb, 0x8e, 0xeb, 0xb3, 0x64, 0x9f, 0xcd, 0x5c, 0x5d, 0x4f, 0xbf, 0x5b, 0x86, - 0x15, 0x89, 0xee, 0x0c, 0xc3, 0x98, 0x1d, 0x4d, 0x46, 0x23, 0x2f, 0x2a, 0x10, 0x1a, 0xe7, 0x02, - 0xa1, 0x29, 0xd9, 0x42, 0xc3, 0x59, 0xf9, 0xd4, 0xf3, 0x03, 0xe1, 0xfc, 0x09, 0x89, 0x33, 0x10, - 0x72, 0x13, 0x9a, 0xbd, 0x61, 0x18, 0x0b, 0x87, 0xc8, 0x3c, 0x7d, 0x65, 0xe1, 0xbc, 0x90, 0x57, - 0x8a, 0x84, 0xdc, 0x14, 0xd2, 0xf9, 0x8c, 0x90, 0x52, 0x68, 0xf0, 0x46, 0x99, 0xd2, 0x39, 0x0b, - 0xc2, 0x41, 0x33, 0x31, 0x3e, 0x9e, 0xac, 0x48, 0x08, 0xf9, 0x6b, 0x16, 0x09, 0x04, 0x3f, 0xdc, - 0x71, 0x9d, 0x66, 0x50, 0xd7, 0xa4, 0x40, 0xe4, 0xab, 0xc8, 0x3d, 0x00, 0xd1, 0x17, 0x1a, 0x56, - 0x40, 0xc3, 0xfa, 0x86, 0xbd, 0x23, 0xe6, 0xda, 0xdf, 0xe2, 0x85, 0x49, 0xc4, 0xd0, 0xd8, 0x1a, - 0x5f, 0xd2, 0x5f, 0x73, 0xa0, 0x6e, 0xd4, 0x91, 0x35, 0x58, 0xde, 0x79, 0xf4, 0xe8, 0x70, 0xcf, - 0xdd, 0x7e, 0xfc, 0xe0, 0x8b, 0x7b, 0xdd, 0x9d, 0x83, 0x47, 0x47, 0x7b, 0xad, 0x4b, 0x1c, 0x3e, - 0x78, 0xb4, 0xb3, 0x7d, 0xd0, 0xbd, 0xf7, 0xc8, 0xdd, 0x51, 0xb0, 0x43, 0xd6, 0x81, 0xb8, 0x7b, - 0xef, 0x3f, 0x7a, 0xbc, 0x67, 0xe1, 0x25, 0xd2, 0x82, 0xc6, 0x5d, 0x77, 0x6f, 0x7b, 0x67, 0x5f, - 0x22, 0x73, 0x64, 0x15, 0x5a, 0xf7, 0x9e, 0x3c, 0xdc, 0x7d, 0xf0, 0xf0, 0x7e, 0x77, 0x67, 0xfb, - 0xe1, 0xce, 0xde, 0xc1, 0xde, 0x6e, 0xab, 0x4c, 0x16, 0xa1, 0xb6, 0x7d, 0x77, 0xfb, 0xe1, 0xee, - 0xa3, 0x87, 0x7b, 0xbb, 0xad, 0x0a, 0xfd, 0x7b, 0x07, 0xd6, 0x70, 0xd4, 0xfd, 0xac, 0x80, 0x5c, - 0x83, 0x7a, 0x2f, 0x0c, 0xc7, 0x8c, 0xeb, 0x73, 0xad, 0xb2, 0x4d, 0x88, 0x33, 0xbf, 0x50, 0x90, - 0x27, 0x61, 0xd4, 0x63, 0x52, 0x3e, 0x00, 0xa1, 0x7b, 0x1c, 0xe1, 0xcc, 0x2f, 0xb7, 0x57, 0x50, - 0x08, 0xf1, 0xa8, 0x0b, 0x4c, 0x90, 0xac, 0xc3, 0xfc, 0x71, 0xc4, 0xbc, 0xde, 0xa9, 0x94, 0x0c, - 0x59, 0x22, 0x9f, 0x48, 0x7d, 0xf7, 0x1e, 0x5f, 0xfd, 0x21, 0xeb, 0x23, 0xc7, 0x54, 0xdd, 0xa6, - 0xc4, 0x77, 0x24, 0xcc, 0x35, 0x83, 0x77, 0xec, 0x05, 0xfd, 0x30, 0x60, 0x7d, 0x64, 0x9a, 0xaa, - 0x9b, 0x02, 0xf4, 0x10, 0xd6, 0xb3, 0xf3, 0x93, 0xf2, 0xf5, 0xb6, 0x21, 0x5f, 0xc2, 0xbb, 0xea, - 0xcc, 0xde, 0x4d, 0x43, 0xd6, 0xfe, 0xd9, 0x81, 0x32, 0x37, 0xb6, 0xb3, 0x0d, 0xb3, 0xe9, 0x3f, - 0xcd, 0xe5, 0xc2, 0x36, 0x78, 0x38, 0x11, 0xea, 0x57, 0x98, 0x28, 0x03, 0x49, 0xeb, 0x23, 0xd6, - 0x3b, 0xc3, 0x19, 0xeb, 0x7a, 0x8e, 0x70, 0x01, 0xe1, 0x1e, 0x2c, 0x7e, 0x2d, 0x05, 0x44, 0x95, - 0x55, 0x1d, 0x7e, 0xb9, 0x90, 0xd6, 0xe1, 0x77, 0x6d, 0x58, 0xf0, 0x83, 0xe3, 0x70, 0x12, 0xf4, - 0x51, 0x20, 0xaa, 0xae, 0x2a, 0xf2, 0xe5, 0x1b, 0xa3, 0xa0, 0xfa, 0x23, 0xc5, 0xfe, 0x29, 0x40, - 0x09, 0x3f, 0xe1, 0xc4, 0xe8, 0x5c, 0xe8, 0x38, 0xc5, 0xdb, 0xb0, 0x6c, 0x60, 0xa9, 0xa3, 0x3a, - 0xe6, 0x40, 0xc6, 0x51, 0x45, 0xaf, 0x44, 0xd4, 0xd0, 0x16, 0x2c, 0xdd, 0x67, 0xc9, 0x83, 0xe0, - 0x24, 0x54, 0x2d, 0xfd, 0x51, 0x19, 0x9a, 0x1a, 0x92, 0x0d, 0xdd, 0x84, 0xa6, 0xdf, 0x67, 0x41, - 0xe2, 0x27, 0xd3, 0xae, 0x75, 0x90, 0xca, 0xc2, 0xdc, 0x9b, 0xf3, 0x86, 0xbe, 0xa7, 0x42, 0x63, - 0xa2, 0x40, 0xee, 0xc0, 0x2a, 0x37, 0x35, 0xca, 0x7a, 0xe8, 0x2d, 0x16, 0xe7, 0xb9, 0xc2, 0x3a, - 0xae, 0x0c, 0x38, 0x2e, 0xb5, 0xbd, 0xfe, 0x44, 0x78, 0x35, 0x45, 0x55, 0x7c, 0xd5, 0x44, 0x4b, - 0x7c, 0xca, 0x15, 0x61, 0x8e, 0x34, 0x90, 0x8b, 0x37, 0xcd, 0x0b, 0x55, 0x95, 0x8d, 0x37, 0x19, - 0x31, 0xab, 0x6a, 0x2e, 0x66, 0xc5, 0x55, 0xd9, 0x34, 0xe8, 0xb1, 0x7e, 0x37, 0x09, 0xbb, 0xa8, - 0x72, 0x71, 0x77, 0xaa, 0x6e, 0x16, 0x26, 0x57, 0x60, 0x21, 0x61, 0x71, 0x12, 0xb0, 0x04, 0xb5, - 0x52, 0xf5, 0x6e, 0xa9, 0xed, 0xb8, 0x0a, 0xe2, 0x2e, 0xe8, 0x24, 0xf2, 0xe3, 0x76, 0x03, 0xa3, - 0x51, 0xf8, 0x9b, 0x7c, 0x0a, 0xd6, 0x8e, 0x59, 0x9c, 0x74, 0x4f, 0x99, 0xd7, 0x67, 0x11, 0xee, - 0xb4, 0x08, 0x7b, 0x09, 0xcb, 0x5e, 0x5c, 0xc9, 0x79, 0xe8, 0x8c, 0x45, 0xb1, 0x1f, 0x06, 0x68, - 0xd3, 0x6b, 0xae, 0x2a, 0xf2, 0xf6, 0xf8, 0xe4, 0xb5, 0xbd, 0xd4, 0x2b, 0xd8, 0xc4, 0x89, 0x17, - 0x57, 0x92, 0xeb, 0x30, 0x8f, 0x13, 0x88, 0xdb, 0x2d, 0x2b, 0x10, 0xb0, 0xc3, 0x41, 0x57, 0xd6, - 0x7d, 0xae, 0x5c, 0xad, 0xb7, 0x1a, 0xf4, 0xc7, 0xa0, 0x82, 0x30, 0xdf, 0x74, 0xb1, 0x18, 0x82, - 0x29, 0x44, 0x81, 0x0f, 0x2d, 0x60, 0xc9, 0x79, 0x18, 0x3d, 0x53, 0x71, 0x52, 0x59, 0xa4, 0x5f, - 0x47, 0x27, 0x5e, 0xc7, 0x0a, 0x9f, 0xa0, 0x07, 0xc2, 0x8f, 0x62, 0x62, 0xa9, 0xe3, 0x53, 0x4f, - 0x9e, 0x2b, 0xaa, 0x08, 0x1c, 0x9d, 0x7a, 0x5c, 0x6d, 0x59, 0xbb, 0x27, 0x8e, 0x6a, 0x75, 0xc4, - 0xf6, 0xc5, 0xe6, 0x5d, 0x87, 0x25, 0x15, 0x85, 0x8c, 0xbb, 0x43, 0x76, 0x92, 0xa8, 0x70, 0x41, - 0x30, 0x19, 0xe1, 0x79, 0xee, 0x80, 0x9d, 0x24, 0xf4, 0x21, 0x2c, 0x4b, 0x55, 0xf2, 0x68, 0xcc, - 0x54, 0xd7, 0x9f, 0x29, 0x32, 0xc9, 0x33, 0xe2, 0xae, 0x36, 0x25, 0x75, 0x81, 0x98, 0xaa, 0x49, - 0x36, 0x28, 0xed, 0xa2, 0x0a, 0x4a, 0xc8, 0xe9, 0x58, 0x18, 0x5f, 0x9f, 0x78, 0xd2, 0xeb, 0xa9, - 0x38, 0x72, 0xd5, 0x55, 0x45, 0xfa, 0x6d, 0x07, 0x56, 0xb0, 0x35, 0xe5, 0x54, 0x48, 0xf5, 0xff, - 0xce, 0xf7, 0x31, 0xcc, 0x46, 0xcf, 0x0c, 0xd4, 0xac, 0x42, 0xc5, 0x34, 0x08, 0xa2, 0xf0, 0xfd, - 0x9f, 0xcd, 0xcb, 0xb9, 0xb3, 0xf9, 0xef, 0x38, 0xb0, 0x2c, 0x74, 0x72, 0xe2, 0x25, 0x93, 0x58, - 0x4e, 0xff, 0xc7, 0x61, 0x51, 0x18, 0x57, 0x29, 0xd5, 0x72, 0xa0, 0xab, 0x5a, 0x01, 0x21, 0x2a, - 0x88, 0xf7, 0x2f, 0xb9, 0x36, 0x31, 0x79, 0x0f, 0x1d, 0x9c, 0xa0, 0x8b, 0xa8, 0x8c, 0xa5, 0x5d, - 0x2e, 0x30, 0x03, 0xfa, 0x7b, 0x83, 0xfc, 0x6e, 0x15, 0xe6, 0x85, 0x47, 0x4b, 0xef, 0xc3, 0xa2, - 0xd5, 0x91, 0x15, 0x32, 0x68, 0x88, 0x90, 0x41, 0x2e, 0xc2, 0x54, 0xca, 0x47, 0x98, 0xe8, 0x1f, - 0xcf, 0x01, 0xe1, 0xcc, 0x92, 0xd9, 0x0d, 0xee, 0x52, 0x87, 0x7d, 0xeb, 0x80, 0xd4, 0x70, 0x4d, - 0x88, 0xdc, 0x02, 0x62, 0x14, 0x55, 0x10, 0x4e, 0x58, 0x9f, 0x82, 0x1a, 0xae, 0x26, 0xa5, 0xf1, - 0x96, 0x66, 0x56, 0x1e, 0x05, 0xc5, 0xb2, 0x17, 0xd6, 0x71, 0x03, 0x33, 0x9e, 0xc4, 0xa7, 0x78, - 0xe3, 0x20, 0x8f, 0x50, 0xaa, 0x9c, 0xdd, 0xdf, 0xf9, 0x0b, 0xf7, 0x77, 0x21, 0xbb, 0xbf, 0xa6, - 0x13, 0x5f, 0xb5, 0x9c, 0x78, 0xee, 0x3c, 0x8e, 0xb8, 0xcb, 0x99, 0x0c, 0x7b, 0xdd, 0x11, 0xef, - 0x5d, 0x9e, 0x98, 0x2c, 0x90, 0x6c, 0x42, 0x4b, 0xba, 0x1b, 0xe9, 0x49, 0x01, 0x70, 0x8d, 0x73, - 0x38, 0xd7, 0xdf, 0x69, 0xa0, 0xa6, 0x8e, 0x83, 0x4d, 0x01, 0x7e, 0xb6, 0x8a, 0x39, 0x87, 0x74, - 0x27, 0x81, 0xbc, 0x68, 0x60, 0x7d, 0x3c, 0x2b, 0x55, 0xdd, 0x7c, 0x05, 0xfd, 0x2d, 0x07, 0x5a, - 0x7c, 0xcf, 0x2c, 0xb6, 0x7c, 0x17, 0x50, 0x2a, 0x5e, 0x92, 0x2b, 0x2d, 0x5a, 0xf2, 0x0e, 0xd4, - 0xb0, 0x1c, 0x8e, 0x59, 0x20, 0x79, 0xb2, 0x6d, 0xf3, 0x64, 0xaa, 0x4f, 0xf6, 0x2f, 0xb9, 0x29, - 0xb1, 0xc1, 0x91, 0x7f, 0xe3, 0x40, 0x5d, 0xf6, 0xf2, 0x03, 0x07, 0x02, 0x3a, 0xc6, 0xed, 0x90, - 0xe0, 0xa4, 0xf4, 0x22, 0xe8, 0x26, 0x34, 0x47, 0x5e, 0x32, 0x89, 0xb8, 0x3d, 0xb6, 0x82, 0x00, - 0x59, 0x98, 0x1b, 0x57, 0x54, 0x9d, 0x71, 0x37, 0xf1, 0x87, 0x5d, 0x55, 0x2b, 0xef, 0x60, 0x8a, - 0xaa, 0xb8, 0x06, 0x89, 0x13, 0x6f, 0xc0, 0xa4, 0xdd, 0x14, 0x05, 0xda, 0x86, 0x75, 0x39, 0xa1, - 0x8c, 0xab, 0x4a, 0xff, 0xbc, 0x01, 0x1b, 0xb9, 0x2a, 0x7d, 0x69, 0x2b, 0x4f, 0xb7, 0x43, 0x7f, - 0x74, 0x1c, 0x6a, 0x3f, 0xdf, 0x31, 0x0f, 0xbe, 0x56, 0x15, 0x19, 0xc0, 0x9a, 0x72, 0x10, 0xf8, - 0x9a, 0xa6, 0xc6, 0xac, 0x84, 0x56, 0xea, 0x2d, 0x7b, 0x0b, 0xb3, 0x1d, 0x2a, 0xdc, 0x14, 0xe2, - 0xe2, 0xf6, 0xc8, 0x29, 0xb4, 0xb5, 0x27, 0x22, 0x95, 0xb5, 0xe1, 0xad, 0xf0, 0xbe, 0xde, 0xbc, - 0xa0, 0x2f, 0xcb, 0xb3, 0x75, 0x67, 0xb6, 0x46, 0xa6, 0x70, 0x55, 0xd5, 0xa1, 0x36, 0xce, 0xf7, - 0x57, 0x7e, 0xa9, 0xb9, 0xa1, 0xcf, 0x6e, 0x77, 0x7a, 0x41, 0xc3, 0xe4, 0xab, 0xb0, 0x7e, 0xee, - 0xf9, 0x89, 0x1a, 0x96, 0xe1, 0x1b, 0x54, 0xb0, 0xcb, 0x3b, 0x17, 0x74, 0xf9, 0x54, 0x7c, 0x6c, - 0x99, 0xa8, 0x19, 0x2d, 0x76, 0xfe, 0xca, 0x81, 0x25, 0xbb, 0x1d, 0xce, 0xa6, 0x52, 0xf6, 0x95, - 0x0e, 0x54, 0xde, 0x64, 0x06, 0xce, 0x1f, 0x95, 0x4b, 0x45, 0x47, 0x65, 0xf3, 0x80, 0x3a, 0x77, - 0x51, 0x14, 0xa9, 0xfc, 0x72, 0x51, 0xa4, 0x4a, 0x51, 0x14, 0xa9, 0xf3, 0x1f, 0x0e, 0x90, 0x3c, - 0x2f, 0x91, 0xfb, 0xe2, 0xac, 0x1e, 0xb0, 0xa1, 0x54, 0x29, 0xff, 0xff, 0xe5, 0xf8, 0x51, 0xad, - 0x9d, 0xfa, 0x9a, 0x0b, 0x86, 0x79, 0x89, 0x6a, 0x3a, 0x3b, 0x8b, 0x6e, 0x51, 0x55, 0x26, 0xae, - 0x55, 0xbe, 0x38, 0xae, 0x55, 0xb9, 0x38, 0xae, 0x35, 0x9f, 0x8d, 0x6b, 0x75, 0x7e, 0xd9, 0x81, - 0x95, 0x82, 0x4d, 0xff, 0xd1, 0x4d, 0x9c, 0x6f, 0x93, 0xa5, 0x0b, 0x4a, 0x72, 0x9b, 0x4c, 0xb0, - 0xf3, 0x73, 0xb0, 0x68, 0x31, 0xfa, 0x8f, 0xae, 0xff, 0xac, 0xbf, 0x26, 0xf8, 0xcc, 0xc2, 0x3a, - 0xff, 0x52, 0x02, 0x92, 0x17, 0xb6, 0xff, 0xd3, 0x31, 0xe4, 0xd7, 0x69, 0xae, 0x60, 0x9d, 0xfe, - 0x57, 0xed, 0xc0, 0x9b, 0xb0, 0x2c, 0x33, 0x3c, 0x8c, 0x08, 0x8d, 0xe0, 0x98, 0x7c, 0x05, 0xf7, - 0x58, 0xed, 0xa0, 0x62, 0xd5, 0xba, 0x29, 0x37, 0x8c, 0x61, 0x26, 0xb6, 0x48, 0xd7, 0x61, 0x55, - 0x64, 0x8c, 0xdc, 0x15, 0x4d, 0x29, 0xbb, 0xf2, 0x7b, 0x0e, 0xac, 0x65, 0x2a, 0xd2, 0x7b, 0x5d, - 0x61, 0x3a, 0x6c, 0x7b, 0x62, 0x83, 0x7c, 0xfc, 0xda, 0x4b, 0xc8, 0x70, 0x5b, 0xbe, 0x82, 0xaf, - 0x8f, 0xe1, 0x55, 0x64, 0x56, 0xbd, 0xa8, 0x8a, 0x6e, 0x88, 0xbc, 0x96, 0x80, 0x0d, 0x33, 0x03, - 0x3f, 0x11, 0x99, 0x28, 0x66, 0x45, 0x7a, 0xb3, 0x63, 0x0f, 0x59, 0x15, 0xb9, 0x43, 0x68, 0x99, - 0x29, 0x7b, 0xbc, 0x85, 0x75, 0xf4, 0xbb, 0x0e, 0x90, 0x2f, 0x4c, 0x58, 0x34, 0xc5, 0xbb, 0x5b, - 0x1d, 0x3a, 0xda, 0xc8, 0x06, 0x46, 0xe6, 0xc7, 0x93, 0xe3, 0xcf, 0xb3, 0xa9, 0xca, 0x02, 0x28, - 0xa5, 0x59, 0x00, 0xaf, 0x02, 0xf0, 0x83, 0x94, 0xbe, 0x10, 0x46, 0x47, 0x2c, 0x98, 0x8c, 0x44, - 0x83, 0x85, 0x17, 0xf5, 0xe5, 0x8b, 0x2f, 0xea, 0x2b, 0x17, 0x5d, 0xd4, 0xbf, 0x07, 0x2b, 0xd6, - 0xb8, 0xf5, 0xb6, 0xaa, 0xab, 0x69, 0xe7, 0x05, 0x57, 0xd3, 0xbf, 0x5a, 0x82, 0xb9, 0xfd, 0x70, - 0x6c, 0x86, 0x4d, 0x1d, 0x3b, 0x6c, 0x2a, 0x6d, 0x49, 0x57, 0x9b, 0x0a, 0xa9, 0x62, 0x2c, 0x90, - 0x6c, 0xc2, 0x92, 0x37, 0x4a, 0xf8, 0x39, 0xfe, 0x24, 0x8c, 0xce, 0xbd, 0xa8, 0x2f, 0xf6, 0x1a, - 0x8f, 0xef, 0x99, 0x1a, 0xb2, 0x0a, 0x73, 0x5a, 0xe9, 0x22, 0x01, 0x2f, 0x72, 0xc7, 0x0d, 0xaf, - 0x5c, 0xa6, 0x32, 0x04, 0x21, 0x4b, 0x9c, 0x95, 0xec, 0xef, 0x85, 0xd7, 0x2c, 0x44, 0xa7, 0xa8, - 0x8a, 0xdb, 0x35, 0xbe, 0x7c, 0x48, 0x26, 0x63, 0x47, 0xaa, 0x6c, 0xc6, 0xb9, 0xaa, 0xf6, 0x05, - 0xd4, 0x3f, 0x39, 0x50, 0xc1, 0xb5, 0xe1, 0x6a, 0x40, 0xf0, 0xbe, 0x8e, 0x9c, 0xe2, 0x9a, 0x2c, - 0xba, 0x59, 0x98, 0x50, 0x2b, 0x8f, 0xa6, 0xa4, 0x27, 0x64, 0xe6, 0xd2, 0x5c, 0x83, 0x9a, 0x28, - 0xe9, 0x9c, 0x11, 0x24, 0x49, 0x41, 0x72, 0x15, 0xca, 0xa7, 0xe1, 0x58, 0xf9, 0x2d, 0xa0, 0x2e, - 0x0e, 0xc2, 0xb1, 0x8b, 0x78, 0x3a, 0x1e, 0xde, 0x9e, 0x98, 0x96, 0xb0, 0x46, 0x59, 0x98, 0xdb, - 0x63, 0xdd, 0xac, 0xb9, 0x4c, 0x19, 0x94, 0x6e, 0x42, 0xf3, 0x61, 0xd8, 0x67, 0x46, 0xf8, 0x6a, - 0x26, 0x9f, 0xd3, 0x9f, 0x77, 0xa0, 0xaa, 0x88, 0xc9, 0x4d, 0x28, 0x73, 0x27, 0x23, 0x73, 0x02, - 0xd0, 0x17, 0x86, 0x9c, 0xce, 0x45, 0x0a, 0xae, 0x95, 0x31, 0xaa, 0x90, 0x3a, 0x9c, 0x2a, 0xa6, - 0x90, 0xfa, 0x53, 0x7a, 0xb8, 0x19, 0x37, 0x24, 0x83, 0xd2, 0xef, 0x38, 0xb0, 0x68, 0xf5, 0xc1, - 0xcf, 0x90, 0x43, 0x2f, 0x4e, 0xe4, 0x25, 0x8c, 0xdc, 0x1e, 0x13, 0x32, 0x37, 0xba, 0x64, 0x07, - 0x34, 0x75, 0xa8, 0x6d, 0xce, 0x0c, 0xb5, 0xdd, 0x86, 0x5a, 0x9a, 0xed, 0x54, 0xb6, 0xb4, 0x2d, - 0xef, 0x51, 0x5d, 0x85, 0xa6, 0x44, 0x18, 0xbd, 0x09, 0x87, 0x61, 0x24, 0xa3, 0xff, 0xa2, 0x40, - 0xdf, 0x83, 0xba, 0x41, 0x6f, 0x06, 0x73, 0x1c, 0x2b, 0x98, 0xa3, 0x93, 0x01, 0x4a, 0x69, 0x32, - 0x00, 0xfd, 0x4b, 0x07, 0x16, 0x39, 0x0f, 0xfa, 0xc1, 0xe0, 0x30, 0x1c, 0xfa, 0xbd, 0x29, 0xee, - 0xbd, 0x62, 0x37, 0xa9, 0x33, 0x14, 0x2f, 0xda, 0x30, 0xe7, 0x7a, 0x75, 0x84, 0x94, 0x22, 0xaa, - 0xcb, 0x5c, 0x86, 0xb9, 0x04, 0x1c, 0x7b, 0xb1, 0x14, 0x0b, 0x69, 0xfe, 0x2c, 0x90, 0x4b, 0x1a, - 0x07, 0x22, 0x2f, 0x61, 0xdd, 0x91, 0x3f, 0x1c, 0xfa, 0x82, 0x56, 0x38, 0x47, 0x45, 0x55, 0xbc, - 0xcf, 0xbe, 0x1f, 0x7b, 0xc7, 0x69, 0x44, 0x5b, 0x97, 0xe9, 0x9f, 0x96, 0xa0, 0x2e, 0x15, 0xf7, - 0x5e, 0x7f, 0xc0, 0xe4, 0xf5, 0x0b, 0xba, 0x9f, 0x5a, 0xc9, 0x18, 0x88, 0xaa, 0xb7, 0x1c, 0x56, - 0x03, 0xc9, 0x6e, 0xf9, 0x5c, 0x7e, 0xcb, 0xaf, 0x40, 0x8d, 0xb3, 0xde, 0x5b, 0xe8, 0x19, 0x8b, - 0xab, 0x9b, 0x14, 0x50, 0xb5, 0x77, 0xb0, 0xb6, 0x92, 0xd6, 0x22, 0xf0, 0xc2, 0xcb, 0x9a, 0x77, - 0xa0, 0x21, 0x9b, 0xc1, 0x3d, 0x41, 0x9d, 0x92, 0x32, 0xbf, 0xb5, 0x5f, 0xae, 0x45, 0xa9, 0xbe, - 0xbc, 0xa3, 0xbe, 0xac, 0x5e, 0xf4, 0xa5, 0xa2, 0xa4, 0xf7, 0xf5, 0x1d, 0xd8, 0xfd, 0xc8, 0x1b, - 0x9f, 0x2a, 0x29, 0xbd, 0x0d, 0x2b, 0x7e, 0xd0, 0x1b, 0x4e, 0xfa, 0xac, 0x3b, 0x09, 0xbc, 0x20, - 0x08, 0x27, 0x41, 0x8f, 0xa9, 0x14, 0x80, 0xa2, 0x2a, 0xda, 0xd7, 0xa9, 0x47, 0xd8, 0x10, 0xd9, - 0x84, 0x0a, 0xef, 0x48, 0x59, 0x85, 0x62, 0x11, 0x16, 0x24, 0xe4, 0x26, 0x54, 0x58, 0x7f, 0xc0, - 0xd4, 0x69, 0x91, 0xd8, 0xe7, 0x76, 0xbe, 0xab, 0xae, 0x20, 0xe0, 0x0a, 0x85, 0xa3, 0x19, 0x85, - 0x62, 0x5b, 0x94, 0x79, 0x5e, 0x7c, 0xd0, 0xa7, 0xab, 0x40, 0x1e, 0x0a, 0x19, 0x30, 0xc3, 0xe7, - 0xbf, 0x34, 0x07, 0x75, 0x03, 0xe6, 0xba, 0x61, 0xc0, 0x07, 0xdc, 0xed, 0xfb, 0xde, 0x88, 0x25, - 0x2c, 0x92, 0x7c, 0x9f, 0x41, 0x39, 0x9d, 0x77, 0x36, 0xe8, 0x86, 0x93, 0xa4, 0xdb, 0x67, 0x83, - 0x88, 0x09, 0x23, 0xcf, 0x8d, 0x8e, 0x85, 0x72, 0xba, 0x91, 0xf7, 0xdc, 0xa4, 0x13, 0x1c, 0x94, - 0x41, 0x55, 0x30, 0x5c, 0xac, 0x51, 0x39, 0x0d, 0x86, 0x8b, 0x15, 0xc9, 0x6a, 0xb5, 0x4a, 0x81, - 0x56, 0x7b, 0x1b, 0xd6, 0x85, 0xfe, 0x92, 0x92, 0xde, 0xcd, 0x30, 0xd6, 0x8c, 0x5a, 0xb2, 0x09, - 0x2d, 0x3e, 0x66, 0x25, 0x12, 0xb1, 0xff, 0x75, 0x11, 0x58, 0x72, 0xdc, 0x1c, 0xce, 0x69, 0x31, - 0xc2, 0x63, 0xd2, 0x8a, 0xcb, 0xc1, 0x1c, 0x8e, 0xb4, 0xde, 0x73, 0x9b, 0xb6, 0x26, 0x69, 0x33, - 0x38, 0x5d, 0x84, 0xfa, 0x51, 0x12, 0x8e, 0xd5, 0xa6, 0x2c, 0x41, 0x43, 0x14, 0x65, 0x2a, 0xc6, - 0x2b, 0x70, 0x19, 0xb9, 0xe8, 0x71, 0x38, 0x0e, 0x87, 0xe1, 0x60, 0x7a, 0x34, 0x39, 0x16, 0x39, - 0xb8, 0x7e, 0x18, 0xd0, 0xbf, 0x76, 0x60, 0xc5, 0xaa, 0x95, 0xd1, 0xa3, 0x4f, 0x09, 0x21, 0xd0, - 0x77, 0xe8, 0x82, 0xf1, 0x96, 0x0d, 0xe5, 0x2a, 0x08, 0x45, 0x0c, 0xf0, 0x89, 0xbc, 0x56, 0xdf, - 0x86, 0xa6, 0x1a, 0x99, 0xfa, 0x50, 0x70, 0x61, 0x3b, 0xcf, 0x85, 0xf2, 0xfb, 0x25, 0xf9, 0x81, - 0x6a, 0xe2, 0x27, 0xe4, 0x25, 0x6b, 0x1f, 0xe7, 0xa8, 0xe2, 0x10, 0xfa, 0x62, 0xcc, 0x3c, 0x8d, - 0xa8, 0x11, 0xf4, 0x34, 0x18, 0xd3, 0x5f, 0x77, 0x00, 0xd2, 0xd1, 0xe1, 0xd5, 0x9c, 0x36, 0x10, - 0x22, 0x4d, 0xde, 0x30, 0x06, 0xaf, 0x43, 0x43, 0x5f, 0xe9, 0xa4, 0x36, 0xa7, 0xae, 0x30, 0xee, - 0x30, 0xde, 0x80, 0xe6, 0x60, 0x18, 0x1e, 0xa3, 0xc1, 0xc6, 0xdc, 0x9e, 0x58, 0x26, 0xa4, 0x2c, - 0x09, 0xf8, 0x9e, 0x44, 0x53, 0x03, 0x55, 0x36, 0x0c, 0x14, 0xfd, 0x46, 0x49, 0x47, 0xe0, 0xd3, - 0x39, 0xcf, 0x94, 0x32, 0x72, 0x27, 0xa7, 0x4e, 0x67, 0x04, 0xbc, 0x31, 0xe2, 0x76, 0x78, 0x61, - 0x40, 0xe0, 0x3d, 0x58, 0x8a, 0x84, 0xbe, 0x52, 0xca, 0xac, 0xfc, 0x02, 0x65, 0xb6, 0x18, 0x59, - 0x56, 0xec, 0x13, 0xd0, 0xf2, 0xfa, 0x67, 0x2c, 0x4a, 0x7c, 0x3c, 0x92, 0xa1, 0x0b, 0x21, 0x54, - 0x70, 0xd3, 0xc0, 0xd1, 0xb2, 0xdf, 0x80, 0xa6, 0x4c, 0x02, 0xd2, 0x94, 0x32, 0xef, 0x35, 0x85, - 0x39, 0x21, 0xfd, 0x03, 0x15, 0xec, 0xb7, 0xf7, 0x70, 0xf6, 0x8a, 0x98, 0xb3, 0x2b, 0x65, 0x66, - 0xf7, 0x31, 0x19, 0x78, 0xef, 0xab, 0x73, 0xdf, 0x9c, 0x71, 0x21, 0xdf, 0x97, 0x17, 0x25, 0xf6, - 0x92, 0x96, 0x5f, 0x66, 0x49, 0xe9, 0xf7, 0x1c, 0x58, 0xd8, 0x0f, 0xc7, 0xfb, 0x32, 0x35, 0x01, - 0x05, 0x41, 0x67, 0xdf, 0xa9, 0xe2, 0x0b, 0x92, 0x16, 0x0a, 0x2d, 0xf7, 0x62, 0xd6, 0x72, 0xff, - 0x14, 0xbc, 0x82, 0x51, 0x87, 0x28, 0x1c, 0x87, 0x11, 0x17, 0x46, 0x6f, 0x28, 0xcc, 0x74, 0x18, - 0x24, 0xa7, 0x4a, 0x8d, 0xbd, 0x88, 0x04, 0x8f, 0x77, 0xfc, 0x58, 0x22, 0x9c, 0x6e, 0xe9, 0x69, - 0x08, 0xed, 0x96, 0xaf, 0xa0, 0x9f, 0x81, 0x1a, 0xba, 0xca, 0x38, 0xad, 0x37, 0xa1, 0x76, 0x1a, - 0x8e, 0xbb, 0xa7, 0x7e, 0x90, 0x28, 0xe1, 0x5e, 0x4a, 0x7d, 0xd8, 0x7d, 0x5c, 0x10, 0x4d, 0x40, - 0xff, 0xb3, 0x02, 0x0b, 0x0f, 0x82, 0xb3, 0xd0, 0xef, 0xe1, 0xc5, 0xc2, 0x88, 0x8d, 0x42, 0x95, - 0x8b, 0xc8, 0x7f, 0x93, 0x2b, 0xb0, 0x80, 0xc9, 0x37, 0x63, 0xc1, 0xb4, 0x0d, 0x71, 0x01, 0x28, - 0x21, 0xee, 0x24, 0x44, 0x69, 0x5e, 0xb1, 0x10, 0x1f, 0x03, 0xe1, 0x87, 0x88, 0xc8, 0xcc, 0x0b, - 0x96, 0xa5, 0x34, 0xa1, 0xb3, 0x62, 0x24, 0x74, 0xf2, 0xbe, 0x64, 0x2a, 0x85, 0xb8, 0x6b, 0x17, - 0x7d, 0x49, 0x08, 0x0f, 0x3e, 0x11, 0x13, 0x51, 0x23, 0x74, 0x39, 0x16, 0xe4, 0xc1, 0xc7, 0x04, - 0xb9, 0x5b, 0x22, 0x3e, 0x10, 0x34, 0x42, 0x09, 0x9b, 0x10, 0x77, 0xe1, 0xb2, 0x99, 0xdc, 0x35, - 0xc1, 0xfb, 0x19, 0x98, 0x6b, 0xea, 0x3e, 0xd3, 0x0a, 0x55, 0xcc, 0x03, 0x44, 0xee, 0x74, 0x16, - 0x37, 0x8e, 0x4b, 0x22, 0x4f, 0x4a, 0x1d, 0x97, 0x38, 0xc3, 0x78, 0xc3, 0xe1, 0xb1, 0xd7, 0x7b, - 0x86, 0x89, 0xfa, 0x18, 0xea, 0xaf, 0xb9, 0x36, 0x88, 0x09, 0x11, 0xe9, 0xae, 0xe2, 0x55, 0x69, - 0xd9, 0x35, 0x21, 0x72, 0x07, 0xea, 0x78, 0x44, 0x94, 0xfb, 0xba, 0x84, 0xfb, 0xda, 0x32, 0xcf, - 0x90, 0xb8, 0xb3, 0x26, 0x91, 0x79, 0xe9, 0xd1, 0xb4, 0x2f, 0x3d, 0x84, 0xf2, 0x94, 0x77, 0x45, - 0x2d, 0xec, 0x2d, 0x05, 0xb8, 0x55, 0x95, 0x0b, 0x26, 0x08, 0x96, 0x91, 0xc0, 0xc2, 0xc8, 0x55, - 0xa8, 0xf2, 0xe3, 0xcb, 0xd8, 0xf3, 0xfb, 0x6d, 0xa2, 0x4f, 0x51, 0x1a, 0xe3, 0x6d, 0xa8, 0xdf, - 0x78, 0xa7, 0xb3, 0x82, 0xab, 0x62, 0x61, 0x7c, 0x6d, 0x74, 0x19, 0x85, 0x69, 0x55, 0xec, 0xa8, - 0x05, 0x92, 0xb7, 0x30, 0x62, 0x9f, 0xb0, 0xf6, 0x1a, 0xa6, 0xc5, 0xbc, 0x22, 0xe7, 0x2c, 0x99, - 0x56, 0xfd, 0x3d, 0xe2, 0x24, 0xae, 0xa0, 0xa4, 0x1f, 0x87, 0x86, 0x09, 0x93, 0x2a, 0x94, 0x1f, - 0x1d, 0xee, 0x3d, 0x6c, 0x5d, 0x22, 0x75, 0x58, 0x38, 0xda, 0x7b, 0xfc, 0xf8, 0x60, 0x6f, 0xb7, - 0xe5, 0xd0, 0x04, 0xc8, 0x76, 0xbf, 0x2f, 0x29, 0xf5, 0x41, 0x3d, 0xe5, 0x59, 0xc7, 0xe2, 0xd9, - 0x02, 0xbe, 0x29, 0x15, 0xf3, 0xcd, 0x0b, 0x57, 0x97, 0xee, 0x41, 0xfd, 0xd0, 0x48, 0x71, 0x47, - 0x11, 0x52, 0xc9, 0xed, 0x52, 0xf4, 0x0c, 0xc4, 0x18, 0x4e, 0xc9, 0x1c, 0x0e, 0xfd, 0x43, 0x47, - 0x64, 0x09, 0xeb, 0xe1, 0x8b, 0xbe, 0x29, 0x34, 0x74, 0x38, 0x25, 0x4d, 0x3e, 0xb3, 0x30, 0x4e, - 0x83, 0x43, 0xe9, 0x86, 0x27, 0x27, 0x31, 0x53, 0xa9, 0x22, 0x16, 0xc6, 0x79, 0x9f, 0x7b, 0x51, - 0xdc, 0x23, 0xf1, 0x45, 0x0f, 0xb1, 0x4c, 0x19, 0xc9, 0xe1, 0x5c, 0x93, 0x47, 0xec, 0x8c, 0x45, - 0xb1, 0x4e, 0x92, 0xd1, 0x65, 0x9d, 0x23, 0x97, 0x5d, 0xe5, 0x4d, 0xa8, 0xea, 0x76, 0x6d, 0x25, - 0xa5, 0x28, 0x75, 0x3d, 0x57, 0x86, 0x78, 0xae, 0xb0, 0x06, 0x2d, 0x14, 0x73, 0xbe, 0x82, 0xdc, - 0x02, 0x72, 0xe2, 0x47, 0x59, 0xf2, 0x39, 0x24, 0x2f, 0xa8, 0xa1, 0x4f, 0x61, 0x45, 0x31, 0x8b, - 0xe1, 0x3e, 0xd9, 0x9b, 0xe8, 0x5c, 0x24, 0x22, 0xa5, 0xbc, 0x88, 0xd0, 0xff, 0x72, 0x60, 0x41, - 0xee, 0x74, 0xee, 0x99, 0x84, 0xd8, 0x67, 0x0b, 0x23, 0x6d, 0x2b, 0xcb, 0x1d, 0xe5, 0x49, 0x2a, - 0xc6, 0x9c, 0xea, 0x9b, 0x2b, 0x52, 0x7d, 0x04, 0xca, 0x63, 0x2f, 0x39, 0xc5, 0xd3, 0x72, 0xcd, - 0xc5, 0xdf, 0xa4, 0x25, 0x62, 0x3b, 0x42, 0xcd, 0x62, 0x5c, 0xa7, 0xe8, 0x41, 0x88, 0xb0, 0xe8, - 0xf9, 0x07, 0x21, 0x57, 0xa0, 0x86, 0x03, 0xe8, 0xa6, 0xa1, 0x9b, 0x14, 0xe0, 0x9c, 0x2b, 0x0a, - 0x28, 0xbb, 0x32, 0x17, 0x35, 0x45, 0xe8, 0x9a, 0xd8, 0x79, 0xb9, 0x04, 0xfa, 0x46, 0x4d, 0xe6, - 0x24, 0xa6, 0x70, 0xca, 0x11, 0x72, 0x00, 0x59, 0x8e, 0x90, 0xa4, 0xae, 0xae, 0xa7, 0x1d, 0x68, - 0xef, 0xb2, 0x21, 0x4b, 0xd8, 0xf6, 0x70, 0x98, 0x6d, 0xff, 0x15, 0xb8, 0x5c, 0x50, 0x27, 0x3d, - 0xe6, 0x2f, 0xc0, 0xda, 0xb6, 0xc8, 0xdf, 0xfa, 0x51, 0xe5, 0x24, 0xd0, 0x36, 0xac, 0x67, 0x9b, - 0x94, 0x9d, 0xdd, 0x83, 0xe5, 0x5d, 0x76, 0x3c, 0x19, 0x1c, 0xb0, 0xb3, 0xb4, 0x23, 0x02, 0xe5, - 0xf8, 0x34, 0x3c, 0x97, 0x82, 0x89, 0xbf, 0xc9, 0xab, 0x00, 0x43, 0x4e, 0xd3, 0x8d, 0xc7, 0xac, - 0xa7, 0x72, 0xce, 0x11, 0x39, 0x1a, 0xb3, 0x1e, 0x7d, 0x1b, 0x88, 0xd9, 0x8e, 0x5c, 0x2f, 0x6e, - 0xe9, 0x26, 0xc7, 0xdd, 0x78, 0x1a, 0x27, 0x6c, 0xa4, 0x92, 0xe9, 0x4d, 0x88, 0xde, 0x80, 0xc6, - 0xa1, 0x37, 0x75, 0xd9, 0xd7, 0xe4, 0xeb, 0x98, 0x0d, 0x58, 0x18, 0x7b, 0x53, 0xae, 0xa6, 0x74, - 0x4c, 0x09, 0xab, 0xe9, 0xbf, 0x97, 0x60, 0x5e, 0x50, 0xf2, 0x56, 0xfb, 0x2c, 0x4e, 0xfc, 0x00, - 0x19, 0x4b, 0xb5, 0x6a, 0x40, 0x39, 0x56, 0x2e, 0x15, 0xb0, 0xb2, 0x3c, 0x97, 0xa9, 0xfc, 0x5d, - 0xc9, 0xaf, 0x16, 0xc6, 0x99, 0x2b, 0x4d, 0x0e, 0x12, 0x41, 0x8d, 0x14, 0xc8, 0x84, 0x1f, 0x53, - 0x7b, 0x2a, 0xc6, 0xa7, 0xa4, 0x54, 0x72, 0xae, 0x09, 0x15, 0x5a, 0xed, 0x05, 0xc1, 0xe0, 0x39, - 0xab, 0x9d, 0xb3, 0xce, 0xd5, 0x97, 0xb0, 0xce, 0xe2, 0xb0, 0xf6, 0x22, 0xeb, 0x0c, 0x2f, 0x61, - 0x9d, 0x29, 0x81, 0xd6, 0x3d, 0xc6, 0x5c, 0xc6, 0xfd, 0x3f, 0xc5, 0xbb, 0xdf, 0x74, 0xa0, 0x25, - 0xb9, 0x48, 0xd7, 0x91, 0xd7, 0x2d, 0x3f, 0xb7, 0x30, 0xcb, 0xf6, 0x3a, 0x2c, 0xa2, 0xf7, 0xa9, - 0xe3, 0xac, 0x32, 0x28, 0x6c, 0x81, 0x7c, 0x1e, 0xea, 0x32, 0x6c, 0xe4, 0x0f, 0xe5, 0xa6, 0x98, - 0x90, 0x0a, 0xd5, 0x46, 0x9e, 0x4c, 0x92, 0x71, 0x5c, 0x5d, 0xa6, 0x7f, 0xe6, 0xc0, 0xb2, 0x31, - 0x60, 0xc9, 0x85, 0xef, 0x81, 0x92, 0x06, 0x11, 0x74, 0x15, 0x92, 0xbb, 0x61, 0x8b, 0x4d, 0xfa, - 0x99, 0x45, 0x8c, 0x9b, 0xe9, 0x4d, 0x71, 0x80, 0xf1, 0x64, 0x24, 0x95, 0xa8, 0x09, 0x71, 0x46, - 0x3a, 0x67, 0xec, 0x99, 0x26, 0x11, 0x6a, 0xdc, 0xc2, 0x30, 0x83, 0x83, 0x7b, 0xcd, 0x9a, 0x48, - 0xd8, 0x33, 0x1b, 0xa4, 0x7f, 0xe7, 0xc0, 0x8a, 0x38, 0xfe, 0xc8, 0xc3, 0xa5, 0x7e, 0x02, 0x31, - 0x2f, 0xce, 0x7b, 0x42, 0x22, 0xf7, 0x2f, 0xb9, 0xb2, 0x4c, 0x3e, 0xfd, 0x92, 0x47, 0x36, 0x9d, - 0xb9, 0x33, 0x63, 0x2f, 0xe6, 0x8a, 0xf6, 0xe2, 0x05, 0x2b, 0x5d, 0x14, 0x64, 0xac, 0x14, 0x06, - 0x19, 0xef, 0x2e, 0x40, 0x25, 0xee, 0x85, 0x63, 0x46, 0xd7, 0x61, 0xd5, 0x9e, 0x9c, 0x54, 0x41, - 0xdf, 0x72, 0xa0, 0x7d, 0x4f, 0x04, 0xe3, 0xfd, 0x60, 0xb0, 0xef, 0xc7, 0x49, 0x18, 0xe9, 0xe7, - 0x60, 0x57, 0x01, 0xe2, 0xc4, 0x8b, 0x12, 0x91, 0x9f, 0x29, 0x43, 0x80, 0x29, 0xc2, 0xc7, 0xc8, - 0x82, 0xbe, 0xa8, 0x15, 0x7b, 0xa3, 0xcb, 0x39, 0x1f, 0x42, 0x1e, 0xd0, 0x2c, 0x4b, 0xfc, 0x86, - 0xc8, 0x64, 0xe3, 0xbe, 0x02, 0x3b, 0x43, 0xbd, 0x2e, 0x4e, 0x3e, 0x19, 0x94, 0xfe, 0xad, 0x03, - 0xcd, 0x74, 0x90, 0x7b, 0x1c, 0xb4, 0xb5, 0x83, 0x34, 0xbf, 0xa9, 0x76, 0x50, 0xc1, 0x49, 0x9f, - 0xdb, 0x63, 0x39, 0x36, 0x03, 0x41, 0x89, 0x95, 0xa5, 0x70, 0xa2, 0x1c, 0x1c, 0x13, 0x12, 0x79, - 0x29, 0xdc, 0x13, 0x90, 0x5e, 0x8d, 0x2c, 0x61, 0x7a, 0xed, 0x28, 0xc1, 0xaf, 0xe6, 0xc5, 0xd1, - 0x4f, 0x16, 0x95, 0x29, 0x5d, 0x40, 0x14, 0x4d, 0xa9, 0x79, 0xb1, 0x51, 0x15, 0xeb, 0xa3, 0xca, - 0xf4, 0x37, 0x1c, 0xb8, 0x5c, 0xb0, 0xf0, 0x52, 0x6a, 0x76, 0x61, 0xf9, 0x44, 0x57, 0xaa, 0xc5, - 0x11, 0xa2, 0xb3, 0xae, 0x6e, 0x96, 0xec, 0x05, 0x71, 0xf3, 0x1f, 0x68, 0xbf, 0x48, 0x2c, 0xb7, - 0x95, 0xf9, 0x95, 0xaf, 0xd8, 0xfc, 0x2c, 0xd4, 0x8d, 0x37, 0x5a, 0x64, 0x03, 0x56, 0x9e, 0x3e, - 0x78, 0xfc, 0x70, 0xef, 0xe8, 0xa8, 0x7b, 0xf8, 0xe4, 0xee, 0xe7, 0xf7, 0xbe, 0xd4, 0xdd, 0xdf, - 0x3e, 0xda, 0x6f, 0x5d, 0x22, 0xeb, 0x40, 0x1e, 0xee, 0x1d, 0x3d, 0xde, 0xdb, 0xb5, 0x70, 0xe7, - 0xce, 0x6f, 0xce, 0xc1, 0x92, 0xb8, 0xb1, 0x14, 0x0f, 0xe1, 0x59, 0x44, 0xde, 0x87, 0x05, 0xf9, - 0x8f, 0x0c, 0xc8, 0x9a, 0x1c, 0xb6, 0xfd, 0xaf, 0x13, 0x3a, 0xeb, 0x59, 0x58, 0xf2, 0xe5, 0xca, - 0x2f, 0x7e, 0xef, 0x1f, 0x7f, 0xbb, 0xb4, 0x48, 0xea, 0x5b, 0x67, 0x6f, 0x6d, 0x0d, 0x58, 0x10, - 0xf3, 0x36, 0x7e, 0x06, 0x20, 0x7d, 0xe2, 0x4f, 0xda, 0xda, 0x1f, 0xcc, 0xfc, 0xef, 0x82, 0xce, - 0xe5, 0x82, 0x1a, 0xd9, 0xee, 0x65, 0x6c, 0x77, 0x85, 0x2e, 0xf1, 0x76, 0xfd, 0xc0, 0x4f, 0xc4, - 0x7b, 0xff, 0x77, 0x9d, 0x4d, 0xd2, 0x87, 0x86, 0xf9, 0x82, 0x9f, 0xa8, 0xc0, 0x53, 0xc1, 0xff, - 0x0f, 0xe8, 0xbc, 0x52, 0x58, 0xa7, 0xa2, 0x6e, 0xd8, 0xc7, 0x1a, 0x6d, 0xf1, 0x3e, 0x26, 0x48, - 0x91, 0xf6, 0x32, 0x84, 0x25, 0xfb, 0xa1, 0x3e, 0xb9, 0x62, 0xa8, 0x8c, 0xdc, 0xbf, 0x09, 0xe8, - 0xbc, 0x3a, 0xa3, 0x56, 0xf6, 0xf5, 0x2a, 0xf6, 0xb5, 0x41, 0x09, 0xef, 0xab, 0x87, 0x34, 0xea, - 0xdf, 0x04, 0xbc, 0xeb, 0x6c, 0xde, 0xf9, 0xb7, 0xd7, 0xa0, 0xa6, 0x43, 0xc5, 0xe4, 0xab, 0xb0, - 0x68, 0x5d, 0x29, 0x13, 0x35, 0x8d, 0xa2, 0x1b, 0xe8, 0xce, 0x95, 0xe2, 0x4a, 0xd9, 0xf1, 0x55, - 0xec, 0xb8, 0x4d, 0xd6, 0x79, 0xc7, 0xf2, 0x4e, 0x76, 0x0b, 0x2f, 0xd2, 0x45, 0x56, 0xec, 0x33, - 0x31, 0xcf, 0xf4, 0x1a, 0xd8, 0x9a, 0x67, 0xee, 0xda, 0xd8, 0x9a, 0x67, 0xfe, 0xee, 0x98, 0x5e, - 0xc1, 0xee, 0xd6, 0xc9, 0xaa, 0xd9, 0x9d, 0x0e, 0xe1, 0x32, 0x4c, 0xe5, 0x36, 0xdf, 0xb5, 0x93, - 0x57, 0x35, 0x63, 0x15, 0xbd, 0x77, 0xd7, 0x2c, 0x92, 0x7f, 0xf4, 0x4e, 0xdb, 0xd8, 0x15, 0x21, - 0xb8, 0x7d, 0xe6, 0xb3, 0x76, 0xf2, 0x65, 0xa8, 0xe9, 0x07, 0x9a, 0x64, 0xc3, 0x78, 0x15, 0x6b, - 0xbe, 0x1a, 0xed, 0xb4, 0xf3, 0x15, 0x45, 0x8c, 0x61, 0xb6, 0xcc, 0x19, 0xe3, 0x29, 0xd4, 0x8d, - 0x47, 0x98, 0xe4, 0xb2, 0x0e, 0xf4, 0x67, 0x1f, 0x7a, 0x76, 0x3a, 0x45, 0x55, 0xb2, 0x8b, 0x65, - 0xec, 0xa2, 0x4e, 0x6a, 0xc8, 0x7b, 0xc9, 0xf3, 0x30, 0x26, 0x07, 0xb0, 0x26, 0x0f, 0x2e, 0xc7, - 0xec, 0xfb, 0x59, 0xa2, 0x82, 0x67, 0xfe, 0xb7, 0x1d, 0xf2, 0x1e, 0x54, 0xd5, 0x83, 0x5a, 0xb2, - 0x5e, 0xfc, 0x30, 0xb8, 0xb3, 0x91, 0xc3, 0xa5, 0x5a, 0xfb, 0x12, 0x40, 0xfa, 0xe2, 0x53, 0x0b, - 0x70, 0xee, 0x05, 0xa9, 0xde, 0x9d, 0xfc, 0xf3, 0x50, 0xba, 0x8e, 0x13, 0x6c, 0x11, 0x14, 0xe0, - 0x80, 0x9d, 0xab, 0xc7, 0x0d, 0x5f, 0x81, 0xba, 0xf1, 0xe8, 0x53, 0x2f, 0x5f, 0xfe, 0xc1, 0xa8, - 0x5e, 0xbe, 0x82, 0x37, 0xa2, 0xb4, 0x83, 0xad, 0xaf, 0xd2, 0x26, 0x6f, 0x3d, 0xf6, 0x07, 0xc1, - 0x48, 0x10, 0xf0, 0x0d, 0x3a, 0x85, 0x45, 0xeb, 0x65, 0xa7, 0x96, 0x9e, 0xa2, 0x77, 0xa3, 0x5a, - 0x7a, 0x0a, 0x1f, 0x83, 0x2a, 0x76, 0xa6, 0xcb, 0xbc, 0x9f, 0x33, 0x24, 0x31, 0x7a, 0xfa, 0x00, - 0xea, 0xc6, 0x2b, 0x4d, 0x3d, 0x97, 0xfc, 0x83, 0x50, 0x3d, 0x97, 0xa2, 0x47, 0x9d, 0xab, 0xd8, - 0xc7, 0x12, 0x45, 0x56, 0xc0, 0xb7, 0x01, 0xbc, 0xed, 0xaf, 0xc2, 0x92, 0xfd, 0x6e, 0x53, 0xcb, - 0x65, 0xe1, 0x0b, 0x50, 0x2d, 0x97, 0x33, 0x1e, 0x7b, 0x4a, 0x96, 0xde, 0x5c, 0xd1, 0x9d, 0x6c, - 0x7d, 0x28, 0x2f, 0x6e, 0x3f, 0x22, 0x5f, 0xe0, 0xca, 0x47, 0x3e, 0xd6, 0x20, 0x1b, 0x06, 0xd7, - 0x9a, 0x4f, 0x3a, 0xb4, 0xbc, 0xe4, 0xde, 0x75, 0xd8, 0xcc, 0x2c, 0x5e, 0x37, 0xa0, 0x45, 0xc1, - 0x47, 0x1b, 0x86, 0x45, 0x31, 0xdf, 0x75, 0x18, 0x16, 0xc5, 0x7a, 0xdb, 0x91, 0xb5, 0x28, 0x89, - 0xcf, 0xdb, 0x08, 0xa0, 0x99, 0x49, 0x5f, 0xd2, 0x52, 0x51, 0x9c, 0xef, 0xd9, 0xb9, 0xfa, 0xe2, - 0xac, 0x27, 0x5b, 0x51, 0x29, 0x05, 0xb5, 0xa5, 0xb2, 0x6b, 0x7f, 0x16, 0x1a, 0xe6, 0x7b, 0x3b, - 0x62, 0x8a, 0x72, 0xb6, 0xa7, 0x57, 0x0a, 0xeb, 0xec, 0xcd, 0x25, 0x0d, 0xb3, 0x1b, 0xbe, 0xb9, - 0xf6, 0x83, 0xa3, 0x54, 0xe9, 0x16, 0xbd, 0xb3, 0x4a, 0x95, 0x6e, 0xe1, 0x2b, 0x25, 0xb5, 0xb9, - 0x64, 0xc5, 0x9a, 0x8b, 0x88, 0xb1, 0x93, 0x0f, 0xa0, 0x69, 0xe4, 0x06, 0x1e, 0x4d, 0x83, 0x9e, - 0x66, 0xd4, 0x7c, 0x12, 0x79, 0xa7, 0xc8, 0x2f, 0xa6, 0x1b, 0xd8, 0xfe, 0x32, 0xb5, 0x26, 0xc1, - 0x99, 0x74, 0x07, 0xea, 0x66, 0xde, 0xe1, 0x0b, 0xda, 0xdd, 0x30, 0xaa, 0xcc, 0x1c, 0xe8, 0xdb, - 0x0e, 0xf9, 0x5d, 0x07, 0x1a, 0x56, 0x16, 0x9f, 0x75, 0x93, 0x94, 0x69, 0xa7, 0x6d, 0xd6, 0x99, - 0x0d, 0x51, 0x17, 0x07, 0x79, 0xb0, 0xf9, 0x39, 0x6b, 0x11, 0x3e, 0xb4, 0xce, 0x57, 0xb7, 0xb2, - 0xff, 0xd1, 0xe1, 0xa3, 0x2c, 0x81, 0x99, 0x68, 0xff, 0xd1, 0x6d, 0x87, 0x7c, 0xc7, 0x81, 0x25, - 0x3b, 0x2a, 0xa0, 0xb7, 0xaa, 0x30, 0xfe, 0xa0, 0xb7, 0x6a, 0x46, 0x28, 0xe1, 0x03, 0x1c, 0xe5, - 0xe3, 0x4d, 0xd7, 0x1a, 0xa5, 0x7c, 0x8a, 0xf6, 0xc3, 0x8d, 0x96, 0xbc, 0x2b, 0xfe, 0x07, 0x8b, - 0x0a, 0x55, 0x11, 0x43, 0xbb, 0x67, 0xb7, 0xd7, 0xfc, 0x07, 0x24, 0x37, 0x9d, 0xdb, 0x0e, 0xf9, - 0x8a, 0xf8, 0x27, 0x13, 0xf2, 0x5b, 0xe4, 0x92, 0x97, 0xfd, 0x9e, 0x5e, 0xc7, 0x39, 0x5d, 0xa5, - 0x97, 0xad, 0x39, 0x65, 0xed, 0xe6, 0xb6, 0x18, 0x9d, 0xfc, 0xdf, 0x21, 0xa9, 0xe2, 0xcf, 0xfd, - 0x3f, 0x91, 0xd9, 0x83, 0x1c, 0x89, 0x41, 0x4a, 0x72, 0x8b, 0x95, 0x5f, 0xb2, 0x19, 0xba, 0x89, - 0x63, 0xbd, 0x4e, 0x5f, 0x9b, 0x39, 0xd6, 0x2d, 0x3c, 0xdb, 0xf3, 0x11, 0x1f, 0x02, 0xa4, 0x61, - 0x65, 0x92, 0x09, 0x6b, 0x6a, 0xdb, 0x97, 0x8f, 0x3c, 0xdb, 0xf2, 0xa2, 0xa2, 0x9f, 0xbc, 0xc5, - 0x2f, 0x0b, 0xb5, 0xf2, 0x40, 0x05, 0x44, 0x4d, 0xe7, 0xc1, 0x8e, 0xff, 0x5a, 0xce, 0x43, 0xb6, - 0x7d, 0x4b, 0xa9, 0xe8, 0xe8, 0xea, 0x13, 0x58, 0x3c, 0x08, 0xc3, 0x67, 0x93, 0xb1, 0xbe, 0x06, - 0xb2, 0xc3, 0x6e, 0xfb, 0x5e, 0x7c, 0xda, 0xc9, 0xcc, 0x82, 0x5e, 0xc3, 0xa6, 0x3a, 0xa4, 0x6d, - 0x34, 0xb5, 0xf5, 0x61, 0x1a, 0xb6, 0xfe, 0x88, 0x78, 0xb0, 0xac, 0xdd, 0x12, 0x3d, 0xf0, 0x8e, - 0xdd, 0x8c, 0x19, 0x70, 0xcd, 0x75, 0x61, 0x79, 0xa0, 0x6a, 0xb4, 0x5b, 0xb1, 0x6a, 0xf3, 0xb6, - 0x43, 0x0e, 0xa1, 0xb1, 0xcb, 0x7a, 0x61, 0x9f, 0xc9, 0xd8, 0xd5, 0x4a, 0x3a, 0x70, 0x1d, 0xf4, - 0xea, 0x2c, 0x5a, 0xa0, 0xad, 0xbf, 0xc7, 0xde, 0x34, 0x62, 0x5f, 0xdb, 0xfa, 0x50, 0x46, 0xc5, - 0x3e, 0x52, 0xfa, 0x5b, 0x85, 0x0d, 0x2d, 0xfd, 0x9d, 0x89, 0x33, 0x5a, 0xfa, 0x3b, 0x17, 0x67, - 0xb4, 0x96, 0x5a, 0x85, 0x2d, 0xc9, 0x10, 0x96, 0x73, 0xa1, 0x49, 0xf2, 0x9a, 0xb2, 0xc0, 0x33, - 0x02, 0x9a, 0x9d, 0x6b, 0xb3, 0x09, 0xec, 0xde, 0x36, 0xed, 0xde, 0x8e, 0x60, 0x71, 0x97, 0x89, - 0xc5, 0x12, 0xb9, 0x26, 0x99, 0x37, 0xa8, 0x66, 0x26, 0x4b, 0x56, 0x81, 0x63, 0x9d, 0x6d, 0xa0, - 0x31, 0xd1, 0x83, 0x7c, 0x19, 0xea, 0xf7, 0x59, 0xa2, 0x92, 0x4b, 0xb4, 0x8b, 0x98, 0xc9, 0x36, - 0xe9, 0x14, 0xe4, 0xa6, 0xd8, 0x3c, 0x83, 0xad, 0x6d, 0xb1, 0xfe, 0x80, 0x09, 0xe5, 0xd4, 0xf5, - 0xfb, 0x1f, 0x91, 0x9f, 0xc6, 0xc6, 0x75, 0x76, 0xdb, 0xba, 0x91, 0x93, 0x60, 0x36, 0xde, 0xcc, - 0xe0, 0x45, 0x2d, 0x07, 0x61, 0x9f, 0x19, 0xae, 0x4a, 0x00, 0x75, 0x23, 0x29, 0x53, 0x0b, 0x50, - 0x3e, 0xc1, 0x54, 0x0b, 0x50, 0x41, 0x0e, 0x27, 0xbd, 0x89, 0xfd, 0x50, 0x72, 0x2d, 0xed, 0x47, - 0xe4, 0x6d, 0xa6, 0x3d, 0x6d, 0x7d, 0xe8, 0x8d, 0x92, 0x8f, 0xc8, 0x53, 0x7c, 0x8f, 0x6a, 0x26, - 0xd0, 0xa4, 0x3e, 0x6f, 0x36, 0xd7, 0x46, 0x2f, 0x96, 0x51, 0x65, 0xfb, 0xc1, 0xa2, 0x2b, 0xf4, - 0x68, 0x3e, 0x0d, 0x70, 0x94, 0x84, 0xe3, 0x5d, 0x8f, 0x8d, 0xc2, 0x20, 0xd5, 0xb5, 0x69, 0x92, - 0x48, 0xaa, 0xbf, 0x8c, 0x4c, 0x11, 0xf2, 0xd4, 0x38, 0x24, 0x58, 0xf9, 0x47, 0x8a, 0xb9, 0x66, - 0xe6, 0x91, 0xe8, 0x05, 0x29, 0xc8, 0x25, 0xb9, 0xed, 0x90, 0x6d, 0x80, 0x34, 0x36, 0xad, 0x5d, - 0xfe, 0x5c, 0xd8, 0x5b, 0xab, 0xbd, 0x82, 0x40, 0xf6, 0x21, 0xd4, 0xd2, 0x60, 0xe7, 0x46, 0x9a, - 0x58, 0x6b, 0x85, 0x46, 0xb5, 0x05, 0xcf, 0x85, 0x20, 0x69, 0x0b, 0x97, 0x0a, 0x48, 0x95, 0x2f, - 0x15, 0xc6, 0x15, 0x7d, 0x58, 0x11, 0x03, 0xd4, 0xee, 0x08, 0xa6, 0x3d, 0xa8, 0x99, 0x14, 0x84, - 0x01, 0xb5, 0x34, 0x17, 0x46, 0xd1, 0xac, 0xa8, 0x02, 0xe7, 0x56, 0x91, 0x72, 0xc1, 0x55, 0xf3, - 0x08, 0x96, 0x73, 0x61, 0x1e, 0x2d, 0xd2, 0xb3, 0x22, 0x6f, 0x5a, 0xa4, 0x67, 0x46, 0x88, 0xe8, - 0x1a, 0x76, 0xd9, 0xa4, 0x80, 0x27, 0x95, 0x73, 0x3f, 0xe9, 0x9d, 0xbe, 0xeb, 0x6c, 0xde, 0xbd, - 0xf1, 0xc1, 0xc7, 0x07, 0x7e, 0x72, 0x3a, 0x39, 0xbe, 0xd5, 0x0b, 0x47, 0x5b, 0x43, 0x75, 0xf4, - 0x97, 0xc9, 0x4b, 0x5b, 0xc3, 0xa0, 0xbf, 0x85, 0x2d, 0x1f, 0xcf, 0xe3, 0x3f, 0xb3, 0xfc, 0xe4, - 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8f, 0xb0, 0xe2, 0xcc, 0xfe, 0x52, 0x00, 0x00, +func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_e66000aa8614d793) } + +var fileDescriptor_rpc_e66000aa8614d793 = []byte{ + // 6738 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7c, 0x5d, 0x6c, 0x24, 0xd9, + 0x55, 0xff, 0x54, 0xbb, 0xdb, 0xee, 0x3e, 0xdd, 0xb6, 0xdb, 0xd7, 0x5f, 0x3d, 0xbd, 0xb3, 0xb3, + 0xb3, 0x37, 0x93, 0x9d, 0x89, 0xff, 0xfb, 0x1f, 0xcf, 0x4e, 0x92, 0x65, 0xb3, 0x0b, 0x01, 0x8f, + 0xed, 0x19, 0x4f, 0xe2, 0x9d, 0x71, 0xca, 0x33, 0x19, 0xb2, 0x01, 0x75, 0xca, 0xdd, 0xd7, 0xed, + 0xca, 0x54, 0x57, 0x75, 0xaa, 0xaa, 0xed, 0xe9, 0x2c, 0x2b, 0x21, 0x40, 0x20, 0x21, 0x22, 0x04, + 0xbc, 0x10, 0x04, 0x42, 0x0a, 0x48, 0x24, 0x8f, 0xbc, 0x44, 0x48, 0xc0, 0x1b, 0x2f, 0x20, 0x21, + 0x84, 0xf2, 0x88, 0xc4, 0x0b, 0xbc, 0x00, 0x82, 0x07, 0x24, 0x1e, 0x78, 0x00, 0xa1, 0x7b, 0xee, + 0x47, 0xdd, 0x5b, 0x55, 0x1e, 0x4f, 0x3e, 0xe0, 0xc9, 0xbe, 0xbf, 0x7b, 0xea, 0x7e, 0x9e, 0xaf, + 0x7b, 0xee, 0xb9, 0x0d, 0x8d, 0x78, 0xdc, 0xbf, 0x35, 0x8e, 0xa3, 0x34, 0x22, 0xb5, 0x20, 0x8c, + 0xc7, 0xfd, 0xee, 0x95, 0x61, 0x14, 0x0d, 0x03, 0xb6, 0xe9, 0x8d, 0xfd, 0x4d, 0x2f, 0x0c, 0xa3, + 0xd4, 0x4b, 0xfd, 0x28, 0x4c, 0x04, 0x11, 0xfd, 0x0a, 0x2c, 0xdc, 0x67, 0xe1, 0x21, 0x63, 0x03, + 0x97, 0x7d, 0x6d, 0xc2, 0x92, 0x94, 0xfc, 0x3f, 0x58, 0xf2, 0xd8, 0xd7, 0x19, 0x1b, 0xf4, 0xc6, + 0x5e, 0x92, 0x8c, 0x4f, 0x62, 0x2f, 0x61, 0x1d, 0xe7, 0x9a, 0x73, 0xb3, 0xe5, 0xb6, 0x45, 0xc5, + 0x81, 0xc6, 0xc9, 0xeb, 0xd0, 0x4a, 0x38, 0x29, 0x0b, 0xd3, 0x38, 0x1a, 0x4f, 0x3b, 0x15, 0xa4, + 0x6b, 0x72, 0x6c, 0x57, 0x40, 0x34, 0x80, 0x45, 0xdd, 0x43, 0x32, 0x8e, 0xc2, 0x84, 0x91, 0xdb, + 0xb0, 0xd2, 0xf7, 0xc7, 0x27, 0x2c, 0xee, 0xe1, 0xc7, 0xa3, 0x90, 0x8d, 0xa2, 0xd0, 0xef, 0x77, + 0x9c, 0x6b, 0x33, 0x37, 0x1b, 0x2e, 0x11, 0x75, 0xfc, 0x8b, 0xf7, 0x65, 0x0d, 0xb9, 0x01, 0x8b, + 0x2c, 0x14, 0x38, 0x1b, 0xe0, 0x57, 0xb2, 0xab, 0x85, 0x0c, 0xe6, 0x1f, 0xd0, 0xbf, 0x70, 0x60, + 0xe9, 0x41, 0xe8, 0xa7, 0x4f, 0xbd, 0x20, 0x60, 0xa9, 0x9a, 0xd3, 0x0d, 0x58, 0x3c, 0x43, 0x00, + 0xe7, 0x74, 0x16, 0xc5, 0x03, 0x39, 0xa3, 0x05, 0x01, 0x1f, 0x48, 0xf4, 0xdc, 0x91, 0x55, 0xce, + 0x1d, 0x59, 0xe9, 0x72, 0xcd, 0x9c, 0xb3, 0x5c, 0x37, 0x60, 0x31, 0x66, 0xfd, 0xe8, 0x94, 0xc5, + 0xd3, 0xde, 0x99, 0x1f, 0x0e, 0xa2, 0xb3, 0x4e, 0xf5, 0x9a, 0x73, 0xb3, 0xe6, 0x2e, 0x28, 0xf8, + 0x29, 0xa2, 0x74, 0x05, 0x88, 0x39, 0x0b, 0xb1, 0x6e, 0x74, 0x08, 0xcb, 0x4f, 0xc2, 0x20, 0xea, + 0x3f, 0xfb, 0x01, 0x67, 0x57, 0xd2, 0x7d, 0xa5, 0xb4, 0xfb, 0x35, 0x58, 0xb1, 0x3b, 0x92, 0x03, + 0x60, 0xb0, 0xba, 0x7d, 0xe2, 0x85, 0x43, 0xa6, 0x9a, 0x54, 0x43, 0xf8, 0x04, 0xb4, 0xfb, 0x93, + 0x38, 0x66, 0x61, 0x61, 0x0c, 0x8b, 0x12, 0xd7, 0x83, 0x78, 0x1d, 0x5a, 0x21, 0x3b, 0xcb, 0xc8, + 0x24, 0xcb, 0x84, 0xec, 0x4c, 0x91, 0xd0, 0x0e, 0xac, 0xe5, 0xbb, 0x91, 0x03, 0xf8, 0x57, 0x07, + 0xaa, 0x4f, 0xd2, 0xe7, 0x11, 0xb9, 0x05, 0xd5, 0x74, 0x3a, 0x16, 0x8c, 0xb9, 0x70, 0x87, 0xdc, + 0x42, 0x5e, 0xbf, 0xb5, 0x35, 0x18, 0xc4, 0x2c, 0x49, 0x1e, 0x4f, 0xc7, 0xcc, 0x6d, 0x79, 0xa2, + 0xd0, 0xe3, 0x74, 0xa4, 0x03, 0x73, 0xb2, 0x8c, 0x1d, 0x36, 0x5c, 0x55, 0x24, 0x57, 0x01, 0xbc, + 0x51, 0x34, 0x09, 0xd3, 0x5e, 0xe2, 0xa5, 0xb8, 0x73, 0x33, 0xae, 0x81, 0x90, 0xeb, 0x30, 0x9f, + 0xf4, 0x63, 0x7f, 0x9c, 0xf6, 0xc6, 0x93, 0xa3, 0x67, 0x6c, 0x8a, 0x3b, 0xd6, 0x70, 0x6d, 0x90, + 0x6c, 0x42, 0x3d, 0x9a, 0xa4, 0xe3, 0xc8, 0x0f, 0xd3, 0x4e, 0xed, 0x9a, 0x73, 0xb3, 0x79, 0x67, + 0x59, 0x8e, 0x89, 0xcf, 0x24, 0x64, 0xc1, 0x01, 0xaf, 0x72, 0x35, 0x11, 0x6f, 0xb6, 0x1f, 0x85, + 0xc7, 0x7e, 0x3c, 0x12, 0xf2, 0xd8, 0x99, 0xc5, 0x9e, 0x6d, 0x90, 0x7e, 0xb3, 0x02, 0xcd, 0xc7, + 0xb1, 0x17, 0x26, 0x5e, 0x9f, 0x03, 0x7c, 0x1a, 0xe9, 0xf3, 0xde, 0x89, 0x97, 0x9c, 0xe0, 0xcc, + 0x1b, 0xae, 0x2a, 0x92, 0x35, 0x98, 0x15, 0x83, 0xc6, 0xf9, 0xcd, 0xb8, 0xb2, 0x44, 0xde, 0x84, + 0xa5, 0x70, 0x32, 0xea, 0xd9, 0x7d, 0xcd, 0xe0, 0xae, 0x17, 0x2b, 0xf8, 0x62, 0x1c, 0xf1, 0x7d, + 0x17, 0x5d, 0x88, 0x99, 0x1a, 0x08, 0xa1, 0xd0, 0x92, 0x25, 0xe6, 0x0f, 0x4f, 0xc4, 0x54, 0x6b, + 0xae, 0x85, 0xf1, 0x36, 0x52, 0x7f, 0xc4, 0x7a, 0x49, 0xea, 0x8d, 0xc6, 0x72, 0x5a, 0x06, 0x82, + 0xf5, 0x51, 0xea, 0x05, 0xbd, 0x63, 0xc6, 0x92, 0xce, 0x9c, 0xac, 0xd7, 0x08, 0x79, 0x03, 0x16, + 0x06, 0x2c, 0x49, 0x7b, 0x72, 0x83, 0x58, 0xd2, 0xa9, 0xa3, 0xf4, 0xe5, 0x50, 0xce, 0x25, 0xf7, + 0x59, 0x6a, 0xac, 0x4e, 0x22, 0xb9, 0x91, 0xee, 0x03, 0x31, 0xe0, 0x1d, 0x96, 0x7a, 0x7e, 0x90, + 0x90, 0xb7, 0xa1, 0x95, 0x1a, 0xc4, 0xa8, 0x6d, 0x9a, 0x9a, 0x75, 0x8c, 0x0f, 0x5c, 0x8b, 0x8e, + 0xde, 0x87, 0xfa, 0x3d, 0xc6, 0xf6, 0xfd, 0x91, 0x9f, 0x92, 0x35, 0xa8, 0x1d, 0xfb, 0xcf, 0x99, + 0x60, 0xee, 0x99, 0xbd, 0x4b, 0xae, 0x28, 0x92, 0x2e, 0xcc, 0x8d, 0x59, 0xdc, 0x67, 0x6a, 0xf9, + 0xf7, 0x2e, 0xb9, 0x0a, 0xb8, 0x3b, 0x07, 0xb5, 0x80, 0x7f, 0x4c, 0xbf, 0x5d, 0x81, 0xe6, 0x21, + 0x0b, 0xb5, 0xd0, 0x10, 0xa8, 0xf2, 0x29, 0x49, 0x41, 0xc1, 0xff, 0xc9, 0x6b, 0xd0, 0xc4, 0x69, + 0x26, 0x69, 0xec, 0x87, 0x43, 0xc9, 0xab, 0xc0, 0xa1, 0x43, 0x44, 0x48, 0x1b, 0x66, 0xbc, 0x91, + 0xe2, 0x53, 0xfe, 0x2f, 0x17, 0xa8, 0xb1, 0x37, 0x1d, 0x71, 0xd9, 0xd3, 0xbb, 0xd6, 0x72, 0x9b, + 0x12, 0xdb, 0xe3, 0xdb, 0x76, 0x0b, 0x96, 0x4d, 0x12, 0xd5, 0x7a, 0x0d, 0x5b, 0x5f, 0x32, 0x28, + 0x65, 0x27, 0x37, 0x60, 0x51, 0xd1, 0xc7, 0x62, 0xb0, 0xb8, 0x8f, 0x0d, 0x77, 0x41, 0xc2, 0x6a, + 0x0a, 0x37, 0xa1, 0x7d, 0xec, 0x87, 0x5e, 0xd0, 0xeb, 0x07, 0xe9, 0x69, 0x6f, 0xc0, 0x82, 0xd4, + 0xc3, 0x1d, 0xad, 0xb9, 0x0b, 0x88, 0x6f, 0x07, 0xe9, 0xe9, 0x0e, 0x47, 0xc9, 0x9b, 0xd0, 0x38, + 0x66, 0xac, 0x87, 0x2b, 0xd1, 0xa9, 0xa3, 0x84, 0x2c, 0xca, 0xa5, 0x57, 0xab, 0xeb, 0xd6, 0x8f, + 0xe5, 0x7f, 0xf4, 0x4f, 0x1c, 0x68, 0x89, 0xa5, 0x92, 0x26, 0xe3, 0x3a, 0xcc, 0xab, 0x11, 0xb1, + 0x38, 0x8e, 0x62, 0xc9, 0xfe, 0x36, 0x48, 0x36, 0xa0, 0xad, 0x80, 0x71, 0xcc, 0xfc, 0x91, 0x37, + 0x64, 0x52, 0xbf, 0x14, 0x70, 0x72, 0x27, 0x6b, 0x31, 0x8e, 0x26, 0xa9, 0x50, 0xda, 0xcd, 0x3b, + 0x2d, 0x39, 0x28, 0x97, 0x63, 0xae, 0x4d, 0xc2, 0xd9, 0xbf, 0x64, 0xa9, 0x2d, 0x8c, 0x7e, 0xc3, + 0x01, 0xc2, 0x87, 0xfe, 0x38, 0x12, 0x4d, 0xc8, 0x95, 0xca, 0xef, 0x92, 0xf3, 0xd2, 0xbb, 0x54, + 0x39, 0x6f, 0x97, 0xae, 0xc3, 0x2c, 0x0e, 0x8b, 0xcb, 0xf3, 0x4c, 0x61, 0xe8, 0xb2, 0x8e, 0x7e, + 0xcb, 0x81, 0x96, 0xa9, 0x83, 0xc8, 0x6d, 0x20, 0xc7, 0x93, 0x70, 0xe0, 0x87, 0xc3, 0x5e, 0xfa, + 0xdc, 0x1f, 0xf4, 0x8e, 0xa6, 0xbc, 0x09, 0x1c, 0xcf, 0xde, 0x25, 0xb7, 0xa4, 0x8e, 0xbc, 0x09, + 0x6d, 0x0b, 0x4d, 0xd2, 0x58, 0x8c, 0x6a, 0xef, 0x92, 0x5b, 0xa8, 0xe1, 0x8b, 0xc4, 0xb5, 0xdc, + 0x24, 0xed, 0xf9, 0xe1, 0x80, 0x3d, 0xc7, 0x75, 0x9d, 0x77, 0x2d, 0xec, 0xee, 0x02, 0xb4, 0xcc, + 0xef, 0xe8, 0x67, 0xa1, 0xbd, 0xcf, 0x95, 0x47, 0xe8, 0x87, 0x43, 0xa9, 0xc4, 0xb9, 0x46, 0x93, + 0x1a, 0x57, 0xec, 0xb5, 0x2c, 0x71, 0xb1, 0x39, 0x89, 0x92, 0x54, 0xae, 0x0b, 0xfe, 0x4f, 0xff, + 0xc1, 0x81, 0x45, 0xbe, 0xe8, 0xef, 0x7b, 0xe1, 0x54, 0xad, 0xf8, 0x3e, 0xb4, 0x78, 0x53, 0x8f, + 0xa3, 0x2d, 0xa1, 0x17, 0x85, 0xbc, 0xdf, 0x94, 0x8b, 0x94, 0xa3, 0xbe, 0x65, 0x92, 0x72, 0xd7, + 0x65, 0xea, 0x5a, 0x5f, 0x73, 0xc1, 0x4c, 0xbd, 0x78, 0xc8, 0x52, 0xd4, 0x98, 0x52, 0x83, 0x82, + 0x80, 0xb6, 0xa3, 0xf0, 0x98, 0x5c, 0x83, 0x56, 0xe2, 0xa5, 0xbd, 0x31, 0x8b, 0x71, 0xd5, 0x50, + 0xb8, 0x66, 0x5c, 0x48, 0xbc, 0xf4, 0x80, 0xc5, 0x77, 0xa7, 0x29, 0xeb, 0xfe, 0x24, 0x2c, 0x15, + 0x7a, 0xe1, 0xf2, 0x9c, 0x4d, 0x91, 0xff, 0x4b, 0x56, 0xa0, 0x76, 0xea, 0x05, 0x13, 0x26, 0x15, + 0xb9, 0x28, 0xbc, 0x5b, 0x79, 0xc7, 0xa1, 0x6f, 0x40, 0x3b, 0x1b, 0xb6, 0x14, 0x0c, 0x02, 0x55, + 0xbe, 0x82, 0xb2, 0x01, 0xfc, 0x9f, 0xfe, 0xae, 0x23, 0x08, 0xb7, 0x23, 0x5f, 0x2b, 0x45, 0x4e, + 0xc8, 0x75, 0xa7, 0x22, 0xe4, 0xff, 0x9f, 0x6b, 0x34, 0x7e, 0xf8, 0xc9, 0x92, 0xcb, 0x50, 0x4f, + 0x58, 0x38, 0xe8, 0x79, 0x41, 0x80, 0xba, 0xa3, 0xee, 0xce, 0xf1, 0xf2, 0x56, 0x10, 0xd0, 0x1b, + 0xb0, 0x64, 0x8c, 0xee, 0x05, 0xf3, 0x78, 0x08, 0x64, 0xdf, 0x4f, 0xd2, 0x27, 0x61, 0x32, 0x36, + 0x74, 0xce, 0x2b, 0xd0, 0x18, 0xf9, 0x21, 0x8e, 0x4c, 0xb0, 0x6d, 0xcd, 0xad, 0x8f, 0xfc, 0x90, + 0x8f, 0x2b, 0xc1, 0x4a, 0xef, 0xb9, 0xac, 0xac, 0xc8, 0x4a, 0xef, 0x39, 0x56, 0xd2, 0x77, 0x60, + 0xd9, 0x6a, 0x4f, 0x76, 0xfd, 0x3a, 0xd4, 0x26, 0xe9, 0xf3, 0x48, 0x59, 0x84, 0xa6, 0xe4, 0x10, + 0xee, 0x67, 0xb8, 0xa2, 0x86, 0xbe, 0x07, 0x4b, 0x0f, 0xd9, 0x99, 0xe4, 0x4c, 0x35, 0x90, 0x37, + 0x2e, 0xf4, 0x41, 0xb0, 0x9e, 0xde, 0x02, 0x62, 0x7e, 0x2c, 0x7b, 0x35, 0x3c, 0x12, 0xc7, 0xf2, + 0x48, 0xe8, 0x1b, 0x40, 0x0e, 0xfd, 0x61, 0xf8, 0x3e, 0x4b, 0x12, 0x6f, 0xa8, 0x15, 0x48, 0x1b, + 0x66, 0x46, 0xc9, 0x50, 0xea, 0x0d, 0xfe, 0x2f, 0xfd, 0x24, 0x2c, 0x5b, 0x74, 0xb2, 0xe1, 0x2b, + 0xd0, 0x48, 0xfc, 0x61, 0xe8, 0xa5, 0x93, 0x98, 0xc9, 0xa6, 0x33, 0x80, 0xde, 0x83, 0x95, 0x2f, + 0xb2, 0xd8, 0x3f, 0x9e, 0x5e, 0xd4, 0xbc, 0xdd, 0x4e, 0x25, 0xdf, 0xce, 0x2e, 0xac, 0xe6, 0xda, + 0x91, 0xdd, 0x0b, 0xf6, 0x95, 0x3b, 0x59, 0x77, 0x45, 0xc1, 0x10, 0xe6, 0x8a, 0x29, 0xcc, 0xf4, + 0x09, 0x90, 0xed, 0x28, 0x0c, 0x59, 0x3f, 0x3d, 0x60, 0x2c, 0xce, 0xce, 0x20, 0x19, 0xaf, 0x36, + 0xef, 0xac, 0xcb, 0x95, 0xcd, 0x6b, 0x08, 0xc9, 0xc4, 0x04, 0xaa, 0x63, 0x16, 0x8f, 0xb0, 0xe1, + 0xba, 0x8b, 0xff, 0xd3, 0x55, 0x58, 0xb6, 0x9a, 0x95, 0xee, 0xe3, 0x5b, 0xb0, 0xba, 0xe3, 0x27, + 0xfd, 0x62, 0x87, 0x1d, 0x98, 0x1b, 0x4f, 0x8e, 0x7a, 0x99, 0x24, 0xaa, 0x22, 0xf7, 0x32, 0xf2, + 0x9f, 0xc8, 0xc6, 0x7e, 0xd9, 0x81, 0xea, 0xde, 0xe3, 0xfd, 0x6d, 0xd2, 0x85, 0xba, 0x1f, 0xf6, + 0xa3, 0x11, 0x57, 0xd6, 0x62, 0xd2, 0xba, 0x7c, 0xae, 0x84, 0x5d, 0x81, 0x06, 0xea, 0x78, 0xee, + 0x38, 0xc9, 0xe3, 0x42, 0x06, 0x70, 0xa7, 0x8d, 0x3d, 0x1f, 0xfb, 0x31, 0x7a, 0x65, 0xca, 0xd7, + 0xaa, 0xa2, 0x1e, 0x2d, 0x56, 0xd0, 0xff, 0xae, 0xc2, 0x9c, 0xd4, 0xf0, 0xd8, 0x5f, 0x3f, 0xf5, + 0x4f, 0x99, 0x1c, 0x89, 0x2c, 0x71, 0xfb, 0x19, 0xb3, 0x51, 0x94, 0xb2, 0x9e, 0xb5, 0x0d, 0x36, + 0x88, 0x4e, 0xa9, 0x68, 0xa8, 0x27, 0x5c, 0xd9, 0x19, 0x41, 0x65, 0x81, 0x7c, 0xb1, 0x38, 0xd0, + 0xf3, 0x07, 0x38, 0xa6, 0xaa, 0xab, 0x8a, 0x7c, 0x25, 0xfa, 0xde, 0xd8, 0xeb, 0xfb, 0xe9, 0x54, + 0xaa, 0x04, 0x5d, 0xe6, 0x6d, 0x07, 0x51, 0xdf, 0x0b, 0x7a, 0x47, 0x5e, 0xe0, 0x85, 0x7d, 0xa6, + 0x1c, 0x5e, 0x0b, 0xe4, 0xce, 0x9f, 0x1c, 0x92, 0x22, 0x13, 0x0e, 0x62, 0x0e, 0xe5, 0x4e, 0x64, + 0x3f, 0x1a, 0x8d, 0xfc, 0x94, 0xfb, 0x8c, 0xe8, 0x4f, 0xcc, 0xb8, 0x06, 0x22, 0xdc, 0x6b, 0x2c, + 0x9d, 0x89, 0xd5, 0x6b, 0x28, 0xf7, 0xda, 0x00, 0x79, 0x2b, 0xdc, 0x29, 0xe1, 0x6a, 0xec, 0xd9, + 0x59, 0x07, 0x44, 0x2b, 0x19, 0xc2, 0xf7, 0x61, 0x12, 0x26, 0x2c, 0x4d, 0x03, 0x36, 0xd0, 0x03, + 0x6a, 0x22, 0x59, 0xb1, 0x82, 0xdc, 0x86, 0x65, 0xe1, 0xc6, 0x26, 0x5e, 0x1a, 0x25, 0x27, 0x7e, + 0xd2, 0x4b, 0xb8, 0x43, 0xd8, 0x42, 0xfa, 0xb2, 0x2a, 0xf2, 0x0e, 0xac, 0xe7, 0xe0, 0x98, 0xf5, + 0x99, 0x7f, 0xca, 0x06, 0x9d, 0x79, 0xfc, 0xea, 0xbc, 0x6a, 0x72, 0x0d, 0x9a, 0xdc, 0x7b, 0x9f, + 0x8c, 0x07, 0x1e, 0xb7, 0xde, 0x0b, 0xb8, 0x0f, 0x26, 0x44, 0xde, 0x82, 0xf9, 0x31, 0x13, 0x26, + 0xf6, 0x24, 0x0d, 0xfa, 0x49, 0x67, 0xd1, 0xd2, 0x6e, 0x9c, 0x73, 0x5d, 0x9b, 0x82, 0x33, 0x65, + 0x3f, 0x41, 0x37, 0xce, 0x9b, 0x76, 0xda, 0xc8, 0x6e, 0x19, 0x80, 0x32, 0x12, 0xfb, 0xa7, 0x5e, + 0xca, 0x3a, 0x4b, 0x42, 0xa1, 0xcb, 0x22, 0xfd, 0x7d, 0x47, 0x28, 0x56, 0xc9, 0x84, 0x5a, 0x41, + 0xbe, 0x06, 0x4d, 0xc1, 0x7e, 0xbd, 0x28, 0x0c, 0xa6, 0x92, 0x23, 0x41, 0x40, 0x8f, 0xc2, 0x60, + 0x4a, 0x3e, 0x06, 0xf3, 0x7e, 0x68, 0x92, 0x08, 0x19, 0x6e, 0x29, 0x10, 0x89, 0x5e, 0x83, 0xe6, + 0x78, 0x72, 0x14, 0xf8, 0x7d, 0x41, 0x32, 0x23, 0x5a, 0x11, 0x10, 0x12, 0x70, 0xd7, 0x4a, 0x8c, + 0x44, 0x50, 0x54, 0x91, 0xa2, 0x29, 0x31, 0x4e, 0x42, 0xef, 0xc2, 0x8a, 0x3d, 0x40, 0xa9, 0xac, + 0x36, 0xa0, 0x2e, 0x79, 0x3b, 0xe9, 0x34, 0x71, 0x7d, 0x16, 0xec, 0x63, 0x9b, 0xab, 0xeb, 0xe9, + 0x77, 0xab, 0xb0, 0x2c, 0xd1, 0xed, 0x20, 0x4a, 0xd8, 0xe1, 0x64, 0x34, 0xf2, 0xe2, 0x12, 0xa1, + 0x71, 0x2e, 0x10, 0x9a, 0x8a, 0x2d, 0x34, 0x9c, 0x95, 0x4f, 0x3c, 0x3f, 0x14, 0x7e, 0xa1, 0x90, + 0x38, 0x03, 0x21, 0x37, 0x61, 0xb1, 0x1f, 0x44, 0x89, 0xf0, 0x95, 0xcc, 0x83, 0x59, 0x1e, 0x2e, + 0x0a, 0x79, 0xad, 0x4c, 0xc8, 0x4d, 0x21, 0x9d, 0xcd, 0x09, 0x29, 0x85, 0x16, 0x6f, 0x94, 0x29, + 0x9d, 0x33, 0x27, 0x7c, 0x37, 0x13, 0xe3, 0xe3, 0xc9, 0x8b, 0x84, 0x90, 0xbf, 0xc5, 0x32, 0x81, + 0xe0, 0xe7, 0x3e, 0xae, 0xd3, 0x0c, 0xea, 0x86, 0x14, 0x88, 0x62, 0x15, 0xb9, 0x07, 0x20, 0xfa, + 0x42, 0xc3, 0x0a, 0x68, 0x58, 0xdf, 0xb0, 0x77, 0xc4, 0x5c, 0xfb, 0x5b, 0xbc, 0x30, 0x89, 0x19, + 0x1a, 0x5b, 0xe3, 0x4b, 0xfa, 0xab, 0x0e, 0x34, 0x8d, 0x3a, 0xb2, 0x0a, 0x4b, 0xdb, 0x8f, 0x1e, + 0x1d, 0xec, 0xba, 0x5b, 0x8f, 0x1f, 0x7c, 0x71, 0xb7, 0xb7, 0xbd, 0xff, 0xe8, 0x70, 0xb7, 0x7d, + 0x89, 0xc3, 0xfb, 0x8f, 0xb6, 0xb7, 0xf6, 0x7b, 0xf7, 0x1e, 0xb9, 0xdb, 0x0a, 0x76, 0xc8, 0x1a, + 0x10, 0x77, 0xf7, 0xfd, 0x47, 0x8f, 0x77, 0x2d, 0xbc, 0x42, 0xda, 0xd0, 0xba, 0xeb, 0xee, 0x6e, + 0x6d, 0xef, 0x49, 0x64, 0x86, 0xac, 0x40, 0xfb, 0xde, 0x93, 0x87, 0x3b, 0x0f, 0x1e, 0xde, 0xef, + 0x6d, 0x6f, 0x3d, 0xdc, 0xde, 0xdd, 0xdf, 0xdd, 0x69, 0x57, 0xc9, 0x3c, 0x34, 0xb6, 0xee, 0x6e, + 0x3d, 0xdc, 0x79, 0xf4, 0x70, 0x77, 0xa7, 0x5d, 0xa3, 0x7f, 0xef, 0xc0, 0x2a, 0x8e, 0x7a, 0x90, + 0x17, 0x90, 0x6b, 0xd0, 0xec, 0x47, 0xd1, 0x98, 0x71, 0x7d, 0xae, 0x55, 0xb6, 0x09, 0x71, 0xe6, + 0x17, 0x0a, 0xf2, 0x38, 0x8a, 0xfb, 0x4c, 0xca, 0x07, 0x20, 0x74, 0x8f, 0x23, 0x9c, 0xf9, 0xe5, + 0xf6, 0x0a, 0x0a, 0x21, 0x1e, 0x4d, 0x81, 0x09, 0x92, 0x35, 0x98, 0x3d, 0x8a, 0x99, 0xd7, 0x3f, + 0x91, 0x92, 0x21, 0x4b, 0xe4, 0x13, 0x99, 0x5b, 0xdf, 0xe7, 0xab, 0x1f, 0xb0, 0x01, 0x72, 0x4c, + 0xdd, 0x5d, 0x94, 0xf8, 0xb6, 0x84, 0xb9, 0x66, 0xf0, 0x8e, 0xbc, 0x70, 0x10, 0x85, 0x6c, 0x20, + 0xdd, 0xb9, 0x0c, 0xa0, 0x07, 0xb0, 0x96, 0x9f, 0x9f, 0x94, 0xaf, 0xb7, 0x0d, 0xf9, 0x12, 0xde, + 0x55, 0xf7, 0xfc, 0xdd, 0x34, 0x64, 0xed, 0x9f, 0x1d, 0xa8, 0x72, 0x63, 0x7b, 0xbe, 0x61, 0x36, + 0xfd, 0xa7, 0x99, 0x42, 0x44, 0x07, 0xcf, 0x2d, 0x42, 0xfd, 0x0a, 0x13, 0x65, 0x20, 0x59, 0x7d, + 0xcc, 0xfa, 0xa7, 0x38, 0x63, 0x5d, 0xcf, 0x11, 0x2e, 0x20, 0xdc, 0xb9, 0xc5, 0xaf, 0xa5, 0x80, + 0xa8, 0xb2, 0xaa, 0xc3, 0x2f, 0xe7, 0xb2, 0x3a, 0xfc, 0xae, 0x03, 0x73, 0x7e, 0x78, 0x14, 0x4d, + 0xc2, 0x01, 0x0a, 0x44, 0xdd, 0x55, 0x45, 0xbe, 0x7c, 0x63, 0x14, 0x54, 0x7f, 0xa4, 0xd8, 0x3f, + 0x03, 0x28, 0xe1, 0x87, 0x9f, 0x04, 0x9d, 0x0b, 0x1d, 0xc2, 0x78, 0x1b, 0x96, 0x0c, 0x2c, 0x73, + 0x54, 0xc7, 0x1c, 0xc8, 0x39, 0xaa, 0xe8, 0x95, 0x88, 0x1a, 0xda, 0x86, 0x85, 0xfb, 0x2c, 0x7d, + 0x10, 0x1e, 0x47, 0xaa, 0xa5, 0x3f, 0xaa, 0xc2, 0xa2, 0x86, 0x64, 0x43, 0x37, 0x61, 0xd1, 0x1f, + 0xb0, 0x30, 0xf5, 0xd3, 0x69, 0xcf, 0x3a, 0x63, 0xe5, 0x61, 0xee, 0xcd, 0x79, 0x81, 0xef, 0xa9, + 0xa8, 0x99, 0x28, 0x90, 0x3b, 0xb0, 0xc2, 0x4d, 0x8d, 0xb2, 0x1e, 0x7a, 0x8b, 0xc5, 0x51, 0xaf, + 0xb4, 0x8e, 0x2b, 0x03, 0x8e, 0x4b, 0x6d, 0xaf, 0x3f, 0x11, 0x5e, 0x4d, 0x59, 0x15, 0x5f, 0x35, + 0xd1, 0x12, 0x9f, 0x72, 0x4d, 0x98, 0x23, 0x0d, 0x14, 0x42, 0x51, 0xb3, 0x42, 0x55, 0xe5, 0x43, + 0x51, 0x46, 0x38, 0xab, 0x5e, 0x08, 0x67, 0x71, 0x55, 0x36, 0x0d, 0xfb, 0x6c, 0xd0, 0x4b, 0xa3, + 0x1e, 0xaa, 0x5c, 0xdc, 0x9d, 0xba, 0x9b, 0x87, 0xc9, 0x15, 0x98, 0x4b, 0x59, 0x92, 0x86, 0x2c, + 0x45, 0xad, 0x54, 0xbf, 0x5b, 0xe9, 0x38, 0xae, 0x82, 0xb8, 0x0b, 0x3a, 0x89, 0xfd, 0xa4, 0xd3, + 0xc2, 0x40, 0x15, 0xfe, 0x4f, 0x3e, 0x05, 0xab, 0x47, 0x2c, 0x49, 0x7b, 0x27, 0xcc, 0x1b, 0xb0, + 0x18, 0x77, 0x5a, 0x44, 0xc4, 0x84, 0x65, 0x2f, 0xaf, 0xe4, 0x3c, 0x74, 0xca, 0xe2, 0xc4, 0x8f, + 0x42, 0xb4, 0xe9, 0x0d, 0x57, 0x15, 0x79, 0x7b, 0x7c, 0xf2, 0xda, 0x5e, 0xea, 0x15, 0x5c, 0xc4, + 0x89, 0x97, 0x57, 0x92, 0xeb, 0x30, 0x8b, 0x13, 0x48, 0x3a, 0x6d, 0x2b, 0x46, 0xb0, 0xcd, 0x41, + 0x57, 0xd6, 0x7d, 0xae, 0x5a, 0x6f, 0xb6, 0x5b, 0xf4, 0xc7, 0xa0, 0x86, 0x30, 0xdf, 0x74, 0xb1, + 0x18, 0x82, 0x29, 0x44, 0x81, 0x0f, 0x2d, 0x64, 0xe9, 0x59, 0x14, 0x3f, 0x53, 0x21, 0x54, 0x59, + 0xa4, 0x5f, 0x47, 0x27, 0x5e, 0x87, 0x11, 0x9f, 0xa0, 0x07, 0xc2, 0x8f, 0x62, 0x62, 0xa9, 0x93, + 0x13, 0x4f, 0x9e, 0x2b, 0xea, 0x08, 0x1c, 0x9e, 0x78, 0x5c, 0x6d, 0x59, 0xbb, 0x27, 0x8e, 0x6a, + 0x4d, 0xc4, 0xf6, 0xc4, 0xe6, 0x5d, 0x87, 0x05, 0x15, 0xa0, 0x4c, 0x7a, 0x01, 0x3b, 0x4e, 0x55, + 0x24, 0x21, 0x9c, 0x8c, 0xf0, 0x3c, 0xb7, 0xcf, 0x8e, 0x53, 0xfa, 0x10, 0x96, 0xa4, 0x2a, 0x79, + 0x34, 0x66, 0xaa, 0xeb, 0xcf, 0x94, 0x99, 0xe4, 0x73, 0x42, 0xb2, 0x36, 0x25, 0x75, 0x81, 0x98, + 0xaa, 0x49, 0x36, 0x28, 0xed, 0xa2, 0x8a, 0x57, 0xc8, 0xe9, 0x58, 0x18, 0x5f, 0x9f, 0x64, 0xd2, + 0xef, 0xab, 0x10, 0x33, 0x3f, 0xf0, 0x8a, 0x22, 0xfd, 0xb6, 0x03, 0xcb, 0xd8, 0x9a, 0x72, 0x2a, + 0xa4, 0xfa, 0x7f, 0xe7, 0xfb, 0x18, 0x66, 0xab, 0x6f, 0xc6, 0x70, 0x56, 0xa0, 0x66, 0x1a, 0x04, + 0x51, 0xf8, 0xfe, 0x8f, 0xed, 0xd5, 0xfc, 0xb1, 0x9d, 0xfe, 0xb6, 0x03, 0x4b, 0x42, 0x27, 0xa7, + 0x5e, 0x3a, 0x49, 0xe4, 0xf4, 0x7f, 0x1c, 0xe6, 0x85, 0x71, 0x95, 0x52, 0x2d, 0x07, 0xba, 0xa2, + 0x15, 0x10, 0xa2, 0x82, 0x78, 0xef, 0x92, 0x6b, 0x13, 0x93, 0xf7, 0xd0, 0xc1, 0x09, 0x7b, 0x88, + 0xca, 0x30, 0xdb, 0xe5, 0x12, 0x33, 0xa0, 0xbf, 0x37, 0xc8, 0xef, 0xd6, 0x61, 0x56, 0x78, 0xb4, + 0xf4, 0x3e, 0xcc, 0x5b, 0x1d, 0x59, 0x21, 0x83, 0x96, 0x08, 0x19, 0x14, 0x82, 0x4f, 0x95, 0x62, + 0xf0, 0x89, 0xfe, 0xf1, 0x0c, 0x10, 0xce, 0x2c, 0xb9, 0xdd, 0xe0, 0x2e, 0x75, 0x34, 0xb0, 0x0e, + 0x48, 0x2d, 0xd7, 0x84, 0xc8, 0x2d, 0x20, 0x46, 0x51, 0xc5, 0xe7, 0x84, 0xf5, 0x29, 0xa9, 0xe1, + 0x6a, 0x52, 0x1a, 0x6f, 0x69, 0x66, 0xe5, 0x51, 0x50, 0x2c, 0x7b, 0x69, 0x1d, 0x37, 0x30, 0xe3, + 0x49, 0x72, 0x82, 0x97, 0x11, 0xf2, 0x08, 0xa5, 0xca, 0xf9, 0xfd, 0x9d, 0xbd, 0x70, 0x7f, 0xe7, + 0x0a, 0x61, 0x19, 0xc3, 0x89, 0xaf, 0x5b, 0x4e, 0x3c, 0x77, 0x1e, 0x47, 0xdc, 0xe5, 0x4c, 0x83, + 0x7e, 0x6f, 0xc4, 0x7b, 0x97, 0x27, 0x26, 0x0b, 0x24, 0x1b, 0xd0, 0x96, 0xee, 0x46, 0x76, 0x52, + 0x00, 0x5c, 0xe3, 0x02, 0xce, 0xf5, 0x77, 0x16, 0xa8, 0x69, 0xe2, 0x60, 0x33, 0x80, 0x9f, 0xad, + 0x12, 0xce, 0x21, 0xbd, 0x49, 0x28, 0xef, 0x20, 0xd8, 0x00, 0xcf, 0x4a, 0x75, 0xb7, 0x58, 0x41, + 0x7f, 0xd3, 0x81, 0x36, 0xdf, 0x33, 0x8b, 0x2d, 0xdf, 0x05, 0x94, 0x8a, 0x97, 0xe4, 0x4a, 0x8b, + 0x96, 0xbc, 0x03, 0x0d, 0x2c, 0x47, 0x63, 0x16, 0x4a, 0x9e, 0xec, 0xd8, 0x3c, 0x99, 0xe9, 0x93, + 0xbd, 0x4b, 0x6e, 0x46, 0x6c, 0x70, 0xe4, 0xdf, 0x38, 0xd0, 0x94, 0xbd, 0xfc, 0xc0, 0x81, 0x80, + 0xae, 0x71, 0x71, 0x24, 0x38, 0x29, 0xbb, 0x23, 0xba, 0x09, 0x8b, 0x23, 0x2f, 0x9d, 0xc4, 0xdc, + 0x1e, 0x5b, 0x41, 0x80, 0x3c, 0xcc, 0x8d, 0x2b, 0xaa, 0xce, 0xa4, 0x97, 0xfa, 0x41, 0x4f, 0xd5, + 0xca, 0xeb, 0x99, 0xb2, 0x2a, 0xae, 0x41, 0x92, 0xd4, 0x1b, 0x32, 0x69, 0x37, 0x45, 0x81, 0x76, + 0x60, 0x4d, 0x4e, 0x28, 0xe7, 0xaa, 0xd2, 0x3f, 0x6f, 0xc1, 0x7a, 0xa1, 0x4a, 0xdf, 0xe7, 0xca, + 0xd3, 0x6d, 0xe0, 0x8f, 0x8e, 0x22, 0xed, 0xe7, 0x3b, 0xe6, 0xc1, 0xd7, 0xaa, 0x22, 0x43, 0x58, + 0x55, 0x0e, 0x02, 0x5f, 0xd3, 0xcc, 0x98, 0x55, 0xd0, 0x4a, 0xbd, 0x65, 0x6f, 0x61, 0xbe, 0x43, + 0x85, 0x9b, 0x42, 0x5c, 0xde, 0x1e, 0x39, 0x81, 0x8e, 0xf6, 0x44, 0xa4, 0xb2, 0x36, 0xbc, 0x15, + 0xde, 0xd7, 0x9b, 0x17, 0xf4, 0x65, 0x79, 0xb6, 0xee, 0xb9, 0xad, 0x91, 0x29, 0x5c, 0x55, 0x75, + 0xa8, 0x8d, 0x8b, 0xfd, 0x55, 0x5f, 0x6a, 0x6e, 0xe8, 0xb3, 0xdb, 0x9d, 0x5e, 0xd0, 0x30, 0xf9, + 0x2a, 0xac, 0x9d, 0x79, 0x7e, 0xaa, 0x86, 0x65, 0xf8, 0x06, 0x35, 0xec, 0xf2, 0xce, 0x05, 0x5d, + 0x3e, 0x15, 0x1f, 0x5b, 0x26, 0xea, 0x9c, 0x16, 0xbb, 0x7f, 0xe5, 0xc0, 0x82, 0xdd, 0x0e, 0x67, + 0x53, 0x29, 0xfb, 0x4a, 0x07, 0x2a, 0x6f, 0x32, 0x07, 0x17, 0x8f, 0xca, 0x95, 0xb2, 0xa3, 0xb2, + 0x79, 0x40, 0x9d, 0xb9, 0x28, 0x8a, 0x54, 0x7d, 0xb9, 0x28, 0x52, 0xad, 0x2c, 0x8a, 0xd4, 0xfd, + 0x0f, 0x07, 0x48, 0x91, 0x97, 0xc8, 0x7d, 0x71, 0x56, 0x0f, 0x59, 0x20, 0x55, 0xca, 0xff, 0x7f, + 0x39, 0x7e, 0x54, 0x6b, 0xa7, 0xbe, 0xe6, 0x82, 0x61, 0xde, 0xaf, 0x9a, 0xce, 0xce, 0xbc, 0x5b, + 0x56, 0x95, 0x8b, 0x6b, 0x55, 0x2f, 0x8e, 0x6b, 0xd5, 0x2e, 0x8e, 0x6b, 0xcd, 0xe6, 0xe3, 0x5a, + 0xdd, 0x5f, 0x72, 0x60, 0xb9, 0x64, 0xd3, 0x7f, 0x74, 0x13, 0xe7, 0xdb, 0x64, 0xe9, 0x82, 0x8a, + 0xdc, 0x26, 0x13, 0xec, 0xfe, 0x1c, 0xcc, 0x5b, 0x8c, 0xfe, 0xa3, 0xeb, 0x3f, 0xef, 0xaf, 0x09, + 0x3e, 0xb3, 0xb0, 0xee, 0xbf, 0x54, 0x80, 0x14, 0x85, 0xed, 0xff, 0x74, 0x0c, 0xc5, 0x75, 0x9a, + 0x29, 0x59, 0xa7, 0xff, 0x55, 0x3b, 0xf0, 0x26, 0x2c, 0xc9, 0xe4, 0x0f, 0x23, 0x42, 0x23, 0x38, + 0xa6, 0x58, 0xc1, 0x3d, 0x56, 0x3b, 0xa8, 0x58, 0xb7, 0x2e, 0xd1, 0x0d, 0x63, 0x98, 0x8b, 0x2d, + 0xd2, 0x35, 0x58, 0x11, 0xc9, 0x24, 0x77, 0x45, 0x53, 0xca, 0xae, 0xfc, 0x9e, 0x03, 0xab, 0xb9, + 0x8a, 0xec, 0xca, 0x57, 0x98, 0x0e, 0xdb, 0x9e, 0xd8, 0x20, 0x1f, 0xbf, 0xf6, 0x12, 0x72, 0xdc, + 0x56, 0xac, 0xe0, 0xeb, 0x63, 0x78, 0x15, 0xb9, 0x55, 0x2f, 0xab, 0xa2, 0xeb, 0x22, 0xe5, 0x25, + 0x64, 0x41, 0x6e, 0xe0, 0xc7, 0x22, 0x49, 0xc5, 0xac, 0xc8, 0x6e, 0x76, 0xec, 0x21, 0xab, 0x22, + 0x77, 0x08, 0x2d, 0x33, 0x65, 0x8f, 0xb7, 0xb4, 0x8e, 0x7e, 0xd7, 0x01, 0xf2, 0x85, 0x09, 0x8b, + 0xa7, 0x78, 0xad, 0xab, 0x43, 0x47, 0xeb, 0xf9, 0xc0, 0xc8, 0xec, 0x78, 0x72, 0xf4, 0x79, 0x36, + 0x55, 0x09, 0x02, 0x95, 0x2c, 0x41, 0xe0, 0x55, 0x00, 0x7e, 0x90, 0xd2, 0x77, 0xc5, 0xe8, 0x88, + 0x85, 0x93, 0x91, 0x68, 0xb0, 0xf4, 0x0e, 0xbf, 0x7a, 0xf1, 0x1d, 0x7e, 0xed, 0xa2, 0x3b, 0xfc, + 0xf7, 0x60, 0xd9, 0x1a, 0xb7, 0xde, 0x56, 0x75, 0x6b, 0xed, 0xbc, 0xe0, 0xd6, 0xfa, 0x57, 0x2a, + 0x30, 0xb3, 0x17, 0x8d, 0xcd, 0xb0, 0xa9, 0x63, 0x87, 0x4d, 0xa5, 0x2d, 0xe9, 0x69, 0x53, 0x21, + 0x55, 0x8c, 0x05, 0x92, 0x0d, 0x58, 0xf0, 0x46, 0x29, 0x3f, 0xc7, 0x1f, 0x47, 0xf1, 0x99, 0x17, + 0x0f, 0xc4, 0x5e, 0xe3, 0xf1, 0x3d, 0x57, 0x43, 0x56, 0x60, 0x46, 0x2b, 0x5d, 0x24, 0xe0, 0x45, + 0xee, 0xb8, 0xe1, 0x95, 0xcb, 0x54, 0x86, 0x20, 0x64, 0x89, 0xb3, 0x92, 0xfd, 0xbd, 0xf0, 0x9a, + 0x85, 0xe8, 0x94, 0x55, 0x71, 0xbb, 0xc6, 0x97, 0x0f, 0xc9, 0x64, 0xec, 0x48, 0x95, 0xcd, 0x38, + 0x57, 0xdd, 0xbe, 0x80, 0xfa, 0x27, 0x07, 0x6a, 0xb8, 0x36, 0x5c, 0x0d, 0x08, 0xde, 0xd7, 0x91, + 0x53, 0x5c, 0x93, 0x79, 0x37, 0x0f, 0x13, 0x6a, 0xa5, 0xd8, 0x54, 0xf4, 0x84, 0xcc, 0x34, 0x9b, + 0x6b, 0xd0, 0x10, 0x25, 0x9d, 0x4e, 0x82, 0x24, 0x19, 0x48, 0xae, 0x42, 0xf5, 0x24, 0x1a, 0x2b, + 0xbf, 0x05, 0xd4, 0xc5, 0x41, 0x34, 0x76, 0x11, 0xcf, 0xc6, 0xc3, 0xdb, 0x13, 0xd3, 0x12, 0xd6, + 0x28, 0x0f, 0x73, 0x7b, 0xac, 0x9b, 0x35, 0x97, 0x29, 0x87, 0xd2, 0x0d, 0x58, 0x7c, 0x18, 0x0d, + 0x98, 0x11, 0xbe, 0x3a, 0x97, 0xcf, 0xe9, 0xcf, 0x3b, 0x50, 0x57, 0xc4, 0xe4, 0x26, 0x54, 0xb9, + 0x93, 0x91, 0x3b, 0x01, 0xe8, 0x0b, 0x43, 0x4e, 0xe7, 0x22, 0x05, 0xd7, 0xca, 0x18, 0x55, 0xc8, + 0x1c, 0x4e, 0x15, 0x53, 0xc8, 0xfc, 0x29, 0x3d, 0xdc, 0x9c, 0x1b, 0x92, 0x43, 0xe9, 0x77, 0x1c, + 0x98, 0xb7, 0xfa, 0xe0, 0x67, 0xc8, 0xc0, 0x4b, 0x52, 0x79, 0x09, 0x23, 0xb7, 0xc7, 0x84, 0xcc, + 0x8d, 0xae, 0xd8, 0x01, 0x4d, 0x1d, 0x6a, 0x9b, 0x31, 0x43, 0x6d, 0xb7, 0xa1, 0x91, 0x25, 0x42, + 0x55, 0x2d, 0x6d, 0xcb, 0x7b, 0x54, 0x57, 0xa1, 0x19, 0x11, 0x46, 0x6f, 0xa2, 0x20, 0x8a, 0x65, + 0xf4, 0x5f, 0x14, 0xe8, 0x7b, 0xd0, 0x34, 0xe8, 0xcd, 0x60, 0x8e, 0x63, 0x05, 0x73, 0x74, 0x9e, + 0x40, 0x25, 0xcb, 0x13, 0xa0, 0x7f, 0xe9, 0xc0, 0x3c, 0xe7, 0x41, 0x3f, 0x1c, 0x1e, 0x44, 0x81, + 0xdf, 0x9f, 0xe2, 0xde, 0x2b, 0x76, 0x93, 0x3a, 0x43, 0xf1, 0xa2, 0x0d, 0x73, 0xae, 0x57, 0x47, + 0x48, 0x29, 0xa2, 0xba, 0xcc, 0x65, 0x98, 0x4b, 0xc0, 0x91, 0x97, 0x48, 0xb1, 0x90, 0xe6, 0xcf, + 0x02, 0xb9, 0xa4, 0x71, 0x20, 0xf6, 0x52, 0xd6, 0x1b, 0xf9, 0x41, 0xe0, 0x0b, 0x5a, 0xe1, 0x1c, + 0x95, 0x55, 0xf1, 0x3e, 0x07, 0x7e, 0xe2, 0x1d, 0x65, 0x11, 0x6d, 0x5d, 0xa6, 0x7f, 0x5a, 0x81, + 0xa6, 0x54, 0xdc, 0xbb, 0x83, 0x21, 0x93, 0xd7, 0x2f, 0xe8, 0x7e, 0x6a, 0x25, 0x63, 0x20, 0xaa, + 0xde, 0x72, 0x58, 0x0d, 0x24, 0xbf, 0xe5, 0x33, 0xc5, 0x2d, 0xbf, 0x02, 0x0d, 0xce, 0x7a, 0x6f, + 0xa1, 0x67, 0x2c, 0xae, 0x6e, 0x32, 0x40, 0xd5, 0xde, 0xc1, 0xda, 0x5a, 0x56, 0x8b, 0xc0, 0x0b, + 0x2f, 0x6b, 0xde, 0x81, 0x96, 0x6c, 0x06, 0xf7, 0x04, 0x75, 0x4a, 0xc6, 0xfc, 0xd6, 0x7e, 0xb9, + 0x16, 0xa5, 0xfa, 0xf2, 0x8e, 0xfa, 0xb2, 0x7e, 0xd1, 0x97, 0x8a, 0x92, 0xde, 0xd7, 0x77, 0x60, + 0xf7, 0x63, 0x6f, 0x7c, 0xa2, 0xa4, 0xf4, 0x36, 0x2c, 0xfb, 0x61, 0x3f, 0x98, 0x0c, 0x58, 0x6f, + 0x12, 0x7a, 0x61, 0x18, 0x4d, 0xc2, 0x3e, 0x53, 0x29, 0x00, 0x65, 0x55, 0x74, 0xa0, 0xb3, 0x92, + 0xb0, 0x21, 0xb2, 0x01, 0x35, 0xde, 0x91, 0xb2, 0x0a, 0xe5, 0x22, 0x2c, 0x48, 0xc8, 0x4d, 0xa8, + 0xb1, 0xc1, 0x90, 0xa9, 0xd3, 0x22, 0xb1, 0xcf, 0xed, 0x7c, 0x57, 0x5d, 0x41, 0xc0, 0x15, 0x0a, + 0x47, 0x73, 0x0a, 0xc5, 0xb6, 0x28, 0xb3, 0xbc, 0xf8, 0x60, 0x40, 0x57, 0x80, 0x3c, 0x14, 0x32, + 0x60, 0x86, 0xcf, 0x7f, 0x71, 0x06, 0x9a, 0x06, 0xcc, 0x75, 0xc3, 0x90, 0x0f, 0xb8, 0x37, 0xf0, + 0xbd, 0x11, 0x4b, 0x59, 0x2c, 0xf9, 0x3e, 0x87, 0x72, 0x3a, 0xef, 0x74, 0xd8, 0x8b, 0x26, 0x69, + 0x6f, 0xc0, 0x86, 0x31, 0x13, 0x46, 0x9e, 0x1b, 0x1d, 0x0b, 0xe5, 0x74, 0x23, 0xef, 0xb9, 0x49, + 0x27, 0x38, 0x28, 0x87, 0xaa, 0x60, 0xb8, 0x58, 0xa3, 0x6a, 0x16, 0x0c, 0x17, 0x2b, 0x92, 0xd7, + 0x6a, 0xb5, 0x12, 0xad, 0xf6, 0x36, 0xac, 0x09, 0xfd, 0x25, 0x25, 0xbd, 0x97, 0x63, 0xac, 0x73, + 0x6a, 0xc9, 0x06, 0xb4, 0xf9, 0x98, 0x95, 0x48, 0x24, 0xfe, 0xd7, 0x45, 0x60, 0xc9, 0x71, 0x0b, + 0x38, 0xa7, 0xc5, 0x08, 0x8f, 0x49, 0x2b, 0x2e, 0x07, 0x0b, 0x38, 0xd2, 0x7a, 0xcf, 0x6d, 0xda, + 0x86, 0xa4, 0xcd, 0xe1, 0x74, 0x1e, 0x9a, 0x87, 0x69, 0x34, 0x56, 0x9b, 0xb2, 0x00, 0x2d, 0x51, + 0x94, 0xa9, 0x18, 0xaf, 0xc0, 0x65, 0xe4, 0xa2, 0xc7, 0xd1, 0x38, 0x0a, 0xa2, 0xe1, 0xf4, 0x70, + 0x72, 0x24, 0xd2, 0x73, 0xfd, 0x28, 0xa4, 0x7f, 0xed, 0xc0, 0xb2, 0x55, 0x2b, 0xa3, 0x47, 0x9f, + 0x12, 0x42, 0xa0, 0xef, 0xd0, 0x05, 0xe3, 0x2d, 0x19, 0xca, 0x55, 0x10, 0x8a, 0x18, 0xe0, 0x13, + 0x79, 0xad, 0xbe, 0x05, 0x8b, 0x6a, 0x64, 0xea, 0x43, 0xc1, 0x85, 0x9d, 0x22, 0x17, 0xca, 0xef, + 0x17, 0xe4, 0x07, 0xaa, 0x89, 0x9f, 0x90, 0x97, 0xac, 0x03, 0x9c, 0xa3, 0x8a, 0x43, 0xe8, 0x8b, + 0x31, 0xf3, 0x34, 0xa2, 0x46, 0xd0, 0xd7, 0x60, 0x42, 0x7f, 0xcd, 0x01, 0xc8, 0x46, 0x87, 0x57, + 0x73, 0xda, 0x40, 0x88, 0x0c, 0x7a, 0xc3, 0x18, 0xbc, 0x0e, 0x2d, 0x7d, 0xa5, 0x93, 0xd9, 0x9c, + 0xa6, 0xc2, 0xb8, 0xc3, 0x78, 0x03, 0x16, 0x87, 0x41, 0x74, 0x84, 0x06, 0x1b, 0x73, 0x7b, 0x12, + 0x99, 0x90, 0xb2, 0x20, 0xe0, 0x7b, 0x12, 0xcd, 0x0c, 0x54, 0xd5, 0x30, 0x50, 0xf4, 0x1b, 0x15, + 0x1d, 0x81, 0xcf, 0xe6, 0x7c, 0xae, 0x94, 0x91, 0x3b, 0x05, 0x75, 0x7a, 0x4e, 0xc0, 0x1b, 0x23, + 0x6e, 0x07, 0x17, 0x06, 0x04, 0xde, 0x83, 0x85, 0x58, 0xe8, 0x2b, 0xa5, 0xcc, 0xaa, 0x2f, 0x50, + 0x66, 0xf3, 0xb1, 0x65, 0xc5, 0x3e, 0x01, 0x6d, 0x6f, 0x70, 0xca, 0xe2, 0xd4, 0xc7, 0x23, 0x19, + 0xba, 0x10, 0x42, 0x05, 0x2f, 0x1a, 0x38, 0x5a, 0xf6, 0x1b, 0xb0, 0x28, 0x93, 0x80, 0x34, 0xa5, + 0x4c, 0x89, 0xcd, 0x60, 0x4e, 0x48, 0xff, 0x40, 0x05, 0xfb, 0xed, 0x3d, 0x3c, 0x7f, 0x45, 0xcc, + 0xd9, 0x55, 0x72, 0xb3, 0xfb, 0x98, 0x0c, 0xbc, 0x0f, 0xd4, 0xb9, 0x6f, 0xc6, 0xb8, 0x90, 0x1f, + 0xc8, 0x8b, 0x12, 0x7b, 0x49, 0xab, 0x2f, 0xb3, 0xa4, 0xf4, 0x7b, 0x0e, 0xcc, 0xed, 0x45, 0xe3, + 0x3d, 0x99, 0x9a, 0x80, 0x82, 0xa0, 0xb3, 0xef, 0x54, 0xf1, 0x05, 0x49, 0x0b, 0xa5, 0x96, 0x7b, + 0x3e, 0x6f, 0xb9, 0x7f, 0x0a, 0x5e, 0xc1, 0xa8, 0x43, 0x1c, 0x8d, 0xa3, 0x98, 0x0b, 0xa3, 0x17, + 0x08, 0x33, 0x1d, 0x85, 0xe9, 0x89, 0x52, 0x63, 0x2f, 0x22, 0xc1, 0xe3, 0x1d, 0x3f, 0x96, 0x08, + 0xa7, 0x5b, 0x7a, 0x1a, 0x42, 0xbb, 0x15, 0x2b, 0xe8, 0x67, 0xa0, 0x81, 0xae, 0x32, 0x4e, 0xeb, + 0x4d, 0x68, 0x9c, 0x44, 0xe3, 0xde, 0x89, 0x1f, 0xa6, 0x4a, 0xb8, 0x17, 0x32, 0x1f, 0x76, 0x0f, + 0x17, 0x44, 0x13, 0xd0, 0xff, 0xac, 0xc1, 0xdc, 0x83, 0xf0, 0x34, 0xf2, 0xfb, 0x78, 0xb1, 0x30, + 0x62, 0xa3, 0x48, 0xe5, 0x22, 0xf2, 0xff, 0xc9, 0x15, 0x98, 0xc3, 0xe4, 0x9b, 0xb1, 0x60, 0xda, + 0x96, 0xb8, 0x00, 0x94, 0x10, 0x77, 0x12, 0xe2, 0x2c, 0xe5, 0x58, 0x88, 0x8f, 0x81, 0xf0, 0x43, + 0x44, 0x6c, 0xa6, 0x0c, 0xcb, 0x52, 0x96, 0xeb, 0x59, 0x33, 0x72, 0x3d, 0x79, 0x5f, 0x32, 0x95, + 0x42, 0xdc, 0xb5, 0x8b, 0xbe, 0x24, 0x84, 0x07, 0x9f, 0x98, 0x89, 0xa8, 0x11, 0xba, 0x1c, 0x73, + 0xf2, 0xe0, 0x63, 0x82, 0xdc, 0x2d, 0x11, 0x1f, 0x08, 0x1a, 0xa1, 0x84, 0x4d, 0x88, 0xbb, 0x70, + 0xf9, 0x24, 0xef, 0x86, 0xe0, 0xfd, 0x1c, 0xcc, 0x35, 0xf5, 0x80, 0x69, 0x85, 0x2a, 0xe6, 0x01, + 0x22, 0xad, 0x3a, 0x8f, 0x1b, 0xc7, 0x25, 0x91, 0x27, 0xa5, 0x8e, 0x4b, 0x9c, 0x61, 0xbc, 0x20, + 0x38, 0xf2, 0xfa, 0xcf, 0x30, 0x87, 0x1f, 0x43, 0xfd, 0x0d, 0xd7, 0x06, 0x31, 0x21, 0x22, 0xdb, + 0x55, 0xbc, 0x2a, 0xad, 0xba, 0x26, 0x44, 0xee, 0x40, 0x13, 0x8f, 0x88, 0x72, 0x5f, 0x17, 0x70, + 0x5f, 0xdb, 0xe6, 0x19, 0x12, 0x77, 0xd6, 0x24, 0x32, 0x2f, 0x3d, 0x16, 0xed, 0x4b, 0x0f, 0xa1, + 0x3c, 0xe5, 0x5d, 0x51, 0x1b, 0x7b, 0xcb, 0x00, 0x6e, 0x55, 0xe5, 0x82, 0x09, 0x82, 0x25, 0x24, + 0xb0, 0x30, 0x72, 0x15, 0xea, 0xfc, 0xf8, 0x32, 0xf6, 0xfc, 0x41, 0x87, 0xe8, 0x53, 0x94, 0xc6, + 0x78, 0x1b, 0xea, 0x7f, 0xbc, 0xd3, 0x59, 0xc6, 0x55, 0xb1, 0x30, 0xbe, 0x36, 0xba, 0x8c, 0xc2, + 0xb4, 0x22, 0x76, 0xd4, 0x02, 0xc9, 0x5b, 0x18, 0xb1, 0x4f, 0x59, 0x67, 0x15, 0xd3, 0x62, 0x5e, + 0x91, 0x73, 0x96, 0x4c, 0xab, 0xfe, 0x1e, 0x72, 0x12, 0x57, 0x50, 0xd2, 0x8f, 0x43, 0xcb, 0x84, + 0x49, 0x1d, 0xaa, 0x8f, 0x0e, 0x76, 0x1f, 0xb6, 0x2f, 0x91, 0x26, 0xcc, 0x1d, 0xee, 0x3e, 0x7e, + 0xbc, 0xbf, 0xbb, 0xd3, 0x76, 0x68, 0x0a, 0x64, 0x6b, 0x30, 0x90, 0x94, 0xfa, 0xa0, 0x9e, 0xf1, + 0xac, 0x63, 0xf1, 0x6c, 0x09, 0xdf, 0x54, 0xca, 0xf9, 0xe6, 0x85, 0xab, 0x4b, 0x77, 0xa1, 0x79, + 0x60, 0x64, 0xbf, 0xa3, 0x08, 0xa9, 0xbc, 0x77, 0x29, 0x7a, 0x06, 0x62, 0x0c, 0xa7, 0x62, 0x0e, + 0x87, 0xfe, 0xa1, 0x23, 0xb2, 0x84, 0xf5, 0xf0, 0x45, 0xdf, 0x14, 0x5a, 0x3a, 0x9c, 0x92, 0x25, + 0x9f, 0x59, 0x18, 0xa7, 0xc1, 0xa1, 0xf4, 0xa2, 0xe3, 0xe3, 0x84, 0xa9, 0x54, 0x11, 0x0b, 0xe3, + 0xbc, 0xcf, 0xbd, 0x28, 0xee, 0x91, 0xf8, 0xa2, 0x87, 0x44, 0xa6, 0x8c, 0x14, 0x70, 0xae, 0xc9, + 0x63, 0x76, 0xca, 0xe2, 0x44, 0x27, 0xc9, 0xe8, 0xb2, 0xce, 0x91, 0xcb, 0xaf, 0xf2, 0x06, 0xd4, + 0x75, 0xbb, 0xb6, 0x92, 0x52, 0x94, 0xba, 0x9e, 0x2b, 0x43, 0x3c, 0x57, 0x58, 0x83, 0x16, 0x8a, + 0xb9, 0x58, 0x41, 0x6e, 0x01, 0x39, 0xf6, 0xe3, 0x3c, 0xf9, 0x0c, 0x92, 0x97, 0xd4, 0xd0, 0xa7, + 0xb0, 0xac, 0x98, 0xc5, 0x70, 0x9f, 0xec, 0x4d, 0x74, 0x2e, 0x12, 0x91, 0x4a, 0x51, 0x44, 0xe8, + 0x7f, 0x39, 0x30, 0x27, 0x77, 0xba, 0xf0, 0x82, 0x42, 0xec, 0xb3, 0x85, 0x91, 0x8e, 0x95, 0x00, + 0x8f, 0xf2, 0x24, 0x15, 0x63, 0x41, 0xf5, 0xcd, 0x94, 0xa9, 0x3e, 0x02, 0xd5, 0xb1, 0x97, 0x9e, + 0xe0, 0x69, 0xb9, 0xe1, 0xe2, 0xff, 0xa4, 0x2d, 0x62, 0x3b, 0x42, 0xcd, 0x62, 0x5c, 0xa7, 0xec, + 0xad, 0x88, 0xb0, 0xe8, 0xc5, 0xb7, 0x22, 0x57, 0xa0, 0x81, 0x03, 0xe8, 0x65, 0xa1, 0x9b, 0x0c, + 0xe0, 0x9c, 0x2b, 0x0a, 0x28, 0xbb, 0x32, 0x17, 0x35, 0x43, 0xe8, 0xaa, 0xd8, 0x79, 0xb9, 0x04, + 0xfa, 0x46, 0x4d, 0xe6, 0x24, 0x66, 0x70, 0xc6, 0x11, 0x72, 0x00, 0x79, 0x8e, 0x90, 0xa4, 0xae, + 0xae, 0xa7, 0x5d, 0xe8, 0xec, 0xb0, 0x80, 0xa5, 0x6c, 0x2b, 0x08, 0xf2, 0xed, 0xbf, 0x02, 0x97, + 0x4b, 0xea, 0xa4, 0xc7, 0xfc, 0x05, 0x58, 0xdd, 0x12, 0xf9, 0x5b, 0x3f, 0xaa, 0x9c, 0x04, 0xda, + 0x81, 0xb5, 0x7c, 0x93, 0xb2, 0xb3, 0x7b, 0xb0, 0xb4, 0xc3, 0x8e, 0x26, 0xc3, 0x7d, 0x76, 0x9a, + 0x75, 0x44, 0xa0, 0x9a, 0x9c, 0x44, 0x67, 0x52, 0x30, 0xf1, 0x7f, 0xf2, 0x2a, 0x40, 0xc0, 0x69, + 0x7a, 0xc9, 0x98, 0xf5, 0x55, 0xce, 0x39, 0x22, 0x87, 0x63, 0xd6, 0xa7, 0x6f, 0x03, 0x31, 0xdb, + 0x91, 0xeb, 0xc5, 0x2d, 0xdd, 0xe4, 0xa8, 0x97, 0x4c, 0x93, 0x94, 0x8d, 0x54, 0x32, 0xbd, 0x09, + 0xd1, 0x1b, 0xd0, 0x3a, 0xf0, 0xa6, 0x2e, 0xfb, 0x9a, 0x7c, 0x38, 0xb3, 0x0e, 0x73, 0x63, 0x6f, + 0xca, 0xd5, 0x94, 0x8e, 0x29, 0x61, 0x35, 0xfd, 0xf7, 0x0a, 0xcc, 0x0a, 0x4a, 0xde, 0xea, 0x80, + 0x25, 0xa9, 0x1f, 0x22, 0x63, 0xa9, 0x56, 0x0d, 0xa8, 0xc0, 0xca, 0x95, 0x12, 0x56, 0x96, 0xe7, + 0x32, 0x95, 0xbf, 0x2b, 0xf9, 0xd5, 0xc2, 0x38, 0x73, 0x65, 0xc9, 0x41, 0x22, 0xa8, 0x91, 0x01, + 0xb9, 0xf0, 0x63, 0x66, 0x4f, 0xc5, 0xf8, 0x94, 0x94, 0x4a, 0xce, 0x35, 0xa1, 0x52, 0xab, 0x3d, + 0x27, 0x18, 0xbc, 0x60, 0xb5, 0x0b, 0xd6, 0xb9, 0xfe, 0x12, 0xd6, 0x59, 0x1c, 0xd6, 0x5e, 0x64, + 0x9d, 0xe1, 0x25, 0xac, 0x33, 0x25, 0xd0, 0xbe, 0xc7, 0x98, 0xcb, 0xb8, 0xff, 0xa7, 0x78, 0xf7, + 0x9b, 0x0e, 0xb4, 0x25, 0x17, 0xe9, 0x3a, 0xf2, 0xba, 0xe5, 0xe7, 0x96, 0x66, 0xd9, 0x5e, 0x87, + 0x79, 0xf4, 0x3e, 0x75, 0x9c, 0x55, 0x06, 0x85, 0x2d, 0x90, 0xcf, 0x43, 0x5d, 0x86, 0x8d, 0xfc, + 0x40, 0x6e, 0x8a, 0x09, 0xa9, 0x50, 0x6d, 0xec, 0xc9, 0x24, 0x19, 0xc7, 0xd5, 0x65, 0xfa, 0x67, + 0x0e, 0x2c, 0x19, 0x03, 0x96, 0x5c, 0xf8, 0x1e, 0x28, 0x69, 0x10, 0x41, 0x57, 0x21, 0xb9, 0xeb, + 0xb6, 0xd8, 0x64, 0x9f, 0x59, 0xc4, 0xb8, 0x99, 0xde, 0x14, 0x07, 0x98, 0x4c, 0x46, 0x52, 0x89, + 0x9a, 0x10, 0x67, 0xa4, 0x33, 0xc6, 0x9e, 0x69, 0x12, 0xa1, 0xc6, 0x2d, 0x0c, 0x33, 0x38, 0xb8, + 0xd7, 0xac, 0x89, 0x84, 0x3d, 0xb3, 0x41, 0xfa, 0x77, 0x0e, 0x2c, 0x8b, 0xe3, 0x8f, 0x3c, 0x5c, + 0xea, 0x27, 0x10, 0xb3, 0xe2, 0xbc, 0x27, 0x24, 0x72, 0xef, 0x92, 0x2b, 0xcb, 0xe4, 0xd3, 0x2f, + 0x79, 0x64, 0xd3, 0x99, 0x3b, 0xe7, 0xec, 0xc5, 0x4c, 0xd9, 0x5e, 0xbc, 0x60, 0xa5, 0xcb, 0x82, + 0x8c, 0xb5, 0xd2, 0x20, 0xe3, 0xdd, 0x39, 0xa8, 0x25, 0xfd, 0x68, 0xcc, 0xe8, 0x1a, 0xac, 0xd8, + 0x93, 0x93, 0x2a, 0xe8, 0x5b, 0x0e, 0x74, 0xee, 0x89, 0x60, 0xbc, 0x1f, 0x0e, 0xf7, 0xfc, 0x24, + 0x8d, 0x62, 0xfd, 0x52, 0xec, 0x2a, 0x40, 0x92, 0x7a, 0x71, 0x2a, 0xf2, 0x33, 0x65, 0x08, 0x30, + 0x43, 0xf8, 0x18, 0x59, 0x38, 0x10, 0xb5, 0x62, 0x6f, 0x74, 0xb9, 0xe0, 0x43, 0xc8, 0x03, 0x9a, + 0x65, 0x89, 0xdf, 0x10, 0x99, 0x6c, 0xdc, 0x57, 0x60, 0xa7, 0xa8, 0xd7, 0xc5, 0xc9, 0x27, 0x87, + 0xd2, 0xbf, 0x75, 0x60, 0x31, 0x1b, 0xe4, 0x2e, 0x07, 0x6d, 0xed, 0x20, 0xcd, 0x6f, 0xa6, 0x1d, + 0x54, 0x70, 0xd2, 0xe7, 0xf6, 0x58, 0x8e, 0xcd, 0x40, 0x50, 0x62, 0x65, 0x29, 0x9a, 0x28, 0x07, + 0xc7, 0x84, 0x44, 0x5e, 0x0a, 0xf7, 0x04, 0xa4, 0x57, 0x23, 0x4b, 0x98, 0x5e, 0x3b, 0x4a, 0xf1, + 0xab, 0x59, 0x71, 0xf4, 0x93, 0x45, 0x65, 0x4a, 0xe7, 0x10, 0x45, 0x53, 0x6a, 0x5e, 0x6c, 0xd4, + 0xc5, 0xfa, 0xa8, 0x32, 0xfd, 0x75, 0x07, 0x2e, 0x97, 0x2c, 0xbc, 0x94, 0x9a, 0x1d, 0x58, 0x3a, + 0xd6, 0x95, 0x6a, 0x71, 0x84, 0xe8, 0xac, 0xa9, 0x9b, 0x25, 0x7b, 0x41, 0xdc, 0xe2, 0x07, 0xda, + 0x2f, 0x12, 0xcb, 0x6d, 0x65, 0x7e, 0x15, 0x2b, 0x36, 0x3e, 0x0b, 0x4d, 0xe3, 0x8d, 0x16, 0x59, + 0x87, 0xe5, 0xa7, 0x0f, 0x1e, 0x3f, 0xdc, 0x3d, 0x3c, 0xec, 0x1d, 0x3c, 0xb9, 0xfb, 0xf9, 0xdd, + 0x2f, 0xf5, 0xf6, 0xb6, 0x0e, 0xf7, 0xda, 0x97, 0xc8, 0x1a, 0x90, 0x87, 0xbb, 0x87, 0x8f, 0x77, + 0x77, 0x2c, 0xdc, 0xb9, 0xf3, 0x1b, 0x33, 0xb0, 0x20, 0x6e, 0x2c, 0xc5, 0x1b, 0x79, 0x16, 0x93, + 0xf7, 0x61, 0x4e, 0xfe, 0xc6, 0x01, 0x59, 0x95, 0xc3, 0xb6, 0x7f, 0x55, 0xa1, 0xbb, 0x96, 0x87, + 0x25, 0x5f, 0x2e, 0xff, 0xc2, 0xf7, 0xfe, 0xf1, 0xb7, 0x2a, 0xf3, 0xa4, 0xb9, 0x79, 0xfa, 0xd6, + 0xe6, 0x90, 0x85, 0x09, 0x6f, 0xe3, 0x67, 0x00, 0xb2, 0xd7, 0xff, 0xa4, 0xa3, 0xfd, 0xc1, 0xdc, + 0xcf, 0x1a, 0x74, 0x2f, 0x97, 0xd4, 0xc8, 0x76, 0x2f, 0x63, 0xbb, 0xcb, 0x74, 0x81, 0xb7, 0xeb, + 0x87, 0x7e, 0x2a, 0x7e, 0x0a, 0xe0, 0x5d, 0x67, 0x83, 0x0c, 0xa0, 0x65, 0x3e, 0xee, 0x27, 0x2a, + 0xf0, 0x54, 0xf2, 0xd3, 0x02, 0xdd, 0x57, 0x4a, 0xeb, 0x54, 0xd4, 0x0d, 0xfb, 0x58, 0xa5, 0x6d, + 0xde, 0xc7, 0x04, 0x29, 0xb2, 0x5e, 0x02, 0x58, 0xb0, 0xdf, 0xf0, 0x93, 0x2b, 0x86, 0xca, 0x28, + 0xfc, 0x82, 0x40, 0xf7, 0xd5, 0x73, 0x6a, 0x65, 0x5f, 0xaf, 0x62, 0x5f, 0xeb, 0x94, 0xf0, 0xbe, + 0xfa, 0x48, 0xa3, 0x7e, 0x41, 0xe0, 0x5d, 0x67, 0xe3, 0xce, 0xbf, 0xbd, 0x06, 0x0d, 0x1d, 0x2a, + 0x26, 0x5f, 0x85, 0x79, 0xeb, 0x4a, 0x99, 0xa8, 0x69, 0x94, 0xdd, 0x40, 0x77, 0xaf, 0x94, 0x57, + 0xca, 0x8e, 0xaf, 0x62, 0xc7, 0x1d, 0xb2, 0xc6, 0x3b, 0x96, 0x77, 0xb2, 0x9b, 0x78, 0x91, 0x2e, + 0xb2, 0x62, 0x9f, 0x89, 0x79, 0x66, 0xd7, 0xc0, 0xd6, 0x3c, 0x0b, 0xd7, 0xc6, 0xd6, 0x3c, 0x8b, + 0x77, 0xc7, 0xf4, 0x0a, 0x76, 0xb7, 0x46, 0x56, 0xcc, 0xee, 0x74, 0x08, 0x97, 0x61, 0x2a, 0xb7, + 0xf9, 0xe4, 0x9d, 0xbc, 0xaa, 0x19, 0xab, 0xec, 0x29, 0xbc, 0x66, 0x91, 0xe2, 0x7b, 0x78, 0xda, + 0xc1, 0xae, 0x08, 0xc1, 0xed, 0x33, 0x5f, 0xbc, 0x93, 0x2f, 0x43, 0x43, 0x3f, 0xd0, 0x24, 0xeb, + 0xc6, 0x83, 0x59, 0xf3, 0x41, 0x69, 0xb7, 0x53, 0xac, 0x28, 0x63, 0x0c, 0xb3, 0x65, 0xce, 0x18, + 0x4f, 0xa1, 0x69, 0x3c, 0xc2, 0x24, 0x97, 0x75, 0xa0, 0x3f, 0xff, 0xd0, 0xb3, 0xdb, 0x2d, 0xab, + 0x92, 0x5d, 0x2c, 0x61, 0x17, 0x4d, 0xd2, 0x40, 0xde, 0x4b, 0x9f, 0x47, 0x09, 0xd9, 0x87, 0x55, + 0x79, 0x70, 0x39, 0x62, 0xdf, 0xcf, 0x12, 0x95, 0xfc, 0x02, 0xc0, 0x6d, 0x87, 0xbc, 0x07, 0x75, + 0xf5, 0xd6, 0x96, 0xac, 0x95, 0xbf, 0x19, 0xee, 0xae, 0x17, 0x70, 0xa9, 0xd6, 0xbe, 0x04, 0x90, + 0xbd, 0xf8, 0xd4, 0x02, 0x5c, 0x78, 0x41, 0xaa, 0x77, 0xa7, 0xf8, 0x3c, 0x94, 0xae, 0xe1, 0x04, + 0xdb, 0x04, 0x05, 0x38, 0x64, 0x67, 0xea, 0x71, 0xc3, 0x57, 0xa0, 0x69, 0x3c, 0xfa, 0xd4, 0xcb, + 0x57, 0x7c, 0x30, 0xaa, 0x97, 0xaf, 0xe4, 0x8d, 0x28, 0xed, 0x62, 0xeb, 0x2b, 0x74, 0x91, 0xb7, + 0x9e, 0xf8, 0xc3, 0x70, 0x24, 0x08, 0xf8, 0x06, 0x9d, 0xc0, 0xbc, 0xf5, 0xb2, 0x53, 0x4b, 0x4f, + 0xd9, 0xbb, 0x51, 0x2d, 0x3d, 0xa5, 0x8f, 0x41, 0x15, 0x3b, 0xd3, 0x25, 0xde, 0xcf, 0x29, 0x92, + 0x18, 0x3d, 0x7d, 0x00, 0x4d, 0xe3, 0x95, 0xa6, 0x9e, 0x4b, 0xf1, 0x41, 0xa8, 0x9e, 0x4b, 0xd9, + 0xa3, 0xce, 0x15, 0xec, 0x63, 0x81, 0x22, 0x2b, 0xe0, 0xdb, 0x00, 0xde, 0xf6, 0x57, 0x61, 0xc1, + 0x7e, 0xb7, 0xa9, 0xe5, 0xb2, 0xf4, 0x05, 0xa8, 0x96, 0xcb, 0x73, 0x1e, 0x7b, 0x4a, 0x96, 0xde, + 0x58, 0xd6, 0x9d, 0x6c, 0x7e, 0x28, 0x2f, 0x6e, 0x3f, 0x22, 0x5f, 0xe0, 0xca, 0x47, 0x3e, 0xd6, + 0x20, 0xeb, 0x06, 0xd7, 0x9a, 0x4f, 0x3a, 0xb4, 0xbc, 0x14, 0xde, 0x75, 0xd8, 0xcc, 0x2c, 0x5e, + 0x37, 0xa0, 0x45, 0xc1, 0x47, 0x1b, 0x86, 0x45, 0x31, 0xdf, 0x75, 0x18, 0x16, 0xc5, 0x7a, 0xdb, + 0x91, 0xb7, 0x28, 0xa9, 0xcf, 0xdb, 0x08, 0x61, 0x31, 0x97, 0xbe, 0xa4, 0xa5, 0xa2, 0x3c, 0xdf, + 0xb3, 0x7b, 0xf5, 0xc5, 0x59, 0x4f, 0xb6, 0xa2, 0x52, 0x0a, 0x6a, 0x53, 0x65, 0xd7, 0xfe, 0x2c, + 0xb4, 0xcc, 0xf7, 0x76, 0xc4, 0x14, 0xe5, 0x7c, 0x4f, 0xaf, 0x94, 0xd6, 0xd9, 0x9b, 0x4b, 0x5a, + 0x66, 0x37, 0x7c, 0x73, 0xed, 0x07, 0x47, 0x99, 0xd2, 0x2d, 0x7b, 0x67, 0x95, 0x29, 0xdd, 0xd2, + 0x57, 0x4a, 0x6a, 0x73, 0xc9, 0xb2, 0x35, 0x17, 0x11, 0x63, 0x27, 0x1f, 0xc0, 0xa2, 0x91, 0x1b, + 0x78, 0x38, 0x0d, 0xfb, 0x9a, 0x51, 0x8b, 0x49, 0xe4, 0xdd, 0x32, 0xbf, 0x98, 0xae, 0x63, 0xfb, + 0x4b, 0xd4, 0x9a, 0x04, 0x67, 0xd2, 0x6d, 0x68, 0x9a, 0x79, 0x87, 0x2f, 0x68, 0x77, 0xdd, 0xa8, + 0x32, 0x73, 0xa0, 0x6f, 0x3b, 0xe4, 0x77, 0x1c, 0x68, 0x59, 0x59, 0x7c, 0xd6, 0x4d, 0x52, 0xae, + 0x9d, 0x8e, 0x59, 0x67, 0x36, 0x44, 0x5d, 0x1c, 0xe4, 0xfe, 0xc6, 0xe7, 0xac, 0x45, 0xf8, 0xd0, + 0x3a, 0x5f, 0xdd, 0xca, 0xff, 0xd8, 0xc3, 0x47, 0x79, 0x02, 0x33, 0xd1, 0xfe, 0xa3, 0xdb, 0x0e, + 0xf9, 0x8e, 0x03, 0x0b, 0x76, 0x54, 0x40, 0x6f, 0x55, 0x69, 0xfc, 0x41, 0x6f, 0xd5, 0x39, 0xa1, + 0x84, 0x0f, 0x70, 0x94, 0x8f, 0x37, 0x5c, 0x6b, 0x94, 0xf2, 0x29, 0xda, 0x0f, 0x37, 0x5a, 0xf2, + 0xae, 0xf8, 0x79, 0x16, 0x15, 0xaa, 0x22, 0x86, 0x76, 0xcf, 0x6f, 0xaf, 0xf9, 0xdb, 0x24, 0x37, + 0x9d, 0xdb, 0x0e, 0xf9, 0x8a, 0xf8, 0xfd, 0x09, 0xf9, 0x2d, 0x72, 0xc9, 0xcb, 0x7e, 0x4f, 0xaf, + 0xe3, 0x9c, 0xae, 0xd2, 0xcb, 0xd6, 0x9c, 0xf2, 0x76, 0x73, 0x4b, 0x8c, 0x4e, 0xfe, 0xac, 0x48, + 0xa6, 0xf8, 0x0b, 0x3f, 0x35, 0x72, 0xfe, 0x20, 0x47, 0x62, 0x90, 0x92, 0xdc, 0x62, 0xe5, 0x97, + 0x6c, 0x86, 0x6e, 0xe0, 0x58, 0xaf, 0xd3, 0xd7, 0xce, 0x1d, 0xeb, 0x26, 0x9e, 0xed, 0xf9, 0x88, + 0x0f, 0x00, 0xb2, 0xb0, 0x32, 0xc9, 0x85, 0x35, 0xb5, 0xed, 0x2b, 0x46, 0x9e, 0x6d, 0x79, 0x51, + 0xd1, 0x4f, 0xde, 0xe2, 0x97, 0x85, 0x5a, 0x79, 0xa0, 0x02, 0xa2, 0xa6, 0xf3, 0x60, 0xc7, 0x7f, + 0x2d, 0xe7, 0x21, 0xdf, 0xbe, 0xa5, 0x54, 0x74, 0x74, 0xf5, 0x09, 0xcc, 0xef, 0x47, 0xd1, 0xb3, + 0xc9, 0x58, 0x5f, 0x03, 0xd9, 0x61, 0xb7, 0x3d, 0x2f, 0x39, 0xe9, 0xe6, 0x66, 0x41, 0xaf, 0x61, + 0x53, 0x5d, 0xd2, 0x31, 0x9a, 0xda, 0xfc, 0x30, 0x0b, 0x5b, 0x7f, 0x44, 0x3c, 0x58, 0xd2, 0x6e, + 0x89, 0x1e, 0x78, 0xd7, 0x6e, 0xc6, 0x0c, 0xb8, 0x16, 0xba, 0xb0, 0x3c, 0x50, 0x35, 0xda, 0xcd, + 0x44, 0xb5, 0x79, 0xdb, 0x21, 0x07, 0xd0, 0xda, 0x61, 0xfd, 0x68, 0xc0, 0x64, 0xec, 0x6a, 0x39, + 0x1b, 0xb8, 0x0e, 0x7a, 0x75, 0xe7, 0x2d, 0xd0, 0xd6, 0xdf, 0x63, 0x6f, 0x1a, 0xb3, 0xaf, 0x6d, + 0x7e, 0x28, 0xa3, 0x62, 0x1f, 0x29, 0xfd, 0xad, 0xc2, 0x86, 0x96, 0xfe, 0xce, 0xc5, 0x19, 0x2d, + 0xfd, 0x5d, 0x88, 0x33, 0x5a, 0x4b, 0xad, 0xc2, 0x96, 0x24, 0x80, 0xa5, 0x42, 0x68, 0x92, 0xbc, + 0xa6, 0x2c, 0xf0, 0x39, 0x01, 0xcd, 0xee, 0xb5, 0xf3, 0x09, 0xec, 0xde, 0x36, 0xec, 0xde, 0x0e, + 0x61, 0x7e, 0x87, 0x89, 0xc5, 0x12, 0xb9, 0x26, 0xb9, 0x37, 0xa8, 0x66, 0x26, 0x4b, 0x5e, 0x81, + 0x63, 0x9d, 0x6d, 0xa0, 0x31, 0xd1, 0x83, 0x7c, 0x19, 0x9a, 0xf7, 0x59, 0xaa, 0x92, 0x4b, 0xb4, + 0x8b, 0x98, 0xcb, 0x36, 0xe9, 0x96, 0xe4, 0xa6, 0xd8, 0x3c, 0x83, 0xad, 0x6d, 0xb2, 0xc1, 0x90, + 0x09, 0xe5, 0xd4, 0xf3, 0x07, 0x1f, 0x91, 0x9f, 0xc6, 0xc6, 0x75, 0x76, 0xdb, 0x9a, 0x91, 0x93, + 0x60, 0x36, 0xbe, 0x98, 0xc3, 0xcb, 0x5a, 0x0e, 0xa3, 0x01, 0x33, 0x5c, 0x95, 0x10, 0x9a, 0x46, + 0x52, 0xa6, 0x16, 0xa0, 0x62, 0x82, 0xa9, 0x16, 0xa0, 0x92, 0x1c, 0x4e, 0x7a, 0x13, 0xfb, 0xa1, + 0xe4, 0x5a, 0xd6, 0x8f, 0xc8, 0xdb, 0xcc, 0x7a, 0xda, 0xfc, 0xd0, 0x1b, 0xa5, 0x1f, 0x91, 0xa7, + 0xf8, 0x1e, 0xd5, 0x4c, 0xa0, 0xc9, 0x7c, 0xde, 0x7c, 0xae, 0x8d, 0x5e, 0x2c, 0xa3, 0xca, 0xf6, + 0x83, 0x45, 0x57, 0xe8, 0xd1, 0x7c, 0x1a, 0xe0, 0x30, 0x8d, 0xc6, 0x3b, 0x1e, 0x1b, 0x45, 0x61, + 0xa6, 0x6b, 0xb3, 0x24, 0x91, 0x4c, 0x7f, 0x19, 0x99, 0x22, 0xe4, 0xa9, 0x71, 0x48, 0xb0, 0xf2, + 0x8f, 0x14, 0x73, 0x9d, 0x9b, 0x47, 0xa2, 0x17, 0xa4, 0x24, 0x97, 0xe4, 0xb6, 0x43, 0xb6, 0x00, + 0xb2, 0xd8, 0xb4, 0x76, 0xf9, 0x0b, 0x61, 0x6f, 0xad, 0xf6, 0x4a, 0x02, 0xd9, 0x07, 0xd0, 0xc8, + 0x82, 0x9d, 0xeb, 0x59, 0x62, 0xad, 0x15, 0x1a, 0xd5, 0x16, 0xbc, 0x10, 0x82, 0xa4, 0x6d, 0x5c, + 0x2a, 0x20, 0x75, 0xbe, 0x54, 0x18, 0x57, 0xf4, 0x61, 0x59, 0x0c, 0x50, 0xbb, 0x23, 0x98, 0xf6, + 0xa0, 0x66, 0x52, 0x12, 0x06, 0xd4, 0xd2, 0x5c, 0x1a, 0x45, 0xb3, 0xa2, 0x0a, 0x9c, 0x5b, 0x45, + 0xca, 0x05, 0x57, 0xcd, 0x23, 0x58, 0x2a, 0x84, 0x79, 0xb4, 0x48, 0x9f, 0x17, 0x79, 0xd3, 0x22, + 0x7d, 0x6e, 0x84, 0x88, 0xae, 0x62, 0x97, 0x8b, 0x14, 0xf0, 0xa4, 0x72, 0xe6, 0xa7, 0xfd, 0x93, + 0x77, 0x9d, 0x8d, 0xbb, 0x37, 0x3e, 0xf8, 0xf8, 0xd0, 0x4f, 0x4f, 0x26, 0x47, 0xb7, 0xfa, 0xd1, + 0x68, 0x33, 0x50, 0x47, 0x7f, 0x99, 0xbc, 0xb4, 0x19, 0x84, 0x83, 0x4d, 0x6c, 0xf9, 0x68, 0x16, + 0x7f, 0xe7, 0xf2, 0x93, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0x2c, 0x2c, 0x41, 0x1a, 0x19, 0x53, + 0x00, 0x00, } diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 5a6a0e51f9..75b93821f7 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -837,6 +837,13 @@ message SendCoinsRequest { /// A manual fee rate set in sat/byte that should be used when crafting the transaction. int64 sat_per_byte = 5; + + /** + If set, then the amount field will be ignored, and lnd will attempt to + send all the coins under control of the internal wallet to the specified + address. + */ + bool send_all = 6; } message SendCoinsResponse { /// The transaction ID of the transaction diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index ebaf536587..5ecd1d9e70 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -1288,10 +1288,12 @@ "type": "object", "properties": { "chain": { - "type": "string" + "type": "string", + "title": "/ The blockchain the node is on (eg bitcoin, litecoin)" }, "network": { - "type": "string" + "type": "string", + "title": "/ The network the node is on (eg regtest, testnet, mainnet)" } } }, @@ -2782,6 +2784,11 @@ "type": "string", "format": "int64", "description": "/ A manual fee rate set in sat/byte that should be used when crafting the transaction." + }, + "send_all": { + "type": "boolean", + "format": "boolean", + "description": "*\nIf set, then the amount field will be ignored, and lnd will attempt to\nsend all the coins under control of the internal wallet to the specified\naddress." } } }, diff --git a/lnwallet/btcwallet/signer.go b/lnwallet/btcwallet/signer.go index 21f0959221..f453085613 100644 --- a/lnwallet/btcwallet/signer.go +++ b/lnwallet/btcwallet/signer.go @@ -180,9 +180,10 @@ func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx, // TODO(roasbeef): generate sighash midstate if not present? amt := signDesc.Output.Value - sig, err := txscript.RawTxInWitnessSignature(tx, signDesc.SigHashes, - signDesc.InputIndex, amt, witnessScript, signDesc.HashType, - privKey) + sig, err := txscript.RawTxInWitnessSignature( + tx, signDesc.SigHashes, signDesc.InputIndex, amt, + witnessScript, signDesc.HashType, privKey, + ) if err != nil { return nil, err } @@ -227,8 +228,9 @@ func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx, // spend the p2sh output. The sigScript will contain only a // single push of the p2wkh witness program corresponding to // the matching public key of this address. - p2wkhAddr, err := btcutil.NewAddressWitnessPubKeyHash(pubKeyHash, - b.netParams) + p2wkhAddr, err := btcutil.NewAddressWitnessPubKeyHash( + pubKeyHash, b.netParams, + ) if err != nil { return nil, err } @@ -244,7 +246,7 @@ func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx, return nil, err } - inputScript.ScriptSig = sigScript + inputScript.SigScript = sigScript // Otherwise, this is a regular p2wkh output, so we include the // witness program itself as the subscript to generate the proper @@ -267,7 +269,8 @@ func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx, // TODO(roasbeef): adhere to passed HashType witnessScript, err := txscript.WitnessSignature(tx, signDesc.SigHashes, signDesc.InputIndex, signDesc.Output.Value, witnessProgram, - signDesc.HashType, privKey, true) + signDesc.HashType, privKey, true, + ) if err != nil { return nil, err } diff --git a/lnwallet/interface.go b/lnwallet/interface.go index 62cd0fa39e..efe8b6192d 100644 --- a/lnwallet/interface.go +++ b/lnwallet/interface.go @@ -127,7 +127,7 @@ type TransactionSubscription interface { type WalletController interface { // FetchInputInfo queries for the WalletController's knowledge of the // passed outpoint. If the base wallet determines this output is under - // its control, then the original txout should be returned. Otherwise, + // its control, then the original txout should be returned. Otherwise, // a non-nil error value of ErrNotMine should be returned instead. FetchInputInfo(prevOut *wire.OutPoint) (*wire.TxOut, error) diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 6faa0cd5c9..a32acfa2fc 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -50,11 +50,15 @@ func (c *ChannelContribution) toChanConfig() channeldb.ChannelConfig { } // InputScript represents any script inputs required to redeem a previous -// output. This struct is used rather than just a witness, or scripSig in -// order to accommodate nested p2sh which utilizes both types of input scripts. +// output. This struct is used rather than just a witness, or scripSig in order +// to accommodate nested p2sh which utilizes both types of input scripts. type InputScript struct { - Witness [][]byte - ScriptSig []byte + // Witness is the full witness stack required to unlock this output. + Witness wire.TxWitness + + // SigScript will only be populated if this is an input script sweeping + // a nested p2sh output. + SigScript []byte } // ChannelReservation represents an intent to open a lightning payment channel diff --git a/lnwallet/test_utils.go b/lnwallet/test_utils.go index ca275d3dfd..dd57e311fd 100644 --- a/lnwallet/test_utils.go +++ b/lnwallet/test_utils.go @@ -438,13 +438,15 @@ func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor "address %v", addresses[0]) } - scriptSig, err := txscript.SignatureScript(tx, signDesc.InputIndex, - signDesc.Output.PkScript, txscript.SigHashAll, privKey, true) + sigScript, err := txscript.SignatureScript( + tx, signDesc.InputIndex, signDesc.Output.PkScript, + txscript.SigHashAll, privKey, true, + ) if err != nil { return nil, err } - return &InputScript{ScriptSig: scriptSig}, nil + return &InputScript{SigScript: sigScript}, nil case txscript.WitnessV0PubKeyHashTy: privKey := m.findKey(addresses[0].ScriptAddress(), signDesc.SingleTweak, diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 4784efeab8..2dabf056d2 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -747,14 +747,15 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { signDesc.Output = info signDesc.InputIndex = i - inputScript, err := l.Cfg.Signer.ComputeInputScript(fundingTx, - &signDesc) + inputScript, err := l.Cfg.Signer.ComputeInputScript( + fundingTx, &signDesc, + ) if err != nil { req.err <- err return } - txIn.SignatureScript = inputScript.ScriptSig + txIn.SignatureScript = inputScript.SigScript txIn.Witness = inputScript.Witness pendingReservation.ourFundingInputScripts = append( pendingReservation.ourFundingInputScripts, @@ -958,7 +959,7 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs if len(inputScripts) != 0 && len(txin.Witness) == 0 { // Attach the input scripts so we can verify it below. txin.Witness = inputScripts[sigIndex].Witness - txin.SignatureScript = inputScripts[sigIndex].ScriptSig + txin.SignatureScript = inputScripts[sigIndex].SigScript // Fetch the alleged previous output along with the // pkscript referenced by this input. @@ -1251,12 +1252,22 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) { l.limboMtx.Unlock() } +// WithCoinSelectLock will execute the passed function closure in a +// synchronized manner preventing any coin selection operations from proceeding +// while the closure if executing. This can be seen as the ability to execute a +// function closure under an exclusive coin selection lock. +func (l *LightningWallet) WithCoinSelectLock(f func() error) error { + l.coinSelectMtx.Lock() + defer l.coinSelectMtx.Unlock() + + return f() +} + // selectCoinsAndChange performs coin selection in order to obtain witness // outputs which sum to at least 'numCoins' amount of satoshis. If coin // selection is successful/possible, then the selected coins are available // within the passed contribution's inputs. If necessary, a change address will // also be generated. -// TODO(roasbeef): remove hardcoded fees. func (l *LightningWallet) selectCoinsAndChange(feeRate SatPerKWeight, amt btcutil.Amount, minConfs int32, contribution *ChannelContribution) error { diff --git a/lnwallet/witnessgen.go b/lnwallet/witnessgen.go index 00c3fab094..732836b56a 100644 --- a/lnwallet/witnessgen.go +++ b/lnwallet/witnessgen.go @@ -69,6 +69,16 @@ const ( // broadcast a revoked commitment, but then also immediately attempt to // go to the second level to claim the HTLC. HtlcSecondLevelRevoke WitnessType = 9 + + // WitnessKeyHash is a witness type that allows us to spend a regular + // p2wkh output that's sent to an output which is under complete + // control of the backing wallet. + WitnessKeyHash WitnessType = 10 + + // NestedWitnessKeyHash is a witness type that allows us to sweep an + // output that sends to a nested P2SH script that pays to a key solely + // under our control. The witness generated needs to include the + NestedWitnessKeyHash WitnessType = 11 ) // Stirng returns a human readable version of the target WitnessType. @@ -110,18 +120,22 @@ func (wt WitnessType) String() string { } // WitnessGenerator represents a function which is able to generate the final -// witness for a particular public key script. This function acts as an -// abstraction layer, hiding the details of the underlying script. +// witness for a particular public key script. Additionally, if required, this +// function will also return the sigScript for spending nested P2SH witness +// outputs. This function acts as an abstraction layer, hiding the details of +// the underlying script. type WitnessGenerator func(tx *wire.MsgTx, hc *txscript.TxSigHashes, - inputIndex int) ([][]byte, error) + inputIndex int) (*InputScript, error) -// GenWitnessFunc will return a WitnessGenerator function that an output -// uses to generate the witness for a sweep transaction. +// GenWitnessFunc will return a WitnessGenerator function that an output uses +// to generate the witness and optionally the sigScript for a sweep +// transaction. The sigScript will be generated if the witness type warrants +// one for spending, such as the NestedWitnessKeyHash witness type. func (wt WitnessType) GenWitnessFunc(signer Signer, descriptor *SignDescriptor) WitnessGenerator { return func(tx *wire.MsgTx, hc *txscript.TxSigHashes, - inputIndex int) ([][]byte, error) { + inputIndex int) (*InputScript, error) { desc := descriptor desc.SigHashes = hc @@ -129,34 +143,102 @@ func (wt WitnessType) GenWitnessFunc(signer Signer, switch wt { case CommitmentTimeLock: - return CommitSpendTimeout(signer, desc, tx) + witness, err := CommitSpendTimeout(signer, desc, tx) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil case CommitmentNoDelay: - return CommitSpendNoDelay(signer, desc, tx) + witness, err := CommitSpendNoDelay(signer, desc, tx) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil case CommitmentRevoke: - return CommitSpendRevoke(signer, desc, tx) + witness, err := CommitSpendRevoke(signer, desc, tx) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil case HtlcOfferedRevoke: - return ReceiverHtlcSpendRevoke(signer, desc, tx) + witness, err := ReceiverHtlcSpendRevoke(signer, desc, tx) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil case HtlcAcceptedRevoke: - return SenderHtlcSpendRevoke(signer, desc, tx) + witness, err := SenderHtlcSpendRevoke(signer, desc, tx) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil case HtlcOfferedTimeoutSecondLevel: - return HtlcSecondLevelSpend(signer, desc, tx) + witness, err := HtlcSecondLevelSpend(signer, desc, tx) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil case HtlcAcceptedSuccessSecondLevel: - return HtlcSecondLevelSpend(signer, desc, tx) + witness, err := HtlcSecondLevelSpend(signer, desc, tx) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil case HtlcOfferedRemoteTimeout: // We pass in a value of -1 for the timeout, as we // expect the caller to have already set the lock time // value. - return receiverHtlcSpendTimeout(signer, desc, tx, -1) + witness, err := receiverHtlcSpendTimeout(signer, desc, tx, -1) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil case HtlcSecondLevelRevoke: - return htlcSpendRevoke(signer, desc, tx) + witness, err := htlcSpendRevoke(signer, desc, tx) + if err != nil { + return nil, err + } + + return &InputScript{ + Witness: witness, + }, nil + + case WitnessKeyHash: + fallthrough + case NestedWitnessKeyHash: + return signer.ComputeInputScript(tx, desc) default: return nil, fmt.Errorf("unknown witness type: %v", wt) diff --git a/rpcserver.go b/rpcserver.go index 8275962842..0ab91054fd 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -39,6 +39,7 @@ import ( "github.com/lightningnetwork/lnd/macaroons" "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/signal" + "github.com/lightningnetwork/lnd/sweep" "github.com/lightningnetwork/lnd/zpay32" "github.com/tv42/zbase32" "golang.org/x/net/context" @@ -637,53 +638,7 @@ func (r *rpcServer) sendCoinsOnChain(paymentMap map[string]int64, } txHash := tx.TxHash() - return &txHash, err -} - -// determineFeePerKw will determine the fee in sat/kw that should be paid given -// an estimator, a confirmation target, and a manual value for sat/byte. A value -// is chosen based on the two free parameters as one, or both of them can be -// zero. -func determineFeePerKw(feeEstimator lnwallet.FeeEstimator, targetConf int32, - feePerByte int64) (lnwallet.SatPerKWeight, error) { - - switch { - // If the target number of confirmations is set, then we'll use that to - // consult our fee estimator for an adequate fee. - case targetConf != 0: - feePerKw, err := feeEstimator.EstimateFeePerKW( - uint32(targetConf), - ) - if err != nil { - return 0, fmt.Errorf("unable to query fee "+ - "estimator: %v", err) - } - - return feePerKw, nil - - // If a manual sat/byte fee rate is set, then we'll use that directly. - // We'll need to convert it to sat/kw as this is what we use internally. - case feePerByte != 0: - feePerKW := lnwallet.SatPerKVByte(feePerByte * 1000).FeePerKWeight() - if feePerKW < lnwallet.FeePerKwFloor { - rpcsLog.Infof("Manual fee rate input of %d sat/kw is "+ - "too low, using %d sat/kw instead", feePerKW, - lnwallet.FeePerKwFloor) - feePerKW = lnwallet.FeePerKwFloor - } - return feePerKW, nil - - // Otherwise, we'll attempt a relaxed confirmation target for the - // transaction - default: - feePerKw, err := feeEstimator.EstimateFeePerKW(6) - if err != nil { - return 0, fmt.Errorf("unable to query fee estimator: "+ - "%v", err) - } - - return feePerKw, nil - } + return &txHash, nil } // ListUnspent returns useful information about each unspent output owned by @@ -803,20 +758,100 @@ func (r *rpcServer) SendCoins(ctx context.Context, // Based on the passed fee related parameters, we'll determine an // appropriate fee rate for this transaction. - feePerKw, err := determineFeePerKw( - r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte, + satPerKw := lnwallet.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight() + feePerKw, err := sweep.DetermineFeePerKw( + r.server.cc.feeEstimator, sweep.FeePreference{ + ConfTarget: uint32(in.TargetConf), + FeeRate: satPerKw, + }, ) if err != nil { return nil, err } - rpcsLog.Infof("[sendcoins] addr=%v, amt=%v, sat/kw=%v", in.Addr, - btcutil.Amount(in.Amount), int64(feePerKw)) + rpcsLog.Infof("[sendcoins] addr=%v, amt=%v, sat/kw=%v, sweep_all=%v", + in.Addr, btcutil.Amount(in.Amount), int64(feePerKw), + in.SendAll) - paymentMap := map[string]int64{in.Addr: in.Amount} - txid, err := r.sendCoinsOnChain(paymentMap, feePerKw) - if err != nil { - return nil, err + var txid *chainhash.Hash + + wallet := r.server.cc.wallet + + // If the send all flag is active, then we'll attempt to sweep all the + // coins in the wallet in a single transaction (if possible), + // otherwise, we'll respect the amount, and attempt a regular 2-output + // send. + if in.SendAll { + // At this point, the amount shouldn't be set since we've been + // instructed to sweep all the coins from the wallet. + if in.Amount != 0 { + return nil, fmt.Errorf("amount set while SendAll is " + + "active") + } + + // Additionally, we'll need to convert the sweep address passed + // into a useable struct, and also query for the latest block + // height so we can properly construct the transaction. + sweepAddr, err := btcutil.DecodeAddress( + in.Addr, activeNetParams.Params, + ) + if err != nil { + return nil, err + } + _, bestHeight, err := r.server.cc.chainIO.GetBestBlock() + if err != nil { + return nil, err + } + + // With the sweeper instance created, we can now generate a + // transaction that will sweep ALL outputs from the wallet in a + // single transaction. This will be generated in a concurrent + // safe manner, so no need to worry about locking. + sweepTxPkg, err := sweep.CraftSweepAllTx( + feePerKw, uint32(bestHeight), sweepAddr, wallet, + wallet.WalletController, wallet.WalletController, + r.server.cc.feeEstimator, r.server.cc.signer, + ) + if err != nil { + return nil, err + } + + rpcsLog.Debugf("Sweeping all coins from wallet to addr=%v, "+ + "with tx=%v", in.Addr, spew.Sdump(sweepTxPkg.SweepTx)) + + // As our sweep transaction was created, successfully, we'll + // now attempt to publish it, cancelling the sweep pkg to + // return all outputs if it fails. + err = wallet.PublishTransaction(sweepTxPkg.SweepTx) + if err != nil { + sweepTxPkg.CancelSweepAttempt() + + return nil, fmt.Errorf("unable to broadcast sweep "+ + "transaction: %v", err) + } + + sweepTXID := sweepTxPkg.SweepTx.TxHash() + txid = &sweepTXID + } else { + + // We'll now construct out payment map, and use the wallet's + // coin selection synchronization method to ensure that no coin + // selection (funding, sweep alls, other sends) can proceed + // while we instruct the wallet to send this transaction. + paymentMap := map[string]int64{in.Addr: in.Amount} + err := wallet.WithCoinSelectLock(func() error { + newTXID, err := r.sendCoinsOnChain(paymentMap, feePerKw) + if err != nil { + return err + } + + txid = newTXID + + return nil + }) + if err != nil { + return nil, err + } } rpcsLog.Infof("[sendcoins] spend generated txid: %v", txid.String()) @@ -831,8 +866,12 @@ func (r *rpcServer) SendMany(ctx context.Context, // Based on the passed fee related parameters, we'll determine an // appropriate fee rate for this transaction. - feePerKw, err := determineFeePerKw( - r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte, + satPerKw := lnwallet.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight() + feePerKw, err := sweep.DetermineFeePerKw( + r.server.cc.feeEstimator, sweep.FeePreference{ + ConfTarget: uint32(in.TargetConf), + FeeRate: satPerKw, + }, ) if err != nil { return nil, err @@ -841,7 +880,24 @@ func (r *rpcServer) SendMany(ctx context.Context, rpcsLog.Infof("[sendmany] outputs=%v, sat/kw=%v", spew.Sdump(in.AddrToAmount), int64(feePerKw)) - txid, err := r.sendCoinsOnChain(in.AddrToAmount, feePerKw) + var txid *chainhash.Hash + + // We'll attempt to send to the target set of outputs, ensuring that we + // synchronize with any other ongoing coin selection attempts which + // happen to also be concurrently executing. + wallet := r.server.cc.wallet + err = wallet.WithCoinSelectLock(func() error { + sendManyTXID, err := r.sendCoinsOnChain( + in.AddrToAmount, feePerKw, + ) + if err != nil { + return err + } + + txid = sendManyTXID + + return nil + }) if err != nil { return nil, err } @@ -1170,8 +1226,12 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, // Based on the passed fee related parameters, we'll determine an // appropriate fee rate for the funding transaction. - feeRate, err := determineFeePerKw( - r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte, + satPerKw := lnwallet.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight() + feeRate, err := sweep.DetermineFeePerKw( + r.server.cc.feeEstimator, sweep.FeePreference{ + ConfTarget: uint32(in.TargetConf), + FeeRate: satPerKw, + }, ) if err != nil { return err @@ -1317,8 +1377,12 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, // Based on the passed fee related parameters, we'll determine an // appropriate fee rate for the funding transaction. - feeRate, err := determineFeePerKw( - r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte, + satPerKw := lnwallet.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight() + feeRate, err := sweep.DetermineFeePerKw( + r.server.cc.feeEstimator, sweep.FeePreference{ + ConfTarget: uint32(in.TargetConf), + FeeRate: satPerKw, + }, ) if err != nil { return nil, err @@ -1506,8 +1570,14 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, // Based on the passed fee related parameters, we'll determine // an appropriate fee rate for the cooperative closure // transaction. - feeRate, err := determineFeePerKw( - r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte, + satPerKw := lnwallet.SatPerKVByte( + in.SatPerByte * 1000, + ).FeePerKWeight() + feeRate, err := sweep.DetermineFeePerKw( + r.server.cc.feeEstimator, sweep.FeePreference{ + ConfTarget: uint32(in.TargetConf), + FeeRate: satPerKw, + }, ) if err != nil { return err diff --git a/server.go b/server.go index a55f2f6076..b02cf9084f 100644 --- a/server.go +++ b/server.go @@ -608,7 +608,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl, } s.sweeper = sweep.New(&sweep.UtxoSweeperConfig{ - Estimator: cc.feeEstimator, + FeeEstimator: cc.feeEstimator, GenSweepScript: func() ([]byte, error) { return newSweepPkScript(cc.wallet) }, diff --git a/sweep/fee_estimator_mock_test.go b/sweep/fee_estimator_mock_test.go index 8f3eb44bbc..c926f159c4 100644 --- a/sweep/fee_estimator_mock_test.go +++ b/sweep/fee_estimator_mock_test.go @@ -1,8 +1,9 @@ package sweep import ( - "github.com/lightningnetwork/lnd/lnwallet" "sync" + + "github.com/lightningnetwork/lnd/lnwallet" ) // mockFeeEstimator implements a mock fee estimator. It closely resembles @@ -13,6 +14,8 @@ type mockFeeEstimator struct { relayFee lnwallet.SatPerKWeight + blocksToFee map[uint32]lnwallet.SatPerKWeight + lock sync.Mutex } @@ -20,8 +23,9 @@ func newMockFeeEstimator(feePerKW, relayFee lnwallet.SatPerKWeight) *mockFeeEstimator { return &mockFeeEstimator{ - feePerKW: feePerKW, - relayFee: relayFee, + feePerKW: feePerKW, + relayFee: relayFee, + blocksToFee: make(map[uint32]lnwallet.SatPerKWeight), } } @@ -41,6 +45,10 @@ func (e *mockFeeEstimator) EstimateFeePerKW(numBlocks uint32) ( e.lock.Lock() defer e.lock.Unlock() + if fee, ok := e.blocksToFee[numBlocks]; ok { + return fee, nil + } + return e.feePerKW, nil } diff --git a/sweep/input.go b/sweep/input.go index 57ee793937..57a954df70 100644 --- a/sweep/input.go +++ b/sweep/input.go @@ -6,7 +6,10 @@ import ( "github.com/lightningnetwork/lnd/lnwallet" ) -// Input contains all data needed to construct a sweep tx input. +// Input represents an abstract UTXO which is to be spent using a sweeping +// transaction. The method provided give the caller all information needed to +// construct a valid input within a sweeping transaction to sweep this +// lingering UTXO. type Input interface { // Outpoint returns the reference to the output being spent, used to // construct the corresponding transaction input. @@ -21,12 +24,14 @@ type Input interface { // that spends this output. SignDesc() *lnwallet.SignDescriptor - // BuildWitness returns a valid witness allowing this output to be - // spent, the witness should be attached to the transaction at the - // location determined by the given `txinIdx`. - BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx, + // CraftInputScript returns a valid set of input scripts allowing this + // output to be spent. The returns input scripts should target the + // input at location txIndex within the passed transaction. The input + // scripts generated by this method support spending p2wkh, p2wsh, and + // also nested p2sh outputs. + CraftInputScript(signer lnwallet.Signer, txn *wire.MsgTx, hashCache *txscript.TxSigHashes, - txinIdx int) ([][]byte, error) + txinIdx int) (*lnwallet.InputScript, error) // BlocksToMaturity returns the relative timelock, as a number of // blocks, that must be built on top of the confirmation height before @@ -91,12 +96,12 @@ func MakeBaseInput(outpoint *wire.OutPoint, witnessType lnwallet.WitnessType, } } -// BuildWitness computes a valid witness that allows us to spend from the -// breached output. It does so by generating the witness generation function, -// which is parameterized primarily by the witness type and sign descriptor. -// The method then returns the witness computed by invoking this function. -func (bi *BaseInput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx, - hashCache *txscript.TxSigHashes, txinIdx int) ([][]byte, error) { +// CraftInputScript returns a valid set of input scripts allowing this output +// to be spent. The returns input scripts should target the input at location +// txIndex within the passed transaction. The input scripts generated by this +// method support spending p2wkh, p2wsh, and also nested p2sh outputs. +func (bi *BaseInput) CraftInputScript(signer lnwallet.Signer, txn *wire.MsgTx, + hashCache *txscript.TxSigHashes, txinIdx int) (*lnwallet.InputScript, error) { witnessFunc := bi.witnessType.GenWitnessFunc( signer, bi.SignDesc(), @@ -138,20 +143,27 @@ func MakeHtlcSucceedInput(outpoint *wire.OutPoint, } } -// BuildWitness computes a valid witness that allows us to spend from the -// breached output. For HtlcSpendInput it will need to make the preimage part -// of the witness. -func (h *HtlcSucceedInput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx, - hashCache *txscript.TxSigHashes, txinIdx int) ([][]byte, error) { +// CraftInputScript returns a valid set of input scripts allowing this output +// to be spent. The returns input scripts should target the input at location +// txIndex within the passed transaction. The input scripts generated by this +// method support spending p2wkh, p2wsh, and also nested p2sh outputs. +func (h *HtlcSucceedInput) CraftInputScript(signer lnwallet.Signer, txn *wire.MsgTx, + hashCache *txscript.TxSigHashes, txinIdx int) (*lnwallet.InputScript, error) { desc := h.signDesc desc.SigHashes = hashCache desc.InputIndex = txinIdx - return lnwallet.SenderHtlcSpendRedeem( - signer, &desc, txn, - h.preimage, + witness, err := lnwallet.SenderHtlcSpendRedeem( + signer, &desc, txn, h.preimage, ) + if err != nil { + return nil, err + } + + return &lnwallet.InputScript{ + Witness: witness, + }, nil } // BlocksToMaturity returns the relative timelock, as a number of blocks, that diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 3829d27e6a..61cb1a2229 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -85,10 +85,10 @@ type UtxoSweeperConfig struct { // funds can be swept. GenSweepScript func() ([]byte, error) - // Estimator is used when crafting sweep transactions to estimate the - // necessary fee relative to the expected size of the sweep + // FeeEstimator is used when crafting sweep transactions to estimate + // the necessary fee relative to the expected size of the sweep // transaction. - Estimator lnwallet.FeeEstimator + FeeEstimator lnwallet.FeeEstimator // PublishTransaction facilitates the process of broadcasting a signed // transaction to the appropriate network. @@ -198,7 +198,7 @@ func (s *UtxoSweeper) Start() error { // Retrieve relay fee for dust limit calculation. Assume that this will // not change from here on. - s.relayFeePerKW = s.cfg.Estimator.RelayFeePerKW() + s.relayFeePerKW = s.cfg.FeeEstimator.RelayFeePerKW() // Register for block epochs to retry sweeping every block. bestHash, bestHeight, err := s.cfg.ChainIO.GetBestBlock() @@ -407,7 +407,7 @@ func (s *UtxoSweeper) collector(blockEpochs <-chan *chainntnfs.BlockEpoch, // Retrieve fee estimate for input filtering and final // tx fee calculation. - satPerKW, err := s.cfg.Estimator.EstimateFeePerKW( + satPerKW, err := s.cfg.FeeEstimator.EstimateFeePerKW( s.cfg.SweepTxConfTarget, ) if err != nil { @@ -465,7 +465,7 @@ func (s *UtxoSweeper) scheduleSweep(currentHeight int32) error { // Retrieve fee estimate for input filtering and final tx fee // calculation. - satPerKW, err := s.cfg.Estimator.EstimateFeePerKW( + satPerKW, err := s.cfg.FeeEstimator.EstimateFeePerKW( s.cfg.SweepTxConfTarget, ) if err != nil { @@ -750,10 +750,10 @@ func (s *UtxoSweeper) waitForSpend(outpoint wire.OutPoint, // - Make handling re-orgs easier. // - Thwart future possible fee sniping attempts. // - Make us blend in with the bitcoind wallet. -func (s *UtxoSweeper) CreateSweepTx(inputs []Input, confTarget uint32, +func (s *UtxoSweeper) CreateSweepTx(inputs []Input, feePref FeePreference, currentBlockHeight uint32) (*wire.MsgTx, error) { - feePerKw, err := s.cfg.Estimator.EstimateFeePerKW(confTarget) + feePerKw, err := DetermineFeePerKw(s.cfg.FeeEstimator, feePref) if err != nil { return nil, err } diff --git a/sweep/sweeper_test.go b/sweep/sweeper_test.go index 6a59f5dc5a..abce18b5a4 100644 --- a/sweep/sweeper_test.go +++ b/sweep/sweeper_test.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet" @@ -135,7 +136,7 @@ func createSweeperTestContext(t *testing.T) *sweeperTestContext { outputScriptCount++ return script, nil }, - Estimator: estimator, + FeeEstimator: estimator, MaxInputsPerTx: testMaxInputsPerTx, MaxSweepAttempts: testMaxSweepAttempts, NextAttemptDeltaFunc: func(attempts int) int32 { @@ -376,7 +377,8 @@ func TestNegativeInput(t *testing.T) { if !testTxIns(&sweepTx1, []*wire.OutPoint{ largeInput.OutPoint(), positiveInput.OutPoint(), }) { - t.Fatal("Tx does not contain expected inputs") + t.Fatalf("Tx does not contain expected inputs: %v", + spew.Sdump(sweepTx1)) } ctx.backend.mine() diff --git a/sweep/txgenerator.go b/sweep/txgenerator.go index e173706a29..3cf60d6b8c 100644 --- a/sweep/txgenerator.go +++ b/sweep/txgenerator.go @@ -55,7 +55,7 @@ func generateInputPartitionings(sweepableInputs []Input, // on the signature length, which is not known yet at this point. yields := make(map[wire.OutPoint]int64) for _, input := range sweepableInputs { - size, err := getInputWitnessSizeUpperBound(input) + size, _, err := getInputWitnessSizeUpperBound(input) if err != nil { return nil, fmt.Errorf( "failed adding input weight: %v", err) @@ -125,10 +125,14 @@ func getPositiveYieldInputs(sweepableInputs []Input, maxInputs int, for idx, input := range sweepableInputs { // Can ignore error, because it has already been checked when // calculating the yields. - size, _ := getInputWitnessSizeUpperBound(input) + size, isNestedP2SH, _ := getInputWitnessSizeUpperBound(input) // Keep a running weight estimate of the input set. - weightEstimate.AddWitnessInput(size) + if isNestedP2SH { + weightEstimate.AddNestedP2WSHInput(size) + } else { + weightEstimate.AddWitnessInput(size) + } newTotal := total + btcutil.Amount(input.SignDesc().Output.Value) @@ -216,25 +220,29 @@ func createSweepTx(inputs []Input, outputPkScript []byte, hashCache := txscript.NewTxSigHashes(sweepTx) - // With all the inputs in place, use each output's unique witness + // With all the inputs in place, use each output's unique input script // function to generate the final witness required for spending. - addWitness := func(idx int, tso Input) error { - witness, err := tso.BuildWitness( + addInputScript := func(idx int, tso Input) error { + inputScript, err := tso.CraftInputScript( signer, sweepTx, hashCache, idx, ) if err != nil { return err } - sweepTx.TxIn[idx].Witness = witness + sweepTx.TxIn[idx].Witness = inputScript.Witness + + if len(inputScript.SigScript) != 0 { + sweepTx.TxIn[idx].SignatureScript = inputScript.SigScript + } return nil } - // Finally we'll attach a valid witness to each csv and cltv input + // Finally we'll attach a valid input script to each csv and cltv input // within the sweeping transaction. for i, input := range inputs { - if err := addWitness(i, input); err != nil { + if err := addInputScript(i, input); err != nil { return nil, err } } @@ -243,45 +251,54 @@ func createSweepTx(inputs []Input, outputPkScript []byte, } // getInputWitnessSizeUpperBound returns the maximum length of the witness for -// the given input if it would be included in a tx. -func getInputWitnessSizeUpperBound(input Input) (int, error) { +// the given input if it would be included in a tx. We also return if the +// output itself is a nested p2sh output, if so then we need to take into +// account the extra sigScript data size. +func getInputWitnessSizeUpperBound(input Input) (int, bool, error) { switch input.WitnessType() { - // Outputs on a remote commitment transaction that pay directly - // to us. + // Outputs on a remote commitment transaction that pay directly to us. + case lnwallet.WitnessKeyHash: + fallthrough case lnwallet.CommitmentNoDelay: - return lnwallet.P2WKHWitnessSize, nil + return lnwallet.P2WKHWitnessSize, false, nil // Outputs on a past commitment transaction that pay directly // to us. case lnwallet.CommitmentTimeLock: - return lnwallet.ToLocalTimeoutWitnessSize, nil + return lnwallet.ToLocalTimeoutWitnessSize, false, nil // Outgoing second layer HTLC's that have confirmed within the // chain, and the output they produced is now mature enough to // sweep. case lnwallet.HtlcOfferedTimeoutSecondLevel: - return lnwallet.ToLocalTimeoutWitnessSize, nil + return lnwallet.ToLocalTimeoutWitnessSize, false, nil // Incoming second layer HTLC's that have confirmed within the // chain, and the output they produced is now mature enough to // sweep. case lnwallet.HtlcAcceptedSuccessSecondLevel: - return lnwallet.ToLocalTimeoutWitnessSize, nil + return lnwallet.ToLocalTimeoutWitnessSize, false, nil // An HTLC on the commitment transaction of the remote party, // that has had its absolute timelock expire. case lnwallet.HtlcOfferedRemoteTimeout: - return lnwallet.AcceptedHtlcTimeoutWitnessSize, nil + return lnwallet.AcceptedHtlcTimeoutWitnessSize, false, nil // An HTLC on the commitment transaction of the remote party, // that can be swept with the preimage. case lnwallet.HtlcAcceptedRemoteSuccess: - return lnwallet.OfferedHtlcSuccessWitnessSize, nil + return lnwallet.OfferedHtlcSuccessWitnessSize, false, nil + // A nested P2SH input that has a p2wkh witness script. We'll mark this + // as nested P2SH so the caller can estimate the weight properly + // including the sigScript. + case lnwallet.NestedWitnessKeyHash: + return lnwallet.P2WKHWitnessSize, true, nil } - return 0, fmt.Errorf("unexpected witness type: %v", input.WitnessType()) + return 0, false, fmt.Errorf("unexpected witness type: %v", + input.WitnessType()) } // getWeightEstimate returns a weight estimate for the given inputs. @@ -308,7 +325,10 @@ func getWeightEstimate(inputs []Input) ([]Input, int64, int, int) { for i := range inputs { input := inputs[i] - size, err := getInputWitnessSizeUpperBound(input) + // For fee estimation purposes, we'll now attempt to obtain an + // upper bound on the weight this input will add when fully + // populated. + size, isNestedP2SH, err := getInputWitnessSizeUpperBound(input) if err != nil { log.Warn(err) @@ -316,7 +336,14 @@ func getWeightEstimate(inputs []Input) ([]Input, int64, int, int) { // given. continue } - weightEstimate.AddWitnessInput(size) + + // If this is a nested P2SH input, then we'll need to factor in + // the additional data push within the sigScript. + if isNestedP2SH { + weightEstimate.AddNestedP2WSHInput(size) + } else { + weightEstimate.AddWitnessInput(size) + } switch input.WitnessType() { case lnwallet.CommitmentTimeLock, diff --git a/sweep/walletsweep.go b/sweep/walletsweep.go new file mode 100644 index 0000000000..1cfe905989 --- /dev/null +++ b/sweep/walletsweep.go @@ -0,0 +1,288 @@ +package sweep + +import ( + "fmt" + "math" + + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/lnwallet" +) + +const ( + // defaultNumBlocksEstimate is the number of blocks that we fall back + // to issuing an estimate for if a fee pre fence doesn't specify an + // explicit conf target or fee rate. + defaultNumBlocksEstimate = 6 +) + +// FeePreference allows callers to express their time value for inclusion of a +// transaction into a block via either a confirmation target, or a fee rate. +type FeePreference struct { + // ConfTarget if non-zero, signals a fee preference expressed in the + // number of desired blocks between first broadcast, and confirmation. + ConfTarget uint32 + + // FeeRate if non-zero, signals a fee pre fence expressed in the fee + // rate expressed in sat/kw for a particular transaction. + FeeRate lnwallet.SatPerKWeight +} + +// DetermineFeePerKw will determine the fee in sat/kw that should be paid given +// an estimator, a confirmation target, and a manual value for sat/byte. A +// value is chosen based on the two free parameters as one, or both of them can +// be zero. +func DetermineFeePerKw(feeEstimator lnwallet.FeeEstimator, + feePref FeePreference) (lnwallet.SatPerKWeight, error) { + + switch { + // If both values are set, then we'll return an error as we require a + // strict directive. + case feePref.FeeRate != 0 && feePref.ConfTarget != 0: + return 0, fmt.Errorf("only FeeRate or ConfTarget should " + + "be set for FeePreferences") + + // If the target number of confirmations is set, then we'll use that to + // consult our fee estimator for an adequate fee. + case feePref.ConfTarget != 0: + feePerKw, err := feeEstimator.EstimateFeePerKW( + uint32(feePref.ConfTarget), + ) + if err != nil { + return 0, fmt.Errorf("unable to query fee "+ + "estimator: %v", err) + } + + return feePerKw, nil + + // If a manual sat/byte fee rate is set, then we'll use that directly. + // We'll need to convert it to sat/kw as this is what we use + // internally. + case feePref.FeeRate != 0: + feePerKW := feePref.FeeRate + if feePerKW < lnwallet.FeePerKwFloor { + log.Infof("Manual fee rate input of %d sat/kw is "+ + "too low, using %d sat/kw instead", feePerKW, + lnwallet.FeePerKwFloor) + + feePerKW = lnwallet.FeePerKwFloor + } + + return feePerKW, nil + + // Otherwise, we'll attempt a relaxed confirmation target for the + // transaction + default: + feePerKw, err := feeEstimator.EstimateFeePerKW( + defaultNumBlocksEstimate, + ) + if err != nil { + return 0, fmt.Errorf("unable to query fee estimator: "+ + "%v", err) + } + + return feePerKw, nil + } +} + +// UtxoSource is an interface that allows a caller to access a source of UTXOs +// to use when crafting sweep transactions. +type UtxoSource interface { + // ListUnspentWitness returns all UTXOs from the source that have + // between minConfs and maxConfs number of confirmations. + ListUnspentWitness(minConfs, maxConfs int32) ([]*lnwallet.Utxo, error) + + // FetchInputInfo returns the matching output for an outpoint. If the + // outpoint doesn't belong to this UTXO source, then an error should be + // returned. + FetchInputInfo(*wire.OutPoint) (*wire.TxOut, error) +} + +// CoinSelectionLocker is an interface that allows the caller to perform an +// operation, which is synchronized with all coin selection attempts. This can +// be used when an operation requires that all coin selection operations cease +// forward progress. Think of this as an exclusive lock on coin selection +// operations. +type CoinSelectionLocker interface { + // WithCoinSelectLock will execute the passed function closure in a + // synchronized manner preventing any coin selection operations from + // proceeding while the closure if executing. This can be seen as the + // ability to execute a function closure under an exclusive coin + // selection lock. + WithCoinSelectLock(func() error) error +} + +// OutpointLocker allows a caller to lock/unlock an outpoint. When locked, the +// outpoints shouldn't be used for any sort of channel funding of coin +// selection. Locked outpoints are not expect to be persisted between restarts. +type OutpointLocker interface { + // LockOutpoint locks a target outpoint, rendering it unusable for coin + // selection. + LockOutpoint(o wire.OutPoint) + + // UnlockOutpoint unlocks a target outpoint, allowing it to be used for + // coin selection once again. + UnlockOutpoint(o wire.OutPoint) +} + +// WalletSweepPackage is a package that gives the caller the ability to sweep +// ALL funds from a wallet in a single transaction. We also package a function +// closure that allows one to abort the operation. +type WalletSweepPackage struct { + // SweepTx is a fully signed, and valid transaction that is broadcast, + // will sweep ALL confirmed coins in the wallet with a single + // transaction. + SweepTx *wire.MsgTx + + // CancelSweepAttempt allows the caller to cancel the sweep attempt. + // + // NOTE: If the sweeping transaction isn't or cannot be broadcast, then + // this closure MUST be called, otherwise all selected utxos will be + // unable to be used. + CancelSweepAttempt func() +} + +// CraftSweepAllTx attempts to craft a WalletSweepPackage which will allow the +// caller to sweep ALL outputs within the wallet to a single UTXO, as specified +// by the delivery address. The sweep transaction will be crafted with the +// target fee rate, and will use the utxoSource and outpointLocker as sources +// for wallet funds. +func CraftSweepAllTx(feeRate lnwallet.SatPerKWeight, blockHeight uint32, + deliveryAddr btcutil.Address, coinSelectLocker CoinSelectionLocker, + utxoSource UtxoSource, outpointLocker OutpointLocker, + feeEstimator lnwallet.FeeEstimator, + signer lnwallet.Signer) (*WalletSweepPackage, error) { + + // TODO(roasbeef): turn off ATPL as well when available? + + var allOutputs []*lnwallet.Utxo + + // We'll make a function closure up front that allows us to unlock all + // selected outputs to ensure that they become available again in the + // case of an error after the outputs have been locked, but before we + // can actually craft a sweeping transaction. + unlockOutputs := func() { + for _, utxo := range allOutputs { + outpointLocker.UnlockOutpoint(utxo.OutPoint) + } + } + + // Next, we'll use the coinSelectLocker to ensure that no coin + // selection takes place while we fetch and lock all outputs the wallet + // knows of. Otherwise, it may be possible for a new funding flow to + // lock an output while we fetch the set of unspent witnesses. + err := coinSelectLocker.WithCoinSelectLock(func() error { + // Now that we can be sure that no other coin selection + // operations are going on, we can grab a clean snapshot of the + // current UTXO state of the wallet. + utxos, err := utxoSource.ListUnspentWitness( + 1, math.MaxInt32, + ) + if err != nil { + return err + } + + // We'll now lock each UTXO to ensure that other callers don't + // attempt to use these UTXOs in transactions while we're + // crafting out sweep all transaction. + for _, utxo := range utxos { + outpointLocker.LockOutpoint(utxo.OutPoint) + } + + allOutputs = append(allOutputs, utxos...) + + return nil + }) + if err != nil { + // If we failed at all, we'll unlock any outputs selected just + // in case we had any lingering outputs. + unlockOutputs() + + return nil, fmt.Errorf("unable to fetch+lock wallet "+ + "utxos: %v", err) + } + + // Now that we've locked all the potential outputs to sweep, we'll + // assemble an input for each of them, so we can hand it off to the + // sweeper to generate and sign a transaction for us. + var inputsToSweep []Input + for _, output := range allOutputs { + // We'll consult the utxoSource for information concerning this + // outpoint, we'll need to properly populate a signDescriptor + // for this output. + outputInfo, err := utxoSource.FetchInputInfo(&output.OutPoint) + if err != nil { + unlockOutputs() + + return nil, err + } + + // As we'll be signing for outputs under control of the wallet, + // we only need to populate the output value and output script. + // The rest of the items will be populated internally within + // the sweeper via the witness generation function. + signDesc := &lnwallet.SignDescriptor{ + Output: outputInfo, + HashType: txscript.SigHashAll, + } + + pkScript := outputInfo.PkScript + + // Based on the output type, we'll map it to the proper witness + // type so we can generate the set of input scripts needed to + // sweep the output. + var witnessType lnwallet.WitnessType + switch { + + // If this is a p2wkh output, then we'll assume it's a witness + // key hash witness type. + case txscript.IsPayToWitnessPubKeyHash(pkScript): + witnessType = lnwallet.WitnessKeyHash + + // If this is a p2sh output, then as since it's under control + // of the wallet, we'll assume it's a nested p2sh output. + case txscript.IsPayToScriptHash(pkScript): + witnessType = lnwallet.NestedWitnessKeyHash + + // All other output types we count as unknown and will fail to + // sweep. + default: + unlockOutputs() + + return nil, fmt.Errorf("unable to sweep coins, "+ + "unknown script: %x", pkScript[:]) + } + + // Now that we've constructed the items required, we'll make an + // input which can be passed to the sweeper for ultimate + // sweeping. + input := MakeBaseInput(&output.OutPoint, witnessType, signDesc, 0) + inputsToSweep = append(inputsToSweep, &input) + } + + // Next, we'll convert the delivery addr to a pkScript that we can use + // to create the sweep transaction. + deliveryPkScript, err := txscript.PayToAddrScript(deliveryAddr) + if err != nil { + unlockOutputs() + + return nil, err + } + + // Finally, we'll ask the sweeper to craft a sweep transaction which + // respects our fee preference and targets all the UTXOs of the wallet. + sweepTx, err := createSweepTx( + inputsToSweep, deliveryPkScript, blockHeight, feeRate, signer, + ) + if err != nil { + unlockOutputs() + + return nil, err + } + + return &WalletSweepPackage{ + SweepTx: sweepTx, + CancelSweepAttempt: unlockOutputs, + }, nil +} diff --git a/sweep/walletsweep_test.go b/sweep/walletsweep_test.go new file mode 100644 index 0000000000..f8f692dbe7 --- /dev/null +++ b/sweep/walletsweep_test.go @@ -0,0 +1,409 @@ +package sweep + +import ( + "bytes" + "fmt" + "testing" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/lnwallet" +) + +// TestDetermineFeePerKw tests that given a fee preference, the +// DetermineFeePerKw will properly map it to a concrete fee in sat/kw. +func TestDetermineFeePerKw(t *testing.T) { + t.Parallel() + + defaultFee := lnwallet.SatPerKWeight(999) + relayFee := lnwallet.SatPerKWeight(300) + + feeEstimator := newMockFeeEstimator(defaultFee, relayFee) + + // We'll populate two items in the internal map which is used to query + // a fee based on a confirmation target: the default conf target, and + // an arbitrary conf target. We'll ensure below that both of these are + // properly + feeEstimator.blocksToFee[50] = 300 + feeEstimator.blocksToFee[defaultNumBlocksEstimate] = 1000 + + testCases := []struct { + // feePref is the target fee preference for this case. + feePref FeePreference + + // fee is the value the DetermineFeePerKw should return given + // the FeePreference above + fee lnwallet.SatPerKWeight + + // fail determines if this test case should fail or not. + fail bool + }{ + // A fee rate below the fee rate floor should output the floor. + { + feePref: FeePreference{ + FeeRate: lnwallet.SatPerKWeight(99), + }, + fee: lnwallet.FeePerKwFloor, + }, + + // A fee rate above the floor, should pass through and return + // the target fee rate. + { + feePref: FeePreference{ + FeeRate: 900, + }, + fee: 900, + }, + + // A specified confirmation target should cause the function to + // query the estimator which will return our value specified + // above. + { + feePref: FeePreference{ + ConfTarget: 50, + }, + fee: 300, + }, + + // If the caller doesn't specify any values at all, then we + // should query for the default conf target. + { + feePref: FeePreference{}, + fee: 1000, + }, + + // Both conf target and fee rate are set, we should return with + // an error. + { + feePref: FeePreference{ + ConfTarget: 50, + FeeRate: 90000, + }, + fee: 300, + fail: true, + }, + } + for i, testCase := range testCases { + targetFee, err := DetermineFeePerKw( + feeEstimator, testCase.feePref, + ) + switch { + case testCase.fail && err != nil: + continue + + case testCase.fail && err == nil: + t.Fatalf("expected failure for #%v", i) + + case !testCase.fail && err != nil: + t.Fatalf("unable to estimate fee; %v", err) + } + + if targetFee != testCase.fee { + t.Fatalf("#%v: wrong fee: expected %v got %v", i, + testCase.fee, targetFee) + } + } +} + +type mockUtxoSource struct { + outpoints map[wire.OutPoint]*wire.TxOut + + outputs []*lnwallet.Utxo +} + +func newMockUtxoSource(utxos []*lnwallet.Utxo) *mockUtxoSource { + m := &mockUtxoSource{ + outputs: utxos, + outpoints: make(map[wire.OutPoint]*wire.TxOut), + } + + for _, utxo := range utxos { + m.outpoints[utxo.OutPoint] = &wire.TxOut{ + Value: int64(utxo.Value), + PkScript: utxo.PkScript, + } + } + + return m +} + +func (m *mockUtxoSource) ListUnspentWitness(minConfs int32, + maxConfs int32) ([]*lnwallet.Utxo, error) { + + return m.outputs, nil +} + +func (m *mockUtxoSource) FetchInputInfo(op *wire.OutPoint) (*wire.TxOut, error) { + txOut, ok := m.outpoints[*op] + if !ok { + return nil, fmt.Errorf("no output found") + } + + return txOut, nil +} + +type mockCoinSelectionLocker struct { + fail bool +} + +func (m *mockCoinSelectionLocker) WithCoinSelectLock(f func() error) error { + if err := f(); err != nil { + return err + } + + if m.fail { + return fmt.Errorf("kek") + } + + return nil + +} + +type mockOutpointLocker struct { + lockedOutpoints map[wire.OutPoint]struct{} + + unlockedOutpoints map[wire.OutPoint]struct{} +} + +func newMockOutpointLocker() *mockOutpointLocker { + return &mockOutpointLocker{ + lockedOutpoints: make(map[wire.OutPoint]struct{}), + + unlockedOutpoints: make(map[wire.OutPoint]struct{}), + } +} + +func (m *mockOutpointLocker) LockOutpoint(o wire.OutPoint) { + m.lockedOutpoints[o] = struct{}{} +} +func (m *mockOutpointLocker) UnlockOutpoint(o wire.OutPoint) { + m.unlockedOutpoints[o] = struct{}{} +} + +var sweepScript = []byte{ + 0x0, 0x14, 0x64, 0x3d, 0x8b, 0x15, 0x69, 0x4a, 0x54, + 0x7d, 0x57, 0x33, 0x6e, 0x51, 0xdf, 0xfd, 0x38, 0xe3, + 0xe, 0x6e, 0xf8, 0xef, +} + +var deliveryAddr = func() btcutil.Address { + _, addrs, _, err := txscript.ExtractPkScriptAddrs( + sweepScript, &chaincfg.TestNet3Params, + ) + if err != nil { + panic(err) + } + + return addrs[0] +}() + +var testUtxos = []*lnwallet.Utxo{ + { + // A p2wkh output. + PkScript: []byte{ + 0x0, 0x14, 0x64, 0x3d, 0x8b, 0x15, 0x69, 0x4a, 0x54, + 0x7d, 0x57, 0x33, 0x6e, 0x51, 0xdf, 0xfd, 0x38, 0xe3, + 0xe, 0x6e, 0xf7, 0xef, + }, + Value: 1000, + OutPoint: wire.OutPoint{ + Index: 1, + }, + }, + + { + // A np2wkh output. + PkScript: []byte{ + 0xa9, 0x14, 0x97, 0x17, 0xf7, 0xd1, 0x5f, 0x6f, 0x8b, + 0x7, 0xe3, 0x58, 0x43, 0x19, 0xb9, 0x7e, 0xa9, 0x20, + 0x18, 0xc3, 0x17, 0xd7, 0x87, + }, + Value: 2000, + OutPoint: wire.OutPoint{ + Index: 2, + }, + }, + + // A p2wsh output. + { + PkScript: []byte{ + 0x0, 0x20, 0x70, 0x1a, 0x8d, 0x40, 0x1c, 0x84, 0xfb, 0x13, + 0xe6, 0xba, 0xf1, 0x69, 0xd5, 0x96, 0x84, 0xe2, 0x7a, 0xbd, + 0x9f, 0xa2, 0x16, 0xc8, 0xbc, 0x5b, 0x9f, 0xc6, 0x3d, 0x62, + 0x2f, 0xf8, 0xc5, 0x8c, + }, + Value: 3000, + OutPoint: wire.OutPoint{ + Index: 3, + }, + }, +} + +func assertUtxosLocked(t *testing.T, utxoLocker *mockOutpointLocker, + utxos []*lnwallet.Utxo) { + + t.Helper() + + for _, utxo := range utxos { + if _, ok := utxoLocker.lockedOutpoints[utxo.OutPoint]; !ok { + t.Fatalf("utxo %v was never locked", utxo.OutPoint) + } + } + +} + +func assertNoUtxosUnlocked(t *testing.T, utxoLocker *mockOutpointLocker, + utxos []*lnwallet.Utxo) { + + t.Helper() + + if len(utxoLocker.unlockedOutpoints) != 0 { + t.Fatalf("outputs have been locked, but shouldn't have been") + } +} + +func assertUtxosUnlocked(t *testing.T, utxoLocker *mockOutpointLocker, + utxos []*lnwallet.Utxo) { + + t.Helper() + + for _, utxo := range utxos { + if _, ok := utxoLocker.unlockedOutpoints[utxo.OutPoint]; !ok { + t.Fatalf("utxo %v was never unlocked", utxo.OutPoint) + } + } +} + +func assertUtxosLockedAndUnlocked(t *testing.T, utxoLocker *mockOutpointLocker, + utxos []*lnwallet.Utxo) { + + t.Helper() + + for _, utxo := range utxos { + if _, ok := utxoLocker.lockedOutpoints[utxo.OutPoint]; !ok { + t.Fatalf("utxo %v was never locked", utxo.OutPoint) + } + + if _, ok := utxoLocker.unlockedOutpoints[utxo.OutPoint]; !ok { + t.Fatalf("utxo %v was never unlocked", utxo.OutPoint) + } + } +} + +// TestCraftSweepAllTxCoinSelectFail tests that if coin selection fails, then +// we unlock any outputs we may have locked in the passed closure. +func TestCraftSweepAllTxCoinSelectFail(t *testing.T) { + t.Parallel() + + utxoSource := newMockUtxoSource(testUtxos) + coinSelectLocker := &mockCoinSelectionLocker{ + fail: true, + } + utxoLocker := newMockOutpointLocker() + + _, err := CraftSweepAllTx( + 0, 100, nil, coinSelectLocker, utxoSource, utxoLocker, nil, nil, + ) + + // Since we instructed the coin select locker to fail above, we should + // get an error. + if err == nil { + t.Fatalf("sweep tx should have failed: %v", err) + } + + // At this point, we'll now verify that all outputs were initially + // locked, and then also unlocked due to the failure. + assertUtxosLockedAndUnlocked(t, utxoLocker, testUtxos) +} + +// TestCraftSweepAllTxUnknownWitnessType tests that if one of the inputs we +// encounter is of an unknown witness type, then we fail and unlock any prior +// locked outputs. +func TestCraftSweepAllTxUnknownWitnessType(t *testing.T) { + t.Parallel() + + utxoSource := newMockUtxoSource(testUtxos) + coinSelectLocker := &mockCoinSelectionLocker{} + utxoLocker := newMockOutpointLocker() + + _, err := CraftSweepAllTx( + 0, 100, nil, coinSelectLocker, utxoSource, utxoLocker, nil, nil, + ) + + // Since passed in a p2wsh output, which is unknown, we should fail to + // map the output to a witness type. + if err == nil { + t.Fatalf("sweep tx should have failed: %v", err) + } + + // At this point, we'll now verify that all outputs were initially + // locked, and then also unlocked since we weren't able to find a + // witness type for the last output. + assertUtxosLockedAndUnlocked(t, utxoLocker, testUtxos) +} + +// TestCraftSweepAllTx tests that we'll properly lock all available outputs +// within the wallet, and craft a single sweep transaction that pays to the +// target output. +func TestCraftSweepAllTx(t *testing.T) { + t.Parallel() + + // First, we'll make a mock signer along with a fee estimator, We'll + // use zero fees to we can assert a precise output value. + signer := &mockSigner{} + feeEstimator := newMockFeeEstimator(0, 0) + + // For our UTXO source, we'll pass in all the UTXOs that we know of, + // other than the final one which is of an unknown witness type. + targetUTXOs := testUtxos[:2] + utxoSource := newMockUtxoSource(targetUTXOs) + coinSelectLocker := &mockCoinSelectionLocker{} + utxoLocker := newMockOutpointLocker() + + sweepPkg, err := CraftSweepAllTx( + 0, 100, deliveryAddr, coinSelectLocker, utxoSource, utxoLocker, + feeEstimator, signer, + ) + if err != nil { + t.Fatalf("unable to make sweep tx: %v", err) + } + + // At this point, all of the UTXOs that we made above should be locked + // and none of them unlocked. + assertUtxosLocked(t, utxoLocker, testUtxos[:2]) + assertNoUtxosUnlocked(t, utxoLocker, testUtxos[:2]) + + // Now that we have our sweep transaction, we should find that we have + // a UTXO for each input, and also that our final output value is the + // sum of all our inputs. + sweepTx := sweepPkg.SweepTx + if len(sweepTx.TxIn) != len(targetUTXOs) { + t.Fatalf("expected %v utxo, got %v", len(targetUTXOs), + len(sweepTx.TxIn)) + } + + // We should have a single output that pays to our sweep script + // generated above. + expectedSweepValue := int64(3000) + if len(sweepTx.TxOut) != 1 { + t.Fatalf("should have %v outputs, instead have %v", 1, + len(sweepTx.TxOut)) + } + output := sweepTx.TxOut[0] + switch { + case output.Value != expectedSweepValue: + t.Fatalf("expected %v sweep value, instead got %v", + expectedSweepValue, output.Value) + + case !bytes.Equal(sweepScript, output.PkScript): + t.Fatalf("expected %x sweep script, instead got %x", sweepScript, + output.PkScript) + } + + // If we cancel the sweep attempt, then we should find that all the + // UTXOs within the sweep transaction are now unlocked. + sweepPkg.CancelSweepAttempt() + assertUtxosUnlocked(t, utxoLocker, testUtxos[:2]) +}