Merge pull request #5095 from bottlepay/wtxmgr-parameterized-lock

lnwallet+walletrpc: list leases and parameterize duration
This commit is contained in:
Olaoluwa Osuntokun 2021-03-25 17:31:13 -07:00 committed by GitHub
commit 24d1d9cb14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 491 additions and 167 deletions

@ -46,6 +46,7 @@ func walletCommands() []cli.Command {
listSweepsCommand, listSweepsCommand,
labelTxCommand, labelTxCommand,
releaseOutputCommand, releaseOutputCommand,
listLeasesCommand,
psbtCommand, psbtCommand,
}, },
}, },
@ -605,14 +606,7 @@ func fundPsbt(ctx *cli.Context) error {
return err return err
} }
jsonLocks := make([]*utxoLease, len(response.LockedUtxos)) jsonLocks := marshallLocks(response.LockedUtxos)
for idx, lock := range response.LockedUtxos {
jsonLocks[idx] = &utxoLease{
ID: hex.EncodeToString(lock.Id),
OutPoint: NewOutPointFromProto(lock.Outpoint),
Expiration: lock.Expiration,
}
}
printJSON(&fundPsbtResponse{ printJSON(&fundPsbtResponse{
Psbt: base64.StdEncoding.EncodeToString( Psbt: base64.StdEncoding.EncodeToString(
@ -625,6 +619,21 @@ func fundPsbt(ctx *cli.Context) error {
return nil return nil
} }
// marshallLocks converts the rpc lease information to a more json-friendly
// format.
func marshallLocks(lockedUtxos []*walletrpc.UtxoLease) []*utxoLease {
jsonLocks := make([]*utxoLease, len(lockedUtxos))
for idx, lock := range lockedUtxos {
jsonLocks[idx] = &utxoLease{
ID: hex.EncodeToString(lock.Id),
OutPoint: NewOutPointFromProto(lock.Outpoint),
Expiration: lock.Expiration,
}
}
return jsonLocks
}
// finalizePsbtResponse is a struct that contains JSON annotations for nice // finalizePsbtResponse is a struct that contains JSON annotations for nice
// result serialization. // result serialization.
type finalizePsbtResponse struct { type finalizePsbtResponse struct {
@ -767,3 +776,25 @@ func releaseOutput(ctx *cli.Context) error {
return nil return nil
} }
var listLeasesCommand = cli.Command{
Name: "listleases",
Usage: "Return a list of currently held leases.",
Action: actionDecorator(listLeases),
}
func listLeases(ctx *cli.Context) error {
req := &walletrpc.ListLeasesRequest{}
walletClient, cleanUp := getWalletClient(ctx)
defer cleanUp()
response, err := walletClient.ListLeases(context.Background(), req)
if err != nil {
return err
}
printJSON(marshallLocks(response.LockedUtxos))
return nil
}

4
go.mod

@ -9,11 +9,11 @@ require (
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
github.com/btcsuite/btcutil v1.0.2 github.com/btcsuite/btcutil v1.0.2
github.com/btcsuite/btcutil/psbt v1.0.3-0.20200826194809-5f93e33af2b0 github.com/btcsuite/btcutil/psbt v1.0.3-0.20200826194809-5f93e33af2b0
github.com/btcsuite/btcwallet v0.11.1-0.20201207233335-415f37ff11a1 github.com/btcsuite/btcwallet v0.11.1-0.20210312232944-4ec908df9386
github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0
github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.0.0
github.com/btcsuite/btcwallet/walletdb v1.3.4 github.com/btcsuite/btcwallet/walletdb v1.3.4
github.com/btcsuite/btcwallet/wtxmgr v1.2.0 github.com/btcsuite/btcwallet/wtxmgr v1.2.1-0.20210312232944-4ec908df9386
github.com/coreos/etcd v3.3.22+incompatible github.com/coreos/etcd v3.3.22+incompatible
github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect

7
go.sum

@ -35,8 +35,8 @@ github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2ut
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
github.com/btcsuite/btcutil/psbt v1.0.3-0.20200826194809-5f93e33af2b0 h1:3Zumkyl6PWyHuVJ04me0xeD9CnPOhNgeGpapFbzy7O4= github.com/btcsuite/btcutil/psbt v1.0.3-0.20200826194809-5f93e33af2b0 h1:3Zumkyl6PWyHuVJ04me0xeD9CnPOhNgeGpapFbzy7O4=
github.com/btcsuite/btcutil/psbt v1.0.3-0.20200826194809-5f93e33af2b0/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= github.com/btcsuite/btcutil/psbt v1.0.3-0.20200826194809-5f93e33af2b0/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ=
github.com/btcsuite/btcwallet v0.11.1-0.20201207233335-415f37ff11a1 h1:3gvLezYoUkr9MvxocB/vyPNzL+gSqsNT4Q6XTPK+R04= github.com/btcsuite/btcwallet v0.11.1-0.20210312232944-4ec908df9386 h1:DfZIXWPAm35bW83OtS/AXH9A9pE6dxxIUhf260S9Wmo=
github.com/btcsuite/btcwallet v0.11.1-0.20201207233335-415f37ff11a1/go.mod h1:P1U4LKSB/bhFQdOM7ab1XqNoBGFyFAe7eKObEBD9mIo= github.com/btcsuite/btcwallet v0.11.1-0.20210312232944-4ec908df9386/go.mod h1:P1U4LKSB/bhFQdOM7ab1XqNoBGFyFAe7eKObEBD9mIo=
github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c=
github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU=
github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w=
@ -48,8 +48,9 @@ github.com/btcsuite/btcwallet/walletdb v1.3.2/go.mod h1:GZCMPNpUu5KE3ASoVd+k06p/
github.com/btcsuite/btcwallet/walletdb v1.3.4 h1:ExdPQSfYRLoYMEENsjWyl4w0PePLm9w3wg69nsRS2xc= github.com/btcsuite/btcwallet/walletdb v1.3.4 h1:ExdPQSfYRLoYMEENsjWyl4w0PePLm9w3wg69nsRS2xc=
github.com/btcsuite/btcwallet/walletdb v1.3.4/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= github.com/btcsuite/btcwallet/walletdb v1.3.4/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU=
github.com/btcsuite/btcwallet/wtxmgr v1.0.0/go.mod h1:vc4gBprll6BP0UJ+AIGDaySoc7MdAmZf8kelfNb8CFY= github.com/btcsuite/btcwallet/wtxmgr v1.0.0/go.mod h1:vc4gBprll6BP0UJ+AIGDaySoc7MdAmZf8kelfNb8CFY=
github.com/btcsuite/btcwallet/wtxmgr v1.2.0 h1:ZUYPsSv8GjF9KK7lboB2OVHF0uYEcHxgrCfFWqPd9NA=
github.com/btcsuite/btcwallet/wtxmgr v1.2.0/go.mod h1:h8hkcKUE3X7lMPzTUoGnNiw5g7VhGrKEW3KpR2r0VnY= github.com/btcsuite/btcwallet/wtxmgr v1.2.0/go.mod h1:h8hkcKUE3X7lMPzTUoGnNiw5g7VhGrKEW3KpR2r0VnY=
github.com/btcsuite/btcwallet/wtxmgr v1.2.1-0.20210312232944-4ec908df9386 h1:lCSgu8j264LfpszU3NIiTJbtlT/jL+lsfGHWpSUscpE=
github.com/btcsuite/btcwallet/wtxmgr v1.2.1-0.20210312232944-4ec908df9386/go.mod h1:awQsh1n/0ZrEQ+JZgWvHeo153ubzEisf/FyNtwI0dDk=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc=

@ -267,6 +267,8 @@ http:
- selector: walletrpc.WalletKit.ReleaseOutput - selector: walletrpc.WalletKit.ReleaseOutput
post: "/v2/wallet/utxos/release" post: "/v2/wallet/utxos/release"
body: "*" body: "*"
- selector: walletrpc.WalletKit.ListLeases
post: "/v2/wallet/utxos/leases"
- selector: walletrpc.WalletKit.DeriveNextKey - selector: walletrpc.WalletKit.DeriveNextKey
post: "/v2/wallet/key/next" post: "/v2/wallet/key/next"
body: "*" body: "*"

@ -18,13 +18,10 @@ const (
defaultMaxConf = math.MaxInt32 defaultMaxConf = math.MaxInt32
) )
// utxoLock is a type that contains an outpoint of an UTXO and its lock lease var (
// information. // DefaultLockDuration is the default duration used to lock outputs.
type utxoLock struct { DefaultLockDuration = 10 * time.Minute
lockID wtxmgr.LockID )
outpoint wire.OutPoint
expiration time.Time
}
// verifyInputsUnspent checks that all inputs are contained in the list of // verifyInputsUnspent checks that all inputs are contained in the list of
// known, non-locked UTXOs given. // known, non-locked UTXOs given.
@ -50,24 +47,26 @@ func verifyInputsUnspent(inputs []*wire.TxIn, utxos []*lnwallet.Utxo) error {
// lockInputs requests a lock lease for all inputs specified in a PSBT packet // lockInputs requests a lock lease for all inputs specified in a PSBT packet
// by using the internal, static lock ID of lnd's wallet. // by using the internal, static lock ID of lnd's wallet.
func lockInputs(w lnwallet.WalletController, packet *psbt.Packet) ([]*utxoLock, func lockInputs(w lnwallet.WalletController, packet *psbt.Packet) (
error) { []*wtxmgr.LockedOutput, error) {
locks := make([]*utxoLock, len(packet.UnsignedTx.TxIn)) locks := make([]*wtxmgr.LockedOutput, len(packet.UnsignedTx.TxIn))
for idx, rawInput := range packet.UnsignedTx.TxIn { for idx, rawInput := range packet.UnsignedTx.TxIn {
lock := &utxoLock{ lock := &wtxmgr.LockedOutput{
lockID: LndInternalLockID, LockID: LndInternalLockID,
outpoint: rawInput.PreviousOutPoint, Outpoint: rawInput.PreviousOutPoint,
} }
expiration, err := w.LeaseOutput(lock.lockID, lock.outpoint) expiration, err := w.LeaseOutput(
lock.LockID, lock.Outpoint, DefaultLockDuration,
)
if err != nil { if err != nil {
// If we run into a problem with locking one output, we // If we run into a problem with locking one output, we
// should try to unlock those that we successfully // should try to unlock those that we successfully
// locked so far. If that fails as well, there's not // locked so far. If that fails as well, there's not
// much we can do. // much we can do.
for i := 0; i < idx; i++ { for i := 0; i < idx; i++ {
op := locks[i].outpoint op := locks[i].Outpoint
if err := w.ReleaseOutput( if err := w.ReleaseOutput(
LndInternalLockID, op, LndInternalLockID, op,
); err != nil { ); err != nil {
@ -81,7 +80,7 @@ func lockInputs(w lnwallet.WalletController, packet *psbt.Packet) ([]*utxoLock,
"UTXO: %v", err) "UTXO: %v", err)
} }
lock.expiration = expiration lock.Expiration = expiration
locks[idx] = lock locks[idx] = lock
} }

@ -229,10 +229,13 @@ type LeaseOutputRequest struct {
//using this RPC which will be used to bound the output lease to. //using this RPC which will be used to bound the output lease to.
Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// The identifying outpoint of the output being leased. // The identifying outpoint of the output being leased.
Outpoint *lnrpc.OutPoint `protobuf:"bytes,2,opt,name=outpoint,proto3" json:"outpoint,omitempty"` Outpoint *lnrpc.OutPoint `protobuf:"bytes,2,opt,name=outpoint,proto3" json:"outpoint,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` // The time in seconds before the lock expires. If set to zero, the default
XXX_unrecognized []byte `json:"-"` // lock duration is used.
XXX_sizecache int32 `json:"-"` ExpirationSeconds uint64 `protobuf:"varint,3,opt,name=expiration_seconds,json=expirationSeconds,proto3" json:"expiration_seconds,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *LeaseOutputRequest) Reset() { *m = LeaseOutputRequest{} } func (m *LeaseOutputRequest) Reset() { *m = LeaseOutputRequest{} }
@ -274,6 +277,13 @@ func (m *LeaseOutputRequest) GetOutpoint() *lnrpc.OutPoint {
return nil return nil
} }
func (m *LeaseOutputRequest) GetExpirationSeconds() uint64 {
if m != nil {
return m.ExpirationSeconds
}
return 0
}
type LeaseOutputResponse struct { type LeaseOutputResponse struct {
// //
//The absolute expiration of the output lease represented as a unix timestamp. //The absolute expiration of the output lease represented as a unix timestamp.
@ -1763,6 +1773,77 @@ func (m *FinalizePsbtResponse) GetRawFinalTx() []byte {
return nil return nil
} }
type ListLeasesRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListLeasesRequest) Reset() { *m = ListLeasesRequest{} }
func (m *ListLeasesRequest) String() string { return proto.CompactTextString(m) }
func (*ListLeasesRequest) ProtoMessage() {}
func (*ListLeasesRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_6cc6942ac78249e5, []int{30}
}
func (m *ListLeasesRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListLeasesRequest.Unmarshal(m, b)
}
func (m *ListLeasesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListLeasesRequest.Marshal(b, m, deterministic)
}
func (m *ListLeasesRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListLeasesRequest.Merge(m, src)
}
func (m *ListLeasesRequest) XXX_Size() int {
return xxx_messageInfo_ListLeasesRequest.Size(m)
}
func (m *ListLeasesRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ListLeasesRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ListLeasesRequest proto.InternalMessageInfo
type ListLeasesResponse struct {
// The list of currently leased utxos.
LockedUtxos []*UtxoLease `protobuf:"bytes,1,rep,name=locked_utxos,json=lockedUtxos,proto3" json:"locked_utxos,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListLeasesResponse) Reset() { *m = ListLeasesResponse{} }
func (m *ListLeasesResponse) String() string { return proto.CompactTextString(m) }
func (*ListLeasesResponse) ProtoMessage() {}
func (*ListLeasesResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_6cc6942ac78249e5, []int{31}
}
func (m *ListLeasesResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListLeasesResponse.Unmarshal(m, b)
}
func (m *ListLeasesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListLeasesResponse.Marshal(b, m, deterministic)
}
func (m *ListLeasesResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListLeasesResponse.Merge(m, src)
}
func (m *ListLeasesResponse) XXX_Size() int {
return xxx_messageInfo_ListLeasesResponse.Size(m)
}
func (m *ListLeasesResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ListLeasesResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ListLeasesResponse proto.InternalMessageInfo
func (m *ListLeasesResponse) GetLockedUtxos() []*UtxoLease {
if m != nil {
return m.LockedUtxos
}
return nil
}
func init() { func init() {
proto.RegisterEnum("walletrpc.WitnessType", WitnessType_name, WitnessType_value) proto.RegisterEnum("walletrpc.WitnessType", WitnessType_name, WitnessType_value)
proto.RegisterType((*ListUnspentRequest)(nil), "walletrpc.ListUnspentRequest") proto.RegisterType((*ListUnspentRequest)(nil), "walletrpc.ListUnspentRequest")
@ -1797,125 +1878,130 @@ func init() {
proto.RegisterType((*UtxoLease)(nil), "walletrpc.UtxoLease") proto.RegisterType((*UtxoLease)(nil), "walletrpc.UtxoLease")
proto.RegisterType((*FinalizePsbtRequest)(nil), "walletrpc.FinalizePsbtRequest") proto.RegisterType((*FinalizePsbtRequest)(nil), "walletrpc.FinalizePsbtRequest")
proto.RegisterType((*FinalizePsbtResponse)(nil), "walletrpc.FinalizePsbtResponse") proto.RegisterType((*FinalizePsbtResponse)(nil), "walletrpc.FinalizePsbtResponse")
proto.RegisterType((*ListLeasesRequest)(nil), "walletrpc.ListLeasesRequest")
proto.RegisterType((*ListLeasesResponse)(nil), "walletrpc.ListLeasesResponse")
} }
func init() { proto.RegisterFile("walletrpc/walletkit.proto", fileDescriptor_6cc6942ac78249e5) } func init() { proto.RegisterFile("walletrpc/walletkit.proto", fileDescriptor_6cc6942ac78249e5) }
var fileDescriptor_6cc6942ac78249e5 = []byte{ var fileDescriptor_6cc6942ac78249e5 = []byte{
// 1793 bytes of a gzipped FileDescriptorProto // 1851 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xef, 0x6e, 0x22, 0xc9, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x5f, 0x73, 0xe2, 0xc8,
0x11, 0x5f, 0x0c, 0xc6, 0x50, 0x80, 0x8d, 0x1b, 0xbc, 0x66, 0x59, 0xef, 0xd9, 0x3b, 0x97, 0xe4, 0x11, 0x5f, 0x0c, 0xc6, 0xd0, 0x80, 0x8d, 0x07, 0xbc, 0x66, 0x59, 0xef, 0xd9, 0xab, 0x4b, 0x72,
0x9c, 0xdc, 0x1d, 0x56, 0xbc, 0xba, 0xcb, 0x9e, 0x13, 0x45, 0xb1, 0xf1, 0x58, 0x58, 0x60, 0xf0, 0x4e, 0xee, 0x0e, 0x57, 0xbc, 0x75, 0x97, 0x3d, 0x27, 0x95, 0x8a, 0x8d, 0xe5, 0xc2, 0x05, 0x06,
0x35, 0x78, 0xad, 0x4d, 0x3e, 0x8c, 0x06, 0xa6, 0x6d, 0x8f, 0x0c, 0x33, 0x73, 0x33, 0x8d, 0x19, 0x67, 0xc0, 0xeb, 0xda, 0xe4, 0x41, 0x25, 0xd0, 0xd8, 0x56, 0x19, 0x24, 0x9d, 0x34, 0x18, 0xc8,
0xf2, 0x29, 0x4f, 0x11, 0xe9, 0xa4, 0xbc, 0xc3, 0xbd, 0x40, 0x1e, 0x28, 0x8f, 0x11, 0xf5, 0x1f, 0xd3, 0x7d, 0x8a, 0x54, 0x5d, 0x55, 0xbe, 0xc3, 0x3d, 0xe4, 0x35, 0x1f, 0x2e, 0x35, 0x7f, 0x10,
0x86, 0x1e, 0xc0, 0x7b, 0x8a, 0x72, 0x9f, 0x4c, 0xd7, 0xaf, 0xea, 0xd7, 0xd5, 0x55, 0x35, 0x5d, 0x23, 0x81, 0x6f, 0x93, 0x4a, 0x9e, 0xd0, 0xf4, 0xaf, 0xbb, 0xa7, 0xa7, 0xbb, 0x67, 0xba, 0x1b,
0xd5, 0x86, 0x57, 0x13, 0x73, 0x38, 0x24, 0xd4, 0xf7, 0x06, 0x47, 0xe2, 0xd7, 0xa3, 0x4d, 0x6b, 0x78, 0x35, 0x31, 0x87, 0x43, 0x42, 0x7d, 0x6f, 0x70, 0x24, 0xbe, 0x1e, 0x6d, 0x5a, 0xf3, 0x7c,
0x9e, 0xef, 0x52, 0x17, 0x65, 0x23, 0xa8, 0x9a, 0xf5, 0xbd, 0x81, 0x90, 0x56, 0xcb, 0x81, 0x7d, 0x97, 0xba, 0x28, 0x1b, 0x42, 0xd5, 0xac, 0xef, 0x0d, 0x04, 0xb5, 0x5a, 0x0e, 0xec, 0x7b, 0x87,
0xef, 0x30, 0x75, 0xf6, 0x97, 0xf8, 0x42, 0xaa, 0xb5, 0x01, 0xb5, 0xec, 0x80, 0xde, 0x38, 0x81, 0xb1, 0xb3, 0x5f, 0xe2, 0x0b, 0xaa, 0xd6, 0x06, 0xd4, 0xb2, 0x03, 0x7a, 0xe3, 0x04, 0x1e, 0x71,
0x47, 0x1c, 0x8a, 0xc9, 0x0f, 0x63, 0x12, 0x50, 0xf4, 0x1a, 0xb2, 0x23, 0xdb, 0x31, 0x06, 0xae, 0x28, 0x26, 0xdf, 0x8f, 0x49, 0x40, 0xd1, 0x6b, 0xc8, 0x8e, 0x6c, 0xc7, 0x18, 0xb8, 0xce, 0x5d,
0x73, 0x17, 0x54, 0x12, 0x07, 0x89, 0xc3, 0x75, 0x9c, 0x19, 0xd9, 0x4e, 0x9d, 0xad, 0x39, 0x68, 0x50, 0x49, 0x1c, 0x24, 0x0e, 0xd7, 0x71, 0x66, 0x64, 0x3b, 0x75, 0xb6, 0xe6, 0xa0, 0x39, 0x95,
0x86, 0x12, 0x5c, 0x93, 0xa0, 0x19, 0x72, 0x50, 0x7b, 0x0f, 0xa5, 0x18, 0x5f, 0xe0, 0xb9, 0x4e, 0xe0, 0x9a, 0x04, 0xcd, 0x29, 0x07, 0xb5, 0xf7, 0x50, 0x8a, 0xe8, 0x0b, 0x3c, 0xd7, 0x09, 0x08,
0x40, 0xd0, 0x5b, 0x58, 0x1f, 0xd3, 0xd0, 0x65, 0x64, 0xc9, 0xc3, 0xdc, 0x71, 0xae, 0x36, 0x64, 0x7a, 0x0b, 0xeb, 0x63, 0x3a, 0x75, 0x99, 0xb2, 0xe4, 0x61, 0xee, 0x38, 0x57, 0x1b, 0x32, 0x53,
0xae, 0xd4, 0x6e, 0x68, 0xe8, 0x62, 0x81, 0x68, 0xdf, 0x03, 0x6a, 0x11, 0x33, 0x20, 0x9d, 0x31, 0x6a, 0x37, 0x74, 0xea, 0x62, 0x81, 0x68, 0x3f, 0x24, 0x00, 0xb5, 0x88, 0x19, 0x90, 0xce, 0x98,
0xf5, 0xc6, 0x91, 0x27, 0x9b, 0xb0, 0x66, 0x5b, 0xdc, 0x85, 0x3c, 0x5e, 0xb3, 0x2d, 0xf4, 0x25, 0x7a, 0xe3, 0xd0, 0x94, 0x4d, 0x58, 0xb3, 0x2d, 0x6e, 0x43, 0x1e, 0xaf, 0xd9, 0x16, 0xfa, 0x12,
0x64, 0xdc, 0x31, 0xf5, 0x5c, 0xdb, 0xa1, 0x7c, 0xef, 0xdc, 0xf1, 0x96, 0xe4, 0xea, 0x8c, 0xe9, 0x32, 0xee, 0x98, 0x7a, 0xae, 0xed, 0x50, 0xbe, 0x79, 0xee, 0x78, 0x4b, 0x2a, 0xeb, 0x8c, 0xe9,
0x35, 0x13, 0xe3, 0x48, 0x41, 0xfb, 0x06, 0x4a, 0x31, 0x4a, 0xe9, 0xcc, 0x67, 0x00, 0x24, 0xf4, 0x35, 0x23, 0xe3, 0x90, 0x01, 0x7d, 0x0d, 0x88, 0x4c, 0x3d, 0xdb, 0x37, 0xa9, 0xed, 0x3a, 0x46,
0x6c, 0xdf, 0xa4, 0xb6, 0xeb, 0x70, 0xee, 0x14, 0x56, 0x24, 0x5a, 0x17, 0xca, 0x98, 0x0c, 0x7f, 0x40, 0x06, 0xae, 0x63, 0x05, 0x95, 0xe4, 0x41, 0xe2, 0x30, 0x85, 0xb7, 0x17, 0x48, 0x57, 0x00,
0x61, 0x5f, 0x76, 0x61, 0x67, 0x81, 0x54, 0x78, 0xa3, 0x7d, 0x0f, 0xe9, 0x26, 0x99, 0x62, 0xf2, 0xda, 0x37, 0x50, 0x8a, 0x58, 0x20, 0x8d, 0xff, 0x0c, 0x60, 0xc1, 0xcb, 0x4d, 0x49, 0x61, 0x85,
0x03, 0x3a, 0x84, 0xe2, 0x23, 0x99, 0x1a, 0x77, 0xb6, 0x73, 0x4f, 0x7c, 0xc3, 0xf3, 0x19, 0xaf, 0xa2, 0x75, 0xa1, 0x8c, 0xc9, 0xf0, 0xff, 0x6b, 0xba, 0xb6, 0x0b, 0x3b, 0x31, 0xa5, 0xc2, 0x1a,
0x08, 0xfe, 0xe6, 0x23, 0x99, 0x5e, 0x70, 0xf1, 0x35, 0x93, 0xa2, 0x37, 0x00, 0x5c, 0xd3, 0x1c, 0xed, 0xcf, 0x90, 0x6e, 0x92, 0x19, 0x26, 0xdf, 0xa3, 0x43, 0x28, 0x3e, 0x92, 0x99, 0x71, 0x67,
0xd9, 0xc3, 0xa9, 0xcc, 0x41, 0x96, 0xe9, 0x70, 0x81, 0x56, 0x80, 0xdc, 0xa9, 0x65, 0xf9, 0xd2, 0x3b, 0xf7, 0xc4, 0x37, 0x3c, 0x9f, 0xe9, 0x15, 0xc1, 0xda, 0x7c, 0x24, 0xb3, 0x0b, 0x4e, 0xbe,
0x6f, 0x4d, 0x83, 0xbc, 0x58, 0xca, 0xf3, 0x23, 0x48, 0x99, 0x96, 0xe5, 0x73, 0xee, 0x2c, 0xe6, 0x66, 0x54, 0xf4, 0x06, 0x80, 0x73, 0x9a, 0x23, 0x7b, 0x38, 0x93, 0x31, 0xcb, 0x32, 0x1e, 0x4e,
0xbf, 0xb5, 0x13, 0xc8, 0xf5, 0x7c, 0xd3, 0x09, 0xcc, 0x01, 0x0b, 0x01, 0xda, 0x81, 0x34, 0x0d, 0xd0, 0x0a, 0x90, 0x3b, 0xb5, 0x2c, 0x5f, 0xda, 0xad, 0x69, 0x90, 0x17, 0x4b, 0x79, 0x7e, 0x04,
0x8d, 0x07, 0x12, 0xca, 0xe3, 0xae, 0xd3, 0xb0, 0x41, 0x42, 0x54, 0x86, 0xf5, 0xa1, 0xd9, 0x27, 0x29, 0xd3, 0xb2, 0x7c, 0xae, 0x3b, 0x8b, 0xf9, 0xb7, 0x76, 0x02, 0xb9, 0x9e, 0x6f, 0x3a, 0x81,
0x43, 0xbe, 0x65, 0x16, 0x8b, 0x85, 0xf6, 0x2d, 0x6c, 0x5d, 0x8f, 0xfb, 0x43, 0x3b, 0x78, 0x88, 0x39, 0x60, 0x2e, 0x40, 0x3b, 0x90, 0xa6, 0x53, 0xe3, 0x81, 0x4c, 0xe5, 0x71, 0xd7, 0xe9, 0xb4,
0xb6, 0xf8, 0x1c, 0x0a, 0x9e, 0x10, 0x19, 0xc4, 0xf7, 0xdd, 0xd9, 0x5e, 0x79, 0x29, 0xd4, 0x99, 0x41, 0xa6, 0xa8, 0x0c, 0xeb, 0x43, 0xb3, 0x4f, 0x86, 0x7c, 0xcb, 0x2c, 0x16, 0x0b, 0xed, 0x5b,
0x4c, 0xfb, 0x77, 0x02, 0x50, 0x97, 0x38, 0x96, 0x08, 0x48, 0x30, 0x0b, 0xf3, 0x1e, 0x40, 0x60, 0xd8, 0xba, 0x1e, 0xf7, 0x87, 0x76, 0xf0, 0x10, 0x6e, 0xf1, 0x39, 0x14, 0x3c, 0x41, 0x32, 0x88,
0x52, 0xc3, 0x23, 0xbe, 0xf1, 0x38, 0xe1, 0x86, 0x49, 0x9c, 0x09, 0x4c, 0x7a, 0x4d, 0xfc, 0xe6, 0xef, 0xbb, 0xf3, 0xbd, 0xf2, 0x92, 0xa8, 0x33, 0x9a, 0xf6, 0xaf, 0x04, 0xa0, 0x2e, 0x71, 0x2c,
0x04, 0x1d, 0xc2, 0x86, 0x2b, 0xf4, 0x2b, 0x6b, 0xbc, 0x96, 0x36, 0x6b, 0xb2, 0xb0, 0x6b, 0xbd, 0xe1, 0x90, 0x60, 0xee, 0xe6, 0x3d, 0x80, 0xc0, 0xa4, 0x86, 0x47, 0x7c, 0xe3, 0x71, 0xc2, 0x05,
0xb0, 0x33, 0xa6, 0x78, 0x06, 0xcf, 0x9d, 0x4d, 0x2a, 0xce, 0xc6, 0x4b, 0x3b, 0xb5, 0x50, 0xda, 0x93, 0x38, 0x13, 0x98, 0xf4, 0x9a, 0xf8, 0xcd, 0x09, 0x3a, 0x84, 0x0d, 0x57, 0xf0, 0x57, 0xd6,
0x5f, 0xc2, 0x36, 0xab, 0x5b, 0xcb, 0x18, 0x3b, 0x4c, 0xc1, 0xf6, 0x47, 0xc4, 0xaa, 0xac, 0x1f, 0x78, 0xee, 0x6d, 0xd6, 0xe4, 0x45, 0xa8, 0xf5, 0xa6, 0x9d, 0x31, 0xc5, 0x73, 0x78, 0x61, 0x6c,
0x24, 0x0e, 0x33, 0xb8, 0xc8, 0x81, 0x9b, 0xb9, 0x5c, 0xfb, 0x0a, 0x4a, 0x31, 0xef, 0xe5, 0xd1, 0x52, 0x31, 0x36, 0x7a, 0x15, 0x52, 0xb1, 0xab, 0xf0, 0x25, 0x6c, 0xb3, 0x3c, 0xb7, 0x8c, 0xb1,
0x77, 0x20, 0xed, 0x9b, 0x13, 0x83, 0x46, 0xa1, 0xf3, 0xcd, 0x49, 0x2f, 0xd4, 0xbe, 0x01, 0xa4, 0xc3, 0x18, 0x6c, 0x7f, 0x44, 0xac, 0xca, 0xfa, 0x41, 0xe2, 0x30, 0x83, 0x8b, 0x1c, 0xb8, 0x59,
0x07, 0xd4, 0x1e, 0x99, 0x94, 0x5c, 0x10, 0x32, 0x3b, 0xeb, 0x3e, 0xe4, 0x18, 0xa1, 0x41, 0x4d, 0xd0, 0xb5, 0xaf, 0xa0, 0x14, 0xb1, 0x5e, 0x1e, 0x7d, 0x07, 0xd2, 0xbe, 0x39, 0x31, 0x68, 0xe8,
0xff, 0x9e, 0xcc, 0xb2, 0x0d, 0x4c, 0xd4, 0xe3, 0x12, 0xed, 0x1d, 0x94, 0x62, 0x66, 0x72, 0x93, 0x3a, 0xdf, 0x9c, 0xf4, 0xa6, 0xda, 0x37, 0x80, 0xf4, 0x80, 0xda, 0x23, 0x93, 0x92, 0x0b, 0x42,
0x4f, 0xc6, 0x48, 0xfb, 0x31, 0x09, 0xf9, 0x6b, 0xe2, 0x58, 0xb6, 0x73, 0xdf, 0x9d, 0x10, 0xe2, 0xe6, 0x67, 0xdd, 0x87, 0x1c, 0x53, 0x68, 0x50, 0xd3, 0xbf, 0x27, 0xf3, 0x68, 0x03, 0x23, 0xf5,
0xc5, 0x2a, 0x35, 0xf1, 0x33, 0x95, 0x8a, 0xbe, 0x83, 0xfc, 0xc4, 0xa6, 0x0e, 0x09, 0x02, 0x83, 0x38, 0x45, 0x7b, 0x07, 0xa5, 0x88, 0x98, 0xdc, 0xe4, 0x67, 0x7d, 0xa4, 0xfd, 0x98, 0x84, 0xfc,
0x4e, 0x3d, 0xc2, 0x73, 0xbd, 0x79, 0xfc, 0xb2, 0x16, 0xdd, 0x2a, 0xb5, 0x5b, 0x01, 0xf7, 0xa6, 0x35, 0x71, 0x2c, 0xdb, 0xb9, 0xef, 0x4e, 0x08, 0xf1, 0x22, 0x99, 0x9a, 0xf8, 0xd4, 0x25, 0xfb,
0x1e, 0xc1, 0xb9, 0xc9, 0x7c, 0xc1, 0xea, 0xd2, 0x1c, 0xb9, 0x63, 0x87, 0x1a, 0x81, 0x49, 0x79, 0x0e, 0xf2, 0x13, 0x9b, 0x3a, 0x24, 0x08, 0x0c, 0x3a, 0xf3, 0x08, 0x8f, 0xf5, 0xe6, 0xf1, 0xcb,
0xdc, 0x0b, 0x38, 0x2b, 0x24, 0x5d, 0x93, 0xa2, 0x03, 0xc8, 0xcf, 0xbc, 0xee, 0x4f, 0x29, 0xe1, 0x5a, 0xf8, 0x0a, 0xd5, 0x6e, 0x05, 0xdc, 0x9b, 0x79, 0x04, 0xe7, 0x26, 0x8b, 0x05, 0xcb, 0x4b,
0xe1, 0x2f, 0x60, 0x10, 0x7e, 0x9f, 0x4d, 0x29, 0x41, 0x5f, 0x03, 0xea, 0xfb, 0xae, 0x69, 0x0d, 0x73, 0xe4, 0x8e, 0x1d, 0x6a, 0x04, 0x26, 0xe5, 0x7e, 0x2f, 0xe0, 0xac, 0xa0, 0x74, 0x4d, 0x8a,
0xcc, 0x80, 0x1a, 0x26, 0xa5, 0x64, 0xe4, 0xd1, 0x80, 0x67, 0xa0, 0x80, 0xb7, 0x23, 0xe4, 0x54, 0x0e, 0x20, 0x3f, 0xb7, 0xba, 0x3f, 0xa3, 0x84, 0xbb, 0xbf, 0x80, 0x41, 0xd8, 0x7d, 0x36, 0xa3,
0x02, 0xe8, 0x18, 0x76, 0x1c, 0x12, 0x52, 0x63, 0x6e, 0xf3, 0x40, 0xec, 0xfb, 0x07, 0x5a, 0x49, 0x84, 0x5d, 0xf0, 0xbe, 0xef, 0x9a, 0xd6, 0xc0, 0x0c, 0xa8, 0x61, 0x52, 0x4a, 0x46, 0x1e, 0x0d,
0x73, 0x8b, 0x12, 0x03, 0xcf, 0x66, 0x58, 0x83, 0x43, 0xcc, 0xc6, 0x17, 0xd1, 0x27, 0x96, 0xa1, 0x78, 0x04, 0x0a, 0x78, 0x3b, 0x44, 0x4e, 0x25, 0x80, 0x8e, 0x61, 0xc7, 0x21, 0x53, 0x6a, 0x2c,
0x06, 0x3f, 0x23, 0x6c, 0x22, 0xb0, 0x1e, 0x65, 0x01, 0xbd, 0x83, 0x97, 0x73, 0x9b, 0xd8, 0x11, 0x64, 0x1e, 0x88, 0x7d, 0xff, 0x40, 0x2b, 0x69, 0x2e, 0x51, 0x62, 0xe0, 0xd9, 0x1c, 0x6b, 0x70,
0xb2, 0x0b, 0x46, 0xdd, 0xf9, 0x59, 0xca, 0xb0, 0x7e, 0xe7, 0xfa, 0x03, 0x52, 0xd9, 0xe0, 0x05, 0x88, 0xc9, 0xf8, 0xc2, 0xfb, 0xc4, 0x32, 0x54, 0xe7, 0x67, 0x84, 0x4c, 0x08, 0xd6, 0xc3, 0x28,
0x24, 0x16, 0xda, 0x4b, 0x28, 0xab, 0xa9, 0x99, 0x55, 0xbd, 0x76, 0x0b, 0x3b, 0x0b, 0x72, 0x99, 0xa0, 0x77, 0xf0, 0x72, 0x21, 0x13, 0x39, 0x42, 0x36, 0x26, 0xd4, 0x5d, 0x9c, 0xa5, 0x0c, 0xeb,
0xea, 0x3f, 0xc3, 0xa6, 0x27, 0x00, 0x23, 0xe0, 0x88, 0xbc, 0x43, 0x77, 0x95, 0x84, 0xa8, 0x96, 0x77, 0xae, 0x3f, 0x20, 0x95, 0x0d, 0x9e, 0x40, 0x62, 0xa1, 0xbd, 0x84, 0xb2, 0x1a, 0x9a, 0x79,
0xb8, 0xe0, 0xa9, 0x3c, 0xda, 0x3f, 0x13, 0xb0, 0x79, 0x36, 0x1e, 0x79, 0x4a, 0xd5, 0xfd, 0x4f, 0xd6, 0x6b, 0xb7, 0xb0, 0x13, 0xa3, 0xcb, 0x50, 0xff, 0x11, 0x36, 0x3d, 0x01, 0x18, 0x01, 0x47,
0xe5, 0xb0, 0x0f, 0x39, 0x11, 0x20, 0x1e, 0x2c, 0x5e, 0x0d, 0x05, 0x0c, 0x42, 0xc4, 0x42, 0xb4, 0xe4, 0x9b, 0xbb, 0xab, 0x04, 0x44, 0x95, 0xc4, 0x05, 0x4f, 0xd5, 0xa3, 0xfd, 0x3d, 0x01, 0x9b,
0x94, 0xd5, 0xe4, 0x52, 0x56, 0xa3, 0x48, 0xa4, 0xd4, 0x48, 0x6c, 0xc3, 0x56, 0xe4, 0x97, 0xbc, 0x67, 0xe3, 0x91, 0xa7, 0x64, 0xdd, 0x7f, 0x95, 0x0e, 0xfb, 0x90, 0x13, 0x0e, 0xe2, 0xce, 0xe2,
0x0b, 0xbf, 0x86, 0x6d, 0xd6, 0x3d, 0x62, 0x91, 0x41, 0x15, 0xd8, 0x78, 0x22, 0x7e, 0xdf, 0x0d, 0xd9, 0x50, 0xc0, 0x20, 0x48, 0xcc, 0x45, 0x4b, 0x51, 0x4d, 0x2e, 0x45, 0x35, 0xf4, 0x44, 0x4a,
0x08, 0x77, 0x36, 0x83, 0x67, 0x4b, 0xed, 0x1f, 0x6b, 0xa2, 0x7b, 0x2d, 0x44, 0xac, 0x05, 0x25, 0xf5, 0xc4, 0x36, 0x6c, 0x85, 0x76, 0xc9, 0xb7, 0xf0, 0x6b, 0xd8, 0x66, 0xd5, 0x26, 0xe2, 0x19,
0x3a, 0xbf, 0xcb, 0x0c, 0x8b, 0x50, 0xd3, 0x1e, 0x06, 0xf2, 0xa4, 0xaf, 0xe4, 0x49, 0x95, 0xdb, 0x54, 0x81, 0x8d, 0x27, 0xe2, 0xf7, 0xdd, 0x80, 0x70, 0x63, 0x33, 0x78, 0xbe, 0xd4, 0x7e, 0x58,
0xee, 0x5c, 0x28, 0x34, 0x5e, 0x60, 0x44, 0x97, 0xa4, 0xe8, 0x16, 0xb6, 0x54, 0x36, 0xdb, 0x0a, 0x13, 0xd5, 0x2e, 0xe6, 0xb1, 0x16, 0x94, 0xe8, 0xe2, 0x2d, 0x33, 0x2c, 0x42, 0x4d, 0x7b, 0x18,
0xe4, 0x65, 0xff, 0x95, 0x92, 0x80, 0x65, 0x2f, 0xd4, 0x0d, 0x2e, 0xcf, 0x19, 0xf9, 0xa6, 0x42, 0xc8, 0x93, 0xbe, 0x92, 0x27, 0x55, 0x5e, 0xbb, 0x73, 0xc1, 0xd0, 0x78, 0x81, 0x11, 0x5d, 0xa2,
0x73, 0x69, 0x05, 0xd5, 0xef, 0x60, 0x33, 0xae, 0x83, 0xbe, 0x58, 0xde, 0x8a, 0xe5, 0x3a, 0xbb, 0xa2, 0x5b, 0xd8, 0x52, 0xb5, 0xd9, 0x56, 0x20, 0x1f, 0xfb, 0xaf, 0x94, 0x00, 0x2c, 0x5b, 0xa1,
0x68, 0x7a, 0x96, 0x81, 0xb4, 0xa8, 0x05, 0xcd, 0x84, 0xdd, 0x16, 0xbb, 0xd7, 0x14, 0xa6, 0x59, 0x6e, 0x70, 0x79, 0xce, 0x94, 0x6f, 0x2a, 0x6a, 0x2e, 0xad, 0xa0, 0xfa, 0x1d, 0x6c, 0x46, 0x79,
0xdc, 0x10, 0xa4, 0x68, 0x18, 0x35, 0x2c, 0xfe, 0x7b, 0xf5, 0x05, 0x8e, 0xf6, 0x20, 0xeb, 0x3e, 0xd0, 0x17, 0xcb, 0x5b, 0xb1, 0x58, 0x67, 0xe3, 0xa2, 0x67, 0x19, 0x48, 0x8b, 0x5c, 0xd0, 0x4c,
0x11, 0x7f, 0xe2, 0xdb, 0x32, 0x7d, 0x19, 0x3c, 0x17, 0x68, 0x55, 0xa8, 0x2c, 0x6f, 0x21, 0x13, 0xd8, 0x6d, 0xb1, 0x77, 0x4d, 0xd1, 0x34, 0xf7, 0x1b, 0x82, 0x14, 0x9d, 0x86, 0x05, 0x8b, 0x7f,
0xf6, 0x53, 0x02, 0xb6, 0x2e, 0xc6, 0x8e, 0x75, 0x1d, 0xf4, 0xa3, 0x36, 0x59, 0x86, 0x94, 0x17, 0xaf, 0x7e, 0xc0, 0xd1, 0x1e, 0x64, 0xdd, 0x27, 0xe2, 0x4f, 0x7c, 0x5b, 0x86, 0x2f, 0x83, 0x17,
0xf4, 0x45, 0x65, 0xe5, 0x1b, 0x2f, 0x30, 0x5f, 0xa1, 0xdf, 0x42, 0xd2, 0x37, 0x27, 0x32, 0x74, 0x04, 0xad, 0x0a, 0x95, 0xe5, 0x2d, 0x64, 0xc0, 0x7e, 0x4a, 0xc0, 0xd6, 0xc5, 0xd8, 0xb1, 0xae,
0x3b, 0x4a, 0xe8, 0x7a, 0x61, 0x8f, 0x8c, 0xbc, 0xa1, 0x49, 0x49, 0xe3, 0x05, 0x66, 0x3a, 0xe8, 0x83, 0x7e, 0x58, 0x26, 0xcb, 0x90, 0xf2, 0x82, 0xbe, 0xc8, 0xac, 0x7c, 0xe3, 0x05, 0xe6, 0x2b,
0x6d, 0xbc, 0xe2, 0x78, 0x3d, 0x35, 0x12, 0xb1, 0x9a, 0xfb, 0x15, 0x14, 0x66, 0x35, 0xf7, 0x34, 0xf4, 0x6b, 0x48, 0xfa, 0xe6, 0x44, 0xba, 0x6e, 0x47, 0x71, 0x5d, 0x6f, 0xda, 0x23, 0x23, 0x6f,
0xbf, 0x4a, 0x1a, 0x09, 0x9c, 0x13, 0x65, 0xf7, 0x81, 0x09, 0xcf, 0x00, 0x32, 0x54, 0x72, 0x9f, 0x68, 0x52, 0xd2, 0x78, 0x81, 0x19, 0x0f, 0x7a, 0x1b, 0xcd, 0x38, 0x9e, 0x4f, 0x8d, 0x44, 0x24,
0xa5, 0x21, 0x75, 0x47, 0x48, 0xa0, 0xfd, 0x2b, 0x01, 0xc5, 0xb9, 0xc7, 0xb2, 0x62, 0xf6, 0x21, 0xe7, 0x7e, 0x01, 0x85, 0x79, 0xce, 0x3d, 0x2d, 0x9e, 0x92, 0x46, 0x02, 0xe7, 0x44, 0xda, 0x7d,
0x77, 0x37, 0x76, 0x2c, 0x62, 0x19, 0x73, 0xcf, 0x31, 0x08, 0x11, 0x53, 0x44, 0x35, 0x28, 0x0d, 0x60, 0xc4, 0x33, 0x80, 0x0c, 0x95, 0xba, 0xcf, 0xd2, 0x90, 0xba, 0x23, 0x24, 0xd0, 0xfe, 0x91,
0x1e, 0x4c, 0xe7, 0x9e, 0x18, 0xa2, 0xbb, 0x18, 0xb6, 0x63, 0x91, 0x50, 0x76, 0xde, 0x6d, 0x01, 0x80, 0xe2, 0xc2, 0x62, 0x99, 0x31, 0xfb, 0x90, 0xbb, 0x1b, 0x3b, 0x16, 0xb1, 0x8c, 0x85, 0xe5,
0x89, 0x46, 0x70, 0xc9, 0x00, 0xf4, 0x07, 0xc8, 0x0f, 0xdd, 0xc1, 0x23, 0xb1, 0x0c, 0x31, 0xf6, 0x18, 0x04, 0x89, 0x31, 0xa2, 0x1a, 0x94, 0x06, 0x0f, 0xa6, 0x73, 0x4f, 0x0c, 0x51, 0x5d, 0x0c,
0x24, 0xf9, 0x27, 0x5b, 0x56, 0x8e, 0xcd, 0x46, 0x1f, 0x3e, 0x9c, 0xe0, 0x9c, 0xd0, 0xbc, 0xe1, 0xdb, 0xb1, 0xc8, 0x54, 0x56, 0xde, 0x6d, 0x01, 0x89, 0x42, 0x70, 0xc9, 0x00, 0xf4, 0x3b, 0xc8,
0x53, 0xd0, 0x4f, 0x09, 0x80, 0x79, 0x44, 0xd0, 0x17, 0x90, 0xb6, 0x1d, 0xde, 0xec, 0xc4, 0x47, 0x0f, 0xdd, 0xc1, 0x23, 0xb1, 0x0c, 0xd1, 0x26, 0x25, 0xf9, 0x95, 0x2d, 0x2b, 0xc7, 0x66, 0xad,
0xbf, 0xf4, 0x9d, 0x4a, 0x18, 0xfd, 0x69, 0xb1, 0x2d, 0x6a, 0x2b, 0x43, 0x5c, 0x93, 0xdd, 0x4a, 0x12, 0x6f, 0x4e, 0x70, 0x4e, 0x70, 0xde, 0xf0, 0xae, 0xe9, 0xa7, 0x04, 0xc0, 0xc2, 0x23, 0xe8,
0x77, 0xa8, 0x3f, 0x8d, 0x5a, 0x65, 0xf5, 0x04, 0xf2, 0x2a, 0x80, 0x8a, 0x90, 0x7c, 0x24, 0x53, 0x0b, 0x48, 0xdb, 0x0e, 0x2f, 0x76, 0xe2, 0xd2, 0x2f, 0xdd, 0x53, 0x09, 0xa3, 0x3f, 0xc4, 0xcb,
0xd9, 0xb4, 0xd9, 0x4f, 0x56, 0x38, 0x4f, 0xe6, 0x70, 0x2c, 0xba, 0x41, 0x0a, 0x8b, 0xc5, 0xc9, 0xa2, 0xb6, 0xd2, 0xc5, 0x35, 0x59, 0xad, 0x74, 0x87, 0xfa, 0xb3, 0xb0, 0x54, 0x56, 0x4f, 0x20,
0xda, 0xfb, 0x84, 0xf6, 0x00, 0xd9, 0xe8, 0x2c, 0xff, 0xd7, 0x88, 0xb4, 0x30, 0x97, 0x25, 0x97, 0xaf, 0x02, 0xa8, 0x08, 0xc9, 0x47, 0x32, 0x93, 0x45, 0x9b, 0x7d, 0xb2, 0xc4, 0x79, 0x32, 0x87,
0xe6, 0xb2, 0x6f, 0xa1, 0x74, 0x61, 0x3b, 0xe6, 0xd0, 0xfe, 0x3b, 0x51, 0xeb, 0xed, 0xe7, 0x92, 0x63, 0x51, 0x0d, 0x52, 0x58, 0x2c, 0x4e, 0xd6, 0xde, 0x27, 0xb4, 0x07, 0xc8, 0x86, 0x67, 0xf9,
0xa7, 0x7d, 0x84, 0x72, 0xdc, 0x6e, 0x9e, 0x75, 0x3e, 0x0b, 0xc7, 0x0d, 0x85, 0x88, 0x67, 0xfd, 0xdf, 0xba, 0xbb, 0x68, 0x5f, 0x96, 0x5c, 0xea, 0xcb, 0xbe, 0x85, 0xd2, 0x85, 0xed, 0x98, 0x43,
0x00, 0xf2, 0xac, 0x95, 0xdf, 0x31, 0x63, 0xd6, 0xd0, 0xd7, 0x84, 0x86, 0x6f, 0x4e, 0x38, 0x5f, 0xfb, 0x6f, 0x44, 0xcd, 0xb7, 0x4f, 0x05, 0x4f, 0xfb, 0x08, 0xe5, 0xa8, 0xdc, 0x22, 0xea, 0xbc,
0x2f, 0xfc, 0xdd, 0x8f, 0x49, 0xc8, 0x29, 0xdd, 0x10, 0x95, 0x60, 0xeb, 0xa6, 0xdd, 0x6c, 0x77, 0x77, 0x8e, 0x0a, 0x0a, 0x12, 0x8f, 0xfa, 0x01, 0xe4, 0x59, 0x29, 0xbf, 0x63, 0xc2, 0xac, 0xa0,
0x6e, 0xdb, 0xc6, 0xed, 0x65, 0xaf, 0xad, 0x77, 0xbb, 0xc5, 0x17, 0xa8, 0x02, 0xe5, 0x7a, 0xe7, 0xaf, 0x09, 0x0e, 0xdf, 0x9c, 0x70, 0x7d, 0xbd, 0xa9, 0x56, 0x12, 0x0f, 0x16, 0x3f, 0x7c, 0xf8,
0xea, 0xea, 0xb2, 0x77, 0xa5, 0xb7, 0x7b, 0x46, 0xef, 0xf2, 0x4a, 0x37, 0x5a, 0x9d, 0x7a, 0xb3, 0x94, 0x5f, 0x89, 0x57, 0x69, 0x4e, 0x94, 0xbb, 0xc5, 0x53, 0x22, 0xf1, 0x1f, 0xa6, 0xc4, 0x6f,
0x98, 0x40, 0xbb, 0x50, 0x52, 0x90, 0x76, 0xc7, 0x38, 0xd7, 0x5b, 0xa7, 0x1f, 0x8b, 0x6b, 0x68, 0x7e, 0x4c, 0x42, 0x4e, 0xa9, 0xb8, 0xa8, 0x04, 0x5b, 0x37, 0xed, 0x66, 0xbb, 0x73, 0xdb, 0x36,
0x07, 0xb6, 0x15, 0x00, 0xeb, 0x1f, 0x3a, 0x4d, 0xbd, 0x98, 0x64, 0xfa, 0x8d, 0x5e, 0xab, 0x6e, 0x6e, 0x2f, 0x7b, 0x6d, 0xbd, 0xdb, 0x2d, 0xbe, 0x40, 0x15, 0x28, 0xd7, 0x3b, 0x57, 0x57, 0x97,
0x74, 0x2e, 0x2e, 0x74, 0xac, 0x9f, 0xcf, 0x80, 0x14, 0xdb, 0x82, 0x03, 0xa7, 0xf5, 0xba, 0x7e, 0xbd, 0x2b, 0xbd, 0xdd, 0x33, 0x7a, 0x97, 0x57, 0xba, 0xd1, 0xea, 0xd4, 0x9b, 0xc5, 0x04, 0xda,
0xdd, 0x9b, 0x23, 0xeb, 0xe8, 0xd7, 0xf0, 0x36, 0x66, 0xc2, 0xb6, 0xef, 0xdc, 0xf4, 0x8c, 0xae, 0x85, 0x92, 0x82, 0xb4, 0x3b, 0xc6, 0xb9, 0xde, 0x3a, 0xfd, 0x58, 0x5c, 0x43, 0x3b, 0xb0, 0xad,
0x5e, 0xef, 0xb4, 0xcf, 0x8d, 0x96, 0xfe, 0x41, 0x6f, 0x15, 0xd3, 0xe8, 0x37, 0xa0, 0xc5, 0x09, 0x00, 0x58, 0xff, 0xd0, 0x69, 0xea, 0xc5, 0x24, 0xe3, 0x6f, 0xf4, 0x5a, 0x75, 0xa3, 0x73, 0x71,
0xba, 0x37, 0xf5, 0xba, 0xde, 0xed, 0xc6, 0xf5, 0x36, 0xd0, 0x3e, 0xbc, 0x5e, 0xf0, 0xe0, 0xaa, 0xa1, 0x63, 0xfd, 0x7c, 0x0e, 0xa4, 0xd8, 0x16, 0x1c, 0x38, 0xad, 0xd7, 0xf5, 0xeb, 0xde, 0x02,
0xd3, 0xd3, 0x67, 0xac, 0xc5, 0x0c, 0x3a, 0x80, 0xbd, 0x45, 0x4f, 0xb8, 0x86, 0xe4, 0x2b, 0x66, 0x59, 0x47, 0xbf, 0x84, 0xb7, 0x11, 0x11, 0xb6, 0x7d, 0xe7, 0xa6, 0x67, 0x74, 0xf5, 0x7a, 0xa7,
0xd1, 0x1e, 0x54, 0xb8, 0x86, 0xca, 0x3c, 0xf3, 0x17, 0x50, 0x19, 0x8a, 0x32, 0x72, 0x46, 0x53, 0x7d, 0x6e, 0xb4, 0xf4, 0x0f, 0x7a, 0xab, 0x98, 0x46, 0xbf, 0x02, 0x2d, 0xaa, 0xa0, 0x7b, 0x53,
0xff, 0x68, 0x34, 0x4e, 0xbb, 0x8d, 0x62, 0x0e, 0xbd, 0x86, 0xdd, 0xb6, 0xde, 0x65, 0x74, 0x4b, 0xaf, 0xeb, 0xdd, 0x6e, 0x94, 0x6f, 0x03, 0xed, 0xc3, 0xeb, 0x98, 0x05, 0x57, 0x9d, 0x9e, 0x3e,
0x60, 0x7e, 0x21, 0x58, 0xa7, 0xed, 0x7a, 0xa3, 0x83, 0x8b, 0x85, 0xe3, 0xff, 0x64, 0x20, 0x7b, 0xd7, 0x5a, 0xcc, 0xa0, 0x03, 0xd8, 0x8b, 0x5b, 0xc2, 0x39, 0xa4, 0xbe, 0x62, 0x16, 0xed, 0x41,
0xcb, 0xbf, 0x81, 0xa6, 0x4d, 0x51, 0x0b, 0x72, 0xca, 0xc3, 0x04, 0xbd, 0x59, 0xb8, 0xbc, 0xe3, 0x85, 0x73, 0xa8, 0x9a, 0xe7, 0xf6, 0x02, 0x2a, 0x43, 0x51, 0x7a, 0xce, 0x68, 0xea, 0x1f, 0x8d,
0x0f, 0xa0, 0xea, 0x67, 0xcf, 0xc1, 0x51, 0x8b, 0xc9, 0x29, 0x2f, 0x8b, 0x38, 0xdb, 0xd2, 0xc3, 0xc6, 0x69, 0xb7, 0x51, 0xcc, 0xa1, 0xd7, 0xb0, 0xdb, 0xd6, 0xbb, 0x4c, 0xdd, 0x12, 0x98, 0x8f,
0x21, 0xce, 0xb6, 0xe2, 0x41, 0x82, 0xa1, 0x10, 0x7b, 0x1b, 0xa0, 0x7d, 0xc5, 0x60, 0xd5, 0x53, 0x39, 0xeb, 0xb4, 0x5d, 0x6f, 0x74, 0x70, 0xb1, 0x70, 0xfc, 0xcf, 0x2c, 0x64, 0x6f, 0x79, 0x00,
0xa4, 0x7a, 0xf0, 0xbc, 0x82, 0xe4, 0x3c, 0x81, 0xc2, 0x39, 0xf1, 0xed, 0x27, 0xd2, 0x26, 0x21, 0x9b, 0x36, 0x45, 0x2d, 0xc8, 0x29, 0xc3, 0x12, 0x7a, 0x13, 0x2b, 0x10, 0xd1, 0xa1, 0xac, 0xfa,
0x6d, 0x92, 0x29, 0xda, 0x56, 0x4c, 0xc4, 0x83, 0xa3, 0xfa, 0x32, 0x1a, 0x9d, 0x9b, 0x64, 0x7a, 0xd9, 0x73, 0x70, 0x58, 0xc6, 0x72, 0xca, 0xf4, 0x12, 0xd5, 0xb6, 0x34, 0x9c, 0x44, 0xb5, 0xad,
0x4e, 0x82, 0x81, 0x6f, 0x7b, 0xd4, 0xf5, 0xd1, 0x7b, 0xc8, 0x0a, 0x5b, 0x66, 0x57, 0x52, 0x95, 0x18, 0x7a, 0x30, 0x14, 0x22, 0xf3, 0x07, 0xda, 0x57, 0x04, 0x56, 0x8d, 0x3b, 0xd5, 0x83, 0xe7,
0x5a, 0xee, 0xc0, 0xa4, 0xae, 0xff, 0xac, 0xe5, 0x1f, 0x21, 0xc3, 0xf6, 0x63, 0xcf, 0x0d, 0xa4, 0x19, 0xa4, 0xce, 0x4b, 0x80, 0x45, 0xa2, 0xa3, 0xbd, 0xd8, 0x79, 0x22, 0x97, 0xa2, 0xfa, 0xe6,
0x4e, 0x8c, 0xca, 0x73, 0xa4, 0xba, 0xbb, 0x24, 0x97, 0x2e, 0x37, 0x00, 0xc9, 0x77, 0x84, 0xfa, 0x19, 0x54, 0xaa, 0x3a, 0x81, 0xc2, 0x39, 0xf1, 0xed, 0x27, 0xd2, 0x26, 0x53, 0xda, 0x24, 0x33,
0x14, 0x51, 0x69, 0x14, 0x79, 0xb5, 0xaa, 0xce, 0x3f, 0x0b, 0xcf, 0x8f, 0x16, 0xe4, 0x94, 0xd1, 0xb4, 0xad, 0xf0, 0x8b, 0xf9, 0xa8, 0xfa, 0x32, 0xec, 0xf4, 0x9b, 0x64, 0x76, 0x4e, 0x82, 0x81,
0x3c, 0x96, 0x9e, 0xe5, 0x07, 0x47, 0x2c, 0x3d, 0xab, 0x26, 0xfa, 0x16, 0xe4, 0x94, 0x19, 0x3c, 0x6f, 0x7b, 0xd4, 0xf5, 0xd1, 0x7b, 0xc8, 0x0a, 0x59, 0x26, 0x57, 0x52, 0x99, 0x5a, 0xee, 0xc0,
0xc6, 0xb6, 0x3c, 0xd2, 0xc7, 0xd8, 0x56, 0x8d, 0xee, 0x18, 0x0a, 0xb1, 0x41, 0x2f, 0x96, 0xec, 0xa4, 0xae, 0xff, 0xac, 0xe4, 0xef, 0x21, 0xc3, 0xf6, 0x63, 0xd3, 0x11, 0x52, 0x1b, 0x5c, 0x65,
0x55, 0xa3, 0x61, 0x2c, 0xd9, 0xab, 0x67, 0xc4, 0xbf, 0xc0, 0x86, 0x1c, 0xa5, 0xd0, 0x2b, 0x45, 0x7a, 0xaa, 0xee, 0x2e, 0xd1, 0xa5, 0xc9, 0x0d, 0x40, 0x72, 0xec, 0x51, 0x27, 0x27, 0x55, 0x8d,
0x39, 0x3e, 0xf6, 0xc5, 0x22, 0xb6, 0x30, 0x79, 0xa1, 0x4b, 0x80, 0xf9, 0x0c, 0x83, 0xf6, 0x9e, 0x42, 0xaf, 0x56, 0xd5, 0x76, 0x2d, 0x36, 0x2d, 0xb5, 0x20, 0xa7, 0x4c, 0x12, 0x91, 0x48, 0x2f,
0x19, 0x6d, 0x04, 0xcf, 0x9b, 0x4f, 0x0e, 0x3e, 0xe8, 0x6f, 0x50, 0x5c, 0x9c, 0x17, 0x90, 0xda, 0xcf, 0x47, 0x91, 0x48, 0xaf, 0x1a, 0x40, 0x5a, 0x90, 0x53, 0x46, 0x86, 0x88, 0xb6, 0xe5, 0x09,
0x8d, 0x9e, 0x99, 0x57, 0xaa, 0x9f, 0x7f, 0x52, 0x47, 0x92, 0xd7, 0x21, 0x33, 0xeb, 0xde, 0x48, 0x24, 0xa2, 0x6d, 0xd5, 0xa4, 0x81, 0xa1, 0x10, 0xe9, 0x4b, 0x23, 0x79, 0xb3, 0xaa, 0x93, 0x8d,
0x3d, 0xcf, 0xc2, 0x10, 0x52, 0x7d, 0xbd, 0x12, 0x93, 0x24, 0x1d, 0xc8, 0xab, 0x0d, 0x01, 0xa9, 0xe4, 0xcd, 0xea, 0x96, 0xf6, 0x4f, 0xb0, 0x21, 0x3b, 0x3f, 0xf4, 0x4a, 0x61, 0x8e, 0x76, 0xa9,
0x29, 0x5b, 0xd1, 0x61, 0xaa, 0xfb, 0xcf, 0xe2, 0x82, 0xf0, 0xec, 0xf7, 0x7f, 0x3d, 0xba, 0xb7, 0x11, 0x8f, 0xc5, 0x1a, 0xc5, 0x79, 0xe6, 0x49, 0x93, 0xf6, 0x9e, 0xe9, 0xc4, 0x56, 0x67, 0x5e,
0xe9, 0xc3, 0xb8, 0x5f, 0x1b, 0xb8, 0xa3, 0xa3, 0x21, 0x7b, 0x67, 0x38, 0xb6, 0x73, 0xef, 0x10, 0xcc, 0x98, 0xbf, 0x42, 0x31, 0xde, 0xde, 0x20, 0xb5, 0x78, 0x3e, 0xd3, 0x5e, 0x55, 0x3f, 0xff,
0x3a, 0x71, 0xfd, 0xc7, 0xa3, 0xa1, 0x63, 0x1d, 0xf1, 0xae, 0x77, 0x14, 0xf1, 0xf4, 0xd3, 0xfc, 0x59, 0x1e, 0xa9, 0xbc, 0x0e, 0x99, 0x79, 0xb3, 0x81, 0xd4, 0xf3, 0xc4, 0x7a, 0xa6, 0xea, 0xeb,
0xff, 0x2f, 0xef, 0xfe, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x88, 0xe3, 0xa5, 0xe6, 0xc8, 0x11, 0x00, 0x95, 0x98, 0x54, 0xd2, 0x81, 0xbc, 0x5a, 0xbf, 0x90, 0x1a, 0xb2, 0x15, 0x05, 0xb1, 0xba, 0xff,
0x00, 0x2c, 0x2e, 0x14, 0x9e, 0xfd, 0xf6, 0x2f, 0x47, 0xf7, 0x36, 0x7d, 0x18, 0xf7, 0x6b, 0x03, 0x77,
0x74, 0x34, 0x64, 0x63, 0x91, 0x63, 0x3b, 0xf7, 0x0e, 0xa1, 0x13, 0xd7, 0x7f, 0x3c, 0x1a, 0x3a,
0xd6, 0x11, 0x2f, 0xd2, 0x47, 0xa1, 0x9e, 0x7e, 0x9a, 0xff, 0xbd, 0xf4, 0xee, 0xdf, 0x01, 0x00,
0x00, 0xff, 0xff, 0xad, 0x1e, 0xe8, 0xf0, 0xa7, 0x12, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -1947,6 +2033,9 @@ type WalletKitClient interface {
//originally lock the output. //originally lock the output.
ReleaseOutput(ctx context.Context, in *ReleaseOutputRequest, opts ...grpc.CallOption) (*ReleaseOutputResponse, error) ReleaseOutput(ctx context.Context, in *ReleaseOutputRequest, opts ...grpc.CallOption) (*ReleaseOutputResponse, error)
// //
//ListLeases lists all currently locked utxos.
ListLeases(ctx context.Context, in *ListLeasesRequest, opts ...grpc.CallOption) (*ListLeasesResponse, error)
//
//DeriveNextKey attempts to derive the *next* key within the key family //DeriveNextKey attempts to derive the *next* key within the key family
//(account in BIP43) specified. This method should return the next external //(account in BIP43) specified. This method should return the next external
//child within this branch. //child within this branch.
@ -2092,6 +2181,15 @@ func (c *walletKitClient) ReleaseOutput(ctx context.Context, in *ReleaseOutputRe
return out, nil return out, nil
} }
func (c *walletKitClient) ListLeases(ctx context.Context, in *ListLeasesRequest, opts ...grpc.CallOption) (*ListLeasesResponse, error) {
out := new(ListLeasesResponse)
err := c.cc.Invoke(ctx, "/walletrpc.WalletKit/ListLeases", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *walletKitClient) DeriveNextKey(ctx context.Context, in *KeyReq, opts ...grpc.CallOption) (*signrpc.KeyDescriptor, error) { func (c *walletKitClient) DeriveNextKey(ctx context.Context, in *KeyReq, opts ...grpc.CallOption) (*signrpc.KeyDescriptor, error) {
out := new(signrpc.KeyDescriptor) out := new(signrpc.KeyDescriptor)
err := c.cc.Invoke(ctx, "/walletrpc.WalletKit/DeriveNextKey", in, out, opts...) err := c.cc.Invoke(ctx, "/walletrpc.WalletKit/DeriveNextKey", in, out, opts...)
@ -2219,6 +2317,9 @@ type WalletKitServer interface {
//originally lock the output. //originally lock the output.
ReleaseOutput(context.Context, *ReleaseOutputRequest) (*ReleaseOutputResponse, error) ReleaseOutput(context.Context, *ReleaseOutputRequest) (*ReleaseOutputResponse, error)
// //
//ListLeases lists all currently locked utxos.
ListLeases(context.Context, *ListLeasesRequest) (*ListLeasesResponse, error)
//
//DeriveNextKey attempts to derive the *next* key within the key family //DeriveNextKey attempts to derive the *next* key within the key family
//(account in BIP43) specified. This method should return the next external //(account in BIP43) specified. This method should return the next external
//child within this branch. //child within this branch.
@ -2342,6 +2443,9 @@ func (*UnimplementedWalletKitServer) LeaseOutput(ctx context.Context, req *Lease
func (*UnimplementedWalletKitServer) ReleaseOutput(ctx context.Context, req *ReleaseOutputRequest) (*ReleaseOutputResponse, error) { func (*UnimplementedWalletKitServer) ReleaseOutput(ctx context.Context, req *ReleaseOutputRequest) (*ReleaseOutputResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ReleaseOutput not implemented") return nil, status.Errorf(codes.Unimplemented, "method ReleaseOutput not implemented")
} }
func (*UnimplementedWalletKitServer) ListLeases(ctx context.Context, req *ListLeasesRequest) (*ListLeasesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListLeases not implemented")
}
func (*UnimplementedWalletKitServer) DeriveNextKey(ctx context.Context, req *KeyReq) (*signrpc.KeyDescriptor, error) { func (*UnimplementedWalletKitServer) DeriveNextKey(ctx context.Context, req *KeyReq) (*signrpc.KeyDescriptor, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeriveNextKey not implemented") return nil, status.Errorf(codes.Unimplemented, "method DeriveNextKey not implemented")
} }
@ -2437,6 +2541,24 @@ func _WalletKit_ReleaseOutput_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _WalletKit_ListLeases_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListLeasesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletKitServer).ListLeases(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/walletrpc.WalletKit/ListLeases",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletKitServer).ListLeases(ctx, req.(*ListLeasesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WalletKit_DeriveNextKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _WalletKit_DeriveNextKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(KeyReq) in := new(KeyReq)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@ -2669,6 +2791,10 @@ var _WalletKit_serviceDesc = grpc.ServiceDesc{
MethodName: "ReleaseOutput", MethodName: "ReleaseOutput",
Handler: _WalletKit_ReleaseOutput_Handler, Handler: _WalletKit_ReleaseOutput_Handler,
}, },
{
MethodName: "ListLeases",
Handler: _WalletKit_ListLeases_Handler,
},
{ {
MethodName: "DeriveNextKey", MethodName: "DeriveNextKey",
Handler: _WalletKit_DeriveNextKey_Handler, Handler: _WalletKit_DeriveNextKey_Handler,

@ -133,6 +133,24 @@ func local_request_WalletKit_ReleaseOutput_0(ctx context.Context, marshaler runt
} }
func request_WalletKit_ListLeases_0(ctx context.Context, marshaler runtime.Marshaler, client WalletKitClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListLeasesRequest
var metadata runtime.ServerMetadata
msg, err := client.ListLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_WalletKit_ListLeases_0(ctx context.Context, marshaler runtime.Marshaler, server WalletKitServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListLeasesRequest
var metadata runtime.ServerMetadata
msg, err := server.ListLeases(ctx, &protoReq)
return msg, metadata, err
}
func request_WalletKit_DeriveNextKey_0(ctx context.Context, marshaler runtime.Marshaler, client WalletKitClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_WalletKit_DeriveNextKey_0(ctx context.Context, marshaler runtime.Marshaler, client WalletKitClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq KeyReq var protoReq KeyReq
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@ -609,6 +627,26 @@ func RegisterWalletKitHandlerServer(ctx context.Context, mux *runtime.ServeMux,
}) })
mux.Handle("POST", pattern_WalletKit_ListLeases_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_WalletKit_ListLeases_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_WalletKit_ListLeases_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_WalletKit_DeriveNextKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { mux.Handle("POST", pattern_WalletKit_DeriveNextKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
@ -950,6 +988,26 @@ func RegisterWalletKitHandlerClient(ctx context.Context, mux *runtime.ServeMux,
}) })
mux.Handle("POST", pattern_WalletKit_ListLeases_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_WalletKit_ListLeases_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_WalletKit_ListLeases_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_WalletKit_DeriveNextKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { mux.Handle("POST", pattern_WalletKit_DeriveNextKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
@ -1200,6 +1258,8 @@ var (
pattern_WalletKit_ReleaseOutput_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "wallet", "utxos", "release"}, "", runtime.AssumeColonVerbOpt(true))) pattern_WalletKit_ReleaseOutput_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "wallet", "utxos", "release"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_WalletKit_ListLeases_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "wallet", "utxos", "leases"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_WalletKit_DeriveNextKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "wallet", "key", "next"}, "", runtime.AssumeColonVerbOpt(true))) pattern_WalletKit_DeriveNextKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "wallet", "key", "next"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_WalletKit_DeriveKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "wallet", "key"}, "", runtime.AssumeColonVerbOpt(true))) pattern_WalletKit_DeriveKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "wallet", "key"}, "", runtime.AssumeColonVerbOpt(true)))
@ -1232,6 +1292,8 @@ var (
forward_WalletKit_ReleaseOutput_0 = runtime.ForwardResponseMessage forward_WalletKit_ReleaseOutput_0 = runtime.ForwardResponseMessage
forward_WalletKit_ListLeases_0 = runtime.ForwardResponseMessage
forward_WalletKit_DeriveNextKey_0 = runtime.ForwardResponseMessage forward_WalletKit_DeriveNextKey_0 = runtime.ForwardResponseMessage
forward_WalletKit_DeriveKey_0 = runtime.ForwardResponseMessage forward_WalletKit_DeriveKey_0 = runtime.ForwardResponseMessage

@ -32,6 +32,11 @@ service WalletKit {
*/ */
rpc ReleaseOutput (ReleaseOutputRequest) returns (ReleaseOutputResponse); rpc ReleaseOutput (ReleaseOutputRequest) returns (ReleaseOutputResponse);
/*
ListLeases lists all currently locked utxos.
*/
rpc ListLeases (ListLeasesRequest) returns (ListLeasesResponse);
/* /*
DeriveNextKey attempts to derive the *next* key within the key family DeriveNextKey attempts to derive the *next* key within the key family
(account in BIP43) specified. This method should return the next external (account in BIP43) specified. This method should return the next external
@ -189,6 +194,10 @@ message LeaseOutputRequest {
// The identifying outpoint of the output being leased. // The identifying outpoint of the output being leased.
lnrpc.OutPoint outpoint = 2; lnrpc.OutPoint outpoint = 2;
// The time in seconds before the lock expires. If set to zero, the default
// lock duration is used.
uint64 expiration_seconds = 3;
} }
message LeaseOutputResponse { message LeaseOutputResponse {
@ -599,3 +608,11 @@ message FinalizePsbtResponse {
// The fully signed and finalized transaction in the raw wire format. // The fully signed and finalized transaction in the raw wire format.
bytes raw_final_tx = 2; bytes raw_final_tx = 2;
} }
message ListLeasesRequest {
}
message ListLeasesResponse {
// The list of currently leased utxos.
repeated UtxoLease locked_utxos = 1;
}

@ -457,6 +457,29 @@
] ]
} }
}, },
"/v2/wallet/utxos/leases": {
"post": {
"summary": "ListLeases lists all currently locked utxos.",
"operationId": "ListLeases",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/walletrpcListLeasesResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"tags": [
"WalletKit"
]
}
},
"/v2/wallet/utxos/release": { "/v2/wallet/utxos/release": {
"post": { "post": {
"summary": "ReleaseOutput unlocks an output, allowing it to be available for coin\nselection if it remains unspent. The ID should match the one used to\noriginally lock the output.", "summary": "ReleaseOutput unlocks an output, allowing it to be available for coin\nselection if it remains unspent. The ID should match the one used to\noriginally lock the output.",
@ -876,6 +899,11 @@
"outpoint": { "outpoint": {
"$ref": "#/definitions/lnrpcOutPoint", "$ref": "#/definitions/lnrpcOutPoint",
"description": "The identifying outpoint of the output being leased." "description": "The identifying outpoint of the output being leased."
},
"expiration_seconds": {
"type": "string",
"format": "uint64",
"description": "The time in seconds before the lock expires. If set to zero, the default\nlock duration is used."
} }
} }
}, },
@ -889,6 +917,18 @@
} }
} }
}, },
"walletrpcListLeasesResponse": {
"type": "object",
"properties": {
"locked_utxos": {
"type": "array",
"items": {
"$ref": "#/definitions/walletrpcUtxoLease"
},
"description": "The list of currently leased utxos."
}
}
},
"walletrpcListSweepsResponse": { "walletrpcListSweepsResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

@ -112,6 +112,10 @@ var (
Entity: "onchain", Entity: "onchain",
Action: "write", Action: "write",
}}, }},
"/walletrpc.WalletKit/ListLeases": {{
Entity: "onchain",
Action: "read",
}},
"/walletrpc.WalletKit/ListUnspent": {{ "/walletrpc.WalletKit/ListUnspent": {{
Entity: "onchain", Entity: "onchain",
Action: "read", Action: "read",
@ -368,11 +372,19 @@ func (w *WalletKit) LeaseOutput(ctx context.Context,
return nil, err return nil, err
} }
// Use the specified lock duration or fall back to the default.
duration := DefaultLockDuration
if req.ExpirationSeconds != 0 {
duration = time.Duration(req.ExpirationSeconds) * time.Second
}
// Acquire the global coin selection lock to ensure there aren't any // Acquire the global coin selection lock to ensure there aren't any
// other concurrent processes attempting to lease the same UTXO. // other concurrent processes attempting to lease the same UTXO.
var expiration time.Time var expiration time.Time
err = w.cfg.CoinSelectionLocker.WithCoinSelectLock(func() error { err = w.cfg.CoinSelectionLocker.WithCoinSelectLock(func() error {
expiration, err = w.cfg.Wallet.LeaseOutput(lockID, *op) expiration, err = w.cfg.Wallet.LeaseOutput(
lockID, *op, duration,
)
return err return err
}) })
if err != nil { if err != nil {
@ -413,6 +425,20 @@ func (w *WalletKit) ReleaseOutput(ctx context.Context,
return &ReleaseOutputResponse{}, nil return &ReleaseOutputResponse{}, nil
} }
// ListLeases returns a list of all currently locked utxos.
func (w *WalletKit) ListLeases(ctx context.Context,
req *ListLeasesRequest) (*ListLeasesResponse, error) {
leases, err := w.cfg.Wallet.ListLeasedOutputs()
if err != nil {
return nil, err
}
return &ListLeasesResponse{
LockedUtxos: marshallLeases(leases),
}, nil
}
// DeriveNextKey attempts to derive the *next* key within the key family // DeriveNextKey attempts to derive the *next* key within the key family
// (account in BIP43) specified. This method should return the next external // (account in BIP43) specified. This method should return the next external
// child within this branch. // child within this branch.
@ -909,7 +935,7 @@ func (w *WalletKit) FundPsbt(_ context.Context,
err error err error
packet *psbt.Packet packet *psbt.Packet
feeSatPerKW chainfee.SatPerKWeight feeSatPerKW chainfee.SatPerKWeight
locks []*utxoLock locks []*wtxmgr.LockedOutput
rawPsbt bytes.Buffer rawPsbt bytes.Buffer
) )
@ -1070,18 +1096,7 @@ func (w *WalletKit) FundPsbt(_ context.Context,
} }
// Convert the lock leases to the RPC format. // Convert the lock leases to the RPC format.
rpcLocks := make([]*UtxoLease, len(locks)) rpcLocks := marshallLeases(locks)
for idx, lock := range locks {
rpcLocks[idx] = &UtxoLease{
Id: lock.lockID[:],
Outpoint: &lnrpc.OutPoint{
TxidBytes: lock.outpoint.Hash[:],
TxidStr: lock.outpoint.Hash.String(),
OutputIndex: lock.outpoint.Index,
},
Expiration: uint64(lock.expiration.Unix()),
}
}
return &FundPsbtResponse{ return &FundPsbtResponse{
FundedPsbt: rawPsbt.Bytes(), FundedPsbt: rawPsbt.Bytes(),
@ -1090,6 +1105,24 @@ func (w *WalletKit) FundPsbt(_ context.Context,
}, nil }, nil
} }
// marshallLeases converts the lock leases to the RPC format.
func marshallLeases(locks []*wtxmgr.LockedOutput) []*UtxoLease {
rpcLocks := make([]*UtxoLease, len(locks))
for idx, lock := range locks {
rpcLocks[idx] = &UtxoLease{
Id: lock.LockID[:],
Outpoint: &lnrpc.OutPoint{
TxidBytes: lock.Outpoint.Hash[:],
TxidStr: lock.Outpoint.Hash.String(),
OutputIndex: lock.Outpoint.Index,
},
Expiration: uint64(lock.Expiration.Unix()),
}
}
return rpcLocks
}
// FinalizePsbt expects a partial transaction with all inputs and outputs fully // FinalizePsbt expects a partial transaction with all inputs and outputs fully
// declared and tries to sign all inputs that belong to the wallet. Lnd must be // declared and tries to sign all inputs that belong to the wallet. Lnd must be
// the last signer of the transaction. That means, if there are any unsigned // the last signer of the transaction. That means, if there are any unsigned

@ -131,8 +131,8 @@ func (w *WalletController) LockOutpoint(o wire.OutPoint) {}
func (w *WalletController) UnlockOutpoint(o wire.OutPoint) {} func (w *WalletController) UnlockOutpoint(o wire.OutPoint) {}
// LeaseOutput returns the current time and a nil error. // LeaseOutput returns the current time and a nil error.
func (w *WalletController) LeaseOutput(wtxmgr.LockID, wire.OutPoint) (time.Time, func (w *WalletController) LeaseOutput(wtxmgr.LockID, wire.OutPoint,
error) { time.Duration) (time.Time, error) {
return time.Now(), nil return time.Now(), nil
} }
@ -142,6 +142,10 @@ func (w *WalletController) ReleaseOutput(wtxmgr.LockID, wire.OutPoint) error {
return nil return nil
} }
func (w *WalletController) ListLeasedOutputs() ([]*wtxmgr.LockedOutput, error) {
return nil, nil
}
// FundPsbt currently does nothing. // FundPsbt currently does nothing.
func (w *WalletController) FundPsbt(_ *psbt.Packet, func (w *WalletController) FundPsbt(_ *psbt.Packet,
_ chainfee.SatPerKWeight) (int32, error) { _ chainfee.SatPerKWeight) (int32, error) {

@ -393,8 +393,8 @@ func (b *BtcWallet) UnlockOutpoint(o wire.OutPoint) {
// wtxmgr.ErrOutputAlreadyLocked is returned. // wtxmgr.ErrOutputAlreadyLocked is returned.
// //
// NOTE: This method requires the global coin selection lock to be held. // NOTE: This method requires the global coin selection lock to be held.
func (b *BtcWallet) LeaseOutput(id wtxmgr.LockID, op wire.OutPoint) (time.Time, func (b *BtcWallet) LeaseOutput(id wtxmgr.LockID, op wire.OutPoint,
error) { duration time.Duration) (time.Time, error) {
// Make sure we don't attempt to double lock an output that's been // Make sure we don't attempt to double lock an output that's been
// locked by the in-memory implementation. // locked by the in-memory implementation.
@ -402,7 +402,12 @@ func (b *BtcWallet) LeaseOutput(id wtxmgr.LockID, op wire.OutPoint) (time.Time,
return time.Time{}, wtxmgr.ErrOutputAlreadyLocked return time.Time{}, wtxmgr.ErrOutputAlreadyLocked
} }
return b.wallet.LeaseOutput(id, op) return b.wallet.LeaseOutput(id, op, duration)
}
// ListLeasedOutputs returns a list of all currently locked outputs.
func (b *BtcWallet) ListLeasedOutputs() ([]*wtxmgr.LockedOutput, error) {
return b.wallet.ListLeasedOutputs()
} }
// ReleaseOutput unlocks an output, allowing it to be available for coin // ReleaseOutput unlocks an output, allowing it to be available for coin

@ -250,7 +250,8 @@ type WalletController interface {
// wtxmgr.ErrOutputAlreadyLocked is returned. // wtxmgr.ErrOutputAlreadyLocked is returned.
// //
// NOTE: This method requires the global coin selection lock to be held. // NOTE: This method requires the global coin selection lock to be held.
LeaseOutput(id wtxmgr.LockID, op wire.OutPoint) (time.Time, error) LeaseOutput(id wtxmgr.LockID, op wire.OutPoint,
duration time.Duration) (time.Time, error)
// ReleaseOutput unlocks an output, allowing it to be available for coin // ReleaseOutput unlocks an output, allowing it to be available for coin
// selection if it remains unspent. The ID should match the one used to // selection if it remains unspent. The ID should match the one used to
@ -259,6 +260,9 @@ type WalletController interface {
// NOTE: This method requires the global coin selection lock to be held. // NOTE: This method requires the global coin selection lock to be held.
ReleaseOutput(id wtxmgr.LockID, op wire.OutPoint) error ReleaseOutput(id wtxmgr.LockID, op wire.OutPoint) error
// ListLeasedOutputs returns a list of all currently locked outputs.
ListLeasedOutputs() ([]*wtxmgr.LockedOutput, error)
// PublishTransaction performs cursory validation (dust checks, etc), // PublishTransaction performs cursory validation (dust checks, etc),
// then finally broadcasts the passed transaction to the Bitcoin network. // then finally broadcasts the passed transaction to the Bitcoin network.
// If the transaction is rejected because it is conflicting with an // If the transaction is rejected because it is conflicting with an