diff --git a/channeldb/db.go b/channeldb/db.go index fcb81aa8b..8ae1f2609 100644 --- a/channeldb/db.go +++ b/channeldb/db.go @@ -1111,8 +1111,10 @@ func (d *DB) syncVersions(versions []version) error { } latestVersion := getLatestDBVersion(versions) + minUpgradeVersion := getMinUpgradeVersion(versions) log.Infof("Checking for schema update: latest_version=%v, "+ - "db_version=%v", latestVersion, meta.DbVersionNumber) + "min_upgrade_version=%v, db_version=%v", latestVersion, + minUpgradeVersion, meta.DbVersionNumber) switch { @@ -1125,6 +1127,12 @@ func (d *DB) syncVersions(versions []version) error { latestVersion) return ErrDBReversion + case meta.DbVersionNumber < minUpgradeVersion: + log.Errorf("Refusing to upgrade from db_version=%d to "+ + "latest_version=%d. Upgrade via intermediate major "+ + "release(s).", meta.DbVersionNumber, latestVersion) + return ErrDBVersionTooLow + // If the current database version matches the latest version number, // then we don't need to perform any migrations. case meta.DbVersionNumber == latestVersion: @@ -1168,6 +1176,21 @@ func getLatestDBVersion(versions []version) uint32 { return versions[len(versions)-1].number } +// getMinUpgradeVersion returns the minimum version required to upgrade the +// database. +func getMinUpgradeVersion(versions []version) uint32 { + firstMigrationVersion := versions[0].number + + // If we can upgrade from the base version with this version of lnd, + // return the base version as the minimum required version. + if firstMigrationVersion == 0 { + return 0 + } + + // Otherwise require the version that the first migration upgrades from. + return firstMigrationVersion - 1 +} + // getMigrationsToApply retrieves the migration function that should be // applied to the database. func getMigrationsToApply(versions []version, version uint32) ([]migration, []uint32) { diff --git a/channeldb/error.go b/channeldb/error.go index e0e754522..ea066373a 100644 --- a/channeldb/error.go +++ b/channeldb/error.go @@ -14,6 +14,10 @@ var ( // prior database version. ErrDBReversion = fmt.Errorf("channel db cannot revert to prior version") + // ErrDBVersionTooLow is returned when detecting an attempt to upgrade a + // version for which migration is no longer supported. + ErrDBVersionTooLow = fmt.Errorf("channel db version too old to upgrade") + // ErrLinkNodesNotFound is returned when node info bucket hasn't been // created. ErrLinkNodesNotFound = fmt.Errorf("no link nodes exist")