Skip to content

Commit

Permalink
If ypub was used in createwatchonly, create BTC_Watchonly_P2SH_P2…
Browse files Browse the repository at this point in the history
…WPKH wallet instead
  • Loading branch information
Wukong committed Dec 10, 2021
1 parent f90a760 commit 67700e1
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
31 changes: 30 additions & 1 deletion jmclient/jmclient/cryptoengine.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# make existing wallets unsable.
TYPE_P2PKH, TYPE_P2SH_P2WPKH, TYPE_P2WPKH, TYPE_P2SH_M_N, TYPE_TIMELOCK_P2WSH, \
TYPE_SEGWIT_WALLET_FIDELITY_BONDS, TYPE_WATCHONLY_FIDELITY_BONDS, \
TYPE_WATCHONLY_TIMELOCK_P2WSH, TYPE_WATCHONLY_P2WPKH, TYPE_P2WSH = range(10)
TYPE_WATCHONLY_TIMELOCK_P2WSH, TYPE_WATCHONLY_P2SH_P2WPKH, TYPE_WATCHONLY_P2WPKH, TYPE_P2WSH = range(11)
NET_MAINNET, NET_TESTNET, NET_SIGNET = range(3)
NET_MAP = {'mainnet': NET_MAINNET, 'testnet': NET_TESTNET,
'signet': NET_SIGNET}
Expand Down Expand Up @@ -412,6 +412,34 @@ def sign_transaction(cls, tx, index, privkey, amount,
hashcode=btc.SIGHASH_ALL, **kwargs):
raise RuntimeError("Cannot spend from watch-only wallets")

class BTC_Watchonly_P2SH_P2WPKH(BTC_P2SH_P2WPKH):

@classmethod
def derive_bip32_privkey(cls, master_key, path):
return BTC_Watchonly_Timelocked_P2WSH.derive_bip32_privkey(master_key, path)

@classmethod
def privkey_to_wif(cls, privkey_locktime):
return BTC_Watchonly_Timelocked_P2WSH.privkey_to_wif(privkey_locktime)

@staticmethod
def privkey_to_pubkey(privkey):
#in watchonly wallets there are no privkeys, so functions
# like _get_key_from_path() actually return pubkeys and
# this function is a noop
return privkey

@classmethod
def derive_bip32_pub_export(cls, master_key, path):
return super(BTC_Watchonly_P2SH_P2WPKH, cls).derive_bip32_pub_export(
master_key, BTC_Watchonly_Timelocked_P2WSH.get_watchonly_path(path))

@classmethod
def sign_transaction(cls, tx, index, privkey, amount,
hashcode=btc.SIGHASH_ALL, **kwargs):
raise RuntimeError("Cannot spend from watch-only wallets")


class BTC_Watchonly_P2WPKH(BTC_P2WPKH):

@classmethod
Expand Down Expand Up @@ -445,6 +473,7 @@ def sign_transaction(cls, tx, index, privkey, amount,
TYPE_P2WPKH: BTC_P2WPKH,
TYPE_TIMELOCK_P2WSH: BTC_Timelocked_P2WSH,
TYPE_WATCHONLY_TIMELOCK_P2WSH: BTC_Watchonly_Timelocked_P2WSH,
TYPE_WATCHONLY_P2SH_P2WPKH: BTC_Watchonly_P2SH_P2WPKH,
TYPE_WATCHONLY_P2WPKH: BTC_Watchonly_P2WPKH,
TYPE_SEGWIT_WALLET_FIDELITY_BONDS: BTC_P2WPKH
}
12 changes: 11 additions & 1 deletion jmclient/jmclient/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
select, NotEnoughFundsException
from .cryptoengine import TYPE_P2PKH, TYPE_P2SH_P2WPKH, TYPE_P2WSH,\
TYPE_P2WPKH, TYPE_TIMELOCK_P2WSH, TYPE_SEGWIT_WALLET_FIDELITY_BONDS,\
TYPE_WATCHONLY_FIDELITY_BONDS, TYPE_WATCHONLY_TIMELOCK_P2WSH, TYPE_WATCHONLY_P2WPKH,\
TYPE_WATCHONLY_FIDELITY_BONDS, TYPE_WATCHONLY_TIMELOCK_P2WSH,\
TYPE_WATCHONLY_P2SH_P2WPKH, TYPE_WATCHONLY_P2WPKH,\
ENGINES, detect_script_type
from .support import get_random_bytes
from . import mn_encode, mn_decode
Expand Down Expand Up @@ -2594,6 +2595,14 @@ def _verify_entropy(cls, ent):
def _derive_bip32_master_key(cls, master_entropy):
return btc.bip32_deserialize(master_entropy.decode())

class SegwitLegacyWatchonlyWallet(WatchonlyMixin, BIP49Wallet):
TYPE = TYPE_WATCHONLY_P2SH_P2WPKH
_ENGINE = ENGINES[TYPE_WATCHONLY_P2SH_P2WPKH]

def _get_key_ident(self):
return sha256(sha256(
self.get_bip32_pub_export(0, self.BIP32_EXT_ID).encode('ascii')).digest())\
.digest()[:3]

class SegwitWatchonlyWallet(WatchonlyMixin, BIP84Wallet):
TYPE = TYPE_WATCHONLY_P2WPKH
Expand Down Expand Up @@ -2623,6 +2632,7 @@ def _get_bip32_export_path(self, mixdepth=None, address_type=None):
LegacyWallet.TYPE: LegacyWallet,
SegwitLegacyWallet.TYPE: SegwitLegacyWallet,
SegwitWallet.TYPE: SegwitWallet,
SegwitLegacyWatchonlyWallet.TYPE: SegwitLegacyWatchonlyWallet,
SegwitWatchonlyWallet.TYPE: SegwitWatchonlyWallet,
SegwitWalletFidelityBonds.TYPE: SegwitWalletFidelityBonds,
FidelityBondWatchonlyWallet.TYPE: FidelityBondWatchonlyWallet
Expand Down
11 changes: 8 additions & 3 deletions jmclient/jmclient/wallet_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
VolatileStorage, StoragePasswordError, is_segwit_mode, SegwitLegacyWallet,
LegacyWallet, SegwitWallet, FidelityBondMixin, FidelityBondWatchonlyWallet,
is_native_segwit_mode, load_program_config, add_base_options, check_regtest)
from jmclient.wallet import SegwitWatchonlyWallet, WatchonlyMixin
from jmclient.wallet import SegwitLegacyWatchonlyWallet, SegwitWatchonlyWallet, WatchonlyMixin
from jmclient.wallet_service import WalletService
from jmbase.support import (get_password, jmprint, EXIT_FAILURE,
EXIT_ARGERROR, utxo_to_utxostr, hextobin, bintohex,
Expand Down Expand Up @@ -1345,9 +1345,14 @@ def wallet_createwatchonly(wallet_root_path, master_pub_key, is_fidelity_bond_wa
max_mixdepth=FidelityBondMixin.FIDELITY_BOND_MIXDEPTH,
wallet_cls=FidelityBondWatchonlyWallet, entropy=entropy)
else:
if master_pub_key.startswith('ypub'):
wallet_cls = SegwitLegacyWatchonlyWallet
else:
wallet_cls = SegwitWatchonlyWallet

create_wallet(wallet_path, password,
max_mixdepth=WatchonlyMixin.WATCH_ONLY_MIXDEPTH,
wallet_cls=SegwitWatchonlyWallet, entropy=entropy)
max_mixdepth=WatchonlyMixin.WATCH_ONLY_MIXDEPTH,
wallet_cls=wallet_cls, entropy=entropy)
return "Done"

def get_configured_wallet_type(support_fidelity_bonds):
Expand Down

0 comments on commit 67700e1

Please sign in to comment.