Merge pull request #6563 from yyforyongyu/export-chanstatus

multi: export channel status field in migration25
This commit is contained in:
Olaoluwa Osuntokun
2022-05-23 11:26:53 -07:00
committed by GitHub
5 changed files with 99 additions and 50 deletions

View File

@ -277,9 +277,13 @@ type OpenChannel struct {
// ChanType denotes which type of channel this is. // ChanType denotes which type of channel this is.
ChanType ChannelType ChanType ChannelType
// chanStatus is the current status of this channel. If it is not in // ChanStatus is the current status of this channel. If it is not in
// the state Default, it should not be used for forwarding payments. // the state Default, it should not be used for forwarding payments.
chanStatus ChannelStatus //
// NOTE: In `channeldb.OpenChannel`, this field is private. We choose
// to export this private field such that following migrations can
// access this field directly.
ChanStatus ChannelStatus
// InitialLocalBalance is the balance we have during the channel // InitialLocalBalance is the balance we have during the channel
// opening. When we are not the initiator, this value represents the // opening. When we are not the initiator, this value represents the
@ -320,10 +324,10 @@ func (c *OpenChannel) hasChanStatus(status ChannelStatus) bool {
// Special case ChanStatusDefualt since it isn't actually flag, but a // Special case ChanStatusDefualt since it isn't actually flag, but a
// particular combination (or lack-there-of) of flags. // particular combination (or lack-there-of) of flags.
if status == ChanStatusDefault { if status == ChanStatusDefault {
return c.chanStatus == ChanStatusDefault return c.ChanStatus == ChanStatusDefault
} }
return c.chanStatus&status == status return c.ChanStatus&status == status
} }
// FundingTxPresent returns true if expect the funding transcation to be found // FundingTxPresent returns true if expect the funding transcation to be found
@ -361,7 +365,7 @@ func fetchChanInfo(chanBucket kvdb.RBucket, c *OpenChannel, legacy bool) error {
} }
c.ChanType = ChannelType(chanType) c.ChanType = ChannelType(chanType)
c.chanStatus = ChannelStatus(chanStatus) c.ChanStatus = ChannelStatus(chanStatus)
// If this is not the legacy format, we need to read the extra two new // If this is not the legacy format, we need to read the extra two new
// fields. // fields.
@ -432,7 +436,7 @@ func putChanInfo(chanBucket kvdb.RwBucket, c *OpenChannel, legacy bool) error {
if err := mig.WriteElements(&w, if err := mig.WriteElements(&w,
mig.ChannelType(c.ChanType), c.ChainHash, c.FundingOutpoint, mig.ChannelType(c.ChanType), c.ChainHash, c.FundingOutpoint,
c.ShortChannelID, c.IsPending, c.IsInitiator, c.ShortChannelID, c.IsPending, c.IsInitiator,
mig.ChannelStatus(c.chanStatus), c.FundingBroadcastHeight, mig.ChannelStatus(c.ChanStatus), c.FundingBroadcastHeight,
c.NumConfsRequired, c.ChannelFlags, c.NumConfsRequired, c.ChannelFlags,
c.IdentityPub, c.Capacity, c.TotalMSatSent, c.IdentityPub, c.Capacity, c.TotalMSatSent,
c.TotalMSatReceived, c.TotalMSatReceived,

View File

@ -70,10 +70,6 @@ var (
// NOTE: doesn't have the Packager field as it's not used in current migration. // NOTE: doesn't have the Packager field as it's not used in current migration.
type OpenChannel struct { type OpenChannel struct {
mig25.OpenChannel mig25.OpenChannel
// chanStatus is the current status of this channel. If it is not in
// the state Default, it should not be used for forwarding payments.
chanStatus mig25.ChannelStatus
} }
// FetchChanInfo deserializes the channel info based on the legacy boolean. // FetchChanInfo deserializes the channel info based on the legacy boolean.
@ -104,7 +100,7 @@ func FetchChanInfo(chanBucket kvdb.RBucket, c *OpenChannel, legacy bool) error {
} }
c.ChanType = mig25.ChannelType(chanType) c.ChanType = mig25.ChannelType(chanType)
c.chanStatus = mig25.ChannelStatus(chanStatus) c.ChanStatus = mig25.ChannelStatus(chanStatus)
// If this is the legacy format, we need to read the extra two new // If this is the legacy format, we need to read the extra two new
// fields. // fields.
@ -239,7 +235,7 @@ func PutChanInfo(chanBucket kvdb.RwBucket, c *OpenChannel, legacy bool) error {
if err := mig.WriteElements(&w, if err := mig.WriteElements(&w,
mig.ChannelType(c.ChanType), c.ChainHash, c.FundingOutpoint, mig.ChannelType(c.ChanType), c.ChainHash, c.FundingOutpoint,
c.ShortChannelID, c.IsPending, c.IsInitiator, c.ShortChannelID, c.IsPending, c.IsInitiator,
mig.ChannelStatus(c.chanStatus), c.FundingBroadcastHeight, mig.ChannelStatus(c.ChanStatus), c.FundingBroadcastHeight,
c.NumConfsRequired, c.ChannelFlags, c.NumConfsRequired, c.ChannelFlags,
c.IdentityPub, c.Capacity, c.TotalMSatSent, c.IdentityPub, c.Capacity, c.TotalMSatSent,
c.TotalMSatReceived, c.TotalMSatReceived,

View File

@ -59,10 +59,6 @@ var (
// NOTE: doesn't have the Packager field as it's not used in current migration. // NOTE: doesn't have the Packager field as it's not used in current migration.
type OpenChannel struct { type OpenChannel struct {
mig26.OpenChannel mig26.OpenChannel
// chanStatus is the current status of this channel. If it is not in
// the state Default, it should not be used for forwarding payments.
chanStatus mig25.ChannelStatus
} }
// FetchChanInfo deserializes the channel info based on the legacy boolean. // FetchChanInfo deserializes the channel info based on the legacy boolean.
@ -90,7 +86,7 @@ func FetchChanInfo(chanBucket kvdb.RBucket, c *OpenChannel, legacy bool) error {
} }
c.ChanType = mig25.ChannelType(chanType) c.ChanType = mig25.ChannelType(chanType)
c.chanStatus = mig25.ChannelStatus(chanStatus) c.ChanStatus = mig25.ChannelStatus(chanStatus)
// For single funder channels that we initiated and have the funding // For single funder channels that we initiated and have the funding
// transaction to, read the funding txn. // transaction to, read the funding txn.
@ -182,7 +178,7 @@ func PutChanInfo(chanBucket kvdb.RwBucket, c *OpenChannel, legacy bool) error {
if err := mig.WriteElements(&w, if err := mig.WriteElements(&w,
mig.ChannelType(c.ChanType), c.ChainHash, c.FundingOutpoint, mig.ChannelType(c.ChanType), c.ChainHash, c.FundingOutpoint,
c.ShortChannelID, c.IsPending, c.IsInitiator, c.ShortChannelID, c.IsPending, c.IsInitiator,
mig.ChannelStatus(c.chanStatus), c.FundingBroadcastHeight, mig.ChannelStatus(c.ChanStatus), c.FundingBroadcastHeight,
c.NumConfsRequired, c.ChannelFlags, c.NumConfsRequired, c.ChannelFlags,
c.IdentityPub, c.Capacity, c.TotalMSatSent, c.IdentityPub, c.Capacity, c.TotalMSatSent,
c.TotalMSatReceived, c.TotalMSatReceived,

View File

@ -54,42 +54,80 @@ var (
}, },
} }
// testChannel is used to test the balance fields are correctly set. // testChanStatus specifies the following channel status,
testChannel = &OpenChannel{ // ChanStatusLocalDataLoss|ChanStatusRestored|ChanStatusRemoteCloseInitiator
OpenChannel: mig26.OpenChannel{ testChanStatus = mig25.ChannelStatus(0x4c)
OpenChannel: mig25.OpenChannel{
OpenChannel: mig.OpenChannel{
IdentityPub: dummyPubKey,
FundingOutpoint: dummyOp,
FundingTxn: commitTx1,
IsInitiator: true,
},
},
},
}
) )
// TestMigrateHistoricalBalances checks that the initial balances fields are // TestMigrateHistoricalBalances checks that the initial balances fields are
// patched to the historical channel info. // patched to the historical channel info.
func TestMigrateHistoricalBalances(t *testing.T) { func TestMigrateHistoricalBalances(t *testing.T) {
// Test that when the historical channel doesn't have the two new testCases := []struct {
// fields. name string
migtest.ApplyMigration( isAfterMigration25 bool
t, isRestored bool
genBeforeMigration(testChannel, false), }{
genAfterMigration(testChannel), {
MigrateHistoricalBalances, // Test that when the restored historical channel
false, // doesn't have the two new fields.
) name: "restored before migration25",
isAfterMigration25: false,
isRestored: true,
},
{
// Test that when the restored historical channel have
// the two new fields.
name: "restored after migration25",
isAfterMigration25: true,
isRestored: true,
},
{
// Test that when the historical channel with a default
// channel status flag doesn't have the two new fields.
name: "default before migration25",
isAfterMigration25: false,
isRestored: false,
},
{
// Test that when the historical channel with a default
// channel status flag have the two new fields.
name: "default after migration25",
isAfterMigration25: true,
isRestored: false,
},
}
// Test that when the historical channel have the two new fields. for _, tc := range testCases {
migtest.ApplyMigration( tc := tc
t,
genBeforeMigration(testChannel, true), // testChannel is used to test the balance fields are correctly
genAfterMigration(testChannel), // set.
MigrateHistoricalBalances, testChannel := &OpenChannel{}
false, testChannel.IdentityPub = dummyPubKey
testChannel.FundingOutpoint = dummyOp
testChannel.FundingTxn = commitTx1
testChannel.IsInitiator = true
// Set the channel status flag is we are testing the restored
// case.
if tc.isRestored {
testChannel.ChanStatus = testChanStatus
}
// Create before and after migration functions.
beforeFn := genBeforeMigration(
testChannel, tc.isAfterMigration25,
) )
afterFn := genAfterMigration(testChannel, tc.isRestored)
// Run the test.
t.Run(tc.name, func(t *testing.T) {
migtest.ApplyMigration(
t, beforeFn, afterFn,
MigrateHistoricalBalances, false,
)
})
}
} }
func genBeforeMigration(c *OpenChannel, regression bool) func(kvdb.RwTx) error { func genBeforeMigration(c *OpenChannel, regression bool) func(kvdb.RwTx) error {
@ -116,7 +154,7 @@ func genBeforeMigration(c *OpenChannel, regression bool) func(kvdb.RwTx) error {
} }
} }
func genAfterMigration(c *OpenChannel) func(kvdb.RwTx) error { func genAfterMigration(c *OpenChannel, restored bool) func(kvdb.RwTx) error {
return func(tx kvdb.RwTx) error { return func(tx kvdb.RwTx) error {
chanBucket, err := fetchHistoricalChanBucket(tx, c) chanBucket, err := fetchHistoricalChanBucket(tx, c)
if err != nil { if err != nil {
@ -159,6 +197,16 @@ func genAfterMigration(c *OpenChannel) func(kvdb.RwTx) error {
if !newChan.IsInitiator { if !newChan.IsInitiator {
return fmt.Errorf("wrong IsInitiator") return fmt.Errorf("wrong IsInitiator")
} }
// If it's restored, there should be no funding tx.
if restored {
if newChan.FundingTxn != nil {
return fmt.Errorf("expect nil FundingTxn")
}
return nil
}
// Otherwise check the funding tx is read as expected.
if newChan.FundingTxn.TxHash() != commitTx1.TxHash() { if newChan.FundingTxn.TxHash() != commitTx1.TxHash() {
return fmt.Errorf("wrong FundingTxn") return fmt.Errorf("wrong FundingTxn")
} }
@ -167,7 +215,9 @@ func genAfterMigration(c *OpenChannel) func(kvdb.RwTx) error {
} }
} }
func createHistoricalBucket(tx kvdb.RwTx, c *OpenChannel) (kvdb.RwBucket, error) { func createHistoricalBucket(tx kvdb.RwTx,
c *OpenChannel) (kvdb.RwBucket, error) {
// First fetch the top level bucket which stores all data related to // First fetch the top level bucket which stores all data related to
// historical channels. // historical channels.
rootBucket, err := tx.CreateTopLevelBucket(historicalChannelBucket) rootBucket, err := tx.CreateTopLevelBucket(historicalChannelBucket)

View File

@ -172,6 +172,9 @@ from occurring that would result in an erroneous force close.](https://github.co
* [Fixed an intermittent panic that would occur due to a violated assumption with our * [Fixed an intermittent panic that would occur due to a violated assumption with our
underlying database.](https://github.com/lightningnetwork/lnd/pull/6547) underlying database.](https://github.com/lightningnetwork/lnd/pull/6547)
* [Fixed a wrong channel status inheritance used in `migration26` and
`migration27`](https://github.com/lightningnetwork/lnd/pull/6563).
## Routing ## Routing
* [Add a new `time_pref` parameter to the QueryRoutes and SendPayment APIs](https://github.com/lightningnetwork/lnd/pull/6024) that * [Add a new `time_pref` parameter to the QueryRoutes and SendPayment APIs](https://github.com/lightningnetwork/lnd/pull/6024) that