Un patrón PubSub simple involucra una variedad de suscriptores. Cualquiera puede suscribirse. Una función de publicación hará algo por cada suscriptor. ¿Puedes ver el vector de ataque...?
contract PubSub
{
address[] subscribers;
function PubSub() {
}
function Subscribe() {
subscribers.push(msg.sender);
}
function Publish(uint value) {
// if a malicious user spams Subscribe then
// this loop will never complete, rendering
// this function unusable
for(uint i=0; i<subscribers.length; i++) {
// do something with subscribers[i]...
}
}
}
Un atacante puede llamar Subscribe
desde numerosas direcciones hasta que la subscribers
matriz sea tan grande que Publish
se vuelva inutilizable, siempre con un error de falta de gas.
¿Cuál es una buena manera de evitar esto, mientras se conservan las capacidades de suscripción de publicación? Estoy pensando que algún tipo de cola de prioridad basada en tarifas podría ser una solución, pero quiero verificar aquí primero para ver si alguien más ha encontrado este problema o tiene una buena solución en mente. ¡Gracias!
Soy nuevo en la redacción de contratos así que, si digo algo estúpido, por favor, ignórenlo. Pero, según tengo entendido, si tiene un vector de ataque en el que las personas pueden extinguir sus recursos, entonces no está cobrando correctamente por sus recursos.
Cada vez que alguien se suscribe, aumenta el costo de todas las publicaciones posteriores, para siempre. ¿Derecha? Entonces, si no desea pasar ese costo al editor, el suscriptor debe pagarlo. Ahora bien, es obviamente imposible estimar el costo de la suscripción cuando podría haber llamadas subsiguientes potencialmente infinitas a publish
. Bajo ese punto de vista, parece que limitar la cantidad de publicaciones que recibirá un suscriptor es la única respuesta lógica.
De esa manera, su función de suscripción recibiría un argumento adicional uint total_messages
, para indicar cuántos mensajes futuros desea recibir el suscriptor. Cuando pasa eso, se da de baja automáticamente. Luego, solo encuentra el costo de suscripción como total_messages * message_cost
, donde message_cost
se usa el gas para ejecutar una sola iteración del ciclo. Alternativamente, los suscriptores podrían tener un saldo del cual deduces una pequeña cantidad de Ether en cada publicación para cubrir los costos, cancelando la suscripción de un usuario cuando se queda sin Ether. O simplemente podría cobrarle al editor, pero eso hará que la publicación sea cada vez más costosa.
¿Tiene sentido?
Para evitar esto, simplemente divida su matriz en múltiples matrices cuando sea demasiado grande y publíquela en cada matriz en un bloque nuevo.
Esto resuelve el problema de alcanzar el límite de gasolina, pero no resuelve el problema de aumentar los costos. Para resolver ese problema, tienes algunas opciones. Lo más fácil es simplemente dividir los costos entre todos los usuarios del sistema: si un usuario no ha pagado sus cuotas, no se le publica.
lluvia reverencia
Mate
Edmundo Edgar
Mate