Monitoreo de eventos de múltiples contratos

Estoy trabajando en un proyecto que permite a los usuarios implementar automáticamente un contrato específico que creé. Es importante que el sistema pueda escuchar eventos específicos (por ejemplo, una nueva transacción) en TODOS los contratos implementados.

Nota: estoy usando nodejs a través de web3 json rpc para monitorear eventos.

Una posible solución en la que pensé es usar un contrato contenedor que canaliza todas las solicitudes de transacción y envía los eventos en sí. Esto permitirá escuchar solo eventos de un solo contrato, pero no encuentro esa solución muy elegante.

¿Existe una manera eficiente y escalable de lograr eso sin crear un oyente en cada contrato específico?

Respuestas (2)

Parece que la preocupación es que los oyentes podrían multiplicarse de una manera que podría no escalar. No hay una bala de plata que yo sepa que permita que un solo oyente filtre eventos como los que necesitarías. Esta tercera vía es una variante de las dos opciones que entiendo que estás considerando.

Considere manejar las transacciones de la manera que desee y agregue funciones de registro lógicamente centralizadas. Por ejemplo, la fábrica por contrato. Organice las cosas para que los contratos creados en fábrica se basen en las funciones de registro centralizadas en lugar de los emisores de eventos internos.

Si usted tiene:

contract Factory { ...
contract Created {
  event LogSomething(bytes32 Id); 
  ...
  LogSomething(Id);

Reorganizar como

contract Hub {
  event LogSomething(address contract, bytes32 Id);
  ...
  function logSomething(bytes32 Id);
    LogSomething(msg.sender, Id); // msg.sender will be the "spoke" that called Hub function.

contract Created{ 
   ...
   function important(bytes32 id) {
      .. 
      Hub.logSomething(Id);

Factory probablemente debería llamarse Hub en el caso de que se dependa de él para algo más que contratos de acuñación.

Espero eso ayude.

Inicialmente pensé que también querríamos monitorear eventos generados por contratos que se implementaron fuera del sistema, pero supongo que podría ser demasiado y tal vez ni siquiera necesario. Entonces, la solución que sugiere podría funcionar para nosotros. ¡Gracias!
En realidad, ahora que lo he pensado más, podría seguir siendo un problema, porque eso significa que cualquiera puede enviar eventos desde el concentrador sin el permiso del concentrador. Una forma de resolverlo sería hacer que el concentrador mantenga una lista de contratos que están 'permitidos' para usar el mecanismo de registro del concentrador, pero no estoy seguro de si eso es algo que se acepta como una solución limpia. ¿Lo es?
Tienes razón en lo de asegurar. Pensándolo bien, me di cuenta de que es difícil decir si su aplicación debe usar un contrato único, un concentrador y radio u otra cosa. Tiendo a estar de acuerdo en que cuando se vuelve demasiado intrincado, es una señal de que las cosas no están bien encaminadas.
Hay otra manera de considerar. Puede usar una estructura de contrato actualizable que envía datos a través de un contrato de controlador de datos separado de la lógica de la aplicación. Posibilidad de punto central de inicio de sesión allí.
Como regla general, registre todos los cambios de estado dentro de los contratos y también proporcione captadores y estructuras de datos iterables. No sería especialmente difícil crear un sistema de permisos para que solo los hijos puedan acceder a una función centralizada.
Sí, estaba pensando en un contrato central de datos/registro, pero el problema de la seguridad parece aún más difícil de implementar de esa manera: si el contrato de registro no es también la fábrica del contrato, ni siquiera puede decir qué contratos tienen permitido usar sus instalaciones.
Puedes tener un registro de usuarios autorizados. Es una extensión natural de una fábrica que realiza un seguimiento de los contratos creados. Este centro está bastante cerca: ethereum.stackexchange.com/questions/10878/… . Si quisiéramos una función Hub a la que solo pudieran acceder los contratos descendientes (Personas en el ejemplo), podríamos tener un modificador: modifier onlyPerson() { if(persontIndex[personMap[msg.sender]] != msg.sender) throw ; _; // esto será cierto si Hub creó el msg.sender. } Espero que sea útil.
Sí, eso es lo que quise decir en el segundo comentario, por lo que parece una solución legítima entonces. ¡Muchas gracias!

web3.eth.filter() (el método de bajo nivel, no del tipo que puede obtener de los objetos de contrato) permite especificar una lista de direcciones para escuchar con un filtro. Tendrá que interpretar manualmente los temas, pero eso no debería ser demasiado difícil.

Observar cuándo se crea un contrato (para saber qué direcciones escuchar) es un poco más difícil. Puede usar el mismo método sin especificar una lista de direcciones y luego usar el topicsargumento para asegurarse de que solo obtiene eventos de contratos que afirman ser suyos. La distinción es importante: cualquiera puede hacer que un evento diga cualquier cosa, por lo que sería prudente verificar que proviene de un contrato que tiene su código.

En mi caso específico, creo que sería razonable interceptar solo los eventos generados por los contratos que se crearon a través del sistema, por lo que debería ser más fácil. Sin embargo, todavía no es bueno tener que escuchar múltiples direcciones, ya que eso puede crecer eventualmente y luego tenemos el problema de escalabilidad nuevamente.