Sign Bitcoin transactions using a bitcoind wallet running in a Docker container.
This utility reads unsigned (or partially signed) transactions from a JSON file or stdin, fetches the required prevout information using a local bitcoin-cli, and signs them using a wallet in a dockerized bitcoind instance.
cargo install sign-txsbitcoin-cliavailable in PATH (for decoding transactions and fetching prevout info)- Docker with a running bitcoind container that has a loaded wallet (see Setup below for how to set this up)
sign-txs [OPTIONS] [INPUT_FILE]You can produce a package of transactions to submit with:
tx_package=$(sign-txs [OPTIONS] [INPUT_FILE] | jq 'map(.bitcoin)')Submit the package to the blockchain:
bitcoin-cli submitpackage "$tx_package"INPUT_FILE- JSON file containing transactions (reads from stdin if not provided)
--bitcoind-container <ID>- Docker container ID running bitcoind with the wallet (can also be set viaBITCOIND_CONTAINERenvironment variable)
The input JSON file should contain an array of transaction objects:
[
{ "bitcoin": "<raw_transaction_hex>" },
{ "bitcoin": "<raw_transaction_hex>" }
]Signed transactions are printed to stdout in the same JSON format:
[
{ "bitcoin": "<signed_transaction_hex>" },
{ "bitcoin": "<signed_transaction_hex>" }
]Progress information is printed to stderr.
# Using command line argument
sign-txs --bitcoind-container abc123 txs.json > signed.json
# Using environment variable
export BITCOIND_CONTAINER=abc123
sign-txs txs.json > signed.json
# Reading from stdin
cat txs.json | sign-txs --bitcoind-container abc123 > signed.json
# Piping from another command
some-command-that-outputs-json | sign-txs --bitcoind-container abc123 > signed.jsonCreate a .env file in containers/ (see .env.example). Run docker compose up -d.
The containers/ directory provides Docker configurations for both the nginx proxy and bitcoind signer. Configure and run both services:
cd containers
cp .env.example .env
# Edit .env with your QuickNode endpoint URL and host
docker compose up -dThen create a wallet:
docker exec -it bitcoind-signer bitcoin-cli createwallet "signing-wallet"You can use the wallet as the signing wallet now.
To use bitcoin-cli with a remote Bitcoin node (such as QuickNode), you can set up an nginx reverse proxy. This allows bitcoin-cli to connect to a local port that forwards requests to the remote node.
The containers/nginx/ directory contains a Dockerfile and configuration template for the proxy. Configure it via environment variables:
docker build -t bitcoin-proxy containers/nginx/
docker run -d --name bitcoin-proxy -p 8332:8332 \
-e PROXY_PASS_URL=https://xxx-xxxxx-xxxx.btc.quiknode.pro/ACCESS_TOKEN/ \
-e PROXY_HOST=xxx-xxxxx-xxxx.btc.quiknode.pro \
bitcoin-proxyNow bitcoin-cli can connect to the remote node:
bitcoin-cli -rpcconnect=127.0.0.1 -rpcport=8332 getblockcountFor signing transactions, you need a bitcoind instance with a wallet. This can run in offline mode (no network connections) for security.
The containers/bitcoind/ directory contains a ready-to-use Dockerfile and bitcoin.conf for an offline signing container.
Build and run the container:
# Build the image
docker build -t bitcoind-signer containers/bitcoind/
# Run the container
docker run -d --name bitcoind-signer bitcoind-signer
# Create or load a wallet
docker exec -it bitcoind-signer bitcoin-cli createwallet "signing-wallet"
# Import your private keys or descriptors
docker exec -it bitcoind-signer bitcoin-cli importdescriptors '[...]'Use the container name with sign-txs:
sign-txs --bitcoind-container bitcoind-signer txs.json > signed.jsonMIT