Skip to content

Commit eb55574

Browse files
committed
Implement signer p2wsh-p2ms
1 parent de9d5c7 commit eb55574

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

example/regtest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
f'sh(wpkh({pub2.sec().hex()}))',
1414
f'wpkh({pub1.sec().hex()})',
1515
f'wpkh({pub2.sec().hex()})',
16+
f'wsh(multi(2,{pub1.sec().hex()},{pub2.sec().hex()}))',
17+
f'wsh(multi(2,{pub2.sec().hex()},{pub1.sec().hex()}))',
1618
f'tr({pub1.sec().hex()})',
1719
f'tr({pub2.sec().hex()})',
1820
]:
@@ -25,5 +27,6 @@
2527
pabtc.rpc.generate_to_address(10, pabtc.core.Address.p2sh_p2ms(2, [pub1, pub2]))
2628
pabtc.rpc.generate_to_address(10, pabtc.core.Address.p2sh_p2wpkh(pub1.hash()))
2729
pabtc.rpc.generate_to_address(10, pabtc.core.Address.p2wpkh(pub1.hash()))
30+
pabtc.rpc.generate_to_address(10, pabtc.core.Address.p2wsh_p2ms(2, [pub1, pub2]))
2831
pabtc.rpc.generate_to_address(10, pabtc.core.Address.p2tr(pub1.tr(bytearray())))
2932
pabtc.rpc.generate_to_address(99, pabtc.core.Address.p2pkh(pub1.hash()))

pabtc/wallet.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ def json(self) -> typing.Dict:
171171
'prikey': [e.json() for e in self.prikey],
172172
'pubkey': [e.json() for e in self.pubkey],
173173
'redeem': self.redeem.hex(),
174+
'redeem_hash': self.redeem_hash.hex(),
174175
'script': self.script.hex(),
175176
'addr': self.addr,
176177
}
@@ -240,6 +241,41 @@ def sign(self, tx: pabtc.core.Transaction) -> None:
240241
e.witness = [s, self.pubkey.sec()]
241242

242243

244+
class Signerp2wshp2ms(Signer):
245+
def __init__(self, prikey: typing.List[pabtc.core.PriKey], pubkey: typing.List[pabtc.core.PubKey]) -> None:
246+
self.prikey = prikey
247+
self.pubkey = pubkey
248+
self.redeem = pabtc.core.ScriptPubKey.p2ms(len(prikey), pubkey)
249+
self.redeem_hash = pabtc.core.hashwsh(self.redeem)
250+
self.script = pabtc.core.ScriptPubKey.p2wsh(self.redeem_hash)
251+
self.addr = pabtc.core.Address.p2wsh(self.redeem_hash)
252+
253+
def __repr__(self) -> str:
254+
return json.dumps(self.json())
255+
256+
def json(self) -> typing.Dict:
257+
return {
258+
'prikey': [e.json() for e in self.prikey],
259+
'pubkey': [e.json() for e in self.pubkey],
260+
'redeem': self.redeem.hex(),
261+
'redeem_hash': self.redeem_hash.hex(),
262+
'script': self.script.hex(),
263+
'addr': self.addr,
264+
}
265+
266+
def sign(self, tx: pabtc.core.Transaction) -> None:
267+
for i, e in enumerate(tx.vin):
268+
# The op_checkmultisig opcode has a bug where it pops one extra element off the stack than it needs to.
269+
# This is why the witness includes an extra "dummy value" (00) before the signatures when using a p2ms as
270+
# the Witness Script.
271+
sig = [bytearray()]
272+
for prikey in self.prikey:
273+
s = prikey.sign_ecdsa_der(tx.digest_segwit_v0(i, pabtc.core.sighash_all, self.redeem))
274+
s.append(pabtc.core.sighash_all)
275+
sig.append(s)
276+
e.witness = sig + [self.redeem]
277+
278+
243279
class Signerp2tr(Signer):
244280
def __init__(self, prikey: pabtc.core.PriKey, merkle: bytearray) -> None:
245281
self.prikey = prikey

test/test_wallet.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ def test_wallet_transfer():
1212
),
1313
pabtc.wallet.Wallet(pabtc.wallet.Signerp2shp2wpkh(pabtc.core.PriKey(1))),
1414
pabtc.wallet.Wallet(pabtc.wallet.Signerp2wpkh(pabtc.core.PriKey(1))),
15+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2wshp2ms(
16+
[pabtc.core.PriKey(e) for e in [1, 2]],
17+
[pabtc.core.PriKey(e).pubkey() for e in [1, 2]]),
18+
),
1519
pabtc.wallet.Wallet(pabtc.wallet.Signerp2tr(pabtc.core.PriKey(1), bytearray())),
1620
]
1721
mate_list = [
@@ -22,6 +26,10 @@ def test_wallet_transfer():
2226
),
2327
pabtc.wallet.Wallet(pabtc.wallet.Signerp2shp2wpkh(pabtc.core.PriKey(2))),
2428
pabtc.wallet.Wallet(pabtc.wallet.Signerp2wpkh(pabtc.core.PriKey(2))),
29+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2wshp2ms(
30+
[pabtc.core.PriKey(e) for e in [2, 1]],
31+
[pabtc.core.PriKey(e).pubkey() for e in [2, 1]]),
32+
),
2533
pabtc.wallet.Wallet(pabtc.wallet.Signerp2tr(pabtc.core.PriKey(2), bytearray())),
2634
]
2735
for user, mate in itertools.product(user_list, mate_list):

0 commit comments

Comments
 (0)