SkillAgentSearch skills...

Frigate

Frigate Electrum Server

Install / Use

/learn @sparrowwallet/Frigate
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Frigate logo

Frigate Electrum Server

Frigate is an experimental Electrum Server testing Silent Payments scanning with ephemeral client keys.

It has four goals:

  1. To provide a proof of concept implementation of the Remote Scanner approach discussed in the BIP352 Silent Payments Index Server Specification (WIP).
  2. To propose Electrum RPC protocol methods to request and return Silent Payments information from a server.
  3. To demonstrate an efficient "in database" technique of scanning for Silent Payments transactions.
  4. To demonstrate the use of GPU computation to dramatically decrease scanning time.
  5. (New) To demonstrate that GPU compute can be preferred ahead of CPU compute, greatly reducing the resource impact of scanning while remaining widely deployable.

Motivation

BIP 352 has proposed that light clients use compact block filters to scan for UTXOs received to a Silent Payments address. However, this introduces two significant problems:

The first is one of data gravity. For any reasonable scan period, the client must download gigabytes of data in tweaks, block filters and finally some of the blocks themselves. All this data needs to be downloaded, parsed and potentially saved to avoid downloading it again, requiring significant resources on the client. A client would likely need several gigabytes of data to restore a wallet with historical transactions, which is resource intensive in terms of bandwidth, CPU and storage. Compare this to current Electrum clients which may use just a few megabytes to restore a wallet, and it's easy to see how this approach is unlikely to see widespread adoption - it's just too onerous, particularly for mobile clients.

The second problem is the lack of mempool monitoring, which is not supported with compact block filters. Users rely on mempool monitoring to answer the "did you get my transaction?" question. The lack of ability to do this can cause user confusion and distrust in the wallet, which education can only go some way in reducing.

This project attempts to address these problems using an Electrum protocol styled approach. Instead of asking the client to download the required data and perform the scanning, the server performs the scanning locally with an optimized index. This is the Remote Scanner approach discussed in the BIP352 Silent Payments Index Server Specification (WIP). It should be noted that both the scan private key and the spend public key must be provided to the server in this approach. While this does have a privacy implication, the keys are not stored and only held by the server ephemerally (in RAM) for duration of the client session. This is similar to the widely used public Electrum server approach, where the wallet addresses are shared ephemerally with a public server.

Finally, although this approach will prove to be satisfactory for single user instances, the computation required is still too onerous for a multi-user instance such as an Electrum public server. Payment networks are networks subject to Metcalfe's Law like any other, and Silent Payments is only likely to see widespread real world adoption with free-to-use public servers. For this use case, a further step must be taken to leverage modern GPU computation to dramatically improve performance and allow many simultaneous scanning requests.

Approach

The key problem that BIP 352 introduces with respect to scanning is that much of the computation cannot be done generally ahead of time. Instead, for every silent payment address, each transaction in the blockchain must be considered separately to determine if it sends funds to that address. The computation involves several cryptographic operations, including two resource intensive EC point multiplication operations on every eligible transaction. In order to ensure that client keys are ephemeral and not stored, this computation must be done in a reasonable period of time on millions of transactions.

This is the key difference between Silent Payments wallets and traditional BIP32 wallets, which can rely on a simple monotonically incrementing derivation path index. While Silent Payments provides important advantages in privacy and user experience, this computational burden is the downside that cannot be avoided. Any solution addressing the retrieval of Silent Payments transactions will eventually be bounded by the performance of EC point multiplication. For best performance and user experience this should be done as efficiently as possible, and therefore as close the source data as possible.

In order to achieve this, Frigate addresses the problem of data gravity directly. Like most light client silent payment services, it builds an index of the data that can be pre-computed, generally known as a tweak index. This index contains a large number of elements (one for every silent payments eligible transaction in the blockchain) containing a tweak calculated from the public keys used in the transaction inputs. Frigate stores this data in a single table with the following schema:

| Column | Type | |--------------|--------------| | txid | BLOB | | height | INTEGER | | tweak_key | BLOB | | outputs | LIST(BIGINT) |

The txid and tweak_key values are 32 and 64 byte BLOBS respectively. The outputs value is a list of 8 byte integers, each representing the first 8 bytes of the x-value of the Taproot output public key.

On startup, Frigate connects to the configured Bitcoin Core RPC, downloads blocks from the configured block height (or from Taproot activation on mainnet) and adds entries to the table. Once it has reached the blockchain tip, it starts a simple (and incomplete) Electrum Server to interface with the client.

The scanning is the interesting part. Instead of loading data from the table into the Frigate server application, the database itself performs all the required cryptographic operations. To do this, Frigate uses a fast OLAP database called DuckDB designed for analytical query workloads. It then extends the database with a custom extension wrapping UltrafastSecp256k1, a high-performance secp256k1 library with CPU and GPU backends. This allows the EC point computation to happen as close to the tweak data as possible.

Conceptually, scanning for silent payments requires computing the Taproot output key for k = 0 and comparing it to the list of known output keys for each tweak row:

SELECT txid, tweak_key, height FROM tweak WHERE list_contains(outputs, hash_prefix_to_int(secp256k1_ec_pubkey_combine([SPEND_PUBLIC_KEY, secp256k1_ec_pubkey_create(secp256k1_tagged_sha256('BIP0352/SharedSecret', secp256k1_ec_pubkey_tweak_mul(tweak_key, SCAN_PRIVATE_KEY) || int_to_big_endian(0)))]), 1));

The client can then download the transaction and determine if it does indeed contain outputs it is interested in, including for higher values of k.

Frigate performs all of these steps at once using a single scanning function that also includes a further step to scan for change:

SELECT txid, tweak_key, height FROM ufsecp_scan((SELECT txid, height, tweak_key, outputs FROM tweak), SCAN_PRIVATE_KEY, SPEND_PUBLIC_KEY, [CHANGE_TWEAK_KEY]);

The change tweak is added to the computed P<sub>0</sub> and checked again against the outputs for a match. All inputs are provided in little endian format, with public keys in uncompressed little endian x,y format to avoid decompression overhead on each tweak. UltrafastSecp256k1 uses batch affine addition and KPlan-optimized scalar multiplication to maximize throughput on CPU, and can leverage CUDA, OpenCl or Metal to offload EC computation to the GPU for significantly higher performance.

Electrum protocol

The Electrum protocol is by far the most widely used light client protocol for Bitcoin wallets, and support is now almost a requirement for widespread adoption of any wallet technology proposal. It is characterised by resource efficiency for the client in terms of bandwidth, CPU and storage, allowing a good user experience on almost any platform. It has however been designed around BIP32 wallets. Silent Payments presents an alternative model, where instead of an incrementing derivation path index (and associated gap limit) transactions must be found through scanning the blockchain. As such, new methods are necessary. Frigate proposes the following Electrum JSON-RPC methods:

blockchain.silentpayments.subscribe

Signature

blockchain.silentpayments.subscribe(scan_private_key, spend_public_key, start, labels)
  • scan_private_key: A 64 character string containing the hex of the scan private key.
  • spend_public_key: A 66 character string containing the hex of the spend public key.
  • start: (Optional) Block height or timestamp to start scanning from. Values above 500,000,000 are treated as seconds from the start of the epoch.
  • labels: (Optional) An array of positive integers specifying additional silent payment labels to scan for. Change (m = 0) is always included regardless. To aid in wallet recovery, this parameter should only be used for specialized applications.

Result

The silent payment address that has been subscribed.

Result Example

sp1qqgste7k9hx0qftg6qmwlkqtwu
View on GitHub
GitHub Stars66
CategoryDevelopment
Updated4h ago
Forks6

Languages

Java

Security Score

95/100

Audited on Apr 2, 2026

No findings