N=7
MODE=
ENCRYPTION="luks"
+USB_PATH=
USB_DIRECTORY="$DATA_DIRECTORY/.usb"
USB_DECRYPT_NAME="cold-usb"
USB_PATH_PRE_DECRYPT=
log_info "closing encrypted usb..."
cryptsetup luksClose "$USB_DECRYPT_NAME"
USB_PATH="$USB_PATH_PRE_DECRYPT"
+ USB_PATH_PRE_DECRYPT=""
}
usb_detect() {
cp "$DATA_DIRECTORY/wallet$1.descriptors" "$USB_DIRECTORY/"
cp "$DATA_DIRECTORY/descriptors.txt" "$USB_DIRECTORY/"
- local EXPECTED="`b2sum $DATA_DIRECTORY/wallet$1.descriptors $DATA_DIRECTORY/descriptors.txt`"
- local RESULT="`b2sum $USB_DIRECTORY/wallet$1.descriptors $USB_DIRECTORY/descriptors.txt`"
+ local EXPECTED="`b2sum $DATA_DIRECTORY/wallet$1.descriptors $DATA_DIRECTORY/descriptors.txt | grep -o '^\S*'`"
+ local RESULT="`b2sum $USB_DIRECTORY/wallet$1.descriptors $USB_DIRECTORY/descriptors.txt| grep -o '^\S*'`"
if [[ "$EXPECTED" != "$RESULT" ]]; then
log_error "ERROR: failed to copy descriptors to usb correctly"
exit 1
fi
- shred "$DATA_DIRECTORY/wallet$1.descriptors"
+ shred -u "$DATA_DIRECTORY/wallet$1.descriptors"
log_info "successfully copied descriptors to usb"
}
usb_decrypt
fi
+ mkdir -p "$USB_DIRECTORY"
log_info "mounting $USB_PATH at $USB_DIRECTORY"
mount "$USB_PATH" "$USB_DIRECTORY"
}
}
wallet_change_descriptors() {
+ wallet_exists "$1"
+
local CMD="$BITCOIN_CLI -rpcwallet=wallet$1 listdescriptors | jq -j '.descriptors | map(select(.desc | startswith(\"wpkh(\"))) | map(select(.internal == true)) | map(.desc | ltrimstr(\"wpkh(\")) | .[] | split(\")\") | .[0]'"
local DESCRIPTORS=$(eval "$CMD")
echo "$DESCRIPTORS"
}
wallet_descriptors() {
+ wallet_exists "$1"
+
local CMD="$BITCOIN_CLI -rpcwallet=wallet$1 listdescriptors | jq -j '.descriptors | map(select(.desc | startswith(\"wpkh(\"))) | map(select(.internal == false)) | map(.desc | ltrimstr(\"wpkh(\")) | .[] | split(\")\") | .[0]'"
local DESCRIPTORS=$(eval "$CMD")
echo "$DESCRIPTORS"
}
wallet_dump_descriptors() {
+ wallet_exists "$1"
+
local DUMPFILE="$DATA_DIRECTORY/wallet$1.descriptors"
umask 0077
local CMD="$BITCOIN_CLI -named -rpcwallet=wallet$1 listdescriptors private=true"
log_info "dumped descriptors for wallet$1 into $DUMPFILE"
}
+wallet_exists() {
+ local CMD="$BITCOIN_CLI -named -rpcwallet=wallet$1 getwalletinfo"
+
+ set +e
+ eval "$CMD" >/dev/null 2>&1
+ set -e
+ if [[ "$?" -ne 0 ]]; then
+ log_error "ERROR: wallet$1 doesn't exist"
+ exit 1
+ fi
+}
+
wallet_load() {
if [[ ! -e "$2" ]]; then
log_error "file not found: $2"
setup_env
-test_failed
+setup_test_wallets
+
+multisig_create
+EXPECTED="87faa7387bf537283ef62654bf897c4198e3e27c7c97868cdda2e9dcf1945685dfc00722272a97f690afdb6549aaf16fe3e05f78c5fef8447b798787dd092891 .data/descriptors.txt"
+assert "$EXPECTED" "`b2sum $DATA_DIRECTORY/descriptors.txt`"
+
+M=1
+N=3
+multisig_create
+EXPECTED="a4cfdcbe25bd990e66bd6f8f86597cbeca08fb38b5fa448f7d77e9bc8de24e52c6dabfd25e6ddd1e716c6fac695af5e5d830a43e654a84c1bb51db937599f37f .data/descriptors.txt"
+assert "$EXPECTED" "`b2sum $DATA_DIRECTORY/descriptors.txt`"
+
+M=3
+N=5
+multisig_create
+EXPECTED="702de574ece926314e6ffdc2cba809549eeea97e5e3de16dfed41c462dcc84ffeb9bcd2a5b95b7aa3747c336aa6ad7beaeb7376e607a35c7cd762db9bb6b2425 .data/descriptors.txt"
+assert "$EXPECTED" "`b2sum $DATA_DIRECTORY/descriptors.txt`"
+
+M=6
+N=7
+multisig_create
+EXPECTED="48513d041c3eeaa162dde91f252dee4925eb1a2ecb8099ca6d64a121e913ca49322fea7eaf00af8a80dfc59f6764033272f81bb369b3eebcfbd19d6054863410 .data/descriptors.txt"
+assert "$EXPECTED" "`b2sum $DATA_DIRECTORY/descriptors.txt`"
clean_env
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+setup_env
+
+network_off() {
+ echo "interfaces all off..."
+}
+
+(network_off > result)
+EXPECTED="interfaces all off..."
+RESULT=$(<result)
+assert "$EXPECTED" "$RESULT"
+
+clean_env
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+set +e
+USAGE=$(usage 2>&1)
+set -e
+
+set +e
+(parse_arguments "--notanargumenthelp" > result 2>&1)
+assert "1" "$?"
+set -e
+EXPECTED="${BASH_SOURCE[0]}: illegal option -- -
+$USAGE"
+assert "$EXPECTED" "$(<result)"
+
+set +e
+(parse_arguments "--help" > result 2>&1)
+assert "1" "$?"
+set -e
+assert "$USAGE" "$(<result)"
+
+set +e
+(parse_arguments "-h" > result 2>&1)
+assert "1" "$?"
+set -e
+assert "$USAGE" "$(<result)"
+
+parse_arguments "--interactive"
+assert "interactive" "$MODE"
+MODE=""
+
+parse_arguments "-i"
+assert "interactive" "$MODE"
+
+parse_arguments "--no-encryption"
+assert "" "$ENCRYPTION"
+ENCRYPTION="luks"
+
+parse_arguments "-p"
+assert "" "$ENCRYPTION"
+
+set +e
+(parse_arguments "--threshold" > result 2>&1)
+assert "1" "$?"
+set -e
+
+EXPECTED="${BASH_SOURCE[0]}: option requires an argument -- m
+$USAGE"
+assert "$EXPECTED" "$(<result)"
+
+set +e
+(parse_arguments "--threshold" -1 > result 2>&1)
+assert "1" "$?"
+set -e
+
+EXPECTED="ERROR: invalid threshold (-1)"
+assert "$EXPECTED" "$(<result)"
+
+set +e
+(parse_arguments "--threshold" 0 > result 2>&1)
+assert "1" "$?"
+set -e
+
+EXPECTED="ERROR: invalid threshold (0)"
+assert "$EXPECTED" "$(<result)"
+
+parse_arguments "--threshold" 1
+assert "1" "$M"
+
+parse_arguments "-m" 1
+assert "1" "$M"
+
+parse_arguments "-m" 3
+assert "3" "$M"
+
+COUNT=$RANDOM
+parse_arguments "-m" "$COUNT"
+assert "$COUNT" "$M"
+
+set +e
+(parse_arguments "--wallets" > result 2>&1)
+assert "1" "$?"
+set -e
+
+EXPECTED="${BASH_SOURCE[0]}: option requires an argument -- n
+$USAGE"
+assert "$EXPECTED" "$(<result)"
+
+set +e
+(parse_arguments "--wallets" -1 > result 2>&1)
+assert "1" "$?"
+set -e
+
+EXPECTED="ERROR: invalid wallet count (-1)"
+assert "$EXPECTED" "$(<result)"
+
+set +e
+(parse_arguments "--wallets" 0 > result 2>&1)
+assert "1" "$?"
+set -e
+
+EXPECTED="ERROR: invalid wallet count (0)"
+assert "$EXPECTED" "$(<result)"
+
+parse_arguments "--wallets" 1
+assert "1" "$N"
+
+parse_arguments "-n" 7
+assert "7" "$N"
+
+COUNT=$RANDOM
+parse_arguments "-n" "$COUNT"
+assert "$COUNT" "$N"
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+cryptsetup() {
+ echo "cryptsetup..." > /dev/null
+}
+
+USB_PATH="/dev/sdzzzzz"
+usb_crypt_open > /dev/null
+
+assert "/dev/sdzzzzz" "$USB_PATH_PRE_DECRYPT"
+assert "/dev/mapper/$USB_DECRYPT_NAME" "$USB_PATH"
+
+usb_crypt_close > /dev/null
+
+assert "/dev/sdzzzzz" "$USB_PATH"
+assert "" "$USB_PATH_PRE_DECRYPT"
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+cryptsetup() {
+ echo "cryptsetup..." > /dev/null
+}
+
+USB_PATH="/dev/sdzzzzz"
+usb_crypt_open > /dev/null
+
+assert "/dev/sdzzzzz" "$USB_PATH_PRE_DECRYPT"
+assert "/dev/mapper/$USB_DECRYPT_NAME" "$USB_PATH"
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+test_failed
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+eject() {
+ echo "eject..."
+}
+
+usb_eject > /dev/null
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+cryptsetup() {
+ echo "cryptsetup..."
+}
+
+usb_encrypt > /dev/null
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+setup_env
+
+setup_test_wallets
+
+multisig_create
+mkdir -p "$USB_DIRECTORY"
+
+(usb_load 1 > result)
+EXPECTED="copying descriptors to usb...
+dumped descriptors for wallet1 into $DATA_DIRECTORY/wallet1.descriptors
+successfully copied descriptors to usb"
+assert "$EXPECTED" "$(<result)"
+
+if [[ -e "$DATA_DIRECTORY/wallet1.descriptors" ]]; then
+ test_failed
+fi
+
+clean_env
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+usb_decrypt() {
+ echo "usb_decrypt..."
+}
+
+mount() {
+ echo "mount..."
+}
+
+USB_PATH="/dev/sdzzzzzz"
+(usb_mount > result)
+EXPECTED="usb_decrypt...
+mounting $USB_PATH at $USB_DIRECTORY
+mount..."
+assert "$EXPECTED" "$(<result)"
+
+ENCRYPTION=""
+(usb_mount > result)
+EXPECTED="mounting $USB_PATH at $USB_DIRECTORY
+mount..."
+assert "$EXPECTED" "$(<result)"
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+wipefs() {
+ echo "wipefs..."
+}
+
+usb_encrypt() {
+ echo "usb_encrypt..."
+}
+
+dd() {
+ echo "dd..."
+}
+
+mkfs.ext4() {
+ echo "mkfs.ext4..."
+}
+
+USB_PATH="/dev/sdzzzzzzzz"
+(usb_setup > result)
+EXPECTED="wipefs...
+filesystem wiped from $USB_PATH
+usb_encrypt...
+zero'ing $USB_PATH
+dd...
+$USB_PATH filled with zeroes
+mkfs.ext4...
+created new filesystem on $USB_PATH"
+assert "$EXPECTED" "$(<result)"
+
+ENCRYPTION=""
+(usb_setup > result)
+EXPECTED="wipefs...
+filesystem wiped from $USB_PATH
+zero'ing $USB_PATH
+dd...
+$USB_PATH filled with zeroes
+mkfs.ext4...
+created new filesystem on $USB_PATH"
+assert "$EXPECTED" "$(<result)"
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+umount() {
+ echo "umount..."
+}
+
+usb_crypt_close() {
+ echo "usb_crypt_close..."
+}
+
+(usb_unmount > result)
+EXPECTED="unmounting $USB_DIRECTORY...
+umount...
+usb_crypt_close..."
+assert "$EXPECTED" "$(<result)"
+
+ENCRYPTION=""
+(usb_unmount > result)
+EXPECTED="unmounting $USB_DIRECTORY...
+umount..."
+assert "$EXPECTED" "$(<result)"
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+USB_PATH="/dev/sdzzzzz"
+
+usb_detect() {
+ echo "$USB_PATH"
+}
+
+usb_setup() {
+ echo "usb_setup..."
+}
+
+usb_load() {
+ echo "usb_load..."
+}
+
+usb_unmount() {
+ echo "usb_unmount..."
+}
+
+usb_eject() {
+ echo "usb_eject..."
+}
+
+(usbs > result)
+EXPECTED=$'creating primary usbs...\n'
+for((i = 1; i <= "$N"; i++)); do
+ EXPECTED+="plug in usb stick for wallet $i...
+found usb stick $USB_PATH
+usb_setup...
+usb_load...
+usb_unmount...
+usb_eject...
+"
+done
+
+EXPECTED+=$'creating backup usbs...\n'
+for((i = 1; i <= "$N"; i++)); do
+ EXPECTED+="plug in usb stick for wallet $i...
+found usb stick $USB_PATH
+usb_setup...
+usb_load...
+usb_unmount...
+usb_eject..."
+ if [[ "$i" -ne "$N" ]]; then
+ EXPECTED+="
+"
+ fi
+done
+
+assert "$EXPECTED" "$(<result)"
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
--- /dev/null
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+source setup.sh
+
+mkdir "$TEST_DIR"
+cd "$TEST_DIR"
+
+M=3
+N=2
+set +e
+(validate_parameters > result 2>&1)
+assert "1" "$?"
+set -e
+EXPECTED="ERROR: threshold>wallets (3>2)"
+assert "$EXPECTED" "$(<result)"
+
+M=1
+N=1
+set +e
+(validate_parameters > result 2>&1)
+assert "1" "$?"
+set -e
+EXPECTED=$'ERROR: no multisignature to be created (1 of 1)\nexitting...'
+assert "$EXPECTED" "$(<result)"
+
+cd ..
+rm -rf "$TEST_DIR"
+
+test_succeeded
RESULT=$(<result)
assert "$EXPECTED" "$RESULT"
+set +e
+(wallet_dump_descriptors 2 > result 2>&1)
+assert "1" "$?"
+set -e
+EXPECTED="ERROR: wallet2 doesn't exist"
+RESULT=$(<result)
+assert "$EXPECTED" "$RESULT"
+
clean_env
test_succeeded