log_info "bitcoin core started"
}
+bitcoin_core_start_interactive() {
+ log_msg "start bitcoin core:\n\n\tbitcoind --daemonwait\n"
+
+ confirm "confirm bitcoin core started"
+}
+
bitcoin_core_stop() {
RUNNING=`ps -A | ( grep bitcoind > /dev/null && echo "1" ) || echo "0"`
if [[ "$RUNNING" -eq 0 ]]; then
log_info "bitcoin core stopped"
}
+bitcoin_core_stop_interactive() {
+ log_msg "stop bitcoin core:\n\n\tbitcoin-cli stop\n"
+}
+
+confirm() {
+ local RESULT
+ while true; do
+ read -n 1 -p "$1: [Y/n] " RESULT
+ if [[ "$RESULT" == "Y" ]]; then
+ break;
+ fi
+ log_error "\nfailed...\n"
+ done
+ log_error "\n"
+}
+
depends() {
PATH="$PATH:/sbin"
echo -n '", "active": true, "timestamp": "now", "internal": true}]' >> "$DUMPFILE"
}
+multisig_create_interactive() {
+ log_msg "Creating multi-signature descriptors..."
+
+ log_msg "create output file 'main.descriptors':\n\n\techo -n \"wsh(sortedmulti(3,\" > main.descriptors"
+ confirm "confirm main.descriptors created"
+
+ for((i = 1; i <= $N; i++)); do
+ log_msg "added descriptors from wallet$i to main.descriptors\n\n\tbitcoin-cli -rpcwallet=wallet$i listdescriptors | jq -j '.descriptors | map(select(.desc | startswith(\"wpkh\"))) | map(select(.internal == false)) | map(.desc | ltrimstr(\"wpkh(\")) | .[] | split(\")\") | .[0]' >> main.descriptors"
+ confirm "confirm descriptors from wallet$i added to main.descriptors"
+ done
+
+ log_msg "finish formatting for main.descriptors:\n\n\techo \"))\" >> main.descriptors"
+ confirm "confirm main.descriptors file fully created"
+
+ log_msg "Use bitcoin core to get information on fully formed descriptors and output result to descriptors.txt:\n\n\tcat main.descriptors | bitcoin-cli -stdin getdescriptorinfo | jq -j '.descriptor' >> descriptors.txt"
+ confirm "confirm descriptors.txt created"
+
+ log_msg "create output file 'change.descriptors':\n\n\techo -n \"wsh(sortedmulti(3,\" > change.descriptors"
+ confirm "confirm change.descriptors created"
+
+ for((i = 1; i <= $N; i++)); do
+ log_msg "added change descriptors from wallet$i to change.descriptors\n\n\tbitcoin-cli -rpcwallet=wallet$i listdescriptors | jq -j '.descriptors | map(select(.desc | startswith(\"wpkh\"))) | map(select(.internal == true)) | map(.desc | ltrimstr(\"wpkh(\")) | .[] | split(\")\") | .[0]' >> change.descriptors"
+ confirm "confirm change descriptors from wallet$i added to change.descriptors"
+ done
+
+ log_msg "finish formatting for change.descriptors:\n\n\techo \"))\" >> change.descriptors"
+ confirm "confirm change.descriptors file fully created"
+
+ log_msg "Format descriptors.txt to be ready to append change descriptors:\n\n\techo -n ',{\"desc\": \"' >> descriptors.txt"
+ confirm "confirm descriptors.txt formatted correctly"
+
+ log_msg "Use bitcoin core to get information on fully formed change descriptors and output result to descriptors.txt:\n\n\tcat change.descriptors | bitcoin-cli -stdin getdescriptorinfo | jq -j '.descriptor' >> descriptors.txt"
+ confirm "confirm change descriptors added to descriptors.txt"
+}
+
network_off() {
nmcli networking off
}
+network_off_interactive() {
+ log_msg "shut off networking:\n\n\tnmcli networking off\n"
+
+ confirm "confirm networking shut off"
+}
+
parse_arguments() {
# transform long options into short opts
for arg in "$@"; do
done
}
+usbs_interactive() {
+ # export to usbs
+ for((i = 1; i <= $N; i++)); do
+ log_msg "insert usb drive..."
+ USB_PATH="`usb_detect`"
+ log_msg "usb drive detected at $USB_PATH"
+ confirm "use usb drive at $USB_PATH?"
+
+ log_msg "wipe filesystem on $USB_PATH\n\n\twipefs -a $USB_PATH"
+ confirm "usb drive wiped"
+
+ if [[ -n "$ENCRYPTION" ]]; then
+ log_msg "format usb device for encryption:\n\n\tcryptsetup luksFormat --type luks2 $USB_PATH"
+ confirm "usb drive formatted for encryption"
+
+ log_msg "open encrypted drive:\n\n\tcryptsetup luksOpen $USB_PATH $USB_DECRYPT_NAME"
+ confirm "usb drive opened"
+
+ USB_PATH_PRE_DECRYPT="$USB_PATH"
+ USB_PATH="/dev/mapper/$USB_DECRYPT_NAME"
+ fi
+
+ log_msg "fill drive with zeros:\n\n\tdd if=/dev/zero of=$USB_PATH"
+ confirm "drive filled with zeros"
+
+ log_msg "make filesystem on usb drive:\n\n\tmkfs.ext4 $USB_PATH"
+ confirm "filesystem setup on usb drive"
+
+ log_msg "mount usb drive:\n\n\tmount $USB_PATH $USB_DIRECTORY"
+ confirm "usb drive mounted at $USB_DIRECTORY"
+
+ log_msg "dump descriptors for wallet$i:\n\n\tbitcoin-cli -named -rpcwallet=wallet$i listdescriptors private=true > wallet$i.descriptors"
+ confirm "descriptors dumped into wallet$i.descriptors"
+
+ log_msg "copy descriptors for wallet$i to $USB_DIRECTORY:\n\n\tcp wallet$i.descriptors $USB_DIRECTORY/"
+ confirm "descriptors copied to $USB_DIRECTORY"
+
+ log_msg "copy multi-signature descriptors to $USB_DIRECTORY:\n\n\tcp descriptors.txt $USB_DIRECTORY/"
+ confirm "multi-signature descriptors copied to $USB_DIRECTORY"
+
+ log_msg "verify integrity sum of copied files matches:\n\n\tb2sum wallet$i.descriptors $USB_DIRECTORY/wallet$i.descriptors descriptors.txt $USB_DIRECTORY/descriptors.txt"
+ confirm "copied files' integrity matches"
+
+ log_msg "shred wallet$i.descriptors:\n\n\tshred -u wallet$i.descriptors"
+ confirm "wallet$i.descriptors shredded"
+
+ log_msg "unmount usb drive:\n\n\tumount $USB_DIRECTORY"
+ confirm "usb drive unmounted"
+
+ if [[ -z "$ENCRYPTION" ]]; then
+ log_msg "close encrypted drive:\n\n\tcryptsetup luksClose $USB_PATH"
+ confirm "usb drive closed"
+
+ USB_PATH="$USB_PATH_PRE_DECRYPT"
+ fi
+
+ log_msg "eject device:\n\n\teject $USB_PATH"
+ confirm "usb drive ejected"
+ done
+}
+
validate_parameters() {
if [[ "$M" -gt "$N" ]]; then
log_error "ERROR: threshold>wallets ($M>$N)"
done
}
+wallets_interactive() {
+ log_msg "Creating $N wallets..."
+ for((i = 1; i <= $N; i++)); do
+ log_msg "create wallet$i:\n\tbitcoin-cli -named createwallet wallet_name=wallet$i descriptors=true\n"
+ confirm "confirm wallet$i was created"
+ done
+}
+
wallets_clean() {
find "$DATA_DIRECTORY" -name "wallet.dat" -exec shred -u {} \;
}
+wallets_clean_interactive() {
+ log_msg "clean up wallet files:\n\n\tfind ~/.bitcoin -name \"wallet.dat\" -exec shred -u {} \;"
+
+ confirm "wallet files deleted"
+}
+
main() {
depends
main_interactive() {
log_msg "interactive mode started..."
- log_error "ERROR: interactive mode not implemented"
- exit 1
+ log_msg "A series of commands to fully setup a cold storage solution with be output."
+ log_msg "All commands should be run in a separate shell."
+
+ bitcoin_core_start_interactive
+
+ network_off_interactive
+
+ wallets_interactive
+ multisig_create_interactive
+
+ usbs_interactive
+
+ wallets_clean_interactive
+
+ bitcoin_core_stop_interactive
+
+ log_msg "Successfully completed setup."
}
main "$@"