Skip to content

Commit 1481983

Browse files
committed
Rename signer's name
1 parent 6e06d06 commit 1481983

File tree

4 files changed

+91
-106
lines changed

4 files changed

+91
-106
lines changed

example/taproot.py

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
)
1212

1313

14-
class Tp2trp2pk:
14+
class Signerp2trp2pk(pabtc.wallet.Signer):
1515
def __init__(self, pubkey: pabtc.core.PubKey) -> None:
1616
self.pubkey = pubkey
1717
p2tr_pubkey = bytearray(pabtc.taproot.pubkey_tweak(pubkey.pt(), mast.hash).x.n.to_bytes(32))
@@ -31,18 +31,14 @@ def sign(self, tx: pabtc.core.Transaction) -> None:
3131
for i, e in enumerate(tx.vin):
3232
m = tx.digest_segwit_v1(i, pabtc.core.sighash_all, mast.l.script)
3333
s = pabtc.core.PriKey(2).sign_schnorr(m) + bytearray([pabtc.core.sighash_all])
34-
e.witness[0] = s
35-
36-
def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
37-
assert isinstance(mast.l, pabtc.core.TapLeaf)
38-
return pabtc.core.TxIn(op, bytearray(), 0xffffffff, [
39-
bytearray(65),
40-
mast.l.script,
41-
bytearray([self.prefix]) + self.pubkey.sec()[1:] + mast.r.hash,
42-
])
34+
e.witness = [
35+
s,
36+
mast.l.script,
37+
bytearray([self.prefix]) + self.pubkey.sec()[1:] + mast.r.hash,
38+
]
4339

4440

45-
class Tp2trp2ms:
41+
class Signerp2trp2ms(pabtc.wallet.Signer):
4642
def __init__(self, pubkey: pabtc.core.PubKey) -> None:
4743
self.pubkey = pubkey
4844
p2tr_pubkey = bytearray(pabtc.taproot.pubkey_tweak(pubkey.pt(), mast.hash).x.n.to_bytes(32))
@@ -61,23 +57,18 @@ def sign(self, tx: pabtc.core.Transaction) -> None:
6157
assert isinstance(mast.r, pabtc.core.TapLeaf)
6258
for i, e in enumerate(tx.vin):
6359
m = tx.digest_segwit_v1(i, pabtc.core.sighash_all, mast.r.script)
64-
e.witness[0] = pabtc.core.PriKey(4).sign_schnorr(m) + bytearray([pabtc.core.sighash_all])
65-
e.witness[1] = pabtc.core.PriKey(3).sign_schnorr(m) + bytearray([pabtc.core.sighash_all])
66-
67-
def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
68-
assert isinstance(mast.r, pabtc.core.TapLeaf)
69-
return pabtc.core.TxIn(op, bytearray(), 0xffffffff, [
70-
bytearray(65),
71-
bytearray(65),
72-
mast.r.script,
73-
bytearray([self.prefix]) + self.pubkey.sec()[1:] + mast.l.hash,
74-
])
60+
e.witness = [
61+
pabtc.core.PriKey(4).sign_schnorr(m) + bytearray([pabtc.core.sighash_all]),
62+
pabtc.core.PriKey(3).sign_schnorr(m) + bytearray([pabtc.core.sighash_all]),
63+
mast.r.script,
64+
bytearray([self.prefix]) + self.pubkey.sec()[1:] + mast.l.hash,
65+
]
7566

7667

77-
mate = pabtc.wallet.Wallet(pabtc.wallet.Tp2pkh(1))
68+
mate = pabtc.wallet.Wallet(pabtc.wallet.Signerp2pkh(1))
7869
pabtc.rpc.generate_to_address(10, mate.addr)
7970

80-
user_p2tr_signer = pabtc.wallet.Tp2tr(1, mast.hash)
71+
user_p2tr_signer = pabtc.wallet.Signerp2tr(1, mast.hash)
8172
user_p2tr = pabtc.wallet.Wallet(user_p2tr_signer)
8273
pabtc.rpc.import_descriptors([{
8374
'desc': pabtc.rpc.get_descriptor_info(f'addr({user_p2tr.addr})')['descriptor'],
@@ -95,7 +86,7 @@ def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
9586
# Spending by script path: pay to public key.
9687
mate.transfer(user_p2tr.script, 1 * pabtc.denomination.bitcoin)
9788
assert user_p2tr.balance() == pabtc.denomination.bitcoin
98-
user_p2pk = pabtc.wallet.Wallet(Tp2trp2pk(user_p2tr_signer.pubkey))
89+
user_p2pk = pabtc.wallet.Wallet(Signerp2trp2pk(user_p2tr_signer.pubkey))
9990
print('main: spending by script path p2pk')
10091
user_p2pk.transfer_all(mate.script)
10192
assert user_p2tr.balance() == 0
@@ -104,7 +95,7 @@ def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
10495
# Spending by script path: pay to 2-of-2 multisig script.
10596
mate.transfer(user_p2tr.script, 1 * pabtc.denomination.bitcoin)
10697
assert user_p2tr.balance() == pabtc.denomination.bitcoin
107-
user_p2ms = pabtc.wallet.Wallet(Tp2trp2ms(user_p2tr_signer.pubkey))
98+
user_p2ms = pabtc.wallet.Wallet(Signerp2trp2ms(user_p2tr_signer.pubkey))
10899
print('main: spending by script path p2ms')
109100
user_p2ms.transfer_all(mate.script)
110101
assert user_p2tr.balance() == 0

example/transfer.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@
2121
accept_script = pabtc.core.ScriptPubKey.address(args.to)
2222
accept_value = int(args.value * pabtc.denomination.bitcoin)
2323
prikey = int(args.prikey, 0)
24-
wallet = pabtc.wallet.Wallet(pabtc.wallet.Tp2pkh(prikey))
24+
wallet = pabtc.wallet.Wallet(pabtc.wallet.Signerp2pkh(prikey))
2525
if args.script_type == 'p2pkh':
26-
wallet = pabtc.wallet.Wallet(pabtc.wallet.Tp2pkh(prikey))
26+
wallet = pabtc.wallet.Wallet(pabtc.wallet.Signerp2pkh(prikey))
2727
if args.script_type == 'p2sh-p2wpkh':
28-
wallet = pabtc.wallet.Wallet(pabtc.wallet.Tp2shp2wpkh(prikey))
28+
wallet = pabtc.wallet.Wallet(pabtc.wallet.Signerp2shp2wpkh(prikey))
2929
if args.script_type == 'p2wpkh':
30-
wallet = pabtc.wallet.Wallet(pabtc.wallet.Tp2wpkh(prikey))
30+
wallet = pabtc.wallet.Wallet(pabtc.wallet.Signerp2wpkh(prikey))
3131
if args.script_type == 'p2tr':
32-
wallet = pabtc.wallet.Wallet(pabtc.wallet.Tp2tr(prikey, bytearray()))
32+
wallet = pabtc.wallet.Wallet(pabtc.wallet.Signerp2tr(prikey, bytearray()))
3333
txid = wallet.transfer(accept_script, accept_value)
3434
print(f'0x{txid.hex()}')

pabtc/wallet.py

Lines changed: 59 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import abc
12
import json
23
import pabtc.core
34
import pabtc.denomination
@@ -110,12 +111,29 @@ def unspent(self, addr: str) -> typing.List[Utxo]:
110111
raise Exception('unreachable')
111112

112113

113-
class Tp2pkh:
114+
class Signer(abc.ABC):
115+
# Signer provides the functionality to sign a transaction.
116+
117+
@abc.abstractmethod
118+
def __init__(self) -> None:
119+
self.script: bytearray
120+
self.addr: str
121+
122+
def json(self) -> typing.Dict:
123+
return {}
124+
125+
@abc.abstractmethod
126+
def sign(self, tx: pabtc.core.Transaction) -> None:
127+
# Sign the transaction in place.
128+
pass
129+
130+
131+
class Signerp2pkh(Signer):
114132
def __init__(self, prikey: int) -> None:
115133
self.prikey = pabtc.core.PriKey(prikey)
116134
self.pubkey = self.prikey.pubkey()
135+
self.script = pabtc.core.ScriptPubKey.p2pkh(self.pubkey.hash())
117136
self.addr = pabtc.core.Address.p2pkh(self.pubkey.hash())
118-
self.script = pabtc.core.ScriptPubKey.address(self.addr)
119137

120138
def __repr__(self) -> str:
121139
return json.dumps(self.json())
@@ -124,30 +142,26 @@ def json(self) -> typing.Dict:
124142
return {
125143
'prikey': self.prikey.json(),
126144
'pubkey': self.pubkey.json(),
127-
'addr': self.addr,
128145
'script': self.script.hex(),
146+
'addr': self.addr,
129147
}
130148

131149
def sign(self, tx: pabtc.core.Transaction) -> None:
132150
for i, e in enumerate(tx.vin):
133-
m = tx.digest_legacy(i, pabtc.core.sighash_all, e.out_point.load().script_pubkey)
151+
m = tx.digest_legacy(i, pabtc.core.sighash_all, self.script)
134152
s = self.prikey.sign_ecdsa_der(m)
135153
s.append(pabtc.core.sighash_all)
136154
e.script_sig = pabtc.core.ScriptSig.p2pkh(s, self.pubkey)
137155

138-
def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
139-
return pabtc.core.TxIn(op, bytearray(107), 0xffffffff, [])
140-
141156

142-
class Tp2shp2ms:
143-
# Multi-signature: See https://en.bitcoin.it/wiki/Multi-signature.
144-
def __init__(self, m: int, pubkey: typing.List[pabtc.core.PubKey], prikey: typing.List[int]) -> None:
145-
self.m = m
157+
class Signerp2shp2ms(Signer):
158+
def __init__(self, pubkey: typing.List[pabtc.core.PubKey], prikey: typing.List[int]) -> None:
146159
self.prikey = [pabtc.core.PriKey(e) for e in prikey]
147160
self.pubkey = pubkey
148-
self.redeem = pabtc.core.ScriptPubKey.p2ms(self.m, pubkey)
149-
self.addr = pabtc.core.Address.p2sh(pabtc.core.hash160(self.redeem))
150-
self.script = pabtc.core.ScriptPubKey.address(self.addr)
161+
self.redeem = pabtc.core.ScriptPubKey.p2ms(len(prikey), pubkey)
162+
self.redeem_hash = pabtc.core.hash160(self.redeem)
163+
self.script = pabtc.core.ScriptPubKey.p2sh(self.redeem_hash)
164+
self.addr = pabtc.core.Address.p2sh(self.redeem_hash)
151165

152166
def __repr__(self) -> str:
153167
return json.dumps(self.json())
@@ -156,8 +170,9 @@ def json(self) -> typing.Dict:
156170
return {
157171
'prikey': [e.json() for e in self.prikey],
158172
'pubkey': [e.json() for e in self.pubkey],
159-
'addr': self.addr,
173+
'redeem': self.redeem.hex(),
160174
'script': self.script.hex(),
175+
'addr': self.addr,
161176
}
162177

163178
def sign(self, tx: pabtc.core.Transaction) -> None:
@@ -167,19 +182,15 @@ def sign(self, tx: pabtc.core.Transaction) -> None:
167182
s = prikey.sign_ecdsa_der(tx.digest_legacy(i, pabtc.core.sighash_all, self.redeem))
168183
s.append(pabtc.core.sighash_all)
169184
sig.append(s)
170-
e.script_sig = pabtc.core.ScriptSig.p2sh_p2ms(sig, self.m, self.pubkey)
171-
172-
def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
173-
script_sig = pabtc.core.ScriptSig.p2sh_p2ms([bytearray(72)] * len(self.prikey), self.m, self.pubkey)
174-
return pabtc.core.TxIn(op, script_sig, 0xffffffff, [])
185+
e.script_sig = pabtc.core.ScriptSig.p2sh_p2ms(sig, len(self.prikey), self.pubkey)
175186

176187

177-
class Tp2shp2wpkh:
188+
class Signerp2shp2wpkh(Signer):
178189
def __init__(self, prikey: int) -> None:
179190
self.prikey = pabtc.core.PriKey(prikey)
180191
self.pubkey = self.prikey.pubkey()
192+
self.script = pabtc.core.ScriptPubKey.p2sh_p2wpkh(self.pubkey.hash())
181193
self.addr = pabtc.core.Address.p2sh_p2wpkh(self.pubkey.hash())
182-
self.script = pabtc.core.ScriptPubKey.address(self.addr)
183194

184195
def __repr__(self) -> str:
185196
return json.dumps(self.json())
@@ -188,32 +199,26 @@ def json(self) -> typing.Dict:
188199
return {
189200
'prikey': self.prikey.json(),
190201
'pubkey': self.pubkey.json(),
191-
'addr': self.addr,
192202
'script': self.script.hex(),
203+
'addr': self.addr,
193204
}
194205

195206
def sign(self, tx: pabtc.core.Transaction) -> None:
196207
# See: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh-nested-in-bip16-p2sh
197-
pubkey_hash = pabtc.core.hash160(self.pubkey.sec())
198-
script_code = pabtc.core.ScriptPubKey.p2pkh(pubkey_hash)
199-
script_sig = pabtc.core.ScriptSig.p2sh_p2wpkh(self.pubkey.hash())
200208
for i, e in enumerate(tx.vin):
201-
e.script_sig = script_sig
202-
s = self.prikey.sign_ecdsa_der(tx.digest_segwit_v0(i, pabtc.core.sighash_all, script_code))
209+
e.script_sig = pabtc.core.ScriptSig.p2sh_p2wpkh(self.pubkey.hash())
210+
m = tx.digest_segwit_v0(i, pabtc.core.sighash_all, pabtc.core.ScriptPubKey.p2pkh(self.pubkey.hash()))
211+
s = self.prikey.sign_ecdsa_der(m)
203212
s.append(pabtc.core.sighash_all)
204-
e.witness[0] = s
205-
e.witness[1] = self.pubkey.sec()
206-
207-
def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
208-
return pabtc.core.TxIn(op, bytearray(23), 0xffffffff, [bytearray(72), bytearray(33)])
213+
e.witness = [s, self.pubkey.sec()]
209214

210215

211-
class Tp2wpkh:
216+
class Signerp2wpkh(Signer):
212217
def __init__(self, prikey: int) -> None:
213218
self.prikey = pabtc.core.PriKey(prikey)
214219
self.pubkey = self.prikey.pubkey()
220+
self.script = pabtc.core.ScriptPubKey.p2wpkh(self.pubkey.hash())
215221
self.addr = pabtc.core.Address.p2wpkh(self.pubkey.hash())
216-
self.script = pabtc.core.ScriptPubKey.address(self.addr)
217222

218223
def __repr__(self) -> str:
219224
return json.dumps(self.json())
@@ -222,32 +227,28 @@ def json(self) -> typing.Dict:
222227
return {
223228
'prikey': self.prikey.json(),
224229
'pubkey': self.pubkey.json(),
225-
'addr': self.addr,
226230
'script': self.script.hex(),
231+
'addr': self.addr,
227232
}
228233

229234
def sign(self, tx: pabtc.core.Transaction) -> None:
230235
# See: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh
231-
pubkey_hash = pabtc.core.hash160(self.pubkey.sec())
232-
script_code = pabtc.core.ScriptPubKey.p2pkh(pubkey_hash)
233236
for i, e in enumerate(tx.vin):
234-
s = self.prikey.sign_ecdsa_der(tx.digest_segwit_v0(i, pabtc.core.sighash_all, script_code))
237+
m = tx.digest_segwit_v0(i, pabtc.core.sighash_all, pabtc.core.ScriptPubKey.p2pkh(self.pubkey.hash()))
238+
s = self.prikey.sign_ecdsa_der(m)
235239
s.append(pabtc.core.sighash_all)
236-
e.witness[0] = s
237-
e.witness[1] = self.pubkey.sec()
238-
239-
def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
240-
return pabtc.core.TxIn(op, bytearray(), 0xffffffff, [bytearray(72), bytearray(33)])
240+
e.witness = [s, self.pubkey.sec()]
241241

242242

243-
class Tp2tr:
244-
def __init__(self, prikey: int, root: bytearray) -> None:
243+
class Signerp2tr(Signer):
244+
def __init__(self, prikey: int, merkle: bytearray) -> None:
245245
self.prikey = pabtc.core.PriKey(prikey)
246246
self.pubkey = self.prikey.pubkey()
247-
p2tr_pubkey = bytearray(pabtc.taproot.pubkey_tweak(self.pubkey.pt(), root).x.n.to_bytes(32))
248-
self.addr = pabtc.core.Address.p2tr(p2tr_pubkey)
249-
self.root = root
250-
self.script = pabtc.core.ScriptPubKey.address(self.addr)
247+
self.merkle = merkle
248+
self.prikey_tweak = pabtc.core.PriKey.fr_decode(pabtc.taproot.prikey_tweak(self.prikey.fr(), self.merkle))
249+
self.pubkey_tweak = pabtc.core.PubKey.pt_decode(pabtc.taproot.pubkey_tweak(self.pubkey.pt(), merkle))
250+
self.script = pabtc.core.ScriptPubKey.p2tr(bytearray(self.pubkey_tweak.x.to_bytes(32)))
251+
self.addr = pabtc.core.Address.p2tr(bytearray(self.pubkey_tweak.x.to_bytes(32)))
251252

252253
def __repr__(self) -> str:
253254
return json.dumps(self.json())
@@ -256,32 +257,25 @@ def json(self) -> typing.Dict:
256257
return {
257258
'prikey': self.prikey.json(),
258259
'pubkey': self.pubkey.json(),
259-
'addr': self.addr,
260-
'root': self.root.hex(),
260+
'merkle': self.merkle.hex(),
261261
'script': self.script.hex(),
262+
'addr': self.addr,
262263
}
263264

264265
def sign(self, tx: pabtc.core.Transaction) -> None:
265266
# See: https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
266-
prikey = pabtc.core.PriKey.fr_decode(pabtc.taproot.prikey_tweak(self.prikey.fr(), self.root))
267267
for i, e in enumerate(tx.vin):
268268
m = tx.digest_segwit_v1(i, pabtc.core.sighash_all, bytearray())
269-
s = prikey.sign_schnorr(m) + bytearray([pabtc.core.sighash_all])
270-
e.witness[0] = s
271-
272-
def txin(self, op: pabtc.core.OutPoint) -> pabtc.core.TxIn:
273-
return pabtc.core.TxIn(op, bytearray(), 0xffffffff, [bytearray(65)])
274-
275-
276-
T = Tp2pkh | Tp2shp2ms | Tp2shp2wpkh | Tp2wpkh | Tp2tr | typing.Any
269+
s = self.prikey_tweak.sign_schnorr(m) + bytearray([pabtc.core.sighash_all])
270+
e.witness = [s]
277271

278272

279273
class Wallet:
280-
def __init__(self, signer: T) -> None:
274+
def __init__(self, signer: Signer) -> None:
281275
self.signer = signer
282-
self.addr = self.signer.addr
283276
self.script = self.signer.script
284277
self.search = Searcher()
278+
self.addr = self.signer.addr
285279

286280
def __repr__(self) -> str:
287281
return json.dumps(self.json())
@@ -304,7 +298,7 @@ def transfer(self, script: bytearray, value: int) -> bytearray:
304298
tx.vout.append(pabtc.core.TxOut(accept_value, accept_script))
305299
tx.vout.append(pabtc.core.TxOut(change_value, change_script))
306300
for utxo in self.unspent():
307-
txin = self.signer.txin(utxo.out_point)
301+
txin = pabtc.core.TxIn(utxo.out_point, bytearray(), 0xffffffff, [])
308302
tx.vin.append(txin)
309303
sender_value += utxo.out.value
310304
change_value = sender_value - accept_value - tx.vbytes() * fr
@@ -328,7 +322,7 @@ def transfer_all(self, script: bytearray) -> bytearray:
328322
tx = pabtc.core.Transaction(2, [], [], 0)
329323
tx.vout.append(pabtc.core.TxOut(accept_value, accept_script))
330324
for utxo in self.unspent():
331-
txin = self.signer.txin(utxo.out_point)
325+
txin = pabtc.core.TxIn(utxo.out_point, bytearray(), 0xffffffff, [])
332326
tx.vin.append(txin)
333327
sender_value += utxo.out.value
334328
accept_value = sender_value - tx.vbytes() * fr

test/test_wallet.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@
55
def test_wallet_transfer():
66
pabtc.config.current = pabtc.config.develop
77
user_list = [
8-
pabtc.wallet.Wallet(pabtc.wallet.Tp2pkh(1)),
9-
pabtc.wallet.Wallet(pabtc.wallet.Tp2shp2ms(2, [pabtc.core.PriKey(e).pubkey() for e in [1, 2]], [1, 2])),
10-
pabtc.wallet.Wallet(pabtc.wallet.Tp2shp2wpkh(1)),
11-
pabtc.wallet.Wallet(pabtc.wallet.Tp2wpkh(1)),
12-
pabtc.wallet.Wallet(pabtc.wallet.Tp2tr(1, bytearray())),
8+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2pkh(1)),
9+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2shp2ms([pabtc.core.PriKey(e).pubkey() for e in [1, 2]], [1, 2])),
10+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2shp2wpkh(1)),
11+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2wpkh(1)),
12+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2tr(1, bytearray())),
1313
]
1414
mate_list = [
15-
pabtc.wallet.Wallet(pabtc.wallet.Tp2pkh(2)),
16-
pabtc.wallet.Wallet(pabtc.wallet.Tp2shp2ms(2, [pabtc.core.PriKey(e).pubkey() for e in [2, 1]], [2, 1])),
17-
pabtc.wallet.Wallet(pabtc.wallet.Tp2shp2wpkh(2)),
18-
pabtc.wallet.Wallet(pabtc.wallet.Tp2wpkh(2)),
19-
pabtc.wallet.Wallet(pabtc.wallet.Tp2tr(2, bytearray())),
15+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2pkh(2)),
16+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2shp2ms([pabtc.core.PriKey(e).pubkey() for e in [2, 1]], [2, 1])),
17+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2shp2wpkh(2)),
18+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2wpkh(2)),
19+
pabtc.wallet.Wallet(pabtc.wallet.Signerp2tr(2, bytearray())),
2020
]
2121
for user, mate in itertools.product(user_list, mate_list):
2222
value = pabtc.denomination.bitcoin

0 commit comments

Comments
 (0)