From 9307cab55dd2f4ec4264acf38f468fd5c3c76138 Mon Sep 17 00:00:00 2001 From: Freddie Honohan Date: Mon, 8 Dec 2025 14:46:29 +0900 Subject: [PATCH 1/2] 80% --- bsv/identity/contacts_manager.py | 14 +-- bsv/keystore/local_kv_store.py | 26 +++--- bsv/registry/client.py | 10 +-- bsv/registry/resolver.py | 1 - bsv/transaction/pushdrop.py | 53 ++++++++--- .../substrates/wallet_wire_processor.py | 56 ++++++------ .../auth/clients/test_auth_fetch_coverage.py | 38 ++++---- tests/bsv/auth/clients/test_auth_fetch_e2e.py | 2 +- .../auth/clients/test_auth_fetch_full_e2e.py | 8 +- .../clients/test_auth_fetch_integration.py | 20 ++--- .../auth/clients/test_auth_fetch_simple.py | 4 +- tests/bsv/auth/test_auth_cryptononce.py | 4 +- .../bsv/auth/test_auth_master_certificate.py | 26 +++--- tests/bsv/auth/test_auth_peer_autopersist.py | 20 +++-- tests/bsv/auth/test_auth_peer_basic.py | 26 ++++-- ...st_auth_peer_cert_request_response_flow.py | 21 +++-- tests/bsv/auth/test_auth_peer_certificates.py | 19 ++-- tests/bsv/auth/test_auth_peer_handshake.py | 24 +++-- tests/bsv/auth/test_auth_peer_messages.py | 24 +++-- tests/bsv/auth/test_concurrent_handshakes.py | 22 +++-- tests/bsv/beef/test_kvstore_beef_e2e.py | 76 ++++++++-------- .../keystore/test_keystore_local_kv_store.py | 14 +-- tests/bsv/keystore/test_keystore_retention.py | 6 +- .../bsv/keystore/test_kvstore_beef_parsing.py | 8 +- .../test_kvstore_pushdrop_encrypt.py | 2 +- tests/bsv/transaction/test_pushdrop_parity.py | 32 +++---- tests/bsv/transaction/test_pushdrop_real.py | 11 --- tests/bsv/wallet/test_wallet_actions.py | 40 ++++----- tests/bsv/wallet/test_wallet_certificates.py | 42 ++++----- tests/bsv/wallet/test_wallet_funding.py | 8 +- tests/bsv/wallet/test_wallet_impl.py | 78 ++++++++-------- tests/bsv/wallet/test_wallet_impl_coverage.py | 88 +++++++++---------- .../test_wallet_impl_sign_verify_hmac.py | 8 +- tests/bsv/wallet/test_wallet_outputs.py | 30 +++---- 34 files changed, 474 insertions(+), 387 deletions(-) diff --git a/bsv/identity/contacts_manager.py b/bsv/identity/contacts_manager.py index 0ffde62..9626e3d 100644 --- a/bsv/identity/contacts_manager.py +++ b/bsv/identity/contacts_manager.py @@ -104,7 +104,7 @@ def _build_contact_tags(self, identity_key: Optional[str]) -> List[str]: def _fetch_contact_outputs(self, tags: List[str], limit: int) -> List[Dict]: """Fetch contact outputs from wallet.""" - outputs_result = self.wallet.list_outputs(None, { + outputs_result = self.wallet.list_outputs({ 'basket': 'contacts', 'include': 'locking scripts', 'includeCustomInstructions': True, @@ -146,7 +146,7 @@ def _decrypt_contact_output(self, output: Dict, pushdrop: PushDrop) -> Optional[ key_id = key_id_data.get('keyID') ciphertext = decoded['fields'][0] - decrypt_result = self.wallet.decrypt(None, { + decrypt_result = self.wallet.decrypt({ 'ciphertext': ciphertext, 'protocolID': CONTACT_PROTOCOL_ID, 'keyID': key_id, @@ -198,7 +198,7 @@ def _hash_identity_key(self, identity_key: str) -> bytes: def _find_existing_contact_output(self, hashed_key: bytes, key_id: str) -> tuple: """Find existing contact output if any.""" - outputs_result = self.wallet.list_outputs(None, { + outputs_result = self.wallet.list_outputs({ 'basket': 'contacts', 'include': 'entire transactions', 'includeCustomInstructions': True, @@ -226,7 +226,7 @@ def _find_existing_contact_output(self, hashed_key: bytes, key_id: str) -> tuple def _create_contact_locking_script(self, contact_to_store: Dict, key_id: str) -> str: """Create encrypted locking script for contact.""" contact_json = json.dumps(contact_to_store) - encrypt_result = self.wallet.encrypt(None, { + encrypt_result = self.wallet.encrypt({ 'plaintext': contact_json.encode('utf-8'), 'protocolID': CONTACT_PROTOCOL_ID, 'keyID': key_id, @@ -236,8 +236,8 @@ def _create_contact_locking_script(self, contact_to_store: Dict, key_id: str) -> ciphertext = encrypt_result.get('ciphertext') or b'' pushdrop = PushDrop(self.wallet, None) return pushdrop.lock( - None, [ciphertext], CONTACT_PROTOCOL_ID, key_id, - {'type': 0}, for_self=True, include_signature=True, lock_position='before' + [ciphertext], CONTACT_PROTOCOL_ID, key_id, + None, for_self=True, include_signature=True, lock_position='before' ) def _save_or_update_contact_action( @@ -297,7 +297,7 @@ def delete_contact(self, identity_key: str) -> None: identity_key.encode('utf-8') ) - outputs_result = self.wallet.list_outputs(None, { + outputs_result = self.wallet.list_outputs({ 'basket': 'contacts', 'include': 'entire transactions', 'tags': [f'identityKey {hashed_key.hex()}'], diff --git a/bsv/keystore/local_kv_store.py b/bsv/keystore/local_kv_store.py index 468c952..568fd13 100644 --- a/bsv/keystore/local_kv_store.py +++ b/bsv/keystore/local_kv_store.py @@ -257,7 +257,7 @@ def _lookup_outputs_for_get(self, ctx: Any, key: str) -> Tuple[list, bytes]: # args["counterparty"] = cpty except Exception: pass - lo = self._wallet.list_outputs(ctx, args, self._originator) or {} + lo = self._wallet.list_outputs(args, self._originator) or {} outputs = lo.get("outputs") or [] beef_bytes = lo.get("BEEF") or b"" if not beef_bytes and outputs: @@ -579,7 +579,7 @@ def _execute_set_operation(self, ctx: Any, key: str, value: str, ca_args: dict) if ca_args and "use_woc" in ca_args: create_args["use_woc"] = ca_args["use_woc"] - ca = self._wallet.create_action(ctx, create_args, self._originator) or {} + ca = self._wallet.create_action(create_args, self._originator) or {} signable = (ca.get("signableTransaction") or {}) if isinstance(ca, dict) else {} signable_tx_bytes = signable.get("tx") or b"" @@ -592,7 +592,7 @@ def _execute_set_operation(self, ctx: Any, key: str, value: str, ca_args: dict) self._build_and_cache_beef(key, locking_script, tx_bytes) # Broadcast and return result - self._wallet.internalize_action(ctx, {"tx": tx_bytes}, self._originator) + self._wallet.internalize_action({"tx": tx_bytes}, self._originator) return self._extract_txid_from_bytes(tx_bytes, key) def _build_and_cache_beef(self, key: str, locking_script: bytes, tx_bytes: bytes) -> None: @@ -693,7 +693,7 @@ def _build_locking_script(self, ctx: Any, key: str, value: str, ca_args: dict = }, "plaintext": value.encode('utf-8') } - encrypt_result = self._wallet.encrypt(ctx, encrypt_args, self._originator) + encrypt_result = self._wallet.encrypt(encrypt_args, self._originator) if "ciphertext" in encrypt_result: field_bytes = encrypt_result["ciphertext"] else: @@ -722,7 +722,6 @@ def _build_locking_script(self, ctx: Any, key: str, value: str, ca_args: dict = counterparty = ca_args.get("counterparty", pd_opts.get("counterparty")) pd = PushDrop(self._wallet, self._originator) return pd.lock( - ctx, fields, protocol_id, key_id, @@ -753,7 +752,7 @@ def _lookup_outputs_for_set(self, ctx: Any, key: str, ca_args: Optional[dict] = args["key_id"] = kid if cpty is not None: args["counterparty"] = cpty - lo = self._wallet.list_outputs(ctx, args, self._originator) or {} + lo = self._wallet.list_outputs(args, self._originator) or {} outs = [o for o in lo.get("outputs") or [] if not o.get("error")] input_beef = lo.get("BEEF") or b"" if not input_beef and outs: @@ -814,7 +813,6 @@ def _sign_and_relinquish_set(self, ctx: Any, key: str, outs: list, inputs_meta: try: spends_str_keys = {str(int(k)): v for k, v in (spends or {}).items()} res = self._wallet.sign_action( - ctx, { "spends": spends_str_keys, "reference": signable.get("reference") or b"", @@ -826,7 +824,7 @@ def _sign_and_relinquish_set(self, ctx: Any, key: str, outs: list, inputs_meta: except Exception: for o in outs: try: - self._wallet.relinquish_output(ctx, { + self._wallet.relinquish_output({ "basket": self._context, "output": { "txid": bytes.fromhex(o.get("txid", "00" * 32)) if isinstance(o.get("txid"), str) else (o.get("txid") or b"\x00" * 32), @@ -871,7 +869,7 @@ def remove(self, ctx: Any, key: str) -> List[str]: # NOSONAR - Complexity (17), self._release_key_lock(key) def _lookup_outputs_for_remove(self, ctx: Any, key: str) -> Tuple[list, bytes, Optional[int]]: - lo = self._wallet.list_outputs(ctx, { + lo = self._wallet.list_outputs({ "basket": self._context, "tags": [key], "include": ENTIRE_TXS, @@ -895,7 +893,7 @@ def _lookup_outputs_for_remove(self, ctx: Any, key: str) -> Tuple[list, bytes, O return outs, input_beef, total_outputs def _onchain_remove_flow(self, ctx: Any, key: str, inputs_meta: list, input_beef: bytes) -> Optional[str]: - ca_res = self._wallet.create_action(ctx, { + ca_res = self._wallet.create_action({ "labels": ["kv", "remove"], "description": f"kvstore remove {key}", "inputs": inputs_meta, @@ -909,9 +907,9 @@ def _onchain_remove_flow(self, ctx: Any, key: str, inputs_meta: list, input_beef reference = signable.get("reference") or b"" spends = self._prepare_spends(key, inputs_meta, signable_tx_bytes, input_beef) spends_str = {str(int(k)): v for k, v in (spends or {}).items()} - res = self._wallet.sign_action(ctx, {"spends": spends_str, "reference": reference}, self._originator) or {} + res = self._wallet.sign_action({"spends": spends_str, "reference": reference}, self._originator) or {} signed_tx_bytes = res.get("tx") if isinstance(res, dict) else None - internalize_result = self._wallet.internalize_action(ctx, {"tx": signed_tx_bytes or signable_tx_bytes}, self._originator) + internalize_result = self._wallet.internalize_action({"tx": signed_tx_bytes or signable_tx_bytes}, self._originator) parsed_txid = None try: from bsv.transaction import Transaction @@ -1017,7 +1015,7 @@ def _prepare_inputs_meta(self, key: str, outs: list, ca_args: dict = None) -> li pd = PushDrop(self._wallet, self._originator) unlock_protocol = protocol if protocol is not None else self._get_protocol(key) - unlocker = pd.unlock(unlock_protocol, key, {"type": 0}, sign_outputs='all') + unlocker = pd.unlock(unlock_protocol, key, None, sign_outputs='all') # None = SELF counterparty inputs_meta = [] for o in outs: @@ -1052,7 +1050,7 @@ def _prepare_spends(self, key, inputs_meta, signable_tx_bytes, input_beef): # N pd = PushDrop(self._wallet, self._originator) # Use default protocol for unlocking (GO pattern: protocol and key are separate) unlock_protocol = self._get_protocol(key) - unlocker = pd.unlock(unlock_protocol, key, {"type": 0}, sign_outputs='all') + unlocker = pd.unlock(unlock_protocol, key, None, sign_outputs='all') # None = SELF counterparty # Only prepare spends for inputs whose outpoint matches the tx input at the same index for idx, meta in enumerate(inputs_meta): try: diff --git a/bsv/registry/client.py b/bsv/registry/client.py index bc6e694..53b27ab 100644 --- a/bsv/registry/client.py +++ b/bsv/registry/client.py @@ -150,7 +150,7 @@ def __init__(self, wallet: WalletInterface, originator: str = "registry-client") self._resolver = LookupResolver() def register_definition(self, ctx: Any, data: DefinitionData) -> Dict[str, Any]: - pub = self.wallet.get_public_key(ctx, {"identityKey": True}, self.originator) or {} + pub = self.wallet.get_public_key({"identityKey": True}, self.originator) or {} operator = cast(str, pub.get("publicKey") or "") _ = _map_definition_type_to_wallet_protocol(data.definitionType) # Reserved for future use @@ -165,7 +165,6 @@ def register_definition(self, ctx: Any, data: DefinitionData) -> Dict[str, Any]: # Create transaction randomize_outputs = False ca_res = self.wallet.create_action( - ctx, { "description": f"Register a new {data.definitionType} item", "outputs": [ @@ -189,7 +188,6 @@ def list_own_registry_entries(self, ctx: Any, definition_type: DefinitionType) - include_tags = True include_labels = True lo = self.wallet.list_outputs( - ctx, { "basket": _map_definition_type_to_basket_name(definition_type), "include": "entire transactions", @@ -239,7 +237,7 @@ def list_own_registry_entries(self, ctx: Any, definition_type: DefinitionType) - def revoke_own_registry_entry(self, ctx: Any, record: Dict[str, Any]) -> Dict[str, Any]: # NOSONAR - Complexity (26), requires refactoring # Owner check: ensure this wallet controls the registry operator key - me = self.wallet.get_public_key(ctx, {"identityKey": True}, self.originator) or {} + me = self.wallet.get_public_key({"identityKey": True}, self.originator) or {} my_pub = cast(str, me.get("publicKey") or "") operator = cast(str, record.get("registryOperator") or "") if operator and my_pub and operator.lower() != my_pub.lower(): @@ -254,7 +252,6 @@ def revoke_own_registry_entry(self, ctx: Any, record: Dict[str, Any]) -> Dict[st # Create partial transaction that spends the registry UTXO ca_res = self.wallet.create_action( - ctx, { "description": f"Revoke {record.get('definitionType', 'registry')} item", "inputBEEF": beef, @@ -290,11 +287,10 @@ def revoke_own_registry_entry(self, ctx: Any, record: Dict[str, Any]) -> Dict[st prev_satoshis=satoshis, prev_locking_script=bytes.fromhex(cast(str, record.get("lockingScript", ""))) if record.get("lockingScript") else None, ) - unlocking_script = unlocker.sign(ctx, partial_tx, 0) + unlocking_script = unlocker.sign(partial_tx, 0) spends = {0: {"unlockingScript": unlocking_script}} sign_res = self.wallet.sign_action( - ctx, { "reference": reference, "spends": spends, diff --git a/bsv/registry/resolver.py b/bsv/registry/resolver.py index 9af4041..7bfd272 100644 --- a/bsv/registry/resolver.py +++ b/bsv/registry/resolver.py @@ -48,7 +48,6 @@ def __call__(self, ctx: Any, service_name: str, query: Dict[str, Any]) -> List[D def query(self, ctx: Any, definition_type: DefinitionType, query: Dict[str, Any] = None) -> List[Dict[str, Any]]: # NOSONAR - query parameter reserved for future filtering capability lo = self.wallet.list_outputs( - ctx, { "basket": _basket_name(definition_type), "include": "entire transactions", diff --git a/bsv/transaction/pushdrop.py b/bsv/transaction/pushdrop.py index 33a12ab..fa2efc2 100644 --- a/bsv/transaction/pushdrop.py +++ b/bsv/transaction/pushdrop.py @@ -542,6 +542,26 @@ def sign(self, tx, input_index: int) -> bytes: # noqa: D401 Flags: base (ALL/NONE/SINGLE) derived from sign_outputs_mode, always includes FORKID, and optionally ANYONECANPAY when anyone_can_pay is True. """ + # Try to get locking script from transaction input if not already set + if not self.prev_locking_script and hasattr(tx, "inputs") and input_index < len(tx.inputs): + tin = tx.inputs[input_index] + if hasattr(tin, "source_transaction") and tin.source_transaction: + src_tx = tin.source_transaction + src_idx = getattr(tin, "source_output_index", 0) + if hasattr(src_tx, "outputs") and src_idx < len(src_tx.outputs): + out = src_tx.outputs[src_idx] + if hasattr(out, "locking_script"): + ls = out.locking_script + if hasattr(ls, "to_bytes"): + self.prev_locking_script = ls.to_bytes() + elif isinstance(ls, bytes): + self.prev_locking_script = ls + elif isinstance(ls, str): + try: + self.prev_locking_script = bytes.fromhex(ls) + except Exception: + pass + sighash_flag = self._compute_sighash_flag() hash_to_sign, used_preimage = self._compute_hash_to_sign(tx, input_index, sighash_flag) @@ -683,12 +703,17 @@ def _try_pushdrop_signature(self, hash_to_sign: bytes, sighash_flag: int, used_p return None print(f"[DEBUG] PushDropUnlocker.sign: Using locking public key from PushDrop UTXO: {locking_pubkey.hex()}") + # Use protocol_id/key_id/counterparty to derive the key (same as fallback) + # The derived key should match the locking public key if the protocol/key_id match create_args = { - "encryption_args": { - "publicKey": locking_pubkey.hex(), - }, - ("hash_to_sign" if used_preimage else "data"): hash_to_sign, + "protocol_id": self.protocol_id, + "key_id": self.key_id, + "counterparty": self.counterparty, } + if used_preimage: + create_args["hash_to_directly_sign"] = hash_to_sign + else: + create_args["data"] = hash_to_sign res = self.wallet.create_signature(create_args, "") if hasattr(self.wallet, "create_signature") else {} sig = res.get("signature", b"") sig = bytes(sig) + bytes([sighash_flag]) @@ -699,18 +724,24 @@ def _try_pushdrop_signature(self, hash_to_sign: bytes, sighash_flag: int, used_p def _create_fallback_signature(self, hash_to_sign: bytes, sighash_flag: int, used_preimage: bool) -> bytes: """Create signature using derived key (fallback method).""" - print("[DEBUG] PushDropUnlocker.sign: Fallback to derived public key") + print(f"[DEBUG] PushDropUnlocker.sign: Fallback to derived public key, protocol_id={self.protocol_id}, key_id={self.key_id}") create_args = { - "encryption_args": { - "protocol_id": self.protocol_id, - "key_id": self.key_id, - "counterparty": self.counterparty, - }, - ("hash_to_sign" if used_preimage else "data"): hash_to_sign, + "protocol_id": self.protocol_id, + "key_id": self.key_id, + "counterparty": self.counterparty, } + if used_preimage: + create_args["hash_to_directly_sign"] = hash_to_sign + else: + create_args["data"] = hash_to_sign + print(f"[DEBUG] PushDropUnlocker.sign: Calling create_signature with args: {create_args}") res = self.wallet.create_signature(create_args, "") if hasattr(self.wallet, "create_signature") else {} + print(f"[DEBUG] PushDropUnlocker.sign: create_signature result: {res}") sig = res.get("signature", b"") + if not sig: + print(f"[WARN] PushDropUnlocker.sign: No signature in result, result keys: {list(res.keys()) if isinstance(res, dict) else 'not a dict'}") sig = bytes(sig) + bytes([sighash_flag]) + print(f"[DEBUG] PushDropUnlocker.sign: Final sig length: {len(sig)}, sig: {sig.hex()[:100] if len(sig) > 0 else 'empty'}") return encode_pushdata(sig) diff --git a/bsv/wallet/substrates/wallet_wire_processor.py b/bsv/wallet/substrates/wallet_wire_processor.py index d9a52ce..03939e2 100644 --- a/bsv/wallet/substrates/wallet_wire_processor.py +++ b/bsv/wallet/substrates/wallet_wire_processor.py @@ -189,147 +189,147 @@ def _parse_message(self, message: bytes): # Handler methods for each call type def _handle_encrypt(self, ctx, params, originator): enc_args = deserialize_encrypt_args(params) - result_dict = self.wallet.encrypt(ctx, enc_args, originator) + result_dict = self.wallet.encrypt(enc_args, originator) return write_result_frame(serialize_encrypt_result(result_dict)) def _handle_decrypt(self, ctx, params, originator): dec_args = deserialize_decrypt_args(params) - result_dict = self.wallet.decrypt(ctx, dec_args, originator) + result_dict = self.wallet.decrypt(dec_args, originator) return write_result_frame(serialize_decrypt_result(result_dict)) def _handle_create_action(self, ctx, params, originator): c_args = deserialize_create_action_args(params) - result = self.wallet.create_action(ctx, c_args, originator) or {} + result = self.wallet.create_action(c_args, originator) or {} return write_result_frame(serialize_create_action_result(result or {})) def _handle_sign_action(self, ctx, params, originator): s_args = deserialize_sign_action_args(params) - result = self.wallet.sign_action(ctx, s_args, originator) or {} + result = self.wallet.sign_action(s_args, originator) or {} return write_result_frame(serialize_sign_action_result(result)) def _handle_list_actions(self, ctx, params, originator): la_args = deserialize_list_actions_args(params) - result = self.wallet.list_actions(ctx, la_args, originator) + result = self.wallet.list_actions(la_args, originator) return write_result_frame(serialize_list_actions_result(result or {})) def _handle_internalize_action(self, ctx, params, originator): ia_args = deserialize_internalize_action_args(params) - result = self.wallet.internalize_action(ctx, ia_args, originator) + result = self.wallet.internalize_action(ia_args, originator) return write_result_frame(serialize_internalize_action_result(result or {})) def _handle_abort_action(self, ctx, params, originator): from bsv.wallet.serializer.abort_action import serialize_abort_action_result, deserialize_abort_action_args aa_args = deserialize_abort_action_args(params) - result = self.wallet.abort_action(ctx, aa_args, originator) + result = self.wallet.abort_action(aa_args, originator) return write_result_frame(serialize_abort_action_result(result or {})) def _handle_list_certificates(self, ctx, params, originator): lc_args = deserialize_list_certificates_args(params) - result = self.wallet.list_certificates(ctx, lc_args, originator) + result = self.wallet.list_certificates(lc_args, originator) return write_result_frame(serialize_list_certificates_result(result or {})) def _handle_prove_certificate(self, ctx, params, originator): pc_args = deserialize_prove_certificate_args(params) - result = self.wallet.prove_certificate(ctx, pc_args, originator) + result = self.wallet.prove_certificate(pc_args, originator) return write_result_frame(serialize_prove_certificate_result(result or {})) def _handle_relinquish_certificate(self, ctx, params, originator): rc_args = deserialize_relinquish_certificate_args(params) - result = self.wallet.relinquish_certificate(ctx, rc_args, originator) + result = self.wallet.relinquish_certificate(rc_args, originator) return write_result_frame(serialize_relinquish_certificate_result(result or {})) def _handle_discover_by_identity_key(self, ctx, params, originator): di_args = deserialize_discover_by_identity_key_args(params) - result = self.wallet.discover_by_identity_key(ctx, di_args, originator) + result = self.wallet.discover_by_identity_key(di_args, originator) return write_result_frame(serialize_discover_certificates_result_by_identity(result or {})) def _handle_discover_by_attributes(self, ctx, params, originator): da_args = deserialize_discover_by_attributes_args(params) - result = self.wallet.discover_by_attributes(ctx, da_args, originator) + result = self.wallet.discover_by_attributes(da_args, originator) return write_result_frame(serialize_discover_certificates_result_by_attr(result or {})) def _handle_acquire_certificate(self, ctx, params, originator): ac_args = deserialize_acquire_certificate_args(params) - _ = self.wallet.acquire_certificate(ctx, ac_args, originator) + _ = self.wallet.acquire_certificate(ac_args, originator) return write_result_frame(b"") # No specific result payload def _handle_create_hmac(self, ctx, params, originator): h_args = deserialize_create_hmac_args(params) - result = self.wallet.create_hmac(ctx, h_args, originator) + result = self.wallet.create_hmac(h_args, originator) return write_result_frame(serialize_create_hmac_result(result)) def _handle_verify_hmac(self, ctx, params, originator): vh_args = deserialize_verify_hmac_args(params) - result = self.wallet.verify_hmac(ctx, vh_args, originator) + result = self.wallet.verify_hmac(vh_args, originator) return write_result_frame(serialize_verify_hmac_result(result)) def _handle_create_signature(self, ctx, params, originator): cs_args = deserialize_create_signature_args(params) - result = self.wallet.create_signature(ctx, cs_args, originator) + result = self.wallet.create_signature(cs_args, originator) return write_result_frame(serialize_create_signature_result(result)) def _handle_verify_signature(self, ctx, params, originator): vs_args = deserialize_verify_signature_args(params) - result = self.wallet.verify_signature(ctx, vs_args, originator) + result = self.wallet.verify_signature(vs_args, originator) return write_result_frame(serialize_verify_signature_result(result)) def _handle_list_outputs(self, ctx, params, originator): lo_args = deserialize_list_outputs_args(params) - result = self.wallet.list_outputs(ctx, lo_args, originator) + result = self.wallet.list_outputs(lo_args, originator) return write_result_frame(serialize_list_outputs_result(result or {})) def _handle_relinquish_output(self, ctx, params, originator): ro_args = deserialize_relinquish_output_args(params) - result = self.wallet.relinquish_output(ctx, ro_args, originator) + result = self.wallet.relinquish_output(ro_args, originator) return write_result_frame(serialize_relinquish_output_result(result or {})) def _handle_get_header_for_height(self, ctx, params, originator): from bsv.wallet.serializer.get_network import deserialize_get_header_args, serialize_get_header_result gha = deserialize_get_header_args(params) - result = self.wallet.get_header_for_height(ctx, gha, originator) or {} + result = self.wallet.get_header_for_height(gha, originator) or {} return write_result_frame(serialize_get_header_result(result)) def _handle_get_network(self, ctx, params, originator): from bsv.wallet.serializer.get_network import serialize_get_network_result - result = self.wallet.get_network(ctx, {}, originator) or {} + result = self.wallet.get_network({}, originator) or {} return write_result_frame(serialize_get_network_result(result)) def _handle_get_version(self, ctx, params, originator): from bsv.wallet.serializer.get_network import serialize_get_version_result - result = self.wallet.get_version(ctx, {}, originator) or {} + result = self.wallet.get_version({}, originator) or {} return write_result_frame(serialize_get_version_result(result)) def _handle_get_height(self, ctx, params, originator): from bsv.wallet.serializer.get_network import serialize_get_height_result - result = self.wallet.get_height(ctx, {}, originator) or {} + result = self.wallet.get_height({}, originator) or {} return write_result_frame(serialize_get_height_result(result)) def _handle_get_public_key(self, ctx, params, originator): gp_args = deserialize_get_public_key_args(params) - result = self.wallet.get_public_key(ctx, gp_args, originator) + result = self.wallet.get_public_key(gp_args, originator) if isinstance(result, dict) and result.get("error"): return write_result_frame(None, error=str(result.get("error"))) return write_result_frame(serialize_get_public_key_result(result or {})) def _handle_reveal_counterparty_key_linkage(self, ctx, params, originator): r_args = deserialize_reveal_counterparty_key_linkage_args(params) - result = self.wallet.reveal_counterparty_key_linkage(ctx, r_args, originator) + result = self.wallet.reveal_counterparty_key_linkage(r_args, originator) if isinstance(result, dict) and result.get("error"): return write_result_frame(None, error=str(result.get("error"))) return write_result_frame(serialize_key_linkage_result(result or {})) def _handle_reveal_specific_key_linkage(self, ctx, params, originator): rs_args = deserialize_reveal_specific_key_linkage_args(params) - result = self.wallet.reveal_specific_key_linkage(ctx, rs_args, originator) + result = self.wallet.reveal_specific_key_linkage(rs_args, originator) if isinstance(result, dict) and result.get("error"): return write_result_frame(None, error=str(result.get("error"))) return write_result_frame(serialize_key_linkage_result(result or {})) def _handle_is_authenticated(self, ctx, params, originator): - result = self.wallet.is_authenticated(ctx, None, originator) or {} + result = self.wallet.is_authenticated(None, originator) or {} # encode a single-byte boolean per Go serializer return write_result_frame(bytes([1]) if bool(result.get("authenticated")) else bytes([0])) def _handle_wait_for_authentication(self, ctx, params, originator): - _ = self.wallet.wait_for_authentication(ctx, None, originator) + _ = self.wallet.wait_for_authentication(None, originator) return write_result_frame(bytes([1])) diff --git a/tests/bsv/auth/clients/test_auth_fetch_coverage.py b/tests/bsv/auth/clients/test_auth_fetch_coverage.py index a1d5f32..d0f7af6 100644 --- a/tests/bsv/auth/clients/test_auth_fetch_coverage.py +++ b/tests/bsv/auth/clients/test_auth_fetch_coverage.py @@ -59,13 +59,13 @@ def test_fetch_retry_counter_edge_cases(self): # Test retry counter = 0 (should raise RetryError) config = SimplifiedFetchRequestOptions(retry_counter=0) with pytest.raises(RetryError, match="request failed after maximum number of retries"): - self.auth_fetch.fetch(None, "https://example.com", config) + self.auth_fetch.fetch("https://example.com", config) # Test retry counter = 1 (should decrement) config = SimplifiedFetchRequestOptions(retry_counter=1) # This will fail later but should decrement retry counter try: - self.auth_fetch.fetch(None, "https://example.com", config) + self.auth_fetch.fetch("https://example.com", config) except Exception: pass # Expected to fail assert config.retry_counter == 0 @@ -78,19 +78,19 @@ def test_fetch_invalid_url_formats(self): try: # Test with None URL - urlparse will handle it try: - self.auth_fetch.fetch(None, None) + self.auth_fetch.fetch(None) except Exception: pass # Expected to fail # Test with empty URL try: - self.auth_fetch.fetch(None, "") + self.auth_fetch.fetch("") except Exception: pass # Expected to fail # Test with malformed URL try: - self.auth_fetch.fetch(None, "not-a-url") + self.auth_fetch.fetch("not-a-url") except Exception: pass # Expected to fail @@ -105,7 +105,7 @@ def test_fetch_url_parsing_failures(self, mock_urlparse): mock_urlparse.side_effect = Exception("URL parsing failed") with pytest.raises(Exception): - self.auth_fetch.fetch(None, "https://example.com") + self.auth_fetch.fetch("https://example.com") except ImportError: pytest.skip("AuthFetch not available") @@ -119,7 +119,7 @@ def test_fetch_peer_creation_failures(self, mock_peer, mock_transport): mock_peer.side_effect = Exception("Peer creation failed") with pytest.raises(Exception): - self.auth_fetch.fetch(None, "https://example.com") + self.auth_fetch.fetch("https://example.com") except ImportError: pytest.skip("AuthFetch not available") @@ -135,7 +135,7 @@ def test_fetch_certificate_listener_setup_failures(self): with patch('bsv.auth.clients.auth_fetch.SimplifiedHTTPTransport'): with pytest.raises(Exception): - self.auth_fetch.fetch(None, "https://example.com") + self.auth_fetch.fetch("https://example.com") except ImportError: pytest.skip("AuthFetch not available") @@ -158,7 +158,7 @@ def test_fetch_callback_registration_conflicts(self): # This should still work despite callback conflict # (the callback is created with a new nonce) try: - result = self.auth_fetch.fetch(None, "https://example.com") + result = self.auth_fetch.fetch("https://example.com") assert result is not None except Exception: pass # May fail for other reasons @@ -179,7 +179,7 @@ def test_fetch_to_peer_error_handling(self): # This should handle the session error gracefully try: - self.auth_fetch.fetch(None, "https://example.com") + self.auth_fetch.fetch("https://example.com") except Exception: pass # Expected to fail @@ -202,7 +202,7 @@ def test_fetch_http_auth_failure_fallback(self): mock_handle.return_value = mock_response try: - _ = self.auth_fetch.fetch(None, "https://example.com") + _ = self.auth_fetch.fetch("https://example.com") # Should have called handle_fetch_and_validate mock_handle.assert_called_once() except Exception: @@ -224,7 +224,7 @@ def test_fetch_timeout_handling(self): # Mock threading.Event.wait to timeout with patch('threading.Event.wait', return_value=False): # Timeout # Should return None when timeout occurs (no response received) - result = self.auth_fetch.fetch(None, "https://example.com") + result = self.auth_fetch.fetch("https://example.com") assert result is None except ImportError: @@ -296,7 +296,7 @@ def mock_fetch(*args, **kwargs): # This test is complex to set up correctly, so we'll test the concept # that errors in the response holder are properly handled try: - _ = self.auth_fetch.fetch(None, "https://example.com") + _ = self.auth_fetch.fetch("https://example.com") except Exception: pass # Expected for this complex test @@ -325,7 +325,7 @@ def test_fetch_mutual_auth_fallback(self): mock_response.status_code = 200 mock_handle.return_value = mock_response - _ = self.auth_fetch.fetch(None, "https://example.com") + _ = self.auth_fetch.fetch("https://example.com") mock_handle.assert_called_once() except ImportError: @@ -356,7 +356,7 @@ def test_fetch_payment_retry_handling(self): with patch.object(self.auth_fetch, 'handle_payment_and_retry') as mock_payment: mock_payment.return_value = "payment_result" - result = self.auth_fetch.fetch(None, "https://example.com") + result = self.auth_fetch.fetch("https://example.com") mock_payment.assert_called_once() assert result == "payment_result" @@ -378,7 +378,7 @@ def failing_cert_listener(sender_public_key, certs): # This should not crash even if certificate extension fails try: - self.auth_fetch.fetch(None, "https://example.com") + self.auth_fetch.fetch("https://example.com") except Exception as e: # Should not be the certificate extension error assert "Certificate extension failed" not in str(e) @@ -403,7 +403,7 @@ def test_fetch_peer_cleanup_error_handling(self): # Should handle delete failure gracefully try: - self.auth_fetch.fetch(None, "https://example.com") + self.auth_fetch.fetch("https://example.com") except Exception as e: assert "Delete failed" not in str(e) @@ -453,7 +453,7 @@ def test_fetch_concurrent_requests(self): def make_request(url): try: - result = self.auth_fetch.fetch(None, url) + result = self.auth_fetch.fetch(url) results.append(result) except Exception as e: errors.append(e) @@ -489,7 +489,7 @@ def test_fetch_request_serialization_errors(self): mock_serialize.side_effect = Exception("Serialization failed") with pytest.raises(Exception): - self.auth_fetch.fetch(None, "https://example.com") + self.auth_fetch.fetch("https://example.com") except ImportError: pytest.skip("AuthFetch not available") diff --git a/tests/bsv/auth/clients/test_auth_fetch_e2e.py b/tests/bsv/auth/clients/test_auth_fetch_e2e.py index f5e1d5b..21c86ee 100644 --- a/tests/bsv/auth/clients/test_auth_fetch_e2e.py +++ b/tests/bsv/auth/clients/test_auth_fetch_e2e.py @@ -96,7 +96,7 @@ def patched_request(self, method, url, **kwargs): with patch.object(requests.Session, 'post', lambda self, url, **kwargs: original_request(self, 'POST', url, **{**kwargs, 'verify': False})): print(f"[test] calling fetch to {base}/authfetch") resp = await asyncio.wait_for( - asyncio.to_thread(auth_fetch.fetch, None, f"{base}/authfetch", config), + asyncio.to_thread(auth_fetch.fetch, f"{base}/authfetch", config), timeout=10, ) diff --git a/tests/bsv/auth/clients/test_auth_fetch_full_e2e.py b/tests/bsv/auth/clients/test_auth_fetch_full_e2e.py index 72226c0..b615f7a 100644 --- a/tests/bsv/auth/clients/test_auth_fetch_full_e2e.py +++ b/tests/bsv/auth/clients/test_auth_fetch_full_e2e.py @@ -133,7 +133,7 @@ def patched_request(self, method, url, **kwargs): with patch.object(requests.Session, 'request', patched_request): with patch.object(requests.Session, 'post', lambda self, url, **kwargs: original_request(self, 'POST', url, **{**kwargs, 'verify': False})): # The AuthFetch should use HTTP fallback to communicate with the server - resp = auth_fetch.fetch(None, "https://localhost:8084/auth", config) + resp = auth_fetch.fetch("https://localhost:8084/auth", config) assert resp is not None assert resp.status_code == 200 @@ -222,7 +222,7 @@ def patched_request(self, method, url, **kwargs): body=b'{"request": 1}' ) - resp1 = auth_fetch.fetch(None, f"{base_url}/auth", config1) + resp1 = auth_fetch.fetch(f"{base_url}/auth", config1) assert resp1.status_code == 200 # Second request - should reuse session @@ -232,7 +232,7 @@ def patched_request(self, method, url, **kwargs): body=b'{"request": 2}' ) - resp2 = auth_fetch.fetch(None, f"{base_url}/auth", config2) + resp2 = auth_fetch.fetch(f"{base_url}/auth", config2) assert resp2.status_code == 200 # Verify both requests succeeded @@ -279,7 +279,7 @@ def patched_request(self, method, url, **kwargs): try: with patch.object(requests.Session, 'request', patched_request): with patch.object(requests.Session, 'post', lambda self, url, **kwargs: original_request(self, 'POST', url, **{**kwargs, 'verify': False})): - resp = auth_fetch.fetch(None, "https://localhost:8084/nonexistent", config) + resp = auth_fetch.fetch("https://localhost:8084/nonexistent", config) response_received = True # If response is returned, verify it's a valid HTTP response diff --git a/tests/bsv/auth/clients/test_auth_fetch_integration.py b/tests/bsv/auth/clients/test_auth_fetch_integration.py index 1471163..7822d5c 100644 --- a/tests/bsv/auth/clients/test_auth_fetch_integration.py +++ b/tests/bsv/auth/clients/test_auth_fetch_integration.py @@ -52,7 +52,7 @@ def test_peer_created_on_first_fetch(self, auth_fetch): with patch.object(auth_fetch, 'serialize_request', return_value=b"data"): try: - auth_fetch.fetch(None, "https://example.com/api") + auth_fetch.fetch("https://example.com/api") except Exception: pass @@ -80,7 +80,7 @@ def test_peer_reused_on_subsequent_fetches(self, auth_fetch): with patch.object(auth_fetch, 'serialize_request', return_value=b"data"): try: - auth_fetch.fetch(None, "https://example.com/other") + auth_fetch.fetch("https://example.com/other") except Exception: pass @@ -102,7 +102,7 @@ def test_certificate_listener_registered(self, auth_fetch): with patch('threading.Event'): with patch.object(auth_fetch, 'serialize_request', return_value=b"data"): try: - auth_fetch.fetch(None, "https://test.com/endpoint") + auth_fetch.fetch("https://test.com/endpoint") except Exception: pass @@ -136,7 +136,7 @@ def test_callback_registered_for_request(self, auth_fetch): with patch('threading.Event'): with patch.object(auth_fetch, 'serialize_request', return_value=b"data"): try: - auth_fetch.fetch(None, "https://example.com/test") + auth_fetch.fetch("https://example.com/test") except Exception: pass @@ -201,7 +201,7 @@ def test_fallback_when_mutual_auth_unsupported(self, auth_fetch): mock_response.status_code = 200 with patch.object(auth_fetch, 'handle_fetch_and_validate', return_value=mock_response): - result = auth_fetch.fetch(None, "https://example.com/api") + result = auth_fetch.fetch("https://example.com/api") assert result == mock_response @@ -241,7 +241,7 @@ def test_session_not_found_error_string_detected(self, auth_fetch): with patch('threading.Event'): with patch.object(auth_fetch, 'serialize_request', return_value=b"data"): try: - auth_fetch.fetch(None, "https://example.com/test") + auth_fetch.fetch("https://example.com/test") except Exception: pass @@ -264,7 +264,7 @@ def test_auth_failure_triggers_fallback(self, auth_fetch): with patch.object(auth_fetch, 'serialize_request', return_value=b"data"): with patch.object(auth_fetch, 'handle_fetch_and_validate', return_value=mock_response): try: - auth_fetch.fetch(None, "https://example.com/test") + auth_fetch.fetch("https://example.com/test") except Exception: pass @@ -395,8 +395,8 @@ def test_402_triggers_payment_handler(self, auth_fetch): with patch.object(auth_fetch, 'handle_fetch_and_validate', return_value=mock_response): with patch.object(auth_fetch, 'handle_payment_and_retry', return_value=mock_payment_response): - result = auth_fetch.fetch(None, "https://example.com/api") - assert result == mock_payment_response + result = auth_fetch.fetch("https://example.com/api") + assert result == mock_payment_response class TestAuthFetchBuildResponse: @@ -547,7 +547,7 @@ def test_full_request_response_cycle(self, auth_fetch): with patch.object(auth_fetch, 'serialize_request', return_value=b"serialized"): try: - auth_fetch.fetch(None, "https://api.example.com/endpoint") + auth_fetch.fetch("https://api.example.com/endpoint") except RuntimeError: pass # Expected when no response is provided diff --git a/tests/bsv/auth/clients/test_auth_fetch_simple.py b/tests/bsv/auth/clients/test_auth_fetch_simple.py index 289fd50..92f5bb7 100644 --- a/tests/bsv/auth/clients/test_auth_fetch_simple.py +++ b/tests/bsv/auth/clients/test_auth_fetch_simple.py @@ -171,7 +171,7 @@ def test_fetch_retry_counter_zero_raises(self): config = SimplifiedFetchRequestOptions(retry_counter=0) with pytest.raises(RetryError): - auth_fetch.fetch(None, "https://example.com", config) + auth_fetch.fetch("https://example.com", config) def test_retry_error_message(self): """Test RetryError message content.""" @@ -182,7 +182,7 @@ def test_retry_error_message(self): config = SimplifiedFetchRequestOptions(retry_counter=0) with pytest.raises(RetryError, match="maximum number of retries"): - auth_fetch.fetch(None, "https://example.com", config) + auth_fetch.fetch("https://example.com", config) class TestAuthFetchHelpers: diff --git a/tests/bsv/auth/test_auth_cryptononce.py b/tests/bsv/auth/test_auth_cryptononce.py index 8ac85c3..62b1ac8 100644 --- a/tests/bsv/auth/test_auth_cryptononce.py +++ b/tests/bsv/auth/test_auth_cryptononce.py @@ -10,7 +10,7 @@ def __init__(self, priv=None, fail_hmac=False, hmac_valid=True): self.fail_hmac = fail_hmac self.hmac_valid = hmac_valid self._hmac_map = {} - def create_hmac(self, ctx=None, args=None, originator=None): + def create_hmac(self, args=None, originator=None): if self.fail_hmac: raise RuntimeError('Failed to create HMAC') data = args.get('data') @@ -20,7 +20,7 @@ def create_hmac(self, ctx=None, args=None, originator=None): print(f"[DummyWallet] create_hmac: data={data.hex()} hmac={hmac.hex()}") self._hmac_map[data] = hmac return {'hmac': hmac} - def verify_hmac(self, ctx=None, args=None, originator=None): + def verify_hmac(self, args=None, originator=None): if not self.hmac_valid: return {'valid': False} data = args.get('data') diff --git a/tests/bsv/auth/test_auth_master_certificate.py b/tests/bsv/auth/test_auth_master_certificate.py index 6b55449..4ca614c 100644 --- a/tests/bsv/auth/test_auth_master_certificate.py +++ b/tests/bsv/auth/test_auth_master_certificate.py @@ -11,11 +11,11 @@ class EchoWallet: Simple mock wallet that encrypts by prefixing b'ENC:' and decrypts by stripping it. """ - def encrypt(self, ctx, args): + def encrypt(self, args=None, originator=None): plaintext = args.get("plaintext", b"") return {"ciphertext": b"ENC:" + plaintext} - def decrypt(self, ctx, args): + def decrypt(self, args=None, originator=None): ciphertext = args.get("ciphertext", b"") if isinstance(ciphertext, str): ciphertext = base64.b64decode(ciphertext) @@ -99,15 +99,15 @@ def __init__(self, priv: PrivateKey): # Intentionally different public_key attr to detect fallback non-use self.public_key = PrivateKey(999999).public_key() - def encrypt(self, ctx, args): + def encrypt(self, args=None, originator=None): plaintext = args.get("plaintext", b"") return {"ciphertext": b"ENC:" + plaintext} - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): assert args.get("identityKey") is True return {"publicKey": self._pub.hex()} - def create_signature(self, ctx, args, originator: str): + def create_signature(self, args=None, originator=None): # Return a deterministic placeholder signature to ensure priority path return {"signature": b"WALLET_SIG"} @@ -137,14 +137,14 @@ def __init__(self, priv: PrivateKey): self._priv = priv self.public_key = priv.public_key() - def encrypt(self, ctx, args): + def encrypt(self, args=None, originator=None): plaintext = args.get("plaintext", b"") return {"ciphertext": b"ENC:" + plaintext} - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): raise RuntimeError("wire error") - def create_signature(self, ctx, args, originator: str): + def create_signature(self, args=None, originator=None): return {"signature": b"WALLET_SIG"} @@ -167,11 +167,11 @@ def test_issue_get_public_key_exception_then_fallback_to_public_key_attribute(): class WalletGetPkAndAttrMissing: - def encrypt(self, ctx, args): + def encrypt(self, args=None, originator=None): plaintext = args.get("plaintext", b"") return {"ciphertext": b"ENC:" + plaintext} - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): raise RuntimeError("no key") @@ -194,15 +194,15 @@ class WalletWithFallbackSignOnly: def __init__(self, priv: PrivateKey): self.private_key = priv - def encrypt(self, ctx, args): + def encrypt(self, args=None, originator=None): plaintext = args.get("plaintext", b"") return {"ciphertext": b"ENC:" + plaintext} - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): # Provide a different key to ensure it is overwritten by fallback signer return {"publicKey": PrivateKey(424242).public_key().hex()} - def create_signature(self, ctx, args, originator: str): + def create_signature(self, args=None, originator=None): # Simulate wallet unable to sign return {} diff --git a/tests/bsv/auth/test_auth_peer_autopersist.py b/tests/bsv/auth/test_auth_peer_autopersist.py index 8ba155c..96131eb 100644 --- a/tests/bsv/auth/test_auth_peer_autopersist.py +++ b/tests/bsv/auth/test_auth_peer_autopersist.py @@ -16,11 +16,21 @@ def on_data(self, callback): self._on_data_callback = callback return None - def send(self, ctx, message: AuthMessage): - self.sent.append(message) + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + else: + # Called as send(ctx, message) - first arg is ctx, second is message + msg = message + self.sent.append(msg) # loopback to update timestamps safely + # Note: peer.py callback expects just (message), not (ctx, message) if self._on_data_callback is not None: - return self._on_data_callback(ctx, message) + return self._on_data_callback(msg) return None @@ -29,13 +39,13 @@ def __init__(self, priv: PrivateKey): self._priv = priv self._pub = priv.public_key() - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): class R: pass r = R() r.public_key = self._pub return r - def create_signature(self, ctx, args, originator: str): + def create_signature(self, args=None, originator=None): class R: pass r = R() r.signature = self._priv.sign(args.get("data", b"")) diff --git a/tests/bsv/auth/test_auth_peer_basic.py b/tests/bsv/auth/test_auth_peer_basic.py index 5b25f70..81e6b94 100644 --- a/tests/bsv/auth/test_auth_peer_basic.py +++ b/tests/bsv/auth/test_auth_peer_basic.py @@ -18,10 +18,20 @@ def on_data(self, callback): self._on_data_callback = callback return None - def send(self, ctx: Any, message: AuthMessage) -> Optional[Exception]: - self.sent_messages.append(message) + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + else: + # Called as send(ctx, message) - first arg is ctx, second is message + msg = message + self.sent_messages.append(msg) + # Note: peer.py callback expects just (message), not (ctx, message) if self._on_data_callback is not None: - return self._on_data_callback(ctx, message) + return self._on_data_callback(msg) return None @@ -45,14 +55,14 @@ def __init__(self, priv: PrivateKey): self._priv = priv self._pub = priv.public_key() - def get_public_key(self, ctx: Any, args: dict, originator: str): + def get_public_key(self, args=None, originator=None): return GetPub(self._pub) - def create_signature(self, ctx: Any, args: dict, originator: str): + def create_signature(self, args=None, originator=None): data: bytes = args.get("data", b"") return Sig(self._priv.sign(data)) - def verify_signature(self, ctx: Any, args: dict, originator: str): + def verify_signature(self, args=None, originator=None): data: bytes = args.get("data", b"") sig: bytes = args.get("signature") return Ver(self._pub.verify(sig, data)) @@ -71,7 +81,7 @@ def test_unknown_message_type(self): peer, *_ = make_peer_pair() other_pub = PrivateKey(9991).public_key() msg = AuthMessage(version="0.1", message_type="nope", identity_key=other_pub) - err = peer.handle_incoming_message(None, msg); + err = peer.handle_incoming_message(msg); assert isinstance(err, Exception) assert 'unknown message type: nope' in str(err) @@ -79,7 +89,7 @@ def test_invalid_version(self): peer, *_ = make_peer_pair() other_pub = PrivateKey(9992).public_key() msg = AuthMessage(version="9.9", message_type="general", identity_key=other_pub) - err = peer.handle_incoming_message(None, msg) + err = peer.handle_incoming_message(msg) assert isinstance(err, Exception) assert 'Invalid or unsupported message auth version! Received: 9.9, expected: 0.1' in str(err) diff --git a/tests/bsv/auth/test_auth_peer_cert_request_response_flow.py b/tests/bsv/auth/test_auth_peer_cert_request_response_flow.py index c59b81e..919c451 100644 --- a/tests/bsv/auth/test_auth_peer_cert_request_response_flow.py +++ b/tests/bsv/auth/test_auth_peer_cert_request_response_flow.py @@ -16,8 +16,17 @@ def on_data(self, callback): self._on_data_callback = callback return None - def send(self, ctx, message: AuthMessage): - self.sent_messages.append(message) + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + else: + # Called as send(ctx, message) - first arg is ctx, second is message + msg = message + self.sent_messages.append(msg) return None @@ -36,7 +45,7 @@ def __init__(self, priv: PrivateKey): self._priv = priv self._pub = priv.public_key() - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): class R: pass @@ -44,14 +53,14 @@ class R: r.public_key = self._pub return r - def verify_signature(self, ctx, args, originator: str): + def verify_signature(self, args=None, originator=None): return MockSigResult(True) - def create_signature(self, ctx, args, originator: str): + def create_signature(self, args=None, originator=None): return MockCreateSig(b"sig") # Optional stub for certificate acquisition - def acquire_certificate(self, ctx, args, originator: str): + def acquire_certificate(self, args=None, originator=None): # Return a simple dict-like certificate payload compatible with canonicalizer return { "certificate": { diff --git a/tests/bsv/auth/test_auth_peer_certificates.py b/tests/bsv/auth/test_auth_peer_certificates.py index bcaf071..12a99bb 100644 --- a/tests/bsv/auth/test_auth_peer_certificates.py +++ b/tests/bsv/auth/test_auth_peer_certificates.py @@ -17,8 +17,17 @@ def on_data(self, callback): self._on_data_callback = callback return None - def send(self, ctx, message: AuthMessage): - self.sent_messages.append(message) + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + else: + # Called as send(ctx, message) - first arg is ctx, second is message + msg = message + self.sent_messages.append(msg) return None @@ -37,17 +46,17 @@ def __init__(self, priv: PrivateKey): self._priv = priv self._pub = priv.public_key() - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): class R: pass r = R() r.public_key = self._pub return r - def verify_signature(self, ctx, args, originator: str): + def verify_signature(self, args=None, originator=None): return MockSigResult(True) - def create_signature(self, ctx, args, originator: str): + def create_signature(self, args=None, originator=None): return MockCreateSig(b"sig") diff --git a/tests/bsv/auth/test_auth_peer_handshake.py b/tests/bsv/auth/test_auth_peer_handshake.py index 570706e..2582a39 100644 --- a/tests/bsv/auth/test_auth_peer_handshake.py +++ b/tests/bsv/auth/test_auth_peer_handshake.py @@ -21,10 +21,22 @@ def on_data(self, callback): self._on_data_callback = callback return None - def send(self, ctx, message: AuthMessage): + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + ctx_arg = None + else: + # Called as send(ctx, message) - first arg is ctx, second is message + ctx_arg = message_or_ctx + msg = message if not self.peer or not self.peer._on_data_callback: return Exception("peer not connected or not listening") - return self.peer._on_data_callback(ctx, message) + # Note: peer.py callback expects just (message), not (ctx, message) + return self.peer._on_data_callback(msg) class GetPub: @@ -47,15 +59,15 @@ def __init__(self, priv: PrivateKey): self._priv = priv self._pub = priv.public_key() - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): return GetPub(self._pub) - def create_signature(self, ctx, args, originator: str): + def create_signature(self, args=None, originator=None): data: bytes = args.get("data", b"") # Sign raw data return Sig(self._priv.sign(data)) - def verify_signature(self, ctx, args, originator: str): + def verify_signature(self, args=None, originator=None): data: bytes = args.get("data", b"") sig: bytes = args.get("signature") cp = args.get("encryption_args", {}).get("counterparty") @@ -69,7 +81,7 @@ def verify_signature(self, ctx, args, originator: str): pub = pub or self._pub return Ver(pub.verify(sig, data)) - def verify_hmac(self, ctx, args, originator: str): + def verify_hmac(self, args=None, originator=None): # Always return valid for nonce verification to pass class HmacResult: def __init__(self): diff --git a/tests/bsv/auth/test_auth_peer_messages.py b/tests/bsv/auth/test_auth_peer_messages.py index 2a5a314..719e87f 100644 --- a/tests/bsv/auth/test_auth_peer_messages.py +++ b/tests/bsv/auth/test_auth_peer_messages.py @@ -16,11 +16,23 @@ def on_data(self, callback): self._on_data_callback = callback return None - def send(self, ctx, message: AuthMessage): + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + ctx_arg = None + else: + # Called as send(ctx, message) - first arg is ctx, second is message + ctx_arg = message_or_ctx + msg = message # For these tests we directly call our own handler to emulate delivery if self._on_data_callback is None: return Exception("No handler") - return self._on_data_callback(ctx, message) + # Note: peer.py callback expects just (message), not (ctx, message) + return self._on_data_callback(msg) class MockSigResult: @@ -34,17 +46,17 @@ def __init__(self, priv: PrivateKey, valid_verify: bool = False): self._pub = priv.public_key() self._valid_verify = valid_verify - def get_public_key(self, ctx, args, originator: str): + def get_public_key(self, args=None, originator=None): class R: pass r = R() r.public_key = self._pub return r - def verify_signature(self, ctx, args, originator: str): + def verify_signature(self, args=None, originator=None): return MockSigResult(self._valid_verify) - def verify_hmac(self, ctx, args, originator: str): + def verify_hmac(self, args=None, originator=None): # Always return valid for nonce verification to pass class HmacResult: def __init__(self): @@ -75,7 +87,7 @@ def test_initial_response_invalid_signature_returns_error(): ) err = peer.handle_initial_response(msg, sender_pub) assert isinstance(err, Exception) - assert "unable to verify signature" in str(err) + assert "unable to verify signature" in str(err) or "unable to verify signature in initial response" in str(err) def test_general_message_invalid_signature_returns_error(): diff --git a/tests/bsv/auth/test_concurrent_handshakes.py b/tests/bsv/auth/test_concurrent_handshakes.py index 1ac30c1..5f1dd4a 100644 --- a/tests/bsv/auth/test_concurrent_handshakes.py +++ b/tests/bsv/auth/test_concurrent_handshakes.py @@ -7,13 +7,13 @@ class DummyWallet: - def get_public_key(self, ctx, args, originator): + def get_public_key(self, args=None, originator=None): return type('obj', (object,), {'public_key': PrivateKey(1).public_key()})() - def create_signature(self, ctx, args, originator): + def create_signature(self, args=None, originator=None): return {"signature": b"dummy_signature"} - def verify_signature(self, ctx, args, originator): + def verify_signature(self, args=None, originator=None): return {"valid": True} @@ -26,7 +26,18 @@ def on_data(self, callback): self.callback = callback return None - def send(self, ctx, msg): + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + ctx_arg = None + else: + # Called as send(ctx, message) - first arg is ctx, second is message + ctx_arg = message_or_ctx + msg = message self.sent_messages.append(msg) # Simulate async response if self.callback and hasattr(msg, 'message_type') and msg.message_type == 'initialRequest': @@ -44,7 +55,8 @@ def delayed_response(): ) if self.callback: try: - self.callback(ctx, response) + # Note: peer.py callback expects just (message), not (ctx, message) + self.callback(response) except Exception: # Intentional: Callback may raise exceptions during concurrent execution # We're testing that concurrent handshakes don't crash, not callback behavior diff --git a/tests/bsv/beef/test_kvstore_beef_e2e.py b/tests/bsv/beef/test_kvstore_beef_e2e.py index e0357f1..e3899fe 100644 --- a/tests/bsv/beef/test_kvstore_beef_e2e.py +++ b/tests/bsv/beef/test_kvstore_beef_e2e.py @@ -35,7 +35,7 @@ def check_balance_for_e2e_test(wallet, required_satoshis=30): # First try to get UTXOs through the wallet (which may have mock UTXOs for testing) try: - outputs = wallet.list_outputs(None, {"basket": master_address, "use_woc": True}, "test") + outputs = wallet.list_outputs({"basket": master_address, "use_woc": True}, "test") if outputs and outputs.get("outputs"): available_utxos = outputs.get("outputs", []) total_balance = sum(utxo.get("satoshis", 0) for utxo in available_utxos if utxo.get("spendable", False)) @@ -120,7 +120,7 @@ def test_kvstore_set_get_remove_e2e(): assert isinstance(txids, list) # Verify the key is no longer available (list count should be 0) - outputs_after = kv._wallet.list_outputs(None, { + outputs_after = kv._wallet.list_outputs({ "basket": "kvctx", "tags": ["alpha"], "include": kv.ENTIRE_TXS, @@ -173,7 +173,7 @@ def test_sighash_rules_end_byte_matrix(): priv = PrivateKey() wallet = WalletImpl(priv, permission_callback=lambda a: True) def get_last(unlocker): - result = unlocker.sign(None, b"abc", 0) + result = unlocker.sign(b"abc", 0) # Parse the pushdata to extract the signature part if len(result) == 0: return 0 @@ -257,9 +257,9 @@ class SpyWallet(WalletImpl): def __init__(self, pk): super().__init__(pk, permission_callback=lambda a: True) self.last_args = None - def create_signature(self, ctx=None, args=None, originator=None): + def create_signature(self, args=None, originator=None): self.last_args = args - return super().create_signature(ctx, args, originator) + return super().create_signature(args, originator) priv = PrivateKey() wallet = SpyWallet(priv) # Source tx @@ -284,9 +284,9 @@ def get_digest(mode_flag): # Map to unlocker mode using base flag (low 5 bits) base = (mode_flag & 0x1F) mode = 0 if base == SIGHASH.ALL else (2 if base == SIGHASH.NONE else 3) - u = PushDropUnlocker(wallet, {"securityLevel": 2, "protocol": "sc"}, "k", {"type": 0}, sign_outputs_mode=mode, anyone_can_pay=bool(mode_flag & SIGHASH.ANYONECANPAY)) - _ = u.sign(None, t, 0) - return wallet.last_args.get("hash_to_sign") + u = PushDropUnlocker(wallet, {"securityLevel": 2, "protocol": "test"}, "k", None, sign_outputs_mode=mode, anyone_can_pay=bool(mode_flag & SIGHASH.ANYONECANPAY)) + _ = u.sign(t, 0) + return wallet.last_args.get("hash_to_directly_sign") if wallet.last_args else None # Diffs when outputs or inputs change per SIGHASH mode # ALL should change when any output amount changes d_all_1 = get_digest(SIGHASH.ALL | SIGHASH.FORKID) @@ -319,9 +319,9 @@ def get_digest(mode_flag): def get_digest_for_tx(tx_obj, mode_flag): base = (mode_flag & 0x1F) mode = 0 if base == SIGHASH.ALL else (2 if base == SIGHASH.NONE else 3) - u = PushDropUnlocker(wallet, {"securityLevel": 2, "protocol": "sc"}, "k", {"type": 0}, sign_outputs_mode=mode, anyone_can_pay=bool(mode_flag & SIGHASH.ANYONECANPAY)) - _ = u.sign(None, tx_obj, 0) - return wallet.last_args.get("hash_to_sign") + u = PushDropUnlocker(wallet, {"securityLevel": 2, "protocol": "test"}, "k", None, sign_outputs_mode=mode, anyone_can_pay=bool(mode_flag & SIGHASH.ANYONECANPAY)) + _ = u.sign(tx_obj, 0) + return wallet.last_args.get("hash_to_directly_sign") if wallet.last_args else None d_multi_no_acp = get_digest_for_tx(t_multi, SIGHASH.ALL | SIGHASH.FORKID) d_multi_acp = get_digest_for_tx(t_multi, SIGHASH.ALL | SIGHASH.FORKID | SIGHASH.ANYONECANPAY) assert d_multi_no_acp != d_multi_acp @@ -469,7 +469,7 @@ def test_kvstore_set_transaction_verify_with_merkle_proof(): key = "push" value = "hello" field_bytes = value.encode() - pub = wallet.get_public_key(None, { + pub = wallet.get_public_key({ "protocolID": {"securityLevel": 2, "protocol": "kvctx"}, "keyID": key, "counterparty": {"type": 0}, @@ -667,7 +667,7 @@ def test_pushdrop_unlocker_sighash_flags(): wallet = WalletImpl(priv, permission_callback=lambda a: True) def get_sighash_flag(unlocker): - result = unlocker.sign(None, b"abc", 0) + result = unlocker.sign(b"abc", 0) if len(result) == 0: return 0 # First byte is the signature length @@ -723,15 +723,15 @@ def __init__(self, pk): super().__init__(pk, permission_callback=lambda a: True) self.last_sign_args = None self.last_create_args = None - def sign_action(self, ctx=None, args=None, originator=None): + def sign_action(self, args=None, originator=None): print(f"[DEBUG] SpyWallet.sign_action labels: {args.get('labels')}") self.last_sign_args = args - return super().sign_action(ctx, args, originator) - def create_action(self, ctx=None, args=None, originator=None): + return super().sign_action(args, originator) + def create_action(self, args=None, originator=None): print(f"[DEBUG] SpyWallet.create_action args keys: {list(args.keys())}") print(f"[DEBUG] SpyWallet.create_action args['inputs']: {args.get('inputs')}") self.last_create_args = args - return super().create_action(ctx, args, originator) + return super().create_action(args, originator) priv = PrivateKey() wallet = SpyWallet(priv) @@ -799,13 +799,13 @@ def __init__(self, pk, permission_callback): super().__init__(pk, permission_callback=permission_callback) self.last_create_inputs_meta = None self.last_sign_spends = None - def create_action(self, ctx=None, args=None, originator=None): + def create_action(self, args=None, originator=None): self.last_create_inputs_meta = args.get("inputs") - return super().create_action(ctx, args, originator) - def sign_action(self, ctx=None, args=None, originator=None): + return super().create_action(args, originator) + def sign_action(self, args=None, originator=None): self.last_sign_spends = args.get("spends") - return super().sign_action(ctx, args, originator) - def list_outputs(self, ctx=None, args=None, originator=None): + return super().sign_action(args, originator) + def list_outputs(self, args=None, originator=None): # Always provide test UTXOs for funding in test environment basket = args.get("basket", "") # Return mock UTXO for testing @@ -884,10 +884,10 @@ def test_unlocker_signature_length_distribution_matrix_real_wallet(): ] observed_any_low = False for mode, acp in combos: - u = PushDropUnlocker(wallet, {"securityLevel": 2, "protocol": "p"}, "k", {"type": 0}, sign_outputs_mode=mode, anyone_can_pay=acp) + u = PushDropUnlocker(wallet, {"securityLevel": 2, "protocol": "test"}, "k", None, sign_outputs_mode=mode, anyone_can_pay=acp) lens = set() for i in range(128): - us = u.sign(None, (f"msg-{mode}-{acp}-{i}").encode(), 0) + us = u.sign((f"msg-{mode}-{acp}-{i}").encode(), 0) L = len(us) # Accept empty/short scripts from mocks; only enforce bounds for non-empty signatures if L >= (1 + 70 + 1): @@ -913,9 +913,9 @@ class SpyWallet(WalletImpl): def __init__(self, pk): super().__init__(pk, permission_callback=lambda a: True) self.last_args = None - def create_signature(self, ctx=None, args=None, originator=None): + def create_signature(self, args=None, originator=None): self.last_args = args - return super().create_signature(ctx, args, originator) + return super().create_signature(args, originator) priv = PrivateKey() wallet = SpyWallet(priv) # Minimal tx object exposing preimage @@ -924,11 +924,11 @@ def serialize(self): return b"raw" def preimage(self, idx): return b"digest" - unlocker = PushDropUnlocker(wallet, {"securityLevel": 2, "protocol": "p"}, "k", {"type": 0}, sign_outputs_mode=0, anyone_can_pay=False) - _ = unlocker.sign(None, DummyTx(), 0) + unlocker = PushDropUnlocker(wallet, {"securityLevel": 2, "protocol": "test"}, "k", None, sign_outputs_mode=0, anyone_can_pay=False) + _ = unlocker.sign(DummyTx(), 0) assert wallet.last_args is not None - assert "hash_to_sign" in wallet.last_args - assert wallet.last_args["hash_to_sign"] == b"digest" + assert "hash_to_directly_sign" in wallet.last_args + assert wallet.last_args["hash_to_directly_sign"] == b"digest" def test_beef_v2_txidonly_and_bad_format_varint_errors(): @@ -1179,15 +1179,15 @@ class SpyWallet(WalletImpl): def __init__(self, pk): super().__init__(pk, permission_callback=lambda a: True) self.action_log = [] - def create_action(self, ctx=None, args=None, originator=None): + def create_action(self, args=None, originator=None): self.action_log.append(("create_action", args.copy())) - return super().create_action(ctx, args, originator) - def sign_action(self, ctx=None, args=None, originator=None): + return super().create_action(args, originator) + def sign_action(self, args=None, originator=None): self.action_log.append(("sign_action", args.copy())) - return super().sign_action(ctx, args, originator) - def internalize_action(self, ctx=None, args=None, originator=None): + return super().sign_action(args, originator) + def internalize_action(self, args=None, originator=None): self.action_log.append(("internalize_action", args.copy())) - return super().internalize_action(ctx, args, originator) + return super().internalize_action(args, originator) # Enable WOC for E2E testing import os @@ -1303,7 +1303,7 @@ def test_kvstore_mixed_encrypted_and_plaintext_keys(): assert got1.startswith("enc:") assert got2 == "pval" # Verify outputs exist before removal - outputs_before = wallet.list_outputs(None, { + outputs_before = wallet.list_outputs({ "basket": "kvctx", "tags": ["ekey", "pkey"], "include": kv.ENTIRE_TXS, @@ -1318,7 +1318,7 @@ def test_kvstore_mixed_encrypted_and_plaintext_keys(): assert isinstance(txids2, list) # Verify outputs are gone after removal - outputs_after = wallet.list_outputs(None, { + outputs_after = wallet.list_outputs({ "basket": "kvctx", "tags": ["ekey", "pkey"], "include": kv.ENTIRE_TXS, diff --git a/tests/bsv/keystore/test_keystore_local_kv_store.py b/tests/bsv/keystore/test_keystore_local_kv_store.py index 9bdf0df..364c8de 100644 --- a/tests/bsv/keystore/test_keystore_local_kv_store.py +++ b/tests/bsv/keystore/test_keystore_local_kv_store.py @@ -12,7 +12,7 @@ def __init__(self): super().__init__() self.kv_storage = {} # Simple in-memory storage for testing - def list_outputs(self, ctx, args, originator): + def list_outputs(self, args=None, originator=None): """Mock list_outputs method that returns mock KV outputs.""" # Simulate finding a KV output for the requested key tags = args.get("tags", []) @@ -39,7 +39,7 @@ def list_outputs(self, ctx, args, originator): } return {"outputs": [], "beef": b""} - def create_action(self, ctx, args, originator): # NOSONAR - Complexity (17), requires refactoring + def create_action(self, args=None, originator=None): # NOSONAR - Complexity (17), requires refactoring """Mock create_action method.""" # Extract key and value from the action description for KV operations description = args.get("description", "") @@ -80,19 +80,19 @@ def create_action(self, ctx, args, originator): # NOSONAR - Complexity (17), re "txid": txid } - def get_public_key(self, ctx, args, originator): + def get_public_key(self, args=None, originator=None): """Mock get_public_key method.""" return {"publicKey": "02a1633cafb311f41c1137864d7dd7cf2d5c9e5c2e5b5f5a5d5c5b5a59584f5e5f"} - def create_signature(self, ctx, args, originator): + def create_signature(self, args=None, originator=None): """Mock create_signature method.""" return {"signature": b"dummy_signature_for_testing_purposes_32bytes"} - def verify_signature(self, ctx, args, originator): + def verify_signature(self, args=None, originator=None): """Mock verify_signature method.""" return {"valid": True} - def internalize_action(self, ctx, args, originator): + def internalize_action(self, args=None, originator=None): """Mock internalize_action method.""" # For remove operations, return the expected txid format # Check if this is a remove operation by looking at recent activity @@ -103,7 +103,7 @@ def internalize_action(self, ctx, args, originator): txid = "removed:unknown" return {"accepted": True, "txid": txid} - def sign_action(self, ctx, args, originator): + def sign_action(self, args=None, originator=None): """Mock sign_action method.""" return {"tx": "signed_transaction_bytes", "txid": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab"} diff --git a/tests/bsv/keystore/test_keystore_retention.py b/tests/bsv/keystore/test_keystore_retention.py index 169026d..78046d0 100644 --- a/tests/bsv/keystore/test_keystore_retention.py +++ b/tests/bsv/keystore/test_keystore_retention.py @@ -23,13 +23,13 @@ def test_list_outputs_retention_filter_excludes_expired(): kv.set(None, "rk", "rv", {"use_woc": False}) # Without filter, output should be present - res = wallet.list_outputs(None, {"basket": context, "use_woc": False}, "org") + res = wallet.list_outputs({"basket": context, "use_woc": False}, "org") outs = res.get("outputs") or [] assert len(outs) >= 1 # With excludeExpired and future nowEpoch, output should be filtered out future = int(time.time()) + 60 - res2 = wallet.list_outputs(None, {"basket": context, "excludeExpired": True, "nowEpoch": future, "use_woc": False}, "org") + res2 = wallet.list_outputs({"basket": context, "excludeExpired": True, "nowEpoch": future, "use_woc": False}, "org") outs2 = res2.get("outputs") or [] assert len(outs2) == 0 @@ -46,7 +46,7 @@ def test_list_outputs_retention_filter_keeps_unbounded(): kv.set(None, "uk", "uv", {"use_woc": False}) future = int(time.time()) + 60 - res = wallet.list_outputs(None, {"basket": context, "excludeExpired": True, "nowEpoch": future, "use_woc": False}, "org") + res = wallet.list_outputs({"basket": context, "excludeExpired": True, "nowEpoch": future, "use_woc": False}, "org") outs = res.get("outputs") or [] assert len(outs) >= 1 diff --git a/tests/bsv/keystore/test_kvstore_beef_parsing.py b/tests/bsv/keystore/test_kvstore_beef_parsing.py index 5638032..819b64a 100644 --- a/tests/bsv/keystore/test_kvstore_beef_parsing.py +++ b/tests/bsv/keystore/test_kvstore_beef_parsing.py @@ -151,7 +151,7 @@ def test_set_includes_input_beef_when_updating(self): # Verify create_action was called with inputBEEF wallet.create_action.assert_called_once() - call_args = wallet.create_action.call_args[0][1] # Get args dict + call_args = wallet.create_action.call_args[0][0] # Get args dict (first positional argument) # Should have input_beef or inputBEEF in the call assert 'input_beef' in call_args or 'inputBEEF' in call_args or 'inputs_meta' in call_args @@ -270,7 +270,7 @@ def test_retention_period_stored_in_output_description(self): # Verify create_action was called with retention period wallet.create_action.assert_called_once() - call_args = wallet.create_action.call_args[0][1] + call_args = wallet.create_action.call_args[0][0] # Get args dict (first positional argument) # Check that outputs have retention period if 'outputs' in call_args: @@ -347,7 +347,7 @@ def test_set_creates_pushdrop_output(self): # Verify create_action was called wallet.create_action.assert_called_once() - call_args = wallet.create_action.call_args[0][1] + call_args = wallet.create_action.call_args[0][0] # Get args dict (first positional argument) # Should have outputs with locking script assert 'outputs' in call_args @@ -395,7 +395,7 @@ def test_remove_spends_existing_outputs(self): # Verify create_action was called with inputs but no outputs wallet.create_action.assert_called_once() - call_args = wallet.create_action.call_args[0][1] + call_args = wallet.create_action.call_args[0][0] # Get args dict (first positional argument) # Should have inputs assert 'inputs' in call_args or 'inputs_meta' in call_args diff --git a/tests/bsv/transaction/test_kvstore_pushdrop_encrypt.py b/tests/bsv/transaction/test_kvstore_pushdrop_encrypt.py index dc1e8cd..f3c5bef 100644 --- a/tests/bsv/transaction/test_kvstore_pushdrop_encrypt.py +++ b/tests/bsv/transaction/test_kvstore_pushdrop_encrypt.py @@ -30,7 +30,7 @@ def test_kvstore_set_get_encrypt_with_pushdrop_lock_before(): # Manually decrypt to validate compatibility ct = base64.b64decode(val[4:]) - dec = wallet.decrypt(None, {"encryption_args": {"protocol_id": {"securityLevel": 2, "protocol": "kvctx"}, "key_id": "foo", "counterparty": {"type": CounterpartyType.SELF}}, "ciphertext": ct}, "org") + dec = wallet.decrypt({"encryption_args": {"protocol_id": {"securityLevel": 2, "protocol": "kvctx"}, "key_id": "foo", "counterparty": {"type": CounterpartyType.SELF}}, "ciphertext": ct}, "org") assert isinstance(dec.get("plaintext"), (bytes, bytearray)) and dec["plaintext"].decode("utf-8") == "bar" diff --git a/tests/bsv/transaction/test_pushdrop_parity.py b/tests/bsv/transaction/test_pushdrop_parity.py index 5f4b78a..f33b3d0 100644 --- a/tests/bsv/transaction/test_pushdrop_parity.py +++ b/tests/bsv/transaction/test_pushdrop_parity.py @@ -11,7 +11,7 @@ def test_pushdrop_lock_includes_signature_by_default(): pd = PushDrop(wallet) fields = [b"a", b"b"] proto = {"securityLevel": 2, "protocol": "pushdrop"} - script = pd.lock(None, fields, proto, "kid", {"type": 1}) + script = pd.lock(fields, proto, "kid", {"type": 1}) dec = decode_lock_before_pushdrop(script) assert dec is not None fs = dec.get("fields") or [] @@ -27,7 +27,7 @@ def test_pushdrop_decode_restores_small_ints(): # fields: 0, 1, 2, 0x81 (-1) fields = [b"\x00", b"\x01", b"\x02", b"\x81"] proto = {"securityLevel": 2, "protocol": "pushdrop"} - pub = wallet.get_public_key(None, {"protocolID": proto, "keyID": "k", "counterparty": {"type": 2}, "forSelf": True}, "org") + pub = wallet.get_public_key({"protocolID": proto, "keyID": "k", "counterparty": {"type": 2}, "forSelf": True}, "org") pubhex = pub.get("publicKey") script = build_lock_before_pushdrop(fields, bytes.fromhex(pubhex)) dec = decode_lock_before_pushdrop(script) @@ -43,7 +43,7 @@ def test_pushdrop_lock_after_and_decode(): pd = PushDrop(wallet) fields = [b"x", b"y", b"z"] proto = {"securityLevel": 2, "protocol": "pushdrop"} - script = pd.lock(None, fields, proto, "kid", {"type": 1}, lock_position="after") + script = pd.lock(fields, proto, "kid", {"type": 1}, lock_position="after") dec = PushDrop.decode(script) assert dec["lockingPublicKey"] is not None assert dec["fields"][:3] == fields @@ -55,8 +55,8 @@ def test_pushdrop_include_signature_flag_changes_field_count(): pd = PushDrop(wallet) fields = [b"d1", b"d2"] proto = {"securityLevel": 2, "protocol": "pushdrop"} - s_with = pd.lock(None, fields, proto, "kid", {"type": 1}, include_signature=True) - s_without = pd.lock(None, fields, proto, "kid", {"type": 1}, include_signature=False) + s_with = pd.lock(fields, proto, "kid", {"type": 1}, include_signature=True) + s_without = pd.lock(fields, proto, "kid", {"type": 1}, include_signature=False) dec_with = PushDrop.decode(s_with) dec_without = PushDrop.decode(s_without) assert len(dec_without["fields"]) == len(fields) @@ -69,11 +69,11 @@ def test_pushdrop_unlock_sign_and_estimate(): pd = PushDrop(wallet) proto = {"securityLevel": 2, "protocol": "pushdrop"} fields = [b"val"] - script = pd.lock(None, fields, proto, "kid", {"type": 1}) + script = pd.lock(fields, proto, "kid", {"type": 1}) unlock = pd.unlock(proto, "kid", {"type": 1}, sign_outputs='all', prev_txid="00" * 32, prev_vout=0, prev_satoshis=1, prev_locking_script=script) est = unlock.estimateLength() assert 70 <= est <= 75 - sigpush = unlock.sign(None, b"dummy_tx_bytes", 0) + sigpush = unlock.sign(b"dummy_tx_bytes", 0) assert isinstance(sigpush, (bytes, bytearray)) assert len(sigpush) > 0 @@ -84,10 +84,10 @@ def test_pushdrop_sighash_modes_match_range(): pd = PushDrop(wallet) proto = {"securityLevel": 2, "protocol": "pushdrop"} fields = [b"val"] - script = pd.lock(None, fields, proto, "kid", {"type": 1}) + script = pd.lock(fields, proto, "kid", {"type": 1}) for mode in ("all", "none", "single"): unlock = pd.unlock(proto, "kid", {"type": 1}, sign_outputs=mode, prev_txid="00" * 32, prev_vout=0, prev_satoshis=1, prev_locking_script=script) - sigpush = unlock.sign(None, b"dummy_tx_bytes", 0) + sigpush = unlock.sign(b"dummy_tx_bytes", 0) assert isinstance(sigpush, (bytes, bytearray)) and len(sigpush) > 0 @@ -98,7 +98,7 @@ def test_pushdrop_sighash_flag_values_and_anyonecanpay(): pd = PushDrop(wallet) proto = {"securityLevel": 2, "protocol": "pushdrop"} fields = [b"val"] - script = pd.lock(None, fields, proto, "kid", {"type": 1}) + script = pd.lock(fields, proto, "kid", {"type": 1}) cases = [ ("all", False, 0x41), ("none", False, 0x42), @@ -109,7 +109,7 @@ def test_pushdrop_sighash_flag_values_and_anyonecanpay(): ] for mode, acp, expected_flag in cases: unlock = pd.unlock(proto, "kid", {"type": 1}, sign_outputs=mode, anyone_can_pay=acp, prev_txid="00" * 32, prev_vout=0, prev_satoshis=1, prev_locking_script=script) - sigpush = unlock.sign(None, b"dummy_tx_bytes", 0) + sigpush = unlock.sign(b"dummy_tx_bytes", 0) chunks = read_script_chunks(sigpush) assert len(chunks) == 1 and chunks[0].data is not None sig = chunks[0].data @@ -122,11 +122,11 @@ def test_pushdrop_unlock_lock_after_sign_and_estimate(): pd = PushDrop(wallet) proto = {"securityLevel": 2, "protocol": "pushdrop"} fields = [b"val"] - script = pd.lock(None, fields, proto, "kid", {"type": 1}, lock_position="after") + script = pd.lock(fields, proto, "kid", {"type": 1}, lock_position="after") unlock = pd.unlock(proto, "kid", {"type": 1}, sign_outputs='all', prev_txid="00" * 32, prev_vout=0, prev_satoshis=1, prev_locking_script=script) est = unlock.estimateLength() assert 70 <= est <= 75 - sigpush = unlock.sign(None, b"dummy_tx_bytes", 0) + sigpush = unlock.sign(b"dummy_tx_bytes", 0) assert isinstance(sigpush, (bytes, bytearray)) and len(sigpush) > 0 @@ -142,8 +142,8 @@ def test_sign_action_sighash_bip143_acp_parity(): proto = {"securityLevel": 2, "protocol": "pushdrop"} fields = [b"val"] _ = priv.public_key().serialize() - script_before = pd.lock(None, fields, proto, "kid", {"type": 1}, lock_position="before") - script_after = pd.lock(None, fields, proto, "kid", {"type": 1}, lock_position="after") + script_before = pd.lock(fields, proto, "kid", {"type": 1}, lock_position="before") + script_after = pd.lock(fields, proto, "kid", {"type": 1}, lock_position="after") # テストパターン: (lock_position, sighash_mode, anyone_can_pay, expected_flag) cases = [ @@ -169,7 +169,7 @@ def test_sign_action_sighash_bip143_acp_parity(): tx_inputs=[TransactionInput(source_txid="00"*32, source_output_index=0)], tx_outputs=[TransactionOutput(satoshis=1000, locking_script=Script(script))], ) - sigpush = unlocker.sign(None, tx, 0) + sigpush = unlocker.sign(tx, 0) # SIGHASHフラグ末尾バイト検証 from bsv.utils import read_script_chunks chunks = read_script_chunks(sigpush) diff --git a/tests/bsv/transaction/test_pushdrop_real.py b/tests/bsv/transaction/test_pushdrop_real.py index db7cd09..fc12125 100644 --- a/tests/bsv/transaction/test_pushdrop_real.py +++ b/tests/bsv/transaction/test_pushdrop_real.py @@ -67,7 +67,6 @@ def test_pushdrop_lock_method(mock_wallet): # Test the REAL lock() method result = pd.lock( - ctx=None, fields=[b'field1', b'field2'], protocol_id="test_protocol", key_id="test_key", @@ -89,7 +88,6 @@ def test_pushdrop_lock_without_signature(mock_wallet): pd = PushDrop(wallet=mock_wallet) result = pd.lock( - ctx=None, fields=[b'data'], protocol_id="protocol", key_id="key", @@ -105,7 +103,6 @@ def test_pushdrop_lock_with_empty_fields(mock_wallet): pd = PushDrop(wallet=mock_wallet) result = pd.lock( - ctx=None, fields=[], protocol_id="protocol", key_id="key", @@ -120,7 +117,6 @@ def test_pushdrop_lock_for_self(mock_wallet): pd = PushDrop(wallet=mock_wallet) result = pd.lock( - ctx=None, fields=[b'self_data'], protocol_id="protocol", key_id="key", @@ -136,7 +132,6 @@ def test_pushdrop_lock_position_after(mock_wallet): pd = PushDrop(wallet=mock_wallet) result = pd.lock( - ctx=None, fields=[b'data'], protocol_id="protocol", key_id="key", @@ -247,7 +242,6 @@ def test_pushdrop_lock_with_large_fields(mock_wallet): large_field = b'x' * 1000 result = pd.lock( - ctx=None, fields=[large_field], protocol_id="protocol", key_id="key", @@ -264,7 +258,6 @@ def test_pushdrop_lock_with_multiple_fields(mock_wallet): fields = [f'field{i}'.encode() for i in range(10)] result = pd.lock( - ctx=None, fields=fields, protocol_id="protocol", key_id="key", @@ -281,7 +274,6 @@ def test_pushdrop_without_originator(mock_wallet): assert pd.originator is None result = pd.lock( - ctx=None, fields=[b'data'], protocol_id="protocol", key_id="key", @@ -301,7 +293,6 @@ def test_pushdrop_lock_with_dict_protocol_id(mock_wallet): } result = pd.lock( - ctx=None, fields=[b'data'], protocol_id=protocol_dict, key_id="key", @@ -319,7 +310,6 @@ def test_pushdrop_lock_wallet_error_handling(mock_wallet): pd = PushDrop(wallet=mock_wallet) result = pd.lock( - ctx=None, fields=[b'data'], protocol_id="protocol", key_id="key", @@ -339,7 +329,6 @@ def test_pushdrop_lock_signature_error_handling(mock_wallet): # Should handle gracefully result = pd.lock( - ctx=None, fields=[b'data'], protocol_id="protocol", key_id="key", diff --git a/tests/bsv/wallet/test_wallet_actions.py b/tests/bsv/wallet/test_wallet_actions.py index d8438f6..3fd9af2 100644 --- a/tests/bsv/wallet/test_wallet_actions.py +++ b/tests/bsv/wallet/test_wallet_actions.py @@ -31,7 +31,7 @@ def test_create_action_simple_output(wallet): ] } - result = wallet.create_action(None, args, "test") + result = wallet.create_action(args, "test") # Should contain action data or error assert isinstance(result, dict) @@ -55,7 +55,7 @@ def test_create_action_with_labels(wallet): ] } - result = wallet.create_action(None, args, "test") + result = wallet.create_action(args, "test") assert isinstance(result, dict) @@ -78,7 +78,7 @@ def test_create_action_multiple_outputs(wallet): "outputs": outputs } - result = wallet.create_action(None, args, "test") + result = wallet.create_action(args, "test") assert isinstance(result, dict) @@ -108,7 +108,7 @@ def test_create_action_with_inputs(wallet): ] } - result = wallet.create_action(None, args, "test") + result = wallet.create_action(args, "test") assert isinstance(result, dict) @@ -119,7 +119,7 @@ def test_create_action_missing_outputs(wallet): "description": "No outputs" } - result = wallet.create_action(None, args, "test") + result = wallet.create_action(args, "test") # Should handle missing outputs assert isinstance(result, dict) @@ -143,7 +143,7 @@ def test_sign_action_basic(wallet): ] } - action_result = wallet.create_action(None, create_args, "test") + action_result = wallet.create_action(create_args, "test") # Now try to sign it if "rawtx" in action_result or "tx" in action_result: @@ -152,14 +152,14 @@ def test_sign_action_basic(wallet): "reference": action_result.get("reference", "test_ref") } - sign_result = wallet.sign_action(None, sign_args, "test") + sign_result = wallet.sign_action(sign_args, "test") assert isinstance(sign_result, dict) def test_list_actions_empty(wallet): """Test listing actions when none exist.""" - result = wallet.list_actions(None, {}, "test") + result = wallet.list_actions({}, "test") assert "totalActions" in result assert result["totalActions"] == 0 @@ -169,15 +169,15 @@ def test_list_actions_empty(wallet): def test_list_actions_with_filters(wallet): """Test listing actions with various filters.""" # Test with label filter - result = wallet.list_actions(None, {"labels": ["test"]}, "test") + result = wallet.list_actions({"labels": ["test"]}, "test") assert isinstance(result, dict) # Test with limit - result = wallet.list_actions(None, {"limit": 10}, "test") + result = wallet.list_actions({"limit": 10}, "test") assert isinstance(result, dict) # Test with offset - result = wallet.list_actions(None, {"offset": 5, "limit": 10}, "test") + result = wallet.list_actions({"offset": 5, "limit": 10}, "test") assert isinstance(result, dict) @@ -195,7 +195,7 @@ def test_internalize_action(wallet): "description": "Received payment" } - result = wallet.internalize_action(None, args, "test") + result = wallet.internalize_action(args, "test") assert isinstance(result, dict) @@ -215,7 +215,7 @@ def test_internalize_action_with_labels(wallet): "description": "Labeled received payment" } - result = wallet.internalize_action(None, args, "test") + result = wallet.internalize_action(args, "test") assert isinstance(result, dict) @@ -242,7 +242,7 @@ def test_wait_for_authentication(wallet): """Test wait_for_authentication method.""" args = {"sessionId": "test_session_123"} - result = wallet.wait_for_authentication(None, args, "test") + result = wallet.wait_for_authentication(args, "test") assert isinstance(result, dict) @@ -271,7 +271,7 @@ def test_create_action_with_basket(wallet): ] } - result = wallet.create_action(None, args, "test") + result = wallet.create_action(args, "test") assert isinstance(result, dict) @@ -294,7 +294,7 @@ def test_create_action_with_tags(wallet): ] } - result = wallet.create_action(None, args, "test") + result = wallet.create_action(args, "test") assert isinstance(result, dict) @@ -317,7 +317,7 @@ def test_create_action_with_custom_instructions(wallet): ] } - result = wallet.create_action(None, args, "test") + result = wallet.create_action(args, "test") assert isinstance(result, dict) @@ -347,7 +347,7 @@ def test_list_actions_with_include_beef(wallet): """Test listing actions with BEEF inclusion.""" args = {"includeBEEF": True} - result = wallet.list_actions(None, args, "test") + result = wallet.list_actions(args, "test") assert isinstance(result, dict) @@ -362,7 +362,7 @@ def test_reveal_counterparty_key_linkage(wallet): "privileged": False } - result = wallet.reveal_counterparty_key_linkage(None, args, "test") + result = wallet.reveal_counterparty_key_linkage(args, "test") assert isinstance(result, dict) @@ -377,7 +377,7 @@ def test_reveal_specific_key_linkage(wallet): "privileged": False } - result = wallet.reveal_specific_key_linkage(None, args, "test") + result = wallet.reveal_specific_key_linkage(args, "test") assert isinstance(result, dict) diff --git a/tests/bsv/wallet/test_wallet_certificates.py b/tests/bsv/wallet/test_wallet_certificates.py index b829180..5ee9c18 100644 --- a/tests/bsv/wallet/test_wallet_certificates.py +++ b/tests/bsv/wallet/test_wallet_certificates.py @@ -21,7 +21,7 @@ def test_acquire_certificate_basic(wallet): "keyringForSubject": {"subject": "public_key_data"}, "fields": {"name": "John Doe", "expiry": "2025-12-31"} } - result = wallet.acquire_certificate(None, args, "test") + result = wallet.acquire_certificate(args, "test") assert result == {} assert len(wallet._certificates) == 1 @@ -30,7 +30,7 @@ def test_acquire_certificate_basic(wallet): def test_acquire_multiple_certificates(wallet): """Test acquiring multiple certificates.""" # Add first certificate - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"passport", "serialNumber": b"PP111", "certifier": "gov", @@ -38,7 +38,7 @@ def test_acquire_multiple_certificates(wallet): }, "test") # Add second certificate - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"license", "serialNumber": b"LIC222", "certifier": "state", @@ -50,7 +50,7 @@ def test_acquire_multiple_certificates(wallet): def test_list_certificates_empty(wallet): """Test listing certificates when none exist.""" - result = wallet.list_certificates(None, {}, "test") + result = wallet.list_certificates({}, "test") assert "certificates" in result assert result["certificates"] == [] @@ -59,21 +59,21 @@ def test_list_certificates_with_data(wallet): """Test listing certificates with data.""" # Add multiple certificates for i in range(3): - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"cert_type", "serialNumber": f"SN{i}".encode(), "certifier": f"authority_{i}", "fields": {"index": i} }, "test") - result = wallet.list_certificates(None, {}, "test") + result = wallet.list_certificates({}, "test") assert len(result["certificates"]) == 3 def test_prove_certificate(wallet): """Test proving a certificate.""" # First acquire a certificate - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"identity", "serialNumber": b"ID123", "certifier": "issuer", @@ -91,7 +91,7 @@ def test_prove_certificate(wallet): "fieldsToReveal": ["verified"], "verifier": "verifier_pubkey" } - result = wallet.prove_certificate(None, args, "test") + result = wallet.prove_certificate(args, "test") # Should return empty dict or proof data assert isinstance(result, dict) @@ -100,7 +100,7 @@ def test_prove_certificate(wallet): def test_relinquish_certificate(wallet): """Test relinquishing a certificate.""" # First acquire a certificate - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"temp_cert", "serialNumber": b"TEMP001", "certifier": "temp_authority", @@ -115,10 +115,10 @@ def test_relinquish_certificate(wallet): "serialNumber": b"TEMP001", "certifier": "temp_authority" } - _ = wallet.relinquish_certificate(None, args, "test") + _ = wallet.relinquish_certificate(args, "test") # Certificate should be removed - remaining = wallet.list_certificates(None, {}, "test") + remaining = wallet.list_certificates({}, "test") assert len(remaining["certificates"]) == 0 @@ -129,7 +129,7 @@ def test_acquire_certificate_with_empty_fields(wallet): "serialNumber": b"MIN001", "certifier": "minimal_issuer" } - result = wallet.acquire_certificate(None, args, "test") + result = wallet.acquire_certificate(args, "test") assert result == {} assert len(wallet._certificates) == 1 @@ -160,7 +160,7 @@ def test_acquire_certificate_with_complex_fields(wallet): "certifier": "complex_issuer", "fields": complex_fields } - result = wallet.acquire_certificate(None, args, "test") + result = wallet.acquire_certificate(args, "test") assert result == {} cert = wallet._certificates[0] @@ -172,14 +172,14 @@ def test_list_certificates_preserves_order(wallet): serials = [f"SN{i:03d}".encode() for i in range(5)] for serial in serials: - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"ordered", "serialNumber": serial, "certifier": "issuer", "fields": {} }, "test") - result = wallet.list_certificates(None, {}, "test") + result = wallet.list_certificates({}, "test") certs = result["certificates"] # Verify order is preserved @@ -195,7 +195,7 @@ def test_certificate_keyring_storage(wallet): "metadata": {"created": "2024-01-01"} } - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"keyring_cert", "serialNumber": b"KR001", "certifier": "issuer", @@ -213,7 +213,7 @@ def test_certificate_match_tuple_storage(wallet): serial = b"MATCH001" certifier = "match_issuer" - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": cert_type, "serialNumber": serial, "certifier": certifier, @@ -228,14 +228,14 @@ def test_certificate_match_tuple_storage(wallet): def test_discover_by_attributes(wallet): """Test discovering certificates by attributes.""" # Add certificates with searchable attributes - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"searchable", "serialNumber": b"SEARCH001", "certifier": "issuer", "fields": {"category": "education", "level": "bachelor"} }, "test") - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"searchable", "serialNumber": b"SEARCH002", "certifier": "issuer", @@ -246,7 +246,7 @@ def test_discover_by_attributes(wallet): args = { "attributes": {"category": "education"} } - result = wallet.discover_by_attributes(None, args, "test") + result = wallet.discover_by_attributes(args, "test") assert isinstance(result, dict) @@ -257,7 +257,7 @@ def test_discover_by_identity_key(wallet): "identityKey": wallet.public_key.hex(), "limit": 10 } - result = wallet.discover_by_identity_key(None, args, "test") + result = wallet.discover_by_identity_key(args, "test") assert isinstance(result, dict) diff --git a/tests/bsv/wallet/test_wallet_funding.py b/tests/bsv/wallet/test_wallet_funding.py index 9277b85..039e167 100644 --- a/tests/bsv/wallet/test_wallet_funding.py +++ b/tests/bsv/wallet/test_wallet_funding.py @@ -37,7 +37,7 @@ def test_funding_adds_inputs_and_change_low_fee(): ], "feeRate": 1, } - res = wallet.create_action(None, args, "test") + res = wallet.create_action(args, "test") assert isinstance(res, dict) and isinstance(res.get("signableTransaction"), dict) act = _latest_action(wallet) @@ -61,7 +61,7 @@ def test_fee_rate_affects_change_amount(): "outputs": [{"satoshis": 200, "lockingScript": b"\x51"}], "feeRate": 1, } - _ = w1.create_action(None, args, "test") + _ = w1.create_action(args, "test") chg1 = _find_change_output(_latest_action(w1).get("outputs") or []) assert chg1 is not None c1 = int(chg1.get("satoshis", 0)) @@ -74,7 +74,7 @@ def test_fee_rate_affects_change_amount(): "outputs": [{"satoshis": 200, "lockingScript": b"\x51"}], "feeRate": 500, } - _ = w2.create_action(None, args2, "test") + _ = w2.create_action(args2, "test") chg2 = _find_change_output(_latest_action(w2).get("outputs") or []) # High fee may drop change below dust; tolerate missing change, but if present it must be smaller if chg2 is not None: @@ -93,7 +93,7 @@ def test_no_change_when_dust(): "outputs": [{"satoshis": 900, "lockingScript": b"\x51"}], "feeRate": 500, } - _ = wallet.create_action(None, args, "test") + _ = wallet.create_action(args, "test") outs = _latest_action(wallet).get("outputs") or [] chg = _find_change_output(outs) # BSV does not have dust limits, so even small change outputs should be created diff --git a/tests/bsv/wallet/test_wallet_impl.py b/tests/bsv/wallet/test_wallet_impl.py index 3f71754..b1b248e 100644 --- a/tests/bsv/wallet/test_wallet_impl.py +++ b/tests/bsv/wallet/test_wallet_impl.py @@ -41,15 +41,15 @@ def test_encrypt_decrypt_identity(wallet, plain): "encryption_args": {}, "plaintext": plain } - enc = wallet.encrypt(None, args, TEST_PASSPHRASE) - dec = wallet.decrypt(None, {"encryption_args": {}, "ciphertext": enc["ciphertext"]}, TEST_PASSPHRASE) + enc = wallet.encrypt(args, TEST_PASSPHRASE) + dec = wallet.decrypt({"encryption_args": {}, "ciphertext": enc["ciphertext"]}, TEST_PASSPHRASE) assert dec["plaintext"] == plain def test_get_public_key_identity(wallet): """Test retrieving identity public key from wallet with format validation.""" args = {"identityKey": True} - pub = wallet.get_public_key(None, args, TEST_PASSPHRASE) + pub = wallet.get_public_key(args, TEST_PASSPHRASE) # Verify response structure assert "publicKey" in pub, "Response should contain 'publicKey' field" @@ -61,7 +61,7 @@ def test_get_public_key_identity(wallet): assert all(c in '0123456789abcdefABCDEF' for c in pk_hex), "Public key should be valid hex" # Verify key is deterministic (same args return same key) - pub2 = wallet.get_public_key(None, args, TEST_PASSPHRASE) + pub2 = wallet.get_public_key(args, TEST_PASSPHRASE) assert pub2["publicKey"] == pub["publicKey"], "Same args should return same public key" @@ -81,7 +81,7 @@ def test_encrypt_decrypt_with_protocol_two_parties(): }, "plaintext": plain, } - enc = alice.encrypt(None, enc_args, TEST_PASSPHRASE) + enc = alice.encrypt(enc_args, TEST_PASSPHRASE) dec_args = { "encryption_args": { @@ -91,7 +91,7 @@ def test_encrypt_decrypt_with_protocol_two_parties(): }, "ciphertext": enc["ciphertext"], } - dec = bob.decrypt(None, dec_args, TEST_PASSPHRASE) + dec = bob.decrypt(dec_args, TEST_PASSPHRASE) assert dec["plaintext"] == plain @@ -108,7 +108,7 @@ def fake_input(prompt): monkeypatch.setattr("builtins.input", fake_input) args = {"seekPermission": True, "identityKey": True} - pub = wallet.get_public_key(None, args, TEST_PASSPHRASE) + pub = wallet.get_public_key(args, TEST_PASSPHRASE) # Verify operation succeeded assert "publicKey" in pub, "Should return public key when permission granted" @@ -126,7 +126,7 @@ def fake_input_deny(prompt): return "n" # User denies monkeypatch.setattr("builtins.input", fake_input_deny) - pub_denied = wallet.get_public_key(None, args, TEST_PASSPHRASE) + pub_denied = wallet.get_public_key(args, TEST_PASSPHRASE) assert "error" in pub_denied, "Should return error when permission denied via input" @@ -136,7 +136,7 @@ def test_seek_permission_denied_returns_error_dict(): wallet = WalletImpl(priv, permission_callback=lambda action: False) args = {"seekPermission": True, "identityKey": True} - res = wallet.get_public_key(None, args, TEST_PASSPHRASE) + res = wallet.get_public_key(args, TEST_PASSPHRASE) # Verify error response structure assert "error" in res, "Should return error dict when permission denied" @@ -154,7 +154,7 @@ def test_seek_permission_denied_returns_error_dict(): }, "plaintext": "test" } - res2 = wallet.encrypt(None, enc_args, TEST_PASSPHRASE) + res2 = wallet.encrypt(enc_args, TEST_PASSPHRASE) assert "error" in res2, "Encrypt should also be denied" @@ -164,7 +164,7 @@ def test_get_public_key_with_protocol_and_keyid(wallet): "protocolID": {"securityLevel": 1, "protocol": "test"}, # Fixed: removed " protocol" suffix "keyID": "test key 1" } - result = wallet.get_public_key(None, args, TEST_PASSPHRASE) + result = wallet.get_public_key(args, TEST_PASSPHRASE) # Should return a public key assert "publicKey" in result @@ -176,12 +176,12 @@ def test_get_public_key_missing_required_args(wallet): """Test get_public_key with missing required arguments.""" # Missing keyID args = {"protocolID": [1, "test"]} - result = wallet.get_public_key(None, args, TEST_PASSPHRASE) + result = wallet.get_public_key(args, TEST_PASSPHRASE) assert "error" in result # Missing protocolID args = {"keyID": "test_key"} - result = wallet.get_public_key(None, args, TEST_PASSPHRASE) + result = wallet.get_public_key(args, TEST_PASSPHRASE) assert "error" in result @@ -193,7 +193,7 @@ def test_get_public_key_with_counterparty(wallet, counterparty): "keyID": "key1", "counterparty": counterparty.hex() } - result = wallet.get_public_key(None, args, TEST_PASSPHRASE) + result = wallet.get_public_key(args, TEST_PASSPHRASE) assert "publicKey" in result # Test with dict counterparty @@ -202,7 +202,7 @@ def test_get_public_key_with_counterparty(wallet, counterparty): "keyID": "key1", "counterparty": {"type": "other", "counterparty": counterparty.hex()} } - result = wallet.get_public_key(None, args, TEST_PASSPHRASE) + result = wallet.get_public_key(args, TEST_PASSPHRASE) assert "publicKey" in result @@ -214,7 +214,7 @@ def test_create_signature_basic(wallet): "key_id": "key1", "data": data } - result = wallet.create_signature(None, args, TEST_PASSPHRASE) + result = wallet.create_signature(args, TEST_PASSPHRASE) assert "signature" in result assert "error" not in result @@ -226,12 +226,12 @@ def test_create_signature_missing_args(wallet): """Test create_signature with missing arguments.""" # Missing protocol_id args = {"key_id": "key1", "data": b"test"} - result = wallet.create_signature(None, args, TEST_PASSPHRASE) + result = wallet.create_signature(args, TEST_PASSPHRASE) assert "error" in result # Missing key_id args = {"protocol_id": {"securityLevel": 1, "protocol": "test"}, "data": b"test"} - result = wallet.create_signature(None, args, TEST_PASSPHRASE) + result = wallet.create_signature(args, TEST_PASSPHRASE) assert "error" in result @@ -247,7 +247,7 @@ def test_create_and_verify_signature(wallet): "key_id": key_id, "data": data } - sign_result = wallet.create_signature(None, sign_args, TEST_PASSPHRASE) + sign_result = wallet.create_signature(sign_args, TEST_PASSPHRASE) assert "signature" in sign_result # Verify signature @@ -257,7 +257,7 @@ def test_create_and_verify_signature(wallet): "data": data, "signature": sign_result["signature"] } - verify_result = wallet.verify_signature(None, verify_args, TEST_PASSPHRASE) + verify_result = wallet.verify_signature(verify_args, TEST_PASSPHRASE) assert "valid" in verify_result assert verify_result["valid"] is True @@ -273,7 +273,7 @@ def test_verify_signature_with_invalid_data(wallet): "key_id": "key1", "data": data } - sign_result = wallet.create_signature(None, sign_args, TEST_PASSPHRASE) + sign_result = wallet.create_signature(sign_args, TEST_PASSPHRASE) # Try to verify with different data verify_args = { @@ -282,7 +282,7 @@ def test_verify_signature_with_invalid_data(wallet): "data": tampered_data, "signature": sign_result["signature"] } - verify_result = wallet.verify_signature(None, verify_args, TEST_PASSPHRASE) + verify_result = wallet.verify_signature(verify_args, TEST_PASSPHRASE) assert verify_result["valid"] is False @@ -294,12 +294,12 @@ def test_verify_signature_missing_args(wallet): "key_id": "key1", "data": b"test" } - result = wallet.verify_signature(None, args, TEST_PASSPHRASE) + result = wallet.verify_signature(args, TEST_PASSPHRASE) assert "error" in result # Missing protocol_id args = {"key_id": "key1", "data": b"test", "signature": b"fake"} - result = wallet.verify_signature(None, args, TEST_PASSPHRASE) + result = wallet.verify_signature(args, TEST_PASSPHRASE) assert "error" in result @@ -313,7 +313,7 @@ def test_create_and_verify_hmac(wallet): # Create HMAC create_args = {"encryption_args": enc_args, "data": data} - hmac_result = wallet.create_hmac(None, create_args, TEST_PASSPHRASE) + hmac_result = wallet.create_hmac(create_args, TEST_PASSPHRASE) assert "hmac" in hmac_result assert "error" not in hmac_result @@ -323,7 +323,7 @@ def test_create_and_verify_hmac(wallet): "data": data, "hmac": hmac_result["hmac"] } - verify_result = wallet.verify_hmac(None, verify_args, TEST_PASSPHRASE) + verify_result = wallet.verify_hmac(verify_args, TEST_PASSPHRASE) assert "valid" in verify_result assert verify_result["valid"] is True @@ -339,7 +339,7 @@ def test_verify_hmac_with_tampered_data(wallet): # Create HMAC create_args = {"encryption_args": enc_args, "data": original_data} - hmac_result = wallet.create_hmac(None, create_args, TEST_PASSPHRASE) + hmac_result = wallet.create_hmac(create_args, TEST_PASSPHRASE) # Try to verify with different data verify_args = { @@ -347,7 +347,7 @@ def test_verify_hmac_with_tampered_data(wallet): "data": tampered_data, "hmac": hmac_result["hmac"] } - verify_result = wallet.verify_hmac(None, verify_args, TEST_PASSPHRASE) + verify_result = wallet.verify_hmac(verify_args, TEST_PASSPHRASE) assert verify_result["valid"] is False @@ -358,7 +358,7 @@ def test_create_hmac_missing_args(wallet): "encryption_args": {"protocol_id": {"securityLevel": 1, "protocol": "test"}}, "data": b"test" } - result = wallet.create_hmac(None, args, TEST_PASSPHRASE) + result = wallet.create_hmac(args, TEST_PASSPHRASE) assert "error" in result @@ -372,7 +372,7 @@ def test_verify_hmac_missing_args(wallet): }, "data": b"test" } - result = wallet.verify_hmac(None, args, TEST_PASSPHRASE) + result = wallet.verify_hmac(args, TEST_PASSPHRASE) assert "error" in result @@ -431,7 +431,7 @@ def test_acquire_certificate(wallet): "keyringForSubject": {"test": "data"}, "fields": {"field1": "value1"} } - result = wallet.acquire_certificate(None, args, TEST_PASSPHRASE) + result = wallet.acquire_certificate(args, TEST_PASSPHRASE) # Should return empty dict on success assert result == {} @@ -447,14 +447,14 @@ def test_acquire_certificate(wallet): def test_list_certificates(wallet): """Test listing certificates.""" # Add some certificates - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"type1", "serialNumber": b"123", "certifier": "cert1", "fields": {"name": "cert1"} }, TEST_PASSPHRASE) - wallet.acquire_certificate(None, { + wallet.acquire_certificate({ "type": b"type2", "serialNumber": b"456", "certifier": "cert2", @@ -462,14 +462,14 @@ def test_list_certificates(wallet): }, TEST_PASSPHRASE) # List all certificates - result = wallet.list_certificates(None, {}, TEST_PASSPHRASE) + result = wallet.list_certificates({}, TEST_PASSPHRASE) assert "certificates" in result assert len(result["certificates"]) == 2 def test_get_network(wallet): """Test get_network returns mocknet by default.""" - result = wallet.get_network(None, {}, TEST_PASSPHRASE) + result = wallet.get_network({}, TEST_PASSPHRASE) assert "network" in result # WalletImpl returns "mocknet" by default assert result["network"] in ["mocknet", "mainnet"] @@ -477,14 +477,14 @@ def test_get_network(wallet): def test_get_version(wallet): """Test get_version returns version string.""" - result = wallet.get_version(None, {}, TEST_PASSPHRASE) + result = wallet.get_version({}, TEST_PASSPHRASE) assert "version" in result assert isinstance(result["version"], str) def test_is_authenticated(wallet): """Test is_authenticated returns True.""" - result = wallet.is_authenticated(None, {}, TEST_PASSPHRASE) + result = wallet.is_authenticated({}, TEST_PASSPHRASE) assert "authenticated" in result assert result["authenticated"] is True @@ -506,7 +506,7 @@ def test_encrypt_decrypt_with_forself(wallet): }, "plaintext": plain } - encrypted = wallet.encrypt(None, enc_args, TEST_PASSPHRASE) + encrypted = wallet.encrypt(enc_args, TEST_PASSPHRASE) assert "ciphertext" in encrypted dec_args = { @@ -517,7 +517,7 @@ def test_encrypt_decrypt_with_forself(wallet): }, "ciphertext": encrypted["ciphertext"] } - decrypted = wallet.decrypt(None, dec_args, TEST_PASSPHRASE) + decrypted = wallet.decrypt(dec_args, TEST_PASSPHRASE) assert decrypted["plaintext"] == plain diff --git a/tests/bsv/wallet/test_wallet_impl_coverage.py b/tests/bsv/wallet/test_wallet_impl_coverage.py index 69bcd9f..2276a3c 100644 --- a/tests/bsv/wallet/test_wallet_impl_coverage.py +++ b/tests/bsv/wallet/test_wallet_impl_coverage.py @@ -90,7 +90,7 @@ def test_get_public_key_with_debug_enabled(wallet, capsys): """Test get_public_key with BSV_DEBUG=1.""" args = {"identityKey": True} with patch.dict(os.environ, {"BSV_DEBUG": "1"}): - _ = wallet.get_public_key(None, args, "test_originator") + _ = wallet.get_public_key(args, "test_originator") captured = capsys.readouterr() assert "DEBUG WalletImpl.get_public_key" in captured.out assert "originator=" in captured.out # Sensitive info is redacted @@ -103,7 +103,7 @@ def test_encrypt_with_debug_enabled(wallet, capsys): "plaintext": b"test" } with patch.dict(os.environ, {"BSV_DEBUG": "1"}): - _ = wallet.encrypt(None, args, "test") + _ = wallet.encrypt(args, "test") captured = capsys.readouterr() assert "DEBUG WalletImpl.encrypt" in captured.out @@ -111,14 +111,14 @@ def test_encrypt_with_debug_enabled(wallet, capsys): def test_decrypt_with_debug_enabled(wallet, capsys): """Test decrypt with BSV_DEBUG=1.""" # First encrypt - enc_result = wallet.encrypt(None, {"encryption_args": {}, "plaintext": b"test"}, "test") + enc_result = wallet.encrypt({"encryption_args": {}, "plaintext": b"test"}, "test") args = { "encryption_args": {}, "ciphertext": enc_result["ciphertext"] } with patch.dict(os.environ, {"BSV_DEBUG": "1"}): - _ = wallet.decrypt(None, args, "test") + _ = wallet.decrypt(args, "test") captured = capsys.readouterr() assert "DEBUG WalletImpl.decrypt" in captured.out @@ -130,7 +130,7 @@ def test_decrypt_with_debug_enabled(wallet, capsys): def test_get_public_key_with_none_protocol_id(wallet): """Test get_public_key returns error when protocol_id is None.""" args = {"protocolID": None, "keyID": None} - result = wallet.get_public_key(None, args, "test") + result = wallet.get_public_key(args, "test") assert "error" in result assert "required" in result["error"].lower() @@ -138,7 +138,7 @@ def test_get_public_key_with_none_protocol_id(wallet): def test_get_public_key_with_forself_true_no_protocol(wallet): """Test get_public_key returns identity key when forSelf=True even without protocol.""" args = {"forSelf": True} - result = wallet.get_public_key(None, args, "test") + result = wallet.get_public_key(args, "test") assert "publicKey" in result assert "error" not in result @@ -150,7 +150,7 @@ def test_get_public_key_with_non_dict_protocol_id(wallet): "protocolID": protocol, # Not a dict "keyID": "key1" } - result = wallet.get_public_key(None, args, "test") + result = wallet.get_public_key(args, "test") # Should work with Protocol object directly assert "publicKey" in result or "error" in result @@ -158,7 +158,7 @@ def test_get_public_key_with_non_dict_protocol_id(wallet): def test_encrypt_missing_plaintext(wallet): """Test encrypt returns error when plaintext is missing.""" args = {"encryption_args": {}} - result = wallet.encrypt(None, args, "test") + result = wallet.encrypt(args, "test") assert "error" in result assert "plaintext" in result["error"].lower() @@ -166,7 +166,7 @@ def test_encrypt_missing_plaintext(wallet): def test_encrypt_with_none_plaintext(wallet): """Test encrypt returns error when plaintext is None.""" args = {"encryption_args": {}, "plaintext": None} - result = wallet.encrypt(None, args, "test") + result = wallet.encrypt(args, "test") assert "error" in result assert "plaintext" in result["error"].lower() @@ -174,7 +174,7 @@ def test_encrypt_with_none_plaintext(wallet): def test_decrypt_missing_ciphertext(wallet): """Test decrypt returns error when ciphertext is missing.""" args = {"encryption_args": {}} - result = wallet.decrypt(None, args, "test") + result = wallet.decrypt(args, "test") assert "error" in result assert "ciphertext" in result["error"].lower() @@ -182,7 +182,7 @@ def test_decrypt_missing_ciphertext(wallet): def test_decrypt_with_none_ciphertext(wallet): """Test decrypt returns error when ciphertext is None.""" args = {"encryption_args": {}, "ciphertext": None} - result = wallet.decrypt(None, args, "test") + result = wallet.decrypt(args, "test") assert "error" in result assert "ciphertext" in result["error"].lower() @@ -190,14 +190,14 @@ def test_decrypt_with_none_ciphertext(wallet): def test_create_signature_missing_protocol_id(wallet): """Test create_signature returns error when protocol_id is missing.""" args = {"key_id": "key1", "data": b"test"} - result = wallet.create_signature(None, args, "test") + result = wallet.create_signature(args, "test") assert "error" in result def test_create_signature_missing_key_id(wallet): """Test create_signature returns error when key_id is missing.""" args = {"protocol_id": {"securityLevel": 1, "protocol": "test"}, "data": b"test"} - result = wallet.create_signature(None, args, "test") + result = wallet.create_signature(args, "test") assert "error" in result @@ -209,7 +209,7 @@ def test_create_signature_with_none_data(wallet): "data": None } # Should handle None gracefully or return error - result = wallet.create_signature(None, args, "test") + result = wallet.create_signature(args, "test") # Either succeeds with empty data or returns error assert "signature" in result or "error" in result @@ -221,7 +221,7 @@ def test_verify_signature_missing_signature(wallet): "key_id": "key1", "data": b"test" } - result = wallet.verify_signature(None, args, "test") + result = wallet.verify_signature(args, "test") assert "error" in result assert "signature" in result["error"].lower() @@ -234,7 +234,7 @@ def test_verify_signature_with_none_signature(wallet): "data": b"test", "signature": None } - result = wallet.verify_signature(None, args, "test") + result = wallet.verify_signature(args, "test") assert "error" in result assert "signature" in result["error"].lower() @@ -242,7 +242,7 @@ def test_verify_signature_with_none_signature(wallet): def test_verify_signature_missing_protocol_id(wallet): """Test verify_signature returns error when protocol_id is missing.""" args = {"key_id": "key1", "data": b"test", "signature": b"fake"} - result = wallet.verify_signature(None, args, "test") + result = wallet.verify_signature(args, "test") assert "error" in result @@ -253,7 +253,7 @@ def test_verify_signature_missing_key_id(wallet): "data": b"test", "signature": b"fake" } - result = wallet.verify_signature(None, args, "test") + result = wallet.verify_signature(args, "test") assert "error" in result @@ -265,7 +265,7 @@ def test_verify_signature_with_list_protocol_id(wallet): "key_id": "key1", "data": b"test data" } - sign_result = wallet.create_signature(None, sign_args, "test") + sign_result = wallet.create_signature(sign_args, "test") # Verify with list protocol_id verify_args = { @@ -274,7 +274,7 @@ def test_verify_signature_with_list_protocol_id(wallet): "data": b"test data", "signature": sign_result["signature"] } - result = wallet.verify_signature(None, verify_args, "test") + result = wallet.verify_signature(verify_args, "test") assert "valid" in result @@ -290,7 +290,7 @@ def test_verify_signature_with_hash_to_directly_verify(wallet): "key_id": "key1", "data": data } - sign_result = wallet.create_signature(None, sign_args, "test") + sign_result = wallet.create_signature(sign_args, "test") # Verify using hash directly verify_args = { @@ -299,7 +299,7 @@ def test_verify_signature_with_hash_to_directly_verify(wallet): "hash_to_directly_verify": data_hash, "signature": sign_result["signature"] } - result = wallet.verify_signature(None, verify_args, "test") + result = wallet.verify_signature(verify_args, "test") assert "valid" in result assert result["valid"] is True @@ -310,7 +310,7 @@ def test_create_hmac_missing_protocol_id(wallet): "encryption_args": {"key_id": "key1"}, "data": b"test" } - result = wallet.create_hmac(None, args, "test") + result = wallet.create_hmac(args, "test") assert "error" in result @@ -320,7 +320,7 @@ def test_create_hmac_missing_key_id(wallet): "encryption_args": {"protocol_id": {"securityLevel": 1, "protocol": "test"}}, "data": b"test" } - result = wallet.create_hmac(None, args, "test") + result = wallet.create_hmac(args, "test") assert "error" in result @@ -333,7 +333,7 @@ def test_create_hmac_with_none_data(wallet): }, "data": None } - result = wallet.create_hmac(None, args, "test") + result = wallet.create_hmac(args, "test") # Should handle None gracefully (defaults to empty bytes) assert "hmac" in result or "error" in result @@ -345,7 +345,7 @@ def test_verify_hmac_missing_protocol_id(wallet): "data": b"test", "hmac": b"fake" } - result = wallet.verify_hmac(None, args, "test") + result = wallet.verify_hmac(args, "test") assert "error" in result @@ -356,7 +356,7 @@ def test_verify_hmac_missing_key_id(wallet): "data": b"test", "hmac": b"fake" } - result = wallet.verify_hmac(None, args, "test") + result = wallet.verify_hmac(args, "test") assert "error" in result @@ -369,7 +369,7 @@ def test_verify_hmac_missing_hmac_value(wallet): }, "data": b"test" } - result = wallet.verify_hmac(None, args, "test") + result = wallet.verify_hmac(args, "test") assert "error" in result assert "hmac" in result["error"].lower() @@ -384,7 +384,7 @@ def test_verify_hmac_with_none_hmac_value(wallet): "data": b"test", "hmac": None } - result = wallet.verify_hmac(None, args, "test") + result = wallet.verify_hmac(args, "test") assert "error" in result assert "hmac" in result["error"].lower() @@ -579,7 +579,7 @@ def fake_input(prompt): def test_acquire_certificate_minimal_args(wallet): """Test acquiring certificate with minimal arguments.""" args = {} - result = wallet.acquire_certificate(None, args, "test") + result = wallet.acquire_certificate(args, "test") assert result == {} assert len(wallet._certificates) == 1 @@ -594,7 +594,7 @@ def test_acquire_certificate_with_none_values(wallet): "keyringForSubject": None, "fields": None } - result = wallet.acquire_certificate(None, args, "test") + result = wallet.acquire_certificate(args, "test") assert result == {} # Certificate is stored even with empty/None values assert len(wallet._certificates) >= 1 @@ -602,7 +602,7 @@ def test_acquire_certificate_with_none_values(wallet): def test_list_certificates_empty(wallet): """Test listing certificates when none exist.""" - result = wallet.list_certificates(None, {}, "test") + result = wallet.list_certificates({}, "test") assert "certificates" in result assert len(result["certificates"]) == 0 @@ -613,21 +613,21 @@ def test_list_certificates_empty(wallet): def test_get_network_returns_string(wallet): """Test get_network returns a string.""" - result = wallet.get_network(None, {}, "test") + result = wallet.get_network({}, "test") assert "network" in result assert isinstance(result["network"], str) def test_get_version_returns_string(wallet): """Test get_version returns a string.""" - result = wallet.get_version(None, {}, "test") + result = wallet.get_version({}, "test") assert "version" in result assert isinstance(result["version"], str) def test_is_authenticated_always_true(wallet): """Test is_authenticated always returns True.""" - result = wallet.is_authenticated(None, {}, "test") + result = wallet.is_authenticated({}, "test") assert "authenticated" in result assert result["authenticated"] is True @@ -646,19 +646,19 @@ def test_abort_action_is_noop(wallet): def test_get_public_key_with_empty_args(wallet): """Test get_public_key with empty args dict.""" - result = wallet.get_public_key(None, {}, "test") + result = wallet.get_public_key({}, "test") assert "error" in result or "publicKey" in result def test_encrypt_with_empty_args(wallet): """Test encrypt with empty args dict.""" - result = wallet.encrypt(None, {}, "test") + result = wallet.encrypt({}, "test") assert "error" in result def test_decrypt_with_empty_args(wallet): """Test decrypt with empty args dict.""" - result = wallet.decrypt(None, {}, "test") + result = wallet.decrypt({}, "test") assert "error" in result @@ -669,7 +669,7 @@ def test_create_signature_with_empty_data(wallet): "key_id": "key1", "data": b"" } - result = wallet.create_signature(None, args, "test") + result = wallet.create_signature(args, "test") assert "signature" in result or "error" in result @@ -682,7 +682,7 @@ def test_create_hmac_with_empty_data(wallet): }, "data": b"" } - result = wallet.create_hmac(None, args, "test") + result = wallet.create_hmac(args, "test") assert "hmac" in result @@ -696,7 +696,7 @@ def test_verify_hmac_with_empty_data(wallet): }, "data": b"" } - hmac_result = wallet.create_hmac(None, create_args, "test") + hmac_result = wallet.create_hmac(create_args, "test") # Verify with empty data verify_args = { @@ -707,7 +707,7 @@ def test_verify_hmac_with_empty_data(wallet): "data": b"", "hmac": hmac_result["hmac"] } - result = wallet.verify_hmac(None, verify_args, "test") + result = wallet.verify_hmac(verify_args, "test") assert "valid" in result assert result["valid"] is True @@ -718,7 +718,7 @@ def test_get_public_key_with_empty_protocol_string(wallet): "protocolID": {"securityLevel": 0, "protocol": ""}, "keyID": "key1" } - result = wallet.get_public_key(None, args, "test") + result = wallet.get_public_key(args, "test") # Should work even with empty protocol assert "publicKey" in result or "error" in result @@ -729,6 +729,6 @@ def test_get_public_key_with_zero_security_level(wallet): "protocolID": {"securityLevel": 0, "protocol": "test"}, "keyID": "key1" } - result = wallet.get_public_key(None, args, "test") + result = wallet.get_public_key(args, "test") assert "publicKey" in result or "error" in result diff --git a/tests/bsv/wallet/test_wallet_impl_sign_verify_hmac.py b/tests/bsv/wallet/test_wallet_impl_sign_verify_hmac.py index 7f3638e..78ffe08 100644 --- a/tests/bsv/wallet/test_wallet_impl_sign_verify_hmac.py +++ b/tests/bsv/wallet/test_wallet_impl_sign_verify_hmac.py @@ -18,10 +18,10 @@ def test_create_and_verify_signature_identity(wallet): "counterparty": {"type": "self"}, "data": data, } - sig = wallet.create_signature(None, args, "test") + sig = wallet.create_signature(args, "test") assert "signature" in sig and isinstance(sig["signature"], (bytes, bytearray)) - ver = wallet.verify_signature(None, {**args, "signature": sig["signature"]}, "test") + ver = wallet.verify_signature({**args, "signature": sig["signature"]}, "test") assert ver.get("valid") is True @@ -38,10 +38,10 @@ def test_create_and_verify_hmac_other_counterparty(wallet): }, "data": data, } - h = wallet.create_hmac(None, args, "test") + h = wallet.create_hmac(args, "test") assert "hmac" in h and isinstance(h["hmac"], (bytes, bytearray)) - ver = wallet.verify_hmac(None, {**args, "hmac": h["hmac"]}, "test") + ver = wallet.verify_hmac({**args, "hmac": h["hmac"]}, "test") assert ver.get("valid") is True diff --git a/tests/bsv/wallet/test_wallet_outputs.py b/tests/bsv/wallet/test_wallet_outputs.py index 6753cf1..f84a4c5 100644 --- a/tests/bsv/wallet/test_wallet_outputs.py +++ b/tests/bsv/wallet/test_wallet_outputs.py @@ -14,7 +14,7 @@ def wallet(): def test_list_outputs_empty(wallet): """Test listing outputs when none exist.""" - result = wallet.list_outputs(None, {}, "test") + result = wallet.list_outputs({}, "test") # API returns 'outputs' array, not 'totalOutputs' assert "outputs" in result @@ -26,7 +26,7 @@ def test_list_outputs_empty(wallet): def test_list_outputs_with_basket(wallet): """Test listing outputs filtered by basket.""" args = {"basket": "savings"} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) assert "outputs" in result # Fixed: API returns 'outputs', not 'totalOutputs' @@ -35,7 +35,7 @@ def test_list_outputs_with_basket(wallet): def test_list_outputs_with_tags(wallet): """Test listing outputs filtered by tags.""" args = {"tags": ["important", "urgent"]} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) @@ -43,7 +43,7 @@ def test_list_outputs_with_tags(wallet): def test_list_outputs_with_type_filter(wallet): """Test listing outputs filtered by type.""" args = {"type": "P2PKH"} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) @@ -51,7 +51,7 @@ def test_list_outputs_with_type_filter(wallet): def test_list_outputs_with_limit(wallet): """Test listing outputs with limit.""" args = {"limit": 10} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) @@ -59,7 +59,7 @@ def test_list_outputs_with_limit(wallet): def test_list_outputs_with_offset(wallet): """Test listing outputs with offset pagination.""" args = {"offset": 5, "limit": 10} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) @@ -67,7 +67,7 @@ def test_list_outputs_with_offset(wallet): def test_list_outputs_include_beef(wallet): """Test listing outputs with BEEF inclusion.""" args = {"includeBEEF": True} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) # Should include BEEF if outputs exist @@ -76,7 +76,7 @@ def test_list_outputs_include_beef(wallet): def test_list_outputs_include_locked(wallet): """Test listing outputs including locked ones.""" args = {"includeLocked": True} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) @@ -84,7 +84,7 @@ def test_list_outputs_include_locked(wallet): def test_list_outputs_include_spent(wallet): """Test listing outputs including spent ones.""" args = {"includeSpent": True} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) @@ -92,7 +92,7 @@ def test_list_outputs_include_spent(wallet): def test_list_outputs_include_spendable_only(wallet): """Test listing only spendable outputs.""" args = {"spendable": True} - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) @@ -106,7 +106,7 @@ def test_relinquish_output(wallet): "vout": 0 } } - result = wallet.relinquish_output(None, args, "test") + result = wallet.relinquish_output(args, "test") # Should return empty dict on success assert result == {} @@ -115,13 +115,13 @@ def test_relinquish_output(wallet): def test_relinquish_output_multiple(wallet): """Test relinquishing multiple outputs.""" # Relinquish first output - wallet.relinquish_output(None, { + wallet.relinquish_output({ "basket": "basket1", "output": {"txid": "a" * 64, "vout": 0} }, "test") # Relinquish second output - wallet.relinquish_output(None, { + wallet.relinquish_output({ "basket": "basket1", "output": {"txid": "b" * 64, "vout": 1} }, "test") @@ -215,7 +215,7 @@ def test_list_outputs_combined_filters(wallet): "includeEnvelope": True } - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) assert "outputs" in result # Fixed: API returns 'outputs', not 'totalOutputs' @@ -227,7 +227,7 @@ def test_list_outputs_with_custom_fields(wallet): "customInstructions": {"field1": "value1"} } - result = wallet.list_outputs(None, args, "test") + result = wallet.list_outputs(args, "test") assert isinstance(result, dict) From 44e75fa4b5df512f26bf852d3322bfd4465e948e Mon Sep 17 00:00:00 2001 From: Freddie Honohan Date: Mon, 8 Dec 2025 15:25:03 +0900 Subject: [PATCH 2/2] Refactoring for sonarQube --- tests/bsv/auth/conftest.py | 135 ++++++++++++++++++ tests/bsv/auth/test_auth_peer_basic.py | 41 +----- ...st_auth_peer_cert_request_response_flow.py | 83 +---------- tests/bsv/auth/test_auth_peer_certificates.py | 68 +-------- tests/bsv/auth/test_auth_peer_handshake.py | 46 +----- 5 files changed, 139 insertions(+), 234 deletions(-) create mode 100644 tests/bsv/auth/conftest.py diff --git a/tests/bsv/auth/conftest.py b/tests/bsv/auth/conftest.py new file mode 100644 index 0000000..d507030 --- /dev/null +++ b/tests/bsv/auth/conftest.py @@ -0,0 +1,135 @@ +import base64 + +from bsv.auth.peer_session import PeerSession +from bsv.auth.session_manager import DefaultSessionManager +from bsv.keys import PrivateKey + + +class CaptureTransport: + def __init__(self): + self._on_data_callback = None + self.sent_messages = [] + + def on_data(self, callback): + self._on_data_callback = callback + return None + + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + else: + # Called as send(ctx, message) - first arg is ctx, second is message + msg = message + self.sent_messages.append(msg) + return None + + +class MockSigResult: + def __init__(self, valid: bool): + self.valid = valid + + +class MockCreateSig: + def __init__(self, signature: bytes): + self.signature = signature + + +class WalletOK: + def __init__(self, priv: PrivateKey): + self._priv = priv + self._pub = priv.public_key() + + def get_public_key(self, args=None, originator=None): + class R: + pass + r = R() + r.public_key = self._pub + return r + + def verify_signature(self, args=None, originator=None): + return MockSigResult(True) + + def create_signature(self, args=None, originator=None): + return MockCreateSig(b"sig") + + # Optional stub for certificate acquisition + def acquire_certificate(self, args=None, originator=None): + # Return a simple dict-like certificate payload compatible with canonicalizer + return { + "certificate": { + "type": args.get("cert_type") if args else None, + "serialNumber": base64.b64encode(b"S" * 32).decode(), + "subject": args.get("subject") if args else None, + "certifier": args.get("certifiers", [self._pub.hex()])[0] if args and args.get("certifiers") else self._pub.hex(), + "fields": dict.fromkeys(args.get("fields", []), "v") if args else {}, + }, + "keyring": {}, + "signature": b"sig", + } + + +def _seed_authenticated_session(session_manager: DefaultSessionManager, peer_identity_key): + session_nonce = base64.b64encode(b"S" * 32).decode() + peer_nonce = base64.b64encode(b"P" * 32).decode() + s = PeerSession( + is_authenticated=True, + session_nonce=session_nonce, + peer_nonce=peer_nonce, + peer_identity_key=peer_identity_key, + last_update=1, + ) + session_manager.add_session(s) + return s + + +class LocalTransport: + def __init__(self): + self._on_data_callback = None + self.sent_messages = [] + self.peer = None + + def connect(self, other: "LocalTransport"): + self.peer = other + other.peer = self + + def on_data(self, callback): + self._on_data_callback = callback + return None + + def send(self, message_or_ctx, message=None): + # Handle both calling patterns: + # - send(message) - peer.py calls it this way + # - send(ctx, message) - interface defines it this way + if message is None: + # Called as send(message) - first arg is the message + msg = message_or_ctx + else: + # Called as send(ctx, message) - first arg is ctx, second is message + msg = message + self.sent_messages.append(msg) + # Note: peer.py callback expects just (message), not (ctx, message) + if self.peer and self.peer._on_data_callback: + return self.peer._on_data_callback(msg) + elif self._on_data_callback is not None: + return self._on_data_callback(msg) + return None + + +class GetPub: + def __init__(self, pk): + self.public_key = pk + + +class Sig: + def __init__(self, signature: bytes): + self.signature = signature + + +class Ver: + def __init__(self, valid: bool): + self.valid = valid + diff --git a/tests/bsv/auth/test_auth_peer_basic.py b/tests/bsv/auth/test_auth_peer_basic.py index 81e6b94..be840ac 100644 --- a/tests/bsv/auth/test_auth_peer_basic.py +++ b/tests/bsv/auth/test_auth_peer_basic.py @@ -8,46 +8,7 @@ from bsv.auth.session_manager import DefaultSessionManager from bsv.keys import PrivateKey - -class LocalTransport: - def __init__(self): - self._on_data_callback = None - self.sent_messages: list[AuthMessage] = [] - - def on_data(self, callback): - self._on_data_callback = callback - return None - - def send(self, message_or_ctx, message=None): - # Handle both calling patterns: - # - send(message) - peer.py calls it this way - # - send(ctx, message) - interface defines it this way - if message is None: - # Called as send(message) - first arg is the message - msg = message_or_ctx - else: - # Called as send(ctx, message) - first arg is ctx, second is message - msg = message - self.sent_messages.append(msg) - # Note: peer.py callback expects just (message), not (ctx, message) - if self._on_data_callback is not None: - return self._on_data_callback(msg) - return None - - -class GetPub: - def __init__(self, pk): - self.public_key = pk - - -class Sig: - def __init__(self, signature: bytes): - self.signature = signature - - -class Ver: - def __init__(self, valid: bool): - self.valid = valid +from .conftest import LocalTransport, GetPub, Sig, Ver class MockWallet: diff --git a/tests/bsv/auth/test_auth_peer_cert_request_response_flow.py b/tests/bsv/auth/test_auth_peer_cert_request_response_flow.py index 919c451..5dfed9e 100644 --- a/tests/bsv/auth/test_auth_peer_cert_request_response_flow.py +++ b/tests/bsv/auth/test_auth_peer_cert_request_response_flow.py @@ -2,91 +2,10 @@ from bsv.auth.peer import Peer, PeerOptions from bsv.auth.auth_message import AuthMessage -from bsv.auth.peer_session import PeerSession from bsv.auth.session_manager import DefaultSessionManager from bsv.keys import PrivateKey - -class CaptureTransport: - def __init__(self): - self._on_data_callback = None - self.sent_messages = [] - - def on_data(self, callback): - self._on_data_callback = callback - return None - - def send(self, message_or_ctx, message=None): - # Handle both calling patterns: - # - send(message) - peer.py calls it this way - # - send(ctx, message) - interface defines it this way - if message is None: - # Called as send(message) - first arg is the message - msg = message_or_ctx - else: - # Called as send(ctx, message) - first arg is ctx, second is message - msg = message - self.sent_messages.append(msg) - return None - - -class MockSigResult: - def __init__(self, valid: bool): - self.valid = valid - - -class MockCreateSig: - def __init__(self, signature: bytes): - self.signature = signature - - -class WalletOK: - def __init__(self, priv: PrivateKey): - self._priv = priv - self._pub = priv.public_key() - - def get_public_key(self, args=None, originator=None): - class R: - pass - - r = R() - r.public_key = self._pub - return r - - def verify_signature(self, args=None, originator=None): - return MockSigResult(True) - - def create_signature(self, args=None, originator=None): - return MockCreateSig(b"sig") - - # Optional stub for certificate acquisition - def acquire_certificate(self, args=None, originator=None): - # Return a simple dict-like certificate payload compatible with canonicalizer - return { - "certificate": { - "type": args.get("cert_type"), - "serialNumber": base64.b64encode(b"S" * 32).decode(), - "subject": args.get("subject"), - "certifier": args.get("certifiers", [self._pub.hex()])[0] if args.get("certifiers") else self._pub.hex(), - "fields": dict.fromkeys(args.get("fields", []), "v"), - }, - "keyring": {}, - "signature": b"sig", - } - - -def _seed_authenticated_session(session_manager: DefaultSessionManager, peer_identity_key): - session_nonce = base64.b64encode(b"S" * 32).decode() - peer_nonce = base64.b64encode(b"P" * 32).decode() - s = PeerSession( - is_authenticated=True, - session_nonce=session_nonce, - peer_nonce=peer_nonce, - peer_identity_key=peer_identity_key, - last_update=1, - ) - session_manager.add_session(s) - return s +from .conftest import CaptureTransport, WalletOK, _seed_authenticated_session def test_handle_certificate_request_triggers_response_via_wallet_fallback(): diff --git a/tests/bsv/auth/test_auth_peer_certificates.py b/tests/bsv/auth/test_auth_peer_certificates.py index 12a99bb..d5cae80 100644 --- a/tests/bsv/auth/test_auth_peer_certificates.py +++ b/tests/bsv/auth/test_auth_peer_certificates.py @@ -1,77 +1,11 @@ import base64 -import threading from bsv.auth.peer import Peer, PeerOptions from bsv.auth.auth_message import AuthMessage -from bsv.auth.peer_session import PeerSession from bsv.auth.session_manager import DefaultSessionManager from bsv.keys import PrivateKey - -class CaptureTransport: - def __init__(self): - self._on_data_callback = None - self.sent_messages = [] - - def on_data(self, callback): - self._on_data_callback = callback - return None - - def send(self, message_or_ctx, message=None): - # Handle both calling patterns: - # - send(message) - peer.py calls it this way - # - send(ctx, message) - interface defines it this way - if message is None: - # Called as send(message) - first arg is the message - msg = message_or_ctx - else: - # Called as send(ctx, message) - first arg is ctx, second is message - msg = message - self.sent_messages.append(msg) - return None - - -class MockSigResult: - def __init__(self, valid: bool): - self.valid = valid - - -class MockCreateSig: - def __init__(self, signature: bytes): - self.signature = signature - - -class WalletOK: - def __init__(self, priv: PrivateKey): - self._priv = priv - self._pub = priv.public_key() - - def get_public_key(self, args=None, originator=None): - class R: - pass - r = R() - r.public_key = self._pub - return r - - def verify_signature(self, args=None, originator=None): - return MockSigResult(True) - - def create_signature(self, args=None, originator=None): - return MockCreateSig(b"sig") - - -def _seed_authenticated_session(session_manager: DefaultSessionManager, peer_identity_key): - session_nonce = base64.b64encode(b"S" * 32).decode() - peer_nonce = base64.b64encode(b"P" * 32).decode() - s = PeerSession( - is_authenticated=True, - session_nonce=session_nonce, - peer_nonce=peer_nonce, - peer_identity_key=peer_identity_key, - last_update=1, - ) - session_manager.add_session(s) - return s +from .conftest import CaptureTransport, WalletOK, _seed_authenticated_session def test_handle_certificate_request_valid_signature(): diff --git a/tests/bsv/auth/test_auth_peer_handshake.py b/tests/bsv/auth/test_auth_peer_handshake.py index 2582a39..8ace3bd 100644 --- a/tests/bsv/auth/test_auth_peer_handshake.py +++ b/tests/bsv/auth/test_auth_peer_handshake.py @@ -7,51 +7,7 @@ from bsv.auth.session_manager import DefaultSessionManager from bsv.keys import PrivateKey, PublicKey - -class LocalTransport: - def __init__(self): - self._on_data_callback = None - self.peer: Optional["LocalTransport"] = None - - def connect(self, other: "LocalTransport"): - self.peer = other - other.peer = self - - def on_data(self, callback): - self._on_data_callback = callback - return None - - def send(self, message_or_ctx, message=None): - # Handle both calling patterns: - # - send(message) - peer.py calls it this way - # - send(ctx, message) - interface defines it this way - if message is None: - # Called as send(message) - first arg is the message - msg = message_or_ctx - ctx_arg = None - else: - # Called as send(ctx, message) - first arg is ctx, second is message - ctx_arg = message_or_ctx - msg = message - if not self.peer or not self.peer._on_data_callback: - return Exception("peer not connected or not listening") - # Note: peer.py callback expects just (message), not (ctx, message) - return self.peer._on_data_callback(msg) - - -class GetPub: - def __init__(self, pk: PublicKey): - self.public_key = pk - - -class Sig: - def __init__(self, signature: bytes): - self.signature = signature - - -class Ver: - def __init__(self, valid: bool): - self.valid = valid +from .conftest import LocalTransport, GetPub, Sig, Ver class HandshakeWallet: