Skip to content

Instantly share code, notes, and snippets.

@josibake
Last active October 18, 2023 09:58
Show Gist options
  • Save josibake/7802309f4e4692ca7003900834782824 to your computer and use it in GitHub Desktop.
Save josibake/7802309f4e4692ca7003900834782824 to your computer and use it in GitHub Desktop.
silent payments testing

Silent Payments (BIP352) Testing Guide

This guide assumes you have a basic knowledge of the command line and are familiar with the bitcoin-cli RPC client.

Setup (optional)

While not required, this guide was written using a bendir directory for easier testing. If you want to follow the guide without using bendir, it's recommended you alias bitcoin-cli to bitcoin-cli -named -signet -datadir=<your testing datadir> so you can copy-paste the commands directly from the guide. To use bendir for your testing environment:

git clone https://github.com/josibake/bendir.git
cp -r bendir silent-payments-testing
cd ~/silent-payments-testing
direnv allow

If this is your first time building Bitcoin Core from source, take a look at the build instructions for your system (build-*.md in bitcoin/doc/). Once you're ready to build, checkout and compile #28453:

# in your bitcoin src directory
git fetch upstream pull/28453/head:silent-payments-testing-branch
git checkout silent-payments-testing-branch

# assuming you have the build dependencies installed
./autogen.sh
./configure
make

Once the build has finished, copy the binaries into your testing directory:

cp ~/bitcoin/src/bitcoind ~/silent-payments-testing/bin/
cp ~/bitcoin/src/bitcoin-cli ~/silent-payments-testing/bin/

Start bitcoind on signet/regtest:

cd ~/silent-payments-testing
init signet
bitcoind -daemon

You are now ready to start testing!

Create and fund a silent payments wallet

Create a wallet:

bitcoin-cli createwallet "sp" silent_payments=true

Fund the wallet:

# mine some blocks if using regtest or get some coins from a signet faucet
bitcoin-cli getnewaddress
# can use https://signet.bc-2.jp or your faucet of choice to send coins to the address

Make a silent payment!

# you can use include_unsafe (instead of waiting for a block) if your signet coins are still unconfirmed
bitcoin-cli getnewaddress address_type="silent-payment"
bitcoin-cli sendtoaddress "<your silent payment address>" <amount> include_unsafe=true

Check the transaction:

bitcoin-cli gettransaction "txid" verbose=true

Silent payment usernames

While silent payments is primarily a privacy improvement, it is also a UX improvment for Bitcoin and can enable cool new protocols like usernames for sending Bitcoin. Here is a small script to demonstrate:

#!/bin/bash

# Default to mainnet if no argument is provided
NETWORK="mainnet"

# Help text
display_help() {
    echo "Usage: $0 [OPTION] EMAIL"
    echo "Fetch payment information for a given email address."
    echo ""
    echo "Available options:"
    echo "  -signet, -regtest, -testnet, -mainnet  Specify the network (default: mainnet)"
    echo "  -h, --help                             Display this help and exit"
    exit 0
}

# Function to check and set the network
set_network() {
    case $1 in
        -signet|-regtest|-testnet|-mainnet)
            NETWORK="${1#-}"
            return 0
            ;;
        -h|--help)
            display_help
            ;;
        *)
            return 1
            ;;
    esac
}

# If no arguments are provided, display help
if [ "$#" -eq 0 ]; then
    display_help
fi

# Check the first and second arguments for the network flag or help
if ! set_network $1; then
    set_network $2
    EMAIL_ARG=$1
else
    EMAIL_ARG=$2
fi

read user domain < <(echo $EMAIL_ARG | awk -F@ '{print $1, $2}')

# Fetch the JSON and check if the network exists in the structure
JSON=$(curl --max-time 3 -s -f https://$domain/.well-known/silent-payments/$user)
CURL_EXIT_STATUS=$?

if [ $CURL_EXIT_STATUS -ne 0 ]; then
    echo "Error: Failed to fetch data from https://$domain/.well-known/silent-payments/$user"
    echo "Are you sure $user@$domain has a silent payment address configured?"
    exit 1
fi

if ! echo "$JSON" | jq -e --arg network "$NETWORK" 'has($network)' > /dev/null; then
    echo "Error: $user does not have a $NETWORK silent payment address. Try one of:"
    echo $JSON | jq
    exit 1
fi

# Extract the value for the provided network
echo "$JSON" | jq -r --arg network "$NETWORK" '.[$network]'

If you don't understand the script that's okay. This script takes an email address and a network flag and fetches a silent payment address from the .well-known directory of the domain. To use the script:

# if using bendir, this script is already available in aliases.
# otherwise, save the script in a file called `pay` and make it executable
vim pay
# copy the script
chmod +x pay

If you have a domain, you can put your silent payments address under the well-known directory like so:

# find the .well-known directory on your server and create a file at the following path
USERNAME="your_desired_username"
SILENT_PAYMENT_ADDRESS="your_silent_payment_address_here"
mkdir -p .well-known/silent-payments

# Echo the JSON content into the file
echo "{\"signet\": \"$SILENT_PAYMENT_ADDRESS\"}" > .well-known/silent-payments/$USERNAME

Now you can get your silent payment address with the pay script:

pay user@domain -signet

And you can make payments from the command line:

bitcoin-cli sendtoaddress $(pay [email protected] -signet) <amount>

Further testing

  • Try using different RPCs, like send
  • Send to the same silent payment address multiple times and verify the addresses are different each time
  • Send multiple UTXOs to the same address, then spend from that address multiple times and verify the silent payment outputs are always unique
  • Verify you can detect an incoming silent payment in the mempool and in a block
  • Verify you can detect previous silent payments when doing a wallet rescan

If you run into any issues or have questions, feel free to leave a comment on this gist!

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