From 151d3585a90e785676150c7f596416fe1b23a757 Mon Sep 17 00:00:00 2001 From: Chris Sulmone Date: Fri, 26 Jan 2018 01:25:47 -0600 Subject: [PATCH] Started work on shielded wallet --- lib/base_wizard.py | 9 +++++++++ lib/bitcoin.py | 5 +++++ lib/wallet.py | 12 ++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/base_wizard.py b/lib/base_wizard.py index 268c157d..30fc1146 100644 --- a/lib/base_wizard.py +++ b/lib/base_wizard.py @@ -85,6 +85,7 @@ class BaseWizard(object): ('2fa', _("Wallet with two-factor authentication")), ('multisig', _("Multi-signature wallet")), ('imported', _("Import Zclassic addresses or private keys")), + ('shielded', _("Create a shielded wallet")), ] choices = [pair for pair in wallet_kinds if pair[0] in wallet_types] self.choice_dialog(title=title, message=message, choices=choices, run_next=self.on_wallet_type) @@ -105,6 +106,8 @@ class BaseWizard(object): action = self.storage.get_action() elif choice == 'imported': action = 'import_addresses_or_keys' + elif choice == 'shielded': + action = 'import_shielded' self.run(action) def choose_multisig(self): @@ -146,6 +149,12 @@ class BaseWizard(object): self.add_xpub_dialog(title=title, message=message, run_next=self.on_import, is_valid=v, allow_multi=True) + def import_shielded(self): + title = _("Import Zclassic Private Keys") + message = _("Enter a list of Zclassic private keys.") + self.add_xpub_dialog(title=title, message=message, run_next=self.on_import, + is_valid=keystore.is_private_key_list, allow_multi=True) + def on_import(self, text): if keystore.is_address_list(text): self.wallet = Imported_Wallet(self.storage) diff --git a/lib/bitcoin.py b/lib/bitcoin.py index 5db6b511..87ab3064 100644 --- a/lib/bitcoin.py +++ b/lib/bitcoin.py @@ -80,6 +80,7 @@ class NetworkConstants: cls.ADDRTYPE_P2PKH = [0x1C, 0xB8] cls.ADDRTYPE_P2SH = [0x1C, 0xBD] cls.ADDRTYPE_SHIELDED = [0x16, 0x9A] + cls.SHIELDED_SPEND = [0xAB, 0x36] cls.SEGWIT_HRP = "bc" #TODO zcl has no segwit cls.GENESIS = "0007104ccda289427919efc39dc9e4d499804b7bebc22df55f8b834301260602" cls.DEFAULT_PORTS = {'t': '50001', 's': '50002'} @@ -99,6 +100,7 @@ class NetworkConstants: cls.ADDRTYPE_P2PKH = [0x1D, 0x25] cls.ADDRTYPE_P2SH = [0x1C, 0xBA] cls.ADDRTYPE_SHIELDED [0x16, 0xB6] + cls.SHIELDED_SPEND = [0xAC, 0x08] cls.SEGWIT_HRP = "tb" #TODO zcl has no segwit cls.GENESIS = "03e1c4bb705c871bf9bfda3e74b7f8f86bff267993c215a89d5795e3708e5e1f" cls.DEFAULT_PORTS = {'t': '51001', 's': '51002'} @@ -626,6 +628,9 @@ def deserialize_privkey(key): if is_minikey(key): return 'p2pkh', minikey_to_private_key(key), True elif vch: + if [vch[0], vch[1]] == NetworkConstants.SHIELDED_SPEND: + assert len(vch) == 34 + return 'shielded', vch[2:34], False txin_type = inv_dict(SCRIPT_TYPES)[vch[0] - NetworkConstants.WIF_PREFIX] assert len(vch) in [33, 34] compressed = len(vch) == 34 diff --git a/lib/wallet.py b/lib/wallet.py index 3a3ed8f8..83c734cc 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -1527,6 +1527,7 @@ class Imported_Wallet(Simple_Wallet): def get_public_key(self, address): return self.addresses[address].get('pubkey') +# TODO handle importing of shielded private keys see https://raw.githubusercontent.com/zcash/zips/master/protocol/protocol.pdf page 17 def import_private_key(self, sec, pw, redeem_script=None): try: txin_type, pubkey = self.keystore.import_privkey(sec, pw) @@ -1583,6 +1584,12 @@ class Imported_Wallet(Simple_Wallet): if v.get('pubkey') == pubkey: return addr +class Shielded_Wallet(PrintError): + wallet_type = 'shielded' + + def __init__(self, storage): + self.storage = storage + class Deterministic_Wallet(Abstract_Wallet): def __init__(self, storage): @@ -1837,7 +1844,7 @@ class Multisig_Wallet(Deterministic_Wallet): txin['num_sig'] = self.m -wallet_types = ['standard', 'multisig', 'imported'] +wallet_types = ['standard', 'multisig', 'imported', 'shielded'] def register_wallet_type(category): wallet_types.append(category) @@ -1846,7 +1853,8 @@ wallet_constructors = { 'standard': Standard_Wallet, 'old': Standard_Wallet, 'xpub': Standard_Wallet, - 'imported': Imported_Wallet + 'imported': Imported_Wallet, + 'shielded': Shielded_Wallet } def register_constructor(wallet_type, constructor):