Skip to content

A GO implementation for a BIP0352 Silent Payments Indexing Server

License

Notifications You must be signed in to change notification settings

setavenger/blindbit-oracle

Repository files navigation

BlindBit Oracle

A GO implementation for a BIP0352 Silent Payments Indexing Server. This backend was focused on serving the BlindBit light client suite with tweak data and other simplified data to spend and receive. The produced index matches other implementations.

Setup

The installation process is still very manual. Will be improved based on feedback and new findings. It is advised to look at the example blindbit.toml. As new config options appear they will be listed and explained there.

Breaking changes

  • Endpoints were expanded and have a slightly different syntax now see endpoints

Requirements

  • RPC access to a bitcoin full node
    • unpruned because we need the prevouts for every transaction in the block with a taproot output
    • Note: Indexing will take longer if the rpc calls take longer; You might also want to allow more rpc workers on your node to speed things up.
  • Processing a block takes ~100ms-300ms
  • Disk space (~10Gb)
  • go 1.21 installed

Build

  1. Clone this repo
  2. Navigate into the repo and build go build -o <path/to/new/binary/file> ./src

Run

Create a config file blindbit.toml in your data directory to run. An example blindbit.toml is provided here. The settings in regard to parallelization have to be made in accordance to the cores on the Full node and host machine.

Once the data directory is set up you can run it as following.

$ <path/to/new/binary/file> --datadir <path/to/datadir/with/blindbit.toml>

Note that the program will automatically default --datadir to ~/.blindbit-oracle if not set. You still have to set up a config file in any case as the rpc users can't and should not be defaulted.

You can now also decide which index you want to run. This setting can be set in the config file (blindbit.toml).

Todos

  • Add flags to control setup
    • reindex
    • headers only
    • tweaks only
    • move most env controls to config file or cli flags/args
  • Include gobip352 module
  • Refactor a bunch of stuff to use byte arrays or slices instead of strings for internal uses
    • Could potentially reduce the serialisation overhead
    • In combination with proto buffs we might not even have to convert for serving the API
  • Introduce Proto buffs
  • Clean up code (bytes.Equal, parity on big.int with .Bit(), etc.)
  • Update to new test vectors
  • Write operation tests to ensure data integrity
  • Periodically recompute filters
    • One could implement a periodic re-computation every 144 blocks of filters with the current UTXO set
  • Document EVERYTHING: especially serialization patterns to easily look them up later.
    • Serialisation
    • tweak computation methods
  • Include redundancy for when RPC calls are failing (probably due to networking issues in a testing home environment).
  • Review all duplicate key error exemptions and raise to error/warn from debug.
  • Remove unnecessary panics.
  • Convert hardcoded serialisation assertions into constants (?)
  • Use x-only 32 byte public keys instead of scriptPubKey
  • Don't create all DBs by default, only those which are needed and activated
  • Check import paths (SilentPaymentBackend/.../...)

Low Priority

  • Index the next couple blocks in mempool
    • Every 1-3 minute or so?

Endpoints

GET("/info")  // returns basic information about the oracle instance
GET("/block-height")  // returns the height of the indexing server
GET("/block-hash/:blockheight")  // returns the block-hash for a certain block-height
GET("/tweaks/:blockheight?dustLimit=<sat_amount>")  // returns tweak data (cut-through); optional parameter dustLimit can be omitted; filtering happens per request, so virtually any amount can be specified
GET("/tweak-index/:blockheight?dustLimit=<sat_amount>")  // returns the full tweak index (no cut-through); optional parameter dustLimit can be omitted; filtering happens per request, so virtually any amount can be specified
GET("/spent-index/:blockheight")  // returns the spent outpoints index (see https://github.com/setavenger/BIP0352-light-client-specification?tab=readme-ov-file#spent-utxos)
GET("/filter/spent/:blockheight") // returns a filter for shortened spent outpoint hashes (see https://github.com/setavenger/BIP0352-light-client-specification?tab=readme-ov-file#filters)
GET("/filter/new-utxos/:blockheight") // returns a custom taproot only filter of x-only pubkey which received funds
GET("/utxos/:blockheight")  // UTXO data for that block (cut down to the essentials needed to spend)

Feature Modes

The server supports different storage strategies configured via blindbit.toml.

Storage Flags

These flags control how tweaks are stored:

Flag /tweak-index /tweaks Storage
tweaks_full_basic=1 works (no dust) empty ~1.7GB
tweaks_full_with_dust_filter=1 works (with dust) empty ~1.7GB + dust data
tweaks_cut_through_with_dust_filter=1 empty works (with dust) ~2.8GB (prunable)

At least one storage flag must be enabled, otherwise tweaks are computed but discarded (the server will log a warning).

The tweaks_only Flag

The tweaks_only flag controls whether to skip UTXO processing (filters, spent index, etc.), NOT whether to store tweaks.

Config Behavior
tweaks_only=0 Full processing: tweaks + UTXOs + filters
tweaks_only=1 Skip UTXO processing, only handle tweaks

Important: tweaks_only=1 must be combined with a storage flag (tweaks_full_basic or tweaks_full_with_dust_filter) to be useful. On its own, tweaks are computed and discarded.

Note: tweaks_only=1 cannot be combined with tweaks_cut_through_with_dust_filter=1 (cut-through requires UTXO tracking to prune spent outputs).

Example Configurations

# Full server with block-level index (default)
tweaks_only = 0
tweaks_full_basic = 1

# Tweak-only server (no UTXO tracking, saves storage/processing)
tweaks_only = 1
tweaks_full_basic = 1

# Full server with dust filtering on block index
tweaks_only = 0
tweaks_full_with_dust_filter = 1

# Full server with cut-through (requires UTXO tracking)
tweaks_only = 0
tweaks_cut_through_with_dust_filter = 1

Client Discovery

Clients should call /info to discover which features are enabled and use the appropriate endpoint:

{
  "network": "signet",
  "height": 834761,
  "tweaks_only": false,
  "tweaks_full_basic": true,
  "tweaks_full_with_dust_filter": false,
  "tweaks_cut_through_with_dust_filter": false
}
  • If tweaks_full_basic or tweaks_full_with_dust_filter: use /tweak-index
  • If tweaks_cut_through_with_dust_filter: use /tweaks

DiskUsage

This is roughly the space needed. Some changes were made to the indexing server but overall it should still be in this range.

  709632 -> 834761
  217M	./filters
  2.7G	./utxos
  16M	./headers-inv
  12M	./headers
  2.8G	./tweaks        33,679,543 tweaks
  1.7G	./tweak-index   54,737,510 tweaks
  7.4G	.

About

A GO implementation for a BIP0352 Silent Payments Indexing Server

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 5