Refuse an Electrum server that is not on the PLM chain (B-99, ELC-30)

PLM shares Bitcoin's genesis and powLimit, so a Bitcoin server passed every
header check. connect() now asks server.features and requires PLM's genesis.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-18 00:32:24 +02:00
1 parent 1433813ec7
commit 2c0e71a74c
4 files changed
+72 -2

No files matched your search

+16
View File
@@ -7,6 +7,8 @@ import re
import ssl
from typing import NamedTuple
from app.wallet.plm_network import GENESIS_HASH
logger = logging.getLogger(__name__)
@@ -192,6 +194,20 @@ class ElectrumClient:
raise
self._read_task = asyncio.create_task(self._read_loop())
await self.request("server.version", ["plm-lottery", "1.4"])
try:
await self._check_genesis()
except ElectrumError:
self._read_task.cancel()
self._writer.close()
raise
async def _check_genesis(self) -> None:
"""The server must be on PLM's chain, not just any chain with valid headers: PLM shares
Bitcoin's genesis and powLimit, so only `server.features` tells them apart (B-99, ELC-30)."""
features = await self.request("server.features")
genesis = features.get("genesis_hash") if isinstance(features, dict) else None
if genesis != GENESIS_HASH:
raise ElectrumError(f"{self.host}:{self.port} is not on the PLM chain (genesis {genesis!r})")
def _check_pin(self) -> None:
"""The server's DER certificate must hash to the pinned SHA-256 (B-84, ELC-03)."""