github.com/decred/dcrlnd@v0.7.6/channeldb/dcrdb.go (about) 1 package channeldb 2 3 import ( 4 dcrmigration01 "github.com/decred/dcrlnd/channeldb/dcrmigrations/migration01" 5 dcrmigration02 "github.com/decred/dcrlnd/channeldb/dcrmigrations/migration02" 6 "github.com/decred/dcrlnd/kvdb" 7 ) 8 9 var ( 10 dcrMetaBucket = []byte("dcrlnd_metadata") 11 ) 12 13 var ( 14 // dcrDbVersions are the decred-only migrations. 15 dcrDbVersions = []version{ 16 {number: 1, migration: dcrmigration01.FixMigration20}, 17 {number: 2, migration: dcrmigration02.RemoveFutureTimestampFromPeers}, 18 } 19 ) 20 21 // latestDcrDbVersion returns the latest version of the decred-specific db 22 // migrations. 23 func latestDcrDbVersion() uint32 { 24 return dcrDbVersions[len(dcrDbVersions)-1].number 25 } 26 27 // applyDecredMigations applies the decred-only migrations. 28 func (d *DB) applyDecredMigations(tx kvdb.RwTx, dbVersion uint32) error { 29 latestVersion := dcrDbVersions[len(dcrDbVersions)-1].number 30 log.Infof("Checking for decred-specicic migrations latest_version=%d, "+ 31 "db_version=%d", latestVersion, dbVersion) 32 33 if latestVersion < dbVersion { 34 log.Errorf("Refusing to revert from decred db_version=%d to "+ 35 "lower version=%d", dbVersion, latestVersion) 36 return ErrDBReversion 37 } 38 39 if latestVersion == dbVersion { 40 // Nothing to do. 41 return nil 42 } 43 44 log.Infof("Performing decred-specific database schema migration") 45 46 metaBucket := tx.ReadWriteBucket(dcrMetaBucket) 47 for _, mig := range dcrDbVersions { 48 if mig.migration == nil { 49 continue 50 } 51 if mig.number <= dbVersion { 52 continue 53 } 54 55 log.Infof("Applying migration #%d", mig.number) 56 57 if err := mig.migration(tx); err != nil { 58 log.Infof("Unable to apply migration #%d", 59 mig.number) 60 return err 61 } 62 63 // Save the new db version. 64 dbVersion = mig.number 65 err := metaBucket.Put(dbVersionKey, byteOrder.AppendUint32(nil, dbVersion)) 66 if err != nil { 67 return err 68 } 69 } 70 71 // Stop if running in dry-run mode. 72 if d.dryRun { 73 return ErrDryRunMigrationOK 74 } 75 76 return nil 77 } 78 79 // syncDcrlndDBVersions performs the dcrlnd-specific db upgrades. 80 func (d *DB) syncDcrlndDBVersions(tx kvdb.RwTx) error { 81 // Read dcr-specific version. 82 var dbVersion uint32 83 bucket := tx.ReadWriteBucket(dcrMetaBucket) 84 if bucket == nil { 85 // Filled meta bucket but empty dcr-specific meta bucket. 86 // Create dcr one. 87 var err error 88 bucket, err = tx.CreateTopLevelBucket(dcrMetaBucket) 89 if err != nil { 90 return err 91 } 92 93 // If the global meta bucket is empty, it's a new db. 94 if tx.ReadBucket(metaBucket) == nil { 95 dbVersion = latestDcrDbVersion() 96 } 97 98 // dbVersion == 0. 99 bucket.Put(dbVersionKey, byteOrder.AppendUint32(nil, dbVersion)) 100 } else { 101 v := bucket.Get(dbVersionKey) 102 if v != nil { 103 dbVersion = byteOrder.Uint32(v) 104 } 105 } 106 107 // Apply dcr-specific migrations. 108 return d.applyDecredMigations(tx, dbVersion) 109 } 110 111 // initDcrlndFeatures initializes features that are specific to dcrlnd. 112 func (d *DB) initDcrlndFeatures() error { 113 return kvdb.Update(d, func(tx kvdb.RwTx) error { 114 if err := d.syncDcrlndDBVersions(tx); err != nil { 115 return err 116 } 117 118 // If the inflight payments index bucket doesn't exist, 119 // initialize it. 120 indexBucket := tx.ReadWriteBucket(paymentsInflightIndexBucket) 121 if indexBucket == nil { 122 return recreatePaymentsInflightIndex(tx) 123 } 124 125 return nil 126 }, func() {}) 127 } 128 129 // LocalOpenChanIDs returns a map of channel IDs of all open channels in the 130 // local DB. 131 func (d *DB) LocalOpenChanIDs() (map[uint64]struct{}, error) { 132 // Note: this is less efficient than it could be, because it iterates 133 // through the entire list of channels and then discards all that just 134 // to extract the channel id. In the future, decode that field directly. 135 openChans, err := d.ChannelStateDB().FetchAllOpenChannels() 136 if err != nil { 137 return nil, err 138 } 139 140 res := make(map[uint64]struct{}, len(openChans)) 141 for _, c := range openChans { 142 res[c.ShortChanID().ToUint64()] = struct{}{} 143 } 144 return res, nil 145 }