rpc: SendOutputs considers anchor reserve

This commit is contained in:
Slyghtning committed 2023-04-29 22:44:23 +02:00
1 parent 3c8c057ea9
commit 903b5dde89
3 files changed
+59 -6

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
package walletrpc
import "errors"
var (
// ErrZeroLabel is returned when an attempt is made to label a
// transaction with an empty label.
ErrZeroLabel = errors.New("cannot label transaction with empty " +
"label")
// ErrInsufficientReserve is returned when SendOutputs wouldn't leave
// enough funds in the wallet to cover for the anchor reserve.
ErrInsufficientReserve = errors.New("the outputs to be sent " +
"would leave insufficient reserves for anchor channels in " +
"the wallet")
)
+27 -6
View File
@@ -222,10 +222,6 @@ var (
} }
) )
// ErrZeroLabel is returned when an attempt is made to label a transaction with
// an empty label.
var ErrZeroLabel = errors.New("cannot label transaction with empty label")
// ServerShell is a shell struct holding a reference to the actual sub-server. // ServerShell is a shell struct holding a reference to the actual sub-server.
// It is used to register the gRPC sub-server with the root server before we // It is used to register the gRPC sub-server with the root server before we
// have the necessary dependencies to populate the actual sub-server. // have the necessary dependencies to populate the actual sub-server.
@@ -666,12 +662,14 @@ func (w *WalletKit) SendOutputs(ctx context.Context,
// Before we can request this transaction to be created, we'll need to // Before we can request this transaction to be created, we'll need to
// amp the protos back into the format that the internal wallet will // amp the protos back into the format that the internal wallet will
// recognize. // recognize.
var totalOutputValue int64
outputsToCreate := make([]*wire.TxOut, 0, len(req.Outputs)) outputsToCreate := make([]*wire.TxOut, 0, len(req.Outputs))
for _, output := range req.Outputs { for _, output := range req.Outputs {
outputsToCreate = append(outputsToCreate, &wire.TxOut{ outputsToCreate = append(outputsToCreate, &wire.TxOut{
Value: output.Value, Value: output.Value,
PkScript: output.PkScript, PkScript: output.PkScript,
}) })
totalOutputValue += output.Value
} }
// Then, we'll extract the minimum number of confirmations that each // Then, we'll extract the minimum number of confirmations that each
@@ -681,13 +679,36 @@ func (w *WalletKit) SendOutputs(ctx context.Context,
return nil, err return nil, err
} }
// Before sending out funds we need to ensure that the remainder of our
// wallet funds would cover for the anchor reserve requirement. We'll
// also take unconfirmed funds into account.
walletBalance, err := w.cfg.Wallet.ConfirmedBalance(
0, lnwallet.DefaultAccountName,
)
if err != nil {
return nil, err
}
// We'll get the currently required reserve amount.
reserve, err := w.RequiredReserve(ctx, &RequiredReserveRequest{})
if err != nil {
return nil, err
}
// Then we check if our current wallet balance undershoots the required
// reserve if we'd send out the outputs specified in the request.
if int64(walletBalance)-totalOutputValue < reserve.RequiredReserve {
return nil, ErrInsufficientReserve
}
label, err := labels.ValidateAPI(req.Label) label, err := labels.ValidateAPI(req.Label)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Now that we have the outputs mapped, we can request that the wallet // Now that we have the outputs mapped and checked for the reserve
// attempt to create this transaction. // requirement, we can request that the wallet attempts to create this
// transaction.
tx, err := w.cfg.Wallet.SendOutputs( tx, err := w.cfg.Wallet.SendOutputs(
outputsToCreate, chainfee.SatPerKWeight(req.SatPerKw), minConfs, label, outputsToCreate, chainfee.SatPerKWeight(req.SatPerKw), minConfs, label,
) )
+15
View File
@@ -290,3 +290,18 @@ func (h *HarnessRPC) ImportTapscript(
return resp return resp
} }
// RequiredReserve makes a RPC call to the node's WalletKitClient and asserts.
//
//nolint:lll
func (h *HarnessRPC) RequiredReserve(
req *walletrpc.RequiredReserveRequest) *walletrpc.RequiredReserveResponse {
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
defer cancel()
resp, err := h.WalletKit.RequiredReserve(ctxt, req)
h.NoError(err, "RequiredReserve")
return resp
}