mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 22:25:24 +01:00
lnd: add optional change output index to check reserved wallet balance
This commit is contained in:
parent
32fa48df7d
commit
a5a477e311
2 changed files with 65 additions and 7 deletions
|
@ -272,6 +272,20 @@ type addSingleFunderSigsMsg struct {
|
|||
err chan error
|
||||
}
|
||||
|
||||
// CheckReservedValueTxReq is the request struct used to call
|
||||
// CheckReservedValueTx with. It contains the transaction to check as well as
|
||||
// an optional explicitly defined index to denote a change output that is not
|
||||
// watched by the wallet.
|
||||
type CheckReservedValueTxReq struct {
|
||||
// Tx is the transaction to check the outputs for.
|
||||
Tx *wire.MsgTx
|
||||
|
||||
// ChangeIndex denotes an optional output index that can be explicitly
|
||||
// set for a change that is not being watched by the wallet and would
|
||||
// otherwise not be recognized as a change output.
|
||||
ChangeIndex *int
|
||||
}
|
||||
|
||||
// LightningWallet is a domain specific, yet general Bitcoin wallet capable of
|
||||
// executing workflow required to interact with the Lightning Network. It is
|
||||
// domain specific in the sense that it understands all the fancy scripts used
|
||||
|
@ -1036,8 +1050,8 @@ func (l *LightningWallet) CheckReservedValue(in []wire.OutPoint,
|
|||
// database.
|
||||
//
|
||||
// NOTE: This method should only be run with the CoinSelectLock held.
|
||||
func (l *LightningWallet) CheckReservedValueTx(tx *wire.MsgTx) (btcutil.Amount,
|
||||
error) {
|
||||
func (l *LightningWallet) CheckReservedValueTx(req CheckReservedValueTxReq) (
|
||||
btcutil.Amount, error) {
|
||||
|
||||
numAnchors, err := l.currentNumAnchorChans()
|
||||
if err != nil {
|
||||
|
@ -1045,11 +1059,44 @@ func (l *LightningWallet) CheckReservedValueTx(tx *wire.MsgTx) (btcutil.Amount,
|
|||
}
|
||||
|
||||
var inputs []wire.OutPoint
|
||||
for _, txIn := range tx.TxIn {
|
||||
for _, txIn := range req.Tx.TxIn {
|
||||
inputs = append(inputs, txIn.PreviousOutPoint)
|
||||
}
|
||||
|
||||
return l.CheckReservedValue(inputs, tx.TxOut, numAnchors)
|
||||
reservedVal, err := l.CheckReservedValue(
|
||||
inputs, req.Tx.TxOut, numAnchors,
|
||||
)
|
||||
switch {
|
||||
|
||||
// If the error returned from CheckReservedValue is
|
||||
// ErrReservedValueInvalidated, then it did nonetheless return
|
||||
// the required reserved value and we check for the optional
|
||||
// change index.
|
||||
case errors.Is(err, ErrReservedValueInvalidated):
|
||||
// Without a change index provided there is nothing more to
|
||||
// check and the error is returned.
|
||||
if req.ChangeIndex == nil {
|
||||
return reservedVal, err
|
||||
}
|
||||
|
||||
// If a change index was provided we make only sure that it
|
||||
// would leave sufficient funds for the reserved balance value.
|
||||
//
|
||||
// Note: This is used if a change output index is explicitly set
|
||||
// but that may not be watched by the wallet and therefore is
|
||||
// not picked up by the call to CheckReservedValue above.
|
||||
chIdx := *req.ChangeIndex
|
||||
if chIdx < 0 || chIdx >= len(req.Tx.TxOut) ||
|
||||
req.Tx.TxOut[chIdx].Value < int64(reservedVal) {
|
||||
|
||||
return reservedVal, err
|
||||
}
|
||||
|
||||
case err != nil:
|
||||
return reservedVal, err
|
||||
}
|
||||
|
||||
return reservedVal, nil
|
||||
}
|
||||
|
||||
// initOurContribution initializes the given ChannelReservation with our coins
|
||||
|
|
17
rpcserver.go
17
rpcserver.go
|
@ -1009,7 +1009,14 @@ func (r *rpcServer) sendCoinsOnChain(paymentMap map[string]int64,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
_, err = r.server.cc.Wallet.CheckReservedValueTx(authoredTx.Tx)
|
||||
// Check the authored transaction and use the explicitly set change index
|
||||
// to make sure that the wallet reserved balance is not invalidated.
|
||||
_, err = r.server.cc.Wallet.CheckReservedValueTx(
|
||||
lnwallet.CheckReservedValueTxReq{
|
||||
Tx: authoredTx.Tx,
|
||||
ChangeIndex: &authoredTx.ChangeIndex,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1242,7 +1249,9 @@ func (r *rpcServer) SendCoins(ctx context.Context,
|
|||
err = wallet.WithCoinSelectLock(func() error {
|
||||
var err error
|
||||
reservedVal, err = wallet.CheckReservedValueTx(
|
||||
sweepTxPkg.SweepTx,
|
||||
lnwallet.CheckReservedValueTxReq{
|
||||
Tx: sweepTxPkg.SweepTx,
|
||||
},
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
@ -1292,7 +1301,9 @@ func (r *rpcServer) SendCoins(ctx context.Context,
|
|||
// Sanity check the new tx by re-doing the check.
|
||||
err = wallet.WithCoinSelectLock(func() error {
|
||||
_, err := wallet.CheckReservedValueTx(
|
||||
sweepTxPkg.SweepTx,
|
||||
lnwallet.CheckReservedValueTxReq{
|
||||
Tx: sweepTxPkg.SweepTx,
|
||||
},
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue