ckcc-protocol/tests/test_convert2cc.py
2022-02-28 09:09:08 -05:00

176 lines
6.4 KiB
Python

import os
import re
import json
import pytest
from click.testing import CliRunner
from ckcc.cli import electrum_convert2cc
from ckcc.electrum import (
filepath_append_cc, multisig_find_target, collect_multisig_hww_keystores_from_wallet,
cc_adjust_hww_keystore, is_multisig_wallet_key, is_multisig_wallet
)
# expecting cwd to be ckcc-protocol
test_data_path = os.path.join("tests", "test_data")
encrypted_path = os.path.join(test_data_path, "encrypted")
ledger_path = os.path.join(test_data_path, "ledger")
trezor_path = os.path.join(test_data_path, "trezor.json")
bip32_path = os.path.join(test_data_path, "bip32_wallet")
a2fa_path = os.path.join(test_data_path, "2fa_wallet")
import_path = os.path.join(test_data_path, "import_wallet")
multi3of5_path = os.path.join(test_data_path, "multi3of5")
def assert_keystore(keystore):
assert keystore["hw_type"] == "coldcard"
assert "cfg" not in keystore
assert keystore["label"] == "Coldcard {}".format(keystore["root_fingerprint"])
assert keystore["soft_device_id"] is None
# as this is run without coldcard connected - no ckcc_xpub
# assert "ckcc_xpub" not in keystore
def test_multisig_find_target():
for pth in [ledger_path, trezor_path, bip32_path, a2fa_path]:
with open(pth, "r") as f:
wallet = json.loads(f.read())
with pytest.raises(RuntimeError):
multisig_find_target(
keystores=collect_multisig_hww_keystores_from_wallet(wallet),
key="hw_type", # key and value does not matter here as exc is raised before they can be used
value="ledger"
)
with open(multi3of5_path, "r") as f:
wallet = json.loads(f.read())
keystores = collect_multisig_hww_keystores_from_wallet(wallet)
assert len(keystores) == 2 # only two are hardware
for hw_type in ["trezor", "ledger"]:
key, keystore = multisig_find_target(
keystores=keystores,
key="hw_type",
value=hw_type
)
assert wallet[key] == keystore
new_keystore = cc_adjust_hww_keystore(keystore)
assert_keystore(new_keystore)
def test_filepath_append_cc():
assert filepath_append_cc("ledger_wallet") == "ledger_wallet_cc"
assert filepath_append_cc("ledger_wallet.json") == "ledger_wallet_cc.json"
assert filepath_append_cc("ledger wallet.json") == "ledger wallet_cc.json"
assert filepath_append_cc("/ledger_wallet") == "/ledger_wallet_cc"
assert filepath_append_cc("/tmp/.../ledger_wallet") == "/tmp/.../ledger_wallet_cc"
assert filepath_append_cc("/user/local/h.ledger.wallet") == "/user/local/h.ledger_cc.wallet"
def test_encrypted():
runner = CliRunner()
result = runner.invoke(electrum_convert2cc, [encrypted_path, "--dry-run"])
assert result.exit_code == 1
assert "Failed to load wallet file" in result.output
def test_dry_run():
runner = CliRunner()
for pth in [ledger_path, trezor_path]:
result = runner.invoke(electrum_convert2cc, [pth, "--dry-run"])
assert result.exit_code == 0
loaded = json.loads(result.output)
assert isinstance(loaded, dict)
keystore = loaded["keystore"]
assert_keystore(keystore)
def test_outfile():
runner = CliRunner()
for pth, name in zip([ledger_path, trezor_path], ["ledger00", "trezor00"]):
outfile_path = os.path.join(test_data_path, name)
result = runner.invoke(electrum_convert2cc, [pth, "-o", outfile_path])
assert result.exit_code == 0
assert "New wallet file created: tests/test_data/{}\n".format(name) == result.output
with open(outfile_path, "r") as f:
res = json.loads(f.read())
assert_keystore(res["keystore"])
os.remove(outfile_path)
def test_outfile_same_as_file():
runner = CliRunner()
for pth in [ledger_path, trezor_path]:
result = runner.invoke(electrum_convert2cc, [pth, "-o", pth])
assert result.exit_code == 1
assert "'FILE' and '--outfile' cannot be the same\n" == result.output
def test_no_options():
runner = CliRunner()
for pth in [ledger_path, trezor_path]:
result = runner.invoke(electrum_convert2cc, [pth])
new_pth = filepath_append_cc(pth)
assert result.exit_code == 0
assert "New wallet file created: {}\n".format(new_pth) == result.output
with open(new_pth, "r") as f:
res = json.loads(f.read())
assert_keystore(res["keystore"])
os.remove(new_pth)
def test_not_hww_wallet():
runner = CliRunner()
for pth in [bip32_path]:
result = runner.invoke(electrum_convert2cc, [pth])
assert result.exit_code == 1
assert result.output == "convert2cc failed: Not a hardware wallet type\n"
def test_not_standard_wallet():
runner = CliRunner()
for name, pth in [("2fa", a2fa_path), ("imported", import_path)]:
result = runner.invoke(electrum_convert2cc, [pth])
assert result.exit_code == 1
assert result.output == "convert2cc failed: Unsupported wallet type: {}\n".format(name)
def test_is_multisig_wallet():
valid = ["2of3", "2of2", "35of50"]
for val in valid:
val = {"wallet_type": val}
assert is_multisig_wallet(val) is True
invalid = ["a2of3", "2ofo3", "2of3a", "aaa", "x", "of"]
for val in invalid:
val = {"wallet_type": val}
assert is_multisig_wallet(val) is False
def test_is_multisig_wallet_key():
valid = ["x1/", "x2/", "x30/", "x156/"]
for val in valid:
assert is_multisig_wallet_key(val) is True
invalid = ["1/", "x/", "xxxx", "aaa", "x", "of", "ax1/", "x1/a", "x1a/"]
for val in invalid:
assert is_multisig_wallet_key(val) is False
def test_multisig():
runner = CliRunner()
result = runner.invoke(electrum_convert2cc, [multi3of5_path, "-k", "hw_type", "-v", "ledger"])
assert result.exit_code == 0
new_pth = filepath_append_cc(multi3of5_path)
assert "New wallet file created: {}\n".format(new_pth) == result.output
with open(new_pth, "r") as f:
res = json.loads(f.read())
# ledger is x2/ entry
assert_keystore(res["x2/"])
# make sure other entries are unchanged
assert res["x3/"]["hw_type"] == "trezor"
os.remove(new_pth)
result = runner.invoke(electrum_convert2cc, [multi3of5_path, "-k", "root_fingerprint", "-v", "7633218e"])
assert result.exit_code == 1
assert "Found 2 keystores" in result.output