Skip to content

About

Attestation for Bisq pricenode data

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pricenode Attestations

Cryptographically signed attestations of Bisq pricenode data, published as Nostr events.

Bisq pricenodes serve market reference prices over Tor but do not sign their responses. This script periodically fetches prices from a pricenode and publishes them as signed Nostr events, creating a verifiable trail that trading parties can reference to agree on a price.

Use case

Two parties trading P2P can use these attestations to agree on a reference price:

  1. Alice publishes an offer: "selling BTC at market price + 7%"
  2. Bob wants to accept. He queries the bot for the latest attestation, gets event abc123 with USD price 62,610
  3. Bob sends a TakeOffer to Alice including event abc123 as the price reference. The agreed price is 62,610 * 1.07 = 66,992 USD
  4. Alice fetches event abc123 from any relay, verifies the signature, timestamps, and confirms the price

Verification

Given an event, any party can independently verify it:

  1. Recompute the event ID: SHA-256(json_encode([0, pubkey, created_at, kind, tags, content]))
  2. Verify the Schnorr signature against the public key and event ID
  3. Parse the content field to extract the original pricenode response

How it works

  1. Fetches /getAllMarketPrices from a randomly selected Bisq pricenode via Tor
  2. Builds a Nostr event (kind 1078) with the raw JSON response as content and individual price tags for filtering
  3. Signs the event with a BIP-340 Schnorr signature using the secp256k1_nostr PHP extension
  4. Publishes the signed event to several Nostr relays

The raw pricenode response is embedded byte-for-byte in the event's content field.

Requirements

  • PHP >= 8.1 with extensions: curl, sockets, mbstring, secp256k1_nostr
  • Tor running with a SOCKS5 proxy on 127.0.0.1:9050
  • Composer

The secp256k1_nostr extension can be installed with pie: pie install uma/secp256k1-nostr

Setup

composer install

Generating a keypair

A Nostr private key is a random 32-byte value, hex-encoded (64 characters). Generate one with:

php -r 'echo bin2hex(random_bytes(32)) . "\n";'

Or with OpenSSL:

openssl rand -hex 32

Or rana, if you want a vanity npub:

cargo run --release -- --vanity-n-prefix=n0de

To derive the corresponding public key (which identifies your bot on Nostr):

php -r 'echo secp256k1_nostr_derive_pubkey($argv[1]) . "\n";' <private_key>

Keep the private key secret. Share the public key with anyone who needs to verify your attestations.

Usage

# Dry run (build and sign the event, print it to stdout, don't publish)
NOSTR_PRIVATE_KEY=<hex> php attest.php --dry-run

# Publish to default relays
NOSTR_PRIVATE_KEY=<hex> php attest.php

# Publish and print the signed event to stdout
NOSTR_PRIVATE_KEY=<hex> php attest.php --verbose

# Publish to additional relays (merged with the built-in list)
NOSTR_PRIVATE_KEY=<hex> NOSTR_RELAYS=wss://custom.relay.example php attest.php

By default, only relay status messages are printed (to stderr). Use --verbose to also print the signed event JSON to stdout. --dry-run implies --verbose.

Deployment with systemd

The recommended way to run this periodically is a systemd timer with a dedicated service user. This avoids exposing the private key in crontabs, environment listings or process tables.

Create a credentials file readable only by the service user:

sudo mkdir -p /etc/pricenode-attestations
echo 'NOSTR_PRIVATE_KEY=<hex>' | sudo tee /etc/pricenode-attestations/env > /dev/null
sudo chmod 600 /etc/pricenode-attestations/env
sudo chown pricenode-attestations: /etc/pricenode-attestations/env

Create the service unit (/etc/systemd/system/pricenode-attestations.service):

[Unit]
Description=Pricenode attestation publisher
Wants=network-online.target tor.service
After=network-online.target tor.service

[Service]
Type=oneshot
User=pricenode-attestations
EnvironmentFile=/etc/pricenode-attestations/env
ExecStart=/usr/bin/php /opt/pricenode-attestations/attest.php

# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadOnlyPaths=/opt/pricenode-attestations

Create the timer (/etc/systemd/system/pricenode-attestations.timer):

[Unit]
Description=Run pricenode attestation every 5 minutes

[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
RandomizedDelaySec=30s

[Install]
WantedBy=timers.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now pricenode-attestations.timer

Cron (simpler alternative)

If you prefer simplicity over hardening:

*/5 * * * * NOSTR_PRIVATE_KEY=<hex> php /path/to/attest.php >> /var/log/pricenode-attestations.log 2>&1

Note that the private key will be visible in the crontab file and in /proc/*/environ of the running process.

Event structure

Each event uses kind 1078 (regular, non-replaceable) to preserve full history on relays.

Tags

Tag Purpose
["t", "pricenode"], ["t", "bisq"], ["t", "bitcoin"] Hashtags for discoverability
["L", "io.bisq.pricenode"] NIP-32 label namespace
["l", "attestation", "io.bisq.pricenode"] NIP-32 label: marks the event as a pricenode attestation
["pricenode", "<onion address>"] Which pricenode was queried
["price", "<currency>", "<price>", "<timestamp>"] One tag per Bisq-Aggregate price, filterable by relay queries

Content

The content field contains the raw JSON response from the pricenode, byte-for-byte identical to what was received.

Querying events

From a Nostr relay, using the bot's public key:

// Latest attestation
["REQ", "sub1", {"authors": ["<pubkey>"], "kinds": [1078], "limit": 1}]

// Latest USD price
["REQ", "sub2", {"authors": ["<pubkey>"], "kinds": [1078], "#price": ["USD"], "limit": 1}]

// Attestations within a time window
["REQ", "sub3", {"authors": ["<pubkey>"], "kinds": [1078], "since": 1700000000, "until": 1700000300}]

// Specific event by ID
["REQ", "sub4", {"ids": ["<event_id>"]}]

Known Attestator Identities

NPub Operator
npub1n0deulgn46wl2jq2kckvexlmc9qd3ghpa0a6nz3tsgaemktyztes9wfzmh Barcelona Bitcoin Only

About

Attestation for Bisq pricenode data

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages