Skip to content

Commit 3a05bb9

Browse files
authored
Merge pull request nbd-wtf#13 from nbd-wtf/modern_wallet
Modern wallet with migration
2 parents 5a5e616 + 56f1c48 commit 3a05bb9

12 files changed

+268
-75
lines changed

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ ENV BITCOIN_DIR /root/.bitcoin
2929
ENV NBITS=${NBITS}
3030
ENV SIGNETCHALLENGE=${SIGNETCHALLENGE}
3131
ENV PRIVKEY=${PRIVKEY}
32-
32+
ENV PRIVKEY_MODE=${PRIVKEY_MODE:-"descriptor"}
33+
ENV CHAIN_TIP_AGE=${CHAIN_TIP_AGE:-"7200"}
34+
ENV MINE_GENESIS=${MINE_GENESIS:-"0"}
3335
ENV RPCUSER=${RPCUSER:-"bitcoin"}
3436
ENV RPCPASSWORD=${RPCPASSWORD:-"bitcoin"}
3537
ENV COOKIEFILE=${COOKIEFILE:-"false"}

README.md

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,28 @@
22

33
## 📌 Table of Contents
44

5-
- [🔍 Overview](#-overview)
6-
- [🛠 Environment Variables](#-environment-variables)
7-
- [⛏ Mining Configuration](#-mining-configuration)
8-
- [🌐 RPC Configuration](#-rpc-configuration)
9-
- [🌍 Network Configuration](#-network-configuration)
10-
- [📡 ZMQ Configuration](#-zmq-configuration)
11-
- [🔧 Additional Configuration](#-additional-configuration)
12-
- [🚀 Building and Running the Docker Image](#-building-and-running-the-docker-image)
13-
- [🔧 Docker Commands](#-docker-commands)
14-
- [📜 License](#-license)
5+
- [Bitcoin Signet Docker Image](#bitcoin-signet-docker-image)
6+
- [📌 Table of Contents](#-table-of-contents)
7+
- [🔍 Overview](#-overview)
8+
- [🛠 Environment Variables](#-environment-variables)
9+
- [⛏ Mining Configuration:](#-mining-configuration)
10+
- [🌐 RPC Configuration:](#-rpc-configuration)
11+
- [🌍 Network Configuration:](#-network-configuration)
12+
- [📡 ZMQ Configuration:](#-zmq-configuration)
13+
- [🔧 Additional Configuration:](#-additional-configuration)
14+
- [🚀 Building and Running the Docker Image](#-building-and-running-the-docker-image)
15+
- [🔧 Docker Commands](#-docker-commands)
16+
- [📜 License](#-license)
1517

1618
---
1719

1820
## 🔍 Overview
1921

2022
Bitcoin Signet provides a sandboxed environment for Bitcoin, allowing developers and testers to simulate the Bitcoin network without the risks associated with the main or test networks. This Docker image facilitates the deployment and configuration of a Signet node, offering a range of customizable options through environment variables.
2123

24+
Versions prior to 29.0 were using BDB wallet, system will automaticly update your wallet to new descriptor format.
25+
`PRIVKEY` prior to 29.0 was a WIF, now is descriptor on new wallets.
26+
2227
## 🛠 Environment Variables
2328

2429
### ⛏ Mining Configuration:
@@ -28,15 +33,21 @@ Bitcoin Signet provides a sandboxed environment for Bitcoin, allowing developers
2833
- `MINERENABLED`: Flag to enable the mining chain. (**mining mode only**)
2934
- `NBITS`: Sets the minimum difficulty in mining. (**mining mode only**)
3035
- `PRIVKEY`: Private key of the Signet signer. If `MINERENABLED=1` and not provided, it will be generated. (**mining mode only**)
36+
- `PRIVKEY_MODE`: `descriptor` - provide descriptors (wallets from >=v29.0) or `legacy` - provide WIF (method used prior to <v29.0 to init signet challenge)
3137
- `MINETO`: Address to mine to. If not provided, a new address will be generated for each block. (**mining mode only**)
3238
- `SIGNETCHALLENGE`: Sets the valid block producer for this Signet. Required for client-mode.
33-
- If `MINERENABLED=1` and not provided, it will be generated. If provided, `PRIVKEY` must also be populated.
39+
- If `MINERENABLED=1` and not provided, it will be generated. If provided, `PRIVKEY` must also be populated.
40+
- `CHAIN_TIP_AGE`: 7200s (2hrs), will not start miner until chain-tip timestamp vs local is <= this value, allows things to sync up before trying to mine bad blacks.
41+
- `MINE_GENESIS`: set to 1 if you are starting a new chain, will mine first block so passes `CHAIN_TIP_AGE` check.
3442

3543
### 🌐 RPC Configuration:
3644

3745
- `RPCUSER`: bitcoind RPC User.
3846
- `RPCPASSWORD`: bitcoind RPC password.
39-
47+
- `RPCTHREADS`: # of work threads (default 16)
48+
- `RPCSERVERTIMEOUT`: RPC timeout (default 600s)
49+
- `RPCWORKQUEUE`: RPC queue lenght (50)
50+
4051
### 🌍 Network Configuration:
4152

4253
- `ONIONPROXY`: Tor SOCK5 endpoint.

docker-entrypoint.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ if [[ ! -f "${BITCOIN_DIR}/install_done" ]]; then
1616
install.sh #this is config based on args passed into mining node or peer.
1717
else
1818
echo "install_done file exists, skipping setup process."
19+
if [[ ! -f "${BITCOIN_DIR}/uses_modern_wallet" ]]; then
20+
echo "Hmm looks like you are using a legacy wallet, lets get that migrated over."
21+
migrate.sh
22+
sleep 4
23+
echo "Migration complete, lets start bitcoind."
24+
fi
1925
echo "rewrite bitcoin.conf"
2026
gen-bitcoind-conf.sh >~/.bitcoin/bitcoin.conf
2127
fi

gen-signet-keys.sh

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,56 @@
11
DATADIR=${DATADIR:-"regtest-temp"}
22
BITCOINCLI=${BITCOINCLI:-"bitcoin-cli -regtest -datadir=$DATADIR "}
3-
BITCOIND=${BITCOIND:-"bitcoind -datadir=$DATADIR -regtest -daemon -deprecatedrpc=create_bdb"}
3+
BITCOIND=${BITCOIND:-"bitcoind -datadir=$DATADIR -regtest -daemon"}
44

5-
write_files() {
6-
# echo "ADDR=" $ADDR
7-
echo "PRIVKEY=" $PRIVKEY
8-
# echo "PUBKEY=" $PUBKEY
5+
write_files() {
6+
echo "PRIVKEY="
7+
cat $BITCOIN_DIR/PRIVKEY.txt
98
echo "SIGNETCHALLENGE=" $SIGNETCHALLENGE
10-
# echo $ADDR > ~/.bitcoin/ADDR.txt
11-
echo $PRIVKEY >~/.bitcoin/PRIVKEY.txt
12-
# echo $PUBKEY > ~/.bitcoin/PUBKEY.txt
13-
echo $SIGNETCHALLENGE >~/.bitcoin/SIGNETCHALLENGE.txt
9+
echo $ADDR > $BITCOIN_DIR/ADDR.txt
10+
echo $PUBKEY > $BITCOIN_DIR/PUBKEY.txt
11+
echo $SIGNETCHALLENGE >$BITCOIN_DIR/SIGNETCHALLENGE.txt
1412
}
1513

16-
if [[ "$MINERENABLED" == "1" && ("$SIGNETCHALLENGE" == "" || "$PRIVKEY" == "") ]]; then
17-
echo "Generating new signetchallange and privkey."
18-
#clean if exists
19-
rm -rf $DATADIR
20-
#make it fresh
21-
mkdir $DATADIR
22-
#kill any daemon running stuff
23-
pkill bitcoind
24-
#minimal config file (hardcode bitcoin:bitcoin for rpc)
25-
echo "
26-
regtest=1
27-
server=1
28-
rpcauth=bitcoin:c8c8b9740a470454255b7a38d4f38a52\$e8530d1c739a3bb0ec6e9513290def11651afbfd2b979f38c16ec2cf76cf348a
29-
rpcuser=bitcoin
30-
rpcpassword=bitcoin
31-
" >$DATADIR/bitcoin.conf
32-
#start daemon
33-
$BITCOIND -wallet="temp"
34-
#wait a bit for startup
35-
sleep 5s
36-
#create wallet
37-
$BITCOINCLI -named createwallet wallet_name="temp" descriptors=false
38-
#export future signet seeding key data
39-
ADDR=$($BITCOINCLI getnewaddress "" legacy)
40-
PRIVKEY=$($BITCOINCLI dumpprivkey $ADDR)
41-
PUBKEY=$($BITCOINCLI getaddressinfo $ADDR | jq .pubkey | tr -d '""')
42-
#don't need regtest anymore
43-
$BITCOINCLI stop
44-
SIGNETCHALLENGE=$(echo '5121'$PUBKEY'51ae')
45-
46-
#cleanup
47-
rm -rf $DATADIR
48-
else
49-
echo "Imported signetchallange and privkey being used."
14+
if [[ "$MINERENABLED" == "1" ]]; then
15+
if [[ ("$SIGNETCHALLENGE" == "" || "$PRIVKEY" == "") ]]; then
16+
echo "Generating new signetchallange and privkey."
17+
#clean if exists
18+
rm -rf $DATADIR
19+
#make it fresh
20+
mkdir $DATADIR
21+
#kill any daemon running stuff
22+
pkill bitcoind
23+
#minimal config file (hardcode bitcoin:bitcoin for rpc)
24+
echo "
25+
regtest=1
26+
server=1
27+
rpcauth=bitcoin:c8c8b9740a470454255b7a38d4f38a52\$e8530d1c739a3bb0ec6e9513290def11651afbfd2b979f38c16ec2cf76cf348a
28+
rpcuser=bitcoin
29+
rpcpassword=bitcoin
30+
" >$DATADIR/bitcoin.conf
31+
#start daemon
32+
$BITCOIND -wallet="temp"
33+
#wait a bit for startup
34+
sleep 5s
35+
36+
#create wallet
37+
$BITCOINCLI -named createwallet wallet_name="temp" descriptors=true
38+
#Get the signet script from the 86 descriptor
39+
ADDR=$($BITCOINCLI getnewaddress)
40+
SIGNETCHALLENGE=$($BITCOINCLI getaddressinfo $ADDR | jq -r ".scriptPubKey")
41+
PUBKEY=$($BITCOINCLI getaddressinfo $ADDR | jq .pubkey | tr -d '""')
42+
# Dumping descriptor wallet privatekey
43+
$BITCOINCLI listdescriptors true | jq -r ".descriptors | .[].desc" >> $BITCOIN_DIR/PRIVKEY.txt
44+
45+
#don't need regtest anymore
46+
$BITCOINCLI stop
47+
#cleanup
48+
rm -rf $DATADIR
49+
else
50+
echo "$PRIVKEY" > $BITCOIN_DIR/PRIVKEY.txt
51+
echo "$SIGNETCHALLENGE" > $BITCOIN_DIR/SIGNETCHALLENGE.txt
52+
echo "Imported signetchallange and privkey being used."
53+
fi
5054
fi
5155

5256
write_files

import_wif_to_descriptor.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
5+
WIF_PRIVKEY=$(cat ${BITCOIN_DIR}/PRIVKEY.txt)
6+
7+
# Step 1: Construct input descriptor with WIF
8+
#INPUT_DESC="pk($WIF)"
9+
#BASE_DESC="combo($WIF_PRIVKEY)"
10+
11+
BASE_DESC="multi(1,$WIF_PRIVKEY)"
12+
# Step 2: Get checksum (must preserve private key in input, do NOT use returned descriptor)
13+
CHECKSUM=$(bitcoin-cli getdescriptorinfo "$BASE_DESC" | jq -r .checksum)
14+
# Step 3: Final descriptor with checksum
15+
FINAL_DESC="${BASE_DESC}#${CHECKSUM}"
16+
# Step 4: Build import JSON with rescan
17+
IMPORT_JSON=$(cat <<EOF
18+
[{
19+
"desc": "$FINAL_DESC",
20+
"timestamp": "now",
21+
"label": "bdb-migrated-signet"
22+
}]
23+
EOF
24+
)
25+
# Step 5: Import descriptor into wallet
26+
echo "Importing descriptor for signet multisig(1 of 1)..."
27+
bitcoin-cli importdescriptors "$IMPORT_JSON"
28+
29+
30+
BASE_DESC="combo($WIF_PRIVKEY)"
31+
# Step 2: Get checksum (must preserve private key in input, do NOT use returned descriptor)
32+
CHECKSUM=$(bitcoin-cli getdescriptorinfo "$BASE_DESC" | jq -r .checksum)
33+
# Step 3: Final descriptor with checksum
34+
FINAL_DESC="${BASE_DESC}#${CHECKSUM}"
35+
# Step 4: Build import JSON with rescan
36+
IMPORT_JSON=$(cat <<EOF
37+
[{
38+
"desc": "$FINAL_DESC",
39+
"timestamp": "now",
40+
"label": "bdb-migrated-signet"
41+
}]
42+
EOF
43+
)
44+
# Step 5: Import descriptor into wallet
45+
echo "Importing descriptor for signet combo()..."
46+
bitcoin-cli importdescriptors "$IMPORT_JSON"

install.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
touch ${BITCOIN_DIR}/uses_modern_wallet
12
echo "Generate or import keyset"
23
gen-signet-keys.sh
34
echo "Generate bitcoind configuration"
4-
gen-bitcoind-conf.sh >~/.bitcoin/bitcoin.conf
5+
gen-bitcoind-conf.sh >${BITCOIN_DIR}/bitcoin.conf
56
echo "Setup Signet"
67
setup-signet.sh
78

@@ -10,4 +11,4 @@ if [[ "$MINE_GENESIS" == "1" ]]; then
1011
mine-genesis.sh
1112
fi
1213

13-
touch ~/.bitcoin/install_done
14+
touch ${BITCOIN_DIR}/install_done

migrate.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CLI="bitcoin-cli -datadir=${BITCOIN_DIR}"
2+
3+
bitcoind --daemonwait
4+
sleep 5
5+
$CLI migratewallet custom_signet
6+
if [[ $? -ne 0 ]]; then
7+
echo "Migration failed, exiting."
8+
exit 1
9+
fi
10+
echo "Migrating privkey to descriptor format."
11+
import_wif_to_descriptor.sh
12+
echo "Private key imported into wallet as descriptor."
13+
touch "${BITCOIN_DIR}/uses_modern_wallet"
14+
echo "Migration completed successfully."
15+
$CLI stop
16+
sleep 5

mine-genesis.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
ADDR=${ADDR:-$(bitcoin-cli getnewaddress "" legacy)}
2+
ADDR=${ADDR:-$(bitcoin-cli getnewaddress "gen0" bech32)}
33
NBITS=${NBITS:-"1e0377ae"} #minimum difficulty in signet
44
miner --cli="bitcoin-cli" generate --address=$ADDR --grind-cmd="bitcoin-util grind" --nbits=$NBITS --set-block-time=$(date +%s)
55

mine.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
#!/bin/bash
2+
set -Eeuo pipefail
3+
# Define mining constants
4+
CLI="bitcoin-cli -datadir=${BITCOIN_DIR}"
5+
GRIND="bitcoin-util grind"
6+
27
NBITS=${NBITS:-"1e0377ae"} #minimum difficulty in signet
38

9+
echo "Waiting until Chain tip age is < $CHAIN_TIP_AGE seconds before mining start..."
10+
wait_chain_sync.sh $CHAIN_TIP_AGE
411
while true; do
512
ADDR=${MINETO:-$(bitcoin-cli getnewaddress)}
13+
echo "Mining to address:" $ADDR
614
if [[ -f "${BITCOIN_DIR}/BLOCKPRODUCTIONDELAY.txt" ]]; then
715
BLOCKPRODUCTIONDELAY_OVERRIDE=$(cat ~/.bitcoin/BLOCKPRODUCTIONDELAY.txt)
816
echo "Delay OVERRIDE before next block" $BLOCKPRODUCTIONDELAY_OVERRIDE "seconds."
@@ -14,6 +22,9 @@ while true; do
1422
sleep $BLOCKPRODUCTIONDELAY
1523
fi
1624
fi
17-
echo "Mine To:" $ADDR
18-
miner --cli="bitcoin-cli" generate --grind-cmd="bitcoin-util grind" --address=$ADDR --nbits=$NBITS --set-block-time=$(date +%s)
25+
#echo "Mine To:" $ADDR --addr=$ADDR
26+
miner --cli="bitcoin-cli" generate --grind-cmd="bitcoin-util grind" --addr=$ADDR --nbits=$NBITS --set-block-time=$(date +%s) || true
27+
1928
done
29+
30+

run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22

33
# run bitcoind
4-
bitcoind --daemonwait -deprecatedrpc=create_bdb
4+
bitcoind --daemonwait
55
sleep 5
66
echo "get magic"
77
magic=$(cat /root/.bitcoin/signet/debug.log | grep -m1 magic)

setup-signet.sh

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,49 @@
1-
PRIVKEY=${PRIVKEY:-$(cat ~/.bitcoin/PRIVKEY.txt)}
2-
DATADIR=${DATADIR:-~/.bitcoin/}
3-
bitcoind -datadir=$DATADIR --daemonwait -persistmempool -deprecatedrpc=create_bdb
4-
bitcoin-cli -datadir=$DATADIR -named createwallet wallet_name="custom_signet" load_on_startup=true descriptors=false
5-
6-
#only used in case of mining node
7-
if [[ "$MINERENABLED" == "1" ]]; then
8-
bitcoin-cli -datadir=$DATADIR importprivkey $PRIVKEY
9-
## for future with descriptor wallets, cannot seem to get it working yet
10-
# descinfo=$(bitcoin-cli getdescriptorinfo "wpkh(${PRIVKEY})")
11-
# checksum=$(echo "$descinfo" | jq .checksum | tr -d '"' | tr -d "\n")
12-
# desc='[{"desc":"wpkh('$PRIVKEY')#'$checksum'","timestamp":0,"internal":false}]'
13-
# bitcoin-cli -datadir=$DATADIR importdescriptors $desc
1+
2+
bitcoind -datadir=$BITCOIN_DIR --daemonwait -persistmempool #-deprecatedrpc=create_bdb
3+
bitcoin-cli -datadir=$BITCOIN_DIR -named createwallet wallet_name="custom_signet" load_on_startup=true descriptors=true
4+
5+
6+
# Set privkey if pushed from ENV and doesn't exist in file systems yet.
7+
if [ ! -f "$BITCOIN_DIR/PRIVKEY.txt" ]; then
8+
echo "$PRIV_KEY" > "$BITCOIN_DIR/PRIVKEY.txt"
9+
fi
10+
11+
#only used in case of mining node and modern wallet
12+
if [[ -f "${BITCOIN_DIR}/uses_modern_wallet" && "$MINERENABLED" == "1" ]]; then
13+
14+
if [ "$PRIVKEY_MODE" == "legacy" ]; then
15+
import_wif_to_descriptor.sh
16+
else
17+
line_count=0
18+
while read line; do
19+
# Increment the line counter
20+
line_count=$((line_count+1))
21+
22+
# Check if the line count is even or odd
23+
if [ $((line_count % 2)) -eq 0 ]; then
24+
is_even="true"
25+
else
26+
is_even="false"
27+
fi
28+
29+
DESCRIPTORS="
30+
{
31+
\"desc\": \"${line}\",
32+
\"timestamp\": 0,
33+
\"active\": true,
34+
\"internal\": ${is_even},
35+
\"range\": [
36+
0,
37+
999
38+
]
39+
}"
40+
41+
DESCRIPTORS="[${DESCRIPTORS//[$'\t\r\n ']}]"
42+
43+
bitcoin-cli -datadir=$BITCOIN_DIR importdescriptors "$DESCRIPTORS" 2>&1 > /dev/null
44+
45+
done < $BITCOIN_DIR/PRIVKEY.txt
46+
fi
47+
48+
1449
fi

0 commit comments

Comments
 (0)