channeldb: add new AbandonChannel method
This commit is contained in:
parent
8755a35860
commit
f6614dd435
@ -1094,6 +1094,54 @@ func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error) {
|
|||||||
return dedupedAddrs, nil
|
return dedupedAddrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AbandonChannel attempts to remove the target channel from the open channel
|
||||||
|
// database. If the channel was already removed (has a closed channel entry),
|
||||||
|
// then we'll return a nil error. Otherwise, we'll insert a new close summary
|
||||||
|
// into the database.
|
||||||
|
func (d *DB) AbandonChannel(chanPoint *wire.OutPoint, bestHeight uint32) error {
|
||||||
|
// With the chanPoint constructed, we'll attempt to find the target
|
||||||
|
// channel in the database. If we can't find the channel, then we'll
|
||||||
|
// return the error back to the caller.
|
||||||
|
dbChan, err := d.FetchChannel(*chanPoint)
|
||||||
|
switch {
|
||||||
|
// If the channel wasn't found, then it's possible that it was already
|
||||||
|
// abandoned from the database.
|
||||||
|
case err == ErrChannelNotFound:
|
||||||
|
_, closedErr := d.FetchClosedChannel(chanPoint)
|
||||||
|
if closedErr != nil {
|
||||||
|
return closedErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the channel was already closed, then we don't return an
|
||||||
|
// error as we'd like fro this step to be repeatable.
|
||||||
|
return nil
|
||||||
|
case err != nil:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we've found the channel, we'll populate a close summary for
|
||||||
|
// the channel, so we can store as much information for this abounded
|
||||||
|
// channel as possible. We also ensure that we set Pending to false, to
|
||||||
|
// indicate that this channel has been "fully" closed.
|
||||||
|
summary := &ChannelCloseSummary{
|
||||||
|
CloseType: Abandoned,
|
||||||
|
ChanPoint: *chanPoint,
|
||||||
|
ChainHash: dbChan.ChainHash,
|
||||||
|
CloseHeight: bestHeight,
|
||||||
|
RemotePub: dbChan.IdentityPub,
|
||||||
|
Capacity: dbChan.Capacity,
|
||||||
|
SettledBalance: dbChan.LocalCommitment.LocalBalance.ToSatoshis(),
|
||||||
|
ShortChanID: dbChan.ShortChanID(),
|
||||||
|
RemoteCurrentRevocation: dbChan.RemoteCurrentRevocation,
|
||||||
|
RemoteNextRevocation: dbChan.RemoteNextRevocation,
|
||||||
|
LocalChanConfig: dbChan.LocalChanCfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we'll close the channel in the DB, and return back to the
|
||||||
|
// caller.
|
||||||
|
return dbChan.CloseChannel(summary)
|
||||||
|
}
|
||||||
|
|
||||||
// syncVersions function is used for safe db version synchronization. It
|
// syncVersions function is used for safe db version synchronization. It
|
||||||
// applies migration functions to the current database and recovers the
|
// applies migration functions to the current database and recovers the
|
||||||
// previous state of db if at least one error/panic appeared during migration.
|
// previous state of db if at least one error/panic appeared during migration.
|
||||||
|
@ -469,3 +469,67 @@ func TestRestoreChannelShells(t *testing.T) {
|
|||||||
t.Fatalf("only a single edge should be inserted: %v", err)
|
t.Fatalf("only a single edge should be inserted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestAbandonChannel tests that the AbandonChannel method is able to properly
|
||||||
|
// remove a channel from the database and add a close channel summary. If
|
||||||
|
// called after a channel has already been removed, the method shouldn't return
|
||||||
|
// an error.
|
||||||
|
func TestAbandonChannel(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cdb, cleanUp, err := makeTestDB()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to make test database: %v", err)
|
||||||
|
}
|
||||||
|
defer cleanUp()
|
||||||
|
|
||||||
|
// If we attempt to abandon the state of a channel that doesn't exist
|
||||||
|
// in the open or closed channel bucket, then we should receive an
|
||||||
|
// error.
|
||||||
|
err = cdb.AbandonChannel(&wire.OutPoint{}, 0)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("removing non-existent channel should have failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll now create a new channel to abandon shortly.
|
||||||
|
chanState, err := createTestChannelState(cdb)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create channel state: %v", err)
|
||||||
|
}
|
||||||
|
addr := &net.TCPAddr{
|
||||||
|
IP: net.ParseIP("127.0.0.1"),
|
||||||
|
Port: 18555,
|
||||||
|
}
|
||||||
|
err = chanState.SyncPending(addr, 10)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to sync pending channel: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should now be able to abandon the channel without any errors.
|
||||||
|
closeHeight := uint32(11)
|
||||||
|
err = cdb.AbandonChannel(&chanState.FundingOutpoint, closeHeight)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to abandon channel: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, the channel should no longer be found in the set of
|
||||||
|
// open channels.
|
||||||
|
_, err = cdb.FetchChannel(chanState.FundingOutpoint)
|
||||||
|
if err != ErrChannelNotFound {
|
||||||
|
t.Fatalf("channel should not have been found: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// However we should be able to retrieve a close channel summary for
|
||||||
|
// the channel.
|
||||||
|
_, err = cdb.FetchClosedChannel(&chanState.FundingOutpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to fetch closed channel: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, if we attempt to abandon the channel again, we should get a
|
||||||
|
// nil error as the channel has already been abandoned.
|
||||||
|
err = cdb.AbandonChannel(&chanState.FundingOutpoint, closeHeight)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to abandon channel: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user