embit's Script.from_address accepts a well-formed bech32 address from any chain: a Bitcoin bc1... parses into a perfectly valid witness program. So a withdrawal to a BTC address built, signed and broadcast normally on PLM, and the funds landed on a script nobody holds the key for — silently, with no error anywhere. A malformed address fared slightly better only in that it crashed the request with an unhandled 500. is_valid_plm_address checks the HRP as well as the parse, and runs first in request_withdrawal, before a single UTXO is touched. It matches what the withdrawal form already told the user (bech32 plm1q... only). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
28 lines
976 B
Python
28 lines
976 B
Python
"""Validation for PLM addresses supplied by the user (withdrawal destinations).
|
|
|
|
embit's `Script.from_address` accepts a well-formed bech32 address from *any*
|
|
chain — a Bitcoin `bc1...` parses fine and yields a perfectly valid witness
|
|
program — so parse-success alone is not a sufficient check here: a withdrawal
|
|
to a `bc1...` address would build, sign and broadcast normally on PLM and land
|
|
on a script nobody holds the key for. The HRP check below is what makes the
|
|
destination actually PLM, and it matches what the withdrawal form already
|
|
tells the user (bech32 `plm1q...` only).
|
|
"""
|
|
|
|
from embit import script
|
|
from embit.base import EmbitError
|
|
|
|
from app.wallet.plm_network import PLM_MAINNET
|
|
|
|
_BECH32_PREFIX = PLM_MAINNET["bech32"] + "1"
|
|
|
|
|
|
def is_valid_plm_address(address: str) -> bool:
|
|
if not address.startswith(_BECH32_PREFIX):
|
|
return False
|
|
try:
|
|
script.Script.from_address(address)
|
|
except EmbitError:
|
|
return False
|
|
return True
|