From 1259a23acc3c9ff0d750028e1c3be6f1e1718f99 Mon Sep 17 00:00:00 2001 From: omipheo Date: Fri, 15 May 2026 11:21:53 +0200 Subject: [PATCH] BIP352: complete type annotations on bitcoin_utils class methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Direct follow-up to PR #2154 (which annotated the free-function half of bip-0352/bitcoin_utils.py) and 2f7117c ("BIP352: fix Any typing"). The four classes in this file — COutPoint, VinInfo, CScriptWitness, and CTxInWitness — still had unannotated `__init__`, `serialize`, `deserialize`, and `is_null` methods. mypy could not flow types through the surrounding reference.py code that constructs and passes these objects. Annotate every method on all four classes: - COutPoint: __init__ (hash, n), serialize -> bytes, deserialize -> None - VinInfo: __init__ (typed Optional defaults for the three construct-on-None fields) - CScriptWitness: __init__ -> None, is_null -> bool, plus an inline stack: List[bytes] declaration matching what the rest of the file already assumes - CTxInWitness: __init__ -> None, deserialize -> "CTxInWitness" (forward ref since it returns self), is_null -> bool Adds Optional to the existing typing import (List was already added by #2154). No behavior changes. Verified: mypy --ignore-missing-imports ./bip-0352/bitcoin_utils.py reports "Success: no issues found in 1 source file"; round-trip smoke tests on COutPoint serialize/deserialize, CScriptWitness is_null with empty + non-empty stack, CTxInWitness deserialize returning self, and VinInfo default-construction all match the pre-change behavior. --- bip-0352/bitcoin_utils.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/bip-0352/bitcoin_utils.py b/bip-0352/bitcoin_utils.py index c6edecee..cfd6a807 100644 --- a/bip-0352/bitcoin_utils.py +++ b/bip-0352/bitcoin_utils.py @@ -3,7 +3,7 @@ import struct from io import BytesIO from ripemd160 import ripemd160 from secp256k1lab.secp256k1 import Scalar -from typing import List, Union +from typing import List, Optional, Union def from_hex(hex_string: str) -> BytesIO: @@ -65,17 +65,17 @@ def deser_string_vector(f: BytesIO) -> List[bytes]: class COutPoint: __slots__ = ("hash", "n",) - def __init__(self, hash=b"", n=0,): + def __init__(self, hash: bytes = b"", n: int = 0) -> None: self.hash = hash self.n = n - def serialize(self): + def serialize(self) -> bytes: r = b"" r += self.hash r += struct.pack(" None: self.hash = f.read(32) self.n = struct.unpack(" None: if outpoint is None: self.outpoint = COutPoint() else: @@ -103,11 +110,11 @@ class VinInfo: class CScriptWitness: __slots__ = ("stack",) - def __init__(self): + def __init__(self) -> None: # stack is a vector of strings - self.stack = [] + self.stack: List[bytes] = [] - def is_null(self): + def is_null(self) -> bool: if self.stack: return False return True @@ -116,14 +123,14 @@ class CScriptWitness: class CTxInWitness: __slots__ = ("scriptWitness",) - def __init__(self): + def __init__(self) -> None: self.scriptWitness = CScriptWitness() - def deserialize(self, f: BytesIO): + def deserialize(self, f: BytesIO) -> "CTxInWitness": self.scriptWitness.stack = deser_string_vector(f) return self - def is_null(self): + def is_null(self) -> bool: return self.scriptWitness.is_null()