Skip to content

sea-orm integration + rust-lightning persitence layer#95

Open
dcorral wants to merge 1 commit intoRGB-Tools:masterfrom
dcorral:rust-lightning-tx-persistence
Open

sea-orm integration + rust-lightning persitence layer#95
dcorral wants to merge 1 commit intoRGB-Tools:masterfrom
dcorral:rust-lightning-tx-persistence

Conversation

@dcorral
Copy link
Copy Markdown

@dcorral dcorral commented Feb 17, 2026

Summary

Replaces file-based persistence with SQLite database using sea-orm ORM.

Changes

New database tables:

  • mnemonic - encrypted mnemonic storage
  • kv_store - LDK persistence (channel manager, payments, swaps, network graph, scorer)
  • config - configuration key/value pairs (indexer_url, proxy_url, etc.)
  • revoked_token - revoked auth token IDs
  • channel_peer - channel peer pubkey/address mapping

Migrated to database:

  • Mnemonic (was encrypted file)
  • All LDK KVStore data (channel manager, inbound/outbound payments, swaps, scorer)
  • Config parameters (synced to files for rust-lightning compatibility)
  • Revoked tokens (was flat file)
  • Channel peer data (was flat file)
  • PSBTs (temporary storage during channel funding)
  • Output spender transactions

Architecture:

  • Single shared DatabaseConnection via Arc
  • SeaOrmKvStore implements rust-lightning's KVStoreSync trait
  • Migrations run automatically on startup
  • Config stored in DB as source of truth, synced to files for rust-lightning compatibility

rust-lightning submodule (961313cb061470):

  • RGB data persistence moved from filesystem to KVStoreSync trait across 8 files
  • rgb_utils/mod.rs: replaced file I/O (read_rgb_transfer_info, write_rgb_transfer_info, parse_rgb_payment_info, get_rgb_channel_info_path) with KVStore namespace-based read/write operations using RGB_PRIMARY_NS + secondary namespaces (channel_info, payment_info_inbound, payment_info_outbound, transfer_info, etc.)
  • ChannelContext, ChannelManager, OutboundPayments, KeysManager: added rgb_kv_store: Arc<dyn KVStoreSync + Send + Sync> field, threaded through constructors and deserialization
  • color_commitment, color_htlc, color_closing: now take &dyn KVStoreSync instead of reading files directly
  • is_channel_rgb, get_rgb_channel_info, rename_rgb_files, filter_first_hops, is_payment_rgb: switched from path-based lookups to KVStore reads
  • Removed filesystem fallback — KVStore is now the sole persistence backend for RGB data

IMPORTANT!
This PR depends on RGB-Tools/rust-lightning#17 and .submodule must be updated to point to the right RGB-Tools fork before merging

@dcorral dcorral force-pushed the rust-lightning-tx-persistence branch 3 times, most recently from 60ab584 to 8aceb21 Compare February 17, 2026 11:38
@zoedberg
Copy link
Copy Markdown
Member

@dcorral could you please rebase this PR?

@dcorral dcorral force-pushed the rust-lightning-tx-persistence branch from 8aceb21 to f71fb32 Compare March 24, 2026 12:35
@dcorral
Copy link
Copy Markdown
Author

dcorral commented Mar 24, 2026

@zoedberg done!

@dcorral dcorral force-pushed the rust-lightning-tx-persistence branch 10 times, most recently from f5f35f3 to 84b0895 Compare March 30, 2026 16:34
@dcorral dcorral force-pushed the rust-lightning-tx-persistence branch from 84b0895 to b67a1ff Compare March 30, 2026 20:44
Copy link
Copy Markdown
Member

@zoedberg zoedberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! In addition to the requested changes please

  • commit the src/database/entities/prelude.rs file that gets generated by sea-orm-cli
  • add the migration cargo lock file to the .gitignore file and remove the file
  • do not make changes to src/database/entities/mod.rs since its autogenerated by sea-orm-cli
  • I know you took inspiration from rgb-lib when creating aliases like ChannelPeerActMod, but I saw this is not the best/recommended approach so please drop the aliases (see rgb-multisig-hub to see what is the best way to use the DB utility objects)
  • as requested in the rust-lightning PR, please keep only essential comments

P.S this is not a final review, will do another one after these requests have been addressed

Comment thread src/utils.rs
Comment on lines +361 to +366
// Use single connection to avoid deadlocks
opt.max_connections(1)
.min_connections(0)
.connect_timeout(Duration::from_secs(8))
.idle_timeout(Duration::from_secs(8))
.max_lifetime(Duration::from_secs(8));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Use single connection to avoid deadlocks
opt.max_connections(1)
.min_connections(0)
.connect_timeout(Duration::from_secs(8))
.idle_timeout(Duration::from_secs(8))
.max_lifetime(Duration::from_secs(8));
opt.max_connections(8)
.min_connections(1)
.connect_timeout(Duration::from_secs(8))
.idle_timeout(Duration::from_mins(5))
.max_lifetime(Duration::from_hours(1));

Comment thread src/runtime.rs
.expect("Failed to create database tokio runtime")
});

pub(crate) fn block_on<F>(future: F) -> F::Output
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use the DB in an async way (see comment in the rust-lightning PR) and drop this entire file

Comment thread src/utils.rs

// Initialize the shared database connection
let db_path = get_db_path(&args.storage_dir_path);
let connection_string = format!("sqlite:{}?mode=rwc", db_path.display());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's safe to use db_path.display(), please see how we do this in rgb-lib (adjust_canonicalization)

.integer()
.not_null()
.primary_key()
.default(1),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should set defaults for the indexes

.table(Mnemonic::Table)
.if_not_exists()
.col(
ColumnDef::new(Mnemonic::Id)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's call the indexes Idx, since that's how we did on all our other projects

manager
.create_table(
Table::create()
.table(Mnemonic::Table)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we save the mnemonic in the Config table?

.not_null()
.primary_key(),
)
.col(ColumnDef::new(Config::Value).string().not_null())
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of saving values as strings in multiple rows I think it's better to have a single row DB table with one column per value using the appropriate type for each column (see how we did this in rgb-multisig-hub)

Comment thread src/ldk.rs
Comment on lines +127 to +128
/// Save config to database (source of truth) and sync to file for rust-lightning compatibility.
fn save_config_and_sync_file(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need backwards compatibility so please drop all the files (mnemonic, bitcoin network etc)

Comment thread src/database/mod.rs
Comment on lines +54 to +63
let result = block_on(
ChannelPeerEntity::find()
.filter(ChannelPeerColumn::Pubkey.eq(pubkey))
.one(self.get_connection()),
)?;

if let Some(peer) = result {
block_on(peer.delete(self.get_connection()))?;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here you can just do delete_many().filter(...) instead of reading and then deleting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants