lnrpc/walletrpc: expose pending input sweeps within UtxoSweeper over RPC

This commit is contained in:
Wilmer Paulino 2019-05-16 19:53:25 -07:00
parent d75fac26bc
commit d01f88ecdc
No known key found for this signature in database
GPG Key ID: 6DF57B9F9514972F
6 changed files with 603 additions and 36 deletions

@ -6,6 +6,7 @@ import (
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/sweep"
)
// Config is the primary configuration struct for the WalletKit RPC server. It
@ -38,4 +39,8 @@ type Config struct {
// KeyRing is an interface that the WalletKit will use to derive any
// keys due to incoming client requests.
KeyRing keychain.KeyRing
// Sweeper is the central batching engine of lnd. It is responsible for
// sweeping inputs in batches back into the wallet.
Sweeper *sweep.UtxoSweeper
}

@ -7,6 +7,7 @@ import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
lnrpc "github.com/lightningnetwork/lnd/lnrpc"
signrpc "github.com/lightningnetwork/lnd/lnrpc/signrpc"
grpc "google.golang.org/grpc"
math "math"
@ -23,6 +24,108 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type WitnessType int32
const (
WitnessType_UNKNOWN_WITNESS WitnessType = 0
//
//A witness that allows us to spend the output of a commitment transaction
//after a relative lock-time lockout.
WitnessType_COMMITMENT_TIME_LOCK WitnessType = 1
//
//A witness that allows us to spend a settled no-delay output immediately on a
//counterparty's commitment transaction.
WitnessType_COMMITMENT_NO_DELAY WitnessType = 2
//
//A witness that allows us to sweep the settled output of a malicious
//counterparty's who broadcasts a revoked commitment transaction.
WitnessType_COMMITMENT_REVOKE WitnessType = 3
//
//A witness that allows us to sweep an HTLC which we offered to the remote
//party in the case that they broadcast a revoked commitment state.
WitnessType_HTLC_OFFERED_REVOKE WitnessType = 4
//
//A witness that allows us to sweep an HTLC output sent to us in the case that
//the remote party broadcasts a revoked commitment state.
WitnessType_HTLC_ACCEPTED_REVOKE WitnessType = 5
//
//A witness that allows us to sweep an HTLC output that we extended to a
//party, but was never fulfilled. This HTLC output isn't directly on the
//commitment transaction, but is the result of a confirmed second-level HTLC
//transaction. As a result, we can only spend this after a CSV delay.
WitnessType_HTLC_OFFERED_TIMEOUT_SECOND_LEVEL WitnessType = 6
//
//A witness that allows us to sweep an HTLC output that was offered to us, and
//for which we have a payment preimage. This HTLC output isn't directly on our
//commitment transaction, but is the result of confirmed second-level HTLC
//transaction. As a result, we can only spend this after a CSV delay.
WitnessType_HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL WitnessType = 7
//
//A witness that allows us to sweep an HTLC that we offered to the remote
//party which lies in the commitment transaction of the remote party. We can
//spend this output after the absolute CLTV timeout of the HTLC as passed.
WitnessType_HTLC_OFFERED_REMOTE_TIMEOUT WitnessType = 8
//
//A witness that allows us to sweep an HTLC that was offered to us by the
//remote party. We use this witness in the case that the remote party goes to
//chain, and we know the pre-image to the HTLC. We can sweep this without any
//additional timeout.
WitnessType_HTLC_ACCEPTED_REMOTE_SUCCESS WitnessType = 9
//
//A witness that allows us to sweep an HTLC from the remote party's commitment
//transaction in the case that the broadcast a revoked commitment, but then
//also immediately attempt to go to the second level to claim the HTLC.
WitnessType_HTLC_SECOND_LEVEL_REVOKE WitnessType = 10
//
//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.
WitnessType_WITNESS_KEY_HASH WitnessType = 11
//
//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.
WitnessType_NESTED_WITNESS_KEY_HASH WitnessType = 12
)
var WitnessType_name = map[int32]string{
0: "UNKNOWN_WITNESS",
1: "COMMITMENT_TIME_LOCK",
2: "COMMITMENT_NO_DELAY",
3: "COMMITMENT_REVOKE",
4: "HTLC_OFFERED_REVOKE",
5: "HTLC_ACCEPTED_REVOKE",
6: "HTLC_OFFERED_TIMEOUT_SECOND_LEVEL",
7: "HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL",
8: "HTLC_OFFERED_REMOTE_TIMEOUT",
9: "HTLC_ACCEPTED_REMOTE_SUCCESS",
10: "HTLC_SECOND_LEVEL_REVOKE",
11: "WITNESS_KEY_HASH",
12: "NESTED_WITNESS_KEY_HASH",
}
var WitnessType_value = map[string]int32{
"UNKNOWN_WITNESS": 0,
"COMMITMENT_TIME_LOCK": 1,
"COMMITMENT_NO_DELAY": 2,
"COMMITMENT_REVOKE": 3,
"HTLC_OFFERED_REVOKE": 4,
"HTLC_ACCEPTED_REVOKE": 5,
"HTLC_OFFERED_TIMEOUT_SECOND_LEVEL": 6,
"HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL": 7,
"HTLC_OFFERED_REMOTE_TIMEOUT": 8,
"HTLC_ACCEPTED_REMOTE_SUCCESS": 9,
"HTLC_SECOND_LEVEL_REVOKE": 10,
"WITNESS_KEY_HASH": 11,
"NESTED_WITNESS_KEY_HASH": 12,
}
func (x WitnessType) String() string {
return proto.EnumName(WitnessType_name, int32(x))
}
func (WitnessType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_6cc6942ac78249e5, []int{0}
}
type KeyReq struct {
//*
//Is the key finger print of the root pubkey that this request is targeting.
@ -411,7 +514,170 @@ func (m *EstimateFeeResponse) GetSatPerKw() int64 {
return 0
}
type PendingSweep struct {
// The outpoint of the output we're attempting to sweep.
Outpoint *lnrpc.OutPoint `protobuf:"bytes,1,opt,name=outpoint,proto3" json:"outpoint,omitempty"`
// The witness type of the output we're attempting to sweep.
WitnessType WitnessType `protobuf:"varint,2,opt,name=witness_type,proto3,enum=walletrpc.WitnessType" json:"witness_type,omitempty"`
// The value of the output we're attempting to sweep.
AmountSat uint32 `protobuf:"varint,3,opt,name=amount_sat,proto3" json:"amount_sat,omitempty"`
//
//The fee rate we'll use to sweep the output. The fee rate is only determined
//once a sweeping transaction for the output is created, so it's possible for
//this to be 0 before this.
SatPerByte uint32 `protobuf:"varint,4,opt,name=sat_per_byte,proto3" json:"sat_per_byte,omitempty"`
// The number of broadcast attempts we've made to sweep the output.
BroadcastAttempts uint32 `protobuf:"varint,5,opt,name=broadcast_attempts,proto3" json:"broadcast_attempts,omitempty"`
//
//The next height of the chain at which we'll attempt to broadcast the
//sweep transaction of the output.
NextBroadcastHeight uint32 `protobuf:"varint,6,opt,name=next_broadcast_height,proto3" json:"next_broadcast_height,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PendingSweep) Reset() { *m = PendingSweep{} }
func (m *PendingSweep) String() string { return proto.CompactTextString(m) }
func (*PendingSweep) ProtoMessage() {}
func (*PendingSweep) Descriptor() ([]byte, []int) {
return fileDescriptor_6cc6942ac78249e5, []int{9}
}
func (m *PendingSweep) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PendingSweep.Unmarshal(m, b)
}
func (m *PendingSweep) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PendingSweep.Marshal(b, m, deterministic)
}
func (m *PendingSweep) XXX_Merge(src proto.Message) {
xxx_messageInfo_PendingSweep.Merge(m, src)
}
func (m *PendingSweep) XXX_Size() int {
return xxx_messageInfo_PendingSweep.Size(m)
}
func (m *PendingSweep) XXX_DiscardUnknown() {
xxx_messageInfo_PendingSweep.DiscardUnknown(m)
}
var xxx_messageInfo_PendingSweep proto.InternalMessageInfo
func (m *PendingSweep) GetOutpoint() *lnrpc.OutPoint {
if m != nil {
return m.Outpoint
}
return nil
}
func (m *PendingSweep) GetWitnessType() WitnessType {
if m != nil {
return m.WitnessType
}
return WitnessType_UNKNOWN_WITNESS
}
func (m *PendingSweep) GetAmountSat() uint32 {
if m != nil {
return m.AmountSat
}
return 0
}
func (m *PendingSweep) GetSatPerByte() uint32 {
if m != nil {
return m.SatPerByte
}
return 0
}
func (m *PendingSweep) GetBroadcastAttempts() uint32 {
if m != nil {
return m.BroadcastAttempts
}
return 0
}
func (m *PendingSweep) GetNextBroadcastHeight() uint32 {
if m != nil {
return m.NextBroadcastHeight
}
return 0
}
type PendingSweepsRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PendingSweepsRequest) Reset() { *m = PendingSweepsRequest{} }
func (m *PendingSweepsRequest) String() string { return proto.CompactTextString(m) }
func (*PendingSweepsRequest) ProtoMessage() {}
func (*PendingSweepsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_6cc6942ac78249e5, []int{10}
}
func (m *PendingSweepsRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PendingSweepsRequest.Unmarshal(m, b)
}
func (m *PendingSweepsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PendingSweepsRequest.Marshal(b, m, deterministic)
}
func (m *PendingSweepsRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_PendingSweepsRequest.Merge(m, src)
}
func (m *PendingSweepsRequest) XXX_Size() int {
return xxx_messageInfo_PendingSweepsRequest.Size(m)
}
func (m *PendingSweepsRequest) XXX_DiscardUnknown() {
xxx_messageInfo_PendingSweepsRequest.DiscardUnknown(m)
}
var xxx_messageInfo_PendingSweepsRequest proto.InternalMessageInfo
type PendingSweepsResponse struct {
//
//The set of outputs currently being swept by lnd's central batching engine.
PendingSweeps []*PendingSweep `protobuf:"bytes,1,rep,name=pending_sweeps,proto3" json:"pending_sweeps,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PendingSweepsResponse) Reset() { *m = PendingSweepsResponse{} }
func (m *PendingSweepsResponse) String() string { return proto.CompactTextString(m) }
func (*PendingSweepsResponse) ProtoMessage() {}
func (*PendingSweepsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_6cc6942ac78249e5, []int{11}
}
func (m *PendingSweepsResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PendingSweepsResponse.Unmarshal(m, b)
}
func (m *PendingSweepsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PendingSweepsResponse.Marshal(b, m, deterministic)
}
func (m *PendingSweepsResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_PendingSweepsResponse.Merge(m, src)
}
func (m *PendingSweepsResponse) XXX_Size() int {
return xxx_messageInfo_PendingSweepsResponse.Size(m)
}
func (m *PendingSweepsResponse) XXX_DiscardUnknown() {
xxx_messageInfo_PendingSweepsResponse.DiscardUnknown(m)
}
var xxx_messageInfo_PendingSweepsResponse proto.InternalMessageInfo
func (m *PendingSweepsResponse) GetPendingSweeps() []*PendingSweep {
if m != nil {
return m.PendingSweeps
}
return nil
}
func init() {
proto.RegisterEnum("walletrpc.WitnessType", WitnessType_name, WitnessType_value)
proto.RegisterType((*KeyReq)(nil), "walletrpc.KeyReq")
proto.RegisterType((*AddrRequest)(nil), "walletrpc.AddrRequest")
proto.RegisterType((*AddrResponse)(nil), "walletrpc.AddrResponse")
@ -421,45 +687,73 @@ func init() {
proto.RegisterType((*SendOutputsResponse)(nil), "walletrpc.SendOutputsResponse")
proto.RegisterType((*EstimateFeeRequest)(nil), "walletrpc.EstimateFeeRequest")
proto.RegisterType((*EstimateFeeResponse)(nil), "walletrpc.EstimateFeeResponse")
proto.RegisterType((*PendingSweep)(nil), "walletrpc.PendingSweep")
proto.RegisterType((*PendingSweepsRequest)(nil), "walletrpc.PendingSweepsRequest")
proto.RegisterType((*PendingSweepsResponse)(nil), "walletrpc.PendingSweepsResponse")
}
func init() { proto.RegisterFile("walletrpc/walletkit.proto", fileDescriptor_6cc6942ac78249e5) }
var fileDescriptor_6cc6942ac78249e5 = []byte{
// 524 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x5d, 0x6f, 0xd3, 0x30,
0x14, 0xd5, 0x56, 0x56, 0xd6, 0xdb, 0x76, 0x80, 0xcb, 0x46, 0x89, 0x18, 0x4c, 0x81, 0x87, 0x3e,
0xa0, 0x54, 0x6c, 0x02, 0x21, 0x78, 0x02, 0x6d, 0xd3, 0xa4, 0x4e, 0xac, 0x84, 0x4a, 0x48, 0x08,
0x29, 0x72, 0x93, 0xbb, 0xd4, 0x6a, 0x6a, 0x67, 0xce, 0x0d, 0x49, 0xfe, 0x0f, 0x3f, 0x14, 0xe5,
0xa3, 0x5d, 0x4a, 0x19, 0x4f, 0x71, 0x8e, 0xcf, 0x3d, 0xbe, 0xd7, 0xe7, 0x18, 0x9e, 0x26, 0x3c,
0x08, 0x90, 0x74, 0xe8, 0x0e, 0xcb, 0xd5, 0x5c, 0x90, 0x15, 0x6a, 0x45, 0x8a, 0xb5, 0x56, 0x5b,
0xc6, 0xe3, 0x48, 0xf8, 0x32, 0xe7, 0xe4, 0x5f, 0xd4, 0x25, 0xc1, 0xfc, 0x0a, 0xcd, 0x11, 0x66,
0x36, 0xde, 0xb0, 0x01, 0x3c, 0x9c, 0x63, 0xe6, 0x5c, 0x0b, 0xe9, 0xa3, 0x76, 0x42, 0x2d, 0x24,
0xf5, 0xb7, 0x8e, 0xb6, 0x06, 0x3b, 0xf6, 0xde, 0x1c, 0xb3, 0xf3, 0x02, 0x1e, 0xe7, 0x28, 0x3b,
0x04, 0x28, 0x98, 0x7c, 0x21, 0x82, 0xac, 0xbf, 0x5d, 0x70, 0x5a, 0x39, 0xa7, 0x00, 0xcc, 0x2e,
0xb4, 0x3f, 0x79, 0x9e, 0xb6, 0xf1, 0x26, 0xc6, 0x88, 0x4c, 0x13, 0x3a, 0xe5, 0x6f, 0x14, 0x2a,
0x19, 0x21, 0x63, 0x70, 0x8f, 0x7b, 0x9e, 0x2e, 0xb4, 0x5b, 0x76, 0xb1, 0x36, 0x5f, 0x41, 0x7b,
0xa2, 0xb9, 0x8c, 0xb8, 0x4b, 0x42, 0x49, 0xb6, 0x0f, 0x4d, 0x4a, 0x9d, 0x19, 0xa6, 0x05, 0xa9,
0x63, 0xef, 0x50, 0x7a, 0x81, 0xa9, 0xf9, 0x0e, 0x1e, 0x8c, 0xe3, 0x69, 0x20, 0xa2, 0xd9, 0x4a,
0xec, 0x25, 0x74, 0xc3, 0x12, 0x72, 0x50, 0x6b, 0xb5, 0x54, 0xed, 0x54, 0xe0, 0x59, 0x8e, 0x99,
0x3f, 0x81, 0x7d, 0x43, 0xe9, 0x5d, 0xc5, 0x14, 0xc6, 0x14, 0x55, 0x7d, 0xb1, 0x67, 0x00, 0x11,
0x27, 0x27, 0x44, 0xed, 0xcc, 0x93, 0xa2, 0xae, 0x61, 0xef, 0x46, 0x9c, 0xc6, 0xa8, 0x47, 0x09,
0x1b, 0xc0, 0x7d, 0x55, 0xf2, 0xfb, 0xdb, 0x47, 0x8d, 0x41, 0xfb, 0x78, 0xcf, 0xaa, 0xee, 0xcf,
0x9a, 0xa4, 0x57, 0x31, 0xd9, 0xcb, 0x6d, 0xf3, 0x35, 0xf4, 0xd6, 0xd4, 0xab, 0xce, 0xf6, 0xa1,
0xa9, 0x79, 0xe2, 0xd0, 0x6a, 0x06, 0xcd, 0x93, 0x49, 0x6a, 0xbe, 0x05, 0x76, 0x16, 0x91, 0x58,
0x70, 0xc2, 0x73, 0xc4, 0x65, 0x2f, 0x2f, 0xa0, 0xed, 0x2a, 0x79, 0xed, 0x10, 0xd7, 0x3e, 0x2e,
0xaf, 0x1d, 0x72, 0x68, 0x52, 0x20, 0xe6, 0x09, 0xf4, 0xd6, 0xca, 0xaa, 0x43, 0xfe, 0x3b, 0xc3,
0xf1, 0xef, 0x06, 0xb4, 0xbe, 0x17, 0xfe, 0x8f, 0x04, 0xb1, 0x0f, 0xd0, 0x3d, 0x45, 0x2d, 0x7e,
0xe1, 0x17, 0x4c, 0x69, 0x84, 0x19, 0x7b, 0x64, 0xad, 0xc2, 0x61, 0x95, 0x19, 0x30, 0x0e, 0x56,
0x43, 0x8e, 0x30, 0x3b, 0xc5, 0xc8, 0xd5, 0x22, 0x24, 0xa5, 0xd9, 0x7b, 0x68, 0x95, 0xb5, 0x79,
0x5d, 0xaf, 0x4e, 0xba, 0x54, 0x2e, 0x27, 0xa5, 0xef, 0xac, 0xfc, 0x08, 0xbb, 0xf9, 0x79, 0x79,
0x02, 0xd8, 0x41, 0xed, 0xc0, 0x5a, 0x42, 0x8c, 0x27, 0x1b, 0x78, 0x35, 0xde, 0x05, 0xb0, 0xca,
0xf0, 0x7a, 0x3a, 0xea, 0x32, 0x35, 0xdc, 0x30, 0x6a, 0xf8, 0xdf, 0x39, 0xb9, 0x84, 0x76, 0xcd,
0x24, 0x76, 0x58, 0xa3, 0x6e, 0x46, 0xc3, 0x78, 0x7e, 0xd7, 0xf6, 0xad, 0x5a, 0xcd, 0x8d, 0x35,
0xb5, 0x4d, 0x73, 0xd7, 0xd4, 0xfe, 0x61, 0xe2, 0xe7, 0x37, 0x3f, 0x86, 0xbe, 0xa0, 0x59, 0x3c,
0xb5, 0x5c, 0xb5, 0x18, 0x06, 0xc2, 0x9f, 0x91, 0x14, 0xd2, 0x97, 0x48, 0x89, 0xd2, 0xf3, 0x61,
0x20, 0xbd, 0x61, 0x20, 0x6f, 0x1f, 0xb7, 0x0e, 0xdd, 0x69, 0xb3, 0x78, 0xbc, 0x27, 0x7f, 0x02,
0x00, 0x00, 0xff, 0xff, 0x2d, 0xbb, 0xcd, 0x97, 0xfa, 0x03, 0x00, 0x00,
// 918 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x55, 0x5d, 0x6f, 0xe2, 0x46,
0x14, 0x2d, 0x21, 0x61, 0xc3, 0x05, 0x12, 0xef, 0x10, 0x12, 0x97, 0xcd, 0x6e, 0xa8, 0xfb, 0x21,
0xd4, 0x56, 0xa0, 0x66, 0xdb, 0xaa, 0x6a, 0x1f, 0xaa, 0x14, 0x1c, 0x11, 0xf1, 0x61, 0x6a, 0x3b,
0x9b, 0x6e, 0x55, 0x69, 0x64, 0x60, 0x16, 0x2c, 0xc0, 0x76, 0xc6, 0x43, 0xc1, 0xaf, 0xfd, 0x27,
0xfd, 0x97, 0x7d, 0xac, 0x3c, 0xb6, 0xc9, 0x98, 0x24, 0xfb, 0x14, 0xe7, 0x9c, 0x73, 0xcf, 0xdc,
0xb9, 0x33, 0x73, 0x80, 0x4f, 0xd7, 0xd6, 0x62, 0x41, 0x18, 0xf5, 0xc6, 0xcd, 0xe8, 0x6b, 0x6e,
0xb3, 0x86, 0x47, 0x5d, 0xe6, 0xa2, 0xfc, 0x96, 0xaa, 0xe6, 0xa9, 0x37, 0x8e, 0xd0, 0xea, 0x89,
0x6f, 0x4f, 0x9d, 0x50, 0x1e, 0xfe, 0x25, 0x34, 0x42, 0x95, 0xdf, 0x21, 0xd7, 0x25, 0x81, 0x4e,
0xee, 0x51, 0x1d, 0xa4, 0x39, 0x09, 0xf0, 0x07, 0xdb, 0x99, 0x12, 0x8a, 0x3d, 0x6a, 0x3b, 0x4c,
0xce, 0xd4, 0x32, 0xf5, 0x03, 0xfd, 0x68, 0x4e, 0x82, 0x6b, 0x0e, 0x0f, 0x43, 0x14, 0xbd, 0x06,
0xe0, 0x4a, 0x6b, 0x69, 0x2f, 0x02, 0x79, 0x8f, 0x6b, 0xf2, 0xa1, 0x86, 0x03, 0x4a, 0x09, 0x0a,
0x57, 0x93, 0x09, 0xd5, 0xc9, 0xfd, 0x8a, 0xf8, 0x4c, 0x51, 0xa0, 0x18, 0xfd, 0xeb, 0x7b, 0xae,
0xe3, 0x13, 0x84, 0x60, 0xdf, 0x9a, 0x4c, 0x28, 0xf7, 0xce, 0xeb, 0xfc, 0x5b, 0xf9, 0x02, 0x0a,
0x26, 0xb5, 0x1c, 0xdf, 0x1a, 0x33, 0xdb, 0x75, 0x50, 0x05, 0x72, 0x6c, 0x83, 0x67, 0x64, 0xc3,
0x45, 0x45, 0xfd, 0x80, 0x6d, 0x3a, 0x64, 0xa3, 0xfc, 0x08, 0xc7, 0xc3, 0xd5, 0x68, 0x61, 0xfb,
0xb3, 0xad, 0xd9, 0xe7, 0x50, 0xf2, 0x22, 0x08, 0x13, 0x4a, 0xdd, 0xc4, 0xb5, 0x18, 0x83, 0x6a,
0x88, 0x29, 0x7f, 0x01, 0x32, 0x88, 0x33, 0xd1, 0x56, 0xcc, 0x5b, 0x31, 0x3f, 0xee, 0x0b, 0x9d,
0x03, 0xf8, 0x16, 0xc3, 0x1e, 0xa1, 0x78, 0xbe, 0xe6, 0x75, 0x59, 0xfd, 0xd0, 0xb7, 0xd8, 0x90,
0xd0, 0xee, 0x1a, 0xd5, 0xe1, 0x85, 0x1b, 0xe9, 0xe5, 0xbd, 0x5a, 0xb6, 0x5e, 0xb8, 0x3c, 0x6a,
0xc4, 0xf3, 0x6b, 0x98, 0x1b, 0x6d, 0xc5, 0xf4, 0x84, 0x56, 0xbe, 0x85, 0x72, 0xca, 0x3d, 0xee,
0xac, 0x02, 0x39, 0x6a, 0xad, 0x31, 0xdb, 0xee, 0x81, 0x5a, 0x6b, 0x73, 0xa3, 0xfc, 0x00, 0x48,
0xf5, 0x99, 0xbd, 0xb4, 0x18, 0xb9, 0x26, 0x24, 0xe9, 0xe5, 0x02, 0x0a, 0x63, 0xd7, 0xf9, 0x80,
0x99, 0x45, 0xa7, 0x24, 0x19, 0x3b, 0x84, 0x90, 0xc9, 0x11, 0xe5, 0x2d, 0x94, 0x53, 0x65, 0xf1,
0x22, 0x1f, 0xdd, 0x83, 0xf2, 0xef, 0x1e, 0x14, 0x87, 0xc4, 0x99, 0xd8, 0xce, 0xd4, 0x58, 0x13,
0xe2, 0xa1, 0x6f, 0xe0, 0x30, 0xec, 0xda, 0x4d, 0x8e, 0xb6, 0x70, 0x79, 0xdc, 0x58, 0xf0, 0x3d,
0x69, 0x2b, 0x36, 0x0c, 0x61, 0x7d, 0x2b, 0x40, 0x3f, 0x43, 0x71, 0x6d, 0x33, 0x87, 0xf8, 0x3e,
0x66, 0x81, 0x47, 0xf8, 0x39, 0x1f, 0x5d, 0x9e, 0x36, 0xb6, 0x97, 0xab, 0x71, 0x17, 0xd1, 0x66,
0xe0, 0x11, 0x3d, 0xa5, 0x45, 0x6f, 0x00, 0xac, 0xa5, 0xbb, 0x72, 0x18, 0xf6, 0x2d, 0x26, 0x67,
0x6b, 0x99, 0x7a, 0x49, 0x17, 0x10, 0xa4, 0x40, 0x31, 0xe9, 0x7b, 0x14, 0x30, 0x22, 0xef, 0x73,
0x45, 0x0a, 0x43, 0x0d, 0x40, 0x23, 0xea, 0x5a, 0x93, 0xb1, 0xe5, 0x33, 0x6c, 0x31, 0x46, 0x96,
0x1e, 0xf3, 0xe5, 0x03, 0xae, 0x7c, 0x82, 0x41, 0xdf, 0x43, 0xc5, 0x21, 0x1b, 0x86, 0x1f, 0xa8,
0x19, 0xb1, 0xa7, 0x33, 0x26, 0xe7, 0x78, 0xc9, 0xd3, 0xa4, 0x72, 0x0a, 0x27, 0xe2, 0x88, 0x92,
0xdb, 0xa1, 0xfc, 0x01, 0x95, 0x1d, 0x3c, 0x1e, 0xf9, 0xaf, 0x70, 0xe4, 0x45, 0x04, 0xf6, 0x39,
0x23, 0x67, 0xf8, 0xfd, 0x38, 0x13, 0x06, 0x23, 0x56, 0xea, 0x3b, 0xf2, 0xaf, 0xff, 0xc9, 0x42,
0x41, 0x98, 0x1c, 0x2a, 0xc3, 0xf1, 0xed, 0xa0, 0x3b, 0xd0, 0xee, 0x06, 0xf8, 0xee, 0xc6, 0x1c,
0xa8, 0x86, 0x21, 0x7d, 0x82, 0x64, 0x38, 0x69, 0x69, 0xfd, 0xfe, 0x8d, 0xd9, 0x57, 0x07, 0x26,
0x36, 0x6f, 0xfa, 0x2a, 0xee, 0x69, 0xad, 0xae, 0x94, 0x41, 0x67, 0x50, 0x16, 0x98, 0x81, 0x86,
0xdb, 0x6a, 0xef, 0xea, 0xbd, 0xb4, 0x87, 0x2a, 0xf0, 0x52, 0x20, 0x74, 0xf5, 0x9d, 0xd6, 0x55,
0xa5, 0x6c, 0xa8, 0xef, 0x98, 0xbd, 0x16, 0xd6, 0xae, 0xaf, 0x55, 0x5d, 0x6d, 0x27, 0xc4, 0x7e,
0xb8, 0x04, 0x27, 0xae, 0x5a, 0x2d, 0x75, 0x68, 0x3e, 0x30, 0x07, 0xe8, 0x4b, 0xf8, 0x2c, 0x55,
0x12, 0x2e, 0xaf, 0xdd, 0x9a, 0xd8, 0x50, 0x5b, 0xda, 0xa0, 0x8d, 0x7b, 0xea, 0x3b, 0xb5, 0x27,
0xe5, 0xd0, 0x57, 0xa0, 0xa4, 0x0d, 0x8c, 0xdb, 0x56, 0x4b, 0x35, 0x8c, 0xb4, 0xee, 0x05, 0xba,
0x80, 0x57, 0x3b, 0x1d, 0xf4, 0x35, 0x53, 0x4d, 0x5c, 0xa5, 0x43, 0x54, 0x83, 0xf3, 0xdd, 0x4e,
0xb8, 0x22, 0xf6, 0x93, 0xf2, 0xe8, 0x1c, 0x64, 0xae, 0x10, 0x9d, 0x93, 0x7e, 0x01, 0x9d, 0x80,
0x14, 0x4f, 0x0e, 0x77, 0xd5, 0xf7, 0xb8, 0x73, 0x65, 0x74, 0xa4, 0x02, 0x7a, 0x05, 0x67, 0x03,
0xd5, 0x08, 0xed, 0x1e, 0x91, 0xc5, 0xcb, 0xff, 0xb2, 0x90, 0xbf, 0xe3, 0xe7, 0xd5, 0xb5, 0xc3,
0xab, 0x5e, 0x6a, 0x13, 0x6a, 0xff, 0x4d, 0x06, 0x64, 0xc3, 0xba, 0x24, 0x40, 0x2f, 0x85, 0xc3,
0x8c, 0xe2, 0xb1, 0x7a, 0xba, 0x7d, 0xff, 0x5d, 0x12, 0xb4, 0x89, 0x3f, 0xa6, 0xb6, 0xc7, 0x5c,
0x8a, 0x7e, 0x82, 0x7c, 0x54, 0x1b, 0xd6, 0x95, 0x45, 0x51, 0xcf, 0x1d, 0x5b, 0xcc, 0xa5, 0xcf,
0x56, 0xfe, 0x02, 0x87, 0xe1, 0x7a, 0x61, 0x38, 0x22, 0xf1, 0x59, 0x09, 0xe1, 0x59, 0x3d, 0x7b,
0x84, 0xc7, 0xd7, 0xb0, 0x03, 0x28, 0xce, 0x42, 0x31, 0x38, 0x45, 0x1b, 0x01, 0xaf, 0x56, 0xc5,
0xcb, 0xb9, 0x13, 0xa1, 0x3d, 0x28, 0x08, 0xf9, 0x85, 0x5e, 0x0b, 0xd2, 0xc7, 0xa9, 0x59, 0x7d,
0xf3, 0x1c, 0xfd, 0xe0, 0x26, 0x04, 0x55, 0xca, 0xed, 0x71, 0xee, 0xa5, 0xdc, 0x9e, 0xca, 0x37,
0x1d, 0x4a, 0xa9, 0x57, 0x88, 0x2e, 0x9e, 0x79, 0x65, 0xdb, 0xfe, 0x6a, 0xcf, 0x0b, 0x22, 0xcf,
0xdf, 0xbe, 0xfb, 0xb3, 0x39, 0xb5, 0xd9, 0x6c, 0x35, 0x6a, 0x8c, 0xdd, 0x65, 0x73, 0x11, 0xa6,
0x80, 0x63, 0x3b, 0x53, 0x87, 0xb0, 0xb5, 0x4b, 0xe7, 0xcd, 0x85, 0x33, 0x69, 0xf2, 0x4c, 0x6c,
0x6e, 0x8d, 0x46, 0x39, 0xfe, 0x5b, 0xf9, 0xf6, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xc4,
0xea, 0x93, 0x74, 0x07, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -502,6 +796,16 @@ type WalletKitClient interface {
//determine the fee (in sat/kw) to attach to a transaction in order to
//achieve the confirmation target.
EstimateFee(ctx context.Context, in *EstimateFeeRequest, opts ...grpc.CallOption) (*EstimateFeeResponse, error)
//
//PendingSweeps returns lists of on-chain outputs that lnd is currently
//attempting to sweep within its central batching engine. Outputs with similar
//fee rates are batched together in order to sweep them within a single
//transaction.
//
//NOTE: Some of the fields within PendingSweepsRequest are not guaranteed to
//remain supported. This is an advanced API that depends on the internals of
//the UtxoSweeper, so things may change.
PendingSweeps(ctx context.Context, in *PendingSweepsRequest, opts ...grpc.CallOption) (*PendingSweepsResponse, error)
}
type walletKitClient struct {
@ -566,6 +870,15 @@ func (c *walletKitClient) EstimateFee(ctx context.Context, in *EstimateFeeReques
return out, nil
}
func (c *walletKitClient) PendingSweeps(ctx context.Context, in *PendingSweepsRequest, opts ...grpc.CallOption) (*PendingSweepsResponse, error) {
out := new(PendingSweepsResponse)
err := c.cc.Invoke(ctx, "/walletrpc.WalletKit/PendingSweeps", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// WalletKitServer is the server API for WalletKit service.
type WalletKitServer interface {
//*
@ -596,6 +909,16 @@ type WalletKitServer interface {
//determine the fee (in sat/kw) to attach to a transaction in order to
//achieve the confirmation target.
EstimateFee(context.Context, *EstimateFeeRequest) (*EstimateFeeResponse, error)
//
//PendingSweeps returns lists of on-chain outputs that lnd is currently
//attempting to sweep within its central batching engine. Outputs with similar
//fee rates are batched together in order to sweep them within a single
//transaction.
//
//NOTE: Some of the fields within PendingSweepsRequest are not guaranteed to
//remain supported. This is an advanced API that depends on the internals of
//the UtxoSweeper, so things may change.
PendingSweeps(context.Context, *PendingSweepsRequest) (*PendingSweepsResponse, error)
}
func RegisterWalletKitServer(s *grpc.Server, srv WalletKitServer) {
@ -710,6 +1033,24 @@ func _WalletKit_EstimateFee_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler)
}
func _WalletKit_PendingSweeps_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PendingSweepsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletKitServer).PendingSweeps(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/walletrpc.WalletKit/PendingSweeps",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletKitServer).PendingSweeps(ctx, req.(*PendingSweepsRequest))
}
return interceptor(ctx, in, info, handler)
}
var _WalletKit_serviceDesc = grpc.ServiceDesc{
ServiceName: "walletrpc.WalletKit",
HandlerType: (*WalletKitServer)(nil),
@ -738,6 +1079,10 @@ var _WalletKit_serviceDesc = grpc.ServiceDesc{
MethodName: "EstimateFee",
Handler: _WalletKit_EstimateFee_Handler,
},
{
MethodName: "PendingSweeps",
Handler: _WalletKit_PendingSweeps_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "walletrpc/walletkit.proto",

@ -1,5 +1,6 @@
syntax = "proto3";
import "rpc.proto";
import "signrpc/signer.proto";
package walletrpc;
@ -81,6 +82,127 @@ message EstimateFeeResponse {
int64 sat_per_kw = 1;
}
enum WitnessType {
UNKNOWN_WITNESS = 0;
/*
A witness that allows us to spend the output of a commitment transaction
after a relative lock-time lockout.
*/
COMMITMENT_TIME_LOCK = 1;
/*
A witness that allows us to spend a settled no-delay output immediately on a
counterparty's commitment transaction.
*/
COMMITMENT_NO_DELAY = 2;
/*
A witness that allows us to sweep the settled output of a malicious
counterparty's who broadcasts a revoked commitment transaction.
*/
COMMITMENT_REVOKE = 3;
/*
A witness that allows us to sweep an HTLC which we offered to the remote
party in the case that they broadcast a revoked commitment state.
*/
HTLC_OFFERED_REVOKE = 4;
/*
A witness that allows us to sweep an HTLC output sent to us in the case that
the remote party broadcasts a revoked commitment state.
*/
HTLC_ACCEPTED_REVOKE = 5;
/*
A witness that allows us to sweep an HTLC output that we extended to a
party, but was never fulfilled. This HTLC output isn't directly on the
commitment transaction, but is the result of a confirmed second-level HTLC
transaction. As a result, we can only spend this after a CSV delay.
*/
HTLC_OFFERED_TIMEOUT_SECOND_LEVEL = 6;
/*
A witness that allows us to sweep an HTLC output that was offered to us, and
for which we have a payment preimage. This HTLC output isn't directly on our
commitment transaction, but is the result of confirmed second-level HTLC
transaction. As a result, we can only spend this after a CSV delay.
*/
HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL = 7;
/*
A witness that allows us to sweep an HTLC that we offered to the remote
party which lies in the commitment transaction of the remote party. We can
spend this output after the absolute CLTV timeout of the HTLC as passed.
*/
HTLC_OFFERED_REMOTE_TIMEOUT = 8;
/*
A witness that allows us to sweep an HTLC that was offered to us by the
remote party. We use this witness in the case that the remote party goes to
chain, and we know the pre-image to the HTLC. We can sweep this without any
additional timeout.
*/
HTLC_ACCEPTED_REMOTE_SUCCESS = 9;
/*
A witness that allows us to sweep an HTLC from the remote party's commitment
transaction in the case that the broadcast a revoked commitment, but then
also immediately attempt to go to the second level to claim the HTLC.
*/
HTLC_SECOND_LEVEL_REVOKE = 10;
/*
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.
*/
WITNESS_KEY_HASH = 11;
/*
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.
*/
NESTED_WITNESS_KEY_HASH = 12;
}
message PendingSweep {
// The outpoint of the output we're attempting to sweep.
lnrpc.OutPoint outpoint = 1 [json_name = "outpoint"];
// The witness type of the output we're attempting to sweep.
WitnessType witness_type = 2 [json_name = "witness_type"];
// The value of the output we're attempting to sweep.
uint32 amount_sat = 3 [json_name = "amount_sat"];
/*
The fee rate we'll use to sweep the output. The fee rate is only determined
once a sweeping transaction for the output is created, so it's possible for
this to be 0 before this.
*/
uint32 sat_per_byte = 4 [json_name = "sat_per_byte"];
// The number of broadcast attempts we've made to sweep the output.
uint32 broadcast_attempts = 5 [json_name = "broadcast_attempts"];
/*
The next height of the chain at which we'll attempt to broadcast the
sweep transaction of the output.
*/
uint32 next_broadcast_height = 6 [json_name = "next_broadcast_height"];
}
message PendingSweepsRequest {
}
message PendingSweepsResponse {
/*
The set of outputs currently being swept by lnd's central batching engine.
*/
repeated PendingSweep pending_sweeps = 1 [json_name = "pending_sweeps"];
}
service WalletKit {
/**
DeriveNextKey attempts to derive the *next* key within the key family
@ -121,4 +243,16 @@ service WalletKit {
achieve the confirmation target.
*/
rpc EstimateFee(EstimateFeeRequest) returns (EstimateFeeResponse);
/*
PendingSweeps returns lists of on-chain outputs that lnd is currently
attempting to sweep within its central batching engine. Outputs with similar
fee rates are batched together in order to sweep them within a single
transaction.
NOTE: Some of the fields within PendingSweepsRequest are not guaranteed to
remain supported. This is an advanced API that depends on the internals of
the UtxoSweeper, so things may change.
*/
rpc PendingSweeps(PendingSweepsRequest) returns (PendingSweepsResponse);
}

@ -10,6 +10,7 @@ import (
"path/filepath"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
@ -74,6 +75,10 @@ var (
Entity: "onchain",
Action: "read",
}},
"/walletrpc.WalletKit/PendingSweeps": {{
Entity: "onchain",
Action: "read",
}},
}
// DefaultWalletKitMacFilename is the default name of the wallet kit
@ -331,3 +336,76 @@ func (w *WalletKit) EstimateFee(ctx context.Context,
SatPerKw: int64(satPerKw),
}, nil
}
// PendingSweeps returns lists of on-chain outputs that lnd is currently
// attempting to sweep within its central batching engine. Outputs with similar
// fee rates are batched together in order to sweep them within a single
// transaction. The fee rate of each sweeping transaction is determined by
// taking the average fee rate of all the outputs it's trying to sweep.
func (w *WalletKit) PendingSweeps(ctx context.Context,
in *PendingSweepsRequest) (*PendingSweepsResponse, error) {
// Retrieve all of the outputs the UtxoSweeper is currently trying to
// sweep.
pendingInputs, err := w.cfg.Sweeper.PendingInputs()
if err != nil {
return nil, err
}
// Convert them into their respective RPC format.
rpcPendingSweeps := make([]*PendingSweep, 0, len(pendingInputs))
for _, pendingInput := range pendingInputs {
var witnessType WitnessType
switch pendingInput.WitnessType {
case input.CommitmentTimeLock:
witnessType = WitnessType_COMMITMENT_TIME_LOCK
case input.CommitmentNoDelay:
witnessType = WitnessType_COMMITMENT_NO_DELAY
case input.CommitmentRevoke:
witnessType = WitnessType_COMMITMENT_REVOKE
case input.HtlcOfferedRevoke:
witnessType = WitnessType_HTLC_OFFERED_REVOKE
case input.HtlcAcceptedRevoke:
witnessType = WitnessType_HTLC_ACCEPTED_REVOKE
case input.HtlcOfferedTimeoutSecondLevel:
witnessType = WitnessType_HTLC_OFFERED_TIMEOUT_SECOND_LEVEL
case input.HtlcAcceptedSuccessSecondLevel:
witnessType = WitnessType_HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL
case input.HtlcOfferedRemoteTimeout:
witnessType = WitnessType_HTLC_OFFERED_REMOTE_TIMEOUT
case input.HtlcAcceptedRemoteSuccess:
witnessType = WitnessType_HTLC_ACCEPTED_REMOTE_SUCCESS
case input.HtlcSecondLevelRevoke:
witnessType = WitnessType_HTLC_SECOND_LEVEL_REVOKE
case input.WitnessKeyHash:
witnessType = WitnessType_WITNESS_KEY_HASH
case input.NestedWitnessKeyHash:
witnessType = WitnessType_NESTED_WITNESS_KEY_HASH
default:
log.Warnf("Unhandled witness type %v for input %v",
pendingInput.WitnessType, pendingInput.OutPoint)
}
op := &lnrpc.OutPoint{
TxidBytes: pendingInput.OutPoint.Hash[:],
OutputIndex: pendingInput.OutPoint.Index,
}
amountSat := uint32(pendingInput.Amount)
satPerByte := uint32(pendingInput.LastFeeRate.FeePerKVByte() / 1000)
broadcastAttempts := uint32(pendingInput.BroadcastAttempts)
nextBroadcastHeight := uint32(pendingInput.NextBroadcastHeight)
rpcPendingSweeps = append(rpcPendingSweeps, &PendingSweep{
Outpoint: op,
WitnessType: witnessType,
AmountSat: amountSat,
SatPerByte: satPerByte,
BroadcastAttempts: broadcastAttempts,
NextBroadcastHeight: nextBroadcastHeight,
})
}
return &PendingSweepsResponse{
PendingSweeps: rpcPendingSweeps,
}, nil
}

@ -491,7 +491,7 @@ func newRPCServer(s *server, macService *macaroons.Service,
err = subServerCgs.PopulateDependencies(
s.cc, networkDir, macService, atpl, invoiceRegistry,
s.htlcSwitch, activeNetParams.Params, s.chanRouter,
routerBackend, s.nodeSigner, s.chanDB,
routerBackend, s.nodeSigner, s.chanDB, s.sweeper,
)
if err != nil {
return nil, err

@ -18,6 +18,7 @@ import (
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/netann"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/sweep"
)
// subRPCServerConfigs is special sub-config in the main configuration that
@ -72,7 +73,8 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
chanRouter *routing.ChannelRouter,
routerBackend *routerrpc.RouterBackend,
nodeSigner *netann.NodeSigner,
chanDB *channeldb.DB) error {
chanDB *channeldb.DB,
sweeper *sweep.UtxoSweeper) error {
// First, we'll use reflect to obtain a version of the config struct
// that allows us to programmatically inspect its fields.
@ -129,6 +131,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
subCfgValue.FieldByName("KeyRing").Set(
reflect.ValueOf(cc.keyRing),
)
subCfgValue.FieldByName("Sweeper").Set(
reflect.ValueOf(sweeper),
)
case *autopilotrpc.Config:
subCfgValue := extractReflectValue(subCfg)