Skip to content

Commit 5200e93

Browse files
Add type hints to keys.py
1 parent e9b064f commit 5200e93

1 file changed

Lines changed: 31 additions & 31 deletions

File tree

bitcoinutils/keys.py

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
from typing import TYPE_CHECKING
1414

1515
if TYPE_CHECKING:
16-
from typing import Tuple
16+
from typing import Tuple, List, Union, Any
1717

1818
import re
1919
import struct
2020
import hashlib
2121
from abc import ABC, abstractmethod
2222
from base64 import b64encode, b64decode
23-
from typing import Optional
23+
from typing import Optional, List, Tuple, Union, cast
2424
from base58check import b58encode, b58decode # type: ignore
2525
from ecdsa import ( # type: ignore
2626
SigningKey,
@@ -138,26 +138,26 @@ def to_bytes(self) -> bytes:
138138
return self.key.to_string()
139139

140140
@classmethod
141-
def from_wif(cls, wif: str):
141+
def from_wif(cls, wif: str) -> 'PrivateKey':
142142
"""Creates key from WIFC or WIF format key"""
143143

144144
return cls(wif=wif)
145145

146146
@classmethod
147-
def from_bytes(cls, b: bytes):
147+
def from_bytes(cls, b: bytes) -> 'PrivateKey':
148148
"""Creates a key directly from 32 raw bytes"""
149149

150150
return cls(b=b)
151151

152-
def _from_bytes(self, b: bytes):
152+
def _from_bytes(self, b: bytes) -> None:
153153
"""Creates a key directly from 32 raw bytes"""
154154

155155
if len(b) != 32:
156156
raise ValueError("Invalid key length: must be exactly 32 bytes.")
157157
self.key = SigningKey.from_string(b, curve=SECP256k1)
158158

159159
# expects wif in hex string
160-
def _from_wif(self, wif: str):
160+
def _from_wif(self, wif: str) -> None:
161161
"""Creates key from WIFC or WIF format key
162162
163163
Check to_wif for the detailed process. From WIF is the reverse.
@@ -196,7 +196,7 @@ def _from_wif(self, wif: str):
196196
else:
197197
self.key = SigningKey.from_string(key_bytes, curve=SECP256k1)
198198

199-
def to_wif(self, compressed: bool = True):
199+
def to_wif(self, compressed: bool = True) -> str:
200200
"""Returns key in WIFC or WIF string
201201
202202
| Pseudocode:
@@ -276,8 +276,8 @@ def sign_message(self, message: str, compressed: bool = True) -> Optional[str]:
276276
return None
277277

278278
def sign_input(
279-
self, tx: Transaction, txin_index: int, script: Script, sighash=SIGHASH_ALL
280-
):
279+
self, tx: Transaction, txin_index: int, script: Script, sighash: int = SIGHASH_ALL
280+
) -> str:
281281
# get the digest from the transaction object and sign
282282
tx_digest = tx.get_transaction_digest(txin_index, script, sighash)
283283
return self._sign_input(tx_digest, sighash)
@@ -289,7 +289,7 @@ def sign_segwit_input(
289289
script: Script,
290290
amount: int,
291291
sighash: int = SIGHASH_ALL,
292-
):
292+
) -> str:
293293
# get the digest from the transaction object and sign
294294
tx_digest = tx.get_transaction_segwit_digest(
295295
txin_index, script, amount, sighash
@@ -304,10 +304,10 @@ def sign_taproot_input(
304304
amounts: list[int],
305305
script_path: bool = False,
306306
tapleaf_script: Script = Script([]),
307-
tapleaf_scripts: Optional[Script | list[Script] | list[list[Script]]] | bytes = None,
307+
tapleaf_scripts: Optional[Union[Script, List[Script], List[List[Script]], bytes]] = None,
308308
sighash: int = TAPROOT_SIGHASH_ALL,
309309
tweak: bool = True,
310-
):
310+
) -> str:
311311
# get the digest from the transaction object and sign
312312
# note that when signing a tapleaf we typically won't use tweaked
313313
# keys - so tweak should be set to False
@@ -439,7 +439,7 @@ def _sign_taproot_input(
439439
self,
440440
tx_digest: bytes,
441441
sighash: int = SIGHASH_ALL,
442-
scripts: Optional[Script | list[Script] | list[list[Script]]] = None,
442+
scripts: Optional[Union[Script, List[Script], List[List[Script]], bytes]] = None,
443443
tweak: bool = True,
444444
) -> str:
445445
"""Signs a taproot transaction input with the private key
@@ -483,7 +483,7 @@ def _sign_taproot_input(
483483

484484
return b_to_h(sig)
485485

486-
def get_public_key(self) -> PublicKey:
486+
def get_public_key(self) -> 'PublicKey':
487487
"""Returns the corresponding PublicKey"""
488488

489489
verifying_key = b_to_h(self.key.get_verifying_key().to_string())
@@ -530,7 +530,7 @@ class PublicKey:
530530
returns the corresponding P2trAddress object
531531
"""
532532

533-
def __init__(self, hex_str: str = None, message: str = None, signature: bytes = None) -> None:
533+
def __init__(self, hex_str: Optional[str] = None, message: Optional[str] = None, signature: Optional[bytes] = None) -> None:
534534
"""
535535
Parameters
536536
----------
@@ -614,7 +614,7 @@ def __init__(self, hex_str: str = None, message: str = None, signature: bytes =
614614
if not message:
615615
raise ValueError("Empty message provided for public key recovery.")
616616

617-
if(len(signature) != 65):
617+
if not signature or len(signature) != 65:
618618
raise ValueError("Invalid signature length, must be exactly 65 bytes")
619619

620620
# The compressed signature is of the format: recovery_id (1 byte) | r (32 bytes) | s (32 bytes)
@@ -639,7 +639,7 @@ def __init__(self, hex_str: str = None, message: str = None, signature: bytes =
639639
raise TypeError("Either 'hex_str' or ('message', 'signature') must be provided.")
640640

641641
@classmethod
642-
def from_hex(cls, hex_str: str) -> PublicKey:
642+
def from_hex(cls, hex_str: str) -> 'PublicKey':
643643
"""Creates a public key from a hex string (SEC format)"""
644644

645645
return cls(hex_str)
@@ -674,7 +674,7 @@ def to_x_only_hex(self) -> str:
674674
return key_hex[:64]
675675

676676
def to_taproot_hex(
677-
self, scripts: Optional[Script | list[Script] | list[list[Script]]] = None
677+
self, scripts: Optional[Union[Script, List[Script], List[List[Script]]]] = None
678678
) -> Tuple[str, bool]:
679679
"""Returns the tweaked x coordinate of the public key as a hex string.
680680
@@ -706,7 +706,7 @@ def is_y_even(self) -> bool:
706706
return y % 2 == 0
707707

708708
@classmethod
709-
def from_message_signature(cls, message, signature):
709+
def from_message_signature(cls, message: str, signature: bytes) -> 'PublicKey':
710710
"""Recovers a public key from a Bitcoin-signed message and a 65-byte compressed signature.
711711
"""
712712
#Note: Only works for compressed signatures because DER encoding does not contain the recovery id
@@ -831,14 +831,14 @@ def to_hash160(self, compressed: bool = True) -> str:
831831

832832
return b_to_h(self._to_hash160(compressed))
833833

834-
def get_address(self, compressed: bool = True) -> P2pkhAddress:
834+
def get_address(self, compressed: bool = True) -> 'P2pkhAddress':
835835
"""Returns the corresponding P2PKH Address (default compressed)"""
836836

837837
hash160 = self._to_hash160(compressed)
838838
addr_string_hex = b_to_h(hash160)
839839
return P2pkhAddress(hash160=addr_string_hex)
840840

841-
def get_segwit_address(self) -> P2wpkhAddress:
841+
def get_segwit_address(self) -> 'P2wpkhAddress':
842842
"""Returns the corresponding P2WPKH address
843843
844844
Only compressed is allowed. It is otherwise identical to normal P2PKH
@@ -849,8 +849,8 @@ def get_segwit_address(self) -> P2wpkhAddress:
849849
return P2wpkhAddress(witness_program=addr_string_hex)
850850

851851
def get_taproot_address(
852-
self, scripts: Optional[Script | list[Script] | list[list[Script]]] | bytes = None
853-
) -> P2trAddress:
852+
self, scripts: Optional[Union[Script, List[Script], List[List[Script]], bytes]] = None
853+
) -> 'P2trAddress':
854854
"""Returns the corresponding P2TR address
855855
856856
Only compressed is allowed. Taproot uses x-only public key with
@@ -943,19 +943,19 @@ def __init__(
943943
raise TypeError("A valid address or hash160 is required.")
944944

945945
@classmethod
946-
def from_address(cls, address: str) -> Address:
946+
def from_address(cls, address: str) -> 'Address':
947947
"""Creates an address object from an address string"""
948948

949949
return cls(address=address)
950950

951951
@classmethod
952-
def from_hash160(cls, hash160: str) -> Address:
952+
def from_hash160(cls, hash160: str) -> 'Address':
953953
"""Creates an address object from a hash160 string"""
954954

955955
return cls(hash160=hash160)
956956

957957
@classmethod
958-
def from_script(cls, script: Script) -> Address:
958+
def from_script(cls, script: Script) -> 'Address':
959959
"""Creates an address object from a Script object"""
960960

961961
return cls(script=script)
@@ -1121,7 +1121,7 @@ def __init__(
11211121
address: Optional[str] = None,
11221122
hash160: Optional[str] = None,
11231123
script: Optional[Script] = None,
1124-
):
1124+
) -> None:
11251125
super().__init__(address=address, hash160=hash160, script=script)
11261126

11271127
def to_script_pub_key(self) -> Script:
@@ -1219,19 +1219,19 @@ def __init__(
12191219
raise TypeError("A valid address or witness program is required.")
12201220

12211221
@classmethod
1222-
def from_address(cls, address: str) -> SegwitAddress:
1222+
def from_address(cls, address: str) -> 'SegwitAddress':
12231223
"""Creates an address object from an address string"""
12241224

12251225
return cls(address=address)
12261226

12271227
@classmethod
1228-
def from_witness_program(cls, witness_program: str) -> SegwitAddress:
1228+
def from_witness_program(cls, witness_program: str) -> 'SegwitAddress':
12291229
"""Creates an address object from a hash string"""
12301230

12311231
return cls(witness_program=witness_program)
12321232

12331233
@classmethod
1234-
def from_script(cls, script: Script) -> SegwitAddress:
1234+
def from_script(cls, script: Script) -> 'SegwitAddress':
12351235
"""Creates an address object from a Script object"""
12361236

12371237
return cls(script=script)
@@ -1411,4 +1411,4 @@ def main():
14111411

14121412

14131413
if __name__ == "__main__":
1414-
main()
1414+
main()

0 commit comments

Comments
 (0)