lnwallet: introduce mutex around coin selection logic
This commit is contained in:
parent
7874357384
commit
36e7c38812
@ -136,6 +136,10 @@ type LightningWallet struct {
|
|||||||
lmtx sync.RWMutex
|
lmtx sync.RWMutex
|
||||||
|
|
||||||
DB walletdb.DB
|
DB walletdb.DB
|
||||||
|
// This mutex MUST be held when performing coin selection in order to
|
||||||
|
// avoid inadvertently creating multiple funding transaction which
|
||||||
|
// double spend inputs accross each other.
|
||||||
|
coinSelectMtx sync.RWMutex
|
||||||
|
|
||||||
// A wrapper around a namespace within boltdb reserved for ln-based
|
// A wrapper around a namespace within boltdb reserved for ln-based
|
||||||
// wallet meta-data.
|
// wallet meta-data.
|
||||||
@ -327,12 +331,19 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
|
|||||||
|
|
||||||
reservation.partialState.TheirLNID = req.nodeID
|
reservation.partialState.TheirLNID = req.nodeID
|
||||||
ourContribution := reservation.ourContribution
|
ourContribution := reservation.ourContribution
|
||||||
|
// We hold the coin select mutex while querying for outputs, and
|
||||||
|
// performing coin selection in order to avoid inadvertent double spends
|
||||||
|
// accross funding transactions.
|
||||||
|
// NOTE: we don't use defer her so we can properly release the lock
|
||||||
|
// when we encounter an error condition.
|
||||||
|
l.coinSelectMtx.Lock()
|
||||||
|
|
||||||
// Find all unlocked unspent outputs with greater than 6 confirmations.
|
// Find all unlocked unspent outputs with greater than 6 confirmations.
|
||||||
// TODO(roasbeef): make 6 a config paramter?
|
|
||||||
maxConfs := int32(math.MaxInt32)
|
maxConfs := int32(math.MaxInt32)
|
||||||
|
// TODO(roasbeef): make 6 a config paramter?
|
||||||
unspentOutputs, err := l.wallet.ListUnspent(6, maxConfs, nil)
|
unspentOutputs, err := l.wallet.ListUnspent(6, maxConfs, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
l.coinSelectMtx.Unlock()
|
||||||
req.err <- err
|
req.err <- err
|
||||||
req.resp <- nil
|
req.resp <- nil
|
||||||
return
|
return
|
||||||
@ -341,6 +352,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
|
|||||||
// Convert the outputs to coins for coin selection below.
|
// Convert the outputs to coins for coin selection below.
|
||||||
coins, err := outputsToCoins(unspentOutputs)
|
coins, err := outputsToCoins(unspentOutputs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
l.coinSelectMtx.Unlock()
|
||||||
req.err <- err
|
req.err <- err
|
||||||
req.resp <- nil
|
req.resp <- nil
|
||||||
return
|
return
|
||||||
@ -361,6 +373,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
|
|||||||
}
|
}
|
||||||
selectedCoins, err := selector.CoinSelect(req.fundingAmount, coins)
|
selectedCoins, err := selector.CoinSelect(req.fundingAmount, coins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
l.coinSelectMtx.Unlock()
|
||||||
req.err <- err
|
req.err <- err
|
||||||
req.resp <- nil
|
req.resp <- nil
|
||||||
return
|
return
|
||||||
@ -380,6 +393,8 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
|
|||||||
ourContribution.Inputs[i] = wire.NewTxIn(outPoint, nil)
|
ourContribution.Inputs[i] = wire.NewTxIn(outPoint, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l.coinSelectMtx.Unlock()
|
||||||
|
|
||||||
// Create some possibly neccessary change outputs.
|
// Create some possibly neccessary change outputs.
|
||||||
selectedTotalValue := coinset.NewCoinSet(selectedCoins.Coins()).TotalValue()
|
selectedTotalValue := coinset.NewCoinSet(selectedCoins.Coins()).TotalValue()
|
||||||
if selectedTotalValue > req.fundingAmount {
|
if selectedTotalValue > req.fundingAmount {
|
||||||
|
Loading…
Reference in New Issue
Block a user