**Motivations:** - Export Signet and mining wallet backups to git with only 2 versions kept - Document and add backup/restore scripts for signet and mining wallet **Correctifs:** - Backup-to-git uses SSH URL for passwordless cron; copy timestamped files only; prune to 2 versions; remove *-latest from backup repo **Evolutions:** - data/backup-to-git-cron.sh: daily export to git.4nkweb.com/4nk/backup - save-signet-datadir-backup.sh, restore-signet-from-backup.sh, export-mining-wallet.sh, import-mining-wallet.sh - features/backup-to-git-daily-cron.md, docs/MAINTENANCE.md backup section - .gitignore: data/backup-to-git.log **Pages affectées:** - .gitignore, data/backup-to-git-cron.sh, docs/MAINTENANCE.md, features/backup-to-git-daily-cron.md - save-signet-datadir-backup.sh, restore-signet-from-backup.sh, export-mining-wallet.sh, import-mining-wallet.sh - Plus autres fichiers modifiés ou non suivis déjà présents dans le working tree
100 lines
4.4 KiB
Bash
Executable File
100 lines
4.4 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Re-import a mining wallet export (created by export-mining-wallet.sh).
|
|
# Use on a node that has the same Signet chain (same SIGNETCHALLENGE) to recover funds.
|
|
#
|
|
# Usage: ./import-mining-wallet.sh <path-to-export.json> [container_name]
|
|
# Example: ./import-mining-wallet.sh backups/mining-wallet-export-latest.json
|
|
#
|
|
# Prerequisite: bitcoin-signet-instance (or given container) running with the same chain.
|
|
#
|
|
# Author: 4NK Team
|
|
# Date: 2026-02-02
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
cd "$SCRIPT_DIR"
|
|
EXPORT_PATH="${1:?Usage: $0 <path-to-export.json> [container_name]}"
|
|
CONTAINER_NAME="${2:-bitcoin-signet-instance}"
|
|
|
|
if [[ ! -f "$EXPORT_PATH" ]]; then
|
|
echo "Error: Export file not found: $EXPORT_PATH"
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker ps --format "{{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then
|
|
echo "Error: Container ${CONTAINER_NAME} is not running"
|
|
exit 1
|
|
fi
|
|
|
|
DATADIR=$(docker exec "$CONTAINER_NAME" printenv BITCOIN_DIR 2>/dev/null || echo "/root/.bitcoin")
|
|
|
|
echo "=== Import mining wallet ==="
|
|
echo "Export file: $EXPORT_PATH"
|
|
echo "Container: $CONTAINER_NAME"
|
|
echo ""
|
|
|
|
SIGNET_EXPORT=$(jq -r '.signet_challenge' "$EXPORT_PATH")
|
|
WALLET_NAME=$(jq -r '.wallet_name' "$EXPORT_PATH")
|
|
PRIVKEY_EXPORT=$(jq -r '.privkey' "$EXPORT_PATH")
|
|
|
|
if [[ -z "$WALLET_NAME" ]] || [[ "$WALLET_NAME" == "null" ]]; then
|
|
echo "Error: Invalid export file (missing wallet_name)"
|
|
exit 1
|
|
fi
|
|
|
|
# Verify we are on the same chain (SIGNETCHALLENGE must match)
|
|
SIGNET_NODE=$(sudo docker exec "$CONTAINER_NAME" cat "$DATADIR/SIGNETCHALLENGE.txt" 2>/dev/null || echo "")
|
|
if [[ -n "$SIGNET_NODE" ]] && [[ -n "$SIGNET_EXPORT" ]] && [[ "$SIGNET_EXPORT" != "null" ]]; then
|
|
if [[ "$SIGNET_NODE" != "$SIGNET_EXPORT" ]]; then
|
|
echo "Error: SIGNETCHALLENGE mismatch. Export is for another chain."
|
|
echo " Node: ${SIGNET_NODE:0:20}..."
|
|
echo " Export: ${SIGNET_EXPORT:0:20}..."
|
|
exit 1
|
|
fi
|
|
echo "SIGNETCHALLENGE matches (same chain)"
|
|
fi
|
|
|
|
# Create wallet if it does not exist
|
|
if ! sudo docker exec "$CONTAINER_NAME" bitcoin-cli -datadir="$DATADIR" listwallets 2>/dev/null | grep -q "\"$WALLET_NAME\""; then
|
|
echo "Creating wallet: $WALLET_NAME"
|
|
sudo docker exec "$CONTAINER_NAME" bitcoin-cli -datadir="$DATADIR" -named createwallet \
|
|
wallet_name="$WALLET_NAME" load_on_startup=true descriptors=true 2>/dev/null || true
|
|
fi
|
|
|
|
# Load wallet if not loaded
|
|
if ! sudo docker exec "$CONTAINER_NAME" bitcoin-cli -datadir="$DATADIR" listwallets 2>/dev/null | grep -q "\"$WALLET_NAME\""; then
|
|
echo "Loading wallet: $WALLET_NAME"
|
|
sudo docker exec "$CONTAINER_NAME" bitcoin-cli -datadir="$DATADIR" loadwallet "$WALLET_NAME" 2>/dev/null || true
|
|
fi
|
|
|
|
# Import descriptors (with private keys). Pass JSON via temp file to avoid shell escaping issues.
|
|
DESCRIPTORS_JSON=$(jq -c '.descriptors' "$EXPORT_PATH")
|
|
if [[ -z "$DESCRIPTORS_JSON" ]] || [[ "$DESCRIPTORS_JSON" == "null" ]] || [[ "$DESCRIPTORS_JSON" == "[]" ]]; then
|
|
echo "Warning: No descriptors in export. Importing PRIVKEY as pk() descriptor if present."
|
|
if [[ -n "$PRIVKEY_EXPORT" ]] && [[ "$PRIVKEY_EXPORT" != "null" ]]; then
|
|
DESCRIPTOR_INFO=$(sudo docker exec "$CONTAINER_NAME" bitcoin-cli -datadir="$DATADIR" -rpcwallet="$WALLET_NAME" getdescriptorinfo "pk($PRIVKEY_EXPORT)" 2>/dev/null || echo "{}")
|
|
CHECKSUM=$(echo "$DESCRIPTOR_INFO" | jq -r '.checksum')
|
|
if [[ -n "$CHECKSUM" ]] && [[ "$CHECKSUM" != "null" ]]; then
|
|
sudo docker exec "$CONTAINER_NAME" bitcoin-cli -datadir="$DATADIR" -rpcwallet="$WALLET_NAME" importdescriptors \
|
|
"[{\"desc\":\"pk($PRIVKEY_EXPORT)#$CHECKSUM\",\"timestamp\":0,\"internal\":false}]" 2>/dev/null || true
|
|
echo "PRIVKEY imported as pk() descriptor"
|
|
fi
|
|
fi
|
|
else
|
|
echo "Importing descriptors..."
|
|
TMP_JSON=$(mktemp)
|
|
echo "$DESCRIPTORS_JSON" > "$TMP_JSON"
|
|
sudo docker cp "$TMP_JSON" "$CONTAINER_NAME:/tmp/import-descriptors.json"
|
|
sudo docker exec "$CONTAINER_NAME" sh -c "bitcoin-cli -datadir=$DATADIR -rpcwallet=$WALLET_NAME importdescriptors \"\$(cat /tmp/import-descriptors.json)\"" 2>/dev/null || true
|
|
sudo docker exec "$CONTAINER_NAME" rm -f /tmp/import-descriptors.json 2>/dev/null || true
|
|
rm -f "$TMP_JSON"
|
|
echo "Descriptors imported"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Wallet $WALLET_NAME imported. Check balance:"
|
|
sudo docker exec "$CONTAINER_NAME" bitcoin-cli -datadir="$DATADIR" -rpcwallet="$WALLET_NAME" getwalletinfo 2>/dev/null | jq '{walletname, balance, txcount}' || true
|
|
echo ""
|