@@ -186,6 +186,69 @@ func (s *PostgresStore) ExecuteMigrations(target MigrationTarget) error {
186186 )
187187}
188188
189+ // metadataNetworkKey is the key used to store the network name in the metadata
190+ // table.
191+ const metadataNetworkKey = "network"
192+
193+ // ValidateNetwork checks that the network stored in the metadata table matches
194+ // the provided network name. On the first call the network is persisted so
195+ // that subsequent restarts can detect an accidental network switch.
196+ //
197+ // This prevents silent data corruption when a user points the same postgres
198+ // DSN at a different Bitcoin network.
199+ //
200+ // NOTE: This is part of the sqldb.DB interface.
201+ func (s * PostgresStore ) ValidateNetwork (ctx context.Context ,
202+ network string ) error {
203+
204+ return s .BaseDB .ValidateNetwork (ctx , network )
205+ }
206+
207+ // ValidateNetwork checks that the network stored in the metadata table matches
208+ // the provided network name. On the first call the network is persisted so
209+ // that subsequent restarts can detect an accidental network switch.
210+ func (b * BaseDB ) ValidateNetwork (ctx context.Context , network string ) error {
211+ executor := NewTransactionExecutor (
212+ b , func (tx * sql.Tx ) * sqlc.Queries {
213+ return b .WithTx (tx )
214+ },
215+ )
216+
217+ return executor .ExecTx (ctx , WriteTxOpt (), func (tx * sqlc.Queries ) error {
218+ // Insert the network only if the key doesn't exist yet.
219+ // ON CONFLICT DO NOTHING means this is a no-op on every
220+ // startup after the first.
221+ err := tx .SetMetaValue (ctx , sqlc.SetMetaValueParams {
222+ Key : metadataNetworkKey ,
223+ Value : network ,
224+ })
225+ if err != nil {
226+ return fmt .Errorf ("unable to set network in " +
227+ "metadata: %w" , err )
228+ }
229+
230+ // Read back whatever is stored. This is either the value we
231+ // just inserted (first startup) or a value from a previous run.
232+ storedNetwork , err := tx .GetMetaValue (ctx , metadataNetworkKey )
233+ if err != nil {
234+ return fmt .Errorf ("unable to read network from " +
235+ "metadata: %w" , err )
236+ }
237+
238+ if storedNetwork != network {
239+ return fmt .Errorf ("database network mismatch: the " +
240+ "database was previously used with network " +
241+ "'%s', but lnd is now configured for network " +
242+ "'%s'. To fix this, either point lnd at a " +
243+ "different database or reconfigure lnd to use " +
244+ "network '%s'" ,
245+ storedNetwork , network , storedNetwork )
246+ }
247+
248+ return nil
249+ }, func () {})
250+ }
251+
189252// GetSchemaVersion returns the current schema version of the Postgres database.
190253func (s * PostgresStore ) GetSchemaVersion () (int , bool , error ) {
191254 driver , err := pgx_migrate .WithInstance (s .DB , & pgx_migrate.Config {})
0 commit comments