Skip to content

Commit

Permalink
[ADD] Use multiple witnesses in multisig wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
mccwdev committed Nov 9, 2023
1 parent fe14fda commit 7bc7d94
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 9 deletions.
17 changes: 10 additions & 7 deletions bitcoinlib/wallets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1672,7 +1672,8 @@ def import_key(self, key, account_id=0, name='', network=None, purpose=84, key_t
return w.import_master_key(hdkey)
raise WalletError("Unknown key: Can only import a private key for a known public key in multisig wallets")

def _new_key_multisig(self, public_keys, name, account_id, change, cosigner_id, network, address_index):
def _new_key_multisig(self, public_keys, name, account_id, change, cosigner_id, network, address_index,
witness_type):
if self.sort_keys:
public_keys.sort(key=lambda pubk: pubk.key_public)
public_key_list = [pubk.key_public for pubk in public_keys]
Expand All @@ -1685,9 +1686,9 @@ def _new_key_multisig(self, public_keys, name, account_id, change, cosigner_id,
redeemscript = Script(script_types=['multisig'], keys=public_key_list,
sigs_required=self.multisig_n_required).serialize()
script_type = 'p2sh'
if self.witness_type == 'p2sh-segwit':
if witness_type == 'p2sh-segwit':
script_type = 'p2sh_p2wsh'
address = Address(redeemscript, encoding=self.encoding, script_type=script_type, network=network)
address = Address(redeemscript, script_type=script_type, network=network, witness_type=witness_type)
already_found_key = self._session.query(DbKey).filter_by(wallet_id=self.wallet_id,
address=address.address).first()
if already_found_key:
Expand All @@ -1701,7 +1702,7 @@ def _new_key_multisig(self, public_keys, name, account_id, change, cosigner_id,
name=name[:80], wallet_id=self.wallet_id, purpose=self.purpose, account_id=account_id,
depth=depth, change=change, address_index=address_index, parent_id=0, is_private=False, path=path,
public=address.hash_bytes, wif='multisig-%s' % address, address=address.address, cosigner_id=cosigner_id,
key_type='multisig', witness_type=self.witness_type, network_name=network)
key_type='multisig', witness_type=witness_type, network_name=network)
self._session.add(multisig_key)
self._commit()
for child_id in public_key_ids:
Expand Down Expand Up @@ -2152,7 +2153,7 @@ def key_for_path(self, path, level_offset=None, name=None, account_id=None, cosi
level_offset_key = level_offset - self.main_key.depth
witness_type = witness_type if witness_type else self.witness_type
if ((not self.main_key or not self.main_key.is_private or self.main_key.depth != 0) and
self.witness_type != witness_type):
self.witness_type != witness_type) and not self.multisig:
raise WalletError("This wallet has no private key, cannot use multiple witness types")
key_path = self.key_path
purpose = self.purpose
Expand All @@ -2172,9 +2173,11 @@ def key_for_path(self, path, level_offset=None, name=None, account_id=None, cosi
wk = wlt.main_key
else:
wk = wlt.key_for_path(path, level_offset=level_offset, account_id=account_id, name=name,
cosigner_id=cosigner_id, network=network, recreate=recreate)
cosigner_id=cosigner_id, network=network, recreate=recreate,
witness_type=witness_type)
public_keys.append(wk)
return self._new_key_multisig(public_keys, name, account_id, change, cosigner_id, network, address_index)
return self._new_key_multisig(public_keys, name, account_id, change, cosigner_id, network, address_index,
witness_type)

# Check for closest ancestor in wallet
wpath = fullpath
Expand Down
6 changes: 4 additions & 2 deletions tests/test_wallets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2570,8 +2570,10 @@ def test_wallet_segwit_multiple_networks_accounts(self):
self.assertListEqual(sorted([nw.name for nw in wallet.networks()]), networks_expected)
self.assertListEqual([k.path for k in wallet.keys_accounts(network='litecoin')],
["m/48'/2'/0'/2'", "m/48'/2'/1'/2'"])
self.assertEqual(wallet.keys(network='litecoin')[0].address, "MQNA8FYrN2fvD7SSYny3Ccvpapvsu9cVJH")
self.assertEqual(wallet.keys(network='bitcoin')[0].address, "3L6XFzC6RPeXSFpZS8v4S86v4gsNmKFnFT")
self.assertEqual(wallet.keys(network='litecoin')[0].address,
"ltc1qcu83hcdwy46dv85vmwnnfgzeu8d9arfy7kfyct52dxqcyvq2q6ds5kq2ah")
self.assertEqual(wallet.keys(network='bitcoin')[0].address,
"bc1qd0f952amxkmqc9e60u4g8w4r5a3cx22lt5vqeeyljllacxq8ezusclkwa0")


@parameterized_class(*params)
Expand Down

0 comments on commit 7bc7d94

Please sign in to comment.