rpc: non-existence of a nursery report is no longer an error
This commit fixes a slight logic error that could render the `pendingchannels` RPC unusable if a node was on the reciting end of a channel force close with no time-locked balance. In such a case the channel wouldn’t be sent to the utxoNursery, resulting in an “contract not found error”. To fix this behavior, we’ve created a typed error that can be checked within the RPC, thus we no longer treat this routine case as an error case.
This commit is contained in:
parent
459583ca04
commit
9c685433f3
30
rpcserver.go
30
rpcserver.go
@ -721,13 +721,14 @@ func (r *rpcServer) forceCloseChan(channel *lnwallet.LightningChannel) (*chainha
|
||||
chanPoint := channel.ChannelPoint()
|
||||
chanInfo := channel.StateSnapshot()
|
||||
closeInfo := &channeldb.ChannelCloseSummary{
|
||||
ChanPoint: *chanPoint,
|
||||
ClosingTXID: closeTx.TxHash(),
|
||||
RemotePub: &chanInfo.RemoteIdentity,
|
||||
Capacity: chanInfo.Capacity,
|
||||
OurBalance: chanInfo.LocalBalance,
|
||||
CloseType: channeldb.ForceClose,
|
||||
IsPending: true,
|
||||
ChanPoint: *chanPoint,
|
||||
ClosingTXID: closeTx.TxHash(),
|
||||
RemotePub: &chanInfo.RemoteIdentity,
|
||||
Capacity: chanInfo.Capacity,
|
||||
SettledBalance: chanInfo.LocalBalance,
|
||||
TimeLockedBalance: chanInfo.LocalBalance,
|
||||
CloseType: channeldb.ForceClose,
|
||||
IsPending: true,
|
||||
}
|
||||
if err := channel.DeleteState(closeInfo); err != nil {
|
||||
return nil, err
|
||||
@ -767,7 +768,8 @@ func (r *rpcServer) GetInfo(ctx context.Context,
|
||||
|
||||
isSynced, err := r.server.lnwallet.IsSynced()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to sync PoV of the wallet with current best block in the main chain: %v", err)
|
||||
return nil, fmt.Errorf("unable to sync PoV of the wallet "+
|
||||
"with current best block in the main chain: %v", err)
|
||||
}
|
||||
|
||||
activeChains := make([]string, registeredChains.NumActiveChains())
|
||||
@ -933,7 +935,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context,
|
||||
RemoteNodePub: hex.EncodeToString(pub),
|
||||
ChannelPoint: chanPoint.String(),
|
||||
Capacity: int64(pendingClose.Capacity),
|
||||
LocalBalance: int64(pendingClose.OurBalance),
|
||||
LocalBalance: int64(pendingClose.SettledBalance),
|
||||
}
|
||||
|
||||
closeTXID := pendingClose.ClosingTXID.String()
|
||||
@ -961,9 +963,14 @@ func (r *rpcServer) PendingChannels(ctx context.Context,
|
||||
ClosingTxid: closeTXID,
|
||||
}
|
||||
|
||||
// Query for the maturity state for this force closed
|
||||
// channel. If we didn't have any time-locked outputs,
|
||||
// then the nursery may not know of the contract.
|
||||
nurseryInfo, err := r.server.utxoNursery.NurseryReport(&chanPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if err != nil && err != ErrContractNotFound {
|
||||
return nil, fmt.Errorf("unable to obtain "+
|
||||
"nursery report for ChannelPoint(%v): %v",
|
||||
chanPoint, err)
|
||||
}
|
||||
|
||||
// If the nursery knows of this channel, then we can
|
||||
@ -996,7 +1003,6 @@ func (r *rpcServer) PendingChannels(ctx context.Context,
|
||||
|
||||
// ListChannels returns a description of all direct active, open channels the
|
||||
// node knows of.
|
||||
// TODO(roasbeef): add 'online' bit to response
|
||||
func (r *rpcServer) ListChannels(ctx context.Context,
|
||||
in *lnrpc.ListChannelsRequest) (*lnrpc.ListChannelsResponse, error) {
|
||||
|
||||
|
@ -70,6 +70,12 @@ var (
|
||||
byteOrder = binary.BigEndian
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrContractNotFound is returned when the nursery is unable to
|
||||
// retreive information about a queried contract.
|
||||
ErrContractNotFound = fmt.Errorf("unable to locate contract")
|
||||
)
|
||||
|
||||
// witnessType determines how an output's witness will be generated. The
|
||||
// default commitmentTimeLock type will generate a witness that will allow
|
||||
// spending of a time-locked transaction enforced by CheckSequenceVerify.
|
||||
@ -317,9 +323,9 @@ type incubationRequest struct {
|
||||
func (u *utxoNursery) IncubateOutputs(closeSummary *lnwallet.ForceCloseSummary) {
|
||||
var incReq incubationRequest
|
||||
|
||||
// It could be that our to-self output was below the dust limit. In that
|
||||
// case the SignDescriptor would be nil and we would not have that output
|
||||
// to incubate.
|
||||
// It could be that our to-self output was below the dust limit. In
|
||||
// that case the SignDescriptor would be nil and we would not have that
|
||||
// output to incubate.
|
||||
if closeSummary.SelfOutputSignDesc != nil {
|
||||
outputAmt := btcutil.Amount(closeSummary.SelfOutputSignDesc.Output.Value)
|
||||
selfOutput := &kidOutput{
|
||||
@ -510,7 +516,7 @@ func (u *utxoNursery) NurseryReport(chanPoint *wire.OutPoint) (*contractMaturity
|
||||
// entry for this particular contract.
|
||||
indexInfo := indexBucket.Get(chanPointBytes)
|
||||
if indexInfo == nil {
|
||||
return fmt.Errorf("contract not found in index")
|
||||
return ErrContractNotFound
|
||||
}
|
||||
|
||||
// If an entry is found, then using the height store in
|
||||
@ -519,7 +525,7 @@ func (u *utxoNursery) NurseryReport(chanPoint *wire.OutPoint) (*contractMaturity
|
||||
height := indexInfo[:4]
|
||||
heightRow := kgtnBucket.Get(height)
|
||||
if heightRow == nil {
|
||||
return fmt.Errorf("contract not found")
|
||||
return ErrContractNotFound
|
||||
}
|
||||
|
||||
// Once we have the entry itself, we'll slice of the
|
||||
|
Loading…
Reference in New Issue
Block a user