Bring Your Own Data
easy
Out Of Date: This content needs to be reworked

This section sets up the docker container insert-gossip which is able to read gossip messages in bytes format from a specified file. Such a file is e. g. the gossip_store file that gets created by a Core Lightning node automatically.

In case you want to get a deeper understanding about this file, feel free to check out the official documentation as well as the source code of the insert-gossip service.

Setup

We will start by setting up the directory structure and continue with the docker container

Create directory

From the project root we create the insert-gossip directory with the following command.

ln-history@host:~/ln-historymkdir insert-gossip && cd insert-gossip

Environment variablesauthentication

Update the .env file and add credentials of your RPC User to access your Bitcoin Core node. The easiest way would be to just copy your gossip_store file from your Core Lightning node into the ln-history directory.

FILE_PATH=gossip_store                                                  # File path to gossip_messages
BITCOIN_RPCUSER=YOUR-BITCOIN-RPC-USER
BITCOIN_RPCPASSWORD=YOUR-BITCOIN-RPCPASSWORD

🔐 Important: Never commit .env files containing credentials to version control.

🐳 Docker container

Add this service to your docker-compose.yml.

services:
  insert-gossip:
    image: ghcr.io/ln-history/ln-history:latest
    container_name: insert-gossip
    restart: never ?
    environment:
      FILE_PATH: $FILE_PATH
      BITCOIN_RPCUSER: $BITCOIN_RPCUSER
      BITCOIN_RPCPASSWORD: $BITCOIN_RPCPASSWORD
      LN_HISTORY_DATABASE_CONNECTION_STRING: $POSTGRES_URI
    env_file: .env
    volumes: file_path?

Folder structure

Ultimatly the folder structure should look like this:

ln-history/
├── .env                    # .env file with credentials
├── docker-compose.yml      # Docker Compose with insert-gossip and core services
└── gossip_store            # The file that contains the gossip messages in raw bytes

Please make sure that the permissions are correctly set, such that the insert-gossip service has the permissions to read the file at FILE_PATH. info

Noticewarning

Please note that for every channel_announcement a lookup into the Bitcoin blockchain is necessary. This might take a while depending on your hardware.

Run

We start the service.

ln-history@host:~/ln-history/databasedocker compose up -d

This will start the insert-gossip to go through your inserted file.

Monitoring

You can monitor the progess of the insertion by executing the following command.

ln-history@host:~/ln-history/insert-gossipdocker compose logs -f --tail=100

You can always access the logs by pressing CTRL + C.

Phase 1: Splitting

The insert-gossip service will first iterate through the whole file and log statistics about the parsable gossip messages found. During that run it is sorting the gossip messages into three seperate files node_announcements.bin, channel_announcements.bin, channel_updates.bin. You can see the statistics in the logs:

ln-history@host:~/ln-history/insert-gossipdocker compose logs -f --tail=100
The `insert-gossip` service started. Press CTRL+C or `docker compose down` to stop it. Starting phase 1 Iterating through the file: `gossip_store`. File has a size of `234123` bytes Creating node_announcements.bin ... Creating channel_announcements.bin ... Creating channel_updates.bin ... Splitting the file `gossip_store` into the following three files: - node_announcements.bin - channel_announcements.bin - channel_updates.bin Finished iterating through `gossip_store` file Distribution of messages: - node_announcements: 2314 - channel_announcement: 1832 - channel_updates: 43187 - unable to parse: 0 Sucessfully finished phase 1

Phase 2: DuckDB Setup

The insert-gossip service will setup a DuckDB - an in-memory database - that temporarly stores the gossip messages in the file temp-db.duckdb. The DuckDB has the same schema as the ln-history-database.

After that it will go through the phases 2a -> 2b -> 2c.

ln-history@host:~/ln-historydocker compose logs -f --tail=100
Starting phase 2 Creating DuckDB database `temp-db.duckdb` Sucessfully created DuckDB database `temp-db.duckdb`

Phase 2a: node_anouncements

The service interates through the nodes_announcements.bin. For every node_announcement it checks if the node_id has been seen before. If not it inserts the node_id into the nodes table of the DuckDB. In any case it adds the gossip message into the nodes_raw_gossip table.

ln-history@host:~/ln-historydocker compose logs -f --tail=100
Starting phase 2a Iterating through `nodes_announcements.bin` file File has a size of `234123` bytes Adding data to DuckDB database `temp-db.duckdb` Results of node_announcement insertion: - nodes added: 851 - nodes_raw_gossip added: 2314 - duplicates found: 0 - errors during parsing: 0 Sucessfully finished phase 2a

Phase 2b: channel_announcements

The service interates through the channel_announcements.bin. For every channel_announcement it needs to request the Bitcoin Core to get the amount_sat and timestamp (timestamp of the Bitcoin block when it was mined) of that channel. It also checks if the node_ids of the participating nodes namely node_id_1 and node_id_2 exist in the nodes table. In case they don't, the missing node_id gets inserted with the from_timestamp (and last_seen) being initially the timestamp of the block. For every channel_announcement a new row gets created in the channels table.

ln-history@host:~/ln-historydocker compose logs -f --tail=100
Starting phase 2b Iterating through `channel_announcements.bin` file File has a size of `3212351` bytes Adding data to DuckDB database `temp-db.duckdb` Results of channel_announcement insertion: - complete channels added: 851 - incomplete (missing node_id) channels added: 23 - duplicates found: 0 - errors during parsing: 0 - errors during requesting BLOCKCHAIN_RPC service: 0 Sucessfully finished phase 2b

Phase 2c: channel_updates

The service iterates through the channel_updates.bin. For every channel_update it checks if the channel has been announced before. If not it creates a new entry in the channels table. Every channel_update gets inserted into the channel_updates table.

ln-history@host:~/ln-historydocker compose logs -f --tail=100
Starting phase 2c Iterating through `channel_updates.bin` file File has a size of `832713` bytes Adding data to DuckDB database `temp-db.duckdb` Results of channel_update insertion: - channel_updates (of existing channels) added: 41231 - channel_updates (of not existing channels) added: 326 - duplicates found: 0 - errors during parsing: 0 Sucessfully finished phase 2c Sucessfully finished phase 2

Phase 3: Export data

After the duckdb tables in the temp-db.duckdb have been filled completly, the insert-gossip services exports each table as a parquet file (?). As the last step of the insertion, the service imports the created parquet (?) files into the postgresql database.

ln-history@host:~/ln-historydocker compose logs -f --tail=100
Starting phase 3 Exporting tables to parqut files - nodes table: nodes.parquet - nodes_raw_gossip: nodes_raw_gossip.parquet - channel_announcements: channel_announcements.parquet - channel_updates: channel_updates.parquet Finished exporting nodes table to nodes.parquet ... Finished exporting nodes_raw_gossip table to nodes_raw_gossip.parquet ... Finished exporting channel_announcements table to channel_announcements.parquet ... Finished exporting channel_updates table to channel_updates.parquet Sucessfully finished phase 3

Phase 4: Import data

ln-history@host:~/ln-history/insert-gossipdocker compose logs -f --tail=100
Starting phase 4 Import parquet files into postgresql _ln-history-database_ - nodes table: nodes.parquet - nodes_raw_gossip: nodes_raw_gossip.parquet - channel_announcements: channel_announcements.parquet - channel_updates: channel_updates.parquet Finished importing nodes.parquet into nodes table ... Finished importing nodes_raw_gossip.parquet into nodes_raw_gossip table ... Finished importing channel_announcements.parquet into channel_announcements table ... Finished importing channel_updates.parquet into channel_updates table Sucessfully finished phase 4

Finish

The insert-gossip service is concepted to run once over a given file and does not persist information about which files have already been read. To help the user keep track of the files it appends a .done to the file that was imported into ln-history-database.

It has finished when you see this in your logs:

ln-history@host:~/ln-history/insert-gossipdocker compose logs -f --tail=100
Renaming the initial file `gossip_store` to `gossip_store.done` to indicate that the data has been inserted. Removing parquet temp files: - nodes.parquet - nodes_raw_gossip.parquet - channel_announcements.parquet - channel_updates.parquet Removing temp-db.duckdb Sucessfully cleaned up resources.

More information

Feel free to read the detailed README.md file in the repository.