[Bug] WebSocket Streams: stream registry is global, two clients with the same stream name get each other's data
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 88/100
Línea de trabajo
Comienza en common/src/binance_common/websocket.py con WebSocketStreamBase: busca los mapas a nivel de módulo global_stream_connections y global_user_stream_connections y luego cada lugar donde se leen o escriben — el filtro de subscribe, on, la cancelación de suscripción y la limpieza al reconectar — y muévelos a atributos por instancia inicializados en __init__. Ejecuta primero el script de reproducción de aiohttp autocontenido del cuerpo del issue para confirmar la salida incorrecta, y luego ejecútalo de nuevo para comprobar que cada servidor recibe su propio SUBSCRIBE y que fut_cb recibe {'venue': 'futures'}. Comprueba que las pruebas de websocket existentes del repo sigan pasando, ya que la lógica de pooling y deduplicación depende de este registro.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
WebSocketStreamBase keeps its stream-to-connection registry in two module-level objects (global_stream_connections, global_user_stream_connections in common/src/binance_common/websocket.py). Every client in the process shares them, keyed only by stream name.
Spot and USDⓈ-M Futures use the same stream names (btcusdt@aggTrade, btcusdt@depth, ...), and so do mainnet and testnet. When two stream clients in one process subscribe to the same name:
- the second client never sends
SUBSCRIBE, because the name is already registered; - its callback is attached to the first client's connection, so it receives the other venue's data, with no error.
Reproduce
Self-contained: one local aiohttp server with two endpoints standing in for two venues; each tags its messages with its name. binance-common==4.5.1 (same as master at 43f19a9), Python 3.13.
import asyncio, json, logging
from aiohttp import web
from binance_common.configuration import ConfigurationWebSocketStreams
from binance_common.websocket import WebSocketStreamBase, RequestStream
logging.disable(logging.CRITICAL)
subs = {"spot": [], "futures": []}
def mk(name):
async def handler(request):
ws = web.WebSocketResponse(); await ws.prepare(request)
async for msg in ws:
d = json.loads(msg.data)
if d["method"] == "SUBSCRIBE":
subs[name] += d["params"]
await ws.send_json({"id": d["id"], "result": None})
for s in d["params"]:
await ws.send_json({"stream": s, "data": {"venue": name}})
return ws
return handler
async def main():
app = web.Application()
app.router.add_get("/spot/stream", mk("spot")); app.router.add_get("/fut/stream", mk("futures"))
r = web.AppRunner(app); await r.setup(); await web.TCPSite(r, "127.0.0.1", 18766).start()
spot = WebSocketStreamBase(ConfigurationWebSocketStreams(stream_url="ws://127.0.0.1:18766/spot/stream"))
fut = WebSocketStreamBase(ConfigurationWebSocketStreams(stream_url="ws://127.0.0.1:18766/fut/stream"))
await spot.create_connection(); await fut.create_connection()
got = {"spot_cb": [], "fut_cb": []}
h1 = await RequestStream(spot, "btcusdt@aggTrade"); h1.on("message", lambda d: got["spot_cb"].append(d))
h2 = await RequestStream(fut, "btcusdt@aggTrade"); h2.on("message", lambda d: got["fut_cb"].append(d))
await asyncio.sleep(0.5)
print("SUBSCRIBE frames received by servers:", subs)
print("callback payloads:", got)
await spot.close_connection(); await fut.close_connection(); await r.cleanup()
asyncio.run(main())
Output:
SUBSCRIBE frames received by servers: {'spot': ['btcusdt@aggTrade'], 'futures': []}
callback payloads: {'spot_cb': [{'stream': 'btcusdt@aggTrade', 'data': {'venue': 'spot'}}], 'fut_cb': [{'stream': 'btcusdt@aggTrade', 'data': {'venue': 'spot'}}]}
Expected
Each server receives its own SUBSCRIBE, and fut_cb receives {'venue': 'futures'}.
Impact
A process that follows the same symbol on Spot and Futures (basis or arbitrage monitoring, for example) gets Spot trades delivered to the Futures handler. Nothing is logged, and the payload shapes are close enough that it is easy to miss.
Suggested fix
Make both maps instance attributes created in the client's __init__ and use them wherever the globals are referenced today (subscribe filter, on, unsubscribe and the reconnect cleanup). Streams would then be deduplicated per client, which is what the pooling logic needs.
- Lenguaje dominante
- Python
- Estrellas
- 2.9k
- Forks
- 708
- Merge medio
- 1 d 5 h
- PR fusionados (30 d)
- 4
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de binance/binance-connector-python
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
binance/binance-connector-python#514 · 2 comentarios ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 15/100
-
[Bug] Response models declare numeric fields as strict `str`, causing silent fallback of `.data()` to raw dict (simple-earn & staking)Posiblemente ocupada @Tyagiquamar la tomó hace 29 días. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 68/100
binance/binance-connector-python#553 · 2 comentarios ·
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 20/100
Todos los issues de binance/binance-connector-python
Issues similares
-
`lvm_compact` has no self-hosted twin, and `docs/158` §5 says every language-face component mustAbiertobug sev-3 vm
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
sierra-research/tau2-bench#635 ·
Los mantenedores suelen responder en 1 día
-
The add-ssm-model skill requires a Cython simulator; the contributing guide allows Python onesPosiblemente ocupada @fmuia la tomó hoy. Abiertodocumentation skill
Dificultad 2/5 1-3 horas Aptitud para principiantes 83/100
lnccbrown/ssm-simulators#406 ·
Los mantenedores suelen responder en 4 días
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 95/100
btclib-org/btclib-ecc#309 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
autowarefoundation/autoware_carla_scenario#281 ·
Los mantenedores suelen responder en 1 día